Skip to content

Commit

Permalink
Api enhancements (#24)
Browse files Browse the repository at this point in the history
- generify `FactorDecomposition`
- rename old `FactorDecomposition` to `PolynomialFactorDecomposition`
- implement `FactorDecomposition` for generic rings
- add default `gcd` method in Ring interface
- add default `extendedGCD` method to `Ring` interface
- add `factor` and `factorSquareFree` methods to `Ring` interface
- rename PolynomialRing in scaladsl to IPolynomialRing (consistent with Java API)
- synthetic sugar methods for Rationals in scaladsl
- Diophantine solver for univariate polynomials
- Util multivariate conversions
- minor fixes
  • Loading branch information
PoslavskySV authored Dec 6, 2017
1 parent aaa947a commit 08d525c
Show file tree
Hide file tree
Showing 63 changed files with 1,998 additions and 1,076 deletions.
14 changes: 7 additions & 7 deletions doc/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,7 @@ Methods added to `Ring[E]`_ interface:
Polynomial ring methods
"""""""""""""""""""""""

Methods added to `PolynomialRing[Poly, E]`_ class (``Poly`` is polynomial type, ``E`` is a type of coefficients):
Methods added to `IPolynomialRing[Poly, E]`_ interface (``Poly`` is polynomial type, ``E`` is a type of coefficients):

+------------------------------+--------------------------------------------------------------------------------------------------+
| Scala DSL | Description |
Expand All @@ -808,14 +808,14 @@ Methods added to `PolynomialRing[Poly, E]`_ class (``Poly`` is polynomial type,
+------------------------------+--------------------------------------------------------------------------------------------------+


For more details see `PolynomialRing[Poly, E]`_.
For more details see `IPolynomialRing[Poly, E]`_.


.. _Ring<E>: https://github.com/PoslavskySV/rings/blob/develop/rings/src/main/java/cc/redberry/rings/Ring.java

.. _Ring[E]: https://github.com/PoslavskySV/rings/blob/develop/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Rings.scala

.. _PolynomialRing[Poly, E]: https://github.com/PoslavskySV/rings/blob/develop/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Rings.scala
.. _IPolynomialRing[Poly, E]: https://github.com/PoslavskySV/rings/blob/develop/rings.scaladsl/src/main/scala/cc/redberry/rings/scaladsl/Rings.scala

.. _Z: https://github.com/PoslavskySV/rings/blob/develop/rings/src/main/java/cc/redberry/rings/Rings.java#L30

Expand Down Expand Up @@ -1031,7 +1031,7 @@ Note that there is no any specific polynomial ring used in the ``genericFunc`` a
* @tparam E type of polynomial coefficients
*/
def genericFuncWithRing[Poly <: IPolynomial[Poly], E](poly: Poly)
(implicit ring: PolynomialRing[Poly, E]): Poly = {
(implicit ring: IPolynomialRing[Poly, E]): Poly = {
poly.pow(2) * 3 + poly * 2 + 1
}
Expand All @@ -1049,7 +1049,7 @@ Note that there is no any specific polynomial ring used in the ``genericFunc`` a
/**
* @param <Poly> polynomial type
*/
static <Poly extends IPolynomial<Poly>> Poly genericFuncWithRing(Poly poly, PolynomialRing<Poly> ring) {
static <Poly extends IPolynomial<Poly>> Poly genericFuncWithRing(Poly poly, IPolynomialRing<Poly> ring) {
return ring.add(
ring.getOne(),
ring.multiply(poly, ring.valueOf(2)),
Expand Down Expand Up @@ -1165,7 +1165,7 @@ Internally both implementations use dense data structure (array of coefficients)
* @param <Poly> univariate polynomial type
*/
static <Poly extends IUnivariatePolynomial<Poly>>
Poly genericFuncWithRing(Poly poly, PolynomialRing<Poly> ring) { return null; }
Poly genericFuncWithRing(Poly poly, IPolynomialRing<Poly> ring) { return null; }

.. _ref-univariate-divison:
Expand Down Expand Up @@ -1628,7 +1628,7 @@ The generic parent class for multivariate polynomials is `AMultivariatePolynomia
*/
static <Monomial extends DegreeVector<Monomial>,
Poly extends AMultivariatePolynomial<Monomial, Poly>>
Poly genericFuncWithRing(Poly poly, PolynomialRing<Poly> ring) { return null; }
Poly genericFuncWithRing(Poly poly, IPolynomialRing<Poly> ring) { return null; }
// call generic funcs
genericFunc(MultivariatePolynomial.parse("a + b"));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package cc.redberry.rings.benchmark;

import cc.redberry.rings.benchmark.Bench.ExternalResult;
import cc.redberry.rings.poly.FactorDecomposition;
import cc.redberry.rings.poly.PolynomialFactorDecomposition;
import cc.redberry.rings.poly.PolynomialMethods;
import cc.redberry.rings.poly.univar.UnivariatePolynomialZp64;
import cc.redberry.rings.util.TimeUnits;
Expand All @@ -10,10 +10,8 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;

import static cc.redberry.rings.benchmark.Bench.mathematicaFactor;
import static cc.redberry.rings.benchmark.Bench.writeTimingsTSV;

public class Rings_vs_NTL_vs_FLINT_vs_Mathematica_UnivariateZp {
//NTL and FLINT data are generated from C++ binaries!
Expand Down Expand Up @@ -47,7 +45,7 @@ public static long[][] run(int maxL, boolean silent) throws IOException {

long start = System.nanoTime();
for (int i = 0; i < nIterations; i++) {
FactorDecomposition<UnivariatePolynomialZp64> rFactors = PolynomialMethods.Factor(poly);
PolynomialFactorDecomposition<UnivariatePolynomialZp64> rFactors = PolynomialMethods.Factor(poly);
dummy += rFactors.signum();
}
long ringsTime = (System.nanoTime() - start);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import cc.redberry.rings.Ring;
import cc.redberry.rings.Rings;
import cc.redberry.rings.bigint.BigInteger;
import cc.redberry.rings.poly.FactorDecomposition;
import cc.redberry.rings.poly.PolynomialFactorDecomposition;
import cc.redberry.rings.poly.MultivariateRing;
import cc.redberry.rings.poly.PolynomialMethods;
import cc.redberry.rings.poly.multivar.MultivariatePolynomial;
Expand Down Expand Up @@ -133,7 +133,7 @@ static long[][] run(int nVariables,
System.out.println("Sparsity: " + poly.sparsity());

long start = System.nanoTime();
FactorDecomposition<MultivariatePolynomial<BigInteger>> ringsResult
PolynomialFactorDecomposition<MultivariatePolynomial<BigInteger>> ringsResult
= timeConstrained(RINGS_TIMEOUT, () -> PolynomialMethods.Factor(poly));
long ringsTime = System.nanoTime() - start;
if (!silent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ trait PolynomialSetSyntax {
implicit def polynomialSetOps[Poly <: IPolynomial[Poly]](poly: Poly): PolynomialSetOps[Poly] = new PolynomialSetOps[Poly](poly)
}

class PolynomialCfOps[Poly <: IPolynomial[Poly], E](self: Poly)(pRing: PolynomialRing[Poly, E]) {
class PolynomialCfOps[Poly <: IPolynomial[Poly], E](self: Poly)(pRing: IPolynomialRing[Poly, E]) {
def lc: E = pRing.lc(self)

def cc: E = pRing.cc(self)
Expand Down Expand Up @@ -246,7 +246,7 @@ class MultivariateCfOps[Term <: DegreeVector[Term], Poly <: AMultivariatePolynom
def swapVariables(i: String, j: String): Poly = rings.poly.multivar.AMultivariatePolynomial.swapVariables[Term, Poly](self, pRing.index(i), pRing.index(j))
}

class CfOps[E, Poly <: IPolynomial[Poly]](self: E)(ring: PolynomialRing[Poly, E]) {
class CfOps[E, Poly <: IPolynomial[Poly]](self: E)(ring: IPolynomialRing[Poly, E]) {
def +(poly: Poly): Poly = ring.addConstant(poly, self)

def -(poly: Poly): Poly = ring.negate(ring.subtractConstant(poly, self))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package cc.redberry.rings.scaladsl
import cc.redberry.rings
import cc.redberry.rings.bigint.BigInteger
import cc.redberry.rings.poly.FiniteField
import cc.redberry.rings.{IntegersZp64, Rational, poly}
import cc.redberry.rings.{FactorDecomposition, IntegersZp64, poly}
import org.apache.commons.math3.random.{AbstractRandomGenerator, RandomGenerator}

import scala.collection.JavaConverters.collectionAsScalaIterableConverter
import scala.language.implicitConversions
import scala.util.Random

Expand Down Expand Up @@ -35,30 +36,30 @@ private[scaladsl] trait Predef {
override def setSeed(seed: Long): Unit = random.setSeed(seed)
}
/**
* Delegate [[PolynomialRing]] methods for [[PolynomialRing]]
* Delegate [[IPolynomialRing]] methods for [[IPolynomialRing]]
*/
implicit def ringMethods[Poly <: IPolynomial[Poly], E](ring: PolynomialRing[Poly, E]): poly.PolynomialRing[Poly] = ring.theRing
implicit def ringMethods[Poly <: IPolynomial[Poly], E](ring: IPolynomialRing[Poly, E]): rings.poly.IPolynomialRing[Poly] = ring.theRing

/**
* Delegate [[PolynomialRing]] methods for [[PolynomialRing]]
* Delegate [[IPolynomialRing]] methods for [[IPolynomialRing]]
*/
implicit def ringMethods[E](ring: UnivariateRing[E]): poly.UnivariateRing[UnivariatePolynomial[E]]
= ring.theRing.asInstanceOf[poly.UnivariateRing[UnivariatePolynomial[E]]]

/**
* Delegate [[PolynomialRing]] methods for [[PolynomialRing]]
* Delegate [[IPolynomialRing]] methods for [[IPolynomialRing]]
*/
implicit def ringMethods(ring: UnivariateRingZp64): poly.UnivariateRing[UnivariatePolynomialZp64]
= ring.theRing.asInstanceOf[poly.UnivariateRing[UnivariatePolynomialZp64]]

/**
* Delegate [[PolynomialRing]] methods for [[PolynomialRing]]
* Delegate [[IPolynomialRing]] methods for [[IPolynomialRing]]
*/
implicit def ringMethods[E](ring: MultivariateRing[E]): poly.MultivariateRing[MultivariatePolynomial[E]]
= ring.theRing.asInstanceOf[poly.MultivariateRing[MultivariatePolynomial[E]]]

/**
* Delegate [[PolynomialRing]] methods for [[PolynomialRing]]
* Delegate [[IPolynomialRing]] methods for [[IPolynomialRing]]
*/
implicit def ringMethods(ring: MultivariateRingZp64): poly.MultivariateRing[MultivariatePolynomialZp64]
= ring.theRing.asInstanceOf[poly.MultivariateRing[MultivariatePolynomialZp64]]
Expand Down Expand Up @@ -96,7 +97,7 @@ private[scaladsl] trait Predef {
/**
* Field of rationals (Q)
*/
val Q: Ring[Rational[BigInteger]] = rings.Rings.Q
val Q: Ring[rings.Rational[BigInteger]] = rings.Rings.Q

/**
* Field of integers modulo `modulus`
Expand Down Expand Up @@ -151,7 +152,7 @@ private[scaladsl] trait Predef {
def apply(cf: Int, exponents: Int*) = new MonomialZp64(exponents.toArray, cf.toLong)

def apply(cf: Int, exponents: (String, Int)*)
(implicit ring: PolynomialRing[MultivariatePolynomialZp64, Long]) = {
(implicit ring: IPolynomialRing[MultivariatePolynomialZp64, Long]) = {
val exps: Array[Int] = new Array[Int](exponents.length)
exponents.foreach(e => exps(ring.index(e._1)) = e._2)
new MonomialZp64(exps, ring.cfValue(cf))
Expand All @@ -162,13 +163,31 @@ private[scaladsl] trait Predef {
def apply[E](cf: E, exponents: Int*) = new Monomial[E](exponents.toArray, cf)

def apply[E](cf: E, exponents: (String, Int)*)
(implicit ring: PolynomialRing[MultivariatePolynomial[E], E]) = {
(implicit ring: IPolynomialRing[MultivariatePolynomial[E], E]) = {
val exps: Array[Int] = new Array[Int](exponents.length)
exponents.foreach(e => exps(ring.index(e._1)) = e._2)
new Monomial[E](exps, cf)
}
}

object Rational {
def apply[E](num: E, den: E)(implicit ring: Ring[E]): rings.Rational[E] = new rings.Rational[E](ring, num, den)

def apply[E](num: E)(implicit ring: Ring[E]): rings.Rational[E] = new rings.Rational[E](ring, num)

@inline
def apply[E](num: Int, den: E)(implicit ring: Ring[E]): rings.Rational[E] = apply(ring(num), den)(ring)

@inline
def apply[E](num: E, den: Int)(implicit ring: Ring[E]): rings.Rational[E] = apply(num, ring(den))(ring)

@inline
def apply[E](num: Int, den: Int)(implicit ring: Ring[E]): rings.Rational[E] = apply(ring(num), ring(den))(ring)

@inline
def apply[E](num: Int)(implicit ring: Ring[E]): rings.Rational[E] = apply(ring(num))(ring)
}

final class RichArrayTuple[Poly](arr: Array[Poly]) {
def tuple2: (Poly, Poly) = (arr(0), arr(1))

Expand All @@ -178,4 +197,7 @@ private[scaladsl] trait Predef {
}

implicit def arrayToTuple[Poly](arr: Array[Poly]): RichArrayTuple[Poly] = new RichArrayTuple(arr)

implicit def factors2Seq[E](factors: FactorDecomposition[E]): Seq[(E, Int)] =
(factors.factors.asScala zip factors.exponents.toArray().toSeq).toSeq
}
Loading

0 comments on commit 08d525c

Please sign in to comment.