Skip to content

Commit

Permalink
2.5.1 bugfix:
Browse files Browse the repository at this point in the history
 - minor bugfix in LeinartDecomposition
 - minor bugfix in bivariate MultivariateFactorization
 - better Scala API for GroebnerMethods
 - other small fixes & improvements
  • Loading branch information
PoslavskySV committed Jul 29, 2018
1 parent f66c831 commit 68a5aee
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 39 deletions.
14 changes: 11 additions & 3 deletions rings.repl/rings.repl
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#!/bin/bash

ringsVersion=2.5
ringsString="Rings ${ringsVersion}: efficient Java/Scala library for polynomial rings."

# CHECK JAVA VERSION
java="java"
sedString1="s/\s*\([^.]*\)\..*/\1/"
Expand Down Expand Up @@ -54,6 +51,7 @@ case $os in
;;
esac

ringsVersion=2.5.1
ammArgs=()
javaArgs=()

Expand All @@ -74,6 +72,11 @@ do
esac

;;
-V|--use-version)
ringsVersion="$1"
shift
;;

-v|--version)
echo "$ringsString"
exit 0
Expand Down Expand Up @@ -136,6 +139,9 @@ if [ ${#ammArgs[@]} -eq 0 ]; then
})'
fi

ringsString="Rings ${ringsVersion}: efficient Java/Scala library for polynomial rings."


JAVA_OPTS="-XX:+AggressiveOpts ${javaArgs[@]}" amm \
-b "Running Ammonite Repl
$ringsString" \
Expand All @@ -151,9 +157,11 @@ $ringsString" \
import poly.{univar, multivar}
import poly.PolynomialMethods._
import multivar.MonomialOrder._
import multivar.GroebnerMethods
import rings.scaladsl._
import util._
import syntax._
import scala.collection.JavaConversions._
implicit val $$tPrintBigInteger : pprint.TPrint[IntZ] = pprint.TPrint.literal[IntZ]("IntZ")
implicit val $$tPrintRational : pprint.TPrint[rings.Rational[_]] = pprint.TPrint.literal[rings.Rational[_]]("Rational")
implicit val $$tPrintMonomialOrder : pprint.TPrint[Ordering] = pprint.TPrint.literal[Ordering]("MonomialOrder")
Expand Down
4 changes: 2 additions & 2 deletions rings.scaladsl/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ organization := "cc.redberry"

name := "rings.scaladsl"

version := "2.5"
version := "2.5.1"

scalaVersion := "2.12.3"

Expand All @@ -15,7 +15,7 @@ moduleName := name.value
resolvers += Resolver.mavenLocal

libraryDependencies ++= Seq(
"cc.redberry" % "rings" % "2.5",
"cc.redberry" % "rings" % "2.5.1",
"junit" % "junit" % "4.12" % Test,
"com.novocode" % "junit-interface" % "0.11" % Test exclude("junit", "junit-dep")
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ sealed class Ring[E](val theRing: rings.Ring[E])
final def apply(a: String, b: String, c: String, d: String, e: String): (E, E, E, E, E)
= (apply(a), apply(b), apply(c), apply(d), apply(e))

final def apply(a: String, b: String, c: String, d: String, e: String, f: String): (E, E, E, E, E, E)
= (apply(a), apply(b), apply(c), apply(d), apply(e), apply(f))

final def apply(a: String, b: String, c: String, d: String, e: String, f: String, g: String): (E, E, E, E, E, E, E)
= (apply(a), apply(b), apply(c), apply(d), apply(e), apply(f), apply(g))

final def apply(a: Int, b: Int): (E, E) = (apply(a), apply(b))

final def apply(a: Int, b: Int, c: Int): (E, E, E)
Expand All @@ -99,6 +105,12 @@ sealed class Ring[E](val theRing: rings.Ring[E])
final def apply(a: Int, b: Int, c: Int, d: Int, e: Int): (E, E, E, E, E)
= (apply(a), apply(b), apply(c), apply(d), apply(e))

final def apply(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int): (E, E, E, E, E, E)
= (apply(a), apply(b), apply(c), apply(d), apply(e), apply(f))

final def apply(a: Int, b: Int, c: Int, d: Int, e: Int, f: Int, g: Int): (E, E, E, E, E, E, E)
= (apply(a), apply(b), apply(c), apply(d), apply(e), apply(f), apply(g))

/** element class */
private lazy val eClass: Class[_ <: E] = theRing.getZero.getClass

Expand Down
2 changes: 1 addition & 1 deletion rings/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>cc.redberry</groupId>
<artifactId>rings</artifactId>
<version>2.5</version>
<version>2.5.1</version>
<packaging>jar</packaging>
<name>rings</name>
<url>https://github.com/PoslavskySV/rings/</url>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ List<Poly> GroebnerBasis(List<Poly> generators,
return GroebnerBasisInGF(generators, monomialOrder, null);
if (factory.isOverZ())
return (List<Poly>) GroebnerBasisInZ((List) generators, monomialOrder, null, true);
if (Util.isOverRationals(factory))
if (Util.isOverRationals(factory) && ((MultivariatePolynomial) factory).ring.equals(Rings.Q))
return (List<Poly>) GroebnerBasisInQ((List) generators, monomialOrder, null, true);
else
return BuchbergerGB(generators, monomialOrder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
import cc.redberry.rings.*;
import cc.redberry.rings.bigint.BigInteger;
import cc.redberry.rings.linear.LinearSolver;
import cc.redberry.rings.poly.IPolynomial;
import cc.redberry.rings.poly.MultivariateRing;
import cc.redberry.rings.poly.PolynomialMethods;
import cc.redberry.rings.util.ArraysUtil;
import gnu.trove.list.array.TIntArrayList;
import org.apache.commons.math3.random.RandomGenerator;

import java.util.*;
Expand All @@ -34,8 +34,14 @@ private GroebnerMethods() {}
/**
* Eliminates specified variables from the given ideal.
*/
public static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
@SuppressWarnings("unchecked")
public static <Poly extends AMultivariatePolynomial>
List<Poly> eliminate(List<Poly> ideal, int variable) {
return eliminate0(ideal, variable);
}

private static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
List<Poly> eliminate0(List<Poly> ideal, int variable) {
if (ideal.isEmpty())
return Collections.emptyList();

Expand Down Expand Up @@ -69,7 +75,7 @@ List<Poly> eliminate(List<Poly> ideal, int variable) {
/**
* Eliminates specified variables from the given ideal.
*/
public static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
public static <Poly extends AMultivariatePolynomial>
List<Poly> eliminate(List<Poly> ideal, int... variables) {
for (int variable : variables)
ideal = eliminate(ideal, variable);
Expand All @@ -83,7 +89,8 @@ List<Poly> eliminate(List<Poly> ideal, int... variables) {
* that the given set is certainly independent). The method applies two criteria: it tests for lead set (LEX)
* independence and does a probabilistic Jacobian test.
*/
public static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
@SuppressWarnings("unchecked")
public static <Poly extends AMultivariatePolynomial>
boolean probablyAlgebraicallyDependentQ(List<Poly> sys) {
if (sys.isEmpty())
return false;
Expand Down Expand Up @@ -113,7 +120,7 @@ boolean probablyAlgebraicallyDependentQ(List<Poly> sys) {
/**
* Returns true if a given set of polynomials is algebraically dependent or false otherwise.
*/
public static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
public static <Poly extends AMultivariatePolynomial>
boolean algebraicallyDependentQ(List<Poly> sys) {
return !algebraicRelations(sys).isEmpty();
}
Expand Down Expand Up @@ -154,7 +161,7 @@ static boolean algebraicallyDependentMonomialsQ(List<DegreeVector> sys) {

/** Probabilistic test for the maximality of the rank of Jacobian matrix */
@SuppressWarnings("unchecked")
static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
static <Poly extends AMultivariatePolynomial>
boolean probablyMaximalJacobianRankQ(Poly[][] jacobian) {
if (jacobian[0][0] instanceof MultivariatePolynomialZp64)
return probablyMaximalJacobianRankQ((MultivariatePolynomialZp64[][]) jacobian);
Expand Down Expand Up @@ -212,8 +219,14 @@ static <E> boolean probablyMaximalJacobianRankQ(MultivariatePolynomial<E>[][] ja
/**
* Gives a list of algebraic relations (annihilating polynomials) for the given list of polynomials
*/
public static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
@SuppressWarnings("unchecked")
public static <Poly extends AMultivariatePolynomial>
List<Poly> algebraicRelations(List<Poly> polys) {
return algebraicRelations0(polys);
}

private static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
List<Poly> algebraicRelations0(List<Poly> polys) {
if (!probablyAlgebraicallyDependentQ(polys))
return Collections.emptyList();

Expand Down Expand Up @@ -261,9 +274,10 @@ Poly[][] JacobianMatrix(List<Poly> sys) {
* moderate degree bounds exist (either since {@code polynomials} have a common root or because the degree
* bound on the solutions is so big that the system is intractable for computer)
*/
public static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
@SuppressWarnings("unchecked")
public static <Poly extends AMultivariatePolynomial>
List<Poly> NullstellensatzCertificate(List<Poly> polynomials) {
return NullstellensatzSolver(polynomials, polynomials.get(0).createOne(), true);
return NullstellensatzCertificate(polynomials, true);
}

/**
Expand All @@ -276,9 +290,10 @@ List<Poly> NullstellensatzCertificate(List<Poly> polynomials) {
* moderate degree bounds exist (either since {@code polynomials} have a common root or because the degree
* bound on the solutions is so big that the system is intractable for computer)
*/
public static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
@SuppressWarnings("unchecked")
public static <Poly extends AMultivariatePolynomial>
List<Poly> NullstellensatzCertificate(List<Poly> polynomials, boolean boundTotalDeg) {
return NullstellensatzSolver(polynomials, polynomials.get(0).createOne(), boundTotalDeg);
return NullstellensatzSolver(polynomials, (Poly) polynomials.get(0).createOne(), boundTotalDeg);
}

/**
Expand All @@ -294,8 +309,14 @@ List<Poly> NullstellensatzCertificate(List<Poly> polynomials, boolean boundTotal
* moderate degree bounds exists
*/
@SuppressWarnings("unchecked")
public static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
public static <Poly extends AMultivariatePolynomial>
List<Poly> NullstellensatzSolver(List<Poly> polynomials, Poly rhs, boolean boundTotalDeg) {
return NullstellensatzSolver0(polynomials, rhs, boundTotalDeg);
}

@SuppressWarnings("unchecked")
private static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
List<Poly> NullstellensatzSolver0(List<Poly> polynomials, Poly rhs, boolean boundTotalDeg) {
if (rhs.isOverZ())
// fixme: improve when Bareiss will be done
// switch to Q and then to Z
Expand Down Expand Up @@ -490,8 +511,17 @@ MultivariatePolynomial<Poly> generate(
/**
* Computes Leinart's decomposition of given rational expression (see https://arxiv.org/abs/1206.4740)
*/
public static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
@SuppressWarnings("unchecked")
public static <Poly extends AMultivariatePolynomial>
List<Rational<Poly>> LeinartDecomposition(Rational<Poly> fraction) {
return LeinartDecomposition0(fraction);
}

/**
* Computes Leinart's decomposition of given rational expression (see https://arxiv.org/abs/1206.4740)
*/
private static <Term extends AMonomial<Term>, Poly extends AMultivariatePolynomial<Term, Poly>>
List<Rational<Poly>> LeinartDecomposition0(Rational<Poly> fraction) {
FactorDecomposition<Poly> denDecomposition = fraction.factorDenominator();
List<Factor<Term, Poly>> denominator = IntStream.range(0, denDecomposition.size())
.mapToObj(i -> new Factor<>(denDecomposition.get(i), denDecomposition.getExponent(i)))
Expand Down Expand Up @@ -522,22 +552,13 @@ List<Fraction<Term, Poly>> AlgebraicDecomposition(Fraction<Term, Poly> fraction)
if (!probablyAlgebraicallyDependentQ(fraction.bareDenominatorNoUnits()))
return Collections.singletonList(fraction);

TIntArrayList positions = new TIntArrayList();
List<Poly> denPolys = new ArrayList<>();
List<Poly> raisedDenominator = fraction.raisedDenominator();
for (int i = 0; i < raisedDenominator.size(); ++i) {
if (raisedDenominator.get(i).isConstant())
continue;
positions.add(i);
denPolys.add(raisedDenominator.get(i));
}
assert raisedDenominator.stream().noneMatch(IPolynomial::isConstant);

List<Poly> annihilators = algebraicRelations(denPolys);
List<Poly> annihilators = algebraicRelations(raisedDenominator);
if (annihilators.isEmpty())
return Collections.singletonList(fraction);

int[] varsMapping = positions.toArray();
annihilators = annihilators.stream().map(p -> p.mapVariables(varsMapping)).collect(Collectors.toList());
// denominators are algebraically dependent
// choose the simplest annihilator
Poly annihilator = annihilators
Expand All @@ -556,8 +577,8 @@ List<Fraction<Term, Poly>> AlgebraicDecomposition(Fraction<Term, Poly> fraction)
List<Fraction<Term, Poly>> result = new ArrayList<>();
for (Term numFactor : annihilator) {
// numFactor / minNormTerm / denominator
int[] numExponents = numFactor.exponents;
int[] denExponents = ArraysUtil.sum(denominatorExponents, minNormTerm.exponents);
int[] numExponents = ArraysUtil.multiply(denominatorExponents, numFactor.exponents);
int[] denExponents = ArraysUtil.sum(denominatorExponents, ArraysUtil.multiply(denominatorExponents, minNormTerm.exponents));

for (int i = 0; i < numExponents.length; ++i) {
if (numExponents[i] >= denExponents[i]) {
Expand Down Expand Up @@ -604,10 +625,20 @@ private static final class Fraction<Term extends AMonomial<Term>, Poly extends A
}

Fraction(Poly numerator, List<Factor<Term, Poly>> denominator, Poly denominatorConstantFactor) {
denominator = new ArrayList<>(denominator);
denominatorConstantFactor = denominatorConstantFactor.clone();
for (int i = denominator.size() - 1; i >= 0; --i)
if (denominator.get(i).isConstant()) {
denominatorConstantFactor = denominatorConstantFactor.multiply(denominator.get(i).raised);
denominator.remove(i);
}
Poly cGcd = PolynomialMethods.PolynomialGCD(numerator, denominatorConstantFactor);
this.numerator = numerator.divideByLC(cGcd);
this.denominator = denominator;
this.denominatorConstantFactor = denominatorConstantFactor.divideByLC(cGcd);

for (int i = 0; i < raisedDenominator().size(); ++i)
assert !(raisedDenominator().get(i).isConstant());
}

final List<Poly> raisedDenominator() {
Expand Down Expand Up @@ -637,7 +668,7 @@ private static final class Factor<Term extends AMonomial<Term>, Poly extends AMu
final Poly raised;

Factor(Poly factor, int exponent, Poly raised) {
this.factor = factor;
this.factor = exponent == 0 ? factor.createOne() : factor;
this.exponent = exponent;
this.raised = raised;
}
Expand All @@ -657,5 +688,9 @@ Factor<Term, Poly> setExponent(int newExponent) {
return new Factor<>(factor, newExponent, PolynomialMethods.polyPow(raised, newExponent / exponent));
return new Factor<>(factor, newExponent);
}

boolean isConstant() {
return factor.isConstant();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,10 @@ static boolean isBivariateCertainlyIrreducible(AMultivariatePolynomial<? extends
if (poly.isEffectiveUnivariate())
return factorUnivariate(poly);

MonomialZp64 mContent = poly.monomialContent();
if (mContent.totalDegree != 0)
return bivariateDenseFactorSquareFreeInGF(poly.divideOrNull(mContent)).addFactor(poly.create(mContent), 1);

if (isBivariateCertainlyIrreducible(poly))
return PolynomialFactorDecomposition.of(poly);

Expand Down Expand Up @@ -729,6 +733,10 @@ void swap(PolynomialFactorDecomposition<Poly> factorDecomposition) {
if (poly.isEffectiveUnivariate())
return factorUnivariate(poly);

Monomial<E> mContent = poly.monomialContent();
if (mContent.totalDegree != 0)
return bivariateDenseFactorSquareFreeInGF(poly.divideOrNull(mContent)).addFactor(poly.create(mContent), 1);

if (isBivariateCertainlyIrreducible(poly))
return PolynomialFactorDecomposition.of(poly);

Expand Down Expand Up @@ -1000,6 +1008,10 @@ PolynomialFactorDecomposition<Poly> denseBivariateRecombination(
if (poly.isEffectiveUnivariate())
return factorUnivariate(poly);

Monomial<BigInteger> mContent = poly.monomialContent();
if (mContent.totalDegree != 0)
return bivariateDenseFactorSquareFreeInZ(poly.divideOrNull(mContent)).addFactor(poly.create(mContent), 1);

if (isBivariateCertainlyIrreducible(poly))
return PolynomialFactorDecomposition.of(poly);

Expand Down Expand Up @@ -1050,7 +1062,11 @@ PolynomialFactorDecomposition<Poly> denseBivariateRecombination(
tryZeroFirst = false;
} else {
int bound = 10 * (univariateFactorizations / 5 + 1);
if (bound < usedSubstitutions.size())
bound = usedSubstitutions.size();
do {
if (usedSubstitutions.size() == bound)
bound *= 2;
substitution = BigInteger.valueOf(cc.redberry.rings.poly.multivar.PrivateRandom.getRandom().nextInt(bound));
} while (usedSubstitutions.contains(substitution));
usedSubstitutions.add(substitution);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ else if (isOverMultivariate(a))
else if (isOverMultivariateZp64(a))
return (Poly) PolynomialGCDOverMultivariateZp64((MultivariatePolynomial) a, (MultivariatePolynomial) b);

throw new RuntimeException("Multivariate GCD over " + a.coefficientRingToString() + " ring not supported.");
return null;
}

static <Poly extends AMultivariatePolynomial>
Expand Down
7 changes: 7 additions & 0 deletions rings/src/main/java/cc/redberry/rings/util/ArraysUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,13 @@ public static int[] sum(final int[] a, final int[] b) {
return c;
}

public static int[] multiply(final int[] a, final int[] b) {
int[] c = new int[a.length];
for (int i = 0; i < c.length; i++)
c[i] = a[i] * b[i];
return c;
}

public static int[] subtract(final int[] a, final int[] b) {
int[] c = new int[a.length];
for (int i = 0; i < c.length; i++)
Expand Down
Loading

0 comments on commit 68a5aee

Please sign in to comment.