/*
* $Id$
*/
package edu.jas.ps;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import edu.jas.kern.PrettyPrint;
import edu.jas.poly.ExpVector;
import edu.jas.poly.GenPolynomial;
import edu.jas.poly.GenPolynomialRing;
import edu.jas.poly.Monomial;
import edu.jas.structure.RingElem;
import edu.jas.structure.RingFactory;
import edu.jas.structure.UnaryFunctor;
import edu.jas.util.ListUtil;
/**
* Multivariate power series ring implementation. Uses lazy evaluated generating
* function for coefficients.
* @param ring element type
* @author Heinz Kredel
*/
public class MultiVarPowerSeriesRing> implements RingFactory> {
/**
* A default random sequence generator.
*/
protected final static Random random = new Random();
/**
* Default truncate.
*/
public final static int DEFAULT_TRUNCATE = 7;
/**
* Truncate.
*/
int truncate;
/**
* Zero ExpVector.
*/
public final ExpVector EVZERO;
/**
* Coefficient ring factory.
*/
public final RingFactory coFac;
/**
* The number of variables.
*/
public final int nvar;
/**
* The names of the variables. This value can be modified.
*/
protected String[] vars;
/**
* The constant power series 1 for this ring.
*/
public final MultiVarPowerSeries ONE;
/**
* The constant power series 0 for this ring.
*/
public final MultiVarPowerSeries ZERO;
/**
* No argument constructor.
*/
@SuppressWarnings("unused")
private MultiVarPowerSeriesRing() {
throw new IllegalArgumentException("do not use no-argument constructor");
}
/**
* Constructor.
* @param fac polynomial ring factory.
*/
public MultiVarPowerSeriesRing(GenPolynomialRing fac) {
this(fac.coFac, fac.nvar, fac.getVars());
}
/**
* Constructor.
* @param coFac coefficient ring factory.
*/
public MultiVarPowerSeriesRing(RingFactory coFac, int nv) {
this(coFac, nv, DEFAULT_TRUNCATE);
}
/**
* Constructor.
* @param coFac coefficient ring factory.
* @param truncate index of truncation.
*/
public MultiVarPowerSeriesRing(RingFactory coFac, int nv, int truncate) {
this(coFac, nv, truncate, null);
}
/**
* Constructor.
* @param coFac coefficient ring factory.
* @param names of the variables.
*/
public MultiVarPowerSeriesRing(RingFactory coFac, String[] names) {
this(coFac, names.length, DEFAULT_TRUNCATE, names);
}
/**
* Constructor.
* @param cofac coefficient ring factory.
* @param nv number of variables.
* @param names of the variables.
*/
public MultiVarPowerSeriesRing(RingFactory cofac, int nv, String[] names) {
this(cofac, nv, DEFAULT_TRUNCATE, names);
}
/**
* Constructor.
* @param cofac coefficient ring factory.
* @param truncate index of truncation.
* @param names of the variables.
*/
public MultiVarPowerSeriesRing(RingFactory cofac, int nv, int truncate, String[] names) {
this.coFac = cofac;
this.nvar = nv;
this.truncate = truncate;
if (names == null) {
vars = null;
} else {
vars = Arrays.copyOf(names,names.length); // > Java-5
}
if (vars == null) {
if (PrettyPrint.isTrue()) {
vars = GenPolynomialRing.newVars("x", nvar);
}
} else {
if (vars.length != nvar) {
throw new IllegalArgumentException("incompatible variable size " + vars.length + ", " + nvar);
}
GenPolynomialRing.addVars(vars);
}
EVZERO = ExpVector.create(nvar);
ONE = new MultiVarPowerSeries(this, new MultiVarCoefficients(this) {
@Override
public C generate(ExpVector i) {
if (i.isZERO()) {
return coFac.getONE();
}
return coFac.getZERO();
}
});
ZERO = new MultiVarPowerSeries(this, new MultiVarCoefficients(this) {
@Override
public C generate(ExpVector i) {
return coFac.getZERO();
}
});
}
/**
* Fixed point construction.
* @param map a mapping of power series.
* @return fix point wrt map.
*/
// Cannot be a static method because a power series ring is required.
public MultiVarPowerSeries fixPoint(MultiVarPowerSeriesMap map) {
MultiVarPowerSeries ps1 = new MultiVarPowerSeries(this);
MultiVarPowerSeries ps2 = map.map(ps1);
ps1.lazyCoeffs = ps2.lazyCoeffs;
return ps2;
}
/**
* To String.
* @return string representation of this.
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
String scf = coFac.getClass().getSimpleName();
sb.append(scf + "((" + varsToString() + "))");
return sb.toString();
}
/**
* Get a String representation of the variable names.
* @return names separated by commas.
*/
public String varsToString() {
if (vars == null) {
return "#" + nvar;
}
return ExpVector.varsToString(vars);
//return Arrays.toString(vars);
}
/**
* Get the variable names.
* @return names.
*/
public String[] getVars() {
return Arrays.copyOf(vars,vars.length); // > Java-5
}
/**
* Get a scripting compatible string representation.
* @return script compatible representation for this ElemFactory.
* @see edu.jas.structure.ElemFactory#toScript()
*/
@Override
public String toScript() {
// Python case
StringBuffer s = new StringBuffer("MPS(");
String f = null;
try {
f = ((RingElem) coFac).toScriptFactory(); // sic
} catch (Exception e) {
f = coFac.toScript();
}
s.append(f + ",\"" + varsToString() + "\"," + truncate + ")");
return s.toString();
}
/**
* Comparison with any other object.
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
@SuppressWarnings("unchecked")
public boolean equals(Object B) {
MultiVarPowerSeriesRing a = null;
try {
a = (MultiVarPowerSeriesRing) B;
} catch (ClassCastException ignored) {
}
if (a == null) {
return false;
}
if (!coFac.equals(a.coFac)) {
return false;
}
if (Arrays.equals(vars, a.vars)) {
return true;
}
return false;
}
/**
* Hash code for this .
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int h = coFac.hashCode();
h = h << 7;
h += (Arrays.hashCode(vars) << 17);
h += truncate;
return h;
}
/**
* Get the zero element.
* @return 0 as MultiVarPowerSeries.
*/
public MultiVarPowerSeries getZERO() {
return ZERO;
}
/**
* Get the one element.
* @return 1 as MultiVarPowerSeries.
*/
public MultiVarPowerSeries getONE() {
return ONE;
}
/**
* Get a list of the generating elements.
* @return list of generators for the algebraic structure.
* @see edu.jas.structure.ElemFactory#generators()
*/
public List> generators() {
List rgens = coFac.generators();
List> gens = new ArrayList>(rgens.size());
for (final C cg : rgens) {
MultiVarPowerSeries g = new MultiVarPowerSeries(this, new MultiVarCoefficients(this) {
@Override
public C generate(ExpVector i) {
if (i.isZERO()) {
return cg;
}
return coFac.getZERO();
}
});
gens.add(g);
}
for (int i = 0; i < nvar; i++) {
gens.add(ONE.shift(1, nvar - 1 - i));
}
return gens;
}
/**
* Is this structure finite or infinite.
* @return true if this structure is finite, else false.
* @see edu.jas.structure.ElemFactory#isFinite()
*/
public boolean isFinite() {
return false;
}
/**
* Truncate.
* @return truncate index of power series.
*/
public int truncate() {
return truncate;
}
/**
* Set truncate.
* @param t new truncate index.
* @return old truncate index of power series.
*/
public int setTruncate(int t) {
if (t < 0) {
throw new IllegalArgumentException("negative truncate not allowed");
}
int ot = truncate;
truncate = t;
ONE.setTruncate(t);
ZERO.setTruncate(t);
return ot;
}
/**
* Get the power series of the exponential function.
* @param r variable for the direction.
* @return exp(x_r) as MultiVarPowerSeries.
*/
public MultiVarPowerSeries getEXP(final int r) {
return fixPoint(new MultiVarPowerSeriesMap() {
public MultiVarPowerSeries map(MultiVarPowerSeries e) {
return e.integrate(coFac.getONE(), r);
}
});
}
/**
* Get the power series of the sinus function.
* @param r variable for the direction.
* @return sin(x_r) as MultiVarPowerSeries.
*/
public MultiVarPowerSeries getSIN(final int r) {
return fixPoint(new MultiVarPowerSeriesMap() {
public MultiVarPowerSeries map(MultiVarPowerSeries s) {
return s.negate().integrate(coFac.getONE(), r).integrate(coFac.getZERO(), r);
}
});
}
/**
* Get the power series of the cosinus function.
* @param r variable for the direction.
* @return cos(x_r) as MultiVarPowerSeries.
*/
public MultiVarPowerSeries getCOS(final int r) {
return fixPoint(new MultiVarPowerSeriesMap() {
public MultiVarPowerSeries map(MultiVarPowerSeries c) {
return c.negate().integrate(coFac.getZERO(), r).integrate(coFac.getONE(), r);
}
});
}
/**
* Get the power series of the tangens function.
* @param r variable for the direction.
* @return tan(x_r) as MultiVarPowerSeries.
*/
public MultiVarPowerSeries getTAN(final int r) {
return fixPoint(new MultiVarPowerSeriesMap() {
public MultiVarPowerSeries map(MultiVarPowerSeries t) {
return t.multiply(t).sum(getONE()).integrate(coFac.getZERO(), r);
}
});
}
/**
* Solve an partial differential equation. y_r' = f(y_r) with y_r(0) = c.
* @param f a MultiVarPowerSeries.
* @param c integration constant.
* @param r variable for the direction.
* @return f.integrate(c).
*/
public MultiVarPowerSeries solvePDE(MultiVarPowerSeries f, C c, int r) {
return f.integrate(c, r);
}
/**
* Query if this ring is commuative.
* @return true, if this ring is commutative, else false.
*/
public boolean isCommutative() {
return coFac.isCommutative();
}
/**
* Query if this ring is associative.
* @return true if this ring is associative, else false.
*/
public boolean isAssociative() {
return coFac.isAssociative();
}
/**
* Query if this ring is a field.
* @return false.
*/
public boolean isField() {
return false;
}
/**
* Characteristic of this ring.
* @return characteristic of this ring.
*/
public java.math.BigInteger characteristic() {
return coFac.characteristic();
}
/**
* Get a (constant) MultiVarPowerSeries<C> from a long value.
* @param a long.
* @return a MultiVarPowerSeries<C>.
*/
public MultiVarPowerSeries fromInteger(final long a) {
return new MultiVarPowerSeries(this, new MultiVarCoefficients(this) {
@Override
public C generate(ExpVector i) {
if (i.isZERO()) {
return coFac.fromInteger(a);
}
return coFac.getZERO();
}
});
}
/**
* Get a (constant) MultiVarPowerSeries<C> from a
* java.math.BigInteger.
* @param a BigInteger.
* @return a MultiVarPowerSeries<C>.
*/
public MultiVarPowerSeries fromInteger(final java.math.BigInteger a) {
return new MultiVarPowerSeries(this, new MultiVarCoefficients(this) {
@Override
public C generate(ExpVector i) {
if (i.isZERO()) {
return coFac.fromInteger(a);
}
return coFac.getZERO();
}
});
}
/**
* Get the corresponding GenPolynomialRing<C>.
* @return GenPolynomialRing<C>.
*/
public GenPolynomialRing polyRing() {
return new GenPolynomialRing(coFac, nvar, vars);
}
/**
* Get a MultiVarPowerSeries<C> from a GenPolynomial<C>.
* @param a GenPolynomial<C>.
* @return a MultiVarPowerSeries<C>.
*/
public MultiVarPowerSeries fromPolynomial(GenPolynomial a) {
if (a == null || a.isZERO()) {
return ZERO;
}
if (a.isONE()) {
return ONE;
}
GenPolynomialRing pfac = polyRing();
HashMap> cache = new HashMap>();
int mt = 0;
for (Monomial m : a) {
ExpVector e = m.exponent();
long t = e.totalDeg();
mt = Math.max(mt, (int) t);
GenPolynomial p = cache.get(t);
if (p == null) {
p = pfac.getZERO().copy();
cache.put(t, p);
}
p.doPutToMap(e, m.coefficient());
}
mt++;
if (mt > truncate()) {
setTruncate(mt);
}
BitSet check = new BitSet();
for (int i = 0; i <= truncate(); i++) {
check.set(i);
if (cache.get((long) i) == null) {
GenPolynomial p = pfac.getZERO().copy();
cache.put((long) i, p);
//System.out.println("p zero for deg i = " + i);
}
}
return new MultiVarPowerSeries(this, new MultiVarCoefficients(pfac, cache, check) {
@Override
public C generate(ExpVector e) {
// cached coefficients returned by get
return coFac.getZERO();
}
});
}
/**
* Get a list of MultiVarPowerSeries<C> from a list of
* GenPolynomial<C>.
* @param A list of GenPolynomial<C>.
* @return a list of MultiVarPowerSeries<C>.
*/
public List> fromPolynomial(List> A) {
return ListUtil., MultiVarPowerSeries> map(A,
new UnaryFunctor, MultiVarPowerSeries>() {
public MultiVarPowerSeries eval(GenPolynomial c) {
return fromPolynomial(c);
}
});
}
/**
* Get a MultiVarPowerSeries<C> from a univariate power series.
* @param ps UnivPowerSeries<C>.
* @param r variable for the direction.
* @return a MultiVarPowerSeries<C>.
*/
public MultiVarPowerSeries fromPowerSeries(final UnivPowerSeries ps, final int r) {
if (ps == null) {
return ZERO;
}
return new MultiVarPowerSeries(this, new MultiVarCoefficients(this) {
@Override
public C generate(ExpVector i) {
if (i.isZERO()) {
return ps.coefficient(0);
}
int[] dep = i.dependencyOnVariables();
if (dep.length != 1) {
return coFac.getZERO();
}
if (dep[0] != r) {
return coFac.getZERO();
}
int j = (int) i.getVal(r);
if (j > 0) {
return ps.coefficient(j);
}
return coFac.getZERO();
}
});
}
/**
* Generate a random power series with k = 5, d = 0.7.
* @return a random power series.
*/
public MultiVarPowerSeries random() {
return random(5, 0.7f, random);
}
/**
* Generate a random power series with d = 0.7.
* @param k bit-size of random coefficients.
* @return a random power series.
*/
public MultiVarPowerSeries random(int k) {
return random(k, 0.7f, random);
}
/**
* Generate a random power series with d = 0.7.
* @param k bit-size of random coefficients.
* @param rnd is a source for random bits.
* @return a random power series.
*/
public MultiVarPowerSeries random(int k, Random rnd) {
return random(k, 0.7f, rnd);
}
/**
* Generate a random power series.
* @param k bit-size of random coefficients.
* @param d density of non-zero coefficients.
* @return a random power series.
*/
public MultiVarPowerSeries random(int k, float d) {
return random(k, d, random);
}
/**
* Generate a random power series.
* @param k bit-size of random coefficients.
* @param d density of non-zero coefficients.
* @param rnd is a source for random bits.
* @return a random power series.
*/
public MultiVarPowerSeries random(final int k, final float d, final Random rnd) {
return new MultiVarPowerSeries(this, new MultiVarCoefficients(this) {
@Override
public C generate(ExpVector i) {
// cached coefficients returned by get
C c;
float f = rnd.nextFloat();
if (f < d) {
c = coFac.random(k, rnd);
} else {
c = coFac.getZERO();
}
return c;
}
});
}
/**
* Copy power series.
* @param c a power series.
* @return a copy of c.
*/
public MultiVarPowerSeries copy(MultiVarPowerSeries c) {
return new MultiVarPowerSeries(this, c.lazyCoeffs);
}
/**
* Parse a power series. Note: not implemented.
* @param s String.
* @return power series from s.
*/
public MultiVarPowerSeries parse(String s) {
throw new UnsupportedOperationException("parse for power series not implemented");
}
/**
* Parse a power series. Note: not implemented.
* @param r Reader.
* @return next power series from r.
*/
public MultiVarPowerSeries parse(Reader r) {
throw new UnsupportedOperationException("parse for power series not implemented");
}
/**
* Taylor power series.
* @param f function.
* @param a expansion point.
* @return Taylor series of f.
*/
public MultiVarPowerSeries seriesOfTaylor(final TaylorFunction f, final List a) {
return new MultiVarPowerSeries(this, new MultiVarCoefficients(this) {
TaylorFunction der = f;
// Map> pderCache = ...
final List v = a;
@Override
public C generate(ExpVector i) {
C c;
int s = i.signum();
if (s == 0) {
c = der.evaluate(v);
return c;
}
TaylorFunction pder = der.deriviative(i);
if (pder.isZERO()) {
return coFac.getZERO();
}
c = pder.evaluate(v);
if (c.isZERO()) {
return c;
}
long f = pder.getFacul();
c = c.divide(coFac.fromInteger(f));
return c;
}
});
}
}
Ads help maintain this website.