/** * ResidueSolvableWordPolynomial left and right multiplication. Product with exponent vector. * * @param e exponent. * @param f exponent. * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable multiplication. */ @Override public ResidueSolvableWordPolynomial<C> multiply(ExpVector e, ExpVector f) { if (e == null || e.isZERO()) { return this; } if (f == null || f.isZERO()) { return this; } WordResidue<C> b = ring.getONECoefficient(); return multiply(b, e, b, f); }
/** Test addition. */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a", a, d); c = fac.random(ll); ExpVector u = ExpVector.EVRAND(rl, el, q); BigQuaternion x = BigQuaternion.QRAND(kl); b = new GenPolynomial<BigQuaternion>(fac, x, u); c = a.sum(b); d = a.sum(x, u); assertEquals("a+p(x,u) = a+(x,u)", c, d); c = a.subtract(b); d = a.subtract(x, u); assertEquals("a-p(x,u) = a-(x,u)", c, d); a = new GenPolynomial<BigQuaternion>(fac); b = new GenPolynomial<BigQuaternion>(fac, x, u); c = b.sum(a); d = a.sum(x, u); assertEquals("a+p(x,u) = a+(x,u)", c, d); c = a.subtract(b); d = a.subtract(x, u); assertEquals("a-p(x,u) = a-(x,u)", c, d); }
/** * ResidueSolvableWordPolynomial multiplication. Left product with exponent vector. * * @param e exponent. * @return x<sup>e</sup> * this, where * denotes solvable multiplication. */ @Override public ResidueSolvableWordPolynomial<C> multiplyLeft(ExpVector e) { if (e == null || e.isZERO()) { return this; } ResidueSolvableWordPolynomial<C> Cp = ring.valueOf(e); return Cp.multiply(this); }
/** * ResidueSolvableWordPolynomial multiplication. Commutative product with exponent vector. * * @param B solvable polynomial. * @param f exponent vector. * @return B*f, where * is commutative multiplication. */ protected ResidueSolvableWordPolynomial<C> shift( ResidueSolvableWordPolynomial<C> B, ExpVector f) { ResidueSolvableWordPolynomial<C> C = ring.getZERO().copy(); if (B == null || B.isZERO()) { return C; } if (f == null || f.isZERO()) { return B; } Map<ExpVector, WordResidue<C>> Cm = C.val; Map<ExpVector, WordResidue<C>> Bm = B.val; for (Map.Entry<ExpVector, WordResidue<C>> y : Bm.entrySet()) { ExpVector e = y.getKey(); WordResidue<C> a = y.getValue(); ExpVector d = e.sum(f); if (!a.isZERO()) { Cm.put(d, a); } } return C; }
/** Test iterators. */ public void testIterators() { // integers BigInteger rf = new BigInteger(); // System.out.println("rf = " + rf); // polynomials over integral numbers GenPolynomialRing<BigInteger> pf = new GenPolynomialRing<BigInteger>(rf, rl); // System.out.println("pf = " + pf); // random polynomial GenPolynomial<BigInteger> p = pf.random(kl, 2 * ll, el, q); // System.out.println("p = " + p); // test monomials for (Monomial<BigInteger> m : p) { // System.out.println("m = " + m); assertFalse("m.c == 0 ", m.coefficient().isZERO()); assertFalse("m.e < (0) ", m.exponent().signum() < 0); } // test exponents Iterator<ExpVector> et = p.exponentIterator(); while (et.hasNext()) { ExpVector e = et.next(); // System.out.println("e = " + e); assertFalse("e < (0) ", e.signum() < 0); } // test coefficents Iterator<BigInteger> ct = p.coefficientIterator(); while (ct.hasNext()) { BigInteger i = ct.next(); // System.out.println("i = " + i); assertFalse("i == 0 ", i.isZERO()); } }
/** * Random solvable polynomial. * * @param k size of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @param rnd is a source for random bits. * @return a random solvable polynomial. */ @Override public GenSolvablePolynomial<C> random(int k, int l, int d, float q, Random rnd) { GenSolvablePolynomial<C> r = getZERO(); // .clone(); // copy( ZERO ); // new GenPolynomial<C>( this, getZERO().val ); ExpVector e; C a; // add random coeffs and exponents for (int i = 0; i < l; i++) { e = ExpVector.EVRAND(nvar, d, q, rnd); a = coFac.random(k, rnd); r = (GenSolvablePolynomial<C>) r.sum(a, e); // somewhat inefficient but clean } return r; }
/** * Reverse inverse graded lexicographical compare part. Compare entries between begin and end * (-1). * * @param U * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVRIGLC(ExpVector U, ExpVector V, int begin, int end) { return U.revInvGradCompareTo(V, begin, end); }
/** * Reverse inverse graded lexicographical compare. * * @param U * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVRIGLC(ExpVector U, ExpVector V) { return U.revInvGradCompareTo(V); }
/** * Reverse inverse lexicographical compare part. Compare entries between begin and end (-1). * * @param U * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVRILCP(ExpVector U, ExpVector V, int begin, int end) { return U.revInvLexCompareTo(V, begin, end); }
/** * Reverse inverse lexicographical compare. * * @param U * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVRILCP(ExpVector U, ExpVector V) { return U.revInvLexCompareTo(V); }
/** * ExpVector divides test. Test if V is component wise greater or equal to this. * * @param V * @return true if this divides V, else false. */ public boolean divides(ExpVector V) { return V.multipleOf(this); // return EVMT(V, this); }
/** * ExpVector summation. * * @param U * @param V * @return U+V. */ public static ExpVector EVSUM(ExpVector U, ExpVector V) { return U.sum(V); }
/** * ExpVector substitution. Clone and set exponent to d at position i. * * @param U * @param i position. * @param d new exponent. * @return substituted ExpVector. */ public static ExpVector EVSU(ExpVector U, int i, long d) { return U.subst(i, d); }
/** * ExpVector least common multiple. * * @param U * @param V * @return component wise maximum of U and V. */ public static ExpVector EVLCM(ExpVector U, ExpVector V) { return U.lcm(V); }
/** * ExpVector maximal degree. * * @param U * @return maximal exponent. */ public static long EVMDEG(ExpVector U) { return U.maxDeg(); }
/** * ExpVector weighted degree. * * @param w weights. * @param U * @return weighted sum of all exponents. */ public static long EVWDEG(long[][] w, ExpVector U) { return U.weightDeg(w); }
/** * ExpVector total degree. * * @param U * @return sum of all exponents. */ public static long EVTDEG(ExpVector U) { return U.totalDeg(); }
/** * ExpVector sign. * * @param U * @return 0 if U is zero, -1 if some entry is negative, 1 if no entry is negativ and at least one * entry is positive. */ public static int EVSIGN(ExpVector U) { return U.signum(); }
/** * ExpVector substitution. Clone and set exponent to d at position i. * * @param i position. * @param d new exponent. * @return substituted ExpVector. */ public ExpVector subst(int i, long d) { ExpVector V = (ExpVector) this.clone(); long e = V.setVal(i, d); return V; // return EVSU(this, i, d); }
/** * Inverse weighted lexicographical compare. * * @param w weight array. * @param U * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVIWLC(long[][] w, ExpVector U, ExpVector V) { return U.invWeightCompareTo(w, V); }
/** * ExpVector absolute value. * * @param U * @return abs(U). */ public static ExpVector EVABS(ExpVector U) { return U.abs(); }
/** * Inverse weighted lexicographical compare part. Compare entries between begin and end (-1). * * @param w weight array. * @param U * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVIWLC(long[][] w, ExpVector U, ExpVector V, int begin, int end) { return U.invWeightCompareTo(w, V, begin, end); }
/** * ExpVector difference. Result may have negative entries. * * @param U * @param V * @return U-V. */ public static ExpVector EVDIF(ExpVector U, ExpVector V) { return U.subtract(V); }
// cannot @Override, @NoOverride public ResidueSolvableWordPolynomial<C> multiply(ResidueSolvableWordPolynomial<C> Bp) { if (Bp == null || Bp.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } assert (ring.nvar == Bp.ring.nvar); if (debug) { logger.debug("ring = " + ring); } ExpVector Z = ring.evzero; ResidueSolvableWordPolynomial<C> Dp = ring.getZERO().copy(); ResidueSolvableWordPolynomial<C> zero = ring.getZERO().copy(); WordResidue<C> one = ring.getONECoefficient(); Map<ExpVector, WordResidue<C>> A = val; Map<ExpVector, WordResidue<C>> B = Bp.val; Set<Map.Entry<ExpVector, WordResidue<C>>> Bk = B.entrySet(); for (Map.Entry<ExpVector, WordResidue<C>> y : A.entrySet()) { WordResidue<C> a = y.getValue(); ExpVector e = y.getKey(); if (debug) logger.info("e = " + e + ", a = " + a); for (Map.Entry<ExpVector, WordResidue<C>> x : Bk) { WordResidue<C> b = x.getValue(); ExpVector f = x.getKey(); if (debug) logger.info("f = " + f + ", b = " + b); int[] fp = f.dependencyOnVariables(); int fl1 = 0; if (fp.length > 0) { fl1 = fp[fp.length - 1]; } int fl1s = ring.nvar + 1 - fl1; // polynomial/residue coefficient multiplication ResidueSolvableWordPolynomial<C> Cps = ring.getZERO().copy(); if (ring.polCoeff.coeffTable.isEmpty() || b.isConstant() || e.isZERO()) { // symmetric Cps = new ResidueSolvableWordPolynomial<C>(ring, b, e); if (debug) logger.info("symmetric coeff: b = " + b + ", e = " + e); } else { // unsymmetric if (debug) logger.info("unsymmetric coeff: b = " + b + ", e = " + e); // recursive polynomial coefficient multiplication : e * b.val RecSolvableWordPolynomial<C> rsp1 = new RecSolvableWordPolynomial<C>(ring.polCoeff, e); RecSolvableWordPolynomial<C> rsp2 = new RecSolvableWordPolynomial<C>(ring.polCoeff, b.val); RecSolvableWordPolynomial<C> rsp3 = rsp1.multiply(rsp2); Cps = ring.fromPolyCoefficients(rsp3); } if (debug) { logger.info("coeff-poly: Cps = " + Cps); } // polynomial multiplication ResidueSolvableWordPolynomial<C> Dps = ring.getZERO().copy(); ResidueSolvableWordPolynomial<C> Ds = null; ResidueSolvableWordPolynomial<C> D1, D2; if (ring.table.isEmpty() || Cps.isConstant() || f.isZERO()) { // symmetric if (debug) logger.info("symmetric poly: b = " + b + ", e = " + e); ExpVector g = e.sum(f); if (Cps.isConstant()) { Ds = new ResidueSolvableWordPolynomial<C>( ring, Cps.leadingBaseCoefficient(), g); // symmetric! } else { Ds = shift(Cps, f); // symmetric } } else { // eventually unsymmetric if (debug) logger.info("unsymmetric poly: Cps = " + Cps + ", f = " + f); for (Map.Entry<ExpVector, WordResidue<C>> z : Cps.val.entrySet()) { // split g = g1 * g2, f = f1 * f2 WordResidue<C> c = z.getValue(); ExpVector g = z.getKey(); if (debug) logger.info("g = " + g + ", c = " + c); int[] gp = g.dependencyOnVariables(); int gl1 = ring.nvar + 1; if (gp.length > 0) { gl1 = gp[0]; } int gl1s = ring.nvar + 1 - gl1; if (gl1s <= fl1s) { // symmetric ExpVector h = g.sum(f); if (debug) logger.info("disjoint poly: g = " + g + ", f = " + f + ", h = " + h); Ds = (ResidueSolvableWordPolynomial<C>) zero.sum(one, h); // symmetric! } else { ExpVector g1 = g.subst(gl1, 0); ExpVector g2 = Z.subst(gl1, g.getVal(gl1)); // bug el1, gl1 ExpVector g4; ExpVector f1 = f.subst(fl1, 0); ExpVector f2 = Z.subst(fl1, f.getVal(fl1)); if (debug) logger.info("poly, g1 = " + g1 + ", f1 = " + f1 + ", Dps = " + Dps); if (debug) logger.info("poly, g2 = " + g2 + ", f2 = " + f2); TableRelation<WordResidue<C>> rel = ring.table.lookup(g2, f2); if (debug) logger.info("poly, g = " + g + ", f = " + f + ", rel = " + rel); Ds = new ResidueSolvableWordPolynomial<C>(ring, rel.p); // ring.copy(rel.p); if (rel.f != null) { D2 = new ResidueSolvableWordPolynomial<C>(ring, one, rel.f); Ds = Ds.multiply(D2); if (rel.e == null) { g4 = g2; } else { g4 = g2.subtract(rel.e); } ring.table.update(g4, f2, Ds); } if (rel.e != null) { D1 = new ResidueSolvableWordPolynomial<C>(ring, one, rel.e); Ds = D1.multiply(Ds); ring.table.update(g2, f2, Ds); } if (!f1.isZERO()) { D2 = new ResidueSolvableWordPolynomial<C>(ring, one, f1); Ds = Ds.multiply(D2); // ring.table.update(?,f1,Ds) } if (!g1.isZERO()) { D1 = new ResidueSolvableWordPolynomial<C>(ring, one, g1); Ds = D1.multiply(Ds); // ring.table.update(e1,?,Ds) } } Ds = Ds.multiplyLeft(c); // assume c commutes with Cs Dps = (ResidueSolvableWordPolynomial<C>) Dps.sum(Ds); } // end Dps loop Ds = Dps; } Ds = Ds.multiplyLeft(a); // multiply(a,b); // non-symmetric if (debug) logger.debug("Ds = " + Ds); Dp = (ResidueSolvableWordPolynomial<C>) Dp.sum(Ds); } // end B loop } // end A loop return Dp; }
/** * ExpVector multiple test. Test if U is component wise greater or equal to V. * * @param U * @param V * @return true if U is a multiple of V, else false. */ public static boolean EVMT(ExpVector U, ExpVector V) { return U.multipleOf(V); }
/** * ExpVector greatest common divisor. * * @param U * @param V * @return component wise minimum of U and V. */ public static ExpVector EVGCD(ExpVector U, ExpVector V) { return U.gcd(V); }
/** * ExpVector negate. * * @param U * @return -U. */ public static ExpVector EVNEG(ExpVector U) { return U.negate(); }
/** * ExpVector dependency on variables. * * @param U * @return array of indices where U has positive exponents. */ public static int[] EVDOV(ExpVector U) { return U.dependencyOnVariables(); }
/** * Minimal ordered groebner basis. * * @param Fp a Groebner base. * @return a reduced Groebner base of Fp. */ @SuppressWarnings("cast") @Override public List<GenPolynomial<C>> minimalGB(List<GenPolynomial<C>> Fp) { GenPolynomial<C> a; ArrayList<GenPolynomial<C>> G; G = new ArrayList<GenPolynomial<C>>(Fp.size()); ListIterator<GenPolynomial<C>> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial<C> p; ArrayList<GenPolynomial<C>> F; F = new ArrayList<GenPolynomial<C>>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiMPIReducerServer<C>[] mirs = (MiMPIReducerServer<C>[]) new MiMPIReducerServer[G.size()]; int i = 0; F = new ArrayList<GenPolynomial<C>>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List<GenPolynomial<C>> R = new ArrayList<GenPolynomial<C>>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new MiMPIReducerServer<C>(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList<GenPolynomial<C>>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; }