# $Id: jas.rb 4436 2013-05-25 10:43:29Z kredel $ =begin rdoc jruby interface to JAS. =end module JAS module_function require "java" require "rational" require "mathn" java_import "java.lang.System" java_import "java.io.StringReader" java_import "java.util.ArrayList" java_import "java.util.Collections" #require "../lib/log4j.jar" java_import "org.apache.log4j.BasicConfigurator"; java_import "org.apache.log4j.Logger"; =begin rdoc Configure the log4j system and start logging. =end def startLog() BasicConfigurator.configure(); end #startLog(); =begin rdoc Mimic Python str() function. =end def str(s) return s.to_s; end java_import "edu.jas.kern.ComputerThreads"; =begin rdoc Terminate the running thread pools. =end def terminate() ComputerThreads.terminate(); end =begin rdoc Turn off automatic parallel threads usage. =end def noThreads() puts "nt = ", ComputerThreads.NO_THREADS; ComputerThreads.setNoThreads(); #NO_THREADS = #0; #1; #true; puts "\nnt = ", ComputerThreads.NO_THREADS; puts end =begin rdoc Inject variables for generators in given environment. =end def inject_gens(env) env.class.instance_eval( "attr_accessor :generators;" ) if env.generators == nil env.generators = {}; end #puts "existing generators: " + env.generators.keys().join(", "); for i in self.gens() begin ivs = i.to_s if not ivs.include?(",") and not ivs.include?("(") if ivs == "1" or ivs == "1 " ivs = "one" end if env.generators[ ivs ] != nil puts "redefining #{ivs}"; end env.generators[ ivs ] = i; env.instance_eval( "def #{ivs}; @generators[ '#{ivs}' ]; end" ) #puts "def #{ivs}; @generators[ '#{ivs}' ]; end" first = ivs.slice(0,1); if first.count('A-Z') > 0 first = first.downcase ivl = first + ivs.slice(1,ivs.length); puts "warning: '" + str(ivs) + "' additionaly renamed to '" + str(ivl) + "' to avoid constant semantics" env.instance_eval( "def #{ivl}; @generators[ '#{ivs}' ]; end" ) end end rescue puts "error: #{i} = " + i.to_s + ", class = " + i.class.to_s; end end puts "globally defined generators: " + env.generators.keys().join(", "); end # set output to Ruby scripting java_import "edu.jas.kern.Scripting"; Scripting.setLang(Scripting::Lang::Ruby); java_import "edu.jas.util.ExecutableServer"; java_import "edu.jas.structure.Power"; java_import "edu.jas.arith.BigInteger"; java_import "edu.jas.arith.BigRational"; java_import "edu.jas.arith.ModInteger"; java_import "edu.jas.arith.ModIntegerRing"; java_import "edu.jas.arith.BigDecimal"; java_import "edu.jas.arith.BigComplex"; java_import "edu.jas.arith.BigQuaternion"; java_import "edu.jas.arith.BigOctonion"; java_import "edu.jas.arith.Product"; java_import "edu.jas.arith.ProductRing"; java_import "edu.jas.arith.PrimeList"; =begin rdoc Create JAS BigInteger as ring element. =end def ZZ(z=0) if z.is_a? RingElem z = z.elem; end r = Java::EduJasArith::BigInteger.new(z); return RingElem.new(r); end =begin rdoc Create JAS ModInteger as ring element. =end def ZM(m,z=0,field=false) if m.is_a? RingElem m = m.elem; end if z.is_a? RingElem z = z.elem; end if z != 0 and ( z == true or z == false ) field = z; z = 0; end if field mf = ModIntegerRing.new(m,field); else mf = ModIntegerRing.new(m); end r = ModInteger.new(mf,z); return RingElem.new(r); end =begin rdoc Create JAS ModInteger as field element. =end def GF(m,z=0) return ZM(m,z,true); end =begin rdoc Create JAS BigRational as ring element. =end def QQ(d=0,n=1) if d.is_a? Rational if n != 1 puts "#{n} ignored\n"; end if d.denominator != 1 n = d.denominator; end d = d.numerator; end if d.is_a? RingElem d = d.elem; end if n.is_a? RingElem n = n.elem; end if n == 1 if d == 0 r = BigRational.new(); else r = BigRational.new(d); end else d = BigRational.new(d); n = BigRational.new(n); r = d.divide(n); # BigRational.new(d,n); only for short integers end return RingElem.new(r); end =begin rdoc Create JAS BigComplex as ring element. =end def CC(re=BigRational.new(),im=BigRational.new()) if re == 0 re = BigRational.new(); end if im == 0 im = BigRational.new(); end if re.is_a? Array if re[0].is_a? Array if re.size > 1 im = QQ( re[1] ); end re = QQ( re[0] ); else re = QQ(re); # re = makeJasArith( re ); end end if im.is_a? Array im = QQ( im ); # im = makeJasArith( im ); end if re.is_a? Numeric re = QQ(re); end if im.is_a? Numeric im = QQ(im); end if re.is_a? RingElem re = re.elem; end if im.is_a? RingElem im = im.elem; end if im.isZERO() if re.isZERO() c = BigComplex.new(); else c = BigComplex.new(re); end else c = BigComplex.new(re,im); end return RingElem.new(c); end =begin rdoc Create JAS generic Complex as ring element. =end def CR(re=BigRational.new(),im=BigRational.new(),ring=nil) if re == 0 re = BigRational.new(); end if im == 0 im = BigRational.new(); end if re.is_a? Array if re[0].is_a? Array if re.size > 1 im = QQ( re[1] ); end re = QQ( re[0] ); else re = QQ(re); # re = makeJasArith( re ); end end if im.is_a? Array im = QQ( im ); # im = makeJasArith( im ); end if re.is_a? RingElem re = re.elem; end if im.is_a? RingElem im = im.elem; end if ring == nil ring = re.factory(); end r = ComplexRing.new(ring); if im.isZERO() if re.isZERO() c = Complex.new(r); else c = Complex.new(r,re); end else c = Complex.new(r,re,im); end return RingElem.new(c); end =begin rdoc Create JAS BigDecimal as ring element. =end def DD(d=0) if d.is_a? RingElem d = d.elem; end if d.is_a? Float d = d.to_s; end #puts "d type(#{d}) = #{d.class}"; if d == 0 r = BigDecimal.new(); else r = BigDecimal.new(d); end return RingElem.new(r); end =begin rdoc Create JAS BigQuaternion as ring element. =end def Quat(re=BigRational.new(),im=BigRational.new(),jm=BigRational.new(),km=BigRational.new()) if re == 0 re = BigRational.new(); end if im == 0 im = BigRational.new(); end if jm == 0 jm = BigRational.new(); end if km == 0 km = BigRational.new(); end if re.is_a? Numeric re = QQ(re); # re = makeJasArith( re ); end if im.is_a? Numeric im = QQ( im ); end if jm.is_a? Numeric jm = QQ( jm ); end if km.is_a? Numeric kim = QQ( km ); # im = makeJasArith( im ); end if re.is_a? RingElem re = re.elem; end if im.is_a? RingElem im = im.elem; end if jm.is_a? RingElem jm = jm.elem; end if km.is_a? RingElem km = km.elem; end c = BigQuaternion.new(re,im,jm,km); return RingElem.new(c); end =begin rdoc Create JAS BigOctonion as ring element. =end def Oct(ro=BigQuaternion.new(),io=BigQuaternion.new()) if ro == 0 ro = BigQuaternion.new(); end if io == 0 io = BigQuaternion.new(); end if ro.is_a? Array if ro[0].is_a? Array if ro.size > 1 io = QQ( ro[1] ); end ro = QQ( ro[0] ); else ro = QQ(ro); # re = makeJasArith( re ); end end if io.is_a? Array io = QQ( io ); # im = makeJasArith( im ); end if ro.is_a? RingElem ro = ro.elem; end if io.is_a? RingElem io = io.elem; end c = BigOctonion.new(ro,io); return RingElem.new(c); end =begin rdoc Proxy for JAS ring elements. Methods to be used as + - * ** / %. =end class RingElem include Comparable attr_reader :elem, :ring =begin rdoc Constructor for ring element. =end def initialize(elem) if elem.is_a? RingElem @elem = elem.elem; else @elem = elem; end begin @ring = @elem.factory(); rescue @ring = @elem; end @elem.freeze @ring.freeze self.freeze end =begin rdoc Create a string representation. =end def to_s() return @elem.toScript(); #return @elem.toString(); end =begin rdoc Convert to float. =end def to_f() e = @elem; if e.getClass().getSimpleName() == "BigInteger" e = BigRational(e); end if e.getClass().getSimpleName() == "BigRational" e = BigDecimal(e); end if e.getClass().getSimpleName() == "BigDecimal" e = e.toString(); end e = e.to_f(); return e; end =begin rdoc Zero element of this ring. =end def zero() return RingElem.new( @elem.factory().getZERO() ); end =begin rdoc Test if this is the zero element of the ring. =end def isZERO() return @elem.isZERO(); end =begin rdoc Test if this is the zero element of the ring. =end def zero?() return @elem.isZERO(); end =begin rdoc One element of this ring. =end def one() return RingElem.new( @elem.factory().getONE() ); end =begin rdoc Test if this is the one element of the ring. =end def isONE() return @elem.isONE(); end =begin rdoc Test if this is the one element of the ring. =end def one?() return @elem.isONE(); end =begin rdoc Get the sign of this element. =end def signum() return @elem.signum(); end =begin rdoc Absolute value. =end def abs() return RingElem.new( @elem.abs() ); end =begin rdoc Negative value. =end def -@() return RingElem.new( @elem.negate() ); end =begin rdoc Positive value. =end def +@() return self; end =begin rdoc Coerce other to self =end def coerce(other) s,o = coercePair(self,other); return [o,s]; # keep order for non-commutative end =begin rdoc Coerce type a to type b or type b to type a. =end def coercePair(a,b) #puts "a type(#{a}) = #{a.class}\n"; #puts "b type(#{b}) = #{b.class}\n"; begin if not a.isPolynomial() and b.isPolynomial() s = b.coerceElem(a); o = b; else s = a; o = a.coerceElem(b); end rescue s = a; o = a.coerceElem(b); end #puts "s type(#{s}) = #{s.class}\n"; #puts "o type(#{o}) = #{o.class}\n"; return [s,o]; end =begin rdoc Coerce other to self =end def coerceElem(other) #puts "self type(#{self}) = #{self.class}\n"; #puts "other type(#{other}) = #{other.class}\n"; if @elem.getClass().getSimpleName() == "GenVector" if other.is_a? Array o = rbarray2arraylist(other,@elem.factory().coFac,rec=1); o = GenVector.new(@elem.factory(),o); return RingElem.new( o ); end end if @elem.getClass().getSimpleName() == "GenMatrix" if other.is_a? Array o = rbarray2arraylist(other,@elem.factory().coFac,rec=2); o = GenMatrix.new(@elem.factory(),o); return RingElem.new( o ); end end if other.is_a? RingElem if isPolynomial() and not other.isPolynomial() o = @ring.parse( other.elem.toString() ); # not toScript() return RingElem.new( o ); end return other; end #puts "--1"; if other.is_a? Array # assume BigRational or BigComplex # assume self will be compatible with them. todo: check this puts "other type(#{other})_3 = #{other.class}\n"; o = makeJasArith(other); puts "other type(#{o})_4 = #{o.class}\n"; ##o = BigRational.new(other[0],other[1]); if isPolynomial() o = @ring.parse( o.toString() ); # not toScript(); #o = o.elem; elsif @elem.getClass().getSimpleName() == "BigComplex" o = CC( o ); o = o.elem; elsif @elem.getClass().getSimpleName() == "BigQuaternion" o = Quat( o ); o = o.elem; elsif @elem.getClass().getSimpleName() == "BigOctonion" o = Oct( Quat(o) ); o = o.elem; elsif @elem.getClass().getSimpleName() == "Product" o = RR(@ring, @elem.multiply(o) ); # valueOf #puts "o = #{o}"; o = o.elem; end puts "other type(#{o})_5 = #{o.class}\n"; return RingElem.new(o); end # test if @elem is a factory itself if isFactory() if other.is_a? Integer o = @elem.fromInteger(other); elsif other.is_a? Rational o = @elem.fromInteger( other.numerator ); o = o.divide( @elem.fromInteger( other.denominator ) ); elsif other.is_a? Float # ?? what to do ?? o = @elem.parse( other.to_s ); ##o = @elem.fromInteger( other.to_i ); else puts "unknown other type(#{other})_1 = #{other.class}\n"; o = @elem.parse( other.to_s ); end return RingElem.new(o); end # @elem has a ring factory if other.is_a? Integer o = @elem.factory().fromInteger(other); elsif other.is_a? Rational o = @elem.factory().fromInteger( other.numerator ); o = o.divide( @elem.factory().fromInteger( other.denominator ) ); elsif other.is_a? Float # ?? what to do ?? o = @elem.factory().parse( other.to_s ); if @elem.getClass().getSimpleName() == "Product" o = RR(@ring, @elem.idempotent().multiply(o) ); # valueOf o = o.elem; end else puts "unknown other type(#{other})_2 = #{other.class}\n"; o = @elem.factory().parse( other.to_s ); end return RingElem.new(o); end =begin rdoc Test if this is itself a ring factory. =end def isFactory() f = @elem.factory(); if @elem == f return true; else return false; end end =begin rdoc Test if this is a polynomial. =end def isPolynomial() begin nv = @elem.ring.nvar; rescue return false; end return true; end =begin rdoc Compare two ring elements. =end def <=>(other) #s,o = coercePair(other); s,o = self, other return s.elem.compareTo( o.elem ); end =begin rdoc Test if two ring elements are equal. =end def ===(other) return (self <=> other) == 0; end =begin rdoc Length of an element. =end def len() return self.elem.length(); end =begin rdoc Hash value. =end def object_id() return @elem.hashCode(); end =begin rdoc Multiply two ring elements. =end def *(other) #puts "* self type(#{self}) = #{self.class}\n"; #puts "* other type(#{other}) = #{other.class}\n"; s,o = coercePair(self,other); return RingElem.new( s.elem.multiply( o.elem ) ); end =begin rdoc Add two ring elements. =end def +(other) #puts "+ self type(#{self}) = #{self.elem.class}\n"; #puts "+ other type(#{other}) = #{other.elem.class}\n"; s,o = coercePair(self,other); return RingElem.new( s.elem.sum( o.elem ) ); end =begin rdoc Subtract two ring elements. =end def -(other) #puts "+ self type(#{self}) = #{self.elem.class}\n"; #puts "+ other type(#{other}) = #{other.elem.class}\n"; s,o = coercePair(self,other); return RingElem.new( s.elem.subtract( o.elem ) ); end =begin rdoc Divide two ring elements. =end def /(other) s,o = coercePair(self,other); return RingElem.new( s.elem.divide( o.elem ) ); end =begin rdoc Modular remainder of two ring elements. =end def %(other) s,o = coercePair(self,other); return RingElem.new( s.elem.remainder( o.elem ) ); end =begin rdoc Can not be used as power. =end def ^(other) return nil; end =begin rdoc Power of this to other. =end def **(other) #puts "pow other type(#{other}) = #{other.class}"; if other.is_a? Integer n = other; else if other.is_a? RingElem n = other.elem; if n.getClass().getSimpleName() == "BigRational" n = n.numerator().intValue() / n.denominator().intValue(); end if n.getClass().getSimpleName() == "BigInteger" n = n.intValue(); end end end if isFactory() p = Power.new(@elem).power( @elem, n ); else p = Power.new(@elem.ring).power( @elem, n ); end return RingElem.new( p ); end =begin rdoc Test if two ring elements are equal. =end def equal?(other) o = other; if other.is_a? RingElem o = other.elem; end return @elem.equals(o) end =begin rdoc Get the factory of this element. =end def factory() fac = @elem.factory(); begin nv = fac.nvar; rescue return RingElem.new(fac); end #return PolyRing(fac.coFac,fac.getVars(),fac.tord); return RingElem.new(fac); end =begin rdoc Get the generators for the factory of this element. =end def gens() ll = @elem.factory().generators(); #puts "L = #{ll}"; nn = ll.map {|e| RingElem.new(e) }; #puts "N = #{nn}"; return nn; end =begin rdoc Monic polynomial. =end def monic() return RingElem.new( @elem.monic() ); end =begin rdoc Evaluate at a for power series. =end def evaluate(a) #puts "self type(#{@elem}) = #{@elen.class}"; #puts "a type(#{a}) = #{a.class}"; x = nil; if a.is_a? RingElem x = a.elem; end if a.is_a? Array # assume BigRational or BigComplex # assume self will be compatible with them. todo: check this x = makeJasArith(a); end begin e = @elem.evaluate(x); rescue e = 0; end return RingElem.new( e ); end =begin rdoc Integrate a power series with constant a or as rational function. a is the integration constant, r is for partial integration in variable r. =end def integrate(a=0,r=nil) #puts "self type(#{@elem}) = #{@elem.class}"; #puts "a type(#{a}) = #{a.class}"; x = nil; if a.is_a? RingElem x = a.elem; end if a.is_a? Array # assume BigRational or BigComplex # assume self will be compatible with them. todo: check this x = makeJasArith(a); end begin if r != nil e = @elem.integrate(x,r); else e = @elem.integrate(x); end return RingElem.new( e ); rescue #pass; end cf = @elem.ring; begin cf = cf.ring; rescue #pass; end integrator = ElementaryIntegration.new(cf.coFac); ei = integrator.integrate(@elem); return ei; end =begin rdoc Differentiate a power series. r is for partial differentiation in variable r. =end def differentiate(r=nil) begin if r != nil e = @elem.differentiate(r); else e = @elem.differentiate(); end rescue e = @elem.factory().getZERO(); end return RingElem.new( e ); end =begin rdoc Get the coefficients of a polynomial. =end def coefficients() a = @elem; #L = [ c.toScriptFactory() for c in a.coefficientIterator() ]; ll = a.coefficientIterator().map { |c| RingElem.new(c) }; return ll end end java_import "edu.jas.poly.GenPolynomial"; java_import "edu.jas.poly.GenPolynomialRing"; java_import "edu.jas.poly.GenSolvablePolynomial"; java_import "edu.jas.poly.GenSolvablePolynomialRing"; java_import "edu.jas.poly.RecSolvablePolynomial"; java_import "edu.jas.poly.RecSolvablePolynomialRing"; java_import "edu.jas.poly.GenWordPolynomial"; java_import "edu.jas.poly.GenWordPolynomialRing"; java_import "edu.jas.poly.GenPolynomialTokenizer"; java_import "edu.jas.poly.TermOrder"; java_import "edu.jas.poly.OrderedPolynomialList"; java_import "edu.jas.poly.PolyUtil"; java_import "edu.jas.poly.TermOrderOptimization"; java_import "edu.jas.poly.PolynomialList"; java_import "edu.jas.poly.WordFactory"; java_import "edu.jas.poly.AlgebraicNumber"; java_import "edu.jas.poly.AlgebraicNumberRing"; java_import "edu.jas.poly.OrderedModuleList"; java_import "edu.jas.poly.ModuleList"; java_import "edu.jas.poly.Complex"; java_import "edu.jas.poly.ComplexRing"; =begin rdoc Represents a JAS polynomial ring: GenPolynomialRing. Methods to create ideals and ideals with parametric coefficients. =end class Ring attr_reader :ring, :pset, :engine, :sqf, :factor def initialize(ringstr="",ring=nil) =begin rdoc Ring constructor. =end if ring == nil sr = StringReader.new( ringstr ); tok = GenPolynomialTokenizer.new(sr); @pset = tok.nextPolynomialSet(); @ring = @pset.ring; else @ring = ring; end @engine = GCDFactory.getProxy(@ring.coFac); @sqf = nil; @factor = nil; begin @sqf = SquarefreeFactory.getImplementation(@ring.coFac); #puts "sqf: ", @sqf; #rescue Rescueion => e #puts "error " + str(e) rescue #pass end begin @factor = FactorFactory.getImplementation(@ring.coFac); #puts "factor: ", @factor; #rescue Rescueion => e #puts "error " + str(e) rescue #pass end variable_generators() end =begin rdoc Define instance variables for generators. =end def variable_generators() Ring.instance_eval( "attr_accessor :generators;" ) @generators = {}; for i in self.gens() begin ivs = i.to_s if not ivs.include?(",") and not ivs.include?("(") if ivs == "1" or ivs == "1 " ivs = "one" end @generators[ ivs ] = i; self.instance_eval( "def #{ivs}; @generators[ '#{ivs}' ]; end" ) end rescue puts "error: #{i} = " + i.to_s + ", class = " + i.class.to_s; #pass end end puts "locally defined generators: " + @generators.keys().join(", "); end =begin rdoc Inject variables for generators in top level environment. =end def inject_variables() begin require "irb/frame" # must be placed here bin = IRB::Frame.bottom(0); env = eval "self", bin; #puts "env = " + str(env) inject_gens(env) rescue puts "error: 'irb/frame' not found"; end end =begin rdoc Create a string representation. =end def to_s() return @ring.toScript(); end =begin rdoc Create an ideal. =end def ideal(ringstr="",list=nil) return JAS::SimIdeal.new(self,ringstr,list); end =begin rdoc Create an ideal in a polynomial ring with parameter coefficients. =end def paramideal(ringstr="",list=nil,gbsys=nil) return ParamIdeal.new(self,ringstr,list,gbsys); end =begin rdoc Get list of generators of the polynomial ring. =end def gens() ll = @ring.generators(); n = ll.map{ |e| RingElem.new(e) }; return n; end =begin rdoc Get the one of the polynomial ring. =end def one() return RingElem.new( @ring.getONE() ); end =begin rdoc Get the zero of the polynomial ring. =end def zero() return RingElem.new( @ring.getZERO() ); end =begin rdoc Get a random polynomial. =end def random(k=5,l=7,d=3,q=0.3) r = @ring.random(k,l,d,q); if @ring.coFac.isField() r = r.monic(); end return RingElem.new( r ); end =begin rdoc Create an element from a string or an object. =end def element(poly) if not poly.is_a? String begin if @ring == poly.ring return RingElem.new(poly); end rescue Exception => e # pass end poly = str(poly); end i = SimIdeal.new( self, "( " + poly + " )" ); list = i.pset.list; if list.size > 0 return RingElem.new( list[0] ); end end =begin rdoc Compute the greatest common divisor of a and b. =end def gcd(a,b) if a.is_a? RingElem a = a.elem; else a = element( a ); a = a.elem; end if b.is_a? RingElem b = b.elem; else b = element( b ); b = b.elem; end return RingElem.new( @engine.gcd(a,b) ); end =begin rdoc Compute squarefree factors of polynomial. =end def squarefreeFactors(a) if a.is_a? RingElem a = a.elem; else a = element( a ); a = a.elem; end cf = @ring.coFac; if cf.getClass().getSimpleName() == "GenPolynomialRing" e = @sqf.recursiveSquarefreeFactors( a ); else e = @sqf.squarefreeFactors( a ); end ll = {}; for a in e.keySet() i = e.get(a); ll[ RingElem.new( a ) ] = i; end return ll; end =begin rdoc Compute irreducible factorization for modular, integer, rational number and algebriac number coefficients. =end def factors(a) if a.is_a? RingElem a = a.elem; else a = element( a ); a = a.elem; end begin cf = @ring.coFac; if cf.getClass().getSimpleName() == "GenPolynomialRing" e = @factor.recursiveFactors( a ); else e = @factor.factors( a ); end ll = {}; for a in e.keySet() i = e.get(a); ll[ RingElem.new( a ) ] = i; end return ll; rescue Exception => e puts "error " + str(e) return nil end end =begin rdoc Compute absolute irreducible factorization for (modular,) rational number coefficients. =end def factorsAbsolute(a) if a.is_a? RingElem a = a.elem; else a = element( a ); a = a.elem; end begin ll = @factor.factorsAbsolute( a ); ## ll = {}; ## for a in e.keySet() ## i = e.get(a); ## ll[ RingElem.new( a ) ] = i; return ll; rescue Exception => e puts "error in factorsAbsolute " + str(e) return nil end end =begin rdoc Compute real roots of univariate polynomial. =end def realRoots(a,eps=nil) if a.is_a? RingElem a = a.elem; else a = element( a ); a = a.elem; end if eps.is_a? RingElem eps = eps.elem; end begin if eps == nil #rr = RealRootsSturm.new().realRoots( a ); rr = RootFactory.realAlgebraicNumbers( a ) else rr = RootFactory.realAlgebraicNumbers( a, eps ); ## rr = RealRootsSturm.new().realRoots( a, eps ); ## rr = [ r.toDecimal() for r in rr ]; #rr = RealRootsSturm.new().approximateRoots(a,eps); end rr = rr.map{ |e| RingElem.new(e) }; return rr; rescue Exception => e puts "error " + str(e) return nil end end =begin rdoc Compute complex roots of univariate polynomial. =end def complexRoots(a,eps=nil) if a.is_a? RingElem a = a.elem; else a = element( a ); a = a.elem; end if eps.is_a? RingElem eps = eps.elem; end cmplx = false; begin x = a.ring.coFac.getONE().getRe(); cmplx = true; rescue Exception => e #pass; end begin if eps == nil #rr = ComplexRootsSturm.new(a.ring.coFac).complexRoots( a ); if cmplx rr = RootFactory.complexAlgebraicNumbersComplex( a ); else rr = RootFactory.complexAlgebraicNumbers( a ); end #R = [ r.centerApprox() for r in R ]; else ## rr = ComplexRootsSturm.new(a.ring.coFac).complexRoots( a, eps ); ## rr = [ r.centerApprox() for r in rr ]; ##rr = ComplexRootsSturm.new(a.ring.coFac).approximateRoots( a, eps ); if cmplx rr = RootFactory.complexAlgebraicNumbersComplex( a, eps ); else rr = RootFactory.complexAlgebraicNumbers( a, eps ); end end rr = rr.map{ |e| RingElem.new(e) }; return rr; rescue Exception => e puts "error " + str(e) return nil end end =begin rdoc Integrate (univariate) rational function. =end def integrate(a) if a.is_a? RingElem a = a.elem; else a = element( a ); a = a.elem; end cf = @ring; begin cf = cf.ring; rescue #pass; end integrator = ElementaryIntegration.new(cf.coFac); ei = integrator.integrate(a); return ei; end =begin rdoc Get a power series ring from this ring. =end def powerseriesRing() pr = MultiVarPowerSeriesRing.new(@ring); return MultiSeriesRing.new("",nil,pr); end end =begin rdoc Represents a JAS polynomial ring: GenPolynomialRing. Provides more convenient constructor. Then returns a Ring. =end class PolyRing < Ring # class instance variables != class variables @lex = TermOrder.new(TermOrder::INVLEX) @grad = TermOrder.new(TermOrder::IGRLEX) @auto_inject = true class << self # means add to class attr_reader :lex, :grad attr_accessor :auto_inject end =begin rdoc Ring constructor. coeff = factory for coefficients, vars = string with variable names, order = term order. =end def initialize(coeff,vars,order=self.class.grad) if coeff == nil raise ValueError, "No coefficient given." end cf = coeff; if coeff.is_a? RingElem cf = coeff.elem.factory(); end if coeff.is_a? Ring cf = coeff.ring; end if vars == nil raise ValueError, "No variable names given." end names = vars; if vars.is_a? String names = GenPolynomialTokenizer.variableList(vars); end nv = names.size; to = self.class.grad; if order.is_a? TermOrder to = order; end tring = GenPolynomialRing.new(cf,nv,to,names); #want: super(Ring,self).initialize(ring=tring) @ring = tring; super("",@ring) if self.class.auto_inject inject_variables(); end end =begin rdoc Create a string representation. =end def to_s() return @ring.toScript(); end end =begin rdoc Create JAS AlgebraicNumber as ring element. =end def AN(m,z=0,field=false,pr=nil) if m.is_a? RingElem m = m.elem; end if z.is_a? RingElem z = z.elem; end if z != 0 and ( z == true or z == false ) field = z; z = 0; end #puts "m.getClass() = " + str(m.getClass().getName()); #puts "field = " + str(field); if m.getClass().getSimpleName() == "AlgebraicNumber" mf = AlgebraicNumberRing.new(m.factory().modul,m.factory().isField()); else if field mf = AlgebraicNumberRing.new(m,field); else mf = AlgebraicNumberRing.new(m); end end #puts "mf = " + mf.toString(); if z == 0 r = AlgebraicNumber.new(mf); else r = AlgebraicNumber.new(mf,z); end return RingElem.new(r); end java_import "edu.jas.root.RealRootsSturm"; java_import "edu.jas.root.Interval"; java_import "edu.jas.root.RealAlgebraicNumber"; java_import "edu.jas.root.RealAlgebraicRing"; java_import "edu.jas.root.ComplexRootsSturm"; java_import "edu.jas.root.Rectangle"; java_import "edu.jas.root.RootFactory"; =begin rdoc Create JAS RealAlgebraicNumber as ring element. =end def RealN(m,i,r=0) if m.is_a? RingElem m = m.elem; end if r.is_a? RingElem r = r.elem; end if i.is_a? Array il = BigRational.new(i[0]); ir = BigRational.new(i[1]); i = Interval.new(il,ir); end #puts "m.getClass() = " + m.getClass().getName().to_s; if m.getClass().getSimpleName() == "RealAlgebraicNumber" mf = RealAlgebraicRing.new(m.factory().algebraic.modul,i); else mf = RealAlgebraicRing.new(m,i); end if r == 0 rr = RealAlgebraicNumber.new(mf); else rr = RealAlgebraicNumber.new(mf,r); end return RingElem.new(rr); end java_import "edu.jas.ufd.Quotient"; java_import "edu.jas.ufd.QuotientRing"; java_import "edu.jas.gbmod.SolvableQuotient"; java_import "edu.jas.gbmod.SolvableQuotientRing"; =begin rdoc Create JAS rational function Quotient as ring element. =end def RF(pr,d=0,n=1) if d.is_a? Array if n != 1 puts "#{} ignored\n"; end if d.size > 1 n = d[1]; end d = d[0]; end if d.is_a? RingElem d = d.elem; end if n.is_a? RingElem n = n.elem; end if pr.is_a? RingElem pr = pr.elem; end if pr.is_a? Ring pr = pr.ring; end qr = QuotientRing.new(pr); if d == 0 r = Quotient.new(qr); else if n == 1 r = Quotient.new(qr,d); else r = Quotient.new(qr,d,n); end end return RingElem.new(r); end =begin rdoc Create JAS rational function SolvableQuotient as ring element. =end def SRF(pr,d=0,n=1) if d.is_a? Array if n != 1 puts "#{} ignored\n"; end if d.size > 1 n = d[1]; end d = d[0]; end if d.is_a? RingElem d = d.elem; end if n.is_a? RingElem n = n.elem; end if pr.is_a? RingElem pr = pr.elem; end if pr.is_a? Ring pr = pr.ring; end qr = SolvableQuotientRing.new(pr); if d == 0 r = SolvableQuotient.new(qr); else if n == 1 r = SolvableQuotient.new(qr,d); else r = SolvableQuotient.new(qr,d,n); end end return RingElem.new(r); end java_import "edu.jas.application.PolyUtilApp"; java_import "edu.jas.application.Residue"; java_import "edu.jas.application.ResidueRing"; java_import "edu.jas.application.Ideal"; java_import "edu.jas.application.SolvableResidue"; java_import "edu.jas.application.SolvableResidueRing"; java_import "edu.jas.application.SolvableIdeal"; java_import "edu.jas.application.Local"; java_import "edu.jas.application.LocalRing"; java_import "edu.jas.application.IdealWithRealAlgebraicRoots"; java_import "edu.jas.application.ComprehensiveGroebnerBaseSeq"; =begin rdoc Create JAS polynomial Residue as ring element. =end def RC(ideal,r=0) if ideal == nil raise ValueError, "No ideal given." end if ideal.is_a? SimIdeal #puts "ideal.pset = " + str(ideal.pset) + "\n"; #ideal = Java::EduJasApplication::Ideal.new(ideal.ring,ideal.list); ideal = Ideal.new(ideal.pset); #ideal.doGB(); end #puts "ideal.getList().get(0).ring.ideal = #{ideal.getList().get(0).ring.ideal}\n"; if ideal.getList().get(0).ring.getClass().getSimpleName() == "ResidueRing" rc = ResidueRing.new( ideal.getList().get(0).ring.ideal ); else rc = ResidueRing.new(ideal); end if r.is_a? RingElem r = r.elem; end if r == 0 r = Residue.new(rc); else r = Residue.new(rc,r); end return RingElem.new(r); end =begin rdoc Create JAS polynomial Local as ring element. =end def LC(ideal,d=0,n=1) if ideal == nil raise ValueError, "No ideal given." end if ideal.is_a? SimIdeal ideal = Ideal.new(ideal.pset); #ideal.doGB(); end #puts "ideal.getList().get(0).ring.ideal = #{ideal.getList().get(0).ring.ideal}\n"; if ideal.getList().get(0).ring.getClass().getSimpleName() == "LocalRing" lc = LocalRing.new( ideal.getList().get(0).ring.ideal ); else lc = LocalRing.new(ideal); end if d.is_a? Array if n != 1 puts "#{n} ignored\n"; end if d.size > 1 n = d[1]; end d = d[0]; end if d.is_a? RingElem d = d.elem; end if n.is_a? RingElem n = n.elem; end if d == 0 r = Local.new(lc); else if n == 1 r = Local.new(lc,d); else r = Local.new(lc,d,n); end end return RingElem.new(r); end =begin rdoc Create JAS polynomial SolvableResidue as ring element. =end def SRC(ideal,r=0) if ideal == nil raise ValueError, "No ideal given." end if ideal.is_a? SolvIdeal #puts "ideal.pset = " + str(ideal.pset) + "\n"; #ideal = Java::EduJasApplication::Ideal.new(ideal.ring,ideal.list); ideal = SolvableIdeal.new(ideal.pset); #ideal.doGB(); end #puts "ideal.getList().get(0).ring.ideal = #{ideal.getList().get(0).ring.ideal}\n"; if ideal.getList().get(0).ring.getClass().getSimpleName() == "SolvableResidueRing" rc = SolvableResidueRing.new( ideal.getList().get(0).ring.ideal ); else rc = SolvableResidueRing.new(ideal); end if r.is_a? RingElem r = r.elem; end if r == 0 r = SolvableResidue.new(rc); else r = SolvableResidue.new(rc,r); end return RingElem.new(r); end =begin rdoc Create JAS regular ring Product as ring element. =end def RR(flist,n=1,r=0) if not n.is_a? Integer r = n; n = 1; end if flist == nil raise ValueError, "No list given." end if flist.is_a? Array flist = rbarray2arraylist( flist.map { |x| x.factory() }, rec=1); ncop = 0; else ncop = n; end if flist.is_a? RingElem flist = flist.elem; flist = flist.factory(); ncop = n; end #puts "flist = " + str(flist); #puts "ncop = " + str(ncop); if ncop == 0 pr = ProductRing.new(flist); else pr = ProductRing.new(flist,ncop); end #puts "r type(#{r}) = #{r.class}\n"; if r.is_a? RingElem r = r.elem; end begin #puts "r.class() = #{r.class}\n"; if r.getClass().getSimpleName() == "Product" #puts "r.val = #{r.val}\n"; r = r.val; end rescue #pass; end #puts "r = " + r.to_s; if r == 0 r = Product.new(pr); else r = Product.new(pr,r); end return RingElem.new(r); end =begin rdoc Convert a Ruby array to a Java ArrayList. If list is a Ruby array, it is converted, else list is left unchanged. =end def rbarray2arraylist(list,fac=nil,rec=1) #puts "list type(#{list}) = #{list.class}\n"; if list.is_a? Array ll = ArrayList.new(); for e in list t = true; if e.is_a? RingElem t = false; e = e.elem; end if e.is_a? Array if rec <= 1 e = makeJasArith(e); else t = false; e = rbarray2arraylist(e,fac,rec-1); end end begin n = e.getClass().getSimpleName(); if n == "ArrayList" t = false; end rescue #pass; end if t and fac != nil #puts "e.p(#{e}) = #{e.class}\n"; e = fac.parse( str(e) ); #or makeJasArith(e) ? end ll.add(e); end list = ll; end #puts "list type(#{list}) = #{list.class}\n"; return list end =begin rdoc Construct a jas.arith object. If item is an ruby array then a BigComplex is constructed. If item is a ruby float then a BigDecimal is constructed. =end def makeJasArith(item) #puts "item type(#{item}) = #{item.class}\n"; if item.is_a? Integer return BigInteger.new( item ); end if item.is_a? Rational return BigRational.new( item.numerator ).divide( BigRational.new( item.denominator ) ); end if item.is_a? Float # ?? what to do ?? return BigDecimal.new( item.to_s ); end if item.is_a? Array if item.size > 2 puts "len(item) > 2, remaining items ignored\n"; end puts "item[0] type(#{item[0]}) = #{item[0].class}\n"; if item.size > 1 re = makeJasArith( item[0] ); if not re.isField() re = BigRational.new( re.val ); end im = makeJasArith( item[1] ); if not im.isField() im = BigRational.new( im.val ); end jasArith = BigComplex.new( re, im ); else re = makeJasArith( item[0] ); if not re.isField() re = BigRational.new( re.val ); end jasArith = BigComplex.new( re ); end return jasArith; end puts "unknown item type(#{item}) = #{item.class}\n"; return item; end java_import "edu.jas.gb.DGroebnerBaseSeq"; java_import "edu.jas.gb.EGroebnerBaseSeq"; java_import "edu.jas.gb.EReductionSeq"; java_import "edu.jas.gb.GroebnerBaseDistributedEC"; java_import "edu.jas.gb.GroebnerBaseDistributedHybridEC"; #java_import "edu.jas.gb.GBDist"; java_import "edu.jas.gb.GroebnerBaseParallel"; java_import "edu.jas.gb.GroebnerBaseSeq"; java_import "edu.jas.gb.GroebnerBaseSeqPairSeq"; java_import "edu.jas.gb.ReductionSeq"; java_import "edu.jas.gb.OrderedPairlist"; java_import "edu.jas.gb.OrderedSyzPairlist"; java_import "edu.jas.gb.GroebnerBaseSeqPairParallel"; java_import "edu.jas.gb.SolvableGroebnerBaseParallel"; java_import "edu.jas.gb.SolvableGroebnerBaseSeq"; java_import "edu.jas.gb.SolvableReductionSeq"; java_import "edu.jas.gb.WordGroebnerBaseSeq"; java_import "edu.jas.gbufd.GroebnerBasePseudoRecSeq"; java_import "edu.jas.gbufd.GroebnerBasePseudoSeq"; java_import "edu.jas.gbufd.RGroebnerBasePseudoSeq"; java_import "edu.jas.gbufd.GroebnerBasePseudoParallel"; java_import "edu.jas.gbufd.RGroebnerBaseSeq"; java_import "edu.jas.gbufd.RReductionSeq"; java_import "edu.jas.gbufd.CharacteristicSetWu"; java_import "edu.jas.ufd.GreatestCommonDivisor"; java_import "edu.jas.ufd.PolyUfdUtil"; java_import "edu.jas.ufd.GCDFactory"; java_import "edu.jas.ufd.FactorFactory"; java_import "edu.jas.ufd.SquarefreeFactory"; java_import "edu.jas.integrate.ElementaryIntegration"; =begin rdoc Represents a JAS polynomial ideal: PolynomialList and Ideal. Methods for Groebner bases, ideal sum, intersection and others. =end class SimIdeal attr_reader :pset, :ring, :list, :roots, :prime, :primary =begin rdoc SimIdeal constructor. =end def initialize(ring,polystr="",list=nil) @ring = ring; if list == nil sr = StringReader.new( polystr ); tok = GenPolynomialTokenizer.new(ring::ring,sr); @list = tok.nextPolynomialList(); else @list = rbarray2arraylist(list,rec=1); end @pset = OrderedPolynomialList.new(@ring.ring,@list); @roots = nil; @croots = nil; @prime = nil; @primary = nil; #super(@ring::ring,@list) # non-sense, JRuby extends edu.jas.application.Ideal without beeing told end =begin rdoc Create a string representation. =end def to_s() return @pset.toScript(); end =begin rdoc Compare two ideals. =end def <=>(other) s,o = self, other return s.pset.compareTo( o.pset ); end =begin rdoc Compare two ideals. =end def ===(other) return (self <=> other) == 0; end =begin rdoc Create an ideal in a polynomial ring with parameter coefficients. =end def paramideal() return ParamIdeal.new(@ring,"",@list); end =begin rdoc Compute a Groebner base. =end def GB() s = @pset; cofac = s.ring.coFac; ff = s.list; t = System.currentTimeMillis(); if cofac.isField() #gg = GroebnerBaseSeq.new().GB(ff); #gg = GroebnerBaseSeq.new(ReductionSeq.new(),OrderedPairlist.new()).GB(ff); gg = GroebnerBaseSeq.new(ReductionSeq.new(),OrderedSyzPairlist.new()).GB(ff); else v = nil; begin v = cofac.vars; rescue #pass end if v == nil gg = GroebnerBasePseudoSeq.new(cofac).GB(ff); else gg = GroebnerBasePseudoRecSeq.new(cofac).GB(ff); end end t = System.currentTimeMillis() - t; puts "sequential GB executed in #{t} ms\n"; return SimIdeal.new(@ring,"",gg); end =begin rdoc Test if this is a Groebner base. =end def isGB() s = @pset; cofac = s.ring.coFac; ff = s.list; t = System.currentTimeMillis(); if cofac.isField() b = GroebnerBaseSeq.new().isGB(ff); else v = nil; begin v = cofac.vars; rescue #pass end if v == nil b = GroebnerBasePseudoSeq.new(cofac).isGB(ff); else b = GroebnerBasePseudoRecSeq.new(cofac).isGB(ff); end end t = System.currentTimeMillis() - t; puts "isGB executed in #{t} ms\n"; return b; end =begin rdoc Compute an e-Groebner base. =end def eGB() s = @pset; cofac = s.ring.coFac; ff = s.list; t = System.currentTimeMillis(); if cofac.isField() gg = GroebnerBaseSeq.new().GB(ff); else gg = EGroebnerBaseSeq.new().GB(ff) end t = System.currentTimeMillis() - t; puts "sequential e-GB executed in #{t} ms\n"; return SimIdeal.new(@ring,"",gg); end =begin rdoc Test if this is an e-Groebner base. =end def iseGB() s = @pset; cofac = s.ring.coFac; ff = s.list; t = System.currentTimeMillis(); if cofac.isField() b = GroebnerBaseSeq.new().isGB(ff); else b = EGroebnerBaseSeq.new().isGB(ff) end t = System.currentTimeMillis() - t; puts "is e-GB test executed in #{t} ms\n"; return b; end =begin rdoc Compute an d-Groebner base. =end def dGB() s = @pset; cofac = s.ring.coFac; ff = s.list; t = System.currentTimeMillis(); if cofac.isField() gg = GroebnerBaseSeq.new().GB(ff); else gg = DGroebnerBaseSeq.new().GB(ff) end t = System.currentTimeMillis() - t; puts "sequential d-GB executed in #{t} ms\n"; return SimIdeal.new(@ring,"",gg); end =begin rdoc Test if this is a d-Groebner base. =end def isdGB() s = @pset; cofac = s.ring.coFac; ff = s.list; t = System.currentTimeMillis(); if cofac.isField() b = GroebnerBaseSeq.new().isGB(ff); else b = DGroebnerBaseSeq.new().isGB(ff) end t = System.currentTimeMillis() - t; puts "is d-GB test executed in #{t} ms\n"; return b; end =begin rdoc Compute in parallel a Groebner base. =end def parUnusedGB(th) s = @pset; ff = s.list; bbpar = GroebnerBaseSeqPairParallel.new(th); t = System.currentTimeMillis(); gg = bbpar.GB(ff); t = System.currentTimeMillis() - t; bbpar.terminate(); puts "parallel-old #{th} executed in #{t} ms\n"; return SimIdeal.new(@ring,"",gg); end =begin rdoc Compute in parallel a Groebner base. =end def parGB(th) s = @pset; ff = s.list; cofac = s.ring.coFac; if cofac.isField() bbpar = GroebnerBaseParallel.new(th); else bbpar = GroebnerBasePseudoParallel.new(th,cofac); end t = System.currentTimeMillis(); gg = bbpar.GB(ff); t = System.currentTimeMillis() - t; bbpar.terminate(); puts "parallel #{th} executed in #{t} ms\n"; return SimIdeal.new(@ring,"",gg); end =begin rdoc Compute on a distributed system a Groebner base. =end def distGB(th=2,machine="examples/machines.localhost",port=55711) s = @pset; ff = s.list; t = System.currentTimeMillis(); # old: gbd = GBDist.new(th,machine,port); gbd = GroebnerBaseDistributedEC.new(machine,th,port); #gbd = GroebnerBaseDistributedHybridEC.new(machine,th,3,port); t1 = System.currentTimeMillis(); gg = gbd.GB(ff); t1 = System.currentTimeMillis() - t1; gbd.terminate(false); t = System.currentTimeMillis() - t; puts "distributed #{th} executed in #{t1} ms (#{t-t1} ms start-up)\n"; return SimIdeal.new(@ring,"",gg); end =begin rdoc Client for a distributed computation. =end def distClient(port=4711) s = @pset; e1 = ExecutableServer.new( port ); e1.init(); e2 = ExecutableServer.new( port+1 ); e2.init(); @exers = [e1,e2]; return nil; end =begin rdoc Client for a distributed computation. =end def distClientStop() for es in @exers; es.terminate(); end return nil; end =begin rdoc Compute a normal form of p with respect to this ideal. =end def reduction(p) s = @pset; gg = s.list; if p.is_a? RingElem p = p.elem; end #t = System.currentTimeMillis(); n = ReductionSeq.new().normalform(gg,p); #t = System.currentTimeMillis() - t; #puts "sequential reduction executed in " + str(t) + " ms"; return RingElem.new(n); end =begin rdoc Compute a e-normal form of p with respect to this ideal. =end def eReduction(p) s = @pset; gg = s.list; if p.is_a? RingElem p = p.elem; end t = System.currentTimeMillis(); n = EReductionSeq.new().normalform(gg,p); t = System.currentTimeMillis() - t; puts "sequential eReduction executed in " + str(t) + " ms"; return RingElem.new(n); end =begin rdoc Compute a normal form of this ideal with respect to reducer. =end def NF(reducer) s = @pset; ff = s.list; gg = reducer.list; t = System.currentTimeMillis(); nn = ReductionSeq.new().normalform(gg,ff); t = System.currentTimeMillis() - t; puts "sequential NF executed in #{t} ms\n"; return SimIdeal.new(@ring,"",nn); end =begin rdoc Compute the intersection of this and the given polynomial ring. =end def intersectRing(ring) s = Ideal.new(@pset); nn = s.intersect(ring.ring); return SimIdeal.new(ring,"",nn.getList()); end =begin rdoc Compute the intersection of this and the given ideal. =end def intersect(id2) s1 = Ideal.new(@pset); s2 = Ideal.new(id2.pset); nn = s1.intersect(s2); return SimIdeal.new(@ring,"",nn.getList()); end =begin rdoc Compute the elimination ideal of this and the given polynomial ring. =end def eliminateRing(ring) s = Ideal.new(@pset); nn = s.eliminate(ring.ring); r = Ring.new( "", nn.getRing() ); return SimIdeal.new(r,"",nn.getList()); end =begin rdoc Compute the saturation of this and the given ideal. =end def sat(id2) s1 = Ideal.new(@pset); s2 = Ideal.new(id2.pset); #nn = s1.infiniteQuotient(s2); nn = s1.infiniteQuotientRab(s2); mm = nn.getList(); #PolyUtil.monicRec(nn.getList()); return SimIdeal.new(@ring,"",mm); end =begin rdoc Compute the sum of this and the ideal. =end def sum(other) s = Ideal.new(@pset); t = Ideal.new(other.pset); nn = s.sum( t ); return SimIdeal.new(@ring,"",nn.getList()); end =begin rdoc Compute the univariate polynomials in each variable of this ideal. =end def univariates() s = Ideal.new(@pset); ll = s.constructUnivariate(); nn = ll.map {|e| RingElem.new(e) }; return nn; end =begin rdoc Compute the inverse polynomial modulo this ideal, if it exists. =end def inverse(p) if p.is_a? RingElem p = p.elem; end s = Ideal.new(@pset); i = s.inverse(p); return RingElem.new(i); end =begin rdoc Optimize the term order on the variables. =end def optimize() p = @pset; o = TermOrderOptimization.optimizeTermOrder(p); r = Ring.new("",o.ring); return SimIdeal.new(r,"",o.list); end =begin rdoc Compute real roots of 0-dim ideal. =end def realRoots() ii = Ideal.new(@pset); @roots = PolyUtilApp.realAlgebraicRoots(ii); for r in @roots r.doDecimalApproximation(); end return @roots; end =begin rdoc Print decimal approximation of real roots of 0-dim ideal. =end def realRootsPrint() if @roots == nil ii = Ideal.new(@pset); @roots = PolyUtilApp.realAlgebraicRoots(ii); for r in @roots r.doDecimalApproximation(); end end for ir in @roots for dr in ir.decimalApproximation() puts dr.to_s; end puts; end end =begin rdoc Compute radical decomposition of this ideal. =end def radicalDecomp() ii = Ideal.new(@pset); @radical = ii.radicalDecomposition(); return @radical; end =begin rdoc Compute irreducible decomposition of this ideal. =end def decomposition() ii = Ideal.new(@pset); @irrdec = ii.decomposition(); return @irrdec; end =begin rdoc Compute complex roots of 0-dim ideal. =end def complexRoots() ii = Ideal.new(@pset); @croots = PolyUtilApp.complexAlgebraicRoots(ii); for r in @croots r.doDecimalApproximation(); end return @croots; end =begin rdoc Print decimal approximation of complex roots of 0-dim ideal. =end def complexRootsPrint() if @croots == nil ii = Ideal.new(@pset); @croots = PolyUtilApp.complexAlgebraicRoots(ii); for r in @croots r.doDecimalApproximation(); end end for ic in @croots for dc in ic.decimalApproximation() puts dc.to_s; end puts; end end =begin rdoc Compute prime decomposition of this ideal. =end def primeDecomp() ii = Ideal.new(@pset); @prime = ii.primeDecomposition(); return @prime; end =begin rdoc Compute primary decomposition of this ideal. =end def primaryDecomp() ii = Ideal.new(@pset); ## if @prime == nil: ## @prime = I.primeDecomposition(); @primary = ii.primaryDecomposition(); return @primary; end =begin rdoc Convert rational coefficients to integer coefficients. =end def toInteger() p = @pset; l = p.list; r = p.ring; ri = GenPolynomialRing.new( BigInteger.new(), r.nvar, r.tord, r.vars ); pi = PolyUtil.integerFromRationalCoefficients(ri,l); r = Ring.new("",ri); return SimIdeal.new(r,"",pi); end =begin rdoc Convert integer coefficients to modular coefficients. =end def toModular(mf) p = @pset; l = p.list; r = p.ring; rm = GenPolynomialRing.new( mf, r.nvar, r.tord, r.vars ); pm = PolyUtil.fromIntegerCoefficients(rm,l); r = Ring.new("",rm); return SimIdeal.new(r,"",pm); end =begin rdoc Compute a Characteristic Set. =end def CS() s = @pset; cofac = s.ring.coFac; ff = s.list; t = System.currentTimeMillis(); if cofac.isField() gg = CharacteristicSetWu.new().characteristicSet(ff); else puts "CS not implemented for coefficients #{cofac.toScriptFactory()}\n"; gg = nil; end t = System.currentTimeMillis() - t; puts "sequential char set executed in #{t} ms\n"; return SimIdeal.new(@ring,"",gg); end =begin rdoc Test for Characteristic Set. =end def isCS() s = @pset; cofac = s.ring.coFac; ff = s.list.clone(); Collections.reverse(ff); # todo t = System.currentTimeMillis(); if cofac.isField() b = CharacteristicSetWu.new().isCharacteristicSet(ff); else puts "isCS not implemented for coefficients #{cofac.toScriptFactory()}\n"; b = false; end t = System.currentTimeMillis() - t; #puts "sequential is char set executed in #{t} ms\n"; return b; end =begin rdoc Compute a normal form of polynomial p with respect this characteristic set. =end def csReduction(p) s = @pset; ff = s.list.clone(); Collections.reverse(ff); # todo if p.is_a? RingElem p = p.elem; end t = System.currentTimeMillis(); nn = CharacteristicSetWu.new().characteristicSetReduction(ff,p); t = System.currentTimeMillis() - t; #puts "sequential char set reduction executed in #{t} ms\n"; return RingElem.new(nn); end ## =begin rdoc ## Syzygy of generating polynomials. ## =end ## def syzygy() ## p = @pset; ## l = p.list; ## s = SyzygyAbstract().zeroRelations( l ); ## m = Module("",p.ring); ## return SubModule(m,"",s); ## end end =begin rdoc Represents a JAS polynomial ideal with polynomial coefficients. Methods to compute comprehensive Groebner bases. =end class ParamIdeal =begin rdoc Parametric ideal constructor. =end def initialize(ring,polystr="",list=nil,gbsys=nil) @ring = ring; if list == nil and polystr != nil sr = StringReader.new( polystr ); tok = GenPolynomialTokenizer.new(ring.ring,sr); @list = tok.nextPolynomialList(); else @list = rbarray2arraylist(list,rec=1); end @gbsys = gbsys; @pset = OrderedPolynomialList.new(ring.ring,@list); end =begin rdoc Create a string representation. =end def to_s() if @gbsys == nil return @pset.toScript(); else # return @pset.toScript() + "\n" + @gbsys.toScript(); return @pset.toScript() + "\n" + @gbsys.to_s; end end =begin rdoc Optimize the term order on the variables of the coefficients. =end def optimizeCoeff() p = @pset; o = TermOrderOptimization.optimizeTermOrderOnCoefficients(p); r = Ring.new("",o.ring); return ParamIdeal.new(r,"",o.list); end =begin rdoc Optimize the term order on the variables of the quotient coefficients. =end def optimizeCoeffQuot() p = @pset; l = p.list; r = p.ring; q = r.coFac; c = q.ring; rc = GenPolynomialRing.new( c, r.nvar, r.tord, r.vars ); #puts "rc = ", rc; lp = PolyUfdUtil.integralFromQuotientCoefficients(rc,l); #puts "lp = ", lp; pp = PolynomialList.new(rc,lp); #puts "pp = ", pp; oq = TermOrderOptimization.optimizeTermOrderOnCoefficients(pp); oor = oq.ring; qo = oor.coFac; cq = QuotientRing.new( qo ); rq = GenPolynomialRing.new( cq, r.nvar, r.tord, r.vars ); #puts "rq = ", rq; o = PolyUfdUtil.quotientFromIntegralCoefficients(rq,oq.list); r = Ring.new("",rq); return ParamIdeal.new(r,"",o); end =begin rdoc Convert rational function coefficients to integral function coefficients. =end def toIntegralCoeff() p = @pset; l = p.list; r = p.ring; q = r.coFac; c = q.ring; rc = GenPolynomialRing.new( c, r.nvar, r.tord, r.vars ); #puts "rc = ", rc; lp = PolyUfdUtil.integralFromQuotientCoefficients(rc,l); #puts "lp = ", lp; r = Ring.new("",rc); return ParamIdeal.new(r,"",lp); end =begin rdoc Convert integral function coefficients to modular function coefficients. =end def toModularCoeff(mf) p = @pset; l = p.list; r = p.ring; c = r.coFac; #puts "c = ", c; cm = GenPolynomialRing.new( mf, c.nvar, c.tord, c.vars ); #puts "cm = ", cm; rm = GenPolynomialRing.new( cm, r.nvar, r.tord, r.vars ); #puts "rm = ", rm; pm = PolyUfdUtil.fromIntegerCoefficients(rm,l); r = Ring.new("",rm); return ParamIdeal.new(r,"",pm); end =begin rdoc Convert integral function coefficients to rational function coefficients. =end def toQuotientCoeff() p = @pset; l = p.list; r = p.ring; c = r.coFac; #puts "c = ", c; q = QuotientRing.new(c); #puts "q = ", q; qm = GenPolynomialRing.new( q, r.nvar, r.tord, r.vars ); #puts "qm = ", qm; pm = PolyUfdUtil.quotientFromIntegralCoefficients(qm,l); r = Ring.new("",qm); return ParamIdeal.new(r,"",pm); end =begin rdoc Compute a Groebner base. =end def GB() ii = SimIdeal.new(@ring,"",@pset.list); g = ii.GB(); return ParamIdeal.new(g.ring,"",g.pset.list); end =begin rdoc Test if this is a Groebner base. =end def isGB() ii = SimIdeal.new(@ring,"",@pset.list); return ii.isGB(); end =begin rdoc Compute a comprehensive Groebner base. =end def CGB() s = @pset; ff = s.list; t = System.currentTimeMillis(); if @gbsys == nil @gbsys = ComprehensiveGroebnerBaseSeq.new(@ring.ring.coFac).GBsys(ff); end gg = @gbsys.getCGB(); t = System.currentTimeMillis() - t; puts "sequential comprehensive executed in #{t} ms\n"; return ParamIdeal.new(@ring,"",gg,@gbsys); end =begin rdoc Compute a comprehensive Groebner system. =end def CGBsystem() s = @pset; ff = s.list; t = System.currentTimeMillis(); ss = ComprehensiveGroebnerBaseSeq.new(@ring.ring.coFac).GBsys(ff); t = System.currentTimeMillis() - t; puts "sequential comprehensive system executed in #{t} ms\n"; return ParamIdeal.new(@ring,nil,ff,ss); end =begin rdoc Test if this is a comprehensive Groebner base. =end def isCGB() s = @pset; ff = s.list; t = System.currentTimeMillis(); b = ComprehensiveGroebnerBaseSeq.new(@ring.ring.coFac).isGB(ff); t = System.currentTimeMillis() - t; puts "isCGB executed in #{t} ms\n"; return b; end =begin rdoc Test if this is a comprehensive Groebner system. =end def isCGBsystem() s = @pset; ss = @gbsys; t = System.currentTimeMillis(); b = ComprehensiveGroebnerBaseSeq.new(@ring.ring.coFac).isGBsys(ss); t = System.currentTimeMillis() - t; puts "isCGBsystem executed in #{t} ms\n"; return b; end =begin rdoc Convert Groebner system to a representation with regular ring coefficents. =end def regularRepresentation() if @gbsys == nil return nil; end gg = PolyUtilApp.toProductRes(@gbsys.list); ring = Ring.new(nil,gg[0].ring); return ParamIdeal.new(ring,nil,gg); end =begin rdoc Convert Groebner system to a boolean closed representation with regular ring coefficents. =end def regularRepresentationBC() if @gbsys == nil return nil; end gg = PolyUtilApp.toProductRes(@gbsys.list); ring = Ring.new(nil,gg[0].ring); res = RReductionSeq.new(); gg = res.booleanClosure(gg); return ParamIdeal.new(ring,nil,gg); end =begin rdoc Compute a Groebner base over a regular ring. =end def regularGB() s = @pset; ff = s.list; t = System.currentTimeMillis(); gg = RGroebnerBasePseudoSeq.new(@ring.ring.coFac).GB(ff); t = System.currentTimeMillis() - t; puts "sequential regular GB executed in #{t} ms\n"; return ParamIdeal.new(@ring,nil,gg); end =begin rdoc Test if this is Groebner base over a regular ring. =end def isRegularGB() s = @pset; ff = s.list; t = System.currentTimeMillis(); b = RGroebnerBasePseudoSeq.new(@ring.ring.coFac).isGB(ff); t = System.currentTimeMillis() - t; puts "isRegularGB executed in #{t} ms\n"; return b; end =begin rdoc Get each component (slice) of regular ring coefficients separate. =end def stringSlice() s = @pset; b = PolyUtilApp.productToString(s); return b; end end java_import "edu.jas.gbmod.ModGroebnerBaseAbstract"; java_import "edu.jas.gbmod.ModSolvableGroebnerBaseAbstract"; java_import "edu.jas.gbmod.SolvableSyzygyAbstract"; java_import "edu.jas.gbmod.SyzygyAbstract"; =begin rdoc Represents a JAS solvable polynomial ring: GenSolvablePolynomialRing. Has a method to create solvable ideals. =end class SolvableRing < Ring =begin rdoc Solvable polynomial ring constructor. =end def initialize(ringstr="",ring=nil) if ring == nil sr = StringReader.new( ringstr ); tok = GenPolynomialTokenizer.new(sr); @pset = tok.nextSolvablePolynomialSet(); @ring = @pset.ring; else @ring = ring; end if not @ring.isAssociative() puts "warning: ring is not associative"; end #puts "SolvableRing to super()"; super("",@ring) end =begin rdoc Create a string representation. =end def to_s() return @ring.toScript(); #.to_s; end =begin rdoc Create a solvable ideal. =end def ideal(ringstr="",list=nil) return SolvIdeal.new(self,ringstr,list); end =begin rdoc Get the one of the solvable polynomial ring. =end def one() return RingElem.new( @ring.getONE() ); end =begin rdoc Get the zero of the solvable polynomial ring. =end def zero() return RingElem.new( @ring.getZERO() ); end =begin rdoc Create an element from a string or object. =end def element(poly) if not poly.is_a? String begin if @ring == poly.ring return RingElem.new(poly); end rescue Exception => e # pass end poly = str(poly); end ii = SolvIdeal.new(self, "( " + poly + " )"); list = ii.pset.list; if list.size > 0 return RingElem.new( list[0] ); end end end =begin rdoc Represents a JAS solvable polynomial ring: GenSolvablePolynomialRing. Provides more convenient constructor. Then returns a Ring. =end class SolvPolyRing < SolvableRing @auto_inject = true class << self # means add to class attr_accessor :auto_inject end =begin rdoc Ring constructor. coeff = factory for coefficients, vars = string with variable names, order = term order, rel = triple list of relations. (e,f,p,...) with e * f = p as relation. =end def initialize(coeff,vars,order,rel=nil) if coeff == nil raise ValueError, "No coefficient given." end cf = coeff; if coeff.is_a? RingElem cf = coeff.elem.factory(); end if coeff.is_a? Ring cf = coeff.ring; end if vars == nil raise ValueError, "No variable names given." end names = vars; if vars.is_a? String names = GenPolynomialTokenizer.variableList(vars); end nv = names.size; to = PolyRing.lex; if order.is_a? TermOrder to = order; end ll = []; for x in rel if x.is_a? RingElem x = x.elem; end ll << x; end recSolv = false; (0..ll.size-1).step(3) { |i| if ll[i+1].isConstant() recSolv = true; end } recSolv = recSolv and cf.is_a? GenPolynomialRing if recSolv ring = RecSolvablePolynomialRing.new(cf,nv,to,names); table = ring.table; coeffTable = ring.coeffTable; else ring = GenSolvablePolynomialRing.new(cf,nv,to,names); table = ring.table; coeffTable = table; end if ll != [] #puts "ll = " + str(ll); (0..ll.size-1).step(3) { |i| #puts "type " + str(ll[i].class); if recSolv and ll[i+1].isConstant() coeffTable.update( ll[i], ll[i+1], ll[i+2] ); else table.update( ll[i], ll[i+1], ll[i+2] ); end } #puts "ring " + ring.toScript(); #puts "isAssoc " + str(ring.isAssociative()); end @ring = ring; #puts "SolvPolyRing to super()"; super("",@ring) # puts "ai = " + self.class.auto_inject.to_s if self.class.auto_inject inject_variables(); end end =begin rdoc Create a string representation. =end def to_s() return @ring.toScript(); end end =begin rdoc Represents a JAS solvable polynomial ideal. Methods for left, right two-sided Groebner basees and others. =end class SolvIdeal attr_reader :pset, :ring, :list =begin rdoc Constructor for an ideal in a solvable polynomial ring. =end def initialize(ring,ringstr="",list=nil) @ring = ring; if list == nil sr = StringReader.new( ringstr ); tok = GenPolynomialTokenizer.new(ring.ring,sr); @list = tok.nextSolvablePolynomialList(); else @list = rbarray2arraylist(list,rec=1); end @pset = PolynomialList.new(ring.ring,@list); end =begin rdoc Create a string representation. =end def to_s() return @pset.toScript(); end =begin rdoc Compute a left Groebner base. =end def leftGB() s = @pset; ff = s.list; t = System.currentTimeMillis(); gg = SolvableGroebnerBaseSeq.new().leftGB(ff); t = System.currentTimeMillis() - t; puts "executed leftGB in #{t} ms\n"; return SolvIdeal.new(@ring,"",gg); end =begin rdoc Test if this is a left Groebner base. =end def isLeftGB() s = @pset; ff = s.list; t = System.currentTimeMillis(); b = SolvableGroebnerBaseSeq.new().isLeftGB(ff); t = System.currentTimeMillis() - t; puts "isLeftGB executed in #{t} ms\n"; return b; end =begin rdoc Compute a two-sided Groebner base. =end def twosidedGB() s = @pset; ff = s.list; t = System.currentTimeMillis(); gg = SolvableGroebnerBaseSeq.new().twosidedGB(ff); t = System.currentTimeMillis() - t; puts "executed twosidedGB in #{t} ms\n"; return SolvIdeal.new(@ring,"",gg); end =begin rdoc Test if this is a two-sided Groebner base. =end def isTwosidedGB() s = @pset; ff = s.list; t = System.currentTimeMillis(); b = SolvableGroebnerBaseSeq.new().isTwosidedGB(ff); t = System.currentTimeMillis() - t; puts "isTwosidedGB executed in #{t} ms\n"; return b; end =begin rdoc Compute a right Groebner base. =end def rightGB() s = @pset; ff = s.list; t = System.currentTimeMillis(); gg = SolvableGroebnerBaseSeq.new().rightGB(ff); t = System.currentTimeMillis() - t; puts "executed rightGB in #{t} ms\n"; return SolvIdeal.new(@ring,"",gg); end =begin rdoc Test if this is a right Groebner base. =end def isRightGB() s = @pset; ff = s.list; t = System.currentTimeMillis(); b = SolvableGroebnerBaseSeq.new().isRightGB(ff); t = System.currentTimeMillis() - t; puts "isRightGB executed in #{t} ms\n"; return b; end =begin rdoc Compute the intersection of this and a polynomial ring. =end def intersectRing(ring) s = SolvableIdeal.new(@pset); nn = s.intersect(ring.ring); return SolvIdeal.new(@ring,"",nn.getList()); end =begin rdoc Compute the intersection of this and the other ideal. =end def intersect(other) s = SolvableIdeal.new(@pset); t = SolvableIdeal.new(other.pset); nn = s.intersect( t ); return SolvIdeal.new(@ring,"",nn.getList()); end =begin rdoc Compute the sum of this and the other ideal. =end def sum(other) s = SolvableIdeal.new(@pset); t = SolvableIdeal.new(other.pset); nn = s.sum( t ); return SolvIdeal.new(@ring,"",nn.getList()); end =begin rdoc Compute the univariate polynomials in each variable of this twosided ideal. =end def univariates() s = SolvableIdeal.new(@pset); ll = s.constructUnivariate(); nn = ll.map {|e| RingElem.new(e) }; return nn; end =begin rdoc Compute the inverse polynomial with respect to this twosided ideal. =end def inverse(p) if p.is_a? RingElem p = p.elem; end s = SolvableIdeal.new(@pset); i = s.inverse(p); return RingElem.new(i); end =begin rdoc Compute a left normal form of p with respect to this ideal. =end def leftReduction(p) s = @pset; gg = s.list; if p.is_a? RingElem p = p.elem; end n = SolvableReductionSeq.new().leftNormalform(gg,p); return RingElem.new(n); end =begin rdoc Compute a right normal form of p with respect to this ideal. =end def rightReduction(p) s = @pset; gg = s.list; if p.is_a? RingElem p = p.elem; end n = SolvableReductionSeq.new().rightNormalform(gg,p); return RingElem.new(n); end =begin rdoc Compute a left Groebner base in parallel. =end def parLeftGB(th) s = @pset; ff = s.list; bbpar = SolvableGroebnerBaseParallel.new(th); t = System.currentTimeMillis(); gg = bbpar.leftGB(ff); t = System.currentTimeMillis() - t; bbpar.terminate(); puts "parallel #{th} leftGB executed in #{t} ms\n"; return SolvIdeal.new(@ring,"",gg); end =begin rdoc Compute a two-sided Groebner base in parallel. =end def parTwosidedGB(th) s = @pset; ff = s.list; bbpar = SolvableGroebnerBaseParallel.new(th); t = System.currentTimeMillis(); gg = bbpar.twosidedGB(ff); t = System.currentTimeMillis() - t; bbpar.terminate(); puts "parallel #{th} twosidedGB executed in #{t} ms\n"; return SolvIdeal.new(@ring,"",gg); end end =begin rdoc Represents a JAS module over a polynomial ring. Method to create sub-modules. =end class CommutativeModule attr_reader :ring, :mset, :cols =begin rdoc Module constructor. =end def initialize(modstr="",ring=nil,cols=0) if ring == nil sr = StringReader.new( modstr ); tok = GenPolynomialTokenizer.new(sr); @mset = tok.nextSubModuleSet(); if @mset.cols >= 0 @cols = @mset.cols; else @cols = cols; end else @mset = ModuleList.new(ring.ring,nil); @cols = cols; end @ring = @mset.ring; end =begin rdoc Create a string representation. =end def to_s() return @mset.toScript(); end =begin rdoc Create a sub-module. =end def submodul(modstr="",list=nil) return SubModule.new(self,modstr,list); end =begin rdoc Create an element from a string. =end def element(mods) if not mods.is_a? String begin if @ring == mods.ring return RingElem.new(mods); end rescue Exception => e # pass end mods = str(mods); end ii = SubModule.new( "( " + mods + " )"); list = ii.mset.list; if list.size > 0 return RingElem.new( list[0] ); end end =begin rdoc Get the generators of this module. =end def gens() gm = GenVectorModul.new(@ring,@cols); ll = gm.generators(); nn = ll.map { |e| RingElem.new(e) }; # want use val here, but can not return nn; end end =begin rdoc Represents a JAS sub-module over a polynomial ring. Methods to compute Groebner bases. =end class SubModule attr_reader :modu, :mset, :pset, :cols, :rows, :list =begin rdoc Constructor for a sub-module. =end def initialize(modu,modstr="",list=nil) @modu = modu; if list == nil sr = StringReader.new( modstr ); tok = GenPolynomialTokenizer.new(modu.ring,sr); @list = tok.nextSubModuleList(); else if list.is_a? Array if list.size != 0 if list[0].is_a? RingElem list = list.map { |re| re.elem }; end end @list = rbarray2arraylist(list,@modu.ring,rec=2); else @list = list; end end #puts "list = ", str(list); #e = @list[0]; #puts "e = ", e; @mset = OrderedModuleList.new(modu.ring,@list); @cols = @mset.cols; @rows = @mset.rows; @pset = @mset.getPolynomialList(); end =begin rdoc Create a string representation. =end def to_s() return @mset.toScript(); # + "\n\n" + str(@pset); end =begin rdoc Compute a Groebner base. =end def GB() t = System.currentTimeMillis(); gg = ModGroebnerBaseAbstract.new().GB(@mset); t = System.currentTimeMillis() - t; puts "executed module GB in #{t} ms\n"; return SubModule.new(@modu,"",gg.list); end =begin rdoc Test if this is a Groebner base. =end def isGB() t = System.currentTimeMillis(); b = ModGroebnerBaseAbstract.new().isGB(@mset); t = System.currentTimeMillis() - t; puts "module isGB executed in #{t} ms\n"; return b; end ## =begin rdoc ## Test if this is a syzygy of the polynomials in g. ## =end ## def isSyzygy(g): ## l = @list; ## puts "l = #{l}"; ## puts "g = #{g}"; ## t = System.currentTimeMillis(); ## z = SyzygyAbstract().isZeroRelation( l, g.list ); ## t = System.currentTimeMillis() - t; ## puts "executed isSyzygy in #{t} ms\n"; ## return z; ## end end =begin rdoc Represents a JAS module over a solvable polynomial ring. Method to create solvable sub-modules. =end class SolvableModule < CommutativeModule attr_reader :ring, :mset, :cols =begin rdoc Solvable module constructor. =end def initialize(modstr="",ring=nil,cols=0) if ring == nil sr = StringReader.new( modstr ); tok = GenPolynomialTokenizer.new(sr); @mset = tok.nextSolvableSubModuleSet(); if @mset.cols >= 0 @cols = @mset.cols; end else @mset = ModuleList.new(ring.ring,nil); @cols = cols; end @ring = @mset.ring; end =begin rdoc Create a string representation. =end def to_s() return @mset.toScript(); end =begin rdoc Create a solvable sub-module. =end def submodul(modstr="",list=nil) return SolvableSubModule.new(self,modstr,list); end =begin rdoc Create an element from a string. =end def element(mods) if not mods.is_a? String begin if @ring == mods.ring return RingElem.new(mods); end rescue Exception => e # pass end mods = str(mods); end ii = SolvableSubModule.new( "( " + mods + " )"); list = ii.mset.list; if list.size > 0 return RingElem.new( list[0] ); end end end =begin rdoc Represents a JAS sub-module over a solvable polynomial ring. Methods to compute left, right and two-sided Groebner bases. =end class SolvableSubModule attr_reader :modu, :mset, :cols, :rows, :list =begin rdoc Constructor for sub-module over a solvable polynomial ring. =end def initialize(modu,modstr="",list=nil) @modu = modu; if list == nil sr = StringReader.new( modstr ); tok = GenPolynomialTokenizer.new(modu.ring,sr); @list = tok.nextSolvableSubModuleList(); else if list.is_a? Array @list = rbarray2arraylist(list,@modu.ring,rec=2); else @list = list; end end @mset = OrderedModuleList.new(modu.ring,@list); @cols = @mset.cols; @rows = @mset.rows; end =begin rdoc Create a string representation. =end def to_s() return @mset.toScript(); # + "\n\n" + str(@pset); end =begin rdoc Compute a left Groebner base. =end def leftGB() t = System.currentTimeMillis(); gg = ModSolvableGroebnerBaseAbstract.new().leftGB(@mset); t = System.currentTimeMillis() - t; puts "executed left module GB in #{t} ms\n"; return SolvableSubModule.new(@modu,"",gg.list); end =begin rdoc Test if this is a left Groebner base. =end def isLeftGB() t = System.currentTimeMillis(); b = ModSolvableGroebnerBaseAbstract.new().isLeftGB(@mset); t = System.currentTimeMillis() - t; puts "module isLeftGB executed in #{t} ms\n"; return b; end =begin rdoc Compute a two-sided Groebner base. =end def twosidedGB() t = System.currentTimeMillis(); gg = ModSolvableGroebnerBaseAbstract.new().twosidedGB(@mset); t = System.currentTimeMillis() - t; puts "executed in #{t} ms\n"; return SolvableSubModule.new(@modu,"",gg.list); end =begin rdoc Test if this is a two-sided Groebner base. =end def isTwosidedGB() t = System.currentTimeMillis(); b = ModSolvableGroebnerBaseAbstract.new().isTwosidedGB(@mset); t = System.currentTimeMillis() - t; puts "module isTwosidedGB executed in #{t} ms\n"; return b; end =begin rdoc Compute a right Groebner base. =end def rightGB() t = System.currentTimeMillis(); gg = ModSolvableGroebnerBaseAbstract.new().rightGB(@mset); t = System.currentTimeMillis() - t; puts "executed module rightGB in #{t} ms\n"; return SolvableSubModule.new(@modu,"",gg.list); end =begin rdoc Test if this is a right Groebner base. =end def isRightGB() t = System.currentTimeMillis(); b = ModSolvableGroebnerBaseAbstract.new().isRightGB(@mset); t = System.currentTimeMillis() - t; puts "module isRightGB executed in #{t} ms\n"; return b; end end java_import "edu.jas.ps.UnivPowerSeries"; java_import "edu.jas.ps.UnivPowerSeriesRing"; java_import "edu.jas.ps.UnivPowerSeriesMap"; java_import "edu.jas.ps.Coefficients"; java_import "edu.jas.ps.MultiVarPowerSeries"; java_import "edu.jas.ps.MultiVarPowerSeriesRing"; java_import "edu.jas.ps.MultiVarPowerSeriesMap"; java_import "edu.jas.ps.MultiVarCoefficients"; java_import "edu.jas.ps.StandardBaseSeq"; =begin rdoc Represents a JAS power series ring: UnivPowerSeriesRing. Methods for univariate power series arithmetic. =end class SeriesRing attr_reader :ring =begin rdoc Ring constructor. =end def initialize(ringstr="",truncate=nil,ring=nil,cofac=nil,name="z") if ring == nil if ringstr.size > 0 sr = StringReader.new( ringstr ); tok = GenPolynomialTokenizer.new(sr); pset = tok.nextPolynomialSet(); ring = pset.ring; vname = ring.vars; name = vname[0]; cofac = ring.coFac; end if cofac.is_a? RingElem cofac = cofac.elem; end if truncate == nil @ring = UnivPowerSeriesRing.new(cofac,name); else @ring = UnivPowerSeriesRing.new(cofac,truncate,name); end else @ring = ring; end end =begin rdoc Create a string representation. =end def to_s() return @ring.toScript(); end =begin rdoc Get the generators of the power series ring. =end def gens() ll = @ring.generators(); nn = ll.map { |e| RingElem.new(e) }; return nn; end =begin rdoc Get the one of the power series ring. =end def one() return RingElem.new( @ring.getONE() ); end =begin rdoc Get the zero of the power series ring. =end def zero() return RingElem.new( @ring.getZERO() ); end =begin rdoc Get a random power series. =end def random(n) return RingElem.new( @ring.random(n) ); end =begin rdoc Get the exponential power series. =end def exp() return RingElem.new( @ring.getEXP() ); end =begin rdoc Get the sinus power series. =end def sin() return RingElem.new( @ring.getSIN() ); end =begin rdoc Get the cosinus power series. =end def cos() return RingElem.new( @ring.getCOS() ); end =begin rdoc Get the tangens power series. =end def tan() return RingElem.new( @ring.getTAN() ); end =begin rdoc (Inner) class which extends edu.jas.ps.Coefficients ifunc(int i) must return a value which is used in ((RingFactory)cofac).fromInteger(). jfunc(int i) must return a value of type ring.coFac. =end class Ucoeff < Coefficients def initialize(ifunc,jfunc,cofac=nil) #puts "ifunc = " + ifunc.to_s + ","; #puts "jfunc = " + jfunc.to_s + ","; #puts "cofac = " + cofac.to_s + ","; super(); if jfunc == nil && cofac == nil raise "invalid arguments" end @coFac = cofac; @ifunc = ifunc; @jfunc = jfunc; end def generate(i) if @jfunc == nil return @coFac.fromInteger( @ifunc.call(i) ); else return @jfunc.call(i); end end end =begin rdoc Create a power series with given generating function. ifunc(int i) must return a value which is used in RingFactory.fromInteger(). jfunc(int i) must return a value of type ring.coFac. clazz must implement the Coefficients abstract class. =end def create(ifunc,jfunc=nil,clazz=nil) if clazz == nil #puts "ifunc = " + ifunc.to_s + "."; #puts "jfunc = " + jfunc.to_s + "."; #puts "clazz = " + clazz.to_s + "."; cf = Ucoeff.new(ifunc,jfunc,@ring.coFac); #puts "cf = " + cf.to_s + "."; ps = UnivPowerSeries.new( @ring, cf ); else ps = UnivPowerSeries.new( @ring, clazz ); end return RingElem.new( ps ); end =begin rdoc Create a power series as fixed point of the given mapping. psmap must implement the UnivPowerSeriesMap interface. =end def fixPoint(psmap) ps = @ring.fixPoint( psmap ); return RingElem.new( ps ); end =begin rdoc Compute the greatest common divisor of a and b. =end def gcd(a,b) if a.is_a? RingElem a = a.elem; end if b.is_a? RingElem b = b.elem; end return RingElem.new( a.gcd(b) ); end =begin rdoc Convert a GenPolynomial to a power series. =end def fromPoly(a) if a.is_a? RingElem a = a.elem; end return RingElem.new( @ring.fromPolynomial(a) ); end end =begin rdoc Represents a JAS power series ring: MultiVarPowerSeriesRing. Methods for multivariate power series arithmetic. =end class MultiSeriesRing attr_reader :ring =begin rdoc Ring constructor. =end def initialize(ringstr="",truncate=nil,ring=nil,cofac=nil,names=nil) if ring == nil if ringstr.size > 0 sr = StringReader.new( ringstr ); tok = GenPolynomialTokenizer.new(sr); pset = tok.nextPolynomialSet(); ring = pset.ring; names = ring.vars; cofac = ring.coFac; end if cofac.is_a? RingElem cofac = cofac.elem; end if truncate == nil @ring = MultiVarPowerSeriesRing.new(cofac,names); else @ring = MultiVarPowerSeriesRing.new(cofac,names.size,truncate,names); end else @ring = ring; end end =begin rdoc Create a string representation. =end def to_s() return @ring.toScript(); end =begin rdoc Get the generators of the power series ring. =end def gens() ll = @ring.generators(); nn = ll.map { |e| RingElem.new(e) }; return nn; end =begin rdoc Get the one of the power series ring. =end def one() return RingElem.new( @ring.getONE() ); end =begin rdoc Get the zero of the power series ring. =end def zero() return RingElem.new( @ring.getZERO() ); end =begin rdoc Get a random power series. =end def random(n) return RingElem.new( @ring.random(n) ); end =begin rdoc Get the exponential power series, var r. =end def exp(r) return RingElem.new( @ring.getEXP(r) ); end =begin rdoc Get the sinus power series, var r. =end def sin(r) return RingElem.new( @ring.getSIN(r) ); end =begin rdoc Get the cosinus power series, var r. =end def cos(r) return RingElem.new( @ring.getCOS(r) ); end =begin rdoc Get the tangens power series, var r. =end def tan(r) return RingElem.new( @ring.getTAN(r) ); end =begin (Inner) class which extends edu.jas.ps.MultiVarCoefficients ring must be a polynomial or multivariate power series ring. ifunc(ExpVector i) must return a value which is used in ((RingFactory)cofac).fromInteger(). jfunc(ExpVector i) must return a value of type ring.coFac. =end class Mcoeff < MultiVarCoefficients def initialize(ring,ifunc=nil,jfunc=nil) super(ring); @coFac = ring.coFac; @ifunc = ifunc; @jfunc = jfunc; end def generate(i) if @jfunc == nil return @coFac.fromInteger( @ifunc.call(i) ); else return @jfunc.call(i); end end end =begin rdoc Create a power series with given generating function. ifunc(ExpVector i) must return a value which is used in RingFactory.fromInteger(). jfunc(ExpVector i) must return a value of type ring.coFac. clazz must implement the MultiVarCoefficients abstract class. =end def create(ifunc=nil,jfunc=nil,clazz=nil) #puts "ifunc " #puts "jfunc " #puts "clazz " + str(clazz) if clazz == nil clazz = Mcoeff.new(@ring,ifunc,jfunc); end ps = MultiVarPowerSeries.new( @ring, clazz ); #puts "ps ", ps.toScript(); return RingElem.new( ps ); end =begin rdoc Create a power series as fixed point of the given mapping. psmap must implement the MultiVarPowerSeriesMap interface. =end def fixPoint(psmap) ps = @ring.fixPoint( psmap ); return RingElem.new( ps ); end =begin rdoc Compute the greatest common divisor of a and b. =end def gcd(a,b) if a.is_a? RingElem a = a.elem; end if b.is_a? RingElem b = b.elem; end return RingElem.new( a.gcd(b) ); end =begin rdoc Convert a GenPolynomial to a power series. =end def fromPoly(a) if a.is_a? RingElem a = a.elem; end return RingElem.new( @ring.fromPolynomial(a) ); end end =begin rdoc Represents a JAS power series ideal. Method for Standard bases. =end class PSIdeal attr_reader :ring, :list =begin rdoc PSIdeal constructor. =end def initialize(ring,polylist,ideal=nil,list=nil) if ring.is_a? Ring or ring.is_a? PolyRing ring = MultiVarPowerSeriesRing.new(ring.ring); elsif ring.is_a? MultiSeriesRing ring = ring.ring; end @ring = ring; #puts "ring = ", ring.toScript(); if ideal != nil polylist = ideal.pset.list; end if list == nil @polylist = rbarray2arraylist( polylist.map { |a| a.elem } ); #puts "polylist = ", @polylist; @list = @ring.fromPolynomial(@polylist); else @polylist = nil; @list = rbarray2arraylist( list.map { |a| a.elem } ); end end =begin rdoc Create a string representation. =end def to_s() return "( " + @list.map { |a| a.toScript() }.join(", ") + " )"; end =begin rdoc Compute a standard base. =end def STD(trunc=nil) pr = @ring; if trunc != nil pr.setTruncate(trunc); end #puts "pr = ", pr.toScript(); ff = @list; #puts "ff = ", ff; tm = StandardBaseSeq.new(); t = System.currentTimeMillis(); ss = tm.STD(ff); t = System.currentTimeMillis() - t; puts "sequential standard base executed in #{t} ms\n"; #Sp = [ RingElem.new(a.asPolynomial()) for a in S ]; sp = ss.map { |a| RingElem.new(a) }; #return sp; return PSIdeal.new(@ring,nil,nil,sp); end end class Coeff < Coefficients def initialize(cof,&f) super() # this is important in jruby 1.5.6! #puts "cof type(#{cof}) = #{cof.class}\n"; @coFac = cof; #puts "f type(#{f}) = #{f.class}\n"; @func = f end def generate(i) #puts "f_3 type(#{@func}) = #{@func.class}\n"; #puts "f_3 type(#{i}) = #{i.class}\n"; #return @coFac.getZERO() c = @func.call(i) #puts "f_3 type(#{c}) = #{c.class}\n"; if c.is_a? RingElem c = c.elem end return c end end =begin rdoc Create JAS UnivPowerSeries as ring element. =end def PS(cofac,name,truncate=nil,&f) #=nil,truncate=nil) cf = cofac; if cofac.is_a? RingElem cf = cofac.elem.factory(); end if cofac.is_a? Ring cf = cofac.ring; end if truncate.is_a? RingElem truncate = truncate.elem; end if truncate == nil ps = UnivPowerSeriesRing.new(cf,name); else ps = UnivPowerSeriesRing.new(cf,truncate,name); end #puts "ps type(#{ps}) = #{ps.class}\n"; #puts "f type(#{f}) = #{f.class}\n"; if f == nil r = ps.getZERO(); else #Bug in JRuby 1.5.6? move outside method r = UnivPowerSeries.new(ps,Coeff.new(cf,&f)); end return RingElem.new(r); end class MCoeff < MultiVarCoefficients def initialize(r,&f) super(r) # this is important in jruby 1.5.6! @coFac = r.coFac; @func = f end def generate(i) a = @func.call(i); if a.is_a? RingElem a = a.elem; end #puts "f_5 type(#{a}) = #{a.class}\n"; return a; end end =begin rdoc Create JAS MultiVarPowerSeries as ring element. =end def MPS(cofac,names,truncate=nil,&f) cf = cofac; if cofac.is_a? RingElem cf = cofac.elem.factory(); elsif cofac.is_a? Ring cf = cofac.ring; end vars = names; if vars.is_a? String vars = GenPolynomialTokenizer.variableList(vars); end nv = vars.size; if truncate.is_a? RingElem truncate = truncate.elem; end if truncate == nil ps = MultiVarPowerSeriesRing.new(cf,nv,vars); else ps = MultiVarPowerSeriesRing.new(cf,nv,vars,truncate); end if f == nil r = ps.getZERO(); else r = MultiVarPowerSeries.new(ps,MCoeff.new(ps,&f)); #puts "r = " + str(r); end return RingElem.new(r); end java_import "edu.jas.vector.GenVector"; java_import "edu.jas.vector.GenVectorModul"; java_import "edu.jas.vector.GenMatrix"; java_import "edu.jas.vector.GenMatrixRing"; =begin rdoc Create JAS GenVector ring element. =end def Vec(cofac,n,v=nil) cf = cofac; if cofac.is_a? RingElem cf = cofac.elem.factory(); elsif cofac.is_a? Ring cf = cofac.ring; end if n.is_a? RingElem n = n.elem; end if v.is_a? RingElem v = v.elem; end vr = GenVectorModul.new(cf,n); if v == nil r = GenVector.new(vr); else r = GenVector.new(vr,v); end return RingElem.new(r); end =begin rdoc Create JAS GenMatrix ring element. =end def Mat(cofac,n,m,v=nil) cf = cofac; if cofac.is_a? RingElem cf = cofac.elem.factory(); elsif cofac.is_a? Ring cf = cofac.ring; end if n.is_a? RingElem n = n.elem; end if m.is_a? RingElem m = m.elem; end if v.is_a? RingElem v = v.elem; end #puts "cf type(#{cf}) = #{cf.class}"; if v.is_a? Array v = rbarray2arraylist(v,cf,rec=2); end mr = GenMatrixRing.new(cf,n,m); if v == nil r = GenMatrix.new(mr); else r = GenMatrix.new(mr,v); end return RingElem.new(r); end java_import "edu.jas.application.ExtensionFieldBuilder"; =begin rdoc Extension field builder. Construction of extension field towers according to then builder pattern. =end class EF attr_reader :builder =begin rdoc Constructor to set base field. =end def initialize(base) if base.is_a? RingElem #factory = base.elem; factory = base.ring; else factory = base; end begin factory = factory.factory(); rescue #pass end puts "extension field factory: " + factory.toScript(); # + " :: " + factory.toString(); if factory.is_a? ExtensionFieldBuilder @builder = factory; else @builder = ExtensionFieldBuilder.new(factory); end end =begin rdoc Create a string representation. =end def to_s() return @builder.toScript(); #return @builder.toString(); end =begin rdoc Create an extension field. If algebraic is given as string expression, then an algebraic extension field is constructed, else a transcendental extension field is constructed. =end def extend(vars,algebraic=nil) if algebraic == nil ef = @builder.transcendentExtension(vars); else ef = @builder.algebraicExtension(vars,algebraic); end return EF.new(ef.build()); end =begin rdoc Create a real extension field. Construct a real algebraic extension field with an isolating interval for a real root. =end def realExtend(vars,algebraic,interval) ef = @builder.realAlgebraicExtension(vars,algebraic,interval); return EF.new(ef.build()); end =begin rdoc Create a complex extension field. Construct a complex algebraic extension field with an isolating rectangle for a complex root. =end def complexExtend(vars,algebraic,rectangle) ef = @builder.complexAlgebraicExtension(vars,algebraic,rectangle); return EF.new(ef.build()); end =begin rdoc Create an polynomial ring extension. =end def polynomial(vars) ef = @builder.polynomialExtension(vars); return EF.new(ef.build()); end =begin rdoc Get extension field tower. =end def build() rf = @builder.build(); if rf.is_a? GenPolynomialRing return PolyRing.new(rf.coFac,rf.getVars(),rf.tord); else return RingElem.new(rf.getZERO()); end end end =begin rdoc Represents a JAS non-commutative polynomial ring: GenWordPolynomialRing. Has a method to create non-commutative ideals. Note: watch your step: check that jruby does not reorder multiplication. =end class WordRing < Ring =begin rdoc Word polynomial ring constructor. =end def initialize(ringstr="",ring=nil) if ring == nil raise "parse of word polynomial rings not implemented" sr = StringReader.new( ringstr ); tok = GenPolynomialTokenizer.new(sr); @pset = tok.nextWordPolynomialSet(); @ring = @pset.ring; else @ring = ring; end #if not @ring.isAssociative() # puts "warning: ring is not associative"; #end end =begin rdoc Create a string representation. =end def to_s() return @ring.toScript(); #.to_s; end =begin rdoc Create a word ideal. =end def ideal(ringstr="",list=nil) return WordIdeal.new(self,ringstr,list); end =begin rdoc Get the one of the word polynomial ring. =end def one() return RingElem.new( @ring.getONE() ); end =begin rdoc Get the zero of the word polynomial ring. =end def zero() return RingElem.new( @ring.getZERO() ); end =begin rdoc Get a random word polynomial. =end def random(n=5) r = @ring.random(n); if @ring.coFac.isField() r = r.monic(); end return RingElem.new( r ); end =begin rdoc Get a random word polynomial. =end def random(k=5,l=7,d=3) r = @ring.random(k,l,d); if @ring.coFac.isField() r = r.monic(); end return RingElem.new( r ); end =begin rdoc Create an element from a string or object. =end def element(poly) if not poly.is_a? String begin if @ring == poly.ring return RingElem.new(poly); end rescue Exception => e # pass end poly = str(poly); end ii = WordIdeal.new(self, "( " + poly + " )"); list = ii.pset.list; if list.size > 0 return RingElem.new( list[0] ); end end end =begin rdoc Represents a JAS non-commutative polynomial ring: GenWordPolynomialRing. Provides more convenient constructor. Then returns a Ring. Note: watch your step: check that jruby does not reorder multiplication. =end class WordPolyRing < WordRing =begin rdoc Ring constructor. coeff = factory for coefficients, vars = string with variable names. =end def initialize(coeff,vars) if coeff == nil raise ValueError, "No coefficient given." end cf = coeff; if coeff.is_a? RingElem cf = coeff.elem.factory(); end if coeff.is_a? Ring cf = coeff.ring; end if vars == nil raise ValueError, "No variable names given." end names = vars; if vars.is_a? String names = GenPolynomialTokenizer.variableList(vars); end wf = WordFactory.new(names); ring = GenWordPolynomialRing.new(cf,wf); @ring = ring; end =begin rdoc Create a string representation. =end def to_s() return @ring.toScript(); end end =begin rdoc Represents a JAS non-commutative polynomial ideal. Methods for two-sided Groebner bases and others. Note: watch your step: check that jruby does not reorder multiplication. =end class WordIdeal attr_reader :ring, :list =begin rdoc Constructor for an ideal in a non-commutative polynomial ring. =end def initialize(ring,ringstr="",list=nil) @ring = ring; if list == nil raise "parse of non-commutative polynomials not implemented" sr = StringReader.new( ringstr ); tok = GenPolynomialTokenizer.new(ring.ring,sr); @list = tok.nextWordPolynomialList(); else @list = rbarray2arraylist(list,rec=1); end #@pset = OrderedPolynomialList.new(ring.ring,@list); end =begin rdoc Create a string representation. =end def to_s() return "( " + @list.map{ |e| e.toScript() }.join(", ") + " )"; end =begin rdoc Compute a two-sided Groebner base. =end def GB() return twosidedGB(); end =begin rdoc Compute a two-sided Groebner base. =end def twosidedGB() #s = @pset; ff = @list; t = System.currentTimeMillis(); gg = WordGroebnerBaseSeq.new().GB(ff); t = System.currentTimeMillis() - t; puts "executed twosidedGB in #{t} ms\n"; return WordIdeal.new(@ring,"",gg); end =begin rdoc Test if this is a two-sided Groebner base. =end def isGB() return isTwosidedGB(); end =begin rdoc Test if this is a two-sided Groebner base. =end def isTwosidedGB() #s = @pset; ff = @list; t = System.currentTimeMillis(); b = WordGroebnerBaseSeq.new().isGB(ff); t = System.currentTimeMillis() - t; puts "isTwosidedGB executed in #{t} ms\n"; return b; end end # define some shotcuts ZZ = ZZ(); QQ = QQ(); CC = CC(); CR = CR(); DD = DD(); #no GF = GF(); end include JAS