jas-2.5/0000755000175000017500000000000012140140260012331 5ustar giovannigiovannijas-2.5/jruby_tests.sh0000644000175000017500000001036711650345416015270 0ustar giovannigiovanni#!/bin/sh # run most rb files echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/all_rings.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/all_rings.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/trinks.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/trinks.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/0dim_primary-decomp.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/0dim_primary-decomp.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/0dim_prime-decomp.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/0dim_prime-decomp.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/0dim_radical.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/0dim_radical.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/cgb_0.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/cgb_0.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/cgb_2.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/cgb_2.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/cgb_3.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/cgb_3.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/cgbmmn15.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/cgbmmn15.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/chebyshev.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/chebyshev.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/e-gb.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/e-gb.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/eliminate.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/eliminate.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/factors.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/factors.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/factors_abs.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/factors_abs.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/factors_abs_complex.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/factors_abs_complex.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/factors_abs_mult.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/factors_abs_mult.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/factors_algeb.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/factors_algeb.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/getstart.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/getstart.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/hawes2.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/hawes2.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/module.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/module.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/polynomial.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/polynomial.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/polypower.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/polypower.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/powerseries.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/powerseries.rb echo jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/prime-decomp.rb time jruby -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/prime-decomp.rb jas-2.5/jython/0000755000175000017500000000000012140140252013645 5ustar giovannigiovannijas-2.5/jython/services/0000755000175000017500000000000012140140252015470 5ustar giovannigiovannijas-2.5/jython/services/javax.script.ScriptEngineFactory0000644000175000017500000000004311306743400023754 0ustar giovannigiovanniedu.jas.kern.PyScriptEngineFactory jas-2.5/jython/manifest.mf0000644000175000017500000000010611306744570016014 0ustar giovannigiovanniManifest-Version: 1.0 Created-By: 1.6.0_0 (Sun Microsystems Inc.) jas-2.5/jython/Makefile0000644000175000017500000000367412057226546015341 0ustar giovannigiovanni# # $Id: Makefile 4312 2012-12-03 22:53:26Z kredel $ # # Makefile for the interface of JAS to jython # by Raphael Jolly, Heinz kredel # #JASPATH=$(HOME)/jas JASPATH=.. LIBPATH=$(HOME)/java/lib JYTHONPATH=$(LIBPATH)/jython.jar JRUBYPATH=$(LIBPATH)/jruby.jar:$(HOME)/java/jruby-1.5.6/lib/ruby/1.8 CLASSPATH=$(LIBPATH)/log4j.jar:$(LIBPATH)/junit.jar:$(LIBPATH)/jas.jar BOOTCLASSPATH6="/usr/lib64/jvm/java-1.6.0/jre/lib/rt.jar" .SUFFIXES : .class .java .jar .PHONY : clean FILES=$(wildcard src/edu/jas/*/*.java) #echo $(FILES) $(JASPATH)/examples/jas.py CLASSES=$(subst src,classes,$(subst java,class,$(FILES))) #echo $(CLASSES) #DOCOPTS=-package DOCOPTS=-package -author -version -linksource DOCCLASSES=$(CLASSPATH) DOC=javadoc -classpath $(DOCCLASSES):$(JYTHONPATH) all: clean jas-jython.jar doc $(CLASSES): $(FILES) -mkdir classes javac -g -source 1.6 -target 1.6 -classpath $(JYTHONPATH):$(CLASSPATH) -bootclasspath $(BOOTCLASSPATH6) -sourcepath src -d classes src/edu/jas/*/*.java jas-jython.jar: $(CLASSES) $(JASPATH)/examples/jas.py services/javax.script.ScriptEngineFactory -mkdir classes/META-INF -mkdir classes/META-INF/services -cp -a manifest.mf classes/META-INF/MANIFEST.MF #cp -a services/javax.script.ScriptEngineFactory classes/META-INF/services/ -cp -a $(JASPATH)/examples/jas.py $(JASPATH)/examples/*.class $(JASPATH)/examples/basic_sigbased_gb.py classes -cp -a $(JASPATH)/examples/jas.pyc classes -cp -a $(JASPATH)/examples/jas.rb classes -cp -a $(JASPATH)/log4j.properties classes jar cfM jas-jython.jar -C classes . cp -f jas-jython.jar $(LIBPATH) cp -f jas-jython.jar .. clean: rm -rf classes find . -name "*~" -follow -print -exec rm {} \; tests: jas-jython.jar #java -client -cp $(JYTHONPATH):$(JRUBYPATH):$(CLASSPATH):jas-jython.jar edu.jas.kern.ScriptingExample java -client -cp $(JYTHONPATH):$(JRUBYPATH):$(CLASSPATH):jas-jython.jar edu.jas.gb.GBSigBasedTest doc: $(FILES) $(DOC) $(DOCOPTS) -d ../doc/jas-jython $(FILES) jas-2.5/jython/src/0000755000175000017500000000000012140140252014434 5ustar giovannigiovannijas-2.5/jython/src/edu/0000755000175000017500000000000012140140252015211 5ustar giovannigiovannijas-2.5/jython/src/edu/jas/0000755000175000017500000000000012140140252015766 5ustar giovannigiovannijas-2.5/jython/src/edu/jas/kern/0000755000175000017500000000000012140140252016725 5ustar giovannigiovannijas-2.5/jython/src/edu/jas/kern/PyScriptEngine.java0000644000175000017500000000320311306743400022500 0ustar giovannigiovanni/* * $Id: PyScriptEngine.java 2896 2009-12-06 15:00:16Z kredel $ */ package edu.jas.kern; import org.python.util.PythonInterpreter; import java.io.Reader; import java.io.StringReader; import java.io.StringWriter; import java.io.PrintWriter; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.script.AbstractScriptEngine; import javax.script.Bindings; import javax.script.SimpleBindings; import javax.script.ScriptContext; import javax.script.ScriptEngineFactory; public class PyScriptEngine extends AbstractScriptEngine /*implements Invocable, Compilable*/ { PythonInterpreter pyint = new PythonInterpreter(); public PyScriptEngine() { super(); //pyint.execfile(this.getClass().getResourceAsStream("/jas.py")); } public PyScriptEngine(Bindings b) { super(b); //pyint.execfile(this.getClass().getResourceAsStream("/jas.py")); } @Override public Object eval(Reader r, ScriptContext c) { throw new RuntimeException("eval(Reader r,..) not implemented"); } @Override public Object eval(String s, ScriptContext c) { //Obejct o = pyint.eval(s); //return pyint.eval(s).__str__().toString(); pyint.exec(s); return null; } @Override public ScriptEngineFactory getFactory() { return new PyScriptEngineFactory(); } @Override public Bindings createBindings() { return new SimpleBindings(); } @Override public String toString() { ScriptEngineFactory sf = getFactory(); return "PyScriptEngine(" + sf.getLanguageName() + ", " + sf.getLanguageVersion() + ")"; } } jas-2.5/jython/src/edu/jas/kern/PyScriptEngineFactory.java0000644000175000017500000000371311635361370024045 0ustar giovannigiovanni/* * $Id: PyScriptEngineFactory.java 3768 2011-09-18 12:24:24Z kredel $ */ package edu.jas.kern; import java.util.List; import java.util.ArrayList; import java.util.Collections; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.script.AbstractScriptEngine; import javax.script.ScriptEngineFactory; public class PyScriptEngineFactory implements ScriptEngineFactory { @Override public String getProgram(String... S) { StringBuffer sb = new StringBuffer(); for( String s : S ) { sb.append(s + "; "); } return sb.toString(); } @Override public ScriptEngine getScriptEngine() { return new PyScriptEngine(); } @Override public String getOutputStatement(String s) { return s; } @Override public String getMethodCallSyntax(String o, String m, String... S) { return o + "." + m + "(" + S + ")"; } @Override public Object getParameter(String s) { return s; } @Override public String getLanguageVersion() { return "1.0"; } @Override public String getLanguageName() { return "JAS jython"; } @Override public String getEngineVersion() { return "0.1"; } @Override public String getEngineName() { return "JAS_jython"; } @Override public List getNames() { List ls = new ArrayList(); ls.add("jython"); //System.out.println("getNames: " + ls); return Collections.unmodifiableList(ls); } @Override public List getMimeTypes() { List ls = new ArrayList(); //ls.add("x-application/python"); //System.out.println("getMimeTypes: " + ls); return Collections.unmodifiableList(ls); } @Override public List getExtensions() { List ls = new ArrayList(); //ls.add("py"); //System.out.println("getExtensions: " + ls); return Collections.unmodifiableList(ls); } } jas-2.5/jython/src/edu/jas/kern/ScriptingExample.java0000644000175000017500000000723512025335440023064 0ustar giovannigiovanni/* * $Id: ScriptingExample.java 4193 2012-09-16 11:42:24Z kredel $ */ package edu.jas.kern; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; public class ScriptingExample { public static void main(String[] args) { runJython(); //runJythonRegister(); runJruby(); } public static void runJythonRegister() { ScriptEngine jas = new ScriptEngineManager().getEngineByExtension("py"); System.out.println("JAS service discovered: " + jas); if ( jas == null ) { ScriptEngineManager scriptManager = new ScriptEngineManager(); scriptManager.registerEngineExtension("py", new PyScriptEngineFactory()); jas = scriptManager.getEngineByExtension("py"); } if ( jas == null ) { System.out.println("No JAS engine found"); return; } System.out.println("Using JAS engine: " + jas); try { long millis = System.currentTimeMillis(); //String ex = "x = 1; print(4*2*x)"; String ex = "from jas import PolyRing, ZZ; r = PolyRing(ZZ(),\"x,y,z\",PolyRing.lex); print str(r);" + "[one,x,y,z] = r.gens(); p = ((x*y)+z)**33; print \"p = \" + str(p)"; System.out.println("input: " + ex); Object ans = jas.eval(ex); millis = System.currentTimeMillis() - millis; System.out.println("answer: " + ans); System.out.println("evaluation took " + millis); } catch (ScriptException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public static void runJython() { ScriptEngine jas = new ScriptEngineManager().getEngineByExtension("py"); System.out.println("JAS service discovered: " + jas); if ( jas == null ) { System.out.println("No JAS engine found"); return; } System.out.println("Using JAS engine: " + jas); try { long millis = System.currentTimeMillis(); //String ex = "x = 1; print(4*2*x)"; String ex = "from jas import PolyRing, ZZ;\nr = PolyRing(ZZ(),\"x,y,z\",PolyRing.lex);\nprint str(r);\n" + "[one,x,y,z] = r.gens();\np = ((x*y)+z)**33;\nprint \"p = \" + str(p)"; System.out.println("input: " + ex); Object ans = jas.eval(ex); millis = System.currentTimeMillis() - millis; System.out.println("answer: " + ans); System.out.println("evaluation took " + millis); } catch (ScriptException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public static void runJruby() { ScriptEngine jas = new ScriptEngineManager().getEngineByExtension("rb"); System.out.println("JAS service discovered: " + jas); if ( jas == null ) { System.out.println("No JAS engine found"); return; } System.out.println("Using JAS engine: " + jas); try { long millis = System.currentTimeMillis(); //String ex = "x = 1; print(4*2*x)"; String ex = "require \"jas\"; r = PolyRing.new(ZZ(),\"x,y,z\",PolyRing.lex); puts r.to_s;" + "one,x,y,z = r.gens(); p = ((x*y)+z)**33; puts \"p = \" + p.to_s"; System.out.println("input: " + ex); Object ans = jas.eval(ex); millis = System.currentTimeMillis() - millis; System.out.println("answer: " + ans); System.out.println("evaluation took " + millis); } catch (ScriptException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } jas-2.5/jython/src/edu/jas/gb/0000755000175000017500000000000012140140252016356 5ustar giovannigiovannijas-2.5/jython/src/edu/jas/gb/GBSigBasedTest.java0000644000175000017500000001303112057226546021773 0ustar giovannigiovanni/* * $Id: GBSigBasedTest.java 4312 2012-12-03 22:53:26Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; import edu.jas.arith.BigRational; //import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base sig based via jython tests with JUnit. * @author Heinz Kredel. */ public class GBSigBasedTest extends TestCase { private static final Logger logger = Logger.getLogger(GBSigBasedTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GBSigBasedTest object. * @param name String. */ public GBSigBasedTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GBSigBasedTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; List> Gn; GroebnerBaseAbstract bb; GroebnerBaseAbstract bbn; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 10; int ll = 7; int el = 3; float q = 0.2f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bb = new GBSigBased(); //bbn = new GroebnerBaseSeq(new ReductionSeq(),new OrderedSyzPairlist()); bbn = new GroebnerBaseSeq(); } @Override protected void tearDown() { int s = bb.cancel(); logger.debug("canceled tasks: " + s); //assertTrue("s >= 0 " + s, s >= 0); a = b = c = d = e = null; fac = null; bb = null; bbn = null; } /** * Test GBase. */ public void testGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L.add(a); L = bb.GB(L); assertTrue("isGB( { a } )", bb.isGB(L)); L.add(b); //System.out.println("L = " + L.size() ); L = bb.GB(L); assertTrue("isGB( { a, b } )", bb.isGB(L)); L.add(c); L = bb.GB(L); assertTrue("isGB( { a, b, c } )", bb.isGB(L)); L.add(d); L = bb.GB(L); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L)); L.add(e); L = bb.GB(L); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L)); } /** * Test Trinks7 GBase. */ @SuppressWarnings("unchecked") public void testTrinks7GBase() { //String exam = "Mod 32003 (B,S,T,Z,P,W) L " String exam = "Rat (B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ) " + "( 10000 B**2 + 6600 B + 2673 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); long t; t = System.currentTimeMillis(); Gn = bbn.GB(F.list); t = System.currentTimeMillis() - t; System.out.println("bbn took = " + t); G = bb.GB(F.list); assertEquals("#GB(Trinks7) == 6", 6, G.size()); assertTrue("isGB( GB(Trinks7) ) " + G, bb.isGB(G)); assertEquals("#G == #Gn", G.size(), Gn.size()); assertTrue("t >= 0 ", t >= 0); //PolynomialList trinks = new PolynomialList(F.ring, G); //System.out.println("G = " + trinks); // t = System.currentTimeMillis(); // Gn = bbn.GB(F.list); // t = System.currentTimeMillis() - t; // System.out.println("bbn took = " + t); // G = bb.GB(F.list); // assertEquals("#G == #Gn", G.size(), Gn.size()); // t = System.currentTimeMillis(); // Gn = bbn.GB(F.list); // t = System.currentTimeMillis() - t; // System.out.println("bbn took = " + t); // G = bb.GB(F.list); // assertEquals("#G == #Gn", G.size(), Gn.size()); // assertEquals("#GB(Trinks7) == 6", 6, G.size()); } } jas-2.5/jython/src/edu/jas/gb/GBSigBased.java0000644000175000017500000001107412057227174021136 0ustar giovannigiovanni/* * $Id: GBSigBased.java 4313 2012-12-03 22:58:05Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.ArrayList; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.OptimizedPolynomialList; import edu.jas.poly.TermOrderOptimization; import edu.jas.structure.GcdRingElem; /** * Groebner bases via signatur based GBs in script. * @author Heinz Kredel * TODO: Computing via the ScriptEngine is way slower than the direct execution * in the jython interpreter. Check if a different engine is in the path or if it must * be configured in some special way. */ public class GBSigBased> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GBSigBased.class); private final boolean debug = logger.isDebugEnabled(); //logger.isInfoEnabled(); /** * Scripting engine. */ public final ScriptEngine engine; /** * GBSigBased constructor. */ public GBSigBased() { engine = new ScriptEngineManager().getEngineByExtension("py"); logger.info("Script engine discovered: " + engine.getClass().getName()); if ( engine == null ) { logger.error("no script engine found"); throw new RuntimeException("no script engine found"); } StringBuffer sb = new StringBuffer(); sb.append("from jas import PolyRing, ZZ, QQ, arraylist2pylist, pylist2arraylist;\n" ); sb.append("from basic_sigbased_gb import sigbased_gb, arris_algorithm, ggv, ggv_first_implementation, f5, f5z;\n" ); sb.append("sbgb = sigbased_gb();\n" ); sb.append("arri = arris_algorithm();\n" ); sb.append("ggv = ggv();\n" ); sb.append("ggv1 = ggv_first_implementation();\n" ); sb.append("ff5 = f5z();\n" ); String ex = sb.toString(); if (debug) { logger.info("input for evaluation:\n" + ex); } try { Object ans = engine.eval(ex); } catch (ScriptException e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * Get the String representation with GB engine. * @see java.lang.Object#toString() */ @Override public String toString() { return "GBSigBased[ " + engine.getClass().getName() + " ]"; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { } /** * Cancel ThreadPool. */ @Override public int cancel() { return 0; } /** * Groebner base. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ //JAVA6only: @Override public List> GB(int modv, List> F) { if (F == null || F.isEmpty()) { return F; } if (modv != 0) { throw new UnsupportedOperationException("implemented only for modv = 0, not " + modv); } GenPolynomialRing pfac = F.get(0).ring; List> G = new ArrayList>(); long millis = System.currentTimeMillis(); try { engine.put("F",F); StringBuffer sb = new StringBuffer(); //sb.append("r = " + pfac.toScript() + ";\n"); //sb.append("print str(r);\n"); //sb.append("print \"F = \" + str(F);\n"); sb.append("Fp = arraylist2pylist(F);\n"); //sb.append("Gp = sbgb.basis_sig(Fp);\n"); //sb.append("Gp = ff5.basis_sig(Fp);\n"); //sb.append("Gp = arri.basis_sig(Fp);\n"); sb.append("Gp = ggv1.basis_sig(Fp);\n"); sb.append("G = pylist2arraylist(Gp);\n"); String ex = sb.toString(); if (debug) { logger.info("input for evaluation:\n" + ex); } Object ans = engine.eval(ex); if ( ans != null ) { logger.info("answer: " + ans); } G = (List>) engine.get("G"); } catch (ScriptException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } millis = System.currentTimeMillis() - millis; System.out.println("evaluation took " + millis); if (debug) { logger.info("polynomials G: " + G); } return G; } } jas-2.5/jython/.gitignore0000644000175000017500000000001511306743400015640 0ustar giovannigiovanni/test /*.jar jas-2.5/guide.html0000644000175000017500000006210412056445746014346 0ustar giovannigiovanni JAS project users guide

Interactive users guide

This document contains a first how-to and usage information for the JAS project. JAS can be used as any other Java library by adding jas.jar to the classpath and creating and using objects from JAS classes. JAS can also be used interactively via the Python Java interpreter jython (or the Ruby Java interpreter jruby or the jruby Android App Ruboto-IRB). This is explained in this page. For an introduction the API see the API guide. Since JAS Version 2.2 there is an enhanced interface which allows direct input of algebraic expressions, see here.

Getting started

As first example we will discus how to compute a Groebner base with jython. The jython script will be placed into a file, e.g. getstart.py. This script file is executed by calling

  jython getstart.py

The script file first imports the desired mathematical classes from the jas.py script which does all interfacing to the Java library. For the Epydoc of it see here.

  from jas import Ring
  from jas import Ideal

In our case we need Ring to define an appropriate polynomial ring and Ideal to define sets of polynomials and have methods to compute Groebner bases. Ring takes a string argument which contains required definitions of the polynomial ring: the type of the coefficient ring, the names of the used variables and the desired term order.

  r = Ring( "Rat(B,S,T,Z,P,W) L" );

The ring definition is stored in the variable r for later use. The string "Rat(B,S,T,Z,P,W) L" defines the coefficient ring to be the rational numbers Rat, the polynomial ring consists of the variables B, S, T, Z, P, W and the term order L means a lexicographic term order. For some historical reason the term order orders the variables as B < S < T < Z < P < W and not the other way. I.e. the highest or largest variable is always on the left of the list of variables not on the right as in some other algebra systems. With

  print "Ring: " + str(r);

you can print out the ring definition. str(r) is the usual python way of producing string representations of objects, which in our case calls the respective Java method toString() of the JAS ring object. It produces

Ring: BigRational(B, S, T, Z, P, W) INVLEX

i.e. the coefficients are from the jas class BigRational and the term order is INVLEX (INV because the largest variable is on the left). Next we need to enter the generating polynomials for the ideal. We do this in two steps, first define a python string with the polynomials and then the creation of the ideal using the ring definition from before and the polynomial string.

ps = """
( 
 ( 45 P + 35 S - 165 B - 36 ), 
 ( 35 P + 40 Z + 25 T - 27 S ), 
 ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), 
 ( - 9 W + 15 T P + 20 S Z ), 
 ( P W + 2 T Z - 11 B**3 ), 
 ( 99 W - 11 B S + 3 B**2 ),
 ( B**2 + 33/50 B + 2673/10000 )
) 
""";

The polynomial string can be generated by any means python allows for string manipulation. In our example we use python multiline strings, which are delimited by triple quotes """ ... """. The list of polynomials is delimited by parenthesis ( ... ), as well as every polynomial is delimited by parenthesis, e.g. ( B**2 + 33/50 B + 2673/10000 ). The polynomials are separated by commas. The syntax for polynomials is a sequence of monimals consisting of coefficients and terms (as products of powers of variables). The terms can optionally be written with multiplication sign, i.e. 25 S P can be written 25*S*P. Variable names must be delimited by white space or some operator, i.e. you can not write 25 SP because SP is not a listed variable name in the polynomial ring definition. Coefficients may not contain white space, i.e. the / separating the nominator from the denominator may not be surrounded by spaces, i.e. writing 33 / 50 is not allowed. Powers of variables can be written with ** or ^, i.e. the square of B is written as B**2 or B^2. The ideal is the defined with

  f = Ideal( r, ps );

The ideal is contained the the polynomial ring r and consists of the polynomials from the string ps. Ideals can be printed with

  print "Ideal: " + str(f);

In this example it produces the following output.

Ideal: BigRational(B, S, T, Z, P, W) INVLEX
(
( B^2 + 33/50 B + 2673/10000  ),
( 45 P + 35 S - 165 B - 36  ),
( 35 P + 40 Z + 25 T - 27 S ),
( 15 W + 25 S * P + 30 Z - 18 T - 165 B^2 ),
( -9 W + 15 T * P + 20 S * Z ),
( 99 W - 11 B * S + 3 B^2 ),
( P * W + 2 T * Z - 11 B^3 )
)

The polynomial terms are now sorted with respect to the lexicographical term order. The highest term is first in a polynomial. Also the polynomials are sorted with respect to the term order, but with smallest polynomial first in the list. Finaly we can go to the computation of the Groebner basis of this ideal.

  g = f.GB();

The ideal f has a method GB() which computes the Groebner base. The computed Groebner base is stored in the variable g which is also an ideal. It can be printed as the ideal f

  print "Groebner base:", g;

The output first shows the output from calling the GB() method and the the ideal basis.

sequential executed in 136 ms

Groebner base: BigRational(B, S, T, Z, P, W) INVLEX
(
( B^2 + 33/50 B + 2673/10000  ),
( S - 5/2 B - 9/200  ),
( T - 37/15 B + 27/250  ),
( Z + 49/36 B + 1143/2000  ),
( P - 31/18 B - 153/200  ),
( W + 19/120 B + 1323/20000  )
)

I.e. the Groebner base was computed in 135 ms and consists of six polynomials. The polynomials are now monic, i.e. the leading coefficient is 1 and omitted during print out. This concludes the getting started section.

Overview of jas.py classes and methods

The jython interface to the JAS library consists of the following jython classes. For the Epydoc of them see here.

  • Ring, Ideal and ParamIdeal
    define polynomial rings, ideals and ideals over rings with coefficient parameters.
    Ideal has methods for sequential, parallel and distributed Groebner bases computation, for example GB(), isGB(), parGB(), distGB(), NF() and intersect().
    ParamIdeal has methods for comprehensive Groebner bases computation, for example CGB(), CGBsystem(), regularGB(),

  • SolvableRing and SolvableIdeal
    define solvable polynomial rings and left, right and two-sided ideals.
    SolvableIdeal has methods for left, right and two-sided Groebner bases computation, e.g. leftGB(), rightGB(), twosidedGB(), intersect().

  • Module and SubModule
    define modules over polynomial rings and sub modules.
    Module has a method for sequential Groebner bases computation, e.g. GB().

  • SolvableModule and SolvableSubModule
    define modules over solvable polynomial rings and sub modules.
    SolvableModule has methods for left, right and two-sided Groebner bases computation, e.g. leftGB(), rightGB(), twosidedGB().

Algebraic expressions

Since JAS Version 2.2 there is an enhanced interface which allows direct input of algebraic expressions. For example the above example looks as follows.

r = Ring( "Z(B,S,T,Z,P,W) L" );
print "Ring: " + str(r); 

[B,S,T,Z,P,W] = r.gens();

f1 = 45 * P + 35 * S - 165 * B - 36;
f2 = 35 * P + 40 * Z + 25 * T - 27 * S;
f3 = 15 * W + 25 * S * P + 30 * Z - 18 * T - 165 * B**2;
f4 = - 9 * W + 15 * T * P + 20 * S * Z;
f5 = P * W + 2 * T * Z - 11 * B**3;
f6 = 99 * W - 11 *B * S + 3 * B**2;
f7 = 10000 * B**2 + 6600 * B + 2673;

F = [ f1, f2, f3, f4, f5, f6, f7 ];

I = r.ideal( "", list=F );

The definition of the polynomial ring with r = Ring( "Z(B,S,T,Z,P,W) L" ) is obligatory as before. As above many coefficient rings, e.g. Z, and term orders, e.g. L, can be selected.

New is the setup of a list of generators of the polynomial ring with [B,S,T,Z,P,W] = r.gens(). The sequence of jython variable names B, S, T, Z, P, W should match the sequence of variables as defined in the creation of the ring. A jython variable defined with this idiom then represents a polynomial of the respective ring in the respectively named variable. For example B is the polynomial in ring r in the variable named 'B'.

The so defined polynomial generators can then be used to build (nearly) arbitrary expressions. For example the polynomial f5 is defined by the expression P * W + 2 * T * Z - 11 * B**3. Since Python (and jython) has no built-in rational number support, only (arbitrary long) integers can be used as numbers. As a work around we propose to use python tuples or lists with 2 entries as rational numbers. Floating point numbers are truncated to integer. For exponentiation one must use the double star ** as the carret ^ has a fixed meaning as as bitwise XOR. Additionally all operators must explicitly be written, even between coefficients and variables. The literal representation of the polynomial expression does not restrict the definition of the ring. So the polynomial ring can be defined with rational coefficients but Python integers can be used as operands. If you need to enter rational numbers you must use python tuple or list notation (see below) or explicitly the JAS class BigRational.

Continuing with the example, we build a list of polynomials with a Python list F = [ f1, f2, f3, f4, f5, f6, f7 ]. Finally the ideal is created as usual with the ideal method of r as I = r.ideal( "", list=F ).

When python tuples or lists of integers are used as operands of JAS ring elements they are interpreted as rational or complex rational numbers. For example in the construction of Legendre polynomials a rational number r = 1/n appears. As tuple literal it is written (1,n) and as list literal it can be written as [1,n].

p = (2*n-1) * x * P[n-1] - (n-1) * P[n-2];
r = (1,n); # no rational numbers in python, use tuple notation
p = r * p; 

In the same way complex rational numbers can be written as nested tuples. For example 1/n + 1/2 i can be written as ((1,n),(1,2)). If the second list element is omited it is asumed to be one. In this case it can however not be written as tuple, since one nesting level would be removed as expression parenthesis. If the tuples or lists contain more than 2 elements, the rest is silently ignored. For example 1/n as complex number can be written as [(1,n)] (but not as ((1,n))). Different nesting levels are allowed, i.e. ((1,n),2) or (0,(1,n)) are legal.

In case the types (nesting levels) of operands do not match, for example when adding a rational to a complex number (low level) class cast errors will be thrown. For example in (1,n) + (0,(1,n)) the exception edu.jas.arith.BigComplex cannot be cast to edu.jas.arith.BigRational will be thrown.

Further examples can be found in the jython files polynomial.py, legendre.py, hermite.py or chebyshev.py.

Real roots of zero dimensional ideals

Besides the computation of Gröbner bases JAS is able to use them to solve various other problems. In this sub-section we present the computation of real roots of systems of (algebraic) equations. When the system of equations has only finitely many real roots, such systems define so called zero dimensional ideals, they can be computed as follows.

r = PolyRing(QQ(),"x,y,z",PolyRing.lex);
print "Ring: " + str(r);
print;

[one,x,y,z] = r.gens();

f1 = (x**2 - 5)*(x**2 - 3)**2;
f2 = y**2 - 3;
f3 = z**3 - x * y;

F = r.ideal( list=[f1,f2,f3] );

R = F.realRoots();
F.realRootsPrint()

In the above example we compute the real roots of the equations defined by the polynomials f1, f2, f3. First we define the polynomial ring and then construct the ideal F from the given polynomials. The method F.realRoots() computes the real roots and method F.realRootsPrint() prints a decimal approximation of tuples of real roots. The output of the last method call looks as follows.

[-1.7320508076809346675872802734375, -1.7320508076809346675872802734375, 1.4422495705075562000274658203125]
[1.7320508076809346675872802734375, 1.7320508076809346675872802734375, 1.4422495705075562000274658203125]

[1.7320508076809346675872802734375, -1.7320508076809346675872802734375, -1.4422495705075562000274658203125]
[-1.7320508076809346675872802734375, 1.7320508076809346675872802734375, -1.4422495705075562000274658203125]

[0.50401716955821029841899871826171875, 2.236067977384664118289947509765625, -1.7320508076809346675872802734375, -1.5704178023152053356170654296875]
[-0.50401716955821029841899871826171875, -2.236067977384664118289947509765625, 1.7320508076809346675872802734375, -1.5704178023152053356170654296875]
[-3.96811878503649495542049407958984375, -2.236067977384664118289947509765625, -1.7320508076809346675872802734375, 1.5704178023152053356170654296875]
[3.96811878503649495542049407958984375, 2.236067977384664118289947509765625, 1.7320508076809346675872802734375, 1.5704178023152053356170654296875]

The roots in the tuples [-1.7320508076809346675872802734375, -1.7320508076809346675872802734375, 1.4422495705075562000274658203125] correspond to the roots in the variables [x, y, z]. The last four tuples have four entries [0.50401716955821029841899871826171875, 2.236067977384664118289947509765625, -1.7320508076809346675872802734375, -1.5704178023152053356170654296875], where the first entry stems from an internal field extension, which was needed to correctly identify the roots of the ideal and are to be ignored. That is the tuple [2.236067977384664118289947509765625, -1.7320508076809346675872802734375, -1.5704178023152053356170654296875] without the first entry is a real root of the ideal. That is, the decimal approximation of the real roots are the following 8 tuples.

[-1.7320508076809346675872802734375, -1.7320508076809346675872802734375, 1.4422495705075562000274658203125]
[1.7320508076809346675872802734375, 1.7320508076809346675872802734375, 1.4422495705075562000274658203125]

[1.7320508076809346675872802734375, -1.7320508076809346675872802734375, -1.4422495705075562000274658203125]
[-1.7320508076809346675872802734375, 1.7320508076809346675872802734375, -1.4422495705075562000274658203125]

[2.236067977384664118289947509765625, -1.7320508076809346675872802734375, -1.5704178023152053356170654296875]
[-2.236067977384664118289947509765625, 1.7320508076809346675872802734375, -1.5704178023152053356170654296875]
[-2.236067977384664118289947509765625, -1.7320508076809346675872802734375, 1.5704178023152053356170654296875]
[2.236067977384664118289947509765625, 1.7320508076809346675872802734375, 1.5704178023152053356170654296875]

More details and further examples can be found in the jython file 0dim_real_roots.py.

Univariate power series

Univariate power series can be constructed via the SeriesRing class. In the following example we create a new power series ring pr in the variable y over the rational numbers. The creation of power series is done in the same way as polynomials are created. There are additional methods like r.exp() or r.sin() to create the exponential power series or the power series for the sinus function.

pr = SeriesRing("Q(y)");
print "pr:", pr;

one = pr.one();
r1 = pr.random(4);
r2 = pr.random(4);

print "one:", one;
print "r1:", r1;
print "r2:", r2;

r4 = r1 * r2 + one;
e = pr.exp();
r5 = r1 * r2 + e;

print "e:", e;
print "r4:", r4;
print "r5:", r5;

Once power series are created, for example r1, r2, e above, it is possible to use arithmetic operators to built expressions of power series like 'r1 * r2 + one' or 'r1 * r2 + e'.

pr: BigRational((y))

one: 1  + BigO(y^11)
r1:  - 14/3 * y + 3/5 * y^6 + 1/12 * y^8 + 1/7 * y^10 + BigO(y^11)
r2:  - 9/11  - 11/9 * y - 4/3 * y^4 + 7/9 * y^5 + 3 * y^6 - 3/2 * y^8 + BigO(y^11)

e: 1  + 1 * y + 1/2 * y^2 + 1/6 * y^3 + 1/24 * y^4 + 1/120 * y^5 + 1/720 * y^6 + 1/5040 * y^7 + 1/40320 * y^8 + 1/362880 * y^9 + 1/3628800 * y^10 + BigO(y^11)
r4: 1  + 42/11 * y + 154/27 * y^2 + 56/9 * y^5 - 6119/1485 * y^6 - 221/15 * y^7 - 3/44 * y^8 + 745/108 * y^9 - 353/385 * y^10 + BigO(y^11)
r5: 1  + 53/11 * y + 335/54 * y^2 + 1/6 * y^3 + 1/24 * y^4 + 2243/360 * y^5 - 97871/23760 * y^6 - 14851/1008 * y^7 - 30229/443520 * y^8 + 2503201/362880 * y^9 - 36599029/39916800 * y^10 + BigO(y^11)

It is also possible to create power series by defining a generating function or by defining a fixed point with respect to a map between power series.

def g(a):
    return a+a;
ps1 = pr.create(g);

class coeff( Coefficients ):
    def generate(self,i):
        ...
ps6 = pr.create( clazz=coeff( pr.ring.coFac ) );

class cosmap( PowerSeriesMap ):
    def map(self,ps):
        ...
ps8 = pr.fixPoint( cosmap( pr.ring.coFac ) );

More details and further examples can be found in the jython file powerseries.py.

Overview of jas.rb classes and methods

The jruby interface to the JAS library consists essentially of the same classes as the jython interface, but the ruby language, syntax and semantics is used. For the Rdoc of them see here.

For the Android app the main screen with the "trinks.rb" example and its output looks as follows.

   

The Trinks example from above looks in Ruby as follows.

require "examples/jas"

r = PolyRing.new( QQ(),"B,S,T,Z,P,W", PolyRing.lex);
puts "Ring: " + r.to_s;
puts;

one,B,S,T,Z,P,W = r.gens(); 

f1 = 45 * P + 35 * S - 165 * B - 36;
f2 = 35 * P + 40 * Z + 25 * T - 27 * S;
f3 = 15 * W + 25 * S * P + 30 * Z - 18 * T - 165 * B**2;
f4 = - 9 * W + 15 * T * P + 20 * S * Z;
f5 = P * W + 2 * T * Z - 11 * B**3;
f6 = 99 * W - 11 *B * S + 3 * B**2;
f7 = B**2 + 33/50 * B + 2673/10000; # fractions work with ruby

F = [ f1, f2, f3, f4, f5, f6, f7 ]; # smaller, faster
puts "F = " + F.map { |f| f.to_s }.join(",");
puts

f = r.ideal( "", F );
puts "Ideal: " + f.to_s;
puts;

rg = f.GB();
puts "seq Output:", rg;
puts;

The definition of the polynomial ring with r = PolyRing.new( QQ(),"B,S,T,Z,P,W", PolyRing.lex) is obligatory as before. As above many coefficient rings, e.g. QQ, and term orders, e.g. PolyRing.lex, can be selected.

The setup of a list of generators of the polynomial ring is in Ruby one,B,S,T,Z,P,W = r.gens(). The sequence of jruby variable names B, S, T, Z, P, W should match the sequence of variables as defined in the creation of the ring. A jruby variable defined with this idiom then represents a polynomial of the respective ring in the respectively named variable. For example B is the polynomial in ring r in the variable named 'B'.

The so defined polynomial generators can then be used to build (nearly) arbitrary expressions. For example the polynomial f5 is defined by the expression P * W + 2 * T * Z - 11 * B**3. Since Ruby (and jruby) has built-in rational number support, also integer fractions can be used as coefficients. For exponentiation one uses the double star ** as with Python. Additionally all operators must explicitly be written, even between coefficients and variables.

Continuing with the example, we build a list of polynomials with a Ruby list F = [ f1, f2, f3, f4, f5, f6, f7 ]. Finally the ideal is created as usual with the ideal method of r as f = r.ideal( "", F ) in the same way as in Python.

Solvable polynomial rings

Solvable polynomial rings are non commutative polynomial rings where the non commutativity is expressed by commutator relations. Commutator relations are stored in a data structure called relation table. In the definition of a solvable polynomial ring this relation table must be defined. E.g the definition for the ring of a Weyl algebra is

Rat(a,b,e1,e2,e3) L
RelationTable
(
 ( e3 ), ( e1 ), ( e1 e3 - e1 ),
 ( e3 ), ( e2 ), ( e2 e3 - e2 )
)

The relation table must be build from triples of (commutative) polynomials. A triple p1, p2, p3 is interpreted as non commutative multiplication relation p1 .*. p2 = p3. Currently p1 and p2 must be single term, single variable polynomials. The term order must be choosen such that leadingTerm(p1 p2) equals leadingTerm(p3) and p1 > p2 for each triple. Polynomial p3 must be in commutative form, i.e. multiplication operators occuring in it are commutative. Variables for which there are no commutator relations are assumed to commute with each other and with all other variables, e.g. the variables a, b in the example. Polynomials in the generating set of an ideal are also assumed to be in commutative form. This will be changed in the future to allow the multiplication operator to mean non-commutative multiplication.

A complete example is contained in the python script solvable.py. Running the script computes a left, right and twosided Groebner base for the following ideal

(
 ( e1 e3^3 + e2^10 - a ),
 ( e1^3 e2^2 + e3 ),
 ( e3^3 + e3^2 - b )
)

The left Groebner base is

(
 ( a ), ( b ),
 ( e1^3 * e2^2 ), ( e2^10 ), ( e3 )
)

the twosided Groebner base is

(
 ( a ), ( b ), ( e1 ), ( e2 ), ( e3 )
)

and the right Groebner base is

(
 ( a ), ( b ), ( e1 ), ( e2^10 ), ( e3 )
)

A module example is in armbruster.py and a solvable module example is in solvablemodule.py.


Heinz Kredel

Last modified: Sat Dec 1 19:25:47 CET 2012

jas-2.5/mpj/0000755000175000017500000000000012140140254013122 5ustar giovannigiovannijas-2.5/mpj/manifest.mf0000644000175000017500000000010612026333514015257 0ustar giovannigiovanniManifest-Version: 1.0 Created-By: 1.6.0_0 (Sun Microsystems Inc.) jas-2.5/mpj/Makefile0000644000175000017500000000464712067405420014604 0ustar giovannigiovanni# # $Id: Makefile 4335 2012-12-28 21:11:45Z kredel $ # # Makefile for the (Fast) MPJ (Express) dependend parts # by Heinz kredel # #JASPATH=$(HOME)/jas JASPATH=.. LIBPATH=$(HOME)/java/lib FMPJ_HOME=$(HOME)/java/fastmpj FMPJ_LIB=$(FMPJ_HOME)/lib/mpj.jar FMPJ_RUNLIB=$(FMPJ_HOME)/lib/runtime.jar CLASSPATH=$(LIBPATH)/log4j.jar:$(LIBPATH)/junit.jar:$(FMPJ_LIB):$(JASPATH) #$(LIBPATH)/jas.jar NP=2 PPN=3 FMPJ_CMD=java -cp $(FMPJ_RUNLIB) runtime.FMPJRun -dev niodev -cp $(CLASSPATH):jas-mpj.jar #DOCOPTS=-package DOCOPTS=-package -author -version -linksource DOCCLASSES=$(CLASSPATH) DOC=javadoc -classpath $(DOCCLASSES) # --- syncing ---------- DRY=--dry-run DELETE= RSYNC=rsync -e ssh -avuz $(DRY) $(DELETE) --exclude=*~ --exclude=*.log* --exclude=*.out* --exclude=*.txt* --exclude=.svn .SUFFIXES : .class .java .jar .PHONY : clean FILES=$(wildcard src/edu/jas/*/*.java) #echo $(FILES) $(JASPATH)/examples/jas.py CLASSES=$(subst src,classes,$(subst java,class,$(FILES))) #echo $(CLASSES) all: clean jas-mpj.jar doc $(CLASSES): $(FILES) Makefile -mkdir classes javac -classpath $(CLASSPATH) -d classes src/edu/jas/*/*.java jas-mpj.jar: $(CLASSES) -mkdir classes/META-INF cp -a manifest.mf classes/META-INF/MANIFEST.MF jar cfM jas-mpj.jar -C classes . cp -f jas-mpj.jar $(LIBPATH) cp -f jas-mpj.jar .. clean: rm -rf classes find . -name "*~" -follow -print -exec rm {} \; MFILE=machines EFILE=$(JASPATH)/examples/trinks6.jas tests: jas-mpj.jar FMPJ_HOME=$(FMPJ_HOME) $(FMPJ_CMD) -np $(NP) -machinefile $(MFILE) -class edu.jas.application.RunMPJGB disthybmpj $(EFILE) $(NP)/$(PPN) $(MFILE) notest: jas-mpj.jar FMPJ_HOME=$(FMPJ_HOME) $(FMPJ_CMD) -np $(NP) -machinefile $(MFILE) -class edu.jas.application.RunMPJGB distmpj $(EFILE) $(NP) $(MFILE) FMPJ_HOME=$(FMPJ_HOME) $(FMPJ_CMD) -class edu.jas.gb.HelloWorld FMPJ_HOME=$(FMPJ_HOME) $(FMPJ_CMD) -class edu.jas.kern.MPJEngineTest -n $(NP) FMPJ_HOME=$(FMPJ_HOME) $(FMPJ_CMD) -class edu.jas.util.DistHashTableMPJTest -n $(NP) gbtest: jas-mpj.jar FMPJ_HOME=$(FMPJ_HOME) $(FMPJ_CMD) -np $(NP) -machinefile $(MFILE) -class edu.jas.gb.GroebnerBaseDistMPJTest gbhybtest: jas-mpj.jar FMPJ_HOME=$(FMPJ_HOME) $(FMPJ_CMD) -np $(NP) -machinefile $(MFILE) -class edu.jas.gb.GroebnerBaseDistHybridMPJTest doc: $(FILES) $(DOC) $(DOCOPTS) -d ../doc/mpj $(FILES) BWDIR=java/jas-2.4/mpj home: $(RSYNC) bwgrid:$(BWDIR)/src/ src bwgrid: $(RSYNC) src/ bwgrid:$(BWDIR)/src/ jas-2.5/mpj/src/0000755000175000017500000000000012140140254013711 5ustar giovannigiovannijas-2.5/mpj/src/edu/0000755000175000017500000000000012140140254014466 5ustar giovannigiovannijas-2.5/mpj/src/edu/jas/0000755000175000017500000000000012140140254015243 5ustar giovannigiovannijas-2.5/mpj/src/edu/jas/kern/0000755000175000017500000000000012140140254016202 5ustar giovannigiovannijas-2.5/mpj/src/edu/jas/kern/MPJEngine.java0000644000175000017500000001506512102570256020637 0ustar giovannigiovanni/* * $Id: MPJEngine.java 4363 2013-01-31 22:31:11Z kredel $ */ package edu.jas.kern; import java.util.Arrays; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.atomic.AtomicInteger; import mpi.Comm; import mpi.MPI; import mpi.Request; import mpi.Status; import mpi.MPIException; import org.apache.log4j.Logger; /** * MPJ engine, provides global MPI service. Note: could eventually be * done directly with MPJ, but provides logging. Usage: To obtain a * reference to the MPJ service communicator use * MPJEngine.getComminicator(). Once an engine has been created it * must be shutdown to exit JAS with MPJEngine.terminate(). * @author Heinz Kredel */ public final class MPJEngine { private static final Logger logger = Logger.getLogger(MPJEngine.class); private static final boolean debug = logger.isDebugEnabled(); /** * Command line arguments. Required for MPJ runtime system. */ protected static String[] cmdline; /** * Flag for MPJ usage. Note: Only introduced because Google app * engine does not support MPJ. */ public static boolean NO_MPJ = false; /** * Number of processors. */ public static final int N_CPUS = Runtime.getRuntime().availableProcessors(); /* * Core number of threads. * N_CPUS x 1.5, x 2, x 2.5, min 3, ?. */ public static final int N_THREADS = (N_CPUS < 3 ? 3 : N_CPUS + N_CPUS / 2); /** * MPJ communicator engine. */ static Comm mpjComm; /** * MPJ engine base tag number. */ public static final int TAG = 11; /* * Send locks per tag. */ private static SortedMap sendLocks = new TreeMap(); /* * receive locks per tag. */ private static SortedMap recvLocks = new TreeMap(); /** * No public constructor. */ private MPJEngine() { } /** * Set the commandline. * @param args the command line to use for the MPJ runtime system. */ public static synchronized void setCommandLine(String[] args) { cmdline = args; } /** * Test if a pool is running. * @return true if a thread pool has been started or is running, else false. */ public static synchronized boolean isRunning() { if (mpjComm == null) { return false; } if (MPI.Finalized()) { return false; } return true; } /** * Get the MPJ communicator. * @return a Communicator constructed for cmdline. */ public static synchronized Comm getCommunicator() { if (cmdline == null) { throw new IllegalArgumentException("command line not set"); } return getCommunicator(cmdline); } /** * Get the MPJ communicator. * @param args the command line to use for the MPJ runtime system. * @return a Communicator. */ public static synchronized Comm getCommunicator(String[] args) { if (NO_MPJ) { return null; } if (mpjComm == null) { //String[] args = new String[] { }; //"-np " + N_THREADS }; if (!MPI.Initialized()) { if (args == null) { throw new IllegalArgumentException("command line is null"); } cmdline = args; //args = MPI.Init(args); int tl = MPI.Init_thread(args,MPI.THREAD_MULTIPLE); logger.info("MPJ initialized on " + MPI.Get_processor_name()); logger.info("thread level MPI.THREAD_MULTIPLE: " + MPI.THREAD_MULTIPLE + ", provided: " + tl); if (debug) { logger.debug("remaining args: " + Arrays.toString(args)); } } mpjComm = MPI.COMM_WORLD; logger.info("MPJ size = " + mpjComm.Size() + ", rank = " + mpjComm.Rank()); } return mpjComm; } /** * Stop execution. */ public static synchronized void terminate() { if (mpjComm == null) { return; } logger.info("terminating MPJ on rank = " + mpjComm.Rank()); mpjComm = null; if (MPI.Finalized()) { return; } MPI.Finalize(); } /** * Set no MPJ usage. */ public static synchronized void setNoMPJ() { NO_MPJ = true; terminate(); } /** * Set MPJ usage. */ public static synchronized void setMPJ() { NO_MPJ = false; } /** * Get send lock per tag. * @param tag message tag. * @return a lock for sends. */ public static synchronized Object getSendLock(int tag) { tag = 11; // one global lock Object lock = sendLocks.get(tag); if ( lock == null ) { lock = new Object(); sendLocks.put(tag,lock); } return lock; } /** * Get receive lock per tag. * @param tag message tag. * @return a lock for receives. */ public static synchronized Object getRecvLock(int tag) { Object lock = recvLocks.get(tag); if ( lock == null ) { lock = new Object(); recvLocks.put(tag,lock); } return lock; } /** * Wait for termination of a mpj Request. * @param req a Request. * @return a Status after termination of req.Wait(). */ public static Status waitRequest(final Request req) { if ( req == null ) { throw new IllegalArgumentException("null request"); } int delay = 10; int delcnt = 0; Status stat = null; while (true) { synchronized (MPJEngine.class) { // global static lock stat = req.Get_status(); // should be non destructive, but is not if ( stat != null ) { return req.Wait(); // should terminate immediately } } try { Thread.currentThread().sleep(delay); // varied a bit } catch (InterruptedException e) { logger.info("sleep interrupted"); e.printStackTrace(); } delcnt++; if ( delcnt % 7 == 0 ) { delay++; System.out.println("delay(" + delay + "): " + Thread.currentThread().toString()); } } } } jas-2.5/mpj/src/edu/jas/kern/MPJEngineTest.java0000644000175000017500000000522612041031406021464 0ustar giovannigiovanni/* * $Id: MPJEngineTest.java 4263 2012-10-21 17:38:14Z kredel $ */ package edu.jas.kern; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import mpi.MPI; import mpi.Status; import org.apache.log4j.BasicConfigurator; /** * MPJEngine tests with JUnit. * @author Heinz Kredel */ public class MPJEngineTest extends TestCase { /** * main */ public static void main(String[] args) { cmdline = args; BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); MPJEngine.terminate(); } static String[] cmdline; static mpi.Comm engine; /** * Constructs a MPJEngineTest object. * @param name String. */ public MPJEngineTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(MPJEngineTest.class); return suite; } @Override protected void setUp() { if (engine == null) { engine = MPJEngine.getCommunicator(cmdline); } } @Override protected void tearDown() { if (engine == null) { return; } engine = null; } /** * Test MPJEngine. */ public void testMPJEngine() { int me = engine.Rank(); int size = engine.Size(); assertTrue("size > 0", size > 0); assertTrue("0 <= me < size", 0 <= me && me < size); //System.out.println("testMPJEngine(): Hello World from " + me + " of " + size); } /** * Test communication. */ public void testCommunication() { int me = engine.Rank(); int size = engine.Size(); int tag = 13; int[] data = new int[5]; if (me == 0) { //System.out.println("testCommunication(): from " + me + " of " + size); for (int i = 1; i < size; i++) { data[0] = i; engine.Send(data, 0, data.length, MPI.INT, i, tag); } } else { Status stat = engine.Recv(data, 0, data.length, MPI.INT, 0, tag); int cnt = stat.Get_count(MPI.INT); int elem = stat.Get_elements(MPI.INT); //System.out.println("testCommunication(): status " + me + ", " + cnt + ", " + elem); //System.out.println("testCommunication(): received " + Arrays.toString(data)); assertTrue("length == count", data.length == cnt); assertTrue("recv == me", data[0] == me); assertTrue("elem >= 0: " + elem, elem >= 0); } //System.out.println("testCommunication(): done"); } } jas-2.5/mpj/src/edu/jas/util/0000755000175000017500000000000012140140254016220 5ustar giovannigiovannijas-2.5/mpj/src/edu/jas/util/DistHashTableMPJTest.java0000644000175000017500000001177212041031406022757 0ustar giovannigiovanni/* * $Id: DistHashTableMPJTest.java 4263 2012-10-21 17:38:14Z kredel $ */ package edu.jas.util; import java.util.Iterator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import mpi.Comm; import org.apache.log4j.BasicConfigurator; import edu.jas.kern.MPJEngine; /** * DistHashTableMPJ test with JUnit. * @author Heinz Kredel */ public class DistHashTableMPJTest extends TestCase { protected static Comm engine; /** * main. */ public static void main(String[] args) { //long t = System.currentTimeMillis(); BasicConfigurator.configure(); engine = MPJEngine.getCommunicator(args); junit.textui.TestRunner.run(suite()); engine.Barrier(); MPJEngine.terminate(); //t = System.currentTimeMillis() - t; //System.out.println("MPJ runtime = " + t + " milli seconds"); } /** * Constructs a DistHashTableMPJTest object. * @param name String. */ public DistHashTableMPJTest(String name) { super(name); } /** * suite. * @return a test suite. */ public static Test suite() { TestSuite suite = new TestSuite(DistHashTableMPJTest.class); return suite; } private DistHashTableMPJ l1; private DistHashTableMPJ l2; private DistHashTableMPJ l3; @Override protected void setUp() { engine.Barrier(); } @Override protected void tearDown() { engine.Barrier(); if (l1 != null) l1.terminate(); if (l2 != null) l2.terminate(); if (l3 != null) l3.terminate(); l1 = l2 = l3 = null; try { //Thread.currentThread(); //System.out.println("tearDown: sleep = 1"); Thread.sleep(1); } catch (InterruptedException e) { } engine.Barrier(); } /** * Tests create and terminate DistHashTableMPJ. */ public void xtestDistHashTable1() { l1 = new DistHashTableMPJ(engine); l1.init(); assertTrue("l1==empty", l1.isEmpty()); } /** * Tests if the created DistHashTable has #n objects as content. */ public void xtestDistHashTable2() { int me = engine.Rank(); l1 = new DistHashTableMPJ(engine); l1.init(); assertTrue("l1==empty", l1.isEmpty()); Integer s = 0; if (me == 0) { l1.putWait(Integer.valueOf(1), Integer.valueOf(1)); } else { s = l1.getWait(Integer.valueOf(1)); } assertFalse("l1!=empty: ", l1.isEmpty()); assertTrue("#l1==1: " + l1.getList(), l1.size() >= 1); assertEquals("s == 1: ", s, Integer.valueOf(1)); if (me == 0) { l1.putWait(Integer.valueOf(2), Integer.valueOf(2)); } else { s = l1.getWait(Integer.valueOf(2)); } assertTrue("#l1==2: " + l1.getList(), l1.size() >= 2); assertEquals("s == 2: ", s, Integer.valueOf(2)); if (me == 0) { l1.putWait(Integer.valueOf(3), Integer.valueOf(3)); } else { s = l1.getWait(Integer.valueOf(3)); } assertTrue("#l1==3: " + l1.getList(), l1.size() >= 3); assertEquals("s == 3: ", s, Integer.valueOf(3)); Iterator it = null; it = l1.iterator(); int i = 0; while (it.hasNext()) { Object k = it.next(); Object o = l1.get(k); Integer x = Integer.valueOf(++i); assertEquals("l1(i)==v(i)", x, o); assertEquals("l1(i)==k(i)", x, k); } l1.clear(); assertTrue("#l1==0", l1.size() == 0); } /** * Tests if the two created DistHashTables have #n objects as content. */ public void testDistHashTable3() { int me = engine.Rank(); l2 = new DistHashTableMPJ(engine); l2.init(); //System.out.println("test3: me = " + me + ", l2 = "+ l2); assertTrue("l2==empty", l2.isEmpty()); int i = 0, loops = 10; while (i < loops) { Integer x = Integer.valueOf(++i); //System.out.println("me = " + me + ", x = "+ x); if (me == 0) { l2.putWait(x, x); } else { Integer s = l2.getWait(x); assertEquals("s = x: " + s + ", " + x, s, x); } assertTrue("#l1==i: " + i + ", #l1 = " + l2.size(), l2.size() >= i); } assertTrue("#l2==" + loops, l2.size() == loops); Iterator it = l2.iterator(); i = 0; while (it.hasNext()) { Object k = it.next(); Object o = l2.get(k); Integer x = Integer.valueOf(++i); //System.out.println("me = " + me + ", o = " + o + ", x = "+ x); assertEquals("l2(i)==k(i)", x, k); assertEquals("l2(i)==v(i)", x, o); } } } jas-2.5/mpj/src/edu/jas/util/DistHashTableMPJ.java0000644000175000017500000003027612132614050022122 0ustar giovannigiovanni/* * $Id: DistHashTableMPJ.java 4371 2013-04-14 20:57:13Z kredel $ */ package edu.jas.util; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import mpi.Comm; import mpi.MPI; import mpi.MPIException; import mpi.Status; import mpi.Request; import org.apache.log4j.Logger; import edu.jas.kern.MPJEngine; /** * Distributed version of a HashTable using MPJ. Implemented with a SortedMap / * TreeMap to keep the sequence order of elements. Implemented using MPJ. * @author Heinz Kredel */ public class DistHashTableMPJ extends AbstractMap { private static final Logger logger = Logger.getLogger(DistHashTableMPJ.class); private static boolean debug = true; //logger.isDebugEnabled(); protected final SortedMap theList; protected final Comm engine; protected DHTMPJListener listener; /** * Message tag for DHT communicaton. */ public static final int DHTTAG = MPJEngine.TAG + 1; /** * DistHashTableMPJ. */ public DistHashTableMPJ() { this(MPJEngine.getCommunicator()); } /** * DistHashTableMPJ. * @param args command line for MPJ runtime system. */ public DistHashTableMPJ(String[] args) { this(MPJEngine.getCommunicator(args)); } /** * DistHashTableMPJ. * @param cm MPJ communicator to use. */ public DistHashTableMPJ(Comm cm) { engine = cm; //theList = new ConcurrentSkipListMap(); // Java 1.6 theList = new TreeMap(); listener = new DHTMPJListener(engine, theList); } /** * Hash code. */ @Override public int hashCode() { return theList.hashCode(); } /** * Equals. */ @Override public boolean equals(Object o) { return theList.equals(o); } /** * Contains key. */ @Override public boolean containsKey(Object o) { return theList.containsKey(o); } /** * Contains value. */ @Override public boolean containsValue(Object o) { return theList.containsValue(o); } /** * Get the values as Collection. */ @Override public Collection values() { synchronized (theList) { return new ArrayList(theList.values()); //return theList.values(); } } /** * Get the keys as set. */ @Override public Set keySet() { synchronized (theList) { return theList.keySet(); } } /** * Get the entries as Set. */ @Override public Set> entrySet() { synchronized (theList) { return theList.entrySet(); } } /** * Get the internal list, convert from Collection. */ public List getValueList() { synchronized (theList) { return new ArrayList(theList.values()); } } /** * Get the internal sorted map. For synchronization purpose in normalform. */ public SortedMap getList() { return theList; } /** * Size of the (local) list. */ @Override public int size() { synchronized (theList) { return theList.size(); } } /** * Is the List empty? */ @Override public boolean isEmpty() { synchronized (theList) { return theList.isEmpty(); } } /** * List key iterator. */ public Iterator iterator() { synchronized (theList) { return theList.keySet().iterator(); } } /** * List value iterator. */ public Iterator valueIterator() { synchronized (theList) { return theList.values().iterator(); } } /** * Put object to the distributed hash table. Blocks until the key value pair * is send and received from the server. * @param key * @param value */ public void putWait(K key, V value) { put(key, value); // = send // assume key does not change multiple times before test: V val = null; do { val = getWait(key); //System.out.print("#"); } while (!value.equals(val)); } /** * Put object to the distributed hash table. Returns immediately after * sending does not block. * @param key * @param value */ @Override public V put(K key, V value) { if (key == null || value == null) { throw new NullPointerException("null keys or values not allowed"); } try { DHTTransport tc = DHTTransport. create(key, value); DHTTransport[] tcl = new DHTTransport[1]; tcl[0] = tc; int size = engine.Size(); for (int i = 0; i < size; i++) { // send also to self.listener synchronized (MPJEngine.getSendLock(DHTTAG)) { //engine.Send(tcl, 0, tcl.length, MPI.OBJECT, i, DHTTAG); Request req = engine.Isend(tcl, 0, tcl.length, MPI.OBJECT, i, DHTTAG); Status stat = MPJEngine.waitRequest(req); // req.Wait(); } } //System.out.println("send: "+tc); } catch (MPIException e) { logger.info("sending(key=" + key + ")"); logger.info("send " + e); e.printStackTrace(); } catch (Exception e) { logger.info("sending(key=" + key + ")"); logger.info("send " + e); e.printStackTrace(); } return null; } /** * Get value under key from DHT. Blocks until the object is send and * received from the server (actually it blocks until some value under key * is received). * @param key * @return the value stored under the key. */ public V getWait(K key) { V value = null; try { synchronized (theList) { value = theList.get(key); //value = get(key); while (value == null) { //System.out.print("-"); theList.wait(100); value = theList.get(key); //value = get(key); } } } catch (InterruptedException e) { //Thread.currentThread().interrupt(); e.printStackTrace(); return value; } return value; } /** * Get value under key from DHT. If no value is jet available null is * returned. * @param key * @return the value stored under the key. */ @Override public V get(Object key) { synchronized (theList) { return theList.get(key); } } /** * Clear the List. Caveat: must be called on all clients. */ @Override public void clear() { // send clear message to others synchronized (theList) { theList.clear(); } } /** * Initialize and start the list thread. */ public void init() { logger.debug("init " + listener + ", theList = " + theList); if (listener == null) { return; } if (listener.isDone()) { return; } if (debug) { logger.debug("initialize " + listener); } synchronized (theList) { listener.start(); } } /** * Terminate the list thread. */ public void terminate() { if (listener == null) { return; } if (debug) { Runtime rt = Runtime.getRuntime(); logger.debug("terminate " + listener + ", runtime = " + rt.hashCode()); } try { DHTTransport tc = new DHTTransportTerminate(); DHTTransport[] tcl = new DHTTransport[1]; tcl[0] = tc; // send only to self.listener synchronized (MPJEngine.getSendLock(DHTTAG)) { //engine.Send(tcl, 0, tcl.length, MPI.OBJECT, engine.Rank(), DHTTAG); Request req = engine.Isend(tcl, 0, tcl.length, MPI.OBJECT, engine.Rank(), DHTTAG); Status stat = MPJEngine.waitRequest(req); // req.Wait(); } logger.debug("send terminate to " + engine.Rank()); } catch (MPIException e) { logger.info("sending(terminate)"); logger.info("send " + e); e.printStackTrace(); } catch (Exception e) { logger.info("sending(terminate)"); logger.info("send " + e); e.printStackTrace(); } listener.setDone(); try { while (listener.isAlive()) { //System.out.print("+++++"); listener.join(999); //listener.interrupt(); } } catch (InterruptedException e) { //Thread.currentThread().interrupt(); } listener = null; } } /** * Thread to comunicate with the other DHT lists. */ class DHTMPJListener extends Thread { private static final Logger logger = Logger.getLogger(DHTMPJListener.class); private static boolean debug = true; //logger.isDebugEnabled(); private final Comm engine; private final SortedMap theList; private boolean goon; /** * Constructor. */ DHTMPJListener(Comm cm, SortedMap list) { engine = cm; theList = list; goon = true; } /** * Test if done. */ boolean isDone() { return !goon; } /** * Set to done status. */ void setDone() { goon = false; } /** * run. */ @SuppressWarnings("unchecked") @Override public void run() { logger.debug("listener run() " + this); DHTTransport tc; //goon = true; while (goon) { tc = null; try { DHTTransport[] tcl = new DHTTransport[1]; //System.out.println("engine.Recv"); Status stat = null; synchronized (MPJEngine.getRecvLock(DistHashTableMPJ.DHTTAG)) { //stat = engine.Recv(tcl, 0, tcl.length, MPI.OBJECT, MPI.ANY_SOURCE, // DistHashTableMPJ.DHTTAG); Request req = engine.Irecv(tcl, 0, tcl.length, MPI.OBJECT, MPI.ANY_SOURCE, DistHashTableMPJ.DHTTAG); stat = MPJEngine.waitRequest(req); //req.Wait(); } int cnt = stat.Get_count(MPI.OBJECT); //System.out.println("engine.Recv, cnt = " + cnt); if (cnt == 0) { goon = false; break; } tc = (DHTTransport) tcl[0]; if (debug) { logger.debug("receive(" + tc + ")"); } if (tc instanceof DHTTransportTerminate) { goon = false; break; } if (this.isInterrupted()) { goon = false; break; } K key = tc.key(); if (key != null) { logger.info("receive(" + engine.Rank() + "," + stat.source + "), key=" + key); V val = tc.value(); synchronized (theList) { theList.put(key, val); theList.notifyAll(); } } } catch (MPIException e) { goon = false; logger.info("receive(MPI) " + e); //e.printStackTrace(); } catch (ClassNotFoundException e) { goon = false; logger.info("receive(Class) " + e); e.printStackTrace(); } catch (Exception e) { goon = false; logger.info("receive " + e); e.printStackTrace(); } } logger.info("terminated at " + engine.Rank()); } } jas-2.5/mpj/src/edu/jas/util/MPJChannel.java0000644000175000017500000001000312132614050020775 0ustar giovannigiovanni/* * $Id: MPJChannel.java 4371 2013-04-14 20:57:13Z kredel $ */ package edu.jas.util; import java.io.IOException; import mpi.Comm; import mpi.MPI; import mpi.Status; import mpi.Request; import org.apache.log4j.Logger; import edu.jas.kern.MPJEngine; /** * MPJChannel provides a communication channel for Java objects using MPJ to a * given rank. * @author Heinz Kredel */ public final class MPJChannel { private static final Logger logger = Logger.getLogger(MPJChannel.class); public static final int CHANTAG = MPJEngine.TAG + 2; /* * Underlying MPJ engine. */ private final Comm engine; /* * Partner rank. */ private final int partnerRank; /* * Message tag. */ private final int tag; /** * Constructs a MPJ channel on the given MPJ engine. * @param s MPJ communicator object. * @param r rank of MPJ partner. */ public MPJChannel(Comm s, int r) throws IOException { this(s, r, CHANTAG); } /** * Constructs a MPJ channel on the given MPJ engine. * @param s MPJ communicator object. * @param r rank of MPJ partner. * @param t tag for messages. */ public MPJChannel(Comm s, int r, int t) throws IOException { engine = s; int size = engine.Size(); if (r < 0 || size <= r) { throw new IOException("r out of bounds: 0 <= r < size: " + r + ", " + size); } partnerRank = r; tag = t; logger.info("constructor: " + this.toString()); } /** * Get the MPJ engine. */ public Comm getEngine() { return engine; } /** * Sends an object. * @param v message object. */ public void send(Object v) throws IOException { send(tag, v, partnerRank); } /** * Sends an object. * @param t message tag. * @param v message object. */ public void send(int t, Object v) throws IOException { send(t, v, partnerRank); } /** * Sends an object. * @param t message tag. * @param v message object. * @param pr partner rank. */ void send(int t, Object v, int pr) throws IOException { Object[] va = new Object[1]; va[0] = v; Status stat = null; synchronized (MPJEngine.getSendLock(t)) { //engine.Send(va, 0, va.length, MPI.OBJECT, pr, t); Request req = engine.Isend(va, 0, va.length, MPI.OBJECT, pr, t); stat = MPJEngine.waitRequest(req); // req.Wait(); } //System.out.println("send: "+v); } /** * Receives an object. * @return a message object. */ public Object receive() throws IOException, ClassNotFoundException { return receive(tag); } /** * Receives an object. * @param t message tag. * @return a message object. */ public Object receive(int t) throws IOException, ClassNotFoundException { Object[] va = new Object[1]; //System.out.println("engine.Recv"); //Status stat = engine.Recv(va, 0, va.length, MPI.OBJECT, MPI.ANY_SOURCE, t); Status stat = null; synchronized (MPJEngine.getRecvLock(t)) { //stat = engine.Recv(va, 0, va.length, MPI.OBJECT, partnerRank, t); Request req = engine.Irecv(va, 0, va.length, MPI.OBJECT, partnerRank, t); stat = MPJEngine.waitRequest(req); // req.Wait(); } int cnt = stat.Get_count(MPI.OBJECT); if (cnt == 0) { throw new IOException("no object received"); } //int pr = stat.source; //if (pr != partnerRank) { // logger.warn("received out of order message from " + pr); //} Object v = va[0]; return v; } /** * Closes the channel. */ public void close() { // nothing to do } /** * to string. */ @Override public String toString() { return "MPJChannel(on=" + engine.Rank() + ",to=" + partnerRank + ",tag=" + tag + ")"; } } jas-2.5/mpj/src/edu/jas/application/0000755000175000017500000000000012140140254017546 5ustar giovannigiovannijas-2.5/mpj/src/edu/jas/application/RunMPJGB.java0000644000175000017500000004471512041570744021763 0ustar giovannigiovanni/* * $Id: RunMPJGB.java 4269 2012-10-23 19:37:09Z kredel $ */ package edu.jas.application; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringReader; import java.nio.charset.Charset; import java.util.Arrays; import java.util.List; import org.apache.log4j.BasicConfigurator; import edu.jas.gb.GBDist; import edu.jas.gb.GBDistHybrid; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.GroebnerBaseDistributedHybridMPJ; import edu.jas.gb.GroebnerBaseDistributedMPJ; import edu.jas.gb.GroebnerBaseParallel; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.gb.OrderedSyzPairlist; import edu.jas.gb.ReductionPar; import edu.jas.gb.ReductionSeq; import edu.jas.gbufd.GBFactory; import edu.jas.kern.ComputerThreads; import edu.jas.kern.MPJEngine; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.util.CatReader; import edu.jas.util.ExecutableServer; /** * Simple setup to run a GB example in MPJ environment.
* Usage: RunGB [seq(+)|par(+)|dist(1)(+)|disthyb|cli] <file> * #procs/#threadsPerNode [machinefile] * @author Heinz Kredel */ public class RunMPJGB { /** * Check result GB if it is a GB. */ static boolean doCheck = false; /** * main method to be called from commandline
* Usage: RunMPJGB [seq|par(+)|dist(1)(+)|disthyb|cli] <file> * #procs/#threadsPerNode [machinefile] */ public static void main(java.lang.String[] args) { BasicConfigurator.configure(); MPJEngine.setCommandLine(args); //args = MPI.Init(args); String usage = "Usage: RunMPJGB " + "[ seq | seq+ | par | par+ " + "| dist | dist1 | dist+ | dist1+ | disthyb1 | distmpj " + "| cli [port] ] " + " " + "#procs/#threadsPerNode " + "[machinefile] "; if (args.length < 1) { System.out.println("args: " + Arrays.toString(args)); System.out.println(usage); return; } boolean pairseq = false; String kind = args[0]; String[] allkinds = new String[] { "seq", "seq+", "par", "par+", "dist", "dist1", "dist+", "dist1+", "disthyb1", "distmpj", "distmpj+", "disthybmpj", "disthybmpj+", "cli" }; boolean sup = false; int k = -1; for (int i = 0; i < args.length; i++) { int j = indexOf(allkinds, args[i]); if (j < 0) { continue; } sup = true; k = i; kind = args[k]; if (kind.indexOf("+") >= 0) { pairseq = true; } break; } if (!sup) { System.out.println("args(sup): " + Arrays.toString(args)); System.out.println(usage); return; } System.out.println("kind: " + kind + ", k = " + k); //boolean once = false; final int GB_SERVER_PORT = 7114; //inal int EX_CLIENT_PORT = GB_SERVER_PORT + 1000; int port = GB_SERVER_PORT; if (kind.equals("cli")) { if (args.length - k >= 2) { try { port = Integer.parseInt(args[k + 1]); } catch (NumberFormatException e) { e.printStackTrace(); System.out.println("args(int): " + Arrays.toString(args)); System.out.println(usage); return; } } runClient(port); return; } String filename = null; if (!kind.equals("cli")) { if (args.length - k < 2) { System.out.println("args(cli): " + Arrays.toString(args)); System.out.println(usage); return; } filename = args[k + 1]; } int j = indexOf(args, "check"); if (j >= 0) { doCheck = true; } int threads = 0; int threadsPerNode = 1; if (kind.startsWith("par") || kind.startsWith("dist")) { if (args.length - k < 3) { System.out.println("args(par|dist): " + Arrays.toString(args)); System.out.println(usage); return; } String tup = args[k + 2]; String t = tup; int i = tup.indexOf("/"); if (i >= 0) { t = tup.substring(0, i).trim(); tup = tup.substring(i + 1).trim(); try { threadsPerNode = Integer.parseInt(tup); } catch (NumberFormatException e) { e.printStackTrace(); System.out.println("args(int): " + Arrays.toString(args)); System.out.println(usage); return; } } try { threads = Integer.parseInt(t); } catch (NumberFormatException e) { e.printStackTrace(); System.out.println("args(int): " + Arrays.toString(args)); System.out.println(usage); return; } } String mfile = null; if (kind.startsWith("dist")) { if (args.length - k >= 4) { mfile = args[k + 3]; } else { mfile = "machines"; } } Reader problem = null; try { problem = new InputStreamReader(new FileInputStream(filename), Charset.forName("UTF8")); problem = new BufferedReader(problem); } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println("args(file): " + filename); System.out.println("args(file): " + Arrays.toString(args)); System.out.println(usage); return; } RingFactoryTokenizer rftok = new RingFactoryTokenizer(problem); GenPolynomialRing pfac = null; try { pfac = rftok.nextPolynomialRing(); rftok = null; } catch (IOException e) { e.printStackTrace(); return; } Reader polyreader = new CatReader(new StringReader("("), problem); // ( has gone GenPolynomialTokenizer tok = new GenPolynomialTokenizer(pfac, polyreader); PolynomialList S = null; try { S = new PolynomialList(pfac, tok.nextPolynomialList()); } catch (IOException e) { e.printStackTrace(); return; } System.out.println("S =\n" + S); if (kind.startsWith("seq")) { runSequential(S, pairseq); } if (kind.startsWith("par")) { runParallel(S, threads, pairseq); } if (kind.startsWith("dist1")) { runMasterOnce(S, threads, mfile, port, pairseq); } else if (kind.startsWith("disthyb1")) { runMasterOnceHyb(S, threads, threadsPerNode, mfile, port, pairseq); } else if (kind.startsWith("distmpj")) { runMpj(S, threads, mfile, port, pairseq); } else if (kind.startsWith("disthybmpj")) { runHybridMpj(S, threads, threadsPerNode, mfile, port, pairseq); } else if (kind.startsWith("dist")) { runMaster(S, threads, mfile, port, pairseq); } ComputerThreads.terminate(); //System.exit(0); } @SuppressWarnings("unchecked") static void runMpj(PolynomialList S, int threads, String mfile, int port, boolean pairseq) { List L = S.list; List G = null; long t, t1; t = System.currentTimeMillis(); System.out.println("\nGroebner base distributed MPJ (" + threads + ", " + mfile + ", " + port + ") ..."); GroebnerBaseDistributedMPJ gbd = null; GroebnerBaseDistributedMPJ gbds = null; if (pairseq) { gbds = new GroebnerBaseDistributedMPJ(threads, new OrderedSyzPairlist()); } else { gbd = new GroebnerBaseDistributedMPJ(threads); } t1 = System.currentTimeMillis(); if (pairseq) { G = gbds.GB(L); } else { G = gbd.GB(L); } t1 = System.currentTimeMillis() - t1; if (pairseq) { gbds.terminate(); } else { gbd.terminate(); } MPJEngine.terminate(); if (G == null) { return; // mpi.rank != 0 } S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); t = System.currentTimeMillis() - t; if (pairseq) { System.out.print("m+ "); } else { System.out.print("m "); } System.out.println("= " + threads + ", time = " + t1 + " milliseconds, " + (t - t1) + " start-up " + ", total = " + t); checkGB(S); System.out.println(""); } @SuppressWarnings("unchecked") static void runHybridMpj(PolynomialList S, int threads, int threadsPerNode, String mfile, int port, boolean pairseq) { List L = S.list; List G = null; long t, t1; t = System.currentTimeMillis(); System.out.println("\nGroebner base distributed hybrid MPJ (" + threads + "/" + threadsPerNode + ", " + mfile + ", " + port + ") ..."); GroebnerBaseDistributedHybridMPJ gbd = null; GroebnerBaseDistributedHybridMPJ gbds = null; if (pairseq) { gbds = new GroebnerBaseDistributedHybridMPJ(threads, threadsPerNode, new OrderedSyzPairlist()); } else { gbd = new GroebnerBaseDistributedHybridMPJ(threads, threadsPerNode); } t1 = System.currentTimeMillis(); if (pairseq) { G = gbds.GB(L); } else { G = gbd.GB(L); } t1 = System.currentTimeMillis() - t1; if (pairseq) { gbds.terminate(); } else { gbd.terminate(); } MPJEngine.terminate(); if (G == null) { return; // mpi.rank != 0 } S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); t = System.currentTimeMillis() - t; if (pairseq) { System.out.print("m+ "); } else { System.out.print("m "); } System.out.println("= " + threads + ", ppn = " + threadsPerNode + ", time = " + t1 + " milliseconds, " + (t - t1) + " start-up " + ", total = " + t); checkGB(S); System.out.println(""); } @SuppressWarnings("unchecked") static void runMaster(PolynomialList S, int threads, String mfile, int port, boolean pairseq) { List L = S.list; List G = null; long t, t1; t = System.currentTimeMillis(); System.out.println("\nGroebner base distributed (" + threads + ", " + mfile + ", " + port + ") ..."); GBDist gbd = null; GBDist gbds = null; if (pairseq) { //gbds = new GBDistSP(threads,mfile, port); gbds = new GBDist(threads, new OrderedSyzPairlist(), mfile, port); } else { gbd = new GBDist(threads, mfile, port); } t1 = System.currentTimeMillis(); if (pairseq) { G = gbds.execute(L); } else { G = gbd.execute(L); } t1 = System.currentTimeMillis() - t1; if (pairseq) { gbds.terminate(false); } else { gbd.terminate(false); } S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); t = System.currentTimeMillis() - t; if (pairseq) { System.out.print("d+ "); } else { System.out.print("d "); } System.out.println("= " + threads + ", time = " + t1 + " milliseconds, " + (t - t1) + " start-up " + ", total = " + t); checkGB(S); System.out.println(""); } @SuppressWarnings("unchecked") static void runMasterOnce(PolynomialList S, int threads, String mfile, int port, boolean pairseq) { List L = S.list; List G = null; long t, t1; t = System.currentTimeMillis(); System.out.println("\nGroebner base distributed[once] (" + threads + ", " + mfile + ", " + port + ") ..."); GBDist gbd = null; GBDist gbds = null; if (pairseq) { //gbds = new GBDistSP(threads, mfile, port); gbds = new GBDist(threads, new OrderedSyzPairlist(), mfile, port); } else { gbd = new GBDist(threads, mfile, port); } t1 = System.currentTimeMillis(); if (pairseq) { G = gbds.execute(L); } else { G = gbd.execute(L); } t1 = System.currentTimeMillis() - t1; if (pairseq) { gbds.terminate(true); } else { gbd.terminate(true); } S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); t = System.currentTimeMillis() - t; if (pairseq) { System.out.print("d+ "); } else { System.out.print("d "); } System.out.println("= " + threads + ", time = " + t1 + " milliseconds, " + (t - t1) + " start-up " + ", total = " + t); checkGB(S); System.out.println(""); } @SuppressWarnings("unchecked") static void runMasterOnceHyb(PolynomialList S, int threads, int threadsPerNode, String mfile, int port, boolean pairseq) { List L = S.list; List G = null; long t, t1; t = System.currentTimeMillis(); System.out.println("\nGroebner base distributed hybrid[once] (" + threads + "/" + threadsPerNode + ", " + mfile + ", " + port + ") ..."); GBDistHybrid gbd = null; GBDistHybrid gbds = null; if (pairseq) { //System.out.println("... not implemented."); //return; // gbds = new GBDistSP(threads, mfile, port); gbds = new GBDistHybrid(threads, threadsPerNode, new OrderedSyzPairlist(), mfile, port); } else { gbd = new GBDistHybrid(threads, threadsPerNode, mfile, port); } t1 = System.currentTimeMillis(); if (pairseq) { G = gbds.execute(L); } else { G = gbd.execute(L); } t1 = System.currentTimeMillis() - t1; if (pairseq) { //gbds.terminate(true); } else { //gbd.terminate(true); gbd.terminate(false); // plus eventually killed by script } t = System.currentTimeMillis() - t; S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); if (pairseq) { System.out.print("d+ "); } else { System.out.print("d "); } System.out.println("= " + threads + ", ppn = " + threadsPerNode + ", time = " + t1 + " milliseconds, " + (t - t1) + " start-up " + ", total = " + t); checkGB(S); System.out.println(""); } static void runClient(int port) { System.out.println("\nGroebner base distributed client (" + port + ") ..."); ExecutableServer es = new ExecutableServer(port); es.init(); } @SuppressWarnings("unchecked") static void runParallel(PolynomialList S, int threads, boolean pairseq) { List L = S.list; List G; long t; GroebnerBaseAbstract bb = null; GroebnerBaseAbstract bbs = null; if (pairseq) { //bbs = new GroebnerBaseSeqPairParallel(threads); bbs = new GroebnerBaseParallel(threads, new ReductionPar(), new OrderedSyzPairlist()); } else { bb = new GroebnerBaseParallel(threads); } System.out.println("\nGroebner base parallel (" + threads + ") ..."); t = System.currentTimeMillis(); if (pairseq) { G = bbs.GB(L); } else { G = bb.GB(L); } t = System.currentTimeMillis() - t; S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); if (pairseq) { System.out.print("p+ "); } else { System.out.print("p "); } System.out.println("= " + threads + ", time = " + t + " milliseconds"); if (pairseq) { bbs.terminate(); } else { bb.terminate(); } checkGB(S); System.out.println(""); } @SuppressWarnings("unchecked") static void runSequential(PolynomialList S, boolean pairseq) { List L = S.list; List G; long t; GroebnerBaseAbstract bb = null; if (pairseq) { //bb = new GroebnerBaseSeqPairSeq(); bb = new GroebnerBaseSeq(new ReductionSeq(), new OrderedSyzPairlist()); } else { bb = new GroebnerBaseSeq(); } System.out.println("\nGroebner base sequential ..."); t = System.currentTimeMillis(); G = bb.GB(L); t = System.currentTimeMillis() - t; S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); if (pairseq) { System.out.print("seq+, "); } else { System.out.print("seq, "); } System.out.println("time = " + t + " milliseconds"); checkGB(S); System.out.println(""); } static void checkGB(PolynomialList S) { if (!doCheck) { return; } GroebnerBaseAbstract bb = GBFactory.getImplementation(S.ring.coFac); long t = System.currentTimeMillis(); boolean chk = bb.isGB(S.list); t = System.currentTimeMillis() - t; System.out.println("check isGB = " + chk + " in " + t + " milliseconds"); } static int indexOf(String[] args, String s) { for (int i = 0; i < args.length; i++) { if (s.equals(args[i])) { return i; } } return -1; } } jas-2.5/mpj/src/edu/jas/gb/0000755000175000017500000000000012140140254015633 5ustar giovannigiovannijas-2.5/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java0000644000175000017500000007627212067640742025005 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistributedHybridMPJ.java 4338 2012-12-29 19:17:54Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.concurrent.atomic.AtomicInteger; import mpi.Comm; import org.apache.log4j.Logger; import edu.jas.kern.MPJEngine; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.DistHashTableMPJ; import edu.jas.util.MPJChannel; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; /** * Groebner Base distributed hybrid algorithm with MPJ. Implements a distributed * memory with multi-core CPUs parallel version of Groebner bases with MPJ. * Using pairlist class, distributed multi-threaded tasks do reduction, one * communication channel per remote node. * @param coefficient type * @author Heinz Kredel */ public class GroebnerBaseDistributedHybridMPJ> extends GroebnerBaseAbstract { public static final Logger logger = Logger.getLogger(GroebnerBaseDistributedHybridMPJ.class); public final boolean debug = logger.isDebugEnabled(); /** * Number of threads to use. */ protected final int threads; /** * Default number of threads. */ protected static final int DEFAULT_THREADS = 2; /** * Number of threads per node to use. */ protected final int threadsPerNode; /** * Default number of threads per compute node. */ protected static final int DEFAULT_THREADS_PER_NODE = 1; /** * Pool of threads to use. */ //protected final ExecutorService pool; // not for single node tests protected transient final ThreadPool pool; /* * Underlying MPJ engine. */ protected transient final Comm engine; /** * Message tag for pairs. */ public static final int pairTag = GroebnerBaseDistributedHybridEC.pairTag.intValue(); /** * Message tag for results. */ public static final int resultTag = GroebnerBaseDistributedHybridEC.resultTag.intValue(); /** * Message tag for acknowledgments. */ public static final int ackTag = GroebnerBaseDistributedHybridEC.ackTag.intValue(); /** * Constructor. */ public GroebnerBaseDistributedHybridMPJ() { this(DEFAULT_THREADS); } /** * Constructor. * @param threads number of threads to use. */ public GroebnerBaseDistributedHybridMPJ(int threads) { this(threads, new ThreadPool(threads)); } /** * Constructor. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. */ public GroebnerBaseDistributedHybridMPJ(int threads, int threadsPerNode) { this(threads, threadsPerNode, new ThreadPool(threads)); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. */ public GroebnerBaseDistributedHybridMPJ(int threads, ThreadPool pool) { this(threads, DEFAULT_THREADS_PER_NODE, pool); } /** * Constructor. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. * @param pl pair selection strategy */ public GroebnerBaseDistributedHybridMPJ(int threads, int threadsPerNode, PairList pl) { this(threads, threadsPerNode, new ThreadPool(threads), pl); } /** * Constructor. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. */ public GroebnerBaseDistributedHybridMPJ(int threads, int threadsPerNode, ThreadPool pool) { this(threads, threadsPerNode, pool, new OrderedPairlist()); } /** * Constructor. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. * @param pool ThreadPool to use. * @param pl pair selection strategy */ public GroebnerBaseDistributedHybridMPJ(int threads, int threadsPerNode, ThreadPool pool, PairList pl) { super(new ReductionPar(), pl); this.engine = MPJEngine.getCommunicator(); int size = engine.Size(); if (size < 2) { throw new IllegalArgumentException("Minimal 2 MPJ processes required, not " + size); } if (threads != size || pool.getNumber() != size) { throw new IllegalArgumentException("threads != size: " + threads + " != " + size + ", #pool " + pool.getNumber()); } this.threads = threads; this.pool = pool; this.threadsPerNode = threadsPerNode; //logger.info("generated pool: " + pool); } /** * Cleanup and terminate. */ @Override public void terminate() { if (pool == null) { return; } pool.terminate(); } /** * Distributed Groebner base. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs or on * MPJ client part. */ public List> GB(int modv, List> F) { if (engine.Rank() == 0) { return GBmaster(modv, F); } pool.terminate(); // not used on clients try { clientPart(0); // only 0 } catch (IOException e) { logger.info("clientPart: " + e); e.printStackTrace(); } return null; } /** * Distributed hybrid Groebner base. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs. */ public List> GBmaster(int modv, List> F) { long t = System.currentTimeMillis(); GenPolynomial p; List> G = new ArrayList>(); PairList pairlist = null; boolean oneInGB = false; int l = F.size(); int unused = 0; ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { oneInGB = true; G.clear(); G.add(p); //return G; must signal termination to others } if (!oneInGB) { G.add(p); } if (pairlist == null) { //pairlist = new OrderedPairlist(modv, p.ring); pairlist = strategy.create(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // theList not updated here if (p.isONE()) { unused = pairlist.putOne(); } else { unused = pairlist.put(p); } } else { l--; } } //if (l <= 1) { //return G; must signal termination to others //} logger.info("pairlist " + pairlist + ": " + unused); logger.debug("looking for clients"); DistHashTableMPJ> theList = new DistHashTableMPJ>(engine); theList.init(); List> al = pairlist.getList(); for (int i = 0; i < al.size(); i++) { // no wait required GenPolynomial nn = theList.put(Integer.valueOf(i), al.get(i)); if (nn != null) { logger.info("double polynomials " + i + ", nn = " + nn + ", al(i) = " + al.get(i)); } } Terminator finner = new Terminator((threads - 1) * threadsPerNode); HybridReducerServerMPJ R; logger.info("using pool = " + pool); for (int i = 1; i < threads; i++) { R = new HybridReducerServerMPJ(i, threadsPerNode, finner, engine, theList, pairlist); pool.addJob(R); //logger.info("server submitted " + R); } logger.info("main loop waiting " + finner); finner.waitDone(); int ps = theList.size(); logger.info("#distributed list = " + ps); // make sure all polynomials arrived: not needed in master G = pairlist.getList(); if (ps != G.size()) { logger.info("#distributed list = " + theList.size() + " #pairlist list = " + G.size()); } for (GenPolynomial q : theList.getValueList()) { if (q != null && !q.isZERO()) { logger.debug("final q = " + q.leadingExpVector()); } } logger.debug("distributed list end"); long time = System.currentTimeMillis(); List> Gp; Gp = minimalGB(G); // not jet distributed but threaded time = System.currentTimeMillis() - time; logger.info("parallel gbmi time = " + time); G = Gp; logger.info("server theList.terminate() " + theList.size()); theList.terminate(); t = System.currentTimeMillis() - t; logger.info("server GB end, time = " + t + ", " + pairlist.toString()); return G; } /** * GB distributed client. * @param rank of the MPJ where the server runs on. * @throws IOException */ public void clientPart(int rank) throws IOException { if (rank != 0) { throw new UnsupportedOperationException("only master at rank 0 implemented: " + rank); } Comm engine = MPJEngine.getCommunicator(); MPJChannel chan = new MPJChannel(engine, rank); DistHashTableMPJ> theList = new DistHashTableMPJ>(); theList.init(); ThreadPool pool = new ThreadPool(threadsPerNode); logger.info("client using pool = " + pool); for (int i = 0; i < threadsPerNode; i++) { HybridReducerClientMPJ Rr = new HybridReducerClientMPJ(chan, theList); // i pool.addJob(Rr); } if (debug) { logger.info("clients submitted"); } pool.terminate(); logger.info("client pool.terminate()"); theList.terminate(); return; } /** * Minimal ordered groebner basis. * @param Fp a Groebner base. * @return a reduced Groebner base of Fp. */ @Override public List> minimalGB(List> Fp) { GenPolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiMPJReducerServer[] mirs = (MiMPJReducerServer[]) new MiMPJReducerServer[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new MiMPJReducerServer(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } } /** * Distributed server reducing worker proxy threads. * @param coefficient type */ class HybridReducerServerMPJ> implements Runnable { public static final Logger logger = Logger.getLogger(HybridReducerServerMPJ.class); public final boolean debug = logger.isDebugEnabled(); private final Terminator finner; private MPJChannel pairChannel; protected transient final Comm engine; private final DistHashTableMPJ> theList; private final PairList pairlist; private final int threadsPerNode; final int rank; /** * Message tag for pairs. */ public static final int pairTag = GroebnerBaseDistributedHybridMPJ.pairTag; /** * Constructor. * @param r MPJ rank of partner. * @param tpn number of threads per node * @param fin terminator * @param engine MPJ engine * @param dl distributed hash table * @param L ordered pair list */ HybridReducerServerMPJ(int r, int tpn, Terminator fin, Comm engine, DistHashTableMPJ> dl, PairList L) { rank = r; threadsPerNode = tpn; finner = fin; this.engine = engine; theList = dl; pairlist = L; //logger.info("reducer server created " + this); } /** * Work loop. * @see java.lang.Runnable#run() */ //JAVA6only: @Override public void run() { //logger.info("reducer server running with " + engine); try { pairChannel = new MPJChannel(engine, rank); //,pairTag } catch (IOException e) { e.printStackTrace(); return; } if (logger.isInfoEnabled()) { logger.info("reducer server running: pairChannel = " + pairChannel); } // record idle remote workers (minus one?) //finner.beIdle(threadsPerNode-1); finner.initIdle(threadsPerNode); AtomicInteger active = new AtomicInteger(0); // start receiver HybridReducerReceiverMPJ receiver = new HybridReducerReceiverMPJ(rank, finner, active, pairChannel, theList, pairlist); receiver.start(); Pair pair; //boolean set = false; boolean goon = true; //int polIndex = -1; int red = 0; int sleeps = 0; // while more requests while (goon) { // receive request if thread is reported incactive logger.debug("receive request"); Object req = null; try { req = pairChannel.receive(pairTag); //} catch (InterruptedException e) { //goon = false; //e.printStackTrace(); } catch (IOException e) { goon = false; e.printStackTrace(); } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } logger.debug("received request, req = " + req); if (req == null) { goon = false; break; } if (!(req instanceof GBTransportMessReq)) { goon = false; break; } // find pair and manage termination status logger.debug("find pair"); while (!pairlist.hasNext()) { // wait if (!finner.hasJobs() && !pairlist.hasNext()) { goon = false; break; } try { sleeps++; //if (sleeps % 10 == 0) { logger.info("waiting for reducers, remaining = " + finner.getJobs()); //} Thread.sleep(100); } catch (InterruptedException e) { goon = false; break; } } if (!pairlist.hasNext() && !finner.hasJobs()) { logger.info("termination detection: no pairs and no jobs left"); goon = false; break; //continue; //break? } finner.notIdle(); // before pairlist get!! pair = pairlist.removeNext(); // send pair to client, even if null if (debug) { logger.info("active count = " + active.get()); logger.info("send pair = " + pair); } GBTransportMess msg = null; if (pair != null) { msg = new GBTransportMessPairIndex(pair); } else { msg = new GBTransportMess(); //not End(); at this time // goon ?= false; } try { red++; pairChannel.send(pairTag, msg); int a = active.getAndIncrement(); } catch (IOException e) { e.printStackTrace(); goon = false; break; } //logger.debug("#distributed list = " + theList.size()); } logger.info("terminated, send " + red + " reduction pairs"); /* * send end mark to clients */ logger.debug("send end"); try { for (int i = 0; i < threadsPerNode; i++) { // -1 pairChannel.send(pairTag, new GBTransportMessEnd()); } logger.info("sent end to clients"); // send also end to receiver, no more //pairChannel.send(resultTag, new GBTransportMessEnd(), engine.Rank()); } catch (IOException e) { if (logger.isDebugEnabled()) { e.printStackTrace(); } } int d = active.get(); if ( d > 0 ) { logger.info("remaining active tasks = " + d); } receiver.terminate(); //logger.info("terminated, send " + red + " reduction pairs"); pairChannel.close(); logger.info("redServ pairChannel.close()"); finner.release(); } } /** * Distributed server receiving worker thread. * @param coefficient type */ class HybridReducerReceiverMPJ> extends Thread { public static final Logger logger = Logger.getLogger(HybridReducerReceiverMPJ.class); public final boolean debug = logger.isDebugEnabled(); private final DistHashTableMPJ> theList; private final PairList pairlist; private final MPJChannel pairChannel; final int rank; private final Terminator finner; //private final int threadsPerNode; private final AtomicInteger active; private volatile boolean goon; /** * Message tag for results. */ public static final int resultTag = GroebnerBaseDistributedHybridMPJ.resultTag; /** * Message tag for acknowledgments. */ public static final int ackTag = GroebnerBaseDistributedHybridMPJ.ackTag; /** * Constructor. * @param r MPJ rank of partner. * @param fin terminator * @param a active remote tasks count * @param pc tagged socket channel * @param dl distributed hash table * @param L ordered pair list */ HybridReducerReceiverMPJ(int r, Terminator fin, AtomicInteger a, MPJChannel pc, DistHashTableMPJ> dl, PairList L) { rank = r; active = a; //threadsPerNode = tpn; finner = fin; pairChannel = pc; theList = dl; pairlist = L; goon = true; //logger.info("reducer server created " + this); } /** * Work loop. * @see java.lang.Thread#run() */ @Override public void run() { //Pair pair = null; GenPolynomial H = null; int red = 0; int polIndex = -1; //Integer senderId; // obsolete // while more requests while (goon) { // receive request logger.debug("receive result"); //senderId = null; Object rh = null; try { rh = pairChannel.receive(resultTag); int i = active.getAndDecrement(); //} catch (InterruptedException e) { //goon = false; ////e.printStackTrace(); ////?? finner.initIdle(1); //break; } catch (IOException e) { e.printStackTrace(); goon = false; finner.initIdle(1); break; } catch (ClassNotFoundException e) { e.printStackTrace(); goon = false; finner.initIdle(1); break; } logger.info("received result"); if (rh == null) { if (this.isInterrupted()) { goon = false; finner.initIdle(1); break; } //finner.initIdle(1); } else if (rh instanceof GBTransportMessEnd) { // should only happen from server logger.info("received GBTransportMessEnd"); goon = false; //?? finner.initIdle(1); break; } else if (rh instanceof GBTransportMessPoly) { // update pair list red++; GBTransportMessPoly mpi = (GBTransportMessPoly) rh; H = mpi.pol; //senderId = mpi.threadId; if (H != null) { if (logger.isInfoEnabled()) { // debug logger.info("H = " + H.leadingExpVector()); } if (!H.isZERO()) { if (H.isONE()) { polIndex = pairlist.putOne(); //GenPolynomial nn = theList.putWait(Integer.valueOf(polIndex), H); //goon = false; must wait for other clients //finner.initIdle(1); //break; } else { polIndex = pairlist.put(H); // use putWait ? but still not all distributed //GenPolynomial nn = theList.putWait(Integer.valueOf(polIndex), H); } } } } // only after recording in pairlist ! finner.initIdle(1); try { pairChannel.send(ackTag, new GBTransportMess()); logger.debug("send acknowledgement"); } catch (IOException e) { e.printStackTrace(); goon = false; break; } } // end while goon = false; logger.info("terminated, received " + red + " reductions"); } /** * Terminate. */ public void terminate() { goon = false; try { this.join(); //this.interrupt(); } catch (InterruptedException e) { // unfug Thread.currentThread().interrupt(); } logger.info("terminate end"); } } /** * Distributed clients reducing worker threads. */ class HybridReducerClientMPJ> implements Runnable { private static final Logger logger = Logger.getLogger(HybridReducerClientMPJ.class); public final boolean debug = logger.isDebugEnabled(); private final MPJChannel pairChannel; private final DistHashTableMPJ> theList; private final ReductionPar red; //private final int threadsPerNode; /* * Identification number for this thread. */ //public final Integer threadId; // obsolete /** * Message tag for pairs. */ public static final int pairTag = GroebnerBaseDistributedHybridMPJ.pairTag; /** * Message tag for results. */ public static final int resultTag = GroebnerBaseDistributedHybridMPJ.resultTag; /** * Message tag for acknowledgments. */ public static final int ackTag = GroebnerBaseDistributedHybridMPJ.ackTag; /** * Constructor. * @param tc tagged socket channel * @param dl distributed hash table */ HybridReducerClientMPJ(MPJChannel tc, DistHashTableMPJ> dl) { //this.threadsPerNode = tpn; pairChannel = tc; //threadId = 100 + tid; // keep distinct from other tags theList = dl; red = new ReductionPar(); } /** * Work loop. * @see java.lang.Runnable#run() */ //JAVA6only: @Override public void run() { if (debug) { logger.info("pairChannel = " + pairChannel + " reducer client running"); } Pair pair = null; GenPolynomial pi, pj, ps; GenPolynomial S; GenPolynomial H = null; //boolean set = false; boolean goon = true; boolean doEnd = true; int reduction = 0; //int sleeps = 0; Integer pix, pjx, psx; while (goon) { /* protocol: * request pair, process pair, send result, receive acknowledgment */ // pair = (Pair) pairlist.removeNext(); Object req = new GBTransportMessReq(); logger.debug("send request = " + req); try { pairChannel.send(pairTag, req); } catch (IOException e) { goon = false; if (debug) { e.printStackTrace(); } logger.info("receive pair, exception "); break; } logger.debug("receive pair, goon = " + goon); doEnd = true; Object pp = null; try { pp = pairChannel.receive(pairTag); //} catch (InterruptedException e) { //goon = false; //e.printStackTrace(); } catch (IOException e) { goon = false; if (debug) { e.printStackTrace(); } break; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } if (debug) { logger.info("received pair = " + pp); } H = null; if (pp == null) { // should not happen continue; } if (pp instanceof GBTransportMessEnd) { goon = false; //doEnd = false; // bug continue; } if (pp instanceof GBTransportMessPair || pp instanceof GBTransportMessPairIndex) { pi = pj = ps = null; if (pp instanceof GBTransportMessPair) { pair = ((GBTransportMessPair) pp).pair; if (pair != null) { pi = pair.pi; pj = pair.pj; //logger.debug("pair: pix = " + pair.i // + ", pjx = " + pair.j); } } if (pp instanceof GBTransportMessPairIndex) { pix = ((GBTransportMessPairIndex) pp).i; pjx = ((GBTransportMessPairIndex) pp).j; psx = ((GBTransportMessPairIndex) pp).s; pi = theList.getWait(pix); pj = theList.getWait(pjx); ps = theList.getWait(psx); //logger.info("pix = " + pix + ", pjx = " +pjx + ", psx = " +psx); } if (pi != null && pj != null) { S = red.SPolynomial(pi, pj); //System.out.println("S = " + S); logger.info("ht(S) = " + S.leadingExpVector()); if (S.isZERO()) { // pair.setZero(); does not work in dist H = S; } else { if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(theList, S); reduction++; if (H.isZERO()) { // pair.setZero(); does not work in dist } else { H = H.monic(); if (logger.isInfoEnabled()) { logger.info("ht(H) = " + H.leadingExpVector()); } } } } else { logger.info("pi = " + pi + ", pj = " + pj + ", ps = " + ps); } } if (pp instanceof GBTransportMess) { logger.debug("null pair results in null H poly"); } // send H or must send null, if not at end if (debug) { logger.debug("#distributed list = " + theList.size()); logger.debug("send H polynomial = " + H); } try { pairChannel.send(resultTag, new GBTransportMessPoly(H)); //,threadId)); doEnd = false; } catch (IOException e) { goon = false; e.printStackTrace(); } logger.debug("done send poly message of " + pp); try { pp = pairChannel.receive(ackTag); //} catch (InterruptedException e) { //goon = false; //e.printStackTrace(); } catch (IOException e) { goon = false; if (debug) { e.printStackTrace(); } break; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } if (!(pp instanceof GBTransportMess)) { logger.error("invalid acknowledgement " + pp); } logger.debug("received acknowledgment " + pp); } logger.info("terminated, done " + reduction + " reductions"); if (doEnd) { try { pairChannel.send(resultTag, new GBTransportMessEnd()); } catch (IOException e) { //e.printStackTrace(); } logger.info("terminated, send done"); } } } jas-2.5/mpj/src/edu/jas/gb/GroebnerBaseDistHybridMPJTest.java0000644000175000017500000001453612067405420024251 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistHybridMPJTest.java 4335 2012-12-28 21:11:45Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import mpi.Comm; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.kern.MPJEngine; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Distributed GroebnerBase MPJ tests with JUnit. * @author Heinz Kredel */ public class GroebnerBaseDistHybridMPJTest extends TestCase { protected static Comm engine; boolean mpjBug = true; // bug after cancel recv /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); engine = MPJEngine.getCommunicator(args); junit.textui.TestRunner.run(suite()); engine.Barrier(); MPJEngine.terminate(); //ComputerThreads.terminate(); } /** * Constructs a GroebnerBaseDistHybridMPJTest object. * @param name String. */ public GroebnerBaseDistHybridMPJTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBaseDistHybridMPJTest.class); return suite; } int port = 4711; String host = "localhost"; GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bbseq; GroebnerBaseDistributedHybridMPJ bbdist; GroebnerBaseDistributedHybridMPJ bbdists; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 4; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads; int threadsPerNode = 3; @Override protected void setUp() { threads = engine.Size(); BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bbseq = new GroebnerBaseSeq(); bbdist = new GroebnerBaseDistributedHybridMPJ(threads,threadsPerNode); //bbdists = new GroebnerBaseDistributedHybridMPJ(threads,threadsPerNode, new OrderedSyzPairlist()); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bbseq = null; bbdist.terminate(); bbdist = null; //bbdists.terminate(); bbdists = null; ComputerThreads.terminate(); } /** * Test distributed GBase. */ public void onlyOnetestDistributedGBase() { L = new ArrayList>(); if (engine.Rank() == 0) { a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); } if (engine.Rank() == 0) { L.add(a); L.add(b); System.out.println("L = " + L ); } L = bbdist.GB(L); if (engine.Rank() == 0) { System.out.println("L0 = " + L ); assertTrue("isGB( { a } )", bbseq.isGB(L)); L.add(b); } if (mpjBug) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } return; } L = bbdist.GB(L); if (engine.Rank() == 0) { System.out.println("L1 = " + L ); assertTrue("isGB( { a, b } )", bbseq.isGB(L)); L.add(c); } L = bbdist.GB(L); if (engine.Rank() == 0) { System.out.println("L2 = " + L ); assertTrue("isGB( { a, b, c } )", bbseq.isGB(L)); L.add(d); } L = bbdist.GB(L); if (engine.Rank() == 0) { System.out.println("L3 = " + L ); assertTrue("isGB( { a, b, c, d } )", bbseq.isGB(L)); L.add(e); } L = bbdist.GB(L); if (engine.Rank() == 0) { System.out.println("L4 = " + L ); assertTrue("isGB( { a, b, c, d, e } )", bbseq.isGB(L)); } else { System.out.println("rank = " + engine.Rank() ); } } /** * Test Trinks7 GBase. */ public void testTrinks7GBase() { List> Fl; long t = 0; if (engine.Rank() == 0) { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } System.out.println("F = " + F); Fl = F.list; t = System.currentTimeMillis(); } else { Fl = null; } G = bbdist.GB(Fl); if (engine.Rank() == 0) { t = System.currentTimeMillis() - t; assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); //PolynomialList trinks = new PolynomialList(F.ring, G); System.out.println("G = " + G); System.out.println("executed in " + t + " milliseconds"); } else { assertTrue("G == null: ", G == null); } } } jas-2.5/mpj/src/edu/jas/gb/GroebnerBaseDistMPJTest.java0000644000175000017500000001374612041032404023077 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistMPJTest.java 4264 2012-10-21 17:46:44Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import mpi.Comm; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.kern.MPJEngine; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Distributed GroebnerBase MPJ tests with JUnit. * @author Heinz Kredel */ public class GroebnerBaseDistMPJTest extends TestCase { protected static Comm engine; boolean mpjBug = true; // bug after cancel recv /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); engine = MPJEngine.getCommunicator(args); junit.textui.TestRunner.run(suite()); engine.Barrier(); MPJEngine.terminate(); //ComputerThreads.terminate(); } /** * Constructs a GroebnerBaseDistMPJTest object. * @param name String. */ public GroebnerBaseDistMPJTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBaseDistMPJTest.class); return suite; } int port = 4711; String host = "localhost"; GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bbseq; GroebnerBaseDistributedMPJ bbdist; GroebnerBaseDistributedMPJ bbdists; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 4; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads; @Override protected void setUp() { threads = engine.Size(); BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bbseq = new GroebnerBaseSeq(); bbdists = new GroebnerBaseDistributedMPJ(threads); bbdist = new GroebnerBaseDistributedMPJ(threads, new OrderedSyzPairlist()); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bbseq = null; bbdist.terminate(); bbdist = null; bbdists.terminate(); bbdists = null; ComputerThreads.terminate(); } /** * Test distributed GBase. */ public void testDistributedGBase() { L = new ArrayList>(); if (engine.Rank() == 0) { a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); } if (engine.Rank() == 0) { assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); } L = bbdist.GB(L); if (engine.Rank() == 0) { assertTrue("isGB( { a } )", bbseq.isGB(L)); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); //System.out.println("L = " + L.size() ); } if (mpjBug) { return; } L = bbdist.GB(L); if (engine.Rank() == 0) { assertTrue("isGB( { a, b } )", bbseq.isGB(L)); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); } L = bbdist.GB(L); if (engine.Rank() == 0) { assertTrue("isGB( { a, b, c } )", bbseq.isGB(L)); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); } L = bbdist.GB(L); if (engine.Rank() == 0) { assertTrue("isGB( { a, b, c, d } )", bbseq.isGB(L)); assertTrue("not isZERO( e )", !e.isZERO()); L.add(e); } L = bbdist.GB(L); if (engine.Rank() == 0) { assertTrue("isGB( { a, b, c, d, e } )", bbseq.isGB(L)); } } /** * Test Trinks7 GBase. */ public void testTrinks7GBase() { List> Fl; long t = 0; if (engine.Rank() == 0) { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } System.out.println("F = " + F); Fl = F.list; t = System.currentTimeMillis(); } else { Fl = null; } G = bbdists.GB(Fl); if (engine.Rank() == 0) { t = System.currentTimeMillis() - t; assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); //PolynomialList trinks = new PolynomialList(F.ring, G); System.out.println("G = " + G); System.out.println("executed in " + t + " milliseconds"); } } } jas-2.5/mpj/src/edu/jas/gb/GroebnerBaseDistributedMPJ.java0000644000175000017500000005524312067562026023634 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistributedMPJ.java 4337 2012-12-29 12:37:43Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.concurrent.Semaphore; import mpi.Comm; import org.apache.log4j.Logger; import edu.jas.kern.MPJEngine; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.DistHashTableMPJ; import edu.jas.util.MPJChannel; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; /** * Groebner Base distributed algorithm with MPJ. Implements a distributed memory * parallel version of Groebner bases. Using MPJ and pairlist class, distributed * tasks do reduction. * @param coefficient type * @author Heinz Kredel */ public class GroebnerBaseDistributedMPJ> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBaseDistributedMPJ.class); /** * Number of threads to use. */ protected final int threads; /** * Default number of threads. */ public static final int DEFAULT_THREADS = 2; /* * Pool of threads to use. Note: No ComputerThreads for one node * tests */ protected transient final ThreadPool pool; /* * Underlying MPJ engine. */ protected transient final Comm engine; /** * Constructor. */ public GroebnerBaseDistributedMPJ() { this(DEFAULT_THREADS); } /** * Constructor. * @param threads number of threads to use. */ public GroebnerBaseDistributedMPJ(int threads) { this(threads, new ThreadPool(threads)); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. */ public GroebnerBaseDistributedMPJ(int threads, ThreadPool pool) { this(threads, pool, new OrderedPairlist()); } /** * Constructor. * @param threads number of threads to use. * @param pl pair selection strategy */ public GroebnerBaseDistributedMPJ(int threads, PairList pl) { this(threads, new ThreadPool(threads), pl); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param pl pair selection strategy */ public GroebnerBaseDistributedMPJ(int threads, ThreadPool pool, PairList pl) { super(new ReductionPar(), pl); this.engine = MPJEngine.getCommunicator(); int size = engine.Size(); if (size < 2) { throw new IllegalArgumentException("Minimal 2 MPJ processes required, not " + size); } if (threads != size || pool.getNumber() != size) { throw new IllegalArgumentException("threads != size: " + threads + " != " + size + ", #pool " + pool.getNumber()); } this.threads = threads; this.pool = pool; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { if (pool == null) { return; } pool.terminate(); } /** * Distributed Groebner base. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs or on * MPJ client part. */ public List> GB(int modv, List> F) { if (engine.Rank() == 0) { return GBmaster(modv, F); } pool.terminate(); // not used on clients try { clientPart(0); } catch (IOException e) { logger.info("clientPart: " + e); e.printStackTrace(); } return null; } /** * Distributed Groebner base, part for MPJ master. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs. */ public List> GBmaster(int modv, List> F) { List> G = new ArrayList>(); GenPolynomial p; PairList pairlist = null; boolean oneInGB = false; int l = F.size(); int unused = 0; ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { oneInGB = true; G.clear(); G.add(p); //return G; must signal termination to others } if (!oneInGB) { G.add(p); } if (pairlist == null) { pairlist = strategy.create(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // theList not updated here if (p.isONE()) { unused = pairlist.putOne(); } else { unused = pairlist.put(p); } } else { l--; } } //if (l <= 1) { //return G; must signal termination to others //} logger.debug("initialize DHT, done pairlist: " + unused); DistHashTableMPJ> theList = new DistHashTableMPJ>( engine); theList.init(); List> al = pairlist.getList(); for (int i = 0; i < al.size(); i++) { // no wait required GenPolynomial nn = theList.put(Integer.valueOf(i), al.get(i)); if (nn != null) { logger.info("double polynomials " + i + ", nn = " + nn + ", al(i) = " + al.get(i)); } } Terminator fin = new Terminator(threads - 1); MPJReducerServer R; for (int i = 1; i < threads; i++) { logger.debug("addJob " + i + " of " + threads); R = new MPJReducerServer(i, fin, engine, theList, pairlist); pool.addJob(R); } logger.debug("main loop waiting"); fin.waitDone(); int ps = theList.size(); logger.info("#distributed list = " + ps); // make sure all polynomials arrived: not needed in master // G = (ArrayList)theList.values(); G = pairlist.getList(); if (ps != G.size()) { logger.info("#distributed list = " + theList.size() + " #pairlist list = " + G.size()); } long time = System.currentTimeMillis(); List> Gp = minimalGB(G); // not jet distributed but threaded time = System.currentTimeMillis() - time; logger.debug("parallel gbmi = " + time); G = Gp; logger.info("theList.terminate()"); theList.terminate(); logger.info("end" + pairlist); return G; } /** * GB distributed client. * @param rank of the MPJ where the server runs on. * @throws IOException */ public void clientPart(int rank) throws IOException { if (rank != 0) { throw new UnsupportedOperationException("only master at rank 0 implemented: " + rank); } Comm engine = MPJEngine.getCommunicator(); MPJChannel chan = new MPJChannel(engine, rank); DistHashTableMPJ> theList = new DistHashTableMPJ>(); theList.init(); MPJReducerClient R = new MPJReducerClient(chan, theList); R.run(); theList.terminate(); return; } /** * Minimal ordered groebner basis. * @param Fp a Groebner base. * @return a reduced Groebner base of Fp. */ @Override public List> minimalGB(List> Fp) { GenPolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiMPJReducerServer[] mirs = (MiMPJReducerServer[]) new MiMPJReducerServer[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new MiMPJReducerServer(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } } /** * Distributed server reducing worker threads. * @param coefficient type */ class MPJReducerServer> implements Runnable { /* * Termination detection coordinator. */ private final Terminator finaler; /* * Underlying MPJ engine. */ protected transient final Comm engine; /* * MPJ channel. */ private MPJChannel pairChannel; /* * GB rank. */ final int rank; /* * Distributed HashTable of polynomials. */ private final DistHashTableMPJ> theList; /* * Critical pair list of polynomials. */ private final PairList pairlist; private static final Logger logger = Logger.getLogger(MPJReducerServer.class); /** * Constructor. * @param r MPJ rank of partner. * @param fin termination coordinator to use. * @param e MPJ communicator to use. * @param dl DHT to use. * @param L pair selection strategy */ MPJReducerServer(int r, Terminator fin, Comm e, DistHashTableMPJ> dl, PairList L) { rank = r; finaler = fin; engine = e; theList = dl; pairlist = L; } /** * Main method. */ public void run() { //logger.debug("reducer server running: " + this); try { pairChannel = new MPJChannel(engine, rank); } catch (IOException e) { e.printStackTrace(); return; } if (logger.isInfoEnabled()) { logger.info("reducer server running: pairChannel = " + pairChannel); } Pair pair; GenPolynomial H = null; boolean set = false; boolean goon = true; int polIndex = -1; int red = 0; int sleeps = 0; // while more requests while (goon) { // receive request logger.debug("receive request"); Object req = null; try { req = pairChannel.receive(); } catch (IOException e) { goon = false; e.printStackTrace(); } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } //logger.debug("received request, req = " + req); if (req == null) { goon = false; break; } if (!(req instanceof GBTransportMessReq)) { goon = false; break; } // find pair logger.debug("find pair"); while (!pairlist.hasNext()) { // wait if (!set) { finaler.beIdle(); set = true; } if (!finaler.hasJobs() && !pairlist.hasNext()) { goon = false; break; } try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } Thread.sleep(100); } catch (InterruptedException e) { goon = false; break; } } if (!pairlist.hasNext() && !finaler.hasJobs()) { goon = false; break; //continue; //break? } if (set) { set = false; finaler.notIdle(); } pair = pairlist.removeNext(); /* * send pair to client, receive H */ logger.debug("send pair = " + pair); GBTransportMess msg = null; if (pair != null) { msg = new GBTransportMessPairIndex(pair); } else { msg = new GBTransportMess(); //End(); // goon ?= false; } try { pairChannel.send(msg); } catch (IOException e) { e.printStackTrace(); goon = false; break; } logger.debug("#distributed list = " + theList.size()); Object rh = null; try { rh = pairChannel.receive(); } catch (IOException e) { e.printStackTrace(); goon = false; break; } catch (ClassNotFoundException e) { e.printStackTrace(); goon = false; break; } //logger.debug("received H polynomial"); if (rh == null) { if (pair != null) { pair.setZero(); } } else if (rh instanceof GBTransportMessPoly) { // update pair list red++; H = ((GBTransportMessPoly) rh).pol; if (logger.isDebugEnabled()) { logger.debug("H = " + H); } if (H == null) { if (pair != null) { pair.setZero(); } } else { if (H.isZERO()) { pair.setZero(); } else { if (H.isONE()) { polIndex = pairlist.putOne(); //GenPolynomial nn = theList.putWait(Integer.valueOf(polIndex), H); goon = false; break; } polIndex = pairlist.put(H); // use putWait ? but still not all distributed //GenPolynomial nn = theList.putWait(Integer.valueOf(polIndex), H); } } } } logger.info("terminated, done " + red + " reductions"); /* * send end mark to client */ logger.debug("send end"); try { pairChannel.send(new GBTransportMessEnd()); } catch (IOException e) { if (logger.isDebugEnabled()) { e.printStackTrace(); } } finaler.beIdle(); pairChannel.close(); } } /** * Distributed clients reducing worker threads. */ class MPJReducerClient> implements Runnable { private final MPJChannel pairChannel; private final DistHashTableMPJ> theList; private final ReductionPar red; private static final Logger logger = Logger.getLogger(MPJReducerClient.class); /** * Constructor. * @param pc MPJ communication channel. * @param dl DHT to use. */ MPJReducerClient(MPJChannel pc, DistHashTableMPJ> dl) { pairChannel = pc; theList = dl; red = new ReductionPar(); } /** * Main run method. */ public void run() { logger.info("pairChannel = " + pairChannel + " reducer client running"); Pair pair = null; GenPolynomial pi, pj, ps; GenPolynomial S; GenPolynomial H = null; //boolean set = false; boolean goon = true; int reduction = 0; //int sleeps = 0; Integer pix, pjx, psx; while (goon) { /* protocol: * request pair, process pair, send result */ // pair = (Pair) pairlist.removeNext(); Object req = new GBTransportMessReq(); logger.debug("send request"); try { pairChannel.send(req); } catch (IOException e) { goon = false; e.printStackTrace(); break; } logger.debug("receive pair, goon"); Object pp = null; try { pp = pairChannel.receive(); } catch (IOException e) { goon = false; if (logger.isDebugEnabled()) { e.printStackTrace(); } break; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } if (logger.isDebugEnabled()) { logger.debug("received pair = " + pp); } H = null; if (pp == null) { // should not happen continue; } if (pp instanceof GBTransportMessEnd) { goon = false; continue; } if (pp instanceof GBTransportMessPair || pp instanceof GBTransportMessPairIndex) { pi = pj = ps = null; if (pp instanceof GBTransportMessPair) { pair = ((GBTransportMessPair) pp).pair; if (pair != null) { pi = pair.pi; pj = pair.pj; //logger.debug("pair: pix = " + pair.i // + ", pjx = " + pair.j); } } if (pp instanceof GBTransportMessPairIndex) { pix = ((GBTransportMessPairIndex) pp).i; pjx = ((GBTransportMessPairIndex) pp).j; psx = ((GBTransportMessPairIndex) pp).s; pi = theList.getWait(pix); pj = theList.getWait(pjx); ps = theList.getWait(psx); //logger.info("pix = " + pix + ", pjx = " +pjx + ", psx = " +psx); } if (pi != null && pj != null) { S = red.SPolynomial(pi, pj); //System.out.println("S = " + S); if (S.isZERO()) { // pair.setZero(); does not work in dist } else { if (logger.isDebugEnabled()) { logger.info("ht(S) = " + S.leadingExpVector()); } H = red.normalform(theList, S); reduction++; if (H.isZERO()) { // pair.setZero(); does not work in dist } else { H = H.monic(); if (logger.isInfoEnabled()) { logger.info("ht(H) = " + H.leadingExpVector()); } } } } } // send H or must send null if (logger.isDebugEnabled()) { logger.debug("#distributed list = " + theList.size()); logger.debug("send H polynomial = " + H); } try { pairChannel.send(new GBTransportMessPoly(H)); } catch (IOException e) { goon = false; e.printStackTrace(); } } logger.info("terminated, done " + reduction + " reductions"); pairChannel.close(); } } /** * Distributed server reducing worker threads for minimal GB Not jet distributed * but threaded. */ class MiMPJReducerServer> implements Runnable { private final List> G; private GenPolynomial H; private final Semaphore done = new Semaphore(0); private final Reduction red; private static final Logger logger = Logger.getLogger(MiMPJReducerServer.class); /** * Constructor. * @param G polynomial list. * @param p polynomial. */ MiMPJReducerServer(List> G, GenPolynomial p) { this.G = G; H = p; red = new ReductionPar(); } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenPolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException e) { } return H; } /** * Main run method. */ public void run() { if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = red.normalform(G, H); //mod done.release(); //done.V(); if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } jas-2.5/mpj/machines0000644000175000017500000000001212027670524014641 0ustar giovannigiovannilocalhost jas-2.5/mpj/.gitignore0000644000175000017500000000001512026050556015116 0ustar giovannigiovanni/test /*.jar jas-2.5/build.xml0000644000175000017500000002256512043320732014172 0ustar giovannigiovanni jas-2.5/acknowledge.html0000644000175000017500000000276611547440062015532 0ustar giovannigiovanni Acknowledgements

Acknowledgements

Since 2008 the development of the API design and the Jython scripting interface was done in cooperation with Raphael Jolly. Our joint developments have also been incorporated in a successor "ScAS" of his system jscl-meditor.

The development of JAS would not have been possible without various discussions with our colleagues, their constant support and their encouragement of our work. In particular we are indebted to Thomas Becker, Wolfgang K. Seiler, Thomas Sturm, Axel Kramer, Jaime Gutierrez, Sherm Ostrowsky, Ted Kosan, Yosuke Sato, Peter Horn, Dongming Wang and Georg Thimm for various discussions on the design of and the requirements of typed object oriented computer algebra software.


Heinz Kredel

Last modified: Fri Apr 8 00:51:23 CEST 2011

jas-2.5/svn_change.log0000644000175000017500000051731212140140264015164 0ustar giovannigiovanni------------------------------------------------------------------------ r4408 | kredel | 2013-04-30 12:48:20 +0200 (Di, 30. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/SolvableIdeal.java cosmetic and small fixes ------------------------------------------------------------------------ r4407 | kredel | 2013-04-30 12:34:27 +0200 (Di, 30. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/Residue.java M /trunk/src/edu/jas/application/ResidueRing.java M /trunk/src/edu/jas/application/SolvableResidue.java M /trunk/src/edu/jas/application/SolvableResidueRing.java cosmetic and small fixes ------------------------------------------------------------------------ r4406 | kredel | 2013-04-30 12:07:39 +0200 (Di, 30. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbmod/SolvableQuotient.java M /trunk/src/edu/jas/gbmod/SolvableQuotientRing.java M /trunk/src/edu/jas/ufd/Quotient.java M /trunk/src/edu/jas/ufd/QuotientRing.java cosmetic and small fixes ------------------------------------------------------------------------ r4400 | kredel | 2013-04-29 16:58:52 +0200 (Mo, 29. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gbmod/SolvableQuotientTest.java cleanup ------------------------------------------------------------------------ r4399 | kredel | 2013-04-29 15:03:52 +0200 (Mo, 29. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/SolvableResidueRing.java M /trunk/trc/edu/jas/application/SolvableResidueTest.java cosmetic ------------------------------------------------------------------------ r4398 | kredel | 2013-04-29 14:55:36 +0200 (Mo, 29. Apr 2013) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/application/SolvableResidue.java A /trunk/src/edu/jas/application/SolvableResidueRing.java A /trunk/trc/edu/jas/application/SolvableResidueTest.java add solvable residues ------------------------------------------------------------------------ r4397 | kredel | 2013-04-29 14:54:38 +0200 (Mo, 29. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/ResidueRing.java M /trunk/src/edu/jas/application/SolvableIdeal.java avoid constant generators ------------------------------------------------------------------------ r4396 | kredel | 2013-04-29 11:50:50 +0200 (Mo, 29. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbmod/SolvableQuotientRing.java add experimantal gcd ------------------------------------------------------------------------ r4395 | kredel | 2013-04-29 11:40:04 +0200 (Mo, 29. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/Residue.java M /trunk/src/edu/jas/application/SolvableIdeal.java M /trunk/src/edu/jas/gbmod/SolvableQuotient.java cosmetic ------------------------------------------------------------------------ r4394 | kredel | 2013-04-29 10:39:13 +0200 (Mo, 29. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbmod/SolvableSyzygyAbstract.java fix doc string ------------------------------------------------------------------------ r4393 | kredel | 2013-04-28 21:57:37 +0200 (So, 28. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbmod/SolvableQuotient.java M /trunk/src/edu/jas/gbmod/SolvableSyzygyAbstract.java M /trunk/trc/edu/jas/gbmod/SolvableQuotientTest.java cleanup and avoid Ore conds ------------------------------------------------------------------------ r4392 | kredel | 2013-04-28 17:47:13 +0200 (So, 28. Apr 2013) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/gbmod/SolvableQuotient.java A /trunk/src/edu/jas/gbmod/SolvableQuotientRing.java A /trunk/trc/edu/jas/gbmod/SolvableQuotientTest.java add solvable quotient ring ------------------------------------------------------------------------ r4391 | kredel | 2013-04-28 17:46:54 +0200 (So, 28. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomial.java warn to debug ------------------------------------------------------------------------ r4390 | kredel | 2013-04-28 17:46:19 +0200 (So, 28. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbmod/SolvableSyzygyAbstract.java M /trunk/trc/edu/jas/gbmod/SolvableSyzygyTest.java compute Ore condition ------------------------------------------------------------------------ r4389 | kredel | 2013-04-27 23:07:05 +0200 (Sa, 27. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/TermOrder.java M /trunk/trc/edu/jas/application/SolvableIdealTest.java cleanup ------------------------------------------------------------------------ r4388 | kredel | 2013-04-27 21:38:16 +0200 (Sa, 27. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/SolvableIdeal.java M /trunk/src/edu/jas/poly/GenSolvablePolynomialRing.java M /trunk/src/edu/jas/poly/PolynomialList.java M /trunk/src/edu/jas/poly/RelationTable.java M /trunk/src/edu/jas/poly/WordFactory.java M /trunk/trc/edu/jas/application/SolvableIdealTest.java cleanup and rabinowich only for commutative case ------------------------------------------------------------------------ r4387 | kredel | 2013-04-27 19:58:06 +0200 (Sa, 27. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/examples/u_sl_2.py fix typo ------------------------------------------------------------------------ r4386 | kredel | 2013-04-27 18:17:58 +0200 (Sa, 27. Apr 2013) | 1 Zeile Geänderte Pfade: A /trunk/trc/edu/jas/application/SolvableIdealTest.java unit tests for solvable ideals ------------------------------------------------------------------------ r4385 | kredel | 2013-04-27 15:34:38 +0200 (Sa, 27. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/SolvableIdeal.java M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java M /trunk/src/edu/jas/gb/SolvableGroebnerBase.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseAbstract.java M /trunk/src/edu/jas/poly/PolynomialList.java code beautifying with eclipse ------------------------------------------------------------------------ r4384 | kredel | 2013-04-27 15:20:56 +0200 (Sa, 27. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/SolvableIdeal.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseAbstract.java cleanup and filled missing methods ------------------------------------------------------------------------ r4383 | kredel | 2013-04-27 12:42:03 +0200 (Sa, 27. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/SolvableGroebnerBaseAbstract.java M /trunk/src/edu/jas/poly/PolynomialList.java case solvable ideals ------------------------------------------------------------------------ r4382 | kredel | 2013-04-27 12:41:24 +0200 (Sa, 27. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb M /trunk/examples/solv_ore.py M /trunk/examples/solv_ore.rb method to compute univariate polynomials ------------------------------------------------------------------------ r4381 | kredel | 2013-04-27 11:57:28 +0200 (Sa, 27. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/examples/exterior.py M /trunk/examples/solv_ore.py M /trunk/examples/solvable.py M /trunk/examples/syzsolv.py M /trunk/examples/u_2_wa_1.py M /trunk/examples/u_sl_2.py M /trunk/examples/u_sl_2_e.py M /trunk/examples/u_sl_2_f.py M /trunk/examples/u_sl_2_wa_1.py M /trunk/examples/u_sl_3.py M /trunk/examples/u_sl_3_prod.py M /trunk/examples/u_so_3.py M /trunk/examples/wa_1.py M /trunk/examples/wa_32.py M /trunk/examples/wa_32_syz.py fix names for SolvableIdeal ------------------------------------------------------------------------ r4380 | kredel | 2013-04-27 11:42:41 +0200 (Sa, 27. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/examples/exterior.rb M /trunk/examples/jas.py M /trunk/examples/jas.rb M /trunk/examples/solvable.rb M /trunk/examples/syzsolv.rb M /trunk/examples/u_sl_2.rb M /trunk/examples/u_sl_2_e.rb M /trunk/examples/u_sl_3.rb M /trunk/examples/u_sl_3_prod.rb fix names for SolvableIdeal ------------------------------------------------------------------------ r4379 | kredel | 2013-04-26 22:08:28 +0200 (Fr, 26. Apr 2013) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/application/SolvableIdeal.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseAbstract.java M /trunk/src/edu/jas/poly/PolynomialList.java ideals of solvable polynomial rings ------------------------------------------------------------------------ r4378 | kredel | 2013-04-26 18:50:33 +0200 (Fr, 26. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/SolvableGroebnerBaseAbstract.java M /trunk/src/edu/jas/poly/PolyUtil.java solvable univariate polynomials ------------------------------------------------------------------------ r4377 | kredel | 2013-04-26 17:21:21 +0200 (Fr, 26. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/ufd/GCDHenselTest.java add example ------------------------------------------------------------------------ r4376 | kredel | 2013-04-26 17:01:34 +0200 (Fr, 26. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gb/GroebnerBaseDistECTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseDistHybridECTest.java improve failure cause detection ------------------------------------------------------------------------ r4375 | kredel | 2013-04-26 17:00:36 +0200 (Fr, 26. Apr 2013) | 1 Zeile Geänderte Pfade: A /trunk/examples/solv_ore.py A /trunk/examples/solv_ore.rb new examples ------------------------------------------------------------------------ r4374 | kredel | 2013-04-26 16:59:39 +0200 (Fr, 26. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb cleanup inject in global scope and add for solvable polynomial rings ------------------------------------------------------------------------ r4373 | kredel | 2013-04-20 21:53:37 +0200 (Sa, 20. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/examples/word_solvable_trans.rb fix constant names ------------------------------------------------------------------------ r4372 | kredel | 2013-04-20 21:53:08 +0200 (Sa, 20. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb improves / fixes for jruby 1.7.x ------------------------------------------------------------------------ r4371 | kredel | 2013-04-14 22:57:13 +0200 (So, 14. Apr 2013) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/mpj/src/edu/jas/util/MPJChannel.java global sync also for send ------------------------------------------------------------------------ r4368 | kredel | 2013-03-13 23:17:46 +0100 (Mi, 13. Mär 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/GBAlgorithmBuilder.java fix for Java 6 ------------------------------------------------------------------------ r4366 | kredel | 2013-02-03 18:56:46 +0100 (So, 03. Feb 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/FactorAbstract.java undo variable order optimization ------------------------------------------------------------------------ r4365 | kredel | 2013-02-03 15:07:02 +0100 (So, 03. Feb 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java cleanup ------------------------------------------------------------------------ r4364 | kredel | 2013-02-03 15:04:51 +0100 (So, 03. Feb 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/FactorAbstract.java add variable order optimization ------------------------------------------------------------------------ r4363 | kredel | 2013-01-31 23:31:11 +0100 (Do, 31. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/kern/MPJEngine.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java cleanup ------------------------------------------------------------------------ r4362 | kredel | 2013-01-31 23:24:21 +0100 (Do, 31. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/kern/MPJEngine.java moved Get_status and Wait into globaly locked block ------------------------------------------------------------------------ r4361 | kredel | 2013-01-27 20:37:15 +0100 (So, 27. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/kern/MPJEngine.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/mpj/src/edu/jas/util/MPJChannel.java Irecv with thread-safe Wait ------------------------------------------------------------------------ r4360 | kredel | 2013-01-13 14:23:53 +0100 (So, 13. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java M /trunk/trc/edu/jas/ufd/GCDHenselTest.java constant ldcf ------------------------------------------------------------------------ r4359 | kredel | 2013-01-13 14:17:38 +0100 (So, 13. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java check for monic ldcf ------------------------------------------------------------------------ r4356 | kredel | 2013-01-05 20:33:56 +0100 (Sa, 05. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java cleanup ------------------------------------------------------------------------ r4355 | kredel | 2013-01-05 20:12:56 +0100 (Sa, 05. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java M /trunk/src/edu/jas/ufd/HenselMultUtil.java fixed cofactor mult and cleanup ------------------------------------------------------------------------ r4354 | kredel | 2013-01-05 20:10:47 +0100 (Sa, 05. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/ufd/GCDHenselTest.java cleanup ------------------------------------------------------------------------ r4353 | kredel | 2013-01-05 14:36:47 +0100 (Sa, 05. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java M /trunk/src/edu/jas/ufd/HenselMultUtil.java fixed invalid reuse of variable q added some more throws ------------------------------------------------------------------------ r4352 | kredel | 2013-01-03 23:33:18 +0100 (Do, 03. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java intermediate version ------------------------------------------------------------------------ r4351 | kredel | 2013-01-02 17:48:46 +0100 (Mi, 02. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/ufd/GCDHenselTest.java more fail info ------------------------------------------------------------------------ r4350 | kredel | 2013-01-02 17:42:11 +0100 (Mi, 02. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java cleanup ------------------------------------------------------------------------ r4349 | kredel | 2013-01-02 16:27:02 +0100 (Mi, 02. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/ufd/GCDHenselTest.java update ------------------------------------------------------------------------ r4348 | kredel | 2013-01-02 16:26:03 +0100 (Mi, 02. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java select factors with small ldcfs ------------------------------------------------------------------------ r4347 | kredel | 2013-01-02 12:37:26 +0100 (Mi, 02. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java avoid Hensel on coefficients ------------------------------------------------------------------------ r4346 | kredel | 2013-01-01 23:34:44 +0100 (Di, 01. Jan 2013) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GBFactory.java cleanup ------------------------------------------------------------------------ r4344 | kredel | 2012-12-31 19:34:37 +0100 (Mo, 31. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/HenselMultUtil.java add throw exception ------------------------------------------------------------------------ r4343 | kredel | 2012-12-31 18:10:56 +0100 (Mo, 31. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/FactorInteger.java M /trunk/trc/edu/jas/ufd/HenselMultUtilTest.java adjust to integer points ------------------------------------------------------------------------ r4342 | kredel | 2012-12-31 17:47:27 +0100 (Mo, 31. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java M /trunk/trc/edu/jas/ufd/GCDHenselTest.java adjust number of primes ------------------------------------------------------------------------ r4341 | kredel | 2012-12-31 17:34:28 +0100 (Mo, 31. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java M /trunk/src/edu/jas/ufd/HenselMultUtil.java M /trunk/src/edu/jas/ufd/HenselUtil.java use integer evaluation points ------------------------------------------------------------------------ r4338 | kredel | 2012-12-29 20:17:54 +0100 (Sa, 29. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java M /trunk/src/edu/jas/poly/GenPolynomialTokenizer.java logger cleanup ------------------------------------------------------------------------ r4337 | kredel | 2012-12-29 13:37:43 +0100 (Sa, 29. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedMPJ.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedEC.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybridEC.java logger cleanup ------------------------------------------------------------------------ r4336 | kredel | 2012-12-29 12:54:51 +0100 (Sa, 29. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedMPJ.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedEC.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybridEC.java M /trunk/src/edu/jas/gb/OrderedPairlist.java M /trunk/src/edu/jas/util/DistHashTable.java use putWait on GB master ------------------------------------------------------------------------ r4335 | kredel | 2012-12-28 22:11:45 +0100 (Fr, 28. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile A /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistHybridMPJTest.java M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedMPJ.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java add last index to pair for dist GB and new unit test ------------------------------------------------------------------------ r4334 | kredel | 2012-12-28 12:49:57 +0100 (Fr, 28. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/AbstractPair.java M /trunk/src/edu/jas/gb/GBDist.java M /trunk/src/edu/jas/gb/GBDistHybrid.java M /trunk/src/edu/jas/gb/GBDistSP.java M /trunk/src/edu/jas/gb/GBTransportMess.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedEC.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybridEC.java M /trunk/src/edu/jas/gb/OrderedMinPairlist.java M /trunk/src/edu/jas/gb/OrderedPairlist.java M /trunk/src/edu/jas/gb/OrderedSyzPairlist.java M /trunk/src/edu/jas/gb/Pair.java add last index to pair for dist GB ------------------------------------------------------------------------ r4333 | kredel | 2012-12-28 11:19:33 +0100 (Fr, 28. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/GBAlgorithmBuilder.java test arguments ------------------------------------------------------------------------ r4331 | kredel | 2012-12-27 23:54:41 +0100 (Do, 27. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/GBAlgorithmBuilder.java doc cosmetic ------------------------------------------------------------------------ r4329 | kredel | 2012-12-27 22:41:57 +0100 (Do, 27. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/overview.html M /trunk/src/edu/jas/gb/GroebnerBaseParallel.java cosmetic ------------------------------------------------------------------------ r4328 | kredel | 2012-12-27 22:41:30 +0100 (Do, 27. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/GBAlgorithmBuilderTest.java unit tests for pairlist ------------------------------------------------------------------------ r4326 | kredel | 2012-12-27 19:02:59 +0100 (Do, 27. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/gb-book.html M /trunk/src/edu/jas/application/GBAlgorithmBuilder.java M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java add pairlist selection ------------------------------------------------------------------------ r4325 | kredel | 2012-12-27 14:47:44 +0100 (Do, 27. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java M /trunk/src/edu/jas/gb/GroebnerBaseParallel.java M /trunk/src/edu/jas/gb/GroebnerBaseSeq.java M /trunk/src/edu/jas/gbufd/GBFactory.java M /trunk/src/edu/jas/gbufd/GroebnerBasePseudoSeq.java add pairlist to factory and constructors ------------------------------------------------------------------------ r4324 | kredel | 2012-12-26 18:31:30 +0100 (Mi, 26. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile add dependency and rsync ------------------------------------------------------------------------ r4323 | kredel | 2012-12-26 18:30:38 +0100 (Mi, 26. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java M /trunk/mpj/src/edu/jas/kern/MPJEngine.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/mpj/src/edu/jas/util/MPJChannel.java added synchronization for fastmpj ------------------------------------------------------------------------ r4320 | kredel | 2012-12-22 21:40:51 +0100 (Sa, 22. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb remove assoc test ------------------------------------------------------------------------ r4316 | kredel | 2012-12-15 20:29:42 +0100 (Sa, 15. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/IdealTest.java M /trunk/trc/edu/jas/root/RealRootTest.java adjust eps for DECIMAL128 ------------------------------------------------------------------------ r4315 | kredel | 2012-12-15 20:23:25 +0100 (Sa, 15. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/BigDecimal.java M /trunk/src/edu/jas/root/RealRootsAbstract.java default DECIMAL128 ------------------------------------------------------------------------ r4314 | kredel | 2012-12-09 14:16:29 +0100 (So, 09. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RunGB.java add nolog option ------------------------------------------------------------------------ r4313 | kredel | 2012-12-03 23:58:05 +0100 (Mo, 03. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/jython/src/edu/jas/gb/GBSigBased.java cosmetic ------------------------------------------------------------------------ r4312 | kredel | 2012-12-03 23:53:26 +0100 (Mo, 03. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/jython/Makefile M /trunk/jython/src/edu/jas/gb/GBSigBasedTest.java testing ------------------------------------------------------------------------ r4311 | kredel | 2012-12-02 13:22:28 +0100 (So, 02. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/katsura.rb M /trunk/examples/rose.rb M /trunk/examples/trinks.rb M /trunk/examples/trinks_str.rb add client stop ------------------------------------------------------------------------ r4310 | kredel | 2012-12-02 12:41:44 +0100 (So, 02. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseDistributedEC.java syz pairlist ------------------------------------------------------------------------ r4309 | kredel | 2012-12-02 12:40:30 +0100 (So, 02. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb M /trunk/examples/trinks.py M /trunk/examples/trinks.rb client stop and parallel for ZZ ------------------------------------------------------------------------ r4306 | kredel | 2012-12-01 18:16:25 +0100 (Sa, 01. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/GBAlgorithmBuilderTest.java print cosmetic ------------------------------------------------------------------------ r4305 | kredel | 2012-12-01 11:46:45 +0100 (Sa, 01. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/util/DistThreadPool.java add toString ------------------------------------------------------------------------ r4304 | kredel | 2012-12-01 11:41:22 +0100 (Sa, 01. Dez 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseDistributedEC.java fix name ------------------------------------------------------------------------ r4300 | kredel | 2012-11-24 11:31:57 +0100 (Sa, 24. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/trinks.rb app irb workaround ------------------------------------------------------------------------ r4298 | kredel | 2012-11-18 23:29:28 +0100 (So, 18. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb fix docs and catch irb not found ------------------------------------------------------------------------ r4297 | kredel | 2012-11-18 23:21:49 +0100 (So, 18. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/tuzun.rb fix gen name ------------------------------------------------------------------------ r4296 | kredel | 2012-11-11 19:09:53 +0100 (So, 11. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/GBAlgorithmBuilder.java M /trunk/src/edu/jas/gbufd/GBFactory.java M /trunk/trc/edu/jas/application/GBAlgorithmBuilderTest.java some tests ------------------------------------------------------------------------ r4295 | kredel | 2012-11-04 22:39:34 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/jython/Makefile add missing script module ------------------------------------------------------------------------ r4294 | kredel | 2012-11-04 20:27:21 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GBFactory.java fix non integral domain ------------------------------------------------------------------------ r4293 | kredel | 2012-11-04 19:18:30 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/katsura7m.jas M /trunk/log4j.properties update ------------------------------------------------------------------------ r4292 | kredel | 2012-11-04 19:17:40 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/GBAlgorithmBuilder.java M /trunk/trc/edu/jas/application/GBAlgorithmBuilderTest.java add new algos to GB builder ------------------------------------------------------------------------ r4291 | kredel | 2012-11-04 19:16:27 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GroebnerBaseRational.java M /trunk/src/edu/jas/gbufd/PseudoReductionPar.java M /trunk/src/edu/jas/poly/GenPolynomial.java fixed toArray shrinking ------------------------------------------------------------------------ r4290 | kredel | 2012-11-04 15:47:45 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GBFactory.java M /trunk/src/edu/jas/gbufd/GroebnerBasePseudoParallel.java M /trunk/src/edu/jas/gbufd/GroebnerBasePseudoSeq.java A /trunk/src/edu/jas/gbufd/GroebnerBaseRational.java (von /trunk/src/edu/jas/gbufd/GroebnerBaseSeqRational.java:4289) M /trunk/src/edu/jas/gbufd/GroebnerBaseSeqQuotient.java D /trunk/src/edu/jas/gbufd/GroebnerBaseSeqRational.java M /trunk/src/edu/jas/gbufd/PseudoReductionPar.java M /trunk/src/edu/jas/gbufd/PseudoReductionSeq.java M /trunk/trc/edu/jas/gbufd/GroebnerBasePseudoParTest.java M /trunk/trc/edu/jas/gbufd/GroebnerBaseSeqRationalTest.java eclipse code cosmetic and renaming ------------------------------------------------------------------------ r4289 | kredel | 2012-11-04 15:29:36 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GBOptimized.java M /trunk/src/edu/jas/gb/GBProxy.java M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java M /trunk/src/edu/jas/gbufd/GBFactory.java M /trunk/src/edu/jas/gbufd/GroebnerBaseSeqQuotient.java M /trunk/src/edu/jas/gbufd/GroebnerBaseSeqRational.java add toString and parallel ------------------------------------------------------------------------ r4288 | kredel | 2012-11-04 14:08:25 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RunGB.java A /trunk/src/edu/jas/gbufd/GroebnerBasePseudoParallel.java M /trunk/src/edu/jas/gbufd/GroebnerBasePseudoSeq.java A /trunk/src/edu/jas/gbufd/PseudoReductionPar.java M /trunk/src/edu/jas/gbufd/PseudoReductionSeq.java A /trunk/trc/edu/jas/gbufd/GroebnerBasePseudoParTest.java fraction free parallel GB ------------------------------------------------------------------------ r4287 | kredel | 2012-11-04 12:23:31 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RunGB.java generalize for more implementations ------------------------------------------------------------------------ r4286 | kredel | 2012-11-04 12:22:02 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/RReductionSeq.java improved debugging ------------------------------------------------------------------------ r4285 | kredel | 2012-11-04 12:08:56 +0100 (So, 04. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomial.java fix non intral-domain case ------------------------------------------------------------------------ r4284 | kredel | 2012-11-03 19:32:04 +0100 (Sa, 03. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/trc/edu/jas/poly/IntGenPolynomialTest.java M /trunk/trc/edu/jas/poly/RatGenPolynomialTest.java scale-subtract-multiply and tests ------------------------------------------------------------------------ r4283 | kredel | 2012-11-03 19:31:09 +0100 (Sa, 03. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/ReductionAbstract.java use sale-subtract-mult in s-pol ------------------------------------------------------------------------ r4281 | kredel | 2012-11-03 11:40:06 +0100 (Sa, 03. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseParallel.java M /trunk/src/edu/jas/gb/ReductionPar.java M /trunk/src/edu/jas/gb/ReductionSeq.java M /trunk/src/edu/jas/poly/GenPolynomial.java BLAS level 1 style optimizations ------------------------------------------------------------------------ r4280 | kredel | 2012-11-03 11:36:06 +0100 (Sa, 03. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/ReductionAbstract.java idempotent version of isGB ------------------------------------------------------------------------ r4279 | kredel | 2012-11-03 11:34:03 +0100 (Sa, 03. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RunGB.java M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java M /trunk/src/edu/jas/gb/Reduction.java M /trunk/trc/edu/jas/gb/GroebnerBaseSeqTest.java idempotent version of isGB ------------------------------------------------------------------------ r4277 | kredel | 2012-11-01 10:44:57 +0100 (Do, 01. Nov 2012) | 1 Zeile Geänderte Pfade: M /trunk/jython/Makefile forgotten lib ------------------------------------------------------------------------ r4276 | kredel | 2012-10-28 22:21:30 +0100 (So, 28. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/build.xml M /trunk/doc/index.html M /trunk/jython/Makefile add more to javadocs ------------------------------------------------------------------------ r4275 | kredel | 2012-10-28 19:34:05 +0100 (So, 28. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RunGB.java cleanup ------------------------------------------------------------------------ r4274 | kredel | 2012-10-27 18:56:32 +0200 (Sa, 27. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/mkplot.py update ------------------------------------------------------------------------ r4273 | kredel | 2012-10-27 18:53:21 +0200 (Sa, 27. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile add id ------------------------------------------------------------------------ r4272 | kredel | 2012-10-27 18:50:57 +0200 (Sa, 27. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile request niodev ------------------------------------------------------------------------ r4271 | kredel | 2012-10-26 21:31:26 +0200 (Fr, 26. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/katsura.rb A /trunk/examples/katsura9m.jas version 9 ------------------------------------------------------------------------ r4270 | kredel | 2012-10-24 22:41:11 +0200 (Mi, 24. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/ExpVectorByte.java M /trunk/src/edu/jas/poly/ExpVectorInteger.java M /trunk/src/edu/jas/poly/ExpVectorLong.java M /trunk/src/edu/jas/poly/ExpVectorShort.java made ExpVector implementations final ------------------------------------------------------------------------ r4269 | kredel | 2012-10-23 21:37:09 +0200 (Di, 23. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/application/RunMPJGB.java change default to false ------------------------------------------------------------------------ r4268 | kredel | 2012-10-22 22:48:15 +0200 (Mo, 22. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/katsura.rb M /trunk/examples/katsura8m.jas more modules ------------------------------------------------------------------------ r4267 | kredel | 2012-10-22 22:45:10 +0200 (Mo, 22. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RingFactoryTokenizer.java fix small mods ------------------------------------------------------------------------ r4266 | kredel | 2012-10-21 22:24:01 +0200 (So, 21. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomialTokenizer.java fix small mods ------------------------------------------------------------------------ r4264 | kredel | 2012-10-21 19:46:44 +0200 (So, 21. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistMPJTest.java activate multiple unit tests after interrupt fix ------------------------------------------------------------------------ r4263 | kredel | 2012-10-21 19:38:14 +0200 (So, 21. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/application/RunMPJGB.java M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistMPJTest.java M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedMPJ.java M /trunk/mpj/src/edu/jas/kern/MPJEngine.java M /trunk/mpj/src/edu/jas/kern/MPJEngineTest.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJTest.java M /trunk/mpj/src/edu/jas/util/MPJChannel.java eclipse code cosmetic ------------------------------------------------------------------------ r4262 | kredel | 2012-10-21 15:24:47 +0200 (So, 21. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb A /trunk/examples/primes.py A /trunk/examples/primes.rb M /trunk/src/edu/jas/arith/PrimeList.java some more primes ------------------------------------------------------------------------ r4261 | kredel | 2012-10-21 13:34:02 +0200 (So, 21. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybrid.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybridEC.java avoid interrupt in terminate ------------------------------------------------------------------------ r4260 | kredel | 2012-10-21 12:32:54 +0200 (So, 21. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedMPJ.java avoid interrupt for MPJ ------------------------------------------------------------------------ r4259 | kredel | 2012-10-21 12:20:37 +0200 (So, 21. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/src/edu/jas/util/DHTTransport.java add termination message ------------------------------------------------------------------------ r4258 | kredel | 2012-10-21 12:14:01 +0200 (So, 21. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/kern/MPJEngine.java M /trunk/mpj/src/edu/jas/util/MPJChannel.java internal send method ------------------------------------------------------------------------ r4256 | kredel | 2012-10-20 11:08:49 +0200 (Sa, 20. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb use toScript ------------------------------------------------------------------------ r4254 | kredel | 2012-10-14 20:13:32 +0200 (So, 14. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/util/ThreadPool.java ignore PreemptingException ------------------------------------------------------------------------ r4251 | kredel | 2012-10-14 19:39:35 +0200 (So, 14. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/mkplot.py update and 1d views to 2d graphs ------------------------------------------------------------------------ r4250 | kredel | 2012-10-14 19:25:12 +0200 (So, 14. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/rose.py acitvate dist ------------------------------------------------------------------------ r4249 | kredel | 2012-10-14 12:13:04 +0200 (So, 14. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/OrderedPairlist.java M /trunk/src/edu/jas/gb/OrderedSyzPairlist.java improve logging ------------------------------------------------------------------------ r4248 | kredel | 2012-10-14 12:07:27 +0200 (So, 14. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py add syz pairlist ------------------------------------------------------------------------ r4247 | kredel | 2012-10-14 12:06:38 +0200 (So, 14. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/rose.py M /trunk/examples/rose.rb add logging ------------------------------------------------------------------------ r4246 | kredel | 2012-10-08 00:05:59 +0200 (Mo, 08. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/rose.py name changes ------------------------------------------------------------------------ r4245 | kredel | 2012-10-07 14:27:43 +0200 (So, 07. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RunGB.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybridEC.java fix for production ------------------------------------------------------------------------ r4244 | kredel | 2012-10-07 12:34:47 +0200 (So, 07. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb changes for new distributed GBs ------------------------------------------------------------------------ r4243 | kredel | 2012-10-07 12:33:05 +0200 (So, 07. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/machines.localhost new ports ------------------------------------------------------------------------ r4242 | kredel | 2012-10-07 10:48:00 +0200 (So, 07. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gb/GroebnerBaseDistECTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseDistHybridECTest.java compare with sequential version ------------------------------------------------------------------------ r4241 | kredel | 2012-10-07 10:43:52 +0200 (So, 07. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseDistributedEC.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybridEC.java tests with list size in transport ------------------------------------------------------------------------ r4240 | kredel | 2012-10-07 10:40:47 +0200 (So, 07. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseSeq.java improve logging ------------------------------------------------------------------------ r4239 | kredel | 2012-10-07 10:40:06 +0200 (So, 07. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GBTransportMess.java M /trunk/src/edu/jas/gb/OrderedPairlist.java M /trunk/src/edu/jas/gb/PairList.java add list size-1 to transport message ------------------------------------------------------------------------ r4238 | kredel | 2012-10-05 00:06:05 +0200 (Fr, 05. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RunGB.java M /trunk/trc/edu/jas/gb/GroebnerBaseDistECTest.java cleanup ------------------------------------------------------------------------ r4237 | kredel | 2012-10-05 00:04:30 +0200 (Fr, 05. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseDistributedEC.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybridEC.java fix class names ------------------------------------------------------------------------ r4236 | kredel | 2012-10-05 00:03:47 +0200 (Fr, 05. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/util/DistThreadPool.java M /trunk/src/edu/jas/util/ExecutableServer.java logging ------------------------------------------------------------------------ r4235 | kredel | 2012-10-03 23:17:59 +0200 (Mi, 03. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseDistributed.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybrid.java obsolete ------------------------------------------------------------------------ r4234 | kredel | 2012-10-03 22:58:29 +0200 (Mi, 03. Okt 2012) | 1 Zeile Geänderte Pfade: A /trunk/trc/edu/jas/gb/GroebnerBaseDistHybridECTest.java some unit tests ------------------------------------------------------------------------ r4233 | kredel | 2012-10-03 22:52:34 +0200 (Mi, 03. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RunGB.java M /trunk/src/edu/jas/gb/GBDist.java M /trunk/src/edu/jas/gb/GBDistHybrid.java D /trunk/src/edu/jas/gb/GroebnerBaseDistECTest.java A /trunk/src/edu/jas/gb/GroebnerBaseDistributedEC.java A /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybridEC.java A /trunk/trc/edu/jas/gb/GroebnerBaseDistECTest.java D /trunk/trc/edu/jas/gb/GroebnerBaseDistributedEC.java distributed hybrid GB with EC ------------------------------------------------------------------------ r4232 | kredel | 2012-10-03 21:39:20 +0200 (Mi, 03. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/util/DistThreadPool.java M /trunk/src/edu/jas/util/ExecutableServer.java improved logging ------------------------------------------------------------------------ r4231 | kredel | 2012-10-03 19:48:26 +0200 (Mi, 03. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseDistECTest.java combined version with executable channels ------------------------------------------------------------------------ r4230 | kredel | 2012-10-03 19:46:52 +0200 (Mi, 03. Okt 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/gb/GroebnerBaseDistECTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseDistTest.java A /trunk/trc/edu/jas/gb/GroebnerBaseDistributedEC.java combined version with executable channels ------------------------------------------------------------------------ r4229 | kredel | 2012-10-03 19:19:36 +0200 (Mi, 03. Okt 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/util/ChannelFactory.java M /trunk/src/edu/jas/util/DistThreadPool.java M /trunk/src/edu/jas/util/ExecutableServer.java improved debugging ------------------------------------------------------------------------ r4228 | kredel | 2012-09-30 13:37:39 +0200 (So, 30. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/ReductionPar.java fix array size ------------------------------------------------------------------------ r4227 | kredel | 2012-09-30 13:20:24 +0200 (So, 30. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RunGB.java M /trunk/src/edu/jas/application/RunSGB.java A /trunk/src/edu/jas/gb/GBTransportMess.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributed.java refactoring and cleanup ------------------------------------------------------------------------ r4225 | kredel | 2012-09-29 22:27:56 +0200 (Sa, 29. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomial.java M /trunk/src/edu/jas/poly/GenWordPolynomialRing.java M /trunk/src/edu/jas/poly/WordFactory.java findbug issues ------------------------------------------------------------------------ r4224 | kredel | 2012-09-29 15:40:12 +0200 (Sa, 29. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/src/edu/jas/util/DistHashTable.java M /trunk/src/edu/jas/util/ThreadPool.java fixed synchronization ------------------------------------------------------------------------ r4223 | kredel | 2012-09-28 22:25:15 +0200 (Fr, 28. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/src/edu/jas/util/DistHashTable.java add synchronized ------------------------------------------------------------------------ r4222 | kredel | 2012-09-28 22:10:46 +0200 (Fr, 28. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/ReductionPar.java remove synchronized ------------------------------------------------------------------------ r4221 | kredel | 2012-09-28 21:51:30 +0200 (Fr, 28. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedMPJ.java M /trunk/src/edu/jas/gb/ReductionPar.java improve normalform signature ------------------------------------------------------------------------ r4220 | kredel | 2012-09-27 22:47:26 +0200 (Do, 27. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile M /trunk/mpj/src/edu/jas/application/RunMPJGB.java M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java cleanup ------------------------------------------------------------------------ r4219 | kredel | 2012-09-26 23:47:46 +0200 (Mi, 26. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/application/RunMPJGB.java A /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedHybridMPJ.java M /trunk/mpj/src/edu/jas/util/MPJChannel.java add hybrid version ------------------------------------------------------------------------ r4218 | kredel | 2012-09-23 22:30:12 +0200 (So, 23. Sep 2012) | 1 Zeile Geänderte Pfade: A /trunk/examples/katsura8m.jas M /trunk/mpj/Makefile A /trunk/mpj/machines add machine file ------------------------------------------------------------------------ r4217 | kredel | 2012-09-22 23:10:56 +0200 (Sa, 22. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/application/RunMPJGB.java fix timing print ------------------------------------------------------------------------ r4216 | kredel | 2012-09-22 22:59:38 +0200 (Sa, 22. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile A /trunk/mpj/src/edu/jas/application A /trunk/mpj/src/edu/jas/application/RunMPJGB.java add run GB ------------------------------------------------------------------------ r4215 | kredel | 2012-09-21 23:56:08 +0200 (Fr, 21. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/package.html M /trunk/src/edu/jas/poly/package.html M /trunk/src/edu/jas/ufd/package.html update ------------------------------------------------------------------------ r4214 | kredel | 2012-09-21 22:20:45 +0200 (Fr, 21. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/GBAlgorithmBuilder.java fixes for java6 compatibility ------------------------------------------------------------------------ r4213 | kredel | 2012-09-19 15:30:30 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile fix javadocs ------------------------------------------------------------------------ r4212 | kredel | 2012-09-19 15:24:20 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/kern/MPJEngine.java fix javadocs ------------------------------------------------------------------------ r4211 | kredel | 2012-09-19 15:08:14 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedMPJ.java M /trunk/mpj/src/edu/jas/kern/MPJEngine.java fix javadocs ------------------------------------------------------------------------ r4210 | kredel | 2012-09-19 14:41:43 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/doc/index.html M /trunk/mpj/Makefile update ------------------------------------------------------------------------ r4209 | kredel | 2012-09-19 14:32:17 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/Makefile M /trunk/mpj/Makefile M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java update ------------------------------------------------------------------------ r4208 | kredel | 2012-09-19 14:30:48 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/util/ThreadPool.java simplify ------------------------------------------------------------------------ r4207 | kredel | 2012-09-19 14:15:49 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile update ------------------------------------------------------------------------ r4206 | kredel | 2012-09-19 14:15:09 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/Makefile A /trunk/mpj/manifest.mf add manifest ------------------------------------------------------------------------ r4205 | kredel | 2012-09-19 12:46:00 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistMPJTest.java M /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedMPJ.java M /trunk/mpj/src/edu/jas/kern/MPJEngine.java M /trunk/mpj/src/edu/jas/kern/MPJEngineTest.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJTest.java M /trunk/mpj/src/edu/jas/util/MPJChannel.java eclipse code cosmetic ------------------------------------------------------------------------ r4204 | kredel | 2012-09-19 12:26:49 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile A /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistMPJTest.java A /trunk/mpj/src/edu/jas/gb/GroebnerBaseDistributedMPJ.java distributed GB with MPJ ------------------------------------------------------------------------ r4203 | kredel | 2012-09-19 12:25:48 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/kern/MPJEngine.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/mpj/src/edu/jas/util/MPJChannel.java cleanup and docs ------------------------------------------------------------------------ r4202 | kredel | 2012-09-19 09:33:06 +0200 (Mi, 19. Sep 2012) | 1 Zeile Geänderte Pfade: A /trunk/mpj/src/edu/jas/util/MPJChannel.java channel interface to MPJ ------------------------------------------------------------------------ r4201 | kredel | 2012-09-18 18:22:39 +0200 (Di, 18. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/Makefile M /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java M /trunk/mpj/src/edu/jas/util/DistHashTableMPJTest.java isolate bug in fastmpj ------------------------------------------------------------------------ r4200 | kredel | 2012-09-18 12:52:54 +0200 (Di, 18. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/mpj/src/edu/jas/kern/MPJEngineTest.java add Id ------------------------------------------------------------------------ r4199 | kredel | 2012-09-18 12:48:15 +0200 (Di, 18. Sep 2012) | 1 Zeile Geänderte Pfade: A /trunk/mpj A /trunk/mpj/.gitignore A /trunk/mpj/Makefile A /trunk/mpj/src A /trunk/mpj/src/edu A /trunk/mpj/src/edu/jas A /trunk/mpj/src/edu/jas/gb A /trunk/mpj/src/edu/jas/kern A /trunk/mpj/src/edu/jas/kern/MPJEngine.java A /trunk/mpj/src/edu/jas/kern/MPJEngineTest.java A /trunk/mpj/src/edu/jas/util A /trunk/mpj/src/edu/jas/util/DistHashTableMPJ.java A /trunk/mpj/src/edu/jas/util/DistHashTableMPJTest.java beginning of MPJ parts ------------------------------------------------------------------------ r4198 | kredel | 2012-09-16 22:57:16 +0200 (So, 16. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Word.java fix javadoc ------------------------------------------------------------------------ r4197 | kredel | 2012-09-16 20:11:33 +0200 (So, 16. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/jython update ------------------------------------------------------------------------ r4196 | kredel | 2012-09-16 20:05:39 +0200 (So, 16. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/jython/Makefile M /trunk/jython/src/edu/jas/gb/GBSigBased.java doc update ------------------------------------------------------------------------ r4194 | kredel | 2012-09-16 13:54:00 +0200 (So, 16. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/jython/Makefile add test ------------------------------------------------------------------------ r4193 | kredel | 2012-09-16 13:42:24 +0200 (So, 16. Sep 2012) | 1 Zeile Geänderte Pfade: A /trunk/jython/src/edu/jas/gb A /trunk/jython/src/edu/jas/gb/GBSigBased.java A /trunk/jython/src/edu/jas/gb/GBSigBasedTest.java M /trunk/jython/src/edu/jas/kern/ScriptingExample.java new scripting example with signature based GBs ------------------------------------------------------------------------ r4192 | kredel | 2012-09-16 13:39:06 +0200 (So, 16. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py fix missing values in dictionary in inject variables ------------------------------------------------------------------------ r4191 | kredel | 2012-09-14 10:09:24 +0200 (Fr, 14. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomialRing.java M /trunk/src/edu/jas/poly/WordFactory.java findbugs issues ------------------------------------------------------------------------ r4190 | kredel | 2012-09-13 15:16:03 +0200 (Do, 13. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Word.java M /trunk/src/edu/jas/poly/WordFactory.java cleanup ------------------------------------------------------------------------ r4189 | kredel | 2012-09-13 13:42:50 +0200 (Do, 13. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb M /trunk/examples/solvablepolynomial.rb A /trunk/examples/word_solvable_trans.py A /trunk/examples/word_solvable_trans.rb new multi letter examples ------------------------------------------------------------------------ r4188 | kredel | 2012-09-13 13:40:22 +0200 (Do, 13. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Word.java M /trunk/src/edu/jas/poly/WordFactory.java M /trunk/trc/edu/jas/poly/WordTest.java allow multi letter alphabets ------------------------------------------------------------------------ r4186 | kredel | 2012-09-10 22:08:16 +0200 (Mo, 10. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/solvablepolynomial.py M /trunk/examples/solvablepolynomial.rb A /trunk/examples/word_evans.py A /trunk/examples/word_evans.rb A /trunk/examples/word_solvable.py A /trunk/examples/word_solvable.rb more non-commutative examples ------------------------------------------------------------------------ r4185 | kredel | 2012-09-10 22:07:20 +0200 (Mo, 10. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb small improvements ------------------------------------------------------------------------ r4184 | kredel | 2012-09-10 21:33:52 +0200 (Mo, 10. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/SolvableGroebnerBaseAbstract.java speedup isTwosidedGB test ------------------------------------------------------------------------ r4183 | kredel | 2012-09-09 19:12:52 +0200 (So, 09. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb M /trunk/examples/word_simple.py A /trunk/examples/word_simple.rb jruby interface to non-commutative polynomials ------------------------------------------------------------------------ r4182 | kredel | 2012-09-09 19:11:28 +0200 (So, 09. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Word.java M /trunk/src/edu/jas/poly/WordFactory.java corrections for python and ruby ------------------------------------------------------------------------ r4181 | kredel | 2012-09-09 14:39:55 +0200 (So, 09. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py A /trunk/examples/word_simple.py M /trunk/src/edu/jas/poly/GenWordPolynomialRing.java jython interface to non-commutative polynomials ------------------------------------------------------------------------ r4180 | kredel | 2012-09-09 12:57:20 +0200 (So, 09. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/GBAlgorithmBuilder.java M /trunk/src/edu/jas/gbufd/GBFactory.java update documentation ------------------------------------------------------------------------ r4179 | kredel | 2012-09-09 12:45:58 +0200 (So, 09. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/GBAlgorithmBuilder.java M /trunk/src/edu/jas/gb/GroebnerBase.java M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java M /trunk/src/edu/jas/gb/GroebnerBaseParallel.java M /trunk/src/edu/jas/gb/GroebnerBaseSeq.java M /trunk/src/edu/jas/gbufd/GBFactory.java M /trunk/src/edu/jas/gbufd/GroebnerBasePseudoRecSeq.java M /trunk/src/edu/jas/gbufd/GroebnerBasePseudoSeq.java add documentation and references ------------------------------------------------------------------------ r4178 | kredel | 2012-09-09 12:45:10 +0200 (So, 09. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbmod/ModGroebnerBaseAbstract.java deprecate a constructor ------------------------------------------------------------------------ r4177 | suess | 2012-09-09 12:44:00 +0200 (So, 09. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLM.java add reference ------------------------------------------------------------------------ r4175 | kredel | 2012-09-09 11:39:44 +0200 (So, 09. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/GBAlgorithmBuilderTest.java deactivate prints ------------------------------------------------------------------------ r4174 | kredel | 2012-09-08 22:15:46 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/GBAlgorithmBuilder.java A /trunk/trc/edu/jas/application/GBAlgorithmBuilderTest.java add tests for builder ------------------------------------------------------------------------ r4173 | kredel | 2012-09-08 22:13:53 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLM.java M /trunk/src/edu/jas/gbufd/GroebnerBaseSeqQuotient.java M /trunk/src/edu/jas/gbufd/GroebnerBaseSeqRational.java fix missing terminate and cancel ------------------------------------------------------------------------ r4172 | kredel | 2012-09-08 20:11:33 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/application/GBAlgorithmBuilder.java new GB algorithm builder ------------------------------------------------------------------------ r4171 | suess | 2012-09-08 20:10:43 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLM.java eclipse code cosmetic and backing GB algorithm ------------------------------------------------------------------------ r4170 | kredel | 2012-09-08 20:08:52 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/ExamplesGeoTheorems.java M /trunk/src/edu/jas/gb/GBOptimized.java eclopse code cosmetic ------------------------------------------------------------------------ r4168 | kredel | 2012-09-08 17:58:23 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GBOptimized.java M /trunk/src/edu/jas/gbufd/GBFactory.java javadoc updated and cleanup ------------------------------------------------------------------------ r4167 | kredel | 2012-09-08 14:19:44 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/ExamplesGeoTheorems.java more tests ------------------------------------------------------------------------ r4166 | kredel | 2012-09-08 14:19:22 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GBFactory.java M /trunk/src/edu/jas/gbufd/GroebnerBaseSeqRational.java selection of fraction free algoritms ------------------------------------------------------------------------ r4165 | kredel | 2012-09-08 14:18:00 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/gbufd/GroebnerBaseSeqQuotient.java fraction free version ------------------------------------------------------------------------ r4164 | kredel | 2012-09-08 12:43:08 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/ExamplesGeoTheorems.java A /trunk/src/edu/jas/gb/GBOptimized.java GB with term order optimization ------------------------------------------------------------------------ r4163 | kredel | 2012-09-08 12:42:29 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GBProxy.java javadoc params ------------------------------------------------------------------------ r4162 | kredel | 2012-09-08 12:41:51 +0200 (Sa, 08. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/TermOrderOptimization.java indent cosmetic ------------------------------------------------------------------------ r4161 | kredel | 2012-09-07 23:12:07 +0200 (Fr, 07. Sep 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/application/ExamplesGeoTheorems.java examples from GeoGebra Theorem ------------------------------------------------------------------------ r4160 | kredel | 2012-09-07 23:10:56 +0200 (Fr, 07. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GBProxy.java fix Override ------------------------------------------------------------------------ r4159 | kredel | 2012-09-02 22:37:53 +0200 (So, 02. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Word.java javedoc update ------------------------------------------------------------------------ r4157 | kredel | 2012-09-02 20:18:43 +0200 (So, 02. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/OrderedWordPairlist.java M /trunk/trc/edu/jas/gb/WordGroebnerBaseSeqTest.java new example ------------------------------------------------------------------------ r4156 | kredel | 2012-09-02 18:52:30 +0200 (So, 02. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/OrderedWordPairlist.java M /trunk/trc/edu/jas/poly/WordTest.java activate BB criterion ------------------------------------------------------------------------ r4155 | kredel | 2012-09-02 18:51:12 +0200 (So, 02. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomial.java M /trunk/src/edu/jas/poly/GenWordPolynomialRing.java M /trunk/src/edu/jas/poly/Word.java M /trunk/src/edu/jas/poly/WordFactory.java A /trunk/src/edu/jas/poly/WordMonomial.java A /trunk/src/edu/jas/poly/WordPolyIterator.java missing parts and pseudo lcm for words ------------------------------------------------------------------------ r4154 | kredel | 2012-09-02 14:27:21 +0200 (So, 02. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomialRing.java M /trunk/src/edu/jas/poly/Word.java M /trunk/src/edu/jas/poly/WordFactory.java M /trunk/trc/edu/jas/gb/WordGroebnerBaseSeqTest.java convert from commutative polynomials and examples ------------------------------------------------------------------------ r4153 | kredel | 2012-09-02 13:16:16 +0200 (So, 02. Sep 2012) | 1 Zeile Geänderte Pfade: A /trunk/trc/edu/jas/gb/WordGroebnerBaseSeqTest.java M /trunk/trc/edu/jas/gb/WordReductionTest.java more tests ------------------------------------------------------------------------ r4152 | kredel | 2012-09-02 13:15:48 +0200 (So, 02. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/OrderedWordPairlist.java M /trunk/src/edu/jas/gb/WordReductionAbstract.java M /trunk/src/edu/jas/gb/WordReductionSeq.java cleanup and fixes ------------------------------------------------------------------------ r4151 | kredel | 2012-09-02 13:14:45 +0200 (So, 02. Sep 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomial.java M /trunk/src/edu/jas/poly/WordFactory.java cleanup ------------------------------------------------------------------------ r4150 | kredel | 2012-09-01 11:18:23 +0200 (Sa, 01. Sep 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/gb/OrderedWordPairlist.java A /trunk/src/edu/jas/gb/WordGroebnerBase.java A /trunk/src/edu/jas/gb/WordGroebnerBaseAbstract.java A /trunk/src/edu/jas/gb/WordGroebnerBaseSeq.java A /trunk/src/edu/jas/gb/WordPair.java A /trunk/src/edu/jas/gb/WordPairList.java non-commutative Groebner base ------------------------------------------------------------------------ r4149 | kredel | 2012-09-01 11:01:54 +0200 (Sa, 01. Sep 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/gb/WordReduction.java A /trunk/src/edu/jas/gb/WordReductionAbstract.java A /trunk/src/edu/jas/gb/WordReductionSeq.java A /trunk/src/edu/jas/poly/Overlap.java A /trunk/src/edu/jas/poly/OverlapList.java M /trunk/src/edu/jas/poly/Word.java A /trunk/trc/edu/jas/gb/WordReductionTest.java M /trunk/trc/edu/jas/poly/WordTest.java word overlap computation ------------------------------------------------------------------------ r4148 | kredel | 2012-08-31 21:49:27 +0200 (Fr, 31. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/ModInteger.java M /trunk/src/edu/jas/arith/ModLong.java M /trunk/src/edu/jas/poly/AlgebraicNumber.java M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorAbstract.java cleanup ------------------------------------------------------------------------ r4147 | kredel | 2012-08-31 21:39:05 +0200 (Fr, 31. Aug 2012) | 1 Zeile Geänderte Pfade: A /trunk/examples/alg_stat_1p.py A /trunk/examples/alg_stat_1p.rb parametric examples from algebraic statistics ------------------------------------------------------------------------ r4146 | kredel | 2012-08-31 21:26:38 +0200 (Fr, 31. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb fix braces and parenthesis in generators ------------------------------------------------------------------------ r4145 | kredel | 2012-08-31 21:25:24 +0200 (Fr, 31. Aug 2012) | 1 Zeile Geänderte Pfade: A /trunk/examples/alg_stat_1.py A /trunk/examples/alg_stat_1.rb examples from algebraic statistics ------------------------------------------------------------------------ r4144 | kredel | 2012-08-26 16:29:36 +0200 (So, 26. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomial.java M /trunk/src/edu/jas/poly/Word.java fix javadoc ------------------------------------------------------------------------ r4142 | kredel | 2012-08-26 15:30:59 +0200 (So, 26. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenSolvablePolynomial.java M /trunk/trc/edu/jas/poly/GenSolvablePolynomialTest.java A /trunk/trc/edu/jas/poly/QuatGenSolvablePolynomialTest.java fixed and new test cases ------------------------------------------------------------------------ r4141 | kredel | 2012-08-26 14:03:13 +0200 (So, 26. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenSolvablePolynomial.java some missing parts ------------------------------------------------------------------------ r4140 | kredel | 2012-08-26 13:35:28 +0200 (So, 26. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomial.java M /trunk/src/edu/jas/poly/GenWordPolynomialRing.java M /trunk/src/edu/jas/poly/Word.java M /trunk/src/edu/jas/poly/WordFactory.java M /trunk/trc/edu/jas/poly/WordTest.java small fixes, add missing parts, cosmetic ------------------------------------------------------------------------ r4139 | kredel | 2012-08-26 12:24:29 +0200 (So, 26. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenSolvablePolynomialRing.java M /trunk/src/edu/jas/poly/GenWordPolynomialRing.java M /trunk/src/edu/jas/poly/WordFactory.java M /trunk/trc/edu/jas/poly/GenWordPolynomialTest.java some fixes and improvements ------------------------------------------------------------------------ r4138 | kredel | 2012-08-26 10:35:08 +0200 (So, 26. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomial.java M /trunk/src/edu/jas/poly/GenWordPolynomialRing.java M /trunk/src/edu/jas/poly/Word.java M /trunk/src/edu/jas/poly/WordFactory.java M /trunk/trc/edu/jas/poly/GenWordPolynomialTest.java eclipse code cosmetic ------------------------------------------------------------------------ r4137 | kredel | 2012-08-26 00:13:59 +0200 (So, 26. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomial.java M /trunk/src/edu/jas/poly/Word.java M /trunk/src/edu/jas/poly/WordFactory.java M /trunk/trc/edu/jas/poly/GenWordPolynomialTest.java use divideWord for division and remainder ------------------------------------------------------------------------ r4136 | kredel | 2012-08-25 22:05:15 +0200 (Sa, 25. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomial.java M /trunk/src/edu/jas/poly/Word.java M /trunk/src/edu/jas/poly/WordFactory.java M /trunk/trc/edu/jas/poly/GenWordPolynomialTest.java add missing parts: term order ------------------------------------------------------------------------ r4135 | kredel | 2012-08-25 20:06:53 +0200 (Sa, 25. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenWordPolynomial.java M /trunk/src/edu/jas/poly/GenWordPolynomialRing.java M /trunk/src/edu/jas/poly/Word.java M /trunk/src/edu/jas/poly/WordFactory.java A /trunk/trc/edu/jas/poly/GenWordPolynomialTest.java add missing parts ------------------------------------------------------------------------ r4134 | kredel | 2012-08-25 15:31:50 +0200 (Sa, 25. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/WordFactory.java M /trunk/trc/edu/jas/poly/WordTest.java fix isFinite ------------------------------------------------------------------------ r4133 | kredel | 2012-08-25 15:31:13 +0200 (Sa, 25. Aug 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/poly/GenWordPolynomial.java A /trunk/src/edu/jas/poly/GenWordPolynomialRing.java first compiling version ------------------------------------------------------------------------ r4132 | kredel | 2012-08-25 13:57:06 +0200 (Sa, 25. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Word.java A /trunk/src/edu/jas/poly/WordFactory.java M /trunk/trc/edu/jas/poly/WordTest.java factory needed for alphabet ------------------------------------------------------------------------ r4131 | kredel | 2012-08-25 00:49:37 +0200 (Sa, 25. Aug 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/poly/Word.java A /trunk/trc/edu/jas/poly/WordTest.java new class Word and tests ------------------------------------------------------------------------ r4130 | kredel | 2012-08-22 23:41:29 +0200 (Mi, 22. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/PolyUtil.java add missing method ------------------------------------------------------------------------ r4128 | kredel | 2012-08-19 21:32:19 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/structure/Element.java add reference to discussion ------------------------------------------------------------------------ r4127 | kredel | 2012-08-19 21:27:47 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/OrderedCPairlist.java make copy synchronized ------------------------------------------------------------------------ r4126 | kredel | 2012-08-19 21:10:14 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomial.java remove super.clone ------------------------------------------------------------------------ r4125 | kredel | 2012-08-19 21:05:22 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/ColoredSystem.java M /trunk/src/edu/jas/application/ComprehensiveGroebnerBaseSeq.java M /trunk/src/edu/jas/application/Ideal.java M /trunk/src/edu/jas/application/Local.java M /trunk/src/edu/jas/application/OrderedCPairlist.java M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/application/RealAlgebraicNumber.java M /trunk/src/edu/jas/application/Residue.java M /trunk/src/edu/jas/arith/BigComplex.java M /trunk/src/edu/jas/arith/BigDecimal.java M /trunk/src/edu/jas/arith/BigInteger.java M /trunk/src/edu/jas/arith/BigOctonion.java M /trunk/src/edu/jas/arith/BigQuaternion.java M /trunk/src/edu/jas/arith/BigRational.java M /trunk/src/edu/jas/arith/ModInteger.java M /trunk/src/edu/jas/arith/ModLong.java M /trunk/src/edu/jas/arith/Product.java M /trunk/src/edu/jas/gbmod/SyzygyAbstract.java M /trunk/src/edu/jas/integrate/ElementaryIntegration.java M /trunk/src/edu/jas/poly/AlgebraicNumber.java M /trunk/src/edu/jas/poly/Complex.java M /trunk/src/edu/jas/poly/ExpVector.java M /trunk/src/edu/jas/poly/ExpVectorByte.java M /trunk/src/edu/jas/poly/ExpVectorInteger.java M /trunk/src/edu/jas/poly/ExpVectorLong.java M /trunk/src/edu/jas/poly/ExpVectorShort.java M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/src/edu/jas/poly/GenPolynomialRing.java M /trunk/src/edu/jas/poly/GenSolvablePolynomial.java M /trunk/src/edu/jas/poly/Local.java M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/src/edu/jas/poly/PolynomialList.java M /trunk/src/edu/jas/poly/Quotient.java M /trunk/src/edu/jas/poly/Residue.java M /trunk/src/edu/jas/poly/TermOrderOptimization.java M /trunk/src/edu/jas/poly/WeylRelations.java M /trunk/src/edu/jas/ps/MultiVarCoefficients.java M /trunk/src/edu/jas/ps/MultiVarPowerSeries.java M /trunk/src/edu/jas/ps/MultiVarPowerSeriesRing.java M /trunk/src/edu/jas/ps/UnivPowerSeries.java M /trunk/src/edu/jas/root/Boundary.java M /trunk/src/edu/jas/root/ComplexAlgebraicNumber.java M /trunk/src/edu/jas/root/Interval.java M /trunk/src/edu/jas/root/RealAlgebraicNumber.java M /trunk/src/edu/jas/root/RealRootTuple.java M /trunk/src/edu/jas/root/Rectangle.java M /trunk/src/edu/jas/structure/Element.java M /trunk/src/edu/jas/ufd/FactorAbsolute.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorAbstract.java M /trunk/src/edu/jas/ufd/PolyUfdUtil.java M /trunk/src/edu/jas/ufd/Quotient.java M /trunk/src/edu/jas/ufd/SquarefreeFiniteFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteAlgebraicFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteFieldCharP.java M /trunk/src/edu/jas/vector/GenMatrix.java M /trunk/src/edu/jas/vector/GenMatrixRing.java M /trunk/src/edu/jas/vector/GenVector.java M /trunk/src/edu/jas/vector/GenVectorModul.java M /trunk/trc/edu/jas/application/IdealTest.java M /trunk/trc/edu/jas/arith/ModIntegerTest.java M /trunk/trc/edu/jas/arith/ModLongTest.java M /trunk/trc/edu/jas/poly/GenMatrixTest.java M /trunk/trc/edu/jas/poly/GenVectorTest.java M /trunk/trc/edu/jas/ps/MultiVarPowerSeriesTest.java M /trunk/trc/edu/jas/vector/GenMatrixTest.java M /trunk/trc/edu/jas/vector/GenVectorTest.java rename clone to copy and remove Clonable ------------------------------------------------------------------------ r4124 | kredel | 2012-08-19 20:48:15 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/FactorFactory.java eclipse code formating ------------------------------------------------------------------------ r4122 | kredel | 2012-08-19 17:54:52 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/Residue.java M /trunk/src/edu/jas/poly/Residue.java M /trunk/trc/edu/jas/application/ComplexRootTest.java improvement for findbugs ------------------------------------------------------------------------ r4120 | kredel | 2012-08-19 17:23:53 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/ComplexRootTest.java M /trunk/trc/edu/jas/application/RealAlgebraicTest.java improvement for findbugs ------------------------------------------------------------------------ r4119 | kredel | 2012-08-19 16:38:33 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ps/MultiVarPowerSeries.java improvement for findbugs ------------------------------------------------------------------------ r4118 | kredel | 2012-08-19 16:31:48 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/OrderedCPairlist.java M /trunk/src/edu/jas/ps/MultiVarPowerSeries.java improvements by findbugs ------------------------------------------------------------------------ r4117 | kredel | 2012-08-19 16:01:57 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/src/edu/jas/ufd/FactorAbstract.java M /trunk/src/edu/jas/ufd/PolyUfdUtil.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteFieldCharP.java improvements by findbugs ------------------------------------------------------------------------ r4116 | kredel | 2012-08-19 15:26:25 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseDistributed.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybrid.java M /trunk/src/edu/jas/gb/GroebnerBaseSeqPairDistributed.java M /trunk/src/edu/jas/gbufd/GroebnerBasePartial.java M /trunk/src/edu/jas/gbufd/RGroebnerBasePseudoSeq.java M /trunk/src/edu/jas/gbufd/RGroebnerBaseSeq.java M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/src/edu/jas/poly/PolyUtil.java improvements by findbugs ------------------------------------------------------------------------ r4115 | kredel | 2012-08-19 15:18:59 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/CReductionSeq.java M /trunk/src/edu/jas/gb/EReductionSeq.java M /trunk/src/edu/jas/ufd/FactorInteger.java M /trunk/src/edu/jas/ufd/HenselUtil.java M /trunk/src/edu/jas/ufd/SquarefreeAbstract.java improvements by findbugs ------------------------------------------------------------------------ r4114 | kredel | 2012-08-19 14:53:36 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java improvements by findbugs ------------------------------------------------------------------------ r4113 | kredel | 2012-08-19 14:50:35 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/ComprehensiveGroebnerBaseSeq.java M /trunk/src/edu/jas/application/Ideal.java M /trunk/src/edu/jas/application/PolyUtilApp.java improvements by findbugs ------------------------------------------------------------------------ r4112 | kredel | 2012-08-19 14:35:48 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/SquarefreeFieldChar0.java M /trunk/src/edu/jas/ufd/SquarefreeFiniteFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeRingChar0.java improvements for findbugs ------------------------------------------------------------------------ r4111 | kredel | 2012-08-19 14:30:30 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/OrderedCPairlist.java M /trunk/src/edu/jas/application/RootFactory.java M /trunk/src/edu/jas/ps/MultiVarPowerSeriesRing.java M /trunk/src/edu/jas/root/RealRootsSturm.java M /trunk/src/edu/jas/ufd/FactorAbsolute.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModular.java M /trunk/src/edu/jas/ufd/HenselMultUtil.java improvements and fixes for findbugs ------------------------------------------------------------------------ r4110 | kredel | 2012-08-19 14:02:16 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/FactorAlgebraicPrim.java M /trunk/trc/edu/jas/application/FactorAlgebraicPrimTest.java improvements and fixes for findbugs ------------------------------------------------------------------------ r4109 | kredel | 2012-08-19 14:01:24 +0200 (So, 19. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Residue.java M /trunk/src/edu/jas/util/ExecutableServer.java fixes for findbugs ------------------------------------------------------------------------ r4108 | kredel | 2012-08-18 12:57:40 +0200 (Sa, 18. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenSolvablePolynomial.java M /trunk/src/edu/jas/poly/RelationTable.java M /trunk/src/edu/jas/ps/UnivPowerSeries.java M /trunk/src/edu/jas/root/ComplexRootsAbstract.java unused stores ------------------------------------------------------------------------ r4107 | kredel | 2012-08-18 12:42:35 +0200 (Sa, 18. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/FactorFactory.java M /trunk/src/edu/jas/application/RingFactoryTokenizer.java M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java M /trunk/src/edu/jas/integrate/ElementaryIntegration.java unused stores ------------------------------------------------------------------------ r4106 | suess | 2012-08-18 12:41:52 +0200 (Sa, 18. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLMExamples.java fix wrong bitLength ------------------------------------------------------------------------ r4105 | kredel | 2012-08-18 12:20:41 +0200 (Sa, 18. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/ModIntegerRing.java fix final and protected ------------------------------------------------------------------------ r4104 | kredel | 2012-08-18 12:00:59 +0200 (Sa, 18. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/Ideal.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseAbstract.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseParallel.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseSeq.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseSeqPairParallel.java M /trunk/src/edu/jas/gb/SolvableReductionAbstract.java M /trunk/src/edu/jas/gb/SolvableReductionPar.java M /trunk/src/edu/jas/gb/SolvableReductionSeq.java M /trunk/src/edu/jas/gbmod/ModSolvableGroebnerBaseAbstract.java M /trunk/src/edu/jas/gbmod/SolvableSyzygyAbstract.java add suppress unchecked ------------------------------------------------------------------------ r4103 | kredel | 2012-08-16 23:52:05 +0200 (Do, 16. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb add saturation method ------------------------------------------------------------------------ r4102 | kredel | 2012-08-16 23:51:16 +0200 (Do, 16. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/BigInteger.java implement Rational ------------------------------------------------------------------------ r4100 | kredel | 2012-08-12 21:42:07 +0200 (So, 12. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/SquarefreeFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteAlgebraicFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteFieldCharP.java avoid hiding super fields ------------------------------------------------------------------------ r4099 | kredel | 2012-08-12 20:49:36 +0200 (So, 12. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/DGroebnerBaseSeq.java M /trunk/src/edu/jas/gb/EGroebnerBaseSeq.java M /trunk/src/edu/jas/gbufd/RGroebnerBaseSeq.java avoid hiding super fields ------------------------------------------------------------------------ r4098 | kredel | 2012-08-12 18:39:41 +0200 (So, 12. Aug 2012) | 1 Zeile Geänderte Pfade: D /trunk/src/edu/jas/gb/MiniPair.java M /trunk/src/edu/jas/gb/Pair.java cleanup unused class ------------------------------------------------------------------------ r4097 | kredel | 2012-08-12 18:35:38 +0200 (So, 12. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/ps/MultiVarPowerSeriesTest.java avoid inner classes ------------------------------------------------------------------------ r4096 | kredel | 2012-08-12 13:56:27 +0200 (So, 12. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/util/DistributedList.java M /trunk/trc/edu/jas/util/DistributedListTest.java use init for thread start ------------------------------------------------------------------------ r4095 | kredel | 2012-08-12 13:37:17 +0200 (So, 12. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/OrderedCPairlist.java M /trunk/src/edu/jas/gb/OrderedPairlist.java M /trunk/src/edu/jas/ps/OrderedPairlist.java use synchronized also for read access ------------------------------------------------------------------------ r4094 | kredel | 2012-08-12 12:59:52 +0200 (So, 12. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/util/LongIterable.java use valueOf instead of constructor ------------------------------------------------------------------------ r4093 | kredel | 2012-08-12 12:51:06 +0200 (So, 12. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/util/DistHashTableTest.java M /trunk/trc/edu/jas/util/DistributedListTest.java M /trunk/trc/edu/jas/util/SocketChannelTest.java M /trunk/trc/edu/jas/util/TaggedSocketChannelTest.java use valueOf instead of constructor ------------------------------------------------------------------------ r4092 | kredel | 2012-08-12 12:41:35 +0200 (So, 12. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RingFactoryTokenizer.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributed.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybrid.java M /trunk/src/edu/jas/gb/GroebnerBaseSeqPairDistributed.java M /trunk/src/edu/jas/poly/GenPolynomialTokenizer.java use valueOf instead of constructor ------------------------------------------------------------------------ r4091 | kredel | 2012-08-12 12:32:49 +0200 (So, 12. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/ExpVectorByte.java M /trunk/src/edu/jas/poly/ExpVectorInteger.java M /trunk/src/edu/jas/poly/ExpVectorLong.java M /trunk/src/edu/jas/poly/ExpVectorShort.java M /trunk/src/edu/jas/poly/RelationTable.java use valueOf instead of constructor ------------------------------------------------------------------------ r4089 | kredel | 2012-08-04 12:33:17 +0200 (Sa, 04. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GroebnerBaseSeqRational.java fix javadoc ------------------------------------------------------------------------ r4088 | kredel | 2012-08-03 12:52:12 +0200 (Fr, 03. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GBFactory.java prepare for new version ------------------------------------------------------------------------ r4087 | kredel | 2012-08-03 12:26:37 +0200 (Fr, 03. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GroebnerBaseSeqRational.java cosmetic via eclpise ------------------------------------------------------------------------ r4086 | kredel | 2012-08-03 12:25:34 +0200 (Fr, 03. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gbufd/GroebnerBaseSeqRationalTest.java compare test ------------------------------------------------------------------------ r4085 | kredel | 2012-08-03 12:07:29 +0200 (Fr, 03. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java add debuging ------------------------------------------------------------------------ r4084 | kredel | 2012-08-03 12:04:16 +0200 (Fr, 03. Aug 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java A /trunk/src/edu/jas/gbufd/GroebnerBaseSeqRational.java A /trunk/trc/edu/jas/gbufd/GroebnerBaseSeqRationalTest.java rational via integral coefficients GB ------------------------------------------------------------------------ r4082 | kredel | 2012-07-28 16:57:46 +0200 (Sa, 28. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/jython/Makefile add bootclasspath ------------------------------------------------------------------------ r4080 | kredel | 2012-07-28 15:10:56 +0200 (Sa, 28. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomialRing.java M /trunk/src/edu/jas/ps/MultiVarPowerSeriesRing.java undo fix for Java 5 compatibility ------------------------------------------------------------------------ r4079 | kredel | 2012-07-28 15:07:14 +0200 (Sa, 28. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/src/edu/jas/poly/GenPolynomialRing.java M /trunk/src/edu/jas/poly/PolynomialList.java call super.clone ------------------------------------------------------------------------ r4078 | kredel | 2012-07-28 14:40:12 +0200 (Sa, 28. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RingFactoryTokenizer.java M /trunk/src/edu/jas/application/RunGB.java M /trunk/src/edu/jas/application/RunSGB.java M /trunk/src/edu/jas/poly/GenPolynomialTokenizer.java M /trunk/src/edu/jas/util/ExecutableChannels.java add Charset for Readers ------------------------------------------------------------------------ r4077 | kredel | 2012-07-28 13:26:45 +0200 (Sa, 28. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomialRing.java M /trunk/src/edu/jas/ps/MultiVarPowerSeriesRing.java improve vars handling ------------------------------------------------------------------------ r4076 | kredel | 2012-07-28 13:03:10 +0200 (Sa, 28. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/ComplexRootTest.java M /trunk/trc/edu/jas/ps/MultiVarPowerSeriesTest.java M /trunk/trc/edu/jas/ufd/FactorTest.java fixes for Java 5 and 6 compatibility ------------------------------------------------------------------------ r4074 | kredel | 2012-07-28 12:04:58 +0200 (Sa, 28. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/util/DistHashTableServer.java M /trunk/src/edu/jas/util/DistributedListServer.java M /trunk/src/edu/jas/util/ExecutableServer.java M /trunk/trc/edu/jas/util/ExecutableServerTest.java rearange main ------------------------------------------------------------------------ r4073 | kredel | 2012-07-28 12:04:29 +0200 (Sa, 28. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/root/ComplexRootTest.java fixed null ------------------------------------------------------------------------ r4072 | kredel | 2012-07-27 22:08:01 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/poly/GenPolynomialTokenizerTest.java fix unit test ------------------------------------------------------------------------ r4071 | kredel | 2012-07-27 21:59:38 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/CGBSeqTest.java M /trunk/trc/edu/jas/application/ComplexRootTest.java M /trunk/trc/edu/jas/application/ExtensionFieldBuilderTest.java M /trunk/trc/edu/jas/application/HenselMultUtilTest.java M /trunk/trc/edu/jas/application/IdealTest.java M /trunk/trc/edu/jas/application/RealAlgebraicTest.java M /trunk/trc/edu/jas/application/ReductionTest.java M /trunk/trc/edu/jas/arith/ArithTest.java M /trunk/trc/edu/jas/arith/ModIntegerTest.java M /trunk/trc/edu/jas/gb/EGroebnerBaseSeqTest.java M /trunk/trc/edu/jas/gb/GBProxyTest.java M /trunk/trc/edu/jas/gbufd/CharSetTest.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java M /trunk/trc/edu/jas/gbufd/RGroebnerBasePseudoSeqTest.java M /trunk/trc/edu/jas/gbufd/RGroebnerBaseSeqTest.java M /trunk/trc/edu/jas/poly/ANumGenPolynomialTest.java M /trunk/trc/edu/jas/poly/GFGenPolynomialTest.java M /trunk/trc/edu/jas/poly/GenPolynomialTest.java M /trunk/trc/edu/jas/poly/GenPolynomialTokenizerTest.java M /trunk/trc/edu/jas/poly/TermOrderTest.java M /trunk/trc/edu/jas/ps/IteratorsTest.java M /trunk/trc/edu/jas/ps/UnivPowerSeriesTest.java M /trunk/trc/edu/jas/root/ComplexRootTest.java M /trunk/trc/edu/jas/ufd/HenselMultUtilTest.java M /trunk/trc/edu/jas/ufd/HenselUtilTest.java M /trunk/trc/edu/jas/util/IteratorsTest.java M /trunk/trc/edu/jas/vector/GenMatrixTest.java M /trunk/trc/edu/jas/vector/GenVectorTest.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4070 | kredel | 2012-07-27 20:20:15 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/vector/GenMatrix.java M /trunk/src/edu/jas/vector/GenMatrixRing.java M /trunk/src/edu/jas/vector/GenVectorModul.java fix javadoc ------------------------------------------------------------------------ r4069 | kredel | 2012-07-27 20:19:35 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PseudoReductionSeq.java finally found a suitable cast ------------------------------------------------------------------------ r4068 | kredel | 2012-07-27 18:49:22 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/ComplexRootTest.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4067 | kredel | 2012-07-27 18:17:35 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/FactorAbstract.java M /trunk/src/edu/jas/ufd/FactorFactory.java M /trunk/src/edu/jas/ufd/FactorInteger.java M /trunk/src/edu/jas/ufd/FactorModular.java M /trunk/src/edu/jas/ufd/FactorQuotient.java M /trunk/src/edu/jas/ufd/FactorRational.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorAbstract.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java M /trunk/src/edu/jas/ufd/HenselMultUtil.java M /trunk/src/edu/jas/ufd/PolyUfdUtil.java M /trunk/src/edu/jas/ufd/Quotient.java M /trunk/src/edu/jas/ufd/QuotientRing.java M /trunk/src/edu/jas/ufd/SquarefreeAbstract.java M /trunk/src/edu/jas/ufd/SquarefreeFactory.java M /trunk/src/edu/jas/ufd/SquarefreeFieldChar0.java M /trunk/src/edu/jas/ufd/SquarefreeFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeFiniteFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteAlgebraicFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeRingChar0.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4066 | kredel | 2012-07-27 17:21:28 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufdroot/FactorRealAlgebraic.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4065 | kredel | 2012-07-27 17:17:38 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/util/CartesianProduct.java M /trunk/src/edu/jas/util/CartesianProductInfinite.java M /trunk/src/edu/jas/util/CartesianProductLong.java M /trunk/src/edu/jas/util/CatReader.java M /trunk/src/edu/jas/util/DistHashTableServer.java M /trunk/src/edu/jas/util/DistThreadPool.java M /trunk/src/edu/jas/util/ListUtil.java M /trunk/src/edu/jas/util/LongIterable.java M /trunk/src/edu/jas/util/StrategyEnumeration.java M /trunk/src/edu/jas/util/ThreadPool.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4064 | kredel | 2012-07-27 16:58:03 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/vector/GenMatrix.java M /trunk/src/edu/jas/vector/GenMatrixRing.java M /trunk/src/edu/jas/vector/GenVector.java M /trunk/src/edu/jas/vector/GenVectorModul.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4063 | kredel | 2012-07-27 15:05:07 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/ComplexAlgebraicNumber.java M /trunk/src/edu/jas/root/ComplexRootsAbstract.java M /trunk/src/edu/jas/root/PolyUtilRoot.java M /trunk/src/edu/jas/root/RealAlgebraicNumber.java M /trunk/src/edu/jas/root/RealRootsAbstract.java M /trunk/src/edu/jas/root/RealRootsSturm.java M /trunk/src/edu/jas/root/RootUtil.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4062 | kredel | 2012-07-27 14:22:37 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ps/MultiVarPowerSeries.java M /trunk/src/edu/jas/ps/MultiVarPowerSeriesRing.java M /trunk/src/edu/jas/ps/ReductionSeq.java M /trunk/src/edu/jas/ps/UnivPowerSeries.java M /trunk/src/edu/jas/ps/UnivPowerSeriesRing.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4061 | kredel | 2012-07-27 14:03:20 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/CharacteristicSetSimple.java M /trunk/src/edu/jas/gbufd/CharacteristicSetWu.java M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLM.java M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLMExamples.java M /trunk/src/edu/jas/gbufd/GroebnerBasePartial.java M /trunk/src/edu/jas/gbufd/GroebnerBasePseudoRecSeq.java M /trunk/src/edu/jas/gbufd/GroebnerBasePseudoSeq.java M /trunk/src/edu/jas/gbufd/MultiplicativeSet.java M /trunk/src/edu/jas/gbufd/MultiplicativeSetCoPrime.java M /trunk/src/edu/jas/gbufd/MultiplicativeSetFactors.java M /trunk/src/edu/jas/gbufd/MultiplicativeSetSquarefree.java M /trunk/src/edu/jas/gbufd/PseudoReductionSeq.java M /trunk/src/edu/jas/gbufd/RGroebnerBasePseudoSeq.java M /trunk/src/edu/jas/gbufd/RGroebnerBaseSeq.java M /trunk/src/edu/jas/gbufd/RPseudoReductionSeq.java M /trunk/src/edu/jas/gbufd/RReductionSeq.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4060 | kredel | 2012-07-27 13:19:46 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbmod/SolvableSyzygyAbstract.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4059 | kredel | 2012-07-27 13:16:42 +0200 (Fr, 27. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/DGroebnerBaseSeq.java M /trunk/src/edu/jas/gb/DReductionSeq.java M /trunk/src/edu/jas/gb/EGroebnerBaseSeq.java M /trunk/src/edu/jas/gb/GBDist.java M /trunk/src/edu/jas/gb/GBDistSP.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributed.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybrid.java M /trunk/src/edu/jas/gb/GroebnerBaseParallel.java M /trunk/src/edu/jas/gb/GroebnerBaseSeqPairParallel.java M /trunk/src/edu/jas/gb/OrderedSyzPairlist.java M /trunk/src/edu/jas/gb/ReductionAbstract.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseParallel.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseSeq.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseSeqPairParallel.java M /trunk/src/edu/jas/gb/SolvableReductionAbstract.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4058 | kredel | 2012-07-26 23:03:53 +0200 (Do, 26. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/CReductionSeq.java M /trunk/src/edu/jas/application/ComprehensiveGroebnerBaseSeq.java M /trunk/src/edu/jas/application/Condition.java M /trunk/src/edu/jas/application/FactorAlgebraicPrim.java M /trunk/src/edu/jas/application/FactorRealReal.java M /trunk/src/edu/jas/application/Ideal.java M /trunk/src/edu/jas/application/IdealWithUniv.java M /trunk/src/edu/jas/application/Local.java M /trunk/src/edu/jas/application/OrderedCPairlist.java M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/application/PrimaryComponent.java M /trunk/src/edu/jas/application/RealAlgebraicNumber.java M /trunk/src/edu/jas/application/Residue.java M /trunk/src/edu/jas/application/RingFactoryTokenizer.java M /trunk/src/edu/jas/application/RootFactory.java M /trunk/src/edu/jas/application/RunGB.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4057 | kredel | 2012-07-26 22:35:44 +0200 (Do, 26. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/AlgebraicNumberRing.java M /trunk/src/edu/jas/poly/Examples.java M /trunk/src/edu/jas/poly/ExpVector.java M /trunk/src/edu/jas/poly/ExpVectorByte.java M /trunk/src/edu/jas/poly/ExpVectorInteger.java M /trunk/src/edu/jas/poly/ExpVectorLong.java M /trunk/src/edu/jas/poly/ExpVectorShort.java M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/src/edu/jas/poly/GenPolynomialTokenizer.java M /trunk/src/edu/jas/poly/GenSolvablePolynomialRing.java M /trunk/src/edu/jas/poly/Local.java M /trunk/src/edu/jas/poly/OrderedModuleList.java M /trunk/src/edu/jas/poly/OrderedPolynomialList.java M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/src/edu/jas/poly/Quotient.java M /trunk/src/edu/jas/poly/RelationTable.java M /trunk/src/edu/jas/poly/TermOrder.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4056 | kredel | 2012-07-26 19:44:13 +0200 (Do, 26. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/structure/AbelianGroupElem.java M /trunk/src/edu/jas/structure/AbelianGroupFactory.java M /trunk/src/edu/jas/structure/AlgebraElem.java M /trunk/src/edu/jas/structure/AlgebraFactory.java M /trunk/src/edu/jas/structure/BinaryFunctor.java M /trunk/src/edu/jas/structure/ElemFactory.java M /trunk/src/edu/jas/structure/Element.java M /trunk/src/edu/jas/structure/FieldElem.java M /trunk/src/edu/jas/structure/FieldFactory.java M /trunk/src/edu/jas/structure/GcdRingElem.java M /trunk/src/edu/jas/structure/ModulElem.java M /trunk/src/edu/jas/structure/ModulFactory.java M /trunk/src/edu/jas/structure/MonoidElem.java M /trunk/src/edu/jas/structure/MonoidFactory.java M /trunk/src/edu/jas/structure/NotInvertibleException.java M /trunk/src/edu/jas/structure/Power.java M /trunk/src/edu/jas/structure/RegularRingElem.java M /trunk/src/edu/jas/structure/RingElem.java M /trunk/src/edu/jas/structure/RingFactory.java M /trunk/src/edu/jas/structure/StarRingElem.java M /trunk/src/edu/jas/structure/UnaryFunctor.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4055 | kredel | 2012-07-26 19:37:29 +0200 (Do, 26. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/kern/PreemptStatus.java M /trunk/src/edu/jas/kern/PreemptingException.java M /trunk/src/edu/jas/kern/PrettyPrint.java M /trunk/src/edu/jas/kern/Scripting.java M /trunk/src/edu/jas/kern/StringUtil.java M /trunk/src/edu/jas/kern/TimeExceededException.java M /trunk/src/edu/jas/kern/TimeStatus.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4054 | kredel | 2012-07-26 19:34:57 +0200 (Do, 26. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/BigComplex.java M /trunk/src/edu/jas/arith/BigDecimal.java M /trunk/src/edu/jas/arith/BigInteger.java M /trunk/src/edu/jas/arith/BigOctonion.java M /trunk/src/edu/jas/arith/BigQuaternion.java M /trunk/src/edu/jas/arith/BigRational.java M /trunk/src/edu/jas/arith/ModInteger.java M /trunk/src/edu/jas/arith/ModIntegerRing.java M /trunk/src/edu/jas/arith/ModLong.java M /trunk/src/edu/jas/arith/ModLongRing.java M /trunk/src/edu/jas/arith/ModularNotInvertibleException.java M /trunk/src/edu/jas/arith/PrimeList.java M /trunk/src/edu/jas/arith/Product.java M /trunk/src/edu/jas/arith/ProductRing.java M /trunk/src/edu/jas/arith/Roots.java adjusted coding style with eclipse ------------------------------------------------------------------------ r4052 | kredel | 2012-07-25 21:20:25 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/CriticalPair.java M /trunk/src/edu/jas/gb/CriticalPairComparator.java M /trunk/src/edu/jas/gb/Pair.java M /trunk/src/edu/jas/util/DistHashTableServer.java M /trunk/src/edu/jas/util/KsubSet.java M /trunk/src/edu/jas/util/PowerSet.java stores and Serializable ------------------------------------------------------------------------ r4050 | kredel | 2012-07-25 19:14:32 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/IdealWithComplexAlgebraicRoots.java M /trunk/src/edu/jas/application/IdealWithComplexRoots.java M /trunk/src/edu/jas/application/IdealWithRealAlgebraicRoots.java M /trunk/src/edu/jas/application/IdealWithRealRoots.java fix fix redundant Serializable ------------------------------------------------------------------------ r4049 | kredel | 2012-07-25 19:10:49 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/CriticalPairList.java M /trunk/src/edu/jas/gbufd/PolyGBUtil.java fixed | and & ------------------------------------------------------------------------ r4048 | kredel | 2012-07-25 19:10:23 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/BigInteger.java fixed null returns ------------------------------------------------------------------------ r4047 | kredel | 2012-07-25 19:01:57 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/BigComplex.java M /trunk/src/edu/jas/arith/BigInteger.java M /trunk/src/edu/jas/arith/BigRational.java M /trunk/src/edu/jas/arith/ModInteger.java M /trunk/src/edu/jas/arith/ModLong.java M /trunk/src/edu/jas/arith/ModLongRing.java M /trunk/src/edu/jas/arith/PrimeList.java fix final and protected ------------------------------------------------------------------------ r4046 | kredel | 2012-07-25 18:48:54 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/integrate/Integral.java M /trunk/src/edu/jas/integrate/QuotIntegral.java M /trunk/src/edu/jas/poly/OrderedModuleList.java M /trunk/src/edu/jas/poly/OrderedPolynomialList.java fix equals and hashCode ------------------------------------------------------------------------ r4045 | kredel | 2012-07-25 18:48:23 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GBProxy.java M /trunk/src/edu/jas/ufd/GCDProxy.java mark as transient ------------------------------------------------------------------------ r4044 | kredel | 2012-07-25 18:47:40 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/TermOrder.java show Serializable in comparator ------------------------------------------------------------------------ r4043 | kredel | 2012-07-25 18:46:06 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ps/Coefficients.java M /trunk/src/edu/jas/ps/MultiVarCoefficients.java fixed missing Serializable ------------------------------------------------------------------------ r4041 | kredel | 2012-07-25 17:12:56 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/BigRational.java unread field ------------------------------------------------------------------------ r4040 | kredel | 2012-07-25 16:36:03 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GBDist.java M /trunk/src/edu/jas/gb/GBDistHybrid.java M /trunk/src/edu/jas/gb/GBDistSP.java M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/src/edu/jas/root/PolyUtilRoot.java fix unused fields ------------------------------------------------------------------------ r4039 | kredel | 2012-07-25 16:35:06 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/root/RealAlgebraicTest.java improved failure infos ------------------------------------------------------------------------ r4038 | kredel | 2012-07-25 16:34:14 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/RingElemTest.py fix blank after comma ------------------------------------------------------------------------ r4037 | kredel | 2012-07-25 15:51:21 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/PrimeList.java M /trunk/src/edu/jas/gb/GBProxy.java M /trunk/src/edu/jas/ufd/GCDProxy.java M /trunk/src/edu/jas/util/DistThreadPool.java some more findbugs ------------------------------------------------------------------------ r4036 | kredel | 2012-07-25 15:11:28 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/OrderedSyzPairlist.java M /trunk/src/edu/jas/gbufd/Examples.java M /trunk/src/edu/jas/poly/OrderedModuleList.java some null pointers ------------------------------------------------------------------------ r4035 | kredel | 2012-07-25 14:51:26 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/Ideal.java M /trunk/src/edu/jas/gb/OrderedSyzPairlist.java use entrySet for keySet ------------------------------------------------------------------------ r4034 | suess | 2012-07-25 14:45:02 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLMExamples.java improve String handling ------------------------------------------------------------------------ r4033 | kredel | 2012-07-25 14:36:16 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/ExpVector.java M /trunk/src/edu/jas/poly/GenPolynomialRing.java M /trunk/src/edu/jas/ps/MultiVarPowerSeriesRing.java fix fix for toString ------------------------------------------------------------------------ r4032 | kredel | 2012-07-25 14:03:35 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RingFactoryTokenizer.java M /trunk/src/edu/jas/gb/GroebnerBaseAbstract.java M /trunk/src/edu/jas/gbufd/CharacteristicSetWu.java M /trunk/src/edu/jas/poly/ExpVector.java M /trunk/src/edu/jas/poly/GenPolynomialRing.java M /trunk/src/edu/jas/poly/GenPolynomialTokenizer.java M /trunk/src/edu/jas/ps/MultiVarPowerSeriesRing.java improved String handling ------------------------------------------------------------------------ r4031 | kredel | 2012-07-25 12:58:50 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/GroebnerSystem.java M /trunk/src/edu/jas/application/IdealWithComplexAlgebraicRoots.java M /trunk/src/edu/jas/application/IdealWithRealAlgebraicRoots.java M /trunk/src/edu/jas/application/RootFactory.java M /trunk/src/edu/jas/gbmod/SyzygyAbstract.java fixed some more null pointer issues ------------------------------------------------------------------------ r4030 | kredel | 2012-07-25 12:57:58 +0200 (Mi, 25. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/ExpVectorByte.java M /trunk/src/edu/jas/poly/ExpVectorInteger.java M /trunk/src/edu/jas/poly/ExpVectorLong.java M /trunk/src/edu/jas/poly/ExpVectorShort.java fixed overrides ------------------------------------------------------------------------ r4029 | kredel | 2012-07-24 21:31:31 +0200 (Di, 24. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/SquarefreeAbstract.java M /trunk/src/edu/jas/ufd/SquarefreeFieldChar0.java M /trunk/src/edu/jas/ufd/SquarefreeFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeFiniteFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteAlgebraicFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeRingChar0.java change use of keySet to entrySet ------------------------------------------------------------------------ r4028 | kredel | 2012-07-24 20:42:16 +0200 (Di, 24. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/ComplexRootsAbstract.java M /trunk/src/edu/jas/ufd/FactorAbsolute.java M /trunk/src/edu/jas/ufd/FactorAbstract.java M /trunk/src/edu/jas/ufd/FactorAlgebraic.java M /trunk/src/edu/jas/ufd/FactorModular.java change use of keySet to entrySet ------------------------------------------------------------------------ r4027 | kredel | 2012-07-24 13:31:40 +0200 (Di, 24. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/arith/Product.java M /trunk/src/edu/jas/gb/DReductionSeq.java M /trunk/src/edu/jas/gb/EReductionSeq.java M /trunk/src/edu/jas/gbufd/RGroebnerBasePseudoSeq.java M /trunk/src/edu/jas/gbufd/RReductionSeq.java M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/src/edu/jas/poly/PolynomialList.java change use of keySet to entrySet ------------------------------------------------------------------------ r4026 | kredel | 2012-07-23 18:52:28 +0200 (Mo, 23. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomialRing.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorPrimitive.java M /trunk/src/edu/jas/ufd/HenselMultUtil.java M /trunk/src/edu/jas/ufd/SquarefreeFieldCharP.java removed dead stores ------------------------------------------------------------------------ r4025 | kredel | 2012-07-23 18:41:43 +0200 (Mo, 23. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/ExpVector.java M /trunk/src/edu/jas/poly/ExpVectorByte.java M /trunk/src/edu/jas/poly/ExpVectorInteger.java M /trunk/src/edu/jas/poly/ExpVectorLong.java M /trunk/src/edu/jas/poly/ExpVectorShort.java M /trunk/src/edu/jas/root/ComplexRootsSturm.java M /trunk/src/edu/jas/ufd/Examples.java M /trunk/src/edu/jas/ufd/FactorAlgebraic.java M /trunk/src/edu/jas/ufd/FactorFactory.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorHensel.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModEval.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModular.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorPrimitive.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorSimple.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorSubres.java M /trunk/src/edu/jas/ufd/HenselMultUtil.java M /trunk/src/edu/jas/ufd/HenselUtil.java M /trunk/src/edu/jas/ufd/SquarefreeFactory.java M /trunk/src/edu/jas/ufd/SquarefreeFieldChar0.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteAlgebraicFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeInfiniteFieldCharP.java M /trunk/src/edu/jas/ufd/SquarefreeRingChar0.java M /trunk/src/edu/jas/util/CartesianProductInfinite.java M /trunk/src/edu/jas/vector/GenMatrixRing.java removed dead stores ------------------------------------------------------------------------ r4024 | kredel | 2012-07-23 10:08:52 +0200 (Mo, 23. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Examples.java M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/src/edu/jas/poly/GenPolynomialRing.java M /trunk/src/edu/jas/poly/GenPolynomialTokenizer.java M /trunk/src/edu/jas/poly/PolyUtil.java removed dead stores ------------------------------------------------------------------------ r4023 | kredel | 2012-07-23 09:59:02 +0200 (Mo, 23. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/ComprehensiveGroebnerBaseSeq.java M /trunk/src/edu/jas/application/FactorAlgebraicPrim.java M /trunk/src/edu/jas/application/GroebnerSystem.java M /trunk/src/edu/jas/application/Ideal.java M /trunk/src/edu/jas/application/IdealWithComplexAlgebraicRoots.java M /trunk/src/edu/jas/application/IdealWithRealAlgebraicRoots.java M /trunk/src/edu/jas/application/RingFactoryTokenizer.java M /trunk/src/edu/jas/arith/BigRational.java M /trunk/src/edu/jas/gb/CriticalPairList.java M /trunk/src/edu/jas/gbmod/SyzygyAbstract.java M /trunk/src/edu/jas/gbufd/CharacteristicSetSimple.java M /trunk/src/edu/jas/gbufd/CharacteristicSetWu.java M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLMExamples.java M /trunk/src/edu/jas/gbufd/GroebnerBasePartial.java removed dead stores ------------------------------------------------------------------------ r4022 | kredel | 2012-07-22 21:34:20 +0200 (So, 22. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/ComplexRootTest.java M /trunk/trc/edu/jas/poly/GenPolynomialTest.java M /trunk/trc/edu/jas/poly/GenSolvablePolynomialTest.java removed dead stores ------------------------------------------------------------------------ r4021 | kredel | 2012-07-22 21:24:01 +0200 (So, 22. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/ComplexRootTest.java M /trunk/trc/edu/jas/poly/GenPolynomialTest.java M /trunk/trc/edu/jas/poly/GenSolvablePolynomialTest.java removed dead stores ------------------------------------------------------------------------ r4020 | kredel | 2012-07-22 21:19:51 +0200 (So, 22. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/ComplexRootTest.java M /trunk/trc/edu/jas/application/IdealTest.java M /trunk/trc/edu/jas/poly/GenPolynomialTest.java M /trunk/trc/edu/jas/poly/GenSolvablePolynomialTest.java M /trunk/trc/edu/jas/root/ComplexRootTest.java M /trunk/trc/edu/jas/ufd/FactorTest.java M /trunk/trc/edu/jas/ufd/PolyUfdUtilTest.java M /trunk/trc/edu/jas/vector/GenMatrixTest.java removed dead stores ------------------------------------------------------------------------ r4019 | kredel | 2012-07-22 20:31:13 +0200 (So, 22. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/root/ComplexRootTest.java M /trunk/trc/edu/jas/ufd/FactorIntegerTest.java M /trunk/trc/edu/jas/ufd/FactorModularTest.java M /trunk/trc/edu/jas/ufd/FactorRationalTest.java M /trunk/trc/edu/jas/ufd/FactorTest.java M /trunk/trc/edu/jas/ufd/GCDFactoryTest.java M /trunk/trc/edu/jas/ufd/GCDProxyTest.java M /trunk/trc/edu/jas/ufd/HenselUtilTest.java M /trunk/trc/edu/jas/ufd/PolyUfdUtilTest.java M /trunk/trc/edu/jas/ufd/SquarefreeAlgModTest.java M /trunk/trc/edu/jas/vector/GenMatrixTest.java removed dead stores ------------------------------------------------------------------------ r4018 | kredel | 2012-07-22 20:05:18 +0200 (So, 22. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/Rectangle.java M /trunk/trc/edu/jas/root/ComplexRootTest.java fixed contains ------------------------------------------------------------------------ r4017 | kredel | 2012-07-22 17:43:44 +0200 (So, 22. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gb/GBProxyTest.java fixed cancel task numbers ------------------------------------------------------------------------ r4016 | kredel | 2012-07-22 17:39:44 +0200 (So, 22. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gb/GBProxyTest.java removed dead stores ------------------------------------------------------------------------ r4015 | kredel | 2012-07-22 14:05:38 +0200 (So, 22. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/ComplexRootTest.java M /trunk/trc/edu/jas/application/ExtensionFieldBuilderTest.java M /trunk/trc/edu/jas/application/IdealTest.java M /trunk/trc/edu/jas/application/ReductionTest.java M /trunk/trc/edu/jas/gb/GBProxyTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseParSyzPairTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseSeqPairParTest.java M /trunk/trc/edu/jas/gb/ReductionTest.java M /trunk/trc/edu/jas/gbufd/GBFactoryTest.java M /trunk/trc/edu/jas/gbufd/GroebnerBasePseudoSeqTest.java M /trunk/trc/edu/jas/poly/GenPolynomialTest.java M /trunk/trc/edu/jas/poly/GenSolvablePolynomialTest.java M /trunk/trc/edu/jas/poly/PolyUtilTest.java M /trunk/trc/edu/jas/poly/TermOrderTest.java M /trunk/trc/edu/jas/ps/MultiVarPowerSeriesTest.java removed dead stores ------------------------------------------------------------------------ r4014 | kredel | 2012-07-22 09:00:47 +0200 (So, 22. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/arith/BigRationalTest.java M /trunk/trc/edu/jas/ufd/GCDHenselTest.java cleaner tests for null ------------------------------------------------------------------------ r4013 | kredel | 2012-07-21 23:19:34 +0200 (Sa, 21. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gbufd/CharSetTest.java invert logic ------------------------------------------------------------------------ r4012 | kredel | 2012-07-21 23:18:57 +0200 (Sa, 21. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/arith/BigRationalTest.java M /trunk/trc/edu/jas/ufd/GCDHenselTest.java null pointer avoid ------------------------------------------------------------------------ r4011 | kredel | 2012-07-21 23:02:45 +0200 (Sa, 21. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gb/GroebnerBaseSeqTest.java M /trunk/trc/edu/jas/root/RealAlgebraicTest.java removed dead stores ------------------------------------------------------------------------ r4010 | kredel | 2012-07-21 22:39:56 +0200 (Sa, 21. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/FactorTest.java M /trunk/trc/edu/jas/application/HenselMultUtilTest.java M /trunk/trc/edu/jas/gb/GBProxyTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseDistHybridTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseDistTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseParSyzPairTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseParTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseSeqPairDistTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseSeqPairParTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseSeqPairSeqTest.java M /trunk/trc/edu/jas/gb/GroebnerBaseSeqTest.java M /trunk/trc/edu/jas/gbufd/GroebnerBasePseudoSeqTest.java M /trunk/trc/edu/jas/gbufd/RGroebnerBasePseudoSeqTest.java M /trunk/trc/edu/jas/gbufd/RGroebnerBaseSeqTest.java M /trunk/trc/edu/jas/poly/GenPolynomialTest.java M /trunk/trc/edu/jas/poly/GenSolvablePolynomialTest.java M /trunk/trc/edu/jas/ps/MultiVarPowerSeriesTest.java M /trunk/trc/edu/jas/ps/UnivPowerSeriesTest.java M /trunk/trc/edu/jas/root/ComplexRootTest.java M /trunk/trc/edu/jas/root/RealAlgebraicTest.java M /trunk/trc/edu/jas/root/RealRootTest.java M /trunk/trc/edu/jas/ufd/FactorModularTest.java M /trunk/trc/edu/jas/ufd/FactorQuotientTest.java M /trunk/trc/edu/jas/ufd/FactorTest.java M /trunk/trc/edu/jas/ufd/HenselMultUtilTest.java M /trunk/trc/edu/jas/ufd/PolyUfdUtilTest.java M /trunk/trc/edu/jas/ufdroot/FactorRealAlgebraicTest.java removed dead stores ------------------------------------------------------------------------ r4009 | kredel | 2012-07-16 23:41:42 +0200 (Mo, 16. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/Ideal.java M /trunk/src/edu/jas/application/RootFactory.java M /trunk/src/edu/jas/gbufd/GroebnerBasePartial.java M /trunk/src/edu/jas/root/ComplexRootsSturm.java M /trunk/src/edu/jas/ufd/FactorAbsolute.java M /trunk/src/edu/jas/ufd/HenselMultUtil.java M /trunk/src/edu/jas/ufd/HenselUtil.java fixed dead stores ------------------------------------------------------------------------ r4008 | kredel | 2012-07-15 21:51:40 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/CharacteristicSetWu.java M /trunk/src/edu/jas/gbufd/PolyGBUtil.java special case ------------------------------------------------------------------------ r4007 | kredel | 2012-07-15 21:51:05 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gbufd/CharSetTest.java improved tests ------------------------------------------------------------------------ r4005 | kredel | 2012-07-15 20:37:10 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomial.java cosmetic ------------------------------------------------------------------------ r4003 | kredel | 2012-07-15 19:19:19 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLMExamples.java fix possible null pointers ------------------------------------------------------------------------ r4002 | kredel | 2012-07-15 19:15:06 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/ExpVectorShort.java add comment ------------------------------------------------------------------------ r4000 | kredel | 2012-07-15 18:20:34 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/RingElemTest.py fixed GF case ------------------------------------------------------------------------ r3998 | kredel | 2012-07-15 15:12:53 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/ModIntegerRing.java M /trunk/src/edu/jas/arith/ModLongRing.java add GF case for toScript ------------------------------------------------------------------------ r3997 | kredel | 2012-07-15 15:12:04 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb improve GF ------------------------------------------------------------------------ r3996 | kredel | 2012-07-15 15:04:13 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/trinks.py M /trunk/examples/trinks.rb A /trunk/examples/trinks_str.py A /trunk/examples/trinks_str.rb use scripting expressions ------------------------------------------------------------------------ r3995 | kredel | 2012-07-15 14:08:00 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: D /trunk/examples/rose.mas removed old example ------------------------------------------------------------------------ r3994 | kredel | 2012-07-15 13:50:54 +0200 (So, 15. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/Pair.java M /trunk/src/edu/jas/poly/ExpVectorByte.java M /trunk/src/edu/jas/poly/ExpVectorInteger.java M /trunk/src/edu/jas/poly/ExpVectorLong.java M /trunk/src/edu/jas/poly/ExpVectorShort.java M /trunk/src/edu/jas/poly/PolynomialComparator.java M /trunk/src/edu/jas/ps/Pair.java M /trunk/src/edu/jas/util/DistributedListServer.java add some missing hashCodes ------------------------------------------------------------------------ r3993 | kredel | 2012-07-14 23:39:15 +0200 (Sa, 14. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/Boundary.java M /trunk/src/edu/jas/root/Interval.java M /trunk/src/edu/jas/root/RealRootTuple.java M /trunk/src/edu/jas/root/Rectangle.java implement Cloneable ------------------------------------------------------------------------ r3992 | kredel | 2012-07-14 23:32:18 +0200 (Sa, 14. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/ReductionAbstract.java M /trunk/src/edu/jas/gb/SolvableReductionAbstract.java M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLMExamples.java M /trunk/src/edu/jas/gbufd/MultiplicativeSet.java M /trunk/src/edu/jas/poly/ModuleList.java M /trunk/src/edu/jas/ps/MultiVarPowerSeriesRing.java M /trunk/src/edu/jas/ps/UnivPowerSeries.java M /trunk/src/edu/jas/ps/UnivPowerSeriesRing.java M /trunk/src/edu/jas/root/Boundary.java M /trunk/src/edu/jas/root/RealRootTuple.java M /trunk/src/edu/jas/ufd/FactorsMap.java possible null pointer cleanup ------------------------------------------------------------------------ r3991 | kredel | 2012-07-14 15:56:59 +0200 (Sa, 14. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/ExpVectorByte.java M /trunk/src/edu/jas/poly/ExpVectorInteger.java M /trunk/src/edu/jas/poly/ExpVectorShort.java M /trunk/src/edu/jas/root/Boundary.java M /trunk/src/edu/jas/root/Rectangle.java M /trunk/src/edu/jas/util/DHTTransport.java fixed some statics and finals ------------------------------------------------------------------------ r3990 | kredel | 2012-07-14 14:46:08 +0200 (Sa, 14. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseDistributed.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybrid.java M /trunk/src/edu/jas/gb/GroebnerBaseParallel.java M /trunk/src/edu/jas/gb/GroebnerBaseSeqPairDistributed.java M /trunk/src/edu/jas/gb/GroebnerBaseSeqPairParallel.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseParallel.java M /trunk/src/edu/jas/gb/SolvableGroebnerBaseSeqPairParallel.java add missing transients ------------------------------------------------------------------------ r3989 | kredel | 2012-07-14 14:39:14 +0200 (Sa, 14. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/CReductionSeq.java M /trunk/src/edu/jas/root/ComplexRoots.java M /trunk/src/edu/jas/root/RealRootTuple.java M /trunk/src/edu/jas/root/RealRoots.java M /trunk/src/edu/jas/ufd/Squarefree.java add missing serializations ------------------------------------------------------------------------ r3988 | kredel | 2012-07-14 14:07:13 +0200 (Sa, 14. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/MultiplicativeSetCoPrime.java M /trunk/src/edu/jas/gbufd/MultiplicativeSetFactors.java M /trunk/src/edu/jas/gbufd/MultiplicativeSetSquarefree.java M /trunk/src/edu/jas/poly/GenSolvablePolynomial.java M /trunk/src/edu/jas/poly/OptimizedPolynomialList.java add missing equals ------------------------------------------------------------------------ r3987 | kredel | 2012-07-14 13:58:20 +0200 (Sa, 14. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ps/Examples.java M /trunk/src/edu/jas/root/ComplexAlgebraicRing.java M /trunk/src/edu/jas/root/RealAlgebraicRing.java make varaible static ------------------------------------------------------------------------ r3986 | kredel | 2012-07-14 13:39:27 +0200 (Sa, 14. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseDistributed.java M /trunk/src/edu/jas/gb/GroebnerBaseDistributedHybrid.java M /trunk/src/edu/jas/gb/GroebnerBaseSeqPairDistributed.java M /trunk/src/edu/jas/util/DistHashTable.java M /trunk/trc/edu/jas/util/DistHashTableTest.java move start out of constructor ------------------------------------------------------------------------ r3985 | kredel | 2012-07-14 12:51:53 +0200 (Sa, 14. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomialTokenizer.java fix switch default ------------------------------------------------------------------------ r3984 | kredel | 2012-07-12 23:36:16 +0200 (Do, 12. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/ColorPolynomial.java M /trunk/src/edu/jas/root/Interval.java M /trunk/src/edu/jas/root/Rectangle.java serializable by findbugs ------------------------------------------------------------------------ r3983 | kredel | 2012-07-12 23:18:20 +0200 (Do, 12. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomialRing.java M /trunk/src/edu/jas/ps/MultiVarPowerSeriesRing.java M /trunk/src/edu/jas/root/Interval.java M /trunk/trc/edu/jas/arith/BigIntegerTest.java null pointer by findbugs ------------------------------------------------------------------------ r3982 | kredel | 2012-07-12 23:00:59 +0200 (Do, 12. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/GroebnerBaseSeqPairDistributed.java M /trunk/src/edu/jas/util/TaggedSocketChannel.java null value by findbugs ------------------------------------------------------------------------ r3981 | kredel | 2012-07-12 22:51:22 +0200 (Do, 12. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbmod/SolvableSyzygyAbstract.java M /trunk/src/edu/jas/gbmod/SyzygyAbstract.java M /trunk/src/edu/jas/poly/GenPolynomialRing.java M /trunk/src/edu/jas/ps/ReductionSeq.java nullcheck by findbugs ------------------------------------------------------------------------ r3980 | kredel | 2012-07-12 22:36:12 +0200 (Do, 12. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java nonnull parameters by findbugs ------------------------------------------------------------------------ r3979 | kredel | 2012-07-09 23:13:53 +0200 (Mo, 09. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/ComplexAlgebraicNumber.java M /trunk/src/edu/jas/root/RealAlgebraicNumber.java M /trunk/src/edu/jas/util/Terminator.java sync bugs by findbugs ------------------------------------------------------------------------ r3978 | kredel | 2012-07-09 23:10:01 +0200 (Mo, 09. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/GroebnerBaseFGLMExamples.java M /trunk/src/edu/jas/ps/MultiVarPowerSeries.java M /trunk/src/edu/jas/ps/UnivPowerSeries.java M /trunk/src/edu/jas/root/RootUtil.java M /trunk/src/edu/jas/structure/Power.java M /trunk/src/edu/jas/ufd/FactorAbsolute.java simple bugs by PMD ------------------------------------------------------------------------ r3977 | kredel | 2012-07-05 00:01:49 +0200 (Do, 05. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/download.html M /trunk/examples/trinks.py M /trunk/examples/trinks.rb improved start examples ------------------------------------------------------------------------ r3976 | kredel | 2012-07-05 00:00:48 +0200 (Do, 05. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb corrected comments ------------------------------------------------------------------------ r3974 | kredel | 2012-07-01 14:29:44 +0200 (So, 01. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/RootFactory.java M /trunk/trc/edu/jas/root/RootUtilTest.java fixed multiple roots ------------------------------------------------------------------------ r3973 | kredel | 2012-07-01 13:26:02 +0200 (So, 01. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gb/SolvableGroebnerBaseAbstract.java M /trunk/src/edu/jas/gbmod/ModSolvableGroebnerBaseAbstract.java M /trunk/src/edu/jas/poly/TermOrder.java fixed right module GB and split term orders ------------------------------------------------------------------------ r3972 | kredel | 2012-07-01 13:19:24 +0200 (So, 01. Jul 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/solvablemodule.py A /trunk/examples/solvablemodule.rb A /trunk/examples/solvablepolynomial.rb M /trunk/examples/solvmodright.py A /trunk/examples/solvmodright.rb more ruby examples and rightGB fixes ------------------------------------------------------------------------ r3971 | kredel | 2012-06-30 18:53:10 +0200 (Sa, 30. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb fix indentation ------------------------------------------------------------------------ r3970 | kredel | 2012-06-30 18:18:21 +0200 (Sa, 30. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb M /trunk/examples/powerseries_multi.rb A /trunk/examples/sicora.rb A /trunk/examples/solvable.rb A /trunk/examples/squarefree_poly.rb A /trunk/examples/suzukiSato_ex1.rb A /trunk/examples/tuzun.rb more ruby examples ------------------------------------------------------------------------ r3969 | kredel | 2012-06-30 16:31:43 +0200 (Sa, 30. Jun 2012) | 1 Zeile Geänderte Pfade: A /trunk/examples/integrate.rb M /trunk/examples/jas.rb A /trunk/examples/powerseries_multi.rb A /trunk/examples/pppj2006.rb more ruby examples ------------------------------------------------------------------------ r3968 | kredel | 2012-06-30 14:24:45 +0200 (Sa, 30. Jun 2012) | 1 Zeile Geänderte Pfade: A /trunk/examples/factors_mod.rb A /trunk/examples/factors_mod_abs.rb A /trunk/examples/factors_mod_ins.rb A /trunk/examples/factors_mult.rb more ruby examples ------------------------------------------------------------------------ r3967 | kredel | 2012-06-30 13:45:11 +0200 (Sa, 30. Jun 2012) | 1 Zeile Geänderte Pfade: A /trunk/examples/cgb_4.py A /trunk/examples/cgb_4.rb A /trunk/examples/cyclic5_complex_roots.rb A /trunk/examples/cyclic5_real_roots.rb M /trunk/examples/jas.rb more ruby examples ------------------------------------------------------------------------ r3966 | kredel | 2012-06-30 12:41:17 +0200 (Sa, 30. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb fixed elem to ring ------------------------------------------------------------------------ r3965 | kredel | 2012-06-16 17:28:52 +0200 (Sa, 16. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/root/RootUtilTest.java better diagnose ------------------------------------------------------------------------ r3964 | kredel | 2012-06-16 16:32:47 +0200 (Sa, 16. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/root/ComplexRootsSturm.java cleanup ------------------------------------------------------------------------ r3963 | kredel | 2012-06-16 16:32:14 +0200 (Sa, 16. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Complex.java M /trunk/src/edu/jas/root/Rectangle.java fixed toScript ------------------------------------------------------------------------ r3962 | kredel | 2012-06-16 16:14:12 +0200 (Sa, 16. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/root/ComplexRootsSturm.java clean up ------------------------------------------------------------------------ r3961 | kredel | 2012-06-16 16:13:33 +0200 (Sa, 16. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/trc/edu/jas/poly/PolyUtilTest.java variable removal and test cases ------------------------------------------------------------------------ r3959 | kredel | 2012-06-10 21:00:34 +0200 (So, 10. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java remove unused code ------------------------------------------------------------------------ r3958 | kredel | 2012-06-10 20:47:17 +0200 (So, 10. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/ComplexRootsSturm.java improve compex root count ------------------------------------------------------------------------ r3957 | kredel | 2012-06-10 20:46:27 +0200 (So, 10. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/RealRootsSturm.java fix some corner cases ------------------------------------------------------------------------ r3956 | kredel | 2012-06-10 20:45:21 +0200 (So, 10. Jun 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/Rectangle.java new length methods ------------------------------------------------------------------------ r3954 | kredel | 2012-05-28 21:29:12 +0200 (Mo, 28. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/trc/edu/jas/poly/PolyUtilTest.java doc cosmetic ------------------------------------------------------------------------ r3953 | kredel | 2012-05-28 21:19:32 +0200 (Mo, 28. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java avoid zero length intervals ------------------------------------------------------------------------ r3952 | kredel | 2012-05-28 19:48:23 +0200 (Mo, 28. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java avoid zero length intervals ------------------------------------------------------------------------ r3951 | kredel | 2012-05-28 19:47:29 +0200 (Mo, 28. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/Interval.java added middle method ------------------------------------------------------------------------ r3950 | kredel | 2012-05-28 15:15:06 +0200 (Mo, 28. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java remove unused middle variables ------------------------------------------------------------------------ r3949 | kredel | 2012-05-28 14:27:31 +0200 (Mo, 28. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java cosmetic and algo split ------------------------------------------------------------------------ r3948 | kredel | 2012-05-28 12:51:36 +0200 (Mo, 28. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java prepare root selection via complexRootCount ------------------------------------------------------------------------ r3947 | kredel | 2012-05-28 12:50:47 +0200 (Mo, 28. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RealAlgebraicNumber.java M /trunk/src/edu/jas/application/RealAlgebraicRing.java M /trunk/src/edu/jas/application/RootFactory.java add some missing methods ------------------------------------------------------------------------ r3946 | kredel | 2012-05-20 15:59:50 +0200 (So, 20. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/IdealWithComplexAlgebraicRoots.java M /trunk/src/edu/jas/root/ComplexRootsAbstract.java M /trunk/src/edu/jas/root/RootFactory.java improved checks ------------------------------------------------------------------------ r3945 | kredel | 2012-05-20 15:59:15 +0200 (So, 20. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java small improvements ------------------------------------------------------------------------ r3944 | kredel | 2012-05-20 15:57:04 +0200 (So, 20. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py fixed elem to ring ------------------------------------------------------------------------ r3943 | kredel | 2012-05-17 13:09:23 +0200 (Do, 17. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/RootFactory.java M /trunk/src/edu/jas/root/RealRootsAbstract.java cleanup ------------------------------------------------------------------------ r3942 | kredel | 2012-05-17 13:06:47 +0200 (Do, 17. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/IdealTest.java fix eps ------------------------------------------------------------------------ r3941 | kredel | 2012-05-13 16:45:21 +0200 (So, 13. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/root/RealRootsAbstract.java use integer root bounds and ceiling for maginitude ------------------------------------------------------------------------ r3940 | kredel | 2012-05-13 16:44:14 +0200 (So, 13. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/root/RealRootsSturm.java more logging ------------------------------------------------------------------------ r3939 | kredel | 2012-05-07 12:26:16 +0200 (Mo, 07. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/charset.py M /trunk/examples/charset.rb M /trunk/trc/edu/jas/gbufd/CharSetTest.java fixed typo in example ------------------------------------------------------------------------ r3938 | kredel | 2012-05-06 22:08:39 +0200 (So, 06. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb fix return value ------------------------------------------------------------------------ r3936 | kredel | 2012-05-06 21:19:18 +0200 (So, 06. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/charset.py A /trunk/examples/charset.rb M /trunk/examples/jas.py M /trunk/examples/jas.rb char set for jruby ------------------------------------------------------------------------ r3935 | kredel | 2012-05-06 20:21:10 +0200 (So, 06. Mai 2012) | 1 Zeile Geänderte Pfade: A /trunk/examples/charset.py M /trunk/examples/jas.py M /trunk/trc/edu/jas/gbufd/CharSetTest.java char set methods for jython ------------------------------------------------------------------------ r3934 | kredel | 2012-05-06 18:23:22 +0200 (So, 06. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/src/edu/jas/poly/GenPolynomialRing.java cosmetic ------------------------------------------------------------------------ r3933 | kredel | 2012-05-06 18:07:24 +0200 (So, 06. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/trc/edu/jas/gbufd/CharSetTest.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java impoved top remainder ------------------------------------------------------------------------ r3932 | kredel | 2012-05-06 17:35:00 +0200 (So, 06. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/CharacteristicSetSimple.java M /trunk/src/edu/jas/gbufd/CharacteristicSetWu.java M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/trc/edu/jas/gbufd/CharSetTest.java refactor method names ------------------------------------------------------------------------ r3931 | kredel | 2012-05-06 13:55:44 +0200 (So, 06. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gbufd/CharSetTest.java simple CS tests ------------------------------------------------------------------------ r3930 | kredel | 2012-05-06 13:44:55 +0200 (So, 06. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/CharacteristicSet.java A /trunk/src/edu/jas/gbufd/CharacteristicSetSimple.java M /trunk/src/edu/jas/gbufd/CharacteristicSetWu.java M /trunk/src/edu/jas/gbufd/PolyGBUtil.java simple CS algorithm ------------------------------------------------------------------------ r3929 | kredel | 2012-05-06 00:16:12 +0200 (So, 06. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/CharacteristicSetWu.java M /trunk/trc/edu/jas/gbufd/CharSetTest.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java cosmetic ------------------------------------------------------------------------ r3928 | kredel | 2012-05-05 21:51:33 +0200 (Sa, 05. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/CharacteristicSet.java M /trunk/src/edu/jas/gbufd/CharacteristicSetWu.java M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/trc/edu/jas/gbufd/CharSetTest.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java eclipse formating and fixes ------------------------------------------------------------------------ r3927 | kredel | 2012-05-05 21:38:48 +0200 (Sa, 05. Mai 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/gbufd/CharacteristicSet.java A /trunk/src/edu/jas/gbufd/CharacteristicSetWu.java M /trunk/src/edu/jas/gbufd/PolyGBUtil.java A /trunk/trc/edu/jas/gbufd/CharSetTest.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java refactoring to separate CharSet class ------------------------------------------------------------------------ r3926 | kredel | 2012-05-04 00:03:44 +0200 (Fr, 04. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java make remainder monic ------------------------------------------------------------------------ r3925 | kredel | 2012-05-03 23:48:39 +0200 (Do, 03. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java fixed recursion and cosmetic ------------------------------------------------------------------------ r3924 | kredel | 2012-05-01 22:23:14 +0200 (Di, 01. Mai 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java methods for coefficient pseudo reduction ------------------------------------------------------------------------ r3923 | kredel | 2012-04-15 19:58:03 +0200 (So, 15. Apr 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/poly/PolyUtilTest.java M /trunk/trc/edu/jas/ufd/PolyUfdUtilTest.java add more tests ------------------------------------------------------------------------ r3922 | kredel | 2012-04-15 19:20:27 +0200 (So, 15. Apr 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/trc/edu/jas/poly/PolyUtilTest.java M /trunk/trc/edu/jas/ufd/PolyUfdUtilTest.java fixe pseudo quotient ------------------------------------------------------------------------ r3921 | kredel | 2012-04-15 17:36:50 +0200 (So, 15. Apr 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py cosmetic ------------------------------------------------------------------------ r3920 | kredel | 2012-04-15 17:35:30 +0200 (So, 15. Apr 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java M /trunk/trc/edu/jas/poly/PolyUtilTest.java M /trunk/trc/edu/jas/ufd/PolyUfdUtilTest.java more tests and some fixes ------------------------------------------------------------------------ r3918 | kredel | 2012-03-17 23:42:31 +0100 (Sa, 17. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb fixed pass from python ------------------------------------------------------------------------ r3917 | kredel | 2012-03-17 22:48:15 +0100 (Sa, 17. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py fix self parameter ------------------------------------------------------------------------ r3916 | kredel | 2012-03-17 22:19:40 +0100 (Sa, 17. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py use super.__init__ for initialization ------------------------------------------------------------------------ r3915 | kredel | 2012-03-17 22:19:15 +0100 (Sa, 17. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb use super for initialization ------------------------------------------------------------------------ r3914 | axelclk | 2012-03-17 21:50:46 +0100 (Sa, 17. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/PrimeList.java chaching for prime lists ------------------------------------------------------------------------ r3913 | kredel | 2012-03-11 19:13:38 +0100 (So, 11. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb M /trunk/jas-log.html update ------------------------------------------------------------------------ r3912 | suess | 2012-03-11 18:36:56 +0100 (So, 11. Mär 2012) | 1 Zeile Geänderte Pfade: A /trunk/trc/edu/jas/gbufd/GroebnerBaseFGLMTest.java FGLM unit test ------------------------------------------------------------------------ r3911 | suess | 2012-03-11 18:35:07 +0100 (So, 11. Mär 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/gbufd/GroebnerBaseFGLMExamples.java FGLM version of GB ------------------------------------------------------------------------ r3910 | suess | 2012-03-11 18:31:51 +0100 (So, 11. Mär 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/gbufd/GroebnerBaseFGLM.java FGLM version of GB ------------------------------------------------------------------------ r3909 | kredel | 2012-03-11 18:25:01 +0100 (So, 11. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb fix class instance variable ------------------------------------------------------------------------ r3908 | kredel | 2012-03-11 14:24:55 +0100 (So, 11. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/examples/jas.rb injevt_variables for ruby ------------------------------------------------------------------------ r3907 | kredel | 2012-03-10 23:50:46 +0100 (Sa, 10. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/RingElemTest.py refix blank ------------------------------------------------------------------------ r3906 | kredel | 2012-03-10 13:21:18 +0100 (Sa, 10. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/src/edu/jas/poly/GenPolynomialRing.java change {} to () for recursion ------------------------------------------------------------------------ r3905 | kredel | 2012-03-10 13:17:22 +0100 (Sa, 10. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb M /trunk/jas add inject_variables ------------------------------------------------------------------------ r3904 | kredel | 2012-03-08 00:09:00 +0100 (Do, 08. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py auto_inject variables ------------------------------------------------------------------------ r3900 | kredel | 2012-03-04 23:50:20 +0100 (So, 04. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/RingElemTest.py fix blank ------------------------------------------------------------------------ r3899 | kredel | 2012-03-04 23:04:50 +0100 (So, 04. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py fix instance variables ------------------------------------------------------------------------ r3898 | kredel | 2012-03-04 22:53:16 +0100 (So, 04. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py M /trunk/jas define polynomial ring instance variables ------------------------------------------------------------------------ r3897 | kredel | 2012-03-04 21:04:36 +0100 (So, 04. Mär 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/all_rings.py M /trunk/examples/jas.py M /trunk/examples/jas.rb A /trunk/jas new script launcher ------------------------------------------------------------------------ r3895 | kredel | 2012-02-26 21:32:54 +0100 (So, 26. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py more Sage compatibility methods ------------------------------------------------------------------------ r3894 | kredel | 2012-02-26 21:31:47 +0100 (So, 26. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/FactorInteger.java print to logging ------------------------------------------------------------------------ r3893 | kredel | 2012-02-25 13:54:26 +0100 (Sa, 25. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.rb A /trunk/examples/roots_complex_ideal.rb A /trunk/examples/roots_real_ideal.rb M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java add and use missing method ------------------------------------------------------------------------ r3892 | kredel | 2012-02-25 13:35:24 +0100 (Sa, 25. Feb 2012) | 1 Zeile Geänderte Pfade: A /trunk/examples/cyclic5_complex_roots.py M /trunk/examples/cyclic5_real_roots.py M /trunk/examples/jas.py M /trunk/examples/roots_complex_ideal.py A /trunk/examples/roots_real_ideal.py M /trunk/src/edu/jas/application/PolyUtilApp.java add and use missing method ------------------------------------------------------------------------ r3891 | kredel | 2012-02-25 13:02:13 +0100 (Sa, 25. Feb 2012) | 1 Zeile Geänderte Pfade: A /trunk/examples/real_roots_ideal.py forgotten commit ------------------------------------------------------------------------ r3889 | kredel | 2012-02-24 19:58:06 +0100 (Fr, 24. Feb 2012) | 1 Zeile Geänderte Pfade: A /trunk/examples/RingElemTest.py M /trunk/examples/jas.py M /trunk/examples/jas.rb add length method ------------------------------------------------------------------------ r3888 | kredel | 2012-02-11 19:32:34 +0100 (Sa, 11. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/FactorInteger.java M /trunk/trc/edu/jas/ufd/FactorMoreTest.java fixed permutation after Kronecker ------------------------------------------------------------------------ r3887 | kredel | 2012-02-11 13:48:43 +0100 (Sa, 11. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/ResidueTest.java fixed test case ------------------------------------------------------------------------ r3886 | kredel | 2012-02-11 13:34:14 +0100 (Sa, 11. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/FactorInteger.java M /trunk/trc/edu/jas/ufd/FactorMoreTest.java fixed when no correct factorization ------------------------------------------------------------------------ r3883 | kredel | 2012-02-05 19:43:31 +0100 (So, 05. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/FactorFactory.java M /trunk/src/edu/jas/ufd/FactorComplex.java M /trunk/src/edu/jas/ufd/FactorFactory.java improve cases for complex coefficients ------------------------------------------------------------------------ r3882 | kredel | 2012-02-05 18:53:12 +0100 (So, 05. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/AlgebraicNumber.java M /trunk/src/edu/jas/poly/AlgebraicNumberRing.java M /trunk/src/edu/jas/poly/ComplexRing.java loosen requirements for coefficients ------------------------------------------------------------------------ r3881 | kredel | 2012-02-05 18:47:46 +0100 (So, 05. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Complex.java M /trunk/src/edu/jas/root/ComplexRoots.java M /trunk/src/edu/jas/root/ComplexRootsAbstract.java M /trunk/src/edu/jas/root/ComplexRootsSturm.java M /trunk/src/edu/jas/root/RealRoots.java M /trunk/src/edu/jas/root/RealRootsAbstract.java M /trunk/src/edu/jas/root/RealRootsSturm.java loosen requirements of coefficients ------------------------------------------------------------------------ r3880 | kredel | 2012-02-05 18:09:56 +0100 (So, 05. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/PolyUtilApp.java D /trunk/src/edu/jas/root/RealRootAbstract.java A /trunk/src/edu/jas/root/RealRootsAbstract.java (von /trunk/src/edu/jas/root/RealRootAbstract.java:3879) M /trunk/src/edu/jas/root/RealRootsSturm.java M /trunk/trc/edu/jas/root/RealRootTest.java consistent naming ------------------------------------------------------------------------ r3879 | kredel | 2012-02-05 17:51:04 +0100 (So, 05. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/Examples.java M /trunk/src/edu/jas/application/IdealWithRealAlgebraicRoots.java M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/application/RootFactory.java M /trunk/src/edu/jas/root/RealRootAbstract.java M /trunk/src/edu/jas/root/RealRoots.java M /trunk/src/edu/jas/root/RealRootsSturm.java M /trunk/trc/edu/jas/application/IdealTest.java M /trunk/trc/edu/jas/application/RealAlgebraicTest.java simplify type parameters ------------------------------------------------------------------------ r3878 | kredel | 2012-02-05 17:36:34 +0100 (So, 05. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/Examples.java M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/src/edu/jas/application/RootFactory.java M /trunk/src/edu/jas/root/ComplexRoots.java M /trunk/src/edu/jas/root/ComplexRootsAbstract.java M /trunk/src/edu/jas/root/ComplexRootsSturm.java M /trunk/trc/edu/jas/application/IdealTest.java M /trunk/trc/edu/jas/application/RealAlgebraicTest.java simplify type parameters ------------------------------------------------------------------------ r3877 | kredel | 2012-02-05 14:02:05 +0100 (So, 05. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/IdealWithComplexAlgebraicRoots.java M /trunk/src/edu/jas/application/PolyUtilApp.java M /trunk/trc/edu/jas/application/IdealTest.java simplify type parameters ------------------------------------------------------------------------ r3876 | kredel | 2012-02-05 13:50:21 +0100 (So, 05. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/Complex.java M /trunk/src/edu/jas/poly/ComplexRing.java M /trunk/src/edu/jas/root/Rectangle.java M /trunk/src/edu/jas/structure/GcdRingElem.java M /trunk/src/edu/jas/ufd/FactorComplex.java more constructors for factorization ------------------------------------------------------------------------ r3873 | kredel | 2012-02-04 19:46:18 +0100 (Sa, 04. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/jython ignore some files ------------------------------------------------------------------------ r3872 | kredel | 2012-02-04 19:44:49 +0100 (Sa, 04. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/examples M /trunk/jython ignore some files ------------------------------------------------------------------------ r3871 | kredel | 2012-02-04 19:39:19 +0100 (Sa, 04. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/FactorFactory.java M /trunk/src/edu/jas/ufd/FactorFactory.java logging cosmetic ------------------------------------------------------------------------ r3870 | kredel | 2012-02-04 12:46:17 +0100 (Sa, 04. Feb 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/ufdroot/package.html new package info ------------------------------------------------------------------------ r3869 | kredel | 2012-02-03 23:03:59 +0100 (Fr, 03. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/application/ComplexRootTest.java M /trunk/trc/edu/jas/application/FactorRealRealTest.java impoved factory selection ------------------------------------------------------------------------ r3868 | kredel | 2012-02-03 22:48:52 +0100 (Fr, 03. Feb 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/FactorFactory.java M /trunk/src/edu/jas/application/RealAlgebraicRing.java M /trunk/src/edu/jas/root/RealAlgebraicRing.java M /trunk/src/edu/jas/ufdroot/FactorRealAlgebraic.java M /trunk/trc/edu/jas/application/FactorRealRealTest.java impoved factory selection ------------------------------------------------------------------------ r3867 | kredel | 2012-01-30 23:24:48 +0100 (Mo, 30. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/FactorAlgebraicPrim.java M /trunk/src/edu/jas/application/FactorFactory.java M /trunk/src/edu/jas/application/FactorRealReal.java M /trunk/src/edu/jas/ufd/FactorAlgebraic.java M /trunk/src/edu/jas/ufd/FactorFactory.java M /trunk/src/edu/jas/ufd/FactorQuotient.java M /trunk/src/edu/jas/ufdroot/FactorRealAlgebraic.java extend constructors with engines for base factorization ------------------------------------------------------------------------ r3866 | kredel | 2012-01-29 21:39:11 +0100 (So, 29. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/FactorFactory.java M /trunk/src/edu/jas/ufd/FactorFactory.java fix dependency cycle ------------------------------------------------------------------------ r3865 | kredel | 2012-01-29 19:12:16 +0100 (So, 29. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/FactorFactory.java D /trunk/src/edu/jas/ufd/FactorRealAlgebraic.java A /trunk/src/edu/jas/ufdroot/FactorRealAlgebraic.java (von /trunk/src/edu/jas/ufd/FactorRealAlgebraic.java:3676) D /trunk/trc/edu/jas/ufd/FactorRealAlgebraicTest.java A /trunk/trc/edu/jas/ufdroot/FactorRealAlgebraicTest.java (von /trunk/trc/edu/jas/ufd/FactorRealAlgebraicTest.java:3789) move to ufdroot ------------------------------------------------------------------------ r3864 | kredel | 2012-01-29 18:58:30 +0100 (So, 29. Jan 2012) | 1 Zeile Geänderte Pfade: A /trunk/src/edu/jas/ufdroot A /trunk/trc/edu/jas/ufdroot new package ------------------------------------------------------------------------ r3862 | kredel | 2012-01-08 13:35:38 +0100 (So, 08. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java more tests ------------------------------------------------------------------------ r3861 | kredel | 2012-01-08 13:26:45 +0100 (So, 08. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomial.java cleanup ------------------------------------------------------------------------ r3859 | kredel | 2012-01-08 12:40:35 +0100 (So, 08. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java reduced output ------------------------------------------------------------------------ r3857 | kredel | 2012-01-07 17:44:52 +0100 (Sa, 07. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java more cs methods ------------------------------------------------------------------------ r3856 | kredel | 2012-01-07 16:44:14 +0100 (Sa, 07. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/Ideal.java select max independent set with small variables ------------------------------------------------------------------------ r3855 | kredel | 2012-01-07 13:58:37 +0100 (Sa, 07. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java some characteristic set methods ------------------------------------------------------------------------ r3854 | kredel | 2012-01-07 13:58:01 +0100 (Sa, 07. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/application/Examples.java cosmetic ------------------------------------------------------------------------ r3853 | kredel | 2012-01-01 20:32:34 +0100 (So, 01. Jan 2012) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorAbstract.java added gcd for lists of polynomials ------------------------------------------------------------------------ r3852 | kredel | 2011-12-31 21:03:57 +0100 (Sa, 31. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GCDFactory.java M /trunk/src/edu/jas/ufd/SquarefreeFactory.java cleanup ------------------------------------------------------------------------ r3851 | kredel | 2011-12-30 19:30:04 +0100 (Fr, 30. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/PolyUtil.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModEval.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorSubres.java fixed doc links ------------------------------------------------------------------------ r3850 | kredel | 2011-12-30 19:29:00 +0100 (Fr, 30. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/trc/edu/jas/ufd/GCDSimpleTest.java M /trunk/trc/edu/jas/ufd/GCDSubresTest.java reduce print out ------------------------------------------------------------------------ r3849 | kredel | 2011-12-30 19:27:45 +0100 (Fr, 30. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/examples/jas.py fixed indentation ------------------------------------------------------------------------ r3847 | kredel | 2011-12-30 13:57:31 +0100 (Fr, 30. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GCDProxy.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModEval.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModular.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java M /trunk/trc/edu/jas/ufd/GCDModEvalTest.java reduce logging output and fix mufd selection ------------------------------------------------------------------------ r3846 | kredel | 2011-12-29 21:53:18 +0100 (Do, 29. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GCDProxy.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java parallel proxy for resultants and tests ------------------------------------------------------------------------ r3845 | kredel | 2011-12-29 19:49:37 +0100 (Do, 29. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModEval.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModular.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java special cases and partially fixed degree bounds ------------------------------------------------------------------------ r3844 | kredel | 2011-12-29 13:56:04 +0100 (Do, 29. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModEval.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModular.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorSubres.java undo fix of leadingExpVector ------------------------------------------------------------------------ r3843 | kredel | 2011-12-29 12:56:02 +0100 (Do, 29. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/gbufd/PolyGBUtil.java M /trunk/src/edu/jas/integrate/ElementaryIntegration.java M /trunk/src/edu/jas/ufd/FactorAbsolute.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisor.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorAbstract.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModEval.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModular.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorSimple.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorSubres.java M /trunk/src/edu/jas/ufd/PolyUfdUtil.java M /trunk/trc/edu/jas/gbufd/PolyGBUtilTest.java M /trunk/trc/edu/jas/ufd/GCDModularTest.java M /trunk/trc/edu/jas/ufd/GCDSimpleTest.java M /trunk/trc/edu/jas/ufd/GCDSubresTest.java filled missing methods and respective refactorings ------------------------------------------------------------------------ r3842 | kredel | 2011-12-28 23:49:45 +0100 (Mi, 28. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/poly/GenPolynomial.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModEval.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModular.java M /trunk/trc/edu/jas/ufd/GCDModEvalTest.java M /trunk/trc/edu/jas/ufd/GCDSubresTest.java new mod-eval resultant ------------------------------------------------------------------------ r3841 | kredel | 2011-12-28 19:51:37 +0100 (Mi, 28. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModular.java fixed modular type usage ------------------------------------------------------------------------ r3840 | kredel | 2011-12-28 19:28:55 +0100 (Mi, 28. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/arith/Combinatoric.java M /trunk/src/edu/jas/structure/Power.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModular.java M /trunk/trc/edu/jas/arith/ArithTest.java refactoring and cosmetic ------------------------------------------------------------------------ r3839 | kredel | 2011-12-28 15:04:39 +0100 (Mi, 28. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/structure/Power.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorModular.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorSimple.java M /trunk/src/edu/jas/ufd/GreatestCommonDivisorSubres.java M /trunk/trc/edu/jas/ufd/GCDSimpleTest.java M /trunk/trc/edu/jas/ufd/GCDSubresTest.java add modular resultant ------------------------------------------------------------------------ r3838 | kredel | 2011-12-27 23:29:23 +0100 (Di, 27. Dez 2011) | 1 Zeile Geänderte Pfade: M /trunk/src/edu/jas/ufd/GreatestCommonDivisorSubres.java cleanup ------------------------------------------------------------------------ jas-2.5/COPYING.jas0000644000175000017500000004356711512323746014175 0ustar giovannigiovanni This is the Java Computer Algebra System (JAS) Copyright (C) 2000-2011, Heinz Kredel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. jas-2.5/doc/0000755000175000017500000000000012140140260013076 5ustar giovannigiovannijas-2.5/doc/COPYING.jas0000644000175000017500000004356711622034314014732 0ustar giovannigiovanni This is the Java Computer Algebra System (JAS) Copyright (C) 2000-2011, Heinz Kredel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or any later version. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. jas-2.5/doc/findbugs.html0000644000175000017500000007662412014243364015615 0ustar giovannigiovanni FindBugs Report

FindBugs Report

Project Information

Project:

FindBugs version: 2.0.1-rc3

Code analyzed:

  • /home/kredel/jas/edu/jas/



Metrics

78222 lines of code analyzed, in 792 classes, in 15 packages.

Metric Total Density*
High Priority Warnings 1 0.01
Medium Priority Warnings 37 0.47
Total Warnings 38 0.49

(* Defects per Thousand lines of non-commenting source statements)



Contents

Summary

Warning Type Number
Bad practice Warnings 11
Correctness Warnings 1
Malicious code vulnerability Warnings 10
Performance Warnings 1
Dodgy code Warnings 15
Total 38

Warnings

Click on a warning row to see full context information.

Bad practice Warnings

Code Warning
Nm The class name edu.jas.application.FactorFactory shadows the simple name of the superclass edu.jas.ufd.FactorFactory
RV edu.jas.poly.PolynomialComparator.compare(GenPolynomial, GenPolynomial) negates the return value of edu.jas.poly.GenPolynomial.compareTo(GenPolynomial)
RV edu.jas.poly.TermOrder$69.compare(ExpVector, ExpVector) negates the return value of edu.jas.poly.TermOrder$EVComparator.compare(ExpVector, ExpVector)
RV edu.jas.poly.TermOrder$9.compare(ExpVector, ExpVector) negates the return value of edu.jas.poly.TermOrder$EVComparator.compare(ExpVector, ExpVector)
SnVI edu.jas.gb.GBProxy is Serializable; consider declaring a serialVersionUID
SnVI edu.jas.gb.GroebnerBaseDistributed is Serializable; consider declaring a serialVersionUID
SnVI edu.jas.gb.GroebnerBaseDistributedHybrid is Serializable; consider declaring a serialVersionUID
SnVI edu.jas.gb.GroebnerBaseParallel is Serializable; consider declaring a serialVersionUID
SnVI edu.jas.gb.GroebnerBaseSeqPairDistributed is Serializable; consider declaring a serialVersionUID
SnVI edu.jas.gb.GroebnerBaseSeqPairParallel is Serializable; consider declaring a serialVersionUID
SnVI edu.jas.ufd.GCDProxy is Serializable; consider declaring a serialVersionUID

Correctness Warnings

Code Warning
SA Self comparison of $L0 with itself edu.jas.ps.Examples.example11()

Malicious code vulnerability Warnings

Code Warning
EI edu.jas.poly.GenPolynomialRing.getVars() may expose internal representation by returning GenPolynomialRing.vars
EI edu.jas.poly.TermOrder.getWeight() may expose internal representation by returning TermOrder.weight
EI edu.jas.ps.MultiVarPowerSeriesRing.getVars() may expose internal representation by returning MultiVarPowerSeriesRing.vars
EI2 new edu.jas.application.Dimension(int, Set, Set, String[]) may expose internal representation by storing an externally mutable object into Dimension.v
EI2 new edu.jas.poly.ExpVectorLong(long[]) may expose internal representation by storing an externally mutable object into ExpVectorLong.val
EI2 new edu.jas.poly.GenPolynomialRing(RingFactory, int, TermOrder, String[]) may expose internal representation by storing an externally mutable object into GenPolynomialRing.vars
EI2 edu.jas.poly.GenPolynomialRing.setVars(String[]) may expose internal representation by storing an externally mutable object into GenPolynomialRing.vars
EI2 new edu.jas.poly.TermOrder(long[][]) may expose internal representation by storing an externally mutable object into TermOrder.weight
EI2 new edu.jas.ps.MultiVarPowerSeriesRing(RingFactory, int, int, String[]) may expose internal representation by storing an externally mutable object into MultiVarPowerSeriesRing.vars
MS edu.jas.kern.ComputerThreads.NO_THREADS isn't final and can't be protected from malicious code

Performance Warnings

Code Warning
WMI edu.jas.gb.OrderedSyzPairlist.put(GenPolynomial) makes inefficient use of keySet iterator instead of entrySet iterator

Dodgy code Warnings

Code Warning
DB edu.jas.application.RingFactoryTokenizer.nextCoefficientRing() uses the same code for two branches
DB edu.jas.poly.GenPolynomialTokenizer.nextCoefficientRing() uses the same code for two branches
DLS Dead store to $L5 in edu.jas.poly.ExpVector.subst(int, long)
DLS Dead store to $L4 in edu.jas.poly.ExpVectorByte.subst(int, byte)
DLS Dead store to $L5 in edu.jas.poly.ExpVectorByte.subst(int, long)
DLS Dead store to $L4 in edu.jas.poly.ExpVectorInteger.subst(int, int)
DLS Dead store to $L5 in edu.jas.poly.ExpVectorInteger.subst(int, long)
DLS Dead store to $L5 in edu.jas.poly.ExpVectorLong.subst(int, long)
DLS Dead store to $L5 in edu.jas.poly.ExpVectorShort.subst(int, long)
DLS Dead store to $L4 in edu.jas.poly.ExpVectorShort.subst(int, short)
DLS Dead store to $L1 in edu.jas.ps.MultiVarPowerSeries.orderExpVector()
DLS Dead store to $L14 in edu.jas.ufd.FactorAbsolute.factorsAbsoluteIrreducible(GenPolynomial)
DLS Dead store to $L4 in new edu.jas.util.CartesianTwoProductInfiniteIterator(Iterable, Iterable)
DLS Dead store to $L4 in new edu.jas.util.CartesianTwoProductInfiniteIteratorList(Iterable, Iterable)
SF Switch statement found in edu.jas.poly.GenPolynomialTokenizer.nextPolynomial() where one case falls through to the next case

Details

DB_DUPLICATE_BRANCHES: Method uses the same code for two branches

This method uses the same code to implement two branches of a conditional branch. Check to ensure that this isn't a coding mistake.

DLS_DEAD_LOCAL_STORE: Dead store to local variable

This instruction assigns a value to a local variable, but the value is not read or used in any subsequent instruction. Often, this indicates an error, because the value computed is never used.

Note that Sun's javac compiler often generates dead stores for final local variables. Because FindBugs is a bytecode-based tool, there is no easy way to eliminate these false positives.

EI_EXPOSE_REP: May expose internal representation by returning reference to mutable object

Returning a reference to a mutable object value stored in one of the object's fields exposes the internal representation of the object.  If instances are accessed by untrusted code, and unchecked changes to the mutable object would compromise security or other important properties, you will need to do something different. Returning a new copy of the object is better approach in many situations.

EI_EXPOSE_REP2: May expose internal representation by incorporating reference to mutable object

This code stores a reference to an externally mutable object into the internal representation of the object.  If instances are accessed by untrusted code, and unchecked changes to the mutable object would compromise security or other important properties, you will need to do something different. Storing a copy of the object is better approach in many situations.

MS_CANNOT_BE_FINAL: Field isn't final and can't be protected from malicious code

A mutable static field could be changed by malicious code or by accident from another package. Unfortunately, the way the field is used doesn't allow any easy fix to this problem.

NM_SAME_SIMPLE_NAME_AS_SUPERCLASS: Class names shouldn't shadow simple name of superclass

This class has a simple name that is identical to that of its superclass, except that its superclass is in a different package (e.g., alpha.Foo extends beta.Foo). This can be exceptionally confusing, create lots of situations in which you have to look at import statements to resolve references and creates many opportunities to accidently define methods that do not override methods in their superclasses.

RV_NEGATING_RESULT_OF_COMPARETO: Negating the result of compareTo()/compare()

This code negatives the return value of a compareTo or compare method. This is a questionable or bad programming practice, since if the return value is Integer.MIN_VALUE, negating the return value won't negate the sign of the result. You can achieve the same intended result by reversing the order of the operands rather than by negating the results.

SA_LOCAL_SELF_COMPARISON: Self comparison of value with itself

This method compares a local variable with itself, and may indicate a typo or a logic error. Make sure that you are comparing the right things.

SF_SWITCH_FALLTHROUGH: Switch statement found where one case falls through to the next case

This method contains a switch statement where one case branch will fall through to the next case. Usually you need to end this case with a break or return.

SE_NO_SERIALVERSIONID: Class is Serializable, but doesn't define serialVersionUID

This class implements the Serializable interface, but does not define a serialVersionUID field.  A change as simple as adding a reference to a .class object will add synthetic fields to the class, which will unfortunately change the implicit serialVersionUID (e.g., adding a reference to String.class will generate a static field class$java$lang$String). Also, different source code to bytecode compilers may use different naming conventions for synthetic variables generated for references to class objects or inner classes. To ensure interoperability of Serializable across versions, consider adding an explicit serialVersionUID.

WMI_WRONG_MAP_ITERATOR: Inefficient use of keySet iterator instead of entrySet iterator

This method accesses the value of a Map entry, using a key that was retrieved from a keySet iterator. It is more efficient to use an iterator on the entrySet of the map, to avoid the Map.get(key) lookup.

jas-2.5/doc/jdepend-report.txt0000644000175000017500000010541512004006730016571 0ustar giovannigiovanni -------------------------------------------------- - Package: edu.jas.application -------------------------------------------------- Stats: Total Classes: 57 Concrete Classes: 57 Abstract Classes: 0 Ca: 0 Ce: 10 A: 0 I: 1 D: 0 Abstract Classes: Concrete Classes: edu.jas.application.CGBSeqTest edu.jas.application.CPair edu.jas.application.CReductionSeq edu.jas.application.CReductionSeq$1 edu.jas.application.CoeffConvertAlg edu.jas.application.CoeffRecConvertAlg edu.jas.application.CoeffToComplexReal edu.jas.application.ColorPolynomial edu.jas.application.ColoredSystem edu.jas.application.ComplexRootTest edu.jas.application.ComprehensiveGroebnerBaseSeq edu.jas.application.Condition edu.jas.application.Condition$1 edu.jas.application.Condition$Color edu.jas.application.Dimension edu.jas.application.Examples edu.jas.application.ExtensionFieldBuilder edu.jas.application.ExtensionFieldBuilderTest edu.jas.application.FactorAlgebraicPrim edu.jas.application.FactorAlgebraicPrimTest edu.jas.application.FactorFactory edu.jas.application.FactorRealReal edu.jas.application.FactorRealRealTest edu.jas.application.FactorTest edu.jas.application.GroebnerSystem edu.jas.application.HenselMultUtilTest edu.jas.application.Ideal edu.jas.application.IdealTest edu.jas.application.IdealWithComplexAlgebraicRoots edu.jas.application.IdealWithComplexRoots edu.jas.application.IdealWithRealAlgebraicRoots edu.jas.application.IdealWithRealRoots edu.jas.application.IdealWithUniv edu.jas.application.Local edu.jas.application.LocalRing edu.jas.application.LocalTest edu.jas.application.OrderedCPairlist edu.jas.application.PolyUtilApp edu.jas.application.PolyUtilAppTest edu.jas.application.PrimaryComponent edu.jas.application.PrimitiveElement edu.jas.application.ReAlgFromRealCoeff edu.jas.application.RealAlgebraicNumber edu.jas.application.RealAlgebraicRing edu.jas.application.RealAlgebraicTest edu.jas.application.RealFromReAlgCoeff edu.jas.application.ReductionTest edu.jas.application.Residue edu.jas.application.ResidueRing edu.jas.application.ResidueTest edu.jas.application.RingFactoryTokenizer edu.jas.application.RingFactoryTokenizer$1 edu.jas.application.RingFactoryTokenizer$coeffType edu.jas.application.RingFactoryTokenizer$polyType edu.jas.application.RootFactory edu.jas.application.RunGB edu.jas.application.RunSGB Depends Upon: edu.jas.arith edu.jas.gb edu.jas.gbufd edu.jas.kern edu.jas.poly edu.jas.root edu.jas.structure edu.jas.ufd edu.jas.ufdroot edu.jas.util Used By: Not used by any packages. -------------------------------------------------- - Package: edu.jas.arith -------------------------------------------------- Stats: Total Classes: 38 Concrete Classes: 35 Abstract Classes: 3 Ca: 13 Ce: 2 A: 0,08 I: 0,13 D: 0,79 Abstract Classes: edu.jas.arith.Modular edu.jas.arith.ModularRingFactory edu.jas.arith.Rational Concrete Classes: edu.jas.arith.ArithTest edu.jas.arith.BigComplex edu.jas.arith.BigComplexTest edu.jas.arith.BigDecimal edu.jas.arith.BigDecimalTest edu.jas.arith.BigInteger edu.jas.arith.BigIntegerIterator edu.jas.arith.BigIntegerTest edu.jas.arith.BigOctonion edu.jas.arith.BigOctonionTest edu.jas.arith.BigQuaternion edu.jas.arith.BigQuaternionTest edu.jas.arith.BigRational edu.jas.arith.BigRational$1 edu.jas.arith.BigRationalIterator edu.jas.arith.BigRationalTest edu.jas.arith.BigRationalUniqueIterator edu.jas.arith.Combinatoric edu.jas.arith.ModInteger edu.jas.arith.ModIntegerIterator edu.jas.arith.ModIntegerRing edu.jas.arith.ModIntegerTest edu.jas.arith.ModLong edu.jas.arith.ModLongIterator edu.jas.arith.ModLongRing edu.jas.arith.ModLongTest edu.jas.arith.ModularNotInvertibleException edu.jas.arith.PrimeList edu.jas.arith.PrimeList$1 edu.jas.arith.PrimeList$2 edu.jas.arith.PrimeList$Range edu.jas.arith.Product edu.jas.arith.ProductRing edu.jas.arith.ProductTest edu.jas.arith.Roots Depends Upon: edu.jas.kern edu.jas.structure Used By: edu.jas.application edu.jas.gb edu.jas.gbmod edu.jas.gbufd edu.jas.integrate edu.jas.poly edu.jas.ps edu.jas.root edu.jas.ufd edu.jas.ufdroot edu.jas.util edu.jas.vector edu.mas.kern -------------------------------------------------- - Package: edu.jas.gb -------------------------------------------------- Stats: Total Classes: 104 Concrete Classes: 92 Abstract Classes: 12 Ca: 4 Ce: 6 A: 0,12 I: 0,6 D: 0,28 Abstract Classes: edu.jas.gb.AbstractPair edu.jas.gb.DReduction edu.jas.gb.EReduction edu.jas.gb.GroebnerBase edu.jas.gb.GroebnerBaseAbstract edu.jas.gb.PairList edu.jas.gb.Reduction edu.jas.gb.ReductionAbstract edu.jas.gb.SolvableGroebnerBase edu.jas.gb.SolvableGroebnerBaseAbstract edu.jas.gb.SolvableReduction edu.jas.gb.SolvableReductionAbstract Concrete Classes: edu.jas.gb.CriticalPair edu.jas.gb.CriticalPairComparator edu.jas.gb.CriticalPairList edu.jas.gb.DGroebnerBaseSeq edu.jas.gb.DGroebnerBaseSeqTest edu.jas.gb.DReductionSeq edu.jas.gb.EGroebnerBaseSeq edu.jas.gb.EGroebnerBaseSeqTest edu.jas.gb.EReductionSeq edu.jas.gb.ExtendedGB edu.jas.gb.GBClient edu.jas.gb.GBClientHybrid edu.jas.gb.GBClientSP edu.jas.gb.GBDist edu.jas.gb.GBDistHybrid edu.jas.gb.GBDistSP edu.jas.gb.GBProxy edu.jas.gb.GBProxy$1 edu.jas.gb.GBProxy$2 edu.jas.gb.GBProxyTest edu.jas.gb.GBSPTransportMess edu.jas.gb.GBSPTransportMessEnd edu.jas.gb.GBSPTransportMessPair edu.jas.gb.GBSPTransportMessPairIndex edu.jas.gb.GBSPTransportMessPoly edu.jas.gb.GBSPTransportMessReq edu.jas.gb.GBTransportMess edu.jas.gb.GBTransportMessEnd edu.jas.gb.GBTransportMessPair edu.jas.gb.GBTransportMessPairIndex edu.jas.gb.GBTransportMessPoly edu.jas.gb.GBTransportMessReq edu.jas.gb.GroebnerBaseDistHybridTest edu.jas.gb.GroebnerBaseDistTest edu.jas.gb.GroebnerBaseDistributed edu.jas.gb.GroebnerBaseDistributedHybrid edu.jas.gb.GroebnerBaseParSyzPairTest edu.jas.gb.GroebnerBaseParTest edu.jas.gb.GroebnerBaseParallel edu.jas.gb.GroebnerBaseSeq edu.jas.gb.GroebnerBaseSeqPairDistTest edu.jas.gb.GroebnerBaseSeqPairDistributed edu.jas.gb.GroebnerBaseSeqPairParTest edu.jas.gb.GroebnerBaseSeqPairParallel edu.jas.gb.GroebnerBaseSeqPairSeq edu.jas.gb.GroebnerBaseSeqPairSeqTest edu.jas.gb.GroebnerBaseSeqTest edu.jas.gb.HybridReducerClient edu.jas.gb.HybridReducerReceiver edu.jas.gb.HybridReducerServer edu.jas.gb.JunitClient edu.jas.gb.JunitClientHybrid edu.jas.gb.JunitSeqPairClient edu.jas.gb.Katsura edu.jas.gb.LeftSolvableReducer edu.jas.gb.LeftSolvableReducerSeqPair edu.jas.gb.MiReducer edu.jas.gb.MiReducerClient edu.jas.gb.MiReducerClientSeqPair edu.jas.gb.MiReducerSeqPair edu.jas.gb.MiReducerServer edu.jas.gb.MiReducerServerSeqPair edu.jas.gb.MiniPair edu.jas.gb.OrderedDPairlist edu.jas.gb.OrderedMinPairlist edu.jas.gb.OrderedPairlist edu.jas.gb.OrderedSyzPairlist edu.jas.gb.Pair edu.jas.gb.PairListTest edu.jas.gb.Reducer edu.jas.gb.ReducerClient edu.jas.gb.ReducerClientSeqPair edu.jas.gb.ReducerSeqPair edu.jas.gb.ReducerServer edu.jas.gb.ReducerServerSeqPair edu.jas.gb.ReductionPar edu.jas.gb.ReductionSeq edu.jas.gb.ReductionTest edu.jas.gb.SolvableExtendedGB edu.jas.gb.SolvableGroebnerBaseParTest edu.jas.gb.SolvableGroebnerBaseParallel edu.jas.gb.SolvableGroebnerBaseSeq edu.jas.gb.SolvableGroebnerBaseSeqPairParTest edu.jas.gb.SolvableGroebnerBaseSeqPairParallel edu.jas.gb.SolvableGroebnerBaseSeqTest edu.jas.gb.SolvableMiReducer edu.jas.gb.SolvableMiReducerSeqPair edu.jas.gb.SolvableReductionPar edu.jas.gb.SolvableReductionSeq edu.jas.gb.SolvableReductionTest edu.jas.gb.TwosidedSolvableReducer edu.jas.gb.TwosidedSolvableReducerSeqPair Depends Upon: edu.jas.arith edu.jas.kern edu.jas.poly edu.jas.structure edu.jas.util edu.jas.vector Used By: edu.jas.application edu.jas.gbmod edu.jas.gbufd edu.jas.ufd -------------------------------------------------- - Package: edu.jas.gbmod -------------------------------------------------- Stats: Total Classes: 16 Concrete Classes: 12 Abstract Classes: 4 Ca: 0 Ce: 6 A: 0,25 I: 1 D: 0,25 Abstract Classes: edu.jas.gbmod.ModGroebnerBase edu.jas.gbmod.ModSolvableGroebnerBase edu.jas.gbmod.SolvableSyzygy edu.jas.gbmod.Syzygy Concrete Classes: edu.jas.gbmod.ModGroebnerBaseAbstract edu.jas.gbmod.ModGroebnerBaseTest edu.jas.gbmod.ModSolvableGroebnerBaseAbstract edu.jas.gbmod.ModSolvableGroebnerBaseTest edu.jas.gbmod.ResPart edu.jas.gbmod.ResPolPart edu.jas.gbmod.SolvResPart edu.jas.gbmod.SolvResPolPart edu.jas.gbmod.SolvableSyzygyAbstract edu.jas.gbmod.SolvableSyzygyTest edu.jas.gbmod.SyzygyAbstract edu.jas.gbmod.SyzygyTest Depends Upon: edu.jas.arith edu.jas.gb edu.jas.gbufd edu.jas.poly edu.jas.structure edu.jas.vector Used By: Not used by any packages. -------------------------------------------------- - Package: edu.jas.gbufd -------------------------------------------------- Stats: Total Classes: 33 Concrete Classes: 30 Abstract Classes: 3 Ca: 2 Ce: 7 A: 0,09 I: 0,78 D: 0,13 Abstract Classes: edu.jas.gbufd.PseudoReduction edu.jas.gbufd.RPseudoReduction edu.jas.gbufd.RReduction Concrete Classes: edu.jas.gbufd.Examples edu.jas.gbufd.GBFactory edu.jas.gbufd.GBFactory$1 edu.jas.gbufd.GBFactory$Algo edu.jas.gbufd.GBFactoryTest edu.jas.gbufd.GroebnerBaseExamplesFGLM edu.jas.gbufd.GroebnerBaseFGLM edu.jas.gbufd.GroebnerBaseFGLMTest edu.jas.gbufd.GroebnerBasePartTest edu.jas.gbufd.GroebnerBasePartial edu.jas.gbufd.GroebnerBasePseudoRecSeq edu.jas.gbufd.GroebnerBasePseudoSeq edu.jas.gbufd.GroebnerBasePseudoSeqTest edu.jas.gbufd.MultiplicativeSet edu.jas.gbufd.MultiplicativeSetCoPrime edu.jas.gbufd.MultiplicativeSetFactors edu.jas.gbufd.MultiplicativeSetSquarefree edu.jas.gbufd.MultiplicativeSetTest edu.jas.gbufd.OrderedRPairlist edu.jas.gbufd.PolyGBUtil edu.jas.gbufd.PolyGBUtilTest edu.jas.gbufd.PseudoReductionEntry edu.jas.gbufd.PseudoReductionSeq edu.jas.gbufd.RGroebnerBasePseudoSeq edu.jas.gbufd.RGroebnerBasePseudoSeqTest edu.jas.gbufd.RGroebnerBaseSeq edu.jas.gbufd.RGroebnerBaseSeqTest edu.jas.gbufd.RPseudoReductionSeq edu.jas.gbufd.RReductionSeq edu.jas.gbufd.ReductionTest Depends Upon: edu.jas.arith edu.jas.gb edu.jas.kern edu.jas.poly edu.jas.structure edu.jas.ufd edu.jas.util Used By: edu.jas.application edu.jas.gbmod -------------------------------------------------- - Package: edu.jas.integrate -------------------------------------------------- Stats: Total Classes: 6 Concrete Classes: 6 Abstract Classes: 0 Ca: 0 Ce: 5 A: 0 I: 1 D: 0 Abstract Classes: Concrete Classes: edu.jas.integrate.ElementaryIntegration edu.jas.integrate.ElementaryIntegrationTest edu.jas.integrate.Examples edu.jas.integrate.Integral edu.jas.integrate.LogIntegral edu.jas.integrate.QuotIntegral Depends Upon: edu.jas.arith edu.jas.kern edu.jas.poly edu.jas.structure edu.jas.ufd Used By: Not used by any packages. -------------------------------------------------- - Package: edu.jas.kern -------------------------------------------------- Stats: Total Classes: 11 Concrete Classes: 11 Abstract Classes: 0 Ca: 11 Ce: 0 A: 0 I: 0 D: 1 Abstract Classes: Concrete Classes: edu.jas.kern.ComputerThreads edu.jas.kern.PreemptStatus edu.jas.kern.PreemptingException edu.jas.kern.PrettyPrint edu.jas.kern.Scripting edu.jas.kern.Scripting$Lang edu.jas.kern.StringUtil edu.jas.kern.TSCallMock edu.jas.kern.TimeExceededException edu.jas.kern.TimeStatus edu.jas.kern.TimeStatusTest Depends Upon: Not dependent on any packages. Used By: edu.jas.application edu.jas.arith edu.jas.gb edu.jas.gbufd edu.jas.integrate edu.jas.poly edu.jas.ps edu.jas.root edu.jas.ufd edu.jas.ufdroot edu.jas.vector -------------------------------------------------- - Package: edu.jas.poly -------------------------------------------------- Stats: Total Classes: 187 Concrete Classes: 183 Abstract Classes: 4 Ca: 9 Ce: 5 A: 0,02 I: 0,36 D: 0,62 Abstract Classes: edu.jas.poly.ExpVector edu.jas.poly.Polynomial edu.jas.poly.PolynomialRing edu.jas.poly.TermOrder$EVorder Concrete Classes: edu.jas.poly.ANumGenPolynomialTest edu.jas.poly.AlgToPoly edu.jas.poly.AlgebToCompl edu.jas.poly.AlgebraicNotInvertibleException edu.jas.poly.AlgebraicNumber edu.jas.poly.AlgebraicNumberIterator edu.jas.poly.AlgebraicNumberModTest edu.jas.poly.AlgebraicNumberRing edu.jas.poly.AlgebraicNumberRing$1 edu.jas.poly.AlgebraicNumberTest edu.jas.poly.AnyToComplex edu.jas.poly.CoeffToAlg edu.jas.poly.CoeffToRecAlg edu.jas.poly.CompRatToDec edu.jas.poly.ComplToAlgeb edu.jas.poly.Complex edu.jas.poly.ComplexGenPolynomialTest edu.jas.poly.ComplexRing edu.jas.poly.ComplexTest edu.jas.poly.DistToRec edu.jas.poly.EvalMain edu.jas.poly.EvalMainPol edu.jas.poly.Examples edu.jas.poly.ExpVector$1 edu.jas.poly.ExpVector$StorUnit edu.jas.poly.ExpVectorByte edu.jas.poly.ExpVectorInteger edu.jas.poly.ExpVectorLong edu.jas.poly.ExpVectorPair edu.jas.poly.ExpVectorShort edu.jas.poly.ExpVectorTest edu.jas.poly.FromInteger edu.jas.poly.FromIntegerPoly edu.jas.poly.GFGenPolynomialTest edu.jas.poly.GaloisFieldTest edu.jas.poly.GenMatrixTest edu.jas.poly.GenPolynomial edu.jas.poly.GenPolynomialIterator edu.jas.poly.GenPolynomialMonomialIterator edu.jas.poly.GenPolynomialRing edu.jas.poly.GenPolynomialRing$1 edu.jas.poly.GenPolynomialTest edu.jas.poly.GenPolynomialTokenizer edu.jas.poly.GenPolynomialTokenizer$1 edu.jas.poly.GenPolynomialTokenizer$coeffType edu.jas.poly.GenPolynomialTokenizer$polyType edu.jas.poly.GenPolynomialTokenizerTest edu.jas.poly.GenSolvablePolynomial edu.jas.poly.GenSolvablePolynomialRing edu.jas.poly.GenSolvablePolynomialRing$1 edu.jas.poly.GenSolvablePolynomialTest edu.jas.poly.GenVectorTest edu.jas.poly.ImagPart edu.jas.poly.ImagPartComplex edu.jas.poly.IntGenPolynomialTest edu.jas.poly.InvalidExpressionException edu.jas.poly.Local edu.jas.poly.LocalRing edu.jas.poly.LocalTest edu.jas.poly.ModGenPolynomialTest edu.jas.poly.ModGenSolvablePolynomialTest edu.jas.poly.ModSymToInt edu.jas.poly.ModToInt edu.jas.poly.ModuleList edu.jas.poly.ModuleList$1 edu.jas.poly.ModuleListTest edu.jas.poly.Monomial edu.jas.poly.Multiply edu.jas.poly.OptimizedPolynomialList edu.jas.poly.OrderedModuleList edu.jas.poly.OrderedModuleList$1 edu.jas.poly.OrderedPolynomialList edu.jas.poly.OrderedPolynomialList$1 edu.jas.poly.PolyIterator edu.jas.poly.PolyToAlg edu.jas.poly.PolyUtil edu.jas.poly.PolyUtil$1 edu.jas.poly.PolyUtil$2 edu.jas.poly.PolyUtil$3 edu.jas.poly.PolyUtilTest edu.jas.poly.PolynomialComparator edu.jas.poly.PolynomialList edu.jas.poly.PolynomialList$1 edu.jas.poly.PolynomialListTest edu.jas.poly.QuatGenPolynomialTest edu.jas.poly.Quotient edu.jas.poly.QuotientRing edu.jas.poly.QuotientTest edu.jas.poly.RatGenPolynomialTest edu.jas.poly.RatGenSolvablePolynomialTest edu.jas.poly.RatNumer edu.jas.poly.RatPolyGenPolynomialTest edu.jas.poly.RatToCompl edu.jas.poly.RatToDec edu.jas.poly.RatToInt edu.jas.poly.RatToIntFactor edu.jas.poly.RatToIntPoly edu.jas.poly.RealPart edu.jas.poly.RealPartComplex edu.jas.poly.RecToDist edu.jas.poly.RelationTable edu.jas.poly.RelationTableTest edu.jas.poly.Residue edu.jas.poly.ResidueRing edu.jas.poly.ResidueTest edu.jas.poly.SolvableModuleListTest edu.jas.poly.TableRelation edu.jas.poly.TermOrder edu.jas.poly.TermOrder$1 edu.jas.poly.TermOrder$10 edu.jas.poly.TermOrder$11 edu.jas.poly.TermOrder$12 edu.jas.poly.TermOrder$13 edu.jas.poly.TermOrder$14 edu.jas.poly.TermOrder$15 edu.jas.poly.TermOrder$16 edu.jas.poly.TermOrder$17 edu.jas.poly.TermOrder$18 edu.jas.poly.TermOrder$19 edu.jas.poly.TermOrder$2 edu.jas.poly.TermOrder$20 edu.jas.poly.TermOrder$21 edu.jas.poly.TermOrder$22 edu.jas.poly.TermOrder$23 edu.jas.poly.TermOrder$24 edu.jas.poly.TermOrder$25 edu.jas.poly.TermOrder$26 edu.jas.poly.TermOrder$27 edu.jas.poly.TermOrder$28 edu.jas.poly.TermOrder$29 edu.jas.poly.TermOrder$3 edu.jas.poly.TermOrder$30 edu.jas.poly.TermOrder$31 edu.jas.poly.TermOrder$32 edu.jas.poly.TermOrder$33 edu.jas.poly.TermOrder$34 edu.jas.poly.TermOrder$35 edu.jas.poly.TermOrder$36 edu.jas.poly.TermOrder$37 edu.jas.poly.TermOrder$38 edu.jas.poly.TermOrder$39 edu.jas.poly.TermOrder$4 edu.jas.poly.TermOrder$40 edu.jas.poly.TermOrder$41 edu.jas.poly.TermOrder$42 edu.jas.poly.TermOrder$43 edu.jas.poly.TermOrder$44 edu.jas.poly.TermOrder$45 edu.jas.poly.TermOrder$46 edu.jas.poly.TermOrder$47 edu.jas.poly.TermOrder$48 edu.jas.poly.TermOrder$49 edu.jas.poly.TermOrder$5 edu.jas.poly.TermOrder$50 edu.jas.poly.TermOrder$51 edu.jas.poly.TermOrder$52 edu.jas.poly.TermOrder$53 edu.jas.poly.TermOrder$54 edu.jas.poly.TermOrder$55 edu.jas.poly.TermOrder$56 edu.jas.poly.TermOrder$57 edu.jas.poly.TermOrder$58 edu.jas.poly.TermOrder$59 edu.jas.poly.TermOrder$6 edu.jas.poly.TermOrder$60 edu.jas.poly.TermOrder$61 edu.jas.poly.TermOrder$62 edu.jas.poly.TermOrder$63 edu.jas.poly.TermOrder$64 edu.jas.poly.TermOrder$65 edu.jas.poly.TermOrder$66 edu.jas.poly.TermOrder$67 edu.jas.poly.TermOrder$68 edu.jas.poly.TermOrder$69 edu.jas.poly.TermOrder$7 edu.jas.poly.TermOrder$70 edu.jas.poly.TermOrder$8 edu.jas.poly.TermOrder$9 edu.jas.poly.TermOrderOptimization edu.jas.poly.TermOrderOptimizationTest edu.jas.poly.TermOrderTest edu.jas.poly.ToComplex edu.jas.poly.WeylRelations Depends Upon: edu.jas.arith edu.jas.kern edu.jas.structure edu.jas.util edu.jas.vector Used By: edu.jas.application edu.jas.gb edu.jas.gbmod edu.jas.gbufd edu.jas.integrate edu.jas.ps edu.jas.root edu.jas.ufd edu.jas.ufdroot -------------------------------------------------- - Package: edu.jas.ps -------------------------------------------------- Stats: Total Classes: 111 Concrete Classes: 105 Abstract Classes: 6 Ca: 1 Ce: 5 A: 0,05 I: 0,83 D: 0,11 Abstract Classes: edu.jas.ps.Coefficients edu.jas.ps.MultiVarCoefficients edu.jas.ps.MultiVarPowerSeriesMap edu.jas.ps.TaylorFunction edu.jas.ps.TaylorFunctionAdapter edu.jas.ps.UnivPowerSeriesMap Concrete Classes: edu.jas.ps.Examples edu.jas.ps.Examples$1 edu.jas.ps.Examples$10 edu.jas.ps.Examples$11 edu.jas.ps.Examples$12 edu.jas.ps.Examples$13 edu.jas.ps.Examples$14 edu.jas.ps.Examples$15 edu.jas.ps.Examples$16 edu.jas.ps.Examples$2 edu.jas.ps.Examples$2$1 edu.jas.ps.Examples$3 edu.jas.ps.Examples$4 edu.jas.ps.Examples$5 edu.jas.ps.Examples$6 edu.jas.ps.Examples$7 edu.jas.ps.Examples$8 edu.jas.ps.Examples$9 edu.jas.ps.Examples$Odds edu.jas.ps.Examples$Sum edu.jas.ps.ExamplesMulti edu.jas.ps.ExpVectorIterable edu.jas.ps.ExpVectorIterator edu.jas.ps.IteratorsTest edu.jas.ps.MultiVarPowerSeries edu.jas.ps.MultiVarPowerSeries$1 edu.jas.ps.MultiVarPowerSeries$10 edu.jas.ps.MultiVarPowerSeries$11 edu.jas.ps.MultiVarPowerSeries$12 edu.jas.ps.MultiVarPowerSeries$13 edu.jas.ps.MultiVarPowerSeries$14 edu.jas.ps.MultiVarPowerSeries$15 edu.jas.ps.MultiVarPowerSeries$16 edu.jas.ps.MultiVarPowerSeries$17 edu.jas.ps.MultiVarPowerSeries$18 edu.jas.ps.MultiVarPowerSeries$19 edu.jas.ps.MultiVarPowerSeries$2 edu.jas.ps.MultiVarPowerSeries$20 edu.jas.ps.MultiVarPowerSeries$21 edu.jas.ps.MultiVarPowerSeries$22 edu.jas.ps.MultiVarPowerSeries$23 edu.jas.ps.MultiVarPowerSeries$24 edu.jas.ps.MultiVarPowerSeries$3 edu.jas.ps.MultiVarPowerSeries$4 edu.jas.ps.MultiVarPowerSeries$5 edu.jas.ps.MultiVarPowerSeries$6 edu.jas.ps.MultiVarPowerSeries$7 edu.jas.ps.MultiVarPowerSeries$8 edu.jas.ps.MultiVarPowerSeries$9 edu.jas.ps.MultiVarPowerSeriesRing edu.jas.ps.MultiVarPowerSeriesRing$1 edu.jas.ps.MultiVarPowerSeriesRing$10 edu.jas.ps.MultiVarPowerSeriesRing$11 edu.jas.ps.MultiVarPowerSeriesRing$12 edu.jas.ps.MultiVarPowerSeriesRing$13 edu.jas.ps.MultiVarPowerSeriesRing$14 edu.jas.ps.MultiVarPowerSeriesRing$2 edu.jas.ps.MultiVarPowerSeriesRing$3 edu.jas.ps.MultiVarPowerSeriesRing$4 edu.jas.ps.MultiVarPowerSeriesRing$5 edu.jas.ps.MultiVarPowerSeriesRing$6 edu.jas.ps.MultiVarPowerSeriesRing$7 edu.jas.ps.MultiVarPowerSeriesRing$8 edu.jas.ps.MultiVarPowerSeriesRing$9 edu.jas.ps.MultiVarPowerSeriesTest edu.jas.ps.MultiVarPowerSeriesTest$1 edu.jas.ps.MultiVarPowerSeriesTest$2 edu.jas.ps.MultiVarPowerSeriesTest$3 edu.jas.ps.MultiVarPowerSeriesTest$4 edu.jas.ps.MultiVarPowerSeriesTest$5 edu.jas.ps.MultiVarPowerSeriesTest$6 edu.jas.ps.Multiply edu.jas.ps.Negate edu.jas.ps.OrderedPairlist edu.jas.ps.Pair edu.jas.ps.PolynomialTaylorFunction edu.jas.ps.ReductionSeq edu.jas.ps.ReductionSeq$1 edu.jas.ps.StandardBaseSeq edu.jas.ps.Subtract edu.jas.ps.Sum edu.jas.ps.UnivPowerSeries edu.jas.ps.UnivPowerSeries$1 edu.jas.ps.UnivPowerSeries$10 edu.jas.ps.UnivPowerSeries$11 edu.jas.ps.UnivPowerSeries$2 edu.jas.ps.UnivPowerSeries$3 edu.jas.ps.UnivPowerSeries$4 edu.jas.ps.UnivPowerSeries$5 edu.jas.ps.UnivPowerSeries$6 edu.jas.ps.UnivPowerSeries$7 edu.jas.ps.UnivPowerSeries$8 edu.jas.ps.UnivPowerSeries$9 edu.jas.ps.UnivPowerSeriesRing edu.jas.ps.UnivPowerSeriesRing$1 edu.jas.ps.UnivPowerSeriesRing$10 edu.jas.ps.UnivPowerSeriesRing$2 edu.jas.ps.UnivPowerSeriesRing$3 edu.jas.ps.UnivPowerSeriesRing$4 edu.jas.ps.UnivPowerSeriesRing$5 edu.jas.ps.UnivPowerSeriesRing$6 edu.jas.ps.UnivPowerSeriesRing$7 edu.jas.ps.UnivPowerSeriesRing$8 edu.jas.ps.UnivPowerSeriesRing$9 edu.jas.ps.UnivPowerSeriesTest Depends Upon: edu.jas.arith edu.jas.kern edu.jas.poly edu.jas.structure edu.jas.util Used By: edu.jas.ufd -------------------------------------------------- - Package: edu.jas.root -------------------------------------------------- Stats: Total Classes: 34 Concrete Classes: 30 Abstract Classes: 4 Ca: 2 Ce: 5 A: 0,12 I: 0,71 D: 0,17 Abstract Classes: edu.jas.root.ComplexRoots edu.jas.root.ComplexRootsAbstract edu.jas.root.RealRoots edu.jas.root.RealRootsAbstract Concrete Classes: edu.jas.root.AlgFromRealCoeff edu.jas.root.Boundary edu.jas.root.CoeffToComplex edu.jas.root.CoeffToComplexFromComplex edu.jas.root.CoeffToReAlg edu.jas.root.CoeffToReal edu.jas.root.CoeffToRecReAlg edu.jas.root.ComplexAlgebraicNumber edu.jas.root.ComplexAlgebraicRing edu.jas.root.ComplexAlgebraicTest edu.jas.root.ComplexRootTest edu.jas.root.ComplexRootsAbstract$1 edu.jas.root.ComplexRootsSturm edu.jas.root.Interval edu.jas.root.InvalidBoundaryException edu.jas.root.NoConvergenceException edu.jas.root.PolyToReAlg edu.jas.root.PolyUtilRoot edu.jas.root.RealAlgebraicNumber edu.jas.root.RealAlgebraicRing edu.jas.root.RealAlgebraicTest edu.jas.root.RealFromAlgCoeff edu.jas.root.RealRootTest edu.jas.root.RealRootTuple edu.jas.root.RealRootsAbstract$1 edu.jas.root.RealRootsSturm edu.jas.root.Rectangle edu.jas.root.RootFactory edu.jas.root.RootUtil edu.jas.root.RootUtilTest Depends Upon: edu.jas.arith edu.jas.kern edu.jas.poly edu.jas.structure edu.jas.ufd Used By: edu.jas.application edu.jas.ufdroot -------------------------------------------------- - Package: edu.jas.structure -------------------------------------------------- Stats: Total Classes: 22 Concrete Classes: 2 Abstract Classes: 20 Ca: 12 Ce: 0 A: 0,91 I: 0 D: 0,09 Abstract Classes: edu.jas.structure.AbelianGroupElem edu.jas.structure.AbelianGroupFactory edu.jas.structure.AlgebraElem edu.jas.structure.AlgebraFactory edu.jas.structure.BinaryFunctor edu.jas.structure.ElemFactory edu.jas.structure.Element edu.jas.structure.FieldElem edu.jas.structure.FieldFactory edu.jas.structure.GcdRingElem edu.jas.structure.ModulElem edu.jas.structure.ModulFactory edu.jas.structure.MonoidElem edu.jas.structure.MonoidFactory edu.jas.structure.RegularRingElem edu.jas.structure.RingElem edu.jas.structure.RingFactory edu.jas.structure.Selector edu.jas.structure.StarRingElem edu.jas.structure.UnaryFunctor Concrete Classes: edu.jas.structure.NotInvertibleException edu.jas.structure.Power Depends Upon: Not dependent on any packages. Used By: edu.jas.application edu.jas.arith edu.jas.gb edu.jas.gbmod edu.jas.gbufd edu.jas.integrate edu.jas.poly edu.jas.ps edu.jas.root edu.jas.ufd edu.jas.util edu.jas.vector -------------------------------------------------- - Package: edu.jas.ufd -------------------------------------------------- Stats: Total Classes: 93 Concrete Classes: 85 Abstract Classes: 8 Ca: 5 Ce: 8 A: 0,09 I: 0,62 D: 0,3 Abstract Classes: edu.jas.ufd.FactorAbsolute edu.jas.ufd.FactorAbstract edu.jas.ufd.Factorization edu.jas.ufd.GreatestCommonDivisor edu.jas.ufd.GreatestCommonDivisorAbstract edu.jas.ufd.Squarefree edu.jas.ufd.SquarefreeAbstract edu.jas.ufd.SquarefreeFieldCharP Concrete Classes: edu.jas.ufd.BackSubstKronecker edu.jas.ufd.Examples edu.jas.ufd.ExamplesPartialFraction edu.jas.ufd.FactorAlgebraic edu.jas.ufd.FactorAlgebraicTest edu.jas.ufd.FactorComplex edu.jas.ufd.FactorComplexTest edu.jas.ufd.FactorFactory edu.jas.ufd.FactorGenericTest edu.jas.ufd.FactorInteger edu.jas.ufd.FactorIntegerTest edu.jas.ufd.FactorModular edu.jas.ufd.FactorModularTest edu.jas.ufd.FactorMoreTest edu.jas.ufd.FactorQuotient edu.jas.ufd.FactorQuotientTest edu.jas.ufd.FactorRational edu.jas.ufd.FactorRationalTest edu.jas.ufd.FactorTest edu.jas.ufd.Factors edu.jas.ufd.FactorsList edu.jas.ufd.FactorsMap edu.jas.ufd.GCDFactory edu.jas.ufd.GCDFactoryTest edu.jas.ufd.GCDHenselTest edu.jas.ufd.GCDModEvalTest edu.jas.ufd.GCDModLongEvalTest edu.jas.ufd.GCDModLongTest edu.jas.ufd.GCDModularTest edu.jas.ufd.GCDPartFracRatTest edu.jas.ufd.GCDPrimitiveTest edu.jas.ufd.GCDProxy edu.jas.ufd.GCDProxy$1 edu.jas.ufd.GCDProxy$10 edu.jas.ufd.GCDProxy$11 edu.jas.ufd.GCDProxy$12 edu.jas.ufd.GCDProxy$2 edu.jas.ufd.GCDProxy$3 edu.jas.ufd.GCDProxy$4 edu.jas.ufd.GCDProxy$5 edu.jas.ufd.GCDProxy$6 edu.jas.ufd.GCDProxy$7 edu.jas.ufd.GCDProxy$8 edu.jas.ufd.GCDProxy$9 edu.jas.ufd.GCDProxyTest edu.jas.ufd.GCDSimpleTest edu.jas.ufd.GCDSubresRatTest edu.jas.ufd.GCDSubresTest edu.jas.ufd.GCDTimingTest edu.jas.ufd.GreatestCommonDivisorHensel edu.jas.ufd.GreatestCommonDivisorModEval edu.jas.ufd.GreatestCommonDivisorModular edu.jas.ufd.GreatestCommonDivisorPrimitive edu.jas.ufd.GreatestCommonDivisorSimple edu.jas.ufd.GreatestCommonDivisorSubres edu.jas.ufd.HenselApprox edu.jas.ufd.HenselMultUtil edu.jas.ufd.HenselMultUtilTest edu.jas.ufd.HenselUtil edu.jas.ufd.HenselUtilTest edu.jas.ufd.NoLiftingException edu.jas.ufd.PartialFraction edu.jas.ufd.PolyUfdUtil edu.jas.ufd.PolyUfdUtilTest edu.jas.ufd.QuotIntPolynomialTest edu.jas.ufd.Quotient edu.jas.ufd.QuotientIntTest edu.jas.ufd.QuotientRatTest edu.jas.ufd.QuotientRing edu.jas.ufd.SquarefreeAlgModTest edu.jas.ufd.SquarefreeAlgQuotModTest edu.jas.ufd.SquarefreeFactory edu.jas.ufd.SquarefreeFieldChar0 edu.jas.ufd.SquarefreeFiniteFieldCharP edu.jas.ufd.SquarefreeInfiniteAlgebraicFieldCharP edu.jas.ufd.SquarefreeInfiniteFieldCharP edu.jas.ufd.SquarefreeIntTest edu.jas.ufd.SquarefreeModLongTest edu.jas.ufd.SquarefreeModTest edu.jas.ufd.SquarefreeQuotModTest edu.jas.ufd.SquarefreeRatTest edu.jas.ufd.SquarefreeRingChar0 edu.jas.ufd.SquarefreeTest edu.jas.ufd.SubstKronecker edu.jas.ufd.TrialParts Depends Upon: edu.jas.arith edu.jas.gb edu.jas.kern edu.jas.poly edu.jas.ps edu.jas.structure edu.jas.util edu.jas.vector Used By: edu.jas.application edu.jas.gbufd edu.jas.integrate edu.jas.root edu.jas.ufdroot -------------------------------------------------- - Package: edu.jas.ufdroot -------------------------------------------------- Stats: Total Classes: 2 Concrete Classes: 2 Abstract Classes: 0 Ca: 1 Ce: 5 A: 0 I: 0,83 D: 0,17 Abstract Classes: Concrete Classes: edu.jas.ufdroot.FactorRealAlgebraic edu.jas.ufdroot.FactorRealAlgebraicTest Depends Upon: edu.jas.arith edu.jas.kern edu.jas.poly edu.jas.root edu.jas.ufd Used By: edu.jas.application -------------------------------------------------- - Package: edu.jas.util -------------------------------------------------- Stats: Total Classes: 67 Concrete Classes: 65 Abstract Classes: 2 Ca: 6 Ce: 2 A: 0,03 I: 0,25 D: 0,72 Abstract Classes: edu.jas.util.DHTTransport edu.jas.util.RemoteExecutable Concrete Classes: edu.jas.util.ArrayUtil edu.jas.util.Broadcaster edu.jas.util.CartesianOneProductInfiniteIterator edu.jas.util.CartesianProduct edu.jas.util.CartesianProductInfinite edu.jas.util.CartesianProductIterator edu.jas.util.CartesianProductLong edu.jas.util.CartesianProductLongIterator edu.jas.util.CartesianTwoProductInfiniteIterator edu.jas.util.CartesianTwoProductInfiniteIteratorList edu.jas.util.CatReader edu.jas.util.ChannelFactory edu.jas.util.Counter edu.jas.util.DHTBroadcaster edu.jas.util.DHTListener edu.jas.util.DHTTransport$1 edu.jas.util.DHTTransport$Stor edu.jas.util.DHTTransportMarshal edu.jas.util.DHTTransportPlain edu.jas.util.DistFastWorker edu.jas.util.DistHashTable edu.jas.util.DistHashTableServer edu.jas.util.DistHashTableTest edu.jas.util.DistPoolThread edu.jas.util.DistSlowWorker edu.jas.util.DistThreadPool edu.jas.util.DistThreadPoolTest edu.jas.util.DistributedList edu.jas.util.DistributedListServer edu.jas.util.DistributedListTest edu.jas.util.Executable edu.jas.util.ExecutableChannels edu.jas.util.ExecutableChannelsTest edu.jas.util.ExecutableServer edu.jas.util.ExecutableServerTest edu.jas.util.Executor edu.jas.util.FastWorker edu.jas.util.IteratorsTest edu.jas.util.KsubSet edu.jas.util.KsubSetIterator edu.jas.util.ListUtil edu.jas.util.ListUtilTest edu.jas.util.Listener edu.jas.util.LongIterable edu.jas.util.LongIterator edu.jas.util.MapEntry edu.jas.util.Multiply edu.jas.util.OneSubSetIterator edu.jas.util.PoolThread edu.jas.util.PowerSet edu.jas.util.PowerSetIterator edu.jas.util.PowerSetIterator$Mode edu.jas.util.PowerSetTest edu.jas.util.ShutdownRequest edu.jas.util.SlowWorker edu.jas.util.SocketChannel edu.jas.util.SocketChannelTest edu.jas.util.StrategyEnumeration edu.jas.util.TaggedMessage edu.jas.util.TaggedSocketChannel edu.jas.util.TaggedSocketChannelTest edu.jas.util.Terminator edu.jas.util.ThreadPool edu.jas.util.ThreadPoolTest edu.jas.util.ZeroSubSetIterator Depends Upon: edu.jas.arith edu.jas.structure Used By: edu.jas.application edu.jas.gb edu.jas.gbufd edu.jas.poly edu.jas.ps edu.jas.ufd -------------------------------------------------- - Package: edu.jas.vector -------------------------------------------------- Stats: Total Classes: 8 Concrete Classes: 8 Abstract Classes: 0 Ca: 4 Ce: 3 A: 0 I: 0,43 D: 0,57 Abstract Classes: Concrete Classes: edu.jas.vector.BasicLinAlg edu.jas.vector.Examples edu.jas.vector.GenMatrix edu.jas.vector.GenMatrixRing edu.jas.vector.GenMatrixTest edu.jas.vector.GenVector edu.jas.vector.GenVectorModul edu.jas.vector.GenVectorTest Depends Upon: edu.jas.arith edu.jas.kern edu.jas.structure Used By: edu.jas.gb edu.jas.gbmod edu.jas.poly edu.jas.ufd -------------------------------------------------- - Package: edu.mas.kern -------------------------------------------------- Stats: Total Classes: 2 Concrete Classes: 2 Abstract Classes: 0 Ca: 0 Ce: 1 A: 0 I: 1 D: 0 Abstract Classes: Concrete Classes: edu.mas.kern.LIST edu.mas.kern.LISTTest Depends Upon: edu.jas.arith Used By: Not used by any packages. -------------------------------------------------- - Package Dependency Cycles: -------------------------------------------------- -------------------------------------------------- - Summary: -------------------------------------------------- Name, Class Count, Abstract Class Count, Ca, Ce, A, I, D, V: edu.jas.application,57,0,0,10,0,1,0,1 edu.jas.arith,38,3,13,2,0,08,0,13,0,79,1 edu.jas.gb,104,12,4,6,0,12,0,6,0,28,1 edu.jas.gbmod,16,4,0,6,0,25,1,0,25,1 edu.jas.gbufd,33,3,2,7,0,09,0,78,0,13,1 edu.jas.integrate,6,0,0,5,0,1,0,1 edu.jas.kern,11,0,11,0,0,0,1,1 edu.jas.poly,187,4,9,5,0,02,0,36,0,62,1 edu.jas.ps,111,6,1,5,0,05,0,83,0,11,1 edu.jas.root,34,4,2,5,0,12,0,71,0,17,1 edu.jas.structure,22,20,12,0,0,91,0,0,09,1 edu.jas.ufd,93,8,5,8,0,09,0,62,0,3,1 edu.jas.ufdroot,2,0,1,5,0,0,83,0,17,1 edu.jas.util,67,2,6,2,0,03,0,25,0,72,1 edu.jas.vector,8,0,4,3,0,0,43,0,57,1 edu.mas.kern,2,0,0,1,0,1,0,1 jas-2.5/doc/index.html0000644000175000017500000000336312070113562015107 0ustar giovannigiovanni API, jython, jruby, MPJ and more Documentation

API, jython, jruby, MPJ and more Documentation

This is an intermediate page to the JAS javadoc API documents and more documents.


Heinz Kredel

Last modified: Dec 30 14:40:15 CST 2012

jas-2.5/doc/COPYING0000644000175000017500000004307611252007372014154 0ustar giovannigiovanni GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. jas-2.5/doc/COPYING.lgpl.jas0000644000175000017500000006420211622034314015654 0ustar giovannigiovanni This is the Java Computer Algebra System (JAS) Copyright (C) 2000-2011, Heinz Kredel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or any later version. GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! jas-2.5/doc/COPYING.lgpl0000644000175000017500000006350011252007372015103 0ustar giovannigiovanni GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! jas-2.5/doc/.gitignore0000644000175000017500000000002411512115160015065 0ustar giovannigiovanni/api /jython /jruby jas-2.5/jas0000644000175000017500000000712311726643122013052 0ustar giovannigiovanni#!/bin/bash # $Id: jas 3905 2012-03-10 12:17:22Z kredel $ # SCRIPT_LANG="python" SCRIPT_LANG="ruby" # DEBUG=0 # # setup required libs: JAVA_LIBS="../lib/log4j.jar:../lib/junit.jar:../lib/jas.jar" # if [ -f "../lib/log4j.jar" ] ; then JAVA_LIBS="../lib/log4j.jar" elif [ -f "lib/log4j.jar" ] ; then JAVA_LIBS="lib/log4j.jar" else echo "===========================================" echo "Error: library log4j.jar not found" echo "Please install log4j.jar in lib/ or ../lib/" echo "===========================================" exit 0 fi # if [ -f "../lib/junit.jar" ] ; then JAVA_LIBS="$JAVA_LIBS:../lib/junit.jar" elif [ -f "lib/junit.jar" ] ; then JAVA_LIBS="$JAVA_LIBS:lib/junit.jar" else echo "===========================================" echo "Warning: library junit.jar not found" echo "Please install junit.jar in lib/ or ../lib/" echo "===========================================" fi # if [ -d "examples" ] ; then JAVA_LIBS="$JAVA_LIBS:examples" fi if [ -d "edu/jas" ] ; then JAVA_LIBS="$JAVA_LIBS:." elif [ -f "../lib/jas.jar" ] ; then JAVA_LIBS="$JAVA_LIBS:../lib/jas.jar" elif [ -f "lib/jas.jar" ] ; then JAVA_LIBS="$JAVA_LIBS:lib/jas.jar" elif [ -f "jas.jar" ] ; then JAVA_LIBS="$JAVA_LIBS:jas.jar" else echo "===========================================" echo "Error: library jas.jar not found" echo "Please install jas.jar in lib/ or ../lib/" echo "===========================================" exit 0 fi # #JAVA_LIBS="$JAVA_LIBS:." # #JAVA_OPTS="-J-verbose:gc -J-Xms1100M -J-Xmx1900M" JAVA_OPTS="-J-verbose:gc -J-Xms350M -J-Xmx800M" #JAVA_OPTS="-J-verbose:gc" SCRIPT_OPTS="" # # check for scripting language # Scanning for args is aborted by '--'. #set -- $JAS_OPTS "$@" #echo "jas_args: " $* while [ $# -gt 0 ] do case "$1" in # use python -py*|-jy*) SCRIPT_LANG="python" ;; # use ruby -rb*|-ruby|-jr*) SCRIPT_LANG="ruby" ;; -h|--help) help_requested=true ;; -d) DEBUG=1 ;; -v|--verbose) SCRIPT_OPTS="-v" ;; --) break ;; # Other opts go through -*) jas_args=("${jas_args[@]}" "$1") ;; # Abort processing on first non-opt arg *) jas_args=("${jas_args[@]}" "$1") break ;; esac shift done if [ "$SCRIPT_LANG" = "ruby" ]; then if [ -f "examples/jas.rb" ] ; then echo -n "" else echo "===========================================" echo "Error: library examples/jas.rb not found" echo "Please install examples/jas.rb" echo "===========================================" exit 0 fi fi #echo "jas_args: " $jas_args # Put the jas_args back into the position arguments $1, $2 etc set -- "${jas_args[@]}" if [ -n "$help_requested" ] ; then echo "JAS options:" >&2 echo "-py|-jy : use Python scripting with jython" >&2 echo "-rb|-jr : use Ruby scripting with jruby" >&2 echo "-d : debug this script" >&2 echo "-v : verbose option for scripting language" >&2 echo "-h|--help : this infos" >&2 echo "-- : pass remaining arguments through to Jython|JRuby" >&2 exit 0 fi # if [ "$SCRIPT_LANG" = "python" ]; then [[ $DEBUG > 0 ]] && echo jython $SCRIPT_OPTS -J-cp "$JAVA_LIBS" $JAVA_OPTS $* jython $SCRIPT_OPTS -J-cp "$JAVA_LIBS" $JAVA_OPTS $* elif [ "$SCRIPT_LANG" = "ruby" ]; then [[ $DEBUG > 0 ]] && echo jruby $SCRIPT_OPTS -J-cp "$JAVA_LIBS" $JAVA_OPTS -S jirb --noinspect --readline -r "examples/jas.rb" $* jruby $SCRIPT_OPTS -J-cp "$JAVA_LIBS" $JAVA_OPTS -S jirb --noinspect --readline -r "examples/jas.rb" $* fi # jas-2.5/index.html0000644000175000017500000000160511050125006014330 0ustar giovannigiovanni Java Algebra System (JAS) <body> <div class="nav"> <p><a href="navigate.html">Naviagtion without frames</a></p> <p>Please activate frames to view these pages.</p> </div> <!--p align="right" > $Id: index.html 2058 2008-08-11 21:07:18Z kredel $ </p--> </body> jas-2.5/examples/0000755000175000017500000000000012140140254014152 5ustar giovannigiovannijas-2.5/examples/e-gb.py0000644000175000017500000000151711445125364015356 0ustar giovannigiovanni# # jython examples for jas. # $Id: e-gb.py 3326 2010-09-18 12:05:09Z kredel $ # #import sys; from jas import Ring, PolyRing, Ideal from jas import ZZ from jas import startLog # e-gb and d-gb example to compare with hermit normal form r = PolyRing( ZZ(), "x4,x3,x2,x1", PolyRing.lex ); print "Ring: " + str(r); print; [one,x4,x3,x2,x1] = r.gens(); f1 = x1 + 2 * x2 + 3 * x3 + 4 * x4 + 3; f2 = 3 * x2 + 2 * x3 + x4 + 2; f3 = 3 * x3 + 5 * x4 + 1; f4 = 5 * x4 + 4; L = [f1,f2,f3,f4]; #print "L = ", str(L); f = r.ideal( list=L ); print "Ideal: " + str(f); print; #startLog(); g = f.eGB(); print "seq e-GB:", g; print "is e-GB:", g.iseGB(); print; #sys.exit(); d = f.dGB(); print "seq d-GB:", d; print "is d-GB:", d.isdGB(); print; #startLog(); print "d-GB == e-GB:", g.pset.equals(d.pset); jas-2.5/examples/mark.py0000644000175000017500000000120611644542070015467 0ustar giovannigiovanni# # jython examples for jas. # $Id: mark.py 3797 2011-10-10 10:08:57Z kredel $ # #import sys; from jas import Ring from jas import Ideal from jas import startLog # mark, d-gb diplom example r = Ring( "Z(x,y,z) L" ); print "Ring: " + str(r); print; ps = """ ( ( z + x y**2 + 4 x**2 + 1 ), ( y**2 z + 2 x + 1 ), ( x**2 z + y**2 + x ) ) """; f = r.ideal( ps ); print "Ideal: " + str(f); print; #startLog(); eg = f.eGB(); print "seq e-GB:", eg; print "is e-GB:", eg.isGB(); print; dg = f.dGB(); print "seq d-GB:", dg; print "is d-GB:", dg.isGB(); print; print "d-GB == e-GB:", eg.list.equals(dg.list); print "d-GB == e-GB:", eg == dg; jas-2.5/examples/factors_algeb_trans_charp.py0000644000175000017500000000446311415445670021730 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_algeb_trans_charp.py 3220 2010-07-08 22:05:44Z kredel $ # import sys from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import ZM, QQ, AN, RF from jas import terminate from jas import startLog # polynomial examples: factorization over Z_p(x)(sqrt3(x))[y] Q = PolyRing(ZM(5),"x",PolyRing.lex); print "Q = " + str(Q); [e,a] = Q.gens(); #print "e = " + str(e); print "a = " + str(a); Qr = RF(Q); print "Qr = " + str(Qr.factory()); [er,ar] = Qr.gens(); #print "er = " + str(er); #print "ar = " + str(ar); print; Qwx = PolyRing(Qr,"wx",PolyRing.lex); print "Qwx = " + str(Qwx); [ewx,ax,wx] = Qwx.gens(); #print "ewx = " + str(ewx); print "ax = " + str(ax); print "wx = " + str(wx); print; rootx = wx**3 - ax; print "rootx = " + str(rootx); Q2x = AN(rootx,field=True); print "Q2x = " + str(Q2x.factory()); [ex2,ax2,wx] = Q2x.gens(); #print "ex2 = " + str(ex2); #print "w2x2 = " + str(w2x2); #print "ax2 = " + str(ax2); #print "wx = " + str(wx); print; #Yr = PolyRing(Q2x,"y,z,c0,c1,c2",PolyRing.lex) Yr = PolyRing(Q2x,"y,z",PolyRing.lex) print "Yr = " + str(Yr); #[e,x,wx,y,z,c0,c1,c2] = Yr.gens(); [e,x,wx,y,z] = Yr.gens(); print "e = " + str(e); print "x = " + str(x); print "wx = " + str(wx); print "y = " + str(y); print "z = " + str(z); print; #f = ( y**2 - x ); #f = ( y**2 - ( wx**2 + wx + 2 ) ); f = ( y**2 - ( wx**2 + wx + 2 ) + z**2 + y * wx ); #f = wx**3; print "f = ", f; print; f = f**5; print "f = ", f; print; #g = ( y**2 + ( c0 + c1 * wx + c2 * wx**2 ) ); #print "g = ", g; #g = g**5; #print "g = ", g; #print; #sys.exit(); startLog(); t = System.currentTimeMillis(); #ok: G = Yr.factors(f); G = Yr.squarefreeFactors(f); t = System.currentTimeMillis() - t; print "G = ", G; #print "factor time =", t, "milliseconds"; #sys.exit(); print "f = ", f; g = e; for h, i in G.iteritems(): if i > 1: print "h**i = ", h, "**" + str(i); else: print "h = ", h; h = h**i; g = g*h; print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/syz.rb0000644000175000017500000000357411653754360015356 0ustar giovannigiovanni# # jruby examples for jas. # $Id: syz.rb 3823 2011-11-01 11:33:05Z kredel $ # require "examples/jas" # trinks 7 example r = Ring.new( "Rat(B,S,T,Z,P,W) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B**3 ), ( 99 W - 11 B S + 3 B**2 ), ( B**2 + 33/50 B + 2673/10000 ) ) """; f = SimIdeal.new( r, ps ); puts "Ideal: " + str(f); puts; #Katsura equations for N = 3: #r = Ring.new( "Rat(u0,u1,u2,u3) L" ); #puts "Ring: " + str(r); #puts; ps = """ ( u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 - u0, u3*0 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 - u1, u3*0 + u2*0 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 - u2, u3 + u2 + u1 + u0 + u1 + u2 + u3 - 1 ) """; #f = SimIdeal.new( r, ps ); #puts "Ideal: " + str(f); #puts; rg = f.GB(); puts "seq Output:" + str(rg); puts; #startLog(); include_class "edu.jas.poly.ModuleList"; include_class "edu.jas.gbmod.SyzygyAbstract"; include_class "edu.jas.gbmod.ModGroebnerBaseAbstract"; s = SyzygyAbstract.new().zeroRelations( rg.list ); sl = ModuleList.new(rg.pset.ring,s); puts "syzygy:" + str(sl); puts; z = SyzygyAbstract.new().isZeroRelation( s, rg.list ); print "is Syzygy ? " if z puts "true" else puts "false" end puts; zg = sl; for i in 1..(r.ring.nvar) puts "\n #{i}. resolution"; sl = zg; mg = ModGroebnerBaseAbstract.new().GB(sl); puts "Mod GB: " + str(mg); puts; zg = SyzygyAbstract.new().zeroRelations(mg); puts "syzygies of Mod GB: " + str(zg); puts; if ModGroebnerBaseAbstract.new().isGB( mg ) puts "is GB"; else puts "is not GB"; end if SyzygyAbstract.new().isZeroRelation(zg,mg) puts "is Syzygy"; else puts "is not Syzygy"; end if not zg break; end end terminate(); jas-2.5/examples/nabeshima_cgbF8.rb0000644000175000017500000000267111653002012017442 0ustar giovannigiovanni# # jruby examples for jas. # $Id: nabeshima_cgbF8.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Nabashima, ISSAC 2007, example F8 # modified, take care # integral function coefficients #r = Ring.new( "IntFunc(d, b, a, c) (y,x,w,z) L" ); r = Ring.new( "IntFunc(d, b, a, c) (y,x,w,z) G" ); #r = Ring.new( "IntFunc(d, b, c, a) (w,z,y,x) G" ); #r = Ring.new( "IntFunc(b, c, a) (w,x,z,y) L" ); #r = Ring.new( "IntFunc(b, c) (z,y,w,x) L" ); #r = Ring.new( "IntFunc(b) (z,y,w,x) L" ); #r = Ring.new( "IntFunc(c) (z,y,w,x) L" ); #r = Ring.new( "IntFunc(c) (z,y,w,x) G" ); puts "Ring: " + str(r); puts; ps = """ ( ( { c } w^2 + z ), ( { a } x^2 + { b } y ), ( ( x - z )^2 + ( y - w)^2 ), ( { 2 d } x w - { 2 b } y ) ) """; ## ( { 1 } x^2 + { 1 } y ), ## ( { 1 } w^2 + z ), ## ( { 2 } x w - { 2 1 } y ) # ( { 1 } x^2 + { b } y ), # ( { c } w^2 + z ), # ( { a } x^2 + { b } y ), # ( { 2 d } x w - { 2 b } y ) #startLog(); f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; #startLog(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; terminate(); exit(); bg = gs.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; gs = f.CGB(); puts "CGB: " + str(gs); puts; bg = gs.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/solvmodright.py0000644000175000017500000000246011774031074017262 0ustar giovannigiovanni# # jython examples for jas. from jas import SolvableModule from jas import SolvableSubModule # Quantum plane example rsan = """ AN[ (i) (i^2 + 1) ] (Y,X,x,y) G RelationTable ( ( y ), ( x ), ( {i} x y ) ( X ), ( Y ), ( {i} Y X ) ) """; rsc = """ # not supported: C(Y,X,x,y) G |2| C(Y,X,x,y) G RelationTable ( ( y ), ( x ), ( 0i1 x y ) ( X ), ( Y ), ( 0i1 Y X ) ) """; #r = SolvableModule( rsc ); r = SolvableModule( rsan ); print "SolvableModule: " + str(r); print; ps = """ ( ( ( x + 1 ), ( y ) ), ( ( x y ), ( 0 ) ), ( ( x - X ), ( x - X ) ), ( ( y - Y ), ( y - Y ) ) ) """; f = SolvableSubModule( r, ps ); print "SolvableSubModule: " + str(f); print; flg = f.leftGB(); print "seq left GB:", flg; print; if flg.isLeftGB(): print "is left GB"; else: print "is not left GB"; ftg = f.twosidedGB(); print "seq twosided GB:", ftg; print; if ftg.isLeftGB(): print "twosided GB is left GB"; else: print "twosided GB is not left GB"; if ftg.isRightGB(): print "twosided GB is right GB"; else: print "twosided GB is not right GB"; if ftg.isTwosidedGB(): print "is twosided GB"; else: print "is not twosided GB"; from jas import startLog startLog(); frg = f.rightGB(); print "seq right GB:", frg; print; if frg.isRightGB(): print "is right GB"; else: print "is not right GB"; jas-2.5/examples/radical-decomp_charp_infin.py0000644000175000017500000000231311426337330021740 0ustar giovannigiovanni# # jython examples for jas. # $Id: radical-decomp_charp_infin.py 3244 2010-08-04 19:26:16Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate, startLog, noThreads from jas import QQ, ZM, RF # polynomial examples: ideal radical decomposition, inseparable cases, dim > 0 #noThreads(); # must be called very early cr = PolyRing(ZM(5),"c",PolyRing.lex); print "coefficient Ring: " + str(cr); rf = RF(cr); print "coefficient quotient Ring: " + str(rf.ring); r = PolyRing(rf,"x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,c,x,y,z] = r.gens(); print one,c,x,y,z; #sys.exit(); #f1 = (x**2 - 5)**2; #f1 = (y**10 - x**5)**3; f1 = (x**2 + 2)**2; f2 = (y**2 - x)**5; #f2 = f2**5; f3 = (z**2 - c)**5; f4 = (y**2 - x)**3; #print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; #print "f4 = ", f4; print; #F = r.ideal( list=[f1,f2,f3] ); F = r.ideal( list=[f2,f3] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); t = System.currentTimeMillis() - t; print "R = ", R; print; print "decomp time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/alg_surface.rb0000644000175000017500000000102311641155210016751 0ustar giovannigiovanni# # jruby examples for jas. # $Id: alg_surface.rb 3784 2011-09-29 20:52:24Z kredel $ # require "examples/jas" # polynomial examples: Yr = EF.new(QQ()).extend("x,y").extend("z","z^2 + x^2 + y^2 - 1").build(); #puts "Yr = " + str(Yr); #puts one,x,y,z = Yr.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); puts; f = (1+z)*(1-z); # / ( x**2 + y**2 ); puts "f = " + str(f); puts; g = f / (1 - z); puts "g = " + str(g); puts; #startLog(); terminate(); jas-2.5/examples/roots_rat.rb0000644000175000017500000000236511543637436016544 0ustar giovannigiovanni# # jruby examples for jas. # $Id: roots_rat.rb 3588 2011-03-27 13:43:58Z kredel $ # require "examples/jas" # polynomial examples: real roots over Q r = PolyRing.new(QQ(),"x",PolyRing.lex); puts "Ring: " + str(r); puts; one,x = r.gens(); f1 = x * ( x - 1 ) * ( x - 2 ) * ( x - 3 ) * ( x - 4 ) * ( x - 5 ) * ( x - 6 ) * ( x - 7 ) ; f2 = ( x - 1/2 ) * ( x - 1/3 ) * ( x - 1/4 ) * ( x - 1/5 ) * ( x - 1/6 ) * ( x - 1/7 ) ; f3 = ( x - 1/2**2 ) * ( x - 1/2**3 ) * ( x - 1/2**4 ) * ( x - 1/2**5 ) * ( x - 1/2**6 ) * ( x - 1/2**7 ) ; #f = f1 * f2 * f3; f = f1 * f2; #f = f1 * f3; #f = f2 * f3; #f = f3; #f = ( x**2 - 2 ); puts "f = " + f.to_s; puts; startLog(); t = System.currentTimeMillis(); rr = r.realRoots(f); t = System.currentTimeMillis() - t; #puts "rr = " + str(rr); puts "rr = " + str(rr.map{ |a| str(a.elem.ring.getRoot())+"," }); puts "real roots time = " + str(t) + " milliseconds"; eps = QQ(1,10) ** (BigDecimal::DEFAULT_PRECISION-3); puts "eps = " + str(eps); t = System.currentTimeMillis(); rr = r.realRoots(f,eps); t = System.currentTimeMillis() - t; #puts "rr = ", [ str(r) for r in rr ]; puts "rr = " + str(rr.map{ |a| str(a.elem.decimalMagnitude())+"," }); puts "real roots time = " + str(t) + " milliseconds"; #startLog(); terminate(); jas-2.5/examples/factors_mod_abs.rb0000644000175000017500000000124011773570014017635 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_mod_abs.rb 3968 2012-06-30 12:24:45Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: factorization over Z_p #r = PolyRing.new( GF(19), "x", PolyRing.lex ); r = PolyRing.new( GF(1152921504606846883), "x", PolyRing.lex ); puts "Ring: " + str(r); puts #one,x = r.gens(); #f = x**4 - 1; #f = x**3 + 1; f = x**3 - x - 1; puts "f = ", f; puts; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); #G = r.factors(f); G = r.factorsAbsolute(f); t = System.currentTimeMillis() - t; puts "G = ", G.toScript(); puts "factor time = " + str(t) + " milliseconds"; #startLog(); terminate(); jas-2.5/examples/montes_ex51.py0000644000175000017500000000243511304010406016673 0ustar giovannigiovanni# # jython examples for jas. # $Id: montes_ex51.py 2882 2009-11-27 17:48:55Z kredel $ # import sys; from jas import PolyRing, QQ, RF from jas import Ideal from jas import startLog from jas import terminate # Montes JSC 2002, 33, 183-208, example 5.1 # integral function coefficients r = PolyRing( PolyRing(QQ(),"a, b",PolyRing.lex), "u,z,y,x", PolyRing.lex ); print "Ring: " + str(r); print; [one,a,b,u,z,y,x] = r.gens(); print "gens: ", [ str(f) for f in r.gens() ]; print; f1 = a * x + 2 * y + 3 * z + u - 6; f2 = x + 3 * y - z + 2 * u - b; f3 = 3 * x - a * y + z - 2; f4 = 5 * x + 4 * y + 3 * z + 3 * u - 9; F = [f1,f2,f3,f4]; print "F: ", [ str(f) for f in F ]; print; #startLog(); If = r.paramideal( "", list = F ); print "ParamIdeal: " + str(If); print; ## G = If.GB(); ## print "GB: " + str(G); ## print; ## sys.exit(); GS = If.CGBsystem(); GS = If.CGBsystem(); GS = If.CGBsystem(); print "CGBsystem: " + str(GS); print; bg = GS.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #terminate(); #sys.exit(); CG = If.CGB(); print "CGB: " + str(CG); print; bg = CG.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/real_roots_ideal.rb0000644000175000017500000000172011653060122020011 0ustar giovannigiovanni# # jruby examples for jas. # $Id: real_roots_ideal.rb 3818 2011-10-29 20:21:39Z kredel $ # require "examples/jas" # polynomial examples: real roots over Q for zero dimensional ideals r = PolyRing.new(QQ(),"q,w,s,x",PolyRing.lex); puts "Ring: " + str(r); puts; one,q,w,s,x = r.gens(); # EF.new(QQ()).realExtend("q","q^3 - 3", "[1,2]").realExtend("w", "w^2 - q", "[1,2]").realExtend("s", "s^5 - 2", "[1,2]").polynomial("x").build(); f1 = q**3 - 3; f2 = w**2 - q; #f3 = s**5 - 2; f3 = s**3 - 2; f4 = x**2 - w * s; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts "f4 = " + str(f4); puts; F = r.ideal( "", list=[f1,f2,f3,f4] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.realRoots(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "real roots = "; F.realRootsPrint() puts "real roots time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/factors_compl_algeb.py0000644000175000017500000000467511535146104020534 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_compl_algeb.py 3555 2011-03-07 12:15:01Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import QQ, AN from jas import terminate from jas import startLog # polynomial examples: factorization over Q(i) Qr = PolyRing(QQ(),"i",PolyRing.lex); print "Qr = " + str(Qr); [e,a] = Qr.gens(); print "e = " + str(e); print "a = " + str(a); imag = a**2 + 1; print "imag = " + str(imag); Qi = AN(imag,field=True); print "Qi = " + str(Qi.factory()); [one,i] = Qi.gens(); print "one = " + str(one); print "i = " + str(i); b = i**2 + 1; print "b = " + str(b); c = 1 / i; print "c = " + str(c); #Qix = AN(i**2 + 1); #print "Qix = " + str(Qix.factory()); print; r = PolyRing(Qi,"x",PolyRing.lex) print "r = " + str(r); [one,i,x] = r.gens(); print "one = " + str(one); print "i = " + str(i); print "x = " + str(x); #f = x**7 - 1; f = x**6 + x**5 + x**4 + x**3 + x**2 + x + 1; print "f = ", f; print; startLog(); t = System.currentTimeMillis(); G = r.factors(f); t = System.currentTimeMillis() - t; print "G = ", str(G); #print "factor time =", t, "milliseconds"; ## f2 = one; ## for h, i in G.iteritems(): ## print "h**i = (", h, ")**" + str(i); ## h = h**i; ## f2 = f2*h; #print "f2 = ", f2; print; ## if cmp(f,f2) == 0: ## print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; ## else: ## print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,f2); ## print; r2 = PolyRing(Qi,"a,b",PolyRing.lex) print "r2 = " + str(r2); [one,i,a,b] = r2.gens(); print "one = " + str(one); print "i = " + str(i); print "a = " + str(a); print "b = " + str(b); y = a + i * b; #g = y**7 - 1; g = y**6 + y**5 + y**4 + y**3 + y**2 + y + 1; g = - g; print "g = ", g; print; #sys.exit(); #startLog(); t = System.currentTimeMillis(); G = r2.factors(g); t = System.currentTimeMillis() - t; print "G = ", str(G); #print "factor time =", t, "milliseconds"; ## g2 = one; ## for h, i in G.iteritems(): ## print "h**i = (", h, ")**" + str(i); ## h = h**i; ## g2 = g2*h; #print "g2 = ", g2; print; ## if cmp(g,g2) == 0: ## print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; ## else: ## print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(g,g2); ## print; #sys.exit(); #startLog(); terminate(); jas-2.5/examples/prime-decomp_algeb_trans-plain.py0000644000175000017500000000217411637331234022565 0ustar giovannigiovanni# # jython examples for jas. # $Id: prime-decomp_algeb_trans-plain.py 3777 2011-09-24 10:36:13Z kredel $ # import sys from java.lang import System from jas import PolyRing, Ideal from jas import QQ, AN, RF from jas import terminate, startLog # polynomial examples: prime/primary decomposition in Q[w2,x,wx,y,z] Q = PolyRing(QQ(),"w2,x,wx,y,z",PolyRing.lex); print "Q = " + str(Q); [e,w2,x,wx,y,z] = Q.gens(); print "e = " + str(e); print "w2 = " + str(w2); print "x = " + str(x); print "wx = " + str(wx); print "y = " + str(y); print "z = " + str(z); print; w1 = w2**2 - 2; w2 = wx**2 - x; f1 = ( y**2 - x ) * ( y**2 - 2 ); #f1 = ( y**2 - x )**3 * ( y**2 - 2 )**2; f2 = ( z**2 - y**2 ); print "w1 = ", w1; print "w2 = ", w2; print "f1 = ", f1; print "f2 = ", f2; print; F = Q.ideal( list=[w1,w2,f1,f2] ); print "F = ", F; print; #sys.exit(); startLog(); t = System.currentTimeMillis(); P = F.primeDecomp(); #P = F.primaryDecomp(); t1 = System.currentTimeMillis() - t; print "P = ", P; print; print "prime/primary decomp time =", t1, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/montes_ex114.rb0000644000175000017500000000301611653002012016723 0ustar giovannigiovanni# # jruby examples for jas. # $Id: montes_ex114.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Montes JSC 2002, 33, 183-208, example 11.4 # integral function coefficients R = PolyRing.new( PolyRing.new(QQ(),"Q2, P2, Q1, P1",PolyRing.lex), "f3, e3, f2, e2", PolyRing.lex ); puts "Ring: " + str(R); puts; one, Q2, P2, Q1, P1, f3, e3, f2, e2 = R.gens(); puts "gens: " + R.gens().each{ |f| str(f) }.join(","); puts; fp1 = 14 - 12 * e2 - 110 * f2 - 2 * e3 - 10 * f3 - P1; fp2 = 2397 - 2200 * e2 + 240 * f2 - 200 * e3 + 40 * f3 - 20 * Q1; fp3 = 16 * e2**2 - 4 * e2 * e3 - 20 * e2 * f3 + 20 * e3 * f2 + 16 * f2**2 - 4 * f2 * f3 - 12 * e2 + 110 * f2 - P2; fp4 = 2599 * e2**2 - 400 * e2 * e3 + 80 * e2 * f3 - 80 * e3 * f2 + 2599 * f2**2 - 400 * f2 * f3 - 2200 * e2 - 240 * f2 - 20 * Q2; puts "fp1: " + str(fp1); puts "fp2: " + str(fp2); puts "fp3: " + str(fp3); puts "fp4: " + str(fp4); puts; F = [fp1,fp2,fp3,fp4]; puts "F: " + F.each{ |f| str(f) }.join(","); puts; startLog(); If = R.paramideal( "", list = F ); puts "ParamIdeal: " + str(If); puts; ## G = If.GB(); ## puts "GB: " + str(G); ## puts; GS = If.CGBsystem(); GS = If.CGBsystem(); GS = If.CGBsystem(); puts "CGBsystem: " + str(GS); puts; bg = GS.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; terminate(); exit(); CG = If.CGB(); puts "CGB: " + str(CG); puts; bg = CG.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/sys-bio.py0000644000175000017500000000177111203337072016124 0ustar giovannigiovanni# # jython examples for jas. # $Id: sys-bio.py 2631 2009-05-15 19:10:50Z kredel $ # from java.lang import System from jas import PolyRing, Ideal from jas import terminate, startLog from jas import ZM # system biology examples: GB in Z_2 # see: Informatik Spektrum, 2009, February, # Laubenbacher, Sturmfels: Computer Algebra in der Systembiologie r = PolyRing(ZM(2),"M, B, A, L, P",PolyRing.lex); print "PolyRing: " + str(r); print; [one,M,B,A,L,P] = r.gens(); f1 = M - A; f2 = B - M; f3 = A - A - L * B - A * L * B; f4 = P - M; f5 = L - P - L - L * B - L * P - L * B * P; ## t1 = M - 1; ## t2 = B - 1; ## t3 = A - 1; ## t4 = L - 1; ## t5 = P - 1; # ## t1 = M; ## t2 = B; ## t3 = A; ## t4 = L; ## t5 = P; # ## t1 = M; ## t2 = B; ## t3 = A; ## t4 = L - 1; ## t5 = P; # t1 = M; t2 = B; t3 = A - 1; t4 = L - 1; t5 = P; F = [f1,f2,f3,f4,f5]; #F = [f1,f2,f3,f4,f5,t1,t2,t3,t4,t5]; I = r.ideal( "", list=F ); print "Ideal: " + str(I); print; G = I.GB(); print "GB: " + str(G); print; #startLog(); terminate(); jas-2.5/examples/factors.rb0000644000175000017500000000431511627521076016161 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors.rb 3755 2011-08-31 21:06:06Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: factorization over Z r = PolyRing.new( ZZ(), "x", PolyRing.lex ); puts "Ring: " + str(r); puts; one,x = r.gens(); #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**4 - 1; #f = x**3 - x**2 + x - 1; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; #f = x**15 + 122 * x**10 - 122 * x**5 - 1; #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; f = f * (x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8); puts "f = ", f; puts; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; puts "G = ", str(G.map{ |h,i| str(h)+"**"+str(i)+" " }); #puts "G = ", G; #puts "factor time =", t, "milliseconds"; puts; puts "f = " + str(f); g = one; for h, i in G do if i > 1 then puts "h**i = " + str(h) + "**" + str(i); else puts "h = " + str(h); end h = h**i; g = g*h; end puts; #puts "g = ", g; if f == g then puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): true" ; else puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): " + str(f==g); end puts; #startLog(); terminate(); jas-2.5/examples/suzukiSato_ex1.py0000644000175000017500000000302111316340174017465 0ustar giovannigiovanni# # jython examples for jas. # $Id: suzukiSato_ex1.py 2932 2009-12-29 08:40:28Z kredel $ # import sys; from jas import PolyRing, QQ, RF from jas import Ideal from jas import startLog from jas import terminate # Suzuki and Sato, ISSAC 2006, example 1 # integral function coefficients #r = PolyRing( QQ(),"b,a,z,y,x", PolyRing.lex ); #r = PolyRing( RF( PolyRing(QQ(),"a, b",PolyRing.lex) ), "z,y,x", PolyRing.lex ); r = PolyRing( PolyRing(QQ(),"b, a",PolyRing.lex), "z,y,x", PolyRing.lex ); print "Ring: " + str(r); print; [one,b,a,z,y,x] = r.gens(); print "gens: ", [ str(f) for f in r.gens() ]; print; #f1 = x**2 - a; #f2 = y**3 - b; f1 = x**3 - a; f2 = y**4 - b; f3 = x + y - z; F = [f1,f2,f3]; print "F: ", [ str(f) for f in F ]; print; startLog(); ## If = r.ideal( "", list = F ); ## print "Ideal: " + str(If); ## print; ## G = If.GB(); ## print "GB: " + str(G); ## print; ## E = G.eliminateRing( PolyRing(QQ(),"b, a",PolyRing.lex) ); ## print "E: " + str(E); ## print; ## sys.exit(); If = r.paramideal( "", list = F ); print "ParamIdeal: " + str(If); print; G = If.GB(); print "GB: " + str(G); print; terminate(); sys.exit(); GS = If.CGBsystem(); print "CGBsystem: " + str(GS); print; bg = GS.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #terminate(); #sys.exit(); CG = If.CGB(); print "CGB: " + str(CG); print; bg = CG.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/wa_1.jas0000644000175000017500000000020610653077260015513 0ustar giovannigiovanni# solvable polynomials, Weyl algebra A_1: (a,b,x,y) L RelationTable ( ( y ), ( x ), ( x y - 1 ), ) ( ( x y^2 - a ), ( y^3 - b ) ) jas-2.5/examples/lewis.py0000644000175000017500000000241411633207130015653 0ustar giovannigiovanni# # jython examples for jas. # $Id: lewis.py 3759 2011-09-11 19:39:05Z kredel $ # import sys; from jas import Ring, PolyRing, RF, ZZ, ZM from jas import Ideal from jas import startLog from jas import terminate #startLog(); # Lewis example # integral function coefficients #r = Ring( "IntFunc(a1,a2,a3,b1,b2,b3,c1,c2,c3,d1,d2,d3,e1,e2,e3) (t1,t2,t3) G" ); #r = Ring( "RatFunc(a1,a2,a3,b1,b2,b3,c1,c2,c3,d1,d2,d3,e1,e2,e3) (t1,t2,t3) G" ); r = PolyRing( RF(PolyRing(ZZ(),"a1,a2,a3,b1,b2,b3,c1,c2,c3,d1,d2,d3,e1,e2,e3",PolyRing.lex)), "t1,t2,t3", PolyRing.grad ); #r = PolyRing( RF(PolyRing(ZM(163),"a1,a2,a3,b1,b2,b3,c1,c2,c3,d1,d2,d3,e1,e2,e3",PolyRing.lex)), "t1,t2,t3", PolyRing.grad ); print "Ring: " + str(r); print; ps = """ ( ( { a1 } * t1^2 * t2^2 + { b1 } * t1^2 + { 2 c1 } * t1 * t2 + { d1 } * t2^2 + { e1 } ), ( { a2 } * t2^2 * t3^2 + { b2 } * t2^2 + { 2 c2 } * t2 * t3 + { d2 } * t3^2 + { e2 } ), ( { a3 } * t1^2 * t3^2 + { b3 } * t1^2 + { 2 c3 } * t1 * t3 + { d3 } * t3^2 + { e3 } ) ) """; #a1 = e2 + s22 #+ s27 #- s25 #- 2e * s2 + 2e * s7 - 2s2 * s7 f = r.ideal( ps ); print "ParamIdeal: " + str(f); print; sys.exit(); startLog(); rg = f.GB(); #rg = f.GB(); print "GB:", rg; print; bg = rg.isGB(); print "isGB:", bg; print; #startLog(); terminate(); #sys.exit(); jas-2.5/examples/solvablepolynomial.rb0000644000175000017500000000421612024343272020423 0ustar giovannigiovanni# # jruby examples for jas. # $Id: solvablepolynomial.rb 4189 2012-09-13 11:42:50Z kredel $ # require "examples/jas" # WA_32 solvable polynomial example p = PolyRing.new(QQ(),"a,b,e1,e2,e3"); #is automatic: [one,a,b,e1,e2,e3] = p.gens(); relations = [e3, e1, e1*e3 - e1, e3, e2, e2*e3 - e2]; puts "relations: =" + relations.join(", ") { |r| r.to_s }; puts; rp = SolvPolyRing.new(QQ(), "a,b,e1,e2,e3", PolyRing.lex, relations); puts "SolvPolyRing: " + str(rp); puts; puts "gens =" + rp.gens().join(", ") { |r| r.to_s }; one,a,b,e1,e2,e3 = rp.gens(); f1 = e1 * e3**3 + e2**10 - a; f2 = e1**3 * e2**2 + e3; f3 = e3**3 + e3**2 - b; #puts "f1 = ", f1; #puts "f2 = ", f2; #puts "f3 = ", f3; F = [ f1, f2, f3 ]; puts "F =" + F.join(", ") { |r| r.to_s }; puts I = rp.ideal( "", F ); puts "SolvableIdeal: " + str(I); puts; rgl = I.leftGB(); puts "seq left GB:" + str(rgl); puts "isLeftGB: " + str(rgl.isLeftGB()); puts; rgt = I.twosidedGB(); puts "seq twosided GB:" + str(rgt); puts "isTwosidedGB: " + str(rgt.isTwosidedGB()); puts; rgr = I.rightGB(); puts "seq right GB:" + str(rgr); puts "isRightGB: " + str(rgr.isRightGB()); puts; #exit(0); rs = """ # solvable polynomials, Weyl algebra A_3,2: Rat(a,b,e1,e2,e3) L #Quat(a,b,e1,e2,e3) G|3| RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e1 ), ( e3 ), ( e2 ), ( e2 e3 - e2 ) ) """; r = SolvableRing.new( rs ); puts "SolvableRing: " + str(r); puts; #one,a,b,e1,e2,e3 = r.gens(); f1 = e1 * e3**3 + e2**10 - a; f2 = e1**3 * e2**2 + e3; f3 = e3**3 + e3**2 - b; puts "f1: " + str(f1); puts "f2: " + str(f2); puts "f3: " + str(f3); puts; ff = r.ideal( "", [f1,f2,f3] ); puts "SolvableIdeal: " + str(ff); puts; #exit(); rg = ff.leftGB(); puts "seq left GB: " + str(rg); puts "isLeftGB: " + str(rgt.isLeftGB()); puts; puts "rgl == rg: " + str(rgl.list == rg.list); puts; #exit(); rg = ff.twosidedGB(); puts "seq twosided GB: " + str(rg); puts "isTwosidedGB: " + str(rgt.isTwosidedGB()); puts; puts "rgt == rg: " + str(rgt.list == rg.list); rg = ff.rightGB(); puts "seq right GB: " + str(rg); puts "isRightGB: " + str(rgt.isRightGB()); puts; puts "rgr == rg: " + str(rgr.list == rg.list); #startLog(); #terminate(); jas-2.5/examples/cyclic6_opt.py0000644000175000017500000000215111630417274016755 0ustar giovannigiovanni# # jython examples for jas. # $Id: cyclic6_opt.py 3757 2011-09-03 12:34:04Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog # example cyclic6, optimize term order # optimal is no change #r = Ring( "Rat (x1,x2,x3,x4,x5,x6) G" ); #r = Ring( "Mod 3 (x1,x2,x3,x4,x5,x6) L" ); #r = Ring( "Rat (x6,x5,x4,x3,x2,x1) G" ); #r = Ring( "Mod 19 (x6,x5,x4,x3,x2,x1) G" ); r = Ring( "Mod 3 (x6,x5,x4,x3,x2,x1) G" ); print "Ring: " + str(r); print; ps = """ ( x1 + x2 + x3 + x4 + x5 + x6, x1*x2 + x1*x6 + x2*x3 + x3*x4 + x4*x5 + x5*x6, x1*x2*x3 + x1*x2*x6 + x1*x5*x6 + x2*x3*x4 + x3*x4*x5 + x4*x5*x6, x1*x2*x3*x4 + x1*x2*x3*x6 + x1*x2*x5*x6 + x1*x4*x5*x6 + x2*x3*x4*x5 + x3*x4*x5*x6, x1*x2*x3*x4*x5 + x1*x2*x3*x4*x6 + x1*x2*x3*x5*x6 + x1*x2*x4*x5*x6 + x1*x3*x4*x5*x6 + x2*x3*x4*x5*x6, x1*x2*x3*x4*x5*x6 - 1 ) """; #x1 + x2 + x3 + x4 + x5 + x6, #x1*x2*x3*x4*x5*x6 - 1 f = Ideal( r, ps ); print "Ideal: " + str(f); print; startLog(); o = f.optimize(); print "optimized Ideal: " + str(o); print; rg = f.GB(); print "Output:", rg; print; #org = o.GB(); #print "opt Output:", org; #print; jas-2.5/examples/katsura5.jas0000644000175000017500000000106411353207070016416 0ustar giovannigiovanni#Katsura equations for N = 5: (u5,u4,u3,u2,u1,u0) G ( u5*u5 + u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 + u5*u5 - u0, u5*0 + u4*u5 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 + u5*u4 - u1, u5*0 + u4*0 + u3*u5 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 + u5*u3 - u2, u5*0 + u4*0 + u3*0 + u2*u5 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 + u5*u2 - u3, u5*0 + u4*0 + u3*0 + u2*0 + u1*u5 + u0*u4 + u1*u3 + u2*u2 + u3*u1 + u4*u0 + u5*u1 - u4, u5 + u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 + u5 - 1 ) jas-2.5/examples/factors_mod.py0000644000175000017500000000430111224463142017030 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_mod.py 2717 2009-07-06 21:02:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring from jas import Ideal from jas import terminate from jas import startLog # polynomial examples: factorization over Z_p #r = Ring( "Mod 1152921504606846883 (x) L" ); #r = Ring( "Mod 19 (x) L" ); r = Ring( "Mod 19 (x) L" ); print "Ring: " + str(r); print; [one,x] = r.gens(); #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**4 - 1; f = x**2 + 1; #f = x**19 + x; #f = x**3 - x**2 + x - 1; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; #f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; #f = x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8; print "f = ", f; print; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; print "G = ", G; #print "factor time =", t, "milliseconds"; g = one; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/wa_32_syz.py0000644000175000017500000000306512136720410016353 0ustar giovannigiovanni# # jython examples for jas. # $Id: wa_32_syz.py 4381 2013-04-27 09:57:28Z kredel $ # from jas import SolvableRing from edu.jas.poly import ModuleList; from edu.jas.gbmod import SolvableSyzygyAbstract; # WA_32 example rs = """ # solvable polynomials, Weyl algebra A_3,2: Rat(a,b,e1,e2,e3) G3| RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e1 ), ( e3 ), ( e2 ), ( e2 e3 - e2 ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( e1 e3^3 + e2^10 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) """; f = r.ideal( ps ); print "SolvableIdeal: " + str(f); print; Z = SolvableSyzygyAbstract().leftZeroRelationsArbitrary( f.list ); Zp = ModuleList( r.ring, Z ); print "seq left syz Output:", Zp; print; if SolvableSyzygyAbstract().isLeftZeroRelation( Zp.list, f.list ): print "is left syzygy"; else: print "is not left syzygy"; Zr = SolvableSyzygyAbstract().rightZeroRelationsArbitrary( f.list ); Zpr = ModuleList( r.ring, Zr ); print "seq right syz Output:", Zpr; print; if SolvableSyzygyAbstract().isRightZeroRelation( Zpr.list, f.list ): print "is right syzygy"; else: print "is not right syzygy"; rg = f.leftGB(); print "seq left Output:", rg; print; if rg.isLeftGB(): print "is left GB"; else: print "is not left GB"; g = rg.list; rg = f.twosidedGB(); print "seq twosided Output:", rg; print; if rg.isTwosidedGB(): print "is twosided GB"; else: print "is not twosided GB"; rgb = rg.rightGB(); print "seq right Output:", rgb; print; if rgb.isRightGB(): print "is right GB"; else: print "is not right GB"; jas-2.5/examples/hawes2opt.py0000644000175000017500000000250411505167460016455 0ustar giovannigiovanni# # jython examples for jas. # $Id: hawes2opt.py 3438 2010-12-24 19:06:24Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} import sys; from jas import Ring, PolyRing, RF, ZZ from jas import Ideal from jas import startLog from jas import terminate #startLog(); # Hawes & Gibson example 2 # rational function coefficients #r = Ring( "RatFunc(a, c, b) (y2, y1, z1, z2, x) L" ); r = PolyRing( RF(PolyRing(ZZ(),"a, c, b",PolyRing.lex)), "y2, y1, z1, z2, x", PolyRing.lex ); print "Ring: " + str(r); print; ps = """ ( ( x + 2 y1 z1 + { 3 a } y1^2 + 5 y1^4 + { 2 c } y1 ), ( x + 2 y2 z2 + { 3 a } y2^2 + 5 y2^4 + { 2 c } y2 ), ( 2 z2 + { 6 a } y2 + 20 y2^3 + { 2 c } ), ( 3 z1^2 + y1^2 + { b } ), ( 3 z2^2 + y2^2 + { b } ) ) """; f = r.ideal( ps ); print "Ideal: " + str(f); print; startLog(); o = f.optimize(); print "optimized Ideal: " + str(o); print; p = o.paramideal(); p = p.optimizeCoeffQuot(); print "optimized coeff Ideal: " + str(p); print; #rg = o.GB(); #print "GB:", rg; #print; rg = p; bg = rg.isGB(); print "isGB:", bg; print; terminate(); #sys.exit(); jas-2.5/examples/logic.py0000644000175000017500000000101711005434274015627 0ustar giovannigiovanni# # jython examples for jas. # $Id: logic.py 1770 2008-04-28 20:51:09Z kredel $ # from jas import Ring from jas import Ideal # logic example from Kreutzer JdM 2008 r = Ring( "Mod 2 (a,f,p,u) G" ); print "Ring: " + str(r); print; ks = """ ( ( a^2 - a ), ( f^2 - f ), ( p^2 - p ), ( u^2 - u ) ) """; ps = """ ( ( p f + p ), ( p u + p + u + 1 ), ( a + u + 1 ), ( a + p + 1 ) ) """; k = r.ideal( ks ); p = r.ideal( ps ); f = k.sum( p ); print "Ideal: " + str(f); print; rg = f.GB(); print "Output:", rg; print; jas-2.5/examples/0dim_radical.py0000644000175000017500000000160411370363156017051 0ustar giovannigiovanni# # jython examples for jas. # $Id: 0dim_radical.py 3112 2010-05-05 21:43:10Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: zero dimensional ideals radical decomposition #r = Ring( "Rat(x) L" ); #r = Ring( "Q(x) L" ); r = PolyRing(QQ(),"x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); f1 = (x**2 - 5)**2; f2 = (y**2 - 3)**3 * (y**2 - 5); f3 = z**3 - x * y; print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print; F = r.ideal( list=[f1,f2,f3] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); t = System.currentTimeMillis() - t; print "R = ", R; print; print "decomp time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/cyclic5_complex_roots.rb0000644000175000017500000000177711773563306021045 0ustar giovannigiovanni# # jruby examples for jas. # $Id: cyclic5_complex_roots.rb 3967 2012-06-30 11:45:11Z kredel $ # require "examples/jas" # polynomial examples: complex roots over Q for zero dimensional ideal `cyclic5' r = PolyRing.new(QQ(),"a,b,c,d,e",PolyRing.lex); puts "Ring: " + str(r); puts; #one,q,w,s,x = r.gens(); f1 = a + b + c + d + e; f2 = a*b + b*c + c*d + d*e + e*a; f3 = a*b*c + b*c*d + c*d*e + d*e*a + e*a*b; f4 = a*b*c*d + b*c*d*e + c*d*e*a + d*e*a*b + e*a*b*c; f5 = a*b*c*d*e - 1; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts "f4 = " + str(f4); puts "f5 = " + str(f5); puts; F = r.ideal( "", list=[f1,f2,f3,f4,f5] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.complexRoots(); #R = F.realRoots(); t = System.currentTimeMillis() - t; puts "complex decomposition = " + str(R); puts; puts "complex roots = "; F.complexRootsPrint() puts "complex roots time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/preimage.py0000644000175000017500000000214410653122700016321 0ustar giovannigiovanni# # jython examples for jas. # $Id: preimage.py 1282 2007-07-29 14:35:45Z kredel $ # from jas import Ring from jas import Ideal from edu.jas import application rs = """ # polynomial ring: Rat(x1,x2,x3,y1,y2) G|3| """; ps = """ ( ( y1 + y2 - 1 ), ( x1 - y1^2 - y1 - y2 ), ( x2 - y1 - y2^2 ), ( x3 - y1 y2 ) ) """; r = Ring( rs ); print "Ring: " + str(r); i = Ideal( r, ps ); print "Ideal: " + str(i); g = i.GB(); print "seq GB:", g; rsi = """ # polynomial ring: Rat(x1,x2,x3) G """; ri = Ring( rsi ); print "Ring: " + str(ri); y = application.Ideal(g.pset).intersect(ri.ring); len = y.list.size(); print "seq intersect y: ", y; rs = """ # polynomial ring: Rat(y1,y2,x1,x2,x3) G|2| """; ps = """ ( ( y1 + y2 - 1 ), ( x1 - y1^2 - y1 - y2 ), ( x2 - y1 - y2^2 ), ( x3 - y1 y2 ) ) """; r = Ring( rs ); print "Ring: " + str(r); i = Ideal( r, ps ); print "Ideal: " + str(i); g = i.GB(); print "seq GB:", g; rsb = """ # polynomial ring: Rat(y1,y2) G """; rb = Ring( rsb ); print "Ring: " + str(rb); y = application.Ideal(g.pset).intersect(rb.ring); len = y.list.size(); print "seq intersect y: ", y; jas-2.5/examples/radical-decomp_charp_infin.rb0000644000175000017500000000213511653043730021715 0ustar giovannigiovanni# # jruby examples for jas. # $Id: radical-decomp_charp_infin.rb 3817 2011-10-29 18:37:12Z kredel $ # require "examples/jas" # polynomial examples: ideal radical decomposition, inseparable cases, dim > 0 #noThreads(); # must be called very early cr = PolyRing.new(ZM(5),"c",PolyRing.lex); puts "coefficient Ring: " + str(cr); rf = RF(cr); puts "coefficient quotient Ring: " + str(rf.ring); r = PolyRing.new(rf,"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,c,x,y,z = r.gens(); puts one,c,x,y,z; #sys.exit(); #f1 = (x**2 - 5)**2; #f1 = (y**10 - x**5)**3; f1 = (x**2 + 2)**2; f2 = (y**2 - x)**5; #f2 = f2**5; f3 = (z**2 - c)**5; f4 = (y**2 - x)**3; #puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); #puts "f4 = " + str(f4); puts; #F = r.ideal( "", list=[f1,f2,f3] ); F = r.ideal( "", list=[f2,f3] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "decomp time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/prime-decomp-charp.rb0000644000175000017500000000200611653043730020162 0ustar giovannigiovanni# # jruby examples for jas. # $Id: prime-decomp-charp.rb 3817 2011-10-29 18:37:12Z kredel $ # require "examples/jas" # polynomial examples: ideal prime decomposition in char p > 0, inseparable cases cr = PolyRing.new(ZM(5),"c",PolyRing.lex); puts "coefficient Ring: " + str(cr); rf = RF(cr); puts "coefficient quotient Ring: " + str(rf.ring); r = PolyRing.new(rf,"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,c,x,y,z = r.gens(); puts one,c,x,y,z; #sys.exit(); f1 = (x**2 - 2); #**2; f2 = (y**2 - c)**5; f3 = (z**2 - 2 * c); #**5; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); #puts "f4 = " + str(f4); puts; F = r.ideal( "", list=[f1,f2,f3] ); #F = r.ideal( "", list=[f1,f3] ); #F = r.ideal( "", list=[f2,f3] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); P = F.primeDecomp(); t = System.currentTimeMillis() - t; puts "P = " + str(P); puts; puts "decomp time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/alg_stat_1p.py0000644000175000017500000000252612020211330016716 0ustar giovannigiovanni# # jython examples for jas. # $Id: alg_stat_1p.py 4147 2012-08-31 19:39:05Z kredel $ # import sys; from jas import Ring, PolyRing, Ideal from jas import QQ, ZZ, RF from jas import startLog, terminate # example: Algebraic Statistics # Drton, Sturmfels, Sullivant, example 2.1.3 r = PolyRing(RF(PolyRing(QQ(),"u0,u1,u2,u12",PolyRing.lex)),"l1,l2",PolyRing.grad); print "Ring: " + str(r); print; print one,u0,u1,u2,u12,l1,l2; f1 = (u1+u12)*(l1+l2+2)*(l1+1)*(l1+l2+1)\ + (u12)*l1*(l1+1)*(l1+l2+1)\ - (u2+u12)*l1*(l1+l2+2)*(l1+l2+1)\ - (u0+u1+u2+u12)*l1*(l1+l2+2)*(l1+1) ; f2 = (u2+u12)*(l1+l2+2)*(l2+1)*(l1+l2+1)\ + (u12)*l2*(l2+1)*(l1+l2+1)\ - (u1+u12)*l2*(l1+l2+2)*(l1+l2+1)\ - (u0+u1+u2+u12)*l2*(l1+l2+2)*(l2+1) ; print f1; print f2; print #h = l1*l2*(l1+1)*(l2+1)*(l1+l2+1)*(l1+l2+2); h = l1*l2*(l1+1); hp = (l2+1); hpp = (l1+l2+1)*(l1+l2+2); print h; print hp; print hpp; print F = r.ideal(list=[f1,f2]); print F; print H = r.ideal(list=[h]); print H; print Hp = r.ideal(list=[hp]); print Hp; print Hpp = r.ideal(list=[hpp]); print Hpp; print startLog(); G = F.GB(); print G; print #startLog(); Q = G.sat(H); print Q; print Q = Q.sat(Hp); print Q; print Q = Q.sat(Hpp); print Q; print D = Q.radicalDecomp(); print D; print #Di = Q.decomposition(); #print Di; #print #startLog(); terminate(); #sys.exit(); jas-2.5/examples/module.py0000644000175000017500000000066011226717420016024 0ustar giovannigiovanni# # jython examples for jas. from jas import Module from jas import SubModule # module example r = Module( "Rat(u,v,l) L", cols=4 ); print "Module: " + str(r); print; G = r.gens(); print "gens() = ", [str(e) for e in G]; L = [ e.elem.val for e in G ] print "gens() = ", [str(e) for e in L]; M = r.submodul( list=L ); print "M = ", M; P = M.mset.getPolynomialList(); print "P = ", P.toScript(); print "M.isGB(): ", M.isGB(); jas-2.5/examples/basic_sigbased_gb.py0000644000175000017500000003515311646651532020145 0ustar giovannigiovanni# Implementations of algorithms found in joint paper by Eder and Perry # Copyright (C) 2010-2011, the University of Southern Mississippi # released into the public domain # # Originally from http://www.math.usm.edu/perry/Research/basic_sigbased_gb.py # slightly changed for JAS compatibility, changes are labled with JAS # $Id: basic_sigbased_gb.py 3804 2011-10-16 21:57:47Z kredel $ # this implementation has one significant difference from the paper: # the paper maintains monic signatures, but # this implementation maintains monic polynomials class sigbased_gb: # the base class from which all other classes are derived def basis_sig(self,F): # incremental basis computation # F is a container of generators of an ideal F.sort(key=lambda x: -x.lm().degree()) # JAS #print "JAS F = " + str([ str(g) for g in F]); G = list() for f in F: G = self.incremental_basis(G,f) Gnew = [g[1] for g in G] R = f.parent() print "size before reduction", len(G) G = R.ideal(Gnew).interreduced_basis() return G def spoly_multipliers(self,f,g): # multipliers for the s-polynomial of f and g # returns uf,ug such that # that is, spoly(f,g) = uf.f - ug.g tf = f.lm(); tg = g.lm() tfg = tf.lcm(tg) R = self.R return (R.monomial_quotient(tfg,tf),R.monomial_quotient(tfg,tg)) def subset(self,S,criterion): # this should be changed to use Python's filter() command result = set() for s in S: if criterion(s): result.add(s) return result def min_sig_degree(self,P): # determines the minimal degree of a signature in P return min([p[0].degree() for p in P]) def new_pair(self,sig,p,q,G): # creates a new critical pair from p and q, with signature sig # it needs G for the sake of F5; see derived class below return (sig,p,q) def spoly(self,s,G): # computes the spolynomial # assumes that s has the form (signature, poly, poly) f = s[1]; g = s[2] tf = f.lm(); tg = g.lm() tfg = tf.lcm(tg) R = f.parent() uf = R.monomial_quotient(tfg,tf); ug = R.monomial_quotient(tfg,tg) return uf*f - ug*g def initialize_Syz(self,F,G): # initializes Syz; initially, this does nothing return set() def prune_P(self,P,Syz): # prunes P using Syz; initially, this does nothing return P def prune_S(self,S,Syz,Done,G): # prunes S using Syz, Done, and G; initially, this does nothing # (Done is used as a shortcut) return S def update_Syz(self,Syz,sigma,r): # updates Syz using sigma and r # some algorithms use this; some don't return Syz def sigsafe_reduction(self,s,sigma,G,F,Syz): # computes a complete sigma-reduction of s modulo G # F is assumed to be a subset of G that represents the previous GB incrementally # Syz is sent but not used (I should probably remove this) r = s r_sigma = sigma R = self.R reduced = True while (r != 0) and reduced: reduced = False r = r.reduce(F) if any(g[1] != 0 and R.monomial_divides(g[1].lm(),r.lm()) for g in G): for g in G: if g[1] != 0 and R.monomial_divides(g[1].lm(),r.lm()): u = self.R.monomial_quotient(r.lt(),g[1].lt(),coeff=True) sig_ug = u*g[0] if (sig_ug < r_sigma) or ((sig_ug.lm() == r_sigma.lm()) and (sig_ug.lc() != r_sigma.lc())): reduced = True r -= u*g[1] if (sig_ug.lm() == r_sigma.lm()): r_sigma -= sig_ug # ensure that r is monic if r != 0: c = r.lc() r *= c**(-1) r_sigma *= c**(-1) return r_sigma, r def sig_redundant(self,sigma,r,G): # test whether (sigma,r) is signature-redundant wrt G R = self.R return any(g[0] != 0 and R.monomial_divides(g[0].lm(),sigma.lm()) and R.monomial_quotient(sigma.lm(),g[0].lm())*g[1].lm()==r.lm() for g in G) #if any ((g[0] != 0 and R.monomial_divides(g[0].lm(),sigma.lm())) and (g[1] != 0 and R.monomial_divides(g[1].lm(),r.lm())) and not R.monomial_quotient(sigma.lm(),g[0].lm())*g[1].lm()==r.lm() for g in G): # print "counterexample at", (sigma, r.lm()) return any ((g[0] != 0 and R.monomial_divides(g[0].lm(),sigma.lm())) and (g[1] != 0 and R.monomial_divides(g[1].lm(),r.lm())) for g in G) def incremental_basis(self,F,g): # assuming that F is a Groebner basis of the ideal generated by F, # compute a Groebner basis of F+[g] self.R = g.parent(); R = self.R # to record a signature, we use only the leading monomial of a minimal representation # so that elements of F have "signature" 0 and g has "signature" 1 G = [(R(0),F[i]) for i in xrange(len(F))] + [(R(1),g)] #print "JAS G = " + str([ str(gg[0])+","+str(gg[1]) for gg in G]); # the structure of a pair can vary, except for its first entry, # which should be the signature P = set([self.new_pair(self.spoly_multipliers(g,f)[0],g,f,G) for f in F]) Syz = self.initialize_Syz(F,G) # Done will track new polynomials computed by the algorithm Done = list() while len(P) != 0: P = self.prune_P(P,Syz) if len(P) != 0: S = list(self.subset(P,lambda x: x[0].degree() == self.min_sig_degree(P))) print "treating", len(S), "signatures of degree", self.min_sig_degree(P) P.difference_update(S) while len(S) != 0: S = self.prune_S(S,Syz,Done,G) if len(S) != 0: # sort by signature S.sort(key=lambda x:x[0]); s = S.pop(0) sigma,r = self.sigsafe_reduction(self.spoly(s,G),s[0],G,F,Syz) if (r != 0) and (not self.sig_redundant(sigma,r,G)): #print "new polynomial", (sigma,r.lm()) for (tau,g) in G: if (g != 0): rmul,gmul = self.spoly_multipliers(r,g) if rmul*sigma.lm() != gmul*tau.lm(): if rmul*sigma.lm() > gmul*tau.lm(): p = self.new_pair(rmul*sigma,r,g,G) else: p = self.new_pair(gmul*tau,g,r,G) if p[0].degree() == sigma.degree(): S.append(p) else: P.add(p) G.append((sigma,r)) Done.append((sigma,r)) elif r == 0: #print "zero reduction at", (sigma,r.lm()) self.update_Syz(Syz,sigma,r) Done.append((sigma,r)) #else: #print "sig-redundant at", sigma return list(self.subset(G,lambda x: x[1] != 0)) class ggv(sigbased_gb): # the plugin implementation of ggv def new_pair(self,sig,p,q,G): # creates a new critical pair from p and q, with signature sig # it needs G for the sake of F5; see derived class below i = -1; j = -1; k = 0 up,uq = self.spoly_multipliers(p,q) while (i<0 or j<0) and k < len(G): if p == G[k][1]: i = k elif q == G[k][1]: j = k k += 1; if (i == -1): i=len(G) elif (j == -1): j = len(G) return (sig,i,j) def initialize_Syz(self,F,G): # recognize trivial syzygies return set([f.lm() for f in F]) def spoly(self,s,G): # ggv only computes part of an S-polynomial # (as if it were computing a row of the Macaulay matrix # and not subsequently triangularizing) f = G[s[1]][1]; g = G[s[2]][1] tf = f.lm(); tg = g.lm() tfg = tf.lcm(tg) uf = self.R.monomial_quotient(tfg,tf) return uf*f def prune_P(self,P,Syz): # remove any pair whose signature is divisible by an element of Syz result = set() R = self.R for p in P: if not any(R.monomial_divides(t,p[0]) for t in Syz): result.add(p) return result def prune_S(self,S,Syz,Done,G): # watch out for new syzygies discovered, and allow only one polynomial # per signature result = list() R = self.R for s in S: if not any(R.monomial_divides(t,s[0]) for t in Syz): if not any(s[0].lm()==sig[0].lm() and s[1]sig[1].lm() for sig in S): for (sig,f) in Done: if self.R.monomial_divides(sig,s[0]): u = self.R.monomial_quotient(s[0],sig) if u*f.lm() < s[1].lm(): break else: result.append(s) return result def new_pair(self,sig,p,q,G): # in arri's algorithm, each pair is (sigma,s) where s is the s-polynomial # and sigma is its natural signature tp = p.lm(); tq = q.lm() tpq = tp.lcm(tq) R = p.parent() #JAS tpq.parent() up = R.monomial_quotient(tpq,tp); uq = R.monomial_quotient(tpq,tq) return (sig,up*p-uq*q) def spoly(self,s,G): return s[1] class f5(coeff_free_sigbased_gb): # the plugin implementation of arri's algorithm def initialize_Syz(self,F,G): # recognize trivial syzygies return set([f.lm() for f in F]) def update_Syz(self,Syz,sigma,r): # recognize trivial syzygies # see class f5z for a more thorough update_Syz in line w/arri and ggv return Syz def prune_P(self,P,Syz): # remove any pair whose signature is divisible by an element of Syz result = set() for p in P: if not any(self.R.monomial_divides(t,p[0]) for t in Syz): result.add(p) return result def prune_S(self,S,Syz,Done,G): # watch out for new syzygies discovered, and apply faugere's rewritable criterion: # for any (sigma,p,q) in S, if there exists (tau,g) such that tau divides sigma # but g was generated after p, discard (sigma,p,q) result = list() for (sig,u,j,v,k) in S: if not any(self.R.monomial_divides(t,sig) for t in Syz): if G[j][0] == 0 or not any(self.R.monomial_divides(Done[i][0],G[j][0]*u) and Done[i][0] > G[j][0] for i in xrange(len(Done))): result.append((sig,u,j,v,k)) return result def new_pair(self,sig,p,q,G): # it's easier to deal with faugere's criterion if one creates pairs # using indices rather than polynomials # note that this while look gives f5 a disadvantage i = -1; j = -1; k = 0 up,uq = self.spoly_multipliers(p,q) while (i<0 or j<0) and k < len(G): if p == G[k][1]: i = k elif q == G[k][1]: j = k k += 1; if (i == -1): i=len(G) elif (j == -1): j = len(G) return (sig,up,i,uq,j) def spoly(self,s,G): # since s has the structure (sigma,up,i,uq,j) # we have to compute the s-polynomial by looking up f and g f = G[s[2]][1]; g = G[s[4]][1] uf = s[1]; ug = s[3] return uf*f - ug*g class f5z(f5): def update_Syz(self,Syz,sigma,r): # recognize trivial syzygies if r == 0: Syz.add(sigma.lm()) return Syz class min_size_mons(arris_algorithm): # the plugin implementation of arri's algorithm def prune_S(self,S,Syz,Done,G): # watch out for new syzygies discovered, and apply the minimal "number of monomials" criterion: # for any s-polynomial of a given signature, if there exists another polynomial # in Done of identical signature but fewer monomials, replace this s-polynomial # by the multiple of the polynomial with fewer monomials result = list() R = G[0][1].parent() for (sigma,s) in S: if not any(R.monomial_divides(tau,sigma) for tau in Syz): if not any(tau == sigma for (tau,g) in result): for (tau,g) in Done: if tau.divides(sigma) and len(g.monomials()) < len(s.monomials()): u = R.monomial_quotient(sigma,tau) result.append((u*tau,u*g)) break else: result.append((sigma,s)) return result jas-2.5/examples/factors_abs_complex.rb0000644000175000017500000000305511641415316020530 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_abs_complex.rb 3786 2011-09-30 19:38:55Z kredel $ # require "examples/jas" # polynomial examples: absolute factorization over Q(i) Qr = PolyRing.new(QQ(),"i",PolyRing.lex); puts "Qr = " + str(Qr); e,a = Qr.gens(); puts "e = " + str(e); puts "a = " + str(a); imag = a**2 + 1; puts "imag = " + str(imag); Qi = AN(imag,true); puts "Qi = " + str(Qi.factory()); one,i = Qi.gens(); puts "one = " + str(one); puts "i = " + str(i); puts; r = PolyRing.new(Qi,"x",PolyRing.lex) puts "r = " + str(r); one,i,x = r.gens(); puts "one = " + str(one); puts "i = " + str(i); puts "x = " + str(x); puts; #f = x**7 - 1; #f = x**6 + x**5 + x**4 + x**3 + x**2 + x + 1; #f = x**2 - i; #f = x**3 - i; #f = x**2 + 1; #f = x**5 - 1; #f = x**4 + x**3 + x**2 + x + (1,); #f = ( x**2 - i - 1 ) * ( x**2 + i + 1 ); f = ( x**2 - i ) * ( x**2 + i + 1 ); puts "f = " + str(f); puts; #startLog(); t = System.currentTimeMillis(); g = r.factors(f); t = System.currentTimeMillis() - t; #puts "G = " + str(g); #puts "factor time = " + str(t) + " milliseconds"; f2 = one; for h, i in g puts "h**i = (" + str(h) + ")**" + str(i); h = h**i; f2 = f2*h; end #puts "f2 = " + str(f2); puts; puts "factor time = " + str(t) + " milliseconds, " + "isFactors(f,g): " + str( f==f2 ); puts; startLog(); t = System.currentTimeMillis(); g = r.factorsAbsolute(f); t = System.currentTimeMillis() - t; puts "G = ", g.toScript(); puts puts "factor time = " + str(t) + " milliseconds"; puts #sys.exit(); #startLog(); terminate(); jas-2.5/examples/u_sl_3_prod.rb0000644000175000017500000000474612136716620016735 0ustar giovannigiovanni# # jruby examples for jas. # $Id: u_sl_3_prod.rb 4380 2013-04-27 09:42:41Z kredel $ # require "examples/jas" # U(sl_3) example rs = """ # solvable polynomials, U(sl_3): Rat(Xa,Xb,Xc,Ya,Yb,Yc,Ha,Hb) G RelationTable ( ( Xb ), ( Xa ), ( Xa Xb - Xc ), ( Ya ), ( Xa ), ( Xa Ya - Ha ), ( Yc ), ( Xa ), ( Xa Yc + Yb ), ( Ha ), ( Xa ), ( Xa Ha + 2 Xa ), ( Hb ), ( Xa ), ( Xa Hb - Xa), ( Yb ), ( Xb ), ( Xb Yb - Hb ), ( Yc ), ( Xb ), ( Xb Yc - Ya ), ( Ha ), ( Xb ), ( Xb Ha - Xb ), ( Hb ), ( Xb ), ( Xb Hb + 2 Xb ), ( Ya ), ( Xc ), ( Xc Ya + Xb ), ( Yb ), ( Xc ), ( Xc Yb - Xa ), ( Yc ), ( Xc ), ( Xc Yc - Ha - Hb ), ( Ha ), ( Xc ), ( Xc Ha + Xc ), ( Hb ), ( Xc ), ( Xc Hb + Xc ), ( Yb ), ( Ya ), ( Ya Yb + Yc ), ( Ha ), ( Ya ), ( Ya Ha - 2 Ya ), ( Hb ), ( Ya ), ( Ya Hb + Ya ), ( Ha ), ( Yb ), ( Yb Ha + Yb ), ( Hb ), ( Yb ), ( Yb Hb - 2 Yb ), ( Ha ), ( Yc ), ( Yc Ha - Yc ), ( Hb ), ( Yc ), ( Yc Hb - Yc ) ) """; r = SolvableRing.new( rs ); puts "SolvableRing: " + str(r); puts; ps = """ ( ( Xb + Yb ) ) """; # ( Xa + Xb + Xc + Ya + Yb + Yc + Ha + Hb ) f = r.ideal( ps ); puts "SolvIdeal: " + str(f); puts; #startLog(); fl = f.list; puts "fl: " + str(fl); p = fl[0]; puts "p: " + str(p); puts; #from java.lang import System p2 = p; n = 15; t = System.currentTimeMillis(); for i in 1..n p2 = p2.multiply(p); t1 = System.currentTimeMillis() -t; puts "one product in #{t1} ms"; end puts "p^#{n}.length: " + str(p2.length()); puts; p2 = p; t = System.currentTimeMillis(); for i in 1..n p2 = p2.multiply(p); t1 = System.currentTimeMillis() -t; puts "one product in #{t1} ms"; end puts "p^#{n}.length: " + str(p2.length()); puts; ps = """ ( ( Xa ), ( Xb ), ( Xc ), ( Ya ), ( Yb ), ( Yc ), ( Ha ), ( Hb ) ) """; f = r.ideal( ps ); #puts "SolvableIdeal: " + str(f); #puts; fl = f.list; Yb = fl[4]; p1 = Yb; Xb = fl[1]; p2 = Xb; #n = 10; t = System.currentTimeMillis(); for i in 1..n p1 = p1.multiply(Yb); p2 = p2.multiply(Xb); p = p1.multiply(p2); t1 = System.currentTimeMillis() -t; puts "products in #{t1} ms"; end puts "Xb^#{n} * Yb^#{n} .length(): " + str(p.length); puts; pp = p; p1 = Yb; p2 = Xb; t = System.currentTimeMillis(); for i in 1..n p1 = p1.multiply(Yb); p2 = p2.multiply(Xb); p = p1.multiply(p2); t1 = System.currentTimeMillis() -t; puts "products in #{t1} ms"; end puts "Xb^#{n} * Yb^#{n} .length(): " + str(p.length()); puts; puts "pp == p: " + str(pp == p); puts; #puts "SolvIdeal: " + str(f); #puts; jas-2.5/examples/factors_abs_complex.py0000644000175000017500000000350011210751460020543 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_abs_complex.py 2664 2009-06-01 13:10:09Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import QQ, AN from jas import terminate from jas import startLog # polynomial examples: absolute factorization over Q(i) Qr = PolyRing(QQ(),"i",PolyRing.lex); print "Qr = " + str(Qr); [e,a] = Qr.gens(); print "e = " + str(e); print "a = " + str(a); imag = a**2 + 1; print "imag = " + str(imag); Qi = AN(imag,field=True); print "Qi = " + str(Qi.factory()); [one,i] = Qi.gens(); print "one = " + str(one); print "i = " + str(i); print; r = PolyRing(Qi,"x",PolyRing.lex) print "r = " + str(r); [one,i,x] = r.gens(); print "one = " + str(one); print "i = " + str(i); print "x = " + str(x); print; #f = x**7 - 1; #f = x**6 + x**5 + x**4 + x**3 + x**2 + x + 1; #f = x**2 - i; #f = x**3 - i; #f = x**2 + 1; #f = x**5 - 1; #f = x**4 + x**3 + x**2 + x + (1,); #f = ( x**2 - i - 1 ) * ( x**2 + i + 1 ); f = ( x**2 - i ) * ( x**2 + i + 1 ); print "f = ", f; print; #startLog(); t = System.currentTimeMillis(); G = r.factors(f); t = System.currentTimeMillis() - t; #print "G = ", G; #print "factor time =", t, "milliseconds"; f2 = one; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; f2 = f2*h; #print "f2 = ", f2; print; if cmp(f,f2) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,f2); print; startLog(); t = System.currentTimeMillis(); G = r.factorsAbsolute(f); t = System.currentTimeMillis() - t; print "G = ", G.toScript(); print print "factor time =", t, "milliseconds"; print #sys.exit(); #startLog(); terminate(); jas-2.5/examples/prime-decomp.rb0000644000175000017500000000135111637331234017072 0ustar giovannigiovanni# # jruby examples for jas. # $Id: prime-decomp.rb 3777 2011-09-24 10:36:13Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: ideal prime decomposition r = PolyRing.new(QQ(),"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); f1 = (x**2 - 5)**2; f2 = y**3 - x; f3 = z**2 - y * x; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; #F = r.ideal( "", [f1,f2,f3] ); F = r.ideal( "", [f2,f3] ); puts "F = ", F; puts; startLog(); t = System.currentTimeMillis(); P = F.primeDecomp(); t1 = System.currentTimeMillis() - t; puts "P = " + str(P); puts; puts "prime decomp time = " + str(t1) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/gbks.jas0000644000175000017500000000313110653077260015612 0ustar giovannigiovanni#(*example 7.5.90, ks, hk, uni passau. *) #(*coefficients: rational numbers or integers mod 3. *) #(*variables: *) (a4k1,a4k3,a5k1,a5k2,a5k3,a6k2,a6k3,a7k1,a7k2, a7k3,a8k1,a8k2,a9k1,a9k2,a9k3, a10k1,a10k2,a10k3,a11k1,a11k2, a11k3,a12k1,a12k2,a12k3) G #(*polynomials: *) ( ( -a9k3 - a9k2*a4k3 - 1 ), ( a8k2*a9k3 + a9k2 +1 ), ( a7k3 + a7k1*a6k3 +1 ), ( a7k1 + a8k1*a7k3 +1 ), ( a4k1*a5k2 + a5k1 +1 ), ( a5k1*a6k2 + a5k2 +1 ), ( a4k1*a5k2*a10k3 - a4k1*a10k2*a5k3 + a5k1*a10k3 + a5k1*a10k2*a4k3 - a10k1*a5k3 - a10k1*a5k2*a4k3 -1 ), ( a4k1*a9k2*a10k3 - a4k1*a10k2*a9k3 + a9k1*a10k3 + a9k1*a10k2*a4k3 - a10k1*a9k3 - a10k1*a9k2*a4k3 +1 ), ( a5k1*a6k2*a11k3 - a5k1*a11k2*a6k3 + a5k2*a11k3 - a11k2*a5k3 + a11k1*a5k2*a6k3 - a11k1*a6k2*a5k3 -1 ), ( a5k1*a10k2*a11k3 - a5k1*a11k2*a10k3 - a10k1*a5k2*a11k3 + a10k1*a11k2*a5k3 + a11k1*a5k2*a10k3 - a11k1*a10k2*a5k3 +1 ), ( -a7k2*a11k3 + a11k2*a7k3 - a7k1*a6k2*a11k3 + a7k1*a11k2*a6k3 + a11k1*a6k2*a7k3 - a11k1*a7k2*a6k3 -1 ), ( a7k1*a8k2*a12k3 + a7k1*a12k2 - a8k1*a7k2*a12k3 + a8k1*a12k2*a7k3 - a12k1*a7k2 - a12k1*a8k2*a7k3 -1 ), ( a7k1*a11k2*a12k3 - a7k1*a12k2*a11k3 - a11k1*a7k2*a12k3 + a11k1*a12k2*a7k3 + a12k1*a7k2*a11k3 - a12k1*a11k2*a7k3 +1 ), ( a8k1*a9k2*a12k3 - a8k1*a12k2*a9k3 - a9k1*a8k2*a12k3 - a9k1*a12k2 + a12k1*a8k2*a9k3 + a12k1*a9k2 -1 ), ( a9k1*a10k2*a12k3 - a9k1*a12k2*a10k3 - a10k1*a9k2*a12k3 + a10k1*a12k2*a9k3 + a12k1*a9k2*a10k3 - a12k1*a10k2*a9k3 -1 ), ( a10k1*a11k2*a12k3 - a10k1*a12k2*a11k3 - a11k1*a10k2*a12k3 + a11k1*a12k2*a10k3 + a12k1*a10k2*a11k3 - a12k1*a11k2*a10k3 +1 ) ) #(*wanted Groebner base. *) #(* -EOF- *) jas-2.5/examples/raksanyi_c.py0000644000175000017500000000230111253240426016651 0ustar giovannigiovanni# # jython examples for jas. # $Id: raksanyi_c.py 2811 2009-09-13 18:59:35Z kredel $ # import sys; from jas import Ring from jas import ParamIdeal from jas import startLog from jas import terminate # Raksanyi & Walter example # integral/rational function coefficients #nono: r = Ring( "RatFunc(a1, a2, a3, a4) (x1, x2, x3, x4) L" ); r = Ring( "IntFunc(a1, a2, a3, a4) (x1, x2, x3, x4) G" ); #r = Ring( "IntFunc(a1, a2, a3, a4) (x4, x3, x2, x1) L" ); print "Ring: " + str(r); print; ps = """ ( ( x4 - { a4 - a2 } ), ( x1 + x2 + x3 + x4 - { a1 + a3 + a4 } ), ( x1 x3 + x1 x4 + x2 x3 + x3 x4 - { a1 a4 + a1 a3 + a3 a4 } ), ( x1 x3 x4 - { a1 a3 a4 } ) ) """; f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; #sys.exit(); #startLog(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; #sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); print "2-CGBsystem: " + str(gs); print; gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #sys.exit(); jas-2.5/examples/gcd.rb0000644000175000017500000000206411644030160015240 0ustar giovannigiovanni# # jruby examples for jas. # $Id: gcd.rb 3793 2011-10-08 11:13:52Z kredel $ # require "examples/jas" # polynomial examples: gcd #r = PolyRing.new( ZM(1152921504606846883), "(x,y,z)", PolyRing.lex ); r = PolyRing.new( QQ(), "(x,y,z)", PolyRing.lex ); #r = PolyRing.new( CC(), "(x,y,z)", PolyRing.lex ); #r = PolyRing.new( ZZ(), "(x,y,z)", PolyRing.lex ); puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); a = r.random(); b = r.random(); c = r.random().abs(); #c = 1; #a = 0; puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); puts; ac = a * c; bc = b * c; puts "ac = " + str(ac); puts "bc = " + str(bc); puts; #startLog(); t = System.currentTimeMillis(); d = r.gcd(ac,bc); t = System.currentTimeMillis() - t; #d = d.monic(); puts "d = " + str(d); puts "d = " + str(d.monic()); puts; puts "gcd time = " + str(t) + " milliseconds" ; if r.ring.coFac.isField() m = c % d; #puts "m = " + str(m); puts; if m.isZERO() puts "isGcd(c,d): true" ; else puts "isGcd(c,d): " + str(m); end end puts; #startLog(); terminate(); jas-2.5/examples/word_solvable.rb0000644000175000017500000000402612023444260017347 0ustar giovannigiovanni# # jruby examples for jas. # $Id: word_solvable.rb 4186 2012-09-10 20:08:16Z kredel $ # #load "examples/jas.rb" require "examples/jas" # non-commutative polynomial examples: solvable polynomials example #r = WordPolyRing.new(QQ(),"a,b,e1,e2,e3"); r = WordPolyRing.new(QQ(),"a,b,e,f,g"); puts "WordPolyRing: " + str(r); puts; one,a,b,e,f,g = r.gens(); puts "one = " + str(one); puts "a = " + str(a); puts "b = " + str(b); puts "e = " + str(e); puts "f = " + str(f); puts "g = " + str(g); puts; r1 = g * e - (e*g - e); r2 = g * f - (f*g - f); r3 = e * a - a * e; r4 = e * b - b * e; r5 = f * a - a * f; r6 = f * b - b * f; r7 = g * a - a * g; r8 = g * b - b * g; f1 = e * g**3 + f**10 - a; f2 = e**3 * f**2 + g; f3 = g**3 + g**2 - b; puts "r1 = " + str(r1); puts "r2 = " + str(r2); puts "r3 = " + str(r3); puts "r4 = " + str(r4); puts "r5 = " + str(r5); puts "r6 = " + str(r6); puts "r7 = " + str(r7); puts "r8 = " + str(r8); puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; ff = r.ideal( "", [r1,r2,r3,r4,r5,r6,r7,r8,f1,f2,f3] ); puts "ff = " + str(ff); puts; startLog(); gg = ff.GB(); puts "gg = " + str(gg); puts "isGB(gg) = " + str(gg.isGB()); puts; #exit(0); # now as solvable polynomials p = PolyRing.new(QQ(),"a,b,e1,e2,e3"); #is automatic: [one,a,b,e1,e2,e3] = p.gens(); relations = [e3, e1, e1*e3 - e1, e3, e2, e2*e3 - e2]; puts "relations: = " + relations.join(", ") { |r| r.to_s }; puts; rp = SolvPolyRing.new(QQ(), "a,b,e1,e2,e3", PolyRing.lex, relations); puts "SolvPolyRing: " + str(rp); puts; puts "gens =" + rp.gens().join(", ") { |r| r.to_s }; one,a,b,e1,e2,e3 = rp.gens(); #one,I,J,K,a,b,e1,e2,e3 = rp.gens(); f1 = e1 * e3**3 + e2**10 - a; f2 = e1**3 * e2**2 + e3; f3 = e3**3 + e3**2 - b; F = [ f1, f2, f3 ]; puts "F = " + F.join(", ") { |r| r.to_s }; puts I = rp.ideal( "", F ); puts "SolvableIdeal: " + str(I); puts; rgt = I.twosidedGB(); puts "seq twosided GB:" + str(rgt); puts "isTwosidedGB: " + str(rgt.isTwosidedGB()); puts puts "rgt: " + rgt.list.join(", ") { |r| r.to_s }; puts; jas-2.5/examples/mkplot.py0000644000175000017500000003453412043011100016030 0ustar giovannigiovanni# # read output of jas GB runs and prepare input for gnuplot # $Id: mkplot.py 4274 2012-10-27 16:56:32Z kredel $ # from sys import argv from sys import exit from time import strftime import re; import os from os import system hpat = re.compile(r'(m|d) = (\d+), ppn = (\d+), time = (\d+) milliseconds, (\d+) start-up'); dpat = re.compile(r'(m|d) = (\d+), time = (\d+) milliseconds, (\d+) start-up'); #hpat = re.compile(r'd = (\d+), ppn = (\d+), time = (\d+) milliseconds, (\d+) start-up'); #dpat = re.compile(r'd = (\d+), time = (\d+) milliseconds, (\d+) start-up'); ppat = re.compile(r'time = (\d+) milliseconds'); fpat = re.compile(r'p = (\d+), time = (\d+) milliseconds'); spat = re.compile(r'seq,'); ####fpat = re.compile(r'_p(\d+)\.'); ####spat = re.compile(r'_s\.'); #r0pat = re.compile(r'Pairlist\(#put=(\d+), #rem=(\d+), size=(\d+)\)'); rpat = re.compile(r'Pairlist\(#put=(\d+), #rem=(\d+)\)'); ####r1pat = re.compile(r'pairlist #put = (\d+) #rem = (\d+)'); res = {}; pairs = None; hybrid = False; dist = False; para = False; for fname in argv[1:]: dn = -1; print "file =", fname f = open(fname,"r"); for line in f: pm = rpat.search(line); # pairlist results if pm: print "pair: ", line, np = pm.group(1); nr = pm.group(2); if pairs == None: pairs = ( np, nr ); #print "put = " + np + ", rem = " + nr; continue; ## pm = r0pat.search(line); # pairlist results ## if pm: ## print "pair0: ", line, ## np = pm.group(1); ## nr = pm.group(2); ## if pairs != None: ## pairs = ( np, nr ); ## #print "put = " + np + ", rem = " + nr; ## continue; ma = hpat.search(line); # distributed hybrid results if ma: print "h: ", line, d_h = ma.group(1) print "d_h: ", d_h, dn = int( ma.group(2) ); pp = int( ma.group(3) ); tm = long( ma.group(4) ); su = long( ma.group(5) ); hybrid = True; if not dn in res: res[ dn ] = {}; if pp in res[ dn ]: if 't' in res[ dn ][ pp ]: tx = res[ dn ][ pp ][ 't' ]; if tx < tm: # minimum or maximum tm = tx; su = res[ dn ][ pp ][ 's' ] if 'p' in res[ dn ][ pp ] or 'r' in res[ dn ][ pp ]: pairs = ( res[ dn ][ pp ]['p'], res[ dn ][ pp ]['r'] ); res[ dn ][ pp ] = { 't': tm, 's': su }; if pairs != None: res[ dn ][ pp ]['p'] = pairs[0]; res[ dn ][ pp ]['r'] = pairs[1]; pairs = None; continue; ma = dpat.search(line); # distributed results if ma: print "d: ", line, d_h = ma.group(1) print "d_h: ", d_h, dn = int( ma.group(2) ); pp = 1; tm = long( ma.group(3) ); su = long( ma.group(4) ); dist = True; if not dn in res: res[ dn ] = {}; if pp in res[ dn ]: if 't' in res[ dn ][ pp ]: tx = res[ dn ][ pp ][ 't' ]; if tx < tm: # minimum or maximum tm = tx; su = res[ dn ][ pp ][ 's' ] if 'p' in res[ dn ][ pp ] or 'r' in res[ dn ][ pp ]: pairs = ( res[ dn ][ pp ]['p'], res[ dn ][ pp ]['r'] ); res[ dn ][ pp ] = { 't': tm, 's': su }; if pairs != None: res[ dn ][ pp ]['p'] = pairs[0]; res[ dn ][ pp ]['r'] = pairs[1]; pairs = None; continue; ma = ppat.search(line); # parallel and sequential results if ma: print "p: ", line, tm = long( ma.group(1) ); fm = fpat.search(line); if fm: #print fname dn = 1; pp = int( fm.group(1) ); para = True; else: sm = spat.search(line); if sm: dn = 1; pp = 0; else: print "invalid: ", line, dn = -1; pp = -1; if not dn in res: res[ dn ] = {}; if pp in res[ dn ]: if 't' in res[ dn ][ pp ]: tx = res[ dn ][ pp ][ 't' ]; if tx < tm: # minimum or maximum tm = tx; if 'p' in res[ dn ][ pp ] or 'r' in res[ dn ][ pp ]: pairs = ( res[ dn ][ pp ]['p'], res[ dn ][ pp ]['r'] ); res[ dn ][ pp ] = { 't': tm, 's': '0' }; if pairs != None: res[ dn ][ pp ]['p'] = pairs[0]; res[ dn ][ pp ]['r'] = pairs[1]; pairs = None; print "\nres = ", res; ks = res.keys(); #print "ks = ", ks; ks.sort(); print "ks = ", ks; kpp = []; for d in ks: kdd = res[d].keys(); for dd in kdd: if dd not in kpp: kpp.append(dd); kpp.sort(); print "kpp = ", kpp; for d in ks: rd = res[d].keys(); rd.sort(); for p in rd: print " " + str(d) + "," + str(p) + " & " + str(res[d][p]['t']) + " & " + str(res[d][p]['s']) s1 = ks[0]; if s1 == 0: rxx = res.keys(); rxr = rxx[1]; rk = res[rxr].keys(); rk.sort(); p1 = rk[0]; st = int( res[ rxr ][ p1 ]['t'] ); else: rk = res[s1].keys(); rk.sort(); p1 = rk[0]; st = int( res[ s1 ][ p1 ]['t'] ); print "s1 = ", s1; print "p1 = ", p1; print "st = ", st; speed = {}; for k in ks: speed[k] = {}; rk = res[k].keys(); rk.sort(); for p in rk: speed[k][p] = st / float(res[k][p]['t']); print "speed = ", speed; bname = "kat_"; tag = argv[1]; bname = tag; i = tag.find("/"); if i >= 0: bname = tag[:i]; i = bname.find(".out"); if i >= 0: bname = tag[:i]; print "bname = " + bname; # LaTex output: summary = "\n% run = " + tag + "\n"; summary += r"\begin{tabular}{|r|r|r|r|r|r|}" + "\n"; summary += r"\hline" + "\n"; summary += " nodes & ppn & time & speedup & put & rem \n"; summary += r"\\ \hline" + "\n"; for d in ks: rd = res[d].keys(); rd.sort(); for p in rd: #if res[d][p]['s'] != "0": # summary += " " + str(d) + " & " + str(p) + " & " + str(res[d][p]['t']) + " & " + str(res[d][p]['s']) + " & " + str(speed[d][p])[:4]; #else: # summary += " " + str(d) + " & " + str(p) + " & " + str(res[d][p]['t']) + " & " + " & " + str(speed[d][p])[:4]; summary += " " + str(d) + " & " + str(p) + " & " + str(res[d][p]['t']) + " & " + str(speed[d][p])[:4]; if 'p' in res[d][p] and 'r' in res[d][p]: summary += " & " + str(res[d][p]['p']) + " & " + str(res[d][p]['r']) + "\n" else: summary += " & " + " & " + "\n" summary += r"\\ \hline" + "\n"; summary += r"\end{tabular}" + "\n"; print summary; tname = bname+".tex"; tt=open(tname,"w"); tt.write(summary); tt.close(); # output for 2-d gnuplot: oname = bname+".po"; o=open(oname,"w"); ploting = "\n#nodes #ppn time speedup ideal\n"; for k in ks: rk = res[k].keys(); rk.sort(); for p in rk: ideals = k*p; if ideals == 0: ideals = 1; ploting += str(k) + " " + str(p) + " " + str(res[k][p]['t']) + " " + str(speed[k][p]) + " " + str(ideals) + "\n"; ploting += "\n"; print ploting; o.write(ploting); o.close(); # output for 1-d gnuplot, colums for nodes: oname = bname+"_p.po"; o=open(oname,"w"); ploting = "\n#ppn time p, time d1, time d2, ... \n"; for p in kpp: ploting += str(p); for k in ks: #print "p = " + str(p) + ", k = " + str(k) if res[k]: if p in res[k]: #ploting += " " + str(float(res[k][p]['t'])/1000.0); ploting += " " + str(speed[k][p]); else: ploting += " -"; ploting += "\n"; #ploting += "\n"; print ploting; o.write(ploting); o.close(); # output for 1-d gnuplot, colums for ppn: oname = bname+"_d.po"; o=open(oname,"w"); ploting = "\n#nodes time ppn1, time ppn2, time ppn3, ... \n"; for k in ks: ploting += str(k); for p in kpp: #print "p = " + str(p) + ", k = " + str(k) if res[k]: if p in res[k]: #ploting += " " + str(float(res[k][p]['t'])/1000.0); ploting += " " + str(speed[k][p]); else: ploting += " -"; ploting += "\n"; #ploting += "\n"; print ploting; o.write(ploting); o.close(); #exit(); #--------------------------------------- pscript_2d = """ set grid set terminal x11 set title "Groebner bases on a grid cluster, distributed hybrid version" set time set xlabel "number of nodes" set ylabel "threads per node" set xrange [0:7] set yrange [0:7] #reverse #set clip two set xtics 1.0 set ytics 1.0 set style data lines #set contour base #set surface #set pm3d set dgrid3d set hidden3d set multiplot set size 0.95,0.95 #set size 0.95,0.5 #set origin 0,0.5 set origin 0,0 set datafile missing "-" ##set zlabel "milliseconds" set zlabel "seconds" splot "%s.po" using 1:2:($3/1000) title '%s computing time', "%s.po" using 1:2:( (%s/1000)/($1*$2) ) every ::2 title '%s ideal' #set size 0.95,0.45 #set origin 0,0 #set zlabel "speedup" #splot "%s.po" using 1:2:4 title '%s speedup', "%s.po" using 1:2:(($1*$2)) title '%s ideal' ## every ::2 start from the second line ## smooth acsplines ##with linespoints ##with linespoints ## smooth bezier unset multiplot pause mouse set terminal postscript set output "%s.ps" replot """ #--------------------------------------- #--------------------------------------- pscript_1d = """ set grid set terminal x11 set title "Groebner bases on a grid cluster, distributed version" set time set xlabel "number of nodes" #set xrange [0:8] set xtics 1.0 set style data lines set multiplot set size 0.95,0.5 set origin 0,0.5 #set origin 0,0 ##set ylabel "milliseconds" set ylabel "seconds" # smooth acsplines plot "%s.po" using 1:($3/1000) title '%s computing time', "%s.po" using 1:( (%s/1000)/($5) ) title '%s ideal' #set size 0.95,0.45 set origin 0,0 set ylabel "speedup" # smooth bezier plot "%s.po" using 1:4 title '%s speedup', "%s.po" using 1:(($5)) title '%s ideal' #with linespoints #with linespoints unset multiplot pause mouse set terminal postscript set output "%s.ps" replot """ #--------------------------------------- #--------------------------------------- pscript_1p = """ set grid set terminal x11 set title "Groebner bases on a multi-core computer" set time set xlabel "number of threads" #set xrange [0:8] set xtics 1.0 set style data lines set multiplot set size 0.95,0.5 set origin 0,0.5 #set origin 0,0 ##set ylabel "milliseconds" set ylabel "seconds" # smooth acsplines plot "%s.po" using 2:($3/1000) title '%s computing time', "%s.po" using 2:( (%s/1000)/($5) ) title '%s ideal' #set size 0.95,0.45 set origin 0,0 set ylabel "speedup" # smooth bezier plot "%s.po" using 2:4 title '%s speedup', "%s.po" using 2:(($5)) title '%s ideal' #with linespoints #with linespoints unset multiplot pause mouse set terminal postscript set output "%s.ps" replot """ #--------------------------------------- #--------------------------------------- pscript_d = """ set grid set terminal x11 set title "Groebner bases on a grid cluster, distributed hybrid version" set time set xlabel "number of threads" #set xrange [0:8] set xtics 1.0 set style data lines #set multiplot #set size 0.95,0.5 #set origin 0,0.5 set origin 0,0 ##set ylabel "milliseconds" #set ylabel "seconds" set ylabel "speedup" # smooth acsplines plot "%s.po" using 1:2 title '%s, parallel, n = 1',\ "%s.po" using 1:3 title 'distributed, n = 2',\ "%s.po" using 1:4 title 'distributed, n = 3',\ "%s.po" using 1:5 title 'distributed, n = 4',\ "%s.po" using 1:6 title 'distributed, n = 5',\ "%s.po" using 1:7 title 'distributed, n = 6',\ "%s.po" using 1:8 title 'distributed, n = 7' #with linespoints #unset multiplot pause mouse set terminal postscript set output "%s.ps" replot """ #--------------------------------------- #--------------------------------------- pscript_dp = """ set grid set terminal x11 set title "Groebner bases on a grid cluster, distributed hybrid version" set time set xlabel "number of nodes" #set xrange [0:8] set xtics 1.0 set style data lines #set multiplot #set size 0.95,0.5 #set origin 0,0.5 set origin 0,0 ##set ylabel "milliseconds" #set ylabel "seconds" set ylabel "speedup" # smooth acsplines # 1:2 ignored plot "%s.po" using 1:3 title '%s, ppn = 1',\ "%s.po" using 1:4 title 'ppn = 2',\ "%s.po" using 1:5 title 'ppn = 3',\ "%s.po" using 1:6 title 'ppn = 4',\ "%s.po" using 1:7 title 'ppn = 5',\ "%s.po" using 1:8 title 'ppn = 6',\ "%s.po" using 1:9 title 'ppn = 7',\ "%s.po" using 1:10 title 'ppn = 8' #with linespoints #unset multiplot pause mouse set terminal postscript set output "%s.ps" replot """ #--------------------------------------- exam = bname; psname = bname + ".ps"; pname = "plotin.gp" p=open(pname,"w"); print p; sqt = st; print "seq time = ", sqt; #print "args: %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s. " % ("x11",bname,exam,bname,str(sqt),exam,bname,exam,bname,exam,bname); hyb2d = False; #hyb2d = True t2n = True; # thread to nodes #t2n = False if hybrid: if hyb2d: pscript = pscript_2d % (bname,exam,bname,str(sqt),exam,bname,exam,bname,exam,bname); else: if t2n: oname = bname+"_p"; pscript = pscript_d % (oname,exam,oname,oname,oname,oname,oname,oname,bname); else: oname = bname+"_d"; pscript = pscript_dp % (oname,exam,oname,oname,oname,oname,oname,oname,oname,bname); else: if dist: pscript = pscript_1d % (bname,exam,bname,bname,str(sqt),exam,bname,exam,bname,exam); else: if para: pscript = pscript_1p % (bname,exam,bname,bname,str(sqt),exam,bname,exam,bname,exam); p.write(pscript); p.close(); cmd = "gnuplot " + pname; print "cmd: " + cmd; os.system(cmd); # convert to pdf, better use pstopdf, embed all fonts #cmd = "ps2pdf " + psname; cmd = "epstopdf --autorotate=All --embed " + psname; print "cmd: " + cmd; os.system(cmd); jas-2.5/examples/montes_ex113.py0000644000175000017500000000242211253240426016760 0ustar giovannigiovanni# # jython examples for jas. # $Id: montes_ex113.py 2811 2009-09-13 18:59:35Z kredel $ # import sys; from jas import PolyRing, QQ, RF from jas import Ideal from jas import startLog from jas import terminate # Montes JSC 2002, 33, 183-208, example 11.3 # integral function coefficients R = PolyRing( PolyRing(QQ(),"r, l, z",PolyRing.lex), "c1, c2, s1, s2", PolyRing.lex ); print "Ring: " + str(R); print; [one,r,l,z,c1,c2,s1,s2] = R.gens(); print "gens: ", [ str(f) for f in r.gens() ]; print; f1 = r - c1 + l * ( s1 * s2 - c1 * c2 ); f2 = z - s1 - l * ( s1 * c2 + s2 * c1 ); f3 = s1**2 + c1**2 - 1; f4 = s2**2 + c2**2 - 1; F = [f1,f2,f3,f4]; print "F: ", [ str(f) for f in F ]; print; startLog(); If = R.paramideal( "", list = F ); print "ParamIdeal: " + str(If); print; ## G = If.GB(); ## print "GB: " + str(G); ## print; ## sys.exit(); GS = If.CGBsystem(); #GS = If.CGBsystem(); #GS = If.CGBsystem(); print "CGBsystem: " + str(GS); print; bg = GS.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #terminate(); #sys.exit(); CG = If.CGB(); print "CGB: " + str(CG); print; bg = CG.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/legendre.rb0000644000175000017500000000107411644356076016311 0ustar giovannigiovanni# # jruby examples for jas. # $Id: legendre.rb 3794 2011-10-09 17:39:11Z kredel $ require "examples/jas" # Legendre polynomial example # P(0) = 1 # P(1) = x # P(n) = 1/n [ (2n-1) * x * P(n-1) - (n-1) * P(n-2) ] r = Ring.new( "Q(x) L" ); #r = Ring.new( "C(x) L" ); puts "Ring: " + str(r); puts; # sage like: with generators for the polynomial ring one,x = r.gens(); N = 10; P = [one,x]; for n in 2...N do p = (2*n-1) * x * P[n-1] - (n-1) * P[n-2]; p = 1/n * p; P << p; #.monic(); end for n in 0...N do puts "P[#{n}] = #{P[n]}"; end puts; #sys.exit(); jas-2.5/examples/rose_fac.py0000644000175000017500000017645611653236772016353 0ustar giovannigiovanni# # jython examples for jas. # $Id: rose_fac.py 3820 2011-10-30 12:07:22Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # output gb of rose #r = Ring( "Mod 19 (U3,U4,A46) L" ); #r = Ring( "Mod 1152921504606846883 (U3,U4,A46) L" ); # 2^60-93 #r = Ring( "Quat(U3,U4,A46) L" ); #r = Ring( "Z(U3,U4,A46) L" ); #r = Ring( "C(U3,U4,A46) L" ); #r = Ring( "Rat(A46,U3,U4) G" ); rz = Ring( "Int(A46) G" ); print "Ring: " + str(rz); print; r = Ring( "Rat(A46) G" ); print "Ring: " + str(r); print; ps = """ ( ( A46^34 + 347/70 A46^33 - 56411/58800 A46^32 - 441350327/6174000 A46^31 - 992593010489/3457440000 A46^30 - 217625706587/329280000 A46^29 - 373467217691021/355622400000 A46^28 - 38574512982739/31752000000 A46^27 - 968821009058023/952560000000 A46^26 - 5992612680961049/10886400000000 A46^25 - 13843426727931961/244944000000000 A46^24 + 1486519769228381881/5598720000000000 A46^23 + 61199280870444808261/167961600000000000 A46^22 + 513991046707657214269/1679616000000000000 A46^21 + 37908065080289396962277/201553920000000000000 A46^20 + 27223946509678338655459/335923200000000000000 A46^19 + 668594689016343141054373/48372940800000000000000 A46^18 - 36250135997129945800663817/2418647040000000000000000 A46^17 - 5712667240922865693346483691/290237644800000000000000000 A46^16 - 42053436689365696671983799179/2902376448000000000000000000 A46^15 - 561895388992743685886859196463/69657034752000000000000000000 A46^14 - 704377755966878925481768484749/193491763200000000000000000000 A46^13 - 2531676547158421516985730163481/1857520926720000000000000000000 A46^12 - 4750291847118917831874464404117/11145125560320000000000000000000 A46^11 - 1835783859800409552862056700927/16511297126400000000000000000000 A46^10 - 9916637291915563585725849353/412782428160000000000000000000 A46^9 - 252376016954713294866494065459/59440669655040000000000000000000 A46^8 - 178806028363626133639831815853/297203348275200000000000000000000 A46^7 - 31482408916666847417595615109/475525357240320000000000000000000 A46^6 - 3818476405879526813756500117/713288035860480000000000000000000 A46^5 - 896701239882765996997050397/3170169048268800000000000000000000 A46^4 - 4844358439974218651958787/760840571584512000000000000000000 A46^3 + 171452325388464998728627/730406948721131520000000000000000 A46^2 + 15230552381256429497/811563276356812800000000000000 A46 + 79792266297612001/259700248434180096000000000000 ) ) """; ps1=""" ( ( A46^33 * U3 + 129/28 A46^32 * U3 - 75613/29400 A46^31 * U3 - 871585543/12348000 A46^30 * U3 - 12095701697/46099200 A46^29 * U3 - 124924301563/219520000 A46^28 * U3 - 378293923381/444528000 A46^27 * U3 - 1617620272123/1764000000 A46^26 * U3 - 82886347203347/119070000000 A46^25 * U3 - 668049914090789/2177280000000 A46^24 * U3 + 99688309115142847/1959552000000000 A46^23 * U3 + 231138576685539839/933120000000000 A46^22 * U3 + 11659387634813949601/41990400000000000 A46^21 * U3 + 70151923964052383971/335923200000000000 A46^20 * U3 + 23176161047838396328367/201553920000000000000 A46^19 * U3 + 164454230781271289566939/4031078400000000000000 A46^18 * U3 - 55282700662490687816927/120932352000000000000000 A46^17 * U3 - 747149106093593978873861/50388480000000000000000 A46^16 * U3 - 841282928607636046387355983/58047528960000000000000000 A46^15 * U3 - 54661970877464131720410138953/5804752896000000000000000000 A46^14 * U3 - 830787778268485831652841532151/174142586880000000000000000000 A46^13 * U3 - 274531406380976793484077680017/139314069504000000000000000000 A46^12 * U3 - 750317990428317888436020594041/1114512556032000000000000000000 A46^11 * U3 - 1416119253746536814898928216649/7430083706880000000000000000000 A46^10 * U3 - 33046099809889641357330063959/743008370688000000000000000000 A46^9 * U3 - 25135248767946559916964025799/2972033482752000000000000000000 A46^8 * U3 - 38214637789543687723872942433/29720334827520000000000000000000 A46^7 * U3 - 3604383688017858128502121387/23776267862016000000000000000000 A46^6 * U3 - 10419538500903067530134609/792542262067200000000000000000 A46^5 * U3 - 268160889047530270882049141/356644017930240000000000000000000 A46^4 * U3 - 4494450124912371106208621/228252171475353600000000000000000 A46^3 * U3 + 19160001876330286653661/36520347436056576000000000000000 A46^2 * U3 + 4148034694905888017/81156327635681280000000000000 A46 * U3 + 11398895185373143/12985012421709004800000000000 U3 ) ) """; ps2=""" ( ( A46^32 * U3^2 + 149/35 A46^31 * U3^2 - 119419/29400 A46^30 * U3^2 - 17080619/246960 A46^29 * U3^2 - 32939303767/138297600 A46^28 * U3^2 - 29988193601/61740000 A46^27 * U3^2 - 3784045943831/5556600000 A46^26 * U3^2 - 2693634126319/3969000000 A46^25 * U3^2 - 21841275550799/47628000000 A46^24 * U3^2 - 21239300351867/145152000000 A46^23 * U3^2 + 100022001638857211/979776000000000 A46^22 * U3^2 + 296696864208881153/1399680000000000 A46^21 * U3^2 + 17088141121241394989/83980800000000000 A46^20 * U3^2 + 19261885997631012911/139968000000000000 A46^19 * U3^2 + 13468170505032365821223/201553920000000000000 A46^18 * U3^2 + 35088518623022364409189/2015539200000000000000 A46^17 * U3^2 - 99017698968245042551237/15116544000000000000000 A46^16 * U3^2 - 3789770743783848575384507/302330880000000000000000 A46^15 * U3^2 - 2933051673126807110607585563/290237644800000000000000000 A46^14 * U3^2 - 948072476821568942948806667/161243136000000000000000000 A46^13 * U3^2 - 18896655281197310848727704481/6965703475200000000000000000 A46^12 * U3^2 - 2845096388251912350859674973/2786281390080000000000000000 A46^11 * U3^2 - 39111610674783351035074010869/123834728448000000000000000000 A46^10 * U3^2 - 1486938573940216107905934971/18575209267200000000000000000 A46^9 * U3^2 - 2445791954945323169329394873/148601674137600000000000000000 A46^8 * U3^2 - 333946045138720738819094237/123834728448000000000000000000 A46^7 * U3^2 - 406526799915645826522761061/1188813393100800000000000000000 A46^6 * U3^2 - 6322467405069477857023283/198135565516800000000000000000 A46^5 * U3^2 - 490026291814312040719379/247669456896000000000000000000 A46^4 * U3^2 - 169501103784936018875857/2853152143441920000000000000000 A46^3 * U3^2 + 2012646248526699378523/1826017371802828800000000000000 A46^2 * U3^2 + 5217570099427357/37572373905408000000000000 A46 * U3^2 + 1628413597910449/649250621085450240000000000 U3^2 ) ) """; ps3=""" ( ( U3^4 + 36097228800000000000000000/282475249 A46^33 + 1161224847360000000000000000/1977326743 A46^32 - 4677045387264000000000000000/13841287201 A46^31 - 874485621920563200000000000000/96889010407 A46^30 - 22660530808584929280000000000000/678223072849 A46^29 - 48947976962992465920000000000000/678223072849 A46^28 - 212357741794443264000000000000/1977326743 A46^27 - 33417694635162617446400000000000/290667031221 A46^26 - 1195585718651671592960000000000/13841287201 A46^25 - 4622243456144475926528000000000/124571584809 A46^24 + 57492745364488210585600000000/7626831723 A46^23 + 5064235904207031314222080000000/160163466183 A46^22 + 796549541441999106994688000000/22880495169 A46^21 + 1776805509375610240638745600000/68641485507 A46^20 + 6571948331935947500408320000/466948881 A46^19 + 15900562307775474505007648000/3268642167 A46^18 - 781823011269699906939632000/4202539929 A46^17 - 23911885581267405621130949120/12607619787 A46^16 - 66484142665897834547281936/36756909 A46^15 - 31344755225898717841650588049/27016328115 A46^14 - 748245898727397783769699627/1286491815 A46^13 - 61180345995024957255947775667/257298363000 A46^12 - 1772332138625205728147155697/22054145400 A46^11 - 1763442424064055410851226129/78414739200 A46^10 - 72564573592100205725791837/14002632000 A46^9 - 65329613048147169962793719/67212633600 A46^8 - 87361765982805204782291/600112800 A46^7 - 6483564254536224014425081/384072192000 A46^6 - 23648026104539505065429/16460236800 A46^5 - 880685511246977438581/10973491200 A46^4 - 31439956654789887473/15676416000 A46^3 + 17918243525346457327/300987187200 A46^2 + 10074090036167/1866240 A46 + 34829612499283/382205952 ) ) """; ps4=""" ( ( A46 * U4 + 7/20 U4 + 2806378846741861368786614566878031251136601782233486293371124444033709909300049715978016727056150885946954243402645730462178807446021415693833183139081658586984935909957265108287928306576671117507805428087796888020739324547730219269915178825763993883433817341952000000000000000/193099928700513998070936429904026968056396066087989232333196930214044975387024916636846108968424103894255784064885243976305160746405290836679402752295622754790839675018341679885489238996414850488675112243144046216420956878738117538991288033099828416943500600350187 A46^32 * U3 + 140608368210259054916983904673796347993009087108223449480869140637168687474157820242084293427769280716150829987371903694486407125016157557573489507333502558345102130864385866957396552184077632209367448052303724048297487583320428452817989972383673573195382911926272000000000000000/1351699500903597986496555009328188776394772462615924626332378511498314827709174416457922762778968727259790488454196707834136125224837035856755819266069359283535877725128391759198424672974903953420725785702008323514946698151166822772939016231698798918604504202451309 A46^31 * U3 + 2973132530031750926781836728171190368295908349443863657109054185698567452354483691980282671132312007156981877065422976124734148815655910511834380182331303177950358622308259910423832682100194502857004946063777788209711503282994815361158167402207667989232295462169477120000000000000/28385689518975557716427655195891964304290221714934417152979948741464611381892662745616378018358343272455600257538130864516858629721577752991872204587456544954253432227696226943166918132472983021835241499742174793813880661174503278231719340865674777290694588251477489 A46^30 * U3 - 738219222373037292445012084441369194910728746958545194778441077198902948054263364937417682200010729210575746685991736931724571115099030702915394756575817790642985569814303481715585979651308619587706574566955474220298898070223241914619143731590342509740953174566721552384000000000000/596099479898486712044980759113731250390094656013622760212578923570756839019745917657943938385525208721567605408300748154854031224153132812829316296336587444039322076781620765806505280781932643458540071494585670670091493884664568842866106158179170323104586353281027269 A46^29 * U3 - 26263613198277033357242907881790564317638488547844618743001644843010275951255995601618105986940603997061861718415452159942810394664057894925733725044191873926510994765442061292542368154720543459005227757920995136654748098710382908816433885918895473973271287136201940664320000000000000/4172696359289406984314865313796118752730662592095359321488052464995297873138221423605607568698676461050973237858105237083978218569071929689805214074356112108275254537471345360645536965473528504209780500462099694690640457192651981900062743107254192261732104472967190883 A46^28 * U3 - 9560261987467874294850640971728702760731659080417859619462176031496681069887590878558384729317157715276514804678872739436230630658282680026803340746414284932116802254277874675348065517256502425989246849745315895036906790401640417642341755791726718494097465403286844184985600000000000/596099479898486712044980759113731250390094656013622760212578923570756839019745917657943938385525208721567605408300748154854031224153132812829316296336587444039322076781620765806505280781932643458540071494585670670091493884664568842866106158179170323104586353281027269 A46^27 * U3 - 144636713736027890114035034090555770840107473490985685648308419164337400894146263765715981457017308677715082713471432001864714782421560684446718632104959754377888118909536279270581334669935787514862899283922492256748522286708189406470339423887947462918232309558821679529984000000000000/5364895319086380408404826832023581253510851904122604841913210312136811551177713258921495445469726878494108448674706733393686281017378195315463846667029286996353898691034586892258547527037393791126860643451271036030823444961981119585794955423612532907941277179529245421 A46^26 * U3 - 24532425560872733727048401118804283865911311477564921900335177229012489937286467620463606284515609505035616190873825110294676684892007020876691541110492442185186251334711679953191506232457944676021905960044901546391272864711217070545467913465760834235337077332640608895369216000000000/766413617012340058343546690289083036215835986303229263130458616019544507311101894131642206495675268356301206953529533341955183002482599330780549523861326713764842670147798127465506789576770541589551520493038719432974777851711588512256422203373218986848753882789892203 A46^25 * U3 - 61280378855985472962083715267099870468639547774190782208008687497788816915947177474302623147240238616774447758611668598585355022788830824893247197811650042416494226679277235085459349523493402070913785423068849805945203419134911827923486496461119063853055966658119121257129574400000000/2299240851037020175030640070867249108647507958909687789391375848058633521933305682394926619487025805068903620860588600025865549007447797992341648571583980141294528010443394382396520368730311624768654561479116158298924333555134765536769266610119656960546261648369676609 A46^24 * U3 - 1484357436021657507567420650984058019197004585757942514498995263423808522091214018761612749478663033895612373062807866818414484967623858841053321992327465827514651989711202442802087572810894125998644840666538477463088224296505304638389800637458850650417392471695314042172211200000000/109487659573191436906220955755583290887976569471889894732922659431363501044443127733091743785096466908043029564789933334565026143211799904397221360551618101966406095735399732495072398510967220227078788641862674204710682550244512644608060314767602712406964840398556029 A46^23 * U3 - 142706740914560864457369678713491100078718980040431434176679594896408407693192038718320939423503224607224793619606860312440116490102586591426353170601317496666073657735251911434293391435267804199376695206269942247915428218586358462081096742118453704497075161839492889751191552000000/2956166808476168796467965805400748853975367375741027157788911804646814528199964448793477082197604606517161798249328200033255705866718597418724976734893688753092964584855792777366954759796114946131127293330292203527188428856601841404417628498725273234988050690761012783 A46^22 * U3 + 3437067913738929851828191102489541091985420513352095924549529468703404236611368673420787140580385095687914414418203044807769960408456154049568142240000401501441029724428786621410870408162134547736165823446770365996810358019535793543622855984068400287198402234509017467116735692800000/422309544068024113781137972200106979139338196534432451112701686378116361171423492684782440313943515216737399749904028576179386552388371059817853819270526964727566369265113253909564965685159278018732470475756029075312632693800263057773946928389324747855435812965858969 A46^21 * U3 + 12665325755293011964582773351828201837497408957482566179025807264260205331500166852839160281570134088487784028319208757397082649585467393387792231298887791806004696105674306391612545456300491907001838309111269128096161395643695348999989978496685257886403350330750962195611697479680000/1266928632204072341343413916600320937418014589603297353338105059134349083514270478054347320941830545650212199249712085728538159657165113179453561457811580894182699107795339761728694897055477834056197411427268087225937898081400789173321840785167974243566307438897576907 A46^20 * U3 + 472460708046707276929317308260575825818443603966144032149144933738614980186931958850077619729999743406167265787440681567111099352622569281813602576458470534069879413676204407012264193237661238006825286040265059435939142815940360874733243831244058419301704863623227097616300687360000/60329934866860587683019710314300997019905456647776064444671669482588051595917641812111777187706216459533914249986289796597055221769767294259693402752932423532509481323587607701366423669308468288390352925108004153616090384828609008253420989769903535407919401852265567 A46^19 * U3 + 49390047765871082949860891586805882007616506646541386751626133624251152479425727198070508507708042448289532261339277046519001543624931425618731092311111454034423497441761556818193037978230663070411942523132669576228611039810197751659696742852563815776238111135652689883724583731200/11081008444933577329534232506708346391411206323060909795960102558026376823739975026714408054884815268077657719385236901415785652978120523435453890301559016567195619018618132026781588020893392134602309720938204844541730887009336348454709977712839424870842339115722247 A46^18 * U3 + 129068221133437408101386032010227938242790415417408002956440388834868112181036866325987181792617952620211570225145421401636968642407417865428308813969801472080155460044151903911373059980563777215433387329713871436510348502082703071326443785803142144287247590693723735936473435504640/77567059114535041306739627546958424739878444261426368571720717906184637766179825187000856384193706876543604035696658309910499570846843664048177232110913115970369333130326924187471116146253744942216168046567433911792116209065354439182969843989875974095896373810055729 A46^17 * U3 + 12783978249076530856412299581616499812448814070864143616141639515320829793115590125926560504059268257844159130491162326200688965203538567110804552270764562224831755709762903109729453955480299083281536877866482795304181415809809747877796974966623540360991948948407257749615539560448/232701177343605123920218882640875274219635332784279105715162153718553913298539475561002569152581120629630812107089974929731498712540530992144531696332739347911107999390980772562413348438761234826648504139702301735376348627196063317548909531969627922287689121430167187 A46^16 * U3 - 1810442970097170462121122653290427291604967782620000014180906504389275928944428879269826615110693111930022066722356506712480414023024345146923757896554522544082287653722476697782328057603177530844114988866728376051365543251948667665657844199641256470495166203610372754104633985024/3392145442326605304959458930625003997370777445834972386518398742252972497063257661239104506597392429003364607975072520841567036625955262276159354173946637724651720107740244497994363679865324122837441751307613727920938026635511127077972442156991660674747654831343545 A46^15 * U3 - 270639555533122280020486247514756020301825934358369840608010596756492667631965814059407427090369596575058017999403434671889521831726503036761805006306129032875224481365310003762906407037966481686173976406974516397321267076580148872307324693442737067092534607150395172934720327272832/498645380022010979829040462801875587613504284537740940818204615111186957068298876202148362469816687063494597372335660563710354384015423554595425063570155745523802855837815941205171460940202646057103937442219218004377889915420135680461948997077774119187905260207501115 A46^14 * U3 - 1435948341205771592618056822768583583847960643508655403782679773815551216480844799951609196462939014609390424305428592870359320910647059517420727369800472093539593358295705161364370776721823709904982580674821197915654942789644804770077615722633391761110116425814824933514747954464/4038268383722149172570784441220242854012830292660681412521903264586872020313401977665600603092133844051624533303657762906627424554708645566856374016603140148394904890166957735707575809363481098616002084890016342763021460280370389378538621615466262708032922418266125 A46^13 * U3 - 24031158593232439577778424195027450454772002899626269270999618447601656149784654839122276071971243436018537991067130120319932291937910513510530154436517553834823319688270120213094719167314095473720221761127649325967639043315665428464820334187025317629951306324495868404822629086296/134236911348351843098270045621466866730124986864072399717750703996191750825995749157075115524896810946741187375897970359936383987082400454395753337285576744128805506776152891566359869240901645564547003977625417625011994772636432792658457195911102149817275285411208125 A46^12 * U3 - 55342608527391903114377714171300343766958416997314322747423256743530874483390328684036373961531616542340488099823707750319655515404839491476271584066825595064560837447788507941963050626463472192927052092190464771899480038023820496414639119032434176994304931597908860375406025786078/763232724523486193615878259390625899408424925312868786966639717006918811839232973778798513984413296525757036794391317189352583240839934012135854689137993488046637024241555012048731827969697927638424394044213088782211055992990003592543799485323123651818222337052297625 A46^11 * U3 - 2029624852259950049380302093920186872530375028355631473518046159913882812276759452807058944803805569580457303136641881139738479285051882346521262597896200616610534853804143612625821026733823701571937719332556063675018717208715246680768950536936393557501213975920703061913308587814/84803636058165132623986473265625099934269436145874309662959968556324312426581441530977612664934810725084115199376813021039175915648881556903983854348665943116293002693506112449859091996633103070936043782690343198023450665887778176949311053924791516868691370783588625 A46^10 * U3 - 1168942911153266036621765763524847385999721254478313573544681811727225087201633669304728449000690805131434160354788200355429868149616777944697604839445821146293319865569802164294050791015324448927695484221067203620046595245414313118308514802029950573572440600781377894978809819943/181722077267496712765685299854910928430577363169730663563485646906409240914103088994952027139146022982323103998664599330798234104961889050508536830747141306677770720057513098106840911421356649437720093820050735424335965712616667522034237972695981821861481508821975625 A46^9 * U3 - 101409764297139370497431870913772400890980479461654448912068336828050482388546012701358058370032729748116854879439321035194274795413256750973689666942448462456840973308098467386964329640348557236019188613852479460195591937286545711022988218130783801374434056440021146855389791263/72688830906998685106274119941964371372230945267892265425394258762563696365641235597980810855658409192929241599465839732319293641984755620203414732298856522671108288023005239242736364568542659775088037528020294169734386285046667008813695189078392728744592603528790250 A46^8 * U3 - 3322794676291853666085201130675181837616673614933545069242421946525758427676251695684072633966150401809622984292825237098582373428490919709859723984671293905443481868170729806447368393045191340333060166403807452609937752781689646834959249508572627032878032237058297511762260717/13845491601333082877385546655612261213758275289122336271503668335726418355360235351996344924887316036748426971326826615679865455616143927657793282342639337651639673909143855093854545632103363766683435719622913175187502149532698477869275274110170043570398591148341000 A46^7 * U3 - 235997802096027015525218011390431135161602429335194555350491794738198772970078394908866958050373633238495091699843397584952514894044850979218568026142058202580747771909113137749719827302612618129281900176792733050978935129822521807364852652110897499832909022097494923166043147/7417227643571294398599399994077997078799076047744108716876965179853438404657268938569470495475347876829514448925085686971356494080077104102389258397842502313378396737041350943136363731483944875008983421226560629564733294392517041715683182559019666198427816686611250 A46^6 * U3 - 3496748794132449388555216753002710407113019869328151832331519672134490805457467271923368355368145123271002659562187642206698039955131848140898636455957544259518289841694390481218777439807140629994396001816472151472171553970751649445797629489197230923775536860056783627934479/1130244212353721051215146665764266221531287778703864185428870884549095375947774314448681218358148247897830773169536866586111465764583177767983125089195047971562422359930110619906493520988029695239464140377380667362245073431240692070961246866136330087379476828436000 A46^5 * U3 - 25797731568499728113711563609522696636972574369245543976139702215108120141166264492184554278639511568603311186805558250985505155379498427020368472760296798230482403566780044258141402965693251712985897771176010862913999745411179857703742819398871451136186089552354116699661/129170767126139548710302476087344711032147174709013049763299529662753757251174207365563567812359799759752088362232784752698453230238077459198071438765148339607133983992012642275027830970060536598795901757414933412828008392141793379538428213272723438557654494678400 A46^4 * U3 - 105307750747592845167925795351809474019566402815312738506184953133174877999878727791254675413428352747128321422294719175016172361719591143541377238760546940146607913162164819516842775340285454038918138509577296566880300576934730064221978046439482447941555635234543414413987/16607670059075084834181746925515748561276065319730249255281368099496911646579540947001030147303402826253839932287072325346943986744895673325466327841233357949488655084687339721075006839007783276988044511667634295935029650418230577369226484563635870671698435030080000 A46^3 * U3 + 6729992771983469644834688420302244188161700009523433301108672306478446515336817887911228386552702182506838452635857560083522640089937561680000956097567263329228552440470166784211722333574861459688985916960390707820563713605127900163322847651117899308325942825648612997/67786408404388101364007130308227545148065572733592854103189257548966986312569554885718490397156746229607509927702336021824261170387329278879454399351972889589749612590560570290102068730644013375461406170071976718102161838441757458649904018627085186415095653184000 A46^2 * U3 + 97004104716134687567531815774189859076177884454360758941608137811927278665332561915062791777635759119435458822688898910056883442317958132684946302161704171063308484365878439710058473575123783245727688981281817771384031307613137609700123391407537243830931947114431/6831585629064056574855845836052158745080934515857178544035198543609673601669897191808363859627789995425297044867960294464526195050373321126677188143307925380675194012654126509458510328107232388557460939286669359345141026801890396437380097619257766330571494400 A46 * U3 + 91815250260603771367686439814867337622922814376622703580092567517752668189839523750475603039746288206705982958930474905045662465449513750706031249185792777351062825505761724720085638243587008740273119957261765515541418363044444151757419729917247863640658968103/351338689494722909564014928711253878318448060815512039407524496528497499514451855578715855638000628336158133736066529429604204316876342229371969675941550448149009977793640791915009102588371951411526562591885852766321538521240077531065262163276113697000819712 U3 ) ) """; ps5=""" ( ( U3^2 * U4 + 535179163636213160230552332612905761790726203364450534489129686242659247983859225063689303002742332435127911688744222034136908867349929123331100864371658990936252805314758914346647230739008414163809378439226935298947238851749778443095061790353887385009084423995392000000000000000/348416638018627423852659631690165992696423968578095238206531661082875150589988624585082662615359891459868853047741275214579945040097279766315202366058735323894271720291427837740051083562531195231732794190712907389828879861536476746186614041056457073638389583231854077 A46^31 * U3^3 + 117444957438518475167713581434975737067164998391805610491814809960560346257088363610575217412650923824342320317819214071400331125353389211274396241076281078058047842081052040344628591911420714970389327499109713526665438238583003654833271274497439548231330310580181401600000000000000/2438916466130391966968617421831161948874967780046666667445721627580126054129920372095578638307519240219081971334188926502059615280680958364206416562411147267259902042039994864180357584937718366622129559334990351728802159030755337223306298287395199515468727082622978539 A46^30 * U3^3 + 2401741581776741318484092416102407292900015435135593836159021006355478379624893489598800836632769384261155218893078011625298104568085745627327942804937416501911688374548247994274079800109905304371024073616832343444568942958320613360649846757743965134232833554270042193920000000000000/17072415262912743768780321952818133642124774460326666672120051393060882378909442604669050468152634681533573799339322485514417306964766708549444915936878030870819314294279964049262503094564028566354906915344932462101615113215287360563144088011766396608281089578360849773 A46^29 * U3^3 - 805568218873790937813389084592233191792825630736851320718859307972639139165702967980087508722852747263747190017939561005107936647865901266983449666943346565871280018184856673037268657368899455757140347277745038838145391480304288946439289988670652938164442307992695603200000000000000/2072374107058772364996455265949022002801273200386473989101277914764615780098834073399133293821996117411589883156796371074004412984162432829701405980777102013220841619536874248754407890091587282621115868336668102336034204494341240299572403747093030802161288330321259221 A46^28 * U3^3 - 7685682775116980037756417525104129020857901100253508944433808002299072796987780826355035229956095427761674994214377901743588098560205258976689072899389795364550488078379086807213438803727723516868672038614031636269842625366221371250239578203300336002844575259786307614801920000000000000/2509645043648173334010707327064265645392341845668020000801647554779949709699688062886350418818437298185435348502880405370619344123820706156768402642721070538010439201259154715241587954900912199254171316555705071928937421642647242002782180937729660301417320168019044916631 A46^27 * U3^3 - 1034113844705967884541016548705263783711258150109052467551058076026319678448759166131211515280654219796468782344958028728719356943011812509405877602376788836215237969187146349036450163464263286874467724055879617971867571915156566751269616939474200904886354631269920338765414400000000000/119506906840389206381462253669726935494873421222286666704840359751426176652366098232683353277068442770735016595375257398600921148753366959846114411558146216095735200059959748344837521661948199964484348407414527234711305792507011523942008616082364776257967627048525948411 A46^26 * U3^3 - 48658714056579159584588250657320626399886844717677219117243540154602424522685502681521979204132079896072758913281262740708279626890869807641530459145331943833017069929236863886983924086820489878464574416932681640220499275442882030223770711661291180467191894819368336275978321920000000000/3226686484690508572299480849082627258361582373001740001030689713288506769613884652282450538480847954809845448075131949762224871016340907915845089112069947834584850401618913205310613084872601399041077407000192235337205256397689311146434232634223848958965125930310200607097 A46^25 * U3^3 - 8255947206923045970115261594812428132415296386179673138598668698030130733176457946142061749654776338102806089384084736737962150165972226111226766639416349566788039796025933969548991539844303719591225974525365272074129459969218772790071341578178550260218707253120429402938146816000000000/460955212098644081757068692726089608337368910428820000147241387612643824230554950326064362640121136401406492582161707108889267288048701130835012730295706833512121485945559029330087583553228771291582486714313176476743608056812758735204890376317692708423589418615742943871 A46^24 * U3^3 - 19945713493372992010989573088745323542756396319972931197979116120090053547915047057950693601445545496940530403318628583782260656315550176840007325651552659987878417938292973350492923084265613272190430226035072662253316611695490659970858884921554483178528771682266082834119655424000000000/1382865636295932245271206078178268825012106731286460000441724162837931472691664850978193087920363409204219477746485121326667801864146103392505038190887120500536364457836677087990262750659686313874747460142939529430230824170438276205614671128953078125270768255847228831613 A46^23 * U3^3 - 435093775488421369600147732183313564461463032259212791823425518543075036047179553289353390602878450300140400400876508808029170501403708143242207930225443742617112912856658164191471704385406656699565008229508861688289615831997614509046870265598882388184233731177202498351136768000000000/65850744585520583108152670389441372619624130061260000021034483944663403461507850046580623234303019485915213226023101015555609612578385875833573247185100976216017355135079861332869654793318395898797498102044739496677658293830394105029270053759670386917655631230820420553 A46^22 * U3^3 + 1666712214493918375843073715679404854923553599857383781647492939009113706816140218151303957915155518916011997458056804212971047568027330977305056462875462122879154305439206460319912215754500114817599379012537086490342649170430864147520080485377840240561213239361225941393442471936000000/1777970103809055743920122100514917060729851511654020000567931066505911893460711951257676827326181526119710757102623727420001459539616418647506477673997726357832468588647156255987480679419596689267532448755207966410296773933420640835790291451511100446776702043232151354931 A46^21 * U3^3 + 1284088025543201778701542120995051734041815978306710257005722604826526562109618762971947126682732875656141515493855498879095407124008034223158582017519436364169634168807052804122297828912887489492802203539147042679430553728949689548527311377444129568517124121118716963986204576972800000/253995729115579391988588871502131008675693073093431428652561580929415984780101707322525261046597360874244393871803389631428779934230916949643782524856818051118924084092450893712497239917085241323933206965029709487185253419060091547970041635930157206682386006176021622133 A46^20 * U3^3 + 4254014381230883330619305014989375799554837810367142599761760649672291739447040860678177727995158715416431102910496713847267271580162773653334863631889973825919344031375754538234961810569091573254261817527160589941054559827804400510444074230128005539082809168028853708352942800568320000/761987187346738175965766614506393026027079219280294285957684742788247954340305121967575783139792082622733181615410168894286339802692750848931347574570454153356772252277352681137491719751255723971799620895089128461555760257180274643910124907790471620047158018528064866399 A46^19 * U3^3 + 745516437593004300883570660646246938247823802410590380979420190673989967797085587628924839737460064182360717893802831288295892815613347860630889607237862285660785165032805451166314560759396503899171227181213064059364949918934022222627542591929187087049764507673930916328360804352000/182337206830997409898484473440151477871997898846684442679512979848826981177388160317677861483558765882443929556212052858168542666353852799457130312172877280056657633950072429082912591469551501309356214619547530141554381492505449783180216536920428719800707829272090181 A46^18 * U3^3 + 100659132205313930529625050503119312070810564089441017863641173372860790994172383194397174444036783482169409680952402366953488358200797270823652786371161310119627780987982282462009952616082069316251196025335382901954198189565730812891991210118588783206461023328312986396596201321267200/46652276776330908732597955990187328124106890976344548119858249558464160469814599304137292845293392813636725405025112381282837130777107194832531484157374744083067688914939960069642350188852391263579568626229946640503413893296751508810823973946355405309009674603759073453 A46^17 * U3^3 + 31840686398285739366370901635863389542030022459808048577847041429885472147377770155737274410841071887893024815380774859603070679264257251115288897069582531630147721152091634280145756325435744966628395355333013175929902375331398691019183890365382567317614167783255315159428074691624960/46652276776330908732597955990187328124106890976344548119858249558464160469814599304137292845293392813636725405025112381282837130777107194832531484157374744083067688914939960069642350188852391263579568626229946640503413893296751508810823973946355405309009674603759073453 A46^16 * U3^3 - 13828528445690452987305064022092959448876463072880660857470397879545100109724829810338301593203092974158319894346856522064022294423111854351244636838712011841678369295025322372766599272518628248765532325453911764768121252460833528916104395772737785984090513826255228303325154466127872/139956830328992726197793867970561984372320672929033644359574748675392481409443797912411878535880178440910176215075337143848511392331321584497594452472124232249203066744819880208927050566557173790738705878689839921510241679890254526432471921839066215927029023811277220359 A46^15 * U3^3 - 33610752624740506302912013993814981775024007915215935211163351291344044163786135068634072771353605827815789041344588941769903151215762730402577426802629600007206325972644549999333779030662823436337121030730985687375264611402234685156485004573481758060166931327023163395774356304113664/99969164520709090141281334264687131694514766377881174542553391910994629578174141366008484668485841743507268725053812245606079565950943988926853180337231594463716476246299914434947893261826552707670504199064171372507315485635896090308908515599333011376449302722340871685 A46^14 * U3^3 - 440458073572699732774489360478761084951279455207275623193025208264809731530938512938804891081421616585621742589211241713795773058743821672163780025900276255331592774249357759549304463610560721287707008918417645237050696497113058739332361880620366592325582276896858182823540813585536384/1499537467810636352119220013970306975417721495668217618138300878664919443672612120490127270027287626152609030875807183684091193489264159833902797705058473916955747143694498716524218398927398290615057562985962570587609732284538441354633627733989995170646739540835113075275 A46^13 * U3^3 - 6996214565149446678253694413083490264717525678004855498090489246100920822500988095095030219926214938120572903557109272761916802518646083631510656210142715036721759509042764836946925860045014447394355560737664073350497528956878636493202886375323607681733788379035427399732074066732736/39670303381233765929079894549479020513696335864238561326410076155156599038957992605558922487494381644248916160735639780002412526171009519415417928705250632723697014383452346997995195738820060598281946110739750544645760113347577813614646236348941671181130675683468599875 A46^12 * U3^3 - 52720968043649456846417369507000756940194406072631641273516890434262149856954069120692268860993592166109579882175849063584157212108249084107098488501914404760103187541211164434424785557474548152913921719930232076831591869022033755032242197725738904601218545055852510881677688297536184/642658914775987008051094291701560132321880641000664693487843233713536904431119480210054544297408982636832441803917364436039082923970354214529770445025060250123891633011928021367522170968884981692167526993983958823261313836230760580557269028852855073134316946072191317975 A46^11 * U3^3 - 560521169089131499065785274068646758491670755018612288505863123339558028653018546907577396130067320298156818038178669090843281588218301520813686567954392296875641272535840128326520911631312236737399924421960962557597703529589857661762970259131745451459708625790997896125768972935928/18361683279313914515745551191473146637768018314304705528224092391815340126603413720287272694211685218195212622969067555315402369256295834700850584143573150003539760943197943467643490599110999476919072199828113109236037538178021730873064829395795859232409055602062609085 A46^10 * U3^3 - 4197422272012614585634130742038816517252315110924247183388171916467791237166762578598405913589164581591069795124771062594877274429670076994003284050036156103051961891924620808585164846207763280779766288975531255051754977759088637973954664073448069462858272840556659782286260872647812/459042081982847862893638779786828665944200457857617638205602309795383503165085343007181817355292130454880315574226688882885059231407395867521264603589328750088494023579948586691087264977774986922976804995702827730900938454450543271826620734894896480810226390051565227125 A46^9 * U3^3 - 4106654994410345218350715474180779469031652386352768990088763404863224321126834681787202405252012606245929498654531112676402813452159609458415502006915204469860173111678951294367642751272844986752033113410832855341088770049302498143130605877209294548098061602991987492963051239744/1873641150950399440382199101170729248751838603500480155941233917532177563939123849008905376960376042672980879894802811766877792781254677010290875933017668367708138871754892190575866387664387701726435938757970725432248728385512421517659676468958761146164189347149245825 A46^8 * U3^3 - 10861509873129061552037235599451402972763702999367178857883272454799214845428691114656489287350714907124422743117360275388527760856063819431352503904308954737409956132586217400390831701855393788768594250812823801249588131220343764676215839452260384917296536245871426396362711599029/26230976113305592165350787416390209482525740449006722183177274845450485895147733886124675277445264597421732318527239364736289098937565478144072263062247357147913944204568490668062129427301427824170103142611590156051482197397173901247235470565422656046298650860089441550 A46^7 * U3^3 - 1124486478466758794641936904982948237084283820279761242642612077110909965390094116007619021675739939209813695144499796429672334602667319111431706473000996398421642195295148270757273990731860799515046565486145747844982383328993615581180179952020178830599171027345719008701601415523/18736411509503994403821991011707292487518386035004801559412339175321775639391238490089053769603760426729808798948028117668777927812546770102908759330176683677081388717548921905758663876643877017264359387579707254322487283855124215176596764689587611461641893471492458250 A46^6 * U3^3 - 13634406027258739162572410843253056158384774240138183339467954043156022885658076072571122964861139837559116738714581975870696472208621260986499059519385686842525264750880868543070223665506121563803996657564834448591138230910580178478122708511083518804685049985931165670484826297/2141304172514742217579656115623690570002101261143405892504267334322488644501855827438749002240429763054835291308346070590717477464291059440332429637734478134523587282005591074943847300187871659115926787151966543351141403869157053163039630250238584167044787825313423800 A46^5 * U3^3 - 275610949766603790350543874491973128402944565236452331621829945535128551051089218509229304570354572863614983692536142099515347666278429222971179578469228299012270654864962841491251938427241318189542247237765029951590277176611163743592667595081103539096197325545120410752450853/611801192147069205022758890178197305714886074612401683572647809806425327000530236411071143497265646587095797516670305883062136418368874125809265610781279467006739223430168878555384942910820474033121939186276155243183258248330586618011322928639595476298510807232406800 A46^4 * U3^3 - 57091321219446868547123718685194170669561742150029307684083906984399449382980015516422277491250022223527057750658840237853760266613003361978501494129695368914676980282464037464506358216208278225667602395223784571111874119085762583994232092883441120694085505220223346971423259/3496006812268966885844336515303984604085063283499438191843701770322430440003029922348977962841517980497690271523830319331783636676393566433195803490178739811467081276743822163173628245204688423046411081064435172818190047133317637817207559592226259864562918898470896000 A46^3 * U3^3 + 2096019020134284361588278549962801625099190206781628224639171740828930915568065430755481920106589988497979688771818295815492190569468006618308754762164717538084498525703860854191800473065932573287633087040724218118612995977781646506334852358874110328385808128162955638079/14269415560281497493242189858383610628918625646936482415688578654377267102053183356526440664659257063255878659280940078905239333373034965033452259143586693108028903170382947604790319368182401726720045228834429276808938967891092399253908406498882693324746607748860800 A46^2 * U3^3 + 144724249725887284436232581781817786550817001839619049910175696311756292310832604781793691600419996522748911371809754829004775699207861014225518336712102081581627568566107942347420832194840104563187671858359656942129120425684588448408665047033556866808539561866776501/4314260184514436127964380909564205783497694829005739203533961800265235707347901241580178583419276511944332172118198058625922700944228258513515422265634676676652729605557958459498206914038519040580512540841853144915778977442507150190146154648188267067194741571840 A46 * U3^3 + 34523752399540034716636145000935730218516677827634880256328110824710605643763228906652973946423825292328221117422519494495751855171799684110699308767573648503790821554402991388888863972166596620407299382152069987750344858727174998460595722071373991687451348757265/52827675728748197485278133586500478981604426477621296369803613880798804579770219284655247960236038921767332719814670105623543276868101124655290884885322571550849750272138266850998452008634927027516480091941058917336069111540903879879340669161488984496262141696 U3^3 ) ) """; ps6=""" ( ( U3 * U4^3 + 41822330490195068041017320363097809729090890052699731534033293673080362045613806875773900749189755394694179768458994485940692483615892634922652342251410719603257617491056399521754985563535628528166060660260046980535041591378337983957604595139759378622893247460686601951641600000000000000000/356450080441422916364430404818046149990025416021600380113859661592463002937141992302140913567282244477259049192463045797202514832886802745887131987012951584257301943346187289394823441396232477000190857226368174895516164344503923290523438801001095804385269931852430936453389 A46^33 + 454125157206527413523601969987620494847328162420135984302287459170369832878272220272886380031914311891233003000504439954565744301327926677967038692247319542412616194634678505272858478303439697166808691979442683766268105374119197842122316902319990742401536311538368167952547840000000000000000/831716854363320138183670944575441016643392637383734220265672543715747006853331315371662131656991903780271114782413773526805867943402539740403307969696887029933704534474437008587921363257875779667112000194859074756204383470509154344554690535669223543565629840989005518391241 A46^32 - 14740085336461820800966266074682241729581054272188710537515241908189807762813569534360041532382661570106035157724159025403425541339461211407295309969242948500584368294316900034869383665586431029071989963112162284745485647807851469068632801796651905968443260670347124770482847744000000000000000/52398161824889168705571269508252784048533736155175255876737370254092061431759872868414714294390489938157080231292067732188769680434360003645408402090903882885823385671889531541039045885246174119028056012276121709640876158642076723706945503747161083244634679982307347658648183 A46^31 - 9149331424499552779979794487803049109145854134654822152707377782056977306922942650458296507280354954701791394660220920473087273186333364153948147270760935725093184452955662120588287066833595316280317830971486425063174196982668087569045226676196390232025049390929919119574244207001600000000000000/1100361398322672542816996659673308465019208459258680373411484775335933290066957330236709000182200288701298684857133422375964163289121560076553576443908981540602291099109680162361819963590169656499589176257798555902458399331483611197845855578690382748137328279628454300831611843 A46^30 - 79973012198225026539332842880094613358418060119022835029835910425124670099764459027277518388837201641732137026202824480404214035628958792843162201239309141530235969873589550508448718782972837671619969580166184326037129487506541556889887126810734028550977167372000415444560765391994880000000000000/2567509929419569266572992205904386418378153071603587537960131142450511010156233770552321000425134006969696931333311318877249714341283640178625011702454290261405345897922587045510913248377062531832374744601529963772402931773461759461640329683610893078987099319133060035273760967 A46^29 - 8299397433438618012971050717608586981007096658561248516910138778913485394953866129982359922925735316581762478702897711207576975054100165652131628929716109958379944654693325699234875749400905318226733372296404518054930456353699133199857710268046545544970469824348289708598182344299520000000000000/122262377591408060312999628852589829446578717695408930379053863926214810007439703359634333353577809855699853873014824708440462587680173341839286271545442393400254566567742240262424440398907739611065464028644283989162044370164845688649539508743375860904147586625383811203512427 A46^28 - 1009095872071060606887382314527808282304198676274688330469220230071145794033535363745528418711512251257265245188164841956986767644719780200297491853553606313847573922892151658199998953665772946824914444133907829818800088800411900616394966638527678678559806341695040379358176887422246912000000000000/9903252584904052885352969937059776185172876133328123360703362978023399610602615972130381001639802598311688163714200801383677469602094040688982187995180833865420619891987121461256379672311526908496302586320187003122125593983352500780612700208213444733235954516656088707484506587 A46^27 - 17315208871659672382889994991298216489948823684300447200387695359236475124436480420376202114747618244141605164691824173316146543744310447948881287127831116503491247576077521276794352818587011612296482326427954766142441690371899121755561881707409211508579604162112995865737896762901299200000000000/157194485474667506116713808524758352145601208465525767630212110762276184295279618605244142883171469814471240693876203196566309041303080010936225206272711648657470157015668594623117137655738522357084168036828365128922628475926230171120836511241483249733904039946922042975944549 A46^26 - 355912103283291653350342202441876054749468980229513306853575234001898259812970951366303068842390266228175806871138615053043787098181575854719444584002263604429051532090218493757283996626942336013246526185261992049786421446412979193448620795644178642889464382438869086312841888992127016960000000000/4244251107816022665151272830168475507931232628569195726015726990581456975972549702341591857845629684990723498734657486307290344115183160295278080569363214513751694239423052054824162716704940103641272536994365858480910968850008214620262585803520047742815409078566895160350502823 A46^25 - 22500215142403543279349306218081169611665243245444094081053540155023353065879988896297915009225132894908494486994564419892386896801934687727963175381359248310045430450423575265267918061375611015895078661355902220676428093155477822434762767854058633074606376473106078760663121039247968256000000000/606321586830860380735896118595496501133033232652742246573675284368779567996078528905941693977947097855817642676379640901041477730740451470754011509909030644821670605631864579260594673814991443377324648142052265497272995550001173517180369400502863963259344154080985022907214689 A46^24 + 32673087924159313144791905275717518339829777902894646782455060134934567490559434999059780860378598405024654197705939033389093954547300991047620772736355387222770403567834688718752714161637753797576326177011424906610337687450739278051783922665936466482962665445318545262436466728042148326400000000/5456894281477743426623065067359468510197299093874680219163077559319016111964706760153475245801523880702358784087416768109373299576664063236786103589181275803395035450686781213345352064334922990395921833278470389475456959950010561654623324604525775669334097386728865206164932201 A46^23 + 1104476613898878470428452483404305645696373154435799116198630014006790595031027352442953347316486180518984682424499974769238555293892978509198039261572798669589819427036166245573413843280166968329333248039556067221899335330112207191529323373567807146257408223366473003726728025624000104960000000/37121729805971043718524252158907949048961218325678096729000527614415075591596644626894389427221250889131692408757937198022947616167782743107388459790348814989081873814195790566975184111121925104734162131146057071261611972449051439827369555132828405913837397188631736096360083 A46^22 + 78113480257566589843454213154883751458293793164562951385751797138539577840045698708433870322843582703179960018071553825115618374965480805851557122788075034745129320776152687748718547900383557327895464091642273092813119121008016975113831330943443029648706513051422069517463619351777438820096000000/2338668977776175754267027886011200790084556754517720093927033239708149762270588611494346533914938806015296621751750043475445699818570312815765472966791975344312158050294334805719436599000681281598252214262201595489481554264290240709124281973368189572571756022883799374070685229 A46^21 + 8395276376303141598390829139882556608548753795333152128887172440477769331506706983960503595713255764449491015079245760485357931286228197098907656335096624996307325605986758954601108746818602104646481755620539840786476094323961082674609265938980034638463288197875497334999695180183262425971200000/334095568253739393466718269430171541440650964931102870561004748529735680324369801642049504844991258002185231678821434782206528545510044687966496138113139334901736864327762115102776657000097325942607459180314513641354507752041462958446325996195455653224536574697685624867240747 A46^20 + 1980830687381076339084629170133609739180380880215294749410365337574729337777957070632004952411058046327505217385303454420099905980785666056543363976205429431407119959330949327855470437048628780012191977441692141470352845169941328389007388270439665640289698273307474532663228874959149967256320000/143183814965888311485736401184359232045993270684758373097573463655601005853301343560878359219281967715222242148066329192374226519504304866271355487762774000672172941854755192186904281571470282546831768220134791560580503322303484125048425426940909565667658532013293839228817463 A46^19 + 702091132949191502045640382611695646026178320839883517672739200609357661071215369230485179018215789550721046578374598929240937327355327668355522069483080934376708869486654867322142997232774287348753757914178992350603911472387418363244015679942880338944525806103128925167085917623892484556464000/143183814965888311485736401184359232045993270684758373097573463655601005853301343560878359219281967715222242148066329192374226519504304866271355487762774000672172941854755192186904281571470282546831768220134791560580503322303484125048425426940909565667658532013293839228817463 A46^18 - 26433410235178253131164568590264182053663342966938907183003177081908265950075927144928504095882195140380650366718219667766773538150084001651408286437201753129205947322295717753544109541401358911647830600006212366636193412718513659512611675534262638709507230297656780911489899859088163252104000/429551444897664934457209203553077696137979812054275119292720390966803017559904030682635077657845903145666726444198987577122679558512914598814066463288322002016518825564265576560712844714410847640495304660404374681741509966910452375145276280822728697002975596039881517686452389 A46^17 - 36588941424973786825226031379192323188694220080503719244669152016528167903934256688892636045811947246452459444223170684913020286311345813411596839167079667051478933505562383477365997492491009488269523510100891279267477520527793501298375191462023458969167972627835965786511419141962714020174080/20454830709412615926533771597765604577999038669251196156796209093657286550471620508696908459897423959317463164009475598910603788500614980895907926823253428667453277407822170312414897367352897506690252602876398794368643331757640589292632203848701366523951218859041977032688209 A46^16 - 321333621660414138288318264757386991534769910679354013783840583853994409935788586791159864436843010390611984538928952685258511624721739694382405481016998808554437914129696961450517494564423154689101019268062664959334760483746323046684415109519127596246390980123789139075174901071183005966554488/184093476384713543338803944379890441201991348023260765411165881842915578954244584578272176139076815633857168476085280390195434096505534828063171341409280858007079496670399532811734076306176077560212273425887589149317789985818765303633689834638312298715560969731377793294193881 A46^15 - 297844721921145322765306527355860406934008939169980445647884079222865480952075045050385650004580591246687712266033786754423786883489838690861527534993455211693991394970866545156968100893505892393812058175717385845665650930957741425381878068688495541752226534683879631214290521382589457098661971/262990680549590776198291349114129201717130497176086807730236974061307969934635120826103108770109736619795954965836114843136334423579335468661673344870401225724399280957713618302477251865965825086017533465553698784739699979741093290905271192340446141022229956759111133277419830 A46^14 - 451879932351907431338340841430894291445765587061006243890312609075513994394090487211287876791443241336702645913369115324679497644368945637845627225355027484550118544624707338874219923703785680226085214156696766542732612750915702425388991747367656078911167375594394305408128145699286227195203039/788972041648772328594874047342387605151391491528260423190710922183923909803905362478309326310329209859387864897508344529409003270738006405985020034611203677173197842873140854907431755597897475258052600396661096354219099939223279872715813577021338423066689870277333399832259490 A46^13 - 5320311585057193929116580887725053048673711797951597468291152199479233897939064740829295546757123058099231381384546836150171434463598328526972269844562130162789158735497528507679194843684312884543346736256634246332090848994957191293298207019966632338305847326064328022091724095239631394444614337/22542058332822066531282115638353931575754042615093154948306026348112111708683010356523123608866548853125367568500238415125971522021085897313857715274605819347805652653518310140212335874225642150230074297047459895834831426834950853506166102200609669230476853436495239995207414000 A46^12 - 362392746608515719372641040156549702648285106850030418671446645004524075469397447508371929006539117538692298420067983710297061362768282375139330712098123029408339164065434243491074476680334774441684136089288247838831323010949142346356824849579571331534045674787558012078606230561135787887949871/4508411666564413306256423127670786315150808523018630989661205269622422341736602071304624721773309770625073513700047683025194304404217179462771543054921163869561130530703662028042467174845128430046014859409491979166966285366990170701233220440121933846095370687299047999041482800 A46^11 - 155718157831390278974558432491864519634779570729825416271843627583866505195625371450767361228547485547131717071612734991086436233519540316144548267366374648257565699340887077601451758110896914837331994622765481537988675137980472319274860288480400497182597917963360319541332897673699613001900139/6869960634764820276200263813593579146896470130314104365198027077519881663598631727702285290321233936190588211352453612228867511473092844895651875131308440182188389380119865947493283314049719512451070261957321111111567672940175498211403002575423899194050088666360454093777497600 A46^10 - 45201548094888346900126189229758597421851803521277808642167463508827660396693637290758710792553278488070609212455021345000119146078696472196451660991329985879243486243508404638669646114695294849026046972039432309027960523963229014364806077507073721111320914116188285819616980932331878040743049/8587450793456025345250329766991973933620587662892630456497533846899852079498289659627856612901542420238235264190567015286084389341366056119564843914135550227735486725149832434366604142562149390563837827446651388889459591175219372764253753219279873992562610832950567617221872000 A46^9 - 1953129387759091287411246093721824623775778716719168388328766612507051710224152064386589191585418322171515414473927996208486195431232117229550712885298021138550712056198139675205800600486010459477444720900066414100009247618626937808864666954121404483671145377185645585361795757512848953771727/1962845895647091507485789661026736899113277180089744104342293450719966189599609065057795797234638267483025203243558174922533574706597955684471964323230982909196682680034247413569509518299919860700305789130663174603305049411478713774686572164406828341157168190388701169650713600 A46^8 - 376134847222603342228005080394985602907218977535587514699426664550583601459354985670099124083557791013853499761803409404040812308856476452671356746803998334683915044848315929579536086205259194433291389544619656281935845620125586677702558497845124290906144446668089290971220577745466063821/2503629968937616718731874567636144003971016811338959316763129401428528303060725848288004843411528402401817861280048692503231600391068821026112199391876253710710054438819193129552945814158061046811614526952376498218501338535049379814651240005620954516782102283659057614350400 A46^7 - 574485486982304350778070191971122027743291593240873280940414570314432804154563998121312928497476285147145839708807365153231143249845428378451535410210139619924467103332329351315189638465205694465434576925840400070753365257384354164688588108696337944766401214964460997424273537531595188679/32700473063674993877314280067084329847784709372590489035273526875801185999160500875598430607824044439533947575902676800042208658169062152177791992057159232139886425323352726590079292266554266733865985658153488956323282789029216389415852930685661446749807050235546874962944000 A46^6 - 11511257781723192579987461460171218665430662046039138877189380600683547596344289008862892439158437560118751792069494864896646099764172740280826359491156661557991789303166781418829521172671095190437798106362980957418171493748387515586895216124868996215985307716367044170468765302175191523/7630110381524165238039998682319676964483098853604447441563822937686943399804116870972967141825610369224587767710624586676515353572781168841484798146670487499306832575448969537685168195529328904568729986902480756475432650773483824197032350493321004241621645054960937491353600 A46^5 - 1671303995297463181793089014042140921533205745175671854516004230292597522756847916940561516331382516496857206868368002684300205049090986725992113164539129267661714078303721803021367606163396471932149786832020402699788845934151506635865863054320744139050271729184411228168473604636972839/19620283838204996326388568040250597908670825623554293421164116125480711599496300525359058364694426663720368545541606080025325194901437291306675195234295539283931855194011635954047575359932560040319591394892093373793969673417529833649511758411396868049884230141328124977766400 A46^4 - 60908092525844337290393747162251644298087521040833441461527761929200066595412859133091070618059209993364079718454967764919058787501486800829921561765930651085782549124215742770618379064496572773262751298821893631502246026461480269869465295797601392220253848115075799372526327938111547/28028976911721423323412240057500854155244036605077562030234451607829587999280429321941511949563466662457669350773722971464750278430624701866678850334707913262759793134302337077210821942760800057599416278417276248277099533453614048070731083444852668642691757344754464253952000 A46^3 + 45086394754577700869380844548742167538951281901932651744568905863102388384166263647335650948182916349574945031051918658847888488603435323077118198631600514293001349841754886818523071957433889642885763744141389343414660044929152119754129057333007696856923108253108183335928470691323/732185519326600445999340148440838639157395241928556722422450980775956584470998970042553781539617088325424832020211538846426129722269379967129569967927063856659847657385856968547548001770078042320964343599471706077442600057563795541439505853253294201278478559209912535613440 A46^2 + 3731272476720292507686304261693030416127583479257486748224902831742134747688100663209642453477726001478166688384847374161566164080254468319618379882752444074260128081142704326346717896603236118487929226426342553598574093896870131278947045099476660390852113706889521422745255/648548681376311336096354298151253046305799356866989727202426109672580591403591774768418528149462415254238265324025243450986863770434187187437615121817481448997172315569955506437383079799176270479879130881051326953517042284548430007652623523644145232141509494765016064 A46 + 9280862118536625477466695256284609672515130143361639412543372050128009110823486812077779222084224626376141852085219762625785282075028284601725310082870373135311800354168551231605316413369320027988216942534660872550537108296929260273306523538001567960935496614750288886518875/94873407104191829737523828758126159916734077347399640093612048043531789371039711051837224689292787602905711955971692756258649785846372525705159697820157286253300635877662062655982896244908071567342318574599508400057350185625370332548040926887372102530415103234196635648 ), ( U4^4 - 20/7 A46^2 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; rg = f.isGB(); print "is GB output:", rg; print; ri = f.toInteger(); print "integer Output:", ri; print; rip = ri.list.get(0); print "integer polynomial:", rip; print; #startLog(); rfi = rz.squarefreeFactors(rip); print "squarefree Output:", str(rfi); print; for h, i in rfi.iteritems(): print "h**i = ", h, "**" + str(i); #print "g = ", g; print; startLog(); terminate(); jas-2.5/examples/hawes2_gens.py0000644000175000017500000000237711151546512016752 0ustar giovannigiovanni# # jython examples for jas. # $Id: hawes2_gens.py 2456 2009-02-26 17:11:39Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate #startLog(); # Hawes & Gibson example 2 # rational function coefficients r = Ring( "IntFunc(a, c, b) (y2, y1, z1, z2, x) G" ); print "Ring: " + str(r); print; [one,a,c,b,y2,y1,z1,z2,x] = r.gens(); p1 = x + 2 * y1 * z1 + 3 * a * y1**2 + 5 * y1**4 + 2 * c * y1; p2 = x + 2 * y2 * z2 + 3 * a * y2**2 + 5 * y2**4 + 2 * c * y2; p3 = 2 * z2 + 6 * a * y2 + 20 * y2**3 + 2 * c; p4 = 3 * z1**2 + y1**2 + b; p5 = 3 * z2**2 + y2**2 + b; F = [p1,p2,p3,p4,p5]; g = r.ideal( list=F ); print "Ideal: " + str(g); print; rg = g.GB(); rg = g.GB(); rg = g.GB(); rg = g.GB(); print "GB:", rg; print; bg = rg.isGB(); print "isGB:", bg; print; p7 = ( x + 1 ) / ( x**2 - x + 1 ); print "p7 = ", p7; p8 = ( x + 1 ) % ( x**2 - x + 1 ); print "p8 = ", p8; startLog(); terminate(); #sys.exit(); jas-2.5/examples/sicora.py0000644000175000017500000000065311441233352016015 0ustar giovannigiovanni# # jython examples for jas. # $Id: sicora.py 3316 2010-09-06 18:46:03Z kredel $ # import sys; from jas import Ring, Ideal from jas import startLog, terminate # sicora, e-gb example r = Ring( "Z(t) L" ); print "Ring: " + str(r); print; ps = """ ( ( 2 t + 1 ), ( t**2 + 1 ) ) """; f = r.ideal( ps ); print "Ideal: " + str(f); print; #startLog(); g = f.eGB(); print "seq e-GB:", g; print "is e-GB:", g.iseGB(); print; jas-2.5/examples/0dim_radical.rb0000644000175000017500000000134411641147136017024 0ustar giovannigiovanni# # jruby examples for jas. # $Id: 0dim_radical.rb 3783 2011-09-29 20:00:31Z kredel $ # require "examples/jas" # polynomial examples: zero dimensional ideals radical decomposition r = PolyRing.new(QQ(),"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); f1 = (x**2 - 5)**2; f2 = (y**2 - 3)**3 * (y**2 - 5); f3 = z**3 - x * y; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; F = r.ideal( "", [f1,f2,f3] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "decomp time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/polypower.py0000644000175000017500000000211210625376002016570 0ustar giovannigiovanni# # jython examples for jas. # $Id: polypower.py 1094 2007-05-24 20:56:35Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring from jas import Ideal # sparse polynomial powers #r = Ring( "Mod 1152921504606846883 (x,y,z) G" ); #r = Ring( "Rat(x,y,z) G" ); #r = Ring( "C(x,y,z) G" ); r = Ring( "Z(x,y,z) L" ); print "Ring: " + str(r); print; ps = """ ( ( 1 + x^2147483647 + y^2147483647 + z^2147483647 ) ( 1 + x + y + z ) ( 10000000001 + 10000000001 x + 10000000001 y + 10000000001 z ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; pset = f.pset; print "pset:", pset; print; plist = pset.list; print "plist:", plist; print; p = plist[0]; #p = plist[2]; print "p:", p; print; q = p; for i in range(1,20): q = q.multiply(p); print "q:", q.length(); print; q1 = q.sum( r.ring.getONE() ); #print "q1:", q1; print "q1:", q1.length(); print; t = System.currentTimeMillis(); q2 = q.multiply(q1); t = System.currentTimeMillis() - t; print "q2:", q2.length(); print "t:",t; print; print "Integer.MAX_VALUE = ", Integer.MAX_VALUE; jas-2.5/examples/nabeshima_cgbF2.py0000644000175000017500000000173211253240426017467 0ustar giovannigiovanni# # jython examples for jas. # $Id: nabeshima_cgbF2.py 2811 2009-09-13 18:59:35Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Nabashima, ISSAC 2007, example F2 # integral function coefficients r = Ring( "IntFunc(b, a) (x,y) L" ); print "Ring: " + str(r); print; ps = """ ( ( { a } x^2 y^3 + { b } y + y ), ( x^2 y^2 + x y + 2 ), ( { a } x^2 + { b } y + 2 ) ) """; #startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; #sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/syz.py0000644000175000017500000000346411505613454015373 0ustar giovannigiovanni# # jython examples for jas. # $Id: syz.py 3450 2010-12-26 10:21:33Z kredel $ # from jas import Ring from jas import Ideal # trinks 7 example r = Ring( "Rat(B,S,T,Z,P,W) L" ); print "Ring: " + str(r); print; ps = """ ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B**3 ), ( 99 W - 11 B S + 3 B**2 ), ( B**2 + 33/50 B + 2673/10000 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; #Katsura equations for N = 3: #r = Ring( "Rat(u0,u1,u2,u3) L" ); #print "Ring: " + str(r); #print; ps = """ ( u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 - u0, u3*0 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 - u1, u3*0 + u2*0 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 - u2, u3 + u2 + u1 + u0 + u1 + u2 + u3 - 1 ) """; #f = Ideal( r, ps ); #print "Ideal: " + str(f); #print; rg = f.GB(); print "seq Output:", rg; print; from edu.jas.gbmod import SyzygyAbstract; from edu.jas.gbmod import ModGroebnerBaseAbstract; from edu.jas.poly import ModuleList; s = SyzygyAbstract().zeroRelations( rg.list ); sl = ModuleList(rg.pset.ring,s); print "syzygy:", sl; print; z = SyzygyAbstract().isZeroRelation( s, rg.list ); print "is Syzygy ?", if z: print "true" else: print "false" print; zg = sl; for i in range(1,len(r.ring.vars)+1): print "\n %s. resolution" % i; sl = zg; mg = ModGroebnerBaseAbstract().GB(sl); print "Mod GB: ", mg; print; zg = SyzygyAbstract().zeroRelations(mg); print "syzygies of Mod GB: ", zg; print; if ModGroebnerBaseAbstract().isGB( mg ): print "is GB"; else: print "is not GB"; if SyzygyAbstract().isZeroRelation(zg,mg): print "is Syzygy"; else: print "is not Syzygy"; if not zg: break; jas-2.5/examples/getstart.py0000644000175000017500000000107310407615210016365 0ustar giovannigiovanni# # jython examples for jas. # $Id: getstart.py 802 2006-03-20 21:11:37Z kredel $ # from jas import Ring from jas import Ideal # trinks 7 example r = Ring( "Rat(B,S,T,Z,P,W) L" ); print "Ring: " + str(r); print; ps = """ ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B**3 ), ( 99 W - 11 B S + 3 B**2 ), ( B**2 + 33/50 B + 2673/10000 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; g = f.GB(); print "Groebner base:", g; print; jas-2.5/examples/ascm_demo.rb0000644000175000017500000000245311641155210016435 0ustar giovannigiovanni# # jruby examples for jas. # $Id: ascm_demo.rb 3784 2011-09-29 20:52:24Z kredel $ # require "examples/jas" # Raksanyi & Walter example # integral/rational function coefficients r = PolyRing.new(PolyRing.new(QQ(),"a1,a2,a3,a4",PolyRing.grad),"x1,x2,x3,x4",PolyRing.lex); puts "r = " + str(r); one,a1,a2,a3,a4,x1,x2,x3,x4 = r.gens(); puts "one = " + str(one); puts "a1 = " + str(a1); puts "a2 = " + str(a2); puts "a3 = " + str(a3); puts "a4 = " + str(a4); puts "x1 = " + str(x1); puts "x2 = " + str(x2); puts "x3 = " + str(x3); puts "x4 = " + str(x4); pl = [ ( x4 - ( a4 - a2 ) ), ( x1 + x2 + x3 + x4 - ( a1 + a3 + a4 ) ), ( x1 * x3 + x1 * x4 + x2 * x3 + x3 * x4 - ( a1 * a4 + a1 * a3 + a3 * a4 ) ), ( x1 * x3 * x4 - ( a1 * a3 * a4 ) ) ]; f = ParamIdeal.new(r,"",pl); puts "ParamIdeal: " + str(f); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; puts f.CGB(); puts gs.isCGBsystem(); #rs = gs.regularRepresentation(); #puts "regular representation: " + str(rs); rs = gs.regularRepresentationBC(); puts "boolean closed regular representation: " + str(rs); puts rs.isRegularGB(); rsg = rs.regularGB(); puts "regular GB: " + str(rsg); puts rsg.isRegularGB(); #ss = rsg.stringSlice(); #puts "regular string slice: " + str(ss); startLog(); terminate(); #sys.exit(); jas-2.5/examples/mkplotold.py0000644000175000017500000000670710373614370016556 0ustar giovannigiovanni# # read output of jas runnings and prepare input for gnuplot # import re; import os; exam = "kat_6"; runs = "t16"; #bname = exam + "_" + runs; bname = "k6seqpair-3" fname = bname + ".out"; oname = bname + ".po"; f=open(fname,"r"); print f; o=open(oname,"w"); print o; res = {}; resold = {}; for line in f: if line.find("executed in") > 0: print line, if line.find("sequential") >= 0: s = re.search(".*in (\d+)",line); if s != None: t = ('0', s.group(1)); res[ int( t[0] ) ] = float( t[1] ); resold[ int( t[0] ) ] = float( t[1] ); else: if line.find("-old") >= 0: s = re.search("(\d+).*in (\d+)",line); if s != None: t = s.groups(); t0 = int( t[0] ); if resold.has_key( t0 ): resold[ t0 ] = ( resold[ t0 ] + float(t[1]) )/2.0; else: resold[ t0 ] = float( t[1] ); else: s = re.search("(\d+).*in (\d+)",line); if s != None: t = s.groups(); t0 = int( t[0] ); if res.has_key( t0 ): res[ t0 ] = ( res[ t0 ] + float(t[1]) )/2.0; else: res[ t0 ] = float( t[1] ); # print "t = ", t, "\n"; print "\nres = ", res; print "resold = ", resold; ks = res.keys(); #print "ks = ", ks; ks.sort(); #print "ks = ", ks; s1 = ks[0]; st = res[ s1 ]; #print "s1 = ", s1; #print "st = ", st; kso = resold.keys(); #print "kso = ", kso; kso.sort(); #print "kso = ", kso; s1o = kso[0]; sto = resold[ s1o ]; #print "s1o = ", s1o; #print "sto = ", sto; speed = {}; speedold = {}; for k in ks: speed[ k ] = st / res[ k ]; for k in kso: speedold[ k ] = sto / resold[ k ]; print "speed = ", speed; print "speedold = ", speedold; print; o.write("\n#threads time speedup timeold speedupold\n"); print "#threads time speedup timeold speedupold"; for k in ks: o.write(str(k) + " " + str(res[k]) + " " + str(speed[k]) + " " + str(resold[k]) + " " + str(speedold[k]) +"\n"); print(str(k) + " " + str(res[k]) + " " + str(speed[k]) + " " + str(resold[k]) + " " + str(speedold[k])); f.close(); o.close(); #--------------------------------------- pscript = """ set grid set term %s set output "%s.ps" set title "GBs of Katsuras example on compute" set time set xlabel "#CPUs" set multiplot set size 0.75,0.5 set origin 0,0.5 set ylabel "milliseconds" # smooth acsplines plot "%s.po" title '%s computing time' with linespoints, \ "%s.po" using 1:4 title '%s-old computing time' with linespoints, \ "%s.po" using 1:( %s/$1 ) title '%s ideal' with linespoints set size 0.75,0.5 set origin 0,0 set ylabel "speedup" # smooth bezier plot "%s.po" using 1:3 title '%s speedup' with linespoints, \ "%s.po" using 1:5 title '%s-old speedup' with linespoints, \ "%s.po" using 1:1 title '%s ideal' with linespoints unset multiplot pause mouse """; #--------------------------------------- psname = bname + ".ps"; pname = "plotin.gp" p=open(pname,"w"); print p; pscript = pscript % ("x11",bname,bname,exam,bname,exam,bname,str(res[0]),exam,bname,exam,bname,exam,bname,exam); #pscript = pscript % ("postscript",bname,bname,exam,bname,exam,bname,str(res[0]),exam,bname,exam,bname,exam,bname,exam); p.write(pscript); p.close(); os.system("gnuplot plotin.gp"); cmd = "ps2pdf " + psname; print "cmd: " + cmd; #os.system(cmd); jas-2.5/examples/suzukiSato_ex1.rb0000644000175000017500000000222511773623314017454 0ustar giovannigiovanni# # jruby examples for jas. # $Id: suzukiSato_ex1.rb 3970 2012-06-30 16:18:21Z kredel $ # require "examples/jas" # Suzuki and Sato, ISSAC 2006, example 1 # integral function coefficients #r = PolyRing.new( QQ(),"b,a,z,y,x", PolyRing.lex ); #r = PolyRing.new( RF( PolyRing.new(QQ(),"a, b",PolyRing.lex) ), "z,y,x", PolyRing.lex ); r = PolyRing.new( PolyRing.new(QQ(),"b, a",PolyRing.lex), "z,y,x", PolyRing.lex ); puts "Ring: " + str(r); puts; #one,c,b,a,z,y,x = r.gens(); puts "gens: " + r.gens().each{ |f| str(f) }.join(","); puts; #f1 = x**2 - a; #f2 = y**3 - b; f1 = x**3 - a; f2 = y**4 - b; f3 = x + y - z; F = [f1,f2,f3]; puts "F: " + F.each{ |f| str(f) }.join(","); puts; startLog(); If = r.paramideal( "", list = F ); puts "ParamIdeal: " + str(If); puts; G = If.GB(); puts "GB: " + str(G); puts; terminate(); exit(); GS = If.CGBsystem(); puts "CGBsystem: " + str(GS); puts; bg = GS.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; terminate(); exit(); CG = If.CGB(); puts "CGB: " + str(CG); puts; bg = CG.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); jas-2.5/examples/rose_fac.rb0000644000175000017500000017641211653236772016316 0ustar giovannigiovanni# # jruby examples for jas. # $Id: rose_fac.rb 3820 2011-10-30 12:07:22Z kredel $ # require "examples/jas" # output gb of rose #r = Ring.new( "Mod 19 (U3,U4,A46) L" ); #r = Ring.new( "Mod 1152921504606846883 (U3,U4,A46) L" ); # 2^60-93 #r = Ring.new( "Quat(U3,U4,A46) L" ); #r = Ring.new( "Z(U3,U4,A46) L" ); #r = Ring.new( "C(U3,U4,A46) L" ); #r = Ring.new( "Rat(A46,U3,U4) G" ); rz = Ring.new( "Int(A46) L" ); puts "Ring: " + str(rz); puts; r = Ring.new( "Rat(A46) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( A46^34 + 347/70 A46^33 - 56411/58800 A46^32 - 441350327/6174000 A46^31 - 992593010489/3457440000 A46^30 - 217625706587/329280000 A46^29 - 373467217691021/355622400000 A46^28 - 38574512982739/31752000000 A46^27 - 968821009058023/952560000000 A46^26 - 5992612680961049/10886400000000 A46^25 - 13843426727931961/244944000000000 A46^24 + 1486519769228381881/5598720000000000 A46^23 + 61199280870444808261/167961600000000000 A46^22 + 513991046707657214269/1679616000000000000 A46^21 + 37908065080289396962277/201553920000000000000 A46^20 + 27223946509678338655459/335923200000000000000 A46^19 + 668594689016343141054373/48372940800000000000000 A46^18 - 36250135997129945800663817/2418647040000000000000000 A46^17 - 5712667240922865693346483691/290237644800000000000000000 A46^16 - 42053436689365696671983799179/2902376448000000000000000000 A46^15 - 561895388992743685886859196463/69657034752000000000000000000 A46^14 - 704377755966878925481768484749/193491763200000000000000000000 A46^13 - 2531676547158421516985730163481/1857520926720000000000000000000 A46^12 - 4750291847118917831874464404117/11145125560320000000000000000000 A46^11 - 1835783859800409552862056700927/16511297126400000000000000000000 A46^10 - 9916637291915563585725849353/412782428160000000000000000000 A46^9 - 252376016954713294866494065459/59440669655040000000000000000000 A46^8 - 178806028363626133639831815853/297203348275200000000000000000000 A46^7 - 31482408916666847417595615109/475525357240320000000000000000000 A46^6 - 3818476405879526813756500117/713288035860480000000000000000000 A46^5 - 896701239882765996997050397/3170169048268800000000000000000000 A46^4 - 4844358439974218651958787/760840571584512000000000000000000 A46^3 + 171452325388464998728627/730406948721131520000000000000000 A46^2 + 15230552381256429497/811563276356812800000000000000 A46 + 79792266297612001/259700248434180096000000000000 ) ) """; ps1=""" ( ( A46^33 * U3 + 129/28 A46^32 * U3 - 75613/29400 A46^31 * U3 - 871585543/12348000 A46^30 * U3 - 12095701697/46099200 A46^29 * U3 - 124924301563/219520000 A46^28 * U3 - 378293923381/444528000 A46^27 * U3 - 1617620272123/1764000000 A46^26 * U3 - 82886347203347/119070000000 A46^25 * U3 - 668049914090789/2177280000000 A46^24 * U3 + 99688309115142847/1959552000000000 A46^23 * U3 + 231138576685539839/933120000000000 A46^22 * U3 + 11659387634813949601/41990400000000000 A46^21 * U3 + 70151923964052383971/335923200000000000 A46^20 * U3 + 23176161047838396328367/201553920000000000000 A46^19 * U3 + 164454230781271289566939/4031078400000000000000 A46^18 * U3 - 55282700662490687816927/120932352000000000000000 A46^17 * U3 - 747149106093593978873861/50388480000000000000000 A46^16 * U3 - 841282928607636046387355983/58047528960000000000000000 A46^15 * U3 - 54661970877464131720410138953/5804752896000000000000000000 A46^14 * U3 - 830787778268485831652841532151/174142586880000000000000000000 A46^13 * U3 - 274531406380976793484077680017/139314069504000000000000000000 A46^12 * U3 - 750317990428317888436020594041/1114512556032000000000000000000 A46^11 * U3 - 1416119253746536814898928216649/7430083706880000000000000000000 A46^10 * U3 - 33046099809889641357330063959/743008370688000000000000000000 A46^9 * U3 - 25135248767946559916964025799/2972033482752000000000000000000 A46^8 * U3 - 38214637789543687723872942433/29720334827520000000000000000000 A46^7 * U3 - 3604383688017858128502121387/23776267862016000000000000000000 A46^6 * U3 - 10419538500903067530134609/792542262067200000000000000000 A46^5 * U3 - 268160889047530270882049141/356644017930240000000000000000000 A46^4 * U3 - 4494450124912371106208621/228252171475353600000000000000000 A46^3 * U3 + 19160001876330286653661/36520347436056576000000000000000 A46^2 * U3 + 4148034694905888017/81156327635681280000000000000 A46 * U3 + 11398895185373143/12985012421709004800000000000 U3 ) ) """; ps2=""" ( ( A46^32 * U3^2 + 149/35 A46^31 * U3^2 - 119419/29400 A46^30 * U3^2 - 17080619/246960 A46^29 * U3^2 - 32939303767/138297600 A46^28 * U3^2 - 29988193601/61740000 A46^27 * U3^2 - 3784045943831/5556600000 A46^26 * U3^2 - 2693634126319/3969000000 A46^25 * U3^2 - 21841275550799/47628000000 A46^24 * U3^2 - 21239300351867/145152000000 A46^23 * U3^2 + 100022001638857211/979776000000000 A46^22 * U3^2 + 296696864208881153/1399680000000000 A46^21 * U3^2 + 17088141121241394989/83980800000000000 A46^20 * U3^2 + 19261885997631012911/139968000000000000 A46^19 * U3^2 + 13468170505032365821223/201553920000000000000 A46^18 * U3^2 + 35088518623022364409189/2015539200000000000000 A46^17 * U3^2 - 99017698968245042551237/15116544000000000000000 A46^16 * U3^2 - 3789770743783848575384507/302330880000000000000000 A46^15 * U3^2 - 2933051673126807110607585563/290237644800000000000000000 A46^14 * U3^2 - 948072476821568942948806667/161243136000000000000000000 A46^13 * U3^2 - 18896655281197310848727704481/6965703475200000000000000000 A46^12 * U3^2 - 2845096388251912350859674973/2786281390080000000000000000 A46^11 * U3^2 - 39111610674783351035074010869/123834728448000000000000000000 A46^10 * U3^2 - 1486938573940216107905934971/18575209267200000000000000000 A46^9 * U3^2 - 2445791954945323169329394873/148601674137600000000000000000 A46^8 * U3^2 - 333946045138720738819094237/123834728448000000000000000000 A46^7 * U3^2 - 406526799915645826522761061/1188813393100800000000000000000 A46^6 * U3^2 - 6322467405069477857023283/198135565516800000000000000000 A46^5 * U3^2 - 490026291814312040719379/247669456896000000000000000000 A46^4 * U3^2 - 169501103784936018875857/2853152143441920000000000000000 A46^3 * U3^2 + 2012646248526699378523/1826017371802828800000000000000 A46^2 * U3^2 + 5217570099427357/37572373905408000000000000 A46 * U3^2 + 1628413597910449/649250621085450240000000000 U3^2 ) ) """; ps3=""" ( ( U3^4 + 36097228800000000000000000/282475249 A46^33 + 1161224847360000000000000000/1977326743 A46^32 - 4677045387264000000000000000/13841287201 A46^31 - 874485621920563200000000000000/96889010407 A46^30 - 22660530808584929280000000000000/678223072849 A46^29 - 48947976962992465920000000000000/678223072849 A46^28 - 212357741794443264000000000000/1977326743 A46^27 - 33417694635162617446400000000000/290667031221 A46^26 - 1195585718651671592960000000000/13841287201 A46^25 - 4622243456144475926528000000000/124571584809 A46^24 + 57492745364488210585600000000/7626831723 A46^23 + 5064235904207031314222080000000/160163466183 A46^22 + 796549541441999106994688000000/22880495169 A46^21 + 1776805509375610240638745600000/68641485507 A46^20 + 6571948331935947500408320000/466948881 A46^19 + 15900562307775474505007648000/3268642167 A46^18 - 781823011269699906939632000/4202539929 A46^17 - 23911885581267405621130949120/12607619787 A46^16 - 66484142665897834547281936/36756909 A46^15 - 31344755225898717841650588049/27016328115 A46^14 - 748245898727397783769699627/1286491815 A46^13 - 61180345995024957255947775667/257298363000 A46^12 - 1772332138625205728147155697/22054145400 A46^11 - 1763442424064055410851226129/78414739200 A46^10 - 72564573592100205725791837/14002632000 A46^9 - 65329613048147169962793719/67212633600 A46^8 - 87361765982805204782291/600112800 A46^7 - 6483564254536224014425081/384072192000 A46^6 - 23648026104539505065429/16460236800 A46^5 - 880685511246977438581/10973491200 A46^4 - 31439956654789887473/15676416000 A46^3 + 17918243525346457327/300987187200 A46^2 + 10074090036167/1866240 A46 + 34829612499283/382205952 ) ) """; ps4=""" ( ( A46 * U4 + 7/20 U4 + 2806378846741861368786614566878031251136601782233486293371124444033709909300049715978016727056150885946954243402645730462178807446021415693833183139081658586984935909957265108287928306576671117507805428087796888020739324547730219269915178825763993883433817341952000000000000000/193099928700513998070936429904026968056396066087989232333196930214044975387024916636846108968424103894255784064885243976305160746405290836679402752295622754790839675018341679885489238996414850488675112243144046216420956878738117538991288033099828416943500600350187 A46^32 * U3 + 140608368210259054916983904673796347993009087108223449480869140637168687474157820242084293427769280716150829987371903694486407125016157557573489507333502558345102130864385866957396552184077632209367448052303724048297487583320428452817989972383673573195382911926272000000000000000/1351699500903597986496555009328188776394772462615924626332378511498314827709174416457922762778968727259790488454196707834136125224837035856755819266069359283535877725128391759198424672974903953420725785702008323514946698151166822772939016231698798918604504202451309 A46^31 * U3 + 2973132530031750926781836728171190368295908349443863657109054185698567452354483691980282671132312007156981877065422976124734148815655910511834380182331303177950358622308259910423832682100194502857004946063777788209711503282994815361158167402207667989232295462169477120000000000000/28385689518975557716427655195891964304290221714934417152979948741464611381892662745616378018358343272455600257538130864516858629721577752991872204587456544954253432227696226943166918132472983021835241499742174793813880661174503278231719340865674777290694588251477489 A46^30 * U3 - 738219222373037292445012084441369194910728746958545194778441077198902948054263364937417682200010729210575746685991736931724571115099030702915394756575817790642985569814303481715585979651308619587706574566955474220298898070223241914619143731590342509740953174566721552384000000000000/596099479898486712044980759113731250390094656013622760212578923570756839019745917657943938385525208721567605408300748154854031224153132812829316296336587444039322076781620765806505280781932643458540071494585670670091493884664568842866106158179170323104586353281027269 A46^29 * U3 - 26263613198277033357242907881790564317638488547844618743001644843010275951255995601618105986940603997061861718415452159942810394664057894925733725044191873926510994765442061292542368154720543459005227757920995136654748098710382908816433885918895473973271287136201940664320000000000000/4172696359289406984314865313796118752730662592095359321488052464995297873138221423605607568698676461050973237858105237083978218569071929689805214074356112108275254537471345360645536965473528504209780500462099694690640457192651981900062743107254192261732104472967190883 A46^28 * U3 - 9560261987467874294850640971728702760731659080417859619462176031496681069887590878558384729317157715276514804678872739436230630658282680026803340746414284932116802254277874675348065517256502425989246849745315895036906790401640417642341755791726718494097465403286844184985600000000000/596099479898486712044980759113731250390094656013622760212578923570756839019745917657943938385525208721567605408300748154854031224153132812829316296336587444039322076781620765806505280781932643458540071494585670670091493884664568842866106158179170323104586353281027269 A46^27 * U3 - 144636713736027890114035034090555770840107473490985685648308419164337400894146263765715981457017308677715082713471432001864714782421560684446718632104959754377888118909536279270581334669935787514862899283922492256748522286708189406470339423887947462918232309558821679529984000000000000/5364895319086380408404826832023581253510851904122604841913210312136811551177713258921495445469726878494108448674706733393686281017378195315463846667029286996353898691034586892258547527037393791126860643451271036030823444961981119585794955423612532907941277179529245421 A46^26 * U3 - 24532425560872733727048401118804283865911311477564921900335177229012489937286467620463606284515609505035616190873825110294676684892007020876691541110492442185186251334711679953191506232457944676021905960044901546391272864711217070545467913465760834235337077332640608895369216000000000/766413617012340058343546690289083036215835986303229263130458616019544507311101894131642206495675268356301206953529533341955183002482599330780549523861326713764842670147798127465506789576770541589551520493038719432974777851711588512256422203373218986848753882789892203 A46^25 * U3 - 61280378855985472962083715267099870468639547774190782208008687497788816915947177474302623147240238616774447758611668598585355022788830824893247197811650042416494226679277235085459349523493402070913785423068849805945203419134911827923486496461119063853055966658119121257129574400000000/2299240851037020175030640070867249108647507958909687789391375848058633521933305682394926619487025805068903620860588600025865549007447797992341648571583980141294528010443394382396520368730311624768654561479116158298924333555134765536769266610119656960546261648369676609 A46^24 * U3 - 1484357436021657507567420650984058019197004585757942514498995263423808522091214018761612749478663033895612373062807866818414484967623858841053321992327465827514651989711202442802087572810894125998644840666538477463088224296505304638389800637458850650417392471695314042172211200000000/109487659573191436906220955755583290887976569471889894732922659431363501044443127733091743785096466908043029564789933334565026143211799904397221360551618101966406095735399732495072398510967220227078788641862674204710682550244512644608060314767602712406964840398556029 A46^23 * U3 - 142706740914560864457369678713491100078718980040431434176679594896408407693192038718320939423503224607224793619606860312440116490102586591426353170601317496666073657735251911434293391435267804199376695206269942247915428218586358462081096742118453704497075161839492889751191552000000/2956166808476168796467965805400748853975367375741027157788911804646814528199964448793477082197604606517161798249328200033255705866718597418724976734893688753092964584855792777366954759796114946131127293330292203527188428856601841404417628498725273234988050690761012783 A46^22 * U3 + 3437067913738929851828191102489541091985420513352095924549529468703404236611368673420787140580385095687914414418203044807769960408456154049568142240000401501441029724428786621410870408162134547736165823446770365996810358019535793543622855984068400287198402234509017467116735692800000/422309544068024113781137972200106979139338196534432451112701686378116361171423492684782440313943515216737399749904028576179386552388371059817853819270526964727566369265113253909564965685159278018732470475756029075312632693800263057773946928389324747855435812965858969 A46^21 * U3 + 12665325755293011964582773351828201837497408957482566179025807264260205331500166852839160281570134088487784028319208757397082649585467393387792231298887791806004696105674306391612545456300491907001838309111269128096161395643695348999989978496685257886403350330750962195611697479680000/1266928632204072341343413916600320937418014589603297353338105059134349083514270478054347320941830545650212199249712085728538159657165113179453561457811580894182699107795339761728694897055477834056197411427268087225937898081400789173321840785167974243566307438897576907 A46^20 * U3 + 472460708046707276929317308260575825818443603966144032149144933738614980186931958850077619729999743406167265787440681567111099352622569281813602576458470534069879413676204407012264193237661238006825286040265059435939142815940360874733243831244058419301704863623227097616300687360000/60329934866860587683019710314300997019905456647776064444671669482588051595917641812111777187706216459533914249986289796597055221769767294259693402752932423532509481323587607701366423669308468288390352925108004153616090384828609008253420989769903535407919401852265567 A46^19 * U3 + 49390047765871082949860891586805882007616506646541386751626133624251152479425727198070508507708042448289532261339277046519001543624931425618731092311111454034423497441761556818193037978230663070411942523132669576228611039810197751659696742852563815776238111135652689883724583731200/11081008444933577329534232506708346391411206323060909795960102558026376823739975026714408054884815268077657719385236901415785652978120523435453890301559016567195619018618132026781588020893392134602309720938204844541730887009336348454709977712839424870842339115722247 A46^18 * U3 + 129068221133437408101386032010227938242790415417408002956440388834868112181036866325987181792617952620211570225145421401636968642407417865428308813969801472080155460044151903911373059980563777215433387329713871436510348502082703071326443785803142144287247590693723735936473435504640/77567059114535041306739627546958424739878444261426368571720717906184637766179825187000856384193706876543604035696658309910499570846843664048177232110913115970369333130326924187471116146253744942216168046567433911792116209065354439182969843989875974095896373810055729 A46^17 * U3 + 12783978249076530856412299581616499812448814070864143616141639515320829793115590125926560504059268257844159130491162326200688965203538567110804552270764562224831755709762903109729453955480299083281536877866482795304181415809809747877796974966623540360991948948407257749615539560448/232701177343605123920218882640875274219635332784279105715162153718553913298539475561002569152581120629630812107089974929731498712540530992144531696332739347911107999390980772562413348438761234826648504139702301735376348627196063317548909531969627922287689121430167187 A46^16 * U3 - 1810442970097170462121122653290427291604967782620000014180906504389275928944428879269826615110693111930022066722356506712480414023024345146923757896554522544082287653722476697782328057603177530844114988866728376051365543251948667665657844199641256470495166203610372754104633985024/3392145442326605304959458930625003997370777445834972386518398742252972497063257661239104506597392429003364607975072520841567036625955262276159354173946637724651720107740244497994363679865324122837441751307613727920938026635511127077972442156991660674747654831343545 A46^15 * U3 - 270639555533122280020486247514756020301825934358369840608010596756492667631965814059407427090369596575058017999403434671889521831726503036761805006306129032875224481365310003762906407037966481686173976406974516397321267076580148872307324693442737067092534607150395172934720327272832/498645380022010979829040462801875587613504284537740940818204615111186957068298876202148362469816687063494597372335660563710354384015423554595425063570155745523802855837815941205171460940202646057103937442219218004377889915420135680461948997077774119187905260207501115 A46^14 * U3 - 1435948341205771592618056822768583583847960643508655403782679773815551216480844799951609196462939014609390424305428592870359320910647059517420727369800472093539593358295705161364370776721823709904982580674821197915654942789644804770077615722633391761110116425814824933514747954464/4038268383722149172570784441220242854012830292660681412521903264586872020313401977665600603092133844051624533303657762906627424554708645566856374016603140148394904890166957735707575809363481098616002084890016342763021460280370389378538621615466262708032922418266125 A46^13 * U3 - 24031158593232439577778424195027450454772002899626269270999618447601656149784654839122276071971243436018537991067130120319932291937910513510530154436517553834823319688270120213094719167314095473720221761127649325967639043315665428464820334187025317629951306324495868404822629086296/134236911348351843098270045621466866730124986864072399717750703996191750825995749157075115524896810946741187375897970359936383987082400454395753337285576744128805506776152891566359869240901645564547003977625417625011994772636432792658457195911102149817275285411208125 A46^12 * U3 - 55342608527391903114377714171300343766958416997314322747423256743530874483390328684036373961531616542340488099823707750319655515404839491476271584066825595064560837447788507941963050626463472192927052092190464771899480038023820496414639119032434176994304931597908860375406025786078/763232724523486193615878259390625899408424925312868786966639717006918811839232973778798513984413296525757036794391317189352583240839934012135854689137993488046637024241555012048731827969697927638424394044213088782211055992990003592543799485323123651818222337052297625 A46^11 * U3 - 2029624852259950049380302093920186872530375028355631473518046159913882812276759452807058944803805569580457303136641881139738479285051882346521262597896200616610534853804143612625821026733823701571937719332556063675018717208715246680768950536936393557501213975920703061913308587814/84803636058165132623986473265625099934269436145874309662959968556324312426581441530977612664934810725084115199376813021039175915648881556903983854348665943116293002693506112449859091996633103070936043782690343198023450665887778176949311053924791516868691370783588625 A46^10 * U3 - 1168942911153266036621765763524847385999721254478313573544681811727225087201633669304728449000690805131434160354788200355429868149616777944697604839445821146293319865569802164294050791015324448927695484221067203620046595245414313118308514802029950573572440600781377894978809819943/181722077267496712765685299854910928430577363169730663563485646906409240914103088994952027139146022982323103998664599330798234104961889050508536830747141306677770720057513098106840911421356649437720093820050735424335965712616667522034237972695981821861481508821975625 A46^9 * U3 - 101409764297139370497431870913772400890980479461654448912068336828050482388546012701358058370032729748116854879439321035194274795413256750973689666942448462456840973308098467386964329640348557236019188613852479460195591937286545711022988218130783801374434056440021146855389791263/72688830906998685106274119941964371372230945267892265425394258762563696365641235597980810855658409192929241599465839732319293641984755620203414732298856522671108288023005239242736364568542659775088037528020294169734386285046667008813695189078392728744592603528790250 A46^8 * U3 - 3322794676291853666085201130675181837616673614933545069242421946525758427676251695684072633966150401809622984292825237098582373428490919709859723984671293905443481868170729806447368393045191340333060166403807452609937752781689646834959249508572627032878032237058297511762260717/13845491601333082877385546655612261213758275289122336271503668335726418355360235351996344924887316036748426971326826615679865455616143927657793282342639337651639673909143855093854545632103363766683435719622913175187502149532698477869275274110170043570398591148341000 A46^7 * U3 - 235997802096027015525218011390431135161602429335194555350491794738198772970078394908866958050373633238495091699843397584952514894044850979218568026142058202580747771909113137749719827302612618129281900176792733050978935129822521807364852652110897499832909022097494923166043147/7417227643571294398599399994077997078799076047744108716876965179853438404657268938569470495475347876829514448925085686971356494080077104102389258397842502313378396737041350943136363731483944875008983421226560629564733294392517041715683182559019666198427816686611250 A46^6 * U3 - 3496748794132449388555216753002710407113019869328151832331519672134490805457467271923368355368145123271002659562187642206698039955131848140898636455957544259518289841694390481218777439807140629994396001816472151472171553970751649445797629489197230923775536860056783627934479/1130244212353721051215146665764266221531287778703864185428870884549095375947774314448681218358148247897830773169536866586111465764583177767983125089195047971562422359930110619906493520988029695239464140377380667362245073431240692070961246866136330087379476828436000 A46^5 * U3 - 25797731568499728113711563609522696636972574369245543976139702215108120141166264492184554278639511568603311186805558250985505155379498427020368472760296798230482403566780044258141402965693251712985897771176010862913999745411179857703742819398871451136186089552354116699661/129170767126139548710302476087344711032147174709013049763299529662753757251174207365563567812359799759752088362232784752698453230238077459198071438765148339607133983992012642275027830970060536598795901757414933412828008392141793379538428213272723438557654494678400 A46^4 * U3 - 105307750747592845167925795351809474019566402815312738506184953133174877999878727791254675413428352747128321422294719175016172361719591143541377238760546940146607913162164819516842775340285454038918138509577296566880300576934730064221978046439482447941555635234543414413987/16607670059075084834181746925515748561276065319730249255281368099496911646579540947001030147303402826253839932287072325346943986744895673325466327841233357949488655084687339721075006839007783276988044511667634295935029650418230577369226484563635870671698435030080000 A46^3 * U3 + 6729992771983469644834688420302244188161700009523433301108672306478446515336817887911228386552702182506838452635857560083522640089937561680000956097567263329228552440470166784211722333574861459688985916960390707820563713605127900163322847651117899308325942825648612997/67786408404388101364007130308227545148065572733592854103189257548966986312569554885718490397156746229607509927702336021824261170387329278879454399351972889589749612590560570290102068730644013375461406170071976718102161838441757458649904018627085186415095653184000 A46^2 * U3 + 97004104716134687567531815774189859076177884454360758941608137811927278665332561915062791777635759119435458822688898910056883442317958132684946302161704171063308484365878439710058473575123783245727688981281817771384031307613137609700123391407537243830931947114431/6831585629064056574855845836052158745080934515857178544035198543609673601669897191808363859627789995425297044867960294464526195050373321126677188143307925380675194012654126509458510328107232388557460939286669359345141026801890396437380097619257766330571494400 A46 * U3 + 91815250260603771367686439814867337622922814376622703580092567517752668189839523750475603039746288206705982958930474905045662465449513750706031249185792777351062825505761724720085638243587008740273119957261765515541418363044444151757419729917247863640658968103/351338689494722909564014928711253878318448060815512039407524496528497499514451855578715855638000628336158133736066529429604204316876342229371969675941550448149009977793640791915009102588371951411526562591885852766321538521240077531065262163276113697000819712 U3 ) ) """; ps5=""" ( ( U3^2 * U4 + 535179163636213160230552332612905761790726203364450534489129686242659247983859225063689303002742332435127911688744222034136908867349929123331100864371658990936252805314758914346647230739008414163809378439226935298947238851749778443095061790353887385009084423995392000000000000000/348416638018627423852659631690165992696423968578095238206531661082875150589988624585082662615359891459868853047741275214579945040097279766315202366058735323894271720291427837740051083562531195231732794190712907389828879861536476746186614041056457073638389583231854077 A46^31 * U3^3 + 117444957438518475167713581434975737067164998391805610491814809960560346257088363610575217412650923824342320317819214071400331125353389211274396241076281078058047842081052040344628591911420714970389327499109713526665438238583003654833271274497439548231330310580181401600000000000000/2438916466130391966968617421831161948874967780046666667445721627580126054129920372095578638307519240219081971334188926502059615280680958364206416562411147267259902042039994864180357584937718366622129559334990351728802159030755337223306298287395199515468727082622978539 A46^30 * U3^3 + 2401741581776741318484092416102407292900015435135593836159021006355478379624893489598800836632769384261155218893078011625298104568085745627327942804937416501911688374548247994274079800109905304371024073616832343444568942958320613360649846757743965134232833554270042193920000000000000/17072415262912743768780321952818133642124774460326666672120051393060882378909442604669050468152634681533573799339322485514417306964766708549444915936878030870819314294279964049262503094564028566354906915344932462101615113215287360563144088011766396608281089578360849773 A46^29 * U3^3 - 805568218873790937813389084592233191792825630736851320718859307972639139165702967980087508722852747263747190017939561005107936647865901266983449666943346565871280018184856673037268657368899455757140347277745038838145391480304288946439289988670652938164442307992695603200000000000000/2072374107058772364996455265949022002801273200386473989101277914764615780098834073399133293821996117411589883156796371074004412984162432829701405980777102013220841619536874248754407890091587282621115868336668102336034204494341240299572403747093030802161288330321259221 A46^28 * U3^3 - 7685682775116980037756417525104129020857901100253508944433808002299072796987780826355035229956095427761674994214377901743588098560205258976689072899389795364550488078379086807213438803727723516868672038614031636269842625366221371250239578203300336002844575259786307614801920000000000000/2509645043648173334010707327064265645392341845668020000801647554779949709699688062886350418818437298185435348502880405370619344123820706156768402642721070538010439201259154715241587954900912199254171316555705071928937421642647242002782180937729660301417320168019044916631 A46^27 * U3^3 - 1034113844705967884541016548705263783711258150109052467551058076026319678448759166131211515280654219796468782344958028728719356943011812509405877602376788836215237969187146349036450163464263286874467724055879617971867571915156566751269616939474200904886354631269920338765414400000000000/119506906840389206381462253669726935494873421222286666704840359751426176652366098232683353277068442770735016595375257398600921148753366959846114411558146216095735200059959748344837521661948199964484348407414527234711305792507011523942008616082364776257967627048525948411 A46^26 * U3^3 - 48658714056579159584588250657320626399886844717677219117243540154602424522685502681521979204132079896072758913281262740708279626890869807641530459145331943833017069929236863886983924086820489878464574416932681640220499275442882030223770711661291180467191894819368336275978321920000000000/3226686484690508572299480849082627258361582373001740001030689713288506769613884652282450538480847954809845448075131949762224871016340907915845089112069947834584850401618913205310613084872601399041077407000192235337205256397689311146434232634223848958965125930310200607097 A46^25 * U3^3 - 8255947206923045970115261594812428132415296386179673138598668698030130733176457946142061749654776338102806089384084736737962150165972226111226766639416349566788039796025933969548991539844303719591225974525365272074129459969218772790071341578178550260218707253120429402938146816000000000/460955212098644081757068692726089608337368910428820000147241387612643824230554950326064362640121136401406492582161707108889267288048701130835012730295706833512121485945559029330087583553228771291582486714313176476743608056812758735204890376317692708423589418615742943871 A46^24 * U3^3 - 19945713493372992010989573088745323542756396319972931197979116120090053547915047057950693601445545496940530403318628583782260656315550176840007325651552659987878417938292973350492923084265613272190430226035072662253316611695490659970858884921554483178528771682266082834119655424000000000/1382865636295932245271206078178268825012106731286460000441724162837931472691664850978193087920363409204219477746485121326667801864146103392505038190887120500536364457836677087990262750659686313874747460142939529430230824170438276205614671128953078125270768255847228831613 A46^23 * U3^3 - 435093775488421369600147732183313564461463032259212791823425518543075036047179553289353390602878450300140400400876508808029170501403708143242207930225443742617112912856658164191471704385406656699565008229508861688289615831997614509046870265598882388184233731177202498351136768000000000/65850744585520583108152670389441372619624130061260000021034483944663403461507850046580623234303019485915213226023101015555609612578385875833573247185100976216017355135079861332869654793318395898797498102044739496677658293830394105029270053759670386917655631230820420553 A46^22 * U3^3 + 1666712214493918375843073715679404854923553599857383781647492939009113706816140218151303957915155518916011997458056804212971047568027330977305056462875462122879154305439206460319912215754500114817599379012537086490342649170430864147520080485377840240561213239361225941393442471936000000/1777970103809055743920122100514917060729851511654020000567931066505911893460711951257676827326181526119710757102623727420001459539616418647506477673997726357832468588647156255987480679419596689267532448755207966410296773933420640835790291451511100446776702043232151354931 A46^21 * U3^3 + 1284088025543201778701542120995051734041815978306710257005722604826526562109618762971947126682732875656141515493855498879095407124008034223158582017519436364169634168807052804122297828912887489492802203539147042679430553728949689548527311377444129568517124121118716963986204576972800000/253995729115579391988588871502131008675693073093431428652561580929415984780101707322525261046597360874244393871803389631428779934230916949643782524856818051118924084092450893712497239917085241323933206965029709487185253419060091547970041635930157206682386006176021622133 A46^20 * U3^3 + 4254014381230883330619305014989375799554837810367142599761760649672291739447040860678177727995158715416431102910496713847267271580162773653334863631889973825919344031375754538234961810569091573254261817527160589941054559827804400510444074230128005539082809168028853708352942800568320000/761987187346738175965766614506393026027079219280294285957684742788247954340305121967575783139792082622733181615410168894286339802692750848931347574570454153356772252277352681137491719751255723971799620895089128461555760257180274643910124907790471620047158018528064866399 A46^19 * U3^3 + 745516437593004300883570660646246938247823802410590380979420190673989967797085587628924839737460064182360717893802831288295892815613347860630889607237862285660785165032805451166314560759396503899171227181213064059364949918934022222627542591929187087049764507673930916328360804352000/182337206830997409898484473440151477871997898846684442679512979848826981177388160317677861483558765882443929556212052858168542666353852799457130312172877280056657633950072429082912591469551501309356214619547530141554381492505449783180216536920428719800707829272090181 A46^18 * U3^3 + 100659132205313930529625050503119312070810564089441017863641173372860790994172383194397174444036783482169409680952402366953488358200797270823652786371161310119627780987982282462009952616082069316251196025335382901954198189565730812891991210118588783206461023328312986396596201321267200/46652276776330908732597955990187328124106890976344548119858249558464160469814599304137292845293392813636725405025112381282837130777107194832531484157374744083067688914939960069642350188852391263579568626229946640503413893296751508810823973946355405309009674603759073453 A46^17 * U3^3 + 31840686398285739366370901635863389542030022459808048577847041429885472147377770155737274410841071887893024815380774859603070679264257251115288897069582531630147721152091634280145756325435744966628395355333013175929902375331398691019183890365382567317614167783255315159428074691624960/46652276776330908732597955990187328124106890976344548119858249558464160469814599304137292845293392813636725405025112381282837130777107194832531484157374744083067688914939960069642350188852391263579568626229946640503413893296751508810823973946355405309009674603759073453 A46^16 * U3^3 - 13828528445690452987305064022092959448876463072880660857470397879545100109724829810338301593203092974158319894346856522064022294423111854351244636838712011841678369295025322372766599272518628248765532325453911764768121252460833528916104395772737785984090513826255228303325154466127872/139956830328992726197793867970561984372320672929033644359574748675392481409443797912411878535880178440910176215075337143848511392331321584497594452472124232249203066744819880208927050566557173790738705878689839921510241679890254526432471921839066215927029023811277220359 A46^15 * U3^3 - 33610752624740506302912013993814981775024007915215935211163351291344044163786135068634072771353605827815789041344588941769903151215762730402577426802629600007206325972644549999333779030662823436337121030730985687375264611402234685156485004573481758060166931327023163395774356304113664/99969164520709090141281334264687131694514766377881174542553391910994629578174141366008484668485841743507268725053812245606079565950943988926853180337231594463716476246299914434947893261826552707670504199064171372507315485635896090308908515599333011376449302722340871685 A46^14 * U3^3 - 440458073572699732774489360478761084951279455207275623193025208264809731530938512938804891081421616585621742589211241713795773058743821672163780025900276255331592774249357759549304463610560721287707008918417645237050696497113058739332361880620366592325582276896858182823540813585536384/1499537467810636352119220013970306975417721495668217618138300878664919443672612120490127270027287626152609030875807183684091193489264159833902797705058473916955747143694498716524218398927398290615057562985962570587609732284538441354633627733989995170646739540835113075275 A46^13 * U3^3 - 6996214565149446678253694413083490264717525678004855498090489246100920822500988095095030219926214938120572903557109272761916802518646083631510656210142715036721759509042764836946925860045014447394355560737664073350497528956878636493202886375323607681733788379035427399732074066732736/39670303381233765929079894549479020513696335864238561326410076155156599038957992605558922487494381644248916160735639780002412526171009519415417928705250632723697014383452346997995195738820060598281946110739750544645760113347577813614646236348941671181130675683468599875 A46^12 * U3^3 - 52720968043649456846417369507000756940194406072631641273516890434262149856954069120692268860993592166109579882175849063584157212108249084107098488501914404760103187541211164434424785557474548152913921719930232076831591869022033755032242197725738904601218545055852510881677688297536184/642658914775987008051094291701560132321880641000664693487843233713536904431119480210054544297408982636832441803917364436039082923970354214529770445025060250123891633011928021367522170968884981692167526993983958823261313836230760580557269028852855073134316946072191317975 A46^11 * U3^3 - 560521169089131499065785274068646758491670755018612288505863123339558028653018546907577396130067320298156818038178669090843281588218301520813686567954392296875641272535840128326520911631312236737399924421960962557597703529589857661762970259131745451459708625790997896125768972935928/18361683279313914515745551191473146637768018314304705528224092391815340126603413720287272694211685218195212622969067555315402369256295834700850584143573150003539760943197943467643490599110999476919072199828113109236037538178021730873064829395795859232409055602062609085 A46^10 * U3^3 - 4197422272012614585634130742038816517252315110924247183388171916467791237166762578598405913589164581591069795124771062594877274429670076994003284050036156103051961891924620808585164846207763280779766288975531255051754977759088637973954664073448069462858272840556659782286260872647812/459042081982847862893638779786828665944200457857617638205602309795383503165085343007181817355292130454880315574226688882885059231407395867521264603589328750088494023579948586691087264977774986922976804995702827730900938454450543271826620734894896480810226390051565227125 A46^9 * U3^3 - 4106654994410345218350715474180779469031652386352768990088763404863224321126834681787202405252012606245929498654531112676402813452159609458415502006915204469860173111678951294367642751272844986752033113410832855341088770049302498143130605877209294548098061602991987492963051239744/1873641150950399440382199101170729248751838603500480155941233917532177563939123849008905376960376042672980879894802811766877792781254677010290875933017668367708138871754892190575866387664387701726435938757970725432248728385512421517659676468958761146164189347149245825 A46^8 * U3^3 - 10861509873129061552037235599451402972763702999367178857883272454799214845428691114656489287350714907124422743117360275388527760856063819431352503904308954737409956132586217400390831701855393788768594250812823801249588131220343764676215839452260384917296536245871426396362711599029/26230976113305592165350787416390209482525740449006722183177274845450485895147733886124675277445264597421732318527239364736289098937565478144072263062247357147913944204568490668062129427301427824170103142611590156051482197397173901247235470565422656046298650860089441550 A46^7 * U3^3 - 1124486478466758794641936904982948237084283820279761242642612077110909965390094116007619021675739939209813695144499796429672334602667319111431706473000996398421642195295148270757273990731860799515046565486145747844982383328993615581180179952020178830599171027345719008701601415523/18736411509503994403821991011707292487518386035004801559412339175321775639391238490089053769603760426729808798948028117668777927812546770102908759330176683677081388717548921905758663876643877017264359387579707254322487283855124215176596764689587611461641893471492458250 A46^6 * U3^3 - 13634406027258739162572410843253056158384774240138183339467954043156022885658076072571122964861139837559116738714581975870696472208621260986499059519385686842525264750880868543070223665506121563803996657564834448591138230910580178478122708511083518804685049985931165670484826297/2141304172514742217579656115623690570002101261143405892504267334322488644501855827438749002240429763054835291308346070590717477464291059440332429637734478134523587282005591074943847300187871659115926787151966543351141403869157053163039630250238584167044787825313423800 A46^5 * U3^3 - 275610949766603790350543874491973128402944565236452331621829945535128551051089218509229304570354572863614983692536142099515347666278429222971179578469228299012270654864962841491251938427241318189542247237765029951590277176611163743592667595081103539096197325545120410752450853/611801192147069205022758890178197305714886074612401683572647809806425327000530236411071143497265646587095797516670305883062136418368874125809265610781279467006739223430168878555384942910820474033121939186276155243183258248330586618011322928639595476298510807232406800 A46^4 * U3^3 - 57091321219446868547123718685194170669561742150029307684083906984399449382980015516422277491250022223527057750658840237853760266613003361978501494129695368914676980282464037464506358216208278225667602395223784571111874119085762583994232092883441120694085505220223346971423259/3496006812268966885844336515303984604085063283499438191843701770322430440003029922348977962841517980497690271523830319331783636676393566433195803490178739811467081276743822163173628245204688423046411081064435172818190047133317637817207559592226259864562918898470896000 A46^3 * U3^3 + 2096019020134284361588278549962801625099190206781628224639171740828930915568065430755481920106589988497979688771818295815492190569468006618308754762164717538084498525703860854191800473065932573287633087040724218118612995977781646506334852358874110328385808128162955638079/14269415560281497493242189858383610628918625646936482415688578654377267102053183356526440664659257063255878659280940078905239333373034965033452259143586693108028903170382947604790319368182401726720045228834429276808938967891092399253908406498882693324746607748860800 A46^2 * U3^3 + 144724249725887284436232581781817786550817001839619049910175696311756292310832604781793691600419996522748911371809754829004775699207861014225518336712102081581627568566107942347420832194840104563187671858359656942129120425684588448408665047033556866808539561866776501/4314260184514436127964380909564205783497694829005739203533961800265235707347901241580178583419276511944332172118198058625922700944228258513515422265634676676652729605557958459498206914038519040580512540841853144915778977442507150190146154648188267067194741571840 A46 * U3^3 + 34523752399540034716636145000935730218516677827634880256328110824710605643763228906652973946423825292328221117422519494495751855171799684110699308767573648503790821554402991388888863972166596620407299382152069987750344858727174998460595722071373991687451348757265/52827675728748197485278133586500478981604426477621296369803613880798804579770219284655247960236038921767332719814670105623543276868101124655290884885322571550849750272138266850998452008634927027516480091941058917336069111540903879879340669161488984496262141696 U3^3 ) ) """; ps6=""" ( ( U3 * U4^3 + 41822330490195068041017320363097809729090890052699731534033293673080362045613806875773900749189755394694179768458994485940692483615892634922652342251410719603257617491056399521754985563535628528166060660260046980535041591378337983957604595139759378622893247460686601951641600000000000000000/356450080441422916364430404818046149990025416021600380113859661592463002937141992302140913567282244477259049192463045797202514832886802745887131987012951584257301943346187289394823441396232477000190857226368174895516164344503923290523438801001095804385269931852430936453389 A46^33 + 454125157206527413523601969987620494847328162420135984302287459170369832878272220272886380031914311891233003000504439954565744301327926677967038692247319542412616194634678505272858478303439697166808691979442683766268105374119197842122316902319990742401536311538368167952547840000000000000000/831716854363320138183670944575441016643392637383734220265672543715747006853331315371662131656991903780271114782413773526805867943402539740403307969696887029933704534474437008587921363257875779667112000194859074756204383470509154344554690535669223543565629840989005518391241 A46^32 - 14740085336461820800966266074682241729581054272188710537515241908189807762813569534360041532382661570106035157724159025403425541339461211407295309969242948500584368294316900034869383665586431029071989963112162284745485647807851469068632801796651905968443260670347124770482847744000000000000000/52398161824889168705571269508252784048533736155175255876737370254092061431759872868414714294390489938157080231292067732188769680434360003645408402090903882885823385671889531541039045885246174119028056012276121709640876158642076723706945503747161083244634679982307347658648183 A46^31 - 9149331424499552779979794487803049109145854134654822152707377782056977306922942650458296507280354954701791394660220920473087273186333364153948147270760935725093184452955662120588287066833595316280317830971486425063174196982668087569045226676196390232025049390929919119574244207001600000000000000/1100361398322672542816996659673308465019208459258680373411484775335933290066957330236709000182200288701298684857133422375964163289121560076553576443908981540602291099109680162361819963590169656499589176257798555902458399331483611197845855578690382748137328279628454300831611843 A46^30 - 79973012198225026539332842880094613358418060119022835029835910425124670099764459027277518388837201641732137026202824480404214035628958792843162201239309141530235969873589550508448718782972837671619969580166184326037129487506541556889887126810734028550977167372000415444560765391994880000000000000/2567509929419569266572992205904386418378153071603587537960131142450511010156233770552321000425134006969696931333311318877249714341283640178625011702454290261405345897922587045510913248377062531832374744601529963772402931773461759461640329683610893078987099319133060035273760967 A46^29 - 8299397433438618012971050717608586981007096658561248516910138778913485394953866129982359922925735316581762478702897711207576975054100165652131628929716109958379944654693325699234875749400905318226733372296404518054930456353699133199857710268046545544970469824348289708598182344299520000000000000/122262377591408060312999628852589829446578717695408930379053863926214810007439703359634333353577809855699853873014824708440462587680173341839286271545442393400254566567742240262424440398907739611065464028644283989162044370164845688649539508743375860904147586625383811203512427 A46^28 - 1009095872071060606887382314527808282304198676274688330469220230071145794033535363745528418711512251257265245188164841956986767644719780200297491853553606313847573922892151658199998953665772946824914444133907829818800088800411900616394966638527678678559806341695040379358176887422246912000000000000/9903252584904052885352969937059776185172876133328123360703362978023399610602615972130381001639802598311688163714200801383677469602094040688982187995180833865420619891987121461256379672311526908496302586320187003122125593983352500780612700208213444733235954516656088707484506587 A46^27 - 17315208871659672382889994991298216489948823684300447200387695359236475124436480420376202114747618244141605164691824173316146543744310447948881287127831116503491247576077521276794352818587011612296482326427954766142441690371899121755561881707409211508579604162112995865737896762901299200000000000/157194485474667506116713808524758352145601208465525767630212110762276184295279618605244142883171469814471240693876203196566309041303080010936225206272711648657470157015668594623117137655738522357084168036828365128922628475926230171120836511241483249733904039946922042975944549 A46^26 - 355912103283291653350342202441876054749468980229513306853575234001898259812970951366303068842390266228175806871138615053043787098181575854719444584002263604429051532090218493757283996626942336013246526185261992049786421446412979193448620795644178642889464382438869086312841888992127016960000000000/4244251107816022665151272830168475507931232628569195726015726990581456975972549702341591857845629684990723498734657486307290344115183160295278080569363214513751694239423052054824162716704940103641272536994365858480910968850008214620262585803520047742815409078566895160350502823 A46^25 - 22500215142403543279349306218081169611665243245444094081053540155023353065879988896297915009225132894908494486994564419892386896801934687727963175381359248310045430450423575265267918061375611015895078661355902220676428093155477822434762767854058633074606376473106078760663121039247968256000000000/606321586830860380735896118595496501133033232652742246573675284368779567996078528905941693977947097855817642676379640901041477730740451470754011509909030644821670605631864579260594673814991443377324648142052265497272995550001173517180369400502863963259344154080985022907214689 A46^24 + 32673087924159313144791905275717518339829777902894646782455060134934567490559434999059780860378598405024654197705939033389093954547300991047620772736355387222770403567834688718752714161637753797576326177011424906610337687450739278051783922665936466482962665445318545262436466728042148326400000000/5456894281477743426623065067359468510197299093874680219163077559319016111964706760153475245801523880702358784087416768109373299576664063236786103589181275803395035450686781213345352064334922990395921833278470389475456959950010561654623324604525775669334097386728865206164932201 A46^23 + 1104476613898878470428452483404305645696373154435799116198630014006790595031027352442953347316486180518984682424499974769238555293892978509198039261572798669589819427036166245573413843280166968329333248039556067221899335330112207191529323373567807146257408223366473003726728025624000104960000000/37121729805971043718524252158907949048961218325678096729000527614415075591596644626894389427221250889131692408757937198022947616167782743107388459790348814989081873814195790566975184111121925104734162131146057071261611972449051439827369555132828405913837397188631736096360083 A46^22 + 78113480257566589843454213154883751458293793164562951385751797138539577840045698708433870322843582703179960018071553825115618374965480805851557122788075034745129320776152687748718547900383557327895464091642273092813119121008016975113831330943443029648706513051422069517463619351777438820096000000/2338668977776175754267027886011200790084556754517720093927033239708149762270588611494346533914938806015296621751750043475445699818570312815765472966791975344312158050294334805719436599000681281598252214262201595489481554264290240709124281973368189572571756022883799374070685229 A46^21 + 8395276376303141598390829139882556608548753795333152128887172440477769331506706983960503595713255764449491015079245760485357931286228197098907656335096624996307325605986758954601108746818602104646481755620539840786476094323961082674609265938980034638463288197875497334999695180183262425971200000/334095568253739393466718269430171541440650964931102870561004748529735680324369801642049504844991258002185231678821434782206528545510044687966496138113139334901736864327762115102776657000097325942607459180314513641354507752041462958446325996195455653224536574697685624867240747 A46^20 + 1980830687381076339084629170133609739180380880215294749410365337574729337777957070632004952411058046327505217385303454420099905980785666056543363976205429431407119959330949327855470437048628780012191977441692141470352845169941328389007388270439665640289698273307474532663228874959149967256320000/143183814965888311485736401184359232045993270684758373097573463655601005853301343560878359219281967715222242148066329192374226519504304866271355487762774000672172941854755192186904281571470282546831768220134791560580503322303484125048425426940909565667658532013293839228817463 A46^19 + 702091132949191502045640382611695646026178320839883517672739200609357661071215369230485179018215789550721046578374598929240937327355327668355522069483080934376708869486654867322142997232774287348753757914178992350603911472387418363244015679942880338944525806103128925167085917623892484556464000/143183814965888311485736401184359232045993270684758373097573463655601005853301343560878359219281967715222242148066329192374226519504304866271355487762774000672172941854755192186904281571470282546831768220134791560580503322303484125048425426940909565667658532013293839228817463 A46^18 - 26433410235178253131164568590264182053663342966938907183003177081908265950075927144928504095882195140380650366718219667766773538150084001651408286437201753129205947322295717753544109541401358911647830600006212366636193412718513659512611675534262638709507230297656780911489899859088163252104000/429551444897664934457209203553077696137979812054275119292720390966803017559904030682635077657845903145666726444198987577122679558512914598814066463288322002016518825564265576560712844714410847640495304660404374681741509966910452375145276280822728697002975596039881517686452389 A46^17 - 36588941424973786825226031379192323188694220080503719244669152016528167903934256688892636045811947246452459444223170684913020286311345813411596839167079667051478933505562383477365997492491009488269523510100891279267477520527793501298375191462023458969167972627835965786511419141962714020174080/20454830709412615926533771597765604577999038669251196156796209093657286550471620508696908459897423959317463164009475598910603788500614980895907926823253428667453277407822170312414897367352897506690252602876398794368643331757640589292632203848701366523951218859041977032688209 A46^16 - 321333621660414138288318264757386991534769910679354013783840583853994409935788586791159864436843010390611984538928952685258511624721739694382405481016998808554437914129696961450517494564423154689101019268062664959334760483746323046684415109519127596246390980123789139075174901071183005966554488/184093476384713543338803944379890441201991348023260765411165881842915578954244584578272176139076815633857168476085280390195434096505534828063171341409280858007079496670399532811734076306176077560212273425887589149317789985818765303633689834638312298715560969731377793294193881 A46^15 - 297844721921145322765306527355860406934008939169980445647884079222865480952075045050385650004580591246687712266033786754423786883489838690861527534993455211693991394970866545156968100893505892393812058175717385845665650930957741425381878068688495541752226534683879631214290521382589457098661971/262990680549590776198291349114129201717130497176086807730236974061307969934635120826103108770109736619795954965836114843136334423579335468661673344870401225724399280957713618302477251865965825086017533465553698784739699979741093290905271192340446141022229956759111133277419830 A46^14 - 451879932351907431338340841430894291445765587061006243890312609075513994394090487211287876791443241336702645913369115324679497644368945637845627225355027484550118544624707338874219923703785680226085214156696766542732612750915702425388991747367656078911167375594394305408128145699286227195203039/788972041648772328594874047342387605151391491528260423190710922183923909803905362478309326310329209859387864897508344529409003270738006405985020034611203677173197842873140854907431755597897475258052600396661096354219099939223279872715813577021338423066689870277333399832259490 A46^13 - 5320311585057193929116580887725053048673711797951597468291152199479233897939064740829295546757123058099231381384546836150171434463598328526972269844562130162789158735497528507679194843684312884543346736256634246332090848994957191293298207019966632338305847326064328022091724095239631394444614337/22542058332822066531282115638353931575754042615093154948306026348112111708683010356523123608866548853125367568500238415125971522021085897313857715274605819347805652653518310140212335874225642150230074297047459895834831426834950853506166102200609669230476853436495239995207414000 A46^12 - 362392746608515719372641040156549702648285106850030418671446645004524075469397447508371929006539117538692298420067983710297061362768282375139330712098123029408339164065434243491074476680334774441684136089288247838831323010949142346356824849579571331534045674787558012078606230561135787887949871/4508411666564413306256423127670786315150808523018630989661205269622422341736602071304624721773309770625073513700047683025194304404217179462771543054921163869561130530703662028042467174845128430046014859409491979166966285366990170701233220440121933846095370687299047999041482800 A46^11 - 155718157831390278974558432491864519634779570729825416271843627583866505195625371450767361228547485547131717071612734991086436233519540316144548267366374648257565699340887077601451758110896914837331994622765481537988675137980472319274860288480400497182597917963360319541332897673699613001900139/6869960634764820276200263813593579146896470130314104365198027077519881663598631727702285290321233936190588211352453612228867511473092844895651875131308440182188389380119865947493283314049719512451070261957321111111567672940175498211403002575423899194050088666360454093777497600 A46^10 - 45201548094888346900126189229758597421851803521277808642167463508827660396693637290758710792553278488070609212455021345000119146078696472196451660991329985879243486243508404638669646114695294849026046972039432309027960523963229014364806077507073721111320914116188285819616980932331878040743049/8587450793456025345250329766991973933620587662892630456497533846899852079498289659627856612901542420238235264190567015286084389341366056119564843914135550227735486725149832434366604142562149390563837827446651388889459591175219372764253753219279873992562610832950567617221872000 A46^9 - 1953129387759091287411246093721824623775778716719168388328766612507051710224152064386589191585418322171515414473927996208486195431232117229550712885298021138550712056198139675205800600486010459477444720900066414100009247618626937808864666954121404483671145377185645585361795757512848953771727/1962845895647091507485789661026736899113277180089744104342293450719966189599609065057795797234638267483025203243558174922533574706597955684471964323230982909196682680034247413569509518299919860700305789130663174603305049411478713774686572164406828341157168190388701169650713600 A46^8 - 376134847222603342228005080394985602907218977535587514699426664550583601459354985670099124083557791013853499761803409404040812308856476452671356746803998334683915044848315929579536086205259194433291389544619656281935845620125586677702558497845124290906144446668089290971220577745466063821/2503629968937616718731874567636144003971016811338959316763129401428528303060725848288004843411528402401817861280048692503231600391068821026112199391876253710710054438819193129552945814158061046811614526952376498218501338535049379814651240005620954516782102283659057614350400 A46^7 - 574485486982304350778070191971122027743291593240873280940414570314432804154563998121312928497476285147145839708807365153231143249845428378451535410210139619924467103332329351315189638465205694465434576925840400070753365257384354164688588108696337944766401214964460997424273537531595188679/32700473063674993877314280067084329847784709372590489035273526875801185999160500875598430607824044439533947575902676800042208658169062152177791992057159232139886425323352726590079292266554266733865985658153488956323282789029216389415852930685661446749807050235546874962944000 A46^6 - 11511257781723192579987461460171218665430662046039138877189380600683547596344289008862892439158437560118751792069494864896646099764172740280826359491156661557991789303166781418829521172671095190437798106362980957418171493748387515586895216124868996215985307716367044170468765302175191523/7630110381524165238039998682319676964483098853604447441563822937686943399804116870972967141825610369224587767710624586676515353572781168841484798146670487499306832575448969537685168195529328904568729986902480756475432650773483824197032350493321004241621645054960937491353600 A46^5 - 1671303995297463181793089014042140921533205745175671854516004230292597522756847916940561516331382516496857206868368002684300205049090986725992113164539129267661714078303721803021367606163396471932149786832020402699788845934151506635865863054320744139050271729184411228168473604636972839/19620283838204996326388568040250597908670825623554293421164116125480711599496300525359058364694426663720368545541606080025325194901437291306675195234295539283931855194011635954047575359932560040319591394892093373793969673417529833649511758411396868049884230141328124977766400 A46^4 - 60908092525844337290393747162251644298087521040833441461527761929200066595412859133091070618059209993364079718454967764919058787501486800829921561765930651085782549124215742770618379064496572773262751298821893631502246026461480269869465295797601392220253848115075799372526327938111547/28028976911721423323412240057500854155244036605077562030234451607829587999280429321941511949563466662457669350773722971464750278430624701866678850334707913262759793134302337077210821942760800057599416278417276248277099533453614048070731083444852668642691757344754464253952000 A46^3 + 45086394754577700869380844548742167538951281901932651744568905863102388384166263647335650948182916349574945031051918658847888488603435323077118198631600514293001349841754886818523071957433889642885763744141389343414660044929152119754129057333007696856923108253108183335928470691323/732185519326600445999340148440838639157395241928556722422450980775956584470998970042553781539617088325424832020211538846426129722269379967129569967927063856659847657385856968547548001770078042320964343599471706077442600057563795541439505853253294201278478559209912535613440 A46^2 + 3731272476720292507686304261693030416127583479257486748224902831742134747688100663209642453477726001478166688384847374161566164080254468319618379882752444074260128081142704326346717896603236118487929226426342553598574093896870131278947045099476660390852113706889521422745255/648548681376311336096354298151253046305799356866989727202426109672580591403591774768418528149462415254238265324025243450986863770434187187437615121817481448997172315569955506437383079799176270479879130881051326953517042284548430007652623523644145232141509494765016064 A46 + 9280862118536625477466695256284609672515130143361639412543372050128009110823486812077779222084224626376141852085219762625785282075028284601725310082870373135311800354168551231605316413369320027988216942534660872550537108296929260273306523538001567960935496614750288886518875/94873407104191829737523828758126159916734077347399640093612048043531789371039711051837224689292787602905711955971692756258649785846372525705159697820157286253300635877662062655982896244908071567342318574599508400057350185625370332548040926887372102530415103234196635648 ), ( U4^4 - 20/7 A46^2 ) ) """; f = r.ideal( ps ); puts "Ideal: " + str(f); puts; rg = f.isGB(); puts "is GB output: " + str(rg); puts; ri = f.toInteger(); puts "integer Output: " + str(ri); puts; rip = ri.list.get(0); puts "integer polynomial: " + str(rip); puts; startLog(); rfi = rz.squarefreeFactors(rip); #rfi = rz.factors(rip); puts "squarefree Output: " + str(rfi); puts; rfi.each{ |h,i| puts "h**i = " + str(h) + "**" + str(i) }; #puts "g = ", g; puts; #startLog(); terminate(); jas-2.5/examples/solv_ore.py0000644000175000017500000000245212136725524016375 0ustar giovannigiovanni# # jython examples for jas. # $Id: solv_ore.py 4382 2013-04-27 10:41:24Z kredel $ # from java.lang import System from java.lang import Integer from jas import SolvableRing, SolvPolyRing, PolyRing from jas import QQ, startLog # Ore extension solvable polynomial example, Gomez-Torrecillas, 2003 p = PolyRing(QQ(),"x,y,z,t"); #is automatic: [one,x,y,z,t] = p.gens(); relations = [z, y, y * z + x, t, y, y * t + y, t, z, z * t - z ]; print "relations: = " + str([ str(f) for f in relations ]); print; rp = SolvPolyRing(QQ(), "x,y,z,t", PolyRing.lex, relations); print "SolvPolyRing: " + str(rp); print; print "gens =", [ str(f) for f in rp.gens() ]; f1 = x**2 + y**2 + z**2 + t**2 + 1; print "f1 = ", f1; F = [ f1 ]; print "F =", [ str(f) for f in F ]; print I = rp.ideal( list=F ); print "SolvableIdeal: " + str(I); print; rgl = I.leftGB(); print "seq left GB:" + str(rgl); print "isLeftGB: " + str(rgl.isLeftGB()); print; rgr = I.rightGB(); print "seq right GB:" + str(rgr); print "isRightGB: " + str(rgr.isRightGB()); print; #startLog(); rgt = I.twosidedGB(); print "seq twosided GB:" + str(rgt); print "isTwosidedGB: " + str(rgt.isTwosidedGB()); print; startLog(); rgi = rgl.intersect(rgt); print "leftGB intersect twosidedGB:" + str(rgi); print; #exit(0); jas-2.5/examples/cgbmmn15.py0000644000175000017500000000234211045305426016145 0ustar giovannigiovanni# # jython examples for jas. # $Id: cgbmmn15.py 1977 2008-08-03 10:40:23Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # rational function coefficients # IP (alpha,beta,gamma,epsilon,theta,eta) # (c3,c2,c1) /G/ #r = Ring( "IntFunc(alpha,beta,gamma,epsilon,theta,eta)(c3,c2,c1) G" ); # ( { alpha } c1 - { beta } c1**2 - { gamma } c1 c2 + { epsilon } c3 ), # ( - { gamma } c1 c2 + { epsilon + theta } c3 - { gamma } c2 ), # ( { gamma } c2 c3 + { eta } c2 - { epsilon + theta } c3 ) r = Ring( "IntFunc(a,b,g,e,t,eta)(c3,c2,c1) G" ); print "Ring: " + str(r); print; ps = """ ( ( { a } c1 - { b } c1**2 - { g } c1 c2 + { e } c3 ), ( - { g } c1 c2 + { e + t } c3 - { g } c2 ), ( { g } c2 c3 + { eta } c2 - { e + t } c3 ) ) """; f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; #sys.exit(); #startLog(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #sys.exit(); jas-2.5/examples/factors_compl.py0000644000175000017500000000227111316645236017377 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_compl.py 2946 2009-12-30 12:42:06Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import terminate from jas import startLog from jas import QQ, DD, CR # polynomial examples: complex factorization via algebraic factorization r = PolyRing( CR(QQ()), "x", PolyRing.lex ); print "Ring: " + str(r); print; [one,I,x] = r.gens(); f1 = x**3 - 2; f2 = ( x - I ) * ( x + I ); f3 = ( x**3 - 2 * I ); #f = f1**2 * f2 * f3; f = f1 * f2 * f3; #f = f1 * f2; #f = f1 * f3; #f = f2 * f3; #f = f3; #f = f**3; print "f = ", f; print; #startLog(); t = System.currentTimeMillis(); R = r.factors(f); t = System.currentTimeMillis() - t; #print "R = ", R; #print "complex factor time =", t, "milliseconds"; g = one; for h, i in R.iteritems(): print "h**i = "+ str(h) + "**" + str(i); h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "complex factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "complex factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/integrate.py0000644000175000017500000000222411456131252016515 0ustar giovannigiovanni# # jython examples for jas. # $Id: integrate.py 3348 2010-10-15 19:59:39Z kredel $ # import sys from java.lang import System from jas import Ring, RF, QQ, PolyRing from jas import terminate from jas import startLog # elementary integration r = PolyRing(QQ(),"x",PolyRing.lex); print "r = " + str(r); rf = RF(r); print "rf = " + str(rf.factory()); [one,x] = rf.gens(); print "one = " + str(one); print "x = " + str(x); print; #f = 1 / ( 1 + x**2 ); #f = x**2 / ( x**2 + 1 ); #f = 1 / ( x**2 - 2 ); #f = 1 / ( x**3 - 2 ); #f = ( x + 3 ) / ( x**2- 3 * x - 40 ); f = ( x**7 - 24 * x**4 - 4 * x**2 + 8 * x - 8 ) / ( x**8 + 6 * x**6 + 12 * x**4 + 8 * x**2 ); print "f = ", f; print; #sys.exit(); #startLog(); t = System.currentTimeMillis(); e1 = r.integrate(f); t = System.currentTimeMillis() - t; print "e1 = ", e1; ## print "e1.toScript() = "; ## for a in e1.logarithm: ## print a.toScript(); print "integration time =", t, "milliseconds"; print t = System.currentTimeMillis(); e2 = f.integrate(); t = System.currentTimeMillis() - t; print "e2 = ", e2; print "integration time =", t, "milliseconds"; print #startLog(); terminate(); #sys.exit(); jas-2.5/examples/montes_ex51s.rb0000644000175000017500000000255111653002012017031 0ustar giovannigiovanni# # jruby examples for jas. # $Id: montes_ex51s.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Montes JSC 2002, 33, 183-208, example 5.1, simplified # integral function coefficients r = PolyRing.new( PolyRing.new(QQ(),"a, b",PolyRing.lex), "u,z,y,x", PolyRing.lex ); puts "Ring: " + str(r); puts; one,a,b,u,z,y,x = r.gens(); puts "gens: " + r.gens().each{ |f| str(f) }.join(","); puts; f1 = 756 * x - 39 * a * b - 4 * b - 155 - 117 * a + ( 117 * a + 51 ) * u; f2 = 189 * y + 6 * a * b - 107 - 43 * b + 18 * a - ( 18 * a - 123 ) * u; f3 = 756 * z - 1439 + 236 * b + 99 * a + 33 * a * b - ( 99 * a - 15 ) * u; f4 = ( 9 * a**2 - 30 * a + 21 ) * u - 9 * a**2 - 3 * a**2 * b + 11 * a * b + 22 * a - 49 + 28 * b; F = [f1,f2,f3,f4]; puts "F: " + F.each{ |f| str(f) }.join(","); puts; #startLog(); If = r.paramideal( "", list = F ); puts "ParamIdeal: " + str(If); puts; ## G = If.GB(); ## puts "GB: " + str(G); ## puts; ## sys.exit(); GS = If.CGBsystem(); GS = If.CGBsystem(); GS = If.CGBsystem(); puts "CGBsystem: " + str(GS); puts; bg = GS.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; terminate(); exit(); CG = If.CGB(); puts "CGB: " + str(CG); puts; bg = CG.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/algNum.rb0000644000175000017500000000734111513655460015744 0ustar giovannigiovanni# # jruby examples for jas. # $Id: algNum.rb 3491 2011-01-13 20:06:08Z kredel $ # require "examples/jas" # multiple algebraic field extensions startLog(); puts "------- multiple algebraic field extensions QQ(alpha)(beta)(gamma)(delta) ---------"; r = PolyRing.new(QQ(),"alpha",PolyRing.lex); puts "r = " + str(r); e,a = r.gens(); puts "e = " + str(e); puts "a = " + str(a); ap = a**5 - a + 1; puts "ap = " + str(ap); x = r.factors(ap); puts "x = " + str( x.map{ |p,e| str(p)+"**"+str(e)+"," }); qs2 = AN(ap,x.size==1); # and e==1 puts "qs2 = " + str(qs2.factory()); one,alpha = qs2.gens(); puts "one = " + str(one); puts "alpha = " + str(alpha); b = alpha**2 - 1; puts "b = " + str(b); c = 1 / b; puts "c = " + str(c); puts ar = PolyRing.new(qs2,"beta",PolyRing.lex); puts "ar = " + str(ar); e,a,b = ar.gens(); puts "e = " + str(e); puts "a = " + str(a); puts "b = " + str(b); bp = b**2 - a; puts "bp = " + str(bp); x = ar.factors(bp); puts "x = " + str( x.map{ |p,e| str(p)+"**"+str(e)+"," }); qs3 = AN(bp,x.size==1); # and e==1 puts "qs3 = " + str(qs3.factory()); one,alpha,beta = qs3.gens(); puts "one = " + str(one); puts "alpha = " + str(alpha); puts "beta = " + str(beta); c = -alpha + beta**3; puts "c = " + str(c); d = 1 / c; puts "d = " + str(d); e = c * d; puts "e = " + str(e); puts br = PolyRing.new(qs3,"gamma",PolyRing.lex); puts "br = " + str(br); e,a,b,c = br.gens(); puts "e = " + str(e); puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); cp = c**2 - b*c - a; puts "cp = " + str(cp); x = br.factors(cp); puts "x = " + str( x.map{ |p,e| str(p)+"**"+str(e)+"," }); qs4 = AN(cp,x.size==1); # and e==1 puts "qs4 = " + str(qs4.factory()); one,alpha,beta,gamma = qs4.gens(); puts "one = " + str(one); puts "alpha = " + str(alpha); puts "beta = " + str(beta); puts "gamma = " + str(gamma); d = -alpha*gamma + beta; puts "d = " + str(d); e = 1 / d; puts "e = " + str(e); f = e * d; puts "f = " + str(f); puts cr = PolyRing.new(qs4,"delta",PolyRing.lex); puts "cr = " + str(cr); e,a,b,c,d = cr.gens(); puts "e = " + str(e); puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); puts "d = " + str(d); dp = d**2 + c*d - b + a; # irreducible #dp = (d**2 + b) * ( c**2 - a ); # = b * c * ( d**2 + b ) #dp = (d + b * c) * ( d + c - a**2 ); puts "dp = " + str(dp); x = cr.factors(dp); puts "x = " + str( x.map{ |p,e| str(p)+"**"+str(e)+", " }); qs5 = AN(dp,x.size==1); # and e==1 puts "qs5 = " + str(qs5.factory()); one,alpha,beta,gamma,delta = qs5.gens(); puts "one = " + str(one); puts "alpha = " + str(alpha); puts "beta = " + str(beta); puts "gamma = " + str(gamma); puts "delta = " + str(delta); #e = -alpha*gamma + beta*delta; # ok #e = alpha**3 - gamma; # 1/e does fail not because it is a unit e = delta**2 + beta; # 1/e fails e = delta + beta*gamma; # 1/e fails puts "e = " + str(e); f = 1 / e; puts "f = " + str(f); g = e * f; puts "g = " + str(g); puts f = ( ( ( ( 3/82 * alpha**4 - 12/41 * alpha**3 - 13/82 * alpha**2 - 19/82 * alpha - 15/82 ) * beta + ( 3/82 * alpha**4 - 12/41 * alpha**3 - 13/82 * alpha**2 - 19/82 * alpha - 15/82 ) ) * gamma - ( ( 21/82 * alpha**4 - 45/82 * alpha**3 - 25/41 * alpha**2 - 51/82 * alpha - 32/41 ) * beta - ( 45/82 * alpha**4 + 25/41 * alpha**3 + 51/82 * alpha**2 + 43/82 * alpha + 21/82 ) ) ) * delta - ( ( 39/82 * alpha**4 + 8/41 * alpha**3 - 5/82 * alpha**2 - 1/82 * alpha - 31/82 ) * beta * gamma + ( 11/82 * alpha**4 - 3/41 * alpha**3 + 7/82 * alpha**2 - 15/82 * alpha + 27/82 ) ) ); puts "f = " + str(f); e = 1 / f; puts "e = " + str(e); g = e * f; puts "g = " + str(g); puts puts terminate(); __END__ s to_skip = <dg); puts "d-GB == e-GB: " + str(eg===dg); puts jas-2.5/examples/cgb_3.rb0000644000175000017500000000162611641163152015470 0ustar giovannigiovanni# # jruby examples for jas. # $Id: cgb_3.rb 3785 2011-09-29 21:43:06Z kredel $ # require "examples/jas" # 2 univariate polynomials of degree 2 example for comprehensive GB # integral/rational function coefficients #r = Ring.new( "IntFunc(a3, b3, a2, b2, a1, b1, a0, b0) (x) L" ); r = PolyRing.new( PolyRing.new(ZZ(),"(a3, b3, a2, b2, a1, b1, a0, b0)",PolyRing.lex),"(x)", PolyRing.lex ); puts "Ring: " + str(r); puts; ps = """ ( ( { a3 } x^3 + { a2 } x^2 + { a1 } x + { a0 } ), ( { b3 } x^3 + { b2 } x^2 + { b1 } x + { b0 } ) ) """; f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; #sys.exit(); # long run time startLog(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; #sys.exit(); bg = gs.isCGBsystem(); puts "isCGBsystem: " + str(bg); puts; #sys.exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; #sys.exit(); #bg = gs.isCGB(); #puts "isCGB: " + str(bg); #puts; terminate(); jas-2.5/examples/squarefree_poly.rb0000644000175000017500000000173611773623314017731 0ustar giovannigiovanni# # jruby examples for jas. # $Id: squarefree_poly.rb 3970 2012-06-30 16:18:21Z kredel $ # require "examples/jas" # polynomial examples: squarefree: characteristic 0 #r = PolyRing.new(PolyRing.new(QQ(),"u,v",PolyRing.lex),"x, y",PolyRing.lex) #r = PolyRing.new(PolyRing.new(ZZ(),"u,v",PolyRing.lex),"x, y",PolyRing.lex) r = PolyRing.new(PolyRing.new(GF(7),"u,v",PolyRing.lex),"x, y",PolyRing.lex) puts "Ring: " + str(r); puts; #one,u,v,x,y = r.gens(); a = r.random(k=1,l=3); b = r.random(k=1,l=3); c = r.random(k=1,l=3); if a.isZERO() a = x; end if b.isZERO() b = y; end if c.isZERO() c = y; end f = a**2 * c**3 * b; puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); puts "f = " + str(f); puts; t = System.currentTimeMillis(); F = r.squarefreeFactors(f); t = System.currentTimeMillis() - t; puts "factors:"; for g in F.keys() i = F[g]; puts "g = #{g}**#{i}"; end puts puts "factor time = " + str(t) + " milliseconds"; startLog(); terminate(); jas-2.5/examples/factors_rat.rb0000644000175000017500000000423711627521076017032 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_rat.rb 3755 2011-08-31 21:06:06Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: factorization over Q r = PolyRing.new( QQ(), "x", PolyRing.lex ); puts "Ring: " + str(r); puts one,x = r.gens(); #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**4 - 1; #f = x**3 - x**2 + x - 1; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; #f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; f = x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8; puts "f = ", f; puts; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; puts "G = ", str(G.map{ |h,i| str(h)+"**"+str(i)+" " }); #puts "G = ", G; #puts "factor time =", t, "milliseconds"; puts; puts "f = " + str(f); g = one; for h, i in G do if i > 1 then puts "h**i = " + str(h) + "**" + str(i); else puts "h = " + str(h); end h = h**i; g = g*h; end puts; #puts "g = ", g; if f == g then puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): true" ; else puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): " + str(f==g); end puts; #startLog(); terminate(); jas-2.5/examples/0dim_prime-decomp.rb0000644000175000017500000000135011641147136020003 0ustar giovannigiovanni# # jruby examples for jas. # $Id: 0dim_prime-decomp.rb 3783 2011-09-29 20:00:31Z kredel $ # require "examples/jas" # polynomial examples: zero dimensional ideals prime and primary decomposition r = PolyRing.new(QQ(),"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); f1 = (x**2 - 5)**2; f2 = y**3 - x; f3 = z**2 - y * x; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; F = r.ideal( "", [f1,f2,f3] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); P = F.primeDecomp(); t1 = System.currentTimeMillis() - t; puts "P = " + str(P); puts; puts "prime decomp time = " + str(t1) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/charset.rb0000644000175000017500000000213711751721510016142 0ustar giovannigiovanni# # jruby examples for jas. # $Id: charset.rb 3939 2012-05-07 10:26:16Z kredel $ # require "examples/jas" # characteristic set example Circle of Apollonius, from CLO IVA #r = PolyRing.new( QQ(),"u1,u2,u3,u4,x1,x2,x3,x4,x5,x6,x7,x8",PolyRing.lex ); r = PolyRing.new( QQ(),"u1,u2,x1,x2,x3,x4,x5,x6,x7,x8",PolyRing.lex ); puts "Ring: " + str(r); puts; #one,u1,u2,u3,u4,x1,x2,x3,x4,x5,x6,x7,x8 = r.gens(); #one,u1,u2,x1,x2,x3,x4,x5,x6,x7,x8 = r.gens(); #h3 = 2 * x3 - u3; typo #h4 = 2 * x4 - u4; h1 = 2 * x1 - u1; h2 = 2 * x2 - u2; h3 = 2 * x3 - u1; h4 = 2 * x4 - u2; h5 = u2 * x5 + u1 * x6 - u1 * u2; h6 = u1 * x5 - u2 * x6; h7 = x1**2 - x2**2 - 2 * x1 * x7 + 2 * x2 * x8; h8 = x1**2 - 2 * x1 * x7 - x3**2 + 2 * x3 * x7 - x4**2 + 2 * x4 * x8; g = ( ( x5 - x7 )**2 + ( x6 - x8 )**2 - ( x1 - x7 )**2 - x8**2 ); L = [h1,h2,h3,h4,h5,h6,h7,h8]; #print "L = ", str(L); f = r.ideal( "", L ); puts "Ideal: " + str(f); puts; startLog(); cc = f.CS(); puts "seq char set: " + str(cc); puts "is char set: " + str(cc.isCS()); puts; puts "g: " + str(g); puts; h = cc.csReduction(g); puts "h: " + str(h); puts; #sys.exit(); jas-2.5/examples/nabeshima_cgbF7.py0000644000175000017500000000166011536656334017511 0ustar giovannigiovanni# # jython examples for jas. # $Id: nabeshima_cgbF7.py 3562 2011-03-12 11:45:32Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Nabashima, ISSAC 2007, example F7 # integral function coefficients r = Ring( "IntFunc(a, b) (z,y,x) G" ); print "Ring: " + str(r); print; ps = """ ( ( x^3 - { a } ), ( y^4 - { b } ), ( x + y - { a } z ) ) """; #startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/factors_abs_mult.rb0000644000175000017500000000115011641415316020034 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_abs_mult.rb 3786 2011-09-30 19:38:55Z kredel $ # require "examples/jas" # polynomial examples: absolute factorization over Q r = Ring.new( "Q(x,y) L" ); puts "Ring: " + str(r); puts; one,x,y = r.gens(); f1 = x**2 + y**2; f2 = x**3 + y**2; f3 = x**4 + 4; f = f1**3 * f2**1 * f3**2; puts "f = " + str(f); puts; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factorsAbsolute(f); t = System.currentTimeMillis() - t; puts "G = " + str(G.toScript()); puts puts "factor time = " + str(t) + " milliseconds"; puts #startLog(); terminate(); jas-2.5/examples/mark_kr.py0000644000175000017500000000245611644542070016173 0ustar giovannigiovanni# # jython examples for jas. # $Id: mark_kr.py 3797 2011-10-10 10:08:57Z kredel $ # #import sys; from jas import Ring from jas import Ideal from jas import startLog # mark, d-gb diplom example, due to kandri-rody 1984 # # The MAS DIIPEGB implementation contains an error because the output e-GB # is not correct. Also the cited result from k-r contains this error. # The polynomial # # ( 2 x * y^2 - x^13 + 2 x^11 - x^9 + 2 x^7 - 2 x^3 ), # # is in the DIIPEGB output, but it must be # # ( 2 x * y^2 - x^13 + 2 x^11 - 3 x^9 + 2 x^7 - 2 x^3 ), # # Test by adding the polynomials to the input. # Frist polynomial produces a different e-GB. # Second polynomial reproduces the e-GB with the second polynomial. r = Ring( "Z(x,y) L" ); print "Ring: " + str(r); print; ps = """ ( ( y**6 + x**4 y**4 - x**2 y**4 - y**4 - x**4 y**2 + 2 x**2 y**2 + x**6 - x**4 ), ( 2 x**3 y**4 - x y**4 - 2 x**3 y**2 + 2 x y**2 + 3 x**5 - 2 x** 3 ), ( 3 y**5 + 2 x**4 y**3 - 2 x**2 y**3 - 2 y**3 - x**4 y + 2 x**2 y ) ) """; f = r.ideal( ps ); print "Ideal: " + str(f); print; #startLog(); eg = f.eGB(); print "seq e-GB:", eg; print "is e-GB:", eg.isGB(); print; #startLog(); dg = f.dGB(); print "seq d-GB:", dg; print "is d-GB:", dg.isGB(); print; print "d-GB == e-GB:", eg.list.equals(dg.list); print "d-GB == e-GB:", eg == dg; jas-2.5/examples/solv_ore.rb0000644000175000017500000000256412136725524016354 0ustar giovannigiovanni# # jruby examples for jas. # $Id: solv_ore.rb 4382 2013-04-27 10:41:24Z kredel $ # require "examples/jas" # Ore extension solvable polynomial example, Gomez-Torrecillas, 2003 p = PolyRing.new(QQ(),"x,y,z,t"); #is automatic: [one,x,y,z,t] = p.gens(); relations = [z, y, y * z + x, t, y, y * t + y, t, z, z * t - z ]; puts "relations: = [" + relations.join(", ") { |r| r.to_s } + "]"; puts; rp = SolvPolyRing.new(QQ(), "x,y,z,t", PolyRing.lex, relations); puts "SolvPolyRing: " + str(rp); puts; puts "gens =" + rp.gens().join(", ") { |r| r.to_s }; #is automatic: one,x,y,z,t = rp.gens(); f1 = x**2 + y**2 + z**2 + t**2 + 1; puts "f1 = " +str(f1); ff = [ f1 ]; puts "ff = [" + ff.join(", ") { |r| r.to_s } + "]"; puts ii = rp.ideal( "", ff ); puts "SolvableIdeal: " + str(ii); puts; rgl = ii.leftGB(); puts "seq left GB: " + str(rgl); puts "isLeftGB: " + str(rgl.isLeftGB()); puts; rgr = ii.rightGB(); puts "seq right GB: " + str(rgr); puts "isRightGB: " + str(rgr.isRightGB()); puts; #startLog(); rgt = ii.twosidedGB(); puts "seq twosided GB: " + str(rgt); puts "isTwosidedGB: " + str(rgt.isTwosidedGB()); puts; #startLog(); rgi = rgl.intersect(rgt); puts "leftGB intersect twosidedGB: " + str(rgi); puts; #startLog(); rgtu = rgt.univariates(); puts "univariate polynomials for twosidedGB: " + rgtu.join(", "); puts; #terminate(); jas-2.5/examples/prime-decomp-h.rb0000644000175000017500000000256611653043730017327 0ustar giovannigiovanni# # jruby examples for jas. # $Id: prime-decomp-h.rb 3817 2011-10-29 18:37:12Z kredel $ # require "examples/jas" # polynomial examples: ideal prime decomposition # TRANSACTIONS OF THE AMERICAN MATHEMATICAL SOCIETY # Volume 296, Number 2. August 1986 # ON THE DEPTH OF THE SYMMETRIC ALGEBRA # J. HERZOG M. E. ROSSI AND G. VALLA #r = PolyRing.new(QQ(),"x,t,z,y",PolyRing.lex); #r = PolyRing.new(QQ(),"x,y,t,z",PolyRing.lex); #r = EF.new(QQ()).extend("x").polynomial("y,z,t").build(); #,PolyRing.lex); #c = PolyRing.new(QQ(),"t,y",PolyRing.lex); #c = PolyRing.new(ZM(32003,0,True),"t",PolyRing.lex); c = PolyRing.new(ZZ(),"t",PolyRing.lex); r = PolyRing.new(RF(c),"z,y,x",PolyRing.lex); puts "Ring: " + str(r); puts; one,t,z,y,x = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); puts "t = " + str(t); f1 = x**3 - y**7; f2 = x**2 * y - x * t**3 - z**6; f3 = z**2 - t**3; #f3 = z**19 - t**23; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; F = r.ideal( "", list=[f1,f2,f3] ); puts "F = " + str(F); puts; #sys.exit(); startLog(); t = System.currentTimeMillis(); P = F.radicalDecomp(); #P = F.primeDecomp(); t1 = System.currentTimeMillis() - t; puts "P = " + str(P); puts; puts "prime/radical decomp time = " + str(t1) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/nabeshima_cgbF3.rb0000644000175000017500000000160311653002012017427 0ustar giovannigiovanni# # jruby examples for jas. # $Id: nabeshima_cgbF3.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Nabashima, ISSAC 2007, example F3 # integral function coefficients r = Ring.new( "IntFunc(c, b, a, d) (x) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( { a } x^4 + { c } x^2 + { b } ), ( { b } x^3 + x^2 + 2 ), ( { c } x^2 + { d } x ) ) """; #startLog(); f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; terminate(); exit(); bg = gs.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; #exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; bg = gs.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/syzsolv.rb0000644000175000017500000000130312136716620016240 0ustar giovannigiovanni# # jruby examples for jas. # $Id: syzsolv.rb 4380 2013-04-27 09:42:41Z kredel $ # require "examples/jas" # ? example rs = """ Rat(a,b,e1,e2,e3) L RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e1 ), ( e3 ), ( e2 ), ( e2 e3 - e2 ) ) """; r = SolvableRing.new( rs ); puts "SolvableRing: " + str(r); puts; ps = """ ( ( e1 e3^3 + e2^10 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) """; f = r.ideal( ps ); puts "SolvIdeal: " + str(f); puts; include_class "edu.jas.gbmod.SolvableSyzygyAbstract"; #startLog(); R = SolvableSyzygyAbstract.new().resolution( f.pset ); for i in 0..R.size() puts "\n #{i+1}. resolution"; puts "\n" + str(R[i]); end #terminate(); jas-2.5/examples/montes_ex114.py0000644000175000017500000000316311253240426016764 0ustar giovannigiovanni# # jython examples for jas. # $Id: montes_ex114.py 2811 2009-09-13 18:59:35Z kredel $ # import sys; from jas import PolyRing, QQ, RF from jas import Ideal from jas import startLog from jas import terminate # Montes JSC 2002, 33, 183-208, example 11.4 # integral function coefficients R = PolyRing( PolyRing(QQ(),"Q2, P2, Q1, P1",PolyRing.lex), "f3, e3, f2, e2", PolyRing.lex ); print "Ring: " + str(R); print; [one, Q2, P2, Q1, P1, f3, e3, f2, e2] = R.gens(); print "gens: ", [ str(f) for f in R.gens() ]; print; fp1 = 14 - 12 * e2 - 110 * f2 - 2 * e3 - 10 * f3 - P1; fp2 = 2397 - 2200 * e2 + 240 * f2 - 200 * e3 + 40 * f3 - 20 * Q1; fp3 = 16 * e2**2 - 4 * e2 * e3 - 20 * e2 * f3 + 20 * e3 * f2 + 16 * f2**2 - 4 * f2 * f3 - 12 * e2 + 110 * f2 - P2; fp4 = 2599 * e2**2 - 400 * e2 * e3 + 80 * e2 * f3 - 80 * e3 * f2 + 2599 * f2**2 - 400 * f2 * f3 - 2200 * e2 - 240 * f2 - 20 * Q2; print "fp1: " + str(fp1); print "fp2: " + str(fp2); print "fp3: " + str(fp3); print "fp4: " + str(fp4); print; F = [fp1,fp2,fp3,fp4]; print "F: ", [ str(f) for f in F ]; print; startLog(); If = R.paramideal( "", list = F ); print "ParamIdeal: " + str(If); print; ## G = If.GB(); ## print "GB: " + str(G); ## print; GS = If.CGBsystem(); GS = If.CGBsystem(); GS = If.CGBsystem(); print "CGBsystem: " + str(GS); print; bg = GS.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; terminate(); sys.exit(); CG = If.CGB(); print "CGB: " + str(CG); print; bg = CG.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/polynomial.py0000644000175000017500000000216311151514632016717 0ustar giovannigiovanni# # jython examples for jas. # $Id: polynomial.py 2448 2009-02-26 13:31:07Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring from jas import Ideal from jas import terminate from jas import startLog # polynomial examples: gcd #r = Ring( "Mod 1152921504606846883 (x,y,z) L" ); #r = Ring( "Rat(x,y,z) L" ); #r = Ring( "C(x,y,z) L" ); r = Ring( "Z(x,y,z) L" ); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); a = r.random(); b = r.random(); c = abs(r.random()); #c = 1; #a = 0; f = x * a + b * y**2 + one * z**7; print "a = ", a; print "b = ", b; print "c = ", c; print "f = ", f; print; ac = a * c; bc = b * c; print "ac = ", ac; print "bc = ", bc; print; t = System.currentTimeMillis(); g = r.gcd(ac,bc); t = System.currentTimeMillis() - t; print "g = ", g; #print "gcd time =", t, "milliseconds"; d = r.gcd(g,c); if cmp(c,d) == 0: print "gcd time =", t, "milliseconds,", "isGcd(c,d): true" ; else: print "gcd time =", t, "milliseconds,", "isGcd(c,d): ", cmp(c,d); print; #d = g / c; #m = g % c; #print "d = ", d; #print "m = ", m; #print; #startLog(); terminate(); jas-2.5/examples/nabeshima_cgbF00.py0000644000175000017500000000155711045305426017553 0ustar giovannigiovanni# # jython examples for jas. # $Id: nabeshima_cgbF00.py 1977 2008-08-03 10:40:23Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Nabashima, ISSAC 2007, example Ex-Fig-2 # integral function coefficients r = Ring( "IntFunc(a, b, c) (x) L" ); print "Ring: " + str(r); print; ps = """ ( ( { a } x^3 ), ( { b } x^2 ), ( { c } x ) ) """; #startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/solvable.py0000644000175000017500000000127212136720410016340 0ustar giovannigiovanni# # jython examples for jas. # $Id: solvable.py 4381 2013-04-27 09:57:28Z kredel $ # from jas import SolvableRing # WA_32 solvable polynomial example rs = """ # solvable polynomials, Weyl algebra A_3,2: Rat(a,b,e1,e2,e3) G|3| RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e1 ), ( e3 ), ( e2 ), ( e2 e3 - e2 ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( e1 e3^3 + e2^10 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) """; f = r.ideal( ps ); print "SolvableIdeal: " + str(f); print; rg = f.leftGB(); print "seq left GB:", rg; print; rg = f.twosidedGB(); print "seq twosided GB:", rg; print; rg = f.rightGB(); print "seq right GB:", rg; print; jas-2.5/examples/factors_mod_ins.py0000644000175000017500000000325111224463142017704 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_mod_ins.py 2717 2009-07-06 21:02:27Z kredel $ # import sys from java.lang import System from jas import PolyRing, ZM, QQ, RF from jas import terminate from jas import startLog # polynomial examples: factorization over Z_p p = 5; cr = PolyRing(ZM(p,field=True),"u",PolyRing.lex ); print "Ring cr: " + str(cr); [one,u] = cr.gens(); fu = (u**2+u+1)**p; print "fu = ", fu; t = System.currentTimeMillis(); G = cr.squarefreeFactors(fu); t = System.currentTimeMillis() - t; #print "G = ", G; #.toScript(); print "factor time =", t, "milliseconds"; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; print; qcr = RF(cr); print "Ring qcr: " + str(qcr.factory()); #not ok#r = PolyRing(cr,"x",PolyRing.lex ); r = PolyRing(qcr,"x",PolyRing.lex ); print "Ring r: " + str(r); #qr = RF(r); #print "Ring qr: " + str(qr.factory()); print; [one,u,x] = r.gens(); print "one = " + str(one); print "u = " + str(u); print "x = " + str(x); #f = x**3 - u; #f = (x - u)**3; #f = (x - u**3)**3; #f = (x - u**9)**3; #f = x**p - u; #f = (x - u)**p; p2 = p * 2; fu = (u**2+u+1)**p; #f = x**p + 1/fu; f = x**p + fu; #f = x**p2 - fu * x**p - fu; #f = x**p2 + x**p + 1; #f = x**p2 + 1; print "f = ", f; print; startLog(); t = System.currentTimeMillis(); G = r.squarefreeFactors(f); #G = r.factorsAbsolute(f); #G = None; t = System.currentTimeMillis() - t; #print "G = ", G; #.toScript(); print "factor time =", t, "milliseconds"; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; print; gu = u**2+u+1; #g = (x + 1/gu); g = (x + gu); print "g = ", g; g = g**p; print "g**p = ", g; print; terminate(); jas-2.5/examples/hawes2_c.py0000644000175000017500000000274211304010406016220 0ustar giovannigiovanni# # jython examples for jas. # $Id: hawes2_c.py 2882 2009-11-27 17:48:55Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate #startLog(); # Hawes & Gibson example 2 # rational function coefficients #r = Ring( "IntFunc(a, c, b) (y2, y1, z1, z2, x) L" ); r = Ring( "IntFunc(b, c, a) (y2, y1, z2, z1, x) G" ); print "Ring: " + str(r); print; ps = """ ( ( x + 2 y1 z1 + { 3 a } y1^2 + 5 y1^4 + { 2 c } y1 ), ( x + 2 y2 z2 + { 3 a } y2^2 + 5 y2^4 + { 2 c } y2 ), ( 2 z2 + { 6 a } y2 + 20 y2^3 + { 2 c } ), ( 3 z1^2 + y1^2 + { b } ), ( 3 z2^2 + y2^2 + { b } ) ) """; startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; sys.exit(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/squarefree_finite.rb0000644000175000017500000000156011653336426020221 0ustar giovannigiovanni# # jruby examples for jas. # $Id: squarefree_finite.rb 3822 2011-10-30 21:09:42Z kredel $ # require "examples/jas" # polynomial examples: squarefree: characteristic p, finite #r = PolyRing.new(QQ(),"x, y, z",PolyRing.lex) r = PolyRing.new(ZM(5,field=true),"x, y, z",PolyRing.lex) puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); a = r.random(k=2,l=3); b = r.random(k=2,l=3); c = r.random(k=1,l=3); if a.isZERO() a = x; end if b.isZERO() b = y; end if c.isZERO() c = z; end f = a**10 * b**5 * c; #f = 1; puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); puts "f = " + str(f); puts; t = System.currentTimeMillis(); F = r.squarefreeFactors(f); t = System.currentTimeMillis() - t; puts "factors:"; for g in F.keys() i = F[g]; puts "g = #{g}**#{i}"; end puts puts "factor time = " + str(t) + " milliseconds"; startLog(); terminate(); jas-2.5/examples/powerseries_multi.py0000644000175000017500000000763511444730432020331 0ustar giovannigiovanni# # jython examples for jas. # $Id: powerseries_multi.py 3325 2010-09-17 18:19:07Z kredel $ # import sys; from jas import QQ, DD, Ring from jas import MultiSeriesRing, MPS from jas import startLog from edu.jas.ps import MultiVarCoefficients from edu.jas.ps import MultiVarPowerSeriesMap # example for power series # # # # rational number examples # psr = MultiSeriesRing("Q(x,y,z)",truncate=4); print "psr:", psr; print; one = psr.one(); print "one:", one; print; zero = psr.zero(); print "zero:", zero; print; r1 = psr.random(4); print "r1:", r1; print; print "r1:", r1; print; print "r1-r1:", r1-r1; print; r2 = psr.random(4); print "r2:", r2; print; print "r2:", r2; print; print "r2-r2:", r2-r2; print; #sys.exit(); r3 = r1 + r2; print "r3:", r3; print; r4 = r1 * r2 + one; print "r4:", r4; print; e = psr.exp(1); print "e:", e; print; r5 = r1 * r2 + e; print "r5:", r5; print; #print "psr.gens: ", [ str(i) for i in psr.gens() ]; [one,x,y,z] = psr.gens(); print "x:", x; print "y:", y; print "z:", z; print; r6 = one - y; print "r6:", r6; print; r7 = one / r6; print "r7:", r7; print; s = psr.sin(1); print "s:", s; print; r8 = psr.gcd(y,s); print "r8:", r8; print; ## s1 = s.evaluate( QQ(0) ); ## print "s1:", s1; ## print; c = psr.cos(1); print "c:", c; print; ## c1 = c.evaluate( QQ(0) ); ## print "c1:", c1; ## print; s2c2 = s*s+c*c; # sin^2 + cos^2 = 1 print "s2c2:", s2c2; print; #sys.exit(); # conversion from polynomials pr = Ring("Q(x,y,z) L"); print "pr:", pr; print; [one,xp,yp,zp] = pr.gens(); p1 = one; p2 = one - yp; ps1 = psr.fromPoly(p1); ps2 = psr.fromPoly(p2); # rational function as power series: ps3 = ps1 / ps2; print "p1:", p1; print "p2:", p2; print "ps1:", ps1; print "ps2:", ps2; print "ps3:", ps3; print; p1 = one * 2 + yp**3 - yp**5; p2 = one - yp**2 + yp**4; ps1 = psr.fromPoly(p1); ps2 = psr.fromPoly(p2); # rational function as power series: ps3 = ps1 / ps2; ps4 = ps3.integrate( QQ(1), 1 ); ps5 = ps3.differentiate(1); print "p1:", p1; print "p2:", p2; print "ps1:", ps1; print "ps2:", ps2; print "ps3:", ps3; print "ps4:", ps4; print "ps5:", ps5; print; #sys.exit(); # # floating point examples # dr = MultiSeriesRing(cofac=DD(),names=psr.ring.polyRing().getVars(),truncate=psr.ring.truncate()); print "dr:", dr; print; de = dr.exp(1); print "de:", de; print; def f(a): return a.totalDeg(); ps = psr.create(f); print "ps:", ps; print; def g(a): return a.maxDeg(); ps1 = psr.create(g); print "ps1:", ps1; print; ps2 = ps * ps1; print "ps2:", ps2; print; def h(a): return psr.ring.coFac.fromInteger( 2*a.maxDeg() ); ps3 = psr.create(jfunc=h); print "ps3:", ps3; print; ps4 = ps3 * ps1; print "ps4:", ps4; print; def k(a): if a.signum() > 0: r = psr.ring.coFac.fromInteger( 2*a.totalDeg() ); else: r = psr.ring.coFac.getONE(); #print "r: ", r; return r; ps5 = MPS(psr.ring.coFac,psr.ring.getVars(),f=k); print "ps5:", ps5; print; #sys.exit(); class coeff( MultiVarCoefficients ): def __init__(self,r): MultiVarCoefficients.__init__(self,r); self.coFac = r.coFac; def generate(self,i): #print "i: ", i; if i.signum() < 0: return self.coFac.getZERO(); else: if i.isZERO(): return self.coFac.getONE(); else: c = self.coFac.getONE(); #self.get( i-1 ).negate(); return c.divide( self.coFac.fromInteger(i.totalDeg()) ).divide( self.coFac.fromInteger(i.totalDeg()-1) ); ps6 = psr.create( clazz=coeff(psr.ring) ); print "ps6:", ps6; print; ps7 = ps6 - s; print "ps7:", ps7; print; #sys.exit(); class cosmap( MultiVarPowerSeriesMap ): def __init__(self,cofac): self.coFac = cofac; def map(self,ps): return ps.negate().integrate( self.coFac.getZERO(), 1 ).integrate( self.coFac.getONE(), 1 ); ps8 = psr.fixPoint( cosmap( psr.ring.coFac ) ); print "ps8:", ps8; print; ps9 = ps8 - c; print "ps9:", ps9; print; jas-2.5/examples/armbruster.py0000644000175000017500000000200111143314276016714 0ustar giovannigiovanni# # jython examples for jas. from jas import Module from jas import SubModule # Armbruster module example r = Module( "Rat(u,v,l) L" ); print "Module: " + str(r); print; ps = """ ( ( ( 1 ), ( 2 ), ( 0 ), ( l^2 ) ), ( ( 0 ), ( l + 3 v ), ( 0 ), ( u ) ), ( ( 1 ), ( 0 ), ( 0 ), ( l^2 ) ), ( ( l + v ), ( 0 ), ( 0 ), ( u ) ), ( ( l^2 ), ( 0 ), ( 0 ), ( v ) ), ( ( u ), ( 0 ), ( 0 ), ( v l + v^2 ) ), ( ( 1 ), ( 0 ), ( l + 3 v ), ( 0 ) ), ( ( l^2 ), ( 0 ), ( 2 u ), ( v ) ), ( ( 0 ), ( 1 ), ( l + v ), ( 0 ) ), ( ( 0 ), ( l^2 ), ( u ), ( 0 ) ), ( ( 0 ), ( v ), ( u l^2 ), ( 0 ) ), ( ( 0 ), ( v l + v^2 ), ( u^2 ), ( 0 ) ) ) """; f = SubModule( r, ps ); print "SubModule: " + str(f); print; rg = f.GB(); print "seq Output:", rg; print; print "isGB:", rg.isGB(); jas-2.5/examples/cgb_3.py0000644000175000017500000000177511304010406015507 0ustar giovannigiovanni# # jython examples for jas. # $Id: cgb_3.py 2882 2009-11-27 17:48:55Z kredel $ # import sys; from jas import Ring from jas import ParamIdeal from jas import startLog from jas import terminate # 2 univariate polynomials of degree 2 example for comprehensive GB # integral/rational function coefficients #r = Ring( "RatFunc(u,v) (x,y) L" ); r = Ring( "IntFunc(a3, b3, a2, b2, a1, b1, a0, b0) (x) L" ); print "Ring: " + str(r); print; ps = """ ( ( { a3 } x^3 + { a2 } x^2 + { a1 } x + { a0 } ), ( { b3 } x^3 + { b2 } x^2 + { b1 } x + { b0 } ) ) """; f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; #sys.exit(); # long run time startLog(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; #sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; sys.exit(); bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); jas-2.5/examples/factors_me.py0000644000175000017500000000466211177352632016674 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_me.py 2624 2009-05-03 17:34:18Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring from jas import Ideal from jas import terminate from jas import startLog # polynomial examples: factorization #r = Ring( "Mod 1152921504606846883 (x,y,z) L" ); #r = Ring( "Rat(x,y,z) L" ); #r = Ring( "C(x,y,z) L" ); #r = Ring( "Z(x,y,z) L" ); #r = Ring( "Q(x) L" ); r = Ring( "Z(x) L" ); #r = Ring( "Mod 11 (x) L" ); print "Ring: " + str(r); print; [one,x] = r.gens(); #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**4 - 1; #f = x**3 - x**2 + x - 1; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; #f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; #f = x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8; #f = (-1+x)*(1+x)*(1+x+x**2)*(1-x+x**2); f = x**16 - 1; # == #f = (-1+x)*(1+x)*(1+x**2)*(1+x**4)*(1+x**8); print "f = ", f; print; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; print "G = ", G; #print "factor time =", t, "milliseconds"; g = one; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #d = g / c; #m = g % c; #print "d = ", d; #print "m = ", m; #print; #startLog(); terminate(); jas-2.5/examples/std.py0000644000175000017500000000155511456131252015333 0ustar giovannigiovanni# # jython examples for jas. # $Id: std.py 3348 2010-10-15 19:59:39Z kredel $ # import sys; from jas import Ring, PolyRing, Ideal, PSIdeal, QQ, ZM from jas import startLog, terminate # example from CLO(UAG), 4.4 #R = PolyRing( ZM(32003), "x,y,z" ); R = PolyRing( QQ(), "x,y,z" ); print "Ring: " + str(R); print; [one,x,y,z] = R.gens(); f1 = x**5 - x * y**6 - z**7; f2 = x * y + y**3 + z**3; f3 = x**2 + y**2 - z**2; L = [f1,f2,f3]; #print "L = ", str(L); F = R.ideal( list=L ); print "Ideal: " + str(F); print; PR = R.powerseriesRing(); print "Power series ring: " + str(PR); print; Fp = PSIdeal(PR,L); print "Power series ideal: " + str(Fp); print; startLog(); #9+5 # truncate at total degree 9 S = Fp.STD(); #print "std: " + str(S); print; for p in S.list: #print "p = ", str(p.asPolynomial()); print "p = ", str(p); print; #sys.exit(); #terminate(); jas-2.5/examples/nabeshima_cgbF1.py0000644000175000017500000000172111253240426017464 0ustar giovannigiovanni# # jython examples for jas. # $Id: nabeshima_cgbF1.py 2811 2009-09-13 18:59:35Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Nabashima, ISSAC 2007, example F1 # integral function coefficients r = Ring( "IntFunc(a, b) (y,x) G" ); print "Ring: " + str(r); print; ps = """ ( ( { a } x^4 y + x y^2 + { b } x ), ( x^3 + 2 x y ), ( { b } x^2 + x^2 y ) ) """; #startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; #sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/wa_41.jas0000644000175000017500000000033310653077260015600 0ustar giovannigiovanni# solvable polynomials, Weyl algebra A_4,1: (a,b,e1,e2,e3,e4) G RelationTable ( ( e4 ), ( e2 ), ( e2 e4 - e1 ), ( e4 ), ( e3 ), ( e3 e4 - e2 ) ) ( ( e1 e3^3 + e2^2 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) jas-2.5/examples/0dim_primary-decomp.rb0000644000175000017500000000134511641147136020356 0ustar giovannigiovanni# # jruby examples for jas. # $Id: 0dim_primary-decomp.rb 3783 2011-09-29 20:00:31Z kredel $ # require "examples/jas" # polynomial examples: zero dimensional ideals prime and primary decomposition r = PolyRing.new(QQ(),"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); f1 = (x**2 - 5)**2; f2 = y**2 - 5; f3 = z**3 - y * x ; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; F = r.ideal( "", [f1,f2,f3] ); puts "F = ", F; puts; startLog(); t = System.currentTimeMillis(); Q = F.primaryDecomp(); t = System.currentTimeMillis() - t; puts "Q = " + str(Q); puts; puts "primary decomp time = " +str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/katsura8m.jas0000644000175000017500000000465212041330416016600 0ustar giovannigiovanni#Katsura equations for N = 8: #Mod 2^127-1: 39 digits, Mersenne prime 12: Mod 170141183460469231731687303715884105727 #Mod 2^3217-1: 969 digits Mersenne prime 18: Mod 259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071 #Mod 170141183460469231731687303715884105727 Mod 23 #Mod 32003 #Mod 536870909 #Mod 4294967291 #Mod 9223372036854775783 (u8,u7,u6,u5,u4,u3,u2,u1,u0) G ( u8*u8 + u7*u7 + u6*u6 + u5*u5 + u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 + u5*u5 + u6*u6 + u7*u7 + u8*u8 - u0, u8*0 + u7*u8 + u6*u7 + u5*u6 + u4*u5 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 + u5*u4 + u6*u5 + u7*u6 + u8*u7 - u1, u8*0 + u7*0 + u6*u8 + u5*u7 + u4*u6 + u3*u5 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 + u5*u3 + u6*u4 + u7*u5 + u8*u6 - u2, u8*0 + u7*0 + u6*0 + u5*u8 + u4*u7 + u3*u6 + u2*u5 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 + u5*u2 + u6*u3 + u7*u4 + u8*u5 - u3, u8*0 + u7*0 + u6*0 + u5*0 + u4*u8 + u3*u7 + u2*u6 + u1*u5 + u0*u4 + u1*u3 + u2*u2 + u3*u1 + u4*u0 + u5*u1 + u6*u2 + u7*u3 + u8*u4 - u4, u8*0 + u7*0 + u6*0 + u5*0 + u4*0 + u3*u8 + u2*u7 + u1*u6 + u0*u5 + u1*u4 + u2*u3 + u3*u2 + u4*u1 + u5*u0 + u6*u1 + u7*u2 + u8*u3 - u5, u8*0 + u7*0 + u6*0 + u5*0 + u4*0 + u3*0 + u2*u8 + u1*u7 + u0*u6 + u1*u5 + u2*u4 + u3*u3 + u4*u2 + u5*u1 + u6*u0 + u7*u1 + u8*u2 - u6, u8*0 + u7*0 + u6*0 + u5*0 + u4*0 + u3*0 + u2*0 + u1*u8 + u0*u7 + u1*u6 + u2*u5 + u3*u4 + u4*u3 + u5*u2 + u6*u1 + u7*u0 + u8*u1 - u7, u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 + u5 + u6 + u7 + u8 - 1 ) jas-2.5/examples/katsura6.jas0000644000175000017500000000137011353207070016417 0ustar giovannigiovanni#Katsura equations for N = 6: (u6,u5,u4,u3,u2,u1,u0) G ( u6*u6 + u5*u5 + u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 + u5*u5 + u6*u6 - u0, u6*0 + u5*u6 + u4*u5 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 + u5*u4 + u6*u5 - u1, u6*0 + u5*0 + u4*u6 + u3*u5 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 + u5*u3 + u6*u4 - u2, u6*0 + u5*0 + u4*0 + u3*u6 + u2*u5 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 + u5*u2 + u6*u3 - u3, u6*0 + u5*0 + u4*0 + u3*0 + u2*u6 + u1*u5 + u0*u4 + u1*u3 + u2*u2 + u3*u1 + u4*u0 + u5*u1 + u6*u2 - u4, u6*0 + u5*0 + u4*0 + u3*0 + u2*0 + u1*u6 + u0*u5 + u1*u4 + u2*u3 + u3*u2 + u4*u1 + u5*u0 + u6*u1 - u5, u6 + u5 + u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 + u5 + u6 - 1 ) jas-2.5/examples/syzy2.py0000644000175000017500000000237011505613454015641 0ustar giovannigiovanni# # jython examples for jas. # $Id: syzy2.py 3450 2010-12-26 10:21:33Z kredel $ # from jas import Ring from jas import Ideal # ? example r = Ring( "Rat(x,y,z) L" ); print "Ring: " + str(r); print; ps = """ ( ( z^3 - y ), ( y z - x ), ( y^3 - x^2 z ), ( x z^2 - y^2 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; rg = f.GB(); print "seq Output:", rg; print; from edu.jas.gbmod import SyzygyAbstract; from edu.jas.poly import ModuleList; from edu.jas.gbmod import ModGroebnerBaseAbstract; s = SyzygyAbstract().zeroRelations( rg.list ); sl = ModuleList(rg.pset.ring,s); print "syzygy:", sl; print; z = SyzygyAbstract().isZeroRelation( s, rg.list ); print "is zero s ?", if z: print "true" else: print "false" print; zg = sl; for i in range(1,len(r.ring.vars)+1): print "\n %s. resolution" % i; sl = zg; mg = ModGroebnerBaseAbstract().GB(sl); print "Mod GB: ", mg; print; zg = SyzygyAbstract().zeroRelations(mg); print "syzygies of Mod GB: ", zg; print; if ModGroebnerBaseAbstract().isGB( mg ): print "is GB"; else: print "is not GB"; if SyzygyAbstract().isZeroRelation(zg,mg): print "is Syzygy"; else: print "is not Syzygy"; if not zg.list: break; jas-2.5/examples/squarefree.py0000644000175000017500000000157011224463142016677 0ustar giovannigiovanni# # jython examples for jas. # $Id: squarefree.py 2717 2009-07-06 21:02:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import PolyRing, QQ, ZM from jas import terminate from jas import startLog # polynomial examples: squarefree: characteristic 0 r = PolyRing(QQ(),"x, y, z",PolyRing.lex) print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); a = r.random(k=2,l=3); b = r.random(k=2,l=3); c = r.random(k=1,l=3); if a.isZERO(): a = x; if b.isZERO(): b = y; if c.isZERO(): c = z; f = a**2 * b**3 * c; print "a = ", a; print "b = ", b; print "c = ", c; print "f = ", f; print; t = System.currentTimeMillis(); F = r.squarefreeFactors(f); t = System.currentTimeMillis() - t; print "factors:"; for g in F.keys(): i = F[g]; print "g = %s**%s" % (g,i); print print "factor time =", t, "milliseconds"; #startLog(); terminate(); jas-2.5/examples/syzsolv.py0000644000175000017500000000124712136720410016264 0ustar giovannigiovanni# # jython examples for jas. # $Id: syzsolv.py 4381 2013-04-27 09:57:28Z kredel $ # from jas import SolvableRing # ? example rs = """ Rat(a,b,e1,e2,e3) L RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e1 ), ( e3 ), ( e2 ), ( e2 e3 - e2 ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( e1 e3^3 + e2^10 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) """; f = r.ideal( ps ); print "SolvIdeal: " + str(f); print; from edu.jas.gbmod import SolvableSyzygyAbstract; R = SolvableSyzygyAbstract().resolution( f.pset ); for i in range(0,R.size()): print "\n %s. resolution" % (i+1); print "\n", R[i]; jas-2.5/examples/u_2_wa_1.py0000644000175000017500000000344312136720410016127 0ustar giovannigiovanni# # jython examples for jas. # $Id: u_2_wa_1.py 4381 2013-04-27 09:57:28Z kredel $ # from jas import SolvableRing from edu.jas.application import Ideal # U_t, dim 2 and WA_1 example rs1 = """ # solvable polynomials, U_t, dim_2 and Weyl algebra A_1: Rat(D,X,a,b) G|2| RelationTable ( ( b ), ( a ), ( a b + %s a ) ( X ), ( D ), ( D X + 1 ) ) """; rs1c = """ # solvable polynomials, Weyl algebra A_1: Rat(D,X) G RelationTable ( ( X ), ( D ), ( D X + 1 ) ) """; rs2 = """ # solvable polynomials, U_t, dim_2 and Weyl algebra A_1: Rat(a,b,D,X) G|2| RelationTable ( ( b ), ( a ), ( a b + %s a ) ( X ), ( D ), ( D X + 1 ) ) """; rs2c = """ # solvable polynomials, U_t, dim_2: Rat(a,b) G RelationTable ( ( b ), ( a ), ( a b + %s a ) ) """; ps = """ ( ( a - X^%s ), ( b - D X + %s ) ) """; for t in (2,3,5,7,11,13,17,19,23,27,31,37,43): #for t in (5,7): r1 = SolvableRing( rs1 % t ); r1c = SolvableRing( rs1c ); #print "SolvableRing: " + str(r1); #print "SolvableRing: " + str(r1c); #print; it = r1.ideal( ps % (t,t) ); #print "SolvableIdeal: " + str(it); #print; # compute I_{\phi_t} \cap WA_1^opp x = it.leftGB(); print "seq left x:", x; y = Ideal(x.pset).intersect(r1c.ring); len = y.list.size(); print "seq left y: ", y; print "seq left y len: ", len; #print; #------------------------------------- r2 = SolvableRing( rs2 % t ); r2c = SolvableRing( rs2c % t ); #print "SolvableRing: " + str(r2); #print "SolvableRing: " + str(r2c); #print; ikt = r2.ideal( ps % (t,t) ); #print "SolvableIdeal: " + str(ikt); print; # compute ker(\phi_t) x = ikt.leftGB(); print "seq left x:", x; y = Ideal(x.pset).intersect(r2c.ring); len = y.list.size(); print "seq left y: ", y; print "seq left y len: ", len; #print; #------------------------------------- jas-2.5/examples/hawes2.py0000644000175000017500000000224711505167460015736 0ustar giovannigiovanni# # jython examples for jas. # $Id: hawes2.py 3438 2010-12-24 19:06:24Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} import sys; from jas import Ring, PolyRing, QQ, ZZ, RF from jas import Ideal from jas import startLog from jas import terminate #startLog(); # Hawes & Gibson example 2 # rational function coefficients #r = Ring( "RatFunc(a, c, b) (y2, y1, z1, z2, x) G" ); r = PolyRing( RF(PolyRing(ZZ(),"a, c, b",PolyRing.lex)), "y2, y1, z1, z2, x", PolyRing.grad ); print "Ring: " + str(r); print; ps = """ ( ( x + 2 y1 z1 + { 3 a } y1^2 + 5 y1^4 + { 2 c } y1 ), ( x + 2 y2 z2 + { 3 a } y2^2 + 5 y2^4 + { 2 c } y2 ), ( 2 z2 + { 6 a } y2 + 20 y2^3 + { 2 c } ), ( 3 z1^2 + y1^2 + { b } ), ( 3 z2^2 + y2^2 + { b } ) ) """; f = r.ideal( ps ); print "Ideal: " + str(f); print; rg = f.GB(); rg = f.GB(); print "GB:", rg; print; bg = rg.isGB(); print "isGB:", bg; print; startLog(); terminate(); #sys.exit(); jas-2.5/examples/trinks_str.rb0000644000175000017500000000224312056644004016712 0ustar giovannigiovanni# # jruby examples for jas. # $Id: trinks_str.rb 4311 2012-12-02 12:22:28Z kredel $ # #load "examples/jas.rb" require "examples/jas" # trinks 6/7 example #r = Ring.new( "Mod 19 (B,S,T,Z,P,W) L" ); #r = Ring.new( "Mod 1152921504606846883 (B,S,T,Z,P,W) L" ); # 2^60-93 #r = Ring.new( "Quat(B,S,T,Z,P,W) L" ); #r = Ring.new( "Z(B,S,T,Z,P,W) L" ); #r = Ring.new( "C(B,S,T,Z,P,W) L" ); #r = Ring.new( "Rat(B,S,T,Z,P,W) L" ); r = PolyRing.new( QQ(),"B,S,T,Z,P,W", PolyRing.lex); puts "Ring: " + r.to_s; puts; ps = """ ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B**3 ), ( 99 W - 11 B S + 3 B**2 ), ( 10000 B**2 + 6600 B + 2673 ) ) """; # ( 10000 B**2 + 6600 B + 2673 ) # ( B**2 + 33/50 B + 2673/10000 ) #f = Ideal.new( r, ps ); #puts "Ideal: " + str(f); #puts; f = r.ideal( ps ); puts "Ideal: " + f.to_s; puts; #startLog(); rg = f.GB(); #puts "seq Output:", rg; #puts; rg = f.parGB(2); #puts "par Output:", rg; #puts; f.distClient(); # starts in background rg = f.distGB(2); #puts "dist Output:", rg; #puts; f.distClientStop(); # stops them terminate(); jas-2.5/examples/u_sl_2.py0000644000175000017500000000116712137010656015724 0ustar giovannigiovanni# # jython examples for jas. # $Id: u_sl_2.py 4387 2013-04-27 17:58:06Z kredel $ # from jas import SolvableRing # U(sl_2) example rs = """ # solvable polynomials, U(sl_2): Rat(e,f,h) G RelationTable ( ( f ), ( e ), ( e f - h ), ( h ), ( e ), ( e h + 2 e ), ( h ), ( f ), ( f h - 2 f ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( e^2 + f^3 ) ) """; f = r.ideal( ps ); print "SolvableIdeal: " + str(f); print; rg = f.leftGB(); print "seq left GB:", rg; print; rg = f.twosidedGB(); print "seq twosided GB:", rg; print; #rg = f.rightGB(); #print "seq right GB:", rg; #print; jas-2.5/examples/factors_algeb_trans_build.rb0000644000175000017500000000263511537152632021702 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_algeb_trans_build.rb 3565 2011-03-13 14:32:58Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: factorization over Q(sqrt(2))(x)(sqrt(x))[y] Yr = EF.new(QQ()).extend("w2","w2^2 - 2").extend("x").extend("wx","wx^2 - x").polynomial("y").build(); puts "Yr = " + str(Yr); puts one,w2,x,wx,y = Yr.gens(); puts "one = " + str(one); puts "w2 = " + str(w2); puts "x = " + str(x); puts "wx = " + str(wx); puts "y = " + str(y); puts; f = ( y**2 - x ) * ( y**2 - 2 ); #f = ( y**2 - x )**2 * ( y**2 - 2 )**3; #f = ( y**4 - x * 2 ); #f = ( y**7 - x * 2 ); #f = ( y**2 - 2 ); #f = ( y**2 - x ); #f = ( w2 * y**2 - 1 ); #f = ( y**2 - 1/x ); #f = ( y**2 - (1,2) ); #f = ( y**2 - 1/x ) * ( y**2 - (1,2) ); puts "f = ", f; puts; #exit(); startLog(); t = System.currentTimeMillis(); G = Yr.factors(f); t = System.currentTimeMillis() - t; #puts "G = ", G; #puts "factor time =", t, "milliseconds"; #exit(); puts "f = " + str(f); g = one; for h, i in G do if i > 1 then puts "h**i = " + str(h) + "**" + str(i); else puts "h = " + str(h); end h = h**i; g = g*h; end #puts "g = " + str(g); if f == g then puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): true" ; else puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): " + str(f==g); end puts; #startLog(); terminate(); jas-2.5/examples/katsura4.jas0000644000175000017500000000061711353207070016420 0ustar giovannigiovanni#Katsura equations for N = 4: (u4,u3,u2,u1,u0) L ( u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 - u0, u4*0 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 - u1, u4*0 + u3*0 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 - u2, u4*0 + u3*0 + u2*0 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 - u3, u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 - 1 ) jas-2.5/examples/sicora.rb0000644000175000017500000000105211773623314015773 0ustar giovannigiovanni# # jruby examples for jas. # $Id: sicora.rb 3970 2012-06-30 16:18:21Z kredel $ # require "examples/jas" # sicora, e-gb example r = PolyRing.new(ZZ(),"t",PolyRing.lex) puts "Ring: " + str(r); puts; one,x = r.gens(); f1 = 2 * t + 1; f2 = t**2 + 1; ff = r.ideal( "", [f1,f2] ); puts "ideal: " + str(ff); puts; #t = System.currentTimeMillis(); gg = ff.eGB(); #t = System.currentTimeMillis() - t; puts "seq e-GB: " + str(gg); puts; puts "is e-GB: " + str(gg.iseGB()); #puts "e-GB time = " + str(t) + " milliseconds"; puts; #startLog(); terminate(); jas-2.5/examples/syzy2.rb0000644000175000017500000000246411653754360015626 0ustar giovannigiovanni# # jruby examples for jas. # $Id: syzy2.rb 3823 2011-11-01 11:33:05Z kredel $ # require "examples/jas" # ? example r = Ring.new( "Rat(x,y,z) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( z^3 - y ), ( y z - x ), ( y^3 - x^2 z ), ( x z^2 - y^2 ) ) """; f = SimIdeal.new( r, ps ); puts "Ideal: " + str(f); puts; rg = f.GB(); puts "seq Output:" + str(rg); puts; #startLog(); include_class "edu.jas.poly.ModuleList"; include_class "edu.jas.gbmod.SyzygyAbstract"; include_class "edu.jas.gbmod.ModGroebnerBaseAbstract"; s = SyzygyAbstract.new().zeroRelations( rg.list ); sl = ModuleList.new(rg.pset.ring,s); puts "syzygy:" + str(sl); puts; z = SyzygyAbstract.new().isZeroRelation( s, rg.list ); print "is Syzygy ? " if z puts "true" else puts "false" end puts; zg = sl; for i in 1..(r.ring.nvar) puts "\n #{i}. resolution"; sl = zg; mg = ModGroebnerBaseAbstract.new().GB(sl); puts "Mod GB: " + str(mg); puts; zg = SyzygyAbstract.new().zeroRelations(mg); puts "syzygies of Mod GB: " + str(zg); puts; if ModGroebnerBaseAbstract.new().isGB( mg ) puts "is GB"; else puts "is not GB"; end if SyzygyAbstract.new().isZeroRelation(zg,mg) puts "is Syzygy"; else puts "is not Syzygy"; end if not zg break; end end terminate(); jas-2.5/examples/machines.test0000644000175000017500000000041210401313222016632 0ustar giovannigiovanni# maschines file for jas for junit tests localhost:4712 # first host is master on different local port localhost:4711 # second host with port localhost:4711 # third host with port localhost:4711 # last host with port #localhost:4711 # ignored host # eof jas-2.5/examples/mkplotold2.py0000644000175000017500000000550011112336474016624 0ustar giovannigiovanni# # read output of jas runnings and prepare input for gnuplot # import re; import os; exam = "kat_6"; runs = "t16"; #bname = exam + "_" + runs; bname = "k6seqpair-2" fname = bname + ".out"; oname = bname + ".po"; f=open(fname,"r"); print f; o=open(oname,"w"); print o; res = {}; resold = {}; for line in f: if line.find("executed in") > 0: print line, if line.find("sequential") >= 0: s = re.search(".*in (\d+)",line); if s != None: t = ('0', s.group(1)); res[ int( t[0] ) ] = float( t[1] ); else: if line.find("-old") >= 0: s = re.search("(\d+).*in (\d+)",line); if s != None: t = s.groups(); t0 = int( t[0] ); if resold.has_key( t0 ): resold[ t0 ] = ( resold[ t0 ] + float(t[1]) )/2.0; else: resold[ t0 ] = float( t[1] ); else: s = re.search("(\d+).*in (\d+)",line); if s != None: t = s.groups(); t0 = int( t[0] ); if res.has_key( t0 ): res[ t0 ] = ( res[ t0 ] + float(t[1]) )/2.0; else: res[ t0 ] = float( t[1] ); # print "t = ", t, "\n"; print "\nres = ", res; ks = res.keys(); #print "ks = ", ks; ks.sort(); #print "ks = ", ks; s1 = ks[0]; st = res[ s1 ]; #print "s1 = ", s1; #print "st = ", st; speed = {}; speedold = {}; for k in ks: speed[ k ] = st / res[ k ]; #print "speed = ", speed; print; o.write("\n#threads time speedup\n"); print "#threads time speedup"; for k in ks: o.write(str(k) + " " + str(res[k]) + " " + str(speed[k]) +"\n"); print(str(k) + " " + str(res[k]) + " " + str(speed[k])); f.close(); o.close(); #--------------------------------------- pscript = """ set grid set term %s set output "%s.ps" set title "GBs of Katsuras example on compute" set time set xlabel "#CPUs" set multiplot set size 0.75,0.5 set origin 0,0.5 set ylabel "milliseconds" # smooth acsplines plot "%s.po" title '%s computing time' with linespoints, \ "%s.po" using 1:( %s/$1 ) title '%s ideal' with linespoints set size 0.75,0.5 set origin 0,0 set ylabel "speedup" # smooth bezier plot "%s.po" using 1:3 title '%s speedup' with linespoints, \ "%s.po" using 1:1 title '%s ideal' with linespoints unset multiplot pause mouse """; #--------------------------------------- psname = bname + ".ps"; pname = "plotin.gp" p=open(pname,"w"); print p; pscript = pscript % ("x11",bname,bname,exam,bname,str(res[0]),exam,bname,exam,bname,exam); #pscript = pscript % ("postscript",bname,bname,exam,bname,str(res[0]),exam,bname,exam,bname,exam); p.write(pscript); p.close(); os.system("gnuplot plotin.gp"); cmd = "ps2pdf " + psname; print "cmd: " + cmd; #os.system(cmd); jas-2.5/examples/staggered_linear_basis.py0000644000175000017500000001263011645562730021226 0ustar giovannigiovanni# implementation of the Staggered Linear Basis Algorithm of Gebauer and M\"oller # "Buchberger's algorithm and Staggered Linear Bases" # in Proceedings of SYMSAC 1986 (Waterloo/Ontario), pages 218--221 # ACM Press, 1986 # Originally from http://www.math.usm.edu/perry/Research/staggered_linear_basis.py # small changes for JAS compatibility, changes are labled with JAS # $Id: staggered_linear_basis.py 3801 2011-10-13 13:21:29Z kredel $ # usage: staglinbasis(F) where F is a list of polynomials # result: groebner basis of F # example: # sage: R = PolynomialRing(GF(32003),x,5) # sage: I = sage.rings.ideal.Cyclic(R,5).homogenize() # sage: F = list(I.gens()) # sage: B = staglinbasis(F) # >> reduction to zero: (9, 12, x1*x2*x3^3*x4^2) x2 # >> reduction to zero: (7, 12, x1*x2*x3^3*x4^2) x2 # >> reduction to zero: (5, 12, x1^2*x3^3*x4^2) x1 # ... [more omitted] # >> 32 reductions to zero # sage: len(B) # >> 42 # minimal_pair # used to select a minimal critical pair from a list; # form of the list is (i,j,t) where t=lcm(lt(g[i]),lt(g[j])); # chosen by smallest lcm # inputs: list of pairs P # outputs: minimal pair in P def minimal_pair(P): result = P.pop() P.add(result) for p in P: if p[2] < result[2]: result = p return result # spol # compute the s-polynomial corresponding to the critical pair p # inputs: critical pair p, basis G # outputs: s-polynomial def spol(p,G): i,j,tij = p R = G[i].parent() # JAS ti = R.monomial_quotient(tij,G[i].lm()) tj = R.monomial_quotient(tij,G[j].lm()) return ti*G[i] - tj*G[j] # monid_quotient # computes the quotient I:J of the monomial ideals I and J # for each tI in I, and for each tJ in J, it computes lcm(tI,tJ)/tJ # this corresponds to computing the u's such that uv is in I for each v in J # note that the ideals must be simplified for this to work correctly # (see below) # inputs: lists of monomials I and J (generators of ideals) # outputs: list of monomials that generate I:J def monid_quotient(I,J,R): # JAS result = set() for tI in I: # R = tI.parent() #JAS for tJ in J: u = R.monomial_quotient(tI.lcm(tJ),tJ).lm() # JAS if not any(R.monomial_divides(t,u) for t in result): result.add(u) return result # monid_add # expands the monomial ideal I by the monomial t # simplifies the result # inputs: list of monomials I (generators of ideal), monomial t # outputs: simplified I+(t) def monid_add(I,t): result = set() R = t.parent() for u in I: if not(R.monomial_divides(t,u)) and not(R.monomial_divides(u,t)): result.add(u) if not any(R.monomial_divides(u,t) for u in result): result.add(t) return result # simplify_monid # simplifies the list of generators of the monomial ideal I # by pruning redundant elements # inputs: list of monomials I (generators of ideal) # outputs: simplified I def simplify_monid(I,R): # JAS result = set() for t in I: #R = t.parent() #JAS if not any(u != t and R.monomial_divides(u,t) for u in I): result.add(t) return result # staglinbasis # computes the Groebner Basis of a polynomial ideal using the # Staggered Linear Basis algorithm of Gebauer-Moeller # inputs: list of polynomials F # outputs: Groebner basis of F def staglinbasis(F): # tracks the number of zero reductions num_zrs = 0 # get polynomial ring R = F[0].parent() G = list(F) # JAS m = len(G) # Z is the set of monomial used to detect principal syzygies # in general, Z should be simplified anytime you modify it Z = [set([G[j].lm() for j in xrange(i)]) for i in xrange(m)] Z = [simplify_monid(ZI,R) for ZI in Z] # JAS # initial set of critical pairs P = set() for i in xrange(m-1): for j in xrange(i+1,m): tij = G[i].lm().lcm(G[j].lm()) tj = R.monomial_quotient(tij,G[j].lm()) # JAS if not any(R.monomial_divides(t,tj) for t in Z[j]): P.add((i,j,tij)) # main loop while len(P) != 0: # choose the pair w/smallest lcm p = minimal_pair(P) P.remove(p) # compute S-polynomial, reduce it s = spol(p,G) i,j,tij = p r = s.reduce(G) if r == 0: print "reduction to zero:", p, R.monomial_quotient(tij,G[j].lm()) num_zrs += 1 else: # new polynomial; add to basis r *= r.lc()**(-1) G.append(r) # update ideals here, also below # need new ideal for G[-1]=r, essentially # Znew = (Z[j] + t[i])):(lcm(t[i],t[j])/t[j]) + (t[1], ..., t[m]) # where t[i] = lm(g[i]) Znew = Z[j].copy() # JAS Znew.update([G[i].lm()]) Znew = simplify_monid(Znew,R) #JAS tj = R.monomial_quotient(tij,G[j].lm()).lm() # JAS Znew = monid_quotient(Znew,[tj],R) # JAS Znew.update([g.lm() for g in G[:-1]]) Znew = simplify_monid(Znew,R) Z.append(Znew) # compute new critical pairs w/new polynomial m = len(G) - 1 for i in xrange(m): tim = G[i].lm().lcm(G[m].lm()) tm = R.monomial_quotient(tim,G[m].lm()) # don't add pairs detected by Z[m] if not any(R.monomial_divides(t,tm) for t in Z[m]): P.add((i,m,tim)) # update Z[j] Z[j].add(R.monomial_quotient(tij,G[j].lm()).lm()) # JAS Z[j] = simplify_monid(Z[j],R) # JAS # prune pairs detected by new Z[j] Q = set() for (i,j,tij) in P: tj = R.monomial_quotient(tij,G[j].lm()) if any(R.monomial_divides(t,tj) for t in Z[j]): Q.add((i,j,tij)) P.difference_update(Q) print num_zrs, "reductions to zero" return G jas-2.5/examples/rose.jas0000644000175000017500000000113210653077260015633 0ustar giovannigiovanni# of rose (U3,U4,A46) L ( U4^4 - 20/7 A46^2, A46^2 U3^4 + 7/10 A46 U3^4 + 7/48 U3^4 - 50/27 A46^2 - 35/27 A46 - 49/216, A46^5 U4^3 + 7/5 A46^4 U4^3 + 609/1000 A46^3 U4^3 + 49/1250 A46^2 U4^3 - 27391/800000 A46 U4^3 - 1029/160000 U4^3 + 3/7 A46^5 U3 U4^2 + 3/5 A46^6 U3 U4^2 + 63/200 A46^3 U3 U4^2 + 147/2000 A46^2 U3 U4^2 + 4137/800000 A46 U3 U4^2 - 7/20 A46^4 U3^2 U4 - 77/125 A46^3 U3^2 U4 - 23863/60000 A46^2 U3^2 U4 - 1078/9375 A46 U3^2 U4 - 24353/1920000 U3^2 U4 - 3/20 A46^4 U3^3 - 21/100 A46^3 U3^3 - 91/800 A46^2 U3^3 - 5887/200000 A46 U3^3 - 343/128000 U3^3 ) jas-2.5/examples/jas.groovy0000644000175000017500000000450411143314276016212 0ustar giovannigiovanni/* * groovy interface to jas. * $Id: $ */ package edu.jas.groovy import java.lang.System import java.io.StringReader import edu.jas.structure.* import edu.jas.arith.* import edu.jas.poly.* import edu.jas.gb.* import edu.jas.gbmod.* import edu.jas.vector.* import edu.jas.application.* import edu.jas.util.* import edu.jas.ufd.* //import edu.jas.* //import edu.* //PrettyPrint.setInternal(); import edu.jas.kern.ComputerThreads; import org.apache.log4j.BasicConfigurator; //t = new ComputerThreads() //println "t = " + t //p = t.getPool() //println "p = " + p //l = new BasicConfigurator() //println "l = " + l //l.configure() def startLog = { BasicConfigurator.configure(); } //startLog(); def terminate = { ComputerThreads.terminate(); } class Ring { def ring; def pset; def Ring(ringstr="",ring=null) { if ( ring == null ) { def sr = new StringReader( ringstr ); def tok = new GenPolynomialTokenizer(sr); this.pset = tok.nextPolynomialSet(); this.ring = this.pset.ring; } else { this.ring = ring; } } String toString() { return ring.toString(); } def ideal(ringstr="",list=null) { return new Ideal(this,ringstr,list); } } class Ideal { def ring; def list; def pset; def Ideal(ring,ringstr="",list=null) { this.ring = ring; if ( list == null ) { def sr = new StringReader( ringstr ); def tok = new GenPolynomialTokenizer(ring.pset.ring,sr); this.list = tok.nextPolynomialList(); } else { this.list = list; } this.pset = new OrderedPolynomialList(ring.ring,this.list); } String toString() { return pset.toString(); } def GB() { def s = this.pset; def F = s.list; def t = System.currentTimeMillis(); def G = new GroebnerBaseSeq().GB(F); t = System.currentTimeMillis() - t; println "sequential executed in ${t} ms"; return new Ideal(this.ring,"",G); } def isGB() { def s = this.pset; def F = s.list; def t = System.currentTimeMillis(); def b = new GroebnerBaseSeq().isGB(F); t = System.currentTimeMillis() - t; println "isGB executed in ${t} ms"; return b; } } jas-2.5/examples/intprog2.py0000644000175000017500000000160010373614370016300 0ustar giovannigiovanni# # jython for jas example 2 integer programming. # $Id: intprog2.py 597 2006-02-12 11:16:09Z kredel $ # # CLO2, p372 # 3 A - 2 B + C = -1 # 4 A + B - C - D = 5 # # max: A + 1000 B + C + 100 D # import sys; from jas import Ring from jas import Ideal r = Ring( "Rat(w1,w2,w3,w4,t,z1,z2) W( (0,0,0,0,1,1,1),(1,1,2,2,0,0,0) )" ); print "Ring: " + str(r); print; ps = """ ( ( z1^3 z2^4 - w1 ), ( t^2 z2^3 - w2 ), ( t z1^2 - w3 ), ( t z1 - w4 ), ( t z1 z2 - 1 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; rg = f.GB(); print "seq Output:", rg; print; pf = """ ( ( t z2^6 ) ) """; fp = Ideal( r, pf ); print "Ideal: " + str(fp); print; nf = fp.NF(rg); print "NFs: " + str(nf); print; #rg = f.parGB(2); #print "par Output:", rg; #print; #f.distClient(); # starts in background #rg = f.distGB(2); #print "dist Output:", rg; #print; #sys.exit(); jas-2.5/examples/boolean_gb.py0000644000175000017500000000200611633202702016614 0ustar giovannigiovanniimport sys; from jas import Ring, PolyRing, ParamIdeal, QQ, ZM, RR from jas import startLog, terminate # Boolean coefficient boolean GB # see S. Inoue and A. Nagai "On the Implementation of Boolean Groebner Bases" in ASCM 2009 # Z_2 regular ring coefficent example r = PolyRing(RR(ZM(2),3),"x,y",PolyRing.lex); print "r = " + str(r); #print len(r.gens()) [s1,s2,s3,x,y] = r.gens(); one = r.one(); print "one = " + str(one); print "s1 = " + str(s1); print "s2 = " + str(s2); print "s2 = " + str(s3); print "x = " + str(x); print "y = " + str(y); brel = [ x**2 - x, y**2 - y ]; print "brel = " + str(brel[0]) + ", " + str(brel[1]); pl = [ ( one + s1 + s2 ) * ( x*y + x +y ), s1 * x + s1, s2 * y + s2, x * y ]; #pl = [ ( one ) * ( x*y + x +y ), s1 * x + s1, s2 * y + s2, x * y ]; pl = pl + brel; startLog(); f = ParamIdeal(r,list=pl); print "Ideal: " + str(f); gb = f.regularGB(); print "boolean GB: " + str(gb); #ss = gb.stringSlice(); #print "regular string slice: " + str(ss); terminate(); #sys.exit(); jas-2.5/examples/powerseries.py0000644000175000017500000000737211437245700017116 0ustar giovannigiovanni# # jython examples for jas. # $Id: powerseries.py 3307 2010-08-31 18:36:49Z kredel $ # import sys; from jas import QQ from jas import DD from jas import Ring from jas import SeriesRing from jas import startLog from edu.jas.ps import Coefficients from edu.jas.ps import UnivPowerSeriesMap # example for power series # # # # rational number examples # psr = SeriesRing("Q(y)"); print "psr:", psr; print; one = psr.one(); print "one:", one; print; zero = psr.zero(); print "zero:", zero; print; r1 = psr.random(4); print "r1:", r1; print; print "r1:", r1; print; print "r1-r1:", r1-r1; print; r2 = psr.random(4); print "r2:", r2; print; print "r2:", r2; print; print "r2-r2:", r2-r2; print; #sys.exit(); r3 = r1 + r2; print "r3:", r3; print; r4 = r1 * r2 + one; print "r4:", r4; print; e = psr.exp(); print "e:", e; print; r5 = r1 * r2 + e; print "r5:", r5; print; #print "psr.gens: ", [ str(i) for i in psr.gens() ]; [one,y] = psr.gens(); print "y:", y; print; r6 = one - y; print "r6:", r6; print; r7 = one / r6; print "r7:", r7; print; s = psr.sin(); print "s:", s; print; r8 = psr.gcd(y,s); print "r8:", r8; print; s1 = s.evaluate( QQ(0) ); print "s1:", s1; print; c = psr.cos(); print "c:", c; print; c1 = c.evaluate( QQ(0) ); print "c1:", c1; print; s2c2 = s*s+c*c; # sin^2 + cos^2 = 1 print "s2c2:", s2c2; print; # # floating point examples # dr = SeriesRing(cofac=DD()); print "dr:", dr; print; de = dr.exp(); print "de:", de; print; d0 = de.evaluate( DD(0) ); print "d0:", d0; print; d1 = de.evaluate( DD(0.5) ); print "d1:", d1; print; d01 = de.evaluate( DD(0.000000000000000001) ); print "d01:", d01; print; def f(a): return a*a; ps = psr.create(f); print "ps:", ps; print; def g(a): return a+a; ps1 = psr.create(g); print "ps1:", ps1; print; ps2 = ps * ps1; print "ps2:", ps2; print; def h(a): return psr.ring.coFac.fromInteger( 2*a ); ps3 = psr.create(jfunc=h); print "ps3:", ps3; print; ps4 = ps3 * ps1; print "ps4:", ps4; print; # does not work, since get() is not known def k(a): if a > 0: return get(a-1).multiply( psr.ring.coFac.fromInteger( 2*a ) ); else: return psr.ring.coFac.fromInteger( 2*a ); #no#ps5 = psr.create(jfunc=k); #no#print "ps5:", ps5; #no#print; class coeff( Coefficients ): def __init__(self,cofac): self.coFac = cofac; def generate(self,i): if i == 0: return self.coFac.getZERO(); else: if i == 1: return self.coFac.getONE(); else: c = self.get( i-2 ).negate(); return c.divide( self.coFac.fromInteger(i) ).divide( self.coFac.fromInteger(i-1) ); ps6 = psr.create( clazz=coeff(psr.ring.coFac) ); print "ps6:", ps6; print; ps7 = ps6 - s; print "ps7:", ps7; print; class cosmap( UnivPowerSeriesMap ): def __init__(self,cofac): self.coFac = cofac; def map(self,ps): return ps.negate().integrate( self.coFac.getZERO() ).integrate( self.coFac.getONE() ); ps8 = psr.fixPoint( cosmap( psr.ring.coFac ) ); print "ps8:", ps8; print; ps9 = ps8 - c; print "ps9:", ps9; print; # conversion from polynomials pr = Ring("Q(y) L"); print "pr:", pr; print; [one,yp] = pr.gens(); p1 = one; p2 = one - yp; ps1 = psr.fromPoly(p1); ps2 = psr.fromPoly(p2); # rational function as power series: ps3 = ps1 / ps2; print "p1:", p1; print "p2:", p2; print "ps1:", ps1; print "ps2:", ps2; print "ps3:", ps3; print; p1 = one * 2 + yp**3 - yp**5; p2 = one - yp**2 + yp**4; ps1 = psr.fromPoly(p1); ps2 = psr.fromPoly(p2); # rational function as power series: ps3 = ps1 / ps2; ps4 = ps3.integrate( QQ(1) ); ps5 = ps3.differentiate(); print "p1:", p1; print "p2:", p2; print "ps1:", ps1; print "ps2:", ps2; print "ps3:", ps3; print "ps4:", ps4; print "ps5:", ps5; print; #sys.exit(); jas-2.5/examples/radical-decomp_charp_infin_0dim.py0000644000175000017500000000236111377546034022664 0ustar giovannigiovanni# # jython examples for jas. # $Id: radical-decomp_charp_infin_0dim.py 3157 2010-05-27 19:46:36Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, ZM, RF # polynomial examples: ideal radical decomposition, inseparable case, 0-dim cr = PolyRing(ZM(5),"c",PolyRing.lex); print "coefficient Ring: " + str(cr); rf = RF(cr); print "coefficient quotient Ring: " + str(rf); r = PolyRing(rf,"x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,c,x,y,z] = r.gens(); print one,c,x,y,z; #sys.exit(); #f1 = (x**2 - 5)**2; #f1 = (y**10 - x**5)**3; #f2 = y**6 + 2 * x * y**4 + 4 * x**2 * y**2 + 4 * x**3; #f2 = y**6 + 2 * x * y**4 + 3 * x**2 * y**2 + 4 * x**3; f1 = (x**2 + 2)**2; f2 = (y**2 + 2)**3; #f2 = f2**5; f3 = z**10 - c**5; f4 = (y**2 - x)**3; print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; #print "f4 = ", f4; print; F = r.ideal( list=[f1,f2,f3] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); t = System.currentTimeMillis() - t; print "R = ", R; print; print "decomp time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/chebyshev.py0000644000175000017500000000112211151514632016506 0ustar giovannigiovanni# # jython examples for jas. # $Id: chebyshev.py 2448 2009-02-26 13:31:07Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # chebyshev polynomial example # T(0) = 1 # T(1) = x # T(n) = 2 * x * T(n-1) - T(n-2) r = Ring( "Z(x) L" ); print "Ring: " + str(r); print; # sage like: with generators for the polynomial ring [one,x] = r.gens(); x2 = 2 * x; N = 10; T = [one,x]; for n in range(2,N): t = x2 * T[n-1] - T[n-2]; T.append( t ); for n in range(0,N): print "T[%s] = %s" % (n,T[n]); print; #sys.exit(); jas-2.5/examples/primes.py0000644000175000017500000000173412040773636016047 0ustar giovannigiovanni# # jython examples for jas. # $Id: primes.py 4262 2012-10-21 13:24:47Z kredel $ # #import sys; #from jas import startLog, terminate from edu.jas.arith import PrimeList # example for prime numbers # pl = PrimeList(PrimeList.Range.small); print "pl: " + str(pl); print; pp = ""; for i in range(0,pl.size()+10): pp = pp + " " + str(pl.get(i)) print "pp: " + pp; print; pl = PrimeList(PrimeList.Range.low); print "pl: " + str(pl); print; pp = ""; for i in range(0,pl.size()+10): pp = pp + " " + str(pl.get(i)) print "pp: " + pp; print; pl = PrimeList(PrimeList.Range.medium); print "pl: " + str(pl); print; pp = ""; for i in range(0,pl.size()+10): pp = pp + " " + str(pl.get(i)) print "pp: " + pp; print; pl = PrimeList(PrimeList.Range.large); print "pl: " + str(pl); print; pp = ""; for i in range(0,pl.size()+10): pp = pp + " " + str(pl.get(i)) print "pp: " + pp; print; #pl = PrimeList(PrimeList.Range.mersenne); #print "pl: " + str(pl); #print; jas-2.5/examples/atan.py0000644000175000017500000000360411476710552015471 0ustar giovannigiovanni# jython examples for jas. # $Id: atan.py 3392 2010-12-05 13:19:39Z kredel $ # import sys from java.lang import System from jas import Ring, RF, QQ, PolyRing from jas import terminate from jas import startLog # elementary integration atan examples r = PolyRing(QQ(),"x",PolyRing.lex); print "r = " + str(r); rf = RF(r); print "rf = " + str(rf.factory()); [one,x] = rf.gens(); print "one = " + str(one); print "x = " + str(x); print; #f = 1 / ( 1 + x**2 ); #f = 1 / ( x**2 - 2 ); #f = 1 / ( x**3 - 2 ); #f = ( x + 3 ) / ( x**2- 3 * x - 40 ); f = ( x**7 - 24 * x**4 - 4 * x**2 + 8 * x - 8 ) / ( x**8 + 6 * x**6 + 12 * x**4 + 8 * x**2 ); print "f = ", f; print; #sys.exit(); #startLog(); t = System.currentTimeMillis(); e1 = r.integrate(f); t = System.currentTimeMillis() - t; print "e1 = ", e1; print "integration time =", t, "milliseconds"; print t = System.currentTimeMillis(); e2 = f.integrate(); t = System.currentTimeMillis() - t; print "e2 = ", e2; print "integration time =", t, "milliseconds"; print #startLog(); terminate(); #sys.exit(); jas-2.5/examples/nabeshima_cgbF4.rb0000644000175000017500000000165411653002012017436 0ustar giovannigiovanni# # jruby examples for jas. # $Id: nabeshima_cgbF4.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Nabashima, ISSAC 2007, example F4 # integral function coefficients r = Ring.new( "IntFunc(a, b, c, d) (y, x) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( { a } x^3 y + { c } x y^2 ), ( x^4 y + { 3 d } y ), ( { c } x^2 + { b } x y ), ( x^2 y^2 + { a } x^2 ), ( x^5 + y^5 ) ) """; #startLog(); f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; terminate(); exit(); bg = gs.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; #exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; bg = gs.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/powerseries_multi.rb0000644000175000017500000001107211773623314020277 0ustar giovannigiovanni# # jruby examples for jas. # $Id: powerseries_multi.rb 3970 2012-06-30 16:18:21Z kredel $ # require "examples/jas" # examples for power series # # rational number examples # psr = MultiSeriesRing.new("Q(x,y,z)",truncate=4); puts "psr: " + str(psr); puts; one = psr.one(); puts "one: " + str(one); #puts; zero = psr.zero(); puts "zero: " + str(zero); puts; r1 = psr.random(4); puts "r1: " + str(r1); #puts; puts "r1: " + str(r1); #puts; puts "r1-r1: " + str(r1-r1); puts; r2 = psr.random(4); puts "r2: " + str(r2); #puts; puts "r2: " + str(r2); #puts; puts "r2-r2: " + str(r2-r2); puts; #sys.exit(); r3 = r1 + r2; puts "r3: " + str(r3); puts; r4 = r1 * r2 + one; puts "r4: " + str(r4); puts; e = psr.exp(1); puts "e: " + str(e); puts; r5 = r1 * r2 + e; puts "r5: " + str(r5); puts; #puts "psr.gens: ", [ str(i) for i in psr.gens() ]; one,x,y,z = psr.gens(); puts "x: " + str(x); puts "y: " + str(y); puts "z: " + str(z); puts; r6 = one - y; puts "r6: " + str(r6); puts; r7 = one / r6; puts "r7: " + str(r7); puts; s = psr.sin(1); puts "s: " + str(s); puts; r8 = psr.gcd(y,s); puts "r8: " + str(r8); puts; ## s1 = s.evaluate( QQ(0) ); ## puts "s1: " + str(s1); ## puts; c = psr.cos(1); puts "c: " + str(c); puts; ## c1 = c.evaluate( QQ(0) ); ## puts "c1: " + str(c1); ## puts; s2c2 = s*s + c*c; # sin^2 + cos^2 = 1 puts "s2c2: " + str(s2c2); puts "s2c2 == 1: " + str(s2c2.isONE()); puts; # conversion from polynomials pr = Ring.new("Q(x,y,z) L"); puts "pr: " + str(pr); puts; one,xp,yp,zp = pr.gens(); p1 = one; p2 = one - yp; ps1 = psr.fromPoly(p1); ps2 = psr.fromPoly(p2); # rational function as power series: ps3 = ps1 / ps2; puts "p1: " + str(p1); puts "p2: " + str(p2); puts "ps1: " + str(ps1); puts "ps2: " + str(ps2); puts "ps3: " + str(ps3); puts; p1 = one * 2 + yp**3 - yp**5; p2 = one - yp**2 + yp**4; ps1 = psr.fromPoly(p1); ps2 = psr.fromPoly(p2); # rational function as power series: ps3 = ps1 / ps2; ps4 = ps3.integrate( QQ(1), 1 ); ps5 = ps3.differentiate(1); puts "p1: " + str(p1); puts "p2: " + str(p2); puts "ps1: " + str(ps1); puts "ps2: " + str(ps2); puts "ps3: " + str(ps3); puts "ps4: " + str(ps4); puts "ps5: " + str(ps5); puts; #exit(); # # floating point examples # #dr = MultiSeriesRing.new(cofac=DD(),names=psr.ring.polyRing().getVars(),truncate=psr.ring.truncate()); dr = MultiSeriesRing.new("",psr.ring.truncate(),nil,DD(),psr.ring.polyRing().getVars()); puts "dr: " + str(dr); puts; de = dr.exp(1); puts "de: " + str(de); puts; # use lambdas: # type(a) == ExpVector f = lambda { |a| a.getVal(0) * a.getVal(1) * a.getVal(2) }; ps = psr.create(f); puts "ps: " + str(ps); puts; # type(a) == ExpVector g = lambda { |a| a.totalDeg() }; ps1 = psr.create(g); puts "ps1: " +str(ps1); puts; ps2 = ps * ps1; puts "ps2: " + str(ps2); puts; h = lambda { |a| psr.ring.coFac.fromInteger( 3 * a.totalDeg() ) }; ps3 = psr.create(nil,h); puts "ps3: " + str(ps3); puts; ps4 = ps3 * ps1; puts "ps4: " + str(ps4); puts; #exit(); # does not work, since get() is not known #def k(a) # if a > 0 # return get(a-1).multiply( psr.ring.coFac.fromInteger( 2*a ) ); # else # return psr.ring.coFac.fromInteger( 2*a ); # end #end #no#ps5 = psr.create(jfunc=k); #no#puts "ps5: ", ps5; #no#puts; class Mycoeff < MultiVarCoefficients def initialize(ring,ifunc=nil,jfunc=nil) super(ring); @coFac = ring.coFac; @ifunc = ifunc; @jfunc = jfunc; end def generate(i) # type(i) == ExpVector if i.signum() <= 0 return @coFac.getONE(); else dep = i.dependencyOnVariables(); #if dep.length == 0 # return @coFac.getZERO(); #end i1 = i.subst( dep[0], i.getVal(dep[0])-1 ); # 0 <= i1 < i c = get( i1 ).negate(); c = c.divide( @coFac.fromInteger(i.maxDeg()) ).sum( @coFac.fromInteger(i.totalDeg()-1) ); #puts "c: " + str(c) + " i: " + str(i); return c; end end end ps6 = psr.create(nil,nil, Mycoeff.new(psr.ring) ); puts "ps6: " + str(ps6); puts; ps7 = ps6*2 + s - ps6 - ps6; puts "ps7: " + str(ps7); puts "ps7 == s: " + str(ps7 == s); puts; #exit(); class Cosmap include MultiVarPowerSeriesMap # for interfaces use Module notations def initialize(cofac) @coFac = cofac; end def map(ps) return ps.negate().integrate( @coFac.getZERO(), 1 ).integrate( @coFac.getONE(), 1 ); end end ps8 = psr.fixPoint( Cosmap.new( psr.ring.coFac ) ); puts "ps8: " + str(ps8); puts; ps9 = ps8 - c; puts "ps9: " + str(ps9); puts "ps9 == 0: " + str(ps9.isZERO()); puts; #exit(); jas-2.5/examples/prime-decomp_algeb_trans-plain.rb0000644000175000017500000000205211637331234022533 0ustar giovannigiovanni# # jruby examples for jas. # $Id: prime-decomp_algeb_trans-plain.rb 3777 2011-09-24 10:36:13Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: prime / primary decomposition in Q[w2,x,wx,y,z] Q = PolyRing.new(QQ(),"w2,x,wx,y,z",PolyRing.lex); puts "Q = " + str(Q); e,w2,x,wx,y,z = Q.gens(); puts "e = " + str(e); puts "w2 = " + str(w2); puts "x = " + str(x); puts "wx = " + str(wx); puts "y = " + str(y); puts "z = " + str(z); w1 = w2**2 - 2; w2 = wx**2 - x; f1 = ( y**2 - x ) * ( y**2 - 2 ); #f1 = ( y**2 - x ) * ( y**2 - 2 )**2; f2 = ( z**2 - y**2 ); puts "w1 = " + str(w1); puts "w2 = " + str(w2); puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts; #sys.exit(); startLog(); F = Q.ideal( "", [w1,w2,f1,f2] ); puts "F = ", F; puts; #sys.exit(); t = System.currentTimeMillis(); P = F.primeDecomp(); #P = F.primaryDecomp(); t1 = System.currentTimeMillis() - t; puts "P = ", P; puts; puts "prime/primary decomp time = " + str(t1) + " milliseconds"; puts; puts "F = ", F; puts; #startLog(); terminate(); jas-2.5/examples/radical-decomp_charp_infin_0dim.rb0000644000175000017500000000217311653043730022630 0ustar giovannigiovanni# # jruby examples for jas. # $Id: radical-decomp_charp_infin_0dim.rb 3817 2011-10-29 18:37:12Z kredel $ # require "examples/jas" # polynomial examples: ideal radical decomposition, inseparable case, 0-dim cr = PolyRing.new(ZM(5),"c",PolyRing.lex); puts "coefficient Ring: " + str(cr); rf = RF(cr); puts "coefficient quotient Ring: " + str(rf); r = PolyRing.new(rf,"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,c,x,y,z = r.gens(); puts one,c,x,y,z; #sys.exit(); #f1 = (x**2 - 5)**2; #f1 = (y**10 - x**5)**3; #f2 = y**6 + 2 * x * y**4 + 4 * x**2 * y**2 + 4 * x**3; #f2 = y**6 + 2 * x * y**4 + 3 * x**2 * y**2 + 4 * x**3; f1 = (x**2 + 2)**2; f2 = (y**2 + 2)**3; #f2 = f2**5; f3 = z**10 - c**5; f4 = (y**2 - x)**3; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); #puts "f4 = " + str(f4); puts; F = r.ideal( "", list=[f1,f2,f3] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "decomp time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/e-gb.rb0000644000175000017500000000143511641415316015325 0ustar giovannigiovanni# # jruby examples for jas. # $Id: e-gb.rb 3786 2011-09-30 19:38:55Z kredel $ # require "examples/jas" # e-gb and d-gb example to compare with hermit normal form r = PolyRing.new( ZZ(), "x4,x3,x2,x1", PolyRing.lex ); puts "Ring: " + str(r); puts; one,x4,x3,x2,x1 = r.gens(); f1 = x1 + 2 * x2 + 3 * x3 + 4 * x4 + 3; f2 = 3 * x2 + 2 * x3 + x4 + 2; f3 = 3 * x3 + 5 * x4 + 1; f4 = 5 * x4 + 4; L = [f1,f2,f3,f4]; #puts "L = " + str(L); f = r.ideal( "", L ); puts "Ideal: " + str(f); puts; #startLog(); g = f.eGB(); puts "seq e-GB: " + str(g); puts "is e-GB: " + str(g.iseGB()); puts; #sys.exit(); d = f.dGB(); puts "seq d-GB: " + str(d); puts "is d-GB: " + str(d.isdGB()); puts; #startLog(); puts "d-GB == e-GB:" + str(g.pset.equals(d.pset)); jas-2.5/examples/montes_ex112.rb0000644000175000017500000000273111653002012016724 0ustar giovannigiovanni# # jruby examples for jas. # $Id: montes_ex112.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Montes JSC 2002, 33, 183-208, example 11.2 # integral function coefficients r = PolyRing.new( PolyRing.new(QQ(),"f, e, d, c, b, a",PolyRing.lex), "y,x", PolyRing.lex ); #r = PolyRing.new( PolyRing.new(QQ(),"f, e, d, c, b, a",PolyRing.grad), "y,x", PolyRing.lex ); #r = PolyRing.new( PolyRing.new(QQ(),"f, e, d, c, b, a",PolyRing.lex), "y,x", PolyRing.grad ); #r = PolyRing.new( PolyRing.new(QQ(),"e, d, c, b, f, a",PolyRing.lex), "y,x", PolyRing.grad ); puts "Ring: " + str(r); puts; #one,e,d,c,b,f,a,y,x = r.gens(); one,f,e,d,c,b,a,y,x = r.gens(); puts "gens: " + r.gens().each{ |f| str(f) }.join(","); puts; f1 = x**2 + b * y**2 + 2 * c * x * y + 2 * d * x + 2 * e * y + f; f2 = x + c * y + d; f3 = b * y + c * x + e; F = [f1,f2,f3]; puts "F: " + F.each{ |f| str(f) }.join(","); puts; #startLog(); If = r.paramideal( "", list = F ); puts "ParamIdeal: " + str(If); puts; G = If.GB(); puts "GB: " + str(G); puts; ## sys.exit(); startLog(); GS = If.CGBsystem(); #GS = If.CGBsystem(); #GS = If.CGBsystem(); puts "CGBsystem: " + str(GS); puts; bg = GS.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; terminate(); exit(); CG = If.CGB(); puts "CGB: " + str(CG); puts; bg = CG.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/alg_surface.py0000644000175000017500000000134411630417274017015 0ustar giovannigiovanni# # jython examples for jas. # $Id: alg_surface.py 3757 2011-09-03 12:34:04Z kredel $ # import sys from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import QQ, AN, RF, EF from jas import terminate from jas import startLog # polynomial examples: Yr = EF(QQ()).extend("x,y").extend("z","z^2 + x^2 + y^2 - 1").build(); #print "Yr = " + str(Yr); #print [one,x,y,z] = Yr.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); print; f = (1+z)*(1-z); # / ( x**2 + y**2 ); print "f = " + str(f); print; g = f / (1 - z); print "g = " + str(g); print; #startLog(); terminate(); jas-2.5/examples/ascm_demo.py0000644000175000017500000000260711316340174016467 0ustar giovannigiovanni# # jython examples for jas. # $Id: ascm_demo.py 2932 2009-12-29 08:40:28Z kredel $ # import sys; from jas import Ring, PolyRing, ParamIdeal, QQ from jas import startLog, terminate # Raksanyi & Walter example # integral/rational function coefficients r = PolyRing(PolyRing(QQ(),"a1,a2,a3,a4",PolyRing.grad),"x1,x2,x3,x4",PolyRing.lex); #print "r = " + str(r); [one,a1,a2,a3,a4,x1,x2,x3,x4] = r.gens(); pl = [ ( x4 - ( a4 - a2 ) ), ( x1 + x2 + x3 + x4 - ( a1 + a3 + a4 ) ), ( x1 * x3 + x1 * x4 + x2 * x3 + x3 * x4 - ( a1 * a4 + a1 * a3 + a3 * a4 ) ), ( x1 * x3 * x4 - ( a1 * a3 * a4 ) ) ]; f = ParamIdeal(r,list=pl); print "ParamIdeal: " + str(f); gs = f.CGBsystem(); #print "CGBsystem: " + str(gs); #print; print f.CGB(); print gs.isCGBsystem(); #rs = gs.regularRepresentation(); #print "regular representation: " + str(rs); rs = gs.regularRepresentationBC(); print "boolean closed regular representation: " + str(rs); print rs.isRegularGB(); rsg = rs.regularGB(); print "regular GB: " + str(rsg); print rsg.isRegularGB(); #ss = rsg.stringSlice(); #print "regular string slice: " + str(ss); startLog(); terminate(); sys.exit(); print "one = " + str(one); print "a1 = " + str(a1); print "a2 = " + str(a2); print "a3 = " + str(a3); print "a4 = " + str(a4); print "x1 = " + str(x1); print "x2 = " + str(x2); print "x3 = " + str(x3); print "x4 = " + str(x4); jas-2.5/examples/solvable.rb0000644000175000017500000000133312136716620016321 0ustar giovannigiovanni# # jruby examples for jas. # $Id: solvable.rb 4380 2013-04-27 09:42:41Z kredel $ # require "examples/jas" # WA_32 solvable polynomial example rs = """ # solvable polynomials, Weyl algebra A_3,2: Rat(a,b,e1,e2,e3) G|3| RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e1 ), ( e3 ), ( e2 ), ( e2 e3 - e2 ) ) """; r = SolvableRing.new( rs ); puts "SolvableRing: " + str(r); puts; ps = """ ( ( e1 e3^3 + e2^10 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) """; f = r.ideal( ps ); puts "SolvableIdeal: " + str(f); puts; rg = f.leftGB(); puts "seq left GB: " + str(rg); puts; rg = f.twosidedGB(); puts "seq twosided GB: " + str(rg); puts; rg = f.rightGB(); puts "seq right GB: " + str(rg); puts; startLog(); terminate(); jas-2.5/examples/hawes2mod.py0000644000175000017500000000272111505167460016433 0ustar giovannigiovanni# # jython examples for jas. # $Id: hawes2mod.py 3438 2010-12-24 19:06:24Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} import sys; from jas import Ring, PolyRing, RF, ZZ, QQ from jas import Ideal from jas import startLog from jas import terminate from edu.jas.arith import ModIntegerRing #startLog(); # Hawes & Gibson example 2 # rational function coefficients #r = Ring( "RatFunc(a, c, b) (y2, y1, z1, z2, x) G" ); r = PolyRing( RF(PolyRing(ZZ(),"a, c, b",PolyRing.lex)), "y2, y1, z1, z2, x", PolyRing.grad ); print "Ring: " + str(r); print; ps = """ ( ( x + 2 y1 z1 + { 3 a } y1^2 + 5 y1^4 + { 2 c } y1 ), ( x + 2 y2 z2 + { 3 a } y2^2 + 5 y2^4 + { 2 c } y2 ), ( 2 z2 + { 6 a } y2 + 20 y2^3 + { 2 c } ), ( 3 z1^2 + y1^2 + { b } ), ( 3 z2^2 + y2^2 + { b } ) ) """; f = r.paramideal( ps ); print "Ideal: " + str(f); print; fi = f.toIntegralCoeff(); print "Ideal: " + str(fi); print; #mf = ModIntegerRing( str(2**60-93), True ); mf = ModIntegerRing( str(19), True ); fm = fi.toModularCoeff(mf); print "Ideal: " + str(fm); print; fmq = fm.toQuotientCoeff(); print "Ideal: " + str(fmq); print; rg = fmq.GB(); print "GB:", rg; print; bg = rg.isGB(); print "isGB:", bg; print; terminate(); #sys.exit(); jas-2.5/examples/word_solvable_trans.rb0000644000175000017500000000437512134571100020562 0ustar giovannigiovanni# # jruby examples for jas. # $Id: word_solvable_trans.rb 4373 2013-04-20 19:53:37Z kredel $ # #load "examples/jas.rb" require "examples/jas" # non-commutative polynomial examples: solvable polynomials example r = WordPolyRing.new(QQ(),"a,b,e1,e2,e3"); puts "WordPolyRing: " + str(r); puts; one,a,b,e1,e2,e3 = r.gens(); puts "one = " + str(one); puts "a = " + str(a); puts "b = " + str(b); puts "e1 = " + str(e1); puts "e2 = " + str(e2); puts "e3 = " + str(e3); puts; r1 = e3 * e1 - (e1 * e3 - e1); r2 = e3 * e2 - (e2 * e3 - e2); r3 = e1 * a - a * e1; r4 = e1 * b - b * e1; r5 = e2 * a - a * e2; r6 = e2 * b - b * e2; r7 = e3 * a - a * e3; r8 = e3 * b - b * e3; f1 = e1 * e3**3 + e2**10 - a; f2 = e1**3 * e2**2 + e3; f3 = e3**3 + e3**2 - b; puts "r1 = " + str(r1); puts "r2 = " + str(r2); puts "r3 = " + str(r3); puts "r4 = " + str(r4); puts "r5 = " + str(r5); puts "r6 = " + str(r6); puts "r7 = " + str(r7); puts "r8 = " + str(r8); puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; ff = r.ideal( "", [r1,r2,r3,r4,r5,r6,r7,r8,f1,f2,f3] ); puts "ff = " + str(ff); puts; startLog(); gg = ff.GB(); puts "gg = " + str(gg); puts "isGB(gg) = " + str(gg.isGB()); puts; #exit(0); # now as solvable polynomials p = PolyRing.new(QQ(),"a,b,e1,e2,e3"); #is automatic: ? one,a,b,e1,e2,e3 = p.gens(); relations = [e3, e1, e1*e3 - e1, e3, e2, e2*e3 - e2]; puts "relations: = " + relations.join(", ") { |r| r.to_s }; puts; rp = SolvPolyRing.new( QQ(), "a,b,e1,e2,e3", PolyRing.grad, relations); puts "SolvPolyRing: " + str(rp); puts; puts "gens =" + rp.gens().join(", ") { |r| r.to_s }; one,a,b,e1,e2,e3 = rp.gens(); #one,I,J,K,a,b,e1,e2,e3 = rp.gens(); f1 = - a + e2**10 + e1 * e3**3; #puts "f1 = " + f1.to_s; f2 = e1**3 * e2**2 + e3; #puts "f2 = " + f2.to_s; f3 = e3**3 + e3**2 - b; #puts "f3 = " + f3.to_s; #puts "+ f3 type(#{f3}) = #{f3.elem.class}\n"; #puts "+ f3.val = " + f3.elem.getMap().map { |e,c| c.to_s + " " + e.to_s }.join(", "); ff = [ f1, f2, f3 ]; puts "ff = " + ff.join(", ") { |r| r.to_s }; puts ii = rp.ideal( "", ff ); puts "SolvableIdeal: " + str(ii); puts; rgt = ii.twosidedGB(); puts "seq twosided GB:" + str(rgt); puts "isTwosidedGB: " + str(rgt.isTwosidedGB()); puts puts "rgt: " + rgt.list.join(", ") { |r| r.to_s }; puts; jas-2.5/examples/roots_real_tower.rb0000644000175000017500000000201011543637436020104 0ustar giovannigiovanni# # jruby examples for jas. # $Id: roots_real_tower.rb 3588 2011-03-27 13:43:58Z kredel $ # require "examples/jas" # polynomial examples: real roots tower over Q r = EF.new(QQ()).realExtend("q","q^3 - 3", "[1,2]").realExtend("w", "w^2 - q", "[1,2]").realExtend("s", "s^5 - 2", "[1,2]").polynomial("x").build(); puts "Ring: " + str(r); puts; one,q,w,s,x = r.gens(); f = x**2 - w * s; puts "f = " + f.to_s; puts; startLog(); t = System.currentTimeMillis(); rr = r.realRoots(f); t = System.currentTimeMillis() - t; #puts "rr = " + str(rr); puts "rr = " + str(rr.map{ |a| str(a.elem.ring.getRoot())+"," }); puts "real roots time = " + str(t) + " milliseconds"; eps = QQ(1,10) ** (BigDecimal::DEFAULT_PRECISION); puts "eps = " + str(eps); t = System.currentTimeMillis(); rr = r.realRoots(f,eps); t = System.currentTimeMillis() - t; #puts "rr = ", [ str(r) for r in rr ]; puts "rr = " + str(rr.map{ |a| str(a.elem.decimalMagnitude())+"," }); puts "real roots time = " + str(t) + " milliseconds"; #startLog(); terminate(); jas-2.5/examples/rose.py0000644000175000017500000000256112036572570015516 0ustar giovannigiovanni# # jython examples for jas. # $Id: rose.py 4250 2012-10-14 17:25:12Z kredel $ # import sys; from jas import Ring, Ideal from jas import startLog # example from rose (modified) #r = Ring( "Mod 19 (U3,U4,A46) L" ); #r = Ring( "Mod 1152921504606846883 (U3,U4,A46) L" ); # 2^60-93 #r = Ring( "Quat(U3,U4,A46) L" ); #r = Ring( "Z(U3,U4,A46) L" ); #r = Ring( "C(U3,U4,A46) L" ); r = Ring( "Rat(A46,U3,U4) G" ); print "Ring: " + str(r); print; ps = """ ( ( U4^4 - 20/7 A46^2 ), ( A46^2 U3^4 + 7/10 A46 U3^4 + 7/48 U3^4 - 50/27 A46^2 - 35/27 A46 - 49/216 ), ( A46^5 U4^3 + 7/5 A46^4 U4^3 + 609/1000 A46^3 U4^3 + 49/1250 A46^2 U4^3 - 27391/800000 A46 U4^3 - 1029/160000 U4^3 + 3/7 A46^5 U3 U4^2 + 3/5 A46^6 U3 U4^2 + 63/200 A46^3 U3 U4^2 + 147/2000 A46^2 U3 U4^2 + 4137/800000 A46 U3 U4^2 - 7/20 A46^4 U3^2 U4 - 77/125 A46^3 U3^2 U4 - 23863/60000 A46^2 U3^2 U4 - 1078/9375 A46 U3^2 U4 - 24353/1920000 U3^2 U4 - 3/20 A46^4 U3^3 - 21/100 A46^3 U3^3 - 91/800 A46^2 U3^3 - 5887/200000 A46 U3^3 - 343/128000 U3^3 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; #startLog(); rg = f.GB(); #print "seq Output:", rg; #print; #sys.exit(); rg = f.parNewGB(2); #print "par-new Output:", rg; #print; rg = f.parGB(2); #print "par Output:", rg; #print; f.distClient(); # starts in background rg = f.distGB(2); #print "dist Output:", rg; #print; sys.exit(); jas-2.5/examples/intersect.py0000644000175000017500000000132011147066002016524 0ustar giovannigiovanni# # jython examples for jas. # $Id: intersect.py 2435 2009-02-18 20:13:55Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # ideal intersection example r = Ring( "Rat(x,y,z) L" ); print "Ring: " + str(r); print; ps1 = """ ( ( x - 1 ), ( y - 1 ), ( z - 1 ) ) """; ps2 = """ ( ( x - 2 ), ( y - 3 ), ( z - 3 ) ) """; F1 = r.ideal( ps1 ); #print "Ideal: " + str(F1); #print; F2 = r.ideal( ps2 ); #print "Ideal: " + str(F2); #print; #startLog(); rg1 = F1.GB(); print "rg1 = ", rg1; print; rg2 = F2.GB(); print "rg2 = ", rg2; print; #startLog(); ig = F1.intersect(F2); print "rg1 intersect rg2 = ", ig; print; terminate(); #sys.exit(); jas-2.5/examples/module.rb0000644000175000017500000000117311644542070016000 0ustar giovannigiovanni# # jruby examples for jas. # $Id: module.rb 3797 2011-10-10 10:08:57Z kredel $ # require "examples/jas" # module example p = PolyRing.new(QQ(),"(u,v,l)", PolyRing.lex); #r = CommutativeModule.new( "Rat(u,v,l) L", nil, 4 ); r = CommutativeModule.new( "", p, 4 ); puts "Module: " + str(r); puts; G = r.gens(); puts "gens() = " + str( G.map { |e| str(e) }.join(", ") ); puts L = G.map { |e| e.elem.val } puts "gens() = " + str( L.map { |e| str(e) }.join(", ") ); puts M = r.submodul("", L ); puts "M = " + str(M); puts P = M.mset.getPolynomialList(); puts "P = " + str(P.toScript()); puts puts "M.isGB(): " + str(M.isGB()); puts jas-2.5/examples/montes_ex112.py0000644000175000017500000000304311474505546016773 0ustar giovannigiovanni# # jython examples for jas. # $Id: montes_ex112.py 3379 2010-11-28 17:03:34Z kredel $ # import sys; from jas import PolyRing, QQ, RF from jas import Ideal from jas import startLog from jas import terminate # Montes JSC 2002, 33, 183-208, example 11.2 # integral function coefficients r = PolyRing( PolyRing(QQ(),"f, e, d, c, b, a",PolyRing.lex), "y,x", PolyRing.lex ); #r = PolyRing( PolyRing(QQ(),"f, e, d, c, b, a",PolyRing.grad), "y,x", PolyRing.lex ); #r = PolyRing( PolyRing(QQ(),"f, e, d, c, b, a",PolyRing.lex), "y,x", PolyRing.grad ); #r = PolyRing( PolyRing(QQ(),"e, d, c, b, f, a",PolyRing.lex), "y,x", PolyRing.grad ); print "Ring: " + str(r); print; #[one,e,d,c,b,f,a,y,x] = r.gens(); [one,f,e,d,c,b,a,y,x] = r.gens(); print "gens: ", [ str(f) for f in r.gens() ]; print; f1 = x**2 + b * y**2 + 2 * c * x * y + 2 * d * x + 2 * e * y + f; f2 = x + c * y + d; f3 = b * y + c * x + e; F = [f1,f2,f3]; print "F: ", [ str(f) for f in F ]; print; #startLog(); If = r.paramideal( "", list = F ); print "ParamIdeal: " + str(If); print; G = If.GB(); print "GB: " + str(G); print; ## sys.exit(); startLog(); GS = If.CGBsystem(); #GS = If.CGBsystem(); #GS = If.CGBsystem(); print "CGBsystem: " + str(GS); print; bg = GS.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; terminate(); sys.exit(); CG = If.CGB(); print "CGB: " + str(CG); print; bg = CG.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/montes_ex111.rb0000644000175000017500000000217411653002012016724 0ustar giovannigiovanni# # jruby examples for jas. # $Id: montes_ex111.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Montes JSC 2002, 33, 183-208, example 11.1 # integral function coefficients r = PolyRing.new( PolyRing.new(QQ(),"c, b, a",PolyRing.lex), "z,y,x", PolyRing.lex ); puts "Ring: " + str(r); puts; one,c,b,a,z,y,x = r.gens(); puts "gens: " + r.gens().each{ |f| str(f) }.join(","); puts; f1 = x + c * y + b * z + a; f2 = c * x + y + a * z + b; f3 = b * x + a * y + z + c; F = [f1,f2,f3]; puts "F: " + F.each{ |f| str(f) }.join(","); puts; #startLog(); If = r.paramideal( "", list = F ); puts "ParamIdeal: " + str(If); puts; ## G = If.GB(); ## puts "GB: " + str(G); ## puts; ## sys.exit(); GS = If.CGBsystem(); GS = If.CGBsystem(); GS = If.CGBsystem(); puts "CGBsystem: " + str(GS); puts; bg = GS.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; terminate(); exit(); CG = If.CGB(); puts "CGB: " + str(CG); puts; bg = CG.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/nabeshima_cgbF3.py0000644000175000017500000000173611253240426017474 0ustar giovannigiovanni# # jython examples for jas. # $Id: nabeshima_cgbF3.py 2811 2009-09-13 18:59:35Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Nabashima, ISSAC 2007, example F3 # integral function coefficients r = Ring( "IntFunc(c, b, a, d) (x) L" ); print "Ring: " + str(r); print; ps = """ ( ( { a } x^4 + { c } x^2 + { b } ), ( { b } x^3 + x^2 + 2 ), ( { c } x^2 + { d } x ) ) """; #startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/trinks_sigbased_gb.py0000644000175000017500000000765011645621462020375 0ustar giovannigiovanni# # jython examples for jas. # $Id: trinks_sigbased_gb.py 3802 2011-10-13 17:43:15Z kredel $ # from java.lang import System, Integer from jas import PolyRing, ZZ, QQ, ZM from jas import terminate, startLog from basic_sigbased_gb import sigbased_gb from basic_sigbased_gb import ggv, ggv_first_implementation from basic_sigbased_gb import coeff_free_sigbased_gb from basic_sigbased_gb import arris_algorithm, min_size_mons from basic_sigbased_gb import f5, f5z from staggered_linear_basis import staglinbasis #r = PolyRing( QQ(), "(B,S,T,Z,P,W)", PolyRing.lex ); r = PolyRing( ZM(32003), "(B,S,T,Z,P,W)", PolyRing.lex ); #r = PolyRing( ZM(19), "(B,S,T,Z,P,W)", PolyRing.lex ); print "Ring: " + str(r); print; [one,B,S,T,Z,P,W] = r.gens(); p1 = 45 * P + 35 * S - 165 * B - 36; p2 = 35 * P + 40 * Z + 25 * T - 27 * S; p3 = 15 * W + 25 * S * P + 30 * Z - 18 * T - 165 * B**2; p4 = -9 * W + 15 * T * P + 20 * S * Z; p5 = P * W + 2 * T * Z - 11 * B**3; p6 = 99 * W - 11 * B * S + 3 * B**2; p7 = 10000 * B**2 + 6600 * B + 2673; F = [p1,p2,p3,p4,p5,p6,p7]; #F = [p1,p2,p3,p4,p5,p6]; f = r.ideal( list=F ); print "Ideal: " + str(f); print; #startLog(); rg = f.GB(); rg = f.GB(); if not rg.isGB(): print "seq Output:", rg; print; #------------------- sbgb = sigbased_gb(); arri = arris_algorithm(); arrm = min_size_mons(); ggv = ggv(); ggv1 = ggv_first_implementation(); f5 = f5(); ff5 = f5z(); if True: gg = staglinbasis(F); gg = staglinbasis(F); t = System.currentTimeMillis(); gg = staglinbasis(F); t = System.currentTimeMillis() - t; print "stag executed in " + str(t) + " milliseconds"; if not r.ideal(list=gg).isGB(): print "stag Output:" + str([ str(ggg) for ggg in gg]); print; if True: gg = sbgb.basis_sig(F); t = System.currentTimeMillis(); gg = sbgb.basis_sig(F); t = System.currentTimeMillis() - t; print "sbgb executed in " + str(t) + " milliseconds"; if not r.ideal(list=gg).isGB(): print "sbgb Output:" + str([ str(ggg) for ggg in gg]); print; if True: gg = ff5.basis_sig(F); t = System.currentTimeMillis(); gg = ff5.basis_sig(F); t = System.currentTimeMillis() - t; print "f5 executed in " + str(t) + " milliseconds"; if not r.ideal(list=gg).isGB(): print "f5 Output:" + str([ str(ggg) for ggg in gg]); print; if True: gg = ggv1.basis_sig(F); t = System.currentTimeMillis(); gg = ggv1.basis_sig(F); t = System.currentTimeMillis() - t; print "ggv executed in " + str(t) + " milliseconds"; if not r.ideal(list=gg).isGB(): print "ggv Output:" + str([ str(ggg) for ggg in gg]); print; if True: gg = arri.basis_sig(F); t = System.currentTimeMillis(); gg = arri.basis_sig(F); t = System.currentTimeMillis() - t; print "arri executed in " + str(t) + " milliseconds"; if not r.ideal(list=gg).isGB(): print "arri Output:" + str([ str(ggg) for ggg in gg]); print; ## Output: for Z_32003 and Trinks 7 ## sequential GB executed in 44 ms ## stag executed in 99 milliseconds ## sbgb executed in 1180 milliseconds ## f5 executed in 128 milliseconds ## ggv executed in 110 milliseconds ## arri executed in 116 milliseconds ## Output: for Z_32003 and Trinks 6 ## sequential GB executed in 302 ms ## stag executed in 213 milliseconds ## sbgb executed in 28849 milliseconds ## f5 executed in 1248 milliseconds ## ggv executed in 237 milliseconds ## arri executed in 410 milliseconds ## Output: for Q and Trinks 7 ## sequential GB executed in 104 ms ## stag executed in 223 milliseconds ## sbgb executed in 1155 milliseconds ## f5 executed in 226 milliseconds ## ggv executed in 98 milliseconds ## arri executed in 111 milliseconds ## Output: for Q and Trinks 6 ## sequential GB executed in 779 ms ## stag executed in 196 milliseconds ## sbgb executed in 740980 milliseconds ## f5 executed in 1435 milliseconds ## ggv executed in 717 milliseconds ## arri executed in 562 milliseconds jas-2.5/examples/trinks.py0000644000175000017500000000324212056637056016060 0ustar giovannigiovanni# # jython examples for jas. # $Id: trinks.py 4309 2012-12-02 11:40:30Z kredel $ # import sys; from jas import Ring, PolyRing, Ideal, QQ, ZZ, GF, ZM, CC from jas import startLog, terminate # trinks 6/7 example # QQ = rational numbers, ZZ = integers, CC = complex rational numbers, GF = finite field #QQ = QQ(); ZZ = ZZ(); CC = CC(); #r = PolyRing( GF(19),"B,S,T,Z,P,W", PolyRing.lex); #r = PolyRing( GF(1152921504606846883),"B,S,T,Z,P,W", PolyRing.lex); # 2^60-93 #r = PolyRing( GF(2**60-93),"B,S,T,Z,P,W", PolyRing.lex); #r = PolyRing( CC(),"B,S,T,Z,P,W", PolyRing.lex); #r = PolyRing( ZZ(),"B,S,T,Z,P,W", PolyRing.lex); # not for parallel r = PolyRing( QQ(),"B,S,T,Z,P,W", PolyRing.lex); print "Ring: " + str(r); print; # sage like: with generators for the polynomial ring #[one,I,B,S,T,Z,P,W] = r.gens(); # is automaticaly included #[one,B,S,T,Z,P,W] = r.gens(); # is automaticaly included f1 = 45 * P + 35 * S - 165 * B - 36; f2 = 35 * P + 40 * Z + 25 * T - 27 * S; f3 = 15 * W + 25 * S * P + 30 * Z - 18 * T - 165 * B**2; f4 = - 9 * W + 15 * T * P + 20 * S * Z; f5 = P * W + 2 * T * Z - 11 * B**3; f6 = 99 * W - 11 *B * S + 3 * B**2; f7 = 10000 * B**2 + 6600 * B + 2673; F = [ f1, f2, f3, f4, f5, f6, f7 ]; # smaller, faster #F = [ f1, f2, f3, f4, f5, f6 ]; # bigger, needs more time #print "F = ", [ str(f) for f in F ]; #print; I = r.ideal( "", list=F ); print "Ideal: " + str(I); print; rg = I.GB(); print "seq Output:", rg; print; #startLog(); rg = I.parGB(2); #print "par Output:", rg; #print; #sys.exit(); # if using ZZ coefficients I.distClient(); # starts in background rg = I.distGB(2); #print "dist Output:", rg; #print; I.distClientStop(); # stops them terminate(); jas-2.5/examples/intprog.py0000644000175000017500000000150710373614370016224 0ustar giovannigiovanni# # jython for jas example integer programming. # $Id: intprog.py 597 2006-02-12 11:16:09Z kredel $ # # CLO2, p370 # 4 A + 5 B + C = 37 # 2 A + 3 B + D = 20 # # max: 11 A + 15 B # import sys; from jas import Ring from jas import Ideal r = Ring( "Rat(w1,w2,w3,w4,z1,z2) W( (0,0,0,0,1,1),(1,1,2,2,0,0) )" ); print "Ring: " + str(r); print; ps = """ ( ( z1^4 z2^2 - w1 ), ( z1^5 z2^3 - w2 ), ( z1 - w3 ), ( z2 - w4 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; rg = f.GB(); print "seq Output:", rg; print; pf = """ ( ( z1^37 z2^20 ) ) """; fp = Ideal( r, pf ); print "Ideal: " + str(fp); print; nf = fp.NF(rg); print "NFs: " + str(nf); print; #rg = f.parGB(2); #print "par Output:", rg; #print; #f.distClient(); # starts in background #rg = f.distGB(2); #print "dist Output:", rg; #print; #sys.exit(); jas-2.5/examples/alg_stat_1p.rb0000644000175000017500000000264412020211330016672 0ustar giovannigiovanni# # jruby examples for jas. # $Id: alg_stat_1p.rb 4147 2012-08-31 19:39:05Z kredel $ # require "examples/jas" #startLog(); # example: Algebraic Statistics # Drton, Sturmfels, Sullivant, example 2.1.3 r = PolyRing.new(RF(PolyRing.new(QQ(),"u0,u1,u2,u12",PolyRing.lex)),"l1,l2",PolyRing.grad); puts "Ring: " + str(r); puts; puts one, u0, u1, u2, u12, l1 ,l2; puts; f1 = (u1+u12)*(l1+l2+2)*(l1+1)*(l1+l2+1)\ + (u12)*l1*(l1+1)*(l1+l2+1)\ - (u2+u12)*l1*(l1+l2+2)*(l1+l2+1)\ - (u0+u1+u2+u12)*l1*(l1+l2+2)*(l1+1) ; f2 = (u2+u12)*(l1+l2+2)*(l2+1)*(l1+l2+1)\ + (u12)*l2*(l2+1)*(l1+l2+1)\ - (u1+u12)*l2*(l1+l2+2)*(l1+l2+1)\ - (u0+u1+u2+u12)*l2*(l1+l2+2)*(l2+1) ; puts "f1 = " + str(f1); puts; puts "f2 = " + str(f2); puts #h = l1*l2*(l1+1)*(l2+1)*(l1+l2+1)*(l1+l2+2); h = l1*l2*(l1+1); hp = (l2+1); hpp = (l1+l2+1)*(l1+l2+2); puts "h = " + str(h); puts F = r.ideal("",[f1,f2]); puts "F = " + str(F); puts H = r.ideal("",[h]); puts "H = " + str(H); puts Hp = r.ideal("",[hp]); puts "Hp = " + str(Hp); puts Hpp = r.ideal("",[hpp]); puts "Hpp = " + str(Hpp); puts startLog(); G = F.GB(); puts "G = " + str(G); puts Q = G.sat(H); puts "Q = " + str(Q); puts Qp = Q.sat(Hp); puts "Qp = " + str(Qp); puts Qpp = Q.sat(Hpp); puts "Qpp = " + str(Qpp); puts D = Qpp.radicalDecomp(); puts "D = " + str(D); puts #Di = Qpp.decomposition(); #puts "Di = " + str(Di); #puts #startLog(); terminate(); #sys.exit(); jas-2.5/examples/cyclic6.jas0000644000175000017500000000063511513654422016223 0ustar giovannigiovanni#Cyclic equations for N = 6: Mod 32003 (x6,x5,x4,x3,x2,x1) G ( x1 + x2 + x3 + x4 + x5 + x6, x1*x2 + x1*x6 + x2*x3 + x3*x4 + x4*x5 + x5*x6, x1*x2*x3 + x1*x2*x6 + x1*x5*x6 + x2*x3*x4 + x3*x4*x5 + x4*x5*x6, x1*x2*x3*x4 + x1*x2*x3*x6 + x1*x2*x5*x6 + x1*x4*x5*x6 + x2*x3*x4*x5 + x3*x4*x5*x6, x1*x2*x3*x4*x5 + x1*x2*x3*x4*x6 + x1*x2*x3*x5*x6 + x1*x2*x4*x5*x6 + x1*x3*x4*x5*x6 + x2*x3*x4*x5*x6, x1*x2*x3*x4*x5*x6 - 1 ) jas-2.5/examples/radical-decomp_charp_ex816.py0000644000175000017500000000347611425634532021526 0ustar giovannigiovanni# # jython examples for jas. # $Id: radical-decomp_charp_ex816.py 3242 2010-08-02 21:32:10Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate, startLog, noThreads from jas import QQ, ZM, RF, AN # polynomial examples: ideal radical decomposition, modified from example 8.16 in GB book # noThreads(); # must be called very early prime = 5; cf = ZM(prime); #cf = QQ(); ca = PolyRing(cf,"a",PolyRing.lex); #print "ca = " + str(ca); [ea,aa] = ca.gens(); print "ea = " + str(ea); print "aa = " + str(aa); print; #!#roota = aa**prime + 2; roota = aa**2 + 2; print "roota = " + str(roota); Q3a = AN(roota,field=True); print "Q3a = " + str(Q3a.factory()); ## Q3a = RF(ca); #print Q3a.gens(); [ea2,aa2] = Q3a.gens(); print "ea2 = " + str(ea2); print "aa2 = " + str(aa2); print; #cr = PolyRing(QQ(),"t",PolyRing.lex); cr = PolyRing(Q3a,"t",PolyRing.lex); print "coefficient Ring: " + str(cr); rf = RF(cr); print "coefficient quotient Ring: " + str(rf.ring.toScript()); r = PolyRing(rf,"x,y",PolyRing.lex); print "Ring: " + str(r); #print; [one,a,t,x,y] = r.gens(); #print one,a,t,x,y; print "one = " + str(one); print "a = " + str(a); print "t = " + str(t); print "x = " + str(x); print "y = " + str(y); print; #sys.exit(); #f1 = x**prime - t; #f2 = y**prime - t; ##f1 = x**4 + t; ##f2 = y**4 + t; f1 = x**3 + t; f2 = y**3 + t; #f2 = f2**2; f3 = (y-x); f3 = f3**prime; print "f1 = ", f1; print "f2 = ", f2; #print "f3 = ", f3; print; F = r.ideal( list=[f1,f2] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); #R = F.primeDecomp(); t = System.currentTimeMillis() - t; print "R = ", R; print; print "decomp time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/ore_t.jas0000644000175000017500000000032010653077260015771 0ustar giovannigiovanni# solvable polynomials, Ore extension Q[x,y][z;d][t,e]: Rat(x,y,z,t) L RelationTable ( ( z ), ( y ), ( y z + x ), ( t ), ( y ), ( y t + y ), ( t ), ( z ), ( z t - z ) ) ( ( x^2 + y^2 + z^2 + t^2 + 1 ) ) jas-2.5/examples/0dim_prime-decomp.py0000644000175000017500000000160711376447326020046 0ustar giovannigiovanni# # jython examples for jas. # $Id: 0dim_prime-decomp.py 3149 2010-05-24 10:03:02Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: zero dimensional ideals prime and primary decomposition #r = Ring( "Rat(x) L" ); #r = Ring( "Q(x) L" ); r = PolyRing(QQ(),"x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); f1 = (x**2 - 5)**2; f2 = y**3 - x; f3 = z**2 - y * x; print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print; F = r.ideal( list=[f1,f2,f3] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); P = F.primeDecomp(); t1 = System.currentTimeMillis() - t; print "P = ", P; print; print "prime decomp time =", t1, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/arith.rb0000644000175000017500000000243011641155210015610 0ustar giovannigiovanni# # jruby examples for jas. # $Id: arith.rb 3784 2011-09-29 20:52:24Z kredel $ # require "examples/jas" # example for rational and complex numbers # # zn = ZZ(7); puts "zn: " + str(zn); puts "zn^2: " + str(zn*zn); puts; x = 10000000000000000000000000000000000000000000000000; rn = QQ(2*x,4*x); puts "rn: " + str(rn); puts "rn^2: " + str(rn*rn); puts; rn = QQ(6/4); puts "rn: " + str(rn); puts "rn^2: " + str(rn*rn); puts; c = CC(); puts "c: " + str(c); c = c.one(); puts "c: " + str(c); c = CC(2,3); puts "c: " + str(c); puts "c^5: " + str(c**5 + c.one()); puts; c = CC( 2,rn ); puts "c: " + str(c); puts; r = PolyRing.new(QQ(), "(x,y)", PolyRing.lex ); puts "Ring: " + str(r); puts; # sage like: with generators for the polynomial ring one,x,y = r.gens(); zero = r.zero(); begin f = RF(r); rescue f = None; end puts "f: " + str(f); d = x**2 + 5 * x - 6; f = RF(r,d); puts "f: " + str(f); n = d*d + y + 1; f = RF(r,d,n); puts "f: " + str(f); puts; # beware not to mix expressions f = f**2 - f; puts "f^2-f: " + str(f); puts; f = f/f; puts "f/f: " + str(f); f = RF(r,d,one); puts "f: " + str(f); f = RF(r,zero); puts "f: " + str(f); f = RF(r,d,y); puts "f: " + str(f); puts "one: " + str(f.one()); puts "zero: " + str(f.zero()); puts; terminate(); #sys.exit(); jas-2.5/examples/u_sl_3.rb0000644000175000017500000000243512136716620015702 0ustar giovannigiovanni# # jruby examples for jas. # $Id: u_sl_3.rb 4380 2013-04-27 09:42:41Z kredel $ # require "examples/jas" # U(sl_3) example rs = """ # solvable polynomials, U(sl_3): Rat(Xa,Xb,Xc,Ya,Yb,Yc,Ha,Hb) G RelationTable ( ( Xb ), ( Xa ), ( Xa Xb - Xc ), ( Ya ), ( Xa ), ( Xa Ya - Ha ), ( Yc ), ( Xa ), ( Xa Yc + Yb ), ( Ha ), ( Xa ), ( Xa Ha + 2 Xa ), ( Hb ), ( Xa ), ( Xa Hb - Xa), ( Yb ), ( Xb ), ( Xb Yb - Hb ), ( Yc ), ( Xb ), ( Xb Yc - Ya ), ( Ha ), ( Xb ), ( Xb Ha - Xb ), ( Hb ), ( Xb ), ( Xb Hb + 2 Xb ), ( Ya ), ( Xc ), ( Xc Ya + Xb ), ( Yb ), ( Xc ), ( Xc Yb - Xa ), ( Yc ), ( Xc ), ( Xc Yc - Ha - Hb ), ( Ha ), ( Xc ), ( Xc Ha + Xc ), ( Hb ), ( Xc ), ( Xc Hb + Xc ), ( Yb ), ( Ya ), ( Ya Yb + Yc ), ( Ha ), ( Ya ), ( Ya Ha - 2 Ya ), ( Hb ), ( Ya ), ( Ya Hb + Ya ), ( Ha ), ( Yb ), ( Yb Ha + Yb ), ( Hb ), ( Yb ), ( Yb Hb - 2 Yb ), ( Ha ), ( Yc ), ( Yc Ha - Yc ), ( Hb ), ( Yc ), ( Yc Hb - Yc ) ) """; r = SolvableRing.new( rs ); puts "SolvableRing: " + str(r); puts; ps = """ ( ( Xa + Hb ), ( Xb + Ha Hb ) ) """; f = r.ideal( ps ); puts "SolvableIdeal: " + str(f); puts; #startLog(); rg = f.leftGB(); puts "seq left Output:" + str(rg); puts; rg = f.twosidedGB(); puts "seq twosided Output:" + str(rg); puts; rg = f.rightGB(); puts "seq right GB: " + str(rg); puts; jas-2.5/examples/factors_algeb_2.rb0000644000175000017500000000303311641415316017523 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_algeb_2.rb 3786 2011-09-30 19:38:55Z kredel $ # require "examples/jas" # polynomial examples: factorization over Q(i)(sqrt2) Q = PolyRing.new(QQ(),"i",PolyRing.lex); puts "Q = " + str(Q); e,a = Q.gens(); puts "e = " + str(e); puts "a = " + str(a); imag = a**2 + 1; puts "imag = " + str(imag); Qi = AN(imag,true); puts "Qi = " + str(Qi.factory()); one,i = Qi.gens(); puts "one = " + str(one); puts "i = " + str(i); puts; Wr = PolyRing.new(Qi,"w2",PolyRing.lex) puts "Wr = " + str(Wr); e,a,b = Wr.gens(); puts "e = " + str(e); puts "a = " + str(a); puts "b = " + str(b); w2 = b**2 - 2; puts "w2 = " + str(w2); Qw2 = AN(w2,true); puts "Qw2 = " + str(Qw2.factory()); one,i,w2 = Qw2.gens(); puts "one = " + str(one); puts "i = " + str(i); puts "w2 = " + str(w2); puts; Qiw2 = PolyRing.new(Qw2,"x",PolyRing.lex) puts "Qiw2 = " + str(Qiw2); one,i,w2,x = Qiw2.gens(); puts "one = " + str(one); puts "i = " + str(i); puts "w2 = " + str(w2); puts "x = " + str(x); puts; #sys.exit(); f = ( x**2 + 1 ) * ( x**2 - 2 ); puts "f = " + str(f); puts; startLog(); t = System.currentTimeMillis(); G = Qiw2.factors(f); t = System.currentTimeMillis() - t; #puts "G = ", G; #puts "factor time =", t, "milliseconds"; puts; g = one; for h, i in G puts "h**i = (" + str(h) + ")**" + str(i); h = h**i; g = g*h; end #puts "g = ", g; puts; puts "factor time = " + str(t) + " milliseconds," + "isFactors(f,g): " + str(f==g); puts; #startLog(); terminate(); jas-2.5/examples/roots_real_ideal.py0000644000175000017500000000265211722152614020050 0ustar giovannigiovanni# # jython examples for jas. # $Id: roots_real_ideal.py 3892 2012-02-25 12:35:24Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: real roots over Q r = PolyRing(QQ(),"I,x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,I,x,y,z] = r.gens(); f1 = z - x - y * I; f2 = I**2 + 1; #f3 = z**3 - 2; f3 = z**3 - 2*I; print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print; F = r.ideal( list=[f1,f2,f3] ); print "F = ", F; print; startLog(); G = F.GB(); print "G = ", G; print; #terminate(); #sys.exit(); r = PolyRing(QQ(),"x,y",PolyRing.lex); print "Ring: " + str(r); print; [one,x,y] = r.gens(); # y**3 - 3 * I * x * y**2 - 3 * x**2 * y + I * x**3 - 2 * I = z**3 - 2 #fr = y**3 - 3 * x**2 * y; #fi = -3 * x * y**2 + x**3 - 2; # y**3 - 3 * I * x * y**2 - 3 * x**2 * y + I * x**3 + 2 = z**3 - 2 I fr = y**3 - 3 * x**2 * y - 2; fi = -3 * x * y**2 + x**3; print "fr = ", fr; print "fi = ", fi; print; F = r.ideal( list=[fr,fi] ); print "F = ", F; print; G = F.GB(); print "G = ", G; print; t = System.currentTimeMillis(); R = G.realRoots(); t = System.currentTimeMillis() - t; print "R = ", R; print; print "real roots: "; G.realRootsPrint() print "real roots time =", t, "milliseconds"; print; print "G = ", G; print; #startLog(); terminate(); jas-2.5/examples/factors_algeb_trans.rb0000644000175000017500000000473411534200272020514 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_algeb_trans.rb 3553 2011-03-04 15:09:47Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: factorization over Q(sqrt(2))(x)(sqrt(x))[y] Q = PolyRing.new(QQ(),"w2",PolyRing.lex); puts "Q = " + str(Q); e,a = Q.gens(); #puts "e = " + str(e); puts "a = " + str(a); root = a**2 - 2; puts "root = " + str(root); Q2 = AN(root,field=true); puts "Q2 = " + str(Q2.factory()); one,w2 = Q2.gens(); #puts "one = " + str(one); #puts "w2 = " + str(w2); puts; Qp = PolyRing.new(Q2,"x",PolyRing.lex); puts "Qp = " + str(Qp); ep,wp,ap = Qp.gens(); #puts "ep = " + str(ep); #puts "wp = " + str(wp); #puts "ap = " + str(ap); puts; Qr = RF(Qp); puts "Qr = " + str(Qr.factory()); er,wr,ar = Qr.gens(); #puts "er = " + str(er); #puts "wr = " + str(wr); #puts "ar = " + str(ar); puts; Qwx = PolyRing.new(Qr,"wx",PolyRing.lex); puts "Qwx = " + str(Qwx); ewx,wwx,ax,wx = Qwx.gens(); #puts "ewx = " + str(ewx); puts "ax = " + str(ax); #puts "wwx = " + str(wwx); puts "wx = " + str(wx); puts; rootx = wx**2 - ax; puts "rootx = " + str(rootx); Q2x = AN(rootx,field=true); puts "Q2x = " + str(Q2x.factory()); ex2,w2x2,ax2,wx = Q2x.gens(); #puts "ex2 = " + str(ex2); #puts "w2x2 = " + str(w2x2); #puts "ax2 = " + str(ax2); #puts "wx = " + str(wx); puts; Yr = PolyRing.new(Q2x,"y",PolyRing.lex) puts "Yr = " + str(Yr); e,w2,x,wx,y = Yr.gens(); puts "e = " + str(e); puts "w2 = " + str(w2); puts "x = " + str(x); puts "wx = " + str(wx); puts "y = " + str(y); puts; f = ( y**2 - x ) * ( y**2 - 2 ); #f = ( y**2 - x )**2 * ( y**2 - 2 )**3; #f = ( y**4 - x * 2 ); #f = ( y**7 - x * 2 ); #f = ( y**2 - 2 ); #f = ( y**2 - x ); #f = ( w2 * y**2 - 1 ); #f = ( y**2 - 1/x ); #f = ( y**2 - (1,2) ); #f = ( y**2 - 1/x ) * ( y**2 - (1,2) ); puts "f = ", f; puts; #sys.exit(); startLog(); t = System.currentTimeMillis(); G = Yr.factors(f); t = System.currentTimeMillis() - t; #puts "G = ", G; #puts "factor time =", t, "milliseconds"; #exit(); puts "f = " + str(f); g = one; for h, i in G do if i > 1 then puts "h**i = " + str(h) + "**" + str(i); else puts "h = " + str(h); end h = h**i; g = g*h; end #puts "g = " + str(g); if f == g then puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): true" ; else puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): " + str(f==g); end puts; #startLog(); terminate(); jas-2.5/examples/katsura7m.jas0000644000175000017500000004744612045530566016623 0ustar giovannigiovanni#Katsura equations for N = 7: Mod 536870909 #Mod 1152921504606846883 #= 2^60-93 #Mod 170141183460469231731687303715884105727 = Mersenne prime 12 #Mod 359334085968622831041960188598043661065388726959079837 = Bell prime #Mod 1363005552434666078217421284621279933627102780881053358473 = Padovan Prime #Mod 1558877695141608507751098941899265975115403618621811951868598809164180630185566719 = Padovan Prime #Mod 1 11 = repunit primes #Mod 2 1111111111111111111 #Mod 3 11111111111111111111111 #Mod 4 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 #Mod 5 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 #Mod Mersenne primes #Mod 2^3217-1: 969 digits #Mod 259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071 #Mod 2^4253-1: 1281 digits #Mod 190797007524439073807468042969529173669356994749940177394741882673528979787005053706368049835514900244303495954950709725762186311224148828811920216904542206960744666169364221195289538436845390250168663932838805192055137154390912666527533007309292687539092257043362517857366624699975402375462954490293259233303137330643531556539739921926201438606439020075174723029056838272505051571967594608350063404495977660656269020823960825567012344189908927956646011998057988548630107637380993519826582389781888135705408653045219655801758081251164080554609057468028203308718724654081055323215860189611391296030471108443146745671967766308925858547271507311563765171008318248647110097614890313562856541784154881743146033909602737947385055355960331855614540900081456378659068370317267696980001187750995491090350108417050917991562167972281070161305972518044872048331306383715094854938415738549894606070722584737978176686422134354526989443028353644037187375385397838259511833166416134323695660367676897722287918773420968982326089026150031515424165462111337527431154890666327374921446276833564519776797633875503548665093914556482031482248883127023777039667707976559857333357013727342079099064400455741830654320379350833236245819348824064783585692924881021978332974949906122664421376034687815350484991 #Mod 2^9689-1: 2917 digits #Mod 4782202788054612029528392986600059097414971724022365008513345109918378950942662970278927686112707894586824720981524256319306585052676834087480834429433264797425893247623688331021633208954847354805799943341309825989013743806187109581043148680813778321530496715601563282624414040398143207622036272190408590790537203475256105564071579263867875240985573356522656108542128577321057879052328865035355873615679363655889925711574420153832091752422843046918811427400662135559303516853703976812686385750376227787949580582081831261725701003498206512329872677233489510953469375683037038373999696771585788905639115522613405495707184524158219208223766442059014593330657009722153962376853423770486138578089775621301167811299166407361746606697808186757966914671246073712904200588408923186387737887675292886953797066980967406053530122853539036965490224784924649007954898678503314655546475504501686187354866964374552614120640782949622452027788962138602665933147687696322089504278791624651519312327831756553779377194524673395819281486668576384019590720179413349582970319393884388810494546040342087536563628332152073181614300721769371426238517540520845214665313301183551962591849558938499025348780376716477073930634436840084468255937443451690315999349137664638968972614199015304906547819056227171224947070739716300953775743441307920501863532234466545645695774331885044978250148663467372130392099894852145190998232878772486650513010816769902892518719250066947215706536216248696240569256865554296221552211560427778662545936998801070186162601476474293459830183651273363462732675883060701410359254829149774339297173680765610959599911309189788238350131635672661435969218239977196933874395403996623675580528211207136396370858056051160781770985452576988032333812939272752101944629527490313835551985197095928885236415301789218675141014541203096191270934369039522098280317668942061325572349643638403056487349290884223786292887472231219032385281034091824306618947740727265524284893304474861454942076799041739447165838281671410435831206790501914527326287370339974707206016882562827404270170322606727980343479326425730091839813077719322455394763960606588214326603156141490740557698055166263044447583756711516490181193442236859424151843795389335765432129944054855345155859273424561825146813714720606287781021240923708021492298349635179527270302962970156927686511635050080407282674252362644695710769768866137302789313609674382719017385508484663373476120843567983065059558072935110637544240807350667082987233779768874938983584523095638996120616318634391967112086464384649470963230072729200912586147267999762496709852769503535733924416202657720741248683592202828983311140833923302433917797976990311425843619350936754483811194408812763388084204451804912454383884180800945275626668057628954763384641305107753773247082495804533355717481965025070819730466422826105697510564289798951182192885976352229053898948737614642139910911535864505818992696826225754111 #Mod 2^19937-1: 6002 digits #Mod 43154247973881626480552355163379198390539350432267115051652505414033306801376580911304513629318584665545269938257648835317902217334584413909528269154609168019007875343741396296801920114486480902661414318443276980300066728104984095451588176077132969843762134621790396391341285205627619600513106646376648615994236675486537480241964350295935168662363909047948347692313978301377820785712419054474332844529183172973242310888265081321626469451077707812282829444775022680488057820028764659399164766265200900561495800344054353690389862894061792872011120833614808447482913547328367277879565648307846909116945866230169702401260240187028746650033445774570315431292996025187780790119375902863171084149642473378986267503308961374905766340905289572290016038000571630875191373979555047468154333253474991046248132504516341796551470575481459200859472614836213875557116864445789750886277996487304308450484223420629266518556024339339190844368921018424844677042727664601852914925277280922697538426770257333928954401205465895610347658855386633902546289962132643282425748035786233580608154696546932563833327670769899439774888526687278527451002963059146963875715425735534475979734463100678367393327402149930968778296741391514599602374213629898720611431410402147238998090962818915890645693934483330994169632295877995848993366747014871763494805549996163051541225403465297007721146231355704081493098663065733677191172853987095748167816256084212823380168625334586431254034670806135273543270714478876861861983320777280644806691125713197262581763151313596429547763576367837019349835178462144294960757190918054625114143666384189433852576452289347652454631535740468786228945885654608562058042468987372436921445092315377698407168198376538237748614196207041548106379365123192817999006621766467167113471632715481795877005382694393400403061700457691135349187874888923429349340145170571716181125795888889277495426977149914549623916394014822985025331651511431278802009056808456506818877266609831636883884905621822262933986548645669080672191704740408891349835685662428063231198520436826329415290752972798343429446509992206368781367154091702655772727391329424277529349082600585884766523150957417077831910016168475685658673192860882070179760307269849987354836042371734660257694347235506301744118874141292438958141549100609752216882230887611431996472330842380137110927449483557815037586849644585749917772869926744218369621137675101083278543794081749094091043084096774144708436324279476892056200427227961638669149805489831121244676399931955371484012886360748706479568669048574782855217054740113945929622177502575565811067452201448981991968635965361551681273982740760138899638820318776303668762730157584640042798880691862640268612686180883874939573818125022279689930267446255773959542469831637863000171279227151406034129902181570659650532600775823677398182129087394449859182749999007223592423334567850671186568839186747704960016277540625331440619019129983789914712515365200336057993508601678807687568562377857095255541304902927192220184172502357124449911870210642694565061384919373474324503966267799038402386781686809962015879090586549423504699190743519551043722544515740967829084336025938225780730880273855261551972044075620326780624448803490998232161231687794715613405793249545509528052518010123087258778974115817048245588971438596754408081313438375502988726739523375296641615501406091607983229239827240614783252892479716519936989519187808681221191641747710902480633491091704827441228281186632445907145787138351234842261380074621914004818152386666043133344875067903582838283562688083236575482068479639546383819532174522502682372441363275765875609119783653298312066708217149316773564340379289724393986744139891855416612295739356668612658271234696438377122838998040199739078061443675415671078463404673702403777653478173367084844734702056866636158138003692253382209909466469591930161626097920508742175670306505139542860750806159835357541032147095084278461056701367739794932024202998707731017692582046210702212514120429322530431789616267047776115123597935404147084870985465426502772057300900333847905334250604119503030001704002887892941404603345869926367501355094942750552591581639980523190679610784993580896683299297681262442314008657033421868094551740506448829039207316711307695131892296593509018623094810557519560305240787163809219164433754514863301000915916985856242176563624771328981678548246297376249530251360363412768366456175077031977457534912806433176539995994343308118470147158712816149394421276614228262909950055746981053206610001560295784656616193252269412026831159508949671513845195883217147982748879261851417819979034417285598607727220866677680426090308754823803345446566305619241308374452754668143015487710877728011086004325892262259413968285283497045571062757701421761565262725153407407625405149931989494459106414660534305378576709862520049864880961144869258603473714363659194013962706366851389299692869491805172556818508298824954954815796063169517658741420159798754273428026723452481263569157307213153739781041627653715078598504154797287663122946711348158529418816432825044466692781137474494898385064375787507376496345148625306383391555145690087891955315994462944493235248817599907119135755933382121706191477185054936632211157222920331148502487563303118018805685073569841580518118710778653953571296014372940865270407021924383167290323231567912289419486240594039074452321678019381871219092155460768444573578559513613304242206151356457513937270939009707237827101245853837678338161023397586854894230696091540249987907453461311923963852950754758058205625956600817743007191746812655955021747670922460866747744520875607859062334750627098328593480067789456169602494392813763495657599847485773553990957557313200809040830036446492219409934096948730547494301216165686750735749555882340303989874672975455060957736921559195480815514035915707129930057027117286252843197413312307617886797506784260195436760305990340708481464607278955495487742140753570621217198252192978869786916734625618430175454903864111585429504569920905636741539030968041471 #Mod 43154247973881626480552355163379198390539350432267115051652505414033306801376580911304513629318584665545269938257648835317902217334584413909528269154609168019007875343741396296801920114486480902661414318443276980300066728104984095451588176077132969843762134621790396391341285205627619600513106646376648615994236675486537480241964350295935168662363909047948347692313978301377820785712419054474332844529183172973242310888265081321626469451077707812282829444775022680488057820028764659399164766265200900561495800344054353690389862894061792872011120833614808447482913547328367277879565648307846909116945866230169702401260240187028746650033445774570315431292996025187780790119375902863171084149642473378986267503308961374905766340905289572290016038000571630875191373979555047468154333253474991046248132504516341796551470575481459200859472614836213875557116864445789750886277996487304308450484223420629266518556024339339190844368921018424844677042727664601852914925277280922697538426770257333928954401205465895610347658855386633902546289962132643282425748035786233580608154696546932563833327670769899439774888526687278527451002963059146963875715425735534475979734463100678367393327402149930968778296741391514599602374213629898720611431410402147238998090962818915890645693934483330994169632295877995848993366747014871763494805549996163051541225403465297007721146231355704081493098663065733677191172853987095748167816256084212823380168625334586431254034670806135273543270714478876861861983320777280644806691125713197262581763151313596429547763576367837019349835178462144294960757190918054625114143666384189433852576452289347652454631535740468786228945885654608562058042468987372436921445092315377698407168198376538237748614196207041548106379365123192817999006621766467167113471632715481795877005382694393400403061700457691135349187874888923429349340145170571716181125795888889277495426977149914549623916394014822985025331651511431278802009056808456506818877266609831636883884905621822262933986548645669080672191704740408891349835685662428063231198520436826329415290752972798343429446509992206368781367154091702655772727391329424277529349082600585884766523150957417077831910016168475685658673192860882070179760307269849987354836042371734660257694347235506301744118874141292438958141549100609752216882230887611431996472330842380137110927449483557815037586849644585749917772869926744218369621137675101083278543794081749094091043084096774144708436324279476892056200427227961638669149805489831121244676399931955371484012886360748706479568669048574782855217054740113945929622177502575565811067452201448981991968635965361551681273982740760138899638820318776303668762730157584640042798880691862640268612686180883874939573818125022279689930267446255773959542469831637863000171279227151406034129902181570659650532600775823677398182129087394449859182749999007223592423334567850671186568839186747704960016277540625331440619019129983789914712515365200336057993508601678807687568562377857095255541304902927192220184172502357124449911870210642694565061384919373474324503966267799038402386781686809962015879090586549423504699190743519551043722544515740967829084336025938225780730880273855261551972044075620326780624448803490998232161231687794715613405793249545509528052518010123087258778974115817048245588971438596754408081313438375502988726739523375296641615501406091607983229239827240614783252892479716519936989519187808681221191641747710902480633491091704827441228281186632445907145787138351234842261380074621914004818152386666043133344875067903582838283562688083236575482068479639546383819532174522502682372441363275765875609119783653298312066708217149316773564340379289724393986744139891855416612295739356668612658271234696438377122838998040199739078061443675415671078463404673702403777653478173367084844734702056866636158138003692253382209909466469591930161626097920508742175670306505139542860750806159835357541032147095084278461056701367739794932024202998707731017692582046210702212514120429322530431789616267047776115123597935404147084870985465426502772057300900333847905334250604119503030001704002887892941404603345869926367501355094942750552591581639980523190679610784993580896683299297681262442314008657033421868094551740506448829039207316711307695131892296593509018623094810557519560305240787163809219164433754514863301000915916985856242176563624771328981678548246297376249530251360363412768366456175077031977457534912806433176539995994343308118470147158712816149394421276614228262909950055746981053206610001560295784656616193252269412026831159508949671513845195883217147982748879261851417819979034417285598607727220866677680426090308754823803345446566305619241308374452754668143015487710877728011086004325892262259413968285283497045571062757701421761565262725153407407625405149931989494459106414660534305378576709862520049864880961144869258603473714363659194013962706366851389299692869491805172556818508298824954954815796063169517658741420159798754273428026723452481263569157307213153739781041627653715078598504154797287663122946711348158529418816432825044466692781137474494898385064375787507376496345148625306383391555145690087891955315994462944493235248817599907119135755933382121706191477185054936632211157222920331148502487563303118018805685073569841580518118710778653953571296014372940865270407021924383167290323231567912289419486240594039074452321678019381871219092155460768444573578559513613304242206151356457513937270939009707237827101245853837678338161023397586854894230696091540249987907453461311923963852950754758058205625956600817743007191746812655955021747670922460866747744520875607859062334750627098328593480067789456169602494392813763495657599847485773553990957557313200809040830036446492219409934096948730547494301216165686750735749555882340303989874672975455060957736921559195480815514035915707129930057027117286252843197413312307617886797506784260195436760305990340708481464607278955495487742140753570621217198252192978869786916734625618430175454903864111585429504569920905636741539030968041471 (u0,u1,u2,u3,u4,u5,u6,u7) G ( u7*u7 + u6*u6 + u5*u5 + u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 + u5*u5 + u6*u6 + u7*u7 - u0, u7*0 + u6*u7 + u5*u6 + u4*u5 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 + u5*u4 + u6*u5 + u7*u6 - u1, u7*0 + u6*0 + u5*u7 + u4*u6 + u3*u5 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 + u5*u3 + u6*u4 + u7*u5 - u2, u7*0 + u6*0 + u5*0 + u4*u7 + u3*u6 + u2*u5 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 + u5*u2 + u6*u3 + u7*u4 - u3, u7*0 + u6*0 + u5*0 + u4*0 + u3*u7 + u2*u6 + u1*u5 + u0*u4 + u1*u3 + u2*u2 + u3*u1 + u4*u0 + u5*u1 + u6*u2 + u7*u3 - u4, u7*0 + u6*0 + u5*0 + u4*0 + u3*0 + u2*u7 + u1*u6 + u0*u5 + u1*u4 + u2*u3 + u3*u2 + u4*u1 + u5*u0 + u6*u1 + u7*u2 - u5, u7*0 + u6*0 + u5*0 + u4*0 + u3*0 + u2*0 + u1*u7 + u0*u6 + u1*u5 + u2*u4 + u3*u3 + u4*u2 + u5*u1 + u6*u0 + u7*u1 - u6, u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 + u5 + u6 + u7 - 1 ) jas-2.5/examples/cyclic5_real_roots.rb0000644000175000017500000000170511773563306020310 0ustar giovannigiovanni# # jruby examples for jas. # $Id: cyclic5_real_roots.rb 3967 2012-06-30 11:45:11Z kredel $ # require "examples/jas" # polynomial examples: real roots over Q for zero dimensional ideal `cyclic5' r = PolyRing.new(QQ(),"a,b,c,d,e",PolyRing.lex); puts "Ring: " + str(r); puts; #one,q,w,s,x = r.gens(); f1 = a + b + c + d + e; f2 = a*b + b*c + c*d + d*e + e*a; f3 = a*b*c + b*c*d + c*d*e + d*e*a + e*a*b; f4 = a*b*c*d + b*c*d*e + c*d*e*a + d*e*a*b + e*a*b*c; f5 = a*b*c*d*e - 1; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts "f4 = " + str(f4); puts "f5 = " + str(f5); puts; F = r.ideal( "", list=[f1,f2,f3,f4,f5] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.realRoots(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "real roots = "; F.realRootsPrint() puts "real roots time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/alg_stat_1.rb0000644000175000017500000000230312020207644016517 0ustar giovannigiovanni# # jruby examples for jas. # $Id: alg_stat_1.rb 4145 2012-08-31 19:25:24Z kredel $ # require "examples/jas" #startLog(); # example: Algebraic Statistics # Drton, Sturmfels, Sullivant, example 2.1.3 #r = PolyRing(QQ(),"l1,l2",PolyRing.grad); r = PolyRing.new(QQ(),"l1,l2",PolyRing.lex); puts "Ring: " + r.to_s; puts; puts "gens: " + one.to_s + "," + l1.to_s + ", " + l2.to_s; puts; u0 = 3; u1 = 5; u2 = 7; u12 = 11; f1 = (u1+u12)*(l1+l2+2)*(l1+1)*(l1+l2+1)\ + (u12)*l1*(l1+1)*(l1+l2+1)\ - (u2+u12)*l1*(l1+l2+2)*(l1+l2+1)\ - (u0+u1+u2+u12)*l1*(l1+l2+2)*(l1+1) ; f2 = (u2+u12)*(l1+l2+2)*(l2+1)*(l1+l2+1)\ + (u12)*l2*(l2+1)*(l1+l2+1)\ - (u1+u12)*l2*(l1+l2+2)*(l1+l2+1)\ - (u0+u1+u2+u12)*l2*(l1+l2+2)*(l2+1) ; puts "f1: " + str(f1); puts; puts "f2: " + str(f2); puts h = l1*l2*(l1+1)*(l2+1)*(l1+l2+1)*(l1+l2+2); puts "h: " + str(h); puts F = r.ideal("",[f1,f2]); puts "F = " + str(F); puts H = r.ideal("",[h]); puts "H = " + str(H); puts G = F.GB(); puts "G = " + str(G); puts #startLog(); Q = G.sat(H); puts "Q = " + str(Q); puts #D = Q.radicalDecomp(); #puts "D = " + str(D); #puts R = Q.realRoots(); puts "R = " + str(R); puts #startLog(); terminate(); #sys.exit(); jas-2.5/examples/hawes2modpars.rb0000644000175000017500000000224111644356076017300 0ustar giovannigiovanni# # jruby examples for jas. # $Id: hawes2modpars.rb 3794 2011-10-09 17:39:11Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} require "examples/jas" #startLog(); # Hawes & Gibson example 2 # rational function coefficients #r = Ring.new( "ModFunc 17 (a, c, b) (y2, y1, z1, z2, x) G" ); r = PolyRing.new( PolyRing.new(ZM(17),"a, c, b",PolyRing.lex), "y2, y1, z1, z2, x", PolyRing.grad ); puts "Ring: " + str(r); puts; one,a,c,b,y2,y1,z1,z2,x = r.gens(); p1 = x + 2 * y1 * z1 + 3 * a * y1**2 + 5 * y1**4 + 2 * c * y1; p2 = x + 2 * y2 * z2 + 3 * a * y2**2 + 5 * y2**4 + 2 * c * y2; p3 = 2 * z2 + 6 * a * y2 + 20 * y2**3 + 2 * c; p4 = 3 * z1**2 + y1**2 + b; p5 = 3 * z2**2 + y2**2 + b; f = [p1,p2,p3,p4,p5]; g = r.ideal( "", f ); puts "Ideal: " + str(g); puts; rg = g.GB(); rg = g.GB(); rg = g.GB(); puts "GB: " + str(rg); puts; bg = rg.isGB(); puts "isGB: " + str(bg); puts; startLog(); terminate(); #sys.exit(); jas-2.5/examples/nabeshima_cgbF00.rb0000644000175000017500000000141311653002012017503 0ustar giovannigiovanni# # jruby examples for jas. # $Id: nabeshima_cgbF00.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Nabashima, ISSAC 2007, example Ex-Fig-2 # integral function coefficients r = Ring.new( "IntFunc(a, b, c) (x) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( { a } x^3 ), ( { b } x^2 ), ( { c } x ) ) """; #startLog(); f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; bg = gs.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; #exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; bg = gs.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/boolean_gb.rb0000644000175000017500000000200211641163152016567 0ustar giovannigiovanni# # jruby examples for jas. # $Id: boolean_gb.rb 3785 2011-09-29 21:43:06Z kredel $ # require "examples/jas" # Boolean coefficient boolean GB # see S. Inoue and A. Nagai "On the Implementation of Boolean Groebner Bases" in ASCM 2009 # Z_2 regular ring coefficent example r = PolyRing.new(RR(ZM(2),3),"x,y",PolyRing.lex); puts "r = " + str(r); #puts len(r.gens()) s1,s2,s3,x,y = r.gens(); one = r.one(); puts "one = " + str(one); puts "s1 = " + str(s1); puts "s2 = " + str(s2); puts "s2 = " + str(s3); puts "x = " + str(x); puts "y = " + str(y); brel = [ x**2 - x, y**2 - y ]; puts "brel = " + str(brel[0]) + ", " + str(brel[1]); pl = [ ( one + s1 + s2 ) * ( x*y + x +y ), s1 * x + s1, s2 * y + s2, x * y ]; #pl = [ ( one ) * ( x*y + x +y ), s1 * x + s1, s2 * y + s2, x * y ]; pl = pl + brel; startLog(); f = ParamIdeal.new(r,"",pl); puts "Ideal: " + str(f); gb = f.regularGB(); puts "boolean GB: " + str(gb); #ss = gb.stringSlice(); #puts "regular string slice: " + str(ss); terminate(); #sys.exit(); jas-2.5/examples/exterior.rb0000644000175000017500000000504012136716620016352 0ustar giovannigiovanni# # jruby examples for jas. # $Id: exterior.rb 4380 2013-04-27 09:42:41Z kredel $ # require "examples/jas" # exterior calculus example # Hartley and Tuckey, 1993, # GB in Clifford and Grassmann algebras rs = """ # exterior calculus example: Rat(a,b,c,f,g,h,u,v,w,x,y,z) L RelationTable ( ( b ), ( a ), ( - a b ), ( c ), ( a ), ( - a c ), ( f ), ( a ), ( - a f ), ( g ), ( a ), ( - a g ), ( h ), ( a ), ( - a h ), ( u ), ( a ), ( - a u ), ( v ), ( a ), ( - a v ), ( w ), ( a ), ( - a w ), ( x ), ( a ), ( - a x ), ( y ), ( a ), ( - a y ), ( z ), ( a ), ( - a z ), ( c ), ( b ), ( - b c ), ( f ), ( b ), ( - b f ), ( g ), ( b ), ( - b g ), ( h ), ( b ), ( - b h ), ( u ), ( b ), ( - b u ), ( v ), ( b ), ( - b v ), ( w ), ( b ), ( - b w ), ( x ), ( b ), ( - b x ), ( y ), ( b ), ( - b y ), ( z ), ( b ), ( - b z ), ( f ), ( c ), ( - c f ), ( g ), ( c ), ( - c g ), ( h ), ( c ), ( - c h ), ( u ), ( c ), ( - c u ), ( v ), ( c ), ( - c v ), ( w ), ( c ), ( - c w ), ( x ), ( c ), ( - c x ), ( y ), ( c ), ( - c y ), ( z ), ( c ), ( - c z ), ( g ), ( f ), ( - f g ), ( h ), ( f ), ( - f h ), ( u ), ( f ), ( - f u ), ( v ), ( f ), ( - f v ), ( w ), ( f ), ( - f w ), ( x ), ( f ), ( - f x ), ( y ), ( f ), ( - f y ), ( z ), ( f ), ( - f z ), ( h ), ( g ), ( - g h ), ( u ), ( g ), ( - g u ), ( v ), ( g ), ( - g v ), ( w ), ( g ), ( - g w ), ( x ), ( g ), ( - g x ), ( y ), ( g ), ( - g y ), ( z ), ( g ), ( - g z ), ( u ), ( h ), ( - h u ), ( v ), ( h ), ( - h v ), ( w ), ( h ), ( - h w ), ( x ), ( h ), ( - h x ), ( y ), ( h ), ( - h y ), ( z ), ( h ), ( - h z ), ( v ), ( u ), ( - u v ), ( w ), ( u ), ( - u w ), ( x ), ( u ), ( - u x ), ( y ), ( u ), ( - u y ), ( z ), ( u ), ( - u z ), ( w ), ( v ), ( - v w ), ( x ), ( v ), ( - v x ), ( y ), ( v ), ( - v y ), ( z ), ( v ), ( - v z ), ( x ), ( w ), ( - w x ), ( y ), ( w ), ( - w y ), ( z ), ( w ), ( - w z ), ( y ), ( x ), ( - x y ), ( z ), ( x ), ( - x z ), ( z ), ( y ), ( - y z ) ) """; r = SolvableRing.new( rs ); puts "SolvableRing: " + str(r); puts; # ( a b + c f + g h ), # ( u v + w x + y z ), # ( a v + w x + y z ), ps = """ ( ( a b + c f + g h ), ( u v + w x + y z ), ( a^2 ), ( b^2 ), ( c^2 ), ( f^2 ), ( g^2 ), ( h^2 ), ( u^2 ), ( v^2 ), ( w^2 ), ( x^2 ), ( y^2 ), ( z^2 ) ) """; f = r.ideal(ps); puts "SolvableIdeal: " + str(f); puts; startLog(); rg = f.leftGB(); puts "seq left GB: " + str(rg); puts; rg = f.twosidedGB(); puts "seq twosided GB: " + str(rg); puts; rg = f.rightGB(); puts "seq right GB: " + str(rg); puts; jas-2.5/examples/radical-decomp_charp_ex816_algeb.py0000644000175000017500000000411311535146104022640 0ustar giovannigiovanni# # jython examples for jas. # $Id: radical-decomp_charp_ex816_algeb.py 3555 2011-03-07 12:15:01Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate, startLog, noThreads from jas import QQ, ZM, RF, AN # polynomial examples: ideal radical decomposition, example 8.16 in GB book, base field with p-th root # noThreads(); # must be called very early prime = 5; cf = ZM(prime); #cf = QQ(); ca = PolyRing(cf,"t",PolyRing.lex); print "ca = " + str(ca); [ea,ta] = ca.gens(); print "ea = " + str(ea); print "ta = " + str(ta); print; Qpt = RF(ca); #print Qpt.gens(); [ea2,ta2] = Qpt.gens(); print "ea2 = " + str(ea2); print "ta2 = " + str(ta2); print; cr = PolyRing(Qpt,"wpt",PolyRing.lex); print "polynomial quotient ring: " + str(cr); [et2,t,wpt] = cr.gens(); print "et2 = " + str(et2); print "t = " + str(t); print "wpt = " + str(wpt); print; root = wpt**prime - ta2; af = AN(root,field=True); print "coefficient algebraic quotient ring: " + str(af.ring.toScript()); #print af.gens(); ##xx = AN(( wpt**5 + 4 * t ),True,PolyRing(RF(PolyRing(ZM(5),"t",PolyRing.lex)),"wpt",PolyRing.lex)) ##print "xx: " + str(xx.ring.toScript()); [one,t,wpt] = af.gens(); print "one = " + str(one); print "t = " + str(t); print "wpt = " + str(wpt); #print one,t,wpt; print; #sys.exit(); r = PolyRing(af,"x,y",PolyRing.lex); print "polynomial ring: " + str(r); #print; [one,t,wpt,x,y] = r.gens(); #print one,t,wpt,x,y; print "one = " + str(one); print "t = " + str(t); print "wpt = " + str(wpt); print "x = " + str(x); print "y = " + str(y); print; #sys.exit(); f1 = x**prime - t; f2 = y**prime - t; f2 = f2**3; f3 = (y-x); f3 = f3**prime; print "f1 = ", f1; print "f2 = ", f2; #print "f3 = ", f3; print; F = r.ideal( list=[f1,f2] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); #R = F.primeDecomp(); t = System.currentTimeMillis() - t; print "R = ", R; print; print "decomp time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/getstart.rb0000644000175000017500000000121611644030160016336 0ustar giovannigiovanni# # jruby examples for jas. # $Id: getstart.rb 3793 2011-10-08 11:13:52Z kredel $ # require "examples/jas" # trinks 7 example r = PolyRing.new( QQ(), "B,S,T,Z,P,W", PolyRing.lex); # or PolyRing.grad puts "Ring: " + str(r); puts; ps = """ ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B**3 ), ( 99 W - 11 B S + 3 B**2 ), ( B**2 + 33/50 B + 2673/10000 ) ) """; #puts "ps: " + ps; #puts; #f = SimIdeal.new( r, ps ); f = r.ideal( ps ); puts "Ideal: " + str(f); puts; startLog() g = f.GB(); puts "Groebner base: " + str(g); puts; jas-2.5/examples/u_sl_2_e.py0000644000175000017500000000072712136720410016224 0ustar giovannigiovanni# # jython examples for jas. from jas import SolvableRing # U(sl_2_e) example rs = """ # solvable polynomials, U(sl_2_e): Rat(e,h) G RelationTable ( ( h ), ( e ), ( e h + 2 e ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( e^2 + h^3 ) ) """; f = r.ideal( ps ); print "SolvableIdeal: " + str(f); print; rg = f.leftGB(); print "seq left Output:", rg; print; rg = f.twosidedGB(); print "seq twosided Output:", rg; print; jas-2.5/examples/radical-decomp.rb0000644000175000017500000000141711653043730017357 0ustar giovannigiovanni# # jruby examples for jas. # $Id: radical-decomp.rb 3817 2011-10-29 18:37:12Z kredel $ # require "examples/jas" # polynomial examples: ideal radical decomposition #r = Ring.new( "Rat(x) L" ); #r = Ring.new( "Q(x) L" ); r = PolyRing.new(QQ(),"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); f1 = (x**2 - 5)**2; f2 = (y**2 - 3)**3 * (y**2 - 5); f3 = z**3 - x * y; #puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; F = r.ideal( "", list=[f2,f3] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "decomp time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/factors_abs.py0000644000175000017500000000375411227701102017023 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_abs.py 2754 2009-07-16 19:40:51Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring from jas import Ideal from jas import terminate from jas import startLog # polynomial examples: absolute factorization over Q #r = Ring( "Rat(x) L" ); r = Ring( "Q(x) L" ); print "Ring: " + str(r); print; [one,x] = r.gens(); #f = x**5 - 1; #f = x**6 - 1; f = x**3 - 2; f = f*f; #f = x**7 - 1; #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**2 + 1; #f = x**3 - x**2 + x - 1; #f = x**6 - 5 * x**4 + 5 * x**2 + 4; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; #f = x**4 + 2 * x**2 - 4 * x + 2; #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; #f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; #f = x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8; print "f = ", f; print; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factorsAbsolute(f); t = System.currentTimeMillis() - t; print "G = ", G.toScript(); print print "factor time =", t, "milliseconds"; print #startLog(); terminate(); jas-2.5/examples/factors_algeb_2.py0000644000175000017500000000331011652350364017551 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_algeb_2.py 3810 2011-10-27 21:45:24Z kredel $ # import sys from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import QQ, AN from jas import terminate from jas import startLog # polynomial examples: factorization over Q(i)(sqrt2) Q = PolyRing(QQ(),"i",PolyRing.lex); print "Q = " + str(Q); Q.inject_variables(); print "i = " + str(i); imag = i**2 + 1; print "imag = " + str(imag); Qi = AN(imag,field=True); print "Qi = " + str(Qi.factory()); Qi.inject_variables(); print "i = " + str(i); print; Wr = PolyRing(Qi,"w2",PolyRing.lex) print "Wr = " + str(Wr); Wr.inject_variables(); print "i = " + str(i); print "w2 = " + str(w2); w2p = w2**2 - 2; print "w2p = " + str(w2p); Qw2 = AN(w2p,field=True); print "Qw2 = " + str(Qw2.factory()); Qw2.inject_variables(); print "i = " + str(i); print "w2 = " + str(w2); print; Qiw2 = PolyRing(Qw2,"x",PolyRing.lex) print "Qiw2 = " + str(Qiw2); Qiw2.inject_variables(); print "i = " + str(i); print "w2 = " + str(w2); print "x = " + str(x); print; #sys.exit(); f = ( x**2 + 1 ) * ( x**2 - 2 ); print "f = ", f; print; startLog(); t = System.currentTimeMillis(); G = Qiw2.factors(f); t = System.currentTimeMillis() - t; #print "G = ", G; #print "factor time =", t, "milliseconds"; g = one; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/0dim_primary-decomp.py0000644000175000017500000000161411376460372020407 0ustar giovannigiovanni# # jython examples for jas. # $Id: 0dim_primary-decomp.py 3150 2010-05-24 11:20:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: zero dimensional ideals prime and primary decomposition #r = Ring( "Rat(x) L" ); #r = Ring( "Q(x) L" ); r = PolyRing(QQ(),"x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); f1 = (x**2 - 5)**2; f2 = y**2 - 5; f3 = z**3 - y * x ; print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print; F = r.ideal( list=[f1,f2,f3] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); Q = F.primaryDecomp(); t = System.currentTimeMillis() - t; print "Q = ", Q; print; print "primary decomp time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/u_sl_2.rb0000644000175000017500000000121012136716620015667 0ustar giovannigiovanni# # jruby examples for jas. # $Id: u_sl_2.rb 4380 2013-04-27 09:42:41Z kredel $ # require "examples/jas" # U(sl_2) example rs = """ # solvable polynomials, U(sl_2): Rat(e,f,h) G RelationTable ( ( f ), ( e ), ( e f - h ), ( h ), ( e ), ( e h + 2 e ), ( h ), ( f ), ( f h - 2 f ) ) """; r = SolvableRing.new( rs ); puts "SolvableRing: " + str(r); puts; ps = """ ( ( e^2 + f^3 ) ) """; f = r.ideal( ps ); puts "SolvableIdeal: " + str(f); puts; #startLog(); rg = f.leftGB(); puts "seq left GB: " + str(rg); puts; rg = f.twosidedGB(); puts "seq twosided GB: " + str(rg); puts; rg = f.rightGB(); puts "seq right GB: " + str(rg); puts; jas-2.5/examples/quantum.py0000644000175000017500000000251011425115600016216 0ustar giovannigiovanni# # jython examples for jas. # $Id: quantum.py 3235 2010-07-31 21:54:09Z kredel $ # from jas import SolvableModule from jas import SolvableSubModule # Quantum plane example rsan = """ AN[ (i) (i^2 + 1) ] (Y,X,x,y) G RelationTable ( ( y ), ( x ), ( {i} x y ) ( X ), ( Y ), ( {i} Y X ) ) """; rsc = """ C(Y,X,x,y) G |2| RelationTable ( ( y ), ( x ), ( 0i1 x y ) ( X ), ( Y ), ( 0i1 Y X ) ) """; #r = SolvableModule( rsc ); r = SolvableModule( rsan ); print "SolvableModule: " + str(r); print; ps = """ ( ( ( x + 1 ), ( y ) ), ( ( x y ), ( 0 ) ), ( ( x - X ), ( x - X ) ), ( ( y - Y ), ( y - Y ) ) ) """; f = SolvableSubModule( r, ps ); print "SolvableSubModule: " + str(f); print; flg = f.leftGB(); print "seq left GB:", flg; print; if flg.isLeftGB(): print "is left GB"; else: print "is not left GB"; ftg = f.twosidedGB(); print "seq twosided GB:", ftg; print; if ftg.isLeftGB(): print "twosided GB is left GB"; else: print "twosided GB is not left GB"; if ftg.isRightGB(): print "twosided GB is right GB"; else: print "twosided GB is not right GB"; if ftg.isTwosidedGB(): print "is twosided GB"; else: print "is not twosided GB"; from jas import startLog startLog(); frg = f.rightGB(); print "seq right GB:", frg; print; if frg.isRightGB(): print "is right GB"; else: print "is not right GB"; jas-2.5/examples/katsura3.jas0000644000175000017500000000041111353207070016407 0ustar giovannigiovanni#Katsura equations for N = 3: (u3,u2,u1,u0) L ( u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 - u0, u3*0 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 - u1, u3*0 + u2*0 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 - u2, u3 + u2 + u1 + u0 + u1 + u2 + u3 - 1 ) jas-2.5/examples/nabeshima_cgbF8.py0000644000175000017500000000300211304010406017453 0ustar giovannigiovanni# # jython examples for jas. # $Id: nabeshima_cgbF8.py 2882 2009-11-27 17:48:55Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Nabashima, ISSAC 2007, example F8 # modified, take care # integral function coefficients #r = Ring( "IntFunc(d, b, a, c) (y,x,w,z) L" ); r = Ring( "IntFunc(d, b, a, c) (y,x,w,z) G" ); #r = Ring( "IntFunc(d, b, c, a) (w,z,y,x) G" ); #r = Ring( "IntFunc(b, c, a) (w,x,z,y) L" ); #r = Ring( "IntFunc(b, c) (z,y,w,x) L" ); #r = Ring( "IntFunc(b) (z,y,w,x) L" ); #r = Ring( "IntFunc(c) (z,y,w,x) L" ); #r = Ring( "IntFunc(c) (z,y,w,x) G" ); print "Ring: " + str(r); print; ps = """ ( ( { c } w^2 + z ), ( { a } x^2 + { b } y ), ( ( x - z )^2 + ( y - w)^2 ), ( { 2 d } x w - { 2 b } y ) ) """; ## ( { 1 } x^2 + { 1 } y ), ## ( { 1 } w^2 + z ), ## ( { 2 } x w - { 2 1 } y ) # ( { 1 } x^2 + { b } y ), # ( { c } w^2 + z ), # ( { a } x^2 + { b } y ), # ( { 2 d } x w - { 2 b } y ) #startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; #startLog(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; terminate(); sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/raksanyi_int.py0000644000175000017500000000140711051351722017225 0ustar giovannigiovanni# # jython examples for jas. # $Id: raksanyi_int.py 2065 2008-08-15 19:06:59Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Raksanyi & Walter example # rational function coefficients r = Ring( "IntFunc(a1, a2, a3, a4) (x1, x2, x3, x4) L" ); print "Ring: " + str(r); print; ps = """ ( ( x4 - { a4 - a2 } ), ( x1 + x2 + x3 + x4 - { a1 + a3 + a4 } ), ( x1 x3 + x1 x4 + x2 x3 + x3 x4 - { a1 a4 + a1 a3 + a3 a4 } ), ( x1 x3 x4 - { a1 a3 a4 } ) ) """; f = r.paramideal( ps ); print "Ideal: " + str(f); print; #startLog(); rg = f.GB(); rg = f.GB(); print "Ideal: " + str(rg); print; bg = rg.isGB(); if bg: print "isGB: true"; else: print "isGB: false"; print; terminate(); #sys.exit(); jas-2.5/examples/cyclic5_real_roots.py0000644000175000017500000000221011722152614020313 0ustar giovannigiovanni# # jython examples for jas. # $Id: cyclic5_real_roots.py 3892 2012-02-25 12:35:24Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: real roots over Q for zero dimensional ideal `cyclic5' #r = Ring( "Q(x) L" ); r = PolyRing(QQ(),"a,b,c,d,e",PolyRing.lex); print "Ring: " + str(r); print; [one,a,b,c,d,e] = r.gens(); f1 = a + b + c + d + e; f2 = a*b + b*c + c*d + d*e + e*a; f3 = a*b*c + b*c*d + c*d*e + d*e*a + e*a*b; f4 = a*b*c*d + b*c*d*e + c*d*e*a + d*e*a*b + e*a*b*c; f5 = a*b*c*d*e - 1; print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print "f4 = ", f4; print "f5 = ", f5; print; F = r.ideal( list=[f1,f2,f3,f4,f5] ); print "F = ", F; print; startLog(); #G = F.GB(); #print "G = ", G; #print; #sys.exit(); t = System.currentTimeMillis(); R = F.realRoots(); t = System.currentTimeMillis() - t; print; print "R = ", R; print; print "real roots: "; F.realRootsPrint() print "real roots time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/cgbmmn15.rb0000644000175000017500000000207611641163152016124 0ustar giovannigiovanni# # jruby examples for jas. # $Id: cgbmmn15.rb 3785 2011-09-29 21:43:06Z kredel $ # require "examples/jas" # rational function coefficients # IP (alpha,beta,gamma,epsilon,theta,eta) # (c3,c2,c1) /G/ #r = Ring( "IntFunc(alpha,beta,gamma,epsilon,theta,eta)(c3,c2,c1) G" ); # ( { alpha } c1 - { beta } c1**2 - { gamma } c1 c2 + { epsilon } c3 ), # ( - { gamma } c1 c2 + { epsilon + theta } c3 - { gamma } c2 ), # ( { gamma } c2 c3 + { eta } c2 - { epsilon + theta } c3 ) r = Ring.new( "IntFunc(a,b,g,e,t,eta)(c3,c2,c1) G" ); puts "Ring: " + str(r); puts; ps = """ ( ( { a } c1 - { b } c1**2 - { g } c1 c2 + { e } c3 ), ( - { g } c1 c2 + { e + t } c3 - { g } c2 ), ( { g } c2 c3 + { eta } c2 - { e + t } c3 ) ) """; f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; #sys.exit(); startLog(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; #sys.exit(); #bg = gs.isCGBsystem(); #puts "isCGBsystem: " + str(bg); #puts; #sys.exit(); #gs = f.CGB(); #puts "CGB: " + str(gs); #puts; #bg = gs.isCGB(); #puts "isCGB: " + str(bg); #puts; terminate(); #sys.exit(); jas-2.5/examples/factors_algeb_trans.py0000644000175000017500000000570511572725750020557 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_algeb_trans.py 3658 2011-06-05 16:16:41Z kredel $ # import sys from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import QQ, AN, RF from jas import terminate from jas import startLog # polynomial examples: factorization over Q(sqrt(2))(x)(sqrt(x))[y] Q = PolyRing(QQ(),"w2",PolyRing.lex); print "Q = " + str(Q); [e,a] = Q.gens(); #print "e = " + str(e); print "a = " + str(a); root = a**2 - 2; print "root = " + str(root); Q2 = AN(root,field=True); print "Q2 = " + str(Q2.factory()); [one,w2] = Q2.gens(); #print "one = " + str(one); #print "w2 = " + str(w2); print; Qp = PolyRing(Q2,"x",PolyRing.lex); print "Qp = " + str(Qp); [ep,wp,ap] = Qp.gens(); #print "ep = " + str(ep); #print "wp = " + str(wp); #print "ap = " + str(ap); print; Qr = RF(Qp); print "Qr = " + str(Qr.factory()); [er,wr,ar] = Qr.gens(); #print "er = " + str(er); #print "wr = " + str(wr); #print "ar = " + str(ar); print; Qwx = PolyRing(Qr,"wx",PolyRing.lex); print "Qwx = " + str(Qwx); [ewx,wwx,ax,wx] = Qwx.gens(); #print "ewx = " + str(ewx); print "ax = " + str(ax); #print "wwx = " + str(wwx); print "wx = " + str(wx); print; rootx = wx**2 - ax; print "rootx = " + str(rootx); Q2x = AN(rootx,field=True); print "Q2x = " + str(Q2x.factory()); [ex2,w2x2,ax2,wx] = Q2x.gens(); #print "ex2 = " + str(ex2); #print "w2x2 = " + str(w2x2); #print "ax2 = " + str(ax2); #print "wx = " + str(wx); print; Yr = PolyRing(Q2x,"y",PolyRing.lex) print "Yr = " + str(Yr); [e,w2,x,wx,y] = Yr.gens(); print "e = " + str(e); print "w2 = " + str(w2); print "x = " + str(x); print "wx = " + str(wx); print "y = " + str(y); print; f = ( y**2 - x ) * ( y**2 - 2 ); #f = ( y**2 - x )**2 * ( y**2 - 2 )**3; #f = ( y**4 - x * 2 ); #f = ( y**7 - x * 2 ); #f = ( y**2 - 2 ); #f = ( y**2 - x ); #f = ( w2 * y**2 - 1 ); #f = ( y**2 - 1/x ); #f = ( y**2 - (1,2) ); #f = ( y**2 - 1/x ) * ( y**2 - (1,2) ); print "f = ", f; print; #sys.exit(); startLog(); t = System.currentTimeMillis(); G = Yr.factors(f); t = System.currentTimeMillis() - t; #print "G = ", G; #print "factor time =", t, "milliseconds"; #sys.exit(); print "f = ", f; g = one; for h, i in G.iteritems(): if i > 1: print "h**i = ", h, "**" + str(i); else: print "h = ", h; h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; sys.exit(); t = System.currentTimeMillis(); G = Yr.factors(f); t = System.currentTimeMillis() - t; #print "G = ", G; print "2 factor time =", t, "milliseconds"; t = System.currentTimeMillis(); G = Yr.factors(f); t = System.currentTimeMillis() - t; #print "G = ", G; print "3 factor time =", t, "milliseconds"; #startLog(); terminate(); jas-2.5/examples/wa_1.py0000644000175000017500000000121512136720410015355 0ustar giovannigiovanni# # jython examples for jas. # $Id: wa_1.py 4381 2013-04-27 09:57:28Z kredel $ # from jas import SolvableRing # WA_1 example rs = """ # solvable polynomials, Weyl algebra A_1: Rat(p,t,x,d) G RelationTable ( ( d ), ( x ), ( x d + 1 ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( x^7 ), ( x d + 7 ) ) """; i7 = r.ideal( ps ); print "SolvableIdeal: " + str(i7); print; i7rg = i7.leftGB(); print "seq left i7 Output:", i7rg; print; ps = """ ( ( d^7 ), ( x d - 7 + 1 ) ) """; j7 = r.ideal( ps ); print "SolvableIdeal: " + str(j7); print; j7rg = j7.leftGB(); print "seq left i7 Output:", j7rg; print; jas-2.5/examples/rose_part.py0000644000175000017500000000537210676546664016564 0ustar giovannigiovanni# # jython examples for jas. # $Id: rose_part.py 1385 2007-09-26 21:23:01Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # example from rose (modified) #r = Ring( "Mod 19 (U3,U4,A46) L" ); #r = Ring( "Mod 1152921504606846883 (U3,U4,A46) L" ); # 2^60-93 #r = Ring( "Quat(U3,U4,A46) L" ); #r = Ring( "Z(U3,U4,A46) L" ); #r = Ring( "C(U3,U4,A46) L" ); r = Ring( "Rat(A46,U3,U4) L" ); print "Ring: " + str(r); print; ps = """ ( %s ( U4^4 - 20/7 A46^2 ), ( A46^2 U3^4 + 7/10 A46 U3^4 + 7/48 U3^4 - 50/27 A46^2 - 35/27 A46 - 49/216 ), ( A46^5 U4^3 + 7/5 A46^4 U4^3 + 609/1000 A46^3 U4^3 + 49/1250 A46^2 U4^3 - 27391/800000 A46 U4^3 - 1029/160000 U4^3 + 3/7 A46^5 U3 U4^2 + 3/5 A46^6 U3 U4^2 + 63/200 A46^3 U3 U4^2 + 147/2000 A46^2 U3 U4^2 + 4137/800000 A46 U3 U4^2 - 7/20 A46^4 U3^2 U4 - 77/125 A46^3 U3^2 U4 - 23863/60000 A46^2 U3^2 U4 - 1078/9375 A46 U3^2 U4 - 24353/1920000 U3^2 U4 - 3/20 A46^4 U3^3 - 21/100 A46^3 U3^3 - 91/800 A46^2 U3^3 - 5887/200000 A46 U3^3 - 343/128000 U3^3 ) ) """; pp1 = """ ( 20 A46 + 7 ), """; pp2 = """ ( 5480334637123239936000000000000000000 A46^32 + 23330567455181792870400000000000000000 A46^31 - 22260410953422455439360000000000000000 A46^30 - 379039147753503876710400000000000000000 A46^29 - 1305289515920841108357120000000000000000 A46^28 - 2661894008686715272062566400000000000000 A46^27 - 3732109213267597335472373760000000000000 A46^26 - 3719328899522099347074318336000000000000 A46^25 - 2513175000419852400394764288000000000000 A46^24 - 801907472074794268996141056000000000000 A46^23 + 559468735767998648283977220096000000000 A46^22 + 1161692745234469227508358814105600000000 A46^21 + 1115120737963786660933876454522880000000 A46^20 + 754183677763034219243933188227072000000 A46^19 + 366205139138005719200006792439398400000 A46^18 + 95407136698255889087520898673541120000 A46^17 - 35897763757636362165902256717692928000 A46^16 - 68696958358719191677546842722559590400 A46^15 - 55382563098545072682320366954843996160 A46^14 - 32223104574376823941781148035505979392 A46^13 - 14867126462105106300205537184606126080 A46^12 - 5596017809975575801376014016653721600 A46^11 - 1730893404306213749794640488178116608 A46^10 - 438698743729822786570094575456788480 A46^9 - 90199241991532353478039712103521280 A46^8 - 14778859703096558479650421488297984 A46^7 - 1874056025467134008603806670325120 A46^6 - 174876413639867324175892636604160 A46^5 - 10843113615171040141214782270464 A46^4 - 325577720150105105056746125600 A46^3 + 6040454553390756509792153750 A46^2 + 761038687880048862537750000 A46 + 13745464623924567359765625 ), """; pp = ps % pp1; f = Ideal( r, pp ); print "Ideal: " + str(f); print; startLog(); rg = f.GB(); print "seq Output:", rg; print; #sys.exit(); jas-2.5/examples/cgb_0.py0000644000175000017500000000163111226350524015506 0ustar giovannigiovanni# # jython examples for jas. # $Id: cgb_0.py 2734 2009-07-12 12:04:37Z kredel $ # import sys; from jas import Ring from jas import ParamIdeal from jas import startLog from jas import terminate # simple example for comprehensive GB # integral/rational function coefficients #r = Ring( "RatFunc(u,v) (x,y) L" ); r = Ring( "IntFunc(u,v) (x,y) L" ); print "Ring: " + str(r); print; ps = """ ( ( { v } x y + x ), ( { u } y^2 + x^2 ) ) """; f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; #sys.exit(); #startLog(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; #sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); #startLog(); gs = f.CGB(); print "CGB: " + str(gs); print; #startLog(); bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #sys.exit(); jas-2.5/examples/cgb_2.py0000644000175000017500000000174711304010406015505 0ustar giovannigiovanni# # jython examples for jas. # $Id: cgb_2.py 2882 2009-11-27 17:48:55Z kredel $ # import sys; from jas import Ring from jas import ParamIdeal from jas import startLog from jas import terminate # 2 univariate polynomials of degree 2 example for comprehensive GB # integral/rational function coefficients #r = Ring( "RatFunc(u,v) (x,y) L" ); r = Ring( "IntFunc(a2, a1, a0, b2, b1, b0) (x) L" ); print "Ring: " + str(r); print; ps = """ ( ( { a2 } x^2 + { a1 } x + { a0 } ), ( { b2 } x^2 + { b1 } x + { b0 } ) ) """; f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; #sys.exit(); #startLog(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; #sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; terminate(); sys.exit(); bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #sys.exit(); jas-2.5/examples/squarefree_finite.py0000644000175000017500000000167711224463142020245 0ustar giovannigiovanni# # jython examples for jas. # $Id: squarefree_finite.py 2717 2009-07-06 21:02:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import PolyRing, QQ, ZM from jas import terminate from jas import startLog # polynomial examples: squarefree: characteristic p, finite #r = PolyRing(QQ(),"x, y, z",PolyRing.lex) r = PolyRing(ZM(5,field=True),"x, y, z",PolyRing.lex) print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); a = r.random(k=2,l=3); b = r.random(k=2,l=3); c = r.random(k=1,l=3); if a.isZERO(): a = x; if b.isZERO(): b = y; if c.isZERO(): c = z; f = a**10 * b**5 * c; print "a = ", a; print "b = ", b; print "c = ", c; print "f = ", f; print; t = System.currentTimeMillis(); F = r.squarefreeFactors(f); t = System.currentTimeMillis() - t; print "factors:"; for g in F.keys(): i = F[g]; print "g = %s**%s" % (g,i); print print "factor time =", t, "milliseconds"; #startLog(); terminate(); jas-2.5/examples/word_evans.py0000644000175000017500000000225212023444260016700 0ustar giovannigiovanni# # jython examples for jas. # $Id: word_evans.py 4186 2012-09-10 20:08:16Z kredel $ # #from java.lang import System from jas import WordRing, WordPolyRing, WordIdeal from jas import terminate, startLog from jas import QQ, ZZ, GF, ZM # non-commutative polynomial examples: evans example r = WordPolyRing(QQ(),"x,y,z"); print "WordPolyRing: " + str(r); print; [one,x,y,z] = r.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); print; f1 = x * y - z; f2 = y * z + 2 * x + z; f3 = y * z + x; print "f1 = " + str(f1); print "f2 = " + str(f2); print "f3 = " + str(f3); print; F = r.ideal( list=[f1,f2,f3] ); print "F = " + str(F); print; startLog(); G = F.GB(); print "G = " + str(G); print "isGB(G) = " + str(G.isGB()); print; #exit(0); c1 = f1 * f2; c2 = f2 * f1; s = c1 - c2; print "c1 = " + str(c1); print "c2 = " + str(c2); print "s = " + str(s); print; Fa = r.ideal( list=[f1,f2,f3,c1,c2,s] ); print "Fa = " + str(Fa); print; Ga = Fa.GB(); print "Ga = " + str(Ga); print "isGB(Ga) = " + str(Ga.isGB()); #print; #print "G = " + str(G); print "G == Ga: " + str(cmp(G,Ga)); print "G == Ga: " + str(G.list == Ga.list); print; jas-2.5/examples/factors_mult.rb0000644000175000017500000000306411773570014017220 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_mult.rb 3968 2012-06-30 12:24:45Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: factorization r = PolyRing.new( ZZ(), "x,y,z", PolyRing.lex ); puts "Ring: " + str(r); puts #one,x,y,z = r.gens(); #f = z * ( y + 1 )**2 * ( x**2 + x + 1 )**3; #f = z * ( y + 1 ) * ( x**2 + x + 1 ); #f = ( y + 1 ) * ( x**2 + x + 1 ); #f = ( y + z**2 ) * ( x**2 + x + 1 ); #f = x**4 * y + x**3 + z + x + z**2 + y * z**2; ## f = x**3 + ( ( y + 2 ) * z + 2 * y + 1 ) * x**2 \ ## + ( ( y + 2 ) * z**2 + ( y**2 + 2 * y + 1 ) * z + 2 * y**2 + y ) * x \ ## + ( y + 1 ) * z**3 + ( y + 1 ) * z**2 + ( y**3 + y**2 ) * z + y**3 + y**2; #f = ( x + y * z + y + z + 1 ) * ( x**2 + ( y + z ) * x + y**2 + z**2 ); f = ( x + y * z + y + z + 1 ) * ( x**2 + ( y + z ) * x + y**2 + 1 ); #f = ( x + y ) * ( x - y); puts "f = ", f; puts; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; puts "G = ", str(G.map{ |h,i| str(h)+"**"+str(i)+" " }); #puts "G = ", G; #puts "factor time =", t, "milliseconds"; puts; puts "f = " + str(f); g = one; for h, i in G do if i > 1 then puts "h**i = " + str(h) + "**" + str(i); else puts "h = " + str(h); end h = h**i; g = g*h; end puts; #puts "g = ", g; if f == g then puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): true" ; else puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): " + str(f==g); end puts; #startLog(); terminate(); jas-2.5/examples/kw_18.jas0000644000175000017500000000027410653077260015622 0ustar giovannigiovanni# solvable polynomials, example 1.8 from KW: (x,y,z) L RelationTable ( ( y ), ( x ), ( x y + x ), ( z ), ( y ), ( y z + z ) ) ( ( y**3 + x**2 y + x y ), ( x**2 + z ), ( z**2 + z ) ) jas-2.5/examples/all_rings.rb0000644000175000017500000005675611511413244016477 0ustar giovannigiovanni# # jruby examples for jas. # $Id: all_rings.rb 3471 2011-01-06 19:23:17Z kredel $ # #load "examples/jas.rb" require "examples/jas" puts "------- ZZ = BigInteger ------------"; z1 = ZZ(12345678901234567890); puts "z1 = " + str(z1); z2 = z1**2 + 12345678901234567890; puts "z2 = " + str(z2); puts; puts "------- QQ = BigRational ------------"; r1 = QQ(1,12345678901234567890); puts "r1 = " + str(r1**3); r2 = r1**2 + 1/12345678901234567890; puts "r2 = " + str(r2); puts; puts "------- ZM = ModInteger ------------"; m1 = ZM(19,12345678901234567890); puts "m1 = " + str(m1); m2 = m1**2 + 12345678901234567890; puts "m2 = " + str(m2); puts; puts "------- DD = BigDecimal ------------"; d1 = DD(12345678901234567890); puts "d1 = " + str(d1); d2 = (1/d1)**2; puts "d2 = " + str(d2); puts; puts "------- CC = BigComplex ------------"; c1 = CC(1/2,5); puts "c1 = " + str(c1); c2 = (1/c1)**2; puts "c2 = " + str(c2); c3 = CC(0,1); c3 = 1/c3; puts "c3 = " + str(c3); one,I = CC().gens(); puts "one = " + str(one); puts "I = " + str(I); c4 = c3 + 5 * I; puts "c4 = " + str(c4); c5 = -396/10201 - 80/10201*I; puts "c5 = " + str(c5); puts; puts "------- Quat = BigQuaternion ------------"; oneQ,IQ,JQ,KQ = Quat().gens(); puts "oneQ = " + str(oneQ); puts "IQ = " + str(IQ); puts "JQ = " + str(JQ); puts "KQ = " + str(KQ); q1 = 2 + 3 * IQ + 4 * JQ + 5 * KQ; puts "q1 = " + str(q1); q2 = (1/q1)**2; puts "q2 = " + str(q2); q3 = q2 * q1 * q1; puts "q3 = " + str(q3); q4 = -23/1458 + -1/243*IQ + -4/729*JQ + -5/729*KQ puts "q4 = " + str(q4); q5 = q2 - q4; puts "q5 = " + str(q5); puts; puts "------- Oct = BigOctonion ------------"; #puts [ str(g) for g in Oct().gens() ]; oneOR,IOR,JOR,KOR,oneOI,IOI,JOI,KOI = Oct().gens(); puts "oneOR = " + str(oneOR); puts "IOR = " + str(IOR); puts "JOR = " + str(JOR); puts "KOR = " + str(KOR); puts "oneOI = " + str(oneOI); puts "IOI = " + str(IOI); puts "JOI = " + str(JOI); puts "KOI = " + str(KOI); o1 = 2 * oneOR + 3 * IOR + 4 * JOR + 5 * KOR + 6 * oneOI + 7 * IOI + 8 * JOI + 9 * KOI; puts "o1 = " + str(o1); o2 = (1/o1)**2; puts "o2 = " + str(o2); o3 = o2 * o1 * o1; puts "o3 = " + str(o3); o4 = -69/20164*oneOR + -3/20164*IOR + -1/5041*JOR + -5/20164*KOR + -3/10082*oneOI + -7/20164*IOI + -2/5041*JOI + -9/20164*KOI; puts "o4 = " + str(o4); o5 = o2 - o4; puts "o5 = " + str(o5); puts; puts "------- PolyRing(ZZ(),\"x,y,z\") ---------"; r = PolyRing.new(ZZ(),"x,y,z",PolyRing::grad); puts "r = " + str(r); one,x,y,z = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); p1 = 2 + 3 * x + 4 * y + 5 * z + ( x + y + z )**2; puts "p1 = " + str(p1); p2 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + 5 * z + 4 * y + 3 * x + 2; puts "p2 = " + str(p2); p3 = p1 - p2; puts "p3 = " + str(p3); puts "p3.factory() = " + str(p3.factory()); puts; puts "------- PolyRing(QQ(),\"x,y,z\") ---------"; r = PolyRing.new(QQ(),"x,y,z",PolyRing.grad); puts "r = " + str(r); one,x,y,z = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); s1 = QQ(1,2) + QQ(2,3) * x + QQ(2,5) * y + ( x + y + z )**2; puts "s1 = " + str(s1); s2 = 1/2 + 2/3 * x + 2/5 * y + ( x + y + z )**2; puts "s2 = " + str(s2); s3 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + 2/5 * y + 2/3 * x + 1/2; puts "s3 = " + str(s3); s4 = s1 - s3; puts "s4 = " + str(s4); puts "s4.factory() = " + str(s4.factory()); puts; puts "------- PolyRing(ZM(11),\"x,y,z\") ---------"; r = PolyRing.new(ZM(11),"x,y,z",PolyRing.grad); puts "r = " + str(r); one,x,y,z = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); p1 = 12 + 13 * x + 14 * y + 15 * z + ( x + y + z )**2; puts "p1 = " + str(p1); p2 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + 4 * z + 3 * y + 2 * x + 1; puts "p2 = " + str(p2); p3 = p1 - p2; puts "p3 = " + str(p3); puts "p3.factory() = " + str(p3.factory()); puts; puts "------- PolyRing(DD(),\"x,y,z\") ---------"; r = PolyRing.new(DD(),"x,y,z",PolyRing.grad); puts "r = " + str(r); one,x,y,z = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); p1 = 0.2 + 0.3 * x + 0.4 * y + 0.5 * z + ( x + y + z )**2; puts "p1 = " + str(p1); p2 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + 0.5 * z + 0.40000000000000002220446049250313080847263336181641 * y + 0.29999999999999998889776975374843459576368331909180 * x + 0.200000000000000011102230246251565404236316680908203125; puts "p2 = " + str(p2); p3 = p1 - p2; puts "p3 = " + str(p3); puts "p3.factory() = " + str(p3.factory()); puts; puts "------- PolyRing(CC(),\"x,y,z\") ---------"; r = PolyRing.new(CC(),"x,y,z",PolyRing.grad); puts "r = " + str(r); one,I,x,y,z = r.gens(); puts "one = " + str(one); puts "I = " + str(I); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); s1 = CC(1/2) + CC(2/3) * x + 3 * I * y + ( x + y + z )**2; puts "s1 = " + str(s1); #puts "s1.factory() = " + str(s1.factory()); #puts "s1.coefficients() = " + str(s1.coefficients()); s2 = CC(1/2) + CC(2/3) * x + 3 * I * y + ( x + y + z )**2; puts "s2 = " + str(s2); #puts "s2.factory() = " + str(s2.factory()); #puts "s2.coefficients() = " + str(s2.coefficients()); s3 = z**2 + CC(2) * y * z + CC(2) * x * z + y**2 + CC(2) * x * y + x**2 + CC(0,3) * y + CC(2/3) * x + CC(1/2); puts "s3 = " + str(s3); #puts "s3.factory() = " + str(s3.factory()); #puts "s3.coefficients() = " + str(s3.coefficients()); s4 = s3 - s1; puts "s4 = " + str(s4); puts "s4.factory() = " + str(s4.factory()); puts; puts "------- PolyRing(Quat(),\"x,y,z\") ---------"; r = PolyRing.new(Quat(),"x,y,z",PolyRing.grad); puts "r = " + str(r); oneQ,IQ,JQ,KQ,x,y,z = r.gens(); puts "oneQ = " + str(oneQ); puts "IQ = " + str(IQ); puts "JQ = " + str(JQ); puts "KQ = " + str(KQ); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); s1 = Quat(1/2) + Quat(2/3) * x + Quat(2/5) * y + ( x + y + z )**2; puts "s1 = " + str(s1); s2 = Quat(1/2) + Quat(2/3) * x + Quat(2/5) * y + ( x + y + z )**2; puts "s2 = " + str(s2); s3 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + Quat(2/5) * y + Quat(2/3) * x + Quat(1/2); puts "s3 = " + str(s3); s4 = s3 - s1; puts "s4 = " + str(s4); puts "s4.factory() = " + str(s4.factory()); puts; puts "------- PolyRing(Oct(),\"x,y,z\") ---------"; r = PolyRing.new(Oct(),"x,y,z",PolyRing.grad); puts "r = " + str(r); oneOR,IOR,JOR,KOR,oneOI,IOI,JOI,KOI,x,y,z = r.gens(); puts "oneOR = " + str(oneOR); puts "IOR = " + str(IOR); puts "JOR = " + str(JOR); puts "KOR = " + str(KOR); puts "oneOI = " + str(oneOI); puts "IOI = " + str(IOI); puts "JOI = " + str(JOI); puts "KOI = " + str(KOI); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); s1 = Oct(Quat(1/2)) + Oct(Quat(2/3)) * x + Oct(Quat(2/5)) * y + ( x + y + z )**2; puts "s1 = " + str(s1); s2 = QQ(1,2) + QQ(2,3) * x + QQ(2,5) * y + ( x + y + z )**2; puts "s2 = " + str(s2); s3 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + QQ(2,5) * y + QQ(2,3) * x + QQ(1,2); puts "s3 = " + str(s3); s4 = s3 - s1; puts "s4 = " + str(s4); puts "s4.factory() = " + str(s4.factory()); puts; puts "------- AN(alpha**2 - 2) ---------"; r = PolyRing.new(QQ(),"alpha",PolyRing.lex); puts "r = " + str(r); e,a = r.gens(); puts "e = " + str(e); puts "a = " + str(a); sqrt2 = a**2 - 2; puts "sqrt2 = " + str(sqrt2); Qs2 = AN(sqrt2); puts "Qs2 = " + str(Qs2.factory()); one,alpha = Qs2.gens(); puts "one = " + str(one); puts "alpha = " + str(alpha); b = alpha**2 - 2; puts "b = " + str(b); c = 1 / alpha; puts "c = " + str(c); Qs2x = AN(alpha**2 - 2); puts "Qs2x = " + str(Qs2x.factory()); puts; puts "------- GF_17(alpha**2 - 2) ---------"; r = PolyRing.new(ZM(17),"alpha",PolyRing.lex); puts "r = " + str(r); e,a = r.gens(); puts "e = " + str(e); puts "a = " + str(a); sqrt2 = a**2 - 2; puts "sqrt2 = " + str(sqrt2); Qs2 = AN(sqrt2); puts "Qs2 = " + str(Qs2.factory()); one,alpha = Qs2.gens(); puts "one = " + str(one); puts "alpha = " + str(alpha); b = alpha**2 - 2; puts "b = " + str(b); c = 1 / alpha; puts "c = " + str(c); Qs2x = AN(alpha**2 - 2); puts "Qs2x = " + str(Qs2x.factory()); puts; puts "------- RealN(alpha**2 - 2,(1,2) ---------"; r = PolyRing.new(QQ(),"alpha",PolyRing.lex); puts "r = " + str(r); e,a = r.gens(); puts "e = " + str(e); puts "a = " + str(a); sqrt2 = a**2 - 2; puts "sqrt2 = " + str(sqrt2); Qs2r = RealN(sqrt2,[1,2]); puts "Qs2r = " + str(Qs2r.factory()); one,alpha = Qs2r.gens(); puts "one = " + str(one); puts "alpha = " + str(alpha); b = 7 * alpha - 10; puts "b = " + str(b); puts "b.factory() = " + str(b.factory()); puts "sign(b) = " + str(b.signum()); puts "magnitude(b) = " + str(BigDecimal.new(b.elem.magnitude())); c = 1 / b; puts "c = " + str(c); puts "sign(c) = " + str(c.signum()); puts "magnitude(c) = " + str(BigDecimal.new(c.elem.magnitude())); Qs2rx = RealN( alpha**2 - 2, [1,2] ); puts "Qs2rx = " + str(Qs2rx.factory()); puts; puts "------- PolyRing(PolyRing(QQ(),\"a,b,c\"),\"x,y,z\") ---------"; r = PolyRing.new(QQ(),"a,b,c",PolyRing.grad); puts "r = " + str(r); pr = PolyRing.new(r,"x,y,z",PolyRing.lex); puts "pr = " + str(pr); one,a,b,c,x,y,z = pr.gens(); puts "one = " + str(one); puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); s1 = QQ(1,2) + ( QQ(2,3) - c ) * x + ( QQ(2,5) + a + b )**2 * y + ( x + y + z )**2; puts "s1 = " + str(s1); s2 = 1/2 + ( 2/3 - c ) * x + ( 2/5 + a + b )**2 * y + ( x + y + z )**2; puts "s2 = " + str(s2); s3 = z**2 + ( 2 ) * y * z + ( 2 ) * x * z + y**2 + ( 2 ) * x * y + ( b**2 + 2 * a * b + a**2 + QQ(4,5) * b + QQ(4,5) * a + QQ(4,25) ) * y + x**2 - ( c - QQ(2,3) ) * x + ( QQ(1,2) ); puts "s3 = " + str(s3); s4 = s1 + s2 - 2 * s3; puts "s4 = " + str(s4); puts "s4.factory() = " + str(s4.factory()); x = PolyRing.new(PolyRing.new(QQ(),"a, b, c",PolyRing.grad),"x, y, z",PolyRing.lex); puts "x = " + str(x); puts; puts "------- RF(PolyRing(ZZ(),\"a,b,c\",PolyRing.lex)) ---------"; r = PolyRing.new(ZZ(),"a,b,c",PolyRing.lex); puts "r = " + str(r); rf = RF(r); puts "rf = " + str(rf.factory()); one,a,b,c = rf.gens(); puts "one = " + str(one); puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); q1 = a / b; puts "q1 = " + str(q1); q2 = ( -2 * c**2 + 4 * b**2 + 4 * a**2 - 7 ); puts "q2 = " + str(q2); q3 = ( -7 * b + 4 * a + 12 ); puts "q3 = " + str(q3); q4 = q2 / q3; puts "q4 = " + str(q4); q5 = ( 2 * c**2 - 4 * b**2 - 4 * a**2 + 7 ) / (7 * b - 4 * a - 12 ); puts "q5 = " + str(q5); q6 = q4 - q5; puts "q6 = " + str(q6); puts "q6.factory() = " + str(q6.factory()); x = RF(PolyRing.new(ZZ(),"a, b, c",PolyRing.lex)); puts "x = " + str(x.factory()); puts; puts "------- RC(PolyRing(QQ(),\"a,b,c\",PolyRing.lex)) ---------"; r = PolyRing.new(QQ(),"a,b,c",PolyRing.lex); puts "r = " + str(r); pone,pa,pb,pc = r.gens(); puts "pone = " + str(pone); puts "pa = " + str(pa); puts "pb = " + str(pb); puts "pc = " + str(pc); g1 = pa**2 - 2; puts "g1 = " + str(g1); g2 = pb**3 - 2; puts "g2 = " + str(g2); g3 = pc**2 - pa*pb; puts "g3 = " + str(g3); F = r.ideal("",list=[g1,g2,g3]); puts "F = " + str(F); rc = RC(F,0); puts "rc.factory() = " + str(rc.factory()); one,a,b,c = rc.gens(); puts "one = " + str(one); puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); r1 = a*b + c; puts "r1 = " + str(r1); r2 = r1*r1*r1 - r1*r1 + one; puts "r2 = " + str(r2); r3 = r2**3 - r1 + one; puts "r3 = " + str(r3); r4 = ( -120 * a * b**2 * c + 606 * b**2 * c + 1917 * a * b * c + 400 * b * c - 132 * a * c - 673 * c + 432 * a * b**2 + 2130 * b**2 + 1436 * a * b - 72 * b + 100 * a - 1950 ); puts "r4 = " + str(r4); r5 = r3 - r4; puts "r5 = " + str(r5); puts "r5.factory() = " + str(r5.factory()); r6 = 1/r2; puts "r6 = " + str(r6); r7 = r6 * r2; puts "r7 = " + str(r7); #F1 = SimIdeal.new(PolyRing.new(QQ(),"a, b, c",PolyRing.lex),list=[( pa**2 - 2 ), ( pb**3 - 2 ), ( pc**2 - pa * pb )]); #puts "F1 = " + str(F1); rc1 = RC(SimIdeal.new(PolyRing.new(QQ(),"a, b, c",PolyRing.lex),"",list=[( a**2 - 2 ), ( b**3 - 2 ), ( c**2 - a * b )])); puts "rc1.factory() = " + str(rc1.factory()); puts; puts "------- LC(PolyRing(QQ(),\"a,b,c\",PolyRing.lex)) ---------"; r = PolyRing.new(QQ(),"a,b,c",PolyRing.lex); puts "r = " + str(r); pone,pa,pb,pc = r.gens(); puts "pone = " + str(pone); puts "pa = " + str(pa); puts "pb = " + str(pb); puts "pc = " + str(pc); g1 = pa**2 - 2; puts "g1 = " + str(g1); g2 = pb**3 - 2; puts "g2 = " + str(g2); g3 = pc**2 - pa*pb; puts "g3 = " + str(g3); ff = r.ideal("",list=[g1,g2,g3]); puts "ff = " + str(ff); lc = LC(ff,0,1); puts "lc.factory() = " + str(lc.factory()); one,a,b,c = lc.gens(); puts "one = " + str(one); puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); #F1 = SimIdeal.new(PolyRing.new(QQ(),"a, b, c",PolyRing.lex),"",list=[( pa**2 - 2 ), ( pb**3 - 2 ), ( pc**2 - pa * pb )]); #puts "F1 = " + str(F1); lc1 = LC(SimIdeal.new(PolyRing.new(QQ(),"a, b, c",PolyRing.lex),"",list=[( a**2 - 2 ), ( b**3 - 2 ), ( c**2 - a * b )])); puts "lc1.factory() = " + str(lc1.factory()); l1 = a*b + c; puts "l1 = " + str(l1); l2 = l1*l1*l1 - l1*l1 + one; puts "l2 = " + str(l2); l3 = 1/l2; puts "l3 = " + str(l3); l4 = l3 * l2; puts "l4 = " + str(l4); l5 = a**2 - 2 + 1; puts "l5 = " + str(l5); l6 = 1/l5; puts "l6 = " + str(l6); l7 = (l1 * l2) / l2; puts "l7 = " + str(l7); puts; puts "------- RR( [QQ(),ZM(19),DD()] ) ---------"; r = RR( [ QQ(),ZM(19),DD() ] ); puts "r = " + str(r); puts "r.factory() = " + str(r.factory()); rc1 = RR( [ QQ(), ZM(19), DD() ] ); print "gens = " , r.gens().map { |x| str(x) + ", " }, "\n"; puts "rc1.factory() = " + str(rc1.factory()); pg0,pg1,pg2 = r.gens(); puts "pg0 = " + str(pg0); puts "pg1 = " + str(pg1); puts "pg2 = " + str(pg2); r1 = pg1 + pg2 + pg0; puts "r1 = " + str(r1); r2 = r1 * r1 + 7 * r1; puts "r2 = " + str(r2); r3 = r2**3; puts "r3 = " + str(r3); r4 = 1/r3; puts "r4 = " + str(r4); r5 = r4 - r1; puts "r5 = " + str(r5); r6 = -511/512 * pg0 + 17 * pg1; #TODO - 0.998046875 * pg2; puts "r6 = " + str(r6); puts; puts "------- PS(QQ(),\"x\") ---------"; r = PS(QQ(),"x"); puts "r = " + str(r); puts "r.factory() = " + str(r.factory()); one,x = r.gens(); puts "one = " + str(one); puts "x = " + str(x); p1 = x**2 - 2; puts "p1 = " + str(p1); p2 = x**3 - 2; puts "p2 = " + str(p2); p3 = x**2 - p1 * p2; puts "p3 = " + str(p3); p4 = - 4 + 3 * x**2 + 2 * x**3 - x**5; puts "p4 = " + str(p4); def g1(i) return r.ring.coFac.fromInteger( 2*i ); end def g2(i) #puts "2*QQ(i) = " + str(QQ(2)*QQ(i)) return 2*QQ(i); end g3 = Proc.new { |i| 2*QQ(i) } r = PS(QQ(),"x",&g3); puts "r = " + str(r); puts "r.factory() = " + str(r.factory()); one,x = r.gens(); puts "one = " + str(one); puts "x = " + str(x); p1 = x**2 - r; puts "p1 = " + str(p1); p2 = x**3 + r/2; puts "p2 = " + str(p2); puts; puts "------- MPS(QQ(),\"x,y\") ---------"; r = MPS(QQ(),"x,y"); puts "r = " + str(r); puts "r.factory() = " + str(r.factory()); one,x,y = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); p1 = x**2 - 2*y; puts "p1 = " + str(p1); p2 = x**3 * y - y**2; puts "p2 = " + str(p2); p3 = x**2 * y**2 - p1 * p2; puts "p3 = " + str(p3); p4 = - 4 + 3 * x**2 + 2 * x**3 - x**5; puts "p4 = " + str(p4); def g1(i) return r.ring.coFac.fromInteger( i.getVal(0)*i.getVal(1) ); end def g2(i) #puts "QQ(i.0)*QQ(i.1) = " + str(QQ(i.getVal(0))*QQ(i.getVal(1))) return QQ(i.getVal(0))*QQ(i.getVal(1)); end g3 = Proc.new { |i| QQ(i.getVal(0))*QQ(i.getVal(1)) } r = MPS(QQ(),"x,y",&g3); puts "r = " + str(r); puts "r.factory() = " + str(r.factory()); one,x,y = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); p1 = x**2 - r; puts "p1 = " + str(p1); p2 = y**3 + r/2; puts "p2 = " + str(p2); puts; puts "------- Vec(QQ(),7) ---------"; r = Vec(QQ(),7); puts "r = " + str(r); puts "r.factory() = " + str(r.factory()); #puts [ str(g) for g in r.gens() ]; e1,e2,e3,e4,e5,e6,e7 = r.gens(); puts "e1 = " + str(e1); puts "e2 = " + str(e2); puts "e3 = " + str(e3); puts "e4 = " + str(e4); puts "e5 = " + str(e5); puts "e6 = " + str(e6); puts "e7 = " + str(e7); v1 = e1 + e3; puts "v1 = " + str(v1); #v2 = v1 + 5 * e7; #puts "v2 = " + str(v2); v3 = v1 - e1 - e3; puts "v3 = " + str(v3); puts; puts "------- Mat(QQ(),3,3) ---------"; r = Mat(QQ(),3,3); puts "r = " + str(r); puts "r.factory() = " + str(r.factory()); #puts [ str(g) for g in r.gens() ]; e11,e12,e13,e21,e22,e23,e31,e32,e33 = r.gens(); puts "e11 = " + str(e11); puts "e12 = " + str(e12); puts "e13 = " + str(e13); puts "e21 = " + str(e21); puts "e22 = " + str(e22); puts "e23 = " + str(e23); puts "e31 = " + str(e31); puts "e32 = " + str(e32); puts "e33 = " + str(e33); m1 = e11 + e31; puts "m1 = " + str(m1); m2 = m1 * m1 + 5*e22; puts "m2 = " + str(m2); m3 = m2**3 - 125*e21 - 125*e23; puts "m3 = " + str(m3); #m4 = 1/m2; #puts "m4 = " + str(m4); m5 = Mat(QQ(),3,3,v=[ [ 1, 0, 0 ], [ -125, 125, -125 ], [ 1, 0, 0 ] ]); puts "m5 = " + str(m5); m6 = m3 * m5; puts "m6 = " + str(m6); puts; puts "------- Mat(PolyRing(QQ(),\"x,y,z\",PolyRing.lex),3,3) ---------"; r = Mat(PolyRing.new(QQ(),"x,y,z",PolyRing.lex),3,3); puts "r = " + str(r); puts "r.factory() = " + str(r.factory()); #puts [ str(g) for g in r.gens() ]; for g in r.gens() print "g = ", str(g), "\n"; end puts; puts "------- PolyRing(Mat(QQ(),3,3),\"x,y,z\",PolyRing.lex) ---------"; r = PolyRing.new(Mat(QQ(),3,3),"x,y,z",PolyRing.lex); puts "r = " + str(r); for g in r.gens() print "g = ", str(g), "\n"; end puts; puts "------- SolvPolyRing(QQ(),\"x,y,z\") ---------"; r = PolyRing.new(QQ(),"x,y,z",PolyRing.lex); puts "r = " + str(r); pone,px,py,pz = r.gens(); puts "pone = " + str(pone); puts "px = " + str(px); puts "py = " + str(py); puts "pz = " + str(pz); rel = [ py, px, px * py - 1 , pz, py, py * pz - 1 ]; #puts "rel = " + str(rel); sr = SolvPolyRing.new(QQ(),"x,y,z",PolyRing.lex,rel); puts "sr = " + str(sr); one,x,y,z = sr.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); puts "one.factory() = " + str(one.factory()); s1 = QQ(1,2) + QQ(2,3) * x + QQ(2,5) * y + ( x + y + z )**2; puts "s1 = " + str(s1); s2 = QQ(1,2) + QQ(2,3) * x + QQ(2,5) * y + ( x + y + z )**2; puts "s2 = " + str(s2); s3 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + QQ(2,5) * y + QQ(2,3) * x + QQ(1,2); puts "s3 = " + str(s3); s4 = s1 - s3; puts "s4 = " + str(s4); puts "s4.factory() = " + str(s4.factory()); sr1 = SolvPolyRing.new(QQ(),"x, y, z",PolyRing.lex,[( z ), ( y ), ( y * z - 1 ), ( y ), ( x ), ( x * y - 1 )]); puts "sr1 = " + str(sr1); s5 = z * y; puts "s5 = " + str(s5); s6 = s5**3; puts "s6 = " + str(s6); s7 = ( z * y )**3; puts "s7 = " + str(s7); s8 = s7 - s6; puts "s8 = " + str(s8); s9 = y**3 * z**3 - 3 * y**2 * z**2 + 3 * y * z - 1; puts "s9 = " + str(s9); s10 = s9 - s7; puts "s10 = " + str(s10); puts; puts "------- SubModule(PolyRing(QQ(),\"u, v, l\",PolyRing.lex) ---------"; p = PolyRing.new(QQ(),"u, v, l",PolyRing.lex); puts "p = " + str(p); one,u,v,l = p.gens(); puts "one = " + str(one); puts "u = " + str(u); puts "v = " + str(v); puts "l = " + str(l); m = CommutativeModule.new("",ring=p,cols=4); puts "m = " + str(m); for g in m.gens() print "g = ", str(g), "\n"; end m1 = [ 0, 1, l + v, 0 ] m2 = [ 0, v, u * l**2, 0 ] m3 = [ 0, l + 3 * v, 0, u ] m4 = [ 0, v * l + v**2, u**2, 0 ] m5 = [ 0, l**2, u, 0 ] m6 = [ 1, 0, 0, l**2 ] m7 = [ 1, 0, l + 3 * v, 0 ] m8 = [ 1, 2, 0, l**2 ] m9 = [ u, 0, 0, v * l + v**2 ] m10 = [ l + v, 0, 0, u ] m11 = [ l**2, 0, 0, v ] m12 = [ l**2, 0, 2 * u,v ] ml = [m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12]; #ml= [ [ 0, 1, l + v, 0 ], [ 0, v, u * l**2, 0 ], [ 0, l + 3 * v, 0, u ], [ 0, v * l + v**2, u**2, 0 ], [ 0, l**2, u, 0 ], [ 1, 0, 0, l**2 ], [ 1, 0, l + 3 * v, 0 ], [ 1, 2, 0, l**2 ], [ u, 0, 0, v * l + v**2 ], [ l + v, 0, 0, u ], [ l**2, 0, 0, v ], [ l**2, 0, 2 * u,v ] ]; #puts "ml = " + str(ml); #puts; sm = m.submodul("",list=ml); #sm = SubModule(m,list=ml); puts "sm = " + str(sm); xm = SubModule.new(PolyRing.new(QQ(),"u, v, l",PolyRing.lex),"",list=[ [ 0, 1, ( l + v ), 0 ], [ 0, v, u * l**2, 0 ], [ 0, ( l + 3 * v ), 0, u ], [ 0, ( v * l + v**2 ), u**2, 0 ], [ 0, l**2, u, 0 ], [ 1, 0, 0, l**2 ], [ 1, 0, ( l + 3 * v ), 0 ], [ 1, 2, 0, l**2 ], [ u, 0, 0, ( v * l + v**2 ) ], [ ( l + v ), 0, 0, u ], [ l**2, 0, 0, v ], [ l**2, 0, 2 * u, v ] ]) # SubModule(PolyRing.new(QQ(),"u, v, l",PolyRing.lex),list=( ( 0, 1, ( l + v ), 0 ), ( 0, v, u * l**2, 0 ), ( 0, ( l + 3 * v ), 0, u ), ( 0, ( v * l + v**2 ), u**2, 0 ), ( 0, l**2, u, 0 ), ( 1, 0, 0, l**2 ), ( 1, 0, ( l + 3 * v ), 0 ), ( 1, 2, 0, l**2 ), ( u, 0, 0, ( v * l + v**2 ) ), ( ( l + v ), 0, 0, u ), ( l**2, 0, 0, v ), ( l**2, 0, 2 * u, v ) )) # SubModule(PolyRing.new(QQ(),"u, v, l",PolyRing.lex),list=( ( 0, (1,), l + v, 0 ), ( 0, v, u * l**2, 0 ), ( 0, l + (3,) * v, 0, u ), ( 0, v * l + v**2, u**2, 0 ), ( 0, l**2, u, 0 ), ( (1,), 0, 0, l**2 ), ( (1,), 0, l + (3,) * v, 0 ), ( (1,), (2,), 0, l**2 ), ( u, 0, 0, v * l + v**2 ), ( l + v, 0, 0, u ), ( l**2, 0, 0, v ), ( l**2, 0, (2,) * u, v ) )); # SubModule(PolyRing.new(QQ(),"u, v, l",PolyRing.lex),list=( ( 0, (1,), l + v, 0 ), ( 0, v, u * l**2, 0 ), ( 0, l + (3,) * v, 0, u ), ( 0, v * l + v**2, u**2, 0 ), ( 0, l**2, u, 0 ), ( (1,), 0, 0, l**2 ), ( (1,), 0, l + (3,) * v, 0 ), ( (1,), (2,), 0, l**2 ), ( u, 0, 0, v * l + v**2 ), ( l + v, 0, 0, u ), ( l**2, 0, 0, v ), ( l**2, 0, (2,) * u, v ) )); puts "xm = " + str(xm); puts; #rg = sm.GB(); #puts "rg:", rg; #puts "isGB:", rg.isGB(); #puts; puts "------- SolvableSubModule(SolvPolyRing(CC(),\"X,Y,x,y\")) ---------"; r = PolyRing.new(CC(),"X,Y,x,y",PolyRing.lex); puts "r = " + str(r); pone,pi,pX,pY,px,py = r.gens(); puts "pone = " + str(pone); puts "pi = " + str(pi); puts "pX = " + str(pX); puts "pY = " + str(pY); puts "px = " + str(px); puts "py = " + str(py); #rel = ( py, px, px * py - 1 , pz, py, py * pz - 1 ); rel = [ py, px, pi * px * py, pX, pY, pi * pY * pX ]; print "rel = ", rel.map { |z| z.to_s + ", " }, "\n"; #print "rel = ", rel.to_s, "\n"; sr = SolvPolyRing.new(CC(),"X,Y,x,y",PolyRing.lex,rel); puts "sr = " + str(sr); one,i,X,Y,x,y = sr.gens(); puts "one = " + str(one); puts "i = " + str(i); puts "X = " + str(X); puts "Y = " + str(Y); puts "x = " + str(x); puts "y = " + str(y); m1 = [ ( x + 1 ), ( y ) ] m2 = [ ( x * y ), ( 0 ) ] m3 = [ ( x - X ), ( x - X ) ] m4 = [ ( y - Y ), ( y - Y ) ] ml = [m1,m2,m3,m4]; #puts "ml = " + str(ml); ssm = SolvableSubModule.new( sr, "", list=ml ); puts "ssm: " + str(ssm); puts; xsm = SolvableSubModule.new(SolvPolyRing.new(CC(),"X, Y, x, y",PolyRing.lex,rel=[y, x, ( CC(0,1) * x * y ), Y, X, ( CC(0,1) * X * Y )]),"",list=[ [ x - X, x - X ], [ x + CC(1), y ], [ y - Y, y - Y ], [ x * y, 0 ] ]); # SolvableSubModule(SolvPolyRing.new(CC(),"X, Y, x, y",PolyRing.lex,rel=(y, x, ( ((0,),(1,)) * x * y ), Y, X, ( ((0,),(1,)) * X * Y )]),list=[ ( x - X, x - X ), ( x + ((1,),), y ), ( y - Y, y - Y ), ( x * y, 0 ) )); # SolvableSubModule(SolvPolyRing.new(CC(),"X, Y, x, y",PolyRing.lex,(( y ), ( x ), ( ((0,),(1,)) * x * y ),( Y ), ( X ), ( ((0,),(1,)) * X * Y ))),list=( ( x - X, x - X ), ( x + ((1,),), y ), ( y - Y, y - Y ), ( x * y, 0 ) )); puts "xsm: " + str(xsm); puts; ## mlg = ssm.leftGB(); ## puts "mlg:", mlg; ## puts; ## mtg = ssm.twosidedGB(); ## puts "mtg:", mtg; ## puts; puts "------------------------------------"; #puts "globals() = " + str(globals()); terminate(); #puts "globals() = " + str(globals()); #puts "locals() = " + str(locals()); #puts "vars() = " + str(vars()); terminate(); __END__ to_skip = < 0, inseparable cases cr = PolyRing.new(ZM(5),"c",PolyRing.lex); puts "coefficient Ring: " + str(cr); rf = RF(cr); puts "coefficient quotient Ring: " + str(rf.ring); r = PolyRing.new(rf,"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,c,x,y,z = r.gens(); puts one,c,x,y,z; #exit(); f1 = (x**2 - 2); #**2; f2 = (y**2 - c)**5; f3 = (z**2 - 2 * c); #**5; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); #puts "f4 = " + str(f4); puts; F = r.ideal( "", list=[f1,f2,f3] ); #F = r.ideal( "", list=[f1,f3] ); #F = r.ideal( "", list=[f2,f3] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); P = F.primeDecomp(); t = System.currentTimeMillis() - t; puts "P = " + str(P); puts; puts "decomp time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/hawes2modpars.py0000644000175000017500000000221711505167460017321 0ustar giovannigiovanni# # jython examples for jas. # $Id: hawes2modpars.py 3438 2010-12-24 19:06:24Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} import sys; from jas import Ring, PolyRing, ZM from jas import Ideal from jas import startLog from jas import terminate #startLog(); # Hawes & Gibson example 2 # rational function coefficients #r = Ring( "ModFunc 17 (a, c, b) (y2, y1, z1, z2, x) G" ); r = PolyRing( PolyRing(ZM(17),"a, c, b",PolyRing.lex), "y2, y1, z1, z2, x", PolyRing.grad ); print "Ring: " + str(r); print; ps = """ ( ( x + 2 y1 z1 + { 3 a } y1^2 + 5 y1^4 + { 2 c } y1 ), ( x + 2 y2 z2 + { 3 a } y2^2 + 5 y2^4 + { 2 c } y2 ), ( 2 z2 + { 6 a } y2 + 20 y2^3 + { 2 c } ), ( 3 z1^2 + y1^2 + { b } ), ( 3 z2^2 + y2^2 + { b } ) ) """; f = r.ideal( ps ); print "Ideal: " + str(f); print; rg = f.GB(); print "GB:", rg; print; bg = rg.isGB(); print "isGB:", bg; print; terminate(); #sys.exit(); jas-2.5/examples/jas.py0000644000175000017500000032441412136725524015327 0ustar giovannigiovanni'''jython interface to JAS. ''' # $Id: jas.py 4382 2013-04-27 10:41:24Z kredel $ from java.lang import System from java.io import StringReader from java.util import ArrayList, List, Collections from org.apache.log4j import BasicConfigurator; from edu.jas.structure import RingElem, RingFactory, Power from edu.jas.arith import BigInteger, BigRational, BigComplex, BigDecimal,\ ModInteger, ModIntegerRing, BigQuaternion, BigOctonion,\ Product, ProductRing, PrimeList from edu.jas.poly import GenPolynomial, GenPolynomialRing, Monomial,\ GenSolvablePolynomial, GenSolvablePolynomialRing,\ GenWordPolynomial, GenWordPolynomialRing,\ Word, WordFactory,\ GenPolynomialTokenizer, OrderedPolynomialList, PolyUtil,\ TermOrderOptimization, TermOrder, PolynomialList,\ AlgebraicNumber, AlgebraicNumberRing,\ OrderedModuleList, ModuleList,\ Complex, ComplexRing from edu.jas.ps import UnivPowerSeries, UnivPowerSeriesRing,\ UnivPowerSeriesMap, Coefficients, \ MultiVarPowerSeries, MultiVarPowerSeriesRing,\ MultiVarPowerSeriesMap, MultiVarCoefficients,\ StandardBaseSeq from edu.jas.gb import EReductionSeq, DGroebnerBaseSeq, EGroebnerBaseSeq,\ GroebnerBaseDistributedEC, GroebnerBaseDistributedHybridEC,\ GroebnerBaseSeq, GroebnerBaseSeqPairSeq,\ OrderedPairlist, OrderedSyzPairlist,\ ReductionSeq, GroebnerBaseParallel, GroebnerBaseSeqPairParallel,\ SolvableGroebnerBaseParallel, SolvableGroebnerBaseSeq,\ WordGroebnerBaseSeq from edu.jas.gbufd import GroebnerBasePseudoRecSeq, GroebnerBasePseudoSeq,\ GroebnerBasePseudoParallel,\ RGroebnerBasePseudoSeq, RGroebnerBaseSeq, RReductionSeq,\ CharacteristicSetWu from edu.jas.gbmod import ModGroebnerBaseAbstract, ModSolvableGroebnerBaseAbstract,\ SolvableSyzygyAbstract, SyzygyAbstract from edu.jas.vector import GenVector, GenVectorModul,\ GenMatrix, GenMatrixRing from edu.jas.application import PolyUtilApp, Residue, ResidueRing, Ideal, SolvableIdeal,\ Local, LocalRing, IdealWithRealAlgebraicRoots,\ ComprehensiveGroebnerBaseSeq, ExtensionFieldBuilder from edu.jas.kern import ComputerThreads, StringUtil, Scripting from edu.jas.ufd import GreatestCommonDivisor, PolyUfdUtil, GCDFactory,\ FactorFactory, SquarefreeFactory, Quotient, QuotientRing from edu.jas.root import RealRootsSturm, Interval, RealAlgebraicNumber, RealAlgebraicRing,\ ComplexRootsSturm, Rectangle, RootFactory from edu.jas.integrate import ElementaryIntegration from edu.jas.util import ExecutableServer from edu.jas import structure, arith, poly, ps, gb, gbmod, vector,\ application, util, ufd from edu import jas #PrettyPrint.setInternal(); from org.python.core import PyInstance, PyList, PyTuple,\ PyInteger, PyLong, PyFloat, PyString # set output to Python scripting Scripting.setLang(Scripting.Lang.Python); def startLog(): '''Configure the log4j system and start logging. ''' BasicConfigurator.configure(); def terminate(): '''Terminate the running thread pools. ''' ComputerThreads.terminate(); def noThreads(): '''Turn off automatic parallel threads usage. ''' print "nt = ", ComputerThreads.NO_THREADS; ComputerThreads.setNoThreads(); #NO_THREADS = #0; #1; #True; print "nt = ", ComputerThreads.NO_THREADS; auto_inject = True def inject_variable(name, value): '''Inject a variable into the main global namespace INPUT: - "name" - a string - "value" - anything Found in Sage. AUTHORS: - William Stein ''' assert type(name) is str import sys depth = 0 while True: G = sys._getframe(depth).f_globals #print "G = `%s` " % G; depth += 1 if depth > 100: print "depth limit %s reached " % depth; break if G is None: continue # orig: if G["__name__"] == "__main__" and G["__package__"] is None: try: if G["__name__"] is None: break except: #print "G[__name__] undefined"; break if G["__name__"] == "__main__": try: if G["__package__"] is None: break except: break if G is None: print "error at G no global environment found for `%s` = `%s` " % (name, value); return if name in G: print "redefining global variable `%s` from `%s` " % (name, G[name]); G[name] = value def inject_generators(gens): '''Inject generators as variables into the main global namespace INPUT: - "gens" - generators ''' for v in gens: #print "vars = " + str(v); if str(v) == "1": inject_variable("one",v) else: inject_variable(str(v),v) class Ring: '''Represents a JAS polynomial ring: GenPolynomialRing. Methods to create ideals and ideals with parametric coefficients. ''' def __init__(self,ringstr="",ring=None,fast=False): '''Ring constructor. ''' if ring == None: sr = StringReader( ringstr ); tok = GenPolynomialTokenizer(sr); self.pset = tok.nextPolynomialSet(); self.ring = self.pset.ring; else: self.ring = ring; if fast: return; self.engine = GCDFactory.getProxy(self.ring.coFac); try: self.sqf = SquarefreeFactory.getImplementation(self.ring.coFac); # print "sqf: ", self.sqf; # except Exception, e: # print "error " + str(e) except: pass try: self.factor = FactorFactory.getImplementation(self.ring.coFac); #print "factor: ", self.factor; except: pass # except Exception, e: # print "error " + str(e) #print "dict: " + str(self.__dict__) vns = "" for v in self.ring.generators(): #print "vars = " + str(v); vs = str(v); vr = RingElem(v); vs = vs.replace(" ",""); if vs == "1": vs='one'; if vs.find("(") >= 0: vs = vs.replace("(",""); vs = vs.replace(")",""); if vs.find("{") >= 0: vs = vs.replace("{",""); vs = vs.replace("}",""); try: if self.__dict__[vs] is None: self.__dict__[vs] = vr; else: print vs + " not redefined to " + str(v); except: self.__dict__[vs] = vr; if auto_inject: inject_variable(vs,vr) vns = vns + vs + " " if auto_inject: print "globally defined variables: " + vns #print "dict: " + str(self.__dict__) def __str__(self): '''Create a string representation. ''' return str(self.ring.toScript()); def ideal(self,ringstr="",list=None): '''Create an ideal. ''' return Ideal(self,ringstr,list=list); def paramideal(self,ringstr="",list=None,gbsys=None): '''Create an ideal in a polynomial ring with parameter coefficients. ''' return ParamIdeal(self,ringstr,list,gbsys); def gens(self): '''Get list of generators of the polynomial ring. ''' L = self.ring.generators(); N = [ RingElem(e) for e in L ]; return N; def inject_variables(self): '''Inject generators as variables into the main global namespace ''' inject_generators(self.gens()); def one(self): '''Get the one of the polynomial ring. ''' return RingElem( self.ring.getONE() ); def zero(self): '''Get the zero of the polynomial ring. ''' return RingElem( self.ring.getZERO() ); def random(self,k=5,l=7,d=3,q=0.3): '''Get a random polynomial. ''' r = self.ring.random(k,l,d,q); if self.ring.coFac.isField(): r = r.monic(); return RingElem( r ); def element(self,poly): '''Create an element from a string or object. ''' if not isinstance(poly,str): try: if self.ring == poly.ring: return RingElem(poly); except Exception, e: pass poly = str(poly); I = Ideal(self, "( " + poly + " )"); list = I.pset.list; if len(list) > 0: return RingElem( list[0] ); def gcd(self,a,b): '''Compute the greatest common divisor of a and b. ''' if isinstance(a,RingElem): a = a.elem; else: a = self.element( a ); a = a.elem; if isinstance(b,RingElem): b = b.elem; else: b = self.element( b ); b = b.elem; return RingElem( self.engine.gcd(a,b) ); def squarefreeFactors(self,a): '''Compute squarefree factors of polynomial. ''' if isinstance(a,RingElem): a = a.elem; else: a = self.element( a ); a = a.elem; cf = self.ring.coFac; if cf.getClass().getSimpleName() == "GenPolynomialRing": e = self.sqf.recursiveSquarefreeFactors( a ); else: e = self.sqf.squarefreeFactors( a ); L = {}; for a in e.keySet(): i = e.get(a); L[ RingElem( a ) ] = i; return L; def factors(self,a): '''Compute irreducible factorization for modular, integer, rational number and algebriac number coefficients. ''' if isinstance(a,RingElem): a = a.elem; else: a = self.element( a ); a = a.elem; try: cf = self.ring.coFac; if cf.getClass().getSimpleName() == "GenPolynomialRing": e = self.factor.recursiveFactors( a ); else: e = self.factor.factors( a ); L = {}; for a in e.keySet(): i = e.get(a); L[ RingElem( a ) ] = i; return L; except Exception, e: print "error " + str(e) return None def factorsAbsolute(self,a): '''Compute absolute irreducible factorization for (modular,) rational number coefficients. ''' if isinstance(a,RingElem): a = a.elem; else: a = self.element( a ); a = a.elem; try: L = self.factor.factorsAbsolute( a ); ## L = {}; ## for a in e.keySet(): ## i = e.get(a); ## L[ RingElem( a ) ] = i; return L; except Exception, e: print "error in factorsAbsolute " + str(e) return None def realRoots(self,a,eps=None): '''Compute real roots of univariate polynomial. ''' if isinstance(a,RingElem): a = a.elem; else: a = self.element( a ); a = a.elem; if isinstance(eps,RingElem): eps = eps.elem; try: if eps == None: #R = RealRootsSturm().realRoots( a ); R = RootFactory.realAlgebraicNumbers( a ); else: R = RootFactory.realAlgebraicNumbers( a, eps ); R = [ RingElem(r) for r in R ]; #R = [ RingElem(BigDecimal(r.getRational())) for r in R ]; return R; except Exception, e: print "error " + str(e) return None def complexRoots(self,a,eps=None): '''Compute complex roots of univariate polynomial. ''' if isinstance(a,RingElem): a = a.elem; else: a = self.element( a ); a = a.elem; if isinstance(eps,RingElem): eps = eps.elem; cmplx = False; try: x = a.ring.coFac.getONE().getRe(); cmplx = True; except Exception, e: pass; try: if eps == None: if cmplx: R = RootFactory.complexAlgebraicNumbersComplex(a); else: R = RootFactory.complexAlgebraicNumbers(a); # R = ComplexRootsSturm(a.ring.coFac).complexRoots( a ); # R = [ r.centerApprox() for r in R ]; # R = [ r.ring.getRoot() for r in R ]; R = [ RingElem(r) for r in R ]; else: if cmplx: R = RootFactory.complexAlgebraicNumbersComplex(a,eps); else: R = RootFactory.complexAlgebraicNumbers(a,eps); R = [ RingElem(r) for r in R ]; # R = [ r.decimalMagnitude() for r in R ]; # R = ComplexRootsSturm(a.ring.coFac).complexRoots( a, eps ); # R = ComplexRootsSturm(a.ring.coFac).approximateRoots( a, eps ); return R; except Exception, e: print "error " + str(e) return None def integrate(self,a): '''Integrate (univariate) rational function. ''' if isinstance(a,RingElem): a = a.elem; else: a = self.element( a ); a = a.elem; cf = self.ring; try: cf = cf.ring; except: pass; integrator = ElementaryIntegration(cf.coFac); ei = integrator.integrate(a); return ei; def powerseriesRing(self): '''Get a power series ring from this ring. ''' pr = MultiVarPowerSeriesRing(self.ring); return MultiSeriesRing(ring=pr); class Ideal: '''Represents a JAS polynomial ideal: PolynomialList and Ideal. Methods for Groebner bases, ideal sum, intersection and others. ''' def __init__(self,ring,polystr="",list=None): '''Ideal constructor. ''' self.ring = ring; if list == None: sr = StringReader( polystr ); tok = GenPolynomialTokenizer(ring.ring,sr); self.list = tok.nextPolynomialList(); else: self.list = pylist2arraylist(list,rec=1); self.pset = OrderedPolynomialList(ring.ring,self.list); self.roots = None; self.croots = None; self.prime = None; self.primary = None; def __str__(self): '''Create a string representation. ''' return str(self.pset.toScript()); def __eq__(self,other): '''Test if two ideals are equal. ''' o = other; if isinstance(other,Ideal): o = other.pset; return self.pset.equals(o) def paramideal(self): '''Create an ideal in a polynomial ring with parameter coefficients. ''' return ParamIdeal(self.ring,"",self.list); def GB(self): '''Compute a Groebner base. ''' s = self.pset; cofac = s.ring.coFac; F = s.list; t = System.currentTimeMillis(); if cofac.isField(): G = GroebnerBaseSeq(ReductionSeq(),OrderedSyzPairlist()).GB(F); #G = GroebnerBaseSeq().GB(F); else: v = None; try: v = cofac.vars; except: pass if v == None: G = GroebnerBasePseudoSeq(cofac).GB(F); else: G = GroebnerBasePseudoRecSeq(cofac).GB(F); t = System.currentTimeMillis() - t; print "sequential GB executed in %s ms" % t; return Ideal(self.ring,"",G); def isGB(self): '''Test if this is a Groebner base. ''' s = self.pset; cofac = s.ring.coFac; F = s.list; t = System.currentTimeMillis(); if cofac.isField(): b = GroebnerBaseSeq().isGB(F); else: v = None; try: v = cofac.vars; except: pass if v == None: b = GroebnerBasePseudoSeq(cofac).isGB(F); else: b = GroebnerBasePseudoRecSeq(cofac).isGB(F); t = System.currentTimeMillis() - t; #print "isGB executed in %s ms" % t; return b; def eGB(self): '''Compute an e-Groebner base. ''' s = self.pset; cofac = s.ring.coFac; F = s.list; t = System.currentTimeMillis(); G = EGroebnerBaseSeq().GB(F) t = System.currentTimeMillis() - t; print "sequential e-GB executed in %s ms" % t; return Ideal(self.ring,"",G); def iseGB(self): '''Test if this is an e-Groebner base. ''' s = self.pset; cofac = s.ring.coFac; F = s.list; t = System.currentTimeMillis(); b = EGroebnerBaseSeq().isGB(F) t = System.currentTimeMillis() - t; print "is e-GB test executed in %s ms" % t; return b; def dGB(self): '''Compute an d-Groebner base. ''' s = self.pset; cofac = s.ring.coFac; F = s.list; t = System.currentTimeMillis(); G = DGroebnerBaseSeq().GB(F) t = System.currentTimeMillis() - t; print "sequential d-GB executed in %s ms" % t; return Ideal(self.ring,"",G); def isdGB(self): '''Test if this is a d-Groebner base. ''' s = self.pset; cofac = s.ring.coFac; F = s.list; t = System.currentTimeMillis(); b = DGroebnerBaseSeq().isGB(F) t = System.currentTimeMillis() - t; print "is d-GB test executed in %s ms" % t; return b; def parNewGB(self,th): '''Compute in parallel a Groebner base. ''' s = self.pset; F = s.list; bbpar = GroebnerBaseSeqPairParallel(th); t = System.currentTimeMillis(); G = bbpar.GB(F); t = System.currentTimeMillis() - t; bbpar.terminate(); print "parallel-new %s executed in %s ms" % (th, t); return Ideal(self.ring,"",G); def parGB(self,th): '''Compute in parallel a Groebner base. ''' s = self.pset; F = s.list; cofac = s.ring.coFac; if cofac.isField(): bbpar = GroebnerBaseParallel(th); else: bbpar = GroebnerBasePseudoParallel(th,cofac); t = System.currentTimeMillis(); G = bbpar.GB(F); t = System.currentTimeMillis() - t; bbpar.terminate(); print "parallel %s executed in %s ms" % (th, t); return Ideal(self.ring,"",G); def distGB(self,th=2,machine="examples/machines.localhost",port=55711): '''Compute on a distributed system a Groebner base. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); #old: gbd = GBDist(th,machine,port); gbd = GroebnerBaseDistributedEC(machine,th,port); #gbd = GroebnerBaseDistributedHybridEC(machine,th,port); t1 = System.currentTimeMillis(); G = gbd.GB(F); t1 = System.currentTimeMillis() - t1; gbd.terminate(); t = System.currentTimeMillis() - t; print "distributed %s executed in %s ms (%s ms start-up)" % (th,t1,t-t1); return Ideal(self.ring,"",G); def distClient(self,port=4711): #8114 '''Client for a distributed computation. ''' e1 = ExecutableServer( port ); e1.init(); e2 = ExecutableServer( port+1 ); e2.init(); self.exers = [e1,e2]; return None; def distClientStop(self): '''Stop client for a distributed computation. ''' for es in self.exers: es.terminate(); return None; def eReduction(self,p): '''Compute a e-normal form of p with respect to this ideal. ''' s = self.pset; G = s.list; if isinstance(p,RingElem): p = p.elem; t = System.currentTimeMillis(); n = EReductionSeq().normalform(G,p); t = System.currentTimeMillis() - t; print "sequential eReduction executed in %s ms" % t; return RingElem(n); def reduction(self,p): '''Compute a normal form of p with respect to this ideal. ''' s = self.pset; G = s.list; if isinstance(p,RingElem): p = p.elem; t = System.currentTimeMillis(); n = ReductionSeq().normalform(G,p); t = System.currentTimeMillis() - t; print "sequential reduction executed in %s ms" % t; return RingElem(n); def NF(self,reducer): '''Compute a normal form of this ideal with respect to reducer. ''' s = self.pset; F = s.list; G = reducer.list; t = System.currentTimeMillis(); N = ReductionSeq().normalform(G,F); t = System.currentTimeMillis() - t; print "sequential NF executed in %s ms" % t; return Ideal(self.ring,"",N); def interreduced_basis(self): '''Compute a interreduced ideal basis of this. Compatibility method for Sage/Singular. ''' F = self.pset.list; N = ReductionSeq().irreducibleSet(F); #N = GroebnerBaseSeq().minimalGB(F); return [ RingElem(n) for n in N ]; def intersectRing(self,ring): '''Compute the intersection of this and the given polynomial ring. ''' s = jas.application.Ideal(self.pset); N = s.intersect(ring.ring); return Ideal(ring,"",N.getList()); def intersect(self,id2): '''Compute the intersection of this and the given ideal id2. ''' s1 = jas.application.Ideal(self.pset); s2 = jas.application.Ideal(id2.pset); N = s1.intersect(s2); return Ideal(self.ring,"",N.getList()); def eliminateRing(self,ring): '''Compute the elimination ideal of this and the given polynomial ring. ''' s = jas.application.Ideal(self.pset); N = s.eliminate(ring.ring); r = Ring( ring=N.getRing() ); return Ideal(r,"",N.getList()); def sat(self,id2): '''Compute the saturation of this with respect to given ideal id2. ''' s1 = jas.application.Ideal(self.pset); s2 = jas.application.Ideal(id2.pset); #Q = s1.infiniteQuotient(s2); Q = s1.infiniteQuotientRab(s2); return Ideal(self.ring,"",Q.getList()); def sum(self,other): '''Compute the sum of this and the ideal. ''' s = jas.application.Ideal(self.pset); t = jas.application.Ideal(other.pset); N = s.sum( t ); return Ideal(self.ring,"",N.getList()); def univariates(self): '''Compute the univariate polynomials in each variable of this ideal. ''' s = jas.application.Ideal(self.pset); L = s.constructUnivariate(); N = [ RingElem(e) for e in L ]; return N; def optimize(self): '''Optimize the term order on the variables. ''' p = self.pset; o = TermOrderOptimization.optimizeTermOrder(p); r = Ring("",o.ring); return Ideal(r,"",o.list); def realRoots(self): '''Compute real roots of 0-dim ideal. ''' I = jas.application.Ideal(self.pset); self.roots = jas.application.PolyUtilApp.realAlgebraicRoots(I); for R in self.roots: R.doDecimalApproximation(); return self.roots; def realRootsPrint(self): '''Print decimal approximation of real roots of 0-dim ideal. ''' if self.roots == None: I = jas.application.Ideal(self.pset); self.roots = jas.application.PolyUtilApp.realAlgebraicRoots(I); for R in self.roots: R.doDecimalApproximation(); for Ir in self.roots: for Dr in Ir.decimalApproximation(): print str(Dr); print; def radicalDecomp(self): '''Compute radical decomposition of this ideal. ''' I = jas.application.Ideal(self.pset); self.radical = I.radicalDecomposition(); return self.radical; def decomposition(self): '''Compute irreducible decomposition of this ideal. ''' I = jas.application.Ideal(self.pset); self.irrdec = I.decomposition(); return self.irrdec; def complexRoots(self): '''Compute complex roots of 0-dim ideal. ''' I = jas.application.Ideal(self.pset); self.croots = jas.application.PolyUtilApp.complexAlgebraicRoots(I); for R in self.croots: R.doDecimalApproximation(); return self.croots; def complexRootsPrint(self): '''Print decimal approximation of complex roots of 0-dim ideal. ''' if self.croots == None: I = jas.application.Ideal(self.pset); self.croots = jas.application.PolyUtilApp.realAlgebraicRoots(I); for R in self.croots: R.doDecimalApproximation(); for Ic in self.croots: for Dc in Ic.decimalApproximation(): print str(Dc); print; def primeDecomp(self): '''Compute prime decomposition of this ideal. ''' I = jas.application.Ideal(self.pset); self.prime = I.primeDecomposition(); return self.prime; def primaryDecomp(self): '''Compute primary decomposition of this ideal. ''' I = jas.application.Ideal(self.pset); ## if self.prime == None: ## self.prime = I.primeDecomposition(); self.primary = I.primaryDecomposition(); return self.primary; def toInteger(self): '''Convert rational coefficients to integer coefficients. ''' p = self.pset; l = p.list; r = p.ring; ri = GenPolynomialRing( BigInteger(), r.nvar, r.tord, r.vars ); pi = PolyUtil.integerFromRationalCoefficients(ri,l); r = Ring("",ri); return Ideal(r,"",pi); def toModular(self,mf): '''Convert integer coefficients to modular coefficients. ''' p = self.pset; l = p.list; r = p.ring; rm = GenPolynomialRing( mf, r.nvar, r.tord, r.vars ); pm = PolyUtil.fromIntegerCoefficients(rm,l); r = Ring("",rm); return Ideal(r,"",pm); def CS(self): '''Compute a Characteristic Set. ''' s = self.pset; cofac = s.ring.coFac; F = s.list; t = System.currentTimeMillis(); if cofac.isField(): G = CharacteristicSetWu().characteristicSet(F); else: print "CS not implemented for coefficients %s" % cofac.toScriptFactory(); G = None; t = System.currentTimeMillis() - t; print "sequential CS executed in %s ms" % t; return Ideal(self.ring,"",G); def isCS(self): '''Test for Characteristic Set. ''' s = self.pset; cofac = s.ring.coFac; F = s.list.clone(); Collections.reverse(F); # todo t = System.currentTimeMillis(); if cofac.isField(): b = CharacteristicSetWu().isCharacteristicSet(F); else: print "isCS not implemented for coefficients %s" % cofac.toScriptFactory(); b = False; t = System.currentTimeMillis() - t; return b; def csReduction(self,p): '''Compute a normal form of p with respect to this characteristic set. ''' s = self.pset; F = s.list.clone(); Collections.reverse(F); # todo if isinstance(p,RingElem): p = p.elem; t = System.currentTimeMillis(); n = CharacteristicSetWu().characteristicSetReduction(F,p); t = System.currentTimeMillis() - t; #print "sequential char set reduction executed in %s ms" % t; return RingElem(n); ## def syzygy(self): ## '''Syzygy of generating polynomials. ## ''' ## p = self.pset; ## l = p.list; ## s = SyzygyAbstract().zeroRelations( l ); ## m = Module("",p.ring); ## return SubModule(m,"",s); class ParamIdeal: '''Represents a JAS polynomial ideal with polynomial coefficients. Methods to compute comprehensive Groebner bases. ''' def __init__(self,ring,polystr="",list=None,gbsys=None): '''Parametric ideal constructor. ''' self.ring = ring; if list == None and polystr != None: sr = StringReader( polystr ); tok = GenPolynomialTokenizer(ring.ring,sr); self.list = tok.nextPolynomialList(); else: self.list = pylist2arraylist(list,rec=1); self.gbsys = gbsys; self.pset = OrderedPolynomialList(ring.ring,self.list); def __str__(self): '''Create a string representation. ''' if self.gbsys == None: return self.pset.toScript(); else: return self.gbsys.toString(); # toScript() not available # return self.pset.toScript() + "\n" + self.gbsys.toScript(); def optimizeCoeff(self): '''Optimize the term order on the variables of the coefficients. ''' p = self.pset; o = TermOrderOptimization.optimizeTermOrderOnCoefficients(p); r = Ring("",o.ring); return ParamIdeal(r,"",o.list); def optimizeCoeffQuot(self): '''Optimize the term order on the variables of the quotient coefficients. ''' p = self.pset; l = p.list; r = p.ring; q = r.coFac; c = q.ring; rc = GenPolynomialRing( c, r.nvar, r.tord, r.vars ); #print "rc = ", rc; lp = PolyUfdUtil.integralFromQuotientCoefficients(rc,l); #print "lp = ", lp; pp = PolynomialList(rc,lp); #print "pp = ", pp; oq = TermOrderOptimization.optimizeTermOrderOnCoefficients(pp); oor = oq.ring; qo = oor.coFac; cq = QuotientRing( qo ); rq = GenPolynomialRing( cq, r.nvar, r.tord, r.vars ); #print "rq = ", rq; o = PolyUfdUtil.quotientFromIntegralCoefficients(rq,oq.list); r = Ring("",rq); return ParamIdeal(r,"",o); def toIntegralCoeff(self): '''Convert rational function coefficients to integral function coefficients. ''' p = self.pset; l = p.list; r = p.ring; q = r.coFac; c = q.ring; rc = GenPolynomialRing( c, r.nvar, r.tord, r.vars ); #print "rc = ", rc; lp = PolyUfdUtil.integralFromQuotientCoefficients(rc,l); #print "lp = ", lp; r = Ring("",rc); return ParamIdeal(r,"",lp); def toModularCoeff(self,mf): '''Convert integral function coefficients to modular function coefficients. ''' p = self.pset; l = p.list; r = p.ring; c = r.coFac; #print "c = ", c; cm = GenPolynomialRing( mf, c.nvar, c.tord, c.vars ); #print "cm = ", cm; rm = GenPolynomialRing( cm, r.nvar, r.tord, r.vars ); #print "rm = ", rm; pm = PolyUfdUtil.fromIntegerCoefficients(rm,l); r = Ring("",rm); return ParamIdeal(r,"",pm); def toQuotientCoeff(self): '''Convert integral function coefficients to rational function coefficients. ''' p = self.pset; l = p.list; r = p.ring; c = r.coFac; #print "c = ", c; q = QuotientRing(c); #print "q = ", q; qm = GenPolynomialRing( q, r.nvar, r.tord, r.vars ); #print "qm = ", qm; pm = PolyUfdUtil.quotientFromIntegralCoefficients(qm,l); r = Ring("",qm); return ParamIdeal(r,"",pm); def GB(self): '''Compute a Groebner base. ''' I = Ideal(self.ring,"",self.pset.list); g = I.GB(); return ParamIdeal(g.ring,"",g.pset.list); def isGB(self): '''Test if this is a Groebner base. ''' I = Ideal(self.ring,"",self.pset.list); return I.isGB(); def CGB(self): '''Compute a comprehensive Groebner base. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); if self.gbsys == None: self.gbsys = ComprehensiveGroebnerBaseSeq(self.ring.ring.coFac).GBsys(F); G = self.gbsys.getCGB(); t = System.currentTimeMillis() - t; print "sequential comprehensive executed in %s ms" % t; return ParamIdeal(self.ring,"",G,self.gbsys); def CGBsystem(self): '''Compute a comprehensive Groebner system. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); S = ComprehensiveGroebnerBaseSeq(self.ring.ring.coFac).GBsys(F); t = System.currentTimeMillis() - t; print "sequential comprehensive system executed in %s ms" % t; return ParamIdeal(self.ring,None,F,S); def isCGB(self): '''Test if this is a comprehensive Groebner base. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); b = ComprehensiveGroebnerBaseSeq(self.ring.ring.coFac).isGB(F); t = System.currentTimeMillis() - t; print "isCGB executed in %s ms" % t; return b; def isCGBsystem(self): '''Test if this is a comprehensive Groebner system. ''' s = self.pset; S = self.gbsys; t = System.currentTimeMillis(); b = ComprehensiveGroebnerBaseSeq(self.ring.ring.coFac).isGBsys(S); t = System.currentTimeMillis() - t; print "isCGBsystem executed in %s ms" % t; return b; def regularRepresentation(self): '''Convert Groebner system to a representation with regular ring coefficents. ''' if self.gbsys == None: return None; G = PolyUtilApp.toProductRes(self.gbsys.list); ring = Ring(None,G[0].ring); return ParamIdeal(ring,None,G); def regularRepresentationBC(self): '''Convert Groebner system to a boolean closed representation with regular ring coefficents. ''' if self.gbsys == None: return None; G = PolyUtilApp.toProductRes(self.gbsys.list); ring = Ring(None,G[0].ring); res = RReductionSeq(); G = res.booleanClosure(G); return ParamIdeal(ring,None,G); def regularGB(self): '''Compute a Groebner base over a regular ring. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); G = RGroebnerBasePseudoSeq(self.ring.ring.coFac).GB(F); t = System.currentTimeMillis() - t; print "sequential regular GB executed in %s ms" % t; return ParamIdeal(self.ring,None,G); def isRegularGB(self): '''Test if this is Groebner base over a regular ring. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); b = RGroebnerBasePseudoSeq(self.ring.ring.coFac).isGB(F); t = System.currentTimeMillis() - t; print "isRegularGB executed in %s ms" % t; return b; def stringSlice(self): '''Get each component (slice) of regular ring coefficients separate. ''' s = self.pset; b = PolyUtilApp.productToString(s); return b; class SolvableRing(Ring): '''Represents a JAS solvable polynomial ring: GenSolvablePolynomialRing. Has a method to create solvable ideals. ''' def __init__(self,ringstr="",ring=None): '''Solvable polynomial ring constructor. ''' if ring == None: sr = StringReader( ringstr ); tok = GenPolynomialTokenizer(sr); self.pset = tok.nextSolvablePolynomialSet(); self.ring = self.pset.ring; else: self.ring = ring; if not self.ring.isAssociative(): print "warning: ring is not associative"; Ring.__init__(self,ring=self.ring) def __str__(self): '''Create a string representation. ''' return str(self.ring.toScript()); def ideal(self,ringstr="",list=None): '''Create a solvable ideal. ''' return SolvableIdeal(self,ringstr,list); def one(self): '''Get the one of the solvable polynomial ring. ''' return RingElem( self.ring.getONE() ); def zero(self): '''Get the zero of the solvable polynomial ring. ''' return RingElem( self.ring.getZERO() ); def element(self,poly): '''Create an element from a string or object. ''' if not isinstance(poly,str): try: if self.ring == poly.ring: return RingElem(poly); except Exception, e: pass poly = str(poly); I = SolvableIdeal(self, "( " + poly + " )"); list = I.pset.list; if len(list) > 0: return RingElem( list[0] ); class SolvableIdeal: '''Represents a JAS solvable polynomial ideal. Methods for left, right two-sided Groebner basees and others. ''' def __init__(self,ring,ringstr="",list=None): '''Constructor for an ideal in a solvable polynomial ring. ''' self.ring = ring; if list == None: sr = StringReader( ringstr ); tok = GenPolynomialTokenizer(ring.ring,sr); self.list = tok.nextSolvablePolynomialList(); else: self.list = pylist2arraylist(list,rec=1); self.pset = OrderedPolynomialList(ring.ring,self.list); def __str__(self): '''Create a string representation. ''' return str(self.pset.toScript()); def __cmp__(self,other): '''Compare two ideals. ''' t = False; if not isinstance(other,WordIdeal): return t; t = self.list.equals(other.list); return t; def leftGB(self): '''Compute a left Groebner base. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); G = SolvableGroebnerBaseSeq().leftGB(F); t = System.currentTimeMillis() - t; print "executed leftGB in %s ms" % t; return SolvableIdeal(self.ring,"",G); def isLeftGB(self): '''Test if this is a left Groebner base. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); b = SolvableGroebnerBaseSeq().isLeftGB(F); t = System.currentTimeMillis() - t; print "isLeftGB executed in %s ms" % t; return b; def twosidedGB(self): '''Compute a two-sided Groebner base. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); G = SolvableGroebnerBaseSeq().twosidedGB(F); t = System.currentTimeMillis() - t; print "executed twosidedGB in %s ms" % t; return SolvableIdeal(self.ring,"",G); def isTwosidedGB(self): '''Test if this is a two-sided Groebner base. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); b = SolvableGroebnerBaseSeq().isTwosidedGB(F); t = System.currentTimeMillis() - t; print "isTwosidedGB executed in %s ms" % t; return b; def rightGB(self): '''Compute a right Groebner base. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); G = SolvableGroebnerBaseSeq().rightGB(F); t = System.currentTimeMillis() - t; print "executed rightGB in %s ms" % t; return SolvableIdeal(self.ring,"",G); def isRightGB(self): '''Test if this is a right Groebner base. ''' s = self.pset; F = s.list; t = System.currentTimeMillis(); b = SolvableGroebnerBaseSeq().isRightGB(F); t = System.currentTimeMillis() - t; print "isRightGB executed in %s ms" % t; return b; def intersectRing(self,ring): '''Compute the intersection of this and the polynomial ring. ''' s = jas.application.SolvableIdeal(self.pset); N = s.intersect(ring.ring); return SolvableIdeal(self.ring,"",N.getList()); def intersect(self,other): '''Compute the intersection of this and the other ideal. ''' s = jas.application.SolvableIdeal(self.pset); t = jas.application.SolvableIdeal(other.pset); N = s.intersect( t ); return SolvableIdeal(self.ring,"",N.getList()); def sum(self,other): '''Compute the sum of this and the other ideal. ''' s = jas.application.SolvableIdeal(self.pset); t = jas.application.SolvableIdeal(other.pset); N = s.sum( t ); return SolvableIdeal(self.ring,"",N.getList()); def univariates(self): '''Compute the univariate polynomials in each variable of this twosided ideal. ''' s = jas.application.SolvableIdeal(self.pset); L = s.constructUnivariate(); N = [ RingElem(e) for e in L ]; return N; def parLeftGB(self,th): '''Compute a left Groebner base in parallel. ''' s = self.pset; F = s.list; bbpar = SolvableGroebnerBaseParallel(th); t = System.currentTimeMillis(); G = bbpar.leftGB(F); t = System.currentTimeMillis() - t; bbpar.terminate(); print "parallel %s leftGB executed in %s ms" % (th, t); return SolvableIdeal(self.ring,"",G); def parTwosidedGB(self,th): '''Compute a two-sided Groebner base in parallel. ''' s = self.pset; F = s.list; bbpar = SolvableGroebnerBaseParallel(th); t = System.currentTimeMillis(); G = bbpar.twosidedGB(F); t = System.currentTimeMillis() - t; bbpar.terminate(); print "parallel %s twosidedGB executed in %s ms" % (th, t); return SolvableIdeal(self.ring,"",G); class Module: '''Represents a JAS module over a polynomial ring. Method to create sub-modules. ''' def __init__(self,modstr="",ring=None,cols=0): '''Module constructor. ''' if ring == None: sr = StringReader( modstr ); tok = GenPolynomialTokenizer(sr); self.mset = tok.nextSubModuleSet(); if self.mset.cols >= 0: self.cols = self.mset.cols; else: self.cols = cols; else: self.mset = ModuleList(ring.ring,None); self.cols = cols; self.ring = self.mset.ring; def __str__(self): '''Create a string representation. ''' return str(self.mset.toScript()); def submodul(self,modstr="",list=None): '''Create a sub-module. ''' return SubModule(self,modstr,list); def element(self,poly): '''Create an element from a string or object. ''' if not isinstance(poly,str): try: if self.ring == poly.ring: return RingElem(poly); except Exception, e: pass poly = str(poly); I = SubModule(self, "( " + poly + " )"); list = I.mset.list; if len(list) > 0: return RingElem( list[0] ); def gens(self): '''Get the generators of this module. ''' gm = GenVectorModul(self.ring,self.cols); L = gm.generators(); #for g in L: # print "g = ", str(g); N = [ RingElem(e) for e in L ]; # want use val here, but can not return N; def inject_variables(self): '''Inject generators as variables into the main global namespace ''' inject_generators(self.gens()); class SubModule: '''Represents a JAS sub-module over a polynomial ring. Methods to compute Groebner bases. ''' def __init__(self,module,modstr="",list=None): '''Constructor for a sub-module. ''' self.module = module; if list == None: sr = StringReader( modstr ); tok = GenPolynomialTokenizer(module.ring,sr); self.list = tok.nextSubModuleList(); else: if isinstance(list,PyList) or isinstance(list,PyTuple): if len(list) != 0: if isinstance(list[0],RingElem): list = [ re.elem for re in list ]; self.list = pylist2arraylist(list,self.module.ring,rec=2); else: self.list = list; #print "list = ", str(list); #e = self.list[0]; #print "e = ", e; self.mset = OrderedModuleList(module.ring,self.list); self.cols = self.mset.cols; self.rows = self.mset.rows; #print "list = %s" % self.list; #print "cols = %s" % self.cols; #print "mset = %s" % self.mset.toString(); #print "mset = %s" % self.mset.toScript(); self.pset = self.mset.getPolynomialList(); def __str__(self): '''Create a string representation. ''' return str(self.mset.toScript()); # + "\n\n" + str(self.pset); def GB(self): '''Compute a Groebner base. ''' t = System.currentTimeMillis(); G = ModGroebnerBaseAbstract().GB(self.mset); t = System.currentTimeMillis() - t; print "executed module GB in %s ms" % t; return SubModule(self.module,"",G.list); def isGB(self): '''Test if this is a Groebner base. ''' t = System.currentTimeMillis(); b = ModGroebnerBaseAbstract().isGB(self.mset); t = System.currentTimeMillis() - t; print "module isGB executed in %s ms" % t; return b; ## def isSyzygy(self,g): ## '''Test if this is a syzygy of the polynomials in g. ## ''' ## l = self.list; ## print "l = %s" % l; ## print "g = %s" % g; ## t = System.currentTimeMillis(); ## z = SyzygyAbstract().isZeroRelation( l, g.list ); ## t = System.currentTimeMillis() - t; ## print "executed isSyzygy in %s ms" % t; ## return z; class SolvableModule(Module): '''Represents a JAS module over a solvable polynomial ring. Method to create solvable sub-modules. ''' def __init__(self,modstr="",ring=None,cols=0): '''Solvable module constructor. ''' if ring == None: sr = StringReader( modstr ); tok = GenPolynomialTokenizer(sr); self.mset = tok.nextSolvableSubModuleSet(); if self.mset.cols >= 0: self.cols = self.mset.cols; else: self.mset = ModuleList(ring.ring,None); self.cols = cols; self.ring = self.mset.ring; def __str__(self): '''Create a string representation. ''' return str(self.mset.toScript()); def submodul(self,modstr="",list=None): '''Create a solvable sub-module. ''' return SolvableSubModule(self,modstr,list); def element(self,poly): '''Create an element from a string or object. ''' if not isinstance(poly,str): try: if self.ring == poly.ring: return RingElem(poly); except Exception, e: pass poly = str(poly); I = SolvableSubModule(self, "( " + poly + " )"); list = I.mset.list; if len(list) > 0: return RingElem( list[0] ); class SolvableSubModule: '''Represents a JAS sub-module over a solvable polynomial ring. Methods to compute left, right and two-sided Groebner bases. ''' def __init__(self,module,modstr="",list=None): '''Constructor for sub-module over a solvable polynomial ring. ''' self.module = module; if list == None: sr = StringReader( modstr ); tok = GenPolynomialTokenizer(module.ring,sr); self.list = tok.nextSolvableSubModuleList(); else: if isinstance(list,PyList) or isinstance(list,PyTuple): self.list = pylist2arraylist(list,self.module.ring,rec=2); else: self.list = list; self.mset = OrderedModuleList(module.ring,self.list); self.cols = self.mset.cols; self.rows = self.mset.rows; def __str__(self): '''Create a string representation. ''' return str(self.mset.toScript()); # + "\n\n" + str(self.pset); def leftGB(self): '''Compute a left Groebner base. ''' t = System.currentTimeMillis(); G = ModSolvableGroebnerBaseAbstract().leftGB(self.mset); t = System.currentTimeMillis() - t; print "executed left module GB in %s ms" % t; return SolvableSubModule(self.module,"",G.list); def isLeftGB(self): '''Test if this is a left Groebner base. ''' t = System.currentTimeMillis(); b = ModSolvableGroebnerBaseAbstract().isLeftGB(self.mset); t = System.currentTimeMillis() - t; print "module isLeftGB executed in %s ms" % t; return b; def twosidedGB(self): '''Compute a two-sided Groebner base. ''' t = System.currentTimeMillis(); G = ModSolvableGroebnerBaseAbstract().twosidedGB(self.mset); t = System.currentTimeMillis() - t; print "executed in %s ms" % t; return SolvableSubModule(self.module,"",G.list); def isTwosidedGB(self): '''Test if this is a two-sided Groebner base. ''' t = System.currentTimeMillis(); b = ModSolvableGroebnerBaseAbstract().isTwosidedGB(self.mset); t = System.currentTimeMillis() - t; print "module isTwosidedGB executed in %s ms" % t; return b; def rightGB(self): '''Compute a right Groebner base. ''' t = System.currentTimeMillis(); G = ModSolvableGroebnerBaseAbstract().rightGB(self.mset); t = System.currentTimeMillis() - t; print "executed module rightGB in %s ms" % t; return SolvableSubModule(self.module,"",G.list); def isRightGB(self): '''Test if this is a right Groebner base. ''' t = System.currentTimeMillis(); b = ModSolvableGroebnerBaseAbstract().isRightGB(self.mset); t = System.currentTimeMillis() - t; print "module isRightGB executed in %s ms" % t; return b; class SeriesRing: '''Represents a JAS power series ring: UnivPowerSeriesRing. Methods for univariate power series arithmetic. ''' def __init__(self,ringstr="",truncate=None,ring=None,cofac=None,name="z"): '''Ring constructor. ''' if ring == None: if len(ringstr) > 0: sr = StringReader( ringstr ); tok = GenPolynomialTokenizer(sr); pset = tok.nextPolynomialSet(); ring = pset.ring; vname = ring.vars; name = vname[0]; cofac = ring.coFac; if isinstance(cofac,RingElem): cofac = cofac.elem; if truncate == None: self.ring = UnivPowerSeriesRing(cofac,name); else: self.ring = UnivPowerSeriesRing(cofac,truncate,name); else: self.ring = ring; def __str__(self): '''Create a string representation. ''' return str(self.ring.toScript()); def gens(self): '''Get the generators of the power series ring. ''' L = self.ring.generators(); N = [ RingElem(e) for e in L ]; return N; def inject_variables(self): '''Inject generators as variables into the main global namespace ''' inject_generators(self.gens()); def one(self): '''Get the one of the power series ring. ''' return RingElem( self.ring.getONE() ); def zero(self): '''Get the zero of the power series ring. ''' return RingElem( self.ring.getZERO() ); def random(self,n): '''Get a random power series. ''' return RingElem( self.ring.random(n) ); def exp(self): '''Get the exponential power series. ''' return RingElem( self.ring.getEXP() ); def sin(self): '''Get the sinus power series. ''' return RingElem( self.ring.getSIN() ); def cos(self): '''Get the cosinus power series. ''' return RingElem( self.ring.getCOS() ); def tan(self): '''Get the tangens power series. ''' return RingElem( self.ring.getTAN() ); def create(self,ifunc=None,jfunc=None,clazz=None): '''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. ''' class coeff( Coefficients ): def __init__(self,cofac): self.coFac = cofac; def generate(self,i): if jfunc == None: return self.coFac.fromInteger( ifunc(i) ); else: return jfunc(i); if clazz == None: ps = UnivPowerSeries( self.ring, coeff(self.ring.coFac) ); else: ps = UnivPowerSeries( self.ring, clazz ); return RingElem( ps ); def fixPoint(self,psmap): '''Create a power series as fixed point of the given mapping. psmap must implement the UnivPowerSeriesMap interface. ''' ps = self.ring.fixPoint( psmap ); return RingElem( ps ); def gcd(self,a,b): '''Compute the greatest common divisor of a and b. ''' if isinstance(a,RingElem): a = a.elem; if isinstance(b,RingElem): b = b.elem; return RingElem( a.gcd(b) ); def fromPoly(self,a): '''Convert a GenPolynomial to a power series. ''' if isinstance(a,RingElem): a = a.elem; return RingElem( self.ring.fromPolynomial(a) ); class MultiSeriesRing: '''Represents a JAS power series ring: MultiVarPowerSeriesRing. Methods for multivariate power series arithmetic. ''' def __init__(self,ringstr="",truncate=None,ring=None,cofac=None,names=None): '''Ring constructor. ''' if ring == None: if len(ringstr) > 0: sr = StringReader( ringstr ); tok = GenPolynomialTokenizer(sr); pset = tok.nextPolynomialSet(); ring = pset.ring; names = ring.vars; cofac = ring.coFac; if isinstance(cofac,RingElem): cofac = cofac.elem; if truncate == None: self.ring = MultiVarPowerSeriesRing(cofac,names); else: self.ring = MultiVarPowerSeriesRing(cofac,len(names),truncate,names); else: self.ring = ring; def __str__(self): '''Create a string representation. ''' return str(self.ring.toScript()); def gens(self): '''Get the generators of the power series ring. ''' L = self.ring.generators(); N = [ RingElem(e) for e in L ]; return N; def inject_variables(self): '''Inject generators as variables into the main global namespace ''' inject_generators(self.gens()); def one(self): '''Get the one of the power series ring. ''' return RingElem( self.ring.getONE() ); def zero(self): '''Get the zero of the power series ring. ''' return RingElem( self.ring.getZERO() ); def random(self,n): '''Get a random power series. ''' return RingElem( self.ring.random(n) ); def exp(self,r): '''Get the exponential power series, var r. ''' return RingElem( self.ring.getEXP(r) ); def sin(self,r): '''Get the sinus power series, var r. ''' return RingElem( self.ring.getSIN(r) ); def cos(self,r): '''Get the cosinus power series, var r. ''' return RingElem( self.ring.getCOS(r) ); def tan(self,r): '''Get the tangens power series, var r. ''' return RingElem( self.ring.getTAN(r) ); def create(self,ifunc=None,jfunc=None,clazz=None): '''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. ''' class coeff( MultiVarCoefficients ): def __init__(self,r): MultiVarCoefficients.__init__(self,r); self.coFac = r.coFac; def generate(self,i): if jfunc == None: return self.coFac.fromInteger( ifunc(i) ); else: return jfunc(i); #print "ifunc" if clazz == None: ps = MultiVarPowerSeries( self.ring, coeff(self.ring) ); else: ps = MultiVarPowerSeries( self.ring, clazz ); #print "ps ", ps.toScript(); return RingElem( ps ); def fixPoint(self,psmap): '''Create a power series as fixed point of the given mapping. psmap must implement the UnivPowerSeriesMap interface. ''' ps = self.ring.fixPoint( psmap ); return RingElem( ps ); def gcd(self,a,b): '''Compute the greatest common divisor of a and b. ''' if isinstance(a,RingElem): a = a.elem; if isinstance(b,RingElem): b = b.elem; return RingElem( a.gcd(b) ); def fromPoly(self,a): '''Convert a GenPolynomial to a power series. ''' if isinstance(a,RingElem): a = a.elem; return RingElem( self.ring.fromPolynomial(a) ); class PSIdeal: '''Represents a JAS power series ideal. Method for Standard bases. ''' def __init__(self,ring,polylist,ideal=None,list=None): '''PSIdeal constructor. ''' if isinstance(ring,Ring) or isinstance(ring,PolyRing): ring = MultiVarPowerSeriesRing(ring.ring); if isinstance(ring,MultiSeriesRing): ring = ring.ring; self.ring = ring; #print "ring = ", ring.toScript(); if ideal != None: polylist = ideal.pset.list; if list == None: self.polylist = pylist2arraylist( [ a.elem for a in polylist ] ); #print "polylist = ", self.polylist; self.list = self.ring.fromPolynomial(self.polylist); else: self.polylist = None; self.list = pylist2arraylist( [ a.elem for a in list ] ); def __str__(self): '''Create a string representation. ''' ll = [ e.toScript() for e in self.list ] return "( " + ", ".join(ll) + " )"; def STD(self,trunc=None): '''Compute a standard base. ''' pr = self.ring; if trunc != None: pr.setTruncate(trunc); #print "pr = ", pr.toScript(); F = self.list; #print "F = ", F; tm = StandardBaseSeq(); t = System.currentTimeMillis(); S = tm.STD(F); t = System.currentTimeMillis() - t; print "sequential standard base executed in %s ms" % t; #Sp = [ RingElem(a.asPolynomial()) for a in S ]; Sp = [ RingElem(a) for a in S ]; #return Sp; return PSIdeal(self.ring,None,list=Sp); def pylist2arraylist(list,fac=None,rec=1): '''Convert a Python list to a Java ArrayList. If list is a Python list, it is converted, else list is left unchanged. ''' #print "list type(%s) = %s" % (list,type(list)); if isinstance(list,PyList) or isinstance(list,PyTuple): L = ArrayList(); for e in list: t = True; if isinstance(e,RingElem): t = False; e = e.elem; if isinstance(e,PyList) or isinstance(e,PyTuple): if rec <= 1: e = makeJasArith(e); else: t = False; e = pylist2arraylist(e,fac,rec-1); try: n = e.getClass().getSimpleName(); if n == "ArrayList": t = False; except: pass; if t and fac != None: #print "e.p(%s) = %s" % (e,e.getClass().getName()); e = fac.parse( str(e) ); #or makeJasArith(e) ? L.add(e); list = L; #print "list type(%s) = %s" % (list,type(list)); return list def arraylist2pylist(list,rec=1): '''Convert a Java ArrayList to a Python list. If list is a Java ArrayList list, it is converted, else list is left unchanged. ''' #print "list type(%s) = %s" % (list,type(list)); if isinstance(list,List): L = []; for e in list: if not isinstance(e,RingElem): e = RingElem(e); L.append(e); list = L; #print "list type(%s) = %s" % (list,type(list)); return list def makeJasArith(item): '''Construct a jas.arith object. If item is a python tuple or list then a BigRational, BigComplex is constructed. If item is a python float then a BigDecimal is constructed. ''' #print "item type(%s) = %s" % (item,type(item)); if isinstance(item,PyInteger) or isinstance(item,PyLong): return BigInteger( item ); if isinstance(item,PyFloat): # ?? what to do ?? return BigDecimal( str(item) ); if isinstance(item,PyTuple) or isinstance(item,PyList): if len(item) > 2: print "len(item) > 2, remaining items ignored"; #print "item[0] type(%s) = %s" % (item[0],type(item[0])); isc = isinstance(item[0],PyTuple) or isinstance(item[0],PyList) if len(item) > 1: isc = isc or isinstance(item[1],PyTuple) or isinstance(item[1],PyList); if isc: if len(item) > 1: re = makeJasArith( item[0] ); if not re.isField(): re = BigRational( re.val ); im = makeJasArith( item[1] ); if not im.isField(): im = BigRational( im.val ); jasArith = BigComplex( re, im ); else: re = makeJasArith( item[0] ); jasArith = BigComplex( re ); else: if len(item) > 1: jasArith = BigRational( item[0] ).divide( BigRational( item[1] ) ); else: jasArith = BigRational( item[0] ); return jasArith; print "makeJasArith: unknown item type(%s) = %s" % (item,type(item)); return item; def ZZ(z=0): '''Create JAS BigInteger as ring element. ''' if isinstance(z,RingElem): z = z.elem; r = BigInteger(z); return RingElem(r); def ZM(m,z=0,field=False): '''Create JAS ModInteger as ring element. ''' if isinstance(m,RingElem): m = m.elem; if isinstance(z,RingElem): z = z.elem; # if z != 0 and ( z == False ): # never true # field = z; # z = 0; if field: mf = ModIntegerRing(m,field); else: mf = ModIntegerRing(m); r = ModInteger(mf,z); return RingElem(r); def GF(m,z=0): '''Create JAS ModInteger as field element. ''' #print "m = %s" % m return ZM(m,z,True); def QQ(d=0,n=1): '''Create JAS BigRational as ring element. ''' if isinstance(d,PyTuple) or isinstance(d,PyList): if n != 1: print "%s ignored" % n; if len(d) > 1: n = d[1]; d = d[0]; if isinstance(d,RingElem): d = d.elem; if isinstance(n,RingElem): n = n.elem; if n == 1: if d == 0: r = BigRational(); else: r = BigRational(d); else: d = BigRational(d); n = BigRational(n); r = d.divide(n); # BigRational(d,n); only for short integers return RingElem(r); def CC(re=BigRational(),im=BigRational()): '''Create JAS BigComplex as ring element. ''' if re == 0: re = BigRational(); if im == 0: im = BigRational(); if isinstance(re,PyTuple) or isinstance(re,PyList): if isinstance(re[0],PyTuple) or isinstance(re[0],PyList): if len(re) > 1: im = QQ( re[1] ); re = QQ( re[0] ); else: re = QQ(re); # re = makeJasArith( re ); if isinstance(im,PyTuple) or isinstance(im,PyList): im = QQ( im ); # im = makeJasArith( im ); if isinstance(re,RingElem): re = re.elem; if isinstance(im,RingElem): im = im.elem; if im.isZERO(): if re.isZERO(): c = BigComplex(); else: c = BigComplex(re); else: c = BigComplex(re,im); return RingElem(c); def CR(re=BigRational(),im=BigRational(),ring=None): '''Create JAS generic Complex as ring element. ''' if re == 0: re = BigRational(); if im == 0: im = BigRational(); if isinstance(re,PyTuple) or isinstance(re,PyList): if isinstance(re[0],PyTuple) or isinstance(re[0],PyList): if len(re) > 1: im = QQ( re[1] ); re = QQ( re[0] ); else: re = QQ(re); # re = makeJasArith( re ); if isinstance(im,PyTuple) or isinstance(im,PyList): im = QQ( im ); # im = makeJasArith( im ); if isinstance(re,RingElem): re = re.elem; if isinstance(im,RingElem): im = im.elem; if ring == None: ring = re.factory(); r = ComplexRing(ring); #print "d type(%s) = %s" % (r,type(r)); if im.isZERO(): if re.isZERO(): c = Complex(r); else: c = Complex(r,re); else: c = Complex(r,re,im); #print "d type(%s) = %s" % (c,type(c)); return RingElem(c); def DD(d=0): '''Create JAS BigDecimal as ring element. ''' if isinstance(d,RingElem): d = d.elem; if isinstance(d,PyFloat): d = str(d); #print "d type(%s) = %s" % (d,type(d)); if d == 0: r = BigDecimal(); else: r = BigDecimal(d); return RingElem(r); def Quat(re=BigRational(),im=BigRational(),jm=BigRational(),km=BigRational()): '''Create JAS BigQuaternion as ring element. ''' if re == 0: re = BigRational(); if im == 0: im = BigRational(); if jm == 0: jm = BigRational(); if km == 0: km = BigRational(); if isinstance(re,PyTuple) or isinstance(re,PyList): if isinstance(re[0],PyTuple) or isinstance(re[0],PyList): if len(re) > 1: im = QQ( re[1] ); re = QQ( re[0] ); else: re = QQ(re); # re = makeJasArith( re ); if isinstance(im,PyTuple) or isinstance(im,PyList): im = QQ( im ); if isinstance(jm,PyTuple) or isinstance(jm,PyList): jm = QQ( jm ); if isinstance(km,PyTuple) or isinstance(km,PyList): kim = QQ( km ); # im = makeJasArith( im ); if isinstance(re,RingElem): re = re.elem; if isinstance(im,RingElem): im = im.elem; if isinstance(jm,RingElem): jm = jm.elem; if isinstance(km,RingElem): km = km.elem; c = BigQuaternion(re,im,jm,km); return RingElem(c); def Oct(ro=BigQuaternion(),io=BigQuaternion()): '''Create JAS BigOctonion as ring element. ''' if ro == 0: ro = BigQuaternion(); if io == 0: io = BigQuaternion(); if isinstance(ro,PyTuple) or isinstance(ro,PyList): if isinstance(ro[0],PyTuple) or isinstance(ro[0],PyList): if len(ro) > 1: io = QQ( ro[1] ); ro = QQ( ro[0] ); else: ro = QQ(ro); # re = makeJasArith( re ); if isinstance(io,PyTuple) or isinstance(io,PyList): io = QQ( io ); # im = makeJasArith( im ); if isinstance(ro,RingElem): ro = ro.elem; if isinstance(io,RingElem): io = io.elem; c = BigOctonion(ro,io); return RingElem(c); def AN(m,z=0,field=False,pr=None): '''Create JAS AlgebraicNumber as ring element. ''' if isinstance(m,RingElem): m = m.elem; if isinstance(z,RingElem): z = z.elem; # if z != 0 and ( z == True or z == False ): # not working # field = z; # z = 0; #print "m.getClass() = " + str(m.getClass().getName()); #print "field = " + str(field); if m.getClass().getSimpleName() == "AlgebraicNumber": mf = AlgebraicNumberRing(m.factory().modul,m.factory().isField()); else: if field: mf = AlgebraicNumberRing(m,field); else: mf = AlgebraicNumberRing(m); #print "mf = " + mf.toString(); if z == 0: r = AlgebraicNumber(mf); else: r = AlgebraicNumber(mf,z); return RingElem(r); def RealN(m,i,r=0): '''Create JAS RealAlgebraicNumber as ring element. ''' if isinstance(m,RingElem): m = m.elem; if isinstance(r,RingElem): r = r.elem; if isinstance(i,PyTuple) or isinstance(i,PyList): il = BigRational(i[0]); ir = BigRational(i[1]); i = Interval(il,ir); #print "m.getClass() = " + str(m.getClass().getName()); if m.getClass().getSimpleName() == "RealAlgebraicNumber": mf = RealAlgebraicRing(m.factory().algebraic.modul,i); else: mf = RealAlgebraicRing(m,i); if r == 0: rr = RealAlgebraicNumber(mf); else: rr = RealAlgebraicNumber(mf,r); return RingElem(rr); def RF(pr,d=0,n=1): '''Create JAS rational function Quotient as ring element. ''' if isinstance(d,PyTuple) or isinstance(d,PyList): if n != 1: print "%s ignored" % n; if len(d) > 1: n = d[1]; d = d[0]; if isinstance(d,RingElem): d = d.elem; if isinstance(n,RingElem): n = n.elem; if isinstance(pr,RingElem): pr = pr.elem; if isinstance(pr,Ring): pr = pr.ring; qr = QuotientRing(pr); if d == 0: r = Quotient(qr); else: if n == 1: r = Quotient(qr,d); else: r = Quotient(qr,d,n); return RingElem(r); def RC(ideal,r=0): '''Create JAS polynomial Residue as ring element. ''' if ideal == None: raise ValueError, "No ideal given." if isinstance(ideal,Ideal): ideal = jas.application.Ideal(ideal.pset); #ideal.doGB(); #print "ideal.getList().get(0).ring.ideal = %s" % ideal.getList().get(0).ring.ideal; if ideal.getList().get(0).ring.getClass().getSimpleName() == "ResidueRing": rc = ResidueRing( ideal.getList().get(0).ring.ideal ); else: rc = ResidueRing(ideal); if isinstance(r,RingElem): r = r.elem; if r == 0: r = Residue(rc); else: r = Residue(rc,r); return RingElem(r); def LC(ideal,d=0,n=1): '''Create JAS polynomial Local as ring element. ''' if ideal == None: raise ValueError, "No ideal given." if isinstance(ideal,Ideal): ideal = jas.application.Ideal(ideal.pset); #ideal.doGB(); #print "ideal.getList().get(0).ring.ideal = %s" % ideal.getList().get(0).ring.ideal; if ideal.getList().get(0).ring.getClass().getSimpleName() == "LocalRing": lc = LocalRing( ideal.getList().get(0).ring.ideal ); else: lc = LocalRing(ideal); if isinstance(d,PyTuple) or isinstance(d,PyList): if n != 1: print "%s ignored" % n; if len(d) > 1: n = d[1]; d = d[0]; if isinstance(d,RingElem): d = d.elem; if isinstance(n,RingElem): n = n.elem; if d == 0: r = Local(lc); else: if n == 1: r = Local(lc,d); else: r = Local(lc,d,n); return RingElem(r); def RR(flist,n=1,r=0): '''Create JAS regular ring Product as ring element. ''' if not isinstance(n,PyInteger): r = n; n = 1; if flist == None: raise ValueError, "No list given." if isinstance(flist,PyList) or isinstance(flist,PyTuple): flist = pylist2arraylist( [ x.factory() for x in flist ], rec=1); ncop = 0; else: ncop = n; if isinstance(flist,RingElem): flist = flist.elem; flist = flist.factory(); ncop = n; #print "flist = " + str(flist); #print "ncop = " + str(ncop); if ncop == 0: pr = ProductRing(flist); else: pr = ProductRing(flist,ncop); #print "r type(%s) = %s" % (r,type(r)); if isinstance(r,RingElem): r = r.elem; try: #print "r.class() = %s" % r.getClass().getSimpleName(); if r.getClass().getSimpleName() == "Product": #print "r.val = %s" % r.val; r = r.val; except: pass; #print "r = " + str(r); if r == 0: r = Product(pr); else: r = Product(pr,r); return RingElem(r); def PS(cofac,name,f=None,truncate=None): '''Create JAS UnivPowerSeries as ring element. ''' cf = cofac; if isinstance(cofac,RingElem): cf = cofac.elem.factory(); if isinstance(cofac,Ring): cf = cofac.ring; if isinstance(truncate,RingElem): truncate = truncate.elem; if truncate == None: ps = UnivPowerSeriesRing(cf,name); else: ps = UnivPowerSeriesRing(cf,truncate,name); if f == None: r = ps.getZERO(); else: class Coeff( Coefficients ): def __init__(self,cofac): self.coFac = cofac; def generate(self,i): a = f(i); if isinstance(a,RingElem): a = a.elem; #print "a = " + str(a); return a; r = UnivPowerSeries(ps,Coeff(cf)); return RingElem(r); def MPS(cofac,names,f=None,truncate=None): '''Create JAS MultiVarPowerSeries as ring element. ''' cf = cofac; if isinstance(cofac,RingElem): cf = cofac.elem.factory(); if isinstance(cofac,Ring): cf = cofac.ring; vars = names; if isinstance(vars,PyString): vars = GenPolynomialTokenizer.variableList(vars); nv = len(vars); if isinstance(truncate,RingElem): truncate = truncate.elem; if truncate == None: ps = MultiVarPowerSeriesRing(cf,nv,vars); else: ps = MultiVarPowerSeriesRing(cf,nv,vars,truncate); if f == None: r = ps.getZERO(); else: class MCoeff( MultiVarCoefficients ): def __init__(self,r): MultiVarCoefficients.__init__(self,r); self.coFac = r.coFac; def generate(self,i): a = f(i); if isinstance(a,RingElem): a = a.elem; return a; r = MultiVarPowerSeries(ps,MCoeff(ps)); #print "r = " + str(r); return RingElem(r); def Vec(cofac,n,v=None): '''Create JAS GenVector ring element. ''' cf = cofac; if isinstance(cofac,RingElem): cf = cofac.elem.factory(); if isinstance(cofac,Ring): cf = cofac.ring; if isinstance(n,RingElem): n = n.elem; if isinstance(v,RingElem): v = v.elem; vr = GenVectorModul(cf,n); if v == None: r = GenVector(vr); else: r = GenVector(vr,v); return RingElem(r); def Mat(cofac,n,m,v=None): '''Create JAS GenMatrix ring element. ''' cf = cofac; if isinstance(cofac,RingElem): cf = cofac.elem.factory(); if isinstance(cofac,Ring): cf = cofac.ring; if isinstance(n,RingElem): n = n.elem; if isinstance(m,RingElem): m = m.elem; if isinstance(v,RingElem): v = v.elem; #print "cf type(%s) = %s" % (cf,type(cf)); mr = GenMatrixRing(cf,n,m); if v == None: r = GenMatrix(mr); else: r = GenMatrix(mr,v); return RingElem(r); def coercePair(a,b): '''Coerce type a to type b or type b to type a. ''' #print "a type(%s) = %s" % (a,type(a)); #print "b type(%s) = %s" % (b,type(b)); try: if not a.isPolynomial() and b.isPolynomial(): s = b.coerce(a); o = b; else: s = a; o = a.coerce(b); except: s = a; o = a.coerce(b); return (s,o); def isJavaInstance(a): '''Test if a is a Java instance. ''' #print "a type(%s) = %s" % (a,type(a)); try: c = a.getClass(); except: return False; return True; class RingElem: '''Proxy for JAS ring elements. Methods to be used as + - * ** / %. ''' def __init__(self,elem): '''Constructor for ring element. ''' if isinstance(elem,RingElem): self.elem = elem.elem; else: self.elem = elem; try: self.ring = self.elem.factory(); except: self.ring = self.elem; def __str__(self): '''Create a string representation. ''' return str(self.elem.toScript()); def zero(self): '''Zero element of this ring. ''' return RingElem( self.ring.getZERO() ); def isZERO(self): '''Test if this is the zero element of the ring. ''' return self.elem.isZERO(); def one(self): '''One element of this ring. ''' return RingElem( self.ring.getONE() ); def isONE(self): '''Test if this is the one element of the ring. ''' return self.elem.isONE(); def signum(self): '''Get the sign of this element. ''' return self.elem.signum(); def __abs__(self): '''Absolute value. ''' return RingElem( self.elem.abs() ); def __neg__(self): '''Negative value. ''' return RingElem( self.elem.negate() ); def __pos__(self): '''Positive value. ''' return self; def coerce(self,other): '''Coerce other to self. ''' #print "self type(%s) = %s" % (self,type(self)); #print "other type(%s) = %s" % (other,type(other)); #print "self.elem class(%s) = %s" % (self.elem,self.elem.getClass()); if self.elem.getClass().getSimpleName() == "GenVector": #print "self, other = %s, %s " % (self,other); if isinstance(other,PyTuple) or isinstance(other,PyList): o = pylist2arraylist(other,self.elem.factory().coFac,rec=1); o = GenVector(self.elem.factory(),o); return RingElem( o ); if self.elem.getClass().getSimpleName() == "GenMatrix": #print "self, other = %s, %s " % (type(self),type(other)); #print "o type(%s) = %s, str = %s" % (o,type(o),str(o)); if isinstance(other,PyTuple) or isinstance(other,PyList): o = pylist2arraylist(other,self.elem.factory().coFac,rec=2); o = GenMatrix(self.elem.factory(),o); return RingElem( o ); if self.elem.getClass().getSimpleName() == "GenPolynomial": #print "self, other = %s, %s " % (type(self),type(other)); #print "o type(%s) = %s, str = %s" % (o,type(o),str(o)); if isinstance(other,PyInteger) or isinstance(other,PyLong): o = self.ring.fromInteger(other); return RingElem( o ); if isinstance(other,RingElem): o = other.elem; else: o = other; if o == None: return RingElem( GenPolynomial(self.ring) ) if isJavaInstance(o): #print "self.elem, o = %s, %s " % (type(self.ring.coFac),type(o)); if o.getClass().getSimpleName() == "ExpVectorLong": # want startsWith or substring(0,8) == "ExpVector": o = GenPolynomial(self.ring,o); return RingElem( o ); if self.ring.coFac.getClass().getSimpleName() == o.getClass().getSimpleName(): o = GenPolynomial(self.ring,o); return RingElem( o ); if isinstance(other,RingElem): if self.isPolynomial() and not other.isPolynomial(): #print "self.ring = %s" % (self.ring); o = self.ring.parse( other.elem.toString() ); # not toScript() #print "o type(%s) = %s, str = %s" % (o,type(o),str(o)); return RingElem( o ); return other; #print "--1"; if isinstance(other,PyTuple) or isinstance(other,PyList): # assume BigRational or BigComplex # assume self will be compatible with them. todo: check this o = makeJasArith(other); #print "other class(%s) = %s" % (o,o.getClass()); if self.isPolynomial(): #print "other type(%s) = %s" % (o,type(o)); o = self.ring.parse( o.toString() ); # not toScript(); #o = o.elem; if self.elem.getClass().getSimpleName() == "BigComplex": #print "other type(%s) = %s" % (o,type(o)); o = CC( o ); o = o.elem; if self.elem.getClass().getSimpleName() == "BigQuaternion": #print "other type(%s) = %s" % (o,type(o)); o = Quat( o ); o = o.elem; if self.elem.getClass().getSimpleName() == "BigOctonion": #print "other type(%s) = %s" % (o,type(o)); o = Oct( Quat(o) ); o = o.elem; if self.elem.getClass().getSimpleName() == "Product": #print "other type(%s) = %s" % (o,type(o)); o = RR(self.ring, self.elem.multiply(o) ); # valueOf #print "o = %s" % o; o = o.elem; return RingElem(o); #print "--2"; # test if self.elem is a factory itself if self.isFactory(): if isinstance(other,PyInteger) or isinstance(other,PyLong): o = self.elem.fromInteger(other); else: if isinstance(other,PyFloat): # ?? what to do ?? o = self.elem.fromInteger( int(other) ); else: print "coerce_1: unknown other type(%s) = %s" % (other,type(other)); o = self.elem.parse( str(other) ); return RingElem(o); #print "--3"; #print "other type(%s) = %s" % (other,type(other)); # self.elem has a ring factory if isinstance(other,PyInteger) or isinstance(other,PyLong): o = self.elem.factory().fromInteger(other); else: if isinstance(other,PyFloat): # ?? what to do ?? #print "other type(%s) = %s" % (other,type(other)); #print "self type(%s) = %s" % (self.elem,self.elem.getClass().getName()); o = BigDecimal(other); if self.elem.getClass().getSimpleName() == "Product": o = RR(self.ring, self.elem.idempotent().multiply(o) ); # valueOf o = o.elem; else: o = self.elem.factory().getZERO().sum( o ); else: print "coerce_2: unknown other type(%s) = %s" % (other,type(other)); print "coerce_2: self type(%s) = %s" % (self,type(self)); o = self.elem.factory().parse( str(other) ); #print "--4"; return RingElem(o); def isFactory(self): '''Test if this is itself a ring factory. ''' f = self.elem.factory(); if self.elem == f: return True; else: return False; def isPolynomial(self): '''Test if this is a polynomial. ''' try: nv = self.elem.ring.nvar; except: return False; return True; def __cmp__(self,other): '''Compare two ring elements. ''' [s,o] = coercePair(self,other); return s.elem.compareTo( o.elem ); def __hash__(self): '''Hash value. ''' return self.elem.hashCode(); def __len__(self): '''Length of the element. ''' return self.elem.length(); def __mul__(self,other): '''Multiply two ring elements. ''' [s,o] = coercePair(self,other); #print "self type(%s) = %s" % (s,type(s)); #print "other type(%s) = %s" % (o,type(o)); return RingElem( s.elem.multiply( o.elem ) ); def __rmul__(self,other): '''Reverse multiply two ring elements. ''' [s,o] = coercePair(self,other); return o.__mul__(s); def __add__(self,other): '''Add two ring elements. ''' [s,o] = coercePair(self,other); return RingElem( s.elem.sum( o.elem ) ); def __radd__(self,other): '''Reverse add two ring elements. ''' [s,o] = coercePair(self,other); return o.__add__(s); def __sub__(self,other): '''Subtract two ring elements. ''' [s,o] = coercePair(self,other); return RingElem( s.elem.subtract( o.elem ) ); def __rsub__(self,other): '''Reverse subtract two ring elements. ''' [s,o] = coercePair(self,other); return o.__sub__(self); def __div__(self,other): '''Divide two ring elements. ''' [s,o] = coercePair(self,other); return RingElem( s.elem.divide( o.elem ) ); def __rdiv__(self,other): '''Reverse divide two ring elements. ''' [s,o] = coercePair(self,other); return o.__div__(s); def __mod__(self,other): '''Modular remainder of two ring elements. ''' [s,o] = coercePair(self,other); return RingElem( s.elem.remainder( o.elem ) ); def __xor__(self,other): '''Can not be used as power. ''' return None; def __pow__(self,other,n=None): '''Power of this to other. ''' #print "self type(%s) = %s" % (self,type(self)); #print "pow other type(%s) = %s" % (other,type(other)); if isinstance(other,PyInteger) or isinstance(other,PyLong): n = other; else: if isinstance(other,RingElem): n = other.elem; #if isinstance(n,BigRational): # does not work if n.getClass().getSimpleName() == "BigRational": n = n.numerator().intValue() / n.denominator().intValue(); #if isinstance(n,BigInteger): # does not work if n.getClass().getSimpleName() == "BigInteger": n = n.intValue(); if n == None: n = other; if self.isFactory(): p = Power(self.elem).power( self.elem, n ); else: p = Power(self.ring).power( self.elem, n ); return RingElem( p ); def __eq__(self,other): '''Test if two ring elements are equal. ''' if other == None: return False; [s,o] = coercePair(self,other); return s.elem.equals(o.elem) def __ne__(self,other): '''Test if two ring elements are not equal. ''' if other == None: return False; [s,o] = coercePair(self,other); return not self.elem.equals(o.elem) def __float__(self): '''Convert to Python float. ''' #print "self type(%s) = %s" % (self,type(self)); e = self.elem; if e.getClass().getSimpleName() == "BigInteger": e = BigRational(e); if e.getClass().getSimpleName() == "BigRational": e = BigDecimal(e); if e.getClass().getSimpleName() == "BigDecimal": e = e.toString(); e = float(e); return e; def factory(self): '''Get the factory of this element. ''' fac = self.elem.factory(); try: nv = fac.nvar; except: return RingElem(fac); #return PolyRing(fac.coFac,fac.getVars(),fac.tord); return RingElem(fac); def gens(self): '''Get the generators for the factory of this element. ''' L = self.elem.factory().generators(); #print "L = %s" % L; N = [ RingElem(e) for e in L ]; #print "N = %s" % N; return N; def inject_variables(self): '''Inject generators as variables into the main global namespace ''' inject_generators(self.gens()); def monic(self): '''Monic polynomial. ''' return RingElem( self.elem.monic() ); def evaluate(self,a): '''Evaluate at a for power series. ''' #print "self type(%s) = %s" % (self,type(self)); #print "a type(%s) = %s" % (a,type(a)); x = None; if isinstance(a,RingElem): x = a.elem; if isinstance(a,PyTuple) or isinstance(a,PyList): # assume BigRational or BigComplex # assume self will be compatible with them. todo: check this x = makeJasArith(a); try: e = self.elem.evaluate(x); except: e = 0; return RingElem( e ); def integrate(self,a=0,r=None): '''Integrate a power series with constant a or as rational function. a is the integration constant, r is for partial integration in variable r. ''' #print "self type(%s) = %s" % (self,type(self)); #print "a type(%s) = %s" % (a,type(a)); x = None; if isinstance(a,RingElem): x = a.elem; if isinstance(a,PyTuple) or isinstance(a,PyList): # assume BigRational or BigComplex # assume self will be compatible with them. todo: check this x = makeJasArith(a); try: if r != None: e = self.elem.integrate(x,r); else: e = self.elem.integrate(x); return RingElem( e ); except: pass; cf = self.elem.ring; try: cf = cf.ring; except: pass; integrator = ElementaryIntegration(cf.coFac); ei = integrator.integrate(self.elem); return ei; def differentiate(self,r=None): '''Differentiate a power series. r is for partial differentiation in variable r. ''' try: if r != None: e = self.elem.differentiate(r); else: e = self.elem.differentiate(); except: e = self.elem.factory().getZERO(); return RingElem( e ); def coefficients(self): '''Get the coefficients of a polynomial. ''' a = self.elem; #L = [ c.toScriptFactory() for c in a.coefficientIterator() ]; L = [ RingElem(c) for c in a.coefficientIterator() ]; return L #---------------- # Compatibility methods for Sage/Singular: # Note: the meaning of lt and lm is swapped compared to JAS. #---------------- def parent(self): '''Parent in Sage is factory in JAS. Compatibility method for Sage/Singular. ''' return self.factory(); def __call__(self,num): '''Apply this to num. ''' if num == 0: return self.zero(); if num == 1: return self.one(); return RingElem( self.ring.fromInteger(num) ); def lm(self): '''Leading monomial of a polynomial. Compatibility method for Sage/Singular. Note: the meaning of lt and lm is swapped compared to JAS. ''' ev = self.elem.leadingExpVector(); return ev; def lc(self): '''Leading coefficient of a polynomial. Compatibility method for Sage/Singular. ''' c = self.elem.leadingBaseCoefficient(); return RingElem(c); def lt(self): '''Leading term of a polynomial. Compatibility method for Sage/Singular. Note: the meaning of lt and lm is swapped compared to JAS. ''' ev = self.elem.leadingMonomial(); return Monomial(ev); def degree(self): '''Degree of a polynomial. ''' try: ev = self.elem.degree(); except: return None; return ev; def base_ring(self): '''Coefficient ring of a polynomial. ''' try: ev = self.elem.ring.coFac; except: return None; return RingElem(ev); def is_field(self): '''Test if this RingElem is field. ''' return self.elem.isField(); def monomials(self): '''All monomials of a polynomial. Compatibility method for Sage/Singular. ''' ev = self.elem.getMap().keySet(); return ev; def divides(self,other): '''Test if self divides other. Compatibility method for Sage/Singular. ''' [s,o] = coercePair(self,other); return o.elem.remainder( s.elem ).isZERO(); def ideal(self,list): '''Create an ideal. Compatibility method for Sage/Singular. ''' p = Ring("",ring=self.ring,fast=True); return p.ideal("",list=list); def monomial_quotient(self,a,b,coeff=False): '''Quotient of ExpVectors. Compatibility method for Sage/Singular. ''' if isinstance(a,RingElem): a = a.elem; if isinstance(b,RingElem): b = b.elem; if coeff == False: if a.getClass().getSimpleName() == "GenPolynomial": return RingElem( a.divide(b) ); else: return RingElem( GenPolynomial(self.ring, a.subtract(b)) ); else: # assume JAS Monomial c = a.coefficient().divide(b.coefficient()); e = a.exponent().subtract(b.exponent()) return RingElem( GenPolynomial(self.ring, c, e) ); def monomial_divides(self,a,b): '''Test divide of ExpVectors. Compatibility method for Sage/Singular. ''' #print "JAS a = " + str(a) + ", b = " + str(b); if isinstance(a,RingElem): a = a.elem; if a.getClass().getSimpleName() == "GenPolynomial": a = a.leadingExpVector(); if a.getClass().getSimpleName() != "ExpVectorLong": raise ValueError, "No ExpVector given " + str(a) + ", " + str(b) if b == None: return False; if isinstance(b,RingElem): b = b.elem; if b.getClass().getSimpleName() == "GenPolynomial": b = b.leadingExpVector(); if b.getClass().getSimpleName() != "ExpVectorLong": raise ValueError, "No ExpVector given " + str(a) + ", " + str(b) return a.divides(b); def monomial_pairwise_prime(self,e,f): '''Test if ExpVectors are pairwise prime. Compatibility method for Sage/Singular. ''' if isinstance(e,RingElem): e = e.elem; if isinstance(f,RingElem): f = f.elem; # assume JAS ExpVector c = e.gcd(f); return c.isZERO(); def monomial_lcm(self,e,f): '''Lcm of ExpVectors. Compatibility method for Sage/Singular. ''' if isinstance(e,RingElem): e = e.elem; if isinstance(f,RingElem): f = f.elem; # assume JAS ExpVector c = e.lcm(f); return c; def reduce(self,F): '''Compute a normal form of self with respect to F. Compatibility method for Sage/Singular. ''' s = self.elem; Fe = [ e.elem for e in F ]; n = ReductionSeq().normalform(Fe,s); return RingElem(n); #---------------- # End of compatibility methods #---------------- class PolyRing(Ring): '''Represents a JAS polynomial ring: GenPolynomialRing. Provides more convenient constructor. Then returns a Ring. ''' def __init__(self,coeff,vars,order=TermOrder(TermOrder.IGRLEX)): '''Ring constructor. coeff = factory for coefficients, vars = string with variable names, order = term order. ''' if coeff == None: raise ValueError, "No coefficient given." cf = coeff; if isinstance(coeff,RingElem): cf = coeff.elem.factory(); if isinstance(coeff,Ring): cf = coeff.ring; if vars == None: raise ValueError, "No variable names given." names = vars; if isinstance(vars,PyString): names = GenPolynomialTokenizer.variableList(vars); nv = len(names); to = PolyRing.lex; if isinstance(order,TermOrder): to = order; tring = GenPolynomialRing(cf,nv,to,names); #want: super(Ring,self).__init__(ring=tring) Ring.__init__(self,ring=tring) def __str__(self): '''Create a string representation. ''' return self.ring.toScript(); lex = TermOrder(TermOrder.INVLEX) grad = TermOrder(TermOrder.IGRLEX) class SolvPolyRing(SolvableRing): '''Represents a JAS solvable polynomial ring: GenSolvablePolynomialRing. Provides more convenient constructor. Then returns a Ring. ''' def __init__(self,coeff,vars,order=PolyRing.lex,rel=None): '''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 and e, f and p are commutative polynomials. ''' if coeff == None: raise ValueError, "No coefficient given." cf = coeff; if isinstance(coeff,RingElem): cf = coeff.elem.factory(); if isinstance(coeff,Ring): cf = coeff.ring; if vars == None: raise ValueError, "No variable names given." names = vars; if isinstance(vars,PyString): names = GenPolynomialTokenizer.variableList(vars); nv = len(names); to = PolyRing.lex; if isinstance(order,TermOrder): to = order; ring = GenSolvablePolynomialRing(cf,nv,to,names); if rel != None: #print "rel = " + str(rel); table = ring.table; L = []; for x in rel: if isinstance(x,RingElem): x = x.elem; L.append(x); #print "rel = " + str(L); for i in range(0,len(L),3): #print "adding relation: " + str(L[i]) + " * " + str(L[i+1]) + " = " + str(L[i+2]); table.update( L[i], L[i+1], L[i+2] ); self.ring = ring; SolvableRing.__init__(self,ring=self.ring) def __str__(self): '''Create a string representation. ''' return self.ring.toScript(); class EF: '''Extension field builder. Construction of extension field towers according to the builder pattern. ''' def __init__(self,base): '''Constructor to set base field. ''' if isinstance(base,RingElem): #factory = base.elem; factory = base.ring; else: factory = base; try: factory = self.factory.factory(); except: pass print "extension field factory: " + factory.toScript(); # + " :: " + factory.toString(); #print "d type(%s) = %s" % (factory,type(factory)); if isinstance(factory,ExtensionFieldBuilder): self.builder = factory; else: self.builder = ExtensionFieldBuilder(factory); def __str__(self): '''Create a string representation. ''' return str(self.builder.toScript()); def extend(self,vars,algebraic=None): '''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. ''' if algebraic == None: ef = self.builder.transcendentExtension(vars); else: ef = self.builder.algebraicExtension(vars,algebraic); return EF(ef.build()); def realExtend(self,vars,algebraic,interval): '''Create a real extension field. Construct a real algebraic extension field with an isolating interval for a real root. ''' ef = self.builder.realAlgebraicExtension(vars,algebraic,interval); return EF(ef.build()); def complexExtend(self,vars,algebraic,rectangle): '''Create a complex extension field. Construct a complex algebraic extension field with an isolating rectangle for a complex root. ''' ef = self.builder.complexAlgebraicExtension(vars,algebraic,rectangle); return EF(ef.build()); def polynomial(self,vars): '''Create an polynomial ring extension. ''' ef = self.builder.polynomialExtension(vars); return EF(ef.build()); def build(self): '''Get extension field tower. ''' rf = self.builder.build(); if isinstance(rf,GenPolynomialRing): return PolyRing(rf.coFac,rf.getVars(),rf.tord); else: return RingElem(rf.getZERO()); class WordRing(Ring): '''Represents a JAS free non-commutative polynomial ring: GenWordPolynomialRing. Has a method to create word ideals. Note: watch your step: check that jython does not reorder multiplication. ''' def __init__(self,ringstr="",ring=None): '''Word polynomial ring constructor. ''' if ring == None: raise ValueError, "parse of word polynomials not implemented" sr = StringReader( ringstr ); tok = GenPolynomialTokenizer(sr); self.pset = tok.nextWordPolynomialSet(); self.ring = self.pset.ring; else: self.ring = ring; #if not self.ring.isAssociative(): # print "warning: ring is not associative"; def __str__(self): '''Create a string representation. ''' return str(self.ring.toScript()); def ideal(self,ringstr="",list=None): '''Create a word ideal. ''' return WordIdeal(self,ringstr,list); def one(self): '''Get the one of the word polynomial ring. ''' return RingElem( self.ring.getONE() ); def zero(self): '''Get the zero of the word polynomial ring. ''' return RingElem( self.ring.getZERO() ); def random(self,n): '''Get a random word polynomial. ''' return RingElem( self.ring.random(n) ); def random(self,k,l,d): '''Get a random word polynomial. ''' return RingElem( self.ring.random(k,l,d) ); def element(self,poly): '''Create an element from a string or object. ''' if not isinstance(poly,str): try: if self.ring == poly.ring: return RingElem(poly); except Exception, e: pass poly = str(poly); I = WordIdeal(self, "( " + poly + " )"); list = I.list; if len(list) > 0: return RingElem( list[0] ); class WordPolyRing(WordRing): '''Represents a JAS free non-commutative polynomial ring: GenWordPolynomialRing. Provides more convenient constructor. Then returns a Ring. Note: watch your step: check that jython does not reorder multiplication. ''' def __init__(self,coeff,vars): '''Ring constructor. coeff = factory for coefficients, vars = string with variable names. ''' if coeff == None: raise ValueError, "No coefficient given." cf = coeff; if isinstance(coeff,RingElem): cf = coeff.elem.factory(); if isinstance(coeff,Ring): cf = coeff.ring; if vars == None: raise ValueError, "No variable names given." names = vars; if isinstance(vars,PyString): names = GenPolynomialTokenizer.variableList(vars); wf = WordFactory(names); ring = GenWordPolynomialRing(cf,wf); self.ring = ring; def __str__(self): '''Create a string representation. ''' return self.ring.toScript(); class WordIdeal: '''Represents a JAS word polynomial ideal. Methods for two-sided Groebner basees and others. Note: watch your step: check that jython does not reorder multiplication. ''' def __init__(self,ring,ringstr="",list=None): '''Constructor for an ideal in a word polynomial ring. ''' self.ring = ring; if list == None: raise ValueError, "parse of word polynomials not implemented" sr = StringReader( ringstr ); tok = GenPolynomialTokenizer(ring.ring,sr); self.list = tok.nextSolvablePolynomialList(); else: self.list = pylist2arraylist(list,rec=1); #self.pset = PolynomialList(ring.ring,self.list); def __str__(self): '''Create a string representation. ''' ll = [ e.toScript() for e in self.list ] return "( " + ", ".join(ll) + " )"; def __cmp__(self,other): '''Compare two ideals. ''' t = False; if not isinstance(other,WordIdeal): return t; t = self.list.equals(other.list); return t; def GB(self): '''Compute a two-sided Groebner base. ''' return self.twosidedGB(); def twosidedGB(self): '''Compute a two-sided Groebner base. ''' #s = self.pset; F = self.list; t = System.currentTimeMillis(); G = WordGroebnerBaseSeq().GB(F); t = System.currentTimeMillis() - t; print "executed twosidedGB in %s ms" % t; return WordIdeal(self.ring,"",G); def isGB(self): '''Test if this is a two-sided Groebner base. ''' return self.isTwosidedGB(); def isTwosidedGB(self): '''Test if this is a two-sided Groebner base. ''' #s = self.pset; F = self.list; t = System.currentTimeMillis(); b = WordGroebnerBaseSeq().isGB(F); t = System.currentTimeMillis() - t; print "isTwosidedGB executed in %s ms" % t; return b; jas-2.5/examples/nabeshima_cgbF7.rb0000644000175000017500000000151411653002012017434 0ustar giovannigiovanni# # jruby examples for jas. # $Id: nabeshima_cgbF7.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Nabashima, ISSAC 2007, example F7 # integral function coefficients r = Ring.new( "IntFunc(a, b) (z,y,x) G" ); puts "Ring: " + str(r); puts; ps = """ ( ( x^3 - { a } ), ( y^4 - { b } ), ( x + y - { a } z ) ) """; #startLog(); f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; bg = gs.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; #exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; bg = gs.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/pppj2006.py0000644000175000017500000000146210625376002016020 0ustar giovannigiovanni# # jython examples for jas. # $Id: pppj2006.py 1094 2007-05-24 20:56:35Z kredel $ # import sys; from jas import Ring from jas import Ideal # pppj 2006 paper examples r = Ring( "Z(x1,x2,x3) L" ); print "Ring: " + str(r); print; ps = """ ( ( 3 x1^2 x3^4 + 7 x2^5 - 61 ) ) """; #f = Ideal( r, ps ); #print "Ideal: " + str(f); #print; f = r.ideal( ps ); print "Ideal: " + str(f); print; from java.lang import System from java.io import StringReader from edu.jas.structure import * from edu.jas.arith import * from edu.jas.poly import * from org.apache.log4j import BasicConfigurator; BasicConfigurator.configure(); pps = """ 3 x1^2 x3^4 + 7 x2^5 - 61 """; ri = r.ring; print "ri = " + str(ri); pol = r.pset; print "pol = " + str(pol); pol = ri.parse( pps ); print "pol = " + str(pol); jas-2.5/examples/u_sl_3.py0000644000175000017500000000232612136720410015716 0ustar giovannigiovanni# # jython examples for jas. # $Id: u_sl_3.py 4381 2013-04-27 09:57:28Z kredel $ # from jas import SolvableRing # U(sl_3) example rs = """ # solvable polynomials, U(sl_3): Rat(Xa,Xb,Xc,Ya,Yb,Yc,Ha,Hb) G RelationTable ( ( Xb ), ( Xa ), ( Xa Xb - Xc ), ( Ya ), ( Xa ), ( Xa Ya - Ha ), ( Yc ), ( Xa ), ( Xa Yc + Yb ), ( Ha ), ( Xa ), ( Xa Ha + 2 Xa ), ( Hb ), ( Xa ), ( Xa Hb - Xa), ( Yb ), ( Xb ), ( Xb Yb - Hb ), ( Yc ), ( Xb ), ( Xb Yc - Ya ), ( Ha ), ( Xb ), ( Xb Ha - Xb ), ( Hb ), ( Xb ), ( Xb Hb + 2 Xb ), ( Ya ), ( Xc ), ( Xc Ya + Xb ), ( Yb ), ( Xc ), ( Xc Yb - Xa ), ( Yc ), ( Xc ), ( Xc Yc - Ha - Hb ), ( Ha ), ( Xc ), ( Xc Ha + Xc ), ( Hb ), ( Xc ), ( Xc Hb + Xc ), ( Yb ), ( Ya ), ( Ya Yb + Yc ), ( Ha ), ( Ya ), ( Ya Ha - 2 Ya ), ( Hb ), ( Ya ), ( Ya Hb + Ya ), ( Ha ), ( Yb ), ( Yb Ha + Yb ), ( Hb ), ( Yb ), ( Yb Hb - 2 Yb ), ( Ha ), ( Yc ), ( Yc Ha - Yc ), ( Hb ), ( Yc ), ( Yc Hb - Yc ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( Xa + Hb ), ( Xb + Ha Hb ) ) """; f = r.ideal( ps ); print "SolvableIdeal: " + str(f); print; rg = f.leftGB(); print "seq left Output:", rg; print; rg = f.twosidedGB(); print "seq twosided Output:", rg; print; jas-2.5/examples/factors_algeb_trans_algeb_charp.py0000644000175000017500000000535411425263522023055 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_algeb_trans_algeb_charp.py 3239 2010-08-01 12:23:46Z kredel $ # import sys from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import ZM, QQ, AN, RF from jas import terminate from jas import startLog # polynomial examples: factorization over Z_p(sqrt(2))(x)(sqrt(x))[y] Q = PolyRing(ZM(5),"w2",PolyRing.lex); print "Q = " + str(Q); [e,a] = Q.gens(); #print "e = " + str(e); print "a = " + str(a); root = a**2 - 2; print "root = " + str(root); Q2 = AN(root,field=True); print "Q2 = " + str(Q2.factory()); [one,w2] = Q2.gens(); #print "one = " + str(one); #print "w2 = " + str(w2); print; Qp = PolyRing(Q2,"x",PolyRing.lex); print "Qp = " + str(Qp); [ep,wp,ap] = Qp.gens(); #print "ep = " + str(ep); #print "wp = " + str(wp); #print "ap = " + str(ap); print; Qr = RF(Qp); print "Qr = " + str(Qr.factory()); [er,wr,ar] = Qr.gens(); #print "er = " + str(er); #print "wr = " + str(wr); #print "ar = " + str(ar); print; Qwx = PolyRing(Qr,"wx",PolyRing.lex); print "Qwx = " + str(Qwx); [ewx,wwx,ax,wx] = Qwx.gens(); #print "ewx = " + str(ewx); print "ax = " + str(ax); #print "wwx = " + str(wwx); print "wx = " + str(wx); print; #rootx = wx**5 - ax; rootx = wx**2 - ax; print "rootx = " + str(rootx); Q2x = AN(rootx,field=True); print "Q2x = " + str(Q2x.factory()); [ex2,w2x2,ax2,wx] = Q2x.gens(); #print "ex2 = " + str(ex2); #print "w2x2 = " + str(w2x2); #print "ax2 = " + str(ax2); #print "wx = " + str(wx); print; Yr = PolyRing(Q2x,"y",PolyRing.lex) print "Yr = " + str(Yr); [e,w2,x,wx,y] = Yr.gens(); print "e = " + str(e); print "w2 = " + str(w2); print "x = " + str(x); print "wx = " + str(wx); print "y = " + str(y); print; #f = ( y**5 - x ) * ( y**2 - 2 ); f = ( y**2 - x ) * ( y**2 - 2 ); #f = ( y**2 - x )**5 * ( y**2 - 2 )**3; #f = ( y**4 - x * 2 ); #f = ( y**7 - x * 2 ); #f = ( y**2 - 2 ); #f = ( y**2 - x ); #f = ( w2 * y**2 - 1 ); #f = ( y**2 - 1/x ); #f = ( y**2 - 3 ); # 1/2 = 3 mod 5 #f = ( y**2 - 1/x ) * ( y**2 - 3 ); # 1/2 = 3 mod 5 print "f = ", f; print; #sys.exit(); startLog(); t = System.currentTimeMillis(); G = Yr.factors(f); t = System.currentTimeMillis() - t; #print "G = ", G; #print "factor time =", t, "milliseconds"; #sys.exit(); print "f = ", f; g = e; for h, i in G.iteritems(): if i > 1: print "h**i = ", h, "**" + str(i); else: print "h = ", h; h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/montes_ex51s.py0000644000175000017500000000271111253240426017065 0ustar giovannigiovanni# # jython examples for jas. # $Id: montes_ex51s.py 2811 2009-09-13 18:59:35Z kredel $ # import sys; from jas import PolyRing, QQ, RF from jas import Ideal from jas import startLog from jas import terminate # Montes JSC 2002, 33, 183-208, example 5.1, simplified # integral function coefficients r = PolyRing( PolyRing(QQ(),"a, b",PolyRing.lex), "u,z,y,x", PolyRing.lex ); print "Ring: " + str(r); print; [one,a,b,u,z,y,x] = r.gens(); print "gens: ", [ str(f) for f in r.gens() ]; print; f1 = 756 * x - 39 * a * b - 4 * b - 155 - 117 * a + ( 117 * a + 51 ) * u; f2 = 189 * y + 6 * a * b - 107 - 43 * b + 18 * a - ( 18 * a - 123 ) * u; f3 = 756 * z - 1439 + 236 * b + 99 * a + 33 * a * b - ( 99 * a - 15 ) * u; f4 = ( 9 * a**2 - 30 * a + 21 ) * u - 9 * a**2 - 3 * a**2 * b + 11 * a * b + 22 * a - 49 + 28 * b; F = [f1,f2,f3,f4]; print "F: ", [ str(f) for f in F ]; print; #startLog(); If = r.paramideal( "", list = F ); print "ParamIdeal: " + str(If); print; ## G = If.GB(); ## print "GB: " + str(G); ## print; ## sys.exit(); GS = If.CGBsystem(); GS = If.CGBsystem(); GS = If.CGBsystem(); print "CGBsystem: " + str(GS); print; bg = GS.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; terminate(); sys.exit(); CG = If.CGB(); print "CGB: " + str(CG); print; bg = CG.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/radical-decomp_charp_ex816.rb0000644000175000017500000000326711653043730021474 0ustar giovannigiovanni# # jruby examples for jas. # $Id: radical-decomp_charp_ex816.rb 3817 2011-10-29 18:37:12Z kredel $ # require "examples/jas" # polynomial examples: ideal radical decomposition, modified from example 8.16 in GB book # noThreads(); # must be called very early prime = 5; cf = ZM(prime); #cf = QQ(); ca = PolyRing.new(cf,"a",PolyRing.lex); #puts "ca = " + str(ca); ea,aa = ca.gens(); puts "ea = " + str(ea); puts "aa = " + str(aa); puts; #!#roota = aa**prime + 2; roota = aa**2 + 2; puts "roota = " + str(roota); Q3a = AN(roota,field=true); puts "Q3a = " + str(Q3a.factory()); ## Q3a = RF(ca); #puts Q3a.gens(); ea2,aa2 = Q3a.gens(); puts "ea2 = " + str(ea2); puts "aa2 = " + str(aa2); puts; #cr = PolyRing.new(QQ(),"t",PolyRing.lex); cr = PolyRing.new(Q3a,"t",PolyRing.lex); puts "coefficient Ring: " + str(cr); rf = RF(cr); puts "coefficient quotient Ring: " + str(rf.ring.toScript()); r = PolyRing.new(rf,"x,y",PolyRing.lex); puts "Ring: " + str(r); #puts; one,a,t,x,y = r.gens(); #puts one,a,t,x,y; puts "one = " + str(one); puts "a = " + str(a); puts "t = " + str(t); puts "x = " + str(x); puts "y = " + str(y); puts; #sys.exit(); #f1 = x**prime - t; #f2 = y**prime - t; ##f1 = x**4 + t; ##f2 = y**4 + t; f1 = x**3 + t; f2 = y**3 + t; #f2 = f2**2; f3 = (y-x); f3 = f3**prime; puts "f1 = " + str(f1); puts "f2 = " + str(f2); #puts "f3 = " + str(f3); puts; F = r.ideal( "", list=[f1,f2] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); #R = F.primeDecomp(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "decomp time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/wa_32.jas0000644000175000017500000000033110653077260015576 0ustar giovannigiovanni# solvable polynomials, Weyl algebra A_3,2: (a,b,e1,e2,e3) L RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e1 ), ( e3 ), ( e2 ), ( e2 e3 - e2 ) ) ( ( e1 e3^3 + e2^10 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) jas-2.5/examples/RingElemTest.py0000644000175000017500000000464712004001746017102 0ustar giovannigiovanni# # jython unit tests for jas. # $Id: RingElemTest.py 4038 2012-07-25 14:34:14Z kredel $ # from java.lang import System from java.lang import Integer from jas import PolyRing, ZZ, QQ, ZM, GF from jas import terminate from jas import startLog import unittest # some unit tests: class RingElemTest (unittest.TestCase): def testRingZZ(self): r = PolyRing( ZZ(), "(t,x)", PolyRing.lex ); self.assertEqual(str(r),'PolyRing(ZZ(),"t,x",PolyRing.lex)'); [one,x,t] = r.gens(); self.assertTrue(one.isONE()); self.assertTrue(len(x)==1); self.assertTrue(len(t)==1); # f = 11 * x**4 - 13 * t * x**2 - 11 * x**2 + 2 * t**2 + 11 * t; f = f**2 + f + 3; #print "f = " + str(f); self.assertEqual(str(f),'( 4 * x**4 - 52 * t**2 * x**3 + 44 * x**3 + 213 * t**4 * x**2 - 330 * t**2 * x**2 + 123 * x**2 - 286 * t**6 * x + 528 * t**4 * x - 255 * t**2 * x + 11 * x + 121 * t**8 - 242 * t**6 + 132 * t**4 - 11 * t**2 + 3 )'); #end def testRingQQ(self): r = PolyRing( QQ(), "(t,x)", PolyRing.lex ); self.assertEqual(str(r),'PolyRing(QQ(),"t,x",PolyRing.lex)'); [one,x,t] = r.gens(); self.assertTrue(one.isONE()); self.assertTrue(len(x)==1); self.assertTrue(len(t)==1); # f = 11 * x**4 - 13 * t * x**2 - 11 * x**2 + 2 * t**2 + 11 * t; f = f**2 + f + 3; #print "f = " + str(f); self.assertEqual(str(f),'( 4 * x**4 - 52 * t**2 * x**3 + 44 * x**3 + 213 * t**4 * x**2 - 330 * t**2 * x**2 + 123 * x**2 - 286 * t**6 * x + 528 * t**4 * x - 255 * t**2 * x + 11 * x + 121 * t**8 - 242 * t**6 + 132 * t**4 - 11 * t**2 + 3 )'); #end def testRingZM(self): r = PolyRing( GF(17), "(t,x)", PolyRing.lex ); self.assertEqual(str(r),'PolyRing(GF(17),"t,x",PolyRing.lex)'); [one,x,t] = r.gens(); self.assertTrue(one.isONE()); self.assertTrue(len(x)==1); self.assertTrue(len(t)==1); # f = 11 * x**4 - 13 * t * x**2 - 11 * x**2 + 2 * t**2 + 11 * t; f = f**2 + f + 3; #print "f = " + str(f); self.assertEqual(str(f),'( 4 * x**4 + 16 * t**2 * x**3 + 10 * x**3 + 9 * t**4 * x**2 + 10 * t**2 * x**2 + 4 * x**2 + 3 * t**6 * x + t**4 * x + 11 * x + 2 * t**8 + 13 * t**6 + 13 * t**4 + 6 * t**2 + 3 )'); #end if __name__ == '__main__': #print str(__name__) + ": " + str(sys.modules[__name__]) unittest.main() jas-2.5/examples/hawes2_gens_quot.py0000644000175000017500000000257311505167460020024 0ustar giovannigiovanni# # jython examples for jas. # $Id: hawes2_gens_quot.py 3438 2010-12-24 19:06:24Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} import sys; from jas import Ring, PolyRing, RF, ZZ from jas import Ideal from jas import startLog from jas import terminate #startLog(); # Hawes & Gibson example 2 # rational function coefficients #r = Ring( "RatFunc(a, c, b) (y2, y1, z1, z2, x) G" ); r = PolyRing( RF(PolyRing(ZZ(),"a, c, b",PolyRing.lex)), "y2, y1, z1, z2, x", PolyRing.grad ); print "Ring: " + str(r); print; [one,a,c,b,y2,y1,z1,z2,x] = r.gens(); p1 = x + 2 * y1 * z1 + 3 * a * y1**2 + 5 * y1**4 + 2 * c * y1; p2 = x + 2 * y2 * z2 + 3 * a * y2**2 + 5 * y2**4 + 2 * c * y2; p3 = 2 * z2 + 6 * a * y2 + 20 * y2**3 + 2 * c; p4 = 3 * z1**2 + y1**2 + b; p5 = 3 * z2**2 + y2**2 + b; p6 = ( ( p5 / a ) / b ) / c; print "p6 = ", p6; F = [p1,p2,p3,p4,p6]; g = r.ideal( list=F ); print "Ideal: " + str(g); print; rg = g.GB(); rg = g.GB(); rg = g.GB(); rg = g.GB(); print "GB:", rg; print; bg = rg.isGB(); print "isGB:", bg; print; p7 = 1 / b; print "p7 = ", p7; p8 = p7 * b; print "p8 = ", p8; startLog(); terminate(); #sys.exit(); jas-2.5/examples/katsura5w.jas0000644000175000017500000000110111353207070016575 0ustar giovannigiovanni#Katsura equations for N = 5: (u5,u4,u3,u2,u1,u0) W(1,1,1,2,2,1) ( u5*u5 + u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 + u5*u5 - u0, u5*0 + u4*u5 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 + u5*u4 - u1, u5*0 + u4*0 + u3*u5 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 + u5*u3 - u2, u5*0 + u4*0 + u3*0 + u2*u5 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 + u5*u2 - u3, u5*0 + u4*0 + u3*0 + u2*0 + u1*u5 + u0*u4 + u1*u3 + u2*u2 + u3*u1 + u4*u0 + u5*u1 - u4, u5 + u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 + u5 - 1 ) jas-2.5/examples/mark_kr.rb0000644000175000017500000000242411644542070016141 0ustar giovannigiovanni# # jruby examples for jas. # $Id: mark_kr.rb 3797 2011-10-10 10:08:57Z kredel $ # require "examples/jas" # mark, d-gb diplom example, due to kandri-rody 1984 # # The MAS DIIPEGB implementation contains an error because the output e-GB # is not correct. Also the cited result from k-r contains this error. # The polynomial # # ( 2 x * y^2 - x^13 + 2 x^11 - x^9 + 2 x^7 - 2 x^3 ), # # is in the DIIPEGB output, but it must be # # ( 2 x * y^2 - x^13 + 2 x^11 - 3 x^9 + 2 x^7 - 2 x^3 ), # # Test by adding the polynomials to the input. # Frist polynomial produces a different e-GB. # Second polynomial reproduces the e-GB with the second polynomial. #r = Ring.new( "Z(x,y) L" ); r = PolyRing.new( ZZ(), "(x,y)", PolyRing.lex ); puts "Ring: " + str(r); puts; ps = """ ( ( y**6 + x**4 y**4 - x**2 y**4 - y**4 - x**4 y**2 + 2 x**2 y**2 + x**6 - x**4 ), ( 2 x**3 y**4 - x y**4 - 2 x**3 y**2 + 2 x y**2 + 3 x**5 - 2 x** 3 ), ( 3 y**5 + 2 x**4 y**3 - 2 x**2 y**3 - 2 y**3 - x**4 y + 2 x**2 y ) ) """; f = r.ideal( ps ); puts "Ideal: " + str(f); puts; #startLog(); eg = f.eGB( ); puts "seq e-GB: " + str(eg); puts "is e-GB: " + str(eg.isGB()); puts; #startLog(); dg = f.dGB(); puts "seq d-GB: " + str(dg); puts "is d-GB: " + str(dg.isGB()); puts; puts "d-GB == e-GB: "+ str(eg===dg); puts jas-2.5/examples/factors_mult.py0000644000175000017500000000320111177352404017235 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_mult.py 2623 2009-05-03 17:31:49Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring from jas import Ideal from jas import terminate from jas import startLog # polynomial examples: factorization #r = Ring( "Mod 1152921504606846883 (x,y,z) L" ); #r = Ring( "Rat(x,y,z) L" ); #r = Ring( "C(x,y,z) L" ); r = Ring( "Z(x,y,z) L" ); #r = Ring( "Z(x) L" ); #r = Ring( "Mod 3 (x,y,z) L" ); #r = Ring( "Z(y,x) L" ); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); #f = z * ( y + 1 )**2 * ( x**2 + x + 1 )**3; #f = z * ( y + 1 ) * ( x**2 + x + 1 ); #f = ( y + 1 ) * ( x**2 + x + 1 ); #f = ( y + z**2 ) * ( x**2 + x + 1 ); #f = x**4 * y + x**3 + z + x + z**2 + y * z**2; ## f = x**3 + ( ( y + 2 ) * z + 2 * y + 1 ) * x**2 \ ## + ( ( y + 2 ) * z**2 + ( y**2 + 2 * y + 1 ) * z + 2 * y**2 + y ) * x \ ## + ( y + 1 ) * z**3 + ( y + 1 ) * z**2 + ( y**3 + y**2 ) * z + y**3 + y**2; #f = ( x + y * z + y + z + 1 ) * ( x**2 + ( y + z ) * x + y**2 + z**2 ); f = ( x + y * z + y + z + 1 ) * ( x**2 + ( y + z ) * x + y**2 + 1 ); #f = ( x + y ) * ( x - y); print "f = ", f; print; startLog(); t = System.currentTimeMillis(); G = r.factors(f); t = System.currentTimeMillis() - t; print "G = ", G; #print "factor time =", t, "milliseconds"; g = one; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/solvmodright.rb0000644000175000017500000000257111774031074017240 0ustar giovannigiovanni# # jruby examples for jas. # $Id: solvmodright.rb 3972 2012-07-01 11:19:24Z kredel $ # require "examples/jas" # Quantum plane example rsan = """ AN[ (i) (i^2 + 1) ] (Y,X,x,y) G RelationTable ( ( y ), ( x ), ( {i} x y ) ( X ), ( Y ), ( {i} Y X ) ) """; rsc = """ #not supported C(Y,X,x,y) G |2| C(Y,X,x,y) G RelationTable ( ( y ), ( x ), ( 0i1 x y ) ( X ), ( Y ), ( 0i1 Y X ) ) """; r = SolvableModule.new( rsc ); #r = SolvableModule.new( rsan ); puts "SolvableModule: " + str(r); puts; ps = """ ( ( ( x + 1 ), ( y ) ), ( ( x y ), ( 0 ) ), ( ( x - X ), ( x - X ) ), ( ( y - Y ), ( y - Y ) ) ) """; f = SolvableSubModule.new( r, ps ); puts "SolvableSubModule: " + str(f); puts; #exit() lg = f.leftGB(); puts "seq left GB: " + str(lg); puts "is left GB: " + str(lg.isLeftGB()); puts; tg = f.twosidedGB(); puts "seq twosided GB: " + str(tg); puts "is twosided GB: " + str(tg.isTwosidedGB()); puts "is right GB: " + str(tg.isRightGB()); puts; startLog(); rg = f.rightGB(); puts "seq right GB: " + str(rg); puts "is right GB: " + str(rg.isRightGB()); puts; exit(); rg2 = rg.rightGB(); puts "seq right GB: " + str(rg2); puts "is right GB: " + str(rg2.isRightGB()); puts "rg == rg2: " + str(rg == rg2); puts; rg3 = rg2.rightGB(); puts "seq right GB: " + str(rg3); puts "is right GB: " + str(rg3.isRightGB()); puts "rg2 == rg3: " + str(rg2 == rg3); puts; #startLog(); terminate(); jas-2.5/examples/trinks6.jas0000644000175000017500000000034110653077260016264 0ustar giovannigiovanni# trinks6 (B,S,T,Z,P,W) L ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B^2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B^3 ), ( 99 W - 11 B S + 3 B^2 ) ) jas-2.5/examples/factors_rat.py0000644000175000017500000000415011151515162017040 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_rat.py 2449 2009-02-26 13:34:43Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring from jas import Ideal from jas import terminate from jas import startLog # polynomial examples: factorization over Q #r = Ring( "Rat(x) L" ); r = Ring( "Q(x) L" ); print "Ring: " + str(r); print; [one,x] = r.gens(); #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**4 - 1; #f = x**3 - x**2 + x - 1; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; #f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; f = x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8; print "f = ", f; print; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; print "G = ", G; #print "factor time =", t, "milliseconds"; g = one; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/nabeshima_cgbF6.py0000644000175000017500000000173211474505546017507 0ustar giovannigiovanni# # jython examples for jas. # $Id: nabeshima_cgbF6.py 3379 2010-11-28 17:03:34Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Nabashima, ISSAC 2007, example F6 # integral function coefficients r = Ring( "IntFunc(a, b,c, d) (x) G" ); print "Ring: " + str(r); print; ps = """ ( ( x^4 + { a } x^3 + { b } x^2 + { c } x + { d } ), ( 4 x^3 + { 3 a } x^2 + { 2 b } x + { c } ) ) """; #startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/primary-decomp.py0000644000175000017500000000155211376460372017477 0ustar giovannigiovanni# # jython examples for jas. # $Id: primary-decomp.py 3150 2010-05-24 11:20:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: ideal primary decomposition #r = Ring( "Rat(x) L" ); #r = Ring( "Q(x) L" ); r = PolyRing(QQ(),"x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); f1 = (x**2 - 5)**2; f2 = (y**2 - x)**2; f3 = z**2 - x ; #print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print; F = r.ideal( list=[f2,f3] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); Q = F.primaryDecomp(); t = System.currentTimeMillis() - t; print "Q = ", Q; print; print "primary decomp time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/pppj2006.rb0000644000175000017500000000100711773606716016003 0ustar giovannigiovanni# # jruby examples for jas. # $Id: pppj2006.rb 3969 2012-06-30 14:31:43Z kredel $ # require "examples/jas" # pppj 2006 paper examples r = PolyRing.new( ZZ(), "x1,x2,x3", PolyRing.lex ); puts "Ring: " + str(r); puts; f = 3 * x1**2 * x3**4 + 7 * x2**5 - 61; puts "f = " + str(f); puts; id = r.ideal( "", list=[f] ); puts "Ideal: " + str(id); puts; ri = r.ring; puts "ri = " + str(ri); pol = r.pset; puts "pol = " + str(pol); pol = ri.parse( str(f) ); puts "pol = " + str(pol); puts; #startLog(); #terminate(); jas-2.5/examples/raksanyi.py0000644000175000017500000000141511505167460016362 0ustar giovannigiovanni# # jython examples for jas. # $Id: raksanyi.py 3438 2010-12-24 19:06:24Z kredel $ # import sys; from jas import Ring, PolyRing, RF, ZZ from jas import Ideal # Raksanyi & Walter example # rational function coefficients #r = Ring( "RatFunc(a1, a2, a3, a4) (x1, x2, x3, x4) G" ); r = PolyRing( RF(PolyRing(ZZ(),"a1, a2, a3, a4",PolyRing.lex)), "x1, x2, x3, x4", PolyRing.grad ); print "Ring: " + str(r); print; ps = """ ( ( x4 - { a4 - a2 } ), ( x1 + x2 + x3 + x4 - { a1 + a3 + a4 } ), ( x1 x3 + x1 x4 + x2 x3 + x3 x4 - { a1 a4 + a1 a3 + a3 a4 } ), ( x1 x3 x4 - { a1 a3 a4 } ) ) """; f = r.ideal( ps ); print "Ideal: " + str(f); print; rg = f.GB(); rg = f.GB(); print "GB:", rg; print; from edu.jas.kern import ComputerThreads; ComputerThreads.terminate(); #sys.exit(); jas-2.5/examples/factors_algeb_trans_build.py0000644000175000017500000000307211537152632021723 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_algeb_trans_build.py 3565 2011-03-13 14:32:58Z kredel $ # import sys from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import QQ, AN, RF, EF from jas import terminate from jas import startLog # polynomial examples: factorization over Q(sqrt(2))(x)(sqrt(x))[y] Yr = EF(QQ()).extend("w2","w2^2 - 2").extend("x").extend("wx","wx^2 - x").polynomial("y").build(); #print "Yr = " + str(Yr); #print [one,w2,x,wx,y] = Yr.gens(); print "one = " + str(one); print "w2 = " + str(w2); print "x = " + str(x); print "wx = " + str(wx); print "y = " + str(y); print; f = ( y**2 - x ) * ( y**2 - 2 ); #f = ( y**2 - x )**2 * ( y**2 - 2 )**3; #f = ( y**4 - x * 2 ); #f = ( y**7 - x * 2 ); #f = ( y**2 - 2 ); #f = ( y**2 - x ); #f = ( w2 * y**2 - 1 ); #f = ( y**2 - 1/x ); #f = ( y**2 - (1,2) ); #f = ( y**2 - 1/x ) * ( y**2 - (1,2) ); print "f = ", f; print; #sys.exit(); startLog(); t = System.currentTimeMillis(); G = Yr.factors(f); t = System.currentTimeMillis() - t; #print "G = ", G; #print "factor time =", t, "milliseconds"; #sys.exit(); print "f = ", f; g = one; for h, i in G.iteritems(): if i > 1: print "h**i = ", h, "**" + str(i); else: print "h = ", h; h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/wa_1r.jas0000644000175000017500000000065511356104256015702 0ustar giovannigiovanni# solvable polynomials, Weyl algebra A_1, right GB: Rat (a,b,x,y) L RelationTable ( #( y^3 ), ( x ), ( x * y^3 - 3 y^2 ), #( y^2 ), ( x^2 ), ( x^2 * y^2 - 4 x * y + 2 ), #( y^2 ), ( x ), ( x * y^2 - 2 y ), #( y ), ( x^4 ), ( x^4 * y - 4 x^3 ), #( y ), ( x^3 ), ( x^3 * y - 3 x^2 ), #( y ), ( x^2 ), ( x^2 * y - 2 x ), ( y ), ( x ), ( x * y - 1 ) ) ( ( y - 1/48 a^3 * x^2 + 1/12 a^2 * x - 1/2 a ), ( b - 1/24 a^3 ), ( a^4 ) ) jas-2.5/examples/katsura.rb0000644000175000017500000000244412056644004016165 0ustar giovannigiovanni# # jruby examples for jas. # $Id: katsura.rb 4311 2012-12-02 12:22:28Z kredel $ require "examples/jas" include_class "edu.jas.gb.Katsura"; # katsura examples knum = 4; tnum = 2; #r = Ring( "Mod 19 (B,S,T,Z,P,W) L" ); #r = Ring( "Mod 1152921504606846883 (B,S,T,Z,P,W) L" ); # 2^60-93 #r = Ring( "Quat(B,S,T,Z,P,W) L" ); #r = Ring( "Z(B,S,T,Z,P,W) L" ); #r = Ring( "C(B,S,T,Z,P,W) L" ); #r = Ring( "Rat(B,S,T,Z,P,W) L" ); #puts "Ring: " + str(r); #puts; k = Katsura.new(knum); r = Ring.new( k.varList("Rat","G") ); #r = Ring.new( k.varList("Mod 23","G") ); #r = Ring.new( k.varList("Mod 32003","G") ); #r = Ring.new( k.varList("Mod 536870909","G") ); #r = Ring.new( k.varList("Mod 4294967291","G") ); #r = Ring.new( k.varList("Mod 9223372036854775783","G") ); #r = Ring.new( k.varList("Mod 170141183460469231731687303715884105727","G") ); #no?#r = Ring.new( k.varList("Mod 1152921504606846883","G") ); puts "Ring: " + str(r); puts; ps = k.polyList(); puts "ps : " + ps; puts; exit(); f = r.ideal( ps ); puts "Ideal: " + str(f); puts; #puts "Range: " + Range.new(tnum,2,-1).to_s; #puts "Range: " + (tnum...2).to_s; #puts; rg = f.parGB(tnum); for th in tnum.downto(2) do rg = f.parGB(th); #puts "par(#{th}) Output:" + rg.to_s; #puts; end rg = f.GB(); #puts "seq Output:", rg; puts; terminate(); jas-2.5/examples/polypower.rb0000644000175000017500000000265611641577122016565 0ustar giovannigiovanni# # jruby examples for jas. # $Id: polypower.rb 3788 2011-10-01 11:49:39Z kredel $ # require "examples/jas" # sparse polynomial powers #r = Ring( "Mod 1152921504606846883 (x,y,z) G" ); #r = Ring( "Rat(x,y,z) G" ); #r = Ring( "C(x,y,z) G" ); r = PolyRing.new( ZZ(), "(x,y,z)", PolyRing.lex ); puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); puts; p1 = ( 1 + x**2147483647 + y**2147483647 + z**2147483647 ); p2 = ( 1 + x + y + z ); p3 = ( 10000000001 + 10000000001 * x + 10000000001 * y + 10000000001 * z ); puts "p1 = " + str(p1); puts "p2 = " + str(p2); puts "p3 = " + str(p3); puts; # unused: ps = """ ( ( 1 + x^2147483647 + y^2147483647 + z^2147483647 ) ( 1 + x + y + z ) ( 10000000001 + 10000000001 x + 10000000001 y + 10000000001 z ) ) """; #f = Ideal.new( r, ps ); f = r.ideal( ps ); puts "Ideal: " + str(f); puts; plist = f.pset.list; puts "plist: " + str(plist); puts; p = plist[0]; #p = plist[2]; p = p2; #p = p1; puts "p: " + str(p); puts; q = p; for i in 1..19 q = q * p; end puts "q: " + str(q.elem.length()); puts; q1 = q + one; #puts "q1:", q1; puts "q1: " + str(q1.elem.length()); puts; t = System.currentTimeMillis(); q2 = q * q1; t = System.currentTimeMillis() - t; puts "q2: " + str(q2.elem.length()); puts "time " + str(t) + " milliseconds"; puts; #puts "Integer.MAX_VALUE = " +str(Integer::MAX_VALUE); jas-2.5/examples/factors_abs.rb0000644000175000017500000000353511641415316017004 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_abs.rb 3786 2011-09-30 19:38:55Z kredel $ # require "examples/jas" # polynomial examples: absolute factorization over Q r = Ring.new( "Q(x) L" ); puts "Ring: " + str(r); puts; one,x = r.gens(); #f = x**5 - 1; #f = x**6 - 1; f = x**3 - 2; f = f*f; #f = x**7 - 1; #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**2 + 1; #f = x**3 - x**2 + x - 1; #f = x**6 - 5 * x**4 + 5 * x**2 + 4; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; #f = x**4 + 2 * x**2 - 4 * x + 2; #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; #f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; #f = x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8; puts "f = " + str(f); puts; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factorsAbsolute(f); t = System.currentTimeMillis() - t; puts "G = " + str(G.toScript()); puts puts "factor time = " + str(t) + " milliseconds"; puts #startLog(); terminate(); jas-2.5/examples/factors_algeb.py0000644000175000017500000000614311535146104017332 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_algeb.py 3555 2011-03-07 12:15:01Z kredel $ # from java.lang import System from java.lang import Integer from jas import PolyRing, AN, QQ from jas import Ideal from jas import terminate from jas import startLog # polynomial examples: factorization over Q(i) #r = Ring( "AN[ (i) (i^2 + 1) ] (x) L" ); #r = Ring( "AN[ (a) (4 a^2 + 1) ] (x) L" ); #r = Ring( "AN[ (a) (a^4 + 2 a^2 - 4 a + 2) ] (x) L" ); #print "Ring: " + str(r); #print; Qr = PolyRing(QQ(),"i",PolyRing.lex); print "Qr = " + str(Qr); [e,a] = Qr.gens(); print "e = " + str(e); print "a = " + str(a); imag = a**2 + 1; print "imag = " + str(imag); Qi = AN(imag,field=True); print "Qi = " + str(Qi.factory()); [one,i] = Qi.gens(); print "one = " + str(one); print "i = " + str(i); b = i**2 + 1; print "b = " + str(b); c = 1 / i; print "c = " + str(c); #Qix = AN(i**2 + 1); #print "Qix = " + str(Qix.factory()); print; r = PolyRing(Qi,"x",PolyRing.lex) print "r = " + str(r); [one,i,x] = r.gens(); print "one = " + str(one); print "i = " + str(i); print "x = " + str(x); #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11) + 3 * x**(2*11) - x**(11); #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**4 + 1; #f = x**3 - x**2 + x - 1; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; f = x**6 - 5 * x**4 + 5 * x**2 + 4; # == f = ( x**3 + 2 * i * x**2 - 3 * x - 4 * i ) * ( x**3 - 2 * i * x**2 - 3 * x + 4 * i ); #f = ( x**3 + ( 2 * i ) * x**2 - ( 3 ) * x - ( 4 * i ) ) * ( x**3 - ( 2 * i ) * x**2 - ( 3 ) * x + ( 4 * i ) ); #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; #f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; #f = x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8; print "f = ", f; print; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; print "G = ", G; #print "factor time =", t, "milliseconds"; g = one; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/cgb_2.rb0000644000175000017500000000157111641163152015466 0ustar giovannigiovanni# # jruby examples for jas. # $Id: cgb_2.rb 3785 2011-09-29 21:43:06Z kredel $ # require "examples/jas" # 2 univariate polynomials of degree 2 example for comprehensive GB # integral/rational function coefficients #r = Ring.new( "IntFunc(a2, a1, a0, b2, b1, b0) (x) L" ); r = PolyRing.new( PolyRing.new(ZZ(),"(a2, a1, a0, b2, b1, b0)",PolyRing.lex),"(x)", PolyRing.lex ); puts "Ring: " + str(r); puts; ps = """ ( ( { a2 } x^2 + { a1 } x + { a0 } ), ( { b2 } x^2 + { b1 } x + { b0 } ) ) """; f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; #sys.exit(); #startLog(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; #sys.exit(); bg = gs.isCGBsystem(); puts "isCGBsystem: " + str(bg); puts; #sys.exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; terminate(); #sys.exit(); #bg = gs.isCGB(); #puts "isCGB: " + str(bg); #puts; #terminate(); #sys.exit(); jas-2.5/examples/katsura7.jas0000644000175000017500000000173311353207070016423 0ustar giovannigiovanni#Katsura equations for N = 7: (u7,u6,u5,u4,u3,u2,u1,u0) G ( u7*u7 + u6*u6 + u5*u5 + u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 + u5*u5 + u6*u6 + u7*u7 - u0, u7*0 + u6*u7 + u5*u6 + u4*u5 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 + u5*u4 + u6*u5 + u7*u6 - u1, u7*0 + u6*0 + u5*u7 + u4*u6 + u3*u5 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 + u5*u3 + u6*u4 + u7*u5 - u2, u7*0 + u6*0 + u5*0 + u4*u7 + u3*u6 + u2*u5 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 + u5*u2 + u6*u3 + u7*u4 - u3, u7*0 + u6*0 + u5*0 + u4*0 + u3*u7 + u2*u6 + u1*u5 + u0*u4 + u1*u3 + u2*u2 + u3*u1 + u4*u0 + u5*u1 + u6*u2 + u7*u3 - u4, u7*0 + u6*0 + u5*0 + u4*0 + u3*0 + u2*u7 + u1*u6 + u0*u5 + u1*u4 + u2*u3 + u3*u2 + u4*u1 + u5*u0 + u6*u1 + u7*u2 - u5, u7*0 + u6*0 + u5*0 + u4*0 + u3*0 + u2*0 + u1*u7 + u0*u6 + u1*u5 + u2*u4 + u3*u3 + u4*u2 + u5*u1 + u6*u0 + u7*u1 - u6, u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 + u5 + u6 + u7 - 1 ) jas-2.5/examples/word_solvable_trans.py0000644000175000017500000000435612024343272020613 0ustar giovannigiovanni# # jython examples for jas. # $Id: word_solvable_trans.py 4189 2012-09-13 11:42:50Z kredel $ # #from java.lang import System from jas import WordRing, WordPolyRing, WordIdeal, PolyRing, SolvPolyRing from jas import terminate, startLog from jas import QQ, ZZ, GF, ZM # non-commutative polynomial examples: solvable polynomials example r = WordPolyRing(QQ(),"a,b,e1,e2,e3"); print "WordPolyRing: " + str(r); print; [one,a,b,e1,e2,e3] = r.gens(); print "one = " + str(one); print "a = " + str(a); print "b = " + str(b); print "e1 = " + str(e1); print "e2 = " + str(e2); print "e3 = " + str(e3); print; r1 = e3 * e1 - (e1 * e3 - e1); r2 = e3 * e2 - (e2 * e3 - e2); r3 = e1 * a - a * e1; r4 = e1 * b - b * e1; r5 = e2 * a - a * e2; r6 = e2 * b - b * e2; r7 = e3 * a - a * e3; r8 = e3 * b - b * e3; f1 = e1 * e3**3 + e2**10 - a; f2 = e1**3 * e2**2 + e3; f3 = e3**3 + e3**2 - b; print "r1 = " + str(r1); print "r2 = " + str(r2); print "r3 = " + str(r3); print "r4 = " + str(r4); print "r5 = " + str(r5); print "r6 = " + str(r6); print "r7 = " + str(r7); print "r8 = " + str(r8); print "f1 = " + str(f1); print "f2 = " + str(f2); print "f3 = " + str(f3); print; F = r.ideal( list=[r1,r2,r3,r4,r5,r6,r7,r8,f1,f2,f3] ); #F = r.ideal( list=[r1,r2,f1,f2,f3] ); print "F = " + str(F); print; startLog(); G = F.GB(); print "G = " + str(G); print "isGB(G) = " + str(G.isGB()); print; # now as solvable polynomials p = PolyRing(QQ(),"a,b,e1,e2,e3"); #is automatic: [one,a,b,e1,e2,e3] = p.gens(); relations = [e3, e1, e1*e3 - e1, e3, e2, e2*e3 - e2]; print "relations: =", [ str(f) for f in relations ]; print; #rp = SolvPolyRing(QQ(), "a,b,e1,e2,e3", rel=relations); rp = SolvPolyRing(QQ(), "a,b,e1,e2,e3", PolyRing.lex, relations); print "SolvPolyRing: " + str(rp); print; print "gens =", [ str(f) for f in rp.gens() ]; #[one,a,b,e1,e2,e3] = rp.gens(); #[one,I,J,K,a,b,e1,e2,e3] = rp.gens(); f1 = e1 * e3**3 + e2**10 - a; f2 = e1**3 * e2**2 + e3; f3 = e3**3 + e3**2 - b; F = [ f1, f2, f3 ]; print "F =", [ str(f) for f in F ]; print I = rp.ideal( list=F ); print "SolvableIdeal: " + str(I); print; rgt = I.twosidedGB(); print "seq twosided GB:" + str(rgt); print "isTwosidedGB: " + str(rgt.isTwosidedGB()); print print "rgt: ", [ str(f) for f in rgt.list ]; print; jas-2.5/examples/raksanyi.rb0000644000175000017500000000125311653060122016324 0ustar giovannigiovanni# # jruby examples for jas. # $Id: raksanyi.rb 3818 2011-10-29 20:21:39Z kredel $ # require "examples/jas" # Raksanyi & Walter example # rational function coefficients #r = Ring.new( "RatFunc(a1, a2, a3, a4) (x1, x2, x3, x4) G" ); r = PolyRing.new( RF(PolyRing.new(ZZ(),"a1, a2, a3, a4",PolyRing.lex)), "x1, x2, x3, x4", PolyRing.grad ); puts "Ring: " + str(r); puts; ps = """ ( ( x4 - { a4 - a2 } ), ( x1 + x2 + x3 + x4 - { a1 + a3 + a4 } ), ( x1 x3 + x1 x4 + x2 x3 + x3 x4 - { a1 a4 + a1 a3 + a3 a4 } ), ( x1 x3 x4 - { a1 a3 a4 } ) ) """; f = r.ideal( ps ); puts "Ideal: " + str(f); puts; rg = f.GB(); rg = f.GB(); rg = f.GB(); puts "GB:" + str(rg); puts; terminate(); jas-2.5/examples/hawes2_int.py0000644000175000017500000000205511071723024016575 0ustar giovannigiovanni# # jython examples for jas. # $Id: hawes2_int.py 2174 2008-10-04 17:21:25Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate #startLog(); # Hawes & Gibson example 2 # integral function coefficients r = Ring( "IntFunc(a, c, b) (y2, y1, z1, z2, x) L" ); print "Ring: " + str(r); print; ps = """ ( ( x + 2 y1 z1 + { 3 a } y1^2 + 5 y1^4 + { 2 c } y1 ), ( x + 2 y2 z2 + { 3 a } y2^2 + 5 y2^4 + { 2 c } y2 ), ( 2 z2 + { 6 a } y2 + 20 y2^3 + { 2 c } ), ( 3 z1^2 + y1^2 + { b } ), ( 3 z2^2 + y2^2 + { b } ) ) """; f = r.ideal( ps ); print "Ideal: " + str(f); print; #startLog(); rgl = f.GB(); print "GB:", rgl; print; bg = rgl.isGB(); print "isGB:", bg; print; terminate(); #sys.exit(); jas-2.5/examples/factors_mod_ins.rb0000644000175000017500000000256411773570014017673 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_mod_ins.rb 3968 2012-06-30 12:24:45Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: factorization over Z_p p = 5; cr = PolyRing.new( GF(p), "u", PolyRing.lex ); puts "Ring: " + str(cr); puts #one,u = r.gens(); fu = (u**2+u+1)**p; puts "fu = ", fu; puts; startLog(); t = System.currentTimeMillis(); G = cr.squarefreeFactors(fu); #G = cr.factors(fu); t = System.currentTimeMillis() - t; puts "G = ", str(G.map{ |h,i| str(h)+"**"+str(i)+" " }); #puts "G = ", G; puts "factor time = " + str(t) + " milliseconds"; qcr = RF(cr); puts "Ring qcr: " + str(qcr.factory()); #not ok#r = PolyRing(cr,"x",PolyRing.lex ); r = PolyRing.new(qcr,"x",PolyRing.lex ); puts "Ring r: " + str(r); #f = x**3 - u; #f = (x - u)**3; #f = (x - u**3)**3; #f = (x - u**9)**3; #f = x**p - u; #f = (x - u)**p; p2 = p * 2; fu = (u**2+u+1)**p; #f = x**p + 1/fu; f = x**p + fu; #f = x**p2 - fu * x**p - fu; #f = x**p2 + x**p + 1; #f = x**p2 + 1; puts "f = ", f; puts; t = System.currentTimeMillis(); G = r.squarefreeFactors(f); #G = r.factors(f); t = System.currentTimeMillis() - t; puts "G = ", str(G.map{ |h,i| str(h)+"**"+str(i)+" " }); #puts "G = ", G; puts "factor time = " + str(t) + " milliseconds"; gu = u**2+u+1; #g = (x + 1/gu); g = (x + gu); puts "g = " + str(g); gp = g**p; puts "g**p = " + str(gp); puts; #startLog(); terminate(); jas-2.5/examples/trinksTest.py0000644000175000017500000000220611012020470016670 0ustar giovannigiovanni# # jython examples for jas. # $Id: trinksTest.py 1781 2008-05-12 10:51:36Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # trinks 6/7 example #r = Ring( "Mod 19 (B,S,T,Z,P,W) L" ); #r = Ring( "Mod 1152921504606846883 (B,S,T,Z,P,W) L" ); # 2^60-93 #r = Ring( "Quat(B,S,T,Z,P,W) L" ); #r = Ring( "Z(B,S,T,Z,P,W) L" ); #r = Ring( "C(B,S,T,Z,P,W) L" ); r = Ring( "Rat(B,S,T,Z,P,W) L" ); print "Ring: " + str(r); print; ps = """ ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B**3 ), ( 99 W - 11 B S + 3 B**2 ), ( 10000 B**2 + 6600 B + 2673 ) ) """; # ( 10000 B**2 + 6600 B + 2673 ) # ( B**2 + 33/50 B + 2673/10000 ) #f = Ideal( r, ps ); #print "Ideal: " + str(f); #print; f = r.ideal( ps ); print "Ideal: " + str(f); print; #startLog(); rg = f.GB(); #print "seq Output:", rg; #print; rg = f.parGB(2); #print "par Output:", rg; #print; f.distClient(); # starts in background rg = f.distGB(2); #print "dist Output:", rg; #print; terminate(); sys.exit(); jas-2.5/examples/intprog.rb0000644000175000017500000000125011644356076016202 0ustar giovannigiovanni# # jruby examples for jas. # $Id: intprog.rb 3794 2011-10-09 17:39:11Z kredel $ # # CLO2, p370 # 4 A + 5 B + C = 37 # 2 A + 3 B + D = 20 # # max: 11 A + 15 B # require "examples/jas" r = Ring.new( "Rat(w1,w2,w3,w4,z1,z2) W( (0,0,0,0,1,1),(1,1,2,2,0,0) )" ); puts "Ring: " + str(r); puts; ps = """ ( ( z1^4 z2^2 - w1 ), ( z1^5 z2^3 - w2 ), ( z1 - w3 ), ( z2 - w4 ) ) """; f = SimIdeal.new( r, ps ); puts "Ideal: " + str(f); puts; #startLog(); rg = f.GB(); puts "seq Output: " + str(rg); puts; pf = """ ( ( z1^37 z2^20 ) ) """; fp = SimIdeal.new( r, pf ); puts "Ideal: " + str(fp); puts; nf = fp.NF(rg); puts "NFs: " + str(nf); puts; terminate() #sys.exit(); jas-2.5/examples/sgb.jas0000644000175000017500000000017410653077260015443 0ustar giovannigiovanni# solvable polynomials: (a,x,y) L RelationTable ( ( y ), ( x ), ( x y + a ) ) ( ( y**3 + x**2 y + x y ), ( x**2 + x ) ) jas-2.5/examples/sys-bio.rb0000644000175000017500000000162511653754360016111 0ustar giovannigiovanni# # jruby examples for jas. # $Id: sys-bio.rb 3823 2011-11-01 11:33:05Z kredel $ # require "examples/jas" # system biology examples: GB in Z_2 # see: Informatik Spektrum, 2009, February, # Laubenbacher, Sturmfels: Computer Algebra in der Systembiologie r = PolyRing.new(ZM(2),"M, B, A, L, P",PolyRing.lex); puts "PolyRing: " + str(r); puts; one,M,B,A,L,P = r.gens(); f1 = M - A; f2 = B - M; f3 = A - A - L * B - A * L * B; f4 = P - M; f5 = L - P - L - L * B - L * P - L * B * P; ## t1 = M - 1; ## t2 = B - 1; ## t3 = A - 1; ## t4 = L - 1; ## t5 = P - 1; # ## t1 = M; ## t2 = B; ## t3 = A; ## t4 = L; ## t5 = P; # ## t1 = M; ## t2 = B; ## t3 = A; ## t4 = L - 1; ## t5 = P; # t1 = M; t2 = B; t3 = A - 1; t4 = L - 1; t5 = P; F = [f1,f2,f3,f4,f5]; #F = [f1,f2,f3,f4,f5,t1,t2,t3,t4,t5]; I = r.ideal( "", list=F ); puts "Ideal: " + str(I); puts; G = I.GB(); puts "GB: " + str(G); puts; #startLog(); terminate(); jas-2.5/examples/real_roots_ideal.py0000644000175000017500000000206411722146704020050 0ustar giovannigiovanni# # jython examples for jas. # $Id: real_roots_ideal.py 3891 2012-02-25 12:02:13Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: real roots over Q for zero dimensional ideals r = PolyRing(QQ(),"q,w,s,x",PolyRing.lex); print "Ring: " + str(r); print; [one,q,w,s,x] = r.gens(); # EF(QQ()).realExtend("q","q^3 - 3", "[1,2]").realExtend("w", "w^2 - q", "[1,2]").realExtend("s", "s^5 - 2", "[1,2]").polynomial("x").build(); f1 = q**3 - 3; f2 = w**2 - q; #f3 = s**5 - 2; f3 = s**3 - 2; f4 = x**2 - w * s; print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print "f4 = ", f4; print; F = r.ideal( list=[f1,f2,f3,f4] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); R = F.realRoots(); t = System.currentTimeMillis() - t; print "R = ", R; print; print "real roots = "; F.realRootsPrint() print "real roots time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/montes_ex51.rb0000644000175000017500000000221011653043730016652 0ustar giovannigiovanni# # jruby examples for jas. # $Id: montes_ex51.rb 3817 2011-10-29 18:37:12Z kredel $ # require "examples/jas" # Montes JSC 2002, 33, 183-208, example 5.1 # integral function coefficients r = PolyRing.new( PolyRing.new(QQ(),"a, b",PolyRing.lex), "u,z,y,x", PolyRing.lex ); puts "Ring: " + str(r); puts; one,a,b,u,z,y,x = r.gens(); puts "gens: " + r.gens().each{ |f| str(f) }.join(","); puts; f1 = a * x + 2 * y + 3 * z + u - 6; f2 = x + 3 * y - z + 2 * u - b; f3 = 3 * x - a * y + z - 2; f4 = 5 * x + 4 * y + 3 * z + 3 * u - 9; F = [f1,f2,f3,f4]; puts "F: " + F.each{ |f| str(f) }.join(","); puts; #startLog(); If = r.paramideal( "", list = F ); puts "ParamIdeal: " + str(If); puts; ## G = If.GB(); ## puts "GB: " + str(G); ## puts; ## sys.exit(); GS = If.CGBsystem(); GS = If.CGBsystem(); GS = If.CGBsystem(); puts "CGBsystem: " + str(GS); puts; bg = GS.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; #terminate(); #exit(); CG = If.CGB(); puts "CGB: " + str(CG); puts; bg = CG.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); jas-2.5/examples/nabeshima_cgbF5.rb0000644000175000017500000000160211653002012017430 0ustar giovannigiovanni# # jruby examples for jas. # $Id: nabeshima_cgbF5.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Nabashima, ISSAC 2007, example F5 # integral function coefficients r = Ring.new( "IntFunc(b, a, c) (x,y) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( { a } x^2 y + { b } x + y^2 ), ( { a } x^2 y + { b } x y ), ( y^2 + { b } x^2 y + { c } x y ) ) """; #startLog(); f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; #exit(); bg = gs.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; #exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; bg = gs.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/trinks.groovy0000644000175000017500000000160210677760034016753 0ustar giovannigiovanni/* * groovy trinks example. * $Id: $ */ import edu.jas.groovy.Ring import edu.jas.groovy.Ideal def r = new Ring( "Rat(B,S,T,Z,P,W) L" ); println "Ring: " + r.toString(); println ""; def ps = """ ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B**3 ), ( 99 W - 11 B S + 3 B**2 ) , ( B**2 + 33/50 B + 2673/10000 ) ) """; // ( B**2 + 33/50 B + 2673/10000 ) def f = r.ideal( ps ); println "Ideal: " + f println "" def rg = f.GB(); println "seq Output: " + rg println "" //terminate() a = new edu.jas.arith.BigRational(2,3) println "a = " + a b = a.fromInteger(5) println "b = " + b c = a.sum(b) println "c = " + c pp = new edu.jas.structure.Power(a) d = pp.positivePower(c,10) println "d = " + d d = pp.power(c,10) println "d = " + d //println "plus = " + (a+b) jas-2.5/examples/nabeshima_cgbF0.py0000644000175000017500000000161611060462722017467 0ustar giovannigiovanni# # jython examples for jas. # $Id: nabeshima_cgbF0.py 2106 2008-09-06 11:13:23Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Nabashima, ISSAC 2007, example Ex-4.8 # integral function coefficients r = Ring( "IntFunc(a, b, c) (y,x) L" ); print "Ring: " + str(r); print; ps = """ ( ( { a } x^2 + { b } y^2 ), ( { c } x^2 + y^2 ), ( { 2 a } x - { 2 c } y ) ) """; #startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/nabeshima_cgbF5.py0000644000175000017500000000175211253240426017474 0ustar giovannigiovanni# # jython examples for jas. # $Id: nabeshima_cgbF5.py 2811 2009-09-13 18:59:35Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Nabashima, ISSAC 2007, example F5 # integral function coefficients r = Ring( "IntFunc(b, a, c) (x,y) L" ); print "Ring: " + str(r); print; ps = """ ( ( { a } x^2 y + { b } x + y^2 ), ( { a } x^2 y + { b } x y ), ( y^2 + { b } x^2 y + { c } x y ) ) """; #startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; #sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/squarefree_finite_alg.py0000644000175000017500000000201011224463142021046 0ustar giovannigiovanni# # jython examples for jas. # $Id: squarefree_finite_alg.py 2717 2009-07-06 21:02:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import PolyRing, QQ, ZM, AN from jas import terminate from jas import startLog # polynomial examples: squarefree: characteristic p, finite algebraic ar = PolyRing(ZM(7,field=True),"i",PolyRing.lex) [one,i] = ar.gens(); # irred for 7, 11, 19 r = PolyRing(AN(i**2+1,field=True),"x, y, z",PolyRing.lex) print "Ring: " + str(r); print; [one,i,x,y,z] = r.gens(); a = r.random(k=2,l=3); b = r.random(k=2,l=3); c = r.random(k=1,l=3); if a.isZERO(): a = x; if b.isZERO(): b = y; if c.isZERO(): c = z; f = a**2 * b**7 * c; print "a = ", a; print "b = ", b; print "c = ", c; print "f = ", f; print; t = System.currentTimeMillis(); F = r.squarefreeFactors(f); t = System.currentTimeMillis() - t; print "factors:"; for g in F.keys(): i = F[g]; print "g = %s**%s" % (g,i); print print "factor time =", t, "milliseconds"; #startLog(); terminate(); jas-2.5/examples/radical-decomp_charp_ex816_algeb.rb0000644000175000017500000000366311653043730022626 0ustar giovannigiovanni# # jruby examples for jas. # $Id: radical-decomp_charp_ex816_algeb.rb 3817 2011-10-29 18:37:12Z kredel $ # require "examples/jas" # polynomial examples: ideal radical decomposition, example 8.16 in GB book, base field with p-th root # noThreads(); # must be called very early prime = 5; cf = ZM(prime); #cf = QQ(); ca = PolyRing.new(cf,"t",PolyRing.lex); puts "ca = " + str(ca); ea,ta = ca.gens(); puts "ea = " + str(ea); puts "ta = " + str(ta); puts; Qpt = RF(ca); #puts Qpt.gens(); ea2,ta2 = Qpt.gens(); puts "ea2 = " + str(ea2); puts "ta2 = " + str(ta2); puts; cr = PolyRing.new(Qpt,"wpt",PolyRing.lex); puts "polynomial quotient ring: " + str(cr); et2,t,wpt = cr.gens(); puts "et2 = " + str(et2); puts "t = " + str(t); puts "wpt = " + str(wpt); puts; root = wpt**prime - ta2; af = AN(root,field=true); puts "coefficient algebraic quotient ring: " + str(af.ring.toScript()); #puts af.gens(); ##xx = AN(( wpt**5 + 4 * t ),True,PolyRing(RF(PolyRing(ZM(5),"t",PolyRing.lex)),"wpt",PolyRing.lex)) ##puts "xx: " + str(xx.ring.toScript()); one,t,wpt = af.gens(); puts "one = " + str(one); puts "t = " + str(t); puts "wpt = " + str(wpt); #puts one,t,wpt; puts; #sys.exit(); r = PolyRing.new(af,"x,y",PolyRing.lex); puts "polynomial ring: " + str(r); #puts; one,t,wpt,x,y = r.gens(); #puts one,t,wpt,x,y; puts "one = " + str(one); puts "t = " + str(t); puts "wpt = " + str(wpt); puts "x = " + str(x); puts "y = " + str(y); puts; #sys.exit(); f1 = x**prime - t; f2 = y**prime - t; f2 = f2**3; f3 = (y-x); f3 = f3**prime; puts "f1 = " + str(f1); puts "f2 = " + str(f2); #puts "f3 = " + str(f3); puts; F = r.ideal( "", list=[f1,f2] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); #R = F.primeDecomp(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "decomp time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/squarefree.rb0000644000175000017500000000143411653336426016663 0ustar giovannigiovanni# # jruby examples for jas. # $Id: squarefree.rb 3822 2011-10-30 21:09:42Z kredel $ # require "examples/jas" # polynomial examples: squarefree: characteristic 0 r = PolyRing.new(QQ(),"x, y, z",PolyRing.lex) puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); a = r.random(k=2,l=3); b = r.random(k=2,l=3); c = r.random(k=1,l=3); if a.isZERO() a = x; end if b.isZERO() b = y; end if c.isZERO() c = z; end f = a**2 * b**3 * c; puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); puts "f = " + str(f); puts; t = System.currentTimeMillis(); F = r.squarefreeFactors(f); t = System.currentTimeMillis() - t; puts "factors:"; for g in F.keys() i = F[g]; puts "g = #{g}**#{i}"; end puts puts "factor time = " + str(t) + " milliseconds"; startLog(); terminate(); jas-2.5/examples/u_sl_3.jas0000644000175000017500000000022010653077260016044 0ustar giovannigiovanni# solvable polynomials in U(sl_3): #(a,x,y) L #RelationTable #( # ( y ), ( x ), ( x y + a ) #) #( # ( y**3 + x**2 y + x y ), # ( x**2 + x ) #) jas-2.5/examples/trinks_str.py0000644000175000017500000000231112000537714016731 0ustar giovannigiovanni# # jython examples for jas. # $Id: trinks_str.py 3996 2012-07-15 13:04:13Z kredel $ # import sys; from jas import QQ, Ring, PolyRing, Ideal from jas import startLog, terminate # trinks 6/7 example #r = Ring( "Mod 19 (B,S,T,Z,P,W) L" ); #r = Ring( "Mod 1152921504606846883 (B,S,T,Z,P,W) L" ); # 2^60-93 #r = Ring( "Quat(B,S,T,Z,P,W) L" ); #r = Ring( "Z(B,S,T,Z,P,W) L" ); #r = Ring( "C(B,S,T,Z,P,W) L" ); #r = Ring( "Rat(B,S,T,Z,P,W) L" ); r = PolyRing( QQ(),"B,S,T,Z,P,W", PolyRing.lex); print "Ring: " + str(r); print; ps = """ ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B**3 ), ( 99 W - 11 B S + 3 B**2 ), ( 10000 B**2 + 6600 B + 2673 ) ) """; # ( 10000 B**2 + 6600 B + 2673 ) # ( B**2 + 33/50 B + 2673/10000 ) #f = Ideal( r, ps ); #print "Ideal: " + str(f); #print; f = r.ideal( ps ); print "Ideal: " + str(f); print; #startLog(); rg = f.GB(); #print "seq Output:", rg; #print; rg = f.parGB(2); #print "par Output:", rg; #print; f.distClient(); # starts in background rg = f.distGB(2); #print "dist Output:", rg; #print; terminate(); sys.exit(); # required because of distClient jas-2.5/examples/word_simple.py0000644000175000017500000000466112023147024017061 0ustar giovannigiovanni# # jython examples for jas. # $Id: word_simple.py 4183 2012-09-09 17:12:52Z kredel $ # from java.lang import System from java.lang import Integer from jas import WordRing, WordPolyRing, WordIdeal from jas import terminate, startLog from jas import QQ, ZZ, GF, ZM # non-commutative polynomial examples: simple test r = WordPolyRing(QQ(),"x,y"); print "WordPolyRing: " + str(r); print; [one,x,y] = r.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); print; f1 = x*y - (1,10); f2 = y*x + x + y; print "f1 = " + str(f1); print "f2 = " + str(f2); print; c1 = f1 * f2; c2 = f2 * f1; s = c1 - c2; print "c1 = " + str(c1); print "c2 = " + str(c2); print "s = " + str(s); print; F = r.ideal( list=[f1,f2] ); print "F = " + str(F); print; startLog(); G = F.GB(); print "G = " + str(G); print "isGB(G) = " + str(G.isGB()); print; F = r.ideal( list=[f1,f2,c1,c2,s] ); print "F = " + str(F); print; G = F.GB(); print "G = " + str(G); print "isGB(G) = " + str(G.isGB()); print; p = r.random(3,6,4); print "p = " + str(p); print; pp = p**5; print "pp = " + str(len(pp)); print "p == pp: " + str(p == pp); print "pp == pp: " + str(pp == pp); print "pp-pp == 0: " + str(pp-pp == 0); print; #exit(0); ri = WordPolyRing(ZZ(),"x,y"); print "WordPolyRing: " + str(ri); print; [one,x,y] = ri.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); print; f1 = x*y - 10; f2 = y*x + x + y; print "f1 = " + str(f1); print "f2 = " + str(f2); print; c1 = f1 * f2; c2 = f2 * f1; s = c1 - c2; print "c1 = " + str(c1); print "c2 = " + str(c2); print "s = " + str(s); print; Fi = ri.ideal( list=[f1,f2] ); print "Fi = " + str(Fi); print; #not implemented: #Gi = Fi.GB(); #print "Gi = " + str(Gi); #print "isGB(Gi) = " + str(Gi.isGB()); #print; #exit(0); rp = WordPolyRing(GF(23),"x,y"); print "WordPolyRing: " + str(rp); print; [one,x,y] = rp.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); print; f1 = x*y - 10; f2 = y*x + x + y; print "f1 = " + str(f1); print "f2 = " + str(f2); print; c1 = f1 * f2; c2 = f2 * f1; s = c1 - c2; s1 = 22 * y*x*x*y + x*y*y*x + 22 * y*x*y + x*y*y + x*y*x + 22 * x*x*y; print "c1 = " + str(c1); print "c2 = " + str(c2); print "s = " + str(s); print "s1 = " + str(s1); print "s == s1: " + str(s==s1); print; Fp = rp.ideal( list=[f1,f2] ); print "Fp = " + str(Fp); print; Gp = Fp.GB(); print "Gp = " + str(Gp); print "isGB(Gp) = " + str(Gp.isGB()); print; jas-2.5/examples/cyclic5.jas0000644000175000017500000000030611501522556016214 0ustar giovannigiovanni#Cyclic equations for N = 5: (a,b,c,d,e) G ( a + b + c + d + e, a*b + b*c + c*d + d*e + e*a, a*b*c + b*c*d + c*d*e + d*e*a + e*a*b, a*b*c*d + b*c*d*e + c*d*e*a + d*e*a*b + e*a*b*c, a*b*c*d*e - 1 ) jas-2.5/examples/quantumplane.py0000644000175000017500000000242011425115600017236 0ustar giovannigiovanni# # jython examples for jas. # $Id: quantumplane.py 3235 2010-07-31 21:54:09Z kredel $ # from jas import SolvableModule from jas import SolvableSubModule # Quantum plane example rsan = """ AN[ (i) (i^2 + 1) ] (Y,X,x,y) G RelationTable ( ( y ), ( x ), ( {i} x y ) ( X ), ( Y ), ( {i} Y X ) ) """; rsc = """ C(Y,X,x,y) G RelationTable ( ( y ), ( x ), ( 0i1 x y ) ( X ), ( Y ), ( 0i1 Y X ) ) """; r = SolvableModule( rsc ); #r = SolvableModule( rsan ); print "SolvableModule: " + str(r); print; ps = """ ( ( ( x + 1 ), ( y ) ), ( ( x y ), ( 0 ) ), ( ( x - X ), ( x - X ) ), ( ( y - Y ), ( y - Y ) ) ) """; # ( ( y^2 x ) ), # ( ( y^3 x^2 ) ) # ( ( x + 1 ) ), # ( ( x + 1 ), ( y ) ), # ( ( x y ), ( 0 ) ) f = SolvableSubModule( r, ps ); print "SolvableSubModule: " + str(f); print; #flg = f.leftGB(); #print "seq left GB Output:", flg; #print; ftg = f.twosidedGB(); print "seq twosided GB Output:", ftg; print; from edu.jas.gbmod import SolvableSyzygyAbstract; from edu.jas.gbmod import ModSolvableGroebnerBase; s = SolvableSyzygyAbstract().leftZeroRelations( ftg.mset ); #sl = ModuleList(f.pset.vars,f.pset.tord,s,f.pset.table); print "leftSyzygy:", s; print; if SolvableSyzygyAbstract().isLeftZeroRelation(s,ftg.mset): print "is Syzygy"; else: print "is not Syzygy"; jas-2.5/examples/gbs.rb0000644000175000017500000000147111534200272015260 0ustar giovannigiovanni# # jruby examples for jas. # $Id: $ # require "examples/jas" #startLog(); # ? example #r = Ring.new( "Rat(t,x,y,z) L" ); #r = Ring.new( "Z(t,x,y,z) L" ); #r = Ring.new( "Mod 11(t,x,y,z) L" ); r = Ring.new( "Rat(t,x,y) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( t - x - 2 y ), ( x^4 + 4 ), ( y^4 + 4 ) ) """; # ( y^4 + 4 x y^3 - 2 y^3 - 6 x y^2 + 1 y^2 + 6 x y + 2 y - 2 x + 3 ), # ( x^2 + 1 ), # ( y^3 - 1 ) # ( y^2 + 2 x y + 2 y + 2 x + 1 ), # ( y^4 + 4 x - 2 y^3 - 6 x + 1 y^2 + 6 x + 2 y - 2 x + 3 ), # ( t - x - 2 y ), # ( 786361/784 y^2 + 557267/392 y + 432049/784 ), # ( x^7 + 3 y x^4 + 27/8 x^4 + 2 y x^3 + 51/7 x^3 + 801/28 y + 1041/56 ) # ( x**2 + 1 ), # ( y**2 + 1 ) f = r.ideal( ps ); puts "Ideal: " + str(f); puts; startLog(); rg = f.GB(); puts "seq Output:", rg; puts; terminate(); jas-2.5/examples/cyclic5_complex_roots.py0000644000175000017500000000225611722152614021051 0ustar giovannigiovanni# # jython examples for jas. # $Id: cyclic5_complex_roots.py 3892 2012-02-25 12:35:24Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: complex roots over Q for zero dimensional ideal `cyclic5' #r = Ring( "Q(x) L" ); r = PolyRing(QQ(),"a,b,c,d,e",PolyRing.lex); print "Ring: " + str(r); print; [one,a,b,c,d,e] = r.gens(); f1 = a + b + c + d + e; f2 = a*b + b*c + c*d + d*e + e*a; f3 = a*b*c + b*c*d + c*d*e + d*e*a + e*a*b; f4 = a*b*c*d + b*c*d*e + c*d*e*a + d*e*a*b + e*a*b*c; f5 = a*b*c*d*e - 1; print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print "f4 = ", f4; print "f5 = ", f5; print; F = r.ideal( list=[f1,f2,f3,f4,f5] ); print "F = ", F; print; startLog(); #G = F.GB(); #print "G = ", G; #print; #sys.exit(); t = System.currentTimeMillis(); R = F.complexRoots(); #R = F.realRoots(); t = System.currentTimeMillis() - t; print; print "R = ", R; print; print "complex roots: "; F.complexRootsPrint() print "complex roots time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/eliminate.py0000644000175000017500000000115111162775700016506 0ustar giovannigiovanni# # jython examples for jas. # $Id: eliminate.py 2507 2009-03-26 22:03:45Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # ideal elimination example r = Ring( "Rat(x,y,z) G" ); print "Ring: " + str(r); print; ps1 = """ ( ( x^2 - 2 ), ( y^2 - 3 ), ( z^3 - x * y ) ) """; F1 = r.ideal( ps1 ); print "Ideal: " + str(F1); print; e = Ring( "Rat(z) G" ); print "Ring: " + str(e); print; #startLog(); rg1 = F1.eliminateRing(e); print "rg1 = ", rg1; print; rg2 = rg1.intersectRing(e); print "rg2 = ", rg2; print; terminate(); #sys.exit(); jas-2.5/examples/raksanyi_cr.py0000644000175000017500000000267211255676466017071 0ustar giovannigiovanni# # jython examples for jas. # $Id: raksanyi_cr.py 2819 2009-09-21 13:18:47Z kredel $ # import sys; from jas import Ring from jas import ParamIdeal from jas import startLog from jas import terminate # Raksanyi & Walter example # integral/rational function coefficients #r = Ring( "RatFunc(a1, a2, a3, a4) (x1, x2, x3, x4) L" ); r = Ring( "IntFunc(a1, a2, a3, a4) (x1, x2, x3, x4) L" ); print "Ring: " + str(r); print; ps = """ ( ( x4 - { a4 - a2 } ), ( x1 + x2 + x3 + x4 - { a1 + a3 + a4 } ), ( x1 x3 + x1 x4 + x2 x3 + x3 x4 - { a1 a4 + a1 a3 + a3 a4 } ), ( x1 x3 x4 - { a1 a3 a4 } ) ) """; f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; #sys.exit(); #startLog(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; #sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; rs = gs.regularRepresentation(); print "regular representation: " + str(rs); print; rs = gs.regularRepresentationBC(); print "boolean closed regular representation: " + str(rs); print; startLog(); bg = rs.isRegularGB(); if bg: print "pre isRegularGB: true"; else: print "pre isRegularGB: false"; print; rsg = rs.regularGB(); print "regular GB: " + str(rsg); print; bg = rsg.isRegularGB(); if bg: print "post isRegularGB: true"; else: print "post isRegularGB: false"; print; ss = rsg.stringSlice(); print "regular string slice: " + str(ss); terminate(); #sys.exit(); jas-2.5/examples/chebyshev.rb0000644000175000017500000000075411641163152016474 0ustar giovannigiovanni# # jruby examples for jas. # $Id: chebyshev.rb 3785 2011-09-29 21:43:06Z kredel $ # require "examples/jas" # chebyshev polynomial example # T(0) = 1 # T(1) = x # T(n) = 2 * x * T(n-1) - T(n-2) r = Ring.new( "Z(x) L" ); puts "Ring: " + str(r); puts; # sage like: with generators for the polynomial ring one,x = r.gens(); x2 = 2 * x; N = 10; T = [one,x]; for n in 2..N t = x2 * T[n-1] - T[n-2]; T[n] = t; end for n in 0..N puts "T[#{n}] = #{T[n]}"; end puts; #sys.exit(); jas-2.5/examples/intprog4a.py0000644000175000017500000000242410373614370016450 0ustar giovannigiovanni# # jython for jas example 3 integer programming. # $Id: intprog4a.py 597 2006-02-12 11:16:09Z kredel $ # # CLO2, p374,c # 3 A + 2 B + C + D = 45 # A + 2 B + 3 C + E = 21 # 2 A + B + C + F = 18 # # max: 3 A + 4 B + 2 C # import sys; from jas import Ring from jas import Ideal r = Ring( "Rat(w1,w2,w3,w4,w5,w6,z1,z2,z3) W( (0,0,0,0,0,0,1,1,1),(-3,-4,-2,0,0,0,0,0,0) )" ); #r = Ring( "Rat(w1,w2,w3,w4,w5,w6,z1,z2,z3) W( (0,0,0,0,0,0,1,1,1),( 6, 5, 5,1,1,1,0,0,0)*2 )" ); #r = Ring( "Rat(w1,w2,w3,w4,w5,w6,z1,z2,z3) W( (0,0,0,0,0,0,1,1,1),( 3, 1, 3,1,1,1,0,0,0) )" ); #r = Ring( "Rat(w1,w2,w3,w4,w5,w6,z1,z2,z3) W( (0,0,0,0,0,0,1,1,1),( 9, 6, 8,2,2,2,0,0,0) )" ); print "Ring: " + str(r); print; ps = """ ( ( z1^3 z2 z3^2 - w1 ), ( z1^2 z2^2 z3 - w2 ), ( z1 z2^3 z3 - w3 ), ( z1 - w4 ), ( z2 - w5 ), ( z3 - w6 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; rg = f.GB(); print "seq Output:", rg; print; pf = """ ( ( z1^45 z2^21 z3^18 ) ) """; fp = Ideal( r, pf ); print "Ideal: " + str(fp); print; nf = fp.NF(rg); print "NFs: " + str(nf); print; #rg = f.parGB(2); #print "par Output:", rg; #print; #f.distClient(); # starts in background #rg = f.distGB(2); #print "dist Output:", rg; #print; #sys.exit(); jas-2.5/examples/hermite.rb0000644000175000017500000000100011644356076016146 0ustar giovannigiovanni# # jruby examples for jas. # $Id: hermite.rb 3794 2011-10-09 17:39:11Z kredel $ # require "examples/jas" # hermite polynomial example # H(0) = 1 # H(1) = 2 * x # H(n) = 2 * x * H(n-1) - 2 * (n-1) * H(n-2) r = Ring.new( "Z(x) L" ); puts "Ring: " + str(r); puts; # sage like: with generators for the polynomial ring one,x = r.gens(); x2 = 2 * x; N = 10; H = [one,x2]; for n in 2..N h = x2 * H[n-1] - 2 * (n-1) * H[n-2]; H << h; end for n in 0..N puts "H[#{n}] = #{H[n]}"; end puts; #sys.exit(); jas-2.5/examples/std.rb0000644000175000017500000000143111644361154015304 0ustar giovannigiovanni# # jruby examples for jas. # $Id: std.rb 3795 2011-10-09 18:05:33Z kredel $ # require "examples/jas" # example from CLO(UAG), 4.4 #R = PolyRing( ZM(32003), "x,y,z" ); R = PolyRing.new( QQ(), "x,y,z" ); puts "Ring: " + str(R); puts; one,x,y,z = R.gens(); f1 = x**5 - x * y**6 - z**7; f2 = x * y + y**3 + z**3; f3 = x**2 + y**2 - z**2; L = [f1,f2,f3]; #puts "L = ", str(L); F = R.ideal( "", L ); puts "Ideal: " + str(F); puts; PR = R.powerseriesRing(); puts "Power series ring: " + str(PR); puts; Fp = PSIdeal.new(PR,L); puts "Power series ideal: " + str(Fp); puts; startLog(); #9+5 # truncate at total degree 9 S = Fp.STD(); #puts "std: " + str(S); puts; for p in S.list do #puts "p = ", str(p.asPolynomial()); puts "p = " + str(p); end puts; #sys.exit(); #terminate(); jas-2.5/examples/atan.rb0000644000175000017500000000305011641155210015423 0ustar giovannigiovanni# # jruby examples for jas. # $Id: atan.rb 3784 2011-09-29 20:52:24Z kredel $ # require "examples/jas" # elementary integration atan examples r = PolyRing.new(QQ(),"x",PolyRing.lex); puts "r = " + str(r); rf = RF(r); puts "rf = " + str(rf.factory()); one,x = rf.gens(); puts "one = " + str(one); puts "x = " + str(x); puts; #f = 1 / ( 1 + x**2 ); #f = 1 / ( x**2 - 2 ); #f = 1 / ( x**3 - 2 ); #f = ( x + 3 ) / ( x**2- 3 * x - 40 ); f = ( x**7 - 24 * x**4 - 4 * x**2 + 8 * x - 8 ) / ( x**8 + 6 * x**6 + 12 * x**4 + 8 * x**2 ); puts "f = " + str(f); puts; #sys.exit(); #startLog(); t = System.currentTimeMillis(); e1 = r.integrate(f); t = System.currentTimeMillis() - t; puts "e1 = " + str(e1); puts "integration time = " + str(t) + " milliseconds"; puts t = System.currentTimeMillis(); e2 = f.integrate(); t = System.currentTimeMillis() - t; puts "e2 = " + str(e2); puts "integration time = " + str(t) + " milliseconds"; puts #startLog(); terminate(); #sys.exit(); jas-2.5/examples/boolean_cgb.rb0000644000175000017500000000212211641163152016735 0ustar giovannigiovanni# # jruby examples for jas. # $Id: boolean_cgb.rb 3785 2011-09-29 21:43:06Z kredel $ # require "examples/jas" # Boolean coefficient boolean GB # see S. Inoue and A. Nagai "On the Implementation of Boolean Groebner Bases" in ASCM 2009 # Z_2 regular ring coefficent example r = PolyRing.new(RR(ZM(2),3),"a,x,y",PolyRing.lex); puts "r = " + str(r); #puts len(r.gens()) s1,s2,s3,a,x,y = r.gens(); one = r.one(); puts "one = " + str(one); puts "s1 = " + str(s1); puts "s2 = " + str(s2); puts "s3 = " + str(s3); puts "a = " + str(a); puts "x = " + str(x); puts "y = " + str(y); #brel = [ a**2 - a, x**2 - x, y**2 - y ]; brel = [ x**2 - x, y**2 - y ]; #puts "brel = " + str(brel[0]) + ", " + str(brel[1]) + ", " + str(brel[2]); puts "brel = " + str(brel[0]) + ", " + str(brel[1]); pl = [ ( one + s1 + s2 ) * ( x*y + x + y ), s1 * x + s1, a * y + a, x * y ]; pl = pl + brel; startLog(); f = ParamIdeal.new(r,"",pl); puts "Ideal: " + str(f); gb = f.regularGB(); puts "boolean GB: " + str(gb); #ss = gb.stringSlice(); #puts "regular string slice: " + str(ss); terminate(); #sys.exit(); jas-2.5/examples/nabeshima_cgbF01.py0000644000175000017500000000157011045305426017547 0ustar giovannigiovanni# # jython examples for jas. # $Id: nabeshima_cgbF01.py 1977 2008-08-03 10:40:23Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # Nabashima, ISSAC 2007, example Ex-4.3 # integral function coefficients r = Ring( "IntFunc(a, b) (y,x) L" ); print "Ring: " + str(r); print; ps = """ ( ( x y + x ), ( { a } x^2 + y + 2 ), ( { b } x y + y ) ) """; #startLog(); f = r.paramideal( ps ); print "ParamIdeal: " + str(f); print; gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/hawes2_gens.rb0000644000175000017500000000243611644356076016734 0ustar giovannigiovanni# # jruby examples for jas. # $Id: hawes2_gens.rb 3794 2011-10-09 17:39:11Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} require "examples/jas" #startLog(); # Hawes & Gibson example 2 # rational function coefficients #r = Ring.new( "IntFunc(a, c, b) (y2, y1, z1, z2, x) G" ); r = PolyRing.new( PolyRing.new(QQ(),"a, c, b",PolyRing.lex), "y2, y1, z1, z2, x", PolyRing.grad ); puts "Ring: " + str(r); puts; one,a,c,b,y2,y1,z1,z2,x = r.gens(); p1 = x + 2 * y1 * z1 + 3 * a * y1**2 + 5 * y1**4 + 2 * c * y1; p2 = x + 2 * y2 * z2 + 3 * a * y2**2 + 5 * y2**4 + 2 * c * y2; p3 = 2 * z2 + 6 * a * y2 + 20 * y2**3 + 2 * c; p4 = 3 * z1**2 + y1**2 + b; p5 = 3 * z2**2 + y2**2 + b; F = [p1,p2,p3,p4,p5]; g = r.ideal( "", F ); puts "Ideal: " + str(g); puts; rg = g.GB(); rg = g.GB(); rg = g.GB(); rg = g.GB(); puts "GB: " + str(rg); puts; bg = rg.isGB(); puts "isGB: " + str(bg); puts; p7 = ( x + 1 ) / ( x**2 - x + 1 ); puts "p7 = " + str(p7); p8 = ( x + 1 ) % ( x**2 - x + 1 ); puts "p8 = " + str(p8); startLog(); terminate(); #sys.exit(); jas-2.5/examples/squarefree_infinite.rb0000644000175000017500000000205211653336426020545 0ustar giovannigiovanni# # jruby examples for jas. # $Id: squarefree_infinite.rb 3822 2011-10-30 21:09:42Z kredel $ # require "examples/jas" # polynomial examples: squarefree: characteristic p, infinite r = PolyRing.new( RF(PolyRing.new(ZM(5,field=true),"u, v",PolyRing.lex)), "x y z",PolyRing.lex); puts "r = " + str(r); one,u,v,x,y,z = r.gens(); puts "one = " + str(one); puts "u = " + str(u); puts "v = " + str(v); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); puts "Ring: " + str(r); puts; a = r.random(k=1,l=3); b = r.random(k=1,l=3); c = r.random(k=1,l=3); if a.isZERO() a = x; end if b.isZERO() b = y; end if c.isZERO() c = z; end #f = a**2 * b**3 * c; f = b**5 * c; puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); puts "f = " + str(f); puts; t = System.currentTimeMillis(); F = r.squarefreeFactors(f); t = System.currentTimeMillis() - t; puts "factors:"; for g in F.keys() i = F[g]; puts "g = #{g}**#{i}"; end puts puts "factor time = " + str(t) + " milliseconds"; startLog(); terminate(); jas-2.5/examples/wa_32.py0000644000175000017500000000327512136720410015451 0ustar giovannigiovanni# # jython examples for jas. # $Id: wa_32.py 4381 2013-04-27 09:57:28Z kredel $ # import sys; from jas import SolvableRing from jas import startLog, terminate # WA_32 example rs = """ # solvable polynomials, Weyl algebra A_3,2: Rat(a,b,e1,e2,e3) G RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e1 ), ( e3 ), ( e2 ), ( e2 e3 - e2 ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( e1 e3^3 + e2^10 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) """; f = r.ideal( ps ); print "SolvableIdeal: " + str(f); print; startLog(); rg = f.leftGB(); print "seq left GB:", rg; print; if rg.isLeftGB(): print "is left GB"; else: print "is not left GB"; threads = 2; rg = f.parLeftGB(threads); # 2 threads print "par left GB:", rg; print; if rg.isLeftGB(): print "is left GB"; else: print "is not left GB"; #sys.exit(); rg = f.twosidedGB(); print "seq twosided GB:", rg; print; if rg.isLeftGB(): print "twosided GB is left GB"; else: print "twosided GB is not left GB"; if rg.isRightGB(): print "twosided GB is right GB"; else: print "twosided GB is not right GB"; if rg.isTwosidedGB(): print "is twosided GB"; else: print "is not twosided GB"; rg = f.parTwosidedGB(threads); print "par twosided GB:", rg; print; if rg.isLeftGB(): print "twosided GB is left GB"; else: print "twosided GB is not left GB"; if rg.isRightGB(): print "twosided GB is right GB"; else: print "twosided GB is not right GB"; if rg.isTwosidedGB(): print "is twosided GB"; else: print "is not twosided GB"; rg = f.rightGB(); print "seq right GB:", rg; print; if rg.isRightGB(): print "is right GB"; else: print "is not right GB"; terminate(); jas-2.5/examples/testunit.py0000644000175000017500000000063110407615210016406 0ustar giovannigiovanni# # test functionality of the jython interface to jas. # $Id: testunit.py 802 2006-03-20 21:11:37Z kredel $ # # test ideal Groebner bases execfile("examples/trinksTest.py") # test module Groebner bases execfile("examples/armbruster.py") # test solvable Groebner bases execfile("examples/wa_32.py") # test solvable module Groebner bases execfile("examples/solvablemodule.py") import sys; sys.exit(); jas-2.5/examples/optimize.py0000644000175000017500000000214310663360336016401 0ustar giovannigiovanni# # jython examples for jas. # $Id: optimize.py 1351 2007-08-23 19:32:46Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog # example from rose (modified) # optimal is # Rat(A46, U3, U4) # r = Ring( "Rat(U3,U4,A46) G" ); print "Ring: " + str(r); print; ps = """ ( ( U4^4 - 20/7 A46^2 ), ( A46^2 U3^4 + 7/10 A46 U3^4 + 7/48 U3^4 - 50/27 A46^2 - 35/27 A46 - 49/216 ), ( A46^5 U4^3 + 7/5 A46^4 U4^3 + 609/1000 A46^3 U4^3 + 49/1250 A46^2 U4^3 - 27391/800000 A46 U4^3 - 1029/160000 U4^3 + 3/7 A46^5 U3 U4^2 + 3/5 A46^6 U3 U4^2 + 63/200 A46^3 U3 U4^2 + 147/2000 A46^2 U3 U4^2 + 4137/800000 A46 U3 U4^2 - 7/20 A46^4 U3^2 U4 - 77/125 A46^3 U3^2 U4 - 23863/60000 A46^2 U3^2 U4 - 1078/9375 A46 U3^2 U4 - 24353/1920000 U3^2 U4 - 3/20 A46^4 U3^3 - 21/100 A46^3 U3^3 - 91/800 A46^2 U3^3 - 5887/200000 A46 U3^3 - 343/128000 U3^3 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; startLog(); o = f.optimize(); print "optimized Ideal: " + str(o); print; #rg = f.GB(); #print "Output:", rg; #print; org = o.GB(); print "opt Output:", org; print; jas-2.5/examples/cgb_0.rb0000644000175000017500000000150011642326232015455 0ustar giovannigiovanni# # jruby examples for jas. # $Id: cgb_0.rb 3792 2011-10-03 12:37:47Z kredel $ # require "examples/jas" # simple example for comprehensive GB # integral/rational function coefficients #r = Ring( "RatFunc(u,v) (x,y) L" ); #r = Ring.new( "IntFunc(u,v) (x,y) L" ); r = PolyRing.new( PolyRing.new(ZZ(),"(u,v)",PolyRing.lex),"(x,y)", PolyRing.lex ); puts "Ring: " + str(r); puts; ps = """ ( ( { v } x y + x ), ( { u } y^2 + x^2 ) ) """; f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; #sys.exit(); #startLog(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; #sys.exit(); #bg = gs.isCGBsystem(); #puts "isCGBsystem: " + str(bg); #puts; #sys.exit(); #startLog(); gs = f.CGB(); puts "CGB: " + str(gs); puts; #startLog(); #bg = gs.isCGB(); #puts "isCGB: " + str(bg); #puts; terminate(); #sys.exit(); jas-2.5/examples/integrate.rb0000644000175000017500000000166511773606716016516 0ustar giovannigiovanni# # jruby examples for jas. # $Id: integrate.rb 3969 2012-06-30 14:31:43Z kredel $ # require "examples/jas" #startLog(); # elementary integration r = PolyRing.new( QQ(), "x", PolyRing.lex ); puts "Ring: " + str(r); puts rf = RF(r); puts "Ring: " + str(rf.factory()); puts one,x = rf.gens(); #f = 1 / ( 1 + x**2 ); #f = x**2 / ( x**2 + 1 ); #f = 1 / ( x**2 - 2 ); #f = 1 / ( x**3 - 2 ); #f = ( x + 3 ) / ( x**2- 3 * x - 40 ); f = ( x**7 - 24 * x**4 - 4 * x**2 + 8 * x - 8 ) / ( x**8 + 6 * x**6 + 12 * x**4 + 8 * x**2 ); puts "f = " + str(f); puts; startLog(); t = System.currentTimeMillis(); e1 = r.integrate(f); t = System.currentTimeMillis() - t; puts "e1 = " + str(e1); puts "integration time = " + str(t) + " milliseconds"; puts; t = System.currentTimeMillis(); e2 = f.integrate(); t = System.currentTimeMillis() - t; puts "e2 = " + str(e2); puts "integration time = " + str(t) + " milliseconds"; puts; #startLog(); terminate(); jas-2.5/examples/tuzun.py0000644000175000017500000000112411525740106015717 0ustar giovannigiovanni# # jython examples for jas. # $Id: tuzun.py 3529 2011-02-13 11:28:06Z kredel $ # import sys; from jas import PolyRing, Ideal, ZZ from jas import startLog, terminate # tuzun, e-gb example r = PolyRing(ZZ(), "(t)" ); print "Ring: " + str(r); [one,t] = r.gens(); print "one: " + str(one); print "t: " + str(t); print; f1 = 2 * t + 1; f2 = t**2 + 1; F = [f1,f2]; I = r.ideal( list=F ); print "Ideal: " + str(I); print; #startLog(); G = I.eGB(); print "seq e-GB:", G; print "is e-GB:", G.iseGB(); print; p = f1 + 2*f2 - f1*f2 + f1**4; print "p:", p; n = G.eReduction(p); print "n:", n; jas-2.5/examples/factors_mod.rb0000644000175000017500000000445411773570014017022 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_mod.rb 3968 2012-06-30 12:24:45Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: factorization over Z_p #r = Ring( "Mod 1152921504606846883 (x) L" ); #r = Ring( "Mod 19 (x) L" ); #r = Ring( "Mod 19 (x) L" ); r = PolyRing.new( GF(19), "x", PolyRing.lex ); puts "Ring: " + str(r); puts #one,x = r.gens(); #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**4 - 1; f = x**2 + 1; #f = x**19 + x; #f = x**3 - x**2 + x - 1; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; #f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; #f = x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8; puts "f = ", f; puts; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; puts "G = ", str(G.map{ |h,i| str(h)+"**"+str(i)+" " }); #puts "G = ", G; #puts "factor time =", t, "milliseconds"; puts; puts "f = " + str(f); g = one; for h, i in G do if i > 1 then puts "h**i = " + str(h) + "**" + str(i); else puts "h = " + str(h); end h = h**i; g = g*h; end puts; #puts "g = ", g; if f == g then puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): true" ; else puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): " + str(f==g); end puts; #startLog(); terminate(); jas-2.5/examples/exterior.py0000644000175000017500000000502412136720410016371 0ustar giovannigiovanni# # jython examples for jas. # $Id: exterior.py 4381 2013-04-27 09:57:28Z kredel $ # from jas import SolvableRing # exterior calculus example # Hartley and Tuckey, 1993, # GB in Clifford and Grassmann algebras rs = """ # exterior calculus example: Rat(a,b,c,f,g,h,u,v,w,x,y,z) L RelationTable ( ( b ), ( a ), ( - a b ), ( c ), ( a ), ( - a c ), ( f ), ( a ), ( - a f ), ( g ), ( a ), ( - a g ), ( h ), ( a ), ( - a h ), ( u ), ( a ), ( - a u ), ( v ), ( a ), ( - a v ), ( w ), ( a ), ( - a w ), ( x ), ( a ), ( - a x ), ( y ), ( a ), ( - a y ), ( z ), ( a ), ( - a z ), ( c ), ( b ), ( - b c ), ( f ), ( b ), ( - b f ), ( g ), ( b ), ( - b g ), ( h ), ( b ), ( - b h ), ( u ), ( b ), ( - b u ), ( v ), ( b ), ( - b v ), ( w ), ( b ), ( - b w ), ( x ), ( b ), ( - b x ), ( y ), ( b ), ( - b y ), ( z ), ( b ), ( - b z ), ( f ), ( c ), ( - c f ), ( g ), ( c ), ( - c g ), ( h ), ( c ), ( - c h ), ( u ), ( c ), ( - c u ), ( v ), ( c ), ( - c v ), ( w ), ( c ), ( - c w ), ( x ), ( c ), ( - c x ), ( y ), ( c ), ( - c y ), ( z ), ( c ), ( - c z ), ( g ), ( f ), ( - f g ), ( h ), ( f ), ( - f h ), ( u ), ( f ), ( - f u ), ( v ), ( f ), ( - f v ), ( w ), ( f ), ( - f w ), ( x ), ( f ), ( - f x ), ( y ), ( f ), ( - f y ), ( z ), ( f ), ( - f z ), ( h ), ( g ), ( - g h ), ( u ), ( g ), ( - g u ), ( v ), ( g ), ( - g v ), ( w ), ( g ), ( - g w ), ( x ), ( g ), ( - g x ), ( y ), ( g ), ( - g y ), ( z ), ( g ), ( - g z ), ( u ), ( h ), ( - h u ), ( v ), ( h ), ( - h v ), ( w ), ( h ), ( - h w ), ( x ), ( h ), ( - h x ), ( y ), ( h ), ( - h y ), ( z ), ( h ), ( - h z ), ( v ), ( u ), ( - u v ), ( w ), ( u ), ( - u w ), ( x ), ( u ), ( - u x ), ( y ), ( u ), ( - u y ), ( z ), ( u ), ( - u z ), ( w ), ( v ), ( - v w ), ( x ), ( v ), ( - v x ), ( y ), ( v ), ( - v y ), ( z ), ( v ), ( - v z ), ( x ), ( w ), ( - w x ), ( y ), ( w ), ( - w y ), ( z ), ( w ), ( - w z ), ( y ), ( x ), ( - x y ), ( z ), ( x ), ( - x z ), ( z ), ( y ), ( - y z ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; # ( a b + c f + g h ), # ( u v + w x + y z ), # ( a v + w x + y z ), ps = """ ( ( a b + c f + g h ), ( u v + w x + y z ), ( a^2 ), ( b^2 ), ( c^2 ), ( f^2 ), ( g^2 ), ( h^2 ), ( u^2 ), ( v^2 ), ( w^2 ), ( x^2 ), ( y^2 ), ( z^2 ) ) """; f = r.ideal( ps ); print "SolvableIdeal: " + str(f); print; rg = f.leftGB(); print "seq left GB:", rg; print; #rg = f.twosidedGB(); #print "seq twosided GB:", rg; #print; #rg = f.rightGB(); #print "seq right GB:", rg; #print; jas-2.5/examples/polynomial.rb0000644000175000017500000000204411641577122016677 0ustar giovannigiovanni# # jruby examples for jas. # $Id: polynomial.rb 3788 2011-10-01 11:49:39Z kredel $ # require "examples/jas" # polynomial examples: gcd #r = Ring( "Mod 1152921504606846883 (x,y,z) L" ); #r = Ring( "Rat(x,y,z) L" ); #r = Ring( "C(x,y,z) L" ); r = Ring.new( "Z(x,y,z) L" ); puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); puts; a = r.random(); b = r.random(); c = r.random().abs(); #c = one; #a = 0; f = x * a + b * y**2 + one * z**7; puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); #puts "f = " + str(f); puts; ac = a * c; bc = b * c; puts "ac = " + str(ac); puts "bc = " + str(bc); puts; t = System.currentTimeMillis(); g = r.gcd(ac,bc); t = System.currentTimeMillis() - t; puts "g = " + str(g); #puts "gcd time =", t, "milliseconds"; d = r.gcd(g,c); puts "gcd time = " + str(t) + " milliseconds," + " isGcd(c,d): " + str(c==d); puts; #d = g / c; #m = g % c; #puts "d = ", d; #puts "m = ", m; #puts; #startLog(); terminate(); jas-2.5/examples/factors_mod_abs.py0000644000175000017500000000144011224463142017656 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_mod_abs.py 2717 2009-07-06 21:02:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import PolyRing, ZM, QQ from jas import terminate from jas import startLog # polynomial examples: factorization over Z_p r = PolyRing(ZM(1152921504606846883,field=True),"(x)",PolyRing.lex); #r = PolyRing(ZM(19),"x",PolyRing.lex ); #r = PolyRing(ZM(23),"x",PolyRing.lex ); print "Ring: " + str(r); print; [one,x] = r.gens(); #f = x**4 - 1; #f = x**3 + 1; f = x**3 - x - 1; print "f = ", f; print; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factorsAbsolute(f); t = System.currentTimeMillis() - t; print "G = ", G.toScript(); print "factor time =", t, "milliseconds"; #startLog(); terminate(); jas-2.5/examples/nabeshima_cgbF6.rb0000644000175000017500000000156611653002012017442 0ustar giovannigiovanni# # jruby examples for jas. # $Id: nabeshima_cgbF6.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Nabashima, ISSAC 2007, example F6 # integral function coefficients r = Ring.new( "IntFunc(a, b,c, d) (x) G" ); puts "Ring: " + str(r); puts; ps = """ ( ( x^4 + { a } x^3 + { b } x^2 + { c } x + { d } ), ( 4 x^3 + { 3 a } x^2 + { 2 b } x + { c } ) ) """; #startLog(); f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; bg = gs.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; #exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; bg = gs.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/gens_define.rb0000644000175000017500000000105011653324230016747 0ustar giovannigiovanni# # jruby examples for jas. # $Id: gens_define.rb 3821 2011-10-30 19:42:16Z kredel $ # #load "examples/jas.rb" require "examples/jas" # test auto defined generators startLog(); r = PolyRing.new( CC(), "(b,s,t,z,p,w)", PolyRing.lex ); puts "Ring: " + r.to_s; puts; puts "1 = " + str(r.one); puts "I = " + str(r.I); puts "b = " + str(r.b); puts "s = " + str(r.s); puts "t = " + str(r.t); puts "z = " + str(r.z); puts "p = " + str(r.p); puts "w = " + str(r.w); puts; x = r.b * r.w + ( r.s - r.t + r.one )**2 + r.z**5; puts "x = " + str(x**2); puts jas-2.5/examples/intprog3.py0000644000175000017500000000203610373614370016305 0ustar giovannigiovanni# # jython for jas example 3 integer programming. # $Id: intprog3.py 597 2006-02-12 11:16:09Z kredel $ # # CLO2, p374,a,b # 3 A + 2 B + C + D = 10 # 4 A + B + C = 5 # # max: 2 A + 3 B + C + 5 D # import sys; from jas import Ring from jas import Ideal #r = Ring( "Rat(w1,w2,w3,w4,z1,z2) W( (0,0,0,0,1,1),(-2,-3,-1,-5,0,0) )" ); #r = Ring( "Rat(w1,w2,w3,w4,z1,z2) W( (0,0,0,0,1,1),( 7, 3, 2, 1,0,0)*6 )" ); r = Ring( "Rat(w1,w2,w3,w4,z1,z2) W( (0,0,0,0,1,1),(40,15,11, 1,0,0) )" ); print "Ring: " + str(r); print; ps = """ ( ( z1^3 z2^4 - w1 ), ( z1^2 z2 - w2 ), ( z1 z2 - w3 ), ( z1 - w4 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; rg = f.GB(); print "seq Output:", rg; print; pf = """ ( ( z1^10 z2^5 ), ( z1^20 z2^14 ) ) """; fp = Ideal( r, pf ); print "Ideal: " + str(fp); print; nf = fp.NF(rg); print "NFs: " + str(nf); print; #rg = f.parGB(2); #print "par Output:", rg; #print; #f.distClient(); # starts in background #rg = f.distGB(2); #print "dist Output:", rg; #print; #sys.exit(); jas-2.5/examples/montes_ex111.py0000644000175000017500000000233311253240426016757 0ustar giovannigiovanni# # jython examples for jas. # $Id: montes_ex111.py 2811 2009-09-13 18:59:35Z kredel $ # import sys; from jas import PolyRing, QQ, RF from jas import Ideal from jas import startLog from jas import terminate # Montes JSC 2002, 33, 183-208, example 11.1 # integral function coefficients r = PolyRing( PolyRing(QQ(),"c, b, a",PolyRing.lex), "z,y,x", PolyRing.lex ); print "Ring: " + str(r); print; [one,c,b,a,z,y,x] = r.gens(); print "gens: ", [ str(f) for f in r.gens() ]; print; f1 = x + c * y + b * z + a; f2 = c * x + y + a * z + b; f3 = b * x + a * y + z + c; F = [f1,f2,f3]; print "F: ", [ str(f) for f in F ]; print; #startLog(); If = r.paramideal( "", list = F ); print "ParamIdeal: " + str(If); print; ## G = If.GB(); ## print "GB: " + str(G); ## print; ## sys.exit(); GS = If.CGBsystem(); GS = If.CGBsystem(); GS = If.CGBsystem(); print "CGBsystem: " + str(GS); print; bg = GS.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; terminate(); sys.exit(); CG = If.CGB(); print "CGB: " + str(CG); print; bg = CG.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); #------------------------------------------ #sys.exit(); jas-2.5/examples/u_sl_2_wa_1.py0000644000175000017500000000353512136720410016627 0ustar giovannigiovanni# # jython examples for jas. # $Id: u_sl_2_wa_1.py 4381 2013-04-27 09:57:28Z kredel $ # from jas import SolvableRing from jas import startLog, terminate from edu.jas.application import Ideal # U_sl_2 and WA_1 example rs1 = """ # solvable polynomials, U_sl_2 and Weyl algebra A_1: Rat(D,X,e,f,h) G|3| RelationTable ( ( f ), ( e ), ( e f - h ), ( h ), ( e ), ( e h + 2 e ), ( h ), ( f ), ( f h - 2 f ), ( X ), ( D ), ( D X + 1 ) ) """; rs1c = """ # solvable polynomials, Weyl algebra A_1: Rat(D,X) G RelationTable ( ( X ), ( D ), ( D X + 1 ) ) """; rs2 = """ # solvable polynomials, U_sl_2 and Weyl algebra A_1: Rat(e,f,h,D,X) G|2| RelationTable ( ( f ), ( e ), ( e f - h ), ( h ), ( e ), ( e h + 2 e ), ( h ), ( f ), ( f h - 2 f ), ( X ), ( D ), ( D X + 1 ) ) """; rs2c = """ # solvable polynomials, U_sl_2: Rat(e,f,h) G RelationTable ( ( f ), ( e ), ( e f - h ), ( h ), ( e ), ( e h + 2 e ), ( h ), ( f ), ( f h - 2 f ) ) """; ps = """ ( ( e - X ), ( f + D^2 X ), ( h - 2 D X ) ) """; startLog(); r1 = SolvableRing( rs1 ); r1c = SolvableRing( rs1c ); #print "SolvableRing: " + str(r1); #print "SolvableRing: " + str(r1c); print; it = r1.ideal( ps ); print "SolvableIdeal: " + str(it); print; # compute I_{\phi_t} \cap WA_1^opp x = it.leftGB(); print "seq left x:", x; y = Ideal(x.pset).intersect(r1c.ring); len = y.list.size(); print "seq left y: ", y; print "seq left y len: ", len; print; #------------------------------------- r2 = SolvableRing( rs2 ); r2c = SolvableRing( rs2c ); #print "SolvableRing: " + str(r2); #print "SolvableRing: " + str(r2c); print; ikt = r2.ideal( ps ); print "SolvableIdeal: " + str(ikt); print; # compute ker(\phi_t) x = ikt.leftGB(); print "seq left x:", x; y = Ideal(x.pset).intersect(r2c.ring); len = y.list.size(); print "seq left y: ", y; print "seq left y len: ", len; print; #------------------------------------- jas-2.5/examples/factors_poly.rb0000644000175000017500000000316711627521076017230 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_poly.rb 3755 2011-08-31 21:06:06Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: factorization cr = PolyRing.new( QQ(), "x", PolyRing.lex ); puts "Ring: " + str(cr); r = PolyRing.new( cr, "y,z", PolyRing.lex ); puts "Ring: " + str(r); puts one,x,y,z = r.gens(); #f = z * ( y + 1 )**2 * ( x**2 + x + 1 )**3; #f = z * ( y + 1 ) * ( x**2 + x + 1 ); #f = ( y + 1 ) * ( x**2 + x + 1 ); #f = ( y + z**2 ) * ( x**2 + x + 1 ); #f = x**4 * y + x**3 + z + x + z**2 + y * z**2; ## f = x**3 + ( ( y + 2 ) * z + 2 * y + 1 ) * x**2 \ ## + ( ( y + 2 ) * z**2 + ( y**2 + 2 * y + 1 ) * z + 2 * y**2 + y ) * x \ ## + ( y + 1 ) * z**3 + ( y + 1 ) * z**2 + ( y**3 + y**2 ) * z + y**3 + y**2; f = ( x + y * z + y + z + 1 ) * ( x**2 + ( y + z ) * x + y**2 + z**2 ); #f = ( x + y * z + y + z + 1 ) * ( x**2 + ( y + z ) * x + y**2 + 1 ); #f = ( x + y ) * ( x - y); puts "f = ", f; puts; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; puts "G = ", str(G.map{ |h,i| str(h)+"**"+str(i)+" " }); #puts "G = ", G; #puts "factor time =", t, "milliseconds"; puts; puts "f = " + str(f); g = one; for h, i in G do if i > 1 then puts "h**i = " + str(h) + "**" + str(i); else puts "h = " + str(h); end h = h**i; g = g*h; end puts; #puts "g = ", g; if f == g then puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): true" ; else puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): " + str(f==g); end puts; #startLog(); terminate(); jas-2.5/examples/trinks7.jas0000644000175000017500000000040610653077260016267 0ustar giovannigiovanni# trinks 7 (B,S,T,Z,P,W) L ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B**3 ), ( 99 W - 11 B S + 3 B**2 ), ( B**2 + 33/50 B + 2673/10000 ) ) jas-2.5/examples/primes.rb0000644000175000017500000000164212040773636016020 0ustar giovannigiovanni# # jruby examples for jas. # $Id: primes.rb 4262 2012-10-21 13:24:47Z kredel $ # require "examples/jas" # example for prime numbers # pl = PrimeList.new(PrimeList::Range.small); puts "pl: " + str(pl); puts; pp = ""; for i in 0..pl.size()+10 do pp = pp + " " + str(pl.get(i)) end puts "pp: " + pp; puts; pl = PrimeList.new(PrimeList::Range.low); puts "pl: " + str(pl); puts; pp = ""; for i in 0..pl.size()+10 do pp = pp + " " + str(pl.get(i)) end puts "pp: " + pp; puts; pl = PrimeList.new(PrimeList::Range.medium); puts "pl: " + str(pl); puts; pp = ""; for i in 0..pl.size()+10 do pp = pp + " " + str(pl.get(i)) end puts "pp: " + pp; puts; pl = PrimeList.new(PrimeList::Range.large); puts "pl: " + str(pl); puts; pp = ""; for i in 0..pl.size()+10 do pp = pp + " " + str(pl.get(i)) end puts "pp: " + pp; puts; #pl = PrimeList.new(PrimeList::Range.mersenne); #puts "pl: " + str(pl); #puts; jas-2.5/examples/katsura9m.jas0000644000175000017500000000531212042562416016603 0ustar giovannigiovanni#Katsura equations for N = 9: #Mod 2^127-1: 39 digits, Mersenne prime 12: Mod 170141183460469231731687303715884105727 #Mod 2^3217-1: 969 digits Mersenne prime 18: Mod 259117086013202627776246767922441530941818887553125427303974923161874019266586362086201209516800483406550695241733194177441689509238807017410377709597512042313066624082916353517952311186154862265604547691127595848775610568757931191017711408826252153849035830401185072116424747461823031471398340229288074545677907941037288235820705892351068433882986888616658650280927692080339605869308790500409503709875902119018371991620994002568935113136548829739112656797303241986517250116412703509705427773477972349821676443446668383119322540099648994051790241624056519054483690809616061625743042361721863339415852426431208737266591962061753535748892894599629195183082621860853400937932839420261866586142503251450773096274235376822938649407127700846077124211823080804139298087057504713825264571448379371125032081826126566649084251699453951887789613650248405739378594599444335231188280123660406262468609212150349937584782292237144339628858485938215738821232393687046160677362909315071 #Mod 170141183460469231731687303715884105727 #Mod 23 #Mod 32003 Mod 536870909 #Mod 4294967291 #Mod 9223372036854775783 (u9,u8,u7,u6,u5,u4,u3,u2,u1,u0) G ( u9*u9 + u8*u8 + u7*u7 + u6*u6 + u5*u5 + u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 + u5*u5 + u6*u6 + u7*u7 + u8*u8 + u9*u9 - u0, u9*0 + u8*u9 + u7*u8 + u6*u7 + u5*u6 + u4*u5 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 + u5*u4 + u6*u5 + u7*u6 + u8*u7 + u9*u8 - u1, u9*0 + u8*0 + u7*u9 + u6*u8 + u5*u7 + u4*u6 + u3*u5 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 + u5*u3 + u6*u4 + u7*u5 + u8*u6 + u9*u7 - u2, u9*0 + u8*0 + u7*0 + u6*u9 + u5*u8 + u4*u7 + u3*u6 + u2*u5 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 + u5*u2 + u6*u3 + u7*u4 + u8*u5 + u9*u6 - u3, u9*0 + u8*0 + u7*0 + u6*0 + u5*u9 + u4*u8 + u3*u7 + u2*u6 + u1*u5 + u0*u4 + u1*u3 + u2*u2 + u3*u1 + u4*u0 + u5*u1 + u6*u2 + u7*u3 + u8*u4 + u9*u5 - u4, u9*0 + u8*0 + u7*0 + u6*0 + u5*0 + u4*u9 + u3*u8 + u2*u7 + u1*u6 + u0*u5 + u1*u4 + u2*u3 + u3*u2 + u4*u1 + u5*u0 + u6*u1 + u7*u2 + u8*u3 + u9*u4 - u5, u9*0 + u8*0 + u7*0 + u6*0 + u5*0 + u4*0 + u3*u9 + u2*u8 + u1*u7 + u0*u6 + u1*u5 + u2*u4 + u3*u3 + u4*u2 + u5*u1 + u6*u0 + u7*u1 + u8*u2 + u9*u3 - u6, u9*0 + u8*0 + u7*0 + u6*0 + u5*0 + u4*0 + u3*0 + u2*u9 + u1*u8 + u0*u7 + u1*u6 + u2*u5 + u3*u4 + u4*u3 + u5*u2 + u6*u1 + u7*u0 + u8*u1 + u9*u2 - u7, u9*0 + u8*0 + u7*0 + u6*0 + u5*0 + u4*0 + u3*0 + u2*0 + u1*u9 + u0*u8 + u1*u7 + u2*u6 + u3*u5 + u4*u4 + u5*u3 + u6*u2 + u7*u1 + u8*u0 + u9*u1 - u8, u9 + u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 + u5 + u6 + u7 + u8 + u9 - 1 ) jas-2.5/examples/machines.localhost0000644000175000017500000000041412034255140017655 0ustar giovannigiovanni# maschines file for jas for junit tests localhost:4712 # first host is master on different local port localhost:4711 # second host with port #localhost:4711 # third host with port #localhost:4711 # last host with port #localhost:4711 # ignored host # eof jas-2.5/examples/factors_poly.py0000644000175000017500000000301111624206726017240 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_poly.py 3748 2011-08-21 13:53:26Z kredel $ # from java.lang import System from java.lang import Integer from jas import PolyRing, QQ from jas import terminate from jas import startLog # polynomial examples: factorization cr = PolyRing(QQ(),"x",PolyRing.lex ); print "Ring cr: " + str(cr); r = PolyRing(cr,"y,z",PolyRing.lex ); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); #f = z * ( y + 1 )**2 * ( x**2 + x + 1 )**3; #f = z * ( y + 1 ) * ( x**2 + x + 1 ); #f = ( y + 1 ) * ( x**2 + x + 1 ); #f = ( y + z**2 ) * ( x**2 + x + 1 ); #f = x**4 * y + x**3 + z + x + z**2 + y * z**2; ## f = x**3 + ( ( y + 2 ) * z + 2 * y + 1 ) * x**2 \ ## + ( ( y + 2 ) * z**2 + ( y**2 + 2 * y + 1 ) * z + 2 * y**2 + y ) * x \ ## + ( y + 1 ) * z**3 + ( y + 1 ) * z**2 + ( y**3 + y**2 ) * z + y**3 + y**2; f = ( x + y * z + y + z + 1 ) * ( x**2 + ( y + z ) * x + y**2 + z**2 ); #f = ( x + y * z + y + z + 1 ) * ( x**2 + ( y + z ) * x + y**2 + 1 ); #f = ( x + y ) * ( x - y); print "f = ", f; print; startLog(); t = System.currentTimeMillis(); G = r.factors(f); t = System.currentTimeMillis() - t; print "G = ", G; #print "factor time =", t, "milliseconds"; g = one; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/montes_ex113.rb0000644000175000017500000000226211653002012016724 0ustar giovannigiovanni# # jruby examples for jas. # $Id: montes_ex113.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Montes JSC 2002, 33, 183-208, example 11.3 # integral function coefficients R = PolyRing.new( PolyRing.new(QQ(),"r, l, z",PolyRing.lex), "c1, c2, s1, s2", PolyRing.lex ); puts "Ring: " + str(R); puts; one,r,l,z,c1,c2,s1,s2 = R.gens(); puts "gens: " + r.gens().each{ |f| str(f) }.join(","); puts; f1 = r - c1 + l * ( s1 * s2 - c1 * c2 ); f2 = z - s1 - l * ( s1 * c2 + s2 * c1 ); f3 = s1**2 + c1**2 - 1; f4 = s2**2 + c2**2 - 1; F = [f1,f2,f3,f4]; puts "F: " + F.each{ |f| str(f) }.join(","); puts; startLog(); If = R.paramideal( "", list = F ); puts "ParamIdeal: " + str(If); puts; ## G = If.GB(); ## puts "GB: " + str(G); ## puts; ## sys.exit(); GS = If.CGBsystem(); #GS = If.CGBsystem(); #GS = If.CGBsystem(); puts "CGBsystem: " + str(GS); puts; bg = GS.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; #terminate(); #exit(); CG = If.CGB(); puts "CGB: " + str(CG); puts; bg = CG.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/vw.jas0000644000175000017500000000023210653077260015317 0ustar giovannigiovanni#Weispfenning-94, from SymbolicData: (x, y, z) L ( y^4+x*y^2*z+x^2-2*x*y+y^2+z^2, x*y^4+y*z^4-2*x^2*y-3, -x^3*y^2+x*y*z^3+y^4+x*y^2*z-2*x*y ) jas-2.5/examples/katsura2.jas0000644000175000017500000000024311353207070016411 0ustar giovannigiovanni#Katsura equations for N = 2: (u2,u1,u0) L ( u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 - u0, u2*0 + u1*u2 + u0*u1 + u1*u0 + u2*u1 - u1, u2 + u1 + u0 + u1 + u2 - 1 ) jas-2.5/examples/squarefree_poly.py0000644000175000017500000000205011226363734017744 0ustar giovannigiovanni# # jython examples for jas. # $Id: squarefree_poly.py 2740 2009-07-12 13:40:44Z kredel $ # from java.lang import System from java.lang import Integer from jas import PolyRing, QQ, ZM, ZZ from jas import terminate from jas import startLog # polynomial examples: squarefree: characteristic 0 #r = PolyRing(PolyRing(QQ(),"u,v",PolyRing.lex),"x, y",PolyRing.lex) #r = PolyRing(PolyRing(ZZ(),"u,v",PolyRing.lex),"x, y",PolyRing.lex) r = PolyRing(PolyRing(ZM(7),"u,v",PolyRing.lex),"x, y",PolyRing.lex) print "Ring: " + str(r); print; [one,u,v,x,y] = r.gens(); a = r.random(k=1,l=3); b = r.random(k=1,l=3); c = r.random(k=1,l=3); if a.isZERO(): a = x; if b.isZERO(): b = y; if c.isZERO(): c = y; f = a**2 * c**3 * b; print "a = ", a; print "b = ", b; print "c = ", c; print "f = ", f; print; t = System.currentTimeMillis(); F = r.squarefreeFactors(f); t = System.currentTimeMillis() - t; print "factors:"; for g in F.keys(): i = F[g]; print "g = %s**%s" % (g,i); print print "factor time =", t, "milliseconds"; #startLog(); terminate(); jas-2.5/examples/alg_stat_1.py0000644000175000017500000000216612020207644016553 0ustar giovannigiovanni# # jython examples for jas. # $Id: alg_stat_1.py 4145 2012-08-31 19:25:24Z kredel $ # import sys; from jas import Ring, PolyRing, Ideal from jas import QQ, ZZ from jas import startLog, terminate # example: Algebraic Statistics # Drton, Sturmfels, Sullivant, example 2.1.3 #r = PolyRing(QQ(),"l1,l2",PolyRing.grad); r = PolyRing(QQ(),"l1,l2",PolyRing.lex); print "Ring: " + str(r); print; print one,l1,l2; u0 = 3; u1 = 5; u2 = 7; u12 = 11; f1 = (u1+u12)*(l1+l2+2)*(l1+1)*(l1+l2+1)\ + (u12)*l1*(l1+1)*(l1+l2+1)\ - (u2+u12)*l1*(l1+l2+2)*(l1+l2+1)\ - (u0+u1+u2+u12)*l1*(l1+l2+2)*(l1+1) ; f2 = (u2+u12)*(l1+l2+2)*(l2+1)*(l1+l2+1)\ + (u12)*l2*(l2+1)*(l1+l2+1)\ - (u1+u12)*l2*(l1+l2+2)*(l1+l2+1)\ - (u0+u1+u2+u12)*l2*(l1+l2+2)*(l2+1) ; print f1; print f2; print h = l1*l2*(l1+1)*(l2+1)*(l1+l2+1)*(l1+l2+2); print h; print F = r.ideal(list=[f1,f2]); print F; print H = r.ideal(list=[h]); print H; print G = F.GB(); print G; print #startLog(); Q = G.sat(H); print Q; print #D = Q.radicalDecomp(); #print D; #print R = Q.realRoots(); print R; print print; #startLog(); terminate(); #sys.exit(); jas-2.5/examples/word_simple.rb0000644000175000017500000000440412023147024017027 0ustar giovannigiovanni# # jruby examples for jas. # $Id: word_simple.rb 4183 2012-09-09 17:12:52Z kredel $ # #load "examples/jas.rb" require "examples/jas" # non-commutative polynomial examples: simple test r = WordPolyRing.new(QQ(),"x,y"); puts "WordPolyRing: " + str(r); puts; one,x,y = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts; f1 = x*y - 1/10; f2 = y*x + x + y; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts; c1 = f1 * f2; c2 = f2 * f1; s = c1 - c2; puts "c1 = " + str(c1); puts "c2 = " + str(c2); puts "s = " + str(s); puts; ff = r.ideal( "", [f1,f2] ); puts "ff = " + str(ff); puts; #startLog(); gg = ff.GB(); puts "gg = " + str(gg); puts "isGB(gg) = " + str(gg.isGB()); puts; ff = r.ideal( "", [f1,f2,c1,c2,s] ); puts "ff = " + str(ff); puts; gg = ff.GB(); puts "gg = " + str(gg); puts "isGB(gg) = " + str(gg.isGB()); puts; p = r.random(3,6,4); puts "p = " + str(p); puts; pp = p**5; puts "pp = " + str(pp.to_s.length); puts "p == pp: " + str(p == pp); puts "pp == pp: " + str(pp == pp); puts "pp-pp == 0: " + str(pp-pp == 0); puts; #exit(0); ri = WordPolyRing.new(ZZ(),"x,y"); puts "WordPolyRing: " + str(ri); puts; one,x,y = ri.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts; f1 = x*y - 10; f2 = y*x + x + y; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts; c1 = f1 * f2; c2 = f2 * f1; s = c1 - c2; puts "c1 = " + str(c1); puts "c2 = " + str(c2); puts "s = " + str(s); puts; fi = ri.ideal( "", [f1,f2] ); puts "fi = " + str(fi); puts; #not implemented: #Gi = Fi.GB(); #puts "Gi = " + str(Gi); #puts "isGB(Gi) = " + str(Gi.isGB()); #puts; #exit(0); rp = WordPolyRing.new(GF(23),"x,y"); puts "WordPolyRing: " + str(rp); puts; one,x,y = rp.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts; f1 = x*y - 10; f2 = y*x + x + y; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts; c1 = f1 * f2; c2 = f2 * f1; s = c1 - c2; s1 = 22 * y*x*x*y + x*y*y*x + 22 * y*x*y + x*y*y + x*y*x + 22 * x*x*y; puts "c1 = " + str(c1); puts "c2 = " + str(c2); puts "s = " + str(s); puts "s1 = " + str(s1); puts "s == s1: " + str(s==s1); puts; fp = rp.ideal( "", [f1,f2] ); puts "fp = " + str(fp); puts; gp = fp.GB(); puts "gp = " + str(gp); puts "isGB(gp) = " + str(gp.isGB()); puts; jas-2.5/examples/katsura8.jas0000644000175000017500000000233511353223320016417 0ustar giovannigiovanni#Katsura equations for N = 8: (u8,u7,u6,u5,u4,u3,u2,u1,u0) G ( u8*u8 + u7*u7 + u6*u6 + u5*u5 + u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 + u5*u5 + u6*u6 + u7*u7 + u8*u8 - u0, u8*0 + u7*u8 + u6*u7 + u5*u6 + u4*u5 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 + u5*u4 + u6*u5 + u7*u6 + u8*u7 - u1, u8*0 + u7*0 + u6*u8 + u5*u7 + u4*u6 + u3*u5 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 + u5*u3 + u6*u4 + u7*u5 + u8*u6 - u2, u8*0 + u7*0 + u6*0 + u5*u8 + u4*u7 + u3*u6 + u2*u5 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 + u5*u2 + u6*u3 + u7*u4 + u8*u5 - u3, u8*0 + u7*0 + u6*0 + u5*0 + u4*u8 + u3*u7 + u2*u6 + u1*u5 + u0*u4 + u1*u3 + u2*u2 + u3*u1 + u4*u0 + u5*u1 + u6*u2 + u7*u3 + u8*u4 - u4, u8*0 + u7*0 + u6*0 + u5*0 + u4*0 + u3*u8 + u2*u7 + u1*u6 + u0*u5 + u1*u4 + u2*u3 + u3*u2 + u4*u1 + u5*u0 + u6*u1 + u7*u2 + u8*u3 - u5, u8*0 + u7*0 + u6*0 + u5*0 + u4*0 + u3*0 + u2*u8 + u1*u7 + u0*u6 + u1*u5 + u2*u4 + u3*u3 + u4*u2 + u5*u1 + u6*u0 + u7*u1 + u8*u2 - u6, u8*0 + u7*0 + u6*0 + u5*0 + u4*0 + u3*0 + u2*0 + u1*u8 + u0*u7 + u1*u6 + u2*u5 + u3*u4 + u4*u3 + u5*u2 + u6*u1 + u7*u0 + u8*u1 - u7, u8 + u7 + u6 + u5 + u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 + u5 + u6 + u7 + u8 - 1 ) jas-2.5/examples/armbruster.rb0000644000175000017500000000207311641155210016672 0ustar giovannigiovanni# # jruby examples for jas. # $Id: armbruster.rb 3784 2011-09-29 20:52:24Z kredel $ # require "examples/jas" # Armbruster module example r = CommutativeModule.new( "Rat(u,v,l) L" ); puts "Module: " + str(r); puts; ps = """ ( ( ( 1 ), ( 2 ), ( 0 ), ( l^2 ) ), ( ( 0 ), ( l + 3 v ), ( 0 ), ( u ) ), ( ( 1 ), ( 0 ), ( 0 ), ( l^2 ) ), ( ( l + v ), ( 0 ), ( 0 ), ( u ) ), ( ( l^2 ), ( 0 ), ( 0 ), ( v ) ), ( ( u ), ( 0 ), ( 0 ), ( v l + v^2 ) ), ( ( 1 ), ( 0 ), ( l + 3 v ), ( 0 ) ), ( ( l^2 ), ( 0 ), ( 2 u ), ( v ) ), ( ( 0 ), ( 1 ), ( l + v ), ( 0 ) ), ( ( 0 ), ( l^2 ), ( u ), ( 0 ) ), ( ( 0 ), ( v ), ( u l^2 ), ( 0 ) ), ( ( 0 ), ( v l + v^2 ), ( u^2 ), ( 0 ) ) ) """; f = SubModule.new( r, ps ); puts "SubModule: " + str(f); puts; rg = f.GB(); puts "seq Output: " + str(rg); puts; puts "isGB: " + str(rg.isGB()); jas-2.5/examples/roots_complex_ideal.py0000644000175000017500000000270311722152614020571 0ustar giovannigiovanni# # jython examples for jas. # $Id: roots_complex_ideal.py 3892 2012-02-25 12:35:24Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: complex roots over Q r = PolyRing(QQ(),"I,x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,I,x,y,z] = r.gens(); f1 = z - x - y * I; f2 = I**2 + 1; #f3 = z**3 - 2; f3 = z**3 - 2*I; print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print; F = r.ideal( list=[f1,f2,f3] ); print "F = ", F; print; startLog(); G = F.GB(); print "G = ", G; print; #terminate(); #sys.exit(); r = PolyRing(QQ(),"x,y",PolyRing.lex); print "Ring: " + str(r); print; [one,x,y] = r.gens(); # y**3 - 3 * I * x * y**2 - 3 * x**2 * y + I * x**3 - 2 * I = z**3 - 2 #fr = y**3 - 3 * x**2 * y; #fi = -3 * x * y**2 + x**3 - 2; # y**3 - 3 * I * x * y**2 - 3 * x**2 * y + I * x**3 + 2 = z**3 - 2 I fr = y**3 - 3 * x**2 * y - 2; fi = -3 * x * y**2 + x**3; print "fr = ", fr; print "fi = ", fi; print; F = r.ideal( list=[fr,fi] ); print "F = ", F; print; G = F.GB(); print "G = ", G; print; t = System.currentTimeMillis(); R = G.complexRoots(); t = System.currentTimeMillis() - t; print "R = ", R; print; print "complex roots: "; G.complexRootsPrint() print; print "complex roots time =", t, "milliseconds"; print; print "G = ", G; print; #startLog(); terminate(); jas-2.5/examples/jas.rb0000644000175000017500000031370012136725524015276 0ustar giovannigiovanni# $Id: jas.rb 4382 2013-04-27 10:41:24Z 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.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 =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 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.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 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.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.ufd.Quotient"; java_import "edu.jas.ufd.QuotientRing"; 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 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 ring = GenSolvablePolynomialRing.new(cf,nv,to,names); if rel != nil #puts "rel = " + str(rel); table = ring.table; ll = []; for x in rel if x.is_a? RingElem x = x.elem; end ll << x; end #puts "rel = " + str(ll); (0..ll.size-1).step(3) { |i| #puts "type " + str(ll[i].class); table.update( ll[i], ll[i+1], ll[i+2] ); } 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 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 jas-2.5/examples/roots_real_ideal.rb0000644000175000017500000000252311722155002020012 0ustar giovannigiovanni# # jruby examples for jas. # $Id: roots_real_ideal.rb 3893 2012-02-25 12:54:26Z kredel $ # require "examples/jas" # polynomial examples: complex roots over Q r = PolyRing.new(QQ(),"I,x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,I,x,y,z = r.gens(); f1 = z - x - y * I; f2 = I**2 + 1; #f3 = z**3 - 2; f3 = z**3 - 2*I; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; F = r.ideal( "", list=[f1,f2,f3] ); puts "F = " + str(F); puts; startLog(); G = F.GB(); puts "G = " + str(G); puts; #terminate(); #sys.exit(); r = PolyRing.new(QQ(),"x,y",PolyRing.lex); puts "Ring: " + str(r); puts; one,x,y = r.gens(); # y**3 - 3 * I * x * y**2 - 3 * x**2 * y + I * x**3 - 2 * I = z**3 - 2 #fr = y**3 - 3 * x**2 * y; #fi = -3 * x * y**2 + x**3 - 2; # y**3 - 3 * I * x * y**2 - 3 * x**2 * y + I * x**3 + 2 = z**3 - 2 I fr = y**3 - 3 * x**2 * y - 2; fi = -3 * x * y**2 + x**3; puts "fr = " + str(fr); puts "fi = " + str(fi); puts; F = r.ideal( "", list=[fr,fi] ); puts "F = " + str(F); puts; G = F.GB(); puts "G = " + str(G); puts; t = System.currentTimeMillis(); R = G.realRoots(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "real roots: "; G.realRootsPrint() puts; puts "real roots time = " + str(t) + " milliseconds"; puts; puts "G = " + str(G); puts; #startLog(); terminate(); jas-2.5/examples/squarefree_infinite.py0000644000175000017500000000221411224463142020560 0ustar giovannigiovanni# # jython examples for jas. # $Id: squarefree_infinite.py 2717 2009-07-06 21:02:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import PolyRing, QQ, ZM, RF from jas import terminate from jas import startLog # polynomial examples: squarefree: characteristic p, infinite r = PolyRing( RF(PolyRing(ZM(5,field=True),"u, v",PolyRing.lex)), "x y z",PolyRing.lex); print "r = " + str(r); [one,u,v,x,y,z] = r.gens(); print "one = " + str(one); print "u = " + str(u); print "v = " + str(v); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); print "Ring: " + str(r); print; a = r.random(k=1,l=3); b = r.random(k=1,l=3); c = r.random(k=1,l=3); if a.isZERO(): a = x; if b.isZERO(): b = y; if c.isZERO(): c = z; #f = a**2 * b**3 * c; f = b**5 * c; print "a = ", a; print "b = ", b; print "c = ", c; print "f = ", f; print; t = System.currentTimeMillis(); F = r.squarefreeFactors(f); t = System.currentTimeMillis() - t; print "factors:"; for g in F.keys(): i = F[g]; print "g = %s**%s" % (g,i); print print "factor time =", t, "milliseconds"; #startLog(); terminate(); jas-2.5/examples/0dim_real_roots.rb0000644000175000017500000000141711641147136017577 0ustar giovannigiovanni# # jruby examples for jas. # $Id: 0dim_real_roots.rb 3783 2011-09-29 20:00:31Z kredel $ # require "examples/jas" # polynomial examples: real roots over Q for zero dimensional ideals r = PolyRing.new(QQ(),"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); f1 = (x**2 - 5)*(x**2 - 3)**2; f2 = y**2 - 3; f3 = z**3 - x * y; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; F = r.ideal( "", [f1,f2,f3] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.realRoots(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "real roots = "; F.realRootsPrint() puts; puts "real roots time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/syzy3.py0000644000175000017500000000114011505613454015634 0ustar giovannigiovanni# # jython examples for jas. # $Id: syzy3.py 3450 2010-12-26 10:21:33Z kredel $ # from jas import Ring from jas import Ideal # ? example r = Ring( "Rat(x,y,z) L" ); print "Ring: " + str(r); print; ps = """ ( ( z^3 - y ), ( y z - x ), ( y^3 - x^2 z ), ( x z^2 - y^2 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; from edu.jas.gbmod import SyzygyAbstract; from edu.jas.poly import ModuleList; from edu.jas.gbmod import ModGroebnerBaseAbstract; R = SyzygyAbstract().resolution( f.pset ); for i in range(0,R.size()): print "\n %s. resolution" % (i+1); print "\n ", R[i]; jas-2.5/examples/u_sl_2_e.rb0000644000175000017500000000111312136716620016175 0ustar giovannigiovanni# # jruby examples for jas. # $Id: u_sl_2_e.rb 4380 2013-04-27 09:42:41Z kredel $ # require "examples/jas" # U(sl_2_e) example rs = """ # solvable polynomials, U(sl_2_e): Rat(e,h) G RelationTable ( ( h ), ( e ), ( e h + 2 e ) ) """; r = SolvableRing.new( rs ); puts "SolvableRing: " + str(r); puts; ps = """ ( ( e^2 + h^3 ) ) """; f = r.ideal( ps ); puts "SolvableIdeal: " + str(f); puts; rg = f.leftGB(); puts "seq left Output: " + str(rg); puts; rg = f.twosidedGB(); puts "seq twosided Output: " + str(rg); puts rg = f.rightGB(); puts "seq right GB: " + str(rg); puts; jas-2.5/examples/cgb_4.rb0000644000175000017500000000162011773563306015476 0ustar giovannigiovanni# # jruby examples for jas. # $Id: cgb_4.rb 3967 2012-06-30 11:45:11Z kredel $ # require "examples/jas" # 2 univariate polynomials of degree 2 example for comprehensive GB # integral/rational function coefficients r = PolyRing.new( PolyRing.new(QQ(),"a",PolyRing.lex),"x,y,z", PolyRing.lex ); puts "Ring: " + str(r); puts; #puts "gens: " + str(r.gens()); f1 = ( x**2 + a * y**2 - x ); f2 = ( a * x**2 + y**2 - y ); f3 = ( x - y ) * z - 1; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); f = r.paramideal( "", list=[f1,f2,f3] ); puts "ParamIdeal: " + str(f); puts; #sys.exit(); # long run time startLog(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; #sys.exit(); bg = gs.isCGBsystem(); puts "isCGBsystem: " + str(bg); puts; #sys.exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; #sys.exit(); #bg = gs.isCGB(); #puts "isCGB: " + str(bg); #puts; terminate(); jas-2.5/examples/roots_complex.py0000644000175000017500000000263411613034154017433 0ustar giovannigiovanni# # jython examples for jas. # $Id: roots_complex.py 3697 2011-07-24 15:21:16Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import terminate from jas import startLog from jas import QQ, DD, CR # polynomial examples: complex roots over Q #r = Ring( "Rat(x) L" ); #r = Ring( "Q(x) L" ); r = PolyRing( CR(QQ()), "x", PolyRing.lex ); print "Ring: " + str(r); print; [one,I,x] = r.gens(); print "one = ", one; print "I = ", I; print "x = ", x; print; f1 = x**3 - 2; f2 = ( x - I ) * ( x + I ) * ( x - 2 * I ) * ( x + (1,2) * I ); f3 = ( x**3 - 2 * I ); #f = f1 * f2 * f3; #f = f1 * f2; #f = f1 * f3; #f = f2 * f3; f = f2; print "f = ", f; print; startLog(); t = System.currentTimeMillis(); R = r.complexRoots(f); t = System.currentTimeMillis() - t; #print "R = ", [ a.elem.ring for a in R ]; print "R = ", [ a.elem.ring.getRoot() for a in R ]; print "complex roots time =", t, "milliseconds"; #terminate(); #sys.exit(); #eps = QQ(1,10) ** (DD().elem.DEFAULT_PRECISION-3); # not too big eps = QQ(1,10) ** 10; print "eps = ", eps; t = System.currentTimeMillis(); R = r.complexRoots(f,eps); t = System.currentTimeMillis() - t; #print "R = ", [ str(a) for a in R ]; print "R = ", [ a.elem.decimalMagnitude() for a in R ]; print "complex root refinement time =", t, "milliseconds"; #startLog(); terminate(); jas-2.5/examples/word_solvable.py0000644000175000017500000000434212023444260017375 0ustar giovannigiovanni# # jython examples for jas. # $Id: word_solvable.py 4186 2012-09-10 20:08:16Z kredel $ # #from java.lang import System from jas import WordRing, WordPolyRing, WordIdeal, PolyRing, SolvPolyRing from jas import terminate, startLog from jas import QQ, ZZ, GF, ZM # non-commutative polynomial examples: solvable polynomials example #r = WordPolyRing(QQ(),"a,b,e1,e2,e3"); r = WordPolyRing(QQ(),"a,b,e,f,g"); print "WordPolyRing: " + str(r); print; [one,a,b,e,f,g] = r.gens(); print "one = " + str(one); print "a = " + str(a); print "b = " + str(b); print "e = " + str(e); print "f = " + str(f); print "g = " + str(g); print; r1 = g * e - (e*g - e); r2 = g * f - (f*g - f); r3 = e * a - a * e; r4 = e * b - b * e; r5 = f * a - a * f; r6 = f * b - b * f; r7 = g * a - a * g; r8 = g * b - b * g; f1 = e * g**3 + f**10 - a; f2 = e**3 * f**2 + g; f3 = g**3 + g**2 - b; print "r1 = " + str(r1); print "r2 = " + str(r2); print "r3 = " + str(r3); print "r4 = " + str(r4); print "r5 = " + str(r5); print "r6 = " + str(r6); print "r7 = " + str(r7); print "r8 = " + str(r8); print "f1 = " + str(f1); print "f2 = " + str(f2); print "f3 = " + str(f3); print; F = r.ideal( list=[r1,r2,r3,r4,r5,r6,r7,r8,f1,f2,f3] ); #F = r.ideal( list=[r1,r2,f1,f2,f3] ); print "F = " + str(F); print; startLog(); G = F.GB(); print "G = " + str(G); print "isGB(G) = " + str(G.isGB()); print; # now as solvable polynomials p = PolyRing(QQ(),"a,b,e1,e2,e3"); #is automatic: [one,a,b,e1,e2,e3] = p.gens(); relations = [e3, e1, e1*e3 - e1, e3, e2, e2*e3 - e2]; print "relations: =", [ str(f) for f in relations ]; print; #rp = SolvPolyRing(QQ(), "a,b,e1,e2,e3", rel=relations); rp = SolvPolyRing(QQ(), "a,b,e1,e2,e3", PolyRing.lex, relations); print "SolvPolyRing: " + str(rp); print; print "gens =", [ str(f) for f in rp.gens() ]; #[one,a,b,e1,e2,e3] = rp.gens(); #[one,I,J,K,a,b,e1,e2,e3] = rp.gens(); f1 = e1 * e3**3 + e2**10 - a; f2 = e1**3 * e2**2 + e3; f3 = e3**3 + e3**2 - b; F = [ f1, f2, f3 ]; print "F =", [ str(f) for f in F ]; print I = rp.ideal( list=F ); print "SolvableIdeal: " + str(I); print; rgt = I.twosidedGB(); print "seq twosided GB:" + str(rgt); print "isTwosidedGB: " + str(rgt.isTwosidedGB()); print print "rgt: ", [ str(f) for f in rgt.list ]; print; jas-2.5/examples/hermite.py0000644000175000017500000000115311151514632016167 0ustar giovannigiovanni# # jython examples for jas. # $Id: hermite.py 2448 2009-02-26 13:31:07Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # hermite polynomial example # H(0) = 1 # H(1) = 2 * x # H(n) = 2 * x * H(n-1) - 2 * (n-1) * H(n-2) r = Ring( "Z(x) L" ); print "Ring: " + str(r); print; # sage like: with generators for the polynomial ring [one,x] = r.gens(); x2 = 2 * x; N = 10; H = [one,x2]; for n in range(2,N): h = x2 * H[n-1] - 2 * (n-1) * H[n-2]; H.append( h ); for n in range(0,N): print "H[%s] = %s" % (n,H[n]); print; #sys.exit(); jas-2.5/examples/trinks_sym.py0000644000175000017500000000421711225726560016747 0ustar giovannigiovanni# # jython examples for jas. # $Id: trinks_sym.py 2730 2009-07-10 21:06:57Z kredel $ # import sys; from jas import Ring from jas import PolyRing from jas import Ideal from jas import startLog from jas import terminate from jas import ZZ, QQ, ZM, DD, RF, CC #r = Ring( "Mod 19 (B,S,T,Z,P,W) L" ); #r = Ring( "Mod 1152921504606846883 (B,S,T,Z,P,W) L" ); # 2^60-93 #r = Ring( "Quat(B,S,T,Z,P,W) L" ); #r = Ring( "Z(B,S,T,Z,P,W) L" ); #r = Ring( "C(B,S,T,Z,P,W) L" ); #r = Ring( "IntFunc(e,f)(B,S,T,Z,P,W) L" ); #r = Ring( "Z(B,S,T,Z,P,W) L" ); #r = Ring( "Q(B,S,T,Z,P,W) L" ); #print "Ring: " + str(r); #print; #r = PolyRing(ZZ(),"B,S,T,Z,P,W",PolyRing.lex); #r = PolyRing(QQ(),"B,S,T,Z,P,W",PolyRing.lex); #r = PolyRing(CC(),"B,S,T,Z,P,W",PolyRing.lex); #r = PolyRing(DD(),"B,S,T,Z,P,W",PolyRing.lex); #r = PolyRing(ZM(19),"B,S,T,Z,P,W",PolyRing.lex); #r = PolyRing(ZM(1152921504606846883),"B,S,T,Z,P,W",PolyRing.lex); # 2^60-93 #rc = PolyRing(ZZ(),"e,f",PolyRing.lex); #rc = PolyRing(QQ(),"e,f",PolyRing.lex); #r = PolyRing(rc,"B,S,T,Z,P,W",PolyRing.lex); rqc = PolyRing(ZZ(),"e,f",PolyRing.lex); print "Q-Ring: " + str(rqc); print "rqc.gens() = ", [ str(f) for f in rqc.gens() ]; print; [pone,pe,pf] = rqc.gens(); r = PolyRing(RF(rqc),"B,S,T,Z,P,W",PolyRing.lex); print "Ring: " + str(r); print; # sage like: with generators for the polynomial ring print "r.gens() = ", [ str(f) for f in r.gens() ]; print; [one,e,f,B,S,T,Z,P,W] = r.gens(); #[one,B,S,T,Z,P,W] = r.gens(); #[one,I,B,S,T,Z,P,W] = r.gens(); f1 = 45 * P + 35 * S - 165 * B - 36; f2 = 35 * P + 40 * Z + 25 * T - 27 * S; f3 = 15 * W + 25 * S * P + 30 * Z - 18 * T - 165 * B**2; f4 = - 9 * W + 15 * T * P + 20 * S * Z; f5 = P * W + 2 * T * Z - 11 * B**3; f6 = 99 * W - 11 *B * S + 3 * B**2; f7 = 10000 * B**2 + 6600 * B + 2673; #all ok: f1 = f1 + e; #f7 = f7 + e * f6**0; #f7 = f7 + 5959345574908321469098512640906154241024000000**2 * f6; #f7 = f7 + 35555./332 * f1; F = [ f1, f2, f3, f4, f5, f6, f7 ]; #F = [ f1, f2, f3, f4, f5, f6 ]; #print "F = ", [ str(f) for f in F ]; I = r.ideal( "", list=F ); print "Ideal: " + str(I); print; #sys.exit(); rg = I.GB(); print "seq Output:", rg; print; terminate(); sys.exit(); jas-2.5/examples/powerseries.rb0000644000175000017500000000776311642052604017072 0ustar giovannigiovanni# # jruby examples for jas. # $Id: powerseries.rb 3790 2011-10-02 12:13:57Z kredel $ # require "examples/jas" # examples for power series # # rational number examples # psr = SeriesRing.new("Q(y)"); puts "psr: " + str(psr); puts; one = psr.one(); puts "one: " + str(one); #puts; zero = psr.zero(); puts "zero: " + str(zero); puts; r1 = psr.random(4); puts "r1: " + str(r1); #puts; puts "r1: " + str(r1); #puts; puts "r1-r1: " + str(r1-r1); puts; r2 = psr.random(4); puts "r2: " + str(r2); #puts; puts "r2: " + str(r2); #puts; puts "r2-r2: " + str(r2-r2); puts; #sys.exit(); r3 = r1 + r2; puts "r3: " + str(r3); puts; r4 = r1 * r2 + one; puts "r4: " + str(r4); puts; e = psr.exp(); puts "e: " + str(e); puts; r5 = r1 * r2 + e; puts "r5: " + str(r5); puts; #puts "psr.gens: ", [ str(i) for i in psr.gens() ]; one,y = psr.gens(); puts "y: " + str(y); puts; r6 = one - y; puts "r6: " + str(r6); puts; r7 = one / r6; puts "r7: " + str(r7); puts; s = psr.sin(); puts "s: " + str(s); puts; r8 = psr.gcd(y,s); puts "r8: " + str(r8); puts; s1 = s.evaluate( QQ(0) ); puts "s1: " + str(s1); puts; c = psr.cos(); puts "c: " + str(c); puts; c1 = c.evaluate( QQ(0) ); puts "c1: " + str(c1); puts; s2c2 = s*s+c*c; # sin^2 + cos^2 = 1 puts "s2c2: " + str(s2c2); puts; # # floating point examples # dr = SeriesRing.new("",nil,nil,DD()); puts "dr: " + str(dr); puts; de = dr.exp(); puts "de: " + str(de); puts; d0 = de.evaluate( DD(0) ); puts "d0: " + str(d0); #puts; d1 = de.evaluate( DD(0.5) ); puts "d1: " + str(d1); #puts; d01 = de.evaluate( DD(0.000000000000000001) ); puts "d01: " + str(d01); puts; #def f(a) # return a*a; #end # use lambdas: f = lambda { |a| a*a }; ps = psr.create(f); puts "ps: " + str(ps); puts; g = lambda { |a| a+a }; ps1 = psr.create(g); puts "ps1: " +str(ps1); puts; ps2 = ps * ps1; puts "ps2: " + str(ps2); puts; #exit(); h = lambda { |a| psr.ring.coFac.fromInteger( 3*a ) }; ps3 = psr.create(nil,h); puts "ps3: " + str(ps3); puts; ps4 = ps3 * ps1; puts "ps4: " + str(ps4); puts; # does not work, since get() is not known #def k(a) # if a > 0 # return get(a-1).multiply( psr.ring.coFac.fromInteger( 2*a ) ); # else # return psr.ring.coFac.fromInteger( 2*a ); # end #end #no#ps5 = psr.create(jfunc=k); #no#puts "ps5: ", ps5; #no#puts; class Mcoeff < Coefficients def initialize(cofac) super(); @coFac = cofac; end def generate(i) if i == 0 return @coFac.getZERO(); else if i == 1 return @coFac.getONE(); else c = get( i-2 ).negate(); return c.divide( @coFac.fromInteger(i) ).divide( @coFac.fromInteger(i-1) ); end end end end ps6 = psr.create(nil,nil, Mcoeff.new(psr.ring.coFac) ); puts "ps6: " + str(ps6); puts; ps7 = ps6 - s; puts "ps7: " + str(ps7); puts; #exit(); class Cosmap include UnivPowerSeriesMap # for interfaces use Module notations def initialize(cofac) @coFac = cofac; end def map(ps) return ps.negate().integrate( @coFac.getZERO() ).integrate( @coFac.getONE() ); end end ps8 = psr.fixPoint( Cosmap.new( psr.ring.coFac ) ); puts "ps8: " + str(ps8); puts; ps9 = ps8 - c; puts "ps9: " + str(ps9); puts; #exit(); # conversion from polynomials pr = Ring.new("Q(y) L"); puts "pr: " + str(pr); puts; one,yp = pr.gens(); p1 = one; p2 = one - yp; ps1 = psr.fromPoly(p1); ps2 = psr.fromPoly(p2); # rational function as power series: ps3 = ps1 / ps2; puts "p1: " + str(p1); puts "p2: " + str(p2); puts "ps1: " + str(ps1); puts "ps2: " + str(ps2); puts "ps3: " + str(ps3); puts; p1 = one * 2 + yp**3 - yp**5; p2 = one - yp**2 + yp**4; ps1 = psr.fromPoly(p1); ps2 = psr.fromPoly(p2); # rational function as power series: ps3 = ps1 / ps2; ps4 = ps3.integrate( QQ(1) ); ps5 = ps3.differentiate(); puts "p1: " + str(p1); puts "p2: " + str(p2); puts "ps1: " + str(ps1); puts "ps2: " + str(ps2); puts "ps3: " + str(ps3); puts "ps4: " + str(ps4); puts "ps5: " + str(ps5); puts; #exit(); jas-2.5/examples/prime-decomp.py0000644000175000017500000000154211376460372017127 0ustar giovannigiovanni# # jython examples for jas. # $Id: prime-decomp.py 3150 2010-05-24 11:20:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: ideal prime decomposition #r = Ring( "Rat(x) L" ); #r = Ring( "Q(x) L" ); r = PolyRing(QQ(),"x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); f1 = (x**2 - 5)**2; f2 = y**3 - x; f3 = z**2 - y * x; #print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print; F = r.ideal( list=[f2,f3] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); P = F.primeDecomp(); t1 = System.currentTimeMillis() - t; print "P = ", P; print; print "prime decomp time =", t1, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/legendre.py0000644000175000017500000000154011151514632016317 0ustar giovannigiovanni# # jython examples for jas. # $Id: legendre.py 2448 2009-02-26 13:31:07Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate from edu.jas.arith import BigRational # Legendre polynomial example # P(0) = 1 # P(1) = x # P(n) = 1/n [ (2n-1) * x * P(n-1) - (n-1) * P(n-2) ] r = Ring( "Q(x) L" ); #r = Ring( "C(x) L" ); print "Ring: " + str(r); print; # sage like: with generators for the polynomial ring [one,x] = r.gens(); N = 10; P = [one,x]; for n in range(2,N): p = (2*n-1) * x * P[n-1] - (n-1) * P[n-2]; r = (1,n); # no rational numbers in python #r = [(1,n)]; # no complex rational numbers in python #r = ((1,n),(0,1)); # no complex rational numbers in python p = r * p; P.append( p ); for n in range(0,N): print "P[%s] = %s" % (n,P[n]); print; #sys.exit(); jas-2.5/examples/u_so_3.py0000644000175000017500000000205412136720410015717 0ustar giovannigiovanni# # jython examples for jas. # $Id: u_so_3.py 4381 2013-04-27 09:57:28Z kredel $ # from jas import SolvableRing # U(so_3) example rs = """ # solvable polynomials, U(so_3): Rat(x,y,z) G RelationTable ( ( y ), ( x ), ( x y - z ), ( z ), ( x ), ( x z + y ), ( z ), ( y ), ( y z - x ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( x^2 + y^3 ) ) """; f = r.ideal( ps ); print "SolvableIdeal: " + str(f); print; rg = f.leftGB(); print "seq left GB:", rg; print; if rg.isLeftGB(): print "is left GB"; else: print "is not left GB"; rg = f.twosidedGB(); print "seq twosided GB:", rg; print; if rg.isLeftGB(): print "twosided GB is left GB"; else: print "twosided GB is not left GB"; if rg.isRightGB(): print "twosided GB is right GB"; else: print "twosided GB is not right GB"; if rg.isTwosidedGB(): print "is twosided GB"; else: print "is not twosided GB"; rg = f.rightGB(); print "seq right GB:", rg; print; if rg.isRightGB(): print "is right GB"; else: print "is not right GB"; jas-2.5/examples/u_sl_3_prod.py0000644000175000017500000000471612136720410016747 0ustar giovannigiovanni# # jython examples for jas. # $Id: u_sl_3_prod.py 4381 2013-04-27 09:57:28Z kredel $ # from jas import SolvableRing # U(sl_3) example rs = """ # solvable polynomials, U(sl_3): Rat(Xa,Xb,Xc,Ya,Yb,Yc,Ha,Hb) G RelationTable ( ( Xb ), ( Xa ), ( Xa Xb - Xc ), ( Ya ), ( Xa ), ( Xa Ya - Ha ), ( Yc ), ( Xa ), ( Xa Yc + Yb ), ( Ha ), ( Xa ), ( Xa Ha + 2 Xa ), ( Hb ), ( Xa ), ( Xa Hb - Xa), ( Yb ), ( Xb ), ( Xb Yb - Hb ), ( Yc ), ( Xb ), ( Xb Yc - Ya ), ( Ha ), ( Xb ), ( Xb Ha - Xb ), ( Hb ), ( Xb ), ( Xb Hb + 2 Xb ), ( Ya ), ( Xc ), ( Xc Ya + Xb ), ( Yb ), ( Xc ), ( Xc Yb - Xa ), ( Yc ), ( Xc ), ( Xc Yc - Ha - Hb ), ( Ha ), ( Xc ), ( Xc Ha + Xc ), ( Hb ), ( Xc ), ( Xc Hb + Xc ), ( Yb ), ( Ya ), ( Ya Yb + Yc ), ( Ha ), ( Ya ), ( Ya Ha - 2 Ya ), ( Hb ), ( Ya ), ( Ya Hb + Ya ), ( Ha ), ( Yb ), ( Yb Ha + Yb ), ( Hb ), ( Yb ), ( Yb Hb - 2 Yb ), ( Ha ), ( Yc ), ( Yc Ha - Yc ), ( Hb ), ( Yc ), ( Yc Hb - Yc ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( Xb + Yb ) ) """; # ( Xa + Xb + Xc + Ya + Yb + Yc + Ha + Hb ) f = r.ideal( ps ); print "SolvIdeal: " + str(f); print; fl = f.list; print "fl: ", fl; p = fl[0]; print "p: ", p; print; from java.lang import System p2 = p; n = 15; t = System.currentTimeMillis(); for i in range(1,n): p2 = p2.multiply(p); t1 = System.currentTimeMillis() -t; print "one product in %s ms" % t1; print "p^%s.length: " % n, p2.length(); print; p2 = p; t = System.currentTimeMillis(); for i in range(1,n): p2 = p2.multiply(p); t1 = System.currentTimeMillis() -t; print "one product in %s ms" % t1; print "p^%s.length: " % n, p2.length(); print; ps = """ ( ( Xa ), ( Xb ), ( Xc ), ( Ya ), ( Yb ), ( Yc ), ( Ha ), ( Hb ) ) """; f = r.ideal( ps ); #print "SolvableIdeal: " + str(f); #print; fl = f.list; Yb = fl[4]; p1 = Yb; Xb = fl[1]; p2 = Xb; n = 10; t = System.currentTimeMillis(); for i in range(1,n): p1 = p1.multiply(Yb); p2 = p2.multiply(Xb); p = p1.multiply(p2); t1 = System.currentTimeMillis() -t; print "products in %s ms" % t1; print "Xb^%s * Yb^%s: " % (n,n); #, p; print; pp = p; p1 = Yb; p2 = Xb; t = System.currentTimeMillis(); for i in range(1,n): p1 = p1.multiply(Yb); p2 = p2.multiply(Xb); p = p1.multiply(p2); t1 = System.currentTimeMillis() -t; print "products in %s ms" % t1; print "Xb^%s * Yb^%s: " % (n,n); #, p; print; print "pp == p: ", (pp == p); print; #print "SolvIdeal: " + str(f); #print; jas-2.5/examples/u_sl_2_f.py0000644000175000017500000000073012136720410016217 0ustar giovannigiovanni# # jython examples for jas. from jas import SolvableRing # U(sl_2_f) example rs = """ # solvable polynomials, U(sl_2_f): Rat(f,h) G RelationTable ( ( h ), ( f ), ( f h - 2 f ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; ps = """ ( ( h^2 + f^3 ) ) """; f = r.ideal( ps ); print "SolvableIdeal: " + str(f); print; rg = f.leftGB(); print "seq left Output:", rg; print; rg = f.twosidedGB(); print "seq twosided Output:", rg; print; jas-2.5/examples/gbs.py0000644000175000017500000000164011140646266015315 0ustar giovannigiovanni# # jython examples for jas. # $Id: gbs.py 2382 2009-01-30 18:53:42Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate # ? example #r = Ring( "Rat(t,x,y,z) L" ); #r = Ring( "Z(t,x,y,z) L" ); #r = Ring( "Mod 11(t,x,y,z) L" ); r = Ring( "Rat(t,x,y) L" ); print "Ring: " + str(r); print; ps = """ ( ( t - x - 2 y ), ( x^4 + 4 ), ( y^4 + 4 ) ) """; # ( y^4 + 4 x y^3 - 2 y^3 - 6 x y^2 + 1 y^2 + 6 x y + 2 y - 2 x + 3 ), # ( x^2 + 1 ), # ( y^3 - 1 ) # ( y^2 + 2 x y + 2 y + 2 x + 1 ), # ( y^4 + 4 x - 2 y^3 - 6 x + 1 y^2 + 6 x + 2 y - 2 x + 3 ), # ( t - x - 2 y ), # ( 786361/784 y^2 + 557267/392 y + 432049/784 ), # ( x^7 + 3 y x^4 + 27/8 x^4 + 2 y x^3 + 51/7 x^3 + 801/28 y + 1041/56 ) # ( x**2 + 1 ), # ( y**2 + 1 ) f = r.ideal( ps ); print "Ideal: " + str(f); print; #startLog(); rg = f.GB(); print "seq Output:", rg; print; terminate(); jas-2.5/examples/wa_34.jas0000644000175000017500000000033110653077260015600 0ustar giovannigiovanni# solvable polynomials, Weyl algebra A_3,4: (a,b,e1,e2,e3) L RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e1 ), ( e3 ), ( e2 ), ( e2 e3 + e2 ) ) ( ( e1 e3^3 + e2^10 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) jas-2.5/examples/all_rings.py0000644000175000017500000005775611724745324016542 0ustar giovannigiovanni# # jython examples for jas. # $Id: all_rings.py 3897 2012-03-04 20:04:36Z kredel $ # import sys; from jas import Ring, PolyRing, SolvPolyRing from jas import Ideal from jas import Module, SubModule, SolvableModule, SolvableSubModule from jas import startLog from jas import terminate from jas import ZZ, QQ, ZM, GF, DD, CC, Quat, Oct, AN, RealN, RF, RC, LC, RR, PS, MPS, Vec, Mat from edu.jas.arith import BigDecimal print "------- ZZ = BigInteger ------------"; z1 = ZZ(12345678901234567890); print "z1 = " + str(z1); z2 = z1**2 + 12345678901234567890; print "z2 = " + str(z2); print; print "------- QQ = BigRational ------------"; r1 = QQ(1,12345678901234567890); print "r1 = " + str(r1**3); r2 = r1**2 + (1,12345678901234567890); print "r2 = " + str(r2); print; print "------- ZM = ModInteger ------------"; m1 = ZM(19,12345678901234567890); print "m1 = " + str(m1); m2 = m1**2 + 12345678901234567890; print "m2 = " + str(m2); print; print "------- GF = ModInteger ------------"; m1 = GF(19,12345678901234567890); print "m1 = " + str(m1); m2 = m1**2 + 12345678901234567890; print "m2 = " + str(m2); print; print "------- DD = BigDecimal ------------"; d1 = DD(12345678901234567890); print "d1 = " + str(d1); d2 = (1/d1)**2; print "d2 = " + str(d2); print; print "------- CC = BigComplex ------------"; c1 = CC((1,2),(5,)); print "c1 = " + str(c1); c2 = (1/c1)**2; print "c2 = " + str(c2); c3 = CC(0,(1,)); c3 = 1/c3; print "c3 = " + str(c3); [one,I] = CC().gens(); print "one = " + str(one); print "I = " + str(I); c4 = c3 + 5 * I; print "c4 = " + str(c4); c5 = (-396,10201)-(80,10201)*I; print "c5 = " + str(c5); print; print "------- Quat = BigQuaternion ------------"; [oneQ,IQ,JQ,KQ] = Quat().gens(); print "oneQ = " + str(oneQ); print "IQ = " + str(IQ); print "JQ = " + str(JQ); print "KQ = " + str(KQ); q1 = 2 + 3 * IQ + 4 * JQ + 5 * KQ; print "q1 = " + str(q1); q2 = (1/q1)**2; print "q2 = " + str(q2); q3 = q2 * q1 * q1; print "q3 = " + str(q3); q4 = (-23,1458) + (-1,243)*IQ + (-4,729)*JQ + (-5,729)*KQ print "q4 = " + str(q4); q5 = q2 - q4; print "q5 = " + str(q5); print; print "------- Oct = BigOctonion ------------"; #print [ str(g) for g in Oct().gens() ]; [oneOR,IOR,JOR,KOR,oneOI,IOI,JOI,KOI] = Oct().gens(); print "oneOR = " + str(oneOR); print "IOR = " + str(IOR); print "JOR = " + str(JOR); print "KOR = " + str(KOR); print "oneOI = " + str(oneOI); print "IOI = " + str(IOI); print "JOI = " + str(JOI); print "KOI = " + str(KOI); o1 = 2 * oneOR + 3 * IOR + 4 * JOR + 5 * KOR + 6 * oneOI + 7 * IOI + 8 * JOI + 9 * KOI; print "o1 = " + str(o1); o2 = (1/o1)**2; print "o2 = " + str(o2); o3 = o2 * o1 * o1; print "o3 = " + str(o3); o4 = (-69,20164)*oneOR + (-3,20164)*IOR + (-1,5041)*JOR + (-5,20164)*KOR + (-3,10082)*oneOI + (-7,20164)*IOI + (-2,5041)*JOI + (-9,20164)*KOI; print "o4 = " + str(o4); o5 = o2 - o4; print "o5 = " + str(o5); print; print "------- PolyRing(ZZ(),\"x,y,z\") ---------"; r = PolyRing(ZZ(),"x,y,z",PolyRing.grad); print "r = " + str(r); [one,x,y,z] = r.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); p1 = 2 + 3 * x + 4 * y + 5 * z + ( x + y + z )**2; print "p1 = " + str(p1); p2 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + 5 * z + 4 * y + 3 * x + 2; print "p2 = " + str(p2); p3 = p1 - p2; print "p3 = " + str(p3); print "p3.factory() = " + str(p3.factory()); print; print "------- PolyRing(QQ(),\"x,y,z\") ---------"; r = PolyRing(QQ(),"x,y,z",PolyRing.grad); print "r = " + str(r); [one,x,y,z] = r.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); s1 = QQ(1,2) + QQ(2,3) * x + QQ(2,5) * y + ( x + y + z )**2; print "s1 = " + str(s1); s2 = (1,2) + (2,3) * x + (2,5) * y + ( x + y + z )**2; print "s2 = " + str(s2); s3 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + (2,5) * y + (2,3) * x + (1,2); print "s3 = " + str(s3); s4 = s1 - s3; print "s4 = " + str(s4); print "s4.factory() = " + str(s4.factory()); print; print "------- PolyRing(ZM(11),\"x,y,z\") ---------"; r = PolyRing(ZM(11),"x,y,z",PolyRing.grad); print "r = " + str(r); [one,x,y,z] = r.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); p1 = 12 + 13 * x + 14 * y + 15 * z + ( x + y + z )**2; print "p1 = " + str(p1); p2 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + 4 * z + 3 * y + 2 * x + 1; print "p2 = " + str(p2); p3 = p1 - p2; print "p3 = " + str(p3); print "p3.factory() = " + str(p3.factory()); print; print "------- PolyRing(DD(),\"x,y,z\") ---------"; r = PolyRing(DD(),"x,y,z",PolyRing.grad); print "r = " + str(r); [one,x,y,z] = r.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); p1 = 0.2 + 0.3 * x + 0.4 * y + 0.5 * z + ( x + y + z )**2; print "p1 = " + str(p1); p2 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + 0.5 * z + 0.40000000000000002220446049250313080847263336181641 * y + 0.29999999999999998889776975374843459576368331909180 * x + 0.200000000000000011102230246251565404236316680908203125; print "p2 = " + str(p2); p3 = p1 - p2; print "p3 = " + str(p3); print "p3.factory() = " + str(p3.factory()); print; print "------- PolyRing(CC(),\"x,y,z\") ---------"; r = PolyRing(CC(),"x,y,z",PolyRing.grad); print "r = " + str(r); [one,I,x,y,z] = r.gens(); print "one = " + str(one); print "I = " + str(I); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); s1 = CC((1,2)) + CC((2,3)) * x + 3 * I * y + ( x + y + z )**2; print "s1 = " + str(s1); #print "s1.factory() = " + str(s1.factory()); #print "s1.coefficients() = " + str(s1.coefficients()); s2 = ((1,2),) + ((2,3),) * x + 3 * I * y + ( x + y + z )**2; print "s2 = " + str(s2); #print "s2.factory() = " + str(s2.factory()); #print "s2.coefficients() = " + str(s2.coefficients()); s3 = z**2 + ((2,),) * y * z + ((2,),) * x * z + y**2 + ((2,),) * x * y + x**2 + ((0,),(3,)) * y + (( 2,3),) * x + ((1,2),); print "s3 = " + str(s3); #print "s3.factory() = " + str(s3.factory()); #print "s3.coefficients() = " + str(s3.coefficients()); s4 = s3 - s1; print "s4 = " + str(s4); print "s4.factory() = " + str(s4.factory()); print; print "------- PolyRing(Quat(),\"x,y,z\") ---------"; r = PolyRing(Quat(),"x,y,z",PolyRing.grad); print "r = " + str(r); [oneQ,IQ,JQ,KQ,x,y,z] = r.gens(); print "oneQ = " + str(oneQ); print "IQ = " + str(IQ); print "JQ = " + str(JQ); print "KQ = " + str(KQ); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); s1 = Quat((1,2)) + Quat((2,3)) * x + Quat((2,5)) * y + ( x + y + z )**2; print "s1 = " + str(s1); s2 = ((1,2),) + ((2,3),) * x + ((2,5),) * y + ( x + y + z )**2; print "s2 = " + str(s2); s3 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + (2,5) * y + (2,3) * x + (1,2); print "s3 = " + str(s3); s4 = s3 - s1; print "s4 = " + str(s4); print "s4.factory() = " + str(s4.factory()); print; print "------- PolyRing(Oct(),\"x,y,z\") ---------"; r = PolyRing(Oct(),"x,y,z",PolyRing.grad); print "r = " + str(r); [oneOR,IOR,JOR,KOR,oneOI,IOI,JOI,KOI,x,y,z] = r.gens(); print "oneOR = " + str(oneOR); print "IOR = " + str(IOR); print "JOR = " + str(JOR); print "KOR = " + str(KOR); print "oneOI = " + str(oneOI); print "IOI = " + str(IOI); print "JOI = " + str(JOI); print "KOI = " + str(KOI); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); s1 = Oct(Quat((1,2))) + Oct(Quat((2,3))) * x + Oct(Quat((2,5))) * y + ( x + y + z )**2; print "s1 = " + str(s1); s2 = QQ(1,2) + QQ(2,3) * x + QQ(2,5) * y + ( x + y + z )**2; print "s2 = " + str(s2); s3 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + (2,5) * y + (2,3) * x + (1,2); print "s3 = " + str(s3); s4 = s3 - s1; print "s4 = " + str(s4); print "s4.factory() = " + str(s4.factory()); print; print "------- AN(alpha**2 - 2) ---------"; r = PolyRing(QQ(),"alpha",PolyRing.lex); print "r = " + str(r); [e,a] = r.gens(); print "e = " + str(e); print "a = " + str(a); sqrt2 = a**2 - 2; print "sqrt2 = " + str(sqrt2); Qs2 = AN(sqrt2); print "Qs2 = " + str(Qs2.factory()); [one,alpha] = Qs2.gens(); print "one = " + str(one); print "alpha = " + str(alpha); b = alpha**2 - 2; print "b = " + str(b); c = 1 / alpha; print "c = " + str(c); Qs2x = AN(alpha**2 - 2); print "Qs2x = " + str(Qs2x.factory()); print; print "------- GF_17(alpha**2 - 2) ---------"; r = PolyRing(GF(17),"alpha",PolyRing.lex); print "r = " + str(r); [e,a] = r.gens(); print "e = " + str(e); print "a = " + str(a); sqrt2 = a**2 - 2; print "sqrt2 = " + str(sqrt2); Qs2 = AN(sqrt2); print "Qs2 = " + str(Qs2.factory()); [one,alpha] = Qs2.gens(); print "one = " + str(one); print "alpha = " + str(alpha); b = alpha**2 - 2; print "b = " + str(b); c = 1 / alpha; print "c = " + str(c); Qs2x = AN(alpha**2 - 2); print "Qs2x = " + str(Qs2x.factory()); print; print "------- RealN(alpha**2 - 2,(1,2) ---------"; r = PolyRing(QQ(),"alpha",PolyRing.lex); print "r = " + str(r); [e,a] = r.gens(); print "e = " + str(e); print "a = " + str(a); sqrt2 = a**2 - 2; print "sqrt2 = " + str(sqrt2); Qs2r = RealN(sqrt2,(1,2)); print "Qs2r = " + str(Qs2r.factory()); [one,alpha] = Qs2r.gens(); print "one = " + str(one); print "alpha = " + str(alpha); b = 7 * alpha - 10; print "b = " + str(b); print "b.factory() = " + str(b.factory()); print "sign(b) = " + str(b.signum()); print "magnitude(b) = " + str(BigDecimal(b.elem.magnitude())); c = 1 / b; print "c = " + str(c); print "sign(c) = " + str(c.signum()); print "magnitude(c) = " + str(BigDecimal(c.elem.magnitude())); Qs2rx = RealN( alpha**2 - 2, ( 1, 2 ) ); print "Qs2rx = " + str(Qs2rx.factory()); print; print "------- PolyRing(PolyRing(QQ(),\"a,b,c\"),\"x,y,z\") ---------"; r = PolyRing(QQ(),"a,b,c",PolyRing.grad); print "r = " + str(r); pr = PolyRing(r,"x,y,z",PolyRing.lex); print "pr = " + str(pr); [one,a,b,c,x,y,z] = pr.gens(); print "one = " + str(one); print "a = " + str(a); print "b = " + str(b); print "c = " + str(c); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); s1 = QQ(1,2) + ( QQ(2,3) - c ) * x + ( QQ(2,5) + a + b )**2 * y + ( x + y + z )**2; print "s1 = " + str(s1); s2 = (1,2) + ( (2,3) - c ) * x + ( (2,5) + a + b )**2 * y + ( x + y + z )**2; print "s2 = " + str(s2); s3 = z**2 + ( 2 ) * y * z + ( 2 ) * x * z + y**2 + ( 2 ) * x * y + ( b**2 + 2 * a * b + a**2 + (4,5) * b + (4,5) * a + (4,25) ) * y + x**2 - ( c - (2,3) ) * x + ( (1,2) ); print "s3 = " + str(s3); s4 = s1 + s2 - 2 * s3; print "s4 = " + str(s4); print "s4.factory() = " + str(s4.factory()); x = PolyRing(PolyRing(QQ(),"a, b, c",PolyRing.grad),"x, y, z",PolyRing.lex); print "x = " + str(x); print; print "------- RF(PolyRing(ZZ(),\"a,b,c\",PolyRing.lex)) ---------"; r = PolyRing(ZZ(),"a,b,c",PolyRing.lex); print "r = " + str(r); rf = RF(r); print "rf = " + str(rf.factory()); [one,a,b,c] = rf.gens(); print "one = " + str(one); print "a = " + str(a); print "b = " + str(b); print "c = " + str(c); q1 = a / b; print "q1 = " + str(q1); q2 = ( -2 * c**2 + 4 * b**2 + 4 * a**2 - 7 ); print "q2 = " + str(q2); q3 = ( -7 * b + 4 * a + 12 ); print "q3 = " + str(q3); q4 = q2 / q3; print "q4 = " + str(q4); q5 = ( 2 * c**2 - 4 * b**2 - 4 * a**2 + 7 ) / (7 * b - 4 * a - 12 ); print "q5 = " + str(q5); q6 = q4 - q5; print "q6 = " + str(q6); print "q6.factory() = " + str(q6.factory()); x = RF(PolyRing(ZZ(),"a, b, c",PolyRing.lex)); print "x = " + str(x.factory()); print; print "------- RC(PolyRing(QQ(),\"a,b,c\",PolyRing.lex)) ---------"; r = PolyRing(QQ(),"a,b,c",PolyRing.lex); print "r = " + str(r); [pone,pa,pb,pc] = r.gens(); print "pone = " + str(pone); print "pa = " + str(pa); print "pb = " + str(pb); print "pc = " + str(pc); g1 = pa**2 - 2; print "g1 = " + str(g1); g2 = pb**3 - 2; print "g2 = " + str(g2); g3 = pc**2 - pa*pb; print "g3 = " + str(g3); F = Ideal(r,list=[g1,g2,g3]); print "F = " + str(F); rc = RC(F); print "rc.factory() = " + str(rc.factory()); [one,a,b,c] = rc.gens(); print "one = " + str(one); print "a = " + str(a); print "b = " + str(b); print "c = " + str(c); r1 = a*b + c; print "r1 = " + str(r1); r2 = r1*r1*r1 - r1*r1 + one; print "r2 = " + str(r2); r3 = r2**3 - r1 + one; print "r3 = " + str(r3); r4 = ( -120 * a * b**2 * c + 606 * b**2 * c + 1917 * a * b * c + 400 * b * c - 132 * a * c - 673 * c + 432 * a * b**2 + 2130 * b**2 + 1436 * a * b - 72 * b + 100 * a - 1950 ); print "r4 = " + str(r4); r5 = r3 - r4; print "r5 = " + str(r5); print "r5.factory() = " + str(r5.factory()); r6 = 1/r2; print "r6 = " + str(r6); r7 = r6 * r2; print "r7 = " + str(r7); #F1 = Ideal(PolyRing(QQ(),"a, b, c",PolyRing.lex),list=[( pa**2 - 2 ), ( pb**3 - 2 ), ( pc**2 - pa * pb )]); #print "F1 = " + str(F1); rc1 = RC(Ideal(PolyRing(QQ(),"a, b, c",PolyRing.lex),list=[( a**2 - 2 ), ( b**3 - 2 ), ( c**2 - a * b )])); print "rc1.factory() = " + str(rc1.factory()); print; print "------- LC(PolyRing(QQ(),\"a,b,c\",PolyRing.lex)) ---------"; r = PolyRing(QQ(),"a,b,c",PolyRing.lex); print "r = " + str(r); [pone,pa,pb,pc] = r.gens(); print "pone = " + str(pone); print "pa = " + str(pa); print "pb = " + str(pb); print "pc = " + str(pc); g1 = pa**2 - 2; print "g1 = " + str(g1); g2 = pb**3 - 2; print "g2 = " + str(g2); g3 = pc**2 - pa*pb; print "g3 = " + str(g3); F = Ideal(r,list=[g1,g2,g3]); print "F = " + str(F); lc = LC(F); print "lc.factory() = " + str(lc.factory()); [one,a,b,c] = lc.gens(); print "one = " + str(one); print "a = " + str(a); print "b = " + str(b); print "c = " + str(c); #F1 = Ideal(PolyRing(QQ(),"a, b, c",PolyRing.lex),list=[( pa**2 - 2 ), ( pb**3 - 2 ), ( pc**2 - pa * pb )]); #print "F1 = " + str(F1); lc1 = LC(Ideal(PolyRing(QQ(),"a, b, c",PolyRing.lex),list=[( a**2 - 2 ), ( b**3 - 2 ), ( c**2 - a * b )])); print "lc1.factory() = " + str(lc1.factory()); l1 = a*b + c; print "l1 = " + str(l1); l2 = l1*l1*l1 - l1*l1 + one; print "l2 = " + str(l2); l3 = 1/l2; print "l3 = " + str(l3); l4 = l3 * l2; print "l4 = " + str(l4); l5 = a**2 - 2 + 1; print "l5 = " + str(l5); l6 = 1/l5; print "l6 = " + str(l6); l7 = (l1 * l2) / l2; print "l7 = " + str(l7); print; print "------- RR( [QQ(),ZM(19),DD()] ) ---------"; r = RR( [QQ(),ZM(19),DD()] ); print "r = " + str(r); print "r.factory() = " + str(r.factory()); rc1 = RR( [ QQ(), ZM(19), DD() ] ); print [ str(x) for x in r.gens() ]; print "rc1.factory() = " + str(rc1.factory()); [pg0,pg1,pg2] = r.gens(); print "pg0 = " + str(pg0); print "pg1 = " + str(pg1); print "pg2 = " + str(pg2); r1 = pg1 + pg2 + pg0; print "r1 = " + str(r1); r2 = r1 * r1 + 7 * r1; print "r2 = " + str(r2); r3 = r2**3; print "r3 = " + str(r3); r4 = 1/r3; print "r4 = " + str(r4); r5 = r4 - r1; print "r5 = " + str(r5); r6 = ( (-511,512)*pg0 + 17*pg1 - 0.998046875*pg2 ); print "r6 = " + str(r6); print; print "------- PS(QQ(),\"x\") ---------"; r = PS(QQ(),"x"); print "r = " + str(r); print "r.factory() = " + str(r.factory()); [one,x] = r.gens(); print "one = " + str(one); print "x = " + str(x); p1 = x**2 - 2; print "p1 = " + str(p1); p2 = x**3 - 2; print "p2 = " + str(p2); p3 = x**2 - p1 * p2; print "p3 = " + str(p3); p4 = - 4 + 3 * x**2 + 2 * x**3 - x**5; print "p4 = " + str(p4); def g1(i): return r.ring.coFac.fromInteger( 2*i ); def g2(i): #print "2*QQ(i) = " + str(QQ(2)*QQ(i)) return 2*QQ(i); r = PS(QQ(),"x",g2); print "r = " + str(r); print "r.factory() = " + str(r.factory()); [one,x] = r.gens(); print "one = " + str(one); print "x = " + str(x); p1 = x**2 - r; print "p1 = " + str(p1); p2 = x**3 - r/2; print "p2 = " + str(p2); print; print "------- MPS(QQ(),\"x,y\") ---------"; r = MPS(QQ(),"x,y"); print "r = " + str(r); print "r.factory() = " + str(r.factory()); one,x,y = r.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); p1 = x**2 - 2*y; print "p1 = " + str(p1); p2 = x**3 * y - y**2; print "p2 = " + str(p2); p3 = x**2 * y**2 - p1 * p2; print "p3 = " + str(p3); p4 = - 4 + 3 * x**2 + 2 * x**3 - x**5; print "p4 = " + str(p4); def g1(i): return r.ring.coFac.fromInteger( i.getVal(0)*i.getVal(1) ); def g2(i): #print "QQ(i.0)*QQ(i.1) = " + str(QQ(i.0)*QQ(i.1)) return QQ(i.getVal(0)) * QQ(i.getVal(1)); r = MPS(QQ(),"x,y",g2); print "r = " + str(r); print "r.factory() = " + str(r.factory()); one,x,y = r.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); p1 = x**2 - r; print "p1 = " + str(p1); p2 = y**3 + r/2; print "p2 = " + str(p2); print; print "------- Vec(QQ(),7) ---------"; r = Vec(QQ(),7); print "r = " + str(r); print "r.factory() = " + str(r.factory()); #print [ str(g) for g in r.gens() ]; [e1,e2,e3,e4,e5,e6,e7] = r.gens(); print "e1 = " + str(e1); print "e2 = " + str(e2); print "e3 = " + str(e3); print "e4 = " + str(e4); print "e5 = " + str(e5); print "e6 = " + str(e6); print "e7 = " + str(e7); v1 = e1 + e3; print "v1 = " + str(v1); #v2 = v1 + 5 * e7; #print "v2 = " + str(v2); v3 = v1 - e1 - e3; print "v3 = " + str(v3); print; print "------- Mat(QQ(),3,3) ---------"; r = Mat(QQ(),3,3); print "r = " + str(r); print "r.factory() = " + str(r.factory()); #print [ str(g) for g in r.gens() ]; [e11,e12,e13,e21,e22,e23,e31,e32,e33] = r.gens(); print "e11 = " + str(e11); print "e12 = " + str(e12); print "e13 = " + str(e13); print "e21 = " + str(e21); print "e22 = " + str(e22); print "e23 = " + str(e23); print "e31 = " + str(e31); print "e32 = " + str(e32); print "e33 = " + str(e33); m1 = e11 + e31; print "m1 = " + str(m1); m2 = m1 * m1 + 5*e22; print "m2 = " + str(m2); m3 = m2**3 - 125*e21 - 125*e23; print "m3 = " + str(m3); #m4 = 1/m2; #print "m4 = " + str(m4); m5 = ( ( 1, 0, 0 ), ( -125, 125, -125 ), ( 1, 0, 0 ) ); # is PyTuple! print "m5 = " + str(m5); m6 = m3 * m5; print "m6 = " + str(m6); print; print "------- Mat(PolyRing(QQ(),\"x,y,z\",PolyRing.lex),3,3) ---------"; r = Mat(PolyRing(QQ(),"x,y,z",PolyRing.lex),3,3); print "r = " + str(r); print "r.factory() = " + str(r.factory()); #print [ str(g) for g in r.gens() ]; for g in r.gens(): print "g = " + str(g); print; print "------- PolyRing(Mat(QQ(),3,3),\"x,y,z\",PolyRing.lex) ---------"; r = PolyRing(Mat(QQ(),3,3),"x,y,z",PolyRing.lex); print "r = " + str(r); for g in r.gens(): print "g = " + str(g); print; print "------- SolvPolyRing(QQ(),\"x,y,z\") ---------"; r = PolyRing(QQ(),"x,y,z",PolyRing.lex); print "r = " + str(r); [pone,px,py,pz] = r.gens(); print "pone = " + str(pone); print "px = " + str(px); print "py = " + str(py); print "pz = " + str(pz); rel = ( py, px, px * py - 1 , pz, py, py * pz - 1 ); #print "rel = " + str(rel); sr = SolvPolyRing(QQ(),"x,y,z",PolyRing.lex,rel); print "sr = " + str(sr); [one,x,y,z] = sr.gens(); print "one = " + str(one); print "x = " + str(x); print "y = " + str(y); print "z = " + str(z); print "one.factory() = " + str(one.factory()); s1 = QQ(1,2) + QQ(2,3) * x + QQ(2,5) * y + ( x + y + z )**2; print "s1 = " + str(s1); s2 = (1,2) + (2,3) * x + (2,5) * y + ( x + y + z )**2; print "s2 = " + str(s2); s3 = z**2 + 2 * y * z + 2 * x * z + y**2 + 2 * x * y + x**2 + (2,5) * y + (2,3) * x + (1,2); print "s3 = " + str(s3); s4 = s1 - s3; print "s4 = " + str(s4); print "s4.factory() = " + str(s4.factory()); sr1 = SolvPolyRing(QQ(),"x, y, z",PolyRing.lex,(( z ), ( y ), ( y * z - 1 ),( y ), ( x ), ( x * y - 1 ))); print "sr1 = " + str(sr1); s5 = z * y; print "s5 = " + str(s5); s6 = s5**3; print "s6 = " + str(s6); s7 = ( z * y )**3; print "s7 = " + str(s7); s8 = s7 - s6; print "s8 = " + str(s8); s9 = y**3 * z**3 - 3 * y**2 * z**2 + 3 * y * z - 1; print "s9 = " + str(s9); s10 = s9 - s7; print "s10 = " + str(s10); print; print "------- SubModule(PolyRing(QQ(),\"u, v, l\",PolyRing.lex) ---------"; p = PolyRing(QQ(),"u, v, l",PolyRing.lex); print "p = " + str(p); [one,u,v,l] = p.gens(); print "one = " + str(one); print "u = " + str(u); print "v = " + str(v); print "l = " + str(l); m = Module(ring=p,cols=4); print "m = " + str(m); for g in m.gens(): print "g =", str(g); m1 = ( 0, 1, l + v, 0 ) m2 = ( 0, v, u * l**2, 0 ) m3 = ( 0, l + 3 * v, 0, u ) m4 = ( 0, v * l + v**2, u**2, 0 ) m5 = ( 0, l**2, u, 0 ) m6 = ( 1, 0, 0, l**2 ) m7 = ( 1, 0, l + 3 * v, 0 ) m8 = ( 1, 2, 0, l**2 ) m9 = ( u, 0, 0, v * l + v**2 ) m10 = ( l + v, 0, 0, u ) m11 = ( l**2, 0, 0, v ) m12 = ( l**2, 0, 2 * u,v ) ml = [m1,m2,m3,m4,m5,m6,m7,m8,m9,m10,m11,m12]; #ml=[ ( 0, 1, l + v, 0 ), ( 0, v, u * l**2, 0 ), ( 0, l + 3 * v, 0, u ), ( 0, v * l + v**2, u**2, 0 ), ( 0, l**2, u, 0 ), ( 1, 0, 0, l**2 ), ( 1, 0, l + 3 * v, 0 ), ( 1, 2, 0, l**2 ), ( u, 0, 0, v * l + v**2 ), ( l + v, 0, 0, u ), ( l**2, 0, 0, v ), ( l**2, 0, 2 * u,v ) ]; #print "ml = " + str(ml); #print; sm = m.submodul(list=ml); #sm = SubModule(m,list=ml); print "sm = " + str(sm); xm = SubModule(PolyRing(QQ(),"u, v, l",PolyRing.lex),list=[ ( 0, 1, ( l + v ), 0 ), ( 0, v, u * l**2, 0 ), ( 0, ( l + 3 * v ), 0, u ), ( 0, ( v * l + v**2 ), u**2, 0 ), ( 0, l**2, u, 0 ), ( 1, 0, 0, l**2 ), ( 1, 0, ( l + 3 * v ), 0 ), ( 1, 2, 0, l**2 ), ( u, 0, 0, ( v * l + v**2 ) ), ( ( l + v ), 0, 0, u ), ( l**2, 0, 0, v ), ( l**2, 0, 2 * u, v ) ]) # SubModule(PolyRing(QQ(),"u, v, l",PolyRing.lex),list=[ ( 0, 1, ( l + v ), 0 ), ( 0, v, u * l**2, 0 ), ( 0, ( l + 3 * v ), 0, u ), ( 0, ( v * l + v**2 ), u**2, 0 ), ( 0, l**2, u, 0 ), ( 1, 0, 0, l**2 ), ( 1, 0, ( l + 3 * v ), 0 ), ( 1, 2, 0, l**2 ), ( u, 0, 0, ( v * l + v**2 ) ), ( ( l + v ), 0, 0, u ), ( l**2, 0, 0, v ), ( l**2, 0, 2 * u, v ) ]) # SubModule(PolyRing(QQ(),"u, v, l",PolyRing.lex),list=[ ( 0, (1,), l + v, 0 ), ( 0, v, u * l**2, 0 ), ( 0, l + (3,) * v, 0, u ), ( 0, v * l + v**2, u**2, 0 ), ( 0, l**2, u, 0 ), ( (1,), 0, 0, l**2 ), ( (1,), 0, l + (3,) * v, 0 ), ( (1,), (2,), 0, l**2 ), ( u, 0, 0, v * l + v**2 ), ( l + v, 0, 0, u ), ( l**2, 0, 0, v ), ( l**2, 0, (2,) * u, v ) ]); # SubModule(PolyRing(QQ(),"u, v, l",PolyRing.lex),list=[ ( 0, (1,), l + v, 0 ), ( 0, v, u * l**2, 0 ), ( 0, l + (3,) * v, 0, u ), ( 0, v * l + v**2, u**2, 0 ), ( 0, l**2, u, 0 ), ( (1,), 0, 0, l**2 ), ( (1,), 0, l + (3,) * v, 0 ), ( (1,), (2,), 0, l**2 ), ( u, 0, 0, v * l + v**2 ), ( l + v, 0, 0, u ), ( l**2, 0, 0, v ), ( l**2, 0, (2,) * u, v ) ]); print "xm = " + str(xm); print; #rg = sm.GB(); #print "rg:", rg; #print "isGB:", rg.isGB(); #print; print "------- SolvableSubModule(SolvPolyRing(CC(),\"X,Y,x,y\")) ---------"; r = PolyRing(CC(),"X,Y,x,y",PolyRing.lex); print "r = " + str(r); [pone,pi,pX,pY,px,py] = r.gens(); print "pone = " + str(pone); print "pi = " + str(pi); print "pX = " + str(pX); print "pY = " + str(pY); print "px = " + str(px); print "py = " + str(py); #rel = ( py, px, px * py - 1 , pz, py, py * pz - 1 ); rel = [ py, px, pi * px * py, pX, pY, pi * pY * pX ]; print "rel = " + str([ str(x) for x in rel ]); sr = SolvPolyRing(CC(),"X,Y,x,y",PolyRing.lex,rel); print "sr = " + str(sr); [one,i,X,Y,x,y,] = sr.gens(); print "one = " + str(one); print "i = " + str(i); print "X = " + str(X); print "Y = " + str(Y); print "x = " + str(x); print "y = " + str(y); m1 = ( ( x + 1 ), ( y ) ) m2 = ( ( x * y ), ( 0 ) ) m3 = ( ( x - X ), ( x - X ) ) m4 = ( ( y - Y ), ( y - Y ) ) ml = [m1,m2,m3,m4]; #print "ml = " + str(ml); ssm = SolvableSubModule( sr, list=ml ); print "ssm: " + str(ssm); print; xsm = SolvableSubModule(SolvPolyRing(CC(),"X, Y, x, y",PolyRing.lex,rel=[y, x, ( ((0,),(1,)) * x * y ), Y, X, ( ((0,),(1,)) * X * Y )]),list=[ ( x - X, x - X ), ( x + ((1,),), y ), ( y - Y, y - Y ), ( x * y, 0 ) ]); # SolvableSubModule(SolvPolyRing(CC(),"X, Y, x, y",PolyRing.lex,rel=[y, x, ( ((0,),(1,)) * x * y ), Y, X, ( ((0,),(1,)) * X * Y )]),list=[ ( x - X, x - X ), ( x + ((1,),), y ), ( y - Y, y - Y ), ( x * y, 0 ) ]); # SolvableSubModule(SolvPolyRing(CC(),"X, Y, x, y",PolyRing.lex,(( y ), ( x ), ( ((0,),(1,)) * x * y ),( Y ), ( X ), ( ((0,),(1,)) * X * Y ))),list=[ ( x - X, x - X ), ( x + ((1,),), y ), ( y - Y, y - Y ), ( x * y, 0 ) ]); print "xsm: " + str(xsm); print; ## mlg = ssm.leftGB(); ## print "mlg:", mlg; ## print; ## mtg = ssm.twosidedGB(); ## print "mtg:", mtg; ## print; print "------------------------------------"; #print "globals() = " + str(globals()); terminate(); sys.exit(); print "globals() = " + str(globals()); print "locals() = " + str(locals()); print "vars() = " + str(vars()); jas-2.5/examples/factors.py0000644000175000017500000000425411630410536016200 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors.py 3756 2011-09-03 11:37:03Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring from jas import Ideal from jas import terminate from jas import startLog # polynomial examples: factorization over Z r = Ring( "Z(x) L" ); print "Ring: " + str(r); print; [one,x] = r.gens(); #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**4 - 1; #f = x**3 - x**2 + x - 1; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; #f = x**15 + 122 * x**10 - 122 * x**5 - 1; #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; f = f * (x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8); print "f = ", f; print; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; print "G = ", [ str(h)+"**"+str(i) for (h,i) in G.iteritems() ]; #print "factor time =", t, "milliseconds"; g = one; for h, i in G.iteritems(): print "h**i = (", h, ")**" + str(i); h = h**i; g = g*h; #print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/factors_abs_mult.py0000644000175000017500000000136711210751460020066 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_abs_mult.py 2664 2009-06-01 13:10:09Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring from jas import Ideal from jas import terminate from jas import startLog # polynomial examples: absolute factorization over Q #r = Ring( "Rat(x) L" ); r = Ring( "Q(x,y) L" ); print "Ring: " + str(r); print; [one,x,y] = r.gens(); f1 = x**2 + y**2; f2 = x**3 + y**2; f3 = x**4 + 4; f = f1**3 * f2**1 * f3**2; print "f = ", f; print; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factorsAbsolute(f); t = System.currentTimeMillis() - t; print "G = ", G.toScript(); print print "factor time =", t, "milliseconds"; print #startLog(); terminate(); jas-2.5/examples/prime-decomp_algeb_trans.rb0000644000175000017500000000413111637162530021433 0ustar giovannigiovanni# # jruby examples for jas. # $Id: prime-decomp_algeb_trans.rb 3774 2011-09-23 20:00:24Z kredel $ # require "examples/jas" #startLog(); # polynomial examples: prime / primary decomposition in Q(sqrt(2))(x)(sqrt(x))[y,z] Q = PolyRing.new(QQ(),"w2",PolyRing.lex); puts "Q = " + str(Q); e,a = Q.gens(); #puts "e = " + str(e); puts "a = " + str(a); root = a**2 - 2; puts "root = " + str(root); Q2 = AN(root,field=true); puts "Q2 = " + str(Q2.factory()); one,w2 = Q2.gens(); #puts "one = " + str(one); #puts "w2 = " + str(w2); puts; Qp = PolyRing.new(Q2,"x",PolyRing.lex); puts "Qp = " + str(Qp); ep,wp,ap = Qp.gens(); #puts "ep = " + str(ep); #puts "wp = " + str(wp); #puts "ap = " + str(ap); puts; Qr = RF(Qp); puts "Qr = " + str(Qr.factory()); er,wr,ar = Qr.gens(); #puts "er = " + str(er); #puts "wr = " + str(wr); #puts "ar = " + str(ar); puts; Qwx = PolyRing.new(Qr,"wx",PolyRing.lex); puts "Qwx = " + str(Qwx); ewx,wwx,ax,wx = Qwx.gens(); #puts "ewx = " + str(ewx); puts "ax = " + str(ax); #puts "wwx = " + str(wwx); puts "wx = " + str(wx); puts; rootx = wx**2 - ax; puts "rootx = " + str(rootx); Q2x = AN(rootx,field=true); puts "Q2x = " + str(Q2x.factory()); ex2,w2x2,ax2,wx = Q2x.gens(); #puts "ex2 = " + str(ex2); #puts "w2x2 = " + str(w2x2); #puts "ax2 = " + str(ax2); #puts "wx = " + str(wx); puts; Yr = PolyRing.new(Q2x,"y,z",PolyRing.lex) puts "Yr = " + str(Yr); e,w2,x,wx,y,z = Yr.gens(); puts "e = " + str(e); puts "w2 = " + str(w2); puts "x = " + str(x); puts "wx = " + str(wx); puts "y = " + str(y); puts "z = " + str(z); puts; f1 = ( y**2 - x ) * ( y**2 - 2 ); #f1 = ( y**2 - x ) * ( y**2 - 2 )**2; f2 = ( z**2 - y**2 ); puts "f1 = ", f1; puts "f2 = ", f2; puts; #sys.exit(); startLog(); F = Yr.ideal( "", [f1,f2] ); puts "F = ", F; puts; #sys.exit(); t = System.currentTimeMillis(); P = F.primeDecomp(); #P = F.primaryDecomp(); t1 = System.currentTimeMillis() - t; puts "P = ", P; puts; puts "prime/primary decomp time = " + str(t1) + " milliseconds"; puts; puts "F = ", F; puts; #startLog(); terminate(); jas-2.5/examples/word_evans.rb0000644000175000017500000000176612023444260016664 0ustar giovannigiovanni# # jruby examples for jas. # $Id: word_evans.rb 4186 2012-09-10 20:08:16Z kredel $ # #load "examples/jas.rb" require "examples/jas" # non-commutative polynomial examples: evans example r = WordPolyRing.new(QQ(),"x,y,z"); puts "WordPolyRing: " + str(r); puts; one,x,y,z = r.gens(); puts "one = " + str(one); puts "x = " + str(x); puts "y = " + str(y); puts "z = " + str(z); puts; f1 = x * y - z; f2 = y * z + 2 * x + z; f3 = y * z + x; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; ff = r.ideal( "", [f1,f2,f3] ); puts "ff = " + str(ff); puts; startLog(); gg = ff.GB(); puts "gg = " + str(gg); puts "isGB(gg) = " + str(gg.isGB()); puts; #exit(0); c1 = f1 * f2; c2 = f2 * f1; s = c1 - c2; puts "c1 = " + str(c1); puts "c2 = " + str(c2); puts "s = " + str(s); puts; ff = r.ideal( "", [f1,f2,f3,c1,c2,s] ); puts "ff = " + str(ff); puts; gga = ff.GB(); puts "gga = " + str(gga); puts "isGB(gga) = " + str(gga.isGB()); puts "gg == gga: " + str(gg.list == gga.list); puts; jas-2.5/examples/wa_61.jas0000644000175000017500000000040210653077260015577 0ustar giovannigiovanni# solvable polynomials, Weyl algebra A_6,1: (a,b,e1,e2,e3,e4,e5,e6) G RelationTable ( ( e2 ), ( e1 ), ( e1 e2 - e3 ), ( e3 ), ( e1 ), ( e1 e3 - e4 ), ( e5 ), ( e1 ), ( e1 e5 - e6 ) ) ( ( e1 e3^3 + e2^2 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) jas-2.5/examples/roots_complex_ideal.rb0000644000175000017500000000254211722155002020537 0ustar giovannigiovanni# # jruby examples for jas. # $Id: roots_complex_ideal.rb 3893 2012-02-25 12:54:26Z kredel $ # require "examples/jas" # polynomial examples: complex roots over Q r = PolyRing.new(QQ(),"I,x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,I,x,y,z = r.gens(); f1 = z - x - y * I; f2 = I**2 + 1; #f3 = z**3 - 2; f3 = z**3 - 2*I; puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); puts; F = r.ideal( "", list=[f1,f2,f3] ); puts "F = " + str(F); puts; startLog(); G = F.GB(); puts "G = " + str(G); puts; #terminate(); #sys.exit(); r = PolyRing.new(QQ(),"x,y",PolyRing.lex); puts "Ring: " + str(r); puts; one,x,y = r.gens(); # y**3 - 3 * I * x * y**2 - 3 * x**2 * y + I * x**3 - 2 * I = z**3 - 2 #fr = y**3 - 3 * x**2 * y; #fi = -3 * x * y**2 + x**3 - 2; # y**3 - 3 * I * x * y**2 - 3 * x**2 * y + I * x**3 + 2 = z**3 - 2 I fr = y**3 - 3 * x**2 * y - 2; fi = -3 * x * y**2 + x**3; puts "fr = " + str(fr); puts "fi = " + str(fi); puts; F = r.ideal( "", list=[fr,fi] ); puts "F = " + str(F); puts; G = F.GB(); puts "G = " + str(G); puts; t = System.currentTimeMillis(); R = G.complexRoots(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "complex roots: "; G.complexRootsPrint() puts; puts "complex roots time = " + str(t) + " milliseconds"; puts; puts "G = " + str(G); puts; #startLog(); terminate(); jas-2.5/examples/squarefree_finite_alg.rb0000644000175000017500000000165411653336426021050 0ustar giovannigiovanni# # jruby examples for jas. # $Id: squarefree_finite_alg.rb 3822 2011-10-30 21:09:42Z kredel $ # require "examples/jas" # polynomial examples: squarefree: characteristic p, finite algebraic ar = PolyRing.new(ZM(7,field=true),"i",PolyRing.lex) one,i = ar.gens(); # irred for 7, 11, 19 r = PolyRing.new(AN(i**2+1,field=true),"x, y, z",PolyRing.lex) puts "Ring: " + str(r); puts; one,i,x,y,z = r.gens(); a = r.random(k=2,l=3); b = r.random(k=2,l=3); c = r.random(k=1,l=3); if a.isZERO() a = x; end if b.isZERO() b = y; end if c.isZERO() c = z; end f = a**2 * b**7 * c; puts "a = " + str(a); puts "b = " + str(b); puts "c = " + str(c); puts "f = " + str(f); puts; t = System.currentTimeMillis(); F = r.squarefreeFactors(f); t = System.currentTimeMillis() - t; puts "factors:"; for g in F.keys() i = F[g]; puts "g = #{g}**#{i}"; end puts puts "factor time = " + str(t) + " milliseconds"; startLog(); terminate(); jas-2.5/examples/prime-decomp-charp.py0000644000175000017500000000216411414647340020216 0ustar giovannigiovanni# # jython examples for jas. # $Id: prime-decomp-charp.py 3216 2010-07-06 15:42:25Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, ZM, RF # polynomial examples: ideal prime decomposition in char p > 0, inseparable cases cr = PolyRing(ZM(5),"c",PolyRing.lex); print "coefficient Ring: " + str(cr); rf = RF(cr); print "coefficient quotient Ring: " + str(rf.ring); r = PolyRing(rf,"x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,c,x,y,z] = r.gens(); print one,c,x,y,z; #sys.exit(); f1 = (x**2 - 2); #**2; f2 = (y**2 - c)**5; f3 = (z**2 - 2 * c); #**5; print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; #print "f4 = ", f4; print; F = r.ideal( list=[f1,f2,f3] ); #F = r.ideal( list=[f1,f3] ); #F = r.ideal( list=[f2,f3] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); P = F.primeDecomp(); t = System.currentTimeMillis() - t; print "P = ", P; print; print "decomp time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/raksanyi_int.rb0000644000175000017500000000125711653060122017202 0ustar giovannigiovanni# # jruby examples for jas. # $Id: raksanyi_int.rb 3818 2011-10-29 20:21:39Z kredel $ # require "examples/jas" # Raksanyi & Walter example # rational function coefficients r = Ring.new( "IntFunc(a1, a2, a3, a4) (x1, x2, x3, x4) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( x4 - { a4 - a2 } ), ( x1 + x2 + x3 + x4 - { a1 + a3 + a4 } ), ( x1 x3 + x1 x4 + x2 x3 + x3 x4 - { a1 a4 + a1 a3 + a3 a4 } ), ( x1 x3 x4 - { a1 a3 a4 } ) ) """; f = r.paramideal( ps ); puts "Ideal: " + str(f); puts; #startLog(); rg = f.GB(); rg = f.GB(); rg = f.GB(); puts "Ideal: " + str(rg); puts; bg = rg.isGB(); if bg puts "isGB: true"; else puts "isGB: false"; end puts; terminate(); jas-2.5/examples/roots_complex.rb0000644000175000017500000000224411613034154017403 0ustar giovannigiovanni# # jruby examples for jas. # $Id: roots_complex.rb 3697 2011-07-24 15:21:16Z kredel $ # require "examples/jas" # polynomial examples: complex roots over Q r = PolyRing.new(CR(QQ()),"x",PolyRing.lex); puts "Ring: " + str(r); puts; one,I,x = r.gens(); puts "one = " + one.to_s; puts "I = " + I.to_s; puts "x = " + x.to_s; puts; f1 = x**3 - 2; f2 = ( x - I ) * ( x + I ) * ( x - 2 * I ) * ( x + 1/2 * I ); f3 = ( x**3 - 2 * I ); #f = f1 * f2 * f3; #f = f1 * f2; #f = f1 * f3; #f = f2 * f3; f = f2; puts "f = " + f.to_s; puts; startLog(); t = System.currentTimeMillis(); rr = r.complexRoots(f); t = System.currentTimeMillis() - t; #puts "rr = " + str(rr); puts "rr = " + str(rr.map{ |a| str(a.elem.ring.getRoot())+"," }); puts "complex roots time = " + str(t) + " milliseconds"; #eps = QQ(1,10) ** (BigDecimal::DEFAULT_PRECISION-3); eps = QQ(1,10) ** 10; puts "eps = " + str(eps); t = System.currentTimeMillis(); rr = r.complexRoots(f,eps); t = System.currentTimeMillis() - t; #puts "rr = ", [ str(r) for r in rr ]; puts "rr = " + str(rr.map{ |a| str(a.elem.decimalMagnitude())+"," }); puts "complex roots time = " + str(t) + " milliseconds"; #startLog(); terminate(); jas-2.5/examples/solvablepolynomial.py0000644000175000017500000000506412023444260020450 0ustar giovannigiovanni# # jython examples for jas. # $Id: solvablepolynomial.py 4186 2012-09-10 20:08:16Z kredel $ # from java.lang import System from java.lang import Integer from jas import SolvableRing, SolvPolyRing, PolyRing, SolvableIdeal from jas import QQ, Quat # WA_32 solvable polynomial example p = PolyRing(QQ(),"a,b,e1,e2,e3"); #is automatic: [one,a,b,e1,e2,e3] = p.gens(); relations = [e3, e1, e1*e3 - e1, e3, e2, e2*e3 - e2]; print "relations: =", [ str(f) for f in relations ]; print; #rp = SolvPolyRing(QQ(), "a,b,e1,e2,e3", rel=relations); rp = SolvPolyRing(QQ(), "a,b,e1,e2,e3", PolyRing.lex, relations); print "SolvPolyRing: " + str(rp); print; print "gens =", [ str(f) for f in rp.gens() ]; #[one,a,b,e1,e2,e3] = rp.gens(); #[one,I,J,K,a,b,e1,e2,e3] = rp.gens(); f1 = e1 * e3**3 + e2**10 - a; f2 = e1**3 * e2**2 + e3; f3 = e3**3 + e3**2 - b; f4 = ( e3**2 * e2**3 + e1 )**3; #print "f1 = ", f1; #print "f2 = ", f2; #print "f3 = ", f3; #print "f4 = ", f4; F = [ f1, f2, f3 ]; print "F =", [ str(f) for f in F ]; print I = rp.ideal( list=F ); print "SolvableIdeal: " + str(I); print; rgl = I.leftGB(); print "seq left GB:" + str(rgl); print "isLeftGB: " + str(rgl.isLeftGB()); print; rgt = I.twosidedGB(); print "seq twosided GB:" + str(rgt); print "isTwosidedGB: " + str(rgt.isTwosidedGB()); print; rgr = I.rightGB(); print "seq right GB:" + str(rgr); print "isRightGB: " + str(rgr.isRightGB()); print; #exit(0); rs = """ # solvable polynomials, Weyl algebra A_3,2: Rat(a,b,e1,e2,e3) L #Quat(a,b,e1,e2,e3) G|3| RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e1 ), ( e3 ), ( e2 ), ( e2 e3 - e2 ) ) """; r = SolvableRing( rs ); print "SolvableRing: " + str(r); print; print "gens =", [ str(f) for f in r.gens() ]; #[one,a,b,e1,e2,e3] = r.gens(); #[one,I,J,K,a,b,e1,e2,e3] = r.gens(); fs1 = e1 * e3**3 + e2**10 - a; fs2 = e1**3 * e2**2 + e3; fs3 = e3**3 + e3**2 - b; fs4 = ( e3**2 * e2**3 + e1 )**3; #print "fs1 = ", fs1; #print "fs2 = ", fs2; #print "fs3 = ", fs3; print "fs4 = ", fs4; Fs = [ fs1, fs2, fs3 ]; print "Fs =", [ str(f) for f in Fs ]; print Is = r.ideal( list=Fs ); print "SolvableIdeal: " + str(Is); print; rgsl = I.leftGB(); print "seq left GB:" + str(rgsl); print "isLeftGB: " + str(rgsl.isLeftGB()); print; rgst = I.twosidedGB(); print "seq twosided GB:" + str(rgst); print "isTwosidedGB: " + str(rgst.isTwosidedGB()); print; rgsr = I.rightGB(); print "seq right GB:" + str(rgsr); print "isRightGB: " + str(rgsr.isRightGB()); print; print "rgl == rgsl: " + str(rgl == rgsl); print "rgr == rgsr: " + str(rgr == rgsr); print "rgt == rgst: " + str(rgt == rgst); jas-2.5/examples/eliminate.rb0000644000175000017500000000110711641415316016456 0ustar giovannigiovanni# # jruby examples for jas. # $Id: eliminate.rb 3786 2011-09-30 19:38:55Z kredel $ # require "examples/jas" # ideal elimination example r = PolyRing.new( QQ(), "(x,y,z)", PolyRing.grad ); puts "Ring: " + str(r); puts; ps1 = """ ( ( x^2 - 2 ), ( y^2 - 3 ), ( z^3 - x * y ) ) """; F1 = r.ideal( ps1 ); puts "Ideal: " + str(F1); puts; e = PolyRing.new( QQ(), "(x,z)", PolyRing.grad ); puts "Ring: " + str(e); puts; #startLog(); rg1 = F1.eliminateRing(e); puts "rg1 = " + str(rg1); puts; rg2 = rg1.intersectRing(e); puts "rg2 = " + str(rg2); puts; terminate(); #sys.exit(); jas-2.5/examples/mmt.rb0000644000175000017500000000126511516125140015303 0ustar giovannigiovanni# # jruby examples for jas. # $Id: $ # require "examples/jas" #startLog(); # example form Moeller, Mora, Traverso #r = PolyRing.new(QQ(),"t,z,y,x",PolyRing.grad); r = PolyRing.new(QQ(),"z,y,x",PolyRing.grad); #r = PolyRing.new(QQ(),"x,y,z",PolyRing.grad); print "Ring: " + str(r); print; #one,t,z,y,x = r.gens(); one,z,y,x = r.gens(); #one,x,y,z = r.gens(); f0 = x**2 * y - z**2; f1 = x * z**2 - y**2; f2 = y * z**3 - x**2; #f0h = x**2 * y - z**2 * t; #f1h = x * z**2 - y**2 * t; #f2h = y * z**3 - x**2 * t**2; f = r.ideal("",[f0,f1,f2]); #f = r.ideal("",[f0h,f1h,f2h]); print "Ideal: " + str(f); print; startLog(); rg = f.GB(); print "seq Output: ", rg; print "\n"; #terminate(); jas-2.5/examples/solvablemodule.rb0000644000175000017500000000215611774031074017533 0ustar giovannigiovanni# # jruby examples for jas. # $Id: solvablemodule.rb 3972 2012-07-01 11:19:24Z kredel $ # require "examples/jas" # Quantum plane example rsan = """ AN[ (i) (i^2 + 1) ] (Y,X,x,y) G RelationTable ( ( y ), ( x ), ( {i} x y ) ( X ), ( Y ), ( {i} Y X ) ) """; rsc = """ C(Y,X,x,y) G |2| #C(Y,X,x,y) G RelationTable ( ( y ), ( x ), ( 0i1 x y ) ( X ), ( Y ), ( 0i1 Y X ) ) """; r = SolvableModule.new( rsc ); #r = SolvableModule.new( rsan ); puts "SolvableModule: " + str(r); puts; ps = """ ( ( ( x + 1 ), ( y ) ), ( ( x y ), ( 0 ) ), ( ( x - X ), ( x - X ) ), ( ( y - Y ), ( y - Y ) ) ) """; f = SolvableSubModule.new( r, ps ); puts "SolvableSubModule: " + str(f); puts; #exit() lg = f.leftGB(); puts "seq left GB: " + str(lg); puts "is left GB: " + str(lg.isLeftGB()); puts; tg = f.twosidedGB(); puts "seq twosided GB: " + str(tg); puts "is twosided GB: " + str(tg.isTwosidedGB()); puts "is right GB: " + str(tg.isRightGB()); puts; #startLog(); # not supported for split term orders: #rg = f.rightGB(); #puts "seq right GB: " + str(rg); #puts "is right GB: " + str(rg.isRightGB()); #puts; #startLog(); terminate(); jas-2.5/examples/hawes2.rb0000644000175000017500000000215211644356076015713 0ustar giovannigiovanni# # jruby examples for jas. # $Id: hawes2.rb 3794 2011-10-09 17:39:11Z kredel $ # ## \begin{PossoExample} ## \Name{Hawes2} ## \Parameters{a;b;c} ## \Variables{x;y[2];z[2]} ## \begin{Equations} ## x+2y_1z_1+3ay_1^2+5y_1^4+2cy_1 \& ## x+2y_2z_2+3ay_2^2+5y_2^4+2cy_2 \& ## 2 z_2+6ay_2+20 y_2^3+2c \& ## 3 z_1^2+y_1^2+b \& ## 3z_2^2+y_2^2+b \& ## \end{Equations} ## \end{PossoExample} require "examples/jas" #startLog(); # Hawes & Gibson example 2 # rational function coefficients #r = Ring.new( "RatFunc(a, c, b) (y2, y1, z1, z2, x) G" ); r = PolyRing.new( RF(PolyRing.new(ZZ(),"a, c, b",PolyRing.lex)), "y2, y1, z1, z2, x", PolyRing.grad ); puts "Ring: " + str(r); puts; ps = """ ( ( x + 2 y1 z1 + { 3 a } y1^2 + 5 y1^4 + { 2 c } y1 ), ( x + 2 y2 z2 + { 3 a } y2^2 + 5 y2^4 + { 2 c } y2 ), ( 2 z2 + { 6 a } y2 + 20 y2^3 + { 2 c } ), ( 3 z1^2 + y1^2 + { b } ), ( 3 z2^2 + y2^2 + { b } ) ) """; f = r.ideal( ps ); puts "Ideal: " + str(f); puts; rg = f.GB(); rg = f.GB(); puts "GB: " + str(rg); #puts "GB: " + str(rg.pset); puts; bg = rg.isGB(); puts "isGB: " + str(bg); puts; startLog(); terminate(); #sys.exit(); jas-2.5/examples/katsura5s.jas0000644000175000017500000000107010653077260016606 0ustar giovannigiovanni#Katsura equations for N = 5: (u0,u1,u2,u3,u4,u5) G|1| ( u5*u5 + u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 + u5*u5 - u0, u5*0 + u4*u5 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 + u5*u4 - u1, u5*0 + u4*0 + u3*u5 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 + u5*u3 - u2, u5*0 + u4*0 + u3*0 + u2*u5 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 + u5*u2 - u3, u5*0 + u4*0 + u3*0 + u2*0 + u1*u5 + u0*u4 + u1*u3 + u2*u2 + u3*u1 + u4*u0 + u5*u1 - u4, u5 + u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 + u5 - 1 ) jas-2.5/examples/logic.rb0000644000175000017500000000106611645621462015615 0ustar giovannigiovanni# # jruby examples for jas. # $Id: logic.rb 3802 2011-10-13 17:43:15Z kredel $ # require "examples/jas" # logic example from Kreutzer JdM 2008 #r = Ring.new( "Mod 2 (a,f,p,u) G" ); r = PolyRing.new( ZM(2), "(a,f,p,u)", PolyRing.grad ); puts "Ring: " + str(r); puts; ks = """ ( ( a^2 - a ), ( f^2 - f ), ( p^2 - p ), ( u^2 - u ) ) """; ps = """ ( ( p f + p ), ( p u + p + u + 1 ), ( a + u + 1 ), ( a + p + 1 ) ) """; k = r.ideal( ks ); p = r.ideal( ps ); f = k.sum( p ); puts "Ideal: " + str(f); puts; rg = f.GB(); puts "Output:" + str(rg); puts; jas-2.5/examples/factors_algeb.rb0000644000175000017500000000556411641415316017315 0ustar giovannigiovanni# # jruby examples for jas. # $Id: factors_algeb.rb 3786 2011-09-30 19:38:55Z kredel $ # require "examples/jas" # polynomial examples: factorization over Q(i) #r = Ring( "AN[ (i) (i^2 + 1) ] (x) L" ); #r = Ring( "AN[ (a) (4 a^2 + 1) ] (x) L" ); #r = Ring( "AN[ (a) (a^4 + 2 a^2 - 4 a + 2) ] (x) L" ); #puts "Ring: " + str(r); #puts; Qr = PolyRing.new(QQ(),"i",PolyRing.lex); puts "Qr = " + str(Qr); e,a = Qr.gens(); puts "e = " + str(e); puts "a = " + str(a); imag = a**2 + 1; puts "imag = " + str(imag); Qi = AN(imag,true); puts "Qi = " + str(Qi.factory()); one,i = Qi.gens(); puts "one = " + str(one); puts "i = " + str(i); b = i**2 + 1; puts "b = " + str(b); c = 1 / i; puts "c = " + str(c); #Qix = AN(i**2 + 1); #puts "Qix = " + str(Qix.factory()); puts; r = PolyRing.new(Qi,"x",PolyRing.lex) puts "r = " + str(r); one,i,x = r.gens(); puts "one = " + str(one); puts "i = " + str(i); puts "x = " + str(x); #f = x**15 - 1; #f = x * ( x + 1 )**2 * ( x**2 + x + 1 )**3; #f = x**6 - 3 * x**5 + x**4 - 3 * x**3 - x**2 - 3 * x+ 1; #f = x**(3*11) + 3 * x**(2*11) - x**(11); #f = x**(3*11*11) + 3 * x**(2*11*11) - x**(11*11); #f = x**(3*11*11*11) + 3 * x**(2*11*11*11) - x**(11*11*11); #f = (x**2+1)*(x-3)*(x-5)**3; #f = x**4 + 1; #f = x**12 + x**9 + x**6 + x**3 + 1; #f = x**24 - 1; #f = x**20 - 1; #f = x**22 - 1; #f = x**8 - 40 * x**6 + 352 * x**4 - 960 * x**2 + 576; #f = 362408718672000 * x**9 + 312179013226080 * x**8 - 591298435728000 * x**6 - 509344705789920 * x**5 - 1178946881112000 * x**2 - 4170783473878580 * x - 2717923400363451; #f = 292700016000 * x**8 + 614670033600 * x**7 - 417466472400 * x**6 - 110982089400 * x**5 + 1185906158780 * x**4 - 161076194335 * x**3 + 204890011200 * x**2 - 359330651400 * x - 7719685302; #f = x**10 - 212 * x**9 - 1760 * x**8 + 529 * x**7 - 93699 * x**6 - 726220 * x**5 + 37740 * x**4 + 169141 * x**3 + 24517680 * x**2 - 9472740; #f = x**4 + 1; #f = x**3 - x**2 + x - 1; #f = x**8 + 4 * x**6 + 8 * x**4 - 8 * x**2 + 4; f = x**6 - 5 * x**4 + 5 * x**2 + 4; # == f = ( x**3 + 2 * i * x**2 - 3 * x - 4 * i ) * ( x**3 - 2 * i * x**2 - 3 * x + 4 * i ); #f = ( x**3 + ( 2 * i ) * x**2 - ( 3 ) * x - ( 4 * i ) ) * ( x**3 - ( 2 * i ) * x**2 - ( 3 ) * x + ( 4 * i ) ); #f = x**16 + 272 * x**12 - 7072 * x**8 + 3207424 * x**4 + 12960000; #f = x**16 + 16 * x**12 + 96 * x**8 + 256 * x**4 + 256; #f = x**24 + 272 * x**20 - 7072 * x**16 + 3207424 * x**12 + 12960000 * x**8; puts "f = " + str(f); puts; startLog(); t = System.currentTimeMillis(); #G = r.squarefreeFactors(f); G = r.factors(f); t = System.currentTimeMillis() - t; puts "G = " + str(G); #puts "factor time =", t, "milliseconds"; puts; g = one; for h, i in G puts "h**i = (" + str(h) + ")**" + str(i); h = h**i; g = g*h; end #puts "g = ", g; puts; puts "factor time = " + str(t) + " milliseconds," + " isFactors(f,g): " + str(f==g); puts; #startLog(); terminate(); jas-2.5/examples/nabeshima_cgbF01.rb0000644000175000017500000000142411653002012017506 0ustar giovannigiovanni# # jruby examples for jas. # $Id: nabeshima_cgbF01.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Nabashima, ISSAC 2007, example Ex-4.3 # integral function coefficients r = Ring.new( "IntFunc(a, b) (y,x) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( x y + x ), ( { a } x^2 + y + 2 ), ( { b } x y + y ) ) """; #startLog(); f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; bg = gs.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; #exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; bg = gs.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/radical-decomp.py0000644000175000017500000000156211376460372017414 0ustar giovannigiovanni# # jython examples for jas. # $Id: radical-decomp.py 3150 2010-05-24 11:20:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, DD # polynomial examples: ideal radical decomposition #r = Ring( "Rat(x) L" ); #r = Ring( "Q(x) L" ); r = PolyRing(QQ(),"x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); f1 = (x**2 - 5)**2; f2 = (y**2 - 3)**3 * (y**2 - 5); f3 = z**3 - x * y; #print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; print; F = r.ideal( list=[f2,f3] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); t = System.currentTimeMillis() - t; print "R = ", R; print; print "decomp time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/intprog4.py0000644000175000017500000000242310373614370016306 0ustar giovannigiovanni# # jython for jas example 3 integer programming. # $Id: intprog4.py 597 2006-02-12 11:16:09Z kredel $ # # CLO2, p374,c # 3 A + 2 B + C + D = 45 # A + 2 B + 3 C + E = 21 # 2 A + B + C + F = 18 # # max: 3 A + 4 B + 2 C # import sys; from jas import Ring from jas import Ideal #r = Ring( "Rat(w1,w2,w3,w4,w5,w6,z1,z2,z3) W( (0,0,0,0,0,0,1,1,1),(-3,-4,-2,0,0,0,0,0,0) )" ); #r = Ring( "Rat(w1,w2,w3,w4,w5,w6,z1,z2,z3) W( (0,0,0,0,0,0,1,1,1),( 6, 5, 5,1,1,1,0,0,0)*2 )" ); #r = Ring( "Rat(w1,w2,w3,w4,w5,w6,z1,z2,z3) W( (0,0,0,0,0,0,1,1,1),( 3, 1, 3,1,1,1,0,0,0) )" ); r = Ring( "Rat(w1,w2,w3,w4,w5,w6,z1,z2,z3) W( (0,0,0,0,0,0,1,1,1),( 9, 6, 8,2,2,2,0,0,0) )" ); print "Ring: " + str(r); print; ps = """ ( ( z1^3 z2 z3^2 - w1 ), ( z1^2 z2^2 z3 - w2 ), ( z1 z2^3 z3 - w3 ), ( z1 - w4 ), ( z2 - w5 ), ( z3 - w6 ) ) """; f = Ideal( r, ps ); print "Ideal: " + str(f); print; rg = f.GB(); print "seq Output:", rg; print; pf = """ ( ( z1^45 z2^21 z3^18 ) ) """; fp = Ideal( r, pf ); print "Ideal: " + str(fp); print; nf = fp.NF(rg); print "NFs: " + str(nf); print; #rg = f.parGB(2); #print "par Output:", rg; #print; #f.distClient(); # starts in background #rg = f.distGB(2); #print "dist Output:", rg; #print; #sys.exit(); jas-2.5/examples/intersect.rb0000644000175000017500000000127011644356076016522 0ustar giovannigiovanni# # jruby examples for jas. # $Id: intersect.rb 3794 2011-10-09 17:39:11Z kredel $ # require "examples/jas" # ideal intersection example #r = Ring.new( "Rat(x,y,z) L" ); r = PolyRing.new( QQ(), "(x,y,z)", PolyRing.lex ); puts "Ring: " + str(r); puts; ps1 = """ ( ( x - 1 ), ( y - 1 ), ( z - 1 ) ) """; ps2 = """ ( ( x - 2 ), ( y - 3 ), ( z - 3 ) ) """; F1 = r.ideal( ps1 ); #puts "Ideal: " + str(F1); #puts; F2 = r.ideal( ps2 ); #puts "Ideal: " + str(F2); #puts; #startLog(); rg1 = F1.GB(); puts "rg1 = " + str(rg1); puts; rg2 = F2.GB(); puts "rg2 = " + str(rg2); puts; #startLog(); ig = F1.intersect(F2); puts "rg1 intersect rg2 = " + str(ig); puts; terminate(); #sys.exit(); jas-2.5/examples/trinks.rb0000644000175000017500000000324112056644004016021 0ustar giovannigiovanni# # jruby examples for jas. # $Id: trinks.rb 4311 2012-12-02 12:22:28Z kredel $ # #load "examples/jas.rb" require "examples/jas" # trinks 6/7 example # QQ = rational numbers, ZZ = integers, CC = complex rational numbers, GF = finite field #r = PolyRing.new( GF(19),"B,S,T,Z,P,W", PolyRing.lex); #r = PolyRing.new( GF(1152921504606846883),"B,S,T,Z,P,W", PolyRing.lex); #r = PolyRing.new( GF(2**60-93),"B,S,T,Z,P,W", PolyRing.lex); #r = PolyRing.new( CC,"B,S,T,Z,P,W", PolyRing.lex); #r = PolyRing.new( ZZ,"B,S,T,Z,P,W", PolyRing.lex); r = PolyRing.new( QQ,"B,S,T,Z,P,W", PolyRing.lex); puts "Ring: " + r.to_s; puts; # sage like: with generators for the polynomial ring one,B,S,T,Z,P,W = r.gens(); # capital letter variables not automaticaly included #one,I,B,S,T,Z,P,W = r.gens(); f1 = 45 * P + 35 * S - 165 * B - 36; f2 = 35 * P + 40 * Z + 25 * T - 27 * S; f3 = 15 * W + 25 * S * P + 30 * Z - 18 * T - 165 * B**2; f4 = - 9 * W + 15 * T * P + 20 * S * Z; f5 = P * W + 2 * T * Z - 11 * B**3; f6 = 99 * W - 11 *B * S + 3 * B**2; f7 = 10000 * B**2 + 6600 * B + 2673; #f7 = B**2 + 33/50 * B + 2673/10000; # fractions work with ruby #puts "f1 = " + f1.to_s; F = [ f1, f2, f3, f4, f5, f6, f7 ]; # smaller, faster #F = [ f1, f2, f3, f4, f5, f6 ]; # bigger, needs more time puts "F = " + F.map { |f| f.to_s }.join(","); puts f = r.ideal( "", F ); puts "Ideal: " + f.to_s; puts; #startLog(); rg = f.GB(); puts "seq Output:", rg; puts; rg = f.parGB(2); puts "par Output:", rg; puts; terminate(); return # if using ZZ coefficients f.distClient(); # starts in background, needs socket permission rg = f.distGB(2); #puts "dist Output:", rg; #puts; f.distClientStop(); # stops them terminate(); jas-2.5/examples/boolean_cgb.py0000644000175000017500000000212611633202702016762 0ustar giovannigiovanniimport sys; from jas import Ring, PolyRing, ParamIdeal, QQ, ZM, RR from jas import startLog, terminate # Boolean coefficient boolean GB # see S. Inoue and A. Nagai "On the Implementation of Boolean Groebner Bases" in ASCM 2009 # Z_2 regular ring coefficent example r = PolyRing(RR(ZM(2),3),"a,x,y",PolyRing.lex); print "r = " + str(r); #print len(r.gens()) [s1,s2,s3,a,x,y] = r.gens(); one = r.one(); print "one = " + str(one); print "s1 = " + str(s1); print "s2 = " + str(s2); print "s3 = " + str(s3); print "a = " + str(a); print "x = " + str(x); print "y = " + str(y); #brel = [ a**2 - a, x**2 - x, y**2 - y ]; brel = [ x**2 - x, y**2 - y ]; #print "brel = " + str(brel[0]) + ", " + str(brel[1]) + ", " + str(brel[2]); print "brel = " + str(brel[0]) + ", " + str(brel[1]); pl = [ ( one + s1 + s2 ) * ( x*y + x + y ), s1 * x + s1, a * y + a, x * y ]; pl = pl + brel; startLog(); f = ParamIdeal(r,list=pl); print "Ideal: " + str(f); gb = f.regularGB(); print "boolean GB: " + str(gb); #ss = gb.stringSlice(); #print "regular string slice: " + str(ss); terminate(); #sys.exit(); jas-2.5/examples/radical-decomp_charp.rb0000644000175000017500000000163311653043730020534 0ustar giovannigiovanni# # jruby examples for jas. # $Id: radical-decomp_charp.rb 3817 2011-10-29 18:37:12Z kredel $ # require "examples/jas" # polynomial examples: ideal radical decomposition, dim > 0, char p separable #r = Ring.new( "Rat(x) L" ); #r = Ring.new( "Q(x) L" ); r = PolyRing.new(ZM(5),"x,y,z",PolyRing.lex); puts "Ring: " + str(r); puts; one,x,y,z = r.gens(); #f1 = (x**2 - 5)**2; #f1 = (y**10 - x**5)**3; f2 = y**6 + 2 * x * y**4 + 3 * x**2 * y**2 + 4 * x**3; f2 = f2**5; f3 = z**10 - x**5; f4 = (y**2 - x)**3; #puts "f1 = " + str(f1); puts "f2 = " + str(f2); puts "f3 = " + str(f3); #puts "f4 = " + str(f4); puts; F = r.ideal( "", list=[f2,f3] ); puts "F = " + str(F); puts; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); t = System.currentTimeMillis() - t; puts "R = " + str(R); puts; puts "decomp time = " + str(t) + " milliseconds"; puts; puts "F = " + str(F); puts; #startLog(); terminate(); jas-2.5/examples/.gitignore0000644000175000017500000000003411306031572016144 0ustar giovannigiovanni/*.txt /*.out /*.class /edu jas-2.5/examples/arith.py0000644000175000017500000000252711173156534015656 0ustar giovannigiovanni# # jython examples for jas. # $Id: arith.py 2586 2009-04-20 20:38:53Z kredel $ # import sys; from jas import Ring from jas import ZZ from jas import QQ from jas import CC from jas import RF from jas import startLog from jas import terminate # example for rational and complex numbers # # zn = ZZ(7); print "zn:", zn; print "zn^2:", zn*zn; print; x = 10000000000000000000000000000000000000000000000000; rn = QQ(2*x,4*x); print "rn:", rn; print "rn^2:", rn*rn; print; rn = QQ((6,4)); print "rn:", rn; print "rn^2:", rn*rn; print; c = CC(); print "c:", c; c = c.one(); print "c:", c; c = CC((2,),(3,)); print "c:", c; print "c^5:", c**5 + c.one(); print; c = CC( (2,),rn ); print "c:", c; print; r = Ring( "Q(x,y) L" ); print "Ring: " + str(r); print; # sage like: with generators for the polynomial ring [one,x,y] = r.gens(); zero = r.zero(); try: f = RF(r); except: f = None; print "f: " + str(f); d = x**2 + 5 * x - 6; f = RF(r,d); print "f: " + str(f); n = d*d + y + 1; f = RF(r,d,n); print "f: " + str(f); print; # beware not to mix expressions f = f**2 - f; print "f^2-f: " + str(f); print; f = f/f; print "f/f: " + str(f); f = RF(r,d,one); print "f: " + str(f); f = RF(r,zero); print "f: " + str(f); f = RF(r,d,y); print "f: " + str(f); print "one: " + str(f.one()); print "zero: " + str(f.zero()); print; terminate(); #sys.exit(); jas-2.5/examples/prime-decomp_algeb_trans.py0000644000175000017500000000433111637162530021462 0ustar giovannigiovanni# # jython examples for jas. # $Id: prime-decomp_algeb_trans.py 3774 2011-09-23 20:00:24Z kredel $ # import sys from java.lang import System from jas import PolyRing, Ideal from jas import QQ, AN, RF from jas import terminate, startLog # polynomial examples: prime/primary decomposition in Q(sqrt(2))(x)(sqrt(x))[y,z] Q = PolyRing(QQ(),"w2",PolyRing.lex); print "Q = " + str(Q); [e,a] = Q.gens(); #print "e = " + str(e); print "a = " + str(a); root = a**2 - 2; print "root = " + str(root); Q2 = AN(root,field=True); print "Q2 = " + str(Q2.factory()); [one,w2] = Q2.gens(); #print "one = " + str(one); #print "w2 = " + str(w2); print; Qp = PolyRing(Q2,"x",PolyRing.lex); print "Qp = " + str(Qp); [ep,wp,ap] = Qp.gens(); #print "ep = " + str(ep); #print "wp = " + str(wp); #print "ap = " + str(ap); print; Qr = RF(Qp); print "Qr = " + str(Qr.factory()); [er,wr,ar] = Qr.gens(); #print "er = " + str(er); #print "wr = " + str(wr); #print "ar = " + str(ar); print; Qwx = PolyRing(Qr,"wx",PolyRing.lex); print "Qwx = " + str(Qwx); [ewx,wwx,ax,wx] = Qwx.gens(); #print "ewx = " + str(ewx); print "ax = " + str(ax); #print "wwx = " + str(wwx); print "wx = " + str(wx); print; rootx = wx**2 - ax; print "rootx = " + str(rootx); Q2x = AN(rootx,field=True); print "Q2x = " + str(Q2x.factory()); [ex2,w2x2,ax2,wx] = Q2x.gens(); #print "ex2 = " + str(ex2); #print "w2x2 = " + str(w2x2); #print "ax2 = " + str(ax2); #print "wx = " + str(wx); print; Yr = PolyRing(Q2x,"y,z",PolyRing.lex) print "Yr = " + str(Yr); [e,w2,x,wx,y,z] = Yr.gens(); print "e = " + str(e); print "w2 = " + str(w2); print "x = " + str(x); print "wx = " + str(wx); print "y = " + str(y); print "z = " + str(z); print; f1 = ( y**2 - x ) * ( y**2 - 2 ); #f1 = ( y**2 - x )**3 * ( y**2 - 2 )**2; f2 = ( z**2 - y**2 ); print "f1 = ", f1; print "f2 = ", f2; print; F = Yr.ideal( list=[f1,f2] ); print "F = ", F; print; #sys.exit(); startLog(); t = System.currentTimeMillis(); P = F.primeDecomp(); #P = F.primaryDecomp(); t1 = System.currentTimeMillis() - t; print "P = ", P; print; print "prime/primary decomp time =", t1, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/solvablemodule.py0000644000175000017500000000154011774031074017554 0ustar giovannigiovanni# # jython examples for jas. # $Id: solvablemodule.py 3972 2012-07-01 11:19:24Z kredel $ # from jas import SolvableModule from jas import SolvableSubModule # Quantum plane example rsan = """ AN[ (i) (i^2 + 1) ] (Y,X,x,y) G RelationTable ( ( y ), ( x ), ( {i} x y ) ( X ), ( Y ), ( {i} Y X ) ) """; rsc = """ C(Y,X,x,y) G |2| RelationTable ( ( y ), ( x ), ( 0i1 x y ) ( X ), ( Y ), ( 0i1 Y X ) ) """; r = SolvableModule( rsc ); #r = SolvableModule( rsan ); print "SolvableModule: " + str(r); print; ps = """ ( ( ( x + 1 ), ( y ) ), ( ( x y ), ( 0 ) ), ( ( x - X ), ( x - X ) ), ( ( y - Y ), ( y - Y ) ) ) """; f = SolvableSubModule( r, ps ); print "SolvableSubModule: " + str(f); print; flg = f.leftGB(); print "seq left GB:", flg; print; ftg = f.twosidedGB(); print "seq twosided GB:", ftg; print; # split term order not supported for rightGB jas-2.5/examples/katsura.py0000644000175000017500000000155011143314276016210 0ustar giovannigiovanni# # jython examples for jas. # $Id: katsura.py 2418 2009-02-07 14:20:47Z kredel $ # from jas import Ring from jas import Ideal from edu.jas.gb import Katsura; # katsura examples knum = 4 tnum = 2; #r = Ring( "Mod 19 (B,S,T,Z,P,W) L" ); #r = Ring( "Mod 1152921504606846883 (B,S,T,Z,P,W) L" ); # 2^60-93 #r = Ring( "Quat(B,S,T,Z,P,W) L" ); #r = Ring( "Z(B,S,T,Z,P,W) L" ); #r = Ring( "C(B,S,T,Z,P,W) L" ); #r = Ring( "Rat(B,S,T,Z,P,W) L" ); #print "Ring: " + str(r); #print; k = Katsura(knum); r = Ring( k.varList("Rat","G") ); print "Ring: " + str(r); print; ps = k.polyList(); f = Ideal( r, ps ); print "Ideal: " + str(f); print; rg = f.parGB(tnum); for th in range(tnum,0,-1): rg = f.parGB(th); #print "par Output:", rg; #print; rg = f.GB(); #print "seq Output:", rg; print; # rg = f.distGB(2); #print "dist Output:", rg; #print; #f.distClient(); jas-2.5/examples/factors_algebp_trans_charp.py0000644000175000017500000000470711415445670022111 0ustar giovannigiovanni# # jython examples for jas. # $Id: factors_algebp_trans_charp.py 3220 2010-07-08 22:05:44Z kredel $ # import sys from java.lang import System from java.lang import Integer from jas import Ring from jas import PolyRing from jas import Ideal from jas import ZM, QQ, AN, RF from jas import terminate from jas import startLog # polynomial examples: factorization over Z_p(x)(sqrt3(x))[y] Q = PolyRing(ZM(5),"x",PolyRing.lex); print "Q = " + str(Q); [e,a] = Q.gens(); #print "e = " + str(e); print "a = " + str(a); Qr = RF(Q); print "Qr = " + str(Qr.factory()); [er,ar] = Qr.gens(); #print "er = " + str(er); #print "ar = " + str(ar); print; Qwx = PolyRing(Qr,"wx",PolyRing.lex); print "Qwx = " + str(Qwx); [ewx,ax,wx] = Qwx.gens(); #print "ewx = " + str(ewx); print "ax = " + str(ax); print "wx = " + str(wx); print; #rootx = wx**5 - 2; # not working #rootx = wx**5 - 1/ax; #rootx = wx**5 - ax; #rootx = wx**5 - ( ax**2 + 3 * ax ); rootx = wx**5 - ( ax**2 + 3 / ax ); print "rootx = " + str(rootx); Q2x = AN(rootx,field=True); print "Q2x = " + str(Q2x.factory()); [ex2,ax2,wx] = Q2x.gens(); #print "ex2 = " + str(ex2); #print "w2x2 = " + str(w2x2); #print "ax2 = " + str(ax2); #print "wx = " + str(wx); print; #Yr = PolyRing(Q2x,"y,z,c0,c1,c2",PolyRing.lex) Yr = PolyRing(Q2x,"y,z",PolyRing.lex) print "Yr = " + str(Yr); #[e,x,wx,y,z,c0,c1,c2] = Yr.gens(); [e,x,wx,y,z] = Yr.gens(); print "e = " + str(e); print "x = " + str(x); print "wx = " + str(wx); print "y = " + str(y); print "z = " + str(z); print; #f = ( y**2 - x ); f = ( y**2 - ( wx ) ); #f = ( y**2 - ( 1 / wx ) ); #f = ( y**2 - ( wx**2 + wx + 2 ) + z**2 + y * wx ); #f = wx**3; print "f = ", f; print; f = f**5; print "f = ", f; print; #g = ( y**2 + ( c0 + c1 * wx + c2 * wx**2 ) ); #print "g = ", g; #g = g**5; #print "g = ", g; #print; #sys.exit(); startLog(); t = System.currentTimeMillis(); #ok: G = Yr.factors(f); G = Yr.squarefreeFactors(f); t = System.currentTimeMillis() - t; print "G = ", G; #print "factor time =", t, "milliseconds"; #sys.exit(); print "f = ", f; g = e; for h, i in G.iteritems(): if i > 1: print "h**i = ", h, "**" + str(i); else: print "h = ", h; h = h**i; g = g*h; print "g = ", g; if cmp(f,g) == 0: print "factor time =", t, "milliseconds,", "isFactors(f,g): true" ; else: print "factor time =", t, "milliseconds,", "isFactors(f,g): ", cmp(f,g); print; #startLog(); terminate(); jas-2.5/examples/katsura6w.jas0000644000175000017500000000141011353207070016601 0ustar giovannigiovanni#Katsura equations for N = 6: (u6,u5,u4,u3,u2,u1,u0) W(1,1,1,1,1,1,1) ( u6*u6 + u5*u5 + u4*u4 + u3*u3 + u2*u2 + u1*u1 + u0*u0 + u1*u1 + u2*u2 + u3*u3 + u4*u4 + u5*u5 + u6*u6 - u0, u6*0 + u5*u6 + u4*u5 + u3*u4 + u2*u3 + u1*u2 + u0*u1 + u1*u0 + u2*u1 + u3*u2 + u4*u3 + u5*u4 + u6*u5 - u1, u6*0 + u5*0 + u4*u6 + u3*u5 + u2*u4 + u1*u3 + u0*u2 + u1*u1 + u2*u0 + u3*u1 + u4*u2 + u5*u3 + u6*u4 - u2, u6*0 + u5*0 + u4*0 + u3*u6 + u2*u5 + u1*u4 + u0*u3 + u1*u2 + u2*u1 + u3*u0 + u4*u1 + u5*u2 + u6*u3 - u3, u6*0 + u5*0 + u4*0 + u3*0 + u2*u6 + u1*u5 + u0*u4 + u1*u3 + u2*u2 + u3*u1 + u4*u0 + u5*u1 + u6*u2 - u4, u6*0 + u5*0 + u4*0 + u3*0 + u2*0 + u1*u6 + u0*u5 + u1*u4 + u2*u3 + u3*u2 + u4*u1 + u5*u0 + u6*u1 - u5, u6 + u5 + u4 + u3 + u2 + u1 + u0 + u1 + u2 + u3 + u4 + u5 + u6 - 1 ) jas-2.5/examples/radical-decomp_charp.py0000644000175000017500000000177111377546034020574 0ustar giovannigiovanni# # jython examples for jas. # $Id: radical-decomp_charp.py 3157 2010-05-27 19:46:36Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import terminate from jas import startLog from jas import QQ, ZM # polynomial examples: ideal radical decomposition, dim > 0, char p separable #r = Ring( "Rat(x) L" ); #r = Ring( "Q(x) L" ); r = PolyRing(ZM(5),"x,y,z",PolyRing.lex); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); #f1 = (x**2 - 5)**2; #f1 = (y**10 - x**5)**3; f2 = y**6 + 2 * x * y**4 + 3 * x**2 * y**2 + 4 * x**3; f2 = f2**5; f3 = z**10 - x**5; f4 = (y**2 - x)**3; #print "f1 = ", f1; print "f2 = ", f2; print "f3 = ", f3; #print "f4 = ", f4; print; F = r.ideal( list=[f2,f3] ); print "F = ", F; print; startLog(); t = System.currentTimeMillis(); R = F.radicalDecomp(); t = System.currentTimeMillis() - t; print "R = ", R; print; print "decomp time =", t, "milliseconds"; print; print "F = ", F; print; #startLog(); terminate(); jas-2.5/examples/trinks_s.py0000644000175000017500000000367311225726560016406 0ustar giovannigiovanni# # jython examples for jas. # $Id: trinks_s.py 2730 2009-07-10 21:06:57Z kredel $ # import sys; from jas import Ring from jas import Ideal from jas import startLog from jas import terminate #import rational; # trinks 6/7 example #r = Ring( "Mod 19 (B,S,T,Z,P,W) L" ); #r = Ring( "Mod 1152921504606846883 (B,S,T,Z,P,W) L" ); # 2^60-93 #r = Ring( "Quat(B,S,T,Z,P,W) L" ); #r = Ring( "Z(B,S,T,Z,P,W) L" ); #r = Ring( "C(B,S,T,Z,P,W) L" ); #r = Ring( "Z(B,S,T,Z,P,W) L" ); #r = Ring( "IntFunc(e,f)(B,S,T,Z,P,W) L" ); r = Ring( "Z(B,S,T,Z,P,W) L" ); #r = Ring( "Q(B,S,T,Z,P,W) L" ); print "Ring: " + str(r); print; # sage like: with generators for the polynomial ring print "r.gens() = ", [ str(f) for f in r.gens() ]; print; #[one,e,f,B,S,T,Z,P,W] = r.gens(); [one,B,S,T,Z,P,W] = r.gens(); f1 = 45 * P + 35 * S - 165 * B - 36; f2 = 35 * P + 40 * Z + 25 * T - 27 * S; f3 = 15 * W + 25 * S * P + 30 * Z - 18 * T - 165 * B**2; f4 = - 9 * W + 15 * T * P + 20 * S * Z; f5 = P * W + 2 * T * Z - 11 * B**3; f6 = 99 * W - 11 *B * S + 3 * B**2; f7 = 10000 * B**2 + 6600 * B + 2673; #all ok: #f7 = f7 + e * f6**0; #f7 = f7 + 5959345574908321469098512640906154241024000000**2 * f6; #f7 = f7 + 35555./332 * f1; F = [ f1, f2, f3, f4, f5, f6, f7 ]; #F = [ f1, f2, f3, f4, f5, f6 ]; #print "F = ", [ str(f) for f in F ]; I = r.ideal( "", list=F ); print "Ideal: " + str(I); print; #sys.exit(); rg = I.GB(); print "seq Output:", rg; print; terminate(); sys.exit(); ps = """ ( ( 45 P + 35 S - 165 B - 36 ), ( 35 P + 40 Z + 25 T - 27 S ), ( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), ( - 9 W + 15 T P + 20 S Z ), ( P W + 2 T Z - 11 B**3 ), ( 99 W - 11 B S + 3 B**2 ), ( 10000 B**2 + 6600 B + 2673 ) ) """; # ( 10000 B**2 + 6600 B + 2673 ) # ( B**2 + 33/50 B + 2673/10000 ) #f = Ideal( r, ps ); #print "Ideal: " + str(f); #print; f = r.ideal( ps ); print "Ideal: " + str(f); print; #startLog(); rg = f.GB(); #print "seq Output:", rg; #print; terminate(); #sys.exit(); jas-2.5/examples/wa_39.jas0000644000175000017500000000037110653077260015611 0ustar giovannigiovanni# solvable polynomials, Weyl algebra A_3,9: (a,b,e1,e2,e3) G RelationTable ( ( e3 ), ( e1 ), ( e1 e3 - e3 ), ( e3 ), ( e2 ), ( e2 e3 - e1 ), ( e3 ), ( e1 ), ( e1 e3 + e2 ) ) ( ( e1 e3^3 + e2^2 - a ), ( e1^3 e2^2 + e3 ), ( e3^3 + e3^2 - b ) ) jas-2.5/examples/syzy3.rb0000644000175000017500000000103511653754360015620 0ustar giovannigiovanni# # jruby examples for jas. # $Id: syzy3.rb 3823 2011-11-01 11:33:05Z kredel $ # require "examples/jas" # ? example r = Ring.new( "Rat(x,y,z) L" ); print "Ring: " + str(r); print; ps = """ ( ( z^3 - y ), ( y z - x ), ( y^3 - x^2 z ), ( x z^2 - y^2 ) ) """; f = SimIdeal.new( r, ps ); print "Ideal: " + str(f); print; include_class "edu.jas.gbmod.SyzygyAbstract"; #startLog(); R = SyzygyAbstract.new().resolution( f.pset ); for i in 0..R.size() puts "\n #{i+1}. resolution"; puts "\n" + str(R[i]); end #terminate(); jas-2.5/examples/gcd.py0000644000175000017500000000176211224463142015275 0ustar giovannigiovanni# # jython examples for jas. # $Id: gcd.py 2717 2009-07-06 21:02:27Z kredel $ # from java.lang import System from java.lang import Integer from jas import Ring from jas import Ideal from jas import terminate from jas import startLog # polynomial examples: gcd #r = Ring( "Mod 1152921504606846883 (x,y,z) L" ); r = Ring( "Rat(x,y,z) L" ); #r = Ring( "C(x,y,z) L" ); #r = Ring( "Z(x,y,z) L" ); print "Ring: " + str(r); print; [one,x,y,z] = r.gens(); a = r.random(); b = r.random(); c = abs(r.random()); #c = 1; #a = 0; print "a = ", a; print "b = ", b; print "c = ", c; print; ac = a * c; bc = b * c; print "ac = ", ac; print "bc = ", bc; print; t = System.currentTimeMillis(); d = r.gcd(ac,bc); t = System.currentTimeMillis() - t; #d = d.monic(); print "d = ", d; m = c % d; ## print "m = ", m; ## print; if m.isZERO(): print "gcd time =", t, "milliseconds,", "isGcd(c,d): true" ; else: print "gcd time =", t, "milliseconds,", "isGcd(c,d): ", str(m); print; #startLog(); terminate(); jas-2.5/examples/nabeshima_cgbF2.rb0000644000175000017500000000156611653002012017436 0ustar giovannigiovanni# # jruby examples for jas. # $Id: nabeshima_cgbF2.rb 3815 2011-10-29 13:47:55Z kredel $ # require "examples/jas" # Nabashima, ISSAC 2007, example F2 # integral function coefficients r = Ring.new( "IntFunc(b, a) (x,y) L" ); puts "Ring: " + str(r); puts; ps = """ ( ( { a } x^2 y^3 + { b } y + y ), ( x^2 y^2 + x y + 2 ), ( { a } x^2 + { b } y + 2 ) ) """; #startLog(); f = r.paramideal( ps ); puts "ParamIdeal: " + str(f); puts; gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); gs = f.CGBsystem(); puts "CGBsystem: " + str(gs); puts; #sys.exit(); bg = gs.isCGBsystem(); if bg puts "isCGBsystem: true"; else puts "isCGBsystem: false"; end puts; #exit(); gs = f.CGB(); puts "CGB: " + str(gs); puts; bg = gs.isCGB(); if bg puts "isCGB: true"; else puts "isCGB: false"; end puts; terminate(); #------------------------------------------ #exit(); jas-2.5/examples/cgb_4.py0000644000175000017500000000227111773563306015526 0ustar giovannigiovanni# # jython examples for jas. # $Id: cgb_4.py 3967 2012-06-30 11:45:11Z kredel $ # import sys; from jas import Ring, PolyRing, ParamIdeal, QQ from jas import startLog from jas import terminate # 2 univariate polynomials of degree 2 example for comprehensive GB # integral/rational function coefficients #rp = PolyRing(QQ(), "a,b" ); rp = PolyRing(QQ(), "a" ); r = PolyRing( rp, "x,y,z", PolyRing.lex ); print "Ring: " + str(r); print; #one,a,b,x,y = r.gens(); one,a,x,y,z = r.gens(); #f1 = x * ( x**2 + a * y + b ); #f2 = x * ( y**2 + b * x + a ); f1 = ( x**2 + a * y**2 - x ); f2 = ( a * x**2 + y**2 - y ); f3 = ( x - y ) * z - 1; print "f1 = " + str(f1); print "f2 = " + str(f2); print "f3 = " + str(f3); f = r.paramideal( "", list=[f1,f2,f3] ); print "ParamIdeal: " + str(f); print; #sys.exit(); # long run time startLog(); gs = f.CGBsystem(); print "CGBsystem: " + str(gs); print; #sys.exit(); bg = gs.isCGBsystem(); if bg: print "isCGBsystem: true"; else: print "isCGBsystem: false"; print; #sys.exit(); gs = f.CGB(); print "CGB: " + str(gs); print; terminate(); sys.exit(); bg = gs.isCGB(); if bg: print "isCGB: true"; else: print "isCGB: false"; print; terminate(); jas-2.5/examples/roots_real_tower.py0000644000175000017500000000241111543344330020122 0ustar giovannigiovanni# # jython examples for jas. # $Id: roots_real_tower.py 3581 2011-03-26 11:07:05Z kredel $ # import sys; from java.lang import System from java.lang import Integer from jas import Ring, PolyRing from jas import QQ, DD, EF from jas import terminate from jas import startLog # polynomial examples: real root tower over Q r = EF(QQ()).realExtend("q","q^3 - 3", "[1,2]").realExtend("w", "w^2 - q", "[1,2]").realExtend("s", "s^5 - 2", "[1,2]").polynomial("x").build(); print "Ring: " + str(r); print; [one,q,w,s,x] = r.gens(); print "one = " + str(one); print "q = " + str(q); print "w = " + str(w); print "s = " + str(s); print "x = " + str(x); print; f = x**2 - w * s; print "f = ", f; print; startLog(); t = System.currentTimeMillis(); R = r.realRoots(f); t = System.currentTimeMillis() - t; #print "R = ", R; print "R = ", [ a.elem.ring.getRoot() for a in R ]; print "real roots time =", t, "milliseconds"; #sys.exit(); eps = QQ(1,10) ** (DD().elem.DEFAULT_PRECISION); print "eps = ", eps; t = System.currentTimeMillis(); R = r.realRoots(f,eps); t = System.currentTimeMillis() - t; #print "R = ", [ str(r) for r in R ]; print "R = ", [ a.elem.decimalMagnitude() for a in R ]; print "real roots time =", t, "milliseconds"; print; #startLog(); terminate(); jas-2.5/COPYING0000644000175000017500000004307610210372004013375 0ustar giovannigiovanni GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. jas-2.5/log4j.properties0000644000175000017500000000635412045530566015516 0ustar giovannigiovanni# $Id: log4j.properties 4293 2012-11-04 18:18:30Z kredel $ #log4j.debug=true # Set root category priority to INFO and set its appender to log # categories: DEBUG, INFO, WARN, ERROR, FATAL # log4j.rootCategory=INFO, log, err, sys # log4j.rootCategory=WARN, log #log4j.rootCategory=WARN log4j.rootCategory=INFO, null #log4j.rootCategory=INFO, out #log4j.rootCategory=WARN, out #log4j.rootCategory=DEBUG, log #log4j.rootCategory=DEBUG, out #### 'out' appender writes to System.out or System.err # out is set to be a ConsoleAppender (writes to system error/out). log4j.appender.out=org.apache.log4j.ConsoleAppender log4j.appender.out.target=System.out # out uses PatternLayout. # log4j.appender.out.layout=org.apache.log4j.SimpleLayout log4j.appender.out.layout=org.apache.log4j.PatternLayout #log4j.appender.out.layout.ConversionPattern=%c - %m%n #log4j.appender.out.layout.ConversionPattern=[%t] %-5p %c - %m%n log4j.appender.out.layout.ConversionPattern=%-4r [%t] %-5p %c - %m%n # log4j.appender.out.layout.ConversionPattern=%-5p %t %c - %m%n # log4j.appender.out.layout.ConversionPattern=[%t] %-5p %c %x - %m%n # log4j.appender.out.layout.ConversionPattern=%d{ISO8601} %-4r [%t] %-5p %c %x - %m%n # log4j.appender.out.layout.ConversionPattern=[%t] %c - %m%n #### 'log' appender writes to a file log4j.appender.log=org.apache.log4j.RollingFileAppender log4j.appender.log.File=test/jastest.log # Control the maximum log file size log4j.appender.log.MaxFileSize=1000KB # Archive log files (ten backup file here) log4j.appender.log.MaxBackupIndex=10 # log4j.appender.log.layout=org.apache.log4j.HTMLLayout # log4j.appender.log.layout=org.apache.log4j.SimpleLayout log4j.appender.log.layout=org.apache.log4j.PatternLayout log4j.appender.log.layout.ConversionPattern=%-4r [%t] %-5p %c - %m%n # log4j.appender.log.layout.ConversionPattern=%-5p [%t] %c - %m%n # log4j.appender.log.layout.ConversionPattern=%-4r %-5p [%t,%X{hostname}] %c - %m%n # log4j.appender.log.layout.ConversionPattern=%p %t %c - %m%n # log4j.appender.log.layout.ConversionPattern=[%t] %c - %m%n #### 'err' appender writes to System.out or System.err # err is set to be a ConsoleAppender (writes to system error). log4j.appender.err=org.apache.log4j.ConsoleAppender log4j.appender.err.target=System.err # err uses PatternLayout. # log4j.appender.err.layout=org.apache.log4j.SimpleLayout log4j.appender.err.layout=org.apache.log4j.PatternLayout log4j.appender.err.layout.ConversionPattern=%-4r [%t] %-5p %c - %m%n # log4j.appender.err.layout.ConversionPattern=%-5p %t %c - %m%n # log4j.appender.err.layout.ConversionPattern=[%t] %-5p %c %x - %m%n # log4j.appender.err.layout.ConversionPattern=%d{ISO8601} %-4r [%t] %-5p %c %x - %m%n # log4j.appender.err.layout.ConversionPattern=[%t] %c - %m%n #### 'sys' appender writes to remote syslog #### needs syslogd -r on target, see /etc/sysconfig/syslog log4j.appender.sys=org.apache.log4j.net.SyslogAppender log4j.appender.sys.layout=org.apache.log4j.PatternLayout log4j.appender.sys.syslogHost=localhost log4j.appender.sys.facility=user # log4j.appender.sys.facility=local0 # log4j.appender.sys.facilityPrinting=true # log4j.appender.sys.layout.ConversionPattern=%-4r [%t] %-5p %c - %m%n #### 'null' appender writes to /dev/null log4j.appender.null=org.apache.log4j.varia.NullAppender jas-2.5/problems.html0000644000175000017500000005167310405021104015053 0ustar giovannigiovanni JAS - Designs, Problems and Solutions

JAS - Designs, Problems and Solutions

In ths document we discus some design alternatives, some problems and present our implemented solutions.

1. Designs

Note: In this section 'base ring' and 'extension ring' mean object oriented concepts not the mathematical concepts. I.e. 'base ring' is the super class of all considered ring classes and 'extension ring' is some subclass of the 'base ring' class.

The first question is which classes or which objects implement the arithmetic of polynomials. Are polynomials only passive containers which are transformed by ring methods? Or are polynomials active objects with methods.

1.1. Ring is object with methods

One design was proposed e.g. by M. Conrad in 2002 (see ring.perisic.com). It starts with an abstract Ring with abstract methods for the ring operations and some real implementations, e.g. for powers. The method parameters are RingElts, which serve mostly as containers for the different ring implementations. The concrete rings, e.g. rational numbers or polynomials, extend Ring and implement the algortihms for the respective (extended) RingElt data structures. RingElt structures are moreover mostly private classes within their corresponding Ring extension.

Type resolution of the parameters of the methods is completely dynamic during runtime. There is no compile time type checking. The type resolution, by means of a RingX.map(RingElt) method, is moreover able to coerce elements from one ring to some other ring, e.g. form rational to polynomial over rationals, similar to Scratchpad. The base Ring knows about all extension rings, like in a closed world.

Creation of extension rings is mainly at initialization time of the base ring (since it knows all extensions) into ring properties. Creation of ring elements is mostly dynamic using direct constructors in the various map() methods.

1.2. Polynomial is object with methods

An other design, e.g. used in our approach, takes polynomials as the primary players. A Polynomial is implemented as a class with the usual algebraic operations as methods. Each polynomial has a reference to a corresponding Ring object, which is a container for the ring characteristics. E.g. for polynomial rings these are the number of variables, the type information of the coefficent ring, the term order, the names of the variables and eventualy the commutator relations. There is one proposal by V. Niculescu, from 2003, [ref: A design proposal for an object oriented algebraic library] to view and implement the Ring as a factory class for polynomials and to make the polynomial constructors unavailable.

Creation of ring elements was in our first design by employing the prototype creational pattern (via clone()) and directly using element constructors. In the new design it will use the factory pattern (via getZERO(), getONE() etc.) of the RingFactory

Type resolution of the coefficient or polynomial method parameters are to the respective interface during compile time with a dynamic upcast to the actual polynomial or coefficient during runtime. There is currently no mapping of elements from one ring to another. However there are conversions / constructor / parser methods from long, java.math.BigInteger, String and java.io.Reader in the new design.

1.3. Template, generics and type parameter approaches

These approaches may not be completely covered by Java, C++ or C#. For polynomials they mean the usage of a type parameter (eventually restricted to some unterface) for the coefficient ring.

The creation problem is difficult to solve in Java, since type parameters can not be used in new or class.newInstance(). I.e. new objects can not be generated only from a type parameter but only from an object or class.

2. Problems

During the development and refactorings some problems have been detected. Consider the following interface and class definitions.

interface ModulElem {
  ModulElem sum(ModulElem other);
  ...
}

interface RingElem extends ModulElem {
  // RingElem sum(RingElem other); no override
  RingElem multiply(RingElem other);
  ...
}

class Rational implements RingElem { // jdk 1.5

  /*ModulElem*/ Rational sum(ModulElem other) {
  ...
  }

  /*RingElem*/  Rational multiply(RingElem other) {
     if ( other instanceof Rational ) {
        return multiply( (Rational)other );
     } else { 
        return // coerce to suitable ring extension
     }
  }

  Rational multiply(Rational other) {
  ...
  }

}

class Complex implements RingElem {
  ...
}

  void usageOK() {
    Rational a = new Rational();
    Rational b = new Rational();
    Rational c;
    c = a.sum(b);       // jdk 1.5
    c = a.multiply(b);  // jdk 1.5
  }

  void usageProblem1() {
    RingElem a = new Rational();
    RingElem b = new Rational();
    RingElem c;
    c = (RingElem) a.sum(b); // must cast
    c = a.multiply(b);       // no cast
  }

  void usageProblem2() {
    RingElem a = new Rational();
    RingElem b = new Complex();
    RingElem c;
    c = a.multiply(b); // runtime failiure
  }

One problem is the cast in c = (RingElem)a.sum(b) which is not expected since a and b are RingElems. One sulution would be to redefine sum() for RingElem, but then sum() in ModulElem is not overriden. Then RingElem is no longer an extension of ModulElem and the relation between the interfaces is broken.

The other problem is 'up cast' in return multiply( (Rational)other ) which defeates compile time type safety. multiply( ) is at first not meaningful defined between Rational and Complex. One could as in Scratchpad coerce Rational to Complex (here extend) and multiply to Complex objects, but this may not be expected by the application.

This problems exist also if abstract classes are used instead of interfaces.

3. Solutions

Reflecting on the mentioned designs and problems our design proposal is as follows.

  1. We do not distinguish between interfaces for modules, rings or fields. There is only one interface for rings, wich also defines inverse() and quotient() together with a method isUnit() to see if a certain element is invertible or can be used as divisor.

  2. To separate the creation process of ring elements from the implementation of the ring element abstract data type we distinguish two interfaces: RingElem<C extends RingElem> and RingFactory<C extends RingElem>.

  3. RingElem uses a type parameter C which is itself recursively reqired to extend RingElem: C extends RingElem. Also the interface RingFactory depends on the same type parameter.

  4. Basic data types, such as rational numbers, can directly implement both interfaces but more complex data types, such as polynomials will implement the interfaces in two different classes. e.g.

    BigRational implements RingElem<BigRational>, RingFactory<BigRational>
    

    or for generic polynomials

    GenPolynomial<C extends RingElem<C> > implements RingElem< GenPolynomial<C> >
    
    GenPolynomialRing<C extends RingElem<C> > implements RingFactory< GenPolynomial<C> >
    
  5. Constructors for basic data types can be implemented in any appropriate way. Constructors for more complex data types should always require one parameter to be of the respective factory type. This is to avoid the creation of elements with no knowledge of is corresponding ring factory. Constructors which require more preconditions, which are only provided by type (internal) methods should not be declared public. It seems best to declare them as protected.

  6. Basic arithmetic is implemented using the java.math.BigInteger class, which is itself implemented like GnuMP. At the moment the following classes are implemented BigInteger, BigRational, ModInteger, BigComplex, BigQuaternion and AlgebraicNumber.

  7. Generic polynomials are implemented as sorted maps from exponent vectors to coefficients. For sorted map the Java class java.util.TreeMap is used. The older alternative implementation using Map, implemented with java.util.LinkedHashMap, has been abandoned. There is only one implementation of exponent vectors ExpVector as dense Java array of longs. Other implementations, e.g. sparse representation or bigger numbers or ints are not considered at the moment. The comparators for SortedMap<ExpVector,C> are created from a TermOrder class which implements most used term orders in practice.

  8. Non commutative polynomials with respect to certain commutator relations, so called solvable polynomials, are extended from GenPolynomial respectively GenPolynomialRing. The relations are stored in RelationTable objects, which are inteded to be internal to the GenSolvablePolynomialRing. The class GenSolvablePolynomial implements the non commutative multiplication and uses the commutative methods from its super class GenPolynomial. As mentioned before, some casts are eventualy required, e.g. GenSolvablePolynomial<C> p.sum(q). The respective objects are however correctly buildt using the methods from the solvable ring factory.
    The class design allows solvable polynomial objects to be used in all algorithms where GenPolynomials can be used as parameters as long as no distinction between left and right multiplication is required.

3.1. Interfaces

The interface definition for ring elements with the usual arithmetic operations and some status, comparison methods and a clone method is as follows.

public interface RingElem<C extends RingElem> 
                 extends Cloneable, 
                         Comparable<C>, 
                         Serializable {
    public C clone();

    public boolean isZERO();
    public boolean isONE();
    public boolean isUnit();
    public boolean equals(Object b);
    public int     hashCode();
    public int     compareTo(C b);
    public int     signum();

    public C sum(C S);
    public C subtract(C S);
    public C negate();
    public C abs();
    public C multiply(C S);
    public C divide(C S);
    public C remainder(C S);
    public C inverse();
}

The interface definition for a ring factory for the creation respectively the reference to the ring constants 0 and 1 is given in the following code. Moreover there are often used casts / conversions from the basic Java types long and BigInteger, as well as a method to create a random element of the ring, a counter part to clone and some parsing methods to obtain a ring element from some external String or Reader.

public interface RingFactory<C extends RingElem> 
                 extends Serializable {
    public C getZERO();
    public C getONE();

    public C fromInteger(long a);
    public C fromInteger(BigInteger a);

    public C random(int n);
    public C copy(C c);

    public C parse(String s);
    public C parse(Reader r);
}

3.2. Some constructors

Constructors for BigRational:

    protected BigRational(BigInteger n, BigInteger d)
              // assert gcd(n,d) == 1
    public BigRational(BigInteger n)
    public BigRational(long n, long d)
    public BigRational(long n)
    public BigRational()
    public BigRational(String s) throws NumberFormatException

Constructors for GenPolynomial

    public GenPolynomial(GenPolynomialRing< C > r) 
    public GenPolynomial(GenPolynomialRing< C > r, SortedMap<ExpVector,C> v) 
    public GenPolynomial(GenPolynomialRing< C > r, C c, ExpVector e)

Constructors for GenPolynomialRing

    public GenPolynomialRing(RingFactory< C > cf, int n) 
    public GenPolynomialRing(RingFactory< C > cf, int n, TermOrder t) {
    public GenPolynomialRing(RingFactory< C > cf, int n, TermOrder t, String[] v)

3.3. Polynomial examples

Example of a random polynomial in 7 variables over the rational numbers with default term order and with 10 non zero coefficients:

   BigRational cfac = new BigRational();
   GenPolynomialRing<BigRational> fac;
                fac = new GenPolynomialRing<BigRational>(cfac,7);

   GenPolynomial<BigRational> a = fac.random(10);

a = GenPolynomial[ 31/5 (0,0,0,1,2,1,2), 19/15 (2,0,0,0,0,0,2), 
    13/5 (0,2,1,1,0,0,0), 2/3 (0,0,2,0,0,0,0), 217/18 (0,0,0,2,0,0,0), 
    18/5 (0,0,0,0,2,0,0), 11/32 (1,0,0,0,0,0,0), 63/4 (0,0,0,0,0,0,0) ] 
    :: GenPolynomialRing[ BigRational, 7, IGRLEX(4),  ]

Example of a random polynomial in 3 variables over a polynomial ring in 7 variables over the rational numbers, both with default term order and with 10 non zero coefficients:

   BigRational cfac = new BigRational();
   GenPolynomialRing<BigRational> fac;
                fac = new GenPolynomialRing<BigRational>(cfac,7);

   GenPolynomialRing<GenPolynomial<BigRational>> gfac;
               gfac = new GenPolynomialRing<GenPolynomial<BigRational>>(fac,3);

   GenPolynomial<GenPolynomial<BigRational>> a = gfac.random(10);

a = GenPolynomial[ 
       GenPolynomial[ 10/3 (2,0,1,1,0,0,2), 8/7 (1,0,2,0,0,0,0), 
         9/5 (0,1,0,0,0,0,0), 1/4 (0,0,1,0,0,0,0), 3/14 (0,0,0,0,0,0,0) ] 
         :: GenPolynomialRing[ BigRational, 7, IGRLEX(4),  ] (2,1,0), 
       GenPolynomial[ 26/23 (0,2,2,0,1,0,2), 9/4 (1,0,0,0,0,1,1), 
         29/17 (0,0,2,0,1,0,0), 24/19 (2,0,0,0,0,0,0), 28/13 (1,0,0,1,0,0,0), 
         11/32 (0,0,1,0,1,0,0), 18/11 (1,0,0,0,0,0,0), 5/11 (0,0,0,0,1,0,0), 
         475/32 (0,0,0,0,0,0,0) ] 
         :: GenPolynomialRing[ BigRational, 7, IGRLEX(4),  ] (2,0,0), 
       GenPolynomial[ 14/15 (2,0,0,1,1,0,2), 19/5 (1,1,0,0,0,0,0), 
         4/29 (0,0,2,0,0,0,0), 23/27 (0,0,0,2,0,0,0), 20/13 (0,0,0,0,0,0,0) ] 
         :: GenPolynomialRing[ BigRational, 7, IGRLEX(4),  ] (0,0,2), 
       GenPolynomial[ 13/8 (2,0,0,1,1,0,0), 8/7 (2,0,0,0,0,0,2), 
         21/2 (0,0,1,0,0,0,2), 23/22 (0,1,0,0,0,1,0), 9/11 (0,0,0,2,0,0,0), 
         21/2 (0,0,0,0,2,0,0), 23/13 (0,0,0,0,0,2,0), 5/2 (0,1,0,0,0,0,0), 
         367/62 (0,0,0,0,0,0,0) ] 
         :: GenPolynomialRing[ BigRational, 7, IGRLEX(4),  ] (1,0,0), 
       GenPolynomial[ 4/3 (0,1,0,1,2,1,1), 17/2 (2,1,0,0,2,0,0), 
         10/29 (1,0,0,0,0,2,2), 3/2 (0,0,2,2,0,0,1), 11/8 (2,0,0,0,0,0,2), 
         26/31 (0,2,1,0,0,0,0), 10/9 (0,0,1,2,0,0,0), 4/5 (0,0,1,0,0,2,0), 
         1/8 (2,0,0,0,0,0,0), 1161/406 (0,2,0,0,0,0,0), 31/6 (0,0,0,2,0,0,0), 
         19 (0,0,1,0,0,0,0), 2 (0,0,0,0,0,1,0), 7/19 (0,0,0,0,0,0,1), 
         20227/2520 (0,0,0,0,0,0,0) ] 
         :: GenPolynomialRing[ BigRational, 7, IGRLEX(4),  ] (0,0,0) ] 
    :: GenPolynomialRing[ GenPolynomialRing, 3, IGRLEX(4),  ]

3.4. Algebraic number examples

Example of algebraic numbers

  AlgebraicNumber<C extends RingElem<C> > 
                 implements RingElem< AlgebraicNumber<C> >, 
                            RingFactory< AlgebraicNumber<C> >

over rational numbers (so defining an algebraic extension Q(alpha))

   BigRational cfac = new BigRational();

   GenPolynomialRing<BigRational> mfac;
       mfac = new GenPolynomialRing<BigRational>( cfac, 1 );

   GenPolynomial<BigRational> modul = mfac.random(8).monic();
       // assume !modul.isUnit()

   AlgebraicNumber<BigRational> fac;
       fac = new AlgebraicNumber<BigRational>( modul );

   AlgebraicNumber< BigRational > a = fac.random(15);

modul = GenPolynomial[ 1 (2), 13/12 (1), 55/21 (0) ] 
        :: GenPolynomialRing[ BigRational, 1, IGRLEX(4),  ]

a = AlgebraicNumber[ 
       GenPolynomial[ 1 (1), -175698982/14106209 (0) ] 
       :: GenPolynomialRing[ BigRational, 1, IGRLEX(4),  ] 
       mod 
       GenPolynomial[ 1 (2), 13/12 (1), 55/21 (0) ] 
       :: GenPolynomialRing[ BigRational, 1, IGRLEX(4),  ] ]

or modular integers (so defining a Galois field GF(p,n)).

   long prime = getPrime(); // 2^60-93
   ModInteger cfac = new ModInteger(prime,1);

   GenPolynomialRing<ModInteger> mfac;
       mfac = new GenPolynomialRing<ModInteger>( cfac, 1 );

   GenPolynomial<ModInteger> modul = mfac.random(8).monic();
       // assume !modul.isUnit()

   AlgebraicNumber<ModInteger> fac;
       fac = new AlgebraicNumber<ModInteger>( modul );

   AlgebraicNumber< ModInteger > a = fac.random(12);

modul = GenPolynomial[                  1 mod(1152921504606846883) (2), 
                       123527304065019309 mod(1152921504606846883) (1), 
                       452933448238404135 mod(1152921504606846883) (0) ] 
        :: GenPolynomialRing[ ModInteger, 1, IGRLEX(4),  ]

a = AlgebraicNumber[ 
       GenPolynomial[                  1 mod(1152921504606846883) (1), 
                      384307168202282226 mod(1152921504606846883) (0) ] 
       :: GenPolynomialRing[ ModInteger, 1, IGRLEX(4),  ] 
       mod 
       GenPolynomial[                  1 mod(1152921504606846883) (2), 
                      123527304065019309 mod(1152921504606846883) (1), 
                      452933448238404135 mod(1152921504606846883) (0) ] 
       :: GenPolynomialRing[ ModInteger, 1, IGRLEX(4),  ] ]

3.5. Solvable polynomial examples

Example for the creation of a solvable polynomial ring factory. The relation table is created internally.

     BigRational fac = new BigRational(0);
     TermOrder tord = new TermOrder(TermOrder.INVLEX);
     String[] vars = new String[]{ "x", "y", "z" };
     int nvar = vars.length;
     spfac = new GenSolvablePolynomialRing<BigRational>(fac,nvar,tord,vars);

spfac = GenSolvablePolynomialRing[ BigRational, 3, 
                                   INVLEX(2), x y z , 
                                   #rel = 0 ]
spfac.table = RelationTable[]

A non empty relation table looks as follows.

f = GenSolvablePolynomialRing[ BigRational, 3, INVLEX(2), x y z , #rel = 1 ]

f.ring.table = RelationTable[
               [0, 1]=[ExpVectorPair[(1,0,0),(0,1,0)], 
                       GenSolvablePolynomial[ 1 (1,1,0), -1 (0,0,0) ] 
                       :: GenSolvablePolynomialRing[ BigRational, 3, 
                                                     INVLEX(2), x y z , 
                                                     #rel = 1 ]
                      ]
               ]

Example of a solvable polynomial over Z_19.

d = GenSolvablePolynomial[ 3 mod(19) (1,1,0), 1 mod(19) (0,0,1) ] 
    :: GenSolvablePolynomialRing[ ModInteger, 3, INVLEX(2), x y z , #rel = 1 ]


Heinz Kredel

Last modified: Sun Mar 12 14:29:09 CET 2006

$Id: problems.html 787 2006-03-12 13:29:40Z kredel $

jas-2.5/gb-book.html0000644000175000017500000004057712137677610014600 0ustar giovannigiovanni JAS - Gröbner bases book

Gröbner bases book algorithms and JAS methods

Summary of algorithms from the Gröbner bases book and corresponding JAS classes and methods.

Gröbner bases book algorithms

The JAS base package edu.jas name is omitted in the following table. JAS also contains improved versions of the algorithms which may be located through the links. A short explanation of code organization with interfaces and several implementing classes can be found in the API guide.

GB book algorithm JAS interfaces, classes and methods remarks
0.1 DIVINT arith.BigInteger.divideAndRemainder adapter for java.math.BigInteger.divideAndRemainder
 
2.1 DIV structure.MonoidElem.divide and structure.MonoidElem.remainder all classes which implement this interface
2.2 DIVPOL poly.GenPolynomial.divideAndRemainder for univariate polynomials over fields
2.3 EXTEUC poly.GenPolynomial.egcd for univariate polynomials over fields
 
3.1 LINDEP not implemented
3.2 EXCHANGE not implemented
 
4.1 EQUIV structure.Residue.equals or application.Residue.equals arbitrary residue class rings and residue class rings modulo polynomial ideals
 
5.1 REDPOL gb.Reduction.normalform, gb.ReductionAbstract.normalform, gb.ReductionSeq.normalform interface and sequential computation class, the method exists also for polynomial lists and with a reduction recording matrix (this is exactly REDPOL)
5.2 REDUCTION gb.Reduction.irreducibleSet
5.3 GRÖBNERTEST gb.GroebnerBase.isGB provided by all classes which implement this interface
5.4 GRÖBNER not implemented
5.5 REDGRÖBNER gb.GroebnerBase.GB with gb.OrderedMinPairlist provided by all classes which implement the interface and allow the selection of the pair-list in a constructor
5.6 GRÖBNERNEW1 gb.GroebnerBase.GB with gb.OrderedPairlist provided by all classes which implement the interface and allow the selection of the pair-list in a constructor
5.7 UPDATE, 5.8 GRÖBNERNEW2 gb.GroebnerBase.GB with gb.OrderedSyzPairlist provided by all classes which implement the interface and allow the selection of the pair-list in a constructor
5.9 EXTGRÖBNER gb.GroebnerBase.extGB provided by some classes which implement the interface
 
6.1 ELIMINATION application.Ideal.eliminate the version with the String[] parameter computes a Gröbner base wrt. the corresponding elimination order
6.2 PROPER application.Ideal.isONE proper ideal test is ! id.isONE()
6.3 INTERSECTION application.Ideal.intersect for lists of ideals a simple iterative algorithm is used and for a pair of ideals it is the same algorithm
6.4 CRT not implemented
6.5 IDEALDIV1 application.Ideal.quotient for an ideal a simple iterative algorithm is used and for one polynomial it is an algorithm without computing syzygies
6.6 IDEALDIV2 application.Ideal.infiniteQuotientRab and application.Ideal.infiniteQuotientExponent the exponent is computed in a separate step at the moment
6.7 RADICALMEMTEST application.Ideal.isRadicalMember the exponent is not computed
6.8 SUBRINGMEMTEST not implemented
 
8.1 PREDEC application.Ideal.zeroDimDecomposition univariate polynomials of minimal degree in the ideal are irreducible and not a power of an irreducible polynomial as specified in PREDEC
8.2 ZRADICALTEST application.Ideal.isZeroDimRadical will also work in characteritsic p > 0
8.3 ZRADICAL application.Ideal.radical ZRADICAL is containted as special case, see also application.Ideal.zeroDimRadicalDecomposition
8.4 NORMPRIMDEC application.Ideal.zeroDimPrimaryDecomposition contains all preprocessing steps, see ZPRIMDEC
8.5 NORMPOS application.Ideal.normalPositionFor one step of NORMPOS as explained for the modified algorithm on page 383ff
8.6 ZPRIMDEC application.Ideal.zeroDimPrimaryDecomposition returns a list of PrimaryComponent containers
8.7 CONT application.Ideal.contraction more complicated since the permutation of variables must be considered also, see application.Ideal.permContraction, the polynomial f is returned in the IdealWithUniv container
8.8 EXTCONT application.Ideal.extension only EXT, the combination EXTCONT is not implemented explicitly, the polynomial f is returned in the IdealWithUniv container
8.9 RADICAL application.Ideal.radical for ideals with arbitrary dimension
8.10 PRIMDEC application.Ideal.primaryDecomposition for ideals with arbitrary dimension
8.11 VARSIGN root.RootUtil.signVar
8.12 STURMSEQ root.RealRootsSturm.sturmSequence
8.13 ISOLATE root.RealRoots.realRoots could also be used for real root isolations not using Sturm sequences
8.14 ISOREC root.RealRootsSturm.realRoots interval bi-section until a root is isolated
8.15 ISOREFINE root.RealRoots.refineInterval also for real root isolations not using Sturm sequences
8.16 SQUEEZE root.RealRoots.invariantMagnitudeInterval see also root.RealRoots.realMagnitude
8.17 REALZEROS application.PolyUtilApp.realAlgebraicRoots different algorithm and different result data structure with RealAlgebraicNumbers
 
9.1 REDTERMS gbufd.GroebnerBaseFGLM.redTerms
9.2 UNIVPOL application.Ideal.constructUnivariate
9.3 CONVGRÖBNER gbufd.GroebnerBaseFGLM.convGroebnerToLex See also gbufd.GroebnerBaseFGLM.GB. It computes a Gröbner base with respect to a graded term order and then uses FGLM to convert to a lexicographic term order
9.4 LMINTERM gbufd.GroebnerBaseFGLM.lMinterm
9.5 STRCONST not implemented
9.6 DIMENSION application.Ideal.dimension
 
10.1 D-GRÖBNER gb.DGroebnerBaseSeq.GB and gb.EGroebnerBaseSeq.GB


Heinz Kredel

Last modified: Tue Apr 30 10:19:32 CEST 2013

jas-2.5/meditor/0000755000175000017500000000000012140140260013774 5ustar giovannigiovannijas-2.5/meditor/services/0000755000175000017500000000000012140140260015617 5ustar giovannigiovannijas-2.5/meditor/services/jscl.editor.EngineFactory0000644000175000017500000000005111047325454022531 0ustar giovannigiovanniedu.jas.editorengine.EditorEngineFactory jas-2.5/meditor/meditor0000644000175000017500000000105711110373062015371 0ustar giovannigiovanni#!/bin/bash # script to call meditor with the jas engine # # $Id: meditor 2228 2008-11-17 22:54:43Z kredel $ LIBPATH=~/java/lib MEDITORPATH=~/java/meditor3.0 JASPATH=. UTILS=$LIBPATH/jython.jar:$LIBPATH/log4j.jar JAS=$JASPATH/jas.jar:$JASPATH/jas-meditor.jar if [[ ! -f "jas.py" ]]; then jar xf $JASPATH/jas-meditor.jar jas.py fi MEDITOR=$MEDITORPATH/meditor.jar:$MEDITORPATH/lib/jscl.jar CLASSPATH=$UTILS:$JAS:$MEDITOR:. mkdir -p test #####-Dpython.home=$JASPATH/examples java -classpath $CLASSPATH -Duser.home=$JASPATH/examples jscl.editor.Editor jas-2.5/meditor/manifest.mf0000644000175000017500000000053111047334124016136 0ustar giovannigiovanniManifest-Version: 1.0 Class-Path: retrotranslator-runtime-1.2.6.jar backport-util-concurrent-3.1.jar log4j.jar Name: edu/jas/editorengine/ Specification-Title: JAS Specification-Version: @VERSION@ Specification-Vendor: Heinz Kredel Implementation-Title: edu.jas.editorengine Implementation-Version: @SVNREV@ Implementation-Vendor: Heinz Kredel jas-2.5/meditor/Makefile0000644000175000017500000000256312004777612015462 0ustar giovannigiovanni# # $Id: Makefile 4083 2012-07-28 15:04:42Z kredel $ # # Makefile for the interface of JAS to meditor # by Raphael Jolly, Heinz kredel # #JASPATH=$(HOME)/jas JASPATH=.. LIBPATH=$(HOME)/java/lib MEDITORPATH=$(HOME)/java/meditor3.0 CLASSPATH=$(LIBPATH)/jython.jar:$(MEDITORPATH)/meditor.jar # incompatible with jython version #BOOTCLASSPATH4="/usr/java/j2sdk1.4.0/jre/lib/rt.jar" # javac -g -source 1.4 -target 1.4 -classpath $(CLASSPATH) -bootclasspath $(BOOTCLASSPATH4) -sourcepath src -d classes src/edu/jas/editorengine/*.java .SUFFIXES : .class .java .jar .PHONY : clean FILES=$(wildcard src/edu/jas/editorengine/*.java) #echo $(FILES) $(JASPATH)/examples/jas.py CLASSES=$(subst src,classes,$(subst java,class,$(FILES))) #echo $(CLASSES) all: jas-meditor.jar $(CLASSES): $(FILES) mkdir classes javac -g -source 1.4 -target 1.4 -classpath $(CLASSPATH) -sourcepath src -d classes src/edu/jas/editorengine/*.java jas-meditor.jar: $(CLASSES) $(JASPATH)/examples/jas.py manifest.mf services/jscl.editor.EngineFactory mkdir classes/META-INF mkdir classes/META-INF/services cp -a manifest.mf classes/META-INF/MANIFEST.MF cp -a services/jscl.editor.EngineFactory classes/META-INF/services/ jar cfM jas-meditor.jar -C classes . jar uf jas-meditor.jar -C $(JASPATH)/examples jas.py cp -f jas-meditor.jar $(LIBPATH) cp -f jas-meditor.jar .. rm -rf classes clean: rm -rf classes jas-2.5/meditor/src/0000755000175000017500000000000012140140260014563 5ustar giovannigiovannijas-2.5/meditor/src/edu/0000755000175000017500000000000012140140260015340 5ustar giovannigiovannijas-2.5/meditor/src/edu/jas/0000755000175000017500000000000012140140260016115 5ustar giovannigiovannijas-2.5/meditor/src/edu/jas/editorengine/0000755000175000017500000000000012140140260020571 5ustar giovannigiovannijas-2.5/meditor/src/edu/jas/editorengine/EditorEngine.java0000644000175000017500000000074711060053124024022 0ustar giovannigiovannipackage edu.jas.editorengine; import jscl.editor.Engine; import org.python.util.PythonInterpreter; public class EditorEngine extends Engine { PythonInterpreter interp=new PythonInterpreter(); public EditorEngine() { //interp.execfile(EditorEngine.class.getResourceAsStream("/jas.py")); } public String eval(String str) { if(str.lastIndexOf("\n")==str.length()-1) { interp.exec(str); return str; } else return interp.eval(str).__str__().toString(); } } jas-2.5/meditor/src/edu/jas/editorengine/EditorEngineFactory.java0000644000175000017500000000032511047325454025357 0ustar giovannigiovannipackage edu.jas.editorengine; import jscl.editor.Engine; import jscl.editor.EngineFactory; public class EditorEngineFactory extends EngineFactory { public Engine getEngine() { return new EditorEngine(); } } jas-2.5/meditor/.gitignore0000644000175000017500000000001511306031572015770 0ustar giovannigiovanni/test /*.jar jas-2.5/jython_tests.sh0000644000175000017500000000574711634731372015460 0ustar giovannigiovanni#!/bin/sh # run most py files time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/armbruster.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/intprog.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/intprog2.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/intprog3.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/intprog4.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/intprog4a.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/katsura.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/preimage.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/quantumplane.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/rose.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/solvablemodule.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/solvmodright.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/syz.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/syzsolv.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/syzy2.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/syzy3.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/trinks.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/mark.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/u_2_wa_1.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/u_sl_2.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/u_sl_2_e.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/u_sl_2_f.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/u_sl_2_wa_1.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/u_sl_3.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/u_sl_3_prod.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/u_so_3.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/wa_1.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/wa_32.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/wa_32_syz.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/chebyshev.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/legendre.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/arith.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/powerseries.py time jython -J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc examples/polynomial.py jas-2.5/spin/0000755000175000017500000000000012140140252013303 5ustar giovannigiovannijas-2.5/spin/pgb.spin0000644000175000017500000000171710004753022014756 0ustar giovannigiovanni/* * parallel GB check * $Id: pgb.spin 187 2004-01-25 14:43:31Z kredel $ */ byte idler = 0; #define PROCNUM 3 #define noJobs (idler == PROCNUM) byte pairsRemaining = 10; #define nextPair (pairsRemaining != 0) byte maxPairs = 30; #define erledigt ( (! nextPair) && noJobs ) inline addPair() { atomic { if :: ( maxPairs == 0 ) -> skip; :: ( maxPairs > 0 ) -> pairsRemaining++; maxPairs--; fi } } inline getPair() { atomic { if :: (pairsRemaining == 0) -> skip; :: (pairsRemaining > 0) -> pairsRemaining--; fi } } proctype Server () { do :: idler++; if :: ( erledigt ) -> break; //goto fertig; :: ( ! nextPair ) -> skip //delay; :: else skip; fi; idler--; getPair(); /* compute H-Pol */ progress: skip; addPair(); od; fertig: assert( ! nextPair ); } active proctype Monitor() { atomic { noJobs -> ! nextPair; } } init { idler = 0; run Server(); run Server(); run Server(); } jas-2.5/spin/dgb.spin0000644000175000017500000000260110004753022014733 0ustar giovannigiovanni/* * Distributed GB communications check * $Id: dgb.spin 187 2004-01-25 14:43:31Z kredel $ */ mtype = { Get, Fin, Pair, Hpol }; byte idler = 0; #define PROCNUM 3 #define noJobs (idler == PROCNUM) byte pairsRemaining = 10; #define nextPair (pairsRemaining != 0) byte maxPairs = 50; #define erledigt (! nextPair && noJobs ) inline addPair() { atomic { if :: ( maxPairs == 0 ) -> skip; :: ( maxPairs > 0 ) -> pairsRemaining++; maxPairs--; fi } } inline getPair() { atomic { if :: (pairsRemaining == 0) -> skip; :: (pairsRemaining > 0) -> pairsRemaining--; fi } } chan pairchan[PROCNUM] = [2] of { mtype }; proctype Server (chan pairs) { do :: idler++; pairs ? Get; if :: ( erledigt ) -> pairs ! Fin; break; //goto fertig; :: ( ! nextPair ) -> skip //delay; :: else skip; fi; idler--; getPair(); pairs ! Pair; /* compute H-Pol in client */ progress: skip; pairs ? Hpol; addPair(); od; fertig: assert( ! nextPair ); } proctype Client (chan pairs) { do :: pairs ! Get; if :: pairs ? Fin -> break; :: pairs ? Pair -> pairs ! Hpol; fi od } active proctype Monitor() { atomic { noJobs -> ! nextPair; } } init { idler = 0; run Server(pairchan[0]); run Server(pairchan[1]); run Client(pairchan[0]); run Client(pairchan[1]); run Client(pairchan[2]); run Server(pairchan[2]); } jas-2.5/design.html0000644000175000017500000013664712137537330014527 0ustar giovannigiovanni JAS - API Design

API usage and design overview

In ths document we give an overview on the structure of the interfaces, classes and packages of JAS. In the first section we show how to compute Legendre polynomials with the JAS API. In the next three sections we focus on the structure of the required types and the creation of the corresponding objects. In the following three sections we focus on the functional aspects of the types, i.e. their constructors and methods. For a discussion of other design alternatives see the problems document. Further programming issues and bugs are listed in the Findbugs report.

1. Getting started

1.1. Computation of the Legendre polynomials

At first we present an example for the usage of the JAS API with the computation of the Legendre polynomials. The Legendre polynomials can be defined by the following recursion
  • P[0](x) = 1
  • P[1](x) = x
  • P[n](x) = 1/n ( (2n-1) x P[n-1] - (n-1) P[n-2] ).
The first 10 Legendre polynomials are:
P[0] = 1 
P[1] = x
P[2] = 3/2 x^2 - 1/2 
P[3] = 5/2 x^3 - 3/2 x
P[4] = 35/8 x^4 - 15/4 x^2 + 3/8 
P[5] = 63/8 x^5 - 35/4 x^3 + 15/8 x
P[6] = 231/16 x^6 - 315/16 x^4 + 105/16 x^2 - 5/16 
P[7] = 429/16 x^7 - 693/16 x^5 + 315/16 x^3 - 35/16 x
P[8] = 6435/128 x^8 - 3003/32 x^6 + 3465/64 x^4 - 315/32 x^2 + 35/128 
P[9] = 12155/128 x^9 - 6435/32 x^7 + 9009/64 x^5 - 1155/32 x^3 + 315/128 x

The polynomials have been computed with the following Java program. First we need a polynomial ring ring over the rational numbers, in one variable "x" and a list P to store the computed polynomials. The polynomial factory object itself needs at least a factory for the creation of coefficients and the number of variables. Additionally the term order and names for the variables can be specified. With this information the polynomial ring factory can be created by new GenPolynomialRing <BigRational>(fac,1,var), where fac is the coefficient factory, 1 is the number of variables, and var is an String array of names.

    BigRational fac = new BigRational();
    String[] var = new String[]{ "x" };
    GenPolynomialRing<BigRational> ring
        = new GenPolynomialRing<BigRational>(fac,1,var);

    int n = 10;
    List<GenPolynomial<BigRational>> P 
       = new ArrayList<GenPolynomial<BigRational>>(n);
    GenPolynomial<BigRational> t, one, x, xc;
    BigRational n21, nn;

    one = ring.getONE();
    x   = ring.univariate(0);

    P.add( one );
    P.add( x );
    for ( int i = 2; i < n; i++ ) {
        n21 = new BigRational( 2*i-1 );
        xc = x.multiply( n21 );
        t = xc.multiply( P.get(i-1) );  // (2n-1) x P[n-1]
        nn = new BigRational( i-1 );
        xc = P.get(i-2).multiply( nn ); // (n-1) P[n-2]
        t = t.subtract( xc );
        nn = new BigRational(1,i);      
        t = t.multiply( nn );           // 1/n t
        P.add( t );
    }
    for ( int i = 0; i < n; i++ ) {
        System.out.println("P["+i+"] = " + P.get(i).toString(var) );
        System.out.println();
    }

The polynomials for the recursion base are one and x. Both are generated from the polynomial ring factory with method ring.getONE() and ring.univariate(0), respectively. The polynomial (2n-1)x is produced in the for-loop by n21 = new BigRational( 2*i-1 ); and xc = x.multiply( n21 );. The polynomial (n-1) P[n-2] is computed by nn = new BigRational( i-1 ); and xc = P.get(i-2).multiply( nn ). Finally we have to multiply the difference of the intermediate polynomials by 1/i as nn = new BigRational( 1, i ); and t = t.multiply( nn ). Then, in the for-loop, the polynomials P[i] are computed using the definition, and stored in the list P for further use. In the last for-loop, the polynomials are printed, producing the output shown above. The string representation of the polynomial object can be created, as expected, by toString(), or by using names for the variables with toString(var). The imports required are

import java.util.ArrayList;
import java.util.List;
import edu.jas.arith.BigRational;
import edu.jas.poly.GenPolynomial;
import edu.jas.poly.GenPolynomialRing;

To use other coefficient rings, one simply changes the generic type parameter, say, from BigRational to BigComplex and adjusts the coefficient factory. The factory would then be created as c = new BigComplex(), followed by new GenPolynomialRing<BigComplex> (c,1,var). This small example shows that this library can easily be used, just as any other Java package or library.

In the following sections we describe the central classes and interfaces for the polynomial API.

1.2. Algebraic structures overview

To get an idea of the scope of JAS we summarize the implemented algebraic structures and of the implemented algebraic algorithms.

class factory structure methods
BigInteger self ring of arbitrary precision integers, a facade for java.math.BigInteger arithmetic, gcd, primality test
BigRational self ring of arbitrary precision rational numbers, i.e. fractions of integers, with Henrici optimizations for gcds arithmetic
ModInteger ModIntegerRing ring of integers modulo some fixed (arbitrary precision) integer n, if n is a prime number, the ring is a field arithmetic, chinese remainder
BigDecimal self ring of arbitrary precision floating point numbers, a facade for java.math.BigDecimal arithmetic, compareTo() with given precision
BigComplex self ring of arbitrary precision complex numbers, i.e. pairs of rational numbers arithmetic
BigQuaternion self ring of arbitrary precision quaternion numbers, i.e. quadruples of rational numbers arithmetic
BigOctonion self ring of arbitrary precision octonion numbers, i.e. implemented as pairs of quaternion numbers arithmetic
GenPolynomial GenPolynomialRing ring of polynomials in r variables over any implemented coefficient ring with respect to any implemented term ordering arithmetic, univariate gcd, norms, chinese remainders for coefficients, evaluation
AlgebraicNumber AlgebraicNumber- Ring ring of algebraic numbers, represented as univariate polynomials over any implemented coefficient field arithmetic
Real- AlgebraicNumber RealAlgebraicRing ring of real algebraic numbers, represented as algebraic number and an isolating interval for a real root over rational numbers or real algebraic numbers arithmetic, real sign, magnitude
Complex- AlgebraicNumber ComplexAlgebraicRing ring of complex algebraic numbers, represented as algebraic number and an isolating rectangle for a complex root over rational numbers as base ring arithmetic, sign invariant rectangle, magnitude
GenSolvable- Polynomial GenSolvable- PolynomialRing ring of non-commutative, solvable polynomials in r variables over any implemented coefficient ring with respect to any implemented term ordering (compatible with the multiplication) arithmetic
GenWordPolynomial GenWordPolynomialRing ring of free non-commutative polynomials in r letters over any implemented coefficient ring with respect to a graded term ordering arithmetic
Quotient QuotientRing ring of rational functions, i.e. fractions of multivariate polynomials over any implemented commutative unique factorization coefficient domain arithmetic
SolvableQuotient SolvableQuotientRing ring of rational functions, i.e. fractions of multivariate solvable polynomials (satisfying the left-, right-Ore condition) over some implemented coefficient domains arithmetic
Residue ResidueRing ring of polynomials modulo a given polynomial ideal, over any implemented commutative coefficient ring arithmetic
SolvableResidue SolvableResidueRing ring of polynomials modulo a given polynomial ideal, over some implemented coefficient domains arithmetic
Local LocalRing ring of polynomials fractions localized with respect to a given polynomial ideal, over any implemented commutative coefficient ring arithmetic
Product ProductRing (finite) direct product of fields and rings over any implemented coefficient ring arithmetic, idempotent elements
GenVector GenVectorModule tuples (vectors) of any implemented ring elements arithmetic, scalar product
GenMatrix GenMatrixModule matrices of any implemented ring elements arithmetic, scalar product
UnivPowerSeries UnivPowerSeriesRing ring of univariate power series over any implemented coefficient ring arithmetic, gcd, evaluation, integration, fixed points
MultiVarPowerSeries MultiVarPowerSeriesRing ring of multivatiate power series over any implemented coefficient ring arithmetic, evaluation, integration, fixed points
Quotient QuotientRing ring of fractions over any implemented (unique factorization domain) ring arithmetic
Residue ResidueRing ring of elements modulo a given (main) ideal, over any implemented ring arithmetic
Local LocalRing ring of fractions localized with respect to a given (main) ideal, over any implemented ring arithmetic
Complex ComplexRing ring of complex numbers over any implemented ring (with gcd) arithmetic

"Arithmetic" means implementation of the methods defined in the interface RingElem. As of 2013-04 there are 25 rings implemented. To be continued.

1.3. Algebraic algorithms overview

The following table contains an overview of implemented algebraic algorithms.

class / interface algorithm                                                                  methods
Reduction, Reduction- Abstract, ReductionSeq, ReductionPar, PseudoReduction Iterated subtraction of polynomials to eliminate terms from a given polynomial, i.e. reduction of polynomial(s) wrt. a set of polynomials. Coefficients of polynomials must be from a field and for the Pseudo* version from a ring with gcd. For *Par the list of polynomials can concurrently be modified. normalform, S-polynomial, criterions, extended normalform
DReduction EReduction DReductionSeq EReductionSeq Reduction of polynomial(s) wrt. a set of polynomials. Coefficients of polynomials must be from a principial ideal domain (PID) or from an Euclidean domain. normalform, S-polynomial, G-polynomial, criterions, extended normalform
SolvableReduction SolvableReduction- Abstract Solvable- ReductionSeq Solvable- ReductionPar Left and right reduction of solvable polynomial(s) wrt. a set of solvable polynomials. Coefficients of polynomials must be from a field. left/right normalform, left/right S-polynomial, criterions, extended left normalform
RReduction, RPseudoReduction, RReductionSeq, RPseudoReductionSeq Iterated subtraction of polynomials to eliminate terms from a given polynomial, i.e. reduction of polynomial(s) wrt. a set of polynomials. Coefficients of polynomials must be from a regular ring and for the Pseudo* version from a regular ring with gcd. Boolean closure and boolean remainder of polynomials. normalform, S-polynomial, boolean closure
CReductionSeq, Condition, ColorPolynomial Iterated subtraction of polynomials to eliminate terms from a given polynomial, i.e. reduction of polynomial(s) wrt. a set of polynomials. Coefficients of polynomials must be from a polynomial ring. Case distinction and determination of polynomaials with respect to conditions leading to colored polynomials. normalform, S-polynomial, color, determine
GroebnerBase, GroebnerBase- Abstract, GroebnerBaseSeq, GroebnerBase- Parallel, GroebnerBase- Distributed, GroebnerBase- PseudoSeq, etc. Buchberger algorithm to compute Groebner bases of sets of polynomials. Coefficients of polynomials must be from a field. *Parallel is a multi-threaded and *Distributed is a message passing implementation. The *Pseudo version is for non-field coefficients. GB, isGB, extended GB, minimal GB
DGroebnerBaseSeq, EGroebnerBaseSeq Algorithm to compute D- and E- Groebner bases of sets of polynomials. Coefficients of polynomials must be from a principial ideal domain (PID) or from an Euclidean domain. GB, isGB, minimal GB
SolvableGroebnerBase, SolvableGroebnerBase- Abstract, SolvableGroebnerBaseSeq, SolvableGroebnerBase- Parallel Algorithm to compute left, right and two-sided Groebner bases of sets of solvable polynomials. Coefficients of polynomials must be from a field. Parallel is a multi-threaded implementation. left, right, two-sided versions of GB, isGB, extended GB, minimal GB
WordGroebnerBase, WordGroebnerBase- Abstract, WordGroebnerBaseSeq Algorithm to compute two-sided Groebner bases of sets of free non-commutative polynomials. Coefficients of polynomials must be from a field. two-sided versions of GB, isGB, minimal GB
RGroebnerBaseSeq, RGroebnerBasePseudoSeq Algorithm to compute Groebner bases in polynomial rings over regular rings. Coefficients of polynomials must be from a product of fields or Euclidean domains. GB, isGB, minimal GB
ComprehensiveGroebnerBaseSeq, GroebnerSystem, ColoredSystem Algorithm to compute comprehensive Groebner bases in polynomial rings over parameter rings. Coefficients of polynomials must be from a polynomial ring. Computation is done via Groebner systems (lists of colored systems). GBsys, isGBsys, GB, isGB, minimalGB
Syzygy, SyzygyAbstract, ModGroebnerBase, ModGroebnerBaseAbstract, Algorithm to compute syzygies of lists of polynomials or Groebner Bases, free resolutions. Groebner Bases for modules over polynomial rings. Coefficients of polynomials must be from a field. zeroRelations, isZeroRelation, resolution, zeroRelationsArbitrary, GB, isGB
SolvableSyzygy, Solvable- SyzygyAbstract, ModSolvable- GroebnerBase, ModSolvable- GroebnerBaseAbstract, Algorithm to compute left and right syzygies of lists of solvable polynomials or Groebner Bases, free left resolutions. Left, right and two-sided Groebner Bases for modules over solvable polynomial rings. Coefficients of polynomials must be from a field. leftZeroRelations, rightZeroRelations, isLeftZeroRelation, isRightZeroRelation, (left) resolution, zeroRelationsArbitrary, leftOreCond, rightOreCont(ition), left, right, two-sided GB, isGB
ReductionSeq, StandardBaseSeq, etc. Mora's tangent cone reduction algorithm and computation of standard bases of sets of multivariate power series. Coefficients of polynomials must be from a field. STD, isSTD, minimalSTD, normalForm, SPolynomial
Ideal Algorithms to compute sums, products, intersections, containment and (infinite) quotients of polynomial ideals. Coefficients of polynomials must be from a field. Prime, primary, irreducible and radical decomposition of zero dimensional ideals. Prime, primary, irreducible and radical decomposition of non-zero dimensional ideals. Univariate polynomials of minimal degree in ideal as well as elimination, extension and contraction ideals. sum, product, intersect, contains, quotient, infiniteQuotient, inverse modulo ideal, zeroDimRadicalDecomposition, zeroDimPrimeDecomposition, zeroDimPrimaryDecomposition, zeroDimDecomposition, zeroDimRootDecomposition, radicalDecomposition, primeDecomposition, decomposition, primaryDecomposition
SolvableIdeal Algorithms to compute sums, products, intersections, containment and (infinite) quotients of solvable polynomial ideals. Coefficients of solvable polynomials must be from a field. sum, product, intersect, contains, quotient, infiniteQuotient, inverse modulo ideal, univariate polynomials of minimal degree in ideal
GreatestCommonDivisor, GCDFactory, GreatestCommonDivisorAbstract, GreatestCommonDivisorSimple, GreatestCommonDivisorPrimitive, GreatestCommonDivisorSubres, GreatestCommonDivisorModular, GreatestCommonDivisorModEval, GCDProxy Algorithms to compute greatest common divisors of polynomials via different polynomial remainder sequences (PRS) and modular methods. Coefficients of polynomials must be from a unique factorization domain (UFD). GCDFactory helps with the optimal selection of an algorithm and GCDProxy uses multi-threading to compute with several implementations in parallel. gcd, lcm, content, primitivePart, resultant, coPrime
Squarefree, SquarefreeFactory, SquarefreeAbstract, SquarefreeFieldChar0, SquarefreeFieldCharP, SquarefreeFiniteFieldCharP, SquarefreeInfiniteFieldCharP, SquarefreeInfiniteAlgebraicFieldCharP, SquarefreeRingChar0 Algorithms to compute squarefree decomposition of polynomials over fields of characteristic zero, finite and infinite fields of characteristic p and other coefficients from unique factorization domains (UFD). SquarefreeFactory helps with the optimal selection of an algorithm. squarefreePart, squarefreeFactors, isFactorization, isSquarefree, coPrimeSquarefree
Factorization, FactorFactory, FactorAbstract, FactorAbsolute, FactorModular, FactorInteger, FactorRational, FactorAlgebraic Algorithms to compute factorizations of polynomials as products of irreducible polynomials over different ground rings. FactorFactory helps with the correct selection of an algorithm. Reduction of the multivariate factorization to an univariate factorization is done with Kronecker's algorithm in the general case and with Wang's algorithm over the integers. squarefreeFactors, factors, baseFactors, isIrreducible, isReducible, isSquarefree, isFactorization, isAbsoluteIrreducible, factorsAbsolute
RealRoots, RealRootsAbstract, RealRootsSturm Algorithms to compute isolating intervals for real roots and for refinement of isolating intervals to any prescribed precision. Algorithms to compute the sign of a real algebraic numer and the magnitude of a real algebraic number to a given precision. Coefficients of polynomials must be from a real field, for example from BigRational or RealAlgebricNumber. realRoots, refineInterval, algebraicSign, algebraicMagnitude
ComplexRoots, ComplexRootsAbstract, ComplexRootsSturm Algorithms to compute isolating rectangles for complex roots and for refinement of isolating rectangles to any prescribed precision. Coefficients of polynomials must be of type Complex field. complexRoots, complexRootCount, complexRootRefinement
ElementaryIntegration Algorithms to compute elementary integrals of univariate rational functions. integrate, integrateHermite, integrateLogPart, isIntegral
CharacteristicSet, CharacteristicSetSimple, CharacteristicSetWu Algorithms to compute simple or Wu-Ritt characteristic sets. characteristicSet, isCharacteristicSet, characteristicSetReduction

1.4. Packages overview

Static package structure overview

More details can be found in the JDepend report.txt.

2. Recursive ring element design

The next figure gives an overview of the central interfaces and classes. The interface RingElem defines a recursive type which defines the functionality (see next section) of the polynomial coefficients and is also implemented by the polynomials itself. So polynomials can be taken as coefficients for other polynomials, thus defining a recursive polynomial ring structure.

Since the construction of constant ring elements has been difficult in previuos designs, we separated the creational aspects of ring elements into ring factories with sufficient context information. The minimal factory functionality is defined by the interface RingFactory. Constructors for polynomial rings will then require factories for the coefficients so that the construction of polynomials over these coefficient rings poses no problem. The ring factories are additionaly required because of the Java generic type design. I.e. if C is a generic type name it is not possible to construct an new object with new C(). Even if this would be possible, one can not specify constructor signatures in Java interfaces, e.g. to construct a one or zero constant ring element. Recursion is again achieved by using polynomial factories as coefficient factories in recursive polynomial rings. Constructors for polynomials will always require a polynomial factory parameter which knows all details about the polynomial ring under consideration.

JAS type overview
UML diagram of JAS types

3. Coefficients and polynomials

We continue the discussion of the next layer of classes in the the above figure.

Elementary coefficient classes, such as BigRational or BigInteger, implement both the RingElem and RingFactory interfaces. This is convenient, since these factories do not need further context information. In the implementation of the interfaces the type parameter C extends RingElem<C> is simultaneously bound to the respective class, e.g. BigRational. Coefficient objects can in most cases created directly via the respective class constructors, but also via the factory methods. E.g. the object representing the rational number 2 can be created by new BigRational(2) or by fac = new BigRational(), fac.fromInteger(2) and the object representing the rational number 1/2 can be created by new BigRational(1,2) or by fac.parse("1/2").

Generic polynomials are implemented in the GenPolynomial class, which has a type parameter C extends RingElem<C> for the coefficient type. So all operations on coefficients required in polynomial arithmetic and manipulation are guaranteed to exist by the RingElem interface. The constructors of the polynomials always require a matching polynomial factory. The generic polynomial factory is implemented in the class GenPolynomialRing, again with type parameter C extends RingElem<C> (not RingFactory). The polynomial factory however implements the interface RingFactory<C extends RingElem<C>> so that it can also be used recursively. The constructors for GenPolynomialRing require at least parameters for a coefficient factory and the number of variables of the polynomial ring.

Having generic polynomial and elementary coefficient implementations one can attempt to construct polynomial objects. The type is first created by binding the type parameter C extends RingElem<C> to the desired coefficient type, e.g. BigRational. So we arrive at the type GenPolynomial<BigRational>. Polynomial objects are then created via the respective polynomial factory of type GenPolynomialRing<BigRational>, which is created by binding the generic coefficient type of the generic polynomial factory to the desired coefficient type, e.g. BigRational. A polynomial factory object is created from a coefficient factory object and the number of variables in the polynomial ring as usual with the new operator via one of its constructors. Given an object coFac of type BigRational, e.g. created with new BigRational(), a polynomial factory object pfac of the above described type could be created by new GenPolynomialRing<BigRational>(coFac,5). I.e. we specified a polynomial ring with 5 variables over the rational numbers. A polynomial object p of the above described type can then be created by any method defined in RingFactory, e.g. by pfac.getONE(), pfac.fromInteger(1), pfac.random(3) or pfac.parse("(1)").

Since GenPolynomial itself implements the RingElem interface, they can also be used recursively as coefficients. We continue the polynomial example and are going to use polynomials over the rational numbers as coefficients of a new polynomial. The type is then GenPolynomial<GenPolynomial<BigRational>> and the polynomial factory has type GenPolynomialRing<GenPolynomial<BigRational>>. Using the polynomial coefficient factory pfac from above a recursive polynomial factory rfac could be created by new GenPolynomialRing<GenPolynomial<BigRational>>(pfac,3). The creation of a recursive polynomial object r of the above described type is then as a easy as before e.g. by rfac.getONE(), rfac.fromInteger(1) or rfac.random(3).

4. Solvable polynomials

We turn now to the last layer of classes in the the above figure.

The generic polynomials are intended as super class for further types of polynomial rings. As one example we take so called solvable polynomials, which are like normal polynomials but are equipped with a new non-commutative multiplication. They are implemented in the class GenSolvablePolynomial which extends GenPolynomial and inherits all methods except clone() and multiply(). The class also has a type parameter C extends RingElem<C> for the coefficient type. Note, that the inherited methods are in fact creating solvable polynomials since they employ the solvable polynomial factory for the creation of any new polynomial internally. Only the formal method return type is that of GenPolynomial, the run-time type is GenSolvablePolynomial to which they can be casted at any time. The factory for solvable polynomials is implemented by the class GenSolvablePolynomialRing which also extends the generic polynomial factory. So this factory can also be used in the constructors of GenPolynomial via super() to produce in fact solvable polynomials internally. The data structure is enhanced by a table of non-commutative relations defining the new multiplication. The constructors delegate most things to the corresponding super class constructors and additionally have a parameter for the RelationTable to be used. Also the methods delegate the work to the respective super class methods where possible and then handle the non-commutative multiplication relations separately.

The construction of solvable polynomial objects follows directly that of polynomial objects. The type is created by binding the type parameter C extends RingElem<C> to the desired coefficient type, e.g. BigRational. So we have the type GenSolvablePolynomial<BigRational>. Solvable polynomial objects are then created via the respective solvable polynomial factory of type GenSolvablePolynomialRing<BigRational>, which is created by binding the generic coefficient type of the generic polynomial factory to the desired coefficient type, e.g. BigRational. A solvable polynomial factory object is created from a coefficient factory object, the number of variables in the polynomial ring and a table containing the defining non-commutative relations as usual with the new operator via one of its constructors. Given an object coFac of type BigRational as before, a polynomial factory object spfac of the above described type could be created by new GenSolvablePolynomialRing<BigRational>(coFac,5). I.e. we specified a polynomial ring with 5 variables over the rational numbers with no commutator relations. A solvable polynomial object p of the above described type can then be created by any method defined in RingFactory, e.g. by spfac.getONE(), spfac.fromInteger(1), spfac.random(3) or spfac.parse("(1)"). Some care is needed to create RelationTable objects since its constructor requires the solvable polynomial ring which is under construction as parameter. It is most convenient to first create a GenSolvablePolynomialRing with an empty relation table and then to add the defining relations.

5. Ring element and factory functionality

The following sections and the next figure gives an overview of the functionality of the main interfaces and polynomial classes.

The RingElem interface has a generic type parameter C which is constrained to a type with the same functionality C extends RingElem<C>. It defines the usual methods required for ring arithmetic such as C sum(C S); C subtract(C S); C negate(); C abs(); C multiply(C S); C divide(C S); C remainder(C S); C inverse(); Although the actual ring may not have inverses for every element or some division algorithm we have included these methods in the definition. In a case where there is no such function, the implementation may deliberately throw a RuntimeException or choose some other meaningful element to return. The method isUnit() can be used to check if an element is invertible.

Besides the arithmetic method there are following testing methods boolean isZERO(); boolean isONE(); boolean isUnit(); int signum(); boolean equals(Object b); int hashCode(); int compareTo(C b); The first three test if the element is 0, 1 or a unit in the respective ring. The signum() method defines the sign of the element (in case of an ordered ring). equals(), hashCode() and compareTo() are required to keep Javas object machinery working in our sense. They are used when an element is put into a Java collection class, e.g. Set, Map or SortedMap. The last method C clone() can be used to obtain a copy of the actual element. As creational method one should better use the method C copy(C a) from the ring factory, but in Java it is more convenient to use the clone() method.

As mentioned before, the creational aspects of rings are separated into a ring factory. A ring factory is intended to store all context information known or required for a specific ring. Every ring element should also know its ring factory, so all constructors of ring element implementations require a parameter for the corresponding ring factory. Unfortunately constructors and their signature can not be specified in a Java interface. The RingFactory interface also has a generic type parameter C which is constrained to a type with the ring element functionality C extends RingElem<C>. The defined methods are C getZERO(); C getONE(); C fromInteger(long a); C fromInteger(java.math.BigInteger a); C random(int n); C copy(C c); C parse(String s); C parse(Reader r); The first two create 0 and 1 of the ring. The second two are used to embed a natural number into the ring and create the corresponding ring element. The copy() method was intended as the main means to obtain a copy of a ring element, but it is now no more used in our implmentation. Instead the clone() method is used from the ring element interface. The random(int n) method creates a random element of the respective ring. The parameter n specifies an appropriate maximal size for the created element. In case of coefficients it usually means the maximal bit-length of the element, in case of polynomials it influences the coefficient size and the degrees. For polynomials there are random() methods with more parameters. The two methods C parse(String s) and C parse(Reader r) create a ring element from some external string representation. For coefficients this is mostly implemented directly and for polynomials the class GenPolynomialTokenizer is employed internally. In the current implementation the external representation of coefficients may never contain white space and must always start with a digit. In the future the ring factory will be enhanced by methods that test if the ring is commutative, associative or has some other important property or the value of a property, e.g. is an euclidean ring, is a field, an integal domain, a uniqe factorization domain, its characteristic or if it is noetherian.

JAS type functionality
UML diagram of JAS type functionality

6. Polynomial and polynomial factory functionality

We continue the discussion of the above figure with the generic polynomial and factory classes.

The GenPolynomial class has a generic type parameter C which is constrained to a type with the functionality of ring elements C extends RingElem<C>. Further the class implements a RingElem over itself RingElem<GenPolynomial<C>> so that it can be used for the coefficients of an other polynomial ring. The functionality of the ring element methods has already been explained in the previous section. There are two public and one protected constructors, each requires at least a ring factory parameter GenPolynomialRing<C> r. The first creates a zero polynomial GenPolynomial(. r), the second creates a polynomial of one monomial with given coefficient and exponent tuple GenPolynomial(. r, C c, ExpVector e), the third creates a polynomial from the internal sorted map of an other polynomial GenPolynomial(. r, SortedMap<ExpVector,C> v). Further there are methods to access parts of the polynomial like leading term, leading coefficient (still called leading base coefficient from the Aldes/SAC-2 tradition) and leading monomial. The toString() method creates as usual a string representation of the polynomials consisting of exponent tuples and coefficients. One variant of it takes an array of variable names and creates a string consisting of coefficients and products of powers of variables. The method extend() is used to embed the polynomial into the 'bigger' polynomial ring specified in the first parameter. The embeded polynomial can also be multiplied by a power of a variable. The contract() method returns a map of exponents and coefficients. The coefficients are polynomials belonging to the 'smaller' polynomial ring specified in the first parameter. If the polynomial actually belongs to the smaller polynomial ring the map will contain only one pair, mapping the zero exponent vector to the polynomial with variables removed. A last group of methods computes (extended) greatest common divisors. They work correct for univariate polynomials over a field but not for arbitrary multivatiate polynomials. These methods will be moved to a new separate class in the future.

The GenPolynomialRing class has a generic type parameter C which is constrained to a type with the functionality of ring elements C extends RingElem<C>. Further the class implements a RingFactory over GenPolynomial<C> so that it can be used as coefficient factory of a different polynomial ring. The constructors require at least a factory for the coefficents as first parameter of type RingFactory<C> and the number of variables in the second parameter. A third parameter can optionally specify a TermOrder and a fourth parameter can specify the names for the variables of the polynomial ring. Besides the methods required by the RingFactory interface there are additional random() methods which provide more control over the creation of random polynomials. They have the following parameters: the bitsize of random coefficients to be used in the random() method of the coefficient factory, the number of terms (i.e. the length of the polynomial), the maximal degree in each variable and the density of nozero exponents, i.e. the ratio of nonzero to zero exponents. The toString() method creates a string representation of the polynomial ring consisting of the coefficient factory string representation, the tuple of variable names and the string representation of the term order. The extend() and contract() methods create 'bigger' respectively 'smaller' polynomial rings. Both methods take a parameter of how many variables are to be added or removed form the actual polynomial ring. extend() will setup an elimination term order consisting of two times the actual term order when ever possible.

7. Solvable polynomial and solvable polynomial factory functionality

We continue the discussion of the above figure with the generic solvable polynomial and factory classes.

The GenSolvablePolynomial class has a generic type parameter C which is constrained to a type with the functionality of ring elements C extends RingElem<C>. The class extends the GenPolynomial class. It inherits all additive functionality and overwrites the multiplicative functionality with a new non-commutative multiplication method. Unfortunately it cannot implement a RingElem over itself RingElem<GenSolvablePolynomial<C>> but can only inherit the implementation of RingElem<GenPolynomial<C>> from its super class. By this limitation a solvable polynomial can still be used as coefficent in another polynomial, but only with the type of its super class. The limitation comes form the erasure of template parameters in RingElem<...> to RingElem for the code generated. I.e. the generic interfaces become the same after type erasure and it is not allowed to implement the same interface twice. There are two public and one protected constructors as in the super class. Each requires at least a ring factory parameter GenSolvablePolynomialRing<C> r which is stored in a variable of this type shadowing the variable with the same name of the super factory type. The rest of the initialization work is delegated to the super class constructor.

The GenSolvablePolynomialRing class has a generic type parameter C which is constrained to a type with the functionality of ring elements C extends RingElem<C>. The class extends the GenPolynomialRing class. It overwrites most methods to implement the new non-commutative methods. Also this class cannot implement a RingFactory over GenSolvablePolynomial<C>. It only implements RingFactory over GenPolynomial<C> by inheritance by the same reason of type erasure as above. But it can be used as coefficient factory with the type of its super class for a different polynomial ring. One part of the constructors just restate the super class constructors with the actual solvable type. A solvable polynomial ring however must know how to perform the non-commutative multiplication. To this end a data structure with the respective commutator relations is required. It is implemented in the RelationTable class. The other part of the constructors additionaly takes a parameter of type RelationTable to set the initial commutator relation table. Some care is needed to create relation tables and solvable polynomial factories since the relation table requires a solvable polynomial factory as parameter in the constructor. So it is most advisable to create a solvable polynomial factory object with empty relation table and to fill it with commutator relations after the constructor is completed but before the factory will be used. There is also a new method isAssociative() which tries to check if the commutator relations indeed define an associative algebra. This method should be extracted to the RingFactory interface together with a method isCommutative(), since both are of general importance and not always fulfilled in our rings. E.g. BigQuaternion is not commutative and so is a polynomial ring over these coefficents is not commutative. The same applies to associativity and the (not jet existing) class BigOctonion.

This concludes the discussion of the main interfaces and classes of the Java algebra system.


Heinz Kredel

Last modified: Mon Apr 29 20:39:43 CEST 2013

jas-2.5/trc/0000755000175000017500000000000012140140260013121 5ustar giovannigiovannijas-2.5/trc/edu/0000755000175000017500000000000012140140260013676 5ustar giovannigiovannijas-2.5/trc/edu/jas/0000755000175000017500000000000012140140260014453 5ustar giovannigiovannijas-2.5/trc/edu/jas/root/0000755000175000017500000000000012140140260015436 5ustar giovannigiovannijas-2.5/trc/edu/jas/root/RealRootTest.java0000644000175000017500000003721512063147646020723 0ustar giovannigiovanni/* * $Id: RealRootTest.java 4316 2012-12-15 19:29:42Z kredel $ */ package edu.jas.root; import java.util.ArrayList; import java.util.Collections; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.structure.Power; /** * RealRoot tests with JUnit. * @author Heinz Kredel. */ public class RealRootTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a RealRootTest object. * @param name String. */ public RealRootTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(RealRootTest.class); return suite; } TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; BigRational ai; BigRational bi; BigRational ci; BigRational di; BigRational ei; BigRational eps; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 1; int kl = 5; int ll = 7; int el = 7; float q = 0.7f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; String[] vars = new String[] { "x" }; dfac = new GenPolynomialRing(new BigRational(1), rl, to, vars); // eps = new BigRational(1L,1000000L*1000000L*1000000L); eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; dfac = null; eps = null; } /** * Test Sturm sequence. * */ public void testSturmSequence() { a = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); RealRootsSturm rrs = new RealRootsSturm(); List> S = rrs.sturmSequence(a); //System.out.println("S = " + S); try { b = a.remainder(S.get(0)); } catch (Exception e) { fail("not S(0)|f " + e); } assertTrue("a mod S(0) == 0 ", b.isZERO()); assertTrue("S(-1) == 1 ", S.get(S.size() - 1).isConstant()); } /** * Test root bound. * */ public void testRootBound() { a = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); RealRoots rr = new RealRootsSturm(); BigRational M = rr.realRootBound(a); //System.out.println("M = " + M); assertTrue("M >= 1 ", M.compareTo(BigRational.ONE) >= 0); a = a.monic(); //System.out.println("a = " + a); M = rr.realRootBound(a); //System.out.println("M = " + M); assertTrue("M >= 1 ", M.compareTo(BigRational.ONE) >= 0); } /** * Test real root isolation. * */ public void testRealRootIsolation() { a = dfac.random(kl, ll * 2, el * 2, q); //a = a.multiply( dfac.univariate(0) ); //System.out.println("a = " + a); RealRoots rr = new RealRootsSturm(); List> R = rr.realRoots(a); //System.out.println("R = " + R); assertTrue("#roots >= 0 ", R.size() >= 0); } /** * Test real root isolation Wilkinson polynomials. * p = (x-0)*(x-1)*(x-2)*(x-3)*...*(x-n) */ public void testRealRootIsolationWilkinson() { final int N = 10; d = dfac.getONE(); e = dfac.univariate(0); List> Rn = new ArrayList>(N); a = d; for (int i = 0; i < N; i++) { c = dfac.fromInteger(i); Rn.add(new Interval(c.leadingBaseCoefficient())); b = e.subtract(c); a = a.multiply(b); } //System.out.println("a = " + a); RealRoots rr = new RealRootsSturm(); List> R = rr.realRoots(a); //System.out.println("R = " + R); assertTrue("#roots = " + N + " ", R.size() == N); //System.out.println("eps = " + eps); //BigDecimal eps1 = new BigDecimal(eps); //System.out.println("eps1 = " + eps1); R = rr.refineIntervals(R, a, eps); //System.out.println("R = " + R); int i = 0; for (Interval v : R) { BigDecimal dd = v.toDecimal(); //.sum(eps1); BigDecimal di = Rn.get(i++).toDecimal(); //System.out.println("v = " + dd); //System.out.println("vi = " + di); assertTrue("|dd - di| < eps ", dd.compareTo(di) == 0); } } /** * Test real root isolation Wilkinson polynomials inverse. * p = (x-1)*(x-1/2)*(x-1/3)*...*(x-1/n) */ public void testRealRootIsolationWilkinsonInverse() { final int N = 9; d = dfac.getONE(); e = dfac.univariate(0); List> Rn = new ArrayList>(N); a = d; for (int i = 1; i < N; i++) { // use only for i > 0, since reverse c = dfac.fromInteger(i); if (i != 0) { c = d.divide(c); } Rn.add(new Interval(c.leadingBaseCoefficient())); b = e.subtract(c); a = a.multiply(b); } //System.out.println("a = " + a); //System.out.println("Rn = " + Rn); Collections.reverse(Rn); //System.out.println("Rn = " + Rn); RealRoots rr = new RealRootsSturm(); List> R = rr.realRoots(a); //System.out.println("R = " + R); assertTrue("#roots = " + (N - 1) + " ", R.size() == (N - 1)); //System.out.println("eps = " + eps); //BigDecimal eps1 = new BigDecimal(eps); //System.out.println("eps1 = " + eps1); R = rr.refineIntervals(R, a, eps); //System.out.println("R = " + R); int i = 0; for (Interval v : R) { BigDecimal dd = v.toDecimal(); //.sum(eps1); BigDecimal di = Rn.get(i++).toDecimal(); //System.out.println("v = " + dd); //System.out.println("vi = " + di); assertTrue("|dd - di| < eps ", dd.compareTo(di) == 0); } } /** * Test real algebraic number sign. * */ public void testRealAlgebraicNumberSign() { d = dfac.fromInteger(2); e = dfac.univariate(0); a = e.multiply(e); // a = a.multiply(e).multiply(e).multiply(e); a = a.subtract(d); // x^2 -2 //System.out.println("a = " + a); RealRoots rr = new RealRootsSturm(); ai = new BigRational(1); bi = new BigRational(2); Interval iv = new Interval(ai, bi); //System.out.println("iv = " + iv); assertTrue("sign change", rr.signChange(iv, a)); b = dfac.random(kl, (int) a.degree() + 1, (int) a.degree(), 1.0f); //b = dfac.getZERO(); //b = dfac.random(kl,ll,el,q); //b = b.multiply(b); //b = b.abs().negate(); //System.out.println("b = " + b); if (b.isZERO()) { int s = rr.realSign(iv, a, b); assertTrue("algebraic sign", s == 0); return; } int as = rr.realSign(iv, a, b); //System.out.println("as = " + as); // how to test? int asn = rr.realSign(iv, a, b.negate()); //System.out.println("asn = " + asn); assertTrue("algebraic sign", as != asn); iv = new Interval(bi.negate(), ai.negate()); //System.out.println("iv = " + iv); assertTrue("sign change", rr.signChange(iv, a)); int as1 = rr.realSign(iv, a, b); //System.out.println("as1 = " + as1); // how to test? int asn1 = rr.realSign(iv, a, b.negate()); //System.out.println("asn1 = " + asn1); assertTrue("algebraic sign", as1 != asn1); assertTrue("algebraic sign", as * as1 == asn * asn1); } /** * Test real root isolation and decimal refinement of Wilkinson polynomials. * p = (x-0)*(x-1)*(x-2)*(x-3)*...*(x-n) */ public void testRealRootIsolationDecimalWilkinson() { final int N = 10; d = dfac.getONE(); e = dfac.univariate(0); List> Rn = new ArrayList>(N); a = d; for (int i = 0; i < N; i++) { c = dfac.fromInteger(i); Rn.add(new Interval(c.leadingBaseCoefficient())); b = e.subtract(c); a = a.multiply(b); } //System.out.println("a = " + a); RealRootsAbstract rr = new RealRootsSturm(); List> R = rr.realRoots(a); //System.out.println("R = " + R); assertTrue("#roots = " + N + " ", R.size() == N); eps = eps.multiply(new BigRational(100000)); //System.out.println("eps = " + eps); BigDecimal eps1 = new BigDecimal(eps); BigDecimal eps2 = eps1.multiply(new BigDecimal("100")); //System.out.println("eps1 = " + eps1); //System.out.println("eps2 = " + eps2); try { int i = 0; for (Interval v : R) { //System.out.println("v = " + v); BigDecimal dd = rr.approximateRoot(v,a,eps); BigDecimal di = Rn.get(i++).toDecimal(); //System.out.println("di = " + di); //System.out.println("dd = " + dd); assertTrue("|dd - di| < eps ", dd.subtract(di).abs().compareTo(eps2) <= 0); } } catch (NoConvergenceException e) { fail(e.toString()); } } /** * Test real root isolation and decimal refinement of Wilkinson polynomials, inverse roots. * p = (x-1)*(x-1/2)*(x-1/3)*...*(x-1/n) */ public void testRealRootIsolationDecimalWilkinsonInverse() { final int N = 10; d = dfac.getONE(); e = dfac.univariate(0); List> Rn = new ArrayList>(N); a = d; for (int i = 1; i < N; i++) { // use only for i > 0, since reverse c = dfac.fromInteger(i); if (i != 0) { c = d.divide(c); } Rn.add(new Interval(c.leadingBaseCoefficient())); b = e.subtract(c); a = a.multiply(b); } //System.out.println("a = " + a); //System.out.println("Rn = " + Rn); Collections.reverse(Rn); //System.out.println("Rn = " + Rn); RealRootsAbstract rr = new RealRootsSturm(); List> R = rr.realRoots(a); //System.out.println("R = " + R); assertTrue("#roots = " + (N - 1) + " ", R.size() == (N - 1)); eps = eps.multiply(new BigRational(1000000)); //System.out.println("eps = " + eps); BigDecimal eps1 = new BigDecimal(eps); BigDecimal eps2 = eps1.multiply(new BigDecimal("10")); //System.out.println("eps1 = " + eps1); //System.out.println("eps2 = " + eps2); try { int i = 0; for (Interval v : R) { //System.out.println("v = " + v); BigDecimal dd = rr.approximateRoot(v,a,eps); BigDecimal di = Rn.get(i++).toDecimal(); //System.out.println("di = " + di); //System.out.println("dd = " + dd); assertTrue("|dd - di| < eps ", dd.subtract(di).abs().compareTo(eps2) <= 0); } } catch (NoConvergenceException e) { fail(e.toString()); } } /** * Test real root isolation and decimal refinement of Wilkinson polynomials, all roots. * p = (x-0)*(x-1)*(x-2)*(x-3)*...*(x-n) */ public void testRealRootIsolationDecimalWilkinsonAll() { final int N = 10; d = dfac.getONE(); e = dfac.univariate(0); List> Rn = new ArrayList>(N); a = d; for (int i = 0; i < N; i++) { c = dfac.fromInteger(i); Rn.add(new Interval(c.leadingBaseCoefficient())); b = e.subtract(c); a = a.multiply(b); } //System.out.println("a = " + a); RealRootsAbstract rr = new RealRootsSturm(); eps = eps.multiply(new BigRational(10000)); //System.out.println("eps = " + eps); BigDecimal eps1 = new BigDecimal(eps); BigDecimal eps2 = eps1.multiply(new BigDecimal("100")); //System.out.println("eps1 = " + eps1); //System.out.println("eps2 = " + eps2); List R = null; R = rr.approximateRoots(a,eps); //System.out.println("R = " + R); assertTrue("#roots = " + N + " ", R.size() == N); int i = 0; for (BigDecimal dd : R) { //System.out.println("dd = " + dd); BigDecimal di = Rn.get(i++).toDecimal(); //System.out.println("di = " + di); assertTrue("|dd - di| < eps ", dd.subtract(di).abs().compareTo(eps2) <= 0); } boolean t = rr.isApproximateRoot(R,a,eps); assertTrue("some |a(dd)| < eps ", t); } /** * Test real root isolation and decimal refinement of Wilkinson polynomials, inverse roots, all roots. * p = (x-1)*(x-1/2)*(x-1/3)*...*(x-1/n) */ public void testRealRootIsolationDecimalWilkinsonInverseAll() { final int N = 10; d = dfac.getONE(); e = dfac.univariate(0); List> Rn = new ArrayList>(N); a = d; for (int i = 1; i < N; i++) { // use only for i > 0, since reverse c = dfac.fromInteger(i); if (i != 0) { c = d.divide(c); } Rn.add(new Interval(c.leadingBaseCoefficient())); b = e.subtract(c); a = a.multiply(b); } //System.out.println("a = " + a); //System.out.println("Rn = " + Rn); Collections.reverse(Rn); //System.out.println("Rn = " + Rn); RealRootsAbstract rr = new RealRootsSturm(); eps = eps.multiply(new BigRational(1000000)); //System.out.println("eps = " + eps); BigDecimal eps1 = new BigDecimal(eps); BigDecimal eps2 = eps1.multiply(new BigDecimal("10")); //System.out.println("eps1 = " + eps1); //System.out.println("eps2 = " + eps2); List R = null; R = rr.approximateRoots(a,eps); //System.out.println("R = " + R); assertTrue("#roots = " + (N - 1) + " ", R.size() == (N - 1)); int i = 0; for (BigDecimal dd : R) { //System.out.println("dd = " + dd); BigDecimal di = Rn.get(i++).toDecimal(); //System.out.println("di = " + di); assertTrue("|dd - di| < eps ", dd.subtract(di).abs().compareTo(eps2) <= 0); } boolean t = rr.isApproximateRoot(R,a,eps); assertTrue("some |a(dd)| < eps ", t); } } jas-2.5/trc/edu/jas/root/ComplexAlgebraicTest.java0000644000175000017500000001704411641660762022373 0ustar giovannigiovanni/* * $Id: ComplexAlgebraicTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.root; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.NotInvertibleException; /** * ComplexAlgebraicNumber Test using JUnit. * @author Heinz Kredel. */ public class ComplexAlgebraicTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a ComplexAlgebraicTest object. * @param name String. */ public ComplexAlgebraicTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(ComplexAlgebraicTest.class); return suite; } //private final static int bitlen = 100; ComplexAlgebraicRing fac; GenPolynomialRing> mfac; ComplexAlgebraicNumber a; ComplexAlgebraicNumber b; ComplexAlgebraicNumber c; ComplexAlgebraicNumber d; ComplexAlgebraicNumber e; ComplexAlgebraicNumber alpha; int rl = 1; int kl = 10; int ll = 10; int el = ll; float q = 0.5f; @Override protected void setUp() { a = b = c = d = e = null; ComplexRing cfac = new ComplexRing(new BigRational(1)); Complex im = cfac.getIMAG(); BigRational rfac = new BigRational(); BigRational two = new BigRational(2); Complex nw = new Complex(cfac, rfac.getZERO(), two); Complex sw = new Complex(cfac, rfac.getZERO(), rfac.getZERO()); Complex se = new Complex(cfac, two, rfac.getZERO()); Complex ne = new Complex(cfac, two, two); Rectangle positiv = new Rectangle(nw, sw, se, ne); //System.out.println("postiv = " + positiv); String[] vars = new String[] { "alpha" }; mfac = new GenPolynomialRing>(cfac, rl, vars); Complex r1 = cfac.fromInteger(1).sum(im); Complex r2 = r1.conjugate(); GenPolynomial> mo = mfac.univariate(0, 1); mo = mo.subtract(r1).multiply(mo.subtract(r2)); // (x - (1+i))((x - (1-i))) fac = new ComplexAlgebraicRing(mo, positiv); alpha = fac.getGenerator(); //System.out.println("fac = " + fac); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; alpha = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); //System.out.println("c.getVal() = " + c.getVal()); assertTrue("length( c ) = 1", c.number.getVal().length() == 1); assertTrue("isZERO( c )", !c.isZERO()); assertTrue("isONE( c )", c.isONE()); d = fac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.getVal() = " + d.getVal()); assertTrue("length( d ) = 0", d.number.getVal().length() == 0); assertTrue("isZERO( d )", d.isZERO()); assertTrue("isONE( d )", !d.isONE()); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(el); //System.out.println("a = " + a); if (a.isZERO() || a.isONE()) { continue; } // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a" + i + " ) <> 0", a.number.getVal().length() >= 0); assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); assertTrue(" not isONE( a" + i + " )", !a.isONE()); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a", a, d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a", c, d); c = fac.random(ll); d = c.sum(a.sum(b)); e = c.sum(a).sum(b); assertEquals("c+(a+b) = (c+a)+b", d, e); c = a.sum(fac.getZERO()); d = a.subtract(fac.getZERO()); assertEquals("a+0 = a-0", c, d); c = fac.getZERO().sum(a); d = fac.getZERO().subtract(a.negate()); assertEquals("0+a = 0+(-a)", c, d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO()); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO()); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO()); assertTrue("not isZERO( d )", !d.isZERO()); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO()); assertTrue("a*b = b*a", c.equals(d)); assertEquals("a*b = b*a", c, d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply(b.multiply(c)); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c", d, e); assertTrue("a(bc) = (ab)c", d.equals(e)); c = a.multiply(fac.getONE()); d = fac.getONE().multiply(a); assertEquals("a*1 = 1*a", c, d); c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*1/a = 1", fac.getONE(), d); try { a = fac.getZERO().inverse(); } catch (NotInvertibleException expected) { return; } fail("0 invertible"); } /** * Test distributive law. * */ public void testDistributive() { a = fac.random(ll); b = fac.random(ll); c = fac.random(ll); d = a.multiply(b.sum(c)); e = a.multiply(b).sum(a.multiply(c)); assertEquals("a(b+c) = ab+ac", d, e); } /** * Test compareTo of complex algebraic numbers. * */ public void testCompare() { a = fac.random(ll).abs(); b = a.sum(fac.getONE()); c = b.sum(fac.getONE()); int ab = a.compareTo(b); int bc = b.compareTo(c); int ac = a.compareTo(c); assertTrue("a < a+1 ", ab < 0); assertTrue("a+1 < a+2 ", bc < 0); assertTrue("a < a+2 ", ac < 0); a = a.negate(); b = a.sum(fac.getONE()); c = b.sum(fac.getONE()); ab = a.compareTo(b); bc = b.compareTo(c); ac = a.compareTo(c); assertTrue("a < a+1 ", ab < 0); assertTrue("a+1 < a+2 ", bc < 0); assertTrue("a < a+2 ", ac < 0); } } jas-2.5/trc/edu/jas/root/RootUtilTest.java0000644000175000017500000001607411774041270020747 0ustar giovannigiovanni/* * $Id: RootUtilTest.java 3974 2012-07-01 12:29:44Z kredel $ */ package edu.jas.root; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.arith.Roots; import edu.jas.kern.ComputerThreads; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.structure.Power; /** * RootUtil tests with JUnit. * @author Heinz Kredel. */ public class RootUtilTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a RootUtilTest object. * @param name String. */ public RootUtilTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(RootUtilTest.class); return suite; } //private final static int bitlen = 100; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; BigRational ai; BigRational bi; BigRational ci; BigRational di; BigRational ei; BigRational eps; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 1; int kl = 3; int ll = 5; int el = 7; float q = 0.7f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; String[] vars = new String[] { "x" }; dfac = new GenPolynomialRing(new BigRational(1), rl, to, vars); // eps = new BigRational(1L,1000000L*1000000L*1000000L); eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; dfac = null; eps = null; ComputerThreads.terminate(); } /** * Test sign variations. */ public void testSignVar() { int[] li = new int[] { 1, 0, 0, -1, 2, 3, 0, 1, 0, 0, 0, -1 }; List Li = new ArrayList(); ai = new BigRational(); for (int i = 0; i < li.length; i++) { bi = ai.fromInteger(li[i]); Li.add(bi); } //System.out.println("Li = " + Li); long v = RootUtil. signVar(Li); //System.out.println("v = " + v); assertEquals("varSign(Li)", v, 3); List Mi = new ArrayList(); for (int i = 0; i < 7; i++) { bi = ai.random(kl); Mi.add(bi); } //System.out.println("Mi = " + Mi); v = RootUtil. signVar(Mi); //System.out.println("v = " + v); long vv = v; assertTrue("varSign(Mi)>=0", v >= 0); List Ni = new ArrayList(Mi); Ni.addAll(Li); //System.out.println("Ni = " + Ni); v = RootUtil. signVar(Ni); //System.out.println("v = " + v); assertTrue("varSign(Mi)>=3", v >= 3 + vv); Ni = new ArrayList(Ni); Ni.addAll(Mi); //System.out.println("Ni = " + Ni); v = RootUtil. signVar(Ni); //System.out.println("v = " + v); assertTrue("varSign(Mi)>=3", v >= 3 + vv); } /** * Test real algebraic factory. */ public void testRealAlgebraicFactory() { a = dfac.random(kl, ll * 2, el * 2, q); //a = a.multiply( dfac.univariate(0) ); //System.out.println("a = " + a); List> lrn = RootFactory. realAlgebraicNumbers(a); //System.out.println("lrn = " + lrn); assertTrue("#roots >= 0 ", lrn.size() >= 0); for (RealAlgebraicNumber ra : lrn) { //System.out.println("ra = " + ra.toScript() + " in " + ra.toScriptFactory()); assertTrue("f(r) == 0: " + ra, RootFactory. isRoot(a,ra)); } lrn = RootFactory. realAlgebraicNumbersField(a); //System.out.println("lrn = " + lrn); assertTrue("#roots >= 0 ", lrn.size() >= 0); for (RealAlgebraicNumber ra : lrn) { //System.out.println("ra = " + ra.toScript() + " in " + ra.toScriptFactory()); assertTrue("f(r) == 0: " + ra, RootFactory. isRoot(a,ra)); } } /** * Test complex algebraic factory. */ public void testComplexAlgebraicFactory() { a = dfac.random(kl, ll, el, q); //a = a.multiply( dfac.univariate(0) ); //System.out.println("a = " + a); ComplexRing cf = new ComplexRing(new BigRational()); GenPolynomialRing> cfac = new GenPolynomialRing>(cf, dfac); GenPolynomial> ca = PolyUtil. toComplex(cfac, a); //System.out.println("ca = " + ca); List> lcn = RootFactory. complexAlgebraicNumbersComplex(ca); //System.out.println("lcn = " + lcn); assertTrue("#roots == deg(a): " + a, lcn.size() == a.degree(0)); for (ComplexAlgebraicNumber car : lcn) { //System.out.println("car = " + car.toScript() + " in " + car.toScriptFactory()); //System.out.println("car = " + car.ring.root); //System.out.println("car = " + car.ring.root.centerApprox() + ", " // + (Roots.sqrt(new BigDecimal(car.ring.root.rationalLength()))) + ", " + car.ring.root); assertTrue("f(r) == 0: " + car, RootFactory. isRoot(a,car)); } } /** * Test complex rational factory. */ public void testComplexRationalFactory() { a = dfac.random(kl, ll, el, q); //a = a.multiply( dfac.univariate(0) ); //a = dfac.parse(" 1/8 x^6 - 5/3 x^5 + 3/20 x^4 - 2 x^3 "); //System.out.println("a = " + a); List> lcn = RootFactory. complexAlgebraicNumbers(a); //System.out.println("lcn = " + lcn); assertTrue("#roots == deg(a): " + a, lcn.size() == a.degree(0)); for (ComplexAlgebraicNumber car : lcn) { //System.out.println("car = " + car.toScript() + " in " + car.toScriptFactory()); //System.out.println("car = " + car.ring.root); //System.out.println("car = " + car.ring.root.centerApprox() + ", " // + (Roots.sqrt(new BigDecimal(car.ring.root.rationalLength()))) + ", " + car.ring.root); assertTrue("f(r) == 0: " + car, RootFactory. isRoot(a,car)); } } } jas-2.5/trc/edu/jas/root/RealAlgebraicTest.java0000644000175000017500000003205512004002032021614 0ustar giovannigiovanni/* * $Id: RealAlgebraicTest.java 4039 2012-07-25 14:35:06Z kredel $ */ package edu.jas.root; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.NotInvertibleException; import edu.jas.structure.Power; /** * RealAlgebraicNumber Test using JUnit. * @author Heinz Kredel. */ public class RealAlgebraicTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a RealAlgebraicTest object. * @param name String. */ public RealAlgebraicTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(RealAlgebraicTest.class); return suite; } //private final static int bitlen = 100; RealAlgebraicRing fac; GenPolynomialRing mfac; RealAlgebraicNumber a; RealAlgebraicNumber b; RealAlgebraicNumber c; RealAlgebraicNumber d; RealAlgebraicNumber e; RealAlgebraicNumber alpha; int rl = 1; int kl = 10; int ll = 10; int el = ll; float q = 0.5f; @Override protected void setUp() { a = b = c = d = e = null; BigRational l = new BigRational(1); BigRational r = new BigRational(2); Interval positiv = new Interval(l, r); String[] vars = new String[] { "alpha" }; mfac = new GenPolynomialRing(new BigRational(1), rl, vars); GenPolynomial mo = mfac.univariate(0, 2); mo = mo.subtract(mfac.fromInteger(2)); // alpha^2 -2 fac = new RealAlgebraicRing(mo, positiv); alpha = fac.getGenerator(); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; alpha = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); //System.out.println("c.getVal() = " + c.getVal()); assertTrue("length( c ) = 1", c.number.getVal().length() == 1); assertTrue("isZERO( c )", !c.isZERO()); assertTrue("isONE( c )", c.isONE()); d = fac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.getVal() = " + d.getVal()); assertTrue("length( d ) = 0", d.number.getVal().length() == 0); assertTrue("isZERO( d )", d.isZERO()); assertTrue("isONE( d )", !d.isONE()); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(el); //System.out.println("a = " + a); if (a.isZERO() || a.isONE()) { continue; } // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a" + i + " ) <> 0", a.number.getVal().length() >= 0); assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); assertTrue(" not isONE( a" + i + " )", !a.isONE()); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a", a, d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a", c, d); c = fac.random(ll); d = c.sum(a.sum(b)); e = c.sum(a).sum(b); assertEquals("c+(a+b) = (c+a)+b", d, e); c = a.sum(fac.getZERO()); d = a.subtract(fac.getZERO()); assertEquals("a+0 = a-0", c, d); c = fac.getZERO().sum(a); d = fac.getZERO().subtract(a.negate()); assertEquals("0+a = 0+(-a)", c, d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO()); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO()); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO()); assertTrue("not isZERO( d )", !d.isZERO()); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO()); assertTrue("a*b = b*a", c.equals(d)); assertEquals("a*b = b*a", c, d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply(b.multiply(c)); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c", d, e); assertTrue("a(bc) = (ab)c", d.equals(e)); c = a.multiply(fac.getONE()); d = fac.getONE().multiply(a); assertEquals("a*1 = 1*a", c, d); c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*1/a = 1", fac.getONE(), d); try { a = fac.getZERO().inverse(); } catch (NotInvertibleException expected) { return; } fail("0 invertible"); } /** * Test distributive law. * */ public void testDistributive() { a = fac.random(ll); b = fac.random(ll); c = fac.random(ll); d = a.multiply(b.sum(c)); e = a.multiply(b).sum(a.multiply(c)); assertEquals("a(b+c) = ab+ac", d, e); } /** * Test sign of real algebraic numbers. * */ public void testSignum() { a = fac.random(ll); b = fac.random(ll); c = fac.random(ll); int sa = a.signum(); int sb = b.signum(); int sc = c.signum(); d = a.multiply(b); e = a.multiply(c); int sd = d.signum(); int se = e.signum(); assertEquals("sign(a*b) = sign(a)*sign(b) ", sa * sb, sd); assertEquals("sign(a*c) = sign(a)*sign(c) ", sa * sc, se); b = a.negate(); sb = b.signum(); assertEquals("sign(-a) = -sign(a) ", -sa, sb); } /** * Test compareTo of real algebraic numbers. * */ public void testCompare() { a = fac.random(ll).abs(); b = a.sum(fac.getONE()); c = b.sum(fac.getONE()); int ab = a.compareTo(b); int bc = b.compareTo(c); int ac = a.compareTo(c); assertTrue("a < a+1 ", ab < 0); assertTrue("a+1 < a+2 ", bc < 0); assertTrue("a < a+2 ", ac < 0); a = a.negate(); b = a.sum(fac.getONE()); c = b.sum(fac.getONE()); ab = a.compareTo(b); bc = b.compareTo(c); ac = a.compareTo(c); assertTrue("a < a+1 ", ab < 0); assertTrue("a+1 < a+2 ", bc < 0); assertTrue("a < a+2 ", ac < 0); } /** * Test arithmetic of magnitude of real algebraic numbers. * */ public void testMagnitude() { a = fac.random(ll); b = fac.random(ll); c = fac.random(ll); //BigDecimal ad = new BigDecimal(a.magnitude()); //BigDecimal bd = new BigDecimal(b.magnitude()); //BigDecimal cd = new BigDecimal(c.magnitude()); d = a.multiply(b); e = a.sum(b); BigDecimal dd = new BigDecimal(d.magnitude()); BigDecimal ed = new BigDecimal(e.magnitude()); BigDecimal dd1 = new BigDecimal(a.magnitude().multiply(b.magnitude())); BigDecimal ed1 = new BigDecimal(a.magnitude().sum(b.magnitude())); //System.out.println("ad = " + ad); //System.out.println("bd = " + bd); //System.out.println("cd = " + cd); //System.out.println("dd = " + dd); //System.out.println("dd1 = " + dd1); //System.out.println("ed = " + ed); //System.out.println("ed1 = " + ed1); //BigRational eps = Power.positivePower(new BigRational(1L,10L),BigDecimal.DEFAULT_PRECISION); BigRational eps = Power.positivePower(new BigRational(1L, 10L), 8); BigDecimal epsd = new BigDecimal(eps); assertTrue("mag(a*b) = mag(a)*mag(b): " + dd + ", " + dd1, dd.subtract(dd1).abs().compareTo(epsd) <= 0); assertTrue("mag(a+b) = mag(a)+mag(b): " + ed + ", " + ed1, ed.subtract(ed1).abs().compareTo(epsd) <= 0); d = a.divide(b); e = a.subtract(b); dd = new BigDecimal(d.magnitude()); ed = new BigDecimal(e.magnitude()); dd1 = new BigDecimal(a.magnitude().divide(b.magnitude())); ed1 = new BigDecimal(a.magnitude().subtract(b.magnitude())); //System.out.println("dd = " + dd); //System.out.println("dd1 = " + dd1); //System.out.println("ed = " + ed); //System.out.println("ed1 = " + ed1); assertTrue("mag(a/b) = mag(a)/mag(b)", dd.subtract(dd1).abs().compareTo(epsd) <= 0); assertTrue("mag(a-b) = mag(a)-mag(b)", ed.subtract(ed1).abs().compareTo(epsd) <= 0); } /** * Test real root isolation. Tests nothing. */ public void notestRealRootIsolation() { System.out.println(); GenPolynomialRing> dfac; dfac = new GenPolynomialRing>(fac, 1); GenPolynomial> ar; RealAlgebraicNumber epsr; ar = dfac.random(3, 5, 7, q); System.out.println("ar = " + ar); RealRoots> rrr = new RealRootsSturm>(); List>> R = rrr.realRoots(ar); System.out.println("R = " + R); assertTrue("#roots >= 0 ", R.size() >= 0); BigRational eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION); //BigRational eps = Power.positivePower(new BigRational(1L,10L),10); epsr = dfac.coFac.getONE().multiply(eps); //System.out.println("epsr = " + epsr); R = rrr.refineIntervals(R, ar, epsr); //System.out.println("R = " + R); for (Interval> v : R) { BigDecimal dd = v.toDecimal(); //.sum(eps1); System.out.println("v = " + dd); // assertTrue("|dd - di| < eps ", dd.compareTo(di) == 0); } } /** * Test real root isolation for Wilkinson like polynomials. * product_{i=1..n}( x - i * alpha ) * */ public void testRealRootIsolationWilkinson() { //System.out.println(); GenPolynomialRing> dfac; dfac = new GenPolynomialRing>(fac, 1); GenPolynomial> ar, br, cr, dr, er; RealRoots> rrr = new RealRootsSturm>(); final int N = 3; dr = dfac.getONE(); er = dfac.univariate(0); List>> Rn = new ArrayList>>( N); ar = dr; for (int i = 0; i < N; i++) { cr = dfac.fromInteger(i).multiply(alpha); // i * alpha Rn.add(new Interval>(cr.leadingBaseCoefficient())); br = er.subtract(cr); // ( x - i * alpha ) ar = ar.multiply(br); } //System.out.println("ar = " + ar); List>> R = rrr.realRoots(ar); //System.out.println("R = " + R); assertTrue("#roots = " + N + " ", R.size() == N); BigRational eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION); //BigRational eps = Power.positivePower(new BigRational(1L,10L),10); //System.out.println("eps = " + eps); //BigDecimal eps1 = new BigDecimal(eps); //System.out.println("eps1 = " + eps1); RealAlgebraicNumber epsr = dfac.coFac.getONE().multiply(eps); //System.out.println("epsr = " + epsr); R = rrr.refineIntervals(R, ar, epsr); //System.out.println("R = " + R); int i = 0; for (Interval> v : R) { BigDecimal dd = v.toDecimal();//.sum(eps1); BigDecimal di = Rn.get(i++).toDecimal(); //System.out.println("v = " + dd); //System.out.println("vi = " + di); assertTrue("|dd - di| < eps ", dd.compareTo(di) == 0); } } } jas-2.5/trc/edu/jas/root/ComplexRootTest.java0000644000175000017500000006516412004734454021445 0ustar giovannigiovanni/* * $Id: ComplexRootTest.java 4073 2012-07-28 10:04:29Z kredel $ */ package edu.jas.root; import java.util.ArrayList; import java.util.Collections; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.structure.Power; import edu.jas.ufd.Squarefree; import edu.jas.ufd.SquarefreeFactory; /** * RootUtil tests with JUnit. * @author Heinz Kredel. */ public class ComplexRootTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a ComplexRootTest object. * @param name String. */ public ComplexRootTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(ComplexRootTest.class); return suite; } TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing> dfac; ComplexRing cfac; BigRational eps; Complex ceps; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; GenPolynomial> d; GenPolynomial> e; int rl = 1; int kl = 3; int ll = 3; int el = 5; float q = 0.7f; @Override protected void setUp() { a = b = c = d = e = null; cfac = new ComplexRing(new BigRational(1)); String[] vars = new String[] { "x" }; dfac = new GenPolynomialRing>(cfac, rl, to, vars); eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION); ceps = new Complex(cfac, eps); } @Override protected void tearDown() { a = b = c = d = e = null; dfac = null; cfac = null; eps = null; } /** * Test root bound. * */ public void testRootBound() { //a = dfac.random(kl, ll, el, q); a = dfac.univariate(0, 2L).sum(dfac.getONE()); // x^2 + 1 //System.out.println("a = " + a); ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); Complex Mb = cr.rootBound(a); BigRational M = Mb.getRe(); //System.out.println("M = " + M); assertTrue("M >= 1 ", M.compareTo(BigRational.ONE) >= 0); //a = a.monic(); a = a.multiply(dfac.fromInteger(5)); //System.out.println("a = " + a); M = cr.rootBound(a).getRe(); //System.out.println("M = " + M); assertTrue("M >= 1 ", M.compareTo(BigRational.ONE) >= 0); } /** * Test Cauchy index. * */ public void testCauchyIndex() { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); //a = dfac.univariate(0,2L).sum(dfac.getONE()); // x^2 + 1 //System.out.println("a = " + a); //System.out.println("b = " + b); BigRational l = new BigRational(0); BigRational r = new BigRational(1); GenPolynomialRing fac = new GenPolynomialRing(l, dfac); ComplexRootsSturm cr = new ComplexRootsSturm(cfac); GenPolynomial f = PolyUtil. realPartFromComplex(fac, a); GenPolynomial g = PolyUtil. imaginaryPartFromComplex(fac, b); //System.out.println("re(a) = " + f); //System.out.println("im(b) = " + g); long ci = cr.indexOfCauchy(l, r, g, f); //System.out.println("ci = " + ci); assertTrue("ci >= 0 ", ci >= -a.degree(0)); } /** * Test Routh. * */ public void testRouth() { ComplexRootsSturm cr = new ComplexRootsSturm(cfac); //a = dfac.random(kl, ll, el, q); //b = dfac.random(kl, ll, el, q); Complex I = cfac.getIMAG(); GenPolynomial> X = dfac.univariate(0); //System.out.println("I = " + I); //System.out.println("X = " + X); //a = dfac.univariate(0,2L).sum( dfac.getONE().multiply(I) ); // x^2 + i //b = X.subtract( dfac.getONE().multiply( I ) ); // x - i b = X.subtract(dfac.getONE().multiply(I.negate())); // x + i c = X.subtract(dfac.getONE().multiply(I.multiply(cfac.fromInteger(3)))); // x - 3i d = X.subtract(dfac.getONE().multiply(I.multiply(cfac.fromInteger(4)))); // x - 4i e = X.subtract(dfac.getONE().multiply(I.multiply(cfac.fromInteger(5)))); // x - 5i a = b.multiply(c).multiply(d).multiply(e); //System.out.println("a = " + a.toScript()); //System.out.println("i = " + cfac.getIMAG()); Complex Mb = cr.rootBound(a); BigRational M = Mb.getRe(); //System.out.println("M = " + M); BigRational minf = M.negate(); // - infinity BigRational pinf = M; // + infinity GenPolynomialRing fac = new GenPolynomialRing(pinf, dfac); GenPolynomial f = PolyUtil. realPartFromComplex(fac, a); GenPolynomial g = PolyUtil. imaginaryPartFromComplex(fac, a); //System.out.println("re(a) = " + f.toScript()); //System.out.println("im(a) = " + g.toScript()); long[] ri = cr.indexOfRouth(minf, pinf, f, g); //System.out.println("ri = [" + ri[0] + ", " + ri[1] + " ]"); long deg = ri[0] + ri[1]; assertTrue("sum(ri) == deg(a) ", deg >= a.degree(0)); } /** * Test winding number. * */ @SuppressWarnings("unchecked") public void testWindingNumber() { ComplexRootsSturm cr = new ComplexRootsSturm(cfac); //Complex I = cfac.getIMAG(); a = dfac.univariate(0, 2L).sum(cfac.fromInteger(1)); // x^2 + 1 //a = dfac.random(kl, ll, el, q); //a = dfac.univariate(0,2L).subtract(cfac.getONE()); // x^2 - 1 //a = dfac.univariate(0,2L).subtract(I); // x^2 - I //a = dfac.univariate(0,1L); // x //System.out.println("a = " + a); Complex Mb = cr.rootBound(a); BigRational M = Mb.getRe(); //System.out.println("M = " + M); BigRational eps = new BigRational(1, 1000); //System.out.println("eps = " + eps); Complex[] corner = new Complex[4]; corner[0] = new Complex(cfac, M.negate(), M); // nw corner[1] = new Complex(cfac, M.negate(), M.negate()); // sw corner[2] = new Complex(cfac, M, M.negate()); // se corner[3] = new Complex(cfac, M, M); // ne long v = 0; try { v = cr.windingNumber(new Rectangle(corner), a); } catch (InvalidBoundaryException e) { fail("" + e); } //System.out.println("winding number = " + v); assertTrue("wind(rect,a) == 2 ", v == 2); //if ( true ) return; corner[0] = new Complex(cfac, M.negate(), M); // nw corner[1] = new Complex(cfac, M.negate(), eps); // sw corner[2] = new Complex(cfac, M, eps); // se corner[3] = new Complex(cfac, M, M); // ne try { v = cr.windingNumber(new Rectangle(corner), a); } catch (InvalidBoundaryException e) { fail("" + e); } //System.out.println("winding number = " + v); assertTrue("wind(rect,a) == 1 ", v == 1); corner[0] = new Complex(cfac, eps.negate(), eps); // nw corner[1] = new Complex(cfac, eps.negate(), eps.negate()); // sw corner[2] = new Complex(cfac, eps, eps.negate()); // se corner[3] = new Complex(cfac, eps, eps); // ne try { v = cr.windingNumber(new Rectangle(corner), a); } catch (InvalidBoundaryException e) { fail("" + e); } //System.out.println("winding number = " + v); assertTrue("wind(rect,a) == 0 ", v == 0); } /** * Test complex roots, sqrt(-1). * */ @SuppressWarnings("unchecked") public void testComplexRootsImag() { ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); //Complex I = cfac.getIMAG(); a = dfac.univariate(0, 2L).sum(cfac.fromInteger(1)); // x^2 + 1 //a = dfac.univariate(0,2L).subtract(cfac.getONE()); // x^2 - 1 //a = dfac.univariate(0,2L).subtract(I); // x^2 - I //a = dfac.univariate(0,1L); // x //System.out.println("a = " + a); Complex Mb = cr.rootBound(a); BigRational M = Mb.getRe(); //System.out.println("M = " + M); Complex[] corner = new Complex[4]; corner[0] = new Complex(cfac, M.negate(), M); // nw corner[1] = new Complex(cfac, M.negate(), M.negate()); // sw corner[2] = new Complex(cfac, M, M.negate()); // se corner[3] = new Complex(cfac, M, M); // ne Rectangle rect = new Rectangle(corner); List> roots = null; try { roots = cr.complexRoots(rect, a); } catch (InvalidBoundaryException e) { fail("" + e); } //System.out.println("roots = " + roots); assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); } /** * Test complex roots. */ @SuppressWarnings("unchecked") public void testComplexRootsRand() { ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); //Complex I = cfac.getIMAG(); a = dfac.random(kl, ll, el, q); Squarefree> engine = SquarefreeFactory .> getImplementation(cfac); a = engine.squarefreePart(a); //a = dfac.univariate(0,2L).subtract(cfac.getONE()); // x^2 - 1 //a = dfac.univariate(0,2L).sum(cfac.fromInteger(1)); // x^2 + 1 //a = dfac.univariate(0,2L).subtract(I); // x^2 - I //a = dfac.univariate(0,1L); // x //System.out.println("a = " + a); Complex Mb = cr.rootBound(a); BigRational M = Mb.getRe(); //System.out.println("M = " + M); Complex[] corner = new Complex[4]; corner[0] = new Complex(cfac, M.negate(), M); // nw corner[1] = new Complex(cfac, M.negate(), M.negate()); // sw corner[2] = new Complex(cfac, M, M.negate()); // se corner[3] = new Complex(cfac, M, M); // ne Rectangle rect = new Rectangle(corner); List> roots = null; try { roots = cr.complexRoots(rect, a); } catch (InvalidBoundaryException e) { fail("" + e); } //System.out.println("a = " + a); //System.out.println("roots = " + roots); assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); } /** * Test complex roots. */ public void testComplexRoots() { ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); a = dfac.random(kl, ll, el + 1, q); //System.out.println("a = " + a); List> roots = cr.complexRoots(a); //System.out.println("a = " + a); //System.out.println("roots = " + roots); assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); } /** * Test complex root refinement. */ public void testComplexRootRefinement() { ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); a = dfac.random(kl, ll, el - 1, q); //a = dfac.parse("( (x-1)^3 )"); Squarefree> engine = SquarefreeFactory .> getImplementation(cfac); //System.out.println("a = " + a); a = engine.squarefreePart(a); //System.out.println("a = " + a); List> roots = cr.complexRoots(a); //System.out.println("a = " + a); //System.out.println("roots = " + roots); assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); BigRational len = new BigRational(1, 1000); //System.out.println("len = " + len); for (Rectangle root : roots) { try { Rectangle refine = cr.complexRootRefinement(root, a, len); //System.out.println("refine = " + refine); assertFalse("refine != null", refine == null); } catch (InvalidBoundaryException e) { fail("" + e); } } } /** * Test complex root refinement full. */ public void testComplexRootRefinementFull() { ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); a = dfac.random(kl, ll, el - 1, q); //a = dfac.parse("( (x-1)^3 )"); //a = dfac.parse("( x^4-2 )"); //System.out.println("a = " + a); BigRational len = new BigRational(1, 1000); //System.out.println("len = " + len); List> refine = cr.complexRoots(a, len); //System.out.println("refine = " + refine); assertTrue("#roots == deg(a) ", refine.size() == a.degree(0)); } /** * Test winding number with wrong precondition. */ @SuppressWarnings("unchecked") public void testWindingNumberWrong() { ComplexRootsSturm cr = new ComplexRootsSturm(cfac); //Complex I = cfac.getIMAG(); a = dfac.univariate(0, 2L).sum(cfac.fromInteger(1)); // x^2 + 1 //a = dfac.random(kl, ll, el, q); //a = dfac.univariate(0,2L).subtract(cfac.getONE()); // x^2 - 1 //a = dfac.univariate(0,2L).subtract(I); // x^2 - I //a = dfac.univariate(0,1L); // x //System.out.println("a = " + a); Complex Mb = cfac.fromInteger(1); //.divide(cfac.fromInteger(2)); //cr.rootBound(a); BigRational M = Mb.getRe(); //System.out.println("M = " + M); //BigRational eps = new BigRational(1, 1000); //System.out.println("eps = " + eps); BigRational zero = new BigRational(); //BigRational one = new BigRational(1); Complex[] corner = new Complex[4]; corner[0] = new Complex(cfac, M.negate(), M); // nw corner[1] = new Complex(cfac, M.negate(), zero); // sw corner[2] = new Complex(cfac, M, zero); // se corner[3] = new Complex(cfac, M, M); // ne Rectangle rect = new Rectangle(corner); //System.out.println("rect = " + rect); try { long v = cr.windingNumber(rect, a); System.out.println("winding number = " + v); fail("wind(rect,a) must throw an exception"); } catch (InvalidBoundaryException e) { } } /** * Test complex root approximation. */ public void testComplexRootApproximation() { ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); //a = dfac.random(kl, ll, el-1, q); //a = dfac.parse("( (x-1)*(x-2)*(x-3)*(x - { 0i1 })*(x-5) )*( x^4-2 )"); //a = dfac.parse("( (x-1)*(x-2)*(x-3)*( x^4-2 ) )"); //a = dfac.parse("( (x-2)*( x^4-2 ) )"); a = dfac.parse("( ( x^4-2 ) )"); b = dfac.parse("( (x-1)*(x-2)*(x-3) )"); c = dfac.parse("( x^4-2 )"); d = dfac.parse("( (x - { 0i1 })*(x-5) )"); //a = c; // b; //.multiply(c); //.multiply(d); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); //a = b.multiply(c).multiply(d); //System.out.println("a = " + a); Squarefree> engine = SquarefreeFactory .> getImplementation(cfac); a = engine.squarefreePart(a); //System.out.println("a = " + a); eps = eps.multiply(new BigRational(1000000)); //System.out.println("eps = " + eps); //BigDecimal eps1 = new BigDecimal(eps); //BigDecimal eps2 = eps1.multiply(new BigDecimal("10")); //System.out.println("eps1 = " + eps1); //System.out.println("eps2 = " + eps2); List> roots = cr.complexRoots(a); //System.out.println("a = " + a); //System.out.println("roots = " + roots); assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); for (Rectangle root : roots) { try { Complex cd = cr.approximateRoot(root, a, eps); //System.out.println("cd = " + cd); assertFalse("cd != 0", cd.isZERO()); } catch (NoConvergenceException e) { //fail("" + e); } } } /** * Test complex root approximation full algorithm. */ public void testComplexRootApproximationFull() { ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); //a = dfac.random(kl, ll, el-1, q); //a = dfac.parse("( (x-1)*(x-2)*(x-3)*(x - { 0i1 })*(x-5) )*( x^4-2 )"); //a = dfac.parse("( (x-1)*(x-2)*(x-3)*( x^4-2 ) )"); a = dfac.parse("( (x-2)*( x^4-2 ) )"); //a = dfac.parse("( ( x^4-2 ) )"); b = dfac.parse("( (x-1)*(x-2)*(x-3) )"); c = dfac.parse("( x^4-2 )"); d = dfac.parse("( (x - { 0i1 })*(x-5) )"); //a = c; // b; //.multiply(c); //.multiply(d); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); //a = b.multiply(c).multiply(d); //System.out.println("a = " + a); eps = eps.multiply(new BigRational(1000000)); //System.out.println("eps = " + eps); //BigDecimal eps1 = new BigDecimal(eps); //BigDecimal eps2 = eps1.multiply(new BigDecimal("10")); //System.out.println("eps1 = " + eps1); //System.out.println("eps2 = " + eps2); List> roots = cr.approximateRoots(a, eps); //System.out.println("a = " + a); //System.out.println("roots = " + roots); //now always true: assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); } /** * Test complex root approximation full algorithm with Wilkinson * polynomials. p = (x-i0)*(x-i1)*(x-i2)*(x-i3*...*(x-in) */ public void testComplexRootApproximationWilkinsonFull() { final int N = 4; d = dfac.getONE(); e = dfac.univariate(0); BigDecimal br = new BigDecimal(); ComplexRing cf = new ComplexRing(br); Complex I = cf.getIMAG(); Complex cc = null; Complex Ir = cfac.getIMAG(); List> Rn = new ArrayList>(N); a = d; for (int i = 0; i < N; i++) { cc = cf.fromInteger(i).multiply(I); Rn.add(cc); c = dfac.fromInteger(i).multiply(Ir); b = e.subtract(c); a = a.multiply(b); } //System.out.println("a = " + a); Collections.reverse(Rn); //System.out.println("Rn = " + Rn); ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); eps = eps.multiply(new BigRational(100000)); //System.out.println("eps = " + eps); BigDecimal eps1 = new BigDecimal(eps); BigDecimal eps2 = eps1.multiply(new BigDecimal("10")); //System.out.println("eps1 = " + eps1); //System.out.println("eps2 = " + eps2); List> roots = cr.approximateRoots(a, eps); //System.out.println("a = " + a); //System.out.println("roots = " + roots); //now always true: assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); int i = 0; for (Complex dd : roots) { Complex di = Rn.get(i++); //System.out.print("di = " + di + ", "); //System.out.println("dd = " + dd); assertTrue("|dd - di| < eps ", dd.subtract(di).norm().getRe().compareTo(eps2) <= 0); } } /** * Test complex root approximation full algorithm with Wilkinson * polynomials, inverse roots. p = (x-1/i1)*(x-1/i2)*(x-1/i3*...*(x-1/in) */ public void testComplexRootApproximationWilkinsonInverseFull() { final int N = 5; d = dfac.getONE(); e = dfac.univariate(0); BigDecimal br = new BigDecimal(); ComplexRing cf = new ComplexRing(br); Complex I = cf.getIMAG(); Complex cc = null; Complex Ir = cfac.getIMAG(); List> Rn = new ArrayList>(N); a = d; for (int i = 1; i < N; i++) { cc = cf.fromInteger(i).multiply(I); cc = cc.inverse(); Rn.add(cc); c = dfac.fromInteger(i).multiply(Ir); c = d.divide(c); b = e.subtract(c); a = a.multiply(b); } //System.out.println("a = " + a); //Collections.sort(Rn); //System.out.println("Rn = " + Rn); ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); eps = eps.multiply(new BigRational(100000)); //System.out.println("eps = " + eps); BigDecimal eps1 = new BigDecimal(eps); BigDecimal eps2 = eps1.multiply(new BigDecimal("10")); //System.out.println("eps1 = " + eps1); //System.out.println("eps2 = " + eps2); List> roots = cr.approximateRoots(a, eps); //System.out.println("a = " + a); //System.out.println("roots = " + roots); //now always true: assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); //Collections.sort(roots); //System.out.println("roots = " + roots); for (Complex dd : roots) { //System.out.println("dd = " + dd); boolean t = false; for (Complex di : Rn) { //System.out.println("di = " + di); t = dd.subtract(di).norm().getRe().compareTo(eps2) <= 0; if (t) { break; } } if (!t) { //assertTrue("|dd - di| < eps ", dd.subtract(di).norm().getRe().compareTo(eps2) <= 0); fail("|dd - di| < eps "); } } } /** * Test complex root invariant rectangle. */ public void testComplexRootInvariant() { ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); a = dfac.random(kl, ll, el - 1, q); b = dfac.random(kl, ll, 2, q); //a = dfac.parse("( (x-1)^3 )"); //a = dfac.parse("( x^4-2 )"); if (a.degree() == 0) { return; } Squarefree> engine = SquarefreeFactory .> getImplementation(cfac); a = engine.squarefreePart(a); b = engine.squarefreePart(b); //System.out.println("a = " + a); //System.out.println("b = " + b); List> roots = cr.complexRoots(a); //System.out.println("roots = " + roots); assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); Rectangle rect = roots.get(0); //System.out.println("rect = " + rect); try { Rectangle ref = cr.invariantRectangle(rect, a, b); //System.out.println("rect = " + rect); //System.out.println("ref = " + ref); assertTrue("rect subseteq ref ", rect.contains(ref)); } catch (InvalidBoundaryException e) { e.printStackTrace(); fail("bad boundary"); } } /** * Test complex root invariant magnitude rectangle. */ public void testComplexRootInvariantMagnitude() { ComplexRootsAbstract cr = new ComplexRootsSturm(cfac); a = dfac.random(kl, ll, el - 1, q); b = dfac.random(kl, ll, 3, q); //a = dfac.parse("( x^2 + 1 )"); //b = dfac.parse("( x - 0i1 )"); if (a.degree() == 0) { return; } Squarefree> engine = SquarefreeFactory .> getImplementation(cfac); a = engine.squarefreePart(a); b = engine.squarefreePart(b); //System.out.println("a = " + a); //System.out.println("b = " + b); List> roots = cr.complexRoots(a); //System.out.println("roots = " + roots); assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); Rectangle rect = roots.get(0); //System.out.println("rect = " + rect); try { Rectangle ref = cr.invariantMagnitudeRectangle(rect, a, b, eps); //System.out.println("ref = " + ref); assertTrue("rect subseteq ref ", rect.contains(ref)); Complex mag = cr.complexRectangleMagnitude(ref, a, b); //System.out.println("mag = " + mag); Complex cmag = cr.complexMagnitude(ref, a, b, eps); //System.out.println("cmag = " + cmag); assertEquals("mag == cmag: " + cmag, mag, cmag); //BigRational rmag = cmag.getRe(); //System.out.println("rmag = " + new BigDecimal(cmag.getRe()) + " i " + new BigDecimal(cmag.getIm())); } catch (InvalidBoundaryException e) { e.printStackTrace(); fail("bad boundary"); } } } jas-2.5/trc/edu/jas/vector/0000755000175000017500000000000012140140260015755 5ustar giovannigiovannijas-2.5/trc/edu/jas/vector/GenMatrixTest.java0000644000175000017500000002401012014234362021362 0ustar giovannigiovanni/* * $Id: GenMatrixTest.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.vector; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; /** * GenMatrix tests with JUnit * @author Heinz Kredel. */ public class GenMatrixTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a GenMatrixTest object. * @param name String. */ public GenMatrixTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GenMatrixTest.class); return suite; } int rl = 5; int kl = 10; int ll = 10; float q = 0.5f; int rows = 3; int cols = 3; @Override protected void setUp() { } @Override protected void tearDown() { } /** * Test constructor and toString. */ public void testConstruction() { BigRational cfac = new BigRational(1); GenMatrixRing mfac = new GenMatrixRing(cfac, rows, cols); assertTrue("#rows = " + rows, mfac.rows == rows); assertTrue("#columns = " + cols, mfac.cols == cols); assertTrue("cfac == coFac ", cfac == mfac.coFac); GenMatrix a; a = mfac.getZERO(); //System.out.println("a = " + a); assertTrue("isZERO( a )", a.isZERO()); GenMatrix b = new GenMatrix(mfac); //System.out.println("b = " + b); assertTrue("isZERO( b )", b.isZERO()); assertTrue("a == b ", a.equals(b)); GenMatrix c = b.copy(); //System.out.println("c = " + c); assertTrue("isZERO( c )", c.isZERO()); assertTrue("a == c ", a.equals(c)); GenMatrix d = mfac.copy(b); //System.out.println("d = " + d); assertTrue("isZERO( d )", d.isZERO()); assertTrue("a == d ", a.equals(d)); a = mfac.getONE(); //System.out.println("a = " + a); assertTrue("isONE( a )", a.isONE()); List> m = a.matrix; List> ml = new ArrayList>(m.size()); for (ArrayList r : m) { ml.add(r); } b = mfac.fromList(ml); assertEquals("a == fromList(a.matrix)", a, b); } /** * Test random matrix. */ public void testRandom() { BigRational cfac = new BigRational(1); GenMatrixRing mfac = new GenMatrixRing(cfac, rows, cols); GenMatrixRing tfac = mfac.transpose(); if (rows == cols) { assertTrue(" mfac = tfac ", mfac.equals(tfac)); } GenMatrix a, b, c; for (int i = 0; i < 5; i++) { a = mfac.random(kl, q); //System.out.println("a = " + a); if (a.isZERO()) { continue; } assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); b = a.transpose(tfac); //System.out.println("b = " + b); assertTrue(" not isZERO( b" + i + " )", !b.isZERO()); c = b.transpose(mfac); //System.out.println("c = " + c); assertEquals(" a^r^r == a ", a, c); } } /** * Test addition. */ public void testAddition() { BigRational cfac = new BigRational(1); GenMatrixRing mfac = new GenMatrixRing(cfac, rows, cols); GenMatrix a, b, c, d, e; a = mfac.random(kl, q); b = mfac.random(kl, q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.sum(b); d = c.subtract(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b-b = a", a, d); c = a.sum(b); d = c.sum(b.negate()); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b+(-b) = a", a, d); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a", c, d); c = mfac.random(kl, q); d = a.sum(b).sum(c); e = a.sum(b.sum(c)); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("a+(b+c) = (a+b)+c", d, e); } /** * Test scalar multiplication. */ public void testScalarMultiplication() { BigRational cfac = new BigRational(1); GenMatrixRing mfac = new GenMatrixRing(cfac, rows, cols); BigRational r, s, t; GenMatrix a, b, c, d; r = cfac.random(kl); //System.out.println("r = " + r); s = r.inverse(); //System.out.println("s = " + s); a = mfac.random(kl, q); //System.out.println("a = " + a); c = a.scalarMultiply(r); d = c.scalarMultiply(s); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*b*(1/b) = a", a, d); b = mfac.random(kl, q); //System.out.println("b = " + b); t = cfac.getONE(); //System.out.println("t = " + t); c = a.linearCombination(b, t); d = b.linearCombination(a, t); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b = b+1*a", c, d); c = a.linearCombination(b, t); d = a.sum(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b = b+1*a", c, d); s = t.negate(); //System.out.println("s = " + s); c = a.linearCombination(b, t); d = c.linearCombination(b, s); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b+(-1)*b = a", a, d); c = a.linearCombination(t, b, t); d = c.linearCombination(t, b, s); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*1+b*1+b*(-1) = a", a, d); t = cfac.getZERO(); //System.out.println("t = " + t); c = a.linearCombination(b, t); //System.out.println("c = " + c); assertEquals("a+0*b = a", a, c); d = a.linearCombination(t, b, t); //System.out.println("d = " + d); assertEquals("0*a+0*b = 0", mfac.getZERO(), d); } /** * Test (simple) multiplication. */ public void testSimpleMultiplication() { BigRational cfac = new BigRational(1); GenMatrixRing mfac = new GenMatrixRing(cfac, rows, cols); GenMatrix a, b, c, d, e, f; a = mfac.getZERO(); b = mfac.getZERO(); c = a.multiplySimple(b); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("0*0 = 0 ", c.isZERO()); a = mfac.getONE(); b = mfac.getONE(); c = a.multiplySimple(b); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("1*1 = 1 ", c.isONE()); a = mfac.random(kl, q); b = mfac.getONE(); c = a.multiplySimple(b); d = a.multiply(b); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*1 = a ", a, c); assertEquals("a*1 = a*1 ", c, d); c = b.multiplySimple(a); d = a.multiply(b); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("1*a = a ", a, c); assertEquals("a*1 = a*1 ", c, d); b = mfac.random(kl, q); long s, t; s = System.currentTimeMillis(); c = a.multiplySimple(b); s = System.currentTimeMillis() - s; assertTrue("nonsense " + s, s >= 0L); d = b.multiplySimple(a); t = System.currentTimeMillis(); e = a.multiply(b); t = System.currentTimeMillis() - t; assertTrue("nonsense " + t, t >= 0L); f = b.multiply(a); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("f = " + e); //System.out.println("e = " + e); assertTrue("a*b != b*a ", !c.equals(d)); assertEquals("a*1 = a*1 ", c, e); assertEquals("a*1 = a*1 ", d, f); //System.out.println("time: s = " + s + ", t = " + t); if (!mfac.isAssociative()) { return; } c = mfac.random(kl, q); d = a.multiply(b.sum(c)); e = (a.multiply(b)).sum(a.multiply(c)); assertEquals("a*(b+c) = a*b+a*c", d, e); d = a.multiply(b.multiply(c)); e = (a.multiply(b)).multiply(c); assertEquals("a*(b*c) = (a*b)*c", d, e); } /** * Test parse matrix. */ public void testParse() { BigRational cfac = new BigRational(1); GenMatrixRing mfac = new GenMatrixRing(cfac, rows, cols); GenMatrix a, c; a = mfac.random(kl, q); //System.out.println("a = " + a); if (!a.isZERO()) { //return; assertTrue(" not isZERO( a )", !a.isZERO()); } String s = a.toString(); //System.out.println("s = " + s); c = mfac.parse(s); //System.out.println("c = " + c); assertEquals("parse(toStirng(a) == a ", a, c); } } jas-2.5/trc/edu/jas/vector/GenVectorTest.java0000644000175000017500000001510612014234362021366 0ustar giovannigiovanni/* * $Id: GenVectorTest.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.vector; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; /** * GenVector tests with JUnit * @author Heinz Kredel. */ public class GenVectorTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a RatGenVectorTest object. * @param name String. */ public GenVectorTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GenVectorTest.class); return suite; } int rl = 5; int kl = 10; int ll = 10; float q = 0.5f; @Override protected void setUp() { } @Override protected void tearDown() { } /** * Test constructor and toString. */ public void testConstruction() { BigRational cfac = new BigRational(1); GenVectorModul mfac = new GenVectorModul(cfac, ll); assertTrue("#columns = " + ll, mfac.cols == ll); assertTrue("cfac == coFac ", cfac == mfac.coFac); GenVector a; a = mfac.getZERO(); //System.out.println("a = " + a); assertTrue("isZERO( a )", a.isZERO()); GenVector b = new GenVector(mfac); //System.out.println("b = " + b); assertTrue("isZERO( b )", b.isZERO()); assertTrue("a == b ", a.equals(b)); GenVector c = b.copy(); //System.out.println("c = " + c); assertTrue("isZERO( c )", c.isZERO()); assertTrue("a == c ", a.equals(c)); GenVector d = mfac.copy(b); //System.out.println("d = " + d); assertTrue("isZERO( d )", d.isZERO()); assertTrue("a == d ", a.equals(d)); } /** * Test random vector. * */ public void testRandom() { BigRational cfac = new BigRational(1); GenVectorModul mfac = new GenVectorModul(cfac, ll); GenVector a; for (int i = 0; i < 7; i++) { a = mfac.random(kl, q); //System.out.println("a = " + a); if (a.isZERO()) { continue; } assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); } } /** * Test addition. * */ public void testAddition() { BigRational cfac = new BigRational(1); GenVectorModul mfac = new GenVectorModul(cfac, ll); GenVector a, b, c, d, e; a = mfac.random(kl, q); b = mfac.random(kl, q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.sum(b); d = c.subtract(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b-b = a", a, d); c = a.sum(b); d = c.sum(b.negate()); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b+(-b) = a", a, d); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a", c, d); c = mfac.random(kl, q); d = a.sum(b).sum(c); e = a.sum(b.sum(c)); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("a+(b+c) = (a+b)+c", d, e); } /** * Test scalar multiplication. * */ public void testMultiplication() { BigRational cfac = new BigRational(1); GenVectorModul mfac = new GenVectorModul(cfac, ll); BigRational r, s, t; GenVector a, b, c, d; r = cfac.random(kl); if (r.isZERO()) { r = cfac.getONE(); } //System.out.println("r = " + r); s = r.inverse(); //System.out.println("s = " + s); a = mfac.random(kl, q); //System.out.println("a = " + a); c = a.scalarMultiply(r); d = c.scalarMultiply(s); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*b*(1/b) = a " + r, a, d); b = mfac.random(kl, q); //System.out.println("b = " + b); t = cfac.getONE(); //System.out.println("t = " + t); c = a.linearCombination(b, t); d = b.linearCombination(a, t); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b = b+1*a", c, d); c = a.linearCombination(b, t); d = a.sum(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b = b+1*a", c, d); s = t.negate(); //System.out.println("s = " + s); c = a.linearCombination(b, t); d = c.linearCombination(b, s); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b+(-1)*b = a", a, d); c = a.linearCombination(t, b, t); d = c.linearCombination(t, b, s); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*1+b*1+b*(-1) = a", a, d); t = cfac.getZERO(); //System.out.println("t = " + t); c = a.linearCombination(b, t); //System.out.println("c = " + c); assertEquals("a+0*b = a", a, c); d = a.linearCombination(t, b, t); //System.out.println("d = " + d); assertEquals("0*a+0*b = 0", mfac.getZERO(), d); r = a.scalarProduct(b); s = b.scalarProduct(a); //System.out.println("r = " + r); //System.out.println("s = " + s); assertEquals("a.b = b.a", r, s); } /** * Test parse vector. * */ public void testParse() { BigRational cfac = new BigRational(1); GenVectorModul mfac = new GenVectorModul(cfac, ll); GenVector a, c; a = mfac.random(kl, q); //System.out.println("a = " + a); if (!a.isZERO()) { //return; assertTrue(" not isZERO( a )", !a.isZERO()); } String s = a.toString(); //System.out.println("s = " + s); c = mfac.parse(s); //System.out.println("c = " + c); assertEquals("parse(toStirng(a) == a ", a, c); } } jas-2.5/trc/edu/jas/gbufd/0000755000175000017500000000000012140140260015542 5ustar giovannigiovannijas-2.5/trc/edu/jas/gbufd/GroebnerBaseFGLMTest.java0000644000175000017500000002510511727161270022272 0ustar giovannigiovanni/* * $Id: GroebnerBaseFGLMTest.java 3912 2012-03-11 17:36:56Z suess $ */ package edu.jas.gbufd; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBase; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.gb.OrderedSyzPairlist; import edu.jas.gb.ReductionSeq; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.Complex; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; /** * Groebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class GroebnerBaseFGLMTest extends TestCase { /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GroebnerBaseFGLMTest object. * @param name String. */ public GroebnerBaseFGLMTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBaseFGLMTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G, Gs; GroebnerBase bb; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 4; //4; //3; int kl = 7; // 10 int ll = 7; int el = 3; // 4 float q = 0.2f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl, new TermOrder(TermOrder.INVLEX)); a = b = c = d = e = null; bb = new GroebnerBaseFGLM(); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; } /** * Test Trinks7 GBase. */ @SuppressWarnings("unchecked") public void testTrinks7GBase() { GroebnerBase bbs = new GroebnerBaseSeq(new ReductionSeq(), new OrderedSyzPairlist()); String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; String exam2 = "(x,y,z) L " + "( " + "( z y**2 + 2 x + 1/2 )" + "( z x**2 - y**2 - 1/2 x )" + "( -z + y**2 x + 4 x**2 + 1/4 )" + " )"; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); G = bb.GB(F.list); PolynomialList trinks = new PolynomialList(F.ring, G); //System.out.println("G = " + trinks); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); Gs = bbs.GB(F.list); PolynomialList trinks2 = new PolynomialList(F.ring, Gs); assertTrue("isGB( GB(Trinks7) )", bb.isGB(Gs)); assertEquals("#GB(Trinks7) == 6", 6, Gs.size()); assertEquals("GB == FGLM", trinks, trinks2); } /** * Test Trinks6 GBase. */ @SuppressWarnings("unchecked") public void testTrinks6GBase() { GroebnerBase bbs = new GroebnerBaseSeq(new ReductionSeq(), new OrderedSyzPairlist()); String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); G = bb.GB(F.list); PolynomialList trinks = new PolynomialList(F.ring, G); //System.out.println("G = " + trinks); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); Gs = bbs.GB(F.list); PolynomialList trinks2 = new PolynomialList(F.ring, Gs); assertTrue("isGB( GB(Trinks7) )", bb.isGB(Gs)); assertEquals("#GB(Trinks7) == 6", 6, Gs.size()); assertEquals("GB == FGLM", trinks, trinks2); } /** * Test Trinks7 GBase over Q(sqrt(2)). */ @SuppressWarnings("unchecked") public void testTrinks7GBaseSqrt() { GroebnerBase> bbs = new GroebnerBaseSeq>( new ReductionSeq>(), new OrderedSyzPairlist>()); GroebnerBase> bb = new GroebnerBaseFGLM>(); String exam = "AN[ (w2) (w2^2 - 2) ] (B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); PolynomialList> F = null; List>> G, Gs; try { F = (PolynomialList>) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); GenPolynomialRing> pfac = F.ring; AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac; //System.out.println("afac = " + afac); afac = new AlgebraicNumberRing(afac.modul, true); //System.out.println("afac = " + afac); pfac = new GenPolynomialRing>(afac, pfac); List>> Fp = new ArrayList>>( F.list.size()); for (GenPolynomial> p : F.list) { GenPolynomial> pp = pfac.copy(p); Fp.add(pp); } F = new PolynomialList>(pfac, Fp); G = bb.GB(F.list); PolynomialList> trinks = new PolynomialList>( F.ring, G); //System.out.println("G = " + trinks); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); Gs = bbs.GB(F.list); PolynomialList> trinks2 = new PolynomialList>( F.ring, Gs); //System.out.println("Gs = " + trinks2); assertTrue("isGB( GB(Trinks7) )", bb.isGB(Gs)); assertEquals("#GB(Trinks7) == 6", 6, Gs.size()); assertEquals("GB == FGLM", trinks, trinks2); } /** * Test Trinks7 GBase over Q(i). */ @SuppressWarnings("unchecked") public void testTrinks7GBaseCompl() { GroebnerBase> bbs = new GroebnerBaseSeq>( new ReductionSeq>(), new OrderedSyzPairlist>()); GroebnerBase> bb = new GroebnerBaseFGLM>(); String exam = "Complex (B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); PolynomialList> F = null; List>> G, Gs; try { F = (PolynomialList>) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); G = bb.GB(F.list); PolynomialList> trinks = new PolynomialList>(F.ring, G); //System.out.println("G = " + trinks); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); Gs = bbs.GB(F.list); PolynomialList> trinks2 = new PolynomialList>(F.ring, Gs); //System.out.println("Gs = " + trinks2); assertTrue("isGB( GB(Trinks7) )", bb.isGB(Gs)); assertEquals("#GB(Trinks7) == 6", 6, Gs.size()); assertEquals("GB == FGLM", trinks, trinks2); } } jas-2.5/trc/edu/jas/gbufd/GroebnerBaseSeqRationalTest.java0000644000175000017500000001625112045500020023751 0ustar giovannigiovanni/* * $Id: GroebnerBaseSeqRationalTest.java 4290 2012-11-04 14:47:45Z kredel $ */ package edu.jas.gbufd; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base sequential rational fraction free tests with JUnit. * @author Heinz Kredel. */ public class GroebnerBaseSeqRationalTest extends TestCase { private static final Logger logger = Logger.getLogger(GroebnerBaseSeqRationalTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GroebnerBaseSeqRationalTest object. * @param name String. */ public GroebnerBaseSeqRationalTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBaseSeqRationalTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBaseAbstract bb; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 4; //4; //3; int kl = 7; // 10 int ll = 7; int el = 3; // 4 float q = 0.2f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bb = new GroebnerBaseRational(); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; } /** * Test sequential GBase. */ public void testSequentialGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); L = bb.GB(L); assertTrue("isGB( { a } )", bb.isGB(L)); assertTrue("isMinimalGB( { a } )", bb.isMinimalGB(L)); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); //System.out.println("L = " + L.size() ); L = bb.GB(L); assertTrue("isGB( { a, b } )", bb.isGB(L)); assertTrue("isMinimalGB( { a, b } )", bb.isMinimalGB(L)); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.GB(L); assertTrue("isGB( { a, b, c } )", bb.isGB(L)); assertTrue("isMinimalGB( { a, b, c } )", bb.isMinimalGB(L)); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.GB(L); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L)); assertTrue("isMinimalGB( { a, b, c, d } )", bb.isMinimalGB(L)); assertTrue("not isZERO( e )", !e.isZERO()); L.add(e); L = bb.GB(L); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L)); assertTrue("isMinimalGB( { a, b, c, d, e } )", bb.isMinimalGB(L)); } /** * Test Trinks7 GBase. */ @SuppressWarnings("unchecked") public void testTrinks7GBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; String exam2 = "(x,y,z) L " + "( " + "( z y**2 + 2 x + 1/2 )" + "( z x**2 - y**2 - 1/2 x )" + "( -z + y**2 x + 4 x**2 + 1/4 )" + " )"; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); G = bb.GB(F.list); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G)); assertTrue("isMinimalGB( GB(Trinks7) )", bb.isMinimalGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } /** * Test Trinks7 compare GBase. */ @SuppressWarnings("unchecked") public void testTrinks7CompareGBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " //+ "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); long i = System.currentTimeMillis(); G = bb.GB(F.list); i = System.currentTimeMillis() - i; assertTrue("isGB( GB(Trinks7) )", bb.isGB(G)); assertTrue("isMinimalGB( GB(Trinks7) )", bb.isMinimalGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); GroebnerBaseAbstract bbr = new GroebnerBaseSeq(); List> Gr; long r = System.currentTimeMillis(); Gr = bbr.GB(F.list); r = System.currentTimeMillis() - r; assertTrue("isGB( GB(Trinks7) )", bbr.isGB(Gr)); assertTrue("isMinimalGB( GB(Trinks7) )", bbr.isMinimalGB(Gr)); assertEquals("#GB(Trinks7) == 6", 6, Gr.size()); if (logger.isInfoEnabled()) { logger.info("i = " + i + ", r = " + r); } assertEquals("GB_r == GB_i", G, Gr); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } } jas-2.5/trc/edu/jas/gbufd/GroebnerBasePseudoSeqTest.java0000644000175000017500000001260112002766222023445 0ustar giovannigiovanni/* * $Id: GroebnerBasePseudoSeqTest.java 4015 2012-07-22 12:05:38Z kredel $ */ package edu.jas.gbufd; import java.util.List; import java.util.ArrayList; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBase; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.poly.PolyUtil; /** * Groebner base pseudo reduction sequential tests with JUnit. * @author Heinz Kredel. */ public class GroebnerBasePseudoSeqTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBasePseudoSeqTest.class); /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a GroebnerBasePseudoSeqTest object. * @param name String. */ public GroebnerBasePseudoSeqTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(GroebnerBasePseudoSeqTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bb; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 10; int ll = 7; int el = 3; float q = 0.2f; //0.4f protected void setUp() { BigInteger coeff = new BigInteger(9); fac = new GenPolynomialRing(coeff,rl); a = b = c = d = e = null; bb = new GroebnerBasePseudoSeq(coeff); } protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; } /** * Test sequential GBase. * */ public void testSequentialGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); L = bb.GB( L ); assertTrue("isGB( { a } )", bb.isGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = bb.GB( L ); assertTrue("isGB( { a, b } )", bb.isGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = bb.GB( L ); assertTrue("isGB( { a, b, c } )", bb.isGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = bb.GB( L ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = bb.GB( L ); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L) ); } /** * Test Trinks7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7GBase() { String exam = "Z(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( 10000 B**2 + 6600 B + 2673 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); long s,t; t = System.currentTimeMillis(); G = bb.GB(F.list); t = System.currentTimeMillis() - t; assertTrue("isGB( GB(Trinks7) )", bb.isGB(G) ); assertEquals("#GB(Trinks7) == 6", 6, G.size() ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); assertTrue("nonsense ", t >= 0L); GenPolynomialRing ifac = F.ring; BigRational cf = new BigRational(); GenPolynomialRing rfac = new GenPolynomialRing(cf,ifac); List> Gr, Fr, Gir; Fr = PolyUtil.fromIntegerCoefficients(rfac,F.list); GroebnerBaseSeq bbr = new GroebnerBaseSeq(); s = System.currentTimeMillis(); Gr = bbr.GB(Fr); s = System.currentTimeMillis() - s; Gir = PolyUtil.fromIntegerCoefficients(rfac,G); Gir = PolyUtil.monic(Gir); assertEquals("ratGB == intGB", Gr, Gir ); //System.out.println("time: ratGB = " + s + ", intGB = " + t); assertTrue("nonsense ", s >= 0L); } } jas-2.5/trc/edu/jas/gbufd/CharSetTest.java0000644000175000017500000003356112004571452020620 0ustar giovannigiovanni/* * $Id: CharSetTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Chararacteristic set tests with JUnit. * @author Heinz Kredel. */ public class CharSetTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a CharSetTest object. * @param name String. */ public CharSetTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(CharSetTest.class); return suite; } CharacteristicSet cs; //TermOrder to = new TermOrder(TermOrder.INVLEX); TermOrder to = new TermOrder(TermOrder.IGRLEX); int rl = 3; int kl = 3; int ll = 4; int el = 3; float q = 0.29f; @Override protected void setUp() { cs = new CharacteristicSetWu(); } @Override protected void tearDown() { cs = null; } /** * Test random characteristic set simple. */ public void testCharacteristicSet() { CharacteristicSet css = new CharacteristicSetSimple(); GenPolynomialRing dfac; BigRational br = new BigRational(); to = new TermOrder(TermOrder.INVLEX); dfac = new GenPolynomialRing(br, rl, to); //System.out.println("dfac = " + dfac); GenPolynomial a, b, c, d, e; List> F, G, W; F = new ArrayList>(); a = dfac.random(kl, ll, el, q * 1.1f); b = dfac.random(kl, ll + 2, el, q); c = dfac.random(kl, ll, el, q); F.add(a); F.add(b); F.add(c); while (F.size() <= rl) { F.add(dfac.getZERO()); // make false cs } //F.add(dfac.fromInteger(17)); // test 1 //System.out.println("F = " + F); assertFalse("isCharacteristicSet: " + F, css.isCharacteristicSet(F)); G = css.characteristicSet(F); //System.out.println("G = " + G); assertTrue("isCharacteristicSet: " + G, css.isCharacteristicSet(G)); e = PolyGBUtil. topPseudoRemainder(G, a); //System.out.println("a = " + a + ", deg_1 = " + a.degree(rl-1)); //System.out.println("e = " + e + ", deg_1 = " + e.degree(rl-1)); assertTrue("a rem G: " + e, e.isZERO() || e.degree(rl - 1) < a.degree(rl - 1)); // not always true e = PolyGBUtil. topPseudoRemainder(G, G.get(0)); //System.out.println("e = " + e); assertTrue("a rem G: " + e + ", G = " + G, e.isZERO()); e = css.characteristicSetReduction(G, a); //System.out.println("a = " + a); //System.out.println("e = " + e); assertTrue("a mod G: " + e, e.isZERO() || e.degree(rl - 1) < a.degree(rl - 1)); // not always true d = dfac.getONE(); if (!G.contains(d)) { d = dfac.random(kl, ll, el, q).sum(d); //System.out.println("d = " + d); e = PolyGBUtil. topPseudoRemainder(G, d); //System.out.println("e = " + e); assertFalse("a rem G: " + e, e.isZERO()); e = css.characteristicSetReduction(G, d); //System.out.println("e = " + e); assertFalse("a mod G: " + e, e.isZERO()); } // now with Wu W = cs.characteristicSet(F); //System.out.println("F = " + F); //System.out.println("W = " + W); assertTrue("isCharacteristicSet: " + W, cs.isCharacteristicSet(W)); e = PolyGBUtil. topPseudoRemainder(W, a); //System.out.println("a = " + a + ", deg = " + a.degree(rl-1)); //System.out.println("e = " + e + ", deg = " + e.degree(rl-1)); assertTrue("a rem W: " + e, e.isZERO() || e.degree(rl - 1) < a.degree(rl - 1)); // not always true e = PolyGBUtil. topPseudoRemainder(W, W.get(0)); //System.out.println("e = " + e); assertTrue("a rem G: " + e + ", W = " + W, e.isZERO()); e = cs.characteristicSetReduction(W, W.get(W.size() - 1)); //System.out.println("e = " + e); assertTrue("a mod W: " + e, e.isZERO()); e = cs.characteristicSetReduction(W, a); //System.out.println("a = " + a); //System.out.println("e = " + e); assertTrue("a mod W: " + e, e.isZERO() || e.degree(rl - 1) < a.degree(rl - 1)); // not always true } /** * Test random characteristic set Wu. */ public void testCharacteristicSetWu() { GenPolynomialRing dfac; BigRational br = new BigRational(); to = new TermOrder(TermOrder.INVLEX); dfac = new GenPolynomialRing(br, rl, to); //System.out.println("dfac = " + dfac); GenPolynomial a, b, c, d, e; List> F, G; F = new ArrayList>(); a = dfac.random(kl, ll, el, q * 1.1f); b = dfac.random(kl, ll + 2, el, q); c = dfac.random(kl, ll, el, q); F.add(a); F.add(b); F.add(c); while (F.size() <= rl) { F.add(dfac.getZERO()); // make false cs } //F.add(dfac.fromInteger(19)); // test 1 //System.out.println("F = " + F); assertFalse("isCharacteristicSet: " + F, cs.isCharacteristicSet(F)); G = cs.characteristicSet(F); //System.out.println("G = " + G); assertTrue("isCharacteristicSet: " + G, cs.isCharacteristicSet(G)); e = PolyGBUtil. topPseudoRemainder(G, a); //System.out.println("e = " + e); assertTrue("a rem G: " + e, e.isZERO() || e.degree(rl - 1) < a.degree(rl - 1)); // not always true e = cs.characteristicSetReduction(G, G.get(G.size() - 1)); //System.out.println("e = " + e); assertTrue("a mod G: " + e, e.isZERO()); e = cs.characteristicSetReduction(G, G.get(0)); //System.out.println("e = " + e); assertTrue("a mod G: " + e, e.isZERO()); e = cs.characteristicSetReduction(G, a); //System.out.println("e = " + e); assertTrue("a mod G: " + e + ", G = " + G, e.isZERO() || e.degree(rl - 1) < a.degree(rl - 1)); // not always true d = dfac.getONE(); if (!G.contains(d)) { d = dfac.random(kl, ll, el, q).sum(d); //System.out.println("d = " + d); e = PolyGBUtil. topPseudoRemainder(G, d); //System.out.println("e = " + e); assertFalse("a rem G: " + e, e.isZERO()); e = cs.characteristicSetReduction(G, d); //System.out.println("e = " + e); assertFalse("a mod G: " + e, e.isZERO()); } } /** * Test characteristic set, example Circle of Apollonius, from CLO IVA, * 1992. */ public void testCharacteristicSetExample() { GenPolynomialRing dfac; BigRational br = new BigRational(); to = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "u1", "u2", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8" }; dfac = new GenPolynomialRing(br, to, vars); //System.out.println("dfac = " + dfac); GenPolynomial h1, h2, h3, h4, h5, h6, h7, h8, g, e; List> F, G; F = new ArrayList>(); h1 = dfac.parse(" 2 x1 - u1 "); h2 = dfac.parse(" 2 x2 - u2 "); h3 = dfac.parse(" 2 x3 - u1 "); h4 = dfac.parse(" 2 x4 - u2 "); h5 = dfac.parse(" u2 x5 + u1 x6 - u1 u2 "); h6 = dfac.parse(" u1 x5 - u2 x6 "); h7 = dfac.parse(" x1^2 - x2^2 - 2 x1 x7 + 2 x2 x8 "); h8 = dfac.parse(" x1^2 - 2 x1 x7 - x3^2 + 2 x3 x7 - x4^2 + 2 x4 x8 "); F.add(h1); F.add(h2); F.add(h3); F.add(h4); F.add(h5); F.add(h6); F.add(h7); F.add(h8); //System.out.println("F = " + F); assertFalse("isCharacteristicSet: " + F, cs.isCharacteristicSet(F)); G = cs.characteristicSet(F); //System.out.println("G = " + G); assertTrue("isCharacteristicSet: " + G, cs.isCharacteristicSet(G)); g = dfac.parse("( ( x5 - x7 )**2 + ( x6 - x8 )**2 - ( x1 - x7 )**2 - x8^2 )"); //g = dfac.parse("-2 x6 * x8 - 2 x5 * x7 + 2 x1 * x7 + x6^2 + x5^2 - x1^2"); //System.out.println("g = " + g); e = cs.characteristicSetReduction(G, g); //e = PolyGBUtil. topPseudoRemainder(G, g); //System.out.println("e = " + e); assertTrue("g mod G: " + e, e.isZERO()); // || true ?not always true //GroebnerBaseAbstract bb = GBFactory.getImplementation(br); //H = bb.GB(F); //System.out.println(" H = " + H); //Reduction red = bb.red; //f = red.normalform(H, g); //System.out.println("fg = " + f); //k = red.normalform(H, e); //System.out.println("fk' = " + k); //System.out.println("fk' == f: " + k.equals(f)); //System.out.println("fk' - f: " + k.subtract(f)); //K = red.normalform(H, G); //System.out.println("Kg = " + K); //L = red.normalform(H, F); //System.out.println("Lf = " + L); //assertEquals("Kg == Kf: " + L, K, L); } /** * Test characteristic set, example circum-center. */ public void ytestCharacteristicSetExampleCC() { GenPolynomialRing dfac; BigRational br = new BigRational(); to = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "u1", "u2", "u3", "x1", "x2", "x3" }; dfac = new GenPolynomialRing(br, to, vars); //System.out.println("dfac = " + dfac); GenPolynomial h1, h2, h3, g, e; List> F, G; F = new ArrayList>(); // wrong: h1 = dfac.parse(" 2 u1 x2 - u1^2 "); h2 = dfac.parse(" 2 u2 x2 + 2 u3 x1 - u2^2 - u3^2 "); h3 = dfac.parse(" 2 u3 x3 - 2 ( u2 - u1 ) x2 - u2^2 - u3^2 + u1^2 "); F.add(h1); F.add(h2); F.add(h3); System.out.println("F = " + F); assertFalse("isCharacteristicSet: " + F, cs.isCharacteristicSet(F)); G = cs.characteristicSet(F); System.out.println("G = " + G); assertTrue("isCharacteristicSet: " + G, cs.isCharacteristicSet(G)); g = dfac.parse(" x3^2 - 2 x3 x1 + x1^2 "); //g = dfac.parse(" x3 - x1 "); System.out.println("g = " + g); e = cs.characteristicSetReduction(G, g); //e = PolyGBUtil. characteristicSetRemainder(G,g); System.out.println("e = " + e); assertTrue("g mod G: " + e, e.isZERO() || e.degree(rl - 1) < g.degree(rl - 1)); // not always true } /** * Test characteristic set, example secant from wang. */ public void testCharacteristicSetExampleSec() { GenPolynomialRing dfac; BigRational br = new BigRational(); to = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "u1", "u2", "u3", "u4", "y1", "y2", "y3" }; dfac = new GenPolynomialRing(br, to, vars); //System.out.println("dfac = " + dfac); GenPolynomial h1, h2, h3, g, e; List> F, G; F = new ArrayList>(); h1 = dfac.parse(" 2 u3 y1 - u2^2 + u1^2 - u3^2 "); h2 = dfac.parse(" - y2^2 + 2 y1 y2 + u1^2 - u4^2 "); h3 = dfac.parse(" - y2 y3 + u3 y3 + y2 u2 - u4 u3 "); F.add(h1); F.add(h2); F.add(h3); //System.out.println("F = " + F); assertTrue("isCharacteristicSet: " + F, cs.isCharacteristicSet(F)); // already CS G = cs.characteristicSet(F); //System.out.println("G = " + G); assertTrue("isCharacteristicSet: " + G, cs.isCharacteristicSet(G)); g = dfac.parse("( (y3 + u1)^2 (y3 - u1)^2 - ( (y3 - u2)^2 + u3^2 ) ( (y3 - u4)^2 + y2^2 ) )"); //g = dfac.parse(" x3 - x1 "); //System.out.println("g = " + g); e = cs.characteristicSetReduction(G, g); //e = PolyGBUtil. characteristicSetRemainder(G,g); //System.out.println("e = " + e); assertTrue("g mod G: " + e, e.isZERO()); } /** * Test characteristic set, example ??. */ public void testCharacteristicSetExampleT() { GenPolynomialRing dfac; BigRational br = new BigRational(); to = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; dfac = new GenPolynomialRing(br, to, vars); //System.out.println("dfac = " + dfac); GenPolynomial h1, h2, h3; List> F, G; F = new ArrayList>(); h1 = dfac.parse(" x^2 + y + z - 1 "); h2 = dfac.parse(" x + y^2 + z - 1 "); h3 = dfac.parse(" x + y + z^2 - 1 "); F.add(h1); F.add(h2); F.add(h3); //System.out.println("F = " + F); assertFalse("isCharacteristicSet: " + F, cs.isCharacteristicSet(F)); G = cs.characteristicSet(F); //System.out.println("G = " + G); assertTrue("isCharacteristicSet: " + G, cs.isCharacteristicSet(G)); } } jas-2.5/trc/edu/jas/gbufd/ReductionTest.java0000644000175000017500000005566611641660762021246 0ustar giovannigiovanni/* * $Id: ReductionTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gbufd; import java.util.List; import java.util.ArrayList; import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.structure.RingFactory; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.BigComplex; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolynomialList; /** * Reduction tests with JUnit. * @author Heinz Kredel. */ public class ReductionTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ReductionTest object. * @param name String */ public ReductionTest(String name) { super(name); } /** * suite. * @return a test suite. */ public static Test suite() { TestSuite suite= new TestSuite(ReductionTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing fac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; List> L; PolynomialList F; PolynomialList G; //ReductionSeq red; //Reduction redpar; int rl = 4; int kl = 10; int ll = 11; int el = 5; float q = 0.6f; protected void setUp() { a = b = c = d = e = null; fac = new GenPolynomialRing( new BigRational(0), rl ); //red = new ReductionSeq(); //redpar = new ReductionPar(); } protected void tearDown() { a = b = c = d = e = null; fac = null; //red = null; //redpar = null; } /** * Test rational coefficient r-reduction. * */ public void testRationalRReduction() { RingFactory bi = new BigRational(0); ProductRing pr = new ProductRing(bi,3); GenPolynomialRing> fac = new GenPolynomialRing>( pr, rl ); RReductionSeq> rred = new RReductionSeq>(); GenPolynomial> a = fac.random(kl, ll, el, q ); GenPolynomial> b = fac.random(kl, ll, el, q ); GenPolynomial> d; while ( a.isZERO() ) { a = fac.random(kl, ll, el, q ); } while ( b.isZERO() ) { b = fac.random(kl, ll, el, q ); } assertTrue("not isZERO( a )", !a.isZERO() ); List>> L = new ArrayList>>(); L.add(a); GenPolynomial> e = rred.normalform( L, a ); //System.out.println("a = " + a); //System.out.println("e = " + e); assertTrue("isNF( e )", rred.isNormalform(L,e) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = rred.normalform( L, a ); //System.out.println("b = " + b); //System.out.println("e = " + e); assertTrue("isNF( e )", rred.isNormalform(L,e) ); GenPolynomial> c = fac.getONE(); a = a.sum(c); e = rred.normalform( L, a ); //System.out.println("a = " + a); //System.out.println("e = " + e); assertTrue("isNF( e )", rred.isNormalform(L,e) ); L = new ArrayList>>(); L.add( a ); assertTrue("isTopRed( a )", rred.isTopReducible(L,a) ); assertTrue("isRed( a )", rred.isReducible(L,a) ); //b = fac.random(kl, ll, el, q ); L.add( b ); assertTrue("isTopRed( b )", rred.isTopReducible(L,b) ); assertTrue("isRed( b )", rred.isReducible(L,b) ); c = fac.random(kl, ll, el, q ); e = rred.normalform( L, c ); assertTrue("isNF( e )", rred.isNormalform(L,e) ); c = rred.booleanClosure(a); //System.out.println("a = " + a); //System.out.println("c = " + c); assertTrue("isBC( c )", rred.isBooleanClosed(c) ); b = a.subtract(c); //System.out.println("b = " + b); d = rred.booleanRemainder(a); //System.out.println("d = " + d); assertEquals("a-BC(a)=BR(a)", b, d ); e = c.sum(d); //System.out.println("e = " + e); assertEquals("a==BC(a)+BR(a)", a, e ); List>> B; List>> Br; L = new ArrayList>>(); L.add( a ); B = rred.booleanClosure(L); Br = rred.reducedBooleanClosure(L); //System.out.println("L = " + L); //System.out.println("B = " + B); //System.out.println("Br = " + Br); assertTrue("isBC( B )", rred.isBooleanClosed(B) ); assertTrue("isBC( Br )", rred.isReducedBooleanClosed(Br) ); assertTrue("isBC( Br )", rred.isBooleanClosed(Br) ); //not always: assertEquals("B == Br", B, Br ); L.add( b ); B = rred.booleanClosure(L); Br = rred.reducedBooleanClosure(L); //System.out.println("L = " + L); //System.out.println("B = " + B); //System.out.println("Br = " + Br); assertTrue("isBC( B )", rred.isBooleanClosed(B) ); assertTrue("isBC( Br )", rred.isReducedBooleanClosed(Br) ); assertTrue("isBC( Br )", rred.isBooleanClosed(Br) ); //not always: assertEquals("B == Br", B, Br ); while ( c.isZERO() ) { c = fac.random(kl, ll, el, q ); } L.add( c ); B = rred.booleanClosure(L); Br = rred.reducedBooleanClosure(L); //System.out.println("L = " + L); //System.out.println("B = " + B); //System.out.println("Br = " + Br); assertTrue("isBC( B )", rred.isBooleanClosed(B) ); assertTrue("isBC( Br )", rred.isReducedBooleanClosed(Br) ); assertTrue("isBC( Br )", rred.isBooleanClosed(Br) ); //not always: assertEquals("B == Br", B, Br ); while ( d.isZERO() ) { d = fac.random(kl, ll, el, q ); } L.add( d ); B = rred.booleanClosure(L); Br = rred.reducedBooleanClosure(L); //System.out.println("L = " + L); //System.out.println("B = " + B); //System.out.println("Br = " + Br); assertTrue("isBC( B )", rred.isBooleanClosed(B) ); assertTrue("isBC( Br )", rred.isReducedBooleanClosed(Br) ); assertTrue("isBC( Br )", rred.isBooleanClosed(Br) ); //not always: assertEquals("B == Br", B, Br ); } /** * Test rational coefficient r-reduction with recording. * */ public void testRatRReductionRecording() { RingFactory bi = new BigRational(0); ProductRing pr = new ProductRing(bi,3); GenPolynomialRing> fac = new GenPolynomialRing>( pr, rl ); RReductionSeq> rred = new RReductionSeq>(); GenPolynomial> a = fac.random(kl, ll, el, q ); GenPolynomial> b = fac.random(kl, ll, el, q ); GenPolynomial> c, d, e; while ( a.isZERO() ) { a = fac.random(kl, ll, el, q ); } while ( b.isZERO() ) { b = fac.random(kl, ll, el, q ); } c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); List>> row = null; List>> L; assertTrue("not isZERO( a )", !a.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L = new ArrayList>>(); L.add(a); row = new ArrayList>>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = rred.normalform( row, L, a ); //not for regular rings: assertTrue("isZERO( e )", e.isZERO() ); //System.out.println("row = " + row); //System.out.println("L = " + L); //System.out.println("a = " + a); //System.out.println("e = " + e); assertTrue("is Reduction ", rred.isReductionNF(row,L,a,e) ); L.add(b); row = new ArrayList>>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = rred.normalform( row, L, b ); assertTrue("is Reduction ", rred.isReductionNF(row,L,b,e) ); L.add(c); row = new ArrayList>>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = rred.normalform( row, L, c ); assertTrue("is Reduction ", rred.isReductionNF(row,L,c,e) ); L.add(d); row = new ArrayList>>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = rred.normalform( row, L, d ); assertTrue("is Reduction ", rred.isReductionNF(row,L,d,e) ); } /** * Test integer coefficient pseudo-reduction. * */ public void testIntegerPseudoReduction() { BigInteger bi = new BigInteger(0); GenPolynomialRing fac = new GenPolynomialRing( bi, rl ); PseudoReductionSeq pred = new PseudoReductionSeq(); GenPolynomial a = fac.random(kl, ll, el, q ); GenPolynomial b = fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); List> L = new ArrayList>(); L.add(a); GenPolynomial e; e = pred.normalform( L, a ); //System.out.println("a = " + a); //System.out.println("e = " + e); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = pred.normalform( L, a ); //System.out.println("b = " + b); //System.out.println("e = " + e); assertTrue("isZERO( e ) some times", e.isZERO() ); GenPolynomial c = fac.getONE(); a = a.sum(c); e = pred.normalform( L, a ); //System.out.println("b = " + b); //System.out.println("e = " + e); assertTrue("isConstant( e ) some times", e.isConstant() ); L = new ArrayList>(); a = c.multiply( bi.fromInteger(4) ); b = c.multiply( bi.fromInteger(5) ); L.add( a ); e = pred.normalform( L, b ); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("e = " + e); assertTrue("isZERO( e )", e.isZERO() ); a = fac.random(kl, ll, el, q ); //.abs(); b = fac.random(kl, ll, el, q ); //.abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); L = new ArrayList>(); L.add( a ); assertTrue("isTopRed( a )", pred.isTopReducible(L,a) ); assertTrue("isRed( a )", pred.isReducible(L,a) ); b = fac.random(kl, ll, el, q ); L.add( b ); assertTrue("isTopRed( b )", pred.isTopReducible(L,b) ); assertTrue("isRed( b )", pred.isReducible(L,b) ); c = fac.random(kl, ll, el, q ); e = pred.normalform( L, c ); assertTrue("isNF( e )", pred.isNormalform(L,e) ); } /** * Test integer pseudo coefficient reduction with recording. * */ public void testIntReductionRecording() { BigInteger bi = new BigInteger(0); GenPolynomialRing fac = new GenPolynomialRing( bi, rl ); PseudoReductionSeq pred = new PseudoReductionSeq(); GenPolynomial a = fac.random(kl, ll, el, q ); GenPolynomial b = fac.random(kl, ll, el, q ); GenPolynomial c, d, e, f; if ( a.isZERO() || b.isZERO() ) { return; } c = fac.random(kl, ll, el+1, q ); d = fac.random(kl, ll, el+2, q ); // ------------ //a = fac.parse(" 1803 x0 * x1^4 - 299 x0^3 * x1^2 - 464 x1^4 + 648 x1^3 + 383 x0^3 + 1633 "); //b = fac.parse(" 593 x0^4 * x1^4 - 673 x0^3 * x1^4 + 36 x0^4 + 627 x1^2 + 617 x1 + 668 x0 + 168 "); //b = b.multiply( fac.parse(" 10567759154481 " ) ); //c = a.multiply( fac.parse(" 593 x0^3 - 938267 x0^2 - 435355888 x0 - 202005132032 ") ); //d = a.multiply( fac.parse(" 3475696715811 x0^3 - 3050126808003 x0^2 - 784946666064 x0 - 202005132032 ") ); //------------- List> row = null; List> L; PseudoReductionEntry mf; assertTrue("not isZERO( a )", !a.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L = new ArrayList>(); L.add(a); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } mf = pred.normalformFactor( L, a ); e = mf.pol; f = a.multiply( mf.multiplicator ); e = pred.normalform( row, L, f ); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("is Reduction ", pred.isNormalform(L,e) ); assertTrue("is ReductionNF ", pred.isReductionNF(row,L,f,e) ); L.add(b); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } mf = pred.normalformFactor( L, a ); e = mf.pol; f = a.multiply( mf.multiplicator ); e = pred.normalform( row, L, f ); assertTrue("is Reduction ", pred.isNormalform(L,e) ); assertTrue("is ReductionNF ", pred.isReductionNF(row,L,f,e) ); L.add(c); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } mf = pred.normalformFactor( L, a ); e = mf.pol; f = a.multiply( mf.multiplicator ); e = pred.normalform( row, L, f ); assertTrue("is Reduction ", pred.isNormalform(L,e) ); assertTrue("is ReductionNF ", pred.isReductionNF(row,L,f,e) ); L.add(d); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } mf = pred.normalformFactor( L, a ); e = mf.pol; f = a.multiply( mf.multiplicator ); e = pred.normalform( row, L, f ); assertTrue("is Reduction ", pred.isNormalform(L,e) ); assertTrue("is ReductionNF ", pred.isReductionNF(row,L,f,e) ); } /** * Test integer coefficient pseudo r-reduction. * */ public void testIntegerRReduction() { RingFactory bi = new BigInteger(0); ProductRing pr = new ProductRing(bi,3); GenPolynomialRing> fac = new GenPolynomialRing>( pr, rl ); RReductionSeq> rpred = new RPseudoReductionSeq>(); GenPolynomial> a = fac.random(kl, ll, el, q ); GenPolynomial> b = fac.random(kl, ll, el, q ); GenPolynomial> c, d, e; while ( a.isZERO() ) { a = fac.random(kl, ll, el, q ); } while ( b.isZERO() ) { b = fac.random(kl, ll, el, q ); } assertTrue("not isZERO( a )", !a.isZERO() ); List>> L = new ArrayList>>(); L.add(a); e = rpred.normalform( L, a ); //System.out.println("a = " + a); //System.out.println("e = " + e); assertTrue("isNF( e )", rpred.isNormalform(L,e) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = rpred.normalform( L, a ); assertTrue("isNF( e )", rpred.isNormalform(L,e) ); c = fac.getONE(); a = a.sum(c); e = rpred.normalform( L, a ); assertTrue("isNF( e )", rpred.isNormalform(L,e) ); L = new ArrayList>>(); L.add( a ); assertTrue("isTopRed( a )", rpred.isTopReducible(L,a) ); assertTrue("isRed( a )", rpred.isReducible(L,a) ); //b = fac.random(kl, ll, el, q ); L.add( b ); assertTrue("isTopRed( b )", rpred.isTopReducible(L,b) ); assertTrue("isRed( b )", rpred.isReducible(L,b) ); c = fac.random(kl, ll, el, q ); e = rpred.normalform( L, c ); assertTrue("isNF( e )", rpred.isNormalform(L,e) ); c = rpred.booleanClosure(a); //System.out.println("\nboolean closure"); //System.out.println("a = " + a); //System.out.println("c = " + c); assertTrue("isBC( c )", rpred.isBooleanClosed(c) ); b = a.subtract(c); //System.out.println("b = " + b); d = rpred.booleanRemainder(a); //System.out.println("d = " + d); assertEquals("a-BC(a)=BR(a)", b, d ); e = c.sum(d); //System.out.println("e = " + e); assertEquals("a==BC(a)+BR(a)", a, e ); List>> B; List>> Br; L = new ArrayList>>(); L.add( a ); B = rpred.booleanClosure(L); Br = rpred.reducedBooleanClosure(L); assertTrue("isBC( B )", rpred.isBooleanClosed(B) ); assertTrue("isBC( Br )", rpred.isReducedBooleanClosed(Br) ); assertTrue("isBC( Br )", rpred.isBooleanClosed(Br) ); //not always: assertEquals("B == Br", B, Br ); L.add( b ); B = rpred.booleanClosure(L); Br = rpred.reducedBooleanClosure(L); assertTrue("isBC( B )", rpred.isBooleanClosed(B) ); assertTrue("isBC( Br )", rpred.isReducedBooleanClosed(Br) ); assertTrue("isBC( Br )", rpred.isBooleanClosed(Br) ); //not always: assertEquals("B == Br", B, Br ); L.add( c ); B = rpred.booleanClosure(L); Br = rpred.reducedBooleanClosure(L); assertTrue("isBC( B )", rpred.isBooleanClosed(B) ); assertTrue("isBC( Br )", rpred.isReducedBooleanClosed(Br) ); assertTrue("isBC( Br )", rpred.isBooleanClosed(Br) ); //not always: assertEquals("B == Br", B, Br ); while ( d.isZERO() ) { d = fac.random(kl, ll, el, q ); } L.add( d ); B = rpred.booleanClosure(L); Br = rpred.reducedBooleanClosure(L); assertTrue("isBC( B )", rpred.isBooleanClosed(B) ); assertTrue("isBC( Br )", rpred.isReducedBooleanClosed(Br) ); assertTrue("isBC( Br )", rpred.isBooleanClosed(Br) ); //not always: assertEquals("B == Br", B, Br ); } /** * Test integer pseudo coefficient r-reduction with recording. * */ public void testIntRReductionRecording() { RingFactory bi = new BigInteger(0); ProductRing pr = new ProductRing(bi,3); GenPolynomialRing> fac = new GenPolynomialRing>( pr, rl ); RPseudoReductionSeq> rpred = new RPseudoReductionSeq>(); GenPolynomial> a = fac.random(kl, ll, el, q ); GenPolynomial> b = fac.random(kl, ll, el, q ); GenPolynomial> c, d, e, f; while ( a.isZERO() ) { a = fac.random(kl, ll, el, q ); } while ( b.isZERO() ) { b = fac.random(kl, ll, el, q ); } assertTrue("not isZERO( a )", !a.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); List>> row = null; List>> L; PseudoReductionEntry> mf; L = new ArrayList>>(); L.add(a); row = new ArrayList>>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } mf = rpred.normalformFactor( L, a ); e = mf.pol; f = a.multiply( mf.multiplicator ); e = rpred.normalform( row, L, f ); //not for regular rings: assertTrue("isZERO( e )", e.isZERO() ); assertTrue("is Reduction ", rpred.isNormalform(L,e) ); assertTrue("is ReductionNF ", rpred.isReductionNF(row,L,f,e) ); L.add(b); row = new ArrayList>>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } mf = rpred.normalformFactor( L, a ); e = mf.pol; f = a.multiply( mf.multiplicator ); e = rpred.normalform( row, L, f ); assertTrue("is Reduction ", rpred.isNormalform(L,e) ); assertTrue("is ReductionNF ", rpred.isReductionNF(row,L,f,e) ); L.add(c); row = new ArrayList>>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } mf = rpred.normalformFactor( L, a ); e = mf.pol; f = a.multiply( mf.multiplicator ); e = rpred.normalform( row, L, f ); assertTrue("is Reduction ", rpred.isNormalform(L,e) ); assertTrue("is ReductionNF ", rpred.isReductionNF(row,L,f,e) ); L.add(d); row = new ArrayList>>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } mf = rpred.normalformFactor( L, a ); e = mf.pol; f = a.multiply( mf.multiplicator ); e = rpred.normalform( row, L, f ); assertTrue("is Reduction ", rpred.isNormalform(L,e) ); assertTrue("is ReductionNF ", rpred.isReductionNF(row,L,f,e) ); } } jas-2.5/trc/edu/jas/gbufd/RGroebnerBaseSeqTest.java0000644000175000017500000001604312004571452022414 0ustar giovannigiovanni/* * $Id: RGroebnerBaseSeqTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.gbufd; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.gb.GroebnerBase; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolyUtil; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; import edu.jas.structure.RingFactory; /** * R-Groebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class RGroebnerBaseSeqTest extends TestCase { //private static final Logger logger = Logger.getLogger(RGroebnerBaseSeqTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a RGroebnerBaseSeqTest object. * @param name String. */ public RGroebnerBaseSeqTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(RGroebnerBaseSeqTest.class); return suite; } ProductRing pfac; GenPolynomialRing> fac; List>> L; PolynomialList> F; List>> G; GroebnerBase> bb; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; GenPolynomial> d; GenPolynomial> e; int rl = 3; //4; //3; int kl = 10; int ll = 7; int el = 3; float q = 0.2f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(9); pfac = new ProductRing(coeff, 4); fac = new GenPolynomialRing>(pfac, rl); a = b = c = d = e = null; bb = new RGroebnerBaseSeq>(); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; } /** * Test sequential GBase. * */ public void testSequentialGBase() { L = new ArrayList>>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); L = bb.GB(L); assertTrue("isGB( { a } )", bb.isGB(L)); //System.out.println("L = " + L ); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); //System.out.println("L = " + L.size() ); L = bb.GB(L); assertTrue("isGB( { a, b } )", bb.isGB(L)); //System.out.println("L = " + L ); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.GB(L); assertTrue("isGB( { a, b, c } )", bb.isGB(L)); //System.out.println("L = " + L ); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.GB(L); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L)); //System.out.println("L = " + L ); assertTrue("not isZERO( e )", !e.isZERO()); L.add(e); L = bb.GB(L); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L)); //System.out.println("L = " + L ); } /** * Test Trinks7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7() { String exam = "Z(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( 10000 B**2 + 6600 B + 2673 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); PolynomialList F = null; try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); int rl = F.ring.nvar; TermOrder to = F.ring.tord; String[] vars = F.ring.getVars(); PolynomialList> trinks; List> colist; colist = new ArrayList>(); //colist.add( new ModIntegerRing(2) ); //colist.add( new ModIntegerRing(3) ); //colist.add( new ModIntegerRing(5) ); //colist.add( new ModIntegerRing(30) ); // now ok, was not possible colist.add(new ModIntegerRing(19)); colist.add(new ModIntegerRing(23)); //colist.add( new ModIntegerRing((2<<30)-19) ); //System.out.println("colist = " + colist); ProductRing pfac; pfac = new ProductRing(colist); //System.out.println("pfac = " + pfac); GenPolynomialRing> fac; fac = new GenPolynomialRing>(pfac, rl, to, vars); //System.out.println("fac = " + fac); List>> Fp; Fp = PolyUtil.toProduct(fac, F.list); List>> Fpp; Fpp = new ArrayList>>(); for (GenPolynomial> a : Fp) { Fpp.add(a.multiply(pfac.getAtomic(0))); Fpp.add(a.multiply(pfac.getAtomic(1))); //Fpp.add( a ); } Fp = Fpp; //trinks = new PolynomialList>(fac, Fp); //System.out.println("Fp = " + trinks); GroebnerBase> bbr = new RGroebnerBaseSeq>(); List>> G; G = bbr.GB(Fp); //System.out.println("gb = " + G ); //assertEquals("#GB(Trinks7) == 6", 6, G.size() ); //System.out.println("Fp = " + trinks); trinks = new PolynomialList>(fac, G); assertFalse("trings != null", trinks == null); //System.out.println("G = " + trinks); assertTrue("isGB( GB(Trinks7) )", bbr.isGB(G)); } } jas-2.5/trc/edu/jas/gbufd/MultiplicativeSetTest.java0000644000175000017500000004616111641660762022747 0ustar giovannigiovanni/* * $Id: MultiplicativeSetTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gbufd; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; /** * MultiplicativeSet tests with JUnit. * @author Heinz Kredel. */ public class MultiplicativeSetTest extends TestCase { //private static final Logger logger = Logger.getLogger(MultiplicativeSetTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a MultiplicativeSetTest object. * @param name String. */ public MultiplicativeSetTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(MultiplicativeSetTest.class); return suite; } TermOrder to; GenPolynomialRing fac; List> L; PolynomialList F; List> G; List> M; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 4; //10 int ll = 5; //7 int el = 3; float q = 0.2f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(17, 1); to = new TermOrder( /*TermOrder.INVLEX*/); fac = new GenPolynomialRing(coeff, rl, to); a = b = c = d = e = null; } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; ComputerThreads.terminate(); } /** * Test multiplicative set contained. * */ public void testContaines() { a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } MultiplicativeSet ms = new MultiplicativeSet(fac); //System.out.println("ms = " + ms); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("isEmpty ", ms.isEmpty()); if (!a.isConstant()) { assertFalse("not contained ", ms.contains(a)); } MultiplicativeSet ms2 = ms.add(a); //System.out.println("ms2 = " + ms2); if (!a.isConstant()) { assertFalse("not isEmpty ", ms2.isEmpty()); assertTrue("contained ", ms2.contains(a)); } if (!a.equals(b) && !b.isConstant()) { assertFalse("not contained ", ms2.contains(b)); } MultiplicativeSet ms3 = ms2.add(b); //System.out.println("ms3 = " + ms3); if (!b.isConstant()) { assertFalse("not isEmpty ", ms3.isEmpty()); } assertTrue("contained ", ms3.contains(a)); assertTrue("contained ", ms3.contains(b)); if (!a.equals(c) && !b.equals(c) && !c.isConstant()) { assertFalse("not contained ", ms3.contains(c)); } e = a.multiply(b); //System.out.println("e = " + e); if (!e.isConstant()) { assertTrue("contained ", ms3.contains(e)); } MultiplicativeSet ms4 = ms3.add(e); //System.out.println("ms4 = " + ms4); assertTrue("m3 == m4 ", ms3.equals(ms4)); } /** * Test multiplicative set removeFactors. * */ public void testRemoveFactors() { a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } MultiplicativeSet ms = new MultiplicativeSet(fac); //System.out.println("ms = " + ms); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("isEmpty ", ms.isEmpty()); e = ms.removeFactors(a); //System.out.println("e = " + e); assertEquals("a == remove(a) ", a, e); MultiplicativeSet ms2 = ms.add(a); //System.out.println("ms2 = " + ms2); if (!a.isConstant()) { assertFalse("not isEmpty ", ms2.isEmpty()); assertTrue("contained ", ms2.contains(a)); e = ms2.removeFactors(a); //System.out.println("e = " + e); assertTrue("1 == remove(a) ", e.isConstant()); if (!b.isConstant()) { e = ms2.removeFactors(b); //System.out.println("e = " + e); assertEquals("b == remove(b) ", e, b); } } d = a.multiply(b); MultiplicativeSet ms3 = ms2.add(d); //System.out.println("ms3 = " + ms3); if (!d.isConstant()) { assertFalse("not isEmpty ", ms3.isEmpty()); e = ms3.removeFactors(a); //System.out.println("e = " + e); assertTrue("1 == remove(a) ", e.isConstant()); e = ms3.removeFactors(b); //System.out.println("e = " + e); assertTrue("1 == remove(b) ", e.isConstant()); e = ms3.removeFactors(d); //System.out.println("e = " + e); assertTrue("1 == remove(a*b) ", e.isConstant()); if (!c.isConstant()) { e = ms3.removeFactors(c); //System.out.println("e = " + e); assertEquals("c == remove(c) ", e, c); } } } /** * Test co-prime multiplicative set contained. * */ public void testCoPrimeContaines() { a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } MultiplicativeSet ms = new MultiplicativeSetCoPrime(fac); //System.out.println("ms = " + ms); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("isEmpty ", ms.isEmpty()); if (!a.isConstant()) { assertFalse("not contained ", ms.contains(a)); } MultiplicativeSet ms2 = ms.add(a); //System.out.println("ms2 = " + ms2); if (!a.isConstant()) { assertFalse("not isEmpty ", ms2.isEmpty()); assertTrue("contained ", ms2.contains(a)); } if (!a.equals(b) && !b.isConstant()) { assertFalse("not contained " + ms2, ms2.contains(b)); } MultiplicativeSet ms3 = ms2.add(b); //System.out.println("ms3 = " + ms3); if (!b.isConstant()) { assertFalse("not isEmpty ", ms3.isEmpty()); } assertTrue("contained ", ms3.contains(a)); assertTrue("contained ", ms3.contains(b)); if (!a.equals(c) && !b.equals(c) && !c.isConstant()) { assertFalse("not contained " + ms3, ms3.contains(c)); } e = a.multiply(b); //System.out.println("e = " + e); if (!e.isConstant()) { assertTrue("contained ", ms3.contains(e)); } MultiplicativeSet ms4 = ms3.add(e); //System.out.println("ms4 = " + ms4); assertTrue("m3 == m4 ", ms3.equals(ms4)); } /** * Test co-prime multiplicative set removeFactors. * */ public void testCoPrimeRemoveFactors() { a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } MultiplicativeSet ms = new MultiplicativeSetCoPrime(fac); //System.out.println("ms = " + ms); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("isEmpty ", ms.isEmpty()); e = ms.removeFactors(a); //System.out.println("e = " + e); assertEquals("a == remove(a) ", a, e); MultiplicativeSet ms2 = ms.add(a); //System.out.println("ms2 = " + ms2); if (!a.isConstant()) { assertFalse("not isEmpty ", ms2.isEmpty()); assertTrue("contained ", ms2.contains(a)); e = ms2.removeFactors(a); //System.out.println("e = " + e); assertTrue("1 == remove(a) ", e.isConstant()); if (!b.isConstant()) { e = ms2.removeFactors(b); //System.out.println("e = " + e); assertEquals("b == remove(b) ", e, b); } } d = a.multiply(b); MultiplicativeSet ms3 = ms2.add(d); //System.out.println("ms3 = " + ms3); if (!d.isConstant()) { assertFalse("not isEmpty ", ms3.isEmpty()); e = ms3.removeFactors(a); //System.out.println("e = " + e); assertTrue("1 == remove(a) ", e.isConstant()); e = ms3.removeFactors(b); //System.out.println("e = " + e); assertTrue("1 == remove(b) ", e.isConstant()); e = ms3.removeFactors(d); //System.out.println("e = " + e); assertTrue("1 == remove(a*b) ", e.isConstant()); if (!c.isConstant()) { e = ms3.removeFactors(c); //System.out.println("e = " + e); assertEquals("c == remove(c) ", e, c); } } } /** * Test squarefree multiplicative set contained. * */ public void testSquarefreeContaines() { a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } MultiplicativeSet ms = new MultiplicativeSetSquarefree(fac); //System.out.println("ms = " + ms); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("isEmpty ", ms.isEmpty()); if (!a.isConstant()) { assertFalse("not contained ", ms.contains(a)); } MultiplicativeSet ms2 = ms.add(a); //System.out.println("ms2 = " + ms2); if (!a.isConstant()) { assertFalse("not isEmpty ", ms2.isEmpty()); assertTrue("contained ", ms2.contains(a)); } if (!a.equals(b) && !b.isConstant()) { assertFalse("not contained " + ms2, ms2.contains(b)); } MultiplicativeSet ms3 = ms2.add(b); //System.out.println("ms3 = " + ms3); if (!b.isConstant()) { assertFalse("not isEmpty ", ms3.isEmpty()); } assertTrue("contained ", ms3.contains(a)); assertTrue("contained ", ms3.contains(b)); if (!a.equals(c) && !b.equals(c) && !c.isConstant()) { assertFalse("not contained " + ms3, ms3.contains(c)); } e = a.multiply(b); //System.out.println("e = " + e); if (!e.isConstant()) { assertTrue("contained ", ms3.contains(e)); } MultiplicativeSet ms4 = ms3.add(e); //System.out.println("ms4 = " + ms4); assertTrue("m3 == m4 ", ms3.equals(ms4)); } /** * Test squarefree multiplicative set removeFactors. * */ public void testSquarefreeRemoveFactors() { a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } MultiplicativeSet ms = new MultiplicativeSetSquarefree(fac); //System.out.println("ms = " + ms); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("isEmpty ", ms.isEmpty()); e = ms.removeFactors(a); //System.out.println("e = " + e); assertEquals("a == remove(a) ", a, e); MultiplicativeSet ms2 = ms.add(a); //System.out.println("ms2 = " + ms2); if (!a.isConstant()) { assertFalse("not isEmpty ", ms2.isEmpty()); assertTrue("contained ", ms2.contains(a)); e = ms2.removeFactors(a); //System.out.println("e = " + e); assertTrue("1 == remove(a) ", e.isConstant()); if (!b.isConstant()) { e = ms2.removeFactors(b); //System.out.println("e = " + e); assertEquals("b == remove(b) ", e, b); } } d = a.multiply(b); MultiplicativeSet ms3 = ms2.add(d); //System.out.println("ms3 = " + ms3); if (!d.isConstant()) { assertFalse("not isEmpty ", ms3.isEmpty()); e = ms3.removeFactors(a); //System.out.println("e = " + e); assertTrue("1 == remove(a) ", e.isConstant()); e = ms3.removeFactors(b); //System.out.println("e = " + e); assertTrue("1 == remove(b) ", e.isConstant()); e = ms3.removeFactors(d); //System.out.println("e = " + e); assertTrue("1 == remove(a*b) ", e.isConstant()); if (!c.isConstant()) { e = ms3.removeFactors(c); //System.out.println("e = " + e); assertEquals("c == remove(c) ", e, c); } } } /** * Test irreducible multiplicative set contained. * */ public void testFactorsContaines() { a = fac.random(kl - 2, ll - 2, el, q); b = fac.random(kl - 2, ll - 2, el, q); c = fac.random(kl - 2, ll - 2, el, q).monic(); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } MultiplicativeSet ms = new MultiplicativeSetFactors(fac); //System.out.println("ms = " + ms); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("isEmpty ", ms.isEmpty()); if (!a.isConstant()) { assertFalse("not contained ", ms.contains(a)); } MultiplicativeSet ms2 = ms.add(a); //System.out.println("ms2 = " + ms2); if (!a.isConstant()) { assertFalse("not isEmpty ", ms2.isEmpty()); assertTrue("contained ", ms2.contains(a)); if (!a.equals(b) && !b.isConstant()) { assertFalse("not contained " + ms2 + ", " + b, ms2.contains(b)); } } MultiplicativeSet ms3 = ms2.add(b); //System.out.println("ms3 = " + ms3); assertTrue("contained ", ms3.contains(a)); assertTrue("contained ", ms3.contains(b)); if (!b.isConstant()) { assertFalse("not isEmpty ", ms3.isEmpty()); if (!a.monic().equals(c) && !b.monic().equals(c) && !c.isConstant() && !ms3.mset.contains(c)) { assertFalse("not contained " + ms3 + ", " + c, ms3.contains(c)); } } e = a.multiply(b); //System.out.println("e = " + e); if (!e.isConstant()) { assertTrue("contained ", ms3.contains(e)); } MultiplicativeSet ms4 = ms3.add(e); //System.out.println("ms4 = " + ms4); assertTrue("m3 == m4 ", ms3.equals(ms4)); } /** * Test irreducible multiplicative set removeFactors. * */ public void testFactorsRemoveFactors() { a = fac.random(kl - 2, ll - 2, el, q); b = fac.random(kl - 2, ll - 2, el, q); c = fac.random(kl - 2, ll - 2, el, q); d = fac.random(kl - 2, ll - 2, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } MultiplicativeSet ms = new MultiplicativeSetFactors(fac); //System.out.println("ms = " + ms); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("isEmpty ", ms.isEmpty()); e = ms.removeFactors(a); //System.out.println("e = " + e); assertEquals("a == remove(a) ", a, e); MultiplicativeSet ms2 = ms.add(a); //System.out.println("ms2 = " + ms2); if (!a.isConstant()) { assertFalse("not isEmpty ", ms2.isEmpty()); assertTrue("contained ", ms2.contains(a)); e = ms2.removeFactors(a); //System.out.println("e = " + e); assertTrue("1 == remove(a) ", e.isConstant()); if (!b.isConstant()) { e = ms2.removeFactors(b); //System.out.println("e = " + e); assertTrue("remove(b) | b ", b.remainder(e).isZERO()); } } d = a.multiply(b); MultiplicativeSet ms3 = ms2.add(d); //System.out.println("ms3 = " + ms3); if (!d.isConstant()) { assertFalse("not isEmpty ", ms3.isEmpty()); e = ms3.removeFactors(a); //System.out.println("e = " + e); assertTrue("1 == remove(a) ", e.isConstant()); e = ms3.removeFactors(b); //System.out.println("e = " + e); assertTrue("1 == remove(b) ", e.isConstant()); e = ms3.removeFactors(d); //System.out.println("e = " + e); assertTrue("1 == remove(a*b) ", e.isConstant()); if (!c.isConstant()) { e = ms3.removeFactors(c); //System.out.println("e = " + e); assertTrue("remove(c) | c ", c.remainder(e).isZERO()); } } } } jas-2.5/trc/edu/jas/gbufd/PolyGBUtilTest.java0000644000175000017500000003205112004571452021252 0ustar giovannigiovanni/* * $Id: PolyGBUtilTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.gbufd; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.PrimeList; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.ufd.GCDProxy; import edu.jas.ufd.GreatestCommonDivisorAbstract; import edu.jas.ufd.GreatestCommonDivisorModEval; import edu.jas.ufd.GreatestCommonDivisorModular; import edu.jas.ufd.GreatestCommonDivisorSimple; import edu.jas.ufd.GreatestCommonDivisorSubres; /** * PolyGBUtil tests with JUnit. * @author Heinz Kredel. */ public class PolyGBUtilTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a PolyUtilTest object. * @param name String. */ public PolyGBUtilTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(PolyGBUtilTest.class); return suite; } //TermOrder to = new TermOrder(TermOrder.INVLEX); TermOrder to = new TermOrder(TermOrder.IGRLEX); int rl = 3; int kl = 3; int ll = 4; int el = 3; float q = 0.29f; @Override protected void setUp() { } @Override protected void tearDown() { } /** * Test resultant modular. */ public void testResultantModular() { GenPolynomialRing dfac; ModIntegerRing mi; PrimeList primes = new PrimeList(); mi = new ModIntegerRing(primes.get(1)); // 17, 19, 23, 41, 163, dfac = new GenPolynomialRing(mi, rl, to); //System.out.println("dfac = " + dfac); GreatestCommonDivisorAbstract ufds = new GreatestCommonDivisorSimple(); GreatestCommonDivisorAbstract sres = new GreatestCommonDivisorSubres(); GreatestCommonDivisorAbstract ufdm = new GreatestCommonDivisorModEval(); GenPolynomial a, b, c, d, e; for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll + 2, el, q); //a = dfac.parse("6 x0^4 - 17"); //b = dfac.parse("6 x1^2 - 7 x0^2 - 5 x1 - 14"); //a = dfac.parse("5 x1^4 * x2^4 + 2 x1^2 + x0^2"); //b = dfac.parse("5 x0^2 * x1^2 + 2 x2^2 + 5 x2 + 15"); //a = dfac.parse("x0^3 * x2^2 + 6 x0^4 + 6 x0 + 7"); //b = dfac.parse("7 x0^2 * x2^2 + 3 x2^2 + 4 x1^2 * x2 + 4 x2 + 4 x1^2 + x1 + 7"); //System.out.println("a = " + a); //System.out.println("b = " + b); c = ufds.resultant(a, b); d = sres.resultant(a, b); e = ufdm.resultant(a, b); boolean t1 = PolyGBUtil. isResultant(a, b, c); //System.out.println("t1 = " + t1); boolean t2 = PolyGBUtil. isResultant(a, b, d); //System.out.println("t2 = " + t2); boolean t3 = PolyGBUtil. isResultant(a, b, e); //System.out.println("t3 = " + t3); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); assertTrue("isResultant(a,b,c): " + c, t1); assertTrue("isResultant(a,b,d): " + d, t2); assertTrue("isResultant(a,b,e): " + e, t3); } } /** * Test resultant integer. */ public void testResultantInteger() { GenPolynomialRing dfac; dfac = new GenPolynomialRing(new BigInteger(1), rl, to); //System.out.println("dfac = " + dfac); GreatestCommonDivisorAbstract ufds = new GreatestCommonDivisorSimple(); GreatestCommonDivisorAbstract sres = new GreatestCommonDivisorSubres(); GreatestCommonDivisorAbstract ufdm = new GreatestCommonDivisorModular(); //true); GenPolynomial a, b, c, d, e; for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll + 2, el, q); //a = dfac.parse("6 x0^4 - 17"); //b = dfac.parse("6 x1^2 - 7 x0^2 - 5 x1 - 14"); //System.out.println("a = " + a); //System.out.println("b = " + b); c = ufds.resultant(a, b); d = sres.resultant(a, b); e = ufdm.resultant(a, b); boolean t1 = PolyGBUtil. isResultant(a, b, c); //System.out.println("t1 = " + t1); boolean t2 = PolyGBUtil. isResultant(a, b, d); //System.out.println("t2 = " + t2); boolean t3 = PolyGBUtil. isResultant(a, b, e); //System.out.println("t3 = " + t3); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); assertTrue("isResultant(a,b,d): " + d, t2); assertTrue("isResultant(a,b,e): " + e, t3); assertTrue("isResultant(a,b,c): " + c, t1); } } /** * Test resultant modular parallel proxy. */ public void testResultantModularParallel() { GenPolynomialRing dfac; ModIntegerRing mi; PrimeList primes = new PrimeList(); mi = new ModIntegerRing(primes.get(1)); // 17, 19, 23, 41, 163, dfac = new GenPolynomialRing(mi, rl, to); //System.out.println("dfac = " + dfac); GreatestCommonDivisorAbstract ufds = new GreatestCommonDivisorSimple(); GreatestCommonDivisorAbstract sres = new GreatestCommonDivisorSubres(); GreatestCommonDivisorAbstract ufdm = new GreatestCommonDivisorModEval(); GreatestCommonDivisorAbstract pufds = new GCDProxy(sres, ufds); GreatestCommonDivisorAbstract pufdm = new GCDProxy(ufdm, sres); GenPolynomial a, b, c, d; for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll + 2, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = pufds.resultant(a, b); d = pufdm.resultant(a, b); boolean t1 = PolyGBUtil. isResultant(a, b, c); //System.out.println("t1 = " + t1); boolean t2 = PolyGBUtil. isResultant(a, b, d); //System.out.println("t2 = " + t2); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isResultant(a,b,c): " + c, t1); assertTrue("isResultant(a,b,d): " + d, t2); } } /** * Test resultant integer parallel proxy. */ public void testResultantIntegerProxy() { GenPolynomialRing dfac; dfac = new GenPolynomialRing(new BigInteger(1), rl, to); //System.out.println("dfac = " + dfac); GreatestCommonDivisorAbstract ufds = new GreatestCommonDivisorSimple(); GreatestCommonDivisorAbstract sres = new GreatestCommonDivisorSubres(); GreatestCommonDivisorAbstract ufdm = new GreatestCommonDivisorModular(); //true); GreatestCommonDivisorAbstract pufds = new GCDProxy(sres, ufds); GreatestCommonDivisorAbstract pufdm = new GCDProxy(ufdm, sres); GenPolynomial a, b, c, d; for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll + 1, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = pufds.resultant(a, b); d = pufdm.resultant(a, b); boolean t1 = PolyGBUtil. isResultant(a, b, c); //System.out.println("t1 = " + t1); boolean t2 = PolyGBUtil. isResultant(a, b, d); //System.out.println("t2 = " + t2); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isResultant(a,b,d): " + d, t2); assertTrue("isResultant(a,b,c): " + c, t1); } } /** * Test coefficient base pseudo remainder. */ public void testCoefficientBasePseudoRemainder() { GenPolynomialRing dfac; BigRational br = new BigRational(); to = new TermOrder(TermOrder.INVLEX); //String[] vars = new String[] { "x1", "x2", "x3" }; String[] vars = new String[] { "x1", "x2" }; dfac = new GenPolynomialRing(br, to, vars); //System.out.println("dfac = " + dfac); GenPolynomialRing> rfac = dfac.recursive(1); //System.out.println("rfac = " + rfac); GenPolynomialRing cfac = (GenPolynomialRing) rfac.coFac; //System.out.println("cfac = " + cfac); GenPolynomial> ar, cr, dr, er; GenPolynomial b; ar = rfac.random(kl, ll, el, q * 1.1f); b = cfac.random(kl, ll + 2, el * 2, q); //System.out.println("ar = " + ar); //System.out.println("b = " + b); cr = PolyGBUtil. coefficientPseudoRemainderBase(ar, b); //System.out.println("cr = " + cr); assertTrue("deg(c) < deg(a): ", cr.degree(0) <= ar.degree(0) || ar.degree(0) == 0); assertTrue("deg(lfcd(c)) < deg(b): ", cr.leadingBaseCoefficient().degree(0) < b.degree(0) || b.degree(0) == 0); dr = ar.multiply(b); //System.out.println("dr = " + dr); cr = PolyGBUtil. coefficientPseudoRemainderBase(dr, b); //System.out.println("cr = " + cr); assertTrue("c == 0: ", cr.isZERO()); long s = ar.degree(0); er = rfac.univariate(0, s + 1); //System.out.println("er = " + er); er = er.multiply(b.multiply(b)); er = er.sum(ar); //System.out.println("er = " + er); cr = PolyGBUtil. coefficientPseudoRemainderBase(er, b); //System.out.println("cr = " + cr); assertTrue("deg(c) < deg(a): ", cr.degree(0) < er.degree(0)); } /** * Test coefficient recursive pseudo remainder. */ public void testCoefficientRecursivePseudoRemainder() { GenPolynomialRing dfac; BigRational br = new BigRational(); to = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x1", "x2", "x3" }; //String[] vars = new String[] { "x1", "x2" }; dfac = new GenPolynomialRing(br, to, vars); //System.out.println("dfac = " + dfac); GenPolynomialRing> r1fac = dfac.recursive(2); //System.out.println("r1fac = " + r1fac); GenPolynomialRing>> rfac = r1fac.recursive(1); //System.out.println("rfac = " + rfac); GenPolynomialRing> cfac = (GenPolynomialRing>) rfac.coFac; //System.out.println("cfac = " + cfac); GenPolynomial>> ar, cr, dr, er; GenPolynomial> b; ar = rfac.random(kl, ll, el, q); b = cfac.random(kl, ll + 2, el, q); //System.out.println("ar = " + ar); //System.out.println("b = " + b); cr = PolyGBUtil. coefficientPseudoRemainder(ar, b); //System.out.println("cr = " + cr); assertTrue("deg(c) < deg(a): ", cr.degree(0) <= ar.degree(0) || ar.degree(0) == 0); assertTrue("deg(lfcd(c)) < deg(b): ", cr.leadingBaseCoefficient().degree(0) < b.degree(0) || b.degree(0) == 0); dr = ar.multiply(b); //System.out.println("dr = " + dr); cr = PolyGBUtil. coefficientPseudoRemainder(dr, b); //System.out.println("cr = " + cr); assertTrue("c == 0: ", cr.isZERO()); long s = ar.degree(0); er = rfac.univariate(0, s + 1); ////System.out.println("er = " + er); er = er.multiply(b.multiply(cfac.fromInteger(100))); er = er.sum(ar); //System.out.println("er = " + er); cr = PolyGBUtil. coefficientPseudoRemainder(er, b); //System.out.println("cr = " + cr); assertTrue("deg(c) < deg(a): ", cr.degree(0) < er.degree(0)); } } jas-2.5/trc/edu/jas/gbufd/GroebnerBasePartTest.java0000644000175000017500000003147611641660762022470 0ustar giovannigiovanni/* * $Id: GroebnerBasePartTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gbufd; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBase; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrderOptimization; import edu.jas.util.KsubSet; /** * Groebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class GroebnerBasePartTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBasePartTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GroebnerBasePartTest object. * @param name String. */ public GroebnerBasePartTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBasePartTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bb; GroebnerBasePartial bbp; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 10; int ll = 7; int el = 3; float q = 0.2f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bb = new GroebnerBaseSeq(); bbp = new GroebnerBasePartial(); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; ComputerThreads.terminate(); } /** * Test partial recursive Trinks7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7GBasePartRec() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ) " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); //PolynomialList Fo = TermOrderOptimization.optimizeTermOrder(F); //System.out.println("\nFo = " + Fo); PolynomialList> rtrinks = bbp.partialGBrec(F.list, new String[] { "P", "Z", "T", "W" }); assertTrue("isGB( GB(Trinks7) )", bbp.isGBrec(rtrinks.list)); //System.out.println("\nTrinksR = " + rtrinks); // not meaning-full PolynomialList trinks = bbp.partialGB(F.list, new String[] { "P", "Z", "T", "W" }); //System.out.println("\ntrinks = " + trinks); assertTrue("isGB( GB(Trinks7) )", bbp.isGB(trinks.list)); } /** * Test partial Trinks7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7GBasePart() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ) " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); //PolynomialList Fo = TermOrderOptimization.optimizeTermOrder(F); //System.out.println("\nFo = " + Fo); PolynomialList trinks = bbp.partialGB(F.list, new String[] { "B", "S", "P", "Z", "T", "W" }); //PolynomialList trinks = bbp.partialGB(F.list, new String[] { "T", "Z", "P", "W", "B", "S" }); assertTrue("isGB( GB(Trinks7) )", bbp.isGB(trinks.list)); //System.out.println("\nG = " + trinks); try { PolynomialList> tr = bbp.partialGBrec(F.list, new String[] { "B", "S", "P", "Z", "T", "W" }); fail("must throw exception"); } catch (IllegalArgumentException e) { //pass } } /** * Test partial permutation. * */ public void testPartialPermutation() { String[] vars = new String[] { "B", "S", "T", "Z", "P", "W" }; String[] pvars = new String[] { "P", "Z", "T", "W" }; String[] rvars = new String[] { "S", "B" }; List perm1 = GroebnerBasePartial.partialPermutation(vars, pvars); //System.out.println("perm1 = " + perm1); List perm2 = GroebnerBasePartial.partialPermutation(vars, pvars, null); //System.out.println("perm2 = " + perm2); assertEquals("perm1 == perm2 ", perm1, perm2); List perm3 = GroebnerBasePartial.partialPermutation(vars, pvars, rvars); //System.out.println("perm3 = " + perm3); assertFalse("perm1 != perm3 ", perm1.equals(perm3)); } /** * Test elimination partial permutation. * */ public void xtestElimPartialPermutation() { String[] vars = new String[] { "B", "S", "T", "Z", "P", "W" }; String[] evars = new String[] { "P", "Z" }; String[] pvars = new String[] { "T", "W" }; String[] rvars = new String[] { "B", "S" }; List perm1 = GroebnerBasePartial.partialPermutation(vars, evars, pvars, rvars); System.out.println("perm1 = " + perm1); List perm2 = GroebnerBasePartial.partialPermutation(vars, evars, pvars, null); System.out.println("perm2 = " + perm2); assertEquals("perm1 == perm2 ", perm1, perm2); rvars = new String[] { "S", "B" }; List perm3 = GroebnerBasePartial.partialPermutation(vars, evars, pvars, rvars); System.out.println("perm3 = " + perm3); assertFalse("perm1 != perm3 ", perm1.equals(perm3)); } /** * Test elim partial Trinks7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7GBaseElimPart() { String exam = "(B,S,T,Z,P,W) G " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ) " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); String[] evars = new String[] { "P", "Z" }; String[] pvars = new String[] { "B", "S", "T", "W" }; //System.out.println("evars = " + Arrays.toString(evars)); //System.out.println("pvars = " + Arrays.toString(pvars)); PolynomialList trinks = bbp.elimPartialGB(F.list, evars, pvars); assertTrue("isGB( GB(Trinks7) )", bbp.isGB(trinks.list)); //System.out.println("\nG = " + trinks); } /** * Test partial GBase. * */ @SuppressWarnings("unchecked") public void testGBasePart() { String exam = "(a,b,c,d,e,f) G " + "( " + "( a ), " + "( b^2 ), " + "( c^3 ), " + "( d^4 ), " + "( e^5 ), " + "( f^6 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); // String[] evars = new String[] { "c", "d", "e", "f", "a", "b"}; String[] evars = new String[] { "a", "b" }; //System.out.println("evars = " + Arrays.toString(evars)); PolynomialList G = bbp.partialGB(F.list, evars); assertTrue("isGB( GB(G) )", bbp.isGB(G.list)); //System.out.println("evars = " + Arrays.toString(evars)); //System.out.println("G = " + G); } /** * Test permutation generation. * */ @SuppressWarnings("unchecked") public void testPermGen() { String[] vars = new String[] { "a", "b", "c", "d", "e", "f" }; //System.out.println("vars = " + Arrays.toString(vars)); List sv = new ArrayList(vars.length); for (int i = 0; i < vars.length; i++) { sv.add(vars[i]); } //System.out.println("sv = " + sv); String exam = "(a,b,c,d,e,f) G " + "( " + "( a ), " + "( b^2 ), " + "( c^3 ), " + "( d^4 ), " + "( e^5 ), " + "( f^6 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); PolynomialList F = null; try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); for (int i = 0; i <= vars.length; i++) { KsubSet ps = new KsubSet(sv, i); //System.out.println("========================== ps : " + i); for (List ev : ps) { //System.out.println("ev = " + ev); String[] evars = new String[ev.size()]; for (int j = 0; j < ev.size(); j++) { evars[j] = ev.get(j); } //System.out.println("evars = " + Arrays.toString(evars)); String[] rvars = GroebnerBasePartial.remainingVars(vars, evars); //System.out.println("rvars = " + Arrays.toString(rvars)); List perm1 = GroebnerBasePartial.partialPermutation(vars, evars); //System.out.println("perm1 = " + perm1); List perm2 = GroebnerBasePartial.getPermutation(vars, rvars); //System.out.println("perm2 = " + perm2); assertEquals("perm1 == perm2 " + Arrays.toString(evars), perm1, perm2); GenPolynomialRing r = new GenPolynomialRing(fac.coFac, vars); GenPolynomialRing pr1 = TermOrderOptimization . permutation(perm1, r); //System.out.println("pr1 = " + pr1); GenPolynomialRing pr2 = TermOrderOptimization . permutation(perm2, r); //System.out.println("pr2 = " + pr2); assertEquals("pr1 == pr2 ", pr1, pr2); List> pF1 = TermOrderOptimization. permutation(perm1, pr1, F.list); //System.out.println("pF1 = " + pF1); List> pF2 = TermOrderOptimization. permutation(perm2, pr2, F.list); //System.out.println("pF2 = " + pF2); assertEquals("pF1 == pF2 ", pF1, pF2); } } } } jas-2.5/trc/edu/jas/gbufd/GBFactoryTest.java0000644000175000017500000002164212002766222021103 0ustar giovannigiovanni/* * $Id: GBFactoryTest.java 4015 2012-07-22 12:05:38Z kredel $ */ package edu.jas.gbufd; //import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigComplex; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.gb.GBProxy; import edu.jas.gb.GroebnerBase; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.structure.RingFactory; /** * GreatestCommonDivisor factory tests with JUnit. * @author Heinz Kredel. */ public class GBFactoryTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GBFactoryTest object. * @param name String. */ public GBFactoryTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GBFactoryTest.class); return suite; } //private final static int bitlen = 100; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 5; int kl = 4; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; dfac = new GenPolynomialRing(new BigInteger(1), rl, to); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; dfac = null; cfac = null; rfac = null; } /** * Test get BigInteger implementation. * */ public void testBigInteger() { BigInteger bi = new BigInteger(); GroebnerBase bba; bba = GBFactory.getImplementation(bi); //System.out.println("bba = " + bba); assertTrue("bba integer " + bba, bba instanceof GroebnerBasePseudoSeq); } /** * Test get ModInteger implementation. * */ public void testModInteger() { ModIntegerRing mi = new ModIntegerRing(19, true); GroebnerBase bba; bba = GBFactory.getImplementation(mi); //System.out.println("bba = " + bba); assertTrue("bba modular field " + bba, bba instanceof GroebnerBaseSeq); mi = new ModIntegerRing(30); bba = GBFactory.getImplementation(mi); //System.out.println("bba = " + bba); assertTrue("bba modular ring " + bba, bba instanceof GroebnerBasePseudoSeq); } /** * Test get BigRational implementation. * */ public void testBigRational() { BigRational b = new BigRational(); GroebnerBase bba; bba = GBFactory.getImplementation(b); //System.out.println("bba = " + bba); assertTrue("bba field " + bba, bba instanceof GroebnerBaseSeq); } /** * Test get BigComplex implementation. * */ public void testBigComplex() { BigComplex b = new BigComplex(); GroebnerBase bba; bba = GBFactory. getImplementation(b); //System.out.println("bba = " + bba); assertTrue("bba field " + bba, bba instanceof GroebnerBaseSeq); } /** * Test get AlgebraicNumber<BigRational> implementation. * */ public void testAlgebraicNumberBigRational() { BigRational b = new BigRational(); GenPolynomialRing fac; fac = new GenPolynomialRing(b, 1); GenPolynomial mo = fac.random(kl, ll, el, q); while (mo.isZERO() || mo.isONE() || mo.isConstant()) { mo = fac.random(kl, ll, el, q); } AlgebraicNumberRing afac; afac = new AlgebraicNumberRing(mo); GroebnerBase> bba; bba = GBFactory.> getImplementation(afac); //System.out.println("bba1 = " + bba); assertTrue("bba algebraic ring " + bba, bba instanceof GroebnerBasePseudoSeq); mo = fac.univariate(0).subtract(fac.getONE()); afac = new AlgebraicNumberRing(mo, true); bba = GBFactory.> getImplementation(afac); //System.out.println("bba1 = " + bba); assertTrue("bba algebraic field " + bba, bba instanceof GroebnerBaseSeq); } /** * Test get AlgebraicNumber<ModInteger> implementation. * */ public void testAlgebraicNumberModInteger() { ModIntegerRing b = new ModIntegerRing(19, true); GenPolynomialRing fac; fac = new GenPolynomialRing(b, 1); GenPolynomial mo = fac.random(kl, ll, el, q); while (mo.isZERO() || mo.isONE() || mo.isConstant()) { mo = fac.random(kl, ll, el, q); } AlgebraicNumberRing afac; afac = new AlgebraicNumberRing(mo); AlgebraicNumber a = afac.getONE(); assertTrue("a == 1 " + a, a.isONE()); GroebnerBase> bba; bba = GBFactory.> getImplementation(afac); //System.out.println("bba2 = " + bba); assertTrue("bba algebraic ring " + bba, bba instanceof GroebnerBasePseudoSeq); } /** * Test get GenPolynomial implementation. * */ public void testGenPolynomial() { BigRational b = new BigRational(); GenPolynomialRing fac; fac = new GenPolynomialRing(b, rl, to); RingFactory> rf = fac; GroebnerBase> bba; bba = GBFactory.getImplementation(fac); //System.out.println("bba = " + bba); assertTrue("bba recursive polynomial " + bba, bba instanceof GroebnerBasePseudoRecSeq); GroebnerBase bb; bb = GBFactory.getImplementation((RingFactory)rf); //System.out.println("bb = " + bb); assertTrue("bba recursive polynomial " + bb, bb instanceof GroebnerBasePseudoRecSeq); } /** * Test get Product implementation. * */ public void testProduct() { ModIntegerRing mi = new ModIntegerRing(19, true); ProductRing fac; fac = new ProductRing(mi, 3); RingFactory> rf = fac; GroebnerBase> bba; bba = GBFactory.getImplementation(fac); //System.out.println("bba = " + bba); assertTrue("bba product " + bba, bba instanceof RGroebnerBaseSeq); mi = new ModIntegerRing(30); fac = new ProductRing(mi, 3); rf = fac; GroebnerBase> bb; bb = GBFactory.>getImplementation((RingFactory)rf); //System.out.println("bb = " + bb); assertTrue("bba product " + bb, bb instanceof RGroebnerBasePseudoSeq); } /** * Test get proxy implementation. * */ public void testProxy() { BigRational b = new BigRational(); GroebnerBaseAbstract bba; bba = GBFactory.getProxy(b); //System.out.println("bba = " + bba); assertTrue("bba field " + bba, bba instanceof GBProxy); bba.terminate(); ModIntegerRing m = new ModIntegerRing(2*3); GroebnerBaseAbstract bbm; bbm = GBFactory.getProxy(m); //System.out.println("bba = " + bba); assertTrue("bbm ! field " + bbm, ! (bbm instanceof GBProxy) ); bbm.terminate(); } } jas-2.5/trc/edu/jas/gbufd/GroebnerBasePseudoParTest.java0000644000175000017500000001215712045500020023432 0ustar giovannigiovanni/* * $Id: GroebnerBasePseudoParTest.java 4290 2012-11-04 14:47:45Z kredel $ */ package edu.jas.gbufd; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base pseudo reduction parallel tests with JUnit. * @author Heinz Kredel. */ public class GroebnerBasePseudoParTest extends TestCase { /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GroebnerBasePseudoParTest object. * @param name String. */ public GroebnerBasePseudoParTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBasePseudoParTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBaseAbstract bb; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 10; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads = 2; @Override protected void setUp() { BigInteger coeff = new BigInteger(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bb = new GroebnerBasePseudoParallel(threads, coeff); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bb.terminate(); bb = null; } /** * Test parallel GBase. * */ public void testParallelGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); //if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { // return; //} L.add(a); L = bb.GB(L); assertTrue("isGB( { a } )", bb.isGB(L)); L.add(b); //System.out.println("L = " + L.size() ); L = bb.GB(L); assertTrue("isGB( { a, b } )", bb.isGB(L)); L.add(c); L = bb.GB(L); assertTrue("isGB( { a, b, c } )", bb.isGB(L)); L.add(d); L = bb.GB(L); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L)); L.add(e); L = bb.GB(L); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L)); } /** * Test Trinks6/7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7GBase() { String exam = "Z(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " //+ "( 10000 B**2 + 6600 B + 2673 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); long s, t; t = System.currentTimeMillis(); G = bb.GB(F.list); t = System.currentTimeMillis() - t; assertTrue("isGB( GB(Trinks7) )", bb.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); PolynomialList Gpl = new PolynomialList(F.ring, G); //System.out.println("G = " + Gpl); assertTrue("nonsense ", t >= 0L); GenPolynomialRing ifac = F.ring; List> Gi; GroebnerBasePseudoSeq bbr = new GroebnerBasePseudoSeq(ifac.coFac); s = System.currentTimeMillis(); Gi = bbr.GB(F.list); s = System.currentTimeMillis() - s; PolynomialList Gipl = new PolynomialList(F.ring, Gi); //System.out.println("G = " + Gpl); //System.out.println("Gi = " + Gipl); assertEquals("seqGB == parGB", Gpl, Gipl); //System.out.println("time: seqGB = " + s + ", parGB = " + t); assertTrue("nonsense ", s >= 0L); } } jas-2.5/trc/edu/jas/gbufd/RGroebnerBasePseudoSeqTest.java0000644000175000017500000001606012004571452023573 0ustar giovannigiovanni/* * $Id: RGroebnerBasePseudoSeqTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.gbufd; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.gb.GroebnerBase; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolyUtil; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingFactory; /** * R-Groebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class RGroebnerBasePseudoSeqTest extends TestCase { // private static final Logger logger = // Logger.getLogger(RGroebnerBasePseudoSeqTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); // ComputerThreads.terminate(); } /** * Constructs a RGroebnerBasePseudoSeqTest object. * @param name String. */ public RGroebnerBasePseudoSeqTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(RGroebnerBasePseudoSeqTest.class); return suite; } ProductRing pfac; GenPolynomialRing> fac; List>> L; PolynomialList> F; List>> G; GroebnerBase> bb; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; GenPolynomial> d; GenPolynomial> e; int pl = 3; int rl = 3; // 4; //3; int kl = 7; // 10; int ll = 7; int el = 3; float q = 0.3f; // 0.4f @Override protected void setUp() { BigInteger coeff = new BigInteger(9); pfac = new ProductRing(coeff, pl); fac = new GenPolynomialRing>(pfac, rl); a = b = c = d = e = null; bb = new RGroebnerBasePseudoSeq>(pfac); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; } /** * Test sequential GBase. * */ public void testSequentialGBase() { L = new ArrayList>>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; // fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() /* || c.isZERO() || d.isZERO() */) { return; } assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); // System.out.println("L = " + L ); L = bb.GB(L); // System.out.println("L = " + L ); assertTrue("isGB( { a } )", bb.isGB(L)); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); // System.out.println("L = " + L ); L = bb.GB(L); // System.out.println("L = " + L ); assertTrue("isGB( { a, b } )", bb.isGB(L)); // assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); // System.out.println("L = " + L ); L = bb.GB(L); // System.out.println("L = " + L ); assertTrue("isGB( { a, b, c } )", bb.isGB(L)); // assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); // System.out.println("L = " + L ); L = bb.GB(L); // System.out.println("L = " + L ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L)); // assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); // System.out.println("L = " + L ); L = bb.GB(L); // System.out.println("L = " + L ); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L)); } /** * Test Trinks7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7() { String exam = "Z(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( 10000 B**2 + 6600 B + 2673 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); PolynomialList F = null; try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } // System.out.println("F = " + F); PolynomialList> trinks; List> colist; colist = new ArrayList>(); // colist.add( new BigInteger() ); // colist.add( new BigInteger() ); // colist.add( new BigInteger() ); // colist.add( new BigInteger() ); colist.add(new BigInteger()); colist.add(new BigInteger()); // colist.add( new BigInteger() ); // System.out.println("colist = " + colist); ProductRing pfac; pfac = new ProductRing(colist); // System.out.println("pfac = " + pfac); GenPolynomialRing> fac; fac = new GenPolynomialRing>(pfac, F.ring); // System.out.println("fac = " + fac); List>> Fp = null; Fp = PolyUtil. toProductGen(fac, F.list); List>> Fpp; Fpp = new ArrayList>>(); for (GenPolynomial> a : Fp) { Fpp.add(a.multiply(pfac.getAtomic(0))); Fpp.add(a.multiply(pfac.getAtomic(1))); // Fpp.add( a ); } Fp = Fpp; //trinks = new PolynomialList>(fac, Fp); // System.out.println("Fp = " + trinks); GroebnerBase> bbri = new RGroebnerBasePseudoSeq>(pfac); List>> G; G = bbri.GB(Fp); // System.out.println("gb = " + G ); // assertEquals("#GB(Trinks7) == 6", 6, G.size() ); // System.out.println("Fp = " + trinks); trinks = new PolynomialList>(fac, G); // System.out.println("G = " + trinks); assertFalse("trinks != null", trinks == null); assertTrue("isGB( GB(Trinks7) )", bbri.isGB(G)); } } jas-2.5/trc/edu/jas/ps/0000755000175000017500000000000012140140260015075 5ustar giovannigiovannijas-2.5/trc/edu/jas/ps/MultiVarPowerSeriesTest.java0000644000175000017500000004752412014234362022556 0ustar giovannigiovanni/* * $Id: MultiVarPowerSeriesTest.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.ps; import java.util.ArrayList; import java.util.List; import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; /** * Multivariate power series tests with JUnit. * @author Heinz Kredel. */ public class MultiVarPowerSeriesTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a MultiVarPowerSeriesTest object. * @param name String. */ public MultiVarPowerSeriesTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(MultiVarPowerSeriesTest.class); return suite; } MultiVarPowerSeriesRing fac; MultiVarPowerSeries a; MultiVarPowerSeries b; MultiVarPowerSeries c; MultiVarPowerSeries d; MultiVarPowerSeries e; MultiVarPowerSeries f; int rl = 2; int kl = 10; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; String[] vars = new String[] { "x", "y" }; fac = new MultiVarPowerSeriesRing(new BigRational(1), rl, vars); //System.out.println("fac = " + fac); //System.out.println("fac = " + fac.toScript()); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test MultiVarCoefficients. * */ public void testCoefficients() { BigRational cf = new BigRational(0); GenPolynomialRing pring = new GenPolynomialRing(cf, rl); MultiVarCoefficients zeros = new Zeros(pring); MultiVarCoefficients ones = new Ones(pring); MultiVarCoefficients vars = new Vars(pring); int m = 5; ExpVectorIterable eiter = new ExpVectorIterable(rl, true, m); for (ExpVector e : eiter) { BigRational c = zeros.get(e); //System.out.println("c = " + c + ", e = " + e); assertTrue("isZERO( c )", c.isZERO()); } //System.out.println("coeffCache = " + zeros.coeffCache); //System.out.println("zeroCache = " + zeros.zeroCache); assertTrue("coeffCache is one element", zeros.coeffCache.size() == (m + 1)); for (ExpVector e : eiter) { BigRational c = ones.get(e); //System.out.println("c = " + c + ", e = " + e); assertTrue("isONE( c )", c.isONE()); } //System.out.println("coeffCache = " + ones.coeffCache); //System.out.println("zeroCache = " + ones.zeroCache); assertTrue("zeroCache is empty", ones.zeroCache.isEmpty()); for (int i = 0; i <= m; i++) { GenPolynomial c = ones.getHomPart(i); //System.out.println("c = " + c + ", i = " + i); GenPolynomial d = ones.getHomPart(i); //System.out.println("d = " + d + ", i = " + i); assertTrue("c.equals(d) ", c.equals(d)); } //System.out.println("coeffCache = " + ones.coeffCache); //System.out.println("zeroCache = " + ones.zeroCache); //System.out.println("homCheck = " + ones.homCheck); //System.out.println("homCheck = " + ones.homCheck.length()); assertTrue("zeroCache is empty", ones.zeroCache.isEmpty()); assertTrue("#coeffCache = " + m, ones.coeffCache.size() == (m + 1)); assertTrue("#homCheck = " + m, ones.homCheck.length() == (m + 1)); for (int i = 0; i <= m; i++) { GenPolynomial c = vars.getHomPart(i); //System.out.println("c = " + c + ", i = " + i); assertTrue("c==0 || deg(c)==1 ", c.isZERO() || c.degree() == 1L); } //System.out.println("coeffCache = " + vars.coeffCache); //System.out.println("zeroCache = " + vars.zeroCache); //System.out.println("homCheck = " + vars.homCheck); //System.out.println("homCheck = " + vars.homCheck.length()); //no-more: assertTrue("zeroCache is not empty", !vars.zeroCache.isEmpty()); assertTrue("#coeffCache = " + m, vars.coeffCache.size() == (m + 1)); assertTrue("#homCheck = " + m, vars.homCheck.length() == (m + 1)); } /** * Test constructor and generators. * */ public void testConstruction() { //System.out.println("fac = " + fac); //System.out.println("fac = " + fac.toScript()); c = fac.getONE(); //System.out.println("c = " + c); assertTrue("isZERO( c )", !c.isZERO()); assertTrue("isONE( c )", c.isONE()); d = fac.getZERO(); //System.out.println("d = " + d); assertTrue("isZERO( d )", d.isZERO()); assertTrue("isONE( d )", !d.isONE()); List> gens = fac.generators(); assertTrue("#gens == rl+1 ", rl + 1 == gens.size()); for (MultiVarPowerSeries p : gens) { //System.out.println("p = " + p); assertTrue("red(p) == 0 ", p.reductum().isZERO()); } a = fac.copy(c); b = c.copy(); assertEquals("copy(c) == c.clone() ", a, b); a = fac.fromInteger(1); assertEquals("1 == fromInteger(1) ", a, c); b = fac.fromInteger(java.math.BigInteger.ONE); assertEquals("1 == fromInteger(1) ", b, c); } /** * Test random polynomial. */ public void testRandom() { for (int i = 0; i < 5; i++) { a = fac.random(i + 2); //System.out.println("a = " + a); assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); assertTrue(" not isONE( a" + i + " )", !a.isONE()); } } /** * Test MultiVarCoefficients in power series. * */ public void testCoefficientsInPS() { MultiVarCoefficients zeros = new Zeros(fac); MultiVarCoefficients ones = new Ones(fac); MultiVarCoefficients vars = new Vars(fac); a = new MultiVarPowerSeries(fac, zeros); b = new MultiVarPowerSeries(fac, ones); c = new MultiVarPowerSeries(fac, vars); int m = 5; ExpVectorIterable eiter = new ExpVectorIterable(rl, true, m); for (ExpVector e : eiter) { BigRational r = a.coefficient(e); //System.out.println("r = " + r + ", e = " + e); assertTrue("isZERO( r )", r.isZERO()); } //System.out.println("#a = " + a.lazyCoeffs.coeffCache); assertTrue("coeffCache is one element", a.lazyCoeffs.coeffCache.size() == (m + 1)); assertTrue("isZERO( a )", a.isZERO()); // after previous for (ExpVector e : eiter) { BigRational r = b.coefficient(e); //System.out.println("r = " + r + ", e = " + e); assertTrue("isONE( r )", r.isONE()); } assertTrue("zeroCache is empty", b.lazyCoeffs.zeroCache.isEmpty()); for (int i = 0; i <= m; i++) { GenPolynomial p = b.homogeneousPart(i); //System.out.println("p = " + p + ", i = " + i); GenPolynomial q = b.homogeneousPart(i); //System.out.println("q = " + q + ", i = " + i); assertTrue("p.equals(q) ", p.equals(q)); } assertTrue("zeroCache is empty", b.lazyCoeffs.zeroCache.isEmpty()); assertTrue("#coeffCache = " + m, b.lazyCoeffs.coeffCache.size() == (m + 1)); assertTrue("#homCheck = " + m, b.lazyCoeffs.homCheck.length() == (m + 1)); for (int i = 0; i <= m; i++) { GenPolynomial p = c.homogeneousPart(i); //System.out.println("p = " + p + ", i = " + i); assertTrue("p==0 || deg(p)==1 ", p.isZERO() || p.degree() == 1L); } //no-more:assertTrue("zeroCache is not empty", !c.lazyCoeffs.zeroCache.isEmpty()); assertTrue("#coeffCache = " + m, c.lazyCoeffs.coeffCache.size() == (m + 1)); assertTrue("#homCheck = " + m, c.lazyCoeffs.homCheck.length() == (m + 1)); } /** * Test addition. * */ public void testAddition() { a = fac.random(kl); b = fac.random(kl); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a", c, d); d = c.subtract(b); assertEquals("a+b-b = a", a, d); d = c.sum(b.negate()); assertEquals("a+b-b = a", a, d); c = fac.random(kl); d = a.sum(b.sum(c)); e = a.sum(b).sum(c); assertEquals("a+(b+c) = (a+b)+c", d, e); Map.Entry ma = a.orderMonomial(); c = a.reductum().sum(ma); assertEquals("a = red(a)+om(a)", a, c); } /** * Test multiplication. * */ public void testMultiplication() { a = fac.random(kl); b = fac.random(kl); if (a.isZERO() || b.isZERO()) { return; } assertTrue("not isZERO( a )", !a.isZERO()); assertTrue("not isZERO( b )", !b.isZERO()); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO()); assertTrue("not isZERO( d )", !d.isZERO()); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO()); assertTrue("a*b = b*a", c.equals(d)); assertEquals("a*b = b*a", c, d); c = fac.random(kl); //System.out.println("c = " + c); d = a.multiply(b.multiply(c)); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c", d, e); assertTrue("a(bc) = (ab)c", d.equals(e)); ExpVector ev = ExpVector.random(rl, 5, 0.8f); BigRational br = fac.coFac.random(5); b = a.shift(ev).multiply(br); c = a.multiply(br, ev); assertEquals("(a ev) br = a (ev,br)", b, c); //System.out.println("a = " + a); //System.out.println("ev = " + ev); //System.out.println("br = " + br); //System.out.println("b = " + b); //System.out.println("c = " + c); } /** * Test distributive law. * */ public void testDistributive() { a = fac.random(kl, q); b = fac.random(kl, q); c = fac.random(kl, q); d = a.multiply(b.sum(c)); e = a.multiply(b).sum(a.multiply(c)); assertEquals("a(b+c) = ab+ac", d, e); } /** * Test inverse. * */ public void testInverse() { a = fac.getONE(); assertTrue("not isZERO( a )", !a.isZERO()); assertTrue("isUnit( a )", a.isUnit()); //System.out.println("a = " + a); b = a.inverse(); c = a.multiply(b); assertTrue("isONE( c )", c.isONE()); //System.out.println("b = " + b); //System.out.println("c = " + c); a = fac.random(kl); if (!a.isUnit()) { a = fac.fromInteger(23); //return; } //System.out.println("a = " + a); b = a.inverse(); c = a.multiply(b); assertTrue("isONE( c )", c.isONE()); //System.out.println("b = " + b); //System.out.println("c = " + c); b = fac.random(kl); c = b.divide(a); d = c.multiply(a); assertEquals("b/a * a == b ", d, b); } /** * Test fix point constructions. * */ public void testFixpoints() { int r = 0; UnivPowerSeriesRing ufac = new UnivPowerSeriesRing(fac.coFac, fac.vars[r]); UnivPowerSeries exp = ufac.getEXP(); //System.out.println("exp = " + exp); a = fac.fromPowerSeries(exp, 0); b = fac.fromPowerSeries(exp, 1); //System.out.println("a = " + a); //System.out.println("b = " + b); c = fac.getEXP(0); d = fac.getEXP(1); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a == c ", a, c); assertEquals("b == d ", b, d); e = d.differentiate(0); //System.out.println("e = " + e); assertTrue("isZERO( e )", e.isZERO()); e = d.differentiate(1); //System.out.println("e = " + e); assertEquals("e == d ", d, e); } /** * Test reductum. * */ public void testReductum() { a = fac.random(kl); //System.out.println("a = " + a); Map.Entry m = a.orderMonomial(); //System.out.println("m = " + m); ExpVector k = m.getKey(); BigRational br = m.getValue(); b = fac.getONE().multiply(br, k); //System.out.println("b = " + b); c = a.reductum(); //System.out.println("c = " + c); d = c.sum(b); //System.out.println("d = " + d); assertEquals("a = red(a)+1*lm(a) ", a, d); e = c.sum(br, k); //System.out.println("e = " + e); assertEquals("a = red(a)+lm(a) ", a, e); e = a.subtract(br, k); //System.out.println("e = " + e); assertEquals("a - lm(a) = red(a) ", c, e); b = fac.random(kl); String s = b.toString(); // generate and cache some coefficients //System.out.println("b = " + b); assertFalse("s.size > 0 " + s, s.length() == 0); // java-5 c = a.sum(b); //System.out.println("c = " + c); d = a.sum(b.lazyCoeffs); //System.out.println("d = " + d); // while ( !c.isZERO() ) { // c = c.reductum(); // //System.out.println("c = " + c); // } // assertTrue("red^n(a) == 0 ", c.isZERO()); br = new BigRational(2, 3); c = a.prepend(br, 0); d = c.reductum(0); assertEquals("red(a + br_0,0) = a ", d, a); c = a.shift(3, 0); d = c.shift(-3, 0); assertEquals("shift(shift(a,3,),-3,0) = a ", d, a); } /** * Test polynomial constructions. * */ public void testPolynomial() { GenPolynomialRing pr = fac.polyRing(); //System.out.println("pr = " + pr); GenPolynomial p = pr.random(kl, 3, 3, q + q); //System.out.println("p = " + p); a = fac.fromPolynomial(p); //System.out.println("a = " + a); GenPolynomial s = a.asPolynomial(); //System.out.println("s = " + s); assertEquals("asPolynomial(fromPolynomial(p)) = p ", p, s); // if ( a.isUnit() ) { // b = a.inverse(); // System.out.println("b = " + b); // } } /** * Test gcd. * */ public void testGcd() { a = fac.random(kl); //System.out.println("a = " + a); b = fac.random(kl); //System.out.println("b = " + b); c = a.gcd(b); //System.out.println("c = " + c); d = a.divide(c); //System.out.println("d = " + d); e = b.divide(c); //System.out.println("e = " + e); f = d.gcd(e); //System.out.println("f = " + f); assertTrue("gcd(a/gcd(a,b),b/gcd(a,b)) == 1 ", f.isONE()); } /** * Test Taylor series. * */ public void testTaylor() { BigRational ar = new BigRational(5); BigRational br = new BigRational(0); BigRational cr = new BigRational(-5); List Ar = new ArrayList(rl); List Br = new ArrayList(rl); List Cr = new ArrayList(rl); for (int i = 0; i < rl; i++) { Ar.add(ar); Br.add(br); Cr.add(cr); } GenPolynomialRing pr = fac.polyRing(); //System.out.println("pr = " + pr.toScript()); GenPolynomial p = pr.random(kl, 3, 3, q + q); //System.out.println("p = " + p); int tdeg = (int) p.degree(); fac.setTruncate(tdeg + 1); TaylorFunction F = new PolynomialTaylorFunction(p); MultiVarPowerSeries pps = fac.fromPolynomial(p); //System.out.println("pps = " + pps); MultiVarPowerSeries ps = fac.seriesOfTaylor(F, Br); //System.out.println("ps = " + ps); assertEquals("taylor(p) == p", ps, pps); MultiVarPowerSeries psa = fac.seriesOfTaylor(F, Ar); //System.out.println("psa = " + psa); F = new PolynomialTaylorFunction(psa.asPolynomial()); MultiVarPowerSeries psc = fac.seriesOfTaylor(F, Cr); //System.out.println("psc = " + psc); assertEquals("taylor(taylor(p,5),-5) == p", ps, psc); for (GenPolynomial g : pr.generators()) { F = new PolynomialTaylorFunction(g); ps = fac.seriesOfTaylor(F, Br); //System.out.println("g = " + g); //System.out.println("ps = " + ps); pps = fac.fromPolynomial(g); //System.out.println("pps = " + pps); assertEquals("taylor(p) == p", ps, pps); psa = fac.seriesOfTaylor(F, Ar); //System.out.println("psa = " + psa); F = new PolynomialTaylorFunction(psa.asPolynomial()); psc = fac.seriesOfTaylor(F, Cr); //System.out.println("psc = " + psc); assertEquals("taylor(taylor(p,5),-5) == p", ps, psc); } } /** * Test evaluation. * */ public void testEvaluation() { a = fac.random(kl, q); b = fac.random(kl, q); BigRational fv = new BigRational(0); List v = new ArrayList(rl); for ( int i = 0; i < rl; i++ ) { v.add( fv.random(kl) ); } BigRational av = a.evaluate(v); BigRational bv = b.evaluate(v); c = a.sum(b); BigRational cv = c.evaluate(v); BigRational dv = av.sum(bv); assertEquals("a(v)+b(v) = (a+b)(v) ", cv, dv); c = fac.getZERO(); cv = c.evaluate(v); dv = fv.getZERO(); assertEquals("0(v) = 0 ", cv, dv); c = fac.getONE(); cv = c.evaluate(v); dv = fv.getONE(); assertEquals("1(v) = 1 ", cv, dv); } } class Zeros extends MultiVarCoefficients { public Zeros(MultiVarPowerSeriesRing pf) { super(pf); } public Zeros(GenPolynomialRing pf) { super(pf); } @Override public BigRational generate(ExpVector i) { return pfac.coFac.getZERO(); } } class Ones extends MultiVarCoefficients { public Ones(MultiVarPowerSeriesRing pf) { super(pf); } public Ones(GenPolynomialRing pf) { super(pf); } @Override public BigRational generate(ExpVector i) { return pfac.coFac.getONE(); } } class Vars extends MultiVarCoefficients { public Vars(MultiVarPowerSeriesRing pf) { super(pf); } public Vars(GenPolynomialRing pf) { super(pf); } @Override public BigRational generate(ExpVector i) { int[] v = i.dependencyOnVariables(); if (v.length == 1 && i.getVal(v[0]) == 1L) { return pfac.coFac.getONE(); } return pfac.coFac.getZERO(); } } jas-2.5/trc/edu/jas/ps/UnivPowerSeriesTest.java0000644000175000017500000001613112004571452021725 0ustar giovannigiovanni/* * $Id: UnivPowerSeriesTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.ps; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; /** * Univariate power series tests with JUnit. * @author Heinz Kredel. */ public class UnivPowerSeriesTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a UnivPowerSeriesTest object. * @param name String. */ public UnivPowerSeriesTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(UnivPowerSeriesTest.class); return suite; } //private final static int bitlen = 100; UnivPowerSeriesRing fac; UnivPowerSeries a; UnivPowerSeries b; UnivPowerSeries c; UnivPowerSeries d; UnivPowerSeries e; int kl = 10; float q = 0.5f; @Override protected void setUp() { a = b = c = d = e = null; fac = new UnivPowerSeriesRing(new BigRational(1)); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); assertTrue("isZERO( c )", !c.isZERO()); assertTrue("isONE( c )", c.isONE()); d = fac.getZERO(); assertTrue("isZERO( d )", d.isZERO()); assertTrue("isONE( d )", !d.isONE()); } /** * Test random polynomial. */ public void testRandom() { for (int i = 0; i < 5; i++) { a = fac.random(i + 2); //System.out.println("a = " + a); assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); assertTrue(" not isONE( a" + i + " )", !a.isONE()); } } /** * Test addition. * */ public void testAddition() { a = fac.random(kl); b = fac.random(kl); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a", c, d); d = c.subtract(b); assertEquals("a+b-b = a", a, d); c = fac.random(kl); d = a.sum(b.sum(c)); e = a.sum(b).sum(c); assertEquals("a+(b+c) = (a+b)+c", d, e); } /** * Test multiplication. * */ public void testMultiplication() { a = fac.random(kl); assertTrue("not isZERO( a )", !a.isZERO()); b = fac.random(kl); assertTrue("not isZERO( b )", !b.isZERO()); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO()); assertTrue("not isZERO( d )", !d.isZERO()); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO()); assertTrue("a*b = b*a", c.equals(d)); assertEquals("a*b = b*a", c, d); c = fac.random(kl); //System.out.println("c = " + c); d = a.multiply(b.multiply(c)); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c", d, e); assertTrue("a(bc) = (ab)c", d.equals(e)); } /** * Test distributive law. * */ public void testDistributive() { a = fac.random(kl, q); b = fac.random(kl, q); c = fac.random(kl, q); d = a.multiply(b.sum(c)); e = a.multiply(b).sum(a.multiply(c)); assertEquals("a(b+c) = ab+ac", d, e); } /** * Test object quotient and remainder. * */ public void testQuotRem() { fac = new UnivPowerSeriesRing(new BigRational(1)); a = fac.random(kl); assertTrue("not isZERO( a )", !a.isZERO()); b = fac.random(kl); assertTrue("not isZERO( b )", !b.isZERO()); UnivPowerSeries g = fac.random(kl); assertTrue("not isZERO( g )", !g.isZERO()); a = a.multiply(g); b = b.multiply(g); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("g = " + g); /* UnivPowerSeries[] qr; qr = b.divideAndRemainder(a); c = qr[0]; d = qr[1]; //System.out.println("q = " + c); //System.out.println("r = " + d); e = c.multiply(a).sum(d); assertEquals("b = q a + r", b, e ); */ // gcd tests ------------------------------- c = a.gcd(b); //System.out.println("gcd = " + c); assertTrue("a mod gcd(a,b) = 0", a.remainder(c).isZERO()); assertTrue("b mod gcd(a,b) = 0", b.remainder(c).isZERO()); //assertEquals("g = gcd(a,b)", c, g ); } /** * Test evaluation. * */ public void testEvaluation() { a = fac.random(kl, q); b = fac.random(kl, q); BigRational fv = new BigRational(0); BigRational v = fv.random(kl); BigRational av = a.evaluate(v); BigRational bv = b.evaluate(v); c = a.sum(b); BigRational cv = c.evaluate(v); BigRational dv = av.sum(bv); assertEquals("a(v)+b(v) = (a+b)(v) ", cv, dv); c = fac.getZERO(); cv = c.evaluate(v); dv = fv.getZERO(); assertEquals("0(v) = 0 ", cv, dv); c = fac.getONE(); cv = c.evaluate(v); dv = fv.getONE(); assertEquals("1(v) = 1 ", cv, dv); // not true: //c = a.multiply(b); //cv = c.evaluate(v); //dv = av.multiply(bv); //assertEquals("a(v)*b(v) = (a*b)(v) ", cv, dv); } /** * Test Taylor series. * */ public void testTaylor() { BigRational br = new BigRational(0); GenPolynomialRing pr = fac.polyRing(); //System.out.println("pr = " + pr); GenPolynomial p = pr.random(kl, 3, 3, q + q); //System.out.println("p = " + p); TaylorFunction F = new PolynomialTaylorFunction(p); UnivPowerSeries ps = fac.seriesOfTaylor(F, br); //System.out.println("ps = " + ps); UnivPowerSeries pps = fac.fromPolynomial(p); //System.out.println("pps = " + pps); assertEquals("taylor(p) == p", ps, pps); for (GenPolynomial g : pr.generators()) { F = new PolynomialTaylorFunction(g); ps = fac.seriesOfTaylor(F, br); //System.out.println("g = " + g); //System.out.println("ps = " + ps); pps = fac.fromPolynomial(g); //System.out.println("pps = " + pps); assertEquals("taylor(p) == p", ps, pps); } } } jas-2.5/trc/edu/jas/ps/IteratorsTest.java0000644000175000017500000002055712004571452020577 0ustar giovannigiovanni/* * $Id: IteratorsTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.ps; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.util.CartesianProductInfinite; import edu.jas.util.CartesianProductLong; import edu.jas.util.LongIterable; /** * Iterator tests with JUnit. * @author Heinz Kredel. */ public class IteratorsTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a ListUtilTest object. * @param name String. */ public IteratorsTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(IteratorsTest.class); return suite; } @Override protected void setUp() { } @Override protected void tearDown() { } /** * Test ExpVector iterator. * */ public void testExpVector() { int n = 5; LongIterable li = new LongIterable(); li.setNonNegativeIterator(); List> tlist = new ArrayList>(n); for (int i = 0; i < n; i++) { tlist.add(li); } //System.out.println("tlist = " + tlist); Set set = new TreeSet((new TermOrder()).getDescendComparator()); Iterable> ib = new CartesianProductInfinite(tlist); long t = 0L; for (List i : ib) { //System.out.println("i = " + i); ExpVector e = ExpVector.create(i); //System.out.println("e = " + e); assertFalse("e in set", set.contains(e)); set.add(e); t++; if (t > 100L) { //System.out.println("i = " + i); break; } } //System.out.println("set = " + set); assertTrue("#set", set.size() == t); } /** * Test GenPolynomial iterator. * */ public void testGenPolynomial() { ModIntegerRing mi = new ModIntegerRing(5, true); int n = 3; GenPolynomialRing ring = new GenPolynomialRing(mi, n); Set> set = new TreeSet>(); long t = 0; for (GenPolynomial p : ring) { //System.out.println("p = " + p); if (set.contains(p)) { System.out.println("p = " + p); System.out.println("set = " + set); assertFalse("p in set ", true); } set.add(p); t++; if (t > 650L) { //System.out.println("i = " + i); break; } } //System.out.println("set = " + set); assertTrue("#set", set.size() == t); } /** * Test GenPolynomial monomial iterator. * */ public void testGenPolynomialMonomial() { BigInteger bi = new BigInteger(1); int n = 3; GenPolynomialRing ring = new GenPolynomialRing(bi, n); Set> set = new TreeSet>(); long t = 0; for (GenPolynomial p : ring) { //System.out.println("p = " + p); if (set.contains(p)) { System.out.println("p = " + p); //System.out.println("set = " + set); assertFalse("p in set ", true); } set.add(p); t++; if (t > 650L) { //System.out.println("i = " + i); break; } } //System.out.println("set = " + set); assertTrue("#set", set.size() == t); } /** * Test total degree ExpVector iterator. * */ public void testTotalDegExpVector() { int n = 4; Set set = new TreeSet((new TermOrder()).getDescendComparator()); Map> degset = new TreeMap>(); long t = 0L; for (long k = 0; k < 14; k++) { LongIterable li = new LongIterable(); li.setNonNegativeIterator(); li.setUpperBound(k); List tlist = new ArrayList(n); for (int i = 0; i < n; i++) { tlist.add(li); // can reuse li } long kdeg = k; //if ( kdeg > 5 ) { // kdeg < k ok but kdeg > k not allowed // kdeg -= 2; //} Iterable> ib = new CartesianProductLong(tlist, kdeg); //System.out.println("kdeg = " + kdeg); for (List i : ib) { //System.out.println("i = " + i); ExpVector e = ExpVector.create(i); long tdeg = e.totalDeg(); //System.out.println("e = " + e + ", deg = " + tdeg); assertTrue("tdeg == k", tdeg == kdeg); Set es = degset.get(tdeg); if (es == null) { es = new TreeSet((new TermOrder()).getDescendComparator()); degset.put(tdeg, es); } es.add(e); //assertFalse("e in set", set.contains(e) ); set.add(e); t++; if (t > 500000L) { //System.out.println("i = " + i); break; } } } //System.out.println("waste = " + w + ", of " + t); //System.out.println("set = " + set); //System.out.println("degset = " + degset); for (Set es : degset.values()) { assertFalse("es != null", es == null); //System.out.println("#es = " + es.size() + ", es = " + es); //System.out.println("#es = " + es.size() + ", deg = " + es.iterator().next().totalDeg()); } assertTrue("#set", set.size() == t); } /** * Test total degree ExpVector iterator. * */ public void testTotalDegExpVectorIteratorInf() { int n = 4; Set set = new TreeSet((new TermOrder()).getDescendComparator()); ExpVectorIterable eiter = new ExpVectorIterable(n); long t = 0; for (ExpVector e : eiter) { //System.out.println("e = " + e + ", deg = " + e.totalDeg()); t++; if (t > 500L) { //System.out.println("i = " + i); break; } assertFalse("e in set", set.contains(e)); set.add(e); } } /** * Test total degree ExpVector iterator. * */ public void testTotalDegExpVectorIteratorFin() { int n = 4; Set set = new TreeSet((new TermOrder()).getDescendComparator()); ExpVectorIterable eiter = new ExpVectorIterable(n, 5); long t = 0; for (ExpVector e : eiter) { //System.out.println("e = " + e + ", deg = " + e.totalDeg()); t++; if (t > 500L) { //System.out.println("i = " + i); break; } assertFalse("e in set", set.contains(e)); set.add(e); } } /** * Test total degree ExpVector iterator. * */ public void testTotalDegExpVectorIteratorAllFin() { int n = 4; Set set = new TreeSet((new TermOrder()).getDescendComparator()); ExpVectorIterable eiter = new ExpVectorIterable(n, true, 5); long t = 0; for (ExpVector e : eiter) { //System.out.println("e = " + e + ", deg = " + e.totalDeg()); t++; if (t > 500L) { //System.out.println("i = " + i); break; } assertFalse("e in set", set.contains(e)); set.add(e); } } } jas-2.5/trc/edu/jas/structure/0000755000175000017500000000000012140140260016513 5ustar giovannigiovannijas-2.5/trc/edu/jas/arith/0000755000175000017500000000000012140140260015562 5ustar giovannigiovannijas-2.5/trc/edu/jas/arith/ModLongTest.java0000644000175000017500000002306612014234362020642 0ustar giovannigiovanni/* * $Id: ModLongTest.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.arith; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.kern.PrettyPrint; import edu.jas.structure.NotInvertibleException; /** * ModLong tests with JUnit. * @author Heinz Kredel. */ public class ModLongTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a ModLongTest object. * @param name String */ public ModLongTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(ModLongTest.class); return suite; } ModLongRing zm; ModLongRing z1; ModLongRing z2; ModLong a; ModLong b; ModLong c; ModLong d; ModLong e; @Override protected void setUp() { zm = z1 = z2 = null; a = b = c = d = e = null; } @Override protected void tearDown() { zm = z1 = z2 = null; a = b = c = d = e = null; } protected static java.math.BigInteger getPrime1() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 30; i++) { prime *= 2; } //prime -= 93; prime -= 35; //System.out.println("p1 = " + prime); return new java.math.BigInteger("" + prime); } protected static java.math.BigInteger getPrime2() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 30; i++) { prime *= 2; } //prime -= 35; prime = 37; //System.out.println("p2 = " + prime); return new java.math.BigInteger("" + prime); } /** * Test static initialization and constants. * */ public void testConstants() { zm = new ModLongRing(5); d = new ModLong(zm, 11); a = zm.getZERO(); b = zm.getONE(); c = b.subtract(b); assertEquals("1-1 = 0", c, a); assertTrue("1-1 = 0", c.isZERO()); assertTrue("1 = 1", b.isONE()); } /** * Test constructor and toString. * */ public void testConstructor() { zm = new ModLongRing("5"); a = new ModLong(zm, "64"); b = new ModLong(zm, "34"); assertEquals("64(5) = 34(5)", a, b); zm = new ModLongRing("7"); a = new ModLong(zm, "-4"); b = new ModLong(zm, "3"); assertEquals("-4(7) = 3(7)", a, b); String s = "61111111111111111"; zm = new ModLongRing("10"); a = new ModLong(zm, s); String t = a.toString(); if (PrettyPrint.isTrue()) { String st = "1"; assertEquals("stringConstr = toString", st, t); } else { String st = "1 mod(10)"; assertEquals("stringConstr = toString", st, t); } zm = new ModLongRing(7); a = new ModLong(zm, 1); b = new ModLong(zm, -1); c = b.sum(a); assertTrue("1 = 1", a.isONE()); assertTrue("1 = 1", b.isUnit()); assertEquals("1+(-1) = 0", c, zm.getZERO()); zm = new ModLongRing(5); a = new ModLong(zm, 3); b = new ModLong(zm, 0); c = zm.parse(" 13 "); assertEquals("3(5) = 3(5)", a, c); StringReader sr = new StringReader(" 13\n w "); c = zm.parse(sr); assertEquals("3(5) = 3(5)", a, c); //System.out.println("c = " + c); } /** * Test random modular integers. * */ public void testRandom() { zm = new ModLongRing(19); a = zm.random(500); b = a.copy(); c = b.subtract(a); assertEquals("a-b = 0", c, zm.getZERO()); d = new ModLong(new ModLongRing(b.getModul()), b.getVal()); assertEquals("sign(a-a) = 0", 0, b.compareTo(d)); } /** * Test addition. * */ public void testAddition() { zm = new ModLongRing(19); a = zm.random(100); b = a.sum(a); c = b.subtract(a); assertEquals("a+a-a = a", c, a); assertEquals("a+a-a = a", 0, c.compareTo(a)); d = a.sum(zm.getZERO()); assertEquals("a+0 = a", d, a); d = a.subtract(zm.getZERO()); assertEquals("a-0 = a", d, a); d = a.subtract(a); assertEquals("a-a = 0", d, zm.getZERO()); } /** * Test multiplication. * */ public void testMultiplication() { zm = new ModLongRing(5); d = new ModLong(zm, 11); a = zm.random(100); if (a.isZERO()) { a = d; } b = a.multiply(a); c = b.divide(a); assertEquals("a*a/a = a", c, a); assertEquals("a*a/a = a", 0, c.compareTo(a)); d = a.multiply(zm.getONE()); assertEquals("a*1 = a", d, a); d = a.divide(zm.getONE()); assertEquals("a/1 = a", d, a); a = zm.random(100); if (a.isZERO()) { a = d; } b = a.inverse(); c = a.multiply(b); assertTrue("a*1/a = 1", c.isONE()); try { a = zm.getZERO().inverse(); fail("0 invertible"); } catch (NotInvertibleException expected) { //ok } zm = new ModLongRing(5*3); a = new ModLong(zm, 5); assertFalse("5 !unit mod 15", a.isUnit()); try { b = a.inverse(); fail("5 invertible"); } catch (ModularNotInvertibleException expected) { //ok //expected.printStackTrace(); assertTrue("f = 15 ", expected.f.equals(new BigInteger(15))); assertTrue("f1 = 5 ", expected.f1.equals(new BigInteger(5))); assertTrue("f2 = 3 ", expected.f2.equals(new BigInteger(3))); assertTrue("f = f1*f2 ", expected.f.equals(expected.f1.multiply(expected.f2))); } catch (NotInvertibleException e) { //e.printStackTrace(); fail("wrong exception " + e); } } /** * Test chinese remainder. * */ public void testChineseRemainder() { zm = new ModLongRing(19 * 13); a = zm.random(9); //System.out.println("a = " + a); z1 = new ModLongRing(19); b = new ModLong(z1, a.getVal()); //System.out.println("b = " + b); z2 = new ModLongRing(13); c = new ModLong(z2, a.getVal()); //System.out.println("c = " + c); d = new ModLong(z2, 19); d = d.inverse(); //System.out.println("d = " + d); e = zm.chineseRemainder(b, d, c); //System.out.println("e = " + e); assertEquals("cra(a mod 19,a mod 13) = a", a, e); java.math.BigInteger p1 = getPrime2(); java.math.BigInteger p2 = new java.math.BigInteger("19"); //getPrime1(); java.math.BigInteger p1p2 = p1.multiply(p2); //System.out.println("p1p2 = " + p1p2); //System.out.println("prime p1 ? = " + p1.isProbablePrime(66)); //System.out.println("prime p2 ? = " + p2.isProbablePrime(33)); //System.out.println("prime p1p1 ? = " + p1p2.isProbablePrime(3)); zm = new ModLongRing(p1p2); z1 = new ModLongRing(p1); z2 = new ModLongRing(p2); for (int i = 0; i < 5; i++) { a = zm.random((59 + 29) / 2); //60+30 ); //System.out.println("a = " + a); b = new ModLong(z1, a.getVal()); //System.out.println("b = " + b); c = new ModLong(z2, a.getVal()); //System.out.println("c = " + c); ModLong di = new ModLong(z2, p1); d = di.inverse(); //System.out.println("d = " + d); e = zm.chineseRemainder(b, d, c); //System.out.println("e = " + e); assertEquals("cra(a mod p1,a mod p2) = a ", a, e); } } /** * Test timing ModLong to ModInteger. * */ public void testTiming() { zm = new ModLongRing(getPrime1()); a = zm.random(9); //System.out.println("a = " + a); b = zm.random(9); //System.out.println("b = " + b); c = zm.getONE(); //System.out.println("c = " + c); ModIntegerRing ZM = new ModIntegerRing(zm.modul); ModInteger A = new ModInteger(ZM, a.getVal()); ModInteger B = new ModInteger(ZM, b.getVal()); ModInteger C = ZM.getONE(); int run = 1000; //000; long t = System.currentTimeMillis(); for (int i = 0; i < run; i++) { if (c.isZERO()) { c = zm.getONE(); } c = a.sum(b.divide(c)); } t = System.currentTimeMillis() - t; //System.out.println("long time = " + t); ModInteger D = new ModInteger(ZM, c.getVal()); t = System.currentTimeMillis(); for (int i = 0; i < run; i++) { if (C.isZERO()) { C = ZM.getONE(); } C = A.sum(B.divide(C)); } t = System.currentTimeMillis() - t; //System.out.println("BigInteger time = " + t); assertEquals("C == D ", C, D); } /** * Test iterator. */ public void testIterator() { int m = 5*2; zm = new ModLongRing(m); ModLong j = null; for ( ModLong i : zm ) { //System.out.println("i = " + i); j = i; } ModLong end = new ModLong(zm,m-1); assertTrue("j == m-1 ", j.equals(end) ); } } jas-2.5/trc/edu/jas/arith/BigDecimalTest.java0000644000175000017500000001170411641660762021273 0ustar giovannigiovanni/* * $Id: BigDecimalTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.arith; import java.math.MathContext; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; //import edu.jas.arith.BigDecimal; /** * BigDecimal tests with JUnit. * @author Heinz Kredel. */ public class BigDecimalTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a BigDecimalTest object. * @param name String. */ public BigDecimalTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(BigDecimalTest.class); return suite; } BigDecimal a; BigDecimal b; BigDecimal c; BigDecimal d; BigDecimal e; BigDecimal fac; int kl = 100; int precision = 100; // must match default MathContext mc = new MathContext( precision ); protected void setUp() { a = b = c = d = e = null; fac = new BigDecimal(0L,mc); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test static initialization and constants. * */ public void testConstants() { a = BigDecimal.ZERO; b = BigDecimal.ONE; c = b.subtract(b); assertTrue("1-1 = 0",c.compareTo(a)==0); assertTrue("1-1 = 0",c.isZERO()); assertTrue("1 = 1", b.isONE() ); a = BigDecimal.ZERO; b = BigDecimal.ONE; c = b.subtract(b); assertTrue("1-1 = 0",c.compareTo(a)==0); } /** * Test constructor and toString. * */ public void testConstructor() { a = new BigDecimal( "6.8" ); b = new BigDecimal( "3.4" ); b = b.sum(b); assertEquals("6.8 = 3.4",0,a.compareTo(b)); String s = "6.1111111111111111111111111111111111111111111"; a = new BigDecimal( s ); String t = a.toString(); assertEquals("stringConstr = toString",s,t); a = new BigDecimal( 1 ); b = new BigDecimal( -1 ); c = b.sum(a); assertTrue("1 = 1", a.isONE() ); assertTrue("1+(-1) = 0", c.compareTo(BigDecimal.ZERO)==0 ); assertTrue("1+(-1) = 0", c.isZERO() ); } /** * Test random rationals. * */ public void testRandom() { a = fac.random( 5*kl ); //System.out.println("a = " + a); b = new BigDecimal( "" + a ); c = a.subtract(a); //System.out.println("c = " + c); //assertTrue("a-b = 0", c.compareTo(BigDecimal.ZERO)==0 ); assertTrue("a-b = 0", c.isZERO() ); d = new BigDecimal( "" + b ); //System.out.println("b = " + b); //System.out.println("d = " + d); assertTrue("sign(a-a) = 0", b.compareTo(d)==0 ); } /** * Test addition. * */ public void testAddition() { a = fac.random( kl ); b = a.sum( a ); c = b.subtract( a ); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //assertEquals("a+a-a = a", c, a); assertEquals("a+a-a = a",0,c.compareTo(a)); d = a.sum( BigDecimal.ZERO ); assertEquals("a+0 = a",0,d.compareTo(a)); d = a.subtract( BigDecimal.ZERO ); assertEquals("a-0 = a",0,d.compareTo(a)); d = a.subtract( a ); assertTrue("a-a = 0", d.compareTo(BigDecimal.ZERO)==0); b = fac.random( kl ); c = a.sum( b ); d = b.sum( a ); assertTrue("a-b = b+a", d.compareTo(c)==0 ); // addition is not associative } /** * Test multiplication. * Is not associative. */ public void testMultiplication() { a = fac.random( kl ); b = a.multiply( a ); c = b.divide( a ); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //assertEquals("a*a/a = a",c,a); assertTrue("a*a/a = a", c.compareTo(a)==0 ); d = a.multiply( BigDecimal.ONE ); assertEquals("a*1 = a",d,a); d = a.divide( BigDecimal.ONE ); assertEquals("a/1 = a",0,d.compareTo(a)); a = fac.random( kl ); b = a.inverse(); c = a.multiply( b ); //System.out.println("c = " + c); assertTrue("a*1/a = 1", c.compareTo( fac.getONE() ) == 0 ); b = fac.random( kl ); c = a.multiply( b ); d = b.multiply( a ); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("ab = ba",d.compareTo(c)==0); c = fac.random( kl ); d = a.multiply( b.multiply( c ) ); e = a.multiply( b ).multiply( c ); //System.out.println("d = " + d); //System.out.println("e = " + e); if ( d.compareTo(e) == 0 ) { assertTrue("a(bc) = (ab)c",d.compareTo(e)==0); } } /** * Test distributive law. * Does not hold. */ public void testDistributive() { a = fac.random( kl ); b = fac.random( kl ); c = fac.random( kl ); d = a.multiply( b.sum( c ) ); e = a.multiply( b ).sum( a.multiply( c ) ); if ( d.compareTo(e) == 0 ) { assertTrue("a(b+c) = ab+ac",d.compareTo(e)==0); } } } jas-2.5/trc/edu/jas/arith/BigIntegerTest.java0000644000175000017500000001433111777637434021343 0ustar giovannigiovanni/* * $Id: BigIntegerTest.java 3983 2012-07-12 21:18:20Z kredel $ */ package edu.jas.arith; import java.util.Iterator; //import edu.jas.arith.BigInteger; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * BigInteger tests with JUnit. * @author Heinz Kredel. */ public class BigIntegerTest extends TestCase { /** * main */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a BigIntegerTest object. * @param name String. */ public BigIntegerTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(BigIntegerTest.class); return suite; } private final static int bitlen = 100; BigInteger a; BigInteger b; BigInteger c; BigInteger d; BigInteger e; protected void setUp() { a = b = c = d = e = null; } protected void tearDown() { a = b = c = d = e = null; } /** * Test static initialization and constants. */ public void testConstants() { a = BigInteger.ZERO; b = BigInteger.ONE; c = BigInteger.IDIF(b,b); assertEquals("1-1 = 0",c,a); assertTrue("1-1 = 0",c.isZERO()); assertTrue("1 = 1", b.isONE() ); } /** * Test constructor and toString. */ public void testConstructor() { a = new BigInteger( "34" ); b = new BigInteger( "34" ); assertEquals("34 = 34",a,b); a = new BigInteger( "-4" ); b = new BigInteger( "-4" ); assertEquals("-4 = -4",a,b); String s = "1111111111111111111111111111111111111111111"; a = new BigInteger( s ); String t = a.toString(); assertEquals("stringConstr = toString",s,t); a = new BigInteger( 1 ); b = new BigInteger( -1 ); c = BigInteger.ISUM(b,a); assertTrue("1 = 1", a.isONE() ); assertEquals("1+(-1) = 0",c,BigInteger.ZERO); } /** * Test random integer. */ public void testRandom() { a = BigInteger.IRAND( 500 ); b = new BigInteger( "" + a ); c = BigInteger.IDIF(b,a); assertEquals("a-b = 0",c,BigInteger.ZERO); d = new BigInteger( b.getVal() ); assertEquals("sign(a-a) = 0", 0, b.compareTo(d) ); } /** * Test addition. */ public void testAddition() { a = BigInteger.IRAND( bitlen ); b = BigInteger.ISUM(a,a); c = BigInteger.IDIF(b,a); assertEquals("a+a-a = a",c,a); assertEquals("a+a-a = a", 0, c.compareTo(a) ); d = BigInteger.ISUM( a, BigInteger.ZERO ); assertEquals("a+0 = a",d,a); d = BigInteger.IDIF( a, BigInteger.ZERO ); assertEquals("a-0 = a",d,a); d = BigInteger.IDIF( a, a ); assertEquals("a-a = 0", d, BigInteger.ZERO ); } /** * Test multiplication. */ public void testMultiplication() { a = BigInteger.IRAND( bitlen ); b = BigInteger.IPROD( a, a ); c = BigInteger.IQ( b, a ); assertEquals("a*a/a = a",c,a); assertEquals("a*a/a = a",0,BigInteger.ICOMP(c,a)); d = BigInteger.IPROD( a, BigInteger.ONE ); assertEquals("a*1 = a",d,a); d = BigInteger.IQ( a, BigInteger.ONE ); assertEquals("a/1 = a",d,a); a = BigInteger.IRAND( bitlen*2 ); b = BigInteger.IRAND( bitlen ); BigInteger[] qr = BigInteger.IQR( a, b ); c = BigInteger.IPROD( qr[0], b ); c = BigInteger.ISUM( c, qr[1] ); assertEquals("a = q*b+r)",a,c); } /** * Test distributive law. */ public void testDistributive() { BigInteger fac = new BigInteger(); a = fac.random( bitlen ); b = fac.random( bitlen ); c = fac.random( bitlen ); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } /** * Test gcd. */ public void testGcd() { a = BigInteger.IRAND( bitlen ); b = BigInteger.IRAND( bitlen ); c = BigInteger.IGCD( a, b ); // ~1 BigInteger[] qr = BigInteger.IQR( a, c ); d = BigInteger.IPROD( qr[0], c ); assertEquals("a = gcd(a,b)*q1",a,d); assertEquals("a/gcd(a,b) = q*x + 0", qr[1], BigInteger.ZERO ); qr = BigInteger.IQR( b, c ); d = BigInteger.IPROD( qr[0], c ); assertEquals("b = gcd(a,b)*q1",b,d); assertEquals("b/gcd(a,b) = q*x + 0", qr[1], BigInteger.ZERO ); c = BigInteger.IRAND( bitlen*4 ); a = BigInteger.IPROD( a, c ); b = BigInteger.IPROD( b, c ); c = BigInteger.IGCD( a, b ); // = c qr = BigInteger.IQR( a, c ); d = BigInteger.IPROD( qr[0], c ); assertEquals("a = gcd(a,b)*q1",a,d); assertEquals("a/gcd(a,b) = q*x + 0", qr[1], BigInteger.ZERO ); qr = BigInteger.IQR( b, c ); d = BigInteger.IPROD( qr[0], c ); assertEquals("b = gcd(a,b)*q1",b,d); assertEquals("b/gcd(a,b) = q*x + 0", qr[1], BigInteger.ZERO ); } /** * Test iterator. */ public void testIterator() { int t = 0; BigInteger bi = new BigInteger(); bi.setAllIterator(); BigInteger j = null, ten = null; for ( BigInteger i : bi ) { t++; //System.out.println("i = " + i); if ( t >= 20 ) { j = i; break; } } ten = new BigInteger(10); assertEquals("j == 10 ", j, ten ); } /** * Test non-negative iterator. */ public void testNNIterator() { int t = 0; BigInteger bi = new BigInteger(); bi.setNonNegativeIterator(); BigInteger j = null, ten = null; Iterator iter = bi.iterator(); while ( iter.hasNext() ) { BigInteger i = iter.next(); t++; //System.out.println("i = " + i); if ( t > 20 ) { j = i; break; } } ten = new BigInteger(20); assertEquals("j == 10 ", j, ten ); } } jas-2.5/trc/edu/jas/arith/ArithTest.java0000644000175000017500000006155412004571452020361 0ustar giovannigiovanni/* * $Id: ArithTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.arith; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.structure.Power; /** * Basic arithmetic tests with JUnit. * @author Heinz Kredel. */ public class ArithTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a ArithTest object. * @param name String. */ public ArithTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(ArithTest.class); return suite; } /* RingElem a; RingElem b; RingElem c; RingElem d; RingElem e; */ @Override protected void setUp() { //a = b = c = d = e = null; } @Override protected void tearDown() { //a = b = c = d = e = null; } /** * Test static initialization and constants for BigInteger. */ public void testIntegerConstants() { BigInteger a, b, c, d; a = BigInteger.ZERO; b = BigInteger.ONE; c = b.subtract(b); assertTrue("0.isZERO()", a.isZERO()); assertTrue("1.isONE", b.isONE()); assertEquals("1-1 = 0", c, a); assertTrue("(1-1).isZERO()", c.isZERO()); d = b.multiply(b); assertTrue("1*1 = 1", d.isONE()); d = b.multiply(a); assertTrue("1*0 = 0", d.isZERO()); } //-------------------------------------------------------- /** * Test string constructor and toString for BigInteger. */ public void testIntegerConstructor() { BigInteger a, b, c, d; a = new BigInteger(1); b = new BigInteger(-1); c = new BigInteger(0); d = a.sum(b); assertTrue("'1'.isONE()", a.isONE()); assertTrue("1+(-1) = 0", d.isZERO()); d = a.negate(); assertEquals("-1 = -(1)", d, b); d = a.multiply(c); assertTrue("'0'.isZERO()", d.isZERO()); d = b.multiply(b); assertTrue("(-1)*(-1) = 1", d.isONE()); a = new BigInteger(3); b = new BigInteger("3"); assertEquals("3 = '3'", a, b); a = new BigInteger(-5); b = new BigInteger("-5"); assertEquals("-5 = '-5'", a, b); // 0 1 2 3 4 // 0123456789012345678901234567890123456789012345 String s = "1111111111111111111111111111111111111111111111"; a = new BigInteger(s); String t = a.toString(); assertEquals("stringConstr = toString", s, t); } //-------------------------------------------------------- /** * Test random and compares Integer. * */ public void testIntegerRandom() { BigInteger a, b, c; a = BigInteger.ZERO.random(500); b = new BigInteger("" + a); c = b.subtract(a); assertTrue("a-'a' = 0", c.isZERO()); assertEquals("compareTo('a',a) = 0", 0, b.compareTo(a)); assertEquals("signum('a'-a) = 0", 0, c.signum()); } //-------------------------------------------------------- /** * Test addition for Integer. * */ public void testIntegerAddition() { BigInteger a, b, c, d, e; // neutral element a = BigInteger.ZERO.random(500); d = a.sum(BigInteger.ZERO); assertEquals("a+0 = a", d, a); d = a.subtract(BigInteger.ZERO); assertEquals("a-0 = a", d, a); // inverse operations b = a.sum(a); c = b.subtract(a); assertEquals("(a+a)-a = a", c, a); b = a.subtract(a); c = b.sum(a); assertEquals("(a-a)+a = a", c, a); // comutativity b = BigInteger.ZERO.random(500); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a", c, d); // negation c = a.subtract(b); d = a.sum(b.negate()); assertEquals("a-b = a+(-b)", c, d); // associativity c = BigInteger.ZERO.random(500); d = a.sum(b.sum(c)); e = a.sum(b).sum(c); assertEquals("a+(b+c) = (a+b)+c", d, e); } //-------------------------------------------------------- /** * Test multiplication for Integer. * */ public void testIntegerMultiplication() { BigInteger a, b, c, d, e; // neutral element a = BigInteger.ZERO.random(500); d = a.multiply(BigInteger.ONE); assertEquals("a*1 = a", d, a); d = a.divide(BigInteger.ONE); assertEquals("a/1 = a", d, a); // inverse operations b = a.multiply(a); c = b.divide(a); assertEquals("(a*a)/a = a", c, a); b = a.divide(a); c = b.multiply(a); assertEquals("(a/a)*a = a", c, a); // comutativity b = BigInteger.ZERO.random(500); c = a.multiply(b); d = b.multiply(a); assertEquals("a*b = b*a", c, d); // inverse d = c.divide(b); // e = c.multiply( b.inverse() ); e = a; assertEquals("a/b = a*(1/b)", d, e); // associativity c = BigInteger.ZERO.random(500); d = a.multiply(b.multiply(c)); e = a.multiply(b).multiply(c); assertEquals("a*(b*c) = (a*b)*c", d, e); } /** * Test static initialization and constants for BigRational. * */ public void testRationalConstants() { BigRational a, b, c, d; a = BigRational.ZERO; b = BigRational.ONE; //System.out.println("a = " + a); //System.out.println("b = " + b); c = b.subtract(b); assertTrue("0.isZERO()", a.isZERO()); assertTrue("1.isONE", b.isONE()); assertEquals("1-1 = 0", c, a); assertTrue("(1-1).isZERO()", c.isZERO()); d = b.multiply(b); assertTrue("1*1 = 1", d.isONE()); d = b.multiply(a); assertTrue("1*0 = 0", d.isZERO()); } /** * Test static initialization and constants for BigComplex. * */ public void testComplexConstants() { BigComplex a, b, c, d; a = BigComplex.ZERO; b = BigComplex.ONE; c = b.subtract(b); assertTrue("0.isZERO()", a.isZERO()); assertTrue("1.isONE", b.isONE()); assertEquals("1-1 = 0", c, a); assertTrue("(1-1).isZERO()", c.isZERO()); d = b.multiply(b); assertTrue("1*1 = 1", d.isONE()); d = b.multiply(a); assertTrue("1*0 = 0", d.isZERO()); } /** * Test static initialization and constants for BigQuaternion. * */ public void testQuaternionConstants() { BigQuaternion a, b, c, d; a = BigQuaternion.ZERO; b = BigQuaternion.ONE; c = b.subtract(b); assertTrue("0.isZERO()", a.isZERO()); assertTrue("1.isONE", b.isONE()); assertEquals("1-1 = 0", c, a); assertTrue("(1-1).isZERO()", c.isZERO()); d = b.multiply(b); assertTrue("1*1 = 1", d.isONE()); d = b.multiply(a); assertTrue("1*0 = 0", d.isZERO()); } //-------------------------------------------------------- /** * Test string constructor and toString for BigRational. * */ public void testRationalConstructor() { BigRational a, b, c, d; a = new BigRational(1); b = new BigRational(-1); c = new BigRational(0); d = a.sum(b); assertTrue("'1'.isONE()", a.isONE()); assertTrue("1+(-1) = 0", d.isZERO()); d = a.negate(); assertEquals("-1 = -(1)", d, b); d = a.multiply(c); assertTrue("'0'.isZERO()", d.isZERO()); d = b.multiply(b); assertTrue("(-1)*(-1) = 1", d.isONE()); a = new BigRational(3); b = new BigRational("3"); assertEquals("3 = '3'", a, b); a = new BigRational(-5); b = new BigRational("-5"); assertEquals("-5 = '-5'", a, b); // 0 1 2 3 4 // 0123456789012345678901234567890123456789012345 String s = "1111111111111111111111111111111111111111111111"; a = new BigRational(s); String t = a.toString(); assertEquals("stringConstr = toString", s, t); s = "2/4"; a = new BigRational(s); t = a.toString(5); //System.out.println("a = " + a); //System.out.println("t = " + t); String r = "0.5"; assertEquals("stringConstr = toString", r, t); } /** * Test string constructor and toString for BigComplex. * */ public void testComplexConstructor() { BigComplex a, b, c, d; a = new BigComplex(1); b = new BigComplex(-1); c = new BigComplex(0); d = a.sum(b); assertTrue("'1'.isONE()", a.isONE()); assertTrue("1+(-1) = 0", d.isZERO()); d = a.negate(); assertEquals("-1 = -(1)", d, b); d = a.multiply(c); assertTrue("'0'.isZERO()", d.isZERO()); d = b.multiply(b); assertTrue("(-1)*(-1) = 1", d.isONE()); a = new BigComplex(3); b = new BigComplex("3"); assertEquals("3 = '3'", a, b); a = new BigComplex(-5); b = new BigComplex("-5"); assertEquals("-5 = '-5'", a, b); // 0 1 2 3 4 // 0123456789012345678901234567890123456789012345 String s = "1111111111111111111111111111111111111111111111"; a = new BigComplex(s); String t = a.toString(); assertEquals("stringConstr = toString", s, t); } /** * Test string constructor and toString for BigQuaternion. * */ public void testQuaternionConstructor() { BigQuaternion a, b, c, d; a = new BigQuaternion(1); b = new BigQuaternion(-1); c = new BigQuaternion(0); d = a.sum(b); assertTrue("'1'.isONE()", a.isONE()); assertTrue("1+(-1) = 0", d.isZERO()); d = a.negate(); assertEquals("-1 = -(1)", d, b); d = a.multiply(c); assertTrue("'0'.isZERO()", d.isZERO()); d = b.multiply(b); assertTrue("(-1)*(-1) = 1", d.isONE()); a = new BigQuaternion(3); b = new BigQuaternion("3"); assertEquals("3 = '3'", a, b); a = new BigQuaternion(-5); b = new BigQuaternion("-5"); assertEquals("-5 = '-5'", a, b); // 0 1 2 3 4 // 0123456789012345678901234567890123456789012345 String s = "1111111111111111111111111111111111111111111111"; a = new BigQuaternion(s); String t = a.toString(); assertEquals("stringConstr = toString", s, t); } //-------------------------------------------------------- /** * Test random and compares Rational. * */ public void testRationalRandom() { BigRational a, b, c; a = BigRational.ZERO.random(500); b = new BigRational("" + a); c = b.subtract(a); assertTrue("a-'a' = 0", c.isZERO()); assertEquals("compareTo('a',a) = 0", 0, b.compareTo(a)); assertEquals("signum('a'-a) = 0", 0, c.signum()); } /** * Test random and compares Complex. * */ public void testComplexRandom() { BigComplex a, b, c; a = BigComplex.ZERO.random(500); b = new BigComplex("" + a); c = b.subtract(a); assertTrue("a-'a' = 0", c.isZERO()); assertEquals("compareTo('a',a) = 0", 0, b.compareTo(a)); assertEquals("signum('a'-a) = 0", 0, c.signum()); } /** * Test random and compares Quaternion. * */ public void testQuaternionRandom() { BigQuaternion a, b, c; a = BigQuaternion.ZERO.random(500); b = new BigQuaternion("" + a); c = b.subtract(a); assertTrue("a-'a' = 0", c.isZERO()); assertEquals("signum('a'-a) = 0", 0, c.signum()); assertEquals("compareTo('a',a) = 0", 0, b.compareTo(a)); } //-------------------------------------------------------- /** * Test addition for Rational. * */ public void testRationalAddition() { BigRational a, b, c, d, e; // neutral element a = BigRational.ZERO.random(500); d = a.sum(BigRational.ZERO); assertEquals("a+0 = a", d, a); d = a.subtract(BigRational.ZERO); assertEquals("a-0 = a", d, a); // inverse operations b = a.sum(a); c = b.subtract(a); assertEquals("(a+a)-a = a", c, a); b = a.subtract(a); c = b.sum(a); assertEquals("(a-a)+a = a", c, a); // comutativity b = BigRational.ZERO.random(500); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a", c, d); // negation c = a.subtract(b); d = a.sum(b.negate()); assertEquals("a-b = a+(-b)", c, d); // associativity c = BigRational.ZERO.random(500); d = a.sum(b.sum(c)); e = a.sum(b).sum(c); assertEquals("a+(b+c) = (a+b)+c", d, e); } /** * Test addition for Complex. * */ public void testComplexAddition() { BigComplex a, b, c, d, e; // neutral element a = BigComplex.ZERO.random(500); d = a.sum(BigComplex.ZERO); assertEquals("a+0 = a", d, a); d = a.subtract(BigComplex.ZERO); assertEquals("a-0 = a", d, a); // inverse operations b = a.sum(a); c = b.subtract(a); assertEquals("(a+a)-a = a", c, a); b = a.subtract(a); c = b.sum(a); assertEquals("(a-a)+a = a", c, a); // comutativity b = BigComplex.ZERO.random(500); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a", c, d); // negation c = a.subtract(b); d = a.sum(b.negate()); assertEquals("a-b = a+(-b)", c, d); // associativity c = BigComplex.ZERO.random(500); d = a.sum(b.sum(c)); e = a.sum(b).sum(c); assertEquals("a+(b+c) = (a+b)+c", d, e); } /** * Test addition for Quaternion. * */ public void testQuaternionAddition() { BigQuaternion a, b, c, d, e; // neutral element a = BigQuaternion.ZERO.random(500); d = a.sum(BigQuaternion.ZERO); assertEquals("a+0 = a", d, a); d = a.subtract(BigQuaternion.ZERO); assertEquals("a-0 = a", d, a); // inverse operations b = a.sum(a); c = b.subtract(a); assertEquals("(a+a)-a = a", c, a); b = a.subtract(a); c = b.sum(a); assertEquals("(a-a)+a = a", c, a); // comutativity b = BigQuaternion.ZERO.random(500); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a", c, d); // negation c = a.subtract(b); d = a.sum(b.negate()); assertEquals("a-b = a+(-b)", c, d); // associativity c = BigQuaternion.ZERO.random(500); d = a.sum(b.sum(c)); e = a.sum(b).sum(c); assertEquals("a+(b+c) = (a+b)+c", d, e); } //-------------------------------------------------------- /** * Test multiplication for Rational. * */ public void testRationalMultiplication() { BigRational a, b, c, d, e; // neutral element a = BigRational.ZERO.random(500); d = a.multiply(BigRational.ONE); assertEquals("a*1 = a", d, a); d = a.divide(BigRational.ONE); assertEquals("a/1 = a", d, a); // inverse operations b = a.multiply(a); c = b.divide(a); assertEquals("(a*a)/a = a", c, a); b = a.divide(a); c = b.multiply(a); assertEquals("(a/a)*a = a", c, a); // comutativity b = BigRational.ZERO.random(500); c = a.multiply(b); d = b.multiply(a); assertEquals("a*b = b*a", c, d); // inverse d = c.divide(b); e = c.multiply(b.inverse()); //e = a; assertEquals("a/b = a*(1/b)", d, e); // associativity c = BigRational.ZERO.random(500); d = a.multiply(b.multiply(c)); e = a.multiply(b).multiply(c); assertEquals("a*(b*c) = (a*b)*c", d, e); } /** * Test multiplication for Complex. * */ public void testComplexMultiplication() { BigComplex a, b, c, d, e; // neutral element a = BigComplex.ZERO.random(500); d = a.multiply(BigComplex.ONE); assertEquals("a*1 = a", d, a); d = a.divide(BigComplex.ONE); assertEquals("a/1 = a", d, a); // inverse operations b = a.multiply(a); c = b.divide(a); assertEquals("(a*a)/a = a", c, a); b = a.divide(a); c = b.multiply(a); assertEquals("(a/a)*a = a", c, a); // comutativity b = BigComplex.ZERO.random(500); c = a.multiply(b); d = b.multiply(a); assertEquals("a*b = b*a", c, d); // inverse d = c.divide(b); e = c.multiply(b.inverse()); //e = a; assertEquals("a/b = a*(1/b)", d, e); // associativity c = BigComplex.ZERO.random(500); d = a.multiply(b.multiply(c)); e = a.multiply(b).multiply(c); assertEquals("a*(b*c) = (a*b)*c", d, e); } /** * Test multiplication for Quaternion. * */ public void testQuaternionMultiplication() { BigQuaternion a, b, c, d, e; // neutral element a = BigQuaternion.ZERO.random(500); d = a.multiply(BigQuaternion.ONE); assertEquals("a*1 = a", d, a); d = a.divide(BigQuaternion.ONE); assertEquals("a/1 = a", d, a); // inverse operations b = a.multiply(a); c = b.divide(a); assertEquals("(a*a)/a = a", c, a); b = a.divide(a); c = b.multiply(a); assertEquals("(a/a)*a = a", c, a); // inverse b = BigQuaternion.ZERO.random(500); c = b.multiply(a); d = c.divide(b); e = c.multiply(b.inverse()); //e = a; assertEquals("a/b = a*(1/b)", d, e); // associativity c = BigQuaternion.ZERO.random(500); d = a.multiply(b.multiply(c)); e = a.multiply(b).multiply(c); assertEquals("a*(b*c) = (a*b)*c", d, e); // non comutativity a = BigQuaternion.I; b = BigQuaternion.J; c = a.multiply(b); d = b.multiply(a); assertEquals("I*J = -J*I", c, d.negate()); a = BigQuaternion.I; b = BigQuaternion.K; c = a.multiply(b); d = b.multiply(a); assertEquals("I*K = -K*I", c, d.negate()); a = BigQuaternion.J; b = BigQuaternion.K; c = a.multiply(b); d = b.multiply(a); assertEquals("J*K = -K*J", c, d.negate()); } /** * Test power for Rational. * */ public void testRationalPower() { BigRational a, b, c, d; a = BigRational.ZERO.random(500); // power operations b = Power. positivePower(a, 1); assertEquals("a^1 = a", b, a); Power pow = new Power(BigRational.ONE); b = pow.power(a, 1); assertEquals("a^1 = a", b, a); b = pow.power(a, 2); c = a.multiply(a); assertEquals("a^2 = a*a", b, c); d = pow.power(a, -2); c = b.multiply(d); assertTrue("a^2 * a^-2 = 1", c.isONE()); b = pow.power(a, 3); c = a.multiply(a).multiply(a); assertEquals("a^3 = a*a*a", b, c); d = pow.power(a, -3); c = b.multiply(d); assertTrue("a^3 * a^-3 = 1", c.isONE()); } /** * Test power for Integer. * */ public void testIntegerPower() { BigInteger a, b, c, d, e; a = BigInteger.ZERO.random(500); // power operations b = Power. positivePower(a, 1); assertEquals("a^1 = a", b, a); Power pow = new Power(BigInteger.ONE); b = pow.power(a, 1); assertEquals("a^1 = a", b, a); b = pow.power(a, 2); c = a.multiply(a); assertEquals("a^2 = a*a", b, c); b = pow.power(a, 3); c = a.multiply(a).multiply(a); assertEquals("a^3 = a*a*a", b, c); // mod power operations a = new BigInteger(3); b = Power. positivePower(a, 1); assertEquals("a^1 = a", b, a); a = new BigInteger(11); e = new BigInteger(2); c = Power. modPositivePower(a, 10, e); assertTrue("3^n mod 2 = 1", c.isONE()); // little fermat a = BigInteger.ZERO.random(500); b = new BigInteger(11); c = Power. modPositivePower(a, 11, b); d = a.remainder(b); assertEquals("a^p = a mod p", c, d); c = pow.modPower(a, 11, b); assertEquals("a^p = a mod p", c, d); } /** * Test Combinatoric. */ public void testCombinatoric() { BigInteger a, b, c; a = Combinatoric.binCoeff(5, 0); assertTrue("(5 0) == 1 ", a.isONE()); a = Combinatoric.binCoeff(5, 7); //System.out.println(5 + " over " + 7 + " = " + a); assertTrue("(5 7) == 1 ", a.isONE()); int n = 7; for (int k = 0; k <= n; k++) { a = Combinatoric.binCoeff(n, k); b = Combinatoric.binCoeff(n, n - k); assertEquals("(5 k) == (5 5-k) ", b, a); //System.out.println(n + " over " + k + " = " + a); } assertTrue("(5 5) == 1 ", a.isONE()); b = Combinatoric.binCoeffSum(n, n); //System.out.println("sum( " + n + " over " + n + " ) = " + b); c = Power.positivePower(new BigInteger(2), n); assertEquals("sum(5 5) == 1 ", b, c); b = Combinatoric.factorial(3); assertEquals("3! == 6 ", b, new BigInteger(6)); b = Combinatoric.factorial(0); assertEquals("0! == 1 ", b, new BigInteger(1)); } /** * Test square root. */ public void testSquareRoot() { BigInteger a, b, c, d, e, f; a = BigInteger.ONE; b = a.random(47).abs(); //b = c.multiply(c); d = Roots.sqrtInt(b); //System.out.println("b = " + b); //System.out.println("root = " + d); e = d.multiply(d); //System.out.println("root^2 = " + e); assertTrue("root^2 <= a ", e.compareTo(b) <= 0); d = d.sum(BigInteger.ONE); f = d.multiply(d); //System.out.println("(root+1)^2 = " + f); assertTrue("(root+1)^2 >= a ", f.compareTo(b) >= 0); c = Roots.sqrt(b); //System.out.println("b = " + b); //System.out.println("root = " + c); e = c.multiply(c); //System.out.println("root^2 = " + e); assertTrue("root^2 <= a ", e.compareTo(b) <= 0); c = c.sum(BigInteger.ONE); f = c.multiply(c); //System.out.println("(root+1)^2 = " + f); assertTrue("(root+1)^2 >= a ", f.compareTo(b) >= 0); } /** * Test root. */ public void testRoot() { BigInteger a, b, d, e, f; a = BigInteger.ONE; b = a.random(47).abs(); //System.out.println("\nb = " + b); //System.out.println("bitsize(b) = " + b.val.bitLength()); for (int n = 2; n < 8; n++) { d = Roots.root(b, n); //System.out.println(n+"-th root = " + d); e = Power.positivePower(d, n); //System.out.println("root^"+n+" = " + e); assertTrue("root^" + n + " <= a " + (b.subtract(e)), e.compareTo(b) <= 0); d = d.sum(BigInteger.ONE); f = Power.positivePower(d, n); //System.out.println("(root+1)^"+n+" = " + f); assertTrue("(root+1)^" + n + " >= a ", f.compareTo(b) >= 0); } } /** * Test root decimal. */ public void testRootDecimal() { BigDecimal a, b, d, e; a = BigDecimal.ONE; b = a.random(7).abs(); //System.out.println("\nb = " + b); //System.out.println("ulp(b) = " + b.val.ulp()); for (int n = 1; n < 8; n++) { d = Roots.root(b, n); //System.out.println(n+"-th root = " + d); e = Power.positivePower(d, n); //System.out.println("root^"+n+" = " + e); e = e.subtract(d).abs(); //System.out.println("e = " + e); e = e.divide(b); //System.out.println("e = " + e); if (b.compareTo(a) > 0) { assertTrue("root^" + n + " == a: " + e, a.compareTo(e) >= 0); } else { assertTrue("root^" + n + " == a: " + e, a.compareTo(e) <= 0); } } } } jas-2.5/trc/edu/jas/arith/ModIntegerTest.java0000644000175000017500000002406012014234362021333 0ustar giovannigiovanni/* * $Id: ModIntegerTest.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.arith; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.kern.PrettyPrint; import edu.jas.structure.NotInvertibleException; /** * ModInteger and PrimeList tests with JUnit. * @author Heinz Kredel. */ public class ModIntegerTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a ModIntegerTest object. * @param name String */ public ModIntegerTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(ModIntegerTest.class); return suite; } ModIntegerRing zm; ModIntegerRing z1; ModIntegerRing z2; ModInteger a; ModInteger b; ModInteger c; ModInteger d; ModInteger e; @Override protected void setUp() { zm = z1 = z2 = null; a = b = c = d = e = null; } @Override protected void tearDown() { zm = z1 = z2 = null; a = b = c = d = e = null; } protected static java.math.BigInteger getPrime1() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 60; i++) { prime *= 2; } prime -= 93; //prime = 37; //System.out.println("p1 = " + prime); return new java.math.BigInteger("" + prime); } protected static java.math.BigInteger getPrime2() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 30; i++) { prime *= 2; } prime -= 35; //prime = 19; //System.out.println("p2 = " + prime); return new java.math.BigInteger("" + prime); } /** * Test static initialization and constants. * */ public void testConstants() { zm = new ModIntegerRing(5); d = new ModInteger(zm, 11); a = zm.getZERO(); b = zm.getONE(); c = ModInteger.MIDIF(b, b); assertEquals("1-1 = 0", c, a); assertTrue("1-1 = 0", c.isZERO()); assertTrue("1 = 1", b.isONE()); } /** * Test constructor and toString. * */ public void testConstructor() { zm = new ModIntegerRing("5"); a = new ModInteger(zm, "64"); b = new ModInteger(zm, "34"); assertEquals("64(5) = 34(5)", a, b); zm = new ModIntegerRing("7"); a = new ModInteger(zm, "-4"); b = new ModInteger(zm, "3"); assertEquals("-4(7) = 3(7)", a, b); String s = "61111111111111111111111111111111111111111111"; zm = new ModIntegerRing("10"); a = new ModInteger(zm, s); String t = a.toString(); if (PrettyPrint.isTrue()) { String st = "1"; assertEquals("stringConstr = toString", st, t); } else { String st = "1 mod(10)"; assertEquals("stringConstr = toString", st, t); } zm = new ModIntegerRing(7); a = new ModInteger(zm, 1); b = new ModInteger(zm, -1); c = ModInteger.MISUM(b, a); assertTrue("1 = 1", a.isONE()); assertTrue("1 = 1", b.isUnit()); assertEquals("1+(-1) = 0", c, zm.getZERO()); zm = new ModIntegerRing(5); a = new ModInteger(zm, 3); b = new ModInteger(zm, 0); c = zm.parse(" 13 "); assertEquals("3(5) = 3(5)", a, c); StringReader sr = new StringReader(" 13\n w "); c = zm.parse(sr); assertEquals("3(5) = 3(5)", a, c); //System.out.println("c = " + c); } /** * Test random modular integers. * */ public void testRandom() { zm = new ModIntegerRing(19); a = zm.random(500); b = a.copy(); c = ModInteger.MIDIF(b, a); assertEquals("a-b = 0", c, zm.getZERO()); d = new ModInteger(new ModIntegerRing(b.getModul()), b.getVal()); assertEquals("sign(a-a) = 0", 0, b.compareTo(d)); } /** * Test addition. * */ public void testAddition() { zm = new ModIntegerRing(19); a = zm.random(100); b = ModInteger.MISUM(a, a); c = ModInteger.MIDIF(b, a); assertEquals("a+a-a = a", c, a); assertEquals("a+a-a = a", 0, ModInteger.MICOMP(c, a)); d = ModInteger.MISUM(a, zm.getZERO()); assertEquals("a+0 = a", d, a); d = ModInteger.MIDIF(a, zm.getZERO()); assertEquals("a-0 = a", d, a); d = ModInteger.MIDIF(a, a); assertEquals("a-a = 0", d, zm.getZERO()); } /** * Test multiplication. * */ public void testMultiplication() { zm = new ModIntegerRing(5); d = new ModInteger(zm, 11); a = zm.random(100); if (a.isZERO()) { a = d; } b = ModInteger.MIPROD(a, a); c = ModInteger.MIQ(b, a); assertEquals("a*a/a = a", c, a); assertEquals("a*a/a = a", 0, c.compareTo(a)); d = ModInteger.MIPROD(a, zm.getONE()); assertEquals("a*1 = a", d, a); d = ModInteger.MIQ(a, zm.getONE()); assertEquals("a/1 = a", d, a); a = zm.random(100); if (a.isZERO()) { a = d; } b = ModInteger.MIINV(a); c = ModInteger.MIPROD(a, b); assertTrue("a*1/a = 1", c.isONE()); try { a = zm.getZERO().inverse(); fail("0 invertible"); } catch (NotInvertibleException expected) { // ok } zm = new ModIntegerRing(5 * 3); a = new ModInteger(zm, 5); assertFalse("5 !unit mod 15", a.isUnit()); try { b = a.inverse(); fail("5 invertible"); } catch (ModularNotInvertibleException expected) { //ok //expected.printStackTrace(); assertTrue("f = 15 ", expected.f.equals(new BigInteger(15))); assertTrue("f1 = 5 ", expected.f1.equals(new BigInteger(5))); assertTrue("f2 = 3 ", expected.f2.equals(new BigInteger(3))); assertTrue("f = f1*f2 ", expected.f.equals(expected.f1.multiply(expected.f2))); } catch (NotInvertibleException e) { //e.printStackTrace(); fail("wrong exception " + e); } } /** * Test chinese remainder. * */ public void testChineseRemainder() { zm = new ModIntegerRing(19 * 13); a = zm.random(9); //System.out.println("a = " + a); z1 = new ModIntegerRing(19); b = new ModInteger(z1, a.getVal().longValue()); //System.out.println("b = " + b); z2 = new ModIntegerRing(13); c = new ModInteger(z2, a.getVal().longValue()); //System.out.println("c = " + c); d = new ModInteger(z2, 19); d = d.inverse(); //System.out.println("d = " + d); e = zm.chineseRemainder(b, d, c); //System.out.println("e = " + e); assertEquals("cra(a mod 19,a mod 13) = a", a, e); java.math.BigInteger p1 = getPrime1(); java.math.BigInteger p2 = getPrime2(); java.math.BigInteger p1p2 = p1.multiply(p2); //System.out.println("p1p2 = " + p1p2); //System.out.println("prime p1 ? = " + p1.isProbablePrime(66)); //System.out.println("prime p2 ? = " + p2.isProbablePrime(33)); //System.out.println("prime p1p1 ? = " + p1p2.isProbablePrime(3)); zm = new ModIntegerRing(p1p2); z1 = new ModIntegerRing(p1); z2 = new ModIntegerRing(p2); for (int i = 0; i < 5; i++) { a = zm.random((59 + 29) / 2); //60+30 ); //System.out.println("a = " + a); b = new ModInteger(z1, a.getVal()); //System.out.println("b = " + b); c = new ModInteger(z2, a.getVal()); //System.out.println("c = " + c); ModInteger di = new ModInteger(z2, p1); d = di.inverse(); //System.out.println("d = " + d); e = zm.chineseRemainder(b, d, c); //System.out.println("e = " + e); assertEquals("cra(a mod p1,a mod p2) = a", a, e); } } /** * Test prime list. * */ public void testPrime() { PrimeList primes = new PrimeList(); //System.out.println("primes = " + primes); //assertTrue("all primes ", primes.checkPrimes() ); int i = 0; //System.out.println("primes = "); for (java.math.BigInteger p : primes) { assertFalse("p != null", p == null); //System.out.print("" + p); if (i++ > 50) { break; } //System.out.print(", "); } //System.out.println(); //System.out.println("primes = " + primes); assertTrue("all primes ", primes.checkPrimes()); } /** * Test Mersenne prime list. * */ public void testMersennePrime() { PrimeList primes = new PrimeList(PrimeList.Range.mersenne); //System.out.println("primes = " + primes); //assertTrue("all primes ", primes.checkPrimes() ); int i = 1; //System.out.println("primes = "); for (java.math.BigInteger p : primes) { assertFalse("p != null", p == null); //System.out.println(i + " = " + p); if (i++ > 23) { break; } //System.out.print(", "); } //System.out.println(); //System.out.println("primes = " + primes); assertTrue("all primes ", primes.checkPrimes(15)); } /** * Test iterator. */ public void testIterator() { int m = 5 * 2; zm = new ModIntegerRing(m); ModInteger j = null; for (ModInteger i : zm) { //System.out.println("i = " + i); j = i; } ModInteger end = new ModInteger(zm, m - 1); assertTrue("j == m-1 ", j.equals(end)); } } jas-2.5/trc/edu/jas/arith/BigComplexTest.java0000644000175000017500000000732411641660762021347 0ustar giovannigiovanni/* * $Id: BigComplexTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.arith; //import edu.jas.arith.BigRational; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * BigComplex tests with JUnit. * @author Heinz Kredel. */ public class BigComplexTest extends TestCase { /** * main */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a BigComplexTest object. * @param name String. */ public BigComplexTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(BigComplexTest.class); return suite; } BigComplex a; BigComplex b; BigComplex c; BigComplex d; BigComplex e; protected void setUp() { a = b = c = d = e = null; } protected void tearDown() { a = b = c = d = e = null; } /** * Test static initialization and constants. * */ public void testConstants() { a = BigComplex.ZERO; b = BigComplex.ONE; c = BigComplex.CDIF(b,b); assertEquals("1-1 = 0",c,a); assertTrue("1-1 = 0",c.isZERO()); assertTrue("1 = 1", b.isONE() ); a = BigComplex.ZERO; b = BigComplex.ONE; c = BigComplex.CDIF(b,b); assertEquals("1-1 = 0",c,a); } /** * Test constructor and toString. * */ public void testConstructor() { a = new BigComplex( "6/8" ); b = new BigComplex( "3/4" ); assertEquals("6/8 = 3/4",a,b); a = new BigComplex( "3/4 i 4/5" ); b = new BigComplex( "-3/4 i -4/5" ); assertEquals("3/4 + i 4/5 ",a,b.negate()); String s = "6/1111111111111111111111111111111111111111111"; a = new BigComplex( s ); String t = a.toString(); assertEquals("stringConstr = toString",s,t); a = new BigComplex( 1 ); b = new BigComplex( -1 ); c = BigComplex.CSUM(b,a); assertTrue("1 = 1", a.isONE() ); assertEquals("1+(-1) = 0",c,BigComplex.ZERO); } /** * Test random rationals. * */ public void testRandom() { a = BigComplex.CRAND( 500 ); b = new BigComplex( a.getRe(), a.getIm() ); c = BigComplex.CDIF(b,a); assertEquals("a-b = 0",c,BigComplex.ZERO); d = new BigComplex( b.getRe(), b.getIm() ); assertEquals("sign(a-a) = 0", 0, b.compareTo(d) ); } /** * Test addition. * */ public void testAddition() { a = BigComplex.CRAND( 100 ); b = BigComplex.CSUM( a, a ); c = BigComplex.CDIF( b, a ); assertEquals("a+a-a = a",c,a); assertEquals("a+a-a = a",0,c.compareTo(a)); d = BigComplex.CSUM( a, BigComplex.ZERO ); assertEquals("a+0 = a",d,a); d = BigComplex.CDIF( a, BigComplex.ZERO ); assertEquals("a-0 = a",d,a); d = BigComplex.CDIF( a, a ); assertEquals("a-a = 0",d,BigComplex.ZERO); } /** * Test multiplication. * */ public void testMultiplication() { a = BigComplex.CRAND( 100 ); b = BigComplex.CPROD( a, a ); c = BigComplex.CQ( b, a ); assertEquals("a*a/a = a",c,a); assertEquals("a*a/a = a",0,c.compareTo(a)); d = BigComplex.CPROD( a, BigComplex.ONE ); assertEquals("a*1 = a",d,a); d = BigComplex.CQ( a, BigComplex.ONE ); assertEquals("a/1 = a",d,a); a = BigComplex.CRAND( 100 ); b = BigComplex.CINV( a ); c = BigComplex.CPROD( a, b ); assertTrue("a*1/a = 1", c.isONE() ); } /** * Test distributive law. * */ public void testDistributive() { BigComplex fac = new BigComplex(); a = fac.random( 500 ); b = fac.random( 500 ); c = fac.random( 500 ); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } } jas-2.5/trc/edu/jas/arith/ProductTest.java0000644000175000017500000003546011641660762020740 0ustar giovannigiovanni /* * $Id: ProductTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.arith; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.structure.RingFactory; /** * Product test with JUnit. * @author Heinz Kredel. */ public class ProductTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ProductTest object. * @param name String. */ public ProductTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ProductTest.class); return suite; } ProductRing fac; ModIntegerRing pfac; ProductRing mfac; ProductRing ifac; Product< BigRational > a; Product< BigRational > b; Product< BigRational > c; Product< BigRational > d; Product< BigRational > e; Product< BigRational > f; Product< ModInteger > ap; Product< ModInteger > bp; Product< ModInteger > cp; Product< ModInteger > dp; Product< ModInteger > ep; Product< ModInteger > fp; Product< BigInteger > ai; Product< BigInteger > bi; Product< BigInteger > ci; Product< BigInteger > di; Product< BigInteger > ei; Product< BigInteger > fi; int pl = 5; int rl = 1; int kl = 13; int ll = 7; int el = 3; float q = 0.9f; int il = 2; //long p = 1152921504606846883L; // 2^60-93; protected void setUp() { a = b = c = d = e = null; ap = bp = cp = dp = ep = null; ai = bi = ci = di = ei = null; BigRational cfac = new BigRational(2,3); fac = new ProductRing( cfac, pl ); List> lpfac = new ArrayList>(); pfac = new ModIntegerRing( 2 ); lpfac.add(pfac); pfac = new ModIntegerRing( 3 ); lpfac.add(pfac); pfac = new ModIntegerRing( 5 ); lpfac.add(pfac); pfac = new ModIntegerRing( 7 ); lpfac.add(pfac); mfac = new ProductRing( lpfac ); BigInteger cifac = new BigInteger(3); ifac = new ProductRing( cifac, pl ); } protected void tearDown() { a = b = c = d = e = null; ap = bp = cp = dp = ep = null; ai = bi = ci = di = ei = null; fac = null; pfac = null; mfac = null; ifac = null; } /** * Test constructor for rational. * */ public void testRatConstruction() { c = fac.getONE(); //System.out.println("c = " + c); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); //System.out.println("d = " + d); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test constructor for modular. * */ public void testModConstruction() { cp = mfac.getONE(); //System.out.println("cp = " + cp); assertTrue("isZERO( cp )", !cp.isZERO() ); assertTrue("isONE( cp )", cp.isONE() ); dp = mfac.getZERO(); //System.out.println("dp = " + dp); assertTrue("isZERO( dp )", dp.isZERO() ); assertTrue("isONE( dp )", !dp.isONE() ); } /** * Test random rational. * */ public void testRatRandom() { for (int i = 0; i < 7; i++) { a = fac.random(kl*(i+1)); if ( a.isZERO() ) { continue; } assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); a = fac.random( kl, q ); if ( a.isZERO() ) { continue; } //System.out.println("a = " + a); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test random modular. * */ public void testModRandom() { for (int i = 0; i < 7; i++) { ap = mfac.random(kl,q); if ( ap.isZERO() || ap.isONE() ) { continue; } //System.out.println("ap = " + ap); assertTrue(" not isZERO( ap"+i+" )", !ap.isZERO() ); assertTrue(" not isONE( ap"+i+" )", !ap.isONE() ); } } /** * Test rational addition. * */ public void testRatAddition() { a = fac.random(kl,q); b = fac.random(kl,q); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a",c,d); //System.out.println("c = " + c); //System.out.println("d = " + d); c = fac.random(kl,q); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); //System.out.println("c = " + c); //System.out.println("d = " + d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); //System.out.println("c = " + c); //System.out.println("d = " + d); } /** * Test integer addition. * */ public void testIntAddition() { ai = ifac.random(kl,q); bi = ifac.random(kl,q); ci = ai.sum(bi); di = ci.subtract(bi); assertEquals("a+b-b = a",ai,di); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); ci = ai.sum(bi); di = bi.sum(ai); assertEquals("a+b = b+a",ci,di); //System.out.println("c = " + c); //System.out.println("d = " + d); ci = ifac.random(kl,q); di = ci.sum( ai.sum(bi) ); ei = ci.sum( ai ).sum(bi); assertEquals("c+(a+b) = (c+a)+b",di,ei); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); ci = ai.sum( ifac.getZERO() ); di = ai.subtract( ifac.getZERO() ); assertEquals("a+0 = a-0",ci,di); //System.out.println("c = " + c); //System.out.println("d = " + d); ci = ifac.getZERO().sum( ai ); di = ifac.getZERO().subtract( ai.negate() ); assertEquals("0+a = 0+(-a)",ci,di); //System.out.println("c = " + c); //System.out.println("d = " + d); } /** * Test modular addition. * */ public void testModAddition() { ap = mfac.random(kl,q); bp = mfac.random(kl,q); //System.out.println("a = " + a); //System.out.println("b = " + b); cp = ap.sum(bp); dp = cp.subtract(bp); assertEquals("a+b-b = a",ap,dp); cp = ap.sum(bp); dp = bp.sum(ap); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",cp,dp); cp = mfac.random(kl,q); dp = cp.sum( ap.sum(bp) ); ep = cp.sum( ap ).sum(bp); assertEquals("c+(a+b) = (c+a)+b",dp,ep); cp = ap.sum( mfac.getZERO() ); dp = ap.subtract( mfac.getZERO() ); assertEquals("a+0 = a-0",cp,dp); cp = mfac.getZERO().sum( ap ); dp = mfac.getZERO().subtract( ap.negate() ); assertEquals("0+a = 0+(-a)",cp,dp); } /** * Test rational multiplication. * */ public void testRatMultiplication() { a = fac.random(kl); if ( a.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(kl,q); if ( b.isZERO() ) { return; } assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); //assertTrue("not isZERO( c )", !c.isZERO() ); //assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(kl,q); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.divide(b); d = a.remainder(b); e = c.multiply(b).sum(d); f = a.multiply( e.idempotent() ); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("f = " + f); assertEquals("a = (a/b)c+d ",e,f); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); b = a.idempotent(); c = a.idemComplement(); d = b.multiply(c); assertEquals("idem(a)*idemComp(a) = 0",d,fac.getZERO()); d = b.sum(c); assertEquals("idem(a)+idemComp(a) = 1",d,fac.getONE()); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); e = a.idempotent(); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("a*1/a = 1",e,d); } } /** * Test integer multiplication. * */ public void testIntMultiplication() { ai = ifac.random(kl); while ( ai.isZERO() ) { ai = ifac.random(kl); } assertTrue("not isZERO( a )", !ai.isZERO() ); bi = ifac.random(kl,q); if ( bi.isZERO() ) { bi = ifac.random(kl,q); } assertTrue("not isZERO( b )", !bi.isZERO() ); ci = bi.multiply(ai); di = ai.multiply(bi); //assertTrue("not isZERO( c )", !c.isZERO() ); //assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + ai); //System.out.println("b = " + bi); ei = di.subtract(ci); assertTrue("isZERO( a*b-b*a ) " + ei, ei.isZERO() ); assertTrue("a*b = b*a", ci.equals(di) ); assertEquals("a*b = b*a",ci,di); ci = ifac.random(kl,q); //System.out.println("c = " + ci); di = ai.multiply( bi.multiply(ci) ); ei = (ai.multiply(bi)).multiply(ci); //System.out.println("d = " + di); //System.out.println("e = " + ei); //System.out.println("d-e = " + di.subtract(ci) ); assertEquals("a(bc) = (ab)c",di,ei); assertTrue("a(bc) = (ab)c", di.equals(ei) ); ci = ai.divide(bi); di = ai.remainder(bi); ei = ci.multiply(bi).sum(di); fi = ai.multiply( ei.idempotent() ); //System.out.println("c = " + ci); //System.out.println("d = " + di); //System.out.println("e = " + ei); //System.out.println("f = " + fi); assertEquals("a = (a/b)c+d ",ei,fi); ci = ai.gcd(bi); di = ai.remainder(ci); ei = bi.remainder(ci); //System.out.println("c = " + ci); //System.out.println("d = " + di); //System.out.println("e = " + ei); assertTrue("gcd(a,b) | a ",di.isZERO()); assertTrue("gcd(a,b) | b ",ei.isZERO()); Product< BigInteger >[] gcd; gcd = ai.egcd(bi); ci = gcd[0]; di = ai.remainder(ci); ei = bi.remainder(ci); //System.out.println(); //System.out.println("c = " + ci); //System.out.println("d = " + di); //System.out.println("e = " + ei); assertTrue("gcd(a,b) | a ",di.isZERO()); assertTrue("gcd(a,b) | b ",ei.isZERO()); di = ai.multiply(gcd[1]); ei = bi.multiply(gcd[2]); fi = di.sum(ei); //System.out.println("c = " + ci); //System.out.println("c1= " + gcd[1]); //System.out.println("c2= " + gcd[2]); //System.out.println("d = " + di); //System.out.println("e = " + ei); //System.out.println("f = " + fi); assertEquals("gcd(a,b) = c1*a + c2*b ",ci,fi); ci = ai.multiply( ifac.getONE() ); di = ifac.getONE().multiply( ai ); assertEquals("a*1 = 1*a",ci,di); bi = ai.idempotent(); ci = ai.idemComplement(); di = bi.multiply(ci); assertEquals("idem(a)*idemComp(a) = 0",di,ifac.getZERO()); di = bi.sum(ci); assertEquals("idem(a)+idemComp(a) = 1",di,ifac.getONE()); if ( ai.isUnit() ) { ci = ai.inverse(); di = ci.multiply(ai); ei = ai.idempotent(); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("a*1/a = 1",ei,di); } } /** * Test modular multiplication. * */ public void testModMultiplication() { ap = mfac.random(kl,q); if ( ap.isZERO() ) { return; } assertTrue("not isZERO( a )", !ap.isZERO() ); bp = mfac.random(kl,q); if ( bp.isZERO() ) { return; } assertTrue("not isZERO( b )", !bp.isZERO() ); cp = bp.multiply(ap); dp = ap.multiply(bp); //assertTrue("not isZERO( c )", !cp.isZERO() ); //assertTrue("not isZERO( d )", !dp.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); ep = dp.subtract(cp); assertTrue("isZERO( a*b-b*a ) " + ep, ep.isZERO() ); assertTrue("a*b = b*a", cp.equals(dp) ); assertEquals("a*b = b*a",cp,dp); cp = mfac.random(kl,q); //System.out.println("c = " + c); dp = ap.multiply( bp.multiply(cp) ); ep = (ap.multiply(bp)).multiply(cp); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",dp,ep); assertTrue("a(bc) = (ab)c", dp.equals(ep) ); cp = ap.divide(bp); dp = ap.remainder(bp); ep = cp.multiply(bp).sum(dp); fp = ap.multiply( ep.idempotent() ); //System.out.println("cp = " + cp); //System.out.println("dp = " + dp); //System.out.println("ep = " + ep); //System.out.println("fp = " + fp); assertEquals("a = (a/b)c+d ",ep,fp); cp = ap.multiply( mfac.getONE() ); dp = mfac.getONE().multiply( ap ); assertEquals("a*1 = 1*a",cp,dp); bp = ap.idempotent(); cp = ap.idemComplement(); dp = bp.multiply(cp); assertEquals("idem(a)*idemComp(a) = 0",dp,mfac.getZERO()); dp = bp.sum(cp); assertEquals("idem(a)+idemComp(a) = 1",dp,mfac.getONE()); if ( ap.isUnit() ) { cp = ap.inverse(); dp = cp.multiply(ap); ep = ap.idempotent(); //System.out.println("ap = " + ap); //System.out.println("cp = " + cp); //System.out.println("dp = " + dp); //System.out.println("ep = " + ep); assertEquals("a*1/a = 1",ep,dp); } } } jas-2.5/trc/edu/jas/arith/BigRationalTest.java0000644000175000017500000001536312002722436021500 0ustar giovannigiovanni/* * $Id: BigRationalTest.java 4014 2012-07-22 07:00:47Z kredel $ */ package edu.jas.arith; import java.util.Iterator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * BigRational tests with JUnit. * @author Heinz Kredel. */ public class BigRationalTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a BigRationalTest object. * @param name String. */ public BigRationalTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(BigRationalTest.class); return suite; } BigRational a; BigRational b; BigRational c; BigRational d; BigRational e; protected void setUp() { a = b = c = d = e = null; } protected void tearDown() { a = b = c = d = e = null; } /** * Test static initialization and constants. * */ public void testConstants() { a = BigRational.ZERO; b = BigRational.ONE; c = BigRational.RNDIF(b,b); assertEquals("1-1 = 0",c,a); assertTrue("1-1 = 0",c.isZERO()); assertTrue("1 = 1", b.isONE() ); a = BigRational.ZERO; b = BigRational.ONE; c = BigRational.RNDIF(b,b); assertEquals("1-1 = 0",c,a); } /** * Test constructor and toString. * */ public void testConstructor() { a = new BigRational( "6/8" ); b = new BigRational( "3/4" ); assertEquals("6/8 = 3/4",a,b); a = new BigRational( "3/-4" ); b = new BigRational( "-3/4" ); assertEquals("3/-4 = -3/4",a,b); String s = "6/1111111111111111111111111111111111111111111"; a = new BigRational( s ); String t = a.toString(); assertEquals("stringConstr = toString",s,t); a = new BigRational( 1 ); b = new BigRational( -1 ); c = BigRational.RNSUM(b,a); assertTrue("1 = 1", a.isONE() ); assertEquals("1+(-1) = 0",c,BigRational.ZERO); s = "1.500000000"; a = new BigRational( s ); b = new BigRational( "3/2" ); assertEquals("decimalConstr = b ",a,b); s = "-1.500000000"; a = new BigRational( s ); b = new BigRational( "-3/2" ); assertEquals("decimalConstr = b ",a,b); s = "0.750000000"; a = new BigRational( s ); b = new BigRational( "3/4" ); assertEquals("decimalConstr = b ",a,b); s = "0.333333333"; a = new BigRational( s ); t = a.toString(9); assertEquals("decimalConstr = b " + t,s,t); s = "-0.000033333"; a = new BigRational( s ); t = a.toString(9); assertEquals("decimalConstr = b " + t,s,t); //System.out.println("a = " + a); } /** * Test random rationals. * */ public void testRandom() { a = BigRational.RNRAND( 500 ); b = new BigRational( "" + a ); c = BigRational.RNDIF(b,a); assertEquals("a-b = 0",c,BigRational.ZERO); d = new BigRational( b.numerator(), b.denominator() ); assertEquals("sign(a-a) = 0", 0, b.compareTo(d) ); } /** * Test addition. * */ public void testAddition() { a = BigRational.RNRAND( 100 ); b = BigRational.RNSUM( a, a ); c = BigRational.RNDIF( b, a ); assertEquals("a+a-a = a",c,a); assertEquals("a+a-a = a",0,BigRational.RNCOMP(c,a)); d = BigRational.RNSUM( a, BigRational.ZERO ); assertEquals("a+0 = a",d,a); d = BigRational.RNDIF( a, BigRational.ZERO ); assertEquals("a-0 = a",d,a); d = BigRational.RNDIF( a, a ); assertEquals("a-a = 0",d,BigRational.ZERO); } /** * Test multiplication. * */ public void testMultiplication() { a = BigRational.RNRAND( 100 ); b = BigRational.RNPROD( a, a ); c = BigRational.RNQ( b, a ); assertEquals("a*a/a = a",c,a); assertEquals("a*a/a = a",0,BigRational.RNCOMP(c,a)); d = BigRational.RNPROD( a, BigRational.ONE ); assertEquals("a*1 = a",d,a); d = BigRational.RNQ( a, BigRational.ONE ); assertEquals("a/1 = a",d,a); a = BigRational.RNRAND( 100 ); b = BigRational.RNINV( a ); c = BigRational.RNPROD( a, b ); assertTrue("a*1/a = 1", c.isONE() ); } /** * Test distributive law. * */ public void testDistributive() { BigRational fac = new BigRational(); a = fac.random( 500 ); b = fac.random( 500 ); c = fac.random( 500 ); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } /** * Test iterator. */ public void testIterator() { int t = 0; BigRational bi = new BigRational(); bi.setAllIterator(); BigRational j = null, elem = null; for ( BigRational i : bi ) { t++; //System.out.println("i = " + i); if ( t >= 20 ) { j = i; break; } } assertFalse("j == null ", j == null); elem = new BigRational(-2,3); assertTrue("j == 10 ", j.equals(elem) ); } /** * Test non-negative iterator. */ public void testNNIterator() { int t = 0; BigRational bi = new BigRational(); bi.setNonNegativeIterator(); BigRational j = null, elem = null; Iterator iter = bi.iterator(); while ( iter.hasNext() ) { BigRational i = iter.next(); t++; //System.out.println("i = " + i); if ( t >= 20 ) { j = i; break; } } assertFalse("j == null ", j == null); elem = new BigRational(4,3); assertTrue("j == 10 ", j.equals(elem) ); } /** * Test non-negative unique iterator. */ public void testUniqueNNIterator() { int t = 0; BigRational bi = new BigRational(); bi.setNonNegativeIterator(); //bi.setAllIterator(); BigRational j = null, elem = null; Iterator iter = bi.uniqueIterator(); while ( iter.hasNext() ) { BigRational i = iter.next(); t++; //System.out.println("i = " + i); if ( t >= 20 ) { j = i; break; } } assertFalse("j == null ", j == null); elem = new BigRational(5,3); assertTrue("j == 10 ", j.equals(elem) ); } } jas-2.5/trc/edu/jas/arith/BigQuaternionTest.java0000644000175000017500000001061311641660762022060 0ustar giovannigiovanni/* * $Id: BigQuaternionTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.arith; //import edu.jas.arith.BigRational; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * BigQuaternion tests with JUnit. * @author Heinz Kredel. */ public class BigQuaternionTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a BigQuaternionTest object. * @param name String. */ public BigQuaternionTest(String name) { super(name); } /** */ /** * @return suite. */ public static Test suite() { TestSuite suite= new TestSuite(BigQuaternionTest.class); return suite; } BigQuaternion a; BigQuaternion b; BigQuaternion c; BigQuaternion d; BigQuaternion e; BigQuaternion fac; protected void setUp() { a = b = c = d = e = null; fac = new BigQuaternion(); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test static initialization and constants. * */ public void testConstants() { a = BigQuaternion.ZERO; b = BigQuaternion.ONE; c = b.subtract(b); assertEquals("1-1 = 0",c,a); assertTrue("1-1 = 0",c.isZERO()); assertTrue("1 = 1", b.isONE() ); a = BigQuaternion.ZERO; b = BigQuaternion.ONE; c = b.subtract(b); assertEquals("1-1 = 0",c,a); } /** * Test constructor and toString. * */ public void testConstructor() { a = new BigQuaternion( "6/8" ); b = new BigQuaternion( "3/4" ); assertEquals("6/8 = 3/4",a,b); a = new BigQuaternion( "3/4 i 4/5 j 1/5 k 2/5" ); b = new BigQuaternion( "-3/4 i -4/5 j -1/5 k -2/5" ); assertEquals("3/4 + i 4/5 + j 1/5 + k 2/5",a,b.negate()); String s = "6/1111111111111111111111111111111111111111111"; a = new BigQuaternion( s ); String t = a.toString(); assertEquals("stringConstr = toString",s,t); a = new BigQuaternion( 1 ); b = new BigQuaternion( -1 ); c = b.sum(a); assertTrue("1 = 1", a.isONE() ); assertEquals("1+(-1) = 0",c,BigQuaternion.ZERO); } /** * Test random rationals. * */ public void testRandom() { a = fac.random( 500 ); b = new BigQuaternion( a.getRe(), a.getIm(), a.getJm(), a.getKm() ); c = b.subtract(a); assertEquals("a-b = 0",BigQuaternion.ZERO,c); d = new BigQuaternion( b.getRe(), b.getIm(), b.getJm(), b.getKm() ); assertEquals("sign(a-a) = 0", 0, b.compareTo(d) ); } /** * Test addition. * */ public void testAddition() { a = fac.random( 100 ); b = a.sum( a ); c = b.subtract( a ); assertEquals("a+a-a = a",c,a); assertEquals("a+a-a = a",0,c.compareTo(a)); d = a.sum( BigQuaternion.ZERO ); assertEquals("a+0 = a",d,a); d = a.subtract( BigQuaternion.ZERO ); assertEquals("a-0 = a",d,a); d = a.subtract( a ); assertEquals("a-a = 0",d,BigQuaternion.ZERO); } /** * Test multiplication. * */ public void testMultiplication() { a = fac.random( 100 ); b = a.multiply( a ); c = b.divide( a ); assertEquals("a*a/a = a",c,a); assertEquals("a*a/a = a",0,c.compareTo(a)); d = a.multiply( BigQuaternion.ONE ); assertEquals("a*1 = a",d,a); d = a.divide( BigQuaternion.ONE ); assertEquals("a/1 = a",d,a); a = fac.random( 100 ); b = a.inverse(); c = a.multiply( b ); assertTrue("a*1/a = 1", c.isONE() ); b = a.abs(); c = b.inverse(); d = b.multiply( c ); assertTrue("abs(a)*1/abs(a) = 1", d.isONE() ); b = a.abs(); c = a.conjugate(); d = a.multiply( c ); assertEquals("abs(a)^2 = a a^", b, d ); } /** * Test multiplication axioms. * */ public void testMultiplicationAxioms() { a = fac.random( 100 ); b = fac.random( 100 ); c = a.multiply( b ); d = b.multiply( a ); assertTrue("a*b != b*a",!c.equals(d)); c = fac.random( 100 ); d = a.multiply( b.multiply( c ) ); e = a.multiply( b ).multiply( c ); assertTrue("a(bc) = (ab)c",e.equals(d)); } /** * Test distributive law. * */ public void testDistributive() { a = fac.random( 20 ); b = fac.random( 20 ); c = fac.random( 20 ); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } } jas-2.5/trc/edu/jas/arith/BigOctonionTest.java0000644000175000017500000001121611641660762021523 0ustar giovannigiovanni/* * $Id: BigOctonionTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.arith; //import edu.jas.arith.BigRational; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * BigOctonion tests with JUnit. * @author Heinz Kredel. */ public class BigOctonionTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a BigOctonionTest object. * @param name String. */ public BigOctonionTest(String name) { super(name); } /** */ /** * @return suite. */ public static Test suite() { TestSuite suite= new TestSuite(BigOctonionTest.class); return suite; } BigOctonion a; BigOctonion b; BigOctonion c; BigOctonion d; BigOctonion e; BigOctonion fac; protected void setUp() { a = b = c = d = e = null; fac = new BigOctonion(); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test static initialization and constants. * */ public void testConstants() { a = BigOctonion.ZERO; b = BigOctonion.ONE; c = b.subtract(b); assertEquals("1-1 = 0",c,a); assertTrue("1-1 = 0",c.isZERO()); assertTrue("1 = 1", b.isONE() ); a = BigOctonion.ZERO; b = BigOctonion.ONE; c = b.subtract(b); assertEquals("1-1 = 0",c,a); } /** * Test constructor and toString. * */ public void testConstructor() { a = new BigOctonion( "6/8" ); b = new BigOctonion( "3/4" ); assertEquals("6/8 = 3/4",a,b); a = new BigOctonion( "3/4 i 4/5 j 1/5 k 2/5" ); b = new BigOctonion( "-3/4 i -4/5 j -1/5 k -2/5" ); assertEquals("3/4 + i 4/5 + j 1/5 + k 2/5",a,b.negate()); String s = "6/1111111111111111111111111111111111111111111"; a = new BigOctonion( s ); String t = a.toString(); assertEquals("stringConstr = toString",s,t); String sr = "3/4 i 4/5 j 1/5 k 2/5"; String si = "-3/4 i -4/5 j -1/5 k -2/5"; s = sr + " o " + si; a = new BigOctonion( s ); BigQuaternion qr = new BigQuaternion( sr ); BigQuaternion qi = new BigQuaternion( si ); b = new BigOctonion( qr, qi ); assertEquals("s = "+s,a,b); a = new BigOctonion( 1 ); b = new BigOctonion( -1 ); c = b.sum(a); assertTrue("1 = 1", a.isONE() ); assertEquals("1+(-1) = 0",c,BigOctonion.ZERO); } /** * Test random rationals. * */ public void testRandom() { a = fac.random( 100 ); b = new BigOctonion( a.getR(), a.getI() ); c = b.subtract(a); assertEquals("a-b = 0",BigOctonion.ZERO,c); d = new BigOctonion( b.getR(), b.getI() ); assertEquals("sign(a-a) = 0", 0, b.compareTo(d) ); } /** * Test addition. * */ public void testAddition() { a = fac.random( 50 ); b = a.sum( a ); c = b.subtract( a ); assertEquals("a+a-a = a",c,a); assertEquals("a+a-a = a",0,c.compareTo(a)); d = a.sum( BigOctonion.ZERO ); assertEquals("a+0 = a",d,a); d = a.subtract( BigOctonion.ZERO ); assertEquals("a-0 = a",d,a); d = a.subtract( a ); assertEquals("a-a = 0",d,BigOctonion.ZERO); } /** * Test multiplication. * */ public void testMultiplication() { a = fac.random( 30 ); //System.out.println("a = " + a); b = a.multiply( a ); c = b.divide( a ); assertEquals("a*a/a = a",c,a); assertEquals("a*a/a = a",0,c.compareTo(a)); d = a.multiply( BigOctonion.ONE ); assertEquals("a*1 = a",d,a); d = a.divide( BigOctonion.ONE ); assertEquals("a/1 = a",d,a); a = fac.random( 30 ); b = a.inverse(); c = a.multiply( b ); assertTrue("a*1/a = 1", c.isONE() ); b = a.abs(); c = b.inverse(); d = b.multiply( c ); assertTrue("abs(a)*1/abs(a) = 1", d.isONE() ); a = fac.random( 3 ); b = a.abs(); c = a.conjugate(); d = a.multiply( c ); assertEquals("abs(a)^2 = a a^", b, d ); } /** * Test multiplication axioms. * */ public void testMultiplicationAxioms() { a = fac.random( 20 ); b = fac.random( 20 ); c = a.multiply( b ); d = b.multiply( a ); assertTrue("a*b != b*a",!c.equals(d)); c = fac.random( 20 ); d = a.multiply( b.multiply( c ) ); e = a.multiply( b ).multiply( c ); assertTrue("a(bc) != (ab)c",!e.equals(d)); } /** * Test distributive law. * */ public void testDistributive() { a = fac.random( 20 ); b = fac.random( 20 ); c = fac.random( 20 ); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } } jas-2.5/trc/edu/jas/kern/0000755000175000017500000000000012140140260015412 5ustar giovannigiovannijas-2.5/trc/edu/jas/kern/TimeStatusTest.java0000644000175000017500000000561111641660762021245 0ustar giovannigiovanni/* * $Id: TimeStatusTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.kern; import java.util.concurrent.Callable; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; /** * TimeStatus tests with JUnit. * @author Heinz Kredel */ public class TimeStatusTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a TimeStatusTest object. * @param name String. */ public TimeStatusTest(String name) { super(name); } /* */ public static Test suite() { TestSuite suite = new TestSuite(TimeStatusTest.class); return suite; } @Override protected void setUp() { } @Override protected void tearDown() { TimeStatus.setNotActive(); TimeStatus.setLimit(Long.MAX_VALUE); TimeStatus.setCallBack((Callable) null); } /** * Tests checkTime. */ public void testCheckTime() { TimeStatus.setActive(); assertTrue("is active ", TimeStatus.isActive()); TimeStatus.restart(); try { TimeStatus.checkTime("test1"); // succeed } catch (TimeExceededException e) { fail("test1 " + e); } TimeStatus.setLimit(0L); assertTrue("is active ", TimeStatus.isActive()); try { Thread.sleep(10); TimeStatus.checkTime("test2"); fail("test2 checkTime"); } catch (TimeExceededException e) { // succeed } catch (InterruptedException e) { fail("test2 interrupt"); } } /** * Tests call back. */ public void testCallBack() { TimeStatus.setActive(); TimeStatus.restart(); TimeStatus.setLimit(0L); TimeStatus.setCallBack(new TSCallMock(true)); assertTrue("is active ", TimeStatus.isActive()); try { Thread.sleep(10); TimeStatus.checkTime("test3"); // succeed } catch (TimeExceededException e) { fail("test3 checkTime"); } catch (InterruptedException e) { fail("test3 interrupt"); } TimeStatus.setCallBack(new TSCallMock(false)); try { Thread.sleep(10); TimeStatus.checkTime("test4"); fail("test4 checkTime"); } catch (TimeExceededException e) { // succeed } catch (InterruptedException e) { fail("test4 interrupt"); } } } class TSCallMock implements Callable { boolean flag = true; public TSCallMock(boolean b) { flag = b; } public Boolean call() { return flag; } } jas-2.5/trc/edu/jas/util/0000755000175000017500000000000012140140260015430 5ustar giovannigiovannijas-2.5/trc/edu/jas/util/ThreadPoolTest.java0000644000175000017500000000741011641660762021221 0ustar giovannigiovanni/* * $Id: ThreadPoolTest.java 3789 2011-10-01 18:54:43Z kredel $ */ //package edu.unima.ky.parallel; package edu.jas.util; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; /** * ThreadPool tests with JUnit. * @author Akitoshi Yoshida * @author Heinz Kredel */ public class ThreadPoolTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ThreadPoolTest object. * @param name String. */ public ThreadPoolTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(ThreadPoolTest.class); return suite; } static final int JOBS = 10; // number of jobs to start private ThreadPool p1; protected void setUp() { } protected void tearDown() { p1.terminate(); } /** * Tests if the created ThreadPool is empty. */ public void testThreadPool1() { p1 = new ThreadPool(0); assertTrue( "not empty pool ", p1.getNumber() == 0 ); } /** * Tests if the created ThreadPool is non empty. */ public void testThreadPool2() { p1 = new ThreadPool(1); //p1.init(); assertTrue( "# empty pool ", p1.getNumber() == 1 ); p1.terminate(); p1 = new ThreadPool(); //p1.init(); assertTrue( "# empty pool ", p1.getNumber() == ThreadPool.DEFAULT_SIZE ); p1.terminate(); p1 = new ThreadPool(10); //p1.init(); assertTrue( "# empty pool ", p1.getNumber() == 10 ); p1.terminate(); } /** * Tests if the created ThreadPool has no jobs. */ public void testThreadPool3() { p1 = new ThreadPool(); assertFalse( "no jobs ", p1.hasJobs() ); assertFalse( "more than 0 jobs ", p1.hasJobs(0) ); p1.terminate(); } /** * Tests if the created ThreadPool has jobs. */ public void testThreadPool4() { p1 = new ThreadPool(); assertFalse( "no jobs ", p1.hasJobs() ); for (int i = 0; i < JOBS*p1.getNumber(); i++ ) { p1.addJob( new FastWorker() ); } boolean j = p1.hasJobs(); assertTrue( "more than 0 jobs ", (j | true) ); // stupid p1.terminate(); assertFalse( "no jobs ", p1.hasJobs() ); } /** * Tests if the created ThreadPool has many jobs. */ public void testThreadPool5() { p1 = new ThreadPool(); //p1.init(); assertFalse( "no jobs ", p1.hasJobs() ); for (int i = 0; i < JOBS*p1.getNumber(); i++ ) { p1.addJob( new SlowWorker() ); } assertTrue( "more than 10 jobs ", p1.hasJobs(JOBS) ); p1.terminate(); assertFalse( "no jobs ", p1.hasJobs() ); } /** * Tests if the created ThreadPool has correct strategy. */ public void testThreadPool6() { p1 = new ThreadPool(StrategyEnumeration.LIFO); assertTrue( "FIFO strategy ", p1.getStrategy() == StrategyEnumeration.LIFO ); } /** * Tests if the created ThreadPool has jobs and correct strategy. */ public void testThreadPool7() { p1 = new ThreadPool(StrategyEnumeration.LIFO); assertFalse( "no jobs ", p1.hasJobs() ); for (int i = 0; i < JOBS*p1.getNumber(); i++ ) { p1.addJob( new FastWorker() ); } boolean j = p1.hasJobs(); assertTrue( "more than 0 jobs ", (j | true) ); // stupid p1.terminate(); assertFalse( "no jobs ", p1.hasJobs() ); } } /** * Utility class for ThreadPool Test. */ class FastWorker implements Runnable { public void run() { } } /** * Utility class for ThreadPool Test. */ class SlowWorker implements Runnable { public void run() { try { Thread.sleep(10); } catch (InterruptedException e ) { } } } jas-2.5/trc/edu/jas/util/DistThreadPoolTest.java0000644000175000017500000001050411641660762022043 0ustar giovannigiovanni/* * $Id: DistThreadPoolTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.util; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import edu.unima.ky.parallel.ChannelFactory; /** * DistThreadPool tests with JUnit. * @author Akitoshi Yoshida * @author Heinz Kredel */ public class DistThreadPoolTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a DistThreadPoolTest object. * @param name String. */ public DistThreadPoolTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(DistThreadPoolTest.class); return suite; } //private static final String host = "localhost"; private static final int port = ChannelFactory.DEFAULT_PORT; //private static final String mfile = "machines.test"; private ExecutableServer es; private DistThreadPool pool; static final int JOBS = 10; // number of jobs to start protected void setUp() { es = new ExecutableServer(port); es.init(); } protected void tearDown() { pool.terminate(); es.terminate(); } /** * Tests if the created DistThreadPool is empty. */ public void testDistThreadPool1() { pool = new DistThreadPool(0); assertTrue( "not empty pool ", pool.getNumber() == 0 ); } /** * Tests if the created DistThreadPool is non empty. */ public void testDistThreadPool2() { pool = new DistThreadPool(1); assertTrue( "# empty pool ", pool.getNumber() == 1 ); pool.terminate(); pool = new DistThreadPool(); assertTrue( "# empty pool ", pool.getNumber() == DistThreadPool.DEFAULT_SIZE ); pool.terminate(); pool = new DistThreadPool(10); assertTrue( "# empty pool ", pool.getNumber() == 10 ); pool.terminate(); } /** * Tests if the created DistThreadPool has no jobs. */ public void testDistThreadPool3() { pool = new DistThreadPool(); assertFalse( "no jobs ", pool.hasJobs() ); assertFalse( "more than 0 jobs ", pool.hasJobs(0) ); pool.terminate(); } /** * Tests if the created DistThreadPool has jobs. */ public void testDistThreadPool4() { pool = new DistThreadPool(); assertFalse( "no jobs ", pool.hasJobs() ); for (int i = 0; i < JOBS*pool.getNumber(); i++ ) { pool.addJob( new DistFastWorker() ); } boolean j = pool.hasJobs(); assertTrue( "more than 0 jobs ", (j | true) ); // stupid pool.terminate(); assertFalse( "no jobs ", pool.hasJobs() ); } /** * Tests if the created DistThreadPool has many jobs. */ public void testDistThreadPool5() { pool = new DistThreadPool(); assertFalse( "no jobs ", pool.hasJobs() ); for (int i = 0; i < JOBS*pool.getNumber(); i++ ) { pool.addJob( new DistSlowWorker() ); } assertTrue( "more than 10 jobs ", pool.hasJobs(JOBS) ); pool.terminate(); assertFalse( "no jobs ", pool.hasJobs() ); } /** * Tests if the created DistThreadPool has correct strategy. */ public void testDistThreadPool6() { pool = new DistThreadPool(StrategyEnumeration.LIFO); assertTrue( "FIFO strategy ", pool.getStrategy() == StrategyEnumeration.LIFO ); } /** * Tests if the created DistThreadPool has jobs and correct strategy. */ public void testDistThreadPool7() { pool = new DistThreadPool(StrategyEnumeration.LIFO); assertFalse( "no jobs ", pool.hasJobs() ); for (int i = 0; i < JOBS*pool.getNumber(); i++ ) { pool.addJob( new DistFastWorker() ); } boolean j = pool.hasJobs(); assertTrue( "more than 0 jobs ", (j | true) ); // stupid pool.terminate(); assertFalse( "no jobs ", pool.hasJobs() ); } } /** * Utility class for DistThreadPool Test. */ class DistFastWorker implements RemoteExecutable { public void run() { try { Thread.sleep(0); } catch (InterruptedException e ) { } } } /** * Utility class for DistThreadPool Test. */ class DistSlowWorker implements RemoteExecutable { public void run() { try { Thread.sleep(10); } catch (InterruptedException e ) { } } } jas-2.5/trc/edu/jas/util/ExecutableServerTest.java0000644000175000017500000001052012004734512022411 0ustar giovannigiovanni/* * $Id: ExecutableServerTest.java 4074 2012-07-28 10:04:58Z kredel $ */ package edu.jas.util; import java.io.IOException; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; //import edu.unima.ky.parallel.ChannelFactory; //import edu.unima.ky.parallel.SocketChannel; /** * ExecutableServer tests with JUnit. * @author Heinz Kredel */ public class ExecutableServerTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ExecutableServerTest object. * @param name String. */ public ExecutableServerTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ExecutableServerTest.class); return suite; } private static final String host = "localhost"; private static final int port = ChannelFactory.DEFAULT_PORT; private ExecutableServer es; private ChannelFactory cf; protected void setUp() { es = new ExecutableServer(port); es.init(); cf = new ChannelFactory(); } protected void tearDown() { es.terminate(); es = null; cf.terminate(); cf = null; } /** * Tests if the ExecutableServer could be started and terminated. */ public void testExecutableServer1() { assertTrue("should never fail", true ); } /** * Tests if the ExecutableServer can execute a RemoteExecutable. */ public void testExecutableServer2() { RemoteExecutable e1 = new Executable("2"); try { SocketChannel sc = cf.getChannel(host,port); sc.send( e1 ); Object o = sc.receive(); assertTrue("o:String", o instanceof String); assertEquals("o==done", (String)o, ExecutableServer.DONE ); sc.close(); } catch (IOException e) { e.printStackTrace(); fail("IOException"); } catch (ClassNotFoundException e) { e.printStackTrace(); fail("ClassNotFoundException"); } } /** * Tests if the ExecutableServer can execute more RemoteExecutable. */ public void testExecutableServer3() { RemoteExecutable e1 = new Executable("3"); int numloops = 1; // can be changed in ExecutableServer.run() Object o; try { SocketChannel sc = cf.getChannel(host,port); for (int i = 0; i < numloops; i++ ) { sc.send( e1 ); o = sc.receive(); assertTrue("o:String", o instanceof String); assertEquals("o==done", (String)o, ExecutableServer.DONE ); } sc.close(); } catch (IOException e) { e.printStackTrace(); fail("IOException"); } catch (ClassNotFoundException e) { e.printStackTrace(); fail("ClassNotFoundException"); } } /** * Tests if the ExecutableServer can execute a RemoteExecutable. */ public void testExecutableServer4() { RemoteExecutable e1 = null; SocketChannel sc = null; Object o; try { for (int i = 0; i < 4; i++ ) { e1 = new Executable("4-"+i); sc = cf.getChannel(host,port); sc.send( e1 ); o = sc.receive(); assertTrue("o:String", o instanceof String); assertEquals("o==done", (String)o, ExecutableServer.DONE ); e1 = null; sc.close(); sc = null; } } catch (IOException e) { e.printStackTrace(); fail("IOException"); } catch (ClassNotFoundException e) { e.printStackTrace(); fail("ClassNotFoundException"); } } } /** * Unit Test Class which implements interface RemoteExecutable. */ class Executable implements RemoteExecutable { private static final Logger logger = Logger.getLogger(Executable.class); private String param = null; /** * Executable. * @param param String. */ public Executable(String param) { this.param = param; } /** * run. */ public void run() { logger.debug(this + " has been run"); } /** * toString. */ public String toString() { return "Executable(" + param + ")"; } } jas-2.5/trc/edu/jas/util/PowerSetTest.java0000644000175000017500000001164111641660762020731 0ustar giovannigiovanni/* * $Id: PowerSetTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.util; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.Combinatoric; /** * PowerSet tests with JUnit. * @author Heinz Kredel. */ public class PowerSetTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a ListUtilTest object. * @param name String. */ public PowerSetTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(PowerSetTest.class); return suite; } BigInteger ai; @Override protected void setUp() { ai = null; } @Override protected void tearDown() { ai = null; } /** * Test iterator. * */ public void testIterator() { final int N = 10; ai = new BigInteger(); List list = new ArrayList(); for (int i = 0; i < N; i++) { list.add(ai.random(7)); } //System.out.println("list = " + list); PowerSet ps = new PowerSet(list); long i = 0; for (List subs : ps) { if (i < 0) { System.out.println("subs = " + subs); } if (subs != null) { assertTrue("size(subs) >= 0 ", subs.size() >= 0); i++; } } long j = 1; for (int k = 0; k < N; k++) { j *= 2; } assertEquals("size(ps) == 2**N ", i, j); } /** * Test k-subset iterator. * */ public void noTestKSubsetIterator() { final int N = 10; ai = new BigInteger(); List list = new ArrayList(); for (int i = 0; i < N; i++) { list.add(ai.random(7)); } System.out.println("list = " + list); KsubSet ks = new KsubSet(list, 0); long i = 0; for (List subs : ks) { if (i >= 0) { System.out.println("subs = " + subs); } if (subs != null) { assertTrue("size(subs) >= 0 ", subs.size() == 0); i++; } } long s = Combinatoric.binCoeff(N, 0).getVal().longValue(); assertEquals("size(ks) == " + s + " ", i, s); ks = new KsubSet(list, 1); i = 0; for (List subs : ks) { if (i >= 0) { System.out.println("subs = " + subs); } if (subs != null) { assertTrue("size(subs) >= 0 ", subs.size() == 1); i++; } } s = Combinatoric.binCoeff(N, 1).getVal().longValue(); assertEquals("size(ks) == " + s + " ", i, s); ks = new KsubSet(list, 2); i = 0; for (List subs : ks) { if (i >= 0) { System.out.println("subs = " + subs); } if (subs != null) { assertTrue("size(subs) >= 0 ", subs.size() == 2); i++; } } s = Combinatoric.binCoeff(N, 2).getVal().longValue(); assertEquals("size(ks) == " + s + " ", i, s); ks = new KsubSet(list, 3); i = 0; for (List subs : ks) { if (i >= 0) { System.out.println("subs = " + subs); } if (subs != null) { assertTrue("size(subs) >= 0 ", subs.size() == 3); i++; } } s = Combinatoric.binCoeff(N, 3).getVal().longValue(); assertEquals("size(ks) == " + s + " ", i, s); } /** * Test any k-subset iterator. * */ public void testAnyKSubsetIterator() { final int N = 10; ai = new BigInteger(); List list = new ArrayList(); for (int i = 0; i < N; i++) { list.add(ai.random(7)); } //System.out.println("list = " + list); for (int k = 0; k <= N; k++) { KsubSet ks = new KsubSet(list, k); long i = 0; for (List subs : ks) { if (i < 0) { System.out.println("subs = " + subs); } if (subs != null) { assertTrue("size(subs) >= 0 ", subs.size() == k); i++; } } long s = Combinatoric.binCoeff(N, k).getVal().longValue(); assertEquals("size(ks) == " + s + " ", i, s); } } } jas-2.5/trc/edu/jas/util/TaggedSocketChannelTest.java0000644000175000017500000001222612011705232022776 0ustar giovannigiovanni/* * $Id: TaggedSocketChannelTest.java 4093 2012-08-12 10:51:06Z kredel $ */ package edu.jas.util; import java.io.IOException; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; /** * TaggedSocketChannel tests with JUnit. * @author Heinz Kredel. */ public class TaggedSocketChannelTest extends TestCase { public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } public TaggedSocketChannelTest(String name) { super(name); } public static Test suite() { TestSuite suite= new TestSuite(TaggedSocketChannelTest.class); return suite; } private ChannelFactory cf; private SocketChannel sc1; private SocketChannel sc2; private TaggedSocketChannel tsc1; private TaggedSocketChannel tsc2; private String host; private int port; final Integer tag1 = Integer.valueOf(1); protected void setUp() { host = "localhost"; port = 4711; cf = new ChannelFactory(port); cf.init(); try { sc1 = cf.getChannel(host,port); sc2 = cf.getChannel(); tsc1 = new TaggedSocketChannel(sc1); tsc1.init(); tsc2 = new TaggedSocketChannel(sc2); tsc2.init(); } catch(IOException e) { fail("IOException"+e); } catch (InterruptedException e) { fail("InterruptedException"+e); } } protected void tearDown() { cf.terminate(); tsc1.close(); tsc2.close(); sc1.close(); sc2.close(); try { Thread.sleep(1); } catch(InterruptedException e) { fail("InterruptedException"+e); } } public void testTaggedSocketChannel0() { // test setUp() and tearDown() } public void testTaggedSocketChannel1() { Object o = new IllegalArgumentException("leer"); Integer err = Integer.valueOf(-1); try { tsc1.send(err,o); fail("no Exception thrown"); } catch(IOException e) { fail("Exception"+e); } catch(IllegalArgumentException e) { // ok } err = null; try { tsc1.send(err,o); fail("no Exception thrown"); } catch(IOException e) { fail("Exception"+e); } catch(IllegalArgumentException e) { // ok } } public void testTaggedSocketChannel2() { Object o = Integer.valueOf(0); try { tsc1.send(tag1,o); assertEquals(o,tsc2.receive(tag1)); } catch(IOException e) { fail("Exception"+e); } catch(InterruptedException e) { fail("Exception"+e); } catch(ClassNotFoundException e) { fail("Exception"+e); } } public void testTaggedSocketChannel3() { Object o = Integer.valueOf(0); try { tsc1.send(tag1,o); tsc2.send(tag1,o); assertEquals(o,tsc1.receive(tag1)); assertEquals(o,tsc2.receive(tag1)); } catch(IOException e) { fail("Exception"+e); } catch(InterruptedException e) { fail("Exception"+e); } catch(ClassNotFoundException e) { fail("Exception"+e); } } public void testTaggedSocketChannel4() { int n = 10; Object o; try { for (int i = 0; i < n; i++) { o = Integer.valueOf(i); tsc1.send(tag1,o); } assertEquals("#tags == 0 ", 0, tsc1.tagSize()); for (int i = 0; i < n; i++) { o = Integer.valueOf(i); assertEquals(o,tsc2.receive(tag1)); } assertTrue("#tags == 1 ", tsc2.tagSize() == 1); assertTrue("#messages == 0 ", tsc1.messages() == 0); assertTrue("#messages == 0 ", tsc2.messages() == 0); } catch(IOException e) { fail("Exception"+e); } catch(InterruptedException e) { fail("Exception"+e); } catch(ClassNotFoundException e) { fail("Exception"+e); } } public void testTaggedSocketChannel5() { int n = 10; String msg = "Hello_"; Integer o; try { for (int i = 0; i < n; i++) { o = Integer.valueOf(i); tsc1.send(o,msg+i); } assertTrue("#tags == 0 ", tsc1.tagSize() == 0); assertTrue("#messages == 0 ", tsc1.messages() == 0); assertTrue("#messages >= 0 ", tsc2.messages() >= 0); // not all 10 arrive in time for (int i = 0; i < n; i++) { o = Integer.valueOf(i); assertEquals(msg+i,tsc2.receive(o)); } //System.out.println("tsc2 = " + tsc2); assertTrue("#tags == 10 ", tsc2.tagSize() == 10); assertTrue("#messages == 0 ", tsc2.messages() <= 1); } catch(IOException e) { fail("Exception"+e); } catch(InterruptedException e) { fail("Exception"+e); } catch(ClassNotFoundException e) { fail("Exception"+e); } } } jas-2.5/trc/edu/jas/util/SocketChannelTest.java0000644000175000017500000000543712011705232021670 0ustar giovannigiovanni/* * $Id: SocketChannelTest.java 4093 2012-08-12 10:51:06Z kredel $ */ // from package edu.unima.ky.parallel; package edu.jas.util; import java.io.IOException; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; /** * SocketChannel tests with JUnit. * Refactored for java.util.concurrent. * @author Akitoshi Yoshida * @author Heinz Kredel. */ public class SocketChannelTest extends TestCase { public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } public SocketChannelTest(String name) { super(name); } public static Test suite() { TestSuite suite= new TestSuite(SocketChannelTest.class); return suite; } private ChannelFactory cf; private SocketChannel sc1; private SocketChannel sc2; private String host; private int port; protected void setUp() { host = "localhost"; port = 4711; cf = new ChannelFactory(port); cf.init(); try { sc1 = cf.getChannel(host,port); sc2 = cf.getChannel(); } catch(IOException e) { fail("IOException"+e); } catch (InterruptedException e) { fail("InterruptedException"+e); } } protected void tearDown() { cf.terminate(); sc1.close(); sc2.close(); try { Thread.sleep(1); } catch(InterruptedException e) { fail("InterruptedException"+e); } } public void testSocketChannel0() { // test setUp() and tearDown() } public void testSocketChannel1() { Object o = Integer.valueOf(0); try { sc1.send(o); assertEquals(o,sc2.receive()); } catch(IOException e) { fail("Exception"+e); } catch(ClassNotFoundException e) { fail("Exception"+e); } } public void testSocketChannel2() { Object o = Integer.valueOf(0); try { sc1.send(o); sc2.send(o); assertEquals(o,sc1.receive()); assertEquals(o,sc2.receive()); } catch(IOException e) { fail("Exception"+e); } catch(ClassNotFoundException e) { fail("Exception"+e); } } public void testSocketChannel3() { int n = 10; Object o; try { for (int i = 0; i < n; i++) { o = Integer.valueOf(i); sc1.send(o); } for (int i = 0; i < n; i++) { o = Integer.valueOf(i); assertEquals(o,sc2.receive()); } } catch(IOException e) { fail("Exception"+e); } catch(ClassNotFoundException e) { fail("Exception"+e); } } } jas-2.5/trc/edu/jas/util/IteratorsTest.java0000644000175000017500000002104512004571452021123 0ustar giovannigiovanni/* * $Id: IteratorsTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.util; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; /** * Iterator tests with JUnit. * @author Heinz Kredel. */ public class IteratorsTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a ListUtilTest object. * @param name String. */ public IteratorsTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(IteratorsTest.class); return suite; } @Override protected void setUp() { } @Override protected void tearDown() { } /** * Test cartesian product. * */ public void testCartesianProduct() { BigInteger ai = new BigInteger(); int s1 = 5; int s2 = 3; int s = 1; for (int i = 0; i < s1; i++) { s *= s2; } //System.out.println("s = " + s); List> tlist = new ArrayList>(s1); for (int i = 0; i < s1; i++) { List list = new ArrayList(s2); for (int j = 0; j < s2; j++) { list.add(ai.fromInteger(j)); } tlist.add(list); } //System.out.println("tlist = " + tlist); int t = 0; for (List tuple : new CartesianProduct(tlist)) { t++; //System.out.println("tuple = " + tuple); assertTrue("|tuple| == " + s1 + " ", s1 == tuple.size()); } assertTrue("#tuple == " + s + " == " + t + " ", t == s); } /** * Test power set. * */ public void testPowerSet() { BigInteger ai = new BigInteger(); int s1 = 5; int s = 1; for (int i = 0; i < s1; i++) { s *= 2; } //System.out.println("s = " + s); List tlist = new ArrayList(s1); for (int j = 0; j < s1; j++) { tlist.add(ai.random(7)); } //System.out.println("tlist = " + tlist); int t = 0; for (List tuple : new PowerSet(tlist)) { t++; //System.out.println("tuple = " + tuple); assertFalse("tuple != null", tuple == null); } assertTrue("#tuple == " + s + " == " + t + " ", t == s); } /** * Test k-subset set. * */ public void testKsubSet() { BigInteger ai = new BigInteger(); int s1 = 5; int s = 1; for (int i = 0; i < s1; i++) { s *= 2; } //System.out.println("s = " + s); List tlist = new ArrayList(s1); for (int j = 0; j < s1; j++) { tlist.add(ai.random(7)); } //System.out.println("tlist = " + tlist); int t = 0; for (int k = 0; k <= s1; k++) { for (List tuple : new KsubSet(tlist, k)) { t++; //System.out.println("tuple = " + tuple); assertTrue("|tuple| == " + k + " ", k == tuple.size()); } } assertTrue("#tuple == " + s + " == " + t + " ", t == s); } /** * Test infinite cartesian product. * */ public void testInfiniteCartesianProductTwoList() { BigInteger ai = new BigInteger(); ai.setNonNegativeIterator(); int s1 = 2; //System.out.println("s1 = " + s1); List> tlist = new ArrayList>(s1); for (int i = 0; i < s1; i++) { tlist.add(ai); } //System.out.println("tlist = " + tlist); Set> set = new HashSet>(); int s2 = 5; int s = 1; for (int i = 0; i < s1; i++) { s *= s2; } //System.out.println("s = " + s); List> ftlist = new ArrayList>(s1); for (int i = 0; i < s1; i++) { List list = new ArrayList(s2); for (int j = 0; j < s2; j++) { list.add(ai.fromInteger(j)); } ftlist.add(list); } //System.out.println("tlist = " + tlist); int r = 0; for (List tuple : new CartesianProduct(ftlist)) { r++; set.add(tuple); } //System.out.println("set = " + set.size()); //System.out.println("set = " + r); int t = 0; int h = 0; Iterable> ib = new CartesianProductInfinite(tlist); Iterator> iter = ib.iterator(); while (iter.hasNext()) { List tuple = iter.next(); t++; //System.out.println("tuple = " + tuple); //assertTrue("|tuple| == " + s1 + " ", s1 == tuple.size()); if (set.contains(tuple)) { h++; } if (h >= r) { break; } assertTrue("#tuple <= 125 " + t, t <= 125); } //System.out.println("#tuple = " + t + ", #set = " + r); } /** * Test infinite cartesian product. * */ public void testInfiniteCartesianProduct() { BigInteger ai = new BigInteger(); ai.setNonNegativeIterator(); int s1 = 4; //System.out.println("s1 = " + s1); List> tlist = new ArrayList>(s1); for (int i = 0; i < s1; i++) { tlist.add(ai); } //System.out.println("tlist = " + tlist); Set> set = new HashSet>(); int s2 = 5; int s = 1; for (int i = 0; i < s1; i++) { s *= s2; } //System.out.println("s = " + s); List> ftlist = new ArrayList>(s1); for (int i = 0; i < s1; i++) { List list = new ArrayList(s2); for (int j = 0; j < s2; j++) { list.add(ai.fromInteger(j)); } ftlist.add(list); } //System.out.println("tlist = " + tlist); int r = 0; for (List tuple : new CartesianProduct(ftlist)) { r++; set.add(tuple); } //System.out.println("set = " + set.size()); //System.out.println("set = " + r); int t = 0; int h = 0; Iterable> ib = new CartesianProductInfinite(tlist); Iterator> iter = ib.iterator(); while (iter.hasNext()) { List tuple = iter.next(); t++; //System.out.println("tuple = " + tuple); //assertTrue("|tuple| == " + s1 + " ", s1 == tuple.size()); if (set.contains(tuple)) { h++; } if (h >= r) { break; } assertTrue("#tuple <= 3281 " + t, t <= 3281); } //System.out.println("#tuple = " + t + ", #set = " + r); } /** * Test Long iterator. * */ public void testLong() { LongIterable li = new LongIterable(); li.setNonNegativeIterator(); long s = 0L; long t = 0L; for (Long i : li) { //System.out.println("i = " + i); s = i; assertTrue("t == i", t == i); t++; if (t > 1000L) { //% 100000000L == 0L ) { //System.out.println("i = " + i); break; } } //System.out.println("t = " + t); assertTrue("i == 1000", s == 1000L); li.setAllIterator(); s = 0L; t = 0L; for (Long i : li) { //System.out.println("i = " + i); s = i; //assertTrue("t == i", t == i ); t++; if (t >= 1000L) { //% 100000000L == 0L ) { //System.out.println("i = " + i); break; } } //System.out.println("t = " + t); assertTrue("i == 500", s == 500L); } } jas-2.5/trc/edu/jas/util/DistributedListTest.java0000644000175000017500000001422412011714752022266 0ustar giovannigiovanni/* * $Id: DistributedListTest.java 4096 2012-08-12 11:56:27Z kredel $ */ //package edu.unima.ky.parallel; package edu.jas.util; import java.util.Iterator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; /** * DistributedList tests with JUnit. * @author Heinz Kredel */ public class DistributedListTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a DistributedListTest object. * @param name String. */ public DistributedListTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(DistributedListTest.class); return suite; } private static final String host = "localhost"; private DistributedList l1; private DistributedList l2; private DistributedList l3; private DistributedListServer dls; int rl = 7; int kl = 10; int ll = 10; int el = 5; float q = 0.5f; protected void setUp() { dls = new DistributedListServer(); dls.init(); } protected void tearDown() { dls.terminate(); dls = null; if ( l1 != null ) l1.terminate(); if ( l2 != null ) l2.terminate(); if ( l3 != null ) l3.terminate(); l1 = l2 = l3 = null; } /** * Tests if the created DistributedList has #n objects as content. */ public void testDistributedList1() { l1 = new DistributedList(host); l1.init(); assertTrue("l1==empty",l1.isEmpty()); l1.add( Integer.valueOf(1) ); assertFalse("l1!=empty",l1.isEmpty()); assertTrue("#l1==1", l1.size() == 1 ); l1.add( Integer.valueOf(2) ); assertTrue("#l1==2", l1.size() == 2 ); l1.add( Integer.valueOf(3) ); assertTrue("#l1==3", l1.size() == 3 ); Iterator it = null; it = l1.iterator(); int i = 0; while ( it.hasNext() ) { Object o = it.next(); Integer x = Integer.valueOf( ++i ); assertEquals("l1(i)==(i)", x, o ); } l1.clear(); assertTrue("#l1==0", l1.size() == 0 ); } /** * Tests if the two created DistributedLists have #n objects as content. */ public void testDistributedList2() { l2 = new DistributedList(host); l2.init(); assertTrue("l2==empty",l2.isEmpty()); l1 = new DistributedList(host); l1.init(); assertTrue("l1==empty",l1.isEmpty()); int i = 0, loops = 10; while ( i < loops ) { Integer x = Integer.valueOf( ++i ); l1.add( x ); assertTrue("#l1==i", l1.size() == i ); } assertTrue("#l1==10", l1.size() == loops ); while ( l2.size() < loops ) { try { System.out.print("2"); Thread.sleep(100); } catch (InterruptedException e) { } } Iterator it = null; it = l2.iterator(); i = 0; while ( it.hasNext() ) { Object o = it.next(); Integer x = Integer.valueOf( ++i ); //System.out.println("o = " + o + " x = "+ x); assertEquals("l2(i)==(i)", x, o ); } assertTrue("#l2==10", l2.size() == loops ); } /** * Tests if the three created DistributedLists have #n objects as content. */ public void testDistributedList3() { l1 = new DistributedList(host); l1.init(); assertTrue("l1==empty",l1.isEmpty()); l2 = new DistributedList(host); l2.init(); assertTrue("l2==empty",l2.isEmpty()); l3 = new DistributedList(host); l3.init(); assertTrue("l3==empty",l3.isEmpty()); int i = 0, loops = 10; while ( i < loops ) { Integer x = Integer.valueOf( ++i ); l3.add( x ); assertTrue("#l3==i", l3.size() == i ); } assertTrue("#l3==10", l3.size() == loops ); while ( l2.size() < loops || l1.size() < loops-1 ) { try { System.out.print("3"); Thread.sleep(100); } catch (InterruptedException e) { } } assertTrue("#l2==10", l2.size() == loops ); assertTrue("#l1==10", l1.size() == loops ); Iterator it = null; it = l2.iterator(); Iterator it3 = null; it3 = l1.iterator(); i = 0; /* sequence of elements is not correct at moment */ while ( it.hasNext() && it3.hasNext() ) { Object o = it.next(); Object p = it3.next(); Integer x = Integer.valueOf( ++i ); //System.out.println("o = " + o + " x = "+ x); assertEquals("l2(i)==(i)", x, o ); assertEquals("l1(i)==(i)", x, p ); } } /** * Tests if the two created DistributedLists have #n objects as content * when one is created later. */ public void testDistributedList6() { l1 = new DistributedList(host); l1.init(); assertTrue("l1==empty",l1.isEmpty()); int i = 0, loops = 10; while ( i < loops ) { Integer x = Integer.valueOf( ++i ); l1.add( x ); assertTrue("#l1==i", l1.size() == i ); } assertTrue("#l1==10", l1.size() == loops ); l2 = new DistributedList(host); l2.init(); // assertTrue("l2==empty",l2.isEmpty()); while ( l2.size() < loops ) { try { //System.out.print("2"); Thread.sleep(100); } catch (InterruptedException e) { } } Iterator it = null; it = l2.iterator(); i = 0; while ( it.hasNext() ) { Object o = it.next(); Integer x = Integer.valueOf( ++i ); //System.out.println("o = " + o + " x = "+ x); assertEquals("l2(i)==(i)", x, o ); } assertTrue("#l2==10", l2.size() == loops ); } } jas-2.5/trc/edu/jas/util/DistHashTableTest.java0000644000175000017500000002032412011705232021616 0ustar giovannigiovanni/* * $Id: DistHashTableTest.java 4093 2012-08-12 10:51:06Z kredel $ */ package edu.jas.util; import java.util.Iterator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; /** * DistHashTable test with JUnit. * @author Heinz Kredel */ public class DistHashTableTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a DistHashTableTest object. * @param name String. */ public DistHashTableTest(String name) { super(name); } /** * suite. * @return a test suite. */ public static Test suite() { TestSuite suite= new TestSuite(DistHashTableTest.class); return suite; } private static final String host = "localhost"; private DistHashTable l1; private DistHashTable l2; private DistHashTable l3; private DistHashTableServer dls; int rl = 7; int kl = 10; int ll = 10; int el = 5; float q = 0.5f; protected void setUp() { dls = new DistHashTableServer(); dls.init(); } protected void tearDown() { dls.terminate(); dls = null; if ( l1 != null ) l1.terminate(); if ( l2 != null ) l2.terminate(); if ( l3 != null ) l3.terminate(); l1 = l2 = l3 = null; } /** * Tests create and terminate DistHashTableServer. */ public void testDistHashTable0() { } /** * Tests create and terminate DistHashTable. */ public void testDistHashTable1() { l1 = new DistHashTable(host); l1.init(); assertTrue("l1==empty",l1.isEmpty()); } /** * Tests if the created DistHashTable has #n objects as content. */ public void testDistHashTable2() { l1 = new DistHashTable(host); l1.init(); assertTrue("l1==empty",l1.isEmpty()); l1.putWait( Integer.valueOf(1), Integer.valueOf(1) ); assertFalse("l1!=empty",l1.isEmpty()); assertTrue("#l1==1", l1.size() == 1 ); l1.putWait( Integer.valueOf(2), Integer.valueOf(2) ); assertTrue("#l1==2", l1.size() == 2 ); l1.putWait( Integer.valueOf(3), Integer.valueOf(3) ); assertTrue("#l1==3", l1.size() == 3 ); Iterator it = null; it = l1.iterator(); int i = 0; while ( it.hasNext() ) { Object k = it.next(); Object o = l1.get(k); Integer x = Integer.valueOf( ++i ); assertEquals("l1(i)==v(i)", x, o ); assertEquals("l1(i)==k(i)", x, k ); } l1.clear(); assertTrue("#l1==0", l1.size() == 0 ); } /** * Tests if the two created DistHashTables have #n objects as content. */ public void testDistHashTable3() { l2 = new DistHashTable(host); l2.init(); assertTrue("l2==empty",l2.isEmpty()); l1 = new DistHashTable(host); l1.init(); assertTrue("l1==empty",l1.isEmpty()); int i = 0, loops = 10; while ( i < loops ) { Integer x = Integer.valueOf( ++i ); l1.putWait( x, x ); assertTrue("#l1==i", l1.size() == i ); } assertTrue("#l1=="+loops, l1.size() == loops ); while ( l2.size() < loops ) { try { //System.out.print("*2"); Thread.sleep(100); } catch (InterruptedException e) { } } assertTrue("#l2=="+loops, l2.size() == loops ); Iterator it = null; it = l2.iterator(); i = 0; while ( it.hasNext() ) { Object k = it.next(); Object o = l2.get(k); Integer x = Integer.valueOf( ++i ); //System.out.println("o = " + o + " x = "+ x); assertEquals("l2(i)==k(i)", x, k ); assertEquals("l2(i)==v(i)", x, o ); } } /** * Tests if the three created DistHashTables have #n objects as content. */ public void testDistHashTable4() { l1 = new DistHashTable(host); l1.init(); assertTrue("l1==empty",l1.isEmpty()); l2 = new DistHashTable(host); l2.init(); assertTrue("l2==empty",l2.isEmpty()); l3 = new DistHashTable(host); l3.init(); assertTrue("l3==empty",l3.isEmpty()); int i = 0, loops = 10; while ( i < loops ) { Integer x = Integer.valueOf( ++i ); l3.putWait( x, x ); assertTrue("#l3==i", l3.size() == i ); } assertTrue("#l3=="+loops, l3.size() == loops ); while ( l2.size() < loops || l1.size() < loops-1 ) { try { //System.out.print("*3"); Thread.sleep(100); } catch (InterruptedException e) { } } assertTrue("#l2=="+loops, l2.size() == loops ); assertTrue("#l1=="+loops, l1.size() == loops ); Iterator it = null; it = l2.iterator(); Iterator it3 = null; it3 = l1.iterator(); i = 0; while ( it.hasNext() && it3.hasNext() ) { Object k1 = it.next(); Object k2 = it3.next(); Object v1 = l2.get(k1); Object v2 = l1.get(k2); Integer x = Integer.valueOf( ++i ); //System.out.println("o = " + o + " x = "+ x); assertEquals("l2(i)==k(i)", x, k1 ); assertEquals("l1(i)==k(i)", x, k2 ); assertEquals("l2(i)==v(i)", x, v1 ); assertEquals("l1(i)==v(i)", x, v2 ); } } /** * Tests if the two created DistHashTables have #n objects as content * when one is created later. */ public void testDistHashTable5() { l1 = new DistHashTable(host); l1.init(); assertTrue("l1==empty",l1.isEmpty()); int i = 0, loops = 10; while ( i < loops ) { Integer x = Integer.valueOf( ++i ); l1.putWait( x, x ); assertTrue("#l1==i", l1.size() == i ); } assertTrue("#l1=="+loops, l1.size() == loops ); l2 = new DistHashTable(host); l2.init(); // assertTrue("l2==empty",l2.isEmpty()); while ( l2.size() < loops ) { try { //System.out.print("*2"); Thread.sleep(100); } catch (InterruptedException e) { } } Iterator it = null; it = l2.iterator(); i = 0; while ( it.hasNext() ) { Object k = it.next(); Object v = l2.get(k); Integer x = Integer.valueOf( ++i ); //System.out.println("o = " + o + " x = "+ x); assertEquals("l2(i)==k(i)", x, k ); assertEquals("l2(i)==v(i)", x, v ); } assertTrue("#l2=="+loops, l2.size() == loops ); } /** * Tests if the two created DistHashTables have #n objects as content * using getWait() when one is created later. */ public void testDistHashTable6() { l1 = new DistHashTable(host); l1.init(); assertTrue("l1==empty",l1.isEmpty()); int i = 0, loops = 10; while ( i < loops ) { Integer x = Integer.valueOf( ++i ); l1.putWait( x, x ); assertTrue("#l1==i", l1.size() == i ); } assertTrue("#l1=="+loops, l1.size() == loops ); l2 = new DistHashTable(host); l2.init(); Iterator it = null; it = l1.iterator(); i = 0; while ( it.hasNext() ) { Integer k = it.next(); Integer v = l2.getWait(k); Integer x = Integer.valueOf( ++i ); //System.out.println("o = " + o + " x = "+ x); assertEquals("l1(i)==k(i)", x, k ); assertEquals("l2(i)==v(i)", x, v ); } assertTrue("#l2=="+loops, l2.size() == loops ); } } jas-2.5/trc/edu/jas/util/ExecutableChannelsTest.java0000644000175000017500000001755011641660762022723 0ustar giovannigiovanni/* * $Id: ExecutableChannelsTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.util; import java.io.FileNotFoundException; import java.io.IOException; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import edu.unima.ky.parallel.ChannelFactory; /** * ExecutableChannels tests with JUnit. * @author Heinz Kredel */ public class ExecutableChannelsTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ExecutableChannelsTest object. * @param name String. */ public ExecutableChannelsTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ExecutableChannelsTest.class); return suite; } private static final String host = "localhost"; private static final int port = ChannelFactory.DEFAULT_PORT; private static final String mfile = ExecutableChannels.DEFAULT_MFILE; private ExecutableChannels ec; private ExecutableServer es; protected void setUp() { ec = null; es = new ExecutableServer(port); es.init(); } protected void tearDown() { es.terminate(); es = null; if ( ec != null ) { ec.close(); ec = null; } } /** * Tests if the ExecutableChannels could be initialized with null. */ public void testExecutableChannels1() { String[] servers = null; ec = new ExecutableChannels(servers); assertEquals("numServers<0", -1, ec.numServers() ); assertEquals("numChannels<0", -1, ec.numChannels() ); String ts = "" + ec; assertEquals("toString", "ExecutableChannels()", ts ); } /** * Tests if the ExecutableChannels could be initialized with small server array. */ public void testExecutableChannels2() { int nums = 1; String[] servers = new String[nums]; for ( int i = 0; i < nums; i++ ) { servers[i] = host + ":" + port; } ec = new ExecutableChannels(servers); assertEquals("numServers==1", 1, ec.numServers() ); assertEquals("numChannels<0", -1, ec.numChannels() ); String ts = "" + ec; assertEquals("toString", "ExecutableChannels("+host+":"+port+")", ts ); } /** * Tests if the ExecutableChannels could be initialized with big server array. */ public void testExecutableChannels3() { int nums = 100; String[] servers = new String[nums]; for ( int i = 0; i < nums; i++ ) { servers[i] = host + ":" + port; } ec = new ExecutableChannels(servers); assertEquals("numServers==100", 100, ec.numServers() ); assertEquals("numChannels<0", -1, ec.numChannels() ); String ts = "" + ec; int l = "ExecutableChannels()".length() + nums * servers[0].length() + nums-1; assertEquals("toString.length()", l, ts.length()); } /** * Tests if the ExecutableChannels could be initialized and opened. */ public void testExecutableChannels4() { int nums = 2; int numc = nums - 1; String[] servers = new String[nums]; for ( int i = 0; i < nums; i++ ) { servers[i] = host + ":" + port; } ec = new ExecutableChannels(servers); assertEquals("numServers==2", nums, ec.numServers() ); assertEquals("numChannels<0", -1, ec.numChannels() ); String ts = "" + ec; int l = "ExecutableChannels()".length() + nums * servers[0].length() + nums-1; assertEquals("toString.length()", l, ts.length()); try { ec.open(); assertEquals("numServers==1", nums, ec.numServers() ); assertEquals("numServers==numChannels", numc, ec.numChannels() ); } catch (IOException e) { fail("open()"+e); } ec.close(); assertEquals("numChannels<0", -1, ec.numChannels() ); } /** * Tests if 11 ExecutableChannels could be initialized and opened. */ public void testExecutableChannels5() { int nums = 11; // max 11 by some limit on number of threads int numc = nums - 1; String[] servers = new String[nums]; for ( int i = 0; i < nums; i++ ) { servers[i] = host + ":" + port; } ec = new ExecutableChannels(servers); assertEquals("numServers==1", nums, ec.numServers() ); assertEquals("numChannels<0", -1, ec.numChannels() ); String ts = "" + ec; int l = "ExecutableChannels()".length() + nums * servers[0].length() + nums-1; assertEquals("toString.length()", l, ts.length()); try { ec.open(); assertEquals("numServers==1", nums, ec.numServers() ); assertEquals("numServers==numChannels", numc, ec.numChannels() ); } catch (IOException e) { fail("open()"+e); } ec.close(); assertEquals("numChannels<0", -1, ec.numChannels() ); } /** * Tests if 10 ExecutableChannels to 1 server could be initialized and opened. */ public void testExecutableChannels6() { int nums = 2; // max 11 by some limit on number of threads int numc = 10; // max 11 by some limit on number of threads String[] servers = new String[nums]; for ( int i = 0; i < nums; i++ ) { servers[i] = host + ":" + port; } ec = new ExecutableChannels(servers); assertEquals("numServers==1", nums, ec.numServers() ); assertEquals("numChannels<0", -1, ec.numChannels() ); try { ec.open(numc); assertEquals("numServers==1", nums, ec.numServers() ); assertEquals("numServers==numChannels", numc, ec.numChannels() ); } catch (IOException e) { fail("open()"+e); } ec.close(); assertEquals("numChannels<0", -1, ec.numChannels() ); } /** * Tests if 5 ExecutableChannels to 10 servers could be initialized and opened. */ public void testExecutableChannels7() { int nums = 10; // max 11 by some limit on number of threads int numc = 5; // max 11 by some limit on number of threads String[] servers = new String[nums]; for ( int i = 0; i < nums; i++ ) { servers[i] = host + ":" + port; } ec = new ExecutableChannels(servers); assertEquals("numServers==1", nums, ec.numServers() ); assertEquals("numChannels<0", -1, ec.numChannels() ); try { ec.open(numc); assertEquals("numServers==1", nums, ec.numServers() ); assertEquals("numServers==numChannels", numc, ec.numChannels() ); } catch (IOException e) { fail("open()"+e); } ec.close(); assertEquals("numChannels<0", -1, ec.numChannels() ); } /** * Tests if the ExecutableChannels could be initialized with servers from file. */ public void testExecutableChannels8() { try { ec = new ExecutableChannels( mfile ); } catch (FileNotFoundException e) { fail("readfile()"+e); } assertEquals("numServers==4", 4, ec.numServers() ); assertEquals("numChannels<0", -1, ec.numChannels() ); int numc = ec.numServers(); try { ec.open(numc); assertEquals("numServers==numChannels", numc, ec.numChannels() ); } catch (IOException e) { fail("open()"+e); } ec.close(); assertEquals("numChannels<0", -1, ec.numChannels() ); } /** * Tests if the ExecutableChannels could be initialized with servers from file. */ public void testExecutableChannels9() { try { ec = new ExecutableChannels( mfile ); } catch (FileNotFoundException e) { fail("readfile()"+e); } assertEquals("numServers==4", 4, ec.numServers() ); assertEquals("numChannels<0", -1, ec.numChannels() ); int numc = 10; try { ec.open(numc); assertEquals("numServers==numChannels", numc, ec.numChannels() ); } catch (IOException e) { fail("open()"+e); } ec.close(); assertEquals("numChannels<0", -1, ec.numChannels() ); } } jas-2.5/trc/edu/jas/util/ListUtilTest.java0000644000175000017500000000545511641660762020740 0ustar giovannigiovanni/* * $Id: ListUtilTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.util; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.structure.RingElem; import edu.jas.structure.UnaryFunctor; /** * ListUtil tests with JUnit. * @author Heinz Kredel. */ public class ListUtilTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a ListUtilTest object. * @param name String. */ public ListUtilTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(ListUtilTest.class); return suite; } BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; @Override protected void setUp() { ai = bi = ci = di = ei = null; } @Override protected void tearDown() { ai = bi = ci = di = ei = null; } /** * Test list map. * */ public void testListMap() { ai = new BigInteger(); List list = new ArrayList(); for (int i = 0; i < 10; i++) { list.add(ai.random(7)); } bi = ai.getONE(); List nl; nl = ListUtil. map(list, new Multiply(bi)); assertEquals("list == nl ", list, nl); } /** * Test tuple transpose. * */ public void testTuple() { ai = new BigInteger(); List> tlist = new ArrayList>(); int s1 = 4; int s2 = 3; int s = 1; for (int i = 0; i < s1; i++) { s *= s2; } //System.out.println("s = " + s); for (int i = 0; i < s1; i++) { List list = new ArrayList(); for (int j = 0; j < s2; j++) { list.add(ai.random(7)); } tlist.add(list); } //System.out.println("tlist = " + tlist); List> ltuple = ListUtil. tupleFromList(tlist); //System.out.println("ltuple = " + ltuple); assertTrue("#ltuple == " + s + " ", ltuple.size() == s); for (List t : ltuple) { assertTrue("#t == " + s1 + " ", t.size() == s1); } } } /** * Internal scalar multiplication functor. */ class Multiply> implements UnaryFunctor { C x; public Multiply(C x) { this.x = x; } public C eval(C c) { return c.multiply(x); } } jas-2.5/trc/edu/jas/integrate/0000755000175000017500000000000012140140260016435 5ustar giovannigiovannijas-2.5/trc/edu/jas/integrate/ElementaryIntegrationTest.java0000644000175000017500000002012711641660762024476 0ustar giovannigiovanni/* * $Id: ElementaryIntegrationTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.integrate; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.poly.PolyUtil; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; import edu.jas.kern.ComputerThreads; /** * Quotient over BigRational GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class ElementaryIntegrationTest extends TestCase { /** * main. */ public static void main (String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ElementaryIntegrationTest object. * @param name String. */ public ElementaryIntegrationTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ElementaryIntegrationTest.class); return suite; } //private final static int bitlen = 100; TermOrder tord; QuotientRing qfac; GenPolynomialRing mfac; ElementaryIntegration integrator; QuotIntegral rint; Quotient< BigRational > a; Quotient< BigRational > b; Quotient< BigRational > c; Quotient< BigRational > d; Quotient< BigRational > e; int rl = 1; // only univariate polynomials int kl = 5; int ll = 3; //6; int el = 4; float q = 0.4f; protected void setUp() { a = b = c = d = e = null; tord = new TermOrder( TermOrder.INVLEX ); BigRational br = new BigRational(1); String[] vars = new String[]{ "x" }; mfac = new GenPolynomialRing( br, rl, tord, vars ); qfac = new QuotientRing( mfac ); integrator = new ElementaryIntegration(br); } protected void tearDown() { a = b = c = d = e = null; //qfac.terminate(); qfac = null; ComputerThreads.terminate(); } /** * Test rational integral. * */ public void testRational() { for (int i = 0; i < 3; i++) { a = qfac.random(kl, ll+2*i, el+i, q ); //System.out.println("a = " + a); // if ( a.isZERO() || a.isONE() ) { // continue; // } b = integrator.deriviative(a); //System.out.println("b = " + b); rint = integrator.integrate(b); //System.out.println("QuotIntegral: " + rint); assertTrue("isIntegral ", integrator.isIntegral(rint)); } } /** * Test 1/p pure logarithm integral. * */ public void testPureLogarithm1() { for (int i = 0; i < 3; i++) { a = qfac.random(kl, ll+i, el+i, q ); //System.out.println("a = " + a); // if ( a.isZERO() || a.isONE() ) { // continue; // } b = new Quotient(qfac,qfac.getONE().num,a.den); //System.out.println("b = " + b); rint = integrator.integrate(b); //System.out.println("QuotIntegral: " + rint); assertTrue("isIntegral ", integrator.isIntegral(rint)); } } /** * Test p'/p pure logarithm integral. * */ public void testPureLogarithmD() { for (int i = 0; i < 3; i++) { a = qfac.random(kl, ll+i, el+i, q ); //System.out.println("a = " + a); // if ( a.isZERO() || a.isONE() ) { // continue; // } GenPolynomial pp = PolyUtil. baseDeriviative(a.den); b = new Quotient(qfac, pp ,a.den); //System.out.println("b = " + b); rint = integrator.integrate(b); //System.out.println("QuotIntegral: " + rint); assertTrue("isIntegral ", integrator.isIntegral(rint)); } } /** * Test mixed rational with p'/p logarithm integral. * */ public void testRationalWithLogarithmD() { for (int i = 0; i < 3; i++) { a = qfac.random(kl, ll+i, el+i, q ); //System.out.println("a = " + a); // if ( a.isZERO() || a.isONE() ) { // continue; // } b = integrator.deriviative(a); //System.out.println("b = " + b); GenPolynomial pp = PolyUtil. baseDeriviative(a.den); c = new Quotient(qfac, pp ,a.den); //System.out.println("c = " + c); e = b.sum(c); //System.out.println("e = " + e); rint = integrator.integrate(e); //System.out.println("QuotIntegral: " + rint); assertTrue("isIntegral ", integrator.isIntegral(rint)); } } /** * Test mixed rational with 1/p logarithm integral. * */ public void xtestRationalWithLogarithm1() { for (int i = 0; i < 3; i++) { a = qfac.random(kl, ll+i, el+i, q ); //System.out.println("a = " + a); // if ( a.isZERO() || a.isONE() ) { // continue; // } b = integrator.deriviative(a); //System.out.println("b = " + b); d = new Quotient(qfac,qfac.getONE().num,a.den); //System.out.println("d = " + d); e = b.sum(d); //System.out.println("e = " + e); rint = integrator.integrate(e); //System.out.println("QuotIntegral: " + rint); assertTrue("isIntegral ", integrator.isIntegral(rint)); } } /** * Test mixed rational with p'/p + 1/p logarithm integral. * */ public void testRationalWithLogarithm() { for (int i = 0; i < 3; i++) { a = qfac.random(kl, ll+i, el+i, q ); //System.out.println("a = " + a); // if ( a.isZERO() || a.isONE() ) { // continue; // } b = integrator.deriviative(a); //System.out.println("b = " + b); GenPolynomial pp = PolyUtil. baseDeriviative(a.den); c = new Quotient(qfac, pp ,a.den); //System.out.println("c = " + c); d = new Quotient(qfac,qfac.getONE().num,a.den); //System.out.println("d = " + d); e = b.sum(c).sum(d); //System.out.println("e = " + e); rint = integrator.integrate(e); //System.out.println("QuotIntegral: " + rint); assertTrue("isIntegral ", integrator.isIntegral(rint)); } } /** * Test rational integral with quotient coefficients. * */ public void testRationalRecursive() { QuotientRing> qqfac; GenPolynomialRing> qmfac; ElementaryIntegration> qintegrator; QuotIntegral> qrint; String[] vars = new String[]{ "y" }; qmfac = new GenPolynomialRing>(qfac,1,tord,vars); qqfac = new QuotientRing>(qmfac); qintegrator = new ElementaryIntegration>(qfac); Quotient< Quotient< BigRational > > qa, qb; for (int i = 0; i < 2; i++) { qa = qqfac.random(2, ll, el, q ); //System.out.println("qa = " + qa); // if ( a.isZERO() || a.isONE() ) { // continue; // } qb = qintegrator.deriviative(qa); //System.out.println("qb = " + qb); qrint = qintegrator.integrate(qb); //System.out.println("QuotIntegral: " + qrint); assertTrue("isIntegral ", qintegrator.isIntegral(qrint)); } } } jas-2.5/trc/edu/jas/gbmod/0000755000175000017500000000000012140140260015543 5ustar giovannigiovannijas-2.5/trc/edu/jas/gbmod/ModGroebnerBaseTest.java0000644000175000017500000001017111641660762022267 0ustar giovannigiovanni/* * $Id: ModGroebnerBaseTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gbmod; import java.util.List; import java.util.ArrayList; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; //import edu.jas.structure.RingElem; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; /** * ModGroebnerBase tests with JUnit. * @author Heinz Kredel. */ public class ModGroebnerBaseTest extends TestCase { //private static final Logger logger = Logger.getLogger(ModGroebnerBaseTest.class); /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ModGroebnerBaseTest object. * @param name String. */ public ModGroebnerBaseTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ModGroebnerBaseTest.class); return suite; } GenPolynomialRing fac; PolynomialList F; List> G; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; TermOrder tord; List>> L; List> V; ModuleList M; ModuleList N; ModGroebnerBase mbb; int rl = 3; //4; //3; int kl = 8; int ll = 5; int el = 2; float q = 0.2f; //0.4f protected void setUp() { BigRational coeff = new BigRational(9); tord = new TermOrder(); fac = new GenPolynomialRing(coeff,rl,tord); mbb = new ModGroebnerBaseAbstract(coeff); a = b = c = d = e = null; do { a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); } while ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ); e = d; //fac.random(kl, ll, el, q ); } protected void tearDown() { mbb = null; a = b = c = d = e = null; fac = null; tord = null; } /** * Test sequential GBase. * */ public void testSequentialModGB() { L = new ArrayList>>(); assertTrue("not isZERO( a )", !a.isZERO() ); V = new ArrayList>(); V.add(a); V.add(fac.getZERO()); V.add(fac.getONE()); L.add(V); M = new ModuleList(fac,L); assertTrue("isGB( { (a,0,1) } )", mbb.isGB(M) ); N = mbb.GB( M ); assertTrue("isGB( { (a,0,1) } )", mbb.isGB(N) ); assertTrue("not isZERO( b )", !b.isZERO() ); V = new ArrayList>(); V.add(b); V.add(fac.getONE()); V.add(fac.getZERO()); L.add(V); M = new ModuleList(fac,L); //System.out.println("L = " + L.size() ); N = mbb.GB( M ); assertTrue("isDIRPGB( { (a,0,1),(b,1,0) } )", mbb.isGB(N) ); //System.out.println("N = " + N ); assertTrue("not isZERO( c )", !c.isZERO() ); V = new ArrayList>(); V.add(c); V.add(fac.getZERO()); V.add(fac.getZERO()); L.add(V); M = new ModuleList(fac,L); //System.out.println("L = " + L.size() ); N = mbb.GB( M ); assertTrue("isDIRPGB( { (a,),(b,),(c,) } )", mbb.isGB(N) ); //System.out.println("N = " + N ); assertTrue("not isZERO( d )", !d.isZERO() ); V = new ArrayList>(); V.add(d); V.add(fac.getZERO()); V.add(fac.getZERO()); L.add(V); M = new ModuleList(fac,L); //System.out.println("L = " + L.size() ); N = mbb.GB( M ); assertTrue("isDIRPGB( { (a,b,c,d) } )", mbb.isGB(N) ); //System.out.println("N = " + N ); } } jas-2.5/trc/edu/jas/gbmod/SolvableSyzygyTest.java0000644000175000017500000003612412137242112022267 0ustar giovannigiovanni/* * $Id: SolvableSyzygyTest.java 4390 2013-04-28 15:46:19Z kredel $ */ package edu.jas.gbmod; import java.util.List; import java.util.ArrayList; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.gb.SolvableGroebnerBase; import edu.jas.gb.SolvableGroebnerBaseSeq; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.WeylRelations; import edu.jas.poly.RelationTable; /** * SolvableSyzygy tests with JUnit. * @author Heinz Kredel. */ public class SolvableSyzygyTest extends TestCase { //private static final Logger logger = Logger.getLogger(SolvableSyzygyTest.class); /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a SolvableSyzygyTest object. * @param name String. */ public SolvableSyzygyTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(SolvableSyzygyTest.class); return suite; } int port = 4711; String host = "localhost"; BigRational cfac; GenSolvablePolynomialRing fac; PolynomialList F; List> G; GenSolvablePolynomial a; GenSolvablePolynomial b; GenSolvablePolynomial c; GenSolvablePolynomial d; GenSolvablePolynomial e; GenSolvablePolynomial zero; GenSolvablePolynomial one; TermOrder tord; RelationTable table; List> L; List>> K; List> V; List>> W; ModuleList M; ModuleList N; ModuleList Z; SolvableGroebnerBase sbb; ModSolvableGroebnerBase msbb; SolvableSyzygyAbstract ssz; int rl = 4; //4; //3; int kl = 5; int ll = 7; int el = 2; float q = 0.3f; //0.4f protected void setUp() { cfac = new BigRational(1); tord = new TermOrder(); fac = new GenSolvablePolynomialRing(cfac,rl,tord); table = fac.table; a = b = c = d = e = null; L = null; K = null; V = null; do { a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); } while ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ); e = d; //fac.random(kl, ll, el, q ); one = fac.getONE(); zero = fac.getZERO(); sbb = new SolvableGroebnerBaseSeq(); msbb = new ModSolvableGroebnerBaseAbstract(); ssz = new SolvableSyzygyAbstract(); } protected void tearDown() { a = b = c = d = e = null; L = null; K = null; V = null; fac = null; tord = null; table = null; sbb = null; msbb = null; ssz = null; } /** * Test sequential SolvableSyzygy. * */ public void testSequentialSolvableSyzygy() { L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); assertTrue("isGB( { a } )", sbb.isLeftGB(L) ); K = ssz.leftZeroRelations( L ); assertTrue("is ZR( { a } )", ssz.isLeftZeroRelation(K,L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); L = sbb.leftGB(L); assertTrue("isGB( { a, b } )", sbb.isLeftGB(L) ); //System.out.println("\nL = " + L ); K = ssz.leftZeroRelations( L ); //System.out.println("\nK = " + K ); assertTrue("is ZR( { a, b } )", ssz.isLeftZeroRelation(K,L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = sbb.leftGB(L); //System.out.println("\nL = " + L ); assertTrue("isGB( { a, b, c } )", sbb.isLeftGB(L) ); K = ssz.leftZeroRelations( L ); //System.out.println("\nK = " + K ); assertTrue("is ZR( { a, b, c } )", ssz.isLeftZeroRelation(K,L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = sbb.leftGB(L); //System.out.println("\nL = " + L ); assertTrue("isGB( { a, b, c, d } )", sbb.isLeftGB(L) ); K = ssz.leftZeroRelations( L ); //System.out.println("\nK = " + K ); assertTrue("is ZR( { a, b, c, d } )", ssz.isLeftZeroRelation(K,L) ); //System.out.println("K = " + K ); } /** * Test sequential Weyl SolvableSyzygy. * */ public void testSequentialWeylSolvableSyzygy() { int rloc = 4; fac = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(fac); wl.generate(); table = fac.table; a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); assertTrue("isGB( { a } )", sbb.isLeftGB(L) ); K = ssz.leftZeroRelations( L ); assertTrue("is ZR( { a } )", ssz.isLeftZeroRelation(K,L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); L = sbb.leftGB(L); assertTrue("isGB( { a, b } )", sbb.isLeftGB(L) ); //System.out.println("\nL = " + L ); K = ssz.leftZeroRelations( L ); //System.out.println("\nK = " + K ); assertTrue("is ZR( { a, b } )", ssz.isLeftZeroRelation(K,L) ); // useless since 1 in GB assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = sbb.leftGB(L); //System.out.println("\nL = " + L ); assertTrue("isGB( { a, b, c } )", sbb.isLeftGB(L) ); K = ssz.leftZeroRelations( L ); //System.out.println("\nK = " + K ); assertTrue("is ZR( { a, b, c } )", ssz.isLeftZeroRelation(K,L) ); // useless since 1 in GB assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = sbb.leftGB(L); //System.out.println("\nL = " + L ); assertTrue("isGB( { a, b, c, d } )", sbb.isLeftGB(L) ); K = ssz.leftZeroRelations( L ); //System.out.println("\nK = " + K ); assertTrue("is ZR( { a, b, c, d } )", ssz.isLeftZeroRelation(K,L) ); //System.out.println("K = " + K ); } /** * Test sequential module SolvableSyzygy. * */ public void testSequentialModSolvableSyzygy() { W = new ArrayList>>(); assertTrue("not isZERO( a )", !a.isZERO() ); V = new ArrayList>(); V.add(a); V.add(zero); V.add(one); W.add(V); M = new ModuleList(fac,W); assertTrue("isGB( { (a,0,1) } )", msbb.isLeftGB(M) ); N = msbb.leftGB( M ); assertTrue("isGB( { (a,0,1) } )", msbb.isLeftGB(N) ); Z = ssz.leftZeroRelations(N); //System.out.println("Z = " + Z); assertTrue("is ZR( { a) } )", ssz.isLeftZeroRelation(Z,N) ); assertTrue("not isZERO( b )", !b.isZERO() ); V = new ArrayList>(); V.add(b); V.add(one); V.add(zero); W.add(V); M = new ModuleList(fac,W); //System.out.println("W = " + W.size() ); N = msbb.leftGB( M ); assertTrue("isGB( { a, b } )", msbb.isLeftGB(N) ); Z = ssz.leftZeroRelations(N); //System.out.println("Z = " + Z); assertTrue("is ZR( { a, b } )", ssz.isLeftZeroRelation(Z,N) ); assertTrue("not isZERO( c )", !c.isZERO() ); V = new ArrayList>(); V.add(c); V.add(one); V.add(zero); W.add(V); M = new ModuleList(fac,W); //System.out.println("W = " + W.size() ); N = msbb.leftGB( M ); //System.out.println("GB(M) = " + N); assertTrue("isGB( { a,b,c) } )", msbb.isLeftGB(N) ); Z = ssz.leftZeroRelations(N); //System.out.println("Z = " + Z); //boolean b = ssz.isLeftZeroRelation(Z,N); //System.out.println("boolean = " + b); assertTrue("is ZR( { a,b,c } )", ssz.isLeftZeroRelation(Z,N) ); } /** * Test sequential arbitrary base Syzygy. * */ public void testSequentialArbitrarySyzygy() { L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); assertTrue("isGB( { a } )", sbb.isLeftGB(L) ); K = ssz.leftZeroRelationsArbitrary( L ); assertTrue("is ZR( { a } )", ssz.isLeftZeroRelation(K,L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); K = ssz.leftZeroRelationsArbitrary( L ); //System.out.println("\nN = " + N ); assertTrue("is ZR( { a, b } )", ssz.isLeftZeroRelation(K,L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); K = ssz.leftZeroRelationsArbitrary( L ); //System.out.println("\nN = " + N ); assertTrue("is ZR( { a, b, c } )", ssz.isLeftZeroRelation(K,L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); K = ssz.leftZeroRelationsArbitrary( L ); //System.out.println("\nN = " + N ); assertTrue("is ZR( { a, b, c, d } )", ssz.isLeftZeroRelation(K,L) ); //System.out.println("N = " + N ); } /** * Test sequential arbitrary base Syzygy, ex CLO 2, p 214 ff. * */ @SuppressWarnings("unchecked") public void testSequentialArbitrarySyzygyCLO() { PolynomialList F = null; String exam = "Rat(x,y) G " + "( " + "( x y + x ), " + "( y^2 + 1 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextSolvablePolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); L = F.castToSolvableList(); K = ssz.leftZeroRelationsArbitrary( L ); assertTrue("is ZR( { a, b } )", ssz.isLeftZeroRelation(K,L) ); } /** * Test sequential arbitrary base Syzygy, ex WA_32. * */ @SuppressWarnings("unchecked") public void testSequentialArbitrarySyzygyWA32() { PolynomialList F = null; String exam = "Rat(e1,e2,e3) L " + "RelationTable " + "( " + " ( e3 ), ( e1 ), ( e1 e3 - e1 ), " + " ( e3 ), ( e2 ), ( e2 e3 - e2 ) " + ")" + "( " + " ( e1 e3^3 + e2^2 ), " + " ( e1^3 e2^2 + e3 ), " + " ( e3^3 + e3^2 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextSolvablePolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); L = F.castToSolvableList(); K = ssz.leftZeroRelationsArbitrary( L ); assertTrue("is ZR( { a, b } )", ssz.isLeftZeroRelation(K,L) ); } /** * Test sequential arbitrary module SolvableSyzygy. * */ public void testSequentialArbitraryModSolvableSyzygy() { W = new ArrayList>>(); assertTrue("not isZERO( a )", !a.isZERO() ); V = new ArrayList>(); V.add(a); V.add(zero); V.add(one); W.add(V); M = new ModuleList(fac,W); assertTrue("isGB( { (a,0,1) } )", msbb.isLeftGB(M) ); Z = ssz.leftZeroRelationsArbitrary(M); //System.out.println("Z = " + Z); assertTrue("is ZR( { a) } )", ssz.isLeftZeroRelation(Z,M) ); assertTrue("not isZERO( b )", !b.isZERO() ); V = new ArrayList>(); V.add(b); V.add(one); V.add(zero); W.add(V); M = new ModuleList(fac,W); //System.out.println("W = " + W.size() ); Z = ssz.leftZeroRelationsArbitrary(M); //System.out.println("Z = " + Z); assertTrue("is ZR( { a, b } )", ssz.isLeftZeroRelation(Z,M) ); assertTrue("not isZERO( c )", !c.isZERO() ); V = new ArrayList>(); V.add(c); V.add(one); V.add(zero); W.add(V); M = new ModuleList(fac,W); //System.out.println("W = " + W.size() ); Z = ssz.leftZeroRelationsArbitrary(M); //System.out.println("Z = " + Z); //boolean b = ssz.isLeftZeroRelation(Z,N); //System.out.println("boolean = " + b); assertTrue("is ZR( { a,b,c } )", ssz.isLeftZeroRelation(Z,M) ); } /** * Test Ore conditions. */ public void testOreConditions() { do { a = fac.random(kl, ll-1, el, q); b = fac.random(kl, ll-1, el, q); } while ( a.isZERO() || b.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); //SolvableIdeal I = new SolvableIdeal(fac); GenSolvablePolynomial[] oc = ssz.leftOreCond(a,b); //System.out.println("oc[0] = " + oc[0]); //System.out.println("oc[1] = " + oc[1]); c = oc[0].multiply(a); d = oc[1].multiply(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("c_0 * a = c_1 * b: ", c, d); assertTrue("left Ore condition: ", ssz.isLeftOreCond(a,b,oc)); oc = ssz.rightOreCond(a,b); //System.out.println("oc[0] = " + oc[0]); //System.out.println("oc[1] = " + oc[1]); c = a.multiply(oc[0]); d = b.multiply(oc[1]); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a * c_0 = b * c_1: ", c, d); assertTrue("left Ore condition: ", ssz.isRightOreCond(a,b,oc)); } } jas-2.5/trc/edu/jas/gbmod/SolvableQuotientTest.java0000644000175000017500000002124212137505254022565 0ustar giovannigiovanni /* * $Id: SolvableQuotientTest.java 4400 2013-04-29 14:58:52Z kredel $ */ package edu.jas.gbmod; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.poly.WeylRelations; import edu.jas.kern.PrettyPrint; import edu.jas.kern.ComputerThreads; /** * SolvableQuotient over BigRational GenSolvablePolynomial tests with JUnit. * @author Heinz Kredel. */ public class SolvableQuotientTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a SolvableQuotientTest object. * @param name String. */ public SolvableQuotientTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(SolvableQuotientTest.class); return suite; } SolvableQuotientRing zFac; SolvableQuotientRing efac; GenSolvablePolynomialRing mfac; SolvableQuotient< BigRational > a, b, c, d, e; SolvableQuotient< BigRational > az, bz, cz, dz, ez; int rl = 4; int kl = 3; int ll = 3; //6; int el = 2; float q = 0.2f; protected void setUp() { a = b = c = d = e = null; TermOrder to = new TermOrder( TermOrder.INVLEX ); String[] vars = new String[] { "w", "x", "y", "z" }; mfac = new GenSolvablePolynomialRing( new BigRational(1), rl, to, vars ); WeylRelations wl = new WeylRelations(mfac); wl.generate(); efac = new SolvableQuotientRing( mfac ); zFac = new SolvableQuotientRing( mfac ); } protected void tearDown() { a = b = c = d = e = null; //efac.terminate(); efac = null; zFac = null; ComputerThreads.terminate(); } /** * Test constructor and toString. */ public void testConstruction() { c = efac.getONE(); //System.out.println("c = " + c); //System.out.println("c.val = " + c.val); assertTrue("length( c ) = 1", c.num.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = efac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.val = " + d.val); assertTrue("length( d ) = 0", d.num.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); for (SolvableQuotient g : efac.generators() ) { //System.out.println("g = " + g); assertFalse("not isZERO( g )", g.isZERO() ); } } /** * Test random polynomial. */ public void testRandom() { for (int i = 0; i < 7; i++) { //a = efac.random(ll+i); a = efac.random(kl*(i+1), ll+2+2*i, el, q ); //System.out.println("a = " + a); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.num.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); assertEquals("a == a: ", a, a ); } } /** * Test addition. */ public void testAddition() { a = efac.random(kl,ll,el,q); b = efac.random(kl,ll,el,q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.sum( efac.getZERO() ); d = a.subtract( efac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = efac.getZERO().sum( a ); d = efac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); c = a.sum(b); d = c.subtract(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b-b = a", a, d); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",c,d); //c = efac.random(kl,ll,el,q); c = new SolvableQuotient(efac, mfac.univariate(1,2)); //efac.random(kl,ll,el,q); //System.out.println("c = " + c); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("c+(a+b) = (c+a)+b",d,e); } /** * Test multiplication. */ public void testMultiplication() { a = efac.random(kl,ll,el,q); b = efac.random(kl,ll,el,q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.multiply( efac.getONE() ); d = efac.getONE().multiply( a ); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*1 = 1*a",c,a); assertEquals("a*1 = 1*a",c,d); c = b.multiply(a); d = a.multiply(b); //System.out.println("c = " + c); //System.out.println("d = " + d); //non-com assertFalse("a*b = b*a", c.equals(d) ); //e = d.subtract(c); //non-com assertFalse("not isZERO( a*b-b*a ) " + e, e.isZERO() ); c = new SolvableQuotient(efac, mfac.univariate(1,2)); //efac.random(kl,ll,el,q); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); //System.out.println("d = " + d); e = (a.multiply(b)).multiply(c); //System.out.println("e = " + e); assertEquals("a(bc) = (ab)c",d,e); //assertTrue("a(bc) = (ab)c", d.equals(e) ); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",d.isONE()); } } /** * Test addition with syzygy gcd and euclids gcd. */ public void ytestAdditionGcd() { long te, tz; a = efac.random(kl,ll,el,q); b = efac.random(kl,ll,el,q); //System.out.println("a = " + a); //System.out.println("b = " + b); az = new SolvableQuotient(zFac,a.num,a.den,true); bz = new SolvableQuotient(zFac,b.num,b.den,true); if ( true ) { return; } te = System.currentTimeMillis(); c = a.sum(b); d = c.subtract(b); d = d.monic(); te = System.currentTimeMillis() - te; assertEquals("a+b-b = a",a,d); tz = System.currentTimeMillis(); cz = az.sum(bz); dz = cz.subtract(bz); dz = dz.monic(); tz = System.currentTimeMillis() - tz; assertEquals("a+b-b = a",az,dz); System.out.println("te = " + te); System.out.println("tz = " + tz); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",c,d); c = efac.random(kl,ll,el,q); cz = new SolvableQuotient(zFac,c.num,c.den,true); te = System.currentTimeMillis(); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); te = System.currentTimeMillis() - te; assertEquals("c+(a+b) = (c+a)+b",d,e); tz = System.currentTimeMillis(); dz = cz.sum( az.sum(bz) ); ez = cz.sum( az ).sum(bz); tz = System.currentTimeMillis() - tz; assertEquals("c+(a+b) = (c+a)+b",dz,ez); System.out.println("te = " + te); System.out.println("tz = " + tz); c = a.sum( efac.getZERO() ); d = a.subtract( efac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = efac.getZERO().sum( a ); d = efac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test parse. */ public void testParse() { a = efac.random(kl*2,ll*2,el*2,q*2); //PrettyPrint.setInternal(); //System.out.println("a = " + a); PrettyPrint.setPretty(); //System.out.println("a = " + a); String p = a.toString(); //System.out.println("p = " + p); b = efac.parse(p); //System.out.println("b = " + b); //c = a.subtract(b); //System.out.println("c = " + c); assertEquals("parse(a.toSting()) = a",a,b); } } jas-2.5/trc/edu/jas/gbmod/SyzygyTest.java0000644000175000017500000002454211641660762020616 0ustar giovannigiovanni/* * $Id: SyzygyTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gbmod; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBase; import edu.jas.gbufd.GBFactory; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; /** * Syzygy tests with JUnit. * @author Heinz Kredel. */ public class SyzygyTest extends TestCase { //private static final Logger logger = Logger.getLogger(SyzygyTest.class); /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a SyzygyTest object. * @param name String. */ public SyzygyTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(SyzygyTest.class); return suite; } GenPolynomialRing fac; PolynomialList F; List> G; GroebnerBase bb; ModGroebnerBase mbb; Syzygy sz; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial zero; GenPolynomial one; TermOrder tord; List> L; List>> K; List> V; List>> W; ModuleList M; ModuleList N; ModuleList Z; int rl = 3; //4; //3; int kl = 3; //7; int ll = 7; //9; int el = 2; float q = 0.3f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(9); tord = new TermOrder(); fac = new GenPolynomialRing(coeff, rl, tord); bb = GBFactory.getImplementation(coeff); mbb = new ModGroebnerBaseAbstract(coeff); sz = new SyzygyAbstract(); a = b = c = d = e = null; L = null; K = null; V = null; do { a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); } while (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()); e = d; //fac.random(kl, ll, el, q ); one = fac.getONE(); zero = fac.getZERO(); } @Override protected void tearDown() { a = b = c = d = e = null; L = null; K = null; V = null; fac = null; tord = null; bb = null; mbb = null; sz = null; } /** * Test sequential Syzygy. * */ public void testSequentialSyzygy() { L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); assertTrue("isGB( { a } )", bb.isGB(L)); K = sz.zeroRelations(L); assertTrue("is ZR( { a } )", sz.isZeroRelation(K, L)); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); L = bb.GB(L); assertTrue("isGB( { a, b } )", bb.isGB(L)); //System.out.println("\nL = " + L ); K = sz.zeroRelations(L); //System.out.println("\nN = " + N ); assertTrue("is ZR( { a, b } )", sz.isZeroRelation(K, L)); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.GB(L); //System.out.println("\nL = " + L ); assertTrue("isGB( { a, b, c } )", bb.isGB(L)); K = sz.zeroRelations(L); //System.out.println("\nN = " + N ); assertTrue("is ZR( { a, b, c } )", sz.isZeroRelation(K, L)); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.GB(L); //System.out.println("\nL = " + L ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L)); K = sz.zeroRelations(L); //System.out.println("\nN = " + N ); assertTrue("is ZR( { a, b, c, d } )", sz.isZeroRelation(K, L)); //System.out.println("N = " + N ); /* */ } /** * Test sequential module Syzygy. * */ public void testSequentialModSyzygy() { W = new ArrayList>>(); assertTrue("not isZERO( a )", !a.isZERO()); V = new ArrayList>(); V.add(a); V.add(zero); V.add(one); W.add(V); M = new ModuleList(fac, W); assertTrue("isGB( { (a,0,1) } )", mbb.isGB(M)); N = mbb.GB(M); assertTrue("isGB( { (a,0,1) } )", mbb.isGB(N)); Z = sz.zeroRelations(N); //System.out.println("Z = " + Z); assertTrue("is ZR( { a) } )", sz.isZeroRelation(Z, N)); assertTrue("not isZERO( b )", !b.isZERO()); V = new ArrayList>(); V.add(b); V.add(one); V.add(zero); W.add(V); M = new ModuleList(fac, W); //System.out.println("W = " + W.size() ); N = mbb.GB(M); assertTrue("isGB( { a, b } )", mbb.isGB(N)); Z = sz.zeroRelations(N); //System.out.println("Z = " + Z); assertTrue("is ZR( { a, b } )", sz.isZeroRelation(Z, N)); assertTrue("not isZERO( c )", !c.isZERO()); V = new ArrayList>(); V.add(c); V.add(one); V.add(zero); W.add(V); M = new ModuleList(fac, W); //System.out.println("W = " + W.size() ); N = mbb.GB(M); //System.out.println("GB(M) = " + N); assertTrue("isGB( { a,b,c) } )", mbb.isGB(N)); Z = sz.zeroRelations(N); //System.out.println("Z = " + Z); //boolean b = Syzygy.isZeroRelation(Z,N); //System.out.println("boolean = " + b); assertTrue("is ZR( { a,b,c } )", sz.isZeroRelation(Z, N)); } /** * Test sequential arbitrary base Syzygy. * */ public void testSequentialArbitrarySyzygy() { L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); assertTrue("isGB( { a } )", bb.isGB(L)); K = sz.zeroRelationsArbitrary(L); assertTrue("is ZR( { a } )", sz.isZeroRelation(K, L)); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); // L = bb.GB(L); // assertTrue("isGB( { a, b } )", bb.isGB(L) ); //System.out.println("\nL = " + L ); K = sz.zeroRelationsArbitrary(L); //System.out.println("\nN = " + N ); assertTrue("is ZR( { a, b } )", sz.isZeroRelation(K, L)); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); //L = bb.GB(L); //System.out.println("\nL = " + L ); //assertTrue("isGB( { a, b, c } )", bb.isGB(L) ); K = sz.zeroRelationsArbitrary(L); //System.out.println("\nN = " + N ); assertTrue("is ZR( { a, b, c } )", sz.isZeroRelation(K, L)); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); //L = bb.GB(L); //System.out.println("\nL = " + L ); //assertTrue("isGB( { a, b, c, d } )", bb.isGB(L) ); K = sz.zeroRelationsArbitrary(L); //System.out.println("\nN = " + N ); assertTrue("is ZR( { a, b, c, d } )", sz.isZeroRelation(K, L)); //System.out.println("N = " + N ); } /** * Test sequential arbitrary base Syzygy, ex CLO 2, p 214 ff. * */ @SuppressWarnings("unchecked") // not jet working public void testSequentialArbitrarySyzygyCLO() { PolynomialList F = null; String exam = "(x,y) G " + "( " + "( x y + x ), " + "( y^2 + 1 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); L = F.list; K = sz.zeroRelationsArbitrary(L); assertTrue("is ZR( { a, b } )", sz.isZeroRelation(K, L)); } /** * Test sequential arbitrary module Syzygy. * */ public void testSequentialArbitraryModSyzygy() { W = new ArrayList>>(); assertTrue("not isZERO( a )", !a.isZERO()); V = new ArrayList>(); V.add(a); V.add(zero); V.add(one); W.add(V); M = new ModuleList(fac, W); assertTrue("isGB( { (a,0,1) } )", mbb.isGB(M)); Z = sz.zeroRelationsArbitrary(M); //System.out.println("Z = " + Z); assertTrue("is ZR( { a) } )", sz.isZeroRelation(Z, M)); assertTrue("not isZERO( b )", !b.isZERO()); V = new ArrayList>(); V.add(b); V.add(one); V.add(zero); W.add(V); M = new ModuleList(fac, W); //System.out.println("W = " + W.size() ); Z = sz.zeroRelationsArbitrary(M); //System.out.println("Z = " + Z); assertTrue("is ZR( { a, b } )", sz.isZeroRelation(Z, M)); assertTrue("not isZERO( c )", !c.isZERO()); V = new ArrayList>(); V.add(c); V.add(one); V.add(zero); W.add(V); M = new ModuleList(fac, W); //System.out.println("W = " + W.size() ); Z = sz.zeroRelationsArbitrary(M); //System.out.println("Z = " + Z); //boolean b = Syzygy.isZeroRelation(Z,N); //System.out.println("boolean = " + b); assertTrue("is ZR( { a,b,c } )", sz.isZeroRelation(Z, M)); } } jas-2.5/trc/edu/jas/gbmod/ModSolvableGroebnerBaseTest.java0000644000175000017500000003405211641660762023763 0ustar giovannigiovanni/* * $Id: ModSolvableGroebnerBaseTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gbmod; //import edu.jas.poly.GroebnerBase; import java.util.List; import java.util.ArrayList; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; //import edu.jas.structure.RingElem; import edu.jas.arith.BigRational; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.poly.RelationTable; import edu.jas.poly.WeylRelations; /** * ModSolvableGroebnerBase tests with JUnit. * @author Heinz Kredel. */ public class ModSolvableGroebnerBaseTest extends TestCase { //private static final Logger logger = Logger.getLogger(ModSolvableGroebnerBaseTest.class); /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ModSolvableGroebnerBaseTest object. * @param name String. */ public ModSolvableGroebnerBaseTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ModSolvableGroebnerBaseTest.class); return suite; } int port = 4711; String host = "localhost"; BigRational cfac; GenSolvablePolynomialRing pfac; GenSolvablePolynomial a; GenSolvablePolynomial b; GenSolvablePolynomial c; GenSolvablePolynomial d; GenSolvablePolynomial e; TermOrder tord; GenSolvablePolynomial one; GenSolvablePolynomial zero; RelationTable table; List>> L; List> V; PolynomialList F; PolynomialList G; ModuleList M; ModuleList N; ModSolvableGroebnerBase msbb; int rl = 3; //4; //3; int kl = 4; int ll = 3; int el = 2; float q = 0.2f; //0.4f protected void setUp() { a = b = c = d = e = null; cfac = new BigRational(1); tord = new TermOrder(); pfac = new GenSolvablePolynomialRing(cfac,rl,tord); msbb = new ModSolvableGroebnerBaseAbstract(); do { a = pfac.random(kl, ll, el, q ); b = pfac.random(kl, ll, el, q ); c = pfac.random(kl, ll, el, q ); d = pfac.random(kl, ll, el, q ); } while ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ); e = d; // = pfac.random(kl, ll, el, q ); one = pfac.getONE(); zero = pfac.getZERO(); } protected void tearDown() { a = b = c = d = e = null; one = null; zero = null; msbb = null; } /** * Test sequential left GBase. * */ public void testSequentialLeftModSolvableGB() { assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>>(); V = new ArrayList>(); V.add(a); V.add(zero); V.add(one); L.add(V); M = new ModuleList(pfac,L); assertTrue("isLeftGB( { (a,0,1) } )", msbb.isLeftGB(M) ); //System.out.println("M = " + M ); N = msbb.leftGB( M ); //System.out.println("N = " + N ); assertTrue("isLeftGB( { (a,0,1) } )", msbb.isLeftGB(N) ); assertTrue("not isZERO( b )", !b.isZERO() ); V = new ArrayList>(); V.add(b); V.add(one); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("L = " + L.size() ); N = msbb.leftGB( M ); assertTrue("isLeftGB( { (a,0,1),(b,1,0) } )", msbb.isLeftGB(N) ); //System.out.println("N = " + N ); assertTrue("not isZERO( c )", !c.isZERO() ); V = new ArrayList>(); V.add(c); V.add(zero); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("M = " + M ); //System.out.println("L = " + L.size() ); N = msbb.leftGB( M ); assertTrue("isLeftGB( { (a,),(b,),(c,) } )", msbb.isLeftGB(N) ); //System.out.println("N = " + N ); assertTrue("not isZERO( d )", !d.isZERO() ); V = new ArrayList>(); V.add(d); V.add(zero); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("M = " + M ); //System.out.println("L = " + L.size() ); N = msbb.leftGB( M ); assertTrue("isLeftGB( { (a,b,c,d) } )", msbb.isLeftGB(N) ); //System.out.println("N = " + N ); } /** * Test sequential twosided GBase. * */ public void testSequentialTSModSolvableGB() { assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>>(); V = new ArrayList>(); V.add(a); V.add(zero); V.add(one); L.add(V); M = new ModuleList(pfac,L); assertTrue("isTwosidedGB( { (a,0,1) } )", msbb.isTwosidedGB(M) ); N = msbb.twosidedGB( M ); assertTrue("isTwosidedGB( { (a,0,1) } )", msbb.isTwosidedGB(N) ); assertTrue("not isZERO( b )", !b.isZERO() ); V = new ArrayList>(); V.add(b); V.add(one); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("L = " + L.size() ); N = msbb.twosidedGB( M ); assertTrue("isTwosidedGB( { (a,0,1),(b,1,0) } )", msbb.isTwosidedGB(N) ); //System.out.println("N = " + N ); assertTrue("not isZERO( c )", !c.isZERO() ); V = new ArrayList>(); V.add(c); V.add(zero); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("L = " + L.size() ); N = msbb.twosidedGB( M ); assertTrue("isTwosidedGB( { (a,),(b,),(c,) } )", msbb.isTwosidedGB(N) ); //System.out.println("N = " + N ); assertTrue("not isZERO( d )", !d.isZERO() ); V = new ArrayList>(); V.add(d); V.add(zero); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("L = " + L.size() ); N = msbb.twosidedGB( M ); assertTrue("isTwosidedGB( { (a,b,c,d) } )", msbb.isTwosidedGB(N) ); //System.out.println("N = " + N ); } /** * Test sequential Weyl GBase. * */ public void testSequentialLeftModSolvableWeylGB() { int rloc = 4; pfac = new GenSolvablePolynomialRing(cfac,rloc,tord); //System.out.println("pfac = " + pfac); //System.out.println("pfac end"); WeylRelations wl = new WeylRelations(pfac); //System.out.println("wl = "); wl.generate(); //System.out.println("generate = "); table = pfac.table; //System.out.println("table = "); //System.out.println("table = " + table.size()); do { a = pfac.random(kl, ll, el, q ); b = pfac.random(kl, ll, el, q ); c = pfac.random(kl, ll, el, q ); d = pfac.random(kl, ll, el, q ); } while ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ); e = d; // = pfac.random(kl, ll, el, q ); one = pfac.getONE(); zero = pfac.getZERO(); //System.out.println("a = " + a ); //System.out.println("b = " + b ); //System.out.println("c = " + c ); //System.out.println("d = " + d ); //System.out.println("e = " + e ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>>(); V = new ArrayList>(); V.add(a); V.add(zero); V.add(one); L.add(V); M = new ModuleList(pfac,L); assertTrue("isLeftGB( { (a,0,1) } )", msbb.isLeftGB(M) ); N = msbb.leftGB( M ); assertTrue("isLeftGB( { (a,0,1) } )", msbb.isLeftGB(N) ); assertTrue("not isZERO( b )", !b.isZERO() ); V = new ArrayList>(); V.add(b); V.add(one); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("L = " + L.size() ); N = msbb.leftGB( M ); assertTrue("isLeftGB( { (a,0,1),(b,1,0) } )", msbb.isLeftGB(N) ); //System.out.println("N = " + N ); assertTrue("not isZERO( c )", !c.isZERO() ); V = new ArrayList>(); V.add(c); V.add(zero); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("M = " + M ); //System.out.println("L = " + L.size() ); N = msbb.leftGB( M ); assertTrue("isLeftGB( { (a,),(b,),(c,) } )", msbb.isLeftGB(N) ); //System.out.println("N = " + N ); assertTrue("not isZERO( d )", !d.isZERO() ); V = new ArrayList>(); V.add(d); V.add(zero); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("M = " + M ); //System.out.println("L = " + L.size() ); N = msbb.leftGB( M ); assertTrue("isLeftGB( { (a,b,c,d) } )", msbb.isLeftGB(N) ); //System.out.println("N = " + N ); } /** * Test sequential right GBase. * */ public void testSequentialRightModSolvableGB() { assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>>(); V = new ArrayList>(); V.add(a); V.add(zero); V.add(one); L.add(V); M = new ModuleList(pfac,L); assertTrue("isRightGB( { (a,0,1) } )", msbb.isRightGB(M) ); //System.out.println("M = " + M ); N = msbb.rightGB( M ); //System.out.println("N = " + N ); assertTrue("isRightGB( { (a,0,1) } )", msbb.isRightGB(N) ); assertTrue("not isZERO( b )", !b.isZERO() ); V = new ArrayList>(); V.add(b); V.add(one); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("L = " + L.size() ); //System.out.println("M = " + M ); N = msbb.rightGB( M ); //System.out.println("N = " + N ); assertTrue("isRightGB( { (a,0,1),(b,1,0) } )", msbb.isRightGB(N) ); assertTrue("not isZERO( c )", !c.isZERO() ); V = new ArrayList>(); V.add(c); V.add(zero); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("M = " + M ); //System.out.println("L = " + L.size() ); N = msbb.rightGB( M ); assertTrue("isRightGB( { (a,),(b,),(c,) } )", msbb.isRightGB(N) ); //System.out.println("N = " + N ); assertTrue("not isZERO( d )", !d.isZERO() ); V = new ArrayList>(); V.add(d); V.add(zero); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("M = " + M ); //System.out.println("L = " + L.size() ); N = msbb.rightGB( M ); assertTrue("isRightGB( { (a,b,c,d) } )", msbb.isRightGB(N) ); //System.out.println("N = " + N ); } /** * Test sequential Weyl GBase. * */ public void testSequentialRightModSolvableWeylGB() { int rloc = 4; pfac = new GenSolvablePolynomialRing(cfac,rloc,tord); //System.out.println("pfac = " + pfac); //System.out.println("pfac end"); WeylRelations wl = new WeylRelations(pfac); //System.out.println("wl = "); wl.generate(); //System.out.println("generate = "); table = pfac.table; //System.out.println("table = "); //System.out.println("table = " + table.size()); do { a = pfac.random(kl, ll, el, q ); b = pfac.random(kl, ll, el, q ); c = pfac.random(kl, ll, el, q ); d = pfac.random(kl, ll, el, q ); } while ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ); e = d; // = pfac.random(kl, ll, el, q ); one = pfac.getONE(); zero = pfac.getZERO(); //System.out.println("a = " + a ); //System.out.println("b = " + b ); //System.out.println("c = " + c ); //System.out.println("d = " + d ); //System.out.println("e = " + e ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>>(); V = new ArrayList>(); V.add(a); V.add(zero); V.add(one); L.add(V); M = new ModuleList(pfac,L); assertTrue("isRightGB( { (a,0,1) } )", msbb.isRightGB(M) ); N = msbb.rightGB( M ); assertTrue("isRightGB( { (a,0,1) } )", msbb.isRightGB(N) ); assertTrue("not isZERO( b )", !b.isZERO() ); V = new ArrayList>(); V.add(b); V.add(one); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("L = " + L.size() ); //System.out.println("M = " + M ); N = msbb.rightGB( M ); //System.out.println("N = " + N ); assertTrue("isRightGB( { (a,0,1),(b,1,0) } )", msbb.isRightGB(N) ); assertTrue("not isZERO( c )", !c.isZERO() ); V = new ArrayList>(); V.add(c); V.add(zero); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("M = " + M ); //System.out.println("L = " + L.size() ); N = msbb.rightGB( M ); assertTrue("isRightGB( { (a,),(b,),(c,) } )", msbb.isRightGB(N) ); //System.out.println("N = " + N ); assertTrue("not isZERO( d )", !d.isZERO() ); V = new ArrayList>(); V.add(d); V.add(zero); V.add(zero); L.add(V); M = new ModuleList(pfac,L); //System.out.println("M = " + M ); //System.out.println("L = " + L.size() ); N = msbb.rightGB( M ); assertTrue("isRightGB( { (a,b,c,d) } )", msbb.isRightGB(N) ); //System.out.println("N = " + N ); } } jas-2.5/trc/edu/jas/application/0000755000175000017500000000000012140140260016756 5ustar giovannigiovannijas-2.5/trc/edu/jas/application/FactorAlgebraicPrimTest.java0000644000175000017500000001247512014152710024335 0ustar giovannigiovanni/* * $Id: FactorAlgebraicPrimTest.java 4110 2012-08-19 12:02:16Z kredel $ */ package edu.jas.application; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Factor algebraic tests with JUnit. * @author Heinz Kredel. */ public class FactorAlgebraicPrimTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructor. * @param name String. */ public FactorAlgebraicPrimTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorAlgebraicPrimTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. * */ public void testDummy() { } /** * Test algebraic factorization. * */ public void testAlgebraicFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] alpha = new String[] { "alpha" }; String[] vars = new String[] { "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, alpha); GenPolynomial agen = pfac.univariate(0, 2); agen = agen.sum(pfac.getONE()); // x^2 + 1 AlgebraicNumberRing afac = new AlgebraicNumberRing(agen, true); GenPolynomialRing> apfac = new GenPolynomialRing>( afac, 1, to, vars); // univariate //System.out.println("agen = " + agen); //System.out.println("afac = " + afac); //System.out.println("apfac = " + apfac); FactorAlgebraicPrim fac = new FactorAlgebraicPrim(afac); for (int i = 1; i < 7; i++) { int facs = 0; GenPolynomial> a; GenPolynomial> c = apfac.random(2, ll + i, el + i, q); //a = a.monic(); GenPolynomial> b = apfac.random(2, ll + i, el + i, q); if (b.degree() == 0) { b = b.multiply(apfac.univariate(0)); } //b = b.monic(); //if ( false && ! a.leadingBaseCoefficient().isONE() ) { //continue; //ExpVector e = a.leadingExpVector(); //a.doPutToMap(e,cfac.getONE()); //} if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } //a = apfac.univariate(0,2).sum( apfac.getONE() ); // x^2 + 1 //a = a.multiply(a); //a = a.multiply( apfac.univariate(0,2).subtract( apfac.getONE() ) ); // x^2 - 1 //a = apfac.univariate(0,3).subtract( apfac.getONE() ); // x^3 - 1 //a = apfac.univariate(0,3).sum( apfac.getONE() ); // x^3 + 1 a = c.multiply(b); //a = a.monic(); //System.out.println("\na = " + a); //System.out.println("b = " + b.monic()); //System.out.println("c = " + c.monic()); SortedMap>, Long> smi, smr; long si = System.currentTimeMillis(); smi = fac.baseFactors(a); si = System.currentTimeMillis() - si; //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (smi.size() >= facs) { assertTrue("#facs < " + facs, smi.size() >= facs); } else { System.out.println("smi.size() < facs = " + facs); } boolean t = fac.isFactorization(a, smi); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); long sr = System.currentTimeMillis(); smr = new edu.jas.ufd.FactorAlgebraic(afac).baseFactors(a); sr = System.currentTimeMillis() - sr; //System.out.println("\na = " + a); //System.out.println("smr = " + smr); if (smr.size() >= facs) { assertTrue("#facs < " + facs, smr.size() >= facs); } else { System.out.println("smr.size() < facs = " + facs); } t = fac.isFactorization(a, smr); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); //System.out.println("time: si = " + si + ", sr = " + sr + " milliseconds"); assertTrue("positive times", sr >= 0L && si >= 0L); assertEquals("smi == smr: ", smi, smr); } } } jas-2.5/trc/edu/jas/application/GBAlgorithmBuilderTest.java0000644000175000017500000003146212067140212024142 0ustar giovannigiovanni/* * $Id: GBAlgorithmBuilderTest.java 4328 2012-12-27 21:41:30Z kredel $ */ package edu.jas.application; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.gb.DGroebnerBaseSeq; import edu.jas.gb.EGroebnerBaseSeq; import edu.jas.gb.GBOptimized; import edu.jas.gb.GBProxy; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.GroebnerBaseParallel; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.gbufd.GBFactory; import edu.jas.gbufd.GroebnerBaseFGLM; import edu.jas.gbufd.GroebnerBasePseudoSeq; import edu.jas.gbufd.GroebnerBaseRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; /** * GBAlgorithmBuilder tests with JUnit. * @author Heinz Kredel. */ public class GBAlgorithmBuilderTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GBAlgorithmBuilderTest object. * @param name String. */ public GBAlgorithmBuilderTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GBAlgorithmBuilderTest.class); return suite; } GBAlgorithmBuilder builder; @Override protected void setUp() { builder = null; } @Override protected void tearDown() { builder = null; ComputerThreads.terminate(); } /** * Test basic construction for BigRational. */ public void testConstructionRational() { BigRational bf = new BigRational(1); String[] vars = new String[] { "a", "b", "c" }; GenPolynomialRing pf = new GenPolynomialRing(bf, vars); GBAlgorithmBuilder ab = GBAlgorithmBuilder. polynomialRing(pf); //System.out.println("ab = " + ab); GroebnerBaseAbstract bb = ab.build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof GroebnerBaseSeq); } /** * Test construction for BigRational and FGLM. */ public void testConstructionRationalFGLM() { BigRational bf = new BigRational(1); String[] vars = new String[] { "a", "b", "c" }; GenPolynomialRing pf = new GenPolynomialRing(bf, vars); GBAlgorithmBuilder ab = GBAlgorithmBuilder. polynomialRing(pf); //System.out.println("ab = " + ab); ab = ab.graded(); //System.out.println("ab = " + ab); GroebnerBaseAbstract bb = ab.build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof GroebnerBaseFGLM); } /** * Test construction for BigRational and parallel. */ public void testConstructionRationalParallel() { BigRational bf = new BigRational(1); String[] vars = new String[] { "a", "b", "c" }; GenPolynomialRing pf = new GenPolynomialRing(bf, vars); GBAlgorithmBuilder ab = GBAlgorithmBuilder. polynomialRing(pf); //System.out.println("ab = " + ab); ab = ab.parallel(); //System.out.println("ab = " + ab); GroebnerBaseAbstract bb = ab.build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof GBProxy); GBProxy bbp = (GBProxy) bb; assertTrue("instance of " + bbp.e1, bbp.e1 instanceof GroebnerBaseSeq); assertTrue("instance of " + bbp.e2, bbp.e2 instanceof GroebnerBaseParallel); } /** * Test construction for BigRational fraction free and parallel. */ public void testConstructionRationalFFParallel() { BigRational bf = new BigRational(1); String[] vars = new String[] { "a", "b", "c" }; GenPolynomialRing pf = new GenPolynomialRing(bf, vars); GBAlgorithmBuilder ab = GBAlgorithmBuilder. polynomialRing(pf); //System.out.println("ab = " + ab); ab = ab.fractionFree(); //System.out.println("ab = " + ab); ab = ab.parallel(); //System.out.println("ab = " + ab); GroebnerBaseAbstract bb = ab.build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof GBProxy); GBProxy bbp = (GBProxy) bb; assertTrue("instance of " + bbp.e1, bbp.e1 instanceof GroebnerBaseRational); assertTrue("instance of " + bbp.e2, bbp.e2 instanceof GroebnerBaseRational); } /** * Test construction for BigRational and optimize. */ public void testConstructionRationalOptimized() { BigRational bf = new BigRational(1); String[] vars = new String[] { "a", "b", "c" }; GenPolynomialRing pf = new GenPolynomialRing(bf, vars); GBAlgorithmBuilder ab = GBAlgorithmBuilder. polynomialRing(pf); //System.out.println("ab = " + ab); ab = ab.optimize(); //System.out.println("ab = " + ab); GroebnerBaseAbstract bb = ab.build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof GBOptimized); } /** * Test construction for BigRational and fraction free. */ public void testConstructionRationalFF() { BigRational bf = new BigRational(1); String[] vars = new String[] { "a", "b", "c" }; GenPolynomialRing pf = new GenPolynomialRing(bf, vars); GBAlgorithmBuilder ab = GBAlgorithmBuilder. polynomialRing(pf); //System.out.println("ab = " + ab); ab = ab.fractionFree(); //System.out.println("ab = " + ab); GroebnerBaseAbstract bb = ab.build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof GroebnerBaseRational); } /** * Test basic construction for BigInteger. */ public void testConstructionInteger() { BigInteger bf = new BigInteger(1); String[] vars = new String[] { "a", "b", "c" }; GenPolynomialRing pf = new GenPolynomialRing(bf, vars); GBAlgorithmBuilder ab = GBAlgorithmBuilder. polynomialRing(pf); //System.out.println("ab = " + ab); GroebnerBaseAbstract bb = ab.build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof GroebnerBasePseudoSeq); } /** * Test construction for d-GB BigInteger. */ public void testConstructionIntegerDGB() { BigInteger bf = new BigInteger(1); String[] vars = new String[] { "a", "b", "c" }; GenPolynomialRing pf = new GenPolynomialRing(bf, vars); GBAlgorithmBuilder ab = GBAlgorithmBuilder. polynomialRing(pf); //System.out.println("ab = " + ab); ab = ab.domainAlgorithm(GBFactory.Algo.dgb); //System.out.println("ab = " + ab); GroebnerBaseAbstract bb = ab.build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof DGroebnerBaseSeq); } /** * Test construction for e-GB BigInteger. */ public void testConstructionIntegerEGB() { BigInteger bf = new BigInteger(1); String[] vars = new String[] { "a", "b", "c" }; GenPolynomialRing pf = new GenPolynomialRing(bf, vars); GBAlgorithmBuilder ab = GBAlgorithmBuilder. polynomialRing(pf); //System.out.println("ab = " + ab); ab = ab.domainAlgorithm(GBFactory.Algo.egb); //System.out.println("ab = " + ab); GroebnerBaseAbstract bb = ab.build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof EGroebnerBaseSeq); } /** * Test construction for BigRational and more. */ public void testConstructionRationalMore() { BigRational bf = new BigRational(1); String[] vars = new String[] { "a", "b", "c" }; GenPolynomialRing pf = new GenPolynomialRing(bf, vars); GroebnerBaseAbstract bb = GBAlgorithmBuilder. polynomialRing(pf) .fractionFree().optimize().build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof GBOptimized); bb = GBAlgorithmBuilder. polynomialRing(pf).fractionFree().parallel().optimize().build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof GBOptimized); bb = GBAlgorithmBuilder. polynomialRing(pf).fractionFree().graded().parallel() .optimize().build(); //System.out.println("bb = " + bb); assertTrue("instance of " + bb, bb instanceof GBOptimized); } /** * Test construction for BigRational and more and compute. */ public void testConstructionRationalMoreCompute() { List> cp = ExamplesGeoTheorems.getExample(); GenPolynomialRing pf = cp.get(0).ring; GroebnerBaseAbstract bb; //bb = GBAlgorithmBuilder. polynomialRing(pf).fractionFree().parallel().optimize().build(); //bb = GBAlgorithmBuilder. polynomialRing(pf).parallel().optimize().build(); //bb = GBAlgorithmBuilder. polynomialRing(pf).build(); bb = GBAlgorithmBuilder. polynomialRing(pf).optimize().build(); //bb = GBAlgorithmBuilder. polynomialRing(pf).fractionFree().build(); //bb = GBAlgorithmBuilder. polynomialRing(pf).parallel().build(); //bb = GBAlgorithmBuilder. polynomialRing(pf).fractionFree().optimize().build(); //bb = GBAlgorithmBuilder. polynomialRing(pf).parallel().fractionFree().optimize().build(); //bb = GBAlgorithmBuilder. polynomialRing(pf).optimize().fractionFree().build(); //bb = GBAlgorithmBuilder. polynomialRing(pf).fractionFree().optimize().parallel().build(); //System.out.println("bb = " + bb); //assertTrue("instance of " + bb, bb instanceof GBOptimized); List> gb; long t; t = System.currentTimeMillis(); gb = bb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("time(gb) = " + t); t = System.currentTimeMillis(); gb = bb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("time(gb) = " + t); t = System.currentTimeMillis(); gb = bb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("time(gb) = " + t); assertTrue("t >= 0: ", t >= 0L); // praise findbugs assertTrue("isGB: ", bb.isGB(gb)); bb.terminate(); //System.out.println("gb = " + gb); //System.out.println("bb = " + bb); } /** * Test construction for BigRational and pairlists and compute. */ public void testConstructionRationalParilistCompute() { List> cp = ExamplesGeoTheorems.getExample(); GenPolynomialRing pf = cp.get(0).ring; GroebnerBaseAbstract bb; List> gb; long t; bb = GBAlgorithmBuilder. polynomialRing(pf).normalPairlist().build(); t = System.currentTimeMillis(); gb = bb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("time(gb) = " + t); assertTrue("isGB: ", bb.isGB(gb)); bb = GBAlgorithmBuilder. polynomialRing(pf).syzygyPairlist().build(); t = System.currentTimeMillis(); gb = bb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("time(gb) = " + t); assertTrue("isGB: ", bb.isGB(gb)); bb = GBAlgorithmBuilder. polynomialRing(pf).simplePairlist().build(); t = System.currentTimeMillis(); gb = bb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("time(gb) = " + t); assertTrue("isGB: ", bb.isGB(gb)); assertTrue("t >= 0: ", t >= 0L); // for findbugs } } jas-2.5/trc/edu/jas/application/SolvableResidueTest.java0000644000175000017500000001635012137467670023605 0ustar giovannigiovanni/* * $Id: SolvableResidueTest.java 4399 2013-04-29 13:03:52Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.WeylRelations; import edu.jas.poly.TermOrder; import edu.jas.structure.NotInvertibleException; /** * SolvableResidue tests with JUnit. * @author Heinz Kredel. */ public class SolvableResidueTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a SolvableResidueTest object. * @param name String. */ public SolvableResidueTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(SolvableResidueTest.class); return suite; } SolvableIdeal id; SolvableResidueRing fac; GenSolvablePolynomialRing mfac; List> F; SolvableResidue< BigRational > a, b, c, d, e; int rl = 4; int kl = 3; int ll = 4; int el = 2; float q = 0.2f; int il = ( rl == 1 ? 1 : 2 ); protected void setUp() { a = b = c = d = e = null; TermOrder to = new TermOrder( TermOrder.INVLEX ); String[] vars = new String[] { "w", "x", "y", "z" }; mfac = new GenSolvablePolynomialRing( new BigRational(1), rl, to, vars ); WeylRelations wl = new WeylRelations(mfac); wl.generate(); if (!mfac.isAssociative() ) { System.out.println("ring not associative: " + mfac); } do { F = new ArrayList>( il ); for ( int i = 0; i < il; i++ ) { GenSolvablePolynomial mo = mfac.random(kl,ll,el,q); while ( mo.isConstant() ) { mo = mfac.random(kl,ll,el,q); } F.add( mo ); } id = new SolvableIdeal(mfac,F); id.doGB(); } while (id.isONE()); //System.out.println("id = " + id); assert !id.isONE() : "id = " + id; fac = new SolvableResidueRing( id ); //System.out.println("fac = " + fac); F = null; } protected void tearDown() { a = b = c = d = e = null; fac = null; id = null; mfac = null; } /** * Test constructor and toString. */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); //System.out.println("c.val = " + c.val); assertTrue("length( c ) = 1 ", c.val.length() == 1 || id.isONE()); assertTrue("isZERO( c )", !c.isZERO() || id.isONE()); assertTrue("isONE( c )", c.isONE() || id.isONE()); d = fac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.val = " + d.val); assertTrue("length( d ) = 0", d.val.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); for (SolvableResidue g : fac.generators() ) { //System.out.println("g = " + g); assertFalse("not isZERO( g )", g.isZERO() ); } } /** * Test random polynomial. */ public void testRandom() { for (int i = 1; i < 7; i++) { //a = fac.random(ll+i); a = fac.random(kl*(i+1), ll+2*i, el+i, q ); //System.out.println("a = " + a); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.val.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. */ public void testAddition() { a = fac.random(kl,ll,el,q); b = fac.random(kl,ll,el,q); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a",c,d); c = fac.random(kl,ll,el,q); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test object multiplication. */ public void testMultiplication() { List> g = fac.generators(); //System.out.println("g = " + g); //a = fac.random(kl,ll,el,q); a = g.get(1); if ( a.isZERO() ) { a = fac.getONE(); //return; } assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(kl,ll,el,q); //b = g.get(g.size()-1); if ( b.isZERO() ) { b = fac.getONE(); //return; } assertTrue("not isZERO( b )", !b.isZERO() ); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); assertEquals("a*1 = 1*a",c,a); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); //e = d.subtract(c); //non-com: assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); //non-com: assertEquals("a*b = b*a",c,d); c = fac.random(kl,ll+1,el,q); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(e) ); assertEquals("a(bc) = (ab)c",d,e); //assertTrue("a(bc) = (ab)c", d.equals(e) ); if ( !a.isZERO() ) { // !a.isZERO() isUnit() try { c = a.inverse(); System.out.println("a = " + a); System.out.println("c = " + c); d = c.multiply(a); System.out.println("d = " + d); assertTrue("a*1/a = 1: " + fac,d.isONE()); } catch (NotInvertibleException e) { // can happen } } // d = c.remainder(a); // //System.out.println("c = " + c); // System.out.println("d = " + d); // if ( d.isZERO() ) { // d = c.divide(a); // System.out.println("c = " + c); // System.out.println("d = " + d); // e = a.multiply(d); // System.out.println("e = " + e); // assertEquals("((b*a)/a)*a = b*a",e,c); // } } } jas-2.5/trc/edu/jas/application/PolyUtilAppTest.java0000644000175000017500000001731211641660762022732 0ustar giovannigiovanni/* * $Id: PolyUtilAppTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.application; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * PolyUtilApp tests with JUnit. * @author Heinz Kredel. */ public class PolyUtilAppTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a PolyUtilAppTest object. * @param name String. */ public PolyUtilAppTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(PolyUtilAppTest.class); return suite; } //private final static int bitlen = 100; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigRational ai; BigRational bi; BigRational ci; BigRational di; BigRational ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 5; int kl = 5; int ll = 5; int el = 5; float q = 0.6f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; dfac = new GenPolynomialRing(new BigRational(1), rl, to); cfac = null; //new GenPolynomialRing(new BigRational(1),rl-1,to); rfac = null; //new GenPolynomialRing>(cfac,1,to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; dfac = null; cfac = null; rfac = null; } /** * Test primitive element. * */ public void testPrimitiveElement() { String[] va = new String[] { "alpha" }; String[] vb = new String[] { "beta" }; GenPolynomialRing aufac, bufac; // x^3 - 2 aufac = new GenPolynomialRing(new BigRational(1), 1, va); GenPolynomial m; m = aufac.univariate(0, 3); m = m.subtract(aufac.fromInteger(2)); //System.out.println("m = " + m); // x^2 - 3 bufac = new GenPolynomialRing(new BigRational(1), 1, vb); GenPolynomial n; n = bufac.univariate(0, 2); n = n.subtract(bufac.fromInteger(3)); //System.out.println("n = " + n); AlgebraicNumberRing afac = new AlgebraicNumberRing(m); //System.out.println("afac = " + afac); AlgebraicNumberRing bfac = new AlgebraicNumberRing(n); //System.out.println("bfac = " + bfac); PrimitiveElement pe; pe = PolyUtilApp. primitiveElement(afac, bfac); //System.out.println("pe = " + pe); AlgebraicNumberRing cfac = pe.primitiveElem; AlgebraicNumber a = afac.getGenerator(); AlgebraicNumber b = bfac.getGenerator(); // convert to primitive element field AlgebraicNumber as = PolyUtilApp. convertToPrimitiveElem(cfac, pe.A, a); AlgebraicNumber bs = PolyUtilApp. convertToPrimitiveElem(cfac, pe.B, b); // test alpha+(t)beta == gamma AlgebraicNumber cs = as.sum(bs); //System.out.println("cs = " + cs); assertEquals("alpha+beta == gamma", cs, cfac.getGenerator()); } /** * Test primitive element of extension tower. * */ public void testPrimitiveElementTower() { String[] va = new String[] { "alpha" }; String[] vb = new String[] { "beta" }; GenPolynomialRing ufac; ufac = new GenPolynomialRing(new BigRational(1), 1, va); GenPolynomial m; m = ufac.univariate(0, 3); m = m.subtract(ufac.fromInteger(2)); //System.out.println("m = " + m); AlgebraicNumberRing afac; afac = new AlgebraicNumberRing(m); //System.out.println("afac = " + afac); GenPolynomialRing> aufac; aufac = new GenPolynomialRing>(afac, 1, vb); GenPolynomial> n; n = aufac.univariate(0, 2); n = n.subtract(aufac.getONE().multiply(afac.getGenerator())); //System.out.println("n = " + n); AlgebraicNumberRing> bfac; bfac = new AlgebraicNumberRing>(n); //System.out.println("bfac = " + bfac); PrimitiveElement pe; pe = PolyUtilApp. primitiveElement(bfac); //System.out.println("pe = " + pe); AlgebraicNumberRing cfac = pe.primitiveElem; AlgebraicNumber a = afac.getGenerator(); AlgebraicNumber> b = bfac.getGenerator(); // convert to primitive element ring AlgebraicNumber as = PolyUtilApp. convertToPrimitiveElem(cfac, pe.A, a); AlgebraicNumber bs = PolyUtilApp. convertToPrimitiveElem(cfac, pe.A, pe.B, b); // test alpha+(t)beta == gamma AlgebraicNumber cs = as.sum(bs); //System.out.println("cs = " + cs); assertEquals("alpha+beta == gamma", cs, cfac.getGenerator()); // test for polynomials, too simple String[] vx = new String[] { "x" }; GenPolynomialRing> rafac = new GenPolynomialRing>( afac, 1, vx); GenPolynomialRing>> rbfac = new GenPolynomialRing>>( bfac, 1, vx); GenPolynomial> ap = rafac.getGenerators().get(0).multiply(a); GenPolynomial>> bp = rbfac.getGenerators().get(0) .multiply(b); GenPolynomial> asp = PolyUtilApp. convertToPrimitiveElem( cfac, pe.A, ap); GenPolynomial> bsp = PolyUtilApp. convertToPrimitiveElem( cfac, pe.A, pe.B, bp); //System.out.println("asp = " + asp); //System.out.println("bsp = " + bsp); // test alpha+(t)beta == gamma GenPolynomial> csp = asp.sum(bsp); //System.out.println("csp = " + csp); assertEquals("alpha+beta == gamma", csp.leadingBaseCoefficient(), cfac.getGenerator()); } } jas-2.5/trc/edu/jas/application/IdealTest.java0000644000175000017500000017177412063147646021543 0ustar giovannigiovanni/* * $Id: IdealTest.java 4316 2012-12-15 19:29:42Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBase; import edu.jas.gbufd.GBFactory; import edu.jas.kern.ComputerThreads; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; import edu.jas.ufd.Quotient; import edu.jas.util.KsubSet; /** * Ideal tests with JUnit. * @author Heinz Kredel. */ public class IdealTest extends TestCase { private static final Logger logger = Logger.getLogger(IdealTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a IdealTest object. * @param name String. */ public IdealTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(IdealTest.class); return suite; } TermOrder to; GenPolynomialRing fac; List> L; PolynomialList F; List> G; List> M; GroebnerBase bb; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 4; //10 int ll = 5; //7 int el = 3; float q = 0.2f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(17, 1); to = new TermOrder( /*TermOrder.INVLEX*/); String[] vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); //bb = new GroebnerBaseSeq(); bb = GBFactory.getImplementation(coeff); a = b = c = d = e = null; } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; ComputerThreads.terminate(); } /** * Test Ideal sum. */ public void testIdealSum() { Ideal I; Ideal J; Ideal K; L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("not isONE( I )", !I.isONE()); assertTrue("isGB( I )", I.isGB()); I = new Ideal(fac, L, false); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("not isONE( I )", !I.isONE()); assertTrue("isGB( I )", I.isGB()); L = bb.GB(L); assertTrue("isGB( { a } )", bb.isGB(L)); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); I = new Ideal(fac, L, false); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); //System.out.println("L = " + L.size() ); I = new Ideal(fac, L, false); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); //assertTrue("not isGB( I )", !I.isGB() ); L = bb.GB(L); assertTrue("isGB( { a, b } )", bb.isGB(L)); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); // assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I; K = J.sum(I); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("equals( K, I )", K.equals(I)); L = new ArrayList>(); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); assertTrue("isGB( { c } )", bb.isGB(L)); J = new Ideal(fac, L, true); K = J.sum(I); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("K contains(I)", K.contains(I)); assertTrue("K contains(J)", K.contains(J)); L = new ArrayList>(); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); assertTrue("isGB( { d } )", bb.isGB(L)); J = new Ideal(fac, L, true); I = K; K = J.sum(I); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("K contains(I)", K.contains(I)); assertTrue("K contains(J)", K.contains(J)); L = new ArrayList>(); assertTrue("not isZERO( e )", !e.isZERO()); L.add(e); assertTrue("isGB( { e } )", bb.isGB(L)); J = new Ideal(fac, L, true); I = K; K = J.sum(I); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("equals( K, I )", K.equals(I)); assertTrue("K contains(J)", K.contains(I)); assertTrue("I contains(K)", I.contains(K)); } /** * Test Ideal product. */ public void testIdealProduct() { Ideal I; Ideal J; Ideal K; Ideal H; a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("not isONE( I )", !I.isONE()); assertTrue("isGB( I )", I.isGB()); L = new ArrayList>(); assertTrue("not isZERO( b )", !a.isZERO()); L.add(b); J = new Ideal(fac, L, true); assertTrue("not isZERO( J )", !J.isZERO()); assertTrue("not isONE( J )", !J.isONE()); assertTrue("isGB( J )", J.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = I.intersect(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); assertTrue("I contains(H)", I.contains(H)); assertTrue("J contains(H)", J.contains(H)); assertTrue("H contains(K)", H.contains(K)); //if (false /*! H.equals(K)*/) { // System.out.println("I = " + I); // System.out.println("J = " + J); // System.out.println("K = " + K); // System.out.println("H = " + H); //} L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = I.intersect(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); assertTrue("I contains(H)", I.contains(H)); assertTrue("J contains(H)", J.contains(H)); assertTrue("H contains(K)", H.contains(K)); //if (false /*! H.equals(K)*/) { // System.out.println("I = " + I); // System.out.println("J = " + J); // System.out.println("K = " + K); // System.out.println("H = " + H); //} L = new ArrayList>(); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.GB(L); J = new Ideal(fac, L, true); assertTrue("not isZERO( J )", !J.isZERO()); //assertTrue("not isONE( J )", !J.isONE() ); assertTrue("isGB( J )", J.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = I.intersect(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); assertTrue("I contains(H)", I.contains(H)); assertTrue("J contains(H)", J.contains(H)); assertTrue("H contains(K)", H.contains(K)); //if (false /*! H.equals(K)*/) { // System.out.println("I = " + I); // System.out.println("J = " + J); // System.out.println("K = " + K); // System.out.println("H = " + H); //} } /** * Test Ideal quotient. */ public void testIdealQuotient() { Ideal I; Ideal J; Ideal K; Ideal H; a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); L = new ArrayList>(); assertTrue("not isZERO( b )", !a.isZERO()); L.add(b); L = bb.GB(L); J = new Ideal(fac, L, true); assertTrue("not isZERO( J )", !J.isZERO()); //assertTrue("not isONE( J )", !J.isONE() ); assertTrue("isGB( J )", J.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = K.quotient(J.getList().get(0)); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); assertTrue("equals(H,I)", H.equals(I)); // GBs only H = K.quotient(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); assertTrue("equals(H,I)", H.equals(I)); // GBs only L = new ArrayList>(); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.GB(L); J = new Ideal(fac, L, true); assertTrue("not isZERO( J )", !J.isZERO()); //assertTrue("not isONE( J )", !J.isONE() ); assertTrue("isGB( J )", J.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = K.quotient(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); assertTrue("equals(H,I)", H.equals(I)); // GBs only L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( J )", !J.isONE() ); assertTrue("isGB( I )", I.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = K.quotient(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); assertTrue("equals(H,I)", H.equals(I)); // GBs only } /** * Test Ideal infinite quotient. */ public void testIdealInfiniteQuotient() { Ideal I; Ideal J; Ideal K; a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L = new ArrayList>(); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotient(a); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotient(a); assertTrue("equals(J,I)", J.equals(I)); // GBs only assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotient(a); assertTrue("isGB( J )", J.isGB()); assertTrue("equals(J,I)", J.equals(I)); // GBs only G = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); G.add(a); G = bb.GB(G); K = new Ideal(fac, G, true); assertTrue("not isZERO( K )", !K.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( K )", K.isGB()); J = I.infiniteQuotient(K); assertTrue("equals(J,I)", J.equals(I)); // GBs only assertTrue("not isZERO( e )", !e.isZERO()); G.add(e); G = bb.GB(G); K = new Ideal(fac, G, true); assertTrue("not isZERO( K )", !K.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( K )", K.isGB()); J = I.infiniteQuotient(K); assertTrue("equals(J,I)", J.equals(I)); // GBs only } /** * Test Ideal infinite quotient with Rabinowich trick. */ public void testIdealInfiniteQuotientRabi() { Ideal I; Ideal J; Ideal K; Ideal JJ; a = fac.random(kl - 1, ll - 1, el - 1, q / 2); b = fac.random(kl - 1, ll - 1, el, q / 2); c = fac.random(kl - 1, ll - 1, el, q / 2); d = fac.random(kl - 1, ll - 1, el, q / 2); e = a; //fac.random(kl, ll-1, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L = new ArrayList>(); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotientRab(a); JJ = I.infiniteQuotient(a); assertTrue("equals(J,JJ)", J.equals(JJ)); // GBs only assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotientRab(a); assertTrue("equals(J,I)", J.equals(I)); // GBs only JJ = I.infiniteQuotient(a); assertTrue("equals(J,JJ)", J.equals(JJ)); // GBs only assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotientRab(a); assertTrue("isGB( J )", J.isGB()); assertTrue("equals(J,I)", J.equals(I)); // GBs only JJ = I.infiniteQuotient(a); assertTrue("equals(J,JJ)", J.equals(JJ)); // GBs only G = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); G.add(a); G = bb.GB(G); K = new Ideal(fac, G, true); assertTrue("not isZERO( K )", !K.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( K )", K.isGB()); J = I.infiniteQuotientRab(K); assertTrue("equals(J,I)", J.equals(I)); // GBs only JJ = I.infiniteQuotient(a); assertTrue("equals(J,JJ)", J.equals(JJ)); // GBs only assertTrue("not isZERO( e )", !e.isZERO()); G.add(e); G = bb.GB(G); K = new Ideal(fac, G, true); assertTrue("not isZERO( K )", !K.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( K )", K.isGB()); J = I.infiniteQuotientRab(K); assertTrue("equals(J,I)", J.equals(I)); // GBs only JJ = I.infiniteQuotient(a); assertTrue("equals(J,JJ)", J.equals(JJ)); // GBs only } /** * Test Ideal radical membership. */ public void testIdealRadicalMember() { Ideal I; //Ideal J; //Ideal K; //Ideal JJ; a = fac.random(kl - 1, ll, el - 1, q); b = fac.random(kl - 1, ll, el, q); c = fac.random(kl - 1, ll - 1, el, q / 2); d = fac.random(kl - 1, ll - 1, el, q / 2); e = a; //fac.random(kl, ll-1, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L = new ArrayList>(); L.add(b); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("I = " + I); if (!I.isONE()) { assertFalse("a in radical(b)", I.isRadicalMember(a)); assertTrue("b in radical(b)", I.isRadicalMember(b)); } L = new ArrayList>(); L.add(b.multiply(b)); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); if (!I.isONE()) { assertFalse("a in radical(b*b)", I.isRadicalMember(a)); assertTrue("b in radical(b*b)", I.isRadicalMember(b)); } //System.out.println("c = " + c); L.add(c); L = bb.GB(L); I = new Ideal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); if (!I.isONE()) { assertFalse("a in radical(b*b)", I.isRadicalMember(a)); assertTrue("b in radical(b*b)", I.isRadicalMember(b)); } } /** * Test Ideal common zeros. */ public void testIdealCommonZeros() { Ideal I; L = new ArrayList>(); I = new Ideal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), 1); a = fac.getZERO(); L.add(a); I = new Ideal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), 1); b = fac.getONE(); L.add(b); I = new Ideal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), -1); L = new ArrayList>(); a = fac.random(kl, ll, el, q); if (!a.isZERO() && !a.isConstant()) { L.add(a); I = new Ideal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), 1); } L = (List>) fac.univariateList(); I = new Ideal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), 0); L.remove(0); I = new Ideal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), 1); } /** * Test Ideal dimension. */ public void testIdealDimension() { Ideal I; L = new ArrayList>(); Dimension dim; I = new Ideal(fac, L, true); assertEquals("dimension( I )", rl, I.dimension().d); a = fac.getZERO(); L.add(a); I = new Ideal(fac, L, true); assertEquals("dimension( I )", rl, I.dimension().d); b = fac.getONE(); L.add(b); I = new Ideal(fac, L, true); assertEquals("dimension( I )", -1, I.dimension().d); L = new ArrayList>(); a = fac.random(kl, ll, el, q); if (!a.isZERO() && !a.isConstant()) { L.add(a); I = new Ideal(fac, L, true); //System.out.println("a = " + a); dim = I.dimension(); //System.out.println("dim(I) = " + dim); assertTrue("dimension( I )", dim.d >= 1); } L = (List>) fac.univariateList(); I = new Ideal(fac, L, true); dim = I.dimension(); assertEquals("dimension( I )", 0, dim.d); while (L.size() > 0) { L.remove(0); I = new Ideal(fac, L, true); //System.out.println("I = " + I); dim = I.dimension(); //System.out.println("dim(I) = " + dim); assertEquals("dimension( I )", rl - L.size(), dim.d); } L = (List>) fac.univariateList(); I = new Ideal(fac, L, true); I = I.product(I); //System.out.println("I = " + I); dim = I.dimension(); //System.out.println("dim(I) = " + dim); assertEquals("dimension( I )", 0, dim.d); L = I.getList(); while (L.size() > 0) { L.remove(0); I = new Ideal(fac, L, true); //System.out.println("I = " + I); dim = I.dimension(); //System.out.println("dim(I) = " + dim); assertTrue("dimension( I )", dim.d > 0); } } /** * Test Ideal term order optimization. */ public void testIdealTopt() { Ideal I; Ideal J; Ideal K; L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); J = I.copy(); //new Ideal(fac,L); J.doToptimize(); assertTrue("not isZERO( J )", !J.isZERO()); assertTrue("isGB( J )", J.isGB()); //System.out.println("J = " + J); if (I.isONE()) { return; } assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); I = new Ideal(fac, L); K = I.copy(); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("GB(I) = " + I); K.doToptimize(); K.doGB(); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); //System.out.println("GB(opt(K)) = " + K); J = I.copy(); J.doToptimize(); assertTrue("not isZERO( J )", !J.isZERO()); assertTrue("isGB( J )", J.isGB()); //System.out.println("opt(GB(J)) = " + J); if (I.isONE()) { return; } assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); I = new Ideal(fac, L); K = I.copy(); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("GB(I) = " + I); K.doToptimize(); K.doGB(); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); //System.out.println("GB(opt(K)) = " + K); J = I.copy(); J.doToptimize(); assertTrue("not isZERO( J )", !J.isZERO()); assertTrue("isGB( J )", J.isGB()); //System.out.println("opt(GB(J)) = " + J); } /** * Test elimination Ideals. */ public void testElimIdeal() { String[] vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); Ideal I; Ideal J; L = new ArrayList>(); a = fac.univariate(2, 3L); //fac.random(kl, ll, el, q ); b = fac.univariate(1, 2L); //fac.random(kl, ll, el, q ); c = fac.univariate(0, 1L); //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); //I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List sv = new ArrayList(vars.length); for (int i = 0; i < vars.length; i++) { sv.add(vars[i]); } //System.out.println("sv = " + sv); for (int i = 0; i <= vars.length; i++) { KsubSet ps = new KsubSet(sv, i); //System.out.println("========================== ps : " + i); for (List ev : ps) { //System.out.println("ev = " + ev); String[] evars = new String[ev.size()]; for (int j = 0; j < ev.size(); j++) { evars[j] = ev.get(j); } GenPolynomialRing efac; efac = new GenPolynomialRing(fac.coFac, evars.length, fac.tord, evars); //System.out.println("efac = " + efac); J = I.eliminate(efac); assertTrue("isGB( J )", J.isGB()); assertTrue("size( J ) <= |ev|", J.getList().size() <= ev.size()); //System.out.println("J = " + J); } } } /** * Test univariate polynomials in ideal. */ public void testUnivPoly() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^3 + 34/55 x^2 + 1/9 x + 99 )"); b = fac.parse("( y^4 - x )"); c = fac.parse("( z^3 - x y )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); //I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); for (int i = 0; i < rl; i++) { // rl GenPolynomial u = I.constructUnivariate(rl - 1 - i); //System.out.println("u = " + u); GenPolynomial U = fac.parse(u.toString()); //System.out.println("U = " + U + "\n"); assertTrue("I.contains(U) ", I.contains(U)); } List> Us = I.constructUnivariate(); for (GenPolynomial u : Us) { //System.out.println("u = " + u); GenPolynomial U = fac.parse(u.toString()); //System.out.println("U = " + U + "\n"); assertTrue("I.contains(U) ", I.contains(U)); } } /** * Test complex roots univariate polynomials in zero dim ideal. */ public void testComplexRoot() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^3 - 27 )"); b = fac.parse("( y^2 - 9 )"); c = fac.parse("( z - 7 )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); //I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); BigRational eps = new BigRational(1, 1000000); eps = eps.multiply(eps); eps = eps.multiply(eps).multiply(eps); BigDecimal e = new BigDecimal(eps.getRational()); e = e.abs(); //.multiply(e); BigDecimal dc = BigDecimal.ONE; GenPolynomialRing dfac = new GenPolynomialRing(dc, fac); //System.out.println("dfac = " + dfac); ComplexRing dcc = new ComplexRing(dc); GenPolynomialRing> dcfac = new GenPolynomialRing>(dcc, dfac); //System.out.println("dcfac = " + dcfac); List>> roots = PolyUtilApp. complexRootTuples(I, eps); //System.out.println("roots = " + roots + "\n"); for (GenPolynomial p : I.getList()) { GenPolynomial dp = PolyUtil. decimalFromRational(dfac, p); GenPolynomial> dpc = PolyUtil. toComplex(dcfac, dp); //System.out.println("dpc = " + dpc); for (List> r : roots) { //System.out.println("r = " + r); Complex ev = PolyUtil.> evaluateAll(dcc, dcfac, dpc, r); if (ev.norm().getRe().compareTo(e) > 0) { //System.out.println("ev = " + ev); fail("ev > eps : " + ev + " > " + e); } } } //System.out.println(); } /** * Test real roots univariate polynomials in zero dim ideal. */ public void testRealRoot() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^3 - 27 )"); b = fac.parse("( y^4 - x )"); c = fac.parse("( z^2 - x^2 )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); //I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); BigRational eps = new BigRational(1, 1000000); eps = eps.multiply(eps); eps = eps.multiply(eps); //.multiply(eps); BigDecimal e = new BigDecimal(eps.getRational()); e = e.abs(); //.multiply(e); eps = eps.multiply(new BigRational(1, 100)); List> roots = PolyUtilApp. realRootTuples(I, eps); //System.out.println("roots = " + roots + "\n"); // polynomials with decimal coefficients BigDecimal dc = BigDecimal.ONE; GenPolynomialRing dfac = new GenPolynomialRing(dc, fac); //System.out.println("dfac = " + dfac); for (GenPolynomial p : I.getList()) { GenPolynomial dp = PolyUtil. decimalFromRational(dfac, p); //System.out.println("dp = " + dp); for (List r : roots) { //System.out.println("r = " + r); BigDecimal ev = PolyUtil. evaluateAll(dc, dfac, dp, r); if (ev.abs().compareTo(e) > 0) { //System.out.println("ev = " + ev); fail("ev > e : " + ev + " > " + e + ", eps = " + new BigDecimal(eps)); } } } //System.out.println(); } /** * Test zero dimensional decomposition. */ public void testZeroDimDecomp() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^3 - 27 )"); b = fac.parse("( y^4 - x )"); c = fac.parse("( z^2 - x^2 )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); //I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> zd = I.zeroDimDecomposition(); //System.out.println("I = " + I); //System.out.println("zd = " + zd); boolean t = I.isZeroDimDecomposition(zd); //System.out.println("t = " + t); assertTrue("is decomposition ", t); } /** * Test real roots univariate polynomials in zero dim ideal. */ public void testIdealRealRoot() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^3 - 27 )"); b = fac.parse("( y^4 - x )"); c = fac.parse("( z^2 - x^2 )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); //I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> zd = I.zeroDimDecomposition(); //System.out.println("zd = " + zd); assertTrue("is decomposition ", I.isZeroDimDecomposition(zd)); BigRational eps = new BigRational(1, 1000000); eps = eps.multiply(eps); eps = eps.multiply(eps); //.multiply(eps); BigDecimal e = new BigDecimal(eps.getRational()); e = e.abs(); //.multiply(e); eps = eps.multiply(new BigRational(1, 10)); BigDecimal dc = BigDecimal.ONE; List> roots = PolyUtilApp. realRoots(zd, eps); //System.out.println("roots = " + roots + "\n"); for (IdealWithRealRoots Ir : roots) { List> L = Ir.ideal.getList(); List> Ld = new ArrayList>(L.size()); GenPolynomialRing dfac = new GenPolynomialRing(dc, Ir.ideal.list.ring); //System.out.println("dfac = " + dfac); for (GenPolynomial p : L) { GenPolynomial dp = PolyUtil. decimalFromRational(dfac, p); //System.out.println("dp = " + dp); Ld.add(dp); } boolean t = PolyUtilApp.isRealRoots(Ld, Ir.rroots, e); assertTrue("isRealRoots ", t); // this example only } } /** * Test complex roots univariate polynomials in zero dim ideal. */ public void testIdealComplexRoot() { String[] vars; BigRational coeff = new BigRational(1, 1); to = new TermOrder(TermOrder.INVLEX); //vars = new String[] { "x", "y" }; vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, vars.length, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^3 + 3 )"); //a = fac.parse("( x^3 - 3 )"); //a = fac.parse("( x^2 + 3 )"); b = fac.parse("( y^2 - x )"); //b = fac.parse("( y^2 + x )"); //b = fac.parse("( y^2 + 4 )"); c = fac.parse("( z^2 - x y )"); if (a.isZERO() || b.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); //I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> zd = I.zeroDimRootDecomposition(); //System.out.println("zd = " + zd); assertTrue("is decomposition ", I.isZeroDimDecomposition(zd)); BigRational eps = new BigRational(1, 1000000); //eps = eps.multiply(eps); eps = eps.multiply(eps).multiply(eps); BigDecimal e = new BigDecimal(eps.getRational()); e = e.abs(); //.multiply(e); List> roots = PolyUtilApp . complexAlgebraicRoots(zd); //, eps); //System.out.println("roots = " + roots + "\n"); ComplexRing dcc = new ComplexRing(e); int d = 0; int s = 0; for (IdealWithComplexAlgebraicRoots Ic : roots) { List> L = Ic.ideal.getList(); List>> Ld = new ArrayList>>( L.size()); s += Ic.can.size(); GenPolynomialRing dfac = new GenPolynomialRing(e, Ic.ideal.list.ring); //System.out.println("dfac = " + dfac); GenPolynomialRing> dcfac; dcfac = new GenPolynomialRing>(dcc, dfac); //System.out.println("dcfac = " + dcfac); int ds = 1; for (GenPolynomial p : L) { long dl = p.leadingExpVector().totalDeg(); ds *= dl; GenPolynomial dp = PolyUtil. decimalFromRational(dfac, p); GenPolynomial> dpc = PolyUtil. toComplex(dcfac, dp); //System.out.println("p = " + p); //System.out.println("dpc = " + dpc); Ld.add(dpc); } d += ds; List>> droot = Ic.decimalApproximation(); for (List> dr : droot) { //System.out.println("dr = " + dr); // TODO } } logger.info("#roots = " + s + ", #vr-dim = " + d); assertTrue("#roots(" + s + ") == degree(" + d + "): ", s == d); } /** * Test normal position. */ public void testNormalPosition() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^3 - 27 )"); b = fac.parse("( y^3 - x )"); c = fac.parse("( z^2 - x^2 )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); int[] np = I.normalPositionIndex2Vars(); //System.out.println("np = " + np); if (np == null) { np = I.normalPositionIndexUnivars(); //System.out.println("np = " + np); } if (np == null) { return; } int i = np[0]; int j = np[1]; IdealWithUniv Ip = I.normalPositionFor(i, j, null); //System.out.println("Ip = " + Ip); boolean t = Ip.ideal.isNormalPositionFor(i + 1, j + 1); // sic //System.out.println("t = " + t); assertTrue("is normal position ", t); np = Ip.ideal.normalPositionIndex2Vars(); //System.out.println("np = " + np); if (np == null) { np = Ip.ideal.normalPositionIndexUnivars(); //System.out.println("np = " + Arrays.toString(np)); } if (np == null) { return; } i = np[0]; j = np[1]; assertTrue("i == 0: " + i, i == 0); assertTrue("j == 2: " + j, j == 2); // fixed, was 3 } /** * Test 0-dim root decomposition. */ public void testRootDecomposition() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^2 - 7 )"); b = fac.parse("( y^2 - 5 )"); c = fac.parse("( z^3 - x * y )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> rzd = I.zeroDimRootDecomposition(); //System.out.println("rzd = " + rzd); assertTrue("is contained in intersection ", I.isZeroDimDecomposition(rzd)); } /** * Test 0-dim prime decomposition. */ public void testPrimeDecomposition() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^2 - 5 )^2 "); b = fac.parse("( y^2 - 5 )"); c = fac.parse("( z^3 - x )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> pzd = I.zeroDimPrimeDecomposition(); //System.out.println("pzd = " + pzd); //System.out.println("I = " + I); assertTrue("is contained in intersection ", I.isZeroDimDecomposition(pzd)); } /** * Test 0-dim primary decomposition. */ public void testPrimaryDecomposition() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^2 - 5 )^2 "); b = fac.parse("( y^2 - 5 )"); c = fac.parse("( z^3 - x )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> qzd = I.zeroDimPrimaryDecomposition(); //System.out.println("qzd = " + qzd); //System.out.println("I = " + I); assertTrue("is intersection ", I.isPrimaryDecomposition(qzd)); } /** * Test 0-dim root decomposition and real roots. */ public void testRootDecompositionReal() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); a = fac.parse("( x^2 - 5 )"); b = fac.parse("( y^2 - 7 )"); c = fac.parse("( z^3 - x * y )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> iur; iur = PolyUtilApp. realAlgebraicRoots(I); List> iul = new ArrayList>(); for (IdealWithRealAlgebraicRoots iu : iur) { iul.add(iu); } assertTrue("is contained in intersection ", I.isZeroDimDecomposition(iul)); for (IdealWithRealAlgebraicRoots iu : iur) { //System.out.println("iu = " + iu); //System.out.println(""); List> rd = iu.decimalApproximation(); // TODO //System.out.println("iu = " + iu); //System.out.println(""); } } /** * Test extension-contraction. */ public void testExtCont() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(); //TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); //a = fac.parse("( y^2 - 5 ) x "); //b = fac.parse("( y^2 - 5 ) x "); //c = fac.parse("( x z^3 - 3 )"); //a = fac.parse("( x^2 + 2 x y z + z^4 ) "); //b = fac.parse("( y z - z^2 ) "); //c = fac.parse("0"); a = fac.parse("( y + x y^2 ) "); b = fac.parse("( x z + x^2 y ) "); //c = fac.parse("0"); if (a.isZERO() || b.isZERO()) { return; } L.add(a); L.add(b); //L.add(c); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); IdealWithUniv> Ext = I.extension(new String[] { "x" }); //Ideal> Ext = I.extension( new String[] { "y", "z" } ); //System.out.println("Ext = " + Ext); //System.out.println("I = " + I); IdealWithUniv Con = I.permContraction(Ext); //System.out.println("Con = " + Con); //System.out.println("I = " + I); assertTrue("I subseteq Con(Ext(I)) ", Con.ideal.contains(I)); } /** * Test prime ideal decomposition. */ public void testPrimeDecomp() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); //a = fac.parse("( y^2 - 5 ) x "); //b = fac.parse("( y^2 - 5 ) x "); //c = fac.parse("( x z^3 - 3 )"); //a = fac.parse("( x^2 + 2 x y z + z^4 ) "); //b = fac.parse("( y z - z^2 ) "); //a = fac.parse("( y + x y^2 ) "); //b = fac.parse("( x z + x^2 y ) "); a = fac.parse("( z^2 - x ) "); b = fac.parse("( y^2 - x ) "); //a = fac.parse("( x y ) "); //b = fac.parse("( x z ) "); if (a.isZERO() || b.isZERO()) { return; } L.add(a); L.add(b); //L.add(c); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> pdec = I.primeDecomposition(); //System.out.println("pdec = " + pdec); //System.out.println("I = " + I); assertTrue("I subseteq cup G_i ", I.isDecomposition(pdec)); List> dec = new ArrayList>(pdec.size()); for (IdealWithUniv pu : pdec) { dec.add(pu.ideal); } Ideal Ii = I.intersect(dec); //System.out.println("Ii = " + Ii); //System.out.println("I = " + I); // not always: assertTrue("I == Ii ", I.equals(Ii)); } /** * Test radical ideal decomposition. */ public void testRadicalDecomp() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); //a = fac.parse("( y^2 - 5 ) x "); //b = fac.parse("( y^2 - 5 ) x "); //c = fac.parse("( x z^3 - 3 )"); a = fac.parse("( x^2 + 2 x y z + z^4 ) "); b = fac.parse("( y z - z^2 ) "); //a = fac.parse("( y + x y^2 ) "); //b = fac.parse("( x z + x^2 y ) "); //a = fac.parse("( z^2 - x )^2 "); //b = fac.parse("( y^2 - x ) "); //a = fac.parse("( x^2 y^3 ) "); //b = fac.parse("( x^2 z^5 ) "); if (a.isZERO() || b.isZERO()) { return; } L.add(a); L.add(b); //L.add(c); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> rdec = I.radicalDecomposition(); //System.out.println("rdec = " + rdec); //System.out.println("I = " + I); assertTrue("I subseteq cup G_i ", I.isDecomposition(rdec)); List> dec = new ArrayList>(rdec.size()); for (IdealWithUniv ru : rdec) { dec.add(ru.ideal); } Ideal Ii = I.intersect(dec); //System.out.println("Ii = " + Ii); //System.out.println("I = " + I); assertTrue("Ii.contains(I) ", Ii.contains(I)); //Ii = I.radical(); //System.out.println("Ii = " + Ii); //System.out.println("I = " + I); //assertTrue("Ii.contains(I) ", Ii.contains(I)); } /** * Test ideal decomposition. */ public void testIrredDecomp() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); //a = fac.parse("( y^2 - 5 ) x "); //b = fac.parse("( y^2 - 5 ) x "); //c = fac.parse("( x z^3 - 3 )"); a = fac.parse("( x^2 + 2 x y z + z^4 ) "); b = fac.parse("( y z - z^2 ) "); //a = fac.parse("( y + x y^2 ) "); //b = fac.parse("( x z + x^2 y ) "); //a = fac.parse("( z^2 - x )^2 "); //b = fac.parse("( y^2 - x ) "); //a = fac.parse("( x^2 y^3 ) "); //b = fac.parse("( x^2 z^5 ) "); if (a.isZERO() || b.isZERO()) { return; } L.add(a); L.add(b); //L.add(c); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> rdec = I.decomposition(); //System.out.println("rdec = " + rdec); //System.out.println("I = " + I); assertTrue("I subseteq cup G_i ", I.isDecomposition(rdec)); List> dec = new ArrayList>(rdec.size()); for (IdealWithUniv ru : rdec) { dec.add(ru.ideal); } Ideal Ii = I.intersect(dec); //System.out.println("Ii = " + Ii); //System.out.println("I = " + I); assertTrue("Ii.contains(I) ", Ii.contains(I)); //Ii = I.radical(); //System.out.println("Ii = " + Ii); //System.out.println("I = " + I); //assertTrue("Ii.contains(I) ", Ii.contains(I)); } /** * Test primary ideal decomposition. */ public void testPrimaryDecomp() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "x", "y", "z" }; fac = new GenPolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 3 ", vars.length == 3); Ideal I; L = new ArrayList>(); //a = fac.parse("( y^2 - 5 ) x "); //b = fac.parse("( y^2 - 5 ) x "); //c = fac.parse("( x z^3 - 3 )"); //a = fac.parse("( x^2 + 2 x y z + z^4 ) "); //b = fac.parse("( y z - z^2 ) "); //a = fac.parse("( y + x y^2 ) "); //b = fac.parse("( x z + x^2 y ) "); a = fac.parse("( x z^2 - 1 )^2 "); b = fac.parse("( y^2 - x ) "); //a = fac.parse("( x^2 y ) "); //b = fac.parse("( x z^3 ) "); if (a.isZERO() || b.isZERO()) { return; } L.add(a); L.add(b); //L.add(c); I = new Ideal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List> qdec = I.primaryDecomposition(); //System.out.println("qdec = " + qdec); //System.out.println("I = " + I); List> dec = new ArrayList>(qdec.size()); for (PrimaryComponent ru : qdec) { dec.add(ru.primary); } assertTrue("I eq cup G_i ", I.isPrimaryDecomposition(qdec)); } } jas-2.5/trc/edu/jas/application/ReductionTest.java0000644000175000017500000002106312004571452022431 0ustar giovannigiovanni/* * $Id: ReductionTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingFactory; // import edu.jas.application.Ideal; /** * Reduction tests with JUnit. * @author Heinz Kredel. */ public class ReductionTest extends TestCase { /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a ReductionTest object. * @param name String */ public ReductionTest(String name) { super(name); } /** * suite. * @return a test suite. */ public static Test suite() { TestSuite suite = new TestSuite(ReductionTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing fac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; List> L; PolynomialList F; PolynomialList G; //ReductionSeq red; //Reduction redpar; int rl = 2; int kl = 2; int ll = 3; int el = 3; float q = 0.4f; @Override protected void setUp() { a = b = c = d = e = null; fac = new GenPolynomialRing(new BigRational(0), rl); //red = new ReductionSeq(); //redpar = new ReductionPar(); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; //red = null; //redpar = null; } /* * Test dummy. * public void testDummy() { } */ /** * Test rational coefficient polynomial parametric reduction, * caseDistinction and determination. * */ public void testRatPolReduction() { RingFactory bi = new BigRational(0); GenPolynomialRing pr = new GenPolynomialRing(bi, 2, new String[] { "a", "b" }); GenPolynomialRing> fac = new GenPolynomialRing>( pr, rl); CReductionSeq cred = new CReductionSeq(bi); GenPolynomial> a = fac.random(kl, ll, el, q); while (a.isZERO()) { a = fac.random(kl, ll, el, q).sum(fac.getONE()); } GenPolynomial> b = fac.random(kl, ll, el, q); while (b.isZERO()) { b = fac.random(kl, ll, el, q).subtract(fac.getONE()); } GenPolynomial> g = fac.getZERO(); Map.Entry> m = a.leadingMonomial(); ExpVector e = m.getKey(); GenPolynomial c = m.getValue(); GenPolynomial> r = fac.getZERO(); r = r.sum(c, e); if (r.isZERO()) { r = fac.getONE(); } GenPolynomial> w = a.reductum(); ColorPolynomial p = new ColorPolynomial(g, r, w); //System.out.println("p = " + p); assertTrue("check(p) ", p.checkInvariant()); assertTrue("deter(p) ", p.isDetermined()); //System.out.println("cond != 0: " + p.getConditionNonZero()); //System.out.println("cond == 0: " + p.getConditionZero()); p = new ColorPolynomial(r, g, w); //System.out.println("p = " + p); assertTrue("check(p) ", p.checkInvariant()); if (!w.isZERO()) { assertFalse("deter(p) ", p.isDetermined()); } //System.out.println("cond != 0: " + p.getConditionNonZero()); //System.out.println("cond == 0: " + p.getConditionZero()); p = new ColorPolynomial(r, w, g); //System.out.println("p = " + p); assertTrue("check(p) ", p.checkInvariant()); assertTrue("deter(p) ", p.isDetermined()); //System.out.println("cond != 0: " + p.getConditionNonZero()); //System.out.println("cond == 0: " + p.getConditionZero()); // wrong test: p = new ColorPolynomial(w,r,g); //(w,g,r); //System.out.println("p = " + p); //if ( !w.isZERO() ) { // assertFalse("check(p) ", p.checkInvariant()); //} //assertFalse("deter(p) ", p.isDetermined()); //assertFalse("p == 0 ", p.isZERO()); //System.out.println("cond != 0: " + p.getConditionNonZero()); //System.out.println("cond == 0: " + p.getConditionZero()); p = new ColorPolynomial(w, g, g); //System.out.println("p = " + p); assertTrue("check(p) ", p.checkInvariant()); assertTrue("deter(p) ", p.isDetermined()); assertTrue("p == 0 ", p.isZERO()); //System.out.println("cond != 0: " + p.getConditionNonZero()); //System.out.println("cond == 0: " + p.getConditionZero()); List> i = new ArrayList>(); Ideal id = new Ideal(pr, i); List> cp = new ArrayList>(); Condition cond = new Condition(id); ColoredSystem s = new ColoredSystem(cond, cp); //System.out.println("s = " + s); assertTrue("isDetermined ", s.isDetermined()); assertTrue("checkInvariant ", s.checkInvariant()); List> CS = new ArrayList>(); CS.add(s); //System.out.println("CS = " + CS); List> CSp = CS; //System.out.println("\na = " + a); //System.out.println("b = " + b + "\n"); //CS = cred.determine(p); //System.out.println("CS = " + CS); for (ColoredSystem x : CS) { assertTrue("isDetermined ", x.isDetermined()); assertTrue("checkInvariant ", x.checkInvariant()); } List>> L; L = new ArrayList>>(); L.add(a); L.add(b); //System.out.println("\na = " + a); //System.out.println("b = " + b + "\n"); //System.out.println("L = " + L); //List> Ccond; //Ccond = cred.caseDistinction(L); //for ( Condition cnd : Ccond ) { // System.out.println("" + cnd); //} //+System.out.println("Ccond = " + Ccond); // check if polynomials are determined CSp = cred.determine(L); //+System.out.println("CSp = " + CSp); for (ColoredSystem x : CSp) { assertTrue("isDetermined ", x.isDetermined()); assertTrue("checkInvariant ", x.checkInvariant()); } // check if reduced polynomials are in normalform ColorPolynomial q, h; //List> NCS; for (ColoredSystem x : CSp) { int k = x.list.size(); for (int j = 0; j < k; j++) { p = x.list.get(j); for (int l = j + 1; l < k; l++) { q = x.list.get(l); h = cred.SPolynomial(p, q); //System.out.println("spol(a,b) = " + h); boolean t = true; //cred.isNormalform( x.list, h ); //System.out.println("isNF(spol(a,b)) = " + t); h = cred.normalform(x.condition, x.list, h); //System.out.println("NF(spol(a,b)) = " + h); t = cred.isNormalform(x.list, h); //System.out.println("isNF(NF(spol(a,b))) = " + t); assertTrue("isNF(NF(spol(a,b))) ", t); //h = x.condition.reDetermine( h ); } } } } } jas-2.5/trc/edu/jas/application/LocalTest.java0000644000175000017500000001425511641660762021545 0ustar giovannigiovanni /* * $Id: LocalTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; //import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; //import edu.jas.structure.RingElem; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; /** * Local tests with JUnit. * @author Heinz Kredel. */ public class LocalTest extends TestCase { /** * main. */ public static void main (String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a LocalTest object. * @param name String. */ public LocalTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(LocalTest.class); return suite; } //private final static int bitlen = 100; Ideal id; LocalRing fac; GenPolynomialRing mfac; List> F; Local< BigRational > a; Local< BigRational > b; Local< BigRational > c; Local< BigRational > d; Local< BigRational > e; int rl = 3; int kl = 3; int ll = 5; int el = 2; float q = 0.3f; int il = 2; protected void setUp() { a = b = c = d = e = null; BigRational cfac = new BigRational(1); String[] vars = new String[] { "x", "y", "z" }; mfac = new GenPolynomialRing( cfac, rl, vars ); id = null; while ( id == null || id.isONE() ) { F = new ArrayList>( il ); for ( int i = 0; i < rl; i++ ) { //GenPolynomial mo = mfac.random(kl,ll,el,q); GenPolynomial mo = mfac.univariate(i); mo = mo.sum( mfac.fromInteger( cfac.random(7).denominator() ) ); while ( mo.isConstant() ) { mo = mfac.random(kl,ll,el,q); } F.add( mo ); } id = new Ideal(mfac,F); id = id.GB(); } //System.out.println("id = " + id); fac = new LocalRing( id ); //System.out.println("fac = " + fac); F = null; } protected void tearDown() { a = b = c = d = e = null; fac = null; id = null; mfac = null; ComputerThreads.terminate(); } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); //System.out.println("c.num = " + c.num); assertTrue("length( c ) = 1", c.num.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.num = " + d.num); assertTrue("length( d ) = 0", d.num.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { //System.out.println("fac = " + fac); for (int i = 0; i < 4; i++) { //a = fac.random(ll+i); a = fac.random(kl*(i+1), ll+i, el, q ); //System.out.println("a = " + a); assertTrue("length( a"+i+" ) <> 0", a.num.length() >= 0); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * Not jet working because of monic GBs. */ public void testAddition() { //System.out.println("fac = " + fac); a = fac.random(kl,ll,el,q); b = fac.random(kl,ll,el,q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.sum(b); d = c.subtract(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a",c,d); c = fac.random(kl,ll,el,q); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test object multiplication. * Not jet working because of monic GBs */ public void testMultiplication() { //System.out.println("fac = " + fac); a = fac.random(kl,ll,el,q); b = fac.random(kl,ll,el,q); if ( a.isZERO() || b.isZERO() ) { return; } //System.out.println("a = " + a); //System.out.println("b = " + b); assertTrue("not isZERO( a )", !a.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(kl,ll,el,q); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",d.isONE()); d = c.inverse(); //System.out.println("d = " + d); assertTrue("1/(1/a) = a",d.equals(a)); } } } jas-2.5/trc/edu/jas/application/CGBSeqTest.java0000644000175000017500000001157612004571452021551 0ustar giovannigiovanni/* * $Id: CGBSeqTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.application; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Comprehenssive Groebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class CGBSeqTest extends TestCase { //private static final Logger logger = Logger.getLogger(CGBSeqTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a CGBSeqTest object. * @param name String. */ public CGBSeqTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(CGBSeqTest.class); return suite; } GenPolynomialRing cfac; GenPolynomialRing> fac; List>> L; ComprehensiveGroebnerBaseSeq bb; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; GenPolynomial> d; GenPolynomial> e; int rl = 2; //4; //3; int kl = 2; int ll = 3; int el = 3; float q = 0.2f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(kl); String[] cv = { "a" }; //, "b" }; cfac = new GenPolynomialRing(coeff, 1, cv); String[] v = { "x" }; //, "y" }; fac = new GenPolynomialRing>(cfac, 1, v); a = b = c = d = e = null; bb = new ComprehensiveGroebnerBaseSeq(coeff); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; cfac = null; bb = null; } /* * Dummy test method for jUnit. * public void testDummy() { } */ /** * Test sequential CGB. * */ public void testSequentialCGB() { L = new ArrayList>>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = a; //fac.random(kl, ll, el, q ); d = c; //fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); L = bb.GB(L); assertTrue("isGB( { a } )", bb.isGB(L)); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); //System.out.println("L = " + L.size() ); L = bb.GB(L); assertTrue("isGB( { a, b } )", bb.isGB(L)); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.GB(L); assertTrue("isGB( { a, b, c } )", bb.isGB(L)); } /** * Test Trinks CGB. * */ @SuppressWarnings("unchecked") public void testTrinks7GBase() { PolynomialList> F = null; List>> G = null; String exam = "IntFunc(b) (S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - { 165 b + 36 } ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - { 165 b**2 } ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - { 11 b**3 } ), " + "( 99 W - { 11 b } S + { 3 b**2 } ), " + "( { b**2 + 33/50 b + 2673/10000 } ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList>) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); G = bb.GB(F.list); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G)); //PolynomialList> trinks // = new PolynomialList>(F.ring,G); //System.out.println("G = " + trinks); //System.out.println("G = " + G); } } jas-2.5/trc/edu/jas/application/RealAlgebraicTest.java0000644000175000017500000002631012014202410023134 0ustar giovannigiovanni/* * $Id: RealAlgebraicTest.java 4120 2012-08-19 15:23:53Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.root.RealRootTuple; import edu.jas.structure.NotInvertibleException; import edu.jas.structure.Power; /** * RealAlgebraicNumber Test using JUnit. * @author Heinz Kredel. */ public class RealAlgebraicTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a RealAlgebraicTest object. * @param name String. */ public RealAlgebraicTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(RealAlgebraicTest.class); return suite; } //private final static int bitlen = 100; RealAlgebraicRing fac; GenPolynomialRing mfac; RealAlgebraicNumber a; RealAlgebraicNumber b; RealAlgebraicNumber c; RealAlgebraicNumber d; RealAlgebraicNumber e; int rl = 1; int kl = 10; int ll = 10; int el = ll; float q = 0.5f; @Override protected void setUp() { a = b = c = d = e = null; BigRational rfac = new BigRational(); String[] vars = new String[] { "x", "y" }; TermOrder tord = new TermOrder(TermOrder.INVLEX); mfac = new GenPolynomialRing(rfac, tord, vars); //System.out.println("mfac = " + mfac); // z^3 - 2 i: z |--> x + i y GenPolynomial fr = mfac.parse("y**3 - 3 * x**2 * y - 2"); GenPolynomial fi = mfac.parse("-3 * x * y**2 + x**3"); List> li = new ArrayList>(2); li.add(fr); li.add(fi); Ideal id = new Ideal(mfac, li); //System.out.println("id = " + id); List> idul = id.zeroDimRootDecomposition(); IdealWithUniv idu = idul.get(0); //if (idul.size() > 1) { //System.out.println("idul = " + idul); //idu = idul.get(1); //} //System.out.println("idu = " + idu); GenPolynomial x = idu.ideal.list.list.remove(1); //System.out.println("x = " + x); x = x.multiply(x).subtract(mfac.fromInteger(3)); //System.out.println("x = " + x); idu.ideal.list.list.add(x); //System.out.println("idu = " + idu); IdealWithRealAlgebraicRoots idr = PolyUtilApp . realAlgebraicRoots(idu.ideal).get(0); //System.out.println("idr = " + idr); //idr.doDecimalApproximation(); //for ( List d : idr.decimalApproximation() ) { // System.out.println("d = " + d); //} List>> ran = idr.ran; RealRootTuple root = new RealRootTuple(ran.get(0)); if (ran.size() > 1) { //System.out.println("ran = " + ran); root = new RealRootTuple(ran.get(1)); } //System.out.println("root = " + root); fac = new RealAlgebraicRing(idu, root); //,not true); //System.out.println("fac = " + fac); } @Override protected void tearDown() { ComputerThreads.terminate(); a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); //System.out.println("c.getVal() = " + c.getVal()); //assertTrue("length( c ) = 1", c.number.getVal().length() == 1); assertTrue("isZERO( c )", !c.isZERO()); assertTrue("isONE( c )", c.isONE()); d = fac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.getVal() = " + d.getVal()); //assertTrue("length( d ) = 0", d.number.getVal().length() == 0); assertTrue("isZERO( d )", d.isZERO()); assertTrue("isONE( d )", !d.isONE()); } /** * Test random polynomial. */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(el); //System.out.println("a = " + a); if (a.isZERO() || a.isONE()) { continue; } // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); //assertTrue("length( a" + i + " ) <> 0", a.number.getVal().length() >= 0); assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); assertTrue(" not isONE( a" + i + " )", !a.isONE()); } } /** * Test real and imaginary. */ public void testReIm() { //System.out.println("fac = " + fac.toScript()); a = fac.random(ll); b = fac.random(ll); //a = fac.getZERO(); //a = fac.getONE(); //a = fac.parse("x"); //a = fac.parse("y^3 + 2"); //a = fac.parse("3 y^2"); //b = fac.parse("y"); //System.out.println("a = " + a); //System.out.println("b = " + b); ComplexRing> crr; crr = new ComplexRing>(fac); Complex> ac, cc, dc, ec; cc = new Complex>(crr, a, b); //System.out.println("cc = " + cc); assertEquals("a == re(c)", a, cc.getRe()); assertEquals("b == im(c)", b, cc.getIm()); dc = cc.conjugate(); ec = dc.conjugate(); //System.out.println("dc = " + dc); //System.out.println("ec = " + ec); assertEquals("con(con(c)) = c", cc, ec); ac = cc.multiply(dc); ec = cc.norm(); //System.out.println("ac = " + ac); //System.out.println("ec = " + ec); c = ac.getRe(); e = ec.getRe(); //System.out.println("c = " + c); //System.out.println("e = " + e); assertEquals("c*con(c) = norm(c)", c, e); c = ac.getIm(); e = ec.getIm(); //System.out.println("c = " + c); //System.out.println("e = " + e); assertEquals("c*con(c) = norm(c)", c, e); } /** * Test addition. */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a", a, d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a", c, d); c = fac.random(ll); d = c.sum(a.sum(b)); e = c.sum(a).sum(b); assertEquals("c+(a+b) = (c+a)+b", d, e); c = a.sum(fac.getZERO()); d = a.subtract(fac.getZERO()); assertEquals("a+0 = a-0", c, d); c = fac.getZERO().sum(a); d = fac.getZERO().subtract(a.negate()); assertEquals("0+a = 0+(-a)", c, d); } /** * Test object multiplication. */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO()); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO()); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO()); assertTrue("not isZERO( d )", !d.isZERO()); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO()); assertTrue("a*b = b*a", c.equals(d)); assertEquals("a*b = b*a", c, d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply(b.multiply(c)); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c", d, e); assertTrue("a(bc) = (ab)c", d.equals(e)); c = a.multiply(fac.getONE()); d = fac.getONE().multiply(a); assertEquals("a*1 = 1*a", c, d); c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*1/a = 1", fac.getONE(), d); try { a = fac.getZERO().inverse(); fail("0 invertible"); } catch (NotInvertibleException expected) { //pass, return; } } /** * Test distributive law. */ public void testDistributive() { a = fac.random(ll); b = fac.random(ll); c = fac.random(ll); d = a.multiply(b.sum(c)); e = a.multiply(b).sum(a.multiply(c)); assertEquals("a(b+c) = ab+ac", d, e); } /** * Test signum and magnitude. */ public void testSignum() { a = fac.random(ll); //a = fac.getONE(); //System.out.println("a = " + a); int s = a.signum(); //System.out.println("sign(a) = " + s); assertTrue("isZERO( c )", (a.isZERO() && s == 0) || (!a.isZERO() && s != 0)); BigDecimal r = a.decimalMagnitude(); //System.out.println("magnitude(a) = " + r); b = a.multiply(a); BigDecimal rb = b.decimalMagnitude(); //System.out.println("magnitude(a*a) = " + rb); BigDecimal rr = r.multiply(r); //System.out.println("magnitude(a)*magnitude(a) = " + rr); BigDecimal eps = Power.positivePower(new BigDecimal(0.1), 9); //BigDecimal.DEFAULT_PRECISION); //System.out.println("eps = " + eps); BigDecimal err = rr.subtract(rb).divide(rr).abs(); //System.out.println("err = " + err); assertTrue("magnitude(a)*magnitude(a) == magnitude(a*a): " + err + " <= " + eps, err.compareTo(eps) <= 0); } /** * Test compareTo of complex algebraic numbers. */ public void testCompare() { a = fac.random(ll).abs(); b = a.sum(fac.getONE()); c = b.sum(fac.getONE()); int ab = a.compareTo(b); int bc = b.compareTo(c); int ac = a.compareTo(c); assertTrue("a < a+1 ", ab < 0); assertTrue("a+1 < a+2 ", bc < 0); assertTrue("a < a+2 ", ac < 0); a = a.negate(); b = a.sum(fac.getONE()); c = b.sum(fac.getONE()); ab = a.compareTo(b); bc = b.compareTo(c); ac = a.compareTo(c); assertTrue("a < a+1 ", ab < 0); assertTrue("a+1 < a+2 ", bc < 0); assertTrue("a < a+2 ", ac < 0); } } jas-2.5/trc/edu/jas/application/ResidueTest.java0000644000175000017500000001347611715461652022116 0ustar giovannigiovanni /* * $Id: ResidueTest.java 3887 2012-02-11 12:48:43Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; //import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; //import edu.jas.structure.RingElem; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; /** * Residue tests with JUnit. * @author Heinz Kredel. */ public class ResidueTest extends TestCase { /** * main. */ public static void main (String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ResidueTest object. * @param name String. */ public ResidueTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ResidueTest.class); return suite; } //private final static int bitlen = 100; Ideal id; ResidueRing fac; GenPolynomialRing mfac; List> F; Residue< BigRational > a; Residue< BigRational > b; Residue< BigRational > c; Residue< BigRational > d; Residue< BigRational > e; int rl = 3; int kl = 3; int ll = 7; int el = 3; float q = 0.4f; int il = ( rl == 1 ? 1 : 2 ); protected void setUp() { a = b = c = d = e = null; mfac = new GenPolynomialRing( new BigRational(1), rl ); F = new ArrayList>( il ); for ( int i = 0; i < il; i++ ) { GenPolynomial mo = mfac.random(kl,ll,el,q); while ( mo.isConstant() ) { mo = mfac.random(kl,ll,el,q); } F.add( mo ); } id = new Ideal(mfac,F); //System.out.println("id = " + id); assert !id.isONE() : "id = " + id; fac = new ResidueRing( id ); //System.out.println("fac = " + fac); F = null; } protected void tearDown() { a = b = c = d = e = null; fac = null; id = null; mfac = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); //System.out.println("c.val = " + c.val); assertTrue("length( c ) = 1 ", c.val.length() == 1 || id.isONE()); assertTrue("isZERO( c )", !c.isZERO() || id.isONE()); assertTrue("isONE( c )", c.isONE() || id.isONE()); d = fac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.val = " + d.val); assertTrue("length( d ) = 0", d.val.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { //a = fac.random(ll+i); a = fac.random(kl*(i+1), ll+2*i, el+i, q ); //System.out.println("a = " + a); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.val.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = fac.random(kl,ll,el,q); b = fac.random(kl,ll,el,q); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a",c,d); c = fac.random(kl,ll,el,q); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(kl,ll,el,q); if ( a.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); a = a.monic(); b = fac.random(kl,ll,el,q); if ( b.isZERO() ) { return; } assertTrue("not isZERO( b )", !b.isZERO() ); b = b.monic(); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); d = c.remainder(a); //System.out.println("c = " + c); //System.out.println("d = " + d); if ( d.isZERO() ) { d = c.divide(a); //System.out.println("c = " + c); //System.out.println("d = " + d); e = d.multiply(a); //System.out.println("e = " + e); assertEquals("((b*a)/a)*a = b*a",e,c); } c = fac.random(kl,ll,el,q); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",d.isONE()); } } } jas-2.5/trc/edu/jas/application/HenselMultUtilTest.java0000644000175000017500000004243012004571452023414 0ustar giovannigiovanni/* * $Id: HenselMultUtilTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.PrimeList; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.structure.Power; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisor; import edu.jas.ufd.HenselMultUtil; import edu.jas.ufd.NoLiftingException; /** * HenselMultUtil tests with JUnit. Two seperate classes because of package * dependency. * @see edu.jas.ufd.HenselMultUtilTest * @author Heinz Kredel. */ public class HenselMultUtilTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a HenselMultUtilTest object. * @param name String. */ public HenselMultUtilTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(HenselMultUtilTest.class); return suite; } TermOrder tord = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 2; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; dfac = new GenPolynomialRing(new BigInteger(1), rl, tord); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, tord); rfac = new GenPolynomialRing>(cfac, 1, tord); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; dfac = null; cfac = null; rfac = null; ComputerThreads.terminate(); } protected static java.math.BigInteger getPrime1() { return PrimeList.getLongPrime(60, 93); } protected static java.math.BigInteger getPrime2() { return PrimeList.getLongPrime(30, 35); } /** * Test multivariate diophant lifting. */ public void testDiophantLifting() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModIntegerRing pm = new ModIntegerRing(p, false); //ModLongRing pl = new ModLongRing(p, false); //GenPolynomialRing pfac = new GenPolynomialRing(pm, 2, tord, new String[]{ "x", "y" }); GenPolynomialRing pfac = new GenPolynomialRing(pm, 3, tord, new String[] { "x", "y", "z" }); //GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(),pfac); BigInteger mi = m; long k = 5L; long d = 3L; java.math.BigInteger pk = p.pow((int) k); //m = new BigInteger(pk); ModIntegerRing pkm = new ModIntegerRing(pk, false); //ModLongRing pkl = new ModLongRing(pk, false); GenPolynomialRing pkfac = new GenPolynomialRing(pkm, pfac); dfac = new GenPolynomialRing(mi, pfac); //GreatestCommonDivisor ufd = GCDFactory.getProxy(mi); GreatestCommonDivisor ufd = GCDFactory.getImplementation(mi); //ModLong v = pl.fromInteger(3L); ModInteger v = pkm.fromInteger(5L); List V = new ArrayList(1); V.add(v); V.add(pkm.fromInteger(3L)); //System.out.println("V = " + V); GenPolynomial ap; GenPolynomial bp; GenPolynomial cp; //GenPolynomial dp; GenPolynomial sp; GenPolynomial tp; GenPolynomial rp; for (int i = 1; i < 2; i++) { a = dfac.random(kl + 7 * i, ll, el + 3, q).abs(); b = dfac.random(kl + 7 * i, ll, el + 2, q).abs(); //a = dfac.parse(" y^2 + 2 x y - 3 y + x^2 - 3 x - 4 "); //b = dfac.parse(" y^2 + 2 x y + 5 y + x^2 + 5 x + 4 "); //a = dfac.parse(" (x - 4 + y)*( x + y + 1 ) "); //b = dfac.parse(" (x + 4 + y)*( x + y + 1 ) "); //a = dfac.parse(" (x - 4 + y) "); ///a = dfac.parse(" (x - 13 + y) "); ///b = dfac.parse(" (x + 4 + y) "); //a = dfac.parse(" (x - 1)*(1 + x) "); //b = dfac.parse(" (x - 2)*(3 + x) "); //a = dfac.parse(" (x - 1)*(y + x) "); //b = dfac.parse(" (x - 2)*(y - x) "); //a = dfac.parse(" (x - 1)*(y + 1) "); //b = dfac.parse(" (x - 2)*(y - 1) "); //a = dfac.parse(" (x - 1)*(y^2 + 1) "); //b = dfac.parse(" (x - 2)*(y^2 - 1) "); //a = dfac.parse(" z + (y - 1)*(1 + y) "); //b = dfac.parse(" z + (y - 2)*(2 + y) "); //a = dfac.parse(" (y - 1)*(1 + y) "); //b = dfac.parse(" (y - 2)*(2 + y) "); ///a = dfac.parse(" (y - 3) "); //2 // tp = 47045880 = -1 ///b = dfac.parse(" (y - 1) "); // sp = 1 //a = dfac.parse(" (y - 4) "); // tp = 15681960 //b = dfac.parse(" (y - 1) "); // sp = 31363921 //a = dfac.parse(" (x - 3) "); // tp = 15681960, 1238049 //b = dfac.parse(" (x - 1) "); // sp = 31363921, -1238049 //a = dfac.parse(" ( y^2 + x^3 - 2 x ) "); //b = dfac.parse(" ( y - x^2 + 3 ) "); c = ufd.gcd(a, b); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (!c.isUnit()) { continue; } //c = dfac.parse(" x y z "); //System.out.println("c = " + c); ap = PolyUtil. fromIntegerCoefficients(pkfac, a); bp = PolyUtil. fromIntegerCoefficients(pkfac, b); cp = PolyUtil. fromIntegerCoefficients(pkfac, c); //if (ap.degree(0) < 1 || bp.degree(0) < 1) { // continue; //} //System.out.println("\nap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); List> lift; try { lift = HenselMultUtil. liftDiophant(ap, bp, cp, V, d, k); // 5 is max sp = lift.get(0); tp = lift.get(1); //System.out.println("liftMultiDiophant:"); //System.out.println("sp = " + sp); //System.out.println("tp = " + tp); //System.out.println("isDiophantLift: " + HenselUtil. isDiophantLift(bp,ap,sp,tp,cp) ); GenPolynomialRing qfac = sp.ring; //System.out.println("qfac = " + qfac.toScript()); assertEquals("pkfac == qfac: " + qfac, pkfac, qfac); rp = bp.multiply(sp).sum(ap.multiply(tp)); // order assertFalse("rp != null: " + rp, rp == null); //System.out.println("\nrp = " + rp); //not true: System.out.println("a s + b t = c: " + cp.equals(rp)); //assertEquals("a s + b t = c ", dp,rp); //GenPolynomialRing cfac = pkfac.contract(1); ModInteger vp = pkfac.coFac.fromInteger(V.get(0).getSymmetricInteger().getVal()); GenPolynomial ya = pkfac.univariate(1); ya = ya.subtract(vp); ya = Power.> power(pkfac, ya, d + 1); //System.out.println("ya = " + ya); List> Y = new ArrayList>(); Y.add(ya); vp = pkfac.coFac.fromInteger(V.get(1).getSymmetricInteger().getVal()); GenPolynomial za = pkfac.univariate(0); za = za.subtract(vp); za = Power.> power(pkfac, za, d + 1); //System.out.println("za = " + za); Y.add(za); //System.out.println("\nY = " + Y); Ideal Yi = new Ideal(pkfac, Y); //System.out.println("Yi = " + Yi); ResidueRing Yr = new ResidueRing(Yi); //System.out.println("Yr = " + Yr); Residue apr = new Residue(Yr, ap); Residue bpr = new Residue(Yr, bp); Residue cpr = new Residue(Yr, cp); Residue spr = new Residue(Yr, sp); Residue tpr = new Residue(Yr, tp); Residue rpr = bpr.multiply(spr).sum(apr.multiply(tpr)); // order //System.out.println("\napr = " + apr); //System.out.println("bpr = " + bpr); //System.out.println("cpr = " + cpr); //System.out.println("spr = " + spr); //System.out.println("tpr = " + tpr); //System.out.println("rpr = " + rpr); //System.out.println("ar sr + br tr = cr: " + cpr.equals(rpr) + "\n"); assertEquals("ar sr + br tr = cr ", cpr, rpr); } catch (NoLiftingException e) { // can happen: fail("" + e); System.out.println("e = " + e); } } } /** * Test multivariate diophant lifting list. */ public void testDiophantLiftingList() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModIntegerRing pm = new ModIntegerRing(p, false); //ModLongRing pl = new ModLongRing(p, false); //GenPolynomialRing pfac = new GenPolynomialRing(pm, 2, tord, new String[]{ "x", "y" }); GenPolynomialRing pfac = new GenPolynomialRing(pm, 3, tord, new String[] { "x", "y", "z" }); //GenPolynomialRing pfac = new GenPolynomialRing(pm, 4, tord, new String[]{ "w", "x", "y", "z" }); //GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(),pfac); BigInteger mi = m; long k = 5L; long d = 3L; java.math.BigInteger pk = p.pow((int) k); //m = new BigInteger(pk); ModIntegerRing pkm = new ModIntegerRing(pk, false); //ModLongRing pkl = new ModLongRing(pk, false); GenPolynomialRing pkfac = new GenPolynomialRing(pkm, pfac); dfac = new GenPolynomialRing(mi, pfac); //GreatestCommonDivisor ufd = GCDFactory.getProxy(mi); GreatestCommonDivisor ufd = GCDFactory.getImplementation(mi); //ModLong v = pl.fromInteger(3L); ModInteger v = pkm.fromInteger(5L); List V = new ArrayList(1); V.add(v); V.add(pkm.fromInteger(3L)); if (pkfac.nvar > 3) { V.add(pkm.fromInteger(7L)); } //System.out.println("V = " + V); GenPolynomial ap; GenPolynomial cp; //GenPolynomial rp; List> A = new ArrayList>(); for (int i = 1; i < 2; i++) { a = dfac.random(kl + 7 * i, ll, el + 3, q).abs(); b = dfac.random(kl + 7 * i, ll, el + 2, q).abs(); c = dfac.random(kl + 7 * i, ll, el + 2, q).abs(); //a = dfac.parse(" z + x*y + (y - 1)*(1 + y) "); //b = dfac.parse(" z - x + (y - 2)*(2 + y) "); //c = dfac.parse(" z + x + (y - 2)*(2 + y) "); A.add(a); A.add(b); A.add(c); //System.out.println("\nA = " + A); A = ufd.coPrime(A); //System.out.println("coprime(A) = " + A); if (A.size() == 0) { continue; } List> Ap = new ArrayList>(A.size()); for (GenPolynomial ai : A) { ap = PolyUtil. fromIntegerCoefficients(pkfac, ai); Ap.add(ap); } //System.out.println("A mod p^k = " + Ap); cp = pkfac.parse(" x y z + x y + x "); //cp = pkfac.parse(" x y + x "); //cp = Ap.get(0).multiply(Ap.get(1)); //System.out.println("cp = " + cp); GenPolynomial B = pkfac.getONE(); for (GenPolynomial bp : Ap) { B = B.multiply(bp); } //System.out.println("B = " + B); List> Bp = new ArrayList>(A.size()); for (GenPolynomial bp : Ap) { GenPolynomial b = PolyUtil. basePseudoDivide(B, bp); if (b.isZERO()) { System.out.println("b == 0"); return; } Bp.add(b); } //System.out.println("B mod p^k = " + Bp); try { List> lift; lift = HenselMultUtil. liftDiophant(Ap, cp, V, d, k); // 5 is max //System.out.println("liftMultiDiophant:"); //System.out.println("lift = " + lift); GenPolynomialRing qfac = lift.get(0).ring; assertEquals("pkfac == qfac: " + qfac, pkfac, qfac); //GenPolynomialRing cfac = pkfac.contract(1); List> Y = new ArrayList>(); for (int j = 0; j < V.size(); j++) { ModInteger vp = pkfac.coFac.fromInteger(V.get(j).getSymmetricInteger().getVal()); GenPolynomial ya = pkfac.univariate(pkfac.nvar - 2 - j); ya = ya.subtract(vp); //ya = Power.>power(pkfac,ya,d+1); //System.out.println("ya = " + ya); Y.add(ya); } //System.out.println("\nY = " + Y); Ideal Yi = new Ideal(pkfac, Y); //System.out.println("Yi = " + Yi); Yi = Yi.power((int) d + 1); //System.out.println("Yi = " + Yi); ResidueRing Yr = new ResidueRing(Yi); //System.out.println("\nYr = " + Yr); List> Bpr = new ArrayList>(A.size()); for (GenPolynomial tp : Bp) { Residue apr = new Residue(Yr, tp); Bpr.add(apr); } List> Spr = new ArrayList>(A.size()); for (GenPolynomial sp : lift) { Residue apr = new Residue(Yr, sp); if (apr.isZERO()) { System.out.println("apr == 0"); //return; } Spr.add(apr); } //System.out.println("\nBpr = " + Bpr); //System.out.println("Spr = " + Spr); Residue cpr = new Residue(Yr, cp); Residue rpr = Yr.getZERO(); int j = 0; for (Residue r : Bpr) { rpr = rpr.sum(r.multiply(Spr.get(j++))); } //System.out.println("cpr = " + cpr); //System.out.println("rpr = " + rpr); assertEquals("sum_i( br sr ) = cr ", cpr, rpr); } catch (ArithmeticException e) { // ok, can happen } catch (NoLiftingException e) { // can now happen: fail("" + e); System.out.println("e = " + e); } } } } jas-2.5/trc/edu/jas/application/SolvableIdealTest.java0000644000175000017500000007245512137036770023224 0ustar giovannigiovanni/* * $Id: SolvableIdealTest.java 4389 2013-04-27 21:07:05Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBase; import edu.jas.gb.SolvableGroebnerBase; import edu.jas.gb.SolvableGroebnerBaseSeq; import edu.jas.gbufd.GBFactory; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; import edu.jas.poly.WeylRelations; import edu.jas.ufd.Quotient; import edu.jas.util.KsubSet; /** * SolvableIdeal tests with JUnit. * @author Heinz Kredel. */ public class SolvableIdealTest extends TestCase { private static final Logger logger = Logger.getLogger(SolvableIdealTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a SolvableIdealTest object. * @param name String. */ public SolvableIdealTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(SolvableIdealTest.class); return suite; } TermOrder to; GenSolvablePolynomialRing fac; List> L; PolynomialList F; List> G; //List> M; SolvableGroebnerBase bb; GenSolvablePolynomial a, b, c, d, e; int rl = 4; // even for Weyl relations int kl = 3; //10 int ll = 3; //7 int el = 3; float q = 0.2f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(17, 1); to = new TermOrder( /*TermOrder.INVLEX*/); String[] vars = new String[] { "w", "x", "y", "z" }; fac = new GenSolvablePolynomialRing(coeff, rl, to, vars); WeylRelations wl = new WeylRelations(fac); wl.generate(); bb = new SolvableGroebnerBaseSeq(); //bb = GBFactory.getImplementation(coeff); a = b = c = d = e = null; } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; ComputerThreads.terminate(); } /** * Test Ideal sum. */ public void testIdealSum() { SolvableIdeal I, J, K; L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("not isONE( I )", !I.isONE()); assertTrue("isGB( I )", I.isGB()); I = new SolvableIdeal(fac, L, false); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("not isONE( I )", !I.isONE()); assertTrue("isGB( I )", I.isGB()); L = bb.leftGB(L); assertTrue("isGB( { a } )", bb.isLeftGB(L)); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); I = new SolvableIdeal(fac, L, false); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); //System.out.println("L = " + L.size() ); I = new SolvableIdeal(fac, L, false); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); //assertTrue("not isGB( I )", !I.isGB() ); L = bb.leftGB(L); assertTrue("isGB( { a, b } )", bb.isLeftGB(L)); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); // assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I; K = J.sum(I); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("equals( K, I )", K.equals(I)); L = new ArrayList>(); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); assertTrue("isGB( { c } )", bb.isLeftGB(L)); J = new SolvableIdeal(fac, L, true); K = J.sum(I); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("K contains(I)", K.contains(I)); assertTrue("K contains(J)", K.contains(J)); L = new ArrayList>(); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); assertTrue("isGB( { d } )", bb.isLeftGB(L)); J = new SolvableIdeal(fac, L, true); I = K; K = J.sum(I); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("K contains(I)", K.contains(I)); assertTrue("K contains(J)", K.contains(J)); L = new ArrayList>(); assertTrue("not isZERO( e )", !e.isZERO()); L.add(e); assertTrue("isGB( { e } )", bb.isLeftGB(L)); J = new SolvableIdeal(fac, L, true); I = K; K = J.sum(I); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); assertTrue("equals( K, I )", K.equals(I)); assertTrue("K contains(J)", K.contains(I)); assertTrue("I contains(K)", I.contains(K)); } /** * Test SolvableIdeal product. */ public void testSolvableIdealProduct() { SolvableIdeal I, J, K, H; a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el-1, q); c = fac.random(kl, ll, el-1, q); d = c; //fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L = new ArrayList>(); //assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); I = new SolvableIdeal(fac, L, false); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("not isONE( I )", !I.isONE()); assertTrue("isGB( I )", I.isGB()); L = new ArrayList>(); assertTrue("not isZERO( b )", !a.isZERO()); L.add(b); J = new SolvableIdeal(fac, L, false); assertTrue("not isZERO( J )", !J.isZERO()); assertTrue("not isONE( J )", !J.isONE()); assertTrue("isGB( J )", J.isGB()); K = I.product(J); //System.out.println("I = " + I); //System.out.println("J = " + J); //System.out.println("K = " + K); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); //non-com assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = I.intersect(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); assertTrue("I contains(H)", I.contains(H)); assertTrue("J contains(H)", J.contains(H)); //non-com assertTrue("H contains(K)", H.contains(K)); L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); //non-com assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = I.intersect(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); assertTrue("I contains(H)", I.contains(H)); assertTrue("J contains(H)", J.contains(H)); //non-com assertTrue("H contains(K)", H.contains(K)); L = new ArrayList>(); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.leftGB(L); J = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( J )", !J.isZERO()); //assertTrue("not isONE( J )", !J.isONE() ); assertTrue("isGB( J )", J.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); //non-com assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = I.intersect(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); assertTrue("I contains(H)", I.contains(H)); assertTrue("J contains(H)", J.contains(H)); //non-com assertTrue("H contains(K)", H.contains(K)); } /** * Test SolvableIdeal quotient. */ public void testSolvableIdealQuotient() { SolvableIdeal I, J, K, H; a = fac.random(kl, ll-2, el, q); b = fac.random(kl, ll, el, q/2); c = fac.random(kl, ll, el-1, q); d = c; //fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); L = new ArrayList>(); assertTrue("not isZERO( b )", !a.isZERO()); L.add(b); L = bb.leftGB(L); J = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( J )", !J.isZERO()); //assertTrue("not isONE( J )", !J.isONE() ); assertTrue("isGB( J )", J.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); //non-com assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = K.quotient(J.getList().get(0)); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); //non-com assertTrue("equals(H,I)", H.equals(I)); // GBs only H = K.quotient(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); //non-com assertTrue("equals(H,I)", H.equals(I)); // GBs only L = new ArrayList>(); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.leftGB(L); J = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( J )", !J.isZERO()); //assertTrue("not isONE( J )", !J.isONE() ); assertTrue("isGB( J )", J.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); //non-com assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = K.quotient(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); //non-com assertTrue("equals(H,I)", H.equals(I)); // GBs only L = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( J )", !J.isONE() ); assertTrue("isGB( I )", I.isGB()); K = I.product(J); assertTrue("not isZERO( K )", !K.isZERO()); assertTrue("isGB( K )", K.isGB()); //non-com assertTrue("I contains(K)", I.contains(K)); assertTrue("J contains(K)", J.contains(K)); H = K.quotient(J); assertTrue("not isZERO( H )", !H.isZERO()); assertTrue("isGB( H )", H.isGB()); //non-com assertTrue("equals(H,I)", H.equals(I)); // GBs only } /** * Test SolvableIdeal infinite quotient. */ public void testSolvableIdealInfiniteQuotient() { SolvableIdeal I, J, K; a = fac.random(kl, ll-2, el, q); b = fac.random(kl, ll-1, el-1, q); c = fac.random(kl, ll/2, el-1, q/2); d = c; //fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L = new ArrayList>(); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotient(a); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotient(a); assertTrue("equals(J,I)", J.equals(I)); // GBs only assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotient(a); assertTrue("isGB( J )", J.isGB()); assertTrue("equals(J,I)", J.equals(I)); // GBs only G = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); G.add(a); G = bb.leftGB(G); K = new SolvableIdeal(fac, G, true); assertTrue("not isZERO( K )", !K.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( K )", K.isGB()); J = I.infiniteQuotient(K); assertTrue("equals(J,I)", J.equals(I)); // GBs only assertTrue("not isZERO( e )", !e.isZERO()); G.add(e); G = bb.leftGB(G); K = new SolvableIdeal(fac, G, true); assertTrue("not isZERO( K )", !K.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( K )", K.isGB()); J = I.infiniteQuotient(K); assertTrue("equals(J,I)", J.equals(I)); // GBs only } /** * Test (commutative) SolvableIdeal infinite quotient with Rabinowich trick. */ public void testSolvableIdealInfiniteQuotientRabi() { fac = new GenSolvablePolynomialRing(fac.coFac, rl, fac.tord, fac.getVars()); SolvableIdeal I, J, K, JJ; a = fac.random(kl - 1, ll - 1, el - 1, q / 2); b = fac.random(kl - 1, ll - 1, el, q / 2); c = fac.random(kl - 1, ll - 1, el, q / 2); d = fac.random(kl - 1, ll - 1, el, q / 2); e = a; //fac.random(kl, ll-1, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L = new ArrayList>(); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotientRab(a); JJ = I.infiniteQuotient(a); assertTrue("equals(J,JJ)", J.equals(JJ)); // GBs only assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotientRab(a); assertTrue("equals(J,I)", J.equals(I)); // GBs only JJ = I.infiniteQuotient(a); assertTrue("equals(J,JJ)", J.equals(JJ)); // GBs only assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); J = I.infiniteQuotientRab(a); assertTrue("isGB( J )", J.isGB()); assertTrue("equals(J,I)", J.equals(I)); // GBs only JJ = I.infiniteQuotient(a); assertTrue("equals(J,JJ)", J.equals(JJ)); // GBs only G = new ArrayList>(); assertTrue("not isZERO( a )", !a.isZERO()); G.add(a); G = bb.leftGB(G); K = new SolvableIdeal(fac, G, true); assertTrue("not isZERO( K )", !K.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( K )", K.isGB()); J = I.infiniteQuotientRab(K); assertTrue("equals(J,I)", J.equals(I)); // GBs only JJ = I.infiniteQuotient(a); assertTrue("equals(J,JJ)", J.equals(JJ)); // GBs only assertTrue("not isZERO( e )", !e.isZERO()); G.add(e); G = bb.leftGB(G); K = new SolvableIdeal(fac, G, true); assertTrue("not isZERO( K )", !K.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( K )", K.isGB()); J = I.infiniteQuotientRab(K); assertTrue("equals(J,I)", J.equals(I)); // GBs only JJ = I.infiniteQuotient(a); assertTrue("equals(J,JJ)", J.equals(JJ)); // GBs only } /** * Test (commutative) SolvableIdeal radical membership. */ public void testSolvableIdealRadicalMember() { fac = new GenSolvablePolynomialRing(fac.coFac, rl, fac.tord, fac.getVars()); SolvableIdeal I; a = fac.random(kl - 1, ll, el - 1, q); b = fac.random(kl - 1, ll, el, q); c = fac.random(kl - 1, ll - 1, el, q / 2); //d = fac.random(kl - 1, ll - 1, el, q / 2); //e = a; //fac.random(kl, ll-1, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L = new ArrayList>(); L.add(b); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("I = " + I); if (!I.isONE() && ! a.equals(b)) { assertFalse("a in radical(b)", I.isRadicalMember(a)); assertTrue("b in radical(b)", I.isRadicalMember(b)); } L = new ArrayList>(); L.add(b.multiply(b)); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); if (!I.isONE() && ! a.equals(b)) { assertFalse("a in radical(b*b)", I.isRadicalMember(a)); assertTrue("b in radical(b*b)", I.isRadicalMember(b)); } //System.out.println("c = " + c); L.add(c); L = bb.leftGB(L); I = new SolvableIdeal(fac, L, true); assertTrue("not isZERO( I )", !I.isZERO()); //assertTrue("not isONE( I )", !I.isONE() ); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); if (!I.isONE() && ! a.equals(b)) { assertFalse("a in radical(b*b,c)", I.isRadicalMember(a)); assertTrue("b in radical(b*b,c)", I.isRadicalMember(b)); } } /** * Test SolvableIdeal common zeros. */ public void testSolvableIdealCommonZeros() { SolvableIdeal I; L = new ArrayList>(); I = new SolvableIdeal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), 1); a = fac.getZERO(); L.add(a); I = new SolvableIdeal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), 1); b = fac.getONE(); L.add(b); I = new SolvableIdeal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), -1); L = new ArrayList>(); a = fac.random(kl, ll, el, q); if (!a.isZERO() && !a.isConstant()) { L.add(a); I = new SolvableIdeal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), 1); } L = (List>) fac.univariateList(); I = new SolvableIdeal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), 0); L.remove(0); I = new SolvableIdeal(fac, L, true); assertEquals("commonZeroTest( I )", I.commonZeroTest(), 1); } /** * Test SolvableIdeal dimension. */ public void testSolvableIdealDimension() { SolvableIdeal I; L = new ArrayList>(); Dimension dim; I = new SolvableIdeal(fac, L, true); assertEquals("dimension( I )", rl, I.dimension().d); a = fac.getZERO(); L.add(a); I = new SolvableIdeal(fac, L, true); assertEquals("dimension( I )", rl, I.dimension().d); b = fac.getONE(); L.add(b); I = new SolvableIdeal(fac, L, true); assertEquals("dimension( I )", -1, I.dimension().d); L = new ArrayList>(); a = fac.random(kl, ll, el, q); if (!a.isZERO() && !a.isConstant()) { L.add(a); I = new SolvableIdeal(fac, L, true); //System.out.println("a = " + a); dim = I.dimension(); //System.out.println("dim(I) = " + dim); assertTrue("dimension( I )", dim.d >= 1); } L = (List>) fac.univariateList(); I = new SolvableIdeal(fac, L, true); dim = I.dimension(); assertEquals("dimension( I )", 0, dim.d); while (L.size() > 0) { L.remove(0); I = new SolvableIdeal(fac, L, true); //System.out.println("I = " + I); dim = I.dimension(); //System.out.println("dim(I) = " + dim); assertEquals("dimension( I )", rl - L.size(), dim.d); } L = (List>) fac.univariateList(); I = new SolvableIdeal(fac, L, true); I = I.product(I); //System.out.println("I = " + I); dim = I.dimension(); //System.out.println("dim(I) = " + dim); assertTrue("dimension( I )", 0 >= dim.d); L = I.getList(); while (L.size() > 0) { L.remove(0); I = new SolvableIdeal(fac, L, true); //System.out.println("I = " + I); dim = I.dimension(); //System.out.println("dim(I) = " + dim); assertTrue("dimension( I )", dim.d > 0); } } /** * Test elimination SolvableIdeals. */ public void testElimSolvableIdeal() { String[] vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); SolvableIdeal I, J; L = new ArrayList>(); //non-com a = fac.univariate(0, 3L); //fac.random(kl, ll, el, q ); b = fac.univariate(1, 2L); //fac.random(kl, ll, el, q ); c = fac.univariate(0, 1L); //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); I = new SolvableIdeal(fac, L); I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("not isONE( I )", !I.isONE()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); List sv = new ArrayList(vars.length); for (int i = 0; i < vars.length; i++) { sv.add(vars[i]); } //System.out.println("sv = " + sv); for (int i = 2; i <= vars.length; i=i+2) { KsubSet ps = new KsubSet(sv, i); //System.out.println("========================== ps : " + i); for (List ev : ps) { //System.out.println("ev = " + ev); String[] evars = new String[ev.size()]; for (int j = 0; j < ev.size(); j++) { evars[j] = ev.get(j); } GenSolvablePolynomialRing efac; efac = new GenSolvablePolynomialRing(fac.coFac, evars.length, fac.tord, evars); WeylRelations wl = new WeylRelations(efac); wl.generate(); //System.out.println("efac = " + efac); J = I.eliminate(efac); //System.out.println("J = " + J); assertTrue("isGB( J )", J.isGB()); assertTrue("size( J ) <= |ev|", J.getList().size() <= ev.size()); //System.out.println("J = " + J); break; // non-com } } } /** * Test univariate polynomials in ideal. */ public void testUnivPoly() { String[] vars; BigRational coeff = new BigRational(17, 1); to = new TermOrder(TermOrder.INVLEX); vars = new String[] { "w", "x", "y", "z" }; fac = new GenSolvablePolynomialRing(coeff, rl, to, vars); vars = fac.getVars(); //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("fac = " + fac); assertTrue("vars.length == 4 ", vars.length == 4); SolvableIdeal I; L = new ArrayList>(); a = fac.parse("( x^3 + 34/55 x^2 + 1/9 x + 99 )"); b = fac.parse("( y^4 - x )"); c = fac.parse("( z^3 - x y )"); d = fac.parse("( w^2 + 3 )"); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); L.add(d); I = new SolvableIdeal(fac, L); //I.doGB(); assertTrue("not isZERO( I )", !I.isZERO()); assertTrue("isGB( I )", I.isGB()); //System.out.println("I = " + I); for (int i = 0; i < rl; i++) { // rl GenSolvablePolynomial u = I.constructUnivariate(rl - 1 - i); //System.out.println("u = " + u); GenSolvablePolynomial U = fac.parse(u.toString()); //System.out.println("U = " + U + "\n"); assertTrue("I.contains(U) ", I.contains(U)); } List> Us = I.constructUnivariate(); for (GenSolvablePolynomial u : Us) { //System.out.println("u = " + u); GenSolvablePolynomial U = fac.parse(u.toString()); //System.out.println("U = " + U + "\n"); assertTrue("I.contains(U) ", I.contains(U)); } } } jas-2.5/trc/edu/jas/application/FactorRealRealTest.java0000644000175000017500000001107511713054716023332 0ustar giovannigiovanni/* * $Id: FactorRealRealTest.java 3869 2012-02-03 22:03:59Z kredel $ */ package edu.jas.application; import java.util.SortedMap; import java.util.List; import org.apache.log4j.BasicConfigurator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.root.Interval; import edu.jas.root.RootUtil; import edu.jas.ufd.FactorAbstract; /** * Factor real algebraic tests with JUnit. * @author Heinz Kredel. */ public class FactorRealRealTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorRealRealTest object. * @param name String. */ public FactorRealRealTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorRealRealTest.class); return suite; } int rl = 1; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. */ public void testDummy() { } /** * Test real real algebraic factorization. */ public void testRealRealAlgebraicFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational bfac = new BigRational(1); ComplexRing cfac = new ComplexRing(bfac); String[] vars = new String[] { "z" }; GenPolynomialRing> dfac = new GenPolynomialRing>(cfac, to, vars); GenPolynomial> ap = dfac.parse("z^3 - i2"); List>> roots = RootFactory. complexAlgebraicNumbersComplex(ap); //System.out.println("ap = " + ap); //System.out.println("roots = " + roots); assertTrue("#roots == deg(ap) ", roots.size() == ap.degree(0)); for ( Complex> root : roots ) { RealAlgebraicRing rfac = root.getRe().ring; rfac.setField(true); // ?? to check assertTrue("isField(rfac) ", rfac.isField()); FactorRealReal fac = new FactorRealReal(rfac); //FactorAbstract> fac = FactorFactory.> getImplementation(rfac); String[] var = new String[] { "t" }; GenPolynomialRing> rpfac = new GenPolynomialRing>(rfac, to, var); // univariate GenPolynomial> a; GenPolynomial> b = rpfac.random(2, ll, el, q); GenPolynomial> c = rpfac.random(2, ll, el, q); if (b.degree() == 0) { b = b.multiply(rpfac.univariate(0)); } //b = b.monic(); int facs = 0; if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); //a = c; //a = a.monic(); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("b = " + b.monic()); //System.out.println("c = " + c.monic()); SortedMap>, Long> sm = fac.baseFactors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { System.out.println("sm.size() < facs = " + facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); break; } } } jas-2.5/trc/edu/jas/application/FactorTest.java0000644000175000017500000002566112002611634021716 0ustar giovannigiovanni/* * $Id: FactorTest.java 4010 2012-07-21 20:39:56Z kredel $ */ package edu.jas.application; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.structure.RingFactory; import edu.jas.ufd.FactorRational; import edu.jas.ufd.Factorization; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; import edu.jas.ufd.FactorAlgebraic; import edu.jas.ufd.FactorQuotient; import edu.jas.ufd.FactorModular; import edu.jas.ufd.FactorInteger; /** * Factor tests with JUnit. * @see edu.jas.ufd.FactorTest * @author Heinz Kredel. */ public class FactorTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorTest object. * @param name String. */ public FactorTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. */ public void testDummy() { } /** * Test factory. */ public void testFactory() { ModIntegerRing mi = new ModIntegerRing(19, true); Factorization ufdm = FactorFactory.getImplementation(mi); //System.out.println("ufdm = " + ufdm); assertTrue("ufd != Modular " + ufdm, ufdm instanceof FactorModular); ModLongRing ml = new ModLongRing(19, true); Factorization ufdml = FactorFactory.getImplementation(ml); //System.out.println("ufdml = " + ufdml); assertTrue("ufd != Modular " + ufdml, ufdml instanceof FactorModular); BigInteger bi = new BigInteger(1); Factorization ufdi = FactorFactory.getImplementation(bi); //System.out.println("ufdi = " + ufdi); assertTrue("ufd != Integer " + ufdi, ufdi instanceof FactorInteger); BigRational br = new BigRational(1); Factorization ufdr = FactorFactory.getImplementation(br); //System.out.println("ufdr = " + ufdr); assertTrue("ufd != Rational " + ufdr, ufdr instanceof FactorRational); GenPolynomialRing pmfac = new GenPolynomialRing(mi, 1); GenPolynomial pm = pmfac.univariate(0); AlgebraicNumberRing am = new AlgebraicNumberRing(pm, true); Factorization> ufdam = FactorFactory.getImplementation(am); //System.out.println("ufdam = " + ufdam); assertTrue("ufd != AlgebraicNumber " + ufdam, ufdam instanceof FactorAlgebraic); GenPolynomialRing prfac = new GenPolynomialRing(br, 1); GenPolynomial pr = prfac.univariate(0); AlgebraicNumberRing ar = new AlgebraicNumberRing(pr, true); Factorization> ufdar = FactorFactory.getImplementation(ar); //System.out.println("ufdar = " + ufdar); assertTrue("ufd != AlgebraicNumber " + ufdar, ufdar instanceof FactorAlgebraic); prfac = new GenPolynomialRing(br, 2); QuotientRing qrfac = new QuotientRing(prfac); Factorization> ufdqr = FactorFactory.getImplementation(qrfac); //System.out.println("ufdqr = " + ufdqr); assertTrue("ufd != Quotient " + ufdqr, ufdqr instanceof FactorQuotient); } /** * Test factory generic. */ @SuppressWarnings("unchecked") public void testFactoryGeneric() { ModIntegerRing mi = new ModIntegerRing(19, true); Factorization ufdm = FactorFactory.getImplementation((RingFactory) mi); //System.out.println("ufdm = " + ufdm); assertTrue("ufd != Modular " + ufdm, ufdm instanceof FactorModular); BigInteger bi = new BigInteger(1); Factorization ufdi = FactorFactory.getImplementation((RingFactory) bi); //System.out.println("ufdi = " + ufdi); assertTrue("ufd != Integer " + ufdi, ufdi instanceof FactorInteger); BigRational br = new BigRational(1); Factorization ufdr = FactorFactory.getImplementation((RingFactory) br); //System.out.println("ufdr = " + ufdr); assertTrue("ufd != Rational " + ufdr, ufdr instanceof FactorRational); GenPolynomialRing pmfac = new GenPolynomialRing(mi, 1); GenPolynomial pm = pmfac.univariate(0); AlgebraicNumberRing am = new AlgebraicNumberRing(pm, true); Factorization> ufdam = FactorFactory.getImplementation((RingFactory) am); //System.out.println("ufdam = " + ufdam); assertTrue("ufd != AlgebraicNumber " + ufdam, ufdam instanceof FactorAlgebraic); GenPolynomialRing prfac = new GenPolynomialRing(br, 1); GenPolynomial pr = prfac.univariate(0); AlgebraicNumberRing ar = new AlgebraicNumberRing(pr, true); Factorization> ufdar = FactorFactory.getImplementation((RingFactory) ar); //System.out.println("ufdar = " + ufdar); assertTrue("ufd != AlgebraicNumber " + ufdar, ufdar instanceof FactorAlgebraic); prfac = new GenPolynomialRing(br, 2); QuotientRing qrfac = new QuotientRing(prfac); Factorization> ufdqr = FactorFactory.getImplementation((RingFactory) qrfac); //System.out.println("ufdqr = " + ufdqr); assertTrue("ufd != Quotient " + ufdqr, ufdqr instanceof FactorQuotient); pmfac = new GenPolynomialRing(mi, 1); QuotientRing qmfac = new QuotientRing(pmfac); Factorization> ufdqm = FactorFactory.getImplementation((RingFactory) qmfac); //System.out.println("ufdqm = " + ufdqm); assertTrue("ufd != Quotient " + ufdqm, ufdqm instanceof FactorQuotient); prfac = new GenPolynomialRing(br, 2); GenPolynomialRing> rrfac = new GenPolynomialRing>( prfac, 1); Factorization ufdrr = FactorFactory.getImplementation((RingFactory) rrfac); //System.out.println("ufdrr = " + ufdrr); assertTrue("ufd != GenPolynomial> " + ufdrr, ufdrr instanceof FactorRational); } /** * Test factory specific. */ public void testFactorySpecific() { ModIntegerRing mi = new ModIntegerRing(19, true); Factorization ufdm = FactorFactory.getImplementation(mi); //System.out.println("ufdm = " + ufdm); assertTrue("ufd != Modular " + ufdm, ufdm instanceof FactorModular); BigInteger bi = new BigInteger(1); Factorization ufdi = FactorFactory.getImplementation(bi); //System.out.println("ufdi = " + ufdi); assertTrue("ufd != Integer " + ufdi, ufdi instanceof FactorInteger); BigRational br = new BigRational(1); Factorization ufdr = FactorFactory.getImplementation(br); //System.out.println("ufdr = " + ufdr); assertTrue("ufd != Rational " + ufdr, ufdr instanceof FactorRational); GenPolynomialRing pmfac = new GenPolynomialRing(mi, 1); GenPolynomial pm = pmfac.univariate(0); AlgebraicNumberRing am = new AlgebraicNumberRing(pm, true); Factorization> ufdam = FactorFactory. getImplementation(am); //System.out.println("ufdam = " + ufdam); assertTrue("ufd != AlgebraicNumber " + ufdam, ufdam instanceof FactorAlgebraic); GenPolynomialRing prfac = new GenPolynomialRing(br, 1); GenPolynomial pr = prfac.univariate(0); AlgebraicNumberRing ar = new AlgebraicNumberRing(pr, true); Factorization> ufdar = FactorFactory. getImplementation(ar); //System.out.println("ufdar = " + ufdar); assertTrue("ufd != AlgebraicNumber " + ufdar, ufdar instanceof FactorAlgebraic); prfac = new GenPolynomialRing(br, 2); QuotientRing qrfac = new QuotientRing(prfac); Factorization> ufdqr = FactorFactory. getImplementation(qrfac); //System.out.println("ufdqr = " + ufdqr); assertTrue("ufd != Quotient " + ufdqr, ufdqr instanceof FactorQuotient); pmfac = new GenPolynomialRing(mi, 1); QuotientRing qmfac = new QuotientRing(pmfac); Factorization> ufdqm = FactorFactory. getImplementation(qmfac); //System.out.println("ufdqm = " + ufdqm); assertTrue("ufd != Quotient " + ufdqm, ufdqm instanceof FactorQuotient); prfac = new GenPolynomialRing(br, 2); Factorization ufdrr = FactorFactory. getImplementation(prfac); //System.out.println("ufdrr = " + ufdrr); assertTrue("ufd != GenPolynomial> " + ufdrr, ufdrr instanceof FactorRational); //GenPolynomialRing> rrfac = new GenPolynomialRing>( // prfac, 1); //RingFactory> rrfac1 = (RingFactory>) (RingFactory) rrfac; //ufdrr = FactorFactory. getImplementation(rrfac1); //.coFac); //ufdrr = FactorFactory.>getImplementation(rrfac1); //.coFac); //ufdrr = FactorFactory.getImplementation(rrfac.coFac); //System.out.println("ufdrr = " + ufdrr); //assertTrue("ufd != GenPolynomial> " + ufdrr, // ufdrr instanceof FactorRational); } } jas-2.5/trc/edu/jas/application/ComplexRootTest.java0000644000175000017500000003025612014206114022743 0ustar giovannigiovanni/* * $Id: ComplexRootTest.java 4122 2012-08-19 15:54:52Z kredel $ */ package edu.jas.application; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.structure.Power; import edu.jas.ufd.Squarefree; import edu.jas.ufd.SquarefreeFactory; /** * RootUtil tests with JUnit. * @author Heinz Kredel. */ public class ComplexRootTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a ComplexRootTest object. * @param name String. */ public ComplexRootTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(ComplexRootTest.class); return suite; } TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing> dfac; ComplexRing cfac; BigRational eps; Complex ceps; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; GenPolynomial> d; GenPolynomial> e; int rl = 1; int kl = 3; int ll = 3; int el = 5; float q = 0.7f; @Override protected void setUp() { a = b = c = d = e = null; cfac = new ComplexRing(new BigRational(1)); String[] vars = new String[] { "z" }; dfac = new GenPolynomialRing>(cfac, rl, to, vars); eps = Power.positivePower(new BigRational(1L, 10L), BigDecimal.DEFAULT_PRECISION); ceps = new Complex(cfac, eps); } @Override protected void tearDown() { a = b = c = d = e = null; dfac = null; cfac = null; eps = null; } /** * Test complex roots, imaginary. */ public void testComplexRootsImag() { //Complex I = cfac.getIMAG(); //a = dfac.parse("z^3 - i2"); //a = dfac.random(ll+1).monic(); //a = dfac.parse("z^7 - 2 z"); a = dfac.parse("z^6 - i3"); //System.out.println("a = " + a); List>> roots; roots = RootFactory. complexAlgebraicNumbersComplex(a); //System.out.println("a = " + a); //System.out.println("roots = " + roots); assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); for (Complex> root : roots) { //System.out.println("root = " + root.getRe().decimalMagnitude() + " + " + root.getIm().decimalMagnitude() + " i"); assertTrue("f(r) == 0: " + root, RootFactory. isRoot(a, root)); } } /* * Test complex roots, random polynomial. */ public void testComplexRootsRand() { //Complex I = cfac.getIMAG(); a = dfac.random(ll + 1).monic(); if (a.isZERO() || a.isONE()) { a = dfac.parse("z^6 - i3"); } Squarefree> sqf = SquarefreeFactory .> getImplementation(cfac); a = sqf.squarefreePart(a); //System.out.println("a = " + a); List>> roots; roots = RootFactory. complexAlgebraicNumbersComplex(a); //System.out.println("a = " + a); //System.out.println("roots = " + roots); assertTrue("#roots == deg(a): " + (roots.size() - a.degree(0)) + ", a = " + a, roots.size() == a.degree(0)); for (Complex> root : roots) { //System.out.println("root = " + root.getRe().decimalMagnitude() + " + " + root.getIm().decimalMagnitude() + " i"); assertTrue("f(r) == 0: " + root, RootFactory. isRoot(a, root)); } } /** * Test polynomial with complex roots. */ public void testPolynomialComplexRoots() { a = dfac.parse("z^3 - 2"); //System.out.println("a = " + a); List>> roots = RootFactory . complexAlgebraicNumbersComplex(a); //System.out.println("a = " + a); //System.out.println("roots = " + roots); assertTrue("#roots == deg(a) ", roots.size() == a.degree(0)); for (Complex> car : roots) { //System.out.println("car = " + car); RealAlgebraicRing rfac = car.getRe().ring; rfac.setField(true); // ?? to check assertTrue("isField(rfac) ", rfac.isField()); assertTrue("f(r) == 0: " + car, RootFactory. isRoot(a, car)); } Complex> root = roots.get(2); // 0,1,2) //System.out.println("a = " + a); //System.out.println("root = " + root.getRe().decimalMagnitude() + " + " // + root.getIm().decimalMagnitude() + " i"); //System.out.println("root = " + root.getRe() + " + " + root.getIm() + " i"); //String vre = root.getRe().toString().replace("{", "").replace("}", "").trim(); //String vim = root.getIm().toString().replace("{", "").replace("}", "").trim(); //System.out.println("vre = " + vre); //System.out.println("vim = " + vim); //String IM = root.ring.getIMAG().toString().replace("{", "").replace("}", "").replace(" ", "").trim(); //System.out.println("IM = " + IM); GenPolynomialRing>> cring = new GenPolynomialRing>>( root.ring, to, new String[] { "t" }); //List>>> gens = cring.generators(); //System.out.println("gens = " + gens); GenPolynomial>> cpol; //cpol = cring.random(1, 4, 4, q); //cpol = cring.univariate(0,3L).subtract(cring.fromInteger(2L)); //cpol = cring.univariate(0,3L).subtract(gens.get(2)); //cpol = cring.univariate(0,5L).subtract(cring.univariate(0,2L).multiply(root)); //cpol = cring.univariate(0,4L).subtract(root); //cpol = cring.univariate(0,4L).subtract(root.multiply(root)); //cpol = cring.univariate(0,3L).subtract(cring.univariate(0,1L).multiply(root).sum(root.multiply(root))); cpol = cring.univariate(0, 2L).subtract(root.multiply(root)); // okay //cpol = cring.univariate(0,3L).subtract(root.multiply(root)); // okay //cpol = cring.univariate(0,3L).subtract(root.multiply(root).multiply(root)); // not much sense r^3 = 2 ///String vpol = vre + " + " + IM + " " + vim; //String vpol = " 3 + " + IM + " * 3 "; //String vpol = " 3i3 "; //String vpol = IM + " " + vim; //String vpol = " 2 ";// + vre; // + " " + IM; //String vpol = vre; // + " " + IM; //System.out.println("vpol = " + vpol); //cpol = cring.univariate(0, 3L).subtract(cring.parse(vpol)); cpol = cpol.monic(); //System.out.println("cpol = " + cpol); //long dd = cpol.degree(0); Squarefree>> sen = SquarefreeFactory .>> getImplementation(root.ring); cpol = sen.squarefreePart(cpol); //if (cpol.degree(0) < dd) { //System.out.println("cpol = " + cpol); //} //System.out.println("cpol = " + cpol); // new version with recursion: with real factorization long t1 = System.currentTimeMillis(); List>>> croots = RootFactory .> complexAlgebraicNumbersComplex(cpol); t1 = System.currentTimeMillis() - t1; assertTrue("nonsense " + t1, t1 >= 0L); //System.out.println("\na = " + a.toScript()); //System.out.println("root = " + root.getRe().decimalMagnitude() + " + " // + root.getIm().decimalMagnitude() + " i"); //System.out.println("a = " + a); //System.out.println("root = " + root.getRe().decimalMagnitude() + " + " // + root.getIm().decimalMagnitude() + " i"); //System.out.println("root = " + root.getRe() + " + (" + root.getIm() + ") i"); //System.out.println("root.ring = " + root.ring); //System.out.println("cpol = " + cpol); //System.out.println("cpol.ring = " + cpol.ring); //System.out.println("croots = " + croots); for (Complex>> croot : croots) { //System.out.println("croot = " + croot); //System.out.println("croot = " + croot.getRe() + " + ( " + croot.getIm() + ") i"); //System.out.println("croot.ring = " + croot.ring); //magnitude()); //System.out.println("croot = " + croot.getRe().decimalMagnitude() + " + " // + croot.getIm().decimalMagnitude() + " i"); assertTrue("f(r) == 0: " + croot, RootFactory.> isRoot(cpol, croot)); } assertTrue("#croots == deg(cpol) " + croots.size() + " != " + cpol.degree(0), croots.size() == cpol.degree(0)); // existing version with winding number and recursion: but only one step long t2 = System.currentTimeMillis(); List>> coroots = edu.jas.root.RootFactory .> complexAlgebraicNumbersComplex(cpol); t2 = System.currentTimeMillis() - t2; assertTrue("nonsense " + t2, t2 >= 0L); //System.out.println("\ncpol = " + cpol); //System.out.println("root = " + root.getRe() + " + (" + root.getIm() + ") i"); //System.out.println("root = " + root.getRe().decimalMagnitude() + " + " // + root.getIm().decimalMagnitude() + " i"); for (edu.jas.root.ComplexAlgebraicNumber> cr2 : coroots) { //System.out.println("r2.ring = " + cr2.ring); //magnitude()); assertTrue("f(r) == 0: " + cr2, edu.jas.root.RootFactory.> isRootComplex(cpol, cr2)); } // decimal for comparison long t3 = System.currentTimeMillis(); for (Complex>> croot : croots) { String crs = croot.getRe().decimalMagnitude() + " + " + croot.getIm().decimalMagnitude() + " i"; //System.out.println("croot = " + crs); assertFalse("crs not empty", crs.length() == 0); // java-5 } t3 = System.currentTimeMillis() - t3; assertTrue("nonsense " + t3, t3 >= 0L); long t4 = System.currentTimeMillis(); for (edu.jas.root.ComplexAlgebraicNumber> cr2 : coroots) { String crs = cr2.decimalMagnitude().toString(); //System.out.println("r2.dec = " + crs); assertFalse("crs not empty", crs.length() == 0); // java-5 } t4 = System.currentTimeMillis() - t4; assertTrue("nonsense " + t4, t4 >= 0L); assertTrue("#coroots == deg(cpol) ", coroots.size() == cpol.degree(0)); //System.out.println("time, real ideal = " + t1 + "+" + t3 + ", complex winding = " + t2 + "+" + t4 + " milliseconds"); } } jas-2.5/trc/edu/jas/application/ExtensionFieldBuilderTest.java0000644000175000017500000004143012004571452024724 0ustar giovannigiovanni/* * $Id: ExtensionFieldBuilderTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.application; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.arith.ModLongRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.root.RealAlgebraicNumber; import edu.jas.root.RootFactory; import edu.jas.structure.Power; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; /** * ExtensionFieldBuilder tests with JUnit. * @author Heinz Kredel. */ public class ExtensionFieldBuilderTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a ExtensionFieldBuilderTest object. * @param name String. */ public ExtensionFieldBuilderTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(ExtensionFieldBuilderTest.class); return suite; } ExtensionFieldBuilder builder; @Override protected void setUp() { builder = null; } @Override protected void tearDown() { builder = null; ComputerThreads.terminate(); } /** * Test construction Q(sqrt(2))(x)(sqrt(x)) by hand. */ public void testConstructionF0() { BigRational bf = new BigRational(1); GenPolynomialRing pf = new GenPolynomialRing(bf, new String[] { "w2" }); GenPolynomial a = pf.parse("w2^2 - 2"); AlgebraicNumberRing af = new AlgebraicNumberRing(a); GenPolynomialRing> tf = new GenPolynomialRing>( af, new String[] { "x" }); QuotientRing> qf = new QuotientRing>(tf); GenPolynomialRing>> qaf = new GenPolynomialRing>>( qf, new String[] { "wx" }); GenPolynomial>> b = qaf.parse("wx^2 - x"); AlgebraicNumberRing>> fac = new AlgebraicNumberRing>>( b); //System.out.println("fac = " + fac.toScript()); List>>> gens = fac.generators(); int s = gens.size(); //System.out.println("gens = " + gens); assertTrue("#gens == 4 " + s, s == 4); AlgebraicNumber>> elem = fac.random(2); if (elem.isZERO() || elem.isONE()) { elem = gens.get(s - 1).sum(gens.get(s - 2)); //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2)); elem = elem.multiply(elem); } //System.out.println("elem = " + elem.toScript()); //System.out.println("elem = " + elem); AlgebraicNumber>> inv = elem.inverse(); //System.out.println("inv = " + inv.toScript()); //System.out.println("inv = " + inv); AlgebraicNumber>> e = elem.multiply(inv); assertTrue("e / e == 1 " + e, e.isONE()); } /** * Test construction Q(sqrt(2))(x)(sqrt(x)) by extension field builder. */ public void testConstructionF1() { builder = ExtensionFieldBuilder.baseField(new BigRational(1)); //System.out.println("builder = " + builder.toString()); RingFactory fac = builder.build(); //System.out.println("fac = " + fac.toScript()); builder = builder.algebraicExtension("w2", "w2^2 - 2"); //System.out.println("builder = " + builder.toString()); fac = builder.build(); //System.out.println("fac = " + fac.toScript()); builder = builder.transcendentExtension("x"); //System.out.println("builder = " + builder.toString()); fac = builder.build(); //System.out.println("fac = " + fac.toScript()); builder = builder.algebraicExtension("wx", "wx^2 - x"); // number of { } resolved //System.out.println("builder = " + builder.toString()); fac = builder.build(); //System.out.println("fac = " + fac.toScript()); List gens = fac.generators(); int s = gens.size(); //System.out.println("gens = " + gens); assertTrue("#gens == 4 " + s, s == 4); RingElem elem = (RingElem) fac.random(2); if (elem.isZERO() || elem.isONE()) { elem = (RingElem) gens.get(s - 1).sum(gens.get(s - 2)); //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2)); elem = (RingElem) elem.multiply(elem); } //System.out.println("elem = " + elem.toScript()); //System.out.println("elem = " + elem); RingElem inv = (RingElem) elem.inverse(); //System.out.println("inv = " + inv.toScript()); //System.out.println("inv = " + inv); RingElem a = (RingElem) elem.multiply(inv); assertTrue("e / e == 1 " + a, a.isONE()); } /** * Test construction Q(x)(sqrt(2))(sqrt(x)) by extension field builder. */ public void testConstructionF2() { builder = ExtensionFieldBuilder.baseField(new BigRational(1)); //System.out.println("builder = " + builder.toString()); RingFactory fac = builder.build(); //System.out.println("fac = " + fac.toScript()); builder = builder.transcendentExtension("x"); //System.out.println("builder = " + builder.toString()); fac = builder.build(); //System.out.println("fac = " + fac.toScript()); builder = builder.algebraicExtension("w2", "w2^2 - 2"); //System.out.println("builder = " + builder.toString()); fac = builder.build(); //System.out.println("fac = " + fac.toScript()); builder = builder.algebraicExtension("wx", "wx^2 - x"); // number of { } resolved //System.out.println("builder = " + builder.toString()); fac = builder.build(); //System.out.println("fac = " + fac.toScript()); List gens = fac.generators(); int s = gens.size(); //System.out.println("gens = " + gens); assertTrue("#gens == 4 " + s, s == 4); RingElem elem = (RingElem) fac.random(1); if (elem.isZERO() || elem.isONE()) { elem = (RingElem) gens.get(s - 1).sum(gens.get(s - 2)); //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2)); elem = (RingElem) elem.multiply(elem); } //System.out.println("elem = " + elem.toScript()); //System.out.println("elem = " + elem); RingElem inv = (RingElem) elem.inverse(); //System.out.println("inv = " + inv.toScript()); //System.out.println("inv = " + inv); RingElem a = (RingElem) elem.multiply(inv); assertTrue("e / e == 1 " + a, a.isONE()); } /** * Test construction Z_p(sqrt(2))(x)(sqrt(x)) by extension field builder. */ public void testConstructionF3() { RingFactory fac = ExtensionFieldBuilder.baseField(new ModLongRing(7)) .algebraicExtension("w2", "w2^2 - 3").transcendentExtension("x") .algebraicExtension("wx", "wx^7 - x").build(); //System.out.println("fac = " + fac.toScript()); List gens = fac.generators(); int s = gens.size(); //System.out.println("gens = " + gens); assertTrue("#gens == 4 " + s, s == 4); RingElem elem = (RingElem) fac.random(2); if (elem.isZERO() || elem.isONE()) { elem = (RingElem) gens.get(s - 1).sum(gens.get(s - 2)); //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2)); elem = (RingElem) elem.multiply(elem); } //System.out.println("elem = " + elem.toScript()); //System.out.println("elem = " + elem); RingElem inv = (RingElem) elem.inverse(); //System.out.println("inv = " + inv.toScript()); //System.out.println("inv = " + inv); RingElem a = (RingElem) elem.multiply(inv); assertTrue("e / e == 1 " + a, a.isONE()); } /** * Test construction Q(+3rt(3))(+sqrt(+3rt(3)))(+5rt(2)) by extension field * builder. */ public void testConstructionR1() { RingFactory fac = ExtensionFieldBuilder.baseField(new BigRational(1)) .realAlgebraicExtension("q", "q^3 - 3", "[1,2]") .realAlgebraicExtension("w", "w^2 - q", "[1,2]") .realAlgebraicExtension("s", "s^5 - 2", "[1,2]").build(); //System.out.println("fac = " + fac.toScript()); List gens = fac.generators(); int s = gens.size(); //System.out.println("gens = " + gens); assertTrue("#gens == 4 " + s, s == 4); RingElem elem = (RingElem) fac.random(2); if (elem.isZERO() || elem.isONE()) { elem = (RingElem) gens.get(s - 1).sum(gens.get(s - 2)); //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2)); elem = (RingElem) elem.multiply(elem); } //elem = (RingElem)elem.negate(); //System.out.println("elem = " + elem.toScript()); //System.out.println("elem = " + elem); //BigDecimal ed = new BigDecimal(((Rational)elem).getRational()); //System.out.println(" ~ " + ed); RingElem inv = (RingElem) elem.inverse(); //System.out.println("inv = " + inv.toScript()); //System.out.println("inv = " + inv); //BigDecimal id = new BigDecimal(((Rational)inv).getRational()); //System.out.println(" ~ " + id); RingElem a = (RingElem) elem.multiply(inv); //System.out.println("a = " + a); //System.out.println(" ~ " + ed.multiply(id)); assertTrue("e / e == 1 " + a, a.isONE()); } /** * Test construction Q(sqrt(-1))(+3rt(i)) by extension field builder. */ public void testConstructionC1() { ComplexRing cf = new ComplexRing(new BigRational(1)); //System.out.println("cf = " + cf.toScript()); RingFactory fac = ExtensionFieldBuilder.baseField(cf) .complexAlgebraicExtension("w2", "w2^2 + 2", "[-1i0,1i2]") //.complexAlgebraicExtension("q3", "q3^3 + { w2 }","[-1i0,1i2]") // not possible, TODO .build(); //System.out.println("fac = " + fac.toScript()); List gens = fac.generators(); int s = gens.size(); //System.out.println("gens = " + gens); assertTrue("#gens == 3 " + s, s == 3); RingElem elem = (RingElem) fac.random(2); if (elem.isZERO() || elem.isONE()) { elem = (RingElem) gens.get(s - 1).sum(gens.get(s - 2)); //elem = (RingElem)gens.get(s-1).multiply(gens.get(s-2)); elem = (RingElem) elem.multiply(elem); } //System.out.println("elem = " + elem.toScript()); //System.out.println("elem = " + elem); RingElem inv = (RingElem) elem.inverse(); //System.out.println("inv = " + inv.toScript()); //System.out.println("inv = " + inv); RingElem a = (RingElem) elem.multiply(inv); //System.out.println("a = " + a); assertTrue("e / e == 1 " + a, a.isONE()); } /** * Test construction Q(+3rt(3))(+sqrt(+3rt(3)))(+5rt(2))[y] by extension * field builder and real root calculation. */ public void testConstructionR2factory() { RingFactory fac = ExtensionFieldBuilder.baseField(new BigRational(1)) .realAlgebraicExtension("q", "q^3 - 3", "[1,2]") .realAlgebraicExtension("w", "w^2 - q", "[1,2]") .realAlgebraicExtension("s", "s^5 - 2", "[1,2]").build(); //System.out.println("fac = " + fac.toScript()); List gens = fac.generators(); int s = gens.size(); //System.out.println("gens = " + gens); assertTrue("#gens == 4 " + s, s == 4); GenPolynomialRing pfac = new GenPolynomialRing(fac, new String[] { "y" }); GenPolynomial elem = pfac.parse("y^2 - w s"); //elem = (RingElem)elem.negate(); //System.out.println("elem = " + elem.toScript()); //System.out.println("elem = " + elem); List> roots = RootFactory .realAlgebraicNumbers((GenPolynomial) elem); //System.out.println("roots = " + roots); assertTrue("#roots == 2 " + roots, roots.size() == 2); for (RealAlgebraicNumber root : roots) { //BigDecimal id = new BigDecimal(root.getRational()); //System.out.println("root = " + root); //System.out.println(" ~ " + id); RealAlgebraicNumber inv = root.inverse(); //System.out.println("inv = " + inv); //BigDecimal ivd = new BigDecimal(inv.getRational()); //System.out.println(" ~ " + ivd); RealAlgebraicNumber a = root.multiply(inv); //System.out.println("a = " + a); //System.out.println(" ~ " + id.multiply(ivd)); assertTrue("y / y == 1 " + a, a.isONE()); } } /** * Test construction by extension field builder and multiple algebraic * extension. */ public void testConstructionM1() { RingFactory fac = ExtensionFieldBuilder.baseField(new BigRational(1)) .algebraicExtension("q,w,s", "( q^3 - 3, w^2 - q, s^5 - 2)").build(); //System.out.println("fac = " + fac.toScript()); List gens = fac.generators(); int s = gens.size(); //System.out.println("gens = " + gens); assertTrue("#gens == 4 " + s, s == 4); GenPolynomialRing pfac = (GenPolynomialRing) ExtensionFieldBuilder.baseField(fac) .polynomialExtension("y").build(); GenPolynomial elem = pfac.parse("y^2 - w s"); //System.out.println("elem = " + elem.toScript()); //System.out.println("elem = " + elem); RingElem r = elem.trailingBaseCoefficient(); RingElem t = (RingElem) r.inverse(); RingElem u = (RingElem) r.multiply(t); //System.out.println("r = " + r); //System.out.println("t = " + t); //System.out.println("r*t = " + u); assertTrue("r*t == 1: ", u.isONE()); elem = elem.multiply(elem.negate()); //System.out.println("elem = " + elem); elem = Power.positivePower(elem, 3); //System.out.println("elem = " + elem); assertFalse("elem == 0 " + elem, elem.isZERO()); } /** * Test construction by extension field builder and multiple transcendent * extension. */ public void testConstructionM2() { RingFactory fac = ExtensionFieldBuilder.baseField(new BigRational(1)).algebraicExtension("q,w,s", "") .build(); //System.out.println("fac = " + fac.toScript()); List gens = fac.generators(); int s = gens.size(); //System.out.println("gens = " + gens); assertTrue("#gens == 4 " + s, s == 4); GenPolynomialRing pfac = (GenPolynomialRing) ExtensionFieldBuilder.baseField(fac) .polynomialExtension("y").build(); GenPolynomial elem = pfac.parse("y^2 - w s"); //System.out.println("elem = " + elem.toScript()); //System.out.println("elem = " + elem); RingElem r = elem.trailingBaseCoefficient(); RingElem t = (RingElem) r.inverse(); RingElem u = (RingElem) r.multiply(t); //System.out.println("r = " + r); //System.out.println("t = " + t); //System.out.println("r*t = " + u); assertTrue("r*t == 1: ", u.isONE()); elem = elem.multiply(elem.negate()); //System.out.println("elem = " + elem); elem = Power.positivePower(elem, 3); //System.out.println("elem = " + elem); assertFalse("elem == 0 " + elem, elem.isZERO()); } } jas-2.5/trc/edu/jas/gb/0000755000175000017500000000000012140140260015043 5ustar giovannigiovannijas-2.5/trc/edu/jas/gb/GroebnerBaseDistHybridTest.java0000644000175000017500000003046312002611634023105 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistHybridTest.java 4010 2012-07-21 20:39:56Z kredel $ */ package edu.jas.gb; //import edu.jas.poly.GroebnerBase; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.kern.ComputerThreads; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingElem; /** * Distributed hybrid architecture GroebnerBase tests with JUnit. * @author Heinz Kredel */ public class GroebnerBaseDistHybridTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBaseDistHybridTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); //ComputerThreads.terminate(); } /** * Constructs a GroebnerBaseDistHybridTest object. * @param name String. */ public GroebnerBaseDistHybridTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBaseDistHybridTest.class); return suite; } int port = 4711; String host = "localhost"; GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bbseq; GroebnerBaseDistributedHybrid bbdisthybs; GroebnerBaseDistributedHybrid bbdisthyb; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 4; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads = 2; int threadsPerNode = 2; @Override protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bbseq = new GroebnerBaseSeq(); bbdisthybs = null; //new GroebnerBaseDistributed(threads, port); bbdisthyb = null; //new GroebnerBaseDistributedHybrid(threads, threadsPerNode, port); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bbseq = null; bbdisthybs.terminate(); bbdisthybs = null; bbdisthyb.terminate(); bbdisthyb = null; ComputerThreads.terminate(); } /** * Helper method to start threads with distributed clients. * */ Thread[] startThreads() { Thread[] clients = new Thread[threads]; for (int t = 0; t < threads; t++) { clients[t] = new Thread(new JunitClientHybrid(threadsPerNode, host, port)); clients[t].start(); } return clients; } /** * Helper method to stop threads with distributed clients. * */ void stopThreads(Thread[] clients) { for (int t = 0; t < threads; t++) { try { while ( clients[t].isAlive() ) { clients[t].interrupt(); clients[t].join(100); } } catch (InterruptedException e) { } } } /** * Test distributed hybrid GBase. * */ public void testDistributedHybridGBase() { bbdisthybs = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, port); bbdisthyb = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, new OrderedSyzPairlist(), port); Thread[] clients; L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); clients = startThreads(); L = bbdisthyb.GB(L); stopThreads(clients); assertTrue("isGB( { a } )", bbseq.isGB(L)); //System.out.println("L = " + L.size() ); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); //System.out.println("L = " + L.size() ); clients = startThreads(); L = bbdisthyb.GB(L); stopThreads(clients); assertTrue("isGB( { a, b } )", bbseq.isGB(L)); //System.out.println("L = " + L.size() ); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); clients = startThreads(); L = bbdisthyb.GB(L); stopThreads(clients); assertTrue("isGB( { a, b, c } )", bbseq.isGB(L)); //System.out.println("L = " + L.size() ); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); clients = startThreads(); L = bbdisthyb.GB(L); stopThreads(clients); assertTrue("isGB( { a, b, c, d } )", bbseq.isGB(L)); //System.out.println("L = " + L.size() ); assertTrue("not isZERO( e )", !e.isZERO()); L.add(e); clients = startThreads(); L = bbdisthyb.GB(L); stopThreads(clients); assertTrue("isGB( { a, b, c, d, e } )", bbseq.isGB(L)); //System.out.println("L = " + L.size() ); } /** * Test Trinks7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7GBase() { bbdisthybs = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, port); bbdisthyb = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, new OrderedSyzPairlist(), port); Thread[] clients; String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); clients = startThreads(); G = bbdisthyb.GB(F.list); stopThreads(clients); assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); //PolynomialList trinks = new PolynomialList(F.ring, G); //System.out.println("G = " + trinks); } /** * Test Trinks7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7GBase_t1_p4() { //bbdisthyb.terminate(); threads = 1; threadsPerNode = 4; bbdisthybs = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, port); bbdisthyb = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, new OrderedSyzPairlist(), port); Thread[] clients; String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); clients = startThreads(); G = bbdisthyb.GB(F.list); stopThreads(clients); assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); //PolynomialList trinks = new PolynomialList(F.ring, G); //System.out.println("G = " + trinks); } /** * Test Trinks7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7GBase_t4_p1() { //bbdisthyb.terminate(); threads = 4; threadsPerNode = 1; bbdisthybs = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, port); bbdisthyb = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, new OrderedSyzPairlist(), port); Thread[] clients; String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); clients = startThreads(); G = bbdisthyb.GB(F.list); stopThreads(clients); assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); //PolynomialList trinks = new PolynomialList(F.ring, G); //System.out.println("G = " + trinks); } /** * Test Trinks7 GBase. * */ @SuppressWarnings("unchecked") public void testTrinks7GBase_t2_p2() { //bbdisthyb.terminate(); threads = 2; threadsPerNode = 4; bbdisthybs = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, port); bbdisthyb = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, new OrderedSyzPairlist(), port); Thread[] clients; String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + ") "; // + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); clients = startThreads(); G = bbdisthyb.GB(F.list); stopThreads(clients); assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); //PolynomialList trinks = new PolynomialList(F.ring, G); //System.out.println("G = " + trinks); } } /** * Unit Test client to be executed by test threads. */ class JunitClientHybrid> implements Runnable { private final int threadsPerNode; private final String host; private final int port; JunitClientHybrid(int threadsPerNode, String host, int port) { this.threadsPerNode = threadsPerNode; this.host = host; this.port = port; } public void run() { GroebnerBaseDistributedHybrid bbd; bbd = new GroebnerBaseDistributedHybrid(1, threadsPerNode, null, null, port); try { bbd.clientPart(host); } catch (IOException ignored) { } bbd.terminate(); } } jas-2.5/trc/edu/jas/gb/SolvableGroebnerBaseSeqPairParTest.java0000644000175000017500000001750511641660762024557 0ustar giovannigiovanni/* * $Id: SolvableGroebnerBaseSeqPairParTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.poly.RelationTable; import edu.jas.poly.TermOrder; import edu.jas.poly.WeylRelations; /** * SolvableGroebnerBase parallel tests with JUnit. * @author Heinz Kredel. */ public class SolvableGroebnerBaseSeqPairParTest extends TestCase { //private static final Logger logger = Logger.getLogger(SolvableGroebnerBaseSeqPairParTest.class); /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a SolvableGroebnerBaseSeqPairParTest object. * @param name String. */ public SolvableGroebnerBaseSeqPairParTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(SolvableGroebnerBaseSeqPairParTest.class); return suite; } int port = 4711; String host = "localhost"; GenSolvablePolynomial a; GenSolvablePolynomial b; GenSolvablePolynomial c; GenSolvablePolynomial d; GenSolvablePolynomial e; List> L; PolynomialList F; PolynomialList G; GenSolvablePolynomialRing ring; SolvableGroebnerBase psbb; BigRational cfac; TermOrder tord; RelationTable table; int rl = 4; //4; //3; int kl = 10; int ll = 4; int el = 2; float q = 0.3f; //0.4f protected void setUp() { cfac = new BigRational(9); tord = new TermOrder(); ring = new GenSolvablePolynomialRing(cfac,rl,tord); table = ring.table; a = b = c = d = e = null; psbb = new SolvableGroebnerBaseSeqPairParallel(); a = ring.random(kl, ll, el, q ); b = ring.random(kl, ll, el, q ); c = ring.random(kl, ll, el, q ); d = ring.random(kl, ll, el, q ); e = d; //ring.random(kl, ll, el, q ); } protected void tearDown() { a = b = c = d = e = null; ring = null; tord = null; table = null; cfac = null; ((SolvableGroebnerBaseSeqPairParallel)psbb).terminate(); psbb = null; } /** * Test parallel GBase. */ public void testParallelGBase() { assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d, e } )", psbb.isLeftGB(L) ); } /** * Test Weyl parallel GBase. * */ public void testWeylParallelGBase() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); table = ring.table; a = ring.random(kl, ll, el, q ); b = ring.random(kl, ll, el, q ); c = ring.random(kl, ll, el, q ); d = ring.random(kl, ll, el, q ); e = d; //ring.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d, e } )", psbb.isLeftGB(L) ); } /** * Test parallel twosided GBase. * */ public void testParallelTSGBase() { assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); L = psbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); L = psbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = psbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b, c } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = psbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b, c, d } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = psbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b, c, d, e } )", psbb.isTwosidedGB(L) ); } /** * Test Weyl parallel twosided GBase * is always 1. */ public void testWeylParallelTSGBase() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); table = ring.table; a = ring.random(kl, ll, el, q ); b = ring.random(kl, ll, el, q ); c = ring.random(kl, ll, el, q ); d = ring.random(kl, ll, el, q ); e = d; //ring.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); //System.out.println("La = " + L ); L = psbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); L = psbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = psbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b, c } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = psbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b, c, d } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = psbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b, c, d, e } )", psbb.isTwosidedGB(L) ); } } jas-2.5/trc/edu/jas/gb/WordReductionTest.java0000644000175000017500000002234212020640000021333 0ustar giovannigiovanni/* * $Id: WordReductionTest.java 4153 2012-09-02 11:16:16Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.ArrayList; import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.structure.RingFactory; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.BigComplex; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.poly.Word; import edu.jas.poly.WordFactory; import edu.jas.poly.OverlapList; import edu.jas.poly.Overlap; import edu.jas.poly.GenWordPolynomial; import edu.jas.poly.GenWordPolynomialRing; /** * Word reduction tests with JUnit. * @author Heinz Kredel. */ public class WordReductionTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a WordReductionTest object. * @param name String */ public WordReductionTest(String name) { super(name); } /** * suite. * @return a test suite. */ public static Test suite() { TestSuite suite= new TestSuite(WordReductionTest.class); return suite; } GenWordPolynomialRing fac; WordFactory wfac; BigRational cfac; GenWordPolynomial a; GenWordPolynomial b; GenWordPolynomial c; GenWordPolynomial d; GenWordPolynomial e; List> L; WordReductionSeq red; int kl = 3; int ll = 7; int el = 5; protected void setUp() { a = b = c = d = e = null; cfac = new BigRational(0); wfac = new WordFactory("abcdef"); fac = new GenWordPolynomialRing( cfac, wfac ); red = new WordReductionSeq(); } protected void tearDown() { a = b = c = d = e = null; fac = null; red = null; } /** * Test constants and empty list reduction. */ public void testRatReduction0() { L = new ArrayList>(); a = fac.random(kl, ll, el ); c = fac.getONE(); d = fac.getZERO(); e = red.normalform( L, c ); assertTrue("isONE( e )", e.isONE() ); e = red.normalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); L.add( c ); e = red.normalform( L, c ); assertTrue("isZERO( e )", e.isZERO() ); e = red.normalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); e = red.normalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); L = new ArrayList>(); L.add( d ); e = red.normalform( L, c ); assertTrue("isONE( e )", e.isONE() ); e = red.normalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); } /** * Test rational coefficient reduction. */ public void testRatReduction() { do { a = fac.random(kl, ll, el); } while ( a.isZERO() ); do { b = fac.random(kl, ll, el); } while ( b.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); L = new ArrayList>(); L.add(a); e = red.normalform( L, a ); //System.out.println("e = " + e); assertTrue("isZERO( e )", e.isZERO() ); L.add(b); e = red.normalform( L, a ); //System.out.println("e = " + e); assertTrue("isZERO( e ) some times", e.isZERO() ); L = new ArrayList>(); L.add( a ); assertTrue("isTopRed( a )", red.isTopReducible(L,a) ); assertTrue("isRed( a )", red.isReducible(L,a) ); L.add( b ); assertTrue("isTopRed( b )", red.isTopReducible(L,b) ); assertTrue("isRed( b )", red.isReducible(L,b) ); c = fac.random(kl, ll, el ); //System.out.println("c = " + c); e = red.normalform( L, c ); //System.out.println("e = " + e); assertTrue("isNF( e )", red.isNormalform(L,e) ); Word u = new Word(wfac,"f"); Word v = new Word(wfac,"abc"); c = a.multiply(cfac.getONE(),u,v); //System.out.println("c = " + c); e = red.normalform( L, c ); //System.out.println("e = " + e); assertTrue("isNF( e )", red.isNormalform(L,e) ); assertTrue("e == 0", e.isZERO() ); } /** * Test rational coefficient reduction with recording. */ public void testRatReductionRecording() { List> lrow, rrow = null; do { a = fac.random(kl, ll, el); } while ( a.isZERO() ); do { b = fac.random(kl, ll, el); } while ( b.isZERO() ); c = fac.random(kl, ll, el); d = fac.random(kl, ll, el); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); L = new ArrayList>(); L.add(a); lrow = new ArrayList>( L.size() ); rrow = new ArrayList>( L.size() ); e = fac.getZERO(); for ( int m = 0; m < L.size(); m++ ) { lrow.add(e); rrow.add(e); } e = red.normalform( lrow, rrow, L, a ); //System.out.println("e = " + e); //System.out.println("lrow = " + lrow); //System.out.println("rrow = " + rrow); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("is Reduction ", red.isReductionNF(lrow,rrow,L,a,e) ); L.add(b); lrow = new ArrayList>( L.size() ); rrow = new ArrayList>( L.size() ); e = fac.getZERO(); for ( int m = 0; m < L.size(); m++ ) { lrow.add(e); rrow.add(e); } e = red.normalform( lrow, rrow, L, b ); //System.out.println("e = " + e); //System.out.println("lrow = " + lrow); //System.out.println("rrow = " + rrow); assertTrue("is Reduction ", red.isReductionNF(lrow,rrow,L,b,e) ); L.add(c); lrow = new ArrayList>( L.size() ); rrow = new ArrayList>( L.size() ); e = fac.getZERO(); for ( int m = 0; m < L.size(); m++ ) { lrow.add(e); rrow.add(e); } e = red.normalform( lrow, rrow, L, c ); //System.out.println("e = " + e); //System.out.println("lrow = " + lrow); //System.out.println("rrow = " + rrow); assertTrue("is Reduction ", red.isReductionNF(lrow,rrow,L,c,e) ); L.add(d); lrow = new ArrayList>( L.size() ); rrow = new ArrayList>( L.size() ); e = fac.getZERO(); for ( int m = 0; m < L.size(); m++ ) { lrow.add(e); rrow.add(e); } Word u = new Word(wfac,"f"); Word v = new Word(wfac,"abc"); d = a.multiply(cfac.random(3),u,v); //System.out.println("d = " + d); e = red.normalform(lrow, rrow, L, d ); //System.out.println("e = " + e); //System.out.println("lrow = " + lrow); //System.out.println("rrow = " + rrow); assertTrue("is Reduction ", red.isReductionNF(lrow,rrow,L,d,e) ); } /** * Test rational S-polynomial. */ public void testRatSpolynomial() { do { a = fac.random(kl, ll, el); } while ( a.isZERO() ); do { b = fac.random(kl, ll, el); } while ( b.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); Word de = new Word(wfac,"a"); a = a.multiply(wfac.getONE(),de); b = b.multiply(de,wfac.getONE()); //System.out.println("a = " + a); //System.out.println("b = " + b); Word ae = a.leadingWord(); Word be = b.leadingWord(); //System.out.println("ae = " + ae); //System.out.println("be = " + be); List> S = red.SPolynomials( a, b ); //System.out.println("S = " + S); OverlapList oll = ae.overlap(be); //System.out.println("oll = " + oll); for ( GenWordPolynomial s : S ) { //System.out.println("s = " + s); Word ee = s.leadingWord(); //System.out.println("ee = " + ee); boolean t = false; Word ce = fac.alphabet.getONE(); for ( Overlap ol : oll.ols ) { ce = ol.l1.multiply(ae).multiply(ol.r1); //System.out.println("ce = " + ce); if (fac.alphabet.getAscendComparator().compare(ce,ee) > 0) { t = true; break; } } assertTrue("ce > ee: " + ce + " > " + ee, t); // findbugs } } } jas-2.5/trc/edu/jas/gb/ReductionTest.java0000644000175000017500000003704312002766222020522 0ustar giovannigiovanni/* * $Id: ReductionTest.java 4015 2012-07-22 12:05:38Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.ArrayList; import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.structure.RingFactory; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.BigComplex; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolynomialList; /** * Reduction tests with JUnit. * @author Heinz Kredel. */ public class ReductionTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ReductionTest object. * @param name String */ public ReductionTest(String name) { super(name); } /** * suite. * @return a test suite. */ public static Test suite() { TestSuite suite= new TestSuite(ReductionTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing fac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; List> L; PolynomialList F; PolynomialList G; ReductionSeq red; Reduction redpar; int rl = 4; int kl = 10; int ll = 11; int el = 5; float q = 0.6f; protected void setUp() { a = b = c = d = e = null; fac = new GenPolynomialRing( new BigRational(0), rl ); red = new ReductionSeq(); redpar = new ReductionPar(); } protected void tearDown() { a = b = c = d = e = null; fac = null; red = null; redpar = null; } /** * Test constants and empty list reduction. */ public void testRatReduction0() { L = new ArrayList>(); a = fac.random(kl, ll, el, q ); c = fac.getONE(); d = fac.getZERO(); e = red.normalform( L, c ); assertTrue("isONE( e )", e.isONE() ); e = red.normalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); L.add( c ); e = red.normalform( L, c ); assertTrue("isZERO( e )", e.isZERO() ); e = red.normalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); e = red.normalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); L = new ArrayList>(); L.add( d ); e = red.normalform( L, c ); assertTrue("isONE( e )", e.isONE() ); e = red.normalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); } /** * Test parallel reduction with constants and empty list reduction. */ public void testRatReductionPar0() { L = new ArrayList>(); a = fac.random(kl, ll, el, q ); c = fac.getONE(); d = fac.getZERO(); e = redpar.normalform( L, c ); assertTrue("isONE( e )", e.isONE() ); e = redpar.normalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); L.add( c ); e = redpar.normalform( L, c ); assertTrue("isZERO( e )", e.isZERO() ); e = redpar.normalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); e = redpar.normalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); L = new ArrayList>(); L.add( d ); e = redpar.normalform( L, c ); assertTrue("isONE( e )", e.isONE() ); e = redpar.normalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); } /** * Test rational coefficient reduction. * */ public void testRatReduction() { a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); e = red.normalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = red.normalform( L, a ); assertTrue("isZERO( e ) some times", e.isZERO() ); e = red.SPolynomial( a, b ); //System.out.println("e = " + e); ExpVector ce = a.leadingExpVector().lcm(b.leadingExpVector()); ExpVector ee = e.leadingExpVector(); assertTrue("lcm(lt(a),lt(b)) > lt(e) " + ce + " > " + ee, fac.tord.getAscendComparator().compare(ce,ee) > 0 ); // findbugs L = new ArrayList>(); L.add( a ); assertTrue("isTopRed( a )", red.isTopReducible(L,a) ); assertTrue("isRed( a )", red.isReducible(L,a) ); b = fac.random(kl, ll, el, q ); L.add( b ); assertTrue("isTopRed( b )", red.isTopReducible(L,b) ); assertTrue("isRed( b )", red.isReducible(L,b) ); c = fac.random(kl, ll, el, q ); e = red.normalform( L, c ); assertTrue("isNF( e )", red.isNormalform(L,e) ); } /** * Test rational coefficient parallel reduction. * */ public void testRatReductionPar() { a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); e = redpar.normalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = redpar.normalform( L, a ); assertTrue("isZERO( e ) some times", e.isZERO() ); L = new ArrayList>(); L.add( a ); assertTrue("isTopRed( a )", redpar.isTopReducible(L,a) ); assertTrue("isRed( a )", redpar.isReducible(L,a) ); b = fac.random(kl, ll, el, q ); L.add( b ); assertTrue("isTopRed( b )", redpar.isTopReducible(L,b) ); assertTrue("isRed( b )", redpar.isReducible(L,b) ); c = fac.random(kl, ll, el, q ); e = redpar.normalform( L, c ); assertTrue("isNF( e )", redpar.isNormalform(L,e) ); } /** * Test complex coefficient reduction. * */ public void testComplexReduction() { GenPolynomialRing fac = new GenPolynomialRing( new BigComplex(0), rl ); Reduction cred = new ReductionSeq(); GenPolynomial a = fac.random(kl, ll, el, q ); GenPolynomial b = fac.random(kl, ll, el, q ); GenPolynomial c; assertTrue("not isZERO( a )", !a.isZERO() ); List> L = new ArrayList>(); L.add(a); GenPolynomial e = cred.normalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = cred.normalform( L, a ); assertTrue("isZERO( e ) some times", e.isZERO() ); L = new ArrayList>(); L.add( a ); assertTrue("isTopRed( a )", cred.isTopReducible(L,a) ); assertTrue("isRed( a )", cred.isReducible(L,a) ); b = fac.random(kl, ll, el, q ); L.add( b ); assertTrue("isTopRed( b )", cred.isTopReducible(L,b) ); assertTrue("isRed( b )", cred.isReducible(L,b) ); c = fac.random(kl, ll, el, q ); e = cred.normalform( L, c ); assertTrue("isNF( e )", cred.isNormalform(L,e) ); } /** * Test rational coefficient reduction with recording. * */ public void testRatReductionRecording() { List> row = null; a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = red.normalform( row, L, a ); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); assertTrue("is Reduction ", red.isReductionNF(row,L,a,e) ); L.add(b); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = red.normalform( row, L, b ); assertTrue("is Reduction ", red.isReductionNF(row,L,b,e) ); L.add(c); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = red.normalform( row, L, c ); assertTrue("is Reduction ", red.isReductionNF(row,L,c,e) ); L.add(d); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = red.normalform( row, L, d ); assertTrue("is Reduction ", red.isReductionNF(row,L,d,e) ); } /** * Test integer coefficient e-reduction. * */ public void testIntegerEReduction() { BigInteger bi = new BigInteger(0); GenPolynomialRing fac = new GenPolynomialRing( bi, rl ); EReductionSeq ered = new EReductionSeq(); GenPolynomial a = fac.random(kl, ll, el, q ); GenPolynomial b = fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); List> L = new ArrayList>(); L.add(a); GenPolynomial e = ered.normalform( L, a ); //System.out.println("a = " + a); //System.out.println("e = " + e); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = ered.normalform( L, a ); //System.out.println("b = " + b); //System.out.println("e = " + e); assertTrue("isZERO( e ) some times", e.isZERO() ); GenPolynomial c = fac.getONE(); a = a.sum(c); e = ered.normalform( L, a ); //System.out.println("b = " + b); //System.out.println("e = " + e); assertTrue("isONE( e ) some times", e.isONE() ); L = new ArrayList>(); a = c.multiply( bi.fromInteger(4) ); b = c.multiply( bi.fromInteger(5) ); L.add( a ); e = ered.normalform( L, b ); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("e = " + e); assertTrue("isONE( e )", e.isONE() ); a = fac.random(kl, ll, el, q ); //.abs(); b = fac.random(kl, ll, el, q ); //.abs(); c = ered.GPolynomial( a, b ); e = ered.SPolynomial( a, b ); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("e = " + e); BigInteger ci = a.leadingBaseCoefficient().gcd( b.leadingBaseCoefficient() ); assertEquals("gcd(lbc(a),lbc(b)) = lbc(c) ", ci, c.leadingBaseCoefficient() ); ExpVector ce = a.leadingExpVector().lcm(b.leadingExpVector()); assertEquals("lcm(lt(a),lt(b)) == lt(c) ", ce, c.leadingExpVector() ); assertFalse("lcm(lt(a),lt(b)) != lt(e) ", ce.equals( e.leadingExpVector() ) ); L = new ArrayList>(); L.add( a ); assertTrue("isTopRed( a )", ered.isTopReducible(L,a) ); assertTrue("isRed( a )", ered.isReducible(L,a) ); b = fac.random(kl, ll, el, q ); L.add( b ); assertTrue("isTopRed( b )", ered.isTopReducible(L,b) ); assertTrue("isRed( b )", ered.isReducible(L,b) ); c = fac.random(kl, ll, el, q ); e = ered.normalform( L, c ); assertTrue("isNF( e )", ered.isNormalform(L,e) ); } /** * Test integer coefficient d-reduction. * */ public void testIntegerDReduction() { BigInteger bi = new BigInteger(0); GenPolynomialRing fac = new GenPolynomialRing( bi, rl ); DReductionSeq dred = new DReductionSeq(); GenPolynomial a = fac.random(kl, ll, el, q ); GenPolynomial b = fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); List> L = new ArrayList>(); L.add(a); GenPolynomial e = dred.normalform( L, a ); //System.out.println("a = " + a); //System.out.println("e = " + e); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = dred.normalform( L, a ); //System.out.println("b = " + b); //System.out.println("e = " + e); assertTrue("isZERO( e ) some times", e.isZERO() ); GenPolynomial c = fac.getONE(); a = a.sum(c); e = dred.normalform( L, a ); //System.out.println("b = " + b); //System.out.println("e = " + e); assertTrue("isONE( e ) some times", e.isONE() ); L = new ArrayList>(); a = c.multiply( bi.fromInteger(5) ); L.add( a ); b = c.multiply( bi.fromInteger(4) ); e = dred.normalform( L, b ); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("e = " + e); assertTrue("nf(b) = b ", e.equals(b) ); a = fac.random(kl, ll, el, q ); //.abs(); b = fac.random(kl, ll, el, q ); //.abs(); c = dred.GPolynomial( a, b ); e = dred.SPolynomial( a, b ); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("e = " + e); BigInteger ci = a.leadingBaseCoefficient().gcd( b.leadingBaseCoefficient() ); assertEquals("gcd(lbc(a),lbc(b)) = lbc(c) ", ci, c.leadingBaseCoefficient() ); ExpVector ce = a.leadingExpVector().lcm(b.leadingExpVector()); assertEquals("lcm(lt(a),lt(b)) == lt(c) ", ce, c.leadingExpVector() ); assertFalse("lcm(lt(a),lt(b)) != lt(e) ", ce.equals( e.leadingExpVector() ) ); L = new ArrayList>(); L.add( a ); assertTrue("isTopRed( a )", dred.isTopReducible(L,a) ); assertTrue("isRed( a )", dred.isReducible(L,a) ); b = fac.random(kl, ll, el, q ); L.add( b ); assertTrue("isTopRed( b )", dred.isTopReducible(L,b) ); assertTrue("isRed( b )", dred.isReducible(L,b) ); c = fac.random(kl, ll, el, q ); e = dred.normalform( L, c ); assertTrue("isNF( e )", dred.isNormalform(L,e) ); } } jas-2.5/trc/edu/jas/gb/GroebnerBaseParSyzPairTest.java0000644000175000017500000002251112002766222023103 0ustar giovannigiovanni/* * $Id: GroebnerBaseParSyzPairTest.java 4015 2012-07-22 12:05:38Z kredel $ */ package edu.jas.gb; //import edu.jas.poly.GroebnerBase; import java.util.List; import java.util.ArrayList; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBase; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base parallel, syzygy pair list, tests with JUnit. * @author Heinz Kredel. */ public class GroebnerBaseParSyzPairTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBaseParSyzPairTest.class); /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a GroebnerBaseParSyzPairTest object. * @param name String. */ public GroebnerBaseParSyzPairTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(GroebnerBaseParSyzPairTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBaseAbstract bbseq; GroebnerBaseAbstract bbpar; GroebnerBaseAbstract bbspar; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 10; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads = 2; protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff,rl); a = b = c = d = e = null; bbseq = new GroebnerBaseSeq(); bbpar = new GroebnerBaseParallel(threads); bbspar = new GroebnerBaseParallel(threads, new ReductionPar(), new OrderedSyzPairlist()); } protected void tearDown() { a = b = c = d = e = null; fac = null; bbseq = null; bbpar.terminate(); bbpar = null; bbspar.terminate(); bbspar = null; } /** * Test syzygy pair parallel GBase. * */ public void testSyzPairParallelGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); L = bbspar.GB( L ); assertTrue("isGB( { a } )", bbspar.isGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = bbspar.GB( L ); assertTrue("isGB( { a, b } )", bbspar.isGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = bbspar.GB( L ); assertTrue("isGB( { a, b, c } )", bbspar.isGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = bbspar.GB( L ); assertTrue("isGB( { a, b, c, d } )", bbspar.isGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = bbspar.GB( L ); assertTrue("isGB( { a, b, c, d, e } )", bbspar.isGB(L) ); } /** * Test compare sequential with syzygy pair parallel GBase. * */ public void testSequentialSyzPairParallelGBase() { List> Gs, Gp; L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } L.add(a); Gs = bbseq.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(b); Gs = bbseq.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(c); Gs = bbseq.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(d); Gs = bbseq.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(e); Gs = bbseq.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); } /** * Test compare parallel with syzygy pair parallel GBase. * */ public void testParallelSyzPairParallelGBase() { List> Gs, Gp; L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } L.add(a); Gs = bbpar.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp) " + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs) " + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(b); Gs = bbpar.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp) " + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs) " + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(c); Gs = bbpar.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp) " + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs) " + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(d); Gs = bbpar.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp) " + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs) " + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(e); Gs = bbpar.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp) " + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs) " + Gs + ", " + Gp, Gp.containsAll(Gs) ); } /** * Test Trinks7 GBase. * */ public void testTrinks7GBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ) " + ", ( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); long t; /* t = System.currentTimeMillis(); G = bbseq.GB( F.list ); t = System.currentTimeMillis() - t; System.out.println("bbseq ms = " + t); t = System.currentTimeMillis(); G = bbpar.GB( F.list ); t = System.currentTimeMillis() - t; System.out.println("bbpar ms = " + t); */ t = System.currentTimeMillis(); G = bbspar.GB( F.list ); t = System.currentTimeMillis() - t; //System.out.println("bbspar ms = " + t); assertTrue("nonsense ", t >= 0L); assertTrue("isGB( GB(Trinks7) )", bbspar.isGB(G) ); assertEquals("#GB(Trinks7) == 6", 6, G.size() ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } } jas-2.5/trc/edu/jas/gb/PairListTest.java0000644000175000017500000001165511641660762020330 0ustar giovannigiovanni/* * $Id: PairListTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.ArrayList; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBase; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class PairListTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a PairListTest object. * @param name String. */ public PairListTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(PairListTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; PairList pairlist; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 4; //4; //3; int kl = 5; int ll = 2; int el = 4; float q = 0.3f; //0.4f protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff,rl); a = b = c = d = e = null; } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test and compare random OrderedPairlist and CriticalPairList. */ public void testRandomPL() { pairlist = new OrderedPairlist(fac); //System.out.println("pairlist = " + pairlist); CriticalPairList cpl = new CriticalPairList(fac); //System.out.println("cpl = " + cpl); L = new ArrayList>(); for ( int i = 0; i < 7; i++ ) { a = fac.random(kl, ll, el, q ); if ( a.isZERO() ) { continue; } pairlist.put(a); cpl.put(a); } //System.out.println("pairlist = " + pairlist); //System.out.println("cpl = " + cpl); while ( pairlist.hasNext() && cpl.hasNext() ) { Pair pair = pairlist.removeNext(); //System.out.println("pair = " + pair); CriticalPair cpair = cpl.getNext(); //System.out.println("cpair = " + cpair); if ( cpair != null ) { cpl.update(cpair,fac.getZERO()); } else { cpl.update(); } if ( pair != null && cpair != null ) { boolean t = (pair.i == cpair.i) && (pair.j == cpair.j); assertTrue("pair == cpair ", t); } } //System.out.println("pairlist = " + pairlist); //System.out.println("cpl = " + cpl); boolean t = pairlist.hasNext() || cpl.hasNext(); assertFalse("#pairlist == #cpl ", t); } /** * Test and compare random OrderedPairlist and OrderedSyzPairlist. */ public void testRandomSyzPL() { pairlist = new OrderedPairlist(fac); //System.out.println("pairlist = " + pairlist); OrderedSyzPairlist spl = new OrderedSyzPairlist(fac); //System.out.println("spl = " + spl); L = new ArrayList>(); for ( int i = 0; i < 7; i++ ) { a = fac.random(kl, ll, el, q ); if ( a.isZERO() ) { continue; } pairlist.put(a); spl.put(a); } //System.out.println("pairlist = " + pairlist); //System.out.println("spl = " + spl); while ( pairlist.hasNext() && spl.hasNext() ) { Pair pair = pairlist.removeNext(); //System.out.println("pair = " + pair); Pair spair = spl.removeNext(); //System.out.println("spair = " + spair); if ( pair != null && spair != null ) { boolean t = (pair.i == spair.i) && (pair.j == spair.j); //not always true: assertTrue("pair == spair " + pair + ", " + spair, t); } } //System.out.println("pairlist = " + pairlist); //System.out.println("spl = " + spl); boolean t = pairlist.hasNext() && spl.hasNext(); assertFalse("#pairlist == #spl ", t); } } jas-2.5/trc/edu/jas/gb/GroebnerBaseDistECTest.java0000644000175000017500000001716212136513316022162 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistECTest.java 4376 2013-04-26 15:01:34Z kredel $ */ package edu.jas.gb; //import edu.jas.poly.GroebnerBase; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.kern.ComputerThreads; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingElem; import edu.jas.util.ExecutableServer; /** * Distributed GroebnerBase tests with JUnit. * @author Heinz Kredel */ public class GroebnerBaseDistECTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBaseDistECTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); //ComputerThreads.terminate(); } /** * Constructs a GroebnerBaseDistECTest object. * @param name String. */ public GroebnerBaseDistECTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBaseDistECTest.class); return suite; } int port = 55711; String host = "localhost"; String mfile = "examples/machines.localhost"; // contains localhost GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bbseq; GroebnerBaseAbstract bbdist; GroebnerBaseAbstract bbdists; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 4; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads = 2; ExecutableServer es1; ExecutableServer es2; @Override protected void setUp() { es1 = new ExecutableServer(4712); // == machines.localhost:4712 es1.init(); es2 = new ExecutableServer(4711); // == machines.localhost:4711 es2.init(); //System.out.println("es1 = " + es1); //System.out.println("es2 = " + es2); BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bbseq = new GroebnerBaseSeq(); bbdist = new GroebnerBaseDistributedEC(mfile, threads, port); //bbdists = new GroebnerBaseDistributedEC(mfile, threads, new OrderedSyzPairlist(), port); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bbseq = null; bbdist.terminate(); bbdist = null; //bbdists.terminate(); //bbdists = null; es1.terminate(); es2.terminate(); es1 = null; es2 = null; ComputerThreads.terminate(); } /** * Test distributed GBase. */ public void testDistributedGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); L.add(a); L = bbdist.GB(L); assertTrue("isGB( { a } ): " + L, bbseq.isGB(L)); L.add(b); //System.out.println("L = " + L.size() ); L = bbdist.GB(L); assertTrue("isGB( { a, b } ): " + L, bbseq.isGB(L)); L.add(c); L = bbdist.GB(L); assertTrue("isGB( { a, b, c } ): " + L, bbseq.isGB(L)); L.add(d); L = bbdist.GB(L); assertTrue("isGB( { a, b, c, d } ): " + L, bbseq.isGB(L)); L.add(e); L = bbdist.GB(L); assertTrue("isGB( { a, b, c, d, e } ): " + L, bbseq.isGB(L)); } /** * Test compare sequential with distributed GBase. */ public void testSequentialDistributedGBase() { List> Gs, Gp = null; L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); L.add(a); Gs = bbseq.GB(L); Gp = bbdist.GB(L); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(b); Gs = bbseq.GB(L); Gp = bbdist.GB(L); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(c); Gs = bbseq.GB(L); Gp = bbdist.GB(L); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(d); Gs = bbseq.GB(L); Gp = bbdist.GB(L); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(e); Gs = bbseq.GB(L); Gp = bbdist.GB(L); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); } /** * Test Trinks7 GBase. */ public void testTrinks7GBase() { List> Gs, Gp = null; String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; //exam = "(x3,x4,x5) L " + // "( (x3^2 - 13974703710478159/3775194259200) , (x4 - 34297/840), (x5^2 - 6389/480), (-4/3 x5^2 + x3^2 + x3 - 833/180) ) "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); Gp = bbdist.GB(F.list); //System.out.println("Gp = " + Gp); Gs = bbseq.GB(F.list); //System.out.println("Gs = " + Gs); assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(Gp)); assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(Gs)); //assertEquals("#GB(Trinks7) == 6", 6, G.size()); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + F, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + F, Gp.containsAll(Gs)); //PolynomialList trinks = new PolynomialList(F.ring, Gp); //System.out.println("G = " + trinks); } } jas-2.5/trc/edu/jas/gb/SolvableGroebnerBaseSeqTest.java0000644000175000017500000003131411641660762023272 0ustar giovannigiovanni/* * $Id: SolvableGroebnerBaseSeqTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.poly.RelationTable; import edu.jas.poly.TermOrder; import edu.jas.poly.WeylRelations; /** * Solvable Groebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class SolvableGroebnerBaseSeqTest extends TestCase { //private static final Logger logger = Logger.getLogger(SolvableGroebnerBaseSeqTest.class); /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a SolvableGroebnerBaseSeqTest object. * @param name String. */ public SolvableGroebnerBaseSeqTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(SolvableGroebnerBaseSeqTest.class); return suite; } int port = 4711; String host = "localhost"; GenSolvablePolynomial a; GenSolvablePolynomial b; GenSolvablePolynomial c; GenSolvablePolynomial d; GenSolvablePolynomial e; List> L; PolynomialList F; PolynomialList G; GenSolvablePolynomialRing ring; SolvableGroebnerBase sbb; BigRational cfac; TermOrder tord; RelationTable table; int rl = 4; //4; //3; int kl = 10; int ll = 4; int el = 2; float q = 0.3f; //0.4f protected void setUp() { cfac = new BigRational(9); tord = new TermOrder(); ring = new GenSolvablePolynomialRing(cfac,rl,tord); table = ring.table; a = b = c = d = e = null; sbb = new SolvableGroebnerBaseSeq(); a = ring.random(kl, ll, el, q ); b = ring.random(kl, ll, el, q ); c = ring.random(kl, ll, el, q ); d = ring.random(kl, ll, el, q ); e = d; //ring.random(kl, ll, el, q ); } protected void tearDown() { a = b = c = d = e = null; ring = null; tord = null; table = null; cfac = null; sbb = null; } /** * Test sequential GBase. */ public void testSequentialGBase() { if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); L = sbb.leftGB( L ); assertTrue("isLeftGB( { a } )", sbb.isLeftGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = sbb.leftGB( L ); assertTrue("isLeftGB( { a, b } )", sbb.isLeftGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = sbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c } )", sbb.isLeftGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = sbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d } )", sbb.isLeftGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = sbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d, e } )", sbb.isLeftGB(L) ); } /** * Test Weyl sequential GBase. * */ public void testWeylSequentialGBase() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); table = ring.table; a = ring.random(kl, ll, el, q ); b = ring.random(kl, ll, el, q ); c = ring.random(kl, ll, el, q ); d = ring.random(kl, ll, el, q ); e = d; //ring.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); L = sbb.leftGB( L ); assertTrue("isLeftGB( { a } )", sbb.isLeftGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = sbb.leftGB( L ); assertTrue("isLeftGB( { a, b } )", sbb.isLeftGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = sbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c } )", sbb.isLeftGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = sbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d } )", sbb.isLeftGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = sbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d, e } )", sbb.isLeftGB(L) ); } /** * Test sequential twosided GBase. * */ public void testSequentialTSGBase() { if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); L = sbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a } )", sbb.isTwosidedGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); L = sbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b } )", sbb.isTwosidedGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = sbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b, c } )", sbb.isTwosidedGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = sbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b, c, d } )", sbb.isTwosidedGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = sbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b, c, d, e } )", sbb.isTwosidedGB(L) ); } /** * Test Weyl sequential twosided GBase * is always 1. */ public void testWeylSequentialTSGBase() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); table = ring.table; a = ring.random(kl, ll, el, q ); b = ring.random(kl, ll, el, q ); c = ring.random(kl, ll, el, q ); d = ring.random(kl, ll, el, q ); e = d; //ring.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); //System.out.println("La = " + L ); L = sbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a } )", sbb.isTwosidedGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); L = sbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b } )", sbb.isTwosidedGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = sbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b, c } )", sbb.isTwosidedGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = sbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b, c, d } )", sbb.isTwosidedGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = sbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b, c, d, e } )", sbb.isTwosidedGB(L) ); } /** * Test sequential extended GBase. * */ public void testSequentialExtendedGBase() { L = new ArrayList>(); SolvableExtendedGB exgb; if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); //System.out.println("L = " + L ); exgb = sbb.extLeftGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isLeftGB( { a } )", sbb.isLeftGB(exgb.G) ); assertTrue("isLeftRmat( { a } )", sbb.isLeftReductionMatrix(exgb) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L ); exgb = sbb.extLeftGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isLeftGB( { a, b } )", sbb.isLeftGB(exgb.G) ); assertTrue("isLeftRmat( { a, b } )", sbb.isLeftReductionMatrix(exgb) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); exgb = sbb.extLeftGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isLeftGB( { a, b, c } )", sbb.isLeftGB(exgb.G) ); assertTrue("isLeftRmat( { a, b, c } )", sbb.isLeftReductionMatrix(exgb) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); exgb = sbb.extLeftGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isLeftGB( { a, b, c, d } )", sbb.isLeftGB(exgb.G) ); assertTrue("isLeftRmat( { a, b, c, d } )", sbb.isLeftReductionMatrix(exgb) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); exgb = sbb.extLeftGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isLeftGB( { a, b, c, d, e } )", sbb.isLeftGB(exgb.G) ); assertTrue("isLeftRmat( { a, b, c, d, e } )", sbb.isLeftReductionMatrix(exgb) ); } /** * Test Weyl sequential extended GBase. * */ public void testWeylSequentialExtendedGBase() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); table = ring.table; a = ring.random(kl, ll, el, q ); b = ring.random(kl, ll, el, q ); c = ring.random(kl, ll, el, q ); d = ring.random(kl, ll, el, q ); e = d; //ring.random(kl, ll, el, q ); SolvableExtendedGB exgb; assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); exgb = sbb.extLeftGB( L ); // System.out.println("exgb = " + exgb ); assertTrue("isLeftGB( { a } )", sbb.isLeftGB(exgb.G) ); assertTrue("isRmat( { a } )", sbb.isLeftReductionMatrix(exgb) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); exgb = sbb.extLeftGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isLeftGB( { a, b } )", sbb.isLeftGB(exgb.G) ); assertTrue("isRmat( { a, b } )", sbb.isLeftReductionMatrix(exgb) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); exgb = sbb.extLeftGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isLeftGB( { a, b, c } )", sbb.isLeftGB(exgb.G) ); assertTrue("isRmat( { a, b, c } )", sbb.isLeftReductionMatrix(exgb) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); exgb = sbb.extLeftGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isLeftGB( { a, b, c, d } )", sbb.isLeftGB(exgb.G) ); assertTrue("isRmat( { a, b, c, d } )", sbb.isLeftReductionMatrix(exgb) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); exgb = sbb.extLeftGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isLeftGB( { a, b, c, d, e } )", sbb.isLeftGB(exgb.G) ); assertTrue("isRmat( { a, b, c, d, e } )", sbb.isLeftReductionMatrix(exgb) ); } } jas-2.5/trc/edu/jas/gb/GroebnerBaseParTest.java0000644000175000017500000001430112002611634021553 0ustar giovannigiovanni/* * $Id: GroebnerBaseParTest.java 4010 2012-07-21 20:39:56Z kredel $ */ package edu.jas.gb; //import edu.jas.poly.GroebnerBase; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * GroebnerBase parallel tests with JUnit. * @author Heinz Kredel. */ public class GroebnerBaseParTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBaseParTest.class); /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a GroebnerBaseParTest object. * @param name String. */ public GroebnerBaseParTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(GroebnerBaseParTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bbseq; GroebnerBase bbpar; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 10; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads = 2; protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff,rl); a = b = c = d = e = null; bbseq = new GroebnerBaseSeq(); bbpar = new GroebnerBaseParallel(threads); } protected void tearDown() { a = b = c = d = e = null; fac = null; bbseq = null; ((GroebnerBaseParallel)bbpar).terminate(); bbpar = null; } /** * Test parallel GBase. * */ public void testParallelGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); L = bbpar.GB( L ); assertTrue("isGB( { a } )", bbpar.isGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = bbpar.GB( L ); assertTrue("isGB( { a, b } )", bbpar.isGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = bbpar.GB( L ); assertTrue("isGB( { a, b, c } )", bbpar.isGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = bbpar.GB( L ); assertTrue("isGB( { a, b, c, d } )", bbpar.isGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = bbpar.GB( L ); assertTrue("isGB( { a, b, c, d, e } )", bbpar.isGB(L) ); } /** * Test compare sequential with parallel GBase. * */ public void testSequentialParallelGBase() { List> Gs, Gp; L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } L.add(a); Gs = bbseq.GB( L ); Gp = bbpar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(b); Gs = bbseq.GB( L ); Gp = bbpar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(c); Gs = bbseq.GB( L ); Gp = bbpar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(d); Gs = bbseq.GB( L ); Gp = bbpar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(e); Gs = bbseq.GB( L ); Gp = bbpar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); } /** * Test Trinks7 GBase. * */ public void testTrinks7GBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); G = bbpar.GB( F.list ); assertTrue("isGB( GB(Trinks7) )", bbpar.isGB(G) ); assertEquals("#GB(Trinks7) == 6", 6, G.size() ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } } jas-2.5/trc/edu/jas/gb/EGroebnerBaseSeqTest.java0000644000175000017500000001635312004571452021704 0ustar giovannigiovanni/* * $Id: EGroebnerBaseSeqTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolyUtil; import edu.jas.poly.PolynomialList; /** * EGroebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class EGroebnerBaseSeqTest extends TestCase { //private static final Logger logger = Logger.getLogger(EGroebnerBaseSeqTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a EGroebnerBaseSeqTest object. * @param name String. */ public EGroebnerBaseSeqTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(EGroebnerBaseSeqTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bb; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 4; //4; 10 int ll = 4; int el = 3; float q = 0.2f; //0.4f @Override protected void setUp() { BigInteger coeff = new BigInteger(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bb = new EGroebnerBaseSeq(); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; } /** * Test sequential GBase. * */ public void testSequentialGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q).abs(); b = fac.random(kl, ll, el, q).abs(); c = fac.random(kl, ll / 2, el, q).abs(); d = fac.random(kl, ll / 2, el, q).abs(); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } L.add(a); //System.out.println(" L = " + L ); L = bb.GB(L); //System.out.println("eGB(L) = " + L ); assertTrue("isGB( { a } )", bb.isGB(L)); L.add(b); //System.out.println(" L = " + L ); L = bb.GB(L); //System.out.println("eGB(L) = " + L ); assertTrue("isGB( { a, b } )", bb.isGB(L)); L.add(c); //System.out.println(" L = " + L ); L = bb.GB(L); //System.out.println("eGB(L) = " + L ); assertTrue("isGB( { a, b, c } )", bb.isGB(L)); L.add(d); //System.out.println(" L = " + L ); L = bb.GB(L); //System.out.println("eGB(L) = " + L ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L)); L.add(e); //System.out.println(" L = " + L ); L = bb.GB(L); //System.out.println("eGB(L) = " + L ); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L)); } /** * Test Trinks7 GBase over Z. * */ @SuppressWarnings("unchecked") public void xtestTrinks7GBaseZ() { // needs 20 sec String exam = "Z(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( 10000 B**2 + 6600 B + 2673 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } System.out.println("F = " + F); G = bb.GB(F.list); PolynomialList trinks = new PolynomialList(F.ring, G); System.out.println("G = " + trinks); System.out.println("G.size() = " + G.size()); assertTrue("isGB( eGB(Trinks7) )", bb.isGB(G)); //assertEquals("#GB(Trinks7) == 44", 44, G.size() ); } /** * Test Trinks7 GBase over Z(B). * */ @SuppressWarnings("unchecked") public void xtestTrinks7GBaseZ_B() { String exam = "IntFunc{ B } (S,T,Z,P,W) G " + "( " + "( { 45 } P + { 35 } S - { 165 B } - { 36 } ), " + "( { 35 } P + { 40 } Z + { 25 } T - { 27 } S ), " + "( { 15 } W + { 25 } S P + { 30 } Z - { 18 } T - { 165 B**2 } ), " + "( { - 9 } W + { 15 } T P + { 20 } S Z ), " + "( P W + { 2 } T Z - { 11 B**3 } ), " + "( { 99 } W - { 11 B } S + { 3 B**2 } ), " + "( { 10000 B**2 + 6600 B + 2673 } ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); EGroebnerBaseSeq> bb = new EGroebnerBaseSeq>(); PolynomialList> F = null; List>> G = null; try { F = (PolynomialList>) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } System.out.println("F = " + F); List>> Fp = new ArrayList>>( F.list.size()); for (GenPolynomial> p : F.list) { p = PolyUtil. monic(p); Fp.add(p); } //System.out.println("Fp = " + Fp); G = bb.GB(Fp); //System.out.println("G = " + G); List>> Gp = new ArrayList>>( F.list.size()); for (GenPolynomial> p : G) { p = PolyUtil. monic(p); Gp.add(p); } PolynomialList> trinks = new PolynomialList>( F.ring, Gp); System.out.println("G = " + trinks); System.out.println("G.size() = " + G.size()); ComputerThreads.terminate(); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G)); //assertEquals("#GB(Trinks7) == 1", 1, G.size() ); } } jas-2.5/trc/edu/jas/gb/GroebnerBaseSeqPairParTest.java0000644000175000017500000002230112002766222023043 0ustar giovannigiovanni/* * $Id: GroebnerBaseSeqPairParTest.java 4015 2012-07-22 12:05:38Z kredel $ */ package edu.jas.gb; //import edu.jas.poly.GroebnerBase; import java.util.List; import java.util.ArrayList; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBase; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base parallel, sequential pair list, tests with JUnit. * @author Heinz Kredel. */ public class GroebnerBaseSeqPairParTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBaseSeqPairParTest.class); /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a GroebnerBaseSeqPairParTest object. * @param name String. */ public GroebnerBaseSeqPairParTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(GroebnerBaseSeqPairParTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBaseAbstract bbseq; GroebnerBaseAbstract bbpar; GroebnerBaseAbstract bbspar; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 10; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads = 2; protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff,rl); a = b = c = d = e = null; bbseq = new GroebnerBaseSeq(); bbpar = new GroebnerBaseParallel(threads); bbspar = new GroebnerBaseSeqPairParallel(threads); } protected void tearDown() { a = b = c = d = e = null; fac = null; bbseq = null; bbpar.terminate(); bbpar = null; bbspar.terminate(); bbspar = null; } /** * Test parallel GBase. * */ public void testSeqPairParallelGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); L = bbspar.GB( L ); assertTrue("isGB( { a } )", bbspar.isGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = bbspar.GB( L ); assertTrue("isGB( { a, b } )", bbspar.isGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = bbspar.GB( L ); assertTrue("isGB( { a, b, c } )", bbspar.isGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = bbspar.GB( L ); assertTrue("isGB( { a, b, c, d } )", bbspar.isGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = bbspar.GB( L ); assertTrue("isGB( { a, b, c, d, e } )", bbspar.isGB(L) ); } /** * Test compare sequential with parallel GBase. * */ public void testSequentialSeqPairParallelGBase() { List> Gs, Gp; L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } L.add(a); Gs = bbseq.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(b); Gs = bbseq.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(c); Gs = bbseq.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(d); Gs = bbseq.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(e); Gs = bbseq.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); } /** * Test compare parallel with sequential pair parallel GBase. * */ public void testParallelSeqPairParallelGBase() { List> Gs, Gp; L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } L.add(a); Gs = bbpar.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp) " + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs) " + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(b); Gs = bbpar.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp) " + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs) " + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(c); Gs = bbpar.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp) " + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs) " + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(d); Gs = bbpar.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp) " + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs) " + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(e); Gs = bbpar.GB( L ); Gp = bbspar.GB( L ); assertTrue("Gs.containsAll(Gp) " + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs) " + Gs + ", " + Gp, Gp.containsAll(Gs) ); } /** * Test Trinks7 GBase. * */ public void testTrinks7GBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ) " + ", ( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); long t; /* t = System.currentTimeMillis(); G = bbseq.GB( F.list ); t = System.currentTimeMillis() - t; System.out.println("bbseq ms = " + t); t = System.currentTimeMillis(); G = bbpar.GB( F.list ); t = System.currentTimeMillis() - t; System.out.println("bbpar ms = " + t); */ t = System.currentTimeMillis(); G = bbspar.GB( F.list ); t = System.currentTimeMillis() - t; //System.out.println("bbspar ms = " + t); assertTrue("nonsense ", t >= 0L); assertTrue("isGB( GB(Trinks7) )", bbspar.isGB(G) ); assertEquals("#GB(Trinks7) == 6", 6, G.size() ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } } jas-2.5/trc/edu/jas/gb/GroebnerBaseDistHybridECTest.java0000644000175000017500000001711512136513316023322 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistHybridECTest.java 4376 2013-04-26 15:01:34Z kredel $ */ package edu.jas.gb; //import edu.jas.poly.GroebnerBase; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.kern.ComputerThreads; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingElem; import edu.jas.util.ExecutableServer; /** * Distributed hybrid GroebnerBase tests with JUnit. * @author Heinz Kredel */ public class GroebnerBaseDistHybridECTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBaseDistHybridECTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); //ComputerThreads.terminate(); } /** * Constructs a GroebnerBaseDistHybridECTest object. * @param name String. */ public GroebnerBaseDistHybridECTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBaseDistHybridECTest.class); return suite; } int port = 55711; String host = "localhost"; String mfile = "examples/machines.localhost"; // contains localhost GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bbseq; GroebnerBaseAbstract bbdist; GroebnerBaseAbstract bbdists; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 4; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads = 2; ExecutableServer es1; ExecutableServer es2; @Override protected void setUp() { es1 = new ExecutableServer(4712); // == machines.localhost:4712 es1.init(); es2 = new ExecutableServer(4711); // == machines.localhost:4711 es2.init(); BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bbseq = new GroebnerBaseSeq(); bbdist = new GroebnerBaseDistributedHybridEC(mfile, threads, port); //bbdists = new GroebnerBaseDistributedHybridEC(mfile, threads, new OrderedSyzPairlist(), port); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bbseq = null; bbdist.terminate(); bbdist = null; //bbdists.terminate(); //bbdists = null; es1.terminate(); es2.terminate(); es1 = null; es2 = null; ComputerThreads.terminate(); } /** * Test distributed GBase. */ public void testDistributedGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); L.add(a); L = bbdist.GB(L); assertTrue("isGB( { a } ): " + L, bbseq.isGB(L)); L.add(b); //System.out.println("L = " + L.size() ); L = bbdist.GB(L); assertTrue("isGB( { a, b } ): " + L, bbseq.isGB(L)); L.add(c); L = bbdist.GB(L); assertTrue("isGB( { a, b, c } ): " + L, bbseq.isGB(L)); L.add(d); L = bbdist.GB(L); assertTrue("isGB( { a, b, c, d } ): " + L, bbseq.isGB(L)); L.add(e); L = bbdist.GB(L); assertTrue("isGB( { a, b, c, d, e } ): " + L, bbseq.isGB(L)); } /** * Test compare sequential with distributed GBase. */ public void testSequentialDistributedGBase() { List> Gs, Gp = null; L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); L.add(a); Gs = bbseq.GB(L); Gp = bbdist.GB(L); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(b); Gs = bbseq.GB(L); Gp = bbdist.GB(L); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(c); Gs = bbseq.GB(L); Gp = bbdist.GB(L); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(d); Gs = bbseq.GB(L); Gp = bbdist.GB(L); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(e); Gs = bbseq.GB(L); Gp = bbdist.GB(L); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); } /** * Test Trinks7 GBase. */ public void testTrinks7GBase() { List> Gs, Gp = null; String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; //exam = "(x3,x4,x5) L " + // "( (x3^2 - 13974703710478159/3775194259200) , (x4 - 34297/840), (x5^2 - 6389/480), (-4/3 x5^2 + x3^2 + x3 - 833/180) ) "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); Gp = bbdist.GB(F.list); //System.out.println("Gp = " + Gp); Gs = bbseq.GB(F.list); //System.out.println("Gs = " + Gs); assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(Gp)); assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(Gs)); //assertEquals("#GB(Trinks7) == 6", 6, G.size()); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + F, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + F, Gp.containsAll(Gs)); //PolynomialList trinks = new PolynomialList(F.ring, Gp); //System.out.println("G = " + trinks); } } jas-2.5/trc/edu/jas/gb/GroebnerBaseSeqPairDistTest.java0000644000175000017500000002041012002611634023217 0ustar giovannigiovanni/* * $Id: GroebnerBaseSeqPairDistTest.java 4010 2012-07-21 20:39:56Z kredel $ */ package edu.jas.gb; //import edu.jas.poly.GroebnerBase; import java.util.List; import java.util.ArrayList; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.structure.RingElem; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBase; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base distributed, sequential pair list, tests with JUnit. * @author Heinz Kredel */ public class GroebnerBaseSeqPairDistTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBaseSeqPairDistTest.class); /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a GroebnerBaseSeqPairDistTest object. * @param name String. */ public GroebnerBaseSeqPairDistTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(GroebnerBaseSeqPairDistTest.class); return suite; } int port = 4711; String host = "localhost"; GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bbseq; GroebnerBaseSeqPairDistributed bbdist; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 3; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads = 2; protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff,rl); a = b = c = d = e = null; bbseq = new GroebnerBaseSeq(); bbdist = new GroebnerBaseSeqPairDistributed(threads,port); } protected void tearDown() { a = b = c = d = e = null; fac = null; bbseq = null; bbdist.terminate(); bbdist = null; } /** * Helper method to start threads with distributed clients. * */ Thread[] startThreads() { Thread[] clients = new Thread[threads]; for (int t = 0; t < threads; t++) { clients[t] = new Thread( new JunitSeqPairClient(host,port) ); clients[t].start(); } return clients; } /** * Helper method to stop threads with distributed clients. * */ void stopThreads(Thread[] clients) { for (int t = 0; t < threads; t++) { try { clients[t].join(); } catch (InterruptedException e) { } } } /** * Test distributed GBase. * */ public void testSeqPairDistributedGBase() { Thread[] clients; L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); clients = startThreads(); L = bbdist.GB( L ); stopThreads( clients ); assertTrue("isGB( { a } )", bbseq.isGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); clients = startThreads(); L = bbdist.GB( L ); stopThreads( clients ); assertTrue("isGB( { a, b } )", bbseq.isGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); clients = startThreads(); L = bbdist.GB( L ); stopThreads( clients ); assertTrue("isGB( { a, b, c } )", bbseq.isGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); clients = startThreads(); L = bbdist.GB( L ); stopThreads( clients ); assertTrue("isGB( { a, b, c, d } )", bbseq.isGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); clients = startThreads(); L = bbdist.GB( L ); stopThreads( clients ); assertTrue("isGB( { a, b, c, d, e } )", bbseq.isGB(L) ); } /** * Test compare sequential with distributed GBase. * */ public void testSequentialSeqPairDistributedGBase() { Thread[] clients; List> Gs, Gp = null; L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } L.add(a); Gs = bbseq.GB( L ); clients = startThreads(); Gp = bbdist.GB( L ); stopThreads( clients ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(b); Gs = bbseq.GB( L ); clients = startThreads(); Gp = bbdist.GB( L ); stopThreads( clients ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(c); Gs = bbseq.GB( L ); clients = startThreads(); Gp = bbdist.GB( L ); stopThreads( clients ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(d); Gs = bbseq.GB( L ); clients = startThreads(); Gp = bbdist.GB( L ); stopThreads( clients ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); L = Gs; L.add(e); Gs = bbseq.GB( L ); clients = startThreads(); Gp = bbdist.GB( L ); stopThreads( clients ); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp, Gs.containsAll(Gp) ); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp, Gp.containsAll(Gs) ); } /** * Test Trinks7 GBase. * */ public void testTrinks7GBase() { Thread[] clients; String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); clients = startThreads(); G = bbdist.GB( F.list ); stopThreads( clients ); assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(G) ); assertEquals("#GB(Trinks7) == 6", 6, G.size() ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } } /** * Unit Test client to be executed by test threads. */ class JunitSeqPairClient> implements Runnable { private final String host; private final int port; JunitSeqPairClient(String host, int port) { this.host = host; this.port = port; } public void run() { GroebnerBaseSeqPairDistributed bbd; bbd = new GroebnerBaseSeqPairDistributed(1,null,port); try { bbd.clientPart(host); } catch (IOException ignored) { } bbd.terminate(); } } jas-2.5/trc/edu/jas/gb/GroebnerBaseSeqTest.java0000644000175000017500000003266212045171432021577 0ustar giovannigiovanni/* * $Id: GroebnerBaseSeqTest.java 4279 2012-11-03 10:34:03Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.ArrayList; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class GroebnerBaseSeqTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a GroebnerBaseSeqTest object. * @param name String. */ public GroebnerBaseSeqTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(GroebnerBaseSeqTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBaseAbstract bb; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 4; //4; //3; int kl = 7; // 10 int ll = 7; int el = 3; // 4 float q = 0.2f; //0.4f protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff,rl); a = b = c = d = e = null; bb = new GroebnerBaseSeq(); } protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; } /** * Test sequential GBase. */ public void testSequentialGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); L = bb.GB( L ); assertTrue("isGB( { a } )", bb.isGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = bb.GB( L ); assertTrue("isGB( { a, b } )", bb.isGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = bb.GB( L ); assertTrue("isGB( { a, b, c } )", bb.isGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = bb.GB( L ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = bb.GB( L ); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L) ); } /** * Test Trinks7 GBase. */ @SuppressWarnings("unchecked") public void testTrinks7GBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; String exam2 = "(x,y,z) L " + "( " + "( z y**2 + 2 x + 1/2 )" + "( z x**2 - y**2 - 1/2 x )" + "( -z + y**2 x + 4 x**2 + 1/4 )" + " )"; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); G = bb.GB(F.list); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G) ); assertEquals("#GB(Trinks7) == 6", 6, G.size() ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } /** * Test sequential extended GBase. */ public void testSequentialExtendedGBase() { L = new ArrayList>(); ExtendedGB exgb; a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); //System.out.println("L = " + L ); exgb = bb.extGB( L ); // System.out.println("exgb = " + exgb ); assertTrue("isGB( { a } )", bb.isGB(exgb.G) ); assertTrue("isRmat( { a } )", bb.isReductionMatrix(exgb) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L ); exgb = bb.extGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isGB( { a, b } )", bb.isGB(exgb.G) ); assertTrue("isRmat( { a, b } )", bb.isReductionMatrix(exgb) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); exgb = bb.extGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isGB( { a, b, c } )", bb.isGB(exgb.G) ); assertTrue("isRmat( { a, b, c } )", bb.isReductionMatrix(exgb) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); exgb = bb.extGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(exgb.G) ); assertTrue("isRmat( { a, b, c, d } )", bb.isReductionMatrix(exgb) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); exgb = bb.extGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(exgb.G) ); assertTrue("isRmat( { a, b, c, d, e } )", bb.isReductionMatrix(exgb) ); } /** * Test Trinks7 GBase. */ @SuppressWarnings("unchecked") public void testTrinks7ExtendedGBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); ExtendedGB exgb; exgb = bb.extGB(F.list); //System.out.println("exgb = " + exgb ); assertTrue("isGB( GB(Trinks7) )", bb.isGB(exgb.G) ); //assertEquals("#GB(Trinks7) == 6", 6, exgb.G.size() ); assertTrue("isRmat( GB(Trinks7) )", bb.isReductionMatrix(exgb) ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } /** * Test Trinks7 GBase, syz pair list. */ @SuppressWarnings("unchecked") public void testTrinks7GBaseSyz() { GroebnerBase bbs; bbs = new GroebnerBaseSeq(new ReductionSeq(), new OrderedSyzPairlist()); String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; String exam2 = "(x,y,z) L " + "( " + "( z y**2 + 2 x + 1/2 )" + "( z x**2 - y**2 - 1/2 x )" + "( -z + y**2 x + 4 x**2 + 1/4 )" + " )"; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); G = bbs.GB(F.list); assertTrue("isGB( GB(Trinks7) )", bbs.isGB(G) ); assertEquals("#GB(Trinks7) == 6", 6, G.size() ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G) ); //Reduction rd = new ReductionSeq(); //System.out.println("G.contains(F) = " + rd.normalform(G,F.list) ); } /** * Test Trinks7 GBase, min pair list. */ @SuppressWarnings("unchecked") public void testTrinks7GBaseMin() { bb = new GroebnerBaseSeq(new ReductionSeq(), new OrderedMinPairlist()); String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); G = bb.GB(F.list); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G) ); assertEquals("#GB(Trinks7) == 6", 6, G.size() ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } /** * Test sequential GBase, both. * Test isGBsimple and isGBidem. */ public void testSequentialGBaseBoth() { GroebnerBaseAbstract bbs = new GroebnerBaseSeq(new ReductionSeq(), new OrderedSyzPairlist()); L = new ArrayList>(); List> G; do { a = fac.random(kl, ll, el, q ); } while ( a.isZERO() || a.isONE() ); do { b = fac.random(kl, ll, el, q ); } while ( b.isZERO() || b.isONE() ); do { c = fac.random(kl, ll, el, q ); } while ( c.isZERO() || c.isONE() ); do { d = fac.random(kl, ll, el, q ); } while ( d.isZERO() || d.isONE() ); e = d; //fac.random(kl, ll, el, q ); L.add(a); G = bb.GB( L ); assertTrue("isGB( { a } )", bb.isGB(G) ); G = bbs.GB( L ); assertTrue("isGB( { a } )", bbs.isGB(G) ); assertEquals("isGBsimple(G) == isGBidem(G)", bb.isGB(G), bb.isGB(G,false) ); G.add(b); L = G; G = bb.GB( L ); assertTrue("isGB( { a, b } )", bb.isGB(G) ); G = bbs.GB( L ); assertTrue("isGB( { a, b } )", bbs.isGB(G) ); assertEquals("isGBsimple(G) == isGBidem(G)", bb.isGB(G), bb.isGB(G,false) ); G.add(c); L = G; G = bb.GB( L ); assertTrue("isGB( { a, b, c } )", bb.isGB(G) ); G = bbs.GB( L ); assertTrue("isGB( { a, b, c } )", bbs.isGB(G) ); assertEquals("isGBsimple(G) == isGBidem(G)", bb.isGB(G), bb.isGB(G,false) ); G.add(d); L = G; G = bb.GB( L ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(G) ); G = bbs.GB( L ); assertTrue("isGB( { a, b, c, d } )", bbs.isGB(G) ); assertEquals("isGBsimple(G) == isGBidem(G)", bb.isGB(G), bb.isGB(G,false) ); G.add(e); L = G; G = bb.GB( L ); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(G) ); G = bbs.GB( L ); assertTrue("isGB( { a, b, c, d, e } )", bbs.isGB(G) ); //System.out.println("G = " + G); assertEquals("isGBsimple(G) == isGBidem(G)", bb.isGB(G), bb.isGB(G,false) ); } } jas-2.5/trc/edu/jas/gb/GroebnerBaseDistTest.java0000644000175000017500000002066212033075014021743 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistTest.java 4230 2012-10-03 17:46:52Z kredel $ */ package edu.jas.gb; //import edu.jas.poly.GroebnerBase; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.kern.ComputerThreads; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingElem; /** * Distributed GroebnerBase tests with JUnit. * @author Heinz Kredel */ public class GroebnerBaseDistTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBaseDistTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); //ComputerThreads.terminate(); } /** * Constructs a GroebnerBaseDistTest object. * @param name String. */ public GroebnerBaseDistTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBaseDistTest.class); return suite; } int port = 4711; String host = "localhost"; GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bbseq; GroebnerBaseDistributed bbdist; GroebnerBaseDistributed bbdists; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 4; int ll = 7; int el = 3; float q = 0.2f; //0.4f int threads = 2; @Override protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; bbseq = new GroebnerBaseSeq(); bbdists = new GroebnerBaseDistributed(threads, port); bbdist = new GroebnerBaseDistributed(threads, new OrderedSyzPairlist(), port); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; bbseq = null; bbdist.terminate(); bbdist = null; bbdists.terminate(); bbdists = null; ComputerThreads.terminate(); } /** * Helper method to start threads with distributed clients. * */ Thread[] startThreads() { Thread[] clients = new Thread[threads]; for (int t = 0; t < threads; t++) { clients[t] = new Thread(new JunitClient(host, port)); clients[t].start(); } return clients; } /** * Helper method to stop threads with distributed clients. * */ void stopThreads(Thread[] clients) { for (int t = 0; t < threads; t++) { try { clients[t].join(); } catch (InterruptedException e) { } } } /** * Test distributed GBase. * */ public void testDistributedGBase() { Thread[] clients; L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); L.add(a); clients = startThreads(); L = bbdist.GB(L); stopThreads(clients); assertTrue("isGB( { a } )", bbseq.isGB(L)); L.add(b); //System.out.println("L = " + L.size() ); clients = startThreads(); L = bbdist.GB(L); stopThreads(clients); assertTrue("isGB( { a, b } )", bbseq.isGB(L)); L.add(c); clients = startThreads(); L = bbdist.GB(L); stopThreads(clients); assertTrue("isGB( { a, b, c } )", bbseq.isGB(L)); L.add(d); clients = startThreads(); L = bbdist.GB(L); stopThreads(clients); assertTrue("isGB( { a, b, c, d } )", bbseq.isGB(L)); L.add(e); clients = startThreads(); L = bbdist.GB(L); stopThreads(clients); assertTrue("isGB( { a, b, c, d, e } )", bbseq.isGB(L)); } /** * Test compare sequential with distributed GBase. * */ public void testSequentialDistributedGBase() { Thread[] clients; List> Gs, Gp = null; L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); L.add(a); Gs = bbseq.GB(L); clients = startThreads(); Gp = bbdist.GB(L); stopThreads(clients); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(b); Gs = bbseq.GB(L); clients = startThreads(); Gp = bbdist.GB(L); stopThreads(clients); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(c); Gs = bbseq.GB(L); clients = startThreads(); Gp = bbdist.GB(L); stopThreads(clients); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(d); Gs = bbseq.GB(L); clients = startThreads(); Gp = bbdist.GB(L); stopThreads(clients); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); L = Gs; L.add(e); Gs = bbseq.GB(L); clients = startThreads(); Gp = bbdist.GB(L); stopThreads(clients); assertTrue("Gs.containsAll(Gp)" + Gs + ", " + Gp + ", " + L, Gs.containsAll(Gp)); assertTrue("Gp.containsAll(Gs)" + Gs + ", " + Gp + ", " + L, Gp.containsAll(Gs)); } /** * Test Trinks7 GBase. * */ public void testTrinks7GBase() { Thread[] clients; String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); clients = startThreads(); G = bbdist.GB(F.list); stopThreads(clients); assertTrue("isGB( GB(Trinks7) )", bbseq.isGB(G)); assertEquals("#GB(Trinks7) == 6", 6, G.size()); //PolynomialList trinks = new PolynomialList(F.ring, G); //System.out.println("G = " + trinks); } } /** * Unit Test client to be executed by test threads. */ class JunitClient> implements Runnable { private final String host; private final int port; JunitClient(String host, int port) { this.host = host; this.port = port; } public void run() { GroebnerBaseDistributed bbd; bbd = new GroebnerBaseDistributed(1, null, null, port); try { bbd.clientPart(host); } catch (IOException ignored) { } bbd.terminate(); } } jas-2.5/trc/edu/jas/gb/SolvableGroebnerBaseParTest.java0000644000175000017500000001741511641660762023272 0ustar giovannigiovanni/* * $Id: SolvableGroebnerBaseParTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.poly.RelationTable; import edu.jas.poly.TermOrder; import edu.jas.poly.WeylRelations; /** * SolvableGroebnerBase parallel tests with JUnit. * @author Heinz Kredel. */ public class SolvableGroebnerBaseParTest extends TestCase { //private static final Logger logger = Logger.getLogger(SolvableGroebnerBaseParTest.class); /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a SolvableGroebnerBaseParTest object. * @param name String. */ public SolvableGroebnerBaseParTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(SolvableGroebnerBaseParTest.class); return suite; } int port = 4711; String host = "localhost"; GenSolvablePolynomial a; GenSolvablePolynomial b; GenSolvablePolynomial c; GenSolvablePolynomial d; GenSolvablePolynomial e; List> L; PolynomialList F; PolynomialList G; GenSolvablePolynomialRing ring; SolvableGroebnerBase psbb; BigRational cfac; TermOrder tord; RelationTable table; int rl = 4; //4; //3; int kl = 10; int ll = 4; int el = 2; float q = 0.3f; //0.4f protected void setUp() { cfac = new BigRational(9); tord = new TermOrder(); ring = new GenSolvablePolynomialRing(cfac,rl,tord); table = ring.table; a = b = c = d = e = null; psbb = new SolvableGroebnerBaseParallel(); a = ring.random(kl, ll, el, q ); b = ring.random(kl, ll, el, q ); c = ring.random(kl, ll, el, q ); d = ring.random(kl, ll, el, q ); e = d; //ring.random(kl, ll, el, q ); } protected void tearDown() { a = b = c = d = e = null; ring = null; tord = null; table = null; cfac = null; ((SolvableGroebnerBaseParallel)psbb).terminate(); psbb = null; } /** * Test parallel GBase. */ public void testParallelGBase() { assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d, e } )", psbb.isLeftGB(L) ); } /** * Test Weyl parallel GBase. * */ public void testWeylParallelGBase() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); table = ring.table; a = ring.random(kl, ll, el, q ); b = ring.random(kl, ll, el, q ); c = ring.random(kl, ll, el, q ); d = ring.random(kl, ll, el, q ); e = d; //ring.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d } )", psbb.isLeftGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = psbb.leftGB( L ); assertTrue("isLeftGB( { a, b, c, d, e } )", psbb.isLeftGB(L) ); } /** * Test parallel twosided GBase. * */ public void testParallelTSGBase() { assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); L = psbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); L = psbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = psbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b, c } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = psbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b, c, d } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = psbb.twosidedGB( L ); //System.out.println("L = " + L.size() ); assertTrue("isTwosidedGB( { a, b, c, d, e } )", psbb.isTwosidedGB(L) ); } /** * Test Weyl parallel twosided GBase * is always 1. */ public void testWeylParallelTSGBase() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); table = ring.table; a = ring.random(kl, ll, el, q ); b = ring.random(kl, ll, el, q ); c = ring.random(kl, ll, el, q ); d = ring.random(kl, ll, el, q ); e = d; //ring.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); //System.out.println("La = " + L ); L = psbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); L = psbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = psbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b, c } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = psbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b, c, d } )", psbb.isTwosidedGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = psbb.twosidedGB( L ); //System.out.println("L = " + L ); assertTrue("isTwosidedGB( { a, b, c, d, e } )", psbb.isTwosidedGB(L) ); } } jas-2.5/trc/edu/jas/gb/GroebnerBaseSeqPairSeqTest.java0000644000175000017500000001747512002611634023065 0ustar giovannigiovanni/* * $Id: GroebnerBaseSeqPairSeqTest.java 4010 2012-07-21 20:39:56Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.ArrayList; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.gb.ExtendedGB; import edu.jas.gb.GroebnerBase; import edu.jas.gb.GroebnerBaseSeqPairSeq; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base sequential, sequential pair list, tests with JUnit. * @author Heinz Kredel. */ public class GroebnerBaseSeqPairSeqTest extends TestCase { //private static final Logger logger = Logger.getLogger(GroebnerBaseSeqPairSeqTest.class); /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a GroebnerBaseSeqPairSeqTest object. * @param name String. */ public GroebnerBaseSeqPairSeqTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(GroebnerBaseSeqPairSeqTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bb; // do interface GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 2; // 10; int ll = 5; //7; int el = 3; float q = 0.3f; //0.2f; //0.4f protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff,rl); a = b = c = d = e = null; bb = new GroebnerBaseSeqPairSeq(); } protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; } /** * Test sequential GBase. * */ public void testSeqPairSequentialGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); L = bb.GB( L ); assertTrue("isGB( { a } )", bb.isGB(L) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L.size() ); L = bb.GB( L ); assertTrue("isGB( { a, b } )", bb.isGB(L) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); L = bb.GB( L ); assertTrue("isGB( { a, b, c } )", bb.isGB(L) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); L = bb.GB( L ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); L = bb.GB( L ); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L) ); } /** * Test Trinks7 GBase. * */ @SuppressWarnings("unchecked") // not jet working public void testTrinks7GBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); G = bb.GB(F.list); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G) ); assertEquals("#GB(Trinks7) == 6", 6, G.size() ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } /** * Test sequential extended GBase. * */ public void testSeqPairSequentialExtendedGBase() { L = new ArrayList>(); ExtendedGB exgb; a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); //System.out.println("L = " + L ); exgb = bb.extGB( L ); // System.out.println("exgb = " + exgb ); assertTrue("isGB( { a } )", bb.isGB(exgb.G) ); assertTrue("isRmat( { a } )", bb.isReductionMatrix(exgb) ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); //System.out.println("L = " + L ); exgb = bb.extGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isGB( { a, b } )", bb.isGB(exgb.G) ); assertTrue("isRmat( { a, b } )", bb.isReductionMatrix(exgb) ); assertTrue("not isZERO( c )", !c.isZERO() ); L.add(c); exgb = bb.extGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isGB( { a, b, c } )", bb.isGB(exgb.G) ); assertTrue("isRmat( { a, b, c } )", bb.isReductionMatrix(exgb) ); assertTrue("not isZERO( d )", !d.isZERO() ); L.add(d); exgb = bb.extGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(exgb.G) ); assertTrue("isRmat( { a, b, c, d } )", bb.isReductionMatrix(exgb) ); assertTrue("not isZERO( e )", !e.isZERO() ); L.add(e); exgb = bb.extGB( L ); //System.out.println("exgb = " + exgb ); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(exgb.G) ); assertTrue("isRmat( { a, b, c, d, e } )", bb.isReductionMatrix(exgb) ); } /** * Test Trinks7 GBase. * */ @SuppressWarnings("unchecked") // not jet working public void testTrinks7ExtendedGBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); ExtendedGB exgb; exgb = bb.extGB(F.list); //System.out.println("exgb = " + exgb ); assertTrue("isGB( GB(Trinks7) )", bb.isGB(exgb.G) ); //assertEquals("#GB(Trinks7) == 6", 6, exgb.G.size() ); assertTrue("isRmat( GB(Trinks7) )", bb.isReductionMatrix(exgb) ); //PolynomialList trinks = new PolynomialList(F.ring,G); //System.out.println("G = " + trinks); } } jas-2.5/trc/edu/jas/gb/DGroebnerBaseSeqTest.java0000644000175000017500000001566611641660762021722 0ustar giovannigiovanni/* * $Id: DGroebnerBaseSeqTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.ArrayList; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import org.apache.log4j.Logger; import org.apache.log4j.BasicConfigurator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.gb.GroebnerBase; import edu.jas.kern.ComputerThreads; import edu.jas.arith.BigRational; import edu.jas.arith.BigInteger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.poly.PolyUtil; /** * DGroebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class DGroebnerBaseSeqTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a DGroebnerBaseSeqTest object. * @param name String. */ public DGroebnerBaseSeqTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(DGroebnerBaseSeqTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBase bb; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 4; //4; 10 int ll = 4; int el = 3; float q = 0.2f; //0.4f protected void setUp() { BigInteger coeff = new BigInteger(9); fac = new GenPolynomialRing(coeff,rl); a = b = c = d = e = null; bb = new DGroebnerBaseSeq(); } protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; } /** * Test sequential GBase. * */ public void testSequentialGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q ); //.abs(); b = fac.random(kl, ll, el, q ); //.abs(); c = fac.random(kl, ll/2, el, q ); //.abs(); d = fac.random(kl, ll/2, el, q ); //.abs(); e = d; //fac.random(kl, ll, el, q ); if ( a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO() ) { return; } L.add(a); //System.out.println(" L = " + L ); L = bb.GB( L ); //System.out.println("dGB(L) = " + L ); assertTrue("isGB( { a } )", bb.isGB(L) ); L.add(b); //System.out.println(" L = " + L ); L = bb.GB( L ); //System.out.println("dGB(L) = " + L ); assertTrue("isGB( { a, b } )", bb.isGB(L) ); L.add(c); //System.out.println(" L = " + L ); L = bb.GB( L ); //System.out.println("dGB(L) = " + L ); assertTrue("isGB( { a, b, c } )", bb.isGB(L) ); L.add(d); //System.out.println(" L = " + L ); L = bb.GB( L ); //System.out.println("dGB(L) = " + L ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L) ); L.add(e); //System.out.println(" L = " + L ); L = bb.GB( L ); //System.out.println("dGB(L) = " + L ); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L) ); } /** * Test Trinks7 GBase over Z. * */ @SuppressWarnings("unchecked") // needs to long public void xtestTrinks7GBaseZ() { String exam = "Z(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( 10000 B**2 + 6600 B + 2673 ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } System.out.println("F = " + F); G = bb.GB(F.list); PolynomialList trinks = new PolynomialList(F.ring,G); System.out.println("G = " + trinks); System.out.println("G.size() = " + G.size()); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G) ); //assertEquals("#GB(Trinks7) == 6", 6, G.size() ); } /** * Test Trinks7 GBase over Z(B). * */ @SuppressWarnings("unchecked") public void xtestTrinks7GBaseZ_B() { String exam = "IntFunc{ B } (S,T,Z,P,W) G " + "( " + "( { 45 } P + { 35 } S - { 165 B } - { 36 } ), " + "( { 35 } P + { 40 } Z + { 25 } T - { 27 } S ), " + "( { 15 } W + { 25 } S P + { 30 } Z - { 18 } T - { 165 B**2 } ), " + "( { - 9 } W + { 15 } T P + { 20 } S Z ), " + "( P W + { 2 } T Z - { 11 B**3 } ), " + "( { 99 } W - { 11 B } S + { 3 B**2 } ), " + "( { 10000 B**2 + 6600 B + 2673 } ) " + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); DGroebnerBaseSeq> bb = new DGroebnerBaseSeq>(); PolynomialList> F = null; List>> G = null; try { F = (PolynomialList>) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } System.out.println("F = " + F); List>> Fp = new ArrayList>>( F.list.size() ); for ( GenPolynomial> p : F.list ) { p = PolyUtil.monic(p); Fp.add( p ); } //System.out.println("Fp = " + Fp); G = bb.GB(Fp); //System.out.println("G = " + G); List>> Gp = new ArrayList>>( F.list.size() ); for ( GenPolynomial> p : G ) { p = PolyUtil.monic(p); Gp.add( p ); } PolynomialList> trinks = new PolynomialList>(F.ring,Gp); System.out.println("G = " + trinks); System.out.println("G.size() = " + Gp.size()); ComputerThreads.terminate(); assertTrue("isGB( GB(Trinks7) )", bb.isGB(G) ); //assertEquals("#GB(Trinks7) == 1", 1, G.size() ); } } jas-2.5/trc/edu/jas/gb/SolvableReductionTest.java0000644000175000017500000001762411641660762022227 0ustar giovannigiovanni/* * $Id: SolvableReductionTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.poly.RelationTable; import edu.jas.poly.WeylRelations; /** * Solvable Reduction tests with JUnit. * @author Heinz Kredel. */ public class SolvableReductionTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ReductionSolvableTest object. * @param name String. */ public SolvableReductionTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(SolvableReductionTest.class); return suite; } //private final static int bitlen = 100; GenSolvablePolynomialRing fac; RelationTable table; GenSolvablePolynomial a; GenSolvablePolynomial b; GenSolvablePolynomial c; GenSolvablePolynomial d; GenSolvablePolynomial e; List> L; PolynomialList F; PolynomialList G; SolvableReduction sred; SolvableReduction sredpar; int rl = 4; int kl = 10; int ll = 5; int el = 3; float q = 0.4f; protected void setUp() { a = b = c = d = e = null; fac = new GenSolvablePolynomialRing( new BigRational(0), rl ); sred = new SolvableReductionSeq(); sredpar = new SolvableReductionPar(); } protected void tearDown() { a = b = c = d = e = null; fac = null; sred = null; sredpar = null; } /** * Test constants and empty list reduction. * */ public void testRatReduction0() { L = new ArrayList>(); a = fac.random(kl, ll, el, q ); c = fac.getONE(); d = fac.getZERO(); e = sred.leftNormalform( L, c ); assertTrue("isONE( e )", e.isONE() ); e = sred.leftNormalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); L.add( c ); e = sred.leftNormalform( L, c ); assertTrue("isZERO( e )", e.isZERO() ); // e = Reduction.leftNormalform( L, a ); // assertTrue("isZERO( e )", e.isZERO() ); e = sred.leftNormalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); L = new ArrayList>(); L.add( d ); e = sred.leftNormalform( L, c ); assertTrue("isONE( e )", e.isONE() ); e = sred.leftNormalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); } /** * Test constants and empty list reduction. * */ public void testWeylRatReduction0() { L = new ArrayList>(); WeylRelations wl = new WeylRelations(fac); wl.generate(); a = fac.random(kl, ll, el, q ); c = fac.getONE(); d = fac.getZERO(); e = sred.leftNormalform( L, c ); assertTrue("isONE( e )", e.isONE() ); e = sred.leftNormalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); L.add( c ); e = sred.leftNormalform( L, c ); assertTrue("isZERO( e )", e.isZERO() ); e = sred.leftNormalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); e = sred.leftNormalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); L = new ArrayList>(); L.add( d ); e = sred.leftNormalform( L, c ); assertTrue("isONE( e )", e.isONE() ); e = sred.leftNormalform( L, d ); assertTrue("isZERO( e )", e.isZERO() ); } /** * Test Rat reduction. * */ public void testRatReduction() { a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); e = sred.leftNormalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = sred.leftNormalform( L, a ); assertTrue("isZERO( e ) some times", e.isZERO() ); } /** * Test Rat reduction parallel. * */ public void testRatReductionPar() { a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); e = sredpar.leftNormalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = sredpar.leftNormalform( L, a ); assertTrue("isZERO( e ) some times", e.isZERO() ); } /** * Test Weyl Rational reduction. * */ public void testWeylRatReduction() { L = new ArrayList>(); WeylRelations wl = new WeylRelations(fac); wl.generate(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); e = sred.leftNormalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = sred.leftNormalform( L, a ); assertTrue("isZERO( e ) some times", e.isZERO() ); } /** * Test Weyl Rational reduction parallel. * */ public void testWeylRatReductionPar() { L = new ArrayList>(); WeylRelations wl = new WeylRelations(fac); wl.generate(); a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L.add(a); e = sredpar.leftNormalform( L, a ); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); L.add(b); e = sredpar.leftNormalform( L, a ); assertTrue("isZERO( e ) some times", e.isZERO() ); } /** * Test Rat reduction recording. * */ public void testRatReductionRecording() { List> row = null; a = fac.random(kl, ll, el, q ); b = fac.random(kl, ll, el, q ); c = fac.random(kl, ll, el, q ); d = fac.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); L = new ArrayList>(); L.add(a); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = sred.leftNormalform( row, L, a ); assertTrue("isZERO( e )", e.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); assertTrue("is leftReduction ", sred.isLeftReductionNF(row,L,a,e) ); L.add(b); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = sred.leftNormalform( row, L, b ); assertTrue("is leftReduction ", sred.isLeftReductionNF(row,L,b,e) ); L.add(c); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = sred.leftNormalform( row, L, c ); assertTrue("is leftReduction ", sred.isLeftReductionNF(row,L,c,e) ); L.add(d); row = new ArrayList>( L.size() ); for ( int m = 0; m < L.size(); m++ ) { row.add(null); } e = sred.leftNormalform( row, L, d ); assertTrue("is leftReduction ", sred.isLeftReductionNF(row,L,d,e) ); } } jas-2.5/trc/edu/jas/gb/GBProxyTest.java0000644000175000017500000001223112004571452020111 0ustar giovannigiovanni/* * $Id: GBProxyTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class GBProxyTest extends TestCase { private static final Logger logger = Logger.getLogger(GBProxyTest.class); /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a GBProxyTest object. * @param name String. */ public GBProxyTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GBProxyTest.class); return suite; } GenPolynomialRing fac; List> L; PolynomialList F; List> G; GroebnerBaseAbstract bb; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 3; //4; //3; int kl = 10; int ll = 7; int el = 3; float q = 0.2f; //0.4f @Override protected void setUp() { BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff, rl); a = b = c = d = e = null; GroebnerBaseAbstract bbs = new GroebnerBaseSeq(); //GroebnerBaseAbstract bbs = new GroebnerBaseSeqPairSeq(); int nt = ComputerThreads.N_CPUS; //System.out.println("nt = " + nt); //GroebnerBaseAbstract bbp = new GroebnerBaseParallel(nt); GroebnerBaseAbstract bbp = new GroebnerBaseSeqPairParallel(nt); bb = new GBProxy(bbs, bbp); } @Override protected void tearDown() { int s = bb.cancel(); logger.info("canceled tasks: " + s); //assertTrue("s >= 0 " + s, s >= 0); ComputerThreads.terminate(); a = b = c = d = e = null; fac = null; bb = null; } /** * Test GBase. * */ public void testGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = fac.random(kl, ll, el, q); d = fac.random(kl, ll, el, q); e = d; //fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO() || d.isZERO()) { return; } assertTrue("not isZERO( a )", !a.isZERO()); L.add(a); L = bb.GB(L); assertTrue("isGB( { a } )", bb.isGB(L)); assertTrue("not isZERO( b )", !b.isZERO()); L.add(b); //System.out.println("L = " + L.size() ); L = bb.GB(L); assertTrue("isGB( { a, b } )", bb.isGB(L)); assertTrue("not isZERO( c )", !c.isZERO()); L.add(c); L = bb.GB(L); assertTrue("isGB( { a, b, c } )", bb.isGB(L)); assertTrue("not isZERO( d )", !d.isZERO()); L.add(d); L = bb.GB(L); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L)); assertTrue("not isZERO( e )", !e.isZERO()); L.add(e); L = bb.GB(L); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L)); } /** * Test Trinks7 GBase. * */ @SuppressWarnings("unchecked") // not jet working public void testTrinks7GBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { fail("" + e); } catch (IOException e) { fail("" + e); } //System.out.println("F = " + F); G = bb.GB(F.list); assertEquals("#GB(Trinks7) == 6", 6, G.size()); assertTrue("isGB( GB(Trinks7) ) " + G, bb.isGB(G)); //PolynomialList trinks = new PolynomialList(F.ring, G); //System.out.println("G = " + trinks); } } jas-2.5/trc/edu/jas/gb/WordGroebnerBaseSeqTest.java0000644000175000017500000001616712020721402022424 0ustar giovannigiovanni/* * $Id: WordGroebnerBaseSeqTest.java 4157 2012-09-02 18:18:43Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.ArrayList; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.poly.WordFactory; import edu.jas.poly.GenWordPolynomial; import edu.jas.poly.GenWordPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; /** * Groebner base sequential tests with JUnit. * @author Heinz Kredel. */ public class WordGroebnerBaseSeqTest extends TestCase { //private static final Logger logger = Logger.getLogger(WordGroebnerBaseSeqTest.class); /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a WordGroebnerBaseSeqTest object. * @param name String. */ public WordGroebnerBaseSeqTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(WordGroebnerBaseSeqTest.class); return suite; } GenWordPolynomialRing fac; WordFactory wfac; List> L; PolynomialList F; List> G; WordGroebnerBase bb; GenWordPolynomial a; GenWordPolynomial b; GenWordPolynomial c; GenWordPolynomial d; GenWordPolynomial e; int kl = 3; // 10 int ll = 7; int el = 4; // 4 protected void setUp() { BigRational coeff = new BigRational(0); wfac = new WordFactory("a"); fac = new GenWordPolynomialRing(coeff,wfac); a = b = c = d = e = null; bb = new WordGroebnerBaseSeq(); } protected void tearDown() { a = b = c = d = e = null; fac = null; bb = null; } /** * Test sequential univariate Word GBase. */ public void testSequentialGBase() { L = new ArrayList>(); a = fac.random(kl, ll, el); b = fac.random(kl, ll, el); c = fac.random(kl, ll, el); d = fac.random(kl, ll, el); e = d; //fac.random(kl, ll, el); while ( a.isZERO() ) { a = fac.random(kl, ll, el); } while ( b.isZERO() ) { b = fac.random(kl, ll, el); } while ( c.isZERO() ) { c = fac.random(kl, ll, el); } while ( d.isZERO() ) { d = fac.random(kl, ll, el); } L.add(a); //System.out.println("L = " + L); L = bb.GB( L ); assertTrue("isGB( { a } )", bb.isGB(L) ); L.add(a.multiply(b)); //System.out.println("L = " + L); L = bb.GB( L ); assertTrue("isGB( { a, b } )", bb.isGB(L) ); L.add(a.multiply(c)); //System.out.println("L = " + L); L = bb.GB( L ); assertTrue("isGB( { a, b, c } )", bb.isGB(L) ); L.add(a.multiply(d)); //System.out.println("L = " + L); L = bb.GB( L ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L) ); L.add(e); //System.out.println("L = " + L); L = bb.GB( L ); assertTrue("isGB( { a, b, c, d, e } )", bb.isGB(L) ); L.clear(); L.add(a); L.add(a.multiply(b)); L.add(a.multiply(c)); L.add(a.multiply(d)); //System.out.println("L = " + L); L = bb.GB( L ); assertTrue("isGB( { a, b, c, d } )", bb.isGB(L) ); } /** * Test example 1 word GBase. */ @SuppressWarnings("unchecked") public void testExample1GBase() { String exam = "(x,y,z) L " + "( " + "( z y**2 + 2 x + 1/2 )" + "( z x**2 - y**2 - 1/2 x )" + "( -z + y**2 x + 4 x**2 + 1/4 )" + " )"; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); fac = new GenWordPolynomialRing(F.ring); //System.out.println("fac = " + fac); L = fac.valueOf(F.list); //System.out.println("L = " + L); G = bb.GB(L); //System.out.println("G = " + G); assertTrue("isGB( G )", bb.isGB(G) ); } /** * Test Trinks7 as non-commutative example word GBase. */ @SuppressWarnings("unchecked") public void testTrinks7GBase() { String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " // is needed + ") "; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); fac = new GenWordPolynomialRing(F.ring); //System.out.println("fac = " + fac); L = fac.valueOf(F.list); //System.out.println("L = " + L); G = bb.GB(L); //System.out.println("G = " + G); assertTrue("isGB( G )", bb.isGB(G) ); assertTrue("#G == 6", G.size() == 6); } /** * Test example 2 word GBase. */ @SuppressWarnings("unchecked") public void testExample2GBase() { String exam = "(x,y,z) L " + "( " + "( x y - z )" // will not be correct when converted to non-com + "( y z + 2 x + z )" + "( y z + x )" + " )"; Reader source = new StringReader( exam ); GenPolynomialTokenizer parser = new GenPolynomialTokenizer( source ); try { F = (PolynomialList) parser.nextPolynomialSet(); } catch(ClassCastException e) { fail(""+e); } catch(IOException e) { fail(""+e); } //System.out.println("F = " + F); fac = new GenWordPolynomialRing(F.ring); //System.out.println("fac = " + fac); L = fac.valueOf(F.list); //System.out.println("L = " + L); G = bb.GB(L); //System.out.println("G = " + G); assertTrue("isGB( G )", bb.isGB(G) ); } } jas-2.5/trc/edu/jas/poly/0000755000175000017500000000000012140140260015436 5ustar giovannigiovannijas-2.5/trc/edu/jas/poly/GenPolynomialTokenizerTest.java0000644000175000017500000011371712004572440023633 0ustar giovannigiovanni/* * $Id: GenPolynomialTokenizerTest.java 4072 2012-07-27 20:08:01Z kredel $ */ package edu.jas.poly; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigComplex; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigInteger; import edu.jas.arith.BigQuaternion; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.structure.RingFactory; /** * GenPolynomialTokenizer tests with JUnit. * @author Heinz Kredel */ public class GenPolynomialTokenizerTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GenPolynomialTokenizerTest object. * @param name String. */ public GenPolynomialTokenizerTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GenPolynomialTokenizerTest.class); return suite; } RingFactory fac; // unused GenPolynomialRing pfac; GenSolvablePolynomialRing spfac; GenPolynomialTokenizer parser; Reader source; @Override protected void setUp() { fac = null; pfac = null; parser = null; source = null; } @Override protected void tearDown() { fac = null; pfac = null; parser = null; source = null; } /** * Test rational polynomial. */ @SuppressWarnings("unchecked") public void testBigRational() { String exam = "Rat(x,y,z) L " + "( " + "( 1 ), " + "( 0 ), " + "( 3/4 - 6/8 ), " + "( 1 x + x^3 + 1/3 y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 4", f.list.size() == 4); BigRational fac = new BigRational(0); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenPolynomial c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); GenPolynomial d = f.list.get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); } /** * Test integer polynomial. */ @SuppressWarnings("unchecked") public void testBigInteger() { String exam = "Int(x,y,z) L " + "( " + "( 1 ), " + "( 0 ), " + "( 3 2 - 6 ), " + "( 1 x + x^3 + 3 y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 4", f.list.size() == 4); BigInteger fac = new BigInteger(0); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenPolynomial c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); GenPolynomial d = f.list.get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); } /** * Test modular integer polynomial. */ @SuppressWarnings("unchecked") public void testModInteger() { String exam = "Mod 19 (x,y,z) L " + "( " + "( 1 ), " + "( 0 ), " + "( 3 2 - 6 + 19 ), " + "( 1 x + x^3 + 3 y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 4", f.list.size() == 4); ModLongRing fac = new ModLongRing(19); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenPolynomial c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); GenPolynomial d = f.list.get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); } /** * Test complex polynomial. */ @SuppressWarnings("unchecked") public void testBigComplex() { String exam = "Complex(x,y,z) L " + "( " + "( 1i0 ), " + "( 0i0 ), " + "( 3/4i2 - 6/8i2 ), " + "( 1i0 x + x^3 + 1i3 y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 4", f.list.size() == 4); BigComplex fac = new BigComplex(0); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenPolynomial c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); GenPolynomial d = f.list.get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); } /** * Test decimal polynomial. */ @SuppressWarnings("unchecked") public void testBigDecimal() { String exam = "D(x,y,z) L " + "( " + "( 1 ), " + "( 0 ), " + "( 0.25 * 0.25 - 0.25^2 ), " + "( 1 x + x^3 + 0.3333333333333333333333 y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 4", f.list.size() == 4); BigDecimal fac = new BigDecimal(0); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenPolynomial c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); GenPolynomial d = f.list.get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); } /** * Test quaternion polynomial. */ @SuppressWarnings("unchecked") public void testBigQuaternion() { String exam = "Quat(x,y,z) L " + "( " + "( 1i0j0k0 ), " + "( 0i0j0k0 ), " + "( 3/4i2j1k3 - 6/8i2j1k3 ), " + "( 1 x + x^3 + 1i2j3k4 y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 4", f.list.size() == 4); BigQuaternion fac = new BigQuaternion(0); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenPolynomial c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); GenPolynomial d = f.list.get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); } /** * Test rational solvable polynomial. */ @SuppressWarnings("unchecked") public void testSolvableBigRational() { String exam = "Rat(x,y,z) L " + "RelationTable " + "( " + " ( z ), ( y ), ( y z -1 ) " + ") " + "( " + " ( 1 ), " + " ( 0 ), " + " ( 3/4 - 6/8 ), " + " ( 1 x + x^3 + 1/3 y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList f = null; try { f = (PolynomialList) parser.nextSolvablePolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); //System.out.println("f.ring.table = " + ((GenSolvablePolynomialRing)f.ring).table); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 4", f.list.size() == 4); BigRational fac = new BigRational(0); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; spfac = new GenSolvablePolynomialRing(fac, nvar, tord, vars); assertEquals("spfac == f.ring", spfac, f.ring); //System.out.println("spfac = " + spfac); //System.out.println("spfac.table = " + spfac.table); GenSolvablePolynomial a = f.castToSolvableList().get(0); //System.out.println("a = " + a); assertTrue("isZERO( f.get(0) )", a.isONE()); GenSolvablePolynomial b = f.castToSolvableList().get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenSolvablePolynomial c = f.castToSolvableList().get(2); //System.out.println("c = " + c); assertTrue("isONE( f.get(2) )", c.isZERO()); GenSolvablePolynomial d = f.castToSolvableList().get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); } /** * Test mod integer solvable polynomial. */ @SuppressWarnings("unchecked") public void testSolvableModInteger() { String exam = "Mod 19 (x,y,z) L " + "RelationTable " + "( " + " ( z ), ( y ), ( y z -1 ) " + ") " + "( " + "( 1 ), " + "( 0 ), " + "( 3 2 - 6 + 19 ), " + "( 1 x + x^3 + 3 y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList f = null; try { f = (PolynomialList) parser.nextSolvablePolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); //System.out.println("f.ring.table = " + ((GenSolvablePolynomialRing)f.ring).table); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 4", f.list.size() == 4); ModLongRing fac = new ModLongRing(19); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; spfac = new GenSolvablePolynomialRing(fac, nvar, tord, vars); assertEquals("spfac == f.ring", spfac, f.ring); //System.out.println("spfac = " + spfac); //System.out.println("spfac.table = " + spfac.table); GenSolvablePolynomial a = f.castToSolvableList().get(0); //System.out.println("a = " + a); assertTrue("isZERO( f.get(0) )", a.isONE()); GenSolvablePolynomial b = f.castToSolvableList().get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenSolvablePolynomial c = f.castToSolvableList().get(2); //System.out.println("c = " + c); assertTrue("isONE( f.get(2) )", c.isZERO()); GenSolvablePolynomial d = f.castToSolvableList().get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); } /** * Test integer polynomial module. */ @SuppressWarnings("unchecked") public void testBigIntegerModule() { String exam = "Int(x,y,z) L " + "( " + " ( " + " ( 1 ), " + " ( 0 ), " + " ( 3 2 - 6 ), " + " ( 1 x + x^3 + 3 y z - x^3 ) " + " ), " + " ( ( 1 ), ( 0 ) ) " + ")"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); ModuleList m = null; try { m = (ModuleList) parser.nextSubModuleSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("m = " + m); assertTrue("m != null", m.list != null); assertTrue("length( m ) = 2", m.list.size() == 2); assertTrue("length( m[0] ) = 4", ((List) m.list.get(0)).size() == 4); BigInteger fac = new BigInteger(0); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing(fac, nvar, tord, vars); assertEquals("pfac == m.ring", pfac, m.ring); List>> rows = m.list; List> f; f = rows.get(0); GenPolynomial a = f.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial b = f.get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenPolynomial c = f.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); GenPolynomial d = f.get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); f = rows.get(1); assertTrue("length( f ) = 4", f.size() == 4); a = f.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); b = f.get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); c = f.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); d = f.get(3); //System.out.println("c = " + d); assertTrue("isZERO( f.get(3) )", d.isZERO()); } /** * Test rational solvable polynomial module. */ @SuppressWarnings("unchecked") public void testBigRationalSolvableModule() { String exam = "Rat(x,y,z) L " + "RelationTable " + "( " + " ( z ), ( y ), ( y z -1 ) " + ") " + "( " + " ( " + " ( 1 ), " + " ( 0 ), " + " ( 3/4 - 6/8 ), " + " ( 1 x + x^3 + 1/3 y z - x^3 ) " + " ), " + " ( ( x ), ( 1 ), ( 0 ) ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); ModuleList m = null; try { m = (ModuleList) parser.nextSolvableSubModuleSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("m = " + m); //System.out.println("m.ring = " + m.ring); assertTrue("m != null", m.list != null); assertTrue("length( m ) = 2", m.list.size() == 2); assertTrue("length( m[0] ) = 4", ((List) m.list.get(0)).size() == 4); BigRational fac = new BigRational(0); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; spfac = new GenSolvablePolynomialRing(fac, nvar, tord, vars); assertEquals("spfac == m.ring", spfac, m.ring); List>> rows = m.castToSolvableList(); List> f; f = rows.get(0); GenSolvablePolynomial a = f.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenSolvablePolynomial b = f.get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenSolvablePolynomial c = f.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); GenSolvablePolynomial d = f.get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); f = rows.get(1); assertTrue("length( f ) = 4", f.size() == 4); a = f.get(0); //System.out.println("a = " + a); assertTrue("!isONE( f.get(0) )", !a.isONE()); b = f.get(1); //System.out.println("b = " + b); assertTrue("isONE( f.get(1) )", b.isONE()); c = f.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); d = f.get(3); //System.out.println("d = " + d); assertTrue("isZERO( f.get(3) )", d.isZERO()); } /** * Test algebraic number polynomial. Note: Syntax no more supported. */ @SuppressWarnings("unchecked") public void removedTestAlgebraicNumber() { String exam = "AN[ (i) ( i^2 + 1 ) ] (x,y,z) L " + "( " + "( 1 ), " + "( _i_ ), " + "( 0 ), " + "( _i^2_ + 1 ), " + "( 1 x + x^3 + _3 i_ y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList> f = null; AlgebraicNumberRing fac = null; try { f = (PolynomialList>) parser.nextPolynomialSet(); fac = (AlgebraicNumberRing) f.ring.coFac; } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 5", f.list.size() == 5); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing>(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial> a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial> b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isUnit( f.get(1) )", b.isUnit()); b = b.monic(); //System.out.println("b = " + b); assertTrue("isUnit( f.get(1) )", b.isONE()); GenPolynomial> c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(1) )", c.isZERO()); GenPolynomial> d = f.list.get(3); //System.out.println("d = " + d); assertTrue("isZERO( f.get(2) )", d.isZERO()); GenPolynomial> e = f.list.get(4); //System.out.println("e = " + e); assertEquals("f.get(3).length() == 2", 2, e.length()); } /** * Test Galois field coefficient polynomial. Note: Syntax no more * supported. */ @SuppressWarnings("unchecked") public void removedTestGaloisField() { String exam = "AN[ 19 (i) ( i^2 + 1 ) ] (x,y,z) L " + "( " + "( 20 ), " + "( _i_ ), " + "( 0 ), " + "( _i^2_ + 20 ), " + "( 1 x + x^3 + _3 i_ y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList> f = null; AlgebraicNumberRing fac = null; try { f = (PolynomialList>) parser.nextPolynomialSet(); fac = (AlgebraicNumberRing) f.ring.coFac; } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 5", f.list.size() == 5); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing>(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial> a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial> b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isUnit( f.get(1) )", b.isUnit()); b = b.monic(); //System.out.println("b = " + b); assertTrue("isUnit( f.get(1) )", b.isONE()); GenPolynomial> c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(1) )", c.isZERO()); GenPolynomial> d = f.list.get(3); //System.out.println("d = " + d); assertTrue("isZERO( f.get(2) )", d.isZERO()); GenPolynomial> e = f.list.get(4); //System.out.println("e = " + e); assertEquals("f.get(3).length() == 2", 2, e.length()); } /** * Test algebraic number polynomial with braces. */ @SuppressWarnings("unchecked") public void testAlgebraicNumberBrace() { String exam = "AN[ (i) ( i^2 + 1 ) ] (x,y,z) L " + "( " + "( 1 ), " + "( { i } ), " + "( 0 ), " + "( { i^2 } + 1 ), " + "( 1 x + x^3 + { 3 i }^2 y z - x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList> f = null; AlgebraicNumberRing fac = null; try { f = (PolynomialList>) parser.nextPolynomialSet(); fac = (AlgebraicNumberRing) f.ring.coFac; } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 5", f.list.size() == 5); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing>(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial> a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial> b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isUnit( f.get(1) )", b.isUnit()); b = b.monic(); //System.out.println("b = " + b); assertTrue("isUnit( f.get(1) )", b.isONE()); GenPolynomial> c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(1) )", c.isZERO()); GenPolynomial> d = f.list.get(3); //System.out.println("d = " + d); assertTrue("isZERO( f.get(2) )", d.isZERO()); GenPolynomial> e = f.list.get(4); //System.out.println("e = " + e); assertEquals("f.get(3).length() == 2", 2, e.length()); } /** * Test Galois field coefficient polynomial with braces. */ @SuppressWarnings("unchecked") public void testGaloisFieldBrace() { String exam = "AN[ 19 (i) ( i^2 + 1 ) ] (x,y,z) L " + "( " + "( 20 ), " + "( { i } ), " + "( 0 ), " + "( { i^2 } + 20 ), " + "( 1 x + x^3 + { 3 i }^3 y z + { -1 }^3 x^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList> f = null; AlgebraicNumberRing fac = null; try { f = (PolynomialList>) parser.nextPolynomialSet(); fac = (AlgebraicNumberRing) f.ring.coFac; } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 5", f.list.size() == 5); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing>(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial> a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial> b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isUnit( f.get(1) )", b.isUnit()); b = b.monic(); //System.out.println("b = " + b); assertTrue("isUnit( f.get(1) )", b.isONE()); GenPolynomial> c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(1) )", c.isZERO()); GenPolynomial> d = f.list.get(3); //System.out.println("d = " + d); assertTrue("isZERO( f.get(2) )", d.isZERO()); GenPolynomial> e = f.list.get(4); //System.out.println("e = " + e); assertEquals("f.get(3).length() == 2", 2, e.length()); } /** * Test Galois field coefficient polynomial without braces. */ @SuppressWarnings("unchecked") public void testGaloisFieldWoBrace() { String exam = "AN[ 19 (i) ( i^2 + 1 ) ] (x,y,z) L " + "( " + "( 20 ), " + "( i ), " + "( 0 ), " + "( i^2 + 20 ), " + "( 1 x + x^3 + 3^3 i^3 y z - (x)^3 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList> f = null; AlgebraicNumberRing fac = null; try { f = (PolynomialList>) parser.nextPolynomialSet(); fac = (AlgebraicNumberRing) f.ring.coFac; } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 5", f.list.size() == 5); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing>(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial> a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial> b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isUnit( f.get(1) )", b.isUnit()); b = b.monic(); //System.out.println("b = " + b); assertTrue("isUnit( f.get(1) )", b.isONE()); GenPolynomial> c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(1) )", c.isZERO()); GenPolynomial> d = f.list.get(3); //System.out.println("d = " + d); assertTrue("isZERO( f.get(2) )", d.isZERO()); GenPolynomial> e = f.list.get(4); //System.out.println("e = " + e); assertEquals("f.get(3).length() == 2", 2, e.length()); } /** * Test rational polynomial with generic coefficients. */ @SuppressWarnings("unchecked") public void testBigRationalGeneric() { String exam = "Rat(x,y,z) L " + "( " + "( 1^3 ), " + "( 0^3 ), " + "( { 3/4 }^2 - 6/8^2 ), " + "( { 1 }^2 x + x^3 + 1/3 y z - x^3 ), " + "( 1.0001 - 0.0001 + { 0.25 }**2 - 1/4^2 ) " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } //System.out.println("f = " + f); assertTrue("f != null", f.list != null); assertTrue("length( f ) = 5", f.list.size() == 5); BigRational fac = new BigRational(0); TermOrder tord = new TermOrder(TermOrder.INVLEX); String[] vars = new String[] { "x", "y", "z" }; int nvar = vars.length; pfac = new GenPolynomialRing(fac, nvar, tord, vars); assertEquals("pfac == f.ring", pfac, f.ring); GenPolynomial a = f.list.get(0); //System.out.println("a = " + a); assertTrue("isONE( f.get(0) )", a.isONE()); GenPolynomial b = f.list.get(1); //System.out.println("b = " + b); assertTrue("isZERO( f.get(1) )", b.isZERO()); GenPolynomial c = f.list.get(2); //System.out.println("c = " + c); assertTrue("isZERO( f.get(2) )", c.isZERO()); GenPolynomial d = f.list.get(3); //System.out.println("d = " + d); assertEquals("f.get(3).length() == 2", 2, d.length()); GenPolynomial e = f.list.get(4); //System.out.println("e = " + e); assertTrue("isONE( f.get(4) )", e.isONE()); } /** * Test rational polynomial with errors. */ @SuppressWarnings("unchecked") public void testBigRationalErorr() { // brace mismatch String exam = "Rat(x,y,z) L " + "( " + "( { 3 ), " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); PolynomialList f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } catch (InvalidExpressionException e) { // pass } // brace mismatch exam = "Rat(x,y,z) L " + "( " + "( 3 } ), " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } catch (InvalidExpressionException e) { // pass } // invalid nesting exam = "Rat(x,y,z) L " + "( " + "( { x } ), " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } catch (InvalidExpressionException e) { // pass } // unknown variable exam = "Rat(x,y,z) L " + "( " + "( w ), " + " )"; source = new StringReader(exam); parser = new GenPolynomialTokenizer(source); f = null; try { f = (PolynomialList) parser.nextPolynomialSet(); } catch (IOException e) { fail("" + e); } catch (ClassCastException e) { fail("" + e); } catch (InvalidExpressionException e) { // pass } assertTrue("f != null", f == null); } /** * Test variables. */ public void testVariables() { String vars = "a,b,c,d,e"; String[] variables = GenPolynomialTokenizer.variableList(vars); assertTrue("len == 5: ", variables.length == 5); String expr = "a,b,c,d,e"; variables = GenPolynomialTokenizer.expressionVariables(expr); //System.out.println("variables = " + Arrays.toString(variables) + ", len = " + variables.length); assertTrue("len == 5: ", variables.length == 5); expr = "b,c,d,e*a,b,c,d"; variables = GenPolynomialTokenizer.expressionVariables(expr); //System.out.println("variables = " + Arrays.toString(variables) + ", len = " + variables.length); assertTrue("len == 5: ", variables.length == 5); expr = "b + c^3 - d + e*a - b/c +d"; variables = GenPolynomialTokenizer.expressionVariables(expr); //System.out.println("variables = " + Arrays.toString(variables) + ", len = " + variables.length); assertTrue("len == 5: ", variables.length == 5); expr = "(b + c)^3 - { d + e*a } / [ b/c + d ] + (b + 3f + f*3 + f3)"; variables = GenPolynomialTokenizer.expressionVariables(expr); //System.out.println("variables = " + Arrays.toString(variables) + ", len = " + variables.length); assertTrue("len == 7: ", variables.length == 7); } } jas-2.5/trc/edu/jas/poly/AlgebraicNumberModTest.java0000644000175000017500000001713511641660762022655 0ustar giovannigiovanni/* * $Id: AlgebraicNumberModTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import java.util.Iterator; import java.util.Set; import java.util.HashSet; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.structure.Power; import edu.jas.structure.NotInvertibleException; import edu.jas.poly.GenPolynomial; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; /** * AlgebraicNumber modular Test using JUnit. * @author Heinz Kredel. */ public class AlgebraicNumberModTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a AlgebraicNumberModTest object. * @param name String. */ public AlgebraicNumberModTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(AlgebraicNumberModTest.class); return suite; } long p = 19; long qp = p; ModIntegerRing mpfac; AlgebraicNumberRing fac; GenPolynomialRing mfac; AlgebraicNumber< ModInteger > a; AlgebraicNumber< ModInteger > b; AlgebraicNumber< ModInteger > c; AlgebraicNumber< ModInteger > d; AlgebraicNumber< ModInteger > e; int rl = 1; int kl = 10; int ll = 10; int el = ll; float q = 0.5f; protected void setUp() { a = b = c = d = e = null; mpfac = new ModIntegerRing(p,true); String[] vars = new String[] { "i" }; mfac = new GenPolynomialRing( mpfac, rl, vars ); // GenPolynomial mo = mfac.random(kl,ll,el,q); // while ( mo.isConstant() ) { // mo = mfac.random(kl,ll,el,q); // } GenPolynomial mo = mfac.univariate(0,2); mo = mo.sum( mfac.getONE() ); // x^2 + 1 fac = new AlgebraicNumberRing( mo, true ); qp = 1L; for ( int i = 0; i < mo.degree(0); i++ ) { qp = qp * p; } //System.out.println("p = " + p + ", qp = " + qp); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); //System.out.println("c.getVal() = " + c.getVal()); assertTrue("length( c ) = 1", c.getVal().length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.getVal() = " + d.getVal()); assertTrue("length( d ) = 0", d.getVal().length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(el); //System.out.println("a = " + a); if ( a.isZERO() || a.isONE() ) { continue; } // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a"+i+" ) <> 0", a.getVal().length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a",c,d); c = fac.random(ll); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); b = fac.random(ll); if ( a.isZERO() || b.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*1/a = 1",fac.getONE(),d); try { a = fac.getZERO().inverse(); } catch(NotInvertibleException expected) { return; } fail("0 invertible"); } /** * Test distributive law. * */ public void testDistributive() { a = fac.random( ll ); b = fac.random( ll ); c = fac.random( ll ); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } /** * Test object potentiation. * */ public void testCharPower() { //System.out.println("fac = " + fac); a = fac.random(6); if ( a.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); b = Power.> positivePower(a, qp); assertTrue("not isZERO( b )", !b.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.subtract(b); //System.out.println("c = " + c); assertTrue("isZERO( a^(p^n) - a ) " + c, c.isZERO() ); } /** * Test enumerator. * */ public void testEnumerator() { long s = 1L; for ( int i = 0; i < (int)fac.modul.degree(0); i++ ) { s = s * p; } //System.out.println("s = " + s); long t = 0L; Set> elems = new HashSet>(49); //Iterator> iter = fac.iterator(); for ( AlgebraicNumber an : fac ) { t++; //System.out.println("an = " + an); elems.add(an); } //System.out.println("elems = " + elems); assertTrue("#elems " + s + ", t = " + t, s == t ); assertTrue("#elems " + s + ", t = " + elems.size(), s == elems.size() ); } } jas-2.5/trc/edu/jas/poly/GFGenPolynomialTest.java0000644000175000017500000002300412004571452022144 0ustar giovannigiovanni/* * $Id: GFGenPolynomialTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; /** * Galois field coefficients GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class GFGenPolynomialTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a GFGenPolynomialTest object. * @param name String. */ public GFGenPolynomialTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GFGenPolynomialTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing> fac; AlgebraicNumberRing cfac; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; GenPolynomial> d; GenPolynomial> e; int rl = 7; int kl = 10; int ll = 8; int el = 5; float q = 0.5f; protected long getPrime() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 60; i++) { prime *= 2; } prime -= 93; //System.out.println("prime = " + prime); return prime; } @Override protected void setUp() { a = b = c = d = e = null; long prime = getPrime(); ModIntegerRing r = new ModIntegerRing(prime); // univariate minimal polynomial GenPolynomialRing mfac = new GenPolynomialRing(r, 1); GenPolynomial modul = mfac.random(5); while (modul.isZERO() || modul.isUnit() || modul.isConstant()) { modul = mfac.random(5); } cfac = new AlgebraicNumberRing(modul.monic()); fac = new GenPolynomialRing>(cfac, rl); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )c" + c, !c.isZERO()); assertTrue("isONE( c ) " + c, c.isONE()); d = fac.getZERO(); //System.out.println("d = " + d); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO()); assertTrue("isONE( d )", !d.isONE()); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(ll + i); //System.out.println("a = " + a); // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a" + i + " ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); assertTrue(" not isONE( a" + i + " )", !a.isONE()); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a", a, d); c = fac.random(ll); ExpVector u = ExpVector.EVRAND(rl, el, q); AlgebraicNumber x = cfac.random(kl); b = new GenPolynomial>(fac, x, u); c = a.sum(b); d = a.sum(x, u); assertEquals("a+p(x,u) = a+(x,u)", c, d); c = a.subtract(b); d = a.subtract(x, u); assertEquals("a-p(x,u) = a-(x,u)", c, d); a = new GenPolynomial>(fac); b = new GenPolynomial>(fac, x, u); c = b.sum(a); d = a.sum(x, u); assertEquals("a+p(x,u) = a+(x,u)", c, d); c = a.subtract(b); d = a.subtract(x, u); assertEquals("a-p(x,u) = a-(x,u)", c, d); c = fac.random(ll); d = c.sum(a.sum(b)); e = c.sum(a).sum(b); assertEquals("c+(a+b) = (c+a)+b", d, e); c = a.sum(fac.getZERO()); d = a.subtract(fac.getZERO()); assertEquals("a+0 = a-0", c, d); c = fac.getZERO().sum(a); d = fac.getZERO().subtract(a.negate()); assertEquals("0+a = 0+(-a)", c, d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO()); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO()); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO()); assertTrue("not isZERO( d )", !d.isZERO()); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO()); assertTrue("a*b = b*a", c.equals(d)); assertEquals("a*b = b*a", c, d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply(b.multiply(c)); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c", d, e); assertTrue("a(bc) = (ab)c", d.equals(e)); AlgebraicNumber z = a.leadingBaseCoefficient(); //System.out.println("z = " + z); if (z.isUnit()) { AlgebraicNumber x = z.inverse(); //System.out.println("x = " + x); //System.out.println("a = " + a); c = a.monic(); //System.out.println("c = " + c); d = a.multiply(x); //System.out.println("d = " + d); assertEquals("a.monic() = a(1/ldcf(a))", c, d); } AlgebraicNumber y = b.leadingBaseCoefficient(); if (y.isUnit()) { y = y.inverse(); c = b.monic(); d = b.multiply(y); assertEquals("b.monic() = b(1/ldcf(b))", c, d); e = new GenPolynomial>(fac, y); d = b.multiply(e); assertEquals("b.monic() = b(1/ldcf(b))", c, d); d = e.multiply(b); assertEquals("b.monic() = (1/ldcf(b))*b", c, d); } } /** * Test distributive law. * */ public void testDistributive() { a = fac.random(ll); b = fac.random(ll); c = fac.random(ll); d = a.multiply(b.sum(c)); e = a.multiply(b).sum(a.multiply(c)); assertEquals("a(b+c) = ab+ac", d, e); } /** * Test object quotient and remainder. * */ public void testQuotRem1() { fac = new GenPolynomialRing>(cfac, 1); a = fac.random(ll).monic(); assertTrue("not isZERO( a )", !a.isZERO()); b = fac.random(ll).monic(); assertTrue("not isZERO( b )", !b.isZERO()); GenPolynomial> g = fac.random(ll).monic(); assertTrue("not isZERO( g )", !g.isZERO()); g = fac.getONE(); a = a.multiply(g); b = b.multiply(g); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("g = " + g); GenPolynomial>[] qr; qr = b.divideAndRemainder(a); c = qr[0]; d = qr[1]; //System.out.println("q = " + c); //System.out.println("r = " + d); e = c.multiply(a).sum(d); assertEquals("b = q a + r", b, e); qr = a.divideAndRemainder(b); c = qr[0]; d = qr[1]; //System.out.println("q = " + c); //System.out.println("r = " + d); e = c.multiply(b).sum(d); assertEquals("a = q b + r", a, e); // gcd tests ------------------------------- c = a.gcd(b); //System.out.println("gcd = " + c); assertTrue("a mod gcd(a,b) = 0", a.remainder(c).isZERO()); assertTrue("b mod gcd(a,b) = 0", b.remainder(c).isZERO()); assertEquals("g = gcd(a,b)", c, g); GenPolynomial>[] gst; gst = a.egcd(b); //System.out.println("egcd = " + gst[0]); //System.out.println(", s = " + gst[1] + ", t = " + gst[2]); c = gst[0]; d = gst[1]; e = gst[2]; assertEquals("g = gcd(a,b)", c, g); GenPolynomial> x; x = a.multiply(d).sum(b.multiply(e)).monic(); //System.out.println("x = " + x); assertEquals("gcd(a,b) = a s + b t", c, x); //System.out.println("g = " + g); //System.out.println("h = " + h); if (a.isZERO() || b.isZERO()) { return; } try { c = a.modInverse(b); //System.out.println("c = " + c); x = c.multiply(a).remainder(b).monic(); //System.out.println("x = " + x); assertTrue("a invertible mod b", x.isUnit()); } catch (RuntimeException e) { // dann halt nicht } } } jas-2.5/trc/edu/jas/poly/GenSolvablePolynomialTest.java0000644000175000017500000003043712016422422023422 0ustar giovannigiovanni/* * $Id: GenSolvablePolynomialTest.java 4142 2012-08-26 13:30:59Z kredel $ */ package edu.jas.poly; import java.util.Map; import java.util.List; import java.util.ArrayList; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.structure.RingElem; //import edu.jas.structure.RingFactory; /** * GenSolvablePolynomial Test using JUnit. * Note: not optimal since GenSolvablePolynomial does not * implement RingElem<GenSolvablePolynomial> * @author Heinz Kredel. */ public class GenSolvablePolynomialTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a GenSolvablePolynomialTest object. * @param name String. */ public GenSolvablePolynomialTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(GenSolvablePolynomialTest.class); return suite; } //private final static int bitlen = 100; int rl = 6; // even for Weyl int kl = 10; int ll = 7; int el = 4; float q = 0.5f; protected void setUp() { // a = b = c = d = e = null; } protected void tearDown() { // a = b = c = d = e = null; } /** * Test constructors and factory. */ public void testConstructors() { // rational numbers BigRational rf = new BigRational(); // System.out.println("rf = " + rf); //BigRational r = rf.fromInteger( 99 ); // System.out.println("r = " + r); //r = rf.random( 9 ); // System.out.println("r = " + r); // polynomials over rational numbers GenSolvablePolynomialRing pf = new GenSolvablePolynomialRing(rf,2); // System.out.println("pf = " + pf); GenSolvablePolynomial p = pf.getONE(); // System.out.println("p = " + p); p = pf.random( 9 ); // System.out.println("p = " + p); p = pf.getZERO(); // System.out.println("p = " + p); RingElem< GenPolynomial > pe = new GenSolvablePolynomial( pf ); //System.out.println("pe = " + pe); //System.out.println("p.equals(pe) = " + p.equals(pe) ); //System.out.println("p.equals(p) = " + p.equals(p) ); assertTrue("p.equals(pe) = ", p.equals(pe) ); assertTrue("p.equals(p) = ", p.equals(p) ); pe = pe.sum( p ); // why not p = p.add(pe) ? //System.out.println("pe = " + pe); assertTrue("pe.isZERO() = ", pe.isZERO()); p = pf.random( 9 ); p = (GenSolvablePolynomial)p.subtract( p ); //System.out.println("p = " + p); //System.out.println("p.isZERO() = " + p.isZERO()); assertTrue("p.isZERO() = ", p.isZERO()); // polynomials over (polynomials over rational numbers) GenSolvablePolynomialRing< GenPolynomial > ppf = new GenSolvablePolynomialRing< GenPolynomial >(pf,3); // System.out.println("ppf = " + ppf); GenSolvablePolynomial< GenPolynomial > pp = ppf.getONE(); // System.out.println("pp = " + pp); pp = ppf.random( 2 ); // System.out.println("pp = " + pp); pp = ppf.getZERO(); // System.out.println("pp = " + pp); RingElem< GenPolynomial< GenPolynomial > > ppe = new GenSolvablePolynomial< GenPolynomial >( ppf ); // System.out.println("ppe = " + ppe); // System.out.println("pp.equals(ppe) = " + pp.equals(ppe) ); // System.out.println("pp.equals(pp) = " + pp.equals(pp) ); assertTrue("pp.equals(ppe) = ", pp.equals(ppe) ); assertTrue("pp.equals(pp) = ", pp.equals(pp) ); ppe = ppe.sum( pp ); // why not pp = pp.add(ppe) ? //System.out.println("ppe = " + ppe); assertTrue("ppe.isZERO() = ", ppe.isZERO()); pp = ppf.random( 2 ); pp = (GenSolvablePolynomial< GenPolynomial>)pp.subtract( pp ); //System.out.println("pp = " + pp); //System.out.println("pp.isZERO() = " + pp.isZERO()); assertTrue("pp.isZERO() = ", pp.isZERO()); // polynomials over (polynomials over (polynomials over rational numbers)) GenSolvablePolynomialRing< GenPolynomial< GenPolynomial > > pppf = new GenSolvablePolynomialRing< GenPolynomial< GenPolynomial > >(ppf,4); // System.out.println("pppf = " + pppf); GenSolvablePolynomial< GenPolynomial< GenPolynomial > > ppp = pppf.getONE(); //System.out.println("ppp = " + ppp); ppp = pppf.random( 2 ); // System.out.println("ppp = " + ppp); ppp = pppf.getZERO(); // System.out.println("ppp = " + ppp); RingElem< GenPolynomial< GenPolynomial< GenPolynomial > > > pppe = new GenSolvablePolynomial< GenPolynomial< GenPolynomial > >( pppf ); // System.out.println("pppe = " + pppe); // System.out.println("ppp.equals(pppe) = " + ppp.equals(pppe) ); // System.out.println("ppp.equals(ppp) = " + ppp.equals(ppp) ); assertTrue("ppp.equals(pppe) = ", ppp.equals(pppe) ); assertTrue("ppp.equals(ppp) = ", ppp.equals(ppp) ); pppe = pppe.sum( ppp ); // why not ppp = ppp.add(pppe) ? // System.out.println("pppe = " + pppe); assertTrue("pppe.isZERO() = ", pppe.isZERO()); ppp = pppf.random( 2 ); ppp = (GenSolvablePolynomial>>)ppp.subtract( ppp ); // System.out.println("ppp = " + ppp); // System.out.println("ppp.isZERO() = " + ppp.isZERO()); assertTrue("ppp.isZERO() = ", ppp.isZERO()); } /** * Test extension and contraction. */ public void testExtendContract() { // rational numbers BigRational cf = new BigRational( 99 ); // System.out.println("cf = " + cf); // polynomials over rational numbers GenSolvablePolynomialRing pf = new GenSolvablePolynomialRing(cf,rl); // System.out.println("pf = " + pf); GenSolvablePolynomial a = pf.random(kl,ll,el,q); //System.out.println("a = " + a); int k = rl; GenSolvablePolynomialRing pfe = pf.extend(k); GenSolvablePolynomialRing pfec = pfe.contract(k); assertEquals("pf == pfec",pf,pfec); GenSolvablePolynomial ae = (GenSolvablePolynomial)a.extend(pfe,0,0); Map> m = ae.contract(pfec); List> ml = new ArrayList>( m.values() ); GenSolvablePolynomial aec = (GenSolvablePolynomial)ml.get(0); assertEquals("a == aec",a,aec); //System.out.println("ae = " + ae); //System.out.println("aec = " + aec); } /** * Test extension and contraction for Weyl relations. */ public void testExtendContractWeyl() { // rational numbers BigRational cf = new BigRational( 99 ); // System.out.println("cf = " + cf); // polynomials over rational numbers GenSolvablePolynomialRing pf = new GenSolvablePolynomialRing(cf,rl); WeylRelations wl = new WeylRelations(pf); wl.generate(); // System.out.println("pf = " + pf); GenSolvablePolynomial a = pf.random(kl,ll,el,q); //System.out.println("a = " + a); int k = rl; GenSolvablePolynomialRing pfe = pf.extend(k); GenSolvablePolynomialRing pfec = pfe.contract(k); assertEquals("pf == pfec",pf,pfec); GenSolvablePolynomial ae = (GenSolvablePolynomial)a.extend(pfe,0,0); Map> m = ae.contract(pfec); List> ml = new ArrayList>( m.values() ); GenSolvablePolynomial aec = (GenSolvablePolynomial)ml.get(0); assertEquals("a == aec",a,aec); //System.out.println("ae = " + ae); //System.out.println("aec = " + aec); } /** * Test reversion. */ public void testReverse() { // rational numbers BigRational cf = new BigRational( 99 ); // System.out.println("cf = " + cf); // polynomials over rational numbers GenSolvablePolynomialRing pf = new GenSolvablePolynomialRing(cf,rl); //System.out.println("pf = " + pf); GenSolvablePolynomial a = pf.random(kl,ll,el,q); //System.out.println("a = " + a); GenSolvablePolynomialRing pfr = pf.reverse(); GenSolvablePolynomialRing pfrr = pfr.reverse(); assertEquals("pf == pfrr",pf,pfrr); //System.out.println("pfr = " + pfr); GenSolvablePolynomial ar = (GenSolvablePolynomial)a.reverse(pfr); GenSolvablePolynomial arr = (GenSolvablePolynomial)ar.reverse(pfrr); assertEquals("a == arr",a,arr); //System.out.println("ar = " + ar); //System.out.println("arr = " + arr); } /** * Test reversion for Weyl relations. * */ public void testReverseWeyl() { // rational numbers BigRational cf = new BigRational( 99 ); // System.out.println("cf = " + cf); // polynomials over rational numbers GenSolvablePolynomialRing pf = new GenSolvablePolynomialRing(cf,rl); WeylRelations wl = new WeylRelations(pf); wl.generate(); //System.out.println("pf = " + pf); GenSolvablePolynomial a = pf.random(kl,ll,el,q); //System.out.println("a = " + a); GenSolvablePolynomialRing pfr = pf.reverse(); GenSolvablePolynomialRing pfrr = pfr.reverse(); assertEquals("pf == pfrr",pf,pfrr); //System.out.println("pfr = " + pfr); GenSolvablePolynomial ar = (GenSolvablePolynomial)a.reverse(pfr); GenSolvablePolynomial arr = (GenSolvablePolynomial)ar.reverse(pfrr); assertEquals("a == arr",a,arr); //System.out.println("ar = " + ar); //System.out.println("arr = " + arr); } /** * Test recursion. */ public void testRecursion() { // rational numbers BigRational rf = new BigRational(); // System.out.println("rf = " + rf); String[] vars = new String[] { "a", "b", "c", "d" }; TermOrder to = new TermOrder(TermOrder.INVLEX); // polynomials over rational numbers GenSolvablePolynomialRing pf = new GenSolvablePolynomialRing(rf,4,to,vars); WeylRelations wl = new WeylRelations(pf); wl.generate(); //System.out.println("pf = " + pf); GenSolvablePolynomial sp = pf.random(5); //System.out.println("sp = " + sp); sp = (GenSolvablePolynomial) sp.subtract(sp); assertTrue("sp == 0 ",sp.isZERO()); // polynomials over (solvable) polynomials over rational numbers GenSolvablePolynomialRing> rpf = new GenSolvablePolynomialRing>(pf,2); WeylRelations> rwl = new WeylRelations>(rpf); rwl.generate(); //System.out.println("rpf = " + rpf); GenSolvablePolynomial> rsp = rpf.random(5); //System.out.println("rsp = " + rsp); rsp = (GenSolvablePolynomial>) rsp.subtract(rsp); assertTrue("rsp == 0 ",rsp.isZERO()); } } jas-2.5/trc/edu/jas/poly/AlgebraicNumberTest.java0000644000175000017500000001741711641660762022220 0ustar giovannigiovanni /* * $Id: AlgebraicNumberTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import java.util.Iterator; import java.util.Set; import java.util.HashSet; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; //import edu.jas.structure.RingElem; import edu.jas.structure.NotInvertibleException; import edu.jas.poly.GenPolynomial; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; /** * AlgebraicNumber Test using JUnit. * @author Heinz Kredel. */ public class AlgebraicNumberTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a AlgebraicNumberTest object. * @param name String. */ public AlgebraicNumberTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(AlgebraicNumberTest.class); return suite; } //private final static int bitlen = 100; AlgebraicNumberRing fac; GenPolynomialRing mfac; AlgebraicNumber< BigRational > a; AlgebraicNumber< BigRational > b; AlgebraicNumber< BigRational > c; AlgebraicNumber< BigRational > d; AlgebraicNumber< BigRational > e; int rl = 1; int kl = 10; int ll = 10; int el = ll; float q = 0.5f; protected void setUp() { a = b = c = d = e = null; BigRational bi = new BigRational(1); //bi.setAllIterator(); bi.setNoDuplicatesIterator(); mfac = new GenPolynomialRing( bi, rl ); GenPolynomial mo = mfac.random(kl,ll,7,q); while ( mo.isConstant() ) { mo = mfac.random(kl,ll,5,q); } fac = new AlgebraicNumberRing( mo.monic() ); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); //System.out.println("c.getVal() = " + c.getVal()); assertTrue("length( c ) = 1", c.getVal().length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.getVal() = " + d.getVal()); assertTrue("length( d ) = 0", d.getVal().length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(el); //System.out.println("a = " + a); if ( a.isZERO() || a.isONE() ) { continue; } // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a"+i+" ) <> 0", a.getVal().length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a",c,d); c = fac.random(ll); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*1/a = 1",fac.getONE(),d); try { a = fac.getZERO().inverse(); fail("0 invertible"); } catch(NotInvertibleException expected) { // ok } GenPolynomial dp = fac.modul; GenPolynomial cp = fac.modul.multiply(a.val.monic()); //System.out.println("dp = " + dp); //System.out.println("cp = " + cp); fac = new AlgebraicNumberRing( cp ); a = new AlgebraicNumber(fac,a.val.monic()); assertFalse("a !unit mod m*a", a.isUnit()); try { b = a.inverse(); fail("invertible " + a); } catch (AlgebraicNotInvertibleException expected) { //ok //expected.printStackTrace(); //System.out.println("expected = " + expected); assertTrue("f = " + cp, expected.f.equals(cp)); assertTrue("f1 = " + a.val, expected.f1.equals(a.val)); assertTrue("f2 = " + dp, expected.f2.equals(dp)); assertTrue("f = f1*f2 ", expected.f.equals(expected.f1.multiply(expected.f2))); } catch (NotInvertibleException e) { //e.printStackTrace(); fail("wrong exception " + e); } } /** * Test distributive law. * */ public void testDistributive() { a = fac.random( ll ); b = fac.random( ll ); c = fac.random( ll ); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } /** * Test enumerator. * */ public void testEnumerator() { //System.out.println("fac = " + fac); long s = 0L; long t = 0L; Set> elems = new HashSet>(49); //Iterator> iter = fac.iterator(); for ( AlgebraicNumber an : fac ) { t++; if ( elems.contains(an) ) { //System.out.println("dup(an) = " + an); s++; } else { //System.out.println("an = " + an); elems.add(an); } if ( t >= 100 ) { break; } } //System.out.println("elems = " + elems); assertTrue("#elems " + t + ", t = " + elems.size(), t == elems.size() ); assertTrue("#elems " + t + ", t = " + elems.size(), s == 0L ); } } jas-2.5/trc/edu/jas/poly/TermOrderOptimizationTest.java0000644000175000017500000000367511641660762023511 0ustar giovannigiovanni/* * $Id: TermOrderOptimizationTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.ArrayList; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; /** * TermOrderOptimization tests with JUnit. * @author Heinz Kredel */ public class TermOrderOptimizationTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a TermOrderOptimizationTest object. * @param name String. */ public TermOrderOptimizationTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(TermOrderOptimizationTest.class); return suite; } protected void setUp() { } protected void tearDown() { } /** * Test permutations. */ public void testPermutation() { List P = new ArrayList(); P.add(2); P.add(1); P.add(4); P.add(0); P.add(3); //System.out.println("P = " + P); List S = TermOrderOptimization.inversePermutation(P); //System.out.println("S = " + S); assertFalse("P != id", TermOrderOptimization.isIdentityPermutation(P)); assertFalse("S != id", TermOrderOptimization.isIdentityPermutation(S)); List T = TermOrderOptimization.multiplyPermutation(P,S); //System.out.println("T = " + T); List U = TermOrderOptimization.multiplyPermutation(S,P); //System.out.println("U = " + U); assertTrue("T == id", TermOrderOptimization.isIdentityPermutation(T)); assertTrue("U == id", TermOrderOptimization.isIdentityPermutation(U)); } } jas-2.5/trc/edu/jas/poly/GenPolynomialTest.java0000644000175000017500000003553412004571452021742 0ustar giovannigiovanni/* * $Id: GenPolynomialTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.poly; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.structure.RingElem; import edu.jas.structure.UnaryFunctor; /** * GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class GenPolynomialTest extends TestCase { /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GenPolynomialTest object. * @param name String. */ public GenPolynomialTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GenPolynomialTest.class); return suite; } int rl = 6; int kl = 10; int ll = 7; int el = 4; float q = 0.5f; @Override protected void setUp() { } @Override protected void tearDown() { } /** * Test constructors and factory. */ public void testConstructors() { // rational numbers BigRational rf = new BigRational(); // System.out.println("rf = " + rf); //BigRational r = rf.fromInteger( 99 ); // System.out.println("r = " + r); //r = rf.random( 9 ).sum(r); // System.out.println("r = " + r); //assertFalse("r.isZERO() = ", r.isZERO()); //RingElem re = new BigRational( 3 ); // System.out.println("re = " + re); //rf = (BigRational) re; //RingFactory ref = new BigRational( 3 ); // System.out.println("re = " + re); //rf = (BigRational) ref; // polynomials over rational numbers GenPolynomialRing pf = new GenPolynomialRing(rf, 2); // System.out.println("pf = " + pf); GenPolynomial p = pf.getONE(); // System.out.println("p = " + p); p = pf.random(9); // System.out.println("p = " + p); p = pf.getZERO(); // System.out.println("p = " + p); RingElem> pe = new GenPolynomial(pf); //System.out.println("pe = " + pe); //System.out.println("p.equals(pe) = " + p.equals(pe) ); //System.out.println("p.equals(p) = " + p.equals(p) ); assertTrue("p.equals(pe) = ", p.equals(pe)); assertTrue("p.equals(p) = ", p.equals(p)); pe = pe.sum(p); // why not p = p.add(pe) ? //System.out.println("pe = " + pe); assertTrue("pe.isZERO() = ", pe.isZERO()); p = pf.random(9); p = p.subtract(p); //System.out.println("p = " + p); //System.out.println("p.isZERO() = " + p.isZERO()); assertTrue("p.isZERO() = ", p.isZERO()); // polynomials over (polynomials over rational numbers) GenPolynomialRing> ppf = new GenPolynomialRing>( pf, 3); // System.out.println("ppf = " + ppf); GenPolynomial> pp = ppf.getONE(); // System.out.println("pp = " + pp); pp = ppf.random(2); // System.out.println("pp = " + pp); pp = ppf.getZERO(); // System.out.println("pp = " + pp); RingElem>> ppe = new GenPolynomial>( ppf); // System.out.println("ppe = " + ppe); // System.out.println("pp.equals(ppe) = " + pp.equals(ppe) ); // System.out.println("pp.equals(pp) = " + pp.equals(pp) ); assertTrue("pp.equals(ppe) = ", pp.equals(ppe)); assertTrue("pp.equals(pp) = ", pp.equals(pp)); ppe = ppe.sum(pp); // why not pp = pp.add(ppe) ? //System.out.println("ppe = " + ppe); assertTrue("ppe.isZERO() = ", ppe.isZERO()); pp = ppf.random(2); pp = pp.subtract(pp); //System.out.println("pp = " + pp); //System.out.println("pp.isZERO() = " + pp.isZERO()); assertTrue("pp.isZERO() = ", pp.isZERO()); // polynomials over (polynomials over (polynomials over rational numbers)) GenPolynomialRing>> pppf = new GenPolynomialRing>>( ppf, 4); // System.out.println("pppf = " + pppf); GenPolynomial>> ppp = pppf.getONE(); //System.out.println("ppp = " + ppp); ppp = pppf.random(2); // System.out.println("ppp = " + ppp); ppp = pppf.getZERO(); // System.out.println("ppp = " + ppp); RingElem>>> pppe = new GenPolynomial>>( pppf); // System.out.println("pppe = " + pppe); // System.out.println("ppp.equals(pppe) = " + ppp.equals(pppe) ); // System.out.println("ppp.equals(ppp) = " + ppp.equals(ppp) ); assertTrue("ppp.equals(pppe) = ", ppp.equals(pppe)); assertTrue("ppp.equals(ppp) = ", ppp.equals(ppp)); pppe = pppe.sum(ppp); // why not ppp = ppp.add(pppe) ? // System.out.println("pppe = " + pppe); assertTrue("pppe.isZERO() = ", pppe.isZERO()); ppp = pppf.random(2); ppp = ppp.subtract(ppp); // System.out.println("ppp = " + ppp); // System.out.println("ppp.isZERO() = " + ppp.isZERO()); assertTrue("ppp.isZERO() = ", ppp.isZERO()); // some tests //GenPolynomial pfx = new GenPolynomial(); //System.out.println("pfx = " + pfx); } /** * Test extension and contraction. */ public void testExtendContract() { // rational numbers BigRational cf = new BigRational(99); // System.out.println("cf = " + cf); // polynomials over rational numbers GenPolynomialRing pf = new GenPolynomialRing(cf, rl); // System.out.println("pf = " + pf); GenPolynomial a = pf.random(kl, ll, el, q); //System.out.println("a = " + a); int k = rl; GenPolynomialRing pfe = pf.extend(k); GenPolynomialRing pfec = pfe.contract(k); assertEquals("pf == pfec", pf, pfec); GenPolynomial ae = a.extend(pfe, 0, 0); Map> m = ae.contract(pfec); List> ml = new ArrayList>(m.values()); GenPolynomial aec = ml.get(0); assertEquals("a == aec", a, aec); //System.out.println("ae = " + ae); //System.out.println("aec = " + aec); } /** * Test reversion. */ public void testReverse() { // rational numbers BigRational cf = new BigRational(99); // System.out.println("cf = " + cf); // polynomials over rational numbers GenPolynomialRing pf = new GenPolynomialRing(cf, rl); //System.out.println("pf = " + pf); GenPolynomial a = pf.random(kl, ll, el, q); //System.out.println("a = " + a); GenPolynomialRing pfr = pf.reverse(); GenPolynomialRing pfrr = pfr.reverse(); assertEquals("pf == pfrr", pf, pfrr); //System.out.println("pfr = " + pfr); GenPolynomial ar = a.reverse(pfr); GenPolynomial arr = ar.reverse(pfrr); assertEquals("a == arr", a, arr); //System.out.println("ar = " + ar); //System.out.println("arr = " + arr); } /** * Test accessors. */ public void testAccessors() { // rational numbers BigRational rf = new BigRational(); // System.out.println("rf = " + rf); // polynomials over rational numbers GenPolynomialRing pf = new GenPolynomialRing(rf, rl); // System.out.println("pf = " + pf); // test 1 GenPolynomial p = pf.getONE(); // System.out.println("p = " + p); ExpVector e = p.leadingExpVector(); BigRational c = p.leadingBaseCoefficient(); GenPolynomial f = new GenPolynomial(pf, c, e); assertEquals("1 == 1 ", p, f); GenPolynomial r = p.reductum(); assertTrue("red(1) == 0 ", r.isZERO()); // test 0 p = pf.getZERO(); // System.out.println("p = " + p); e = p.leadingExpVector(); c = p.leadingBaseCoefficient(); f = new GenPolynomial(pf, c, e); assertEquals("0 == 0 ", p, f); r = p.reductum(); assertTrue("red(0) == 0 ", r.isZERO()); // test random p = pf.random(kl, 2 * ll, el, q); // System.out.println("p = " + p); e = p.leadingExpVector(); c = p.leadingBaseCoefficient(); r = p.reductum(); f = new GenPolynomial(pf, c, e); f = r.sum(f); assertEquals("p == lm(f)+red(f) ", p, f); // test iteration over random GenPolynomial g; g = p; f = pf.getZERO(); while (!g.isZERO()) { e = g.leadingExpVector(); c = g.leadingBaseCoefficient(); //System.out.println("c e = " + c + " " + e); r = g.reductum(); f = f.sum(c, e); g = r; } assertEquals("p == lm(f)+lm(red(f))+... ", p, f); } /** * Test homogeneous. */ public void testHomogeneous() { // rational numbers BigRational rf = new BigRational(); // System.out.println("rf = " + rf); // polynomials over rational numbers GenPolynomialRing pf = new GenPolynomialRing(rf, 2); //rl); // System.out.println("pf = " + pf); // test 1 GenPolynomial p = pf.getONE(); // System.out.println("p = " + p); assertTrue("1 is homogeneous " + p, p.isHomogeneous()); // test 0 p = pf.getZERO(); // System.out.println("p = " + p); assertTrue("0 is homogeneous " + p, p.isHomogeneous()); // test random p = pf.random(kl, 2 * ll, el, q); //p = pf.random(kl,ll,el,q); //System.out.println("p = " + p); assertFalse("rnd is homogeneous " + p, p.isHomogeneous()); // make homogeneous GenPolynomialRing pfh = pf.extend(1); //System.out.println("pfh = " + pfh); // remove block order TermOrder to = new TermOrder(TermOrder.IGRLEX); pfh = new GenPolynomialRing(pfh, to); //System.out.println("pfh = " + pfh); GenPolynomial ph = p.homogenize(pfh); //System.out.println("ph = " + ph); assertTrue("ph is homogeneous " + ph, ph.isHomogeneous()); GenPolynomial ps = ph.deHomogenize(pf); //System.out.println("ps = " + ps); assertEquals("phs == p ", ps, p); // findbugs //System.out.println("p is homogeneous = " + p.isHomogeneous()); //System.out.println("ph is homogeneous = " + ph.isHomogeneous()); GenPolynomial s = pf.random(kl, ll, el, q); //System.out.println("s = " + s); assertFalse("rnd is homogeneous " + s, s.isHomogeneous()); GenPolynomial sh = s.homogenize(pfh); //System.out.println("sh = " + sh); assertTrue("sh is homogeneous " + sh, sh.isHomogeneous()); GenPolynomial ss = sh.deHomogenize(pf); //System.out.println("ss = " + ss); assertEquals("ss = s ", ss, s); GenPolynomial th = ph.multiply(sh); //System.out.println("th = " + th); assertTrue("th is homogeneous " + th, th.isHomogeneous()); GenPolynomial t = p.multiply(s); //System.out.println("t = " + t); GenPolynomial ts = th.deHomogenize(pf); //System.out.println("ts = " + ts); assertEquals("ts = t ", ts, t); } /** * Test iterators. */ public void testIterators() { // integers BigInteger rf = new BigInteger(); // System.out.println("rf = " + rf); // polynomials over integral numbers GenPolynomialRing pf = new GenPolynomialRing(rf, rl); // System.out.println("pf = " + pf); // random polynomial GenPolynomial p = pf.random(kl, 2 * ll, el, q); //System.out.println("p = " + p); // test monomials for (Monomial m : p) { //System.out.println("m = " + m); assertFalse("m.c == 0 ", m.coefficient().isZERO()); assertFalse("m.e < (0) ", m.exponent().signum() < 0); } // test exponents Iterator et = p.exponentIterator(); while (et.hasNext()) { ExpVector e = et.next(); //System.out.println("e = " + e); assertFalse("e < (0) ", e.signum() < 0); } // test coefficents Iterator ct = p.coefficientIterator(); while (ct.hasNext()) { BigInteger i = ct.next(); //System.out.println("i = " + i); assertFalse("i == 0 ", i.isZERO()); } } /** * Test coefficient map function. */ public void testMap() { // integers BigInteger rf = new BigInteger(); // System.out.println("rf = " + rf); // polynomials over integral numbers GenPolynomialRing pf = new GenPolynomialRing(rf, rl); // System.out.println("pf = " + pf); // random polynomial GenPolynomial p = pf.random(kl, 2 * ll, el, q); //System.out.println("p = " + p); // test times 1 GenPolynomial q; q = p.map(new Multiply(rf.getONE())); assertEquals("p == q ", p, q); // test times 0 q = p.map(new Multiply(rf.getZERO())); assertTrue("q == 0 ", q.isZERO()); // test times -1 q = p.map(new Multiply(rf.getONE().negate())); assertEquals("p == q ", p.negate(), q); } } /** * Internal scalar multiplication functor. */ class Multiply> implements UnaryFunctor { C x; public Multiply(C x) { this.x = x; } public C eval(C c) { return c.multiply(x); } } jas-2.5/trc/edu/jas/poly/LocalTest.java0000644000175000017500000001715611641660762020230 0ustar giovannigiovanni /* * $Id: LocalTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.arith.BigInteger; /** * Local tests with JUnit. * @author Heinz Kredel. */ public class LocalTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a LocalTest object. * @param name String. */ public LocalTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(LocalTest.class); return suite; } LocalRing fac; GenPolynomialRing pfac; LocalRing< GenPolynomial > mfac; Local< BigInteger > a; Local< BigInteger > b; Local< BigInteger > c; Local< BigInteger > d; Local< BigInteger > e; Local< GenPolynomial > ap; Local< GenPolynomial > bp; Local< GenPolynomial > cp; Local< GenPolynomial > dp; Local< GenPolynomial > ep; int rl = 1; int kl = 13; int ll = 5; int el = 2; float q = 0.3f; int il = 2; long p = 1152921504606846883L; // 2^60-93; protected void setUp() { a = b = c = d = e = null; ap = bp = cp = dp = ep = null; BigInteger cfac = new BigInteger(1); fac = new LocalRing( cfac, new BigInteger( p ) ); pfac = new GenPolynomialRing( new BigRational(1), 1 ); GenPolynomial mo = pfac.random(kl,ll,el,q); while ( mo.isConstant() ) { mo = pfac.random(kl,ll,el,q); } mfac = new LocalRing>( pfac, mo ); } protected void tearDown() { a = b = c = d = e = null; ap = bp = cp = dp = ep = null; fac = null; pfac = null; mfac = null; } /** * Test constructor for integer. * */ public void testIntConstruction() { c = fac.getONE(); //System.out.println("c = " + c); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); //System.out.println("d = " + d); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test constructor for polynomial. * */ public void testPolyConstruction() { cp = mfac.getONE(); assertTrue("isZERO( cp )", !cp.isZERO() ); assertTrue("isONE( cp )", cp.isONE() ); dp = mfac.getZERO(); assertTrue("isZERO( dp )", dp.isZERO() ); assertTrue("isONE( dp )", !dp.isONE() ); } /** * Test random integer. * */ public void testRandom() { for (int i = 0; i < 4; i++) { a = fac.random(kl*(i+1)); //a = fac.random(kl*(i+1), ll+i, el, q ); //System.out.println("a = " + a); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test random polynomial. * */ public void testPolyRandom() { for (int i = 0; i < 7; i++) { ap = mfac.random(kl+i); assertTrue(" not isZERO( ap"+i+" )", !ap.isZERO() ); assertTrue(" not isONE( ap"+i+" )", !ap.isONE() ); } } /** * Test integer addition. */ public void testIntAddition() { a = fac.random(kl); b = fac.random(kl); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a",c,d); c = fac.random(kl); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test polynomial addition. * */ public void testPolyAddition() { ap = mfac.random(kl); bp = mfac.random(kl); //System.out.println("a = " + a); //System.out.println("b = " + b); cp = ap.sum(bp); dp = cp.subtract(bp); assertEquals("a+b-b = a",ap,dp); cp = ap.sum(bp); dp = bp.sum(ap); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",cp,dp); cp = mfac.random(kl); dp = cp.sum( ap.sum(bp) ); ep = cp.sum( ap ).sum(bp); assertEquals("c+(a+b) = (c+a)+b",dp,ep); cp = ap.sum( mfac.getZERO() ); dp = ap.subtract( mfac.getZERO() ); assertEquals("a+0 = a-0",cp,dp); cp = mfac.getZERO().sum( ap ); dp = mfac.getZERO().subtract( ap.negate() ); assertEquals("0+a = 0+(-a)",cp,dp); } /** * Test integer multiplication. */ public void testIntMultiplication() { a = fac.random(kl); b = fac.random(kl); if ( a.isZERO() || b.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(kl); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",d.isONE()); } } /** * Test polynomial multiplication. * */ public void testPolyMultiplication() { ap = mfac.random(kl); bp = mfac.random(kl); if ( ap.isZERO() || bp.isZERO() ) { return; } assertTrue("not isZERO( a )", !ap.isZERO() ); assertTrue("not isZERO( b )", !bp.isZERO() ); cp = bp.multiply(ap); dp = ap.multiply(bp); assertTrue("not isZERO( c )", !cp.isZERO() ); assertTrue("not isZERO( d )", !dp.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); ep = dp.subtract(cp); assertTrue("isZERO( a*b-b*a ) " + ep, ep.isZERO() ); assertTrue("a*b = b*a", cp.equals(dp) ); assertEquals("a*b = b*a",cp,dp); cp = mfac.random(kl); //System.out.println("c = " + c); dp = ap.multiply( bp.multiply(cp) ); ep = (ap.multiply(bp)).multiply(cp); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",dp,ep); assertTrue("a(bc) = (ab)c", dp.equals(ep) ); cp = ap.multiply( mfac.getONE() ); dp = mfac.getONE().multiply( ap ); assertEquals("a*1 = 1*a",cp,dp); if ( ap.isUnit() ) { cp = ap.inverse(); dp = cp.multiply(ap); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",dp.isONE()); } } } jas-2.5/trc/edu/jas/poly/QuotientTest.java0000644000175000017500000001711411641660762021000 0ustar giovannigiovanni /* * $Id: QuotientTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; //import edu.jas.arith.BigRational; import edu.jas.arith.BigInteger; //import edu.jas.structure.RingElem; /** * Quotient tests with JUnit. * @author Heinz Kredel. */ public class QuotientTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a QuotientTest object. * @param name String. */ public QuotientTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(QuotientTest.class); return suite; } QuotientRing fac; GenPolynomialRing pfac; QuotientRing< GenPolynomial > mfac; Quotient< BigInteger > a; Quotient< BigInteger > b; Quotient< BigInteger > c; Quotient< BigInteger > d; Quotient< BigInteger > e; Quotient< GenPolynomial > ap; Quotient< GenPolynomial > bp; Quotient< GenPolynomial > cp; Quotient< GenPolynomial > dp; Quotient< GenPolynomial > ep; int rl = 2; int kl = 17; int ll = 3; //6; int el = 2; float q = 0.4f; protected void setUp() { a = b = c = d = e = null; ap = bp = cp = dp = ep = null; fac = new QuotientRing( new BigInteger(1) ); pfac = new GenPolynomialRing( new BigInteger(1), 1 ); mfac = new QuotientRing>( pfac ); } protected void tearDown() { a = b = c = d = e = null; ap = bp = cp = dp = ep = null; fac = null; pfac = null; mfac = null; } /** * Test constructor for integer. * */ public void testIntConstruction() { c = fac.getONE(); //System.out.println("c = " + c); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); //System.out.println("d = " + d); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test constructor for polynomial. * */ public void testPolyConstruction() { cp = mfac.getONE(); assertTrue("isZERO( cp )", !cp.isZERO() ); assertTrue("isONE( cp )", cp.isONE() ); dp = mfac.getZERO(); assertTrue("isZERO( dp )", dp.isZERO() ); assertTrue("isONE( dp )", !dp.isONE() ); } /** * Test random integer. * */ public void testIntRandom() { for (int i = 0; i < 7; i++) { a = fac.random(kl*(i+1)); //a = fac.random(kl*(i+1), ll+2+2*i, el, q ); //System.out.println("a = " + a); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test random polynomial. * */ public void testPolyRandom() { for (int i = 0; i < 7; i++) { ap = mfac.random(kl+i); assertTrue(" not isZERO( ap"+i+" )", !ap.isZERO() ); assertTrue(" not isONE( ap"+i+" )", !ap.isONE() ); } } /** * Test integer addition. * */ public void testIntAddition() { a = fac.random(kl); b = fac.random(kl); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",c,d); c = fac.random(kl); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test polynomial addition. * */ public void testPolyAddition() { ap = mfac.random(kl); bp = mfac.random(kl); //System.out.println("a = " + a); //System.out.println("b = " + b); cp = ap.sum(bp); dp = cp.subtract(bp); assertEquals("a+b-b = a",ap,dp); cp = ap.sum(bp); dp = bp.sum(ap); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",cp,dp); cp = mfac.random(kl); dp = cp.sum( ap.sum(bp) ); ep = cp.sum( ap ).sum(bp); assertEquals("c+(a+b) = (c+a)+b",dp,ep); cp = ap.sum( mfac.getZERO() ); dp = ap.subtract( mfac.getZERO() ); assertEquals("a+0 = a-0",cp,dp); cp = mfac.getZERO().sum( ap ); dp = mfac.getZERO().subtract( ap.negate() ); assertEquals("0+a = 0+(-a)",cp,dp); } /** * Test integer multiplication. * */ public void testIntMultiplication() { a = fac.random(kl); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(kl); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(kl); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",d.isONE()); } } /** * Test polynomial multiplication. * */ public void testPolyMultiplication() { ap = mfac.random(kl); assertTrue("not isZERO( a )", !ap.isZERO() ); bp = mfac.random(kl); assertTrue("not isZERO( b )", !bp.isZERO() ); cp = bp.multiply(ap); dp = ap.multiply(bp); assertTrue("not isZERO( c )", !cp.isZERO() ); assertTrue("not isZERO( d )", !dp.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); ep = dp.subtract(cp); assertTrue("isZERO( a*b-b*a ) " + ep, ep.isZERO() ); assertTrue("a*b = b*a", cp.equals(dp) ); assertEquals("a*b = b*a",cp,dp); cp = mfac.random(kl); //System.out.println("c = " + c); dp = ap.multiply( bp.multiply(cp) ); ep = (ap.multiply(bp)).multiply(cp); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",dp,ep); assertTrue("a(bc) = (ab)c", dp.equals(ep) ); cp = ap.multiply( mfac.getONE() ); dp = mfac.getONE().multiply( ap ); assertEquals("a*1 = 1*a",cp,dp); if ( ap.isUnit() ) { cp = ap.inverse(); dp = cp.multiply(ap); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",dp.isONE()); } } } jas-2.5/trc/edu/jas/poly/ExpVectorTest.java0000644000175000017500000004347311641660762021116 0ustar giovannigiovanni/* * $Id: ExpVectorTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import java.util.Arrays; import java.util.List; import java.util.ArrayList; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; /** * ExpVector tests with JUnit. * Tests arithmetic operations, for comparison tests @see TermOrderTest.java * @author Heinz Kredel. */ public class ExpVectorTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ExpVectorTest object. * @param name String. */ public ExpVectorTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(ExpVectorTest.class); return suite; } //private final static int bitlen = 100; ExpVector a; ExpVector b; ExpVector c; ExpVector d; protected void setUp() { a = b = c = d = null; } protected void tearDown() { a = b = c = d = null; } /** * Test constructor and toString. * */ public void testConstructor() { a = ExpVector.create( 0 ); b = ExpVector.create( 0 ); assertEquals("() = ()",a,b); assertEquals("length( () ) = 0",a.length(),0); assertTrue("isZERO( () )",a.isZERO()); a = ExpVector.create( 10 ); b = ExpVector.create( 10 ); assertEquals("10e = 10e",a,b); assertEquals("length( 10e ) = 10",a.length(),10); assertTrue("isZERO( ( 10e ) )",a.isZERO()); String s = "(0,0,0,0,0,0,0,0,0,0)"; a = ExpVector.create( s ); String t = a.toString().substring(0,s.length()); assertEquals("stringConstr = toString",s,t); assertTrue("isZERO( ( 10e ) )",a.isZERO()); } /** * Test random integer. * */ public void testRandom() { float q = (float) 0.2; a = ExpVector.EVRAND(5,10,q); String s = a.toString(); if ( s.indexOf(":") >= 0 ) { s = s.substring(0,s.indexOf(":")); } b = ExpVector.create( s ); assertEquals("a == b", true, a.equals(b) ); c = ExpVector.EVDIF(b,a); assertTrue("a-b = 0",c.isZERO()); } /** * Test addition. * */ public void testAddition() { float q = (float) 0.2; a = ExpVector.EVRAND(5,10,q); b = ExpVector.EVSUM(a,a); c = ExpVector.EVDIF(b,a); assertEquals("a+a-a = a",c,a); assertTrue("a+a-a = a", c.equals(a) ); boolean t; t = ExpVector.EVMT(b,a); assertTrue("a | a+a", t ); a = ExpVector.EVRAND(5,10,q); b = ExpVector.EVRAND(5,10,q); c = ExpVector.EVSUM(a,b); d = ExpVector.EVSUM(b,a); assertTrue("a+b = b+a", c.equals(d) ); } /** * Test lcm. * */ public void testLcm() { float q = (float) 0.2; a = ExpVector.EVRAND(5,10,q); b = ExpVector.EVRAND(5,10,q); c = ExpVector.EVLCM(a,b); d = ExpVector.EVLCM(b,a); assertTrue("lcm(a,b) = lcm(b,a)", c.equals(d) ); assertTrue("a | lcm(a,b)", ExpVector.EVMT(c,a) ); assertTrue("b | lcm(a,b)", ExpVector.EVMT(c,b) ); d = ExpVector.EVDIF(c,a); assertTrue("sign(lcm(a,b)-a) >= 0", ExpVector.EVSIGN(d) >= 0 ); d = ExpVector.EVDIF(c,b); assertTrue("sign(lcm(a,b)-b) >= 0", ExpVector.EVSIGN(d) >= 0 ); } /** * Test tdeg. * */ public void testTdeg() { a = ExpVector.create( 100 ); assertTrue("tdeg(a) = 0", ExpVector.EVTDEG(a) == 0 ); float q = (float) 0.2; a = ExpVector.EVRAND(5,10,q); b = ExpVector.EVRAND(5,10,q); assertTrue("tdeg(a) >= 0", ExpVector.EVTDEG(a) >= 0 ); assertTrue("tdeg(b) >= 0", ExpVector.EVTDEG(b) >= 0 ); c = ExpVector.EVSUM(a,b); assertTrue("tdeg(a+b) >= tdeg(a)", ExpVector.EVTDEG(c) >= ExpVector.EVTDEG(a) ); assertTrue("tdeg(a+b) >= tdeg(b)", ExpVector.EVTDEG(c) >= ExpVector.EVTDEG(b) ); c = ExpVector.EVLCM(a,b); assertTrue("tdeg(lcm(a,b)) >= tdeg(a)", ExpVector.EVTDEG(c) >= ExpVector.EVTDEG(a) ); assertTrue("tdeg(lcm(a,b)) >= tdeg(b)", ExpVector.EVTDEG(c) >= ExpVector.EVTDEG(b) ); } /** * Test weighted. * */ public void testWeightdeg() { a = ExpVector.create( 100 ); assertTrue("tdeg(a) = 0", ExpVector.EVTDEG(a) == 0 ); assertTrue("wdeg(a) = 0", ExpVector.EVWDEG(null,a) == 0 ); float q = (float) 0.2; a = ExpVector.EVRAND(5,10,q); b = ExpVector.EVRAND(5,10,q); long [][] w = new long [][] { new long[] { 1l, 1l, 1l, 1l, 1l } }; assertTrue("tdeg(a) >= 0", ExpVector.EVTDEG(a) >= 0 ); assertTrue("tdeg(b) >= 0", ExpVector.EVTDEG(b) >= 0 ); assertTrue("wdeg(a) >= 0", ExpVector.EVWDEG(w,a) >= 0 ); assertTrue("wdeg(b) >= 0", ExpVector.EVWDEG(w,b) >= 0 ); assertEquals("tdeg(a) == wdeg(a)", ExpVector.EVTDEG(a), ExpVector.EVWDEG(w,a) ); assertEquals("tdeg(b) == wdeg(b)", ExpVector.EVTDEG(b), ExpVector.EVWDEG(w,b) ); c = ExpVector.EVSUM(a,b); assertTrue("wdeg(a+b) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(a+b) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); c = ExpVector.EVLCM(a,b); assertTrue("wdeg(lcm(a,b)) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(lcm(a,b)) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); w = new long [][] { new long[] { 10l, 1l, 3l, 9l, 100l } }; assertTrue("tdeg(a) >= 0", ExpVector.EVTDEG(a) >= 0 ); assertTrue("tdeg(b) >= 0", ExpVector.EVTDEG(b) >= 0 ); assertTrue("wdeg(a) >= 0", ExpVector.EVWDEG(w,a) >= 0 ); assertTrue("wdeg(b) >= 0", ExpVector.EVWDEG(w,b) >= 0 ); assertTrue("tdeg(a) <= wdeg(a)", ExpVector.EVTDEG(a) <= ExpVector.EVWDEG(w,a) ); assertTrue("tdeg(b) <= wdeg(b)", ExpVector.EVTDEG(b) <= ExpVector.EVWDEG(w,b) ); c = ExpVector.EVSUM(a,b); assertTrue("wdeg(a+b) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(a+b) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); c = ExpVector.EVLCM(a,b); assertTrue("wdeg(lcm(a,b)) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(lcm(a,b)) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); w = new long [][] { new long[] { 10l, 1l, 3l, 9l, 100l }, new long[] { 1l, 1l, 1l, 1l, 1l } }; assertTrue("tdeg(a) >= 0", ExpVector.EVTDEG(a) >= 0 ); assertTrue("tdeg(b) >= 0", ExpVector.EVTDEG(b) >= 0 ); assertTrue("wdeg(a) >= 0", ExpVector.EVWDEG(w,a) >= 0 ); assertTrue("wdeg(b) >= 0", ExpVector.EVWDEG(w,b) >= 0 ); assertTrue("tdeg(a) <= wdeg(a)", ExpVector.EVTDEG(a) <= ExpVector.EVWDEG(w,a) ); assertTrue("tdeg(b) <= wdeg(b)", ExpVector.EVTDEG(b) <= ExpVector.EVWDEG(w,b) ); c = ExpVector.EVSUM(a,b); assertTrue("wdeg(a+b) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(a+b) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); c = ExpVector.EVLCM(a,b); assertTrue("wdeg(lcm(a,b)) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(lcm(a,b)) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); } /** * Test dependency on variables. * */ public void testDependency() { int[] exp; int[] dep; a = ExpVector.create(10,5,2l); exp = new int[] { 5 }; dep = ExpVector.EVDOV(a); assertTrue("[5] = [5]",Arrays.equals(exp,dep)); b = ExpVector.create(10,3,9l); exp = new int[] { 3 }; dep = ExpVector.EVDOV(b); assertTrue("[3] = [3]",Arrays.equals(exp,dep)); c = ExpVector.EVSUM(a,b); exp = new int[] { 3, 5 }; dep = ExpVector.EVDOV(c); assertTrue("[3,5] = [3,5] "+Arrays.toString(exp)+","+Arrays.toString(dep),Arrays.equals(exp,dep)); b = ExpVector.create(10); exp = new int[] { }; dep = ExpVector.EVDOV(b); assertTrue("[] = []",Arrays.equals(exp,dep)); b = ExpVector.create(0); exp = new int[] { }; dep = ExpVector.EVDOV(b); assertTrue("[] = []",Arrays.equals(exp,dep)); b = ExpVector.create(1,0,1l); exp = new int[] { 0 }; dep = ExpVector.EVDOV(b); assertTrue("[0] = [0]",Arrays.equals(exp,dep)); } /** * Test random exp vector 2. * */ public void testRandom2() { float q = (float) 0.2; a = ExpVector.EVRAND(5,10,q); b = ExpVector.create( "" + a ); assertEquals("a == b", true, a.equals(b) ); c = b.subtract(a); assertTrue("a-b = 0",c.isZERO()); } /** * Test addition. * */ public void testAddition2() { float q = (float) 0.2; a = ExpVector.EVRAND(5,10,q); b = a.sum(a); c = b.subtract(a); assertEquals("a+a-a = a",c,a); assertTrue("a+a-a = a", c.equals(a) ); boolean t; t = b.multipleOf(a); assertTrue("a | a+a", t ); a = ExpVector.EVRAND(5,10,q); b = ExpVector.EVRAND(5,10,q); c = a.sum(b); d = b.sum(a); assertTrue("a+b = b+a", c.equals(d) ); } /** * Test lcm. * */ public void testLcm2() { float q = (float) 0.2; a = ExpVector.EVRAND(5,10,q); b = ExpVector.EVRAND(5,10,q); c = a.lcm(b); d = b.lcm(a); assertTrue("lcm(a,b) = lcm(b,a)", c.equals(d) ); assertTrue("a | lcm(a,b)", c.multipleOf(a) ); assertTrue("b | lcm(a,b)", c.multipleOf(b) ); d = c.subtract(a); assertTrue("sign(lcm(a,b)-a) >= 0", d.signum() >= 0 ); d = c.subtract(b); assertTrue("sign(lcm(a,b)-b) >= 0", d.signum() >= 0 ); } /** * Test tdeg. * */ public void testTdeg2() { a = ExpVector.create( 100 ); assertTrue("tdeg(a) = 0", ExpVector.EVTDEG(a) == 0 ); float q = (float) 0.2; a = ExpVector.EVRAND(5,10,q); b = ExpVector.EVRAND(5,10,q); assertTrue("tdeg(a) >= 0", ExpVector.EVTDEG(a) >= 0 ); assertTrue("tdeg(b) >= 0", ExpVector.EVTDEG(b) >= 0 ); c = a.sum(b); assertTrue("tdeg(a+b) >= tdeg(a)", ExpVector.EVTDEG(c) >= ExpVector.EVTDEG(a) ); assertTrue("tdeg(a+b) >= tdeg(b)", ExpVector.EVTDEG(c) >= ExpVector.EVTDEG(b) ); c = a.lcm(b); assertTrue("tdeg(lcm(a,b)) >= tdeg(a)", ExpVector.EVTDEG(c) >= ExpVector.EVTDEG(a) ); assertTrue("tdeg(lcm(a,b)) >= tdeg(b)", ExpVector.EVTDEG(c) >= ExpVector.EVTDEG(b) ); } /** * Test weighted. * */ public void testWeightdeg2() { a = ExpVector.create( 100 ); assertTrue("tdeg(a) = 0", ExpVector.EVTDEG(a) == 0 ); assertTrue("wdeg(a) = 0", ExpVector.EVWDEG(null,a) == 0 ); float q = (float) 0.2; a = ExpVector.EVRAND(5,10,q); b = ExpVector.EVRAND(5,10,q); long [][] w = new long [][] { new long[] { 1l, 1l, 1l, 1l, 1l } }; assertTrue("tdeg(a) >= 0", ExpVector.EVTDEG(a) >= 0 ); assertTrue("tdeg(b) >= 0", ExpVector.EVTDEG(b) >= 0 ); assertTrue("wdeg(a) >= 0", ExpVector.EVWDEG(w,a) >= 0 ); assertTrue("wdeg(b) >= 0", ExpVector.EVWDEG(w,b) >= 0 ); assertEquals("tdeg(a) == wdeg(a)", ExpVector.EVTDEG(a), ExpVector.EVWDEG(w,a) ); assertEquals("tdeg(b) == wdeg(b)", ExpVector.EVTDEG(b), ExpVector.EVWDEG(w,b) ); c = a.sum(b); assertTrue("wdeg(a+b) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(a+b) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); c = a.lcm(b); assertTrue("wdeg(lcm(a,b)) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(lcm(a,b)) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); w = new long [][] { new long[] { 10l, 1l, 3l, 9l, 100l } }; assertTrue("tdeg(a) >= 0", ExpVector.EVTDEG(a) >= 0 ); assertTrue("tdeg(b) >= 0", ExpVector.EVTDEG(b) >= 0 ); assertTrue("wdeg(a) >= 0", ExpVector.EVWDEG(w,a) >= 0 ); assertTrue("wdeg(b) >= 0", ExpVector.EVWDEG(w,b) >= 0 ); assertTrue("tdeg(a) <= wdeg(a)", ExpVector.EVTDEG(a) <= ExpVector.EVWDEG(w,a) ); assertTrue("tdeg(b) <= wdeg(b)", ExpVector.EVTDEG(b) <= ExpVector.EVWDEG(w,b) ); c = a.sum(b); assertTrue("wdeg(a+b) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(a+b) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); c = a.lcm(b); assertTrue("wdeg(lcm(a,b)) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(lcm(a,b)) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); w = new long [][] { new long[] { 10l, 1l, 3l, 9l, 100l }, new long[] { 1l, 1l, 1l, 1l, 1l } }; assertTrue("tdeg(a) >= 0", ExpVector.EVTDEG(a) >= 0 ); assertTrue("tdeg(b) >= 0", ExpVector.EVTDEG(b) >= 0 ); assertTrue("wdeg(a) >= 0", ExpVector.EVWDEG(w,a) >= 0 ); assertTrue("wdeg(b) >= 0", ExpVector.EVWDEG(w,b) >= 0 ); assertTrue("tdeg(a) <= wdeg(a)", ExpVector.EVTDEG(a) <= ExpVector.EVWDEG(w,a) ); assertTrue("tdeg(b) <= wdeg(b)", ExpVector.EVTDEG(b) <= ExpVector.EVWDEG(w,b) ); c = a.sum(b); assertTrue("wdeg(a+b) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(a+b) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); c = a.lcm(b); assertTrue("wdeg(lcm(a,b)) >= wdeg(a)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,a) ); assertTrue("wdeg(lcm(a,b)) >= wdeg(b)", ExpVector.EVWDEG(w,c) >= ExpVector.EVWDEG(w,b) ); } /** * Test dependency on variables. * */ public void testDependency2() { int[] exp; int[] dep; a = ExpVector.create(10,5,2l); exp = new int[] { 5 }; dep = a.dependencyOnVariables(); assertTrue("[5] = [5]",Arrays.equals(exp,dep)); b = ExpVector.create(10,3,9l); exp = new int[] { 3 }; dep = b.dependencyOnVariables(); assertTrue("[3] = [3]",Arrays.equals(exp,dep)); c = a.sum(b); exp = new int[] { 3, 5 }; dep = c.dependencyOnVariables(); assertTrue("[3,5] = [3,5] "+Arrays.toString(exp)+","+Arrays.toString(dep),Arrays.equals(exp,dep)); b = ExpVector.create(10); exp = new int[] { }; dep = b.dependencyOnVariables(); assertTrue("[] = []",Arrays.equals(exp,dep)); b = ExpVector.create(0); exp = new int[] { }; dep = b.dependencyOnVariables(); assertTrue("[] = []",Arrays.equals(exp,dep)); b = ExpVector.create(1,0,1l); exp = new int[] { 0 }; dep = b.dependencyOnVariables(); assertTrue("[0] = [0]",Arrays.equals(exp,dep)); } /** * Test evaluation. * */ public void testEvaluation() { float q = (float) 0.2; int rl = 5; a = ExpVector.EVRAND(rl,10,q); b = ExpVector.EVRAND(rl,10,q); BigInteger fv = new BigInteger(0); List v = new ArrayList(a.length()); for ( int i = 0; i < a.length(); i++ ) { v.add( fv.random(4) ); } BigInteger av = a.evaluate(fv,v); BigInteger bv = b.evaluate(fv,v); c = a.sum(b); BigInteger cv = c.evaluate(fv,v); BigInteger dv = av.multiply(bv); assertEquals("a(v)*b(v) = (a+b)(v) ", cv, dv); c = ExpVector.create(rl); cv = c.evaluate(fv,v); dv = fv.getONE(); assertEquals("0(v) = 1 ", cv, dv); v.clear(); for ( int i = 0; i < a.length(); i++ ) { v.add( fv.getZERO() ); } cv = c.evaluate(fv,v); dv = fv.getONE(); assertEquals("0(0) = 1 ", cv, dv); av = a.evaluate(fv,v); if ( a.isZERO() ) { dv = fv.getONE(); assertEquals("0(0) = 1 ", av, dv); } else { dv = fv.getZERO(); assertEquals("a(0) = 0 ", av, dv); } } } jas-2.5/trc/edu/jas/poly/RelationTableTest.java0000644000175000017500000002432211641660762021714 0ustar giovannigiovanni/* * $Id: RelationTableTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; //import edu.jas.poly.RelationTable; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; /** * RelationTable tests with JUnit. * @author Heinz Kredel. */ public class RelationTableTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a RelationTableTest object. * @param name String. */ public RelationTableTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(RelationTableTest.class); return suite; } RelationTable table; GenSolvablePolynomialRing ring; int rl = 5; protected void setUp() { BigRational cfac = new BigRational(1); ring = new GenSolvablePolynomialRing(cfac,rl); table = ring.table; // non null } protected void tearDown() { table = null; ring = null; } /** * Test constructor and toString. * */ public void testConstructor() { table = new RelationTable(ring); assertEquals("size() = 0",0,table.size()); assertEquals("ring == table.ring",ring,table.ring); String s = "RelationTable[]"; String t = table.toString(); assertEquals("RelationTable[]",s,t); } /** * Test update one key. * */ public void testUpdateOneKey() { table = ring.table; assertEquals("size() = 0",0,table.size()); //ExpVector z = ring.evzero; ExpVector e = ExpVector.create(rl,2,1); ExpVector f = ExpVector.create(rl,3,1); // insert in empty ExpVector ef = e.sum(f); GenSolvablePolynomial a = ring.getONE(); GenSolvablePolynomial b = ring.getONE().multiply(ef); GenSolvablePolynomial rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 1",1,table.size()); e = ExpVector.create(rl,2,2); f = ExpVector.create(rl,3,1); // insert in beginning ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 2",2,table.size()); e = ExpVector.create(rl,2,2); f = ExpVector.create(rl,3,2); ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 3",3,table.size()); e = ExpVector.create(rl,2,2); f = ExpVector.create(rl,3,4); ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 4",4,table.size()); e = ExpVector.create(rl,2,2); f = ExpVector.create(rl,3,3); // insert in middle ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 5",5,table.size()); //System.out.println("table = " + table); } /** * Test update more keys. * */ public void testUpdateKeys() { table = ring.table; assertEquals("size() = 0",0,table.size()); //ExpVector z = ring.evzero; ExpVector e = ExpVector.create(rl,2,1); ExpVector f = ExpVector.create(rl,3,1); // insert in empty ExpVector ef = e.sum(f); GenSolvablePolynomial a = ring.getONE(); GenSolvablePolynomial b = ring.getONE().multiply(ef); GenSolvablePolynomial rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 1",1,table.size()); e = ExpVector.create(rl,0,1); f = ExpVector.create(rl,2,1); ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 2",2,table.size()); e = ExpVector.create(rl,2,1); f = ExpVector.create(rl,4,1); ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 3",3,table.size()); //System.out.println("table = " + table); } /** * Test lookup one key. * */ public void testLookupOneKey() { table = ring.table; assertEquals("size() = 0",0,table.size()); //ExpVector z = ring.evzero; ExpVector e = ExpVector.create(rl,2,1); ExpVector f = ExpVector.create(rl,3,1); // insert in empty ExpVector ef = e.sum(f); GenSolvablePolynomial a = ring.getONE(); GenSolvablePolynomial b = ring.getONE().multiply(ef); GenSolvablePolynomial rel = (GenSolvablePolynomial)a.sum(b); GenSolvablePolynomial r1 = rel; table.update(e,f,rel); assertEquals("size() = 1",1,table.size()); TableRelation r = table.lookup(e,f); //System.out.println("relation = " + r); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = p",rel,r.p); e = ExpVector.create(rl,2,2); f = ExpVector.create(rl,3,1); // insert in beginning ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 2",2,table.size()); r = table.lookup(e,f); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = p",rel,r.p); e = ExpVector.create(rl,2,2); f = ExpVector.create(rl,3,2); ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 3",3,table.size()); r = table.lookup(e,f); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = p",rel,r.p); e = ExpVector.create(rl,2,2); f = ExpVector.create(rl,3,4); ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 4",4,table.size()); r = table.lookup(e,f); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = p",rel,r.p); e = ExpVector.create(rl,2,2); f = ExpVector.create(rl,3,3); // insert in middle ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 5",5,table.size()); r = table.lookup(e,f); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = p",rel,r.p); // lookup only e = ExpVector.create(rl,2,1); f = ExpVector.create(rl,3,1); r = table.lookup(e,f); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = p",r1,r.p); //System.out.println("table = " + table); } /** * Test lookup keys. * */ public void testLookupKeys() { table = ring.table; assertEquals("size() = 0",0,table.size()); //ExpVector z = ring.evzero; ExpVector e = ExpVector.create(rl,2,1); ExpVector f = ExpVector.create(rl,3,1); ExpVector ef = e.sum(f); GenSolvablePolynomial a = ring.getONE(); GenSolvablePolynomial b = ring.getONE().multiply(ef); GenSolvablePolynomial rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 1",1,table.size()); TableRelation r = table.lookup(e,f); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = p",rel,r.p); e = ExpVector.create(rl,0,1); f = ExpVector.create(rl,2,1); ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 2",2,table.size()); r = table.lookup(e,f); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = p",rel,r.p); e = ExpVector.create(rl,2,1); f = ExpVector.create(rl,4,1); ef = e.sum(f); b = ring.getONE().multiply(ef); rel = (GenSolvablePolynomial)a.sum(b); table.update(e,f,rel); assertEquals("size() = 3",3,table.size()); r = table.lookup(e,f); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = p",rel,r.p); //System.out.println("table = " + table); } /** * Test lookup symmetric products. * */ public void testSymmetric() { table = ring.table; assertEquals("size() = 0",0,table.size()); //ExpVector z = ring.evzero; ExpVector e = ExpVector.create(rl,2,1); ExpVector f = ExpVector.create(rl,3,1); ExpVector ef = e.sum(f); //GenSolvablePolynomial a = ring.getONE(); GenSolvablePolynomial b = ring.getONE().multiply(ef); //GenSolvablePolynomial rel // = (GenSolvablePolynomial)a.add(b); TableRelation r = table.lookup(e,f); //System.out.println("relation = " + r); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = b",b,r.p); e = ExpVector.create(rl,0,1); f = ExpVector.create(rl,2,1); ef = e.sum(f); b = ring.getONE().multiply(ef); r = table.lookup(e,f); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = b",b,r.p); e = ExpVector.create(rl,2,1); f = ExpVector.create(rl,4,1); ef = e.sum(f); b = ring.getONE().multiply(ef); r = table.lookup(e,f); assertEquals("e = e",null,r.e); assertEquals("f = f",null,r.f); assertEquals("p = b",b,r.p); assertEquals("size() = 0",0,table.size()); //System.out.println("table = " + table); } } jas-2.5/trc/edu/jas/poly/SolvableModuleListTest.java0000644000175000017500000002402611641660762022741 0ustar giovannigiovanni/* * $Id: SolvableModuleListTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.ArrayList; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; //import edu.jas.structure.RingElem; import edu.jas.arith.BigRational; //import edu.jas.poly.GenPolynomialRing; /** * SolvableModuleList tests using JUnit. * @author Heinz Kredel. */ public class SolvableModuleListTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a SolvableModuleListTest object. * @param name String. */ public SolvableModuleListTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(SolvableModuleListTest.class); return suite; } //private final static int bitlen = 100; ModuleList m; PolynomialList p; GenSolvablePolynomial a; GenSolvablePolynomial b; GenSolvablePolynomial c; GenSolvablePolynomial d; GenSolvablePolynomial e; BigRational cfac; GenSolvablePolynomialRing pfac; int rl = 4; int kl = 4; int ll = 4; int el = 5; float q = 0.5f; protected void setUp() { a = b = c = d = e = null; cfac = new BigRational(1); TermOrder tord = new TermOrder(); pfac = new GenSolvablePolynomialRing(cfac,rl,tord); m = null; p = null; } protected void tearDown() { a = b = c = d = e = null; m = null; p = null; } /** * Test constructor and toString. * */ public void testConstructor() { p = new PolynomialList(pfac,(List>)null); assertTrue("p = 0", p.list == null); m = new ModuleList(pfac,(List>>)null); assertTrue("m = 0", m.list == null); } /** * Test polynomial list. * */ public void testPolynomialList() { List> l = new ArrayList>(); for (int i = 0; i < 7; i++) { a = pfac.random(kl, ll+i, el, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); l.add( a ); } p = new PolynomialList(pfac,l); //System.out.println("p = "+p); assertTrue("p == p", p.equals(p) ); assertEquals("p.length", 7, p.list.size() ); } /** * Test module list. * */ public void testModuleList() { List>> l = new ArrayList>>(); for (int i = 0; i < 4; i++) { List> r = new ArrayList>(); for ( int j = 0; j < 3; j++ ) { a = pfac.random(kl, ll, el, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); r.add( a ); } l.add( r ); } m = new ModuleList(pfac,l); //System.out.println("m = "+m); assertTrue("m == m", m.equals(m) ); assertEquals("m.length", 4, m.list.size() ); } /** * Test module and polynomial list. * */ public void testModulePolynomialList() { List>> l = new ArrayList>>(); for (int i = 0; i < 4; i++) { List> r = new ArrayList>(); for ( int j = 0; j < 3; j++ ) { a = pfac.random(kl, ll, el, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); r.add( a ); } l.add( r ); } m = new ModuleList(pfac,l); //System.out.println("m = "+m); assertTrue("m == m", m.equals(m) ); assertEquals("m.length", 4, m.list.size() ); p = m.getPolynomialList(); //System.out.println("p = "+p); assertTrue("p == p", p.equals(p) ); assertEquals("p.length", 4, p.list.size() ); } /** * Test module and polynomial and module list. * */ public void testModulePolynomialModuleList() { List>> l = new ArrayList>>(); for (int i = 0; i < 4; i++) { List> r = new ArrayList>(); for ( int j = 0; j < 3; j++ ) { a = pfac.random(kl, ll, el, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); r.add( a ); } l.add( r ); } m = new ModuleList(pfac,l); //System.out.println("m = "+m); assertTrue("m == m", m.equals(m) ); assertEquals("m.length", 4, m.list.size() ); p = m.getPolynomialList(); //System.out.println("p = "+p); assertTrue("p == p", p.equals(p) ); assertEquals("p.length", 4, p.list.size() ); ModuleList m2 = null; m2 = p.getModuleList( 3 ); //System.out.println("m2 = "+m2); assertTrue("m2 == m2", m2.equals(m2) ); assertEquals("m2.length", 4, m2.list.size() ); assertTrue("m == m2", m.equals(m2) ); } /** * Test module and polynomial and module and polynomial list. * */ public void testModulePolynomialModuleListPolynomial() { List>> l = new ArrayList>>(); for (int i = 0; i < 4; i++) { List> r = new ArrayList>(); for ( int j = 0; j < 3; j++ ) { a = pfac.random(kl, ll, el, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); r.add( a ); } l.add( r ); } m = new ModuleList(pfac,l); //System.out.println("m = "+m); assertTrue("m == m", m.equals(m) ); assertEquals("m.length", 4, m.list.size() ); p = m.getPolynomialList(); //System.out.println("p = "+p); assertTrue("p == p", p.equals(p) ); assertEquals("p.length", 4, p.list.size() ); ModuleList m2 = null; m2 = p.getModuleList( 3 ); //System.out.println("m2 = "+m2); assertTrue("m2 == m2", m2.equals(m2) ); assertEquals("m2.length", 4, m2.list.size() ); assertTrue("m == m2", m.equals(m2) ); PolynomialList p2 = null; p2 = m2.getPolynomialList(); //System.out.println("p2 = "+p2); assertTrue("p2 == p2", p2.equals(p2) ); assertEquals("p2.length", 4, p2.list.size() ); assertTrue("p == p2", p.list.equals(p2.list) ); } /** * Test module and polynomial and module and polynomial list * with WeylRelations. * */ public void testWeylModulePolynomialModuleListPolynomial() { int rloc = 4; pfac = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(pfac); wl.generate(); RelationTable table1 = pfac.table; RelationTable table2 = null; RelationTable table3 = null; RelationTable table4 = null; RelationTable table5 = null; //System.out.println("table 1 = " + table1); //System.out.println("ring = " + ring); List>> l = new ArrayList>>(); for (int i = 0; i < 4; i++) { List> r = new ArrayList>(); for ( int j = 0; j < 3; j++ ) { a = pfac.random(kl, ll, el, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); r.add( a ); } l.add( r ); } m = new ModuleList(pfac,l); //System.out.println("m = "+m); assertTrue("m == m", m.equals(m) ); assertEquals("m.length", 4, m.list.size() ); table2 = ((GenSolvablePolynomialRing)m.ring).table; //System.out.println("table 2 = " + table2); assertEquals("table1 == table2", table1, table2 ); p = m.getPolynomialList(); //System.out.println("p = "+p); assertTrue("p == p", p.equals(p) ); assertEquals("p.length", 4, p.list.size() ); table3 = ((GenSolvablePolynomialRing)p.ring).table; //System.out.println("table 3 = " + table3); ModuleList m2 = null; m2 = p.getModuleList( 3 ); //System.out.println("m2 = "+m2); assertTrue("m2 == m2", m2.equals(m2) ); assertEquals("m2.length", 4, m2.list.size() ); assertTrue("m == m2", m.equals(m2) ); table4 = ((GenSolvablePolynomialRing)m2.ring).table; //System.out.println("table 4 = " + table4); assertEquals("table2 == table4", table2, table4 ); assertEquals("table1 == table4", table1, table4 ); PolynomialList p2 = null; p2 = m2.getPolynomialList(); //System.out.println("p2 = "+p2); assertTrue("p2 == p2", p2.equals(p2) ); assertEquals("p2.length", 4, p2.list.size() ); assertTrue("p == p2", p.list.equals(p2.list) ); table5 = ((GenSolvablePolynomialRing)p2.ring).table; //System.out.println("table 5= " + table5); assertEquals("table2 == table4", table3.table, table5.table ); } } jas-2.5/trc/edu/jas/poly/GenMatrixTest.java0000644000175000017500000001545212014234362021055 0ustar giovannigiovanni/* * $Id: GenMatrixTest.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.ArrayList; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; //import edu.jas.structure.RingElem; //import edu.jas.structure.ModulElem; import edu.jas.arith.BigRational; import edu.jas.vector.GenMatrix; import edu.jas.vector.GenMatrixRing; /** * GenMatrix tests with JUnit * @author Heinz Kredel. */ public class GenMatrixTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a GenMatrixTest object. * @param name String. */ public GenMatrixTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GenMatrixTest.class); return suite; } int rl = 5; int kl = 10; int ll = 10; float q = 0.5f; int rows = 3; int cols = 3; @Override protected void setUp() { } @Override protected void tearDown() { } /** * Test constructor and toString. * */ public void testPolynomialConstruction() { BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, rl); GenMatrixRing> mfac = new GenMatrixRing>(pfac, rows, cols); assertTrue("#rows = " + rows, mfac.rows == rows); assertTrue("#columns = " + cols, mfac.cols == cols); assertTrue("pfac == coFac ", pfac == mfac.coFac); GenMatrix> a; a = mfac.getZERO(); //System.out.println("a = " + a); assertTrue("isZERO( a )", a.isZERO()); GenMatrix> b = new GenMatrix>(mfac); //System.out.println("b = " + b); assertTrue("isZERO( b )", b.isZERO()); assertTrue("a == b ", a.equals(b)); GenMatrix> c = b.copy(); //System.out.println("c = " + c); assertTrue("isZERO( c )", c.isZERO()); assertTrue("a == c ", a.equals(c)); GenMatrix> d = mfac.copy(b); //System.out.println("d = " + d); assertTrue("isZERO( d )", d.isZERO()); assertTrue("a == d ", a.equals(d)); } /** * Test random matrix * */ public void testPolynomialRandom() { BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, rl); GenMatrixRing> mfac = new GenMatrixRing>(pfac, rows, cols); GenMatrix> a; for (int i = 0; i < 5; i++) { a = mfac.random(kl, q); //System.out.println("a = " + a); if (a.isZERO()) { continue; } assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); } } /** * Test addition. * */ public void testPolynomialAddition() { BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, rl); GenMatrixRing> mfac = new GenMatrixRing>(pfac, rows, cols); GenMatrix> a, b, c, d, e; a = mfac.random(kl, q); b = mfac.random(kl, q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.sum(b); d = c.subtract(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b-b = a", a, d); c = a.sum(b); d = c.sum(b.negate()); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b+(-b) = a", a, d); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a", c, d); c = mfac.random(kl, q); d = a.sum(b).sum(c); e = a.sum(b.sum(c)); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("a+(b+c) = (a+b)+c", d, e); } /** * Test scalar multiplication. * */ public void testPolynomialMultiplication() { BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, rl); GenMatrixRing> mfac = new GenMatrixRing>(pfac, rows, cols); GenPolynomial r, s, t; GenMatrix> a, b, c, d, e; r = pfac.random(kl); //System.out.println("r = " + r); s = r.negate(); //System.out.println("s = " + s); a = mfac.random(kl, q); //System.out.println("a = " + a); c = a.scalarMultiply(r); d = a.scalarMultiply(s); e = c.sum(d); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("a*b + a*(-b) = 0", e, mfac.getZERO()); b = mfac.random(kl, q); //System.out.println("b = " + b); t = pfac.getONE(); //System.out.println("t = " + t); c = a.linearCombination(b, t); d = b.linearCombination(a, t); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b = b+1*a", c, d); c = a.linearCombination(b, t); d = a.sum(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b = b+1*a", c, d); s = t.negate(); //System.out.println("s = " + s); c = a.linearCombination(b, t); d = c.linearCombination(b, s); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b+(-1)*b = a", a, d); c = a.linearCombination(t, b, t); d = c.linearCombination(t, b, s); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b+(-1)*b = a", a, d); t = pfac.getZERO(); //System.out.println("t = " + t); c = a.linearCombination(b, t); //System.out.println("c = " + c); assertEquals("a+0*b = a", a, c); d = a.linearCombination(t, b, t); //System.out.println("d = " + d); assertEquals("0*a+0*b = 0", mfac.getZERO(), d); } } jas-2.5/trc/edu/jas/poly/ANumGenPolynomialTest.java0000644000175000017500000002313312004571452022513 0ustar giovannigiovanni/* * $Id: ANumGenPolynomialTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; /** * AlgebraicNumber coefficients GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class ANumGenPolynomialTest extends TestCase { /** * main */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a ANumGenPolynomialTest object. * @param name String. */ public ANumGenPolynomialTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(ANumGenPolynomialTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing> fac; AlgebraicNumberRing cfac; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; GenPolynomial> d; GenPolynomial> e; int rl = 3; int kl = 10; int ll = 5; int el = 5; float q = 0.5f; @Override protected void setUp() { a = b = c = d = e = null; BigRational r = new BigRational(1); // univariate minimal polynomial GenPolynomialRing mfac = new GenPolynomialRing(r, 1); GenPolynomial modul = mfac.random(3); while (modul.isZERO() || modul.isUnit() || modul.isConstant()) { modul = mfac.random(3); } modul = modul.sum(mfac.fromInteger(3L)); cfac = new AlgebraicNumberRing(modul.monic()); fac = new GenPolynomialRing>(cfac, rl); } @Override protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor //and toString * */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )c" + c, !c.isZERO()); assertTrue("isONE( c ) " + c, c.isONE()); d = fac.getZERO(); //System.out.println("d = " + d); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO()); assertTrue("isONE( d )", !d.isONE()); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(ll + i); //System.out.println("a = " + a); // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a" + i + " ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); assertTrue(" not isONE( a" + i + " )", !a.isONE()); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a", a, d); c = fac.random(ll); ExpVector u = ExpVector.EVRAND(rl, el, q); AlgebraicNumber x = cfac.random(kl); b = new GenPolynomial>(fac, x, u); c = a.sum(b); d = a.sum(x, u); assertEquals("a+p(x,u) = a+(x,u)", c, d); c = a.subtract(b); d = a.subtract(x, u); assertEquals("a-p(x,u) = a-(x,u)", c, d); a = new GenPolynomial>(fac); b = new GenPolynomial>(fac, x, u); c = b.sum(a); d = a.sum(x, u); assertEquals("a+p(x,u) = a+(x,u)", c, d); c = a.subtract(b); d = a.subtract(x, u); assertEquals("a-p(x,u) = a-(x,u)", c, d); c = fac.random(ll); d = c.sum(a.sum(b)); e = c.sum(a).sum(b); assertEquals("c+(a+b) = (c+a)+b", d, e); c = a.sum(fac.getZERO()); d = a.subtract(fac.getZERO()); assertEquals("a+0 = a-0", c, d); c = fac.getZERO().sum(a); d = fac.getZERO().subtract(a.negate()); assertEquals("0+a = 0+(-a)", c, d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO()); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO()); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO()); assertTrue("not isZERO( d )", !d.isZERO()); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO()); assertTrue("a*b = b*a", c.equals(d)); assertEquals("a*b = b*a", c, d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply(b.multiply(c)); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c", d, e); assertTrue("a(bc) = (ab)c", d.equals(e)); AlgebraicNumber z = a.leadingBaseCoefficient(); //System.out.println("z = " + z); if (z.isUnit()) { AlgebraicNumber x = z.inverse(); //System.out.println("x = " + x); //System.out.println("a = " + a); c = a.monic(); //System.out.println("c = " + c); d = a.multiply(x); //System.out.println("d = " + d); assertEquals("a.monic() = a(1/ldcf(a))", c, d); } AlgebraicNumber y = b.leadingBaseCoefficient(); if (y.isUnit()) { y = y.inverse(); c = b.monic(); d = b.multiply(y); assertEquals("b.monic() = b(1/ldcf(b))", c, d); e = new GenPolynomial>(fac, y); d = b.multiply(e); assertEquals("b.monic() = b(1/ldcf(b))", c, d); d = e.multiply(b); assertEquals("b.monic() = (1/ldcf(b))*b", c, d); } } /** * Test distributive law. * */ public void testDistributive() { a = fac.random(ll); b = fac.random(ll); c = fac.random(ll); d = a.multiply(b.sum(c)); e = a.multiply(b).sum(a.multiply(c)); assertEquals("a(b+c) = ab+ac", d, e); } /** * Test object quotient and remainder. * */ public void testQuotRem1() { fac = new GenPolynomialRing>(cfac, 1); a = fac.random(2); //.monic(); if (a.isZERO()) { return; } assertTrue("not isZERO( a )", !a.isZERO()); b = fac.random(2); //.monic(); if (b.isZERO()) { return; } assertTrue("not isZERO( b )", !b.isZERO()); GenPolynomial> g = fac.random(1).monic(); if (g.isZERO()) { return; } assertTrue("not isZERO( g )", !g.isZERO()); //g = fac.getONE(); a = a.multiply(g); b = b.multiply(g); //System.out.println("ta = " + a); //System.out.println("tb = " + b); //System.out.println("tg = " + g); GenPolynomial>[] qr; qr = b.divideAndRemainder(a); c = qr[0]; d = qr[1]; //System.out.println("q = " + c); //System.out.println("r = " + d); e = c.multiply(a).sum(d); assertEquals("b = q a + r", b, e); qr = a.divideAndRemainder(b); c = qr[0]; d = qr[1]; //System.out.println("q = " + c); //System.out.println("r = " + d); e = c.multiply(b).sum(d); assertEquals("a = q b + r", a, e); // gcd tests ------------------------------- c = a.gcd(b); //System.out.println("gcd = " + c); assertTrue("a mod gcd(a,b) = 0", a.remainder(c).isZERO()); assertTrue("b mod gcd(a,b) = 0", b.remainder(c).isZERO()); //assertEquals("g = gcd(a,b)", c, g ); GenPolynomial>[] gst; gst = a.egcd(b); //System.out.println("egcd = " + gst[0]); //System.out.println(", s = " + gst[1] + ", t = " + gst[2]); c = gst[0]; d = gst[1]; e = gst[2]; assertTrue("a mod gcd(a,b) = 0", a.remainder(c).isZERO()); assertTrue("b mod gcd(a,b) = 0", b.remainder(c).isZERO()); //assertEquals("g = gcd(a,b)", c, g ); GenPolynomial> x; x = a.multiply(d).sum(b.multiply(e)).monic(); //System.out.println("x = " + x); assertEquals("gcd(a,b) = a s + b t", c, x); //System.out.println("a = " + a); //System.out.println("b = " + b); if (a.isZERO() || b.isZERO()) { return; } try { c = a.modInverse(b); //System.out.println("c = " + c); x = c.multiply(a).remainder(b).monic(); //System.out.println("x = " + x); assertTrue("a invertible mod b " + x, x.isUnit()); } catch (RuntimeException e) { // dann halt nicht // not invertible } } } jas-2.5/trc/edu/jas/poly/GaloisFieldTest.java0000644000175000017500000003304011641660762021346 0ustar giovannigiovanni/* * $Id: GaloisFieldTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; //import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.poly.GenPolynomial; //import edu.jas.structure.RingElem; /** * Galois field tests with JUnit. * @author Heinz Kredel. */ public class GaloisFieldTest extends TestCase { /** * main */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a GaloisFieldTest object. * @param name String. */ public GaloisFieldTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(GaloisFieldTest.class); return suite; } //private final static int bitlen = 100; AlgebraicNumberRing fac; GenPolynomialRing mfac; AlgebraicNumber< ModInteger > a; AlgebraicNumber< ModInteger > b; AlgebraicNumber< ModInteger > c; AlgebraicNumber< ModInteger > d; AlgebraicNumber< ModInteger > e; int rl = 1; int kl = 10; int ll = 15; int el = ll; float q = 0.5f; protected long getPrime() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for ( int i = 1; i < 60; i++ ) { prime *= 2; } prime -= 93; //System.out.println("prime = " + prime); return prime; } protected void setUp() { a = b = c = d = e = null; long prime = getPrime(); mfac = new GenPolynomialRing( new ModIntegerRing(prime), 1 ); //System.out.println("mfac = " + mfac); GenPolynomial mo = mfac.random(kl,ll,el,q); while ( mo.isConstant() ) { mo = mfac.random(kl,ll,el,q); } fac = new AlgebraicNumberRing( mo ); //System.out.println("fac = " + fac); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); //System.out.println("c = " + c); //System.out.println("c.getVal() = " + c.getVal()); assertTrue("length( c ) = 1", c.getVal().length() == 1); assertTrue("isZERO( c )", !c.getVal().isZERO() ); assertTrue("isONE( c )", c.getVal().isONE() ); d = fac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.getVal() = " + d.getVal()); assertTrue("length( d ) = 0", d.getVal().length() == 0); assertTrue("isZERO( d )", d.getVal().isZERO() ); assertTrue("isONE( d )", !d.getVal().isONE() ); } /** * Test random polynomial * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(ll+i); //System.out.println("a = " + a); // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a"+i+" ) <> 0", a.getVal().length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.getVal().isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.getVal().isONE() ); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = fac.random(ll); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a*1/a = 1",fac.getONE(),d); } /** * Test distributive law. * */ public void testDistributive() { a = fac.random( ll ); b = fac.random( ll ); c = fac.random( ll ); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } /** * Test chinese remainder. * */ public void testChineseRemainder() { ModIntegerRing cfac; GenPolynomialRing m0fac; GenPolynomial x0; GenPolynomial x; GenPolynomial m0; GenPolynomial m1; GenPolynomial m01; AlgebraicNumberRing fac0; AlgebraicNumberRing fac1; AlgebraicNumberRing fac01; cfac = new ModIntegerRing(19); //System.out.println("cfac = " + cfac.getModul()); m0fac = new GenPolynomialRing( cfac, 0 ); //System.out.println("m0fac = " + m0fac); mfac = new GenPolynomialRing( cfac, 1 ); //System.out.println("mfac = " + mfac); x0 = m0fac.getONE(); //System.out.println("x0 = " + x0); x = x0.extend(mfac,0,1); //System.out.println("x = " + x); m0 = mfac.fromInteger(2); m1 = mfac.fromInteger(5); //System.out.println("m0 = " + m0); //System.out.println("m1 = " + m1); m0 = x.subtract(m0); m1 = x.subtract(m1); //System.out.println("m0 = " + m0); //System.out.println("m1 = " + m1); m01 = m0.multiply(m1); //System.out.println("m01 = " + m01); fac0 = new AlgebraicNumberRing( m0, true ); fac1 = new AlgebraicNumberRing( m1, true ); fac01 = new AlgebraicNumberRing( m01, false ); //System.out.println("fac0 = " + fac0); //System.out.println("fac1 = " + fac1); //System.out.println("fac01 = " + fac01); a = fac01.random( 9 ); //System.out.println("a = " + a); b = new AlgebraicNumber(fac0,a.getVal()); //System.out.println("b = " + b); c = new AlgebraicNumber(fac1,a.getVal()); //System.out.println("c = " + c); d = new AlgebraicNumber(fac1,m0); //System.out.println("d = " + d); d = d.inverse(); //System.out.println("d = " + d); e = fac01.chineseRemainder(b,d,c); //System.out.println("e = " + e); assertEquals("cra(a mod (x-m0),a mod (x-m1)) = a (mod 19)",a,e); cfac = new ModIntegerRing(getPrime()); //System.out.println("cfac = " + cfac.getModul()); m0fac = new GenPolynomialRing( cfac, 0 ); //System.out.println("m0fac = " + m0fac); mfac = new GenPolynomialRing( cfac, 1 ); //System.out.println("mfac = " + mfac); x0 = m0fac.getONE(); //System.out.println("x0 = " + x0); x = x0.extend(mfac,0,1); //System.out.println("x = " + x); m0 = mfac.fromInteger(21); m1 = mfac.fromInteger(57); //System.out.println("m0 = " + m0); //System.out.println("m1 = " + m1); m0 = x.subtract(m0); m1 = x.subtract(m1); //System.out.println("m0 = " + m0); //System.out.println("m1 = " + m1); m01 = m0.multiply(m1); //System.out.println("m01 = " + m01); fac0 = new AlgebraicNumberRing( m0, true ); fac1 = new AlgebraicNumberRing( m1, true ); fac01 = new AlgebraicNumberRing( m01, false ); //System.out.println("fac0 = " + fac0); //System.out.println("fac1 = " + fac1); //System.out.println("fac01 = " + fac01); for ( int i = 0; i < 5; i++ ) { a = fac01.random( 9 ); //System.out.println("a = " + a); b = new AlgebraicNumber(fac0,a.getVal()); //System.out.println("b = " + b); c = new AlgebraicNumber(fac1,a.getVal()); //System.out.println("c = " + c); d = new AlgebraicNumber(fac1,m0); //System.out.println("d = " + d); d = d.inverse(); //System.out.println("d = " + d); e = fac01.chineseRemainder(b,d,c); //System.out.println("e = " + e); assertEquals("cra(a mod (x-m0),a mod (x-m1)) = a (mod 2^60-93)",a,e); } } /** * Test interpolate, is chinese remainder special case. * */ public void testInterpolate() { ModIntegerRing cfac; GenPolynomialRing m0fac; GenPolynomial x0; GenPolynomial x; GenPolynomial m0; GenPolynomial m1; GenPolynomial m01; AlgebraicNumberRing fac0; AlgebraicNumberRing fac1; AlgebraicNumberRing fac01; ModInteger cm; ModInteger ci; ModInteger di; cfac = new ModIntegerRing(19); //System.out.println("cfac = " + cfac.getModul()); m0fac = new GenPolynomialRing( cfac, 0 ); //System.out.println("m0fac = " + m0fac); mfac = new GenPolynomialRing( cfac, 1 ); //System.out.println("mfac = " + mfac); x0 = m0fac.getONE(); //System.out.println("x0 = " + x0); x = x0.extend(mfac,0,1); //System.out.println("x = " + x); m0 = mfac.fromInteger(2); m1 = mfac.fromInteger(5); //System.out.println("m0 = " + m0); //System.out.println("m1 = " + m1); m0 = x.subtract(m0); m1 = x.subtract(m1); //System.out.println("m0 = " + m0); //System.out.println("m1 = " + m1); m01 = m0.multiply(m1); //System.out.println("m01 = " + m01); fac0 = new AlgebraicNumberRing( m0, true ); fac1 = new AlgebraicNumberRing( m1, true ); fac01 = new AlgebraicNumberRing( m01, false ); //System.out.println("fac0 = " + fac0); //System.out.println("fac1 = " + fac1); //System.out.println("fac01 = " + fac01); a = fac01.random( 9 ); //System.out.println("a = " + a); b = new AlgebraicNumber(fac0,a.getVal()); //System.out.println("b = " + b); c = new AlgebraicNumber(fac1,a.getVal()); //System.out.println("c = " + c); cm = fac1.modul.trailingBaseCoefficient(); //System.out.println("cm = " + cm); ci = c.val.trailingBaseCoefficient(); //System.out.println("ci = " + ci); d = new AlgebraicNumber(fac1,m0); //System.out.println("d = " + d); d = d.inverse(); //System.out.println("d = " + d); di = d.val.leadingBaseCoefficient(); //System.out.println("di = " + di); e = fac01.interpolate(b,di,cm,ci); //System.out.println("e = " + e); assertEquals("cra(a mod (x-m0),a mod (x-m1)) = a (mod 19)",a,e); cfac = new ModIntegerRing(getPrime()); //System.out.println("cfac = " + cfac.getModul()); m0fac = new GenPolynomialRing( cfac, 0 ); //System.out.println("m0fac = " + m0fac); mfac = new GenPolynomialRing( cfac, 1 ); //System.out.println("mfac = " + mfac); x0 = m0fac.getONE(); //System.out.println("x0 = " + x0); x = x0.extend(mfac,0,1); //System.out.println("x = " + x); m0 = mfac.fromInteger(21); m1 = mfac.fromInteger(57); //System.out.println("m0 = " + m0); //System.out.println("m1 = " + m1); m0 = x.subtract(m0); m1 = x.subtract(m1); //System.out.println("m0 = " + m0); //System.out.println("m1 = " + m1); m01 = m0.multiply(m1); //System.out.println("m01 = " + m01); fac0 = new AlgebraicNumberRing( m0, true ); fac1 = new AlgebraicNumberRing( m1, true ); fac01 = new AlgebraicNumberRing( m01, false ); //System.out.println("fac0 = " + fac0); //System.out.println("fac1 = " + fac1); //System.out.println("fac01 = " + fac01); for ( int i = 0; i < 5; i++ ) { a = fac01.random( 9 ); //System.out.println("a = " + a); b = new AlgebraicNumber(fac0,a.getVal()); //System.out.println("b = " + b); c = new AlgebraicNumber(fac1,a.getVal()); //System.out.println("c = " + c); cm = fac1.modul.trailingBaseCoefficient(); //System.out.println("cm = " + cm); ci = c.val.trailingBaseCoefficient(); //System.out.println("ci = " + ci); d = new AlgebraicNumber(fac1,m0); //System.out.println("d = " + d); d = d.inverse(); //System.out.println("d = " + d); di = d.val.leadingBaseCoefficient(); //System.out.println("di = " + di); e = fac01.interpolate(b,di,cm,ci); //System.out.println("e = " + e); assertEquals("cra(a mod (x-m0),a mod (x-m1)) = a (mod 2^60-93)",a,e); } } } jas-2.5/trc/edu/jas/poly/GenWordPolynomialTest.java0000644000175000017500000005271012016374534022576 0ustar giovannigiovanni/* * $Id: GenWordPolynomialTest.java 4139 2012-08-26 10:24:29Z kredel $ */ package edu.jas.poly; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.BigComplex; import edu.jas.structure.RingElem; /** * GenWordPolynomial tests with JUnit. * @author Heinz Kredel. */ public class GenWordPolynomialTest extends TestCase { /** * main */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GenWordPolynomialTest object. * @param name String. */ public GenWordPolynomialTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GenWordPolynomialTest.class); return suite; } int rl = 6; int kl = 10; int ll = 7; int el = 5; @Override protected void setUp() { } @Override protected void tearDown() { } /** * Test constructors and factory. */ public void testConstructors() { // integers BigInteger rf = new BigInteger(); //System.out.println("rf = " + rf); // non-commuting vars: abcdef WordFactory wf = new WordFactory("abcdef"); //System.out.println("wf = " + wf); // polynomials over integers GenWordPolynomialRing pf = new GenWordPolynomialRing(rf, wf); //System.out.println("pf = " + pf); assertFalse("not commutative",pf.isCommutative()); assertTrue("associative",pf.isAssociative()); assertFalse("not field",pf.isField()); GenWordPolynomial p = pf.getONE(); //System.out.println("p = " + p); assertTrue("p == 1", p.isONE()); p = pf.getZERO(); assertTrue("p == 0", p.isZERO()); //System.out.println("p = " + p); //p = pf.random(9); //System.out.println("p = " + p); List> gens = pf.generators(); //System.out.println("gens = " + gens); assertTrue("#gens == 7", gens.size() == 7); RingElem> pe = new GenWordPolynomial(pf); //System.out.println("pe = " + pe); //System.out.println("p.equals(pe) = " + p.equals(pe) ); //System.out.println("p.equals(p) = " + p.equals(p) ); assertTrue("p.equals(pe) = ", p.equals(pe)); assertTrue("p.equals(p) = ", p.equals(p)); pe = pe.sum(p); //System.out.println("pe = " + pe); assertTrue("pe.isZERO() = ", pe.isZERO()); p = pf.random(9); p = p.subtract(p); //System.out.println("p = " + p); //System.out.println("p.isZERO() = " + p.isZERO()); assertTrue("p.isZERO() = ", p.isZERO()); // polynomials over (polynomials over integers) // non-commuting vars: xyz WordFactory wf2 = new WordFactory("xyz"); //System.out.println("wf2 = " + wf2); GenWordPolynomialRing> ppf = new GenWordPolynomialRing>(pf, wf2); //System.out.println("ppf = " + ppf); GenWordPolynomial> pp = ppf.getONE(); //System.out.println("pp = " + pp); assertTrue("pp == 1", pp.isONE()); //pp = ppf.random(2); //System.out.println("pp = " + pp); pp = ppf.getZERO(); //System.out.println("pp = " + pp); assertTrue("pp == 0", pp.isZERO()); List>> pgens = ppf.generators(); //System.out.println("pgens = " + pgens); assertTrue("#pgens == 7+3", pgens.size() == 10); RingElem>> ppe = new GenWordPolynomial>(ppf); //System.out.println("ppe = " + ppe); //System.out.println("pp.equals(ppe) = " + pp.equals(ppe) ); //System.out.println("pp.equals(pp) = " + pp.equals(pp) ); assertTrue("pp.equals(ppe) = ", pp.equals(ppe)); assertTrue("pp.equals(pp) = ", pp.equals(pp)); ppe = ppe.sum(pp); // why not pp = pp.add(ppe) ? //System.out.println("ppe = " + ppe); assertTrue("ppe.isZERO() = ", ppe.isZERO()); pp = ppf.random(2); pp = pp.subtract(pp); //System.out.println("pp = " + pp); //System.out.println("pp.isZERO() = " + pp.isZERO()); assertTrue("pp.isZERO() = ", pp.isZERO()); // polynomials over (polynomials over (polynomials over integers)) // non-commuting vars: uvw WordFactory wf3 = new WordFactory("uvw"); //System.out.println("wf3 = " + wf3); GenWordPolynomialRing>> pppf = new GenWordPolynomialRing>>(ppf, wf3); //System.out.println("pppf = " + pppf); GenWordPolynomial>> ppp = pppf.getONE(); //System.out.println("ppp = " + ppp); assertTrue("ppp == 1", ppp.isONE()); //ppp = pppf.random(2); //System.out.println("ppp = " + ppp); ppp = pppf.getZERO(); //System.out.println("ppp = " + ppp); assertTrue("ppp == 0", ppp.isZERO()); List>>> ppgens = pppf.generators(); //System.out.println("ppgens = " + ppgens); assertTrue("#ppgens == 7+3+3", ppgens.size() == 13); RingElem>>> pppe = new GenWordPolynomial>>(pppf); //System.out.println("pppe = " + pppe); // System.out.println("ppp.equals(pppe) = " + ppp.equals(pppe) ); // System.out.println("ppp.equals(ppp) = " + ppp.equals(ppp) ); assertTrue("ppp.equals(pppe) = ", ppp.equals(pppe)); assertTrue("ppp.equals(ppp) = ", ppp.equals(ppp)); pppe = pppe.sum(ppp); //System.out.println("pppe = " + pppe); assertTrue("pppe.isZERO() = ", pppe.isZERO()); //ppp = pppf.random(2); ppp = ppp.subtract(ppp); //System.out.println("ppp = " + ppp); //System.out.println("ppp.isZERO() = " + ppp.isZERO()); assertTrue("ppp.isZERO() = ", ppp.isZERO()); } /** * Test accessors. */ public void testAccessors() { // integers BigInteger rf = new BigInteger(); // System.out.println("rf = " + rf); // non-commuting vars: abcdef WordFactory wf = new WordFactory("abcdef"); //System.out.println("wf = " + wf); // polynomials over integers GenWordPolynomialRing pf = new GenWordPolynomialRing(rf, wf); //System.out.println("pf = " + pf); // test 1 GenWordPolynomial p = pf.getONE(); //System.out.println("p = " + p); Word e = p.leadingWord(); BigInteger c = p.leadingBaseCoefficient(); GenWordPolynomial f = new GenWordPolynomial(pf, c, e); assertEquals("1 == 1 ", p, f); GenWordPolynomial r = p.reductum(); assertTrue("red(1) == 0 ", r.isZERO()); // test 0 p = pf.getZERO(); // System.out.println("p = " + p); e = p.leadingWord(); c = p.leadingBaseCoefficient(); f = new GenWordPolynomial(pf, c, e); assertEquals("0 == 0 ", p, f); r = p.reductum(); assertTrue("red(0) == 0 ", r.isZERO()); // test random p = pf.random(kl, ll, el); // System.out.println("p = " + p); e = p.leadingWord(); c = p.leadingBaseCoefficient(); r = p.reductum(); f = new GenWordPolynomial(pf, c, e); f = r.sum(f); assertEquals("p == lm(f)+red(f) ", p, f); // test iteration over random GenWordPolynomial g; g = p; f = pf.getZERO(); while (!g.isZERO()) { e = g.leadingWord(); c = g.leadingBaseCoefficient(); //System.out.println("c e = " + c + " " + e); r = g.reductum(); f = f.sum(c, e); g = r; } assertEquals("p == lm(f)+lm(red(f))+... ", p, f); } /** * Test addition. */ public void testAddition() { // integers BigInteger rf = new BigInteger(); // System.out.println("rf = " + rf); // non-commuting vars: abcdef WordFactory wf = new WordFactory("abcdef"); //System.out.println("wf = " + wf); // polynomials over integers GenWordPolynomialRing fac = new GenWordPolynomialRing(rf, wf); //System.out.println("fac = " + fac); GenWordPolynomial a = fac.random(kl, ll, el); GenWordPolynomial b = fac.random(kl, ll, el); GenWordPolynomial c = a.sum(b); GenWordPolynomial d = c.subtract(b); GenWordPolynomial e; assertEquals("a+b-b = a", a, d); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); c = fac.random(kl, ll, el); //System.out.println("\nc = " + c); d = a.sum(b.sum(c)); e = (a.sum(b)).sum(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(e) ); assertEquals("a+(b+c) = (a+b)+c", d, e); Word u = wf.random(rl); BigInteger x = rf.random(kl); b = new GenWordPolynomial(fac, x, u); c = a.sum(b); d = a.sum(x, u); assertEquals("a+p(x,u) = a+(x,u)", c, d); //System.out.println("\nc = " + c); //System.out.println("d = " + d); c = a.subtract(b); d = a.subtract(x, u); assertEquals("a-p(x,u) = a-(x,u)", c, d); //System.out.println("c = " + c); //System.out.println("d = " + d); //a = new GenWordPolynomial(fac); b = new GenWordPolynomial(fac, x, u); c = b.sum(a); d = a.sum(x, u); assertEquals("a+p(x,u) = a+(x,u)", c, d); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); c = a.subtract(b); d = a.subtract(x, u); assertEquals("a-p(x,u) = a-(x,u)", c, d); //System.out.println("c = " + c); //System.out.println("d = " + d); } /** * Test multiplication. */ public void testMultiplication() { // integers BigInteger rf = new BigInteger(); // System.out.println("rf = " + rf); // non-commuting vars: abcdef WordFactory wf = new WordFactory("abcdef"); //System.out.println("wf = " + wf); // polynomials over integers GenWordPolynomialRing fac = new GenWordPolynomialRing(rf, wf); //System.out.println("fac = " + fac); GenWordPolynomial a = fac.random(kl, ll, el); GenWordPolynomial b = fac.random(kl, ll, el); GenWordPolynomial c = a.multiply(b); GenWordPolynomial d = b.multiply(a); GenWordPolynomial e; assertFalse("a*b != b*a", c.equals(d)); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); c = fac.random(kl, ll, el); //System.out.println("c = " + c); d = a.multiply(b.multiply(c)); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a*(b*c) = (a*b)*c", d, e); Word u = wf.random(rl); BigInteger x = rf.random(kl); b = new GenWordPolynomial(fac, x, u); c = a.multiply(b); d = a.multiply(x, u); assertEquals("a+p(x,u) = a+(x,u)", c, d); //System.out.println("c = " + c); //System.out.println("d = " + d); //a = new GenWordPolynomial(fac); b = new GenWordPolynomial(fac, x, u); c = a.multiply(b); d = a.multiply(x, u); assertEquals("a+p(x,u) = a+(x,u)", c, d); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); } /** * Test distributive law. */ public void testDistributive() { // integers BigInteger rf = new BigInteger(); // System.out.println("rf = " + rf); // non-commuting vars: abcdef WordFactory wf = new WordFactory("abcdef"); //System.out.println("wf = " + wf); // polynomials over integers GenWordPolynomialRing fac = new GenWordPolynomialRing(rf, wf); //System.out.println("fac = " + fac); GenWordPolynomial a = fac.random(kl, ll, el); GenWordPolynomial b = fac.random(kl, ll, el); GenWordPolynomial c = fac.random(kl, ll, el); GenWordPolynomial d, e; d = a.multiply(b.sum(c)); e = a.multiply(b).sum(a.multiply(c)); assertEquals("a(b+c) = ab+ac", d, e); } /** * Test univariate division. */ public void testUnivDivision() { // rational numbers BigRational rf = new BigRational(); //System.out.println("rf = " + rf); // non-commuting vars: x WordFactory wf = new WordFactory("x"); //System.out.println("wf = " + wf); // polynomials over rational numbers GenWordPolynomialRing fac = new GenWordPolynomialRing(rf, wf); //System.out.println("fac = " + fac); GenWordPolynomial a = fac.random(7, ll, el).monic(); GenWordPolynomial b = fac.random(7, ll, el).monic(); GenWordPolynomial c = a.multiply(b); GenWordPolynomial d = b.multiply(a); GenWordPolynomial e, f; assertTrue("a*b == b*a", c.equals(d)); // since univariate //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); e = c.divide(a); //System.out.println("e = " + e); assertTrue("a*b/a == b", b.equals(e)); d = c.divide(b); //System.out.println("d = " + d); assertTrue("a*b/b == a", a.equals(d)); d = c.gcd(a); //System.out.println("d = " + d); assertTrue("gcd(a*b,a) == a", a.equals(d)); d = a.gcd(b); //System.out.println("d = " + d); if (d.isConstant()) { assertTrue("gcd(b,a) == 1", d.isONE()); } else { return; } d = a.modInverse(b); //System.out.println("d = " + d); e = d.multiply(a); //System.out.println("e = " + e); f = e.remainder(b); //System.out.println("f = " + f); assertTrue("d * a == 1 mod b ", f.isONE()); } /** * Test multivariate 2 division. */ public void testMulti2Division() { // rational numbers BigRational rf = new BigRational(); // System.out.println("rf = " + rf); // non-commuting vars: xy WordFactory wf = new WordFactory("xy"); //System.out.println("wf = " + wf); // polynomials over rational numbers GenWordPolynomialRing fac = new GenWordPolynomialRing(rf, wf); //System.out.println("fac = " + fac); GenWordPolynomial a = fac.random(7, ll, el).monic(); GenWordPolynomial b = fac.random(7, ll, el).monic(); GenWordPolynomial c = a.multiply(b); GenWordPolynomial d = b.multiply(a); GenWordPolynomial e, f; assertFalse("a*b == b*a", c.equals(d)); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); e = c.divide(a); //System.out.println("e = " + e); assertTrue("a*b/a == b", b.equals(e)); f = d.divide(b); //System.out.println("f = " + f); assertTrue("a*b/b == a", a.equals(f)); try { f = a.divide(b); //System.out.println("f = " + f); } catch (RuntimeException re) { System.out.println("a divide b fail: " + a + ", " + b); return; } WordFactory.WordComparator cmp = fac.alphabet.getDescendComparator(); f = a.remainder(b); //System.out.println("a = " + a); //System.out.println("f = " + f); assertTrue("a rem2 b <= a", cmp.compare(a.leadingWord(), f.leadingWord()) <= 0); } /** * Test multivariate 3 division. */ public void testMulti3Division() { // rational numbers BigRational rf = new BigRational(); // System.out.println("rf = " + rf); // non-commuting vars: xyz WordFactory wf = new WordFactory("xyz"); //System.out.println("wf = " + wf); // polynomials over rational numbers GenWordPolynomialRing fac = new GenWordPolynomialRing(rf, wf); //System.out.println("fac = " + fac); GenWordPolynomial a = fac.random(7, ll, el).monic(); GenWordPolynomial b = fac.random(7, ll, el).monic(); GenWordPolynomial c = a.multiply(b); GenWordPolynomial d = b.multiply(a); GenWordPolynomial e, f; assertFalse("a*b == b*a", c.equals(d)); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); e = c.divide(a); //System.out.println("e = " + e); assertTrue("a*b/a == b", b.equals(e)); f = d.divide(b); //System.out.println("f = " + f); assertTrue("a*b/b == a", a.equals(f)); try { f = a.divide(b); //System.out.println("f = " + f); } catch (RuntimeException re) { System.out.println("a divide b fail: " + a + ", " + b); return; } WordFactory.WordComparator cmp = fac.alphabet.getDescendComparator(); f = a.remainder(b); //System.out.println("a = " + a); //System.out.println("f = " + f); assertTrue("a rem3 b <= a: " + a.leadingWord() + ", " + f.leadingWord(), cmp.compare(a.leadingWord(), f.leadingWord()) <= 0); } /** * Test polynomial and solvable coefficients. */ public void testCoefficients() { // integers BigComplex rf = new BigComplex(); //System.out.println("rf = " + rf); // commuting vars: uvw String[] cvar = new String[] { "u", "v", "w" }; GenPolynomialRing cf = new GenPolynomialRing(rf, cvar); //System.out.println("cf = " + cf); // solvable vars: x1 x2 y1 y2 String[] svar = new String[] { "x1", "x2", "y1", "y2" }; GenSolvablePolynomialRing> sf; sf = new GenSolvablePolynomialRing>(cf, svar); //System.out.println("sf = " + sf); WeylRelations> wr = new WeylRelations>(sf); wr.generate(); //System.out.println("sf = " + sf); // non-commuting vars: abcdef WordFactory wf = new WordFactory("abcdef"); //System.out.println("wf = " + wf); // non-commuting polynomials over commuting and solvable coefficients GenWordPolynomialRing>> nf; nf = new GenWordPolynomialRing>>(sf, wf); //System.out.println("nf = " + nf); //want: GenWordPolynomialRing>> nf; assertFalse("not commutative",nf.isCommutative()); assertTrue("associative",nf.isAssociative()); assertFalse("not field",nf.isField()); GenWordPolynomial>> p = nf.getONE(); //System.out.println("p = " + p); assertTrue("p == 1", p.isONE()); p = nf.getZERO(); //System.out.println("p = " + p); assertTrue("p == 0", p.isZERO()); p = nf.random(3); //System.out.println("p = " + p); p = p.multiply(p); //System.out.println("p = " + p); p = p.subtract(p); //System.out.println("p = " + p); assertTrue("p == 0", p.isZERO()); List>>> gens = nf.generators(); //System.out.println("gens = " + gens); assertTrue("#gens == 2+3+4+6", gens.size() == 15); } } jas-2.5/trc/edu/jas/poly/ModGenPolynomialTest.java0000644000175000017500000001151611641660762022405 0ustar giovannigiovanni/* * $Id: ModGenPolynomialTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.poly.GenPolynomial; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; //import edu.jas.structure.RingElem; /** * ModInteger coefficients GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class ModGenPolynomialTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a ModGenPolynomialTest object. * @param name String. */ public ModGenPolynomialTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ModGenPolynomialTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing fac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int ml = 19; // modul int rl = 7; int kl = 10; int ll = 10; int el = 5; float q = 0.5f; protected void setUp() { a = b = c = d = e = null; fac = new GenPolynomialRing(new ModIntegerRing(ml),rl); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(ll); // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = fac.random(ll); ExpVector u = ExpVector.EVRAND(rl,el,q); ModInteger x = c.leadingBaseCoefficient().ring.random(kl); b = new GenPolynomial(fac,x, u); c = a.sum(b); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); a = new GenPolynomial(fac); b = new GenPolynomial(fac,x, u); c = b.sum(a); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); ModInteger x = a.leadingBaseCoefficient().inverse(); c = a.monic(); d = a.multiply(x); assertEquals("a.monic() = a(1/ldcf(a))",c,d); ModInteger y = b.leadingBaseCoefficient().inverse(); c = b.monic(); d = b.multiply(y); assertEquals("b.monic() = b(1/ldcf(b))",c,d); e = new GenPolynomial(fac,y); d = b.multiply(e); assertEquals("b.monic() = b(1/ldcf(b))",c,d); d = e.multiply(b); assertEquals("b.monic() = (1/ldcf(b) (0))*b",c,d); } /** * Test distributive law. * */ public void testDistributive() { a = fac.random(kl,ll,el,q); b = fac.random(kl,ll,el,q); c = fac.random(kl,ll,el,q); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } } jas-2.5/trc/edu/jas/poly/ComplexGenPolynomialTest.java0000644000175000017500000001073111641660762023273 0ustar giovannigiovanni/* * $Id: ComplexGenPolynomialTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.poly.GenPolynomial; import edu.jas.arith.BigComplex; //import edu.jas.structure.RingElem; /** * Complex coefficients GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class ComplexGenPolynomialTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a ComplexGenPolynomialTest object. * @param name String. */ public ComplexGenPolynomialTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ComplexGenPolynomialTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing fac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 7; int kl = 10; int ll = 10; int el = 5; float q = 0.5f; protected void setUp() { a = b = c = d = e = null; fac = new GenPolynomialRing(new BigComplex(1),rl); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(ll); // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = fac.random(ll); ExpVector u = ExpVector.EVRAND(rl,el,q); BigComplex x = BigComplex.CRAND(kl); b = new GenPolynomial(fac,x, u); c = a.sum(b); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); a = new GenPolynomial(fac); b = new GenPolynomial(fac,x, u); c = b.sum(a); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); BigComplex x = a.leadingBaseCoefficient().inverse(); c = a.monic(); d = a.multiply(x); assertEquals("a.monic() = a(1/ldcf(a))",c,d); BigComplex y = b.leadingBaseCoefficient().inverse(); c = b.monic(); d = b.multiply(y); assertEquals("b.monic() = b(1/ldcf(b))",c,d); e = new GenPolynomial(fac,y); d = b.multiply(e); assertEquals("b.monic() = b(1/ldcf(b))",c,d); d = e.multiply(b); assertEquals("b.monic() = (1/ldcf(b) (0))*b",c,d); } } jas-2.5/trc/edu/jas/poly/RatGenPolynomialTest.java0000644000175000017500000002006012045261444022377 0ustar giovannigiovanni/* * $Id: RatGenPolynomialTest.java 4284 2012-11-03 18:32:04Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; /** * BigRational coefficients GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class RatGenPolynomialTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a RatGenPolynomialTest object. * @param name String. */ public RatGenPolynomialTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(RatGenPolynomialTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing fac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 7; int kl = 10; int ll = 10; int el = 5; float q = 0.5f; protected void setUp() { a = b = c = d = e = null; fac = new GenPolynomialRing(new BigRational(1),rl); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. */ public void testConstruction() { c = fac.getONE(); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(ll); //System.out.println("a = " + a); // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = fac.random(ll); ExpVector u = ExpVector.EVRAND(rl,el,q); BigRational x = BigRational.RNRAND(kl); b = new GenPolynomial(fac,x, u); c = a.sum(b); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); a = new GenPolynomial(fac); b = new GenPolynomial(fac,x, u); c = b.sum(a); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); } /** * Test object multiplication. */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); BigRational x = a.leadingBaseCoefficient().inverse(); c = a.monic(); d = a.multiply(x); assertEquals("a.monic() = a(1/ldcf(a))",c,d); BigRational y = b.leadingBaseCoefficient().inverse(); c = b.monic(); d = b.multiply(y); assertEquals("b.monic() = b(1/ldcf(b))",c,d); e = new GenPolynomial(fac,y); d = b.multiply(e); assertEquals("b.monic() = b(1/ldcf(b))",c,d); d = e.multiply(b); assertEquals("b.monic() = (1/ldcf(b) (0))*b",c,d); } /** * Test BLAS level 1. */ public void testBLAS1() { a = fac.random(kl,ll,el,q); b = fac.random(kl,ll,el,q); c = fac.random(kl,3,el*el,q); ExpVector ev = ExpVector.EVRAND(rl,el,q); BigRational lc = BigRational.RNRAND(kl); d = a.subtractMultiple(lc,b); e = a.subtract( b.multiply(lc) ); assertEquals("a - (lc) b == a - ((lc) b)",d,e); d = a.subtractMultiple(lc,ev,b); e = a.subtract( b.multiply(lc,ev) ); assertEquals("a - (lc ev) b == a - ((lc ev) b)",d,e); ExpVector fv = ExpVector.EVRAND(rl,el,q); BigRational tc = BigRational.RNRAND(kl); d = a.scaleSubtractMultiple(tc,lc,ev,b); e = a.multiply(tc).subtract( b.multiply(lc,ev) ); assertEquals("(tc) a - (lc ev) b == ((tc) a - ((lc ev) b))",d,e); d = a.scaleSubtractMultiple(tc,fv,lc,ev,b); e = a.multiply(tc,fv).subtract( b.multiply(lc,ev) ); assertEquals("(tc fv) a - (lc ev) b == ((tc fv) a - ((lc ev) b))",d,e); } /** * Test distributive law. */ public void testDistributive() { a = fac.random(kl,ll,el,q); b = fac.random(kl,ll,el,q); c = fac.random(kl,ll,el,q); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) == ab+ac",d,e); } /** * Test object quotient and remainder. */ public void testQuotRem() { fac = new GenPolynomialRing(new BigRational(1),1); a = fac.random(ll).monic(); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(ll).monic(); assertTrue("not isZERO( b )", !b.isZERO() ); GenPolynomial h = a; GenPolynomial g = fac.random(ll).monic(); assertTrue("not isZERO( g )", !g.isZERO() ); a = a.multiply(g); b = b.multiply(g); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("g = " + g); GenPolynomial[] qr; qr = b.divideAndRemainder(a); c = qr[0]; d = qr[1]; //System.out.println("q = " + c); //System.out.println("r = " + d); e = c.multiply(a).sum(d); assertEquals("b = q a + r", b, e ); qr = a.divideAndRemainder(b); c = qr[0]; d = qr[1]; //System.out.println("q = " + c); //System.out.println("r = " + d); e = c.multiply(b).sum(d); assertEquals("a = q b + r", a, e ); // gcd tests ------------------------------- c = a.gcd(b); //System.out.println("gcd = " + c); assertTrue("a mod gcd(a,b) = 0", a.remainder(c).isZERO() ); assertTrue("b mod gcd(a,b) = 0", b.remainder(c).isZERO() ); assertEquals("g = gcd(a,b)", c, g ); GenPolynomial[] gst; gst = a.egcd(b); //System.out.println("egcd = " + gst[0]); //System.out.println(", s = " + gst[1] + ", t = " + gst[2]); c = gst[0]; d = gst[1]; e = gst[2]; assertEquals("g = gcd(a,b)", c, g ); GenPolynomial x; x = a.multiply(d).sum( b.multiply(e) ).monic(); //System.out.println("x = " + x); assertEquals("gcd(a,b) = a s + b t", c, x ); gst = a.hegcd(b); //System.out.println("hegcd = " + gst[0]); //System.out.println("s = " + gst[1]); c = gst[0]; d = gst[1]; assertEquals("g = gcd(a,b)", c, g ); x = a.multiply(d).remainder(b).monic(); //System.out.println("x = " + x); assertEquals("gcd(a,b) = a s mod b", c, x ); //System.out.println("g = " + g); //System.out.println("h = " + h); c = h.modInverse(g); //System.out.println("c = " + c); x = c.multiply(h).remainder( g ).monic(); //System.out.println("x = " + x); assertTrue("h invertible mod g", x.isONE() ); } } jas-2.5/trc/edu/jas/poly/PolyUtilTest.java0000644000175000017500000016234712002766222020750 0ustar giovannigiovanni/* * $Id: PolyUtilTest.java 4015 2012-07-22 12:05:38Z kredel $ */ package edu.jas.poly; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigComplex; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.kern.ComputerThreads; import edu.jas.ufd.PolyUfdUtil; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; /** * PolyUtil tests with JUnit. * @author Heinz Kredel. */ public class PolyUtilTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a PolyUtilTest object. * @param name String. */ public PolyUtilTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(PolyUtilTest.class); return suite; } //private final static int bitlen = 100; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 5; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; dfac = new GenPolynomialRing(new BigInteger(1), rl, to); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; dfac = null; cfac = null; rfac = null; } protected static java.math.BigInteger getPrime1() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 60; i++) { prime *= 2; } prime -= 93; //prime = 37; //System.out.println("p1 = " + prime); return new java.math.BigInteger("" + prime); } protected static java.math.BigInteger getPrime2() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 30; i++) { prime *= 2; } prime -= 35; //prime = 19; //System.out.println("p1 = " + prime); return new java.math.BigInteger("" + prime); } /** * Test recursive <--> distributive conversion. */ public void testConversion() { c = dfac.getONE(); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO()); assertTrue("isONE( c )", c.isONE()); cr = PolyUtil.recursive(rfac, c); a = PolyUtil.distribute(dfac, cr); assertEquals("c == dist(rec(c))", c, a); d = dfac.getZERO(); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO()); assertTrue("isONE( d )", !d.isONE()); dr = PolyUtil.recursive(rfac, d); b = PolyUtil.distribute(dfac, dr); assertEquals("d == dist(rec(d))", d, b); } /** * Test recursive <--> distributive ring conversion. */ public void testConversionRing() { GenPolynomialRing> rf = dfac.recursive(1); GenPolynomialRing cf = (GenPolynomialRing)rf.coFac; assertEquals("rfac#var == rf#var ", rfac.nvar, rf.nvar); assertEquals("rfac.coFac#var == rf.coFac#var ", cfac.nvar, cf.nvar); assertEquals("rfac.coFac.coFac == rf.coFac.coFac ", cfac.coFac, cf.coFac); // variable names not same in this test } /** * Test random recursive <--> distributive conversion. */ public void testRandomConversion() { for (int i = 0; i < 7; i++) { c = dfac.random(kl * (i + 2), ll + 2 * i, el + i, q); assertTrue("length( c" + i + " ) <> 0", c.length() >= 0); assertTrue(" not isZERO( c" + i + " )", !c.isZERO()); assertTrue(" not isONE( c" + i + " )", !c.isONE()); cr = PolyUtil.recursive(rfac, c); a = PolyUtil.distribute(dfac, cr); //System.out.println("c = " + c); //System.out.println("cr = " + cr); //System.out.println("crd = " + a); assertEquals("c == dist(rec(c))", c, a); } } /** * Test random rational <--> integer conversion. */ public void testRationalConversion() { GenPolynomialRing rfac = new GenPolynomialRing(new BigRational(1), rl, to); GenPolynomial ar; GenPolynomial br; for (int i = 0; i < 3; i++) { c = dfac.random(kl * (i + 9), ll * (i + 3), el + i, q).abs(); //c = c.multiply( new BigInteger(99) ); // fails, since not primitive //c = GreatestCommonDivisor.primitivePart(c); assertTrue("length( c" + i + " ) <> 0", c.length() >= 0); assertTrue(" not isZERO( c" + i + " )", !c.isZERO()); assertTrue(" not isONE( c" + i + " )", !c.isONE()); ar = PolyUtil. fromIntegerCoefficients(rfac, c); br = ar.monic(); a = PolyUtil.integerFromRationalCoefficients(dfac, br); //System.out.println("c = " + c); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("crd = " + a); assertEquals("c == integer(rational(c))", c, a); } } /** * Test random modular <--> integer conversion. */ public void testModularConversion() { ModIntegerRing pm = new ModIntegerRing(getPrime1()); GenPolynomialRing mfac = new GenPolynomialRing(pm, rl, to); GenPolynomial ar; for (int i = 0; i < 3; i++) { c = dfac.random(kl * (i + 2), ll * (i + 1), el + i, q).abs(); //c = c.multiply( new BigInteger(99) ); // fails, since not primitive //c = GreatestCommonDivisor.primitivePart(c); assertTrue("length( c" + i + " ) <> 0", c.length() >= 0); assertTrue(" not isZERO( c" + i + " )", !c.isZERO()); assertTrue(" not isONE( c" + i + " )", !c.isONE()); ar = PolyUtil. fromIntegerCoefficients(mfac, c); a = PolyUtil.integerFromModularCoefficients(dfac, ar); //System.out.println("c = " + c); //System.out.println("ar = " + ar); //System.out.println("crd = " + a); assertEquals("c == integer(modular(c))", c, a); } } /** * Test chinese remainder. */ public void testChineseRemainder() { java.math.BigInteger p1 = getPrime1(); java.math.BigInteger p2 = getPrime2(); java.math.BigInteger p12 = p1.multiply(p2); ModIntegerRing pm1 = new ModIntegerRing(p1); GenPolynomialRing mfac1 = new GenPolynomialRing(pm1, rl, to); ModIntegerRing pm2 = new ModIntegerRing(p2); GenPolynomialRing mfac2 = new GenPolynomialRing(pm2, rl, to); ModIntegerRing pm12 = new ModIntegerRing(p12); GenPolynomialRing mfac = new GenPolynomialRing(pm12, rl, to); ModInteger di = pm2.create(p1); di = di.inverse(); //System.out.println("di = " + di); GenPolynomial am; GenPolynomial bm; GenPolynomial cm; ExpVector degv, qdegv; for (int i = 0; i < 3; i++) { c = dfac.random((59 + 29) / 2, ll * (i + 1), el + i, q); //c = c.multiply( new BigInteger(99) ); // fails, since not primitive //c = GreatestCommonDivisor.primitivePart(c); degv = c.degreeVector(); //System.out.println("degv = " + degv); assertTrue("length( c" + i + " ) <> 0", c.length() >= 0); assertTrue(" not isZERO( c" + i + " )", !c.isZERO()); assertTrue(" not isONE( c" + i + " )", !c.isONE()); am = PolyUtil. fromIntegerCoefficients(mfac1, c); qdegv = am.degreeVector(); //System.out.println("qdegv = " + qdegv); if (!degv.equals(qdegv)) { continue; } bm = PolyUtil. fromIntegerCoefficients(mfac2, c); qdegv = bm.degreeVector(); //System.out.println("qdegv = " + qdegv); if (!degv.equals(qdegv)) { continue; } cm = PolyUtil.chineseRemainder(mfac, am, di, bm); a = PolyUtil.integerFromModularCoefficients(dfac, cm); //System.out.println("c = " + c); //System.out.println("am = " + am); //System.out.println("bm = " + bm); //System.out.println("cm = " + cm); //System.out.println("a = " + a); assertEquals("cra(c mod p1,c mod p2) = c", c, a); } } /** * Test complex conversion. */ public void testComplexConversion() { BigRational rf = new BigRational(1); GenPolynomialRing rfac = new GenPolynomialRing(rf, rl, to); BigComplex cf = new BigComplex(1); GenPolynomialRing cfac = new GenPolynomialRing(cf, rl, to); BigComplex imag = BigComplex.I; GenPolynomial rp; GenPolynomial ip; GenPolynomial crp; GenPolynomial cip; GenPolynomial cp; GenPolynomial ap; for (int i = 0; i < 3; i++) { cp = cfac.random(kl + 2 * i, ll * (i + 1), el + i, q); assertTrue("length( c" + i + " ) <> 0", cp.length() >= 0); assertTrue(" not isZERO( c" + i + " )", !cp.isZERO()); assertTrue(" not isONE( c" + i + " )", !cp.isONE()); rp = PolyUtil.realPart(rfac, cp); ip = PolyUtil.imaginaryPart(rfac, cp); crp = PolyUtil.complexFromRational(cfac, rp); cip = PolyUtil.complexFromRational(cfac, ip); ap = crp.sum(cip.multiply(imag)); //System.out.println("cp = " + cp); //System.out.println("rp = " + rp); //System.out.println("ip = " + ip); //System.out.println("crp = " + crp); //System.out.println("cip = " + cip); //System.out.println("ap = " + ap); assertEquals("re(c)+i*im(c) = c", cp, ap); } } /** * Test base pseudo division. */ public void testBasePseudoDivision() { String[] names = new String[] { "x" }; dfac = new GenPolynomialRing(new BigInteger(1),to,names); GenPolynomialRing rdfac = new GenPolynomialRing(new BigRational(1),dfac); //System.out.println("\ndfac = " + dfac); //System.out.println("rdfac = " + rdfac); a = dfac.random(kl, 2*ll, el+17, q); //a = dfac.parse(" 3 x^5 + 44 "); //b = a; b = dfac.random(kl, 2*ll, el+3, q); //a = a.multiply(b); //a = a.sum(b); //b = dfac.parse(" 2 x^2 + 40 "); //System.out.println("a = " + a); //System.out.println("b = " + b); GenPolynomial[] QR = PolyUtil. basePseudoQuotientRemainder(a, b); c = QR[1]; d = QR[0]; //System.out.println("q = " + d); //System.out.println("r = " + c); boolean t = PolyUtil. isBasePseudoQuotientRemainder(a, b, d, c); assertTrue("lc^n a = q b + r: " + c, t); GenPolynomial ap = PolyUtil. fromIntegerCoefficients(rdfac,a); GenPolynomial bp = PolyUtil. fromIntegerCoefficients(rdfac,b); GenPolynomial cp = PolyUtil. fromIntegerCoefficients(rdfac,c); GenPolynomial dp = PolyUtil. fromIntegerCoefficients(rdfac,d); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); ////System.out.println("dp = " + dp); //System.out.println("dp = " + dp.monic()); GenPolynomial qp = ap.divide(bp); GenPolynomial rp = ap.remainder(bp); //System.out.println("qp = " + qp); //System.out.println("qp = " + qp.monic()); //System.out.println("rp = " + rp); GenPolynomial rhs = qp.multiply(bp).sum(rp); //System.out.println("qp bp + rp = " + rhs); assertEquals("ap = qp bp + rp: ", ap, rhs); assertEquals("cp = rp: ", rp.monic(), cp.monic() ); assertEquals("dp = qp: ", qp.monic(), dp.monic() ); // ?? //System.out.println("dp = qp: " + qp.monic().equals(dp.monic()) ); } /** * Test base sparse pseudo division. */ public void testBasePseudoDivisionSparse() { String[] names = new String[] { "x" }; dfac = new GenPolynomialRing(new BigInteger(1),to,names); GenPolynomialRing rdfac = new GenPolynomialRing(new BigRational(1),dfac); //System.out.println("\ndfac = " + dfac); //System.out.println("rdfac = " + rdfac); a = dfac.random(kl, 2*ll, el+17, q); //a = dfac.parse(" 3 x^5 + 44 "); //b = a; b = dfac.random(kl, 2*ll, el+3, q); //a = a.multiply(b); //a = a.sum(b); //b = dfac.parse(" 2 x^2 + 40 "); //System.out.println("a = " + a); //System.out.println("b = " + b); d = PolyUtil. basePseudoDivide(a, b); //System.out.println("q = " + d); c = PolyUtil. baseSparsePseudoRemainder(a, b); //System.out.println("r = " + c); boolean t = PolyUtil. isBasePseudoQuotientRemainder(a, b, d, c); assertTrue("lc^n a = q b + r: " + c, t); GenPolynomial ap = PolyUtil. fromIntegerCoefficients(rdfac,a); GenPolynomial bp = PolyUtil. fromIntegerCoefficients(rdfac,b); GenPolynomial cp = PolyUtil. fromIntegerCoefficients(rdfac,c); GenPolynomial dp = PolyUtil. fromIntegerCoefficients(rdfac,d); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); ////System.out.println("dp = " + dp); //System.out.println("dp = " + dp.monic()); GenPolynomial qp = ap.divide(bp); GenPolynomial rp = ap.remainder(bp); //System.out.println("qp = " + qp); //System.out.println("qp = " + qp.monic()); //System.out.println("rp = " + rp); GenPolynomial rhs = qp.multiply(bp).sum(rp); //System.out.println("qp bp + rp = " + rhs); assertEquals("ap = qp bp + rp: ", ap, rhs); assertEquals("cp = rp: ", rp.monic(), cp.monic() ); assertEquals("dp = qp: ", qp.monic(), dp.monic() ); // ?? //System.out.println("dp = qp: " + qp.monic().equals(dp.monic()) ); } /** * Test base dense pseudo division. */ public void testBasePseudoDivisionDense() { String[] names = new String[] { "x" }; dfac = new GenPolynomialRing(new BigInteger(1),to,names); GenPolynomialRing rdfac = new GenPolynomialRing(new BigRational(1),dfac); //System.out.println("\ndfac = " + dfac); //System.out.println("rdfac = " + rdfac); a = dfac.random(kl, 2*ll, el+17, q); //a = dfac.parse(" 3 x^5 + 44 "); //b = a; b = dfac.random(kl, 2*ll, el+3, q); //a = a.multiply(b); //a = a.sum(b); //b = dfac.parse(" 2 x^2 + 40 "); //System.out.println("a = " + a); //System.out.println("b = " + b); d = PolyUtil. baseDensePseudoQuotient(a, b); //System.out.println("q = " + d); c = PolyUtil. baseDensePseudoRemainder(a, b); //System.out.println("r = " + c); boolean t = PolyUtil. isBasePseudoQuotientRemainder(a, b, d, c); assertTrue("lc^n a = q b + r: " + c, t); GenPolynomial ap = PolyUtil. fromIntegerCoefficients(rdfac,a); GenPolynomial bp = PolyUtil. fromIntegerCoefficients(rdfac,b); GenPolynomial cp = PolyUtil. fromIntegerCoefficients(rdfac,c); GenPolynomial dp = PolyUtil. fromIntegerCoefficients(rdfac,d); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); ////System.out.println("dp = " + dp); //System.out.println("dp = " + dp.monic()); GenPolynomial qp = ap.divide(bp); GenPolynomial rp = ap.remainder(bp); //System.out.println("qp = " + qp); //System.out.println("qp = " + qp.monic()); //System.out.println("rp = " + rp); GenPolynomial rhs = qp.multiply(bp).sum(rp); //System.out.println("qp bp + rp = " + rhs); assertEquals("ap = qp bp + rp: ", ap, rhs); assertEquals("cp = rp: ", rp.monic(), cp.monic() ); assertEquals("dp = qp: ", qp.monic(), dp.monic() ); // ?? //System.out.println("dp = qp: " + qp.monic().equals(dp.monic()) ); } /** * Test recursive pseudo division. * @see edu.jas.ufd.PolyUfdUtilTest#testRecursivePseudoDivisionSparse */ public void testRecursivePseudoDivision() { } /** * Test evaluate main recursive. */ public void testEvalMainRecursive() { ai = (new BigInteger()).random(kl); //System.out.println("ai = " + ai); ar = rfac.getZERO(); //System.out.println("ar = " + ar); a = PolyUtil. evaluateMainRecursive(cfac, ar, ai); //System.out.println("a = " + a); assertTrue("isZERO( a )", a.isZERO()); ar = rfac.getONE(); //System.out.println("ar = " + ar); a = PolyUtil. evaluateMainRecursive(cfac, ar, ai); //System.out.println("a = " + a); assertTrue("isONE( a )", a.isONE()); //ar = rfac.getONE(); ar = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //br = rfac.getONE(); br = rfac.random(kl, ll, el, q); //System.out.println("br = " + br); cr = br.sum(ar); //System.out.println("cr = " + cr); a = PolyUtil. evaluateMainRecursive(cfac, ar, ai); b = PolyUtil. evaluateMainRecursive(cfac, br, ai); c = PolyUtil. evaluateMainRecursive(cfac, cr, ai); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); d = a.sum(b); //System.out.println("d = " + d); assertEquals("eval(a+b) == eval(a) + eval(b)", c, d); cr = br.multiply(ar); //System.out.println("cr = " + cr); a = PolyUtil. evaluateMainRecursive(cfac, ar, ai); b = PolyUtil. evaluateMainRecursive(cfac, br, ai); c = PolyUtil. evaluateMainRecursive(cfac, cr, ai); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); d = a.multiply(b); //System.out.println("d = " + d); assertEquals("eval(a*b) == eval(a) * eval(b)", c, d); } /** * Test evaluate main. */ public void testEvalMain() { ei = (new BigInteger()).random(kl); //System.out.println("ei = " + ei); cfac = new GenPolynomialRing(new BigInteger(1), 1, to); //System.out.println("cfac = " + cfac); a = cfac.getZERO(); //System.out.println("a = " + a); ai = PolyUtil. evaluateMain(ei, a, ei); //System.out.println("ai = " + ai); assertTrue("isZERO( ai )", ai.isZERO()); a = cfac.getONE(); //System.out.println("a = " + a); ai = PolyUtil. evaluateMain(ei, a, ei); //System.out.println("ai = " + ai); assertTrue("isONE( ai )", ai.isONE()); //a = cfac.getONE(); a = cfac.random(kl, ll, el, q); //System.out.println("a = " + a); //b = cfac.getONE(); b = cfac.random(kl, ll, el, q); //System.out.println("b = " + b); c = b.sum(a); //System.out.println("c = " + c); ai = PolyUtil. evaluateMain(ei, a, ei); bi = PolyUtil. evaluateMain(ei, b, ei); ci = PolyUtil. evaluateMain(ei, c, ei); //System.out.println("ai = " + ai); //System.out.println("bi = " + bi); //System.out.println("ci = " + ci); di = bi.sum(ai); //System.out.println("di = " + di); assertEquals("eval(a+b) == eval(a) + eval(b)", ci, di); c = b.multiply(a); //System.out.println("c = " + c); ai = PolyUtil. evaluateMain(ei, a, ei); bi = PolyUtil. evaluateMain(ei, b, ei); ci = PolyUtil. evaluateMain(ei, c, ei); //System.out.println("ai = " + ai); //System.out.println("bi = " + bi); //System.out.println("ci = " + ci); di = bi.multiply(ai); //System.out.println("di = " + di); assertEquals("eval(a*b) == eval(a) * eval(b)", ci, di); } /** * Test evaluate first. */ public void testEvalFirst() { ei = (new BigInteger()).random(kl); //System.out.println("ei = " + ei); GenPolynomial ae, be, ce, de; GenPolynomialRing fac; fac = new GenPolynomialRing(new BigInteger(1), rl, to); //System.out.println("fac = " + fac); cfac = new GenPolynomialRing(new BigInteger(1), 1, to); //System.out.println("cfac = " + cfac); dfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to); //System.out.println("dfac = " + dfac); a = fac.getZERO(); //System.out.println("a = " + a); ae = PolyUtil. evaluateFirst(cfac, dfac, a, ei); //System.out.println("ae = " + ae); assertTrue("isZERO( ae )", ae.isZERO()); a = fac.getONE(); //System.out.println("a = " + a); ae = PolyUtil. evaluateFirst(cfac, dfac, a, ei); //System.out.println("ae = " + ae); assertTrue("isONE( ae )", ae.isONE()); //a = fac.getONE(); a = fac.random(kl, ll, el, q); //System.out.println("a = " + a); //b = fac.getONE(); b = fac.random(kl, ll, el, q); //System.out.println("b = " + b); c = b.sum(a); //System.out.println("c = " + c); ae = PolyUtil. evaluateFirst(cfac, dfac, a, ei); be = PolyUtil. evaluateFirst(cfac, dfac, b, ei); ce = PolyUtil. evaluateFirst(cfac, dfac, c, ei); //System.out.println("ae = " + ae); //System.out.println("be = " + be); //System.out.println("ce = " + ce); de = be.sum(ae); //System.out.println("de = " + de); assertEquals("eval(a+b) == eval(a) + eval(b)", ce, de); c = b.multiply(a); //System.out.println("c = " + c); ae = PolyUtil. evaluateFirst(cfac, dfac, a, ei); be = PolyUtil. evaluateFirst(cfac, dfac, b, ei); ce = PolyUtil. evaluateFirst(cfac, dfac, c, ei); //System.out.println("ae = " + ae); //System.out.println("be = " + be); //System.out.println("ce = " + ce); de = be.multiply(ae); //System.out.println("de = " + de); assertEquals("eval(a*b) == eval(a) * eval(b)", ce, de); } /** * Test evaluate all. */ public void testEvalAll() { BigInteger cfac = new BigInteger(); List Ev = new ArrayList(); for (int i = 0; i < rl; i++) { ei = cfac.random(kl); Ev.add(ei); } //System.out.println("Ev = " + Ev); BigInteger ae, be, ce, de; GenPolynomialRing fac; fac = new GenPolynomialRing(cfac, rl, to); //System.out.println("fac = " + fac); a = fac.getZERO(); //System.out.println("a = " + a); ae = PolyUtil. evaluateAll(cfac, dfac, a, Ev); //System.out.println("ae = " + ae); assertTrue("isZERO( ae )", ae.isZERO()); a = fac.getONE(); //System.out.println("a = " + a); ae = PolyUtil. evaluateAll(cfac, dfac, a, Ev); //System.out.println("ae = " + ae); assertTrue("isONE( ae )", ae.isONE()); //a = fac.getONE(); a = fac.random(kl, ll, el, q); //System.out.println("a = " + a); //b = fac.getONE(); b = fac.random(kl, ll, el, q); //System.out.println("b = " + b); c = b.sum(a); //System.out.println("c = " + c); ae = PolyUtil. evaluateAll(cfac, dfac, a, Ev); be = PolyUtil. evaluateAll(cfac, dfac, b, Ev); ce = PolyUtil. evaluateAll(cfac, dfac, c, Ev); //System.out.println("ae = " + ae); //System.out.println("be = " + be); //System.out.println("ce = " + ce); de = be.sum(ae); //System.out.println("de = " + de); assertEquals("eval(a+b) == eval(a) + eval(b)", ce, de); c = b.multiply(a); //System.out.println("c = " + c); ce = PolyUtil. evaluateAll(cfac, dfac, c, Ev); //System.out.println("ae = " + ae); //System.out.println("be = " + be); //System.out.println("ce = " + ce); de = be.multiply(ae); //System.out.println("de = " + de); assertEquals("eval(a*b) == eval(a) * eval(b)", ce, de); } /** * Test interpolate univariate 1 polynomial. */ public void testInterpolateUnivariateOne() { ModInteger ai, bi, ci, di, ei, fi, gi, hi; GenPolynomial a; GenPolynomialRing cfac; ModIntegerRing fac; GenPolynomial r; GenPolynomial Q; GenPolynomial Qp; fac = new ModIntegerRing(19); //System.out.println("fac.modul = " + fac.getModul()); cfac = new GenPolynomialRing(fac, 1, to); //System.out.println("cfac = " + cfac); a = cfac.getONE(); //System.out.println("a = " + a); ei = fac.fromInteger(11); //System.out.println("ei = " + ei); // a(ei) ai = PolyUtil. evaluateMain(fac, a, ei); //System.out.println("ai = " + ai); assertTrue("isONE( ai )", ai.isONE()); di = fac.fromInteger(13); //System.out.println("di = " + di); // a(di) bi = PolyUtil. evaluateMain(fac, a, di); //System.out.println("bi = " + bi); assertTrue("isONE( bi )", bi.isONE()); // interpolation result r = cfac.getZERO(); //System.out.println("r = " + r); // interpolation polynomials product Q = cfac.getONE(); //System.out.println("Q = " + Q); ci = PolyUtil. evaluateMain(fac, Q, ei); //System.out.println("ci = " + ci); // Q(ei)^-1 fi = ci.inverse(); //System.out.println("fi = " + fi); r = PolyUtil. interpolate(cfac, r, Q, fi, ai, ei); //System.out.println("r = " + r); // next evaluation polynomial Qp = cfac.univariate(0); Qp = Qp.subtract(cfac.getONE().multiply(ei)); //System.out.println("Qp = " + Qp); Q = Q.multiply(Qp); //System.out.println("Q = " + Q); ci = PolyUtil. evaluateMain(fac, Q, di); //System.out.println("ci = " + ci); // Q(di)^-1 fi = ci.inverse(); //System.out.println("fi = " + fi); r = PolyUtil. interpolate(cfac, r, Q, fi, bi, di); //System.out.println("r = " + r); // check evaluation gi = PolyUtil. evaluateMain(fac, r, ei); //System.out.println("gi = " + gi); hi = PolyUtil. evaluateMain(fac, r, di); //System.out.println("hi = " + hi); assertTrue("gi == 1 ", gi.isONE()); assertTrue("hi == 1 ", hi.isONE()); // interpolate( a(ei), a(di) ) = a (mod 19) assertEquals("interpolate(a mod (x-ei),a mod (x-di)) = a (mod 19)", a, r); } /** * Test interpolate univariate deg > 0 polynomial. */ public void testInterpolateUnivariate() { ModInteger ai, ci, ei, fi; GenPolynomial a; GenPolynomialRing cfac; ModIntegerRing fac; GenPolynomial r; GenPolynomial Q; GenPolynomial Qp; //long prime = 19; long prime = getPrime1().longValue(); fac = new ModIntegerRing(prime); //System.out.println("fac.modul = " + fac.getModul()); cfac = new GenPolynomialRing(fac, 1, to); //System.out.println("cfac = " + cfac); int maxdeg = 19; // polynomial to interpolate long deg = 0; do { a = cfac.random(kl, ll, maxdeg, q); if (!a.isZERO()) { deg = a.degree(0); } } while (deg <= 0); //System.out.println("a = " + a); //System.out.println("deg = " + deg); // interpolation result r = cfac.getZERO(); //System.out.println("r = " + r); // interpolation polynomials product Q = cfac.getONE(); //System.out.println("Q = " + Q); long i = -1; long qdeg; do { i++; if (i >= prime) { assertTrue("elements of Z_prime exhausted", i < prime); } qdeg = Q.degree(0); ei = fac.fromInteger(i); //System.out.println("ei = " + ei); // a(ei) ai = PolyUtil. evaluateMain(fac, a, ei); //System.out.println("ai = " + ai); ci = PolyUtil. evaluateMain(fac, Q, ei); //System.out.println("ci = " + ci); // Q(ei)^-1 fi = ci.inverse(); //System.out.println("fi = " + fi); r = PolyUtil. interpolate(cfac, r, Q, fi, ai, ei); //System.out.println("r = " + r); // next evaluation polynomial Qp = cfac.univariate(0); Qp = Qp.subtract(cfac.getONE().multiply(ei)); //System.out.println("Qp = " + Qp); Q = Q.multiply(Qp); //System.out.println("Q = " + Q); } while (qdeg < deg); //System.out.println("a = " + a); //System.out.println("r = " + r); // interpolate( a(e1), ..., a(ei) ) = a (mod 19) assertEquals("interpolate(a mod (x-e1),...,a mod (x-ei)) = a (mod 19)", a, r); } /** * Test interpolate multivariate deg > 0 polynomial. */ public void testInterpolateMultivariate() { ModInteger ci, ei, fi; GenPolynomial ap, bp; GenPolynomial> a; GenPolynomialRing> cfac; GenPolynomialRing ufac; GenPolynomialRing dfac; ModIntegerRing fac; GenPolynomial> r; GenPolynomial Q; GenPolynomial Qp; //long prime = 19; long prime = getPrime1().longValue(); fac = new ModIntegerRing(prime); //System.out.println("fac.modul = " + fac.getModul()); ufac = new GenPolynomialRing(fac, 1, to); //System.out.println("ufac = " + ufac); cfac = new GenPolynomialRing>(ufac, rl, to); //System.out.println("cfac = " + cfac); dfac = new GenPolynomialRing(fac, rl, to); //System.out.println("dfac = " + dfac); int maxdeg = 19; // polynomial to interpolate long deg = 0; do { a = cfac.random(kl, ll + 9, maxdeg, q); if (!a.isZERO()) { deg = PolyUtil. coeffMaxDegree(a); } } while (deg <= 0); //System.out.println("a = " + a); //System.out.println("deg = " + deg); ExpVector degv = a.degreeVector(); //System.out.println("degv = " + degv); // interpolation result r = cfac.getZERO(); //System.out.println("r = " + r); // interpolation polynomials product Q = ufac.getONE(); //System.out.println("Q = " + Q); long i = -1; long qdeg; ExpVector qdegv; do { i++; if (i >= prime) { assertTrue("elements of Z_prime exhausted", i < prime); } qdeg = Q.degree(0); ei = fac.fromInteger(i); //System.out.println("ei = " + ei); // a(ei) ap = PolyUtil. evaluateFirstRec(ufac, dfac, a, ei); //System.out.println("ap = " + ap); qdegv = ap.degreeVector(); //System.out.println("qdegv = " + qdegv); if (!degv.equals(qdegv)) { continue; } ci = PolyUtil. evaluateMain(fac, Q, ei); //System.out.println("ci = " + ci); // Q(ei)^-1 fi = ci.inverse(); //System.out.println("fi = " + fi); r = PolyUtil. interpolate(cfac, r, Q, fi, ap, ei); //System.out.println("r = " + r); // check bp = PolyUtil. evaluateFirstRec(ufac, dfac, r, ei); //System.out.println("bp = " + bp); assertEquals("interpolate(a)(ei) == a ", bp, ap); // next evaluation polynomial Qp = ufac.univariate(0); Qp = Qp.subtract(ufac.getONE().multiply(ei)); //System.out.println("Qp = " + Qp); Q = Q.multiply(Qp); //System.out.println("Q = " + Q); } while (qdeg <= deg); //System.out.println("a = " + a); //System.out.println("r = " + r); // interpolate( a(e1), ..., a(ei) ) = a (mod 19) assertEquals("interpolate(a mod (x-e1),...,a mod (x-ei)) = a (mod 19)", a, r); } /** * Test interpolate rational multivariate deg > 0 polynomial. */ public void testInterpolateRationalMultivariate() { BigRational ci, ei, fi; GenPolynomial ap, bp; GenPolynomial> a; GenPolynomialRing> cfac; GenPolynomialRing ufac; GenPolynomialRing dfac; BigRational fac; GenPolynomial> r; GenPolynomial Q; GenPolynomial Qp; fac = new BigRational(); //System.out.println("fac.modul = " + fac.getModul()); ufac = new GenPolynomialRing(fac, 1, to); //System.out.println("ufac = " + ufac); cfac = new GenPolynomialRing>(ufac, rl, to); //System.out.println("cfac = " + cfac); dfac = new GenPolynomialRing(fac, rl, to); //System.out.println("dfac = " + dfac); int maxdeg = 19; // polynomial to interpolate long deg = 0; do { a = cfac.random(kl, ll + 9, maxdeg, q); if (!a.isZERO()) { deg = PolyUtil. coeffMaxDegree(a); } } while (deg <= 0); //System.out.println("a = " + a); //System.out.println("deg = " + deg); ExpVector degv = a.degreeVector(); //System.out.println("degv = " + degv); // interpolation result r = cfac.getZERO(); //System.out.println("r = " + r); // interpolation polynomials product Q = ufac.getONE(); //System.out.println("Q = " + Q); long i = -1; long qdeg; ExpVector qdegv; do { i++; qdeg = Q.degree(0); ei = fac.fromInteger(i); //System.out.println("ei = " + ei); // a(ei) ap = PolyUtil. evaluateFirstRec(ufac, dfac, a, ei); //System.out.println("ap = " + ap); qdegv = ap.degreeVector(); //System.out.println("qdegv = " + qdegv); if (!degv.equals(qdegv)) { continue; } ci = PolyUtil. evaluateMain(fac, Q, ei); //System.out.println("ci = " + ci); // Q(ei)^-1 fi = ci.inverse(); //System.out.println("fi = " + fi); r = PolyUtil. interpolate(cfac, r, Q, fi, ap, ei); //System.out.println("r = " + r); // check bp = PolyUtil. evaluateFirstRec(ufac, dfac, r, ei); //System.out.println("bp = " + bp); assertEquals("interpolate(a)(ei) == a ", bp, ap); // next evaluation polynomial Qp = ufac.univariate(0); Qp = Qp.subtract(ufac.getONE().multiply(ei)); //System.out.println("Qp = " + Qp); Q = Q.multiply(Qp); //System.out.println("Q = " + Q); } while (qdeg <= deg); //System.out.println("a = " + a); //System.out.println("r = " + r); // interpolate( a(e1), ..., a(ei) ) = a (mod 19) assertEquals("interpolate(a mod (x-e1),...,a mod (x-ei)) = a (mod 19)", a, r); } /** * Test coefficient map function. */ public void testMap() { // integers BigInteger fi = new BigInteger(); //System.out.println("fi = " + fi); // rational numbers BigRational fr = new BigRational(); //System.out.println("fr = " + fr); // modular integers ModIntegerRing fm = new ModIntegerRing(17); //System.out.println("fm = " + fm); // polynomials over integral numbers GenPolynomialRing pfi = new GenPolynomialRing(fi, rl); //System.out.println("pfi = " + pfi); // polynomials over rational numbers GenPolynomialRing pfr = new GenPolynomialRing(fr, rl); //System.out.println("pfr = " + pfr); // polynomials over modular integers GenPolynomialRing pfm = new GenPolynomialRing(fm, rl); //System.out.println("pfm = " + pfm); // random polynomial GenPolynomial pi = pfi.random(kl, 2 * ll, el, q); //System.out.println("pi = " + pi); // random polynomial GenPolynomial pr = pfr.random(kl, 2 * ll, el, q).monic(); //System.out.println("pr = " + pr); // random polynomial GenPolynomial pm = pfm.random(kl, 2 * ll, el, q); //System.out.println("pm = " + pm); // test integer to rational and back GenPolynomial qr; GenPolynomial qi; qr = PolyUtil. map(pfr, pi, new FromInteger(fr)); qi = PolyUtil. map(pfi, qr, new RatNumer()); //System.out.println("qr = " + qr); //System.out.println("qi = " + qi); assertEquals("pi == qi ", pi, qi); // test rational to integer and back qi = PolyUtil.integerFromRationalCoefficients(pfi, pr); qr = PolyUtil. map(pfr, qi, new FromInteger(fr)); qr = qr.monic(); //System.out.println("pr = " + pr); //System.out.println("qr = " + qr); //System.out.println("qi = " + qi); assertEquals("pr == qr ", pr, qr); // test symmetric modular integer to integer and back GenPolynomial qm; qi = PolyUtil. map(pfi, pm, new ModSymToInt()); qm = PolyUtil. map(pfm, qi, new FromInteger(fm)); //System.out.println("qi = " + qi); //System.out.println("qm = " + qm); assertEquals("pm == qm ", pm, qm); // test modular integer to integer and back qi = PolyUtil. map(pfi, pm, new ModToInt()); qm = PolyUtil. map(pfm, qi, new FromInteger(fm)); //System.out.println("qi = " + qi); //System.out.println("qm = " + qm); assertEquals("pm == qm ", pm, qm); // test symmetric modular integer to integer to rational and back qi = PolyUtil. map(pfi, pm, new ModSymToInt()); qr = PolyUtil. map(pfr, qi, new FromInteger(fr)); qi = PolyUtil. map(pfi, qr, new RatNumer()); qm = PolyUtil. map(pfm, qi, new FromInteger(fm)); //System.out.println("qi = " + qi); //System.out.println("qm = " + qm); assertEquals("pm == qm ", pm, qm); } /** * Test substitution. */ public void testSubstitution() { dfac = new GenPolynomialRing(new BigInteger(1), 1, to); // subs = x - 7 GenPolynomial s = dfac.univariate(0).subtract(dfac.fromInteger(7)); GenPolynomial s1 = dfac.univariate(0).sum(dfac.fromInteger(7)); //System.out.println("s = " + s); //System.out.println("s1 = " + s1); for (int i = 0; i < 5; i++) { a = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); b = PolyUtil. substituteMain(a, s); c = PolyUtil. substituteMain(b, s1); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("a == c " + a.equals(c)); assertEquals("a == c ", a, c); } } /** * Test algebraic substitution. */ public void testAlgebraicSubstitution() { BigRational cfac = new BigRational(1); String[] alpha = new String[] { "alpha" }; String[] vars = new String[] { "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, alpha); GenPolynomial agen = pfac.univariate(0, 2); agen = agen.sum(pfac.getONE()); // x^2 + 1 AlgebraicNumberRing afac = new AlgebraicNumberRing(agen, true); GenPolynomialRing> apfac = new GenPolynomialRing>(afac, 1, to, vars); // univariate //System.out.println("agen = " + agen); //System.out.println("afac = " + afac); //System.out.println("apfac = " + apfac); // subs = x - 7 GenPolynomial> s = apfac.univariate(0).subtract(apfac.fromInteger(7).multiply(afac.getGenerator())); GenPolynomial> s1 = apfac.univariate(0).sum(apfac.fromInteger(7).multiply(afac.getGenerator())); //System.out.println("s = " + s); //System.out.println("s1 = " + s1); GenPolynomial> a, b, c; for (int i = 0; i < 5; i++) { a = apfac.random(kl, ll, el, q); //System.out.println("a = " + a); b = PolyUtil.> substituteMain(a, s); c = PolyUtil.> substituteMain(b, s1); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("a == c " + a.equals(c)); assertEquals("a == c ", a, c); } } /** * Test switch variables. */ public void testSwitchVariables() { BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, rl, to); GenPolynomialRing> rfac = new GenPolynomialRing>(pfac, rl, to); //System.out.println("pfac = " + pfac); //System.out.println("rfac = " + rfac); GenPolynomial> a, c; GenPolynomial> b; for (int i = 0; i < 5; i++) { a = rfac.random(kl, ll, el, q); //System.out.println("a = " + a); b = PolyUtil. switchVariables(a); c = PolyUtil. switchVariables(b); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("a == c " + a.equals(c)); assertEquals("a == c ", a, c); } } /** * Test algebraic conversions. */ public void testAlgebraicConversions() { BigRational cfac = new BigRational(1); String[] alpha = new String[] { "alpha" }; //String[] vars = new String[] { "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, alpha); GenPolynomial agen = pfac.univariate(0, 2); agen = agen.sum(pfac.getONE()); // x^2 + 1 AlgebraicNumberRing afac = new AlgebraicNumberRing(agen, true); GenPolynomialRing> apfac = new GenPolynomialRing>(afac, rl, to); GenPolynomialRing> rfac = new GenPolynomialRing>(pfac, rl, to); //System.out.println("agen = " + agen); //System.out.println("afac = " + afac); //System.out.println("apfac = " + apfac); //System.out.println("pfac = " + pfac); //System.out.println("rfac = " + rfac); GenPolynomial> a, c; GenPolynomial> b; for (int i = 0; i < 5; i++) { a = apfac.random(kl, ll, el, q); //System.out.println("a = " + a); b = PolyUtil. fromAlgebraicCoefficients(rfac, a); c = PolyUtil. convertRecursiveToAlgebraicCoefficients(apfac, b); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("a == c " + a.equals(c)); assertEquals("a == c ", a, c); } } /** * Test Taylor series. */ public void testTaylorSeries() { GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomialRing dfac; BigRational cfac; cfac = new BigRational(1); String[] vars = new String[] { "x" }; dfac = new GenPolynomialRing(cfac, 1, to, vars); a = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); BigRational v = cfac.getZERO(); //System.out.println("v = " + v); b = PolyUtil. seriesOfTaylor(a, v); //System.out.println("taylor(a,0) = " + b); assertTrue("taylor(a,0) == a ", a.equals(b)); v = cfac.random(kl); //System.out.println("v = " + v); b = PolyUtil. seriesOfTaylor(a, v); //System.out.println("taylor(a,v) = " + b); c = PolyUtil. seriesOfTaylor(b, v.negate()); //System.out.println("tailor(taylor(a,v),-v) = " + c); assertTrue("tailor(taylor(a,v),-v) == a ", a.equals(c)); } /** * Test Complex real and imaginary part. */ public void testComplexParts() { BigRational rf = new BigRational(1); GenPolynomialRing rfac = new GenPolynomialRing(rf, rl, to); ComplexRing cf = new ComplexRing(new BigRational(1)); GenPolynomialRing> cfac = new GenPolynomialRing>(cf, rl, to); Complex imag = cf.getIMAG(); GenPolynomial rp; GenPolynomial ip; GenPolynomial> crp; GenPolynomial> cip; GenPolynomial> cp; GenPolynomial> ap; for (int i = 0; i < 3; i++) { cp = cfac.random(kl + 2 * i, ll * (i + 1), el + i, q); assertTrue("length( c" + i + " ) <> 0", cp.length() >= 0); assertTrue(" not isZERO( c" + i + " )", !cp.isZERO()); assertTrue(" not isONE( c" + i + " )", !cp.isONE()); rp = PolyUtil. realPartFromComplex(rfac, cp); ip = PolyUtil. imaginaryPartFromComplex(rfac, cp); crp = PolyUtil. toComplex(cfac, rp); cip = PolyUtil. toComplex(cfac, ip); ap = crp.sum(cip.multiply(imag)); //System.out.println("cp = " + cp); //System.out.println("rp = " + rp); //System.out.println("ip = " + ip); //System.out.println("crp = " + crp); //System.out.println("cip = " + cip); //System.out.println("ap = " + ap); assertEquals("re(c)+i*im(c) = c", cp, ap); } } /** * Test product represenation conversion, rational numbers. */ public void testProductConversionRN() { GenPolynomialRing ufac; ufac = new GenPolynomialRing(new BigRational(1), 1); ProductRing> pfac; pfac = new ProductRing>(ufac, rl); GenPolynomialRing dfac = new GenPolynomialRing(new BigRational(1), rl, to); GenPolynomial c; Product> cp; c = dfac.getONE(); //System.out.println("c = " + c); cp = PolyUtil. toProduct(pfac, c); //System.out.println("cp = " + cp); assertTrue("isONE( cp )", cp.isONE()); c = dfac.random(kl, ll, el, q); //System.out.println("c = " + c); cp = PolyUtil. toProduct(pfac, c); //System.out.println("cp = " + cp); assertTrue("!isONE( cp )", !cp.isONE()); } /** * Test polynomal over product represenation conversion, algebraic numbers. */ public void testPolyProductConversionAN() { GenPolynomialRing ufac; ufac = new GenPolynomialRing(new BigRational(1), 1); GenPolynomial m; m = ufac.univariate(0, 2); m = m.subtract(ufac.univariate(0, 1)); //System.out.println("m = " + m); AlgebraicNumberRing afac; afac = new AlgebraicNumberRing(m); //System.out.println("afac = " + afac); ProductRing> pfac; pfac = new ProductRing>(afac, rl); GenPolynomialRing>> dpfac; dpfac = new GenPolynomialRing>>(pfac, 2); GenPolynomialRing> dfac; dfac = new GenPolynomialRing>(afac, 2, to); GenPolynomial> c; GenPolynomial>> cp; c = dfac.getONE(); //System.out.println("c = " + c); cp = PolyUtil.> toProductGen(dpfac, c); //System.out.println("cp = " + cp); assertTrue("isZERO( cp )", cp.isONE()); c = dfac.random(kl, ll, el, q); //System.out.println("c = " + c); cp = PolyUtil.> toProductGen(dpfac, c); //System.out.println("cp = " + cp); assertTrue("!isONE( cp )", !cp.isONE()); } /** * Test remove unused upper varaibles. */ public void testRemoveUnusedUpper() { //System.out.println("dfac = " + dfac); a = dfac.univariate(3, 2); b = a.subtract(dfac.univariate(1, 1)); //System.out.println("a = " + a); //System.out.println("b = " + b); c = PolyUtil. removeUnusedUpperVariables(b); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 4: " + c.ring.nvar, c.ring.nvar == 4); a = dfac.univariate(3, 2); //System.out.println("a = " + a); c = PolyUtil. removeUnusedUpperVariables(a); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 2: " + c.ring.nvar, c.ring.nvar == 2); a = dfac.univariate(1, 2); //System.out.println("a = " + a); c = PolyUtil. removeUnusedUpperVariables(a); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 4: " + c.ring.nvar, c.ring.nvar == 4); } /** * Test remove unused lower varaibles. */ public void testRemoveUnusedLower() { //System.out.println("dfac = " + dfac); a = dfac.univariate(3, 2); b = a.subtract(dfac.univariate(1, 1)); //System.out.println("a = " + a); //System.out.println("b = " + b); c = PolyUtil. removeUnusedLowerVariables(b); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 4: " + c.ring.nvar, c.ring.nvar == 4); a = dfac.univariate(3, 2); //System.out.println("a = " + a); c = PolyUtil. removeUnusedLowerVariables(a); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 4: " + c.ring.nvar, c.ring.nvar == 4); a = dfac.univariate(1, 2); //System.out.println("a = " + a); c = PolyUtil. removeUnusedLowerVariables(a); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 2: " + c.ring.nvar, c.ring.nvar == 2); } /** * Test remove unused middle varaibles. */ public void testRemoveUnusedMiddle() { //System.out.println("dfac = " + dfac); a = dfac.univariate(4, 2); b = a.subtract(dfac.univariate(0, 1)); //System.out.println("a = " + a); //System.out.println("b = " + b); c = PolyUtil. removeUnusedLowerVariables(b); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 5: " + c.ring.nvar, c.ring.nvar == 5); c = PolyUtil. removeUnusedUpperVariables(c); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 5: " + c.ring.nvar, c.ring.nvar == 5); c = PolyUtil. removeUnusedMiddleVariables(c); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 2: " + c.ring.nvar, c.ring.nvar == 2); a = dfac.univariate(3, 2); b = a.subtract(dfac.univariate(1, 1)); //System.out.println("a = " + a); //System.out.println("b = " + b); try { c = PolyUtil. removeUnusedMiddleVariables(b); fail("c = " + c + ", fac = " + c.ring); } catch (RuntimeException e) { // success } c = PolyUtil. removeUnusedLowerVariables(b); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 4: " + c.ring.nvar, c.ring.nvar == 4); c = PolyUtil. removeUnusedUpperVariables(c); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 3: " + c.ring.nvar, c.ring.nvar == 3); c = PolyUtil. removeUnusedMiddleVariables(c); //System.out.println("c = " + c + ", fac = " + c.ring); assertTrue("#var == 2: " + c.ring.nvar, c.ring.nvar == 2); } } jas-2.5/trc/edu/jas/poly/QuatGenPolynomialTest.java0000644000175000017500000001067111641660762022601 0ustar giovannigiovanni/* * $Id: QuatGenPolynomialTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigQuaternion; /** * BigQuaternion coefficients GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class QuatGenPolynomialTest extends TestCase { /** * main */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a QuatGenPolynomialTest object. * @param name String. */ public QuatGenPolynomialTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(QuatGenPolynomialTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing fac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 7; int kl = 10; int ll = 10; int el = 5; float q = 0.5f; protected void setUp() { a = b = c = d = e = null; fac = new GenPolynomialRing(new BigQuaternion(1),rl); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(ll); // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = fac.random(ll); ExpVector u = ExpVector.EVRAND(rl,el,q); BigQuaternion x = BigQuaternion.QRAND(kl); b = new GenPolynomial(fac,x, u); c = a.sum(b); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); a = new GenPolynomial(fac); b = new GenPolynomial(fac,x, u); c = b.sum(a); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("!isZERO( a*b-b*a ) " + e, !e.isZERO() ); assertTrue("a*b = b*a", !c.equals(d) ); //assertEquals("a*b = b*a",c,d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); BigQuaternion x = a.leadingBaseCoefficient().inverse(); c = a.monic(); d = a.multiply(x); assertEquals("a.monic() = a(1/ldcf(a))",c,d); BigQuaternion y = b.leadingBaseCoefficient().inverse(); c = b.monic(); d = b.multiply(y); assertEquals("b.monic() = b(1/ldcf(b))",c,d); e = new GenPolynomial(fac,y); d = b.multiply(e); assertEquals("b.monic() = b(1/ldcf(b))",c,d); //d = e.multiply(b); //assertEquals("b.monic() = (1/ldcf(b) (0))*b",c,d); } } jas-2.5/trc/edu/jas/poly/ResidueTest.java0000644000175000017500000002007411641660762020567 0ustar giovannigiovanni /* * $Id: ResidueTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; //import java.util.ArrayList; //import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.arith.BigInteger; //import edu.jas.structure.RingElem; /** * Residue test with JUnit. * @author Heinz Kredel. */ public class ResidueTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ResidueTest object. * @param name String. */ public ResidueTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ResidueTest.class); return suite; } ResidueRing fac; GenPolynomialRing pfac; ResidueRing< GenPolynomial > mfac; Residue< BigInteger > a; Residue< BigInteger > b; Residue< BigInteger > c; Residue< BigInteger > d; Residue< BigInteger > e; Residue< GenPolynomial > ap; Residue< GenPolynomial > bp; Residue< GenPolynomial > cp; Residue< GenPolynomial > dp; Residue< GenPolynomial > ep; int rl = 1; int kl = 13; int ll = 7; int el = 3; float q = 0.4f; int il = 2; long p = 1152921504606846883L; // 2^60-93; @Override protected void setUp() { a = b = c = d = e = null; ap = bp = cp = dp = ep = null; BigInteger cfac = new BigInteger(1); fac = new ResidueRing( cfac, new BigInteger( p ) ); pfac = new GenPolynomialRing( new BigRational(1), 1 ); GenPolynomial mo = pfac.random(kl,ll,el,q); while ( mo.isConstant() ) { mo = pfac.random(kl,ll,el,q); } mfac = new ResidueRing>( pfac, mo ); } @Override protected void tearDown() { a = b = c = d = e = null; ap = bp = cp = dp = ep = null; fac = null; pfac = null; mfac = null; } /** * Test constructor for integer. * */ public void testIntConstruction() { c = fac.getONE(); //System.out.println("c = " + c); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); //System.out.println("d = " + d); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test constructor for polynomial. * */ public void testPolyConstruction() { cp = mfac.getONE(); assertTrue("isZERO( cp )", !cp.isZERO() ); assertTrue("isONE( cp )", cp.isONE() ); dp = mfac.getZERO(); assertTrue("isZERO( dp )", dp.isZERO() ); assertTrue("isONE( dp )", !dp.isONE() ); } /** * Test random integer. * */ public void testIntRandom() { for (int i = 0; i < 7; i++) { a = fac.random(kl*(i+1)); if ( a.isZERO() ) { continue; } //a = fac.random(kl*(i+1), ll+2*i, el+i, q ); //System.out.println("a = " + a); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test random polynomial. * */ public void testPolyRandom() { for (int i = 0; i < 7; i++) { ap = mfac.random(kl+i); if ( ap.isZERO() ) { continue; } assertTrue(" not isZERO( ap"+i+" )", !ap.isZERO() ); assertTrue(" not isONE( ap"+i+" )", !ap.isONE() ); } } /** * Test integer addition. * */ public void testIntAddition() { a = fac.random(kl); b = fac.random(kl); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a",c,d); c = fac.random(kl); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test polynomial addition. * */ public void testPolyAddition() { ap = mfac.random(kl); bp = mfac.random(kl); //System.out.println("a = " + a); //System.out.println("b = " + b); cp = ap.sum(bp); dp = cp.subtract(bp); assertEquals("a+b-b = a",ap,dp); cp = ap.sum(bp); dp = bp.sum(ap); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",cp,dp); cp = mfac.random(kl); dp = cp.sum( ap.sum(bp) ); ep = cp.sum( ap ).sum(bp); assertEquals("c+(a+b) = (c+a)+b",dp,ep); cp = ap.sum( mfac.getZERO() ); dp = ap.subtract( mfac.getZERO() ); assertEquals("a+0 = a-0",cp,dp); cp = mfac.getZERO().sum( ap ); dp = mfac.getZERO().subtract( ap.negate() ); assertEquals("0+a = 0+(-a)",cp,dp); } /** * Test integer multiplication. * */ public void testIntMultiplication() { a = fac.random(kl); if ( a.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(kl); if ( b.isZERO() ) { return; } assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(kl); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",d.isONE()); } } /** * Test polynomial multiplication. * */ public void testPolyMultiplication() { ap = mfac.random(kl); if ( ap.isZERO() ) { return; } assertTrue("not isZERO( a )", !ap.isZERO() ); bp = mfac.random(kl); if ( bp.isZERO() ) { return; } assertTrue("not isZERO( b )", !bp.isZERO() ); cp = bp.multiply(ap); dp = ap.multiply(bp); assertTrue("not isZERO( c )", !cp.isZERO() ); assertTrue("not isZERO( d )", !dp.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); ep = dp.subtract(cp); assertTrue("isZERO( a*b-b*a ) " + ep, ep.isZERO() ); assertTrue("a*b = b*a", cp.equals(dp) ); assertEquals("a*b = b*a",cp,dp); cp = mfac.random(kl); //System.out.println("c = " + c); dp = ap.multiply( bp.multiply(cp) ); ep = (ap.multiply(bp)).multiply(cp); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",dp,ep); assertTrue("a(bc) = (ab)c", dp.equals(ep) ); cp = ap.multiply( mfac.getONE() ); dp = mfac.getONE().multiply( ap ); assertEquals("a*1 = 1*a",cp,dp); if ( ap.isUnit() ) { cp = ap.inverse(); dp = cp.multiply(ap); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",dp.isONE()); } } } jas-2.5/trc/edu/jas/poly/RatGenSolvablePolynomialTest.java0000644000175000017500000002054111641660762024102 0ustar giovannigiovanni/* * $Id: RatGenSolvablePolynomialTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; /** * BigRational coefficients GenSolvablePolynomial tests with JUnit. * @author Heinz Kredel. */ public class RatGenSolvablePolynomialTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a RatGenSolvablePolynomialTest object. * @param name String. */ public RatGenSolvablePolynomialTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(RatGenSolvablePolynomialTest.class); return suite; } GenSolvablePolynomial a; GenSolvablePolynomial b; GenSolvablePolynomial c; GenSolvablePolynomial d; GenSolvablePolynomial e; GenSolvablePolynomial f; GenSolvablePolynomial x1; GenSolvablePolynomial x2; int rl = 5; int kl = 10; int ll = 5; int el = 3; float q = 0.5f; RelationTable table; GenSolvablePolynomialRing ring; BigRational cfac; protected void setUp() { cfac = new BigRational(1); ring = new GenSolvablePolynomialRing(cfac,rl); table = ring.table; a = b = c = d = e = null; } protected void tearDown() { table = null; ring = null; a = b = c = d = e = null; } /** * Test constructor and toString. * */ public void testConstructor() { a = new GenSolvablePolynomial(ring); assertTrue("length( a ) = 0", a.length() == 0); assertTrue("isZERO( a )", a.isZERO() ); assertTrue("isONE( a )", !a.isONE() ); c = ring.getONE(); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = ring.getZERO(); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { assertTrue("isCommutative()",ring.isCommutative()); for (int i = 0; i < 2; i++) { // a = ring.random(ll+2*i); a = ring.random(kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = ring.random(kl, ll, el, q ); c = (GenSolvablePolynomial)a.subtract(a); assertTrue("a-a = 0", c.isZERO() ); b = (GenSolvablePolynomial)a.sum(a); c = (GenSolvablePolynomial)b.subtract(a); assertEquals("a+a-a = a",c,a); assertTrue("a+a-a = a", c.equals(a) ); b = ring.random(kl, ll, el, q ); c = (GenSolvablePolynomial)b.sum(a); d = (GenSolvablePolynomial)a.sum(b); assertEquals("a+b = b+a",c,d); assertTrue("a+b = b+a", c.equals(d) ); c = ring.random(kl, ll, el, q ); d = (GenSolvablePolynomial)a.sum(b.sum(c)); e = (GenSolvablePolynomial)a.sum(b).sum(c); assertEquals("a+(b+c) = (a+b)+c",d,e); assertTrue("a+(b+c) = (a+b)+c", d.equals(e) ); ExpVector u = ExpVector.EVRAND(rl,el,q); BigRational x = cfac.random(kl); b = ring.getONE().multiply( x, u); c = (GenSolvablePolynomial)a.sum(b); d = (GenSolvablePolynomial)a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = (GenSolvablePolynomial)a.subtract(b); d = (GenSolvablePolynomial)a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); a = ring.getZERO(); b = ring.getONE().multiply( x, u); c = (GenSolvablePolynomial)b.sum(a); d = (GenSolvablePolynomial)a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = (GenSolvablePolynomial)a.subtract(b); d = (GenSolvablePolynomial)a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = ring.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); //a = RatGenSolvablePolynomial.DIRRAS(1, kl, 4, el, q ); b = ring.random(kl, ll, el, q ); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); e = (GenSolvablePolynomial)d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertEquals("a*b = b*a",c,d); assertTrue("a*b = b*a", c.equals(d) ); c = ring.random(kl, ll, el, q ); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); BigRational x = a.leadingBaseCoefficient().inverse(); c = (GenSolvablePolynomial)a.monic(); d = a.multiply(x); assertEquals("a.monic() = a(1/ldcf(a))",c,d); ExpVector u = ring.evzero; BigRational y = b.leadingBaseCoefficient().inverse(); c = (GenSolvablePolynomial)b.monic(); d = b.multiply(y,u); assertEquals("b.monic() = b(1/ldcf(b))",c,d); e = ring.getONE().multiply(y,u); d = b.multiply(e); assertEquals("b.monic() = b(1/ldcf(b))",c,d); d = e.multiply(b); assertEquals("b.monic() = (1/ldcf(b) (0))*b",c,d); } /** * Test Weyl polynomials. * */ public void testWeyl() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); table = ring.table; //System.out.println("table = " + table); //System.out.println("ring = " + ring); assertFalse("isCommutative()",ring.isCommutative()); assertTrue("isAssociative()",ring.isAssociative()); a = ring.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); //System.out.println("a = " + a); b = ring.random(kl, ll, el, q ); assertTrue("not isZERO( b )", !b.isZERO() ); //System.out.println("b = " + b); // non commutative c = b.multiply(a); d = a.multiply(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); e = (GenSolvablePolynomial)d.subtract(c); assertTrue("!isZERO( a*b-b*a ) " + e, !e.isZERO() ); assertTrue("a*b != b*a", !c.equals(d) ); c = ring.random(kl, ll, el, q ); //System.out.println("\na = " + a); //System.out.println("\nb = " + b); //System.out.println("\nc = " + c); // associative //x1 = b.multiply(c); //System.out.println("\nx1 = " + x1); d = a.multiply( b.multiply(c) ); //x2 = a.multiply(b); //System.out.println("\nx2 = " + x2); e = a.multiply(b).multiply(c); //System.out.println("\nd = " + d); //System.out.println("\ne = " + e); //f = (GenSolvablePolynomial)d.subtract(e); //System.out.println("\nf = " + f); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); } /** * Test distributive law. * */ public void testDistributive() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); //table = ring.table; //System.out.println("table = " + table); //System.out.println("ring = " + ring); a = ring.random(kl,ll,el,q); b = ring.random(kl,ll,el,q); c = ring.random(kl,ll,el,q); d = a.multiply( (GenSolvablePolynomial)b.sum(c) ); e = (GenSolvablePolynomial)a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } } jas-2.5/trc/edu/jas/poly/PolynomialListTest.java0000644000175000017500000001065411652764754022161 0ustar giovannigiovanni/* * $Id: PolynomialListTest.java 3814 2011-10-29 11:56:29Z kredel $ */ package edu.jas.poly; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; /** * PolynomialList Test using JUnit. * @author Heinz Kredel */ public class PolynomialListTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a PolynomialListTest object. * @param name String. */ public PolynomialListTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(PolynomialListTest.class); return suite; } GenPolynomialRing fac; PolynomialList m; PolynomialList p; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 4; int kl = 4; int ll = 4; int el = 5; float q = 0.5f; protected void setUp() { a = b = c = d = e = null; m = null; p = null; BigRational coeff = new BigRational(9); fac = new GenPolynomialRing(coeff,rl); } protected void tearDown() { a = b = c = d = e = null; m = null; p = null; } /** * Test constructor and toString. */ public void testConstructor() { p = new PolynomialList(fac,(List>)null); assertTrue("p = 0", p.list == null); m = new PolynomialList(fac, new ArrayList>()); assertTrue("m = 0", m.list != null); assertTrue("m.size() == 0", m.list.size() == 0 ); } /** * Test polynomial list. */ public void testPolynomialList() { List> l = new ArrayList>(); for (int i = 0; i < 7; i++) { a = fac.random(ll+i); // rl, el, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); l.add( a ); } p = new PolynomialList(fac,l); //System.out.println("p = "+p); assertTrue("p == p", p.equals(p) ); assertEquals("p.length", 7, p.list.size() ); } /** * Test ordered polynomial list. */ public void testOrderedPolynomialList() { List> l = new ArrayList>(); for (int i = 0; i < 7; i++) { a = fac.random(ll+i); // rl, el, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); l.add( a ); } p = new PolynomialList(fac,l); //System.out.println("p = "+p); m = new OrderedPolynomialList(fac,p.list); //System.out.println("m = "+m); assertTrue("p == m", p.equals(m) ); assertTrue("m != p", !m.equals(p) ); assertEquals("p.length", 7, p.list.size() ); assertEquals("m.length", 7, m.list.size() ); } /** * Test homogeneous polynomial list. */ public void testHomogeneousPolynomialList() { List> l = new ArrayList>(); for (int i = 0; i < 7; i++) { a = fac.random(ll+i); // rl, el, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); l.add( a ); } p = new PolynomialList(fac,l); //System.out.println("p = "+p); PolynomialList h = p.homogenize(); //System.out.println("h = "+h); assertTrue("h is homogen", h.isHomogeneous() ); PolynomialList pp = h.deHomogenize(); //System.out.println("pp = "+pp); assertTrue("p == pp", p.equals(pp) ); } } jas-2.5/trc/edu/jas/poly/ModGenSolvablePolynomialTest.java0000644000175000017500000002067011641660762024076 0ustar giovannigiovanni/* * $Id: ModGenSolvablePolynomialTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; //import edu.jas.structure.RingElem; /** * ModInteger coefficients GenSolvablePolynomial tests with JUnit. * @author Heinz Kredel. */ public class ModGenSolvablePolynomialTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ModGenSolvablePolynomialTest object. * @param name String. */ public ModGenSolvablePolynomialTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ModGenSolvablePolynomialTest.class); return suite; } GenSolvablePolynomial a; GenSolvablePolynomial b; GenSolvablePolynomial c; GenSolvablePolynomial d; GenSolvablePolynomial e; GenSolvablePolynomial f; GenSolvablePolynomial x1; GenSolvablePolynomial x2; int ml = 19; // modul int rl = 5; int kl = 10; int ll = 5; int el = 3; float q = 0.5f; RelationTable table; GenSolvablePolynomialRing ring; ModIntegerRing cfac; protected void setUp() { cfac = new ModIntegerRing(ml); ring = new GenSolvablePolynomialRing(cfac,rl); table = null; //ring.table; a = b = c = d = e = null; } protected void tearDown() { table = null; ring = null; a = b = c = d = e = null; } /** * Test constructor and toString. * */ public void testConstructor() { a = new GenSolvablePolynomial(ring); assertTrue("length( a ) = 0", a.length() == 0); assertTrue("isZERO( a )", a.isZERO() ); assertTrue("isONE( a )", !a.isONE() ); c = ring.getONE(); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = ring.getZERO(); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { assertTrue("isCommutative()",ring.isCommutative()); for (int i = 0; i < 2; i++) { // a = ring.random(ll+2*i); a = ring.random(kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = ring.random(kl, ll, el, q ); c = (GenSolvablePolynomial)a.subtract(a); assertTrue("a-a = 0", c.isZERO() ); b = (GenSolvablePolynomial)a.sum(a); c = (GenSolvablePolynomial)b.subtract(a); assertEquals("a+a-a = a",c,a); assertTrue("a+a-a = a", c.equals(a) ); b = ring.random(kl, ll, el, q ); c = (GenSolvablePolynomial)b.sum(a); d = (GenSolvablePolynomial)a.sum(b); assertEquals("a+b = b+a",c,d); assertTrue("a+b = b+a", c.equals(d) ); c = ring.random(kl, ll, el, q ); d = (GenSolvablePolynomial)a.sum(b.sum(c)); e = (GenSolvablePolynomial)a.sum(b).sum(c); assertEquals("a+(b+c) = (a+b)+c",d,e); assertTrue("a+(b+c) = (a+b)+c", d.equals(e) ); ExpVector u = ExpVector.EVRAND(rl,el,q); ModInteger x = cfac.random(kl); b = ring.getONE().multiply( x, u); c = (GenSolvablePolynomial)a.sum(b); d = (GenSolvablePolynomial)a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = (GenSolvablePolynomial)a.subtract(b); d = (GenSolvablePolynomial)a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); a = ring.getZERO(); b = ring.getONE().multiply( x, u); c = (GenSolvablePolynomial)b.sum(a); d = (GenSolvablePolynomial)a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = (GenSolvablePolynomial)a.subtract(b); d = (GenSolvablePolynomial)a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = ring.random(kl, ll, el, q ); assertTrue("not isZERO( a )", !a.isZERO() ); //a = ModGenSolvablePolynomial.DIRRAS(1, kl, 4, el, q ); b = ring.random(kl, ll, el, q ); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); e = (GenSolvablePolynomial)d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertEquals("a*b = b*a",c,d); assertTrue("a*b = b*a", c.equals(d) ); c = ring.random(kl, ll, el, q ); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); ModInteger x = a.leadingBaseCoefficient().inverse(); c = (GenSolvablePolynomial)a.monic(); d = a.multiply(x); assertEquals("a.monic() = a(1/ldcf(a))",c,d); ExpVector u = ring.evzero; ModInteger y = b.leadingBaseCoefficient().inverse(); c = (GenSolvablePolynomial)b.monic(); d = b.multiply(y,u); assertEquals("b.monic() = b(1/ldcf(b))",c,d); e = ring.getONE().multiply(y,u); d = b.multiply(e); assertEquals("b.monic() = b(1/ldcf(b))",c,d); d = e.multiply(b); assertEquals("b.monic() = (1/ldcf(b) (0))*b",c,d); } /** * Test Weyl polynomials. * */ public void testWeyl() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); //table = ring.table; //System.out.println("table = " + table); //System.out.println("ring = " + ring); assertFalse("isCommutative()",ring.isCommutative()); assertTrue("isAssociative()", ring.isAssociative()); a = ring.random(kl, ll, el+2, q ); assertTrue("not isZERO( a )", !a.isZERO() ); //System.out.println("a = " + a); b = ring.random(kl, ll, el+2, q ); assertTrue("not isZERO( b )", !b.isZERO() ); //System.out.println("b = " + b); // non commutative c = b.multiply(a); d = a.multiply(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); e = (GenSolvablePolynomial)d.subtract(c); assertTrue("!isZERO( a*b-b*a ) " + e, !e.isZERO() ); assertTrue("a*b != b*a", !c.equals(d) ); c = ring.random(kl, ll, el, q ); //System.out.println("\na = " + a); //System.out.println("\nb = " + b); //System.out.println("\nc = " + c); // associative //x1 = b.multiply(c); //System.out.println("\nx1 = " + x1); d = a.multiply( b.multiply(c) ); //x2 = a.multiply(b); //System.out.println("\nx2 = " + x2); e = a.multiply(b).multiply(c); //System.out.println("\nd = " + d); //System.out.println("\ne = " + e); //f = (GenSolvablePolynomial)d.subtract(e); //System.out.println("\nf = " + f); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); } /** * Test distributive law. * */ public void testDistributive() { int rloc = 4; ring = new GenSolvablePolynomialRing(cfac,rloc); WeylRelations wl = new WeylRelations(ring); wl.generate(); //table = ring.table; //System.out.println("table = " + table); //System.out.println("ring = " + ring); a = ring.random(kl,ll,el,q); b = ring.random(kl,ll,el,q); c = ring.random(kl,ll,el,q); d = a.multiply( (GenSolvablePolynomial)b.sum(c) ); e = (GenSolvablePolynomial)a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } } jas-2.5/trc/edu/jas/poly/IntGenPolynomialTest.java0000644000175000017500000001317512045261444022414 0ustar giovannigiovanni/* * $Id: IntGenPolynomialTest.java 4284 2012-11-03 18:32:04Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.poly.GenPolynomial; import edu.jas.arith.BigInteger; //import edu.jas.structure.RingElem; /** * BigInteger coefficients GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class IntGenPolynomialTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a IntGenPolynomialTest object. * @param name String. */ public IntGenPolynomialTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(IntGenPolynomialTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing fac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 7; int kl = 10; int ll = 10; int el = 5; float q = 0.3f; protected void setUp() { a = b = c = d = e = null; fac = new GenPolynomialRing(new BigInteger(1),rl); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. */ public void testConstruction() { c = fac.getONE(); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(kl*(i+2),ll+2*i,el+i,q); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. */ public void testAddition() { a = fac.random(kl,ll,el,q); b = fac.random(kl,ll,el,q); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = fac.random(kl,ll,el,q); ExpVector u = ExpVector.EVRAND(rl,el,q); BigInteger x = BigInteger.IRAND(kl); b = new GenPolynomial(fac,x, u); c = a.sum(b); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); a = new GenPolynomial(fac); b = new GenPolynomial(fac,x, u); c = b.sum(a); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); } /** * Test object multiplication. */ public void testMultiplication() { a = fac.random(kl,ll,el,q); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(kl,ll,el,q); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(kl,ll,el,q); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); //BigInteger x = a.leadingBaseCoefficient().inverse(); //c = a.monic(); //d = a.multiply(x); //assertEquals("a.monic() = a(1/ldcf(a))",c,d); BigInteger y = b.leadingBaseCoefficient(); //c = b.monic(); //d = b.multiply(y); //assertEquals("b.monic() = b(1/ldcf(b))",c,d); e = new GenPolynomial(fac,y); c = b.multiply(e); // assertEquals("b.monic() = b(1/ldcf(b))",c,d); d = e.multiply(b); assertEquals("b*p(y,u) = p(y,u)*b",c,d); } /** * Test BLAS level 1. */ public void testBLAS1() { a = fac.random(kl,ll,el,q); b = fac.random(kl,ll,el,q); ExpVector ev = ExpVector.EVRAND(rl,el,q); BigInteger lc = BigInteger.IRAND(kl); d = a.subtractMultiple(lc,b); e = a.subtract( b.multiply(lc) ); assertEquals("a - (lc) b == a - ((lc) b)",d,e); d = a.subtractMultiple(lc,ev,b); e = a.subtract( b.multiply(lc,ev) ); assertEquals("a - (lc ev) b == a - ((lc ev) b)",d,e); ExpVector fv = ExpVector.EVRAND(rl,el,q); BigInteger tc = BigInteger.IRAND(kl); d = a.scaleSubtractMultiple(tc,lc,ev,b); e = a.multiply(tc).subtract( b.multiply(lc,ev) ); assertEquals("(tc) a - (lc ev) b == ((tc) a - ((lc ev) b))",d,e); d = a.scaleSubtractMultiple(tc,fv,lc,ev,b); e = a.multiply(tc,fv).subtract( b.multiply(lc,ev) ); assertEquals("(tc fv) a - (lc ev) b == ((tc fv) a - ((lc ev) b))",d,e); } /** * Test distributive law. */ public void testDistributive() { a = fac.random(kl,ll,el,q); b = fac.random(kl,ll,el,q); c = fac.random(kl,ll,el,q); d = a.multiply( b.sum(c) ); e = a.multiply( b ).sum( a.multiply(c) ); assertEquals("a(b+c) = ab+ac",d,e); } } jas-2.5/trc/edu/jas/poly/RatPolyGenPolynomialTest.java0000644000175000017500000001133511641660762023257 0ustar giovannigiovanni/* * $Id: RatPolyGenPolynomialTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; /** * BigRational coefficients GenPolynomial coefficients GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class RatPolyGenPolynomialTest extends TestCase { /** * main */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a RatPolyGenPolynomialTest object. * @param name String. */ public RatPolyGenPolynomialTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(RatPolyGenPolynomialTest.class); return suite; } //private final static int bitlen = 100; GenPolynomialRing cf; GenPolynomialRing> fac; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; GenPolynomial> d; GenPolynomial> e; int rl = 7; int kl = 10; int ll = 10; int el = 5; float q = 0.5f; protected void setUp() { a = b = c = d = e = null; cf = new GenPolynomialRing( new BigRational(1), 1 ); fac = new GenPolynomialRing>(cf,rl); } protected void tearDown() { a = b = c = d = e = null; fac = null; } /** * Test constructor and toString. * */ public void testConstruction() { c = fac.getONE(); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { a = fac.random(ll); // fac.random(rl+i, kl*(i+1), ll+2*i, el+i, q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = fac.random(ll); b = fac.random(ll); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = fac.random(ll); ExpVector u = ExpVector.EVRAND(rl,el,q); GenPolynomial x = cf.random(kl); b = new GenPolynomial>(fac,x, u); c = a.sum(b); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); a = new GenPolynomial>(fac); b = new GenPolynomial>(fac,x, u); c = b.sum(a); d = a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = a.subtract(b); d = a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(ll); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); //GenPolynomial x = a.leadingBaseCoefficient().inverse(); //c = a.monic(); //d = a.multiply(x); //assertEquals("a.monic() = a(1/ldcf(a))",c,d); GenPolynomial y = b.leadingBaseCoefficient(); //c = b.monic(); //d = b.multiply(y); //assertEquals("b.monic() = b(1/ldcf(b))",c,d); e = new GenPolynomial>(fac,y); c = b.multiply(e); // assertEquals("b.monic() = b(1/ldcf(b))",c,d); d = e.multiply(b); assertEquals("b*p(y,u) = p(y,u)*b",c,d); } } jas-2.5/trc/edu/jas/poly/TermOrderTest.java0000644000175000017500000004463712004571452021074 0ustar giovannigiovanni/* * $Id: TermOrderTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.poly; // import edu.jas.poly.TermOrder; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; /** * TermOrder tests with JUnit. Tests also ExpVector comparisons. * @author Heinz Kredel */ public class TermOrderTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a TermOrderTest object. * @param name String. */ public TermOrderTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(TermOrderTest.class); return suite; } //private final static int bitlen = 100; ExpVector a; ExpVector b; ExpVector c; ExpVector d; TermOrder t; TermOrder s; @Override protected void setUp() { a = b = c = d = null; t = s = null; } @Override protected void tearDown() { a = b = c = d = null; t = s = null; } /** * Test constructor and toString. * */ public void testConstructor() { s = new TermOrder(); t = new TermOrder(); assertEquals("t = s", t, s); String x = t.toString(); String y = s.toString(); assertEquals("x = y", x, y); t = new TermOrder(TermOrder.INVLEX); x = "INVLEX"; boolean z = t.toString().startsWith(x); assertTrue("INVLEX(.)", z); s = new TermOrder(TermOrder.IGRLEX); t = new TermOrder(TermOrder.IGRLEX); assertEquals("t = s", t, s); } /** * Test constructor, split TO. * */ public void testConstructorSplit() { int r = 10; int sp = 5; s = new TermOrder(r, sp); t = new TermOrder(r, sp); assertEquals("t = s", t, s); String x = t.toString(); String y = s.toString(); assertEquals("x = y", x, y); //System.out.println("s = " + s); s = new TermOrder(TermOrder.IGRLEX, TermOrder.INVLEX, r, sp); t = new TermOrder(TermOrder.IGRLEX, TermOrder.INVLEX, r, sp); assertEquals("t = s", t, s); //System.out.println("s = " + s); } /** * Test constructor weight and toString. * */ public void testConstructorWeight() { long[][] w = new long[][] { new long[] { 1l, 1l, 1l, 1l, 1l } }; s = new TermOrder(w); t = new TermOrder(w); assertEquals("t = s", t, s); String x = t.toString(); String y = s.toString(); assertEquals("x = y", x, y); //System.out.println("s = " + s); //int r = 5; //int sp = 3; //w = new long [][] { new long[] { 5l, 4l, 3l, 2l, 1l } }; //s = new TermOrder(w,sp); //t = new TermOrder(w,sp); //assertEquals("t = s",t,s); //x = t.toString(); //y = s.toString(); //assertEquals("x = y",x,y); //System.out.println("s = " + s); x = "W("; boolean z = t.toString().startsWith(x); assertTrue("W(.)", z); } /** * Test compare weight. * */ public void testCompareWeight() { float q = (float) 0.9; a = ExpVector.EVRAND(5, 10, q); b = ExpVector.EVRAND(5, 10, q); c = a.sum(b); long[][] w = new long[][] { new long[] { 1l, 1l, 1l, 1l, 1l } }; t = new TermOrder(w); int x = ExpVector.EVIWLC(w, c, a); int y = ExpVector.EVIWLC(w, c, b); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = ExpVector.EVIWLC(w, a, c); y = ExpVector.EVIWLC(w, b, c); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = ExpVector.EVIWLC(w, a, a); y = ExpVector.EVIWLC(w, b, b); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); } /** * Test compare weight 2 rows. * */ public void testCompareWeight2() { float q = (float) 0.9; a = ExpVector.EVRAND(5, 10, q); b = ExpVector.EVRAND(5, 10, q); c = a.sum(b); long[][] w = new long[][] { new long[] { 1l, 1l, 1l, 1l, 1l }, new long[] { 1l, 1l, 1l, 1l, 1l } }; t = new TermOrder(w); int x = ExpVector.EVIWLC(w, c, a); int y = ExpVector.EVIWLC(w, c, b); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = ExpVector.EVIWLC(w, a, c); y = ExpVector.EVIWLC(w, b, c); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = ExpVector.EVIWLC(w, a, a); y = ExpVector.EVIWLC(w, b, b); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); } /** * Test compare weight split. * */ public void testCompareWeightSplit() { float q = (float) 0.9; int r = 8; int sp = 4; a = ExpVector.EVRAND(r, 10, q); b = ExpVector.EVRAND(r, 10, q); c = a.sum(b); long[][] w = new long[][] { new long[] { 1l, 1l, 1l, 1l, 1l, 1l, 1l, 1l } }; //t = new TermOrder(w,sp); int x; int y; x = ExpVector.EVIWLC(w, c, a); y = ExpVector.EVIWLC(w, c, b); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = ExpVector.EVIWLC(w, c, a, 0, sp); y = ExpVector.EVIWLC(w, c, b, 0, sp); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = ExpVector.EVIWLC(w, c, a, sp, r); y = ExpVector.EVIWLC(w, c, b, sp, r); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = ExpVector.EVIWLC(w, a, c); y = ExpVector.EVIWLC(w, b, c); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = ExpVector.EVIWLC(w, a, c, 0, sp); y = ExpVector.EVIWLC(w, b, c, 0, sp); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = ExpVector.EVIWLC(w, a, c, sp, r); y = ExpVector.EVIWLC(w, b, c, sp, r); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = ExpVector.EVIWLC(w, a, a); y = ExpVector.EVIWLC(w, b, b); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); x = ExpVector.EVIWLC(w, a, a, 0, sp); y = ExpVector.EVIWLC(w, b, b, 0, sp); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); x = ExpVector.EVIWLC(w, a, a, sp, r); y = ExpVector.EVIWLC(w, b, b, sp, r); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); long[][] w2 = new long[][] { new long[] { 1l, 1l, 1l, 1l, 0l, 0l, 0l, 0l }, new long[] { 0l, 0l, 0l, 0l, 1l, 1l, 1l, 1l } }; //t = new TermOrder(w2); x = ExpVector.EVIWLC(w2, c, a); y = ExpVector.EVIWLC(w2, c, b); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = ExpVector.EVIWLC(w2, c, a, 0, sp); y = ExpVector.EVIWLC(w2, c, b, 0, sp); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = ExpVector.EVIWLC(w2, c, a, sp, r); y = ExpVector.EVIWLC(w2, c, b, sp, r); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = ExpVector.EVIWLC(w2, a, c); y = ExpVector.EVIWLC(w2, b, c); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = ExpVector.EVIWLC(w2, a, c, 0, sp); y = ExpVector.EVIWLC(w2, b, c, 0, sp); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = ExpVector.EVIWLC(w2, a, c, sp, r); y = ExpVector.EVIWLC(w2, b, c, sp, r); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = ExpVector.EVIWLC(w2, a, a); y = ExpVector.EVIWLC(w2, b, b); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); x = ExpVector.EVIWLC(w2, a, a, 0, sp); y = ExpVector.EVIWLC(w2, b, b, 0, sp); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); x = ExpVector.EVIWLC(w2, a, a, sp, r); y = ExpVector.EVIWLC(w2, b, b, sp, r); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); } /** * Test ascend comparators. * */ public void testAscendComparator() { float q = (float) 0.9; a = ExpVector.EVRAND(5, 10, q); b = ExpVector.EVRAND(5, 10, q); c = a.sum(b); t = new TermOrder(); int x = t.getAscendComparator().compare(c, a); int y = t.getAscendComparator().compare(c, b); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = t.getAscendComparator().compare(a, c); y = t.getAscendComparator().compare(b, c); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = t.getAscendComparator().compare(a, a); y = t.getAscendComparator().compare(b, b); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); } /** * Test ascend comparators split. * */ public void testAscendComparatorSplit() { float q = (float) 0.9; int r = 10; int sp = 5; a = ExpVector.EVRAND(r, 10, q); b = ExpVector.EVRAND(r, 10, q); c = a.sum(b); t = new TermOrder(r, sp); int x = t.getAscendComparator().compare(c, a); int y = t.getAscendComparator().compare(c, b); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = t.getAscendComparator().compare(a, c); y = t.getAscendComparator().compare(b, c); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = t.getAscendComparator().compare(a, a); y = t.getAscendComparator().compare(b, b); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); } /** * Test ascend comparators weight and split. * */ public void testAscendComparatorWeightSplit() { float q = (float) 0.9; int r = 8; //int sp = 5; //long [][] w = new long [][] { new long[] { 1l, 2l, 3l, 4l, 5l, 1l, 2l, 3l } }; long[][] w2 = new long[][] { new long[] { 1l, 2l, 3l, 4l, 5l, 0l, 0l, 0l }, new long[] { 0l, 0l, 0l, 0l, 0l, 1l, 2l, 3l } }; a = ExpVector.EVRAND(r, 10, q); b = ExpVector.EVRAND(r, 10, q); c = a.sum(b); // t = new TermOrder(w,sp); t = new TermOrder(w2); TermOrder t2 = new TermOrder(w2); // now t equals t2 int x = t.getAscendComparator().compare(c, a); int y = t.getAscendComparator().compare(c, b); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); int x2 = t2.getAscendComparator().compare(c, a); int y2 = t2.getAscendComparator().compare(c, b); assertEquals("x2 = 1", 1, x2); assertEquals("y2 = 1", 1, y2); assertEquals("x = x2", x, x2); assertEquals("y = y2", y, y2); x = t.getAscendComparator().compare(a, c); y = t.getAscendComparator().compare(b, c); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x2 = t2.getAscendComparator().compare(a, c); y2 = t2.getAscendComparator().compare(b, c); assertEquals("x2 = -1", -1, x2); assertEquals("y2 = -1", -1, y2); assertEquals("x = x2", x, x2); assertEquals("y = y2", y, y2); x = t.getAscendComparator().compare(a, a); y = t.getAscendComparator().compare(b, b); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); x2 = t2.getAscendComparator().compare(a, a); y2 = t2.getAscendComparator().compare(b, b); assertEquals("x2 = 0", 0, x2); assertEquals("y2 = 0", 0, y2); assertEquals("x = x2", x, x2); assertEquals("y = y2", y, y2); } /** * Test descend comparators. * */ public void testDescendComparator() { float q = (float) 0.9; a = ExpVector.EVRAND(5, 10, q); b = ExpVector.EVRAND(5, 10, q); c = a.sum(b); t = new TermOrder(); int x = t.getDescendComparator().compare(c, a); int y = t.getDescendComparator().compare(c, b); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = t.getDescendComparator().compare(a, c); y = t.getDescendComparator().compare(b, c); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = t.getDescendComparator().compare(a, a); y = t.getDescendComparator().compare(b, b); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); } /** * Test descend comparators split. * */ public void testDescendComparatorSplit() { float q = (float) 0.9; int r = 10; int sp = 5; a = ExpVector.EVRAND(r, 10, q); b = ExpVector.EVRAND(r, 10, q); c = a.sum(b); t = new TermOrder(r, sp); int x = t.getDescendComparator().compare(c, a); int y = t.getDescendComparator().compare(c, b); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); x = t.getDescendComparator().compare(a, c); y = t.getDescendComparator().compare(b, c); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x = t.getDescendComparator().compare(a, a); y = t.getDescendComparator().compare(b, b); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); } /** * Test descend comparators weight and split. * */ public void testDescendComparatorWeightSplit() { float q = (float) 0.9; int r = 8; //int sp = 5; //long [][] w = new long [][] { new long[] { 1l, 2l, 3l, 4l, 5l, 1l, 2l, 3l } }; long[][] w2 = new long[][] { new long[] { 1l, 2l, 3l, 4l, 5l, 0l, 0l, 0l }, new long[] { 0l, 0l, 0l, 0l, 0l, 1l, 2l, 3l } }; a = ExpVector.EVRAND(r, 10, q); b = ExpVector.EVRAND(r, 10, q); c = a.sum(b); //t = new TermOrder(w,sp); t = new TermOrder(w2); TermOrder t2 = new TermOrder(w2); // now t equals t2 int x = t.getDescendComparator().compare(c, a); int y = t.getDescendComparator().compare(c, b); assertEquals("x = -1", -1, x); assertEquals("y = -1", -1, y); int x2 = t2.getDescendComparator().compare(c, a); int y2 = t2.getDescendComparator().compare(c, b); assertEquals("x2 = -1", -1, x2); assertEquals("y2 = -1", -1, y2); assertEquals("x = x2", x, x2); assertEquals("y = y2", y, y2); x = t.getDescendComparator().compare(a, c); y = t.getDescendComparator().compare(b, c); assertEquals("x = 1", 1, x); assertEquals("y = 1", 1, y); x2 = t2.getDescendComparator().compare(a, c); y2 = t2.getDescendComparator().compare(b, c); assertEquals("x2 = 1", 1, x2); assertEquals("y2 = 1", 1, y2); assertEquals("x = x2", x, x2); assertEquals("y = y2", y, y2); x = t.getDescendComparator().compare(a, a); y = t.getDescendComparator().compare(b, b); assertEquals("x = 0", 0, x); assertEquals("y = 0", 0, y); x2 = t2.getDescendComparator().compare(a, a); y2 = t2.getDescendComparator().compare(b, b); assertEquals("x2 = 0", 0, x2); assertEquals("y2 = 0", 0, y2); assertEquals("x = x2", x, x2); assertEquals("y = y2", y, y2); } /** * Test exception. * */ public void testException() { float q = (float) 0.9; a = ExpVector.EVRAND(5, 10, q); b = ExpVector.EVRAND(5, 10, q); int wrong = 99; //int x = 0; try { t = new TermOrder(wrong); } catch (IllegalArgumentException e) { return; } fail("IllegalArgumentException"); } /** * Test exception split. * */ public void testExceptionSplit() { float q = (float) 0.9; int r = 10; int sp = 5; a = ExpVector.EVRAND(r, 10, q); b = ExpVector.EVRAND(r, 10, q); int wrong = 99; //int x = 0; try { t = new TermOrder(wrong, wrong, r, sp); } catch (IllegalArgumentException e) { return; } fail("IllegalArgumentException"); } /** * Test compare exception. * */ public void testCompareException() { float q = (float) 0.9; a = ExpVector.EVRAND(5, 10, q); b = ExpVector.EVRAND(5, 10, q); int notimpl = TermOrder.REVITDG + 2; int x = 0; try { t = new TermOrder(notimpl); x = t.getDescendComparator().compare(a, b); fail("IllegalArgumentException " + x); } catch (IllegalArgumentException e) { //return; } catch (NullPointerException e) { //return; } } /** * Test compare exception split. * */ public void testCompareExceptionSplit() { float q = (float) 0.9; int r = 10; int sp = 5; a = ExpVector.EVRAND(r, 10, q); b = ExpVector.EVRAND(r, 10, q); int notimpl = TermOrder.REVITDG + 2; int x = 0; try { t = new TermOrder(notimpl, notimpl, r, sp); x = t.getDescendComparator().compare(a, b); fail("IllegalArgumentException " + x); } catch (IllegalArgumentException e) { //return; } catch (NullPointerException e) { //return; } } /** * Test compare exception weight. * */ public void testCompareExceptionWeigth() { float q = (float) 0.9; int r = 10; //int sp = 5; a = ExpVector.EVRAND(r, 10, q); b = ExpVector.EVRAND(r, 10, q); int x = 0; try { t = new TermOrder((long[][]) null); x = t.getDescendComparator().compare(a, b); fail("IllegalArgumentException " + x); } catch (IllegalArgumentException e) { //return; } catch (NullPointerException e) { //return; } } } jas-2.5/trc/edu/jas/poly/ComplexTest.java0000644000175000017500000002515411641660762020602 0ustar giovannigiovanni /* * $Id: ComplexTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; //import java.util.ArrayList; //import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.arith.BigInteger; //import edu.jas.structure.RingElem; /** * Complex test with JUnit. * @author Heinz Kredel. */ public class ComplexTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a ComplexTest object. * @param name String. */ public ComplexTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(ComplexTest.class); return suite; } ComplexRing fac; GenPolynomialRing pfac; ComplexRing< GenPolynomial > mfac; Complex< BigInteger > a; Complex< BigInteger > b; Complex< BigInteger > c; Complex< BigInteger > d; Complex< BigInteger > e; Complex< GenPolynomial > ap; Complex< GenPolynomial > bp; Complex< GenPolynomial > cp; Complex< GenPolynomial > dp; Complex< GenPolynomial > ep; int rl = 1; int kl = 13; int ll = 7; int el = 3; float q = 0.4f; int il = 2; long p = 1152921504606846883L; // 2^60-93; @Override protected void setUp() { a = b = c = d = e = null; ap = bp = cp = dp = ep = null; BigInteger cfac = new BigInteger(1); fac = new ComplexRing( cfac ); pfac = new GenPolynomialRing( new BigRational(1), 1 ); GenPolynomial mo = pfac.random(kl,ll,el,q); while ( mo.isConstant() ) { mo = pfac.random(kl,ll,el,q); } mfac = new ComplexRing>( pfac ); } @Override protected void tearDown() { a = b = c = d = e = null; ap = bp = cp = dp = ep = null; fac = null; pfac = null; mfac = null; } /** * Test constructor for integer. * */ public void testIntConstruction() { c = fac.getONE(); //System.out.println("c = " + c); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); //System.out.println("d = " + d); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test constructor for polynomial. * */ public void testPolyConstruction() { cp = mfac.getONE(); assertTrue("isZERO( cp )", !cp.isZERO() ); assertTrue("isONE( cp )", cp.isONE() ); dp = mfac.getZERO(); assertTrue("isZERO( dp )", dp.isZERO() ); assertTrue("isONE( dp )", !dp.isONE() ); } /** * Test random integer. * */ public void testIntRandom() { for (int i = 0; i < 7; i++) { a = fac.random(kl*(i+1)); if ( a.isZERO() ) { continue; } //a = fac.random(kl*(i+1), ll+2*i, el+i, q ); //System.out.println("a = " + a); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test random polynomial. * */ public void testPolyRandom() { for (int i = 0; i < 7; i++) { ap = mfac.random(kl+i); if ( ap.isZERO() ) { continue; } assertTrue(" not isZERO( ap"+i+" )", !ap.isZERO() ); assertTrue(" not isONE( ap"+i+" )", !ap.isONE() ); } } /** * Test integer addition. * */ public void testIntAddition() { a = fac.random(kl); b = fac.random(kl); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); assertEquals("a+b = b+a",c,d); c = fac.random(kl); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( fac.getZERO() ); d = a.subtract( fac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = fac.getZERO().sum( a ); d = fac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test polynomial addition. * */ public void testPolyAddition() { ap = mfac.random(kl); bp = mfac.random(kl); //System.out.println("a = " + a); //System.out.println("b = " + b); cp = ap.sum(bp); dp = cp.subtract(bp); assertEquals("a+b-b = a",ap,dp); cp = ap.sum(bp); dp = bp.sum(ap); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",cp,dp); cp = mfac.random(kl); dp = cp.sum( ap.sum(bp) ); ep = cp.sum( ap ).sum(bp); assertEquals("c+(a+b) = (c+a)+b",dp,ep); cp = ap.sum( mfac.getZERO() ); dp = ap.subtract( mfac.getZERO() ); assertEquals("a+0 = a-0",cp,dp); cp = mfac.getZERO().sum( ap ); dp = mfac.getZERO().subtract( ap.negate() ); assertEquals("0+a = 0+(-a)",cp,dp); } /** * Test integer multiplication. * */ public void testIntMultiplication() { a = fac.random(kl); if ( a.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(kl); if ( b.isZERO() ) { return; } assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = fac.random(kl); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( fac.getONE() ); d = fac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",d.isONE()); } } /** * Test polynomial multiplication. * */ public void testPolyMultiplication() { ap = mfac.random(kl); if ( ap.isZERO() ) { return; } assertTrue("not isZERO( a )", !ap.isZERO() ); bp = mfac.random(kl); if ( bp.isZERO() ) { return; } assertTrue("not isZERO( b )", !bp.isZERO() ); cp = bp.multiply(ap); dp = ap.multiply(bp); assertTrue("not isZERO( c )", !cp.isZERO() ); assertTrue("not isZERO( d )", !dp.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); ep = dp.subtract(cp); assertTrue("isZERO( a*b-b*a ) " + ep, ep.isZERO() ); assertTrue("a*b = b*a", cp.equals(dp) ); assertEquals("a*b = b*a",cp,dp); cp = mfac.random(kl); //System.out.println("c = " + c); dp = ap.multiply( bp.multiply(cp) ); ep = (ap.multiply(bp)).multiply(cp); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",dp,ep); assertTrue("a(bc) = (ab)c", dp.equals(ep) ); cp = ap.multiply( mfac.getONE() ); dp = mfac.getONE().multiply( ap ); assertEquals("a*1 = 1*a",cp,dp); if ( ap.isUnit() ) { cp = ap.inverse(); dp = cp.multiply(ap); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",dp.isONE()); } } /** * Test integer division. * */ public void testIntDivision() { a = fac.random(kl*2); if ( a.isZERO() ) { return; } assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(kl); if ( b.isZERO() ) { return; } assertTrue("not isZERO( b )", !b.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.divide(b); //System.out.println("c = " + c); d = a.remainder(b); //System.out.println("d = " + d); e = b.multiply(c).sum(d); //System.out.println("e = " + e); assertEquals("a = b (a/b) + a%b ", a, e ); c = a.gcd(b); d = a.divide(c); e = b.divide(c); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); d = c.multiply(d); e = c.multiply(e); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("a/gcd(a,b)*gcd(a,b) = a ", a, d ); assertEquals("b/gcd(a,b)*gcd(a,b) = b ", b, e ); Complex[] gf = a.egcd(b); c = gf[0]; d = gf[1]; e = gf[2]; //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); d = d.multiply(a); e = e.multiply(b); d = d.sum( e ); //System.out.println("d = " + d); assertEquals("d*a + e*b = c = gcd(a,b)", c, d ); } /** * Test polynomial division. * */ public void testPolyDivision() { ap = mfac.random(kl); if ( ap.isZERO() ) { return; } assertTrue("not isZERO( ap )", !ap.isZERO() ); bp = mfac.random(kl/2); if ( bp.isZERO() ) { return; } assertTrue("not isZERO( bp )", !bp.isZERO() ); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); cp = ap.divide(bp); //System.out.println("cp = " + cp); dp = ap.remainder(bp); //System.out.println("dp = " + dp); ep = bp.multiply(cp).sum(dp); //System.out.println("ep = " + ep); assertEquals("ap = bp (ap/bp) + ap%bp ", ap, ep ); // not applicable: // cp = ap.gcd(bp); // dp = ap.divide(cp); // ep = bp.divide(cp); // System.out.println("cp = " + cp); // System.out.println("dp = " + dp); // System.out.println("ep = " + ep); // dp = cp.multiply(dp); // ep = cp.multiply(ep); // System.out.println("dp = " + dp); // System.out.println("ep = " + ep); // assertEquals("ap/gcd(ap,bp)*gcd(ap,bp) = ap ", ap, dp ); // assertEquals("bp/gcd(ap,bp)*gcd(ap,bp) = bp ", bp, ep ); } } jas-2.5/trc/edu/jas/poly/WordTest.java0000644000175000017500000002607112024343046020072 0ustar giovannigiovanni/* * $Id: WordTest.java 4188 2012-09-13 11:40:22Z kredel $ */ package edu.jas.poly; import java.util.Collection; import java.util.List; import java.util.SortedMap; import java.util.Arrays; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; /** * Word and WordFactory tests with JUnit. Tests construction and arithmetic * operations. * @author Heinz Kredel. */ public class WordTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a WordTest object. * @param name String. */ public WordTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(WordTest.class); return suite; } //private final static int bitlen = 100; Word a; Word b; Word c; Word d; @Override protected void setUp() { a = b = c = d = null; } @Override protected void tearDown() { a = b = c = d = null; } /** * Test constructor and toString. */ public void testConstructor() { WordFactory wf = new WordFactory("abcdefg"); a = new Word(wf); b = a; //System.out.println("a = " + a); assertEquals("() = ()", a, b); assertEquals("length( () ) = 0", a.length(), 0); assertTrue("isONE( () )", a.isONE()); assertTrue("isUnit( () )", a.isUnit()); b = new Word(wf, "abc"); c = wf.parse(" a b c "); //System.out.println("b = " + b); //System.out.println("c = " + c); assertEquals("b = c: ", b, c); assertFalse("isONE( () )", b.isONE()); assertFalse("isUnit( () )", b.isUnit()); assertFalse("isONE( () )", c.isONE()); assertFalse("isUnit( () )", c.isUnit()); String s = b.toString(); String t = c.toString(); //System.out.println("s = " + s); //System.out.println("t = " + t); assertEquals("s = t: ", s, t); } /** * Test word factory. */ public void testFactory() { WordFactory wf = new WordFactory("abcdefg"); //System.out.println("wf = " + wf); Word w = wf.getONE(); //System.out.println("w = " + w); assertTrue("w == (): ", w.isONE()); w = wf.parse("aaabbbcccaaa"); //System.out.println("w = " + w); assertFalse("w != (): ", w.isONE()); a = wf.parse(w.toString()); //System.out.println("a = " + a); assertEquals("w = a", a, w); WordFactory wf2 = new WordFactory(w.toString()); //System.out.println("wf2 = " + wf2); a = wf2.parse(w.toString()); //System.out.println("a = " + a); assertEquals("w = a", a, w); List gens = wf.generators(); //System.out.println("gens = " + gens); assertTrue("#gens == 7: ", gens.size() == 7); for (Word v : gens) { a = wf.parse(v.toString()); assertEquals("a == v", a, v); } } /** * Test random word. */ public void testRandom() { WordFactory wf = new WordFactory("uvw"); //System.out.println("wf = " + wf); a = wf.random(5); b = wf.random(6); c = wf.random(7); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertFalse("a != (): ", a.isONE()); assertFalse("b != (): ", b.isONE()); assertFalse("c != (): ", c.isONE()); assertTrue("#a == 5", a.length() == 5); assertTrue("#b == 6", b.length() == 6); assertTrue("#c == 7", c.length() == 7); SortedMap ma = a.dependencyOnVariables(); SortedMap mb = b.dependencyOnVariables(); SortedMap mc = c.dependencyOnVariables(); //System.out.println("ma = " + ma); //System.out.println("mb = " + mb); //System.out.println("mc = " + mc); assertTrue("#ma <= 3", ma.size() <= wf.length()); assertTrue("#mb <= 3", mb.size() <= wf.length()); assertTrue("#mc <= 3", mc.size() <= wf.length()); assertTrue("S ma <= #a", sum(ma.values()) == a.length()); assertTrue("S mb <= #b", sum(mb.values()) == b.length()); assertTrue("S mc <= #c", sum(mc.values()) == c.length()); } int sum(Collection li) { int s = 0; for (Integer i : li) { s += i; } return s; } /** * Test multiplication. */ public void testMultiplication() { WordFactory wf = new WordFactory("abcdefgx"); a = new Word(wf, "abc"); b = new Word(wf, "cddaa"); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.multiply(b); //System.out.println("c = " + c); assertTrue("divides: ", a.divides(c)); assertTrue("divides: ", b.divides(c)); assertTrue("multiple: ", c.multipleOf(a)); assertTrue("multiple: ", c.multipleOf(b)); d = c.divide(a); //System.out.println("d = " + d); assertEquals("d = b", d, b); d = c.divide(b); //System.out.println("d = " + d); assertEquals("d = a", d, a); d = c.divide(c); //System.out.println("d = " + d); assertTrue("isONE( () )", d.isONE()); d = new Word(wf, "xx"); c = a.multiply(d).multiply(b); //System.out.println("d = " + d); //System.out.println("c = " + c); assertTrue("divides: ", d.divides(c)); Word[] ret = c.divideWord(d); //System.out.println("ret = " + ret[0] + ", " + ret[1]); assertEquals("prefix(c/d) = a", a, ret[0]); assertEquals("suffix(c/d) = b", b, ret[1]); Word e = ret[0].multiply(d).multiply(ret[1]); assertEquals("prefix(c/d) d suffix(c/d) = e", e, c); } /** * Test overlap. */ public void testOverlap() { WordFactory wf = new WordFactory("abcdefg"); a = new Word(wf, "abc"); b = new Word(wf, "ddabca"); //System.out.println("a = " + a); //System.out.println("b = " + b); OverlapList ol = a.overlap(b); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(a,b)); ol = b.overlap(a); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(b,a)); a = new Word(wf, "abcfff"); b = new Word(wf, "ddabc"); //System.out.println("a = " + a); //System.out.println("b = " + b); ol = a.overlap(b); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(a,b)); ol = b.overlap(a); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(b,a)); a = new Word(wf, "fffabc"); b = new Word(wf, "abcdd"); //System.out.println("a = " + a); //System.out.println("b = " + b); ol = a.overlap(b); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(a,b)); ol = b.overlap(a); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(b,a)); a = new Word(wf, "ab"); b = new Word(wf, "dabeabfabc"); //System.out.println("a = " + a); //System.out.println("b = " + b); ol = a.overlap(b); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(a,b)); ol = b.overlap(a); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(b,a)); a = new Word(wf, "abc"); b = new Word(wf, "abceabcfabc"); //System.out.println("a = " + a); //System.out.println("b = " + b); ol = a.overlap(b); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(a,b)); ol = b.overlap(a); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(b,a)); a = new Word(wf, "aa"); b = new Word(wf, "aaaaaaaaa"); //System.out.println("a = " + a); //System.out.println("b = " + b); ol = a.overlap(b); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(a,b)); ol = b.overlap(a); //System.out.println("ol = " + ol); assertTrue("isOverlap: ", ol.isOverlap(b,a)); } /** * Test valueOf. */ public void testValueOf() { String[] vars = new String[] { "a", "b", "c", "d" }; WordFactory wf = new WordFactory(vars); ExpVector ef = ExpVector.random(4,5L,0.5f); //System.out.println("ef = " + ef); a = wf.valueOf(ef); //System.out.println("a = " + a); assertTrue("deg(ef) == deg(a): " + ef + ", " + a, ef.degree() == a.degree() ); String es = ef.toString(vars); //System.out.println("es = " + es); assertTrue("ef != ''" + ef, es.length() >= 0 ); } /** * Test constructor with multi-letter Strings. */ public void testMultiLetters() { String[] vars = new String[] {"a1", "b", " e23", "tt*", "x y" }; WordFactory wf = new WordFactory(vars); //System.out.println("wf = " + wf); String s = wf.toString(); assertEquals("w == vars: ", s, "\"a1,b,e23,tt,xy\""); Word w = wf.parse("a1 a1 b*b*b tt xy e23 tt xy"); s = w.toString(); String t = "\"a1 a1 b b b tt xy e23 tt xy\""; //System.out.println("s = " + s); //System.out.println("t = " + t); assertEquals("w == parse: ", s, t); Word u = wf.parse("xy e23 tt xy a1 a1 b*b*b tt"); s = u.toString(); String t1 = "\"xy e23 tt xy a1 a1 b b b tt\""; //System.out.println("s = " + s); //System.out.println("t = " + t1); assertEquals("w == parse: ", s, t1); Word v = u.multiply(w); s = v.toString(); String t2 = t1.substring(0,t1.length()-1) + " " + t.substring(1); //System.out.println("s = " + s); //System.out.println("t = " + t2); assertEquals("w == parse: ", s, t2); v = w.multiply(u); s = v.toString(); t2 = t.substring(0,t.length()-1) + " " + t1.substring(1); //System.out.println("s = " + s); //System.out.println("t = " + t2); assertEquals("w == parse: ", s, t2); w = wf.random(5); //System.out.println("w = " + w); u = wf.random(5); //System.out.println("u = " + u); v = u.multiply(w); //System.out.println("v = " + v); assertTrue("#v = #w+#u: ", v.length() == w.length()+u.length()); List gens = wf.generators(); //System.out.println("gens = " + gens); assertTrue("#gens == 5: ", gens.size() == 5); for (Word x : gens) { a = wf.parse(x.toString()); assertEquals("a == x", a, x); } } } jas-2.5/trc/edu/jas/poly/QuatGenSolvablePolynomialTest.java0000644000175000017500000002006012016422422024244 0ustar giovannigiovanni/* * $Id: QuatGenSolvablePolynomialTest.java 4142 2012-08-26 13:30:59Z kredel $ */ package edu.jas.poly; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigQuaternion; /** * BigQuaternion coefficients GenSolvablePolynomial tests with JUnit. * @author Heinz Kredel. */ public class QuatGenSolvablePolynomialTest extends TestCase { /** * main */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a QuatGenSolvablePolynomialTest object. * @param name String. */ public QuatGenSolvablePolynomialTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite= new TestSuite(QuatGenSolvablePolynomialTest.class); return suite; } BigQuaternion cfac; GenSolvablePolynomialRing fac; GenSolvablePolynomial a; GenSolvablePolynomial b; GenSolvablePolynomial c; GenSolvablePolynomial d; GenSolvablePolynomial e; int rl = 6; int kl = 3; int ll = 7; int el = 5; float q = 0.33f; protected void setUp() { a = b = c = d = e = null; cfac = new BigQuaternion(1); fac = new GenSolvablePolynomialRing(cfac,rl); WeylRelations rel = new WeylRelations(fac); rel.generate(); } protected void tearDown() { a = b = c = d = e = null; fac = null; cfac = null; } /** * Test constructor and toString. */ public void testConstruction() { c = fac.getONE(); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = fac.getZERO(); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test factory. */ public void testFactory() { assertFalse("!is comutative", fac.isCommutative() ); assertFalse("!is field", fac.isField() ); assertTrue("is associative", fac.isAssociative() ); List> gens = fac.generators(); //System.out.println("gens = " + gens); assertTrue("#gens = 4+6 ", gens.size() == 10); } /** * Test random polynomial. */ public void testRandom() { for (int i = 0; i < 3; i++) { //a = fac.random(ll); a = fac.random(kl, ll+i, el+(5-i), q ); assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test solvable addition. */ public void testAddition() { a = fac.random(kl, ll, el, q ); // fac.random(ll); b = fac.random(kl, ll, el, q ); // fac.random(ll); c = (GenSolvablePolynomial) a.sum(b); d = (GenSolvablePolynomial) c.subtract(b); assertEquals("a+b-b = a",a,d); c = fac.random(kl, ll, el, q ); //fac.random(ll); ExpVector u = ExpVector.EVRAND(rl,el,q); BigQuaternion x = BigQuaternion.QRAND(kl); b = new GenSolvablePolynomial(fac, x, u); c = (GenSolvablePolynomial) a.sum(b); d = (GenSolvablePolynomial) a.sum(x,u); assertEquals("a+p(x,u) = a+(x,u)",c,d); c = (GenSolvablePolynomial) a.subtract(b); d = (GenSolvablePolynomial) a.subtract(x,u); assertEquals("a-p(x,u) = a-(x,u)",c,d); a = new GenSolvablePolynomial(fac); assertTrue("a == 0",a.isZERO()); } /** * Test solvable multiplication. */ public void testMultiplication() { a = fac.random(kl, ll, el, q ); //fac.random(ll); assertTrue("not isZERO( a )", !a.isZERO() ); b = fac.random(kl, ll, el, q ); //fac.random(ll); assertTrue("not isZERO( b )", !b.isZERO() ); c = (GenSolvablePolynomial) b.multiply(a); d = (GenSolvablePolynomial) a.multiply(b); assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); e = (GenSolvablePolynomial) d.subtract(c); assertTrue("!isZERO( a*b-b*a ) " + e, !e.isZERO() ); assertTrue("a*b = b*a", !c.equals(d) ); //assertEquals("a*b = b*a",c,d); c = fac.random(kl, ll, el, q ); //fac.random(ll); //System.out.println("c = " + c); d = (GenSolvablePolynomial) a.multiply( b.multiply(c) ); e = (GenSolvablePolynomial) (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); BigQuaternion x = a.leadingBaseCoefficient().inverse(); c = (GenSolvablePolynomial) a.monic(); d = (GenSolvablePolynomial) a.multiply(x); assertEquals("a.monic() = a(1/ldcf(a))",c,d); BigQuaternion y = b.leadingBaseCoefficient().inverse(); c = (GenSolvablePolynomial) b.monic(); d = (GenSolvablePolynomial) b.multiply(y); assertEquals("b.monic() = b(1/ldcf(b))",c,d); e = new GenSolvablePolynomial(fac,y); d = (GenSolvablePolynomial) b.multiply(e); assertEquals("b.monic() = b(1/ldcf(b))",c,d); } /** * Test solvable left and right multiplication. */ public void testDoubleMultiplication() { a = fac.random(kl, 3, el, q ); //fac.random(ll); b = fac.random(kl, 2, el, q ); //fac.random(ll); c = fac.random(kl, 3, el, q ); //fac.random(ll); d = a.multiply(b).multiply(c); e = b.multiply(a,c); assertEquals("a b c = b.multiply(a,c)",d,e); BigQuaternion qa = cfac.random(kl); BigQuaternion qb = cfac.random(kl); BigQuaternion qc = qa.multiply(qb); BigQuaternion qd = qb.multiply(qa); // search non commuting qa, qb while ( qc.equals(qd) ) { qa = cfac.random(kl); qb = cfac.random(kl); qc = qa.multiply(qb); qd = qb.multiply(qa); } //System.out.println("qa = " + qa); //System.out.println("qb = " + qb); //System.out.println("qc = " + qc); //System.out.println("qd = " + qd); a = fac.univariate(0); d = a.multiply(qa,qb); e = a.multiply(qb,qa); //System.out.println("a = " + a); //System.out.println("d = " + d); //System.out.println("e = " + e); assertFalse("a.multiply(qa,qb) != a.multiply(qb,qq)", d.equals(e)); // commuting variables ExpVector ea = fac.univariate(1).leadingExpVector(); ExpVector eb = fac.univariate(2).leadingExpVector(); //System.out.println("ea = " + ea); //System.out.println("eb = " + eb); d = a.multiply(ea,eb); e = a.multiply(eb,ea); //System.out.println("d = " + d); //System.out.println("e = " + e); assertTrue("a.multiply(ea,eb) == a.multiply(eb,eq)", d.equals(e)); d = a.multiply(qa,ea,qb,eb); e = a.multiply(qb,eb,qa,ea); //System.out.println("d = " + d); //System.out.println("e = " + e); assertFalse("a.multiply(qa,ea,qb,eb) != a.multiply(qb,eb,qa,ea)", d.equals(e)); } } jas-2.5/trc/edu/jas/poly/GenVectorTest.java0000644000175000017500000001536712014234362021060 0ustar giovannigiovanni/* * $Id: GenVectorTest.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.poly; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; //import edu.jas.structure.RingElem; //import edu.jas.structure.ModulElem; import edu.jas.arith.BigRational; import edu.jas.vector.GenVector; import edu.jas.vector.GenVectorModul; /** * GenVector tests with JUnit * @author Heinz Kredel. */ public class GenVectorTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a RatGenVectorTest object. * @param name String. */ public GenVectorTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GenVectorTest.class); return suite; } int rl = 5; int kl = 10; int ll = 10; float q = 0.5f; @Override protected void setUp() { } @Override protected void tearDown() { } /** * Test constructor and toString. * */ public void testPolynomialConstruction() { BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, rl); GenVectorModul> mfac = new GenVectorModul>( pfac, ll); assertTrue("#columns = " + ll, mfac.cols == ll); assertTrue("pfac == coFac ", pfac == mfac.coFac); GenVector> a; a = mfac.getZERO(); //System.out.println("a = " + a); assertTrue("isZERO( a )", a.isZERO()); GenVector> b = new GenVector>(mfac); //System.out.println("b = " + b); assertTrue("isZERO( b )", b.isZERO()); assertTrue("a == b ", a.equals(b)); GenVector> c = b.copy(); //System.out.println("c = " + c); assertTrue("isZERO( c )", c.isZERO()); assertTrue("a == c ", a.equals(c)); GenVector> d = mfac.copy(b); //System.out.println("d = " + d); assertTrue("isZERO( d )", d.isZERO()); assertTrue("a == d ", a.equals(d)); } /** * Test random vector * */ public void testPolynomialRandom() { BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, rl); GenVectorModul> mfac = new GenVectorModul>( pfac, ll); GenVector> a; for (int i = 0; i < 7; i++) { a = mfac.random(kl, q); //System.out.println("a = " + a); assertTrue(" not isZERO( a" + i + " )", !a.isZERO()); } } /** * Test addition. * */ public void testPolynomialAddition() { BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, rl); GenVectorModul> mfac = new GenVectorModul>( pfac, ll); GenVector> a, b, c, d, e; a = mfac.random(kl, q); b = mfac.random(kl, q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.sum(b); d = c.subtract(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b-b = a", a, d); c = a.sum(b); d = c.sum(b.negate()); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b+(-b) = a", a, d); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a", c, d); c = mfac.random(kl, q); d = a.sum(b).sum(c); e = a.sum(b.sum(c)); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("a+(b+c) = (a+b)+c", d, e); } /** * Test scalar multiplication. * */ public void testPolynomialMultiplication() { BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, rl); GenVectorModul> mfac = new GenVectorModul>( pfac, ll); GenPolynomial r, s, t; GenVector> a, b, c, d, e; r = pfac.random(kl); //System.out.println("r = " + r); s = r.negate(); //System.out.println("s = " + s); a = mfac.random(kl, q); //System.out.println("a = " + a); c = a.scalarMultiply(r); d = a.scalarMultiply(s); e = c.sum(d); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("a*b + a*(-b) = 0", e, mfac.getZERO()); b = mfac.random(kl, q); //System.out.println("b = " + b); t = pfac.getONE(); //System.out.println("t = " + t); c = a.linearCombination(b, t); d = b.linearCombination(a, t); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b = b+1*a", c, d); c = a.linearCombination(b, t); d = a.sum(b); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b = b+1*a", c, d); s = t.negate(); //System.out.println("s = " + s); c = a.linearCombination(b, t); d = c.linearCombination(b, s); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b+(-1)*b = a", a, d); c = a.linearCombination(t, b, t); d = c.linearCombination(t, b, s); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+1*b+(-1)*b = a", a, d); t = pfac.getZERO(); //System.out.println("t = " + t); c = a.linearCombination(b, t); //System.out.println("c = " + c); assertEquals("a+0*b = a", a, c); d = a.linearCombination(t, b, t); //System.out.println("d = " + d); assertEquals("0*a+0*b = 0", mfac.getZERO(), d); r = a.scalarProduct(b); s = b.scalarProduct(a); //System.out.println("r = " + r); //System.out.println("s = " + s); assertEquals("a.b = b.a", r, s); } } jas-2.5/trc/edu/jas/poly/ModuleListTest.java0000644000175000017500000001714211641660762021252 0ustar giovannigiovanni/* * $Id: ModuleListTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.ArrayList; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; //import edu.jas.structure.RingElem; import edu.jas.arith.BigRational; /** * ModuleList tests with JUnit. * @author Heinz Kredel */ public class ModuleListTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a ModuleListTest object. * @param name String. */ public ModuleListTest(String name) { super(name); } /** * suite. * @return a test suite. */ public static Test suite() { TestSuite suite= new TestSuite(ModuleListTest.class); return suite; } //private final static int bitlen = 100; ModuleList m; PolynomialList p; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; BigRational cfac; GenPolynomialRing pfac; int rl = 4; int kl = 4; int ll = 4; int el = 5; float q = 0.5f; protected void setUp() { a = b = c = d = e = null; cfac = new BigRational(1); TermOrder tord = new TermOrder(); pfac = new GenPolynomialRing(cfac,rl,tord); m = null; p = null; } protected void tearDown() { a = b = c = d = e = null; m = null; p = null; } /** * Test constructor and toString. * */ public void testConstructor() { p = new PolynomialList(pfac,(List>)null); assertTrue("p = 0", p.list == null); m = new ModuleList(pfac,(List>>)null); assertTrue("m = 0", m.list == null); } /** * Test polynomial list. * */ public void testPolynomialList() { List> l = new ArrayList>(); for (int i = 0; i < 7; i++) { a = pfac.random(kl, ll+i, el, q ); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); l.add( a ); } p = new PolynomialList(pfac,l); //System.out.println("p = "+p); assertTrue("p == p", p.equals(p) ); assertEquals("p.length", 7, p.list.size() ); } /** * Test module list. * */ public void testModuleList() { List>> l = new ArrayList>>(); for (int i = 0; i < 4; i++) { List> r = new ArrayList>(); for ( int j = 0; j < 3; j++ ) { a = pfac.random(kl, ll, el, q ); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); r.add( a ); } l.add( r ); } m = new ModuleList(pfac,l); //System.out.println("m = "+m); assertTrue("m == m", m.equals(m) ); assertEquals("m.length", 4, m.list.size() ); } /** * Test module and polynomial list. * */ public void testModulePolynomialList() { List>> l = new ArrayList>>(); for (int i = 0; i < 4; i++) { List> r = new ArrayList>(); for ( int j = 0; j < 3; j++ ) { a = pfac.random(kl, ll, el, q ); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); r.add( a ); } l.add( r ); } m = new ModuleList(pfac,l); //System.out.println("m = "+m); assertTrue("m == m", m.equals(m) ); assertEquals("m.length", 4, m.list.size() ); p = m.getPolynomialList(); //System.out.println("p = "+p); assertTrue("p == p", p.equals(p) ); assertEquals("p.length", 4, p.list.size() ); } /** * Test module and polynomial and module list. * */ public void testModulePolynomialModuleList() { List>> l = new ArrayList>>(); for (int i = 0; i < 4; i++) { List> r = new ArrayList>(); for ( int j = 0; j < 3; j++ ) { a = pfac.random(kl, ll, el, q ); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); r.add( a ); } l.add( r ); } m = new ModuleList(pfac,l); //System.out.println("m = "+m); assertTrue("m == m", m.equals(m) ); assertEquals("m.length", 4, m.list.size() ); p = m.getPolynomialList(); //System.out.println("p = "+p); assertTrue("p == p", p.equals(p) ); assertEquals("p.length", 4, p.list.size() ); ModuleList m2 = null; m2 = p.getModuleList( 3 ); //System.out.println("m2 = "+m2); assertTrue("m2 == m2", m2.equals(m2) ); assertEquals("m2.length", 4, m2.list.size() ); assertTrue("m == m2", m.equals(m2) ); } /** * Test module and polynomial and module and polynomial list. * */ public void testModulePolynomialModuleListPolynomial() { List>> l = new ArrayList>>(); for (int i = 0; i < 4; i++) { List> r = new ArrayList>(); for ( int j = 0; j < 3; j++ ) { a = pfac.random(kl, ll, el, q ); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); r.add( a ); } l.add( r ); } m = new ModuleList(pfac,l); //System.out.println("m = "+m); assertTrue("m == m", m.equals(m) ); assertEquals("m.length", 4, m.list.size() ); p = m.getPolynomialList(); //System.out.println("p = "+p); assertTrue("p == p", p.equals(p) ); assertEquals("p.length", 4, p.list.size() ); ModuleList m2 = null; m2 = p.getModuleList( 3 ); //System.out.println("m2 = "+m2); assertTrue("m2 == m2", m2.equals(m2) ); assertEquals("m2.length", 4, m2.list.size() ); assertTrue("m == m2", m.equals(m2) ); PolynomialList p2 = null; p2 = m2.getPolynomialList(); //System.out.println("p2 = "+p2); assertTrue("p2 == p2", p2.equals(p2) ); assertEquals("p2.length", 4, p2.list.size() ); assertTrue("p == p2", p.list.equals(p2.list) ); } } jas-2.5/trc/edu/jas/ufdroot/0000755000175000017500000000000012140140260016135 5ustar giovannigiovannijas-2.5/trc/edu/jas/ufdroot/FactorRealAlgebraicTest.java0000644000175000017500000001202312002611634023457 0ustar giovannigiovanni/* * $Id: FactorRealAlgebraicTest.java 4010 2012-07-21 20:39:56Z kredel $ */ package edu.jas.ufdroot; import java.util.SortedMap; import org.apache.log4j.BasicConfigurator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.root.RealAlgebraicNumber; import edu.jas.root.RealAlgebraicRing; import edu.jas.root.Interval; import edu.jas.root.RootUtil; import edu.jas.ufdroot.FactorRealAlgebraic; /** * Factor real algebraic tests with JUnit. * @author Heinz Kredel. */ public class FactorRealAlgebraicTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorRealAlgebraicTest object. * @param name String. */ public FactorRealAlgebraicTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorRealAlgebraicTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. */ public void testDummy() { } /** * Test real algebraic factorization. */ public void testRealAlgebraicFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] alpha = new String[] { "alpha" }; String[] vars = new String[] { "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, alpha); GenPolynomial agen = pfac.univariate(0, 2); //agen = agen.subtract(pfac.getONE()); // x^2 - 1 agen = agen.subtract(pfac.fromInteger(2)); // x^2 - 2 //AlgebraicNumberRing afac = new AlgebraicNumberRing(agen, true); Interval iv = RootUtil.parseInterval(cfac, "[0,2]"); //System.out.println("iv = " + iv); RealAlgebraicRing rfac = new RealAlgebraicRing(agen,iv,true); GenPolynomialRing> rpfac = new GenPolynomialRing>( rfac, 1, to, vars); // univariate //System.out.println("agen = " + agen); //System.out.println("afac = " + afac); //System.out.println("rfac = " + rfac); //System.out.println("rpfac = " + rpfac); FactorRealAlgebraic fac = new FactorRealAlgebraic(rfac); for (int i = 1; i < 2; i++) { int facs = 0; GenPolynomial> a; GenPolynomial> c = rpfac.random(2, ll + i, el + i, q); GenPolynomial> b = rpfac.random(2, ll + i, el + i, q); if (b.degree() == 0) { b = b.multiply(rpfac.univariate(0)); } //b = b.monic(); //if ( false && ! a.leadingBaseCoefficient().isONE() ) { //continue; //ExpVector e = a.leadingExpVector(); //a.doPutToMap(e,cfac.getONE()); //} if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } //a = apfac.univariate(0,2).sum( apfac.getONE() ); // x^2 + 1 //a = a.multiply(a); //a = a.multiply( apfac.univariate(0,2).subtract( apfac.getONE() ) ); // x^2 - 1 //a = apfac.univariate(0,3).subtract( apfac.getONE() ); // x^3 - 1 //a = apfac.univariate(0,3).sum( apfac.getONE() ); // x^3 + 1 a = c.multiply(b); //a = c; //a = a.monic(); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("b = " + b.monic()); //System.out.println("c = " + c.monic()); SortedMap>, Long> sm = fac.baseFactors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { System.out.println("sm.size() < facs = " + facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } } jas-2.5/trc/edu/jas/ufd/0000755000175000017500000000000012140140260015231 5ustar giovannigiovannijas-2.5/trc/edu/jas/ufd/QuotIntPolynomialTest.java0000644000175000017500000001507311641660762022434 0ustar giovannigiovanni /* * $Id: QuotIntPolynomialTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; //import edu.jas.arith.BigRational; import edu.jas.arith.BigInteger; import edu.jas.kern.PrettyPrint; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Quotient BigInteger coefficient GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class QuotIntPolynomialTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); ComputerThreads.terminate(); } /** * Constructs a QoutIntPolynomialTest object. * @param name String. */ public QuotIntPolynomialTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(QuotIntPolynomialTest.class); return suite; } //private final static int bitlen = 100; QuotientRing eFac; GenPolynomialRing mfac; GenPolynomialRing> qfac; GenPolynomial< Quotient > a; GenPolynomial< Quotient > b; GenPolynomial< Quotient > c; GenPolynomial< Quotient > d; GenPolynomial< Quotient > e; int rl = 3; int kl = 2; // degree of coefficient polynomials!!! int ll = 4; //6; int el = 3; float q = 0.3f; protected void setUp() { a = b = c = d = e = null; TermOrder to = new TermOrder( TermOrder.INVLEX ); String[] cv = new String[] { "a", "b", "c" }; BigInteger cfac = new BigInteger(1); mfac = new GenPolynomialRing( cfac, rl, to, cv ); eFac = new QuotientRing( mfac ); String[] v = new String[] { "w", "x", "y", "z" }; qfac = new GenPolynomialRing>( eFac, rl+1, v ); } protected void tearDown() { a = b = c = d = e = null; //eFac.terminate(); eFac = null; mfac = null; qfac = null; ComputerThreads.terminate(); } /** * Test constructor and toString. * */ public void testConstruction() { c = qfac.getONE(); //System.out.println("c = " + c); //System.out.println("c.val = " + c.val); assertTrue("length( c ) = 1", c.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = qfac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.val = " + d.val); assertTrue("length( d ) = 0", d.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 3; i++) { //a = qfac.random(ll+i); a = qfac.random(kl, ll+i, el, q ); //System.out.println("a["+i+"] = " + a); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); b = a.monic(); Quotient ldbcf = b.leadingBaseCoefficient(); //System.out.println("b["+i+"] = " + b); assertTrue("ldbcf( b"+i+" ) == 1 " + b + ", a = " + a, ldbcf.isONE()); } } /** * Test addition. * */ public void testAddition() { a = qfac.random(kl,ll,el,q); b = qfac.random(kl,ll,el,q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("a = " + a.toString( qfac.getVars() )); //System.out.println("b = " + b.toString( qfac.getVars() )); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c.toString( qfac.getVars() )); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",c,d); c = qfac.random(kl,ll,el,q); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( qfac.getZERO() ); d = a.subtract( qfac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = qfac.getZERO().sum( a ); d = qfac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = qfac.random(kl,ll,el,q); //assertTrue("not isZERO( a )", !a.isZERO() ); b = qfac.random(kl,ll,el,q); //assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); if ( !a.isZERO() && !b.isZERO() ) { assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); } //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = qfac.random(kl,ll,el,q); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( qfac.getONE() ); d = qfac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",d.isONE()); } } /** * Test parse(). * */ public void testParse() { a = qfac.random(kl,ll*2,el*2,q*2); //assertTrue("not isZERO( a )", !a.isZERO() ); //PrettyPrint.setInternal(); //System.out.println("a = " + a); PrettyPrint.setPretty(); //System.out.println("a = " + a); String p = a.toString( qfac.getVars() ); //System.out.println("p = " + p); b = qfac.parse(p); //System.out.println("b = " + b.toString( qfac.getVars() ) ); //c = a.subtract(b); //System.out.println("c = " + c); assertEquals("parse(a.toSting()) = a",a,b); } } jas-2.5/trc/edu/jas/ufd/SquarefreeRatTest.java0000644000175000017500000002327411641660762021540 0ustar giovannigiovanni/* * $Id: SquarefreeRatTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * Squarefree factorization tests with JUnit. * @author Heinz Kredel. */ public class SquarefreeRatTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a SquarefreeRatTest object. * @param name String. */ public SquarefreeRatTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(SquarefreeRatTest.class); return suite; } TermOrder to = new TermOrder(TermOrder.INVLEX); int rl = 3; int kl = 3; int ll = 4; int el = 3; float q = 0.25f; String[] vars; String[] cvars; String[] c1vars; String[] rvars; BigRational fac; GreatestCommonDivisorAbstract ufd; SquarefreeFieldChar0 sqf; GenPolynomialRing dfac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomialRing cfac; GenPolynomialRing> rfac; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; @Override protected void setUp() { vars = ExpVector.STDVARS(rl); cvars = ExpVector.STDVARS(rl - 1); c1vars = new String[] { cvars[0] }; rvars = new String[] { vars[rl - 1] }; fac = new BigRational(1); //ufd = new GreatestCommonDivisorSubres(); //ufd = GCDFactory. getImplementation(fac); ufd = GCDFactory.getProxy(fac); sqf = new SquarefreeFieldChar0(fac); SquarefreeAbstract sqff = SquarefreeFactory.getImplementation(fac); //System.out.println("sqf = " + sqf); //System.out.println("sqff = " + sqff); assertEquals("sqf == sqff ", sqf.getClass(), sqff.getClass()); a = b = c = d = e = null; ar = br = cr = dr = er = null; } @Override protected void tearDown() { a = b = c = d = e = null; ar = br = cr = dr = er = null; // ComputerThreads.terminate(); } /** * Test base squarefree. * */ public void testBaseSquarefree() { //System.out.println("\nbase:"); dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll, el + 2, q); b = dfac.random(kl, ll, el + 2, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("d = " + d); //System.out.println("c = " + c); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbbc) " + e, e.isZERO()); } /** * Test base squarefree factors. * */ public void testBaseSquarefreeFactors() { dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll, el + 3, q); b = dfac.random(kl, ll, el + 3, q); c = dfac.random(kl, ll, el + 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree. * */ public void testRecursiveSquarefree() { //System.out.println("\nrecursive:"); cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, ll, el, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(ar).multiply(br).multiply(br); cr = ar.multiply(br); //System.out.println("dr = " + dr); //System.out.println("cr = " + cr); cr = sqf.recursiveUnivariateSquarefreePart(cr); dr = sqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("dr = " + dr); //System.out.println("cr = " + cr); assertTrue("isSquarefree(cr) " + cr, sqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, sqf.isRecursiveSquarefree(dr)); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors. * */ public void testRecursiveSquarefreeFactors() { cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, 3, 2, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(cr).multiply(br).multiply(br); //System.out.println("dr = " + dr); SortedMap>, Long> sfactors; sfactors = sqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree. * */ public void testSquarefree() { //System.out.println("\nfull:"); dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, ll, 2, q); b = dfac.random(kl, ll, 2, q); c = dfac.random(kl, ll, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); c = sqf.squarefreePart(c); d = sqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbc) " + e, e.isZERO()); } /** * Test squarefree factors. * */ public void testSquarefreeFactors() { dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } } jas-2.5/trc/edu/jas/ufd/QuotientRatTest.java0000644000175000017500000001751311641660762021245 0ustar giovannigiovanni /* * $Id: QuotientRatTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.kern.PrettyPrint; import edu.jas.kern.ComputerThreads; /** * Quotient over BigRational GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class QuotientRatTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a QuotientRatTest object. * @param name String. */ public QuotientRatTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(QuotientRatTest.class); return suite; } //private final static int bitlen = 100; QuotientRing zFac; QuotientRing efac; GenPolynomialRing mfac; Quotient< BigRational > a; Quotient< BigRational > b; Quotient< BigRational > c; Quotient< BigRational > d; Quotient< BigRational > e; Quotient< BigRational > az; Quotient< BigRational > bz; Quotient< BigRational > cz; Quotient< BigRational > dz; Quotient< BigRational > ez; int rl = 3; int kl = 5; int ll = 3; //6; int el = 2; float q = 0.4f; protected void setUp() { a = b = c = d = e = null; TermOrder to = new TermOrder( TermOrder.INVLEX ); mfac = new GenPolynomialRing( new BigRational(1), rl, to ); efac = new QuotientRing( mfac ); zFac = new QuotientRing( mfac, false ); } protected void tearDown() { a = b = c = d = e = null; //efac.terminate(); efac = null; zFac = null; ComputerThreads.terminate(); } /** * Test constructor and toString. * */ public void testConstruction() { c = efac.getONE(); //System.out.println("c = " + c); //System.out.println("c.val = " + c.val); assertTrue("length( c ) = 1", c.num.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = efac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.val = " + d.val); assertTrue("length( d ) = 0", d.num.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { //a = efac.random(ll+i); a = efac.random(kl*(i+1), ll+2+2*i, el, q ); //System.out.println("a = " + a); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.num.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = efac.random(kl,ll,el,q); b = efac.random(kl,ll,el,q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.sum(b); d = c.subtract(b); //System.out.println("c = " + c); //System.out.println("d = " + d); d = d.monic(); //System.out.println("d = " + d); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",c,d); //System.out.println("monic(d) = " + d.monic()); c = efac.random(kl,ll,el,q); //System.out.println("c = " + c); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); //System.out.println("d = " + d); //System.out.println("e = " + e); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( efac.getZERO() ); d = a.subtract( efac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = efac.getZERO().sum( a ); d = efac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = efac.random(kl,ll,el,q); //assertTrue("not isZERO( a )", !a.isZERO() ); b = efac.random(kl,ll,el,q); //assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); //assertTrue("not isZERO( c )", !c.isZERO() ); //assertTrue("not isZERO( d )", !d.isZERO() ); //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = efac.random(kl,ll,el,q); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( efac.getONE() ); d = efac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",d.isONE()); } } /** * Test addition with syzygy gcd and euclids gcd. * */ public void xtestAdditionGcd() { long te, tz; a = efac.random(kl,ll,el,q); b = efac.random(kl,ll,el,q); //System.out.println("a = " + a); //System.out.println("b = " + b); az = new Quotient(zFac,a.num,a.den,true); bz = new Quotient(zFac,b.num,b.den,true); te = System.currentTimeMillis(); c = a.sum(b); d = c.subtract(b); d = d.monic(); te = System.currentTimeMillis() - te; assertEquals("a+b-b = a",a,d); tz = System.currentTimeMillis(); cz = az.sum(bz); dz = cz.subtract(bz); dz = dz.monic(); tz = System.currentTimeMillis() - tz; assertEquals("a+b-b = a",az,dz); System.out.println("te = " + te); System.out.println("tz = " + tz); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",c,d); c = efac.random(kl,ll,el,q); cz = new Quotient(zFac,c.num,c.den,true); te = System.currentTimeMillis(); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); te = System.currentTimeMillis() - te; assertEquals("c+(a+b) = (c+a)+b",d,e); tz = System.currentTimeMillis(); dz = cz.sum( az.sum(bz) ); ez = cz.sum( az ).sum(bz); tz = System.currentTimeMillis() - tz; assertEquals("c+(a+b) = (c+a)+b",dz,ez); System.out.println("te = " + te); System.out.println("tz = " + tz); c = a.sum( efac.getZERO() ); d = a.subtract( efac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = efac.getZERO().sum( a ); d = efac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test parse(). * */ public void testParse() { a = efac.random(kl*2,ll*2,el*2,q*2); //assertTrue("not isZERO( a )", !a.isZERO() ); //PrettyPrint.setInternal(); //System.out.println("a = " + a); PrettyPrint.setPretty(); //System.out.println("a = " + a); String p = a.toString(); //System.out.println("p = " + p); b = efac.parse(p); //System.out.println("b = " + b); //c = a.subtract(b); //System.out.println("c = " + c); assertEquals("parse(a.toSting()) = a",a,b); } } jas-2.5/trc/edu/jas/ufd/GCDSubresTest.java0000644000175000017500000004372711677401354020554 0ustar giovannigiovanni/* * $Id: GCDSubresTest.java 3850 2011-12-30 18:29:00Z kredel $ */ package edu.jas.ufd; //import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.ModInteger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GCD Subresultant PRS algorithm tests with JUnit. * @author Heinz Kredel. */ public class GCDSubresTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDSubresTest object. * @param name String. */ public GCDSubresTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDSubresTest.class); return suite; } GreatestCommonDivisorAbstract ufd; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 5; int kl = 4; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd = new GreatestCommonDivisorPrimitive(); String[] vars = ExpVector.STDVARS(rl); String[] cvars = ExpVector.STDVARS(rl - 1); String[] rvars = new String[] { vars[rl - 1] }; dfac = new GenPolynomialRing(new BigInteger(1), rl, to, vars); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to, cvars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd = null; dfac = null; cfac = null; rfac = null; } /** * Test base gcd subresultant. */ public void testBaseGcdSubres() { ufd = new GreatestCommonDivisorSubres(); dfac = new GenPolynomialRing(new BigInteger(1), 1, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 2, q); c = dfac.random(kl * (i + 2), ll + 2, el + 2, q); c = c.multiply(dfac.univariate(0)); if (c.isZERO()) { // skip for this turn continue; } //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); c = ufd.basePrimitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); d = ufd.baseGcd(a, b); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); //System.out.println("c = " + c); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a" + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b" + e, e.isZERO()); } } /** * Test recursive gcd subresultant. */ public void testRecursiveGCDsubres() { ufd = new GreatestCommonDivisorSubres(); di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 2, to); cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 5; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); cr = ufd.recursivePrimitivePart(cr).abs(); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); dr = ufd.recursiveUnivariateGcd(ar, br); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); er = PolyUtil. recursivePseudoRemainder(ar, dr); //System.out.println("er = " + er); assertTrue("gcd(a,b) | a" + er, er.isZERO()); er = PolyUtil. recursivePseudoRemainder(br, dr); //System.out.println("er = " + er); assertTrue("gcd(a,b) | b" + er, er.isZERO()); } } /** * Test arbitrary recursive gcd subresultant. */ public void testArbitraryRecursiveGCDsubres() { ufd = new GreatestCommonDivisorSubres(); di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 2, to); cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 5; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); cr = ufd.recursivePrimitivePart(cr).abs(); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); dr = ufd.recursiveGcd(ar, br); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); er = PolyUtil. recursivePseudoRemainder(ar, dr); //System.out.println("er = " + er); assertTrue("gcd(a,b) | a" + er, er.isZERO()); er = PolyUtil. recursivePseudoRemainder(br, dr); //System.out.println("er = " + er); assertTrue("gcd(a,b) | b" + er, er.isZERO()); } } /** * Test gcd subresultant. */ public void testGCDsubres() { //GreatestCommonDivisorAbstract ufd_pp; //ufd_pp = ufd; ufd = new GreatestCommonDivisorSubres(); dfac = new GenPolynomialRing(new BigInteger(1), 5, to); for (int i = 0; i < 2; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); c = c.multiply(dfac.univariate(0)); c = ufd.primitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); d = ufd.gcd(a, b); //System.out.println("c = " + c); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b " + e, e.isZERO()); } } /** * Test base subresultant. */ public void testBaseSubresultant() { GreatestCommonDivisorSubres ufd = new GreatestCommonDivisorSubres(); dfac = new GenPolynomialRing(new BigInteger(1), 1, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 2, q); c = dfac.random(kl, ll, 2, q); //c = c.multiply( cfac.univariate(0) ); //c = dfac.getONE(); if (c.isZERO()) { // skip for this turn continue; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); d = ufd.baseResultant(a, b); e = ufd.baseGcd(a, b); //System.out.println("d = " + d); //System.out.println("c = " + c); //System.out.println("e = " + e); if (!e.isConstant()) { assertTrue("res(a,b) == 0 " + d, d.isZERO()); } else { assertTrue("res(a,b) != 0 " + d, !d.isZERO()); } } } /** * Test recursive subresultant. */ public void testRecursiveSubresultant() { GreatestCommonDivisorSubres ufd = new GreatestCommonDivisorSubres(); di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 2, to); cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 5; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, 2, q); //cr = rfac.getONE(); //cr = ufd.recursivePrimitivePart(cr).abs(); //cr = cr.multiply( rfac.univariate(0) ); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveUnivariateResultant(ar, br); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); er = ufd.recursiveUnivariateGcd(ar, br); //System.out.println("er = " + er); if (er.isZERO()) { // cannot happen since a, b, c != 0 assertTrue("res(a,b) = 0 " + dr + " e = " + er, dr.isZERO()); } if (er.isConstant() && er.leadingBaseCoefficient().isConstant()) { assertTrue("res(a,b) != 0 " + dr + ", e = " + er + ", a = " + ar + ", b = " + br, !dr .isZERO()); } else { assertTrue("res(a,b) = 0 or not const " + dr + ", e = " + er + ", a = " + ar + ", b = " + br, dr.isZERO() || !dr.isConstant() || !dr.leadingBaseCoefficient().isConstant()); } } } /** * Test subresultant. */ public void testSubres() { GreatestCommonDivisorSubres ufd = new GreatestCommonDivisorSubres(); dfac = new GenPolynomialRing(new BigInteger(1), 3, to); for (int i = 0; i < 2; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, 2, q); //c = dfac.getONE(); //c = c.multiply( dfac.univariate(0) ); //c = ufd.primitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.resultant(a, b); e = ufd.gcd(a, b); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); if (e.isZERO()) { // cannot happen since a, b, c != 0 assertTrue("res(a,b) = 0 " + d + " e = " + e, d.isZERO()); } if (e.isConstant()) { assertTrue("res(a,b) != 0 " + d + ", e = " + e + ", a = " + a + ", b = " + b, !d.isZERO()); } else { assertTrue("res(a,b) = 0 or not const " + d + ", e = " + e + ", a = " + a + ", b = " + b, d .isZERO() || !d.isConstant()); } } } /** * Test and compare resultant. */ public void testResultant() { GreatestCommonDivisorAbstract ufdm = new GreatestCommonDivisorModular(true); GreatestCommonDivisorSubres ufds = new GreatestCommonDivisorSubres(); dfac = new GenPolynomialRing(new BigInteger(1), 3, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl+(i+1), ll, el, q); b = dfac.random(kl+(i+2), ll, el, q); c = dfac.random(kl, ll, 2, q); //c = dfac.getONE(); //c = c.multiply( dfac.univariate(0) ); //c = ufd.primitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } if (c.isConstant()) { c = dfac.univariate(0,1); } //System.out.println("c = " + c); assertTrue("length( c" + i + " ) <> 0", c.length() > 0); d = ufdm.resultant(a, b); //System.out.println("d = " + d); e = ufds.resultant(a, b); //System.out.println("e = " + e); assertEquals("d == e: " + d.subtract(e), d.abs().signum(), e.abs().signum()); //assertEquals("d == e: " + d.subtract(e), d, e); GenPolynomial ac = a.multiply(c); GenPolynomial bc = b.multiply(c); //System.out.println("ac = " + ac); //System.out.println("bc = " + bc); d = ufdm.resultant(ac, bc); //System.out.println("d = " + d); //assertTrue("d == 0: " + d, d.isZERO()); e = ufds.resultant(ac, bc); //System.out.println("e = " + e); //assertTrue("e == 0: " + e, e.isZERO()); assertEquals("d == e: " + d.subtract(e), d.abs().signum(), e.abs().signum()); } } } jas-2.5/trc/edu/jas/ufd/GCDTimingTest.java0000644000175000017500000002667111641660762020540 0ustar giovannigiovanni/* * $Id: GCDTimingTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GreatestCommonDivisor timing tests with JUnit. * @author Heinz Kredel. */ public class GCDTimingTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDTimingTest object. * @param name String. */ public GCDTimingTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDTimingTest.class); return suite; } //private final static int bitlen = 100; GreatestCommonDivisorAbstract ufd_si; GreatestCommonDivisorAbstract ufd_pp; GreatestCommonDivisorSubres ufd_sr; // because of non sparse pseudo remainder GreatestCommonDivisorAbstract ufd_mosi; GreatestCommonDivisorAbstract ufd_moevsi; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 5; int kl = 4; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd_si = new GreatestCommonDivisorSimple(); ufd_pp = new GreatestCommonDivisorPrimitive(); ufd_sr = new GreatestCommonDivisorSubres(); ufd_mosi = new GreatestCommonDivisorModular(true); ufd_moevsi = new GreatestCommonDivisorModular(); dfac = new GenPolynomialRing(new BigInteger(1), rl, to); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd_si = null; ufd_pp = null; ufd_sr = null; dfac = null; cfac = null; rfac = null; } /** * Test dummy for junit. * */ public void testDummy() { assertTrue("ufd_pp != null", ufd_pp != null); } /** * Test base gcd simple. * */ public void xtestBaseGcd() { dfac = new GenPolynomialRing(new BigInteger(1), 1, to); long t; for (int i = 0; i < 10; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = c.multiply(dfac.univariate(0)); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); //c = ufd.basePrimitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); System.out .println("\ndegrees: a = " + a.degree() + ", b = " + b.degree() + ", c = " + c.degree()); /* t = System.currentTimeMillis(); d = ufd_si.baseGcd(a,b); t = System.currentTimeMillis() - t; e = PolyUtil.basePseudoRemainder(d,c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO() ); System.out.println("simple prs time = " + t); */ t = System.currentTimeMillis(); d = ufd_pp.baseGcd(a, b); t = System.currentTimeMillis() - t; e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); System.out.println("primitive prs time = " + t); t = System.currentTimeMillis(); d = ufd_sr.baseGcd(a, b); t = System.currentTimeMillis() - t; e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); System.out.println("subsresultant prs time = " + t); } } /** * Test recursive gcd. * */ public void xtestRecursiveGCD() { cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); long t; for (int i = 0; i < 5; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el + i, q); cr = rfac.random(kl, ll, el, q); cr = cr.multiply(rfac.univariate(0)); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); System.out.println("\ndegrees: a = " + ar.degree() + ", b = " + br.degree() + ", c = " + cr.degree()); t = System.currentTimeMillis(); dr = ufd_si.recursiveUnivariateGcd(ar, br); t = System.currentTimeMillis() - t; //System.out.println("dr = " + dr); //er = PolyUtil.recursivePseudoRemainder(dr,cr); //System.out.println("er = " + er); //assertTrue("c | gcd(ac,bc) " + er, er.isZERO() ); System.out.println("simple prs time = " + t); /* */ t = System.currentTimeMillis(); dr = ufd_pp.recursiveUnivariateGcd(ar, br); t = System.currentTimeMillis() - t; //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); System.out.println("primitive prs time = " + t); t = System.currentTimeMillis(); dr = ufd_sr.recursiveUnivariateGcd(ar, br); t = System.currentTimeMillis() - t; //System.out.println("dr = " + dr); er = ufd_sr.recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); System.out.println("subresultant prs time = " + t); } } /** * Test gcd. * */ public void xtestGCD() { long t; dfac = new GenPolynomialRing(new BigInteger(1), 3, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl + i * 30, ll + i, 2 * el, q); b = dfac.random(kl + i * 30, ll + i, 2 * el, q); c = dfac.random(kl, ll, el, q); //c = dfac.getONE(); //c = c.multiply( dfac.univariate(0) ).multiply( dfac.univariate(4) ); //c = c.multiply( dfac.univariate(0) ); c = ufd_pp.primitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); System.out .println("\ndegrees: a = " + a.degree() + ", b = " + b.degree() + ", c = " + c.degree()); /* t = System.currentTimeMillis(); d = ufd_si.gcd(a,b); t = System.currentTimeMillis() - t; e = PolyUtil.basePseudoRemainder(d,c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO() ); System.out.println("simple prs time = " + t); */ /* t = System.currentTimeMillis(); d = ufd_pp.gcd(a,b); t = System.currentTimeMillis() - t; e = PolyUtil.basePseudoRemainder(d,c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO() ); System.out.println("primitive prs time = " + t); */ t = System.currentTimeMillis(); d = ufd_sr.gcd(a, b); t = System.currentTimeMillis() - t; e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); System.out.println("subsresultant prs time = " + t); t = System.currentTimeMillis(); d = ufd_mosi.gcd(a, b); t = System.currentTimeMillis() - t; e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); System.out.println("modular simple time = " + t); t = System.currentTimeMillis(); d = ufd_moevsi.gcd(a, b); t = System.currentTimeMillis() - t; e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); System.out.println("modular eval time = " + t); } } } jas-2.5/trc/edu/jas/ufd/FactorIntegerTest.java0000644000175000017500000006234012003043360021476 0ustar giovannigiovanni/* * $Id: FactorIntegerTest.java 4019 2012-07-22 18:31:13Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import java.util.List; import org.apache.log4j.BasicConfigurator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.ModInteger; import edu.jas.kern.ComputerThreads; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Factor tests with JUnit. * @author Heinz Kredel. */ public class FactorIntegerTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorIntegerTest object. * @param name String. */ public FactorIntegerTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorIntegerTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 5; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. */ public void testDummy() { } /** * Test integer monic factorization. */ public void testIntegerMonicFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(4); BigInteger one = cfac.getONE(); GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, new String[] { "x" }); FactorAbstract fac = new FactorInteger(); for (int i = 1; i < 3; i++) { int facs = 0; GenPolynomial a = null; //pfac.random(kl,ll*(i+1),el*(i+1),q); GenPolynomial b = pfac.random(kl * 2, ll * (i), el * (i + 1), q); GenPolynomial c = pfac.random(kl, ll * (i), el * (i + 2), q); //b = pfac.parse("((x^2 + 1)*(x^2 - 111111111))"); //c = pfac.parse("(x^3 - 222222)"); if (b.isZERO() || c.isZERO()) { continue; } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } if (!c.leadingBaseCoefficient().isUnit()) { ExpVector e = c.leadingExpVector(); c.doPutToMap(e, one); } if (!b.leadingBaseCoefficient().isUnit()) { ExpVector e = b.leadingExpVector(); b.doPutToMap(e, one); } a = c.multiply(b); if (a.isConstant()) { continue; } GreatestCommonDivisorAbstract engine = GCDFactory.getProxy(cfac); //a = engine.basePrimitivePart(a); // a = a.abs(); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap, Long> sm = fac.baseFactors(a); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs + ", " + b + " * " + c, sf >= facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } /** * Test integer factorization. */ public void testIntegerFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(4); //BigInteger one = cfac.getONE(); GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to); FactorAbstract fac = new FactorInteger(); for (int i = 1; i < 2; i++) { int facs = 0; GenPolynomial a = null; //pfac.random(kl,ll*(i+1),el*(i+1),q); GenPolynomial b = pfac.random(kl * 2, ll * (i), el * (i + 1), q); GenPolynomial c = pfac.random(kl, ll * (i), el * (i + 2), q); if (b.isZERO() || c.isZERO()) { continue; } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); if (a.isConstant()) { continue; } GreatestCommonDivisorAbstract engine = GCDFactory.getProxy(cfac); //a = engine.basePrimitivePart(a); // a = a.abs(); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap, Long> sm = fac.baseFactors(a); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs, sf >= facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } /** * Test integer factorization irreducible polynomial. */ public void testIntegerFactorizationIrred() { //BasicConfigurator.configure(); TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(4); //BigInteger one = cfac.getONE(); String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); FactorAbstract fac = new FactorInteger(); for (int i = 1; i < 2; i++) { int facs = 0; GenPolynomial a = pfac.random(kl, ll * (i + 1), el * (i + 1), q); a = pfac.parse("( x^8 - 40 x^6 + 352 x^4 - 960 x^2 + 576 )"); // Swinnerton-Dyer example if (a.isConstant()) { continue; } SortedMap, Long> sm = fac.baseFactors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= 1) { assertTrue("#facs < " + facs, sm.size() >= 1); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } /** * Test bi-variate integer factorization. */ public void testBivariateIntegerFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 2, to, vars); //FactorAbstract fac = new FactorInteger(); FactorInteger fac = new FactorInteger(); for (int i = 1; i < 2; i++) { GenPolynomial b = pfac.random(kl, 3, el, q / 2.0f); GenPolynomial c = pfac.random(kl, 2, el, q); GenPolynomial d = pfac.random(kl, 2, el, q); b = pfac.parse(" ( x y^2 - 1 ) "); c = pfac.parse(" ( 2 x y + 1 ) "); d = pfac.parse(" ( y^4 + 3 x )"); //b = pfac.parse(" ( y + x + 1 ) "); //c = pfac.parse(" ( y ) "); //d = pfac.parse(" ( 1 )"); GenPolynomial a; a = b.multiply(c).multiply(d); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); List> sm = fac.factorsSquarefreeHensel(a); //System.out.println("sm = " + sm); //sm = fac.factorsSquarefree(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 3, sm = " + sm, sm.size() >= 3); } } /** * Test tri-variate integer factorization. */ public void ytestTrivariateIntegerFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y", "z"}; //vars = new String[] { "x", "y"}; GenPolynomialRing pfac = new GenPolynomialRing(cfac, vars.length, to, vars); //FactorAbstract fac = new FactorInteger(); FactorInteger fac = new FactorInteger(); for (int i = 1; i < 2; i++) { GenPolynomial b = pfac.random(kl, 3, el, q / 2.0f); GenPolynomial c = pfac.random(kl, 2, el, q); GenPolynomial d = pfac.random(kl, 2, el, q); b = pfac.parse(" ( 5 x y^2 - 1 ) "); c = pfac.parse(" ( 2 x y z^2 + 1 ) "); d = pfac.parse(" ( y^3 z + 3 x )"); GenPolynomial a; a = b.multiply(c).multiply(d); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); List> sm = fac.factorsSquarefreeHensel(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 3, sm = " + sm, sm.size() >= 3); //sm = fac.factorsSquarefree(a); //System.out.println("sm = " + sm); //t = fac.isFactorization(a, sm); //System.out.println("t = " + t); //assertTrue("prod(factor(a)) = a", t); } } /** * Test quad-variate integer factorization. */ public void ytestQuadvariateIntegerFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y", "z", "w" }; //vars = new String[] { "x", "y", "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, vars.length, to, vars); //FactorAbstract fac = new FactorInteger(); FactorInteger fac = new FactorInteger(); for (int i = 1; i < 2; i++) { GenPolynomial b = pfac.random(kl, 3, el, q / 2.0f); GenPolynomial c = pfac.random(kl, 2, el, q); GenPolynomial d = pfac.random(kl, 2, el, q); b = pfac.parse(" ( 5 x y^2 - 1 ) "); c = pfac.parse(" ( 2 x z^2 + w^2 y ) "); d = pfac.parse(" ( y^3 z + 7 x )"); GenPolynomial a; a = b.multiply(c).multiply(d); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); List> sm = fac.factorsSquarefreeHensel(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 3, sm = " + sm, sm.size() >= 3); //sm = fac.factorsSquarefree(a); //System.out.println("sm = " + sm); //t = fac.isFactorization(a, sm); ////System.out.println("t = " + t); //assertTrue("prod(factor(a)) = a", t); } } /** * Test multivariate integer factorization. */ public void testMultivariateIntegerFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y", "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, to, vars); FactorAbstract fac = new FactorInteger(); for (int i = 1; i < 2; i++) { GenPolynomial b = pfac.random(kl, 3, el, q / 2.0f); GenPolynomial c = pfac.random(kl, 2, el, q); b = pfac.parse("( z - y )"); c = pfac.parse("( z + x )"); GenPolynomial a; // if ( !a.leadingBaseCoefficient().isUnit()) { // //continue; // //ExpVector e = a.leadingExpVector(); // //a.doPutToMap(e,cfac.getONE()); // } a = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap, Long> sm = fac.factors(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 2, sm = " + sm, sm.size() >= 2); } } /** * Test integer factorization, example 1 from Wang. */ public void testIntegerFactorizationEx1() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y", "z"}; GenPolynomialRing pfac = new GenPolynomialRing(cfac, vars.length, to, vars); FactorInteger fac = new FactorInteger(); GenPolynomial a, b, c, d; // (z + xy + 10)(xz + y + 30)(yz + x + 20), b = pfac.parse(" (z + x y + 10) "); c = pfac.parse(" (x z + y + 30) "); d = pfac.parse(" (y z + x + 20) "); a = b.multiply(c).multiply(d); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); List> sm = fac.factorsSquarefreeHensel(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 3, sm = " + sm, sm.size() >= 3); } /** * Test integer factorization, example 2 from Wang. */ public void testIntegerFactorizationEx2() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y", "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, vars.length, to, vars); FactorInteger fac = new FactorInteger(); GenPolynomial a, b, c, d; // (x^3(z + y) + z - 11) (x^(z^2 + y^2) + y + 90), b = pfac.parse(" (x^3 (z + y) + z - 11) "); c = pfac.parse(" (x^2 (z^2 + y^2) + y + 90) "); a = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); List> sm = fac.factorsSquarefreeHensel(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 2, sm = " + sm, sm.size() >= 2); } /** * Test integer factorization, example 3 from Wang. */ public void testIntegerFactorizationEx3() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y", "z"}; GenPolynomialRing pfac = new GenPolynomialRing(cfac, vars.length, to, vars); FactorInteger fac = new FactorInteger(); GenPolynomial a, b, c, d; // (y z^3 + x y z + y^2 + x^3) (x (z^4 + 1) + z + x^3 y^2) b = pfac.parse(" (y z^3 + x y z + y^2 + x^3) "); c = pfac.parse(" (x (z^4 + 1) + z + x^3 y^2) "); a = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); List> sm = fac.factorsSquarefreeHensel(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 2, sm = " + sm, sm.size() >= 2); } /** * Test integer factorization, example 4 from Wang. */ public void testIntegerFactorizationEx4() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y", "z"}; GenPolynomialRing pfac = new GenPolynomialRing(cfac, vars.length, to, vars); FactorInteger fac = new FactorInteger(); GenPolynomial a, b, c, d, e; // (z^2 - x^3 y + 3) (z^2 + x y^3) (z^2 + x^3 y^4) (y^4 z^2 + x^2 z + 5) b = pfac.parse(" ( z^2 - x^3 y + 3 ) "); c = pfac.parse(" (z^2 + x y^3) "); d = pfac.parse(" (z^2 + x^3 y^4) "); e = pfac.parse(" (y^4 z^2 + x^2 z + 5) "); a = b.multiply(c).multiply(d).multiply(e); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); //List> sm = fac.factorsRadical(a); // will check squarefree List> sm = fac.factorsSquarefreeHensel(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 4, sm = " + sm, sm.size() >= 4); } /** * Test integer factorization, example 5 from Wang. */ public void testIntegerFactorizationEx5() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y", "z", "u"}; GenPolynomialRing pfac = new GenPolynomialRing(cfac, vars.length, to, vars); FactorInteger fac = new FactorInteger(); GenPolynomial a, b, c, d; // (z^2 + x^3 y^4 + u^2) ( (y^2 + x) z^2 + 3 u^2 x^3 y^4 z + 19 y^2) (u^2 y^4 z^2 + x^2 z + 5), b = pfac.parse(" (z^2 + x^3 y^4 + u^2) "); c = pfac.parse(" ( (y^2 + x ) z^2 + 3 u^2 x^3 y^4 z + 19 y^2 )"); //d = pfac.parse(" (u^2 y^4 z^2 + x^2 z + 5) "); a = b.multiply(c); // .multiply(d); // all factors need 256 sec //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); List> sm = fac.factorsSquarefreeHensel(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 2, sm = " + sm, sm.size() >= 2); } /** * Test integer factorization, example 6 from Wang. */ public void testIntegerFactorizationEx6() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y", "z", "w"}; GenPolynomialRing pfac = new GenPolynomialRing(cfac, vars.length, to, vars); FactorInteger fac = new FactorInteger(); GenPolynomial a, b, c, d; // (w^4 z^3 -x y^2 z^2 - w^4 x^5 y^6 - w^2 x^3 y) (- x^5 z^3 + y z + x^2 y^3) // . (w^4 z^6 + y^2 z^3 - w^2 x^2 y^2 z^2 + x^5 z - x^4 y^2 - w^3 x^3 y) //b = pfac.parse(" (w^4 z^3 -x y^2 z^2 - w^4 x^5 y^6 - w^2 x^3 y) "); //c = pfac.parse(" (- x^5 z^3 + y z + x^2 y^3) "); //d = pfac.parse(" (w^4 z^6 + y^2 z^3 - w^2 x^2 y^2 z^2 + x^5 z - x^4 y^2 - w^3 x^3 y) "); // with smaller degrees: b = pfac.parse(" (w z^2 - x y^1 z^1 - w x^5 y^2 - w x^3 y) "); c = pfac.parse(" (- x^5 z^2 + y z + x^2 y^1) "); //d = pfac.parse(" (w z^3 + y^2 z^2 - w x^2 y^2 z^1 + x^5 - x^4 y^2 - w x^3 y) "); a = b.multiply(c); //.multiply(d); // all factors with small degrees need 684 sec //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("d = " + d); List> sm = fac.factorsSquarefreeHensel(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 2, sm = " + sm, sm.size() >= 2); } /** * Test integer factorization, example 7 from Wang. */ public void testIntegerFactorizationEx7() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "x", "y", "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, vars.length, to, vars); FactorInteger fac = new FactorInteger(); GenPolynomial a, b, c, d; // (z + y + x- 3)^3 (z + y + x-2)^2, b = pfac.parse(" ( (z + y^2 + x - 3 )^3 ) "); c = pfac.parse(" ( (z + y + x^2 - 2 )^2 ) "); a = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap,Long> sm = fac.factors(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 2, sm = " + sm, sm.size() >= 2); } /** * Test integer factorization. */ public void testIntegerFactorizationHk() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] vars = new String[] { "t", "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, vars.length, to, vars); FactorInteger fac = new FactorInteger(); GenPolynomial a; // 2 t * x^2 + 5 x^2 - 4 t * x - 4 x - 6 t - 9 // 2 t * x^2 - 5 x^2 + 8 t * x - 5 x + 6 t // 7 t * x^3 + 7 x^3 + 7 t * x^2 + 7 x^2 + 8 x + 8 // = ( x + { 1 } ) ( { 7 t + 7 } x^2 + { 8 } ) // 4 t * x^3 + 6 x^3 + 4 t * x^2 + 9 x^2 + 2 x - 1 // 2 t * x^2 - 7 x^2 + 2 t * x - 11 x - 4 // conter example to Wangs condition: [2 , x, x + 1 ] // 3 x^4 - ( 7 t + 2 ) x^2 + ( 4 t^2 + 2 t ) //a = pfac.parse(" ( 2 t * x^2 + 5 x^2 - 4 t * x - 4 x - 6 t - 9 ) "); //a = pfac.parse(" ( 2 t * x^2 - 5 x^2 + 8 t * x - 5 x + 6 t ) "); //a = pfac.parse(" ( 7 t * x^3 + 7 x^3 + 7 t * x^2 + 7 x^2 + 8 x + 8 ) "); //a = pfac.parse(" ( 4 t * x^3 + 6 x^3 + 4 t * x^2 + 9 x^2 + 2 x - 1 ) "); a = pfac.parse(" ( 2 t * x^2 - 7 x^2 + 2 t * x - 11 x - 4 ) "); // example to parts of Wangs condition: [2 , x, x + 1 ] a = pfac.parse(" ( 3 x^4 - ( 7 t + 2 ) x^2 + ( 4 t^2 + 2 t ) ) "); // was not applicable or failed for t < x //System.out.println("a = " + a); SortedMap,Long> sm = fac.factors(a); //System.out.println("sm = " + sm); boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); assertTrue("#facs < 2, sm = " + sm, sm.size() >= 2); } } jas-2.5/trc/edu/jas/ufd/SquarefreeQuotModTest.java0000644000175000017500000004554711641660762022411 0ustar giovannigiovanni/* * $Id: SquarefreeQuotModTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.structure.Power; /** * Squarefree factorization tests with JUnit. * @author Heinz Kredel. */ public class SquarefreeQuotModTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a SquarefreeQuotModTest object. * @param name String. */ public SquarefreeQuotModTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(SquarefreeQuotModTest.class); return suite; } TermOrder to = new TermOrder(TermOrder.INVLEX); int rl = 3; int kl = 1; int ll = 3; int el = 3; float q = 0.25f; String[] vars; String[] cvars; String[] c1vars; String[] rvars; ModIntegerRing mfac; String[] alpha; GenPolynomialRing mpfac; GenPolynomial agen; QuotientRing fac; GreatestCommonDivisorAbstract> ufd; SquarefreeInfiniteFieldCharP sqf; GenPolynomialRing> dfac; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; GenPolynomial> d; GenPolynomial> e; GenPolynomialRing> cfac; GenPolynomialRing>> rfac; GenPolynomial>> ar; GenPolynomial>> br; GenPolynomial>> cr; GenPolynomial>> dr; GenPolynomial>> er; @Override protected void setUp() { vars = ExpVector.STDVARS(rl); cvars = ExpVector.STDVARS(rl - 1); c1vars = new String[] { cvars[0] }; rvars = new String[] { vars[rl - 1] }; mfac = new ModIntegerRing(7); alpha = new String[] { "u" }; mpfac = new GenPolynomialRing(mfac, 1, to, alpha); fac = new QuotientRing(mpfac); //ufd = new GreatestCommonDivisorSubres>(); //ufd = GCDFactory.> getImplementation(fac); ufd = GCDFactory.> getProxy(fac); sqf = new SquarefreeInfiniteFieldCharP(fac); SquarefreeAbstract> sqff = SquarefreeFactory.getImplementation(fac); //System.out.println("sqf = " + sqf); //System.out.println("sqff = " + sqff); assertEquals("sqf == sqff ", sqf.getClass(), sqff.getClass()); a = b = c = d = e = null; ar = br = cr = dr = er = null; } @Override protected void tearDown() { a = b = c = d = e = null; ar = br = cr = dr = er = null; //ComputerThreads.terminate(); } /** * Test base squarefree. * */ public void testBaseSquarefree() { //System.out.println("\nbase:"); dfac = new GenPolynomialRing>(fac, 1, to, rvars); a = dfac.random(kl + 1, ll, el + 1, q); b = dfac.random(kl + 1, ll, el + 1, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("d = " + d); //System.out.println("c = " + c); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil.> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbbc) " + e, e.isZERO()); } /** * Test base squarefree factors. * */ public void testBaseSquarefreeFactors() { dfac = new GenPolynomialRing>(fac, 1, to, rvars); a = dfac.random(kl + 1, ll, el + 2, q); b = dfac.random(kl + 1, ll, el + 2, q); c = dfac.random(kl, ll, el + 1, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap>, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree. * */ public void testRecursiveSquarefree() { //System.out.println("\nrecursive:"); cfac = new GenPolynomialRing>(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(ar).multiply(br).multiply(br); cr = ar.multiply(br); //System.out.println("dr = " + dr); //System.out.println("cr = " + cr); cr = sqf.recursiveUnivariateSquarefreePart(cr); dr = sqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("dr = " + dr); //System.out.println("cr = " + cr); assertTrue("isSquarefree(cr) " + cr, sqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, sqf.isRecursiveSquarefree(dr)); er = PolyUtil.> recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors. * */ public void testRecursiveSquarefreeFactors() { cfac = new GenPolynomialRing>(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, 3, 2, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(cr).multiply(br).multiply(br); //System.out.println("dr = " + dr); SortedMap>>, Long> sfactors; sfactors = sqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree. * */ public void testSquarefree() { //System.out.println("\nfull:"); dfac = new GenPolynomialRing>(fac, rl, to, vars); a = dfac.random(kl, ll, 2, q); b = dfac.random(kl, ll - 1, 2, q); c = dfac.random(kl, ll, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); c = sqf.squarefreePart(c); d = sqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); e = PolyUtil.> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbc) " + e, e.isZERO()); } /** * Test squarefree factors. * */ public void testSquarefreeFactors() { dfac = new GenPolynomialRing>(fac, rl, to, vars); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 2, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap>, Long> sfactors; sfactors = sqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /* ------------char-th root ------------------------- */ /** * Test base squarefree with char-th root. * */ public void testBaseSquarefreeCharRoot() { //System.out.println("\nbase CharRoot:"); long p = fac.characteristic().longValue(); //dfac = new GenPolynomialRing(fac,1,to,rvars); dfac = new GenPolynomialRing>(fac, 1, to, rvars); a = dfac.random(kl + 1, ll + 1, el + 2, q).monic(); b = dfac.random(kl, ll + 1, el + 2, q).monic(); c = dfac.random(kl + 1, ll, el, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.>> positivePower(b, p)).multiply( c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil.> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test base squarefree factors with char-th root. * */ public void testBaseSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); //dfac = new GenPolynomialRing(fac,1,to,rvars); dfac = new GenPolynomialRing>(fac, 1, to, rvars); a = dfac.random(kl, ll + 1, el + 3, q).monic(); b = dfac.random(kl, ll + 1, el + 3, q).monic(); c = dfac.random(kl, ll, el + 2, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.>> positivePower(b, p)).multiply( c); //d = d.monic(); //System.out.println("d = " + d); SortedMap>, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree with char-th root. * */ public void testRecursiveSquarefreeCharRoot() { //System.out.println("\nrecursive CharRoot:"); long p = fac.characteristic().longValue(); cfac = new GenPolynomialRing>(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2 + 1, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, ll, el, q); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } ar = PolyUtil.> monic(ar); br = PolyUtil.> monic(br); cr = PolyUtil.> monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); // a b^p c dr = ar.multiply(Power.>>> positivePower(br, p)).multiply(cr); cr = ar.multiply(br).multiply(cr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); cr = sqf.recursiveUnivariateSquarefreePart(cr); dr = sqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); assertTrue("isSquarefree(cr) " + cr, sqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, sqf.isRecursiveSquarefree(dr)); er = PolyUtil.> recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors with char-th root. * */ public void testRecursiveSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); cfac = new GenPolynomialRing>(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2 + 1, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, 3, 2, q); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } ar = PolyUtil.> monic(ar); br = PolyUtil.> monic(br); cr = PolyUtil.> monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); // a b^p c dr = ar.multiply(Power.>>> positivePower(br, p)).multiply(cr); //System.out.println("dr = " + dr); SortedMap>>, Long> sfactors; sfactors = sqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree with char-th root. * */ public void testSquarefreeCharRoot() { //System.out.println("\nfull CharRoot:"); long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing>(fac, rl, to, vars); a = dfac.random(kl, ll, 3, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, ll, 3, q); if (a.isZERO() || b.isZERO() || c.isZERO() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.>> positivePower(b, p)).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.squarefreePart(c); d = sqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); e = PolyUtil.> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test squarefree factors with char-th root. * */ public void testSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing>(fac, rl, to, vars); a = dfac.random(kl, ll, 3, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, ll, 3, q); if (a.isZERO() || b.isZERO() || c.isZERO() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.>> positivePower(b, p)).multiply(c); //System.out.println("d = " + d); SortedMap>, Long> sfactors; sfactors = sqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } } jas-2.5/trc/edu/jas/ufd/SquarefreeModTest.java0000644000175000017500000004240411641660762021525 0ustar giovannigiovanni/* * $Id: SquarefreeModTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.structure.Power; /** * Squarefree factorization tests with JUnit. * @author Heinz Kredel. */ public class SquarefreeModTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a SquarefreeModTest object. * @param name String. */ public SquarefreeModTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(SquarefreeModTest.class); return suite; } TermOrder to = new TermOrder(TermOrder.INVLEX); int rl = 3; int kl = 3; int ll = 4; int el = 3; float q = 0.25f; String[] vars; String[] cvars; String[] c1vars; String[] rvars; ModIntegerRing fac; GreatestCommonDivisorAbstract ufd; SquarefreeFiniteFieldCharP sqf; GenPolynomialRing dfac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomialRing cfac; GenPolynomialRing> rfac; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; @Override protected void setUp() { vars = ExpVector.STDVARS(rl); cvars = ExpVector.STDVARS(rl - 1); c1vars = new String[] { cvars[0] }; rvars = new String[] { vars[rl - 1] }; fac = new ModIntegerRing(11); //ufd = new GreatestCommonDivisorSubres(); //ufd = GCDFactory. getImplementation(fac); ufd = GCDFactory.getProxy(fac); sqf = new SquarefreeFiniteFieldCharP(fac); a = b = c = d = e = null; ar = br = cr = dr = er = null; } @Override protected void tearDown() { a = b = c = d = e = null; ar = br = cr = dr = er = null; //ComputerThreads.terminate(); } /** * Test base squarefree. * */ public void testBaseSquarefree() { //System.out.println("\nbase:"); dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll, el + 2, q); b = dfac.random(kl, ll, el + 2, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbbc) " + e, e.isZERO()); } /** * Test base squarefree factors. * */ public void testBaseSquarefreeFactors() { dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll, el + 3, q); b = dfac.random(kl, ll, el + 3, q); c = dfac.random(kl, ll, el + 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree. * */ public void testRecursiveSquarefree() { //System.out.println("\nrecursive:"); cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, ll, el, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(ar).multiply(br).multiply(br); cr = ar.multiply(br); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); cr = sqf.recursiveUnivariateSquarefreePart(cr); dr = sqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); assertTrue("isSquarefree(cr) " + cr, sqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, sqf.isRecursiveSquarefree(dr)); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors. * */ public void testRecursiveSquarefreeFactors() { cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, 3, 2, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(cr).multiply(br).multiply(br); //System.out.println("dr = " + dr); SortedMap>, Long> sfactors; sfactors = sqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree. * */ public void testSquarefree() { //System.out.println("\nfull:"); dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, ll, 2, q); b = dfac.random(kl, ll, 2, q); c = dfac.random(kl, ll, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.squarefreePart(c); d = sqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbc) " + e, e.isZERO()); } /** * Test squarefree factors. * */ public void testSquarefreeFactors() { dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /* ------------char-th root ------------------------- */ /** * Test base squarefree with char-th root. * */ public void testBaseSquarefreeCharRoot() { //System.out.println("\nbase CharRoot:"); long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll + 2, el + 2, q); b = dfac.random(kl, ll + 2, el + 2, q); c = dfac.random(kl, ll, el, q); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.> positivePower(b, p)).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test base squarefree factors with char-th root. * */ public void testBaseSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll + 2, el + 3, q); b = dfac.random(kl, ll + 2, el + 3, q); c = dfac.random(kl, ll, el + 2, q); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.> positivePower(b, p)).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree with char-th root. * */ public void testRecursiveSquarefreeCharRoot() { //System.out.println("\nrecursive CharRoot:"); long p = fac.characteristic().longValue(); cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, ll, el + 1, q).monic(); br = rfac.random(kl, ll, el + 1, q).monic(); cr = rfac.random(kl, ll, el, q).monic(); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); // a a b^p dr = ar.multiply(ar).multiply(Power.>> positivePower(br, p)); cr = ar.multiply(ar).multiply(br); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); cr = sqf.recursiveUnivariateSquarefreePart(cr); dr = sqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); assertTrue("isSquarefree(cr) " + cr, sqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, sqf.isRecursiveSquarefree(dr)); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors with char-th root. * */ public void testRecursiveSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2 + 1, q).monic(); br = rfac.random(kl, 3, 2 + 1, q).monic(); cr = rfac.random(kl, 3, 2, q).monic(); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); // a a b^p c dr = ar.multiply(ar).multiply(Power.>> positivePower(br, p)).multiply(cr); //System.out.println("dr = " + dr); SortedMap>, Long> sfactors; sfactors = sqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree with char-th root. * */ public void testSquarefreeCharRoot() { //System.out.println("\nfull CharRoot:"); long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, ll, 3, q).monic(); b = dfac.random(kl, ll, 3, q).monic(); c = dfac.random(kl, ll, 3, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.> positivePower(b, p)).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.squarefreePart(c); d = sqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test squarefree factors with char-th root. * */ public void testSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, ll, 3, q).monic(); b = dfac.random(kl, ll, 3, q).monic(); c = dfac.random(kl, ll, 3, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.> positivePower(b, p)).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } } jas-2.5/trc/edu/jas/ufd/PolyUfdUtilTest.java0000644000175000017500000002425412003051126021163 0ustar giovannigiovanni/* * $Id: PolyUfdUtilTest.java 4020 2012-07-22 19:19:51Z kredel $ */ package edu.jas.ufd; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.poly.PolyUtil; /** * PolyUfdUtil tests with JUnit. * @author Heinz Kredel. */ public class PolyUfdUtilTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a PolyUtilTest object. * @param name String. */ public PolyUfdUtilTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(PolyUfdUtilTest.class); return suite; } //private final static int bitlen = 100; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 5; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; dfac = new GenPolynomialRing(new BigInteger(1), rl, to); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; dfac = null; cfac = null; rfac = null; ComputerThreads.terminate(); } protected static java.math.BigInteger getPrime1() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 60; i++) { prime *= 2; } prime -= 93; //prime = 37; //System.out.println("p1 = " + prime); return new java.math.BigInteger("" + prime); } protected static java.math.BigInteger getPrime2() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 30; i++) { prime *= 2; } prime -= 35; //prime = 19; //System.out.println("p1 = " + prime); return new java.math.BigInteger("" + prime); } /** * Test Kronecker substitution. */ public void testKroneckerSubstitution() { for (int i = 0; i < 10; i++) { a = dfac.random(kl, ll * 2, el * 5, q); long d = a.degree() + 1L; //System.out.println("\na = " + a); //System.out.println("deg(a)+1 = " + d); b = PolyUfdUtil. substituteKronecker(a, d); //System.out.println("b = " + b); c = PolyUfdUtil. backSubstituteKronecker(dfac, b, d); //System.out.println("c = " + c); e = a.subtract(c); //System.out.println("e = " + e); assertTrue("back(subst(a)) = a", e.isZERO()); } } /** * Test recursive dense pseudo division. */ public void testRecursivePseudoDivisionDense() { String[] cnames = new String[] { "x" }; String[] mnames = new String[] { "t" }; dfac = new GenPolynomialRing(new BigInteger(1),to,cnames); //GenPolynomialRing rdfac = new GenPolynomialRing(new BigRational(1),dfac); rfac = new GenPolynomialRing>(dfac, to, mnames); QuotientRing qfac = new QuotientRing(dfac); GenPolynomialRing> rqfac = new GenPolynomialRing>(qfac,rfac); //System.out.println("\ndfac = " + dfac); //System.out.println("rdfac = " + rdfac); //System.out.println("rfac = " + rfac); //System.out.println("qfac = " + qfac); //System.out.println("rqfac = " + rqfac); ar = rfac.random(kl, 2*ll, el+4, q); //ar = rfac.parse(" ( -2 x^4 + 8 x^3 - 5 x^2 - x + 6 ) t^3 + ( 2 x - 8 ) t^2 - ( 13 x^4 - 13 x^3 + x^2 + 2 x - 13 ) "); br = rfac.random(kl, 2*ll, el+2, q); //ar = ar.multiply(br); //br = rfac.parse(" ( 13 ) t^3 + ( 3 x^2 - 6 ) t - ( 13 x^4 - 8 x^3 + 10 x^2 + 22 x + 21 ) "); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = PolyUtil. recursivePseudoDivide(ar, br); //System.out.println("qr = " + dr); cr = PolyUtil. recursiveDensePseudoRemainder(ar, br); //System.out.println("rr = " + cr); //boolean t = PolyUtil. isRecursivePseudoQuotientRemainder(ar, br, dr, cr); //System.out.println("assertTrue lc^n a = q b + r: " + t); //assertTrue("lc^n a = q b + r: " + cr, t); // ?? not always true GenPolynomial> ap = PolyUfdUtil. quotientFromIntegralCoefficients(rqfac,ar); GenPolynomial> bp = PolyUfdUtil. quotientFromIntegralCoefficients(rqfac,br); GenPolynomial> cp = PolyUfdUtil. quotientFromIntegralCoefficients(rqfac,cr); GenPolynomial> dp = PolyUfdUtil. quotientFromIntegralCoefficients(rqfac,dr); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); ////System.out.println("dp = " + dp); //System.out.println("dp = " + dp.monic()); GenPolynomial> qp = ap.divide(bp); GenPolynomial> rp = ap.remainder(bp); ////System.out.println("qp = " + qp); //System.out.println("qp = " + qp.monic()); //System.out.println("rp = " + rp); GenPolynomial> rhs = qp.multiply(bp).sum(rp); //System.out.println("qp bp + rp = " + rhs); assertEquals("ap = qp bp + rp: ", ap, rhs); assertEquals("cp = rp: ", rp.monic(), cp.monic() ); //System.out.println("dp = qp: " + qp.monic().equals(dp.monic()) ); assertEquals("dp = qp: ", qp.monic(), dp.monic() ); // ?? } /** * Test recursive sparse pseudo division. */ public void testRecursivePseudoDivisionSparse() { String[] cnames = new String[] { "x" }; String[] mnames = new String[] { "t" }; dfac = new GenPolynomialRing(new BigInteger(1),to,cnames); //GenPolynomialRing rdfac = new GenPolynomialRing(new BigRational(1),dfac); rfac = new GenPolynomialRing>(dfac, to, mnames); QuotientRing qfac = new QuotientRing(dfac); GenPolynomialRing> rqfac = new GenPolynomialRing>(qfac,rfac); //System.out.println("\ndfac = " + dfac); //System.out.println("rdfac = " + rdfac); //System.out.println("rfac = " + rfac); //System.out.println("qfac = " + qfac); //System.out.println("rqfac = " + rqfac); ar = rfac.random(kl, 2*ll, el+4, q); //ar = rfac.parse(" ( -2 x^4 + 8 x^3 - 5 x^2 - x + 6 ) t^3 + ( 2 x - 8 ) t^2 - ( 13 x^4 - 13 x^3 + x^2 + 2 x - 13 ) "); br = rfac.random(kl, 2*ll, el+2, q); //ar = ar.multiply(br); //br = rfac.parse(" ( 13 ) t^3 + ( 3 x^2 - 6 ) t - ( 13 x^4 - 8 x^3 + 10 x^2 + 22 x + 21 ) "); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = PolyUtil. recursivePseudoDivide(ar, br); //System.out.println("qr = " + dr); cr = PolyUtil. recursiveSparsePseudoRemainder(ar, br); //System.out.println("rr = " + cr); //boolean t = PolyUtil. isRecursivePseudoQuotientRemainder(ar, br, dr, cr); //System.out.println("assertTrue lc^n a = q b + r: " + t); //assertTrue("lc^n a = q b + r: " + cr, t); // ?? not always true GenPolynomial> ap = PolyUfdUtil. quotientFromIntegralCoefficients(rqfac,ar); GenPolynomial> bp = PolyUfdUtil. quotientFromIntegralCoefficients(rqfac,br); GenPolynomial> cp = PolyUfdUtil. quotientFromIntegralCoefficients(rqfac,cr); GenPolynomial> dp = PolyUfdUtil. quotientFromIntegralCoefficients(rqfac,dr); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); ////System.out.println("dp = " + dp); //System.out.println("dp = " + dp.monic()); GenPolynomial> qp = ap.divide(bp); GenPolynomial> rp = ap.remainder(bp); ////System.out.println("qp = " + qp); //System.out.println("qp = " + qp.monic()); //System.out.println("rp = " + rp); GenPolynomial> rhs = qp.multiply(bp).sum(rp); //System.out.println("qp bp + rp = " + rhs); assertEquals("ap = qp bp + rp: ", ap, rhs); assertEquals("cp = rp: ", rp.monic(), cp.monic() ); //System.out.println("dp = qp: " + qp.monic().equals(dp.monic()) ); assertEquals("dp = qp: ", qp.monic(), dp.monic() ); // ?? } } jas-2.5/trc/edu/jas/ufd/SquarefreeIntTest.java0000644000175000017500000002323211641660762021536 0ustar giovannigiovanni/* * $Id: SquarefreeIntTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.kern.ComputerThreads; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * Squarefree factorization tests with JUnit. * @author Heinz Kredel. */ public class SquarefreeIntTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a SquarefreeIntTest object. * @param name String. */ public SquarefreeIntTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(SquarefreeIntTest.class); return suite; } TermOrder to = new TermOrder(TermOrder.INVLEX); int rl = 3; int kl = 7; int ll = 4; int el = 3; float q = 0.25f; String[] vars; String[] cvars; String[] c1vars; String[] rvars; BigInteger fac; GreatestCommonDivisorAbstract ufd; SquarefreeRingChar0 sqf; GenPolynomialRing dfac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomialRing cfac; GenPolynomialRing> rfac; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; @Override protected void setUp() { vars = ExpVector.STDVARS(rl); cvars = ExpVector.STDVARS(rl - 1); c1vars = new String[] { cvars[0] }; rvars = new String[] { vars[rl - 1] }; fac = new BigInteger(1); //ufd = new GreatestCommonDivisorSubres(); //ufd = GCDFactory. getImplementation(fac); ufd = GCDFactory.getProxy(fac); sqf = new SquarefreeRingChar0(fac); SquarefreeAbstract sqff = SquarefreeFactory.getImplementation(fac); //System.out.println("sqf = " + sqf); //System.out.println("sqff = " + sqff); assertEquals("sqf == sqff ", sqf.getClass(), sqff.getClass()); a = b = c = d = e = null; ar = br = cr = dr = er = null; } @Override protected void tearDown() { a = b = c = d = e = null; ar = br = cr = dr = er = null; //ComputerThreads.terminate(); } /** * Test base squarefree. * */ public void testBaseSquarefree() { //System.out.println("\nbase:"); dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll, el + 2, q); b = dfac.random(kl, ll, el + 2, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("d = " + d); //System.out.println("c = " + c); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbbc) " + e, e.isZERO()); } /** * Test base squarefree factors. * */ public void testBaseSquarefreeFactors() { dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll, el + 3, q); b = dfac.random(kl, ll, el + 3, q); c = dfac.random(kl, ll, el + 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree. * */ public void testRecursiveSquarefree() { //System.out.println("\nrecursive:"); cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, ll, el, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(ar).multiply(br).multiply(br); cr = ar.multiply(br); //System.out.println("dr = " + dr); //System.out.println("cr = " + cr); cr = sqf.recursiveUnivariateSquarefreePart(cr); dr = sqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("dr = " + dr); //System.out.println("cr = " + cr); assertTrue("isSquarefree(cr) " + cr, sqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, sqf.isRecursiveSquarefree(dr)); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors. * */ public void testRecursiveSquarefreeFactors() { cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, 3, 2, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(cr).multiply(br).multiply(br); //System.out.println("dr = " + dr); SortedMap>, Long> sfactors; sfactors = sqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree. * */ public void testSquarefree() { //System.out.println("\nfull:"); dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, ll, 2, q); b = dfac.random(kl, ll, 2, q); c = dfac.random(kl, ll, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); c = sqf.squarefreePart(c); d = sqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbc) " + e, e.isZERO()); } /** * Test squarefree factors. * */ public void testSquarefreeFactors() { dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } } jas-2.5/trc/edu/jas/ufd/FactorMoreTest.java0000644000175000017500000002670011715532102021011 0ustar giovannigiovanni/* * $Id: FactorMoreTest.java 3888 2012-02-11 18:32:34Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import org.apache.log4j.BasicConfigurator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Factor tests with JUnit. * @author Heinz Kredel. */ public class FactorMoreTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorTest object. * @param name String. */ public FactorMoreTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorMoreTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. * */ public void testDummy() { } /** * Test integral function factorization. */ public void testIntegralFunctionFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] qvars = new String[] { "t" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, qvars); GenPolynomial t = pfac.univariate(0); FactorAbstract fac = new FactorRational(); String[] vars = new String[] { "x" }; GenPolynomialRing> pqfac = new GenPolynomialRing>( pfac, 1, to, vars); GenPolynomial> x = pqfac.univariate(0); GenPolynomial> x2 = pqfac.univariate(0, 2); for (int i = 1; i < 3; i++) { int facs = 0; GenPolynomial> a; GenPolynomial> b = pqfac.random(2, 3, el, q); //b = b.monic(); //b = b.multiply(b); GenPolynomial> c = pqfac.random(2, 3, el, q); //c = c.monic(); if (c.degree() < 1) { c = x2.subtract(pqfac.getONE().multiply(t)); } if (b.degree() < 1) { b = x.sum(pqfac.getONE()); } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap>, Long> sm = fac.recursiveFactors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs, sf >= facs); } boolean tt = fac.isRecursiveFactorization(a, sm); //System.out.println("t = " + tt); assertTrue("prod(factor(a)) = a", tt); } ComputerThreads.terminate(); } /** * Test integer integral function factorization. */ public void testIntegerIntegralFunctionFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigInteger cfac = new BigInteger(1); String[] qvars = new String[] { "t" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, qvars); GenPolynomial t = pfac.univariate(0); FactorAbstract fac = new FactorInteger(); String[] vars = new String[] { "x" }; GenPolynomialRing> pqfac = new GenPolynomialRing>( pfac, 1, to, vars); GenPolynomial> x = pqfac.univariate(0); GenPolynomial> x2 = pqfac.univariate(0, 2); for (int i = 1; i < 3; i++) { int facs = 0; GenPolynomial> a; GenPolynomial> b = pqfac.random(2, 3, el, q); //b = b.monic(); //b = b.multiply(b); GenPolynomial> c = pqfac.random(2, 3, el, q); //c = c.monic(); if (c.degree() < 1) { c = x2.subtract(pqfac.getONE().multiply(t)); } if (b.degree() < 1) { b = x.sum(pqfac.getONE()); } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); //a = pqfac.parse("( ( -26 t - 91 ) x^3 - ( 13 t + 26 ) x^2 + ( 6 t^2 + 21 t ) x + ( 3 t^2 + 6 t ) )"); //a = pqfac.parse("( -3 x^3 + ( t - 1 ) x^2 + ( 3 t ) x - ( t^2 - t ) )"); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap>, Long> sm = fac.recursiveFactors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs + ", sm = " + sm, sf >= facs); } boolean tt = fac.isRecursiveFactorization(a, sm); //System.out.println("t = " + tt); assertTrue("prod(factor(a)) = a", tt); } ComputerThreads.terminate(); } /** * Test rational function factorization. */ public void testRationalFunctionFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] qvars = new String[] { "t" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, qvars); QuotientRing qfac = new QuotientRing(pfac); Quotient t = qfac.generators().get(1); FactorQuotient fac = new FactorQuotient(qfac); String[] vars = new String[] { "x" }; GenPolynomialRing> pqfac = new GenPolynomialRing>(qfac, 1, to, vars); GenPolynomial> x = pqfac.univariate(0); GenPolynomial> x2 = pqfac.univariate(0, 2); for (int i = 1; i < 3; i++) { int facs = 0; GenPolynomial> a; GenPolynomial> b = pqfac.random(2, 3, el, q); //b = b.monic(); //b = b.multiply(b); GenPolynomial> c = pqfac.random(2, 3, el, q); //c = c.monic(); if (c.degree() < 1) { c = x2.subtract(pqfac.getONE().multiply(t)); } if (b.degree() < 1) { b = x.sum(pqfac.getONE()); } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap>, Long> sm = fac.factors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs, sf >= facs); } boolean tt = fac.isFactorization(a, sm); //System.out.println("t = " + tt); assertTrue("prod(factor(a)) = a", tt); } ComputerThreads.terminate(); } /** * Test modular rational function factorization. */ public void testModularRationalFunctionFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); ModIntegerRing cfac = new ModIntegerRing(19, true); String[] qvars = new String[] { "t" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, qvars); QuotientRing qfac = new QuotientRing(pfac); Quotient t = qfac.generators().get(1); FactorQuotient fac = new FactorQuotient(qfac); String[] vars = new String[] { "x" }; GenPolynomialRing> pqfac = new GenPolynomialRing>(qfac, 1, to, vars); GenPolynomial> x = pqfac.univariate(0); GenPolynomial> x2 = pqfac.univariate(0, 2); for (int i = 1; i < 3; i++) { int facs = 0; GenPolynomial> a; GenPolynomial> b = pqfac.random(2, 3, el, q); //b = b.monic(); //b = b.multiply(b); GenPolynomial> c = pqfac.random(2, 3, el, q); //c = c.monic(); if (c.degree() < 1) { c = x2.subtract(pqfac.getONE().multiply(t)); } if (b.degree() < 1) { b = x.sum(pqfac.getONE()); } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap>, Long> sm = fac.factors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs, sf >= facs); } boolean tt = fac.isFactorization(a, sm); //System.out.println("t = " + tt); assertTrue("prod(factor(a)) = a", tt); } ComputerThreads.terminate(); } } jas-2.5/trc/edu/jas/ufd/GCDModLongEvalTest.java0000644000175000017500000005147211641660762021455 0ustar giovannigiovanni/* * $Id: GCDModLongEvalTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.arith.PrimeList; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GCD Modular Evaluation algorithm tests with JUnit. * @author Heinz Kredel. */ public class GCDModLongEvalTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDModLongEvalTest object. * @param name String. */ public GCDModLongEvalTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDModLongEvalTest.class); return suite; } //private final static int bitlen = 100; GreatestCommonDivisorAbstract ufd; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; PrimeList primes = new PrimeList(); ModLongRing mi; ModLong ai; ModLong bi; ModLong ci; ModLong di; ModLong ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 3; int kl = 4; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; //mi = new ModLongRing(primes.get(0),true); mi = new ModLongRing(19, true); //mi = new ModLongRing(19*17,true); // failing tests //mi = new ModLongRing(primes.get(0).multiply(primes.get(1)),false); // failing tests //ufd = new GreatestCommonDivisorPrimitive(); ufd = new GreatestCommonDivisorModEval(); String[] vars = ExpVector.STDVARS(rl); String[] cvars = ExpVector.STDVARS(rl - 1); String[] rvars = new String[] { vars[rl - 1] }; dfac = new GenPolynomialRing(mi, rl, to, vars); cfac = new GenPolynomialRing(mi, rl - 1, to, cvars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); //System.out.println("mi = " + mi); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; mi = null; ufd = null; dfac = null; cfac = null; rfac = null; } /** * Test modular evaluation gcd. * */ public void testModEvalGcd() { //GreatestCommonDivisorAbstract ufd_me // = new GreatestCommonDivisorModEval(); for (int i = 0; i < 1; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 0 * i, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 0 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 0 * i, q); c = c.multiply(dfac.univariate(0)); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); c = ufd.basePrimitivePart(c).abs(); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a" + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b" + e, e.isZERO()); } } /** * Test base quotioent and remainder. * */ public void testBaseQR() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a).abs(); //c = ufd.basePrimitivePart(c); do { ci = mi.random(kl * (i + 2)); ci = ci.sum(mi.getONE()); } while (ci.isZERO()); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("ci = " + ci); if (a.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); b = a.multiply(c); //System.out.println("b = " + b); d = PolyUtil. basePseudoRemainder(b, c); //System.out.println("d = " + d); assertTrue("rem(ac,c) == 0", d.isZERO()); b = a.multiply(ci); //System.out.println("b = " + b); d = b.divide(ci); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); b = a.multiply(c); //System.out.println("b = " + b); d = PolyUtil. basePseudoDivide(b, c); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); } } /** * Test base content and primitive part. * */ public void testBaseContentPP() { for (int i = 0; i < 13; i++) { c = dfac.random(kl * (i + 2), ll + 2 * i, el + i, q); c = c.multiply(mi.random(kl * (i + 2))); if (c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ci = ufd.baseContent(c); d = ufd.basePrimitivePart(c); //System.out.println("c = " + c); //System.out.println("ci = " + ci); //System.out.println("d = " + d); a = d.multiply(ci); assertEquals("c == cont(c)pp(c)", c, a); } } /** * Test base gcd. * */ public void testBaseGcd() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); //c = ufd.basePrimitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); d = ufd.baseGcd(a, b); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test recursive quotioent and remainder. * */ public void testRecursiveQR() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl * (i + 1), ll + i, el + i, q); a = ufd.basePrimitivePart(a).abs(); c = dfac.random(kl * (i + 1), ll + i, el + i, q); c = ufd.basePrimitivePart(a).abs(); cr = PolyUtil. recursive(rfac, c); c = cfac.random(kl * (i + 1), ll + 2 * i, el + 2 * i, q); c = ufd.basePrimitivePart(c).abs(); ar = PolyUtil. recursive(rfac, a); //System.out.println("ar = " + ar); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("cr = " + cr); if (cr.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); br = ar.multiply(cr); //System.out.println("br = " + br); dr = PolyUtil. recursivePseudoRemainder(br, cr); //System.out.println("dr = " + dr); d = PolyUtil. distribute(dfac, dr); //System.out.println("d = " + d); assertTrue("rem(ac,c) == 0", d.isZERO()); br = ar.multiply(c); //System.out.println("br = " + br); dr = PolyUtil. recursiveDivide(br, c); //System.out.println("dr = " + dr); d = PolyUtil. distribute(dfac, dr); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); } } /** * Test recursive content and primitive part. * */ public void testRecursiveContentPP() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 3; i++) { cr = rfac.random(kl * (i + 2), ll + 2 * i, el + i, q); //System.out.println("cr = " + cr); assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); c = ufd.recursiveContent(cr); dr = ufd.recursivePrimitivePart(cr); //System.out.println("c = " + c); //System.out.println("dr = " + dr); ar = dr.multiply(c); assertEquals("c == cont(c)pp(c)", cr, ar); } } /** * Test recursive gcd. * */ public void testRecursiveGCD() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 2; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveUnivariateGcd(ar, br); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test arbitrary recursive gcd. * */ public void testArbitraryRecursiveGCD() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 2; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveGcd(ar, br); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test content and primitive part. * */ public void testContentPP() { dfac = new GenPolynomialRing(mi, 3, to); for (int i = 0; i < 3; i++) { c = dfac.random(kl * (i + 2), ll + 2 * i, el + i, q); //System.out.println("cr = " + cr); if (c.isZERO()) { continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = ufd.content(c); e = a.extend(dfac, 0, 0L); b = ufd.primitivePart(c); //System.out.println("c = " + c); //System.out.println("a = " + a); //System.out.println("e = " + e); //System.out.println("b = " + b); d = e.multiply(b); assertEquals("c == cont(c)pp(c)", d, c); } } /** * Test gcd 3 variables. * */ public void testGCD3() { dfac = new GenPolynomialRing(mi, 3, to); for (int i = 0; i < 4; i++) { a = dfac.random(kl, ll, el + i, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test gcd. * */ public void testGCD() { // dfac = new GenPolynomialRing(mi,3,to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b " + e, e.isZERO()); } } /** * Test lcm. * */ public void testLCM() { dfac = new GenPolynomialRing(mi, 3, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( a" + i + " ) <> 0", a.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); c = ufd.gcd(a, b); //System.out.println("c = " + c); d = ufd.lcm(a, b); //System.out.println("d = " + d); e = c.multiply(d); //System.out.println("e = " + e); c = a.multiply(b); //System.out.println("c = " + c); assertEquals("ab == gcd(a,b)lcm(ab)", c, e); } } /** * Test co-prime factors. * */ public void testCoPrime() { dfac = new GenPolynomialRing(mi, 3, to); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } assertTrue("length( a ) <> 0", a.length() > 0); d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); e = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); List> F = new ArrayList>(5); F.add(d); F.add(a); F.add(b); F.add(c); F.add(e); List> P = ufd.coPrime(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); //P = ufd.coPrimeSquarefree(F); //System.out.println("F = " + F); //System.out.println("P = " + P); //assertTrue("is co-prime ", ufd.isCoPrime(P) ); //assertTrue("is co-prime of ", ufd.isCoPrime(P,F) ); P = ufd.coPrimeRec(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); } } jas-2.5/trc/edu/jas/ufd/FactorQuotientTest.java0000644000175000017500000000541612002611634021716 0ustar giovannigiovanni/* * $Id: FactorQuotientTest.java 4010 2012-07-21 20:39:56Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Factor quotient tests with JUnit. * @author Heinz Kredel. */ public class FactorQuotientTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorQuotientTest object. * @param name String. */ public FactorQuotientTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorQuotientTest.class); return suite; } int rl = 1; int kl = 3; int ll = 3; int el = 3; float q = 0.4f; QuotientRing efac; GenPolynomialRing mfac; @Override protected void setUp() { BigRational cfac = new BigRational(1); TermOrder to = new TermOrder(TermOrder.INVLEX); mfac = new GenPolynomialRing(cfac, rl, to); efac = new QuotientRing(mfac); } @Override protected void tearDown() { //efac.terminate(); efac = null; ComputerThreads.terminate(); } /** * Test dummy for Junit. * */ public void xtestDummy() { } /** * Test quotient coefficient polynomial factorization. * */ public void testQuotientFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); //BigRational cfac = new BigRational(1); String[] var_x = new String[] { "x" }; GenPolynomialRing> pfac = new GenPolynomialRing>(efac, 1, to, var_x); //System.out.println("pfac = " + pfac.toScript()); GenPolynomial> a = pfac.random(kl, ll, el, q); // will be irreducible most times //System.out.println("a = " + a); FactorAbstract> engine = FactorFactory.getImplementation(efac); //System.out.println("engine = " + engine); SortedMap>, Long> sm = engine.factors(a); //System.out.println("factors(a) = " + sm); assertTrue("#facs >= 1", sm.size() >= 1); boolean t = engine.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } jas-2.5/trc/edu/jas/ufd/FactorModularTest.java0000644000175000017500000002237012003043360021503 0ustar giovannigiovanni/* * $Id: FactorModularTest.java 4019 2012-07-22 18:31:13Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.PrimeList; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Factor modular tests with JUnit. * @author Heinz Kredel. */ public class FactorModularTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorModularTest object. * @param name String. */ public FactorModularTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorModularTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. * */ public void testDummy() { } /** * Test modular factorization. * */ public void testModularFactorization() { PrimeList pl = new PrimeList(PrimeList.Range.medium); TermOrder to = new TermOrder(TermOrder.INVLEX); ModIntegerRing cfac = new ModIntegerRing(pl.get(3)); //System.out.println("cfac = " + cfac); GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to); FactorModular fac = new FactorModular(cfac); for (int i = 1; i < 4; i++) { int facs = 0; GenPolynomial a = null; //pfac.random(kl,ll*(i+1),el*(i+1),q); GenPolynomial b = pfac.random(kl, ll * (i + 1), el * (i + 1), q); GenPolynomial c = pfac.random(kl, ll * (i + 1), el * (i + 1), q); if (b.isZERO() || c.isZERO()) { continue; } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); if (a.isConstant()) { continue; } a = a.monic(); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap, Long> sm = fac.baseFactors(a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs, sf >= facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } /** * Test modular factorization example. * */ public void testModularFactorizationExam() { TermOrder to = new TermOrder(TermOrder.INVLEX); ModIntegerRing cfac = new ModIntegerRing(7); //System.out.println("cfac = " + cfac); String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); FactorModular fac = new FactorModular(cfac); int facs = 3; GenPolynomial a = pfac.parse("(x^12+5)"); a = a.monic(); //System.out.println("\na = " + a); SortedMap, Long> sm = fac.baseFactors(a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs, sf >= facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } /** * Test modular factorization, case p = 2. * */ public void testModular2Factorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); ModIntegerRing cfac = new ModIntegerRing(2L); //System.out.println("cfac = " + cfac); GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to); FactorModular fac = new FactorModular(cfac); for (int i = 1; i < 4; i++) { int facs = 0; GenPolynomial a = null; //pfac.random(kl,ll*(i+1),el*(i+1),q); GenPolynomial b = pfac.random(kl, ll * (i + 1), el * (i + 1), q); GenPolynomial c = pfac.random(kl, ll * (i + 1), el * (i + 1), q); if (b.isZERO() || c.isZERO()) { continue; } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); if (a.isConstant()) { continue; } a = a.monic(); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap, Long> sm = fac.baseFactors(a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs, sf >= facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } /** * Test multivariate modular factorization. * */ public void testMultivariateModularFactorization() { //PrimeList pl = new PrimeList(PrimeList.Range.small); TermOrder to = new TermOrder(TermOrder.INVLEX); ModIntegerRing cfac = new ModIntegerRing(13); // pl.get(3), 7, 11, 13 GenPolynomialRing pfac = new GenPolynomialRing(cfac, rl, to); FactorModular fac = new FactorModular(cfac); for (int i = 1; i < 2; i++) { int facs = 0; GenPolynomial a = null; //pfac.random(kl,ll*(i+1),el,q); GenPolynomial b = pfac.random(kl, 2, el, q); GenPolynomial c = pfac.random(kl, 2, el, q); if (b.isZERO() || c.isZERO()) { continue; } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); if (a.isConstant()) { continue; } //a = a.monic(); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap, Long> sm = fac.factors(a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs, sf >= facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } /** * Test modular absolute factorization. * */ public void testBaseModularAbsoluteFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); ModIntegerRing cfac = new ModIntegerRing(17); String[] alpha = new String[] { "alpha" }; //String[] vars = new String[] { "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, alpha); GenPolynomial agen = pfac.univariate(0, 4); agen = agen.sum(pfac.fromInteger(1)); // x^4 + 1 FactorModular engine = new FactorModular(cfac); FactorsMap F //= engine.baseFactorsAbsoluteSquarefree(agen); //= engine.baseFactorsAbsoluteIrreducible(agen); = engine.baseFactorsAbsolute(agen); //System.out.println("agen = " + agen); //System.out.println("F = " + F); boolean t = engine.isAbsoluteFactorization(F); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } jas-2.5/trc/edu/jas/ufd/FactorGenericTest.java0000644000175000017500000001050611641660762021474 0ustar giovannigiovanni/* * $Id: FactorGenericTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Factor rational tests with JUnit. * @author Heinz Kredel. */ public class FactorGenericTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorGenericTest object. * @param name String. */ public FactorGenericTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorGenericTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. * */ public void xtestDummy() { } /** * Test generic factorization. * */ public void testGenericFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] var_w2 = new String[] { "w2" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, var_w2); //System.out.println("pfac = " + pfac.toScript()); GenPolynomial w2 = pfac.parse(" w2^2 - 2 "); //System.out.println("w2 = " + w2); AlgebraicNumberRing a2fac = new AlgebraicNumberRing(w2, true); //System.out.println("a2fac = " + a2fac.toScript()); String[] var_x = new String[] { "x" }; GenPolynomialRing> apfac = new GenPolynomialRing>( a2fac, 1, to, var_x); //System.out.println("apfac = " + apfac.toScript()); QuotientRing> qfac = new QuotientRing>( apfac); //System.out.println("qfac = " + qfac.toScript()); String[] var_wx = new String[] { "wx" }; GenPolynomialRing>> pqfac = new GenPolynomialRing>>( qfac, 1, to, var_wx); //System.out.println("pqfac = " + pqfac.toScript()); GenPolynomial>> wx = pqfac.parse(" wx^2 - { x } "); //System.out.println("wx = " + wx); AlgebraicNumberRing>> axfac = new AlgebraicNumberRing>>( wx, true); //System.out.println("axfac = " + axfac.toScript()); String[] var_y = new String[] { "y" }; GenPolynomialRing>>> apqfac = new GenPolynomialRing>>>( axfac, 1, to, var_y); //System.out.println("apqfac = " + apqfac.toScript()); // ( y^2 - x ) * ( y^2 - 2 ), need {} for recursive coefficients GenPolynomial>>> f; f = apqfac.parse(" ( y^2 - { { x } } ) * ( y^2 - 2 )^2 "); //System.out.println("f = " + f); FactorAbstract>>> engine = FactorFactory .getImplementation(axfac); //System.out.println("engine = " + engine); SortedMap>>>, Long> F = engine .factors(f); //System.out.println("factors(f) = " + F); assertTrue("#facs >= 4", F.size() >= 4); boolean t = engine.isFactorization(f, F); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } jas-2.5/trc/edu/jas/ufd/FactorComplexTest.java0000644000175000017500000001602611641660762021532 0ustar giovannigiovanni/* * $Id: FactorComplexTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Factor complex via algebraic tests with JUnit. * @author Heinz Kredel. */ public class FactorComplexTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorComplexTest object. * @param name String. */ public FactorComplexTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorComplexTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. * */ public void testDummy() { } /** * Test complex via algebraic factorization. * */ public void testComplexFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational rfac = new BigRational(1); ComplexRing cfac = new ComplexRing(rfac); GenPolynomialRing> cpfac = new GenPolynomialRing>(cfac, 1, to); //System.out.println("cfac = " + cfac); //System.out.println("cpfac = " + cpfac); FactorComplex fac = new FactorComplex(cfac); for (int i = 1; i < 3; i++) { int facs = 0; GenPolynomial> a; GenPolynomial> c = cpfac.random(2, ll + i, el + i, q); //a = a.monic(); GenPolynomial> b = cpfac.random(2, ll + i, el + i, q); if (b.degree() == 0) { b = b.multiply(cpfac.univariate(0)); } if (c.degree() > 0) { facs++; } b = b.multiply(b); if (b.degree() > 0) { facs++; } a = c.multiply(b); //a = a.monic(); //System.out.println("\na = " + a); //System.out.println("b = " + b.monic()); //System.out.println("c = " + c.monic()); SortedMap>, Long> sm = fac.baseFactors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { System.out.println("sm.size() < facs = " + facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } /** * Test complex absolute via algebraic factorization. * */ public void testComplexAbsoluteFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational rfac = new BigRational(1); ComplexRing cfac = new ComplexRing(rfac); GenPolynomialRing> cpfac = new GenPolynomialRing>(cfac, 1, to); //System.out.println("cfac = " + cfac); //System.out.println("cpfac = " + cpfac); FactorComplex fac = new FactorComplex(cfac); for (int i = 1; i < 2; i++) { int facs = 0; GenPolynomial> a; GenPolynomial> c = cpfac.random(2, ll, el, q); //a = a.monic(); GenPolynomial> b = cpfac.random(2, ll, el, q); if (b.degree() == 0) { b = b.multiply(cpfac.univariate(0)); } if (c.degree() > 0) { facs++; } b = b.multiply(b); if (b.degree() > 0) { facs++; } a = c.multiply(b); //a = a.monic(); //System.out.println("\na = " + a); //System.out.println("b = " + b.monic()); //System.out.println("c = " + c.monic()); FactorsMap> sm = fac.baseFactorsAbsolute(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); boolean t = fac.isAbsoluteFactorization(sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } /** * Test bivariate complex via algebraic factorization. * */ public void testBivariateComplexFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational rfac = new BigRational(1); ComplexRing cfac = new ComplexRing(rfac); GenPolynomialRing> cpfac = new GenPolynomialRing>(cfac, 2, to); //System.out.println("cfac = " + cfac); //System.out.println("cpfac = " + cpfac); FactorComplex fac = new FactorComplex(cfac); for (int i = 1; i < 2; i++) { int facs = 0; GenPolynomial> a; GenPolynomial> c = cpfac.random(2, ll + i, el, q); //a = a.monic(); GenPolynomial> b = cpfac.random(2, ll + i, el, q); if (b.degree() == 0) { b = b.multiply(cpfac.univariate(0)); } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); //a = a.monic(); //System.out.println("\na = " + a); //System.out.println("b = " + b.monic()); //System.out.println("c = " + c.monic()); SortedMap>, Long> sm = fac.factors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { System.out.println("sm.size() < facs = " + facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } } jas-2.5/trc/edu/jas/ufd/GCDHenselTest.java0000644000175000017500000002425412136515560020515 0ustar giovannigiovanni/* * $Id: GCDHenselTest.java 4377 2013-04-26 15:21:21Z kredel $ */ package edu.jas.ufd; //import java.util.Map; import org.apache.log4j.BasicConfigurator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.ModInteger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GCD Hensel algorithm tests with JUnit. * @author Heinz Kredel. */ public class GCDHenselTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDHenselTest object. * @param name String. */ public GCDHenselTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDHenselTest.class); return suite; } GreatestCommonDivisorAbstract ufd; GreatestCommonDivisorAbstract ufd1; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; BigInteger cofac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial ac; GenPolynomial bc; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; GenPolynomial> arc; GenPolynomial> brc; int rl = 3; String [] vars = { "x", "y", "z" }; int kl = 4; int ll = 5; int el = 4; //3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; cofac = new BigInteger(); ufd = new GreatestCommonDivisorHensel(); dfac = new GenPolynomialRing(cofac, rl, to, vars); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd = null; dfac = null; } /** * Test Hensel algorithm gcd. */ public void testHenselGcd() { //GenPolynomialRing dfac = new GenPolynomialRing(cofac, rl, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll + i, el + i, q); b = dfac.random(kl, ll + i, el + i, q); c = dfac.random(kl, ll + i, el + i, q); c = c.multiply(dfac.univariate(0)); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); ExpVector ev = c.leadingExpVector(); if ( ev != null ) { c.doPutToMap(ev,dfac.coFac.getONE()); } if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); a = a.multiply(c); //.multiply(c); b = b.multiply(c); //System.out.println("a c = " + a); //System.out.println("b c = " + b); d = ufd.gcd(a, b); //d = ufd.baseGcd(a,b); c = ufd.basePrimitivePart(c).abs(); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc): " + d + ", c = " + c, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a: " + e + ", d = " + d, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b: " + e + ", d = " + d, e.isZERO()); } } /** * Test linear Hensel algorithm gcd. */ public void ytestHenselLinearSubresGcd() { ufd1 = new GreatestCommonDivisorHensel(false); //GenPolynomialRing dfac = new GenPolynomialRing(cofac, rl, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll + i, el + i, q); b = dfac.random(kl, ll + i, el + i, q); c = dfac.random(kl, ll + i, el + i, q); c = c.multiply(dfac.univariate(0)); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); ExpVector ev = c.leadingExpVector(); if ( ev != null ) { c.doPutToMap(ev,dfac.coFac.getONE()); } if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); a = a.multiply(c); //.multiply(c); b = b.multiply(c); //System.out.println("a c = " + a); //System.out.println("b c = " + b); long t = System.currentTimeMillis(); d = ufd1.gcd(a, b); t = System.currentTimeMillis() - t; //d = ufd.baseGcd(a,b); long tq = System.currentTimeMillis(); e = ufd.gcd(a,b); tq = System.currentTimeMillis() - tq; //System.out.println("Hensel quadratic, time = " + tq); //System.out.println("Hensel linear, time = " + t); c = ufd.basePrimitivePart(c).abs(); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc): " + d + ", c = " + c, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a: " + e + ", d = " + d, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b: " + e + ", d = " + d, e.isZERO()); } } /** * Test Hensel gcd 3 variables. */ public void testHenselGCD3() { BigInteger ifa = new BigInteger(1); //dfac = new GenPolynomialRing(ifa, 2, to , new String[] {"x", "y" }); dfac = new GenPolynomialRing(ifa, 3, to , new String[] { "x" , "y", "z" }); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el + i, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); // make monic and c with univariate head term ExpVector ev = a.leadingExpVector(); if ( ev != null ) { a.doPutToMap(ev,ifa.getONE()); } ev = b.leadingExpVector(); if ( ev != null ) { b.doPutToMap(ev,ifa.getONE()); } ev = c.leadingExpVector(); if ( ev != null ) { //c.doPutToMap(ev,ifa.getONE()); } assertFalse("ev == null ", ev == null); if ( ev.dependencyOnVariables().length > 1 ) { c = dfac.univariate(1); //getONE(); } //a = dfac.parse(" y^2 + 2 x y - 3 y + x^2 - 3 x - 4 "); //b = dfac.parse(" y^2 + 2 x y + 5 y + x^2 + 5 x + 4 "); //a = dfac.parse(" x + 2 y + z^2 + 5 "); //b = dfac.parse(" x - y - 3 + y z "); //c = dfac.parse(" x y + z^2 + y "); //a = dfac.parse("7 y^4 - (35 x^3 - 32) y^3 - 160 x^3 y^2 + (105 x^2 - 119) y + (480 x^2 - 544) "); //b = dfac.parse(" 7 y^4 + 39 y^3 + 32 y^2 "); //c = dfac.parse(" 7 y + 32 "); //a = dfac.parse(" ( -13 x^2 ) z^5 + ( 182 x^2 - 143 ) z^3 - ( x^2 * y^3 - 8 x^2 ) z^2 + ( 14 x^2 * y^3 - 11 y^3 - 112 x^2 + 88 ) "); //b = dfac.parse(" ( -13 x^3 * y^3 ) z^6 + ( 65 y ) z^4 - ( x^3 * y^6 - 8 x^3 * y^3 - 52 y^3 - 195 y + 156 ) z^3 + ( 5 y^4 - 40 y ) z + ( 4 y^6 + 15 y^4 - 44 y^3 - 120 y + 96 ) ) "); //c = dfac.parse(" 13 z^3 + y^3 - 8 "); //a = dfac.parse(" 3 z^3 + ( 4 y^2 + 25 x^3 + 16 x^2 + 25 ) z^2 - ( 84 y^4 - 22 x^3 * y^2 + 128 x^2 * y^2 + 138 y^2 - 52 x^6 - 71 x^5 + 35 x^4 - 109 x^3 + 59 x^2 + 18 ) z "); //b = dfac.parse(" 10 z^5 + ( 60 y^2 + 40 x^3 + 70 x^2 + 90 ) z^4 + ( 14 x + 3 ) z^2 + ( 84 x * y^2 + 18 y^2 + 56 x^4 + 110 x^3 + 21 x^2 + 126 x + 27 ) z "); //c = dfac.parse("z^2 + ( 6 y^2 + 4 x^3 + 7 x^2 + 9 ) z"); //a = a.abs(); //b = b.abs(); //c = c.abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); //System.out.println("d = " + d); //System.out.println("c = " + c); assertTrue("c | gcd(ac,bc) " + e + ", d = " + d, e.isZERO()); } } } jas-2.5/trc/edu/jas/ufd/GCDModLongTest.java0000644000175000017500000004450411641660762020643 0ustar giovannigiovanni/* * $Id: GCDModLongTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.arith.PrimeList; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GCD Modular algorithm tests with JUnit. * @author Heinz Kredel. */ public class GCDModLongTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDModularTest object. * @param name String. */ public GCDModLongTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDModLongTest.class); return suite; } //private final static int bitlen = 100; GreatestCommonDivisorAbstract ufd; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; PrimeList primes = new PrimeList(); ModLongRing mi; ModLong ai; ModLong bi; ModLong ci; ModLong di; ModLong ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial ac; GenPolynomial bc; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; GenPolynomial> arc; GenPolynomial> brc; int rl = 5; int kl = 4; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; //mi = new ModLongRing(primes.get(0), true); mi = new ModLongRing(5L, true); ufd = new GreatestCommonDivisorPrimitive(); dfac = new GenPolynomialRing(mi, rl, to); cfac = new GenPolynomialRing(mi, rl - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd = null; dfac = null; cfac = null; rfac = null; } /** * Test modular algorithm gcd with modular evaluation recursive algorithm. * */ public void testModularEvaluationGcd() { GreatestCommonDivisorAbstract ufd_m = new GreatestCommonDivisorModular(); // dummy type GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomialRing dfac = new GenPolynomialRing(new BigInteger(), 3, to); for (int i = 0; i < 2; i++) { a = dfac.random(kl, ll + i, el + i, q); b = dfac.random(kl, ll + i, el + i, q); c = dfac.random(kl, ll + i, el + i, q); c = c.multiply(dfac.univariate(0)); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd_m.gcd(a, b); c = ufd.basePrimitivePart(c).abs(); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a" + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b" + e, e.isZERO()); } } /** * Test modular algorithm gcd with simple PRS recursive algorithm. * */ public void testModularSimpleGcd() { GreatestCommonDivisorAbstract ufd_m = new GreatestCommonDivisorModular(true); // dummy type GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomialRing dfac = new GenPolynomialRing(new BigInteger(), 3, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll + i, el + i, q); b = dfac.random(kl, ll + i, el + i, q); c = dfac.random(kl, ll + i, el + i, q); c = c.multiply(dfac.univariate(0)); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd_m.gcd(a, b); c = ufd.basePrimitivePart(c).abs(); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a" + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b" + e, e.isZERO()); } } /** * Test recursive content and primitive part, modular coefficients. * */ public void testRecursiveContentPPmodular() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); for (int i = 0; i < 1; i++) { a = cfac.random(kl, ll + 2 * i, el + i, q).monic(); cr = rfac.random(kl * (i + 2), ll + 2 * i, el + i, q); cr = PolyUtil. monic(cr); //System.out.println("a = " + a); //System.out.println("cr = " + cr); //a = ufd.basePrimitivePart(a); //b = distribute(dfac,cr); //b = ufd.basePrimitivePart(b); //cr = recursive(rfac,b); //System.out.println("a = " + a); //System.out.println("cr = " + cr); cr = cr.multiply(a); //System.out.println("cr = " + cr); if (cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); c = ufd.recursiveContent(cr).monic(); dr = ufd.recursivePrimitivePart(cr); dr = PolyUtil. monic(dr); //System.out.println("c = " + c); //System.out.println("dr = " + dr); //System.out.println("monic(a) = " + a.monic()); //System.out.println("monic(c) = " + c.monic()); ar = dr.multiply(c); //System.out.println("ar = " + ar); assertEquals("c == cont(c)pp(c)", cr, ar); } } /** * Test base gcd modular coefficients. * */ public void testGCDbaseModular() { dfac = new GenPolynomialRing(mi, 1, to); GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el + 3 + i, q).monic(); b = dfac.random(kl, ll, el + 3 + i, q).monic(); c = dfac.random(kl, ll, el + 3 + i, q).monic(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ac = a.multiply(c); bc = b.multiply(c); //System.out.println("ac = " + ac); //System.out.println("bc = " + bc); //e = PolyUtil.basePseudoRemainder(ac,c); //System.out.println("ac/c a = 0 " + e); //assertTrue("ac/c-a != 0 " + e, e.isZERO() ); //e = PolyUtil.basePseudoRemainder(bc,c); //System.out.println("bc/c-b = 0 " + e); //assertTrue("bc/c-b != 0 " + e, e.isZERO() ); d = ufd.baseGcd(ac, bc); d = d.monic(); // not required //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test recursive gcd modular coefficients. * */ public void testRecursiveGCDModular() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); // GreatestCommonDivisorAbstract ufd // = new GreatestCommonDivisorPrimitive(); for (int i = 0; i < 1; i++) { ar = rfac.random(kl, 2, el + 2, q); br = rfac.random(kl, 2, el + 2, q); cr = rfac.random(kl, 2, el + 2, q); ar = PolyUtil. monic(ar); br = PolyUtil. monic(br); cr = PolyUtil. monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); arc = ar.multiply(cr); brc = br.multiply(cr); //System.out.println("arc = " + arc); //System.out.println("brc = " + brc); //er = PolyUtil.recursivePseudoRemainder(arc,cr); //System.out.println("ac/c-a = 0 " + er); //assertTrue("ac/c-a != 0 " + er, er.isZERO() ); //er = PolyUtil.recursivePseudoRemainder(brc,cr); //System.out.println("bc/c-b = 0 " + er); //assertTrue("bc/c-b != 0 " + er, er.isZERO() ); dr = ufd.recursiveUnivariateGcd(arc, brc); dr = PolyUtil. monic(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test arbitrary recursive gcd modular coefficients. * */ public void testArbitraryRecursiveGCDModular() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); // GreatestCommonDivisorAbstract ufd // = new GreatestCommonDivisorPrimitive(); for (int i = 0; i < 1; i++) { ar = rfac.random(kl, 2, el + 2, q); br = rfac.random(kl, 2, el + 2, q); cr = rfac.random(kl, 2, el + 2, q); ar = PolyUtil. monic(ar); br = PolyUtil. monic(br); cr = PolyUtil. monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); arc = ar.multiply(cr); brc = br.multiply(cr); //System.out.println("arc = " + arc); //System.out.println("brc = " + brc); //er = PolyUtil.recursivePseudoRemainder(arc,cr); //System.out.println("ac/c-a = 0 " + er); //assertTrue("ac/c-a != 0 " + er, er.isZERO() ); //er = PolyUtil.recursivePseudoRemainder(brc,cr); //System.out.println("bc/c-b = 0 " + er); //assertTrue("bc/c-b != 0 " + er, er.isZERO() ); dr = ufd.recursiveGcd(arc, brc); dr = PolyUtil. monic(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test gcd modular coefficients. * */ public void testGcdModular() { dfac = new GenPolynomialRing(mi, 4, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el + i, q).monic(); b = dfac.random(kl, ll, el + i, q).monic(); c = dfac.random(kl, ll, el + i, q).monic(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ac = a.multiply(c); bc = b.multiply(c); //System.out.println("ac = " + ac); //System.out.println("bc = " + bc); //e = PolyUtil.basePseudoRemainder(ac,c); //System.out.println("ac/c-a = 0 " + e); //assertTrue("ac/c-a != 0 " + e, e.isZERO() ); //e = PolyUtil.basePseudoRemainder(bc,c); //System.out.println("bc/c-b = 0 " + e); //assertTrue("bc/c-b != 0 " + e, e.isZERO() ); d = ufd.gcd(ac, bc); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); //System.out.println("c = " + c); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(ac, d); //System.out.println("gcd(ac,bc) | ac " + e); assertTrue("gcd(ac,bc) | ac " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(bc, d); //System.out.println("gcd(ac,bc) | bc " + e); assertTrue("gcd(ac,bc) | bc " + e, e.isZERO()); } } /** * Test co-prime factors. * */ public void testCoPrime() { dfac = new GenPolynomialRing(mi, 3, to); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } assertTrue("length( a ) <> 0", a.length() > 0); d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); e = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); List> F = new ArrayList>(5); F.add(a); F.add(b); F.add(c); F.add(d); F.add(e); List> P = ufd.coPrime(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); P = ufd.coPrimeRec(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); } } jas-2.5/trc/edu/jas/ufd/HenselMultUtilTest.java0000644000175000017500000012771512070343440021676 0ustar giovannigiovanni/* * $Id: HenselMultUtilTest.java 4343 2012-12-31 17:10:56Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.arith.PrimeList; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * HenselMultUtil tests with JUnit. Two seperate classes because of package * dependency. * @see edu.jas.application.HenselMultUtilTest * @author Heinz Kredel. */ public class HenselMultUtilTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a HenselMultUtilTest object. * @param name String. */ public HenselMultUtilTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(HenselMultUtilTest.class); return suite; } TermOrder tord = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 2; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; dfac = new GenPolynomialRing(new BigInteger(1), rl, tord); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, tord); rfac = new GenPolynomialRing>(cfac, 1, tord); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; dfac = null; cfac = null; rfac = null; ComputerThreads.terminate(); } protected static java.math.BigInteger getPrime1() { return PrimeList.getLongPrime(60, 93); } protected static java.math.BigInteger getPrime2() { return PrimeList.getLongPrime(30, 35); } /** * Test multivariate Hensel lifting monic case list. */ public void testHenselLiftingMonicList() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModIntegerRing pm = new ModIntegerRing(p, false); //ModLongRing pl = new ModLongRing(p, false); GenPolynomialRing pfac = new GenPolynomialRing(pm, 4, tord, new String[] { "w", "x", "y", "z" }); //GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(),pfac); BigInteger mi = m; long k = 5L; //long d = 3L; java.math.BigInteger pk = p.pow((int) k); //m = new BigInteger(pk); ModIntegerRing pkm = new ModIntegerRing(pk, false); //ModLongRing pkl = new ModLongRing(pk, false); GenPolynomialRing pkfac = new GenPolynomialRing(pkm, pfac); dfac = new GenPolynomialRing(mi, pfac); //GreatestCommonDivisor ufd = GCDFactory.getProxy(mi); GreatestCommonDivisor ufd = GCDFactory.getImplementation(mi); //ModLong v = pl.fromInteger(3L); ModInteger v = pkm.fromInteger(3L); List V = new ArrayList(1); V.add(new BigInteger(3L)); if (pkfac.nvar > 2) { V.add(new BigInteger(5L)); //pkm.fromInteger(5L)); } if (pkfac.nvar > 3) { V.add(new BigInteger(7L)); //pkm.fromInteger(7L)); } //System.out.println("V = " + V); GenPolynomial ap; GenPolynomial cp; //GenPolynomial rp; List> A = new ArrayList>(); for (int i = 1; i < 2; i++) { //a = dfac.random(kl + 7 * i, ll, el + 1, q).abs(); //b = dfac.random(kl + 7 * i, ll, el + 0, q).abs(); //c = dfac.random(kl + 7 * i, ll, el + 2, q).abs(); a = dfac.parse(" ( z^2 + y^2 + 4 x^3 - x + 1 + w ) "); b = dfac.parse(" ( z + y + x^2 + 10 + w ) "); //c = dfac.parse(" z + x + (y - 2)*(2 + y) "); A.add(a); A.add(b); //A.add(c); //System.out.println("A = " + A); A = ufd.coPrime(A); //System.out.println("coprime(A) = " + A); if (A.size() == 0) { continue; } c = A.get(0).multiply(A.get(1)); //c = dfac.parse(" y^2 + x^2 "); cp = PolyUtil. fromIntegerCoefficients(pkfac, c); //System.out.println("c = " + c); List> Ap = new ArrayList>(A.size()); for (GenPolynomial ai : A) { ap = PolyUtil. fromIntegerCoefficients(pkfac, ai); Ap.add(ap); } //System.out.println("A mod p^k = " + Ap); //System.out.println("v = " + v + ", vp = " + vp); GenPolynomialRing ckfac = pkfac.contract(1); v = pkm.fromInteger( V.get(2).getVal() ); List> Ae = new ArrayList>(A.size()); for (GenPolynomial a : Ap) { GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae.add(ae); } //System.out.println("A(v) mod p^k = " + Ae); ckfac = ckfac.contract(1); v = pkm.fromInteger( V.get(1).getVal() ); List> Ae1 = new ArrayList>(A.size()); for (GenPolynomial a : Ae) { GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae1.add(ae); } Ae = Ae1; //System.out.println("A(v,v) mod p^k = " + Ae); ckfac = ckfac.contract(1); v = pkm.fromInteger( V.get(0).getVal() ); Ae1 = new ArrayList>(A.size()); for (GenPolynomial a : Ae) { GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae1.add(ae); } Ae = Ae1; //System.out.println("A(v,v,v) mod p^k = " + Ae); try { List> lift; lift = HenselMultUtil. liftHenselMonic(c, cp, Ae, V, k); // 5 is max //System.out.println("\nliftMultiHensel:"); //System.out.println("lift = " + lift); //System.out.println("A = " + A); boolean t = HenselMultUtil. isHenselLift(c, cp, Ae, k, lift); assertTrue("isHenselLift: ", t); } catch (ArithmeticException e) { // ok, can happen } catch (NoLiftingException e) { // can now happen: fail("" + e); System.out.println("e = " + e); } } } /** * Test multivariate Hensel lifting list, 2 variables. */ public void testHenselLifting2List() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModIntegerRing pm = new ModIntegerRing(p, false); GenPolynomialRing pfac = new GenPolynomialRing(pm, 2, tord, new String[] { "x", "y" }); GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pfac); GenPolynomialRing> irfac = ifac.recursive(ifac.nvar - 1); BigInteger mi = m; long k = 5L; //long d = 3L; java.math.BigInteger pk = p.pow((int) k); //m = new BigInteger(pk); //System.out.println("m = " + m + " = " + p + "^" + k); ModIntegerRing pkm = new ModIntegerRing(pk, false); //ModLongRing pkl = new ModLongRing(pk, false); GenPolynomialRing pkfac = new GenPolynomialRing(pkm, pfac); dfac = new GenPolynomialRing(mi, pfac); //GreatestCommonDivisor ufd = GCDFactory.getProxy(mi); GreatestCommonDivisor ufd = GCDFactory.getImplementation(mi); //ModLong v = pl.fromInteger(3L); ModInteger v = pkm.fromInteger(3L); List V = new ArrayList(1); V.add(new BigInteger(3L)); //System.out.println("V = " + V); GenPolynomial ap; GenPolynomial cp; //GenPolynomial rp; List> A = new ArrayList>(); for (int i = 1; i < 2; i++) { a = dfac.parse(" ( x^3 y - 1 ) "); b = dfac.parse(" ( 1 + y ) "); e = dfac.parse(" ( y^2 - x ) "); A.add(a); A.add(b); A.add(e); //System.out.println("A = " + A); A = ufd.coPrime(A); //System.out.println("coprime(A) = " + A); // polynomials are rearranged if (A.size() == 0) { continue; } c = A.get(0).multiply(A.get(1)).multiply(A.get(2)); //c = dfac.parse(" y^2 + x^2 "); cp = PolyUtil. fromIntegerCoefficients(pkfac, c); //System.out.println("c = " + c); //System.out.println("cp = " + cp); GenPolynomial> cr = PolyUtil. recursive(irfac, c); GenPolynomial> crr = PolyUtil. switchVariables(cr); //System.out.println("crr = " + crr); GenPolynomial cl = crr.leadingBaseCoefficient(); //System.out.println("cl = " + cl + ", cl.ring = " + cl.ring); FactorAbstract factorizer = FactorFactory.getImplementation(new BigInteger()); List> CF = factorizer.factorsRadical(cl); //System.out.println("CF = " + CF); List> CL = new ArrayList>(2); CL.add(CF.get(0)); CL.add(CF.get(2)); CL.add(CF.get(1)); //CL.add( CF.get(0) ); //System.out.println("CL = " + CL); List> Ap = new ArrayList>(A.size()); for (GenPolynomial ai : A) { ap = PolyUtil. fromIntegerCoefficients(pkfac, ai); Ap.add(ap); } //System.out.println("A mod p^k = " + Ap); //System.out.println("v = " + v + ", V = " + V); GenPolynomialRing ckfac = pkfac.contract(1); v = pkm.fromInteger( V.get(0).getVal() ); List> Ae = new ArrayList>(A.size()); for (GenPolynomial a : Ap) { // Ap GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae.add(ae); } //System.out.println("A(v) mod p^k = " + Ae); try { List> lift; lift = HenselMultUtil. liftHensel(c, cp, Ae, V, k, CL); // 5 is max //System.out.println("\nliftMultiHensel:"); //System.out.println("lift = " + lift); //System.out.println("A = " + A); boolean t = HenselMultUtil. isHenselLift(c, cp, Ae, k, lift); assertTrue("isHenselLift: ", t); } catch (ArithmeticException e) { // ok, can happen System.out.println("e = " + e); } catch (NoLiftingException e) { // can now happen: fail("" + e); System.out.println("e = " + e); } } } /** * Test multivariate Hensel lifting list, 3 variables. */ public void xtestHenselLifting3List() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModIntegerRing pm = new ModIntegerRing(p, false); GenPolynomialRing pfac = new GenPolynomialRing(pm, 3, tord, new String[] { "x", "y", "z" }); GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pfac); GenPolynomialRing> irfac = ifac.recursive(ifac.nvar - 1); BigInteger mi = m; long k = 3L; //long d = 3L; java.math.BigInteger pk = p.pow((int) k); //m = new BigInteger(pk); //System.out.println("m = " + m); ModIntegerRing pkm = new ModIntegerRing(pk, false); //ModLongRing pkl = new ModLongRing(pk, false); GenPolynomialRing pkfac = new GenPolynomialRing(pkm, pfac); dfac = new GenPolynomialRing(mi, pfac); //GreatestCommonDivisor ufd = GCDFactory.getProxy(mi); GreatestCommonDivisor ufd = GCDFactory.getImplementation(mi); //ModLong v = pl.fromInteger(3L); ModInteger v = pkm.fromInteger(3L); List V = new ArrayList(1); V.add(new BigInteger(3L)); if (pkfac.nvar > 2) { V.add(new BigInteger(5L)); //pkm.fromInteger(5L)); } if (pkfac.nvar > 3) { V.add(new BigInteger(7L)); //pkm.fromInteger(7L)); } //System.out.println("V = " + V); GenPolynomial ap; GenPolynomial cp; //GenPolynomial rp; List> A = new ArrayList>(); for (int i = 1; i < 2; i++) { //a = dfac.random(kl + 7 * i, ll, el + 1, q).abs(); //b = dfac.random(kl + 7 * i, ll, el + 0, q).abs(); //c = dfac.random(kl + 7 * i, ll, el + 2, q).abs(); //a = dfac.parse(" ( z^2 + y^2 + 4 x^3 - x + 1 + w ) "); //b = dfac.parse(" ( z y x + x^2 + 10 + w ) "); a = dfac.parse(" ( x^3 z - y ) "); //a = dfac.parse(" ( x - y ) "); b = dfac.parse(" ( 1 + y + z ) "); e = dfac.parse(" ( z^2 y - x ) "); A.add(a); A.add(b); A.add(e); //System.out.println("A = " + A); A = ufd.coPrime(A); //System.out.println("coprime(A) = " + A); // polynomials are rearranged if (A.size() == 0) { continue; } c = A.get(0).multiply(A.get(1)).multiply(A.get(2)); //c = dfac.parse(" y^2 + x^2 "); cp = PolyUtil. fromIntegerCoefficients(pkfac, c); //System.out.println("c = " + c); GenPolynomial> cr = PolyUtil. recursive(irfac, c); GenPolynomial> crr = PolyUtil. switchVariables(cr); //System.out.println("crr = " + crr); GenPolynomial cl = crr.leadingBaseCoefficient(); //System.out.println("cl = " + cl + ", cl.ring = " + cl.ring); FactorAbstract factorizer = FactorFactory.getImplementation(new BigInteger()); List> CF = factorizer.factorsRadical(cl); //System.out.println("CF = " + CF); List> CL = new ArrayList>(2); CL.add(CF.get(0)); CL.add(CF.get(2)); CL.add(CF.get(1)); //System.out.println("CL = " + CL); List> Ap = new ArrayList>(A.size()); for (GenPolynomial ai : A) { ap = PolyUtil. fromIntegerCoefficients(pkfac, ai); Ap.add(ap); } //System.out.println("A mod p^k = " + Ap); //System.out.println("v = " + v + ", V = " + V); GenPolynomialRing ckfac = pkfac.contract(1); //v = pkm.fromInteger( V.get(2) ); List> Ae = new ArrayList>(A.size()); //for ( GenPolynomial a : Ap ) { // GenPolynomial ae = PolyUtil. evaluateMain(ckfac,a,v); // Ae.add(ae); //} //System.out.println("A(v) mod p^k = " + Ae); //ckfac = ckfac.contract(1); Ae = Ap; v = pkm.fromInteger( V.get(1).getVal() ); List> Ae1 = new ArrayList>(A.size()); for (GenPolynomial a : Ae) { GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae1.add(ae); } Ae = Ae1; //System.out.println("A(v) mod p^k = " + Ae); ckfac = ckfac.contract(1); v = pkm.fromInteger( V.get(0).getVal() ); Ae1 = new ArrayList>(A.size()); for (GenPolynomial a : Ae) { // Ap GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae1.add(ae); } Ae = Ae1; //System.out.println("A(v,v) mod p^k = " + Ae); try { List> lift; lift = HenselMultUtil. liftHensel(c, cp, Ae, V, k, CL); // 5 is max //System.out.println("\nliftMultiHensel:"); //System.out.println("lift = " + lift); //System.out.println("A = " + A); boolean t = HenselMultUtil. isHenselLift(c, cp, Ae, k, lift); assertTrue("isHenselLift: ", t); } catch (ArithmeticException e) { // ok, can happen System.out.println("e = " + e); } catch (NoLiftingException e) { // can now happen: fail("" + e); System.out.println("e = " + e); } } } /** * Test multivariate Hensel lifting list, 4 variables. */ public void xtestHenselLifting4List() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModIntegerRing pm = new ModIntegerRing(p, false); GenPolynomialRing pfac = new GenPolynomialRing(pm, 4, tord, new String[] { "x", "y", "z", "w" }); GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pfac); GenPolynomialRing> irfac = ifac.recursive(ifac.nvar - 1); BigInteger mi = m; long k = 3L; //long d = 3L; java.math.BigInteger pk = p.pow((int) k); //m = new BigInteger(pk); //System.out.println("m = " + m); ModIntegerRing pkm = new ModIntegerRing(pk, false); //ModLongRing pkl = new ModLongRing(pk, false); GenPolynomialRing pkfac = new GenPolynomialRing(pkm, pfac); dfac = new GenPolynomialRing(mi, pfac); //GreatestCommonDivisor ufd = GCDFactory.getProxy(mi); GreatestCommonDivisor ufd = GCDFactory.getImplementation(mi); //ModLong v = pl.fromInteger(3L); ModInteger v = pkm.fromInteger(3L); List V = new ArrayList(1); V.add(new BigInteger(3L)); if (pkfac.nvar > 2) { V.add(new BigInteger(5L)); //pkm.fromInteger(5L)); } if (pkfac.nvar > 3) { V.add(new BigInteger(7L)); // pkm.fromInteger(7L)); } //System.out.println("V = " + V); GenPolynomial ap; GenPolynomial cp; //GenPolynomial rp; List> A = new ArrayList>(); for (int i = 1; i < 2; i++) { a = dfac.parse(" ( x^3 w - y ) "); b = dfac.parse(" ( 1 + y + z + w ) "); e = dfac.parse(" ( z^2 y w - x ) "); A.add(a); A.add(b); A.add(e); //System.out.println("A = " + A); A = ufd.coPrime(A); //System.out.println("coprime(A) = " + A); // polynomials are rearranged if (A.size() == 0) { continue; } c = A.get(0).multiply(A.get(1)).multiply(A.get(2)); cp = PolyUtil. fromIntegerCoefficients(pkfac, c); //System.out.println("c = " + c); GenPolynomial> cr = PolyUtil. recursive(irfac, c); GenPolynomial> crr = PolyUtil. switchVariables(cr); //System.out.println("crr = " + crr); GenPolynomial cl = crr.leadingBaseCoefficient(); //System.out.println("cl = " + cl + ", cl.ring = " + cl.ring); FactorAbstract factorizer = FactorFactory.getImplementation(new BigInteger()); List> CF = factorizer.factorsRadical(cl); //System.out.println("CF = " + CF); List> CL = new ArrayList>(2); CL.add(CF.get(0)); CL.add(CF.get(2)); CL.add(CF.get(1)); //System.out.println("CL = " + CL); List> Ap = new ArrayList>(A.size()); for (GenPolynomial ai : A) { ap = PolyUtil. fromIntegerCoefficients(pkfac, ai); Ap.add(ap); } //System.out.println("A mod p^k = " + Ap); //System.out.println("v = " + v + ", V = " + V); GenPolynomialRing ckfac = pkfac.contract(1); v = pkm.fromInteger( V.get(2).getVal() ); List> Ae = new ArrayList>(A.size()); for (GenPolynomial a : Ap) { GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae.add(ae); } //System.out.println("A(v) mod p^k = " + Ae); ckfac = ckfac.contract(1); v = pkm.fromInteger( V.get(1).getVal() ); List> Ae1 = new ArrayList>(A.size()); for (GenPolynomial a : Ae) { GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae1.add(ae); } Ae = Ae1; //System.out.println("A(v,v) mod p^k = " + Ae); ckfac = ckfac.contract(1); v = pkm.fromInteger( V.get(0).getVal() ); Ae1 = new ArrayList>(A.size()); for (GenPolynomial a : Ae) { // Ap GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae1.add(ae); } Ae = Ae1; //System.out.println("A(v,v,v) mod p^k = " + Ae); try { List> lift; lift = HenselMultUtil. liftHensel(c, cp, Ae, V, k, CL); // 5 is max //System.out.println("\nliftMultiHensel:"); //System.out.println("lift = " + lift); //System.out.println("A = " + A); boolean t = HenselMultUtil. isHenselLift(c, cp, Ae, k, lift); assertTrue("isHenselLift: ", t); } catch (ArithmeticException e) { // ok, can happen System.out.println("e = " + e); } catch (NoLiftingException e) { // can now happen: fail("" + e); System.out.println("e = " + e); } } } /** * Test univariate and multivariate Hensel lifting list, 2 variables. */ public void testHenselLifting2FullList() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModLongRing pm = new ModLongRing(p, false); GenPolynomialRing pfac = new GenPolynomialRing(pm, 2, tord, new String[] { "x", "y" }); GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pfac); GenPolynomialRing> irfac = ifac.recursive(ifac.nvar - 1); GenPolynomialRing icfac = ifac.contract(ifac.nvar - 1); GenPolynomialRing pcfac = pfac.contract(pfac.nvar - 1); BigInteger mi = m; long k = 5L; //long d = 3L; java.math.BigInteger pk = p.pow((int) k); //m = new BigInteger(pk); //System.out.println("m = " + m + " = " + p + "^" + k); ModLongRing pkm = new ModLongRing(pk, false); GenPolynomialRing pkfac = new GenPolynomialRing(pkm, pfac); dfac = new GenPolynomialRing(mi, pfac); //GreatestCommonDivisor ufd = GCDFactory.getProxy(mi); GreatestCommonDivisor ufd = GCDFactory.getImplementation(mi); ModLong v = pkm.fromInteger(3L); List V = new ArrayList(1); V.add(new BigInteger(3L)); //System.out.println("V = " + V); GenPolynomial ap; GenPolynomial cp; //GenPolynomial rp; List> A = new ArrayList>(); for (int i = 1; i < 2; i++) { a = dfac.parse(" ( x^3 y - 1 ) "); b = dfac.parse(" ( 1 + y ) "); e = dfac.parse(" ( y^2 - x ) "); A.add(a); A.add(b); A.add(e); //System.out.println("A = " + A); A = ufd.coPrime(A); //System.out.println("coprime(A) = " + A); // polynomials are rearranged if (A.size() == 0) { continue; } c = A.get(0).multiply(A.get(1)).multiply(A.get(2)); cp = PolyUtil. fromIntegerCoefficients(pkfac, c); //System.out.println("c = " + c); GenPolynomial> cr = PolyUtil. recursive(irfac, c); GenPolynomial> crr = PolyUtil. switchVariables(cr); //System.out.println("crr = " + crr); GenPolynomial cl = crr.leadingBaseCoefficient(); //System.out.println("cl = " + cl + ", cl.ring = " + cl.ring); FactorAbstract factorizer = FactorFactory.getImplementation(new BigInteger()); List> CF = factorizer.factorsRadical(cl); //System.out.println("CF = " + CF); List> CL = new ArrayList>(2); CL.add(CF.get(0)); CL.add(CF.get(2)); CL.add(CF.get(1)); //CL.add( CF.get(0) ); //System.out.println("CL = " + CL); List> Apk = new ArrayList>(A.size()); for (GenPolynomial ai : A) { ap = PolyUtil. fromIntegerCoefficients(pkfac, ai); Apk.add(ap); } //System.out.println("A mod p^k = " + Apk); //System.out.println("v = " + v + ", V = " + V); GenPolynomialRing ckfac = pkfac.contract(1); v = pkm.fromInteger( V.get(0).getVal() ); List> Ae = new ArrayList>(A.size()); for (GenPolynomial a : Apk) { // Ap GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae.add(ae); } //System.out.println("A(v) mod p^k = " + Ae); List> Ap = new ArrayList>(A.size()); for (GenPolynomial ai : PolyUtil. integerFromModularCoefficients(icfac, Ae)) { ap = PolyUtil. fromIntegerCoefficients(pcfac, ai); Ap.add(ap); } //System.out.println("A(v) mod p = " + Ap); try { List> lift; lift = HenselMultUtil. liftHenselFull(c, Ap, V, k, CL); // 5 is max //System.out.println("\nliftMultiHensel:"); //System.out.println("lift = " + lift); //System.out.println("A = " + A); boolean t = HenselMultUtil. isHenselLift(c, cp, Ap, k, lift); assertTrue("isHenselLift: ", t); } catch (ArithmeticException e) { // ok, can happen System.out.println("e = " + e); } catch (NoLiftingException e) { // can now happen: fail("" + e); System.out.println("e = " + e); } } } /** * Test univariate and multivariate Hensel lifting list, 3 variables. */ public void testHenselLifting3FullList() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModLongRing pm = new ModLongRing(p, false); GenPolynomialRing pfac = new GenPolynomialRing(pm, 3, tord, new String[] { "x", "y", "z" }); GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pfac); GenPolynomialRing> irfac = ifac.recursive(ifac.nvar - 1); GenPolynomialRing icfac = ifac.contract(ifac.nvar - 1); GenPolynomialRing pcfac = pfac.contract(pfac.nvar - 1); BigInteger mi = m; long k = 5L; //long d = 3L; java.math.BigInteger pk = p.pow((int) k); //m = new BigInteger(pk); //System.out.println("m = " + m + " = " + p + "^" + k); ModLongRing pkm = new ModLongRing(pk, false); GenPolynomialRing pkfac = new GenPolynomialRing(pkm, pfac); dfac = new GenPolynomialRing(mi, pfac); //GreatestCommonDivisor ufd = GCDFactory.getProxy(mi); GreatestCommonDivisor ufd = GCDFactory.getImplementation(mi); ModLong v = pkm.fromInteger(3L); List V = new ArrayList(1); V.add(new BigInteger(3L)); if (pkfac.nvar > 2) { V.add(new BigInteger(5L)); //pkm.fromInteger(5L)); } //System.out.println("V = " + V); GenPolynomial ap; GenPolynomial cp; //GenPolynomial rp; List> A = new ArrayList>(); for (int i = 1; i < 2; i++) { a = dfac.parse(" ( x^3 z - y ) "); b = dfac.parse(" ( 1 + y + z ) "); e = dfac.parse(" ( z^2 y - x ) "); A.add(a); A.add(b); A.add(e); //System.out.println("A = " + A); A = ufd.coPrime(A); //System.out.println("coprime(A) = " + A); // polynomials are rearranged if (A.size() == 0) { continue; } c = A.get(0).multiply(A.get(1)).multiply(A.get(2)); cp = PolyUtil. fromIntegerCoefficients(pkfac, c); //System.out.println("c = " + c); //System.out.println("cp = " + cp); GenPolynomial> cr = PolyUtil. recursive(irfac, c); GenPolynomial> crr = PolyUtil. switchVariables(cr); //System.out.println("crr = " + crr); GenPolynomial cl = crr.leadingBaseCoefficient(); //System.out.println("cl = " + cl + ", cl.ring = " + cl.ring); FactorAbstract factorizer = FactorFactory.getImplementation(new BigInteger()); List> CF = factorizer.factorsRadical(cl); //System.out.println("CF = " + CF); List> CL = new ArrayList>(2); CL.add(CF.get(0)); CL.add(CF.get(2)); CL.add(CF.get(1)); //System.out.println("CL = " + CL); List> Apk = new ArrayList>(A.size()); for (GenPolynomial ai : A) { ap = PolyUtil. fromIntegerCoefficients(pkfac, ai); Apk.add(ap); } //System.out.println("A mod p^k = " + Apk); //System.out.println("v = " + v + ", V = " + V); GenPolynomialRing ckfac = pkfac.contract(1); List> Ae = new ArrayList>(A.size()); Ae = Apk; v = pkm.fromInteger( V.get(0).getVal() ); List> Ae1 = new ArrayList>(A.size()); for (GenPolynomial a : Ae) { GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae1.add(ae); } Ae = Ae1; //System.out.println("A(v) mod p^k = " + Ae); GenPolynomial cpp = PolyUtil. evaluateMain(ckfac, cp, v); //System.out.println("cpp = " + cpp); ckfac = ckfac.contract(1); v = pkm.fromInteger( V.get(1).getVal() ); Ae1 = new ArrayList>(A.size()); for (GenPolynomial a : Ae) { // Ap GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae1.add(ae); } Ae = Ae1; //System.out.println("A(v,v) mod p^k = " + Ae); GenPolynomial cppp = PolyUtil. evaluateMain(ckfac, cpp, v); //System.out.println("cppp = " + cppp); List> Ap = new ArrayList>(A.size()); for (GenPolynomial ai : PolyUtil. integerFromModularCoefficients(icfac, Ae)) { ap = PolyUtil. fromIntegerCoefficients(pcfac, ai); Ap.add(ap); } //System.out.println("A(v,v) mod p = " + Ap); GenPolynomial cpppp = PolyUtil. fromIntegerCoefficients(pcfac, PolyUtil. integerFromModularCoefficients(icfac, cppp)); //System.out.println("cpppp = " + cpppp); GenPolynomial aa = pcfac.getONE(); for (GenPolynomial x : Ap) { aa = aa.multiply(x); } assertTrue("prod(A(v,v)) mod p = " + aa + ", cpppp = " + cpppp + ", aa != cpppp: ", cpppp.equals(aa)); try { List> lift; lift = HenselMultUtil. liftHenselFull(c, Ap, V, k, CL); // 5 is max //System.out.println("\nliftMultiHensel:"); //System.out.println("lift = " + lift); //System.out.println("A = " + A); boolean t = HenselMultUtil. isHenselLift(c, cp, Ap, k, lift); assertTrue("isHenselLift: ", t); } catch (ArithmeticException e) { // ok, can happen System.out.println("e = " + e); } catch (NoLiftingException e) { // can now happen: fail("" + e); System.out.println("e = " + e); } } } /** * Test univariate and multivariate Hensel lifting list, 3 variables. */ public void testHenselLifting4FullList() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModLongRing pm = new ModLongRing(p, false); GenPolynomialRing pfac = new GenPolynomialRing(pm, 4, tord, new String[] { "x", "y", "z", "w" }); GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pfac); GenPolynomialRing> irfac = ifac.recursive(ifac.nvar - 1); GenPolynomialRing icfac = ifac.contract(ifac.nvar - 1); GenPolynomialRing pcfac = pfac.contract(pfac.nvar - 1); BigInteger mi = m; long k = 5L; //long d = 3L; java.math.BigInteger pk = p.pow((int) k); //m = new BigInteger(pk); //System.out.println("m = " + m); ModLongRing pkm = new ModLongRing(pk, false); GenPolynomialRing pkfac = new GenPolynomialRing(pkm, pfac); dfac = new GenPolynomialRing(mi, pfac); //GreatestCommonDivisor ufd = GCDFactory.getProxy(mi); GreatestCommonDivisor ufd = GCDFactory.getImplementation(mi); ModLong v = pkm.fromInteger(3L); List V = new ArrayList(1); V.add(new BigInteger(3L)); if (pkfac.nvar > 2) { V.add(new BigInteger(5L)); //pkm.fromInteger(5L)); } if (pkfac.nvar > 3) { V.add(new BigInteger(7L)); //pkm.fromInteger(7L)); } //System.out.println("V = " + V); GenPolynomial ap; GenPolynomial cp; //GenPolynomial rp; List> A = new ArrayList>(); for (int i = 1; i < 2; i++) { a = dfac.parse(" ( x^3 w - y ) "); b = dfac.parse(" ( 1 + y + z + w ) "); e = dfac.parse(" ( z^2 y w - x ) "); A.add(a); A.add(b); A.add(e); //System.out.println("A = " + A); A = ufd.coPrime(A); //System.out.println("coprime(A) = " + A); // polynomials are rearranged if (A.size() == 0) { continue; } c = A.get(0).multiply(A.get(1)).multiply(A.get(2)); cp = PolyUtil. fromIntegerCoefficients(pkfac, c); //System.out.println("c = " + c); GenPolynomial> cr = PolyUtil. recursive(irfac, c); GenPolynomial> crr = PolyUtil. switchVariables(cr); //System.out.println("crr = " + crr); GenPolynomial cl = crr.leadingBaseCoefficient(); //System.out.println("cl = " + cl + ", cl.ring = " + cl.ring); FactorAbstract factorizer = FactorFactory.getImplementation(new BigInteger()); List> CF = factorizer.factorsRadical(cl); //System.out.println("CF = " + CF); List> CL = new ArrayList>(2); CL.add(CF.get(0)); CL.add(CF.get(2)); CL.add(CF.get(1)); //System.out.println("CL = " + CL); List> Apk = new ArrayList>(A.size()); for (GenPolynomial ai : A) { ap = PolyUtil. fromIntegerCoefficients(pkfac, ai); Apk.add(ap); } //System.out.println("A mod p^k = " + Apk); //System.out.println("v = " + v + ", V = " + V); GenPolynomialRing ckfac = pkfac.contract(1); v = pkm.fromInteger( V.get(0).getVal() ); List> Ae = new ArrayList>(A.size()); for (GenPolynomial a : Apk) { GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae.add(ae); } //System.out.println("A(v) mod p^k = " + Ae); ckfac = ckfac.contract(1); v = pkm.fromInteger( V.get(1).getVal() ); List> Ae1 = new ArrayList>(A.size()); for (GenPolynomial a : Ae) { GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae1.add(ae); } Ae = Ae1; //System.out.println("A(v,v) mod p^k = " + Ae); ckfac = ckfac.contract(1); v = pkm.fromInteger( V.get(2).getVal() ); Ae1 = new ArrayList>(A.size()); for (GenPolynomial a : Ae) { // Ap GenPolynomial ae = PolyUtil. evaluateMain(ckfac, a, v); Ae1.add(ae); } Ae = Ae1; //System.out.println("A(v,v,v) mod p^k = " + Ae); List> Ap = new ArrayList>(A.size()); for (GenPolynomial ai : PolyUtil. integerFromModularCoefficients(icfac, Ae)) { ap = PolyUtil. fromIntegerCoefficients(pcfac, ai); Ap.add(ap); } //System.out.println("A(v,v,v) mod p = " + Ap); try { List> lift; //lift = HenselMultUtil. liftHensel(c, cp, Ae, V, k, CL); // 5 is max lift = HenselMultUtil. liftHenselFull(c, Ap, V, k, CL); // 5 is max //System.out.println("\nliftMultiHensel:"); //System.out.println("lift = " + lift); //System.out.println("A = " + A); boolean t = HenselMultUtil. isHenselLift(c, cp, Ap, k, lift); assertTrue("isHenselLift: ", t); } catch (ArithmeticException e) { // ok, can happen System.out.println("e = " + e); } catch (NoLiftingException e) { // can now happen: fail("" + e); System.out.println("e = " + e); } } } } jas-2.5/trc/edu/jas/ufd/FactorAlgebraicTest.java0000644000175000017500000001051311641660762021767 0ustar giovannigiovanni/* * $Id: FactorAlgebraicTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Factor algebraic tests with JUnit. * @author Heinz Kredel. */ public class FactorAlgebraicTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorAlgebraicTest object. * @param name String. */ public FactorAlgebraicTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorAlgebraicTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. * */ public void testDummy() { } /** * Test algebraic factorization. * */ public void testAlgebraicFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] alpha = new String[] { "alpha" }; String[] vars = new String[] { "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, alpha); GenPolynomial agen = pfac.univariate(0, 2); agen = agen.sum(pfac.getONE()); // x^2 + 1 AlgebraicNumberRing afac = new AlgebraicNumberRing(agen, true); GenPolynomialRing> apfac = new GenPolynomialRing>( afac, 1, to, vars); // univariate //System.out.println("agen = " + agen); //System.out.println("afac = " + afac); //System.out.println("apfac = " + apfac); FactorAlgebraic fac = new FactorAlgebraic(afac); for (int i = 1; i < 2; i++) { int facs = 0; GenPolynomial> a; GenPolynomial> c = apfac.random(2, ll + i, el + i, q); //a = a.monic(); GenPolynomial> b = apfac.random(2, ll + i, el + i, q); if (b.degree() == 0) { b = b.multiply(apfac.univariate(0)); } //b = b.monic(); //if ( false && ! a.leadingBaseCoefficient().isONE() ) { //continue; //ExpVector e = a.leadingExpVector(); //a.doPutToMap(e,cfac.getONE()); //} if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } //a = apfac.univariate(0,2).sum( apfac.getONE() ); // x^2 + 1 //a = a.multiply(a); //a = a.multiply( apfac.univariate(0,2).subtract( apfac.getONE() ) ); // x^2 - 1 //a = apfac.univariate(0,3).subtract( apfac.getONE() ); // x^3 - 1 //a = apfac.univariate(0,3).sum( apfac.getONE() ); // x^3 + 1 a = c.multiply(b); //a = a.monic(); //System.out.println("\na = " + a); //System.out.println("b = " + b.monic()); //System.out.println("c = " + c.monic()); SortedMap>, Long> sm = fac.baseFactors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { System.out.println("sm.size() < facs = " + facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } } jas-2.5/trc/edu/jas/ufd/GCDPrimitiveTest.java0000644000175000017500000005122511641660762021252 0ustar giovannigiovanni/* * $Id: GCDPrimitiveTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.BasicConfigurator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GCD Primitive PRS algorithm tests with JUnit. * @author Heinz Kredel. */ public class GCDPrimitiveTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDPrimitiveTest object. * @param name String. */ public GCDPrimitiveTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDPrimitiveTest.class); return suite; } //private final static int bitlen = 100; GreatestCommonDivisorAbstract ufd; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 5; int kl = 4; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd = new GreatestCommonDivisorPrimitive(); String[] vars = ExpVector.STDVARS(rl); String[] cvars = ExpVector.STDVARS(rl - 1); String[] rvars = new String[] { vars[rl - 1] }; dfac = new GenPolynomialRing(new BigInteger(1), rl, to, vars); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to, cvars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd = null; dfac = null; cfac = null; rfac = null; } /** * Test base quotioent and remainder. * */ public void testBaseQR() { di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 1, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a).abs(); //c = ufd.basePrimitivePart(c); ci = di.random(kl * (i + 2)); ci = ci.sum(di.getONE()); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("ci = " + ci); if (a.isZERO() || c.isZERO() || ci.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); b = a.multiply(c); //System.out.println("b = " + b); d = PolyUtil. basePseudoRemainder(b, c); //System.out.println("d = " + d); assertTrue("rem(ac,c) == 0", d.isZERO()); b = a.multiply(ci); //System.out.println("b = " + b); d = b.divide(ci); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); b = a.multiply(c); //System.out.println("b = " + b); d = PolyUtil. basePseudoDivide(b, c); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); } } /** * Test base content and primitive part. * */ public void testBaseContentPP() { di = new BigInteger(1); for (int i = 0; i < 13; i++) { c = dfac.random(kl * (i + 2), ll + 2 * i, el + i, q); c = c.multiply(di.random(kl * (i + 2))); if (c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ci = ufd.baseContent(c); d = ufd.basePrimitivePart(c); //System.out.println("c = " + c); //System.out.println("ci = " + ci); //System.out.println("d = " + d); a = d.multiply(ci); assertEquals("c == cont(c)pp(c)", c, a); } } /** * Test base gcd. * */ public void testBaseGcd() { dfac = new GenPolynomialRing(new BigInteger(1), 1, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); //c = ufd.basePrimitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); d = ufd.baseGcd(a, b); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test recursive quotioent and remainder. * */ public void testRecursiveQR() { di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 2, to); cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl * (i + 1), ll + i, el + i, q); a = ufd.basePrimitivePart(a).abs(); c = dfac.random(kl * (i + 1), ll + i, el + i, q); c = ufd.basePrimitivePart(a).abs(); cr = PolyUtil. recursive(rfac, c); c = cfac.random(kl * (i + 1), ll + 2 * i, el + 2 * i, q); c = ufd.basePrimitivePart(c).abs(); ar = PolyUtil. recursive(rfac, a); //System.out.println("ar = " + ar); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("cr = " + cr); if (cr.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); br = ar.multiply(cr); //System.out.println("br = " + br); dr = PolyUtil. recursivePseudoRemainder(br, cr); //System.out.println("dr = " + dr); d = PolyUtil. distribute(dfac, dr); //System.out.println("d = " + d); assertTrue("rem(ac,c) == 0", d.isZERO()); br = ar.multiply(c); //System.out.println("br = " + br); dr = PolyUtil. recursiveDivide(br, c); //System.out.println("dr = " + dr); d = PolyUtil. distribute(dfac, dr); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); } } /** * Test recursive content and primitive part. * */ public void testRecursiveContentPP() { di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 2, to); cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 3; i++) { cr = rfac.random(kl * (i + 2), ll + 2 * i, el + i, q); //System.out.println("cr = " + cr); assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); c = ufd.recursiveContent(cr); dr = ufd.recursivePrimitivePart(cr); //System.out.println("c = " + c); //System.out.println("dr = " + dr); ar = dr.multiply(c); assertEquals("c == cont(c)pp(c)", cr, ar); } } /** * Test recursive gcd. * */ public void testRecursiveGCD() { di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 2, to); cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 2; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveUnivariateGcd(ar, br); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test arbitrary recursive gcd. * */ public void testArbitraryRecursiveGCD() { di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 2, to); cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 2; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveGcd(ar, br); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test content and primitive part. * */ public void testContentPP() { dfac = new GenPolynomialRing(new BigInteger(1), 3, to); for (int i = 0; i < 3; i++) { c = dfac.random(kl * (i + 2), ll + 2 * i, el + i, q); //System.out.println("cr = " + cr); assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = ufd.content(c); e = a.extend(dfac, 0, 0L); b = ufd.primitivePart(c); //System.out.println("c = " + c); //System.out.println("a = " + a); //System.out.println("e = " + e); //System.out.println("b = " + b); d = e.multiply(b); assertEquals("c == cont(c)pp(c)", d, c); } } /** * Test gcd 3 variables. * */ public void testGCD3() { dfac = new GenPolynomialRing(new BigInteger(1), 3, to); for (int i = 0; i < 4; i++) { a = dfac.random(kl, ll, el + i, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test gcd. * */ public void testGCD() { // dfac = new GenPolynomialRing(new BigInteger(1),3,to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b " + e, e.isZERO()); } } /** * Test gcd field coefficients. * */ public void testGCDfield() { GenPolynomialRing dfac; dfac = new GenPolynomialRing(new BigRational(1), 3, to); GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); GenPolynomial a, b, c, d, e; for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test lcm. * */ public void testLCM() { dfac = new GenPolynomialRing(new BigInteger(1), 3, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( a" + i + " ) <> 0", a.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); c = ufd.gcd(a, b); //System.out.println("c = " + c); d = ufd.lcm(a, b); //System.out.println("d = " + d); e = c.multiply(d); //System.out.println("e = " + e); c = a.multiply(b); //System.out.println("c = " + c); assertEquals("ab == gcd(a,b)lcm(ab)", c, e); } } /** * Test co-prime factors. * */ public void testCoPrime() { dfac = new GenPolynomialRing(new BigInteger(1), 3, to); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } assertTrue("length( a ) <> 0", a.length() > 0); d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); e = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); List> F = new ArrayList>(5); F.add(d); F.add(a); F.add(b); F.add(c); F.add(e); List> P = ufd.coPrime(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); //P = ufd.coPrimeSquarefree(F); //System.out.println("F = " + F); //System.out.println("P = " + P); //assertTrue("is co-prime ", ufd.isCoPrime(P) ); //assertTrue("is co-prime of ", ufd.isCoPrime(P,F) ); P = ufd.coPrimeRec(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); } } jas-2.5/trc/edu/jas/ufd/GCDSimpleTest.java0000644000175000017500000003363311677401354020535 0ustar giovannigiovanni/* * $Id: GCDSimpleTest.java 3850 2011-12-30 18:29:00Z kredel $ */ package edu.jas.ufd; //import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GCD Simple PRS algorithm tests with JUnit. * @author Heinz Kredel. */ public class GCDSimpleTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDSimpleTest object. * @param name String. */ public GCDSimpleTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDSimpleTest.class); return suite; } GreatestCommonDivisorAbstract ufd; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 5; int kl = 4; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd = new GreatestCommonDivisorSimple(); dfac = new GenPolynomialRing(new BigInteger(1), rl, to); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd = null; dfac = null; cfac = null; rfac = null; } /** * Test base gcd simple. */ public void testBaseGcdSimple() { dfac = new GenPolynomialRing(new BigInteger(1), 1, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 2, q); c = dfac.random(kl * (i + 2), ll + 2, el + 2, q); c = c.multiply(cfac.univariate(0)); if (c.isZERO()) { // skip for this turn continue; } //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); c = ufd.basePrimitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); d = ufd.baseGcd(a, b); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); //System.out.println("c = " + c); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a" + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b" + e, e.isZERO()); } } /** * Test recursive gcd simple. */ public void testRecursiveGCDSimple() { di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 2, to); cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); //kl = 3; ll = 2; for (int i = 0; i < 3; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); cr = ufd.recursivePrimitivePart(cr).abs(); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveUnivariateGcd(ar, br); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); er = PolyUtil. recursivePseudoRemainder(ar, dr); //System.out.println("er = " + er); assertTrue("gcd(a,b) | a" + er, er.isZERO()); er = PolyUtil. recursivePseudoRemainder(br, dr); //System.out.println("er = " + er); assertTrue("gcd(a,b) | b" + er, er.isZERO()); } } /** * Test arbitrary recursive gcd simple. */ public void testArbitraryRecursiveGCDSimple() { di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 2, to); cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); //kl = 3; ll = 2; for (int i = 0; i < 3; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); cr = ufd.recursivePrimitivePart(cr).abs(); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveGcd(ar, br); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); er = PolyUtil. recursivePseudoRemainder(ar, dr); //System.out.println("er = " + er); assertTrue("gcd(a,b) | a" + er, er.isZERO()); er = PolyUtil. recursivePseudoRemainder(br, dr); //System.out.println("er = " + er); assertTrue("gcd(a,b) | b" + er, er.isZERO()); } } /** * Test gcd simple. */ public void testGCDSimple() { dfac = new GenPolynomialRing(new BigInteger(1), 4, to); for (int i = 0; i < 2; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); c = c.multiply(dfac.univariate(0)); c = ufd.primitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); d = ufd.gcd(a, b); //System.out.println("c = " + c); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b " + e, e.isZERO()); } } /** * Test base resultant integral coefficients. */ public void testBaseResultant() { dfac = new GenPolynomialRing(new BigInteger(1), 1, to); GreatestCommonDivisorSimple ufds = new GreatestCommonDivisorSimple(); GreatestCommonDivisorSubres sres = new GreatestCommonDivisorSubres(); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el + 3 + i, q); b = dfac.random(kl, ll, el + 3 + i, q); c = dfac.random(kl, ll, el + 3 + i, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } if (c.isConstant()) { c = dfac.univariate(0,1); } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); d = ufds.baseResultant(a, b); //System.out.println("d = " + d); e = sres.baseResultant(a, b); //System.out.println("e = " + e); assertEquals("d == e: " + d.subtract(e), d.abs().signum(), e.abs().signum() ); //assertEquals("d == e: " + d.subtract(e), d, e); GenPolynomial ac = a.multiply(c); GenPolynomial bc = b.multiply(c); //System.out.println("ac = " + ac); //System.out.println("bc = " + bc); d = ufds.baseResultant(ac, bc); //System.out.println("d = " + d); assertTrue("d == 0: " + d, d.isZERO()); e = sres.baseResultant(ac, bc); //System.out.println("e = " + e); assertTrue("e == 0: " + e, e.isZERO()); } } /** * Test recursive resultant simple. */ public void testRecursiveResultantSimple() { di = new BigInteger(1); dfac = new GenPolynomialRing(new BigInteger(1), 2, to); cfac = new GenPolynomialRing(new BigInteger(1), 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); GreatestCommonDivisorSimple ufds = new GreatestCommonDivisorSimple(); GreatestCommonDivisorSubres sres = new GreatestCommonDivisorSubres(); //kl = 3; ll = 2; for (int i = 0; i < 1; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); cr = ufd.recursivePrimitivePart(cr).abs(); //System.out.println("ar = " + ar); //System.out.println("br = " + br); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } if (cr.isConstant()) { cr = rfac.univariate(0,1); } //System.out.println("cr = " + cr); assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); dr = ufds.recursiveUnivariateResultant(ar, br); //System.out.println("dr = " + dr); er = sres.recursiveUnivariateResultant(ar, br); //System.out.println("er = " + er); assertEquals("dr == er: " + dr.subtract(er), dr.abs().signum(), er.abs().signum()); //assertEquals("dr == er: " + dr.subtract(er), dr, er); GenPolynomial> arc = ar.multiply(cr); GenPolynomial> brc = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufds.recursiveUnivariateResultant(arc, brc); //System.out.println("dr = " + dr); //assertTrue("dr == 0: " + dr, dr.isZERO()); er = sres.recursiveUnivariateResultant(arc, brc); //System.out.println("er = " + er); //assertTrue("er == 0: " + er, er.isZERO()); assertEquals("dr == er: " + dr.subtract(er), dr.signum(), er.signum()); } } } jas-2.5/trc/edu/jas/ufd/GCDModularTest.java0000644000175000017500000006066111677052522020707 0ustar giovannigiovanni/* * $Id: GCDModularTest.java 3843 2011-12-29 11:56:02Z kredel $ */ package edu.jas.ufd; //import java.util.Map; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.PrimeList; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GCD Modular algorithm tests with JUnit. * @author Heinz Kredel. */ public class GCDModularTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDModularTest object. * @param name String. */ public GCDModularTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDModularTest.class); return suite; } GreatestCommonDivisorAbstract ufd; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; PrimeList primes = new PrimeList(); ModIntegerRing mi; ModInteger ai; ModInteger bi; ModInteger ci; ModInteger di; ModInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial ac; GenPolynomial bc; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; GenPolynomial> arc; GenPolynomial> brc; int rl = 5; int kl = 4; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; //mi = new ModIntegerRing(primes.get(0), true); mi = new ModIntegerRing(19L, true); ufd = new GreatestCommonDivisorPrimitive(); dfac = new GenPolynomialRing(mi, rl, to); cfac = new GenPolynomialRing(mi, rl - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; ufd = null; dfac = null; cfac = null; rfac = null; } /** * Test modular algorithm gcd with modular evaluation recursive algorithm. */ public void testModularEvaluationGcd() { GreatestCommonDivisorAbstract ufd_m = new GreatestCommonDivisorModular(/*false*/); GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomialRing dfac = new GenPolynomialRing(new BigInteger(), 3, to); for (int i = 0; i < 2; i++) { a = dfac.random(kl, ll + i, el + i, q); b = dfac.random(kl, ll + i, el + i, q); c = dfac.random(kl, ll + i, el + i, q); c = c.multiply(dfac.univariate(0)); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd_m.gcd(a, b); c = ufd.basePrimitivePart(c).abs(); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a" + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b" + e, e.isZERO()); } } /** * Test modular algorithm gcd with simple PRS recursive algorithm. */ public void testModularSimpleGcd() { GreatestCommonDivisorAbstract ufd_m = new GreatestCommonDivisorModular(true); GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomialRing dfac = new GenPolynomialRing(new BigInteger(), 3, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll + i, el + i, q); b = dfac.random(kl, ll + i, el + i, q); c = dfac.random(kl, ll + i, el + i, q); c = c.multiply(dfac.univariate(0)); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd_m.gcd(a, b); c = ufd.basePrimitivePart(c).abs(); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a" + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b" + e, e.isZERO()); } } /** * Test recursive content and primitive part, modular coefficients. */ public void testRecursiveContentPPmodular() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); for (int i = 0; i < 1; i++) { a = cfac.random(kl, ll + 2 * i, el + i, q).monic(); cr = rfac.random(kl * (i + 2), ll + 2 * i, el + i, q); cr = PolyUtil. monic(cr); //System.out.println("a = " + a); //System.out.println("cr = " + cr); //a = ufd.basePrimitivePart(a); //b = distribute(dfac,cr); //b = ufd.basePrimitivePart(b); //cr = recursive(rfac,b); //System.out.println("a = " + a); //System.out.println("cr = " + cr); cr = cr.multiply(a); //System.out.println("cr = " + cr); if (cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); c = ufd.recursiveContent(cr).monic(); dr = ufd.recursivePrimitivePart(cr); dr = PolyUtil. monic(dr); //System.out.println("c = " + c); //System.out.println("dr = " + dr); //System.out.println("monic(a) = " + a.monic()); //System.out.println("monic(c) = " + c.monic()); ar = dr.multiply(c); //System.out.println("ar = " + ar); assertEquals("c == cont(c)pp(c)", cr, ar); } } /** * Test base gcd modular coefficients. */ public void testGCDbaseModular() { dfac = new GenPolynomialRing(mi, 1, to); GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el + 3 + i, q).monic(); b = dfac.random(kl, ll, el + 3 + i, q).monic(); c = dfac.random(kl, ll, el + 3 + i, q).monic(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ac = a.multiply(c); bc = b.multiply(c); //System.out.println("ac = " + ac); //System.out.println("bc = " + bc); //e = PolyUtil.basePseudoRemainder(ac,c); //System.out.println("ac/c a = 0 " + e); //assertTrue("ac/c-a != 0 " + e, e.isZERO() ); //e = PolyUtil.basePseudoRemainder(bc,c); //System.out.println("bc/c-b = 0 " + e); //assertTrue("bc/c-b != 0 " + e, e.isZERO() ); d = ufd.baseGcd(ac, bc); d = d.monic(); // not required //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test recursive gcd modular coefficients. */ public void testRecursiveGCDModular() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); // GreatestCommonDivisorAbstract ufd // = new GreatestCommonDivisorPrimitive(); for (int i = 0; i < 1; i++) { ar = rfac.random(kl, 2, el + 2, q); br = rfac.random(kl, 2, el + 2, q); cr = rfac.random(kl, 2, el + 2, q); ar = PolyUtil. monic(ar); br = PolyUtil. monic(br); cr = PolyUtil. monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); arc = ar.multiply(cr); brc = br.multiply(cr); //System.out.println("arc = " + arc); //System.out.println("brc = " + brc); //er = PolyUtil.recursivePseudoRemainder(arc,cr); //System.out.println("ac/c-a = 0 " + er); //assertTrue("ac/c-a != 0 " + er, er.isZERO() ); //er = PolyUtil.recursivePseudoRemainder(brc,cr); //System.out.println("bc/c-b = 0 " + er); //assertTrue("bc/c-b != 0 " + er, er.isZERO() ); dr = ufd.recursiveUnivariateGcd(arc, brc); dr = PolyUtil. monic(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test arbitrary recursive gcd modular coefficients. */ public void testArbitraryRecursiveGCDModular() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); // GreatestCommonDivisorAbstract ufd // = new GreatestCommonDivisorPrimitive(); for (int i = 0; i < 1; i++) { ar = rfac.random(kl, 2, el + 2, q); br = rfac.random(kl, 2, el + 2, q); cr = rfac.random(kl, 2, el + 2, q); ar = PolyUtil. monic(ar); br = PolyUtil. monic(br); cr = PolyUtil. monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); arc = ar.multiply(cr); brc = br.multiply(cr); //System.out.println("arc = " + arc); //System.out.println("brc = " + brc); //er = PolyUtil.recursivePseudoRemainder(arc,cr); //System.out.println("ac/c-a = 0 " + er); //assertTrue("ac/c-a != 0 " + er, er.isZERO() ); //er = PolyUtil.recursivePseudoRemainder(brc,cr); //System.out.println("bc/c-b = 0 " + er); //assertTrue("bc/c-b != 0 " + er, er.isZERO() ); dr = ufd.recursiveGcd(arc, brc); dr = PolyUtil. monic(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test gcd modular coefficients. */ public void testGcdModular() { dfac = new GenPolynomialRing(mi, 4, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el + i, q).monic(); b = dfac.random(kl, ll, el + i, q).monic(); c = dfac.random(kl, ll, el + i, q).monic(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ac = a.multiply(c); bc = b.multiply(c); //System.out.println("ac = " + ac); //System.out.println("bc = " + bc); //e = PolyUtil.basePseudoRemainder(ac,c); //System.out.println("ac/c-a = 0 " + e); //assertTrue("ac/c-a != 0 " + e, e.isZERO() ); //e = PolyUtil.basePseudoRemainder(bc,c); //System.out.println("bc/c-b = 0 " + e); //assertTrue("bc/c-b != 0 " + e, e.isZERO() ); d = ufd.gcd(ac, bc); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); //System.out.println("c = " + c); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(ac, d); //System.out.println("gcd(ac,bc) | ac " + e); assertTrue("gcd(ac,bc) | ac " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(bc, d); //System.out.println("gcd(ac,bc) | bc " + e); assertTrue("gcd(ac,bc) | bc " + e, e.isZERO()); } } /** * Test co-prime factors. */ public void testCoPrime() { dfac = new GenPolynomialRing(mi, 3, to); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } assertTrue("length( a ) <> 0", a.length() > 0); d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); e = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); List> F = new ArrayList>(5); F.add(a); F.add(b); F.add(c); F.add(d); F.add(e); List> P = ufd.coPrime(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); P = ufd.coPrimeRec(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); } /** * Test base resultant modular coefficients. */ public void testResultantBaseModular() { dfac = new GenPolynomialRing(mi, 1, to); GreatestCommonDivisorSimple ufds = new GreatestCommonDivisorSimple(); GreatestCommonDivisorSubres sres = new GreatestCommonDivisorSubres(); for (int i = 0; i < 3; i++) { a = dfac.random(kl, ll, el + 3 + i, q).monic(); b = dfac.random(kl, ll, el + 3 + i, q).monic(); c = dfac.random(kl, ll, el + 3 + i, q).monic(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } if (c.isConstant()) { c = dfac.univariate(0,1); } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); d = ufds.baseResultant(a, b); //System.out.println("d = " + d); e = sres.baseResultant(a, b); //System.out.println("e = " + e); assertEquals("d == e: " + d.subtract(e), d.signum(), e.signum()); //assertEquals("d == e: " + d.subtract(e), d, e); ac = a.multiply(c); bc = b.multiply(c); //System.out.println("ac = " + ac); //System.out.println("bc = " + bc); d = ufds.baseResultant(ac, bc); //System.out.println("d = " + d); assertTrue("d == 0: " + d, d.isZERO()); e = sres.baseResultant(ac, bc); //System.out.println("e = " + e); assertTrue("e == 0: " + e, e.isZERO()); //assertEquals("d == e: " + d.subtract(e), d, e); } } /** * Test recursive resultant modular coefficients. */ public void testRecursiveResultantModular() { cfac = new GenPolynomialRing(mi, 2 - 0, to); rfac = new GenPolynomialRing>(cfac, 1, to); //System.out.println("rfac = " + rfac); GreatestCommonDivisorSimple ufds = new GreatestCommonDivisorSimple(); GreatestCommonDivisorSubres sres = new GreatestCommonDivisorSubres(); for (int i = 0; i < 1; i++) { ar = rfac.random(kl, 2, el + 2, q); br = rfac.random(kl, 2, el + 3, q); cr = rfac.random(kl, 2, el + 1, q); ar = PolyUtil. monic(ar); br = PolyUtil. monic(br); cr = PolyUtil. monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } if (cr.isConstant()) { cr = rfac.univariate(0,1); } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); dr = ufds.recursiveUnivariateResultant(ar, br); //System.out.println("dr = " + dr); er = sres.recursiveUnivariateResultant(ar, br); //System.out.println("er = " + er); assertEquals("dr == er: " + dr.subtract(er), dr.signum(), er.signum()); //assertEquals("dr == er: " + dr.subtract(er), dr, er); arc = ar.multiply(cr); brc = br.multiply(cr); //System.out.println("arc = " + arc); //System.out.println("brc = " + brc); dr = ufds.recursiveUnivariateResultant(arc, brc); //System.out.println("dr = " + dr); //assertTrue("dr == 0: " + dr, dr.isZERO()); er = sres.recursiveUnivariateResultant(arc, brc); //System.out.println("er = " + er); //assertTrue("er == 0: " + er, er.isZERO()); assertEquals("dr == er: " + dr.subtract(er), dr.signum(), er.signum()); } } /** * Test resultant modular coefficients. */ public void testResultantModular() { dfac = new GenPolynomialRing(mi, 4, to); //System.out.println("dfac = " + dfac); GreatestCommonDivisorSimple ufds = new GreatestCommonDivisorSimple(); GreatestCommonDivisorSubres sres = new GreatestCommonDivisorSubres(); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el + i, q).monic(); b = dfac.random(kl, ll, el + i, q).monic(); c = dfac.random(kl, ll, el + i, q).monic(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } if (c.isConstant()) { c = dfac.univariate(0,1); } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); d = ufds.resultant(a, b); //System.out.println("d = " + d); e = sres.resultant(a, b); //System.out.println("e = " + e); assertEquals("d == e: " + d.subtract(e), d.signum(), e.signum()); //assertEquals("d == e: " + d.subtract(e), d, e); ac = a.multiply(c); bc = b.multiply(c); //System.out.println("ac = " + ac); //System.out.println("bc = " + bc); d = ufds.resultant(ac, bc); //System.out.println("d = " + d); //assertTrue("d == 0: " + d, d.isZERO()); e = sres.resultant(ac, bc); //System.out.println("e = " + e); //assertTrue("e == 0: " + e, e.isZERO()); assertEquals("d == e: " + d.subtract(e), d.signum(), e.signum()); } } } jas-2.5/trc/edu/jas/ufd/FactorTest.java0000644000175000017500000002760512004743356020202 0ustar giovannigiovanni/* * $Id: FactorTest.java 4076 2012-07-28 11:03:10Z kredel $ */ package edu.jas.ufd; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.structure.RingFactory; /** * Factor tests with JUnit. * @see edu.jas.application.FactorTest * @author Heinz Kredel. */ public class FactorTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorTest object. * @param name String. */ public FactorTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. * */ public void testDummy() { } /** * Test factory. * */ public void testFactory() { ModIntegerRing mi = new ModIntegerRing(19, true); Factorization ufdm = FactorFactory.getImplementation(mi); //System.out.println("ufdm = " + ufdm); assertTrue("ufd != Modular " + ufdm, ufdm instanceof FactorModular); ModLongRing ml = new ModLongRing(19, true); Factorization ufdml = FactorFactory.getImplementation(ml); //System.out.println("ufdml = " + ufdml); assertTrue("ufd != Modular " + ufdml, ufdml instanceof FactorModular); BigInteger bi = new BigInteger(1); Factorization ufdi = FactorFactory.getImplementation(bi); //System.out.println("ufdi = " + ufdi); assertTrue("ufd != Integer " + ufdi, ufdi instanceof FactorInteger); BigRational br = new BigRational(1); Factorization ufdr = FactorFactory.getImplementation(br); //System.out.println("ufdr = " + ufdr); assertTrue("ufd != Rational " + ufdr, ufdr instanceof FactorRational); GenPolynomialRing pmfac = new GenPolynomialRing(mi, 1); GenPolynomial pm = pmfac.univariate(0); AlgebraicNumberRing am = new AlgebraicNumberRing(pm, true); Factorization> ufdam = FactorFactory.getImplementation(am); //System.out.println("ufdam = " + ufdam); assertTrue("ufd != AlgebraicNumber " + ufdam, ufdam instanceof FactorAlgebraic); GenPolynomialRing prfac = new GenPolynomialRing(br, 1); GenPolynomial pr = prfac.univariate(0); AlgebraicNumberRing ar = new AlgebraicNumberRing(pr, true); Factorization> ufdar = FactorFactory.getImplementation(ar); //System.out.println("ufdar = " + ufdar); assertTrue("ufd != AlgebraicNumber " + ufdar, ufdar instanceof FactorAlgebraic); prfac = new GenPolynomialRing(br, 2); QuotientRing qrfac = new QuotientRing(prfac); Factorization> ufdqr = FactorFactory.getImplementation(qrfac); //System.out.println("ufdqr = " + ufdqr); assertTrue("ufd != Quotient " + ufdqr, ufdqr instanceof FactorQuotient); } /** * Test factory generic. * */ @SuppressWarnings("unchecked") public void testFactoryGeneric() { ModIntegerRing mi = new ModIntegerRing(19, true); Factorization ufdm = FactorFactory.getImplementation((RingFactory) mi); //System.out.println("ufdm = " + ufdm); assertTrue("ufd != Modular " + ufdm, ufdm instanceof FactorModular); BigInteger bi = new BigInteger(1); Factorization ufdi = FactorFactory.getImplementation((RingFactory) bi); //System.out.println("ufdi = " + ufdi); assertTrue("ufd != Integer " + ufdi, ufdi instanceof FactorInteger); BigRational br = new BigRational(1); Factorization ufdr = FactorFactory.getImplementation((RingFactory) br); //System.out.println("ufdr = " + ufdr); assertTrue("ufd != Rational " + ufdr, ufdr instanceof FactorRational); GenPolynomialRing pmfac = new GenPolynomialRing(mi, 1); GenPolynomial pm = pmfac.univariate(0); AlgebraicNumberRing am = new AlgebraicNumberRing(pm, true); Factorization> ufdam = FactorFactory.getImplementation((RingFactory) am); //System.out.println("ufdam = " + ufdam); assertTrue("ufd != AlgebraicNumber " + ufdam, ufdam instanceof FactorAlgebraic); GenPolynomialRing prfac = new GenPolynomialRing(br, 1); GenPolynomial pr = prfac.univariate(0); AlgebraicNumberRing ar = new AlgebraicNumberRing(pr, true); Factorization> ufdar = FactorFactory.getImplementation((RingFactory) ar); //System.out.println("ufdar = " + ufdar); assertTrue("ufd != AlgebraicNumber " + ufdar, ufdar instanceof FactorAlgebraic); prfac = new GenPolynomialRing(br, 2); QuotientRing qrfac = new QuotientRing(prfac); Factorization> ufdqr = FactorFactory.getImplementation((RingFactory) qrfac); //System.out.println("ufdqr = " + ufdqr); assertTrue("ufd != Quotient " + ufdqr, ufdqr instanceof FactorQuotient); pmfac = new GenPolynomialRing(mi, 1); QuotientRing qmfac = new QuotientRing(pmfac); Factorization> ufdqm = FactorFactory.getImplementation((RingFactory) qmfac); //System.out.println("ufdqm = " + ufdqm); assertTrue("ufd != Quotient " + ufdqm, ufdqm instanceof FactorQuotient); prfac = new GenPolynomialRing(br, 2); GenPolynomialRing> rrfac = new GenPolynomialRing>( prfac, 1); Factorization ufdrr = FactorFactory.getImplementation((RingFactory) rrfac); //System.out.println("ufdrr = " + ufdrr); assertTrue("ufd != GenPolynomial> " + ufdrr, ufdrr instanceof FactorRational); } /** * Test factory specific. * */ public void testFactorySpecific() { ModIntegerRing mi = new ModIntegerRing(19, true); Factorization ufdm = FactorFactory.getImplementation(mi); //System.out.println("ufdm = " + ufdm); assertTrue("ufd != Modular " + ufdm, ufdm instanceof FactorModular); BigInteger bi = new BigInteger(1); Factorization ufdi = FactorFactory.getImplementation(bi); //System.out.println("ufdi = " + ufdi); assertTrue("ufd != Integer " + ufdi, ufdi instanceof FactorInteger); BigRational br = new BigRational(1); Factorization ufdr = FactorFactory.getImplementation(br); //System.out.println("ufdr = " + ufdr); assertTrue("ufd != Rational " + ufdr, ufdr instanceof FactorRational); GenPolynomialRing pmfac = new GenPolynomialRing(mi, 1); GenPolynomial pm = pmfac.univariate(0); AlgebraicNumberRing am = new AlgebraicNumberRing(pm, true); Factorization> ufdam = FactorFactory. getImplementation(am); //System.out.println("ufdam = " + ufdam); assertTrue("ufd != AlgebraicNumber " + ufdam, ufdam instanceof FactorAlgebraic); GenPolynomialRing prfac = new GenPolynomialRing(br, 1); GenPolynomial pr = prfac.univariate(0); AlgebraicNumberRing ar = new AlgebraicNumberRing(pr, true); Factorization> ufdar = FactorFactory. getImplementation(ar); //System.out.println("ufdar = " + ufdar); assertTrue("ufd != AlgebraicNumber " + ufdar, ufdar instanceof FactorAlgebraic); prfac = new GenPolynomialRing(br, 2); QuotientRing qrfac = new QuotientRing(prfac); Factorization> ufdqr = FactorFactory. getImplementation(qrfac); //System.out.println("ufdqr = " + ufdqr); assertTrue("ufd != Quotient " + ufdqr, ufdqr instanceof FactorQuotient); pmfac = new GenPolynomialRing(mi, 1); QuotientRing qmfac = new QuotientRing(pmfac); Factorization> ufdqm = FactorFactory. getImplementation(qmfac); //System.out.println("ufdqm = " + ufdqm); assertTrue("ufd != Quotient " + ufdqm, ufdqm instanceof FactorQuotient); prfac = new GenPolynomialRing(br, 2); //GenPolynomialRing> rrfac = new GenPolynomialRing>( // prfac, 1); Factorization ufdrr = FactorFactory. getImplementation(prfac); //System.out.println("ufdrr = " + ufdrr); assertTrue("ufd != GenPolynomial> " + ufdrr, ufdrr instanceof FactorRational); } /** * Test rational absolute factorization, Rothstein-Trager step. * */ public void xtestBaseRationalAbsoluteFactorizationRoT() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); //String[] alpha = new String[] { "alpha" }; String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); GenPolynomial agen = pfac.univariate(0, 4); agen = agen.sum(pfac.fromInteger(4)); // x^4 + 4 // GenPolynomial x6 = pfac.univariate(0, 6); // GenPolynomial x4 = pfac.univariate(0, 4); // GenPolynomial x2 = pfac.univariate(0, 2); // // x^6 - 5 x^4 + 5 x^2 + 4 // agen = x6.subtract(x4.multiply(pfac.fromInteger(5))); // agen = agen.sum(x2.multiply(pfac.fromInteger(5))); // agen = agen.sum(pfac.fromInteger(4)); // GenPolynomial x3 = pfac.univariate(0, 3); // GenPolynomial x = pfac.univariate(0); // // x^3 + x // agen = x3.sum(x); GenPolynomial x2 = pfac.univariate(0, 2); // x^2 - 2 agen = x2.subtract(pfac.fromInteger(2)); GenPolynomial N = pfac.getONE(); FactorRational engine = new FactorRational(); PartialFraction F = engine.baseAlgebraicPartialFraction(N, agen); //System.out.println("\npartial fraction = " + F); assertFalse("pf not empty " + F, F.toString().length() == 0); // java-5 // TODO test for PartialFraction } } jas-2.5/trc/edu/jas/ufd/SquarefreeAlgQuotModTest.java0000644000175000017500000005312611641660762023025 0ustar giovannigiovanni/* * $Id: SquarefreeAlgQuotModTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.structure.Power; /** * Squarefree factorization tests with JUnit. * @author Heinz Kredel. */ public class SquarefreeAlgQuotModTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a SquarefreeAlgQuotModTest object. * @param name String. */ public SquarefreeAlgQuotModTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(SquarefreeAlgQuotModTest.class); return suite; } TermOrder to = new TermOrder(TermOrder.INVLEX); int rl = 3; int kl = 1; int ll = 3; int el = 3; float q = 0.25f; String[] vars; String[] cvars; String[] c1vars; String[] rvars; ModIntegerRing mfac; String[] alpha; String[] beta; GenPolynomialRing mpfac; GenPolynomial agen; QuotientRing fac; AlgebraicNumberRing> afac; SquarefreeInfiniteFieldCharP sqf; SquarefreeInfiniteAlgebraicFieldCharP> asqf; GenPolynomialRing>> dfac; GenPolynomial>> a; GenPolynomial>> b; GenPolynomial>> c; GenPolynomial>> d; GenPolynomial>> e; GenPolynomialRing>> cfac; GenPolynomialRing>>> rfac; GenPolynomial>>> ar; GenPolynomial>>> br; GenPolynomial>>> cr; GenPolynomial>>> dr; GenPolynomial>>> er; @Override protected void setUp() { vars = ExpVector.STDVARS(rl); cvars = ExpVector.STDVARS(rl - 1); c1vars = new String[] { cvars[0] }; rvars = new String[] { vars[rl - 1] }; mfac = new ModIntegerRing(7); alpha = new String[] { "u" }; beta = new String[] { "b" }; mpfac = new GenPolynomialRing(mfac, 1, to, alpha); fac = new QuotientRing(mpfac); GenPolynomialRing> qpfac = new GenPolynomialRing>(fac, 1, to, beta); // beta^2 - 3 GenPolynomial> an = qpfac.univariate(0,2L); an = an.subtract(qpfac.fromInteger(3)); afac = new AlgebraicNumberRing>(an,true); sqf = new SquarefreeInfiniteFieldCharP(fac); asqf = new SquarefreeInfiniteAlgebraicFieldCharP>(afac); SquarefreeAbstract>> sqff = SquarefreeFactory.getImplementation(afac); //System.out.println("sqf = " + sqf); //System.out.println("sqff = " + sqff); assertEquals("asqf == sqff ", asqf.getClass(), sqff.getClass()); a = b = c = d = e = null; ar = br = cr = dr = er = null; } @Override protected void tearDown() { a = b = c = d = e = null; ar = br = cr = dr = er = null; //ComputerThreads.terminate(); } /** * Test base squarefree. * */ public void testBaseSquarefree() { //System.out.println("\nbase:"); dfac = new GenPolynomialRing>>(afac, 1, to, rvars); a = dfac.random(kl + 0, ll - 1, el + 0, q); b = dfac.random(kl + 0, ll, el + 1, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); c = asqf.baseSquarefreePart(c); d = asqf.baseSquarefreePart(d); //System.out.println("d = " + d); //System.out.println("c = " + c); assertTrue("isSquarefree(c) " + c, asqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, asqf.isSquarefree(d)); e = PolyUtil.>> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbbc) " + e, e.isZERO()); } /** * Test base squarefree factors. * */ public void testBaseSquarefreeFactors() { dfac = new GenPolynomialRing>>(afac, 1, to, rvars); a = dfac.random(kl + 0, ll - 1, el + 0, q); b = dfac.random(kl + 0, ll, el + 1, q); c = dfac.random(kl, ll, el + 0, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } int num = 0; if (! a.isConstant()) { num++; } if (! b.isConstant()) { num++; } if (! c.isConstant()) { num++; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap>>, Long> sfactors; sfactors = asqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", asqf.isFactorization(d, sfactors)); assertTrue("#factors " + asqf.factorCount(sfactors) + " >= " + num + ": " + d + " = " + sfactors, asqf.factorCount(sfactors) >= num ); } /** * Test recursive squarefree. * */ public void testRecursiveSquarefree() { //System.out.println("\nrecursive:"); cfac = new GenPolynomialRing>>(afac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2+1, q); br = rfac.random(kl, 3-0, 2, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(ar).multiply(br).multiply(br); cr = ar.multiply(br); //System.out.println("dr = " + dr); //System.out.println("cr = " + cr); cr = asqf.recursiveUnivariateSquarefreePart(cr); dr = asqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("dr = " + dr); //System.out.println("cr = " + cr); assertTrue("isSquarefree(cr) " + cr, asqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, asqf.isRecursiveSquarefree(dr)); er = PolyUtil.>> recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors. * */ public void testRecursiveSquarefreeFactors() { cfac = new GenPolynomialRing>>(afac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2+1, q); br = rfac.random(kl, 3-1, 2, q); cr = rfac.random(kl, 3, 2, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); //if (ar.isZERO() || br.isZERO() || cr.isZERO()) { if (ar.isZERO() || br.isZERO()) { // skip for this turn return; } int num = 0; if (! ar.isConstant()) { num++; } if (! br.isConstant()) { num++; } //if (! cr.isConstant()) { // num++; //} //dr = ar.multiply(cr).multiply(br).multiply(br); dr = ar.multiply(br).multiply(br); //System.out.println("dr = " + dr); SortedMap>>>, Long> sfactors; sfactors = asqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); // better use factorCount assertTrue("isFactorization(d,sfactors) ", asqf.isRecursiveFactorization(dr, sfactors)); assertTrue("#factors " + sfactors.size() + " >= " + num + ": " + d + " = " + sfactors, sfactors.size() >= num ); } /** * Test squarefree. * */ public void testSquarefree() { //System.out.println("\nfull:"); dfac = new GenPolynomialRing>>(afac, rl, to, vars); a = dfac.random(kl, ll, 2, q); b = dfac.random(kl, ll - 1, 2, q); c = dfac.random(kl, ll, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); c = asqf.squarefreePart(c); d = asqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, asqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, asqf.isSquarefree(c)); e = PolyUtil.>> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbc) " + e, e.isZERO()); } /** * Test squarefree factors. * */ public void testSquarefreeFactors() { dfac = new GenPolynomialRing>>(afac, rl, to, vars); a = dfac.random(kl, 3, 2+1, q); b = dfac.random(kl, 2, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } int num = 0; if (! a.isConstant()) { num++; } if (! b.isConstant()) { num++; } if (! c.isConstant()) { num++; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap>>, Long> sfactors; sfactors = asqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", asqf.isFactorization(d, sfactors)); assertTrue("#factors " + asqf.factorCount(sfactors) + " >= " + num + ": " + d + " = " + sfactors, asqf.factorCount(sfactors) >= num ); } /* ------------char-th root ------------------------- */ /** * Test base squarefree with char-th root. * */ public void testBaseSquarefreeCharRoot() { //System.out.println("\nbase CharRoot:"); long p = fac.characteristic().longValue(); //dfac = new GenPolynomialRing(fac,1,to,rvars); dfac = new GenPolynomialRing>>(afac, 1, to, rvars); a = dfac.random(kl + 0, ll + 0, el + 1, q).monic(); b = dfac.random(kl, ll + 1, el + 1, q).monic(); c = dfac.random(kl + 0, ll, el, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply( Power.>>> positivePower(b, p) ).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = asqf.baseSquarefreePart(c); d = asqf.baseSquarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(c) " + c, asqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, asqf.isSquarefree(d)); e = PolyUtil.>> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test base squarefree factors with char-th root. * */ public void testBaseSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); //dfac = new GenPolynomialRing(fac,1,to,rvars); dfac = new GenPolynomialRing>>(afac, 1, to, rvars); a = dfac.random(kl, ll + 1, el + 1, q).monic(); b = dfac.random(kl, ll + 1, el + 2, q).monic(); c = dfac.random(kl, ll, el + 2, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply( Power.>>> positivePower(b, p) ).multiply(c); //d = d.monic(); //System.out.println("d = " + d); SortedMap>>, Long> sfactors; sfactors = asqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", asqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree with char-th root. * */ public void testRecursiveSquarefreeCharRoot() { //System.out.println("\nrecursive CharRoot:"); long p = fac.characteristic().longValue(); cfac = new GenPolynomialRing>>(afac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2 + 1, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, ll, el, q); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } ar = PolyUtil.>> monic(ar); br = PolyUtil.>> monic(br); cr = PolyUtil.>> monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); // a b^p c dr = ar.multiply( Power.>>>> positivePower(br, p) ).multiply(cr); cr = ar.multiply(br).multiply(cr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); cr = asqf.recursiveUnivariateSquarefreePart(cr); dr = asqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); assertTrue("isSquarefree(cr) " + cr, asqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, asqf.isRecursiveSquarefree(dr)); er = PolyUtil.>> recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors with char-th root. * */ public void testRecursiveSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); cfac = new GenPolynomialRing>>(afac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2 + 1, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, 3, 2, q); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } ar = PolyUtil.>> monic(ar); br = PolyUtil.>> monic(br); cr = PolyUtil.>> monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); // a b^p c dr = ar.multiply( Power.>>>> positivePower(br, p) ).multiply(cr); //System.out.println("dr = " + dr); SortedMap>>>, Long> sfactors; sfactors = asqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", asqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree with char-th root. * */ public void testSquarefreeCharRoot() { //System.out.println("\nfull CharRoot:"); long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing>>(afac, rl, to, vars); a = dfac.random(kl, ll, 3-1, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, ll, 3, q); if (a.isZERO() || b.isZERO() || c.isZERO() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply( Power.>>> positivePower(b, p) ).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = asqf.squarefreePart(c); d = asqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, asqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, asqf.isSquarefree(c)); e = PolyUtil.>> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test squarefree factors with char-th root. * */ public void testSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing>>(afac, rl, to, vars); a = dfac.random(kl, ll, 3-1, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, ll, 3, q); if (a.isZERO() || b.isZERO() || c.isZERO() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply( Power.>>> positivePower(b, p) ).multiply(c); //System.out.println("d = " + d); SortedMap>>, Long> sfactors; sfactors = asqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", asqf.isFactorization(d, sfactors)); } } jas-2.5/trc/edu/jas/ufd/GCDModEvalTest.java0000644000175000017500000005552411677332472020642 0ustar giovannigiovanni/* * $Id: GCDModEvalTest.java 3847 2011-12-30 12:57:31Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.PrimeList; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GCD Modular Evaluation algorithm tests with JUnit. * @author Heinz Kredel. */ public class GCDModEvalTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDModEvalTest object. * @param name String. */ public GCDModEvalTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDModEvalTest.class); return suite; } GreatestCommonDivisorAbstract ufd; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; PrimeList primes = new PrimeList(); ModIntegerRing mi; ModInteger ai; ModInteger bi; ModInteger ci; ModInteger di; ModInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 3; int kl = 4; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; //mi = new ModIntegerRing(primes.get(0),true); mi = new ModIntegerRing(19, true); //mi = new ModIntegerRing(19*17,true); // failing tests //mi = new ModIntegerRing(primes.get(0).multiply(primes.get(1)),false); // failing tests //ufd = new GreatestCommonDivisorPrimitive(); ufd = new GreatestCommonDivisorModEval(); String[] vars = ExpVector.STDVARS(rl); String[] cvars = ExpVector.STDVARS(rl - 1); String[] rvars = new String[] { vars[rl - 1] }; dfac = new GenPolynomialRing(mi, rl, to, vars); cfac = new GenPolynomialRing(mi, rl - 1, to, cvars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); //System.out.println("mi = " + mi); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; mi = null; ufd = null; dfac = null; cfac = null; rfac = null; } /** * Test modular evaluation gcd. */ public void testModEvalGcd() { //GreatestCommonDivisorAbstract ufd_me // = new GreatestCommonDivisorModEval(); for (int i = 0; i < 1; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 0 * i, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 0 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 0 * i, q); c = c.multiply(dfac.univariate(0)); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); c = ufd.basePrimitivePart(c).abs(); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a" + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b" + e, e.isZERO()); } } /** * Test base quotioent and remainder. */ public void testBaseQR() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a).abs(); //c = ufd.basePrimitivePart(c); do { ci = mi.random(kl * (i + 2)); ci = ci.sum(mi.getONE()); } while (ci.isZERO()); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("ci = " + ci); if (a.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); b = a.multiply(c); //System.out.println("b = " + b); d = PolyUtil. basePseudoRemainder(b, c); //System.out.println("d = " + d); assertTrue("rem(ac,c) == 0", d.isZERO()); b = a.multiply(ci); //System.out.println("b = " + b); d = b.divide(ci); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); b = a.multiply(c); //System.out.println("b = " + b); d = PolyUtil. basePseudoDivide(b, c); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); } } /** * Test base content and primitive part. */ public void testBaseContentPP() { for (int i = 0; i < 13; i++) { c = dfac.random(kl * (i + 2), ll + 2 * i, el + i, q); c = c.multiply(mi.random(kl * (i + 2))); if (c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ci = ufd.baseContent(c); d = ufd.basePrimitivePart(c); //System.out.println("c = " + c); //System.out.println("ci = " + ci); //System.out.println("d = " + d); a = d.multiply(ci); assertEquals("c == cont(c)pp(c)", c, a); } } /** * Test base gcd. */ public void testBaseGcd() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); //c = ufd.basePrimitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); d = ufd.baseGcd(a, b); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test recursive quotioent and remainder. */ public void testRecursiveQR() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 5; i++) { a = dfac.random(kl * (i + 1), ll + i, el + i, q); a = ufd.basePrimitivePart(a).abs(); c = dfac.random(kl * (i + 1), ll + i, el + i, q); c = ufd.basePrimitivePart(a).abs(); cr = PolyUtil. recursive(rfac, c); c = cfac.random(kl * (i + 1), ll + 2 * i, el + 2 * i, q); c = ufd.basePrimitivePart(c).abs(); ar = PolyUtil. recursive(rfac, a); //System.out.println("ar = " + ar); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("cr = " + cr); if (cr.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); br = ar.multiply(cr); //System.out.println("br = " + br); dr = PolyUtil. recursivePseudoRemainder(br, cr); //System.out.println("dr = " + dr); d = PolyUtil. distribute(dfac, dr); //System.out.println("d = " + d); assertTrue("rem(ac,c) == 0", d.isZERO()); br = ar.multiply(c); //System.out.println("br = " + br); dr = PolyUtil. recursiveDivide(br, c); //System.out.println("dr = " + dr); d = PolyUtil. distribute(dfac, dr); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); } } /** * Test recursive content and primitive part. */ public void testRecursiveContentPP() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 3; i++) { cr = rfac.random(kl * (i + 2), ll + 2 * i, el + i, q); //System.out.println("cr = " + cr); assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); c = ufd.recursiveContent(cr); dr = ufd.recursivePrimitivePart(cr); //System.out.println("c = " + c); //System.out.println("dr = " + dr); ar = dr.multiply(c); assertEquals("c == cont(c)pp(c)", cr, ar); } } /** * Test recursive gcd. */ public void testRecursiveGCD() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 2; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveUnivariateGcd(ar, br); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test arbitrary recursive gcd. */ public void testArbitraryRecursiveGCD() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 2; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveGcd(ar, br); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test content and primitive part. */ public void testContentPP() { dfac = new GenPolynomialRing(mi, 3, to); for (int i = 0; i < 3; i++) { c = dfac.random(kl * (i + 2), ll + 2 * i, el + i, q); //System.out.println("cr = " + cr); if (c.isZERO()) { continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = ufd.content(c); e = a.extend(dfac, 0, 0L); b = ufd.primitivePart(c); //System.out.println("c = " + c); //System.out.println("a = " + a); //System.out.println("e = " + e); //System.out.println("b = " + b); d = e.multiply(b); assertEquals("c == cont(c)pp(c)", d, c); } } /** * Test gcd 3 variables. */ public void testGCD3() { dfac = new GenPolynomialRing(mi, 3, to); for (int i = 0; i < 4; i++) { a = dfac.random(kl, ll, el + i, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test gcd. */ public void testGCD() { // dfac = new GenPolynomialRing(mi,3,to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b " + e, e.isZERO()); } } /** * Test lcm. */ public void testLCM() { dfac = new GenPolynomialRing(mi, 3, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( a" + i + " ) <> 0", a.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); c = ufd.gcd(a, b); //System.out.println("c = " + c); d = ufd.lcm(a, b); //System.out.println("d = " + d); e = c.multiply(d); //System.out.println("e = " + e); c = a.multiply(b); //System.out.println("c = " + c); assertEquals("ab == gcd(a,b)lcm(ab)", c, e); } } /** * Test co-prime factors. */ public void testCoPrime() { dfac = new GenPolynomialRing(mi, 3, to); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } assertTrue("length( a ) <> 0", a.length() > 0); d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); e = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); List> F = new ArrayList>(5); F.add(d); F.add(a); F.add(b); F.add(c); F.add(e); //System.out.println("F = " + F); List> P = ufd.coPrime(F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); //P = ufd.coPrimeSquarefree(F); //System.out.println("F = " + F); //System.out.println("P = " + P); //assertTrue("is co-prime ", ufd.isCoPrime(P) ); //assertTrue("is co-prime of ", ufd.isCoPrime(P,F) ); P = ufd.coPrimeRec(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); } /** * Test resultant. */ public void testResultant() { mi = new ModIntegerRing(163, true); dfac = new GenPolynomialRing(mi,3,to); //System.out.println("dfac = " + dfac); GreatestCommonDivisorAbstract ufdm = new GreatestCommonDivisorModEval(); GreatestCommonDivisorSubres ufds = new GreatestCommonDivisorSubres(); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } if (c.isConstant()) { c = dfac.univariate(0,1); } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); d = ufdm.resultant(a, b); //System.out.println("d = " + d); e = ufds.resultant(a, b); //System.out.println("e = " + e); assertEquals("d == e: " + d.subtract(e), d.abs().signum(), e.abs().signum()); //assertEquals("d == e: " + d.subtract(e), d, e); //System.out.println("c = " + c); GenPolynomial ac = a.multiply(c); GenPolynomial bc = b.multiply(c); //System.out.println("ac = " + ac); //System.out.println("bc = " + bc); d = ufdm.resultant(ac, bc); //System.out.println("d = " + d); //assertTrue("d == 0: " + d, d.isZERO()); e = ufds.resultant(ac, bc); //System.out.println("e = " + e); //assertTrue("e == 0: " + e, e.isZERO()); assertEquals("d == e: " + d.subtract(e), d.abs().signum(), e.abs().signum()); } } } jas-2.5/trc/edu/jas/ufd/QuotientIntTest.java0000644000175000017500000001321111641660762021240 0ustar giovannigiovanni /* * $Id: QuotientIntTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; //import org.apache.log4j.Logger; //import edu.jas.arith.BigRational; import edu.jas.arith.BigInteger; import edu.jas.kern.PrettyPrint; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Quotient over BigInteger GenPolynomial tests with JUnit. * @author Heinz Kredel. */ public class QuotientIntTest extends TestCase { /** * main. */ public static void main (String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run( suite() ); } /** * Constructs a QuotientIntTest object. * @param name String. */ public QuotientIntTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(QuotientIntTest.class); return suite; } //private final static int bitlen = 100; QuotientRing efac; GenPolynomialRing mfac; Quotient< BigInteger > a; Quotient< BigInteger > b; Quotient< BigInteger > c; Quotient< BigInteger > d; Quotient< BigInteger > e; int rl = 3; int kl = 5; int ll = 4; //6; int el = 2; float q = 0.4f; protected void setUp() { a = b = c = d = e = null; BigInteger cfac = new BigInteger(1); TermOrder to = new TermOrder( TermOrder.INVLEX ); mfac = new GenPolynomialRing( cfac, rl, to ); efac = new QuotientRing( mfac ); } protected void tearDown() { a = b = c = d = e = null; //efac.terminate(); efac = null; ComputerThreads.terminate(); } /** * Test constructor and toString. * */ public void testConstruction() { c = efac.getONE(); //System.out.println("c = " + c); //System.out.println("c.val = " + c.val); assertTrue("length( c ) = 1", c.num.length() == 1); assertTrue("isZERO( c )", !c.isZERO() ); assertTrue("isONE( c )", c.isONE() ); d = efac.getZERO(); //System.out.println("d = " + d); //System.out.println("d.val = " + d.val); assertTrue("length( d ) = 0", d.num.length() == 0); assertTrue("isZERO( d )", d.isZERO() ); assertTrue("isONE( d )", !d.isONE() ); } /** * Test random polynomial. * */ public void testRandom() { for (int i = 0; i < 7; i++) { //a = efac.random(ll+i); a = efac.random(kl*(i+1), ll+2+2*i, el, q ); //System.out.println("a = " + a); if ( a.isZERO() || a.isONE() ) { continue; } assertTrue("length( a"+i+" ) <> 0", a.num.length() >= 0); assertTrue(" not isZERO( a"+i+" )", !a.isZERO() ); assertTrue(" not isONE( a"+i+" )", !a.isONE() ); } } /** * Test addition. * */ public void testAddition() { a = efac.random(kl,ll,el,q); b = efac.random(kl,ll,el,q); //System.out.println("a = " + a); //System.out.println("b = " + b); c = a.sum(b); d = c.subtract(b); assertEquals("a+b-b = a",a,d); c = a.sum(b); d = b.sum(a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertEquals("a+b = b+a",c,d); c = efac.random(kl,ll,el,q); d = c.sum( a.sum(b) ); e = c.sum( a ).sum(b); assertEquals("c+(a+b) = (c+a)+b",d,e); c = a.sum( efac.getZERO() ); d = a.subtract( efac.getZERO() ); assertEquals("a+0 = a-0",c,d); c = efac.getZERO().sum( a ); d = efac.getZERO().subtract( a.negate() ); assertEquals("0+a = 0+(-a)",c,d); } /** * Test object multiplication. * */ public void testMultiplication() { a = efac.random(kl,ll,el,q); //assertTrue("not isZERO( a )", !a.isZERO() ); b = efac.random(kl,ll,el,q); //assertTrue("not isZERO( b )", !b.isZERO() ); c = b.multiply(a); d = a.multiply(b); if ( !a.isZERO() && !b.isZERO() ) { assertTrue("not isZERO( c )", !c.isZERO() ); assertTrue("not isZERO( d )", !d.isZERO() ); } //System.out.println("a = " + a); //System.out.println("b = " + b); e = d.subtract(c); assertTrue("isZERO( a*b-b*a ) " + e, e.isZERO() ); assertTrue("a*b = b*a", c.equals(d) ); assertEquals("a*b = b*a",c,d); c = efac.random(kl,ll,el,q); //System.out.println("c = " + c); d = a.multiply( b.multiply(c) ); e = (a.multiply(b)).multiply(c); //System.out.println("d = " + d); //System.out.println("e = " + e); //System.out.println("d-e = " + d.subtract(c) ); assertEquals("a(bc) = (ab)c",d,e); assertTrue("a(bc) = (ab)c", d.equals(e) ); c = a.multiply( efac.getONE() ); d = efac.getONE().multiply( a ); assertEquals("a*1 = 1*a",c,d); if ( a.isUnit() ) { c = a.inverse(); d = c.multiply(a); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("a*1/a = 1",d.isONE()); } } /** * Test parse(). * */ public void testParse() { a = efac.random(kl*2,ll*2,el*2,q*2); //assertTrue("not isZERO( a )", !a.isZERO() ); //PrettyPrint.setInternal(); //System.out.println("a = " + a); PrettyPrint.setPretty(); //System.out.println("a = " + a); String p = a.toString(); //System.out.println("p = " + p); b = efac.parse(p); //System.out.println("b = " + b); //c = a.subtract(b); //System.out.println("c = " + c); assertEquals("parse(a.toSting()) = a",a,b); } } jas-2.5/trc/edu/jas/ufd/SquarefreeAlgModTest.java0000644000175000017500000005635612003043360022142 0ustar giovannigiovanni/* * $Id: SquarefreeAlgModTest.java 4019 2012-07-22 18:31:13Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.structure.Power; /** * Squarefree factorization tests with JUnit. * @author Heinz Kredel. */ public class SquarefreeAlgModTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a SquarefreeAlgModTest object. * @param name String. */ public SquarefreeAlgModTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(SquarefreeAlgModTest.class); return suite; } TermOrder to = new TermOrder(TermOrder.INVLEX); //long p = 11L; long p = 7L; long qp; int rl = 3; int kl = 3; int ll = 4; int el = 3; float q = 0.25f; String[] vars; String[] cvars; String[] c1vars; String[] rvars; ModIntegerRing mfac; String[] alpha; GenPolynomialRing mpfac; GenPolynomial agen; AlgebraicNumberRing fac; GreatestCommonDivisorAbstract> ufd; SquarefreeFiniteFieldCharP> sqf; GenPolynomialRing> dfac; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; GenPolynomial> d; GenPolynomial> e; GenPolynomialRing> cfac; GenPolynomialRing>> rfac; GenPolynomial>> ar; GenPolynomial>> br; GenPolynomial>> cr; GenPolynomial>> dr; GenPolynomial>> er; @Override protected void setUp() { vars = ExpVector.STDVARS(rl); cvars = ExpVector.STDVARS(rl - 1); c1vars = new String[] { cvars[0] }; rvars = new String[] { vars[rl - 1] }; mfac = new ModIntegerRing(p); alpha = new String[] { "alpha" }; mpfac = new GenPolynomialRing(mfac, 1, to, alpha); agen = mpfac.univariate(0, 2); agen = agen.sum(mpfac.getONE()); // x^2 + 1, is irred mod 7, 11, 19 fac = new AlgebraicNumberRing(agen, true); qp = 1L; for (int i = 0; i < agen.degree(0); i++) { qp = qp * p; } //System.out.println("p = " + p + ", qp = " + qp); //ufd = new GreatestCommonDivisorSubres>(); //ufd = GCDFactory.> getImplementation(fac); ufd = GCDFactory.> getProxy(fac); sqf = new SquarefreeFiniteFieldCharP>(fac); SquarefreeAbstract> sqff = SquarefreeFactory.getImplementation(fac); //System.out.println("sqf = " + sqf); //System.out.println("sqff = " + sqff); assertEquals("sqf == sqff ", sqf.getClass(), sqff.getClass()); a = b = c = d = e = null; ar = br = cr = dr = er = null; } @Override protected void tearDown() { a = b = c = d = e = null; ar = br = cr = dr = er = null; //ComputerThreads.terminate(); } /** * Test base squarefree. * */ public void testBaseSquarefree() { //System.out.println("\nbase:"); dfac = new GenPolynomialRing>(fac, 1, to, rvars); a = dfac.random(kl, ll, el + 2, q); b = dfac.random(kl, ll, el + 2, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil.> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbbc) " + e, e.isZERO()); } /** * Test base squarefree factors. * */ public void testBaseSquarefreeFactors() { dfac = new GenPolynomialRing>(fac, 1, to, rvars); a = dfac.random(kl, ll, el + 3, q); b = dfac.random(kl, ll, el + 3, q); c = dfac.random(kl, ll, el + 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap>, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree. * */ public void testRecursiveSquarefree() { //System.out.println("\nrecursive:"); cfac = new GenPolynomialRing>(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>(cfac, 1, to, rvars); ar = rfac.random(kl, ll, el, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(ar).multiply(br).multiply(br); cr = ar.multiply(br); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); cr = sqf.recursiveUnivariateSquarefreePart(cr); dr = sqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); assertTrue("isSquarefree(cr) " + cr, sqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, sqf.isRecursiveSquarefree(dr)); er = PolyUtil.> recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors. * */ public void testRecursiveSquarefreeFactors() { cfac = new GenPolynomialRing>(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, 3, 2, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(cr).multiply(br).multiply(br); //System.out.println("dr = " + dr); SortedMap>>, Long> sfactors; sfactors = sqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree. * */ public void testSquarefree() { //System.out.println("\nfull:"); dfac = new GenPolynomialRing>(fac, rl, to, vars); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.squarefreePart(c); d = sqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); e = PolyUtil.> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbc) " + e, e.isZERO()); } /** * Test squarefree factors. * */ public void testSquarefreeFactors() { dfac = new GenPolynomialRing>(fac, rl, to, vars); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap>, Long> sfactors; sfactors = sqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /* ------------char-th root ------------------------- */ /** * Test base squarefree with char-th root. * */ public void testBaseSquarefreeCharRoot() { //System.out.println("\nbase CharRoot:"); long p = fac.characteristic().longValue(); //dfac = new GenPolynomialRing(fac,1,to,rvars); dfac = new GenPolynomialRing>(fac, 1, to, rvars); a = dfac.random(kl, ll + 1, el + 1, q).monic(); b = dfac.random(kl, ll + 1, el + 1, q).monic(); c = dfac.random(kl, ll, el, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); e = Power.>> positivePower(b, p); //System.out.println("b^p = " + e); // a a b^p c d = a.multiply(a).multiply(e).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil.> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test base squarefree factors with char-th root. * */ public void testBaseSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); //dfac = new GenPolynomialRing(fac,1,to,rvars); dfac = new GenPolynomialRing>(fac, 1, to, rvars); a = dfac.random(kl, ll + 1, el + 2, q).monic(); b = dfac.random(kl, ll + 1, el + 2, q).monic(); c = dfac.random(kl, ll, el + 1, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); e = Power.>> positivePower(b, p); //System.out.println("b^p = " + e); // a a b^p d = a.multiply(a).multiply(e); //d = d.monic(); //System.out.println("d = " + d); SortedMap>, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test base squarefree with char-th root, two times. * */ public void testBaseSquarefreeCharRoot2() { //System.out.println("\nbase CharRoot 2:"); //long p = fac.characteristic().longValue(); //dfac = new GenPolynomialRing(fac,1,to,rvars); dfac = new GenPolynomialRing>(fac, 1, to, rvars); a = dfac.random(kl, ll + 1, el + 1, q).monic(); b = dfac.random(kl, ll + 1, el + 1, q).monic(); c = dfac.random(kl, ll, el, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); e = Power.>> positivePower(b, qp); //System.out.println("b^qp = " + e); // a a b^qp c d = a.multiply(a).multiply(e).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil.> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test base squarefree factors with char-th root, two times. * */ public void testBaseSquarefreeFactorsCharRoot2() { //long p = fac.characteristic().longValue(); //dfac = new GenPolynomialRing(fac,1,to,rvars); dfac = new GenPolynomialRing>(fac, 1, to, rvars); a = dfac.random(kl, ll + 1, el + 2, q).monic(); b = dfac.random(kl, ll + 1, el + 2, q).monic(); c = dfac.random(kl, ll, el + 2, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); e = Power.>> positivePower(b, qp); //System.out.println("b^qp = " + e); // a a b^qp d = a.multiply(a).multiply(e); //d = d.monic(); //System.out.println("d = " + d); SortedMap>, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree with char-th root. * */ public void testRecursiveSquarefreeCharRoot() { //System.out.println("\nrecursive CharRoot:"); long p = fac.characteristic().longValue(); cfac = new GenPolynomialRing>(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, el, q); br = rfac.random(kl, 3, el, q); cr = rfac.random(kl, 3, el, q); //cr = rfac.getONE(); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } //ar = PolyUtil.>monic(ar); //br = PolyUtil.>monic(br); //cr = PolyUtil.>monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); er = Power.>>> positivePower(br, p); //System.out.println("b^p = " + er); // a a b^p c dr = ar.multiply(ar).multiply(er).multiply(cr); cr = ar.multiply(br).multiply(cr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); cr = sqf.recursiveUnivariateSquarefreePart(cr); dr = sqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); assertTrue("isSquarefree(cr) " + cr, sqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, sqf.isRecursiveSquarefree(dr)); er = PolyUtil.> recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors with char-th root. * */ public void testRecursiveSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); cfac = new GenPolynomialRing>(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, 3, 2, q); //cr = rfac.getONE(); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } //ar = PolyUtil.>monic(ar); //br = PolyUtil.>monic(br); //cr = PolyUtil.>monic(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); er = Power.>>> positivePower(br, p); //System.out.println("b^p = " + er); // a a b^p c dr = ar.multiply(ar).multiply(er).multiply(cr); //System.out.println("dr = " + dr); SortedMap>>, Long> sfactors; sfactors = sqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree with char-th root. * */ public void testSquarefreeCharRoot() { //System.out.println("\nfull CharRoot:"); long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing>(fac, rl, to, vars); a = dfac.random(kl, 3, 3, q); b = dfac.random(kl, 3, 3, q); c = dfac.random(kl, 3, 3, q); //c = dfac.getONE(); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //a = a.monic(); //b = b.monic(); //c = c.monic(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); e = Power.>> positivePower(b, p); //System.out.println("b^p = " + e); // a a b^p c d = a.multiply(a).multiply(e).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.squarefreePart(c); d = sqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); e = PolyUtil.> basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test squarefree factors with char-th root. * */ public void testSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing>(fac, rl, to, vars); a = dfac.random(kl, 3, 3, q); b = dfac.random(kl, 3, 3, q); c = dfac.random(kl, 3, 3, q); //c = dfac.getONE(); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //a = a.monic(); //b = b.monic(); //c = c.monic(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); e = Power.>> positivePower(b, p); //System.out.println("b^p = " + e); // a a b^p c d = a.multiply(a).multiply(e).multiply(c); //System.out.println("d = " + d); SortedMap>, Long> sfactors; sfactors = sqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } } jas-2.5/trc/edu/jas/ufd/HenselUtilTest.java0000644000175000017500000014674612004571452021044 0ustar giovannigiovanni/* * $Id: HenselUtilTest.java 4071 2012-07-27 19:59:38Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModularRingFactory; import edu.jas.kern.ComputerThreads; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * HenselUtil tests with JUnit. * @author Heinz Kredel. */ public class HenselUtilTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a HenselUtilTest object. * @param name String. */ public HenselUtilTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(HenselUtilTest.class); return suite; } //private final static int bitlen = 100; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; int rl = 5; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; dfac = new GenPolynomialRing(new BigInteger(1), rl, to); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; dfac = null; cfac = null; rfac = null; ComputerThreads.terminate(); } protected static java.math.BigInteger getPrime1() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 60; i++) { prime *= 2; } prime -= 93; //prime = 37; //System.out.println("p1 = " + prime); return new java.math.BigInteger("" + prime); } protected static java.math.BigInteger getPrime2() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 30; i++) { prime *= 2; } prime -= 35; //prime = 19; //System.out.println("p1 = " + prime); return new java.math.BigInteger("" + prime); } /** * Test Hensel lifting. */ public void testHenselLifting() { java.math.BigInteger p; p = getPrime1(); //p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); //.multiply(p).multiply(p).multiply(p); BigInteger mi = m; ModIntegerRing pm = new ModIntegerRing(p, true); GenPolynomialRing pfac = new GenPolynomialRing(pm, 1, to); dfac = new GenPolynomialRing(mi, 1, to); GenPolynomial ap; GenPolynomial bp; GenPolynomial cp; GenPolynomial sp; GenPolynomial tp; GenPolynomial[] egcd; GenPolynomial ap1; GenPolynomial bp1; HenselApprox lift; GenPolynomial a1; GenPolynomial b1; GenPolynomial c1; for (int i = 1; i < 3; i++) { a = dfac.random(kl + 70 * i, ll, el + 5, q).abs(); b = dfac.random(kl + 70 * i, ll, el + 5, q).abs(); //a = dfac.univariate(0).sum( dfac.fromInteger(30) ); //b = dfac.univariate(0).subtract( dfac.fromInteger(20) ); //b = b.multiply( dfac.univariate(0) ).sum( dfac.fromInteger(168)); c = a.multiply(b); if (a.degree(0) < 1 || b.degree(0) < 2) { continue; } ap = PolyUtil.fromIntegerCoefficients(pfac, a); if (!a.degreeVector().equals(ap.degreeVector())) { continue; } bp = PolyUtil.fromIntegerCoefficients(pfac, b); if (!b.degreeVector().equals(bp.degreeVector())) { continue; } cp = PolyUtil.fromIntegerCoefficients(pfac, c); if (!c.degreeVector().equals(cp.degreeVector())) { continue; } ap1 = ap; //.monic(); bp1 = bp; //.monic(); egcd = ap1.egcd(bp1); if (!egcd[0].isONE()) { continue; } sp = egcd[1]; tp = egcd[2]; BigInteger an = a.maxNorm(); BigInteger bn = b.maxNorm(); if (an.compareTo(bn) > 0) { mi = an; } else { mi = bn; } BigInteger cn = c.maxNorm(); if (cn.compareTo(mi) > 0) { mi = cn; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //--System.out.println("mi = " + mi); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); // System.out.println("ap*bp = " + ap.multiply(bp)); //System.out.println("gcd = " + egcd[0]); //System.out.println("gcd = " + ap1.multiply(sp).sum(bp1.multiply(tp))); //System.out.println("sp = " + sp); //System.out.println("tp = " + tp); try { lift = HenselUtil. liftHensel(c, mi, ap, bp, sp, tp); a1 = lift.A; b1 = lift.B; c1 = a1.multiply(b1); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("a1 = " + a1); //System.out.println("b1 = " + b1); //System.out.println("a1*b1 = " + c1); //assertEquals("lift(a mod p) = a",a,a1); //assertEquals("lift(b mod p) = b",b,b1); assertEquals("lift(a b mod p) = a b", c, c1); } catch (NoLiftingException e) { fail("" + e); } } } /** * Test Hensel lifting with gcd. */ public void testHenselLiftingGcd() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); //.multiply(p).multiply(p).multiply(p); BigInteger mi = m; ModIntegerRing pm = new ModIntegerRing(p, true); GenPolynomialRing pfac = new GenPolynomialRing(pm, 1, to); dfac = new GenPolynomialRing(mi, 1, to); GenPolynomial ap; GenPolynomial bp; GenPolynomial cp; HenselApprox lift; GenPolynomial a1; GenPolynomial b1; GenPolynomial c1; for (int i = 1; i < 3; i++) { // 70 better for quadratic a = dfac.random(kl + 70 * i, ll + 10, el + 5, q).abs(); b = dfac.random(kl + 70 * i, ll + 10, el + 5, q).abs(); //a = dfac.univariate(0).sum( dfac.fromInteger(30) ); //b = dfac.univariate(0).subtract( dfac.fromInteger(20) ); //b = b.multiply( dfac.univariate(0) ).sum( dfac.fromInteger(168)); c = a.multiply(b); if (a.degree(0) < 1 || b.degree(0) < 2) { continue; } ap = PolyUtil.fromIntegerCoefficients(pfac, a); if (!a.degreeVector().equals(ap.degreeVector())) { continue; } bp = PolyUtil.fromIntegerCoefficients(pfac, b); if (!b.degreeVector().equals(bp.degreeVector())) { continue; } cp = PolyUtil.fromIntegerCoefficients(pfac, c); if (!c.degreeVector().equals(cp.degreeVector())) { continue; } BigInteger an = a.maxNorm(); BigInteger bn = b.maxNorm(); if (an.compareTo(bn) > 0) { mi = an; } else { mi = bn; } BigInteger cn = c.maxNorm(); if (cn.compareTo(mi) > 0) { mi = cn; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //--System.out.println("mi = " + mi); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); // System.out.println("ap*bp = " + ap.multiply(bp)); //System.out.println("gcd = " + egcd[0]); //System.out.println("gcd = " + ap1.multiply(sp).sum(bp1.multiply(tp))); //System.out.println("sp = " + sp); //System.out.println("tp = " + tp); long tq = System.currentTimeMillis(); try { lift = HenselUtil. liftHensel(c, mi, ap, bp); tq = System.currentTimeMillis() - tq; a1 = lift.A; b1 = lift.B; c1 = a1.multiply(b1); assertEquals("lift(a b mod p) = a b", c, c1); } catch (NoLiftingException e) { // ok no fail(""+e); } //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("a1 = " + a1); //System.out.println("b1 = " + b1); //System.out.println("a1*b1 = " + c1); //assertEquals("lift(a mod p) = a",a,a1); //assertEquals("lift(b mod p) = b",b,b1); } } /** * Test Hensel quadratic lifting. */ public void testHenselQuadraticLifting() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); //.multiply(p).multiply(p).multiply(p); BigInteger mi = m; ModIntegerRing pm = new ModIntegerRing(p, true); GenPolynomialRing pfac = new GenPolynomialRing(pm, 1, to); dfac = new GenPolynomialRing(mi, pfac); GenPolynomial ap; GenPolynomial bp; GenPolynomial cp; GenPolynomial sp; GenPolynomial tp; GenPolynomial[] egcd; GenPolynomial ap1; GenPolynomial bp1; HenselApprox lift; GenPolynomial a1; GenPolynomial b1; GenPolynomial c1; for (int i = 1; i < 3; i++) { // 70 better for quadratic a = dfac.random(kl + 70 * i, ll + 10, el + 5, q).abs(); b = dfac.random(kl + 70 * i, ll + 10, el + 5, q).abs(); //a = dfac.univariate(0).sum( dfac.fromInteger(30) ); //b = dfac.univariate(0).subtract( dfac.fromInteger(20) ); //b = b.multiply( dfac.univariate(0) ).sum( dfac.fromInteger(168)); c = a.multiply(b); if (a.degree(0) < 1 || b.degree(0) < 2) { continue; } ap = PolyUtil.fromIntegerCoefficients(pfac, a); if (!a.degreeVector().equals(ap.degreeVector())) { continue; } bp = PolyUtil.fromIntegerCoefficients(pfac, b); if (!b.degreeVector().equals(bp.degreeVector())) { continue; } cp = PolyUtil.fromIntegerCoefficients(pfac, c); if (!c.degreeVector().equals(cp.degreeVector())) { continue; } ap1 = ap; //.monic(); bp1 = bp; //.monic(); egcd = ap1.egcd(bp1); if (!egcd[0].isONE()) { continue; } sp = egcd[1]; tp = egcd[2]; BigInteger an = a.maxNorm(); BigInteger bn = b.maxNorm(); if (an.compareTo(bn) > 0) { mi = an; } else { mi = bn; } BigInteger cn = c.maxNorm(); if (cn.compareTo(mi) > 0) { mi = cn; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //--System.out.println("mi = " + mi); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); // System.out.println("ap*bp = " + ap.multiply(bp)); //System.out.println("gcd = " + egcd[0]); //System.out.println("gcd = " + ap1.multiply(sp).sum(bp1.multiply(tp))); //System.out.println("sp = " + sp); //System.out.println("tp = " + tp); long tq = System.currentTimeMillis(); try { lift = HenselUtil. liftHenselQuadratic(c, mi, ap, bp, sp, tp); tq = System.currentTimeMillis() - tq; a1 = lift.A; b1 = lift.B; c1 = a1.multiply(b1); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("a1 = " + a1); //System.out.println("b1 = " + b1); //System.out.println("a1*b1 = " + c1); //assertEquals("lift(a mod p) = a",a,a1); //assertEquals("lift(b mod p) = b",b,b1); assertEquals("lift(a b mod p) = a b", c, c1); } catch (NoLiftingException e) { fail("" + e); } if (false) { long t = System.currentTimeMillis(); try { lift = HenselUtil. liftHensel(c, mi, ap, bp, sp, tp); t = System.currentTimeMillis() - t; a1 = lift.A; b1 = lift.B; c1 = a1.multiply(b1); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("a1 = " + a1); //System.out.println("b1 = " + b1); //System.out.println("a1*b1 = " + c1); //assertEquals("lift(a mod p) = a",a,a1); //assertEquals("lift(b mod p) = b",b,b1); assertEquals("lift(a b mod p) = a b", c, c1); } catch (NoLiftingException e) { fail("" + e); } System.out.println("\nquadratic Hensel time = " + tq); System.out.println("linear Hensel time = " + t); } //break; } } /** * Test Hensel quadratic lifting with gcd. */ public void testHenselQuadraticLiftingGcd() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); //.multiply(p).multiply(p).multiply(p); BigInteger mi = m; ModIntegerRing pm = new ModIntegerRing(p, true); GenPolynomialRing pfac = new GenPolynomialRing(pm, 1, to); dfac = new GenPolynomialRing(mi, pfac); GenPolynomial ap; GenPolynomial bp; GenPolynomial cp; HenselApprox lift; GenPolynomial a1; GenPolynomial b1; GenPolynomial c1; for (int i = 1; i < 3; i++) { // 70 better for quadratic a = dfac.random(kl + 70 * i, ll + 10, el + 5, q).abs(); b = dfac.random(kl + 70 * i, ll + 10, el + 5, q).abs(); //a = dfac.univariate(0).sum( dfac.fromInteger(30) ); //b = dfac.univariate(0).subtract( dfac.fromInteger(20) ); //b = b.multiply( dfac.univariate(0) ).sum( dfac.fromInteger(168)); c = a.multiply(b); if (a.degree(0) < 1 || b.degree(0) < 2) { continue; } ap = PolyUtil.fromIntegerCoefficients(pfac, a); if (!a.degreeVector().equals(ap.degreeVector())) { continue; } bp = PolyUtil.fromIntegerCoefficients(pfac, b); if (!b.degreeVector().equals(bp.degreeVector())) { continue; } cp = PolyUtil.fromIntegerCoefficients(pfac, c); if (!c.degreeVector().equals(cp.degreeVector())) { continue; } BigInteger an = a.maxNorm(); BigInteger bn = b.maxNorm(); if (an.compareTo(bn) > 0) { mi = an; } else { mi = bn; } BigInteger cn = c.maxNorm(); if (cn.compareTo(mi) > 0) { mi = cn; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //--System.out.println("mi = " + mi); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); // System.out.println("ap*bp = " + ap.multiply(bp)); //System.out.println("gcd = " + egcd[0]); //System.out.println("gcd = " + ap1.multiply(sp).sum(bp1.multiply(tp))); //System.out.println("sp = " + sp); //System.out.println("tp = " + tp); long tq = System.currentTimeMillis(); try { lift = HenselUtil. liftHenselQuadratic(c, mi, ap, bp); tq = System.currentTimeMillis() - tq; a1 = lift.A; b1 = lift.B; c1 = a1.multiply(b1); assertEquals("lift(a b mod p) = a b", c, c1); } catch (NoLiftingException e) { //ok no fail(""+e); } //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("a1 = " + a1); //System.out.println("b1 = " + b1); //System.out.println("a1*b1 = " + c1); //assertEquals("lift(a mod p) = a",a,a1); //assertEquals("lift(b mod p) = b",b,b1); } } /** * Test lifting of extended Euclidean relation. */ public void testLiftingEgcd() { java.math.BigInteger p; //p = getPrime1(); //p = new java.math.BigInteger("19"); p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); //.multiply(p).multiply(p).multiply(p); //BigInteger mi = m; ModIntegerRing pm = new ModIntegerRing(p, true); GenPolynomialRing mfac = new GenPolynomialRing(pm, 1, to, new String[] { "x" }); dfac = new GenPolynomialRing(m, mfac); GreatestCommonDivisorAbstract ufd = GCDFactory.getProxy(m); GenPolynomial ap; GenPolynomial bp; GenPolynomial cp; GenPolynomial dp; GenPolynomial[] lift; GenPolynomial s; GenPolynomial t; for (int i = 1; i < 2; i++) { // 70 better for quadratic a = dfac.random(kl + 3 * i, ll + 1, el + 1, q).abs(); b = dfac.random(kl + 3 * i, ll + 1, el + 5, q).abs(); d = ufd.baseGcd(a, b); //System.out.println("d = " + d); if (!d.isONE()) { a = PolyUtil. basePseudoDivide(a, d); b = PolyUtil. basePseudoDivide(b, d); } if (a.degree(0) < 1 || b.degree(0) < 2) { continue; } ap = PolyUtil.fromIntegerCoefficients(mfac, a); if (!a.degreeVector().equals(ap.degreeVector())) { continue; } bp = PolyUtil.fromIntegerCoefficients(mfac, b); if (!b.degreeVector().equals(bp.degreeVector())) { continue; } dp = ap.gcd(bp); //System.out.println("dp = " + dp); if (!dp.isONE()) { continue; } c = a.multiply(b); cp = PolyUtil.fromIntegerCoefficients(mfac, c); if (!c.degreeVector().equals(cp.degreeVector())) { continue; } BigInteger mi; BigInteger an = a.maxNorm(); BigInteger bn = b.maxNorm(); if (an.compareTo(bn) > 0) { mi = an; } else { mi = bn; } BigInteger cn = c.maxNorm(); if (cn.compareTo(mi) > 0) { mi = cn; } long k = 1; BigInteger pi = m; while (pi.compareTo(mi) < 0) { k++; pi = pi.multiply(m); } //System.out.println("mi = " + mi); //System.out.println("pi = " + pi); //System.out.println("k = " + k); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); long tq = System.currentTimeMillis(); try { lift = HenselUtil. liftExtendedEuclidean(ap, bp, k); tq = System.currentTimeMillis() - tq; s = lift[0]; t = lift[1]; ModularRingFactory mcfac = (ModularRingFactory) s.ring.coFac; GenPolynomialRing mfac1 = new GenPolynomialRing(mcfac, mfac); //System.out.println("\nmcfac = " + mcfac); ap = PolyUtil.fromIntegerCoefficients(mfac1, PolyUtil.integerFromModularCoefficients(dfac, ap)); bp = PolyUtil.fromIntegerCoefficients(mfac1, PolyUtil.integerFromModularCoefficients(dfac, bp)); cp = s.multiply(ap).sum(t.multiply(bp)); //System.out.println("s = " + s); //System.out.println("t = " + t); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("cp = " + cp); assertTrue("lift(s a + t b mod p^k) = 1: " + cp, cp.isONE()); } catch (NoLiftingException e) { fail("" + e); } //System.out.println("time = " + tq); } } /** * Test lifting of list of extended Euclidean relation. */ public void testLiftingEgcdList() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); //.multiply(p).multiply(p).multiply(p); // BigInteger mi = m; ModIntegerRing pm = new ModIntegerRing(p, true); GenPolynomialRing mfac = new GenPolynomialRing(pm, 1, to, new String[] { "x" }); dfac = new GenPolynomialRing(m, mfac); GreatestCommonDivisorAbstract ufd = GCDFactory.getProxy(m); GenPolynomial ap; GenPolynomial bp; GenPolynomial cp; GenPolynomial dp; GenPolynomial ep; List> lift; //GenPolynomial s; //GenPolynomial t; for (int i = 1; i < 2; i++) { // 70 better for quadratic a = dfac.random(kl + 3 * i, ll + 5, el + 1, q).abs(); //a = dfac.parse("(x - 1)"); b = dfac.random(kl + 3 * i, ll + 5, el + 5, q).abs(); //b = dfac.parse("(x - 2)"); e = ufd.baseGcd(a, b); //System.out.println("e = " + e); if (!e.isONE()) { a = PolyUtil. basePseudoDivide(a, e); b = PolyUtil. basePseudoDivide(b, e); } if (a.degree(0) < 1 || b.degree(0) < 1) { continue; } ap = PolyUtil.fromIntegerCoefficients(mfac, a); if (!a.degreeVector().equals(ap.degreeVector())) { continue; } bp = PolyUtil.fromIntegerCoefficients(mfac, b); if (!b.degreeVector().equals(bp.degreeVector())) { continue; } ep = ap.gcd(bp); //System.out.println("ep = " + ep); if (!ep.isONE()) { continue; } d = dfac.random(kl + 3 * i, ll + 5, el + 4, q).abs(); //d = dfac.parse("(x - 3)"); e = ufd.baseGcd(a, d); //System.out.println("e = " + e); if (!e.isONE()) { a = PolyUtil. basePseudoDivide(a, e); d = PolyUtil. basePseudoDivide(d, e); } e = ufd.baseGcd(b, d); //System.out.println("e = " + e); if (!e.isONE()) { b = PolyUtil. basePseudoDivide(b, e); d = PolyUtil. basePseudoDivide(d, e); } if (d.degree(0) < 1) { continue; } dp = PolyUtil.fromIntegerCoefficients(mfac, d); if (!d.degreeVector().equals(dp.degreeVector())) { continue; } c = a.multiply(b).multiply(d); cp = PolyUtil.fromIntegerCoefficients(mfac, c); if (!c.degreeVector().equals(cp.degreeVector())) { continue; } BigInteger mi; BigInteger an = a.maxNorm(); BigInteger bn = b.maxNorm(); if (an.compareTo(bn) > 0) { mi = an; } else { mi = bn; } BigInteger cn = c.maxNorm(); if (cn.compareTo(mi) > 0) { mi = cn; } BigInteger dn = d.maxNorm(); if (dn.compareTo(mi) > 0) { mi = dn; } long k = 1; BigInteger pi = m; while (pi.compareTo(mi) < 0) { k++; pi = pi.multiply(m); } //System.out.println("mi = " + mi); //System.out.println("pi = " + pi); //System.out.println("k = " + k); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("d = " + d); //System.out.println("c = " + c); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("dp = " + dp); //System.out.println("cp = " + cp); List> A = new ArrayList>(); List> As; // = new ArrayList>(); A.add(ap); A.add(bp); A.add(dp); //A.add(mfac.parse("(x - 4)")); //A.add(mfac.parse("(x - 5)")); //System.out.println("A = " + A); List> A2 = new ArrayList>(); List> As2 = new ArrayList>(); //System.out.println("A2 = " + A2); long tq = System.currentTimeMillis(); try { A2.add(ap); A2.add(bp); GenPolynomial[] L = HenselUtil. liftExtendedEuclidean(ap, bp, k); //System.out.println("lift(a,b) = " + L[0] + ", " + L[1] + "\n"); lift = HenselUtil. liftExtendedEuclidean(A, k); tq = System.currentTimeMillis() - tq; //System.out.println(""); //System.out.println("lift(a,b) = " + L[0] + ", " + L[1] ); //System.out.println("lift = " + lift); As = PolyUtil.fromIntegerCoefficients(mfac, PolyUtil.integerFromModularCoefficients(dfac, lift)); //System.out.println("As = " + As); boolean il = HenselUtil. isExtendedEuclideanLift(A, As); //System.out.println("islift = " + il); assertTrue("lift(s0,s1,s2) mod p^k) = 1: ", il); As2.add(L[1]); As2.add(L[0]); As2 = PolyUtil.fromIntegerCoefficients(mfac, PolyUtil.integerFromModularCoefficients(dfac, As2)); //System.out.println("As2 = " + As2); il = HenselUtil. isExtendedEuclideanLift(A2, As2); //System.out.println("islift = " + il); assertTrue("lift(s a + t b mod p^k) = 1: ", il); } catch (NoLiftingException e) { // ok fail(""+e); } //System.out.println("time = " + tq); } } /** * Test lifting of list of Diophant relation. */ public void testLiftingDiophantList() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); //.multiply(p).multiply(p).multiply(p); // BigInteger mi = m; ModIntegerRing pm = new ModIntegerRing(p, true); GenPolynomialRing mfac = new GenPolynomialRing(pm, 1, to, new String[] { "x" }); dfac = new GenPolynomialRing(m, mfac); GreatestCommonDivisorAbstract ufd = GCDFactory.getProxy(m); GenPolynomial ap; GenPolynomial bp; GenPolynomial cp; GenPolynomial dp; GenPolynomial ep; GenPolynomial fp; List> lift; //GenPolynomial s; //GenPolynomial t; for (int i = 1; i < 2; i++) { // 70 better for quadratic a = dfac.random(kl + 3 * i, ll + 5, el + 1, q).abs(); //a = dfac.parse("(x - 1)"); b = dfac.random(kl + 3 * i, ll + 5, el + 5, q).abs(); //b = dfac.parse("(x - 2)"); e = ufd.baseGcd(a, b); //System.out.println("e = " + e); if (!e.isONE()) { a = PolyUtil. basePseudoDivide(a, e); b = PolyUtil. basePseudoDivide(b, e); } if (a.degree(0) < 1 || b.degree(0) < 1) { continue; } ap = PolyUtil.fromIntegerCoefficients(mfac, a); if (!a.degreeVector().equals(ap.degreeVector())) { continue; } bp = PolyUtil.fromIntegerCoefficients(mfac, b); if (!b.degreeVector().equals(bp.degreeVector())) { continue; } ep = ap.gcd(bp); //System.out.println("ep = " + ep); if (!ep.isONE()) { continue; } d = dfac.random(kl + 3 * i, ll + 5, el + 4, q).abs(); //d = dfac.parse("(x - 3)"); e = ufd.baseGcd(a, d); //System.out.println("e = " + e); if (!e.isONE()) { a = PolyUtil. basePseudoDivide(a, e); d = PolyUtil. basePseudoDivide(d, e); } e = ufd.baseGcd(b, d); //System.out.println("e = " + e); if (!e.isONE()) { b = PolyUtil. basePseudoDivide(b, e); d = PolyUtil. basePseudoDivide(d, e); } if (d.degree(0) < 1) { continue; } dp = PolyUtil.fromIntegerCoefficients(mfac, d); if (!d.degreeVector().equals(dp.degreeVector())) { continue; } c = a.multiply(b).multiply(d); cp = PolyUtil.fromIntegerCoefficients(mfac, c); if (!c.degreeVector().equals(cp.degreeVector())) { continue; } BigInteger mi; BigInteger an = a.maxNorm(); BigInteger bn = b.maxNorm(); if (an.compareTo(bn) > 0) { mi = an; } else { mi = bn; } BigInteger cn = c.maxNorm(); if (cn.compareTo(mi) > 0) { mi = cn; } BigInteger dn = d.maxNorm(); if (dn.compareTo(mi) > 0) { mi = dn; } long k = 1; BigInteger pi = m; while (pi.compareTo(mi) < 0) { k++; pi = pi.multiply(m); } //System.out.println("mi = " + mi); //System.out.println("pi = " + pi); //System.out.println("k = " + k); fp = mfac.random(4); //mfac.univariate(0,2); //mfac.getONE(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("d = " + d); //System.out.println("c = " + c); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("dp = " + dp); //System.out.println("cp = " + cp); List> A = new ArrayList>(); List> As; // = new ArrayList>(); A.add(ap); A.add(bp); A.add(dp); //A.add(mfac.parse("(x - 4)")); //A.add(mfac.parse("(x - 5)")); //System.out.println("A = " + A); List> A2 = new ArrayList>(); List> As2 = new ArrayList>(); //System.out.println("A2 = " + A2); long tq = System.currentTimeMillis(); try { A2.add(ap); A2.add(bp); List> L = HenselUtil. liftDiophant(ap, bp, fp, k); //System.out.println("lift(a,b) = " + L[0] + ", " + L[1] + "\n"); lift = HenselUtil. liftDiophant(A2, fp, k); tq = System.currentTimeMillis() - tq; //System.out.println(""); //System.out.println("lift(a,b) = " + L[0] + ", " + L[1] ); //System.out.println("lift = " + lift); As = PolyUtil.fromIntegerCoefficients(mfac, PolyUtil.integerFromModularCoefficients(dfac, lift)); //System.out.println("As = " + As); boolean il = HenselUtil. isDiophantLift(A2, As, fp); //System.out.println("islift = " + il); assertTrue("lift(s0,s1,s2) mod p^k) = 1: ", il); As2.add(L.get(0)); As2.add(L.get(1)); As2 = PolyUtil.fromIntegerCoefficients(mfac, PolyUtil.integerFromModularCoefficients(dfac, As2)); //System.out.println("As2 = " + As2); il = HenselUtil. isDiophantLift(A2, As2, fp); //System.out.println("islift = " + il); assertTrue("lift(s a + t b mod p^k) = 1: ", il); } catch (NoLiftingException e) { // ok fail(""+e); } //System.out.println("time = " + tq); } } /** * Test Hensel monic lifting new list version. */ public void testHenselLiftingMonicList() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("268435399"); //p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModIntegerRing pm = new ModIntegerRing(p, true); GenPolynomialRing mfac = new GenPolynomialRing(pm, 1, to, new String[] { "x" }); dfac = new GenPolynomialRing(m, mfac); GreatestCommonDivisorAbstract ufd = GCDFactory.getProxy(m); BigInteger one = m.getONE(); GenPolynomial ap; GenPolynomial bp; GenPolynomial cp; GenPolynomial dp; GenPolynomial ep; List> lift; //GenPolynomial s; //GenPolynomial t; for (int i = 1; i < 2; i++) { // 70 better for quadratic //a = dfac.random(kl + 30 * i, ll + 5, el + 3, q).abs(); a = dfac.parse("(x^3 + 20 x^2 - 313131)"); //a = dfac.parse("(x^6 - 24 x^2 - 17)"); //a = dfac.parse("(x^6 + 48)"); b = dfac.random(kl + 30 * i, ll + 5, el + 5, q).abs(); //b = dfac.parse("(x^4 + 23 x^3 - 32)"); //b = dfac.parse("(x^7 + 1448)"); //b = dfac.parse("(x^14 + 44)"); if (!a.leadingBaseCoefficient().isUnit()) { ExpVector e = a.leadingExpVector(); a.doPutToMap(e, one); } if (!b.leadingBaseCoefficient().isUnit()) { ExpVector e = b.leadingExpVector(); b.doPutToMap(e, one); } e = ufd.baseGcd(a, b); //System.out.println("e = " + e); if (!e.isONE()) { a = PolyUtil. basePseudoDivide(a, e); b = PolyUtil. basePseudoDivide(b, e); } if (a.degree(0) < 1) { a = dfac.parse("(x^3 + 20 x^2 - 313131)"); } if (b.degree(0) < 1) { b = dfac.parse("(x^4 + 23 x^3 - 32)"); } ap = PolyUtil.fromIntegerCoefficients(mfac, a); if (!a.degreeVector().equals(ap.degreeVector())) { continue; } bp = PolyUtil.fromIntegerCoefficients(mfac, b); if (!b.degreeVector().equals(bp.degreeVector())) { continue; } ep = ap.gcd(bp); //System.out.println("ep = " + ep); if (!ep.isONE()) { continue; } d = dfac.random(kl + 30 * i, ll + 5, el + 4, q).abs(); //d = dfac.parse("(x^2 + 22 x - 33)"); if (!d.leadingBaseCoefficient().isUnit()) { ExpVector e = d.leadingExpVector(); d.doPutToMap(e, one); } e = ufd.baseGcd(a, d); //System.out.println("e = " + e); if (!e.isONE()) { a = PolyUtil. basePseudoDivide(a, e); d = PolyUtil. basePseudoDivide(d, e); } e = ufd.baseGcd(b, d); //System.out.println("e = " + e); if (!e.isONE()) { b = PolyUtil. basePseudoDivide(b, e); d = PolyUtil. basePseudoDivide(d, e); } if (d.degree(0) < 1) { d = dfac.parse("(x^2 + 22 x - 33)"); //continue; } dp = PolyUtil.fromIntegerCoefficients(mfac, d); if (!d.degreeVector().equals(dp.degreeVector())) { continue; } ep = ap.gcd(dp); //System.out.println("ep = " + ep); if (!ep.isONE()) { continue; } ep = bp.gcd(dp); //System.out.println("ep = " + ep); if (!ep.isONE()) { continue; } c = a.multiply(b).multiply(d); cp = PolyUtil.fromIntegerCoefficients(mfac, c); if (!c.degreeVector().equals(cp.degreeVector())) { continue; } //c = dfac.parse("( (x^6 + 48) * (x^14 + 44) )"); BigInteger mi; BigInteger an = a.maxNorm(); BigInteger bn = b.maxNorm(); if (an.compareTo(bn) > 0) { mi = an; } else { mi = bn; } BigInteger cn = c.maxNorm(); if (cn.compareTo(mi) > 0) { mi = cn; } BigInteger dn = d.maxNorm(); if (dn.compareTo(mi) > 0) { mi = dn; } long k = 1; BigInteger pi = m; while (pi.compareTo(mi) < 0) { k++; pi = pi.multiply(m); } k++; pi = pi.multiply(m); //System.out.println("mi = " + mi); //System.out.println("pi = " + pi); //System.out.println("k = " + k); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("d = " + d); //System.out.println("c = " + c); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("dp = " + dp); //System.out.println("cp = " + cp); List> A = new ArrayList>(); //List> As; // = new ArrayList>(); A.add(ap); A.add(bp); A.add(dp); //A.add(mfac.parse("(x^3 + 26602528)")); //A.add(mfac.parse("(31493559 x^3 + 69993768)")); //A.add(mfac.parse("(121154481 x^7 + 268435398)")); //A.add(mfac.parse("(151258699 x^7 + 90435272)")); //monic: x^3 + 26602528 , x^3 + 241832871 , x^7 + 230524583 , x^7 + 37910816 //A.add( mfac.parse("((x^3 + 26602528)*(31493559 x^3 + 69993768))") ); //A.add( mfac.parse("((121154481 x^7 + 268435398)*(151258699 x^7 + 90435272))") ); //System.out.println("A = " + A); A = PolyUtil.monic(A); //System.out.println("A = " + A); long tq = System.currentTimeMillis(); try { lift = HenselUtil. liftHenselMonic(c, A, k); tq = System.currentTimeMillis() - tq; //System.out.println("\nk = " + k); //System.out.println("c = " + c); //System.out.println("A = " + A); //System.out.println("Ai = [" + a + ", " + b + ", " + d + "]"); //System.out.println("lift = " + lift); List> L = PolyUtil.integerFromModularCoefficients(dfac, lift); //System.out.println("L = " + L); //ModularRingFactory mcfac = (ModularRingFactory) lift.get(0).ring.coFac; //GenPolynomialRing mfac1 = new GenPolynomialRing(mcfac, mfac); //System.out.println("\nmcfac = " + mcfac); boolean ih = HenselUtil.isHenselLift(c, m, pi, L); //System.out.println("ih = " + ih); assertTrue("prod(lift(L)) = c: " + c, ih); } catch (NoLiftingException e) { // ok fail(""+e); } //System.out.println("time = " + tq); } } /** * Test Hensel lifting new list version. */ public void testHenselLiftingList() { java.math.BigInteger p; //p = getPrime1(); p = new java.math.BigInteger("268435399"); //p = new java.math.BigInteger("19"); //p = new java.math.BigInteger("5"); BigInteger m = new BigInteger(p); ModIntegerRing pm = new ModIntegerRing(p, true); GenPolynomialRing mfac = new GenPolynomialRing(pm, 1, to, new String[] { "x" }); dfac = new GenPolynomialRing(m, mfac); GreatestCommonDivisorAbstract ufd = GCDFactory.getProxy(m); //BigInteger one = m.getONE(); GenPolynomial ap; GenPolynomial bp; GenPolynomial cp; GenPolynomial dp; GenPolynomial ep; List> lift; //GenPolynomial s; //GenPolynomial t; for (int i = 1; i < 2; i++) { // 70 better for quadratic a = dfac.random(kl + 30 * i, ll + 5, el + 3, q).abs(); //a = dfac.parse("( 35333333 x^3 + 20 x^2 - 313131)"); a = ufd.basePrimitivePart(a); b = dfac.random(kl + 30 * i, ll + 5, el + 5, q).abs(); //b = dfac.parse("( 51111 x^4 + 23 x^3 - 32)"); b = ufd.basePrimitivePart(b); e = ufd.baseGcd(a, b); //System.out.println("e = " + e); if (!e.isONE()) { a = PolyUtil. basePseudoDivide(a, e); b = PolyUtil. basePseudoDivide(b, e); } if (a.degree(0) < 1) { a = dfac.parse("( 3 x^3 + 20 x^2 - 313131)"); } if (b.degree(0) < 1) { b = dfac.parse("( 5 x^4 + 23 x^3 - 32)"); } ap = PolyUtil.fromIntegerCoefficients(mfac, a); if (!a.degreeVector().equals(ap.degreeVector())) { continue; } bp = PolyUtil.fromIntegerCoefficients(mfac, b); if (!b.degreeVector().equals(bp.degreeVector())) { continue; } ep = ap.gcd(bp); //System.out.println("ep = " + ep); if (!ep.isONE()) { continue; } d = dfac.random(kl + 30 * i, ll + 5, el + 4, q).abs(); //d = dfac.parse("( 711111 x^2 + 22 x - 33)"); //d = dfac.parse("( 7 x^2 + 22 x - 33)"); d = ufd.basePrimitivePart(d); e = ufd.baseGcd(a, d); //System.out.println("e = " + e); if (!e.isONE()) { a = PolyUtil. basePseudoDivide(a, e); d = PolyUtil. basePseudoDivide(d, e); } e = ufd.baseGcd(b, d); //System.out.println("e = " + e); if (!e.isONE()) { b = PolyUtil. basePseudoDivide(b, e); d = PolyUtil. basePseudoDivide(d, e); } if (d.degree(0) < 1) { d = dfac.parse("( 7 x^2 + 22 x - 33)"); //continue; } dp = PolyUtil.fromIntegerCoefficients(mfac, d); if (!d.degreeVector().equals(dp.degreeVector())) { continue; } ep = ap.gcd(dp); //System.out.println("ep = " + ep); if (!ep.isONE()) { continue; } ep = bp.gcd(dp); //System.out.println("ep = " + ep); if (!ep.isONE()) { continue; } c = a.multiply(b).multiply(d); cp = PolyUtil.fromIntegerCoefficients(mfac, c); if (!c.degreeVector().equals(cp.degreeVector())) { continue; } BigInteger mi; BigInteger an = a.maxNorm(); BigInteger bn = b.maxNorm(); if (an.compareTo(bn) > 0) { mi = an; } else { mi = bn; } BigInteger cn = c.maxNorm(); if (cn.compareTo(mi) > 0) { mi = cn; } BigInteger dn = d.maxNorm(); if (dn.compareTo(mi) > 0) { mi = dn; } long k = 1; BigInteger pi = m; while (pi.compareTo(mi) < 0) { k++; pi = pi.multiply(m); } k++; pi = pi.multiply(m); //System.out.println("mi = " + mi); //System.out.println("p = " + p); //System.out.println("pi = " + pi); //System.out.println("k = " + k); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("d = " + d); //System.out.println("c = " + c); //System.out.println("ap = " + ap); //System.out.println("bp = " + bp); //System.out.println("dp = " + dp); //System.out.println("cp = " + cp); List> A = new ArrayList>(); List> Ai = new ArrayList>(); Ai.add(a); Ai.add(b); Ai.add(d); A.add(ap); A.add(bp); A.add(dp); //System.out.println("Ai = " + Ai); //System.out.println("A = " + A); long tq = System.currentTimeMillis(); try { lift = HenselUtil. liftHensel(c, A, k, c.leadingBaseCoefficient()); tq = System.currentTimeMillis() - tq; //System.out.println("\nk = " + k); //System.out.println("c = " + c); //System.out.println("A = " + A); //System.out.println("Ai = [" + a + ", " + b + ", " + d + "]"); //System.out.println("lift = " + lift); List> L = PolyUtil.integerFromModularCoefficients(dfac, lift); //System.out.println("L = " + L); //System.out.println("Ai = " + Ai); boolean ih = HenselUtil.isHenselLift(c, m, pi, L); //System.out.println("ih = " + ih); assertTrue("prod(lift(L)) = c: " + c, ih); } catch (NoLiftingException e) { // ok fail("" + e); } //System.out.println("time = " + tq); } } } jas-2.5/trc/edu/jas/ufd/GCDFactoryTest.java0000644000175000017500000001503212003043360020663 0ustar giovannigiovanni/* * $Id: GCDFactoryTest.java 4019 2012-07-22 18:31:13Z kredel $ */ package edu.jas.ufd; //import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigComplex; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * GreatestCommonDivisor factory tests with JUnit. * @author Heinz Kredel. */ public class GCDFactoryTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDFactoryTest object. * @param name String. */ public GCDFactoryTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDFactoryTest.class); return suite; } //private final static int bitlen = 100; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 5; int kl = 4; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; dfac = new GenPolynomialRing(new BigInteger(1), rl, to); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; dfac = null; cfac = null; rfac = null; } /** * Test get BigInteger implementation. * */ public void testBigInteger() { BigInteger bi = new BigInteger(); GreatestCommonDivisor ufd; ufd = GCDFactory.getImplementation(bi); //System.out.println("ufd = " + ufd); assertTrue("ufd = Modular " + ufd, ufd instanceof GreatestCommonDivisorModular); } /** * Test get ModInteger implementation. * */ public void testModInteger() { ModIntegerRing mi = new ModIntegerRing(19, true); GreatestCommonDivisor ufd; ufd = GCDFactory.getImplementation(mi); //System.out.println("ufd = " + ufd); assertTrue("ufd != ModEval " + ufd, ufd instanceof GreatestCommonDivisorModEval); mi = new ModIntegerRing(30); ufd = GCDFactory.getImplementation(mi); //System.out.println("ufd = " + ufd); assertTrue("ufd != Subres " + ufd, ufd instanceof GreatestCommonDivisorSubres); } /** * Test get BigRational implementation. * */ public void testBigRational() { BigRational b = new BigRational(); GreatestCommonDivisor ufd; ufd = GCDFactory.getImplementation(b); //System.out.println("ufd = " + ufd); assertTrue("ufd = Primitive " + ufd, ufd instanceof GreatestCommonDivisorPrimitive); } /** * Test get BigComplex implementation. * */ public void testBigComplex() { BigComplex b = new BigComplex(); GreatestCommonDivisor ufd; ufd = GCDFactory. getImplementation(b); //System.out.println("ufd = " + ufd); assertTrue("ufd != Simple " + ufd, ufd instanceof GreatestCommonDivisorSimple); } /** * Test get AlgebraicNumber<BigRational> implementation. * */ public void testAlgebraicNumberBigRational() { BigRational b = new BigRational(); GenPolynomialRing fac; fac = new GenPolynomialRing(b, 1); GenPolynomial mo = fac.random(kl, ll, el, q); while (mo.isZERO() || mo.isONE() || mo.isConstant()) { mo = fac.random(kl, ll, el, q); } AlgebraicNumberRing afac; afac = new AlgebraicNumberRing(mo); GreatestCommonDivisor> ufd; ufd = GCDFactory.> getImplementation(afac); //System.out.println("ufd1 = " + ufd); assertTrue("ufd = Subres " + ufd, ufd instanceof GreatestCommonDivisorSubres); mo = fac.univariate(0).subtract(fac.getONE()); afac = new AlgebraicNumberRing(mo, true); ufd = GCDFactory.> getImplementation(afac); //System.out.println("ufd1 = " + ufd); assertTrue("ufd = Simple " + ufd, ufd instanceof GreatestCommonDivisorSimple); } /** * Test get AlgebraicNumber<ModInteger> implementation. * */ public void testAlgebraicNumberModInteger() { ModIntegerRing b = new ModIntegerRing(19, true); GenPolynomialRing fac; fac = new GenPolynomialRing(b, 1); GenPolynomial mo = fac.random(kl, ll, el, q); while (mo.isZERO() || mo.isONE() || mo.isConstant()) { mo = fac.random(kl, ll, el, q); } AlgebraicNumberRing afac; afac = new AlgebraicNumberRing(mo); AlgebraicNumber a = afac.getONE(); assertTrue("a == 1 " + a, a.isONE()); GreatestCommonDivisor> ufd; ufd = GCDFactory.> getImplementation(afac); //System.out.println("ufd2 = " + ufd); assertTrue("ufd = Subres " + ufd, ufd instanceof GreatestCommonDivisorSubres); } } jas-2.5/trc/edu/jas/ufd/GCDSubresRatTest.java0000644000175000017500000005165211641660762021220 0ustar giovannigiovanni/* * $Id: GCDSubresRatTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GCD Subres with rational coefficients algorithm tests with JUnit. * @author Heinz Kredel. */ public class GCDSubresRatTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDSubresRatTest object. * @param name String. */ public GCDSubresRatTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDSubresRatTest.class); return suite; } //private final static int bitlen = 100; GreatestCommonDivisorSubres ufd; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigRational mi; BigRational ai; BigRational bi; BigRational ci; BigRational di; BigRational ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 3; int kl = 2; int ll = 3; int el = 3; float q = 0.25f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; mi = new BigRational(1); ufd = new GreatestCommonDivisorSubres(); String[] vars = ExpVector.STDVARS(rl); String[] cvars = ExpVector.STDVARS(rl - 1); String[] rvars = new String[] { vars[rl - 1] }; dfac = new GenPolynomialRing(mi, rl, to, vars); cfac = new GenPolynomialRing(mi, rl - 1, to, cvars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); //System.out.println("mi = " + mi); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; mi = null; ufd = null; dfac = null; cfac = null; rfac = null; } /** * Test gcd. */ public void testGcd() { for (int i = 0; i < 1; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 0 * i, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 0 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 0 * i, q); c = c.multiply(dfac.univariate(0)); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); c = ufd.basePrimitivePart(c).abs(); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a" + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b" + e, e.isZERO()); } } /** * Test base quotioent and remainder. */ public void testBaseQR() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 3; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a).abs(); //c = ufd.basePrimitivePart(c); do { ci = mi.random(kl * (i + 2)); ci = ci.sum(mi.getONE()); } while (ci.isZERO()); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("ci = " + ci); if (a.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); b = a.multiply(c); //System.out.println("b = " + b); d = PolyUtil. basePseudoRemainder(b, c); //System.out.println("d = " + d); assertTrue("rem(ac,c) == 0", d.isZERO()); b = a.multiply(ci); //System.out.println("b = " + b); d = b.divide(ci); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); b = a.multiply(c); //System.out.println("b = " + b); d = PolyUtil. basePseudoDivide(b, c); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); } } /** * Test base content and primitive part. */ public void testBaseContentPP() { for (int i = 0; i < 9; i++) { c = dfac.random(kl * (i + 2), ll + 2 * i, el + i, q); c = c.multiply(mi.random(kl * (i + 2))); if (c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ci = ufd.baseContent(c); d = ufd.basePrimitivePart(c); //System.out.println("c = " + c); //System.out.println("ci = " + ci); //System.out.println("d = " + d); a = d.multiply(ci); assertEquals("c == cont(c)pp(c)", c, a); } } public void testDiscriminant() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 5; i++) { c = dfac.random(kl * (i + 1), ll + 2 * i, el + i, q*2); //System.out.println("c = " + c); if (c.isZERO()) { // skip for this turn continue; } c = c.multiply(c); d = ufd.baseDiscriminant(c); //System.out.println("d = " + d); assertTrue("disc(c^2) == 0", d.isZERO()); } } /** * Test base gcd. */ public void testBaseGcd() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 3; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); //c = ufd.basePrimitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); d = ufd.baseGcd(a, b); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test recursive quotioent and remainder. */ public void testRecursiveQR() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 3; i++) { a = dfac.random(kl * (i + 1), ll + i, el + i, q); a = ufd.basePrimitivePart(a).abs(); c = dfac.random(kl * (i + 1), ll + i, el + i, q); c = ufd.basePrimitivePart(a).abs(); cr = PolyUtil. recursive(rfac, c); c = cfac.random(kl * (i + 1), ll + 2 * i, el + 2 * i, q); c = ufd.basePrimitivePart(c).abs(); ar = PolyUtil. recursive(rfac, a); //System.out.println("ar = " + ar); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("cr = " + cr); if (cr.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); br = ar.multiply(cr); //System.out.println("br = " + br); dr = PolyUtil. recursivePseudoRemainder(br, cr); //System.out.println("dr = " + dr); d = PolyUtil. distribute(dfac, dr); //System.out.println("d = " + d); assertTrue("rem(ac,c) == 0", d.isZERO()); br = ar.multiply(c); //System.out.println("br = " + br); dr = PolyUtil. recursiveDivide(br, c); //System.out.println("dr = " + dr); d = PolyUtil. distribute(dfac, dr); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); } } /** * Test recursive content and primitive part. */ public void testRecursiveContentPP() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 3; i++) { cr = rfac.random(kl * (i + 2), ll + 2 * i, el + i, q); //System.out.println("cr = " + cr); assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); c = ufd.recursiveContent(cr); dr = ufd.recursivePrimitivePart(cr); //System.out.println("c = " + c); //System.out.println("dr = " + dr); ar = dr.multiply(c); assertEquals("c == cont(c)pp(c)", cr, ar); } } /** * Test recursive gcd. */ public void testRecursiveGCD() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 2; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveUnivariateGcd(ar, br); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test arbitrary recursive gcd. */ public void testArbitraryRecursiveGCD() { dfac = new GenPolynomialRing(mi, 2, to); cfac = new GenPolynomialRing(mi, 2 - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); for (int i = 0; i < 2; i++) { ar = rfac.random(kl, ll, el + i, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn continue; } assertTrue("length( cr" + i + " ) <> 0", cr.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); ar = ar.multiply(cr); br = br.multiply(cr); //System.out.println("ar = " + ar); //System.out.println("br = " + br); dr = ufd.recursiveGcd(ar, br); //System.out.println("dr = " + dr); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("c | gcd(ac,bc) " + er, er.isZERO()); } } /** * Test content and primitive part. */ public void testContentPP() { dfac = new GenPolynomialRing(mi, 3, to); for (int i = 0; i < 3; i++) { c = dfac.random(kl * (i + 2), ll + 2 * i, el + i, q); //System.out.println("cr = " + cr); assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = ufd.content(c); e = a.extend(dfac, 0, 0L); b = ufd.primitivePart(c); //System.out.println("c = " + c); //System.out.println("a = " + a); //System.out.println("e = " + e); //System.out.println("b = " + b); d = e.multiply(b); assertEquals("c == cont(c)pp(c)", d, c); } } /** * Test gcd 3 variables. */ public void testGCD3() { dfac = new GenPolynomialRing(mi, 3, to); for (int i = 0; i < 3; i++) { a = dfac.random(kl, ll, el + i, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } } /** * Test gcd. */ public void testGCD() { // dfac = new GenPolynomialRing(mi,3,to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); d = ufd.gcd(a, b); //System.out.println("d = " + d); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(a, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | a " + e, e.isZERO()); e = PolyUtil. basePseudoRemainder(b, d); //System.out.println("e = " + e); assertTrue("gcd(a,b) | b " + e, e.isZERO()); } } /** * Test lcm. */ public void testLCM() { dfac = new GenPolynomialRing(mi, 3, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl, ll, el, q); b = dfac.random(kl, ll, el, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( a" + i + " ) <> 0", a.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); c = ufd.gcd(a, b); //System.out.println("c = " + c); d = ufd.lcm(a, b); //System.out.println("d = " + d); e = c.multiply(d); //System.out.println("e = " + e); c = a.multiply(b); //System.out.println("c = " + c); assertEquals("ab == gcd(a,b)lcm(ab)", c, e); } } /** * Test co-prime factors. */ public void testCoPrime() { dfac = new GenPolynomialRing(mi, 3, to); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } assertTrue("length( a ) <> 0", a.length() > 0); d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); e = a.multiply(b).multiply(c); //System.out.println("d = " + d); //System.out.println("c = " + c); List> F = new ArrayList>(5); F.add(d); F.add(a); F.add(b); F.add(c); F.add(e); List> P = ufd.coPrime(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); //P = ufd.coPrimeSquarefree(F); //System.out.println("F = " + F); //System.out.println("P = " + P); //assertTrue("is co-prime ", ufd.isCoPrime(P) ); //assertTrue("is co-prime of ", ufd.isCoPrime(P,F) ); P = ufd.coPrimeRec(F); //System.out.println("F = " + F); //System.out.println("P = " + P); assertTrue("is co-prime ", ufd.isCoPrime(P)); assertTrue("is co-prime of ", ufd.isCoPrime(P, F)); } } jas-2.5/trc/edu/jas/ufd/GCDProxyTest.java0000644000175000017500000002551712003043360020406 0ustar giovannigiovanni/* * $Id: GCDProxyTest.java 4019 2012-07-22 18:31:13Z kredel $ */ package edu.jas.ufd; //import java.util.Map; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigComplex; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GreatestCommonDivisor proxy tests with JUnit. * @author Heinz Kredel. */ public class GCDProxyTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); //ComputerThreads.terminate(); //System.out.println("System.exit(0)"); } /** * Constructs a GCDProxyTest object. * @param name String. */ public GCDProxyTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDProxyTest.class); return suite; } //private final static int bitlen = 100; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigInteger ai; BigInteger bi; BigInteger ci; BigInteger di; BigInteger ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 5; int kl = 5; int ll = 7; int el = 3; float q = 0.3f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; dfac = new GenPolynomialRing(new BigInteger(1), rl, to); cfac = new GenPolynomialRing(new BigInteger(1), rl - 1, to); rfac = new GenPolynomialRing>(cfac, 1, to); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; dfac = null; cfac = null; rfac = null; ComputerThreads.terminate(); } /** * Test get BigInteger implementation. * */ public void testBigInteger() { long t; BigInteger bi = new BigInteger(); GreatestCommonDivisor ufd_par; GreatestCommonDivisorAbstract ufd; ufd_par = GCDFactory./**/getProxy(bi); //System.out.println("ufd_par = " + ufd_par); assertTrue("ufd_par != null " + ufd_par, ufd_par != null); ufd = new GreatestCommonDivisorSubres(); //System.out.println("ufd = " + ufd); assertTrue("ufd != null " + ufd, ufd != null); dfac = new GenPolynomialRing(bi, 4, to); for (int i = 0; i < 1; i++) { // 10-50 a = dfac.random(kl + i * 10, ll + i, el, q); b = dfac.random(kl + i * 10, ll + i, el, q); c = dfac.random(kl + 2, ll, el, q); //c = dfac.getONE(); //c = c.multiply( dfac.univariate(0) ); c = ufd.primitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); /* System.out.println("\ni degrees: a = " + a.degree() + ", b = " + b.degree() + ", c = " + c.degree()); */ t = System.currentTimeMillis(); d = ufd_par.gcd(a, b); t = System.currentTimeMillis() - t; //System.out.println("i proxy time = " + t); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } // obsolete ((GCDProxy)ufd_par).terminate(); ComputerThreads.terminate(); } /** * Test get ModInteger implementation. * */ public void testModInteger() { long t; ModIntegerRing mi = new ModIntegerRing(19,true); //ModIntegerRing mi = new ModIntegerRing(536870909, true); GenPolynomial a, b, c, d, e; GreatestCommonDivisor ufd_par; GreatestCommonDivisorAbstract ufd; ufd_par = GCDFactory.getProxy(mi); //System.out.println("ufd_par = " + ufd_par); assertTrue("ufd_par != null " + ufd_par, ufd_par != null); ufd = new GreatestCommonDivisorSubres(); //System.out.println("ufd = " + ufd); assertTrue("ufd != null " + ufd, ufd != null); GenPolynomialRing dfac; dfac = new GenPolynomialRing(mi, 4, to); for (int i = 0; i < 1; i++) { a = dfac.random(kl + i * 2, ll + i, el, q); b = dfac.random(kl + i * 2, ll + i, el, q); c = dfac.random(kl, ll, el, q); //a = dfac.random(kl,ll+i,el,q); //b = dfac.random(kl,ll+i,el,q); //c = dfac.random(kl,ll,el,q); //c = dfac.getONE(); //c = c.multiply( dfac.univariate(0) ); c = ufd.primitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); //System.out.println("a = " + a); //System.out.println("b = " + b); /* System.out.println("\nm degrees: a = " + a.degree() + ", b = " + b.degree() + ", c = " + c.degree()); */ t = System.currentTimeMillis(); d = ufd_par.gcd(a, b); t = System.currentTimeMillis() - t; //System.out.println("m proxy time = " + t); //System.out.println("c = " + c); //System.out.println("d = " + d); //System.out.println("e = " + e); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); } // obsolete ((GCDProxy)ufd_par).terminate(); ComputerThreads.terminate(); } /** * Test get BigRational implementation. * */ public void testBigRational() { BigRational b = new BigRational(); GreatestCommonDivisor ufd; ufd = GCDFactory./**/getImplementation(b); //System.out.println("ufd = " + ufd); assertTrue("ufd = Primitive " + ufd, ufd instanceof GreatestCommonDivisorPrimitive); } /** * Test get BigComplex implementation. * */ public void testBigComplex() { BigComplex b = new BigComplex(); GreatestCommonDivisor ufd; ufd = GCDFactory. getImplementation(b); //System.out.println("ufd = " + ufd); assertTrue("ufd != Simple " + ufd, ufd instanceof GreatestCommonDivisorSimple); } /** * Test get AlgebraicNumber<BigRational> implementation. * */ public void xtestAlgebraicNumberBigRational() { BigRational b = new BigRational(); GenPolynomialRing fac; fac = new GenPolynomialRing(b, 1); GenPolynomial mo = fac.random(kl, ll, el, q); while (mo.isConstant() || mo.isZERO()) { mo = fac.random(kl, ll, el, q); } AlgebraicNumberRing afac; afac = new AlgebraicNumberRing(mo); GreatestCommonDivisor> ufd; ufd = GCDFactory.> getImplementation(afac); //System.out.println("ufd = " + ufd); assertTrue("ufd = Subres " + ufd, ufd instanceof GreatestCommonDivisorSubres); mo = fac.univariate(0).subtract(fac.getONE()); afac = new AlgebraicNumberRing(mo, true); ufd = GCDFactory.> getImplementation(afac); //System.out.println("ufd = " + ufd); assertTrue("ufd = Simple " + ufd, ufd instanceof GreatestCommonDivisorSimple); } /** * Test get AlgebraicNumber<ModInteger&glt; implementation. * */ public void testAlgebraicNumberModInteger() { ModIntegerRing b = new ModIntegerRing(19, true); GenPolynomialRing fac; fac = new GenPolynomialRing(b, 1); GenPolynomial mo = fac.random(kl, ll, el, q); while (mo.isConstant() || mo.isZERO()) { mo = fac.random(kl, ll, el, q); } AlgebraicNumberRing afac; afac = new AlgebraicNumberRing(mo); AlgebraicNumber a = afac.getONE(); assertTrue("a == 1 " + a, a.isONE()); GreatestCommonDivisor> ufd; ufd = GCDFactory.> getImplementation(afac); //System.out.println("ufd = " + ufd); assertTrue("ufd = Subres " + ufd, ufd instanceof GreatestCommonDivisorSubres); } } jas-2.5/trc/edu/jas/ufd/SquarefreeModLongTest.java0000644000175000017500000004257511641660762022356 0ustar giovannigiovanni/* * $Id: SquarefreeModLongTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.structure.Power; /** * Squarefree factorization tests with JUnit. * @author Heinz Kredel. */ public class SquarefreeModLongTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); ComputerThreads.terminate(); } /** * Constructs a SquarefreeModLongTest object. * @param name String. */ public SquarefreeModLongTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(SquarefreeModLongTest.class); return suite; } TermOrder to = new TermOrder(TermOrder.INVLEX); int rl = 3; int kl = 3; int ll = 4; int el = 3; float q = 0.25f; String[] vars; String[] cvars; String[] c1vars; String[] rvars; ModLongRing fac; GreatestCommonDivisorAbstract ufd; SquarefreeFiniteFieldCharP sqf; GenPolynomialRing dfac; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomialRing cfac; GenPolynomialRing> rfac; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; @Override protected void setUp() { vars = ExpVector.STDVARS(rl); cvars = ExpVector.STDVARS(rl - 1); c1vars = new String[] { cvars[0] }; rvars = new String[] { vars[rl - 1] }; fac = new ModLongRing(11); //ufd = new GreatestCommonDivisorSubres(); //ufd = GCDFactory. getImplementation(fac); ufd = GCDFactory.getProxy(fac); sqf = new SquarefreeFiniteFieldCharP(fac); SquarefreeAbstract sqff = SquarefreeFactory.getImplementation(fac); //System.out.println("sqf = " + sqf); //System.out.println("sqff = " + sqff); assertEquals("sqf == sqff ", sqf.getClass(), sqff.getClass()); a = b = c = d = e = null; ar = br = cr = dr = er = null; } @Override protected void tearDown() { a = b = c = d = e = null; ar = br = cr = dr = er = null; //ComputerThreads.terminate(); } /** * Test base squarefree. * */ public void testBaseSquarefree() { //System.out.println("\nbase:"); dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll, el + 2, q); b = dfac.random(kl, ll, el + 2, q); c = dfac.random(kl, ll, el, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbbc) " + e, e.isZERO()); } /** * Test base squarefree factors. * */ public void testBaseSquarefreeFactors() { dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll, el + 3, q); b = dfac.random(kl, ll, el + 3, q); c = dfac.random(kl, ll, el + 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } // a a b b b c d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree. * */ public void testRecursiveSquarefree() { //System.out.println("\nrecursive:"); cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, ll, el, q); br = rfac.random(kl, ll, el, q); cr = rfac.random(kl, ll, el, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(ar).multiply(br).multiply(br); cr = ar.multiply(br); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); cr = sqf.recursiveUnivariateSquarefreePart(cr); dr = sqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); assertTrue("isSquarefree(cr) " + cr, sqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, sqf.isRecursiveSquarefree(dr)); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors. * */ public void testRecursiveSquarefreeFactors() { cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2, q); br = rfac.random(kl, 3, 2, q); cr = rfac.random(kl, 3, 2, q); //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } dr = ar.multiply(cr).multiply(br).multiply(br); //System.out.println("dr = " + dr); SortedMap>, Long> sfactors; sfactors = sqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree. * */ public void testSquarefree() { //System.out.println("\nfull:"); dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, ll, 2, q); b = dfac.random(kl, ll, 2, q); c = dfac.random(kl, ll, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.squarefreePart(c); d = sqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aabbc) " + e, e.isZERO()); } /** * Test squarefree factors. * */ public void testSquarefreeFactors() { dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, 3, 2, q); b = dfac.random(kl, 3, 2, q); c = dfac.random(kl, 3, 2, q); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } d = a.multiply(a).multiply(b).multiply(b).multiply(b).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /* ------------char-th root ------------------------- */ /** * Test base squarefree with char-th root. * */ public void testBaseSquarefreeCharRoot() { //System.out.println("\nbase CharRoot:"); long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll + 2, el + 2, q); b = dfac.random(kl, ll + 2, el + 2, q); c = dfac.random(kl, ll, el, q); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.> positivePower(b, p)).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.baseSquarefreePart(c); d = sqf.baseSquarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test base squarefree factors with char-th root. * */ public void testBaseSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing(fac, 1, to, rvars); a = dfac.random(kl, ll + 2, el + 3, q); b = dfac.random(kl, ll + 2, el + 3, q); c = dfac.random(kl, ll, el + 2, q); if (a.isZERO() || b.isZERO() || c.isZERO() || a.isConstant() || b.isConstant()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.> positivePower(b, p)).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.baseSquarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } /** * Test recursive squarefree with char-th root. * */ public void testRecursiveSquarefreeCharRoot() { //System.out.println("\nrecursive CharRoot:"); long p = fac.characteristic().longValue(); cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, ll, el + 1, q).monic(); br = rfac.random(kl, ll, el + 1, q).monic(); cr = rfac.random(kl, ll, el, q).monic(); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); // a a b^p dr = ar.multiply(ar).multiply(Power.>> positivePower(br, p)); cr = ar.multiply(ar).multiply(br); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); cr = sqf.recursiveUnivariateSquarefreePart(cr); dr = sqf.recursiveUnivariateSquarefreePart(dr); //System.out.println("cr = " + cr); //System.out.println("dr = " + dr); assertTrue("isSquarefree(cr) " + cr, sqf.isRecursiveSquarefree(cr)); assertTrue("isSquarefree(dr) " + dr, sqf.isRecursiveSquarefree(dr)); er = PolyUtil. recursivePseudoRemainder(dr, cr); //System.out.println("er = " + er); assertTrue("squarefree(abc) | squarefree(aabbc) " + er, er.isZERO()); } /** * Test recursive squarefree factors with char-th root. * */ public void testRecursiveSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); cfac = new GenPolynomialRing(fac, 2 - 1, to, c1vars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); ar = rfac.random(kl, 3, 2 + 1, q).monic(); br = rfac.random(kl, 3, 2 + 1, q).monic(); cr = rfac.random(kl, 3, 2, q).monic(); if (ar.isZERO() || br.isZERO() || cr.isZERO()) { // skip for this turn return; } //System.out.println("ar = " + ar); //System.out.println("br = " + br); //System.out.println("cr = " + cr); // a a b^p c dr = ar.multiply(ar).multiply(Power.>> positivePower(br, p)) .multiply(cr); //System.out.println("dr = " + dr); SortedMap>, Long> sfactors; sfactors = sqf.recursiveUnivariateSquarefreeFactors(dr); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isRecursiveFactorization(dr, sfactors)); } /** * Test squarefree with char-th root. * */ public void testSquarefreeCharRoot() { //System.out.println("\nfull CharRoot:"); long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, ll, 3, q).monic(); b = dfac.random(kl, ll, 3, q).monic(); c = dfac.random(kl, ll, 3, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.> positivePower(b, p)).multiply(c); c = a.multiply(b).multiply(c); //System.out.println("c = " + c); //System.out.println("d = " + d); c = sqf.squarefreePart(c); d = sqf.squarefreePart(d); //System.out.println("c = " + c); //System.out.println("d = " + d); assertTrue("isSquarefree(d) " + d, sqf.isSquarefree(d)); assertTrue("isSquarefree(c) " + c, sqf.isSquarefree(c)); e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("e = " + e); assertTrue("squarefree(abc) | squarefree(aab^pc) " + e, e.isZERO()); } /** * Test squarefree factors with char-th root. * */ public void testSquarefreeFactorsCharRoot() { long p = fac.characteristic().longValue(); dfac = new GenPolynomialRing(fac, rl, to, vars); a = dfac.random(kl, ll, 3, q).monic(); b = dfac.random(kl, ll, 3, q).monic(); c = dfac.random(kl, ll, 3, q).monic(); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn return; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a a b^p c d = a.multiply(a).multiply(Power.> positivePower(b, p)).multiply(c); //System.out.println("d = " + d); SortedMap, Long> sfactors; sfactors = sqf.squarefreeFactors(d); //System.out.println("sfactors = " + sfactors); assertTrue("isFactorization(d,sfactors) ", sqf.isFactorization(d, sfactors)); } } jas-2.5/trc/edu/jas/ufd/FactorRationalTest.java0000644000175000017500000001663212003043360021655 0ustar giovannigiovanni/* * $Id: FactorRationalTest.java 4019 2012-07-22 18:31:13Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import org.apache.log4j.BasicConfigurator; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Factor rational tests with JUnit. * @author Heinz Kredel. */ public class FactorRationalTest extends TestCase { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a FactorRationalTest object. * @param name String. */ public FactorRationalTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(FactorRationalTest.class); return suite; } int rl = 3; int kl = 5; int ll = 5; int el = 3; float q = 0.3f; @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test dummy for Junit. */ public void testDummy() { } /** * Test rational univariate factorization. */ public void testRationalFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to); FactorRational fac = new FactorRational(); for (int i = 1; i < 3; i++) { int facs = 0; GenPolynomial a; GenPolynomial c = pfac.random(kl - 2, ll * i, el + i, q); // a = a.monic(); GenPolynomial b = pfac.random(kl - 2, ll, el, q); //b = b.monic(); // if ( false && ! a.leadingBaseCoefficient().isONE() ) { //continue; //ExpVector e = a.leadingExpVector(); //a.doPutToMap(e,cfac.getONE()); //} if (b.isZERO() || c.isZERO()) { continue; } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap, Long> sm = fac.baseFactors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs + ", b = " + b + ", c = " + c + ", sm = " + sm, sf >= facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } /** * Test rational multivariate factorization. */ public void testRationalMultiFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); GenPolynomialRing pfac = new GenPolynomialRing(cfac, 2, to); FactorRational fac = new FactorRational(); for (int i = 1; i < 3; i++) { int facs = 0; GenPolynomial a; GenPolynomial c = pfac.random(kl - 2, ll * i, el + i, q); // a = a.monic(); GenPolynomial b = pfac.random(kl - 2, ll, el, q); //b = b.monic(); // if ( false && ! a.leadingBaseCoefficient().isONE() ) { //continue; //ExpVector e = a.leadingExpVector(); //a.doPutToMap(e,cfac.getONE()); //} if (b.isZERO() || c.isZERO()) { continue; } if (c.degree() > 0) { facs++; } if (b.degree() > 0) { facs++; } a = c.multiply(b); //System.out.println("\na = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); SortedMap, Long> sm = fac.factors(a); //System.out.println("\na = " + a); //System.out.println("sm = " + sm); if (sm.size() >= facs) { assertTrue("#facs < " + facs, sm.size() >= facs); } else { long sf = 0; for (Long e : sm.values()) { sf += e; } assertTrue("#facs < " + facs + ", b = " + b + ", c = " + c + ", sm = " + sm, sf >= facs); } boolean t = fac.isFactorization(a, sm); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } /** * Test rational absolute factorization. */ public void testBaseRationalAbsoluteFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] alpha = new String[] { "alpha" }; //String[] vars = new String[] { "z" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, alpha); GenPolynomial agen = pfac.univariate(0, 4); agen = agen.sum(pfac.fromInteger(4)); // x^4 + 4 FactorRational engine = new FactorRational(); FactorsMap F //= engine.baseFactorsAbsoluteSquarefree(agen); //= engine.baseFactorsAbsoluteIrreducible(agen); = engine.baseFactorsAbsolute(agen); //System.out.println("agen = " + agen); //System.out.println("F = " + F); boolean t = engine.isAbsoluteFactorization(F); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } /** * Test rational absolute factorization. */ public void testRationalAbsoluteFactorization() { TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] vars = new String[] { "x", "y" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 2, to, vars); GenPolynomial xp = pfac.univariate(0, 2); GenPolynomial yp = pfac.univariate(1, 2); GenPolynomial g = xp.sum(yp); // x^2 + y^2 //GenPolynomial g = xp.subtract(yp); // x^2 - y^2 FactorRational engine = new FactorRational(); FactorsMap F //= engine.baseFactorsAbsoluteSquarefree(agen); //= engine.baseFactorsAbsoluteIrreducible(agen); = engine.factorsAbsolute(g); //System.out.println("g = " + g); //System.out.println("F = " + F); boolean t = engine.isAbsoluteFactorization(F); //System.out.println("t = " + t); assertTrue("prod(factor(a)) = a", t); } } jas-2.5/trc/edu/jas/ufd/GCDPartFracRatTest.java0000644000175000017500000003204111641660762021446 0ustar giovannigiovanni/* * $Id: GCDPartFracRatTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import java.util.SortedMap; import java.util.TreeMap; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; /** * GCD partial fraction with rational coefficients algorithm tests with JUnit. * @author Heinz Kredel. */ public class GCDPartFracRatTest extends TestCase { /** * main. */ public static void main(String[] args) { junit.textui.TestRunner.run(suite()); } /** * Constructs a GCDPartFracRatTest object. * @param name String. */ public GCDPartFracRatTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(GCDPartFracRatTest.class); return suite; } //private final static int bitlen = 100; GreatestCommonDivisorAbstract ufd; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing dfac; GenPolynomialRing cfac; GenPolynomialRing> rfac; BigRational mi; BigRational ai; BigRational bi; BigRational ci; BigRational di; BigRational ei; GenPolynomial a; GenPolynomial b; GenPolynomial c; GenPolynomial d; GenPolynomial e; GenPolynomial> ar; GenPolynomial> br; GenPolynomial> cr; GenPolynomial> dr; GenPolynomial> er; int rl = 3; int kl = 2; int ll = 3; int el = 3; float q = 0.25f; @Override protected void setUp() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; mi = new BigRational(1); ufd = new GreatestCommonDivisorSubres(); String[] vars = ExpVector.STDVARS(rl); String[] cvars = ExpVector.STDVARS(rl - 1); String[] rvars = new String[] { vars[rl - 1] }; dfac = new GenPolynomialRing(mi, rl, to, vars); cfac = new GenPolynomialRing(mi, rl - 1, to, cvars); rfac = new GenPolynomialRing>(cfac, 1, to, rvars); //System.out.println("mi = " + mi); } @Override protected void tearDown() { a = b = c = d = e = null; ai = bi = ci = di = ei = null; ar = br = cr = dr = er = null; mi = null; ufd = null; dfac = null; cfac = null; rfac = null; } /** * Test base quotioent and remainder. * */ public void testBaseQR() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 3; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a).abs(); //c = ufd.basePrimitivePart(c); do { ci = mi.random(kl * (i + 2)); ci = ci.sum(mi.getONE()); } while (ci.isZERO()); //System.out.println("a = " + a); //System.out.println("c = " + c); //System.out.println("ci = " + ci); if (a.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); b = a.multiply(c); //System.out.println("b = " + b); d = PolyUtil. basePseudoRemainder(b, c); //System.out.println("d = " + d); assertTrue("rem(ac,c) == 0", d.isZERO()); b = a.multiply(ci); //System.out.println("b = " + b); d = b.divide(ci); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); b = a.multiply(c); //System.out.println("b = " + b); d = PolyUtil. basePseudoDivide(b, c); //System.out.println("d = " + d); assertEquals("a == ac/c", a, d); b = a.multiply(c).sum( dfac.getONE() ); //System.out.println("b = " + b); //System.out.println("c = " + c); GenPolynomial[] qr = PolyUtil. basePseudoQuotientRemainder(b, c); d = qr[0]; e = qr[1]; //System.out.println("d = " + d); //System.out.println("e = " + e); e = d.multiply(c).sum(e); //System.out.println("e = " + e); assertEquals("b == b/c + b%c ", b, e); } } /** * Test base extended gcd. * */ public void testBaseExtGcd() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 3; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); //c = ufd.basePrimitivePart(c).abs(); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); if (a.isZERO() || b.isZERO() || c.isZERO()) { // skip for this turn continue; } assertTrue("length( c" + i + " ) <> 0", c.length() > 0); //assertTrue(" not isZERO( c"+i+" )", !c.isZERO() ); //assertTrue(" not isONE( c"+i+" )", !c.isONE() ); a = a.multiply(c); b = b.multiply(c); GenPolynomial[] egcd = ufd.baseExtendedGcd(a, b); d = egcd[0]; e = PolyUtil. basePseudoRemainder(d, c); //System.out.println("d = " + d); assertTrue("c | gcd(ac,bc) " + e, e.isZERO()); e = egcd[1].multiply(a).sum( egcd[2].multiply(b) ); assertEquals("gcd(a,b) = s a + t b ", d, e); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("d = " + d); GenPolynomial[] diop = ufd.baseGcdDiophant(a, b, d); e = diop[0].multiply(a).sum( diop[1].multiply(b) ); //System.out.println("e = " + e); assertEquals("d*gcd(a,b) = s a + t b ", d, e); } } /** * Test base partial fraction. * */ public void testBasePartFrac() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 3; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); b = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); c = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //a = dfac.random(kl, ll + 2 * i, el + 2 * i, q); //b = dfac.random(kl, ll + 2 * i, el + 2 * i, q); //c = dfac.random(kl, ll + 2 * i, el + 2 * i, q); //a = ufd.basePrimitivePart(a); //b = ufd.basePrimitivePart(b); //c = ufd.basePrimitivePart(c).abs(); if ( b.isZERO() || c.isZERO() ) { // skip for this turn continue; } if ( b.isConstant() || c.isConstant() ) { // skip for this turn continue; } //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); // a / (b*c) = a0 + ap/b + as/c GenPolynomial gcd = ufd.baseGcd(b,c); //System.out.println("gcd = " + gcd); if ( !gcd.isONE() ) { b = PolyUtil. basePseudoDivide(b, gcd); c = PolyUtil. basePseudoDivide(c, gcd); } //System.out.println("b = " + b); //System.out.println("c = " + c); GenPolynomial[] pf = ufd.basePartialFraction(a, b, c); //System.out.println("a0 = " + pf[0]); //System.out.println("ap = " + pf[1]); //System.out.println("as = " + pf[2]); d = pf[0].multiply(b).multiply(c); // a0*b*c //System.out.println("d = " + d); e = c.multiply( pf[1] ).sum( b.multiply(pf[2]) ); // ap * b + as * c //System.out.println("e = " + e); d = d.sum( e ); // a0*b*c + ap * c + as * b //System.out.println("d = " + d); assertEquals("a = a0*b*c + s * c + t * b ", a, d); List> D = new ArrayList>(2); D.add(b); D.add(c); //System.out.println("D = " + D); List> F = ufd.basePartialFraction(a, D); //System.out.println("F = " + F.size()); boolean t = ufd.isBasePartialFraction(a, D, F); assertTrue("a/D = a0 + sum(fi/di)", t); } } /** * Test base partial fraction list. * */ public void testBasePartFracList() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 3; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //System.out.println("a = " + a); List> D = new ArrayList>(); for ( int j = 0; j < i*3; j++ ) { b = dfac.random(kl * (i + 1), ll + i, el + i, q); if ( b.isZERO() || b.isConstant() ) { // skip for this turn continue; } D.add(b); } //System.out.println("D = " + D); D = ufd.coPrime(D); //System.out.println("D = " + D); List> F = ufd.basePartialFraction(a, D); //System.out.println("F = " + F.size()); boolean t = ufd.isBasePartialFraction(a, D, F); assertTrue("a = a0*b*c + s * c + t * b ", t); } } /** * Test base partial fraction exponent. * */ public void testBasePartFracExponent() { dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 3; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //System.out.println("a = " + a); b = dfac.random(kl * (i + 1), ll + i, el + i, q); if ( b.isZERO() || b.isConstant() ) { // skip for this turn continue; } //System.out.println("b = " + b); List> F = ufd.basePartialFraction(a, b, 3); //System.out.println("F = " + F); boolean t = ufd.isBasePartialFraction(a, b, 3, F); assertTrue("a/b^e = a0 + sum(ai/p^i) ", t); } } /** * Test base partial fraction list exponent (squarefree). * */ public void testBasePartFracListExponent() { SquarefreeAbstract sqf = SquarefreeFactory.getImplementation(mi); dfac = new GenPolynomialRing(mi, 1, to); for (int i = 0; i < 3; i++) { a = dfac.random(kl * (i + 2), ll + 2 * i, el + 2 * i, q); //System.out.println("a = " + a); List> D = new ArrayList>(); for ( int j = 0; j < i*3; j++ ) { b = dfac.random(kl, ll + 1 + i, el + i, q); if ( b.isZERO() || b.isConstant() ) { // skip for this turn continue; } D.add(b); } //System.out.println("D = " + D); D = ufd.coPrime(D); //System.out.println("D = " + D); SortedMap,Long> Ds = new TreeMap,Long>(); long j = 1L; for ( GenPolynomial p : D ) { Ds.put(p,j); j++; } //System.out.println("Ds = " + Ds); List>> F = sqf.basePartialFraction(a, Ds); //System.out.println("F = " + F.size()); boolean t = sqf.isBasePartialFraction(a, Ds, F); assertTrue("a/prod(b_i^i) = a0 + sum(aij/b_i^j) ", t); } } } jas-2.5/trc/edu/jas/ufd/SquarefreeTest.java0000644000175000017500000001645411641660762021073 0ustar giovannigiovanni/* * $Id: SquarefreeTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.jas.ufd; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.RingFactory; /** * Squarefree Factory tests with JUnit. * @author Heinz Kredel. */ public class SquarefreeTest extends TestCase { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a SquarefreeTest object. * @param name String. */ public SquarefreeTest(String name) { super(name); } /** */ public static Test suite() { TestSuite suite = new TestSuite(SquarefreeTest.class); return suite; } @Override protected void setUp() { } @Override protected void tearDown() { ComputerThreads.terminate(); } /** * Test factory specific. * */ public void testFactorySpecific() { ModIntegerRing mi = new ModIntegerRing(19, true); Squarefree sqfm = SquarefreeFactory.getImplementation(mi); //System.out.println("sqfm = " + sqfm); assertTrue("sqf != Modular " + sqfm, sqfm instanceof SquarefreeFiniteFieldCharP); ModLongRing ml = new ModLongRing(19, true); Squarefree sqfml = SquarefreeFactory.getImplementation(ml); //System.out.println("sqfml = " + sqfml); assertTrue("sqf != Modular " + sqfml, sqfml instanceof SquarefreeFiniteFieldCharP); BigInteger bi = new BigInteger(1); Squarefree sqfi = SquarefreeFactory.getImplementation(bi); //System.out.println("sqfi = " + sqfi); assertTrue("sqf != Integer " + sqfi, sqfi instanceof SquarefreeRingChar0); BigRational br = new BigRational(1); Squarefree sqfr = SquarefreeFactory.getImplementation(br); //System.out.println("sqfr = " + sqfr); assertTrue("sqf != Rational " + sqfr, sqfr instanceof SquarefreeFieldChar0); GenPolynomialRing pmfac = new GenPolynomialRing(mi, 1); GenPolynomial pm = pmfac.univariate(0); AlgebraicNumberRing am = new AlgebraicNumberRing(pm, true); Squarefree> sqfam = SquarefreeFactory. getImplementation(am); //System.out.println("sqfam = " + sqfam); assertTrue("sqf != AlgebraicNumber " + sqfam, sqfam instanceof SquarefreeFiniteFieldCharP); GenPolynomialRing prfac = new GenPolynomialRing(br, 1); GenPolynomial pr = prfac.univariate(0); AlgebraicNumberRing ar = new AlgebraicNumberRing(pr, true); Squarefree> sqfar = SquarefreeFactory . getImplementation(ar); //System.out.println("sqfar = " + sqfar); assertTrue("sqf != AlgebraicNumber " + sqfar, sqfar instanceof SquarefreeFieldChar0); prfac = new GenPolynomialRing(br, 2); QuotientRing qrfac = new QuotientRing(prfac); Squarefree> sqfqr = SquarefreeFactory. getImplementation(qrfac); //System.out.println("sqfqr = " + sqfqr); assertTrue("sqf != Quotient " + sqfqr, sqfqr instanceof SquarefreeFieldChar0); pmfac = new GenPolynomialRing(mi, 1); QuotientRing qmfac = new QuotientRing(pmfac); Squarefree> sqfqm = SquarefreeFactory. getImplementation(qmfac); //System.out.println("sqfqm = " + sqfqm); assertTrue("sqf != Quotient " + sqfqm, sqfqm instanceof SquarefreeInfiniteFieldCharP); } /** * Test factory generic. * */ @SuppressWarnings("unchecked") public void testFactoryGeneric() { ModIntegerRing mi = new ModIntegerRing(19, true); Squarefree sqfm = SquarefreeFactory.getImplementation((RingFactory) mi); //System.out.println("sqfm = " + sqfm); assertTrue("sqf != Modular " + sqfm, sqfm instanceof SquarefreeFiniteFieldCharP); ModLongRing ml = new ModLongRing(19, true); Squarefree sqfml = SquarefreeFactory.getImplementation((RingFactory) ml); //System.out.println("sqfml = " + sqfml); assertTrue("sqf != Modular " + sqfml, sqfml instanceof SquarefreeFiniteFieldCharP); BigInteger bi = new BigInteger(1); Squarefree sqfi = SquarefreeFactory.getImplementation((RingFactory) bi); //System.out.println("sqfi = " + sqfi); assertTrue("sqf != Integer " + sqfi, sqfi instanceof SquarefreeRingChar0); BigRational br = new BigRational(1); Squarefree sqfr = SquarefreeFactory.getImplementation((RingFactory) br); //System.out.println("sqfr = " + sqfr); assertTrue("sqf != Rational " + sqfr, sqfr instanceof SquarefreeFieldChar0); GenPolynomialRing pmfac = new GenPolynomialRing(mi, 1); GenPolynomial pm = pmfac.univariate(0); AlgebraicNumberRing am = new AlgebraicNumberRing(pm, true); Squarefree> sqfam = SquarefreeFactory.getImplementation((RingFactory) am); //System.out.println("sqfam = " + sqfam); assertTrue("sqf != AlgebraicNumber " + sqfam, sqfam instanceof SquarefreeFiniteFieldCharP); GenPolynomialRing prfac = new GenPolynomialRing(br, 1); GenPolynomial pr = prfac.univariate(0); AlgebraicNumberRing ar = new AlgebraicNumberRing(pr, true); Squarefree> sqfar = SquarefreeFactory .getImplementation((RingFactory) ar); //System.out.println("sqfar = " + sqfar); assertTrue("sqf != AlgebraicNumber " + sqfar, sqfar instanceof SquarefreeFieldChar0); prfac = new GenPolynomialRing(br, 2); QuotientRing qrfac = new QuotientRing(prfac); Squarefree> sqfqr = SquarefreeFactory.getImplementation((RingFactory) qrfac); //System.out.println("sqfqr = " + sqfqr); assertTrue("sqf != Quotient " + sqfqr, sqfqr instanceof SquarefreeFieldChar0); pmfac = new GenPolynomialRing(mi, 1); QuotientRing qmfac = new QuotientRing(pmfac); Squarefree> sqfqm = SquarefreeFactory.getImplementation((RingFactory) qmfac); //System.out.println("sqfqm = " + sqfqm); assertTrue("sqf != Quotient " + sqfqm, sqfqm instanceof SquarefreeInfiniteFieldCharP); } } jas-2.5/trc/edu/mas/0000755000175000017500000000000012140140260014456 5ustar giovannigiovannijas-2.5/trc/edu/mas/kern/0000755000175000017500000000000012140140260015415 5ustar giovannigiovannijas-2.5/trc/edu/mas/kern/LISTTest.java0000644000175000017500000001612511641660762017723 0ustar giovannigiovanni/* * $Id: LISTTest.java 3789 2011-10-01 18:54:43Z kredel $ */ package edu.mas.kern; import edu.jas.arith.BigRational; import static edu.mas.kern.LIST.*; import java.util.List; import java.util.ArrayList; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; /** * Basic list processing tests with JUnit. * @author Heinz Kredel. */ public class LISTTest extends TestCase { /** * main. */ public static void main (String[] args) { junit.textui.TestRunner.run( suite() ); } /** * Constructs a LISTTest object. * @param name String. */ public LISTTest(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite= new TestSuite(LISTTest.class); return suite; } boolean timing =false; protected void setUp() { //a = b = c = d = e = null; } protected void tearDown() { //a = b = c = d = e = null; } /** * Test static initialization LIST. */ public void testLISTinit() { LIST a = null; assertTrue("a == () ", isEmpty(a) ); assertEquals("len(a) == 0 ", LENGTH(a), 0 ); a = new LIST(); assertTrue("a == () ", isEmpty(a) ); assertEquals("len(a) == 0 ", LENGTH(a), 0 ); //System.out.println("a = " + a); a = new LIST( a.list ); assertTrue("a == () ", isEmpty(a) ); assertEquals("len(a) == 0 ", LENGTH(a), 0 ); } /** * Test static LIST creation. */ public void testLISTcreate() { Object five = 5; LIST a = null; assertTrue("a == () ", isEmpty(a) ); assertEquals("len(a) == 0 ", LENGTH(a), 0 ); //System.out.println("a = " + a); a = LIST1( five ); assertFalse("a != () ", isEmpty(a) ); assertEquals("len(a) == 1 ", LENGTH(a), 1 ); //System.out.println("a = " + a); a = COMP( five, a ); assertFalse("a != () ", isEmpty(a) ); assertEquals("len(a) == 2 ", LENGTH(a), 2 ); //System.out.println("a = " + a); LIST b = LIST2(five,five); assertFalse("b != () ", isEmpty(b) ); assertEquals("len(a) == 2 ", LENGTH(a), 2 ); assertTrue("a == b ", EQUAL(a,b) ); } /** * Test static LIST operations. */ public void testLISToper() { Object five = 5; LIST a = LIST1( five ); assertFalse("a != () ", isEmpty(a) ); assertEquals("len(a) == 1 ", LENGTH(a), 1 ); a = COMP( five, a ); assertFalse("a != () ", isEmpty(a) ); assertEquals("len(a) == 2 ", LENGTH(a), 2 ); LIST b = CINV(a); assertFalse("b != () ", isEmpty(b) ); assertEquals("len(a) == 2 ", LENGTH(a), 2 ); assertTrue("a == b ", EQUAL(a,b) ); LIST c = INV(a); assertFalse("c != () ", isEmpty(c) ); assertEquals("len(c) == 2 ", LENGTH(c), 2 ); assertTrue("a == c ", EQUAL(a,c) ); //System.out.println("a = " + a); //System.out.println("c = " + c); } /** * Test static LIST many elements. */ public void testLISTelems() { int max = 100; Object n; LIST a = null; for ( int i = 0; i < max; i++ ) { n = i; a = COMP( n, a ); } assertFalse("a != () ", isEmpty(a) ); assertEquals("len(a) == "+max+" ", LENGTH(a), max ); //System.out.println("a = " + a); LIST b = CINV(a); assertFalse("b != () ", isEmpty(b) ); assertEquals("len(b) == "+max+" ", LENGTH(b), max ); //System.out.println("b = " + b); b = INV( b ); assertFalse("b != () ", isEmpty(b) ); assertEquals("len(b) == "+max+" ", LENGTH(b), max ); //System.out.println("b = " + b); assertTrue("a == INV(CINV(a)) ", EQUAL(a,b) ); } /** * Test static LIST destructive operations. */ public void testLISTdestruct() { Object n = 5; LIST a = LIST1( n ); LIST b = LIST1( n ); assertEquals("len(a) == 1 ", LENGTH(a), 1 ); assertEquals("len(b) == 1 ", LENGTH(b), 1 ); SRED(a,b); assertFalse("a != () ", isEmpty(a) ); assertFalse("b != () ", isEmpty(b) ); assertEquals("len(b) == 1 ", LENGTH(b), 1 ); assertEquals("len(a) == 2 ", LENGTH(a), 2 ); //System.out.println("a = " + a); n = 7; SFIRST(a,n); //System.out.println("a = " + a); assertEquals("len(a) == 2 ", LENGTH(a), 2 ); LIST c = COMP( n, b ); assertEquals("len(c) == 2 ", LENGTH(c), 2 ); assertTrue("a == c ", EQUAL(a,c) ); } /** * Test static LIST recursive structures. */ public void testLISTrecursive() { Object n = 5; LIST a = LIST1( n ); LIST> b = LIST2( a, a ); LIST>> c = LIST3( b, b, b ); //System.out.println("a = " + a); //System.out.println("b = " + b); //System.out.println("c = " + c); assertEquals("len(a) == 1 ", LENGTH(a), 1 ); assertEquals("len(b) == 2 ", LENGTH(b), 2 ); assertEquals("len(c) == 3 ", LENGTH(c), 3 ); //System.out.println("EXTENT(a) = " + EXTENT(a)); //System.out.println("EXTENT(b) = " + EXTENT(b)); //System.out.println("EXTENT(c) = " + EXTENT(c)); assertEquals("EXTENT(a) == 1 ", EXTENT(a), 1 ); assertEquals("EXTENT(b) == 2 ", EXTENT(b), 2 ); assertEquals("EXTENT(c) == 6 ", EXTENT(c), 6 ); //System.out.println("ORDER(a) = " + ORDER(a)); //System.out.println("ORDER(b) = " + ORDER(b)); //System.out.println("ORDER(c) = " + ORDER(c)); assertEquals("ORDER(a) == 1 ", ORDER(a), 1 ); assertEquals("ORDER(b) == 2 ", ORDER(b), 2 ); assertEquals("ORDER(c) == 3 ", ORDER(c), 3 ); } /** * Test static LIST rational content. */ public void testLISTcontent() { int max = 5000; long t0, t1; BigRational cf = new BigRational(2,3); BigRational n; LIST a = null; t0 = System.currentTimeMillis(); for ( int i = 0; i < max; i++ ) { n = cf.random(5); a = COMP( n, a ); } t1 = System.currentTimeMillis(); if ( timing ) System.out.println("t.comp = " + (t1-t0)); //System.out.println("a = " + LENGTH(a)); assertEquals("len(a) == "+max+" ", LENGTH(a), max ); List b = new ArrayList(); /* is/was inefficient */ LIST ap = a; t0 = System.currentTimeMillis(); while ( ! isEmpty( ap ) ) { n = FIRST(ap); ap = RED(ap); b.add( n ); //System.out.println("n = " + n); } t1 = System.currentTimeMillis(); if ( timing ) System.out.println("t.red = " + (t1-t0)); //System.out.println("b = " + b.size()); assertEquals("size(b) == "+max+" ", b.size(), max ); b = new ArrayList(); int len = LENGTH( a ); t0 = System.currentTimeMillis(); for ( int i = 0; i < len; i++ ) { n = LELT(a,i); b.add( n ); } t1 = System.currentTimeMillis(); if ( timing ) System.out.println("t.lelt = " + (t1-t0)); //System.out.println("b = " + b.size()); LIST c = new LIST( b ); //System.out.println("c = " + LENGTH(c)); assertEquals("len(c) == "+max+" ", LENGTH(c), max ); assertTrue("a == c ", EQUAL(a,c) ); } } jas-2.5/images/0000755000175000017500000000000012140140260013576 5ustar giovannigiovannijas-2.5/images/device-2012-11-18-jas-examples-thumb.png0000644000175000017500000002626312054221644022321 0ustar giovannigiovanni‰PNG  IHDRÈU%µ7àsBITÛáOà pHYsÄÄ•+ IDATxœíÝyxSUÚðsoö­iÒ´MÒ%mÒ}/¥-¥”ta_díÊ"8lNÅTú øß£#ú}*££ãȰŒ#Ì¢,Ö" ËÐÖRºÓ½MWš4MÚìËýþ¸N¦)¨¨] ¼¿?xš›÷ž{NžÃMrï›÷ À(  L¡xzzšÍf×¹\n6›ív;BˆÉdÊd2­V;¦}cH X­V‚@Eà’Ó¢î&öŸÚuØãàààÈÈÈ®®®’’r‹D"Y·nA†QXXØØØ8#÷6›ZZZJP(Û^ ó󽕖}ý½—û®_BñSfRxž}…G]{yNkÐ"'AúÒ<½nü BÚ®R©äñx&--͵1''Çßß_.—‹D¢ªªª¡O‰„F£I$•JE>¤àøæÔ0.ã?§]QÝK<ôND…Íc+bh^ƒU׃ýºâsd°ÛÄjkk Žýâ‹/\­VëöíÛÏž=ÛÚÚúÏþ³««k´GÆŽãAAAMMM®-A|ÓÒcs8`/Cí·Þm°t·Ñ}ýBÌÀ0Kw+ù”Û[ass3B($$dè¬Vëk¯½f±X‚x÷ÝwoÞ¼9‚ã÷ˆ   ææf‚ \[œºÔ|Kk² sp"’z?ÿˆé¯`ú)B•æŠÄ† ###44ôÃ?tma2™ñññ!ÔßßãÆ “É4ÂÃãÊËËËÓÓÓb± „˜LfSS“ä3r1*¨ïú7¦®Öñî#!„0Ç< ˜°†xGM{d;q§íCiÚnÖ~s|tº&‚áWÞBlÿX³!„¨8F äp~÷ “E§š­vò>_ Á¹ÃÄrØ,ÂZ<5$À>ðe—• &ú›Dï'¾h0ÛBN»uÌ» î'wšXV‹Óe‚©Çö£î®ÇÂi4Òµnzbõ¦7ºh³ÝùÓïJ‚Êðì„bŽŸ€½Mj'ÚÛ0‘ˆððÀ¼¼.— ¹šîÄyÓÏ×v4}Í7ÈxòšªÅbp5²råÊÊÊÊa-cØðnr¹Üf³¥¦¦’-à8®T*¥Riww·ÃáÑ‘‚1u‡‹X›%‘muªoi zWþ¹úôéÞãÇ5gÏê««y5¡"¦ÓasÅçåå ¼öÚkÞÞÞÀÃÃC (•Ê)S¦°X,ÇSRR¼½½“““ß|óMƒEî»téÒ   W ±±±J¥’ÃáäççÑ FÇß cêKú³gã6þ»oÖï>NѺ¶>ëñòK±+6}cÿÏÄ¢Óé‰Ä`0$&&²X,½^Ïçóår¹¯¯ïîÝ»Õjukkëo~ó›C‡ñx¼¸¸¸eË–Æ‹/ž?~X v»=,,ŒJ¥¶··þØÁ(ºãËlµZÌvûþVsïú­V*Õ‚ÃÏïò’õ§ëz,v»ÍazÆ2›ÍÍÍÍ, Ã0ÇÉ÷»›7ož8qÂÛÛ;44ôèÑ£ ‡C¥R…‡‡Ÿ:uêÓO?jg·‘ü£´zphŒÓöCgàþïøãx÷L@د85Tê¾ÞÞ&Ì@&ÈOt˜LæxwadL˜L‰î50±À¨€‰FÅR“GŠX,–H$ …B¯×'%%™L¦Ñ+ú@§Ó­Öû}NOMMõôôôõõõööÖjµ2™,,,L&“ ÆÅÅY,…BáëëÛÛÛ;Ruz¤B£ÑRSSu:]@@€H$b0ÑÑÑäX˜Lftt´^¯—Éd&“)>>^§Óàk8б6mÚ”’’ÒÖÖF„T*u8yyy£t,.—;88øãqwG*•¾öÚkû÷ïߺukqq±^¯ŒŒ,++KKK«­­µÙlIII§­­íĉ×®]©ã¢ÈêÕ«úûûcbbº»»F#A^^^B¡°²²ÒápÄÄÄ\¹r%--­®®ŽËåÖ××;vlDÆà­0 Àd2ñùüû+†ËåR©T‹ÅrñâÅÀÀ@„PYYYKK ›Í¾|ù²Óé¤ÓéR©ô‡S€ÆWyy¹ÝnŒŒlooÿôÓONgpp°Ñø]VB¡øì³ÏÈA]¸pÁn·‹Åâ<ú(¾zxx †Ã‡‹Åb‡ÃQUUuãÆQ:ÖȾR©Ô“Éd4ÃÂÂ>L¡Pêêêp?wîÜš5k®]»ÖÞÞþñÇs¹Ü‘MÏÁH$’ÈÈÈË—/óùüðððòòò“'OŠD¢öööæææ3gΔ––ÒétÇ CddduuuCCÈzâàr¹ãÝ…‘1aß Á¨€‰FL,0*`bQÉX÷n̺ÿx÷bP61NZÄÄøOâ=púCãÝ‹€‰æ®ï>ŒKW+C"ï^Œ §pÂÇ»Àh¢Ñh4íÇã†Äÿ’cýì}G¶0˜LæÎ;ûÛߺ’7þçþgéÒ¥ç.[øIÁüòÊ+·—U—FÀ/çöóÈéÓ§WVVÆyóæ9Žàà`çt:BO<ñ„P(¬­­ˆˆøàƒ:::È]òòò¼¼¼>ûì³àà`™LÖÒÒr{0“É\¹reUUUuuõ‚ p?räHlllUU™%öðÃÇÅÅÑh´-[¶`öî»ï>þøã‡ãý÷ßß´iNçw{챡Í&%%÷÷÷8p!´téR™LÆf³·mÛæÚÆ‹Ûý²æ±N§óòòš={6Y&”¬ªðöÛoÏŸ?ÿèÑ£«Wÿçbý¤I“^}õÕÇ\©Tþõ¯MMM½=X$¯[·ÎÏÏO§Ó]¸pañâŹ¹¹‡cýúõiii[·nÝ·o_ww÷ìÙ³CCC_|ñÅÖÖÖÒÒÒµk×vtt”––®\¹rX³999~øaRR’P(D‘@8p !!ÁËËkl_IàÆmb ¡P( õz½Íf#•¨n04MÿÀÀ›Ívíb³Ù…BAõõõÝ1xÙ²e‡ƒ\±¯¯¯¸¸8))©££C­VŸ={¶ººšF£9›ÍF£Ñ:;;<ØÜÜl·ÛÕjµÝn·ÛíV«•J¥ÞÞ§Ói4Ùl6•J%‚ìA&“‰Á`ŒÉ îÌ-ç½££cþüù~~~}ô‘P(ÌÉɹqãFGGGmm-‡Ã©¨¨555t:=...&&ÆÛÛ{Μ9 …âÓO?Õëõžžž·777'''755•––Æ®®®”””£Gvuu X,–îîîM›6i4šƒ¦§§+ŠcÇŽÍž=[¡P>|xîܹr¹üƒ>Ölppphh¨N§«««‹ˆˆ0 l6{ÆŒ:¾¯×ü|ÁÁÁÁÁÁ‰ä¿þë¿~ê¾ÑÑѯ¾úê/ïC~~>|N !D¥R'L½/0îÌf³ÝëKp_Â0,33sÆŒ®[%>úèèåc=úè£?£“£Ñqn7¡'Ožœžž.X,AÑÑÑ3gÎÝÓÓ³råÊI“&i4šÇ|pppæÌ™qqq~~~3gÎ,--Ý·oy¬/¿ü!ôá‡,[¶ìêÕ«¿þõ¯Éàá–åp8¨T*…B¡R©¦  Àfûn‰^•Juâĉ¶¶¶óçÏûûÿ§j…J¥úꫯ„B!†aŸ}öÙƒ#""Äbñõë×CBB²³³ýüü\»ž <{öìž={‚‚‚Μ9ÓÚÚ*‹ËÊÊ.]ºtýúõšš___ױȣ455UUU555º6‚{„ÛÄ*))Y¼xñªU«N:E£Ñ^xá…ÁÁA“ÉDæÓ!„ ƒÃá0™Lžžžžžž\.7<<ü¥—^*//'×{¾cðçŸ.¬VkIIÉššš\»ž:wîÜ®]»^|ñÅÂÂÂÝ»w ‚††«ÕjµZm6›Ùlv8®c-Y²„Çã‘G‘H$ùùùãñê»F§ÓÉÜKÇY,Ö÷…mܸqÓ¦M .|ã7î¦l&‡Ã!³LICw=åúÔÏápî˜hõ}Çš0u;ÁLÈcüFäcp_ãr¹<Ïõ0111..ŽN§ÿ¤F½¼¼ärùíOݾ=1ÊšO@n7¡~ÿûßïÝ»744”F£q8œõë×c†aƒÁàñx eØ9ƒÁd2)Šk:òx<×^!.—KÞ $×,%†î»aÃU&·Âk 'Nœ0Ó¦MÛ¼ysww7F[°`J¥zûí·ëëë}}}ûûû É]>~èáÈ}«««_yå•)S¦ŒÑˆÁ˜p›X---ׯ_ …™™™Cs]ìv;AN§sèF‚ pÏÉÉinnÆ0L­VϘ1C&ûnY›ÎÎΜœœÜÜÜåË————»öJHH`0dU·   ¥R9000ºckø'›ääd*•zõêU…BØÜÜŒã¸J¥’Éd !!!*•J"‘äææâ8ÞÖÖV\\ÜÐД”äp8 CWW×ôéÓÛÛÛ[ZZ8NÿôéÓ+**È úÎÎÎööv‡Ãd2ÛÛÛÉ6£¢¢d2Ùµk×\w€!„0 #keðË9N‚ ¨! Ã~êM¾Õju8ãÝ €‡Ãa³Ù?#§åçí5ìпdw0¾Ü®2°ÙìÝ»wïÙ³‡Ïç“[víÚ•=t¹¯»´cÇ@ð£aQQQßW(f×®]?õ àÞáV+;;ûÖ­[ qqq sçÎõööîììlhhxê©§fÍš¼lÙ²–––þþ~r—;vøùù…‡‡¯\¹²­­mÆŒ¹¹¹jµzÒ¤IW¯^% ÂDFFnܸÑh4®^½:33³¬¬lÁ‚+V¬Ðét/¼ð‚T*5™L›6mâp8õõõ®6³²²""", ¹X&¸¿¸±˜LæàààÀÀ€——WFFÆ[o½EĤI“˜Lfhhè›o¾©T*>¼bÅ ×.'OžÜ²e‹J¥"«6ÖÖÖ®Y³fh³¾¾¾]]]~~~ W®\Y»víÌ™3_y啼¼¼ââ⯾ú*''§®®Î•qìØ1Fóûßÿ~Æ £þ€Qà6±ôz½X,öõõÕh4A ½jj2™´Z­^¯7 CË 8ξ¾¾’’’ƒ.Y²d``€JuKLEét:‚ h4…B!‚Ìu&ÂápÐéôo¿ý¶»»{É’%d#²MÇ Ü¸O¹½vvvfffz{{:tˆÅbMŸ>½¤¤¤­­­¾¾žF£ÕÔÔ°Ùì›7o"„RRRâââÄbqwwwEE…ÕjMKKkoo§P(L&³®®®¥¥Ål6Ïž=;..Îét¶´´\»v-;;Ûßßÿƒ>°Ûí‹-:pà@CCCrrr[[[FFÆ¥K—üüüºººÈcùùù)•ÊcÇŽÁ[áýèg~qóóóCY,µZý}1L&“\˜¹¿¿Ÿ¬÷øù ðaPx €‰aÛ¶m?ð,Žãà e¹R¸B,+77wXm™ØØØ´´´‘í$¸g¹å`6uêÔŒŒ Ãâââ0 S*•S§N•J¥ßEãxfffrrrFFÆÿþïÿr82ÞÛÛûÀ®R}䯔J%ùP$¥§§ÇÇǧ§§Ïš5kh±0Q¹M,ooïøøø¥K—FGG#„âãã³²²’““]Å«bccçÏŸŸ‘‘A¥RÍf³@ ã …Ãáp•"²Z­dÊ)&&fîܹƒƒƒ</<<|öìÙc5:0nÜ&–X,–J¥,ËÓÓ!xåÊ•¡u­ZZZjjjd2™F£Q«ÕB¡Œ§R©z½¾··÷ûóí·ßö÷÷———_¸p!,,lôÆînyT*U 8N»ÝÞ××W\\¼gχÃñÍ7ß«ªúúú’U!ûûûår¹P(tÅ÷ôô(•ÊÆÆF„P¿Íf#O`k×®­¯¯7‹E©Tfggïß¿\† ÆÒð|,&“i6›]}ôÑØØØ‹/’Õ‹‹‹››› ‚°Ûí Ãb±¸â)J``àÔ©SɰºººÛ†ã8NÚ>x@) WÝGp—  Œ0ÈÇ`b˜6mÚÏÞÇq__ß¡ jk}MxÃk¹ðx<„Y“ˆÏçóx¼¡egø|>‡Ã Ú²e ŽãdX zs›Xñññ Å`0oR*•*++‹Ì„!I$’–––ˆˆ>ŸïïšêŠ'" àöÈd²9sæôõõ¥¦¦2™LrñËàààyóæiµÚQ7nùX4-%%¥««K­V ‚ÖÖÖ%K–Lš4©§§‡¬a\XXH„Åb©¬¬LII©ªªJHH ã…B¡\.ONNFÔÔÔðx¼[·n½ÿþû,++ãñx===‰D¥RÉårÿ²²2½^?>ããkíÚµ<òÈ/Yi'++kûp_øn!ÌÛ hðóØíöÿ,„ ÁÁHÁ0Œ¼¨ÆÊݬ68›Í‰DwÉ`0†.ó&¤ïý2øòË/ÿ¤†~÷»ßEEEÝMdjjêŒ3~Rãà¾ãvùŠÍf?ýôÓT*õµ×^#Ï+/¾ø¢Ñh<þü¿þõ/„ŸÏòÉ'-KAA•J5™Ll6{Þ¼yƒ!--íäÉ“;wî$w_¶lYHHÈ'Ÿ|yøðáÚÚÚ˜˜˜åË—«Õ길¸´´´×_]£ÑŒÓÀÁ辦J¥"˯!„ÒÓÓ+++ËÊÊ\ý$‰§§g[[›¿¿¿D"‰D‰ÄßßÿøC}}}ee%¹{jjê”)S^}õU©Tº~ýúÎÎÎU«V!„D"QcccUUÕ… NŸ>½dÉ’±0ng¬É“'{{{ ²š#A,Ëáp¸®wÙl¶3gÎäææ~ýõ×\.—Á`X­VƒÁàt:‡îŽã8•Jåñx‡C­V_ºtÉh4zyya688HÇc±XpmsKMÖëõIIIMMMUUUz½þ«¯¾ÊÌÌŒu:QQQ‰‰‰ƒ!..N¥R;v,%%!TVV¦ÕjÉ…w¯]»Fî^^^~ëÖ­œœœK—.©Tª©S§ªTª˜˜˜úúzN§V«årù_ÿúW‹Å2N£ëGÂܹs§§§ç[o½EVK0™LcÒ1€;(¼F^`bxþùç‡>\¶lYN-66önvOLLÌÈÈ®û€[v†a3fÌ P(gÏž Ç0lîܹV«µ®®îÙgŸ¥R©IIIL&³¸¸899Y¥REGGóù|•J%¾üòK„¯¯o||¼T*õóó‰D'Ož„/Ÿ ·ìŸ”””´´´®®®ÔÔÔŽŽŽôôt6›Íçó½¼¼¼½½»»»ù|~NNÎÙ³gŸþù¾¾¾I“&ùùùñùü”””ÚÚZN—œœœžžÞÔÔäãヒJ¥7oÞ§Ñqã–èçïï/“Éèt:Y-R*•^¿~œAìÛ·oëÖ­äß …ÌÙjll¼qãF]]]kk«P($Û©¨¨¨««+**"k¸ÛIJÛíÀn·[,–ÎÎÎk×®-^¼xÅŠAtvv¶µµ?~\«Õž;wn÷îÝ|>ß`0èõúƒÁÐ××g6›×®]k4õz½Ñhœ:uêÆOŸ>=^c÷a¥°6oÞüæ›oÆÅÅýpØaöK k‰Ìßß_,w/î3Fäc01̘1C,GGGß¾ýîQ*•#Ú)pß^xM(zyy!„V®\”––æzÊÓÓÓËËK­V3 OOOòV›Í‹Å<Çq×ÍA2877×ßߊÈ?€†/„ùä“OΛ7¯¢¢"33³´´ÔÇǧ´´”|öoû[{{ûÊ•+u:ÝÆ322ººº¶oß. —.]©T*/_¾ì ^´hAÓ¦M»zõê8 Œ·3F³Z­\.W&“ݪR© Øl6•J½råÊÉ“' Bè½÷Þ£Óé555>>>---Cƒkjjöïßûû)˜ðÜ&Vdd$N·X,w³PAd µåË—3™Ì¨¨¨ŠŠŠ9sæddd¸j×Êåò_ýêW½½½£Òwps«E¥RcbbnݺÕßßïááÑßßÏ`06oÞŒaX[[[aaá­[·Äb±^¯ÇqÜétâ86yòäüüüÈÈÈææf …¢Õj½¼¼nݺ%•JÅbñÍ›7 ÃxÜ—’““×®]ëëë;Þ¸‡`!²zöx÷Lv»ÝétRÑ¿/ŒwÀs `œ¸.©³X,.—;ìÙ;nýÀB˜¤äädiÓ¦%''gggßþìí@Ãò±x<ÞK/½4sæÌ¢¢¢—_~Y({{{oÛ¶­ººzÖ¬Y999åå僃ƒñññO=õ›ÍÎÌÌÌÈȸqãÜfC¹±¨TªJ¥ …±±±žžžŸ|òITTTQQQqq±N§»xñâÙ³gÉÕäAEEEUUUAAÁ§Ÿ~ KZ‚aÜ&VJJЇ‡ÇÀÀ…B1›Íä•.‡ÃÁf³q·Z­‹…J¥J$ ÃL&AÞÞÞB¡–ø½jµÚ¸¸¸ÚÚÚššFÓÔÔd³ÙÊÊÊBCC+**zzzÔju___XXX}}½V«ííí‰Dþþþ‡²Ùlã5?^# ¯0=÷Üs†ýpŒ¿¿ÿ<;yò䬬¬í¸¹Ý„Æqü¡‡ŠŽŽ¾yóæÜ¹s###322h4Ú¬Y³ššš/^Ìf³}||ìv{NNŽŽãG$EDDdee™L¦wß}÷úõë‰dÞ¼yÍÍÍ999ÍÍÍ~~~999ÁÁÁ R©´¶¶ÖétŽ×°ÁhsK›ñòòâóùéééñññëׯ///_½zuiiésÏ=×ÖÖöè£"„jkk~øá¤¤¤ððp¿mÛ6F¨Õj;::víÚe±X~ó›ßí „BCCÃÃÃ;;;u:†a .—ƒ±á6±‚ƒƒår9…Báp8]]]½½½jµº¬¬¬»»»¾¾ž\ç²®®®««K ÔÕÕ :N¡P0 ;tèPBB‚‡‡‡Ùl¶Ùl4Í`0œ={–l‡l¿®®Îd2µµµUVVŒÃZª[ JIDATpÁXq›XƒƒƒÀf³ÆÖÖV„ë_‹ÅÒÑÑQWW·}ûv&“Y]]­ÕjËËË322233ûúúRRRX,–V«­¯¯‰‰¹páBll,›Í&[X·nÝÀÀ€V«˜?--íĉGŽÉÌÌDá8^PPÐÚÚúå—_Ÿ?88Èf³·nÝŠa˜J¥:}ú´@ èíí5 …¢¯¯Ïf³‘‘:N hµZ©TJ¥RÛÚÚ<==M&†aAðù|×ÔÔ‹dðã¾[óû~øÀOeµZN'†Â0lèoø%œN'|͸÷øùùwÀ=ê{¿ .]ºôGw~æ™g~´x0¹M >Ÿ¿cÇvðàÁýû÷?ûì³)))‰äôéÓ  E(þö·¿EmÛ¶Ïç‹D¢îînƒ±{÷îñé>¸W¹±0 kmmåóù\.·¾¾þÚµk½½½*•jáÂ…!!!ï¼óާ§'yŠR(¯¾ú*Bèõ×_§Ñh®ìPHn+--Á`èt:²Ç[´hQss3…B!Ân·;²0$AV«• ˆOOOX ã–šÜÛÛuãÆ›7o¶µµ±X¬îîn„Ð7ª««[[[F£^¯‰D­­­­­­Z­622²¼¼œ, à~…×ÀƒÂkÜ¿RSSg̘ñ}ÏÆÇÇçææþìÆóóóïr#˜ÜnB‡††Îž=[.—WVVNš4iÙ²e4mÆ l6ðÀÀÀÖÖÖ 6Ék×®e0†Íœ93##£ªªŠüž‰ãøªU«¢££kkkW¯^i±XV¬X!•JÕjµV«E-_¾<((hÆŒC7‚ cxi{{{__ß²eË6oÞüücçÎÛ·o?uêÔŠ+B(??¿§§çù矈ˆ¨««{ê©§ …H$˜>}:ÙHvv6ƒÁ°Z­Ë—/çñx8ŽÇÆÆbvìØ±çž{ŽŒÉÍͽtéÒ°`Â>±zzzFcWW‹Åòðð g—ËEñù|£Ñø§?ý)++ËÃÃü uOOOgg'Y!$ ÛÛÛ¯\¹‚ãxss3™{£ÕjÉ]ÒëõÃ6‚ Ãí­ÐÓÓ“,†öÞ{ï‰D¢E‹}þùç%%%[¶léïï¿|ù2…B¹zõjvv6•J%“·¯]»f·Ûõz=ŸÏ÷õõ•Éd---K—.MJJúç?ÿ¹víÚ„„„††‰D¢T*ÏŸ?ÙÞÞPTT”Mn¬©©¯—Œ×Ïí)ʰ?†=öÃ|¡P˜–––––æëë‹a™Äüì³Ïîß¿Ÿ,<¬;6À]ár¹®·H€äcùXÜ¿är¹kY¯Û$''ÿÔ6.\x—ÁDâv³/000%%%$$!Äápbbb( †aQQQ|>_*•ÆÇÇ“¹\.ù‡‡‡‡Ã‹Å¡¡¡C›’Éd~~~<oΜ9ÑÑÑ®:ò‰$ `ØF0ñ¸Ý&3¢L&ÓöíÛ-ËÂ… ccc}}}7nÜXYYéåå5uêTooïGy„F£oÞ¼Y­V¯[·.11Q¯×“KZ*Šgžy&::šÅbÍ™3§§§gÉ’%çÏŸGýýï///_ºtéÐ`âžUXXxäÈ‘™3g †Ã‡‡„„ÄÇÇôÑG---¡´´4???NG§ÓÅb±ŸŸŽãW¯^={ö¬«üZttô‰'Î;‡ãxmmíáÇÉ}B—/_¶L<Ã'Ö¬Y³{ì±ÂÂB6›ýÄOTUU•””<óÌ3mmm¡o¾ùÆ`0ÔÕÕ%%%™L&WæÌÐÅjjjV¬X±hÑ"„PHHH^^žJ¥š7o‡Ã!\Çbˆ`<¸Õ ¥P(l6›ËåvuuÑétŸÎÎN„D"éëë³Z­ Ån·K$NgµZ½¼¼t:Åb!¶Œˆˆ —/((Éd“'O>{ölII‰P(ìîî¦R©‹…Á`˜ÍfrAòîîn¸ö~šìììiÓ¦AMe<˜0„…Ba0ãÝ0AX,‡Ãñ݇kXŒ§Ó9Þ]x`) .—ëãã3tcPPÐ8uÜ~üËàŽ;¢££‡¥æ=õÔS£Ö%0P‡> …ùùùN§óí·ßÎËË£Ñh»wïÆqÜUá!ôç?ÿ¹   ::ú¿ÿû¿ËÊÊŽ=:Ý÷:·3Ö¬Y³¾øâ‹ÿû¿ÿÃ0¬¥¥…ÇãEEE ÛÁl6üñÇuuuùùùsçÎî‚û‰Û«§§'**ÊÓÓS(¡Ñh†¦'utt8„X, ±ÙlcÝ_pŸpKMnmm•H$‹å‹/¾ +**ª¯¯ommmhh¸uë–‡‡‡Z­îíííèèP«Õ }ô‘N§¯®øÅ ðaPx € fï޽ö,\¸pçÎ?dn7¡qÿõ¯PQQ±y󿏏8³Ùœ››+—ËÕjµF£!Þzê©={öìܹóÔ©S¡µk×Êåò¬¬¬aaàA6<Ë`0tvv®X±Âf³ét:rqÔwß}÷™gžq…Ùl6£Ñèºô5gΜS§NÝdn‹Çãi4šÊÊJ ú»»ûûûBƒƒƒd™5W…BÁqÜ•Œ¥V«-ËíaàAæöVØÖÖ¶fÍšøøø¿ÿýïkÖ¬ILLlhh3gÎ<}útHHHXX˜P(´Ûí¿úÕ¯>ùä“”””öövŸÒÒÒ´´42¬¾¾~¼î/½ôÒ{ï½§P(BdiLLLll¬\.wmªaG¥RaíS€Ÿò±Àƒ|,&˜åË—Û"‘HfΜÉf³8 <Ȇ^ –Éd¡   OOϬ¬¬¤¤¤¡…àwïÞm±XvîÜI> $󱆅™ÛÝÀØØØ 6$''S(”5kÖ„‡‡³X¬Ù³g766>üðÃ………dØ_|!•JÙlvII Bèã?.**ÊÍÍdng¬„„„Ï?ÿü…^`2™'Nœøúë¯1 «­­ýÇ?þáëëë ‹Å<òÈûï¿O>¬¯¯/**º= <ÈÜ&Ö¥K—Ö¬YóÎ;ïh4šuëÖ­X±!ú /455¹Â>øà­V»jժŋs¹\rãíaàA6<ƒŠÅb9N‹Å²dÉ’äääS§N]¾|™Ïç÷÷÷oß¾Ã0•JõñÇ“ÁAA®‚‰a6æC÷•)S¦$&&Žw/ÿöÿŽ÷×0ø·¿IEND®B`‚jas-2.5/images/device-2012-11-18-jas-trinks-out-big-part.png0000644000175000017500000022651312054152672023214 0ustar giovannigiovanni‰PNG  IHDRSÇ%ÔPêgAMA± üa=tEXtSoftwareXV version 3.10a-jumboFix+Enh of 20081216 (interim!)°à| IDATxœìÝyx ×ûðsfî¬DVI$BˆÄKÐPK©¥Ö¶¶¶J©VQÛê—j‹¢ö¢J-µÔNí‚Ø#„IDÙd¹7ËÝgæ÷Ça:½[î’¼Ÿ§O™;sæÌ™wι³Üy1L@QÇqÇéùHl#rrFäŒ4EV­ªàꙎ6wggg¥RiúüÁÁÁŸþùýû÷U*c­`oo?uêÔââ✜s« 4lØP¡P¨Õjí0åÐ$ðóÙnm»¹µíæÞ®»üE²²à%Ò7FV"ÓgÅׯ_È!üñGvv¶‰Keee999uìØñìÙ³,Ëš­C‡ÎÎÎz¿M¨Dc??¿àààÌÌLátÚÖÞ£Mº†] w/[·ºˆœôaÊ­õ;N> •"çÎ%F^R9•6ÌŒ‘ÏÙÙùã?nذa¯^½þúë/…BaÊ(%•J“’’Úµk÷äÉŠ¢jÖ¬ioooccƒbF&“åçç3 Ó¾}û¤¤$‰Dbù¦(nnnÁÁÁºg/´½£G×5\Ü1E#Šúwþö=8–QIòòßÕ;òa‘Xìâ)®å*v­£Ì|.OyújÔ4ú‘§¦í„+UK^*Ò’È̘9…†×¨ã£ÌN/Šâ4ÿ9O5cä«Y³fAAZ­V*•vvvîîîc™LöòåKC‹`Œ½¼¼ìììüýýgÍšeoo1Öš‡ã8¹\^£FÂÂBooï””8퀪ÃÅÅ¥}ûöOŸ>mРnŽ0FÅa #D½þ”¥(„8¤;ókµ;ôö›¾SB8ý·ùòÔþÒ¨‘þ³Z‘(pÁ„1ÿiÁ¥¿SVÏàX޲sZú·È¾fqÜ­:C¿a”%Of dJ ùeMù0ÆéééÑÑÑAAAQQQÅÅųfͲ±±yôèѶmÛX–Õ;\¹¸¸Œ92((H,“ó<½BmÚ´©]»öÆáVTb±¸M›6ÉÉÉÉÉɆfÓ°l—€:žs… õ–[‰ c¤Øük'$·þAnqà‰Öiä#!Ú¾&¦Dñ“zÉÓ^r,Dz¡ºC¿¦hqÜ×ÝY¥ ‹k4^q¼Î‡_ìø½>g¥ J`Œ}}}GŒŒ1Öh4!µZÍq\­Zµ\\\Œ,îçç(‹ÌÃ0 )P$ùûûׯ__Ïw  clccž——§çÁ¡^µº×làZóa–Tftf„bV©dU ³>ªÖ­v§¾d8ÕrA©%Ù£æ Çh¸×›kÏ9'ÿ`%˲JyÎÑíîïŽ,¥Œ|4M·k×®GC† qppà—ä8îöíÛR©ôñãÇF.NÚÙÙörrrNŸ>}ðàÁK—.) {{{ãUP8ŽkÙ²%ÆøáÇFžO$ìÅ´³=…PlFþåä,Ä•Ë Líw>pë5c !$®å†â4û!võcêÕ%L,¶Õ¬­Éý÷Iuî ÊÁ‰²±å§”rµ“a˜¤¤$¹\žœœÌ?Ò‚1¶µµ}ùòeIII©-‚1V©T¹¹¹â×lllD"¹G¸wïÞ˜˜F#‰²³³‡ biƒ(34M7jÔÈÁÁáÊ•+ÆÏöGÛš¶6%jŠåF· LxYx%9³Ô¥Ì•²b B˜c„Ø­.bÙàÍWh;,+³RžÎ¤–¼Ä"1Òz$†ÒîØ±£Q£Fï¾û®Oqqñ®]»U*U©W~ Ÿ¡C‡;vL&“ùùùEDDç<ÝÝÝ;uêtòäI™LV»ví¾}ûêýÙ€ ãææÖ±cÇèèè‚‚Ó—ÂÕÑ-¼\öƦ$cŒËýúÇrÌ¿c*;£(ÊÖ–•• Ž¥§UX\!̪þ=O+}äã8N"‘ܹsçÑ£G=zôÈËËS(ô=c`qŠ¢ºwïÞ¢E ¥RIå8c,‰ú÷ïV\\ìæææââBæ7u³”);;»æÍ›ÇÅÅ¥¥¥™µ Ãq>ÎŽ±Y’ó T…œÀøMXˆíRV~K.ÚÖoÄ©•¬BƱŒ"=É®A(ºz‚œçÙ+3ž Ì^ʳ<–eÉûV(Š2þ¸¦Paa!¹*‰êÔ©ãçççè蘑‘}ïÞ½ììlŒ±··w£F\]]ɳ0ä¢(€ fgg‘˜˜höI‡òeÊCSLT,"üUƒôþÕÚïôw é@Õ°shØÜsð„ÌýëÉY`ÆÎ¥}G× §jØ96ní1h|Æ®¥÷ï ¢÷Õ¼¼¼zöìéììÜ·oß;wš2D¥¤¤ÄÄÄ´mÛVxÏÍÍÍÞÞ^.—+•JròG®p2 óàÁƒääd8í€ FÓtHHH~~~||¼Þ;Y†oE‘gþÑËb9…1‡„wÔʸ3¯ýÎâÚî’¨SÇH®ŸÊØùKƒyÛ±Ø!.÷ì¾ìƒëÇ"„$·Îdüùkƒ¹Û±¸§Qeî]]uRxŸÏÔsRŒqß¾},‰Š‹‹×¬YóøñcSîó9::¶k×.""¢víÚäÙNŠ¢H rDz,Ã0*•J*•^¾|ùÖ­[¦ßPP&(ŠjÑ¢…½½ýÍ›7FÏ»WH§ýÞ{ï]¹rExÚcãâÑdâ®ëœìq¬ª ÷ñÚYFViDzˆÓ7Öê|D^iF~Õ@þÆ4EÛ;±J9«V!á„)J,¦íY1«Vk•oÆÛËŠ‹‹Éï”J¥é÷ùŠ‹‹/\¸påÊwww'''±XLQBˆeYµZ]\\œ———››«R©àl*^½zõ¼½½5M÷îÝ õÃdºÖ§ŒB–{ç"eSCï;™YµJSZ¢ŽÑ˜þ§uºÅ±œ†Õê{‡cY•RøT‹÷!{ôètíÚµ›7oÏ·§eN–aÀ€JT£F š¦K}´ž$Ðî±16<”pU3EŸyOà •ä*e9UP*lggWÙuð61;güè%‡j::”GU Y3ñ}–Õ“/ °€9Ù ™\™R FˆC¿Î·ËŸÂ?9Á?Ðÿ^/+\PkÊ¿«bŠ o,³G>ŽeY#o* F>†cu²ÎoKÎùŒ§Pws¬Á!”W¬?¼P`ÝZ2…:£@fn‹™?òq,ÇêÞÀ#â&õœ~ÚEÃ0‹þº~/9—ãôÞÀC¡;6ñnh±RóÍÆ³¹…J}·ýàO l˜}Ý’eYŽe8–áX–û÷ßäOÆ×Í)eÅkV~Ù+´†¿žA8ñL}‡!¿üq¾ƒq £3Ïæ/ÍPmYvµSÿGÎö6-ë»(5,íåU#6zõg2 ŠÈÌ,Ç ¯‘6òõ(Ù·Ç®[·¬¼Â_×KÒá Nò'\ô\À´³¡ÚÆõErÑú¿Çüù§]»v^5j Œƈ\ôÄcŒ0–©ââl;t ãâ¾>ÜÁ†>~÷9DZú~”%³G>–eûêßüè'¢¨9ƒ[¹¼|‘=áKN&C!ŽSßëÛ{,DzˆüŸc§ökæËȲ¾¯).fX–aY†ã¼þúËqäH†ã^MyýŸãðá^0Eþ,ŽŒÌüjÂÇá ¶«8NXþ«µe‡6w†íÞ+Q“›vBÇqãß iíiŸ=ú3&7÷ÕT„8„” òèh¶¤D8‘CH•%‰Qgdü;劎{aãFÒz˜š‡KJ&^Dÿ/rPV,y±áWƒÑ§ï6 ÷wÏ›9¥(\·î«©‡R¦§#„°‡bYá]A–a”ÏŸ£Úµù9Ç)²§Níÿë¯bÞu!žã¸Š¹Í·qãÆ€€€Þ½{3†.Ìx»XpŸyu¾‡ƒ­¸{³úb{Û:7–Áiƈ¢ÞkáÿwÔÓ"™ÊÄ_ñýðýzõÂøÕ8™ŸŸŸžž¾}ûöëׯÿÅ=Ê/^aFŒ1iÒ¤;w®_¿žeÙR·âçŸîÙ³'™ã¸¼¼¼„„„õë×?yòÄ”ÍÀ³èW ¯o½Ë”Gn=íß¶aöôiŠ[·Çá×Or"Á?þ3®gøï”¡¡žK–œ¸›\$Sr,‡à؆իW¯I“&‘‘‘‰!äììüþûï4è§Ÿ~Z½z5[ÚmB¬U=sôïßΜ9‡Zºti©+ÒR»ví   ·ÂÛÛ;((èÒ¥K………c#F <ø‹/¾8uê ~`:ËÏg_C4¾oë^Σ:Ë–eΜ)»rÅâ3?û<–,a•ÊÞa üëÔúõàM…JCî$–:øaŒûí·'N iӦǟ2eÊÆ …eõ1E­Zµ‚‚‚êÖ­kÙâZ#n©[1Þ¼yó?ÿüCf0`ÀÖ­['OžüÏ?ÿÀ¥Z0ïpyõj•Žë6.ÉIýphR÷î%11î ˆ›7g1f2÷?qPÛ¢E%ÑÑÏ zÞ³§¿,¯c“:ˆc8–1ñw,Ë2¯ÅÆÆÞ»wÏÅÅ¥iÓ¦ã9sæ¬\¹’¢þÝÒï¾ûnõêÕÂ)õë×ÿõ×_>¼mÛ¶wß}W8&999MŸ>ý¯¿þúûï¿/^@>ýî»ï DQTXXØÚµk;vìH¦šßÊ­ÐáСCùùù¾¾¾&€°üW ­y?¡ÎÍU:$•«<–-‡†23™þŸ(0ÐmÕªB WpèJ"Q=Ú¶Q=Är–ýªã8{{{Žãrss9ŽëׯßðáÃ…ã\Ÿ>}„S0ÆÿýwŸ>}êÖ­ûÁìÝ»wÀ€d°qww?vìØ÷ßäåå5f̘3gÎtèÐcܤI“ `ŒëÔ©ÓªU+wwwãó[¹º34kÖÌÙÙ955ÕÜ’ š3äã^ó‰EX#—‘“6MQ‘J£9|+ÑuÉRq“&¦Ÿù‰ÜW­>“¢T©5r9_š˜þwEfUÏÁÁáÛo¿mÓ¦ÍÙ³gÓÉÃ¥:wò´¦`Œ/]ºÔ¬Y³ððð±cÇÒ4=mÚ42.Î;·eË–›6mjÓ¦MxxøäÉ“]\\–,YBQÔgŸ}¶lÙ2–e?Þ¹sç#GŽpgd~+·‚èÙ³çÔ©S§M›¶páÂ={ödeeÍŸ?ßÜ[ŒPÍY~ŸeY–<èÉq B,ùÏ2š>KÍ™6UÏqœñ3±¿¿ûŠ•'¤ŠzÚ¾©/Ã0,Ç!Žc)Š%g–&ß5\¿~ýªU«0Æ5kÖ‰DçÎ?~¼‰w¿X–5k–Z­F>|xܸqáááíÚµ»~ýzŸ>}²³³çÏŸO>ݽ{÷G}Ñ©S§ÈÈH2äpÇ0 ©ªñùKÝœR·âóÏ?çÿMQÔ½{÷,¾ËÕ–ù÷ù^ŸŠ±,Ãh4üÙò,£9*ú™ëâ%t` kô²']¿¾ûòÿ|ˆjÞ¼¹î̦M›š5¿[1bÄ777WW×€€€/¾øÂÅÅeãÆÝºu«ø_eÀ›Ëò_5° ˼>áb†cY–å^{Œ×mÉÒìiSUÉÉèõ™Ÿð|ÇÆÏÏmé¯ç§¸ú”œ9±Ì«q”Cˆ¥(–áÌ:ç;pàÿTdÆ Ïž=;iÒ¤µk×Zp%0//!äéééèèˆ*))~ZTT„²µµÕ]ÐÜù-Ø †a4 ù=ß¾}û Åï¿ÿ>zôè‹/Âã`"‹žpáXŽcY–e_Ÿó1³ÿNg\»ð(Í}ñRQýúìë“<þìöñq_²äÂÓ]‰g _GYrÎ÷º4Ÿíä^UˆeYöéÓ§±±±nnncF#‰Äb±‰èææ†ÊÎÎNIIaY¶N:ÂO½¼¼0ÆÙÙÙº£²¹ó›µzg¾}û6B.x€Y,ù^]„LÍÌ…„‡YhoïÔì‚×9f–ÑüùðÒ“t·…¿Ð~~ÂGZhoo__NÈÜù˜Ñ¨9–!K¥dåÚ4mújžºuÓ²ó,ÎLËq9ñªY³&B(;;›¦é–-[’ñÃÅÅÅÍÍMë —N:ñS:uêÄ0LLLLfff\\\Ó¦Mùk•]»v•Ëå/^$·÷BüÕȬ¬,ãó[³z‘×¾ddd˜U2Ts–d)"§a—î%µÚaÌ©ÕÎî?u÷Õ‹ÍB9Ù×Pª4…ˆòX´(sæLuZBHìåå±xq!%–©›—RÙ«¹9tînâ7 {{ªF §¾}¯ì½Ì2ŒÅ/&!wÚ\]]BçÏŸïÖ­Û‚ vìØakk;bÄ'''áÌ*•jãÆ›7oÎÏÏïׯ_ppð™3gâââ8Ž[»ví† ¶oß¾aÆâââáÇûúúnÞ¼™÷*3íó¬‚_ojg#¾pàjBz.ûj¤â(ŒÿoxñÃÅîK܇z.\˜9kbÙ:‹!ŠRý±=¼ip«æï8ÇnñϳÖa;4i>¿ëÂó¬ò*k˶êÑ£Gýû÷ïß¿ÿ?ÿü³aÆ   #F¬ZµJ¥RíÙ³'//¯sçÎüÌ111QQQÓ§Owpp@ݾ}{ÆŒ!´oß¾š5kΘ1cñâÅ!™LöÛo¿Íš5‹Œ47oÞŠ¢(ŠâW œHn˜‘?]]]›6mš’’’’’B~ÏGÆ6š¦BÇyzzgggÇÇÇ“ø¢lllZµjU£F‡1š¦CBBìììnݺůËÈüFjh|+È¿…%9Ysž€,z¶“æd×Ûéz¹:*³³–E'ö ±Ltz>òí‚Õä$,1ÑÛÕ96)ƒ3§þÒJëÕùÁÃÈD–e_¾|©÷܈$2333++ ½Q„Ë*Šëׯë~Dðàð#ãó©¡ñ­Ð; X~ŸÏø<,~ÝOsò碟±Ûº±/ûz,c†¥Ìû¹º•J]‘‘ÌýÎàʲä÷|,ËñOBr‡1&ý¿Y†Áÿ>”ɲ,ËhXđߪ“1aY1§gä#e"?”‹®vþ÷¶ÿoþr…9× ¯"C4ÍrœR­b–å'³ Bˆ£i¹\ű‚;[‚Äíÿ–c€2ey®#ÿÅj‘øÜ£ä\i ÷Ÿ“;üßðÓá¼@™1ûW ÍßY¬,}(Â×°¡ë¹×NÉÌÓ¼Nï€1¢(ʯŽKV~¡\¡6ñ6޳˻ᆀ²bÉ}>S†!ŽCr“˜–Íýw"˲ÏÒs`PY,»ÚiêÈ¥w>öT"˲ Ÿ:Ñ{½”Ó™®;Ekº¡€²dÙÕÎ =mƒsDeÈìÓ,ŒqEEðx ð6Â­Ž¦Tv€Š#´Ù?fÞ\F>€7J`` Æf§;À8ˆ+P¶¨Ê®x«@÷ÊÄ([0ò¨^`äP½ÀÈ z‘@õ#€êF>Õ Œ|ªùT/0ò¨^`äP½ÀÈ z‘@õ#€êETÙ¨B‚ƒƒ¿ùæ›Ó§OK¥Ò?þc¬R©’’’¶oß.•J#""† †1V*•IIIüñGAAAeWT¦V­Z}ñÅõï×ÇíÛ·«Õê±cÇRŲlFFÆ©S§îÞ½Ëq\½zõæÌ™óðáà 6Ì›7¯N:¢RRR~ùå–e?ýôÓîÝ»ÛØØÜ¿Æ üZX–ÍÍÍ=}útTTÇq¾¹ Üyyy?¾Q£F%%%'Nœ8|ø0ÙÑ_|ñEÇŽ1ÆwïÞÝ´i“R©4Â0kÑ¢ŸR©ôîÝ»ýõÇqóçÏ×~uêÔÑ»vð–ëÑ£GAAÁܹs¿øâ ‰DSPPéàà0vìX2ñþýû‰äêÕ«¶¶¶•]å*§aÆÕ'¡ÌÀ ’““o¿öþûï4ˆL¼sçNFFFffæ7ß|CQTHHHAAÁþýûišÞ¿ÿíÛ· ãâânß¾½sçNš¦W¬X!‘H=ztûöm‰DrñâE[[[~-wîÜyñâE^^Þøñã…ÃmuPâÊÝÝýöíÛ/_¾<{öìÇ%É´iÓ(ŠÚ¼y³D"¹yóæÍ›7%ɾ}ûhš6Â0Ægbb¢T*ݲe EQzÃÏÓÓSïÚ+»U@ùëÑ£‡D"™7oÞ¸qã¤Ré¸qãÄbñ¯¿þ*‘Hz÷î-œ¸víZ©TÚ¹sç·þh4Wuè¡x”H$k×®‹Å4MÓ41&7lØ ‹5j›••*‘H8@¿öã?J¥Ò¯¾úŠ,Þ®]»ÜÜÜsçÎÕ¬Y“¦éeË–I$’3f <˜_K³fÍrrr®]»FÓteo}…ªqõñÇK$’Õ«W‹Åbww÷ÄÄÄ«W¯víÚ5??ÿÈ‘#6664M=zT*•6iÒD{¨ áÃL8ƒƒÃÅ‹¥RiPPH$Ò ?½k‹Ã †tƒX–e¦°°cÌq9ñgYV$¹¸¸0 “››[Ùu•O$ùúúúúúº»»óW‡8Žc&!!áøñãvvv]ºtvÜ Ã0 ÃGù3<<\,Ÿ:uª¸¸˜a˜-[¶ „Ú´i#,0??Ÿ_¼eRRRX–íܹsÏž=sssƒ‚‚"""Z´hAÓôÅ‹5 Ã0K–,™:ujII YÄ”¨ ó”””¼xñcìîî®7üô®a˜ŠÛþŠ#ŸA'N¼råÊ7ß|ó÷ߟ={–Ê¢E‹RSSûöí{ìØ±§OŸB†~÷îÝ{÷îmÙ²Eë;2ÇqäëQÍš5K-ÇÍÍ !$•JÉŸ/^¼à8ÎÅÅ… ™={ö¼xñâåË—e2¹#Xö[*Õ7-ZäîîþçŸÞ½{wêÔ©Ç9;;#„Š‹‹É<×®]Û¾}{jj*ùÓ”¨ úßÿþ·fÍš÷Þ{ïùóç䮳‰k/·m­|ð„‹A¹¹¹¾¾¾Íš5ã; ßÿýöíÛ]»v>|xTTÔ–-[ ªæÎž={äÈŽã²²²tƒÁÆÆ!dJ¨Õj„Hôê´µµÅk4ògIIIVV–½½}```Ë–-Ož<ùvwLÕÇqË–-Ûµk׈#† 2gÎ???ò͉¿ßÆ_|"t£B·ØæÍ›7jÔH&“]¹reÑ¢E …ÂôµOš4émíßàœÏ Ý»w>|ùòå½{÷&#ßÓ§O<ø¿ÿýeÙ°°°Ê®#¨|þùç®]»Î;§;…††bŒ“’’J¨ž={† "†‡‡#„RRRÈ‚QQQ#GŽ$a}ôÑGoýM¯jhìØ±û÷ï \±bE—.]222zõê•’’‚jР™çÇŒ‰‰iÛ¶- S¢bÿþý5 :tè;w š޵¿Åaç|·"Þ0 IDAT‘ëã™™™ãÚµkËår„P‹-ÆFÓtbbbe×T¾úõë7Žt(/^$ýüü¾üòËfÍšõîÝûÞ½{§Njܸ±ñrŽ=:mÚ´>ú(+++''gÒ¤Ijµšø@8[vvv```XXØ7à‚çÛä?þhРÁÈ‘#·mÛ†JHH˜={vNNÎ×_½páŸ~ú‰¢¨´´´yóæj-ËGG°LÖý[µ€1‰DEQEþ¡;‘¿tÑ«:<}Î#±!„1N¤iš2]øŒ0Ìøyhš lÞ¼¹n’yhš&+ªÀ ­|Õ$®(Š¢iºqãÆ>>>äG2èuTøøø'ê a˜iÍ£».­Oõ®PºjÒC•+ÒUv-ª–jW•»¥Õ¤áj'U \ìæ*7ªIøÁ%;Õ Œ|ªùT/0ò¨^`äP½ÀÈ z‘@õ#€êF>Õ Œ|ªùT/0ò¨^`ä°T5Iq*Ä€åp«£)•]ðö¸7°Çh*»`ŒÓœ@5O¸¨^`äP½À¥NPÆ›¶Cð$(SÅn:·…¸eF>PÆ.Ø7AÙº7 â ”! ÁÊÇh ¢@™ƒ¸€êŽ6þqíÚµÅb1Ã0ÇUL…€rUÊãRÎÎÎ*• !TTTT!õÊW)ïpyüø±½½½HÏxK”2òÑt)—C€7 ¼·@õ#€êF>Õ Œ|ªùT/0ò¨^`äP½ÀÈ z‘@õ#€êF>Õ Œ|ªùT/0ò¨^`äP½ÀÈ z‘@õ#€êF>Õ Œ|ªùT/0ò¨^`äP½ˆBhÒ:DQhõ׈eµ>nÒ¤‰\.×h4•P5 lMZ‡(J„B…(ý'yyyF&“UhÍ€ò@Q¯G>à *¦2@Åx=òù¢Iëâ*µ2@yòk„Ò’D!ôâ)¢(Da„peW (7iI(ý)F!LÁ Z€‹›ðV»|ù2MÓNNNr¹|Ú´iÔëŸ7ddd,_¾œ¢(­fÍšURR"‰Èô3gÎdddìÝ»—¦i²àÍ›7ãããçÌ™‚±öUT­Ò´þìÚµ«B¡èß¿¿î‚õëן7oÞºuërrrV®\I ~†qöìÙýû÷óJJJZ¼xqïÞ½ V¬Xqýúuš¦Ÿxðàƒ´³ÔÍ΃:uê‰+­é¥nîüb±8222..ÎÝÝÝÐö~ôÑG†¶‹5j”R©lÑ¢™¡I“&­Zµ6l˜B¡hÓ¦ ™Hb¯OŸ>5kÖ4´zc[¸±¦„“°@­e‰´´´ØØØC‡„PHHˆ]\\œÞ‘ïܹs!!!ááágΜ¹yóæóçÏgΜ™žž~ãÆ Žãzôè1hРo¿ý¶oß¾}ôQ\\œ•­¡+-- !Ô ASf¶ >Ïž=ã8î?þøä“OF5räÈéÓ§wëÖMo9¤—oܸ±î)õï¿ÿÎ0ÌâÅ‹œœvìØ¡·1­dÁÖ 2düøñ‹-ŠŒŒ$UÒ»½éé醶‹ ß½š5kFfèׯßÇLŠjݺ5™Ø¼ysôzPÔ«ÔØ.Ãpâ8Žy †=ÊåêêJ¾çZ†ã¸+VœýôÓ† úúúΘ1###ãÊ•+ÂE233Û·o?wî\OOÏaÆ%%%¥¤¤eëÕ«‡1NOO×[ò‘#Glmm4h°oß>†aΟ?ß­[·7nð½ Æ¸V­ZµjÕš4iR§NÊü²Ò­[·RRR&Mšäïï0lØ0¾ô¶‰¹õ9þ|bbâ·ß~ëáá!‹GE®¬ê-çÂ… 999³gÏöññiܸq¿~ýøò³²²ÎŸ??xðàÛ·o?~üØÊ‘¯¤¤Do\™µu 4X±bEddäÞ½{½¼¼|||\\\ônïÅ‹ mñÏ?ÿ<{ölÚ´innn7^¾|yDDÄéÓ§ãããg̘áíííëë;eÊ”èèèÛ·oÚv½±-ÜXswŸ¡†”+Ê××÷ùóçF¾/—ŠeÙ¯¾úª¤¤dóæÍOŸ>7oÞØ±c%ILLÌóçÏ-ZIJìÌ™3{÷îmh—.]ºyófRRR“&M¦M›VXXˆâÉÍÍýâ‹/êׯŸœœüüùsOOÏo¾ù†ºìííB%%%z;¬—/_Þ»w/66–Œ”°±±9wî™ùÔ©SÇŽ[¶lYffæûï¿þüy'''ËÁ¹\>uêTÿ'OžDGG ߉£Û&ÔG.—Oœ8±N:IIIyyy‹-ªW¯ÞéÓ§õ–#‘Hf̘š””tãÆ;wîmß¾}E:tÈú“ŒC‡‘¸jÚ´©ð~˜Y[7dÈ//¯ž={&&&>{öìÙ³gË–-S*•ºÛ+•JlBH¥RMž<9 555&&æÙ³góæÍcfâĉnnn ŽŽŽS¦LaÆP}bccõÆ6¿±©©©Ç7k÷ém(@¹«W¯^HH¹5bÊ}>áM½·v(в³³kÙ²¥ŸŸŸÞ›ˆzWäééÙ¦M±XÌÿZ·Fhšnذa£FD"‘° õ1Òko¥`ŒµÖNÓtƒ BBBD"‘Þ»S¦·€¡yÈJ›5kæää´hÑ¢‚‚ò‘Ö*L¯Ö‚¤qš5k&‹ÉG†Ê!•iݺµ‡‡MÓÂûa3fÌH$žžžºmhn0`ŒõÆ•Y[G–"óëÝ^#Û%l¥Ö­[ Ã’LlÑ¢EóæÍ…QdhõƶpcMÙ@­Øà—ÕÛÚ€òR_6-(³ÔEÈE}ú|þùç©©©gÏžÕûª•õÑ]ÊH9ZÓÝÜÜúöí›’’²{÷nãu3·J¦ÔÓâÂuË1%„¬¯’¡B,+ÍPð:thlllaaavvöñãÇ›4iRÕzº!C†H¥Òk×®ùúúVv] ÜU­.ø­„1¦(ŠŒväñÔòxrÒä¢yž°²ëoŽºuëVv@eJl@ü+A˜ %‹÷ïß/|ïFÕçæææææV¶eŠÅb+¯ê=,ªÔRC­g¨ªwïÞ=z´¡ð0?屛ʕ››[™?lºZµjU©H”G}Œe‡ªò#b·d…1t€WÄqTô_3gÎ4w[¶lÙýû÷õ>ˆÚ½{waa!ÿލÏ>ûL*•ò«ãß_eŠÄÄD²TaaaZZÚñãÇ[µjeîСC‡7nÈår•JÍ¿òÊšŠùøø:t¨¸¸X­Vgee-X°À¬6ܲeKrrrQQQjjªÖC‰K—.ÍÏÏW«Õ………“&M"Å–Iæçç?~üØÜªj=CU%˜››Û±cG½;Koü”Çn*“øáivppð•+Wd2YIIɉ'|||L,gÔ¨QÂ-"6nÜhÖ~iÑ¢Edd¤L&S*•wïÞµþp»råJaaa‘Ž:˜Òbzë3iÒ$Ý-ýôÓOMÜ¥e„™¡CÏâv;xð`LL ?sTTTll,ÿçµk×Î;gÖCde¾g‘ÕýU¹öÃwíܹ3<<¼ýk^^^fm@Ë–-‹ŠŠ†ªwË @~íËoؼyórrrÆŒ3zôèÑ£GðÁ¦7Yff&_Û?üðþýûñññÎÎκsöîÝ»[·nzK~üøqTTThhhHHHllìÕ«WIÄXS±Ã‡'%%uïÞÝÅÅeòäÉ2™lÆŒ¦ÓàÁƒ'Ož|îܹôôtáá÷í·ßJ¥Ò/¿üÒÙÙùwÞ .Ã6Œˆˆ˜7ož\.ÿî»ïL¯ª¡Ö3TUc|äÈ‘K—.霆â§{"ww÷víÚñàÏ?ÿ¬R©>üðCݵ©UTTÔýû÷[µjÕ¤I“ØØØ .XÙ\!!!¤>{öìIOOïØ±#ùÓÄoâzëS§Nö«W¯ÎÌÌÔ #J=Ê,3C‡žÅíöóÏ?+•JÒ_ûúú* †aÈ˃œœœŠŠŠÖ¯_¯{¸UäžEV÷WåÚWÀqôÊúõëi𯝙¸ñ¼ß~û-..Nï»(mmm>|xýúu–eùbýúõ÷ïß'¿2´Æþýûë­qff¦°¶}úôQ«ÕüË …®]»vâÄ Ý&óôôÜôx+=kbK_¼œúáŠ9ŽBˆã8CO^¹r…¼$…ˆÿä“O„OvîÜùÚµkzßúñý÷ß;99­ZµªmÛ¶üDÜÜÜñãÇ»»»_¾|ùÒ¥KÂE\\\ÜÝÝß{ï½Zµj]»vM©T’÷ ñµ-..Æët)ŠÒû&;;»wïÞüÓ•õë×ç_XlMÅÒÒÒºt阘Ȳì‡~ˆ2ý9Iî5áD'''??¿-[¶téÒ¥aÆ÷ïߊŠ"•Uzyyùúú;vÌÄgM µž‘ªòŽ?.‘Hú÷ïÏ¿“Ð?å´›„ÛŽ,ŠB7°É/UÈÛA9ŽKMMµ³³ Ž%ë2^1¾AV­Z%—ËgΜ©7x Õª¤¤$((ˆ±u```ZZš•Í¥Fº³êòxñâcÇŽ# FŒÓªñé§Ÿæççë>^Q&G™¹a†t=d]»]¼x‘\»KJJZ·nÝÏ?ÿLNhŽ?-¬XeíÙR[²²úár=Ž´ÅÅÅ9räðáÇþé§Ÿ´ ¢t?mذ¡F£ùꫯtWìØ±³gÏŠD"­Ú¯[·nöìÙb±ØÖÖöäÉ“YYY€ÃwíÚµ¨¨H¡P|ðÁZ窙™™ Ãh4µZŸŸ©uYãÇLMMMKKS(%%%iiiiii“'OÖªž¿¿ÿ?þ¸qãÆüüüU«V‘O­©ÆØÅÅeÊ”)çÎ+))¹sçN`` V»=zôÖkzƒ[ïÈ·uëV±XLÓôÊ•+É@Œ±•mxîܹ3fLŸ>}ñâÅééé‘‘‘Zó¯ªn멪pA¾G৉ŸòØMe?z»Ô#ÖxÅB5ÊÎÎÞ¾}»îG&F5B($$äÅ‹üñß&Ö4adä+5¤uëCœ?þï¿ÿÖ]õG2?̾‘Ïšvûõ×_óòòÚ·o¯ÑhúöíÛºukFÓ¯_¿”””ß~ûMX‡ÊÚ³¥¶deõÃåz¡ÿF,Ú°aé°hšÖmñgÏžåœ?Þ”6l˜J¥Z¹råŒ36mÚDÒßôìÙ“\Uçg3f Ã0Z/Ëþûï¿÷ìÙsâÄ Ýd³™™™7n´±±áßâ¨÷ü›oܸqúôé5jè}"_Ÿ~ú©¤¤„<.lMÅøµÓ4–žž®{cvܸqÓ_ó÷÷/uässsS©TS¦L!µêСƒF£9r¤õm¸aÃÒ,E½ÿþûjµškbUu[ÏHU… ^¸pÁ¬.©Ìw“õñc(°‡ª{ĶlÙÒôø9}útbb¢Þ'¼MŒj˜˜˜7nŸ5°>ªŒ|ÆãDo}BžžžEEES§NÕ»Ó­<Êùa†ô|Ö´¹Ÿ·uëÖÌÌLrôéÓ§Û¶mcf̘1ÂB*wÏoÉJ采 R~ÇúoÄŠÈ›; ½žæÌ™Â€(((Ι‘‘¡V«uWãëë{÷î]rÄÉÉ cܽ{÷¼¼¼sçÎmÛ¶íĉà8ÎÎÎŽã¸ÂÂBá…ïI“&i4;;;–eu¯Ò²,«Ñh Õ–eY>™'ÇqF«„ÐÐÐ ,X°àÖ­[Çñ©þrrr,®X×®]·nÝ:vìØ‹/²,{çÎ7niÕí·ß~ãÿmÊ]“ÜÜÜœœ>± z’êÁÊ6$· HCÅÇÇcŒ± °¡ªj=òõHoU…j×®Ígè% ÅOyì&ÂÊø1ØgΜAùùù]½z!äåå¥R©ž¨´„šVeÈœ03šv;{ölqqq÷îÝoݺEne]»v­[·n,Ëž>}ZXH¥ìY[²Rúá„„TnÇúoÄ"½OÙò°­žCõA}úé§ Ã„„„Y©5G™éa&ÜF­CÏÊv‹ŠŠbYö›o¾!k$·„=zd¨O¨È=kVUÁýpÅG¯˜¸ †lݺõáÇFzy­kµ;w~ôè‘L&S(qqq¦ô¹„é-Nú&½}ðÁ¤r¹üÉ“'ï½÷žõëØ±ãÅ‹ …D"‘ËåGµà… º‡Ÿ››Û±cÇȵògÏž 0 LÚ¿F_XX3lØ0ÓÀPëª*\V%÷  V«ßy猱¡ø)ÝT&ñÃÓ ìvíÚÅÄÄŠ]»vÍô÷’OŸ>\t!;…ÐÛ‘©Uqq1ùrÍ—0dÈŒ±5ÍEX6òªBh„ Ãøûû›U 2í(37ÌømÔ:ô¬l·5kÖÈåòzõê‘? vîÜi¨¼g­ì¯Êµ®€ãèk†=„PëÖ­‹‹‹u{:ÆX˜ù cLÓtPPPƒ DFóêé*“¼eØ@ª?k*F–õðð svv6÷l iÛx4M’|oeÕ†Bº×è3Ôz†ªÊÛ»wïåË—ÉΛ7ïÞ½{ä߆â§T*•R©tÛ¶m¦wÄež$¬ÌÓ˜Y'e’!Ìд8C².óY© Æ,*kªÂR͕ʚh±2ý¡¡È7ÒS•ªürd"‹‚ÄP?SúŸòhÿWô¦§ŠŽŽ¾ÿ~óæÍÛ¶m›˜˜xöìY+jeZ¯7(S¡¼Y6?U˜—äää3gÎÔ¯_РA¹¹¹ä÷¹¦Ô­Ì“„•y3+ã¤L2„ÚƒgCÖe>+5Á˜AezC骰Ts¥²&ZÌNÛö_†"ßÐtS”SŽLÂÜ 1ÔÏT|ÿ£Wy´ÿ+”¾ôT%%%óçÏ'?§X¿~}ZZšnéežÖ U¥LuºK §É›Å37U˜–aÆ‘W„íÚ¾}û“'Ot£¹’„¡rHcfbœ”_†0C{ÐÊ aVf>ã›ÅP‚1sƒÊĆªÜTs¥ÖÄÊh)µU0ù†¦›Rkz#©+yf‰¡~¦âû½Ê£ý Ÿ$I(55µU«V!‘H’šš*œ§œÒz¡ª‘©Nw)–euË1”7‹gnª0-îîîã§OŸ’e322êÔ©#Ü‹–$ÌÐ~±¦ýK“òÎf(󙕬Ì|Vj‚1Ë‚ÊHCU…Ts¥ÖÄÊh)µU0ù†¦›Ra æöIXÙ¦1ãËÔ'“!ŒîA+3„Y™ùŒ0ž`̬ *µ¡ªBª9Ó[Ʋh1¥UÓ|ãÓË»çÑ›ºRÈô 1ÔÏTXÿSñíolùåË—gggoܸqÓ¦M¹¹¹äD•ÿ—sZ¯ÊÍT§»”‘r e #ÌJ¦Õ,E]¾|ùŋ˗/ÿóÏ?óóóår¹é[WIÂÊ6_¦Þ8)uß•I†0¤³­Ì†­Ë|†JK0†Ì ªRªâ£ÈÐ!S~ÑRj«šÛ#•:½¼{½©+…LŒ±Þ~ÆÐt·ÑôÈ©øö7¸|xx¸R©üüóÏiš¦(jÖ¬YEEEZOiõ®Qn IDAT—_Z/ÝúT|¦:Ý¥ô–c(ϬTaºÍâìì¼pá£GnذaÕªUR©T«=+2I˜î~Aåœþ­2„éîAë3„!+2Ÿ¡ÒŒ!3ƒªÔ†2^ŸŠI5gbË K£™“¶Í”©ÔéÆëc}σõ¥®2+H õ3ÓÿT|ûz–ñ÷÷§iúáÇäjrbb¢···ðº|ù¥õÒUñ™êt—Ò[Ž¡ d<³R…é6‹D"ùþûï1ÆÇíÙ³'##C«­*2I˜^åšþ­\3„º{ðéÓ§ÈÒ aÖg>+5Á2?ÿœñ†2^ŸŠI5gJMJUViÛL鑬¬²¢ç1’ºRX¾YAb¨Ÿ©˜þUFû¿¢5rúûûK$’C‡¹¹¹yxxœ9s&##ƒ>>R©ôüùóÇ:l­<œ+…›››½½½L&+Ã2­?4ô~{pppðññ‘H$ÖÕNÇñãÇiZ{ü[´hQ~~¾H$2·´ììì+VPehŸC‡«Õꬬ¬ ð3Ÿ}ú””)‘H7mÚäææF>2·‘+Œ°MBóçÏÏÈÈÐh4r¹üòåËmÚ´¶‰ñOù¢˜››Û±cG­ö “H$£F’J¥“'O¦(Šß ùùù?†%ÏHèW®\),,,ÒÑ¡CR²F­O7nÜ(,§Ôx8xð`LL öQQQ±±±üŸ×®];wî\ûöíµ6ÐôòuU…x³àØ4qï·k×No[999©Õêÿû¿ÿã{­åšNìÞ½»°°ÑÏ>ûLׯ_×íÁ ±`ßéêСÃ7är¹J¥ŠŽŽnß¾½õ+õÐ0nË–-ÉÉÉEEE©©©ZýöÒ¥KóóóÕjuaa!HÖT•'²³³ÓŠ16·AM\pÍš5¡¡¡ ˆŽŽ5jÔ¢E‹$ɲeËX–íׯÇq,Ëš¸.{{{½\~•/-[¶7nÜ矞““ƒrpp8|øð† X–õõõ3gÎîÝ»IÏeq=íííI™EµnÝzÞ¼y666cÇŽeÆÜF®ZmòÓO?M:uÅŠ{÷îõ÷÷Ÿ?þ¡C‡ºté’œœÌqœñO…E>|ø³Ï>[°`A·n݆áW'‰E"‘ƒƒƒX,F‚½ ‹»té2kÖ¬’’’_~ùEØPFB—Ì0aÂGGG„ÐäÉ“;wîüÑG‘•>zôˆœ œ>}ºgÏžü¾ëÛ·ïÌ™3/\¸ }Ôju¿~ýH­úöí»víÚ5kÖ{L¾žãÆãW‡3fÌW_}EQTzz:_&EQÛ·oOHHÐÛȆ¶ë“O>Ù´iÓœ9sæÍ›W‘mâääôòåË­[·ŠD"Ò& 6ÌÏÏ_½z5EQÆ?Ei5ï AƒT*U—.]„qرcG‰DÒ¤I¥R†1¢¢¢N:¥õ½ÊHèøµÍ›7§¤¤ˆÅbÝþšŸ' ##cÇŽºk1¡=zh4šÑ£GcŒ'L˜ “Éòòò¾ÿþ{Š¢ú÷ï¯Ñh†Þ©S'­ 4±üªoHçØÔб>}úÌ›7¯víÚ!—¹sçöïßclÊÞ7ÔVäœoÆŒzãŠgh:BÈÖÖöáÇׯ_gY–?µZ¿~ýýû÷ùèÕ;œ÷ïßÿÃ?Ôý¨ÔØà]»víĉº'žžžgΜyÿý÷)ŠÂ/]ºôåË—¤òVVÌø¡a ›-[¶¤§§ [2>>~çÎä눰JÖTõ_üà±fÍ¥RyáÂ…+W®dggK¥RR‰™3gŸ8qâæÍ›¹¹¹:uÂ/Y²D*•=zôòåË …âÓO?%ëhVVÖªU«´‚øÖ­[>lذ!™Ÿ¦i¾²²²È '''¥Rúôé›7oj4š½{÷&&&ž8qâåË—QQQdáÈWæ•ç‘ÊÄÄÄœ;wîŸþQ(›7o&óè¾dÉ’ÜÜ\r½cǵZݺukŒñìÙ³‹‹‹½¼¼BOž<Ù¶m¿ÍüŸfàÀãï¾ûN&“9sæÂ… r¹œ¿Ã×sýúõEEE¤X''§ÜÜÜíÛ·ó=_æ>|HJ«‘õn×üùóU*UddäÅ‹†Ñ:°ËµMzõê¥Ñh>úè#>j1Æ.\ ûÝø§ºÍkcc“““³|ùrán þñÇkÕªµråJ²”p/x{{§§§“3CW ùŒ_o?vìXRR’î%2#ñÀoonn.™gÏž=÷ïߌŒ$ãô‚ d2™››[Ó¦Mµ6Дò«l¼¡ÿ›º1Ö¼yóüü|²¢åË—K$2†™²÷uƒÐù´âŠgh:BèçŸNIIùâ‹/†áG¾œ?þ믿þᇄ_» —   uëÖíÚµËÛÛ›¿hlblð®_¿®ûÕ 'ù÷þýû}ú`ŒŸ?þâÅ‹… ’/Aäb´ƒƒƒ\.Ÿ;w®päÛ²e‹ŸŸŸOçÎ###SRR\]]}||òòòÖ®]KÊߺukVV–»»»°žíÛ·W«ÕS¦L¡(j̘1 ÃôèÑcœžž~éÒ¥¹sçΟ?÷îÝùùùŸ}ö™Öènh»jÕª•••µk×.š¦·lÙ¢wä+¿66l˜F£éܹ³0 ÿúë/rˆÿT·yB111ÇŽÓ:9#3÷Bjjêõë×oÞ¼™““sïÞ=Ý1ÉHèj)uä›0a‚B¡{ö¬©©é×_…;ÕÄU‚ÿ+8p ¡¡á™3g¤R©L&ËÏχwT½½½íííCBBöïßÿé§Ÿ:;;æÎ7gΜ€€@`ffF7-•Jé·_cbb ¨¯¯¿oß¾øøxgggÆkÒÂÂB™L&“ɲ³³ ÓÒÒ¤Rijj*ÀÉɉ\³5œ§ŸŸÉÍÍ…©Æh<&&¦¨¨hèСcÇŽ577¿téÒˆ#0 sss‹‰‰Áq¼C‡zzz•••dã_ýunnn^^Þµk× {ÕÕÕ^^^ÆÆÆ'Ož„:{ö¬……Å€ȱJLL|úôé¸qã0 ›0aBffæýû÷aÛF5|øpooïêêê7oÞ(Ù®~ýúYXX\¸pA"‘Àà¿—˜¨£©·oßÂû`Ä“'r~fee]¾|ùÂ… ÇŽ³´´¼páå¼UùÔå¦k×®AAAaaaW¯^e\ Șä ÉÉÉÝ»wwwwïÔ©Ó­[·®\¹bjjêëëÛ«W/¸ú‘±Üö?ü|ƒ0æ|ú›‘‘qöìÙ¼¼¼ÀÀ@âÁžÂÞ玄-E9RwûöíÉÉÉǧtñóçσ‚‚úöíëâârïÞ=ʬ}þüy???### ‹Ù³g:tˆâwnxyy-[¶lÙ²evvvNNNK—.]¶leý ¦¦&)))))I ¤4qL™¡qýúõ¤wÐÆl<~ü¸ÿþýúõ;pàÀŠ+àe¥†1„üßÖÚÚž’SúÉÜÜžÁG÷iiiB¡P œ‹/ŽŠŠš?þ™3gž555}úé§ ÷IJJzóæM@@€££cçÎýýý‰ è&&UUU'Nœ€÷¢MMMû÷ïúôi“ƒâ8Îý+cxmll²³³qïÕ«×áÇ{ôèÁØ===;;;;;»þýûïܹ³±±1::ÚÕÕn‘ºÜfÉzöì¹yóæ‹/>}ú´cÇŽpwÖÖÖnnnÜ({‹Å/_¾´³³‹ŠŠ‚=ekk›••¯Õ8¶e³ÿ±ä[ŽíÞ½»°°pâĉ™™™ä…uJö>=VäB¶aËV¾cÇ///oooooïíÛ·Ëåò+VÀUþÎÎÎ+W®´±±±µµ;wnZZåžSaa¡P(|ýúu~~¾r!T¡Pèáá±eË+++kkkÿÜÜ\xkZmÇ”œÕå$”¼¿víÚôéÓ‡Ú®]»+VÇÇÇã8®•þ_~ˆD¢uëÖõêÕ+777!!8c‹ÅË—/oß¾}nnnUUÕ¶mÛ:vìqãÆ;w …ÂqãÆÝ½{×ÈȈnzýúõÄãSHmm­¿¿sssbbâÛ·ooß¾œœ¼zõjUïQÐócVQQñôéÓôôt˜O/^üä“Oˆ Ky|ÂŽãË—/·°°ÈÎÎÎÎÎnÛ¶íªU«uþüywùòe¶3Á/^˜››SV…p´kÍš5ŽŽŽ™™™)))ð$KÇ1Y½zõñãǃ‚‚ÊÊÊ=zÔ¦M›†††¿þú Þääþ•bjܸqæææ×®]ÃqÜÉÉiÞ¼ylk½ˆ'(÷îÝstt\²dÉ‹/:wî 7©««cK]n³¢Â¸qãLMMg̘‘“““÷Ž[·nuéÒ…ÛÙü799¹¹¹ùÊ•+°Ó¯]»VWW—’’¢Ì¶Œ|,ùƘcßÿ½§§g`` D"ùá‡>ûì³~øÇã)ßûD5Ê~Ù†-c9¼Ô€á7n455ÍÉÉÉÍÍ544\½z5c5¼Iëåå5aÂz÷UVV.Z´ÈÁÁ¬­­W¬X¡¡c­4«“’’nݺ% ]\\V®\ ß\ÔN ‰Çø† ‚~ýúYYYñù|b †a|>ßÍÍÍÝÝ]OOžLñù|'''WWW@@^ÃJ^Ïɸ¶Z³²²rww711!/"`Û–l:Iø çÉóxž|£çyäìR²÷cEy«ž¢¶rrTÉÁ„ÎwëÖÍÉɉ\® }§<Ð.]ºtíÚU[ŽqÌêÊCOiŸÏwvv†sµV\e…£ÿ(?ÑK´²#MЙóš˜Â0l×®]Ïž=SfM)·} ‹ &¼yóæìÙ³êe#cÇŽ]»víøñã¿þúë‚‚‚;wî¨j\[1¡ä:½é¿’Mùúú–——Ãw`;wî$ÞÝTÆM(ÿ*4«y%ëheÛ%ßæ˜z½OTƒG¾úúú°°0˜]l)ªÒpVÒùÖ†ÍsVo Wïø6ÛÎ;5<ƒ›6mZMMM\\œ½½½¶||ñÅéééµµµeeeáááÝ»w×A†i+&dSOŸ>]°`ù:CÕ†(³‰Â:šWP²NklKæãÊ·ääd5zŸ\ÍÇÇgøðá½zõ"î40¦¨Sø‡Ãçómll44o¤hñì›0 ï“ïûé­Ä„lÊÆÆMFZäãÊ7Í{{Q–¢ZL]Ä?¶Q)u´b ƒòøÇÀ6â´púÆ&õĦ«Ä¦›¥¤ž–*Y­!FÕªXXXðùü–––÷²wøÊGCCÃ{Ù;Öð‡CKL÷ù >x]SwÎ`›ÞãdÌ+++ƒ÷2ƒéT3OØR”uØ*”%ã€Mê °è*AØt³ØÊ)¨¤’ÕbTZQÉ" ÈwõèÑãáÇ PSI;Êh¿)¤OŸ>111ÍÍÍÉÉÉš‹Š)”¬S߀€zK•_Á¡PKL—ùɦL¦vÀ•QïSév¥ÖSh,çÖª2uïk²eÂ!Cà,ÍÍÍñññÄCG…h8ôt©™§Œ:&l) a¶§Nòôô:th`` X,Þ´i“ò{}õêì WW×ôôtø]ÀêÕ«kjj¾ùæ“!C†PÞÅ0ìÚµk< „†­œÌgŸ}VWW÷Å_PšÁVÎæa```yyù‚ æÏŸ?þ|???åGŽP(„Aóðð˜>}zjjjFFüÄ___øJ6S“&MjiiÁqœx>|òäIÏž==<<222Ο?¯dYZZ8ÐãÁÁÁ---Œ:^ÅÇǧ¦¦öíÛ·{÷îééé÷îÝÓ0\®®®ÐŸ°°°¢¢¢ÁƒÃß¡TÒŸöíÛ{Ø»w¯P(Tø†2ÁÕ«WsssGŽiff¶råÊÆÆFbå:D—ù9uêÔ•+WFEEQôYÔxpppss3œ¯íí훚šd2|ÅØÈȨ®®Žü±]¦P¢ ¸ÑÊd›t0aË„”””ÔÔÔÞ½{0 ''Gù…Ö=6Øæv­Ì¨ê†ØRÂ:lÊ’±Á!õĦ«DÀ¨›ÅQN ’JVë‰Qi¨’¡ËwuïÞ]"‘Ì›7:¼qãÆºº:zcÙ#Ú¦ýÆí•¡¡aNNÎ’%K`ÓöìÙ?sªI¸ˆú’ulpøC˜õôô¬ªªš>}:}œh¢%¦›üìÊdj\õ>åµ5R(-ç¦{™:Ý @FØ2¡¡¡áÇ„ -,,TÒM†‡¯cV§ IDAT?­¡™Ç­ŽIߊ\‘¢ŒÃVÞ}E­C‡ööö7nÜPòóeee¾¾¾Ä§hàg3ŒŒ:uêtøðáaÆuéÒ%555>>ž²mxx¸H$úüóÏá×ú–x{{ÇÅÅÑߨg,gó`eeUYY¹dÉKKËèèè7433³´´3fŒ±±q\\\ss3ýsìħçêëë1 c|C¾cËÀÍ›7íÙ³~ß×sCmqÇ zô葞ž÷Åí±={öˆÅâõë×3~FÍ«†††nݺáï>]ïìì\XX¨a¸(¨Ì÷ú”ñ‡0²}ûö7n\ºt‰ÜõÜQ*,,6lXçÎsrrärùôéÓ”@é&?‰€ÐM©ð¨¨(¨Nwâĉ!C†dgg×ÔÔÀ[=lii‰ŒŒ¤ïN—)”è‚Ö€l3ƒn #l™PPPзo_€@ puu-(( ×i¥¡ÇæÇÜ®­•|¢o%—ËévØR”€yØ*”%ã†.õÄ¡«D†®›Å]ØÕ°8T²=€J£|׌3Èâsð_òÓSe¤§Ø´ß”Ôî‚L›6M,Ï4ÄRF¬•Š?(ÑB·L+Zb:ËO@S&š\¡zQó}¥„Â.x_2u­:•ž >>>ÙÙÙ¯^½ÊÌÌ|ùò%å!Vk=Ýh汩cÒ·ò÷÷ç°Ã8K@†mTTÔºuëÖ®]»}ûö¢¢¢˜˜ʨæÖUrttüé§Ÿ8P]] ? £säÈ(¹{÷nxæHÙŸÙÊ]ºt‘J¥Ë–-£ô.[9›‡€7êéééëëÿý÷ߥ¥¥äÌÀ0ÌÇǧ®®®©©ÉÏÏâŒP(”ÉdR©T"‘TWWÇÄÄP®£úé§‚‚‚¦¦¦†††ÂÂÂÂÂBBárãÆ;wîòèR8ð¸tíÚµ¬¬ìرcôŸ”ñ âêêZ\\|òäI"&š„ Â1ü wÑýܽ{÷Ê•+ôÝqûƒa˜™™ÙªU«¢¢¢ž3L›6­õ P”ꀖ žžžÍÍÍ_ý5ŸÏçñx6l¨««£Üäh½¡G÷‡cn×pFe; Ñ·b´Ã6KЇ­ç”%ìºJlROyyylºJdØt³8ô´TUÉj 1*ˆ†*Ylò]‘‘‘€N:ÅÆÆ:tèÐÒÒB(.*tŒ[ûM¡WcÇŽN:•ü²ŽV±Øàîbôàêêj``ðòåKƧj‰ä'š\yõ¾÷’JvÁ{‘©ƒŠð­4êuŽŽŽ|>ÿùóç°srr lmmɲZoèÑi=Í<¶Ã}+F;l³ð%î˜÷ïßÿÊ•+µµµJ¾2baaQ^^~óæMkkkkk똘˜¬¬,xP )++óññi×®ÝßÿýæÍSSSÊæ¥¥¥»ví¢ŸˆåŒzZ™™™G¥oÅXÎáallllll‡lmm?~LyþAÀ¸I™E·=b\+ Ïv!³fÍ’J¥žžžðÔ5999&&ÆÆÆÆÑÑ1--qÍ£c=zô¨¬¬<}ú´ƒƒƒÝ;ŸÚ²y ©®®;v¬½½=´ ¯¯4 D½‡ lþæÎ+“É\]]9vJÿ©]»vñññ½{÷Æ0lÈ!ÅÅÅgΜ¡7GùI@¿æÓ0àñññPî>K~ñâÛRC]¦„ò]ÀÖ@Í ÛÌ ›È%E"ÑåË—-,,¬¬¬"##KJJàºJ…þmjë9`ŸÛ5œQ¹Cô­È%³Ãp&î˜×ÖÖ>{öÌßß_™”‚øùù½xñ¢±±Q,gffŽ3:daaqãÆ x“=//.á¯gé«ÃÉå“&M’H$C† !×9räÈóçÏé1e+góÐÛÛ–755½|ùrèСÊ?ŽV~àÁcwʳ„>{ö :§ü×{×®] ÅÀ`oBóëúúzxŽLX˜6m†aš„ ¢Þðcó°téR™Læè訒AÀàÁƒïß¿ßÔÔ$‰Äbñõë×á p2:ËO}~Ñ0àûöí‹Å;v„ÿ¶mÛöíÛ·§Nbs@Ç)¡Lp •È63è`r@É ÃæÌ™“——'‹ÅbqNNÎäÉ“u3ôýìs»†3ª&‡!ŽYÂ<œ$èw̹ÁX¤ž‹®Y7‹­œQOKU•,6±÷­’Eö³s§NTêâÙ¥CUr†n: I¸È›?„A5<Á”ÐÓY~’ÛBwRí€Ó ª‘ ĆZO eº€Û%Í ÷Ìð¾ G&¸¸¸èrèqlË8·k8£jrâ˜% lÃYS0 ct”­œ¢›ÅVÎ&¦†J–ª¾w>X¯>LÇÔƒ­-ºÏO?ð€kèá{oÇÌ {g8øÐ2á#šQÙ†ó{€¢›ÅVÎcÑÓâ!•,Dk‚òøÇÀ6œßlºYÊëiñ‘J¢Õ@ù‰@ücÐT¦é!´R¿C¼Pâ!Èðy<÷kêéQ°µµ­««ÓŽËók¡©›6•&2c­$Ÿ¦{õ;¶Üû@r’-ßW–j¥ßߣ"¦ª:m­*»øáð¡‰n*I+ŽíêÑ9räóçÏ›››kjjŽ=ª¤Fh¥1­k¡i¨€¥™16m*µeÆ€fòi UÊt©~Ç–{BN²e#‡.šB4Ô9ÓP6¡ÙÙÚþ«§ÓÖ‰§ÉÐ֙¢B4™ßZI­P“ÑAE»zcÌÌÌ^¿~éàà0eÊ”ÊÊJÆ·ƒѺҘֵÐ4TÀÒŠÌ›6•Ú2c@3ù4…*e˜®ÔïØrO÷9É[6²•+ƒ†:gÊ÷»ºw:ð_=6­'PehÓљ¢B4™ßZI­P“ÑAE»zcüýýáJàj×cÇŽeffÒ㮥1Ð ZhD}n¬Ö“cÓ¦ÒPfLCù4",l*eºQ¿cË=Ýç$#lÙÈV®Ð7 HçL™Í•éw ºîVüo%6ŽrU§A%‡öûUXT艆ó›Ây€ƒÖÚÕ£`ii‰aXVV4^RRÒ¾}{ʉ¹n”Æ@+h¡)TÀjm™16ù4 eÆ4”O#‚À¦R¦õ;¶ÜÓ}N2–lå }£X`”ÛÔ\¹–Š˜šøßº:m­ »Hn`Ú‚¢BO4œßδÞè à•””téÒ…ñihhhooŸŸŸ¯d9ììlÇGí›››S>:7zôèÇOž|xHHˆ\.‡Ÿ­#$4ئM%[·n¾¾þ“'Onܸ¿OIYeb²téÒQ£F­_¿¾¼¼œòSKK cÖ±•CTÍF¶ÜÓYN¶ #?a„¸¸¸ÄÄħOŸVTT‘çeÍû]™„ìÝ»7Ô½:tè÷߯¼lþÓ·3f ÝãX ×MâAmÍ{ÜaiÕù pÎZGµ¶hWoŒ"øÄãñ¢££‹‹‹ÿøã3gÎTWW‹ÅbÊÕ«Ž•Æ´«…FØdü2÷¶Ú’4m* eÆ0ÍäÓ€"•2 õ; Ãs­\ÉÖ)Ÿ“@-=6îr…Å-·©a¿«­{§¡ÿô­8ì¨¬ÓÆYÔšmÝÏ{lai½ù ´‚Z!w¹2mùÿhWoŒ.ødbbòË/¿\¿~}ÿþý{öì©©©¡x¬K¥1ƨ‘oh]|N2ctm*ÍeÆ€òi@‘JЕú[îé&'êúg ˹}ãÐ9SfsG¿+™“"¦†þ·žNw9P÷ÈÇ=´¹ã …Ee<¨7¿m«*,W¦-íêÑŸD"ÑæÍ›1 Ãq<,,¬¤¤„r—V—JcŒ´ªø\«ÊŒAèÚTYYY@]™1ÍåÓª”]©ß±åžnr¨®¦ ê霻֤ßÕÖ½#ßéúàtÚ8˺²‹ÜC›;ºQXTÆ…èR­PC(lllŸÏ¶ @ ZCA,n-.%±ø|þÍ›7“’’ø|¾’ZY@¨&‚XÜZ\˜Ò‚XáááðÈǶ @ ZCmA,e´¸”Ä"Ž|› ¡xàÝ7Ólll èÄêÖ­Û˜1c>ÿüó:XXXÐK ×­[·à—åèZ\€$|E9Œ±•sÿ„@ „(((xôèQbbbyyùÓ§O­­­_}õUmmmIIIQQQmmíÒ¥Kýýý)%ð¦hŸ>} Wyy¹¯¯/ýpõìÙ³7nÐï^’ËÉ×|› ¡9‚¬¬¬Û·oã8nii9sæÌ .øøøœ?¾¬¬ìúõëzzz_~ùexx¸\./--¥”jjj’’’¬¬¬ÆŽ M‘wðöí[SSSúŽÙʹB BS4ÄâÖâÊ bQ®ù8´²ÐÚ‚XÊhqµ±8~B BCj b)£Å”Ä¢ûÄñ@ 𢉠–B-.e±ÀÿÞídÛ@ í ¹ ‡—2‚Xà|l› ñ¡À¦Å¥¤ VNNNssóãÇù|>Û&@|()ˆåíí=|øð~ýúaƶ @ J baïàØ@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ >.]º´téRnevî:ŽŽŽúúú­ãÝ{`Á‚×®]ãóùäBe¢DÇÆÆ†^haaaaaA/·µµUÉ8@|,¨6u¶ôôôÄ0 ``` §§Ç]ßËË«k×®ôòàà`¡P˜••UUUíáámæääÔÕÕÕÕÕUWW¿zõjëÖ­ª3´ ¹½ qvvööö¦TV&J‡~ýúu]]]bb¢@ Ê ”PXXXRR’’’B„käȑϟ?ÏËË«©©9zô¨‘‘ÅàÙ³gkkkû÷ï¯dA%"""&&^Öðù|…‡¥òòòÝ»wSªmÛ¶­¡¡!00°cÇŽƒ züøqVV–‰‰ @(ž:uÊÓÓsèСb±xÓ¦MïñàGn¯B~ýõ×·oß’X@¹(L:uåÊ•QQQEEEd;¯^½ŠïÕ«—««kzzzll,ŸÏ733{ýúudd¤ƒƒÃ”)S*++wíÚEÞפI“ZZZp'Ž”ñ‘±`Á‚àà`gggb"›0aBhhèÖ­[?ûì3¢pñâÅüî»ïÜÜÜV­ZÅãñŒŒŒ ë 2dóæÍÄ,I1¢§§ؽ{÷åË—ïß¿ùòå°æŠ+^¾|™““óÓO?ÙØØ¬[·nìØ±ÄN'Ož¼gÏž?þøÃÇLJ(¤ùôõõËËËOž< ¯„0 >|¸T*ýüóÏ1  …¡¡¡|>Ã0ëÖ-ú‡âðøñãMMMfff[¶lÖØâ3uêÔÐÐÐß~û­oß¾†±‡Ò^Žhïß¿? à·ß~£ùˆ(±E• lõáÇÉG>kkëÈÈÈqãÆñx< ÃvìØQQQ!üýý¥R)¼$Å0ìØ±c™™™D¬ôõõŸ?þèÑ#¹\N9òAO\]]׬YsðàÁ%K–ðx¼#FüùçŸAAAVVVÜ)‡@ º£¢¢ââÅ‹iiiåååðþÕúõëëëëoÞ¼™˜˜XYYéåå…aؾ}ûšššnß¾ýðáÃׯ_ççç ;;»ææfb¶Ý¼yscc#œ[éFÚµk×ÜÜüìÙ³¨¨¨Û·o755:tˆÇã…††•––^½zµsçÎeeeÄEÆo¿ýVSSsýúõèè覦¦¹s牒~ä4hT*]°`QˆaXÏž=‰k¾ÐÐPø“­­mQQÑþýû)GºÃ½{÷®®®†ÎüñÇ"‘ÈÝÝ->ÁÁÁ±±±"‘hÔ¨QöööŒÁ¡´÷ûï¿gŒvssó½{÷>|XVVVSSC9ò•––BÇŒŒŒ£JïèC‡Q®ùà©üûÂ… iii|>? @&“Oþ¶nÝJÞ{ppð›7o-Z$“É(G>èIFFFDDDbb¢T*=wî\NNÎÍ›7+**âããááóܹsô”S9kBõôôLLLâãã×®]Û©S§ªªª;wêééñùü”””ÿþ÷¿:uª©© ……—.]zóæ <òI$’+VÀ©ö?ÿùOSS“@ °··§166–H$!!!°ðèÑ£%%%€Çãݹs'..î“O>Á0Œ|T;}úôš5k`ý¤¤¤ˆˆ8{Ò|cÇŽ•J¥“&M"O£ÄßB¡°  àÑ£G‰‰‰åååOŸ>µ¶¶&Ña@(‰Æ'‰~ùå>ŸÏXÓÉÉéíÛ·;v쀅qqq—/_îÔ©cpÈíe´£Mêܹs"‘ˆrä#"`ddÄUzGÓ|€>}úDDD¤¤¤”——ûúúbæëë+•Jýýýaô8@œÍôèÑ£ººzáÂ…3gΔJ¥ô#ŸD"Ù»w/ôäÙ³g}ûö .”J¥^^^””{¿Ï\Ä¿œÅ®_¿>dȹ\îïïolllooøôÓO=<< Ïœ9#•Jq¯ªªâ6êííM7gÉüü|™L&—ËsssÍÍÍr¹ÇqÇe2Žãd;sçÎíß¿ÿœ9sÚµk'ÌÌÌ”iÒüùó‰+¼µk×B²²²n߾㸥¥åÌ™3/\¸àãã#“É8ÆqüçŸöõõ={öl^^^`` L&c¬éííÝ®]»°°0Ÿ%K–ÈårF÷Èíe´F‰v~~>%,tèQU’ššš¤¤$+++‡±cÇÞ¾};"""..î÷ßwww·¶¶†‡CXyûöíÉÉÉÇŸ>}:›ÁÂÂBèIvv¶AZZšT*MMM899ÅÅŽzõŠ’rlB ˆVBpíÚµ©S§nÞ¼9!!aÁ‚ð±PÛ¶miiiB¡ÐÚÚÃ0e¦`ˆ¹¹9Ýe[¹\Î}²¯§§wúôéÑ£G'&&Ö××›››—••±U®««˜™™avåʕǷiÓ&>>ž¸ÄÉÎÎÞµkœd£££¯]»æïïæÌè›Ãr¹üÁƒîîî111ð0ÉXÞS---…Ö^¼xèØ±£zR5ÚdF•B~~~PP ¢¢bÍš5[·n-//÷óó[¿~½««kqqñ©S§æÍ›ð÷÷3fLhhèêÕ«áyÌäɓ۵kwçÎF?áaþÔÜÜ €×ô'N\½z59å^¿~­FKBm¿ýöÛ† ÜÜÜnÞ¼ùŸÿüçÊ•+8ŽŸÂq|Ò¤I8ŽwíÚµ¤¤„}ÇñððpŽ«™ÔÔÔššš!C†œ8qB$ÕÔÔXZZ’]…‡1xäËÈÈÀ0ÌÄÄÃ0X‡Ña¹\Þ§OŸÅ‹GEEÍŸ?ÿÌ™3Ož99yÀ€### ÃFŽYUU¥¼“NNN#Gޤ¤ÜÂ… ‰‹oм5kÖà8.‹qoii¹{÷nNNÎêÕ«­¬¬ôôôfÏž=qâÄû÷ï———¯[·ÎÔÔ´sçÎÄ»hMMM¯_¿9r¤‰‰I¯^½üýýᣎ… æææäå ÃŒ¼¼¼8®fêëë=:}úô5kÖ}úé§sæÌáñxµµµ°‚žžž]ÿþýwîÜÙØØMLÙlïÞ½»°°pâĉ™™™{öìáñxŒ5###óòò¾ûî; —?þøcèСÍÍÍŒÁ!·—#Ú7n´³³sqq™8qbk<  …[¶l±²²²¶¶ö÷÷ÏÍÍ}óæ ÀÝÝÝÜÜ\&“͘1cüøñׯ_Çq|ÇŽ^^^ÞÞÞÞÞÞÛ·o—Ëå+V¬Ø¹s§J÷* wîÜII9tÁ‡@ tMEEEmmmSSS\\œƒƒ`äÈ‘b±¸¡¡A(~ûí·<oæÌ™¥¥¥p…HAA¼‘8cÆŒŠŠŠæææŠŠŠ#GŽ477Ãrº‘víÚI$’uëÖÁy|ãÆ‰Vž={vCCCsssÏž=+**àÚ xßR*•¶´´Ü¹sçêÕ«ÄòzÆ÷ùx<ÞŽ;*++àN·oßí …B™L&•J%Immí³gÏÈÇ!Ýá 6´´´ÀU3£F‹Å[¶láñxŒññõõÍÍÍ‹ÅMMM‘‘‘p [pÈí5j[´%‰H$‚W±Ü+\£J¾ÂÅÏÏïÅ‹b±833s̘1ðìäСC555õõõ‡200 ˜š1cÛ “°°°ŒŒ Ø_nnnR©tÑ¢E|>ݺuô”C b``ðÙgŸuêÔ‰xg Ã0>Ÿïæææîî®§§'2 ÃAŸ>}ŒŒŒ> ×vÂrƒþýû›™™ñxŸïäääêê*ø|>á!¹øÀlàÀ®®®ÄNa}2äÕüt‡¡3°&l> Æøðùü~ýúQ"É¢½ÑîׯŸ••ŸÏ§ÉÈ`‹*=8”Ÿà®»téÒµkW¢¥°¦½½½»»{›6mã Ý£ÇÒwä8?ñx úòË/‰+< ÃîÝ»UÙØdüÈJu½zõjiiÉÊÊŠŠŠŠ•J¥¿þú+ÇSf[¨ê¿.ö^bˆ@ ˆ Môù#PÈÛÛÛ›|oó¿ÿý/;e“ñ#+ÕÁo›»8sæLee¥¥¥¥2Û’?‚@ 7­¢Ï§$te>BgîÌ™3_~ù¥»»ûóçÏ•ÙV*•jÅ%@üãáA}¾¤¤¤;wî888õùÚ¶m›––öàÁ…ŠqP¡}ûöäB33³ÆÆF•¼!ìçççÓ "¡9¼ß~ûÍÝÝÝÓÓ³[·nÿùÏ LèÉ“'çÌ™3{öìY³f­]»¶¨¨êó±-ÔLHH¨¯¯6lQÁÖÖÖÍÍ-55Çq6?ºuë(..Vc[@ ¸Ø¶mÇsqq)..>xð ¡¡aFFƃ:tè ¯¯?oÞzzzä$ªÜ¡µPÍõùnȱ#XNVôV[å@ …hGŸOá†Ü?á8.—Ë‹ŠŠàQµUîhZIŸÏç£;–hmÔ9€ÁWȵîJ+™U›úúú÷µ÷-Æ.ßEþ×¢a.ééémܸqذa¶¶¶/^¼Ph g7|€žž^ÇŽkjjÈ?\ºtÉÜÜ<%%Eãт ‚‚‚.\¸ ªm9 ==½óçÏ»ººÞ¹sG}iâ§ÎÚ¨*Œ1áV^dû•0µyóæ––ø!r-úIOÝ6B¾©a'::Z"‘¨Ýû†††7oÞ´³³«©©¹{÷.ŽãlÃVÃáÌ ãÕ‚Ïç·´´hݲ•••ý{ ¶¶¶uuut#ª–³aaaѦMU¿C¢Œ¶±ÅPÕú*pùòåúúz‰DRZZºuëVâ~ãßÿ üíÇÈÈÈððpú]ÐmÛ¶UWW³-‡á ¬¬l×®]:¸ÿ¹sçÎÔÔTkkk@NNN]]]]]]mmmaaaxxxß¾}¹Ñ(ô3++ Ú‰D999´°°€?©dAŽ P¤¼Èý+ajòäÉ•••ƒ¦ÄÓÝÝ]$Íž=»¦¦fåÊ•<è…êêêW¯^‘Ó’ÀÎÎŽ-u!>¬­­­£1hÐ èÜ#å×í(̇K—.={öŒHûøøøôôtâ߸¸¸¨¨(J•·OçCÈ75Ʀ’½?pà@ÆXÁpßÿ=1“PR”€±\™Œâàðáï_¿®««£¼ÍÕ£G‡666644À³ò6¹-2$99¹¹¹¹¹¹9>>¾W¯^0n#GŽ|þüysssMMÍÑ£GŒŒ`}UËçÍ›GNþGÁ¤4hPBB‚X,niiIIIñðð ÷—¡¡a^^ñ¾äìÙ³µµµÄ¨g³ÀÖ"¶ªZ_erssGŽiff¶råÊÆÆF¸º¨þÔ-66öîÝ»ô#߯¿þúöí[5Ž|ååå»wïní£ÂgŸ}VWWGô¥P(ÌG›”˜p+/rÿJ6…aصkׄ|Scl*Ùûl±"¯ý´%`+W&£8˜:uêÊ•+£¢¢ŠŠŠÈSÙÇŸßÌÌìõëב‘‘S¦L©¬¬„窖ËËË,X0þüùóçûùùA÷^½z3®®®ééé±±±ä-Y²$??_OO(™4iRKK ŽãÄŽÍc‹8b¨j}•ùóÏ?á–<ïÒ¥Kÿý7üwݺuð«(zzz®®®kÖ¬9xðà’%Kx<Þˆ#þüóÏ   +++h‡rä[¼xñþýû~ûí7ò‘o„ ¡¡¡[·nýì³ÏˆT˜ÎÔãÇ—H$'N„^M˜0áÏ?ÿÜ·oßèÑ£é~.^¼˜Ø`Á‚Ë–-ãñxEEE„MwìØ±ììlÆ ³µkΜ9üá‡:wî¨Ë˜ÁÀ41 ëÒ¥KuuõÞ½{y<÷¯Jx§L™ÒÒÒBþÊ`ðàÁ"‘¨{÷îðƒ†‘{ÇãÅÇÇߺu‹’ßB¡-u!Ø;àK8ð QÊìCÔéܹsIIɉ'è{áÈÀ¨Q£àLaØÒ¥K«ªª6oÞÌãñ>ÿüs©T:cÆ ///J•´ÿaæ MJŽ?>00ÐÔÔ`ff¶eË–Ï?ÿÃ0ezŸ-V”#%¯ØÊ¹3êóÏ?§œñPJàV‡&Ÿºwï.‘HæÍ›_ÄÚ¸qc]]ã)~\\ÜÍ›7'hFË€†††ü:ZXX( $ާ§'Ì–cÇŽeffòù|UË¡¡¡©©©Ä°…-µ¶¶ŽŒŒ7nlÑŽ;***È^Ý»w/44”èw}}ýçÏŸ?zôH.—Ã#‡ÆqÄPÕúdèJ‡7lØ0x†.—˧OŸ>qâD™Løî»ïÆŒƒa˜¾¾þ¦M›.^¼8zôè>}ú„„„œ={öàÁƒŽŽŽß~ûíÕ«Wé=ºoß¾}ûöuëÖí‹/¾˜;w.©õëן;w®S§N#G޼sç¼õñÛo¿?~ÜÑѱ_¿~·nÝš3g‡ÇЙ°°°I“&uîÜù÷ß'nOÑ»¹¹úé§€¥K—þúë¯pdN™2eíÚµµµµ8Ž{{{'$$Èårò^ðwÔ××c#»iÓ¦ÿþ÷¿]»víÙ³çµk×èwúôé³cÇø•m##£íÛ·»»»SlÊår###âa%ÈŒíúñÇÿúë¯îÝ»9222rË–-”ý¶jLljj 51pÏÉÉyöì¼¹Áý+€Þððp‘HçAÂÿ·oßîÝ»·¤¤dÿþýäGGР½½=ýké………l©KéDÆ)…{öì‹Åëׯ'[àÎHTT”H$‚sô!C²³³_¼x{àÀ---‘‘‘l üHó=ÇŠŠŠV®\ 7ܼyóš5k„B¡’½O›8ba¶åä˜3ÊÌ̬[·ncÆŒùüóÏ;tè`aaA/ï^»¢8Ó½{w Ãà‡Žq/((000 ¾×H†Çã±ÅÑ2    oß¾@àêêZPP€ã¸¥¥%†aYYYp%%%íÛ·Ç0LÕr€••Ueeå’%K‡ wZVVæëë{ëÖ-è’ƒƒƒP($|ëÞ½ûÀ?N”lÞ¼ÙÈÈèèÑ£D ‡ÆqÄPÕúÐÆîc&''§¦¦&<<ü믿þä“Oˆrâ´žmíÝ»*ç={ö¬±±±oß¾`áÂ…R©J××|ð)tHH¬îÜ9‘H$ìííéÊ|>ÿôéÓkÖ¬…IIIðPÊxÍ!Œ=z´¤¤„ÍøðáÃ¥Réøñã1 ËÏÏ/..þå—_àõ¼¯mhh(‹Éc[(>|¸S§NvvvÞÞÞ111oÞ¼177·³³«ªªúóÏ?¡ý#GŽ”––ZZZ’ýôððH$«V­âñx ,Éd£FÂ0¬¨¨èÁƒ[¶lùñÇÏž=[]]=oÞ<ØU” ÓÛell\ZZzúôéO>ù„Ïç>|X&“QÎqZ5&ÜʋܿÒà xöìÙ7(g°¹ =z”˜˜¿–Gœ3tèP¶Ô¥ÀýáÀÒ¥K›šš¦NJŸ³Øò\çþýûð–NnnnHHHpp0<Ï OII!®3È ThÿCÎ7²Æ"‘hܸq"‘è—_~!º[aï³ÅŠ|ÍǘW¶rÀžQ_}õUmmmII |™xéÒ¥þþþ”ÂÚ¡C‡ÈWf3fÌ '?ü—ü`lôèÑ6lظqcvvvZZÚ¦M›6nÜHÒI· ðññÉÎÎ~õêUffæË—/ᩤ¯¯¯T*õ÷÷‡8eºU-DGG777§§§ççç755‘o,÷éÓ'"""%%¥¼¼Ü××—ðö÷ß'œìÑ£GuuõÂ… ¡Î¹áŒ[ÄCUëÃ]Ó;”휃7`À€ÀÀ@}}ý}ûöÅÇÇ;;;3^rÊd2™L–]XX˜––&•JSSSNNNäš$Äüd2q¶îííM(ÿíß¿*ÿæÎ7gΜ€€@`ffÆè((ã'“Érssá4Äh<&&¦¨¨hèСcÇŽ577¿té¼Ûîææƒãx‡ôôô*++ÉÆ¿þúëÜÜܼ¼¼k×®A÷ª««½¼¼ŒOž< uöìY ‹c•˜˜øôéÓqãÆa6a„ÌÌÌû÷ïö;88Œ5jøðáÞÞÞÕÕÕoÞ¼Q²]ýúõ³°°¸pá‚D"Á/1QFSoß¾…÷Áài/€|ªž••uùòå .;vÌÒÒòÂ… ”[ 111J¦.7]»v »zõ*ãc>+$''wïÞÝÝݽS§N·nݺr助©©¯¯o¯^½àU c¹íøùaÌ1Çþù猌Œ³gÏæååWÒ {Ÿ;V¶åN]ÆŒ:þ¼ŸŸŸ‘‘‘……ÅìÙ³:tîÜ9J ‡'Üxyy-[¶lÙ²evvvNNNK—.]¶leý'Nl×®]ttôƒ¬¬¬à=ꈈˆ¸¸¸ßÿ}çÎgΜ!nè©ZxþüyPPPß¾}]\\îÝ»G>òÕÔÔ$%%%%% ² €ŸŸß¥K—ˆhlß¾=99™| HÀh±EªF@aÜèÊÖ}x{aß¾}}ûö½råÊÖ­[g̘ÁxÏÅiaká]¨ŠNT`ó377ÇÞ)ÿÒÒÒ„B¡@ 8yòäèÑ£ëëëÍÍÍËÊÊ6@.—Ãc4.—ËÜÝÝÛµk÷äÉ“sçÎ-Z´ÈÓÓÓÁÁ!<<œíFÊáÇÈãÇq([X\\ ·*--Ï8!8Ž_¾|ù‡~°µµ2dȱcLj ßºu Ú422ŠŽŽþñÇ}||8‚L´«C‡€ÂÂBb:Ž ›ò"œý¹eD™&²³³wíÚ}íÚ5ÿ3gÎï^ªšºŒìÝ»·®®nݺul2æ¹BLL̪U«-ZTQQqûöm©Tš——7yòäŽ;>zôHa{?ê|cÌ1ØŠ¸»»ÇÄÄPnAsl=Ø2* <<¼]»v³fÍ‚C€RÂfqI=ù­ž   Ÿ~ú +‰üüü ì¶ÂC©§§ç·ß~»téÒ'Nà8þúõë~øáäÉ“~~~ëׯwuu-..>uêÔ¼yó8Ž«TX±b@.—K$’K—.3ÆÙÙ933Çñüüü   @EEÅš5k¶nÝZ^^>uêT33³'N@çýýýÇŒºzõjxÆ9yòävíÚÁ7Ièœ[ÄC¶(Œ¹òÝ'>|øýû÷årù“'O 0ž&ÀÔwqq!ß#äååá8~òäÉ›7oÂrÇÇŽ;eÊ”E‹>}ÇñððpÊ­$%a4.—Ë£¢¢¶mÛfnn–˜˜˜ŸŸ¿~ýú¢¢¢„„xã["‘PîËår©TJÉÎÜÜ\Çûõë?ÛÖ»wo@FFÅãÇoذaûöíFFF°Ï`9Žã0éE"QRRyÁ7prrrzúôé{‰ ¡¼xéÒ%h*/ž;wÇqî_ÃkjjZ\\¬Ðyè*ì…ŒŒ ÃLLL0 ƒ{ñññ9räÈÂ… 5LÝU«V 6Ìßß¿ªªŠ­c>¹sçN}}ýÈ‘#“’’àq+..nĈr¹<""Bá\ÿQç[ŽõéÓgñâÅQQQóçÏ?sæÌ“'Oà¯Jö>7ŒyÅQa˨€€©Tj`` —ËáAš^ÂHVV S§N±±±€:´´´Àƒ¬@ì^*ÀËweèèèÈçóŸ?Ó)''ÇÀÀÀÖÖ¶°°P$mÞ¼„°°0â+’ª–=zôæÍ›/^ÄqÜÀÀÇñÚÚÚ^½zoݺ5)) Ž_}}ý¶mÛ–——Ïœ9óÎ;oß¾…ÚÛÛ'''0`dd„aØÈ‘#«ªªÊÊÊ~þùgº¶Á› ôNžÌ¸" §§gggggg׿ÿ;w666FGG»ººÂM’““cêr›%WèÙ³çæÍ›/^¼øôéÓŽ;ÂÝY[[»¹¹q[ ìE,¿|ùÒÎÎ.** öxTT”­­mVV¼VãØ–ÍþÇ’ol9¶{÷î‰'fff’åÔì}z¬È…lÖ{83fŽã………B¡ðõë×ùùù°&½„‘ôôôÔÔÔÅ‹·oßÞÑÑqΜ9<`û΃JÄÇÇ×××oذÁÜÜÜÊÊjñâÅåååðìÁÝÝÝÜÜ\&“͘1cüøñׯ_‡®j¹³³óÊ•+mlllmmçΛ––VVVVRRâáá±eË+++kkkÿÜÜÜ7oÞØØØŒ1âôéÓÄùÙŽ;¼¼¼¼½½½½½·oß.—ËW¬X±sçÎââbF l-JKKcŒ¡ªõÉÑS²ûÀýû÷›ššD"‘X,¾~ý:qG…ò0œXO–‘‘º¸¹¹I¥ÒE‹ñx<ò[ PÌO"‘ˆD¢'NÀ.€IùÏç_¹rE*•¶´´Ü¹sçêիĺ[ò —ÒÒR8~(ÎlܸQ"‘°‡ubbb ÍaÆI¥Ò CñÈ‘#ÏŸ?'ž!ÁÕÏŒGßaƽzõJ,777¿|ù®´•8Ó§O—J¥Ä۸ʜø÷›o¾‘H$ðý ¶ “ÛåççWTTƒy÷î]¹\ËuÞÿ*/&&&¾}ûöÑ£GP˜ûWŠ©qãÆI$¸®}Ò¤I‰dÈ!ŒëJd2™T*•H$µµµÏž=ó÷÷çñxäM̘ºt³”.Dx‡^rIÞ‘’’2uêTÂ[>Pö²oß>±XܱcGøkÛ¶mß¾}{êÔ)Æ…ìäm?Æ|£ø@ϱ 6´´´Lš4 ðQ£F«N”ì}ÆXA3ÂaJ^°•³eÇ®éÐס 8®øƒú¦på!}C>ŸÏýÎÅ2†asæÌÉËË‹Åb±8''gòäÉØ;œÆÆÆšššúúúC‡T*÷öö~ñâôüåË—C‡…öýüü`¹X,ÎÌÌ„+7mÚÄø®„²Ì„ÑG‹c¨j}å;ñzÅÊÊÊÝÝÝÄÄ„Ü=dÅ;òßä^Ä0Œø‰^Þ¯_?+++>ŸOîQºòŸÏwrrruud#lÿæý¯\Ý8‡Ã~ýúÕ××ÃQJ1NÚïÓ§OïÞ½ÉꃔMÖ­['‰Èk) ÏôÝq´K ¸¹¹mÛ¶x9Rg1$åE;;;>Ÿ?f̘'OžodrüJ1uîܹèèhè^``àÓ§O‡“àË#)›À¦ÑS—n–rXNßÙ[>PöBÙÜm²SÆ>øxòžcä=’³KÉÞgŒåPMOQ[9[F©½—aÛ¡¾©šS0»ånݺ¹¸¸{®§uwwoÓ¦ ¥—U*'ì;99‘íÃò.]ºtíÚ•(¿~ý:ãkÄ& -p´ˆ-†ªÖWM·WÅ&<¤s—h²S•La¶k×®gÏž)³¦”Û¾……Å„ Þ¼ysöìY5?+ÀÄØ±c×®];~üø¯¿þº  €ø–òh+&”ä£w"ýW²)__ßòòrø `çÎsçÎUÉ1ÆM(ÿ*4«y%ëheÛ%ßæ˜z½OTƒG¾úúú°°0˜]l)ªÒpÖ ­1y–sL­ª–³Ù'—óUÿô’–5ñP% À·ÙvîÜ©jïR˜6mZMMM\\œ½½½¶||ñÅéééµµµeeeáááê_Ý«‚¶bB6õôéSò=U‹1·)…›(¬£y%ë´Æ¶d>®|KNNV£÷ÉÕ|||†N|¿‘-Eµ˜ºÄ?>ŸŸKi¼ê×âÙ7aÞ1Vû.zh%&dS666h2Ò"W¾iÞûØ;ˆ¶Õbê"@ ØÚÚjnDÕs4•ê[YYq}ÀMéú†††„ ’(é§±±1å=en l1·°° ´”­¾¶Êu€ªËcÙ,³•«:T &›}¶äa³£¹ÿÿÔtýÓÑZh"[Å&þ¤<ŒòTtá4ø ›MΊMnŠM䉀".ÅQÇŽÕÕÕpU4ñù`¶ý²ù !Ë\õéÓ'&&¦±±±¹¹999™ð„Í[ÌÊVQZÊV_[åÊ ¡jšÂÎUˆªêhªª¦±¥‡ªÁd³Ï–<ªjžqäCº~héÍ1*ï‚ µe«8ÄŸ(¨*OÕ¾}{{÷î …ð¥W69+6¹)6‘']\Š­þêÕ«kjj¾ùæ“!C†oà²í—ÍOYæ*>>>55µo߾ݻwOOO¿wïÜ#£Ž˜sËVÑ[ÊV_[åÊ ¡jwçhK­\ 4•‚ÉaŸ-yTÒ|xذa]ºtIMMçÞ/›ŸàÌÕ† à÷½ºu놿û>½³³saa!ñýCº²à9æl²Uééé8ŽÓ[ÊV~|Vór¸_=‘èŸÒW/ý*++9:—ŒéÇfY¡jøßÀ˜ªŸm ±%G2¨êÿ¿$]?ÌôÆYæ@åÓÁ`„ Ÿ}öÇstt,.. ’Ëå£G>tèP}}½\.õêÕ÷ß/‰|ø7ß|ñ9[ÌõõõÁv# IDATIØZnÓ¦ [KÙêk«œp˜žH$7Píô;xð [ç»V;ýØ,3–s ÆôP5˜ö“‡£STõü;ÒõÃLoh‡mÔ|vý—#ÈÊʺ}û6<õ›9sæ… |||Ο?_VVvýúu==½/¿ü2<<\.——––RJ ø“»»»µµ5YÃâåå%1---e2ÙÒ¥KÊH·@æÌ™­ÌÇÝŸ?ñûï¿óùüË—/¯]»v÷îÝr¹Š<]¹rð©S§Ž;ŽaB\júôéd;ŒõáO?†ã|çÎ+V¬8vìXVVÛ~9\õóó;pॎ««ëž={.\¸@â¡Cn±Åœ[Kuc"‘+h’~l -k’~l–Ë9:…1=T¡ÂNW2yØÚÅmÿ_•®ªÒªé -°ÍšÏ®ÿrjËVáìâOµå© ÖÖÖPzT™Žd”›277gy]XXõ58šÉs6Ùª¯¾úб¥‰„±>›UËÉsËe©~fвÖÕÑ:v쨒j`IKUƒÉ=ÐèÉ£ªæ‡ÿÿ’týÓnÎ1j8»"¸²UlâOµå© ®®®/_¾TæÈÇ(7Õ¯_?>“ÈS§NÅ¥JJJë'$$”——Òó&&&(UŸ_‡)2WcÇŽN:U$)l)cÌÙ¤ÂFÍØÒÈÈHÆú°ƒ4/'G€[.KíôãÐ0ƒ{׺:šªiŒéÁ¦1ÆLŽFO¶d`Ó<ãðÿ_’®`zÃÍ9æ@ gW8|øp§N lÕ•+W >!y}¥>¹ÄÝÝÝÒÒ0kÖ¬úúúíÛ·3>k}ôèyQºü`îܹ2™ÌÕÕ•î½~llllll‡lmm?~œ’’ÂçóE"ÑåË—-,,¬¬¬"##KJJàçäùï˜5k\~ÆQRVVæããÓ®]»¿ÿþûÍ›7¦¦¦lûeóÓÆÆ¦¦¦f„ ä…„„TWW;ÖÞÞê‡Á§ l-eŒ9†aÉÉÉ111666ŽŽŽiiiÿý7üÎ,cKÙêk«œÞÅŒ·¹„B¡ÚéÇÑYTM?6Ë{dŒé¡F0Ùì3&›Uýÿ÷¤ë˜ÞŽ9@az#˜ÑD¶ŠMü‰Len;ô#ßÒ¥K᩽2õå¦0v‘'²¸G} ‹7n455544äåå2(l2WŒ~2Ê\Õ××ÃS6B"nÚ´i„zKÙb®P¶Š"£ÅV_[åÿ½÷®²ºòÿÏs¦PEš{ (,Á‚ *ø:(ÂbŒi c -.‘0PuùׂL—,TÚ!X¨Cá…iQ±´("…‚‰ ¿#"wˆ€$üHB’û|ÿ8Ÿ¬öQ{Ru½©¸%œ;~Í6×§ˆqJÈŒâtSÐXú7åGÃCç÷Y›×V8Þ‚|Z}ÿòÿIP²%?±õ7•Çgþ>æ mÇí7©} ŠÛÜ–g&âÜ!DUUÕ–-["‘HÏž=ï¸ãI™¢‰hþqz(€öØcEEE½{÷&ˆh,œž6ee%+ÍÓ®G|2„ë[·n뺈F¦­ßò̌Ľÿv“Æ?kvx|òÏÔq €ÇS× <®r½vüŒºnjšï%88=”Ÿ›G`lžv=×' Õoyf¦âêˆj¿=ÕBþ=<žhþ™:®èPôõQ‡­'®vxÐzÖ,ÖµE¸A‹ lUquÚ“q iÄ©§¤`ÕAÉÎΖ\±ššš½{÷Ž3Fþ¾)ADcáô´ùäAØ<ízº~©*¢‘ië·<3ƒq?j!ÿŒO4ÿL;®\<ž”ÿqE× ZâšÅº¶¨N‹ lmq?já5¤§žèk@ŽÀ|2ù®Nôƒ¯#PRþósó€Í£÷õë£ùg õ[ž™Á¸µœF OiÇ•>,?ÿ㊮=<è:£8«Y¬k‹êÔÆíµúã~dв©Eœ~?’Ÿ¨ú›ÊŸì—°@² !îG-çJ©—ÎÊÊ* ´˜+š™¤b«ê aŸÐz.ÿåaå'êä‚Ö?Zlq.¹ÀÉZÜZ0C­Iy€™•ÕE,-æŠ`&©Ø*Pgö ¡Ñ¸ü?”‡•?¶ŠÅùM³¢ØÐ¹¤,¬•Ç®R’fh¨d`feu+´xñbùǃñ˜+™4{öì‘#GÆ¿@b«–,Yâý½¡ää•••9²°°pøðá2ŽpVh½ ùRñ0”‡›Õ‰âŽã4Ëù‹÷Gà¿îÔžËsïúë¯ÿýïï6É´ÒfŽ’É·d¤dòIªVÎu¦­Å½@;w¾êª«ÆŒsçwvëÖMûÓ_ùÚ®]»fffVTT¸®«¾ åÑU‚äŸo£µ²²ŠWª|Ô&`®3I‹­Bœ<„}ŠD"Æâÿ¡} nŸ6l—óGK 6³@²Ö÷ O*À¬oß¾ÄP%`feu+$t˜«;wΙ3çÚk¯íÛ·ïúõëüqù餇­R/ÕÖ­[‡:dÈ… NŸ>½OŸ>ôÆêzÇq$L’y#‘ÈwÜÿ-L›'X~ÿByiÏ•ÿ% Höâ‹/¾ñÆÚoÁ%(XåVR+V¬ÈÎÎNKKKOO¿÷Þ{‹‹‹U€ÙÊ•+KJJ–.]‡KJJRRRÔW-_¾\ÍC·æ¦›n*,,,,,ìѣǕW^9uêÔÂÂBû[0VV´BZÌÕôéÓçÍ›W___[[ûöÛo‡ÃáÞ½{çåå3æ‹/¾xôÑGåûŠæääÜvÛm§NòPg+V¬øÁ~pÝu×!œUUU•v½’=ýôÓKö /<õÔSÝ»w—/”°?þØ»ÿñˆµø<(Žòs±U(ò‡~©ç†€d¯¿þzïÞ½«««—-[&ÏBÉÔÊÛ¬å³?ýéO“&MRK€ÙK/½ôôÓO?ôÐC7Þxc^^ž"áUjžf‡jΜ9W\qE¯^½ÊÊÊ>þøãÞ½{÷êÕë·¿ýmËfVV±Rµ˜+-3)33qì´¨³Ã‡ öéìÙ³Úõ½˜ü?„XCq”Ÿ $C 5šó‡ ›Y ÙoY’fÄ¥“»'`feu±J‹¹Ò2“B$ÇNE9û¤]ß‹ÏÿCˆ5V~T'Š£<„?R*7nœ|×çŸþÛo¿MMMEÔ7yxŽŽ‡ò£8A§Cû ÌÉ“Šçá¡ü輄ˆÛ‡â„ojÞÑ,·ï"‹'\ÉdpþÐåR–ógÕ”*9v}úô)//ß´i“âèÑ£cÇŽõþضgÏžÑhÔuÝxꛣ¾IÞâÅ‹òˆ8þ\ü–(?ŠK:üû_!„G§#öMH³ùóçË÷<ôê‘ÿÏÃCùÑyQ\`¾ 6Nû¦Ö)#’Û7sæLÂä<ªñçvìØáº®ê$Z/ÿ´ßƹqé³¢sçÎápx̘1—^zé'Ÿ|RWWwìØ±„+_Û­[·ÌÌÌÕ«W»®«¾*‹%DÐåRŸ–ógÕ”ªåØ5664è¹çž‹D"Ý»w/((ˆÅbˆúFððЮÚüt\¾0žNGìKsòTž6?:/Š ÌíÓÆ›õÍrûÚHÜkPR9èry[[ΟUÛQêÖ­[åãòÅ_œ>}úÒ¥Kå×UUU[¶l‰D"={ö¼ãŽ;Þÿ}úvÝu×eddŒ;6þ[+(ÚXÍ/£¸t:í¾Òìç?ÿ¹ºµ–‡§æGç%|ܾU«V9Ž“››{ÇwÈQÚx³¾!nßÂ… [ÈíÓvP+ÚI+³Z±bÅÑ£GKKKÛµk÷ÏÿüÏï¼óŽÊù“7"ççç—””Œ5JûªÿýßÿUó—릛nºÿþûå·4§N*„8{öì§Ÿ~j?òY]| ©;ùsæÌ),,|å•W|ðÁôôtPßÞXÍOÇU:Ú—FšiyxÚüè¼(ޏ}(Nûf¹}m'îý·›4Οº\Ârþ¬Ú˜RUŽÝÀŸ}öÙ¢¢¢-[¶¸®{äÈ‘öíÛÿèG?ª¬¬ÔRßm9pàÀ¢¢"5—.]оBG§Cû8@šiyxÚüPîPñÿP|óæÍ„o–Û×vâñ-Nç]:y¹„åüYµ5©»ôôôÊÊÊ5kÖdddddd|ôÑGûö퓿륥¾ ÌÉ“J`è üľˆN§Ý—Fš!Ο6?:¯6ޏ}wðÍrûÚN\½•ÚïB·„óG\®YΟU›–o—-ù|555{÷î3fŒŒ#êâäI©Ï_”ÅŽÞWèfZÎÊΫ;€Û‡â´o–Ûצâ~ÔBκ\ ²œ?«¶ ‡àØÉ·Ô:xð GÔ79yBGCùQœ Óû ÒLËùCùÑyiúâÿiy~¨~ËíkSq?j!ç].+«6*ùu +ÎÊcj_nS"Î˪§…çµÜ¾‹>~”ìËbeeeeeeeeeeeeeeeeeeeeeeÕªE ¾Œpø¸âòí ñó¸ô;T—ç‡ò³2hÅ%)ÇVÅ·»ÐãçAÄ0[Yµ9%Ð×P!¾Lqø¸õÀç»ÿþûãwŸ~ú©üEmDGCü<.ýÕÃåùùÅßóù´h‹¤ˆÖ·6¾Ý…÷£òùÈ¥•U[”J_Cq„ø2ÅáãÖƒø|³gÏ®¬¬œ«¶ T-ÇñíhÄ—*.‡í«|»p8|à 7D"‘´´´™3g>óÌ3/½ôAGC\=ýÕ€çG(ÏGgH üqIŠh}kãÛ]èqÏðdóùdí0[>ŸU›RHÒ׆ۣ²©C/_[¶lIMM½ãŽ;šýyZ¯£}‰z¶nÝ:tèÐ!C†,\¸púôé}úôqgçÎsæÌ¹öÚkûöí»~ýúÇœþ4VòóäW‡‘H$á\>éw¨ž÷ß_Rñ^|ñÅ7Þx#þ[Rô¾ZeggÇ#Úé ZŸÖ1Ö‰è ­kÅŠÙÙÙiiiééé÷Þ{oqq±Êç[¹reIIÉÒ¥KÃápIIIJJŠúªåË—£öØcEEEèD+´^ÿã?þ£v_TÏgŸ}æñíb±ØŠ+þå_þåºë®Û·oßôéÓ…±X¬¾¾þí·ß3fLïÞ½Mòó¦Núú믻®ûå—_þë¿þëþç:tHpèwñ¼½„z²³³Ÿ|òÉ|óÍ7Ë–-»ÿþûEÏí«UŸÎ ³gÏöpD…¬Å#åâlmÜ» %îý·ÛÄÕ»ä’K&MšôÎ;ï$,–|>Ùý 6üñÌËË{ã7^…òÃ|XëdkãÞ](ñøv'‰Ï'_N ³åóYµ-©ô5DekñÕBÚ—àí!¾ÝÆ7nÜØ­[·Ë/¿|ëÖ­Û·o'èh4?E¿Cõ°x~(¿Êç£3 ¡’"Zœ´ñVËçkv˜=Y>ŸU’Ê±ÓÆiÄWË9|Üzßîæ›o–ùkkkwíÚuë­·:˜Žæ`~—~‡êañüŸ*ŸÎ %rIŠh}kãÛ]èq?j!ŸfO–ÏgÕôŸ-&pì´q‡D|µœÃ‡ö%â_°wïÞ _}õ•OªœÊÏãÒïP=\žŸ6¿–ÏGdÐ’Q…ÜÑNÚ87îG-äóÑÃleeÕŒä×I-_ÏÍc*?Úô<ÔÓ’} >Ÿ©Žp×'²ñq++++++++++++++++++++++++3B<9BFø|ˆ6‡âˆÇåöòÉÉ3(䤖ëÆí‚´µ6^Ý…ÿÞÅ1rEå7²¯Á«ä³N.ïûÐkm#}ñĵ;Ä“ó”ÀÉ3ÅçC¼:€Gĵõ#žŸö\4ýNÍßìúxÞrqÝP§Ð‰¤­µñê.ô¸µ·'…-˜ F”‡‹ºDùiä¤ð}%ѹˆõ¬üþјګD\vîC¯µôE*ÇŽàÉI©œÄ«CqDCqT?âùiÏEÐï´ù›]ÏÛCNj¹nD§Ð‰¤­µñê.ô¸ùçíÌ<Ôh.ˆåá¢.Q~9éÿJr‘œÜüþјګD\vîC¯µôE*ÇŽàÉ ÀÉs ñùmÅmÅQýZž:——ÓQèw„?h½ø{ÞžvGÄu#:¥=‚´µ6^Ý…Ox\ãíÅ‹`æ¡Ñå‚Q.ê’¸29ɺ’,$g€üD"îªÒðNõ²sz­m¤/¾xªÊ±#xrðóÜ&ÅOI>¢ÍiãˆGPèPýZž:—ô;Ú´>·§Ýñð"‘ê”öDˆ8hy{­Š·'ÌdÈT¿–ç—€IJ¿£ýQ× …·‡„¸n®ëj;%„ N¤BÚZ¯îB{ÿíåíÉ!ñÃÌÓ6úرc,#ʳwï^ê%G"® ÷\Úõƒ6uåµWñµ—]pz­m¤/¾x(77W~Šáqì\ו<¹œœœiÓ¦uéÒEòä233%'/''GþVÅèÑ£ „>C8p`iié°aÃ\×Åb‡ïšk®ÑÆãis±X̣͡øñãǵô8D•#ê_²d‰Öí¹¤Túíº^(¼=$ùÀÊÊÊ’ÿ7žë¦í”‚8‘„´åçç{6”߯ƒÅã[]__ÿ¿ÿû¿ÁPdVVVVVVô—¿ü%áO…Çùãÿ¨Æã5xðàS§NIB£Ÿøÿ÷ÿÏÿüÏèÑ£;wîüË_þòìÙ³O<ñ„ýàgeeeeõ=èܹs#GŽLø@õ³ŸýL÷ôÚk¯iÿ Å£ÑèüÇÈ¥¡Pèí·ßFïvaeeeee•\UVV¾ôÒK _~ýÃ?üƒ6îiïÞ½K–6š$ IDAT,QÿÅ·lÙ²sçNïÝâ‰÷¤°²²²²²JªBGŽQñ%çÎÓÆ¥:v옙™YQQá3.„xâ‰'Ú·oÿ·¿ýmõêÕ¿øÅ/ä›);„••••••o…¾ûî»ø·²õ„âBˆnݺµk×N¥K£¸â£>’ØŽöíÛÿö·¿Ý´i“|·žø5¥¥¥[šÔìï×XYYYYYS*úÓ³ÀR×uOœ8ñ›ßüæ·¿ýíµ×^»jÕª¢¢¢{î¹'þ+?‰1“ÿ}äȃ»[YYYYYyJ½ì²ËÀÁR(.„8räH}}}zzºÏø¨Q£~÷»ß=øàƒþóŸc±Øßþö·Í›7_uÕU Ë^{í5ï¿%Œ}+++++«æêÚµëþýûÕ3^|àÀ‹/îß¿¿÷íÇ3gÎ:t¨gÏž /AñmÛ¶¥¦¦>ûì³×\sã87ß|ó7ÞøÅ_$,‹ÅÉ~س²²²²J–êëëÕ¿^7nœ¿ë®»êëëo¹å–ø5¿ûÝïvîÜ©þ~&Š1âÏþsmmíÉ“'kjjJKK#‘H’NdeeeeeEiÆ êŸß-_¾Ü‹Ïž=û³Ï>KX3dÈÓ§O«ÄWw'%%%‰\wÝu:u²Ò`eeeeõ½é¦›nJø(5vìØÊÊJ/þâ‹/¨É~ýë_—••uîÜÙO<~éXYYYYYq¤þÕù¶mÛ&OžìÅC¡öÕ|+–_|1!Š[YYYYYµRuíÚÕç­””-Å­¬¬¬¬¬¬¬¬¬¬¬¬¾i¿D‹D"êç !.½ôRíof¦§§k×_~ùåÚMQ$´Õ‰öEu"¡ü(žžžž––¦ÆQý¨N$®êGþ°¾”GyLù`ª¿\uìØñŠ+®P€â¦æ{ïÐ|rçY€y@õþhó£þ¢<¨~®P=zܿ΃ì'Ú·Eõå—_ž:uêСCñ¿½yË-·lÛ¶­®®®®®nÓ¦M”Ù ôÑG={¶®®nÛ¶mC‡•ño¼qóæÍ555çÎÛ¾}û 7Ü ã£GÞ¹sg]]]UUÕ’%K¼j´yf̘QUUuêï%¹í‹êDû¢:ï¿ÿþø­?ýôSùÛ§(?Š÷ïßÿã?>{öì™3gÖ¬YÓ£G⼨Nƒ>pãÈŸÅ‹kçù†ò°|ˆ×ý×UWW7»žÕ_äó#<‚üB<ÿüó'Nœ¨¯¯¯®®ž1c†÷smÜÔ¼qïÊæ“;ÏhP=È”Ÿ˜mmýÄ=âús¡Ç¥:vìxðàÁ„\ÂÍb9LÜPG‚âľ-¨_þò—~øááÇã'xûöíååå?ùÉO† vàÀuëÖÉÉØ´iSyyùµ×^Û¯_¿;v¬_¿^ÆwïÞ-Ë0`ÀŽ;6nܘ’’Ò¹sç/¿üòƒ>èÙ³çÏ~ö³cÇŽýú׿–õiótéÒå†8ýæ7¿‰F£ò/èѾÚ:‰}µu !fÏž]YY9yòäxàÈÎΖþ"Püã?þÛßþvõÕWßpà {öìY±báªÓ”âÈŸÜÜ\íœ ßP–Þ.wÝu×¹sç\ו÷ÁT‘Ï„ÿ>úhUUÕÃ?Ü©S§[n¹Å{{75o¬{GäGóÉg4¨ä6?Ñ_”G[?ÑG®?z\jÊ”)íÚµC7‹ë0‘ÅÑ„ 8Ú·å%B¡ÐâÅ‹&øÌ™3ÿöoÿ–’’â8΂ ¾þúëÔÔÔŽ;8p`Ê”)2>þüh4šššš‘‘ñÁŒ7NþèóÏ?ÿí·ß¦¦¦æåå544 >ÜqÇq–.]ºwïÞ”””Gá4iøðáÇÿùÏ …ˆõÚ:Ѿ¨N!Ä‚ ÊËËSSS½P¼_¿~õõõ÷ß¿ÌÿôÓOŸ:uŠð ÕiÊnœðÇqíœh}Cyø „hß¾ýÎ;?ýôÓX,&ïÁþj}&â{öìY¶l™|vÄçÑÆMÍ÷Þ¡üh>¹óŒæ¨GëÊOÌòÍ9ê#ËŸ =îÝÖõë×/X°ÀûœR½YFy´q4!Ää }[>Q©Ú· ;tèе×^+„HMM0`À¡C‡\×=sæÌUW]åºn,BôîÝû믿v]÷èÑ£cÇŽõòôìÙ3º®‡ÇÙ·oŸŒ9r¤K—.Žã <"îm²çÍ›·zõê·ß~;‹ëµu¢}QBˆH$rìØ±)S¦„Ãá 6üå/!|@ñ~ýú9Žóå—_Ê7=tèP‡ú÷ï¿cÇmý¨NS>pã„?n“æDëʃê'|B<óÌ3iiióçÏ6l˜Œì¯ÖgOKKËÊÊZ¼xñÈ‘#ûôéS^^¾iÓ&!Š›š7î½Cù‰ùäγvP=È”?‰hû‹òsŽúËòGRe.ܸìW¿~ý®¿þú™3gzž¨7+€ÃÚ<(Ž&„˜dí¾F&*ñÝ[¤ ‹‹‹wîÜ …ï»ï>91Za„ ?ýéO~øa/>hРçž{.‰tïÞ½   ‹É·ý¼í¶Û–/_îºîücï m”Gª  àꫯÎÏÏ÷–¡õÚ:é}Õ:…ápø†nˆD"iii3gÎ|æ™g^zé¥X,†|ÐÆÛ·o/„ð"]þáˆê'ê4âC€8ò ù†òp}èß¿aaá“O>YSSãÝ4ƒýE>kãáp¸]»vò^õíÛ÷å—_ž5kŠ>pçuïP~b>¹óŒ¤­ùƒò£þ>#ßPYþ\èqù'Ož\^^¾}ûv×Þ¬kóqâÉ k÷52Qú¿Ûû§ú§K.¹D~6‰Dî¸ãïsp!Ä€æÏŸ_RRòÆox§ªªª’h½ÔÔT¹þ½÷Þûä“O^xá…_|ñ7ÞøùÏŸåBÜwß}6lPIêzmô¾jBˆ;wΙ3çÚk¯íÛ·ïúõëüqù=äíRBýÍúÓB‚Õ¯õ ùFçñïüyó¶mÛöûßÿ>~< ö—öYߺuëСC‡ ²páÂéÓ§{ôf72o¨ïÁΫ*Ø«ñcÇŽUVV^yå•òÿÊ@ß}÷Š›š·÷N›Í'Ú—žgU¨äϾ}ûP~mQúy¥í/ËTç…w]7??ݺuß}÷ü't³Ž?Îr8++K›ÅÑÅѾ¨NÖD ¡|îÖ«W¯“'O®\¹2===‰|ðÁGŽ‘ßjå•WNœ8qÇwdfföèÑ£GíÛ·OOO¯¬¬\³fMFFFFFÆG}´oß>ù»X×]w]8BLš4éôéÓóæÍ“¥µyäî ˆÿ~…v=Q§v_¢Î7nܸ±[·n—_~ùÖ­[·oßž’’‚ò£¸ã8Û¶mû裺víÚ«W¯Ï?ÿüÝwß•ùÑy‘?F|àÆ ¤ÔÏñµ¾yX>„B¡”&Mš4Iþv1WÜþ>þ=ztÔ¨Q—\rÉ»ï¾ûÕW_]vÙe(njÞÜ;m~4ŸæY;tßUˆüÄsCÍCø†úÈòçBwíÚµªªjüøñžÄÍb9Œò 8š§oD 'J3ÁŽãÜwß}¬©©©©©9pà@NNŽtíôéÓ®ë644Ô7i„ ŽãdggñÅgÏž­©©Ù»wï˜1cäúâââ³gÏVUU>}º¸¸¸C‡r ”G1uêÔÆÆÆ^½zÅ?†ÐzT'ÚÕyóÍ7Ëxmmí®]»n½õVÇqP~bß믿¾¬¬Læùä“Oäïõ£:ø ~äúȧõÈÀ)ù ïw¦ô—ðÅÓÓÓW¯^][[{æÌ™ƒz4.72oî:¯v>Ì3šTòåGýÕæ!êG}dùs¡ÇgÍšµk×.E§½YÖæAq4!Ú8±oË'ÊMßõnhhðÊ•ßr•¿&{àÀÆÆFù½Õ>ùOr½|#™ƒzëC¡P÷îÝ322¾øâ‹ÚÚZïç«(WŒ÷éõ¨N´/ªÓËÓÐÐðÕW_©ñ„üt¼W¯^õõõ‡ö~OÕê4åC°¸êO|IÚ9Ñú¦æ àƒ·QJJŠñþ"Ÿ‰¸üT´}ûö{öì‰ÿWmÜÔ¼qï_Oî<Óó Â5?1Dµ~ÔÇ`þ\ ñÒÒÒmÛ¶Í;Wû{Ú 7+€Ã(6NO,1É꾦&J#ùQ—Záo=+Iq÷%Ö›Š7SqËÖy’z.Sûyü/&Ö›ª‡Ø7Ùó“Tÿøæ¿³õÉ Nn=­9.¿ý¨]‰tÜ ´/³R+++++++++++++++++++« AÉæ±™ÊOСX|A.—Ž[?—;È­‰Ë·˜¯Æå·q©]I«;#> <ú‚ÄÊÏå´™šŸV(ƒ-°ºHÄâ±yj!u‰Ë{C”&”Ç—Ž[?⨙âÿ¡<\¾ªŸËoÓúCpÑ´ûë¹}árìLù€òpù‹Ü~¡¾kë'öåÖÉz>ø9/¡È—œ8qb÷îÝEEE¬ß×höjXµQ±xlR-§.qyoˆÒ„ò˜âÒqëG5Sü?m.ߎ¨ŸËoÓúCpÑ´ûë¹}árìLù Í€¿ÈêÑwmýhßu²žÍž—V4]¶lÙðáÃo½õÖÙ³g×ÔÔÌš5Ëç¿f¯†UÛ‹Ç& Q—P~.'å1Â¥ãÖOðóŒðÿP.ßÕÏå·ÑþH©Ü;m¿´ë¹} À±3âÊÃå/rû…òÓ\=ußu²žôy=Ýyçê›¶ !¢Ñè‚ ¤ç¡PhÓ¦Mk×®õÆ[}U|„¾VmY©k×®u}óØ„!êÊÏåä¡›¼<ÜüßWSû~_õ)’È“lˆz’:Äú¤æ1%¢N#y.]ÄG³²²²²²²²²²²²²²²²²²²²²²‚2ÂëØ±£ü埛"ŽÊÃåq× &‡ŒË‡ À·ãŠÕG._åAý"æÁˆÏ\¡y0u Àäò#Ñ<³üäž­GüB¢_,Î%·NîœpŸ3ÄóÐȽFûrãþ…àC‘¸ŽömQ§Xü-LêùçŸ?qâ„üä3f$ü:²OÎÊÃåujëár ¹|8â¼ÚüZ>_Žê#—/HÀÏPßµqS>£:QÍ‹w€/ˆÎËT?×O.Ÿùƒø…¨_\Î%·N”ù€æ“;'\n%w>¹q©Ž;úhUUÕÃ?Ü©S§[n¹%ÊåŸó‡ò°8dŽã :Q=\N!—‡â(¿–ÏÇå¨}dñ‰<¨_(nÊgÄADqí±^Ë/$ú¥­­çÖIì‹úÈzΠzp+YóÉ{­_¿~ý‚ ¼Ïáü;€:Käa=á Çо-ïTªü›P?ü-.ìË/¿ÌÊÊZ¼xñÈ‘#ûôéS^^¾iÓ&/›Î_ZZš6—CF¯÷ÏECõsùp7N›_`Οö¼Ü>rù‚(ꊛò™ðGGó@CÝüóç¸\@îœÐóìßO.ŸX¯åýÒÖ‰Ösë$öÕúÀ}Π9 À­dͧ|#ÿq9ýúõ»þúëgΜÀÔYâFhãž„Ú}t*Uøæoqy`‘H¤]»v²Ž¾}û¾üò˳fÍŠÅb,Î_8ÖæárȈõ,.±žË‡Cq”qþ´çåö‘¨ŸÅDýBqâm5¸>#´q4y‡þù‚H¬9ivþ}úÉåóë Ž£¶_„êúA´¯Öîs†¾G,n%k>¹qù'Ož\^^¾}ûvg9@DÑ0ErÕîk¤S!᛿Œ¶uëÖ¡C‡2dáÂ…Ó§OïÓ§ã88jžf·6Åã®gñá´q”qþXçm¶>ù‚tm߉¸Ÿ‘?´oþý ÀŸãr r"Uiëçòùˆõ4¿P{/%¬ÌT÷%úèÿ9C×ÃâV²æ3˜²³³½/1ÓÇqPgQS$Wb¢ZØ©PFFưaÃ>þøãfgÑuÝììì×_½wïÞÕÕÕË–-;wîœBþo‚äoÑÄb±;v466666®X±â?øÁu×]———7f̘/¾øâÑG•﹜““sÛm·É#UTTÌ™3§°°ð•W^yðÁÓÓÓ«««µyêëëµûÊÿPÏ…ê¼ûzTÑõG"‘?üá_ýµ¦x¯RÏ…âDþéÓ§Ï›7¯¾¾¾¶¶öí·ß‡Ãò[Úórû(¥­_»¯B›õ ÅQ|Fþhãh?t=ÈÔw$ÿs‚êçú‰ú(¥ž ù3|øðiÓ¦=ýôÓÓ¦M›:uê /¼ðÔSOuïÞ]¾ Ý $u==·È5òáÔ©S¬ç ]ꣶNÖ|rãBˆÜÜÜÎ;¿þúëò#×ÔY”çž{îa=á‘ch_îGm§B,Žš„]åääL›6­K—. <0¹Æã;v¬²²òÊ+¯”qI ýî»ï<ŽWNNŽü©ãèÑ£ tÍ5×”––6ÌuÝX,æqÔP´¯ 8dh=ª}ä£×K>\~~~<N{.tÞ¬¬,”É’%¹¹¹r£x>Ÿö¼Ü>ÊRëB }µyP¿PÉõ™¨Sß¿?ší¹èz´|AmÑy¹sBÔÏõ“˜‚ç—°>ž+‹Å<~!Ñ/BÚõÜ:µyÇç>g´õÐ}×ÖÉšOTQg~~þºuë¼»Æuu=©PM2Š£}tŠÇQãòÀ^yå•£GŽ5ê’K.y÷Ýw¿úê«Ë.»,Ääü¡<ľBÇCëQ=Èb=‹‡âD~ÄçÓž—ÛGT?±/‘Gí7â3Q§6NÌOÞ¡¾ :/wNèùgùÉåói×üBÔ/4Ÿh=·Nmz®XÏm=¸•¬ù䯻víZUU5~üxoG®¨³(÷ âôDµ°S<þ—–žž¾zõêÚÚÚ3gÎízó Q¿Ph=·Nz_ÕîsÕÃåVr瓟5kÖ®]»´càÓ¢³(г&œØ·årXü­<0ù¡»}ûö{öìQwqüqþPb_í¹ˆõÚzh=—Gœ—ðGåó¡órûÈå ð3ÔwbLùLpµquš…º©sBÌ— èNèyöï'q^í¹èç€Ê/DýBu¢õÜ:é}Uó9CûàŸ[ÉOV¼´´tÛ¶msçÎÕþ>-ËD¦ÔæÑƃM¸v_#âIý~Z³qôO¬õDÜòëM‰{.nžõp׳ü7u^®LÍ©"[ÛüûYú›¼äÂÜœì;wßøÿ+¿ýè¿ ºSOî„·ªmeeeeeeeeeeeeeeeeeeeÕºÄå‡qó˜ÊOС´yÐz7U?—Æ­)Oñá´t+®oÜ}‘¸}áòQ=\PSœ?n~.§ÍÔü´B™ËY]jë÷s^B/9qâÄîÝ»‹ŠŠX¿¯Ñ,XΪŠÅ“j9u åGœ*DiByÐz7U?—Ç­“ËÉCýBõ#¾Ë7./0ߏ|DS>°8ˆÄyYýâò2¹¼=nѼ5{^ZÑhtÙ²eÇ¿õÖ[gÏž]SS3kÖ,ÿüh°œUÛ•~˜”êÊøjˆÒ„ò õÚ¸©úpãXu¢<Áxrjýß‹å›húmcÇ/­çö…ËG4åÊÃåÉqû€—©Ý7@¬ç}^OwÞy§öMð£Ñè‚ ¤ç¡PhÓ¦Mk×®õÆ[}UB„ËYµe¥®]»ÖÕq¤¤Ô¡.¡üˆ¯†èP(Z¯›ª?7ŽU'ÊCpË´ýBõ¼7–o‚É Dë¹}áòMù€òpyrÜ~qy™ˆ[ NÖó>¯¢sçÎápx̘1—^zé'Ÿ|RWWwìØ1uB\×íÖ­[ffæêÕ«]×U_%Ï’‡ËYµi 4è½÷ÞÛ¾}{ee娱cã?{RßU¨ÿþ'NœxðÁóóóÞ«åaåß°aC]]ÝŽ;***jkk=ZǨQ£öïß¿{÷î½{÷îÚµËûùʃÖyŒÔïi„ 555Þ3¸çBqmž±cÇ644äååÉ5 .<{ö¬¬Šè—Z¿|Ÿ¡›o¾Y®‰’x IDATÛ¡¾ ! Nœ8‘™™™`òM»>@_TÿY} 惚‡è :/«_(?Q¿vßu¢>Òõ£\]]=uêÔø¯£Ñè¡C‡>ýôÓ¿þõ¯•••Ÿ}öYFF†öUyyyjºeVmV!÷Ëu qªhî—*´žÈc‹æŸÇ­“ËÉãr¹~Òþøç#ëô…ÅG4僪<9V¿‚ñ2Õ}sïTà !V¬X‘–––žž~ï½÷'¼¹Ô¾}ûV®\YRR²téÒp8\RR’’’¢¾jùòåjžf[VZZº¥I#FŒ°ÛŠäwÏC¡ÐܹsÏœ9ÿëà ŸÓååå;wîå—_~â‰'-ZÔØØ8oÞ¼Ûo¿=þGjÿùEÓ›ÚÉÿž³êDç¥ë'ò!V­Zõæ›o®Y³F~T‹ÿ§h4úꫯ¦¦¦Êö7®¾¾~Ò¤IŽã¨¯JˆÐW^ꡇz¼I½zõ²ùÚˆR‡ ¶eË×u=*Ree¥v©GuB¤¥¥9Ž3zôèãÇ=ztîܹEEE yºtéòì³Ïªq”_±dÉ’5kÖ¼õÖ[®ëzœª!C†¤4Qš\×õ(MÞOÑÔ+Žê¿Å;u꤭3@ý¢‰–›››Àó.Tç×_­Íã6ѧÇq]÷Í7ßLàÉ%ôëÃ?ÔúæÑ­6nÜ(âèV999,ߤ?,^ výÀ‹ŠŠ¸}QýGyP¹> 9M<¹„¾ órû…ò£ú]ÌqdÕ‰D×Oç‘ØØ:Äb±ÆÆÆ„•?»•_îÙ³G~ªç8Žúª„q•¼2^{íµøìOÛŠüóÃB†¨K(¿œª^˜Ò¤ÍƒÖ£¸ÁúYÜ8n(Ä“SëwÝŠë›ÌÆâj×è ‹hÊâ\,ž·_(?ªŸè —{§­‡®ŸÈãIûOÑhtñâÅYYY=zô:tèªU«ª««ãÿ,O}•i¶eVmW,~˜§–P—ˆüZN•ÓJ}ri×yLÕÏâÆ¨“ËÉCýBõkéV|L^ ZÏí —hÊ”‡Ë“ãö‹ËËDû«Óÿó¡ÙóŠF£²§ÕÕÕeeeyyy>ÿž¯Ù–YµY9)))þùaÿ÷²–Q—P~§9¾š££CyÖÓñ–ׯ>|rãXu²8yÚ~Ѿ©t+®o‚É Dë¹}¡ýçΡP¢/„?þû…ò£úѾÁêôÿ|hö¼„z*¿óé? Ý2«6-ùùlòòpó_yLíû}Õcê“Y”'Ùþõ$uˆõIÍcJDFò\JöˆZYYYYYYYYYYYYYYYYYYYYY}Ÿbñɸ\:®>œ¶N.›Ÿ ýêØ±£ü% ŸëMqÝLÁɈúYóƒâh~çA+”‡ÛG´/7‘_['Áí3Â)Dë¹sK¬O*Ç‘ˆ³æ‰Ëqä>?MÕÙòJ’ý„ @ÜÔêïò°ødžøaˆ‹†ÖkãÇ A¶P\7³Ð/õ¼Ï?ÿü‰'äofϘ1CþZ6—·‡Ö³ø„Ï(ªŸË·Cq4?ÈSó€úE̿֔‡Ø—5Ü:‘o¦8…\^ wΓÍEqÖÜx^™âzrï—TÇŽ<8qâÄøá÷ù$çFµëiR£öF°ˆ›D~5`ñɤT~⢡õÚ8ÁñB-T'—ÇÆÍOC¿Ôó>úè£UUU?üp§Nn¹åNÆåí!΋ÿGøŒò ú¹|;×Îჩy@ýBy(Ú—5Ü: ßLq ¹¼@îœ'›Šâ¬¹ ð¼2ÅõäÞ/©)S¦TTTÄÿ!¿ÿ'9—0ª]O8†n‹¸IäWóˆ‡O&tü-‚K§]OÄ&%p¼´-Tg. +?ZOœkÏž=Ë–-“3ÿ Ö\Þâüàj}FyPýZ?‘o(Žæ‡ðÁÔhó . w¸uF"­o9…Úõܹ¥¹€Ú{Êò™0·¬ç:—ë¬Î~ýú]ýõ3gÎ$&ß a­×:†nD0⦚_›Gó=tùV“Þû8È\?üá…ýû÷/,,|òÉ'kjjâûç½Éì„ ~úÓŸ>üðÃòåh=ŠK\}õÕùùù^ÚÂÂÂâââ;wÊ·¸ï¾ûb±Qgccã Aƒž{î¹H$Ò½{÷‚‚õmMâÅͯ]·۵kWPP '²oß¾/¿üò¬Y³$Hó†nˆD"iii3gÎ|æ™g^zé¥ýû÷»®{Ûm·-_¾ÜuÝÿøÇÞ7(´ëQžX,†êD>kóõkÍD¾ÑýRç‡ðÁÔsãæVÊçóŠ8z~j} VçäÉ“ËËË·oß.ãÜ'9÷ ƒÖk#nª‡ždµ#j_oç‰æo©\4´žËñâòù“ÇfŠÿGœkëÖ­C‡2dÈÂ… §OŸÞ§OÇq¸¼=Äù Æ5T}FyPýt ¸J˜ÂSó€_¨õ!·ÒÿwîÜ#<"Otã7644HÀ˜¬P–Ñ,oO`>Ÿ6Nóä´¼4mžôôtT¿ÖOäÝ/-WO냩y@ýš8q¢6òžgu_ÂO­ÿÜ:‰ùaÝ ÚOu=ê1·Dj~³|P5lný?¯Ð¹¤üs=Ô™››{üøqï¸OrT ñ„A×:F?a¸ÄMD‚LÈ£ù Âã{Éÿëñ½<þVNNŽü¹ôèÑ£ $ë“\´üü|‹†ÖgeeyTŽW˜šÔ/”ù€æüšk®ÑîKø©õåGu¢ù8p ë^ÐýÒŠ;·h½V\Ÿ¹qä'íƒÿçýeŸvþµ¾¨3??ݺuÞå>ÉQ%Äu\ëý„Që¡'‘ 5çòÉ' aþ––‹†Öy„Žã… [¨N.›­§ý9zôè¨Q£.¹ä’wß}÷«¯¾ºì²Ë“·G¬À5ÔòÒP~T?k~PÍòÁÔ< ~Ñuª> <4GÐÿ<¨Së›)N!Z`n . šŸë37`nYÏ+Â7ד[g×®]«ªªÆïUÈ}’xÂ Ž£'ºˆ›(B}'¾—T qÑÐz"®r¼ ÙBu²xlÜüÄzt®ôôôÕ«W×ÖÖž9sæàÁƒwÝu—Œsy{h}®¡–—†ò£úµ~}Aq4?ZŒÏƒÚ/”‡öA̓öåηN4?F8…ÄzîÜÒ\ÉäñAQœ;·‚ù¼Bçbq=¹uΚ5k×®]ZU'FéIÖ>yÐ@ÜÔæWó8‚Ã'‹_ÇßRmUAk) oL—Åh9mˆ‡8j¸€¬üôK=—ü©}ûö{öì ÌÛC뛫uÒ>'äAõÓ~"ßÔ8šŸf}02j¿ˆù'|@y´û²æ['í[Ë9…h=wnÑz”Ÿës°¸ÿ¹Ìç:šú^û¬³´´tÛ¶msçÎÕþ~©Ï'9÷ CL²Ö1n]2(úÀ¯WÂç›ß»ägÚ8k}+Ìod_nÜTDV<@žd÷ËTžd÷‹7’?@=¬~qeÊgƒskäh-¬S~üåeЕ$õÉcj½•••••••••••••••••••ÕE+._MKE ÀÓŠË]LŽZOP©Xþ˜¢I¡õ(¿)n!#\1¢Ö¼qý†8‚¦Ä­Ý/.ßÍ —cgeu‹ÅåB\+Ì ‡OË»"òsùX\n‹&%0õ ­'8ˆ*ÝŠðÛ®ož|ò¹óÆõßG¦‹©ç%úË­ݯ|;-űC><òÈ#ÍúCèÀò%'NœØ½{wQQ‘ÿßËðÓ+«¿‹Ë¥¥"qy`9|ZÞ‘ŸËÇârËX4)©Wh=ʯ¥[>pûÂõMÊ?‘ËÕãúo„#HÔ¯=/Ñ_Vè~àÛ! ‹c‡|hÖZÑhtÙ²eÇ¿õÖ[gÏž]SS3kÖ,ŸüZ¸µU[TÈ7— Q‘‚ñÀ¤ZÂáM5¢r¼P~íz‚J¥]ÏåÌ>h)Vh=Q'ÁÏS}Юo‚Ã_äÎ×nðØÐyµýåÖ‰îW¾vN¸;zN?žî¼óNí›SG£Ñ HOB¡Ð¦M›Ö®]ë}"¥¾*!âgk++O<>Ÿ–Š„8[\Š’às×Ü&%œ å×®'¨TÚõD=\š”–b…Ö£:i~žêC€¾p}þ"wÞ¸þsû€Ç†Î«í/wÞÐýâòíМp9vôœ „;w‡ÃcÆŒ¹ôÒK?ù䓺ººcÇŽ‰¿—,»[·n™™™«W¯v]W}•Ä9%ä¡·¶²Jϧ¥"浜ÃGKÍ„(PZq9s„ˆbEpÅÔüÍòó´´*V_¸¾±ø‹Üy à?«xlè¼Dý׉î—oGSÐX|;ä¿ýöÛ‹‹‹OŸ>‹ÅvïÞýÔSO-Z´(>áøñã,ß…ä›o¾™3gN,S_uòäÉE‹ióø]«6.ö7T*R`˜)®¢4!i)PäŸ&EP¬ß´ù º•Ö‡t+ÿçåò ਙê#’Z?:/M)óY'º_øvÏIŽê#НX±";;;---==ýÞ{ï-..Nøx¿oß¾•+W–””,]º4—””¤¤¤¨¯Z¾|9ÊCŒViié–&1¢%«‹D,.—££"à™âð©õ£üè¼RˆÅõ‡E“’¹ b…|SóÓt+äƒÿ¾p}£é_j~î¼óß¹<6â¼Dý×)ðýbñíè9AóÀb~„«V­zóÍ7׬Y#?ªÅÿS4}õÕWSSSåvãÆ«¯¯—å©¯Òæ¡·~衇oR¯^½ìG¾6.ŸàÞ൜ÃG:(MHZ*•V\ÎზbEû¦æ§éVªÁèVþ}£é_j~î¼ÑóÐò>rylÄy J™ÿ:æÞ±øvhNÐ< Ž|9šz~f̘ñØcMŸ>ý‰'žP¿!)7’Ú³gã8:urG}•6½õk¯½öR“***’ñÍ« L>¹\)¬å>T?ÊO¬GT*–?(ზbEsÝ´uü<Õ‡t+–o!&‘;o\ÿ¹}¤çM­Ÿ8/Á;ô_§À;ßÍ —cGÏ 1?ž´ÿF/^œ••Õ£G¡C‡®ZµJ~?'t?[[YýŸüs¹)̇կÍO¬§ù‚þýáҤŠ­Gù nœÖ.Ý*˜o‘ð“ËQ3ÕG-^ çEýåÖ‰î—o‡æ„˱#| ý!F¥'ÕÕÕeeeyyy¬¿L¼µU”#ø|5•ŠâóÀ´%‡É]‹O•ÀñÒæGë ­GõpiRI½R×u"ná³ÿ¾óM(ô/ºÿóÆõŸÛGbÞÔó¢þrëD÷ ÅQArýsìh%x"¿óÉJxk+«¿ú¦ã8Úâ®'öeåÿ¾Ä­‡8+ÎÍoj}²ejÞ îk*¿‘T¦êLöZYYYYYYYYYYYYYYYYYYYYYY?<9#|2ÄãrÅq׳„êDç"øg,?§Ð”P~.‘[§©¾s¹}¨/Dý¨?˳Dù¹óÆz L͹`ž×à½02o¦tÎÛòÌI}2›"}ú’–†¸ež|r×౸b¸q¬: ®ª ÅY~ !§ÐÔ¹P~.­G\:S}çrûP_Pýh®¸ü<.Ï’ËÕCqä?—HÌ¡ÿ9vYýB÷íËåer}Fu²ÎKøIïÛ±cǃNœ8‘x° ÐYîj @ÊTãBË CÜ2)ÿÜ5-ŒË ÀcÕ‰âDˆs†â,?…ˆShä\æ rùˆh½–Kg°ï\nê ªÍ‹Ÿ'ø¢ã8(Ç¥›={öÈ‘#Íö]rãÖ®]+_Ò³9nê áQGçBur}àÎòÅ%/P} Ì9ëþè—÷ù€ú«]úÈõÕl>µ~ûöë×ïúë¯÷p"¬›K8Æê,ÊOL ê,Ú­‡ñ &ÔÔÔÈo•Êw`Jx¯zùÁ³ÿþ'NœxðÁóóóÞ•JQPPpâĉÌÌLù¯¸âІ††Ï?ÿ¼¼¼¼¬¬¬¶¶ö¹çž …BcÇŽmhhÈËË“¯]¸páÙ³gÞ«IûÝË„üÄzV(ŽêDçBñ~Ž5jÿþý»wïÞ»wï®]»âþÚòsùµq¢~”gÆ uuu;v쨨¨¨­­•t³}4hÐ{ï½·}ûöÊÊʱcÇu^yå•Ú¾>Ðõ$Äés©ur}àÎòŸˆ{Š Ì9=Ÿ>ÏKô Ý ú¼j‰õjø¬­3Ày‘ŸDý/¼ð¦M›¼Ã²nn³7Âÿ“™;Ü'Z¯ÆC‚Ã3 À]Sy`ï¿ÿ~®ÊoªN5NóÏçL¨q œ‹ÈÏå#¢õZ.]0ž:—Û§í—$—Oi–«§#. —HøÃšs)—‘Õ¯`|DU\^&×gâþ˜OÕO¢þìììø/ŒX7·Ùfùï,w¹O<´^W9aˆOÆå®<0WLÊ?7Ž['‘_[':W8ÖÆ'NœÈòsĈZN¡©s!"—ˆê˜;h°ïŽonêQ?Q6ÎåSáê¡yóvTýGq¡{ y@õ 9§çÓÿyÜ â¼Ú>ëµ}dùŒêD}¤çSë'ª'77÷øñãÞ0 ÎÒhcu–ÎßrÒ'ZÏ=÷¨ñÊ C|2.wàÆ±¸bRþ¹qÜ:‰üÚ:ѹPœë'âfee9ÊÏå#öìÙS»ÞÁ\:#}G<9T'ê :o€/û¸|J#\=â~!ÿY¼@äÏñãÇYsî®!÷¼îq^­¸¼L–Ïè¾#?éùÔú‰êÉÏÏ_·nÇì$2scu–¨P˜ }¢õÚ *'Ì|²“»&07ŽËCùµëÔ‰â¨Nt.mœë'âš:Êâ¨~´^`.‘¾ãö©}!ê'êÑÆ¹|J#\="Žügñ XsNϧÿó¸è¼h_./“å3Qg€ùÔú©Ý·k×®UUUãÇoö À1ngYÈ}â¡õÚ¸puœ0š‡'|s׌ËCù‰õ¬:QՉ΅â,?Ì)4r.”ŸØW[?±qéLõËíÓö¥YŸýäãò)MqõPùÏå"Ì9ëþë—ðÍGDûry™\ŸQΫõS»ï¬Y³víÚ•ð§Ü›‹ãv6±RuŒÞW»>1žpŒxžâá ßÜ5x`!>W åGë¹ujãDÚs¡8×Op M å§ãˆcGäIàÒ™ê»ÃäöÑ}A>£¹Rãè\¨Î>˜7Ä}ôÏ $üáÎ9÷þè—À÷(á¼h_Ú7._í«Öà¼ô½Žß·´´tÛ¶msçÎ3îÍ%:Åê,w Lj}µëâêKþnõϾ%?I^þd ÕIœËÈyQS2U²}@JvêáîËÍÏõÙÈy[aÔojßïËgŸyä·û’º#WÉÎoeeeeeeeeeeeeeeeeeeeÕ¶dŠÏgŠ#Åå~q¹Y\ T²ù…\ž‘'©ü0®oN+®\ÿô‘E#ø|¬:¹æÀ!:­h4ºlÙ²áÇßzë­³gÏ®©©™5k–ÿ^hT¬¬ôbñùœ&ù佡õˆÅâ~Ü,¡£4q)Ph½)~až—ƪǔoN»žë×ÿ}t8ÜGt^nx~Ú{‡ò}DóÆ½¿hÞâuçwjߤ;.X°@Ö …6mÚ´víZolÔW%DЬ¬´âñùÜ&ù佡õZJ—û%q!Zn–Ðј¸(´Þ¿0OŽËcÕcÊ7‚?§]Ïõë€>ºî#:/·ÎHX®ê[,ãú€úbÄ·ýû÷»®{Ûm·-_¾ÜuÝÿøÇÞ› j×s}à?·H¬ó«Sí#á'ºwh´> {çUîóþÆb1zÞn¿ýöâââÓ§OÇb±Ý»w?õÔS‹-ŠPŒ?~ðàÁò]`¾ùæ›9sæÄb1õU'Ož\´hQ|dݺuô¬¬ÄãóIù罡õ¥‰ËýÒr³hª—•T~!‹»Ìÿt+äƒv=ÁŸ£óûôXlª¬üx{D,žqï~¡ÖÄÿœûKû¿bÅŠììì´´´ôôô{ï½·¸¸8á#Ó¾}ûV®\YRR²téÒp8\RR’’’¢¾jùòåÚ<Ä„¥¥¥[š4bÄûíÐ6®P$ùÃþðõ×_Ϙ1C¾ÁÚ¹sçÔuuuuò?222† öñÇ{Ã=|øðiÓ¦=ýôÓÓ¦M›:uê /¼ðÔSOuïÞ­BLŸ>}Þ¼yõõõµµµo¿ýv8îÝ»wuuu,Û±cGcccccãŠ+~ðƒ\wÝuõõõD=sæÌ),,|å•W|ðÁôôô¼¼¼1cÆ|ñÅ>ú¨|GÔœœœÛn»Mκz^îzäÏÝwßMäQ}@yªªª´> ßd~®j=¦|Bdgg¿þúë²§Ë–-“'EëQ‘h=í?wÎUqÏlNÔ>º®«ÍOß;5Œ«> {'×û¿¿ôü!\×1cÆ;ï¼ó§?ýiÒ¤Iª9û÷ïÿõ¯ýÒK/=ýôÓ=ôÐ7Þ˜——'„Hx•š‡>‚Ô;ï¼óÿ5éÈ‘#¨ËVmD©’Š”››«òù6nÜ(|p¶zÅÑž\×õhOò§ˆ#µfÍš·ÞzËu]Ò„¸\‡ÖÖ3`À€¢¢¢¢¢¢-[¶ÈŸHn–GcB¤¥¥9Ž3zôèãÇøá‡®ëªçõ¨N>×#n¿ýv"êÊsöìY‚»¦ú6pàÀgŸ}–ëA·j¹o’?'`öæ›oJþZÿÁ°|@ó@ûÏsUÜórçäèÑ£sçÎUûXYY©Íî]§N´óPYY)š(hñ>œ?í}GsHÏ|¡üpÛ¡Cù-ú‡]וÄ8!Äž={ÇéÔ©“ã8ê«"ô¤^{íµø‚}ÑouñÈ?ŸO®÷Ï{CëIiòÏýBܬÉÁbQ ´ëQ=D­„Ï,îZ´õôMËŸCë¹>ðŸÕGoJýsµçåÖUÌ3 IDATÉåù¡{GäÑú@ÌëþÒó/íw£ÑèâÅ‹³²²zôè1tèÐU«VÉÏêâï ‘‡8‚••F.“ÏçŸ÷†Ö Liâr¿7ËS¥‰KBëMñ Y<9Â7®¨S¾Ñü9u=×®ÿÁúèŸûˆÎË­“Åó#îʃ|@>£9áòçü(666ÊÚª««ËÊÊòòòüÿ=q++Ul>Í…rZÀ‘’ÿ”Âá~9€›¿QJ¥‰K¢¹eZ´yhðä|òøõ˜ò-DòçÔõÁ|ðï°>jid¬órëD}¤ó#Êšš‡è£ÖgÁ¿¿ÚsùQBm.þÃ$t++ž¸Ÿ49ŽÃz ZOÄìkJ¦6åž‹ÿ¾`~Pœ5\‡>ró™S÷ÑÔúó VX’•••••••••••••••••••••UÒ¥åq¹bàX¬} N›).«S<Â|8T'‹ëÆíâºðŽ3ÅADçEþpù‚‚Ù$nh_Sý2u¯“=o„Ï, ò>µûšznø—lŠ*ä>I¸yL=I|‘Dµ2.ŸO0ù^ˆÆå´i9døsÜz¸£}MqÑy‘?\¾ «/ëDûrûÅâe¸×Éž74ÿ\Lñ>Ѿ9¦BˆŽ;I¸y¸Îp;«vPh9d\>—ï…øg\N›–C€?Ç­‡Ë#Dûrùp(Îåºqùˆë†øp\ŸÑ¾¦8ˆÚó"ðY}1U'±/·_,^f€{ìyC£}MqÑy‘?\¾ ·/¦êDûè‹—ɽ×Éž7Úgÿþä}"LqL¥Ö¯_¿`ÁÏy5C²©¶ÂOn®3ÜÉW;˜ªþ¹(âŠíرÃ[Ïë’p¬Å‹9²OŸ>ååå›6m’Ë´ëE÷ËϾ_~ù¥6¿äyõ÷ŒãÒ¡}E?lþüùò ½:ý׳cÇ‚Gè_Úgí[ jãȇx®›Âãºýò¸kápXDßNþe±"žÏ‡|`ùŒö¥ýAùUÿÑy‘?(Î=w>¹u¢}ôKë¿©{ìy£}öï‘GÛw¢N4çÜç†Ö©~ýú]ýõ3gÎ$27T[a€' +Og¸“¯vPóÎL\>_¾—VxuˆC†ö¥ùaþ}àòY\:º*­X\7¢_ÿOn”ÀçC>°|€÷fŠƒˆÎ‹üáò¹}1U'½¯üŸýbñ2¹÷ú<Ìí³Lñ>‘ŒpLåK&Ož\^^¾}ûöøz|@‰“j+ ð$aå à ·³jý¾-^¼´œ9ß+€P~‚CÆåÏù—Ghj_B,®›àóÿ„Žë†|àž—ÞWU¢zÞ÷ß_ëY¾ k>Yu6+ÿýbñ2ƒÝë¤Îí³PSÜGƒÓìììøo)¡ „´'ÕVàIÂÍÃu†–_kÂ;óN˜0¡¡¡áæ›o–{Ë7Ÿµþ ßœ‹5Ÿê$öõß/ä¿©{ìy£}öïÊC÷åQ÷¥ë×ú‰üÉÍÍ=~üx¨è'¹zR¢BÖ“„xBjóp†ÕYm5ŸY{\1ù›åóà{i…öEùXZZ:lØ0ù]C†öõøa999ò§¬£G4húôÕÓ³gÏ”&.Z,ó¸h2ÿ}÷ïßOøì_„’ë–““3mÚ´.]ºH®ѯ%K–äææÊƒxÜ5Yäºåçç{\·x>\¼ЧÏh_äÝGÖ|jýAqîüpç3@„ü÷Ëq­ÿ¦îu²çíšk®!|öïê=Ïj$Âä'ò'??ݺu B‚*ÿo<ÙT{R¢BÖ“„›'€3¬Îjo®ÊGN‡Éç|¾—”ÿ}µù ™vßPsü0Ÿõ .w_Úgµçr݈~ÜD•ë†|àúŒöEþÐùYó‰üañôÅTÈOV¿è¾·ü^'{ÞhŸýûcŠ÷‰öå>7?]»v­ªª?~|‚óþ  è¤D…¬' 7OgXÕvPÿzŸOp,‚ç_”ŸàÒ±øs¬z>팧ÆY\7ÂOÄ]C\7–Ïh_SDt^ä—/Èí‹©:ѾÜ~qy™¨~TO²çæSú÷Ç,ïSýLÚÇtÖ¬Y»víR ,¨ö¤D…¬' 7Oà'ªÿÎj:(t2‡ÉçL¾Wü?ùÜW›ßÁ\:b_øaþëq˜‘?„oÎÅšOVh_n¿ÿ¨¢~m=(©y#|à)Þ'1ç>ŸZJKK·mÛ6wî\íø$€¢“¢ ?I|æ öDõßYµƒ‚úÕ%-ùÑžõÖ¾(¿©}MÕc*€<ÈîzVI}`ÕŸìüÉÞ—»þ<øÔû•ìyKv¦ÔÂóÊoÀrwdU’ì'I²Ÿ¨VVVVVVVVVVVVVVVVVVVVmK7‹ÅQ#èJF8U\¾·.ÅÊGÐMêïeÄOâ\¬óšâr}#8mÚz¸¼7Sõsï—×xþyoVV¼´t%-ýˆ %!‹S_U Õ‰ÖsëáR¬Œp¦I!.×O”ÕÃ=¯A~!Ë7t^T—÷fp>ýß/¢~S¼7¢þfuàÀ™êĉ»wï.**býžš³²:ßÒÒ•´ô#‚–„¸Y,N•÷¯* Q Ðzn=\ЕޠÀ4)Äåâú‰ò z¸ç5Å/äú†Î‹êáòÞLÍ'ŠsçÐï ÕïGÑhtÙ²eÇ¿õÖ[gÏž]SS3kÖ,ÿühÔœ•Õùâo…N*–DЕ´y¸\7DBëYõp)V¦8‚M q¹¸~jó z¸ç5È/äòµùQ=xu¦æ“àÛùŸÃ}G>£úãuçwjß;.X°@î …6mÚ´víZïõU 5geuž•ZVV¦åoI%¬ö" ´$‚®¤ÍÃâº(ízn=\Š•)Ž A“B\.®ŸÚ<¨Gç•vÚr~!ê/ÁKÓæ'úÈåÕ™OšoÇšCnßÑ=E÷EªsçÎápx̘1—^zé'Ÿ|RWWwìØ±„5²Œnݺeff®^½Úu]õU?”‡@ÍYY}úüóÏËËËËÊÊjkkŸ{î¹ù~€R'NœðÞK[1jÔ¨ýû÷ïÞ½{ïÞ½»víJøùš­ïß¿ÿ‰'|ðÁüü|ï]‚®¸âІ†mÚõÜzäûÙ$¼£yüâÞ{ï½íÛ·WVVŽ;Öq´þÊ+¯DujóÄ[:a„ššï‡16l¨««Û±cGEEEmmm½Å¿ŸDTÿó¾Ñþ'ÌÑ_T§6?ÝG­Ï¨N#óIŸ‹;‡¬¾k}&î‹ÔÝwß]]]}äȑÇWWWO:5¾Úh4zèСO?ýô¯ýkeeågŸ}–‘‘¡}U^^žš‡i+«ó¬ÁßBRiI4]IU®›¶N´ž[!.÷+GP¥Iqyu¸k¨žœ3ÿõH±øŽþ)bÍVåŸ÷fj>‰¸™åD®X±";;;---==ýÞ{ï-..Nx¬}ûö­\¹²¤¤déÒ¥áp¸¤¤$%%E}ÕòåËÕ<ÍŽtiié–&1Â~;Ô*¹Bü-¾æSiI4]IÍÃ庅Ãa-êž{îÑ®§ùyj=\Š•YŽ –ï%WÊÿNà–ù÷“΃êñ^SüB®oè¼týóÞLÍ'Š£>Òõ³ú®õ¹Y¾ bÕªUo¾ùæš5käGµø‹F_}õÕÔÔTÙŽqãÆÕ××Ë㨯R#ôH !zè¡Ç›Ô«W/û‘Ï*©JEü-$•–Ô+Ž®äº®GWò~š’ ´Þã` !ÒÒÒÇ=zôñãÇ?üðCÄçÓ®?rä«bµqãFñ÷«¢¢¢¢¢¢-[¶¸®ëQ¬£<¦æ“æÛùŸÃ}×úìQÊÔú½53fÌhhhèСC,SßÕWþ¬T~!¸gÏÇq:uêä8Žú*5ÒìH¿öÚkñ¡S[Y™âo ð5ŸJK¢éJj´>Dr°Ô:Ñzn=“b…Ö£: ~â{!nËO”ÕÃ=/ŠÓþûçÒq)bt_üóÞLÍ'gÍa€¾k}&êOöë­h4ºxñ⬬¬=z :tÕªUò³¨ø_X%òÐ#meu¾…ø[|äSiINsœ6§J*áÇû'L]Ï­G0)VÄz.GѤ·Œë'ʃêáž×¿å‘ÕÉ⽜OznY\Lî= À§¤F¥‡ÕÕÕeeeyyyþK…i+«ó,ñ·àl(ÄiSóÐë…ŽFÔ©®V—b¥®Gu¢<ÍrÈT^ËO”‡>—ÿóÒqm‹å}^µžÿ¿½3Ž­²¼þøûÞ–dŒt.ÌVp*0cB *¢?ˆ¦ÓA˜¤V̺*üctÓh–¸lØh5˜ ʃR\Yf˜›”0ˆ(ÉA­A™ ( ¹ƒÐÆ6¤…Xîûûãïïî}Î÷ÜçûðÖêx¾éáÜóœsžó<÷öÞö~¼yu—?ŸÔùRæŠÚw¥Ï(ÿŠÊôмóéþp}¤ƒ‚FAæuî·ç;èOÅñð•zs´£u©|F:ϼÖýâ¸;{ÄE}R ú~ñ½nœÈ ûéOšK>,‡/Gn%T/ËCü9¶.$´®²_âþ¢|Øø¨^$ÔO–/ñ|;ÊŸµVþH,GЃ+ÉŠÊŸåG"¡º<ø‹¢ØýÊ¥ÏTd–ˆÉÞ¨9%Ù ùÿuEâ™!NX}}ýÁƒ/\¸ÐßßßÑÑaæLá„)°.›gæÁuCñ)žÙïÿ{´®X¯Ò7Ä{Cü9¶®TŽœB”?Ú_”Õ‹êBýdù‚,×õgí£•?uî”8â¾°\@Å_™CqÎY~$;o¨?¢=GŽ)Ëï47nܱcÇ/^¬t’=Yì„S7pÅŠìg ²v]‘È!C<3‘6~üøãÇ¿õÖ[“'O~àΞ=ûòË/ …†`]"Ï̃ë†âS<3dGõ*}C¼7ÄŸcë2rä*ù#ʇêEu¡~²|A–kÈú³öÑÊŸ:wJq_X. âÖEsÎò#Ùy£ø‹9rLY~§Ñã?~âÄ óld–ˆÉ’AY´ã,AÖ®+²ù^ Ï,–8aMMMæû ̯,oÚ´éóÏ?7õÄ—”á„!X—Â3㠟噉vT/ËSøsl]Ã)Ô÷ËÞ_%*¾R¯Xê'ËTêÊ‹+IÙG1sgÇÑïñ¡ùTΘ¿ǃIÍ›Òö¾¢ö˃ßi´{÷îuëÖ)dO–Çä³70{³¡ ;/×eó½nœÈ «­­ãøÈ‘#Æ~êÔ© &˜ü'L„ué<3;Žâ``,ÏL´£z•¾‰ë"þœG]Ã)Ô÷ËÞ_%*¾ÂÛëBýdù‚¨.}(Ê>Šù{œ;;Ž~?G. rîÄüÅ8üHjÞüø‹b]Ô~yð;M7î¼óÎeË–yDf‰˜Š½Ù› MˆØy±®Há{EÏÌ(ó-JóçÏnjj2>mmmƒƒƒåÏÃ6'L„uU䙹sÝ Œå™‰öŠõÚ}SÖµùsuQœÂŠùgöWÉÇ#¾ÈÛ«o³çÐ/ˆêª8îþ¬}´ò÷;wˆÓ)îKÄsѹ³×ãxð#©yóæ/^>ÇõYÉõêÕ{÷îÍ¡vЈ©ØÙ˜½ÙôºÄ‰ÊÔUPø^6ÏLÔÎ;÷ìÙ³zõê—^zióæÍ=ôPæéÓæ„)°.…gæÎuCñ=¸q¶½b½î¸óð¨º(NaÅüE‰ùxÄëÕámâæÂÌ‹+ÉÚG+¿s‡„î– ˆÎ-=Ž»<æÍƒ¿xùS”’ÿ¢E‹ÊÔf#G$“%ƒ²þ~;.NT¦®ñ½Dnœ‘ýLûãÿø…^èîî^¿~ýÚµkûûûÓµ9a€uéœ6Šë&Æg¹qŠ]©×gþ5Í6åϱu!îšR¯’¿½¿(¿øv½h̾£9ã(v»®¼¸’¬}´òG}ÖÏGÙ– ˆÎ½.гxñbŠ‰Îš7Ô¿xùS¥Ï(ÿÆÆÆÞÞ^û¨´'ÐcÂÙ˜ºÙôÉD•©«`ø^¥R)å{™¸†gÖÜÜ\ÎCúú믗/_ÞÐÐðä“ON˜0áÔ©SéS´Í ‹¢¨£££±±Ñ,”ºtž™;× ÅŸªÕ…úÉòźôyp÷gíJž#š¿Òg–#¨Ü,PñW~/#‡âGzÌ›ñò9¦J>bþ---‡Ûå™"b*±70u³é"N”PWUU•Í÷²Ûg£¿Ê9a…Báºë®»æšk>ýôÓóçÏ—¾jœÏφuUž™ù£ø©=v晉vT/êZ7ü9¶®òÆV9p •ý÷·b>ŽñQ½¨.½Ÿî|AT—2”¿Ÿ}ów?wbå~@ç(M ê¿¹€Š¿8‡bœØ—é8oJ¨ûŠÝ¯Š÷IyþÝÝÝûöí[±b…ýë-ld–ˆÉ’AÝýÑŽ£ºôΗ×õkæ ÖOl´.›çûRï·Ð÷ ù ø£µïlœ¼Ö­ýeýó:£%eÞý{1oŽqÌÛƒ—ÖŽ<êö¼ô}Ÿð                    YˆÆÄòÕXŽË¥c9[(…—&Æ÷àr‰Ô(¶Ïl–¶ÅrÈP>l?óâ8²ó†üÙ9gç‰åɱ|¸µµÕï÷5<–ºeÓ˜<øj,¯‹åÒ!ΖQ†Þ¤äèP(>ÅåŠ0 K¬×ƒ“Gõßß­‹ê§R/KçBùSþs.ÖÅòã8fyrÏåGzœ¶ÿ.*‹¯½öÚœ9sæÍ›÷ÜsÏ µ´´°O~~K]‰²iL,_åu±\:…³Iô&…?'Ò¡”ø\®‚EBõ²œ<¶ÿûEÕÅöS©—¢s)ùSþìœ+s"Î9²³<9–çÇò#ÙóÂö?sáÜÿýâ—¤‹ÅuëÖ™˜…BaïÞ½;vìHŸPíGÙ–ŠK¥ªÞ±cG†ÆÄòÕX^Ë¥Cü­$IbÓ›þœH‡Bñ?îÁå2*o1ª—åä±ýgýÙºØ~ÖÕÕ¡z):—2o”?;çúÚsŽæßƒ'GñüX~${^Øþ§?~|mmí}÷ÝwÕUWíÙ³çÂ… gÏžÍø˜Ú¯½öÚn¸aÛ¶mI’Ø2ŒL;޲tPPFÕ·Ür˪U«êêꮻK—–J¥£G&Iò‹_übëÖ­I’üä'?I¿\îâÅ‹3gÎÌø»qxðÁï¹çžßþö·åß#°téÒŸÿüçÍÍÍ©›§¶¶v̘1K—.5Ó?uêÔW^y¥¥¥Å|U]М±þð‡QÝ|óÍO<ñÄÿøÇ¡¡¡ôì)ù?ñÄííí4ä¿dÉ’R©„â×ÕÕ‰ù <2ˆX¯’'Gé?åïQÕO¥ÞÚÚڻ®®®¦¦fÙ²eË—/_³fM©T÷W©—ògç\™C#{ÎE;Š£ÄWö‘š+¶âþzôßèÞ{ïmoo?wî\©T:|øðŸþô§ 6”O×Â… o½õVó­+_}õÕóÏ?_*•ìG}ýõ×6lÈÄ™:uª²tPPF›ÆäÁW3rçu)qlÞ•’½HoRò÷àcyp¹D±}v“þűCþT]T?•zýè\vþ”¿÷œ#9òýäÎócù‘Þç…íÿ믿¾hÑ¢ššš«¯¾ú‘Giooϼ¨:räÈ›o¾ÙÙÙ¹iÓ¦ÚÚÚÎÎΪª*ûQ[·nµãT¹uww÷\ÒܹsÃ{¡Wºb‰ÆòÕ"†×…â âo)ô&1D“B/?.W¾G•í3Gé¿»?Ëicû‰ö%ò¢sÙù³þìœ+u)snÛQ=>ÚGv®Üû óäØþuuumÙ²eûöíæY­¼QÅbqýúõÕÕÕ¦œ |óÍ7füìGe,.K?öØc¸¤)S¦„g¾+\Õ³gÏîééI’$¥19sÆðÕâ8N’dË–-)_­µµµµµÕö.Ñž+òºPœcÇŽ‰¼«“'OFQ4iÒ¤wß}7*ãlÝ{fÞEQMMMÇõõõ½½½o¿ý¶˜ÿ”2šT’$)*å{eâzp¹l)}óôˆ#öŸõgëbû™$ ª·££cûöío¼ñF’$6ËÞß$IìüYÿègÑqΕºÄ97²í)7.Ǽ…hÛ§M›&æ3a„•+W²såÞ´¿æS=¶ÿÆçé§Ÿ;vl©Tʼ'E‘ùìÐü øÙgŸ™—JqÛÊX\–~õÕWË ïˆ^éy`,_âu±\ºp¶ ˜Þ$æèP(>ÊG±ÙLsT/ÅÉcûï±_T]ýDõ²t.1ÖŸs¥.qΑÅAvžÅdÏ‹Gÿ3Þ*‹7nœ4iÒõ×_?kÖ¬®®®ô/ÅG¥÷¥ƒ‚þ#‘ÆòÕX^Ë¥Cœ­Tz“˜ŒéP(¾—+’Þ¥Dõ²œ<¶ÿ¬?U—G?Q½,KçGºû³s®Ì!Åwdyr,ÏåG²ç…í¿‹ŠÅâÅ‹MÌýû÷755yü1»ÇÒAW âªª*›ÆT ùj,¯ ʼnTœÍÙ*XNoÒóGt(1>ËåŠ0ͽÏl–¶åÁ!SòqïgÅ}q¤séüHwvΕ9çÙQÝîÎóCuùõåwÚýwQ&¦yçÓã=I¥ƒ®PÅq,¾>B/šŽëRù(ñÙuY*¥ëÊeÝ‘öWú™Ëºy)¯9Éq]6ŸQ9/AAAAAAAAAAAAAAAAAAAAAAAß ‰Üµ‘V^|5Ä‹@]ˆ?ÇrÚX®Ë]c…êEýdùm¬ØøyÙŽ ʼnDby„,÷Žå)¢|”ó"J9§ÔùBbçÊã<¢8gу'šËù9±Â@Ù uÙ̉¨*r×Re`W,G Ùóâ«!~âÉE€?ÇrÚ(®ž§Pá²û"Ö‹úÉòÛÄu•zÙøyÙÑœPœH¥.–GÈrïXž"ÊG\×c¿Øó…æ“å5²çÔv]T/ògÏ‹~ߎ7îØ±c‹/VH(5!ʲ7Ê­ËÞ`Èß¶G"wÍȆ]±5dÏ…¯a~âɉü9–ÓÆrõ<8…ÈÎî âí¡~²ü6q]¥^*~^veN(N$ËÛË‘{ÇòçO\—Ý/ö|¡9ñà5²çÔj]¥^äÏžý¾}üñÇOœ81fÌÔ„(ÈÞ`(´.{ƒ¹U£‚Ä]‹ìŠâ¨!{^|µðÃ"Ì“ùs,§åê¥kÅnœB…_Èî‹X/ê§¿ ­+ÖËÆÏËŽæ„åD¢ºøàÐÐyKÚÃÿî»ï>zôèáÇ?ÿüóC‡e>/ÌÔõ³Ÿýlxxø“O>ù׿þµÿþóçϯZµªP(ÌŸ?xx¸©©É<¶­­mpp0}ÔÌ™3wîÜùÑG9sfþüùqëþb?–.]Ú××—~Û=Š¯Ø©}Aõ*ýíJ½h”zÝãçe×çÄîsžeê2_—•a,Üu×] ,ðÈÇ}_Pž(Ÿ8Žõu÷+5:ž/4'~sEGñ¼(ý¡ÖÕçD<¿ìyQüW¯^½wïÞÌ%ãÁ{BÄI n0T‘¸.{ƒ!Ñ.LpEÛ¶mÛµkWuuuæKðþò—¿<ûì³cÆŒùÁ~ðüãßÿþ·yòGv£iÓ¦}õÕWÿûßÓ¥Yÿ5kÖœ>}º­­mÆ gÏž]¾|¹òϦþ¿þõ¯cÆŒ©ªªzå•WÌk‡B¡`ðikÖ¬Ù¼ys__ßÐÐPù÷2ÿùÏnkkëëë[»v­ùù]ñûiôÎ;ïtuue~'ÈŽ¯Ø©}Aõ¦-µû)Ú•zÑ<(õºÇÏˮωÝçŠ}ËÔ…îe®ô¹uÜ”§r¯éë:îW*ÇóDZ8'~sEGñ¼(ý¡ÖÕçD<¿ìyQü=úÌ3Ïdž#xOˆ8 Ô †*×eo0äã7Úva‚Ø•ùBãV‘£ö›ßüfDùj:?Ì®Káϱ7®¯¯Ÿ9sfÇfa›£–ñŸ4iŠ]â„577Û|/Gÿ)eü°R©”òÃ2?ž§Røs†OÖÐÐðä“ON˜0!å´uwwÏž=Û¼¡œòÏ¿¸h*‘S(ÆŸ1c†hWú)î‹ÎÛ³û©ØQ½âº‰Ê«£âçbGs‚ú¬÷Máí™ÿµy„Žù 9G}Cy¢|&Ož¬¬Kí—(¥ohN¨¹bÏ#ºOR΢½_Ôº¨^%Oö¼ ÿæææ]»veØ™îPô ±'½ÁP>hÝÞÞ^êC;"Ú£ÈzíVÀ°+Š£¦ÄÉ…¯¦ðÃĺ"ÌŸcy„WÏÈSˆìì¾(õ*|>w~›²®X¯Gü\ìhNXN$ª+&y„,÷N·»ó,õóBí{¾ÐœPsÅžGt^”ýb×ëUüÙó"úOœ8±¿¿áÂ…™—øî<&„"€²Ð×eo0G¢*¼©2Ÿ'±5dÏ‹¯†øaèd"þËic¹zÉ)Dvv_P½¨Ÿ,ÇN™±^6~.veNXN$ª‹â*ù°ûBñ,õóBí{¾Ðœ°såwíó‚ö‹]Õ‹üÙó"ú·´´:tȾ®Ý#xLK¥: ¬ËÞ`Q5’¸k©âÿ†]Å$G Ùímóã«Å€f$ÖU%ñç $§ ù+ë£#§Ù=öE¬õÙõþˆëŠõ²ñó²£9Qú,öMßG›«ÇæÃî Ê壜j¿Êâr¾Ðœ°såw#p^”þ8®«×‹Îµûyý»»»÷íÛ·bÅ ñÚq‰à1!ú ì~ƒéùˆ“IÝ`Èß¶G2ÏÒ>±ù „õg¥ÄÏ«®\Reû“cü¼ìT<úŸK>¬òšç¼äÑç£ä™×º#=Wåþæƒ÷‡ë™Pþñ¿ óŽôýËÉS8v"í ÙY®KiBòà®Q´*6>ŠÃR¬Xz–B碸tyQ»X¾šÇ¾ˆü9eÎsÉ“¥¦9ÑÈ”×Üz軲 ú_“H9byZˆö„ìɵBþ,çÅAþ(Š¥ð·Ø|¸µµ•úý‹Š#4")G,O ÑžåZ±”&#›Ë…â ”E‡RèYlž,ÅŠ­ ѳP½,—Žå¢zY¾ÛÄŸC뢺Ø,*Âô,6OŠbÅÖ…öÕËré<¸ƒb½,_íOøsʺb]lž,5¦‘‘ÇTãǯ­­½ï¾û®ºêª={ö\¸páìÙ³ÑËä|íµ×Þpà ۶mK’Ä~T©TÊXô‘ qe¨KO 1/Ý0#ܹVœ9‘Ë¥ÄQ¸€ˆ>e¯ËrÝ<òd)Vl]:?,S¯—­‹òëeùj~ý‰¬oçRÖëbód©i¬€9yçö׿þõÀÀÀ©S§Nž<900ð»ßý®ü_‹Åâ—_~ùÞ{ï}ðÁgΜùøã¯¹æñQMMMbýˆ„ QM›6míÚµ›7o6/¸<øüóÏßvÛmS§Nݽ{·9!;wîܳgÏêÕ«_zé¥Í›7‹o}¸ëÃ?œ5kÖí·ßÞÖÖöÔSOÝtÓM&ZOOOOOOuuõ/ùËt ä/æÿâ‹/îÛ·ïoû›ýúQŒ£ø£|Äuõ<—,Yb@bi6Ï_ýêW?úÑÌ«õºººŠýaë÷]¯×–>'âº(O¥^QJþlX)sBå)ŠÝwdgûcþéõ×__´hQMMÍÕW_ýÈ#´··g¾7ëÈ‘#o¾ùfggç¦M›jkk;;;«ªªìGmݺUŒ£·®»»»ç’æÎžƒò‘H]2_gþ»"O ÑžåZ±”&Äå)M?ü°Î´óA}c¹nlž,ÅÊ£.´ïb½,—Î<Ê^õÕ«¬+æïןÈú™OYW¬‹Í“¥¦Q42…“§Ï­QWW×–-[¶oßnžÕÊ/b±¸~ýúêêj|Á‚ß|óy¸ý(1:bF=öØ.iÊ”)á™/(UÊQccc9«££cûöío¼ñF’$6O+Žã$I¶lÙb8X)ìÝwßÊhOæ[Amûàà âZ­\¹²µµµ§§'I’”êtìØ±Š”¦òüS.WE555q×××÷öö¾ýöÛh]ÑÿôéÓ+V¬°ó9s挸.ËucóœRÆuK’$¥X½ÿþûyÕ…ö]¬í;š“éÓ§·¶¶Úë¦ÜÁLž§NëMéböº›6m²óW8j¨ÿ
ÞiÓ¦‰u±y"ÿ††jßuNž{Êkú駇‡‡ÇŽ[*•ìoû5Ÿ›à>ûì3óÒ'ŽcûQ  sÄŒ^}õÕò…§€AùH¤Q<­О=â¹V¥© rþì8È_χ¢CE=‹Ís I±ò¨KáüÙõ*ûKñQž¨^e]ŠS¨ôß(ó3ZÕÅæ‰üÙ}Wì,Ç1#ñç­b±¸qãÆI“&]ýõ³fÍêêê24×ÔÙ~TjQF1(hd•H”#–§…xWÈÎr­XJSZ]æ×îšèòaéP gQyÆ<ÅŠ­ í;ª—âÒ)ëŠy*õ²|5¶?F6­‹êbód©iìòú£¨X,^¼xÑÌÆÀÀÀþýû›ššÜÿž¯âH„âÌ_Ïd¸wO Ñžl{Dr­?ËùCq?Êǃe>ɰW¤òŒIŠ[ÚwÎeï¯>'ÜÁXâê)t1GN¡ÒÿHâÏéë¢~ºçYÑß}ßõùaû£(3æO÷‡W‰  o[æõ¦hGþ¬Å§ì¬Ø8#íÏÆÉ«?9ÆaíyåÉúçµ/ìº#í?¢öoA£¸tPPPPPPPPPPPPPPÐÿ–þ#hÖ×?ˆ„1tIMEÜ  4óæ+/IEND®B`‚jas-2.5/images/edu_jas_ring_classes-full.gif0000644000175000017500000003315007773340004021413 0ustar giovannigiovanniGIF89aÔSñïïïÿÿÿ„„„!ù,ÔSþ„©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡Ä¢ñˆL*—̦ó J§ÔªõŠÍj·Ü®÷ ‹Çä²ùŒN«×ì¶û ËçôºýŽÏë÷ü¾ÿ(8HXhxˆ˜¨¸ÈØèø)9IYiy‰™©¹ÉÙéù *:JZjzŠšªºÊÚêú +;K[k{‹›«»ËÛëû ,N^n~Žž®¾ÎÞîþ/?O_oŸ¯¿Ïßïÿ0 À <ˆ0¡Â… :|1¢Ä‰+Z¼ˆ1£Æþ;zü2¤È‘$Kš<‰2¥Ê•,[º|‰0€Ì™4kÚ¼‰3§Î<{úü 4¨Ð¡DD)Š4©Ò¥L›:} 5ªT›x¦Z½Š5ëSxý 6¬Ø±dËš=‹6­ÚµlÛº}û6À(]áÚ½‹7¯Þ½|ûúý x­Ü;u>Œ8ñßÁ2 +~ 9²ä³Œ8žŒ9³æÍœ;­Lç²çѤ9ƒ~!º´êÕ™O/IÍ:¶ìÙ´ϵ»¶îÝ”oÇÈÍ;¸p²®•Ž<¹òÉÅá_}tóÏ£[/=ýHõëÜ»{›½Íöïä‡G1Þ:Mâbë¦/ïõ<‘÷ð%Ï,3~þú×þå«¡/Ý~iÝ'mÕÄ_¾Á r…m\ƒËù'„„ æ{Ÿ…•á….8‡…›uØX—‘x `Î ¢p(`†]‘˜ŸRD‹úÕ!>–X ~ŽÅ¨ãŽ}áxF‘ÌÅ'd“ArÈ$ŒC>8$‡SJé ˆ.(©Û‹>¹_&Ÿ–Æ‘)]”_zi¢€kŽù$š¦™é\r(‚ùe›¢¡H#œ|®Ø˜‘ë9Ùgœlîˆä\Ê —?ª)¦“†ÚÈ(f‰–±(dކ™g¤XBjà”1æ‰Ü¥ d:Û‰QZeœˆÒ‰ª•ªèe¡xÞÚª¬³²eêº"6㛆 ëé­pªéþ' ¿ %®Â®Šf¯;üº«Y‘þ鬱ÚVˬnPkصȊ«í®¦fnpÒv.víÝǪ~ÇÞè­írÛ,˜êæzýº‰¯bë‚qïbkîûé¦5ŠJj­–Z/zOlmÄóQŒqƼZüŸÆø¼AÁ»Èq…#ŸŒ²‚„¥\)ȈÌ2m.ÛsÌ6§Z25ß<'‹<ï:s ;ÿLtgAo1tÑöå…ŸñžþÐVˆA€AñˆHl–¿ˆÅ-NñJBlâªÊG,4B+ŠaÜÉø@3†ïYæëùÚÈÅ1¶Ér# eE¤•1ƒŸÂS­’ˆDljŠŒ\ä¶æÄN:8ºÀ3®bK“\á9U.bñ“£Ä¤åU£5씟LW_W+RæqXbtål5Ä<šñZ»¬c˧²)—ì%®Œ)ÌNªR•[Üá y™Á[*ó@¼*•ØÊGò“ó2b$ÉåÊ‚³>•d˜žH%>ñê‰òK;7éÉXf똠4åõÆéÈ|^°b°Lc:% JyÖï_4*"´ð™ÅzÊr æüg¶þˆ‰Ðu.ÓçœT@ºÐŒæ“ÕÌBBñ™°gEȃÅ {"zÃŽR ’Vbá¡æ™îi‘•ñ©FçÙÉ=•ô¦û„'õTÊ ,êҔ”-‡åSQ2¥ ½)”Ú0q1u§Tt£R³'Uª¢T/•Œ•V¿ºÌ‘"õ¡NÅäVÉSΊºïP/í©ZÁUY†©Yœ¨X•:U¹ºUsý¤ëDí*T*‚4™cÍ«IÉJT½Ò”¤†•«†êzOÆ‚•›€œ]c;×ÇJ±áäbSÔÈÙóX Õ¾ÆÀõù+°ý²*ÏõΗ&¯ŦQÝGG¾>ÁÌ„­lgDÒ ‰“h”'!1þ»Ú9vQ¸R"î0E U‹K§Ì½­‹ ]¼®› -êô ¯Þ6×·¯5§x ºAf äôîíž§§uõTšÙ¸ThŸòLxuàc¾¸_è¹÷ž˜|LæþmÁ n°ƒƒÂUEÁ~°~%Ì€o¾kƒ¯‡»;»{&­"Ž ‡= á{ìÄSqÏŠçbÓaXb1®1qfì?[ Ç Ô±txlA ™¿¡ò×€|€ûŽÅP²‘[†ä3=Y`Q¶ä”[Se®]9ÆL6Ù–1Te'Ó®Ë/û²ŠÉ 1{ŽÄÿ£Ì$Ç;Zþ50.TO–é[Hòæ9Ï´Ö›«WþgöÅY}k¡«Jç8Ÿo’!LÌ{„f©•êÍ=ÜÞ¡­…!R“uÚ›æ_ã©hó :Ñ܉ôÜJØë檪Gõä E}½¶O¶£ÞË£y•Ú@«7Ô˜ŽËí¥)⫞žóþtÕhŽ2lÁm¢ÛzF?ÒµzÄí3ŸÛ>WÝ1µjJÝtaÚÊ=myi [>’·„m÷éZËFn;šØî  »ÜIíÑ´VM6Ÿá(Å >è×EСg¹Ío»ÔµôÜãk±z%ƒr;ŽÛfkE§;Ë"†™ª8µx—:ÔT3š¾Ü–9ëoWÜïú-¾cZòç¦÷™Ùyªáêñþ¤B”–;§·6‰-XNE³~]·ö.»J÷¼Åºæ“&Y¾ëœÛªÐ¬ü8N§]T’›|\ÖþæB7ŽrǾõ´5äd%ºõ1ÕÎ}…©Økô†n7£—ExÕÛIu‡f5ìT(œÕ»j]"l蜬i¯µô!˜7ßÒÍûÜáJh…z“Å îpI Ó‹†æ“G(ØûébZ¬u/k‰Ö•¯”µÚÅß³çWtrϼô?Ïá r¾—µðÝg\7KëȆ½õª×KÞû˜»º¥Ì§6ªj®‡ÅšöGþ×A·A¨ËÚíÂýÙÓîÚϦ>ñ!û8dO>VÜOûº~èAßýèþ"}šU2®“}û^ç•øäÏÑ[ ©mWµ'Z„>MuVÑ÷jP‡z‰Åzõy­%s÷vHš‡|Ï¥o<^ÔÕMÃDi¼Q|¢ÅgG€Ò\èg]ˆyÕzãUo@·y…]Ì$s‡^¿Ôl3¥V•—[Gó–H6W&!–€]—ƒd'n½ö‚z¦0rÄx#\èÕs!Euç%Q‡}ʶ$cÖ fm.#âh\%([(if&†&òyXø5KF†§Fa‡q(‡s7Bh†–Ö`w‡ŽÖ†ß¶‡ö–ó‡iÃiƒh}¸r†¸ £  £Dºcþè IФKšaNZ4FJ£S:ŒZ ‹Vú“TÚ úœº“kÞ蘒9XšdàÃnæÆ’—é˜é!§vh ”Sèg°'CQGI`Z¢Äjr&޾˜†øaŽ=ÈwJ5jšCTOì9’dÚi˜_dÝÈþ#µÖjéW¦{Zj~z¤è˜kX©ž˜†·n*Èso‰§ÿ"ISÈ] ª €âT,}¢ž=yM:5qî&m«¤‘çsÊõsþ¤OçöF*É”ÄÚ¤Aˆ2ù«Ñ–mÕÅÍz<蚘©“ÆÕ—`•t?èV6‘¸ºŸj©wIÜ*u 6sYsÄtUV •¹7’éyMM™r³º%e‰KÄé{¢¹f…Ú«ývyei˜¡Y=äi3á nO´CÑz‚Ç ØrrY°{‡t +úTvΔ±~ÇvÏš—'vEé~²(°aUJÖ©®ÛGš%›2 Ëz²‡-͉N÷ˆ i©ë‡±ÃÙq&››Šþ‰°0Û§B(M 8“K ˜‰ƒ˜·º²âižÝz²Ç‰22ëSoYZ‰éR8¯Å){$;´Ë›Â¶”¥,E6­HKíW:MKƒ—ŠÕi=Xyÿ´šcµÍˆnºI©°zŒú²œOå‘Ñæ\øxÈ•€w0ìéƒpÙ•,Z–e^½êª&¬8—¦( ¤Vk)6¤¨ƒV «¯-Ð"Ö0R*£2[¡«ËºZÑm£Ë;‚jˆ¨ë¢œë¥¢ ¥ J»)j»·Ë2áš`\ú§VÚ»¾[µ°¼©«¹JʉÆ{2À›<̦Âۦ뼽)`½Y³»&Z¼×«1ÙKcÊ»¥äÛ¥à;2â{þÛ»¨H‚ï–w˜¨â(!wÉh˜š©¸öŠ9¦·êÉn7©:""Òç¤êk‚€ªpøû»)«šË7±¥úC²‹¦Å¶“ZÁ¹ØW+oC%©ú‡¦üÁ¼‹¼Ñ›;¨8‹Â¾ÿU¨?k¶¿ypÍé±25tƒú¹0×ÁÏH·è·V‹]YH™«“.è|zdnF¼gbZÂÚ[Ÿ?,·B[¬ðÆ^EÚÂÎE-;JŒ™BðJ›rI™™eGk¶ß¤“I|èú¯Ã¦HûèMª"F™E–•¶!‰Q§uÕLD‹»[)œ/Ü™.,µȸ%×[zÇ·Á·Æôdw`» kqëIþYÈÈî)Æ{ÉÁhÀAV˜Rè}'~P;Ê7Óš=%È:[²Áƒöø{‰üÊžY}l[R‘<³7Ûµ›ª«›œ³² šüJ½!òÀ:—Çôº´J{°1ëÀ㺛ƒL\…¬¸‚Õ·äŠÈ² ´ÌY¶|µ*›ËçŠË¼<¯ýúÍÁ,<ë¨ìGµI °_Š}ÐXiÎH©Ÿ¹{çܱÇ8u–p‡ëÅlz¹õ™žÚÜ¿ 9]òK”Ùx|¬«I<——wÐ+|¥O<¾”K”rê:CýœÀÊ\¾ÐcŽùAcؼ-Ô%苆¹  Ý;búÉÍ·Òí5:­k¡Þ Ñë+½Ã[ÀÚLÒ+6Ó\Ó þÓ?m›8Óx»Óžl¾20I­ÔKÍÔMíÔO ÕQ-ÕSMÕS-UÕY­Õ[ÍÕNÒCý1EMÍãSÝBú-=} bÎ dŽæÂ(=nÞp®Ñš@çª`çq¾l–çÅæ–ð稰ç|žÆ DØmÝæQnèŒã"Pþèéûä9Âè-“Þdnוné -²Š.èÔ­Øý¿õçØ =Á©ÞÑ`Žéå÷C𫆠üÚÏÛê9Zà¡­µ‘JÚÛ‡="¼ë¬nǬâ)ÛàZë=0è§P«{[œqDnÑi—@+Ê l[¸uêšøèZvÜ9loÒ ­i{¨ÊÎxÎá gÈ6¥àšL¦q µ$ùØ}ìW§Z2â|¬Îf{çZ^îÞgB¬±¸ŒoH8u?RÝ«~‰ÙŽgð™W­ønÌ?›ån½ïf‡È â»Ü©½l}Š”Ì~ì0áÄLt¢Ýë/nÊ?-·ÆØœîó:k`›~ ~Ò(Êͨµ.þ~²'oæ¹àÔ|ãí·ýp±JÀºÞï4XôQJó‰ˆvîÌFo[„KNŸ×NÔ= òu<׋ðVØ“ì¦Ðå^ž73Ï×ÞÝô–ÃéN/g‹]ågÎö—îöÀNîr?÷žN× ¾éxŸ÷mÿéµ›ö¸öÿ_Çwïó†ÿ*u‹pOé~Ïø.ø2õ·ðó?ÈØ âr|ê,ìšm¦²Nú'ìäŽÿ·4tl°ÞÒü¸½Ÿf*oÝÃ.ëÁ$Ç›­©ÖSº©^±ŠÙó{øt !<˺ïÊñ¥ÂÁ/ñrÿß݂ǒú<Îeôìú&y8Y^x™ ÊÝž¬G<ÇËíèþƒ/ZÛþ ÙoïÙžáÆÏ2YÍÏ-î¯{ù¶°ìs|’^$Ï{EÍnüîÖ¿ýùOò1,TÅ’§QÇd]‘î>ÁPÉÒ<—XÙÖ}áXžéÚ¾çëÓ?Îç0 8a@vB 'Ñ(é”J ¨pYí–Ûõ~Wð˜\6ŸÑÞòlCùž¨Lä%Ï6*}ôæÞœîâšæEß6Ö{ª(+-›°Ò47»ÖŽ ÝúöéJ-@G™¡ .acA®8kmomÄpwy{Ï<å%Ù\‰Y‡ •"•^£’ü>#÷e½¿g3}ÇÑ 3²QÓ¡‹©Ý[Õ»þÁç¥hÉïñ·tóùû{_ÛE‹wl  Gëä5x.]”€ÓBdŽ"3gô0Ʋçã s jgÚC„;ŒL˜‘¥qaÞÛ“fM}¦@jÈG”›BÍòx:äS'NdØøäløÈŸ¤GENã&äદx˜µÔ:e£M›ªž.ûI ƒÐm<É6 káC:=úl•›à¥W»šfÞÕ«×½¾sÝj<Ø aÃëîí÷÷pcÇKtU<ùK^Ê—ý©ý´™sgÏŸA‡=štiÓ§Q§V½äÁ’1Ët=›vmرqçȽ[vmß¿§}›7.ÆÂ‘'¯B¼8oËÍ¡§9®œzþuë×SDÿÇš{wïßÁ‡ŸX;îçåÑ{™Ž}{÷™§?3€~}û÷ñç׿Ÿÿÿ PÀ ,@ùœCPÁNÞkÐÁ‹oÁ )¬ÐÂ[λÐÂõ ìÐÃ##OÃI,ÑÄ2AlÑE%TQÆi„.Åm|QÇ]ŒÇ 2¦…4Ϩ!z" -Á$Š£µÈ²2Å8œ²0K¦âK‹ìÒË/13Çj:ÉÊDšLiF tëÌY°\‰ª8¯ÔRJ.ÅÌSÏ=q ’O¯Ø)S*$CQ3.¡JJI”À aÊ(ž(4¶BŠÀ)¨ÎqÒR¦4…K3;ïüSÔQIþuÁÏR; ” Mwj„!ŸR ’„¦ÊÒS¬üˆÎ6È,¬Q^çœõ7uôÕc‘UñÔdóQõP«bÕãŽG uŪ¿²f³$ýèÕ¨¨tg-V³]TL˜MW]—]×g“y¦ yW]*W‹@‚ ÜDÚ +Z%Vj=7DwNxÂvÆ\iæ6b~ßÁ·âmÑ‘˜VAÃÝ·¢I.28<.Ùä½>¯#Éìk”$í(+æ'&•Ä EgÆõaež]ØJ±ÆVVš©·Ì™’UnÚéÅžî­%be¡M¥­Vz䨹îj¯yÑL¼±É.Ûì³ÍÖzk°ÙnÛ–”þݾIí¹é&ÌØ¸ñÎ[7½W®Ûï¿3º›ïÁõ†›ðO\qÄoÜq ÜÔÅ)¯¼¦%ÏüéÈ5WÃòÏA§ÙÎI¯‘sͳ]u;ÇëôÒaßíuÉS_Ýö[ß„Øyß°÷>Y÷Ðo!‰«N”ê¹dèÛÏ͓ݽÙÿÓ°ŒŽ—Í+«D¾ÍŽ™/ó°¥/ßFóÇxPOqgÙ‚¶H7ýÔæ‰ì¿Çñæýÿÿ@À«U†ÒÍvų¤eŠR°¢_Á¨?9Ï8þàñ‚Á0Z°Ö)Ú’ m¹ «Ø†¾$Ø#´­…-tá aÃï8Í‚‡þã`1¦¶ šm›;£Ër Šñ´.¿»Æ*w»Û…â7ÿ\q÷·b­\u÷\袗š· ^ÅQ±¾ñ*fÄͤõp­‹ïË.¢¤9Ž•hi‘–a‰RY»T’Á vðƒ]È^rº÷‡éäróø¹èÊM½aܰ²Ü a˜Äcc„ËÑa1~øDÓ†U\W74ÆJd±‰\¼¹ï˜Ç=ö± gl×FARŽ-{-™ÉýQr“¡e)èÉS¶ò•± $ç‚ÈI¼q‰þ¶\²MžÏ  3 †Üå}yaœtsôÆ3cfΪ3ŠÜ#_㉖b­•@JTåú„¾0ŸÙÜæ šÊ†¹s9iæmÊå½4ïP“7B¥úK¨|F)_›OHYºŒ^ôsñhéD:aªæ#W‚¸_Cs9Œm&|%kÝ KŽei¬Zúg®–Ägè”;¡©–Ãnt¤.5äNê¸zÕenõ¤'Ê3ˆé5‚|-®®²ÚC-Fiy¿]Þ³ëØXGÔZ¼ÊîœÍ®h«á‰ÓöµFm0î•Ùž:­>ÎÏ—á“ßrÆg¿4y?™ô“cþ ^ÿûç~ü·?þÞþº¾+v ïÐZ%á¼uOÿör`ï+þO]ð{@h¿¶G5m+Æ/ü€‡¶ö¬Û<¬ÿP&ÓeŸåQ¤á$ˆ ŒííâhQ|ízвº@PÆÌ™%j³ò…Ó”BXÖÍRRî-ŒxЈ6D¾* –°ÈrÐãpÒP+hðb × ÎæÂ«™$¯Ãj­hKÕO % —¡¹k±`êêvmé°ÈÂpÅÜ®êB0 ŸOøP¦$ÁÒ• ¯JªÒQ@}+¨²’.ZÒžfm*询2qrjnéå²W…€KMj/¯,ýrRýŽÜÒêÀÚò–ÞòZKÖÔÈ?]%R†K»*­„ γȰÀ^Ð}šnØH’\~£X0;&ò1 ó=‘´H!4iÎìHˆØŠQ€òªÐD¾Ô×”­ÝŽðð7‡*)Ø)¥5©Q5W³=jð2Çð¤4óþ'®*Ÿdïº ,GB~ú [ îÀTB ³RÚ ƒóaŒ“•2’ro9;r*áÈË+W¤~­)ëÅbúêÜfî ™. QQ6ÿÎ4,=E¥ñö1ATAqÒ9{mE¿º+ f’Cs~<ŠB!´)—núŠŠÚîßÈ-ô^þ¥/Os§ð©Êü>©.-¬ÂŠêD”#ºq²ô8ãñI¡ôõÎ$ÍÎ)ò޳Ϯ43J”I“ÒK-Š=;dG9ÓIÙô®ôNñôÇÎþôöJ‘»´NƒÄEuP µP³ìDYô/ ô%ãP£fON+²µR_Lö6'Mû”'-µSUæ÷JSe‘N=µT…ïò UR}’TMµUSUóJTòO]µV'•Þp³dõ#iÕV}•Õº.UÕ4YõWÕ%suK)CYßæ,×ôX¡Õ,3Žç2UU—’R£5[ƒd&¸UW­U={U[ŵ÷¨5WihW‘ÕÇu]¿nÞÌÕ²ÐUZÕ]é•B,ã^_,^•ûêµ_Û5T¿õ@±Õ_ öÞvX²X vaÓƒYéL_—T]vb6R65–b5Vv,vSÓ0c76d/ÃaþGbu^E6eå¯cGÕ9UeavYYvVýTbcöfA^Öd3g}e«õb“3g¶héofyµf_Öh™–_ñ‰gh›vjkdevg±©vkµö`=–X–kÅÒž6k¿=Ç6mU¯l…vNÃVmá6—Øöl1ömãönûiÓµIíoývo¼¶e•öYÿ¶póvn—omÖpW¬veÍ6q ·q)÷Í—fwi+wsËÕ[ÛöVû–sñöqý/r1wrE—rIwM7i57uwuÏðsW5taWmew`%l÷v 7w¥6j]u}÷o×vqäx“y‹wþk•÷u]÷c™·y§öy‰wo¥·w©7n­—Kévh§w{¶{Ñ–v¯5xÅ·zõV^×{Ó—{×w_Ï7|ßgÉ·Q¿×mµ·~¹ö~±jkOwùwlýM[{Ýw€Å¶€ùtw–~8eØiÍ\÷7‚™v‚Gç€Ùz1¸i5ý8yøƒA8~#6s¯×„‹6„eb„m }YX‚QødÛ·|gø„÷ty׃sØ~kx[5Øg]øh9X~E¸ˆ38ˆ…÷†ñ—‰Ø‰˜QÿWŠ[˜ŠIØŠ ‹§x‡£·‡WØ‹CöˆM†i¤ñÈø‹/7Œø‚טb͸kótáþ8ŽvŽ—·Žk÷Žñ¸`õØ+X`eøé5µŸ ‚ 9[Ù8Ùùü¸‘ëõ‘Ã$‰SxŒ)Ù_-¹Y1Ù†}x“9Y‹cxx‰X” ¶“«6’/_M ‰Ýõ]Qy]UymÙuóbËrù•gùI9{x—7xZ;·—ŵ–7Ïç×\Ϭ[‰Ù˜iù—¹n™¹‹«š}Œt÷¡Îºù™±ù˜¥Y’ëö›¯8YÃ9›Ûx›o5XÑÖÓ9šƒœõ™sÞ\íòì9žÉùSyY–…øTj`•ŸÅ9_Ý5÷Y—053Ú u¡%kÞY¢§Mß@¢¡©µ¢‡‡þ5Ú‘c•ç9„óô¤a(¤ødÌy ºöPNUú”ýW-Ù¤czOgÚš© Ÿo¹B2ò•tz§)XW Z™[,§‰Z‰Íì¡A9•z©ŸúRU§SñI¨ ¨—h¨¥–…•GD«µ2pĉ«C¥Ñ:­_è…ï*ÏøŽ¯”  jæyÍ:dz©ÅÚM÷¬ÚŽ8S®%¯E§«R¯Ò«MÇ­·(iôé’㮉š°›Ÿöx±™3+bS±*4²ÍZ£)»²—F±¡:³® Ñ)=Û°[´«ãÃú: ˆ‹FCoµY&ÁtÓŒ ¶·5ªsKõç C»=é³#Rþ²wº¸™j05s¦Ž/»´“û³!š¹]<ÛÐ15Œ¯ÃZ—€;¸c¸“D(kÏ8¬S)¼Å»Y†[{ Î.UÇ·Áì<°­Û ï›¹`3¢¦Î+л[ì^ÕºÀÇ&¿ùy¿ã‹®2Ïj¸œ\‘¨ºÛ;3\Û®#¼ôöÂ+œû.üµ3œ]½;ÜD?< \AI¼ÄÿáÄ•ƒ¾ÓxÄ9R¹gZÁÙÆ5<§fÁãÙÆ—ÇëûÕ0 «¥´j’IB…Åe"Å™¼ÉW#Ä¿›“æ#)M1œ¬ÇÓÙÇWÈ[Ù¾kM»…§TJ×Úê3yô¿îÖDr3#¢Jó´þ<œ¹ü0½Ü^×;F ÆHcS¾ñ°z­t3ܼ­Ý¢Hòˆóæ›ë¼-ï|AˆdGûÍ;çà®+ Œ¶M‹^4Å).\k<ÍSÉ¥ÆÅƒãÑ•>ËÔèøòNÎ6KR»±›e23tÔIÝÄM]8P=©ù-¾J²ÕÓ5›CôHiû>4@›-×u}×£×qlí|G®³@PB5Ý sM!ª/ãÜ$7TI=l¨’·‹ª}¨+ó–ˆ}.ƒÈ®§¤ÌV¼ÜçªÊpžÈ”X Ð’Ý»í¶Ò \ºîßûÖÄ|®É¼ÏœÛ:¾›JÁáÞšâÑ|Ìgªáþij2…­Ø?Ê ‡ôZž]^áSLÏ¢¿U y´ïFÝÇ ÐÝMБÐñ? 3¤`¾^¡äS}ÇQž†=ï@½Ò¡ÓA³0íÀí±“]°n·²‡êä=>ç½áΪF‹@§á…~èßFÕé3Ø9ÆÕßš7™}h´¾BÕÞØH,Äkæ žÙKÑIÛë9ìó}:Þé¼åÒ•Žåãºíw%µÛCKë.ãî…èçïÞä¿^ïÓKå›n£l;êÀ'¦`0Ù: ¨Ès¶7›ÛSëbî°2G—½¾8Ƚë%?ï)_:r—6°Þµïäg_¶Òö‡è}=î} À;­þÑ™kÑ¡Ùø÷ÚߑðÕ÷¿wá¡Ý7˜_C2ê}lØ€,òpúS¾ú­ø§ñÁ‹„ÔÂÁ?üÅÿ÷#?è«° ¬ØÒËߘ•(¯¿•{‹¸TÛ? @‘á!·?ŒrÒj/6ðî?Š#Yš'šª+Ûº/Ë3-/žë;ßû?0(|6µTà¨\ªN…㙘ޠSÉAªµ»Þ¯†)“Ëæ3:­vUÁî7<.ŸãŠkNò®_9U¿” Ã`QÃáU!ã£Ýžä$e¥å¥dÛ…fNç#h¨è\äZæåçè*«c)*l¬ì,m¦Îbjë.ooÄkÚií®þ¯ñqÑð2s³ó³ÇS–Õ45¢!¶`¶`1²÷w0š04Y78ú·x9{»û»RŸµöv}`ºþ~׺9¼çø\å/ „ Â7ÏžC*'RL¦àÂ+r„s0#È"Q5œW¢É‡W®ü8ãH$,gBRó&Μãi“è¥Ï“4‡òs)¦Î‰2íd3)Ô¨RùpIpWÕª‹n4jêÕ›Q&H§vXúõ,–§dײj-ܸa—Œ]û6®\µm÷òy/`¢sãõýðIèÏD><~3¸0äÈËþ6®Ìñ±@É«L…ò/Ë_0k.mz ÔªW³nþíú5ìØ²gÓ®mû6îܺwßÖûOs®q~Ek¶­†°ŠBú4ôègP¯ný:öìÚ·sïîý;øðâÇ“/oþ<úð_‹è>ë5«)7wî[:þüú÷ó'Q—lqïE|ˆZ}DÜ׃ :ø ]ì5bù@P€ Ú!‡zøaFÿ¹E!‰ôY˜Èæ² ˆ-ºø"ŒÄHÈ †„àrŠ)¢ˆqܨ¸aŒA 9$‘4ˆ(‚?Nô\‘M:ùd‡GF•¤’1 %–Yjiš”PQYå>Wn9&™ez9#˜p‰i&›mº O—I}™&:k¾y'žyƧNsÒ©‹þz :(¡© ù§Wvº(£jt(¢L)ê(¥•Z ¤‘5é¥z:(Ÿ9½Å};.Ÿ¦¿ú)«­6*NõØý¤:§®êºë“°Þ$M­>2rcŽý‘\]ݪ ¯Í:+¨¯1Éф՞hª|Ö.«ê³Ýzkf´~•h>–jà¸Û^¸ê·íº b¸"¥˜®©ÅÔ¨­ºQ°û.¿ýöoHóâKª½¸m®þ*¼0€6tì°§ã6=Eœ¯¾ k¼q~ƒä'Æ£$Ì1É%3”iÈl2Ë-;ãqˆ)·´¯Ë5ÛìÌ ,sM7ûü³B9Íóe4}4Ò†J¶3þѤ4ÔQ«!tBL7ÎÓRk½5](_ ÎÊ\‹=¶T3ôµÊY“½6Û%˜еö\HÁ9fY}VØmë-õÛpÚܸvc7Æyï}øÑ}¿¬¸ÛørTø™äÁù=*Ž8ç6+Ž3ä×["­íÑká´nÞ9ë&ÞÎUÊÑËÈß§SÓ•¹w‡©vë½#ý:;|bŠÍ+ºg–­î;óþ_ŽðW+÷ñ¦'_ÙòÍkßîóÐÄ>ˆìã^9ªÂB^ìŃ_;^Ùoÿ¾³Ý?c·îhÓÍ;üù3,ÿËö…¿þÈ/þ5£~þ‚û¨ÀJ< (Áýþ „Å!¸N°ƒ—"ù’A ò lŸÃ™âFO{*´¢9è%9 ‚ú“¢ýh0:¾ÇQ Äè!À Ò•¾D¤´ÝôÉQ}z”¥6 <59‰<.+CiMo*T<¸ôv£¬†øzª¬u¨7Í)J;ªR§R•—Q½*šZUB«äÔêV-ÚU¯^¬aUèXÉM³ž5 iUk3ÙÚV|z³®v½+^óª×»Nu®~- \‹À¾þÕ¯oþ¬/åZØe±8Tìb[ÙXÇ’²‘õäd) AË^V’™Õ,';+Z|ö—ª,Ÿ«XÏÓª6µ”ãÌL­X·¥ÆÖµå; má#Q„޶·!%Åv›I `…pÃeŸiw.~Öá`ÉR®cPË“z⊄õ­PïB¬3 k|=h(æ~²áä#8™CžÅºk#ôÝ+>HENèŠ>“ÜH©d¤Ý{•>-Ì×3ä•Ý4š»ëbצœ80*5Ýkéâå½]ÅÊ8ô¿ÓEÕƒ­g< “×ÿµVÚ«`åBìŒB! ¼RÉyb¾ ã‹Ã+c‡ªOz©/éˆ0^’jôÆ'Õþñi:«@*Ë\&u…ÓÇÄ}ÂxÁÛ@±Š£\61šÇȲ媌Ô+«„‰%&è–­wb Cº_Ö0ºÉål%y§ÃWbJ)Ó°36ŸÅ\Ð¥æv§ÒÈp„+ü7?GÐ8n-™“³áÀQkÍ/m³O§hñÂÊu®3‚uÔS<ÙȈ~²úd¼å&‡úáK¢yK=Æ—rÄ‘ÃЙqçÞÓêÔ“&åôn\ÒRéÚÉéÝrŠ/íV™•¶¶%DîhÂ!Í` ›®Ä®S²‘m+삳͎a±A{5k_û„ÙÖ6ѸÝí~ÜÄfö¸kîuÿ3ݾ-7»ó%nw+ÞñFþºéÙ{ß{ÞúÖŸvûùi~«Ëßÿ†Ÿv¯Hðpçûà†ÖÈ•h*¤ÒÞ ?†Á®=C˜Ž ÞÅåÝp·QÎ GÑ&C^ð‘“œ‹&ÏñÜ©òee¼å½+ ¯§I;Îß6ÿëƒc÷fâU¼ç"ÿ¹aNÙš#sWú˜ÞôÃ=êªcùÔuXu«×GêYoÛÖ¹.¯}ma;ö°^vo£]­d_»ØÎÞö,ªî”ûÜób÷¡.9uknÞ›óö½óMº›`.q/øº^€Gí0{#Mc*Ÿú¨ÇU¼•ßx€Ë‘:Ÿô‘uyÌ—Só›Gø"},\” ¤ßÝéoWœz43z‘ —öëƒ{®Î¦Ô³=ÌsŸùÝôñ·öîmG¾ôR¸ÂñÅú|šš>ú¾Ãûôg2xë{.ûóÜ>÷]¶×ñ“¿üæ?ÿ^«~Ö¹³ýî?üã/ÿùÓŸþë¿?þó¯ÿýó¿ÿþ‡P;jas-2.5/images/device-2012-11-18-jas-trinks-out-big.png0000644000175000017500000030740412054152672022247 0ustar giovannigiovanni‰PNG  IHDRX² °+sBITÛáOà pHYsÄÄ•+ IDATxœìÝw\Gûð™Ý;¤*RQÁŽ5h,ÑXbMbKb4SÔØ~ójL¢FÝX£¾Fc‰%v]T숢ˆ"Eš”;ÊõÝýý1ºÙ\ã ¼ò|?ùä#{»³³³ÏÎÜ–Û!¨qpUWÀÿŠ¢8Žã8NÏGb;‘‹+"Ÿ`¤)‘°jU%WÏ´e‹¹ºº*•JÓç ýôÓOïß¿¯RkGGÇiÓ¦•––æååYV16Õ¸qc…B¡V«µ?À”KP³àOçx´ïáѾ‡g‡žò©Ê¢—HßY­ˆÌ]cܰaÃaÆýþûï¹¹¹&.•““ãââÒ¹sç³gϲ,kh¶N:¹ººfeeéý®  aŒBCC³³³…Ói{G¯vÝèZµ<}ì=ê#rJˆ)¶o¹ø5bTм;—yYÕTÚf„®®®~øaãÆûôéóçŸ* S-©Tš’’Ò¡C‡'OžPU»vmGGG;;;„Ã02™¬°°a˜Ž;¦¤¤H$K6€-yxx„††êžÌÐŽÎ^Ý×róÄ(êŸù;öâXF%)(||Wï@ˆEb±›·¸Ž»Ø½ž2û¹<íé«AÔèGZ\šw®T-y©ÈH!3cZäY«žŸ27³$>†ÓèœÅ"„,k×®]TT¤V«•J¥ƒƒƒ§§'ÆX&“½|ùÒÐ"c‡ÀÀÀÙ³g;::b¬}o’ã8¹\^«V­ââb__ß´´48)€êÃÍÍ­cÇŽOŸ>mÔ¨‘nŽ0FÅa #D½þ”¥(„8¤;óku;õ ˜±SB8ó·òô$þ:ª‘þµZ‘(xá„1ÿiÑ¥¿ÒÖÌäXŽrp Yö—ȱvi­zÿf”eOffÊŠu 1o ÄgffÆÆÆ†„„ÄÄÄ”––Ξ=ÛÎÎîÑ£GÛ¶mcYVïèåææ6zôè±XLÎõrvvFµk×®nݺ7n„Û„PMˆÅâvíÚ¥¦¦¦¦¦šMò݂êEy#Ì+Ô[n%+TŒ‘b ¯Üúq¸Õ'Z㥑„hÇÚ˜%Nî#ÏHzuÊȱË"„êÿ’¢Å _öd•2,®ÕtåñzïõbÇÏH猖Ò-WÆØßßÔ¨Q¡¡¡cFƒR«ÕÇÕ©SÇÍÍÍÉÉÉÈâÁÁÁb±ØÈ< ÃE"Q```Æ õ|ãP¹0Ævvv‘‘‘ zž‘àjåS·±gíFîµæHeFgF!–a•JV¥0ë£:=êvéOFGQ7„‘Z’Ë1jŽÑpŒ†{=ι÷•wòwFQƱ,«”çÝîùÎ(½#‹I!MÓ:tèÕ«×°aÜœœø‚8Ž»}û¶T*}üø±‘+™ÆGÁ¼¼¼Ó§O!½µî[]Â:Qµœ·ô:){ÿzrŽ˜µs™Wÿ±µÃ#©ZÎMÛz ™˜µkÇ鹄iöÝ8ŸÞ½{»ººöïßçΦŒXiiiqqqíÛ·Þüóððptt”ËåJ¥’œ’Ë¡ Ã~üØ”{„ÎÎÎ:tˆŠŠª[·.yj”¢(Ò DZ,Ë0ŒJ¥’J¥—/_¾uë–é÷fTŠ¢ZµjåèèxóæM†ÑóFÒi¿óÎ;W®\žÙ¹y5ûjQ-w/„uN9VU”ÿxÝ·Êü#«Æ´ˆcY¤ïtM÷#òÞ5òó ò7¦)ÚÑ…UÊYµê_/ŽÁ%ÓŽÎŒ¬”U«õ–,xÅZii)ùÁŸR©4ýaiié… ®\¹âéééæææââ"‹)ŠB±,«V«KKK òóóU*œ @åkР¯¯¯F£éÙ³§¡~˜L×ú”QÈòï\¤ìjé}4«ViÊK=Á1Ó?â´Î¾8–Ó°šb}õp,«Rê}@FÈì›™ÎÎνzõ ¹víÚÍ›7çÔ¿JgÖ0þ@ªU«MÓå>´Or$h÷ØP¸jž’Ð’§zÈUMrI³Â+°)ìààPÕu*œ%/ÝF]z¨¶³SÅVŸµ_½Ë²zòcÖ0;C=!“+ÓŠÔqá×Ù‡ù1Uø''øú÷¿Ñëe… jMùgbµÎáà–…!Dz,c€ÿy„ ÇR[ òY~Fh<¡¼‡s-¡‚Re¹Eׯ#S¨³Šd–Õ°†¥!Çr¬îÍ?ò'nÖÀuÑÇÝ4 ³øÏë÷Ró9NïÍ?„ú°s£Qo‡—*5_o<›_¬ÔwË þ*˜…—7Y–åX†cŽe¹þMþdü=œ‘RVºvÕç}Âk‰ð넳1Ë4ôrÖ¥éË8‰Ç0:óükþŠÝl€°æÒ¨þ\íZ7tSjXÚǧV|ìšOºd•™YŽ^PmâïU¶oC9Åaþî—e³¡*™5Ëè¹Úé`G?¼û‹Ô’õ"Ž+úã‡|jÕB#Œ¹BŠ1Æa,/)Q%$ØwêD'$|1r¤“}üîsŽcõýâ° B–eûêßü`(¢¨¹CÛ¸½|‘;ésN&C!ŽSŸ¨)-eX–aY†ã|þüÓyôh†ã^MyýŸóÈ‘>0Eþ,ŽÎþbÒ‡‘whˆ8NXþ«µ6@[¶Xãï”©É ?!Žã¸‰ï„µõvÌû “Ÿÿj*BBʤ$yl,[V&œÈ!¤ÎÉ‘ÇÅ©³²þ™òâ…âÞ½ˆ £i =L/@ˆ%%/bÿ†×˨p–?,ƒX„ð«±éã·›EzÌšÎR®_ÿÕTŽC)33BØË ±¬ðŽ"Ë0ÊçÏQݺüœˆãII¹Ó¦ üå±ïºÈq\åÜ"ܸqcPPPß¾}CWq¼¡,¾Gȼ:DÈÉ^ܳEC±£}½+ठcDQï´ ü+æi‰Le⯿ÿþû>}ú`üjØ,,,ÌÌÌܾ}ûõë×ÿðŸ ç¯4£FšuêÔ7* ËêcŠ:uê„„„Ô¯_߲ŵàr·c¼yóæ¿ÿþ›Ì0hР­[·N™2åï¿ÿ†ëº`‹ß,óê…/›ÖoZ–—þþð”ž=Ëââ<.·lÉbÌ"dîâÅ‹ËbcŸò¼wï@YAçfõÇp,câ*X–e^‹¿wïž››[óæÍ1ÆsçÎ]µjEý³½ß~ûíš5k„S6løË/¿>|xÛ¶mo¿ý¶pˆrqq™1cÆŸþù×_-Y²$((ˆ|úí·ß2„¢¨ˆˆˆuëÖuîÜ™L74¿•[¡;áC‡ ýýýM,€k>Ѧ‰oññêü|uiiÑ¡CR¹Êkùrqx8ƒ1ƒéÿ‰‚ƒ=V¯.ÖpE‡©$UqqÑÑ£í›4@,gÙÏ'8Žsttä8.??Ÿã¸Œ9R8ìõë×O8cü×_õëׯ~ýúï½÷ÞÞ½{ DÆOOÏcÇŽ}÷Ýw!!!>>>ãÆ;sæL§N0ÆÍš5kÔ¨Ƹ^½zmÚ´ñôô4>¿•[¡;C‹-\]]ÓÓÓÍ-aé@Ƚ:#‹°F.#§tš’•FsøV²ûÒeâfÍL?/y®^s".M©Rkär¾41ýϊ̪ž““Ó7ß|Ó®]»³gÏf’ÇVuîjMÁ_ºt©E‹‘‘‘ãǧizúôéd˜œ7o^ëÖ­7mÚÔ®]»ÈÈÈ)S¦¸¹¹-]º”¢¨O>ùdùòå,Ë?~¼k×®GŽá8ÎÈüVnÑ»wïiÓ¦MŸ>}Ñ¢E{öìÉÉÉY°`¹·'ÖÞ#dY–%rƒË0G®'²Œ¦ß²_ò¦OS&&rgüs_²”f^#¥6ô\±òïG¯>f4j†ÜþBˆAˆÅ˜_‹‰g„/^/ž Ùx,ûåüãŒWŸ’ó*–y5¬r±Å2œYg„àŸ·lܸñÙ³g'Ož¼nÝ: . „¼½½BeeeÂOKJJBöööº š;¿[Á0ŒF£!¿#Ü·oŸB¡øïÿ;vìØ‹/ƒ£`.+–áXŽcY–e_Ÿ2³ÿLg\M¸ð(ÃsÉ2QÆìëS@þÜ‘öóó\ºôÂÓ^Id _VYrFøº4Ÿå^UˆeYöéÓ§ñññÁÁÁcF#‰Äb±‰èááÊÍÍMKKcY¶^½zÂO}||0ƹ¹¹ºƒ´¹ó›µzg¾}û6B®Ž€e,_]±LÏÎ……‘çbh_ßôÜ¢×)v–ÑüýðÒ“LE?Ó§ch__¯Ÿ—\NÊÞý˜Ñ¨9–!K¥åäÛ5oþjžúõ3r ,NÌËq9-«]»6B(77—¦éÖ­[“áÄÍÍÍÃÃCëa™.]ºðSºtéÂ0L\\\vvvBBBóæÍù ›NNNÝ»w—Ëå/^$·Bü¥Ëœœãó[³z‘—Ñdee™U2Âò4Lä$íÒ½”Ãû"Œ9µÚuðàý§î¾zûB!ÇZJ•¦Q^‹gÏš¥ÎÈ@‰}|¼–,)¦Ä25ãæd÷R*{57‡ÎÝMþzÐ äèHÕªåÒ¿ÿ•½—Y†±øu)ä.»»;Bèüùó=zôX¸páŽ;ìííGåââ"œY¥RmܸqóæÍ………  =sæLBBÇqëÖ­Û°aÃöíÛ7lØPZZ:räHÿÍ›7“'9Ÿ={Æq\ddäG}téÒ¥çÏŸŸßš­ z÷DAAA P([·n…GÀ–Þ#ä^%æ}žS´ò¯ë‘ÍÃìÄ\MÊÌg_ \…ñÿì&~§Ø}‰{ÿ}ïE‹²gÏF,[oñbDQªß·G6m3¸Ó‚çøÁ.ñyίgØNÍÚ"„Ïïºð<§ˆ¼Û²J>zôhàÀüûï¿7lØ2jÔ¨Õ«W«Tª={ötíÚ•Ÿ9...&&fÆŒNNN¡Û·oÏœ9S£Ñ „öíÛW»ví™3g.Y²!$“É~ûí·Ù³g“çæÍ›GŽ4hÐêÕ«¿þúë´´4ãó[³d ÿÔ(˲·oß^µjÕåË—ák` Ÿ3ì8ì+©òŸ"0ƈCÜ¿_­Xols¯¬ÿ›…Æ.(¨ÞÏKØÒ„]Ç5sÒçL^¢iÿ_ýíVjü³îuf ŒF‚Ò^§©O<¾ÞÈBŠ¢(ŠâÀ œHn¶‘?ÝÝÝ›7ož–––––F~GH†:š¦BÇy{{‡††æææ&&&’ø¢ìììÚ´iS«V­ G5š¦ÃÂÂnݺůËÈüFjh|+È¿…%9Ys) dñS£Œ0C½Þ>ØÇÝY™›Ã°,â8ù³gˆeb3 –íê¬&ïIÑhdÉɾî®ñ)YüÛDõ—V^'Ï%F&²,ûòåK½gNüÖÙÙÙ999èõ#\V¡P\¿~]÷#²øƒ„ŸßH o…ÞXÃÚ{„Æçañën›ã–=ûŒåضMýÙ×CË0,eÞ¯æ­TÌ`îGp–ÕŸå¿#dYŽÆ’ã8Œ1é÷ÿ™È2 þçqO–eYFÃ"Žüdž  Ërˆá8=!)ÁpÀ–¬¸4úï[‚ü¿ùÈJäZ‹¼/ Ñ4ËqJµŠaX–CœXÌj4!ަårÇ îŠ ÒØÿS> …lÃÚìFþ‹{šA‡4¥}}„\Þy'㥴@RZX\–’ïÔ³'CQ¢À@qãÆñÉ™ä}4¯þãô•fÚêsYyPpúöÏYÛ«)’Ù¹»O¢ü –ËŠ°èdô–a8Ĺ™0´oÿ€~ýÔ"ñ¹G©ùÒ2î_§~øßÿà§ÃY!€ŠgáÏ'Z¾3ºTYþÈ„1®eG7𬛖] y°cDQT@=·œÂb¹Bmâ-Àg—wÃÍBÎò{„¦ŒJ‡ä &9#—û÷D–eŸeæÁ° ÊYsiÔÔLï|0 ¨¬IÃ$|€Eï%VNgºî­é†flšK£•zRglÁÂÓ/ŒqeLð¤ ,‚ÛM«ê:UF„i S¼0 „ÀdÁÁÁ[˜óC ®€PU]ð‚Þ ØÄ°Ôh0¨Ñ` P£Á@ Fƒ@!€ B5 „j4Ôh0¨Ñ` P£Á@ Fƒ@&ªê T;¡¡¡_ýõéÓ§¥Ré‡~ˆ1V©T)))Û·o—J¥QQQ#FŒÀ+•Ê”””ßÿ½¨¨¨ª« ªR›6m>ûì3Šúç;åöíÛÕjõøñã)ŠbY6++ëÔ©SwïÞå8®AƒsçÎ}øðᆠæÏŸ_¯^=aQiii?ÿü3˲üqÏž=íììîß¿¿aÆ¢¢"~-,ËæççŸ>}:&&†ã¸Jß\`s>>>'NlÒ¤IYYÙ‰'>LvôgŸ}Ö¹sgŒñÝ»w7mÚ¤T* E…0ÌZµjÅǧT*½{÷îŸþÉqÜ‚ ô†_½zõô®Ô,½zõ***š7oÞgŸ}&‘HâââŠŠŠ¢££œœÆO&Þ¿_"‘\½zÕÞÞ¾ª«\í4nܸædÌ}:EQ›7o–H$7oÞ¼yó¦D"Ù·oMÓ†¢BfÂøLNN–J¥[¶l¡(Joøy{{ë]{U· ¨t½zõ’H$óçÏŸ0a‚T*0a‚X,þå—_$Iß¾}…×­['•J»víúÆœæª oðàÁ‰dݺub±˜¦iš¦1Æd↠Äbq“&Mâããsrr‚ƒƒÃÃÃ%Éè×~øá©TúÅ_Å;t蟟îܹڵkÓ4½|ùr‰D2sæÌ¡C‡òkiÑ¢E^^Þµk×hš®ê­¯T5!®>üðC‰D²fͱXìé陜œ|õêÕîÝ»9rÄÎÎŽ¦é£GJ¥ÒfÍš cOaaa|˜ çqrrºxñ¢T* ‰Dºá§wí5!Ì`¨/˲ ÃcŒ9Ž#W X–‰Dnnn ÃäççWuAÕ‰Dþþþþþþžžžü¥$Žã†IJJ:~ü¸ƒƒC·nÝ„ý8Ã0 ÃðEþŒŒŒ‹Å§N*--efË–-¡víÚ ,,,äo˜´´4–e»víÚ»wïüüü¨¨¨V­ZÑ4}ñâEFÃ0ÌÒ¥K§M›VVVF1%*È} ]9räÝ»wïÝ»·eË­oÐÇ‘oKµk×.·„T*%¾xñ‚ã87772‚öîÝûâÅ‹—/_–ÉdänbÅo ¨R7nÜX¼x±§§çüq÷îÝiÓ¦qçêêŠ*--%ó\»vmûöíéééäOS¢"$$ä?ÿùÏÚµkßyççÏŸ“;Ö&®ÝfÛZÀÃ2å(**ÊÏÏ÷÷÷oÑ¢ßý÷¿ÿ½}ûv÷îÝG޳eËè’j¸³gÏ9r„㸜œÝ`°³³C™$jµ!$½:0ííí1ƆüYVV–““ãèèܺuë“'OÖ~ªæà8nùòå»ví5jÔ°aÃæÎ@¾Hñ÷êøKS„nTèÛ²eË&MšÈd²+W®,^¼X¡P˜¾öÉ“'¿ñýœ–c÷îÝ#GŽ\±bEPPPß¾}É@øôéÓƒþç?ÿaY6""¢ªëª^VVÖü±k×®sçÎéNáááã”””rÇ­gÏž!„BBBÈŸ‘‘‘¡´´4²`LLÌèÑ£Éó\|ðÁì?~üþýûƒƒƒW®\Ù­[·¬¬¬>}ú¤¥¥!„5jDæùá‡âââÚ·oOÀ”¨Ø¿¡*ªà IDAT“&MÂÃÇ~çÎCq¨wí5!ÌàŒ°äÚzvv6Ƹnݺr¹!ÔªU«‰'FDDÐ4œœ\ÕuU¯aÆ&L ýËÅ‹ÉÄ€€€Ï?ÿ¼E‹}ûö½wïÞ©S§š6mj¼œ£GNŸ>ýƒ>ÈÉÉÉËË›åOúc¦`P#pqlUW@Õ;uêÔåË—išvqq‘ËåÓ§O§^?Wš••µbŠТ´>š={vYY™H$"ÓÏœ9“••µwï^š¦É‚7oÞLLLœ;wnXXÆÚ—\µJÓú³{÷î …bàÀº 6lØpþüù¿þúk^^ÞªU«(Áó¯gϞݿ?_¡”””%K–ôíÛ·¨¨håʕׯ_§iúÉ“'‹-âKˆˆˆ7nÜ7ß|sûöm2ƒñJò-`J+½ýöÛ …bÀ€d‹¦OŸ®T*ɲ†èÖÇÈŠF¥P(öíÛ·yóæÍ›7?xðàÎ;dÝr† ¦P(:vìH*³hÑ¢—/_’ÊÄÄÄœ>}š¦éƒ>xð@«1ËÝLá<¸Қ^îÖéÎ/‹£££<== mï|`h»ˆ1cÆ(•ÊV­Z‘š5kÖ¦M›#F(ŠvíÚ‘‰$öúõëW»vmCÛ¨7¶…kJ8 ÔZ–ÈÈȈ?tèÐÁƒ<¸`ÁÊÀ¯›V!„hšæB‘H$<Þ„ ÿ1¶³³ã§»»»;;;ËårŽ{uóqðàÁß|óÍСC¿ûî»7nŒ7.55•ÿÔøŠ222D"Q½zõ0ÆÂEBiii?þø#B¨°°pÚ´i‹-ÊËËCy{{wìØqþüùZó·oßnß¾}:uâââöïßÿùçŸGFF:uŠã8±X¼k×®Þ½{ß¼y³´´ÔËË+77·ÜJjµ€ñVòññ‰D/^¼ Ó)Š22 šXá¿ÝÝÝÅb±H$rvvF=zô(;;[$íÞ½[·ooo±XœžžNÚJX™£GÎ;×××·[·nÛ·o×jLƒŸ®7®,Ø:„ÐÒ¥K[¶l9hРüü|CÛkd»ˆºuëŠD¢¼¼<2Cbb"B¨sçÎb±8;;›LÌËˉD^^^F¶Qolókâ 6”°µ¯^½:yòd–eBÇ‘*\Å|ÇÜ·oß?þ8zôè>úcܨQ£÷Þ{oéÒ¥‘‘‘!!!ÿùÏÊý>˹nܸ1B(++K؇‡‡=z´}ûö¤GÈÊʲ··'ý B(,,ÌÁÁ!!!Aï@xîܹ°°°ÈÈÈ3gÎܼyóùóç³fÍÊÌ̼qãÇq½zõ2dÈ7ß|Ó¿ÿ>ø !!¡BÚD(##!Ô¨Q#Sf¶ >Ïž=ã8î÷ßÿè£ÆŒ3zôè3fôèÑCo9¤ÓoÚ´©î ÷ÿû_†a–,Yâââ²cǽi% ¶nذa'N\¼xqtt4©’ÞíÍÌÌ4´]ù*Ö¢E 2À>üðCRTÛ¶mÉÄ–-[¢×c¤^åÆv†ÇqÌk0 `;B¨¬¬ÌÝÝ| ¶ Çq+W®mÚ4ŽãÈi¢J¥â8nÚ´i}úô1ÔO}üñÇ7ö÷÷Ÿ9sfVVÖ•+W„‹dggwìØqÞ¼y^^^ÞÞÞ#FŒHIIIKK#Ë6hÐcœ™™©·ä#GŽØÛÛ7jÔhß¾} Ü?¾G7nÜà;Œq:uêÔ©3yòä.]ºTø5¨[·n¥¥¥Mž<9000((hĈ|#èmsësþüùäääo¾ùÆËËK,3†\†Õ[Î… òòòæÌ™ãçç×´iÓðåçääœ?~èС·oß~üø±•¡¡¸2kë5j´råÊèèè½{÷úøøøùù¹¹¹éÝÞ‹/Ú.âï¿ÿ~öìÙôéÓ=<<š6mºbÅŠ¨¨¨Ó§O'&&Μ9Ó×××ßßêÔ©±±±·oß6´íNNNzc[¸±æî>ë@€5(„СC‡üýýŸ?näÛt¹X–ýâ‹/ÊÊÊ6oÞüôéÓùóç?^"‘ÄÅÅ=þ|ñâÅ,ËΚ5«oß¾†VqéÒ¥›7o¦¤¤4kÖlúôéÅÅÅ!~‘üüüÏ>û¬aÆ©©©ÏŸ?÷ööþúë¯ù‘ÌÑÑ!TVV¦·ÿzùòå½{÷âããÉÀyàÀ;;»sçΑ™O:uìØ±åË—ggg¿ûî»çÏŸwqq±¬ ‘ËåÓ¦M |òäIll¬ðM=ºmbA}ärùW_}U¯^½”””‚‚‚Å‹7hÐàôéÓzË‘H$3gÎ OII¹qãÆ;w„¶oß>Š¢:dý)WÍ›7ÞK3kë† æããÓ»wïääägÏž={ölùòåJ¥Rw{¥R©‘íB©Tª)S¦¥§§ÇÅÅ={ölþüù Ã|õÕWIIIIIIÎÎÎS§NeÆP}âããõÆ6¿±éééÇ7k÷ém(@¥Â7hÐ ,,ŒÜV1å¡ðŒÞÛBE988´nÝ: @ï H½+òöön×®X,æ»­Û*4M7nܸI“&"‘HØeúéD„·a0ÆZk§iºQ£Faaa"‘ÈÄ;¦†ZÀÐýôÓôôô³gÏê}ÀÕÊúè.e¤­éýû÷OKKÛ½{·ñº™[%Sêiqáºå˜BÖWÉP!–•f¨@xs ><>>¾¸¸877÷øñãÍš5«nß°aäRéµk×üýý«º.PyªW_üÃSE?òà«-žÉ´¹BHžT¬êºÀÿ¬úõëWu@5eJl@ü+A˜ª$‹÷ïß/|HõçáááááQ±eŠÅb+/-ê=Jœœ‚‚‚ªÕÕTC­g¨ªwïÞ;v¬¡ð0?¶ØM6åááQá›®N:Õê—¶¨‘£Ìâ0CÕ~€¬ä–¬4†ðÊ>Ž’““KþmÖ¬YæŽgË—/¿ÿ¾Þ§ B»wï...æ_dõÉ'ŸH¥R~uüK¶ÌªmqqqFFÆñãÇÛ´icîÑ©S§7nÈår•JË¿—ËšŠùùù:t¨´´T­Vçää,\¸Ð¬6ܲeKjjjIIIzzºÖãŽË–-+,,T«ÕÅÅÅ“'O&ÅVH>~üØÜªj=CU%œŸŸß¹sg½;KoüØb7UHüð´;44ôÊ•+2™¬¬¬ìĉ~~~&–3fÌá7n4k¿´jÕ*::Z&“)•Ê»wïZ¸]¹r¥¸¸¸DG§NLi1½õ™>žÿóÚµkçÎ3ëy´ ß³ÈêþʦýpÕGÙÙÙ;wŒìøšYÛÓºuë’’’áÇëmˆAƒ‘óÛ9þü¼¼¼qãÆ;vìØ±ï½÷žé-(¬íûï¿ÿþýÄÄDWWWÝ9ûöíÛ£G½%?~ü8&&&<<<,,,>>þêÕ«$€¬©ØáÇSRRzöìéææ6eÊ™L6sæLÓckèСS¦L9wî\ff¦ðhüæ›o¤RéçŸîêêúÖ[o…††V`FEEÍŸ?_.—ûí·¦WÕPëª*1>räÈ¥K—tUCñc‹ÝT!ñCèö•+WîܹӼyóŽ;&&&îÛ·ÏÄŽÉÓÓ³C‡üøÓO?©Tª÷ß_wíFjsÿþý6mÚ4kÖ,>>þÂ… V6WXX©Ïž={233;wîLþ4ñ{ºÞúÔ«W¯£Àš5k²³³µBňr2 ÂÌСgq»ýôÓOJ¥’tßþþþ …‚aòJ#—’’’õë×ën•¹g‘Õý•MûáJ8ŽôoÒúõëi𯝙²J¡ß~û-!!Aïû3ííí>|xýúu–eùþbýúõ÷ïß'¿Ù2´ÆêÝ­Úöë×O­VóﳺvíÚ‰'t[ÐÛÛûÌ™3ï¾û.yzeÙ²eüÛ™­¬ØºuëøŸQ©Q!G™¹a†t=d]»]¼x‘\èKIIùõ×_úé'rºsüøñØØXaŪjÏ–Û’UÕÛô82&;;;!!áÈ‘#‡>|øð?þ¨U.¥CøiãÆ5Í_|¡[›cÇŽ={V$im̯¿þ:gαXlooòäÉœœaüaŒ»wï^RR¢P(Þ{ï=­Ûììl†a4Z­.,,ŒŽŽÖºòÃ?¤§§gdd(в²²ŒŒŒŒŒŒ)S¦hU/00ð‡~ظqcaaáêիɧÖT cìææ6uêÔsçΕ••ݹs'88Xk7=zôÖkzc]ï@¸uëV±XLÓôªU«È×CŒ±•mxîܹ™3gΘ1cÉ’%™™™ÑÑÑZó¯ªn멪pA¾ƒà§‰[ì¦ ‰½]îl¼b¡&Mšäæænß¾]÷#£!öâÅ‹ßÿokš‹02–Òºõ!Ο?ÿ×_é®Îú£ ™fHß@hM»ýòË/;vÔh4ýû÷oÛ¶­F£0`@ZZÚo¿ý&¬CUíÙr[²ªúa›GÈHÄfggoذô_4Mëî€gÏžå œ?Þ”1b„J¥ZµjÕÌ™37mÚDòûôîÝ›\‘çg7nÃ0Zïûþ믿öìÙsâÄ Ý\»ÙÙÙ7n´³³ãß<©uðo§¼qãÆéÓ§kÕª¥÷µ|5~üñDz²2ò\²5ã×NÓtDDDff¦î=Þ &Ìx-00°ÜÐÃÃC¥RM:•ÔªS§NfôèÑַᆠH³Põî»ïªÕjR¬‰UÕm=#U.xá³z¨ ßMÖÇ¡À>|¸îܺukÓãçôéÓÉÉÉz%71ª½¼¼ââânܸ!|lÁú¨62½õAy{{—””L›6MïN·ò(Cæ‡Ò7ZÓnä^àÖ­[³³³É½Õ§OŸnÛ¶a˜qãÆ ©Ú=k¼%«¤6l˜íŽ#d b_íuò>C fÍš%Œ¢¢"áœYYYjµZw­þþþwïÞ%wP\\\0Æ={ö,((8wîܶmÛNœ8qàÀŽã8Ž+..^4ŸyòdZZZݺu­©*ú÷õývíÚýõ×_ÅÅÅááá¦\O7Òz†ª*”““³råJŠ¢ÂÃ÷lÙBž›×?¶ØM¨"âÇP`cŒïÞ½]¿~ýÀÀÀzlX·b¡¡¡ùùù»víjذ¡ßkzoܪBè×_-,,ìÓ§¿¿?)ÁÞÞY×\„e÷ Õ!ôñÇ3 fd¥Öe¦‡™pµ=+Û-&&†eÙ¯¿þš¬‘ÜN~ôè‘¡>¡2÷¬YýU%÷Õséaú&²uëÖ‡éôµ®óvíÚõÑ£G2™L¡P$$$DEE™~KÓôÚ’®JïGï½÷©€\.òäÉ;ï¼c}Å:wî|ñâE…B!‘HärùÑ£G-x „îÑèááqìØ1rýÙ³gƒ ª6ä¯ïÇÅÅ1Âô0Ôz†ªÊ#×`ɽ„Aƒ©Õê·Þz cl(~l±›*$~xZÝ¡C‡¸¸8R±k×®™þjõ3fK2d§zû5#µ*--%_½ù† †1¶¦¹ËBCõAMš4‰a˜ÀÀ@³ D¦e憿Z‡ž•í¶víZ¹\Þ Aò§³³sQQÑÎ; U ’÷¬•ý•MûáJ8Žô°>óYÛ¶mKKKu;>ÆX˜é cLÓtHHH£FDFóÚ¢¶|tSZS1²¬——WDD„«««¹ç‚%HSÇ£i:88˜ä·«¨6Ò½¾oœ¡Ö3TUÞÞ½{/_¾L6pþüù÷îÝ#ÿ6?¶ØM?ÂêV,88˜¤*4½bü ­ýbVetK °¦¹„Õ3w)Cõá ´ &¦e憙°Jºë²¸Ýt ´`Ÿò Vøžµ²¿ª„~¸ªŽ#ËaŒW®\çææfÖR ÈP¬¬˜-6ÊFUµ†¹UêÛ·o^^^—.]ȧ˗/çŸ7?ÕpÛ«¶µªž³Œ¡m±8ÌŒ¬¨š·[5ì¯Ì­€¡¼ò+c-Š¢<¸|ùò üº Þ$wïÞ7nÔë¤TüŸ?Àzf ŠÑ4]Í_ߪPýúõ÷>?ÀzfT/ T8*P.«èmò[éʯ úßÉÌg(O˜5©Ñ´øúúZ[ËŠóæB†ö 5Ñl”é­ƒª U·¤‰&2ùUuDÊägqêgªIÿcÛö7”Žë­·Þº{÷®R©T*•$Y†‰Ã•iÌþ‡2óÊFXMWÏž=>|¨T*¥Ré¶mÛLï—+<)Z…§m³2N*$#š¡=hqF4d]¦·rªYTÖ4T¥¥Ö+—5ÑbeºGC‘o¤§*—ír‚"‹‚ÄP?Sú[´¿†ÒqÅÆÆÞ¿¿eË–íÛ·ONN>{ö¬‰õ¶2ÙÿPf>CyÂl~j4-nnn©©©gΜiذá!CòóóÉÏ„M©[…'E«ð´mVÆI…dD3´-Έ†¬ËôVnB5 ‚Êô†ÒUi©õÊeM´X•¦Îpäšn å%Ì CýLå÷?zÙ¢ýõÀÒq•••-X°€üŒcýúõº+«ð4fFêSù™ùt—N1’'Œgnj4-#FŒ /.!Ûµ}ûö'Ožèw%$EC6HÛfbœØ.#š¡=heF4+3½ñÍb(¡š¹AebCUmj½rkbe´”ÛªFŠ|CÓM©5=‘T<³‚ÄP?Sùý^¶h-"d8Wzzz›6mB"‘(,,,==]8Ò˜ªO%gæÓ]ŠeYÝr å ã™›M‹§§'ÆøéÓ§dÙ¬¬¬zõê wj¥%E3´_¬iÿrãÄÖÑ ez³2#š•™ÞÊM¨fYPi¨êZ¯ÜšX-嶪†"ßÐtSê#,ÁÜžÇHªNžYAb¨Ÿ©üþ§’Û_Ý7 uïÞ=))éñãÇOžÝ¥Œ”c(ãaVj4­f¡(êòåË/^¼X±bÅüQXX(—ËMß:[$E«Ø´m|™zã¤Ü}W!Ñδ2#¶.Ó*/¡23¨Êm¨Ê"C‡Œí¢¥ÜV5·G*wº­{½©:…Lvî>Ð IDATŒ±Þ~ÆÐt·ÑôÈ©üö7H«¸ÈÈH¥Rùé§ŸÒ4MQÔìÙ³KJJ´·]3ÝúT~f>Ý¥ô–c(ãϬÔhºÍâêêºhÑ¢£GnذaõêÕR©T«=+3)šî~A6NwW Ñt÷ õÑ™ÞPy Õ™AUnC¯Oå¤Ö3±e¥Ñ‚,JS§µ^³:bãõ±¾çÁúRu ™$†ú™Êé*¿ýµ¼hHÓôÇÉ•èääd___á5}Û¥1ÓUù™ùt—Ò[Ž¡Œk<³R£é6‹D"ùî»ï0ÆÇíÙ³'++K«­*3)š^6MwgÓŒh„î|úô)²4#šõ™ÞÊM¨†ÌÏ·g¼¡Œ×§rRë™R“rÙ$MlÔóIÕ),߬ 1ÔÏTNÿƒª¢ýõÓW%É¡C‡<<<¼¼¼Îœ9“••EžØÔbäj{Þ#DU”™OïãgÂ*ʸƳ 5šPDD„§§'BhôèÑ¥¥¥K–,Ñ»”¡½PIш OÛ†LˆCûÎÊŒhÈÀÄVdD³2Ó›‰ ÕÌ *Óª¢È”CÆHMEÑbUš:ÁzÍ=#1Td]Ïc$U§YAb¨Ÿ©äþLjŠmSWƒ1þ裞={&—ËåryrròàÁƒÍ½Ã\±a5ÌÌg$ãaYj4­vÉdR©´´´tóæÍ&Ö¨À¤h|}*6m²4N*$#š¡=hqF4d]¦7Sª™TÖ'­„Ôz¦WÆ‚h±*M`½–uÄzÙ('(ÏÜ 1ÔÏTrÿcDŶ¿A”át\M›6Ub3#ËÒÕ,3ŸH‡Öâ–¥F¢(Êßß?""ÂÑÑÑ‚¾L·EÖ%è2'•ŸîΚÎ/DïÄ–fDã—µ,ÓeBB5sƒÊú†ªÀ(*÷± 2&.b¼U-^¯ÅÑkMσ ç%Ì CýLõé*¶ý͆1¶ k³Cõ©nõDš­ºmš®jØþÖ³r‹lÑ žoüï2tÐY“ûÓЊ*´â &Ôh ÂAPrA€jR£ AÊA*„ ¼Ù,hB‹X,nРT*µ¦GGG™LVQµ2]:uêÔ©SVV¦5ýòåËjµúÁƒò»Õ‘•™±¬É¾Æ3ž^˦õ·&§ €7•™±LϾf$K™ñôZ6­¿Å9¼!ŒgÆâY™} ÎRfJz-㨒œ‚Þÿôøº™±ø¬Ì¾Æ¾Y¨ÜôZÕ3§ €7„¡ÌX<+³¯™˜¥ÌHz­j˜SÀ›ÃPf,~l]ö5³”I¯e¼U’SÀ›ÃHf,~k²¯™˜¥ M¯UÝr x3¼:û1”«ÜÔƒ¦d_+7K™)鵪[NAoŽr3cñ¬Ì¾f(K™‰éµôVÀ”úß³r ê®Àÿ<+3c™ž}ÍH–²rÓkÙ®þfå4±Lÿ+0BHëñr™Ñôß {{îîîIII%%%z;aJ!AAAãgÏž1 cz¬¬¿îÓ1Zkß»woýúõ{ôè¡ÑhL,@Mdý S5Ìi§•Ù ¨Y´2{5K¹™½T*ºª+PÓÕ¯_¿´´´ªkQ½T`›Ô¯_ßÅÅZ¸Æ²2–Äbñœ9sºuëæëëûèÑ£r‹…Ãù”±pܸqßÿýþýû9Ž3«Ðƒº»»ÇÆÆ_P,7hÐ@*•Z°l¹l]yë‰Åâ}ûö………={Ö‚uYSÏJÛFsém“ÀÀ@Žã”J¥ÞE }ÊõÝwß©TªTàÆê Ý7[uˆ7 ʹ|ù²Z­¶xï;998qÂÏÏO*•ž?žã8C‡­•‡s•ðððptt”ÉdX¦õ‡†Þ/NNN~~~‰ÄºÚuæÌ™ãÇÓ´ö ¸xñâÂÂB‘Hdn¹¹¹+W®¤(ÊÐ ~~~‡*--U«Õ999 .äg>yòääÉ“,[啯(Ë—/¿ÿ¾··7B(99¹¤¤¤¤¤¤¸¸8##ãøñãmÚ´Á[SϧOŸ’2%Irrò¦M›<<<ÈGæ6r¥¶ BhÁ‚YYYF.—_¾|¹]»vÂ61þ)_ÔàÁƒóóó;wî¬Õž‰d̘1R©tÊ”)Eñ{¡°°ðñãǰä ]âÊ•+ÅÅÅ%::uêD*@Ö¨õéÆ…å”Œ‹‹ãÃ>&&&>>žÿóÚµkçÎëØ±£Öš^¾®êo›&îý:èm+µZýÿ÷|O¢¢ýôÓ¼¼<„““ÓáÇ7lØÀ²¬¿¿ÿܹswïÞM:2‹ëéèèHʤ(ªmÛ¶óçÏ·³³?~<Ã0æ6råÐj“üqÚ´i+W®Ü»wo``à‚ :Ô­[·ÔÔTŽãŒ*,êðáß|òÉÂ… {ôèÁ0 ¿:‘Häìì,‰œœœÄb1ì±XÜ­[·Ù³g—••ýüóφ2ºd†I“&9;;#„¦L™Òµk×>ø€¬ôÑ£GäDáôéÓ½{÷æ÷]ÿþýgÍšuáÂáiD¹ñðøñãþýûûøødddøûû·iÓF,7oÞ<>>ÞÙÙ¹E‹;wî¤iZkM/_Wuˆ7 ŽM÷¾n0±,K*¯¢¼zõê+VtïÞŸ˜——·jÕ*2nO›6­OŸ>Z᛽nÝ:²FŠ¢|ظqc2?MÓ|{åää«...J¥211ñôéÓ7oÞÔh4{÷îMNN>qâÄË—/cbbÈ"6­æƒ>àƒc|á²ߪۼvvvyyy+V¬îÖÐÐÐ~ø¡N:«V­"K ÷‚¯¯off&9¿11tµÐøÅùcÇŽ¥¤¤è^O3üöæçç“yöìÙsÿþýèèh2l/\¸P&“yxx4oÞ\kM)¿ÚÆú÷±©c-[¶,,,$+Z±b…D"!Cš){_7­P+®x†¦#„~úé§´´´Ï>ûŒa~ Ñì mW:urrrvíÚeggGÓô–-[ô„¶k“#Fh4š®]» ãûÏ?ÿ$G¬ñOu›!wìØ1­S72ƒp/¤§§_¿~ýæÍ›yyy÷îÝûöÎ; Š£ýã³wG"½‰‚`G¬(*¨Øk°Dób7¶è«X¢FŒ¯cŒ±kì}íŠ ˆ(( ÒiG<êWö÷ÇÄ}7Ûn;Nýe>ÁÜì³Ï<óÌÌÝîì~éKGêRP¹.Y²¤¾¾~Ê”)Œ_®ó\çþýûÑÑÑB¡0;;;888((~¯ MLL$~™‘¨ÒþÇœod;Œ9&‰$ÉØ±c%ÉÏ?ÿLt·ÊÞg‹y!dÌ+[9 K—. ,˜1c†\.'ÂÈÈȆ††”””ÜÜÜúúú5kÖý׿þUUUUTTTPPPUUµdÉò§*scäÈ‘ëׯ÷÷÷ÏÌÌLNNÞ°aƒ¿¿?ý.i=ÂÂÂKKKÇŒ£¹cü‡”…°]»vr¹<999))éùóçõõõ¿üò <©&®ÒùÛgýúõ344}úôîÝûÀË—/‡?:5Œ!…¿}ç²±±_Ø)Ýfaa¿1Á]ÉÉÉb±X$|7›‚\.‡c÷ÊöÙgä8êÌy€R©„Ag4®T*ãââÜÝÝŸ>}zîܹ… 0ÀÑÑ144”mkõáÇýüüÈÃÇqKKK à áQÅÅÅâþ(ÌË—/ÿý÷vvvƒ :vìÑå·nÝ‚6ŒŒ"##øáoooŽ í‚¾òóó‰Sè8&UUU€V­Z‘ ÍÍÍá€çþ”ž;Ú333wîÜ yíÚ5__ß3g·7!uÙ³gOuuõÚµkÙdÌr…¨¨¨•+W.\¸°¬¬ìöíÛr¹<''gÒ¤ImÚ´yôè‘Êö~ÒùƘc°C ÿ.**Rêª*¥R™’’›pþüùeË–¹»»gddhC [a2uêÔ þA”çääà8~òäÉ›7o§=zôäÉ“.\xúôiÇCCC)—nØðöö>räÈ‚ îß¿¯T*Ÿ>}×±cG>Çr ç)0W*•[¶l±°° yüøqnnîºuë âââp/**’Éd”ËÖJ¥’þë9;;ÇñÞ½{á8Þ½{w@ZZÅãǯ_¿~ëÖ­FFF'Nœ ÏÚ0$I||…Ÿòì}nóŠ£ÜÁÁ!!!¡oß¾### Æ^^^qôèÑ›7o^¼xÇqÇ«ªªÈ]æçç'—Ë ”J%ý›wn 9À÷ä ݺuÛ¼yóæÍ›ãããáxÑ××oÙ²eiii“ã94þøãâo⇠oß¾---%.þ™ššÞ½{Ð0†þviôÞ½{¥¥¥þþþööö:uš0aü¾v÷îݬ¬¬U«VY[[ëééÍš5 nRÂ0ÌÄÄÄÄÄÄÏÏÏÓÓ“ñ",}×hBB‚H$ rssÃ0ÌËË«ÿþä·64 Ý8OÍøµk×ôõõÏŸ?¯P(îÞ½;lذ¸¸8˜ µµµyyyŽŽŽ*uëÖ­´´´µk×ÚÙÙ988¬\¹211ñÉ“'”*..¾{÷î”)Sž}úœ>}ÚÔÔôàÁƒ8ŽsÊ^[[ÛÌÌLÇ»uëvøðá.]º06AOOÏÞÞÞÞÞ¾OŸ>Û·o¯««‹ŒŒtuu…‡p¤.·Yr…®]»nܸñâŋϞ=kÓ¦ <››·ÊY¤Ré«W¯ìíí#""`GDDØÙÙeddÀ_rDzÙÿTò-ÇvíÚ•ŸŸ?a„ôôtò=ž½O¹mز•oÛ¶ÍÓÓÓËËËËËkëÖ­J¥rùòåðq—+VØÚÚÚÙÙÍ™3'99™rE*??_,¿~ý:77—_Õ@,{xxlÚ´ÉÚÚÚÆÆÆ××7;;^Çn²c#&,@tt4åÖ #8Ž/[¶ÌÒÒ233333³eË–+W®d ÔùóçÁåË—Ù¾'¾|ùÒ‚²Á„£]«W¯vrrJOOOLL„_Át“U«V?~<00°¤¤äÑ£G-Z´¨­­ýã?àQîO)¦ÆŽkaaqíÚ5ÇçÎ˶‹Œ¸ûrïÞ=''§Å‹¿|ù²]»vðêêj¶Ôå6 *Œ;ÖÌÌlúôéYYY9ï¹uëVûöí¹-À®\¹;ýÚµkÕÕÕ‰‰‰|ŽeäSÉ7Æûî»ï  “ɾÿþûž={~ÿý÷€ïÕ(çe¶Œåð‡„¸ ÿð÷÷733ËÊÊÊÎÎ644\µjc5¼¢ëéé9~üxz÷½}ûváÂ…ŽŽŽp‘°±±Y¾|¹†Ž5Ó¬ˆ¿uë–X,îÔ©ÓŠ+à“Ú!yŸ+†a"‘¨wïÞÖÖÖB¡Ø½ƒa˜P(tsssww×ÓÓƒ_µ„B¡³³³«««H$"!ïeÜ5 ­Y[[»»»›šš’÷#°Kw’ðA7ΓÿÜÆ9†ôîÝ»¦¦fâĉpð0F‰l¿GÝ»w‡Í0víÚµ‰„¼Ë‘RúL?G»D"‘›››‘‘Ñ–-[ˆ‡2uhÓÌÌÌÃÃÃÞÞ^(Ž5êéÓ§Ä“ ŸRL;w.22ºðìÙ3ÆÍœ¢¿Cl1'–ºt³ä€+Àrú¹ÈØòrÊ)àl{ÖùØŸN¾ÑsŒ|Frvñì}ÆXQŸ §(„­œUr0¡ó;vtvv&—ó£ïøhß¾}‡´åǬÎzJ„B¡‹‹ œ«µâ*_8º“ò½D+'Ò9¯‰) ÃvîÜùüùs>»U¹í[ZZŽ?þÍ›7gÏžmZò12zôè5kÖŒ7î믿ÎËË»s玺ƵJêÓ;‘þ)ÙÔ˜1cJKKáÃ6€íÛ·ÏŒò„ñÊ¿*Íj^g­û©ä›ÊkZïÕàBXSS³‹-EÕέ|KHHhBï“«y{{:´[·nÄuÆÕbê"ÿ,„B¡­­­†FàU-~7'ÌÂËËä‹„:@+1!›²µµEs“ù´òMóÞÇÞC”°¥¨SñO-cÔÊ$­A è üD þß rÄiík›´›Ž›NOý°&¨‚5‡øV³bii) ?ÈÙá³%µµµäìtšÃí4Ýç'øèe]uÜ:ƒmfø€1¬­­ >È öÁ4Õ„-Ey [>2l°I[)›N[9µTÁšC|K+ª`¹².]º<|ø°®®®¶¶ê‚ò´ÃGëN%=zôˆŠŠª««khhHHHÐ\DM¥D_üñóó£·”ÿf•ÚiºÌO6%¶&œZ¡Z×6µž@cùºf•åûP- •ihhˆ%nXªDá§K@ —!¶…ð¶b±øÔ©S ÜÜÜ|ÅŠuuuÄyˆ.ósÊ”)+V¬ˆˆˆ Ð49àAAA púvpp¨¯¯W(ðIg##£êêj²|.Sðèn´2Ùf @FØ2!111))©{÷î}ûöÍÊÊâ¿…[Ã¡ÇæÛÜ®•µiË[ŠBø Û¿ \ XdØØà¶bÓ‘"`Ô ã('PK¬ùÄ·4TƒÐåÊ:wî,“ÉæÎ ö÷÷¯®®¦7–Í1¢-lZwÜ^fee-^¼6m÷îÝðÕ¬š„‹¨Ï!ÑLJ?„Ù”——O›6>l4ÑNÓM~v%¶&œXÆ©¹ IDATZ!ÿDmŽ”¼åët/˧›È[&ÔÖÖþðð±ûöíËÏÏçé&CßæÐä^†èG‘K8R”€{Øþ¯*|ó[ëÖ­nܸÁóü’’’1cÆïËqtt„¯ú422jÛ¶íáLJ Ò¾}û¤¤¤ØØXʱ¡¡¡‰ä‹/¾€ú*Ë ¼¼¼bbbèï`,gó`mmýöíÛÅ‹[YYEFF>xð€| ¹¹¹••Õ¨Q£LLLbbbè/˜'^—WSSƒaヺðQ_¶nܸÑÈÈh÷îÝð„¸q*­ã8ž——g``Ð¥K—””x.nLjˆíÞ½[*•®[·Žñål^ÕÖÖvìØÿ2~—üü| ÃEéD>ïäãadëÖ­7nܸté¹ë¹£”ŸŸ?dÈvíÚeee)•ÊiÓ¦(ÒM~¡›jrÀ#"" ߉' ”™™YYY ¯ õëׯ±±1<<œ~:]¦àÑÍ=ÙfÝ @FØ2!//¯W¯^‘Häêêš——G®ÓLCÍ޹][3*y¢¥T*évØR”@å°å%ÃÆ ]ÚŠCGŠ ]'Œ»°«q¨‚1z>U0F¹²éÓ§“Åöà¿ä;¯|¤¶Ø´îxj•A¾üòK©TJÜxÓ\ŒV- Pƒ†þL›V´Ót–Ÿ€¦Ä4 ¸JµB¢æ‡J •]ð¡dùšuòž ÞÞÞ™™™©©©ééé¯^½¢Ükî¡§@¶eˆ~”¯¯/‡ÆYÂ1lÿò ""bíÚµkÖ¬ÙºukAAATT¥6·Ž”““Ó?þxàÀŠŠ ø®[¬#GŽ@åÌ]»vÁï•”‰áJq‰­о}{¹\¾téRJg³•³yö÷÷×ÓÓÓ××ÿóÏ?‹‹‹É‰‚a˜··wuuu}}½Å±X¬P(är¹L&«¨¨ˆŠŠ¢üèþñÇóòòòóóëëëkkkóóóóóó ½oÈ7îܹ#‰ÈƒMå8äv СC‡’’’cÇŽÑ?âãÄÕÕµ°°ðäÉ“DL4 „c4ª*£û¹{÷î•+Wè§ãöÃ0ssó•+WFDDÔÖÖ>}ú”QVPgù ˜¦?MþÛo¿•——{xxÈåòñãÇ÷îÝ[.—O˜0áÍ›7üñÙ‡•*»@0Í Í:T§gÂŽ;JJJ8pðàÁ·oß«Ü<EØlòÐc\çv gTÆeˆ~‡¶YÂ1lÿò`ÿþýðv`ìØ±2™læÌ™äˆ,Z´hÍ{œœœèW¢á±?ýôSmm­µµµ¥¥ecc#”±ôïß_.—SlîÝ»Çè[9hêDC÷üýš ÔÚîÔ©ÙÃ+W®„„„ܼy“.Ð*‹8ðÙgŸ±=,xÿJɸ¸¸°°°Ï?ÿœò’@__ßÆÆÆ]»v­]»öàÁƒ …bëÖ­#GŽœ:u*}/ØTé ,,,++‹ñÍÂ*½‚X[[?þ<..޼û@“pA8F#w‚1ú°±±©®®^½z5c§«ôG …Bww÷‚‚Æ :ËOÀ4ýipx/ðÈ‘#b±ÞÊÈÈ8zô¨B¡˜?>ÙȇM î.hÖ¡Ï _~ùeó @ *Õ- ÐÐÐðõ×_ …B@°~ýúêêjÊ%æzt8æv gT¶eˆ~£¶Y‚€cØþÕ6œS† °ëH±I[åää°éH‘aÓ ãÐSW¬9Ä· ª‚±É•…‡‡Ú¶m hݺucc#!8©Ò1n­;•^AŽ;fhh8eÊòCBÚ£À-TÆèÀÕÕÕÀÀàÕ«WŒý5ÔN:ÉO4 8µÂ’<»àƒÈòeff‚f€@}M>'''¡PøâÅ ØYYYvvväÛ`Í7ôè4ŸF Û2D?ŠÑÛ,A B–’|µ½OŸ>W®\©ªªâù¨Š¥¥eiiéÍ›7mlllll¢¢¢222à’\RRâíímllü矾yóÆÌÌŒrxqqñÎ;é_ÓˆrFý°ôôô£GÒb,çð0:::::ºuëÖvvvOž<¡Ü;!`ŒÜãÄgwï£GwáÂï™3gÊåòÀ/¶ QQQ¶¶¶NNNÉÉÉŒ»éëÒ¥ËÛ·oOŸ>íèèhÿÆ;¾l^‚ƒƒ+**Fíàà-èëëÍÂiÚ 6sæÌQ(®®®'¥dllœ——Û½{w à TXXxæÌzstŸô_„<66jàÁ3ÂûÐ/_¾d»4¤Ë”àßl Ô|²Í º€P2ÁÉÉI"‘\¾|ÙÒÒÒÚÚ:<<¼¨¨îØTéÙ¦¶îö¹]Õ{¢E.á˜%؆óÿ< ®¶WUU=þÜ××—O†A|||^¾|YWW'•JÓÓÓGý³´´¼qã¼@Ÿ““C×(?~éûYÉå'N”Édƒ "×9räÈ‹/è!f+góÐËË –××׿zõjðàÁüïló‡p©ã®C¹ѯ_¿çÏŸCÇbbbø¿€xÍš5Pü ö&„19¼ª©©ß  _~ù%†aš„ Ò´ÑÈæ`É’% …ÂÉÉI-ƒ€Þ¿¿¾¾^"‘H¥Òëׯëådt–Ÿút£aÀ÷îÝ+•JÛ´iÿmÙ²å»wïN:Åæ€ŽS‚Op •È63è`r@É ÃfÏž““#•J¥RiVVÖ¤I“t3ôýìs»†3ª&ËÇ,aÎÿCôwèWÛ¹ÁX¤­‹ŽY'Œ­œQ?L]U06±­ Fö‹KÛ¶mÕêâ¾¥CÕr†n: I¸Èî©{›?„Á&x‚ñÐNÓY~’ÛBw²É§lB2j=%øt·Kš@î™áC @ŽLèÔ©“.‡DZŒs»†3ª&ËÇ,aÎZÃ0F¿ÙÊ):alålRpMPS×ÃÎGëÕÇéXÓ`k‹îó“ÃÃ<àzøÁ[Ç13èÞ>¶Lø„fT¶áüá¡è„±• XôÃH Ñœ üD þßÀ6œ?bË:íf#[îé,'›•‘?~|LLÌãÇŸ={VVVHž¦5ïw> Ù½{w¨ó7xðàï¾ûŽ¿lþÓ5jÝãX ×MâATmÍ{ÜaiÖù pÎZG“¶hY_"p%"## wìØqæÌ™ŠŠ ©TJù©«ce5íj¿6ßæÇ}¬¶dÕM‹KCY5L3¹8 J• èDíÃ0ÆÜc+çÙ:þ9 š¤?Ç]®2£¸åE5ì÷&ëüiè?ý(;MÓ¥Óî4¨rhë~Þc KóÍo Ô¹Ëù´…íê«Ñ®LMMþùçëׯïß¿÷îÝ•••”èRY h[û°ÉöZ[Ȫѵ¸4—UÈÅUªl@Wjl¹§›œê뽩,çö¼¨&ýÎ3!1&P ýon]:í&žÊ¡ÍÝ(JòñÒ´ù h[Qe9Ÿ¶ÐùËŠvõÕèW‰dãÆ†á8RTTD¹Â«Ke5FšUl¯YeÕ t-®ŒŒ ÐTY5ÍåâTª²]©ý±åžnr¨¯÷Ƈ¦éº§Ö¤ß›¬óG¾,öqêÒi]f’{hsÇA7Š’|èlÞS–æ˜ßøÌº¬4“¾™C‡ÕÕÕUVVÖÔÔ:tÈÀÀ@ ÿ´ª¬Fø£]í7ÐTÅ/­Èª±iq5YV h&ÇG•Mgjl¹§ãœä  8ÐP׿s$$›ÎŸüo².ÖÿÐfCŠ’üiÂüÖêŒ*Ë›N3é«‘îîî-Z´hBf´§¬Æfûpb{š¿]Dú5UV8¶irqªl:Sûc˽''Ù2§ÉE »Îúb„Q£T%úÏ6t–xšm-æ˜Ê°4Áž‡pÏM>oÓF+cÇŽÕ™¾ZVƒaØÇ鷺hØ¢æÈQ£dôäÿ_wk Í#óަGfñqñüùs¤¯†Ð1HíñA@‰‡`é«!tRûC|Pâ!iö ¶¶¶b±Xeù·ß~Û¢E‹ÂÂÂãÇÛØØ0‚@ ÄÇ‹¥¥%ãÃ4 óæÍc¼A. ‹Å? …l‡ Ñ,h(Æ­=ÆSL(Þ¼y3>>^(òÔC B;h(Æ­=†ñ … !Û!@4 š€ñÑã)F,„‡ ¡]þ÷³¾çÍÖÖªŠ@°Ž;Ž5ê‹/¾hݺµ¥¥%½jݺu ¾ ®=HB_”U­œû#@ ´È_?ÝÆß³gO@àääTXXH€:t¨¦¦F©T¦¦¦~÷Ýw‰äàÁƒä’ƒ*Š=züòË/ÖÖÖmÚ´™3gŽæ`ÜÚ`@h‹¿ÂŒŒŒÛ·oã8nee5cÆŒ .x{{Ÿ?¾¤¤äúõëzzz_}õUhh¨R©,..¦”*++ããã­­­G M‘OóîÝ;333úéÙʹ?B B[üµfffîܹ®j‘‘‘×®]óõõ=s挟Ÿ_hh¨±±ñÌ™3CCCq§”ÀÃssseee«W¯Þ¼y3E‰˜í-àoo&¡@ Èüµ6YŒöh’ÇG@h‹¿Â& €ñÑ<Àèžq|„@ „6ÑPL¥ö0ð÷Ç'ØA BûhEÀŒC{ŒøûBÈv@ )lÚc<À²²²žB.]º´dÉnzî:NNNúúúÍãÝ`þüù×®] …äB>Q¢ckkK/´´´´´´¤—ÛÙÙ©e@ >9Ô›C›•~ýú 0Ã0€žžw}OOÏ:Ð˃‚‚ÄbqFFFyyydd¤‡‡´™••U]]]]]]QQ‘ššºyófu—íBn¯J\\\¼¼¼(•ùD‰àðáï_¿®®®~üø±H$"Êû÷ï—ŸŸ_TT”˜˜H„køðá/^¼ÈÉÉ©¬¬uêÔ€ •J7lØð×Br{UòË/¿¼{÷޼€~Q"˜2eÊŠ+""" ÈvRSSccc»uëæêêš’’- ÍÍÍ_¿~îèè8yòä·oßîܹ“|®‰'666â8N,œñi3þüààà   b^?~ü¾}û6oÞܳgO¢pÑ¢EüöÛoÝÜÜV®\)ŒŒŒúöí ë 4hãÆÄ¤I1¢§§йsçeË–í߿ٲe°æòåË_½z•••õã?ÚÚÚ®]»vôèÑÄI'Mš´{÷î;vx{{…ô…P__¿´´ôäÉ“ðw†aC‡•Ëå_|ñ†ab±xß¾}B¡Ã0@{ëÖ-ú:DqxܸqfffssóM›6Aklñ™2eʾ}û~ýõ×^½zaÆJ{9¢½ÿ~??¿_ý•¾Qb‹*ØêÇ“B›ððð±cÇ  ömÛVVV&‰|}}år9üÁŠaرcÇÒÓÓ‰Xéëë¿xñâÑ£GJ¥’²BO\]]W¯^}ðàÁÅ‹ ‚aÆýþûïÖÖÖÜ)‡@ †sçΕ••]¼x199¹´´^ìZ·n]MMÍÍ›7?~üöí[OOO ÃöîÝ[__ûö퇾~ý:77W$ÙÛÛ744“ïÆëêêàTK7bllÜÐÐðüù󈈈۷o×××:tH ìÛ·¯   ¸¸øêÕ«íÚµ+))!~‚üú믕••ׯ_ŒŒ¬¯¯Ÿ3gœ7é aÿþýårùüùó‰B úvíJü"Ü·oüÈÎή  `ÿþý”ƒîp÷îÝ+** 3;vìH$îîîlñ ª«« ‹ŽŽ–H$#FŒppp` ¥½ß}÷c´îÝ»÷ðáÃ’’’ÊÊJÊBX\\ 322bŒ*½¯:DùE¿À¿/\¸œœ, ýüü q×póæÍä³½yófáÂ… …‚²BOÒÒÒÂÂÂ?~,—ËÏ;—••uóæÍ²²²ØØX¸š2¦œÚ‰‹@ ZA__¿®®. @OOÏÔÔ466vÍš5mÛ¶-//ß¾}»žžžP(LLLüïÿÛ¶mÛÊÊÊ}ûöÁÂK—.½yó.„2™lùòåpæýÏþS__/‰èFLLLd2Ypp0,qâDò¬Jü-‹óòò=zôøñãÒÒÒgÏžÙØØCÁè°H$ H$cÇŽ•H$?ÿü³P(d¬éììüîÝ»mÛ¶Á˜˜˜Ë—/·mÛ–18äö2ZƒÑ&uîÜ9‰DBY‰1F•ÞÝô…УG°°°ÄÄÄÒÒÒ1cÆ`6f̹\îëë £wàÀâËM—.]***,X0cÆ ¹\N_e2Ùž={ 'ÏŸ?¯««ëÕ«—H$Z°`\.÷ôô400 §Ü‡½_‹@ þɈêëëSSSá¤výúõAƒ)•J___‡àà`ÀçŸîâââááahhxæÌ¹\Žãxyy9·i///º8iæææ* ¥R™maaP*•8Žã8®P(p'Û™3gNŸ>}fÏžmll,‰ÌÍÍù4lÞ¼yÄï¿5kÖ@222n߾㸕•ÕŒ3.\¸àíí­P(8Æqü§Ÿ~3fÌÙ³gsrr cM///ccãŸÅ‹(•JF÷Èíe´F‰vnn.%,tèQåIeee||¼µµµ££ãèÑ£oß¾óÛo¿¹»»ÛØØÀÕVÞºukBBÂñãǧM›Æf0??z’™™i``œœ,—Ë“’’ÎÎÎ111ô”c @47À„ ®]»6eÊ”øøø;wî8::ZZZÂ[J-[¶lÙ²erròƒlll0 ã3#C,,,èF(Ç*•JîŸzzzgÏž ›:uêÀ¹ç÷êêj€¹¹9†aW®\qww÷òò …Ä ÌÌÌ;wîØ±ÃßßÑ¢Eýû÷'~ôp8¬T*}Úä@©m2*£J!77700péÒ¥ÁÁÁ ,°´´ÄqÜÇÇçĉ...UUU§NjlløúúŽ5êåË—«V­|¸©©i·nÝ|}}áÏF#_ükkk-,,È !†™˜˜˜˜˜øùùyzzrüÖ©©©9zôè´iÓV¯^mddôùçŸÏž=[ TUUÁ zzzöööööö}úôÙ¾}{]]]dd$1ƒ³9¼k×®üüü &¤§§ïÞ½[ 0Ö ÏÉÉùöÛo---;uê´cÇŽÁƒ7440‡Ü^ŽhûûûÛÛÛwêÔi„ ÍqM,{xxlÚ´ÉÚÚÚÆÆÆ××7;;ûÍ›7www …B1}úôqãÆ]¿~ÇñmÛ¶yzzzyyyyymݺU©T._¾|ûöíj]ØdL¹æ[ìB†­]»¶¬¬¬ªªª¾¾>&&ÆÑÑ0|øð´´4©TZ[[+‹ÿýï ‚3f×ÕÕÁÍ&yyyðªãôéÓËÊÊÊÊÊŽ9ÒÐÐËéFŒe2ÙÚµká´îïï/“É`åY³fÕÖÖ644tíÚµ¬¬ n9åryccã;w®^½Jìãg|ŽP lÛ¶ííÛ·µµµð¤[·n…öÅb±B¡Ëå2™¬ªªêùóçäe BwxýúõpΈ#¤Ré¦M›c|ÆŒ“-•JëëëÃÃÃáf¶àÛ;bĶhËd2‰Dãro–aŒ*úfŸ—/_ÖÕÕI¥ÒôôôQ£FÁ/+‡ª«««¬¬¬©©9tèÅÔôéÓÙ6Ëž„„„¤¥¥Áþrss“Ëå . …Œ)‡@  @```гg϶mÛÏŠa& ÝÜÜÜÝÝõôô༆a˜H$êÑ£‡‘‘ÑáÇá®QXn``ЧOsss@@̳ŒFàžIâÔäÊmÚ´quu……D¡Pèìììêê*‰„B!á!¹¥9-[¶ìׯŸ««+qRXŸ ù±ºÃÐX6Ÿc|„BaïÞ½)‘d Ñ^Žh÷îÝÛÚÚš|§“€¶¨ÒƒCùžº}ûö:t Z k:88¸»»·hÑ‚1ÎÐ=z )}GŽñcÊ!v&*Á IDATĆñ¢%|žš±æ¡C‡ˆ…ÛÍÝPi§Éû/øË>…”rþÖ´[“›õìhƒ øøß2Æx“†£°¢¢‚²k†í6Z·ø»Ñ;Z?VÝ q—k«íM@+}§­“"ħ@ @µ@ ⦹~Ò999á8Ÿ¡F âÄ?üPTT$—Ë¥Ridd$Ÿ÷)«¥Ì§ÅcÐ2?ýôSmmmPP««ë„ óòòÚµkǽP©¥Ì§Åcøký˜?þ‚  ——÷îÝ;X8~üø•+W0àÝ»w%%%°pÑ¢E‹-êØ±cmm­¯¯/|5üÈÈÈèÔ©S—.]Z³fMIIIFFƽ{÷þýï·hÑâöíÛ-[¶ô÷÷—J¥EEE€AƒÍš5+::zÙ²eðÅ+ð+YYYË—/Ÿ5k–¥¥err2ŽãFFF*MKK[¼x±‰‰Ivv¶®£ˆ@ ˆO õ ;P髯¾"~ÿavïÞ=¨BÇ&[HVæëÖ­[cccFFFDDDtt´\.ÿå—_Ÿc¡Š!|Ú #@ >I4×#$LAYs///ò…Ðÿþ÷¿Pë•M¶¬Ì_ÀFœâÌ™3oß¾µ²²âs,ùÅ%@ð¤õyBW"$tõΜ9óÕW_¹»»¿xñ‚ϱr¹\+.!⟃6õ¡ÈC«V­È…æææuuujùDØÏÍÍ¥D B‹\\\|||~ýõWww÷tìØñ?ÿùÏëׯ¡BÞìÙ³gÍš5sæÌ5kÖ@=B¶- qqq555C† !*ØÙÙ¹¹¹%%%á8Î&[ÈAÇŽ………M8@ ^tïÞ½®®nË–- S§N………444LKK{ðàAëÖ­õõõçÎëããcffVTTô矚››·k×îÅ‹„ ÁîÝ»«««W®\iffÖ§OŸû÷ï—””téÒ.¯^½Šˆˆ077ïÖ­Û«W¯ááW®\IMMµµµ…"><°²²²µµ}øða^^^Ë–-ù X½zõèÑ£Ñ3…P­è‚½{÷J$’ÆÆF™L–˜˜8dÈb‹Je>www¹\þàÁƒ·oßJ¥R±Xm²ª@ º ™ô…B!º¼‰@ Ñô• >É®EWšÕ,Olmmkjj>ÔÙ?N´¸1Eø‹†¹¤§§çïï?dÈ;;»—/_ª4‹†3‚'ÿ[õôôÚ´iSYYIþøÒ¥K‰‰‰.NóçÏ ¼pႺv´å€JôôôΟ?ïêêzçÎ&œK?uÖFuaŒ ·Ò$Û§„©7666Âw©kÑOzêþÿæcÈ·&؉ŒŒ”ÉdMî}CCÛ7oÚÛÛWVVÞ½{Çq¶a«ápæ†q}µ´´ …Z·lmmm``@-‰]uu5݈ºålXZZ¶hÑBÝסð±ÀÖ"¶ª[¿‰ØÛÛ_¾|¹¦¦F&“oÞ¼™¸8ùçŸúùùñ¿VJ¿dºeË–ŠŠ ¶5”””ìܹSK·oßž””dccÈÊʪ®®®®®®ªªÊÏÏ íÕ«÷~•~fdd@›‰$++ëàÁƒ–––ð#uƒ¬3È1ª”&¹?%LMš4éíÛ·¤ÄÓÝÝ]"‘Ìš5«²²rÅŠ€è…ŠŠŠÔÔTrZp¤.äáÇUUUÕ4ú÷ï€g¤|zàÀ²•ùpéÒ¥çÏŸi›’’BüáááAi ût>†|kÂØäÙûýúõcŒÜL÷Ýwß3 %E Ëùd‡~ýúuuu5å±±.]º<|ø°®®®¶¶®Óümr[4hPBBBCCCCCClll·nÝ`܆þâÅ‹†††ÊÊÊ£GÁúê–Ï;—œü=‚IÛ¿ÿ¸¸8©TÚØØ˜˜˜èááAî/CCÜœâÁ6ÈÙ³g«ªªˆQÏf­El1T·¾F\½z5;;{øðáæææ+V¬¨««ƒû6úw좣£ïÞ½K_ùå—wïÞ5a!,--ݵkWs/={ö¬®®&ºV,Ÿ:ujÀ€Ó¦MKJJJKK355ÕÄÏ‚‚hÓÓÓsÅŠÇŽƒú8o‹Rb­4Éý)Ù†a×®]{ðà%Iú÷ï/—ËçÍ›'—Ë׬Y#ˆ^}ú´k×®iiiçÏŸgÜ<1f̘aÆ1~¿a³œ˜˜˜””Ô½{÷¾}ûfeeݹsG(š››¿~ý:<<ÜÑÑqòäÉoß¾…_GÔ-”––Ο?Þ¼yóæÍóññ¦ÂUÇÕÕ5%%%::šÜ¢Å‹çææêéé%'NlllÄqœXðØ,0¶ˆ#†êÖ×±Xüûï¿CCàÒ¥Kþù'üwíÚµð]-zzz®®®«W¯>xðàâÅ‹Á°aÃ~ÿý÷ÀÀ@kkkhв.Z´hÿþý~~~¿þú+y!?~ü¾}û6oÞܳgO"3&Mš´{÷î;vx{{…Œƒ :Ó¹sçeË–íß¿Ÿgb4>sæÌo¾ùVðððøöÛoáß;v ìÔ©†aüñÇ«W¯÷Äbñ¾}û„B!œ¸Ç'“É&L˜½?~üï¿ÿ¾wïÞ‘#GÒý\´hq:Àüùó—.]* ›àرc™™™ŒAfk×ìÙ³<øý÷ß·k×. @—1122‚ï1€†bÖ¾}ûŠŠŠ={öîO”ðNž<¹±±‘ü*>ÀÀ%IçÎá{0 #÷‚@ ˆ½uë%Ý9R‚½>íŸL¥LFDvíÚ8q‚~Ž|Œ1N܆-Y²¤®®®¼¼|ãÆà‹/¾ËåÓ§O÷ôô¤4§ý3ßmlRrlܸqfffssóM›6}ñņñé}¶XQBJ^°•sgÔ_|AùD)G>|˜¼\uîÜY&“Í;>ñåïï_]]Íø?&&ææÍ›Œó5£e@mmí?üÞ·o_~~¾H$‚"? €ÙrìØ±ôôt¡P¨n9`ß¾}IIIİ…-µ±± ;v,lѶmÛÊÊÊÈ^Ý»woß¾}D¿ëëë¿xñâÑ£GJ¥.„[ÄCuë“¡w(@~~þ!Cà÷w¥R9mÚ´ &( À·ß~;jÔ( Ãôõõ7lØpñâÅ‘#GöèÑ#88øìÙ³trrú÷¿ÿ}õêUzïÝ»wïÞ½;vœ:uêœ9sˆÀ­[·îܹsmÛ¶>|ø;wàu’_ýõøñãNNN½{÷¾uëÖìÙ³9 ™8qb»ví~ûí7âZݸ››[PPÐçŸX²dÉ/¿üêäɓ׬YSUU…㸗—W\\œR©$ŸOMM †a0Ð6løïÿÛ¡C‡®]»^»v~‰©GÛ¶mƒ/ 722Úºu«»»;ŦR©422"n¤Q‚ÌØ®~øá?þèܹóðáÃÃÃÃ7mÚD9o³ÆdàÀfffáááPåÇñ¬¬¬çÏŸÃ+!ÜŸ(á •H$pZ$ü÷îÝž={ŠŠŠöïßO¾í ÚÚÚ:88Ð_øÎ‘º”Ndü—R¸{÷n©TºnÝ:²î|€DDDH$8e4(33óåË—0±ûõëרØÎÖÀO4ß(Ðs¬  `ÅŠðÀ7®^½Z,óì}ø-Š#VÆaËQNŽ 9£ÌÍÍ;vì8jÔ¨/¾ø¢uëÖ–––ôðþù.Š3;wÆ0 ¾œÇñ¼¼<⥒d[ -òòòzõê‰D®®®yyy8Ž[YYa–‘‘ÏXTTÔªU+ ÃÔ-X[[¿}ûvñâÅC† '-))3fÌ­[· KŽŽŽb±˜ð­sçÎýúõ;~ü8Q²qãF##££G%[ÄCuëC»O5ƒÎÊʪ¬¬ ýúë¯?ûì3â#âKü.¶gϨøüù󺺺^½z‰D¢ Èår¨ÜKü"„7´ƒƒƒaýsçÎI$‘Häàà@W: …§OŸ^½z5,Œ ƒ++ã/Bè aüèÑ£EEElƇ*—ËLJaXnnnaaáÏ?ÿ =Àkↆ†R©”<ÔÅbñáÇ۶mkooïååõæÍ {{ûòòòßÿÚ?räHqq±••ÙO™L¶råJ@0þ|…B1bÄ à ¼þ“¿‡††&&&¿BÈ TiÿcÎ7²Æ‰D‰dìØ±‰äçŸ&º[eï³ÅŠü‹1¯lå€=£þõ¯UUUÁ‡˜—,YâëëK)!¬:tˆü»múôéää‡ÿ’oª9rýúõþþþ™™™ÉÉÉ6lð÷÷§ß%¥[x{{gff¦¦¦¦§§¿zõ ~³3fŒ\.÷õõ…8UÊÕ-DFF644¤¤¤äææÖ×ד¯B÷èÑ#,,,11±´´t̘1„·¿ýö[ll,ád—.]***,X…üÈ g´ÀØ"Žª[žšÞ¡*/€ QQQ}ûö Ð××ß»woll¬‹‹ ã²üü|…B¡P(233óóó“““åryRRÀÙÙ™\³_¿~„x¡B¡ ¾Ë{yyJ‡û÷ï‡J‡€9sæÄÄÄÌž=ÛÏÏO$™››sû ÞË*Šììl8+1ŠŠ*((l»££ãˆ#†êååUQQñæÍžíêÝ»·¥¥å… d2 þ‰IÓ`4õîÝ;xÑŒ~)¿Ègdd\¾|ùÂ… ÇŽ³²²ºpáåÂÿÔå¦C‡!!!W¯^eüýÁ˜ä ;wvwwoÛ¶í­[·®\¹bff6f̘nݺÁß4Œ ä¶ÿñç„1Çpÿé§ŸÒÒÒΞ=›““@üÎVÙûܱ‚°¥(wê2fÔùóç}||ŒŒŒ,--gÍšuèСsçÎQJ8<áÆÓÓséÒ¥K—.µ··wvv^²dÉÒ¥K)[ÉØ˜0a‚±±qdd䃬­­áí°°°˜˜˜ß~ûmûöígΜ!®þ©[xñâE```¯^½:uêtïÞ=òBXYY/‰ÈJ>>>—.]"¢±uëÖ„„òDF Œ-R7*ãFïP•Ý'à8¯EìÝ»·W¯^W®\Ù¼yóôéÓ/A 6/l<¼ä5≠lâ…Ø{¥C@rr²X,‰D'Ož9räãÇkjj,,,JJJT¶–@©TÂþc4®T*ãââÜÝÝŸ>}zîܹ… 0ÀÑÑ144”íªËáÇýüüÈÃÇq(ÓXXX*..÷G!8Ž_¾|ùûï¿·³³4hбcLj>¸uë´iddùÃ?x{{s™hWëÖ­ùùùÄ)t6¥I¸pÊŸ&233wîÜ yíÚ5__ß3gÎ/uª›ºŒìÙ³§ººzíÚµl2æ¹BTTÔÊ•+.\XVVvûöm¹\ž““3iÒ¤6mÚØ2ÊÏÏ/44ÔØØxæÌ™pPJØ 2îÝ'?>øã?¢££%‰TW950àßÿþ÷’%KNœ8ãøëׯ¿ÿþû“'Oæååùøø¬[·ÎÕÕµ°°ðÔ©SsçÎà8®V9`ùòå¥R)“É.]º4jÔ(—ôôtÇssseee«W¯Þ¼ysiié”)SÌÍÍOœ8÷õõ5jÔ¾}ûV­Z¿€Nš4ÉØØ>²B·àââÂØ"¶²E@eÌùwhèСüñÇ‚ îß¿¯T*Ÿ>}…5Ž„N:‘¯/rrrp?yòäÍ›7a9Žã£Gžãxhh(åºO+•ʈˆˆ-[¶XXX„„„<~ü877wݺuqqqð¢¹L&£\GV*•r¹œ’¬ÙÙÙ8Ž÷îݾ[®{÷´4ŠÇ_¿~ýÖ­[ŒŒ`ÂrÇáH$ñññä½ÜÀ)ÉÙÙùÙ³g$&„Òä¥K— ¨4yîÜ9ǹ?e ¯™™Yaa¡Jç¡«°ÒÒÒ0 355Å0 žÅÛÛûÈ‘#š§îÊ•+‡ âëë[^^ÎV‡1Èܹs§¦¦føðáñññp‹‰‰6l˜R© S9õÒùÆ–c=zôX´hQDDļyóΜ9óôéSø)ÏÞç†1¯8Ê!låçç'—Ë ”J%\³é%ŒdddÚ¶m hݺucc#\K`âtð—üqϧNNNB¡ðÅ‹0²²² ìììòóó%ÉÆá@ !^u©nùÑ£GoÞ¼yñâEÇ p¯ªªêÖ­[PPÐæÍ›ãããáøÕ××oÙ²eiiéŒ3îܹóîÝ;衃ƒCBBBß¾}FFF† >¼¼¼¼¤¤ä§Ÿ~¢[`k¼ä@á¤I“ÔªOe<»@ðôéS‘Hw{{yyõïߟüÖ†¦qïÞ½ÒÒR{{ûN:M˜0~Ù¼{÷nVVÖªU«¬­­õôôfÍšwÇafbbbbbâçççééÉxIW¥Ü ›ñk×®éëë;;;Ÿ?^¡Pܽ{wذaÄíôÚÚÚ¼¼<(>ÅÍ­[·ÒÒÒÖ®]kggçàà°råÊÄÄÄ'OžP¦¹âââ»wïN™2åÉ“'©©©Œ“`}}=ܫ‡øøø7oÞøùù999µk׎¸Ü¯³˜”——Ÿ8q^¸†J“§OŸ655=xð ŽãÜŸ2†×ÖÖ633Çñnݺ>|˜qs@OOÏÞÞÞÞÞ¾OŸ>Û·o¯««‹ŒŒtuu…‡$$$°¥.·Yr…®]»nܸñâŋϞ=kÓ¦ <››·ÊY¤Ré«W¯ìíí#""`GDDØÙÙeddÀ_rDzÙÿTò-ÇvíÚ•ŸŸ?a„ôôt²>ÏÞ§ÇŠ\È6l¹‡3cFá8žŸŸ/‹_¿~›› kÒKIIIIJJZ´hQ«V­œœœfÏžýàÁ¶×M¨ElllMMÍúõë-,,¬­­-ZTZZ ¿L¸»»[XX(ŠéÓ§7îúõë°ÓÕ-wqqY±b…­­­Ýœ9s’““KJJŠŠŠ<<<6mÚdmmmccãëë›ýæÍ[[ÛaÆ>}šøº¶mÛ6OOO/////¯­[·*•ÊåË—oß¾½°°Ñ[‹’““c¨n}rôxvßß8pàýû÷ëëë%‰T*½~ý:qù…r_ظ’––oظ¹¹Éåò…  òãP¼P&“I$’'NÀÍ2€IéP(^¹rE.—766Þ¹sçêÕ«Ä_òf™ââb8œ(ÎøûûËd26ã°NTTT\\´9dȹ\>þ|bd9räÅ‹Äý'¸Íšq12dHjjªT*mhhxõêÜ” h›z¦M›&—ˉÇp;;ñï7ß|#“Éàƒ"lA&·ËÇǧ  óîÝ»J¥–ë,&‚¿+M>~üøÝ»w=‚’ÈÜŸRL;V&“Á ô'N”Édƒ bÜ¢¢P(är¹L&«ªªzþü¹¯¯¯@ –ºt³”Í2Dx9þ “½'11qÊ”)„¶| œeïÞ½R©´M›6ðÓ–-[¾{÷îÔ©SŒ;æÉÇ~ŠùFñžcëׯollœ8q"†a#FŒ 6°ðì}ÆXA™6ÂaJ^°•³eÇ©éз´ôë×n„z®pO#ý@¡PÈý¬Å2†a³gÏÎÉÉ‘J¥R©4++kÒ¤IØ{基ººÊÊÊšššC‡Ô*÷òòzùò%ôüÕ«Wƒ†ö}||`¹T*MOO‡{Œ7lØÀøP „²c…ÑG‹c¨n}þÈ †aB¡ÐÚÚÚÝÝÝÔÔ”Ü[d…?òßäNÅ0Œøˆ^Þ»wokkk¡PHî`ºÒ¡P(tvvvuu‰Dd#lÿü]žnœÃaHïÞ½kjjà ¥gŒU=ºwïNV[¤²víZ‰DBÞåH©}¦ŸŽ£]"‘ÈÍÍÍÈÈhË–-ÄC™:‹ )MÚÛÛ …ÂQ£F=}ú”x”ãSŠ©sçÎEFFB÷ž={Æ8ºDn¼¤–ºt³ä€+Àrú¹ÈØòrÊ)àlsûàÓÉ7zŽ‘ÏHÎ.ž½Ï+ÊÊMOQ[9[F©½—aÛ]\\ žk“gd6Ë;vìÔ©¹÷áN]ww÷-ZPzY­r¾³³3Ù>,oß¾}‡ˆòëׯ3>NJ¢ÒG‹Øb¨n}í esœ6á‚Ï]¢ÉIÕ2…aØÎ;Ÿ?Îg·*·}KKËñãÇ¿yóæìÙ³ZxÙÁ{F½fÍšqãÆ}ýõ×yyyÄø£­˜Pr‘Þ‰ôOɦƌSZZ ¶lß¾}Μ9j9Æxå_•f5¯À³ŽVŽýTòMeŽ5­÷‰jp!¬©© ÙÅ–¢j g­Ð“'a™Ñ8ÇÔªn9›}r¹Pýñ´¬‰‡jùƒP |Šnûöíêv6…/¿ü²²²2&&ÆÁÁA[¾¦Nš’’RUUURRªKªÐVLȦž={F¾+`Q`æ6¥ò•u4¯À³NsKæÓÊ·„„„&ô>¹š··÷СC‰wN²¥¨Søg! á=-M€—´øÝœ0 //7ù’NÓÐJLȦlmmÑܤE>­|Ó¼÷±÷%l)ªÅÔE @ðÀÎÎNs#ê~ƒS«¾µµ5ß—ÎqÖ744$txÂÓOÊãÒÜØbniiI¨+ð­¾¶Êu€ºËcÙ,³•«;Ô &›}¶äa³£¹ÿÿ_Óõ#Lo„.ÐP¦‹MìŠ?Œr\~~~t¡8xÏœM¾‹M^‹MÔŠ€"¦ÅQÛ¶mpû5ñd¶ó²ù !ËzõèÑ#**ª®®®¡¡!!!ð„Í[ÌUÊtQZÊV_[å|Ð0ýTv®JÔUƒSW%Ž-=Ô &›}¶äQWã{ ÿÒõcKoŽ9¿¾h"ÓÅ!vEA]9®V­ZyسgX,†ÏÞ²Éw±Ék±‰ZAèbZlõW­ZUYYùÍ7ߘšš4ˆx˜í¼l~BȲ^±±±III½zõêܹsJJʽ{÷à-pÄœ[¦‹ÞR¶úÚ*烆*qÜK -58¶ò&¨¾©LûlÉ£–Æ›ÊüOH×-½9æ@JMŽôFðE™.±+ Mã"nŒ0 ¼¼|Ú´iÒËééõ嵋¨üˆ.¦ÅQ?--íÔ©Sp. Ûg;/›ŸBÖËÐÐ0++kñâÅðŒ»wï†ï_e³Àsn™.zKÙêk«œÒ^6y0 Uâ8:—Œ¶ÔàØÊÕU}S7˜löÙ’G]7•ùÿ}º~œéÍ6òOoþ×ðUx­[·vpp¸qãŽãæææVVV£F211‰‰‰ihhP*•”kkkì½Ø€,vE>cËèþz9ücëÖ­7nÜ ÞzÎVŸ×²²²‚/,‡åŒ¢Vð#(¦µ{÷nøÆ<ŽúFFFmÛ¶=|øð!CÚ·oŸ””Ë}^6?Á{Y¯õë××uìØÿÆ}—üü|ât d1rÌÙdºRRRp§·”­>|®æåð¼z"ÑÅš–~oß¾åè\2MH?6Ë*UâÀßcz¨|¶Æ–<É ®ÿÿtý8Óg™ù§7‚ÿ“ŒïÙ³§@ prr*,, T*•#GŽ›uËÉs˃59ý84Û e­«ÁµiÓF-•8À’–ê“{ Ñ“G]7ÿÿ!éú¦7<œcÔpvEüµâÈt±‰]Aš,Çquu500xõꟅQ^«wïÞB&Q«¶mÛ2Ši1Ö‹‹+--uvv†ç255@i.Æór8L‘õ‚;vÌÐÐpÊ”)‰DeKcÎ&6räHÆ–†‡‡3Ö‡¤y99Üò`MN?Í6xv­«Á5A%Ž1=Ø4Õ8‚É1ÐèÉÖ loþÿCÒõ#Lox8ǨáìŠøb±øðáÃmÛ¶…2]W®\òŒäK”CÈ%îîîVVV€™3gÖÔÔlݺ•ñ¶í£GÈÛ¥èÐõMsæÌQ(®®®tèõ££££££[·nmgg÷äÉ“ÄÄD¡Pèää$‘H._¾liiimm^TT_/|ÏÌ™3áÆ6Žú€ààà’’oooccã?ÿüóÍ›7ffflçeóÓÖÖ¶²²rüøñäWTTŒ=ÚÁÁê¥Á;l-eŒ9†a QQQ¶¶¶NÿÇÞÛGW]]ùÿç“„o¡4Š4÷PXQÁè ‹1fCÐhq‰„ªËd\ f0]²|¨´#B°P‡:Â/ Ó >aiQ@ ‰ σˆÈ"D’ä~~òñzÏyïûÙŸœ Îû®º9wŸ}Þ{ŸOžï«[·Ï>ûìwÞ‘o•«=)Zo*®¶Xû=±æŒѬ8qÇe&vDA;ÌDùµÃƒòpë¿tƵŽ·ñ ô”p¼­«™˜.»Š“œl:úpòäÉò?ëµx-C­<Å´ˆõ+W®¬­­=uêÔ<Î ÂziëÔb½Nž<)?¡óxcÇŽõ’¨'Ež'ÄtÅaÃÐzSq?jÎøùi®wüPfbG.õk&ʆ‡ËxÓæ¿¤Æµ¥·ñ ô”p¼­h9Bˆ¸)—_ÈûÿYkJJJçÎ333?ÿüóÚÚÚÀßž–¿÷ólllTëQ×;Ž“’’Ò½{÷†††/¿üÒ{•wgÿþýj6ÇqRSSý¬—ŸS·nÝz÷îÝêú¸}µu–••mÙ²eöìÙ±F©–›D=)ò\VÒ­[·úúúÇ«}ÔžT]o*îGÍ¿„Íõ)bœâ2£8Ý4–þÍDùÑðÐù}ÖIk oA>­ZœüŠ”lÉO{ýÇMåñ™?•õBBÛq{ÁÍcj_ƒâ6·ù™‰87ZÏŠ#5³žKp\[àx[YYYYYYYYYYYYYYYYYYYYY%WZŠXFF‹Çf*?7 dqæÞ›Ï<–ß,~€1éS\ `Ž+?bxXy 6‹5䋨Òâ¿EìÆoܸqcMMÍ™3g¶nÝêý³–g¨Í ˜@.gÎS Ñ×?R–ßÖòyoRÚáñ)b\¹8@ñCÃ֣8«Y®-ªÓb[ZÜšy ³óœ ñØvíÚ%/^Ÿ>}¶oß¾nÝ:‚g¨Í Âr9sR* Ñ×?R–ßÖòyoÄðÄ ñÞˆqeáÑ0ëµãG Wg5‹{mQ‹Øã~ÔÌkˆ˜qJ.vÑÑQÄ233?øàƒÑ£GË÷€xî¹ç¾ùæ‚g&˜ø@"?+À˜@´ž…'Dô5¢~)Ëokf :-±Å*©ØEéz°‹ >þøcïq‹”‹Íƒâ(?Ó…ò èG’z.aÀöÚk¯uïÞ½ººzÉ’%ò,4€M­üR°5Øöç?ÿy„ êb l{ñÅŸzê©|ðÆoÌÏÏBĽJÍ“p¨fÍšuÕUWuëÖmÛ¶müq÷îÝ»uëö»ßýÎ °ÍÊê"ÖÙõk±^ZFTVVâöiÑn‡:ÌÕéÓ§µë»1y‡)‡â(?À†Àr4×µA r³¶ "Û²$ÛˆK'w?§À6+«‹Rë¥eD¥Ü>íæ`Ì•v}7>ï!åXùQ(ŽòþH©tí¹,€íB‰«JûÕs€m ‡ÊÓ¹¶YY]”BX¯„Œ¨8LB»!Ì•v½Ãç¢}¹ùY˜.ºN­?RÚ„ê¹,€íŠûQ3m¨5qJ°ÍÊê"–#ñöF”óCL—h7c®ˆõ,Þ!Bʱò£:鸮aìâ~¼§žËØ. ¸5Ÿ›¨m••Õ¹üê§ùëQb½©}¹q”Ÿµo3el\ÜÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊêÂÁÔ¾k"¢Ü¡<ÐòP~G4>b_–P~t^GœBo~ý–SxqÄÏÐå²²º¤¥åöÝxã7n¬©©9sæÌÖ­[½ßØF”;”ÑòP~G4>´¯§X„ÁÿCùÑyQq ~¡Z¿å^‚q?j&×].+«K]ˆÛ·k×.ù¼îÓ§ÏöíÛ×­[—ššJPîP--å'âˆÆ‡ö•ŠC¸ü?m~t^ÂÄ)Dqmý–Sx Æý¨™\Ct¹âd¹†V—œ´Ü¾ÌÌÌ>ø`ôèÑò½Hž{î¹o¾ù&-- QîPhy(?Š4>´¯À\@©XþÊÎKø€8…(Nø¦ÖéÍr /²xÜ­L×].õ™`¹†V—”Ò$·oá…Æ ëÑ£Gyyù† „G5j”÷7¿]»vD"®ëÆRî„åå1¼½ØQ~—4>ùgÈBÆGì+šnsçΕïÓèÕ#ÿO,ÿåGçEqyŠÚ8í›Z§ŒHNáôéÓ gó¨rÄÛÛ¾}»ëºª“h½|‡çÆ¥ÏBˆöíÛ‡B¡‘#G^~ùåëׯ¯««;vìXܽ•¯íÔ©SVVÖÊ•+]×U_Fã"èr©ÏË5´º¤”Fpû÷ïÿì³Ï†ÃáÎ;F£QD¹#øhom~:._Kã#ö¥¹€*ÿO›Åæjã }³œÂK$î5(©\Ct¹¼­-×ÐêÔÙïŠlÞ¼Y>=_xá…©S§.^¼X~ÅPUUµiÓ¦p8ܵk×;î¸ãý÷ß÷(w×]w]ffæ¨Q£b¿ƒò íÕür1Š @ãÓîë!Ü~ñ‹_¨[kùj~t^ÂÉ)\±b…ã8yyywÜq‡üˆ¥'ô q çÏŸßLN¡¶ƒZÑNZ™Õ²eËŽ=ZVVÖªU«ù—yûí·U®¡¼¡P¨   ´´tøðáÚWýßÿýŸš‡¸\7ÝtÓ}÷Ý'¿áÑØØ8yòd!ÄéÓ§?ùäûÐê"V âÊ>xðà¬Y³ŠŠŠ^~ùåx ##Ô;Äÿ£·WóÓq•Ƈö¥nZþŸ6?:/Š#N!ŠÓ¾YNá¥÷þ¿›4®¡º\Âr ­.U¥!n_ß¾}Ÿyæ™âââM›6¹®{äȑ֭[ÿä'?©¨¨ÐRîP´qß¾}‹‹‹Õü:t@û ¨Ÿ@¸iùÚüPýPñQ|ãÆ„o–SxéÄc[œ$®!ºtòr Ë5´º”¥åöeddTTT¬Zµ*33333ó£>Ú»w¯ü-2-ååñv‰ƒ¡üľˆÆ§Ý—F¸!®¡6?:¯6Ž8…g‘ðÍr /¸z1µß²n׸\q²\C«KNˆç—““#y„555{öì9r¤Œ#ÊÊ#¥>ŽQ~G4>z_¡C¸i¹†(?:¯6îN!ŠÓ¾YNá%÷£fr Ñ劓åZ]R:{nŸ|߯xqD¹Cy¤TZÊâØWènZ®!ÊÎKÓþïPË/Dõ[Ná%÷£fr Ñå²²²Â(·Ïÿ§·öåæ1%⼬zšy^Ë)¼èãç@ɾ,VVVVVVVVVVVVVVVVVVVVVVV­¤™î W\ž¢Á!^ —ö‡êáò Q~V­¸äH‚XÙ¢x~züˆf+«K]q´9GH3SÜAn=ðï»ï¾X¤ß'Ÿ|"#Ñà/KûCõpù…D~ñC¡6M4d‘#Ñú–Æó»Ðã~ÔL!õ´²²ÒÐæP!ÍLq¹õ áÌ™3+**&Nœxÿý÷ßÿý999IÑC¼@íÕ€_ˆòKÅòµ¢!—‰Ö·4žß…÷£fòÑ0ÇÉò­.Ei¹}Ú84sLp¹õÌó›7o^yyyZZšÓ$!AƒÓò¹´?TO~!Ê/åñé RqDC9­oi<¿ =×ßdð‰aŽ“åZ]R:{´Ü>mœ@š¹MŠÍÀårë!x~ápøØ±c“&M …Bk×®ýë_ÿ*0EoûöíZ^ —ö‡ê À/Ôæ—ŠåÒäúX¢!—‰Ö[áÇ#úhqq±GrÑ ­WãÿøÿȪçÓO?õx~ÑhtÙ²eÿú¯ÿzÝu×íÝ»wêÔ©Bˆh4Z__ÿÖ[o9²{÷îˆ'y“'O~íµ×\×ýâ‹/þíßþí¿þë¿:$8´¿X¾`\=999O<ñDŸ>}¾þúë%K–Üwß}¢‰_ˆöÕ*ŽGHgDÙ3gzÏ;¢BÖ‰bz±N¶4Îß…÷þ¿Ûļì²Ë&L˜ðöÛoÇ-–üðCÄó[´hѪU«Þ|óM×uÛ´iãºnuuõ¾}û„Ž—››«åÊ¢ø§ý\F¿ýðF(ß…?ïâ‚'¹"ŽòÙ×àÕFòY'—ïÈ}èµ´‘¾8ãˆÛ‡øyžâ¸€¦x„ˆÏ‡âÐòˆ¸¶~äƒö\4íOÍŸp},_9‰8v¨SèDJ×Òø|zܚɔBLð$ÊÃE{¢ü4bSø¾’è\ÄzV~ÿ(PíU".;÷¡×ÒFúb ¸}?OJåšâ">Š#ZŠ£ú¿P{.‚ö§ÍŸp},_9©åØB'BPº–Æç»Ðã~äŸ/H0Q£¹àI”‡‹öDùiĦÿ+ÉEróûGj¯qÙ¹½–6Òk\Àí#øypCß…{zã ÆŠ`¢Ñå‚'Q.Ú“¸2±Éº’,i€üD"æªÒ°Rõ²sz-m¤/Ö¸&-·àç À t›;4x„ˆ®§#ZAÝCõk}@ç€öGûƒÖÇñµ;"þ_8FÒž-_°Eñ…"‚¨m4ö²szöJž³«š&„Ðrû~â"qy„ˆ®§#ZAÝCõk}Hø¾ûq´¿„þ¨ë…ÂÔ qìˆN¡i¡t-Ïw¡Ç½Æã ƾîªÒ|Gõ²³z-m¤/Ö¸çRi´?êz¡ð‘ÇÎu]m§ˆÎº®«BéZŸïB{ÿß Ê”C⇨mô±cÇXàI”gÏž=,´'JŽD\î¹´ë `êÊk¯*â;j/»à<ôZÚH_¬q!¿"\´hQ^^žüÄãö¹®+ùy¹¹¹S¦LéСƒäçeeeI.`nn®ü#Fôïß}þÒ·oß²²²Áƒ»®F=î`¿~ý´ñXº^4õèz(~üøq--Qôˆú‘ÚsI©´?Úu½Pø‚Hòù•-ÿ3–c§íÑYÑ¥+((ð t(¿‹Ç¶xÚ´i>úèÔ©Süq‚/Fcù‚ò_£ÑhCCCCCƒüN üÿqŸ3iÍO¢<®ëjãÚ“8¸q¯$q.ízƒW^{UÕ«$¥^vô0D7äpKõ =~¶AZnŸü<‚ (ÕL!¢ëѼ@-]O'êG>hÏ%¥ÒþhÔõ*_íè`޶Sĉ´P:”߯Ï/_ÐÁ$ÍO¢<,´'}eÔx€+ÉBšºòÚ«JðÕËÎ}èµ´‘¾Xãg{‰¸}Z~^¬´¼Àfò@×Cqiy4uO­ù@Üj-íðG]¯ò‰Çu AéZŸïBû‘¾ |”k“ FsÁ“( íIä§ãÂ÷•ä"H¹ùµuj¯*ÁwÔ>X=Âa7ÿþïÿTnâçyrt¼Àæó@×Cqéz(®­ù€Î%0íù£®×òi'UŽê:‚Ò¡ü6,îGÍä ÒLð$ÊCÇÑÁµW†ˆ ΕԞ‹¾Â¬üjÚ«Jðµ‡`½–3Òkü#¢ý4Öÿç¶´ˆüç%έ3IJÅ|A$Tç:`ããçLɾÉ~D¬'W>ÀUåîÈuØÆÍÆ­¬¬¬¬¬¬¬¬¬¬¬¬.Aá¤$¶beeeee•<¥®[·®®®î³Ï>‹û™áÚµkëëëÕxœZµjµlÙ²>}úÄýA=ŠËêܹsUU•Ù“XYYYYY‘÷ :4î燹¹¹Úxœ^xá…òòòÌÌL?ñ.]º,_¾üäÉ“õõõÿ÷ÿ ½feeeeeeRŽã,-"ž IDATüéOúë_ÿ÷'J(«œ8qB*ýÄÿçþçÿ÷GŒѾ}û_ýêW§OŸ~üñÇíÇB++++«ó¬þç>sæÌ°aÃâ>n¡¸§W_}UûÇà(‰Dþó?ÿS~dMIIyë­·Ð{pXYYYYY;ý¿ÿ÷ÿ***^|ñŸ/ÎPÜÓž={-Z¤þ+ŠoÚ´iÇŽÞûßï”aeeeeeun”"„8sæÌ‘#GT> ŠKµmÛ6++ëàÁƒ>ãBˆÇ¼uëÖÿûßW®\ùË_þR¾Åƒ©“XYYYYYÐÙ/Ú¾ýöÛØwãõ„âBˆN:µjÕJem£¸â£>’\’Ö­[ÿîw¿Û°aƒ|K¡Ø5eee›š”ðWu¬¬¬¬¬¬š©³?ÆC#a–×êºneeåoûÛßýîw×^{íŠ+Š‹‹Çûu¡Ä¶Éÿäȃ»[YYYYY©:ûðŠ+®ˆÃ(Óq!Ä‘#Gêëë322|ƇþûßÿþøË_þFÿþ÷¿oܸñg?ûYܲW_}ÕûÿÀÆ:•••••Kg¿5Ú±cÇ}ûö©u¼xß¾}.\Ø»woï{•§N:tèP×®]ã^‚â[¶lIKK{æ™gúõëç8ÎÍ7ß|ã7~þùçqË¢1²­¬¬¬¬Î…F]__¯þ™Dlü®»îª¯¯¿å–[b×üþ÷¿ß±c‡ú›Ÿ(>tèпüå/µµµß}÷]MMMYYY8NÒ¡¬¬¬¬¬¬üjéÒ¥k×®Uÿì/6>sæÌO?ý4nÍÀOž<©oQÜqœÔÔÔp8|Ýu×µk×Îþí„••••Õù×èÑ£+**nºé¦¸Z£FŠ¿ð ………ê¶ßüæ7Û¶mkß¾½ŸxìÓç°²²²²² ¤mÛ¶Mœ8Qýã÷-[¶ÄÆSRR´½äļð qPÜÊÊÊÊʪe©cÇŽÚU(®*55U‹[Bq++++++++++++«–'ípápXý£@!Äå—_®ýÏŒŒ íú+¯¼R»)ʃ„Ö£:Ѿ¨N$”Å322ÒÓÓÕ8ªÕ‰Äõ!@ýÈÖú()Lõ—«¶mÛ^uÕUêÏ PÜÔ¼qïšOî< 0¨Âm~Ô_”ÕϪçBû×9p˜õäAûšš(±páÂ/¾øâĉ‡Šý½Ð[n¹eË–-uuuuuu6lèÛ·¯Ü¬ÿþ}ôÑéÓ§ëêê¶lÙ2hÐ ¿ñÆ7nÜXSSsæÌ™­[·Þpà 2>bĈ;vÔÕÕUUU-Z´È+N›gÚ´iUUU'~(ù{:h_T'ÚÕyß}÷ÅnýÉ'ŸÈßkEùQ¼wïÞüñéÓ§O:µjÕª.]ºçEuôGþ 9A¾¡<,bõßÿýßÕÕÕ ×³ú‹|~øá‡‘ÿBˆçž{®²²²¾¾¾ººzÚ´iÞ´qSóƽw(?šOî<£y@õ P~b´y´õ÷ˆëÏ…—jÛ¶íâyq7‹å0qCQMŠûšš(!„ÈËËûÕ¯~õá‡>|8v ·nÝZ^^þÿðƒÞ¿ÿêÕ«å lذ¡¼¼üÚk¯íÕ«×öíÛ׬Y#ã»ví’UöéÓgûöíëÖ­KMMmß¾ý_|ñÁtíÚUB€ó›ßÈrµy:tèpCŒ~ûÛßF"ù‡üh_mľÚ:…3gά¨¨˜8qâý÷ßÿý÷çääH»‘(þñÇÿýï¿æškn¸á†Ý»w/[¶Œð ÕiʇqäšäÊÃòÁÛå®»î:sæŒëºòz˜ê/ò™ðÿ‘G©ªªz衇ڵkwË-·xï2â¦æuïˆüh>¹óŒæÕƒüÑæ'ú‹òhë'úÈõçBKMš4éàÁƒ­ZµB7‹ë0‘ÅÑ„ 8Ú×ÔD•ã8))) .ŒèS§Nýû¿ÿ{jjªã8óæÍûꫯÒÒÒÚ¶m»ÿþI“&ɸܹs#‘HZZZffæ|0zôhùû¥Ï=÷Ü7ß|“–––ŸŸßÐÐ0dÈÇqÇY¼xñž={RSSQYÔ!CŽ?þ‹_ü"%%…X¯­í‹êBÌ›7¯¼¼<--Í+€ðÅ{õêU__ß}÷ÉüO=õÔ‰'ßP¦|àÆ Мh}Cyø „hݺõŽ;>ùä“h4*¯“Áþj}&â»wï^²d‰|”ÄæÑÆMÍ÷Þ¡üh>¹óŒæ¨GëÊOÌòÍ9ê#ËŸ =îÝÖ5kÖÌ›7Ïû Þ¬£<Ú8šbrо¦&JÈ÷u›$~¨C‡]{íµBˆ´´´>}ú:tÈuÝS§Nýìg?s]7 !ºwïþÕW_¹®{ôèÑQ£Fyï‹Öµk×H$âºn(rgïÞ½2~äÈ‘:8Žƒòˆ˜wúž3gÎÊ•+ßzë­h4J¬×Ö‰öEu !Âáð±cÇ&Mš …Ö®]û׿þ•ðÅ{õêå8Î_|!-=tèP›6mz÷î½}ûvmý¨NS>pã„?hN´¾¡<¨~Â!ÄÓO?žž>wîÜÁƒˈÁþj}Fñôôôììì… 6¬Gååå6lB ¸©yãÞ;”Ÿ˜Oî}ºç‰z³8¬ÍƒâhBˆIÖîkj¢dUñï&«¢¢¢’’’;v¤¤¤466Þ{ï½r€ûl8îܹsaaa4•oUzÛm·-]ºÔuÝŸþô§ÞWå(Taaá5×\SPPà-CëµuÒûªu !B¡Ð 7܇ÓÓÓ§OŸþôÓO¿øâ‹Ñhù ·nÝZáDšþãÿÕOÔićqäò åáúлw¢'žx¢¦¦Æ»xû‹|ÖÆC¡P«V­ å5ëÙ³çK/½4cÆ '|àÎëÞ¡üÄ|rçI[òåGý%|F¾¡þ²ü¹Ðãò?'NœX^^¾uëV×Þ¬kóqâÉ k÷55QRÔ_ þÓ?ýÓe—]&?W ‡ÃwÜq‡÷ñSѧOŸ¹sç–––¾þúëÞ!«ªª$J0--M®ï½÷Ö¯_ÿüóϿ𠯿þú/~ñ‹Ø$(âÞ{ï]»v­Ê¾P×kë¤÷UëBìØ±cÖ¬Y×^{mÏž=׬YóØcÉo hâêOèO3}V¿Ö$äÇ¿sæÌÙ²eËþð‡Øñ0Ø_Úgm|óæÍƒ 8pàüùó§NêÁ«QÜȼ¡¾;¯ª`ó¬ê»êÊ@÷Wë3]¿ÚG®?rrr¼/ˆ¸YR,‡Q"?šmœè¬©‰ú^%%%±ßë2dH]]äȧ¤¤LŸ>ýĉYYYò_Ãáð¶mÛ6nÜØ®]»Ø$òÇ)))³gÏ>uê”ü=ïvíÚýú׿.++{å•WæÎ[UUåí‚òdffž8qâÑGMu=Q'±¯¶N‘ &NœØØØØ³gÏ¡C‡jó£}ÇŽÛÐÐpóÍ7K—ÇßÐÐ0`ÀùŸÚóu6ßnœðG;'È7y^”Ç¿ùùùgΜy饗üñ 466Ι3çöÛowÇH¦Ÿäi}VãgΜyøá‡½ßmhh˜0aB(ÒÆ XóFøÆÊæíKϳv´õ ߯‡òkû‹òоiûËòçB;Ž“——wüøqï/ÐÍB“ŒFyÆn.ñdPãèIej¢ÎƒêÖ­[jjêŽ;$iÿþýmÚ´¹òÊ+eöÅ‹·mÛ¶  à»ï¾“ëûöí[VV6xð`×u£Ñè‘#GZ·ný“ŸüDñÝwß=ýôÓ¹¹¹S¦LéСÑ#G¼OÔ•P×uj÷%ê\´hQ^^ž<`›6m\×­®®îÚµ«6?Úwß¾}BˆììlY^§NΜ9³gÏyíy šï7Þ¯_?ä’Ö7Âg–YYY[¶lѾô<«Bõ öîÝ‹òkû‹òÐÏ+mYþ :/”¸ëº«W¯þöÛoå?¡›uüøq–ÃÙÙÙÚ<(Žž0(ŽöEur'*~‚ã>³ëÖ­Ûwß}·|ùòŒŒŒp8üÁ9rD~Sõå—_®¬¬¼ãŽ;²²²ºtéÒ¥K—Ö­[gddTTT¬Zµ*33333ó£>Ú»w¯üœë®». !&L˜pòäÉ9sæÈáÚ}úÄ~õª]OÔ©Ý—¨sݺuëÖ­ëÔ©Ó•W^¹yóæ­[·¦¦¦¢ü(î8Ζ-[>ú裎;vëÖí³Ï>{çwd~t^ä¸qÂíœ ßˆ<,RRRR›4aÂù{_Ä\qûKøLøôèÑáÇ_vÙeï¼óΗ_~yÅW ¸©y pï´ùÑ|˜gí<Ð}Wý!òÏ 5áê#ËŸ =Þ±cǪªª1cÆx7‹å0ʃâhBPœ¾F&êŠhÇqî½÷ÞÔÔÔÔÔÔìß¿?77WšxòäI×uê›4vìXÇqrrr>ÿüóÓ§O×ÔÔìÙ³gäÈ‘r}IIÉéÓ§«ªªNž£xFFÆÊ•+kkkO:uàÀ7†âFæ-À½CçÕÎg€yFó€êAþ ü¨¿Ú|Øû…`T?ªÓ”Áâª? çD뛚'€ÞF©©©Æû‹|&âòÕÖ­[ïÞ½;ö_µqSóƽwt~u>¹óLσv~ÔüÄ<yÔúQƒùsÆËÊʶlÙ2{ölío€Çݬ£<Ú8=±Ä$«ûšš¨Ä’“›¿ž•$€¸ûëMÅTܼõDž¤žËÔ¾Dÿ‹‰õ¦ê!öMöü$Õÿ¾ù/Æl=Fò¨“[OKŽËïUjW"]7íˬÔÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊÊêbW²ùs¦ò4,O‘ËáãÖÏå,rëDâòüæÉqyu\JYRç*·Ïˆ(O€¾ ±òs¹t¦æ§Ê` ¬.BqùsžšI™âò핊ËSärø¸õ#nœ)Þ!ÊÃåù¡ú¹¼:­?N»/±žÛ.·Ï”(—7Éíê»¶~b_n¬çƒŸóÚ¿¿|Ieeå®]»Š‹‹Y¿ú‘ðjXY±ùsRͧLqùvˆJÅå)r9|Üú7ÎïP›‡Ëó#êçòê´þ8í¾Äzn_¸Ü>S>hóàM²úEô][?Ú7@¬çCÂóÒŠD"K–,2dÈ­·Þ:sæÌššš3føüX˜Dge€?' Q¦P~.å1ÂáãÖOððQ.ÏÕÏåÕÑþH©œ?m¿´ë¹} Àí3âÊÃåMrû…òÓAußu²žôy=ÝyçÚwCŽD"óæÍ“ž§¤¤lذáÝwßõÆ[}Ul„¾VVBˆ´ü9aˆ2…òs¹€(·~‚h„wˆòpy~¨~.¯ŽöGæT9Ú~i×sû€ÛgÄ”‡Ë›äö å§9‚ê¾êd=èó !Ú·o …FŽyùå—¯_¿¾®®îرcꄸ®Û©S§¬¬¬•+Wº®«¾Jž%6Bƒè¬¬„ärùs¦(SH\N’)·~Ä3Â;Dy¸ÏO[¿ÃäÕÑþ ΟÖ7íú}árûŒø@œ‹Å›äö åGõ}ár1µõÐõy$ ùäÎ —ÓÉOn\ªmÛ¶7n\¬ >@%òhãÜ 'ö5Ò)!Hœþ™â‘G©ªªz衇ڵkwË-·ÄAÈüs QwÍqT'ª‡ËeäòðPå×ò ö‘ÅS$ò ~¡¸)Ÿ÷ŵóÀå;à)¢órçÍ3ËO.ðñQ¿X\ÏÜD´/š+Ös†ðËédÍg€¸Ô¤I“<ûþ@EyPœ;áh_S:+§I~xcøg»wï^²d‰´>î—Îýs Q.wX¯­ù€ÖsyxÄyQ=ˆkh¤\ž"{C}Gq#>þhãh‚ñUÿ¹DîœÐóïßO.X¯å5ýÒÖ‰Ösë$öE}d=gP=8¬ù䯽֝Y³fÞ¼yÞÿ ÎyXOxÂ1´¯‘NÉ:Ó“7ÆåŸ}ñÅÙÙÙ .6lX=ÊËË7lØàeóÏ5LOO׿ár×èõþ9p¨~.àäió Ì54ÒG.OåAýBqS>þhãhhˆÞ—ƒÈzžýûÉåëµ¼F¢_Ú:ÑznľZ¸Ï4'8¬ù”ïçà?.ç¡W¯^×_ýôéÓ8€:KÜm<À“P»¯©Nɪ¾ÿLÁ'oŒË? ‡Ã­Zµ*,,”eõìÙó¥—^š1cF4eq C¡6—»F¬gqàˆõ\Š£üˆkh¤Dý,"êŠoöÁõù££yÌwôÏSDbÍIÂù÷é'—GH¬'¸•Ú~>¨ëpѾZ¸Ïú±8¬ùäÆåNœ8±¼¼|ëÖ­2Îr€ §¢aŠ\«Ý×`§„Ç#¾ycÁøg›7o4hÐÀçÏŸ?uêÔ=z8Ž€k¨æI¸µ)Žw=‹‡§£üˆkÈ:oÂ>úä)Òy´}'âF|Fþоù÷'oËA4ÈÅT¥­ŸË#$ÖÓ¼Fí½ ·>07QÝ—è£ÿç ]‹ÓÉšÏ`ÊÉÉñ¾LÇAEyL‘k‰‰2Õ©³Fgff<øã?N8š®ëæää¼öÚkÝ»w¯®®^²dÉ™3g„òã$?'nß¾½±±±±±qÙ²e?úÑ®»îºüüü‘#G~þùç<òˆ|ÛèÜÜÜÛn»MwðàÁY³f½üòË<ð@FFFuuµ6O}}½v_t.TçÝwßMÔ£Š®?ÿñüꫯ$Æ{•z.'òO:uΜ9õõõµµµo½õV(’ß1ÒG)mýÚ}…Ú<¨_(Žê à3òGGó€ü¡ëAþ£¾#ùŸT?×OÔG)õ\ÈŸ!C†L™2å©§žš2eÊäÉ“Ÿþù'Ÿ|²sçÎòUè^ ©ëé¹Eþ«y'Nœ`=gèzPµu²æ“Bäååµoßþµ×^“¹ Î¢<ãÇg=á‘ch_îGºSg?²¸qî•››;eÊ”:ÄñÏävìØ±ŠŠŠ«¯¾ZÆ%(õÛo¿õ¸e¹¹¹ò˜#FŒèß¿¿~ýÊÊÊìºn4õ¸q(Ú×Ü5´Õƒ>Òë%¯   –‡§=:ovv6Ê¿hÑ¢¼¼<¹Q,ÐHå?©õ !оÚ<¨_(ŽŠäúLÔ©ïÛ·Íö\t=Zž¢¶¿è¼Ü9!êçúIÌÁ/Œ[ËÑŒF£¯‘è!íznÚ<ȇãÇsŸ3Úzè¾këdÍ'ª‡¨³  `õêÕÞ]ã:€:‹žT(Ž&ÅѾ¦:õƒcqã¸ü³—_~ùèѣÇ¿ì²ËÞyç/¿üòŠ+®Har Qb_í¹ÐzTòXÏâá¡8‘ñôÕOìKäQûEÄøLÔ©ó€ï蟧ˆÎËzþY~ry„Úõ¯õ Í'ZÏ­S›‡ž+ÖsF[ON'k>¹ñŽ;VUU3ÆÛ‘ëê,ÊÃ}£8=QÍ‹7ÆåŸedd¬\¹²¶¶öÔ©S¸ë®»âÓ>¹†(—»F¬×Öƒ|@ë¹<<š“§æG(—/€s©­ßÏy íß¿_¾¤²²r×®]ÅÅŬ_ýHÒ³²‚(.ŽK™Bù— Q©P´ÅMÕÏåäqëärQ¿PýˆgÆòËG ÀóCq.Ò”,î#q^V¿¸|P._ÛG4o ÏK+‰,Y²dÈ!·ÞzëÌ™3kjjf̘áÿc! Ò³²‚ü3Ñô×>yf(S(?âÉ!*ʃÖkã¦êÀÉcÕ‰òãç©õ<3–o¢éך|D´žÛ.Ò”(—ŸÇíW>¨vßu²žôy=ÝyçÚ÷ñD"óæÍ“ž§¤¤lذáÝwßõÆ[}U\„éYY !Ò¸¼4)#”)”ñä åAëµqSõàä±êDyN›¶_¨~‚oÇòM0ùˆh=·/\¤)P.?Û/.q:ÔÉz>ÐçB´oß> 9òòË/_¿~}]]ݱcÇÔ q]·S§NYYY+W®t]$,Pþ IDATW}•}ZVEôK­_¾ÒÍ7ß,׾7Rß„………•••YYYqæ ß´ëôEõŸÕÇ`>¨yˆ¾ ó²ú…òõk÷ P'ê#]?Ês÷ÝwWWW9räðáÃÕÕÕ“'OŽýz1‰:tè“O>ùÛßþVQQñé§Ÿfffj_•ŸŸ¯æ¡[feuvÔXœ3S”)$Äå¢9gªÐz"AœN·N.ËYäúIûãŸI¬ÐÒ”ªðóXý ÆU÷ ÌùS€×(„X¶lYNNNzzzFFÆ=÷ÜSRR÷X{÷î]¾|yiiéâÅ‹C¡Piiijjªúª¥K—ªy¶¬¬¬lS“†j?L^¢’ßyOII™={ö©S§bï<î3¾üüü3gμôÒK?þø‚ çÌ™sûí·ÇþCÍã?¿hz#>ùÿ'NœØØØØ³gÏ¡C‡ÖÕÕýò—¿”ï4}úô'NÄ~^—gÈ!Úõ(N×ɪ_‡·mÛ¶qãF  p.¢NmÇqÚµk÷ë_ÿº¬¬ì•W^™;wnUUUZZÝ/µþ±cǪ_I 0€öù“™™yâĉG}TýiÖ7´žÛ­ÿ¬>óA{.m_Ðy¹ýBùQýò?µ>³êDç¥ë'ò!V¬XñÆo¬ZµJ~‹ý§H$òÊ+¯¤¥¥Éö=º¾¾~„ Žã¨¯Š‹ÐW^êÁ|¬Iݺu³/5¥õë×ï™gž)..Þ´i“뺪¢¢Bûb%„HOOwgĈÇ?zôèìÙ³Õ<:t`åB,Z´hÕªUo¾ù¦ëº—kàÀ©MT*×u=*•÷¸8u‹¡XÅ®GñvíÚië P¿hâŸåååÅqòüŸ ÕùÕW_ió¸M´-Çq\×}ã7âøyqýúðõ¾y4¯uëÖ‰šWnn.Ë7鋨]ß·oßââbn_TÿQÔG®hE?/®/è¼Ü~¡ü¨~s+Yu"ÑõÓy$5·M›6Ñh´±±1î_åÏ}å—‰»wï–Ÿù9Ž£¾*.B\%¯ŒW_}5v#ûÄKN\^ZŠ!ÊÊ/—«¦Rió õ(n°~'['Ê#ñóÔú@óâú&³±øˆÚõúÂâAšò8‹ŸÇíÊê'úÂåüië¡ë'òxÒþS$Y¸pavvv—.] ´bÅŠêêêØ?T_åE¶ÌÊJ>/ÍSs(SD~-—ËIDÃRdÚõDSõ³8yêärQ¿PýZšWß“ˆÖsûÂåAšòåáòó¸ýâòAѾÁêôÿ|Hx^B‘H¤±±Qö´ººzÛ¶mùùù>ÿŽ0aˬ¬¾ÿÁž^Ú÷/ne åwñä ‹È·žŽ7¿~õ¡à““Ǫ“ÅÔö‹öM¥yq}L>"ZÏí í?wýû€ò}!üñß/”Õö V§ÿçCÂóŠë©ü6©ÿ$tˬ¬¾—ül7yy¸ùÏWSûž¯zL}ª‹ò$Û¢ž¤Î±>©yL‰¨ÓHž‹@ÉQ+++++++++++++++++++++« U,—ÃÇÁÃÓÖÉåÏqós!gmÛ¶•¿¯ás½)Ž)Q?k~PÍòÁàBqylR*/ qàÐzmœà–!¨ª“ËŸãæ§!gêyy䑪ªª‡z¨]»v·Ür‹cãò×Å;$|FyPýÜùAqíü>˜šÔ/”ù€ò }YóÀ­“ðÍ—‘ËGäÎy²y¨(ΚÛÏ+SSîý’š4iÒÁƒcßOÀÿ“œKTÕ®'C7‚E%òÓ¡Ø<6¡ã>íz"î4)Ž[¦…Š¡:pYùÑzâ\»wï^²d‰ÁØßäæò×0ÇQë3ʃêgÍŠ£ù!|05Ú~}G>hóû²æ['òÍ —Q»ž;·4Q{OY>sãܹå>¯Ð¹¸ÓuJ­Y³fÞ¼yÞ÷0XOrî­GŽioD0¨šŸþ•&ø<6×uUÞÁá€O†âˆ[¦…Šur9ˆÜüäL=WzzzvvöÂ… ‡ Ö£Gòòò 6Èâò×0ÇQë³6Q?k~ä5kýÔÎჩyÐö åùâ‹/Ú<ˆƒÈnápXë›A.£v=wni¢öž²|æÆÌ-ëy…ÎÅ嘫³W¯^×_ýôéÓ‰É7HTE뵎¡Œ0ªæ§?BAL³|{LïÝ%ä ~üã !z÷î]TTôÄOÔÔÔĶÓ{ŸÜ±cÇþüç?衇äËÑz—*,,¼æšk ¼´EEE%%%;vìoNqï½÷F£Q¢ÎÆÆÆþýû?ûì³áp¸sçÎ………ê›­ÄŠ›_»+ µjÕª°°PhÏž=_zé¥3fHŽè 7܇ÓÓÓ§OŸþôÓO¿øâ‹ûöís]÷¶Ûn[ºt©ëº?ýéO½ïfh×£<ÑhÕ‰|Öæ!êgÍÝ/u~L̓¶_(O8F>÷BÝ—;(?ª“ðu/?µâÎ-±‰å37`n¥|>¯ˆs¡ç§Ö·`uNœ8±¼¼|ëÖ­2Î}’sŸ0h½Ö1âF zèIV;‚òGÈÍS9ph=—[Æå &Îï8×æÍ› 4pàÀùóçO:µGŽãpù‚ˆkŒã¨úŒò úép7?„¦æ!¯QëCN§ÿyàÖIóp¹ûrçÉ Õ FžW‚Ã1  œœï VÁ’sŸ0tåZ2%ñ„áFùR›ç{ùä±Ñ¼1•‡Ö?žÅ-CP1𻿸æÏqó#.:o(:sæÌÃ?,Otã7644H š¬P–‘/(0P§ùyZ>œ6OFFªŸ5?t¿´A­¦æõkܸqÚ<ÈzžÕ} ?µþsë$æ‡u/h?Õõ¨_ÄÜuªùÍòPÕx°¹õÿ¼Bç’òÏ1 Pg^^Þñãǽ¿4à>ÉQ%Äu\ëý„áFùåŸYx<3ùŸÏÌãåææÊq1¢ÿþ²\É+((ð8ph}vv6‘Gå–ÅBŢѨÛ·oŸ¶Î>}ú”•• yl)˜7¦åÀ¡õD¡ã–!¨ª“ËŸãæGëiŽ=:|øðË.»ìwÞùòË/¯¸â Áä ëpµ|8”ÕÏšGóƒ|05¨_tª(ÍMô?êÔúfŠËˆÖ˜[‚ƒ¨æçú̘[ÖóŠðÅ1åÖÙ±cǪªª1cÆxrŸäž0¨ãèɃnDÂ(ʯ=×ä“Çû’8ÞâÀ¡õD\å–9*†êdñç¸ù‰õè\+W®¬­­=uêÔîºë.çòÑúG-åGõsçÅÑüh}0>j¿PÚ5Ú—;Ü:Ñüá2ë¹sKs4“ÇCEqîÜ æó ‹Å1åÖ9cÆŒ;wjmT4BT¥'YûäA7"aT›Ÿøõ}cäwZýðØb¤ÆðÆT—U°\ªÂWÓÆe1Z.âá!n\"+?9SÏ%?jݺõîÝ»óÑú„qµNÚç¸<¨~îü 8šŸ„>™µ_Äü> <Ú}YóÀ­“ö­ù\F´ž;·h=ÊÏõ9XÜÿÜ æó Í?}¯}ÖYVV¶eË–Ù³gksÕ瓜û„!&Yë˜7‚®Ç? 5áG(JqŸžwÉÏA´qÖú˜ßȾܸ©:‰<¬x€<Éî—©<Éî7n$€zXýâÊ”ÏçÖÈÑšY§üîzóË +Iê“ÇÔz+++++++++++++++++++++¸<9-*ÿL+.gN0¹eh=AábùcŠž…Ö£ü¦8y„ŒpÔˆzXóÆõ_â&š·Nt¿¸<üðà ý!´ÿ~ù’ÊÊÊ]»vûÿ?­±²‚ârÈ´(.ÿÌ wP[?‘ŸËãúâg LùBëQ~-Í‹ðÛ®oRþy“\Ž ×#ÜD¢~íy‰þ²êD÷+ÏQßXÜ>äCBhE"‘%K– 2äÖ[o9sfMMÍŒ3|~,læÖV—º‡ Q ‚ñϤšÃDõùµë ZËŸô,-µ ­'ê$xªúÂõMpx“ÜyãúÏícþ:¯¶¿Ü:Ñý ÀóÓÎ —ÛGÏ òÇÓwÞ©}íH$2oÞ<éIJJʆ Þ}÷]ïó*õUq?[[Y© Â#ÔR WŒK|Μ¶~"¿v=A«âúÃ¥gi©]h=ª“æª>è ×7ÁáMrçë?·øsè¼Úþrç Ý/.ÏÍ —ÛGÏ òGѾ}ûP(4räÈË/¿|ýúõuuuÇŽ?”,»S§NYYY+W®t]W}•äUÅå¡·¶²B Â#ÔR óϚϤ¥æG"hU\´yˆÚEpÔÔü yZ:«/\ßX¼Iî¼ðŸÕÇü9t^¢¿þëD÷‹Ëó£©o,žòŽß~ûí%%%'OžŒF£»vízòÉ',X›p̘1 ïòõ×_Ïš5+ª¯úî»ï,X Íãt­¬¤~ß@¥@柙âx!!*RZ•où§gÔ.Â7m~‚æ¥õ!ÍËÿy¹¼IB¸q¦úˆ¤ÖÎKSÙ|Ö‰îWžŸÀs€Û‡úˆâË–-ËÉÉIOOÏÈȸçž{JJJâ>üïÝ»wùò奥¥‹/…B¥¥¥©©©ê«–.]Šò£UVV¶©IC‡m΃Åêâ‹Cæè(Pøg¦¸ƒjý(?:¯¢UqýaѳdD.ˆ£v!ßÔü4Í ùà¿/\ßhÚ™šŸ;oÁü÷ßG.Ž8/Ñ_ÿu |¿Xþøãêw/åFR»wïv§]»vŽã¨¯Òæ¡·~õÕW_lÒÁƒ“ñ­« [>9d*ÿ¬ùÜAT?ÊO¬§iUþ9m\z––ÚEsì´u¼@Õ‡4/–o)LÞ$wÞ¸þsûHÏ›Z?q^‚ïè¿N¹},žš.·žb~µ~û !Ö¬Y3oÞ<ú ÀuŒÛYî"Çоh=O‘\´… Ê?Aõ¸hˆÓ&_)¹k‹-Šý«U·I±00É?Û¶mÛ°aÃŠŠŠ† "ÇrÔ\×ã¨iÿŠV›ŸXϪÅQè\(ÀO-—ÑÔ¹ˆü,¤ã8(Çá›9sæ°aÃÌö]ròÞ}÷]ù’®‰8…¨/„D=j ÕÉõ;oÈGÏäO€9gÝßýà^ PµëQ¹>£:ƒÍ§ÖObß^½z]ýõ …us ÇXEù‰ DEû¢õDü;vlMMü6«|›¨¸wß—B{÷î]YYùÀĽu–¢°°°²²2++KþçUW]ÕÐÐðÙgŸ•——oÛ¶­¶¶öÙgŸMII5jTCCC~~¾|íüùóOŸ>÷†RÚouÆå'Ö³êDqT':ŠðsøðáûöíÛµkמ={vîÜû³Û柋ȯõ£¯Ú_b½ÚÇ>kë p^ä'QÿóÏ?¿aÃï°¬››ðFø2s'ûÄCë‰(×gâþ˜OÕO¢þœœœØ/›X77a³üw–;Ü'ZOçBÇEC<6.gŽàŸ±8jRþ9yÜ:‰üÚ:ѹB¡6>nÜ8–ŸC‡ÕrM q¹"òçøñã¬9wÇ‘{Þ÷‚8¯V\>(Ëgtß‘Ÿô|jýDõ¬^½Úc”™¹Ž±:KT(LMÑzúÉ)à¢9€Ç–ÂäÌ ÌÉãrÔP~íúu¢8ªKçú‰¸Œ¦Î…ò£8ª­˜Ãg¤ïÁ8…j_ˆú‰z´q.ÓGˆ#ÿY|DÂÖœÓóéÿ¼î:/Ú—ËeùLÔ`>µ~j÷íØ±cUUÕ˜1c>8Æí,k¹O<´žÎ#æ¢Ñü?á›3‡øg\ŽÊO¬gÕ‰â¨Nt.gùé`.£‘s¡üľÚú‰õˆÃgªï\N¡¶/ }öÿËã4ÅDqä?—ˆü 0ç¬û¬_Â7íËåƒr}Fu8¯ÖOí¾3fÌØ¹sgÜ߇;wî\XX(—õîÝ»¨¨è‰'ž¨©©‰}œiÏË]OÔƒòh}@yÂá°ÖyÿUߢÑ(×Ô#¾íÛ·ÏuÝÛn»méÒ¥®ëþô§?õÞ Q»žëCÿƒÍ¹*ÖyƒÕ©ö‘ðÝ;4Zнó*÷y£Ñ(=o·ß~{IIÉÉ“'£Ñè®]»ž|òÉ Ä>(ÆŒ3`ÀùÞ4_ýõ¬Y³¢Ñ¨úªï¾ûnÁ‚±‘Õ«WÓG°²B Â#”òÏ·Cë *—s¦å„Ñô).õ*©¼F$g.˜þi^Èíz‚·—˜ æÃb±©>²òà u²ø…Ľ#xZïPpî/íÿ²eËrrrÒÓÓ322î¹çž’’’¸T{÷î]¾|yiiéâÅ‹C¡Piiijjªúª¥K—jóGB”••mjÒСCí÷N­¤Î>@ÃáðÿøÇ¯¾újÚ´iòMáΜ9£®®««“ÿ'33sðàÁü±7ëC† ™2eÊSO=5eʔɓ'?ÿüóO>ùdçÎÑz!ÄÔ©SçÌ™S___[[ûÖ[o…B¡îÝ»WWWG£ÑíÛ·766666.[¶ìG?úÑu×]W__OÔsðàÁY³f½üòË<ð@FFF~~þÈ‘#?ÿüóGyD¾©knnîm·Ý&G_=/w=òçî»ï&ò¨> ø€åšÚ➗;'G={¶ÚÇŠŠ m~tïÚµk§‡ŠŠ í}'¸†ÚûŽæžùBùÑ·M›6òûùqËŸ_Ê/ïvïÞí8N»víÇQ_¡ õꫯÆnì[V§Xð?Àœ çR{^n\~!ºwD­ļ±î/=o±Ò~[2‰,\¸0;;»K—.ƒ Z±b…ü$/ö¾yˆ#XY%P¡¾Z/0•ŠË9Cœ0Oqô).õ*Ù¼F?ðëªÇ”o4oO]Ïõë°>úç\¢órëdñ ‰{‡ò ÏhN¸¼=?ŠD"²¶êêêmÛ¶åççûÿ;BâVV„ˆGHs°œfp³ä?¥r8gà„Ån”CŸâR¯’Ík$ò>øç¥që1å[ ÉÛS×óÁ¿ÿÁú¨¥¯±ÎË­õ‘Ψrj¢ZŸÿþjÏåGqµÉo“²¾‰Ž`eÕ,q?¥r‡õ´žˆÙ×”LmÊ=7~¾`~Pœ5\ƒ>ró™S÷ÑÔús X’•••••••••••••••••••••U‹––»Æå¨€±ö%¸t¦8|¬zLñððP,Ž·_ˆcÀçÏ÷ùÃå) f_¸u¢}MõËÔ½Nö¼>³ü1È7Õîkê¹á_\’+ªû$áæ1õ$á’S!wË#Lžk_)-lLË] ÀÛãÖÃå/¢}¹<<çr쟈3‡8vˆ‡ÇõíkŠûˆÎ‹üáòY}1X'Ú—Û/4À½Nö¼¡ùçúcŠoŠö5ÈmB´mÛöÀãÆ{øá‡¹ÄStRä0÷IÂÍÃu†ÛYÔÁ³BÜ5.Ë3cí+0lLË] ÀÛãÖÃå/¢}¹<<çr츼CıC<<®Ïh_SÜGíy‘?xЬ¾˜ª“Ø—Û/4À½Nö¼!þ"×S|S´¯)n«Ô¤I“<تU«ÄStRm…ž$Ü<\g¸E<+GÇ] À#äò̸ûjó>´¯À|>V=\þ¢vß<(ªÕ“ìy£}öï—ëIÔ‰æÜ·UªW¯^×_ýôéÓ‰ H®Ú º*­X;¢_ïPnÇ#D>°|€ogŠûˆÎ‹üáò¹}1U'½¯ü?>ûÅâƒrïõ9˜7Úgÿþ˜â›"á¶Ê—Lœ8±¼¼|ëÖ­±õø$ž'ÕVàIÂÊÀng‰›ë÷MüTi¹z,žY¡üwËÛó/.ÑÔ¾„X;Áç ÇùÀ=/½¯ªÜGõ¼ï¿ÿ¾Ö³ýĉYYYÜ}ÇGø¬Öƒ|“ÒúЮ]»_ÿú×eee¯¼òÊܹs«ªªÒÒÒ?e™pâĉ={ö”õ„ÃámÛ¶mܸQ2n„C† ÑúÀõY4½¡eܾÈ:?k>µþ ßœ‹5Ÿê$öõß/ä¿©{ìy£}öïÊC÷åQ÷¥ë×ú‰üÉËË;~üxÜ_¨è'¹zR¢BÖ“„xBjóp†ÕYºƒð3n£&ÿ3!0ÏŒµ/Êß·oß²²²ÁƒËo {Ü5´¯ÇKËÍÍ•?°1bDÿþýÑ'¨ž®]»¦6qà¢Ñ¨Ç“yüï»oß>Âgÿ"|»ÜÜÜ)S¦tèÐArìˆ~-Z´(//OÄãÌÉz$Ç®  ÀãØÅòðb}ð8ˆ>}Fû"è>²æSëŠsç‡;Ÿê$ä¿_Žãhý7u¯“=oýúõ#|öïê=Ïj$Âä'ò§  `õêÕqÀE‚x*ÿ3–äª=)Q!ëIÂÍÀVgýÞܸ«“G(ø<3î¾ÚüwM»oJ"^šÏzº1ù‹h_Úgµçrìˆ~œH•c‡|àúŒöEþÐùYó‰üañôÅTÈOV¿è¾7ÿ^'{ÞhŸýûcŠoŠöå>7?;v¬ªª3fLœóþ‰§è¤D…¬' 7OgXMxsa:P00‚{ç_”Ÿàð±x{¬z>팇§ÆY;ÂOÄ™C;–Ïh_SÜGt^ä—§Èí‹©:ѾÜ~qù ¨~TO²çæqú÷Ç,ßTýÄÚ·uÆŒ;wîT ,â©ö¤D…¬' 7Oà'ªÿ΢ !¾ÿ7ùÙn,wÍaò“g`_m~søˆ}à¥ù¯ÇaòѾÄyµõÐuúçØÑ~ªœ9õÖÅòü´>ðq‘?Úü¬ùDþ¾8k>Yu¢}¹ýBþ£zˆúµõ <¦æð9€?¦ø¦Äœû|nhý)++Û²eËìÙ³µcà“xŠNŠ* ü$ñ™'ØÕgQ}IýR4ázîKXû¢ü¦ö5U©üò ¸ëY%ôU²ó'{_îúsàCRïW²ç-ÙušR3Ï+¿[ËÝ‘UI²Ÿ$É~¢ZYYYYYYYYYYYYYYYYYYYYùÁ cqãš”.—gÆ­‡Kí2ÅMdÓ³ ùIœ‹u^S¼F®o—N[—ogª~îýâò)Ï=ßÎÊêb“–&¥¥=t(DŸbq¹b«R©QÚ:Ñzn=\j—n¢Àô,Ä!ãú‰ò z¸ç5Èkdù†Î‹êáòí ΧÿûEÔoŠoGÔŸPû÷ï—©*++wíÚU\\Ìú• ­geu>…hRZÚA‡Bœ0—ËûW•…êDë¹õp©]F¸‰Ó³‡Œë'ʃêáž×¯‘ë:/ª‡Ë·35Ÿ¬ûEÔoŠo‡ê÷£H$²dÉ’!C†Üzë­3gά©©™1c†ÿ…4ZÏÊê|Šà¥žTŠ Iióp9v¨N´žU—ÚeŠ›Hг‡Œë§6ª‡{^ƒ¼F.oR›Õ€Ïgj>Y÷+ŸÒ3î™pçwjß×;‰Ì›7Oî•’’²aÆwß}×ûü@}U\„FëYY/¥Ñ¼1©¸×x‘8:A“Òæaqìˆ:µë¹õp©]¦¸‰= qȸ~jó zPWþõkóy¨¿N›Ÿè#—Ïgd>¹÷+ŸÒÓSûöíC¡ÐÈ‘#/¿üòõë××ÕÕ;v,n,£S§NYYY+W®t]W}•ä+Åå!ÐzVVçSW_}uCCÃgŸ}V^^¾mÛ¶ÚÚÚgŸ}6…|C©ÂÂÂÊÊJïÝÁ…Çß·oß®]»öìÙ³sçθŸ=¨yÐúÞ½{WVV>ðÀÞá\uÕU¨Nízn=òMwâÞ£=öÇxï½÷ÞÖ­[+**Få8ZOû©æ‰µtìØ±555ÞrÖ®][WW·}ûöƒÖÖÖÆáiüûIäAõø?/áíÜüýEujóÓ}ÔúŒê42Ÿô¹¸sÈê»Ögâ¾HÝ}÷ÝÕÕÕGŽ9|øpuuõäÉ“c«D"‡úä“Oþö·¿UTT|úé§™™™ÚWåçç«yè‘¶²:_JÌCRéP4MJU޶N´ž[!.ç,7Q¥gqù|8s¨ž\7ÿõH±x–þ©i «òÏ·35ŸD܈Ìr1—-[–“““žžž‘‘qÏ=÷”””Ľ‰×Þ½{—/_^ZZºxñâP(TZZšššª¾jéÒ¥jž„#]VV¶©IC‡µß;µ:G¢yc|E¨Ò¡hš”š‡Ë± …BÚ:ǯ]OóÕz¸Ô.³ÜD-ÏL®”ÿ?ŽÓæßO:ªÇÿyMñ¹¾¡óÒ}ôÏ·35Ÿ(ŽúH×Ïê»Öç„}ÕùÌ3Ϩy***D=+///–g¶hÑ¢U«V½ùæ›®ëÆqÚüûùÕW_ió z:tè £ó666jã¹¹¹„ÿþ9|¨Nt^T§÷‹õå15ŸÜû…æ0@ßµ>{T6µ~oÍ´iÓÚ´iFec%Î*¿Lܽ{·ã8íÚµsG}•I8Ò¯¾újìFèÔVVæEðÆøŠP¥CÑ4)5ZŸBr¿Ô:Ñzn=“Ú…Ö£: ^â™!NËO”ÕÃ=/ŠÓþûçðq©it_üóíLÍ'÷~õsû®õ™¨?NÚ¯Æ"‘ÈÂ… ³³³ÿöÞ=>ªâþÿŸ³—dws¿'ä¶á›`E-VEÅR´ÁRýÖKm­zQZ}hõ£V­ÖŠH[Q(¢ÒÊ£X+U˯(" B H ÙMBîÙì%»{æ÷ÇÀqÙ=3Ù9»É™÷óáÃÇ2™yÍ{fÎì9gÎyϘ1cóæÍäGUèVXF9ì! zÂðC”…0ÒJÈ—ŽË—‹¶S€­3,?¯ÄéÚÅÈÏë›HsÏ¢ù´ñÆ“VMo{ãå×È7Fù4\þvqŸ¼ó‹ËŸRCœiú£ÁétƒAÞžž,]º4ú /ì! zqzÒüÆÅWŒázEó¥‹,‡©¹F1tFæ×¦‡×µ+2?M'­œ}×"ýá¸âI+‡Ý®èÛËNçr㊻½‘z4ûóÅ>>¹æc\qõ;#Î4ýCr™4ú¯³‡4èù<ô嘟« ùuioÓiõré¡1Ø:ãUï”}f åëÈ0’ ç>4?3†Ožª/Zaaa\ôðúÆÑ§ Z{y}ïh~{¼í¢A«—Ñ_ªýKÓÃ[>­½4hñäõSDü~~\ùyÓõÒOƒ×7Qƒ&/\úyý2iÐÚ¥ÁoRÞþŠKœ¹Jæuå=¢ÆÑA“w„¨×Kó]£ù·Ñ|Ñ,XPQQáóùº»»_ýu2ì¾h s²Hÿ6 >v´ò¹üÛî½÷^Z½ªíeÄgšßo»¢ôe¤é§õ/Moù´öÒÚE‹'¯Ÿ"¯#o~Þt½ôsÍ;F9ªýÂëƒÈÈχªãœ×/“w¼Ñ⣚GßV^¿RBRRR]]Ý 7ÜÀˆ$ïÌâá\Gà[Ù㼎¹Œ#-Btß5š›ª/Zfff}}ýG}d·Û¿ÿýï·µµýá0 _4š9™ª›;Zù\þm´tZ{q£Å™æ·ÇÛ.B”¾Œ ý4ß;šÞòií¥µ‹O^?E^GÞü¼ézéçšwŒrTû…ב‘ŸV/mœóúeòŽ7.¿É8ú¶òú•î¸ãŽãÇ“W+ð–ÌëÊë„Ê›ŸÖ㼎¹´vFÕÏŒáß&©ù¢-]º”¼¥‚ì^»vmuu5©F:C˜/ÍœŒáߦZ-?­|^ÿ6ÕtZ{y}ï~{¼íB<¾ŒìþŠì_†®òíUm-ž¼~ŠŒvÅËG“+]Gýæ]d9ìãƒê<¢OƼSÕ¯ZŽ¿L®ñƈïñŠ«¿4ø•¶mÛ¶jÕ*F$yg–†‘Ï{æ=²ÑFˆjäíB™Åόᓧꋖ““#IRMM Iw8ùùùD.ÍMÕœŒíßY#?ÍüŒ×¿M5Ö^FÜTë¥ùíihâñed÷Wdÿ2ôp•ÏðTm-ž¼~Š´v±ÇW~®tõk˜w‘å°$O”>ˆŒy§ª_µ ~™\ãM›ß¤j»¸úKƒ_)‰ÆìÙ³xà %ó:€2ÒyÀ¼G6ÚQ<£]§aû™¡ÿ6BØ«ž®ºêª@ °téR’gõêÕn·;t•ŽôES5'п-z;šù¯›jú€íŒ£ÞH¿= íâòePXÿ2ôh(_Õ_p@³ºÈq½Ÿ"­]އèóó¦ë¥_Û¼£ù’ªö â÷A¤Í»ÈzUËÑà—É5Þ4ûMÆîÛJ‹3CÿsÏ=·sçΰB¸z0zPF:ï˜÷ÈÆn—ꈢÍ,ÈÏ,Ò¿M•­[·~þùçÏ=÷ÜóÏ?¿aÆüàa«i¤/ÜŒáß½­| >y‘é¶7zß;D÷ÿãj—/ã€úUQÕ£¡|Õö²ÍêTÇa\üãå£É›®—~móŽíøÀëƒH›w‘°Ë‰ ãMƒßdì¾­4= ý×]w]è‰8oɈÓ”× •7¿¶WQÔ™ÅöSõÉ#D®ÃéééO=õÔ–-[^}õÕ—^z©»»[ùk¤/¢˜“±}é¸|ìTËçõÉc¤3Ú½ïù«¢VñÛãmÍgŽÑ^†þÈþ¥éÑV~d{iãô;mª–ÃHlW¼|4yÓõÒO‹³6_RZ¿ðú Òæ]d½´rn¸á.¿LÚ<¢7Z|Ø~“±û¶2âLÓ¿dÉ’öööÈ'¸z0rjá¼G`®#{dÒFmfÊBüÌdYVüÌH5Ä¿mÙ²e¡>y4ººº~øáÅ‹ÿìg?ËÏÏw8Ê鋆zýõ×—,YB*RÌÉØþmÑûØÑÊ·ÛíŒöªê¤¥3Ú7Zœ§M›¶eË–Y³f‘‹õŠßo»Ÿ¹Å‹“-* ,˜>}:£ú#¡éá-êÔ©ªí¥µ ‡ø†Æ“V-ž´v±ÇôùyÓi:[?-ÎÚ|IidžbØødÏ»Hhå(>”$›âã¨ø;†¥cŒ¹Æ->¼Ç+ ýE‹3Mÿ²eË>þøãûŽV2mfñŽpI’xÀ\G6vÄ"#Ï8òœîšŸÍ'¹Ïœ93''!´|ùr—ËõÌ3Ï(«±ªÿÍœŒáß½­|F{iåÓÒiíåò½cûFß.¿/#£¿TûWUoùŒö2ÆCdìõzCoÕ’Ì4ÿÂHs2#Å¿MµZ~Zù´ö2ÊWM§µ—7Z½Åo·]¡5FáËÈè/ÕþPO”åÓÚKk;žÑû)ÒÚÅ\ùµ¥ë¨?úy§Zãø@›GŠãÙ>ˆŒüªãPµI«_f”ã®ão x< Õ¿eË–}ûö=ñÄ‘;exKæuåuB>?­ÇiíbGž6³¾É¶üjƒ·Z½¼zxË.í‚øD_ˆ=´òõêwÞrâU¯^ýË›?^óB/ã–>,Æ[”åk‰±Y²îéñb¸p€øCsiâõ“ãõÍâõáãõ£égøÃ©–¯Á‡LÕ%‹7μåðº‹ñú®ÑôðÆ3^¾•¼ã–ŸwœóŽC¼þy¼þ…¼~™¼óeü`( ¹4ñúÉñú“ñúðÑ|ÅÂܪhúinXŒò£÷!Ct_1Þ8ó–Ãë.Æë»Æë‡G‹'­½¼nd ý\ùyǹj»4øYòúçñúòúeòÎÞøGñcÇHˆ:::*++Ÿ|òIm[?4T ŒtT]š4øÉñú“ñúðÑ|ÅanU ý47,Zù\>dˆîþÅg®rhñן·]\ñd´—׌¦Ÿ+¿†q®Ú.^?KI’xýó¸ü yý25ÌÞøGƒÓé\¿~ýܹsçÏŸÿè£z<ž‡zˆw-ÔV50¢¡¹4ñúÉñú“ñúð1|Åš[ÃoOÕ ‹Q¾2C„KoœyËáuÓ໦ª‡7žŒör¹‘1ôsåççŒq¢:Îié¼þy¼þ…¼~™¼ó…7þa‡E‹©¾çÝét®ZµŠ”i0vîÜùá‡*ëkä·"S¬"1Ñ\šxýäxýÉx}øh~c‡ÂGºU1üöTݰhå×××kð!#„š7μåðº‹ñú®ÑôðÆ377—Ö^.72ÆxãÊÏ;ÎÙã0rœÓÆ¿ÿ<.ÿB^¿LÞùÂ…ÌÌÌœœœ+®¸"--íóÏ?÷ù|mmmayHÛGURRòþûïcŒ#¿E©šq·Z²dÉ€þd´rêêêTý½Nž<‰*--ݱc ñûîw¿KܪB)))’$-X° ½½ý“O>QÕ_âž…1Vܰ?³°òÝn·²HqSÕ©¡Õøóæçmo<1Æ´ö¾þúë|ðÁßÿþwŒq¤YdÿbŒ#õóæGg|%£çŒv©ŽsBdºâ“V¹Þ™>eÊU=ùùù\ó—Ô}hýKîòÆŸäùÅ/~¬V«,ËaBä¾#9M¬ªª"¿œ$IŠüVXJ4Uÿå/ ­.Ÿ§a¸4ñúÉqù“ñúðI_1Ý­JU?Í ‹V>M#éðÎg åp¹‹1ú‹«]âIk/¯™ª~Þü¼ãœÑ.ÕqNK§•CK×à_Èå—É;_4Ä? Õ³1§Óùç?ÿ¹´´´¸¸xÆŒ›7oîééQž\Tý–’}ՠͥ‰×OŽ×ŸŒ×‡æ+¦æV¥ª_¢»aÑÊ×àC†Ô.iòÆ™·^ß>^ß5U=âIk/¯Û/3úü¼ãœ1¹ü,yýóxý yý2yç oü£ÁétƒARfOOÏ–.]ªá™z U#™onÒÊáò•ÔàŸ—ù;xðŽ^ÇSÞÐêå=‚q;ÈÒ|æÂ̽x}ãhéñò“£ù¥1Ú¥ê·ÇëKÇå#¨Á—‘á×ÈÛ/ªí¥Å“ׯNµ^F{yËW:mœpùb2ÚÅë¿ÈëóÇëIÓ£Z¯†þâ_´ñÉëOÉ;ió…Þzií¥åÐ'‰ IDATç/ìãmRRR]]Ý 7ÜÀp¾¤•À5B#÷FÓC«—÷FËÏHGˆî3Gˆ4÷âõ£¥ÇÅOÑýÒhíRõÛãõ¥ãõÔàËHKçíš¿ -ž¼~uªõ2ÚËU~¼Òã„Ë“×_0Ž>¼þ‘4_CÕzyû‹w~ÑÆ‰JÞùH›/´øpÕËh/-?ï|aoï¸ãŽãÇ›Íf %pÆä=‚ÑôÐêå=‚ñ:ÈžF¢øÌ!й—o-=^~rˆâ—Æh—ªß¯/¯ R—/#ï‘·_TÛK‹§¿:Z½ªíå-?^é´qÂë‹Ik—ÿE.Ÿ?^ÿH†o"c¾Dß_¼ó‹6NxÇ•†ù¨:_ñ᪗Ö^F~®ùÂ>Þ"„¶mÛ¶jÕ*Ýù’Vïáu<ÕÚÈä:‚1F -&|ª¹—o-=^~rˆâ—FkÍo×—Ž×Gqú2ÒÒyû…Ö^Z<5øÕÑÆƒj{yËW:mœðúbÒÚ¥Á‘Ëç×?’á›È˜/Ñ÷ïü¢Þq¥a>ªÎF|¸ê¥µ—1¹æ #?iÅìÙ³xàFÒJà!¼Ž§" Z/Ÿ12Ï"òU^“&MêèèøÉO~²lÙ²Ð÷mß¾Ýçó:tèøñã^¯W±Ë¡å§¥+\ýõ‡\ÎÖÿÒK/=zôheeeuuõ‘#GÂî5†µkôèÑ@ààÁƒ_ýõ¼^ïÓO?m0®ºêª@ °téRòÝÕ«W»Ýnå[Ó§Oߺuëþýû[[[¯ºê*I’ØùUãIX±bEGG‡òþ~ZùŒt®~¡µ—OÕtF{iãÑÞèËW:{œDÆyÀ¸…µ‹¼Ó+Ì5bΜ9 .Ô 'ú~¡é¤é‘$‰]o”ý¥$F9¿hãD۸⚪ó…®zÙãDuþòÎFþçž{nçÎa™(KÐ#«_híUBOÕtF{iãÑÞèËW:{œDÆyÀ¸…µ‹vXaŒ+ö¸²_h:‡9v½Qö—B”óK’$Õq¢m\qÍGÕùˆW½ìq¢:yç #ÿÑ£GW®\v4²Í#Du$pÁh-R­—÷FË?fÌv9êšaîE^œH² èwÓM7 ªŸÛ/-²] ¿=^ÿE >‚Ñû2ÒÒyû…í/Hó/äòíS­W:s§Dµ½\åÇ%=N"ãÌŽ[ôþ‚´qÅëóGKçõïœ7o£^®þ"D?¿hãDøŠ~>Òæ -> ƉªNÞùBË¿dÉ’ööö°' ¢/6bÙ#„×ñ4úÐêå=‚is¥¾Ö]1÷Z¼x1¹½`Á‚éÓ§K’ôúë¯/Y²„|?Ò7.,ii)­tÆmÙ²e‘~fQæ/ ñK“eYñK _çÏÀðÛ#~l‹/þÙÏ~–ŸŸ¯øÒmÙ²eÖ¬Yäb´â÷FËO‹'AÕ—QµüiÓ¦©¦3â©Ú/lÁÈx2ÒiíU­3ýù¸ÊK:mœÐâÌŽÃ_ü3Ò1J=´qN‹M'MÝngÔËÕ_ª0âF'\ãŠw>ÒŽ'НddqÕKk/C'ï|¡å_¶lÙÇæ} ´°GHäHà=‚ÑôÐêmooç:‚Ñz$Z§Õ°_vº¹—o£œ¸øÉ1üÒTÛ…è~{¼þ‹\>‚„è}ié¼ýÂh/Ã0z¿:F½ªíÕP~\Òiã„דÖ.‰Ó‘1nyû…Ë¿“=_¸ú‹w~ÑÆ ׸â´ùÂè/ÞzUÛËÈÏ;_Tótww_sÍ5a¿ø£/AÃár<å»^Þ#˜Yê€V»ÅëGK—ŸÍ/Ö.šß¯/¯ âôe¤¥óö ­½´xòúö1ƃj{yËK:cœðúbÒÚÅå¿ÈÐÃÛ/\þìùÂÕ_¼ó‹6NxÇ•¶ù9_hýÅ[/­½´ü¼óE5ÿC=täÈ‘ÈÃuô%h!¼Ž§\`ÔË{Óà ûÍ•üz õ™SÎ6÷’8}ãh鑽¨ÍON¢ø¥1ÚeTóÛ3púÒÑò3ê%‰Qú2ÒÒ5ô‹j{iñ¤¥³ã£Z¯j{yËW:mœ0â¬7v?FúòêáíšNšÆ|áê¯Ð¯D3¿hã„w\i›ˆ2_ñ‰²^v{ió:úù¢šË–-ûöí{â‰'T;Ñ” a„°ÀÑÁØzTG&׌–Ÿ‘®²†ÇZJüàÕCËO+„7?/ŒòãÕ®¸HåOËW:W|4Ä?.zx‰×xŽâ<¨å0tÆ«ÞÁW¡ùÉ]’è¿ÎV•_Cù"DLs9ç>¼¾€ ß>Uw+Z:¯¯+ >s\î\¼åÓ •ÃëÚEƒ×-ŒáFÆåÃ/—2^?9 ý¢ê·ÇçqÑÉëÇí¾F!^ãVâ[÷ç24W'^ÿ0š»-qúxÑòóúÒÊ¡å§éárÃbøñêäuíâm­ßiíåõáãõY¤µ—×OŽ7>4¿=Z½´vñêäu‰c´‹ËpÀø08vì)­£££²²òÉ'ŸäÚÊ1à€A‡æêÄëFs·¢¥óúxñºR"}ÈØ®T‘ùiz¸Ü°na¼:y]»xÛEs £µ—ׇ×g‘Ö^^?9ÞøÐüöhõÒÚÅ«“×%Ž×}M[|Ø8Îõë×Ï;wþüù>ú¨Çãy衇¢_ ÙC†«—ÍÝŠázÅëãÅëJ…(¾} WªÈü4=ܰ”0†¹…ñêäríâm­ßiíåõáÓ೨Ú^^?9Þø 3O5…ùíÑꥵ‹W§A^÷5 ñQX´hÑ~ðƒÈ?9ÎU«VmƒaçÎ~ø¡²˜E~+4…=$`01üƸüÃhîVäéÈÈôúúz./^W*Ò¼H2¶+Ud~š^7,Dw ãÕÉåÚÅÛ.Z¿ÓÚËëçÁgQµ½¼~r¼ñA¿=F½ªíâÕÉë§Á}MC|B™™™999W\qEZZÚçŸîóùÚÚÚÐÙÍ£F*))yÿý÷1Ƒߒe9,…=$`¨ s™âò£™zÐÒ‰)Fô>^|õT}Èå0|in[‘õòúØiÐÉëÚÅÛ.¶_ZX{5øðÑê¥éTm/¯Ÿœ¶ø ˆWˆ1êUm¯N^—8 îkÚ|+o¼ñÆžž‡ÃqòäÉžžžŸþô§¡u: _|ñÅîÝ»[[[¿ú꫼¼<Õo-]ºTµö€Aå,—©—^ziÓ¦M6l ?Ç***{ì± .¸`„ Û¶m#fëÖ­ŸþùsÏ=÷üóÏoذAõ:Iô|ùå—3fÌøÖ·¾µzõê»ï¾{ܸq¤´îîî={öìÙ³Çd2]yå•J´üªúŸyæ™}ûö½ñÆ‘¿.UËaä§éQ­—­óG?ú1NSJàÕyíµ×¦¦¦’ßò¹¹¹Ƈ·]ªýÎno$ìq¢Z/M'£½ª0ôóƇÆ8áÒ© o¿ÓÒyãCþôÎ;ï\wÝu)))ÙÙÙ7ß|óš5kÂ^îUSSóÞ{ïmÚ´iíÚµ999›6m2‘ßzûí·UËa‡nË–-{Î0oÞ¡KÎæÍ›7nÜøÁE.ôât:_}õU“ÉD _¸p¡ßï'_ü–j9´)F¸ýöÛy†²²2XørzzW§%K–„ú½þúë|ðÁßÿþwŒq¤˜$Iã7ß/ÅÿlÇŽ(ÄÝ* ª¦»Ýnš×ï~÷»'Ÿ|rÏž=cÅŪ®®n@WªPýŠB(%%E’¤ ´··òÉ'´zUó·´´<ñÄ‘zZ[[Uëåõ±ãÕYâc‡1V\»víÚ¯vÑú]µ½´~§“©S§>ùä“‘õ*>‹a:‡j{7µÈz×®]©ŸáG‹¿ê "­½S¦LQm¯NZþÅ‹sõ;Û0úø„¶ý¿øE °Z­²,“y ¹LN着ªÈ/!I’"¿–BdŠþò—¿„VwøCsuâò“(îV´tÄïãÅåJe`úF–CËÏÖÃ内ÔÜÂxu–qºvihÃ×0²½Œþåòw¤é¤µ—Q/—/##þ„°3BZ½´vñê¤åçíwF:¯oeªgcN§óÏþsiiiqqñŒ36oÞLÌl•Ì‘ßRRC†š«¯Íß‹–ÎëãÅëJ¥40lGÕJ5?M¯¢¸…q锸]»xÛEëwZ{¹|øõªêd´—×OŽ7>„H¿=Z½´vñêäu‰ãu_ÓN§3 ’±ÑÓÓsàÀ¥K—Fÿá€C EáóÇåFs·ŠLGœ>^´ü¼¾†´rhùiz4¸a‘» 4¬(uJœ®]¼í¢õ;{œDö/{œhðY”Ô|njQú22âÔüöØõÒâ½ÎóGßïìñÃacƒ\&þë ÐòkT5–Ÿ7V>W:/¼å v~ÞrâŸ8–Û/¼ùãÕ/¼õvþAMt¬F.4Ÿ¹xùÀ1ˆ‹ß¯¯!­^Z{i¾zñò·£•Ï ­y}y}y}%4å¨ÂëçGƒ×çOƒ/ Wx}1yËáõ¥å×xFq:>ðÂë»Éˆ?WÿÆ…¸Ô¨a„ ª$ã§OªÏ—ÍoïÞ{ï¥ùðÅËï qúÒꥵ—æ«§Z/ÃwV/£|B¨O£|Z?jðäõ}äòM¤ÅAµ½Œrhùyýü4øóÅ%7¼¾˜´vÑÊáõ¥å§¥3â¬ÚÞxTëÕ0hõÒòÓô³ã””TWWwà 70Žœ¼£Õ¯Âë0ª!]uÅËéó44Ÿ9.8šßÇ/^~o¼¾†´zUÛËðÕãõT­—Q>!Ì'Q¾j?jðäõ}äõM¤Å_µ½Œrhùyýüxýùâ•Î^_LZ»TËáõ¥åg”CÓCko¼ŽªõòÎ#F½´ü4ýì8ÜqÇÇ7›ÍLykŒ×áuåM§Í x9}"Äôóãõ“Îæ·ÇH7Äì÷†ø} U륵—æ«G«—·½ŒòÝ'/²|Z?jðäõ}äõM¤ÅŸÖ^Z9ªù5øùñúóÅ++|1UÛE+‡×g”–Ÿ1žiqfŒó¸hõrÍ#Z½ŒøÓú—„жmÛV­ZÅ>rrEŒQc\Fˆ‡QÞtÕG§OÄö#äõSž óÛc¤G¾6×ïæ£Æ09S­—Ö^šÿ¢ßAÕziå“¿Ò|ò"˧õ#­üxù>òú&2âOk/­Õü¼~~ˆÓŸ/^é¼qàõŤµ‹V¯Ï(Ío’1žUõ°ÇyìÇF½\óˆQ/-þ´þeÄaâĉ³gÏ~à”"òFŒQc\Fˆ‡Q®tÚ Š£ÓgxÄÂüüx}àH!‘~{ìôýÞØ>j “³ÈWg©¶—濨ÁwPµ^Zùh Ÿ£´üŒrhzÛ’íûå<°êèó3ô\wÝu¡§}4…¼£ÕÇÂå0Ê›ŽÔf¶ÓÆ?@àÜÅÍIœ«Dë“ç$°#Sì7¨`øg„ÀˆB`Dþ†Ãâââ .¸@õÀCC Ø»w/ãñ;P8  0v@aì€ÂØ9Úl¶ôôô¡” GùçYáÃÛíöööö!Wõ ’$ÙívZXAa4€ÂØ…± cçPèóùB_‹(’$%&&bŒ•§Ã/†½Ô`0ämªÆ  C¬Ðl6‡ýÚPah‘x #…°X¬(ä©_†!šÂ°C O¡øG£ÑÈ¥cìõz…ZBcǪê¬]£Ê‹S‡€²Ñc²³³Mf³Ñht45Õ×Õ*U3Â:” 3³²ÊÊF[m6„ÛÝWW[ÛÕÙ)”¬¬ìR»Ý–”„òz½ -ÍN¡$I:ïüó“’’Oµ¶=óÒ^AŽ7.?ÿ,Ó¯öïs÷õ!a †1cÇæäæFŒqÓÉ“Çëëĉᘱãò#l`™Ñ"(D¥§§—“”œ,I’×ë=q¼¾µ¥…üI…iéé£GIJNFõôt×=Ú××'”Âä””ÑcƦ¦¦"„\½½uµÇzzzT(ÚJ¨lÝ6Ë¢eÀ·ÀéBbbâ¸òñ¶¤¤öö¶®®®ää”qãÊ…z OBBÂØòò¤ääŽöööö6«Õ:vìX2‘D£´´455Íh4Jâõµ%Ñb4û\®ž3½EEù„ £ ƒÁ@kKKG{»÷ì_²ºãñ¸;;:”ÿüýýdÁÖ[×YŒWž’šÚÝÝÕÖvÊjµŽ;.!!AoQß`6›ËÇOIMíìèèîîJOÏ+ØÑ!T>~BzzzggGWggjZÚ¸ñã gû*kt»ÅZ{ìB¨|ü„¼ü|½40ÈÊÎNHHèíé©®¬ÄÏžs¡ÕfKJJr¹\zK;Mb¢¥ÏåêðykÃO›>=--=55­O…[RÒ¨¢bY–ÅüÅC®•UWUz½^’"ÔA<)99;;' :xÐãv#Áä!„MMN‡ƒ|NOϘŸÏï÷›Íæ´ôt¯ÇcNHeÙ#ÒL1'$Hy}^r±ÎëõZ,Öä¤dqB›Í†òù|D¡ÇãNJJ²X­z늺-„‚ÓßßßßßO>—c0ÚÛÚ”AÀ§¤¤Nœ<Ùd2Æ“ gîb B~AAfVVÉãf³@W¢B1'$ŒÆÑcÆ’+QÙÙÙ¿> ί4£Áˆ²Ù’&Nšl00Æyyù_íß õ–NqI‰Ífs8š\½½zk9 ,ËuÇŽ;vÒä)!I’êëjÉéµ ø¼^ŒÍ–D®šÉ"Ô¹“…N_­•„’ $IBýpÔŒ@±“R»=77×ãñÔ;*ÎñQA–e·Ûíóy%IJÏÈÛ§/f³¹ÔnïíëBY(’ÁÐÓÓÝÕÙ¹ßÞ¯öíõûýiééÙ99zë AB¡€ß¸âÐýû|>¯-)©`Ô(½e©››‡1nv8ìë윜„„Ÿ×ër¹$IÊÎÉj¦´žju»ÝV«õ[3gΜ=‡œ~C ,„,ò ŠKJýþ@Uåå’Pôõ¹:¸ïÞŽŽöä䔂Q…ʯ6Ý))µ'&ZL&Ó´éÓ³s²B™e£Çˆ³ ËòáC‡üÚÝ×çr¹zzºB6[’81 !ŸÏ×ÕÙÙÓÓÓÕÙ…²X­âÄ–žn±Z}>Ÿ²×Qò ²²³û\®}{¿üú«ýímm©©©£ŠŠ01IJ|øÐÁ§Ãçõµ¶4÷öö"„0è÷„$iœÙØ0BËÁsãt…=>Á~`eP ­š½wèNÈÎ=z BèØÑš°‹õ"(ÌÍËUXØÛÓ[W{L¹i0BìÑY!ÆØçó£Ñb4šBF£1!!cQ¦¤¤”–•ùûý5ÕUc"2à÷c,³e ™Bò ¹ƒ16™M!¿? N Igžá «W… Býýýäaƒþ~BÈd4!‘bèñxª««BF£ñ[3g!„~B ÈÍËÇ÷öôÃŒÌ̼¼|¯×“žža±X\®ÞŽŽ½E}Cgg‡ÛíNJJ?q"Â(99ÅëñtèúF›ø ¡:6«ßɆ¡†¦j ‰¡¿¿¿öèÑR»<ÃãóùNÔ×»EÚF:VS3®¼<##SÊ”ˆÂÞ32 „d@H²@«ÐÛÓS_[[\RBü÷÷÷766´¶ïßfµeçäG0;::jе#c\S]5fì¸Üܰ_bb"y;€ cAç…PähЬMc,ÚŒ*"SübŒ=Ñê-a0Æ¡nâ÷ûE{B4 Œ±˜{cv#•]£ºïÌp—(P; 0v@aì w…C,&zBeÃ!0¢…ÑÀBŒhà9B†‹ÅzÆý »»{ˆÚs X~\wÝu , ûDžzê©úúz‘÷e‚¾k‰±Ï‡½ F(ŒP;ƒ¤P’$ƒÁ l˜dl\ÔKaÖ 5lj•$i:fàŒ8׸ᆈ—[CCî]»D8LqÇápTTTƒ¬Ëå‚^>g «`FFFbbâ€Ý–A’¤@ ÐÝÝÍûú7XsË/¿Üd2!„öïß¿{÷n8Dž“|úé§Ÿ}öù 7ÏŒFc0œ?þÓO?m±XHÏ’ÿ+'p‘‰JŠÑhìííýÉO~ât:¹ê……8×$‰œ(èþ 10xÄr-² ^tÑE/¾øbjjªrác É:G¼´~¿Ÿ¼¦œ$*K#¹ ÄE< .¸Àn·ƒÁ#GŽ;v,77·°°!ÔÛÛ{ìØ±¡µeee¡þþþÇ&“iêÔ©’$9NåWCIIIvv6BH–寿þZÇ –=uêÔ¬¬¬`0èp8<(Ô •’>;vì”)SZZZ¾øâ ŽJS¦L!ž!›Ívþùç»Ýî*1¼ŸÂä…¡×4 ¥¼¼<99=eBãÇ'ŽƒG`åææ’Ï•••BMBjjê´iÓrss%Ijoo?xð  ÎJÊ,îèè8qâDiiéÔ©SÇÞ½{õzß)YçÎûÇ?þ1555 ²¼I’ôì³ÏºÝîGycŒFcSSÓ£>zÓM7}ûÛ߃!’“|æÅ6¦µ ñ’’’[o½µ¤¤„ü¿öÚk?ýôSŒñüùó%I:vìØÓO?}ÉìßzÑ—3gΜï|ç;’$õ÷÷ÿâ¿èïïGþù·ß~»Á`Ø»wïêիɈE‹MŸ>]’¤S§NE³ÆKa(F£qÙ²esçÎ%¦—¤œÎÎÎM›6i¸¾7 B‹-"?#Èí·%K–˜L¦ýû÷kXCáí·ßž””¤ü?~|yyyssóÃ?¬¡À¸+¼õÖ[ÓÒÒhå&h^ýõ£G&îßüæ7J K—.-..FñsÆ!BhÞ¼y—_~99à<ùä“uuuÚJ$…?üáçÏŸo±X”Ëýýý;wî|ë­·xWš¸+TfqMMM}}ý‚ È­Œñµ×^ûÆoÔÔÔÄkF¹Y†¬‚sæÌyùå—ÓÒÒ‚Á Y•B‚Áà¦M›L&Ó¯~õ+£Ñèp8î¿ÿþššš¥K—’ÓAR‹fÙq8#´X,wÜq9ùSZuÉ%—¸\.£Ñˆô»BU]]½`ÁƒÁ`±XÊËËÉ/Ü)S¦­ãÛ8 IDATFI’Ƨä,(( Rt‘ŠºãŽ;f̘zR/IRVVÖ-·Üâõzõ=O •D¶êedd,^¼Øl6#„z„ñ85 aT.“Š@˜<Qú7,h$‰tµ9lרPÜvÛm^xaX_'&&^rÉ%YYY/¾ø¢¾75•Е•••——+:%I*((¸ýöÛŸzê©ö!t6%§q³fÍúÓŸþDVA²_FA–e²þ­[·!´|ùò{î¹§¾¾þù矟;w.É/˲riTƒ†8,„W]uÕ¨Q£Èg‡Ã±k×.“É4kÖ¬üüüØ …ŠŠŠþþ~‹Å‚*++;|ø0BhüøñdòdddL™2åСC‹%''‡|E¯kSóçÏWVA‡Ã±gÏ«ÕúíoÛf³%&&~ï{ß;xð  ‹ œÙôööú|>Þû҃ǻï¾k6›oºé&ɺºº/¾øBœ-…û÷ïWžGÆéÓ§“Á`ð“O>D' ]tÑœ9sÈliiÙµkW ˜={vQQ‘$IS§N½òÊ+?üðCú:11±££cÏž=}}}³fÍ"'ýYYY×\sͺuë†F!YófΜù§?ý)===r$ ¡,Ë÷Üs$Iëׯÿ׿þ…zöÙg/¼ðBr™Tɉt\/¸à²´x½Þ—_~¹¹¹!´}ûö'žxÂf³Å^¾f|>_CCøqã$I*,,$¿€”5!4}úôC‡7ŽœbŒ:¤Ë½øâ‹ÉÌq¹\øÃÚÚÚBn·û{ßûž$Iv»½¸¸øÄ‰C/ŒÁ?ÿùÏ-[¶„AÝùôÓOB7Þx# fggç¶mÛÈ•½¥!„кuëBÏ`V¬XA.I!„>ù䓽{÷ ¢ˆ…ùóç“á×ßßÿÇ?þÑáp „>ÿüóG}4--M’¤‹/¾xëÖ­"ôµßï饗Èe°;w>ú裩©©¡éÓ§¯_¿~hbŒ“’’{챌Œ eóK!r±ôºë®{ÿý÷O:uñÅ“UÐ`0(<–…0Ö 5ÉÉÉäsmmmKK ‘ÞÞÞîóùb,ùä“ûï¿ÿ¹çž³Ùl@ ôê(™N§ó¾ûî;~üøÓO?=oÞ¼?ýéO7n4?ÿùÏ•×Ðà¬c=# ½øÙ××ciq§¢¢‚ì«¶X,Ó¦M#?Öššš¾úê+µ .¸   @ùa®ËÐ ½od2™,gP¶"‘6)1’ðãÿ˜\ƒ ƒ6lÐå:0„Îå°':B¡ÙÄ¡··Wù<” 1ƃáÿûßÊ•+].Ù;CÎÉ*ˆ1~üñÇkjj~ÿûßÏ›7/Üu×]Ë—/÷ÝwÿñSÆÝ*õ\ß½þi±Xh%p•ÌÈÌ«°¿¿¿¡¡a„ ’$]~ùådc‘#GvïÞMž¬˜óÌ3IIIäiøÌs„7ÝtÓ÷¿ÿý9sæ›…¡[n¹%77wÖ¬YèÌŽŒ1×KJCeÇzi´µµU)+''gh^–ÊE}}ý„ B'N$çU{öì©««s:………cÇŽ%au:d‹ÊÐÓÜÜì÷ûÉùŸßï'¿q"³‰X@_|±È·•GÜB¯FÑÓÔÔ¤ìT5jTèñP¹/(Ëò‰'œÎäþáÔ©SC\;Y ?ûì³_ýêWÏ<óŒÍfSöȲúè£Ñ£G›L&£ÑxÛm·]|ñÅííí&“©   ¤¤¤ººú¹çžð'¤˜tww“ËÝååå÷ÜsOkkë[o½¥{ôÌfóüceEÁßqÇ¡úúú^xá}O«««çÍ›G&Å]wÝUYYi4ÇÇx!ÆG}4~üx³ÙœpÏ=÷9rÄï÷O™2…¼£cüßÿþW÷ÑH0›Í÷ßeee (//OOO'éû÷ï×K!yŽpçÎK—.µZ­¼×Æ$Iòûý]]]¼õÆa!|ÿý÷Ï;ï¼’’„Pzz:¹h‹ÎœêÆ^~Œ††åºè¾}ûHzuuu[[9bƒA}ŸXß»wïG}tå•W ³ÙÓ}4dYNJJš9s& QØÚÚºyóf‘[}Cü^V> Eø|¾—_~ùÀä„T’$¯×ûÞ{ïižØ˜‰†ëêêȇ¶¶¶#GŽà3{m•«¦N§“+îqWˆ1~÷Ýwß|óM²©Zy7˜×ë­¨¨xõÕWyï_Æ]aÜ<…ÿøÇ?öìÙC®:J’Dögê®p0Â÷U«V)WM$Iêìì\»víž={4ì‘61Æ›7o^»vmè\Fµ¶¶nܸqݺu¼kÌàÅÐçó½óÎ;}}}D¡,ËÕÕÕ/¿ürgg§¾ ‡fl„ŠŒûDkkëK/½”““SRRBn¿¹ÝîË.»,.…ÇÎßÿþ÷÷Þ{Ùƒ¤¤¿ñÆo¾ùfdº.`Œ·oßþé§ŸŒ5Êh4vuuÕÖÖ*O˜ê+ðÒK/)±ê1.—kõêÕv»Ý`0Ô×׋ Õétþ¿ÿ÷ÿ'U‚„´¹¹ù™gž)...((p¹\ÕÕÕäîŽ;ÈÖD"„6nÜøÎ;ïÏB½Õ!„1þì³ÏvìØQXX˜ŸŸo0ZZZÈcyBéD}üñÇŸ~úiyyybbbcccss³ ý;ÄÄ͆I–å–––ÖÖV$ÞþF|æ©Ì0Dër2OšššÈk™x‘-b4dYnoo'gùâÄpEïĉäÍ[JôÄ #6©ÌåÆÆÆ“'O"ñ¢§€1v»Ý_ý5XägcÞ‘Ê8aŒ ÆX€èÅ…aÆa!rPÚX€M¬¯XcðôÓO“ÇÕ}>ïÕ|š qî6ƒÂØ…± cg¤)|óÍ7ÉCÞq¼ÏÊP—òƒÐèÅùa(âøµ„¡tŸ.À¥Q`D !0¢…Ñ âfÍ0d€Â(…± cÆÎpW8Äb¢'T6œ#X€ ,„ÀˆB`D !0¢]£Z…± cÆ(ŒØ5 Ûð…Päœ cÆ(ŒP;â+œµbŒ=¾‘Å»ÝnÆ_Aá€€ÂØ…± cg¸+D!=²,‡þS*..Vþ1¶Z­eeeIIIC.ì4n·»¶¶ÖëõJ’ùWP  0v@aì€ÂØ9ö÷÷›Íf£Ñ8ôÚh¿ßŸ˜˜¨h>k!DƒA¿ß¶Z%ƒ5P8  0v@aì€ÂØ97ö÷÷ë¨0ƒÁªY***ÒQè ìF4°#X€Iß­· /pFŒh`!F4°#X€ ,„Àˆv#8#F4¦A-½´´tæÌ™&ÓàÖ ìÞ½»±±‘–A|…h8ˆ… cÆÎ€ SSSóòòT­$Î0ÆÍÍͽ½½JÊ öƸ¬¬ìÔ©SƒWÅ€H’TVVFëuñ¢á F(ŒP;*”$éäÉ“çö-3I’HcIÊà^ÕÝzƒt'£SÅWˆô) V›Mù§8a 3OQG!!!!Ál6‡¦ˆ¦0P;ç€BŸÏwn¯‚!Œ±×ë mæ n–Á‡.¹z!Ë2­â+DC.2-=}ÌØ±©©iƒ¡¯¯oÏ®/ˆ6ýÃ(Iç7=3+K×ן8q<ìïú+D!”˜˜8yêÔ´´t„ЩÖÖÇU‚(d cg¸+b1:Bºƒ|†Í2À7X,–)S¦fddvuv6lìho×[Ñ7äçdegW:xêÔ©»]’¤Q…Eßš9K÷ÃJv{YFFfwWWooo^~~!ø}ž£˜Íæüü‚ìì½…q@·{¶€€ä$Z,]¿>Í5Û¡Äl6cŒ»»º’““FCBB‚Ýnw8zë ‡\R>^_g±ZSSS-«$Iâ„Q!?¿cÜÒÒ¬·áJRRÒÄÉ“]®Þöö6ûàBà4¹yyÙ9¹’$I’4zÌX„PGG»8'…r08õ¼éV‹¥·§wÌØq@àĉ㢃z]½YÙÙEÅ%É)ɲ,ŸjmM¡Åj øýyùrPnoo“$Éï÷ë-jXB&‹Þ*€8 !pšÄ„D²¿Ãd6%%%!„z{{ôõ ®ÞÞƒ¿ÎÍÍíêìèíí8iòÁ¯`½·Dr²¡¡¨¨8'7×ßß_]UÙÝÝ¥·¢pìv{^~–eã ç]t²±ñx}h«uèV#ÑÖé’ÒÒää³Ù$IRb¢eâ¤É¡ÆÆ†Þæ À,„ÀiÜw¿Ïk³Ùú}ý]]!Ÿ×§·¨³èìèèêìD’4s欖æf“Ñ4v\¹»¯ÏáhÒ[ÚiL&Óä©ÓL&ÆØ`0ô÷÷[m¶é矪õTí±£z«;M]m­,ËÅ%¥¡Ç;šDÜ+ÑÅó•“­Ÿnïïï×WO(éé9¹¹äsBBBÁ¨Q¡¶S§`!¾ î®Q$ÆM&ö)‘¢!™œ””h±`Œ-VKVV6B¨ß×ßÙÙ1 È¡ #ƸlÌ“ÙÔÛÛ3iÊ”žî‹åx]­ ‹KJÒÓÒ:ÚÛÛÛÛF;aâ$§ÓaµZ1–Ù†2†ý~FffWW§ÅbµZ­aÛåEPˆr:š”…0 ¥°¾®ödc£Åj?a‚Çã>Z]ƒ1îééVªÖ]á€À®Qtö®Q8#NsâÄ ƒÑTVVæîs}à«ÐQ"É))¥¥öšêªÌ¬,Ÿ×{à«ýSÏ›ž••IBÝIHLD’äv÷5œ8‘XRZj·Ûe·´´ˆL,Ë';;;“lIHôØWUY©|MaOOB(##!$Ë2l–9€…8 Ƹµµ¥¸¤$#3sâäÉ·!\_'ÖÝ#»ÝÞÕÙét8ÒÒÒLf³Ùl6›LÁ@Po]§éîê5ª0/¿ ”Íf³,˃Áãîës¹ô–v'B¢© E¨QœóÀB|ƒ«·÷ÈáŠÑ£ÇäååKy<žúº:½EEuU•ÑhÄŸ¸Ýî'žx¢»»[óž‚áÛÑç¼ÂíÛ·úé§äsŒ—pGl ãÈ)4Á`0;;û‘G¹òÊ+Ib,« ÑhLOO—$©³³3ÆëØ¡kYF ‹…œ(tvvvww˲,Îñˆcù zk†r!7 ^xá…7n\¸p!éz24›––öú믿ùæ›999ñ+ð¥Ñ²²²I“&¥§§‡Ã±oß>·Û­·¨³˜1c†ÝnOLLìë뫯¯?xð €GðY³f•••ƒÁ¯¾úªN0+‰I“&%%%‘={!³Ù §—‡är¨ÉdúéOz×]w%&&âC¶Œ’Ørí%™M&Srr²Ùl6q,âBh·Ûo¾ùæ &(MÅ»\®þóŸ|ð#ræÌ™Ë–-ËËËSnùbŒOž<¹aƯ¿þZ…!»Ý~ÇwØív"rñâÅÿùÏ„ºG½|ùò²²2å:Innî}÷݇Z¿~ý‡~(B‹ŠŠî¼óN²‘!´xñâíÛ·»\®«¯¾Z’¤†††|P¡K/½téÒ¥ÉÉÉ!Œñõ×_ÿÆo|ñłț5kÖ7ÞH†ßË/¿,Ž0UV¬Xqá…µÛ·ogR È*XZZúØcÍ;c  ƒrË# ’Ýp\Q%™À`\4n!ÌÏÏÿå/™zÈ–$)55uÙ²e²,ë~ˆ<ï¼óîºë.›Íš(IRIIÉ=÷Üó /TTTè>m,ËÝwß]TT¤¤˜L¦… ê.,rñ$4…üSÕ:!!áî»ï.--UôÆK/½´§§‡üDD'B(99ùÇ?þ±rn-IÙ¤~üøq‡Ã¡¯6ékå<@o9,f̘1gÎÒÅ'Ož\¿~=\ÎåB–å«®ºêá‡ÎÍÍ ¤ßñÙÞOÙÙÙÊ9b”ÅJ’ÈÒpî/„×\s² ~øá‡‡*))ùÞ÷¾g±X ÃÂ… ·nݪïÑ|Ñ¢Eä±Öžžžµk×VWWÏœ9sùòåf³Ùf³]wÝu‡ð‰]´hQaa!ùìp8vîÜ™0oÞ¼¬¬,}……²eË–´´´E‹Ummmÿú׿0Æ‚ßÚµkE»##8ƒá±ÇûሠƒÊåPåtcl³Ù^ýõ°ttæ•7a™Ã> „¬V«Ç㉯lá^± kkkɦ uëÖɲ¼oß¾âââ¹sçJ’”“““››ët:ã"C›Âüü|rp¬©©ÙµkW0ܺukyy9ÙýÖµ1*Ô,rÆŒD¤×ëýýïON ¶oßþøã'%%i(9îaD}ñÅ¡Ë/¿œüÓëõþç?ÿQî¨ó–w…3fÌ úûûŸþù††„ÐþóŸgžy&55UCɃCBOOÏ£>ÚÕÕ…Ú¹sç3Ï<“˜˜ˆÎìÈAadQÚJT…ão¼±  €üsË–-‡æ=î1ŒM·¶¶³Ù¬\ÃŒ\ÛÈåÓÐ3E|æu3‘™qÈ›hdYöz½qyÔ8´±Â¾ñÆÊge†ÞZOKKknnŽ×xÒ€Ëå"/g™8qâ‚ >ûì3·ÛýòË/+t¿’’’¢œÖÔÔ8N®ÆÆFÇ£,„ºÙ‰qùdݺu¤„Ñ£G‡}Éñ½w‘‘1vìX²$ùå—ä­QãÇÿùÏž››+IÒùçŸÏ[,;¿‘¡÷Psssýnœ^aÔPK,ßÕCòÃ!”““C+A߆~EL…*ÒüÅc ÿú׿ƒÁË/¿\’¤¼¼¼›o¾ù•W^g³LdwF 5ŠSC–e£Ñ¸sçÎ[o½õᇾð 9ÐÆŠõе””åsWWé°äää &(éúžÝÿý+W®\¹rå\€1–e¹ªªJÙñOnjê¨!ÔÑÑÑÜÜL>Oœ8±¬¬ŒH*//g§Œà¸\.å ¼ &·#„Pii)ì@9W‘eyÆ Ê-á‹.ºˆlV×WÕ°†Ü t8÷ÜsÏŸÿügòŽ=o¾Š²8ššš”ÏW_}uZZš$I\pòÄ:{±z*++;;;Éië²e˲³³Ngaaá·¾õ-¢°©©)¾¿ª´±{÷îÅ‹K’”””ôàƒVWWK’4qâD¸R=»ví*))‘$Éb±üú׿®ªª’eyâĉäí-À9‰Ûí^·nÝÊ•+Íf³Á`X¶lYeee{{»Þº†1ä”: ®^½º¢¢â¡‡JJJá ŠXg„555G%1JOO¿úê«.\˜ŸŸ¿{÷n%pñ}×*/@`ݺuäqά¬¬¥K—Þwß}?üáÉ™V__ßÛo¿-BoÞ¼ùĉäsZZÚÌ™3g̘a³Ù”3E`@¶lÙRWWGz355uæÌ™³gÏNKKóûýzK‘ýû÷oß¾ô{vvöŠ+Dó Ž'>ûì³Ûo¿}ç΢g‹ÕÁãW^yåàÁƒäGyâäoûÛ† ”Í ÊËpõb÷îÝÏ>ûlUU9ë'·ý~ÿ¡C‡þïÿþO„÷«!„¼^ïóÏ?¿oß>òØ©É]»v‰‚µÊ IDAT oX@ž£ÿòË/•z<žM›6µµµ‘ ÉsŒñúõë• ¤³gϾä’KD;pGÈц††ßþö·B=;D»4Šr:O=õT~~¾Ýnïïï?vìyRxÅŠ$ŽÍÅ#v0Ƈ~ôÑG322ÊÊÊl6›ËåRìdÅ98677?ûì³¹¹¹v»= VVVöõõ!„Þ~ûm$@V®\IŽ2âHR8uêÔóÏ?Obˆ1®ªªêéé¹âŠ+È_u?5üío«ºßüæ7¢…4ô¤J¨[DÏ>û¬²È)ÂÜn÷}÷ݧ¤ b ¶nݺ¿ýíoä³ ’x!šûûûE?è»F5ü’’eÙáp_d¡{ºb‘_…ä‹íííÊ+obÜ Æøºf‘!òà*±4Š1’ƒFE¤¶/ªÊ`üIƒÂ¢¢"“ÉtâÄ %†W^y¥r÷:sÜÒB§9¤ƒ×ËyyyÊgò*8mŒäbŒãòbÈv2 A-*C¸3BA‚ÅDžÛÌŸ?ÿšk®q8>Ÿ/33S±d’eùóÏ?‡Ø²IIIYºt©ÙlVžîééäL  îBºSVVf4KJJSYåçüG}~­’••uÙe—)L¡mÛ¶ rµ`!*555ÙÙÙ………¡—³ÇÖ­[?úè#¡îu‰ yK0‰žÏçÛ¶m› Ûª ”A¼GHaг5ˆ¯0š CÀp£…ï¾ûî¦M›ìv{YY™Õju»ÝÇ?~ü¸æ]Q#-†Çå•WRRR\.WEEEGGG짃#-†ƒ¾÷axÜ#Ý! ^}}}}}}h¢Ž’†===ä5„â ,„0pˆ >b=PC ,„ÀˆB`D3¸»FE¸=0à{[†R MðØf6¬Ã £ÆÎ°V(‚¼!#´±pFŒh`!F4°#X€ ,„ÀˆvŠ® ‘ 0@aì€ÂØ]£„¡Û5*~XÅWˆ†ƒHP; 0v@! A\1Æ^¯WߎÇ{<Æ_Wˆ†ƒHP  0v@aì xÀñûýC&FGÂ<Ô¤´´´Aª cœšš:zôh›Í6HU ˆÇã9vìXooo¨Ÿœ‚ø Ñp £Æ(ŒJ’”””d2Ë~ ~¿ßív“Æ’”A\B²,˲¬ã/ I’ ƒÁ@=ñ_!"Aá€€ÂØ…±Â`0xn_•$Éh4†AJMMÕQè <>Œh`!F4°#X€ ,„Àˆfp_±‚g„ÀˆB`D !0¢…ÑÀf`DþŠñ¬¬¬ÒÒRö; ‡Y–ÚÚÚhìvû…^h6›‡RU(~¿çÎ'Nœ e… cÆ(Œê¾ÊD®)g-„c«ÕÚÔÔ$Ôi¢$I‹%Ô2#Œñرc[[[‡^˜‚$IcÆŒ¡u<(ŒP; 0v@aì ¨P÷U&rM1„ý¹¿¿_¨U!„1îïï§ýU’$Y–‡RO$ìˆÂh…±# BÉ`˜2uÚø‰ÉG(…ÓΛ>áŒ0¡ªr(Ô}•‰\Sº:¬í×C$ 0v@!/“&M.((èîêR„‰£°««³¤Ô>vÜ8®µP@aÜ…€A!;;»°¨ÈáhjinÖ[‹ 'N´µµÙíeÉÉ)zkQ!!!!'77==]o!TóòòG%f¹ß,€Ñhœ5gBh×Îbþ¶_!B¨¨¤D’¤Ç «ðdcCNNŽÝn¯¨8$šH«Õ:fÌX·»¯»»[4m¡Ì¬¬1cƘLf !ãf§ãĉꌒaóøCçÐ7A’¤¢ââQ……'›Nž$DP˜c=Úép4lŒÔ »B‹Åò­3îDíÛû¥ÇãAb(THII•$)L(ä"##Óår¹\.a¶¶´øýþôÌÌPUB)ÄgˆLd|eðu¡üü“ÉÜÐÐÐçr7.¿`”Ãáðù|Ñ(„P…pFȇÕj-.)5jT¢Å"IRcCƒÞŠÂÀYYYYYYcÆŽu: ^¯GoIg!I’êî_¡mý |«C|…6›Íl6÷ôôè-„ÆØçõ&§¤˜L&¿ß¯·œáDcà §ÉÔÙÙ‰1öz<)©©V«MY‡°r0¶¼¼Ì^f0=OCCƒÓÑÔÕÙ©·¨³hkk۽닂Q…¹99£ÇŒ±ÛíMަÊÇ9\z½ÞÏw|–(ˆ¶0ÄTŠà -„P@øÕÅð#„, ,„\(?q2³²lIIýýý½½Bÿèa !i©iF“©¯ÏÕÐÐà8yRÌ™ÓÕÙÙÝÕÕUP`/+KKKÏÊÌÒ[Ñ7X,–™³f‡~¹g7¹4 œKˆÞòsb¸¨Œ¬¬¬ÑcÆbŒëjkƒÁ Þr´ !ÇŽÖø|¾¼¼¼ &Ž;®£½½®®¶»«Ko]ß`±XF›››K~·:ÕØÐ Ô©C 6‡H ¼/BȤßûM¢„(ôŠ÷S,”½^¯àKJí&“éÈáŠîîn½µÄŰYfÈèîîî©8T]UYRZ:jTa^~þ©S­ÊB(‚ÂÔÔ´â’ŸÏ×ÐÐÐpâ„»/|Ÿ‚ŽÚB^¯w×;Ã…RH`ìÉD¡Õf›:mZ¿¯ÿë_‰©ÐíîëïïOLHˆü“ ·;„&Š °··çÀWûibDPˆjinF’¤º ¢l–ÑÆØï÷×ÕÖÖÕÖæåå{ÛŠâõzªŽi<ÙˆeYÌ(¦ª0$IJMMÓ[ “ј‘‘éóyõ¢»«+'7711ÑëTgvNNBB‚£©Io!*Øl¶’ÒR¯Ç#òc ÉÉÉ!²{Yo-1 ¡H¯77;õNOOàûô†âïÉ$0w´wè-„ÅÉ“Ù99ö²ÑÕU•bF²¨¨cÜÐ âJc6›322û\z a‘‘™yæ.ëðBPAÀ#c(iéi²,××׉¬³µ¥¥¹ÙYT\ÜÞvêÔ©SzË gTaQn^^cCC÷·º»»É}‘»xÏî]Hl…Q ! ?êjk×× {ÉQ¡òða“Ñ”“›×ÖÖ&Úá2??ßép{¶Š†Ã#¾Â(…† ?¡ðûý_íß' 1øJØ[éÀs.ì¡ "¼ôˆ (ŒP¨Œ1 1Gað좡QÈÐ0¬ B¨BpŸF4ƒµ‹WJËÁX\å!Š1>ž/€Á#55Õl6#„0ÆB? "0H‹KüBƒÁ Ëòƒ>(Ëò³Ï>+I’r‡…»ï¾{ÆŒ’$¹Ýî›o¾yX¿­›Á[\⼡¿üå/—/_.I’ßïÿÃþ@ã[œþÿöî=¬Š2ø;3ç~áp?wш„Ó­(5-Ónjfù¬mVú¸¹¦öÛ6{ÚjŸ.ÚZš‰nn[O»ÚšvÓÊ  â]¹ÊÁˆ€\œë̼¿?Þœ=¡ —3p¾Ÿ¿†sÆ3_çò~ç}ç}ß¡iš¦)Š¢ixZ@w4¹x²×¨è“O>‰1æyž,¼ûî»ýwH÷’‚{ÂË#ôHG;/߇öŸÇ{Dr^£îÒ4½qãÆM›6aŒŸ|òÉ矞¬à©mðƒ\<Ó4Ú)ÐÍ›7ðÁ<ÏÓ4=þüùóçcŒßÿ}h#Ðsƒ“\<IË–-}÷ÝwI­ó½÷ÞÃÏ›7oÞ¼yãuëÖI!¦¤¤®z,Ë=zT¨  †Ñ£G“޹­­­çÏŸ«‘!&&&00,×ÖÖVWW“常8ÿk?WHHÈ-·ÜÈqÜÅ‹‹ŠŠ¬V«ØA¡¤¤$­V‹ây¾¨¨èºG¹±±±¢¢B MIDddäm·Ý¦P(Ìfs~~¾fP‹7 ¡æææÒÒRµZ=qâD£Ñh±X Íf³(Q B[[Û¹sç|||222‚‚‚,K~~~]ݯ³á;6!!A&“•––ºŸ`¨´äÒßDH¶½téÒ'Ÿ|’¢((Ïó$ š¦ßÿ}îܹs1Æëׯ=Κ5+!!ô¾]¶lYeå¯3Ož:E­V?ýôÓwÜq‡L&#©… ؾ}û¾}ûÄ-;;;++‹DµlÙ2!áÝqÇä¢BmÛ¶­¢¢BÄ ÝÍ™3çFS<öØc6l8~ü¸¸»1''‡\,gϞݵk×Â… È^}ôÑG?ûì³;w~„<òHJJ EQ{öì™;w®Á`¢Ú¼yó/¿üBzä’1>vìØÛo¿ÝÑÑ1È¡‚>ÌäÒ¯¦U!]/X°€¦é-[¶¸Š" ëÖ­ËÍÍÅçää,^¼‰ý¼°¨¨ˆôÓcf„ ÂçÉÉÉ Ã^|û÷ï±:|øðÑ£GIñññãÆ£(êþûï÷÷÷'ý ¿ûî;)¼¥lÅŠwÞy§B¡ ;¸xñâI“&‰;£BAA‰‡¦é[o½Uø<>>že–e8 ú>$T*ÕìÙ³ …°CBB^|ñÅqöaHHÈsÏ=$kµZýÄO4)bT‹-òóósjþüùK—.MMMeFØŸ)))999ÐSa¨ääÒ÷Ó¢SºÞ¸qã;ï¼Ã²l§„LB_¿~ýÇÌó|NNÎïÿû>‡ë?ýô“Ãá ËIIIä2V*•qqqdÙd2‰Ûb†1Þºu+¹{¥izÆŒ*•ê®»î"áÕÔÔ|öÙg¢9›={ö¸qãÈq¬¬¬Ü¶mÛ®]»Hkž\.衇ÄM„yyyÂõ1cÆÁÄÆÆ’å’’’¦¦&Ñâû-š¦[ZZvîÜùüChŠðóó{衇$Rv8Ž;wnß¾]¸: ÅwÞ)âÖét---_|ñÅçŸÞØØ(|8~üøsçÎ}úé§?üðƒËåBQ•™™)“Ák†€ÁO.}>AF2 ~ñÅŸ~úiPPÓéliiq/£†ñõõU(_|ñ…^¯Ÿ5kÖO<1þðÃ{Õ²çÁ´ÔÒÒrúôi29&&F£Ñ´··§¥¥ét:²BQQQêמMœf³y×®]>ú(EQÉÉÉóçÏ "[ùç?ÿi³Ùúð›žpòäÉä„knn~å•WZ[[)Šjkk›3gEQ£Fºé¦›ªªªÄŠc|òäÉÉ“'SÅ0 ÏóÑÑÑd7"„ û°¹º=r¹\¯¿þzyy9Ïó_ýõºu낃ƒB¤P Z­ÖÕ«W×ÔÔ`ŒüñÇõë׫Õj„Pxxxoʃ:ŽÕ«W×××#„.^¼¸téRrN–””¬ZµŠã8Š¢”J%i$7 ÑÑÑ=yö/‘v‚n ã-¹¸¯ÐÇû#ŒñòåËç΋âyþ®»îÊÎΦiº¹¹yþüù—/_Öôõõýøãýüüxžw¹\dÈO<Á0Ì| ÖáÌÏÏ'EŒJ¥JOOß»wïøñãI‰ÃqÜ?þ(…óìóÏ?OKK‹ŒŒ”ÉdS¦L!áååå‰^XXXXXY>yòd[[9TPP””D #¥R)îSÌüü|ÒBëãã3nܸ#GŽyÅápˆÛú݉Ë媨¨ ¹Õj=~üøÝwßMQ”ŸŸ_DD„ð[D‡£¶¶–Ü ^¾|¹©©iäÈ‘!F#bTÇ544S\\,ì¥+W®ð~ü8y¶ŠŽŽ&g]ßÚEÅb.q«\à ¼GÊDL.}iÅ_[gâ8Ž r$q }ØÜ9tèyr={ölKK‹Ø¡ý*,,ìþûï'Ùl6µZMÓtNNÎÑ£GEjm2™È©‰®6“’Ã:sæLó®]»L&“¸q=z”e¹\~ï½÷ GÙ=‘KPHHˆ{˳¸Á –AK.˜t[¨’>ZÇ‘ÈX– @‘ר ¡Ýüþý&ÆøèÑ£¤ŠÐ©:??_µ·¿æñçÍ›G:²Úl¶uëÖ‘!öaaa=öXnnnoûµz6††† .ÄÄÄP•””4bĈšš„PFFFvv¶{õ³±1ÆÅÅÅ÷Üsé|K+((ÎQ&”J娱cIwÀÀ@Ò¥!d±XJKK{~¬.Ân~¼Wíá°WQá«3BwjµZhëîÔ²ç.BáAÌåË—›››ûö;žzD2 ÉÅ}}ª¡(Šã8F³aÃ÷ÈÈWiNè°ÿ~¡–€²X,ÒéI˜•••ššJb;tèP^^^vv6)ʧNzàÀÑçÛ½{÷’%K(ŠÒjµk×®=qâ„F£III!ÕĪª*‰ÌwèÐ!’›IG «ÕzðàA‰eÃ0úÓŸN:åp8âââHCB¨°°Pô) ͘1cΜ9dùÅ_¼pႤNÅäääeË–‘K877wÇŽRo’‹Çz|q×ÑÑAšìȤ-dê„Ífëèè:tIÇÙ³gÝ ëS§Nõm|žÇ©Õꜜrãc·Û¿üòKŽãvìØAÊD•Jµ`ÁÑûïÛ·oïÞ½ä¤ üÝï~—––F’M{{ûæÍ›¥p !„Nœ8áÞºxúôi Þ–ÕÖÖ*ŠÔÔÔÌÌL! 666nß¾ápB]ÓªSH‰¦ìÈIÁ $Õ[ZZ.\(—˯½n)Šr¹\}®eŒñ‘#GÂÃÃÉ!—Âøúè£7’e)ì7Á_þò¡çÆø§Ÿ~JLLT©T&“Él6Ka7®\¹R8åÜh½ð Bäƒ_gö[§¨~øa²àÕ7ß|óÝwß‘eѾpƒk2™$òìÀÝÁƒóòòȲèûJ0ÉÅ«g޻馛È\¡ãÇK§ ª«H¤¡€ÖeeeeeeHª3?Ip¿³ÙlGŽARÚÒ<»Úúuûž®QOEDD端¾’ÎQHj_ &/M„'N;vì¸qã|||B,ËîÞ½[‚çåP»ÎS`Ocjµ:44!TUU%ú{Ê€;/M„éééÂìPûöí½&`x «¨¨ iz×®]’m¥ðNG88<;nfĈB玃~ôÑGýìw4 c<"ì?ˆ°ÿ¼9Âòòò+VÜp74Ô÷¡D È8¡eÆ ÑÑÑv»½²²²ªª îÎmH¤ï䥉ðüùóÂÛXàÔo楉’B*ïD‰€WƒDÀ«A"àÕ¼t¡Ç õ‘=aO@„ýößPP"Ü#„!¯‰€WƒDÀ«y`@=Ïó6›­‡-ÂE©Õja¶k +=Ì/ýÌ,žI„õõõ=_?<<¼ÿ0ìõ<¿ô'³x f&—Ë…·EßEQ Ãô£î†V÷$i‚û"ì?ˆ°ÿ¤a¯ô0¿ô3³üføÆØårÉåò^ýÃ0©©©=¬“r×ÚÚÚÛw¹\®®Ž.ÆØn·«Õêž'cÃwSy‡{"ì?ˆ°ÿ Âþ»a„½Ê2=Ì/½Í,rÊo²(ÆX¥RùúúÊdšŒÛårµ´´8ŽëZŒ±¿¿TT”F£üØ›ÍV^^ÞÜÜ öDØaÿA„ýwÃEÏ2׿”ÎÕI’$%U¹&±vsƒƒ1¦(JĘÉÖ!Âþ€û"ì?ˆ°ÿz!5Ë\›S<ÿÄB`¯‰€WƒDÀ«A"àÕ ðjŒˆã.ÑA€WƒDÀ«A"àÕ ðjxµÎóÇÆÆJjRŽãÊÊÊ._¾ÜÕ ¢Ç<Ô#ŒˆˆÈÊÊ’Ô+G|,ËáØÑ#55fŒ±Ëå2™ª8Žs8Bº6BIí@¤ «{GI],â–‡S§Ýç¾-‹ÅrðÀþ–6Hªû†O y<ÏŸ9}*yÜø´ôÛëjk¬V›R¥T«Õ¥%P ˆŠòr÷”fw8D ¦ÿ õõõù‡GFFÞÎ02–u564Š`Ø*--éôɾí†D8LX,m§NtÿdHŸ—)fÅ $Âác˜š08 ×(¯‰€WƒDø? …B¯×Kªw/€æ]‰¦iæzd2BèÍ7ß½®®níÚµÒy ÊôéÓ†¡(ŠeÙ¯¾úJjyÚÄÅÅéõz___ò§Ýn¯©©)++Óétý¿»Ç·µµ ?Þ7 Ã@SÄ‘ÂGì(†%K–466~öÙgý¹ùë]"¼ï¾û|ðA£ÑØÚÚšŸŸ¿iÓ&»Ý>mÚ´¬¬,½^o³Ùž~úiŽã~ýu™ìÙgŸ½í¶Û|||Ìfó–-[ŠŠŠH¸jµzáÂ…ééé>>>—/_Þ¹sç®]»ô6–㸺ºº¶¶6’B0ÆätÄ«Õj«ÕJþ¤(êÊ•+/^¼|ù²ð‘‚¬¬,á™3gL&“Øáx#R„•••!„ÈMÙƒU¦IDAT}DD„Á`8}út§Dˆ1&'XÏ‹<£Ñ8f̘úúú+W®ôäwºßù’¢dÁka<%00ðÙgŸU©T¹¹¹}®ô">üðï¾úªL&kkk‹MMMŠŠZ¶lYzzú¬Y³ÈÕXSSãþO6mÚ”‘‘Á²¬ÕjÏÌÌ\°`Á‘#G0Æ~øazz:˲ííí£GÎÌÌôóóÛ¶mÛÀåB§Óù÷¿ÿ½«o)Š":îàÁƒyyy’jMHHˆ‹‹#;yÿþÎsúÁÔÒÒB^÷HQTcccLLLLLLUU• ­VkSS“Z­v8r¹<((ˆ8³ÙLÓthh(YeÙêêê   ½^_WWGÓt```}}½ÙlŽˆˆ jkkÓh4ƒÁ××WÈyíííÍÍÍ*•Êf³i4š€€÷tH¾U*•V«5((H£Ñ âî=RPPW±Güßÿý_rrò’%K Ïœ9Ó·½Ú‹ÆiÓ¦Éd²o¾ùf„ +W®DM™2ÅÇÇç_ÿú×’%Krss;E0iÒ¤ŒŒ Žãžzê©ÌÌÌcÇŽ©ÕjÒ%999-- c¼páÂÛo¿ýË/¿¤izÖ¬Y}+“É”J%ÏóÓ§O?yòä›o¾‰’Ëår¹œã¸âââ+W®œ;wŽçy™LFžÆIÄŒ3H9ër¹þûßÿJ'C{3Œ±ÅbinnÖëõ>>>äC›Í¦×ë§N:}úô™3g&%%ÙívòÕĉ322„Œåçç7uêÔØØX„Pvvöøñã)ŠJOOôÑGišîè舊ŠzðÁg̘1kÖ¬¨¨(¡•ÞjµúûûO:•|•@ÞfN°,;jÔ¨™3gNŸ>ýÞ{ï5 ’jØ!ŒñW_}‰Ð#xžßºu«V«}æ™gúܿ܋²þ7ÞÐétÕÕÕ.—ëÀc¹\zöìÙ3gÎøûûwZ_.—8p ®®®°°ã8“ÉtË-·"„.\¸ðÈ#pwæÌžçÏœ93kÖ,¡(8N§“¤“èèh¥RÏ0Œãêt±þóŸ_}õUÒ!Ðf³ t0½"´‹ž:uªººZìpÀÿttth4­VK•^¯=z4Çq¥¥¥&,,ŒeÙÆÆFŠ¢hšîTöÑ4MnþÌf³^¯×ét—.]"ï ‰ˆˆ ill´X,ƒ!**J£Ñ??¿ØØXŽãÊÊÊT*ÕÈ‘#Bõõõä Ñjµ:Îd21 3bĈ¨¨¨ .@CœDð<ïr¹*++‹‹‹!öÐ÷߯Óé^zé¥C‡]w§íÞ½{ÕªU'NÔh4Bw¶^éE"<þ<º:×üùó)Šª©©)--íªv²wïÞ}ûö!„xž7 &L (êôéÓ¡¶¶¶'N „f̘a0üqŠ¢öîÝ; g†R©|þùçCCC¿ûî;’ç:::âããüq›ÍFz둇.<Ï3 cµZßyç)dĤ¤¤èèhRÌýüóÏpýH ¹‘"7X<Ï5Êétž8q‚ôÉr:ÁÁÁ­­­¤5µ+ÍÍÍ2™L§ÓY­VòŒ0((¨½½ýäÉ“æÊ•+ Ãèt:ÒŸ9,, c|þüyré)Šèèè––’íœNgEE©r¨×뛚šaW€úøã7oÞŒ‚jzÏëõz¥RÙÕ ‡£¤¤$555--mß¾}}(!{‘…_ÿÃþ°`Á‡Ãñ׿þµ›ÃIדå5kÖ„††VVVnÙ²Eè«‚zå•WÈöS§N½óÎ;ÝâGnÀ…þ¢!rŸîþ9É7­ºLŸ>´Ó:Nh•r8Èi£ÑhT*•Ýn !ß* …B¡Õj[[[{õ³.—+888&&¦ººº®®®¥¥…t(Õh4J¥Òb±§ÁÅ‹„DK†aeÒdªP(<ðÿžo¤¤¤ „H[Ý¢E‹T*ù¼¨¨(??Ÿæäú"ƒß6=öØsÏ=×ÑÑñ /tUQíä…^˜>}zssóòåË;ï½÷žÁ`˜6mZbbâk¯½¶lÙ²;QÇ›o¾É0 ˲K—.EétºsçνôÒK]ý‰œµYYYdáÔ©S0\Zj„ÎÆ!¥RIQ”ŸŸŸû·r¹œ,÷ü­¬¬t¹\ááá±±±6›­ªªÊd2ùøøM8Ü^ÿær¹\.× # ÙÙÙûÛß:Ýý»\®””Ñ+¯î,Z´H¯×“å 6üòË/äš²X,¡>?_ëu"œ0aÏóû÷ïÏËËëIžxüñÇ-ZÄqÜš5kNž<Ù© ضm©nܸñž{îY±b…c _ð(“Ɇq¹\.\`Y¶¤¤„eYRH9Ž5kÖL™2eíÚµ»wïV©TdÄôÀÓCãÇŠŠ"eÙO?ýí¢’ÂqMÓr¹œ4¡“?kkkó>HrÔH«»ða7—ÆØl6[,N§×ëÂÃÃU*U]]i·woh%Täӆ††aT*U§SH‚sß¼öÚk¤ÄF={V(I³G÷w„Ýèu"\ºt)¹±íIÌÎÎ^±b…\.ë­·¾ÿþ{áŸÌš5ëücssóÌ™3m6·À0Œ\.ÐD($¶;v^[<Ï“-Ò4’’”°gϧÓ)ú}qß}÷‘ÓÚE%Âår‘‰œ9‰‰‰E577#„ÚÛÛe2yªGî[ív»Íf BÑ4-“É,‹J¥bYÖýÙºZèØív–e5Mffæ¥K—šššH_›Q£FÆúúz‹ÅBžVTTèt:Žã|}}“““Íf³žgƒ!ª½½½¢¢¢S"ìþÁ¶(vìØáþ§p‘Ë­¡¡¡oU…^'Â×_=55õûï¿ë­·º/”#""Ö®]«Ñh,Ëí·ßNÆK „/^|ìØ1…B³}ûöÊÊÊÌÌLš¦ ôJV( .Ôjµ$l2Bc¬R©vìØA¨tttdeeMš4©¡¡á“O>ú¾‹%33“TOœ8qéÒ%qƒèê™CúdÞtÓMJ¥²¤¤D¸üš››FclllUUEQF£1$$¤¢¢cl·ÛBCCkjj|}}Ýo`9ŽS*•*•êòåË2™ÌÇÇG«ÕÚl¶¦¦&ŸÀÀ@¡e•l"22Òd2i4šØØX¹\.ú‰ †´C‡M›6íÚÏ¥P¸a¯Q„PHHƘôÁìƒ^'Âàààððð€€€®d0Bz½>##Cø\¡PTUU­X±bÉ’%IIIcÇŽu¹\ß~ûí믿> ;a˜Q£F S¬ Ÿ“)Öt:ÙÅãÀÀÀ¨¨(µZ-zË@JJJdd$YþñÇ¡]T\Z­Ößßâĉ!Œ±Ëåjmm-++sÆg2™hšŽŽŽŽ‹‹CqGÆNÖNµZ˜˜HR`uuuLLŒÃá ß666Ž1bôèÑqqq………áááééé!Š¢,Kee%9ÈЈ›o¾9>>!d±XÊÊÊÈWƒÁý¦ža???§ÓÙ·À{`Œ¥ó®ë†½F#"""##+++KKKûvžÿæ):EQÝ?ZzWvª’î—ÈíBø¤²ù6$$$((¨¤¤Än·wÿȤ«y„{³{ð]}EQÔŽ;6mÚôöÛoÓ4Ý«™e<a'¯¼òJNNé1yòäúúú>üH÷Ru÷ÝwCŠžèj2³kWcF«ÕbŒÛÛÛÝ›@É‹M”JeGGÇqÂ$·:ŽeYÒ4BQihµÛíN§Ó}Cä+RetÿªÓ^÷Ð žç»ÇÕŸkÙƒ¨´ñ ÏF(ŒMê긬Y³fîܹo¼ñÆ'Ÿ|ÒÃB»S„½®vµ™ko(º¿Å ßšÍæšššÁ¼J¯{ÈLÖ&“)!!Ád2‘þƒR7„‰HŠ‹‹;õ¿ƒ¯‡'*ƘeÙ뎗À;áAx§$SÕ¸ÿI*×ý—ËÕÒÒrÃ!‚¡®ûªjZZÚÌ™3?¾uëÖÁ˜kt€ æ…ÚýnZ¾|ùêÕ«ÛÚÚ0ÆRè/š––FæœDÐ_®ç©§žª««[¾|yŸ»Œ")$Bé°Ûí’êq0eÊÒ–k·ÛwíÚýE “wß}÷Â… îÏéû¡t ýE;í¢p-÷Ñ„}‰P¢ŒFã±cÇHoà~øªƒp-<3‚D(QõõõÂÜoF^ð H„Òµ@09!¯‰€WƒDÀ«A"àÕ ðjx5H„¼$B^ !¯‰€WƒDÀ«A"àÕ ðjðö ÄB¡xæ™g(ŠÚ´iÓÂ… Ý>øàƒ®^é‰ Œ1EQbG0räHR ]»Ð•ß$BŒ1˲r¹|@£ì–e»z3­DbºbŒív»Z­†\¼ÆØf³u¿‚”¯e"ät:W®\‰âyþÚ…®"ì\ö©Õj???™LB5E—ËÕÜÜl·Û»ZAô˜‡z„QQQf£@Rl6[yyù•+WºYGâ×2‚{àÚ¡Bªƒ „ºªÇCÄÿDƒ-â•<äyIEND®B`‚jas-2.5/images/device-2012-11-18-jas-trinks-out-big-part-thumb.png0000644000175000017500000014524412054221644024326 0ustar giovannigiovanni‰PNG  IHDRÈîóÏßâsBITÛáOà pHYsÄÄ•+ IDATxœì}w|T×™ö™{§÷ª®‘4Ò¨ŽzEÔ…M¢ˆbDµ1lc{ã²Á‰³Æë8Ž7¿¬cúabƒÁÓAt!$¡^Q¯£é½Ï÷ÇO´Â)» Áñ7Ï?ÒÜrÎ{Ê=õ}žƒÐ‡P(œù“H$FEEy~ÆÄÄà8޼øQƒÏç‘ĉN ß°——N ’ÿ§gþ ‘H•••W®\™œœT«Õ!:^YY‰¢P(‹Ån·šÍæ•/~hÁÁÁ†âýøËᾂ‘ÔÜÆ·ž5õ ,Xn×*u—ùó–8Í&mÝ„;%nìnÄ©t²¯Ø:1`h«ÃýôÓ¡¡¡AAA;wîÌÎÎ~ë­·Èd2BÃ0ØI°Ùl‹…@ ùûû{=sþÙq_ÅrÚV³Ån¿0¨¼^¾Ö!±"d%L‹—@Vht6§Ãé°ÍcaF$) ‰D"D"!têÔ©ãÇ—””LMM}üñÇQQQ÷îÝkkk“Éd‹ÅžŽã4 !tþüù?þ¸¤¤ä’|/î¯XŽA2-(šÖ\T×or‰Å”eËnÆŒL©î±D“R™^¯w»ÿìJÑÞÞ~âĉðððéééíÛ·»ÝŠeË–]¼xÑßßÛ¶mmmm*•*33³µµuçÎÁÁÁÏ„ÐàààÉ“'y<‘HÌÏÏŸ;w®Ç%È‹RÌ^ '/`Ɖ¸ÍîLÌ?ó™óñŸÐïÖëlÎÿtˆNF ØÎþˇmF BˆB¡¸Ýn»ÝÎd2m6›ŸŸŸZ­¶Z­à26::Êd2E"Ñðð0†a"‘hjjJ,OOO „‹Å2›Í$Él6³Ùl§ÓI£Ñ\.—V«õ¸îxñψû—N›ÅlC!»Ýf±ÙZ†äq&‹Ëér¹¬vûw®9ßu…0Géõz„ÐÐÐЬëƒêÓéGÍ•Ã[‡!¤ÓéBF£ñ'Ò‹== â‡#""B£Ñœ?~Á‚,kjjJ.—Ëd²ññq:n³ÙΟ?ëÖ­õCì ©T*‡Ã …$ Çq@ððâz° l6Ûív;ί¿þ:!!F£]¹rehhÈétÖÕÕŒŒˆÅâÀÀ@p—ýÁâÖ­[B¡066ö믿>räƒÁ DQ(:Î`0ÚÛÛ›››¯]»vãÆ 6›m·ÛTÔ+_Ün÷øøøàààôôtDD„Á`׫ 8ÎÉÉI@`4«««OŸ>œœìp8&''vïÞm±Xêêê.\¸››û¨ýk r8=öØØØXww÷éÓ§#""&''§§§ó›ß˜L&___£Ñép8X,Ö£6ù&“ù‹ Çqa¶WȃÂO¨ ý=šBVwèÝ’ÿ0ñÏå3 Öþ=6?Øty—¼x(ðV,/ ¼Ë‹‡%Pò¨mxp*'Ó£¶âðòŠëßBÊÉÑGmÃ@÷³KŒ] Ú /þ ¢ubðQÛð@ ”ÐÂÿ¶áÖ‰!Š_È}/¼ðb@ÒãQ[áÅž–——“H¤GhŠ?&ü¹bq8œGh‡?2x×±¼x(ðV,/ ¼Ë‹‡oÅòâ¡À[±¼x(ðV,/ 0ò§ïÑ©^<0„ÆPÅãh´¹]†»\.¯œš óˆ+BLî£6Ä‹œNbº44::º»»Ûd2%''›L&•JµbŊ矾ªªJ¡Pœ:u*..ŽD"I$’K—.•––:tˆF£%&& …ÂæææˆˆˆK—.ñx¼íÛ·Ûl¶±±±††† FÇ;VXXÈ`0†‡‡årybb"‰D2™L/^¬¨¨øøãBþþþeee C.—ŽŽjµÚ²²2‡ÃÑÙÙéçç' årùÙ³gSSS…B!Žã,//Ÿ˜˜àr¹ÓÓÓ±±±l6ûæÍ›óçÏ7›Í† ¤¤¤455ÕÔÔhµZ‹õÖ[oUUU}ôÑG›6m:tèÐÒ¥K/\¸°páB·Û][[ëëë«Ñh0 kkkËÉɉD÷îÝ«¯¯ONNæóù~øaEE…Ãáhnnh/¾Ĭ¬,‰466†‰DF£¨sÕÕÕ'**Êh4º\.—˼qãÆááá¼¼<>Ÿ:22"‘H@y[¯×üñôõõÍÉÉa³Ùt:H$‰D@Àf³5^¯ … ¥¾¾~ëÖ­ׯ_OII‰D,Ëívët:»Ý®T*‰D¢H$‹Å,K©T®_¿^©T:òx<½^Ïáp|||ìv;‰DJKKÓëõÙÙÙ‡Édâ8®ÑhBCCW¯^ ÁjµÚ±±±'Ÿ|˜04mçÎCCC›7ov8v»L&ûøø…˜˜˜þþþåË—Óh4‹¥Ñh( ŸÏ óñña±XµµµÞZõ7gÚ|/ˆDâ,JÐ̇ÿÊ‹á¯ÜEñx¼={ölß¾Ýs…B¡ÌzN@ñ\†û /¼àããó½aBŒ÷GíqÙ R©³Ì†À)ÊL·ljD"@ ‘H³¬"‰?ýª‡Çf³g]ôõõõóóCaF¥RÉd2Ç›U`l6›ËåÞOFãr¹Ð`ðx<¨H$‘H4ë*• Ðh4@€a„0ë.—;ËùÇq‘H"‘ˆ@ „††z(— ! …" ÙÌåþ·¡$‘Häñx ãþ<¡P(8ŽÓéôYóð —ËU½(Š@ €Xf½B§Óy<Ç›YwI$’P($‰\.—ÇãÍÊOò#""  B||ýꫯº\.·Ûýâ‹/šL¦þþ~Æf³ÍfóÎ;#"" ®_¿îy±´´4'''&&fÁ‚gppÐív¯]»¶¾¾>&&&&&¦££cëÖ­YYYN§sïÞ½t:½¹¹™@ èõúüüüÅ‹·¶¶Æœœ¹\ît:1 û¯ÿú¯­[·¦§§wuuFxE$åççïÙ³çìÙ³6›­  NÙøÉO~’m6›÷îÝK&“ÛÚÚ0 óõõ5 ¯½öšÅbéëëó÷jjj222AXXØÎ;ëëë D!‘H¶lÙ’žžÞÒÒB£ÑJKK[ZZ`h100P^^^RRÒÞÞþË_þÃ°ŽŽ0Æçž{N«Õ¾õÖ[t:Ýd2)Šüü|0$‘H»wïf±Xmmmn·¢‹ŒŒ¬©©ÉÌÌlll´Ûíp1::zçÎIIIjµZ.—'%%Ùív³Ù\XX˜›››””TTT” Õj§§§ “É,,,|þùç/_¾ g‹`B¡ûóæÍÛ²eKhh(tV«ÕÏÏ/22Òf³Á—D&“ßxãeË–!„Èd2F34mÇŽÏ=÷œL&S©TW¯^¥Ñh‚T*Å0ì¹çžƒ^¯££C"‘ÔÕÕ!„²³³BwîÜÑjµ %,,,##ÃÇÇG«ÕÆÆÆ"„Ö®]û¯ÿú¯ ýàããÃáp‚D"ÉÏÏ'‰ç΃ï#***"""88X¡P@G™‘‘ÑØØˆ:tèPpp°Åb1›Í±±±!55õÀ\.—@ Ðét—Ëåp8ÒÓÓ÷îÝ»mÛ6‰TVV¦P(F£iii –H$H$SSS‹åÀz½~Ñ¢EÏ=÷\UUBèÝwßµZ­J¥Òd2A,¹¹¹ï½÷“Élhhèéé9zô¨Ífó$ùàÁƒƒ¡§§§©©éòåËãããÑÑÑ T©T.—kppÐh4ö÷÷GDDÀ·×ÞÞŽºvíšÕjÅqÜh4ÆÅÅ„üüüwß}—Á`466nÙ²E«ÕÆÅÅõôôäååíÝ»wãÆ¡ßÿþ÷‹ettÔb±DGG‰Ä¸¸¸øúú* Ð××g6›¥RéBBB@HÃ0«ÕýÜsÏíܹ“Á`\¼xÑívÃéÒ¥K‘‘‘àÀIIIz½~llìèÑ£r¹ÜÇǧ¼¼;räÈåË—Bz½^¡PX­VK$$$Ä`0DGGËåòóçχ……Ùl¶wß}šÑÑÑ÷Þ{ï³Ï>3›Í}ôÑ·ß~ÛÖÖæããÃãñ´Z­V«=uê”X,v¹\Ÿ~úé±cÇBàóÏ?¯®®Fõ÷÷{š›Í688¨R©¨Tê·ß~+ 1 ;wîÜûï¿o·Ûm6Û7ß|ãv» †B¡èééq:óçÏ¿uëÇëìì E¹ÝnÈ —••²Ûí ¾$‹™L¦¯¯¯J¥šœœÜ·oßÄÄD```fffgg'Žã'Ož¬­­ýꫯB«W¯Ðh4“D"±³³óõ×_‡C„<ƒ&¤¨¨ˆ@ Œåää444@fîÛ·€7n„……‰D"H¤kfOêp8.^¼ÜÜÜüæ›oƆ†™LöÑGq¹\—ËU[[[[[ûá‡"„ÊÊʬVëÔÔÔ7´Z-NÙ·oŸR© ºråJtt4Çß·o¨M]¿~ýµ×^ëíííêê:qâħŸ~j4çÍ›W__Ïf³1 žžžÖh4ûöí`2™ÕÕÕW¯^%“Éz½¾½½Ý?ÀB=ýôÓÐÍ“Éä@PVV6«Ó ¿ÿE ÃrssètzYYäŽþþþ|>Ö[ð]FGGçääÉä°°°YqI¥Ò™9NYY™@  *,,$‘H7n¬©©‘J¥k×®E‰ÅâÒÒR2™œžžžšš:óu@pÿ€àççÇb±bbbæÌ™3³D}||Š‹‹aõdæóéééÅÅÅYYY‰‰‰³B»?£ââ⊋‹ÃÂfÍpŸ7o^zz:B(&&fùòå7nLOO_¸p!BˆD"‰Åb““#“Éf¾ˆa˜T*Åqüþèâãã‹‹‹ÃÂÂ’““333gÞ"‰óçÏŸ•3 FسÀf³ËÊÊ„Bahhè‚ f Y,VqqqQQÑý…ûßÀb±žêÐ̬„™Úƒ‚ŸŸŸ'pøÐ*f&äþYíÿ3e’`rH$’gòA&“Ñÿõ¯}öìÙŠŠŠ¥K—NNNªÕjè\ ÆæÍ›ËÊÊôzýÄÄ<Íáp^z饮®®ÀÀÀuëÖMOOWUUÍ;···Ö$Ýn7—Ë}ñÅ“““ÛÚÚ`Ù Ã0ÇwíÚ•™™YWWWYYi2™4MZZZdd$tˆ†íÚµ+%%åîÝ».— ‚*--5™L?þøôôt\\Üðð0—Ëu:.—+..nçΗ/_Þ´iÓ¼yóîÝ»g2™L&“ÃáH$Û¶m‹‹‹ó$Çívgee­\¹2++«¾¾Þív …B“É„*))Y¾|¹J¥ª¬¬ÌÎÎnnn†ñ;$ä‰'žHIIiiiñ\ \µjUUUUCCÊ+ÆÇÇFcaa!‡ÃÑét/½ôRbbâÄÄ„V«…ç¥RittôŠ+š››W¯^ÝÒÒB§ÓÉd²Ýn‡#BÅb1ŒŸ €¡‰âp8ÝÝÝ:Îår‘Éä•+Wæåå¹\®‘‘(*•úüóÏ+ .—»wïÞóçÏCÈO<‘‘‘A¡PFFFß¡¼¼|éÒ¥ …ðÊÊÊææf‰´}ûö†††ÂÂÂ¥K—ÂÂxVVVkk«Ãáûsss) ¬_æææöõõyjäÞ½{µZ-ƒÁøéOzîܹ™ „0•JE ÂÃÃN§ŸŸNÿùÏž™™©P(Μ9ÓÛÛÛØØH ¨T*@Ðjµ}}}T*µ¼¼!D$e2™Õj5›Í~~~o¾ù¦D"¡P(0‹–J¥o¾ùæœ9sÞ|óÍèèècÇŽ …B„ÐÉ“'W­Z…*--½tédS@@BˆÉd²X¬ˆˆˆýû÷à øêÕ«!ÙJ¥’Ïç?ýôÓóçÏ'‰P!™Ls‘Hôæ›oJ¥Òþþþúúú[·nÝ»w/55õõ×_g2™~~~°èàïïÿꫯÂzDWWWSSSbb"ƒÁÐëõ‰dÿþý~~~І†8©zÿþýb±xllìÊ•+###æêÕ«eee¡ììì;wîÀqžmmméééçÍ7ߌ+(((((ؼy³Óé¤R©+W®\¿~=N·Z­‡†a@eeåSO=E$=j2™Ž9‚ãø /¼PRRb³ÙŽ=ŠãxSS†a‹¥©©‰Íf÷õõÁYÚ†=þøãëÖ­CI$’ÉÉɤ¤¤ššš-[¶<öØcÛ¶mëèè€NMMÐh´äääÞÞ^‡Ã1gΜ3gÎTTTÀ¹¤žô*ŠeË–®Zµ ÎÀ›Ívç·300`4¡JmÙ²¥¦¦æO þp¹Üîî˜©j4š™ÍŸÏ¯®®†jp8gΜ©ªªúòË/'''ôz½R©„Ã,§§§¢££•J娨˜R©T©Tða™Íf†ã8‰D‚eôÊÊJ@099™˜˜«äjµZ§Óuvv–••½÷Þ{sçΦP(L&“ÍfÃgï~õÕW°oÀ¨ÜsW£Ñ¨ÕjDÇÇÇ?~\©TÒh4ƒsL‹Å’žž~éÒ%Èš™±[,–#GŽ,^¼˜Åbéõz¸H¡PÖ¬Y;Qz½žÉdÎìYÄb±Ãá8~ü¸Á`€Ü0›Í!!!\·nÝ7pg³Ù ªV«×¯_ÿÑGAŽ) 8`³Ù …J¥B­Y³æ›o¾1™Lt:}õêÕAAA÷w=.—kjjjzzÞmoo–Ëår¹®“Éä‘‘õÚívØK€ºrìØ±ŠŠ FÓÓÓ“™™év»=éÎÎÎ~ÿý÷ËÊÊ:::h4ÚªU«BBB<9ìÛíö€Ây<^ww7“É”H$W¯^U©T7oÞT*•!X5›ÍwïÞ…¾ƒÅbMLLŒ———×ÖÖ]¼xQ¯×_½zÕd2á8ž’’B&“/\¸pòäI­V{õêU‹ÅRUUåp8z{{Ùlvnn®Åbéìì´Z­­­­SSSÑÑÑããã°¨sõêU‡ÃaµZÉdòñãÇ1 »}û¶Á`èììlnn†M$>ŸßÙÙ™‘‘záÂ0Qh4­Z­†9,LÈ»»»Bjµº££ãîÝ»n·{Ñ¢EN§S§Óq8 …råʲ¾¼¼\­Vß¾}Ûh4B*¤Rixxx@@Àððpdd¤Ëåš3g‘Hlllt¹\&“éÂ… °wõêUøÌ˜Læ·ß~k³Ù.]ºd³Ùz{{ïÞ½«V«ÃÃÃãããqïëëlii"áñx]]]¡ÆÆÆññq*•ZTTD£ÑÇØØØÝ»wáã¡ÓéðÙðx¼ÎÎNh}¡«‹ÅAAA==='OžìîîîëëëììLOOŒŒ¬­­U«Õ°)§T*CCC[ZZ|||üýýO:%‰<åéµÛíT*¦ä7nÜ€MRhwh4|̺»»{zzî¯ôÿ ’Éd???6›=oÞ¼GfÇÿÅÅÅT*U øûû§¤¤óÌ3‹/Fùøødff’Éä]»v­ZµjçÎ+W®<{ölLLLkk+ŒTu½x Z­V#ß¾}»¸¸Øl6gddðù|G"‘ßÿýk×®Ùl¶uëÖ¹\."‘h·Û7mÚ;?N§vúvìØár¹`bµoß>µZ îVÿ\R°^<0|ïÂ+øÜýþ…ò™kb÷Zú Ìô‹ðºÅyá…^xá…^xáÅutÿ—Ç0ìŸhVñ½¦òù|ØÙ÷09xtt´B¡Ø±c¸"ynÀæ.8¥¤¤,_¾œÅb‰D"µZí9ÕN ¤§§ Ñét¹\îyÇã­^½úîÝ»%n™L–œœ¼jÕªÄÄDØ0žïâÅ‹,XîÎ3ãý{••%‘H,XPXX8::³bÅ @088¸sçÎìì캺:öì³Ï²X¬ŠŠŠ¨¨¨¶¶66›½eË™LÖÖÖ¿iÓ¦„„„¡¡¡ÔÔÔ’’’ää䯯Æ;v¤¤¤‰DFSTTL¥R SSSÁÄÄÄóÏ?Ÿ˜˜8:: ¾%%% ¶ý«««³³³ÙlvPPÐøøøýglÚ´©¿¿vÙ[·níííu¹\[·nŒŒ,))éèèX½zµÙl^´hQOO•Jݰa¸÷ìØ±£³³sçÎ àô ˆ¯®®NIIinnv¹\, 2377·²²R«Õ.]ºtΜ9@q@ÑéôÍ›7'''···{*•Jݽ{÷ôÝÄûf IDATô4Žã[·n5 sçÎ-**™ul 100pýúõ°ï½lÙ²ŽŽŽ   ‹uóæM·Û=þüË—/§¤¤ +•JpÅ/))áp8z½þüùóR©4---<<üèѣ˖-›šš2™LŸþ987/Y²D*•މݰ0«ÕZ[[àëëËãñÞxãÜÜܯ¿þ\ŸI$Ò­[·|||‚ƒƒY,–ŸŸßùóçËÊÊÚÛÛ‰DbQQ‘Á`hnnÎÊÊúä“Oª««Åb1¦}||,KKK …B‰DŸ|òI\\Ü{ï½·k×.ƒñÒK/½öÚkV«µ¡¡ÁÇÇ'!!¡§§gxx˜D"¹\®èèh2™ìïïÏåroß¾ îä)))—/_ç“àà`غ÷õõ}ï½÷jjjîܹ“••Å`0&&&ètúÍ›7§¦¦H$’Óélhh(-- v:ÑÑÑ‘‘‘b±X €ÊÈÈ8LëõúÉÉɨ¨¨îîî£G2Œààà]»vMNN’Éd ÃîܹSPPpòäɱ±1½^oµZTìp8p×ëõË–-»qãB(--mÑ¢E_~ùebbâñãÇBÑÑÑ«W¯þÕ¯~ÐÜÜœššêïï¯×ëŸ}öÙÏ>û¬££crrrbb ˜AAA[·n}ï½÷À íøñã$ÉSÑÁ!…Ïççææbæt:ÓÓÓá×gŸ}öСCàB‚HCCCqq±Ûíf³Ù E*•ÂZ(°jkku:Ý¢E‹„B!›Í®¯¯×ét§OŸ–ÉdL&“H$ž9sF&“ùûûÓét‹_$˜Âår¿ùæ‰DRTTd4årùÓO?íp8Èd²Ëå’H$R©ôìÙ³:®¯¯/,,lbb"&&Æßßßl6Ã'›Ínhh ÓééééŸ|ò ¸ês8œ¯¿þ:..nÞ¼yV«U¯×¯]»6;;Û`0é !D \.83* “˜L¦C‡õC­V‹ÅbµZ}êÔ©ªª*H¾Ûí†FE*•r¹Üúúz„OVVÖ|àt:­V«\. éïï?wî¸FGG …Â;wî j4ŸþþþŒŒ ƒ4§ÓéëëËáp._¾ |¸/¾øÂCHœ3g‰D¢Ë嚘˜àñxv»èG…±X,‹Å‚‰DZ­ÇñÍ›7ëtº¨¨¨÷Þ{/11‘B¡X,*• îh999õõõ###B¡0 <<üõ ‡Ã9tè™L 3›Í Åd2™Íæ#GŽ,Y²„Åb1™Ì'žxˆ!†]¼xqÍš5§NêèèÈÏÏ73« N  Æ‘#G$I___hh¨N§kjj2 111ƒƒƒIII±±±CCCP$&“Éív÷÷÷ã8>99I£ÑBBB.\¸Àår‡‡‡ù|¾Ífkmmu:@:§Ñh½½½@n¡ÓéCCC×®] mmm%_~ù¥R©œ3g‡Ã¹~ýºÑh„jd0Î;'‰¦§§'''!ÞŽŽŽòòr ÃÈd²Ñh!‰ccc‡ãìÙ³n·{rr²¶¶6&&æÒ¥K©©©sçεÙlׯ__ºtiDDÄùó烃ƒÇÆÆ222ºººX,V||¼Ëåâr¹àŒ«Õj9ŽÓéÄq|ll¬ºº\¯$IJJÊààà_|áv»×¬YÓÔÔ488¨T*oß¾­Ñh¢££“““ûúúÀ£0??ð††hì?îv»Oœ82===>>®R©ÈdòÀÀl¦‰òöíÛÁÁÁcccPq©TªÅbÉÌÌô8lmܸ‘N§···ÇÆÆÖÕÕÁ—<88xæÌ—ËuëÖ­… Z­Ök×®Á Ðn·›Ãá´´´@ç¨R©z{{oݺåt:çÌ™Ç]ÇÇÇs¹ÜÚÚZxÅb±Ðéô%K–ƺº:ƒÁpçÎpÃâp8àH¼téÒ¦¦&.—+“ÉΟ?¯Õj/\¸0ËEôO€‘à_Ù¢ù?bV |>Á‚÷?F¥RŸ|òÉ¿´{ñÌ3ÏdddüõÀçÌ™×’àá„-_¾¼²²’ËåÎb-z6²N§P(%%%>>>2™¬¨¨h¦³™L.**ºß«1---)) !<<„†ãøöíÛgn9GDDFpŒ7›Í6›M.—Q(”þþ~ ›"„JJJ BhÕªU}}}<Ãá¬]»633322ü˜ÃÂÂüýýB•••O?ý4Bˆ@ <öØcÈüùó_~ùåE‹a¶mÛ6àëë ©ár¹à'œŸŸ…Äf³×¯_?wî\±Xl6›Á`‘Hät:GGG³³³GGÿ|ž…B‰ŠŠZ¹r%8òCŽ‚×ööíÛ!÷ù|¾T*œœô”A```hh¨ÅbY¸páÔÔ”'[¡:BÔ,K&“„ŠŠŠüüü7ß|³ººJbÆ `C^^‰Dš?~uu5ŒŠH$Rjj*†a)))‰$99™F£‰D¸|Ô”¨â¥¥¥¾¾¾¡äädƒÁ°~ýúššš€€¨yiii8Ž›Íæžžžòòò™ÓL‡Ã±xñb°mÛ6*•šŸŸO ’’’¨TªÙl¶Z­áááu„ËåÊÊÊòññYµj°V¯^ít:ív;xéá8ÎçóSRRæÏŸ•––F&“ÓÒÒ˜L¦T*‚ÌÐÐÐÊ•+BØÜ¹sét:ðd¶lÙÂf³»ºº„B!èEDDTVV"„ôz=—ËõpØ¡ÒŒŽŽ‰Df±X”J¥F£a2™Z­ÖjµVVVböôÓOoÞ¼ //ïÎ;aëÖ­kÖ¬ÉÉÉ¡R©eeer¹<,,¬§§Çq Ã{ì±çž{Çq»Ý.•J;Æf³üñM›6EDDŒ+Š®®.…BãxEEŽãÏ?ÿ<¸ôïJ©T’H¤7FFFZ­Ö7nÈår­V;oÞ¼>ø!´mÛ¶]»v„/¾øbÙ²eà™ÞÝ݃‚BH"‘€ºShh(ˆ à `hhhݺu†•––¾þúëT*µ¹¹yݺu---‰d||<<ìãããããóöÛo'''Ûíö9sæ>|Ød2………mÚ´ ÔàË7 ùùù*•ŠB¡ìß¿¿¨¨Èf³MNNªT*N' 7oÞ,‰¬V+ðü‚ƒƒƒƒƒ×¬YÓßß?oÞ¼°°°ÀÀÀ·ß~Hýqqqb±øí·ß.,,|ûí·e2Ù­[·àÛóÈ ‘H„9óÇl³Ù`Rêv»»ºº˜L&|š0àg¬œœÐQ(`Œi`‚ã8°ÿ^zé%[æàÁƒP#ßÿ}“Étýúu6›}åÊ•5kÖœ;wnñâÅ&“Éétþö·¿%‰N§sÏž=r¹<##ãÆÿùŸÿÑ××' wïÞýé§Ÿ2™L Ãìv»Óé|æ™gfy}ÙíöC‡9"‘øÆo9r”®`‘fÿþý@š+..îîîŽ?}ú4(xAJ% ‘HÔjµÐwÆ™> Ãèt:¬8qâüùó@6Ù¶mÛ±cÇ€€uñâEXï@íÚµËb±ˆD"&“i·ÛÝnwccãâÅ‹ÕjuZZô¿ ¥££cñâņÏç×ÖÖ~ýõ×!¥RyðàÁææf“É´téRn€¾øøñãSSSK–,ÑétAAAK–,9|ø°@ úôÓO=ËQ!6›ÝÞÞîëëk±XV­Z‰J¥ò“O>™¹FØÙÙh±X˜L&”ïèè(Dl‹ááa°dɃÁpëÖ-«ÕzðàÁ#GŽx¨i!Äápf7 È£†a|>žÜÜÜ9sæ”””Àw ­ß¢E‹âââÐw‚8†ØÍÌ0ÿŠ)ÈS ‚Y2IÀКe†a‡ÅbÊÊýNc÷ërâ@¸ß"‘èëë ¦îܹt”6nÜk˜$içÎd2Y"‘¬X±Íßâñx÷Ò!!÷ÇrHd2ˆ_³î ‚YšM†ÍÊ=€GEˆJ¥ÎRÂq’9+CÀ”›5ÄÆ0ì~œ‡a˜Žã4mŤšX,Ö¬Ð<™\UU5K!„`äÁb±f鄤Îrôó¨7Íú ïÏ”ÿ œï í{$ Fu¾¾¾3­‚¤yþñëùÒâI)€B¡Àp÷þ·þÎTüýöï“t:ÚNÿ™µÒ‚ãø÷2 ÿw¶ýýøÞÝ$">gÎí–——;ŽÉÉÉ'Ÿ|²¾¾ÚÒäääM›6Éd²ºº:Èt»Ýþâ‹/:Žšššˆˆˆ±±1P•’ªªªÒÒÒæææ·ß~ÛÏÏÈ»Ðåååýò—¿är¹ êýÝ+¯¼3oÞ¼[·n!„RRR ›å•WJJJ€è‘’’rëÖ-øRív{iié¢E‹ÒÒÒnß¾aƒÁ°ÙlsæÌ©ªªZ±bÅÙ³gŸx≺º:àvÂÊŸŸ_YYYccãòåËõz½Á`Ø·o_^^žÓé\½zuLL °½)ŠÍf{ñʼnDâòåËÓÒÒººº ãp8ñññ¯½öÚ7ß|³fÍš¼¼¼Û·o#„Øl¶Õj¿þõ¯AˆÆ`0ÀE"‘ø‹_ü"''çÞ½{:ÎßߟÉd ™LúX·nÝÅ(‡Ã±gÏžŒŒŒ¤¤¤ææf*•êv»a Ë"½½½?þx]]H$A/„PdddZZZ{{{uuõÄÄ„ÝnÿÝï~k·ÛÇÆÆÀ†èèèüüü§žzª©©iûöíׯ_‰D|>_§ÓI¥ÒíÛ·ÃHÓ·K—.}å•Wpïêê±4"‘¸råÊmÛ¶9:…Byýõ×¾ûî»ï‚”…B!‰ê _C%%%µµµá8Îb±@J+---::ºµµ†c+W®µ*…BQVVæëë"—Ë ^}õU˜[?Þét‚¨4×999¿ýío™Lfmmmww÷Áƒ­VëŽ;`†H¡P¦¦¦@ÇRÓøÿ÷7 ñññ§Nb±Xd2¹²²òµ×^ƒEQ …rõêU„PYYÙþýûi4,÷ýö·¿u:ƒƒƒQQQ@$‡¤Í;÷æÍ›¡„„„ööv8‚Â*0¶B6lxñÅq7 yyy°éžû †µ¶¶B¥?wîL¾üüü>øàƒ¨¨(X­åóùT*•ÏçðÁ n·è©ÓÓÓ`÷îÝ{öìáóù]]]­­­ÐýÕÔÔ¼ð @‘‚ÁÖêÕ«_}õÕ5kÖìÛ·ïÒ¥K·oß¶Z­6›M­VÝ»wÏC§ËÎή¯¯' *Û °´Ëf³?øàƒ”””îînPxòÉ'»ºº¸\î®]»žyæŸ>úñ«««_yå‰ôõ×_÷ôô|ñÅ8Žÿüç?¯¬¬´ÛígΜ™ššºxñ"Lfy<žÕj½pá‘Hìïïïíí…Ök÷îÝO>ù䟛CQA›3Ûº3gΘÍf755}ûí·v»½µµ5<<¼®®vŸ\~ÏÆBhzzúÌ™3t:$`ÜZWWwîÜ9§ÓÙÖÖæïï2ÒýDFsøðaØzokkûâ‹/²³³u:ÝáÇ'&&h4ÚÍ›7‰DbRR’F£¹víÚÕ«WµZmdddoo/F#žH­Vë±cǨTjggç·ß~[__2Á2™¬¶¶!ª$/j ÍXŸ9|øð¹sçôzýáÇÇÇÇÝn·ÏÁƒóòòêêêt:Ý•+Wnܸ¡R©H$Ò¦M›>ýôS„PCCÃéÓ§gŽßm6ÛÉ“'[ZZÂæÍ›?ÿüsO•øÞ¬€âƒ¯€S©ÔyóæÝ¾};00&¨ Éb6›aç8%%åĉ*•J¡P "„ÔjuoooCCý{÷ …Ýn¿qãpÛ].¨Ó$$$ôöööõõét:íÚd2Á~bbþ1 }}}PêPɠ뉉‰a±XõõõQQQ7nܘ˜˜P( Z½ê¥K—@LæÞ½{¡6›Ð××·páÂÓ§OÓéôèèh©TÚÚÚªÕj333[[[CCCAR!##ãæÍ›r¹<99ùرcF.—£ïv<šššz{{U*•^¯Ÿšš‚f4¡´t:\.w8]]]‹ÅårâéÓ§Íf3t v»=""‚D"]ºt úH©ÅbÉÏÏû§¦¦ R·ÛóæMØa„Ɔ†‚òôäädAAÁùóçE"‘ŸŸŸL&knnv8R©´§§'22rddÄ`0¨Tª¡¡!Èê®®.ø˜åry]]]GGGww·Ëåîîîv8B¡P(r¹Üþþ~¹\%ëI#Bh``@¡PÉäÀÀ@§Ó9555>>HK £ÑE966öß”¤=3ÇAAÕÏÏVäÐwC3¨§\.÷~ÁÓÈd2tmb±˜Ëåz&‰°. ò8Ò¾ÿX,–D"AI$&“éч†=öC¤›?ñÄK—.yE <ñÄ0fÚºu+LVW®\9þü]»v­^½úYêÅ?0 –H$»w‹Û½{·P(lll„mµ¡¡¡ôôt¹\.‹AZ<–µÙ^üÐá8n³Ù¤R)(Ðét:§Ó "‚SSS°7l6›aIÐh4ÎZÐó‹ûAäóùƒáîÝ»7oÞt:?ùÉO$ɼyóà”¹àà`ÖBˆÉd~¿Ï^ÌÀ÷Ï1 ƒ¥š•+W~õÕW >>Þd2±Ùl·Û}öìÙ¬‘^xá…^xá…^xá…^üP0ó(ÏÿÄ‹D"Á–Ñý§­ÌrýyH§txñûûû›L&pMq»ÝÀårQ©Tð—‚Ó Y,ܺ·ããã¾¾¾&“éé§Ÿ¾zõjFFFuuõ¼yóÄbqIIIJJÊíÛ·=t:Ýívóù|“Éäççœ5ØÔ Õëõurrrzzz{{{rr2œCa6›Ýn÷Ö­[£¢¢”Jå“O>™••åçç·xñb à Żï¾{áœL&s8“É^Š3Åø½øÇƒ¸mÛ¶»wï–””ÀÉc&“ijj*00P«ÕŽŒŒÂácz½þîÝ»ÑÑÑ6› ŽÉ \„P^^Þ—_~)‘H¢££N'¸5.Y²$33s||\ Èår‘HÄápúûûÁý¼Y&''ýüü{ì1ðí·Ùl@ÉÍÍÍÍÍ5›ÍCCC'Nœ8wîÜ‚  Å7ÊÊʈD"# ü‹   'Ÿ|R$uttôôô544À‰j^<*`“““ÑÑÑT*õÎ;p <ŽãL&“ËåJ¥R¹\ÞÞÞ.—Ë»»»Õju?…B‰‹‹3›ÍàŒ‚F¢¸¸˜Åb]»v ~FGG÷õõ577ûúúŽŒŒ××׋Åâ'Nù˜Ç㎎ªT*vçΠáª,Fs»ÝçΛÙ' …B­Vëv»>E"‘d2™@ €³6;::FFF€ËßÞÞøh²Ó‹ï€'%%]¾|Y¥RÙíöúúú ¨T*¹\îr¹Ž?4:::ôÚÛÛÇÆÆ¨TêÝ»wÇÆÆ†‡‡ïÝ»———wïÞ½ææf¨O­­­R©T¡PÔ××cVWWçççwìØ±¢¢"psƒ£5üüüúúúìvûíÛ·ãââîÞ½ Q ŒŒŒFð…2›Í“““yyy­­­z½>((諯¾:qâÄèèèÝ»wN§Ùlž˜˜„ížžðÓòâ‡hµ^üx‘——§éy®Üt'•Jõv:^|/ðçŸÞår-^¼Î,!•Jµnݺ?üðñÇçñx:®´´ô™gža³Ù RÂf³srrV¯^m³ÙÀiØ /<À0 ‹ˆˆ˜?¾T*ÍÍͽtéR`` ˆ*©T*Ç###£ØÒÒÂd2¿üòË¢¢¢˜˜˜ÀÀ@¥RÙÜÜ|áÂ…G /~pÀùo³Ù:;;Fcrr²Z­®¯¯ÏÌÌÌÊÊjll´X,©©©p,P( ioob±¸¥¥E&“ÂÓ£Nˆ?0üItÀt ’=ž[!`Sá8¾víZ` zôa¿— î…8ÌÐb2™”J%4?À`0°X¬ÐÐPX·t»Ý­­­Ð€ }'8 †Á ° D„5Ç0Í`0ÂÂÂ0 ãr¹ Lø÷[L$ÓÒÒ´ZmDD„^¯w¹\R©Çq£Ñ—””488|: …Ä`0@OØGjµšF£I$Øc P(!!!G£Ñ€r)°ü`ËÉdÒh46›M£ÑL&“X, …f³–õ Fxx8(º°Ùl˜èÀ~ÃLuZ€X,&‘H3S ƒÓé,‹ËåÂIéÅÅÅ*•J h4š¤¤$­VËb±‚ƒƒ¡cñ¼Î`0BBBT*‡Ã i`¨TªD"Q*•,+<<ø®  $•J- $\£Ñøûûûúúêõz‰DB @XÐn·³Ùl( €€­VF"‘l6›T*5, ”5!X ÿý·ŠUUU•žž~ïÞ=ØT ‘J¥jµú©§žêéé)++‹Å°žn·ÛçÎ+—Ë7lØP[[Ëf³³²²¸\®Åb („PPPP(ŒˆˆàñxÕÕÕ*•jÙ²e###™™™“““k×®U«Õ8Ž/^¼8,,léÒ¥---.—+)))$$ØsL&sjjJ(¦§§Ã^ÐܹsA­ØÉÉÉÉ.—kíÚµf³¹¢¢B$I$’ÒÒÒÅ‹…„„ŒŒŒìÙ³G,WTTH$¹\®V«ö³ŸÑét­Vk³ÙŠ‹‹333ìSSSsæÌ™;vØíöU«V]½zÔ”«««ãââ222bccoÞ¼ù³ŸýL§Óh4š„„‹Å:t:½ªªJ(VVV¶µµ9Ž´´4…BQTTD&“§§§á,HH‚H$É“9sæ´µµmÛ¶mΜ9Ë—/`³Ù‡£°°°¶¶–Åb•••ݼy³¦¦†Ãá,Y²¤®®Îßßßn·P(”—_~ùÔ©SÏ>û¬H$"ãããñññ C£Ñp8œ×_ý믿†»0-›3gÇ ***ÊÌÌäóùB¡ð±Çs8N§3##cÑ¢E—/_ÞºukSSÓ;ï¼£P(rss“““q_²dɼyó„B¡¿¿zzzIIIpp0“É,//ÏÉɹ|ù2Žã¡¡¡žúM‘‘‘:nÙ²en·ûôéÓëׯ lCCCDDÄ /¼`2™Îœ9ëÑ  åÇU*¨ÿÕxáÂ…P]¶lÙrãÆE‹!„Ö¬Y£Óé&&& òEFFj4šÊÊJNÒ9k×®mnn†Ao”9 …¿¿ÿää¤Á`8yò¤Ãá8uêTzzzLLÌüÇáøîÝ»555—/_þÕ¯~J| ƒàr¹:;;Áôô´^¯ojjÒjµÀ´¬ªªúÕ¯~åp8H$¨ƒº\®±±±ììl‡ÃÁårñ‹_ç˜Á`)•ʵk×vuuùùù¹ÝîuëÖY­VH;ƒÁHLL.))!‘HR©tbbbݺuÿò/ÿ‚Ñ“ÉT[[›žžþì³Ï.\¸!ª]$I§Óeee‘H$ƒa2™bbb€Ûã8¾xñâ%K–|óÍ7K—.­©©…£Îoß¾599ùÔSOéõú}ûö)•JZ°Z­‰‰‰Ÿþ9‘H hll„T Òh´àà`•J•ššzéÒ¥©©)™L><<\XXzZ'Ož|ùå—/]º ºa`ä IDATÓéBCC8°uëV—Ë944tïÞ=ÙNJJzá…V¬XDYìöíÛ Ö†R*•--- I»Ñ.—K©Tž:u †ù 'J¡PÆÇÇA^·µµõøCRRP™Íf3™LV*•øøãN'N·Z­n·ûöíÛ~~~*•êÈ‘#ÐÎÁqíP‡ˆDbxx8‘H±X,&“éÎ;‡JMMíë뛜œ- …’››Ëb±úûûóóó³²²¦¦¦p'‰‡C&“ ‹Å222rîܹ¬¬¬„„2™¬ÕjSRR<+À /‰h4Zbb¢Õjýì³Ï~ó›ßÄÄÄ@&477ß×n·Ã³¿ÿýï¿úê+04ÐúúúH$’F£9tèR©„œœššÒét†¡Ôét*ŠãÇS(«Õ r 2™Ìd2FFÀçó=Z_V«òÇétÖÕÕÙl¶Û·o¿úê«gΜyùå—A· †ñññ###£££Ÿ~úé‡~8³[äóùüã}||N:¥ÓéjkkÇÇǧ¦¦¾úê+ ÃÆÆÆFGGÕj5¨ :ιsç^¿~Ä"""JKK[[[cccáXÓéé錌 ð¸zõ*•J‹Ål6ø8{öìñh)RSS tö,ËårA Z‰Úg.— {Éð•Àó f¡Óé@ŸD£ÑP©T8¤þâÅ‹ ¢!‰BCC›ššANN¨uÙív‹åt:- üc·Û7nÜ*uV«Õét2™L£Ñ(“ÉZ[[Aª„@ ˆÅb‰DrõêÕ¨¨(‹uõêU™LF¥R'''ËË˧§§ÛÚÚ"""Ž=ŠaXBBŒ‡(ŠZ­ær¹ §ÖÒÒB&“çÏŸßÜÜÌãñœNg||üùó硹Z½z5( ‚‰Z­æóùééé---"èÑ:::ØlvyyyGGGoo¯Édâñx‡¨r8Ž;ŽM›6Q(”÷ßD7ƒ‚‚(ŠV«5™™™:.88øóÏ?‡+x¸\®Ó§O«Õê­[·þîw¿ãóù …b¦ &BÈßßbbz:TÜW(J$’»wïÆÆÆ*•ÊéééÄÄÄŽŽƒáïïßÒÒÃОž™LRPþa³Ù.—‹Ãá…BªIz™LÖÙÙ ‚ÍÍÍááá‹ÅCíÿøKO³®ÿ•Ÿ@Ò¿_XFˆßû"‰DŠ‹‹ãóù3v :Þ8›Íöè`ýÒ5ëî_Ržu³ïµ‡B¡ÄÇÇ{ÄÖf½~¿úN.B¡Àì›ÇãyT¾þ¦y?(àÏ?ÿ}úôÂ… |>T!www Ãsþ;IIIOž<±ÿÙÔÔ$‘H²³³,Kyyùþþ~tt4‘Hqss›ššb2™&“éwÞ±G_Awtss355µ«« –ö‚|òÉ'ñññ ˆJ_d29$$ÄÁÁ@ ìííÙ=)`·h2™‚ÕjµZ­333°ÒëõÝÝÝ<ovvv~~~vvV,ÓéôÇûúúZ,°9å´Ëb±?~ P3™L644Äf³©TêÓ§OáŽ>×î¥K—âââl6›———ÕjžžÆáp ÖàÅgµZwvv233[[[í s¦Ñh„aÆÅÅ„ÐÐP¦ÑhÄ`0Ï “H$šÍf4Çãu:4êB“““:*• …BMLL,..NLL¨Õj¡P"€ÛÛÛƒá9­²ÿ &--mgg§­­íÉ“'f``€@ „„„´··ƒ'ÇÈȬQ(”ÅbY[[£R©³³³°3ZXXæp8·oßöõõ•Éd~øáÄÄÄ‚J¥ruu½{÷®³³³N§©àžžð'²Ùl:nii)77F/--Ùl¶ååe&“éâârõêUÐë¹téRWWׯÆFZZZss3¦?ýôS0éîîÎÎÎîèèØÜÜœ››Û0‹Åãñ::Ú`0…BµZýæ›o¶´´8::fdd€EVqqñèèh^^žÕjÕëõîîî€ÃÃõµµ!!!===©©©...'OžÔh4&;;êËÊÊU*ULLŒÑhŒ züøqEE¬“’’ˆDbxx8ŸÏïíí­¬¬|ôè‘H$b³Ùr¹üĉUUU:ÎÓÓ^—åååóóóR©Ôl6ƒë΂F£_ŒèèèÇçææ …Bpƒ|ÜTð qvvF¡P‰‰‰KKKÛÛÛyyy;;;x<Þ÷/ÅÏϯ¿¿¿¶¶öã?ÍY ãëë233sàÀ°°0@”À‚@ xyy­¬¬„„„(ŠššH]„……­­­Ñh´¬¬¬¤¤$.—ûäÉøúÄÄDZZš‹‹ ŸÏèíí­©©‰ŠŠzøða^^ž··7›Í˜šš*++ {ôèQaa!X…‡‡ËåòìììGùùùAò ´´taa¡¼¼<ñl6›H$òôôtuuÔh4l6Ò$_œ/†uÆØØXHH,!Lš‘‘qýúu¸Ä6›maaÁÍÍÍb±¤¤¤455iµZ“Éó¡¡¡"‘H¥R!bµZƒ‚‚¬Vë±cÇ$‰£££^¯Ÿžž†Àÿþþ~^^ÞÝ»w=z”˜˜øðáÃíímAž<8.,, ƒÁ¤§§çä䤦¦æååÁ]¬­­utt,)))((àp8‹%55õæÍ›8N©TÒh44¶X,0ÛÁ0FãÔÔ”¿¿ÿ‚···ŸŸßÂÂØB´‡Ãi4ƒÁÀápÀ•jb±xggÇf³ @ˆáéÓ§yyyd29::zpppff‡Ã-//CsCCCÅÅÅàZ¸»»Áçóñx¼‹‹Ëææ&pO¶··¹\®F£Êææ& _©Tr¹\N§Óé\]]777aî5°–wuu…ëŒÁ`bbb***íŒF£ãâ⪪ª"##kjjärùüü|]]ƒƒCIIIFFs~¾`aòÞÞPùl6›ƒƒ|X,Ûl¶_ýêW0T½^Ãá Ã;#B¡l6 …*++ S©TøÃœœœ H"‘vww§¦¦êëë'&&¢££aóЦÕj­®®Öëõ»»»óóóÇõòòÒh4ÕÕÕƒaqq±  Àf³577744,//»¸¸ÀùaààZ¨T*çææ¼½½% ÇÓéto¾ùæôô4“ÉÉjŸššŠŠŠJNN¾yóæÐÐPYYYÿáÇÁΤ°°°©©ÉžímhhJUMMMSSSYYt£ººZ¡Pètººº:àÕ9::Þºu ®³Édúä“O®^½jÏ †¦¦&pß¼uëVtttPPÈÊôÑG@œùŠ•‚üÅ,Òm_0³}‰ …zÎ9ãó¦#öz`±~áíñåçÎF©öz»ùà—ÕÓðóçùŠòe~¶?_6L{½½ÿö³Ù¯çW÷¾ç!‰ÏYÒA± Û‡ù\÷ì>ßœ½’˜ÏÕÛqxöëùµå«/—½``†wppÀ†Åb¯pª±Ùlð»$ƒÁ``2™‚J úÄ`0t:N‡@ øHÁñÀ1„Ä0Ô«Õjð*”ñx¼V«%‰h4O4 rm€‹1zƒÁ°¿¿S#d~ö÷÷]\\À ^»NNNðEhtýu:““‡3™L^â...z½\nöööX,–ÕjE¡P0^»Âûþþ>8ç<9‚T&¸DÁŸöúg?Àô| píÙã÷÷÷á¥ñµ‡=[oÿ>|¾¹ÿiý×–çü°¾¬`‹‹‹áÞ †Û·o‰Ä_üâ?ùÉO*++[ZZâããm6›L& … A~àÀ‡›7o&&& ''§éééÁÁÁS§Nݽ{ì* ܶ‘‘‘ŒŒ ÓÝ݈Á`~÷»ßݼy³ªªêèÑ£ "‘(**ê‡?üá /¼Æ óóó\.×jµŠÅb¡PH"‘666p8Üúúz__ßþð‡ÿøÇ………8n~~ÞÑÑÑh4zzzêõúááá””,;88Èf³1 N×jµOŸ>ÍÉÉA£ÑÞÞÞ …Béõz±XœžžnµZ;;;ƒƒƒI$’Z­†ñÞ¾}P&“é_ÿõ_'''Åbñðð°V«%“É:ŽD"}ôÑGÕÕÕà æÂå½ù& LÂX,ÖÅÅecc£¸¸xoooooÃáp¹\&“ÙØØ˜™™€ÇãWWWSRRt:Ý¥K—.\¸P__ÖÁÁÁL&smm->>~mmÍÑѱ­­-??zzÇonn&$$Èåòàà`<ßÝÝ »ÞÞ^‘HtáÂ///pg ›œœ\\\är¹ *ˆF£/_¾œššë±XìææÖmyyy)ÊÎÎƇÏùóç³²²°Xìõë×KJJ¤Réþþ>ŸÏ?þ|ZZ™Lnll¬¨¨X__W*•áááׯ_NNN—.]JJJ}÷ÝwQ(ÔÔÔTUU•ÍfS©T'Nœpqq©««sqq‰ŠŠB¡P]]]\.÷G?úQHHÈÀÀÀ—Í7ßÀ‚yýõ×/^¼H&“BCC-‹@ …MÌdðj_]]õõõåp8ÃÃÃ"‘¨³³S ÌÏÏ“ÉD"‘˜LfSSSHH‹5™L°Uï“ÖÖÖˆˆF´¸¸h6›i4ÚììliiiKKKEEESSSjj*‡Ãééé0Zkk+…Bqss¢¶³³³ÉdŠˆˆ˜››svvvqqY__‡¨ ™L¶X,°£¤ÓéË8ƒÁŽ~Ááp°qÓëõ{{{\.‡Ã-,,P(ÐGtÊÈÈÈââ"ø;@š2..îâÅ‹Àóöôô {úôéÌÌŒÕjíêêzÓòM/B¡Ífƒ9/‚ >>>h4:%%…Çã1ŒÌÌLP'&&âñøÔÔT~xxx âáᑚš 8ô0'vqqñððHIIË×   ‰”““pOOO,K¥RÁÃ<ÒÒÒáóù>>>D"‘Ãá‰ÄœœpYÎÌÌø!ÇÃb±ñññ`Ó™™ h™¤¤$Ø-C¢3++ `Lééé &** ̧³²²˜L&“ÉÌÌ̈¨¨(,›––8»ÌÌL»7‘H”ššúyu{//¯¿Þ îWþ—Ãz¾-§óƒü`oo/::º´´tggçСCB¡paaáôéÓh4ÚÕÕµ¡¡áÑ£Gßýîw322 Åñãǃ‚‚ ¨ˆ Httt\\ÜÜÜœ››ÛÁƒq8à¥üýýóóó¥ ô ‰Š‹‹———O:?33sæÌ«Õ ð6›½¶¶–œœlG#ýøÇ?KLL¬¨¨P©TEEEiiiSSSàzZ__B¡’““³²²VWWOœ8f4H$’P(„ÜÅñãÇ£££¡?ÎÎÎÅÅÅ …âСCqqq …âĉ\.—ËåBJª¬¬,99âõ°Þ¯©©1™Lr¹Ü®ÿvöìY¡Ph±X ¿õ555………Û'Øg]µ¾9 Iø±±1N.{T*533¢ýýý`¥÷øñc±ôööòx¼¥¥¥ÎÎNÈ©A¼¾¾¾žÍf÷ôô(•ÊŽŽŽžžžµµ5¡P(—˽½½³²²®^½ ÎÕ‚ÙÃÕÕ5##ƒ@ àñøææf“ÉÔÙÙ™žž¾´´tûöm ¥Óéðx|\\ÜÝ»wÁ$q~~>,,¬®®ŽÍfgee}üñÇYYY>>>Ož<©¯¯_YYqvv®¨¨hllLNN kii9xð ^¯'‰uuu—.]Љ‰‰‹‹ûì³ÏêêêÀ»±®®îÎ;!!! õUVVF£ÑÖÖÖêëëûúú€’õÉ'Ÿ¤¤¤888œ={¶¤¤AOOO­VüÒK/ÕÕÕ9s¦®®nppôë(ÊÑ£GkkkŸ³¥ý†t[[[QQ…B‘J¥V«uuurÌÏFù-®R©€_–››ÛÔÔ´¹¹¹´´túôi>ŸÏ`0ø|>`Ð?ûì3A||| ðx<•JššŠˆˆP«Õz½ž@ ´··çååh J¥âñxÀšŸŸ·“>ûì3ÀÄcqTT‡Ã hùþþ> …‚ðƒKHÂAç- $˜íV†6› êá„ö/BZÌíõ‚@½Íf3›Íkkk—Õét¾¾¾r¹|mm ê ‚L&c2™ð‹2Åßèæþ- ¦¶¶vdd„L&tvvr8™LvçÎìììÙÙÙÉÉI:>== q ‘‘È–Óh4 …>ŸîÜ9H ¥b~~¾¼¼|ooòS“““2™,  ½½]«Õòx¼¶¶6.—«Õj¯]»VXXøôéÓ••`·áñøÙÙÙ˜Íæ••4½²²B¥RÝÜÜnܸA$Y,Ö… Z[[5MOOO~~~{{;ð0)´±±ÑÚÚZRRòðáà ¡PØØØÈçóÕjõµk×*++ûûû%IRRÒ'Ÿ|âææf³ÙàÁ}úôéÓ§OÓÓÓoÞ¼ ?Œ+W®¤¥¥ÍÏÏ÷÷÷çääêk||6€¾¾¾gttôöíÛR©tzzZ"‘$$$p¹ÜlmmÍÍÍ=“ü¶|[¾-ÿï †ÍfƒnŒP(ÜÝÝçóùÛÛÛÅÅÅ §  `mm-<<<<<|qq‘B¡­¯¯óù| Ãf³ÓÓÓe2Ynn.ÇS*•ÅÅÅJ¥’Çã%%%-..¦¥¥µ  `jjŠÅb•””,--¥¤¤8;;ïììTTTìíí±Ùl8?ö÷÷çóùAAA6›-##ÃÏÏoss³¸¸èot:}}}N«Õj‹ŠŠÌ)‰–––ÒÓÓœœ4MIIÉηÃIIIYXXHIIÜ~yy¹V«äÉââ¢H$òööV(ÅÅÅ‹ÇçææÊd²ððp æåå988Øl¶‚‚¹\n7ÓF$333,,L.—? HKK“H$ ú[ÜÓÿóÓŸþ€çÏŸ¿{÷.Ç …ÃÃÃ@ Ð4‹õ÷÷—Éd]äwÞyG*•VWWwww›L¦êêêÞÞÞ¢¢¢§OŸ–””ˆD"Ø‘H¤ŒŒŒŽŽŽ†††{÷î}ÿûß3é´´´ÈÈH`PÜ»wïðáÃ111T*µ¤¤ÄÉÉixxxggG Ëår‰DB&“ããã·¶¶òóó{zzªªªÆÇÇËËË£¢¢ Ell¬‹‹‹P(ô÷÷¯ªªŠŽŽžššJNNö÷÷ òööž˜˜¨««ƒ €Y,V@@ÀÚÚZiiiDDÄððpAAAxx8رÆÌÌÌÐÐБ‘‘ÜÜÜ¡¡!@€F£5Í /¼0::š™™i6›I$PÎxB§ÓWVV’’’\\\€ŠøM+hƒÁÀ`0^|ñÅááaƒ177çááa4aáÜ×ׯÑh&&&ø|>ˆm>|X*•²Ùl''§ôôô¨¨¨‰‰‰cÇŽ1ŒÕÕUˆƒGEEܤAa©H4€òD3!!A«ÕîììÀ¶ÿ8ŽËå‚*ÄÕ«W™L&‹Å:räJaÇzæÌ‹À7‹Å²¹¹éíí­T*F£««ëêê*•är¹ÏÎÎŽV«õôô\]]…T¿\.÷ôô@©——Ü~‰´¶¶ÆápôzýÎÎÇ[__·Z­°I¤P( æôéÓÅÅÅ‚0 ‘Häààð /8pàøñãUUUííí‘‘‘CCC§¾¾þðáÃvQ‚oTÁ>}ú4""âÖ­[UUU ¥¼¼\£Ñ€q<‚ ÕÕÕ‹‡Ã>|X¥Ríìì<|ø0++ëÉ“'àÃ.•Jétº^¯çñxÀµ?|øðòò2Ȱ¸¸¸¼òÊ+7nÜ @‰™šš€y‘Éd…Bl0‹Å:'f³òü...ÛÛÛcccÁ›v°ý IDATÁÁ2™Ìf³Y­ÖååeHAsSSSÞÞÞÙÙÙwîÜ)..ÞßßôèQCCƒT*e0M@mssó‘#G`O€$POhnn®¬¬Ôh4»»»|üøqBBBdddKKKNNŽÅb™˜˜8tèÐüü¼Åb9sæ ì7- d£Ïž= è.›ÍöãÿØ`0xxxÌÏÏÿþ÷¿7fü¦È(?[a4ý…ˆ" ‰ P§@žÙ?<·Ô€BxÌþ'GGG`Y7ìÈOÏ6‘,ûl7¿à‡°Xì³ÇÛ?Øñg³×Ûñg€Ã|ö‹Ï ÿ¯¬ü¦´ƒƒ„pàÂY­V€æàñxÔ_ òŒÒ@€ãaÆ‚8ò   &•ð]ÀP b6›!ÔîííÙ[ /4³<öž@0ùÏF?×O{ý³Ú?<;®g?|~¼€ÌFþ"Ññ\r&*øQ¡P(˜zí1c‡ÃàƒýÙµƒæìh;ø@"‘`°ö_œz¶~QPWFC®ê‘¿ü†Q(ü8¡P§…z, ýÁãñpÍ¡ƒÁ@‡í?f8!0¡nå³ ¡~ÿûß_»v gîܹ£T*ó›ßœ9sæí·ß~饗òòò<=='&&"""ètúgŸ}VRRb±Xfff|||fgg½¼¼VWW;;;Ïœ9óàÁƒŽŽŽ7ÞxcppP loo_¿~ýÌ™3­­­*•*>>žÇãýèG?jiiùîw¿›’’RPPðÿðEEE}}}?ÿùÏOœ8qèÐ!GGlj‰‰””›ÍöÑG½üòËwïÞÅáp>>>b±8,, AÖÖÖÜÜ\«Õ:99éãã³²²âëë‹B¡ÚÛÛí¯ÂÐÐP»¾Òƒ*++inn‰Dðèãñø¾¾¾ÂÂBÀ즤¤¢œÁ`Œ'%%!òÛßþ^èJ¥2 ॗ^Òjµo¿ý¶R© V(ÛÛÛiii€ºÑh4ÍÍÍgÏžíèèØÙÙ9vìØµk×bccFã­[·NŸ>½¿¿ÿî»ïþú׿>vìXhhhCCÙ3gÜÜÜÞ{ï½³gϾþúëwïÞµZ­ÞÞÞ7nÜxùå—/^¼(‰rrr:;;¯_¿Îãñüüü~ùË_ÆÄÄ0Œ””<ÿñÇÇÅŹ¹¹­®®:99µµµ>|Øf³3Öd2œÓ“'Oòóóm6Û­[·RSSÍf3hÀLLLÄÇÇ#!L‹ÅøýÅÅE Š´µµìïï ñùü .— ·²²2AîÝ»¥ÓéÈd2ƒA«ÕjOOOˆ¼óùüºº:±X¬T*ë|õêU€Ä\ºt‰F£‚ˆ¹ûûûAAA</22ÒÉÉI( ¿u ­ƒÏïÈȈÅbùÕ¯~USS#‘H4Mww÷Í›7aTsss(ŠËå^ºtI ¨•Åb£æÊ•+ÓÓÓqíííÍÍÍíìì„ýÁG}±¶¶¶¼¼¼ÁÁAµZ˜˜/ …ÁÏ™™…B‘}þüy&“Éf³°¿²²"‹srr>ûì3 …âíí}éÒ¥ÄÄÄ‘‘P¶9wîǃŸ²‹‹ lô£½úê« ­nnnaaa C¦R©:0 ÎÎξ¾¾‰^ƒƒƒ‚´+QA>{ggÇÅŦsrr>| l](&“ÉÕÕU*•^¼x…Bíîî^¾|™Éd OOÏîînJqL&(=ÀÌÁb±L&S"‘8;;‰D¹\›JA8΂““™L–J¥nnnûûûf³™ÃáH¥RGGGGGG &#¢×ëAý‡D"æÑÆÆÆÛo¿ ëýÞÞÞæææ¨¨¨ùùù–––ÆÆF­V+—Ëýüü ÅãÇaNEdkkëüùó~~~ãããÍÍÍžžžt:Ęž}™tÛßßßÉÉ©±±‘Åbmmmuvv†‡‡wuuÍÎÎ&%%ŒÖÎÎÎåË—í¬gggàð¼úê«}ô‹e³Ù@ç¼rå °A×ÖÖt:ÀqÍf³««ëÒÒ•J¥Ñh0dHȉD"ƒÁX\\„XOÛÛÛ8ÎÙÙY"‘¸¸¸àñøõõuWWWN‡F£Y,–D"a0$I&“q¹\ Ô¸ºº"UUU^^^¡¡¡ÅÅÅ0ÓÀÔ¤««kUUF‹ŽŽÎÍÍ%‰ Ïf³«««™L¦¯¯oqq1hMÅÄÄÀ•ruu (++sppð …,‚ þþþ8. ÐQvQ],Ëáp*++†%‰°XlqqqPPPHHHeeedddXXXvv¶ƒƒCNNNHHF«¬¬„eAA‹ÍÈÈˆŠŠ"‘H•••À,++Ãb±ÉÉɱ±±8®²² §8.666)) ÈLÞÞÞ,«²²’L&GEEedd<» ‡-3HX=ûdP©Ôªª*‡ãîî^QQ³ˆ¹UUUyxxxzzVUUáñø„„„„„A ¶ —N\1¬££cUUƒÁˆˆˆb>‹åóùt:½ªª ~Q~~~¡¡¡nnn8®¢¢¢´´”H$Âöõõ=pàÏÈÈHKKƒ!»»»pÇ‹D¢ääd²}È‘‘‘ùùùNNN•••t:ÈÌYYYááá ¥²²ÒÅÅn=‹MMMŽŽ&•••ÇÃÃöàžQž½Xðç73{úmù¿RÐîîöÚköÇèàÁƒ Åóâ‹/b±Ø˜˜˜_|1++ëoÚÏoËßYA>|A‰D  …òõõ]YYsss‹%22ryy°lß–oË_YþóØÜÜ ‡8@¯éêêÚÙÙ)--E$&&æÐ¡Cßš|[¾¶ ———ñóóS©T•••°“B¡Póóó ç 鉉 A.^¼ø­+î·åë DWKKKi4x}ÇÄÄÀ«¨¨è¯'ª[¾-ÏLNNŽX,éú¹¹¹°°0СËÉÉ™™™Áb±III2™,00dd’““===5MFF¡ÂÃÃWVVRRRP(”ÅbÉÉÉÙÙÙñòò‰DJ¥2::šÁ`¨Tªüü| :'&&J$MmnnæææîììDFF†‡‡£Ñh777…B‘••^å™™™kkkAAAkkk©©©D"‡Ã …B©T* AX999*•ŠÍfGFF.--¡P¨ððp•J•››«T* FZZÚÒÒ’H$ A0Ÿnnn•¡P(±±±R©4!!˜ŒYYYëëë`cc#!!¼Crrr¶¶¶¸\®H$’ÉdIII>>> …,---EEEq¹\éÙÝÝANN—œœœžž®!$)77W£Ñ¨ÕêÂÂB¡P(‘H¶¶¶ªªª„ï§%‹CCCÝÝÝy<žD"©¯¯¿sçNdd¤V« „‡›ÉdæææúúúnooGFFfeeÁ„ŠÁ`ÊËË»»»Ož<ÙÖÖöâ‹/ÎÏÏ«T*OOÏÂÂBµZ­Óé*++æèèyâÄ &“999 D£ÑèççW\\<22"‘H0L\\܃BCCM&S}}}WW‹ÅJLL ÓjµÉÉÉÉÉÉ333‚$&&&%%ênn.‰D‹ë¢¢¢ÁÁÁÌÌÌ•••òòò„„¥RéïïÚ××wüøñŽŽŽÔÔTƒÁ\^^þàÁƒèèh U\\ (»¸¸„‡‡§§§ßºuËËËËÑÑ177wnnŽH$†……%&&úùù---•––ÆÅÅ;((H(zyy-//WWWÃL‘ ‰üýýÁS£²²8Ʊ±±`ÁÂd2ÿùŸÿyzz:!!a``àÀ*•*::Úd2½ýöÛŸ}öYmmm^^Þîî®Z­.((€ñ‚,ttt4¨~ÌÎΞ9sF*•¦§§ûøø$$$ íšDÙÙÙ[[[f³yxx˜ÅbÙl¶ÕÕU0Ìimm%‘HËËË"‘èÊ•+÷îÝñ.›Í&‘Hø|>µAÂh~~>&&žH"‘¨V«ssswwwÑhôââ"‡ÃyðàZ­žžžNOOwqqÙÙÙ±öövAÖÖÖ ÅS©T Æßß´k Âîî.¼æçç“’’ èìèèØ××ÇçóÛÛÛÕj5LŠÉÉÉ*•jqq1;;›Á`´¶¶Âœ*‹kkkQ(TJJÊ… ¶··===Y,VmmmBB•J}ùå—‘¦V«ççç322€3‚B¡>|ÜÙÙÙÕÕ• R©$ÉÑ£G]]]Åb1‰DÒëõiii6›mssS¥R¡Ñ¾Ô÷îÝËÊÊ2 ,ëèÑ£QQQR©Aõõõøøx6›Íf³8¯Pä mii™ŸŸOII‰‹‹ «››(öîïïÃ+eccC«Õúøø€äƒY\\ ÜÚÚÚÝÝ €_‘H„ÔEllìèèhyyùòò2ǃñÆììlµZ]WW7??âççg±X„B¡V«…ñjµZ0Càñx4í¥—^ @`³Ù|>ÿϱ+*•:33Ãd2ß~ûm°õöòò²Ùl}}}F£qvvö¿øHyzz*Š’’???0°X[[3ccc‰¤  ’öÀÆãñÛÛÛ‹´“Éd²V«-//çwÀ«\&“‰Åb‹ Š·ÞzkccÃÇÇG"‘€V ¸ÖìïïonnFFF È"CÏét:H⤥¥Ƥ¤¤””×ÕÕe2™–––ººº †X,Ѱ^xÒà"z5†ÉdÂ<½ººŠF£çææ@$§¢¢^p ©Tª\.G¡P999€J¥=ztuu•B¡€.ÜäädMMÍÆÆJ¬V«¿¿?—˵‹VÂñ€4Dd||¼¨¨Èd2=|øm+++ ÆÑÑQ&“® @N`¤b±X$‘Éä‘‘‘ššàVåææ¶··‡„„¸¸¸€ØâÆÆ†Z­®¨¨hoo÷öööôôìììÌÙúúzee¥L&C¡P{{{ŽŽŽ`ÞA ÍÕÕÕE¡PðxüÐГ“(oè?›ÍÞÚÚN7 z½¾¤¤¤¿¿ÿÑ£GR©ôÏ:IX,„H$‰D?1»¾9‚ D"êáx‰„Ãáðx<ÞAÎ Fƒƒƒ|‘B¡€ …ˆ 4„Á`àé´£nì Óƒa0@¥rttD¡PŽŽŽv‚ 8T*•H$b±XH¾ÂŒ ÷P%Ѓqrr‚‘gÿ9…-<^ÐŒ "öh‡ÃÙ;t(ŠN§Ã…²71»TÔè!F{öRÛ¢Ñh0R;b :÷ûÙ† d2€+t:P²Ï^jh9t:Á`°X,ûõ±×~Á‘ÿSLË~ga¼( pç‚@=‹…n€bb=—À±×Ùöh–=ÿ³ˆ½¾ø,àé¹>÷çsá±Ï'”žK4=×З}ÑÞçFdG’=×±gf_Ö“çêŸàWôä Ïóµåï1·†ýÞ÷¾g6›‡††JKKÏž=ëêêúïÿþïo¾ùfQQ‘Íf[ZZòõõíïï÷óó3 wîÜùÙÏ~ÖÙÙ¹¿¿2:: þMüñ믿¾··÷øñ㘘Èx»¸¸455“H¤÷ßÿ­·Þª©©9}ú4(Òœù$55šX,V[[[aa!™L~çwÞ|óÍÓ§OWTT¸ºº>|ø°¨¨FÿÇüÇO~ò“7Þx#33“Ë厌Œ0Œ¤¤¤ÿú¯ÿ"‰¥¥¥çÏŸÿáxâĉþð‡Ÿ~úimm­Åbiii‰‹‹suu¿ªÛ·oCr÷_þå_Þxãúúz³Ù|éÒ¥Ÿÿüçñññ©©©?ýéOWVVh4šJ¥ŠŒŒ55åëë›””ï¯ÖÖV€ëÜ¿‹Å‰D«†VWW®\¹2666??¿¿¿ýúõÕÕÕ–––k×®Q(”ááa±XL >üðÕ•µZýñÇS©TÐìG¡PÞÞÞ}ô¸«Îjoo/ …ruu«æææ‰‰‰¹¹¹¬¬,F3==½¸¸=‘Ëåccc ä«Õjß{ï=Psuumkkkii™ššC¤  @§Óéõú–––îîî•••ÀÀÀ>øÀÕÕÞSL&3 àƒ>HMMýàƒbccA5 A‡úÍÃ'æ¯,èññqûZÄÅÅÅÑÑ‘Ïç§¥¥I¥R°â¸{÷. ÕÑétçÎãr¹À~!A¼½½{zz CddäŸþô'www@ËI‰´½½m[Ã^O"‘\¹rÅjµ"F£¹¹¹?>((¨©©ikkk``@­V[,–°°0<yLAÔj5NÇb±ÞÞÞ~ø¡··wxxøÃ‡¹\nJJʳÐ.°xXÕææfttôèè(F …‚,--¹»»/--Ù‹@ FwþþøàƒÀY#<<|~~$œÂÂÂà¢F@®¯¯Ã’Èb±¸»»¯­­ýñã¼¼¼ÎÎN{ÇÀq)"""55Д°-E¤··÷Ñ£GÀöž™™¹páBssóââ"À£­Vë³î½ÿ› ¦°°°µµU©Tj4š………ÎÎN˜®RRRº»» …P(ÅÝÝ]àîõ÷÷÷ööÆÄÄ´´´ìîîªTªééiooïÉÉÉû÷ïÇÇÇß¹sÇjµr¹Ü;wîðùüùùy±X¬ÑhÖÖÖüüüÀ‡N§ËårP£ìè艈ˆhnnÉÙÙÙ¨¨¨7n´µµÖPh&''ù|þàà HÞ¾}ÖÂ]]]z½|S ! ‚ÄÁÁÁ‹‹‹£££YYYwïÞ¥ÑhdNÁÜP«Õ* ‰D" ?ýôS‹Åb6›ûûûµZíÆÆ†³³3‡Ã¹qã†Éd’Éd‰¤§§gnnnyyY£ÑÈåòÀÀÀÝÝÝ[·n±X¬™™©TªR© …¿¿ÿþþ~[[›Ùl^\\Üß߇ã?~<===66f4A_ÞìðÐøûûïîîvttLMMétºÙÙY sëÖ-¥R©×ë766ìú¨ß–oË7®`Ž=*‰p8>>îx …¢¡¡䪪ªär¹Á`8vìØòòrCCƒ‡‡‡N§«¯¯W*•’ÖétEEEZ­öÀ{{{Ç‹Å`0¹OOO??¿¢¢"©TZSS# !:.‘Hjkkårymm-ð m6[iiéÐÐPMM $@>ìéé‰Á`:d6›ãââçç竪ªÜÜÜvvvŽ=ªÓé"""€M&“:´¾¾~äȉÂ]Е••†† …âîî^TT~ÁÇ×étÅÅÅ@©ä¤$°¸>v옱Z­Öˆˆ°Þ8qâÄîîîÖÖVll,—Ë ‡\Pyy9xUTWW*©´´tee¥¤¤$66vmmíÅ_ìÊÊÊÜÜ\@Vê@ñ¨¨¨0J¥òøñã³³³555`G]WWg2™bbbÒÒÒÄbñáÇCCC1 Xi0™Ì¼¼<…BVr¹®›Í.--]]]5™L"‘4Ïfff>L¡Pœ«««Czüøñ‰‰ ‹•——g¯@ ÈÎÎ^^^>tèŸÏí1ƒÁ’ŸŸ/•J<èç燋ʼn¤¿¿´S@×¥¢¢¢··799¹¦¦Æh4Z,–‚‚P5ååå@d _[[c2™>>B¡Ðh4‚vkii©P(Šééiت/--‰Åâ„„pçsvvf2™‡ºÿ~zzzaaá½{÷òóóaF€ñ Îäz½><<<###//‡Ã544ØÇ ‚g ¯°—ÂÂB~JOOôèщ'P(THH:--íþýû‹Åf³) ³Ù Òç3?uêTQQŒF#ÄEGGG€˜©â{÷îa0˜½½=ÐÐа»»ëëë Äùêêj³ÙÌçóWWWAooïîî.ø‚‚tÑ©S§ Ñ{åÊOOO6›‘‘ÑÞÞÁñÝÝÝõõõ¤¤$•JÞ“ÓÓÓ·oßÎËˋř™™8N"‘$''³X¬ÁÁÁÇÐÝÝ=::šÃá¨Tªƒž;w®³³sbb¢   ±±”žAÒ£«««¼¼œÉd‚Žˆ´··(H$ªÙb±èõzxl6‰D²Ùl&“ 4é©©ÙÛÛóóó„‹ž••ÕÖÖvíÚµÚÚZ§¢R©ayyÙn›¸¼¼œ‘‘ÑØØ¸µµ•˜˜ˆ \¥¥¥‚‚‚¶¶¶êêjð¹\XXHKKc0{{{‹ìRÐh´Z­†rRRRww÷ƒ¦§§KJJ€YN$អÑhPÀ \[[ƒñòx¼ÉÉÉ¢¢"p–d2™•••V«µ¤¤„Çãyxx€"<‘HÜÙÙj ¨‹Q©Ô††Aööö L7??¿ááaA¼½½ð¤V«oß¾ Öccc©©©>eåùùù¼¼¼žžž¬¬¬¾¾>, zW>>>ýýýƒ¡¨¨h``àÂ… ¡··ÇÆîîîÅÅEPj0 :®  À`0,--edd¬¬¬üáØßß'‰]]]>>>CCC6› :ìš©©©’’pUc_PokjjŠŠŠ20_NMMÍÎκ¹¹=yòìXÀSiooJ¥FFFvww'$$ Ñè›7o–––J$™Lææævûöíëׯ“ÉäÇûûûÆÆÆMNN* '''xµmmm™L¦¨¨¨©©)0¸ò£^¯øðáÒÒ’V«€Ã­[·À¾V?ããã555ÛÛÛKKKÎÎÎb±\Uu:°y;;;ýýý²²²X,–V«mll$‰ð¢ìèè(,,éyvÿþ}Gxüø1Ç …·oßKœk×®•——‹Åb©Tš’’»¡¡¡®®.2™|÷îÝ”””ÍÍM 2MNN^¸pD"ݺu«§§‡ÃÙnvvvÄýýý>>>Z­ööíÛ………ÓÓÓ°Úiiia0φý¹<MF>öý|ý³T–ÏÿeåYÎñÖä« IDATÙñÏ5ôÅù¯éÀç¿øÕ=ÿŸ^¯îð×öð Ïö…gþ²+ð\‹_8Rpvýuï¹>ÁŸý“””d4!&¹¹¹i³ÙüüüÔjull,è#‚&,ØMqxŸˆD¢­­-ÐÄ(L¶±±±*•ÊÙÙ944,öœœœL&¬”]\\ÁÚÚZhh(ÇÛØØ[­P(ø|>ŠÀJÂ`0¸ººB¯%*Bàr¶³³Ãb±  )Ìf3hEEEùøøX,oooggg•JVD"Q Èåò€€‡£Óé„B¡B¡ R©`}}°C*•J(nmm cÞÞÞ:Îb±xxx`±XpúóðððññY__ #“Ét:xi "111žžžƒ!""¤áÍ"¼¼¼@Ân …Buˆ]#î“P(tpp€—ò³åkã_v€ÍfÛßßÎæÄ~ðW|ë øÂ?1<T¦^xá…ööv‘HôOÿôOÎÎΕ••€² ÁãñQQQëëë }†¸¥Ñháµ²²²¤¤$:N&““’’€mL£Ñ|||òóó?~üýïÿöíÛååå°õ8tèD"ñððpwwÏÏÏ ÃÄÊÊJFS(”¢¢¢'Ožüñä…H$²Z­`ÐèááÇãcbb\]]½¼¼ 2¯¼òJKK ···CBBòòò¶¶¶p8ðõˆD¢››ŸÏOII>uêÔãÇ¿óïh4šÐÐÐ’’//¯………šššÙÙÙ#GŽètºÈÈÈ………’’’©©©¼¼¼²²²Ç¿òÊ+÷ïßå•W( ‹ÅŠïëëƒø0(×CÿàÁƒ===¯¼òJ[[@¸råJGG‡Édª©©éíí5›Í`š*’’’&''ýüü¶··CCC©T*˜àutt|õcô¿ª Y,–Ùl–J¥°*/))Y[[[\\} äk4š¹¹9xÆår¹}û­R©Äb1h‡òx< £Õj“’’vww[[[a&˜››£Óé\EäòåËþþþccc2™¬¤¤ü,!Å‘˜˜¸»»»²²’m2™|}}¹\nuuµT*¥P(ÐWWWÐ2›ÍÉÉÉ»»»íííáááJ¥’Ãá\»v ìé@ PD cxxì™._¾044ÔßßïêêªÑhÀFšJ¥Žyxxàp8777µZ½´´„ ÈÖÖ–¿¿¿³³³^¯Ôepp0ˆnÄd2ñx¼€€€ååe­V«×ëÃÂÂþô§?ét:çèèH¥RïÞ½ r‚?~|||p}}}»»»¡¡¡ï½÷ž««+ì§€)þÞ{ïeff¾÷Þ{°½’zuuõ_é¿õ·-hô3~qadd„Éd¦¤¤€œPUUÕâââ³^g°âp8}}}@ìAÄÅÅeqqÑjµzzzöööº¸¸ÔÖÖÎÌÌx{{'&&‚yêÔ)NÖ•pKž²:ÞÞÞK¬|@£Ñ^^^°%ööö9€Uyxx@RÌÇÇàJd2…B¹»»;;;ƒ, ¼¼¼`_ ÏœŸÁ`¸¹¹Á» º@žÔ)  éX8‚ D": ¹¹¹r:ØCØ÷Úû Øÿ!ÂápX,4D"‘žíè5€l¹ÁnÎÍÍ pT †B¡ðx<„Ù‘[Ð4Äd2AêŒéÿ:;;'…J¥ÂªÖÞCÐc!“ÉÏ-“ÜÜÜ@‘À^ ×üïOðËöD_»·²OB_¸5@žÙ;·©ù|¾¬c_Ö“çzîRØ[ùÚKýµýùj Ø×îs¿zß÷µx2{±×¾b_¹xñâÍ›79’““£Ñhö÷÷ó›ßÌÍÍ>þá‡vuu½öÚk,kooïg?û …JOOÏÍÍÝÞÞ~íµ×‚‚‚”JåÏ~ö30œ®¨¨æÌ /¼ Õj_{í5X€×ÔÔ(•ʬ¬,Hh¼þúë±±±h4º¦¦†Íf§¤¤äçç †ï~÷»ñññz½þèÑ£|>?222''gww÷;ßùN^^xq§§§ûûû˜ÍæÊÊJooïÙÙÙäääÊÊJ'''è@FFFPPÐæææÏþs&“9>>þꫯ’H¤ÂÂÂÌÌL½^ÿï|'&&Æb±ÔÕÕùùù±ÙìÚÚÚ¾¾¾ú§JMMåÈæææ“'O_èìÙ³ ¹,ûÚk¯µµµÑh´÷Þ{obbâÔ©S ÂÁ`0rssóóówvvNž< Ú§ÕÕÕ',,¬¡¡ƒÁœ8q"%%E"‘¼ûî»7nÜ8~üxAAÁÎÎÎ?þã?ÍæèÑ£@vÊÏÏ7f³9++kccãÝwßœœ<}ú4nÕ×׫ÕêcÇŽegg¯­­ýô§?e2™ ¿’˜˜©P(¾ÿý罹¦‚¯G@@€¯¯ï¡C‡¡C‡²³³Ñsss‚øùù]¾|9>>¾¾¾^¯×¯®®^¼xÑÁÁ!>>¦ö•H$SSSW¯^E£Ñ`ßE úúú\]] …zúô)¸Ê_¿~}gg§­­í7¿ùÍfûó$H=‰Äåra;vôèÑ>ú(!!tj¼½½ÝÝݽ¼¼€ÚÁãñnܸÁáp°X,™LÆãñ&“ 2S‚@ÎçÁƒ‡D"988øûû_»v px<>$$D,äú»ßýN œ?žÏç †Ï>ûL§Óáp¸ÿüÏÿ òòòºyó&Ç‹ŠŠ÷À?þñ<O¯×wtt$''Cÿõz=…BÁb±@ù —ÉdêèèÀYxxøµk× †Ífstt„õ»B¡ÈÌÌD¡Pááá(ÊÑÑQ«Õ.//onnVUU988„……EEE=yò<>çççýüü>øàôôtA éK¡P†††@<ÍÏÏobbˆ‚@ä ÇÛµàÏ;·O?ý0·°x…ÿB€ÆÍÍM$©T*À6ºººB”J¥J¥2&&¦­­M.—»¹¹µµµAº÷ÓO?}úôéää¤\.÷ðð¸ÿ>H¥­¬¬¤§§ß¿cc·l6[.—CòG&“yxxP©Ô[·nÚ{zz:,,ìöíÛ›››‹e~~¾££cyy<ÏÆÆÆärylll[[Nwtt¼qã†ÏÌÌ d”ïÞ½«×ë×××e2™»»;èà™Íæåå娨( ZvÛÛÛ7oÞLOOïêê‰DCCCÛÛÛ³³³2™lmmÍÝÝJ¥®¬¬$&&677ƒ tww7Œ2r+++»»»AAAþþþT*U*•&''ß¿_¥R)•Jp¢°oS¾-ß–ÿËó½ï}¯¯¯O ,--B„½¶¶F3™ÌÒÒRN÷ÿ´÷æamgÞÿÑŽ6„‹„„„@,fß÷͈Ý6Øx‰í8qâ4i’6igúΤ3WṲ̂K¦í´M[O´®c;66ì˜}cfǬ’h—ôþq·ºòºãÎLßù]ýuÞ>ø²ÎyÎsŽtžç¾¿÷ç››››™™i2™¤R)Hx«ªª´ZmJJJ`` Íf«¨¨HII1›Íµµµ£££™™™yyyr¹¼¾¾^¯×c±Øúúz»ÝÎçóKKKWWW+**@$tîÜ9ˆcI¥RÇÇÇ/--=zÞ,ÙÙÙ·IMMµX,%%%IIIpƱ±1àÖ-..‰Ä¢¢"ðÄ õòòÊËË[YY©©©…Ù‰'œNg`` ø VUUa0“Étüøq€úô¬¬,°µNLL8 ¤ŒÒÓÓ ÅÉ“'777ýýý«««µZmBBBjjêÊÊ  ðív{CCƒÕj -..^[[«¬¬‹Å‚J$6›‘‘A¥RÇíüùób±X.—»-UBUUUff&”›þYŽÿ›ö»j»ÊÊJ(˜000..ÎÏÏ/66–Íf ‚••ƒÁàééùòË/C¡Î_JÃ*•J—Ë533sôèч–——ët:˜…)ŠŒŒ ƒ1:: Ðl4ít:wwwgffêëë?~l·ÛI@  )ì¿3g΀5!@‚»ºº¦¦¦NŸ>½··ι;;;€¯YYYÉÉÉñôôœœœ""B§Ó9sfssÓf³½õÖ[Ÿþ9Ç«««[YY9zô¨R©ŒŽŽÎÈÈX[[+)) 5›Íb±øÒ¥KƒƒƒÑÑÑ)))SSS·nÝjll”H$ÿëý/´F£™šš¢R©ýýý"‘¨ªªÊ ýÙÏ~¥;h4¦™0…_XXðöö¾qãÆ“'Oìv;“ÉŒ×ëõkkk~~~—/_«ðGAº&""‡ÃUUU …B¡PXZZªP(@> ¬‹Åk2™jjjÖÖÖ´Z­ÏÏþóééi*•ÚÔÔ„Åb9ŽÑh„ò뀀€žž›ÍfµZ››k±Xèt:¨¶­V«Éd²Z­wïÞíéé!‰ œv8ÎáÇ!¼nµZŸ>} %™Læp8,‹§§'‡Ãyøð!—Ë…¹@µ¸H$¢R©eee@"‘ˆÅbè …Òëõ™™™W®\ñöö^ZZuž×ÔÔxzzöõõ±ÙìÝÝݾ¾¾••PÅ„††úúúæååáp¸€€ˆ°Àï ‹‡¡Fdgg'''§¿¿|€wŸ¿µµt(p'œ…2,—˵³³ö/h4\'år¹Ëåjoo7 ¯„–––f-@é0™LIII³³³PBÙÙÙùŤ ´‰‰‰……¥Ryøðá¹¹9‰tçÎ›ÍæÖ¯¬¬0L.—«T*//¯õõu§Óypp°°°àéé ˶µµ¥Óé …V«ƒäääµµµääd™Læ>ãêêêöö6‡Ã±X, \.îÄVH„ ZP(Áûd}}ÝÓÓsccÃápÉäÝÝ]j6@ V«Õj5‘H ÐjµF£ˆ•$Éf³ †ååeX̺½õ‰ŒŒ\ZZrwzE£Ñ^zé%ò­®®r¹\˜®˜Ífˆ'À§¸\."‹§§§D"Ù+` àOØØXö!âÆV“ÀZ‚Àbªð&†‡O"‘°X,4ãååE¡Pâââ¾ÎGpx¯ê‹€²8Aág/22’Íf{xxH$"‘èïï¦ -ã@y‡?iWÊáp °1&&ö„3B° ‡ÃÅÅÅÑh4м“H$¡P(ü |n/ år¹p"OOO0’a0!!!B¡†‚Á`ÀPÃUÃìžÁ``0jø‡U“É$‰Ð`‰¡P(‘HÄáp`DGGc0¡PCŠÇãétº{¨…B!LàC¥R!œ¿ý</,, ƒÁDFFÂ0Às_/œŽB¡˜* P(‹ÂÃá•ßèÕBÿî?ÿpûŸüÁçm^1ÌóÚxÞgzø¼þà ù·ÿ'uWBûË]Nb¾úÕ¯‡……•””Øíö¢¢¢3gÎèõú“'OŠD"__ßêêjWVV»±±qñâEXBBx°´´´¸¸x~~žËåž;wîàààøñã`"õÝï~÷ñãǯ¿þzFF†Á`8yò$‹ÅšŸŸÿÁ~0==}äȘS×ÕÕñx<‹URR"—Ëßzë­¨¨(NwöìÙèèèÑÑÑwÞyà §®®Ç×ÕÕ‘Éä>ø`nnî•W^‰ŠŠzôèQCCè±  ÅÙ³g}}}±XìéÓ§fffÜËÉÉ@PP™L~ñÅ›ø­o} *ǃƒƒaÑh4ï¿ÿþÔÔÔÅ‹“’’¨Tjuu5‡+---**R*•çÏŸOOO7 §NpVV–F£©­­=wîœB¡xûí·1Ìâââw¾ó€‘ˆc}ðÁ111€fq:x<Þétž9sF,ƒ?ÈŸû9ù/7ôoû[&“uýúu¼ÌÍÍét:"‘Èb±Z[[ CKK D D"¬º“““¯^½š˜˜ØÖÖF"‘<==«««‰Dâƒètzqq1‹År:—/_&‰ Ì›Í6à¯yíÚµ°°°ÂÂB4íééÉf³Ñh´J¥‚b‡èèè°°0 uûöm¹\¾ºº ¥ÉÉÉÎÎN//¯²²2ooo@ —ËAp’àããÔÚÚZTT$‘H||| ¯\¹••ˆÃá._¾ŒF£³³³oݺ% ݤ#GŽH$±XüøñãÈÈÈÄÄDP/ ßh4ööö뻽½=!!ÅbA`½££¤ #//‹ÅÚíö;wîl ‡Ã¹\®´´4‡Çã‰Dâ?ýÓ?ò aAAAÿøÿXVVöÞ{ï•••¥§§.Ϙÿÿ¼¡ÏŸ?ùòe§Ó U999B¡pppæI0=¼qãÀÓGFF`®C$!¸²´´z¨&(++kjjÊÈÈ€™Yyyycc#ø2"RPP€ ˆD")))ioo‡í.—Ëh4~þùç%%%×®]s8 Õ„ß§Ó)‘H@M£Ñ"""ètz^^^{{{rr2•J5›Íƒd–N§ôUF£qnnÎËË 8œ.—˽C~~>›!Iò):.‹@2f” IDATwppàv”ôöö†¥«Óé¼~ý:À¨q8ÜØØXhh¨Óé´Z­h4º®®îêÕ«ûûûÅÅÅ¥¥¥mmmjµúûßÿ~fffqq±Ëå’H$f³ø‚¨Tªæææ¨¨(™L¶´´ü…­­-…BÇã%‰»(á/¢aÄb1‘Hœ˜˜HNN¾{÷.‡ƒÕP||üÄÄÄÆÆ†ÅbÙØØˆŽŽÀ_TTÔââbOOäì¸\.™L¾qãÆƒT*ÔÏ Ñè_üâJ¥rrr2)) D………¿þõ¯···=zD&“gffVVV êP&“Ó&È?úÍ•+W–——§¦¦P(”\.Ÿ››ëééQ*•D"”¥—/_V©Tb±xppðÖ­[“““‹‹‹›››t:Ýd2ݸqãðáÃÝÝÝŸ|òÉÖÖÖèèhFF‹íëëš\.ÇápÓÓÓ@ ›››ƒ£L&ËÎξ{÷î§Ÿ~ªV«¡ŸOŸ>ó„»wïZ,‹ÕÕÕ•’’"—Ëm6Dã@PuçÎ,;33ãr¹ÊËË®\¹²±±166¨ià­ &“ÙÑÑÑÕÕ¥V«§§§•J%$‹ÚÚÚ Pǽ$ÿkûkû·a.\¸066^\\¬V«KKKÚTRRB$E"QZZFƒ²ñÝÝÝêêj2™l±Xæ$‘HRSSFcqqq\\Üüü|XX•Jˆˆ …r¹\*•Býç±cÇe“œœ 9ÿÒÒÒ­­­#GŽ@%jRRÒüü|yy9@Ο‹‹‹ EXXÈ¡€ƒe±X*++÷ööÄbqZZðE322€&%“ÉÒÒÒ²³³•Jenn.—Ë]^^æóù±±±)))8.888&&F¥RÕÖÖÚív‹UXX¸¶¶f·ÛKJJÔj5Ä@‘ðþýý}°Hq¹\G‡ÒûŠŠ ·¿¿ôèQ0¿€ÅA||¼X, OXXOHHXXXHIIšÞúúz ZK¥R¥R™œœ 8‚ÊÊJooo<_TT455•ššš––C°¼¼ 7…ÏçC` ‰¡œÄn·:t(99‹Å¦¦¦J$`º ‚ÌÌ̈ˆˆƒƒƒ’’’ôôô¸¸8…BQSSC¡P<<>^SSWJ CC$•J‹ŠŠÀ‘ ¶¶¼ ¡èª‰ H•Íf‡††ªT*__ߥ¥¥¬¬¬¼¼<@,—Ë 777aÊH$=<<"""àÛB"‘Þx㨨(fµZÃÂÂ@‡œœ¬×ë+**º»»a¨¡Çét‡gvvªcžvìØðð0Ç›ŸŸŠÁÎÎ8| rpp`4'&&rrrôz}oo¯X,ÞØØ¨©©1™L6› îVGGÇÐÐV«u¹\ûûû«««¡¡¡x<^§Ó† ä6›í_ÿõ_•Jewww}}ýÆÆ†Óé„q²ŸÏ˜Ìòò²Á`\YYa2™Ä¾¾¾P®c±X”JåǬR©@ö6›=22D"‘ÚÛÛÛÛÛ¡šE.—»aËËËJ¥òÑ£G‹‹‹&“ixxø§?ýéÖÖ–Ífƒg=//ÏËËK¯×³Ù쥥%¨?3™LP3:: ÔZ2™üÒK/W 9,‹Ëå.,,ÀôÜh4ÚívHöííí,ô`¾U[[ uç&“ ;ðY™/}éKú-((Ðjµî¡~å•W@Ú`±XÅðõõüDHHˆÝnÏÉÉyðà‚ (Êd2-,,ÀPmm­^¯ªŠÙl^]]ÕëõCCCöÙÞÞ†Çq=‚î9__ß••w÷.^¼h0üýýò“Ÿü~¼ÏÐ’à+õ‡“2, Û^€ú½SÈs'q „Ÿ‡²xž%"t²1_<‘»ÐÜ;<ïÈî<ÓÐh4äÜòÇãnàìòG®È½ÝÝWéå¦f<3ÔîíÏ\évày홎Až©Üwwï™n|qÀÝv8_¼Þ?2PÿÇIÙl6‚ L&[­V???OOO«Õ oÈ:F:áA Ñ›Ívpp@¥Rív;€ Cg0Èd2“É4L&À“~~~‹F ƒð €âp8»ÝÊ!»Ý¿Ì s8$‰F£™L&È<îÛd2ÉÝh4úúú‚# $‡¿¿?·J___PlÂ*tc Æ×××h4º\.///‹Åâëë‹Çãm6[@@€Ífóôô„ ;/,ƒÁ@¥R¯èëëK¡PL&ÎäA—ËE£ÑètºÕjý"’ŠH$2ŒƒƒwÉ!4z#ò ¿ÊÝ@ÖöGn*Dó¿x@—ËsžgŽóïžî™¿¸Oç>ìó:öņ­¯¯¿wï@8uêÔßüÍßH$’ªªªÛ·o‹Åb‰tóæÍW^yåÒ¥K_ûÚ×l6Û¿üË¿dffJ$’‘‘‹uÿþýƒƒƒË—/¿þúë§OŸÆáp?ùÉOþþïÿþܹs_þò—÷÷÷?~œ˜˜Èáp:;;!Bít:¡ØáìÙ³~~~W¯^•H$~~~0u»wï^AAÅbyòäIii)‘H\ZZb2™€õöö¾ÿ~ll,‡Ã™DP?ŒŒ@ï~õ«ÄÄD(Þ—Ëå&“éÔ©Sl6»¹¹9""äoZ­v~~|ïÞ½›:54ýôéÓÙÙÙïÿûo¿ýv]]]KK —ËK•””6›ÝÒÒï¬?þøßøÆÙ³g¿ò•¯˜Íæžž:.•J¿üå/¿ùæ›ËËËW¯^¥Óé.—K§Ó½óÎ;###çÊ•+`*†Åbëêêinnþb¹Îÿ˜†v:2™L¯×›Íæ………ŽŽŽÕÕÕàà`‡Ã133“køEñöö‹Å€€¢R©©©©õõõ à†_,¹\¾¶¶†ÇãÑhtoo¯¿¿OO…B ojjòññ çp8÷îÝóòò’Édãããkkk@ ìëës:f³™Ïç9—D"ñùüÛ·oûûû¯¬¬ÌÎΦ¹¹9$$Äáp s¹\¨ Ÿ¥R©?ýéOE"ŸÏçñxííí0ˆˆ°Z­4­µµ5<<üÃ?4 •¦,¬Ž=º¼¼B$óóó!ä’’„´   ÑÑQ»Ý®R©är9„ìy<žB¡P«ÕP –`(ê7Þ¸té‚ 8ŽÏç‰Ä‹/¾ýöÛ/½ôÒ;ï¼SÐŒ„‡‡ÿ™Ÿ…ÿÖ††Eû훞žþøñã°°°¦¦&"‘/W𜜜‹ÅZ­¤½sss¡¡¡F£ÑÏÏ/%%åÑ£GV«Þ¾ ¨µX,`wwW¥RÁ¹¹¹999 Õ·§N Œááa··Jhhhkk+ßÝÝ ÊÌÌ|òä hx¬V«V«ŒŒT*•pϰX,T¬qssŠŒÃ °ìêÕ« ÃjµFDD(Н}ík`ÊÒØØH&“®_¿f­h4zee…B¡(•ÊÙÙYw…ŒR© ÂãñP)ööö   ”””ññqpé q¹\W®\¹zõ*‚ f³¹©©‰Á`\¿~ýòåËׯ_ÿÅ/~¡P(Ü—<99 Õÿ9-33t˜ðÕÈ8‡Ê>÷öððpˆ¾@B”H$æää DHÉÉÉÀNýÙl6pâââ"##á€^¼D"‰‰‰ñööÎÈȈe2™999ÀŸðññÁápAAA^^^999d29$$$)) Ç'''S(”¬¬, …Âår“’’°XlRR¨4¡ÛL&3;;ÇÇÆÆ‚pnn®ŸŸŸOVV‹MKKËÈÈðòò‚´´Onn.¼+았˜(@{ ,4àV2!Âçó!;#‚ ùÿâ ‹D¢ôôtgwc0pÉÿßßä?G{žêèO8Âò8ÿIÙÓxÀ?yûŸ¬<{^ûOöäOáÿð¼ÿ½'ú¯ì¿Û0ï¾û®¿¿?T.ììì?~ˆ~gÏže±XAAAR©”Ëå‚Uú… ˆD¢@ J¥áááÁÁÁ‰‰‰ …âwÞàìÉ“'AÆYYYÉ`0ÒÓÓ!ÃP[[K"‘âââ¤RéæææÅ‹SSSÁAXååår¹üÕW_}òä‰D"ÉËËóõõ=räˆÍf«¬¬LKK[]]}÷Ýw!ÄròäIFS]]]XX²*‘H„ ȉ'ètzjjjnnîÖÖÖùóçSSSwwwOŸ> L[©TªR©Nž< z¨%‘H§Nêëë{ýõ׳³³···/\¸B§Ó;vppP\\\PP!111F£ñí·ßnkk{á…ŠŠŠärù¥K—Àœì7Þp¹\!!!KKKà—ŒÅbÏ;Çáp‚ƒƒS°¹¹ùõ¯]­VWVV‚{ï™3g@›ÿo|caaáÂ… B¡B¡=zÔápH¥Ò´´4¥RyîÜ9(?{öìÞÞXžètºšššcÇŽéõú'Ng Üß|óÍŒŒ ¹\þî»ï„§OŸB²¨¡¡¡¯¯ï•W^ÉÉÉ늈ˆðòò‚ë-++ËË˃⎀€‰ÔÐЀÇãsss³²² úòË/ommýÝßýÝÇ«««ËËËI$RuuuFFÚétòx¼±±±ééip.»òðáÄ„„û÷ïÆŽŽŽÐÐP°– “É:4 àÙÊf³!(çr¹|}}oݺ–|---`•qëÖ­ôôôááá§OŸ‚¥F|A¨1²ÙlX,¶ºº‚œ‚„††‚ZœJ¥ÎÌ̉ÄââbA<<<ཷ²²²¹¹977ÇãñD"¨q>ýôS//¯Çƒ)Ífc±X ‰Æ`0<oxxÞJt:‚ô÷÷ïïï'‘HX,v``€ËåÎÎÎB˜¾Nadd„J¥BeŽÉd‚+Âb±]]]t:}ÿ7¿ù ŸÏ¿{÷®Ífëêꪯ¯åãÌÌLOOÏàà ÌP«ªª8NRR,J ®]»–žž.‰‡^¯¿víšOQQ&‘H%%%( Èæçç ¬'ººº P~ãÆ 2™Ìf³©TªÉdòññbwðùmjj‚EÒÐÐǃëõóóøŒ¯¯¯¿¿¿Ùl’|3A ÔÐЊNȲܺuËn·÷õõuuu ÇÇÇ©T*Žˆˆ€ˆÅ;wFC$étúÎÎÎÕ«W-K``àÐÐСC‡ f}}]¥R­®®ÆÆÆþèG?ŠŠŠããã€ßÔjµ6›­¨¨¨££ãêÕ«………ÀÍ Z^^ÖétƒÁ××jí­V냪««?ùä,{ìØ12™Éåre2™‡‡Ç“'OâââÜ1»Ý. X,vyyykk‹@ ÀØaikkëÈÈHjjjffæýû÷©T*°n===ÁÞ~±ù|þää¤{™B¥RB½°°€Ãáe2™¿¿?@€¥Á`€êY—Ë ÀÅÅE€Ñ#²¾¾þᇖ”” †®®®ŠŠ 8‘N§{ñÅùË_N ÇÇÇÇs8œ€€€´´´‘‘ØF£¸Ãá@€Ôétâp8§ÓyëÖ-¹\.‰JJJívûƒÊËË!P\\\\\ÜÑÑ!ÆÆÆ¾È#æÀööö|ŸŸ_XXøðáCø/—˶¸¸h±Xt:@Pe2ŸÏw¹\r¹œL&ÿð‡?”H$|>||œÉd655ÍÌÌœ8q‚Ï燆†Aooo›Í®¨6› SRRòäÉ¡PKn­V{pp ¤žžž§Ó¹ººš’’B¥R!êº(4½´´äááúðáÃÜÜ\…B1::7:: žJ¥ÒÏÏorr’L&Ãn‡²Z­Phª×ëgffŠŠŠ&&&ÆÆÆ ZZZ"##±XìÇÜÓÓUrýýý4M§Óý<Í%%%V«•N§÷÷÷ÕïííeeeÞK,. AF“››ûøñcOOO¡PØÑÑa2™ìv;˜ÂÏÎÎÎÏÏS©Ôééi˜û?|ø0** ¤`b±x``@$‰Ä‘‘‘¼¼¼ÕÕÕÉÉI*•:77&ÅÝÝÝM²Z­ƒƒƒOŸ>ÍÌÌljj‚ Èðx¼R©´X,óóóÍÍÍF£qtt”N§ÏÎÎB*öÉ“'÷îÝÕnffæâââàà`AAA{{{`` ›ÍMNNF£ÑÀ×Ëx04¤P(Ož<Ñëõ‰‰‰2™ jojjjœNçÆÆFYY™L&c2™½½½ð-ZXX¨ªªr8Z­6++kaaaffF,÷õõ!B"‘úûûᅼő‘:. ¯]»vûömƒÁ\»ùùyH|mnn–••A&ê¯í¯í¿¿aêêêÀ6(++kii)===<<\¡PÃH$%''‰D³²²’ŸŸÏd2ív{ii©R©4›Íéééjµº¤¤„@ 8ÎŠŠ ­V˜ššº¼¼œœœ ®vUUU€§‰DkkkyyyB¡P¥RUVVîïïs8@ eddDFF* ©TŠÇãA¼½½þi5¹úüü|\\\rròêêj^^¤M¤R)x´ddd(•J«Õš––¶³³S]]mµZwww¡.955U$)•Êòòr“ÉD£ÑJJJ h(\.W~~~hh(‹ÅJLL¤Ñh,+&&f}}½¨¨8õP JOO—Ëå Åh4VUU™L&6› B±üü|€ÎWWWh4š„„ i¹oCee%Èמ©› Ú_¢¥*üãâ⦧§###q8\||üîî®V«­­­½yó¦H$oœ03©««¬”Ífûæ7¿©P(ˆDbAAFÓëõYYYàß'‹óòòººº’’’(ÊôôôÞÞ^}}}wwwDDDzz:ŸÏmhhxøðaCCCgg§X,ŽŽŽÖëõ{{{555»»»ƒÔåÇÓÓ3>>~ppP£Ñ444´µµ]ºtÉf³ñx<ƒ‘=00P]]µ´´+ ÚÚÚ§OŸnmm?~|jjêW¿úÕ;w@„<99Y__¿··µ¬111x<^.—+•ʘ˜˜û÷ïCX+77ŒwÐhtZZ ìv»§§'H·333•J¥R©Ÿo·Û———!¹¸¸Èf³ù|~gg'Ô4?zôhvv688¯¼ò NßÚÚ¢ÓéÇ_[[ߎ   ³Ùœœœ ² µZÍápÂùóç!ýÚk¯íîîÂünee…ÅbK¥RoooNg·ÛN'///CýãÇãââL&Ó£G¨TªÁ`@£Ñ/^¬‹u¹\"‘ÈÃÃC£ÑX­Vpèóôô”Éd ¬¬,%%Ån·?}ú411±©©éµ×^óññ™ššÚÛÛ,..f2™### ¬ÝÛÛóððÈÊÊ‚µmDDÄÈÈüÚq¹Ü€‹FFFZ,@ /-- ¡P(“É€eªP(€::ع¹¹ØØØ{÷î]¼xqbbÂÇǃÁ|éK_JMMEص^^^/^ÌÍÍ}ùå—‹ŠŠŽ9 ‘¿D>Z X­V™Lf³Ùæææêëë÷÷÷ƒƒƒAìãã£Õj1 °¿———)ŠÙlž™™ihh˜››ôïþþþüüüôô´‡‡ˆ¢,Kiiiww·Ùlv:|>L­l6Têõú­­­ÉÉIØŽÃá AAAõõõd2lZNç7¾ñ “É,50}µÙl°h‚öøøx‰‰ F399éççG§ÓU*ÕÍ›7].Wlll^^žOcc#°q¾õ­o èÃäää‘#GvwwÁ¾kccƒÁ`ìîîzzzêõúýý}€“·¶¶¦§§Ã”ÿ!Ò`0LOOÏÌÌ€U|g¬VëÂÂ(õ¢¢¢JJJ FssóÞÞ`gëêêZ[[±Ûí |á…>ýôÓóçÏ_¿~ýÆ@³>Ö_X®ªÚÑh4¨m0 ¨sž ³¢Ñhˆ²@‚ùÑ;5ù¢šøLîÂ}¢?ÜîÖ}±‡î-î¸7BOܲ!wÜüâÇ¿øOØâî€{(þ]…™{p8œöwwÀ}ÔïùaÏŒÀ‰\»;ó?¦ýn° >b·Œë‹r3÷v»Ý$10ÒÁãñP®‰ú= |oÜûƒ¨Ž÷êø`b[€X¬‡ÃGóðð€ûDP™÷ FÌ > §ƒ=á°ny€æAFÛ!!H àQp÷¹L&?s"x€ÜûÃ#ŽF£!Ò[P(•J…§ ûû„þ£P(˜Q€‚»c`˜Z.Ø,wßkÁxA )À‰àƒp@ÅÃ_p8$^±X,œùýwv" \/ü/…B~€; Ý€+…£áp8 …Zp¸^w7~÷H|öÙgGu¹\wîÜyùå—¿þõ¯Ëd²_ýêWGŽáp8ÿüÏÿüñÇ¿ÿþûÕÕÕ$é»ßýnrrrbbâØØXppðúúztt4‚ ¿þõ¯_|ñÅO>ù„D"%''·´´;vÌétÞ¹s§¼¼ÜÛÛÀ=`ë%•J¿ùÍoJ¥ÒÇ_¾|922’B¡lnn²X¬±±±ùùù?üð+_ù øb±Ø€€€¦¦¦Ó§O“ÉäÆÆÆ‚‚"‘î+++‡R(ÝÝ݇ÊËËûì³ÏÙÈd2GgggYY …Œ–···Óélmm=wîœÃáøÍo~“––F¡Pž>}J£Ñ>|_\\|ûöíèèhPS‘ÉäéééÌÌL—ËuûöíââbpjŸs¦R©ÀñAîîn˜.--åää€Ë…Bùö·¿ýÃþ°¾¾¾¾¾‹ÅÞ½{÷½÷Þ“Éd+++111ÀÏñ÷÷¿{÷nyy¹——Wwwwll¬ËåúÎw¾óýïÿÎ;.—«©©éå—_îêêÚÙÙ‰ŒŒ4›Í`œÙÞÞ~áÂ:þÉ'Ÿœ:u ˆ³²²º»»+**=ztùò円†………ððpX«Q©Ô{÷îLxNçää$ŸÏ_]]…9_SSSvv6mdffÞ¾}ìÜoß¾][[ÛÕÕeµZ:FF£±©©éÝwßíééAOLL R[[»¶¶†F£Á’4 44Ôf³…$þö·¿­×ë=<<âââôz=Tâ+•JмêtºžžA`ÑŽ :ÎÛÛпt:4^}}}0³ljjX>¾ví„nëêêÀâÁ`0h%"" ¸óh ÿIDATâý÷ß7 sssÿöoÿS¹\. AJ “¼O>ù¤©©ixxX¥Rê8<<„ö ceeE(’H¤ÍÍM0Œ%‘HKKK Ð1<¯···¯¯ÏÃÃãþýûÀºY__ ÀŽ\.ÿ裴Zmkk«L&ÛÙÙ‰ˆˆàr¹©©©ž¡Õj½ÿ¾J¥jmmýæ7¿¹¿¿¿µµÐ"‰DB§ÓA@…BÆc )ýío ”^•J˜––f·ÛA¦ÛÛÛn±X‚ƒƒ;;;M& …‹Ål6ÛÛÛ»¹¹|+€þÚÚÚªÕj[ZZ‚ƒƒ1Œ··÷ÐÐÕjýîw¿ët:)ŠP(ÜÙÙ™ššŒ …ºyóæÂÂÂÖÖ¨Œäry?䬜N'üüü°˜””488Øß߯R©¢¢¢|}}£¢¢@oò»É ƒÁðòò‹ÅZ­lsÅb1dgÅbñ… º»»¬V«X,NLL „¶¶6 ¢R©†‡‡ù|þÏþs‰T#µZ}óæM«ÕúEóÙÂÂÂÞÞ^(EDû­[·à;B£ÑnÞ¼éãã–2‘‘‘gÏž@äâŋׯ_ÿøã!AîpkÇÆÆx<^^^^kkëG}D¡P¦¦¦š››­Vëµk×€fûãÿ˜J¥º\®õõu€[­V÷ôôDEE%''OLLììì`0˜>ú&ÚV«µ³³3$$äÒ¥KŸ~ú©H$JLLìêêÚÚÚc±X>>>P‰ù“ŸüÄÏÏ`T‚|õ«_½zõª{ ¥V«»ºº$I{{»F£T(z½~yy¹©© LVGGG!‡h2™À&üKX,–R©¼{÷.@‚··÷ÖÖÖððpJJ äÇ ™(‰ ÈçŸn4!! HppðÆÆÆââbss3étz@@@cc#Ž/­ÄÄÄþþþ¸¸8AL&“Z­þì³Ï /ÒØØ—ËZVVÖÒÒ¢T*{{{CCC¡,³½½½³³·r/J¥òÁƒ=š˜˜hkkƒl¬á»ºº&&&l6v¹\ÓÓÓ¡¿¿_«ÕªTªééi±X|÷î]??¿ÈGÎÌÌèt:‘Hôé§ŸZ,–íímF³··§P(vvv’’’Z[[×××ÃÃÃoܸÑÝÝ-“É ‘ÒÕÕÕßßÝØØˆàÖ2|Xâè¾··wgg@m.— h {{{}}}‡jiiÆÚoû[Ðòß½{×áplnn:tèóÏ?H$·oßÞÝÝÝØØX^^ êîîÆ`0t:ý³Ï>S«ÕX, ’ ©ìp8Boo/›Í¾~ý:Ÿ˜˜hoo‡¥x®Òh4ooïµµµ™™™˜˜˜[·nÁoÒÊÊJttô7àKçÎ4mµZ§§§Áÿg```lll|||ee‡Ãõôô€h`jj*!!¡©© R{¾¾¾333SSSïØßß—Ëåûûûpv 300Ti•Je2™"##oݺµ³³³··wïÞ=xŸÀE¡Pð¦êèèYXXˆ‹‹kll\ZZòöö?ÎååeF?~mmmŸ}ö™V«7Ý¿¶¿¶ÿþ†yóÍ7™L¦¼~üøñ˜˜p"ññña±Xµµµ½ù$:::&&ÆétB`†J¥VVV~þùç±±±7oÞ‚ ƒƒƒ!!!åååžÙßßg2™§N :|ø0L&222233q8ÜÐÐLf¯]»]]]m·Ûu:ݵk×ÀG¤®®N TUUÁ°òx<Ÿôôt˜Kòù|̓¼ Ð4F£yðàAll,8BMvXX˜N§›œœ‰D)))999D"ÑÏÏÇãUVV^½z8N§Ó`0‘ B²|>xxØËË‹N§3 NÇf³‡††BCC nܸ‘——£°°°ùùy>Ÿ/‰,KhhhEE…ÃáðññIHH@£ÑŸÐh4UUUàA¡PÞÿý¨¨(A`Â$‰þáþ!33ó½÷ÞKIIˆ}üå"üžiè‹/~ôÑGmmmà;¿··ú=/  …ÚÜÜ4›Í‡Úß߇p΃@5…B¡Àeäx÷ïß?uêTCCƒÝn‹Å€©Ðh4çÏŸÿå/i±XÚÚÚêëëKJJ>|XSSƒÅb£¢¢\.׃^zé%(A¦ÑhÝÝÝùùù¯¼òŠÉdŠ…í‚|ï{ßKOOßÛÛ«ªªºyó&‚ .—k||t°p.ooï3gÎX,–ÌÌL½^pp¡ õàÁƒ‡J¥RX¼öÚkàãêŠBƒÙÛÛƒÀl¿zõªV«»%A dˆN§ëtºééé’’’ÉÉI@Ìï{ß_'0Û1 f³æÑûûûCCC‰Äd2©T*£Ñh4¡‚™D"1™Ì_|ñ½ü_hÃ@‚ǧ¥¥}þùçL&s{{ûîÝ»³³³333ùùùP0Ãáp†††èØÛÛ+•J{{{³³³FãäääÍ›7m6[GGGUUUÿ‡~h³Ù=zTUU¥Ñh FC¶¿¹¹~„ÆÇÇá7ozzº¸¸øÞ½{6¹}ûv~~þÚÚÚ÷¾÷½ííí™™™ŒŒ <?44´g v@ŬP(lkkãr¹°ŒÊÊÊûðíV+d»õzýÍ›7=:::J"‘RRRZZZ …BùÑ~Ôß߯×ëX,ÖãÇÃÃÃ===ÇÇÇ> ÖŠEEEíííaaa7oÞLOOßÜÜœššŠŠŠš˜˜P©T dÃôôtuuõãÇWVV²³³›››u:]WW8xA2¾¿¿ÿ³Ï>ƒ/×;°r}üøñ_9XmmÏmÿB‚ž¾0íIEND®B`‚jas-2.5/images/device-2012-11-18-jas-trinks-out-thumb.png0000644000175000017500000014142412054221644022617 0ustar giovannigiovanni‰PNG  IHDRÈU%µ7àsBITÛáOà pHYsÄÄ•+ IDATxœì}y\[ǵÿèj—І$bˆ}ßw0Æ€lã½^ã%v¼7q’_š¦M>yi>ïµNÛ´~mö8Ië$Þãƒm°›}»Bûvœ<•‡—$¯v¤úþÁg4wæÌ™;ýsg¾ç„\pá1€8ó7‘ÈårM&“3'00Ðd2Ùl6„Fó÷÷ÿ—êè¿<Ïb±à8búHý=E¤ÒÌ£C¸Ýö}åfü–H$¡¡¡ƒƒƒµµµãååµvíZÇ ŽãçÏŸïêêz=pᇃtûömœH Ùùz°·HšWwèUM]%Bˆ“4›ÈâjÎq& 7­È65ŽQèdw‘©¿Kß\ƒ¦ËÍÎÎf±Xccc©©©ÎÌY³fùøø ‚¦¦¦é—\ø)L&{yyõööÂO"†mIv£þãÑ3yó…ï9=Á ‰'2X i™Í§ùûŒ‘ …ÿ×ÄR©T‰$22òôéÓÎL‹Åòì³Ïž={V©T~ùå—ƒƒƒ»‡.üëaX@@@ww·3Çñ«=ÃV»ã!µô­·„ó7˜‡T‘¡³Á=·”èÆ…KÿëU¨P(B2™lz‹åÍ7ß4›Í8ŽÿùÏnkk{”rᇀ€…Bã¸3Ç£J…zÜhž^ÌYÌø‘SïÓ|¤4o©U£¦zIô-߬ 3ÈÌÌ z÷Ýw94-::šÇã!„&&&ŒFãcèš O |>ŸËåšÍf„Fëîîvâü¥ áHSwÕ8¨üN‚ˆDd·?^]]ø7ðo/å‚ .¸à‚ ?YÌ\¼#„2V=‹ß/:ÆTm­W=•\ø)`æÎ;Bˆái²#„ #àÙß|aÒ)$“Å?°)ׇ¡ Ã}&–Ýj¶Û¡…i2_ÛTù Çq…´=VøÌéÎ)“!ä°Yþ媺ðcÂý&–Åì°£X^Úço£¡Á8î0È~~ãït?³zóoÉz“ÍñýO%]ø·ÂLvBÈ'v–7±SlÃûTg³ |>îæ†»»» Åg]jÔ h PöTÍfóÔÔ”SÈòåËgH&f.Ý­Vkrr2HÀ0,;;[, Ù][m?fÜgËn5Ç2,ŽQõعs#ÇŽž:5úõ×#ÇŽ=«mnfuµ h»ÕY~ÇŽSSSo¾ù¦P(äñxl6›Çãegg§¤¤Ðét Ã’’’„Babbâï~÷;*•*“É niii@@€SBdddvv6“Éüÿïÿý‹n€ ÷FtÔjcø©œ?ÿ·|³œ"ûúnÛÇ~õ…Èe›¯Úþ1±(Š———^¯¥ÓéZ­–ÃáŠD¢_þò—£££J¥rûöíü1‹ÅŠŠŠZ¼x±Á`¸råÊ¥K—fH°ÙlÁÁÁ$©¯¯ïñ÷݅Ljû>±L‹Ùd³½­4¬ßf!‘ÌÙ½½¯-Zÿuû°Ùf³ÚmÓŸX&“I¡PÐét€a¼ïÚÚÚŽ?. ƒ‚‚Ž9ÒÙÙi·Û{{{årùW_}uôèÑ„„„{%`vñâÅ_ýêWÓ¯ºðcÄý¿ ›ýɦëÖVÚ„‹7oÑ8n_·±²Qcw8&KJ[L¸cÚK§Óݹs§««Ë`0¬X±brròÂ… /¼ðBGGG__ßË/¿ìééÙÐÐðôÓO9rdçÎV«õí·ßF9Ç<==³³³Ùlöððð¿î¸ðpŸÐÈ’mÖÿY7oå…cC£óËèÏï¹³~OEû0€pM uõß.¿·.N·X,°îf³ÙZ­!Äb±ôz½Ãá`2™z½žJ¥bö Š<ð¦ó7\ø1âþk,»!„#D0"‚Ãn´(ÓY,£Ùl·~ÃΙþÄšŽéÓfBÈùµ¨×ëB@Ïx\Sê§ûL,›õë„ÁÅ•)›»s–·u Ø­ßl_¹ö±\x8î7±Ì'u`ȉÛͺéeÖ‡=u\pÁ\páÇ‚ä¹?=i\ø ‚pß\pÁH¤û|Þþñ“éÈOÄD‡F£=i ~2ù‰L,~hpM, \Ë…Ç‚ûP“<==½¼¼¤R©V«7Ïé…B±X™}…BINNær¹"‘H(Žûûûûûûëtº¨¨(³Ù,•JE"ÑÈÈÈ£jÔÙô£ê™LNNNžœœôõõT*5<<úB£ÑÂÃõZmtt´¿¿¿ÑhŒŽŽžœœ|„÷ð1nbmÞ¼9))I¥Rá8.‹ívûŽ;S[nnn:îÛË}7ˆÅâ7ß|óí·ßÞ¶m[MMV« ­¯¯OMMmmmµZ­ñññL&S¥R?~üƪ]ôH;²zõj__߉‰‰ˆˆˆ¡¡!ƒÁ€ã8ŸÏwwwoll´ÛíUUU©©©ííínnnŸþù#iý ^…¾¾¾F£‘Ãáü¸ø0nnn$Él6_¹rÅÏÏ!T__ßÓÓÃ`0®]»æp8(ŠX,~8èÉâÎ;6›-44´¯¯ïèÑ£‡C"‘ ß° ¤Ré‰' S—/_¶Ùlžžž°õÇø*d³Ùz½þðáÞžžv»½©©©¡¡á1µõh_…$I&“FƒÁ|øða"‘ØÞÞŽaØ… Ö¬YsãÆ¾¾¾Ï>ûÌÍÍíÑÒóaG¼¼¼BCC¯]»Æápärù;wNž<)úúú Å™3gnß¾M¡P0 Óëõ¡¡¡ÍÍͤéŸÜÜÜž´ ?™Ž¸¾ ]x,pM, \Ë…Ç×Ärá±€àž·äIëð k¼nQ»Œ§@ ÄŸîÒ:<tÿǶñÊSOZ‹Gü§A½$UyÒ:< ‚•OZ‰Gó ’êåÿ¤µpÁ\pÁ\pÁ\pÁ\pÁ\pÁ~ˆH*zÒ¸ðBb!úÆ£_X ú.ü3¸Ïl°Z­QQQ±±±===†mß¾]&“ X­V"‘h·Ûi4šÝn§P(»wﮪª‚•¼žh4Žã >à'™LÆqÞP³fÍêéé¡R©6›J¥B›ÍF"‘t:·Ùl …H$j4h {ã7âââZZZ Á®]»233[ZZL&“X,Þ¼yó¬Y³FFFººº"## JKK/\¸€Úºuklll```ss3BhÆ nnnR©4//¯®®î_w³ÿ@*,,”Ëå§NÊÍÍ=yòäðððöíÛ¹\n[[Û¯ýk£ÑréÒ%_üâF£ñ³Ï>›7ožB¡—H$¡ØØØââbÇ5ŸŸ_?Ì?»Ý?1 ëëë‹///ߺukhh(“ɬ¨¨Ø¶mÛ±cÇââ⪫«u:]UUÕæÍ›y<^EEÅúõëmµµµ}úé§!OOO£ÑèááK:‰DrôèQèÆÀÀÀ¥K—¼¼¼ZZZBwïÞõööV©TpU,¿ûî»O=õ¬ÿ$‰——@˜ñ€tás86›ÍjµêõúW^y!$‰N:%‰¼½½GGG[[[i4ÚÀÀÀøøxffæÄÄNïîînllD¥¦¦~ðÁ`C¥Rñx¼³gϺ»»;–——{{{Ó¬©©I$}ôÑGéééÝÝÝÝÝÝ4íæÍ›!___¸4½-Nïå±±±ŠŠŠììl‰D¥R?ýôSxMñG"‘ŸÏOJJª¨¨€—5…B‘H$„Ÿ*•ŠJ¥„ÁÁÁ'rÓÿ@ìêꪩ©Ñëõ ãÏþ3BˆJ¥B0 «Õ:>>®T*U*ÕØØ˜Íf¼páBHHÈ­[·|}}q¯ªª^¶l™P(üâ‹/ÜÝÝ›››{zzBuuuΟžžžV«Öà°‰päÈÇGGGýýý …··woo/B(//.9Û2‰¤½½=::"s„‡‡·´´¥R™ÐÞÞN&“M&SaaaGGG\\N—H$YYY7oÞ¤R©åååz½~ëÖ­555ãããcccwïÞ…‡Ÿ ?Dp8œÍ›7gdd<&ùnnnÓÃC>ü§@ ˜^÷á?]x| fff&%%MMMÅÆÆ*•Êû‚2V«Õùÿ½xñbXÍøùùåææ¶··‘Éäï`¶„BaNNŽB¡pww_¸p¡ÙlÖh4Ë–-‹ˆˆhjj¢R©D"1''‡F£ „ 0ŒøøøÌÌL©TÚÙÙ™“““””{c+W®”Éd½½½T*•ÏçGDDôõõeddÈåò¡¡!‘HTTT$àÉŠ*--…î „V¬X¨P(222î{Cœ}H$’   ïÞñ7lØpúôé 6 s8œyóæñxŸÏ`0¢¢¢ŠŠŠ ÅŠ+òòòªªªBK—.µÙl¥¥¥,‹Ë庻»^ºtéIå NŸ;wîÔÔTbbbPPеk×ÒÓÓ ®\¹"“ÉàT„ÉdŸ={¶°°ðïÿûÒ¥KB‘‘‘‹/LKKc³Ù"‘ˆÍf …ÂÅ‹9r$::!䔹yóf@ñóŸÿ<''G&“±X,*•:44Ûñ†©ÕjNÒÕÕÕÕÕ%“É&&&öîÝ;>>M"‘X,Ö­[·H$œC›L&‹Å¢Õjq‰DD"¶d2Yllì™3g4M@@ÀÙ³gŸyæ™Ó§OïÝ»wbb!”™™©T* >ùä“ââbØq}á…Ìf³D"ÉÈÈILLŒŽŽ.//_°`››ƒÁ ¾ñg }q8„Sç%˜Z­~ûí·)ŠÑh4›Í‹E¯×k4šùóç#„²³³BÃÃÃ~øá… ÔjõÊ•+ëêê ÃÙ³g©TêÔÔÔÑ£G››› ‚ÕjššÒëõÍÍÍeeel6;++Ëb±€Ìºº:…BñÁà8n2™._¾l2™ÔjµH$Úµk—ÝnoiiÙ¶m›ómåééi2™²²²B‹Çq£Ñ8{öì””xœäçç3™Lˆ“¶`Á‚}ûöÆââ⬬¬ššš¿üå/ƒ!++K«Õ9rD­Vß½{!”ŸŸO¡PNœ8ñþûï×ÖÖ®^½zxxX¯×_½z5!!áÒ¥K7oÞüÓŸþýf³yllÌÇÇ'***88ØÓÓÓ`0@_„BáÉ“'“““qÿqÍ{bHJJzíµ×¢¢¢î½ä\)oÙ²%""â¾Õy<Þž={î=Q™¢=$$dÖ¬YJ¥z{{C‘HD£Ñ¶nݺmÛ6±Xìãóí?<’’’B …@ @Ú©0”ñöövV™^}FÉ{UŠŠŠÚ´iÓýoBkÖ¬yóÍ7§?–œŠ‹‹TÑ…'ƒ±µ0 ûŽD®'Ž‹ž.¸à‚ .¸à‚ .ü„0ý“mÆçÛÃó¿û΃Ä:A&“Âëš^}zIgzF$í[ÕpáŸVPP@£Ñh4Zbb"‰D¢ÑhD"qçÎ$ Ã0&“ ó†L&3Œ]»vQ©T"‘ˆaؾ}ûž}öY™L¶gÏØ2%“Éd2™@ Éd …œ*`  &&&:ÓT*Ú‚¯*(?kÖ¬°°0ȇ IÈG1Œ;wBÔu"‘(‘HF£R©‰D$Í™3¶ â3Ï<#‘H<<<˜L&ì¾Iä „0 M˜L&†aÓ#“ÉÝa0D"qΜ9¡§Ÿ~zëÖ­³fÍz2#ö#iݺuáááV«Ã0.—ä÷]»vݽ{755µººº¼¼üù矇ÃW_}õwÞÿÛßþ¶uëVFsûöíääd„ÐöíÛ™LæÍ›7 BTTŸÏ¯ªªò÷÷çp8v»ýܹs±±±YYYv»ýÂ… K–,áp8o¾ù¦V«U«Õ;wîäóùÕÕÕT*õüã±cÇ€³àååÅçó?žíáá±oß¾®®®ÚÚZ???µZýòË/ÃV-Žã›6mºqãF__ßÒ¥KGGGi4šŸŸŸN§‹‹‹ƒ³?Ÿ††„ÐÖ­[Ùlv{{»L&›œœ äªU«:;;áL=66vttÔÓÓÓn·766®]»öâÅ‹~~~·nÝŠˆˆ8þü½0°¶¶¶¡¡¡sçÎq8&“Y^^ÎãñX,–X,g0𪬬¼{÷nOOÁ`IOO///g³Ùƒƒƒnnn! 4ïÞ½»¥¥ÅÍÍM"‘0™ÌsçΑH¤ãǃa¤ûûûzzzFGG™L&”G„îîîÀÀ@Fc±X ?%%å½÷Þ›šššœœLNNîîî¦ÓéT*µ¿¿4mnn¦ÓéSSS``È`0Ìf3—Ë=xð`||¼B¡HOO9!±XüÎ;ïDGGðÁ¾¾¾ œ2™Ìööv»Ý¢àFknn†ƒ„[·nÁŽ® ‘N§3Œ––Ç{{{ÕjµÃáèîî¾sçƒÁpwwïììôööS\\œÕjU*•D"6͇‡‡óòòjkk …V«mmm¹yó&E×××;Úl6­VÛßßßÝÝ=99éïœ\SSC$ ”¯««³Z­ÀÄjoo÷ððP*•G]¼xqggg}}½»»û7¨T*”èíí…S—ŽŽŽ__ß–––ÞÞ^•Je·ÛƒƒƒÉdòÍ›7ù|þ©S§Š‹‹;;;ž““süøñ TUU©Õêîîn»Ý. GGG;::¸\.Ü•Júóx

Ÿ?55E¡PÄbqff&,’–,Yrùòåyóæ…††Z,¹\žŸŸM&“‹ŠŠ¤Riaa¡B¡ˆŽŽ.,,ìééYµjÕ¬Y³FGG¸víZ(o³ÙÖ­[§×ëW®\i6› ¢££Õjõ–-[är9‹Å‚oX&“i³Ù6mÚ;00àááñú믷··ŽŽnÞ¼(V]]]t:}éÒ¥)))T*µ´´tlllýúõr¹üܹs999 .Ù°a‘HLJJr*&‘Höïß?44TZZJ RRR m6Ûo¼qôèÑ;v|ýõ×ÁÁÁ`#éÂ}555ÙíöëׯÇÅÅÉd²ÊÊÊÔÔT7gΰYpwwGEDD\¼xñîÝ»$I«ÕªT*¥RÙÝÝííí ¶Ñ‘‘‘ÙÙÙÐjµB¡°¨¨H&“]¿~=22²¼¼<===>>ÒóçÏg04­½½}hhÃ0(Â0ŒB¡dffÒéôœœÈ_ºtéáÇ CxxxiiéÀÀ|Ü1™L>Ÿ/‘HŒFcCCCdd¤H$²Ùl ,@ùûû“H¤¡¡¡¦¦¦M›6¹»»¿ôÒK !”ŸŸÿé§Ÿ®_¿þðáÃ………N%Ølvssóøø8ˆ‚K~~~ ‹å£>*,,d³ÙOtà~èÀ&&&€Õ©ÓéL&“Ùlžšš‚I¨Õje2YvvöÄÄŽã~~~~~~B¡ÐÓÓóÅ_´X,©©©ÁÁÁZ­!ÔØØxùòe‰o0L&“Édšœœ4›Íf³Y§ÓAzddÄÛÛÛÉprssƒò@›˜˜¨­­5 ÍÍÍçÎÕ«WÛíö3gÎÉd‹Å%'''§¦¦L&“Ífãp8&“I.—S(N§ÓéÌf3‹Å*++ãr¹·nÝêéé9yò$ÈA©ÕêÕ«W×ÕÕ­^½zppCMNNMLLƒ(§þ‡D"Íž=[§Ó±X¬'¸ußñdz÷…X,~ÈGßt­¼¼¼œFô&‰3º0½Ìƒä<÷= ‚L‘HÄãñ¾UÈ¿3ˆ¿úÕ¯4X,f±XV«544ÇñÕ«WwttP(”ÄÄDب”J¥žžžÛ¶m°Ûí$içÎsæÌMNNž={veee`` ‡Ã±X,~~~|>ŸH$3™ÌˆˆˆÁÁA©TJ¡P áççg±X0 ³X,ááá`NC$ýýýÍfs\\Üää¤L&ãóùééé%%%ýýýF£±Ùl»Ýêááã8‹ÅÚ»w/lº¦§§Ã×@kk+™LŽŠŠ‰D‹%::zdd$--­¤¤äÒ¥KB¡0&&fxx8--M¯×{yy9sssÛ½{wgggtt´N§ƒK&“é…^¸téRZZÚþýû E__ß“¾.ˆ .¤ÓéD"155•ÍfÓéô’’ƒ‘––f2™233­VkOOÏ /¼P]]••%•Ju:Ý7âââ>ùäûÊÊÊ;vÌž=[*•ÆŒŒŒ²²2›Íæææ¶páÂÉÉI??¿ÌÌÌÔÔÔÉÉɰ°°‚‚‚””” .€öªU«ÊÊÊZZZ ÃÆÙlvrrrtt´ŸŸ_YYFs82™,::Z.—ß¹s'..ŽH$®[·.""Âh4bïéé©T*³²²òòò‡Ãá b±866váÂ…yyyýýý2™¬¢¢âùçŸ[°`F£Yºtirr2lÛnܸÇñ€€€®®®¤¤¤¼¼<¸$‘H‚ƒƒ¿þúëÎÎΨ¨¨Ã‡?é±ûAg§¡\kk«ÍfT‹¥··7**J"‘ètºÞÞ^«;]”× IDATÕj6›ÁŸÖK/½tæÌ™ôôô¾¾>8¾lnnž;wn[[[pp0úÂ\illç[f³Ùf³Ùn·Ãj†Ëå:Ë#„T*•Ñhloo¿}û6äÖŽã7nÜðóó7Z`#ޏt:Á`Àq<55Õn·;E„‚‚‚£GZ,–ŠŠŠááaƒÂq\§Ó9£Ñˆã8(ÆçóoÞ¼™ ÑhA\‚2.£‰ï‚¯¯/ŸÏokkF£Q¯×  ×ë)JHHHCCpz{{ãããGOOÙlމ‰A544ÄÇÇ·´´¨Õj‡C ¸\nOO¸]ÒétB¡pdd„ÉdÂüƒô¼yóæÌ™³cÇ“ɤ×ë¡|¿ÅbáñxCCC™™™mmmííí©©©===¡¡¡$éäÉ“îîîP!¤×ëÍfsXXØèèèØØœ‡- Ãär¹ÙlV©T‘‘‘µµµàE§§§G$Éåòëׯ§§§766ÒétP, @§Óéõz777¡P¨T*q‡K‰äöíÛàìÄéqÄ…oÁt×+rÃrßüïÎÇš^=,,L*•Î(ðp>N šÍ}ùX3º¼ïØ -ˆEEE$)>>¼Ê8Ž={öܸqƒ@ ¸¹¹Y­V„…B¡Óé;w­Åqœ@ ìß¿?++K­V¯]»ÖÏϯ©© ÈRà‹L&ƒã*• \(Øô‚ôÔÔ”Ó¼g‘H¤Y³fQ©TxC1™L«Õ ùv»ÝÍÍmÇŽgΜÁqÃ0‰DB$™Löóó£R©™™™@¥R¹¹¹Ùl¶={ö /$0 «Õ r®]»|,ȱÙld2£ÑhaΜ9J¥’Á`8/Ùíö¢¢¢ŽŽŽùóçÏŸ?ß××·©©é‰ŽÝ¤Õ«W‡„„X,‰äîîîççw|Ïž= ©©©UUUçÎ{þùç/^¼˜ðë_ÿúwÞÑh4‡~úé§Õju]]0ì¶oßîæævóæMÇ###…BaUU•¯¯/¼¶ÎŸ?—mµZ/_¾\ZZÊåró›ßkÇŽPžJ¥þá8~üx|||GG‡‡‡‡P(s挻»{?ð±Ba×®]---' €Á`TTT`vâĉ€€Øm:qâD||üÀÀ@¿R©>” ]]]þþþ###F£ò“’’>üðCN7>>ž””¤P(œ|,F|¬––ßàžN§›Ífww÷ƒÆÆÆvvv&''ƒ„——×ûï¿ùñÇûøø€bAAA …‚ÅbuttÀê>((.Q©Ô––«ÕZRRRUU‡ .<D*•J§Ó[ZZð±ìv{WWWCCNwwwooo‹Å£££]]]ÑÑѰ÷/† åååݼyS©TNNN¶¶¶×ÔÔDFF*І†¨P(¬VëÄÄD__ŸB¡÷óóKII>–^¯ŠŠR(õõõcccf³ùâÅ‹¡¡¡ííí@¡P;v¬´´´½½ýîÝ»\.÷Æ J €û.±XÜÞÞÞßßïëëÛÜܬR©€%“ɨTêõë×Á©S§ŠŠŠÚÛÛ[[[Gvvö±cÇæÏŸíÚµááaPR(ªÕêööv‡C§Ó›››•J%\âr¹ YYY°0èïïÒÃçÂ=X¸páŠ+¾o-x>}\xÄpòЦ“™–-[voI æ3™ ‹‹‹ÙlöêÕ«äÄa¾••˜˜åûÂîåc‰ÅâéòËÊÊÄÇš.çA¸/Ý 2sssËÊÊBCC¿UÈ¿3ˆï¼óNOLL‚@II‰@ ˆ‰‰¡ÓéL&sÍš5z½~xxxùòå^^^k×® …Z­–B¡xxxddd(ŠÑÑÑE‹]¾|yþüùaaaV«U.—Ïž=;&&†L&Ëd²ÂÂB¥R)‘Hbbb ½zõêüüü‘‘ØüÇZ$Éf³mܸQ§Ó­X±ÂjµÎ™3'&&øXAAAðz¢R©nnnv»ý©§žŠ‹‹‰D¯½öZggçèèè–-[ˆDbbbbww7F+++KKK>Öøøøúõ냂‚Î;———·páB`hU§b‰dß¾}ÃÃÃ¥¥¥p&QXXh·Û_ýõ£G®Y³æoûÛöíÛ+**žôðýp555Y­Öêêꘘ©TzõêÕääd7{öl FÁ«',, øX†kppv===!DxxxFFÆsÏ=711!æÌ™#•J«««ÃÃÃÏž=›šš éùóçS©T …Ÿàf Œ«€V‘‘qM É’%}ô‘Á` Y´hQ?°wh4Ç 0 ááá"‘Ö×!???‰4<<\__¿aÃ.—û /€„P^^Þ'Ÿ|²víÚ?þ¸  KOO÷õõe±XMMMµ¥¤¤.ùúú‹Édž:uêIŽÛØøø¸X,6™LSSSÀˆšœœìééQ(ÀÇ ÌÎÎÖh48Žûøøøúúë¹çž³ÙlÉÉÉ!!!ããã¡;w6°hÐétF£Ñd21K«ÕBzxxX,;ùX ʃ#5FsóæMƒÁÐÒÒùõõõkÖ¬±ÙlgΜÁ0ÌjµBɉ‰‰ÉÉIˆÂf³ ƒL&£P(Z­vjjÊh4º¹¹•––º»»×ÔÔ¨Tª'N€„ÐàààêÕ«oݺµfͰö1™L‡C«ÕJ¥ÒñññÂÂBåÔŸÍf“H¤þþþ?þøêÕ«Oxè~à€'ă®Î $Ý—åd)=¤â½X½zõ믿þ>pžœùÐÊæÍ›´¸ùV>œ®íÿ™å·Ã9Q¦Xddä½% ÂôEº@  …†ùùù}ÇC’oµ¹ðññyÏiºVÓ™[&‘H3ºð v×}{7÷%?B&›Í3n;ù! ¾úê«ãããÞÞÞL&Ón· nåÊ•]]] %99y||Ül6{yymݺuhh"”lÛ¶ øXqqqsæÌ©¬¬”Éd\.×b±xzz ß1™Ì¨¨¨‰DB§Ó! ¤ ³ÙL$-KTT”@  Ã0L*•šÍæ„„„ÉÉÉàà`@011‘••5oÞ¼àc±X,‡ÃfÊl6{ÿþý}}}ƒƒƒYYY:nÍš5mmmd2966ÖÓÓÓb±ÄÆÆªÕꌌŒyóæ]¼xQ$ÅÅÅ geeéõz Jƒb,kÏž=±±±:.™L¦_|ñÒ¥K/½ô’O\\\II‰ËúA –””À» -- 6ÙKJJ˜LfJJŠÑhLOO>Ö*++³²²$ÉÝ»w§¦¦€)ðé§Ÿ»»»WVVnß¾=??_&“étºôôô²²2«ÕJ£Ñ.\¨Ñhüýý322’““5Mxxx^^^RRÒùóç­V«Õj]±bEYYYss³Á`X»v-›Íß²>>>ÀÇ‚0™QQQr¹¼¾¾>..ðŸýìgaaaZ&R©ÌÌÌÌÍÍ>BÈÓÓ3**jÑ¢E¡¡¡ùùùÕ¬¢¢âÀCCC‹-^ºtiRRxÂ]·n°û;;;sssí(‘Hd2Ù×_šš Vã‡Ãå,ùAÀ4ÃáhkkƒßíííÀ¼ƒ`8}}}QQQR©T§Óõ÷÷Ûív8&‰/¿üò¹sç222à\!400ÐÔÔTXXØÞÞ |å¶¶60‹ÎŒÑhlnn†Íô?Äàc9ùÍ}}}ƒ¡³³øX4 Ã0›Í†ãøõë×}}}ƒE †††Àõ¼^¯7™LÀÇ‚ ¯ ŠH$:uÊd2]¸p¡¿¿ä „€pf³Ùìv»Ãá%ÝÝÝkkkÆÇÇ“““Aè >yq¿sçŽÃá0™LòÉ…û‚àíííîîÞÑÑÁçóLvƒÁ@&“® |¬þþþ˜˜‡Ã¡R©Ìf3¬Tššš¢££ÛÛÛGFF`ÍÁårU*UZZÚÄÄ8$ccc`Ë‚ôüùó €e0 ¼3R°Z­NMMíèèH$IIIJ¥üíž>}šÇãAI„|̆„„Œi4š¨¨(•JsÃ0™Lf6›ûûûÃÂÂêêꢢ¢”Jeoo¯P( ª­­MIIinn¦Ñh ˜¿¿¿^¯>Ð%p‡K T*•Á`À¼ü^þMá ¯:#=03fà»ó±¦‹•Ëå÷n²S(”‡˜ 1™Ìàà`§Û#gIgzF$íA½sá‚8oÞ¼þþ~ …;88ÿ‹»wïoDl6Ûb± „àßtçηoß>Ähmm…§Îàà ¼"8µ>ø¦b2™f³999yhhÒƒÁÉôÅqœN§“H¤¼¼<*•ª×ëq*Fƒíx6›½}ûöòòr‡ÃA$`—„L&ûúúR©Ôœœ§R©Øl¶Õjݽ{÷ÐЉD"‰d2]‹ä\»v |BŽÕj%“É (\TTÔÓÓœ0¸d·ÛçÎÛÑѱsçÎÈÈHLJ††žðèý€AZ¾|yPPÅb!“É|>ßÇLJD"9ùX)))N>ª^yåðuþüùuëÖÏx%«¦¦Æf³mLee%PŸM&йrssÍfseeå¢E‹8Îo¼¡ÕjGFF DJee%•Jýýïâĉ¸¸¸®®.@ ‰Nœ8‘œœ þ±º»»¯_¿ V«·nÝ |,»Ý»ÀÇš˜˜ R©Z­Núúú¼¼¼š››…B!øÇzúé§i4šR©ôññ1™L|>ßl6_ºtiÕªU­­­ééé&“)..nbbB$™ÍæÖÖÖU«V9sÆËËëÒ¥KÎ8<.ÜXGGð±X,Nb–›››H$S‡¡P«««›šš€599I"‘àläüùó³gÏFA€†;w¶¶¶r¹\àc„“'Oúûû³Ùl ÃNž< ¦ZÀxa2™Pý üªét:È?|ø°N§KLLT(4B¡ôõõÁêgll¬µµ•J¥Âw†L&CÑh4‹Å"~÷»ßEEEµ··;å „D"ч~þé§ŸŠÅbPL&“uvvr¹ÜÎÎN Ã@\¢P(­­­V«Õf³) “ÉôDî‡"ðn›››m6›J¥R«ÕV«µ«««¾¾øX---b±ÜGyJ¥Â0,%%E­VŸ8q¢°°°ººZ©TNLL´¶¶ ÔÖÖ†‡‡ƒ;+¨P(Ìfóøøxoo/ð±À?ÖÍ›7å,?66f4/^¼þ±ÀA×ñãÇ.\ØÚÚÚÔÔÄf³oÞ¼I"‘4Ñhìïï‡ÙéååÕÖÖÖ××çãã„D•Je³Ù$ F«®®öððm[[[ÛÛÛ­VkVVÖÑ£GKJJ*++‡†† LÄ¡¡¡¶¶6p@ÒØØ\`bçÎOå'=v?N<î¨CóçÏÿ.ô•€胮N×ù'5éGÝâ¬Y³ ÌÐÈȈ3ðU«VA\«Ù³g ,X° **jºù@``àܹsÅbqgg'BˆL&Æddd$„b›7oÞŒ* £¬¬ŒÃá¨Tª¶¶6¸$V­Zuûöm??¿ùóç÷ôôÜ[Úb±Xåååàº!Äáp`jR©T¨(‹ÃÃÃ{{{ú?D™éïìrAAD"™î¶‚ÿDGGC¼'g•âââˆ`E¥R§[H—––¦¥¥Iœ3ÊÃÇŠ\.ŸýP.—ÁáúêÕ«aŠ‹‹Á#&ܨ„„«îÜìðôô„ƒ¥R™––ÖÛÛK$ ؈/[¶ ¶|gÔ‚ž&&&¶··;ûŽZ¿~}ppp__œ‹€çÝ]]]`eƒb2™¥¥¥)))½½½°:BaÙÙÙÕÕÕ …îýJLLT«Õ!ooï_þò—L&3??rÁÒ¥K)JXX˜J¥JJJâóùT*u÷îÝà€…ÇãiµÚÄÄÄ{«$$$„§`GO 6nÜ800`±XîÛÖÔÔTiiéôŠ"‘¨¡¡aÁ‚Ί …V{Ný¢Ìƒô‡.ûøø„‡‡'&&Òh4g•®®.p!‰b±X»wï†ØÒ‹%999((¨ú¡¤¤¤ÔÔT„ÐÙ³g%IuuµSmgùÎÎÎîînØ=q–_¾|ymm-Æ‘ÉdXwÆÇÇŽŽ:oÔœ9sôzýää$™L.++ƒo£ÒÒÒçž{®¤¤$""ðÜÜܬ¬, ÃÄbquuuiié½µB%%%*•ÊÓÓszfPPPWW×’%K¦ËqÞíåË—ƒY²³ ø–ËåÓí0*•šžžÖ~~~ þÃvìØÑÜÜìããsñâÅyóæQ(??¿åË—ÃíÈÌÌìèè€=ÉŒŒŒÂÂB„Pcc£\.·Ùl÷V¹sçŽÁ`ˆ‹‹Cùûû?ýôÓ`€ÓÜÍÍL&/]ºô¾m‡ã¬ØÛÛ Žœ#çÔÿ!Êœ••ß­===pº ë9窭­Å0,??Ÿ@ ,]ºlzN:–m<¯¨¨ø½mmmyyyŸþù½µ0 ûâ‹/ á±™!©T »ÐN9λa˜F£a³ÙÎ*8Ž/Y²äƒ>°X,ÎÑ!õ÷÷òÉ'0$ï¿ÿ>l,)•J°MxçwÊÊÊàãÜPÕÕÕ­X±Âb±ÆãÇC ûššš?üáçÎC-Z´Èf³éõú{«DDD8ã¼)•Ê·ß~ÒœòÖ­[‘‘‘×®]ËÉɹ·-2™¬×ëív»³bBBBXXØØØXww7TD9ŽÂÂB§mÅC”yþÐeØëÇq|rrÒYeÁ‚8Ž—––~öÙgûÛßÀ9Bhß¾}.\`±Xqqqð|ë­·œ«"èBè/ù $ <ƒÁØôò999°s†‚×tjjª“×¢ø|¾··wEE…ÅbYµjL»ááá/¾ø"44´¹¹ÙápüéO²Ûíáááqqq*•ÊÝÝ}F-‰”››k2™€àUUUõþûïC‹N9λmµZËÊÊNŸ>í¬Âãñ²²² æòôa½ˆDâÆgä|÷øip_î[,HÿRÞ™ð÷÷ÏÏÏ®ÿ÷•éÄÿ!´Ý#!l9I`›6mòôôôòòZ²d ¼¤þɆî­á¾oõ‡œŽü\. 8a8½Iwwwÿé÷×YžÇã{tÿÝ~~~34f0ðøõõõu64=,%øõ›^LÓ`M6ƒYE¡PÀ‘ÍfûûûÃ6LYæïï/‘H¦;݃CÀzN×J$ …Âé—ØBNÏ„æÀÉ{BBdòùüû6jóxûì³PÒ´ÊËËÛµk×Þ½{á)U’’’æÎ qb™</&&æ…^@eff X±b…F£™Þ„³ü† ÂÃÃ?þøãeË–ÁÌh:--ÍÙ_Ð|õêÕ 9”‡ahî…ÒÒÒÜÜÜéΚ5«¨¨èÅ_„À0ð766611q×®]÷ª½xñâääämÛ¶}—ûï´ë…é£ÿÍÄjhhxƒ!‰‰‰‡b±X­­­===V«5>>Œ« à›—%‡Ã× 4­¥¥eïÞ½Ä‰ŽŽŽéoV؇-¥[·n¥§§Ã‚g›Ùl>þüÊ•+ÿøÇ?bª/]º>‘B8Ž9˜a ¼¿¿áÂ…z½~ïÞ½½½½!6›}èСßþö·555ƒá£>²ÙlÀÇŒŽŽzzzÖÖÖ:k91½/_}õÌãÊÊʯ¿þÖ§ Õàà —— 9«ÄÄÄTUU•””9rÄ™™žžN¡PØlöÀÀ•J…¨÷Î×™³ gùÛ·oËåò­[·îß¿Çñ{›¶Z­Óû{¯æÓ[œ1 êi]]]dd¤Z­±{÷î ÒÑ µÏ;—=<<üå—_>üþÃ|zSÈ9úÿØa†……Ýk§àååu¯(F"‘’““g,,$I||¼@ ˜žïááÁãñ¶lÙ²téR¡P¸mÛ6g??¿ØØØ{Û"÷Æ wªáîîž’’2ãv3Œ‹ ‡s_ÎS+çKÖ ‰”””4cÙáåå¾Áöïß’œœ¼gÏö &@ù{cï8›~¸æÓ[¼·û÷íi||üŒ¾Éä””¦j3Œôôt&“ù½î¿³ÝïHៃ’QQQ†q8NÞ‹BGŽY¾|98]¼xñG}ù999L&ó­·ÞŠŽŽ}ÜÜÜüüüÞzë­ôôô·Þz+&&æ½÷ÞƒG`PPÐ+¯¼뼂‚"‘ïG@PXXø­bÝÝÝY,ÖSO=µiÓ&&“©V«Aye³ÙŽ;ÖØØØÒÒÒÐÐ/èÔc’Ÿ0“ÉTYY +€ÖÖÖÖÖV„PSSSkk+’¨Õj½^?55Pt:¸jhhp¤ N×E›6mz÷ÝwBSSS‡ÍfO?æÐétË»êt:¾­À¯•^¯‡(s¡ãÇ'$$ÔÕÕAô¹ÑÑÑ‚‚‚Ó§O#„´Z­^¯‡C:½^öìYp½Çb±€döp±°Ù­ÑhÀϯÑhåAÔ¼yóŠ‹‹+** À¼;¦¦¦\‘)"‡Ã›¥RÙÓÓ‡ÄbqttôÕ«W‡††ÆÆÆnß¾=<<Œãxvv6¸ðó/„‘H ©¨¨¸yó&äzzzÒéô®®. ó‚;xm‘H¤îîn½^Ÿ˜˜øé§ŸzzzŽ?~¼¤¤äòåˉ‰‰Ç7™Lµµµ0wCCCY,ÖÙ³g/\¸ Õj!???ŸL&wuuMLLܾ}[©T"„4MNNΗ_~I¥R-ËgŸ}6oÞ¼o«Ñh::éw¬ IDAT:š››F£SùšššœœœcÇŽ‘Éäææf‰TPPP]]ÝÛÛ;wîÜŠŠ ×ïIÜ{›àÞï) °¯ .¸à‚ .¸à‚ .¸àÂONú½çDÓs<<<€•1ùÔw¬þ ¤¤¤xxx8©B3*2 ©T f´ß7> •J‰‰áñx`•q •””à3„ËåJ¥R8¥!2™ Ú …R©T*•B1Ð!58hƒL¡PèííM&“Açé'€ÓïC`` 0«ä£kÆMóõõ…ãZ6›- ƒ„aØ /¼DAô5*• çƒL&¨ñ^^^"‘¼W0 gþtù÷žzyyÝ{7¬šáû!bBÄçž{îÆ³fÍš3gN[[[RR¸n×ëõ+V¬hoo'‰f³ùÕW_e2™“““|>ŸÅbÅÇÇs877·M›6=¤ú•+WBVV–X,Â5)ár¹B¡0""¢¤¤dbbbùòå©©©*•jãÆ£££†-X°@&“-Z´¨¾¾Þn·ÇÇǃ…ãìÙ³Édòè訷·wLL @`2™III Ãl6 __ßyóæÝ½{wÿþýV«5!!!''Çn·¯\¹,@áe0‡¢R©‰dÑ¢EçÎKIIIKKKNN®®®öññ9pà€J¥êëë \°`“ÉlmmýÍo~ãp8¤R©^¯_¸páÏþ󦦦­[·®Y³¢FFFÎ;·¾¾>33Ó`0,_¾¢G…††îß¿ŸÏçƒK'•9!!A&“Á>ÜæÍ›;::’’’(ŠÃáàóù+V¬¸zõê²eËòóó###ƒƒƒëêê222¤RéíÛ·u:ݶmÛÊËËÙlöüÇ;vlß¾}<O$A”u˜———––ÆãñØl¶R©”J¥“““8Žÿæ7¿ñññg³ÙàT«ÕnÙ²¥   ¼¼!4oÞ¼ööv„жmÛˆDbooï‹/¾800.“É$!DÌÍÍõöö“ËåR©˜„0×®]_?@ñ¹|ùòªU«¦¦¦òòòìvûCª_¹r…D"íÚµK.—{xxÄÇÇ'%%EFFnÚ´‰Åb1Œººº„„³Ùl4gÍšÕÝݘ˜ÈçócccCBBt:8ßÒh4†-[¶L.—s¹\ÑóçÏ;Ž’’’ââb©T{f·nÝòôôüàƒ-ZÄf³ÿüç?C óºº:£Ñ(:::ÊËËy<^DD„»»û™3g ™R©ljj‚@b~ø¡Ýn×ét™™™‡B­Y³fll¬¥¥¥±±qÅŠZ­6''ç‹/¾øË_þ¢V«ƒƒƒÿeee8މÄèèh//¯„„ƒqåÊ•’’’„„pà“žž 1T²³³çÎ+•J-Ë/~ñ‹Ó§OÇÅÅ]ºt©£££ººº¶¶¶¾¾Þápddd¸»»Ÿ:uŠJ¥¦¦¦^½zÕh4FEE]¾|¹°°ðóÏ?_¸pa¿Õj•J¥Ÿ|òIvv6•JýüóÏSRRZZZ>ÜÕÕÕÛÛ»aûÝÞÓÓóæ›o¾þúëgΜ‰ŽŽ¾råJFFƾ}û(J}}=ÄÒf±X|>ÿïÿûƒÄ"„0„3ÀßÔÔÔ•+W¼½½q-ìmÒh4:®ÕjWc4»ºº îÃë{zzr8œ‘‘‘‰‰ 0ÏúòË/QI§Óu:FÓét|ðÁÿ÷Ûl6xä „ªªªÄb±F£ùüóÏ{{{Á¿Èq84H$Êår P(ìv;4ýÞ{ï%&&2Œšš»Ý>22³ßl6kµÚÔÔTooo0¼¡Ñh8ŽK¥RpÚ{÷îÝ¡¡¡”””¸¸¸›7o&''Ëår§oÒ¨¨¨gŸ}¶ººZ&“577H( Ü+çmg±X8ŽËår»Ýn0À] tÉ6›mÃd2%$$ܺuK,»»»C@$üž P( î]»À4r``à믿–Éd»víº~ý:äÿêW¿ºzõ*™L®¬¬üꫯ€=ÖÛÛÛÓÓÃår!leÿCÄ"„p¢Ó××QàÛÛÛ%ÉÀÀ‰´Z­F£Q"‘p¹Üúúz8ZÖjµà­|G=¤ºÍfƒcµ±±±øøøîîn"‘8::êîîn6›W­Zõå—_‚ÛtëÖ-¡P˜œœl6›«ªª¬V+‹Å²ÛíF£äX,–M›6ÑéôC‡Á£üSÊåòÛ·oóù|«ÕªÕjsssÕjõðð°···››Ûõë×cbbX,V}}ý’%K ÆÉ“'ÙlvMM ›Í–H$Îéôÿgï½£Ú¼²õá£.êÑ„h¢wÓD½ƒÁÝ÷—8vìÜÔ›6}™g’±3™rgfÅ3;qK\ÁØÆzII€ u!éûcßû^ý;N¦$ó Ϭ—£Söyë)Ï~ö… áááÓÓÓIIIgΜár¹ qßÞÞN¥RY,–^¯S(@S*•žžž“““¡õë×_¿~]¯× "‘Á¹ãûßÿ>Çß) ÍÍÍÑh´µk׿çç8pÀl63™L“É2999==íïž[^àBàáá±uëÖ .ÀöÚáÇ?n0x<žB¡`±Xþþþ f;22‚Ãá ÝqÓ6::d÷0ïS„ìÐ÷õõ9&º¸¸„……uttxyyQ©Ô‘‘‘'Tû€ÙrNÆq†G¦3¼Û–$>Khn {¯HŸ‚!ZDD„£°ìãèS+Véà7å‡:×{ÉDúCõå­< \]]Áà;åïï¿| 9™LæŠ"Ð0 :;;ƒ2ÞãZÇ~zÊKöÍøpKJŽ9ëááä倀míµ×²²²†††ž{î9ƒÁ’’²aÃggç 6äää455åçç“Éä©©©ƒ¶´´ÀmÿþýT*µ®®îîÝ»¡Ÿÿüç---o¾ùfhh(Ð[©TêââbFFÆÖ­[“’’îܹc³Ù°v·lÙRZZ:22ò /,)¡(Î;‡9Ú{yyýüç??wî\qqqnnîÇßxã (¨Óé–´ÄmN±¶mÛäíí Édò–-[ÚÚÚ°®!„rss]\\&&&öïßßÞÞ¥ââârrrär¹Z­†VBÇŽ 3 …‚ÃáP(بÎÉÉ …qqqEEE …bnnЏ¸¸ÔÕÕmܸ±©©iaaÁñ$”——ƒºSpp°ãIHKK{õÕW]]]{{{a+Ýb±¬_¿¾¼¼Ül6íÞ½»¹¹Ùd29ž4 Ì=Í%‹Å[¶l¹uëÖøÃ%çÏž=£££ï¼óL>¦§§—|äÈ(…÷ððXXX€ÏvVVÖ;ï¼Ç¿þõ¯AÍÌn·»ºº~öÙg ãyéÒ%xP.^¼XYY‰„—'@`0:N,ß¾}*Á-oooxУ££ß{ï=ƒÁd2¥R)èG†„„¼ýöÛ™™™¡ëׯ:¾¼ ø «4Ïç„ÉÉI-æçç?® “É„yœcÁñññ®®.///¬àôô4¼9°®!„ÒÒÒ@º†•òõõ%“ɨâرc0óÇãñ###!!! £¾¾þ™gžqqq¡Óé™™™  q ˆV«ýâ‹/=z499éx®^½ RMËûÒÜܬP(>þøc“ÉÄåradùM&Ó™3g:;;ÕjõŠ'íi.YSSŒ—7=11±oß¾°°°ÌÌÌG=Ù`¼Ñhljj>Öøø¸F£*fII hÂ666fgg3™L«Õ £r Qa»Z­b‰DøÐÒétð!ÉÏÏ·ÛíÑÑÑ¿ÿýïá ž™™ÁX+¡ãÇ«Õê¹¹9F@??¿{÷îùøø,/‚Ãáþú׿‚4NŠŠr¤ºkµÚË—/—””¬ØVgg' †°‚žžž‰„N§c±ª k@½¬kX©›7o^¼xQ,ëtº»wïb’*###§N2›ÍJ¥R¡PX,–‚‚«Õ Ä@ð~ÆŠàñø|ôÑG8Îñ$¸»»»ººvww?î¼|||À)Ë_RR á+ž´§¹d–7ÝÚÚZUUõþûï@À‘'L Óéð²•Éd³³³<€O@VV™L¾~ýzVVÖ­[·@”bbb"##¢Ó„‡‡[­Öþþ~`\EGG÷÷÷gffÞºuË`0ÄÇÇ÷ôô444€\V||üììlggçÂÂø±àp¸ááapH×ét<€ŸŸŸP(¼|ùrddä’"v»=//¯¯¯ÈÄÃÃÃ03Âãñ+J,öÙgËÛŠŒŒT*•wïÞÕjµPL&477wtt@A£Ñ˜’’rëÖ-èZzzú½{÷BBBd2™F£®‘H$(e6›×¬YsþüyƒÁÐÖÖ4e£Ñx÷î]›Í¶¸¸822Òßßo0úûûïß¿?66688˜˜˜øù矛L&(Â`0„B¡··÷ôô´R©ÄN‚H$²Ûí&“ æ­Ž}Áú‹R*•p±üf³¹¿¿¦ÉËOÚÓ\2¬~NwlÚ`0ÌÌÌ\¹rE§ÓŒŒ8^µå£oŒ¤¤$xšE"•J…G!44V¢¿uÆÒã|(–xX8Â××>…Ð5nS©Ô„„äеo+vái|Fþ™—ìÿÁ"""Š‹‹`8(**JLL$‰°"€¹!¬[·>º[¶l•ËåðF™™ÉÈȉDjµZ&“aõlÙ²ü ª««—È‚ãƒÁ€§Ð1¿Z­®©©¡=è9z;Ö××aï-ÀÚµkÃÃÃÖ®];55e4wìØÑÑÑ¿VTT¨T*£Ñ¸mÛ6ì©JLLÌÍÍV©Tð­±Ûí±±±£££"‘èÎ;avvV§Ó¹¹¹íܹóÞ½{)))KLòððذaCBB‚V«õy„PPPPyy9ŸÏ‡õkìÆÆÆ‚pWaa!ôë‚‹‹Ë–-[8Ž£¤VXXX~~~BBBgg'ôÈßß?&&Öë!–Bgg§ŸŸ_||üèèè† ¼½½5ͦM›ôz=P±'&&ìv{VV–\.g³Ùaaa:"0À öÐМü™™¬uè›Ív4i‰X×øôôtp®]¿~ýƒà‘ÅSRR.]º¡PY,ÖÑ£GaAO£Ñ$''oذ¡¥¥¢cbEnܸÁápeÜBJ¥2888..N§Ó•••9æÿâ‹/¼½½A+fIþüü|gggN———§d2¹®®F¬‘‘‘îîîÑÑÑuuu|>¿®®ŽÇãÍÏÏ'$$àp¸æææšš¨ Óˆ‰‰™™™INNvŒº[YY)‘HàÓ•ëtºªªª^x¡²²òóó³³³ Âüü¼¯¯/‡[nÒôôôðð°Z­õð𨭭¥P(¡¡¡=Š‹‹q‡#GŽ`òZ“““yyyB¡0&&†J¥bEâââ`#nVHÆÖlÁèè(8×#„°Áþ——ÇËÌ̬®®nll„ˇðüüüÊÊÊÊÊJmÂÐßߟ˜˜ˆ|ÇÖa‚õ­h§c×þçÆŠ‰‰ÁªO>ù$)) ¶H±DP8uêB(///11144!¤P(èt:‹Åš››ƒ·+V6ÑÀ)£¾¾v[áM@"‘<==afŽå‡ETX>X’Öyëëë[[[F#LŠŠŠ`ªÁ`0ŒF£¿¿QQ‘§§gQQ‘———V«²Ûí333°X%•JáÆÂ„¦ámš““SUUÕÝÝ]PPkñP¹Z­öóó;sæÌþýû›››™LfNNNnn.N‡åb„Ðr“l6›Éd2™L‹‹‹<¯¤¤æó}}}³³³áááIII999¡¶¶¶ÔÔÔ¶¶6ˆ~@¡P°"½½½˜j–ˆÃá*++ûÛß:öýï‡ëèMMM9;;GFF^»vmãÆðMÇN¸J¥¢Óé fipB:>;ØÁ±žžžv»Åb­h§c×Ä_ýêWp”žžŽÃáàm†%J¥Ò?ýéOpüé§ŸªTªööv"‘XYY933síÚµºº:xÉcEvìØ100ššzçÎ'N@¢ÑhÔjµ‹Ån·Ã§ËÂÞºKòwwwWWWK¥R.—ëëë{éÒ%‹Å²cǸ?ôz=…B™šš‚øûñÇ߸qÃÉɉB¡ÀûßÇÇgpp0//ïêի𠌎Žúøø 544 „’’’üýýïß¿ïXùøøøéÓ§ƒƒƒ!,ù‡~h³ÙàJ€µ+šf#„ººº¶oßn±X´ZíçŸÁQ|ˆÃáfffæææ`Œð7n„‡‡›Íf¸á$8^ˆ{[p‹eE;»¶ž^* ÓŽz*©$|Ýü_O“ɰ”¼cÇX{«¬¬är¹t÷8î Ÿ€¯kÒŠXQ… öFWŒÙÙÙð‚Çzäïï¯%Êaÿ <ÉN:¾äÌ‚œæ’œÞÞÞð¡LLL„üð…B˜\€.Ç …K<¸]]]Á³DÖÁ±r !!!!!!޶ñùü%BVþþþL&“J¥‚Û-: f8†ºÄápt:=""$V€x=zóÍ7±yÓwßxVøÏ~íÚµ)))0Õ †§çÅ_ܼysDDDpp0@€¿[¶l%³Ù 㸔”L‘bãÆ³³³ðù?xð §§ç‹/¾ˆâr¹p+9r¤¦¦fûöí í„-]‡UN €8F§Ó=êîîŽÃá°Ølvee%Ü» 233œœ^{í58­\.î݃úùùíÛ·j€ôµk×&''§§§ËårxСG ; ]û.‹³>þøc*• [T?øÁ òÞÞÞ,QçÂjxùå—›››ù|¾T*mjjÂô-–Ëo6››››+++;†Çãm6ǺŒþ÷ù&‰‹…@ ÀÁ?êdÿ[ÅbÅÅÅ-‡†‡‡ÁÙ11"""""‚H$ËêèÑ£B¡¦:D£Ñ ÆþýûÑc(+ ";£K~Â*wL\^IPPPDDÄF6Dò]1?ȵ/¡Á`]ær¹{öìAAÞÿý’’’Uµo ØÎ†ãÜÉÉ èJËæßY0 xx GNNNÿBƯb«XÅ*V±ŠU¬b«XÅß_oû" ÀÝÝD"Á&¥H$¢P(³³³ùùùb±xlllûöíB¡phhÈ‘šóä é_@*‹Å@3ÄÇÇ—””ŒŽŽÏÏÏïÚµ <5Vñ±¼¼<$$äÂ… eee---III4íæÍ›FA«ÕFEEõõõùùùMLLÔÔÔœ;wîæÍ›Ï>û,‡›œœÔëõÎÎοüå/a‘iddD(öôôìß¿_¯×ƒªgIIIkk+xhµÚÛ·o§¦¦ÖÔÔüæ7¿ ¹råJaa!ÌöÝÜÜÒÒÒbbb&&&Μ9C£ÑÆÇÇsss°¥A|Ün·ïرÃÇÇgfff~~^§Ó…„„üêW¿zœÂý*þ™ÀƒÈDuu5‰Dò@àóùt:=,,lëÖ­T*5##£±±1&&\ŽÜÜܘL&°ÆBà^‘’’íââ>?ÞÞÞ™™™¡¡¡*•*33ôBóòòÀ ív{GGÇúõë©Tê¡C‡@O!æëë -"„:;;!8ŠÁ`0›Íx<ÿQQQÇ;î7¯â[‡ÃQ©Ôû÷ïƒCާ§gxxxwwwUU•Ñh¼qã†B¡èíí5 J¥R.—{xx@ü¦™™™……£Ñ¨R© zÖÄÄ„N§srr×€¾¾¾ööö   ²6W¯^åñx¹¹¹ãããjµšB¡Ü¹sG¡Pœ:ujûöí𲙞žV«ÕÐ"BhÇŽjµt³)ŠZ­w„R©.µR©„ެbß`#Ö ñxüž={p8¶»â¸±ƒÃáGÃZÎûÁãñެ~ ÀOð~úJzVöÉYÅ¿±ðvð/BˆÁ`DEE==oi‰“8T²$8 —Ë wvvöóóD"122rõõó¯ BtttJJŠT*MJJòôô$qqqv»===]"‘ìܹ3((¨µµµ¸¸X­VoÙ²¥©©iË–- ´!•JSSSÝÜÜ<==aÌ”››«V«cccüd4ÃÃÃ_}õÕ””…BQXX˜››ÛÐÐ1ž×¬Y0¤R©¬°°Ãá899ݹs'&&&99™Ãá0 :ž””$‘H¾#¬£U<„Ç÷ôôˆD¢ààપ*ƒÁ`4H$Òëõ âÇçó££££¢¢ðx|SSSWWWAAÁ•+Wh4Ú÷¿ÿýøøx½^_^^Îáp¢¢¢rrr\]]M&S^^ÞØØXtt´»»{nn.ŸÏ/..nmm ½víÚŽ;œ¡àõë×…B¡———F£ÎÉÉéîîvuu ¼|ùòáÇgff|}}³³³9ÎÀÀx4¬â; <‘Häp84-44¾Yccc&“ #·hµÚ±±1Œu_WW“ÇÅÅÅ©©©3g΀Ùl»xñ"ÈÕY­Ö˜˜“É„Çãççç›››Š5?>>+^z½^&“ñx<±X¬R©nß¾=;; ä0ˆ811aµZår9xsÿ³ÏÓ*¾&po¿ýö§Ÿ~:00²°°0??o4]]]'''áÞš››‹ŒŒÃãñ333^^^t:}jjjnnÆC àß<66Æd2Íf³^¯‡©¢§§çôô´ŸŸßÐÐP`` B¡˜žžvuu5›ÍF£‘N§«T*ˆ|Ü××Ìw…B288ÆhµZàääd³Ù<=={{{W?…ßu¬(»$²ô*Vñu7™Lîîî%‹H$‚ÏBxx¸““Óã„ËV±Š¯î{ßûžÉdõ•®®®äää?ýéOEEE cnn®µµ8é«XÅ×Þjµ^»v­³³“B¡€ƒ,ÇUÖ‹/~툿«XB!bCCÃØØØôô´Á` Ñh\.÷Ñ£G ¤€íœ¬b|w&ó‹ÊêoéU|Ë ÇŽ+--­­­ŒŒ|\6ŒÚð8dfffeeAޝ„c…P„@ ìÚµ +î˜açÎ+Z¾mÛ6„PUU—ËýðߦÝUüƒ@HIIÑétÞÞÞnnn*•Š@ ÄÆÆòùü‹/nذÁËËk~~>::zçÎÉÉÉ8®¼¼ÜÇLJÁ`°Ùl8 …EEE {ðàÁ¨¨(@[@L&óàÁƒfãÆt:],³ÙìÑÑÑ£Góùüªª*WWלœîóžžž°¼°°ðÊ+¯°X¬äädÈ€µèæææââR[[»¸¸811±{÷n.—[[[ËçóÏœ9SSSq1¾íÓûï ¼N§ûùÏÎf³·oßOþøã´´4>ŸßÐЀÇãAŸ)99ù׿þµ¯¯oSS“P(ôññ¹råJbb"„:÷÷÷Ÿ˜˜èííÕjµXh‘Íf§¦¦FÕ|>¿±±±½½]¯×“Éäã¿3kÖ¬9wîœÝn—Ëå/^„í牉‰ßýîwqqq 6>>ŽÇãµZíÔÔ”B¡pww×ét …ŽçççU*Õýû÷CCCûûûM&Shh¨D"!“Éfjj*;;[&“ÆH¤„„:.“ÉRSSçççGFFx<žÉdJJJR*•F«ÕF777Àd2{{{!ì´¨R©`W"Ô»à”Ut IDATººR(”¶¶¶uëÖ‘H¤»wï ''§¦¦¦oûô®âÇãANÃWÒc’’’Þ|óMÐçÀÔž°R@áZ”˜UŽé¹¹¹°ç Eðx|]]Æ[Kª…Ìååå,ëðáÃOÑÝUüsÁårAn!¶~ýú?.õïkákQ‡—Ì £¢¢àöøúú†‡‡Ã±‹‹Kttttt4—ËÅápnnnÑÑÑ j 9£¢¢°()<týAdÿ<==½½½Adÿ‚‚‚***@ÍÝ݆ÒJ¥2==ÏçONNB„ÁÄÄÄ;wž;wŽJ¥VTTP( …’‘‘aµZAÇÌÅÅþéËÌÌLN÷£ýhhh(33S"‘™ÍæììlÖšššYYY‰$//ϱ- ,¿ýöÛnnn °Àö½ï}Ïjµêt:ˆ ’™™ÑÓÓ£Óé îÒæÍ›!èÞK/½$‘H¶oßZ†¯½öŸÏÏÏϹýUüÝA„§OŸ...¶Ûí¿üå/wîÜyóæM__ß­[·êtº™™ŸÜÜ\«Õ Ê“™™™˜xõúõë¥RéÆ]]]u:]NNιs窫«===áßóçÏÇÆÆ&''C`´;vœ?~Ë–-111ƒ!**jvv‘íÙ³çÂ… [¶l‰ˆˆÀÚ ÿÑ~„òôô„U\0ýÁƒ|>ÿÂ… !FÓßß4 „B¡Øµk×ücȉ©ÿz½žÇãÙl6Ì)cwàGFFZZZ4³³óàà BÈf³yxx@ÐŽ³gÏjµZ½^Ãáæçç ÊÅåË—ák‚Òëõ>>>d2Y¥RݹsG"‘LNNZ­Vì_ˆga2™€J¿¸¸ÈçóÕjõÌÌ LbccAÙl6ÃOŽmµ´´À'ozzúÖ­[ áááT*•ÇãiµÚèèh새Šˆˆ R©¹¹¹T*500xÕ Öõ»ßýþmkk3›Í:®««ë[9éÿø¿A @ΓÉèÀªÕj˜†‰=„ÃjD"a³Ù»wï¦P(ï½÷¸jµZ—ÅÅEì_ C4›™™Ÿƒ1T!¾Ïìì,NçóùðÖH½uttÚl6"‘èììÜÑÑq FGG…B!yyy.\`0\.×jµÆÅÅ>}b´"„Ö­[wúôi2™L¡P 0 Elÿ(} ›Bb˜ÎñŠøŸŒûþ¸²$Åb­Rðß„—_~922288ÂwC6Xæ† ¹f³ù•W^ KHHèîîvww×jµ‡†!yyy6lˆ‹‹Æáp …J¥FÄX,PñFxEÇÉÉ ÜaMǯY³¢z oÞ¼9))©µµ•Á`|üñÇ...¥¥¥"‘¨¹¹Y(îÞ½[$ݾ};--í­·Þrwwïíí---Ý´iŸÏïêê:~üxhh¨Åbqqq‰Dûöí{ðàÁÑ£GŸ}öÙ{÷î%$$lݺ5??ÿÎ;nnnF£ñùçŸïêê2™Lt:¾ ‚ÙÙY.—«ÕjY,–““í>ÜÚÚ }Y\\twwß´iè ®‘ÅbI¥R___^Î!ˆÍ7>>þàÁƒqçά¬¬C‡Æ®®.‰tôèQ8h2™|||‚ƒƒ ÅÞ½{FãéÓ§ccc¹\î›o¾Y\\ìîîÎd2I$‡Ã±Ûí­­­l6›ÅbÑh´'Nètº÷Þ{ï­·Þ¢P(¯¾úê;ï¼±ó|}}ccc»»»;æáááíí ápû¿¹¹977÷ã?¶ÛíçÏŸ_³f ¬øãñø±±1>ŸÿùçŸ×ÖÖz{{8p ¿¿ÿÊ•+111 …B(C Z‰´yóæööö„„ <2Œ´´´ââb•JÕÕÕUZZÊd2Ÿyæ»ÝN"‘^zé%·ñù矯.[,Þl6ß¾}ÛÉɉJ¥‚2…Ba±X·oß&“É0œ·Z­ãããï¾û.‹ÅúòË/AN]&“ÅÄÄÈd²¾¾>ˆ`H$e2ÙÔÔTXXLÖ\\\( Ô)îÝ»wõêÕÚÚZ'•Jñx¼^¯g³Ù\.×d2ÙívÈ7«Á`pvv&“É---V«õîÝ»-ÒÙÙùäÉ“6l`0Ø7‘ÅbmݺõÒ¥Ki]§Óµ´´œ;wÎÉÉÉËËë׿þuiiicccKK‹³³3@P©T¿øÅ/<==/\¸Ÿ¶óçÏÿøÇ?þòË/!h›Í†)—.]‚Ír¹œB¡À’,ô¥»»{Íš5˜cK@°X,===8îáljdjjJ«ÕÊd²ŠŠ ©TJ&“år¹Ùlîìì4›ÍsssiiiùË_t:ÝÄÄ‘H„@‡J¥â>ªÕj‰DrçÎÍ›7³ÙìÉÉÉññq¨óÎ;>>>W¯^ëíí½ÿ¾——×èè(ÄÖëõ§Nª¨¨ ‘Hׯ_ƒƒƒ 2b³Ù"""ÆÇÇCCCÛÛÛ333;::RRRúûûÁ‡g÷îÝz½žÉd†……yxxttttwwC(¬¶¶¶æææGÁ°¶¶¶··whhH©TŽŒŒTTT\½zu|||dd$>>þäÉ“z½ö&&&=z$•J§¦¦|||RRRš››q8ÜÂÂôÅh4þñ„`t·nÝú¶/å¿ÂÂÂjjj`5áq(**zœ§²‹‹KuuuDDÄ“[!“ÉKü¡1$%%%&&Â[Ð1ݱÅ‹,/¾¤”#BCC—-– ¨¨¨¸¸xÅŸ|||V?…«XÅ*V±ŠU¬b«XÅ*þuíÃ@H@jjêòœ8.99û700088˜H$®Y³æ)·ƒ›XOð®q´ÊÏÏ£ˆÁ1…Bq¬?%%E ¬H#[±wK°âö$ ‚ØØØåá€VáÂ{ï½§×ë…B!Bˆ@ ¤¦¦‰ÄŠŠ ¥RI¥R gggµZmbb¢Ï³Ï>«ÓéÌf3‰Dª¬¬ÌÉÉ™žžæp8ëÖ­»qãFll¬‡‡‡Édb¯¯/OJJb³Ù"‘H*•úúú‚p­T*ÍÌÌŒŒŒ4 D"Ñ`0ˆÅb___???¸}õz}^^žZ­Ž÷õõ™™Y»v­X,Öh4x<žF£999-..ŠÅb@°°°Àf³ßzë­ááa¥R¹víZ½^¿nݺþþ~2™œ-¬V«X,–Ëååååb±¸¡¡!00P,OLLTTTèõúÀÀ@Ì0WW×—_~yttT,ëõú   ´´4ƒÁðÃþðÒ¥K/¼ð‚L&«ªªºsçη}ù¾» ˆÅb ¸ˆÅb6;;[^^Î`0âãã§§§×¬Y£Õj¥RéóÏ?áÂ…5kÖp¹ÜÎÎι¹¹‡FDDüå/‰‹‹c±X·nÝÚ³gOFFFttôØØXrr2\`µZ]VVÖÛÛšššÝÛÛ›œœòå—_F«Õºnݺµk×öööêtºÒÒR.—q+]\\ÂÃÃCBBÂÂÂnß¾½fÍ<_ZZêççg6›M&S`` §§§T*‹Å‹‹‹V«H<oË–-^^^¥¥¥×®] ¿víÚÑ£GïÝ»WWW×ÚÚ «nà÷±víZ“ÉDûèèh±XÞÛÛ oÓK—.3 °*>ðàµZ-ƒÁËåð¿R©Z¦Á` ÓéJ¥266yóóó,‹Á`0™L—Ÿüä'ÙÙÙàÀƒ’ÉdÉÉÉ£££XT:¹\n2™&''á;ÇN§s¹\.—ëââÂb±£ØÍÎÎ* ¹\ÞÖÖé Ä ²oîîî@0Äápjµ„–M&™LÆãñࣆUE¥Rkjjúûû§§§[ZZº»»±(²f³900P¥R …Bˆ>?99Éd2µZm~~>T?áp8hÂb±ttt¬ ò<8‹åââ¢T*-‹Ùlvrr‚ ¶ÁËËK&“Á=1??âU333V«ÕÓÓ¤Þýüüär¹V«…˜4mnn.((H«Õ.,,˜ÍfgggNG"‘àþƒã7fee8p`qqÑl6C~F³¸¸H£Ñ„Báää$)¦§§§§§ •Jecc#F³Z­0бX,‹‹‹ ¨Óéø|>ðHÍf3ðßÁøÑÑQøunnÎÅÅÅÓÓóÑ£G éE"‘À0#4™Lª‚ŸÜÝÝe2‡ÃqvvV©T«‚òOÇqîãüòÓq88;<=;ʱ¸»»ûòV`ú ÅÝÜÜ QÇœØñ’.<®¶¿ÝëðïNûÿuuuà£' U*›Í¶Z­¼wï@àñx:x ãàÁƒ]]]v»‡Ã½ñÆùùùÓÓÓuuummmWrqqÑÙÙÙÉÉ >L&“@ ¸ºº.,,ÄÆÆÎÏÏÃ1üj³Ùp8œÍfº\ff&™L¶ÙlV«ÕÝÝÝ`00™L2™l2™<==÷ìÙãe"‘Á)¨T*Fsuu¥R©UUUÀ–ñòò2 Ï?ÿ¼L&#‘HÐÕl6»¹¹ét:¨çæÍ›ðÒjµ^^^F£¢`Â<€H$nÞ¼ùáÇnnnƒ~2›Íµµµ]]]uuu©©©¾¾¾ßöåû““Ãårõz=‹Åòòòâr¹l6ÛÉÉéå—_¾wï^bbbssóÕ«W_{íµÏ?ÿ<$$äõ×_?qâÄÌÌÌ/~ñ‹ÿøÿ9 Bhß¾}l6ûÁƒóóó‘‘‘\.—ÏçOMMµ··§¦¦–––NMMõöö–””°X¬ï}ï{Z­V¥Ríܹ¤lI$ÒÏ~ö³/¿üBžÉäÀÀÀsçÎr¹\ ]½zU(*Š}ûö †K—.Ƽ¼<¹\^UU f¼¢ÕjÙl¶T*µX,ðÆ:räˆN§ÏiçMMMuttÔÖÖÞ¿?55ull,!!Áf³q¹Ü©©©ñññ¼¼¼?ýéO!«Õ 1ÕWñ8à*ÓÔÔD¡PH$RSSP™L¦B¡˜œœôññ¡Óé&“©­­íÑ£Gccc&“I£ÑlÙ²åÓO? „Á`˜››«¯¯ïëëóôô„pNMMM‹åÊ•+T*Ž…B¡\.—ËåSSS†Á`@~„‡5¥±±1H¾pá‚Á`H$ÑÑÑ2™ŒH$‰Dà´H¤ÙÙÙÑÑQ<¥×ëAÖ‹D"™Í怀€wß}×××·¥¥ÅÛÛêAÑéô³gÏ‚J‹ÅÃø|~[[›ŸŸŸT*e³ÙPü„ÇãGGGAÏ·±±±¶¶öÛ½rßqŒF#™LÐh4‰dzz\©Z[[ñx¼»»{KK ðòÆÇÇA#d||‡Ã………Ñéôáááìì솆…BaNúúúzzz|}};;;;;;!~‰T*]XXËå>„»ÁÛÛ;%%åÖ­[8N£Ñ`ùgffæææCCCÈdrggç¹s犋‹ïß¿M···[­VÈ9::*•Jgffètzww÷Ðз·wkkëÈȈD"1™L‡Éd^»vÏçŸ>}:;;ûþýûR©tnn.55õäÉ“………W®\“J¥ d2<<ÜÓÓC (Jkkëðð0ØO"‘)JJJÊÅ‹U*Õ·}ùV± ………_·Taaáê’÷¿0?tGªgžyfyN¬Âþݺukuuµ»»{}}}ZZÚÓ´•••õä ™™™°°"öìÙƒ‡„„`ô:8 uìž={BCCW¤à9Öó8`§eyâ¦M›Ž9’ŸŸÿ••ü;ƒðá‡r8œääd2™Ìáp***ÀÿÄÜëêêìvûØØØÞ½{Ùlvuu5¬'‘H$«ÕšžžÞÝÝ=??Ÿ››{óæÍÚÚZ톆†–••‰D"*•ZZZWPP099–’’RXX(—ËŸ}öÙÒÒÒññq«yàÀ‘Hd4M&Ó‘#G Cuu5™L.))‰D*•jïÞ½>>>~~~@uçr¹6›í…^HMMU(o¼ñÆÔÔÔôôôÞ½{™L&Õœœ6lØPTTÄd2×­[g±X¶oßzIUUUUUU&“iûöíl6[,ƒaõõõB¡°¾¾~nnnýúõL&3;;»°°@ ¼ñƧOŸ(((øýïo³Ù¾íË÷ݾ§§G£Ñ466–ÈÕ«WCCCÙl6læØl6X âñx @>Êr¹œD"uuuÍÏÏ“H$Xéööö }å•W&&&\\\RRR<==½¼¼Îœ9äíí}æÌ™ÂÂBp·R($ ò#„ðx¼F£Y³f ‡ ‚ôòòò'N€ãkQQ‘T*uwwg±XöÂÃÃC­Vwttøúúzxxèõzxu¹»»Ûl6½^îܹõë×ãp¸úúz¨!”püøñŠŠŠ>ú(99 KHH “É$©··wvvª‚ŸÜÜÜ::: l}«î»",%ëõú‰‰ •J¥×ëÇÇÇ'''F£¿¿?,C@X^›ÍÆf³ ‹Å²Z­555­­­!!!ÉÉÉ ‹ÐÒÒB ²³³år9xR@…cccz½~nnnbb!¤×뇇‡ÓÒÒ@À îTÈ?77áUîß¿_PP0::099ÙÔÔ´sçι¹¹¦¦¦ÊÊJ«Õ 9ÇÇÇBsss‚E.—s82™<>>-R(”5kÖÌÍÍ]½z•F£=xðêA îÚµ«¡¡açÎ}}}4M¯×k4£ÑÈb±d2YJJ Te0ôzýìì,@ ‘H‹Ú]Å“€- ¯ˆ%âX+ªU­( õ•ªZ555¯¾úêò;4Dÿ»Ø½k×.ð.\̰Ç5 ŽŽö/i«÷¿XþÓ“;µŠÿlð!„ã®8ÇápŽL¦àààÐÐP"‘˜’’ò”›$ŽM¬ˆ   'xÖ;Z%0ug8¦R©Žõ‹D"ÿ Ÿfª–å‰áááIII°mºŠÇðþûï †ÐÐPX­NKK#‰eeeÓÓÓT*µ¤¤v[“““}}}ëëëF£Åb!‘HåååÀÇrqqY¿~ý7âããAñ‘ÏçÇÄÄðù|’’Âáp ú!8[Ãqvvvtt´^¯>VNNŸÏ‡«•––¦Óé A…‹ÏçÏÌ̬[·‚Ÿãñx'''ð&ÍÉÉñ÷÷W«ÕçwÞœššªªªÒëõ•••}}} %/// ÀjµæääLNNVVV¦§§744gggC„DƒÁŒæêêúê«¯ŽŽŽfggY-==Ýh4‚G«‹‹K^^xb~Û—ï» BzzºÅbQ*•ÙÙÙ4mjj øXqqqSSS ÀÇzî¹çΞ=›Àf³;::T*ÕèèhXXØ_ÿú×5kÖk÷îÝééé±±±V³¼¼\§Ó©Tª²²²ÎÎΰ°°ÔÔÔˆˆˆÎÎÎÔÔÔððð   /¾øÂ`0Øl¶ÊÊÊòòràc¤`TT—Ë-//wqqéîˆ onn>VQQ‘¯¯/D^^^R©4...33øX áææ¶uëVww÷òòò/¿ü2""¢¡¡áÈ‘#wîÜÙ¾}û­[·jjjÂÂÂ:;;ÃÃÃËËË!&YOOOTT„Lïìì d³Ù ä–––öÛßþöÛ¾vßiàa B1== |,¶+..Îh4j4.—Ëb±€•õ_ÿõ_½½½999ÿI*•¶··'&&:ò±¦¦¦@j f—pŒÇãY,–»»»››ƒÁXÂÇš››“Ëå …ãc©Õꈈ"‘ØØØèææ†ñ±4^¯‡ji4Úr>–““Ó¶mÛFFF”Jå½{÷ÚÛÛ¡(6== 1ñ”J%“ÉILL„ûª‚Ÿp84ñŸÿùŸ+.t­ŽÉdBÜy'''‹Åb±XÀWØb±Ê•F£Öìì¬Õj"ØœQ*•z½n*•ªV«ýýýµZ­V«… õz=¶*Ç›6m‹ÅÀDzX,aaÁjµR©TN P(ÜÜÜ´Zíì쬟Ÿ¼üÆÇÇ›šš¨T*äS­V+ÇÓh4ƒÁÛÛ6[€Åår5···L&ƒ_Õjµ“““‡‡‡L&ó÷÷Ÿœœ$‰`‡Ã1™L‹…B¡ï ³ÙÕÕu||ö@A¢òÛ»pÿ:pôbxœGƒãX›N>}ÔqÇjáå·$N_qÔŒíÚ%9±ã%]x\m«ÑPþ ìØ±V¨ƒ‚‚fgg1>Öýû÷AªÕjív;Ng±XÏ=÷\ww·ÝnÇãño½õð±jkk£¢¢Ç Åd2y{{ïÚµ«µµ„„àÝ £x.—K£ÑÖ¯_óññ1 ”J¥D"ô’Ìf³‡‡‡V«…znÞ¼I&“ùÁ0‡C ª««GFF€?™ÍæmÛ¶uttüçþ'¬Þ­jb=ÄÌÌL‹¥Óé8Ž——‡Ãquu¥Ñh¯¼òÊÝ»w׬Yƒñ±NŸ>- _ýõãÇÏÌ̼ûî»/½ôÒÐЯ¯/DÝ>V[[›J¥ŠŠŠ jhhàp8@¡PÀ˜½¬¬L¡P 3™LŒµcÇŽ   K—.9ò±à tîÜ9ðå:zô¨L&»té’P(T*• ÇuñâE£Ñ˜••ååå%—Ë+++a J(ÎÍÍ…†††„„ ‹KµK£Ñ›ÉdMx|­­­©©©£££ 8ŽÃáƒ(++ë¿ÿû¿¥R)ì¬âqÀ‰åư•qãÆ "‘H¡PètºB¡˜˜˜àóù Ãh4¶··;ò±jjjþú׿  æ€Ï<óL__Ÿ———››Th6›¯^½êîîŠßW¯^ >°t äGáp¸¡¡!6› ¼H ºxñ¢Á`xôèD§&‰A*•*•JàcI$~°÷L$Mÿî»ïz{{777{xx@=!—/¾øÂÇÇçòåË  óõõ½wï^@@€L&suu…ªà''‘H`DØÛÛû³ŸýìÛ½rßq`X:000???:::===??ß×××ÒÒ‚Ãá<<<àzŒŽŽNLLðx¼ÙÙYˆ€" étúÐÐX,¾víècõõõuww÷ööz{{···wvvBLr™L¦Ñh&''GFFd2™B¡ðòò‰D7oÞ„É–ffF¥R]¿~øXD"±½½ýìÙ³EEE÷îÝo¢öööÅÅEÈùèÑ#‰Dšá]]]ƒƒƒ^^^wîÜ>‹Åb³ÙW®\ñóó;uêTvv6hzÍÌÌ$''òÉ'………—.]’Éd2™l~~žÁ` vuutà;w†††À~"‘844¤ÕjûûûW÷ ¿£ÈÏÏÏËËû¥ž0º_Åw˜Ú˜#™éÙgŸ]ž“@ 82™jjjêêê<<<öîÝ›‘‘ñ4m}%K,ƒ动¯¯ÇŽ—ó±ÂÃûP__ÿ8>–c=Ê"lXRRSRRò•õüÛ‚ðÁ¸ºº&''S(àc @TwàcÉd²ýû÷ƒÎgpp0ÐÌM&SzzzWW—Z­ÎÉɹyóæ¶mÛ­VkXXXyyyZZ𱀑ššZXX2¸eeeàЧÕj<˜––¦×ëM&Ó‹/¾h4«««¡xZZÆÇL&Ç»ººÚl¶#GŽˆD"…BÁãñ^ýõ™™àc±X¬àà`¹\îää´qãFpÜX·nÝâââ¶mÛ`\µ~ýúªª*‹Å²mÛ6‡“••…ñ±BBBöìÙ3??¿aË•““|¬×_ýôéÓuuu~~~B¡088x5bÊã€ïé陟Ÿohhð÷÷çñx—/_ …l6;>>–+auÔÝÝøX*• øXNNN ¦+ŸžžžAAA¯¼òÊØØ˜³³sRRÇkhhàñxŸþy\\\@@€§§ççŸ^PPË¡ÀÇ"“É!„Çãçççãããív»@ €ô²²²ãÇ/,,0™Ì‚‚‰DâêêÊd2a¡í:::¼½½=<$$àc1 ±X,•JÁû\­VëæÍ›ïÝ»œšš:22‚º}û6@ÈÊÊR(L&s||‚šH¥R˜0Ž!„t:Ýàà H$Љ‰>–F£ü³³³ R©ôÁƒ………‰$00p||¼±±q×®]*•êÆÀÇ‚œ<”Z IDAT2™ !¤R©t:‡“Ëå°–&“É€AE&“cbbT*Äh9yò$Ôƒêïïß½{÷Õ«WwîÜÙÓÓC£Ñt:Ýüü<¨½K$’¤¤$¨Ê`0€ý°Ãsýúu¡Ph6›^¶ŠÇâ |¬å ¤å™Wd)}%u©¦¦æ•W^yB~XÐÇÒá`çÎ|>ÿɦ>®é%bÇ+ò±ÐJä³U>Ö×6Ér >¸â`‡Ã92™ÂÃÃa0›œœìããó4m}e|Ãàà`Ø‚\ŽV9r­à˜F£9ÖŸžž°"ëi¦+Î=ÁA(((H$=e—ÿmAøðÃFcxxøââ"‰DÊÌÌ$‘H@âR©eeeðщD|>¿¾¾Hß E,ètº¨¨¨ááá………5kÖxzzšL&??¿¸¸8@€ÇãÓÒÒ¸\nffæè託—çææÆÆÆêt:àcåçç ˆ–™™©×ë!\yrr²@ ˜ššÚ´i“H$Òét ¢ sss\.÷ûßÿþÀÀÀÔÔÔ† ôz}EEE?…B)((€èNyyyëׯ‰D×®] ÉËË_¿~½Á` …˜aîîúªD"ÉÍÍÕëõ!!!™™™ƒá§?ýé_|ñüóÏß¿_­V±b+‚ššj6›'''³³³©Tª\./++c2™±±±r¹<>>^£ÑH¥Òýû÷öÙgñññjkffÆb±äææ.,,P©T‘HtãÆ]»v¥¥¥ÅÅÅ=zô(11±¬¬L«Õ*•ÊÒÒÒ¶¶¶ˆˆˆ”””ððð¶¶¶´´´€€€óçÏkíÚµ £¥Óéòòò\]]Add$›Í.++£Óé<€˜?·nÝo‹¼¼Hw „p8œV«…‰!Äc>fBÈÙÙyÇŽ2™lrròÁƒ÷ï߇zB&“)..N©TBïÀ0ƒO…^¯/))ªà'MhµÚ÷ßuäþdàèt:FS©T@öµX,˜è@pss÷,„ÜXÓjµ²X,7== RŽƒn …²°°àëë lA¨Ð`0H$¸¢p¼yóæÌÌLàc-..B~N2nƒÁÏÏojjŠÃáÀdÍÇÇgnn®²²R"‘ܼyB‹ðrrww_XX0žžž°`±Xp8øiµZ»Rsss 4ÍÍÍm||œÏç+ ø"“H$‹e6›- ,‚@Uð‡Ã‘ËåÎÎΫÊXßËàô -ǰJXôï¯t°Á°„µ$Ð!—ËÅݘýOO[‚'û/}³œO“;0âD1 8WßlZúä3ðôu.ñ˜úŠÌo¾ùfpp°ÝnW(X*èÕßèücCCÃOúÓ€€€{÷î!„ètºÙlÎËË«®®.**jnn^\\ŒŽŽV*•¡;w–””¨Õê×^{mI‘°°°={ödffÞ¼yœžB^^^Ç?}úôÆÓÒÒ=zô¸¶Äb1PÎ111555111þþþPÐjµîÚµëîÝ»˜ýO0æqöC—oܸñꫯŠÅâëׯcE¢¢¢*++÷îÝ{îÜ9„Vä?øAAAT*}ë­·¬Vë£G ŒÕj­««{ñÅM&Óðð0f9䟙™©¬¬Ü¸qãÕ«W±ü½Q ôõõíÛ·ïîÝ»6›íàÁƒ@€µÿþôôt¹\®V«Á°±X|èС{÷îíÝ»÷Î;<ÏÉÉI§ÓEGGoß¾=***))iI)°D$=zôH£Ñ`‰¿ýíoAè`ll «;Ûñññyyy³³³ÓÓÓPÄÅÅ¥®®îèÑ£­­­Ø¸ïììl4'''BÜ»w/B""„ÊÊʬV+„¤‡8†±±±'Nœ`0T*unnŽH$’H¤øøø·Þz«²²!ôÙgŸAè¶åEÀµe¿‘Hœœœ³´´4ø<­Ø‡ƒ—V°¿¿‚übÕj5p­0ûŸ`Ìãì‡.{yyMNNªÕj‹…éîî6™L¿üå/BëÖ­{ûí·!ÈÔOúS«Õêêêj±X€A´ÿþƒ"„þð‡?<|øð‹/¾€'¨Aö->øàÇüF£ÇÃÐÛÛ =ºv¢@‡Ã9;;Ÿ8q">>~xx8>>žÉd>ÿüóçðáÇIÕO?ý‡Ã-/…²Ùl###333މ0Âqsss¬;Û~~~Ÿ|ò‰H$ŠhµÚÆÆÆÖÖÖ‰‰ ìêà Ãùóça1†;!ð÷…‡’F£EGGÿùÏÝ,…BqêÔ)pgúḰ°088822rãÆ „PBBÂ_|áï“ÉüãÿXUU¯S …âøE˜ŸŸ¿xñbVVÖŠmݼyS*•zyyaCBBúúú V!d·Û!Ô Øÿcg?t¼ûi4šÑhÄŠ€ø[__Bèúõë###¬pûöíþóŸggg?øà¸6·nÝZh(µX~„P(”J¥Žù5Í… ¶oߎ2™L4m¹†þÝ»wÏŸ?Ÿœœ¬ÓéN:%—Ëm6Çûè£ l¬Z­nmmmiiÑjµ$iÇŽøÃ–—¢R©---D"1..KDMMM]¸páìÙ³Žõ`gÛn·³X,{…"áÙgŸýýïKÊÿsYÑ2øúúBßàÃÒÒRÇ<û×ÙÙ¢¢¢¶mÛÆ`0–¡Óé555Ë9`ƒ¿¿ÿŽ;X,ÖŠmÕÔÔ”””8Þˆ,«®®.22+H&“_zé¥Ý»w …B°ÿ Æ<Î~¬ËÅÅÅŽEâââjjjÖ­[·¤ÈÎ;7oÞìîî¾mÛ¶åÁô–/ C~æºmÛ6„Ð /¼SXXøÚk¯AÇáD…‡‡oÛ¶mIпÔÔTÐÚ„¶‰òóóÛ¾}{nn «««—(µ:ŒÕƒí°°°ÚÚZÇè| zôTáõIðoÇòM•¿¼½½¹\.LÿqöcøÇuC$ñx¼¯¯ïß.È‹ám6€ ‰222º»»wíÚ !ÄB …"%%¥ººÈÇV«Ò±üUUU¡¡¡*•jÿþýd2Y"‘`•nذ!99Ùjµbôôôòòr©Têêê*‰†‡‡‰Dâ3Ï<ƒ¹$;epp†!>Ÿïçç—““388XRR244„Iâòx¼C‡ݼy377·¨¨H©Tj4š……ƒÁàîî^[[ Ò˜è^DDĺuëÂÃû»»B =îhUUUUxxxOOf0›ÍÞ¾}ûÛˆˆˆâââÌÌÌ»wïîß¿C[·nœœ plPRR"‘H¶nÝj³Ù\\\æçç—7 Rõ!OOÏÚÚÚÔÔT°\©TÚl¶ððp‘H”˜˜x÷î]¬Zì*ìÙ³ÇjµbÓ°pýúõ>>>Žfóx¼ºº:`ë/1›ÃáÔÖÖÚl¶°°°¯<ÿX…Ð.‡ƒ«°üÆÂß»w¸uáááàáïïäÈggç»wï:99}òÉ'0}@~‹b0<<<`ͳ¢¢ÆO°øžŸŸ)ðW§Ó=|ø044T"‘À' ==½··«977·½½d=z4  wìØ±uëVWWW‰TQQQZZJ"‘¦¦¦`DŸ––1…±R …¢½½]&“ c}ñ÷÷ïéé ùúë¯{zz"„´ZíÇ322\]]ýüüœœœ°"aaaÖ±°Äþþþ‘‘¸_çççaö¤R©›Àò3Œ­[·îÞ½»´´tnnnyÓ¡¡¡O¶Ü±Å%W!Ô××»òŽ=Õëõ°UzäÈ‘ÈÈÈ#GްX¬û÷ï‹D¢åfoذá³Ï>«¨¨øÊóïh´‹]Ç«ÿ?7–Åb±Ûí cqqÑn·CHw£Ñh³Ùl6<^999P òãñx¥RÃá>þøã­[·"„À§ê]\\äp8% h0#„@ÐÛÇÇ5¨üöíÛeeeD"vÉd2D8yòd}}ý­[·œ£££cbbh4šÍfƒyFSSÓàà`qq1VÊn·Ã’©ÍfÃú‚ÊÈÈhiiQ©T|>?(((&&!$•J[[[! L¡ÈèèhGGGYYBK¤P(%%%'OžDMNNzyyÁÂ2ôkËûöíúúúßýîwáááóóóË›nnn~²åŽ-.¹ !ì™wì)dàñxþþþV«ÕßßvvÖn·ÃXj‰ÙgΜٺu+NÿÊ󪯯…lh» K®>Bˆˆ’H$àA2›ÍCCC‡¹:‰DhhhÀÊH$³Ù¬P(¨TêÌÌLEE¼üAªLÆRÀ&ˆ/Òßßo³Ù6mÚ4>>044•'''/,,ܾ}Ûf³>| èîî>wîœÏÇívûñãÇm6˜ ¶±Ùì   3gÎ8–y„Ö•Juúôix™wwwÿìg?ƒÏÁ¦M›T*“É„]mF£Ñh “ÉLLL„…¬žœœF³iÓ¦“'O ‚žžžììl˜ë96å—Éd—/_>{ö,›Í^±i8!O°Ü±Å%WòÃË̱§AAAjµº½½½¥¥Åf³:t(,,,--mpp!´ÄlƒÁ Õj/_¾ BeO8ÿ¡'N@ëX»Øâx­ÿ|ãåã¯;‰‰‰8nóæÍKêüZUþ.#Л~rÍ›6mnØ5ÿÛmø‡ëËr³±Ÿ¾Ùù_!!!iiiŽ“m„›ÍÎÎÎ^’ˆŠŒŒ„7!‡“‘‘±D,ŠH$fffÂdsʼn‹‹suu¥Óé0%vuuMOO'¡¡¡!##ƒÍfCú’+ ¤‰%ÆDDD,1!äì윛›K£ÑüýýaCúëV‹UA322\\\Äb1Èw}ÿ¢7àkjjt:ÝsÏ=‡òòò‚ý©ƒNOOC¦êêj„‹‹«­­ÅápD"1&&‡Ã‰D".—{øða‰Tàèèh·oß>„Phh(L•KKKC±uëVwàÀƒQUUµaÆêêê7’Éä}ûöAzAA‡‹…}ë 6ˆD¢¸¸¸ØØX‰SSSkjjà! Bûöí3v»ýÀZ­¶²²ò+«…Ott4,AEEEñP•ÅbQ(‘‘‘‹eI§Vñ8ài4ZVV|&÷íÛ §OŸ®¬¬„‘õž={¶mÛ&‰l6[{{;„IJII9vì¼ÒœœÄbñ±cÇrss;6<µSEµk[@±S ;²ÉÙD÷-Æ%­v213vzÉ$éét2‰Ú.mH4£FÛ7PP”Ev•}¡ ¨¢ ¾?Þ™ûÕW 1dÒ3_=ä‡'÷œó¾çÞº÷,ïû<žžÃÃÃR©x³¨T*” *•úé§ŸB̪­­­@ `³ÙŸ~úéÒ¥K?ýôÓ   Ë—/kµÚU«V „««krr2ÇËÏÏwuuýÞfi4ÇÛ¼yó–-[Ølv]]M………1™ÌëׯWVVZZZ¤œú…nÙÿ ggg;::`³õ£>‚EDDD}}½ŸŸßÝ»w9233sÿþ} …’””411‡Y=q5­­­R©´¶¶ÖÜÜ<33óàÁƒ!33³ááa777½ÏL&KHH¸sçìn—””¼ñÆÀÁœÐÔÔ¤T*333¥R)Bhrr²¹¹™Ãá@ Èõ;vìܹsFFFwïÞ=uêÔ‰'BíííZ­V¥RÁ&PSSÓ÷6+ +**> ‚ "‘Œ‡¦ðx|```aa!d³Á«ÎÌÌ ø| x)LLL8ŽÞ¦>™L¶¶¶Æ"ï0°X,½£+2™Ìáp°ÝB8ô…WW×Í›7Ãep@¡P€1†ÉdBh—……çA¹nƒl6›Åbé=š‡Ãáè’H$+++H%ΣÚ,f<Ö¨áñxKKK¨Ý»w+~a`‡JD"Òÿ  {Rf€`€`€ÿàg][½¬q<ÿ?eM÷2;á¨ã{Y~A Î ÓÁ [’““ÜÒÒ¬zõšÕ‘Hܸq£D"ð½Šb±8--ÍÑÑ´0~PÒ•«««‡‡‡ÏÒ¥Kíìì222LMM{{{7nÜAA;vì R©qqq µµ•ÅbåççÃß¹¹¹ŽŽŽ­­­qqq<¯½½}Ïž=b±„¨ìì좣£[[[W¬XßÑÑagg—––&‹±È6Ýqسg»»{{{ûâÅ‹u‡ñeƒ& —,YòôéÓààà{{{;;»îîî>øRs;;;srrÌÌÌvíÚUZZ’˜˜ØÑÑ‘™™)‹‡‡‡W¯^M$íìì 211{ÄbñãÇ!†ŸŸïííýèÑ#„N‡ð,”””ŽŽŽeË–-Z´hllìÍ"„999ÀkaaajjšššªT*óòò¸\®­­-0|ÊåòM›6MOOK$’%K–$&&zyy¹»»»¸¸¼¢zYY@øðÃ6mÚäêêÊd2³²²„B¡……E__Ÿ¿¿ÿ‰' X,ÖòåË/^ìææÆd2úúú@÷{nnnÏž=ÁÁÁýýýÛ¶m‹Å>ŒŠŠJNNvtttvvNMMõõõ™™t‰DråÊ•¥K—~ùå—[¶lñòòúä“O fggÉd²Z­–Ë嘀¯¯ïÍ›7½¼¼¬¬¬::: Ç5**êßÿýßÕjugggdddqqñääd||üÍ›7ꪪòòò’““!UazzºªªÊÇǧ§§ÇËËK¥Råççóx<@ô¾ééé"‘¨··—L&ÛÛÛ/Y²$&&fxxxëÖ­ÉÉÉ7oÞDÅÇÇs¹ÜÔÔT *•tçÎ@0==­ÑhärùÀÀ€§§§‹‹Kaa¡V«}ã7®]»¦P(¢¢¢îܹ³nݺ .ddd@ ¸X,þÛßþ–‘‘!‰.\¸ÖÞÞ¾{÷îááá±±±U«V) ¹\ž——'“ÉòóóGFF^¼xª0 ãwÞimm•Éd;vìèëëëèèØ¾};ð_¹råeÍ"„ðàÌ_|!“É’’’Ôjµ›››\.Và'OžÀÆúñãÇcbb@’žÍf=}úÔÖÖöÕÕÑéGh4š¤¤$ȱÎÍÍuqq&‘‘cc㘘˜£Gzxx9r(i4ZTTTgg§@ 022b±X&&&ÐN\\Ü‘#G`Ÿ–Ãá\¿~ÝÞÞºV(»wïí …‚ÇãU*ÕÔÔb@ª••ÕÈÈȳgÏ,,,ärùÁƒ§¦¦ S—ÃáôööVWWCº„£A¼‘D"Ul„£££ƒƒÃ·ß~«T*…BáÉ“'ׯ_íÚµƒb_ååå_~ù%œ¨ÖÕÕ}øá‡MMML&ÓÆÆfjj †ñܹsÑÑÑãããºZàK[[Ûž={ÊËË!v­¼¼¼¤¤äÖ­[}„‚”],¬ 8ÌaÀ! B»¨TªJ¥‚P©Td2Y¥R™››Ã×snnîéÓ§®®®æææÂ’ Ökmmmgg‡W8®±±177wppÐÃÃN·^Ö,Bˆ ÊËË333ÇÆÆðx߯Æ8)à“daaå©©©ššà!‡ü"@P__Ï`0‚‚‚þã?þÃÝÝ}nnîüùóÍÍÍÃÃÃpÀ*•JoÞ¼ ¡¡¡Z­¶¶¶ö«¯¾zþü9”¿õÖ[`ÛÀÀ@WWDƒ€×7x<‘H<<\ïæ™˜˜DDD „ètzLL F{Y_z š$)**ŠÏçcmmmE"‘®kÐ>„ŠƒkX-@¡wr„Q’`033ÂúððpÝ€‘‘QDDDDD„Þa+—ËŠŠZpÜœ¡ŠîI.Ç‹ŠŠ255…ÿ¥Kî¥;h¯sËìíí!Êm~×ööö!‘HÄd2! öãW®\9>>Ñ2¡ÜÜ\„‡óóóËÊÊ ‰D*• ¨i9Ž››[VV‡ëëëƒøO‘H„ýbâããGGG]]]!¢†N§šššæååÁsM"‘¼½½ASÓØØ8;;L„~BÁÁÁt:=<<|~•ÐÐPxìt]Òjµ8nË–-@šº`_t:}ûöíºa.¸iÓ&¬bOOOVVBs !TPPàVkåÊ• k…Ãá0›””###ÈðôôÄBkvîÜ™””´uëV …¢bPE£Ñôôô¤§§CØ6‘‘‘ÀÐ9ßHpèííÅò¦BðhõôôÄÅÅAÈüüA{[633öÏï:>>>((èàÁƒ+V¬€·õ+ ÆS©Ô¨¨(°rݺu¹¹¹AAAZ­öÚµkccc¶¶¶d2yÓ¦MÏž=£Óéµµµ À9ÓÑÑ¿ïÖÖV‘®¼½½áfÀâÙÔÔ´««+33äXÿüç?ƒÞÞÞ@@’›› UEEEaaa f WåáǪ€²±±Y³f •J .„µµµ››[llì‚}-^¼˜F£aAœ\¥RaµZ-„c®!„8ÎÄÄæV«««K$I$*•ú§?ý fr666nnnÕÕÕ<oÓ¦M›7of³Ù gbbÁEÖÖÖXF#‹Ïž=+“ÉtáÌ™3ÕÕÕó}˜˜èì윛› …,\¸¾¢¢‚ËåÞ¸qC­V/8h¯sËúúú`27¿ëòòò;wÞ¿_,÷ôô¼Ú`üììlww7| 9òÍ7ßÀºãßþíߺ»»ÛÛÛi4šV«µ´´£P()))À”L&“aÄ`0fff|||@S!ôâÅ x·×ÔÔP(àq„’ªªªåË—ÃŽÔ•+W>ùä“ÙÙÙ»wï~óÍ7 -™ŸŸßÖÖÙ zUüüü¤R©££#Bh``à›o¾ÑÝ;ikk#Z­vÁ¾ž?.—˱ŠK–,¡Óé«ï?„¸!ÔÐæV zÑjµJ¥255µ¢¢!ÔÔÔôÙgŸµ¶¶ŽŒŒ:tèàÁƒ@2 Ù”“““IIIUÌÌÌòóóMLL¸\®î lݺU¥RøÔ|_0Ü¿XR°ëëêê^6h¯sË0Ìﺡ¡ÁÄÄ䨱cPôjƒFƒätôÿøÐðx<ǃ9/\zF¡åË—;88 „vïÞmggB›6m233322¾;ÉÕÂ@"‘¤×!“É|>Á*8ŽÇãÍć)‘H|YE`½Ò«­Í T´´´„gp æ‹/]p «E"‘àÍ=ß’ùÀápPEOÑA †Þ´ n …B™ïË‚½`×ëÅÕé æëÂÔ IDATÚkÞ2hÁ®!4í,XëPIáp8ˆI"ºÝ˜‚ºX¢ø€ëçO„¿×0¨ˆ‘+ë²,3 p[o"Uà÷ƒæ ø‚¹öSŸÀP,˜õêQ¸\®î cÁ žö`~½ì–ýÐ3¢WØI P($I£Ñ¬_¿Þ××W$555a…ptt ©ªªBùøø<{ö Ç8pÄÀsrrD"Qmm-T™™™ILLÌË˳´´„3À{ï½õš5kÜÝÝ>|ˆu‘——·oß¾©©)])¸^£ÑlÛ¶M.—uð ™™™Aàyaa¡¯¯/仩T*333µZý»ßý...îÆ‰„Ïç÷÷÷oÚ´éáÇ0‰Ü¾}ûÝ»w™LfJJ –Ú¿{÷îèèèÁÁA ŠT©TŽŽŽ‘‘‘»wï†<úÒÒRKKK699iiiyôèѳgÏnß¾]Ï$KKK˜¤÷õõŽŽB!°n,[¶ X¸`B6lˆW*•o¾ùfDD$ B±X¼víÚˆˆˆÒÒR¬¨¹¶mÛváÂð!´~ýúÊÊJ„›ÍRSSu÷Àaaa8.--ÍÉÉéÑ£GðéÐh4û÷ïg±X^^^Ë—//--Õjµ0Í Þ¸qcqq1 >p÷c^äääDFF[Ø‚vb®ý磹mÛ¶·Þz !411A¥Ra‚…R(”/^EIVVÖûï¿ïëë;77wæÌX†;v ~"X•+W®àñxH_”H$À@rõêUXaaÐØõ………Ož<)½ë!}ÞÉɉF£™˜˜‰Dccã#GŽøúúÂ/ÌÌÌŒÇã9r$,,ìÈ‘#>>>¿ùÍoà±+))EuCCäxA–óÌÌ ÆžåàààêêÊápZ[[ÝÝݱƟX%%% £V«Ïœ9³f͸+P8==]\\üá‡"„.]ºÔÒÒÒÔÔÓ ¡¡!¥RÉápàe€UY»víwß}³`PkÆ:óóó;vì$Na×ëBïúñññòòrOOÏšššK—.ùùù)ŠÂÂB –}úôéáÇàÑ„ò7žQYY9>>~ûöíââ≉ ̶êêêù&a,,,„ŒíÚÚÚýû÷Ëåòúúúææfø ùùùi4šúúzà€î;¨ÂårOœ8ÇJX!ˆøÁK¨BZ­–Íf/vžƒ¹ví™Lþæ›oh4Lرòä hÛvuu!R´ùÐõ¢¤¤¤³³øèæÛ©ëš>óòòôROõò9±¹a\\\\\FËÎΆ}3 ÉÉÉ™™™~~~º…G ˜™™ÁA¡^×@V6ÿz"‘¸råJ‘H”››«7ûÎÎÎNKKÓ›*æååeffõÔÒ¥KB»víòôô„·MYYYÁ"ó1==]oºàççG"‘°OxåèZ» I`¶n œ ÎÀ°°°+V899EGGÃ/cc㬬,Ø¿Ààáá±råJ nصkFÃÈÀŒŒŒ0òòòÀ€ÔÔÔ€€‹•——$ºFŠD"{{{H¾Õ¸¶ +W®\ºt©îtPÏÎù놌—MñàŸÿ ±A®®®0 yƒ61B¶.õ …ÿ Æ¿°eii©»œÄ&&&FDD˜››ëÎô7mÚ477§Õjõ«_Áì!ÌJYYY KóJ ÐŠŠŠ èííÉŒ'Ož€GÿôOÿD¥RÇÆÆþÁÙ¶Á5à‡y7B¨È´Z-üß_ø¡¡!¹\îàà@£ÑÞ}÷]`N²··§Óé...ï¾û®——×»ï¾ëììüàÁˆ“)**ÊÉÉA=þöBp8œ­­í‹/BCCaƒÎÙÙùܹsðJOO‡“__߸¸¸ØØXȵ±±Ù¿?“ÉÄápXã"‘è׿þ5NzÌÂÂB•J…µpõêUƒ]`¨««³²²Æ–îØõ]]]aaaPÿÅ\îîî†uxôìÙ3Ì5~$ð2™lffÆÔÔtÞ±I7d‘3 ¥RÉ`0€DHåär9¬A!ddd@KKKøÅÇÆÆþå/Aa‚†CCC4H$Bp…«««@ 077×jµXãsssG©TjµZ,ÆkañâÅ@-´aÄ^@’îõsss<vk sýSæö‡?Ä€€.—[YY©Õj÷ìÙÖää¤P(,//?qâV¾yóæúúzfjj ‹ {{ûúúúÄÄÄË—/Ãܶ¥¥ÅÑÑñéÓ§õõõ§OŸ†>NŸ> /’’’GGGµZ ¦ëׯŒŒ´¶¶"„ ñŽŽŽ·ß~Ì€$wÝ¢¢¢ ¦’â¡ý‰‰ ˜jÌ¿¾¯¯O,777ƒ1𥧧ƒË¡ÙÙYx¬@‚Å eò“ᇆéÄÇÇö{ZZÐö!„ÂÃÃáÀ<--íç0ò§të ðhݺu˜k`€`€`€,ƒ­›tÿþ»eu™9pŠ® ½Ð¥Ÿ¤/~V¨Tª¥¥%dÒÉd2‡í¾¨F£áóùfÆ r¹|zz”±‚ƒƒI$ÒÐÐÐïÿ{ …òÛßþÖ××·³³S*•B¤%Ä– „„B¡L&ƒ° Ug³ÙkÖ¬ill´¶¶–J¥yyyeee®®®“““ÐãÌÌ̦M›âã㧦¦Þ|óͨ¨(¹\žíææVSSÃd2­­­áxâ:t øAÜ·oŸT*suušš1Ï;wîTVVfffšššOLLtttØØØØØØÌÌÌÌÍÍ…‡‡»»»_¼x!ÄårŸ?"ˆ …Á`P©T:þñÇ«Tª¦¦&++«ªª*ÿééi##£þþ~‹uúôéàà`Ÿ>ø€L&ŒŒ @ÆNtt´P(466¶±±9pàÀÑ£GóóóA†J¥&$$|þùçGûë_ÿzdd„D"™ššªÕj©TúÕW_驃ð‹ßÐÐÀb±ÜÝÝ›››ëëë{{{!ƒt Æõë×ÇÆÆîß¿¯Õjž?dX¼ŠL&ãóùÃÃà Ož<ùâ‹/¢££i4(!Âçp8ÍÍÍuuuÏž=«««ƒXo©TÚßßoll|ýúu …RVVfÀ="„¦§§!’ŸF£ p¹\8½Q(÷îÝ{ôèÑÜÜ\ccã|ŠT~)ˆD"‡;v옓“SCCÃÜÜ\``àgŸ}|ïÞ½Û·o‹D¢ŠŠ •oii!‰ FFF÷ïßohhõ __ßÓ§OÓét&“yîܹññqµZ­Õjïß¿___)ó333jµºººÚÎήººzvv¶¨¨ÈÞÞþôéÓ!!!eee -ÛÙÙ9222222<<, ©Têää¤\.ïîî.** ‡œn©TÚÛÛ;:: ¿Š¿ô¨°þAz øß :¾sçÎ-[¶`K0ssóùëµùÁŸ€ÂåååÙÚÚÞºu+**ª¡¡d&Þ~ûí‚‚‚òòrÈ&ÀÉnee¥P(*++ëëëcbbbccOž}útvvÖÉɉÁ`@>t__BÈÝÝÝÍÍ­»»¨E"‘Z­f±XÖÖÖÀëåå%—Ë ÄþÓétkkk‡Ã`0ÆÇÇcbbÁÀÀìhèŽh ùùù-莮ïà&‘Ht:ÝÜÜ|dddïÞ½aaammm¦¦¦þþþ½½½111˜|||¬­­!Jƒ……EXXXww·••Õàà ŸÏ§P(ááá Þ¼dÉ’®®.ݩ˂ÿxöíÛwãÆààà©©)¶lÙ2GGG*•Êãñ@ÈþÆR©î›ÍÖh4CCC‘‘‘111íííqqq@V ¬Ë–-S©T333qqq]]]YYY*• ÓBBBbccår9:88@;ÉÉÉ‹/®««Ãáp«W¯vqqéîî.((022¢P(žžž|>ßÜÜœÉd¦¥¥oß¾D"Q©T‰‰‰äää«W¯&&&Ö××gffòùüÀÀ@HÎzçwÚÚÚ€bJ(òx¼êêê©©)2™SZZºeË–7nlß¾ýÖ­[ -åííÌf³3rãÆ­­­ááá¶¶¶ÎÎÎ, ØDÄbqBBBIIɆ zzzh4Zll,…Báñx±±±*•jtt4''§¶¶Øu‹‹‹ƒƒCOO‘H|÷ÝwŒŒìíí«ªª¢££šæñãÇ›7o¾zõªZ­Þ¸q#‹Y[[ŽŽúøøŒŽŽ†‡‡‡††Bn~~~>DGGk4P€ŒŒ,))Y³fÍäää’%Kjjj6lØÐÞÞîææÖÖÖ&‘HFFFæææ q".— ´P?ÄœœœÊÊJø•Ô××çççwttX[[«Õj ‹ööv`AÎÊÊššš’H$§N‚ÊçÏŸÏÉɉˆˆÉd<O¥R={¤ËÆÇÇ“’’._¾¼nÝ:µZ ØOŸ>urrb±XŸ|òIff&‰D:þ|zz:Øâp8`oo¯ÕjY,—˵¶¶†«´´´¯¯¯ªª*  ½½R„Ož<ùüùs'''FÓÕÕ•ŸŸ:tèV«=wîÜìì,¼ƒ‹‹‹ÃÃÃàN“H$¥R‰JKKƒTo`Ô…„6¹\Îd2çææ”JåÁƒá'ngg<Õ>>>A*•¶´´deeºXzzúää$ csssJJ ™L>{ö¬»»;亭ZµŠËå.[¶ŒÅbUTT´¶¶º¸¸”––®]»2G`T===!¯„ÅbA"šH$¶©÷Þ{ïøÃ¾}ûöïßçÎÈC *¼ãÇ_¿~ý·¿ýí©S§úúúâãã©T*pþæçç‰ÄÎÎθ¸8*•úÇ?þqÿþý°CÄãñÖ¯_?77·ÿþ,†OLLlkkÃ6E§¦¦¤R©R©$“Ér¹è\»ºº¤Ri]]‹‹ –Ò¬Ñh”J%Ø]TTÔÑÑñàÁggçêêjØýºråÊŸþô'˜à+ „ÐÍ›7¯_¿^WW÷ÙgŸ+!´£V«“““££#ŸÏ’cèúêÕ«|>ÿã?622a0ýýýðJ+++[·n]AAAOO@ P(ÓÓÓ‘‘‘i8==ÝÓÓ#‰BCCƒ‚‚”J¥“““D" ›yéÒ¥p¼}üøñóçÏGFFVUU)•J_œ››£Óé‰诪««••dö‘Éä²²2™LöÑG±X,˜ªNMMÍÍÍ©T*  ÝM8›ðàJ¥‚ÞÌÌŒD"Ùz­V‰R,©¼055]¶lÙ7–-[vïÞ½O?ýthhˆJ¥Þ½{÷ĉÀSµvíZxáš$¼ÂÉd2LLL¤¥¥544(•Jhk>Ä_~ùå_|ñÓ¶âñx&“‰Çã!@dy!£ÇW‹Å"‰fffÀõ—Áq§Ñht:Îøà¥½aà „^˜L&Ä ¸¹¹íܹ!u¡kgÕªU„=3(Ǻ†¿gû­·ÞÂáp,K$Á 4‹Å6lX¿~½P(Äè$á* E"…B155"‘º‹ŒŒ$‘Hp PhB­¨¨(° K¡†ZØ4F£áñx:þÇ?þQ×<Ýaô÷÷ÿ×ýW]_€ŒH$îÞ½ ÃîETT{‡ŸŸþøcƒÑÜÜŒå¾nܸ1>>žH$FFFîÝ»÷æÍ›ÙÙÙr¹üÈ‘#§OŸÞµkW@@°d1 àu9uê¥YXXÐét™Læëë»jÕ*??? `òºÊuëÖ%$$tww8p@­V/[¶,22R*•‚Á÷îÝ{…Áb±xùòå;vì8þ}ú!$•JûúúÀúàà`¨H `£•Á`”——÷Ýw0-{óÍ7áëI"‘Èd2·8;;ƒú<ƒÁm…øøø[·n½÷Þ{ …BÏNÌž;wîDGGƒa`|›fggËËË›››= s hÆáÅ‹7oÞ¼xñ"<@ííí° #‘H0=066>~ü8pìÉdƒaddÄår÷îÝ»gÏ‹UWW?~ttôòå˺3™L¹\Îãñ~Á¡>ø!´jÕª÷ß? !”ÝÛÛ+jkk-ZäêêÚÖÖŽH$¸ÑD"ÑÛÛûøñ㦦¦ði†Á Ü¿?F‡ü÷?XÁÁÁJ¥òéÓ§mmmÓÓÓ „_"""¾ýöÛE‹aŒ¨¡±±1“M.— 3JÖßßå¡ÙÙYø8jµZ.— sÝ##£ææf™L£0>>íà 4jLLLV¯^ýõ×_#„®_¿~íÚ5„\.ÿë_ÿ O¡\.Þ¦Ï?ÿœÇãÉår°sûöí………zv‚º‹.}í÷`íÃ8ˆD¢¸¸¸ÒÒÒ€€Œ!TWWwñâEЭ8tèìµ¶¶~þùçÑÑÑð]ºti||óˆÍf+•J`%Å ?|ø°‹‹ ÚkìââB¡PzzzB§Nª­­­®®æóù$I,ß¼y‡Ã)ŠèèèââbpD(b7zppðСCàæµk×ÚÚÚ¬¬¬|öŒ…„„Àill vq°öa.^¼(—Ë{zzÄb1Ú`£äééyáÂFÓÞÞ¯X‡Ãd2¿ûî;Pw‚ I.— ü“™™YOOfpSSShhèåË—kjj^ß``­µ³³{üøñÜÜ\YYÙìì¬B¡(--miiyþü¹Ï©S§h4Ú“'OÀ‘ .Èd2¸Ñ …ø  …››Û“'OµZmYYÙ˨Ø~`óDع°´´411Á”Ò ‡Ã9;;ÿ"æ=!0“fky<Þ|>c½?þ›ñ2ƒáŸ<ï5ceuIËÌÍÍçKüL „††FGG×ÕÕmÛ¶mnnnppÐÏÏÏÙÙÙÙÙ999ôÜ$IBB‚D"€‰§££crr2ˆåyzz>zô(33S*•Êd²¼¼¼ŠŠ ™L¦V«óóó{zz4ÍŠ+ªªªrssHi±±±ÐÑêÕ«Á€àà`2™ü«_ýª¸¸8...%%¥««K—³ê½÷Þóòòjiin-Ø?;;»k×.‰äää¤kHHˆ‡‡ÇÀÀˆG888$''wttàp¸ÈÈÈêêꤤ$°!äáááîîÞÙÙ Ûc D¸víZЃm!„ŒÞ£G¶nݺhÑ¢††]ã—.]š’’ÒÛÛ›••£„Yëåå•™™éààó$½ëêêrss===Á`3330¸··wddD"‘„……‰Åâ—ÝŽááa(ïééÙ¹sgEE…P(ŒŒŒ® ;;; bùY¿{÷.ðVUUYXX‰ÄÜÜ\''§îîn¹\nkk›””ÔÝÝ}çÎ++«ÔÔÔ3gÎDDD@pðêÕ«ŒŒ8ޱ±ñåË—aÆ700¯gmm=66[ÉgΜ½ XG`BÈßß¿³³S­Vãp8wwwØ8566>pàÐL …B¦§âÕA­îùóç¯c|||ww7LÒ1ûBÉÉÉ·nÝÂìÇãñùùùYYYñññCCCl6ûŸÿùŸÍ FÏÚÚZ£ÑÀGY×ø¾¾¾Çb£´hÑ¢ù—111±¶¶žšš&Îù âñøºº:{{{<êÔ)‰DòƒnGnn.”c·Üìéénà±Ã8X]±b…V«‹Åjµzrr’ÉdZXX€BiEE‡ƒ¹9‡ÁØ2Æãñ …6ŠFFF€Ü#Í277‡Í\&üòË/B‘‘‘À¨‰uXYYõ÷÷cV™˜˜ŒŒŒðù|…BA àg­T*kjj@; cÉ‚ê###}ôQffæëØà6ÂìGòfÿýû÷×®]{èÐ!È377‡ý$°Þ‹zÆC*„áÃ(MMMaR±°jáñxóÄãñr¹ÇŒŒlذá/ù˺Àu‹ÝÂíÀÖOàïÏþ`!„`KC*• :uêÃ?¼zõª···•••J¥‚ Ð.+..ÎÎή¬¬¬¬¬\¾|ùW_}ƒ%“É@.!äèè(—ËSRR¦¦¦`#®©© ‚jjjΞ= ’µ%%%°ûµ´´€qqqW®\«´Zmss³¥¥%Xøî»ïB€ÀÄÄ„““¼>ÜÐЀÙ?33“™™ùðáÃ×±ôB€" ìß²e ú/frÌþÁÁÁo¿ýöÊ•+ ØÚÚúûßÿ¶|°Ñ“ÉdEEEzƧ¤¤ ÃÁŒROOÏ;ï¼£Õj‡‡‡-,,@s~ƒsss111ýýýNNN8Î××÷ÝŽ“'OB9ܰۙÞÇê{ñúvll,œ0¤¤¤`ú"K–,ø m~ü´“åïµßÎÎ^x`¿µµ5BˆÉd‚Ì fÿkâçžéÿov7£¢¢ÂÂÂÀß_±±±ºÚv /caa‘œœüŠ£ =è­D A=-<‡¤¤$.—ëââÇv‰‰‰óù¢ øŸBtttBBÂãÇ“’’D"@ˆ‰‰!‰o¼ñFKKKff¦••U]]ݺuë¤R)lÆÅÅMMM …ÂÎÎÎÔÔT[[[;;;§Õjóòò¤RiTT”­­­………B¡ úàƒºººûúú@!ýÖ­[¶¶¶ÆÆÆñññFFF6lèíííêêÚ½{÷7àC••UZZì—ÏÀoIDAT/8ÇKHH=ß_zè xgÏžMIIár¹ ÓÒÒâàààââ¢R©@ÎÄÉɉÃḺºâñøÒÒÒǯZµ t‘÷îÝëèèÏ Çãp8ÑÑÑ ŒÛÝÝmccƒÇãcbbÈdrFFÆ_|áééyûöíU«V‘H¤ÆÆÆ¤¤¤ÒÒRçààÀáp|}}ÝÝÝétú7‚‚‚nß¾½zõꪪ**• 4$---Øa€ÿ˜ÀÓéô¤¤¤ÉÉIxnBÓÓÓk…}ìÚÚÚ&''±Ùå®]»Ôj50yô÷÷¹»»+ŠáááÉÉÉsçÎÙÛÛƒ |:ù|~WWWKKKqqqzzºî¿J¥‚w›Í¦P(ccc@ºüðáü¼~ó›ßXXXH$’¥K—R(”7ÞxVÑÑÑ&&&l6[÷\Ï^x™LvÿþýGi4š…BÊÇr¹¼¬¬l}_ x àÜÜ܆††Èd2—Ë¥P(\.·®®B2úúúÌÌÌ~òTF 0À øG!99Y©T …ÂE‹Aô´üxà›ššþüç?#„ׯ_ÿKÛcÀÿ„‡‡›˜˜GÅ/m‹`À+ñüi÷ HSóIEND®B`‚jas-2.5/images/device-2012-11-18-jas-trinks-out-big-thumb.png0000644000175000017500000014006112054221644023352 0ustar giovannigiovanni‰PNG  IHDRÈU%µ7àsBITÛáOà pHYsÄÄ•+ IDATxœì½y@SWÚ?~r³¯$@„@Ø÷}UYTÐÁ}«ZµjëÔ¶o§­Ó™÷7Ó}¦;íÌômíæØÚj]PQTD\d‘}„-@È’ûýãéÜÉ‹hÛùi·7Ÿ? yîyÎyžsNî=÷œgAÈ;ȳ¿“É|>ß`0¹\n0fffB C&“MLL|¯2Úñ=B ˜L&Glwo¢Íd:Ã8¦Ä-3ßµʬï^^^CCC7nÜŠ««ëÚµkq'‘H8ŽŸ;w®³³óh`Ç,Ë××·¶¶'“vý·Ÿ›ËHbÆ­ƒ/ªn]F9Ä- sùªs‡‰!nØ<†,@×^O¢Ré.2ãH¿æö„f[ojj*—ËOLL$ˆ™™™îîîr¹\(655Ù^²ãç*•êêêÚßß_ÉöH¼‡þï[ÏÔµ34'±ív@4ÃÝǪטF,ï°ñ³Ÿ°äÁPøM¬¾¾>//¯ÐÐЯ¾úŠ šL¦_þò—§OŸîííýì³Ï†††¶†v|ÿÀ0ÌÓÓ³««‹ à8~©gØl±Þ‡KÛrS]wYUyÔ)«‘€öõ¿ÿõ(ìîîFùøøØ6`2™^zé%£Ñˆãø_þò—ÖÖÖ¥Œ?xzzvwwã8NP¬8ºÜ=2¡7Ú# Àv@4ÕIÌ Š5OŒXõ:§¬R³j f5’’âëëû·¿ý 0Œððp@€šœœ¬¯¯×ëõA5;~0899ñù|£Ñˆb0]]]VI’µœD¡ ©n]ÒõÞ##«!„Èdd±|/"Ûñ$ þ¹”vØa‡vül1{ñŽJ.û%>Ýã}­-—Ž>‘ìø9`öÎ;Bˆåj° „#áY¬_¿a2iƒi¾`ÓöC;î‡9&–Ål´X ¡Ây>Ò™éò!Žã åÑHÑί:¦ f„uÆô½‹jÇO sM,“ÑjA‘2Á¼þ )‡6â¸U§£zxL¼ÛµsՖ׆¨ZÃŒõ»ŸJÚñ ³­Bî‘™nÖ.É >ÐG qää„s8¸£#g\™;ÿBËv|PÕ]åaOÕh4NOO•¬X±¢±±qVÍ$Ò쥛\.7›ÍñññP†a©©©‰D©TZì[m?e̱‰e1#Y&ëØÈø™3£GŽ?>vòäèÑ£ã§O«››¹w|… «ÅL”ß±cÇôôôK/½$‰Ç©©© L&ð¸¸8‘Hûúë¯ÓétŸ   à-..öôô$j MMMe³Ùÿõ_ÿõ=u€s? CÚo¨uxó.‡¿¼†›¾^NQ¥Ò¡mó^|:´tË¥™O,æêêªÕj###™L¦Z­vppËå...Ï?ÿüØØXooï£>úÁp¹Ü°°°¥K—êtº‹/^¸paV 333~~~ e``àáënÇCÄœw,ƒÉd4ÌÌü©×0º~›‰B1"dqs«*Z²mØ83c¶ÌØÞ± Cww7“É$‘H†Áó®µµõ‹/¾‰D¾¾¾‡îèè°X,ýýýþþþ'NœøüóÏcbbî®ðóçÏ8pÀöª?EÌýVØì!§b˜¦K}yF´tË#š/¿°¬Ûx¹Qe±Z§ò‹ïp«ÍK£Ñܾ}»³³S§Ó­\¹rjjª¢¢B.—?ýôÓíííÏ=÷œX,®¯¯ß¾}ûáÇwíÚe6›ÿô§?!„¬V+ŽãD b±855•Çã }`ÇCÀ¡¡ùÛÌÿZ7oèEãʱ%%̧öÜ^¿çlÛ0‰„pM+;µåwó2™L“Éën§V«B\.W«ÕZ­V6›­Õjét:†a÷2‘€ž­ý†?E̽ƲXB8B$="é1¬æNo—«7-毭slïX¶°.0«BÄÛ¢V«Eyƽ`ŸR?Ì1±fÌÿžX_ê8\¾Oos—~ÑŠÖÎA‹ùëí+û>–÷Ç\˨#ìQ•:øPÛ¬±-c5ßï®c‡vØa‡?¼žüó-ƒ?CæÜq°Ã;ì°ã¡B™ãõö§ˆŸ"?ƒñC‹ð`ð³Qäg2±ìø±Á>±ìx(°O,; æ0M~P‹Å®®®ÞÞÞjµ:::Z¯×?¼ 4Ídz`þ4->>žÏ绸¸ˆD¢‰‰ ™Læçç'“É4MXX˜Ñhôöövqq}PM?(E¨Tj||üÔÔ”T* …t:=88ta0ÁÁÁjµ:<<\&“éõúððð©©©؇qkË–-qqq}}}8ŽK$‹Å²cÇŽ‡Ô‡ÃÑh4ß\îÛA"‘¼ôÒKúÓŸ¶mÛvýúuµZXWW—˜˜ØÒÒb6›£££Ùlv__ß_|QSSó ÚET‘U«VI¥ÒÉÉÉ¥R©Óépwrrrttlll´X,!!!W®\ILLlkkãp8íííÿüç?HÓè{xJ¥R½^ïààðÓ²‡áp8 Åh4^¼xÑÃÃ!TWW×ÓÓÃb±ªªª¬V+F“H$÷7úaqûöí™™™ÀÀÀÏ?ÿÜjµzyyét_[x{{ùå— TeeåÌÌŒX,~€­?ÄG!ÇÓjµ‡‹Å‹¥©©©¾¾þ!µõ`… ÅÇÇG¯×ët:??¿C‡‘Éä¶¶6 Ã***V¯^]SS300ðñÇs8œkžÿquu ¬ªªrppð÷÷¿}ûö±cÇ„BáÀÀ@ww÷©S§jkki4†aZ­600°¹¹¹££ã4ýó‡Ãù¡Ex0øÙ(b+´ã¡À>±ìx(°O,; ìËŽ‡’cƲZ†MãUÓˆÝyúGRôWŠZ†€®ÿoÛÄåã?´øÏÃô’2~öð-É$ÌþÅ-Ä€q¨—î*û¡¥°ÃŽŸø|þ-‚?ü¯·ÂåË—ÿPrØñ3ƒ}»ÁއûIJã¡À>±ìx(°O,; ìËŽ‡ûIJã¡À>±ìxxˆËÿ?¬ vü›¾Žè”€Dî¡„wÊ*”?}ˆ¤èú)N·X­V‹…J¥Â •Š‘H8B3332QètºÑh¤Ñé8ŽÏÌÌàV+™L¦ÑézŽF§›ŒF„NÇ0 Çq³Ù ,f³j6›Í™LÆ0„Ùl&S($„‰dú—— F&Óét³ÉdÅq …‚pœL&[qÜl6ÓétËÌŒÙl¦ÑhPØh4R(”¯K"dµX¬8N¥Pà•JÅÈd„ã‹ÅŠã$‰D"Q©T„ !½^O£ÑŒF#N7šLtÍd2AÍ $JÕéõtͶ*B~£ÑÈ`0Hf4­ö¤,÷ù™gž‹Å&“iË–-b“É´eóæ¼¼¼ÌŒŒþþþÒÒR¡PØÙÙùÔSOUUUíß¿? @©T †ÐÐÐ;wVVVîß¿¿²²!´{÷îÌŒŒÝ=vùÒ¥]»vmÚ¸‘Œa&“é‘GQ*•óçÏ/**JNNV*•Ë—-‹ÍÊ̬ªªB±X¬ýû÷oÚ¸Ñh4r8œÕ«WGDDÄÆÆº¹¹mÚ¸ÑÍÍ­½½}ïÞ½K—.-//_¼x1—ÃY½zuRR’ƒƒƒÁؼyó¼yóB999…qqq<Éd®^½º·§çå—^rvv.++«©©Ù»woeeåóÏ?__W·oß¾ÆÆÆ}ûö%&&*•ÊÌÌÌÔÔÔÄÄÄÌÌL„PvvvaAA||<È¿téÒ .<ÿüó£##Ójõô úùÌårÙlvss3™LÁ0¬§§§©©‰Ëå ‚ÞÞ^ww÷©©©ööö„„«ÕÚÛÛK&“333U*Õµk×AKK BH«Õ¶¶¶NMMUWWÇÆÆ*Šºº:¨°»»Ûjµj4¥RÙÝÝ­V«½¼¼âããoÞ¼I¡Pt:”¿uë–J¥²Z­çÏŸhoo—H$ …âóÏ?/))ééé¹~ýº³³suu5“Éœ˜˜°Z­J¥r```||ÜËË«££cddD*•vtt ô÷÷[­Ö2™\[[ëààpâĉ¼¼<ÐŽJ¥fdd?~¼¨¨èÚµkcccÝÝÝ8Ž»¸¸LMMuvv …B‹Uü"‘¨¶¶–ÉdVVVÚgÕË–-Û°aÃwåZ±b…££ãÃÇŽ rRRR||<Žãccc¶–/_ÞÜÜŒJLL]¸pahh(Ü™R©4;;ÛÑѱ¯¯!«+„ÏÂ… »ºº²²²f±Ðh´¢¢"ƒ144ÔÜÜ|ëÖ-„££cQQQCCƒ³³ó’%Kz{{333çl‹J¥ž={–Áb±Š‹‹M&…BFwww¹\>44DÈaî%?¡rJJŠ»»;\øùù¥§§ûùùA=Kzzº··÷ØØØÒ¥K Æàà Á²dÉ’èèh¸ñD(O§ÓÓÒÒ<<<<œ‘‘áääD&“·oßK`¹\®V«“’’îfIJJ"‘HÞÞÞ¶3X«ÕFEE‘H¤­[·vwwÆ9ÛR«ÕkÖ¬±eôòòjll,++#»ººòóómå¿0÷’TvssKHHHOO§ÓéKOOO[[›\.‡É£>J&“I$—ËÍÈÈð÷÷—Ëå&$888$$!táÂ…›7obå{zzººº„B¡mù7ÖÔÔDGG#„ø|¾›› ÿØØÑQùùùfjjŠL&/Z´ˆÃáX­Ö’’’_ÿú׋-JHH ‘Hp¿ ‘Hr¹¼¡¡aÕªUws!„JJJÆÆÆ¤R©-¦ÈÊ•+më!z{ýúõ}}}yyy‹^¯?wî\tt4ῘLfnn®ƒƒB(((¶²ág´sçÎÚÚZggç7n¬X±‚J¥†„„<þøã0)))*•*...;;̹ª««µZíÝ,×®]c±X>>>!™L¶}ûv‹EdÐttttww_ºtéœmEGGS(‡C0¶¶¶zyy™L&‚‘9Bþûs/ùAeooï©©)­VËb±–™™™ÒÒÒ·Þz ~ÖÙÙÙÑÑÑ8Ž·´´ NMM544lÚ´ !TXXµ©Õj£Ñ³|óæÍ¡¡¡DyƒÁ°páÂ>úȶüÿüÏÿ‚x¾¾¾L&sff!DtÔíÛ·322¨Têž={"""ÆÇÇ===ËËËwíÚUUUåääTRR²bÅ @ÐÔÔ{ìØ±»¹H$Ò±cDz³³gff"BÈÇÇ'22²¼¼Ü¶¢·1 S*•NNN Žãyyy~ø¡Á` F‡2>>þî»ï¼ÿþûpKT(ÎÎÎmmmGŽ™ëéé Ù—jjj ÃÌÌ̱cÇ CuuõÁƒ;†ZµjÕÔÔBènxƒãñx¡ÞÞ^H†2 Ð_žžž7oÞœ?þÝmY­V½^O&“ ÆÄÄD¹\®×ë F„ŽãéééSSS ÿ}„¹—ü 2ÜÌpŸœœ$XŠ‹‹i4Zaaá'Ÿ|òþûïOMM]»v !ôâ‹/ž8q‚ÏçûúúŠâw¿û†a¶Ú!„þú׿Â(Ïb±0 ƒ Q>''G¥R‰D"„‹‹KOOOll,™L¶­J$9;;ß¹sÇ`0Âk„V«ýôÓO#"",ËŸþô'‹Å¢R©‚ƒƒ333GFFîæ¢ÑhZ­–Ëå* ¢ª›7o¾ýöÛÐ"QÑÛjµzÅŠåååD=   !444d;¬s€B¡lÛ¶Í–B&“ õ¾t:ý^,t:ýî¾ß†qN.(O|Édyyy T*•ÿ>uÞß^ b!BÈsåç†ôÑGuss“J¥«V­šõÊò-š%óÝ\†»ƒß‚ýn–94b0\.!ÄåráÑ$“Éäóù|>ß–‡(Ïd2†aL&Ó¶N‹åàà@üdT*ÕÉɉD"¹¹¹  †……h4AÉd …=+ê+™L†Ât:ÏçÃN)´H¡Pmõ"‹ÅšÕ#„T‡ÍfϺêèè8«]hnº°*B¹¹¹999ÍÙ°3™L …2+"2Ñô,!ù|>Hê@‹³ÜlGmÖtJfI$<¼î›D"9::’ÉäïÔÿÐ.1 w î¹çB¿ýío_|ñEÂÕÕÕjµ¾õÖ[YYY €(ÿÜsÏÅÆÆ8p›\.züÙgŸ]¼xñ–-[€7lذ~ýúøøø±±±GyFÀ“O>¹iÓ¦ððp„D"…çêÕ«:äãã³wï^„\.÷ôôD …·ß~›D"íÚµkÅŠÎÎÎ!±X Ý´yóæÇÜÝÝtAeggoÚ´éÀ°>ÍÈÈ€FAªùóç?û쳿úÕ¯à—,111ëׯ߷oÑ'!™L¶xñâ×^{ ê„i´víÚ‰‰ Û&ˆò;wîôññùøãKKKaý:«éøøxB_|ß¾} ¹‹‹ Ñâ+¯¼b;lÄ(lÛ¶máÂ…¶fggoÞ¼ùÀ@¿ÑÑÑK—.…>œ%v~~þ²e˶mÛömúŸ´KŒ‚íè=±jjj4 ‰Db±X ƒD"EGG¿ûî»<¯¶¶¶µµõÈ‘#&“)<<<11!å™L¦‡‡Grr²@ ˜˜˜ „NܳgBˆB¡ˆÅb6› øûöÛo›L&…B§"¡¤¤$‡•S©T•JåííÍf³ßy縸¸öövÿ±±±½{÷^½zÕÙÙyß¾}O<ñ„““Óððpcc#BÈd29;;;99\###çÏŸ¯®®îêê"tAÁ*Øb±$''ïÛ·oݺu¡ƒšL&³ÙÜÝÝ=<<Ìçó …BÁåraO„ ¶µµ‰D¢ „êëë###i4‰D²Z­¶Må¯\¹²gÏžÑÑшˆˆæææ»›V(÷—ܶÅY£€:wî ¤­¦ÀÉÉ)..îÝwßMOO÷ÝwÛÚÚÆÇÇ¡ä,±9Îè託—×7ö?LJøaC»Ä(ØŽþ× þÁFËðð0ƒÁèêê:pà‘Æ000ÐÕÕE|…,΃Çñ¯¾úÊÝÝ!ôé§ŸÂ;ŽN§ûç?ÿéââø»xñâééi•J…ÂqÜÃÃÃ0x:@åï¼óÇÕjµhooG9::¾óÎ;ááá×®]ùè£>üðC¢B]]]—.]òññ±å²½JèròäÉýû÷ëõúË—/_¸pá½÷ÞCåååMOOÃk?ÇÓh4‹\.ÿòË/áCáå¹°ƒÑQþÆQQQo¾ù¦‹‹‹Õj½»i•JuÉm[œ5 ÷ÒôâÅ‹½½½Pm]]Ýà5îÖ³Ä>zô¨V«U©Tߨÿ¡ææfÛη1úÿlÌÄÅÅÅÆÆÎ* —æ$ÇÆÆR©ÔE‹ÁM˜@pppFF†D"±%†„„dffzxxp8œ;w®ZµÊÕÕž‰??¿ÔÔÔYmy{{cæëë{/1Äbñ¢E‹lÖ!.— ûC„B¡í òn©"##m|!*•š••7c^^^pžˆzâ‰'‚ƒƒSRRöíÛG¥RïÕ„¯¯/‰D‚M–9›¾¿ä¶-Þ­þœšfffÂÆ:N Ó,±¹\nnn.ÇûNýO´;ç ù>0k] …qV·þ´ •JჃƒlþ$ðýˆMÞºukLL —Ëíéé!‘HpL±xñ⬬,‡;òb±žè{÷îMNN¾rå BˆL&ã8¿bÅŠ°°°›7o…L&Ëd²7ºººÞ¹sgÏž=ÕÕÕ¶Mêt:ØñCÁ&ÓOÄjÁh4þ˜£ÜÎÂ÷#6æéé9:: O 6ÀƱ··w__œyEDD8pÀÝÝð‹/³9$$äå—_æñx"‘Èd2„††¾üòËóæÍ{ùå—1 ûðÃáæßÕÕú¤·ãG Ìd2ÕÕÕÁtéïïW(¡ªªªññqØN…Í Ãà†;¶“““ƒƒƒ0÷»»»§¦¦ètúàà LǾ¾¾Gy6š'&&îµÕaÇÏdgggOOOÅÜÙÙ ïׯ_º}ûvoo/ CL}x 2Œ   µZ}êÔ©Ë—/ÝÏÏÏÃÃF£uvvfgg_¸pÁöxÒ;²²²~hì°Ã;ì°Ã;ì°Ã;ì¸'ˆÓ•Y‡b³(Άüýýÿö{!""‚Ãá899ÙÚNŒ`±Äb±Äb±­IÆ·…B a2™`KC&“]]]¡•ˆˆØ&‘H`LæääD(âìì ŸÙl¶““X,988€$!'''@@"‘( •J+.6›íàà@&“AfÛ\K¶ýàää–U³ºñ^&S!:ÎápX,“ÉÄ0lïÞ½  BH*•B°ufž2ÛÁ2‡N§ÏÉBŒ¸-ø|>tôÒœŒòÓO?}åÊ•øøøÂÂÂÛ·o‡„„ŒŽŽÆÇÇk4šõë×755‘Éd“Éô»ßýN&“ŒŒ…B …JîØ±ã>ì/^„‰Dããã 8ŽS©Tggg8ÅŒ/**¢R©MMMCCC[·níïïGΛ7¯¨¨¨®®ÎjµúúúB=‰‰‰†MMM‰D"ÇétzHHø^CfÔüüüööö'Ÿ|R Àñª‹‹Kqqqggç¼yóBCCëëë9ΡC‡˜LfLLL~~þ™3gbccóòòæÏŸéÒ¥   hµÚ®®®ØØXðÝmllŸËåzzzêõú¼¼<6›][[ëîîãàà°mÛ6p8€n¼råJqqñ³Ï> ¶kŸ}öŽã„<ôs?܃!É¥““Óèè¨^¯wqqqvvV«Õï¼óÎ /¼põêUBfggç'žxÂb±<÷Üs7oÞôôôtvvž“…q„PNNNKKKww÷ùóç%IddäÌÌLjj꜌ Þׯ¯ããã‹Åb±”——K¥R‹Å·}P•Á`h4š‰‰ 0ÆÐjµ mmm0uîÃ…B1::J£ÑZZZ>ýÙgŸ±X,ƒÁ@¡P4Í{ï½÷‡?üÇñ‰‰ ¸¯^¿~]&“ŽŽ9rD¡P`F"‘ ƒ1>>Žã¸L&#‘HMMM`[W^^þü#-- ¬óp÷ðð ÒQŠD"³Ù VÂ`“¤T*q¿råJ___lllPPÐÉ“'á~@<}}}wïÞ}êÔ)±XìááÑÜÜüúë¯×ÔÔxxx‚wÞyrà*•J™LF§ÓOž<ùôÓO›Í扉 èÀ£G>þøãG­¯¯ÿÇ?þp:®¾¾ÞÁÁA¯×Fâ º X,«ÕŠã¸§§§Á`˜žžžšš2›Í2™Œ00DÉd²ééi??¿¾¾¾êêj///­Vû«_ýª­­ !2_¼xqddäÃ?|ØÍÍ­§§gݺul6›ÃáLMM ôôôøøøˆÅb…BÑÛÛëååÕÙÙ‰úÅ/~qþüùééiFC¥RÓÒÒnß¾Í`0´ZíÎ;Ÿ{î9OOO¥RIØãŒŒ°ÙìÅ‹çää<ú裃A(êõúˆˆˆÞÞÞ//¯ÔÔT•Juøðaµâãããîî^RRrúôéŽŽŽ¦¦¦'žxâøƒÉd¢ÓéNNNìùâÅ‹Pàéé l –’’ÒÔÔ„ãøÝ,ĈÛú²r8:®R©ÒÒÒZZZ ‚Á,Æoñ„„£­Ç•J…"ˆ÷q>™„mÐ,ÏòÅ @§ÓçÍ›÷míïU¹T*“Wd#0¨À`0lÛSëÿÄünH¤ÐÐP??¿9¯:99Íòbx•y<Þýßl¾ë |×òl{‰¼}ûöèèhx¦Š‹‹óóó•Jeii©L&»sçN~~þÌÌŒJ¥Ú½{÷Õ«Waoݺµ¹¹ðM›6ÕÔÔ\;vì ¹~ý:BˆB¡X­Ö„„„+VÀúÆjµJ$ð½T«Õ/¼ð­[·}ôѸ¸80§P(ÃÃÃ!!!K–,Y¶l˜W,»wï–Édmmmû÷ïÇ0¬«« ”8ޝZµjݺud2ŽÒÁøâñÇONNÖétùùù .¼|ù²F£™žžÆqˆ‰‰±e9vì›Í.//·U¤…;%x@Ü¿£ |VV†al6Ûßßò³ÙìW_}6h\\\Øl¶——׫¯¾:oÞ¼W_}5<<D“=Vmm-a¾µ¶¶ŠÅ⎎'''‘H‘ÊB“““‚0‹Ü€ËÕÕõwÞqss£Óé“““½½½pU"‘|üñÇ{!o7K—.5 ÁÁÁ°š¶Z­‹P(ŒŽŽ†‰…1))©¼¼|ttôå—_ÎÎÎFõööÚ†ÜdeeÁrÊ#„bbbêêêlË×ÔÔ(•Ê¢¢"Ð zÇqð`!ôšå¶:22rwÓ½½½à‹ Ö‘ßR`["•Juss{ýõ×më¡ü+¬‰D¢ÑhðÄ X/^|õêU0Ç%øøøÜ¸qƒð>¿OG,Ë™3grssÏŸ?æÌ™¬¬,­VÛÝÝ ›£££§OŸŽŽŽîîîîïïïîîV©TD“!D …r¹¼±±±³³S¡PÀ144ÔÛÛ»¼¼œËå‚o‰NollÌÉÉéì쌊ŠjnnNMM……[hhhss3p;w.&&fzzúÆjµ~ô4­©© V¸jµúöíÛ­­­¡òòòñññóçÏCôŽ›7o,qqqL&S.—755)•ÊúúzØÜZ²d ‰DêééÉÏϯ©©ÐDÀ6› ·wŸÊwttÐét¸D”÷õõ ª©©Q(999çÏŸ7óæÍóòòjmmÕét WHHH[[¼Ã •JU\\<«i•J5::ÚÑÑÑÐРR©¾¥À¶DØ( 6¢ÇsrrÆÇÇ?ÿüóÂÂÂ+W®ô÷÷,YYY …Åb Šƒ´‰‰‰·nÝêêêºGAùÚÚÚüü|X±ÄÅÅ8qB£Ñ\½z~caaaçìÙ³'OžT«Õ@'z^Š ‡°o…””ØÈÈÈ`³Ù01#""`sög`tn^2™ÌÛÛ›Xhƒ^l6;!!á‡î'b’ „ÐÊ•+‰ , …$iÅŠ1$$dùòå¶Ûö...2™,%%Ã0päÅ0 ^¦œœœÖ®]‹ŠˆˆX¹r¥X,&¸œW®\YVVfÆH&“­\¹’p&œÐýýýËÊÊØlö‚ ÒÓÓm¥g0¥¥¥Ð.ÿ’’xÀƒð1®¹ººBm‹/NJJâñx¿øÅ/fy ÅÇÇ{xxxzzÎj"<<æYaaá¬HL ¬"î%'¡Z```YY™í™BhÕªUK–,™åƒ¿`ÁxtæååAyÛq™5X©©©Ë—/ŸuRt·.DD墣£×¬YSRRb{¼–••µbÅŠYªAc='0‹E¼–'$$ŒÅÄÄLNN%V®\966–‘‘A¡P ø|¾Ùl^¾|ù³Ï>›““…aØüùóçÍ›G"‘¦§§CBBH$Rnn®V«U«Õ×øøøÀÀ€ÉdêëëãóùùùùT*544T¡P¤¤¤À‘ÓŽ;`gU&“eggGEE%%%Aü`IHHÀ0 œ bwww[[øÍ±Ùl©TÚÝÝ“óu˜qB£Õ«W_¹rÅÕÕÕÛÛ;''gÍš5555ëׯGEDDÀûDAAÁ²eËJJJà €@OO¸Ýétº   ÛÖCCC§§§KKKm‰¶rÚªæêê:==@ô B(22ÒÍÍ-22²  @( …’’’B"‘nܸ±jÕ*Bµ9+==ýüùó$ñ^º0™Ì;wR©T8è„Ê ›ššüüüNŸ>m6›‰®\¹âèè8Ë™z€kÛÿ=±ºººà÷GÄaò÷÷wÛŒŒŒÂÂÂöööôôt‹E&“7nܨR©<==O:µsçΪª*GGÇ‚‚‚¢¢">Ÿo2™àÀèÖ­['33“à²X,:N¯×›Íf__ß-[¶À¯'%%Ö€QQQK–,A]¼xqÞ¼yõõõjµZ§Ó1™L‚¥¶¶!Œ"ˆ‹eùòåD¡mÉq8£Ñ866Æç󃃃¯\¹²téRXØ.\¸077!411Áãñèt:¬* BSSS°”&\mµ "“É<oN9mU«­­ 7 DÏÀlc2™nnn7n Ù¸qc@@@__¸(•JøÍÜg°ØlvNNÎÉ“'ï£KQQQFFFxx8ŽãDå„ÀƒÁd2©Õjlj ú{‚ø^DcmÛ"ŠX,îêêJMM­¬¬„ןþþ~±XÜÖÖod±±±îîîuuuF£qùòå°Ç:11qøðáÆÆF«Õúç?ÿÙb±À‹4& ]]]+**l¹Ìf3Ìý›7o.[¶ üÚ¾üòˆ†„PMMÍŸÿügèšmÛ¶iµZèkǧ¦¦–ððp‘H‹<‚XXXˆaD®‹ÅD¬¬ TUUÁpšÍæÆÆF ÃàŒ“^}õU˜…UUU¡¡¡F£¶ª¡ ÚœZ`Ëí9å´U­´´~]¶=c0Ìf3¼šÍæêêj³ÙüÁ”——ÃOÞøî3XJ¥òý÷ß9ï¥Ë‡~899yãÆ „Ð3Ï<• ÚÖ°{÷îúúúÄÄÄêêj"¾Ñw—ÿ7¶nÝ*‘H`»BDZñ¿ïi6§]Ä7âÛ^ºÈdòÝ[ð°p/–­[·"„d2Yvv6 4ò÷÷‡8Û„lß)ÐÔwŽäü®=S\\ át¾q°~DÎÎÎÄšŽˆdêææF"‘ÜÝÝá½/,, ð}ûö…‡‡ßë°åGoÖˆ2ÿÈ…Ÿ÷tüqjDþÕ¯~E¥RSSSÛÚÚ˜L&˜}-[¶,<<œJ¥¶µµíرãòåËaaažžžÝÝÝ¡¡¡¶~l°=4½›8çÕ9î/üS#ŒJ¥Êd2‹µcÇŽÝ»wÃß?þØÛÛ[§ÓÁ™9Bèúõë°—C|°ÃŽû€b0Ž?¾qãÆ¿üå/`GF&“ N:%•Jkkká— jˆÅžCÆŽoY¡PˆD¢¯¾új```bbbrrrbbbttT TTTp¹\ooïëׯgff666Ο?ß`0466ÚÆÈ·ÃŽï "º+lôñx¼YáÔì°Ã;ì°Ã;ì°Ã;ìø¿‰DâïïOXYÅÆÆzyy!„æÍ›WVVÆãñÖ¬YSXX8Ë®èþÚ~-))AÍ Érss/^ÌçóËÊÊÀˆ;##ã¡öÙñƒ¼`Á‚üüü‘‘‘ 6ÌÌÌ¥¦¦B¬ÑôôtWW×ââb‹ù-ž~úéÉÉI…B±téRpk6SSS›6m:r䈿¿zzºÙl6 ###`û“`ݺu333yyyþþþ^^^jµ:33ó™gž™˜˜X²dÉÄÄÄúõë}}}Ïœ9êààŸŸé¨u:ÝÊ•++++åryjjª——WEEÅš5kÚÚÚŸOQíܹ³¡¡A"‘`¾š}ôQaa¡T*3¿ß'0„—ËmiiÑét§OŸöðð jmm-..F]¿~½¯¯ïÎ;pgš˜˜pss£ÑhR©T£Ñ€ÑØØ‡Ã‰D@±Z­&“itt´½½½ºº:  ¿¿|Nž<éîîžžžÖ¡z½žÇãÕÕÕõõõ}ùå—«W¯ãµééið:'¢Àƒ%êÒ¥K'&&†††ÆÆÆnܸñÞ{ï) H»299 9H-‹Z­že:lÇ0‚Å …BÙ±c‰D"l°l1”ÝeQD"‘î^ë@oâ+Q?˜y@ýð.}£Õ‘@ðþë*¢ ;~¤H$¶’ [|ûuºÿ§@–H$¡¡¡ÃÃÃÉÉÉSSSAAAR©T¡P@šä´´´ÎÎNGGGGGÇÄÄÄððp.—ëââB"‘,‹‡‡ÇÞ½{ÇÇÇÁÀæ‡ÖÅŽ(7nÔh4QQQ‰$//Ï`0‚ëׯ'&&~ôÑGÞÞÞ‘‘‘ ¥¾¾žL&¯^½zzzz``àôéÓ+W®d³ÙÓÓÓvC;fëêê‰D"‘¨££ãüùó&“ °šššÒÓÓ[ZZø|¾««+øfX,“É455ÈápT*±ð²ÃŽC"‘€ãÞüùó]]]ÃÃÃÿøÇ?‚1u\\8ÐEDDDFFÒéôèèè7Þx#,,ŒF£%''{xx¸¹¹ßkÙ;þí@_mÝ—méÄUökvvw`§9çßz ¢wÌŠàBå{á?Žü4'æì‡{ýÆî¦ÏÔ*,,Ì6à·É'x¥fõÒÝö*ÿöì䢢¢´´4@ ‰†††X,–F£a0¡¡¡b±xjjjÏž=—/_æñx&“‰Á` 8H¡Ñhl6r<ÃæDŒ¡Ñh[¶láñxEEEóçÏ¿zõ*„åܽ{÷Í›7gff Æïÿ{ˆ[^¡ðæW;‹E¥RÍf3dzZ­ç—L&³X¬µk×:::Â&þðððc=6þü7nlÞ¼ÙÍÍÍd2mÞ¼9((hýúõQQQ°‹ñ¥Z[[ù|þÖ­[.\8<<ìêêZPP°bÅŠ3gÎìÚµ+,,,  ¡¡aëÖ­ttÁ‚‘‘‘AAA·oß~íµ×‚ƒƒ§§§a_ ÂXŒÑh´mÛ¶73ŸÏb2™8Ž“H$6›ã¸ÕjݳgOUUÇão¶}ûö«W¯r¹Ü×_BTWW?öØc7nÜ(++»víÚüùó…Baÿk¯½Z@PLf±XöíÛG¡Ph4Úúõë[ZZB°ùW ƦM› ©{vvöÀÀÀ¶mÛ¢££FcYY™““SlllVV–R©Ü²e †]¼x±B¡ÈÈÈ ËËËÙ¾}{rròðð0´•——§T*7nܘ@Ä}±]jSÄbñÈÈHwww^^ž£££§§gHHÈôô4¬· ´ABB™ …...—/_†EÕ“O>i4¯\¹RTTd0ÆÇÇ9Îõë×qçóù ¥££#**jÁ‚AAAz½žÁ`¬^½ºªª*%%…Ëå* WWט˜˜ôôt£ÑxéÒ¥ââb‡GyðW^yE¯×>|8''Çd2utt¤¥¥566*Š+W®,[¶ì©§ž:pà@qqñûï¿ïãã3oÞ<>ŸÿöÛoïÛ·ï7¿ùÍÕ«WFcvv¶N§ƒ¨¯b±üÇÇÆÆ*** O'BÈËË â®ˆD¢?þB!H$ÄÍ`0>ùäðÏÄ0¬©©)66våÊ•8ŽßºuK*•†„„H¥R‡SYY¡1=<< D†aǧÓ鉉‰999CCC<Ïl6wtt„……µ´´|þùçCCC0*F£1..2«¥¥¥AŽq‘H¤Óéd2Ù† >øàƒU«VõÔSD–M¬¾¾¾««kÙ²e\.—Åb>}zhh¨¹¹ÙÅÅE$uww·´´@‚uFÃçó‰XJt:ðcÇŽÅÄÄ…žžÇqßµkW}}=„†âr¹ï½÷žÏ‡~çÍååå¿ÿýïÏ;§×ë!R-ǃz¢¢¢ Åàà Ÿ‡¦!š²V«…´¿Z­ “ÉZ­žcÒ)2™L¿«T*;–žžîààpôèQ??????b•Á`¸ºº†††^ºt‰Éd’Éd6›ýÚk¯1™L"Þ•B¡hhhhoo§Óé cdd¤¢¢bpppddD ôõõk4‹Å244)–Y,Ö™3g üõ¹sçà6ŒŠ…ß084OMMñù|ÇËËËš››!„:ljW"Ð"&&¦©©©¯¯¯©©‰pó‡Ç¼oMMMFˆíð÷÷‡Ûä‘#G’““»»»{zz¤Ré¡C‡ÉdreeeyyùÂ… ) „mjmmÍÉɱZ­aaab±B¬©Õj2™ mñùü«W¯J¥R*•J¡P Šß;wlÔ“=<>þÚµk\^¡Pœ?šîïïÿðÃÍfó;w nQQ‘@ øûßÿž››ëááÑÑÑ!—ËGGG1 KNN†@•AAA\.·µµÕßßßÅÅ…L&÷ööFEEÁÙvvv6‹Å¢P(^^^)))7oÞ¼xñ¢^¯ä‘GNž<©T*ÛÚÚA°ÄÄÄÆÆÆªª*x#6 ×®]ƒ¸}ô‘V«­®®ær¹}}}D7 äææ* 6›=::ZQQ T*ÛÛÛ©Tª··wGGGDDlø‘Gqpp¨¨¨ ijj êììÔëõ EyyùÙ³gÕj5ä‹$“É:îÆK–,¹té„ ¸uëІ«mmm‰‰‰i‘Ëå;v,  ¾¾^¡P:uŠJ¥ÆÆÆ?~>>_|ñ…³³óÄÄD]]Ýôô4¤¹耘»wÓƒƒƒÁí}N@Ì–û#--í^B0 Y9]Y,qeûٶؽ>ßÍ5‹NG¼aaa[¶l¹WÞùóçϪV DEE PÅbÍŠô9333..bˆÔˆˆˆôôôööv‹ÅBDD …eeeµµµ‹-JHH “ÉÉÉÉf³Ùb±”••ÑétGGÇìììÎÎN‹ÅÝÛÛ»bÅ Xªôôôäåå‰ÅâÚÚZ¨rrrÊÉÉéêêZ²dIcccCCÃòåË5««ëÂ… ;;;­V+,MJJJŒF£‹‹‹ŸŸ_gggVV–\.úøøøÈÈHkk«ÕjMJJ²U „ ËÎÎniiÑëõ ”^¯'”òóóá³³³ÝÝÝÇÆÆ@ ooŒÁÁÁyóæÙ6'•JÓÓÓ›››ÝÝÝýýýîææ–ÝÕÕ•““ƒaØ‘#G<<<(JQQŽã¸ £££  Àd2 -]º„_°`AgggHHˆ««kMMMII‰F£™™™N˜¥¬‹‹ Ðmã`¯[·N.—wttÁß¹\nQQQ|||{{»Éd¢R©Ä¥‡>±6lØpñâÅââb“É$•J%‰T*…,#¾¾¾]]]R©´¯¯Ïd2A c…B___Ïf³!AM\\\uuuIIÉÈÈ—ˉ‰Y²d‰J¥"“ÉóçÏŽŽnllìééÙ¾}ûµk×::: ‹ s½^/‹ ƒ««kJJʹsçÖ¬Y~ñâÅ„„„ÀÀÀ%K–p¹Üëׯ—––=''ÇÃÃÃÃÃÃÏϯººº´´´²²2..N*• Ì©ÔâÅ‹A¼þþþ»•zä‘GàjVV–§§§§§çÙ³g׬Y#—ˇ†††††233m› «««óóó3›ÍÉÉɉäÚµk¥¥¥###þþþ®®®aaaçÏŸ_µj•B¡èëë+--ýꫯV®\ÙÚÚš˜˜Fputt¼õÖ[©©©¶­ÜKY¢sÚÛÛ—-[¦T*õzýÚµkÍfóÌÌLrr²J¥ÊÍÍhkkËÈȸpáFÛµkWCCÃ÷sø†ÁòžJ¥&%%ÍŸ?þÞ¹s'++‹Éd ‚œœœÜÜ\x‘{©™™×ßß!¿&''+++×­[g±Xär9‡ÃIKK#“É\.W.—F.—K£Ñ–/_~þüù¼¼<„Ôñœ®^½š˜˜XUUµUVV.[¶ Vô*•J*•Bmnnnccc|F¥R¹ººj40:B„GÍ©ˆg±X\.‡\)t:^>Þ¶•{) ô'NÀ–ر ‰499 ”k×®ÍÌÌlذ–þæ›ož9sæû™Xsv#¿}y”j–Mñ–¨³‚]‰D¢9k#Ö³³d ¾ÂÂŒçÛ‹z“/¸JX}b}VswwñÕÖÔì^:’̪än¥î¥ìÜ`‰Ìçó´Z­‹‹ —ËÕét^^^ƒÁÑÑÑÉÉ Çqø;33ãååe2™„B¡-Ýd2Éd2‹ÅÂd2ÔjµX,f³ÙZ­–N§Ã¡‡T*U©TÎÎÎ` 76™L699 iþLD ¥ IDAT´Z­««+•J5ñgffF  ‘HÄd2õz½———N§£ÑhnnnÎÎÎ ¤%èSSSGÊÃÝ‘PröéõzÛ,•J…HàV«è8Žóx<8¹²Z­ÐœX,f±X°bS©Tl6ÛÝÝ]¥Ræéé *K¥RÅbiµZgggƒÁâiµZ©T A\]]]A}—©©)Pß`0À9˜L&3Ð9ÓÓÓ®®®Ê”³sˆVîî„oI‡%€ÉdJ$Çm£ÂPR(Û­²{"“ÉÊÊÊöïß_VV&•J¿øâ‹ÀÀ@>Ÿ_QQ±hÑ¢ÊÊÊÐÐÐÞÞ^غËå³è}}}™™™Çg2™eee¿üå/Ÿzê)8ÁxôÑG὆N§755ÅÄÄH¥Ò={ö¬]»¶¾¾ÞÛÛ[*•ž8q¢¬¬ì·¿ýíöíÛi4ÚùóçE"ÑÿøÇÏ>û¬¬¬ ž_—.] …"‘ˆJ¥ŽŒŒô÷÷§§§ú+¯¼ U*Õã?~åÊ•ÂÂÂ>ø€x>®\¹R¡P(•JFãççgµZ;::AtttXX˜^¯²ÕjýÍo~óâ‹/®^½ú±ÇS«Õõõõ±±±R©ôÊ•+d2Y,«T*‹ÕÒÒ%•JOŸ> ê€x …Âb±”––¾øâ‹PÏO<1::ÚÖÖ–ššJ£Ñž|òÉï³sfÑŸyæ˜ÓÝÝÝ™™™îîîr¹ü©§žòððèëëóððàp8kÖ¬ùôÓOa{677r[Ì ¬¾¾^§ÓY­ÖòòrHôe0jjjL&See%<¡áŒÇñYôÐÐPØ€z [‹Å är¹t:ýïÿ;‹Åjoo‡ú©T*•J­®®†e pÁч»»{PPЉ'ø|þÚµkáM¾¯¯ott4!!è\.÷ìÙ³)))ß’Ž‚ˆ_psòõõ¥Óé¶‘Àüýý¥Ridd¤³³óž={vïÞíääÔÓÓ#‹_yå¨688”‡Ã³Ù499 JüR©ôðáÃjµè„:PL&:vìXoo/ÔcµZI$’‡‡¨)[¿·Î™Eçóù±±±W©T*<˜žž~ðàAGGDZ±1ðpÙ¸qã®]»æÍ›wÏG!úWÒ˜œœƒA¡PjjjîܹãååuãÆ ‰DÂår!&³ŸŸ_KK‹-]©Tbæééyþüù´´´ºººˆL o…<B¡´¶¶¦¥¥Aý·oߦR©Û·oÿì³Ï&''ÓÒÒNŸ>m0üüüjkk]\\„Báèèhppp[[[`` ‹Åjhh‰DB¡n3###ÞÞÞ߆é6ëêꦦ¦RSS;–ð׿þµ®®îÖ­[uuuwîÜ‹ÅW¯^˜˜¸uë+ÌËË;}útrr2ØÊ2 8MJJª¬¬\¼xñÙ³g!„:ƒÁ8tè<ûÜÝÝ[[[!ÙƒÁ€Ï„xãããQQQåååZ­6--­²²R¡P„††Þ¼y³££ÃÏÏÏh4666~o3‹^^^®V«kjjúûûýüüÆÆÆX,ÖÕ«WÏ;wçΚšF£Ñhüýý+++oݺ% >|¿Ç!œâÐh´ÄÄD¡PU!‹Åçó!p¹““Ó,:‰DŠ‹‹Óx¨'((BLÓh4‘H$—Ëcbb\\\ þÄÄD„ŸÏ‰‰  ¸bbbÜÝÝÉdr||<ÜiàÆÏÏÏÇLJ ;::ÆÅÅaö-é¶jzyyEGGÏÊsÌårï^ÔCY¨–L&J´"‘¸@)‹•””Äf³…B!púÝâ‰ÅbXƒC=Ô‡P‰ß[çÌ¢ÛªïààãëëkK¤P(0î7™lq/ÛšY®Ä×o7ömwæ¤Wû¡{xPt;þ3KJJòó󇇇÷ìÙxýúõœœœÐÐP™L–••ÕÝݽk×®ÄÄÄŽŽŽ;vèõúÌÌ̼¼>^UU¥T*8`4/^¼ˆÝ uuußô!þæ–•ÞÈJ‡dåöû—.R·ôèËɸ–­¬¹ë¿-ÒúëÚ¿r}i³§ÿƒ‹FŸÏ_ZZZ]]Åg tW‡Ëå.,,àa³N§óõõ5F£þf³ÙÙÙY§Ó¡¿-“ÉÄI'''6›m0mll¼¼¼fgg¡ï1ð·±±qssÓh4îîî,kyyY,k4½^„X,^XXðööæóùóóó Îb±ÀJ(º¸¸ÌÍÍ‘Ò"‘H4;; ᔥäè¯k·¬‡Ã±ÜLG„«««½½ýüüüÿÜ1ü›\4ƒQ[[ ÖO~ò“ááa©TZPP099ùÔSO577ïÝ»·  `zzö7nXú åääÈd²ŠŠ >Ÿ?==ýì³Ï&$$˜Íf Bööööóóc2™)))€ÍfÃÿСC...T*õé§ŸNJJjooûí·«ªª(ÊÁƒSSSÝÝÝ9޽½ýÓO?­V«ÓÓÓe2™@ xê©§ß|óM¹\âïžž˜˜ˆ »eee ÃÏÏï¯nçr¹£££~~~Z­Öl6ÿò—¿„îËåÎÍÍA0øÔSOáÛœ ˆ¢¢"rÏàÿµEݳgϽ{÷8Nii©L&ëêêB¯»wïB§ÕÜÜÌãñ0_nuuÕÊ“«‹ŠŠfggE"Qllìøø¸J¥¢R©Ê}ôÑG\.·¿¿¿½½ ˆø¯¬¬àc‰”:A¯’pãÆ £ÑªP(T*ÕÙ³gÅb1^V˜]XXuáÂÇáp.]º”””„èkÖ¬ù:ìR©”Íf¿ÿþûÐh8::ººº …Â÷ß?33óý÷߇&lëÖ­{î¹çöîÝûÍàojÑBBBÔjõòòr\\Üüü<6Ó]¾|:­¢¢"¨‘ŒF£ŸŸŸL&³ô¿~ýúÊÊŠ§§çÈÈÈôô4”¾l6Ûd2ݺu+ ÀÅÅ…N§÷ôô@Y699‰Þ¸G ‡ÒëêÕ«ëÖ­kiiÙ´iÓ™3g /]ºäèèÞÐЀ.žžžP}577ÇÅÅ--- …B@°ººjcc#—ËØlö;w\]]ÿêv…BÑ××ùÔÒÒRrr2žüþ÷¿ïíí½víÚÀÀÀO~ò“óçÏËåò‘‘@ðá‡~Ó‡ø›[NNN8}†ò:66›wÑÏý,í–þ %&&ròØØX:³­­m\\œP(ôööŽŒŒ„:›Ëå’þ"‘O %‰D"!ÃA èèègccãììŒÍ¥xé&‹% F‹‰‰qppàñxÑÑÑT*Ñ¿>»eÝÂÃÃCCC­®]""""##ÿ{ãÙÿw®GuHS,YMóþÊ9ÞV+¦¯[_õµê±¬RøÒ¿þ)±þÄ–WOþõO”Ç}Mv zM={¶¼¼Ü`0üêW¿*,,d0333 ¿øÅ/^~ùe›“'O(•J …âééyâĉ;v¬¬¬|øá‡{÷îmlltvvööö>~ü8•J}饗>üÜsÏ]¸pÁh4&$$¼ÿþûeee‘‘‘¯½öÚºuë †Ùl éèèèìì ‹mooŸšš***ár¹ÎÎÎGŽyæ™gd2YsssII zýˆD¢ÊÊʲ²²•••ÚÚÚ‘‘L-ø«Ûñ‹_®`ÉÉɉ‰‰KKKï¼óA¾¾¾ØÌˆž9sfÆ cccmmm?þñ<¸k×.Ø:„î&ÕùÏþó—^z©½½ýòåË(8ôß$Ngg' ØØØø¯ÿú¯o¼ñÆ÷¿ÿ}™LVUU|³ÙŒ‡ib±¸¹¹9<<<22ò³Ï>KJJ"Ó©S§6nÜø?P(+ûéÓ§©žžž¸ÿ å—ËMMMurrjiiAW††—‰‰‰îînwwwgggƒ®““Szz:AŽŽŽÙÙÙ4 9¨Tª››¾.377W]]ÝÝݽºº üÊÊJ´e*,,ìèèhjj²··ÏÉÉùôÓOÃÂÂüýý;::âââ<<<¨Têäää±cÇCBBNž‘Ëå(EWWFÃíÆÎÎÎÄÄDl+5÷ïß§Ñh–‡©ªª ‡éë.”•½ªªêËÏ7¿ÝYðíú u÷îÝAˆÅbòk‹J¥îÚµ‹ oooœBìØ±ãK;}»¾]_º¨AˆÅâááa¼‡‚X³fL&#bëÖ­_|ñAèlû¸þß®o×£‹:::ŠA•Ä¿øüüüÆÆÆ‚`³ÙÐå?~ÕÃÃo£ÕÕÕÂÂB6›=<<,‰‚Ðëõц¾V8çÿðÃïÞ½û ³þvýí/<%‹Åééé¸Ë@£ÑÐòÛÇÇ'##ƒ  …ò7ÞéÛõ·¶h2™ŒÏçOLL˜L&ƒÁ€n>7oÞ´µµè‘occ£×ë%ÉÒÒ’›››‹‹‹Ùl<O§Óa8€——š;:88 Ì’ðõõU«Õ"‘R*‰Db0pûN­Vã^ “Éôôôd³Ù+++°ÃߟÄqppÀñ™™>Ÿïåå….¦è–ž$‚ \]] ƒD"ÁþA???è›qÖˆ¸<yq8ÅÍf3N·ôG/n¨jIž–ùR(ÔÁ2_ËPŸ¹¹9àÓh4ø{{{ÛÚÚêõzØñ8½…B!”a–øÇõü³ìËËË<ú¹ÅÅEGGG77·¹¹9dg4a7›Í¨žT*]ZZÂQÓh48:OÈ‚æããsèÐ¡ÆÆÆÿøÇ Ð]ååå¹¹¹‰Åb//¯¼¼¼””µZ-•Jóóóe2Ùúõë1é9++kyy9,,,++kݺuB¡ÐÖÖ6333//O&“íÚµklllçÎNNN˜½^Ë^^^™™™h +‰òóóSRRîܹ’››+‰Äb1‹ÅÂ8 £Ñü„„'''‹•–––——×ÞÞþÓŸþ´ººú…^À‹M›6A+ žàC§ÓÝÜÜÞ|óMÆçó³³³===Åb±½½ýSO=µ°° R©BCCsss'&&Ö¯_¯×ë÷íÛ7>>îì윑‘1>>Ž^·¤?¶ágee‘8©©©–ùVTTp8@°oß>Ë|''':„†—yyy333Àß¿?‡ÃñóóC5 ìprrâr¹ ãСCSSSÛ¶m#ñ=<<6nܘ`ggçéé™™™™˜˜øgÙÛÚÚ8ÐÝÝ][[[SSóýï||ÜÏÏÙ‘ª»7ß|sppÐÏϯ¸¸ØÕÕY#;•Jõ¥Y455Q1?»ãY,ÖíÛ·q;ôôéÓááá³³³€vvvÂÞÕÕµººúÅ_üáÀ 訨(½^¿¼¼Œ6p—.]âóù4mzz:%%eii)""B§Ó_*•677;88à>roo/ðÇÇǽ½½ýë_Ã>88ÿùùyàgvvøjµêðÙ€>J|>Ÿä >>>>ëׯ—Ëå˜Éãáá¼fffRRRd2â"¯[·n¹»»—””ÄÆÆQZZjå¯ÓéÀ‡äo•/›Í¾råJPPU¾¨óêê*üCBB€???Ô´#_…B¡Õjëêê0ȃÄ_»víÄÄ„J¥‚ßÁÁáϵ¯]»¶­­mïÞ½===|>Y›L&d·oß¾žžl”ËåÝÝÝèÛ‹j dú¥YP(”ÿ|Îår Åì쬿¿ÿ¶mÛúúú¶lÙrõêU AÁÁƒ“›‚øéOzíÚµÐÐPtñ:yò$Z'%%©T*³ÙÜ×ׇÏÿ .DFF||<))I§Ómß¾]§ÓiµZà›ÍflW‡ÝÞÞþáááÀNPPðÉs>­V;00€áx*•Ê××<ÁG«Õzyyݺukvvvrr²¬¬ìêÕ«®®®F£‘F£!.Z6...NLL`¨Äì쬃ƒê@ú“ÝÏÀ“Á`Xåk0Ö¬Y£R©¬ò[ÒttøðÇnoµZ=88;òõõõMMMmoo_^^¶ÄG2¡PØÕÕü?××ÑÑ¡R©ÐnY‡……!;ØÃÂÂP½œœœ¹¹9&“‰j";²JVYüç“+ggg‚ üýýýýý¹\nhh(FóDEEÑétŒ#í¶¶¶hÑÊb±¢¢¢ð–Çÿ6??????‰&LÀ>F‹ˆˆàr¹o$ OÒ íð·±±>‰|ÒŸÇãEEE¡‰ŸŸÉ“äC„‹‹‹]LL ŒÇ××]¬CæåéééïïO¡P"""ø|¾•?ɇäi•¯ƒƒCDD]–ù’àOâ“þ¨i'óE“íGñ}||¼½½Iü?×NÎ …4 Y“Ù‘vTN§#:Y d÷¸,þóþɯ(ÊãûXÙ­üÕiYÙ­p§²²|¥ìq<­üåOþúgµæúJ}Ò,âú{|°FÙ¶m›X,®ªªZ¿~}{{û¥K—JJJðÈZ,WWW—––ÚÚÚþÛ¿ýÛüãìÙ³‡Çã9sfÿþý+++¿ÿýïaß½{·‡‡ÇÉ“'+**VVV0N¥RFK|¹\^RR¢P(h4š%ΩS§Ö¯_?>>N§Óy<^]]ÝÖ­[ Ã/ùK𙞞NLLüùÏþòË/£ã9ü±eôÒ¥Kè¥þÛßþöŸþéŸ8PZZzëÖ­ÈÈH[[Û'N€Ïòò²··wUUÕ† ,óÚ¾};ÎÀvïÞm™×þýûœœjkk׬YýÊ+¯ -øüêW¿zùå— C]]]aaáèèèòòrhhhwwwDD„Á`hllŒÇ©gbbâ[o½åèèøƒüàÓO?…ý7ÞÀ׺ÉdzñÅu:ÝÄÄĹsçÈ#´gÏ''§#GŽà™÷ßË¢^¼x:ªÆÆFlùJJJ …¤ýܹsNNNÚA„‡‡fU …BGGGÒŽovvv°Ý½{×ÕÕÕ _.—?~œÏç[á°X,&“ Toz½ÞÍÍÍÁÁ|ZZZ †««+𻺺Âø+++555·oßF»‚ *++ CSSø“|FFF †U^AAA'NœHMMµÊË××â}à›ÍfK>B¡<³³³?þøãĽ}û6ìwîÜQ©TŸþ9ü ‚صk—Ùlîêê‚ ˆC‡=ûì³A899ét:???Xð/àbB,é\Ö¿ÁEõõõÅì9üž yì¾¾¾¤ì •––* FCN¤/^D;Fƒ9<èok‰¿¼¼ e•NlllCCǃ=  §§ÇÙٙ䃗ã•M`` üIüüüüææf214yðqssãóù}}}VyÁf³íìì¬ò:zôhttôââ"ð­øLNN‚§^¯‡ˆ ~#Š· IDATq1„'UOOO‰DâääDÚïÞ½‹‡P>zxxܵX$‚ Lö·¹h"‘I¯×ÏÏÏ_½zµ££cll =OÏ;‡ º;wîP(”‘‘GGǘ˜˜Ó§OCèÓÙÙ ;z*×ÔÔàš¢»»;''çêÕ«AXâs84ž››³ÄihhHLL¼víÚââbLL ôa555àUÝýû÷=<<¦§§›ššào6›O¥RûúúVVVÀ‡ÅbÍÎÎbj©'»zõªH$¢P(ƒ—6d^Z­666öøñãŽŽŽ–yyyy±X¬³gÏ2™Ì¾¾¾žžK>###‘‘‘—.]š›››šš‚}``€J¥’ݳîÝ»×ÐÐ>¤}ll ?°Ùl‰DÒÞÞ~õêÕ‘‘ØI&“ippÐrHÛ·ëÛõnÑòóó“’’lmmÓÒÒL&…B)//_\\‰Dyyy©©©è* ‹ÝÝÝ FFF’““¡¨Ü¶m'>>Þßߟô÷ððˆ‹‹{ðàN/--œœÜ¶mF#qŠŠŠ‚ƒƒ{{{á/‹³³³srrÖ­[§Ñh***nܸ±fÍšÌÌ̇#îž={ †»»;ìééé!!!###«««^^^_øJ¥²¸¸8<<||||ëÖ­+++>>>À!¢´´*õ&“™ŸŸ?22²qãF“É´ºº 777ðÏËËó÷÷ŸÝ·o¦Œ–””ŒoذA$1™Là°ÙlàoذA*•’|Èúlذ!$$D¥R¡þqqq¨çš5kBBBîß¿ú°X¬õë×c¢¿¿¿F£¿··wAAZ­.,,DsáíÛ·ã,DZ  Àßߟ<^J¥2>>^&“•””Œ¡z*•jÇŽALNNÂŽjàU–YK¥ÒÁÁAT}bKKKE"Ñàà õâÅ‹l6Zdÿ­[·677———oÚ´©³³³¤¤dóæÍ333T*õСCØë7??ûæÍ›¯]»¶qãFàèõz<`³Ùðïí퉉!bË–-ùùùNNNØ—Èmãââh4ü333 ÃÄÄÄÙ³g&&&ÜÝÝ)JIIÉÐÐPzzºJ¥ŠŠŠò÷÷‰DÓÓÓ°geeOvv6&ù<..ðµZmZZÚôôô¦M›À8iiiððàÁÐÐ^¯ÏÈÈHÔ‡Ïçß¾};//öŒŒ ä‹­( ÅÛÛûÿý¿ÿçïïïìì¼nݺ‡‡ÄÇã)ðO …‚¼¶mÛ†ú£ž2™ v²>{öìQ*•ˆ»wï^øƒŸŸêæîîŽúà8îÚµ þ;wîD¾'<<líííQ½ÈÈHN—ŸŸ;‹ÅB5¬²ŽŒŒD999¨6¢..ðsrrêëëÑ«üãêê ‹•‘‘qöìÙÁÁA¼cP "¤R©àÆ!KKKT*<Ÿ{î¹þþ~\ ‡††šL&à€¿P(DûÑÑQðO³ÙŒ¼.\¸€ú£žr¹öÂÂBÔ³Öwî܉¸W®\?øº©T*ÔDZ—––È| ëëëÁ6 Õswwwtt\YYyþùçûûû###QÅÅEˬñ3NÇ8úƒR©T­V‹güxÎC …hš`0æçç5F£¹zõêÇËÊÊÐÊl6××ן9sfpp0??ŸF£ÉårØkjj***úúú€355…$uuuð'B©Têõú·ß~ûÁƒþþþ¾¾¾ÀÑh4ëׯW©T---ð …ÁÁÁÎÎθhR*•AŒŽŽêõú›7o>õÔSx²™””444422¢×ë1ÉÜl6Ÿ?>**jxxøqqI|‰D¢×ëÀ8---ð_\\ÄH0ðT«Õ¨O@@@TT”L&ƒýÞ½{ÈW«Õ‚ç»ï¾ÛÝÝ=999<<ÜÖÖf6›þmmm>d‚Èkii õ' ì¨O[[[||üÅ‹wddþ$OÔB¡ >8ާN‚UUòuuu•Ëå`;>>ŽêÉd2*•:33óë_ÿº»»{ll Õ‰D–Y+•JdÑÒÒ‚j?x𠬬ìòåËdÖ_rÚEnÇýG>Yu²ìnûŸx§Ø ÇÊnµðXãQ7ÒþhG«?1.^þ(þãø<ÚIëKóµzÕ£<·¾r{¾UÜÇ>$%ã¿Z̓ùÊê}eÿ0Àþׯ333~~~«««‹‹‹¸?É`0üýýgff0boiiI"‘LOO£ƒ^¯ÇG¢Ñh ˜žžŽJ¥òòò‚ Óš˜L¦%¾Ñh YZZâp8–8äÔ1ÒŽ3ß……;;;lìZ­ÖËË ýº‚ƒƒ1àÏßߟ%ŽŽŽKKK¾¾¾ÓÓÓ¾¾¾nnn«««ÎÎÎBE–y?n¹©T*Ü„4È—ÇãyyyÍÏÏãæäööö\.—ÏçkµZ±XÌ`0ôz}pp°Á`‰Dd\&“Éd2Åb1‡ÃAãVô?rssc0°[öÜòððÀAË–¸daÉr®¢å¯–?Xý OÒ?à‹›\f³öÇM#·Šò¨¿Õ¯´M›6Az†®>üÞ÷¾ççç'‹1X,11177;Ç«««Ÿþy;;»ÑÑÑïÿû ׯ_‡ýÅ_äóùvvv{÷î…®ËÓÓ³¸¸{|I|6›íëë[XXa‰á@VVìóóóÉÉÉMMMà3==}èСÖÖÖï~÷»ñññ E*•feeÛD8pãÆþð‡ÕÕÕžžžEEEƒ!99977W¥R‡‡DjIII–y½øâ‹ ÃÑÑq÷îÝ–y½üòËèÈJ§Ó8ÐÜÜü /|:;;:”œœÌ`0pÿ}||¼¨¨ˆÁ`äçç'''wvv‚çèèè¡C‡šššâãã_ýõ‹/eeeaz ‡ÃÑét/½ô’J¥*..ÆžU;;;‡óì³Ï¢°¸Fû{YÔÊÊʈˆˆùùùÎÎN‚ BCCqâ »V«½råŠ@ Ðh48qÁgRPP‡ÃÁMHØ—––pMûíÛ·ÑŒÚ ¿³³svv¶»»Û gaa!::#¼¼¼||| †··wXXøÜ¿Ýfe2ÙÌÌ …B?ð§§§õz}}}½L&Ü˾zõ*øwvv‚Ï'Ÿ|âìì|ïÞ=«¼X,Vkk«T*}4/.—+€ïëëkÉgyy</_¾Ìår÷Ê•+°Ëd2__ßwß}þ666è<­P(`'â¹çžûÎw¾CƒÁˆˆˆ Óé°à_[±7oÞl5‘ëovQËËËÛÚÚ\\\ð»R©ôòò‚ÝËË+%%eff†üîÔét¸Œ-öä# eˆˆ€=--M¯×3 +|//¯­[·Zᄆ†bx$ì4­¡¡A¥R‘|ðr•Jåáá! ]]]áO⧤¤à6ž*2 ðOIIŸŠŠ ½^Ïb±¬òÒëõ‰‰‰ÓÓÓVy9s†Á`ŒߊÏüüÿѼBBB [²ÌËÕÕ£I|+>àI¥RCCCq.…¸$²›ù´ö¶ñuss“H$x9¹ÈÂþúÿÐz\W§'_¼ŽØtZOÖÃ=öQžOÖ·=Y^ö(ÚŸå¿è¥¦¦®[·î­·Þzå•WVWWÿùŸÿ,[[[//¯ÊÊÊ™™™üàÿøÿûòòrxxø7’’’HÝÕøø8v TWW—””ܸqC©T–””Èd2L7©¬¬„Îéõ×_ŽÁ`ððð8~üøË/¿<::zëÖ­äää‘‘.—{æÌ™gŸ}vttôÊ•+À™››CÜ´´´ÑÑÑÊÊʽ{÷644p8Kþ555àC§ÓÑ_~ýúõ‹‹‹uuu–|ªªªÊÊÊ Æ~ô#ðÁÙwee%˜œ9svˆ¸««« †††ºººž{î¹óçÏ766>|øµ×^{öÙgÑ©ü †epcv|||rrrݺuÿò/ÿòòË//..ž>>B¡ð³Ï>Û¾}û7.^¼h²3ƒ=ÃjµÚd2¹¹¹UWW—••­®®Ö×ׯY³ÆÃÃcddÄÝÝýÔ©S¥¥¥7nܘœœ,..V*•4ËåVUUíØ±Ã²>ÇŽ«¨¨8räÈáÇ_yå•^xN§üñÇ`åéé ´½{÷ŽŽŽ^»v QnÞ¼‰£öüóÏÓéô'N€Dä7oÞŒ‰‰¡Ó鯿þ:µ¥¥ÅÆÆC°–––¼¼¼ø|~]]ÝÈÈNß¹s'š Á^YY©Óé@ ÈÌÌüøãƒƒƒ1ŒÅb566²Ùl&“Éb±„B¡D"9qâDrr2üy<pÒÓÓñ­áììlkkÝØØ¡•Éd‚Ä!ãž––¶ººêêêjÅÆ àþÎÎΚ‚›é–|êëëI>°geeEGG»¹¹ Ø‘—@ €ÝÍÍ :Ž»öB¶´´”žžþVu ëž|>| ß¥Óéb±øöíÛx!›Í&ëLâ€çÈÈt8à¹eËÄV©TGŽ,‹Á`g||üøñã\.—®YÕÇÇÇgaaYÐh´Ã‡Óh4œ Óét Õ†zìÈ‘#8j<þ$+òèÀN wñG“­­mrr2ôF¸G R©pR‚'µ8­1™L\.wrrR£Ñ`væêêj@@@kk+yVRWWñ®œá~Éááá8íÍÍÍ=rä—Ë=}ú´D"1›Í×®];wî\rr2ì111ÀÎÉd2Á¾²²rùòåääd+þ³³³àþMMM‹jÉgyy™ÃáhµÚ¼¼úõŒ‹‹³ªO^^Þùóç‘Exxø† ª««IV$ªÍ`0G-''þžžž`…£³¼¼ ;«««}}}nnnJ¥òäÉ“£££ effæèÑ£“““§OŸ†Ï|FGGáæÌ(àP円N7??ßÛÛ›””tõêÕžžž˜˜˜ãÇ ¥Rùù矧««+%%¥²²Óš†‡‡CCCkjjÌfsLLLmmmPPJ¥jllÎÌÌŒF£Q(ÑÑÑèÑ™™yåÊ|»‘üñQßÜÜìééI¡Pð|ãÆÖÖVK>•••QQQ“““'Nœ< ®¬¬´±±Y\\üä“OnÞ¼9::J„D"9wîž¶µµ¡ÔÑ£GÇÆÆ®^½êää¤T*GGGÁßÖÖÖ²à£P(ð`'::úÆ>,**º|ù²ÝÙ³g———ççç[[[Á‡Œ9aNNΕ+WîÝ»sìØ1Ô³§§‡øãó.‰DrþüyÄEËE6›­ÑhbbbNœ8Áçó-ëÃår»ºº._¾<66vëÖ­¸¸8;;»þþþÜÜÜË—/ã‘×ùóç¥R)º!ŠB¡ÀQÃíFô’¹råŠZ­ÆÑY»v-ÆM~éùÙ·ëÛõ—.Z\\Üš5kúúú6mÚ„GÛ·oÇ™cVVôC!!! %;;;,,ŒÅbá4¶°°000P£Ñinn.++Ëh4b²!žŽ9;;S(”¦¦&6›=:::66æçç'š››óóó­ðE"좄‡‡§¦¦NOOs¹\ĵ±±™˜˜ˆŽŽÞ´i“F£éëëC\øûøøÔÖÖr8ì‚§P(ðˆˆ(//ÏÎÎ&ýKKK;::Š‹‹ÁóæÍW®\)--%ýÁ“´oذ¡££#%%øƒáСC111ÐoMNNFDDh4ÄE}¶oߎÓ|ÒŽ©Ø«««ˆËãñêÓÓÓ| õÜ¿?ž¥êtºÜÜ\ýû÷ûùùíß¿tt‰|Óïÿæ¢bß7ƒÁ@+ˆ¹¹9‹zb)•J6›m6›322êëë©Tªƒƒº,F*•Jzd³Ù …»~‹‹‹=j…?66ûÈÈÔÖÖfddq{zzÖ¬YÓÞÞ¾°°žžîàà€¸ð§R©Ši4þ½½½Ø~Îf³áO¡PæææØl6ø£ƒ„.kÖ¬immO¨ïi4üíìì€ý“ϵk×ÔjuNNŽÉdêíí]^^F\ÔG£Ñ0™Ì°°0“É;“Éœ-//G\ìËÀ…›Ížššþêêª@ À¥A~áçç—œœìààœœ¼´´„D‚ÈÈÈÀ¸Ú¿£E%bjjjjjŠÇãÙØØ…˜˜˜ñññññqt›-))ÁAF³ºº:==M£Ñúúúà¯Õj§¦¦‚Àl‚ ôzýÜÜ\HHˆ¯¯/šW[â{zzž››‹ÝyR©T§Óyzz"î®]»fgg===¡Rš››C\ÒŸ „¸ðwssûéOÚÓÓc0àß××WVVÖÚÚ þ.\¨¨¨èííݹs': €gss3ìðÿâ‹/€ùòå'N À„úƒ655•––â|8(ŽŸŸriooýõ×kjjž{î9N'“É^~ùå‡òùüòòòÁÁÁ²²2:>66VVV–™™i2™WXX˜N§S«ÕO?ýtlllWW0¡ojjúÑ~dÉu¨¬¬üÁ~ R©är9—N§OLLçææÊår˸£££¯½öÚØØê|ðàA‡ƒÛÚûö훚šÚ´iÓàà J¥Ú·o_JJŠeõÈ(®®®óóó±±±B¡ÐÆÆQÒÒÒ\\\ÜÜÜ^{íµÆÆÆ€€€ŒŒŒ[·n-¢Ÿ>}šúé§Ÿº»»+•J¹\®V«“““mmmY,Voo/•Jíêêrwwß¼yóòò²»»»››ôàKKKËËËõõõr¹wóöïßçÎ*• ûàà```ào~óƒÁ€–,ÀÁ ­-[¶°X¬¶¶6©TZTT455¥×ëãâât:Ýãp°‘ŽØlv@@À_|aoo¿´´£Õj EVVFÂ>ʳµµ•Åb™L&Ä Ÿ••Ä…?A]]]A`$,ž*FGG«Õj;;;±X<;;‹|Ñ4&338,K¡PàÆ„···D"ùì³Ï Ÿ>ü!ÆR«Õ:y!.Z‹YòA›••5??¸À¸zõ*fvXÆ C=CCCQgÔM¡P ƒþëÖ­kmmÅ_Éê‘QpôÛÚÚP ‚ ð*¼[úûûezzY€-ǃN§SwïÞm00ÆÒÑÑ¡¯5 2™Ìd2µ··«Õj´éÆJNN¾yó&ùëÄċʼnD¤](êtºêêj›¾¾>à £m—^¯ONNžššêíí‰D‘‘‘/^Ä~¯/Åáñx---aaaÓÓÓsss###óóó---b±#q÷(ÏÄÄD£Ñˆ.†ÉÉÉwïÞ©TЏV§­­­ÀÙ¶mÛÍ›7™Lfcc#¾¸á022233Ã`0€C¥R'&&°¡E&“ÙÛÛ¿õÖ[·nÝ >ü———Qgìœ!ûf‘u&ùu@^äé&ð1Å0-㺻»£ž“““¨3ê&‹Q‡••øGGGß¾}›ü«U¨ÊÈj¯Â»…Ïç#н½=²[‰DBÚ WWW‡“*œýp¹\(»qæäåå…§Ehk©…|>'ãø• G¥R­ìÎÎθ6AR©b_‰D‚LÐÓ188/¾ÇÁÁ!88 ///*•Šy§¤ÝÓÓS$=Ž'F ²··'ã‚e\øc‰cooD£Ñ$ Tp³³³C\àP©Tà“þè Åd2Oú“u&ë†åƒ: /ÒÄ÷ôôôôô|4.êIÖ™¬ê@úGGG[VÕ* yôQ òUä»…ŒbuôI;A<¢["×ã9äeããܧ+úR´Çá<ª—z2½'ðÇãi%0úJbÓu=*Ûz² í+×_øòovQvîÜéééY[[»aÆ•••ººº5kÖ`¯««kSSSHHH||ü|PQQqîÜ9‹åêêzêÔ©çž{nee¥ºº÷ ÿýßÿýƒ>x饗¾óïÐéôýèG7n´±±ÁÈ]ÿg?ûìF£1""³‡VVV>úè£Ý»w744DEEÙÛÛWVVVTT0™Ì×^{ÍÒ¿½½½³³óÕW_ýÝï~WTT¤R©þð‡?|ðÁ?úÑž}öÙÅÅÅ·Þz þL&ÓÕÕµ²²²´´t`` ¿¿-h=jÉóÔ©S¹¹¹2™L&“¥¤¤üä'?qqqyõÕW=ºnݺ±±1;;;àhµÚW_}õÃ?D¾ÐÒ|öÙgO=õÔÊÊ ôReUUUEEECCC¨çèè(‡Ã9sæÌââ⫯¾ ‘;‹ÅÒëõééé  ‹Åâñx{öìihhÀˆ¨¿»E­©©swwW©T‹‹‹ÃÃÃjµú£>„m½^öìÙöövŒ®„ŠÁ`Ãff¦§§ÇÑÑ1''ÇÞÞžF£½÷Þ{ø"‹çñxVøÞÞÞ°CÁs÷î]Ø‹‹‹ÑmWVVΞ=‹‰À–þ;wî\ZZ=qâ›ÍF\GGG½^ïêêJú;v,+++**J$eee}üñÇR©ÔŠgzz:ì---ø$>Îù¢££“œœ ûÐÐòõòòêêꊎŽF;IÒŽ|íìì·»®ý>å IDAT»õtvvF^À!"""âðáÃ\.—Íf!‹aINN>|ø0Y‚ \]]IÎßË¢úøø°ÙìÎÎN;;;è{°QX(Ö××K$¨,T*Õo~ó›µk×b›n"ØÚÚº¹¹ ØÛÛ'&&ÒéôðððÍ›7WVV¢ÅHxx¸~RRì<BØ5MKKKRRÒõë×ëëëÓÓÓ¹\®F£Á³ÒÛ(¤R©££ã¾}û>ú裵k×Òétgg玎@€GàÐWÙÛÛkµÚþþ~|€q¹ÜÕÕUø“<`G9psA*•666úøøày ÎÌ`‹‹C¾Ÿ|ò v4Éåò™™™   Ø‘ïÝ»w—Üx}íÚµúúúM›6b›ææf< ¼qã†\.§ÓéÍÍ̓ƒƒÍÍÍ“““(A|>ÿQüßø¢EEEQ©ÔÙÙY*•Šk´ÕÕÕ±±±……©TzþüùÕÕÕ‡ÆÂ‹/vvvB…‡Ž÷îÝËÎÎniiùüóÏGGG;;;£££¡{¼~ýúðð°›››%>t]ÃÃó³³333£££ÎÎÎSSSçÏŸOKKkiiÑétÑÑÑÕÕÕ¡¡¡“““Ї‘þCCC.\Éd ÀÞÞþøↅ…µµµÕ××ú¥ªª**•j0Ž?ž››ÛÔÔtòäIKžMMM™™™MMMJ¥Òd2Ý¿øãããaaaÕÕÕ111G={ö¬L&ëííE¾¶¶¶vvv§OŸvttT*•]]]°»ºº"":ß¼yõĸòcÇŽÕÔÔÈd²û÷ï/,,twwÛ—/_¾sçÎüü|ww÷èèhzzzKK‹\.W©T“““ßô[åÛõíúX4ô£¹ÿ~YY™D"¡Óé999áááKKKh×Q\\œ––¦V«÷ìÙsýúõ¸¸8L™ËÈÈV«Õe Á …bË–-J¥ò©§ž²ôß´iSpp0…B~ww÷æÍ›‡‡‡7lØ ‘HÔj5üI>[·n S©TÛ¶m3|>Û¶nÝ111±cÇèÆ ‡††VVV,ã&''çää(м¼<‰DÒ××'•J}||¢¢¢À3,,,88xvvvûöíhÇÖ8 ¤,--mxx*møoÛ¶Íd2­¬¬Xñ)//ˆˆèëëÃ.’ØØXÄÍÈÈ0™Lsss°‚g~~~XX˜B¡Ø¹s'®ÿ¡W+++³Ä'í&“iË–-r¹vÔmûöí–uvppþòòrRRÒºuëÒÒÒ EYY•mÆ ÁÁÁ333VÕÆQ#í~~~………*•ª¨¨Èò]_XXUÜ–-[zzz¨èï+ Ñ2 µZ½sçN¨kkkY,Öèè(Ž—””´µµ•””lܸQ«Õr8œ[·neff666²X,xÜ»³ô/,,ŒŠŠŠ‰‰^J­Vûúú¾ð ¸ƒé.ð*•ªP(¢¢¢ÊËËÏ;·iÓ&ð1™LÉÉÉhqáÂ…œœœôôtœZÅMKK[\\¤ÓéÀçp8À– ¤þ$~AAA___jjªÎÊÊ Fb£‰‰‰h]Dúãñ¥ðÌÉÉ?Yø“vðÔjµccc¡¡¡¡¡¡z½>++ qCCC­ðI;x’vÔ «:vv6//o||Yäåå¡=6‰†W=Zm+;²Ãe¾å»‚B¡Œ………AÔÅÅEè¥qï5==ýܹs¶¶¶J¥rË–-))).\ uH ÏUæææRRR¨T*“É„ž‰Åb-//'''ãþ§¥?¶nÒh4üçž{nxx†þàC¡P¦§§íììËË˹\.ø”——WUU¥¤¤LLLlذáèÑ£4Åb¹»»[ÅmmmU(%%%Àß´i“ÉdòõõOµZ þ7oÞ>Äé®®®V8ããã|>ŸN§£,«¯¯1óóóq+Ÿ ˆ¡¡!K>L&<…B!ü•‚àp8°ƒgNN…Béééa±Xè«‹¸e‰»‹‹ xªÕjØQ7l9¶¬3ðsssÑÛ Y0Œùùy611axz¸‘ÕÞ¿¿•Ùa¹å»âþýûñññ÷ïß+G%B.—OMM988Ðét­V;33ƒÝ2ëÖ­ëêêâñxø‚@;×ÞÞÞÍ›7766¢£Ç‹‹‹²hll¬¨¨èééÉÊʲ³³Ç«ÔjµeµoÞ¼ie'³³zWTTT@ AVï¿Î¶½Óýd}©—úJ½‘•¿ÕzÜvÒnÕé¿Áóqø–žGïQü'§óhÜ?WößÓ‡‘ëQbèo`ÕvË*ŠU5¾Òþ•‹†!3*•*00peeݘЪ£   •••åå嘘½^¿¸¸èáὑ···R©d±XL&=gá¿´´¥ÓéX,p|||¸\îììldd$A666¡¡¡° …Â………ˆˆH4]\\Ð)žÏç/,,„……ÙØØP©Tà +ßìì,ðíìì¤R)$DÀÖÖüõz}TTú] …BtÿÖëõL&’#àÓËHžf³ÙÛÛ[«Õ‚çÊÊ p$ òBS@àìì ž–qgffPËÆQD£R©,K(‰ÑÒnÕÈêÑõ8ûãÌf3Úò>9Ê—ö»z‚ýÉ‹ö /h4š‰‰‰ÜÜ\4 òññIKKKLL´µµµ·· uttôðððööÎËËëè訮®®ªªzñÅ{{{'''_|ñEŸŒŒ K‰Dboo_PPàèèˆûÔ………111‹‹‹±±±hSëèèèä䔑‘199¹iÓ¦þþ~vàÀ¦¦¦×^{-66V.—Þ˜˜èèèèìì•““5bAAÁÚµkWVVÜÝÝ·oß{íÚ5±Xœ––†¶¹ØiŽs^ð_YYÁÞ¡ŒŒ Ò¾fÍð÷ððxå•WÆÇÇãã㇆†víÚeY2¯ÁÁAKždÜÛ·oWWWWVV...âªÙl6ÿð‡?„êP(j4©TªV«_ýõÉÉIôƒüß·¨>>>P’¡P(‚ƒƒß{ï=ƒÁ§ÕjaŸ››KHHXXX8pà@WW——'%%ácÆÊßÏÏïúõ맺º½–¡CBƒäíÛ·Ã>;;{âĉÙÙÙÕÕU\r÷÷÷ãj4PÊÏχ¿F£¹~ý:fƒßÎÎîæÍ›ðW*•à¼á???þð÷ññA\­V ;ø †ÂÂB…B žVõ!ó²âIÆE}0äâ½÷ÞKLL$ÂÝÝÝ—Þ{ャ¬,Øåry^^:“ïØ±ÃÎÎî›|#üµuxxX«ÕB#屃ƒƒåVq__ß––.—;22bgg'är¹Éd²±±™œœtww·òïëëËÎÎÆüA´\ÃèÛ›7oF;;;ØœœÞ~ûí;wîØØØ(•Jìa'þ¸‹|~~ž´ÃOý4M?ðu:]ZZÞµóóó˜8¬×ë‘—££#üÀþ>DÜ   ØÁ?((èîÝ»îîî2™ <­êCæeÅ“Œ‹ú¸»»ëõú½{÷âòÌÌL[[›‡‡ÇÞ½{¯\¹ûÂÂÂòò2…BQ*•gÏžµêÝøw¿˜L¦D"¡ÑhŽl{jooHÚét:>‚àr¹T*ÕÙÙ =¥?•Jõ÷÷g±Xv “&" Oß`GŸ*[[Û€€àƒ€H$òðð R©°“þîîîèã |6›Áyð'_Næ’?é¸ v’?AhñžVõ!ãZñ$,ÚÅ¢>–Eööööòò²:í±¯óØ~Ó˪ÓW6RzÜU ùªÇ]…Y†{4îã.7ÕKYù?®–ŸGeR_ªÇzœÿ£v+ÿÇ Âž \³Z¢ŽÍŠØãêÿä¸V}B•žLþQÛF?tè‹‹Ë™3g Æÿý÷ß~ûí]»v=óÌ3|>ÿìÙ³±±± ï¿ÿþÎ;ëëë1e©¡¡!333!!áwÞ)--=þ|LL ›Í>sæÌ3Ï<ƒ¾YkÖ¬ñòòêè舊ŠêêꊌŒ\ZZB£)µZM¥R]\\*++7nÜÈd2>¼{÷nKœ¥¥¥þð‡~ø!dÔ ƒÏç=ztÛ¶m7nܸÿþž={àïââRWW‡9Ê555¹¹¹Z­–B¡°ÙìÊÊÊ={öÐét<„ÖjµKKK"‘¨¶¶¶¸¸øÆÓÓÓÀHKK{óÍ7ß~ûí•••'NÀŽæ>$ÏÏ?ÿ8>´ô?|ø0êvðàAðß¶mÛƒÚÛÛþóŸïÚµk×®]"‘èÒ¥KAAA /¾ø"¶}/..FEEµµµEFFÞ¸q£©©ióæÍc8;;×ÖÖ¢ïÍÑ£GŸþùúúzŒœ¨ªª*..~ðàÁÍ›7Q7///त¤XòAܪªª}ûö >|xË–-¯¿þ:ùךšš 60™ÌãÇ[f}úôéýû÷¶¶¶’vË£ó³Ÿý Ù•––FEEµ··ÇÄÄ0™ÌW^y…Êår¡Ozçw(ŠL&ÃuŠH$ºs环¯o]]ݵk× Æêê*“ÉLIIa04 öððð••è¸Y,n™òx¼®®.¨ÿ*++çççÛÛÛ¡—´f2nMM@ @9,q***t:NG—ð‰ŒŒlhh°³³#ý±-›Ôc ööö ମ®"¯ØëêêÐÐ8$~KK þ«?i·âIâXù“uC\<<õööV(°WVVŽarøµkרTjLL —ËE}À‡ÏçÃîïïìØ±Í›7ãf}@@ê´ÁõööNKKCH+>ð'‚ÏçãÜÃÃc``Àò¯!¬²¦Óéxi·::r¹œÄAtàAutt¬­­E¬S§N‘Ÿiü1îççç_¼xz¬5kÖ` GÆÇ¾Ïƒìíí³víZäåëë {hhèÅ‹Ñ}” ˆððpàãW@þ °[ñ”J¥À±ò'ç"n|||?:˜Áýûýû÷Q·ÔÔTèÆø|¾Ñh$»“v³ÙÌårñ\‹Á`LNN¢þÀééé¾­­-êì°äCÆ=zô(‹ÅZ³fÍ;wÈ£Œ¿"»ØØXˬ¥R)^»ÕÑA3UüïB¿àØÚÚÒ´Z­T*=wîÔòƒƒƒz½~||ÜÛÛ›ÉdÖÕÕÑh´þþþ¥¥¥‚‚‚ææfè±NŸ>½²²Òßß¶0x‡EGGŸ###™™™–8IIIEEECCC%%%R©úªååe©Tš››«P( ömÛärùÎ;mmm'&&Êˡ‡‡Ñ— ýÀþ{WÕä•öïûf' ¶BJ@ ‚‚JÅwÀ•V§*µµué™™¶:Ö¶_§¶==ÓNg9gfìëÔãÌètµ–ÚZ-S[)âÎb‘}Q !I {òýñ´ï¤Ùx߈[›ß=örÏóÜ›ûn÷>‹ÕjO#¢F[´h‘B¡‹Ål6;??ÎŽ`\IIIÐåÊ•®r ýúõ륥¥IIIÇ òA›Íöðûf½’Ëå+V¬‰D­­­®¿ L¬kŒä=Ül6C7>ŸŸ““réÒ%x%ìîîNLL€qo†aÐKðáÆår …ÕjEq8›Í– P(˜L¦B¡(**‚‰E÷f~,Ú²eË Ô ›ÍÖjµfΜ9}}}999f³ydd$11NX¡‚ ¾øâ ¹\Ž:tèDûCŒ×ñãÇår9ì'­Zµªµµµ««+''çë¯¿Ž‰‰—1©TzåÊ7½gÏžMNN&Ú¯\¹R^^IlfΜIØ344ë*'%%…ËåÖÔÔ¤¥¥!„ªªª$ICCŸÏOKK;}útEEýæççëõúwß}—Çã]¸paÇŽýýý]]]P5^.— …ªª*HÒN—.]ŠŠŠb2™—/_.,,D;v Å“““…Ba]]]qq±Ñh¬®®NLL„O³Ù<<< ÷¹k×®A5²ììl³Ù<88öTUU©ÕêÏ>ûÌn·GGGCi´£G;v >:;;a› ¡¡¡³³³©©é®’[·äÝ€¼ú9Ž;ž{¸þý¨<ÕQÝÙ÷åÿDÖsÈï¸<õúU·ªŸ6hqqqÑÑÑàÝ!•JÇÆÆàn<<<œ`0 ]§ÓMŸ>Ýd2Á§©Á`ÉdÜ"77wllL(ÆÄÄ@þ§¤¤¤ÁÁAHcÂçó322T*Ujj*Üð¡¾2¸DBñ>¨˜››k4 ùr¹<>>^©TfggcF§Ó³²²T*è{FFF„BajjªÝn—Ëå±±±à§e2™¸\î”)S”JeZZ‡Ãƒþj}§¦¦BApjÀ0lÆŒðÚDÈ1 Pü‡è?<<zôhvvöîÝ»ÛÛÛ…B!d€ýøã;¶téÒÂÂBÈ7¼dÉ’k×®œ^x¡¡¡aþüùç&—Ë!D¤ººúÙgŸ…‚Ø ,ÿ» @)ÊÒÒRôèÑ;wöôôDEEegg···ÏŸ??,,,"""77·°°P$|…Ba³Ù`+å‘G+W®©T 5]ˆþðâ,Ö¯_Ÿ““£V«A/Ô¦S*•‚‹ÇãÑh´’’’ûî»ÏµÿÀÀÌTµˆˆˆX¿~}CCC^^‹Å*))™5kŽãð#¹Úã6?‘‘‘0Ï›6mù7nìééáñx ´´ì »wï¶Ùl ?++ Æ»`Áð³€ù™;wnXXXTTTYYYOOO___|||AAÁ´iÓl6[WWWffftt´^¯ä‘Gúûû‹‹‹›››}ôQ(Þ¹fÍ×Ñ…†††……‰D¢©S§.X°@¥Rµ>ú(ì‚–••544ˆD"è³×××·{÷•J…···›Íf&“Y\\¬V«!Œ744æ­µµææ9""ä`& !w#„²AX…íƒaÞ¼y½½½n£i±±± …F£AÿÐÐКššÈÈHEJJ ô‡ÙCAû÷¯¡Ä²G"©T 'M<z@z'±X Q\Ð.‹Åb1“É”Édàê r"##'MšÄ`0’““Á‡I*•â8.‘H ¿tƒ@"„H$‚°t7½111à¿Ù„B¡X,æñx JA»Êçóù†v†‡‡ƒ×!è%ì!Ú¡R¡’‚‚o|ˆ$%%Á©°kB>aŒ—èÏår]å¸Î›ëüz ù0^ÏvâwùÄxaÞˆù!Ú‰yuÐ 6£-¦Ã0·Ñ¹i!ú£ƒQý‰Ùƒöï_à}yÞ¸ùy~æøÊ;å%‚ŠZñ*Ç—nk<¿æ|Ù鿯äË OE¾¢•H&¸úI~6Ò6nÜXTT4<<¼{÷n™LÆb±zè!‰D’››»páÂáááíÛ·Ï;·££cÇŽ£££ .,**)//‡´§>úhzzú¥K—##ƒ°ç¥—^*,,„Øn™L6kÖ¬9sæ(•ÊíÛ·»Ê …7nô§Óéo¾ù¦Óéœ3gÈ!Ÿ/|Ébyà­0Àë˜IDATzÁ΢¢¢±±±˜˜˜–––k×®………=4 ¼‹æÎ{ðàAØÕ„rŠnò¿þúk§Ó)‰`¼ýýý äÏž=ôrÜì„´M‰‰‰nòáûü­·Þ‚× „l¯¿õÖ[o½õ–J¥E!±X,“Éîô’˜àõ»¹¹ùÈ‘#l6ûÃ?‰DV«Õáp„††BØ \|óÍ7¹¹¹YYY§NŠ‹‹kmmÅq<**jãÆ‡ÊÉÉa±Xéééо|ùrð+‚þ‰dݺuï¿ÿ¾^¯9áááf³9222""B.—³Ùlh‡š—)))¾ä€\.ô‚­­­UUU|>?%%¥©© ÎéX,Ö<þIpå8ŽsçÎ?~<''ÇM>L²Ùì„„ãt:CCCõz=èµX, ÇÍNƒö»É …ýýý«ººªÑVTT´¶¶VTTDGGƒ"„¼¢ÝÉå0q Abx‹ÅyªÀGç£>jii™6m€€§NAAAee¥Ñhÿ$»Ýn0úûûá–pðàÁööv¸Ÿ †Ã‡_¼x±­­Íd2ÿSjj*ŸÏÿꫯfÍšUYY©Õjººº¾üòËîînB~cccZZÚ§Ÿ~j³Ù¼Êý·ááa¨L^SS3mÚ´O>ù$++«ªªª­­mþüù•••ï¿ÿ~{{{uuuXX˜R©ØŠ«¬¬¬¯¯ùÉÉÉ*•ê“O>9---®v=ztΜ9IÀUþåË— ø'Y­Öôôt¨G|õêUh·Z­ ¨¿¿hhN±‚"ï Íž=»¤¤ò0edd€ßŽãÙÙÙÑÑÑP˜O£ÑlÙ²¥ªªjÖ¬YüÐC)Š–––Ç{Ìf³¥¤¤wwwCú(§Ó¹aÃ!“ÉÀOkñâÅr¹œÁ`,Z´(;;vŒ7lØ •J›ššÒÓÓe2™B¡ÿ§‚‚‚¬¬,F³nÝ:8çùóçχâ«eeel6›Ïç/_¾¼½½òiõ÷÷?ùä“UUU¡µk×¶··¯]»6##£¾¾äC~©ööö5kÖÀxŸxâ &“ÉårA΢E‹äryww7Œ+""Ú×­[g·ÛûûûAŽD"{`ß™_\\|ãÆ|6fyäÇ!Vkkë/~ñ ©TªÑh ww7ØYVVf·Ûm6ô—J¥ íÚµYYYv»æ-$$~¯+V@®˜‡¸¸¸üü|(ü”••U[[›“““PXX˜][[ëªÅn·ƒv©T ^kp†100à6ÛPw²®®FÝÓÓr–,YBü 8ŽO™2ä”””Èåòï¾û‡‚Õiii™™™¥¥¥'Ož,..>qâ‡ÃÖÙÙÉãñ0 +**:sæLII xA´»Ùl…¾æææÄÄÄÔÔÔ±±±‚‚‚ Ô××ÏŸ?ÅŠpóïèèèëëƒäúqqqà=B§Ó{챬¬,ÐÛÒÒÞ±«W¯>vìØŠ+@~FFÈáñxÇ/,,„<'v»ì×h4`gJJÊ–-[8´òÁþ¢¢"h—Éd"‘H­Vƒ Ã@>1.B>Œ‹F£°'-- ì$ä@û¼yó`\>ø Ì'ÌìJ+ŠäädèOØ ò‰ù'æsöìÙļÁï5wîܘ˜˜¤¤¤èèh˜‡Ë—/ƒôG€—s__Ÿ›ÂZ¨_§Óéà×t›m¹\¾víÚY³f£9|>fiÕªU`-È¡Óé`UHHÍn·K¥ÒúúzxUïéé³CBB”J%¤’·!­VK§Ó•J%±«T*ûúú$IKKKjj*µZ­CCC2™¬©©I£Ñ…BF£Ñh ‰mbbbmm-›ÍÆq¼§§'11ÑjµŽŽŽ*•ÊÁÁA½^zÇÆÆ0 kllÌÈÈÐjµ©©©­­­ƒÉdvuu‰ÅbHŽªR©¢££‡Z­K­V›žž~öìY­VËãñÔjµÅbùCCCJ¥’N§[,µZ}ýúõ®®®„„F£R©&MšvÂÑ“D"üŸPæÉjµ‚:x—Ãx1 S«Õ §µµ555õâÅ‹ÑÑÑV«µ³³泿¿_(vttðù|«ÕÚÖÖý؉‚tSÐä455ãdO©­­‘J¥W¯^5™LP¨&66¶¥¥Ål6C®W('®V«i4šN§Z b¬…ìyF£‘Á`\ºtÉu¶›ššX,VGGøŸ FEE={V§ÓA™8[Cµ··ŒŒ„……©Õj+¦L™r‡žÂAü”ñ}e="þi\ŒŽŽB– ëçÀB1™L’,¤L¢Cˆ)<žý€Åb3YLƒ^¯R© 3“ÉäpBôzR©¤Æ Ñ먱BÇjµööö’g±Ùl&‹e2oܸAžIfôz}__yŸÏÇpÜb6wwwßêÙ€lá:ŽÒôz=¡ !d2™HæÄÀ!ät:ݲry‚F§I$IuµWˆ2¬I±±a4N¤)'ÃFD0LˆÒ$Ï¢ÓéiS3šÿÑFÎÂ8‹Ål2)±“’Œcc®•Àɰpœ=44H‰•(±Ûm :ƒÒl$IecÆ1:…I²$IR“ÉÈ`þoæ¡ ¦–'èt:Ù2@½>Ý]],So0Pb©”J.—k³Z)±%c££ô'D&“‘Ádòîeåü#„Âb±##£(±†‡µ4M30@‰e³Ù8œ›ÝF‰e±Z˜ ›bÎ-“¡Ò²9lJ,¯ Ã]Žä½Îùˆÿõß_’$Åq“ɤÄJH”˜L&:A‰¥Ó°9l:N‰…ã4 aÄÈH² BÈAq6Øl¶Åb¦:‡˜™ÅdQb©ûûccã =%–ÑhŒŽ‰Öi ¥‡ §ÓI'Onüîªy\JwW'ŽãDbò,“ivIDF†5 V ºÞVɰzn\@W{{“:Ëd2uvt¸¶a57]c0™õš}úâÅ‹‡ãÀ”Ì»mÈËË;wîÜÛo¿=::J)AMkkëþýû‡‡‡!c…˜L&ðŵX,±±±###F£Ñõ«ŸÝõIIÀáp0 "¾Åõ¯Dg7–F£ÉËË;zôhiiimm­Û—¿WBÈjµêtºšššË—/kµZ2ºx½Vü³¼>úý³¢¢¢6lØðÏþÓs9úaÙív8eƒÛ0¥qQµÐb±°X, Ã`³€¼.Ç1 £Ñh6›Í‹xêõúmÛ¶ýñ„W(=>dž»<Þ·ªªªÊËË%‰×È$_sÑØØÿÍ7ß”––^»v$ëË/¿ÜºuëêÕ«”²%Ãò?,(¬uñâEâ,l\Vii)Ç[µjÕ²eËžþy’¬«W¯>ñÄ{öì±z;B˜Øq:ujÛ¶m)))£££P® ËétN™2eïÞ½4­¶¶– kdddûöíêÚÁó-ÜûéÅ‹»ººìvû믿îÕ&¯¬#GŽ@ÙÁgžyÆèrúæŸuíÚµçž{.<<|``Àש‘×A>ÿüóþ«9xeUTT\¸paÀ÷¹Š'ëСC‡ö%Ы¶¶öÿþïÿÌf³ÍfóµåèUà§Ÿ~ê?ÒГÕÜÜüüóχ……õ÷÷CÚ0’ºššš>úè#N÷£Bp~Y¸ÅyŸÛ 0õccc^o’ž,âg&*‚a!„t:ë.I–§2,›ÍÉ#ȳ|Mú¸º|EFøgùºZ&|M&Q&Ò+ø¼cxíµ×(ÝEȨ ²îÖ_|€’gƒÔó…ßÿuã AÖ]ÈòÿdøŽÜà‘NuKð³;Ò ²(±¼fÍ$C§#„,‹Íf#)‚xµ ²~¬2< ¾PäY<ŸÉbBumâ÷òO¡ 'ì¼ûïAIÜ­féuº&]£Wºxº”auuz/ð§Ó‰HŸõŽ#g<Øív·ðrºœÈ‰ÐD/&7Œ¿Ýp·­-¢gK¯×#¤wcM,œã¾¼ß%«jË–-pôä‡îŠÈÈÈíÛ·{u ÀB?¬¹sçΛ7* !”——·bÅ J¬ûî»oáÂ…éZ¾|9U–+¦OŸNõ#fü—wJ¸E¬ûî»Ï-i˜ ‹ŠŠbbb¼úq`¡Vrr²¯”ˆþuݸq£±±Ñ³ÝK&“AU[ªº$ ‘Èž< À`0vìØ±ÿ~Ï…éËjË!¤P(Š‹‹-Ë»ï¾ µeÉ //oÑ¢E:îÈ‘#~vÝZÂÂÂ6nÜÙ5}Iöd%&&æåå!„Äbñ7H²BCC7nÜh³ÙìvûçŸÞÕÕE†…Љ‰Ù½{·J¥‚j$Y‰‰‰ÉÉÉž¡¶þY¡¤¤¤ÒÒÒüãCCCäYþá‹%‹_}õÕ¼¼<«ÕÊ`0ÜN£g̘aØçŸî•KùK¡P|õÕWÓ§OðÁß|óM·ž¾žk›7o~ï½÷ ¤ ±)7.kÅŠáááGÍÏÏ÷¼¶|±úûû!>ýÚµkž£óÅ‚š|ðÁÎ;¿ýö[’ºB0¹»víªªªjmm%Éš4iÒ”)S¼N¾ƒÁØ´iScc£k<û¸,äû™àÿ×ß³gO^^ôÙ»w¯Ýn‡mø/Nï½÷|é¢üUh·Û.\êõŠñÅúôÓO‹ŠŠôzý¡C‡È³âãã/_¾ìÕCÚËh4êt: Ã(ì‹ÅâÆÆÆÚÚZ"CBH¥RÕÖÖšÍf·j%ãþҞ㲦NÊd2ÿò—¿Pb«Ëžzê©'Ÿ|ÜïÙ³Ç3ÊÄqÞ±ÜZTTtâĉëׯ“ߨd2™ÉÉÉûöíÓétóçÏ÷Õ ylªÕꤤ¤)S¦Ðh4ò,§Ë,“gi4©Tš’’B¤n#¯Ë¿Æ‰²ÐétÖÖÖ^¸páÑGX]NëÃd2ýþ÷¿úé§ɳ™¯B7 Ÿ:ujñâÅJ¥’|Õ³Ù ¹ói4ÚgŸ}æÇ·–£Gâ8^\\ ¥xI²B===¾Þ®üèr:ðõäkÊ<Û{{{áEó»ï¾ó}EIšÿ¿öõõuuu8pÀápLž<™¼L•Jå™óƒ$œNgeeåc=æ5ìÖ(»Í¼ýöÛ8ŽûzKõ%íĉ'OžôÚÁK¥R½òÊ+ˆâ!ôé§Ÿúú“/á¥Ñhv»Ýk(½WñêúÆoו˜˜¨P(Ôj5% Ož< ÿxíµ×ȳB§OŸöõ'’¿¾×HL?pv¤ãËWÕínû9½ñjXuó,«ÕJ&3I€—3&üt¢´¢ çÚÀX·Y]0‹ŒØqîX…îƺÍꂬ›gùA0®0ˆ[‚à ▀Žb±X111”hz½|ÂÃÃÁù‰ ºººššš‚,ƒát:ÛÚÚȳ€b³Ùîȸ(­Xß¿cùÏë â|†N§“?ž$¼ïBV—;6:z{X²ääÖ–J,§Ó™œ2¹éZ#%‡b·Û, %Vhh† ¹z’_!°6èofßêår¹âøø¡¡!•JEžÙÛÓCi[YÏãñ”}JJºB,&sÔ` º… Çq„0È«NžeµZ‰|ñäYÀh2Bæwò,:¥Õ»nù§¸Á9î!´&y•!\.“Ųºè‘aY­V›-ð© ωÐÿv )LJ`åÔŒ?.øF†…a˜ÓÅDòºœN'áG’e2­ U]cccLÎá°vÓ…B˜c@­Ö P7ß5ÔSM'×ÓãÏ Ë˜,–Ÿ´Û^Áf³ÅâøÖ÷Bþa·Û1 #¹‡IúS »ÝîäÇņG¼—”"À¿ )=2œN§Åb¦ÄòZ”’µ”XC?x‘“g™L¦¶Ö·;]mmÜ<‹F§ Ë­:IÖèèÿ|*~ Ý¬ÛÌ­û¥ï6,·2Ĭ*ôË0%–å‡ËìŽÌFðwÇzüñÇBÿûßýk½WI¬²²²ÐÐÐ?ýéOw­…·”å ?ËÃé'Ïû–-[ø|~HHȦM›() …ÊaaaanQŽ~Æ&Øl6F £TµÃá¸ÕÚ—åj¡[¾!?,:Î`0"##Y,y]‡Ãᄇ‡‡„„d ƒ!‰pçóùn‡¹wÉZwyxnÞ¼Y üá@íØ±cãÆï¼óIk^xá…sçÎ544¼ôÒK?þ¸g!S¯X½zµX,®¯¯/((xæ™gH¾¥¦¦¦>ûì³6›­­­Í«'¸WìÚµëÊ•+uuu{÷îݼy³¯0 Odff¾úê«¡;wú pÃúõë Žãç—¿ü¥[•,¯xóÍ7u:]LLLww7ŸÏŠŠÚµk—ÿØÛ 2Ë÷\Œååå<ò\Í8އ‡‡¯Y³¦¬¬ÌµÓnôêêê3fäææ677{-ë•õŸÿü'))顇:xð ×È>¯¬U«VÕÔÔìܹsllŒÍf“d;wnÚ´i …âÚµkž«Ê !ÔÔÔ´cÇ&“9cÆ ’,vãÆ_ýêW\.J)Ëb0Ÿ|òÉ¡C‡âããŸ~úi­V;mÚ4’úÁͰ\[Æ]@ñò(|ÿý÷KJJBBB a7—Ë]³fͱcÇHšræÌ™Lvß}÷}ýõ×ä066644Ä`0(Õ>år¹ƒaxxøã?&¿)_]]’’’}æÌòºB‹Åjµêõz>ŸO‰ÅåÈo1X,½^ïp8¬V«Édb0n6gßMÂu…\^^Þá&o2™öìÙãp8,‹×¸ó‡"7 jµº¹¹9%%åìÙ³n":{²-ZÄår¿þúëÍ›7¿üòË$Y555Ë–-999›7ový«ÖÀÀ@{{{rròË/¿LÞB„\.///‹‹khh ©Ëu®Ð!?,Ïþ®ÿð£+""¢¼¼üÏþ³[…Dÿ¬™3gfeey¾†{íLfy8ýl7¼òÊ+ðêM5R!ÔÙÙ922Bi¿qppðõ×_×h4Ó¦Mc³Ù$O¦***&Mšôá‡z>@ýàí·ß …”,<}útMMD"yùå—ÉÇØü÷¿ÿ…iÜ·od”û÷ïùû÷ïG>|˜¼GnDDDVVÕZ½½½T‘ã.ŸÛ Jм^…¡‡z¨°°ð·¿ý-ùk!TSSÿ¨¬¬$Ïr:ÕÕÕT-D¹eï ÂR¿uuu”Xà€|DzehXOçÏŸ'© !D£Ñöïßï¿X°'ëúõë¾¶<œ7¤ãÉ=uêÔ—_~é™ùAÖ¸¬ÆÆF_i·n›…€‰X%¹¿ÄO7ëÝ€¨,ç ëÞe‘°¼? ݪÔaæ+#~Àë2ȺwYÎךƒ}7Š÷;–Ífsýbb0žµV\?_IÆxW@uo±Ü€a Šâr¹L&Óøý­ˆÍfS ²X,°fq …$¹z½ö‚¬{‹…¨¬X>ŸqAq3 Mx¤bA „î±ê_AÜ+ #„p £të%žÙä¹7Éâñxne~†èëë#ÞnoÛÌÀ¢;N6›í?5ˆ'p‡ü$”¸7ÉJJJš4i%;z0™LpÔs;g>V€G:ì¶Qb±X¬èè„P¿ÊÕe*°m˜Ÿ$ÈLE¢Dât8¯_ï¾Õ¿—'ë.}ÇŠOHÀ0 ðظ¸;mË=ŒAƳ†ÅíÁ]šÜÖétr¹\»Ýn±NX­âŸ!È{]O8& ®ðV°0„™Íf›Ýe ‚O@WÜêÜ””ɇ£½½íftÝ¥w¬ŽŽv¡Ph2™Ì³•qóhkóé¬F·paA¢À¸‡C£ÑL¬=AÄ„<&øå=11133333³¸¸ø×¿þuRR%úŠ+Ž92±&QFãp8ÈÇäºêÊ݉DòÍ7ßÜNQQQ^ÛtÇŠÝ»w¯Åbùì³Ïžx≒’’íÛ·§§§WTTH$’´´´3gÎx-QGÀápÄÆÆŽŒŒ…í(Y¹lÙ²³gÏR¢L,"##GFFD"‘V«5Çh4Bí1ÇY,ŸÏW©TÐŽ‚»Ýn6›ïøùŽã´ø¶!++‹ÃáTTT¸[âú?Ï>ûlXXØÉ“'õz=†a_}õÕ‰'âããÿýï÷ôôø*ÕJ !!aúôér¹œÏç÷õõÅÆÆ’71<<|æÌ™·­îˆ/˜ÍæÁÁÁÐÐИ˜ƒ‰D°çp8ÂÃÃE"NŽŽÆ0ŒÁ`ÄÇÇßYËBjµúé§Ÿ¾ жnÝ_YY¹xñbÏ?ZXV«uÆŒ¯¿þ:±êÇ’%K<(“ÉΞ=›˜˜è__MMÍÅ‹¿ýöÛË—/ yøÁÂ… ;;;ÛÛÛÉSnˆ{-‹ÅÂqjjÚívxZ­VFŠ¢Óé:jùŽŽR½=ß  _á¾}áÂ… .Œ[5ÝûöíËÈȘ={6œÜxvpy§Óé°¥vá§Ó9oÞ<­V»råJ‹Å2{öìqo'yyy¡¡¡ …‚ËåŠÅb“ÉD>(´¨¨èŽß®l6[DD“ÉìïïçñxÇl6ÁíÊjµ²ÙlpÃq\¯×‹D"«Õ ‘gÄÉÝ P«Õ3gÎD“omݺuß¾}¡ðððÞÞ^ÏBˆËåRMnk0àÄÊ“ ïááánQV~X‘‘‘gΜ)**ò ¾#XYYY^óü¬P[[ {{”~5?3“¬Å‹×ÖÖºÖùÖÄo7À÷ÔÐП¢ÑžˆˆˆøÛßþF2¤3ˆ»'NœðÚ~·l677CDh? Ü¥‡ÐAÜë.¬ n ‚ +ˆ[‚»å+ˆ{Ä×:ñyHG œâæ‘3ˆ÷&YF£‘j‚žŸœN'‘øêvÎü¸,"`ÕápPÊ'DADAü?RˆÍ‡ÜÚ»VIEND®B`‚jas-2.5/images/edu_jas_poly_classes-full.gif0000644000175000017500000021265407773340004021447 0ustar giovannigiovanniGIF89aìLñïïïÿÿÿ„„„!ù,ìLþ„©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡Ä¢ñˆL*—̦ó J§ÔªõŠÍj·Ü®÷ ‹Çä²ùŒN«×ì¶û ËçôºýŽÏë÷ü¾ÿ(8HXhxˆ˜¨¸ÈØèø)9IYiy‰™©¹ÉÙéù *:JZjzŠšªºÊÚêú +;K[k{‹›«»ËÛëû ,N^n~Žž®¾ÎÞîþ/?O_oŸ¯¿Ïßïÿ0 À <ˆ0¡Â… :|1¢Ä‰+Z¼ˆ1£Æþ;zü2¤È‘$Kš<‰2¥Ê•,[º| 3¦Ì™4kÚ¼‰3§Î<{úü 4¨Ð¡D‹=Š4©Ò¥L›:} 5ªÔ©T«Z½J(€Ö­\»zý 6¬Ø±dËš=‹6­Z¯X­} 7®Ü¹tå¶@€Þ½|ûúý 8°àÁ„ >Œ8±b¾Ü%–w±äÉ”+[¾,¹ñã‘1{þ :´h½š7ë<:µêÕ¬I;6ÍuëÙ´k'. Û—lÛ¼{ûÆãnßÄ‹«\×pãÌ›[FžœârçÔ«†ÝÖtëÜ»3~½âvï]ûæÿ½÷ÀØÕ}?¾üùp™©·^ž±€ûúþ×/nžCüQ‡Zg‘ Hšÿ÷‚ >È€Â8È\{¨…þIàBga‚ûx¡$nUâ…$Bx!ƒŽ|ÈbŒ¿¹h Œ¿õwâŠû™x V)&hcov˜P¼¡¸b9žˆá’JÊèš$FBIåq43emHš¸£“¤5 æ—UIäAYÒ&Ûy*z™¤ˆ\‰H%™…œYežÉÙ ­¥Ù&›\ö裎2âYæ@z²ÆçŸnÂ&ŽP*È¡vNšÙ•Åi^Ÿ**¨¤ˆZZh‘˜êÇi£l®'¨‰xj›Rz›ª§ªb©‹ÞÊ瘲†Z«£½ ç’]‹äŽM¦*þ%¬Á:Êž² .ã«hÀêxì«Zh´¿îÊ«¡Î~‹¤h»'_Èã–¯Ë.¬âæB.¸¾Ûí>ñÊ« ½~Ü[Ùp`ª©©˜‚ {*³r«¾ gˆp½ÿð»p„ q†ë»¦©Àry.±ÅÛq¾ïRqÄŽì°½&¯,˜¾}”|Ýnû‰*£ËžÌ0ær-;³L\Ï)Óó3ÐB¢ HÑ„Œ1®6ãhkÍ!—¨ô`BÏRµÑh"=ô=Yk½'×ûÆè¯ÓŒf[óÆèkðzWËò5Ø«½Ýõ;ôÝwÞz%öËrÿmuß>ïMxá†Ç%xÝñÄ ¸´‰ëÁxã3Bþ+¹Ét+ÎN䕇ûxšo¾5å ã{9æê|>úd¥×zêVŠîº³«›~Në±#6û¶ßZî«ìÎûÒÓ~zðîðÆ?‡ü+Ê/Ÿ^óÄ›ó<ôæIOGõÖ3 ûöƒb?ý80/‡Þº¹^6³y!JýœðÉz¿°ïªŒXùë/KYúŒÝ?p¿î‡úùE7ÃÏ–fÀ[õ <`”"¡=ø]|¿ ZzÆS­ÿ0p:ÌP¸ ðèúш|”-lñH`Iºßù˜Ä1ógf4\Vˆ>fÂ.m)SýØ–D‡JðÉ(! g8¬Y‹I¨2³n¸Dê†2³aþ£Ø.¢í‰æjšüFØ ¶ýK‡ tÓ¦¸šMŒ´bzz¸Fœ}ÐŒÂúâ„h,ò}Fv²ã)ØÈD–‘‰4ëSýàXHþljL$Ô¬&¦jŒÛäë¸Å<š­ÔZãÙÈ7ð_™4ä!OåÇ6à‘cm C(ºF^rmgÛbOGMv’‡ŠL›'KÉJQjl’”̆%syÉN¡±eˆ4•ÉIYr}Üd*Ù°ÊŒ­Ð\תaȾïŲ™È\&9ç(ÍE*ò–¢,§£‚ÙFT³˜×8¦#QÉ˧5+`ê4˜3OµÂ3Ÿuœ'6ûX«E¥ËOHdÛ"þePRØs–Ö$è@¡™ÌgŽrƒUf!)Ozªìˆ•¡ ©¦M”ФMÄVÙµ± î/†.í"ëø@H¬ò“a¢h!½8©kJÔ„Q$åL6µ'5­,­%QÏF5‡J‡IÝæM;(T‘JFšC« –Õ4dóœ>t§OëÖPp•<·9Α"ªÕh¬?^M _A„ž“Ÿ>Í(²”1×êܵ®¬XZãÚŒW.ï°fëþ>ŠÆ€F•“b¬'k<Ë"¶ˆ‡ë¬g?븊h˜Ý´@‹ÚÔN´›mÆ^ ÛØÊv¶´­­mo‹ÛÜêv·¼í-mã[Þ¾Ïr‹em(‚þ‹Üä*w¹É.sŸKÛÖ¶6X"éŒ+éj[›uå¥Yéhe»äAwcQÚï¶h(ç-¯{Y@Ýø¢W½ß ¯DäKÝ÷êø/}•e߈ôw¿A~ ‹ôÒ7ÀA0ò[àwÀÁn…‚ÕË`ÀÁî0 bçýÀØHˆ7ìáS Â,vÅ…¿›a! Å*®±hŒb øx?Áñƒm dTøÇ3ÖñŽƒZbˆ yÉAn2‘ÀdV¨vÊTm’œ€(;¹ÆC~2”¥|d$÷¤ËdÞ²™»lä0ëŠ(h6ó–Û\A5¯™½n®ó—½+ç¿ ÎvE•ÿ þèú(Ï©x±ucl‚@+zÑdá¡ûÜ CÑ+®nž!ºIƒŽÒ†ô&4½9JO Ó¦ÐÐ`/ÊÃK.Óªn§=]êVWèÊ u)îÓH\–™²µemœWÃz¨À­3`kb/5…ÇÔ4óéìVûZ ®œ°‡-ŠjKnÚHö(úêË$n eíõ±S íÆ]Û~Fë´lÊ@pqûÞÎ6®>¹KÉòúŸyž÷„˜Ÿ„^çº;¨7»uŠÖGR¶•bN‚ÁÛ]0Sbuñä·œýí€+œ?†^÷Á#pÈñ„U8¦néæZßû´¸š1>á?mä>¬)ÉõÌÝþC;h~EhF%xvu.àfQ¹”‚!wQ80j¨z*õ†b¨…`È<è…Ѓ¤e‡wæ_“ÇOåF~uOFx…3RdeVR݇‡ýÒ…{ø"‘(‰Dˆ~÷„„èþQKLj‡èˆžX>kŠ|Š(t–˜?“H‰ŒÐ‡,“…€˜`-XT£.G—‚#¸l%u-'•†¨G-U¤‚0è$&…TºDŒ°‰ªø,:‚­(O-Ã?YrjÕØ;DtÏ(~`G)˜å+±˜Š7BXõƒá‚Açx'ÚxÜwdA*R¨ÆkûÖrh™±^Ùˆ÷G6î27¨Øuñ¨>óˆû”Ât¥:û8}ïèŠDEƒUµMXäDJwE4õXüWCU†-µ‘¥Ô‰à¤ŒHàŽÈŒßw'èM$8‚5’án§'Cw'EšH’š—"øVˆ$ùƒ)r¤$TXˆjþMŸèLÂ(ƒ3éNúDn…‰³˜’v%t'”‘Tn¹bKf‡K¥¸Nn4^©p-Wn% ~@‰ņøS›HX>LÇpé(¡TMh’õ7•aØttiM=ÇSN–pJ/Õ@~‰ŒcÉPéŒh¹*W)–¦„OyO2ùRi„”`G†''9 ¯˜:â8H™Áä‰]yVeN¨É†Ït—ä‡å€³I›µY& ™r(˜§¹˜?¥š§­¹K”…u©—{y‰ˆ˜F©•‚)—Âù•õœ¾9œ¯‰F¬H=ȹcYÈ’¿tTÁø'/)S-H‹—¹6Z×T-ƒÂŠ9µþÇ©•2v6·)Æž)etòHž%Y“5ƒ3ÕRë–“ù“àšñ™‡FXøÑVv•~ü(•Ê9ê× R¡Òò ™*¡ªc‡ êþ¸ªcXÆ©}Š>Ê 1Ó:¢i• IW(ºG%›äÀ¡ÚŒEp£ #šž™|õXx):G¿3 „&9Š;Jp¹¡8zhj›QêY&ê_»htÝDR&׆¸ØP5ˆC3ä¥+T…Þ˜ƒZD‘ õ‚Oå/U¹bRꦅƒ²¹Xü7¤2ZFJŠ;]{Z[Îŧ ¨•"V™…çBtdˆS˜•¼ÔœK(þ„¨‹zE„8FÑÃÏåþ§ª©›Ê©ËU£â³Xá¤-p¸pÖÆ¦Ÿz >ú…Y§O1ô…Úˆê™zŠ8ˆ]«s膎8@§ºªš`Å“Yøi¨AºDfš“v ¦Å)ã•')§‰G0ÊoºI ´Ê)”y«f7q‡É«èƬÐà«5ª]„!+¸„D¹WÑ:zÝÚŽßJ2ÎÚ„§š}—™•)Š´ ¤¥™ˆ¦X?ìzíõ áŠ%sº•9B­ÕR°­º®ãòc{ ‘g o7È¥ 2JôvöÙ‹‹tÊŸ µ±àɱ䢽ڰr¬Á#­äš­¾™k*ë¯40`ïz¢¥ÊVß{Ñx²àš²¼³²ÖÚ²…þIª¦š49±¼—r"Úà˜³Ad´<Û¤ÁZ «“†‡"uIHuºm1+Æ G«x 8%‹nO°=û_bÛxpb§ðé¤è´9æ¶E„¶6•d[>¶:·q»jnÀ·Îз¿ ¶€Ë\ûƒ /‹¸ý*{aÀ¸öq·ë³ŠÛZF·o[³–;A7V¸6 ¹u[#•ë¹®£·æ5†²è3Ž{º™e¡ÛŽ«»¹vµ¯{¹|Pf´K ²;'¸»4â®’ |¼ë§ó¦É«¼¶‰¹]k¸®‹‘oZ»`.â»?p½ßfºÀK´‘ò¼«k#·4ö“C—†ëÙ›mþÛ˽êÖ¼1 ¾|¸xëEF¤D×jCö«B#¦è»ñëgìÛ¾¹÷¾0Àî¯}炤‡ ü³¶¼,ÁLÁlÁp1À¨[À‹û½™x†m²À¹ œ‘g¨ cŽá¿é; ì3šì,¼* –«Í†(Aç+Ãg µèp¸À›º>L³<¦A;¤ÔŠaÖÛÃ{»Âì6tj³Ò; g?˜J[ŽùJ¦Šk0œ¹¡÷k˜ê™¬å둵tÆÕ ‚ØôÄ·‹({$ªåbÅ –4Å2ÊAyì±Ó9ij«Ágssdí‘ÂbÐĚȊ;åJRaš?ŠT!\þ¦ß䥮yÆ“<œ@UV½Hq5Ù“5øÉ LrlY™ìžl+Æ„*Åúü«*‡ü‹,‚•[6ÁèwpgÇYvè:”e9nv)™˜Œ¨Ð©„)%U{¬¿$ oÂl–ªÈàëÂ©ÜÆõÆ@¬¢û©ÆtèŸ6I§mÙSH,ÂÔ$r‡‰†Jü‹š¨ºæ”;äÌšÆðµÊ.6Í«;×\;7é„ÕIЇ©3ÞxFÛ”¤i° ©o‚HqÂÉHmiŠB;sñl²Ñ\¥õüÙƒÏÙ™ù¹›«™Ñ6Ù“†$Ð.‹QK©o§„úœÉÌÎ Mµy"­´L1Ðûºü¯-§}l¿ÙÌÐ<þ‰ÿLµÄ¨1Wû‹Vx­ž|™‘…uôÙÏ•(›‡°Th!Óe+ÑŒLÑÔ,¸8m£°¨néì)aœ {Õ„šÕ°;·( Ç<š{ú#ÖD:ÖE[Öô|Öh}G\ ªuMÀ3=×iFÅÔ;¢­l³ï¦Á½UP¬×KJÖÍ*ÍÓ¸™ã‰­sÄ6hx-AŒ»”-³óœfôkÊ6ˆ…wŒÔ9|ŸjUl–˜]Ó¨}Ó} fö½qIœP3… =i®-tªm ‰í{º]2í½døÁS­¢ä\ÇA=Ð…}χ½Ö¾½2š­º°g­ÉM8´·„ÎÌ­³ÎÍÐíƒÀM½ØRiÝþüª«÷´Ôù†­ÖßMXl¤9#ßàý¹ÃÍØUJÆóJÔ&8˜ù†&ÌÝq@ÞHµ|4¢Ô¸ˆ€m߉Ë×ùÕé…µ¹ÛÜïÏž}Ü1XÚG<«¥ÜÌZœÁÒí¼Ô=?SÓG î¾îýÃùŒÞ:9”¸ýN?ò⦭×"¿œÛ5.Þ•æÝ,~Ôç|Ãéªì Ý6nÀ8g:®âg{à†©ÝA®Þü:´mäLâ…æÛUþo¼MBøº‰ÛÝ›Ýàvý2H^≭åÇåÞ ‘w·­/Éžn¾Þ]ä;NmfŽåhnçPàŸ‰ØíÓ*c®Õº‹ç¨ÀÚ~¸ä„ûç™â$zè)Žþß_KÓ§›æ¶æa$è–³ç·Wè„;]ÌÅÃêä‚k‚íj›¹N=ì꯮7çë³Në´þ¿ ôØ}|S®|Œå(Ù"“iµ.ìÃNÁ‚ЩǎìË•©ÉÎìÍΩí˜éÎWé|.‘"|¬PHÊ›ÇMîW.„6œá|œ¡IíÑ7í°å.|çÞm¹‰†tÔIEM· «ƒ)ãIH䂯®îè XýþzìNoÊF£½qæ¬Ü¥XCn”k»Œwÿm²|)vŸ€Ð„3ºì%XìðPæ&=ÂúN¡/mªÎv;Û=(¯jÏ/ïéÎQ.æ%_Ò-þë6ûîò¯òµ,_öᤣZl0‚&ÈJiÒßYÔΊ[ç;çy0'~uÇÀfô‘f¶_ô^ÑÈn-Ç[Üo*ßqéLÇ„-1Vßovœ¿b¿Ždq?/~]_DÇþÊ)Ÿ¾õÕèýò÷ÆÆö‡ÆŠvD¯õtoàOÖça‹÷£Ébn®ÅÈ„ŽÌà'Ü÷z>ø/w3I/©5O±õYùe—øöRd¬;°?Òá9q¾,å®YôfŸå<Ÿñï–ô0®óÎYö¦/‹Ÿ–ŒGSÌÆá‘ŸíÃ:¬Sž¶²¯ù/mp´ÓkU”lü %pü×ö0ºÀoØè’)ƒÓŸAþ(Ȳ4f[Ÿe³¿ù…ìvÊDþâo3ä¯áæ_ÈŠA¼Ëý¿«ú¾¥‰i­TOŠÅbóòa”“V{qÖû†ÀPÉÒ<ÑT]S‡{áXžéÚ¦;l}œyÕ両‡Š>ÝÄþòæ×c>ÏšM/ÇÃ;,)ܺníËcWñÆü) Wš÷fdŽ&xݽ–/QÊ;µÔSÈ^WOÇáfjùÅiµº;`g>—šwÓžxÀ5ÿ@ßşȼïë1=œZ¹E¾Oãž•>”ïZè¿Ôþg_¿ãîÑGõ•'ä#à.¼@8 Ðì3Ò…&:Å1.u‚Š`ã>•ÁŸý„{ ô ™üwÀq‰°! ü`< ¦l…}Û ÖÂûq#ƒ}þXO˜CF„„ëáÛtDÕ¯…:³¡§ª7ºª‘±‚ Ö&ÄC¦ ‘бù¡ xÅPT‘‹%‘"M˜)ha-]É“`Áàå@ï@Lt&K£ áEv±Š)Ô"zîøÒqAv4Ó=\…císäcý˜G=*rЇDä‰t¢µ©j’’$d!»rIGÚ'‘ŒTG=YMn;4Æ(SeJB ’”×Qe(™JXòb5‚ÙÒ‰1b•b%í§Vµ’0LQ-φ:ÖQͺL&ºáË@¦’üš¥†dyÍgü>;Ù% ¯LÂÈjœ+' ÍI¶WÊâ— 4þf¹Ù£gî›nš§BÈÙKDŒ#šû„¦Þ©Í; Ô|6BâÁæ'Q•Œv ’`¨r·-6–1w¶K™!êPÒÙîW«sÞñE©Q5ú:Ž5q"ÕËM3а¹'[B%HSêÔ¼” %ìê)•é³$î-¬ ›¡QwŠ”ÀH´¨Lt"öÞU±³)J­Üz Oƒ2ÎÍ5/uåÜ b˜W)pR1•i&˺66+†mR[Ú Wˆ¦µ(‚­¬^…&«ËòŒkŒ£ëf‰X‰V®hú,þ\õŠÙµö«îÉfk ô¸8æo™Ì‹Ýêpk½ ò¶ð»à[Û½­±l‹Üo©÷8²2†Çukr£W\ÖÓ°Ð$,¥dëÑ‘6uÜÍ®µ»Öà"ñ·}Xg_EÒÕ¼ÑÍÛ{ùúÜ *Žn˜„-t^{_1Öf£šêÑVRݶõ¿ör+{™«Yþ¥×´å-™ëÌ;Xo£½n>Ú9¦uÂçfý¥­j¿Ùa…-—¸CCðÇ ËQò‹ùÌd„†t¬þ8M_×Ý3Œ…oCɳ\Góôr‘†â¦g«kV¶·™Îu2Ú­a_ZÖšõŸO mO°ÚQä™9"z¬^á•ß{óçc†bt¸Õ© S ÎTÜx›¼¡6Ùâ¹¥xëÝÒ†½9ñnUY;;òÖ™ê h7ç £xˆÙ¾¾;àúp7¿ýy"thß ©¸2ªþëÁ†O»Ø"S‰A¦l×!É ‹r&6~}g|0)¿¸^¾J–ÐåØÀ³ ™ ½$Y‰'Nø7ž}º™Ó<è1Ÿ¶Ñi9tâÕã\>Éü`»~øH>Ï9Šh¥/=ë9Ì×Áv±ìsIúÖÿÆtQ»§Ë-V)8luõzÅÙ=w¡cwj”wãh×Úáéwæ”iå‚ßc ï …ða(¼á¿´ÇC¾ß\<åÒø³3óe—÷…æyŒù¾ ¢w áM¿/Ò·Ûð«çPêGøšxö[²|-©EÍ! AÂêö}]¯ÚK(ø+ =Éç†æß{™çœßdñÙYþûΠÞJ]¶²)N'rú*§|÷!1oäÜó¿qÏþò·_GÙƒq3¹ß(N™dË@ÿS=Ô‡Z ÕMMÖYl»ôˆJ$‚*¼”‡±ødøœcý° òÀ/ ÿlêrðéaˆê¡ú ©0ÓlM¨‚³Pý$¯ý°ÞhÍIìO©"ëYÔÈüpÖ~-bLÊWØÊé.P³$ ©¢ÉDscþÚgÍXl~Ü/ÌÀPý Î$ ´ÐïïðND°ŠÙ€êÛÒíjžèªrŠÒx9n/޼ aÐzl÷º‹·„KWÚ ïäLÏ„È÷ëû¢PæÄ0 Óнjë¨øÍpþM }ËÉlëÔ~æ 1¤d ' —ðyœÐˆL²”­ýÂd,±ùꌪ¶ z¸¬À‚Fù&ýÌì‘¶­õ1é,ѹj7Ñf@nç`° qnÆFQ‡ä°ïœ£ÛøBÛKÍBj¼¶Kï²# Ï0~hp‰îPù¨®É€L×òldXÑOÑzAù”H”ª§qÄŒÓ0±¾ÎLl^ÜŒˆ¯î©èsLïÅ3ѵ=ˆë'Ö>nÖ0ˆ¶²*Æ-Ô~ w‘…Ú.·Q讑þ:L¡.Di!±î‘íZg¸ægîN Êþq~Îí*;Ò C°åŒÌ]Ì+þÉ&Nðô¤rj*È€*¸ä† ïA QÞZ’^òÊD2®ØL#%ØÐ¼tQ ¡«åê15v}r23\P±.°vî&-$*Ÿ’zr ¢ríêoæV²+yä+Y`"·p(}µXLU@Ç`’,Å,",Ų)åREèò-Wq#­2þŽøV ¤0/½d/9Ì0{b,³!òj±rÞ 0gQ0«c ³1W1¹Q3‡11=D8ÓÅ,I6M[,©ú° "234Eó1õ6#¯3i3+es("ç5o's³‘~Ó s8×c4«ƒi¡M|Ó8÷9…¯þì¤s:©³:­S.ðÒ9ë/8mn7[bdšS;“;×G<ï#;«¡¹A­v2œT<ÁÒñç+D,îÓ>—ó ò“?÷“0ÿsúÓ¿!%C‹=yOG¯=‘:Î<Ó=¹’AõÉÐÎÏ›$î ŸS>íп\Âp¬/@çÕhÄ@ËjI¶R˜8fEų8Ã!Gÿ&PFU°ªð§bp¢Èªv1·ÆÍ?°,9´.½S'™sYÿ"°¢®ïq ÿ/ª®j³°/ Ht3‹4ñ ôË@Óuô¯ž,Ý(³Ø2[Vë•ð­ì,êöMÄ,ÄE]‰7Mþ"<_­ÿÌ4ÍL”ª qŽð“P[±ÑšP¯nN‘5C2L¤!ë4Íp)s¯R{ 1)ÑŠÎ<Õ4fGi±/ïKO@ÐCåÁ ^SSkreÍ»nr‰ÄÍTXÆ¡‹oTá E74R%µ¨/ó‰¤"ÓI=ìé‰ ŸñÓKµJ•NO5L–"9´ 0SI5änáº)uN¡õÖRŒ M56…µt´ÔþD=çq^É@Ï"NV9Ñ×mjP‡¤<ÑVŸõΖì§õQÝ2A¤U+Õ6C!@1-õ[çJÈL´4`ÑÌÜ1ê VZ•^þdz]yËb+’qeÕtRÇt±ð'ÒB[pÐl+Ó2©ÈÈ(éÔÆ‚-` R/QÕzó>_–jÊCŸt*2.µŽLg¶k–4ï@îF5$9r ›ï,êkñtÝŠvïIg5G›GGÕT~Lk9ª é{| MÓ 5ô`4(«Ömm&CmhêOýoîp¦¦o·E!²Lo®´Vv3jOkêV‘½Qïê`GvPV´osr#±¦E*°*ïªGGÐ /—-íŒ'´òá>ûʬ,Ö35iH×0Aõ㲩 Î ÿÛ þ#–o%tX_#,TU‘Ô?¯—b¿{·W{ñ3@Eá{u2F9U\v ›)+Ñq¥6Ô+DLV}ÐI#vu5ܼ–KÔo,ðçþ×L÷}9ÃNцuë Í4}Q 0®}U×€ow(}w$ëæ»0ÂdÑ$…Pq‹hZØ=ÅÔ6)¸{,øõw|©9דõOs1W˜/Sø8â×û€Ð}$Ò SÔ´2RªŠ2€å6T—*ÖªVªy‰3zs¸q÷Pî`Ðò6V9°ƒ£*5ÃÖ^éÑ}£˜)Mö>h³€ÃX‚;"ƶ‚ÁøŒö†©±"Ö˜HcÖÅþ8p­·ŠY•+æØŽ{cŒý¸mê8ÂNó˜aïv ù€á¸úø6ÍXRä5lÐpüîm¼8а­d§ ²lÄ@ fS›éj§%“›õdó"Ù’´FSVD‘*ˆÉ·¿ªï‘ù¡‘c등"ÛbyùøýàÓG‰ù–«‰–u¹˜X¹•o…©ÉFŸJmmxJ­pGáVeô‘~ޮטX hº”K1‘y[ÏXòš+ÔÓ¢)±Ùm%j›w±›i8H*œ· Ø—då8£Ö™Évû´+—k-" 5wá>·- Õ…¶8„ë}ÖõÏÙïy£RsþÕ–åO¬ õGw´M#š`)×Ä*š\ïÌQŸ_2 šE ƒ±Øäò°•Vy§9WólWçÃ~ڧΈV|U]_X£©kA™Å­|s6‰ÇŒçnõ¼Ú1¨Cµ§{ëz2—&;N†3ºgkzï3\±XƒwF(¬;Xörë—†å®k†Í¹©Ñ¹fÔz_ÙZœï7¤72«Íµ`ߺÜBå®[ÉzúÊZ7ä]aÙÔ&Ùe›“oö±0;M’ù˜išõ•Ìay–'TÝìi³5ƒiy©B;[G²sc#ËÑÈÐf²—rœk§ÓÐ’°ßº Ìrh‡Ò„Û˜¥Øµ¶¯`l°/´á5B]aÂ[yõMm$²¶‹·Ö/Ê­óðVå[lOÏ·»sCwš•õœØV«4ÐJ¯Zgsª#•’ sÔ°”ÙFUH{¬¥‰ø¨’m±·jXDø7K1ÙL³&›À—³ùm¡T¶…¡£Ï‡=jÜ2‘†º?úOܺвô÷¡ñŠ·&¥é*s[{*;]CÜEÕ¥W†( Øi_‚MÂ¥²2„ÕÉ¡Ñ~¬\bÑþü¹k_ ¼Z“§÷U§¥ªÅ‰SW¼9VÀ •œv–}]OùR“’¾bšÏZ%Ñœ…q•q–Í9Û°?x‚xÎ'¬Cò¯I›_Ì­ãú°ÁÑÍç›§gÆ»c¿ó‚^Æ‹Þ+}^’QùÓx»š1Q“OÔh{눼tDÙiHÙå£>•!ö0æ“^é‘Þ+¥[ß~ºÁ‰Fã΋gäÑîêUy·…Ù„cZ–×ÞYÖím/ºÇ ËþÔÙ¹IÒ˽5ŠÃßÃ)ÊÓojáïןñO»›#ã]xè7G!b’zØí]<­lRñ—ªuÖ?x+JòùòÙ8Ïÿ¾ïaþ :ÁÞþýZ UÊá¤ß0¬Q1z©ëÃòYþóóÃÝWZZk“GŒPqߤ¥y¿‰Œº´ »ZnÐÆ]ÿõÁgL•=õª9xÏm;¬?±Óÿ0Z“Ú/µß¾}9ó{7§÷]V5v¿?Üy‰·$·:˾© ‘\"³>R«Ñj/Îzóîo0#Yš'šª+Ûº/\J]Û7žë;ßû¿%>fã$â @’HÒP™IŒV¦rrhr³]­7\lÃàÆ5‰=Wî7r0•²kÎúÉk7‰›$1Ö²!<®áJ By³g‘>}7ºX·Ããk÷ˆ”Åg×4\o4³˜qÕ“˜P´É³¥0–L]íüUÁÉN¡Ä#A›Ù\è RÑ¿f ï"T–§8R½# ‡ýLæ<µÏ˪bt5ز滞-FT[kèÏeáŒ2* wgV)5— mZ÷é×ÀÂŽ-œdß2þø¢Í±° d5JõrQzT¤!%ÿEVLfgÚÏ¢“}ëKM3iÄo£Rþ-˜äkxcÓ.ÅÚ0nj™†¦tp-RÓž9[BÙ‹åÚ³¦æÖèZ¹›çÃRB¯çvóìvÊMì—.÷¶‘ +®¼8л–Ê?Ì<ÜdVäÊÒ›Þ%óTÒ­;æ¯l¿£#0TåùP•Çž;ç}' ØØ…¶ ˆU†V˜ß…!¶ÀÉåµÛ‰|©xÌ‚ÎWÍ‚’!çE7Ř ˜©Wc7ô•…xè!‘E D":‡Io2~vÖJ,fs`M© ˆJ2ä•]zù%–ZŠÉBfÅT’@­lEP{¨½HÑp¡Y ^Fõr•§=• ƒ÷d¹%˜þ :(.Ž™Ÿ÷±eŸi¸˜'C„F`è¡DHz)¦˜&Yi$Bó_@t~Ê"|iîø¦\pNXZp£Õ'ª¬FÉ'—åPjU¦¹êz妜êÇ£“Ñe¨NÅ i¦½úºB­»:û,)Ê.‹[xñIÆÙ1Î6[rt-+Oï™)Wo•a;lª<Ñ—f‹7ûW³ŽÝº´õÚK›´ÓâJšº4qXNˆp«ã\§†Ûg—ùêk̽ ;|‘ SolÛ ðZFFÜÑÃ{üÇÆ¿@¾¿2¯Èº™¼2Ë?„œòa’ZülAÛù2³-ë¼s¡0£°3ïŠó²Bó|t®Dû¬ŠþÑH;mÊû<=5ÒJ/Í0Õ¼FísÓY{}óÖW#ú5ÙÖYG†¶ fS©åLDìŠóhÀv…e;¶Ø9ÛíáÙ‡v}[¥Ò=ÒGo#\3á9"®ÒÞ}çMïÞ‘æ8 Ãý Kÿ¦ÜË6sÆ,Sεäiã-²åžx眫îöå$w:F—w<úã…”¾;~1×àS™iq»›Èt+Ü2ž}KÆ[îØihÀƒáiiË/ï¨ó¶;Œ{Ê©óŽÑé«&ýõ÷ÔߌfŠ¡›OŽûV‹–½Ça¿Ä¹Zn\׃ô뇟;†¾'ÀhýLmûF»Ö娩\šß…b=áhþ%ÿ2O¤ÀÅ õ¯^ÜCÝÍVÀiUë,ZIOèz18r0‚äÁüVµ>ÐðF‚DÈ6&è:“}€ !I2BPOE:ìîþ››ª[*’2‹BŸ¥AyÑ€Lw0ÎM­€¶ྥ´”ôZïâÑûÞÿæà Ï”N~÷ȶÏ8»no‚IáµEøƒE Q„š‰g\¹™mTUÿ†â»­Þ ýš Ú—¬´óø¦ñt*ËÙà*Cùz óÉZ–1M?&98”:7»ä†[}î¾ÊR£ç>R)`öY ‡yiŸF:tøº&r’‡%1§q]Š=ã9WæÖ©›J|ƒâ™øegÉŽ6´‡ÉÓ¡„û¿ºöGôw”¯yv¦wAo¹ ï‘ÁÀmÇw“œÓ‚ÿÕ,³ ¸^Ä9ŽÛ7ÛþR¨ÿ¹Û¿ý{äþ1÷:ñ¶|ǂ߽Ûù¢¶eÓ£ãì –}l¨gzMÅ9ªÆ£×Ý®´¹Ý;™H«ÛþëÎ`Ðó©øÞjÏà]6>ÿ\úŸÞÊ-"͹ié#4Öú[èûŠ[°ÿÇåmp·h­øì¯(¦™Íµ`_v0 žø‚GìÐú9–ß¶œg h…šLJ 8˜ X8±Z€\R¨Q Í]]=`Dý߸÷ ‰¯5ÈNõ”PÝÿ\žµÜèߺÝN²$ ñäÙ–m÷ çÑR‰·µŸæ‰ŽÉÆÙALfÚ¾ƞ—ŹUA=\Z1I ªÓ¿ÉÞø=þ~ÌÒƒ¢IÔàWLáÂñZ¦½m!š‡h)T%MžU¡! ¦ ä˜ ‚PÞ)Q]µRô}á¤à™!—:[£L^ò<]âáT%áXŒa":Ë"z™fMb'ž¨ DíeâÝ ")šÖ&^""½¡(2‘ŸyÂÃÍ¡á"s¥¢°Ø9"(K+J)Þ -z”-FØ*ê".Û¸^ÞNab0^Ê0rÊ|AÝ8Uü9Ý#±»è×3bv£0Z¢–8Q5’2•#Ì-_þ‘Ùíˆ#1‚ckEã`AaX#0ÂcÉãF€•3 Š>î >:Ö?ŠIÓ`¢ð}á=äþ ¤ñMGl1¤Ô(äaA¤ˆô£D–—)^äBºcE#EÊ’FöÑG¶WHÞKBâKNYc‘!W#;>a…dÙUd¨ñ¡E^GrÄMf“àÄ\í´äš}é¹YP¦ÙNBNIBËIž™£1ŽÒcЕÏ8 ãTšŽMzdNîã=8š.ÕÓΤ½WYåXn×QÞXRÖÁZ.%b}ã` c˜Zæ@["2Òà]Q[$Mu`<¤ZµéšæQOa±¡¿ie ¾å^u¥˜š·Õ¥²A¥5’O}í¥òLFó¼šfÄZ`"‘9*TaÂÔarVb"¦2f[F$\j¢ÊiNõþSµ¢wà]}&\Y\æáž¡õ›fa"•…NÑuÈHÂWÒaÀ5›Ãm †9ÙºLܼ9[JÆi—orœó§ '|çu Ä’µ¦[¾&ͨ\ͤ^ùT®çJv–ðüšåÉ› NÏ%$êy–å]z±fï9&0A¦>xò½gIQ–­e#vA g}×Õ…ÝÖMè~îI'R¨Ð}–_¨F¡§®¨ãA¢\}ÒÚÉ2–huB_nŠ>ÞtZ"ä^fP5ærÎ≒¨.Þ!Å¢vFhìi§‹ÖçôQ"Ða߆BRyš§¥åè™!›ý¢zD‚öè#ŒS뢊þÖèÆªHÓí¹h>Ñ“Þè* ®•›PòNr‚ëÝÖþm Â^ožÓ—è™JœŒöz)‘Þ™“‚$T¶éÜÄ n¤)’“ 6ê ý¦.©´½Ñü)¤^c$ÿfâO¢zcšêÛ¦M¤‡.*W4ê…ºg¦`ó´(€m#nj`Qµ\-€`¥†S§šæ§¶K¨ÊÁ ÊÒf&£ûµZgN _fþŸF6¥ÕcZ‚X•—¼)èé'â·kX¥ª\Š¡´¾ä]Vk& ¸Ra}æ¢êP YŸ”Ù¨BB+ÍlÈ´êuè!šh´aÖGv sŠë¸ªþA¹Œ¾ ¶ “\©;E“×ùé*]$½‚èÔ,,!ˆ›œÒ!,Õ`l¢Y¬ì.'(‡âçîácÅŠlÕ¤kÉÞfƒ âÃNéîìÁ¹¬›ÂlÕöiÝé„/²llêìcn%û *•ébæ#Ï2ÑÞìÓZ’U×VàL ¥5[>kÑF­×àì5Õ_ëh£© êÀ‚mØN­°©m ´¬ÛòÛ¾ã)ŠíÑÅmë‚áí—À-ßÖÜFVÝ® xëßÞŽÌá¢kF.nËØíyÒ"ä*–ã>Íä nå *¥MJ¥øÁd!aÑÚ\e8"íà¦mu `ø$Y΃ Ñþ$·Ö"áúMæî«r‚Ì•Q+¼ånVÎSelWÍndR)êJK>šX’+ñô.Kü.Ä)jâÆXíjn1Œ]¦†]zßdîjðD"×Â_Nû¶… ¶©®Ôš.ñ΢d*e†Ÿeêš>[Åm”nÆŒ/™æ%U¶úâdôJïô èíšßlS‹>âVq—‹¼^ñf!ÚoqgÓ¦/ŽJ®ð*e°^Õ¦JßR%ã_ÞU»fçqr0äQðjîlÿÐ×$ÂçÏ*¨L1èÊIŸÎ™ÏeIè}n©ÏíܪýÚ].¡f"#è Wã‚_Ô-kÃî°ÕõpxJ"‡;m þëÍ o“íèìñªâ¼ÝÉb*ä­¼~qS$f Žl7äú&Ö&!^2Á«šŒ¨Þšq€ÆÞ©ñ ³pï‘”*pëøpQÖÒ!×’áM•j©œÒ1Æ Ç.wåé?òëM,ñµ±ï ±ò~Û½š'?iœò1$/_ƒ©Þ½‹þñ‹à³q ²î*o!o»•©-»S­£†[«Z!³¡«’¦·`­Ì-ã*JjƒQ›Š2Òú+[ an*4³ïˬÿÊTÀM`R@çû--2£8Gªýáj1oò,çl±²`LMQ±iƇי³ÆÒ`¯Ø×â ¦D×(onó ŒþÜIÂ:Îì*à?ïíbõ³@&4‘ç“{Ü^9™²mZ‹pþ1‡ùm24Ú^0úñ²³Ó"óº-´G—î:r b \'X ÚÎL‡©ŒqôkŠCCm@‹ôö”´=qNKÕNkG’‚J,î©+Òìæaáoô>µIuIóõ ³b“?/UûÏJ³ôãýáRb¤ÂߟBu“Nµ?ZuÆ:^õ=õ­ÚìÁuȺuxáuÌ‚V.ŽSu៮Rà­Áïù_>ó{µµ^÷-_« ZieÆDH“Ñÿ^ìc^cnXcÍ^YëMOõf‡hfk09uÚ•¶gþ6Xw¶ìUÂvc³v“Žêi£vj{5më´k¿ön hÿ6¡±B¿q3 ·©6Ý"·ç…kÚu.°.èò¤*q+.ëvÉh`î ï“à(Úu(sïa›«SÖòóò®šêzC×x °qŸt£¥wXÎ1é¶îTf¯w“W|7ny#®sOªa¯óZ³ûrï F›P%«<çêeð†hâ¶Ö¨¯+·o·oÒÎ'ü³55j¦ý:pøÂI8eQx‡ö¶ïøPmN8'mÊÞEÓçÌ —pwR¢ûÀ²T[x"5Ä™Œþ+Ö­‘‹0Ž¿+™°žVh׸‹þ÷Y#«#:«Ÿ;2ŠR±ëVÐNhå§F+"†qŸ¹'ß3?ÝÒ5±]*+Gu™{-€ã½Âê=;éÛSªóÙ.¾bD×>˜Ä|¶f5~|FÏdÏi´;½äðmç°Ô±ç¤{~Uþ-«|8ß»€9XDþç3nodì +•×þ·Ž{U2îÛîJÓ~ì§ý￸î ZÐT86áw:ósýà?nGý|[“Š?=åô»ŒçKá§óÒ/ÙúØju7¼áËü…kwżdwã2¾‚7sé,$¡mÏùƒÞöÏØí§÷ñÆï{Û7ÈG [·¢µXíÅYoÞ}q$KóDSueÛ•òby¦kûÞ@wç{ÿ„á*Á… ‘B‹2391Ò&Çy¡F™[›î÷‡Å¾,×|F§Õkö'4F•#èÄHgàóE…d½²ÓRZ€ÑóÃÓ³sZÔês¤ 4,Tl³¼þò‚Ûä “Ã {ë4íü|¨Ìkü“a<”¨sô›Ä¤t˜el­íí¬•M”}M*¾S tv(UÓ<½ÆF¥ÞæîöþN°6="¾µU¶E7^†WŸ^'œ‡ºMd¿OW}Ü7ÔÜÀ4â²<•ŠàB†XJ!„Ø¢\?uçîAÂXQà3bþž­“¯HAù4þ{DàÊŠD.†[•ñÈfÃ^6Œa0âNž$âTh(›&%9°Õ‹‘˜Â”¢Ô×"ª,íYeé+žVwX§š»2T¬•‡=Íöø9Ví¨¢g#…ŒéSy¹šX7ÍJ$ýþEɵ)2¹Vþ;JÅ5œÇKÁÊܸIY·•±¥•œYóæp”9±ú¸xã°0U¹LÉOßJ”­½ºî xõhΜÛZÆ-smÞ™<çÎú蚤#Ÿ =ú%lȈ^?—¶jÔURÒœw2õÖÝBo¶‹]â7·œ’ƒÏñÞµ¿{â÷ñ즧‘ž/Þ.]}èÓ½º›é&©ºk¯›÷Âëéç¸Ë>üÌcð ò®ë"Â~CP¼äC¾ü6ŒO¥À¢kNžþNÔˆ1ç£P%ç¸3ñºÙÛìÀ o4¡»½\Dã&éLÑŠô ¬Ã1òJm¹¤IéBì4Úkn® Ò˜¤@D.þ;"Õ²ǃ€lqÈÆðsò /-LÓŒ´ÂS<›QÒJ½ØÁs;Ƕ¤i¸±›Q¯ìª".:£T@,ù*ï.>»Ì³78ãÌ–áêáoKBZ©/»–{‡IíÛtQ_¤³Á/Çš”‡Wm4¨WaªUJ?»”Ñ(¡ùHÔ¯Ü4$]¤á>Ua“ãÅÓG5°õVf¥•F‚Þ„°ÚjŒ”VÌ’X›Ò¯NjÖÃŒ´hôÜ2µm(Z‰àZK£×=n»½TÙeÑ•®®Bµ\’ Þ/Ýšþ÷`|̽_£ò­—Ul³¥x y%6«µO“ôT$qÇ>þþIÿ̘¡_h9f™ÁÜ—c\‹cÎPtON +ÿþ ¹ _EŽ.ç¾"¶¾™—f:Þš“ƹÂ̵ôg«YÄNá©øk›¦æåiÁ&»lQĆš¥~¾2à­uíê¢ßŽM6¹åF:m2Ìæ»o6Ðֻ߬cù¯¶çF|¾™†Èèp–×ö›­§°7rËý

yå;“=¡Þí1¬Ãöú¸ÅÛÏ=QSytÉd*ÿÃòÍÉe/~yóá½y1ÊÇ"föχe|Öáþ§¿ïô›”üÕüæ~J÷¯_5ã?õQî^î`Øäçª6iÔÛ A‚8¢ 5è²Pp¡ƒBVë‚zË` ÍÓAªÐ…_:¡çõBª‰…3Ò»êf!­ÕÐ…1„Z }èŽ v±*]ût8D±ˆ)"ÁT _sÃ’¤(E'Ú,Š[œÂ ƒ-?] YD}ØÅ'æHoÌ›ó˜aE¬kI‹Ó‡éG²Qb_ä£*Ę´=Ö4†ä’€Ló‡O™1ËócGÈGФÛ^ Ǡ홮’ç‹d·(ùÉPVo™Ô–ÐÉ}þ”ƒ”äFéJË]ò`GC%3TÙV–„egùÈRºÅc¸t]vIª‚í—ÀŒåY†ùL³ÙòW¥BÜ×Ôõ¢eR3rÅüŸ7ÿÌ?ÎDÄ'¹iNq^œÂÏ‹wž ñpõìa)‚˜Z“nJ'€H×ÎZ’Óƒ{—bðé˜ÒàAB“'úƒŠÒœ¨@GPwV4š8<⇬¡2 Ë:Yú[§Ù[:*{ÅØ–¸Gœð9’£`{§·BšEu©pù¬Oó”AÌä”'…|é¡xå§Ðl©7íèGD8‹ì"SÁJ&³ð±MI)J£RVY ©cèªþOÎX¨ùZ Ô'Tª­3êêP,†9K¬+JáÆª)ºÎQ‘zêê²Ê¸U³Õ£·B–CÝúV¸VªPÜCÜÂŰ]a©TÜéNJ°v™„«•¿øY?kÚ4¤=blAË@²M²g2c°,…ÎF–`­De‰eYÐj’,«Æø—ZÕ®"Ç ^Ïì†:e™>Uîkïv¨·™¬ŽÕ qµK ãº`º‡Ó-è*]Ô}µ¤¾¬ZyOÇh®t»Œ«úv¹³*eEÿlœ=ÉkßBnŠØ€{ß›Àø"è»]gêBK´ÿG¿àâ/ÛØK˜Àînv7Y°¦r­Áþ›ü«‚;œŸKÍ¿¡…ß[àðøÇ™9ÃíˆkÇ\vÂMtv0´0,W[˜Å« Ìî”ãÕû|B&OõÓT­jR† ßžž÷ß÷˜¸?Œ3å×Â(O×Ó]}¥\€PbþŠakå︻Q¬°›Ø¼V6C˹©g3ÈÍ®³vïÜ š°Ît4Am™<Û³‚báó¢Ç‘èÔJš”F1ò0ÍQKKsÓa\ó§9ýçP‹ú•U&㑘D¶*q¤¦–\†Õkî>¡lýIba±jZ{£Óãs¯k`2uI!¹N#«±ÈTaûšÔ^l¶žå¶&ãØVþH¶£‰lÚhëoÚ v·¯Eì2ºB‹.ýEYO¢ÇDÂÝs÷~=UqÏûHåÖ廵ۣYÛ¯ÏZ÷¥îïKØÛ¢/îý‹MM~Ö$¼DUŽ!¾&ñ"\¢ßæW¸‡hp¥-< vØÃ™Iño“ä"¶¸odê”—­¥vbx“2úñæ¢<«5׸•9~Üxï\–έO/;Wò\šWkE÷eËm¸rM+ÝåäÎï9ü݉ó—qè,¹ÓŠñƒwÛçŒzÌqìÓ\Jx•S§›Öqðuª‰EÍÄiÕ¨ã—Æs7óžö¹×‹ëÒºu¤&zƈƽ¡bûüB\b¾½¤÷íþû ™þÁW¶Ï'Uöåç^Z(->¦Q%?jj;ï‰Û‘§èäã°SÍ÷ŽM‡4­ÏZ-áQP ª-X•úU ‰þó¨W¹ê5Ä{•Å$íÆß÷ɹ´äÛºŸFôÚ -gàK^ø%˜kUéaWe%˜É‡”ºI›ÅÕÒÀðïÆ®¼Ó_ý.œÿ‰¦«En¬£ßk‚uô…[õ³?~×Ç>ÛJœ×ò¾×Ó-Úâ-ÏÂ,r¿Žé?Ô¢>ÿ+‚”!ø+?¡®ŸZ@«i¤Šƒ¾º“@ø¢@ R/Ÿi¼è‚0 ì·U™½ȹ´, dËë :‰35ýƒAÒ’ÁJ)Áå²¹þ†;“»Ó&–úAžëAjA@»øã!×R¢Ä«üÁ%¼.ô Ÿ ²¬°½™ºAÇË:IIB„xA,\‹&l1™Ó%˜Š:íž/ãæ“„8|>LãA4„&-Ô°.ܲ}“0l2ÇÉ’Á?"QÃYÓC*ãÃõIµE„´+„Dµ*Cðh4m3<øID˜™ÄÚD<ÂÓëD?c¹QLžO¼7都ý£ÄR3ÅVlD¥yE})ÅYl¬X<ÃBÅÕ³Å=ŒÅŸëÅ"©E qµb ÆqÃÅž«Äaœ‚Ç˧\ìÅ]4¥c IŒB…É6õ ÆXkDhT!it£j;A#ˉmÜpô4s¤™*kþ¤6Äs›w„7uœ eÅz³GÊkGރ¤óà¢Ç{ÉÇ´ñÆ€”¨“ÂûÓA¸-ƒ§dÄÇPKH›XH…½"GÑ»?ïÑÇ+°?l,u˜9M {µÒÆÉ¤L(“‰ü“[Á}*/Š MODHQôMÓìKl-ð0´#<ÖdÉêN¢D»†q¸†´¹ã‘*€|NóÎà #1Ì#‘BÎlêÀqœ3k,OóìÆ Ü/¯,=9ÀrO¨p1û[/"RÌúDŸè,§“±®"»Æ™BÈsÉDËCåÝDOL2Á!, c²¡äÎ e¼ðlME eÀótA»+œt“?êÄAÊùdF¥Åû´›.Nù=ìYQÿÔÀþÇô0#$Mæ)PeA=8çË@ñû² ²ÌœCϼ)SÊ›P#Í MQáüC%[›tŠX@Ù,(µïùL ™?ØARYÄRDlSÄzÓzœÑ9MÃ85ÃLÌ]cš,R;­P<“åTÇ+Ô¡ÐRïÒÓÃü€>õÓñÅÒD ÕMT™„g¬ÒYéÔ¹lUÕ’l:öÄÆÞÔ¨r|NUUÄ“tÅ}¾ üËŠ©O`%Õ[ý­¦;·õª\*hÊ~t΀TV#Ö}Ö~£Ö4MxÒLÖZå1fþUM³Ás (‹üO†QŽÌVÈŠHÅ\×/9å|Ww­Ò—œ×KEWžtVÌ,Ã(<ÍIùôWsØfãTõ|ͪ ZIŠRƒü×” XÍÅ+Ë1tÐWŒÌØpÜVH »›D³³ÔK‹íW’,Ù›UÌSJq${™Õ~Á¨ Ò¢4c]ÙÈŒY |KÁ‹KŽÐJT-Ì@uEž]OŸE3gDË…Õ`…Ë$2ÆSZ¹ÛÁæì¼äà1¥šî“1 É¡$Ö»Z×C™=]TûDÙÚ»K90åO0¬X¡eX'œ-—r²ÜÌ*픹«Ð™ÒƒžœÕDúÜØ…@Û>$,qYMþ«ÖXè¾½êòãUèÖŶªåÄo™›e…¾ÝÐ\é-¬‹m³eå\nhÜÀ„<@ð‘®á7r9]·;ÒÍmÝGõÜÍO€ó’S1[m× TÝí2ÔÞ!¥ºBô*Â'P¸7æ••½]C« @ùÑ…Ð÷¼H U\ìu]í•Ùû‚Þñ%Bë QÙC_N4_ßýÝäÞˆÃÌ-“Ú!‹Ð µå_Lx]ÃQ„e_ä•Xûƒ•‡ `Æß{tÒ§ÊžaÒ°ßö$3/ì5n`:uÞ»/3[²x,SBÄÉ(;Ñ?í`R¬_àEŸäàÞMEÖ°\Äå]æÆþ¶_Ù»V‹‹a¶T¼D·½aVa!>›Ž%®µÑtbo£aZcà(Þaž¤0Õâ-æâ.öâ/ã0ã1&ã26ã3Fã4Vã5fã-._,’ C± øáÿebG¬W”Ŷ8†’þ¡cÄý¡;6¥ äB6äCFäDVäEfäFväG†äH–äI¦äJ¶äKÆäLÆdÖýB‰Êܦ<£SM©Q›b+ÌáÚ}Y_MeÄ EQV?;dcÂâY^9¤rGr4¶Û ‘B©,DMÁÀK¬{ÌEB@_N>`¶¢UþÆXÞHŸdf¢ÝGâeª`Æ*~¼MºªËd2æË$á,¹ÜÅÌ…m®æ@zþ]0ZFç7ÃP[¸Ü«Ž’È=…¼`FúPÜUÀÐò­Ïª¤VF‰tÑiç*üΠt½.mÉwŽ]»˜¦¥r–¥t†è¸å‹žõJÆ:žy^o}®?̼Œ®“&¥gvUgöç¤h/EÚ™óhééÒ7Œ••¶`u%‡&ƒˆ¶i #K's»ö%=1”é¾ÚõÞ©]#‘ž‡5jØ%hÎ/ž–CŸê j!Õà‘ݸ¤6ÛÖjxZjÈljžVªÎQŽV6¡.¢®!~~åP,2½¥”>ŠïþᔯTlÌ¥à”nÍ™þëUÝZbÆZåNj¤Û]¿“Ûd —Æ[Ç6©ˆl³J3ÊN憾ì~ìÚ²¥uÔ±cˆ^甬»êí^–ì¾ÎÔ?ä·îHSÆâs¶íç&Èy´ ÷Ømçugˆ‰QÙbÍ{†gM^͵×:ŽêîÚYvnèFïµb)þ`“ÖCÔQéu_L:ÎÖãõfï>ïôæo9ÅožíÏUèªvéqíGªNîf½ïÿÈæîï'oðöþ+Ó]¼}Z³¦˜*–pÖoñsípy p#jÏÅ<ñÖ=ÓþÛ~Ò|áðŸáñ·Dþ'ñR>ÚbÄÇñ!®Úý¶ñ!÷Ëw“§×ft¯w¶S6òtý]!'ò)ß &Tµ>Ùë}òAòõ¡ò/?ªÌ>â´b‹?>,'é$ve°”n×5óê£éó9WÂ>;Ĥ*ÊÚQ®´.wá4÷ñkœ§O®b$LþS^?h:gt}ìÖj¦f²­^²Âfç[*2O]ã+:²tdÖågBs¤.µh,3íÂݶÇOaùmÁÓPæ·Ü¼ÌV¸_Šs(jô\OI ÃÌ‚åî§în›aƒFÝ ¼,|^@‡¡¦PgÕ’6±ˆÝÎùRÎx¦Èy†Ã©¦¿_‡Wk龜r]þw8@®§}ùîéSÒè–.öŸõÂtÇkPWôt-'¿ž-÷‹>wúþ蟮gêuw™ö¦[‚p'øŽ“ký\•k¾îdëYx©6î¢Öñê–hï^Š9ÐÑð±fê9Ùx†W´xw•‚'yÔ”k•µë…곆xšýxˆ·òÝmo5=¤ÀíUŽù+n¯œ†v~²ð½@˜/p§ÁìŒxoU)/ù¥OòU¯õb±¶î<€ª½Þ–Ö¹}»`>mƆí†÷‰\<2­À£Ÿ*vz’“Ò¤K2­_ìÉ&Ø'cÛB‰íâ~í·¸¯Oz¦×{ùýîs$ï ù´Åe¡­n^ûAÌæ;þǩϾy—ùûfÏû½—üp$sYy|ææCgÿÃ÷ÕWÌa|U“˧âÀW›ÉG}¢Ýr\Íü”¡[Â'Ê»Yõñ™_}É£bë´HÕ«X³;9iþCPð–~rVt(W©h}RÕ*4­Ûku•Ï(Ý—N9uf6ïÛ¿ã²…r°áÈ%œÅûõ)D¿J÷.& ¸²5Á‰@µ|³È¾K+ŠÅG9rè¾¥9«öå9³*×°c–/é¤zSŽv yµïH­{ÕU÷èJŽš~+ ^¶Ý²¸y#‡>y±òë˜'.,»»wÁ†•(““D—⓽k»{3ÚÙFKYW.›ßj8|ÂÐíuU–=èý·›tìå§ß‚“ð÷Ü=(á„®HXB 2¨!~JˆÔq1Q6œ¸”¸—m_8}ÆÈÄŠ³Qh㬼þŒ2ö8c‡ŠøE:ööjÖÕÞ‚4~S¤> ù(e@zˆã•XÒ‘á”\ºÕäUX_á‡dˆå¬´¥T_–Ôå›2¶ f–tÖéÅšp湑œrW\SÏ-ydu9Çd•Xá©ç¢ñ)—F „¢ŒVz¢Ýye›’ÎÇ›s†êç(,”Zjj0£Ž¡¤¬¶jЩ°z‰©l‘ˆ×‹€2–މçÑwE‚¾—j…±‹Ö°­êê²Ìªbì³6!Û´¬ÍT©Ôf[†´à5ëí·Îj+î5ÜŠƒí¸*”[ɹè¶ûã•Ê‚+o–ìºkï ê‚Sï½f¶/¿Ãe­kñþÎkðÕ´˜G <¨W”_²‹€W oÅgäËHÂ…0VÃ-a±' +ÌÈK¢qI·lç,’%—›®2«”Ã5§LÊÊnê<ÏZ.¬›Ì7‡ì±h3㌟Ñ>4©.GM¯yL÷$°±TœD"Íut[ï:æ˜â•Ùt2|öTì BU‡)¶ÖLAö]XÛ¥æmbfMö×&¯qÚˆ¹-õáþú9t€uÓòÖjæýétô)y¦àN¾æüexÏ.®’¦Ôu< å„zZyˆ“ÎùϚ׈øìžÆž×sJÓ#1·jÇ1Ÿùïë?]L<• ø¦í Úœ;äþ¸ZêÑ 2=õF»ŸÓî}¢Cšns}I,:öf›y½ðÚn|ûQ8¨<øÖ¶›JÑ:4û®«w?¡ðÛVì´Ò½ï°Oõ{Φð—"õí}B ö(†§Åbx˜£Dõ>ÆŒlå›™}Ç´R‡ÜÞ„6xÀNkWäqÊÿ¥'/ëÙÛ,b¦&…O° ©ºBÄ"ñˆHL¢—ÈÄ&:ñ‰PŒ¢˜“ù°†¹Ó†Nw vQ=:,PqÆ1ˆL” רŸhm‘ oúñ€ ¤ IÈBò†DbV0ȶþ8BWrd[çÄÆJÒ¯Q%KC&#‰¼H±Ð’<àߦ”=r“œìd@ÉJ’02•Å¢¾Z +Ö`”sx%,c9ÉkÑò—/Ü%eé$`rã“3À¥t)ÌSscÆŒ&)›Àg²LšÅ@æ”™Zfþ³K%(­ä‰Šü@ñ zJh1JQn@”s­(Á˜v^ô:ý‡FGú6CŒEû(vBJÒ¦oi¦K)†–¨Rµôò3-Íé8Lz³nÆ 5E›¤ªSúþA…,TƒK3<T‹Ñª¨P åêRt¼%Ojª¬†U„MÕyUÍ×U`«Ÿ’·M9ìþOqµ«AŠFC(ÖÍUcXí¸Àq×kôÛ®µðåZû‚Xü ª‘íi³Ø¢DËæ5;ïülq’ÎnZ»ù"bêÛe[Ût s·w¢8jS¬»Ñ=¡Ø^znfú wõº¿÷ík{q‚°õ_ÇSo.Ü[UûnE¿‹Ýgx÷ŠŒ#¢YÁÑ(»"è;á® $q¨XœQlÞØý'Þ Ôb¼csÇJž_…|n#'yÉåsLnŸ\ŸQXÓœ³ÝlÞå97«ÌÑs¡\pŠHOºÒ—Îô¦;ýéûÌ”ÊvÎóƒãôç›úЉnug³¨ÊE—êÖ5v¬onìÿ¥ùן\vPíþî3{>ß÷¸«Ñ\`ï:±ê.,½ËYt络ýþu>ïµüJ ÿ÷V^ñ’\d0Üvf@^9•·DãsyùÅK|Ëìž¶Á~í)óÌÿø—qÜßšê¹ê¯S'×ï³~ ¹Ÿ!¹êsõ nòìß .ï— ük(ÿ~æÞÿ·lÞGeä’ !DBb5-÷|ê—xBcBŽÕWó§J/cl` ;Ôn¡ã:és{Ý·~;ñÛ‡Y{Åþ?Òe{<µ3 XPÿÓ]H%$6±‚H! T:ƒ×AÄV%H~htVyß~º§?#d‚6ô8)¸h4Èyà†^dnÃ&ƒ‘WƒÀ&¶¦7E’ ¸W6£a~UøZ8XomW„Fx >õ|pE‚  me£ljø„ñ¤çA<_h…ËA‡XèZˆ2wB{h!tˆÊW…ôæjg¨*Çâ^‰×†¨j¬³„|HqHKµÂ8|ÃWm §…ÿ†4Ȉ~ˆhx2+×géA¸’l4„&[x‰NЊ£–‰mðŠæ‹ Çûlj·&n÷c€¤H…fxвÀOl§ŒþSšd‹ôGbº¸‹7£'záŒëäˆÍ‰1§+ÆZVÛd á'Ž˜@ŽŠic¸ˆXê[ìˆræxŽóH®dc7í˜ÑRÐt;‰pru ¹ Ù‰tÉz¹'‰oYOI‘ÉŒG毗‘½u‘lôx Y'Ê .jzx£øany¡:º.‘iVÙx“I*¹¤dô‹1]\ØCš–-A /ç €ˆŽ8*h[ê2eµ3Dé`JúŽÜ§˜ Ç(0*Zsª2Z:{uúƒê„,2óöŽú¨HôÚM‰ …Š}‡šž•j©‹*¦Z§›ÊuÉ™©wªœ |Wô©Rgªt ){*wX ˜öªª”UʪvW¤£¸*To#)¹—½Šnô²«¼:¬¹`mþ¤ª´‚¬Éj¬€ç¬h^´Ê§"6© ð1àÉ—Q—`z©eَЪ ³­•F2æZ’ÔZ8Á ªki¥Äq®±Ê¬6hãJ®Á¢0í'¯:[Õj­¬!zH@zwH™3â­‰sð§)~ƒ;Æ(C`Xkg*ØŠXö:®²H5Sø`Õq¸Ù°Ë7¯hå¯gç§ùÈ™rxúZ˜à  9›x9‘¢«V=VX±kŽp¯øzƒÊ:4Û–\$ž‹8,õ¯û0LJpÃgÉçnznÐ5›Bzˆ"²™Tw²{/»œŸx>Lš4+ƒÃ§³âʳl‹± Z:@»[½3´þ¶˜´‰ƒRR(\@Û¥ÂÉš«9³W¦IÒ›£}8[3;a‹¨[(7L 3d»[½§¶k«më¶òöE' ¹pkZËJk„㣒&Í…"rJ£“£„ç¸Ú¹­«W 3·è³¸¯×¸‘Ë¢¦³‡;”KmºÝ&7˜¹tÛXg{´ÕRÂ[Rh }wlL³] cm›KZG¼×Ë—É˶«© ŠmÆË‹b%Ú[ºâø»Àk¹ìë³'"§ç«µxCñ{CŸ«¬%;Fµéžyئö!ˆH¥k‰(Ë»e+BŒß{¬ið3é»ÀVqÍ;¼&Ëló˜Ql D´^ôþ§þQÀ2µo+Â>‡\=§›€ [¼ÎU L©ûJw¹¼/|K—{¯õ2ÃŽ©‡ÁÁõˆy¢5 !ÒJ¬ðÒ¾>‹¯E"ÌE«v›ùã{ü,:„{E¶$“»cXŠU{Î{XSçDÌλõ  Õ$Ñá¿(ŠR{ÑЫŸ_¢ùœ H-X íV•[ƒ[Œ}‡Í¤©ÔÊç——I“Èœþù€#Œ #Kƒ8Æq«ºÊ+Gæ »´ qÿ<Ó½a>þ#ı]Íqm›­¥ Ͳ”ØŸæÖÏ EÊj=†l=Ïn]&p-Àr¹ÈQוx×›ìÉMz~å”Ö½XÙˆæ\p+n6£ã 8}¦ºrŽa µ×‰±Í‰y€]Ù]¸ÓÏÃ<¢M"€²·TX½gÙÙúËÔ+8Ö‘\'ø—Í”ÖU ¯ Ìš·xZMm\ävÔŸmÀîË&ûcê|ܼeM¼íÅØÖÑ&-[>­ÄØèd:¼<\ÎxýÜWV²Íµê=Õ˜¬Ià=Þéßä½.yµÇw›É‰LÚq‚.Ðßï2µ³ó½Êþ/å}_ü Ø^ÉNà(&Ü nà–œ¶ áfõ{×íþ¼œÊn î»Þá3g‘õ½áœ,âJ¦ß—Œz(ž.Î=íÊá-^gLáT=ãc®áª,Î8n’&FÇB>äD^äRâ?ž°¹äUö¿¯ìw)¾ÝŒÏÛ¼kÉ {ýÝÌP®ÕÊF)ô5qB´ã<ÞÝ­s-ÚË`ͽÜZå¦8á“‹äPk=/åºryhT^u$nƒD£Ë“Ì î€&2ïK†2Ò¼RÛ3DΆ®µ<ÝTWÞà èž8è 2$‹Žµ›èÐwé2ÚèZeAb>æä™—ò=—UæQÕ¹ ± ZÓ¬»ƒ³x­¾Èì¢:8»ýK®¾½…›×ÚêïcÒÑþŒÝب ^¨îÁcºÒÙ£Ó•…Ѽ  +Ó£]ão^ë»rg[¾²ë¤žb‚ÓÞ»ÂLx¡žÓýÛÙô†ÕÅu/”Àdø;Î>Zùé@¶¾îãîæX¾Úî®ëöï;pÈ›ê„.ëKìf}Î18¢g-힇MoÐ@ý¤<ðµ<ëj8ÃÖ¬Tkî]úîðüžÚš+\OïðlïOcXR¼0]Š OÜ^–ìÍ×sU¤»é‹þ´ò—Þ8ï›[´ðuõèË1°øÌ¹/iìÍâ3Š5On#­è9¯ÞóK¿nо?óA4åÎãÿ^ÖXñüáÇ,g`)ô/Ø'ü´Bþ†Þó K7ã7(](*p®Í,«~·õØÝÁò[õ÷pÇö2oêÌæëæ•Ü ì¦°>œÆùÔ‹RýÎÈûW†á7Ž·rVù‡¯wz_Ìk_σŸäÍ0ë£ûô.çÙçý¿gþ&¾Z S—ÛF9iµg½yoaÄ‘,ÍMÕ• ¼×sá™þ®í dõ}—ï‰E£!ÇS¢Kçm©U+0)Õn¹¾ëYîyë%oÔk÷[`FKÛpûŸ/‡æªf0p©N¯ÐBNPñŒðÐñÒ1q‘r¤13Óf²ÒOó4ô‹3ð¯ó´TTõŽÕ• "@‡Cír7÷¥õíVX•·÷Wö7áøÁ6˜¹¹–¯Ò´w:*Ùùú™ZûäÖÚkÆ{xxJœ\}Íܵ{â;=v^½=í<¿GøC^aY½÷ô ’áâàA€>ö‹ƒ†H&Rü'£!‚§dôèfc4ˆ !"›hLáC‰+K‚SÇåG™ B¢ãþxÓDJZ/3Äô7s4œî(¶,iæQ N"] ꡚCK\Œzµ§P}$U.M ®â¥¦]‘b5›gê ªT2tÛ´bR²dÃF<6®Ã³Ò®}¢å]Ás_>8÷ëѽ‹Çô]k•qd€ZóÖ[·ðàw‰Kö Æq¿8+îZšîC„E93Ë2ÖУ÷e>ÜY©éðË~öMd6éßÃáQ>‡ÚnkÌp·&þ| ñ>ÒhWVzìàΫW7Wæ0t‰Ò«ÏAÎR¹æï¼Ã‹wŸ­¼’ØVgùsžBóµã î+·ÛÒë)ð {A þKºø¨97ÛâÎÀõþœ"н¬J±~ô’‹'·n»Ä·yþq§ñj–]úæ®6„”(/ŸP÷‹´ê$5 j€¸:ú(!³ýYïv3Ú’É?Ž ª7_A ©²•*{H~ì‰ Z²Ç«š/~ó aKF(¿® eIëÖ Y8 ФM²SðǦ켉5ÌŠÖS€DÃþ}ăY–š“&Î T«Òøx(†(¦¢‹RiáÂ’ÕµRá刮9£…vþF8h¨u?dÀš(*†Gx¼—µîƒD>®ã‹ÖÉáÁ$—L‹ã ?0Ft1R$„¹b‘’†T$$ßø¹8Ê1uedÔ£DFÅ”­1` Ü¢G$©½AšÊ’&"™³ÊErŽ”›º"7".îdtºÔÛ+U˯±,“+±%.AâIPòì„ü"å áä(ñKËd¥0æ©¶Éj4dÔE"3*Š™k pê÷ùrJ·œ7kc,tR­ŽuÊazÊ 2¦SŒx&4‰yJ•51JJ+äBk¹Ém”AMW+ÄR1KŸëƒ©µ¦)1OEµ$þQwýç“­ÆçeO3Ý›‰:ç9çU°—Ní¡*í˜I…EÒPæ.„Ÿªá ?FTZs¡‚IåÉÓ÷a.¥:uBSÕæÓ]:õVVõÉ––OeyÍD\õ¨eP­%ˆ©Xíiá¢*ÕA¨Uô| \m¥U:¬ ¯!ÚW2kZS–&d}D$UE‘VºÖ•­nÎa/§X¡1Pv])N)›OLÌY½ÒrdzÁ£“fíÒlÚêXʉ rj‘$Yt °^ UVÓˆê¨éÓ4A¬š§ŽdXÖ¶Öo¥5mG~ëÚôýöDÆêÜLç[ä&—mÂî ;6åVð¹Ð]'.ªûþçf÷=¡‘ît#ŠÜë¼RmïÒ{³Ð¶w©f/yåUÜõÐxø‚/ï‹ÞýB®¿òªc4ÿË_?Ñ÷§¬=¯"x„Ïîo„+&áÆÃÁ–I_æ‹à^ —Ñsçã·˜OÃc©†›qb< †M± SÉblpØÃÁ«±`w O Vì7.~]Ê(„-ߨÂC>2|>Hd“­xɧ«FŽƒ§[#Â$C`C²Æã™jT6I>Ž“ýe{ˆÙ'GHrëgkŒç‡–ú™·»´’wtéô;–±;;ë±Ö™é³”ùÓ kè«o}fòáø]Í+òÅÁýâànøu¼)-Ú"Ͷ—ñz¯AÚn–ç¶ßãV6œÝŽ÷››kîdô¸ißîø t]˜°âÏchù¼‹&ò±ž¼c+ïy&›¹’óç¥hzÖ· ô¢W°ÝçúÓ^ö[¯¹í¹›«ªë¼îWyÔ"vÞ óºoüð7ÿrã•[ÃFö¼ïñ{à^±gýZáWü¸ƒÚòªfèö}}Œj'¬ÇQ®~ìs_nxpÄ4T²J´“Ÿ^l÷~…“/uñGÿTìëÌ­åŠì¦>þJœ°ÉÓÚÁú€/íèJLÔ€lÛ„ïþôªÈôoÿ.OïïÿøI™­Ä^ãá\1ô ñfîÍý^ËÊ>ªˆNî› ¡Ìê¦ÏÄp/} dˆÚ Þ6ptp¹g¤Ö°ÒØ1ÿÀbAñ‡‰¼ìŸÔI-– 4ÚxïÚ3Ym(Á²$Wò T+ð3?©.vÈâËŠQ 3ó<¿ÒM^ø1:ñYJ4OfèþÒûä€F!mŠæ a &{p m# ª‡”HõC@Nõ„ó.ÇóûsÃñ”ÔœÆoŸÜL[sF'”Ú‚,ËŒ%; âŽqE22?C¦>•AÔýó:»súp3 i®=D$ÑmÙñ6µŒ9ÕçÌ J¥”Àö”.úôA¯pKUÉOAÓ<Ã4 8ó?þŸìÛÑýh”¬q/eªøÞMÐt\Uu2&ÉNEï‘ÎEPšê2ýÍÇfÌ$/'}ÕaÆ´¼úà>=ÏW©$ŽE½ ÓK‰ •Ų S=•>5OZ£óº2œ Ko«Y$EéÌîE¯”¬“,'RC³]KÑ‚•;Q‘oÖu˜6€Ž~|i+?5¯.Õ¿4^E¦Æ„±TË“)ù”‡`©R´$9v\¥µ¾†Oå¦Ó(?F¬œŒIÃÉcõ_e’d÷@Î]ÛR§ÈUY•Z°²æU¡Þ©$órùR+K„«’L|$ófÁÆc?6þ5CÖdljçPwç1§Nj·C@gw–6»Tl¿E¿–+òG[/mÁ¦lÍ9Ÿ5nÇp7Ã/lï¶@`nç jKPÑK‹Äh´€@ÑåŒåRÍ/ĤïQ·¥°—üÖj 6;³Ö ×ñ<3uk×PcÑs—óù¦O.ï¦rãÏüI2Ws£‡xÞϦÂM5õmÑöM\ÛUtýMA°b°¹â+P5¸,jkÒqVÁéç”l^v‡P?iÌþm8QÁvDÉI {ZwSƒ÷e£‘yQw;ÜDOÐZEªAWv[Op{DLR–VAHh‰rh'¤C þ°E¹Î<ðV…4pmŒ|éÔ Åé€ËeUÒ;$}wì^=´p Ôwìz®ÕìÖ°J¸’¸5 Mµµ€©0HË.Ë•sY$EÍ÷IT…÷Š ‡‡Õôð„txU0v8XPnÒ\UV¶1‡‰‘AË’€”½T„C÷…±:uÇÊu‘Ô˜h\>³Ô_ß”³âÔÎp·ª€˜]>UßÀЊ4Q1-cQ˜‰÷XÚ‚PÓ–|­bõøJM78RwøEo+9Dñ©”pßQvìni›!¢¸mÐøT¬µ‹-® $G½7UùV=ùñ/IC!‘xÛ-ÝzqoYÁ?þÌ+ 9bðm‡íò}Õqü8ë;™õ$_Ï-“"wyjYõðLH)6‡É¸ªo—™“Y™—™™'Rw‚• gç¢ùj9ù@;ð—%®m'ÏŽ°~OÙšIÌŒ‹eší6œ9'³ùj~I)Yz‹`ÏMÇùbÊy“åùDɰ»¬Çœö^M9žñ9ƒV¹z«™±èùdZ7#YhÙ$}Òè*kh6vÀY¡Y—šAÇžô¢º•í …5Íf;˜º öls™¤Ù š»Ëm¿9 WºQš6B:²2¥e:ÑŒtt7V§©˜¦»)øRàzm¡¸k½íßѨUam§³Äþ¦G+ªë‰A7V‰tÙ3R=7Y³ú5…¤ª;xžºz¾“E'wŠÍú½ä©©@· t«etqáZ…å5S¬Oz˜®·h«¸¯ÒLÃ-3…‘ˆTaϦšg¥¹ IW±A•±'›8=Ò¯Aò-Ô2b%üW„hyk>ù‰{øËx3¨YĈ]Ô‡ƒ9=ëºàTm²=”Å.1;³_ÌI?ø†·ÑˆE•üYOÕ—f “‰_[û‹s¶©‹‹…íÃGur?Æ:ˆ% > ¨ˆsU;kt˜Ý¸¸ýú©K€õÈM“2L›{õÔ^úmÄ/”¿”± ›º+·;âüþH­ÏrÔ»O¸}í»™¾—™v‰ÎDÙÛaU­Ç²|–šR /Áõ¸)«;¿õOù»©ÑSyý¯=ܶ¼µWóžº8º.ˆDq×ÙäZWÛÚº,Å!µçÊ _¹‚ÅXOP´óµ³«¥–™ºY­ÒœQå‡þÛ­-~¡»›ŽÀ#ôÍ#›þ) xÑôµš¢ïËoØ‹+¸¾a~€¼ÁÞ‰Þë·b·\êÓûTIQæMÂcÙ]¾©Aøê]½9‰ë¿žîGý¬Î›ÓÈî;é¶ZRÌünÈS¤ŸþæÅ½kX ‡øí}ÞÓ#¼Hë^òý·(yÆô²Â!–ï“zœ~2þ>ôÛgRú˜X3]{ÿ¨ÎMÈÕ[Óí貿¹"òg?sÞõ€öB ^$ϰâõ…Óa¼p¥¾‘#˜8 ý<0ji_ù­–Ž#Ò©»éÕYŒÿ˜§Ié|¹ñ5û ¿õœßû¿ÿÑ]7ù—Ÿü'ÔöM÷%c|O&j^¼}û+p¤C}§Ëþÿmòü=/qÝ9º·"^Þö¿$ªBs7Åþƒ¡8’¥y"°²­û±3¨}ã¹¾ó½ÿƒ§Z) š!“Ê%³é|B£Ò)µj½b³Ú-·E‚Ãâ1¹l>óŒÝµ²vi¸+Ê;CïÀEœ9ÿkßï¡ .±9ù*.26:*&êRVZ^bfjnrv¶=‚†ŠŽ’†©yrI¸0ÄE°jäÕõåÉÁâÙ¶vÜ~õ¾Ö"°–›œ¢z'+/3ÿD†KOSW[_cg>7sw{COf?m;–㜃«‡[§¯¿ÃÇ÷¸Gˆßãçëïó§Êÿ 8(Z¿ô ¹%p!{¨þ2Œ(‘ÄB/b̨q#µŠ?‚„Gã !O.ù%Ë–Ã<ª$)s&Íš6KâQG.h®€¹ *tDÌ&‡"%T”S xÊ!ú³gÒª"s,½©u+×®žšîÂZXG­¢%–ãÙ´n¬Õ–³ì/¢t‡¼ÍÊd\¯~ÿLn.Ÿ¸ˆ¸ÒÙjU°¶ztÈÑ1äÊE$w[¸b;œ¡.þåÔ2iS:ú N­zµß¦ ÅR5Ìù- ¥oïÅœ-@ʸ§h—óµçm‰iŠ |9ÖÓºYC.¤æY›=ï£p*óîgPwä-÷÷Êà+UïiÝ3r:Ûe—þo×ùôúöï_L¯ü:ìÙµ’'Ÿ€õdÄ "˜ÁsšèçË~ìÕ6 w xÖyøa˜¡†kè§ÜzÅù'!|’xÃ…Õè‡xAB€%.r"vö ˆíy8"Œåµ%ã†?äª3šbf°Š.O…ÛŽO*HŠNêa[0ÍA™Ò‚r5¦ÁXíÔ_’¯, æSVf‰[[ Ù¦›oNùÈ‹i&è#ŠâðÆkJš m¶M@$j±yÉœf ºãšp2Ú¨£85òe¢“²3“€œ‰i¦~  ”šS¨%‡C*¨B9f磫²ê•©§Âz,³ÒZ«­·âš«®»ÒêþOš.™v8ƪpÅ";Ï<¢¶Ú¬³[½š¬´’Ðt)§–%lÚNûÝ‚x¢×­¸Åø ê³ç¢ÛO´ã²k®4)æy-°!R‰-»h,ï¨÷ò;ì²éðMëö+­»_o.(ö§¤5êY01ék¨Äûv°Às¼ ÁǪ±Ç0À²HöTŒÉÇ&—1³Ã³Ç,Ó<ÄËÓ¤ i©+×ìŒ8 3Øó´ä‰,³ÑGSÁ³ÐYÐÈ, ’19suÈpÝŒ´Ö['ͤl³‡q$ŒU£Õy5}ÈÓqž‘Tm¦¯®‰]¦O’Ö‹B"ô”ÝbÛhÒǵàƒwÁpXÙíþ‡÷¶€Wù÷Ii¯äøB¼R^¹å—cž¹æ›s޹矃ºè£“^ºé§£žºê«³Þºë·bqa~ë _]¶—JKÙÀ½ ôöÚq{ø×êy}Øg²0ϘEn@œÙ„5|f˜£Iü"äòÞóöleküNv_+¦½Éu¼·¿«ÿÏÔÃ[l‹ÃQU¯ãÞÌÏ¡K‘Èyy·#Îk3éóŽö²&°²ì{ù _—¨‡<G`£_û$¢À™U0[¸äg÷Ћ=ØcÒ¼¨©>Õ+;Ñû•Ž.V@±-ƒÿºìDÂã‘%„6Ì› ¿qÁ¸õP*ŸÚ8=mýbw0¡þkç¯&æˆq÷šÓß„@“Uq†‹âüp˜Ãâù¯…A|Gãw·’lŠã¡Õ(FÄÂuñˆwùO‹¶x>(þÏ‹'$ ÁPF!]dć lGB¹%ïJ~Sd"Ó$ŽÑƒ¤Ä‡¦g"ã,2ˆùz£ )/^|©z`³$#ˤ'0žrHªK#Ç&6&ëP“üQ /¹ÆÛ¥a‚™ån|I–ð’Crc¡+à'Ú¡‹ôcá1—YK}KeB¤ðdiÀ€=So,‚¤ÅØ©“ágw¯cÝ/ÉxÍ^zP3ŠôT]bîïS4 &ɺ4Î{â“rÙ=c·S¶rŒ9þþÄ&š[j)œåœâ9±QC`ôŽÜô`:轆vr¡ñ!U?*DfÞp¨´úÀICŽ«£­¨íP ÅÆEtBS) ²‰Òn˜Š¦õ±)¹(¾R°vJŠè?1Z­›vK§WxhKuhQÅô©ó4*xŠÔ”ŒA©Ò±j}*?òý¤¤hZQ3´ú•«Œª¨'gç0ЬÒ)LuäÙ”ÊU´–âUf…Î]÷¼¦‚õœš<)¢VêàY{º”Ö×ÛØ5±¥Ñëa[õXé²­‚+[#H&ëÁ2¯•5ŠdC6ÚÈ™¡AaÍ"[ZóLì´Üs‰‹Á×RʶQ¸ìM]þ‹[´•A·©á-¢($\i¢qŽ¿U“l3³\Pøö›‚e-vXK4éJEq×}"¬¢uÜÀW±Í]`rsñÜ–÷¶çQzáWñ¥ƒ|¡mN9ä;Qe]-¸íµâzâQ¹Â5ýuËw›Þ…ºÀtÐØ²¥¿æ±²ð”^—÷׿:Ϙýû }ÕØýºéÀ¦õ¨Sé8àǘ "þet%êÉJôÂfð•lHÖ¯.QÍü`•w_E­†5=qŠ)YL&žØ< 6c’ñµäO$ÉI!¤üVSVž1OE°"»*Ÿb3™5÷dBâQªM¶ ˜{³fA$8Í5¶¶Œþdwâ0Pr¾sn,ä!¸ÍÂtqùÞÌæ3Y·tGÆ]ê&é+&Eœ m/:ÛÑÎ/Å.±\jé?éc‚†‘=G¾˜³†F›©gRj¿Ý„)7a- ßNðHú 0.# Q–¸Èô±¯XÊNóÂËpnµ†& ªQûcÕub6 êL Ë…»~ð:R=Y^ÞÖ3¸ ™§Á’¬æ²ÿ¬³õB{ ΖöK¨mO›ÇZöl—¹Û$vÊÏùxaÓ‚îPæÀ󆭟ݽpÛEôFP¼ëÉRŠzzßQö&]2¾iìFÕÄz9øÄ³Š×äáƒByUK~ëþˆ¯Œ]üô¥©$;šß÷æí<7ÌíòÉùÎá±æn.%ýhÕvuÖîëù»~¾Q¦/ÕØnÝó……etŒS=çÿøÈ¡®r§sœŸPߪºË•É"d[Ö»ûYÁÞ–Cͼˆœk1˜lÐò©©\®²ùäjĺóüXn—‡cÙÎ×çmX”éÜS#Õ©íü}ÖÄaÅ;à'w+|}ðAO¹¸J$Q“†äšÇ)$ Ïv;zaìvÁêz>‹iÇX6¹éÕ;úÉÖ~·YEú@x¿Zß#Eô·gï.ØÿPùÊÆ¾:ÖqîNØ[0÷U~è¥?êcÅëØ÷eéÝ­0M_Úñ‹ûûœ¿ }·þY?~~Ïr—w˜y·_aÛ7‹öç~Èd®>çÖ… §k½ÿ²Ófiÿt±—÷_;‰ß°Ôù†NNúíËÔ=’ƒ½#Í_YI Še ý Saàâ]à9ØWcrýÂMT v¥1Bü‘òÝ] Ý]”‘Tß4`¸SfØ‚IÍ&¾…’…±Þûý\üaïTš ŠÞ­P¯yŠŒÅBÖØFƒ‰ îàV¡¯Eáî BÎWp½ ºŠR|Çý½ºZf[ñLa¡u h±Ï^ƆTPAÞŽ·•›„ñOE‘=‘ì}•"v¡¥PŒ‰!!j‡þ!"â^D r…8•Ù&bÎþWˆÔn!¨é¡±ØDJήQ‘ÛÞuJòAÎ-X%FZ e]*ÙáøØ¢,ê %¦!–Ú'>ÕCÕaÁ•¢œ`¢A#ÙÔ¾é¶É.ñ/Jޫݸ% šùØ4f£1"Ä/ ] %ã½IÞíÜ2ŽšÝ°@Ú–ôÔÊ5c9ÆQÀUØÔQ£ÕYcžýZ>æâ6n?¦ ^"0Šãá`ÞTg¡c½å¡ ²£“Ü‹Ô×ÐÑI‚%dä-¤ƒÅ“•äNKyÜ!Y¡2QÞò…¤°%Žß|ä[Û(‰Á F "ŒÄ¤î5ä¡å¡îBîœþcbðäAí¹éCÓ@¢XýýA 5I 2dÕ$hbëÜäKŽãXÚ q˜À9EIø-ÏL6ÜZqbYšåYŽŽœ8e8BåU®TUŸ[¾Àç½ÉaßI]z%Tí™®ý#î \BtÉåQäI æP¨ã!Úc4:P5ö#žmY°½a`&&œæSúP;’$:èR<ú‘£Ù ‰]fK,&"&Þ`©Ý)S‡•˜L9æo_iúQnhæÄ,eÒ‘ Úñ悦Q¾SaFmš¦púœ_Já ÆAý°RQ6þØÏPraãÅ“XÙZgf&[6΢ª¡C?†âVá#þ"h•g޵R–dØ`›&ST^_v>Žq¾[¾`9Í&}ª)þ™èpˆÛ]†Ý{¡P"¿ñÁ…%#â¥õ Øg×ðgH,&W¾ užÄU(?Y¥fIƒ¡Z/fV(ááØýMž‘ +*ƒ­‘‹ºØ„2V‡zâ)fç~ÚhxÚf8>L\I# ¢ç¢(·µ¦VkBà3Þ"JÁnææŽŠÝC^¦ŽÈîìÌýà ¶hÿAdX::ihäF>VÞ-'`õ&)ù-©Þ}Ú˜JeÒa†I©)L¨†¶R–D¬é± V$U˜à¹‰émê+)d®õbþf–¹m–yNç†aŠŽ(ÃôÛú aGʧ{A¨èÜa©7æiöQibâÚNÒ%,¾XÛƒ‘aj:§%‹‘#å±g¬¢¥Ñ)yÝFE bªKzÑÅêjíiŽÎãk’'‹š¡< ¢V§{Pâ5ú•"î]k²¾…M}ªºÐÖÛ=L°‚ªN¤^ÊܲbMª &®A«{úá9êbuc|*<©'Xêe˜«¢.׸r༆܊òi’]hiF×9cHj©Sucli,N¬oZ(rçyì¿6Ÿ:‘¢»êM³>H®’A…Ò­lÛ4,âu’Î+¦ÍÜÅ#jŠþç-þ%ª8äÆ>WÇBYß´Ý„a’l¹˜,­™cszé{µF> P†MÑꘒÒJrYK&Û*%ŽŒRª v$À¬Ï,ºØÑÒûT I©fþ %:¡‘&ŸšÃ–Ÿ‡ŠÀþкÚžÉZÇ,¶íå+¶&lZf¤¬#S®\Þ’íÞšmÁú­IqžWNsb™!çÈ&ÝNny%êãâß"Ááòçi V±íÍê,?§x%îç6mþ§b¨F®ÇÊnQ©-¸"~eÖQ¦ yîî‚)í ßøD‘®2/8 n)mG íÃDZsòd¦bìˆqèóâ燲%Èþ–ê±½® å.”y/N%-ÃoúöUóžÚc*éÓžoߦ¯aÁ+\êèä>ü¢“ºÞ«©^iÞoBá(qî¯ßöoý¢ÙÌÒb*2°órêôú¤k°0mbdíF `Äög›V×Ú-Ë~fËn—z¨×îl€,cªÿZ¢„˜.½-l•>«ÌÕ0±¡Q€*å#.*¡ÎÇɶà`²pò¢g?'ý #ò¹éö^°e0ûòaÌ>¬ç*tîê¬Ú*s:§xê*|îÉS˜ý!ítq!jgÃÐ ?ÝN—ïSqåjð³B±"$ªq¶êÛy®^Är«Žy+!g.þ /b"2Ã1áLåçTS‡Ù¥r.cÇúêðkGû‰jå°Æùk¿Q+¬V]ëêëÝìâ)oòâFòàÈ14Ññ€ÒQ,s2Tñ's¨3F1µjë(¶®>Úγ@î03bá¾ñ, N-%c%ðR ¸îr1xrÏ ŠfvI³íðo 3w¥0».:ƒeÿeZ1ïlBà¯è¾– Ï¥ÔNªï†óšå°ÀYð+:íQè2ìþrF–©Õ zxítjê·‚q/,tI6tûp{òðIº$fÎs ·%g3øê±µeòz†ê‘†[3åÝ@K n®Öº™œúêíèRþs=‘ÓGks4v§ýÛ¦Ôñ ZuQµ­<3ñÕô5ìórØs á4òZ ÿlêµÕkÞD´½fOûò¯$-uìB®GGµ¦1ká#k]ÈÚ£Pw¯ñŠØS·µnÞnq±¬¢|uÜõvV®YG‒¢Î /q5Ú¾õ]cç¶2ðÙnnö}æuAf0rú¡H’§õk¶òÜ‚5aCoc7nÜ´å TSëõN=¶TËÄ;rß ›ïfíŠÁ5v+œÚ# °]‹uj+à*öKüv» ¶»NÚlã [‰òZÃFœ2g›¶þns¼÷²·gâ$Å®rP3önþß.£p6÷³tÃv‚wÕféìòèñŠÅÿÉrx«Y7jåÄV sC‰qËoj{ó6/ë±Çõ|ô÷°Ñ âf±K›&ïúh£Ö€ñ`±!Ò³97ÌŠo|2Þvÿ÷xC7öêMس*ò*„qaˆßê=ò˜µ."x]„³é÷u§[é7êÍ™Æ%s‡G÷‡´ oÑ4ŽâÇ-tëN ²V&"’Ãx!~ëf¬ƒs4<Ä÷öCN<09_Ú6wøÁ—þK#°Çû¨‰,zpƒ®-—¼É·Ûë¤gÝëÚÞ§†¿rí‹—v¶ø©~Ã;—µ=;Æí¢Û’6¶S²ó|ÏxLUk%|ަmÍû5ÝÕa»C­Ïžlb}Ö÷ûT›Î 7ÇÓgæ9=S”¶àþ]ÙÃ;n§=sí;ÛûQ—ߤÌWéŒÏwÛ)`ÿa2/2~û½±&$w0àwrþÚùFþ¯P0 »ö¢{kw=¥Ïû»7¹Ë’ádâ/ß§7¾Æ3G©Ó0¦F+åG/«ê»­§µq­U *ø÷¾´<£~øF8õš(«ç[ Ám…ϱ±ö!Ú{¾¹ ~CªâüHþ[ ‹×jƒV}´#ýŒÅ8.o_#—¹«·¾s¦}`¶øû9Û¯::^îãöow´7³$@ô3QTÆÔVœÌ„KÝÍ: -$±RãÒ/_8ödº¶oü  ÷`P8$GdR¹<>rOhT:¥V­W¹åv½?&Ù fV½f·Ýox\þÑ~íw¡s¾ç÷ýÿ¨¼Áž0²²2‰1=ưÇC±È2—´‘ÊÉHÍLÃDI“ÑÒ´O·FÀ6AB×WØØÂUÚZÛ·VY]]CÎE ’™Ûaâbãc˜ÜÝå Uägèh5ef¤^É߈`ЖnHNpSnîþìÎðNtgËðóvÓ5uiêêzû×xyýý)úûkØÆxÇÏàA„ÈüÄ%S2aç]q’/áÅ~u渎 :¯‰#9i‘ªŠKº3J¤§“+KÂÃ8OãFœ9‰X¬ÙSÞB8ÅìökƒO¤I•f ËâÀ—–n ™¶Ô* ‡bó8ªRJLF‰ž!Ú뫊`åȸ­-ŠE¥¢Ik¶¬§³lx&ÌÚÔ¯½½Wûéû·^àÁ‰/qÓ° ‘ {ˆ -°1\)Ÿ¬K•±àÂÿ×(߃¥ù…~ÜÚ•êϱ™ºÖzÑmܹu?”ÝÛ7 Ö´‡€òõÀ-%‘þÄ¥ÝTð7Òà‡mï¦^ÝúuìÙµoçÞÝûwðÔ«&Ž.Ü<ØÏÕ's|~Yúõñåÿ)ï@g3ÆÅ"7žŸùòX‚o>[ê{@kPís°™#´éÁj”ðB §jBŽÆêê¸ îò@ÌÒÉpµ …:qÅc,„¦A„·bK>c ˆE{”"GÚô‹,ãòŹôñÅk[òI>\dRG*wäIÈ~L›JJ‰ž²Êá sÌš¤ò¨è²9ª*Êk­Ì>’KÍÉÈæË†ìÔ .2L9,Í5»T³¿B3°«².ÙL£­4¨‘”› RU×:ò8ÿº‹%ÿ0×áN#èd”­Ry‰‚e-™Ð„Õ’Y¯–k†ä…M-KHý¥$-8ÕB/–ýì¹ 2þ&ÖÊø#1g¬ixùž¦³îië$¢vU ËþªntH962Dš+ºÎ›sîš>žŸökn¯«Û½£àš‰ñΛǽ+|ÉÂ軹K9;žÇµ†ñÅ%kÁ£¬ÛnTçkó§«MÕqÍ<7=ñMt^<=’#“)›l×ߺºåÌ5çÜ[Õye=dÑÙÜÑÞG}—Ü‹æø0M<…¤Ø ‘òÚ[2¾7æwß"yåCù]bw¨ž~?î»/ûX®Dû‰§$9Í÷ÞgsŠ‹wZéﯞÖë±ÿ^{®É/èÛÔý^Wµ •O€^ú_k‘¯w rrúÑíH@K5î€ÌZZÉòU—±Ð©8oê_¸@Ã-Ði(þlM¦ÂÃað5„bTª'¨$¤HSô`X&ú1ì…§ùa–|#CÜJ¢â\˜¿%f ‰  šˆÖ«ÒQpP}›IpBB¸H_qP ±ÊHF061}^ºŒ¡è iR®‰ÍˆÞ-‚«ÜãEÿ¸€úˆ£äf >A–T[3%©N¡3R˜ÁͦùÁ)³´ÖɸõŠ2PØRõ6DÅœ¥)í´éÒýÕŒ^Oâ©tžgµ¯*Ô§{ê*®Æê“Y¾Žmj•ärŒΆ=0Já:P©Z„svÓœ~KfÛF¸Ô. T…¦ä¹Ë³ ô˜‰U]ÖÏÈ5§æ,QˆKª‰0”Û8›þe›© rN6ªõº+ÀK…²N ²0•ìi1•Ú¹65޵’ùÉ6›µ·þô f?t»È®¯àí!FÚÒ2DªÆ£­º {Óe½T¶2m®j§ë;úÁ º=œ(ü¾ÉC¬Ö) ^xõ™åN5¹Ê½n ªKÈÕvì·íìbé«´Fr·Îby³ŠQ(ú–1ÍÇÖë¤ûjˆ°*±˜qÌÕ÷"o2·ÛîXѤf8abÕpSÉ•_Vò—]c´íøL¼Í¾2¼Ò5)`k·ôzíÅ­«iáš´÷hÆx•ˆ*'颸¡ìeŒ’Ö6u·œá«ÒêxŠ–rwÉJö+ùþª¼1ZÓÅN®‘1ÇeæØs;Vbó ÖX ii¯M¶CöYÃ3„Vƒ;y™"u^°˜µÆg‰N'<ºñóê@ZÎÃ’6•­º°-f†à²ä -}iLgZÓH…‚È|èB³§Ï¡þ2¨• Â:>S¿&Nê“/Ê/y’š0žtDõŒ»ZûJÖ¥¶oQÍ]²ZÄkÞWª5úá\ßg×ô)V²µ9£…o/6"²¡SzëeÏÔVUޱõÏsdc”Dv³=l[áÓöU_eËq#öýr£ÎFä¹¶n©Ãû©¬‡ok@g&9Ñ‚E±“nS"\oôÖ¤ Úþ†Ùb–ÓÚÍÙŸÍ{Ôö.w¯e OXœãþо“UØ*F9¬¬’¦¢ ¼"“SqäO— 6}sœƒ'äæžùi}`ö&ÓÕ&¶ß‰™jtên¼çÀй^ÐX/”%gø )ö–ïêo«užbm­ÔÜ’XêQ­º;ÇŽn‘³Ï©Þ‡©ì/¤JIìyú¾²•ª˜’¯vÉÖ Wv¼«½Õð;;Ù·]x\¤}dœ;TÛ*nO>^®{0rÝQ ø$æ5ÉD*ê™5§™]V¨:Æ­šÿï7ǹè¯Ú ìâ×·ƈå/÷ŽÚ;ùÛ<±Ê±/ýƺþêŽýÞ¡‡–¹ûx·xn¥lŽÿ"¸3¿Ù@?¯:·õs§W Ÿ–›?ìŠ>´»j?¢³ž»ªGÃ’¢;ºû¾lÀŸÈ<ä+=À€žíÓ»9‹Àå1Á ´yÁ"{´ÿ{<ÄŠjó°þꌶ̱©a0œ ÚC3xƒ$",±´@^AÔ4¸>³Ÿ z2cÁ#{ÂÇÒ§rR›ß‹6¼ÅÀ 60\»÷á@1D£ì²£ç²Â¡p¢9¼þ²Šk'ã7»ø›,kB'4ÀT?-L!:C,,¿Al!.´0Ðû&Ë!Š=ˆ3šp‘I§Hi¦Ýó,‚ÄÜÓDœr·Q¼©3D!#¾’Ë”D Tº§2ÅCüœC£8<â½Æ‘ðÂKЮ´ñ.íÓÅZd´¸™8%ä¾Þ¢?ž{E4<ÅÔð˜[Åž‰B¦ƒÆ5ŠE¯;9ÐÀ˜P”WJ1–ú?mD±{7 Œ®*Ò5Ü{·¦ÚŠuE¼à7q„¢ô ¥´=iÄ9ôŒ:lD;”À@ƒHš¬I›”‡“Do±qÄ—T›}£¹êÊŸŒId¹*ÄÄ/R´F¶ů¼ÉECÝ{¿ÿ˜4J³ÇßËMYMíü¢6DIÜ¥ÔŒË1ÄAñŒ<5œN’,’ ,ЫóÆqËÔÌ,L@ ÔlÃÏÔ7Fü CîÄÁÚ,Üd<ôŒ¼§ $Ó?ƒô†,cÕK¤Äù.‹Χ4J`ÅÊ#2ÝC…qüÓRU>AýÑV5!SC½ ¥ÔýDŠJnìĽÒþV1M˜º„Ëõ,Åf$9‹Ö2õѯKÌje"}ì>a¥Á6CHxé'àò}5F~ýÌ@kL‚-Xƒ=ØïÐ8we¿iýºyÝS«@4»ÀoRü̓ÜUòþòTCµÖwŒÀruȅ͆]ˇ…X[@‚´Ò‘<ËnÜÓŠ½89•Ç­$M1AUyT:,OfìØ5Ù“­¥D‘-í,gÏN½Øœ,š˜ÍÓQ5°¿Ù‘MUót+ b…ÀÔÈ …¾šËf%É7!«¤J;ü<¨¬ÊÞÛÄcXÈ”ÚúªÚ†ÚÄI4Ö‡ƒR±Æ)Ý©5eØ®µ¦¡%†RšÚsMÖ#\¼”ÛØÜK•ä;éiMŸ%=®ý[“ Ü;¹3^«Y¸[Å5+¡cÊÕ„ÒñBºŒ¤Vʽ mÓ¨{=ÄMÜÎõÜñlÊØÙL®óS9ê[³»Z…ÅÓݳÿÔÎÕµA2t¼þ'ENœáÝQÉ3Ü%A|m•JNù²Ý”Y^ŸÃ|@‰Öõ³ÔMÓàåÀë%¼0TOv=¥E¢ÞÏ•¸Î“D<¼ÃÑÛœÝBÙƒÚ£ÐÈí]¦²\$ͯ¥_âú=;ÍNûEPáÃØäUÞ×}Af‹'óÍÏMÁ(ÅNü…½ßÍM$¿p»>4Õ-ájÍÅŸ+ßöÜ()Î j`«ÉûÛà 6Í÷îc?þc@dAdB.dC>dDNdE^äDÔk¨BÐÍ^1KÝpd«”\ÆÇ}˜ò ÎôÔdáEÞôýd´ûÎG~ÃH¦ØÏŠã¥äÃ&ãª;ÆcXŽåô“KMåbß­WÏ›QBUe 5šºÅÊJîEãq­2¸bÄaî P$×[2ÜŠÄd3VI¦ZY®fkîQZžU[öJ/¦E3ýªâýÅ•ÛEeÊìKÉ æ ÕRqNg޽Â[ÖÜh†fá³×ºâkÎgÛf´ Ü”ð6¼ýǦÅÒé|V™½R,ÂÔmÜ~#è§¥æzcÝéÕgŠ®h’þågºóç}üæO=è–åBq\Y†ç¼ÝÀ;=¬Œ…^dŒÚ³›fˆ¶h˜Ži6Å茞Åç—ÝÔ¦µR&4h¦ÅSž6iHCZ}gNéÞ™sé—–i¦Îg¥&LJž,UM=ÊÑ»J÷ÍêS#V&Û,o½2úüâ¡òê¶¾i8W©{jnj¶vjšFÄ .òœç¹ÌBgF¾×Äç¶ÞkøzëíüÚ*lÁì„íâª*<µ^k¾^ìNìÜÞýEëžsl"flËÆc¤L„ -¿6ìãSÝØ c&­Áö1^Ÿcϱ%Þ‹¬å…_½¾lØV–\Þ>Ê.4È6b7æT_P¥ïÅZþÊ[׎mâ–[” ÏXêìÊ~U vcEiÑšÐýªÐ­ßGôT¦ ý_mžµá.nðŽÖã~îÚžä".ÑÑRNÃàâÆàK+-…oGª‘Ò oýÞÐ*ÜŠ.ï»môvîÿõoZDNÑõ@)ÅaÈIp.Ý»„¾ÜüÞo ÿJ”#é:VîåþZÐþÎç-ê‚k0:UÖ6WéUð‘yí oqå³äÙ½_ OR!d2”5fmxÈqÔþî­„qͰTèÄT:Þ ,òänIuq&¿»Ì¾½Sñ»í‚ŒUÁ[ÃFíí¼Óòå¾mr8?0)ÇÂí8GœÁdÎÄneæµõDq]fcþÒÃÆ/T­7sD_0yñ•æð ÞòóúW]ØÏÅqÆ·¶%lNïtß OtQo8FßJFGŸfÙ†Nh}mTý3‡vÍö¼kR›óu\'õRÿ ¾E“ŒT”>h_?éõvY§:Z5[Ç Ïu\_v‡”Nåùõo˜ãÉ•÷yðv4Úu瘿÷™ÇíÝì:8NBêaÑÞºW.ª·zµw®~ºs<÷­Ÿæ¶Í#þïaµØJŸaóâ¿â»·ª_{ØÎú¿yѸµ¹ͺ7ñ¤MÂ$®S§´|ÉŸÔùê$Gø¨ÞÙõsÔž¶„¤ƒF-ïn¸¦ü9}Y9FuÇ'zôòûÉ}]ƒ2'­aq*|‚Çe…†õ‚Pþ°æÙ«m·ßþ}Oþkêë®Í~{_.ãe]åfíCOC™ø…}âŽÛofÜGQZ­cþ¾²3Ú©)9 ÿõå{dk=*f` ‡Ïùt…~èÿ{éoë+ùêßplÄáçæD^<³?{¬7ˆŽgʲ¸ÞK)X&[vºB=QâH–æ Àʶî Çr–V}æ:º÷þ }¸¡ñˆLæR³¦ó J§ÔªõŠÍj·Ü®÷ »ŠÊ²ùŒN«×ì¶‘)Ž;#ƒäÒàpìyºž§çWèW#X÷·a“¨˜q×èÑñç'7E†éù úÙJª¹‰šªºÊÚêú û4ZZk{þ‹›«« "†¸÷1Ié hø¸x‰| Y´Ñl|2!í˜÷×¼[×ëÛB».¾>n®sê­¾ÎÞîþÏZ~N_oŸ–ωl ­@°JÚ"‘ˆ&b`Ÿ–”%ôpY¿jnÓçk¾5r<‡qŸÈ‘$Kš<ùÅãÇ•,[‚솲I„ŠúPËðæµd%9[˜XÍ;ƒ(ªs¡‰„š2ª9.d,•.«Ú¢j—Ô˜\»zý ÖÖ¬dËšM²ÕëØ[k!AÝÕÖeZ±gëêŠk·Íܰ|ûúý ˜Þ¼„ —ÝÓNÒÅŒ;~ 9²äÉ”+[¾Œ9³ã¨0Õ 6 ÚþÄçÐe>:µêŒ¤[».lúäè×´¯vö6»¶áܺÄ^ <¸ðáVfR,&Ôø¤·½›;ïñ»$ïçÔÍDßdœ MœÈ—÷;¸ýaéƒ;’’ÈzuR׉»¸À…Än"]?¿ƒÛ|§ëÿ²Ì‡S}n1—þA´‚ "xăî_…^8œ4ÉìQÐQM"l‚%aˆ&RØŽ†Öt(^xöâÓ2ÕH¢½¥”0:Î(L0î„Ö‰ùŒˆa‘F)PÖø³‡% %(í‰ôd”úM)†Šô1)Žç1)‡<T̆ ‰¦ã"4ŽYæÀ(ô†•Ö‰dþvÞ ‹–ÝɈMOrþY–ñT (u‚‚¡§yÁ rcxH¨æ™U M24i¦ŒÀ9¡ùŠg¨¢Ž E¢Î0Z‘§…®ú]©Êjm zaªv}¦úÝD˜JÊ+›£ØwŒ¦¾ž©¬ëÍJj²ÊŽJ °ok´œ¦œNK]¢Ô‹_6ˆf„Žnûa”ÈrÑ쩺›±~¢+,2¸*Ùk»AJĸËÞ‹/†ÙU4TNÞ•IoÀ¹Êªê-Vf’ë܆[É„öj±oCJºèÔžÚ’ Ô† DâH£ë±ogBp¾.¿l§±+ÏÌ^Ë(̦?›*²AoIÐþçök#Ñ“‰qš½Mœ…Ì~ä4t4sÕV‹ª˜fšMÍ5&L³†¼î(öµ‘ˆìäynv ë¢[vÔZÙ¬JÖZßwÞzï­7r?÷õÕ‚~s׆×øTºþ ÚïbqNÌ4ôëKú{+´KÓÊ߇—÷¹hœNzé$†Žº\£“ôlŒÝR+äf†Ù"åÓX´2ÇåÜ\âUxž:¸ÁóbzñÆS;|ò÷øþJëÃn{¸“-»†îê|¹îWªóü(/ð½¯~|ùæ¯#>øê˜rPÅ`Ññkï±íÀ掣¢BG,9Ç7üïI!}à# ¬Èw¾*Pþëk \¸>L+]`$< ‚ ì SâÀ²…ƒð°ßNˆÂª1ãs‡Q÷ÂÖXðƒ4¬¡`DˆÃš!/‡Ÿ"!yhŠÎІDì Bežo] ‰!_²Ã'ʇ´ÊC¶Ä ïvôr"i†XÄ0š‰™»ÑÑ®‡) Œ¨ð¢ÉAÅ.[bó'È*7††bìc錱»ãìYE„!m²)¥½±…í[¤sø(@nz‚Zÿ옱£¹(e!$ýJ«qÏ;,š]íØ¹™pÒ‘"Š"+ióIŒ2‘¼ãÞOP9;UêÑ»M,C L|YŽþ´$&§âõŒÙò•{Œ#;zÉÌ9s ÃÜ]ØÊ@dòD™‘;Ìp’ gÖìY%S&¬JM/š2œ¦gعAfŽ˜a:gåpIÈevò›î§?7HÜqÇŒÕÓæ»  Ïzõl‹IÄ¥hY2î$ä[éZå¼>Îo`“z2å-ÓùÑl.-‡ý§I=Ìil(ÔXØ%ϘIe:.¡_\è€æÙ3¶íLiÏ „VQŸ®¬¤+HéžVŠÈCò,YSB&Òî‘Ô¦'­ê²JS‰Q5O8¥ÉF¿Æô)OIŸ–ê¶—J‹¨Àj¬ÜJ¶Zu®ʪ]+°ÕæõÏŒþá&šV°–r›"ÕeTÿÄV¸®J±v‘+]«ÆÞuŠ;ÔÉ$ &‰ŽŒzØ{hÙ~Ú+%v² ã¡c!‹ZÀH–´ŒTíâBšÌè‰ç}¹ÓÖÛî©ÏÅæõ{¬iw›ÚàÂgµ½=`ezK_ýwÒ,=—[P‹Zi´ÅÅ£'+Üì ‡¸ÕuÍi±à>›\óÙÊß&™ÊøýÏ”÷sn´¨ÛÝ; »Ú­oj¸ßfºÒø5|ó ÔëÚwÀ/ë/€ãJߺ½n… n°ÖößVyß%°…ßa` #.ÁÓ°êäéaé&¯Â.ñ;ÑÞ+º)‹ž­oClÿÆ+¡þ®£RÜ$,¶´Åê)z\Ü-©II26±‘õZ?ÍÔbf²uiüáFBy#6®ã9£gMw)Èkœlâ‰Ìá#‹9‚Ÿí˜=)9²¥¨Ù©ÅÌé”¶ß7C1Ee–è™S•É‹ñTgšlìÚR‘u½›lK†æ1+šÎ˜µ3D™ÜMØ‚ÔV‡~e‘y+gzT¬”J˜%'¬)·Mç:&>5gØN½ñÒ‹nõ{rÞ>å9·§þ)'œi¯%Z•Îꦷ9ëBn½EÑÔ¤AFëc«ôš¦²YíêhS¬Î´ÝóãÔ¦Íö6;×¼ÜuzMÓ_Ï’¶ãÕœ—ƤìZONÝ¡--þ˜¥ où`y³üê(¶Ù 7n°²úóW#ÖüT×=ƒ¢@~¸÷Íh{‡5Éo£·õÒ-¯èF|B]µ·ãño¿ôM9^[Rm^¥öù’Iĵ¾áx\£]Y‹æÜ¢–ÓÈÅzAøâ/øÇÿíñõÚÈÍ_5óǧWr—¢XÐÆÜ¶ƒ Dhg|é29ùú”>‹®J=Ë wKyÍÌ#³.Êáû{/ÍÇc<+PgºÙÁîà´÷Íé¥({Ó™m4±öU§¾­§c‹N¤™Ü¿_רÚÿøÀ7FeŽtûÙÏ>v¶‡¯ïUÔ^9ùÕh Y2{H¼ì0%>sç7ñV1üá™ÎyÅ?0åŠ äÔþé>ùÚ 4g¸t¡"\ÝÐGùó´O’è‡çy¼¶Ú;ú¶Z>¶ÔsúÞGì{+ûÙ×~ùƒº=î/ÇeÛàŒ#y¯rÿ©wîh޻ءßV'¿%¹g~´Çïü¶ƒŸš,A<_÷Cmýæ7¿üÓ/ ú7mÁ‚ï?཮y±MåW‹vø§kq†€R~˜ˆX€cÆ)jv6]"_ζ€ó§€˜€ g¦wTs$dP¨øy­Ç1÷dè(Ø1ÈÇÇYr.—ÃN¨‚F&IÆTJscD·}Nq‚ï&e4˜ ?‚4„iFt#§IH¸Oþ˜‚?hvƒ)ûbjWjnÆ„ 8ƒcˆ›öx[wyWkù$†ÞO>¨…öpA3S®wP’ÂMe†n ‡EÕ‡øL>ç3fò…Ù&}8K õ‡s8`K†wWF|Õn(ˆ‘„‚—R’ˆyùŠp‡YèˆGNzfL\”nyh‰M(e 5?jÒoà2ZtThpGo7ˆÏ…ŠžxJ“ÆŠ‹Èˆ¤XŠðfT˜tª$…"Sw‡­è‡ÈH§¸pUhmNd$s¢’Ç<Z³åCâ„vSÍ¨Žº³fJÅ8P%bawŒÉhGøŠ–·TÚXu—ÕuþlVVOUzçhL%HCgunr§rY·|¦PxW™HeÖx˜úèZkhˆáW²õ(õ4o‰wq'lÀW+"茿bÏsw„%MiW)ƒ‰“䲑o…‘´{ôD6ÐÕõƒ2ÀèQo(|çY‘W޶U[KÙpÒ€Èçk=™“@¸“yd•¥ò“T’B™”Ûxz” Gy«–huƒÎÅ’Þ‡SIZ6y“WI—3–•¯·•QçxC‰Kà8?gÉQצHÌUolÉîE˜ö3”Q)6‡5™—uùˆw‰—ü6k{ø"h³D#©}ƒVnæÅ™D‘Û÷›‰}éþš«é7pY‘™’Y_rI™›3àE%21ôBŽ9€°)›Á©—µ9]·IüçÉ©œËx­B“ œÂ)ºGœÅY†ÕY®ék“ÕˆÓéO6·lë¸s‡åeØy‰~A›êcc˜‹âikäÉ‹·¨ƒäˆtOÃÆétU.ê¢N´Pžæ©ø)K*•éØh¬§N߸e~Øe„§÷™Ÿ~LI;-9lª rÑØfóH (Ò‘êpiwPiiuŸéFègò“KžÙT,µ¡þÉZÝ)¡¡;9•V^XXˆØ¢¤¢Ùy?š" “•„6èc™Õr=L [ë¶Š À†þZ£Ó™(PyVÂ(izpx(¤x¤_ DšL]’£8Õd#¸+m(^^ʦ¹øP÷D¥U*œ±³Qfº£oZŒbj›aʧâ–J”´dIÊ+`Ø—“x¨¡ØUI§Ò¹Ÿk¹S9Œ”¨¨|:¦–Ù™ÖRh´È‹jùcVÔ©|Ijh(©*2¨¶([†Jq“š¨­º¨á& NàI–,™c÷ެ‰ò˜žÏGzbÅ«$YŸ_rŽ1G¨s¬ã«;x"Êž ‚«õ!Ì1V”s2›’Ϙ¡N…2X\4J«Eô«æÙˆØXšš™ø†¤u8je¢çg¦És. S ¹©dþí8á:«ãj£ÈÉœig©oi™ð²­©Ø0—bwµ„g'j)Åz1Ù‰ªÈ£Î¡ÎIgë±ûÌ*«+™åŠçÚ•jȰ~˜Á§¦DsDÒ#PJ‰§Ã÷‰Ñ€™nY ýÊL&{‘$[— +´CK´Ek´–°µ—|šâè”.û´¼3˜žª˜ÂW±Ý¥•ª‰u´]ëµ_ ¶þ—´@+F`¶g‹¶i«¶k˶më¶l›o+·sK·uk·w‹·y«·{Ë·}ë·;¬Ø#’—Gn…Ù{‡¹ed@Í•¸0‹zÝ7qæVƒë¸—‹¹™«¹|·›ë¹Ÿ º¡Û¶dKº­ þ¸¥‹(§‹‰ÒGµÎÒ{úó3îhšŸ9O²;šÜJ…£«Sߪ³9¶5¤º¨K¼shÅK+ÃÛ Áe%ZÁKCÊ‹¼ÓË|ÇK½ÓfèI°a˽Ý݆“Ò{½ã z@¾ÅQ}á³½$¾ç ¿Ò&ñ‹i°¼+:ù¾ôË¿GF ý;œæ{:økí»@û À L`ÿ«ÀÇ9Q_±¾©#® „À lÁ©¥  v6 \ÀöXÁ,ÂUŸ#<¡àñ*ܧÉÂ&ìÂÁTÂ#8þ¬ÃQlC<¬Á“ÐV÷Û–ÙØ8´XqËúrÅš ßè¬1W|8W}óª­øhúÌÇüüÖ±;á´;r½ÊN{Žà!Î ! â7ÔР꼕Yà"Îâ$B⬳½-ãÊ Í+Þâ7ž"]â'ÜÓª-L8䲡ã#Á0$Ü÷²ãA®äIþN§%^ä¡ããH®äSA,íäPí¡ˆGå[Ža- âOŽQG^Õ\Næ€mådVÖ+Xækž6mà`~8Qž,LÎæNçMÞ|ý¼=»†y¦j`,±€eÄåHª·J×¢ºµK æÌRç.nžç"(ÞGXGqRq(IèéØ_,²‹ý‚GŒ¬‹Ž5ŽNêusÓômÝéý„³ŒŠ\’O]WékêU¯« Ú„8ëÝŠÇ Yjû#ç£^êÁÎk§^B²Í^v˜YJ|ʲÀ­é)yßëkî™*Yf˜}ˆ>*¢Ž'w.ìÅííxn åŠÛZyjê{ÍÞM†=læDËÒÞÏ]OïÎÞþ@Çí1óíùŽ(AÜÎsšÈÞÉþþ¨[Jí¬ ˜ëiÓmÌ„ûÍõ®.÷^'á®ï’-ñUJÜþþïÚ^i2ð’ëé.fínÞ‹{=!ÏðŸdPÚ$?ñjíòzñ¬‹¯ìyª¢M…™É8¯ç°žÏ¾ÏYváj•á¹KP^¥$,R/ÏôM³Ô¬=~»éÐö¹¡Q锩¤^±ÙˆUÛõ~ÁYn˜\6ŸÑiµn¼v¿Qmøœ^OËíyýžß÷ðþë þ« %à '-/û*179;=5?EmBGMOŸJQWY[]‰T_e;bgmoOjqwy{}t…‚‡‹•—™A›ŸI ¥›“§­¯±½ª³Q·¹¿½ÁÇÉËI͇ÅÑ×íÔÙßáã-ÜåÃëïéñ÷ù×õûý8p‰@‚3˜C‡d>”8±EO-fÌ¥‘cÇt-a9ò‚H’'QÂ1™ËJ–/‰Á”9ÓMC.m’Ä™“gO!;}”âP¢G‘²0š”ÇR¦>•:5CTª3¬^•—UkW¯1¿ªáÖÜX²g“šEkBíÚkmÝÆ¥ W.­º3éÞþÕ;2ï^~Qö;ã0O;õÄ“OJþ T>÷įPAß;&EÙcÑóe)Òñ&}´»JOÂÔ:M-­ŽS>….ÔN›µ#S‹C•ÔTUµ7WWå V‹f…­ÖXg»U"]Oã×^õu3a Ø„Ž¥,ÙbK{tÙÆžeÖ5g¥ý¡Úk­¥Û¢Ý8K»MÎÛqkw sïB—Üð:U7.w×}—TxÑ¢7Þzç½W)}ù]Á^|þõ*à~+\u` N˜­Xžªa…¥z‰Ó‚Øâ(~'ã'/îþxƒýñ8D‘IÆñW»,YeÄN^y”]^´X˜ñŠÙæhZ¾™Ly¦Ÿ%åYh Ë!:0¡{–ÖèçÖyééš~ºéŒ¤§jª§vºÚ«iÍúf®¹{W¯m{4­ÉŽÙì³ËN[ml×>(n·ÏÝvn€î¦›Ÿ¼¥á`½]öÁ·|e©QqÃ'wñ/ùñe&/:rÅÉ­êËIÖ\!‘=çÜêuCg[tKÿèâÔO7Ý[Öûnôxa¦vÙc'âÛqü^Þ?ï}õß^xÖô5þåžö~™o~£Ç¥zé—§>yì-¾þï}ã~w艿x‚Áþg%}ó¿G_wöÝßnøÏ—núí×þ~üɯÿÚõù>…° `+ (‹bb¬L÷”æ@ý 0‚,ßøffÁ R0g|qÕ@~B„4؟ױ&b…(ÜD xBfnvíš! QgÃ:®ssj w(£¾i @ ¢$ŒC6ñˆ¯“œÄ&:BŠê#b§8¿'.‹¨bÿðÅUˆñNk2u5®‘mtãáG9ΑŽu´ãñ˜G=î‘}ôãÈ5–MJ0$y,’‘tä#!IIN’’•´ä%1™IMn’“ôä'AJQ þ  ä™rpHD¦q”­tå+aKYÎ’–µôd)OY¦T@«L¤-La“˜Å4æ$q™Ë0•`—¾üå1¡MiN“šÑLfÈ#eÓ™PPd5ÁNqŽ“œÈ4å¸ fv³Gß,ç;3éNI²1’ò ¥=‰OxçT¦–zÉÎgò“ õ4è"Ý©O}Âr¡%è5ÿɤ€ ”•µh>JJ„ª1£åhFªQy~T¤Šüè7׈ы^¢ØäKaS™Î”¦5µéM5œî”§=õ)N©±R–nT£E5ªI=zTR"µ¨(5)Sí‰R¡Z´¥™êU±šUpVµþlZõêWÉÕ嵜Rmj>SzÖ³š•­IUëRÍJVqŠõ •ë]ñš×°ú³gzõkAéZ›¿N³­Jmda¡êVÄ*¶£ƒ…f`»`WÇN–²å«Ó*›YÂ^6š%æbËØÆ‚–´nõl0!«ŸÓ®–µÕLmçZ¾ö{²­iãŠV•6¡!Uko9*YÛ~’¶Wîp‘›\MW…Êun'™«Àç–uºüŒ®Ž[ÝJ¦•’ô„dv/¹PðjwžœíªP¹‹ÌôÖ•â…+IõzÝ‘w«ô}§|½iß[†–½£ý.0Ç«ßÚWmSÍm ëÈCw·ÛÅ*~Õ'` 'ÂþNX°„ÙzÒ“ª”¤L©Q—ŠÑàfØ·Æd…¡g`j8®Nñ‹GÒ¯¸ÄQ1\¯Šâʘ˜Ç­ÕqAz^þ¶øÅkqb›úÔ·š6ÈæŒšŠAüV'UÆHvqp‡ì_‡öÂ[%°/ºÜd1£÷ËÚ³zcÜâ´.¶´¿í†ÏÜÏ'£¾kF+œÛÚfÐâ8ÁïÝm˜©ùãQ:Î…¾o™#kè°òVË[6²›!ÝfEçÑ’S±o‰Üß<‹VϸE°¦\iëý”Ô¥6õ©Qê=Šº%“5¤£\XFGšÓüU´ iå=GÕÓµ¦5¬Gúß(³”Õ‹qõ±s\l*š¼˜þ¶ó°;üç7;ZÍXF6®Iå$ã9¬5vtˆ}íçoÔÅ &6kîs·Iݱdv»åŒ´wƒuÞ¶ÅöEàïCßAߣ¬w¿ªìÕ ÷ß²½wžð@ » wøfçüðø2|¾·8j)žß‹oÀ/ÇïzðÏ€œä¯ùOJžòöz}*÷êɨíy®×Ü t¯­]în–7¡à9ß8ÌÿçóP£µí=hŸkînÝ ]–@瑱u©Oê0Ý9õªžu­oW7Å…7\n>s¾›”ªS3í)ߤJÞ6µ™®s~ÇîÝõúïê¾ne(TØl?pÚqn×+7ÚÊJµþv†CüwÑæ]”No ã!?àˆGžŽGâaËNv{wìw®‚Ënï²Ù×»æö°)¿Ü»¡ç©o·ågæúʯž„Dý¢¥ýêqßž÷pG:éÝiXË^õs'~Üa²ã“3ùTļǽ{Yãs½4ÿu¬{üÒ/~ùá¥}Zßý[ßqâgóÃ!l/=Ížóqîû%Û>Ájö=p=zó—×øûO9ú ÆÿŽè|L½¬ÿ¨JÿºMÿíæPÏŒü^g¹æ©½0þðÝxí¹ð:b+ü Ðì$劮•àðÔï¶è/÷jòlÎ×o¿>Ìè8pcŽ-®þÕƒ“ÂŽþÖ¬ÃÄÈMËÔÆ0ïÈÀ íä)mΔŒÅ¶ÌÙ¦ŒÏ’ðÓì,±Úoø@ÌÙþì?Ð/™Ð¾tCRðÛªûfï*P ½mÓÚ.Òž0Ë´ ËÐYˆÊÚ¨ É8lÏR°·VLûп$M¹îð&ÆðáѲðÎ ÿñ¨È.óô/½žÍÏhMø¦ïôÄ0ç±UïÙ6ð0°þî/Ü JøœëÃ(Žýeeq Ímúf®ÛÖÓ­Ö4qûæÏÁpk|±™LðPPO½TуQF\Qá`Qq¹¬³/±Q÷®ØN¹o £±NˆQþsËMѤ|q›ñòžàÂ1ÎpÚ¶á¬ópïèÐNÖ–îQôRêŸ1‰(²×è) £-IñóíÓ¸¬Æ¼ÐÇÚÑGÞ+’[«/Ròä­˜8’ÆBr#3ÒùÐk»¬/ÍNyðÄxp"+ž`ò˜’-®#…©&Õ䩸®'gR³t’r’óq÷J’c0ž@’)…ì³,à'_¯$†*g)(‡ã%ÕÜÆ‰«+/Qìòo}0ñ„·ØÎ ßN{ï •?ìÒÃ$Ñq1¡.‘Ê.ûñ/¥’ݰ2ß´R— Sî(g—þìô¾“®¥¬ÈÎ kÙRqïðp2kñ8Ó 7P½ò?3Cs4Gs=Ê*i`$ó ]06ïÉ5=0©0ØÈÍ!!‘.}³1øÆ1IÌ3Qñ8Oñ‘I“ú˜ "Ñ‘7Ÿ‰Ð6w6Óí0Ç6]Q;ß@ìúñõ2Ó¾‹úVs2µq‡S3Ÿ8Ý:׳!—Ð4m->©s 9Ì:Í;¯­ÒÒiäø³ñô3¦³@i‘É7­o×b<íóúÚ9ýp)‡Qô²>#A+=å³5§2@ã,°&ª¹@ÔæóqóÊÑ«-ðéBã2÷îÒ õp.þ½ò<›“Qoï¯ÎÒýòò>o´ô¡f’ó(ôžXr%Ÿr¹~2KÃëL?‹³¢t ìKS²SLËÔݼ0À¼Ó ¸“ºr̘Ä;G2OOd(‘ÒR%ý-2,L-iO:Ûp˜„+¡.ë?¿ŽPõ½-E³RQS7°%sï¦ôÌõc¸R=y,ep.Çò,×î-K* 5/HÏÔl´+o5éÔÎí&qíúrHusH!µW“Ða,X‹¥ü©M-Íì*óF•5iŒ9%SWSIg¬-ïÆDQþ«LZÅ“8Õ³ÙªJ[±TÅìTC„1Wô9;”Q_í1)[O±0G‘5ë³ðæ4ýõZé5É4þœ“`S³AÏÓH=ÔYÇ]#^ï“ ja§0Zgõ2ï53´%S576‡Ïü•Y P]{Œ]«Â@ýRE‘\7}s,¿õÑÖ÷1C'BásC—s9=Ó8¡Íg/hÒ'‘6i•vi™öŽX67]V:wSA+ñH߯´ÔhÔßÓRò£]ýÀQQV®Tf1ôF¶`‘NVÃÓ,m1=KvC'TdMsg14:a4GÙÖ»‘÷6?9ÃR»!mv¹þ±žÌ3åO_ËUo×EñS9_”kƒOl3¡lƒìlKâikqãÖs+ÑBÓsrtaû6o…63o6náou—7íš•pMt£o<— s×tév\Ùr“qxù±0W747e“W9•qôÈõy7ojq!gXG±,sSú×VŠUå0ÍðRzwÕþO|/“|Í}¥¬Rmߨ÷£—fOз-h7UÊŽ×ý¤Oê·Ú¶h-qb‘ROvyŒsça#±*µÔ–Õ¼â@íms#0jRã”(—R²ÈÖ0›7n²OÑTé0µ– ´‚ð„'ŒæتþJ0S‹’W·4)+6õbXExsËÌa?®‡·k„óì¢õey´UÛ’ íµ|Õds/möo‡_Fˆy,µXØ"±ØÉs~#vþâR?á0cñ5dS·45Cx̬1ºø…‰x'ç˜ÿ¾ø7?f§y÷’Å2x­õó×µŽE‘ïx¥â˜FÙ9ÑØ¸’×¶tJmcWwm– qùCY¿&ùE"YOY pWx×<¡¯ï¶1tO—>IòV9 J™ G1wÙ#IŒm¯~ï±h=Õu÷ÒrµW-kô÷<-•™·K™$g³”sÙ¸®tš3˜þ0NЃ«·rý¤QÍ96Éy  Ùš´¹¹Y‚iÐPmžqX–)/±Ä){Y%Ú™¥Y½ÄrURT]µ˜aÕµÕW[ÖÈVÓU﹟—‰ý¨L}ë™ñ™<þ™Â$š ¶%vrå ÑóqË2aÑRŒÓ¸ïÜ8¢Pnß³#3Zã6ÚÞ:zP©6w­hôÂW!T8 g1A#o¦5dS·7Cò¦Å¢¦ ΩÛÕ’×™K:™ß–{4=y7së©/D7š¤eZªßªYK¬§js¯qЧí9tCño»:‡¯:ïÄúKp•® ù÷º ÔÚàÐþm…9 ýÒ~%wLÍwq±H—z Y·ÈŽº°‰<[:±ùYƒ(-»]øŸNDû³eØ‘Qò›‘²†Å™¡rдyø‚¡z´„'a +i›õRXLÕïPC2”£…×y⺳++·d¸Å¹Á/U¡Š ßV)Ÿ;í$;[a•¡Ýº2ºw}Tw!º?‹Û¸'‹¹D¹»¼‡€bç•V7BÍ14 Ê,3áÛk+–cš_ÛÖÐØZ¼eó#Û½IP±— Ù«ot­fx¨¼ õ×1AÙSᶯؿ×ÚÂ…¤´‰N“?•“ÛÃaZC;™x÷UB‡wÂ/:‹5| þ0<빑Ü>Z¹IÜ(œ ýš–ïoQ|½GüQ}8¼_œ¸\›gü>±»·˜©ø˜aTV•ZI¼™½—C±±À¹Ñ¼C®Å‘¤ÈO+ÉëƒËOÌïË¥Ózƒ½Ùoy›µ#Õµ%ÎÌE)‘ÙB•îèœ Ðü¡tØË6åTSßšŒMŽÂãüÐ…|È\œC¼àȼºö\#Áœ²úZš8Å× ™¡…U¡¯›VR» 6WWPËøÉÇ/âXõU³›B™\«ÐY¹ÒÇ›ÖuY˜ýŽÄë0ÏÏ8_Q¿åð¾¯×–o¿ mÒ!ÅÆôÄ Ú]ŽÙËÅÖo½þÿrÜ•{ÚÀÿxA­ÖÀ…r‰úÎï¶f¿:¯WýÈ{sÊ{Ý-ÙS”9ÛÚ»|îDÜ A\QëÝ^ó:Ükù¯y–cU|ÑY|ò~xUrný}Úq›åý¯.Àuz²û5–Ï}dz¯ßa÷nS<È#ý«¨R€œÝWwÿ]è>+Þáž–œŠµEwÔÑ­÷u÷×}MÏÊ®;ÞãWžD0{·=m?U"{žã=å}žÈ-=Í+;Æõ™6Oþ:Q»»:xµ?ÍÔ.›ŽŽ™Þ±Ž~ÅKnê·Ï”ìd·_°·çY…)›1µ %UìÁþç£Hé í=…ÃóX&3½Óåþ^º—X`O¤ù2-×JÕƒ-èÓF½]ÊKýÀmúëñÞÀìDÂþéû~žwcó½3Û¤ ¯d…=Èÿ°Ó¬û}<Ù;Ì/Ÿ*߯ô^:2—_?jü@ÜÉ_Vf¯¯±åÛÄ ¹xuô®n%˜óÝÆ%þÎû'ãmÙúó¼.ßu9ž£)ÿù©*úù:ÀÑ_°sÚ•×Ú(QÇgùâ{¼û‹?Le—×¾ö¹ÔùÍ_« ¦.·?ŒrÒj/Îzóî?BPš'šª+Ûº/Ë3]Û·lˆ;ßû)D Á¡ÀXT––GRØœR£É¢ þ›ÌjŸÛ&³K=!ËF®7‹&1Çí«š\U[qö;^xøñ3õ<` à a¡á!b Nc£ã#d¤ä$ã_â%f¦¦á"¥çg…åæ(©éWÜ©êi'h£èêË[‹Ò,m*TmMÔíÝo¬°žk±ñ1r²rOðÊ,N3‹ï05ëÞ2öctõà6w¯Ü·¸`k6ˆ74ùQj:ø”èûëú¸i¹ù>¿ÿ¿†43Þ §BBú2¼ð.!Ĉ'kÐ=6õÀ1hc•ŒãxD¥Ñ 6^ÞõÙ:Щˆíz,³Jâš+´ÑjÚ,µÈJ :#•‡Ôjv´Ä­`tˆ«§euí$†Kìé5“;äºØfÕ¶ÉݲòÚ{ܳ×þê»oõÞ›]¾üReŒRº˜ ¯~M¦Ô^Â>XÏŽù'E_áHŒ›Âvù{aÀÿlü/È]u,0É%Kðqȉ&kò¾öáœà–9%R1>—eSB&˜.v VùÏýõ˜²U¢L4Ò Ì2ÓL´xMó°-NÀ~x¢3"ÚÌ£n:«!Å ‚½Ÿ±>ýÝÒüœ 5Ûä-5Üú®Ý¶v+Ç=ði/‹™¦Ææy(£šÛù5o­"ßBNwvc57ã‘kòöÝ•Ë ¹ä¬:nùó&t7×weßy®1˜{F ß_¦\—d÷yh”gC{æ¹+´9ç½Ë­{©¶;])îþ0Œ < Â/Sü@|úÝ_ò¾Û:©ÈCÁ»ïÙçê™§ªxwü½Ê›Ì|±=µj½aFO®Nu§'\¤¸Y/U>ù_‰¯=þêºw:¸Äà|ÿBv?’Õ}œWs²õ­Ø¹„X ¼|$¬qUM.]Š _X³‘ ²k=|—Ì7Àü‘<°“‰™F7Á¥¤kas`ÅFÕPiØÃ_ ¨C2Ü(žãÒÉ”:`Eé` ãKJT—‹©)lÀAâ2ö#ö°„VÄÑ@G¸,ŒN“áØ"6(†¯Š¾Ëáw8 å­,šY{»š¹181£×f„³aÅçgø šô†FÅþ+Z7;]˜98-îlzµI‘ÍØ;4¦ñ€k,ÕægŸ« RKêŠÖPD¸QŽÍ:cœ˜ìWºA²•™š¢Å¶¶)blˆ=‹$AvÉßU²—ÜØ%(\æÆó N–u‚’Ù§ RNÍ”c¹JºÓ•ÖT›‰šXÌ7ÚIƒ¶Œ.½¤KIrŽ’¾D^5=ñÃ=A…]¢³Òn Æ×¹‡; ëÈä:9ir›kbå5ª#~ÆÎ,0 ‰4kcÏV0aî¢Ù¿ÒiÈsR´Päô˜«ÌI½ŠH Å"G#$Ñ퉬SÎKôä!Lj1¤<Ôñ¨r>—º`¤½)%4JÓ^þ\´rþB©ô@äȃ(4/¸8JM+iSlí´©¯ê)N£º:õP›ù3‚Dl¬¡p*ÆÐBP'<ÛäNJ¬1 5sKVUãÚ«Jµ®É ª\øÑuâgwjâ-æÂp®i‰·1l*ÛÒ="ñ‰Q4à[µ‘×É"‡®v½¬s([˜ÈJJ˜S"&[c6ÇÑz©7x|¦K‰V8š¶²Q¬õ8(ÍÒ–Å,n'×Ú6.ª™Ü ÿ+TMqÛ|3GTM#†â„ìm»ÃÛév4·Öõ!ue]–y¶fÄT¦ˆþVÄÅIs‘¨}ær9y¸\B¦Ù}oo¯+ßÎÀþw"²…_âÙÖ†ð}¬S =ï4Ä9Ù2¸'Ô ^NàÝ·»­oð¶;ß ‹àÁ¼m0œ,Ü iXeî5O½<¤”+ý_KáGâãÄÕÀ0…cœ€‡tÏ™þFŠ,á’u8z®(Œ}ðSö•xtœ**s€ÔQD|A²Ûv,ã)c`ÁèÙ_Ž;µáöâ´ÇfRÔ‹vðÀÞ*«Ã¥P±Ú“¬ç2+‚Y”Ib´}ç¸Âv~k2³2)ÂLeù¦¸ >ìžÍlA¿BEÍ ¶¤”æå/;+ÒlLr_ —E#ÛØˆ+ô3bé&ÞÒ Íd3*U›V‰ÁSþ5õÚ‹-=èYwÎGly„jG~šŒºtŽ&MiË:³eÉçÊ,ÚghgåoÃ΋:UßšJ-,,£©T62:öÊË„µ†ŠMëqÏXuˆDaÑë+p£SÜÒö°9ænu·ÞoîÕZܰ’W”éN.é¸fJä²¶ýçxmÜX“»á’nt,í0¶GÝíöm¼k ì ×ñ„Þn¤Þ:Ž^Jà¯öñþ¸@*¶Û -9µ­áð™;8›¥û·Ê×mqc<ãšÝx¿ŒêjƒÞñµ˜þ´=ùžçˆrf®öYÍ d{W½7ÿ7ýèœiŽæ^óÖe"ÁÕm}¡þLÏñCéxñ.ûüçóÎiFì_; Ž]ÿ:ÞÏÑöoB¾…‹Ûúä¼8(Ëî»®‚G¤™n9X!æûÛóNè½ÿ2ò³2QC•o,÷ Êýü¼Ejy¦Rž²ˆ—|+C_ÕÓ(«^• Wá!™,î™Í%qs[‚ൖ™ó!e=T_z|õ˜~SO/¡kSÓ çk¸hi‡)qÔB ‘¿Óï3§»§¡íÎl>™ \7yرïÚ? Þ¥ä¯r÷ózðgOü4Ý¿ ”½}WyÖ×ʽÎí±›þßÃåßêA ÿõœÊÛžYþ,©]³Ü5ÝþÇnßò] ÷Q`Þ”ÿÙŸ âóyÑ­êpË-“Z!]?ÝÙ¥šM]œ= ÷¡ Gà úæÃ J ²E4!x!Þ¨ÊãÙá=á%ÕÜùr°ØÿÔ˜È,á^÷€9á™m!5‰á›@¡,È|Iá`žY«()]VŠ©¡ºœWÈá6  5Z˜lÔ6Ïe` FÙV-™ìqËWí îy—\Íü°Õ'-”Ye] “s™âÉEÍ ®¢it ÝÞ0iËWÕž>¥A­ 6b>"ؽè8ß·Å`4I_´-þÚaY¾MOöA‘ªåš>yŽ~A †!+²¢ÖÍ¿)×e WP\ý% *‹.:¢{­ÌÐ`¢ÚeÝ,2Ö)©œûñ‘X¹:ÆK)âÒ‰ ¯Qc5â!aÌ‘—Vœr-b.Žã9…ã Õ$àæ1¤)à‹Œà@úÌsÑz…M§éàÂyX?ŽaNÒ—´9SEFŽBrB&$/NMÇQÀ…¤9N( E>W>FæäyŽyuäfµäGjOH®<–¤Îä¯ %H­d/¥¤ä×'Æb;Ú`j›é$;•>1ã†=TNe]£Ñᣪ0åPN Z*þ)›€Å%Úåà:º•ZúS>å]&žâ=ávÞ«X!h@åZNT^Ë^ÈߙԈæšš!®XÀÕTdb`õ¥_ ÝÅzda‚ŸRav¦æÖ²$ÚÑi™½Õ~#àOiŽÅaúRm†æ+Ýæ!ä&v™VÁ%ÞØìI(ÙõEjÚ!¾Þç}bïéž) Ø**–š!oÆVbê&!vg‘|ç"S‘*ñš4æc1–Kõ‘Ú˜Át Â#Å­Ú3U4"#{ ƒoš†xêЂg†è\YàhÁd‚¥ßp$(ûñ }Ü$ý­h‰„¶`›þ¦ÑcFäU£Rú'y¶ŒB¢Þh²dÏቊ~\M†b½%OÂ_Î5d-º{í¤öåaÂyhZwލä h‰ɉâfˆf¦žãõ ÕL&\*ÒÄM#ʥ،â(N¢¥ôÁà ââz]‘ê%‚ªæT~Ö³¡O*]âàrŠdÎÓ&Áe²ZÙMçи³=ßYúÞä©t©w~)Þ…©Rùérª0Ì_âØ‘^”ý¨„ì¡£U‡JƒÏeÆÓ ê×јá5gBõ¡ñ8&ŸVÚ˜ÞÊâùaõæg>*—&QÙ!ô5^á©êFª¢b„¡rªa¶ØsÒ¤¦Žþ*p²Ï±)}ª]Bª¥§%çàaгaâ‚h¢¹äÞšÝ[šagXÚbšÙ‹±òªb*ĈD™ê]Ô“…¦ãqÖâ Õ ³„«?ä*²r®Z€Tššp˜ekî«z:ãp뽊k¬ðë[8Öô(¿,…Ö}6мö½Öëî”ã1—itÚ™³µc„Fiü½_‡ä¾jhŒÊ¦ l¬Ã–Ÿ¹i¥ÄÞéE^"PjdOÃ>‰Ç¢dÐÎ!D®V2*£ÖDd‹ž–ŒžZ<ýä̆–jŸÐlÍ*GQFÜ; ¤8éì‡äÏjlÑ¢ÊДÍ&©Èþ‚—߄܆r࿪lÊÞ*ze¨Æ¬ÕÞJÙfmÚ\ÅQÝö•׆mDŽ-¡`­9tìÙ&ÏÞ.$¦ígÕUå^åH®©º–Ü—üÍ@l<š©Cê(µ .ß2F[ÞY~^c›~=¦®æ‰å¶ê’ˆ®t-.Û ¨â.ªù°Öï5î蛟äŸì.OIYæIëckÞ^V&d Ÿíj¦ýïîöÍíHðÒÊúdÞñNno‚òÊlz„ÞóÒî¦R/•]¯—z”ëI†pq¾™-¶ëÝ^µrb¹xâºTI(Ú©V}6^¨Ÿ}k!ÚïF%ú¦¯úÊX-<0G°O0þW°_0g°o0w°°$0Q䫞 'Åùä`=ÒµZl®uÑÁ5 2áäÁB4ž«7j§ùˆ0°ïCƒ7ð€ €1±1'±/17±?1G±O1G1‚6é½,ʪ­“Þl‰H¨+ãü…±ˆÜ=’ Vj)h¦mƒã1ÇñŸ¶îŠbDº¨Â¨¿É­”æÇØXéÁaiܪqP*kWKöʱ"7°ù)(Ü2iÈv1sõ›„R[•R-Þ‚¯æ>í`¾q¹2Ò$ò"2ßæ+àFî;ÍêÄê!Gš›fcÁ-èù‘+É 2)zh›¯'((§þŒ(“20óêõR•“qád:ªýì2ü¤z ¥¦¦¥f*¯ðð–³5_óãh,r&© ì¢2ŸfçÉj¢« G¢ü–óRb3;·sCPs/×T8£³sÚQìͯ=Óžýê«{*'ºÄLÌR­«þ ¨2»3B *<ÇsѼ*™ê« ÃVš¾Æ2 ÁíZ&[ΠZÌåÎ/'4H¯àB3ôõ€¬xeqh¡£ƒ¶Kvbe1–`çʧ,kÛ<º£A‡4Nç4½‘´¼œ¯Š6ç#?$7WÆh%ËðÚNóü®G´N?õ*Ž4O¿Ô«b1õK>(IŽ¥Ë– ~n”WsT5YsÜTþ‡îA]JÏé·ª‘S—5_çTŸu¤µ¥Œæ_?U_6b‡Âð6ïru³Í=ÏÚ*i ¶6ËŠ&6fg¶m¦1{›*gè)ohká:;4`3¬f§vf¿oZ5k:;aqÖï óó¥«\Ò0–$J¸â'«iŸvFíµj÷u‘ðy.iz^,nI{bt ûë gkQ×d°/S6pÛÊG7w[S#o J“¬ÿÖeû¹ã CR<:óbEl=^YQ20g·v ww×wŠ.-ÒÖ²ü¸¨O$.õp­»bµo#©|Ï·}'8H·’&­éœ4þÞê7'3u@ÿ•Õé)ù–‘!8˜Ñ·‚¸+™²7¹S[—3ØZîm—7,ïÞÈz Û†e4)vs8Ù‚¸[ó0Û×á͸}5³ôv¶K¦Ïm÷¹ÔÜ®N¶„ð8v&9÷+h“ ³Byòy¸‘_9[Òxÿ¶k¯k¿&lù»Ö?á/àRs~AϲéY9–¿9Viù–¸/¶®aø_F´ “9 —+tgì2F÷Â9¡—²œ.e[5^§cÉ6ºy±Ó´M;ÑÊZ÷.:¦‹«’ó´OãwR8.#àQ º#õ gºª馓ôùz x/i¾aqÌ5G–:þ²®:¯ëf«3ô«×¹”°õÊæ9–Ì"m¥qu¥âõY™`¯GûGþz<{eëø{¹´o»|6òš˜Rz“l¸ec{vi;·§;s³e «P»¸ç“Çûâ¹¹ºßû@.,î 4ÝL¢Ñ»<“»À£½ã;ÂëO«ˆ…׺6¼m<Ä×ÈÁ'¼Åk­¿ËÌÒè6zÓÄË»Äüg ûÅ—üo.<ŠŠÃ#­ÈëÕ¡¶|½›¼ÌWoÆëd[ý-ËÃ|Is¹ÎßÌÿ¼¯5ëò¶jî—çfx¼[{Ï<Ð7ý|ÕµkܼG*è©7÷²hÖTa1_Å;½×sì8|óÒþWĺ ‘uãCO&–5»ß|û~=ÜäØû<σ{=7Д÷!´òì¾÷¶™ûsŠw¯µ*û¨ZB ÉǽâëÖÜ ›ç¹Ì G­äWtÀrÑr¯|Û’ùÕ î1&oOwýâ¾±5~í$z$£´œ6(­oîñ“ñ¤®÷éî­·}(‹>éï>ã›þé+¼§O)W/+zFâú>8{ø-ï?ÿE=(»¢y'Á:ä_?”Nxò¢…+ó£-ôÿùþïÿ6ÁŒxÑõ7¿5²§ñ@C¨- š‹z,»1ùïù›ÿÈO=ÈÇÔåö‡0DZ-šWoÞýƒþ KóDSue[÷…cy¦kûÆs}ç{ÿ…CbÑxDö2–@3ãœ8Í)ÈzÅfµ[nW+J†UKoùkÎ’ÑkvûÇåszÝ~Ççõ{~ßoWk|Â0X"< r[dlt| ù „´¼ÄÌÔì‚›ôü %-5=E•9TP”J„E4¤mݼÅÍÕ”LUÝ.ëô=FNV^fnv~¶A”®mu­%›&ÞæîŽ„N©ô'/ß4OW_gow׆¢¶­¶>,¬7çïFO·Ïß@‚=„—PáB† >Ä!¯Š½lõ,ê£gPãÆE¡ äRdAMžD™RþåJPó]¼8KfÆ‘5mìµäMž=w•dTèP¢E²X•TÖ«yø ©aåSêÔ@›í¤šU+«G½~V,3¨[Ížå”S]%¬ ÚZ{Ií\r]ÇÞÅ›WïÞ$O¢Ò˜‚]el;üuKím\Á!æYòdÊ•,vœy.dd«ãËæ´l\¿Ná&Š‚Xój3œ-¿†[6D̬mKuíkF}Q°ývP‘·K¹·cÉ=[ùræÍu‡¾Ym@z.Kk”OSÆÑ½žî\üxòå'ÕþžÞ_rT»­gÜ]U;ðÑÅÕßÞü~þýýA?¹aï÷èN þC´Ìï? '¤°Â„0Ã\ 4Å3‹X‘ ÄAª Í´WNƒIÃ9´°E_Œ Cg¼„ERdlF#„±G´,À¨DãnG#9°q9YòHè’2J)§„§-á<ŒO5'·¬J¿gšä2Ì/¼¤²L3Ϭ5,¯Y*AÞÄ„32¯Š³ÎÇæD3O=÷<æ½çóí7íäÊPÀ$4ÑÁðä³QGíc;6c¢%Ð+ ÓЖ0å´F!5TQ ŽAO»´Ó#5ýQU_måÓQg¥µÖh¤ÈÔIß„uFV=qµWNµµXcUê)ÓPüó¿„Õ‘Ø?‚…6QþiÅ6[*ë«¶[ díLƒyœn½ðZm×e×ÅÒÐ…×<(l0l6´xÓ·]ÿ•’Ú}W%³‰e’EuÈ\yÅn`ïÔ8b‰™Øáhõ3˜¬³T×á,þâ‰G&™²ŠAV Œé®ÈêÌ]¶a”o¹d›oëä™!D‡Þ<¦4טÝyµšqF:é¡t.šßVþèeƒíÔ¦Y;Zi­·¦íjaÁ€úge;Ɔ))L„Ši¯ Êšk·ßvGíµ†¢n»ïÆ;o½÷æ»o¿ÿzqÕJ¾^ógoÞù ¡_Ÿv°fbµ²?¶eê—ŸºßO„Cÿd¶> „çu# ¡äç>“%p ô ýLT ÿmt¦ÂŸŸ‚CÁS йÓ¿‚ ŒQ =5=]ͧ…´à'Cüo†¥Ra—"Âçä0SíCaHˆœÒ‰ÃUFtÖqB£HÐ…ùÚX 'rÃ(ò*;Í¢¡»Õ¶Ç‡? â¶êþ’ o ú»b]€8´ÍjØ9ýܘ 8‚/Eå£#U—C&ŠA‹_ÌJÃx—?~{n$,@ó=E¦¦l3´ŸýP× A.íQô ùµ5–BH¼Îèy“J2,›<Œ1è½ü52ƒŽ ßÐêWŽREg“,Æ™„Ê^ÕÒVz¢Í5J­øÒ”Gáåˆ3.‰T°†.+$ÇaL•$“˜!¡ææŠ]=k–Ö¼¦²yLKNW£™†3´)šcœ'g8 òNJTQ–¾y—åYz’s%ñ¬À2Û‰EuV‘Oœf'm·O õÓ’’#ù¾ÉPž8ÔŸ(¨½ÞÄþ;qðCUÛèÙzg63â É(EÝ©P%ImaÞL•JGrÒ‹vÍ,)U# eê´và0¦0EèN7BÓš:§m8jBu*Tõ5Ûìh$uER¦b“¥E]hUµT­FÇ© ^WivU¬¾&©ûjšbײ!²wd .Ey$F3gMOZoµV±ÚF¯e[_ß@ÖÊÀ1!-cƒ‡F¹jƒ¿“Ý_i€WÁêB²€ÕIey¡SÎäJ’©ö É¿íás˜•rdo@:Ò¶žö£dk%¼.û Í>‰°˜•Œçt»[ÞJî¶“qâF©ÛsµIެt,,é£\˜xÐ…ÕŽc·øÛþóÔÖ¶¸¥eeKÝBQµø2íGëZGa2‹çæÕÇôN7°Ö5Îl±5øJÏBÁ ßrÖÁÄ6ÓžÿÕç@×iP÷ö´¾c¯„´‹.ù¿2lS ÜßÞ×¼›°…ùë;X5øBö+wœ3Ë‹³ 0Šó%ÒçZMªT$- É%]ø´öŰmÊ\™÷ÞgÆÃ#aL_,8zCFJ]tI.ù±É†í“ã…d §ÂÈ~^{»e.çÍ[TRÓPi¾µuff †®ÌOWù+wUlTwº%/¨¤l³^ÖÜãæyèŠÌæ!á©‘Žm+õ…ÚþÆ.Dû;´÷Ê·g«ºy?ˆÂtXÅ%ECšÐÏx¡4ŸWhà ”´±Ü°¦M]aäþ‰ Û ª¼°F¿z¿v³¥oÄhnVH‹t4¾"-Q²ÉÌ­‚Ž2Zr­>QÓeÙ'ÀãAÉÞ‰(mlikµßÝjWøÉ0Æ¡?­k¡<ËÖÏee„ iðµZÂ¥v7†·òìp5ÛÙãÆƒ7]Kkt&vß1.­·aÈmî¸g¹É³Ìò~&¸P†$Á78`eã[,¡¶÷-ëuœýÆb²åªAƒÀ¥2Ý*n­+£'‡¹›RNИÿïžæjÆçÝr:Þî±v·W7óïþ-ªÞEö3Yœ¿˜¡¸³ÃøPyîr›J\ …ð )Nº­ßtêÈÔyÅy|–¨£YÜTwÃÏ-Á¥—ëèk}ð¡ýÖE‹ç÷#[ÃGâÙµïv.uÒ@c+ìd\¼”sJj²¯§Îb¢7Ú#µD®d’`œÕ:ƒ8Zè;?¶óˆ?Ȧuýà þë¿Ã?/ò¾Ò:¼ܰÙ‡$£²¹D¿l¿ ›ÿº9 £¥ ì Ä>Ì*û@9¬«»µœ5l2´!£CÀ„ÀsʰœAy#D‚ ÄAe’B„¼B–>¥›ÔI®&ü>1t)á²»æúÁb[,©b2Â+¹àK:¤‹*ò"Ië¸'G”€†tȇ„Ȉ”ȉ¤ÈŠ´È‹ÄÈŒÔÈäÈŽôÈÉÉ‘$I‡üÄ7ò¨'$À””8Ï39w$xŒGqT<™3¶Ì½è2Câz¾xc.®S%\»$|­ÞÈ¢…œIÉ{¸,¨™{Iþ z¬¨<Å’É¥ühs4t¤6‡C˜¼sA˸ <æ;:D>¶:A–<9¥ÄJ—kʃ»9¨ô(è:Bœ„ÂwtË·l)f8v#C·„7 ¹±TI `"K¬KÿÙK¾´´6‚;œÜÊCÊȉ²qŒD½„̼ÐJ¤°9ÕB&\LÔ”‹\¹¬K{zÌϲi'±¼$•ºJÙ«œdGiƒ¦] Eú£ˆ#GƒÊ±Ó7WóJ¥ºŸÒ£äŠMÝœ¯[RFCªÎ+èLÏ”ÎSj¼™‚èÜNÌÂÅ\¬Å𜟛¢›AOóĪñ$ÏÁbÏºÄø¤ÏpÏ÷ܬú$þŠû„“ÜÔOváOü¼—õüÏ8P0*Ð…6í ÿTP8ÐB!Ðe eÐX¡ÐjšÏ -P ePåÐüóÀ Ñ·é´ú+ÌG´+<"S䫸bL³šÌÕ’µÑo(Q›ÒÂÕOᬣ/¼±¹»Ëh\ÍÛ„C×ü6i¼$ÃKÂs<žÖ!Q }(¿<Q+…Ö<ÊäÓ<0å[1E2Óºƒ¥é‹ÁG -CKK¤|>Fâ55 ¾’#SçK´ðб4eÓªÔE.eˆÅ0uŒ-ÔFñÒ`4-ÏZR+:¸tr%X+Ê Àñ25øëÉù›Tö+ÂK5Sb#HýÚÔñþãÑCMvÄž‚$U2TSÕü : ¯qüÂIS <Ìz„ÁMÈ["«SC̶å4Ì–<>×sÕSÝ!]Õø©Òd%™“ÒE}¤ö*´$ÌxKÍk@'DCsÜÖp«lÝU`%ÁR…Vv J±ÌKóiÕt-fM1Ü#U’ Ì\-Cç²WnuBsU/ÕTMsmW$yVx¥-z ªzWƒ ˜¼cT1åÊq%¾_SAâüÒÔ;i[Ã6,?‹%4ŒuÃe¦ŽeË‹E¯s†Í¬ßÎFeÕ‚UÙvA%%RW|Æ"£$˜Ù$c–÷Ã1BmŒ…ÝÙ‘½o4Ú£EÚÈIÙ¡íÃþúZ¦ µ‰§ýÏ¢U>ÒY¨5 }Oª Ò ÕZ,äZòôÚú[)Û°ý³ÍôO¶M™¬U[Z[t[ö¬Û ¹Û¹5¼Õ¿½ O¿]¹å[QÜÖÜí<\ž*Üì;Qß$S­Àì´ÍB¼GÄ£Üd»Q›D˽—%Áσ¬œÄN ÛÅÅÄmÜÝICáŠ(Pµ3P”ÒIX&EÒ¡{ÒØ…«Ù-k4]­…3ûX’kì°ß]]DÅË0•¹O­ÌºSDÛG9%H:­¿Óæƒ^åDÓX£^G½ÞÔGíu->uSûÛÀãÁ¾C£¿L<,C_¸L^å\Þ€ëÖoþ Hå5Q¿,™CÛe5pÍß–iGÂüWÅ­L•ÔýõÓò|_@ÜSìíSï­K´A] l`ªƒÕ¤`;y5¢a/\5VàW¸ËG>²LËÿñ` þÕm}S»`OZÖaå­aUQÝ6«Ì[ÓùÅ!ôÖlÅWBú}]ØfÍSCâp]à?ÕáC¡ ÑjÍq­ââb]ãàê})N ËnL'æVK}¦{Mb˜Ü×TsÀ–„á,Þ”:}ÍsýT©„–vãÜrXåÝL"½Ö‰] kÃÕêßšÔ®TÑP:?-R:4Òo-ºD.Ù=Ù:,Ý;nJãu;`"®cãµd þ)$šÒ¥]œµCOÚäMCf_ÍÜSÍí%Tþd¢Õ²¤µå[Æå¾¡ÒYž–öÕN^Æ­ ¶7;þÌá 'bf“Z6Kf>æ¼’åfβež©hVÙgk–f£æjÞæ<Àæ‡Ñæo¢n dæËpöªq&çK3çJkç:PçëŠgšç­ç9¸çøbç|Ç ¶^hóõ8åÜÐS¼ÌËÍ…ÑÎÝ%‘­QÒ-¼~†Ö}F06¥-–_žÔ=l”]'e—]5téÒú]Q‚öå¥ÕhK<Œë$el¤F_±è—VŽDe^wËS?vS*޾3_î`;cDÊÇþW^¤í•¾¢VÑå‚`8]b~ŒÔî=t~ËíTë<È»iœ– ŽS×mTY“ßøûÉþQàæä¬CÉMÞGŸà&ô_§àPàQ…ÉókR 61 ÃSCÕÌ@–éÔýê¾Þaï‹Õ6lk}]a_-V>ÖÃn8¶K„Èf×ÁvácMƒÄ>Ô¦„Ó§£Ö¹†¸9ÂÁjÅ®:þêáÎ$} ârcYkArã!¦c®ScÜöm%ækØÖ&b}SÔV´"¾Ö+vmÒ6n<6Ûìí Lã€Íí]Ýê–ÅîáFcã4ãìN‹è–ÇÂlYHÕÖ†kõF[è&ï½è`tþäädºÙFdŽRäWfNä²¶6}düŽäE~N=õïû&YpB¦äŠ~oš4ïÖ-cæfmNv’×npe}Q.eÏíÝ¡ª¾ ¿R ´¼¯ ä7reñ™bŒmß«Íå‡ñ\ÞeW°¥ñ›Qqë²ð™Ìq£qï?Ïw–: ß׌'rp0òÊBòf\òBýñ$o"!r)¿'Ú(·òr¢r’ÐòÅrÁhò-?˜.Ÿ§/Ñ0¿;2—5ת1¯D7·=6oó<h=K&]…F/èΖè>h¬As•sé ó:Ÿî<Úâ·hAcéNKéNÒ‘¾8çCQè›þ½Ü'ö LOt\cÖãäòéæKjd[ê¡nêò5ÆŒjß#ðèóGÉEìP·ÏÑKLY¤éÔéjBÇõkͦmÂÆdšÃ_¼ž>Õöâ’~Ôàe×k­±`ÿ0{ àTêaFÄÂöôvûq`·vպƦ6Žþ\[ýlaM&amká!~á¦*ô ¥Uý‘vvC9çmVL•ã5/÷l‘ÖÐã‘íVÞvÁ3†÷À>bÐönj'÷³.Ùê¦9ám›ëº,§xmáhn]2æîx%¾n“gøu|Ýöë÷Œ6yÍŽŽó{ÿxµºÌŽÖc6¬ïo÷Á pýfäþ5iŽΡOº¢gyœЗŸ¥°üßn î%´yÏy[ åFÏC÷ݬ‡Ð8<d§knýŽC¿¼£¡^h(û­­å—{Þºõ··{Ã5s/ÏûÕÃû¾ïÒ½g§WP¯';Â|g0|™jy\üKüQy|Šj|þ›|<‹|½üõ@üýûÌߓ˟ÄίÚÏý<}yª|Ç5ýÓ?“øFwñ1=mÑ@ÇΆæÕ"ÂýNôCüÔÇ Òw}+yÍ{ùR<ÒÅÝ)ôÝ=é·÷ßéÚ þ–žüÕ~˜uW3B’¶… £i¯3]7VXh«Ï³ð]˶­™bKÚ P§7´x ªuË·¯ß¿€ƒÜõ9Ø`Ἠ#^ÌøÐÀ#û­¦-©-~#òÂê£çΗÐ4O²éÓ¨SÛ£R¶µë×°cËžM»¶íÛ¸sëÞÍ[4éß«N<¡bàÈ“#Þ[¼¹óçЕWN½ºõ류GßÎÝÏtìà÷ÑÞþ½¼ùó¿‹_Ͼ}còèãËO¢Þ½}÷ðçëßÏßýÿ˜R~ý¸_}&˜6èàƒ} ¨à„RÈ „>'a…¢ua† †(bvhâ‰Ø}8⊕ˆâ‹ï¨ÈâŒ4Bè"Œ8戗Œ5öHÔ:É>idw@ ©ä’Ãyä“ %Éä”5å•XF‡ÔL_”%RR]jƒ>.x™“0…©Gf@kŠ™Š/TŽge–t>$eœx0g|ö X/dÅT%õmcÕ™zí¤‚¡”!JÐK:é礱$9XT;ú&Wy–Fé§ ®5M ]CS'n‚ÙecacV˜™©Šþ¦[6eΩ\€ùKµ*Úé ’†*,†.:Æ]˜ºi ¤ÊþºF°ÃF+m¥¬’úA&—Õt&­a¥³ë7&ÜòÕ¶ž5ê­9•Ù—T9[æžÓÆë]SUñk¨‚q7ârµKVÌæ ­¼|Ǩ«bfȵ™VÛ.½¶vò\Ýxr™S)œÅ€zâî˜ð,ò“c™¶*’n]“˜ô1 ,óÌô9Ìp;€ÃeÆiî—:Ïõð/œá,NÐ:½ lÈ47-ÀÚLÒuQ¬´1;­õÖX$ @ÜT.Øcj—ÐeÚdt"(£=îÕ‹2ÍõÜ?À%‘™VS]ÚpÃþ,7Ý€Þ+Ûk‹ UTP}æN­ÚÜxÇë"«¸ÆØ6î3Xj{pY>²Ý„»-µÚ{'Ý·1{®ºÓ›wVëïNXê«sMY$'—[jÉcÎ))a&,;ȵï9k½%¯üòÌ7ïüó³ ÿ“ñÔÇ$ýÕW¯}–°_ï={Ùoj÷ß¾øèûH~ùìWw~ú~®ß~{ïÃo¿ˆòϯÿhõßÏýþxêŸÿØ üð€¢£e@ºO ŒàŠèÀ ‚ü-fðƒåÙ GØ$ ‚°O"$!c#Í‹­2€Úì§B[rEV†nš¾§8ÍfÏxk•ô4â>ã¶P,N) KÙ9:Pc•”Iéì¨J“ÑÃlÑ›Ù0‹Ïx¶(.ö’,Zi¾|Ìd–s£UZé“>ZG^õ"$ gNN:L¡:Õ-®PúÔ"ÝΖØÂÊé;¼e%.’{çU;•Òªš5B€žZ×ÊÖ¶ÞfªK;«#óU–U®x} \÷:Æ„æ•;—¬+ïú×ÂFA°|e¢_ «¡Äˆ°ŒìÓKYb@V²¢r«f7ËÙÎz¶,‹Å¬h逨ÊÚ5´£MÍVËÚÖºöµ°­lgþKÛÚÚö¶¸Í­nwËÛÞÞ6µÀe©i‡ë©à÷¸È Qi‰»¿Ë&÷¹Ð®˜KÝEJ÷ºØÍ.qZJ/¯¦  cbMÅ05V÷u¨Õ®z×ËÞg$ÕŽ€M)Ç´Eð6«2=ïIœÛÞþú÷¿Oè&|» RáÑ“—ÕJ$(»j¯lˆE¿ûM/€'Lá ö¨®’§Î¶Â¨Tv‹PÔE¸<¼F[VÂN±ŠW<©ùÔd}èûµ`Œ3qŒPÌâûØÂÝTîâÝžµÄõ¼qGt¬ÿøÉP^ï{É·k ´lQ«¨C™Œ_'GùË`N.w©±d‰f–…[\å©þK®J3r\¾`˜çLgG†Ë³uëÌç>yŸ ´ …©çìxÙψNôBó\hìZÑŽ´&Ýè—ñWҘδÿ(]iw]ZÓ 5õ8Ýé_}ZÔ¨NõÜH]j=Zհ޵êXÝjt¾ZÖ¸ÎuÓh]ë)Z×À6ŸÆüâÖ”­ÄŒøÎßèFG•‰ÐßÕó¯…Míj[ÕŠ¹ãå4Qûj41ÈFРØHÙi[ûÜèV.†ÉÜæÐÙÁí#¿nÖªXÁ;«“»÷íy8?bÓÜé¸Àû#`¥x¬À?ý¥¹@lJ`ŒXÊ‘—ÜNñÊàϸÆCèbBxlÞoæN=MþŒâø§ÑζĀW´}b|ã0ùvG÷nyÆÔÊöÚ8M~PrÒß„œ¸Ëo-ó¢IØÆ·ÍeÜí%gtÝJfÈüΖÿ›èGϺև3fSgˆ;d‚!_Š2¸bp~£±ïý¥RueÜb|ùÖçNw—öuîëõôêÎ÷¾Ѓ¼àíÊÝïˆO¼3x­w%^ñü+ßxÎa]ò˜Ïüâ+oÚÇkþó —å9#χþô¨Ÿ,ékúÔ»þõ-^=ë/ûÚÛž £—ý‰ZûÞ£žØLYSâ¾½S!’·IäÖ}xïûæk~Ê,çHE¸m^¸0¿Êç§ó·Ïýyþ…<oS°ØU¶G©Þ°2jw‰Ÿý½wÿýð¯CÁ7þ çXé §FˆU†Jˆ#»ýî8€M€LÁÇ86^#·rá ew´G€ø|4g8¨08÷}þ—d<ç2(8‚$(I§LYt‚p’2ó´s‚ÚW‚2(ƒ]‡.µ”l<¥/)§f¦bS_•99•{QÄ|3X„Ávw„ƒ+4FØ„Fx„…Σ„Áá„VBH…ÿA„WØ… –…Zh\è…di`†ôÄe¸†Âv†h¸cȆrHgnø†á‡s˜‡QV‡v˜"j¨‡€j|؇ևxˆ)|þùb8õÇlR—|ˆFCÒ$Ø—×æu臈؉}}VXsQ£èˆinËw_5–‚ªˆ|i色8wóŠc#Sõtf^§ƒ¸€,5w¾ÁGñ¶; CHäwŒæ7o¯Bê7|àó‡³8aV‹÷IjDNa•:s_»`*õÕÛˆDã:5J-ÃŒ+co ‡ÒHðød¸ˆ>øE&Ah÷¸‚(LùØthçŠ ˜/$gc/¨Œ±9pAtËfeÇ «˜ø”FÔ$‘ÕWeZ4qO·ŽJv††˜ \ ØPå‚çˆe9‘:Å2áŽePN‡’Pדsâñ‘!y“˜Uƒ¾´#}#1`-ÈJïodãn¡˜‘GɃiT‘ät9u89•¹ÆxÌ"%WiŠàã,6I•^)WP(…b9–d9–Ñø•h™jƒHˆÔÑ•iù–U–r9—tY—tùŽp™—Áå[|Ù—~ù—€˜‚9˜„Y˜†i[z™˜Š¹˜ŒÙ˜Žù˜™’éz;jas-2.5/images/PackageOverview.png0000644000175000017500000006427311506210710017405 0ustar giovannigiovanni‰PNG  IHDRR¦ ¾ç+ pHYsëëqÍ• IDATxœìÝy\gº7ü«fDƒâ–íc€`rŽQCDÔ@Œ:¸D£QrÄñäyÑ OòÎxÔD3’19Oœ‰KoÆè‰†¨q4NIKd‚Ù5'æILPYYDºëýã–²ìênºé¥îªú}?~’¦ª»¶¾«®¾®º«Ê  J/ChÚ†æÐÍOéð¥@“ÒK aHQz À·Ðü@÷퀎 쀎 쀎 쀎 쀎 쀎 쀎 쀎 쀎 쀎 쀎 쀎 쀎 쀎ð˜Yáü9Ÿ:§ù½Í¯w4ß0t Ù¢؆¡E{ #xººÏqõxkÐÛ¾Ñüœ¤·†¡'Èö@Gö@Gö@Gö@Gö@Gö@GöÔÁ`H1¸Þ£ºwŸê“é))Ùêš2¸„‡è³ö Ú†ëöÀ&O^¥º)€>!ìi™€k“AQhÀ!9•tôhy\\fppjBÂÒ¢¢2é¨#GÊ—§ÆÇg=Z.%/õØ+þH‡wu™×­{;6v~@À”~ýfÌž½î§ŸjÙ¨úú¦ŒŒW£¢ÒÆ©C†ÌËÎÞÞÖÖ.Ÿš½·‰³gÇ^”FF¦''?ïÌ2;öÙü{PPjxøô)SVÿýϦlo:òù’à êjV‹œ:hÐœŠŠ‹Ž×Å^küì³óii/†…M‹ˆ˜±xqNCCs› 4Bß ºùO0±Ÿ~šà/~þþ~¥¥ÛØ(“i«ŸŸŸtT÷—e>‹Ó±9D>|ýú§­¾úÉ“`£¦M{ÈjÔ3ÏÌ”OÍÞÛd-Ê$]ìÇÛã2—•íבùÅ/v0e{Ó‘Ï×ÁF¾ùïÖ÷¢i²æ§Æ(N­°0'0ÐòÅ»z\y«`C‚‚ŒÒ9ΟŸ¢Ç†¡KÈöóúëïuu™ßc{{qAÁ&³Ù²eK¾8Êb±¤§'ÕÔÖÔΘ1ÁýÙíÞý!åå½ÜÙyüË/wÑ©SçÙ¨’’ÓDtúôÛÛ·o8pB>{o³{ˆè¹çfµ¶ËÍ]Ýã²½öÚ{f³å—¿œ^__TX˜CDŸ|rÖÁ”“Î×ÁFÕµ@æÀóçoáÀßüË¿ÜÓãº0òÖ˜œœøÝwû®];Æâqqñî¯#¨ž·ç+âLºßÑѳëê®Jß2xð€K— ˆ(22½¡¡¹ª*ذADTQqñ®»Qw`U#i±9üÚµöââ/Nž<÷ÑGŸŸ;W)Ž3fÙ™3Æ š>}ܤIc¦O*_o³šûóÛoß½÷ÞX{K(•~åJsmíös¼ ާ#Ÿ¯ƒÜýù”›/´½#Èš©°²©ùûû™Í–¸¸_½Ç™u±×+*Þ5*†ˆšš®õë7Ã`0X,Kf–Ò½Å4Ý0t Ùžbäçêë›Ø‹¦¦V"2d ûsøðAò‹¿W:::™]IÉW±±óçÌY¿eK>;âˆöí[Ÿ0êÂ…š;‹žzê7C‡Î?x°T>'ß&:t “Ë|õj+EF†;³"¦#Ÿ¯ƒ ªkŒÙl üŸÿùñðá¿;³.Œ¼5²ˆND¡ÒÕÍCØSLDDÕÕO'tvg£ '¢ªªËìÏ jäoiic/ª«ë™ÝŠ[[²²æ9òZUÕmõŸøø‘gÏî.+Û±vmFZÚØ––¶•+·Ê§àäÛD!!N.s¿~aDtéRƒ3+â`:òù:ØÈ ºȬ^=ÿ÷¿_AD›6ý·3ëÂÈ[£ô\ è žbÆ¿ˆ^yeO[[ûþý&ƒ!%>>“JJŠ'¢U«vÔÖ6ÖÖ6fgo—~‰mÛ ®_¿QYy1+ëMgfÇ:¼-X0yÒ¤1û÷›Ø@³ÙBDAA©CJUU͆ K6nÌ$¢æækò)8xë/pùrCcc‹ø~iŸÇËãÞ{c?ÿüÛ¿þõó×…‘¶ Ð;åzÓ茬+݉[­º/æå½ÌF•—ÿAúSÔh èþ²L‚`Z¸pŠôSb‡4{=Ùë©S”~Šýœ¯¬ÌÓܹÉV­bÉ’iò)8x›X/š5+Éf¿>ÇËüÉ'Û­6ÅæÍÿËæ”_÷7²¾:ìÙêÉ©º(}]P°‰ˆ’’â{\y«pfˆ^†.áb’“Ü”˜xg` 166:7wµx47nôáÛãâFãâF°Î¢ÜÜÕ©¡}ú'''o±9}AˆÈÐÝ—aïÞµ3gN êß¿ï³Ï¦—–n#¢œœw‰hÏž5YYsbb¢üýý¢£û/_>û­·lÜÅÁÛÞx㹘˜¨  css›Í…q¼Ì<’PX˜?Òh ˆ‰‰Z¿þé_ýj¡Í);¹îÎldP] ”š3gâÃÇ—•}ýñǧ¯ €ôäô[]é¼Çl¶œ?_•°444¸µõ˜æ¨V:é°çÛæGh:iº„lO›/ÎIHXJDqq#•^Ð#´@àîÉ©MÕFcÀèÑÃ{,xZ p EN_ñy• œ¢“ZšŸ«tÒ0t ENЄ=Є=МÛóñä ðIÛ;š_¯i»aè²=Є=_ÁoFžiþÛÑü z ¶›¡È©röŠWÞûZ­æ¨€ž ÛS-ƒA6ò9úlpv <wiQéæ[A¤}àd{êa/½„›‘ÀÛñÀ^XõF¸½uWÁz½4ÝÀ›í©–~’›•Uý¬>x²=’&@,ôA$M¿¤Kb5Ö«ó•Î9ô žz°ã¾ƒ,ÇfdògbŒ—âUdµŠ|~à"„=5óýA_P}_lDyÜ€°§ZÒ˜çÕH ®öòNo‡a拾 {ê¤H̳7#Ÿr³ o6çÛcÉÀ„=•óÙqßñŒ~@%öTHñ~>ë>jsÖnÀu{jã³ò¦«³ðêÂèá4àÈöT uE×!ÛSÇf¡½>,lõq‹p²=õðqy@‹öT1O çù ·öTÂgYà™ž×<çöTÇ}ÂF· Ûã zRˆyà„=5À£<EN¾!ÚÙ„{R@o!Ûãzox¯ó¼a{ˆy  .BØãŽæŽá§ôº´ð‡ÿò&ŸKàd{Ctq@Ü8ÈŒÀ{œÁAÀ›öxÂy“Qðéê6ñ³$À=„=n¨%æñ[ \‡°Çͼa⣅ÀyèØ.BØã "€7!ìq™ŠG`3€p¹ºÒØÁšý©^/`£€+ö…Þ›:ÄmeBG!9•ƒ˜çqÜMD<·Rž—Ísíq1Ï}úØ]À}{ Áa@ç“ÒK aHQz |EN% ¼éq¸€œƒ°§(Ä<ßBØó91AÌó$|`žoáˆì=øN@—ÒÌ)=U/<è²=% lx :¶@Oö@GPäô!Í$yªè•c0p½x d{Þ‡‚›/!Ô€C{>ÈÀ„=/"Ÿïa›€ ž7iæŠu75¶9È K‹OàøëcØà`²=¯A… €?¿‹½AÛåMU\ÀÀà2à ~ÛäÃýÙžh;æ©…Ápó‹ÀQ€>ÜOö¼ 1OAØø` º´xr pWOWWÏìŽlÏ£PÞä îL 2{Þ˜À%„=ÏAJÁ3|;@D{ž„›ƒpßÜ]Zöº©éÚ¡CeÍÍm%%¿'¢§Ÿ~õØ±ÏØ¨‹ë·m;xýú]»^t¦ü@¶×+ˆyª#ø¦€[¯¿þ^W—ùý÷7¶·l2›-[¶ä‹£,KzzRMMaMMáŒÜŸÝîÝQ^ÞËÇ¿ür:už*)9MD§O¿ÝÑñ·}ûÖÑ'\š¸XÒoåMÙž{p$·••}MDO>¹Q"Æ!öbûö磣ûÑï~—eUí…êê×®µ±fÍ®>úœˆÄJæèÑÃΜ©˜5kÝôéã&MÓÔt$<<ÔÍÙñaÏu8¥§jìëÃïàICC³Õúú&ö¢©©•ˆ† Èþ>|üã‚  "êèètfv%%_Í›·¡±±E>jß¾õ‹m:w®rç΢;‹úöíóÎ;kžx"Ùæt\/'PätÊ›ª†Ÿ,À¥ˆˆ0"ª«;Ä ƒ‚`êì<ÎF NDUU—ÙŸ.ÔÈ?ÞÒÒÆ^TW×;3»+¶66¶deÍ9r䵪ª|鍸ø‘gÏî.+Û±vmFZÚØ––¶•+·Ú›Ž«óåÂ^o!怇Œ½òÊž¶¶öýûMCJ||&•”OD«Ví¨­m¬­mÌÎÞ.ý`¿~aD´m[Áõë7*+/fe½éÌì**.Ñ‚“'M³¿‰ 4›-D”j0¤TUÕlذdãÆL"jn¾&Ÿ‚ãùúûûÑåË 6Jå à<¢[ÿôLÕAÕ p«šÄ'Nle¡B”—÷2U^þ‡€q¸ÑÐ}è6 ‚iáÂ)ÒO¥cí½ž:õAé§XBYY™'¦¹s­ë™K–L“OÁñ|‡ »Y‰5+ÉÁbÜüçó]Ù^¯ ÕÏINN&ßÌÐl¶œ?_•°444¸µõ˜ofêñJv_íèÉé"(ÑÃãÄ•èÃâÅ9ùù%D7Réeáž”êòŽ£3¸­¢¢Úh =z¸Ír¥¡ÈÙkbü‡=õ6U×iAÕ|^ä䊜üRðøÈÕîáó6 àAèÉérÍã?¥BسD Ãï½B‘Óts¯âétº‚l¯'ˆyš‡´@OölÁqPØ<‡| íÍ&n9ePÞÔ|¿ 4åÒY›LÿHIÉVf©ØƒgQÐ"ýÛÓMÌS»É“W)½ Aú{ìg;žs宎WpÖ¶ h6£ƒ"§XªÒJÍêèÑò¸¸ÌààÔ„„¥EEeÒQGŽ”'&. NÏ5S`3*((ŒLON~^:kq¬òÆÎ¬¬7#"fDE¥/[öŸÍÍלÚd®B¨Ð0AóˆnþS[Knÿ}úin@€¿øõùûû•–nc£L¦­~~~ÒQÝ_±IÌ¢¤“’‘_¿þi«3yòlÔ´iYzæ™™ò©9˜‚t9{l¬tÖ²VzsÈ‚S¤Ã32Ro›¿kõ6pHëÙžV2<Ñ믿×Õe~ÿýííÅ›ÌfË–-ùâ(‹Å’žžTSSXSS8cÆ÷g·{÷‡D”—÷rgçñ/¿ÜED§Ng£JJNÑéÓowtümß¾uDtàÀ —¦À<÷ܬÖÖc¹¹«¥­¢¯8¼±±¥¢â½ë×?ú?ÿç9":rä¶ŒÖ+4ׄtNÓÏÛSû Yn=Î$‹Žž]WwUú®Áƒ\ºT@D‘‘é ÍUUùÆ "¢ŠŠ‹wݵˆºC+JCˆ|ˆÍá×®µqòä¹>úüܹJqÔ˜1ËΜ©6lÐôéã&M3}ú¸ððP›ëao lFß~ûî½÷ÆÊgmµìÏŠŠ÷FŠ!¢¶¶öÐÐiƒÁbùX²è)Ý[Ì_7žÀ EúèÒ¢¡ÃVCC³Õúú&ö¢©©•ˆ† Èþ>|üã‚  "êèètfv%%_Í›·¡±±E>jß¾õ‹m:w®rç΢;‹úöíóÎ;kžx"Ùù)0C‡tfI˜#³}ú‘–´€wh·È©ÑÚTDDÕÕOhuvg£ '¢ªªËìÏ jäoiic/ª«ë™ÝŠ[[²²æ9òZUU¾tT|üȳgw—•íX»6#-mlKKÛÊ•[]šèÌ’0Ò“—^‡;Sh‘FÞÚË›ö½òÊž¶¶öýûMCJ||&•”OD«Ví¨­m¬­mÌÎÞ.ý`¿~aD´m[Áõë7*+/fe½éÌì**.Ñ‚“'M³¿‰ 4›-D”j0¤TUÕlذdãÆL"²Ù¯ÒÁ{‘Œuu¹|¹ÁA¦à2…»ÔxƒØOíkg«'ç‰[Å.šL^ÞËlTyù¤<Æ€î¯Ø$¦… oëd”޵÷zêÔ¥Ÿb eeež ˜æÎµ®g.Y2Í¥)Hß&ÿ ;CID³f%9ÛÕãß»fÚtÓh¶Çh+Ïc’“Ü”˜xg` 166:7wµÏÆ}øð游Ƹ¸……9Òææ®ÎÈHˆíÓ'899±¸x‹Íé ‚@D†îtyïÞµ3gN êß¿ï³Ï¦—–n#¢œœw‰hÏž5YYsbb¢üýý¢£û/_>û­·lÜWÅÁ{ãçbb¢‚‚ŒÍÍmÎoÓbÐ9ÍõäÔRyÓVON¯2›-çÏW%$, nm=æ›™z’g{rÞœ&úshж²=-Å<%,^œ“°”ˆââF*½,Ü@ÇmÑÖ ‚€Ûoº£¢¢Úh =z¸Ír¥~¡9hˆæŠœZâó"§êy£È Ú¢­"'€W¡Î  ~š(r¢Óx€V Ûpâ€Ê©ÿÜž†{oâÛkÞh (*h‚ʳ= Ç<ð5‡=ÍÇMÐD— ‡¯ë|0/eg £Ú°‡_Ü®r¼Å” ?*½½€Á ¾e"RkØÓ|yÓƒœù} ø6TKoñ6@ Zj>·GÜ%gómµÑ”Ú†6çk0 ®€W©0ìá°è˜ƒ³hìŸÕ@¥°:¡|‘8‡Ž-*§¶°‡ò¦=,ObÛǪfhZ”=^ÛüÖTü@µTu¹:bžMÎT2m¾ÙÇÛP-'ðz„v fªêÒÂ1èDÇôâ’¯=[ÔLUaÑùñÚÁ×ñ–á3æ©ôP-•„=dxä¹+¾ùÙ’â©îûU×Ò€„JÂ!-ÑÀ¦@µ|N aOŸGFyMR ½ x|†Iq¥T—ð1*]lãþ>ÏHy•ƒK¶µÝÑ_u¿o¬.5à;ìé*æI/¼“ÒüŠósM!耊œ¤éC¯{fªŽƒÕQûI>”:ԃ㰧êã 3ð,›TBÔ­t‰×"§æË›6‹™Ú>uçJ༆=‘f€թ;ézé9ÚI©1òáÎÔjÃe‘ScG3‡²!xaO3åM¾Ý¤¢“| œ=A1O?=3½GuwäÑÌÃ%t€¿lQãáÅLOÁ¯á,ì‰R—žx.QW©S]K  K\öäTÅÃ^·LBÏLÏQËÝ¿ðu¨7ÙžŠ~&£˜é{*jÀ7>º´¨¢' *™ŠPEÛ`T×@—8Èö8?®¡g¦²Tt%Ú€(öxŽy(fò¥Np›ÒaOÄÏá ÑŽ7Ò„ÿȇR'ßíÉÉUñÊÁÇ虩8µÜ®“çe"R2Ûã§¼‰ôNTt’Ô•èEN¥Žè«¢^ÜuÅf]R¨È©à= ­*¢–R'pL‰°§ÔË^´Óùó]Õ…ÿ¯ Oàà[€Â;§*8u§1($€¸¼''ã½Cr; PÅ7ˆð ÀŽÃžÇ¡˜©œŸäCàXwONÁ¤äRX1¤xrj8i‡1ø¦§l4FzëÞ c ¯ö@µ8/u—ö@ÍTù¸]0]BØ•ãöÜ-·  o{ !|æUˆ~â?K{ Mˆ4`Âh'½(qgjnð«Ø‹s(Kcÿ.Ä…Q|Iô Ùž7á§½²ø 0hŠBØ}P<Øðƒô‡Ë§«k€g½&·=±@÷z~ xƒUòñ÷H#'€”ƒ°ç¼võFŒ|ÊÆ0€þàÜž—qÒDø:ô ÙžBPãò1NNò±ÅÀ· „=ßÂñNAœÔÑ…"§o±š'_ÃW Wn…=ƒ!ÅàzOýÞ}ÊgL¦¤¤d+½àœ<™¿~”ƒ"§µÉ“WykÒ6‹ll _>#~ Øæº¤@Øtui¼U¨c‡Z{Áp,ö Å72'Tè’"çÑ£åqq™ÁÁ© K‹ŠÊ¤£Ž)OL\œŸyôh¹t”¼ti¯˜)ÞÕe^·îíØØùSúõ›1{öºŸ~ªe£êë›22^ŠJ7§2/;{{[[»Õ¤8a0¤ÌŸ¿A2þƒ!åÀ=®Ë±cŸ=ðÀ¿¥†‡OŸ2eõ÷ßÿÌ–M¾ß|óã/~ñaaÓÂçϞ½îŸÿ¬¶Z—‚‚ÒÈÈôääçå+kµæ7_8¸?j_^%°‚‰ýûôÓÜ€q¬¿¿_ié66ÊdÚêçç'us ‚ILàÄéØ"¾~ýÓVË3yòlÔ´iYzæ™™V“jkûkß¾}úô nm=&¦ÖÖc!!Aaa!mmu¼.ee;Äåg~ñ‹‡åi¨ ˜*+óúõ “8°ß… ïK×…Mê±ÇÆÞZ¶[VáÖŸâ+Ò7ôøfð·3¾e…Xg{¯¿þ^W—ùý÷7¶·l2›-[¶ä‹£,KzzRMMaMMáŒÈm»wHDyy/wvÿòË]DtêÔy6ª¤ä4>ývGÇßöí[GDb' š5+©­­ý/ù”ˆþûõë7ÒÓ“BB‚¯Ëk¯½g6[~ùËéõõE……9DôÉ'gIR€£Ú¦Mÿ}õjkZÚØK— .]*HKwuãÆ=ÒÅxî¹Y­­ÇrsWÛ]Ï{R‚íbú>ø†ï·0j› é~Þ^÷á>:zv]ÝUé;péREF¦744WUå6ˆˆ**.Þu×"ê¬$(M˜äCl¿v­½¸ø‹“'Ï}ôÑççÎUŠ£ÆŒYvæLŰaƒ¦O7iÒ˜éÓÇ…‡‡ÊWàÈ‘ò™3×Ì›|ðàoæÎ}©°ð“C‡^MOOr¼.QQéW®4×Ö~0p`?Ç‹7x𜚚Æï¾Ûw÷ÝC‰èûï¾çžŒ;xñ øæo¿}÷Þ{coŸJÊÍöžã£ž½Ð§àYUœÐP‚u—–††f«!õõMìESS+ 2ý9|ø ùäA0 DÔÑÑéÌìKJ¾š7oCcc‹|Ô¾}ë-Útî\åÎE;wõíÛçwÖ<ñD²ÕÛÒÒþuÀ€ð?"zå•=mmíû÷› †”øøL6*))žˆV­ÚQ[ÛX[Û˜½]úAH¶m+¸~ýFeåŬ¬7™}EÅE"Z°`ò¤Icöï7±f³…ˆ‚‚R †”ªªš –lܘIDÍÍ×lNä©§¦Ѿ}ÅlRά˄ qDôÚkº~ýFAA©Á2räB6ŠõO¹|¹å S¦Ùn5jóæÿÅF±3—D4kV’ ˜¾ùfoXXˆôƒ¸xñ ãÞªÞí¤g¯Û'úºC©mˆïÀ·¬Ó”ääă7%&ÞhŒÎÍ]-ƳqãF>¼9.nD` 1.në)ÊÍ]‘‘Ú§Oprrbqñ²E"2tÿ¦Þ»wíÌ™BB‚ú÷ïûì³é¥¥Ûˆ('ç]"Ú³gMVÖœ˜˜(¿èèþË—Ï~ë-Û÷Oñóó{òÉÉD4wîD1;^—GI(,̉i4ÄÄD­_ÿô¯~u3Û{ãçbb¢‚‚ŒÍÍmD4zôð¿ÿý­™3'„†‡……Ì™3±¬l‹²Šq2"ùs6 €¦Y÷äô*³Ùrþ|UBÂÒÐÐàÖÖc>˜£blöäôâìì©qöÈ%ÎwµUûLţO`X¼8'!a)ÅÅôå|µ¯ç AN‘“|øâ|˧÷䬨¨6Fn¯\ nq|Ï3ÂÖ J=“_ €¯ø´È©#>.r:&?Žó°TÜBÕ@Óðà!]ÂýA` ¶ €F!ì銟®RðFeŠÌ@O|Ú¥†{¾ô‚o6 B€¯°·yχ3ÜðÚ1g`¨<ø²=s|§4$JÝ´ [À›íy“º~¶KûqXyÕµ"žåË$ €÷`ƒ›´ô|!<@# öd°÷à²?ð œÛÎØ|àƒƒ à d{À+?À ö€oŽ{~:~€ ¨’?p¨J=_BØuB'èô䕳wÃk[ðtuÐ$®ÂtÙ€¾á‡è Â躴€Fqõtu>¹úÌwM@Ø;¬êŸ8 š€°D„“| {º‡€z‚°v ª Z„°u u¸€tÙÀ-C  .^üлOyƒ»KbóN§Èÿ@[í@7›}[ ôy-A¶à.ò<·‚Kô¬†à¡¾ Èö@ûŽ-‹Ë NMHXZTT&uäHybâ²ààÔøøÌ£GË¥£ †Ãí÷1‘‘ïê2¯[÷vlìü€€)ýú͘={ÝO?Õ²QõõM¯FE¥S‡ ™—½½­­ÝÞÔ*‹‹Ë ²±`ß|óã/~ñaaÓÂçϞ½îŸÿ¬¶šB}}SPPjddúõë7Äׯ߈ŒLN½r¥ÙÁ¶ºí±½ò Ç2?$ j€*¹öO0±Ÿ~šà/6x¿ÒÒml”É´ÕÏÏO:ª{§0‰ œ8›CäÃׯÚj›<ù6jÚ´‡¬F=óÌL{S3oUbüýýÊÊv°±••yýú…I'2p`¿ Þ·Z’ùóSˆh×®ÅÉþ×½@DO?vk^·¶•l ;¹ñTÙhÜ믿×Õe~ÿýííÅ›ÌfË–-ùâ(‹Å’žžTSSXSS8cÆ÷g·{÷‡D”—÷rgçñ/¿ÜED§Ng£JJNÑéÓowtümß¾uDtàÀ {Óyì±±—.ÔÔΘ1Þl¶lÞü'6|Ó¦ÿ¾zµ5-mì¥K—.¤¥­«»ºqã«?óÌL"Ú¾½@Â^?ûlºÝE—ævòš§ƒä@Uð¼=P W¯Ý©Otô캺«Ò1ƒ¸t©€ˆ"#Óš«ªò‡ DDïºkuŸ«“÷Š´×OÒjøµkíÅÅ_œ?w®R5f̲3g*† 4}ú¸I“ÆLŸ>.<<ÔÖŠ¦Ñ?æ~k©"#Ãë니hðà955ß}·ïÑ÷ßÿ|Ï=wÜyñâAé’‚0jÔS?þxùøñßM™òàñã_=úèÿ¾ÿþ;Ïœù£dN)ÝÛÊNÀ³wp°ùƒgþ@íJˆ ‡Õ¿ž44XŸÊª¯ob/ššZ‰hÈìOfd³½9‹ŽŽNg³¤ä«ØØùsæ¬ß²%ŸÅ<Ѿ}ëF]¸P³sgÑSOýfèÐù–Ú›ÎС·-USÓ5ög]]Ãþ9òé‰ òe3ˆhÛ¶ƒâ¥z"gB’?P3„=иˆˆ0"ª«;$žÓêì<ÎF NDUU—ÙŸ.ÔÈ?ÞÒÒÆ^TW×;3»+¶66¶deÍ9r䵪ª|鍸ø‘gÏî.+Û±vmFZÚØ––¶•+·Ú›Î÷ßÿÌ^°1lQ‰hàÀ"ª¬¼Èþd/ ê/ŸÂÒ¥ûûû>üéñã_ýå/Ÿ†……dd¤:³ .°#Ñíø†°7~ü}DôÊ+{ÚÚÚ÷ï7 )ññ™lTRR<­Zµ£¶¶±¶¶1;{»ôƒ¬çȶmׯߨ¬¼˜•õ¦3³«¨¸HD Lž4iÌþý&6Ðl¶QPPªÁRUU³aÃ’3‰¨¹ùš½é¬Xñfuuý•+Í/¼KD'ÞφO™ò ­\¹õò冚šÆçŸßFD6ÏJõøãã,ËO¼d±X/NíÛ·3«à|&Ý?à“Â]jzÁ™®†Ý¹Ý‰[Å.šL^ÞËlTyù¤<ÅΓlìÂ…S¤Ÿ 2JÇÚ{=uêƒÒO±,­²2OLsç&[í}K–L³7µÀ@£ø¶À@ã—_îbc¿ùfoXXˆt"ƒ¸xñ Í¾¦|ðªø¶üãÖ½F½Ô!Ý>oÈö@UÄÂé4"99ñàÁM‰‰wcc£ssW‹ñlܸчoŽ‹hŒ‹QX˜#ý`nîꌌԈˆÐ>}‚““‹‹·Øœ¾ Ddè^ž½{×Μ9!$$¨ÿ¾Ï>›^ZºˆrrÞ%¢={Öde͉‰‰ò÷÷‹Žî¿|ùì·ÞZeo±ûÏøø‘Ƹûرÿ|ðÁ{ØðÑ£‡ÿýïoÍœ9!448,,dΜ‰ee;î¸#ÒæDfÌÏF_bâNn1wÙË‘üГTB~Ä”ß@RzoŸÜ9Ål¶œ?_•°444¸µõ˜G¦é©;|vvvýßÿûÓ¤IÙ Ío¿ýÿ².·Ï)åæ ¯|qJÀÍÉ@ ä—‘Ùå[‹çäç—Q\ÜHæÀÀGÙ‹Áƒ<õÔTÅ–ƒ}Yöîö‰>‡"'ðM^³w TâZQQm4ÜÿÊ•Jéß¿o@€ÿ¿üË=EE¿íÓ'Xá¥+ŸV_*Ÿàs(r¯œ)ŽÉ¯›öm‘SÝ|Sä´;w[ч#ð>d{À%›7Çr‡KÕA·PÎígÐB?l>ÕVüß;xÂpæ¶Þ˜=øpdÔ›Ý^œo®À¹=àƒ´SŸ;?öQ"ë®8ç^†l”†ª&HÙ¼S„kÀmèÒŠ’Æ<$j8&ºŠÛ-&ïÇ$Þ 9=¸ENPˆ~’<'¯;„©·Íp§Õ²= a|N½¯^À™*ϲ?xÞ¤ÜÆ<†çMç8·¾…ÔÜaïVg¸æœ†°¾¢«$±÷3ý2Üäø‚?âµiquç ñ=úƒ°>$¼ÁÁ}®ì@ONð>}Æ<›™‡½4ÜáàqðØÎ ƒ°Þ'z¼µ¦f8s´ÅÙãl60vÁ¶6tCØï°:Ðè'àY‘¯µ>·ƒ/98ó‡à8·ž‡#‹ó[}[¼ ·ú[íçà×4Ùz 7O‡×§ý°ñu Ùxˆ>û­8ÐãqÌõ%<äº!Û·É5ã ܲ×ítٸϊó[ÛJA.øÃ W­C؃ÞÒá]W@cì¥}èö¢i{à:<Ð œùÓ"„=p´;ŽÎÀVR ×<àKÔ ti§É»æã@š„»½hÂ8AÜÛ¹( @pÁŸFá1³ÐôÕtjÂÐëSÚˆ‘ 7Ù؇ òDVÉŸôúw6gp³•Ð¥ì@À³·# Û‹z ì ®OèÇÕl®ž®îKœ=Éa$ð\eóöªHþ8†°ÝPÕèÇ÷¹ΠK b€'èöqʪ‚°§oòSØoÜÄv"ìG¼B‘SÇáx•ƒç<€ríé’ôJ#ì“ '{úƒ$@= †ƒëôîS:"§žàúÐ=„=}@ÀÐA·—Æ;ENW5óuôhy\\fppjBÂÒ¢¢2é¨#GÊ—§ÆÇg=Z.%/]Ú+fJ‡wu™×­{;6v~@À”~ýfÌž½î§ŸjÙ¨úú¦ŒŒW£¢ÒÆ©C†ÌËÎÞÞÖÖnoj‡•ÅÅeY/˜“ážÀ iHò8'0èÙ­oßÄþ_^þÍĉ+»ºÌìO¿?~sâÄû‰èĉ3S¦¬¶X,â(³ÙBÝÙ‹dÒLN>D>ü¥—þ˜“ó®tìäÉ””üžˆüWÇŽ}&õÌ33wízÑæÔŒÆ€ÎÎ.qÁJK·=üp¼S3íÙžv!Éã.ä‰×_¯«ËüþûÛÛ‹ 6™Í–-[òÅQ‹%==©¦¦°¦¦pÆŒ îÏn÷î‰(/ïåÎÎã_~¹‹ˆN:ÏF•”œ&¢Ó§ßîèøÛ¾}ëˆèÀö¦óØcc/]*¨©)œ1c¼ÙlÙ¼ùO½˜íin  8Y¶=»®îªô-ƒ¸t©€ˆ"#Óš«ªò‡ DDïºk¹—íѵkíÅÅ_œ?w®R5f̲3g*† 4}ú¸I“ÆLŸ>.<<ÔÖ¤Ñ?æ~k©"#Ãë닜šgÙž¶XÅ9ƒ“v _²°0…•.EþÇÅQ]]%þþ~DÔÕe6§ÒíaÏbùØ`0QGGgPP*õöJJ¾š7oCcc‹ô lÔ×_ÿ°hÑ&‰¨oß>ï¼³æ‰'’mNÍj©Äeîy"œ…=95gò¸Åî€;ED„Q]Ý!A0±,~Ñ€áDTUu™ýyáBüã--mìEuu½3³[±bkccKVÖœ#G^«ªÊ—ŽŠyöìî²²k×f¤¥mii[¹r«½é|ÿýÏìëÃÕÕ‰ðaO¬©8¼plüøûˆè•Wö´µµïßo2Râã3Ù¨¤¤x"ZµjGmmcmmcvövéûõ #¢mÛ ®_¿QYy1+ëMgfWQq‘ˆ,˜¼9.nD` 1.nDaaŽôƒ¹¹«32R#"Bûô NNN,.Þbsú‚ ‘¡ûø°wïÚ™3'„„õïß÷ÙgÓKK·»¤aÏž5YYsbb¢üýý¢£û/_>û­·VÙ[ìcÇþ3>~d` ñî>vì?|ð6Ü¥‰ð]ZÔ §ñÔ×í陬K‹W™Í–óç«–††·¶óÈ4íõuúó)7_ðÑþ‘í©¼g’<è¶xqNBÂR"Š‹©ô²p ÷äT<<ª¨¨6FÎy¥QA(rªŠ4ìá‹S9õÌ·EN¡È ½Ç ªš½…"'ßäY€œ{Ü^û¬íÀífP³žÎíq~ðÕjäC×Á¹==ãü(êK|´99ƒ ò<‹·#â€Òœ{\õA²õ4aÕCÀó8ÞbžŽ¡‚ÀuSôn<²=> ª  aØ£y‚°§4$y>€ZtCØS’<ßÂåꊒÆ9Ä<ïC¶çs,ÃÃåçJ@¶ç[bU=»”€lÏWç8€°ç}è« À „=/C_Mž ìy ’<þ ìy’<.!ìy’<Ž!ìygpÝž§±P'ˆyr:Ûãóþ¹¾¼Î^“?A €WÈöœ&±ÃmqA:÷ ‚ãÔ‡r)é¶B_Mþ¡õÚƒæ :¦Î§«û˜U}5AíðlwÐ1ôät’<5CØsbžJé¹Va…Ͼi>„°×+xê„°ç"<Ð${ÝÐàAsö\Chº¹‚^áº=Ðïf{C  .v(èݧzÇ—óà* Èö5OÐÞ ˜~â †ƒëÝý{÷©Þ9qâ̸qÏ…„¤……MKK{ÑÝ…±ºÙ€Fõ&ì=Z—œš°´¨¨L:êÈ‘òÄÄeÁÁ©ññ™G–KGÉ÷@{û¤txW—yݺ·ccçLé×oÆìÙë~ú©–ª¯oÊÈx5**Ýhœ:dȼììímmí6¸¨¨ì¾û–„„¤¥¦¾PUU#ŸïÑ£åññ™ÁÁ©‰‰Ë>üð” Û@9ÿöo¿ýì³óíí×®µ‡‡‡zf¢~ uNß“³;ý*/ÿfâÄ•]]fö§¿¿ßÇ¿9qâýDtâÄ™)SV[,q”Ùl¡î3gò³höΫI‡¿ôÒsrÞ•Ž<ù’’ßÑãÿêØ±Ï¤£žyfæ®]Ö¿yOž<—’’Í–„ˆî¹'ö»ï~²Z*qQÙk“ië#$H(¥{#àü‡ªÈZ¯‹ŸN!¾ÏûúùM¡ª*?&&ª½½#,,Äê 6VAþC“µji¨C;Ms9Û{ýõ÷ººÌï¿¿±½½¸ `“ÙlÙ²%_e±XÒÓ“jj kj g̘àþòíÞý!åå½ÜÙyüË/wÑ©SçÙ¨’’ÓDtúôÛÛ·o8pÂæ›Í–9s&ÖÕºt©`Ô¨;äï—9==Él¶lÞü'÷—ø¤®Z…ƒù )ì7ëðá ŒÆ©,æ9Xkblc=!Ò*à!ó-r9Û‹Žž]WwUú–Áƒ\ºT@D‘‘é ÍUUùÆ "¢ŠŠ‹wݵˆÜËöˆèÚµöââ/Nž<÷ÑGŸŸ;W)Ž3fÙ™3Æ š>}ܤIc¦Og³Î•~åJó?üyĈÁDôý÷?ßsO†ÕR]¸ð~ll4UV^¼óÎE„_¹R$Y ”î€_Áª¢þZ…ƒùZ…CA09^…îϧˆè9ÃÃÝø@‹\Îöš­†Ô×7±MM­D4dÈ@öçðáƒä£lGG§3³+)ù*6vþœ9ë·lÉg1O´oßú„„Q.ÔìÜYôÔS¿:tþÁƒ¥ò)\½ÚJD,ªÑÈ‘6²½˜˜¨îeLDÍÍלY6PÕÕ*ƒ™ØÌåUp5Œ!ùMp9ìED„Q]Ý!¶³ ‚©³ó85`@8UU]f^¸P#ÿxKK{Q]]ïÌìV¬ØÚØØ’•5çȑתªò¥£âãGž=»»¬lÇÚµiic[ZÚV®Ü*ŸB¿~aÒ…©¬¼(Ï?ÿYÍ^°[О²²¯‰èÉ'7§ÎûIâ{±}ûóÑÑý££ûÿîwYîÏ®ºú@kë±ààÀ5kvef¾FDb%sôèaD4kÖºçŸßæïïßÔt¤¡á°›³sklÆ3yÙ“ü@õ\{ãÇßGD¯¼²§­­}ÿ~“ÁŸÉF%%ÅѪU;jkkk³³·K?ÈÂ϶mׯߨ¬¼˜•õ¦3³«¨¸HD Lž4iÌþý&6•n‚‚R †”ªªš –lܘIv²´‡Ž'¢^Ƚr¥¹ºº~ùòßËß³bÅ›?ÿ\×ÐÐü ¹âŠ€ö¨®VáÒ|Yù¤o½vp[N?ЗÃÞ¯ý”¿¿ßŽ…¡¡Óž|r#­_ÿolÔš5‹üþû As šó׿~.ýà´iÑK/ý±OŸÇî¼sQIÉWÒ±ö:Lœ˜@DÉÉχ…M{ñÅ?°<Œ¥n3gN ¢E‹6¥>üpÍ›—"ŸÚ¯½Èß߯°ð“¨¨ô¡CçµµÝÏåĉ3±±ó##Ó Jü׬YäêfUP]­Â¥ù:³ 68YêDð­p9ì%''<¸)1ñÎÀ@clltnîê… §°QãÆ>|xs\܈À@c\܈ÂÂéssWgd¤FD„ö霜œX\¼ÅæôÙ[C÷¾´wïÚ™3'„„õïß÷ÙgÓKK·ë&°gÏš¬¬911Qþþ~ÑÑý—/ŸýÖ[«äLJŠÏÏßx÷ÝCCB‚æÏO9tèU" 2JßóÁ9 £Øb>¼ù¡‡F»ºY@TW«pi¾ŽWÁ3ì?õp¹'§W™Í–óç«–††·¶s‚‚ >ÚÕe.*úí´iµ·wìÝûו+·Þ{oì·ß¾ÛóçôäT)Yë--=3eÊjñM"ÊË{™ýn;uêü#¬;y]ÔÝsä©§~óç?—ˆŸ 2Þ¸ÑI¶úyJ_?úèÿ>~üVUcÀ€ð††æÊʼ‘#ïx≗ n«j.Y2mÏž5VSp~¾=®B÷6IéÞ&n7æ[›û¨ _7'[¼8'!a)ÅÅôÈ «…¦§¯ |4<|:+%ef>î‘郺¨®Váä|Yϳw’?à_ÙÞØ±ÿÏ™3£Gÿãõ¯ÿz¯G¦ÙÜ|mýú?>ü÷êêzAbb¢žzjjNβ€g'lO¥T^«ð ¯6f\çjÀWØãžJù¶õ.\ø›üü"zè¡Ñ§NýÁsì _†=ïÍÀ xº:€gTTT£G·Y®Ôùí=Å?ü€{žñùçÿ¥ô"ðÁênŸÒ×~À„=ðyò‡ÎŸÀ§Ãž¯žœ šb³ò  ¾.`m²y;!‚zêÉIh—ÝP–Q4]xhÏx¶-(Á‰"§Ç›£÷.îqp˜ÃNÀ3ôy_q"Ûóð ½ye3¿î±_é >›øÙ p©øœ¶Âž½éÛ„] 'ÛL¯Œ§Ê®†pµp?ð!ßvi±·ßzõ'¹½sé s.Ý@Òƒ±ª×­]ÃÍO5ÒÍu{6/¡¯4ïMV¤ö¶›¼€Oø0ìI¯T•¿6<ܲٔåÓÄþr^ Êž=ŸÍ¦¦¶ëüÀË|Uät¦{¤¡K³:-ýc…5«òš—N2y*,Ù›‚öš7®ó¯ñùåꊤ_bB à€g/#³*i°,¶K—Pyžœüw á©~à.Ÿ„=稷›2v°ÇK1ÏÍ÷8¦¥Ú¦3ä§ý°Gƒë¼öœ9šx»‰j'ôHl$Vç–Ü */oXå‹Vm[ÛÍ>Á|Xät¼·{û¡—ˆ|Ð#O]ë¢HyCœ”æ›7‚¸G‹08ÓSÜãGA¥<Þ?ÞÉò†4JydîVÓt0wmPÑÕÜÆcÞ6”¯x?Û³yRÚÍwözI¤ìeH©pz¯¼a¯_Œ¼ë‡æñŸùñ³$r)«à§ç†¡?{ÝÐÃEÃR}¸Dø…'BÙS—öì@»×NBtÞ½SÎÞ¥~Ø2…°'#£fà7»c(x: ­H‹D[Œ IDATön‡R§XÝš‹†aD>›p©Ÿ ìÉ ò©šã‡€"Ÿ=~š†°g "ŸJ!æ¹ÊêøŽÖ.…à§Q{vàX :ˆy½†Öî®óÓƒ ÈÑÁ#ñô\欜ÇÕCÇOWw4ÔÞŠ8‡ëÙ]…©Èö\Íd¾„È× ~|CØs.ìUê̾‡È×;~¼ÂÓÕ]‡È§Ü=@)¸‡h²½^Á!À÷ó‡fïsCŠÁâ›O¹?5“é))Ùžš¯“z1S\·×[¸‹/©=æ©q™m²jö¤¡U·Mž¼J3EØs"Ÿo¨=æiŒÕÚhùü-í۰i3/Îihhf£äïw°¦EEe÷Ý·$$$-5õ…ªªù\ J##Ó““Ÿw°®Îô&AD7ÿiƒ¸:šY#NhfÃjc-¬hlu¼äÖWobÿ>ý47 À_<ûûû•–nc£L¦­~~~ÒQÝGi“˜r‰Ó±9D>|ýú§­Žù“'?ÀFM›öÕ¨gž™éxjìuPQú©ùóSä¡ã5ýä“íâÚÑ=÷ÄÊçÂÞðØcc¬…K3½ùÙžgàv!Þ€~äÙ³»ËÊv¬]›‘–6¶¥¥måÊ­ÎLSzòÌkÚ¯_IV°²ò¢üã!!ά…ó3!ìyvxw \¦^ˆ|Î?þ>"zå•=mmíû÷› †”øøL6*))žˆV­ÚQ[ÛX[Û˜½]úA*¶m+¸~ýFeåŬ¬7™]EÅE"Z°`ò¤Icöï7±f³…ˆ‚‚R †”ªªš –lܘIDÍÍ×ÜY5Ö åòå––9XÓ‡Ž'¢^Ƚr¥¹ºº~ùòß˧&íÝã`-œŸé-J÷nÒ"Íô?ô1 o1ý´iã×ÃúöHÖ“óĉ­ÒNŒD”—÷2U^þi"e4t¥M‚`Z¸pŠôSbwJ{ý-Ùë©S”~Š%”••y‚`š;׺ž¹dÉ4ÇS“¾–‹Ÿ³f%9^Ó“'wHGM˜çx.ÖÂù™¢'§7áb¾^À=¦µwïìIrrâÁƒ›ï 4ÆÆFçæ®ãÙ¸q£Þ7"0Ð7¢°0GúÁÜÜÕ©¡}ú'''o±9}AˆÈнå÷î];sæ„ þýû>ûlzié6"ÊÉy—ˆöìY“•5'&&Êßß/:ºÿòå³ßzË­Û¬¼ñÆs11QAAÆææ6Çkš”ŸŸ¿ñ†„ÍŸŸrèЫ$».BÊÁZ8?Szrz êuÎÓü¶ÒCƒ·¢ùïÔI²žœ^e6[Ο¯JHXÜÚzÌsìAíê2ývÚ´‡ÚÛ;öîýëÊ•[ï½7öÛoßõúìѓӋpë2gXeØJšîJX¼8'?¿„ˆââF*½,v †™3'|ðÁÉôôµÒá™™ûfðtuoBµÇ1ÄhfoGÌ` IÕûð aˆ|ˆyàqèÞ ž†°ÇU‡ Ä<ð tï¯ÁÓÕ¹¤ê-£ê…~ òw ÛãŒz àf›àqˆ|à{SÅY Ô6Á«Ð½< OWç•*ne‰îvàˆ|à9ÈöxÅÿ~ÎçRVáîà!{ã9ò¡¶éôáòœêO@ØãŸ‘1”"moh{Ð+{Üã-ò!æ²Ðg܃°§œD>«*8î8}¸< çùÀ {*¡x䳚)bp‘œ†°§ F>Ä<àÒ>pN€Ò  ¾ßßœœ£û! 1x&·5QƒMC¶ç <ÿÆtsÙ󀸰\°¡¿8¨"8 ENLJ/„!Å3ÓaE$Ä<àk¢Ò»ú¡Ñ‚-ÈöÀ 8|€Z(Þ縇l<„Ã0à ¿Û@Ùx‡1OÄó²Ï)”íáÇ(ENð(Mvì A‘tD¡lO,µ£Ú >„ltçö¼U n ÛAØA‘ÀûЇ €Èö@Gö@GPäô(>o ¡Æ¢Þl¸¤ÆP j€°:‚"§Gqu^•â³P ZltÙxŸù:og‹ÑiK9Èö|Ž·0¬'xº:芜àQèØåŸE`=A‘tD¡°g0ÜüDCŠÁõ€½ûTï¸3¯'ÎŒ÷\HHZXØ´´´=;qW¡È ÞõoÿöÛ jØëððPeaO­•œAùé§Z"ªªÊ‰‰joïPzq‚>\ÜÀ¹=o9z´<..3885!aiQQ™tÔ‘#剉˂ƒSãã3-—Ž’WüìեûºÌëÖ½;? `J¿~3fÏ^Ç‚ Õ×7ed¼•n4N2d^vöö¶¶v› \TTvß}KBBÒRS_¨ªª‘Ï÷èÑòøøÌààÔÄÄe~xÊ™e6RA ¢áÃSÃÂB¯>€·E~‡jì©›·VÇÄþ_^þÍĉ+»ºÌìO¿?~sâÄû‰èĉ3S¦¬¶X,â(³ÙBÝÙ‹ÒLN>D>ü¥—þ˜“ó®tìäÉ””üžˆüWÇŽ}&õÌ33wí²>Çvòä¹””l¶$DtÏ=±ß}÷“ÕR‰‹Ê^›L[y$Áñ2[…CA09^}"I?7m´ ýí`Z¸ÒíyÅ믿×Õe~ÿýííÅ›ÌfË–-ùâ(‹Å’žžTSSXSS8cÆ÷g·{÷‡D”—÷rgçñ/¿ÜED§Ng£JJNÑéÓowtümß¾uDtàÀ › l6[æÌ™XWwèÒ¥‚Q£î¿G\æôô$³Ù²yóŸz\01˜ ‚‰½öÆê«úp9ÿ¾]®2™þ‘’’­ôR€5d{ž û=»®îªô-ƒ¸t©€ˆ"#Óš«ªò‡ DDïºk¹—íѵkíÅÅ_œ?w®R5f̲3g*† 4}ú¸I“ÆLŸ>Îf¿’¨¨ô+WšøáÏ#F &¢ï¿ÿùž{2¬–êÂ…÷cc£‰¨²òâw.0 üÊ•¢—Ùj¬ãÕ'Òèoa5x›ÜÎöì5uo|Ê7l/›&[¸ª K‹W444[ ©¯ob/ššZ‰hÈìÏáÃÉ?.‚Á` ¢ŽŽNgfWRòÕ¼y[ä£öí[¿hѦsç*wî,Ú¹³¨oß>ï¼³æ‰'’­Þvõj+±¨FD#GÚÈöbb¢º—y057_ëÅ2;³úÎã3àÏPäôŠˆˆ0"ª«;ÄŠ{‚`êì<ÎF NDUU—ÙŸbç~©––6ö¢ººÞ™Ù­X±µ±±%+kΑ#¯UUåKGÅÇ<{vwYÙŽµk3ÒÒÆ¶´´­\¹U>…~ý¤ SYyQþžþ³š½`ýeØŠ¸ºÌά>h‰ºúv±©”FF¦''?Ï~óÍ¿øÅ„…M Ÿ>{ö:qGp/qQ‰( ÀÿÔ©?¸ºÌ=®¾ ˜´Ö6M®”Ù^ ¦Ù³!"±oÍš•ÄF=þø8º½Ÿ”ƒfcsˆ|8«ÃKûvõéÌFéö¾]ýû÷µ7µ+æ´¶«¨xOLK—>NDiic/]*¸t© -m,ýò—ÓÙûµ½Ìzh |C¶çÉɉnJL¼30Л»ZŒ ãÆ>|xs\܈À@c\܈ÂÂéssWgd¤FD„ö霜œX\¼ÅæôA "Cw'‚½{×Μ9!$$¨ÿ¾Ï>›^ZºˆØ% {ö¬ÉÊšåïïÝùòÙo½µJ>Á¤¤øüüwß=4$$hþü”C‡^%Ic>ø '!a[ìÇ7?ôÐh—–Ù™Õ)+ûšˆž|rcppêܹ/‘¤1{±}ûóÑÑý££ûÿîwYîÏ®ºú@kë±ààÀ5kvef¾FDb%sôèaD4kÖºçŸßæïïßÔt¤¡á°½é¬X1744xÔ¨"bÕ×;²0xð€;²‰H¼nÕñXàzrz‚o¯X2›-çÏW%$, nm=æþA |´«Ë\TôÛiÓjoïØ»÷¯+Wn½÷ÞØo¿}·çÏ{–&û¹i¬ÁÛdk/˜"^ëÙ=ÄŸçf£ººJX™¡«Ël4N¥Û;[,‹ý¤‚‚Rű·Ï6En³oõõ×?°¾]l ½¾]lj­­ÇBCƒÙÿ)‹õrëq,zrò Ùžú,^œ“°”ˆââFzd‚ƒaæÌ D”ž¾60ðÑððé¬ÛKfæã™>è–êúv1!!âë#HÒÉ‹½4¨¿3cO{êSQQm4Üÿ6Ë•½³wï¬\9wĈÁFc@@€ÿ°aƒ~ýëE/¾¸ÀSÓ}R]ß.ÆÏïÖqÊ”‰håÊ­—/7ÔÔ4>ÿü6"o³àx,K/_n°yq(E¡"§Æà¶L¤É^‹œ¥¥g¦LY-­sæå½ÌÎsŸ:uþ‘GVˆ7ð3:;»¨»$øÔS¿ùóŸKÄOoÜè¤ÛK ò×>ú¿ÿJüÔ€á Í••y#GÞñÄ/”J—wÉ’i{ö¬q05æüùª‡z¶µõº8dðà_}õÿÝqGdc‡_À²ØY³’>øàÕî •Ò½¡´Ûø†l¼Eu}»äFþ÷¿¿5sæ„ÐÐà°°9s&–•í`Q­Ç±o¼ñ\LLTP±¹¹ÍÕMÞƒlÏíy& ë5Ûó*÷íòM¶pUÁÓÕ@•<Þ· t÷äô(Ü‚ÀWX߮ѣ‡{°oè®Ûó¤­Þ ¶¡(õ; EN¥¡K‹' ùz6)xŠœâ‘ô«Y£obƒ½¥BdB¶§6ŒâQ’œ‡>\ÜÀ¹=5°y¸ôÙ¦sò`¯Ò=4xuWi¸1ð Ùß쥾Üaäó²9wd3 {à"óáæ?Á%Ø\ÊA—¾ ÂÍJ|AŠî0ö2?äy@J´LTàÁu{üãÃg\±¹¾áÒî€Æ ·C‘“'Μãa’·` :ÇÃÞÜC¶Ç !„·è"­¸ 8Ö€’¤Í·=¸„lV»«½@¢T€çkóü"Ž5àcbªÛ!~“ žҬ ›òî‘ÜP€V;€} 9Ñ.'“à·ûpOW÷9—b?D_D>PxÛ ç Ûó9é%ÞšÙW5³"  òsÒQò{>!Om5¼O"á“ã¼R­.¸[¸aÏûä;§&š\)à B¸ aÏˤ{©æ÷Xœe¯r¦d‚Äz‚›“y~ªšRVgYt²Ö= '÷és‡/@¶çØEÙÐ|‚ ¾ <Ùž§éäL€Ïà&,àQÈöpbxž‡èêgàvpbxž' ɳ ‘ܘÞ°ç Ò}û§"¸ûxžä9Ûz—‚w ìõÎäõ>p v+ð„=×I{¯à8î ”:ÁIº}0 øAÀï)— Éë5=÷PÀ]Zz„= |ÙžÓp‰‚›ó=سÀ‡öœƒÞ+ñÿ·wïAQ\ùÀ A@^"n™‚ºe”1 dÁhi)[b\o劽¦²‰º‘䪻k­ø –•kdƒrñŠ¥aÃJЀ‹Ù¯R«[ˆ¨€Ãû¡ˆÀÌÜ?Nh;Ó0 3ÝÓßOñÇtŸîÓ§ÏÐý›sút7ÿ]ƒ b˜—…N&­>–C \`vx&§Q8&‡ê88¾Àö†crXI«Åÿ‚ä°ƒ…ã ,aÏ8 ‡^Ë'CrÖ –†!-Ï‚cr˜``§l!æE¡µÇÃŽFŒ64½^.OV=ºÆ!楡µ×^±,T»Làg%Xž‡dQèê”!Üö %û°‡ûÐ-‘OðãDCÞaC¨E‘Ϻá ˆ‰\ÞÁoO4ò,‘ÏZa ˆŒ,Gr¢‘`8Ð@”âýOŽƒDØŒÀ¡(*ÖÚ2á ˆy V"îäîž.tlо뀘"&ËNNÂq(bøj¤1Ä­/ìéK,Y аáÊG äà‰Ò‚˜¢'×ÖH†tJ‹µ^šë"âk{ s¸ÙKZó@"ö@¬p'Ÿ´àa› { bˆ|Ò‚ÑÑ { nÖùX<°Ê Ý/ä aDÏ:"ŸUb_¾„=x.ˆv M{ Roð±GŸK±äÁ¸M,„=©G>«!|{ €¤ ìt òYÂÒ‡°’‚ÈgAˆy`ö@jp[´E æµ@ØiÂiלóÀŠ ì¡«ÓœóÀºˆøíêÖç‹!'•·–K¥œý’táÐÚ3#´K†êvø°h‡˜Öa¤ çâმóÀJ‰òíêÖgøÞ¼‡}qÛD•‚ÕAk$Ã[†ª¬ÂH"ßBß&X;„=° ˆ|C1da¬"ß BÌy°{ö"R¡×‹4à‰<Šà†t´öÀJ‰3þ‰bÈÌ …=…"L1ø¡ùÏ·Öó1ç¶Ä°]@Wçà æü µVG„¯hçÛÕó@–,pmO[ãa¸á >X¨1~Z{çΕ«T‰ŽŽAA« ÊøIgÏ–¯qtŒP«Ï+ç' »õêèãÏïíÕnÙòy@ÀR;»pw÷踸-÷îÕ³¤ÆÆ¶„„O½¼b•ÊùþþKRRövvvõ»e¯¼²ÊÉ)2"bSuµF¸ÝsçÊÕêDGLjàà5_}uÙ $gÎ\ Zíè–R[Ûxþü*U∠Þ|ó¿¸ÂÑw-úÈÅe¡«kT\Ü–¬1±fDJ„Íb€á×÷†¾Xyù9s’{{µlÒÖÖæ›ovÏ™ó*]¸p-<|£N§ã’´ZõµÞX¤á·ä„s„óÿð‡ÿIOÿ’Ÿ:oÞ´ââ¿Ñ[o}PXø?iíÚ˜ƒß7È­´´",,…•„ˆ&O¸uëžA©¸¢²Ï%%o¼Ä¥ÚØØp;õë_Oþ׿îtuu³É fþ‰ˆ~ú©núôµ­­¹íz{»_¹r0 Àç™5CÄ{8Î/f&’·ˆ¤ 9òfØÚÛ¹óho¯öرԮ®¢¼¼4­V·kW.—¤Óébcgk4ùM~ttÈ‹oþС¯ˆ('çãžžóW®$¢Ë—o²¤ââ«DtõêçÝÝÏÎÞBD'N\æ°sçQ­V?§¡át]]Þ„ c„ËpeŽ­Õê¶o?ÂO}ç·ÚÚÎæå¥Ñ•+·–. km={äÈV"*-­`ˤ¥ýµµõad䌺º¼ºº¼ÈÈ ­©©‡‡¯f`ˆ‰íºš¥pÛ+ÃÖžO\CC+ __ºº<"òôŒmnn¯®Î;v4UVÖ¾üò z±Ö=zÔUTô}iiÅ×_ÿ³¢¢ŠKš:u͵k•cÇŽŽŠš9wîÔ¨¨™®®ÎÂðòŠmjjÿé§ÿ?Þ—ˆnß¾?yr‚A©îÞ=ÆšeUUµ'®ððpmj*àRkjNøùyuw÷88Dp ?yÒãèÁåãë¯Ñ´Üº•=iÒKÜVÆŒñ¬­=ùÌš!BkÏ¢Äp¶HZ{b¨ K3ÒÒÜÜn0§±±}hk{HDþþÞlrܸÑÂìôz½B¡ ¢îîS6_\üÃ’%ÛZZ:„IÙÙ[W¬H«¨¨:p àÀ‚‘#G|ñŇo¿j°ëxdQˆûiíùùyõ•Ù—ˆÚÛñS}}=ˆÈÞ^É&ýý½ˆÈÁAÉ_¦¡¡ˆ&LðãoeP5ÿ‡]Îý{ˆyD$ìätss!¢††Óz} ûëé9Ï’<<\‰¨ºú›¼{W#Ì®££“}¨©i4eóë×g´´t$%ÅŸ=»£º:—Ÿ¤V^¿~¨¬lßæÍ ‘‘3:::““3„9¸»»ð SUU+\†~†¨°áØØØ™d¼½Ýø™³£Gb“¦Ô XnæCÌècxŠŸ5ë"úä“Ã]Ç—(aju"Kš=[MD6쫯o©¯oIIÙË_‘…Ÿ={ò?~RUU›”´Û”ÍWVÖѲeóæÎzüx ›Éƃ88D(aÕÕšmÛV¥¦&’ •Ƽþºšˆ6mÊljj¯©i\·î/ÂeÖ¯ß}ÿ~Cssû¦M™ÜŽ Jxøt"JNÎxð Y£iyï½=DÄ]Ã3^3†˜À§g}m» 2lm sr>fIååŸÙÙÙró•ÊŸ;HYêòåáüµ¸NB–:Ðçùó§ó×bͦªª½¾dñbÃþÌU« s(-ÝÇ/pHˆJ¸-®¨Ddgg{ùògÂ|ŒOÞ¸‘åââÄ/Œ¯¯GmíISjF¯/Ñ?­g°î[0ÿaÁ î5€(¶öBCƒOžL žho¯ ðÉÌÜÈų™3§œ9³]¥oo¯T©Æçç§óWÌÌܘáææp߀\Ì›·ÁÒE°<„=)½Ôî‹òK®†:9A¤Î+W©#‚‚V”ñ“Ξ-^ãè¡V'ž;WÎOvÜ Ô•ÇŸß۫ݲåó€€¥vváîîÑqq[îÝ«gIm ŸzyÅ*•óýý—¤¤ìíììæf$¶¡Ó§ËTªDÃ2O5²#……ßM›ö;‡Wרðð·oß7^ag©A†7nÜY´è#—…®®Qqq[~ü±Æ`Óß}w32ò}—…nnÑ+W¦77·÷[N±ÓˆÑÏú½¾äÿÈ´³³åþKmmm.^ÜÃ’JJ2llløI}ÿÉ%\ó…}hŽpþÖ­¿58.æÍ›Æ’.|Í iíÚanFr`“JåÓž[[›²²}¦§ ?—•íãvœY´èuã%1˜iaUUŽ»» oo÷»wñ7íà ä/°tiØÓxúõˆZ{ F;wííÕ;–ÚÕU”——¦ÕêvíÊå’t:]lìl&_£ÉŽyñÍ:ôåä|ÜÓsþÊ•ƒDtùòM–T\|•ˆ®^ý¼»ûïÙÙ[ˆèĉ ƒÊY°`F]]žF“=K«Õmß~ÄôT¡;ŽjµºwÞ‰jl,ÈÏO'¢o¿½n¼$ýQNZÚ_[[FFΨ«Ë««Ë‹ŒœÑÐКšz˜¿Lhhð­[Ù²ÈZTô½ñBˆÞ·âÀ½³F_BD>>q ­üt__ºº<"òôŒmnn¯®Î;v4UVÖ¾üò ê;­³^;þi]8§ßùu}_ZZñõ×ÿ¬¨¨â’¦N]síZ娱££¢fÎ;5*j¦««s¿{0PlCwîäŽ÷´Àžž®&¦ wÍË+¶©©½¾þ”··û`KÂí2Ò×7^£i¹u+{Ò¤—ˆèöíû“''ŒãY[{’[²²òè„ ~DÔÖöÈÝ=Z¡PètßôÕfØÏp>ÑÃ#áu£ÆÆ6ö¡­í!ùû{³I- èõz…BADÝÝ=¦l®¸ø‡%K¶µ´t“²³·®X‘VQQuà@Á#GŽøâ‹ß~;Ôô˜—^úEÛÚ™ž*ÔÚúˆ<=]µ/F44´‹jD8†xuΰßDäææLDøÅ …NN#77"jh8Í]=êé9Ï’<<\‰¨ºú›¼{W#\½££“}¨©i4esë×g´´t$%ÅŸ=»£º:—Ÿ¤V^¿~¨¬lßæÍ ‘‘3:::““3•à 9aLØ^˜˜*Ä®ÃÕÕ5?GIúåííFDUUµl’}=zþÕVéBØ1š5ë"úä“Ã]Ç—(aju"Kš=[MD6쫯o©¯oIIÙË_‘Ń={ò?~RUU›”´Û”ÍUVÖѲeóæÎzüx ›©ÕêˆÈÁ!B¡«®ÖlÛ¶*55‘ˆÚÛûiŠÉY¿~wMMcSSû¦M™D4gΫüÕ§ …„¨ˆhÇŽ#?ÉË»¨P„.fIØ(˜š…mÁððéD”œœñàA³FÓòÞ{{ˆhH®›ˆŽ…‡Ô0¿ÉyáB†ÁHÅœœYRyùgüf7’¥._Î_‹|h|`äüùÓùk±ÆVUUŽ^_²x±aæªU •›coÿt¤½½òÊ•ƒüLŒ§ ?ûí^ƒúÙ¾ý?žY®—ò7¿™máY..Nü}}=jkOš:>#9A:ÐÚ1 >y2-8x¢½½2 À'3s#ÏfΜræÌv•j¼½½R¥ÏÆ1r237&$D¸¹9á\T´«ßüõz=)úÆÑdemމ qrr5jä»ïÆ^¼¸‡ˆÒÓ¿$¢Ã‡?LJŠ÷óó²µµññµn]Üþýý<ëÄHLaáÕê@{{å´i“ ÿ8}údþêÆS…Þx#(??]­T*íüü¼¶nýí,fIþüçÿôóórpP¶·wd8eʸK—öÇÄ„8;;º¸8ÅÇÏ)+Û7fŒ§ñbHFr‚8ür$ç°Òju7oV­vvv|ø°p¸77ÐPRSR%#9A:ÐÚÙY¹2=(h5©T–. ˜n`Ù©¬¬Q*í¦L×ow%X7tr‚8˜±“†:9A:ÐÉ 2‚°2‚°2‚k{ ܵ=4œO@ôÐÚù‰;gkÃQ«IEND®B`‚jas-2.5/images/edu_jas_classes.gif0000644000175000017500000000554107773340004017437 0ustar giovannigiovanniGIF89aUñïïïÿÿÿ„„„!ù,Uþ„©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡D`àˆL*—̦ó J£ÅªõŠÍz‚®÷ ‹Çä²ùŒ.Ú¶û /rÓôºýެãü¾ÿÏ2—7HXˆ¶˜¨¸È(!hYˆØXiyÙ÷(¹ÉyȆ *:Ä…Ô)–tj¦9F9ú sÆŠšg«Ú•Kæ*û  Bëeªwll¬÷h*Xúõ¼+\êìL=—\|ý)ü îx\¼];Mž-ÍML«ž^>M\N.ì-¾Ï/þnϬÝ6òþÝ{‡p—¶èÔ×/¢DX×Öû§)¡Aþ‡Ñ5œwd¾‰$K‚ªXñ`½YÆSi¯%F‘ê|™¼‰“O*– .³–2ÕÌŽ==îĈRÄœL›^áe(¥.I6Z½ê*.zZ§â©Š5¬X]½š½v¬Z@SÚºm»å¬ÜHiY‹WKÙ¹aêNØË7pߥîæ=üTp¿ã;ö´ âÉV+fá­æÍœ;7Ñ'™²h9!w€:µêÕ¬[»~ ;¶ìÙ±ï›Té3˜o*É ÜÃM–ã `7tðå6 'Ô'òI˜[‡á|Y9wÙ¸rù½;4Âa§GV~=} ©ãe¤­½H¥ˆo3¨®>ÿfþ‰þ¤ @ÊD×”yà§_‚¼LD=¸R1ä©e`fè)ˆá}ç4¡ƒ6HŸhþua†vB}'`„N¸Öˆ hb‚ÅñFŒ1nQb;ÈÉjèècrö)Ö‘Ôí¶ ‘H¦ä“NE €s(e•=féÛˆVÊ…%—Ð(¦I~yV˜e)ãšûÜæYœm9é¦dÖN´íéÚ|®†gwŠIcªÐ&¡- ª(†ž‡(•ºÀè¤F0áH¢#li)vœv: ¦HJr¦‚šC¥¨–ºÄ~/œªéª¡’*댢Š@k©‡VY+Ÿö e«)äºÞ®±+þƒª“>új²v=‹lV¿JÉ,E…]í¥Äªw+8~›-ÊŽVm?gRnãbU®oèb›neÓNÔ®U^*pl¼?¬ L·¹å«ïSóZR/sœ¿Žú{"•(,DÁHìðÂÛÞ ñšW¬“œÃÕëÆǦYjº)òÈo”ìÕÉ«|“Cf›2ÌzÉÜ ŠÖl3,Oår™<÷\ÙO> ‚â^ÎèLèÐD“fTT-­"!ÍO7žEâ5J­´˜N_±‹ñ9äÒG†ˆìØd õ=Fw=ÏB*2¨Ûogåâ| ú Fxã©÷Þ¾ö-÷ßÞÐàun¸YËþý_O(z¤4A9Žräü¬KØ\Bî9Æ8·ÂùË¥ët:*© ½zÄù‚®ŠèY’» ŸÒ~ŠíÔæ.G”¼wâû“¸?ì™/¿Äëb#¯.NOýjÇ›x=ô¶vÄÅ„kÏêò÷Éî½êIzûñå;kêú¿——½¯¯ÿ¦¼&jý—¸/œ;è«]áoYö  <£—Ê@ J2 "Øbí)ðÊSø—)̓5ª Ø1 l&' ´_ h&|½e2%4á wö?æÉ à¾:ÕB /HÞà ád”üÑN­3k6ðE¬a†(«DAñ|’kâþxî3Åpeñ*[\’w#®®‹bâÜa´ì ¥jB¢#šfF©ôqÐa£•·8^äkSCÆv2ǵ@Ïd”Ž×Á8£œm>$!¿WÅ3®?‰A–vÇa<îiK4ü¶!´9òŽ…$I)«„¹I~Ò“«¥ó2yCØE’ôÐNÑV9Irå•°|×èÌøÅQÂò”ü8åsÔËÞ˜Væ0É`ò2™¾œ3›èÌ^Ó[×,b6µi¼ÎyÓ¤f,}DÌê©“zæÔ:Û™ŸmþBžðÜß;ë™zZ ŸùÄ?¹Õ°öSAúèÃjP€ê§  eCþ ÖÐ*4¢Öy¨C)*ÑŠb4£Ë±èFáÑÏ}”£ÿ)IÉeÒë„T')UiG[êÒQŒs¦S€i EqLÇ|Ó¦" EN/SNž4f_DKP…:ÁBÕ¨H5%Q—J‡65JU]¶bUÞuª‹X©jù¤EŒ\uêÃhÉ[Z’šû£-Sùµflµ¬|xê¦Åáƒ#¢leܤJW–:´!v#l‡D9 ͱ(s ,HËHIVE}Ye(ÉêXzu•'‰<,(7„9š46³=©U + î$àY,×jYŠÑ’Ö^ý UvØÙ: ¤·-Mnu»2¶@u1².Uiþ;ܨ׸‚e]rMÃ܈Ô6‚Ï…nt‹™ šj× Ë½înù°ÎðŠ×5Þ•ÈtË;²ó¢·bê]/ÂÚë^}Á7¾éš/}£eßû¶M¿ŽÍ/kåßÿ®*À¶`§Jà/QÁHM0ƒáø`ž:8›¤0L'laYfx¤Þð2=Ìa‡XÄí0‰ïy√8Åe±AWìbÅ8¡0žñDmŒÏãX£;Îqë©ã'ÈBÆ ‘‹,"$›óÈJ®O““Éä'GÊ™Œ2•Çbå+—GËär ³ìå)…|`³!ÍŒ¼2£ù¦kŽšÛ¬Y8QÎs¦³çÞlgä9rxÞ37ýüþ¶>:‚ô< }µB#úŠ^´LݳFCú$“†™¤+ QLsìÒšîj§Ùûi‡q:Ôl!uÀFmêã¦Z‹«®o«­öjüÆZÖ³ªk0\‡L׿õ€}ýk`XØ–º5±#vìb'…ˆp³!ùlhG»sÑÞîüÞdílC̽?…ÄoS]­Z¸ÛQénÂÂ-n “{æöº›4î¥~»hïÎY¼‹:ouÕÛÞê$ûx åbû(R;#Ž”@Ü{f&¡­u•HTJÖÑ"8jx+0áÀ¶5ñ#kŸá5·ÖEŒ7»+[ßzZŸlíãzk^ÝÑn›ªq#Œ^'‹IþHQD‘ø œd=NÙNÎ#æäbÙjóJe#K!ùÊþjX Àç’TlP0þ`šßUk@¥™‘7kátŽ*[.Z…û•³Wg¥Ù¯8&<àkë,מ½gOÛáÁt-y ê­]úkûÂGŠw?y7麡£íÈÏtߨ»·4ÿÇ_‰è-Õ<.z(wÊ»ÎòÍ »š=Ÿ&Îë]ÞOœ§è˜qÖc1¨7™ê/ùÍ„1ʹÏöíM:Þà¿F‡8õ“ð¯ÎicÍØÊ'‹Ó›O™çC¿>ÒŸ¾™oýWU?ûÂ>÷±ýïÃOüØ ?ù x~ ,ýäò>û×cþ÷þKÇýòÇUüë_’ûãŸ^úß¿téï€øUýG€þ0€(B¨€™—€ ¸=hd(T"Bx ¨‘û—2ëׇf+#è.h‚l¶)xfvÂ,¨j³ƒ$„E¨@dƒ¨<9¨ƒG4ƒ\¤%<˜‚ÛöƒÔ{#wDX„‹"{$‚Kˆ(M…PsySH…¥g…WˆM¿—…£R9 6T“×…£Â ÿ¦x7†\X†VÖÀ8 gˆrtȆm8”ÔqrèGI·5Ò x7«%‡6LJˆexq‡‚$q؇tøsÑÀ!vĈÀtvSÓW>—s•(=NAñwixt{$8œx8ø¶ˆ¤ˆ/RˆŠ¦cŠ«˜*ªèŠd‹±˜,³H‹žr„sr‹6€|½xŠ»ŒÁ(Œ'P;jas-2.5/images/edu_jas_poly_classes-new.gif0000644000175000017500000000463607774265702021311 0ustar giovannigiovanniGIF89aCñïïïÿÿÿ„„„!ù,Cþ„©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×¶äúÎ÷þ ‡ÄÝíh**—Ìe$ ˆJ§ÔªõŠÍj·Üh`€ ‡ Ý²ùÌýBÈè¶û‹ç6üŽŸªö¼ÿ¯µG7xÑxØ%Ø`ˆØè§HùäH(çÀX©y)éɹ騩jfš†ÚHúÙj J›•CÉŠ x‹{hëêÉ+¹«éûšG•LëŦ¬ÓlÇ,<{ù‹œ,-5ýÌ íí\m ˸MÍÍξìU¥ïn…kŽMg˜>O+¯o?zâ]hZ·ô¢ùÓpÜ7…ÔTÝÃ'†\þq ý‰sQ^E±¾\ŠâºX Aøïe=}¦.bDò,ž¾–ÞXÂdH°¤Na'K%ÜøgP—eJ,i±èMB$Cölºô*Ö ¡z“z+Q=¥í>jÙìi;§–¦ºÚpkU¦hWv]{Ö ØÕDùµé¶F_¿mÌ &\ pà‡—1ì8²µÅÀ$×Ú{̲比%5Þ¬ ó9Лw~ñ™t,Ñ©U»1}ºEk×D×ÐŽ ;öŠÙ®!ßFœ[w Þª}ÿþ+Z8 â¤ß\y’çoŒ«ôYØ¡.@ÃjKǙ躮wûþø7{ٱн¿AìTÞêqlKƒ·Œ\Ïwjþ]&© DûåäÎɽ·ÛéH“ß]ú•àB“ñ±1¨ÔC1`G9¡·MtŽ¡`\2%Ò‰îÂZ…?Q]ÿ˜Õԉˆ#~`‘‰Ú­Œ6*Øâ}@‚˜×…Wmx#V6ê¸c=ú„ä‹Fn$罸—d‘å_“C*s`”Ó•øR•G¦I%Wõ´˜ÖYÑ(!ãhfœNJ ”fj€ÎDV !ŽJFeuÌô§ ‹–çq®Öh “Zæu—Uºœ¦…Eêé(er Â¥’ej/£’ŠCª§€ê*w«²ZG¬‰°ÖD®ºîºÄ¬´Êk°ÂþÜÆ‹þl²Ê.Ël³ÎðųÒN«Ã¯*L‹m¶Ún{,F¨Ðƒµâ §Ìn|U;nºS•»Û··¡n¼žy#›»¥ +o¾G8ƒðê ° ¡f¯¿9Œ0 /WÁ¿ ?\k<–<_ܰ–ŽRÜ0¾l”.4p\ˆÇ _Œ ÉõòèðɧlƒÊ´ìò¸JÄ,s&׬n΂)L3ÏBŸp0¸;ô>‹`qÒNó8qÑOO]2cGSím68_50øH½õÒ]ãtØðq=6|n‰µÙ¥¦ÛTɽ±ÛuÀmØá~B÷Èh7Œ7§vÏý÷ ^vá >ó×}gô"3þþJâ”E^ åy¯æ•k^q`ƒ¯ô䛞Ñ{£ž6ëaŒ~ÚÞ › ûbÃÞ~óì#¸žÛ¦âá§î ÔÎ7׿ß¼ðï+öñp$Ï·ê¼Gâ|u¾rŽàôƒTÿÚõëîH¼·PM9ðÞ—M»öౕ‹›éÝÚ¨ú­È3vþ%…£€sF¨ÇùYÇO?Æx…y* A ¨ÿ)¯—Ã΢‘-ÉMÐ[àˆºh=tÙ`—8cAaXÚÏñ“$™(©!d˜øB‚?Ž,EPù£ µ&®ðeD>À¹á/Fˆ¾ò0ôL¼tO‘zùBâÈ”è÷¼¬2šZ"þUæÄNU1Š-„ÚöpÆp±‹8b¸…Æ4v‹Œ¯c£ãfÆ72ðcY”c âø<ÚÑp.«ã½X3=þ1sBóã 3 ÈòÊK$#“¶ÈGÎΑ’,$%»xÉ?eÒ‚›L_%HV²“•"%åL ÀOnNs¨TeÂDéÊP¶2–Sä#-Y¹´Y>L—¿ò/öKZÁ.˜ú"¦0ÁHc SeÊì™}wÈfZ‹cÒ¼e”ôfͬšÙŸ»¸ÙMožcàÔ¤ÞEÎdÊÎå”WßÙÎÝÅ’{Ÿ"U<{E{Î3Ÿá¼&?û©ÈTuùŒxÊ÷¦¡<¬ üþçJ#Ý …’ ëÄ?÷ÄoŸrâyV”¦1éI£šäèé4$ Ì(FzÑgDRÂ=ðƒ£_ÚQª”K+Ä‹ˆÓ>¤!#eÐ\(¥P‚n1©JU”M™º>§BU:ôDÃO™Ôç\õŠY•ÔS£Qx‚ñ«^‹¥Ϻ-—N•ybm«[s·Ö™ÙŠ6[µfUçª%²†ó®xMh\Õ×æèµ›| , ÿŠÈ‰j‰>> xˆÓºÞ²§lèƒÐ„÷õ‚¤ˆ¥@‡Ò =­È¨¢ í]Ž”Ñ> ?2-™:· FDEbºh U£9éCY!à`³ùY¢®Ô#³¥(„TþT\zˆT¦â,l'q¥Æô¶Æ].u•[[™†è·vÝé—•ÝåJOὑdiyÙ M$Eëí-Zæ4žÖ¹;ðísó¦(Æn꾞ͯzÃÝÉRüíï€1`ôÁ®Ø‚O•ày¾uÂöA„ÍŠV´F+ÃNkƒúá§±+ĉKì…_*d,ZÜÇØŽõ˜1Ê4fãWâ8Ç/ {<‹7±B~e‘AvÏ#ÿLÉ(cr“¼K(GYÊÀ¤r•­\K,7QËÅäò–½|D0‡YÌéJ2™“pf›¥9‡kžf›{ùæcÆY­sÞhKyg<繤{¦]ŸýüþgðZЃÎ^¡ }è<&ZÑ‹VŽ™ýH“KÒºy4¥‘yéÎX:Ó„ä´èL·'mÃæìh覆Õþt§±ýíæÃ6Ý>>¿ûÝïz÷î]]]•““S__ϻƲ޽{¿öÚk‡ª©©ñôô •WºººŽ5êǬ©©éÚµëØ±c›}¾—¤¤$­VÛú­B,ÜPw§ÝišÚj†aîëÝ=»ö~ÁÊ®ÝlÕ„«îŒÒÂû_{o~ÿmìa9ò9ü®æZšt»¹õ8wµ6RJyžOHH¸|ùrhhè³Ï>[QQqÛdÕ6gYö™gž:th]]¼Ð”RÊ0ŒB¡7n\```uuµ‹‹‹“““\¾•5@Dz¶¶2dHFFF~~¾YŠ”öîb—VÂÿ”]ÄÞÿñÌíÂë9O¦äΣöÎc^uzzbÉÎÏoäÆîžõ%ù¦Æ7ï&¤$Iò·À°,kz!¨1NWWWgcc£P(ºwïN¡”–––²,ëîîîææÖ³gO9.Bêêêä;¨ð€Y[[‡††äää˜=&¡¤²¦î»tM«Hh+ÇÀ1¬¥µ6ö°^W¡K5¤[{ú8=5¾*-Îx¾Ð­WUÊYÓ‡avkÝÝÝŸ{î¹.]ºŒ;ÖÞÞ¾5›h4yQ¨q¢‹‹‹———››[]]a*!DÅK—.ݸqƒB€Œã¸ÁƒWVVfff6;íÕò¼•|'7«kkêô”£7TtðÅüWOPú«rŠÖÂJjaÙß,3lذ¾}ûrççççááqåÊ•{ÎÊó‹™™™¡¡¡]»v•W²,kgggggG)­««E±¾¾^„Ó§O_¸p¡õs³Ð!X–2dˆ¥¥e||¼$I,Ûx¤$GÁÞÁÄÊ4É»÷=Òä‰ý¨$?o"«Ñãe?ü÷æ‘TüUúå™OQB‰É8ev ¬®®–ø«««kýauuõÏ?ÿãêêêäädoo¯T*å^–$©¡¡¡ººº¢¢¢¼¼¼¾¾cA€¯W¯^={öÔëõÏ<óLK×a9½Q®x»¦<á$kaÙì÷HK õú{½z‚ŠÍ|áKKY´¥¨F%Úä OM˜=™igg÷ì³Ïöïß?666>>Þôû›ße #kÄ?€‡ÈÒÒ’ã¸{.Ú—ß‘ÐøŠÍ0-úˆ¿’°-«zX–e†RÚÊ'àÑÁX[[?ì6t¸¶|é6!äíUß9ØÙvlSLÛ0ï÷R+Þ¦`óÞGhPS[§Ñ6B aî¾}ØS?R£ȯ&w·5Þ°QÊ/‰ô;<à7«J’$"6Ào^›¡H%¶c›ðàµ}Dhú…ò.v–”Šêº{V¥êáXs»¡H[Ó¶–´G[!•¨ÔtòOþÈ ìÕå³??­ÅßœK¾QNi³“„2)¤ßäßùV×éç‡/×Õ57eHŒ>t°6ÞÞ”$‰J"•D*Iô—Ÿå¢‡‹©«©Þðùì|-ÌÝÆÅD*‰}Ül_5àæ'Ël„Šb“2¿*ß±‡ kÏ­Ñæ³ºØXø÷qªÓKœ»»eZÒú©£ŠµUra‰Rãª>n·öì²3¦¤B7ØÃùÔå¬ €¬=‹eš¹ÛimÁýãµçÂU›¿!”j££­GŽt·´$ C†ÈwH†aÂ0µUUõVAA\FÆœ7Þ°µà~HÌ¥Tjî‰ €û¢P’$"ÝùÙ ,ûá†9Ý,,ýËlZSC!”Þ¾z•ˆ-ÜØä8¢×ߺpr+6ö­Ï¿àúý…ë”JÍ—èhmœ#¼;5(QI"ò©´èe?±¦dö,}uµ(I¢$‰”ºóÝ”)"¥wRîþ³{ã ÷}ûD–•?VŸ9S<ç/“‚ûMÙ‡Pj\ÿ½Ü\Û6óùü­yÂB)¥³ž<¼›MéÛSÅòò;©„PBê²³k“’¤[·Œ)! %%µ)) EE¿¤ÞNNœ9…cIz^!’\³¬0é(¾^:\ÛˉæNlúóï{¹Vüu±Ä²LwR)%„ÔB77"IÆ3Š’(Öåæ’®] % ¥·³³K-·zµRÁDýœI)}0S„ááá}ûö}ñÅÅ–îâÀcªÍs„âÑ !¶VÊgüú(m¬º‡‡wÀ aË>?Ôk\VUM}+ŸüÇ?þñ /0̰YYYYPPðõ×_Ÿ;wÎôƒÿ2µZíëëkØü™Ghc©˜5vøP÷. Cº¯YSü׿ÖÄÄ´y\hä¶j•TW÷b`?¯îŽ«¿¿]¯—g!ï †ÙºuëáÇåx0hР~øaáÂ…ááá·oßn[{ZÃÑѱÿþ=zôhÛæð=‚a˜/¿üòèÑ£r &üç?ÿy÷Ýw=ŠûºmÐæo–¹ó…/!z ¸U–÷Ç×®=óÌ­”×åË•C†H #bî?eÿþ.+VÜJJÊ}å•Üçžóª©ØP‘Jb+¨$I¼+---99ÙÉÉiРA Ã|øá‡Ÿþ9Ëþr¼ÿûßׯ_oœÒ§OŸÕ«W8p`Û¶m¿ûÝïŒC”½½ýûï¿ÿÍ7ßìß¿åÊ•}ûö•sÿþ÷¿¿òÊ+,Ënܸ1$$DNo©|;¢iï¾û®²²ÒÃã••@#í}|b˜OO݇Ê˪«µß}'ÔÖ»­Y£ôõF$¤õÿ*•Ë_èôTûÝwõ<_¯ÓiáÓ‹H´mOPJmll(¥ååå”Ò—_~ù7Þ0{/½ô’q Ã0û÷ï饗zôè1~üøÝ»wO˜0AŽ=®®®‡ú¿ÿû¿þýû»»»OŸ>ýرcAAA à 8°_¿~ ÃtïÞ}ذa®®®¦Ë·ó(šðóóëÒ¥K^^ž¹5€¬­Þ*Œ¾¶FÒ髪êõúrœWý[9p`ëÇ…Š¾}]¿X8ESWß ¯­5Ô¦ä~Ù‘Yͳµµ}ï½÷Ž?^ /[m2 Ø(…a˜S§Nùùù¿óÎ;Ç-^¼X“ü±¿¿DDD@@@ppð»ï¾ëää´jÕ*–e§NºfÍI’~øá‡'Ÿ|òûï¿§”š(ßΣ=÷Üs‹-Z¼xñgŸ}¶k×®’’’eË–™;= ²öÎJ’$ÉKH) ‘Dñûs™’¨éß«Ë/ªË̤”š)½¼\×}þã%ÍwqYO òEQ¢”P*±¬$;[=ã¸yóæ/¾ø‚a…BqâĉY³fµræL’¤°°°††BÈfΜÃzKooïãÇ/X°`ãÆm¸mXQQAéÖ­›!äÖ­[ƹUUU„++«¦š[¾ G!Š¢^¯—Ÿ#ܳgÏíÛ··oßþöÛoŸwî\Ó,yóK—.g™.o¢…¦¢ÙÐí#4]Fbî^¶)%éDÒu‰JÃxHwC›$ŠkÞSóítÏ™(`nFi¾¶?G(IÔ°Æ’RÊ0Œ|Ýÿ%QEæ—åž’$I¢^"T~d^¢$Q"RÚL ”ë$'p?µãÖ诧 ?~¨½]GºXÊß—F8N¢´®¡^%‰ªTJz=!„r\mm=•ŒfÅŒ^cÿKý…p´÷í&þ¥dåsýp={Š„Ø?ÿ|þM¡‚¯®ÔݺV\nûÌ3"Ë*¼¼”ÞÞi9ò÷ÑÜùG›«­uÔ˜«s„F÷_FmwRøªš‰WC—}¢¬­Ñ2ŠÏ\’D‘z,>ã/Žõ|饅òÄååÂ-ú«¡óë é@ÇkããCžŸR]wïÈÄ0Œ¥×˵«¦¸B÷… CX–õìîTR©«½ÝÐÊ)Àë§wb²:\Ûç[•(%µ·ÅœüRúëDI’®”!¬ÀCמ[£­ dÍ–C€GA{^Ãd¼€¥Ù[¬´IzÓ”Fé-¸/Úskôê0‚€û¡Ã/†atdÂJhfØAÍÃnÀC£`¸6>Sð` ÕT*ôñÏ-Áy÷ û°!\­à~Ày÷ !tj„Щ!@§†@!tj„Щ!@§†@!tj„Щ!@§†@!tjŠ‡Ý€GŽZ­ž?þÿþ÷?A&MšÄ0L}}ýµk×¾þúkABCC_ýu†aêêê®]»©Õjv“áa6lØŒ3Xö—¿)¿þú놆†wÞy‡eYI’ŠŠŠŽ9’˜˜H)íիׇ~˜žž¾eË–¥K—vïÞݸ*Fó¯ýK’¤?ÿùÏÏ<󌅅Ejjê–-[´Z­a/’$•——ÿïÿ‹‹‹£”>ðÃ…ûÎÝÝ}Ö¬Y>>>·nÝ:|øðä_ôŒ3BBB†ILLŒˆˆ¨««ké¬0>͆j8?AHLLüæ›o(¥Ë–-köôëÞ½{³{‡ÎåÙgŸÕjµüñŒ3xžÏÈÈHIIÑjµgΜ±µµ}çwäÄÔÔTžçÏž=keeõ°›üÈñööî?srrAøê«¯X–möôëÖ­[³{ؽܳÏ>ËóüÒ¥KgΜ)ÂÌ™3•JåêÕ«yžñÅ7nÜ(“O>ùØÿÏi®ÎpÁ2˜8q"Ïó7nT*•ÇqÇ0Œœ¸eË¥Réãã“––VRR¢R©|}}yžß·ow×'Ÿ|"œ9säÍGŽY^^~âÄ ŽãÖ¬YÃóü’%Kþð‡?öâççWVVËqÜÃ>úª3œW“&Mây~ýúõJ¥ÒÕÕ5''çìÙ³£G®¬¬üþûï-,,8Ž;xð  4>÷ŒÏŠÁƒN3ã2¶¶¶'Ož¡ÿþ …¢éé×ìÞ;Ãi†P’$‰¢¨Ó醡”Êw $IR(NNN¢(–——?ì6ÂçP(<<<<<<\]] ·’(¥¢(fggÿðÃÖÖÖO?ý´ñu\EQ g”ü188X©T9r¤ººZů¾úŠ`\aee¥aCxÌh4I’ž|òÉçž{®¼¼¼ÿþ¡¡¡C‡å8îäÉ“z½^ÅU«V-Z´èÖ­[ò&­9+ä2·nÝ*,,dÆÕÕµÙÓ¯Ù½‹¢øàŽÿ!A ¼‡yóæÅÄÄÌŸ?ÿþýÇ—Ï›+Väåå;öСCYYY¸$Áo¼‘˜˜˜œœüÕW_5ú šR*ÿµäààpÏz\\\!‚ È )¥NNNr}î¹çNž’$)00ða·¾¢¢¢èè訨¨'N4 N¾¾¾ Ã\»vížqëúõë„þýû˃ƒƒ !FÞ0..nÊ”)òz®?ýéOý„Y'ôÎ;ïìÝ»W¥R­[·îé§Ÿ.**zá…4 !¤_¿~r™O>ù$%%eĈò К³bïÞ½>>>¾¾¾¯½öZBBBKça³{ï §F„÷ ß[/..f¦k×®µµµ„¡C‡Îš5+00㸜œœ‡ÝFxøúôé3sæLùúròäI9ÑÓÓsöìÙ~~~/¾øbrrò‘#G `ºžƒ.^¼øOúSIIIYYÙ‚ äå|äîÙÈó¼V«uuuí W¨Î¦¡¡a̘1ööö®®®ÎÎÎ7nÜøñÇ—¡ŽËx IDAT,Yòúë¯ççç×ÔÔLž<™ã¸«W¯öìÙ“´î¬ ”êõú{ìšÝû}9ÎG a«äææJ’4pàÀäädBÈ›o¾)I’¼.ë‹/¾xìïÀ=…††>õÔSòÏsçέ©©!„<ùä“!!!åååøøã w8Mày~îܹ«W¯þàƒ†)-- ;wîÜøñã‹•––ªTªÀÀÀóçÏãîèã$22²_¿~S¦LÙ¶m!$;;ûƒ>(++›;wîgŸ}öé§Ÿ²,›ŸŸ¿téRN×h[ÃYa˜Mì½ãúÖ1 £P(X–eYVþ¡i¢ž°iVgXæn ŸÆ†1Nä8ÎpžÈ鯫iŒO3CŽãT*Õ!CšžrŽãä=À}ø:ÉyŲ,Çq èÝ»·ü4¹{VôîÝ»o߾Ɖ͞ƧY£2M÷Õ(·Ù½€Ù:Éë¾’/g»–Nu^=Ü#í<ý,íQ€Gnxvr÷èl§îì@§†@!tj„Щ!@§†@!tj„Щ!@§†@!tj„Щ!t¨Îöx0p^t<ü…¿þû¯1Þ¢  §üf0œ:Ë@§†@šÂnð» 𸩾o§A°Æ:Tõåø‡Ýx<)|V|ó°Û›ä }½—ïÂ\t¬ä }vàñÄàjŽŠzœWÐáp^t˜ÈÈÈpGùôÓOOœ8áëëË0ÌClÒ#Ò ³wãc <<üرcÍáÀc€5«tHHÈ¡C‡4MaaáÏ?ÿÝÒm®FWðGdðˆ4£õî+3®G#FŒÈÏÏ?|ø°(Š„„„„ÔÔÔáÇ»ºº–””Búõë7þ|//¯›7onß¾Ý8äÌœ9ÓÏÏoݺuׯ_§”†……Y[[GDDÌ;W­VWUUEEE?~<((èí·ßvrrº|ùòš5kA0ݤ°°°êêê£GΙ3ÇËË«²²2**êäÉ“”R9ׯÆfëÖ­‹/vwwŸ4iÒôéÓÛÙ ''§Ù³goú jô+Óûôé3{öl•Jezs€GKEEÅ™3gŒÇ;wîÔétAAA èTªŒŒ ARSS ‹ŠŠ C™]»v ‚"_ÖÏœ9“ŸŸŸ˜˜˜”””œœ,Bqqñ¼yóòòò®^½*‘#GâÌ™3W®\IKK»xñ¢V«---?~¼ñ^ä!È¥K—8Žkg3úõë—””¤ÕjcccãããyžÏÈÈðòò24Æxwÿ÷ÿÇóüÆYöÎDì¿ÿýožç—/_nHiÊt7ºººžûŒçù¥K—²,+[¹r¥œ5yòäÊÊʳgÏ÷Rë;ÁtŸ7û 2þÈ)6l7Ÿ8qbEE…¡14Ó0'''77×ÞÞ^ÎbYÖxr«iâyÞÂÂB.ìëëËó|zzºR©”S,X BXX˜‰ÁSÓz†ùé§ŸA×%ʹÆkDÛÙ Ÿ'žxÂÖÖVÎ ày~ß¾}†K|£ÝíÛ·O§Ó=ÿüó ÃjµÚŸ~úɰzÈÇHïÞ½åMLt£R©Ôh4ÙÙÙ†æ 0€çùèèh+++F“™™iÈêÖ­Û¹sçV¯^Ͳìõë׳²²lll ½tðàAAä_œ¹`ºÏ›ý÷‰œbèC†aä@k¡<`³fÁÍÍÍÅÅ%!!Á0)ebÌÀPæêÕ«”Ržç )rµ­Ù»a+Jé¥K—|||äDC“ÚߌììlOOÏyóæyxxØÙÙY[[³,k Mw÷Ýwß=ûì³ãÇ?~üø„ X–ýá‡äÊ—.]:iÒ$Ã¥?&&f„ ÎÎÎ&ºqàÀŽŽŽuuuqqq†D–e{ôè1`ÀGGÇôôtCùÒÒÒQ£FQJèääWgè¥ôôôÐÐÐ!C†ÄÄÄ˜Û ­éóFšþ Œ“––¬R©Î;×ìæ÷•°¥å z½ÞÃÃÂó|ÛQ__ßì¾L›%_µ»uëÖ†áÅ=›1}úôeË–BRRRªªª c¦–ìÛ·ïã?~ú駆yúé§kjjvîÜ)‡èèèóçÏYRR"I’én”Ÿú¨¬¬”c•œ˜™™™››+gÕÖÖ——×4ÙÙÙBnݺeœUUUE±²²jC'4eÜçmXóÒÎÍÚÉŒ@¨Óé=ŠÞ¥KJiqq±N§£”:::vtóÌæììL)))éðKªR©üàƒ$Izå•W’““)¥ƒ =z´‰Mêëë=:uêÔ)S¦¨Õê'N”——ËY±±±±±±Æ…)¥¹¹¹&º±°°RZ^^>mÚ49È6tww§”ººº6ÝJ£ÑH’Ô½{wãDwww†aJKK;¤—ÚÙç...„Žj €¹Ìr]¾|ÙÓÓsذaò8ÆÍÍM­Vk4FS^^^PPàëëk˜ërvv~0_àÂ0Œ<’=õÔS’$¥¦¦vøŽœœœrrr’““õz½(Šò›é­¢¢¢$IZ¼x±B¡Ø¿¿ñÅF!¦»±   ;;{À€ÞÞÞ’$‰¢(Š¢•••$IYYYjµÚÛÛ[n’¯¯oyyùöíÛoÞ¼™‘‘1hР!C†ÈY¶¶¶£G®­­móC íìs†aFeèºQ£F‰¢˜’’Ò†–´Ÿ0""B’¤ˆˆˆéÓ§Ož<9**ÊÙÙyÛ¶mòÅtÇŽÖÖÖ»wïž3gδiÓöíÛ÷`ˆ ÃDGGO:õõ×_ß¿¿J¥:vì˜ñÍÃŽRQQ¡Ñhüüü–.]:sæÌmÛ¶-\¸eYÓφËO[öéÓ§´´tÿþý÷l•énÜ´i“R©ŒŠŠš5kÖK/½´dÉ’øøø×_a˜ððp¥R9mÚ´)S¦|õÕW,Ë8p@’$ùޝ¿þzÖ¬YS¦LÙ»w¯‡‡ÇŽ; ÚÖ&ú|ùòåçÏŸ0ñ'B}}}xxø{ï½7uêÔo¿ýV­VÿôÓOÀCaÆ­ÑC‡ýío [³f !¤ªªjõêÕ7n”G9«W¯öòòzíµ×V¬X!IÒÑ£G80f̘ûÕð»$IºpáªU«,-- !çÏŸ_²d‰^¯¿ûúÇ?þ±råÊ B®^½:cƌݻwwëÖÍÄ&”ÒüÑßßÿĉ†"&˜îÆÈÈH;;»… ®\¹’R*IRbb¢F£!„lß¾½k×® ,X»v-!¤¸¸xÑ¢E¤”îÙ³ÇÁÁaÉ’%+W®$„ÔÔÔlݺ5,,¬5 šše¢Ï{÷î=pà@âÐf¥¤¤ÄÅŽÿþûr±‹/Þ¿_@cYÖÊÊ*$$dôèÑŽŽŽP°,ëééùÌ3Ïøøø( ãÑÇq …Â0J?o«P(ŒÌ`F®RTT¤mÎSO=uöìYy)Ïž=ŸyæµZm\mÓ½´§òG++«‘#GŽ9R®Ç¸|ÓÚdááá:nôèÑ­\¿c¢å\Žã‚‚‚ž}öÙ>}úpg¨–eY[[Û§žz* Àø0ÉÝ_\ppðèÑ£qæv‚áñ }n¢‡9Ž“¿¢¯GcÆŒ‘¿£§5ÝpŸ´åÉ-ù2×Ò,Ó¹m ?ëÝ4}×®]ÑÑѾ¾¾...z½¾Ã÷Û³v$¯‘)((6kÐÓæNn[VëÅÄÄtTŸ?°_€ mùcÜô•«Ã¯kŸþy³éîì=°ëiëw´sçΡC‡ÚÚÚ®_¿Þxgû÷b"·mYmÓÎ àQð¸+eb*+99™çùGózêææ¦R©´ZíÆwíÚõh6² å>ètä ³‡ÝŠæÃvC:Ò#ÞçÐ95~¡J¥jåûc~‹rrrŒ_¡Ó8æ! Àã /’€–EFF8p€ã8BȧŸ~zâÄ __߇ûâßG¡ÆÝò?vìØcs8Ð ±f• 9tèF£),,üùçŸÇg"¢øùùùûûËT*U`` ƒƒC{ÛÛ>B3Œ»å1 V«›Ã0ÅßßÿÆùùù7n\»vmNNNYY™‰X˜ššš——§P(!Ý»w÷öö¶¶¶~°MnìQh†q·<bbbxžlÀ”¨¨(AÆÏq˲eee§OŸné¶X£+þ#2hxèÍ@ x¤˜qý1bD~~þáÇEQ$„$$$¤¦¦>ÜÕÕµ¤¤„Ò¯_¿ùóç{yyݼysûöíÆ!gæÌ™~~~ëÖ­»~ý:¥4,,ÌÚÚ:""bîܹjµºªª***êøñãAAAo¿ý¶““Óå˗׬Y#‚é&………UWW=ztΜ9^^^•••QQQ'Ož¤”ʹ666[·n]¼x±»»û¤I“¦OŸÞÎfØÛÛÏ™3gĈ”Ò”””M›6iµZÓ4Ñ-¦+tvvž={¶¿¿CCCJJʆ jjj [Íš5kĈJ¥2+++""âÆ†£6ë L÷aÓoÔ¥rzŸ>}fÏž­R©LoðÛVQQqæÌãñßÎ;u:]PPÃ0*•*##C„ÔÔÔ„„„¢¢"ÃÐg×®]‚ „„„ÈaàÌ™3ùùù‰‰‰IIIÉÉÉ‚ Ï›7////!!áêÕ«‚ 9räžK0Μ9“‘‘qåÊ•´´´‹/jµÚÒÒÒñãÇïE²\ºt‰ã¸v6ÃÕÕõäÉ“Z­öÂ… ‰‰‰<ÏŸ8qÂt#Mw‹‰ {õêuîÜ9­V›œœ|ážçcbbÜÜÜä­N:Åó|jjj|||yyyNNNpppÛÊt6íðF]#BZZÚ•+Wâãã+**ÊÊÊ&NœøÐGÞO«Õ6º­ÓéBCC†Y¿~½N§[¾|¹R©ä8nΜ9•••†+þîÝ»u:!ÅÄÄètºE‹É…×­['Ïó .T*•¶¶¶GŽaìØ±¦¯§r=K—.•ëyë­·xž74RÎݶm[Ïž=å”v6cÓ¦M‚ ,[¶L.¿aÃAf̘Á²-®92Ý-&*üòË/Aøè£ä¬Ï>ûŒçù¥K—²,+[¹r¥œ5yòäÊÊʳgÏuëÊt6ÛáÆ]*§lذAÞ|âĉ†Æ::šã¸îÝ»ûéÝ»·\ÆD·˜¨ÐÊÊJ£Ñdff²ºuëvîܹիW³,{ýúõ¬¬,ÃQyò䨨(ggçmÛ¶Éß;vX[[ïÞ½{Μ9Ó¦MÛ·o߃ 2 =uêÔ×_}ÿþý*•êØ±cÆ7;ЦM›”JeTTÔ¬Y³^zé¥%K–ÄÇÇ¿þúë&nÚ‡+•ÊÈÈÈiÓ¦M™2嫯¾bYöÀ’$mܸ‘eÙ¯¿þzÖ¬YS¦LÙ»w¯‡‡ÇŽ; Úv\&úpùòåçÏŸ0qŒõõõáááï½÷ÞÔ©S¿ýö[µZýÓO?edd`D¿ fÜ=tèÐßþö·°°°5kÖBªªªV¯^½qãFyH´zõj//¯×^{mÅŠ’$=zôÀcÆŒ¹_ ¿K’¤ .¬ZµÊÒÒ’rþüù%K–èõúû±¯ÈÈH;;»… ®\¹R¾#š˜˜¨ÑhLlbº[LT¸}ûö®]».X°`íÚµ„âââE‹ìÝ»÷À ‹B›•’’÷þûïËÅ.^¼xÿ~μ%,ËZXX >ÜÂÂ"))©ªªÊøâ˲lïÞ½½½½óòò®_¿.I˲ò‘ã8†aDQ”G òGãk¥B¡ ”¦Ê†á8N’$I’ŠŠŠšývÐñãÇöÙgƒvsssuu8p`QQQVV–¡Ú¦{iO3 ÇÈ0̈#ììì²³³óóó%I2=ô1Ñ-¦+dYÖÚÚzøðá555)))†f~Æ ³´´¼té’V«5´ÐÜƒŠ‰‰ñõõ5݇&zL~œ†RÚ­[7µZ]ZZ𙙉(¿!myÒK¾KÖÒÕßtnÈφ7MßµkWtt´¯¯¯‹‹‹^¯ïðýšÐ†}µ¹ÓÚ–Õzr ì>|¿€ŽÒ–çM_é:ü:øùçŸ7›ÞèNàƒ¼þ¶a_mî´¶eµM;+D€ß¢ßÀKLL}%''ó<ëo{ ~ÃX–ÅwZ¶úßG¨R©ä·Ê<–rrrŒ_¹Ó8æ! Àã /ž€–EFF8p€ã8BȧŸ~zâÄ __ßGíÅ¿÷£‘æÖ~ìØ1¹ ð€±f• 9tèF£),,üùçŸÇgâZïçççïï/P©TímoG»4·µZø¨ý‰ÐI˜ýýý£¢¢†zèС={öxxxlݺõå—_né Î0Œ!ë½÷Þ HJJ¢”v@«;Îýh¤q÷£<<QQQ‚ Œ?žã8–eËÊÊNŸ>ÝÒ=½ÔÔÔ¼¼<…B!|4¯õ÷£‘»wïÖét!!!­¬-&&†çyCàA2ãâ;bĈüüüÇ‹¢HIHHHMM>|¸««kII !¤_¿~óçÏ÷òòºyóæöíÛÃÀÌ™3ýüüÖ­[wýúuJiXX˜µµuDDÄܹsÕjuUUUTTÔñãǃ‚‚Þ~ûm''§Ë—/¯Y³FÓM ³±±ÙºuëâÅ‹ÝÝÝ'Mš$Š¢““ÓìÙ³¬P(²²²6oÞ\TTdؤõ$„8;;Ïž=Ûßß¿¡¡!%%eÆ 555raÓ{1«ÍrzŸ>}fÏž­R©*++£¢¢Nž<ù¨ž:»ŠŠŠ3gÎÿvîÜ©Óé‚‚‚†Q©T‚ ¤¦¦&$$[»víÁ0H:sæL~~~bbbRRRrr² ÅÅÅóæÍËËËKHH¸zõª G޹çú¹yDuéÒ%Žãúõë—””¤ÕjcccãããyžÏÈÈðòò’Ë›ÕÈ^½z;wN«Õ&''_¸pçù˜˜777Bˆé½˜6msLLŒ iiiW®\‰¯¨¨(++›8qâ£9†x̘1GȲl£1ŠüÑ‚²`Á‚^½zmܸ1 `äȑ˗/·²²2”l4 Æ0Œ££cttôÈ‘#¶mÛfccóÏþsíÚµAAAÆ ‹‹‹ ~ñÅM¹žìììAƒùûû‹¢8wîÜ~ýúýãÿxú駃ƒƒ×¯_ß³gÏ¿üå/,ËšÛÈ?þX­V¯]»vĈAAA›7oöõõ•«2½Óš¶YNÓÇÇç‰'ž°µµ•?ð<¿oß>¹Ù­o¤R©Ôh4™™™†&uëÖíܹs«W¯fYÖô^L›¶YN1ÔÆ0Ì‘#GAÆ à~ë˜nnn... †)4I’¡ÌÕ«W)¥<ÏR***äj[³wÃN !ÙÙÙžžžóæÍóðð°³³³¶¶fYVޏf5rÀ€ŽŽŽééé†2¥¥¥£F¢”J’db/­dÜfY]]ü¥4---88X¥R;w®õu@˜[Z»¡×ë=<<!<Ï·­õõõÍî« ÷§OŸ¾lÙ2BHJJJUU•a<<üË/¿¬¬¬|ùå—Õjõ±cÇ2220"x„0 3}úôììlAA(((øøã W–e·lÙR^^.‚V«Ý½{÷¶mÛ4‰U£Æ‘C«Õž={Ö°$õ7ÞáóÏ?oͪQãz&L˜ ?†(Â… ~÷»ß•••%&&Ê5›ÕH†a-Z”››+×–™™9uêT¹=¦÷Ò¨žÈ–wßú IDATÈHA £Æ¦mމ‰9~üø²eËŠŠŠä:Oœ8ѧOŸöÿÊàžÌ»¡'¯>|¸……ERRRUU•ñÂK–e{÷îííí——wýúuI’X–Õëõ„Žã†EQâÈå,™B¡ ”V£0 Ãqœ$I’$Y[[7mÌøñããââ!Æõ0 cii9dÈBHbb¢(ŠÇ×ÜúFÊ…­­­‡^SS“’’bÈ2½—fÖıËá“RÚ­[7µZ]ZZš™™i\ÌlÉ#›–îÚ™ÎmƒE‹5»,s×®]yyymkƒYl©p‡é}ªLø <¯ÝÒÝÑÖ<ª¯Æ¯aR©Tò+ñK999Ư}móàñ†—Ÿ@Ë"##8Àq!äÓO?=qℯ¯ï#ûâßG¿…÷~ìØ1¹Ã •X³J‡„„:tH£ÑþüóÏãÆ36üüüüýýå*•*00ÐÁÁ¡½í½oýÞ“Z­ üír€‡ÂŒ@èïï5tèÐC‡íÙ³ÇÃÃcëÖ­/¿ürKW^†a Yï½÷^@@@RR¥´Z}·ö7n\||üßþö7–5ï/’f=”Cø­S´¾èâÅ‹œœÞzë­~øRºk׮Ç/^¼øðáâ(šÞ¶¤¤¤´´ô‘‚‹££cÿþý{ôèñ°Ðy™GŒ‘ŸŸo{ ©©©Ã‡wuu-))!„ôë×oþüù^^^7oÞܾ}»ñèdæÌ™~~~ëÖ­»~ý:¥4,,ÌÚÚ:""bîܹjµºªª***êøñãAAAo¿ý¶““Óå˗׬Y#‚é&………ÙØØlݺuñâÅîîî“&MEÑÞÞ~Μ9#FŒ ”¦¤¤lÚ´I«ÕÊ圜fÏž=xð`…B‘••µy󿢢"³ú«¥=Κ5kĈJ¥2+++""âÆ†¨ßRîßÿþ÷ÀÀ@–e7nÜG)õööž5k–——WuuõÙ³gÿóŸÿH’Ôš–Èé}úô™={¶J¥ª¬¬ŒŠŠ:yò$þþègΜ1^‹±sçNNÄ0ŒJ¥ÊÈÈ!555!!¡°°°¨¨(//O¡PBvíÚ%BHHˆÏœ9“ŸŸŸ˜˜˜”””œœ,Bqqñ¼yóòòò®^½*‘#Gî¹îC®'&&†çùK—.qçêêzòäI­V{áÂ…ÄÄDžçOœ8!×Ó¯_¿¤¤$­VÏó|FF†———\ÕîÝ»u:¡…fíñÔ©S<ϧ¦¦ÆÇÇ———çääËõ˜ÈݱcÇ¥K—ªªª®]»vþüù &0 3jÔ¨ÜÜÜÒÒÒS§N]¾|Y„o¿ý¶Ù~hÚ’˜˜AÒÒÒ®\¹_QQQVV6qâDÜ/èZ­öôéÓÆåèèhNÊ0Ìúõëu:ÝòåË•J%ÇqsæÌ©¬¬4ÂFa&&&F§Ó-Z´H.¼nÝ:Axž_¸p¡R©´µµ=räˆ cÇŽ5}—ëÙ¶m[Ïž=å†mÚ´I„eË–É5oذA„3f°,»víZAÞ}÷]9ë“O>aÕªUòü\+aÓ=Ê»X¹r¥\íäÉ“+++Ïž={Ï\Žãþüç? ‚ðÅ_(•Jy¿{÷îÕét/¼ð‚B¡°²²úî»ïAøãÿØ´UM["§lذAÞ×ĉ+** -€ö2srrrssíííå,–eSSSMBžç-,,ä¾¾¾<ϧ§§+•J9eÁ‚‚ „……™^E"×cXê©T*5Mvv¶¡žð<ÍqœÏOùˆZ÷H¹~ýzVV–ü‘a˜ƒ ‚ w‹éÜ7ß|S„Ï?ÿÜp˜ò_Æ “›áïï?kÖ,Ãâ[Ó-‘S È0Œ\›ax M™1Gh‚›››‹‹KBBBMMœÒì´V#†2W¯^¥”ò.....îСC[·n•$©¥y>CK Œ÷•––¬R©Î;׆Ãè Ì„-]‹õz½‡‡!„çù¶5¢¾¾¾Ù}™ûPµµ5!¤²²Rެrbfffnn.¥túôéË–-#„¤¤¤TUUFíaggG¹uë–qbUU!ÄÊÊÊtn³îÙ³';;ûwÞ zþùçÃÂÂ"##?øàƒ¶-x‘ÿžèÖ­Ã0X2Ð,3¡N§kô¼y—.](¥ÅÅÅ:ŽRêèèØÑÍ3Oaa!¥´¼¼|Ú´iÆOtPJ9Žûàƒ$Iúöî=ª©3ßÿ¾$rkâ%•K jÃÅ¢¢”rÊxY«vfÚŠg—N§ÚÖ¶ P´0mÑ9=/=mg†VQ¤rqÄUíÒê©G¤#Cäl¡ d %H’½ƒÚ#%{ÿx~“Ã%o}¿þ"Ï~.Ÿ®å§Ïeg¯X±¢ªªJÅàààE‹rDƒÁ Âc=Ö¿ÐÇLJ¦i£Ñèøê™IÅÊÊÊ„„š¦,X°cÇŽ¸¸8½^Ÿ••5’Iö“&M¢( ®8àÄ”«®®ÎÏÏϾ}5eÊ•Je0 Cwww{{{hhèŒ3Hå‰'Þû_iioo×ëõ³gÏ Áf³Ùl6WWWAd2™\.ojjªªªêëë³Ùld—n”#vvvÖ××Ï™3‡ôæáá±hÑ¢üñüù󮊢H²µ}âëååÕÜÜ|öìYš¦m6[yyynn.MÓ¡¡¡#Œ‡œ;µßWtt´Íf«®®åm<œH„û÷ïaÿþýëÖ­{饗òòò&Nœ˜••Ef¹¹¹nnnùùù6lxíµ×Ž;v_&ˆ{÷î•J¥yyyqqq¿þõ¯ßyç­V»zõj³Ùl0¶nÝúæ›ofeemÚ´‰ar–g4öìÙÃ0Ì_|÷»ßýîË/¿ôõõÍÍÍmoo¿ãUòTeTTÔš5küýý{zzêêê.\¨V«ccc׬Y³~ýzТЋ‹EQܹsgyyùüùóäïÞÞ^µZýöÛo¿òÊ+ÇW©Tß~ûm}}=f„c€¦éuëÖéõzžçyžoooÿ¯ÿú/{"aæóÏ?ïîîæyÞb±äççgee §Fû'!‹ÅÒÿ ÿoûÛÇ)‡4¸š¦HÇ™ÍæsçΑc“Ë—/'O(ò<_QQ±xñâ®®.Nw§FŒøæ›oÚ¿–~ø!==Ý^áŽW³³³É¥5kÖÐ4=}úôœœ“ÉÄqÏóW¯^MNN&æä䨛‰F£9wî\ZZZGGé³°°ÐßßßñV€Ÿ9çÖÉ1ËyóæM˜0¡²²²§§§ÿÆÃ03fÌ jmmmnna˜¾¾>Š¢X–%Ë}djB>’K„D"±/REÓ4˲‚ ‚ÐÑÑANÁ ðâ‹/’Ó¡ýû!a 6OOO½^ßÖÖFN]Ò4íââ2gΊ¢t:ÍfcYÖ>hÿïbÄ &Ì;×ÅÅ¥¦¦Æb± øZ\eY6$$ÄÍÍ­¢¢‚”³,+“ÉBBBnÞ¼YSSC¾„‘|‡$_Š¢¨P(T*•Ñhlhh* p7›ddF2Üj›ã«wÿüsRyÍš5ׯ_ïééqœ¿üòK«ÕºlÙ2‰DâêêúÕW_ñ<¿råJ‰D²víZžçwíÚ%•JÉâaYvpý;I"Ôh4V«5++kÚ´id7‘”ddd0bccM&Ó… pŽà¡àÄ¡Z­~öÙg333úé'›Íöõ×_‹¢øøã™6~õ«_õöö~ôÑG¤rnnn}}ýW ===EQìêê²Ùlÿ÷ÿ·}ûöwß}W¯×Ûl6² J–1I?â²þXaÓ¦M×®]# ª¤$55•„qâÄ‰ŠŠŠÐÐÐ… bRðàsbP¯×ûùù%&&úúúzzzº¹¹1 3a„!+ûøø´¶¶¶··“¢(Ž$eggÏ›7ïäÉ“¥¥¥¥¥¥§NÊÌÌaȶNÅ3¶nݺ5 äöíÛäQkkk£¢¢”JeYYÙ=FÉáºuëJJJ’’’üýý]\\¤Rép5år¹»»»Õju6š£G>÷Üs§OŸž5kVZZZIIɇ~8ܼjäñÜc&“‰¢(…B!Àƒo¤3B©TºyófAV¬XQUU%Šbppð¢E‹†¬l6›oܸáíííl4¢(VVV&$$Ð4½`Á‚;vÄÅÅéõú¬¬¬ÑÄsMš4‰¢(£Ñˆƒ£¾‘Îe2™\.ojjªªªêëë³Ùl111f<---sçÎ%u<<<&Nœèx†äååÕÜÜ|öìY²ÉW^^ž››KÓthh(EQdCÎþtüãP\Ñ4m=::Úf³UWW߃¡`”F:#4™Lƒ!,,lëÖ­mmm‘‘‘111 à w ôСCéééÌÊʲX,«W¯öóós1}úôœœ“ÉÄqÏóW¯^MNN&ýÓ4MF_³f MÓŽã\ÿŽ78äã999<ÏÛ§›ä Âþw¡ÑhÎ;—––ÖÑÑA†+,,ô÷÷¿»/î1'NsÐ4íââ2gΊ¢t:ÍfcYÖþ³,,Ë’%Mû4ˆa…B|íÚ5½^_VVöøã+ŠÖÖV77·Áý¿øâ‹†a™LróæÍššAì¿DòlHHˆ››[EE… ŽãP¿½½ÝÁ $f†a†ð¸Å€û"ûúúúW (JE…B¡R©ŒFcCCCÿ ð súX#™dÑÏßßß`0¿/^œŸŸßÒÒI\ÿÈ‘#­­­ŽG\î8ûÕäää;:z#ÿrà1Žçû­Vkgg'™·I¥ÒM›6‘ó/CÖwü¤£4Ü©™q|ãø3` ÃL™2eúôé‰äÒ¥K)))§OŸ‡7~‘Pÿ|¢ÿ ¾qœ2 Óò7ÜÄŒÒÀÝV*•#y™;ÀCª©©é_Þk;à2² <Úð*$ø§íÛ·†††âÕ¾ý©Õê‚‚–eïw 04f¬:R*•2™l¬:¼g¢¢¢²³³Ïœ9sñâÅæææ•+WŽa.W©TøŸ€Ö˜%Bš¦ÇõŸû^xA«Õ¾÷Þ{ 3¢˜G^Ú´isæÌñññ™2eÊäÉ“Çvö6Þ_ ŒÒ˜%Âñæíí=kÖ¬©S§ŽyýcÇŽÍ›7oîܹ§NEqtaÀCFâTm¹\"‘H®\¹²oß¾ŽŽŽá*Ϙ1#))I©Tr—››+“É–.]š””$‚ƒ!‚‚‚ââânܸqáÂ…ƒ ‚°eË–ˆˆ†a"""öìÙsøðáÒÒRQ‡‹g¸úCŽ(Š¢Íf# ¾šššzãÆ³gÏnذ! Àl6çåå?~¸Êîîî™™™)))>>>«V­"åþþþñññJ¥Òqsx VVVZ,–’’­VËq\}}}@@¹šŸŸoµZŸ~úi²èãã£Óéxž¯­­½xñbgggII Ïó‰£ÔÝÒÒb4‹ŠŠêêêxž?~ü8˲¹¹¹555===W¯^-//_¾|9MÓâ²þo0##Ãjµ®^½ºåâââúúúË—/“±X,F£ñÅ_²Ãâââ¶¶6FÃq\MM ˲†| —/_Öjµ&“©««+66륟ôôtžç7nÜ(•JY–ݶmÏóŸ|ò Ù„ÓÒÒ8ŽûüóÏIå5kÖ\¿~½§§Çq"üòË/­Vë²eË$‰««ëW_}ÅóüÊ•+%ÉÚµkyžßµk—T*%C8ˆ‡eÙÁõïhÈD¨Ñh¬VëÖ­[í7ÂqÜßÿþ÷!·I嬬¬iÓ¦‘ ¤$##ƒ45™L.\À9R€„{„jµúÙgŸÍÌÌüé§Ÿl6Û×_-Šâã?>dšùÕ¯~ÕÛÛûÑG‘ʹ¹¹õõõw\ôôôE±««Ëf³ýßÿýßöíÛß}÷]½^o³ÙÈ‚*YÆ$ý8ˆgÈúwM„ÿþïÿ¶ßˆN§{òÉ'çÎ;ä ‚°iÓ¦k×®‘åVR’ššJšŸ8q¢¢¢"44táÂ…˜<œØ#Ôëõ~~~‰‰‰¾¾¾žžžnnn ÃL˜0aÈÊ>>>­­­íííä£(Š#ÉFÙÙÙóæÍ;yòdiiiiié©S§233A²­SñŒ’}_SÅšššùóçÏœ9ó»ï¾²ò­[·”ܾ}ÛÞ¼¶¶6**J©T–••G¨à'f„ëÖ­+))IJJò÷÷wqq‘J¥ÃÕ”ËåîîîV«ÕÙhŽ=úÜsÏ>}zÖ¬Yiii%%%~øáp3§‘Ç3¶L&EQ …âî¦t£lck¤3B©TºyófAV¬XQUU%Šbppð¢E‹†¬l6›oܸáíííl4¢(VVV&$$Ð4½`Á‚;vÄÅÅéõú¬¬¬ÑÄ3¶&NœHQTggçÝ­¸Nš4‰¢(£Ñˆƒ£‚‘Îe2™\.ojjªªªêëë³Ùl111æ4---ö4‰':žyyy577Ÿ={–lò•——çææÒ4JQÙr³?ÇxÔ š¦}}}íŸyæA.]º4òæÑÑÑöØ¢££m6[uuõè€ÑéŒÐd2 †°°°­[·¶µµEFFÆÄÄ0 3Ü)ÐC‡¥§§1}úôœœ“ÉÄqÏóW¯^MNN&ýÓ4MF_³f MÓŽã\ÿŽ78ÜãÇíÚµ‹Ü ÏógÏžµOsrrxž·OFIåþ÷¨ÑhÎ;—––ÖÑÑAšúûû;ÿõÀ¸pâ¼MÓ...sæÌ¡(J§ÓÙl6–eí?˲,YÒ´Ot†Q(ÁÁÁ×®]Óëõeee?þ¸B¡hmmussÜÿ‹/¾¨Ñh†‘Éd!!!7oÞ¬©©Á~b“eÙ77·ŠŠ AÇ3 ~{{»ƒAIÌ Ã0 3àq FJ~†ô‰'žèèè¸råJ__Ÿ}ˆþwM>Ú¯’Š¢DQT(*•Êh4644ô¯÷—ÓÉÔg$Ëzþþþƒü½xñâüüü–––ÈÈHòüàúGŽimmu<ÊàrÇñد&''ßqÐ!‘D8iÒ¤¾¾¾‘ß»ã`î®9Œ‡q<ÁߨØhµZ;;;ɼM*•nÚ´‰œ²¾ãß ¥áNÍÜqÐþ‰pâ€ûlè‹a˜)S¦LŸ>]"‘\ºt)%%åôéÓâðÆ/êŸOôßÅ áááV«5??39€GÒ8Άé?ùîbpä.ìûŽðø£ÛJ¥r$/sxH555ýË{m\F€GÛÃø*$Û·o/,, }p^ívôèÑÚÚÚòòr–eï}jµº  à¾ #$«Ž”JeDD„L&«GÉÕÕõ/ùKPPPQQQ[[Û}y±J¥z þϳDHÓôõ/þ‚ fΜù·¿ýmõêÕ}}}‚ Üû´ïcîwãÅ××—a˜öööû•à¡àÜŒP.—ÇÇLJ„„H$’+W®ìÛ·¯££c¸Ê3fÌHJJR*•ÇåææÊd²¥K—&%%9NKAAAqqq7nܸpáÂÁƒIý?üá“'ONNN¶7ß²eËc=¶iÓ&ARSSÝÝÝ333SRR|||ª««çÏŸOÓôüùó÷ìÙ£V«kkkñ‹_8~âĉñññááá?ýôSuuuFFÆ­[·È%//¯ 6,X°@Åêêê½{÷Z,–Á‘ˆaÕªU¤Üßß?>>^©TšÍæ¼¼¼óçÏß—uZ­ÀÀÀÊÊJ‹ÅRRR¢Õj9Ž«¯¯ Wóóó­VëÓO?M}||t:Ïóµµµ/^ììì,))áy^"q”z£££[ZZŒFcQQQ]]ÏóÇ'‡MÊËË»ººú7/))éîî&%ÅÅÅmmm†ã¸ššš¼¼¼šššžžž«W¯–——?óÌ3J¥ÒAðÓ§O/++³X,UUUÇi4š)S¦P5yòäóçÏ[,–ŠŠ NÇq\aaáç_ÄÀ²¬F£!ßÀåË—µZ­ÉdêêêŠÅz)ÀC)==çù7J¥R–e·mÛÆóü'Ÿ|Â0 5(¦¥¥q÷ù矓ÊkÖ¬¹~ýzOOãDøå—_Z­ÖeË–I$WWׯ¾úŠçù•+WÒ4­Õj¯_¿Þ¿yii©Éd"%ÆjµfeeM›6eY–e×®]Ëóü®]»¤R)MÓŽƒ?pàÏóï¿ÿ>¹úá‡r·uëV†aöîÝËó|ZZ¹”‘‘Áóüo¼Aö7 {IFFik2™.\¸€s¤¥™3gFFFzxxóçÏç8îØ±cäŸõ‰ðâÅ‹]]]~~~¤2MÓÿûß­V«ãDxæÌžççÎK: ‹‹ I"ä8®ÿ™Õ—_~™çùÏ>ûŒd,ÁK¥RƒÁÐÐÐ •JÉU…BQVVö§?ýÉÅÅÅ`0èõzû¥Ù³gswøðáÁÉlp ¤Ä>(MÓ䣢¢0)x@8±G¨×ëýüü}}}===ÝÜ܆ڞìS IDAT™0a•}||Z[[ÛÛÛÉGQG²1–=oÞ¼“'O––––––ž:u*33S„nªÙwõœ ~öìÙÞÞÞßÿ½}÷Ñh4FGG‹¢âíí}ûöíÒÒR{W ÃL:uä1ܾ}›ü!ŠbmmmTT”R©,++ÉÀxs"®[·.--¢¨êêêžžû$i0¹\îîînµZæèÑ£z½þõ×_ê©§ž}öÙÔÔÔœœœÍ›7þt‰ƒàÝÝÝ)ŠúñÇû×·ÙlE¹¹¹Qe6›í1444´´´Ü]H&“‰¢(…BAÓ4ŽÌ<Fš¥RéæÍ›AX±bEUU•(ŠÁÁÁ‹-²²Ùl¾qㆷ··³Ñˆ¢XYY™@Óô‚ vìØ§×ë³²²úúú$‰T*íëës¶[ÇÁ_»vMÅÉ“'nH.uww¿öÚk$5Úã¼»G2&MšDQ”ÑhDx@Œô9B™L&—Ë›ššªªªúúúl6[LLŒƒ®–––€€ûnŸ‡‡ÇĉoŒyyy577Ÿ={–¦i›ÍV^^ž››KÓthh(EQF£‘eY²_HQ”\.Ÿ4iÒwÚßÞÞ~åÊ•JD CCC»»»:ôÃ?èõúÙ³g ‚`³Ùl6›««ëȳ MÓÑÑÑö±¢££m6[uuõ›ÀxéŒÐd2 †°°°­[·¶µµEFFÆÄÄ0 3Üá—C‡¥§§}ºD"¹téRJJÊéÓ§Åá_$ÃÇ!ÙZ³ùÄ8eàn+•Êá^“ðhjjêÿˆ9YmxüÓöíÛ CCCÞWûªÕê‚‚–eïw pï0cÕ‘R©ŒˆˆÉd#©üþûïWTT¼÷Þ{ ó/ìØ±£¢¢"22ò¾dS•Jñð&r¸ c–išy yì±ÇfÍš•””4`9mÚ´Y³fyzzŽUTNqêàÑ0f‰ÐY4MËd²?üpÀ¤©î%‰Sµåry|||HHˆD"¹råʾ}û:::†«>^©TšÍæ¼¼¼óçÏ‹¢èÔ·¦ÀÀÀÊÊJ‹ÅRRR¢Õj9Ž«¯¯ Wóóó­VëÓO?M¦t>>>:ŽçùÚÚÚ‹/vvv–””ðûlffæO?ýd³Ù¾þúkQüñ!Ó̯~õ«ÞÞÞ>úˆTÎÍÍ­¯¯¼Æø—¿üE£Ñ,_¾ü׿þõ]L¼Aسg"++KÅööö½{÷þôÓO7oÞ>>­­­íííä£(ŠCî´ ‚ðŸÿùŸÿó?ÿ³uëÖ¢¢¢»Ë…䯯FQ9޳—˜L&Š¢¦L™â ù­[·”ܾ}ÛsmmmTT”R©,++s60x(81#\·n]IIIRR’¿¿¿‹‹‹T*®¦\.www·Z­#éöÒ¥K ܲeËh!{{{”Ô;š>I*U(˜<ªF:#”J¥›7oaÅŠUUU¢(/Z´hÈÊf³ùÆÞÞÞ#éYÅ>úhÙ²e¯¾újMMMÿK}}}‰D*•öõõ0α5iÒ$Š¢ŒF#Ž<ªF:[’Édr¹¼©©©ªªª¯¯Ïf³ÅÄÄ8˜'µ´´Ì;—Ôñðð˜8qâpõoß¾ýþûï³,;`7Îh4²,N årù¤I“ÆurFÓttt´}ˆèèh›ÍV]]=~#Àý5Ò¡Éd2 aaa[·nmkk‹ŒŒŒ‰‰a¦ÿ³ ý:t(==ýàÁƒYYY‹eõêÕ~~~úÿöÛo=úòË/(\²dÉÎ;³³³]]]_zé%//¯<ØÎ;—,Y’˜˜¨Ó醛áõööªÕê˜ÍæçŸ^¥R yÌ N–ùàƒ>þøã¤¤$Š¢ßxãüü|…B1då/¾øböìÙk×®MKKE±¨¨¨¡¡aöìÙÃu.Š"y0Ã×××^øùçŸÏš5륗^ÚµkWooï‘#GL&Ó¿ýÛ¿<æþf̘ñÄOxxx8¨S]]]ZZúûßÿžT»xñâ;ï¼s¿fàÁBÓ´««ëÂ… .\(‘Hhš–H$öçÿX–%…öú ÃL:uéÒ¥O<ñ„D"¹xñ¢Éd"3H2•¼È9d'“'Oþå/À0 ©Ð¿rÿæýã!K$ûa™nβ,˲$ì%K–ÐÅ¢‘ÿ2µ¿¿?ýOK–,¹~ýúÅ‹ïî%G÷þÐ&~€àgÂéÏÈwËΞ=kµZ;;;]\\æÌ™Ã²lFFÆ¿):†ƒŽl üLŒãKh†™2eÊôéÓ%É¥K—RRRNŸ>”q\ýc¦ÿê¢ È‚0þè¶R©Ä{øàÖÔÔÔÿ%s² <Úð*$ø§íÛ·†††’Wûøx×ýÜ/jµº  €eÙûÜ’±êH©TFDDÈd²!?Þu?÷‹J¥ºïÉîf¬:¢iºÚðqäÞ~ûíùóçWVVŠ¢8V±Ý…»Ž.c6#+F£ñþfAøùp.Êåòøøø‰DråÊ•}ûöuttŒføÔÔTww÷ÌÌÌ””ŸU«V­[·.,,ìÓO?mnnE155ÕÍÍí³Ï>{ë­·ž|òIŽãNž<ùõ×_Û3åŒ3’’’”J%Çq¹¹¹2™léÒ¥III‚ PpãÆ . €\ÍÏÏ·Z­O?ý4YQðq8ÅÅÅmmm†ã¸šš–e9Âó¼½aqqñ?þñ¿ýíouuuZ­öúõëf³ù•W^!W}||t:Ïóµµµ/^ììì,))áy^"‘PÝÒÒb4‹ŠŠêêêxž?~üøç_‡¡ÑhH·—/_Öjµ&“©««+66ë¥'ö?øàƒ_þò—QQQ»wïž6mÚúõëæî7išöööÖëõÁÁÁááá6›mð^ãĉ¿ýöÛ'Ÿ|2**êå—_áõ×_'ƒÆÅÅþõ¯;wnddä»ï¾;sæL{<7n”Ëåk×®]ºté¼yó¾ýöÛ¥K—þû¿ÿûàd68 RXTTõú믳,›’’2𛀇ÛÌ™3###=<<ÈÇùóçswìØ12Ǻ»!™„õ?#: !©0aÂr•¦éÊÊÊÖÖV2ç»xñbWW—ŸŸŸýêßÿþw«ÕJ®ž9s†çù¹sç’®ÂÃÃãââÂÃÇ48 Rb¿Yš¦IoQQQ˜ŸÖÖÖöövûÕþ{xÙÙÙóæÍ;yòdiiiiié©S§233AnŸop·oß¶÷\[[¥T*ËÊÊœ¼?xp9±Ð·nݺ’’’¤¤$©T:~a„\.www·Z­ÃU8zôèsÏ=wúôéY³f¥¥¥•””|øá‡w=Ÿ3™LE) Ì%#J¥ÒÍ›7 ‚°bÅŠªª*Qƒƒƒ-Z4®Á9f6›oܸáíí=\Q+++hš^°`ÁŽ;âââôz}VVÖgG›4iEQx´à3Ò¡L&“ËåMMMUUU}}}6›-&&æ¾ÏZZZ컀'N${yy577Ÿ={–¦i›ÍV^^ž››KÓthhè;§i:::Ú~ÑÑÑ6›­ººzœîî‹‘ÎM&“Á` Ûºuk[[[dddLL Ã0äXÊýrèСôôôƒfeeY,–Õ«WÛ·{zzêêêžyæµZýÍ7ßÈd²õë×SU\\,ŠâÎ;—,Y’˜˜¨Ó醛áõööªÕê˜ÍæçŸ^¥RÔ××cFð(q"}ðÁüqRREQo¼ñF~~¾B¡·Øîì‹/¾˜={öÚµkÓÒÒDQ,**jhh˜={6¹º~ýú?üpÅŠÿñÿAÓtwwwZZÚ‰'DQœ1cÆO,#ôÐ?Î0Lÿ§8üp <ªþè¶R©ìÿÖ˜¦¦¦þ¯g˜óàц—Àð¶oß^XX:ÜË~ÕjuAA˲w×ÿ(›P%¿®•JeDD„L&®‚J¥r&ïh”Í(ŠbƯë·ß~{þüù•••¢(Rõ /hµÚ÷Þ{aþ¿AišMesj\g„F£‘dAŠ¢¼½½gÍš5uêÔñÀYÎ%B¹\"‘H®\¹²oß¾ŽŽr)55ÕÝÝ=333%%ÅÇÇgÕªUëÖ­ ûôÓO›››7oÞÁ0LDDÄž={>\ZZJz{{oذ!<<œçù“'Ož!yK£ÑX­Ö¬¬¬iÓ¦‘“œùùùV«•$B–e×®]Ëóü®]»¤R)ÉU¤É{ï½G:|î¹çL&SyyùA÷OJ222HóØØX“Étáœ#€q1sæÌÈÈHòqþüùÇ;vÌž–8ŽëF´"¤(êå—_æyþ³Ï>³OøH“ &4M÷ÝwÉ ¶ƒû'%öxhš>sæ ÏóQQQ˜À9±G¨×ëýüü}}}===ÝÜ܆±§1âÖ­[ÎF ùCÅ7nxzz:¨<¸ÿÛ·oÛ›×ÖÖFEE)•ʲ²2gÀŸ''áºuëÒÒÒ(Šª®®îéé‘J¥ãÕ]2™LE) š¦qdFb¤‰P*•nÞ¼Y„+VTUU‰¢¼hÑ¢q ÎY“&M¢(ªÿ3Žôz™L&—Ë›ššªªªúúúl6[LLŒS[q6›¢¨!O„Þ5𦣣£íaDGGÛl¶êêê1m#šL&ƒÁ¶uëÖ¶¶¶ÈÈȘ˜†a†<Ø2¤ææfQ£¢¢Ö¬YSTTÔÒÒâ¸þÎ;—,Y’˜˜¨Ó醛áõööªÕê˜ÍæçŸ^¥RÔ××cF#äÄá|ðñÇ'%%QÕØØøÆoäçç+Š6×jµ'Ož\¾|ù®]»Þzë-ƒÁà¸þŒ3žxâ û¡Ð!UWW—––þþ÷¿'Õ.^¼øÎ;ïôõõ0$'Ö6išvqq™3gEQ:Îf³±,+Š"YódY–¦éþIˆ”Øl6ûüŒeÙ77·ŠŠ A†kBJ4²2EQ¢(* •Je4`|=˜¿”à€Ÿ•ïðS*•x±<šššìoŒ§'BdAx´õÏ‚££V« X–½ßŒÖ#s#pO[,‰Dr¿­GæF~˜ûÀÿ¦iš¦ïÁ@/¼ð‚V«}ï½÷f\nÿžÝŒÞ”ïooïY³fM:õ~÷ŸsËwr¹<>>>$$D"‘\¹reß¾}äRjjª»»{fffJJŠÏªU«Þyç77·ýû÷'$$¨Tªžžž¼¼¼sçÎ=õÔS¯¾úª\.¯««ûóŸÿÌó|ÿ!üýýããã•J¥ÙlÎËË;þ¼(ŠCöŸšš:yòääädAHÛ-[¶<öØc›6m"%AAAqqq7nܸpáÂÁƒAزeKDDÃ0{öì9|øpii©(Š^^^6lX°`(ŠÕÕÕ{÷îµX,CŽk³Ùú<¸‚〇U```ee¥Åb)))ÑjµÇÕ×׫ÅÅÅmmm†ã¸šš–eI‰N§«¬¬¬ªªâyþ‡~HLLlmmýî»ïyž?sæŒýP‰F£áy¾¶¶öòåËZ­Öd2uuuÅÆÆ’eÆÁý———wuuõߊ+))éîî&%ÑÑÑ---F£±¨¨¨®®Žçùãdz,›››[SSÓÓÓsõêÕòòòåË—Ó4=yòäóçÏ[,–ŠŠ NÇq\aa! l𸾖Áß<¬ÒÓÓyžß¸q£T*eYvÛ¶m<ÏòÉ'd§M£ÑX­Ö¬¬¬iÓ¦‘lAJ’““IýO?ý”çyŽã6mÚ$•J=<<Μ9Ãóüo~ó’!HýŒŒ R?66Öd2]¸p¡oýû×jµ×¯_ïŸKKKM&)ùòË/­Vë²eË$‰««ëW_}ÅóüÊ•+%ÉÚµkyžßµk—T*%CïÝ»—çù´´42tFFÏóo¼ñÃ0ƒÇ`¸îFàa5sæÌÈÈHòqþüùÇ;vÌþ¯?Çq2™Ì^Ÿ”L˜0| å8îûï¿—J¥¤$))‰çùÔÔT{*å8ÎÞ?MÓ$SFEEÑ4=¸lj´;w.Iuáááqqqááá4M¿üòË<ÏöÙgd\©Tj0ôz½=°Ù³gswøða2½0îÃÝøp7rß<Œ'öõz½ŸŸ_bb¢¯¯¯§§§››Ã0ö›ššš““³yóæÁ‰ÐÍÍ¢(³ÙLR5)lhhhii«ã-ýoGf(#M„R©tóæÍ‚ ¬X±¢ªªJÅàààE‹kp“&M¢(Êh4™<úúú$‰T*íëë|UÅÊÊÊ„„š¦,X°cÇŽ¸¸8½^Ÿ••5 æµk×DQìîî~íµ×úŸEÑ>y×€ûh¤ÏÊd2¹\ÞÔÔTUUÕ××g³ÙbbbÆ|Ç‹¦éèèh{·ÑÑÑ6›­ººzÈÊF£‘eY²íGQ”\.Ÿ4iùÛËË«¹¹ùìÙ³4MÛl¶òòòÜÜ\š¦CCC)Š"ÙÎ>moo×ëõ³gÏ Áf³Ùl6WW×ÑdA§nÎM&“Á` Ûºuk[[[dddLL Ã0cûCb½½½jµúÀf³ùùçŸW©TõõõCN¤¾ýöÛ%K–ìܹ3;;ÛÕÕõ¥—^òòò"—zzzêêêžyæµZýÍ7ßÈd²õë×SU\\,Šbss³(ŠQQQkÖ¬)**jiiÙ»wï®]»òòòöïßßÖÖ¦R©Ö®]»sçÎüüüÁãîܹsÉ’%‰‰‰:n¸žS7‡åË—“‡ÿxž¯¨¨X¼xqWW—N§ëj´^\b±Xú?EðÛßþ¶ÿéMFsîܹ´´´ŽŽ2Jaa¡¿¿ÿp½1 ³{÷n“ÉÄóüõë×wïÞ}âÄ û©ÑéÓ§çää˜L&Žãxž¿zõjrr2š¦éììl2Äš5kÈ/¢%$$èõzò€‡Ùl>wî\ÿÓªýÇÍÉÉáyÞ>!òÆÜ>^©TšÍæ¼¼¼óçÏÙ,•••‹¥¤¤D«ÕrW__@®FGG·´´Æ¢¢¢ºº:žç?NN…LŸ>½¬¬Ìb±TUUUTTp§Ñh¦L™BQTqqq[[›N§«¬¬¬ªªâyþ‡~HLLlmmýî»ïyž?sæÌO—(•Êúúzžç/]ºôÝwß]»v­£££µµU"‘P5yòäóçÏ[,–ŠŠ NÇq\aa!éÓÙ&Ož\TTÄqÜ¥K—´ZmwwwSSSTTÔ ž¤sFÃq\MM ˲†çùÚÚÚË—/kµZ“ÉÔÕÕ‹õR€‡@zz:Ïó7n”J¥,ËnÛ¶çùO>ù„aŠ¢¾üòK«ÕºlÙ2‰DâêêúÕW_ñ<¿råJš¦8Àóüûï¿O~øá‡Çmݺ•aFcµZ“““É¥O?ý”çyŽã6mÚ$•J=<<Μ9Ãóüo~óÇ©b÷îÝV«uçΤŸ 6˜Íf{"Ü»w/ÏóiiiäjFFÏóo¼ñÆ]@Ú~üñǤþK/½d6›/\¸0dª&geeM›6T %¤yll¬Éd®9Ο?Ÿã¸cÇŽ‘ÄI˜;w.Iáááqqqááá&L0 R©”4T(eeeúÓŸHâ8n„ äRhh(Çqßÿ½½rRRÏó©©©$ݧ©©©¥¥ÅËË‹|dæÒ¥K$J¥RƒÁ ×ëí}Ξ=›ã¸Ã‡“)šS477_¹rÅÝÝ\¥iú믿æy>&&fpª&Ëd²%öï¦iò½ 7§€ñæÄ¡^¯÷óóKLLôõõõôôtsscÆžB²³³çÍ›wòäÉÒÒÒÒÒÒS§Neff ‚âííýý÷ßÛ÷ Fctt´(Šöû¢(rg/1™LE‘uÔáL™2eÒ¤Iß}÷Ùwìß!EQO<ñ„··÷íÛ·KKKí… ÃL:Õþq„Ëåò’’’Û·o“«¢(~ÿý÷111sæÌÑh4CnõÙ£²ëß¼¶¶6**J©T–••9¸G'N$ÂuëÖ¥¥¥QU]]ÝÓÓcŸ3GÕëõ¯¿þúSO=õì³Ï¦¦¦æäälÞ¼™Lž~üñÇþ•m6ÛCôöö(!©ÅñtÐ××—¢(Žã†¼êææFQ”Ùl&IŽ644´´´ Î[Žðôô¤(êæÍ›ý+ôôôPåêêê BH¢U(4MãÈ À½7ÒD(•J7oÞ,Š+ªªªDQ ^´h‘½‚(Š••• 4M/X°`ÇŽqqqz½þìÙ³¢(Nž>>$$D"‘\¹reß¾}EmÙ²%""‚a˜ˆˆˆ={ö>|¸´´TÅáêS•ššêææöÙgŸ½õÖ[O>ù$Çq'Ožüúë¯EQûÌ~XÆq}2½›0a¹JÓteeekkëAIe™L6 ÄÞ9MÓgΜáy>** “B9'öõz½ŸŸ_bb¢¯¯¯§çÿkïþƒ¢¸ïÇïN:¨\ƒ&¢ž{hˆ?ÂPd†jòG;£ä/Ód””6¥ ¥L3f:©¥©™icíjDÇZ¦Úi2c~4f ‘‹!=9ÁàÁ‘ÈoáäîvÅ!án¿ìwvîƒp?4©<qûÚ÷ûõÞýƒ×¼wß»;?66V’$£’MmÿP(¤ÿ¡iÚ7–-[aÃÃÃc¶ŒŒŒÍ›››³²²,K]]]ô˜å&QóóóKKKAp:CCC&“if÷Ÿ&¯×+‚ÙlE‘%3€(E[M&Ó /¼ …žxâ‰ÆÆFMÓÒÒÒ6oÞôÐC{÷îíîîÎÌÌÌÉÉ‘$ÉXÛòùçŸkš–••µsçÎ?ü°££#òþ‘íÛ·ïÑG-,,t8Íð¾øâ‹òòò#GŽø|¾­[·Z­Öªªª––f„€;bûöí­­­ªªªªj·Û·lÙâñx‡¾ TÅ×^{MîܹSÅÈûëË>Ãë¢Ífóz½ú–ŠŠ UUIä¸;Ÿ={¶´´´¯¯OOQ]]ššz—Ï àÝ$®UŠ¢8wîÜôôtAG0”eYÓ4ý¢¨ ²,¯Y³&66Ön·‡B¡Èû˲,Šâèè¨Ñøýï`0¨OïÆÝYMÓÌf³Õjp¹\á;pGD~Ûõ­Ñ»ðvl^À ˜mÆ~ÆÏb±ðm?À=¬½½]ÿê»nlÍ£ îmáUÜëÊËË«ªªdYžñž_zé¥êêêµk×þo}xš'äÎO@ôb¢ßÕjµÞ¡Ze±Xyä‘„„„ïùŽšæ ¹sç=)ú]EQ¼Cÿµï\ÏwÔ4‡ý?zÔp™D!àÞ3‰K£ºÔÔÔ‚‚‹ÅâóùNœ8QSS£išZ°`ÁO~ò“ŒŒ “ÉÔÖÖvøðá+W®DcÁ‚?ûÙÏ2224Ms:ôûýz())©  `Íš5111mmm¯¾új__ŸÚ³gOllìŸÿüçŸÿüç?ü°¢(o½õÖÛo¿=QÃÂ… Ö­[÷å—_:β²²ááa=tÿý÷Y,EQ*++{ì±¢¢¢P(tÛnÏž=qqqG-))IIIÙ±cǤš¾z6›MUÕæææË—/×××{½^Ç“››«_ß[¼xñ‡~¨(ÊÅ‹ëëëÛÛÛ³²²¢‰ž:u*lÚ´ÉØ¹¦¦Æï÷Ûív‡Ã¡(Juuµ¾¨dåÊ•.\ðûýçÏŸ¯¯¯W¥¥¥eùòåúkkk¯\¹òÁ|úé§õõõ×®]óù|yyy‘¯@.]º´®®Îï÷766ÚívEQl6[rr² )))‡C?ꆆ†þþþóçÏ«ªsÛ2Fmmmww·ÍfS¥©©I–åI5|õl6[ (++3™L²,çææz½Þ>úH/Qeeeªªþþ÷¿×£O=õ”Ïç‹2:¦±ûüóÏÛÚÚâââŒèÛo¿­ªjNNÎm£á…Ðd2uvvºÝn“ɤï¼zõjEQ^ýuY–|ðÁÌÌLc 7nTå7Þ0J‹¢(sæÌ1²\¸p¡««K¯[ãÒÓ¹\.#Ùl®««Û¿¿$I gÙ²eF‡çÎ F!ŒpBÆ={á+c'Õp‡LúáÈȈþ‡¦iÍÍÍYYY‹ehh())éüùóáÑK—.åä䤧§û|¾Q›ÍÞÿ·¾õ­ÄÄÄ‘‘‘?þØØ(IÒ}÷Ý'‚Ûí^¶lYaaá<0þüØØXI’ŒÊ§3îÞišvãÆ £ŒkõêÕ‰‰‰—.]2Z dggkš …RRRºººzzzŒo½7î ©««7qëqjÍ3nÒ…0œ×ëÁl6ÏŸ?_„7n„G‡††A˜7o^äè˜>cccAðù|­­­FÕq¹\š¦åçç—–– ‚àt:‡††ŒiÜ”é“Ô›7o†o ƒ‚ $%%ÅÅÅè{3Nˆ(ŠSXó2Íæ€)˜V!\´h‘ ¡Pè›ßüfx4%%EÅÛFÇüÇïííÕ4mppð‡?ü¡^tš¦É²ü /„B¡'žx¢±±QÓ´´´´Í›7Oçôt‹/¾5äóù®_¿ž˜˜}oÆ ™Z›fsÀLî9BQ³³³;XÙÙÙÁ`Ðét^½zµ¥¥%---==]ÆÇÇoÞ¼ùæÍ›555}}}¢cþé÷ôô¸ÝîÕ«W¯Zµ* ƒÁ`08oÞ¼P(”””ÔÞÞÞØØ8:: õ[ŒÓ9þžžž¶¶6«ÕºjÕ*½«µk×?~\–厎ŽåË—¯_¿ÞöÂ… Ã3NtB¦y>§sD€;Åf³]»vÍårçåå½ù曪ªþûßÿÖWŽìرÃï÷_¼x±  àé§Ÿ~ï½÷€¾ää¶Ñ1«FwíÚ¥(JcccAAÁ÷¿ÿý_þò——.]zòÉ'EQt:^¯÷¥—^zöÙg;öÙgŸ ½÷Þ{á‹eÂ—ÆØl6¯×a±Œ Ï<óŒ¢(v»=??ÿé§Ÿþä“O|>ßöíÛEQÌÏÏWUµ©©i÷îÝ»vízÿý÷@øªÑ'dß¾}Ÿ|òÉÆõƒwlš¾vl6ÛÙ³gKKKûúúTUUUµºº:55UŠ¢øì³ÏºÝn=tõêÕÿÓ#GÇBQŸ{î9}gEQ|>ßÙ³gõµ”Û·oommÕ;±Ûí[¶lñx<‡c:…PÅââ⎎½[—Ë•——§WhI’^yåÇ£äôéÓv»=|Õh„RQQa,‹hlšîŽI\WÔ‹¦if³Ùjµ ¸\®ÑÑQc}çúõëçÎÛÔÔä÷û¥˜‘£²,‹¢ ˤ’$‰¢˜‘‘1þ|·ÛÝÝÝ …4MEqîܹééé‚ 8Ž`0(˲¦iúÝD½Ÿð![úúúôe8clÛ¶Íf³‰¢»aÆááa§Ó9f$f³9--­··×ív×ÕÕ­X±Âl6ŽŽF>!cjܱE>Ÿ€»`Š7ØôYθk:"„nrçIu¢+..w‰éÉ“'»ºº"t›ššÚÙÙ©ÿ½eË–S§Nuttdff†/ä™Úf°9`Êf˃Ûú¥Î[…ÏYÇÕÚÚúûûõ™¨ÉdÚ½{wee%E î ³åm^ÚnÛP’¤äää¥K—ÆÄÄ\¼x±¤¤äÝwߥ À=c¶Ì§L¿[iüÔoU~…ãÀ­Æ¾tÛb±„¿c€{L{{{øçÆÖ<ª àÞÆG„˜MÊËË«ªªdYžñž_zé¥êêêµk×~ ? <Í£¾s' 0#b¢ßÕjµÞ¡Ze±Xyä‘„„„ïyú¦yÔwî¤f„ý®¢(Þ¡èw®çé›æØ¾Î‡&U¸÷LâÒ¨.55µ  Àb±ø|¾'NÔÔÔhš¦‡,Xð“Ÿü$##Ãd2µµµ>|øÊ•+QFÇX°`ÁÏ~ö³ŒŒ MÓœNçÁƒý~¿JJJ*((X³fMLLL[[Û«¯¾Ú××§‡öìÙûç?ÿùç?ÿùÃ?¬(Ê[o½õöÛoO”Åpÿý÷Y,EQ*++{ì±¢¢¢P(tÛ£·gÏž¸¸¸£G–””¤¤¤ìرcRÍ_k6›MUÕæææË—/×××{½^Ç“››«_ú[¼xñ‡~¨(ÊÅ‹ëëëÛÛÛ³²²¢‰ž:u*lÚ´ÉØ¹¦¦Æï÷Ûív‡Ã¡(Juuµ¾ÞdåÊ•.\ðûýçÏŸ¯¯¯W¥¥¥eùòåúkkk¯\¹òÁ|úé§õõõ×®]óù|yyy‘/N¦¤¤8ýÐúûûÏŸ?¯ªjLLÌmzŒÚÚÚîîn›Í¦(JSS“,Ë“jøZ³Ùl@ ¬¬Ìd2ɲœ››ëõz?úè#½D•••©ªúûßÿ^>õÔS>Ÿ/Êè˜BxðàAUUKKKõõ¶?þñ%I:pà€ªª¿øÅ/ôÐoû[UUÿð‡?H’dŒðW¿ú•ýîw¿;88hd™Hii©¢(‡Ò[íܹóÚµkCCCF!ŒpÔ㞢cÇŽ-Y²DßaRÍ_kúD'>>^ÿ)Šâ™3gTUÕ'vŸþy[[[\\œ}ûí·UUÍÉɹm4¼šL¦ÎÎN·Ûm2™ôW¯^­(Ê믿.Ëòƒ>˜™™iŒaãÆŠ¢¼ñÆFÕQeΜ9F– .tuué%m" gÙ²eF«sçΣF8êqOQøò×I5Ü}“^,322¢ÿ¡iZss³ ‹eÍš5IIIn·;_kk«Q\.WGG‡¦iùùù¥¥¥‚ 8Ρ¡!cÖ8eIIIqqq@ ú&ÆQ‹¢8…5/Ól˜YÓ*„‹-a`` ³³3 }ó›ß ¦¤¤ˆ¢xÛè˜bÐÛÛ«iÚàààøÃ`0hl×4M–å^x! =ñÄ𦥥¥mÞ¼y:‡àóù®_¿ž˜˜}㨧VƦÙ0³&wiTÅììlãbfvvv0t:W¯^miiIKK3.uÆÇÇoÞ¼ùæÍ›555}}}¢cêAOOÛí^½zõªU«B¡P0 ƒóæÍ …B IIIííí£££Á`P¿Å8ÍSÐÑѱ|ùòõë×c[¸pax·õ4OÚ4‡ ˜“›~ñÅåååGŽñù|[·nµZ­UUU---š¦ýío;tèÐ?þñC‡]¿~ý?øÁù¤±pæ¶G½oß¾G}´°°ÐápL4ËÐ|:ÃÜm6›íìÙ³¥¥¥}}}ªªªªZ]]ššªGEQ|öÙgÝn·ºzõêŒ9:æñ QŸ{î9}gEQ|>ßÙ³gõe–Û·oommÕ;±Ûí[¶lñx<‡#|Õhx]´Ùl^¯7r¥”$é•W^ñx<22RXX(IÒéÓ§;;;z衽{÷vwwgffæääH’Uçûöí{ôÑG ÇD3¼/¾ø¢¼¼üÈ‘#>ŸoëÖ­V«µªªª¥¥…!àîE±¸¸¸££CUUUU].W^^žþ ÃöíÛ[[[õív»}Ë–-ÇápD³j´¢¢BUUc©¯ /¢6›íìÙ³¥¥¥}}}zŠêêêÔÔÔ¯ä$î1“»€)IRllì† †‡‡Ng0Ôçd¢(Î;7==]‡Ã eYÖ4M_M#˲(ŠÆÎÑü5’êÕTÓ4³ÙlµZ\.WøÜU½û.¼›p Üúa^‹ÅÂÿ÷°öövýSðº±5*¸·…WA€ ”——WUUɲ|Ï'`µµµ~¿?&&f² 7mÚôÎ;ïtvvööö~ðÁ?þ¸(Šw:)`V‘îBQ£/`†uëÖ8qâá‡~çwþõ¯=ðÀGݺuk”]M-)3Ïf³)Š2ÙÉÙ‰'TUݶm›,Ë’$=òÈ#çܹsQ^íœZRÀl3¹:±pá‚‚‚uëÖ}ùå—N§³¬¬lxxXÝÿýEEE‹EQ”ÊÊÊ„„„Ç{¬¨¨( é;¤¦¦X,ŸÏwâĉššMÓ"äÊÈÈèîîþÏþ Aøïÿ{ñâÅ 6,^¼¸¿¿ÌÎ{ö쉋‹;zôhIIIJJÊŽ;¦–€ -]º´®®Îï÷766ÚívEQl6[rr² )))‡CUÕæææ†††þþþóçÏ«ªªOÈl6›º|ùr}}½×ëõx<¹¹¹‘/]z½ÞÚÚÚðùß?ÿùÏ@ ðíoûÖ†µµµÝÝÝú,°©©I–å©%`BGŽQUõÅ_4™L²,¿üòËŠ¢ìÝ»W’¤ÒÒREQ:¤‡vîÜyíÚµ¡¡!£²²2=š››ëõz?úè£È9ý~ÿ˜ ¡¯¿þz ÈÉɹµ˜é)Ž;¶dɽÉÔ’0>“ÉÔÙÙér¹L&“¾Ål6×ÕÕíß¿_’¤††dzlÙ2=$Šâ¹sç€QE‰7¢gΜQU5+++Âül²…PQ”„„„1[&›0ÛD»jtõêÕ‰‰‰Ÿ}ö™qÏo`` ;;ûù矅B)))]]]===zHÓ´[oÅŒŒÑææfA,Ë Aã†åÝL øŸm!Œ‹‹áæÍ›áƒÁ`(JJJŠ‹‹ Ñgõz½‚ ˜Í擳‰VµŒŽŽFŸh²I³M´…°··WÓ´Å‹ßòù|ׯ_OLLŒ>ë¢E‹Aˆ°†3„_êáßø†¦iW¯^ÚÊÏh’f›h aOOO[[›Õj]µj•>£Z»víàààñãÇeYîèèX¾|ùúõëõP||üÂ… Ã'^¢(fgg[²³³ƒÁ ÓéŒñÓO?]¶l™Ñgrr²ÕjíìììììŒrÌSH À„žyæEQìv{~~þÓO?ýÉ'Ÿø|¾íÛ·‹¢˜ŸŸ¯ªjSSÓîÝ»wíÚõþûïðU£×®]s¹\ÅÅÅyyyo¾ù¦ªªÿþ÷¿#?íþøã^¸páG?úÑSO=UUUvïÞ-I’ ûöíûä“O6nܨ׹[ŸŸZR&$ŠbqqqGG‡ªªªªº\®¼¼<½,I’ôÊ+¯x<UUE9}ú´Ýn_5zöìÙÒÒÒ¾¾>½muuujjêmÓåçç»Ýn½IOOϯýk£ŒUTT¨ªj¬ ·N!)`¶™Ü²I’bcc7lØ0<<ìt:ƒÁ q¿M’$³Ùœ––ÖÛÛëv»ëêêV¬Xa6›GGGõG 4M3›ÍV«u``Àårék^úúúbccoM´mÛ6›Í&Šâœ9s6lØ0gΜ . kVeYEÑ€þ3|M„¤¦²~RŸ„Yr’ššjܽ۲eË©S§:::233õ¤MÔ¶¸¸Øx01ÜÉ“'»ºº"¤›þ€¦VÇÕÚÚúûûçΛžžn2™vïÞ]YY¹üèWVoeÌü¸£fì}c’$%''/]º4&&æâÅ‹%%%ï¾ûîm'aÚfjTD6c3BI’Ÿ—…BÔ3Üc_ºm±XÂß À=¦½½=ü³ckUpoããH åååUUU²,ßóIGmm­ß™lÃM›6½õÖ[W®\éî«ËÏÏ—$éN'Ì*w£Nˆ¢(Šâd[edd¼þúëóæÍ{ë­·ü~ÿ÷¾÷½?þñ¡Pèµ×^ …Bw()3Ïf³)Š2ÙÉYEEE xæ™gdY–$)--ÍãñÔÖÖFyµsjI³ÍäêÄÂ… Ö­[÷å—_:β²²ááa=tÿý÷Y,EQ*++{ì±¢¢"cö–ššZPP`±X|>߉'jjj4M‹kΜ9mmm•••Á`P„––ŸÏwß}÷»óž={âââŽ=ZRR’’’²cÇŽ©%`BK—.­««óûýv»]Q›Í–œœ,BJJŠÃáPUµ¹¹¹¡¡¡¿¿ÿüùóªªê2›Í¦‡._¾\__ïõz=OnnnäK—²,‡OþV®\988øÁŒ;#¬­­íîîÖgMMM²,O-):r䈪ª/¾ø¢Éd’eùå—_VeïÞ½’$•––*ŠrèÐ!=´sçÎk×® …0”••éÑÜÜ\¯×ûÑGMjIçÑ£G@^^Þ¸•LOqìØ±%K–èÝÎHRþ?“ÉÔÙÙér¹L&“¾Ål6×ÕÕíß¿_’¤††dzlÙ2=$Šâ¹sç€QE‰7¢gΜQU5+++ÊùÙÎ;ý~ÿ›o¾9Ñ=?=EBB˜-ÓI ˜ ¢}aõêÕ‰‰‰Ÿ}ö™qÏo`` ;;ûù矅B)))]]]===zHÓ´[oÅŒŒÑææfA,K4©7mÚô»ßýîêÕ«ÅÅÅ£££ö4nXN?)`–ˆ¶ÆÅÅ ‚póæÍðÁ`0 %%%ÅÅÅè³z½^AÌfóm'g+V¬(//—eù¹çžëêêŠ>Åt’fhWöööjš¶xñâ[C>Ÿïúõ뉉‰Ñg]´h‘ ‘×p.X°àèÑ£K–,)**:wîÜ4|F™0«D;#ìééikk³Z­«V­ÒgTk×®<~ü¸,ËË—/_¿~½Š_¸paøÄKÅììlcKvvv0t:‘“á»õ=2SK ˜m&·lD’¤ØØØ 6 ;Î`0hÌ®$I2›Íiii½½½n·»®®nÅŠf³yttTtOÓ4³ÙlµZ\.—¾þ³¯¯/66öÖDÛ¶mûøãÇC( …B²,‹¢h @ÿ¾¦4BR SY?©OÂÆ\`LMMíììÔÿÞ²eË©S§:::233õ¤MÔ¶¸¸Øx01ÜÉ“'§¹Fô¶@˜Z!Wkkk èïïŸ;wnzzºÉdÚ½{weeeäò3Ñg•¦°4€)˜±÷I’”œœ¼téÒ˜˜˜‹/–””¼ûî»·„i˜©QÙŒÍ%I ^" QÏî¸ÿ¿cü% â5@IEND®B`‚jas-2.5/images/device-2012-11-18-jas-trinks-out.png0000644000175000017500000030606312054152672021510 0ustar giovannigiovanni‰PNG  IHDRX² °+sBITÛáOà pHYsÄÄ•+ IDATxœìÝwTWà;³» M:VEQ°7±÷Ó¬‰=1vÅÏ%&&¶X»&–Xc'öލ((EED:ìÒYvgæûct²ÙÆR~ÏÉÉagîܹwö:ïN} ¨r¨Ênü›Ð4ÍqÇqZfIŒÄV„ŸCe®ŒU¿ç敨l‹YYYÉårÃË»»»?þÁƒÅÅú6Š©©éœ9sòòòÒÒÒÊÖ0x§6lXTT¤P(ÔgP´…K×ñ íÚõ°k×þ}ÏÂ×/äÒt¢-d~PÄ¥]€¢(ggç?þø?þHMM5p©”” ‹N:]¾|™eY]Å:vìhee•””¤õ·T"Š¢êÕ«çîîžœœ¬:]TÍÔ¡MW‘±‰±}íjvµHHÑv­»X86`Š‹Òî0…ù•Óh”:ZYY}þùç 6ìÛ·ï‘#GŠŠŠ ZÙÙÙqqqíÛ·úô)MÓÕ«W755522"„0 SPP••Å0L‡âââd2YYºï’»»»æÁŒÈÔÜ¡Û0c{Ššþ»|‡^ËË2³ž„j „”X"±©!±´•ØÖ”'¿,Œö&ˆê¥‹I½†b Ûܨ`á”61³lé#2·,xñ¸ .’è8 +u ¬^½ºT*U(r¹ÜÄÄÄÞÞž¢¨‚‚‚ôôt]‹PU»vm“úõë/X°ÀÔÔ”¢Ô¯MrWXXhllœ““S§Nøøx|8lll:tèðìÙ³ hîà Ešæ(š"„~;—¥iB8¢Yø-ëŽýêÍû•¢iB¨Äß–&Ä1LÏ,­$6nëÏQ´(bx#ŽQBŒê6^†ÉÎ,x]g·yQ÷^ü4‰UjœÑ-m ¤(*111,,ÌÍÍ-(((//oÁ‚FFFQQQ»víbYVkô²±±=z´›››D"áµ277'„´iÓÆÚÚzÛ¶m¸LðH$mÚ´yñâÅ‹/\]]uS²lW—š>.5Åå)v†Ä3zªÍº}Vr‘pT‹cOÕ⥞YZ9M]A‹$ª%g¯/Š÷ݬR.±®ÑtG mŸéçöiTš€¢(''§Q£F¹»»S¥T* ! …‚ã8KKK333=‹×«WÏÕÕU"‘è)Ã0 _¡X,®_¿¾³³³–_ð~Qeddäåå•™™ùøñc-÷ȨàiQÛº¡}õ¶Õ¥dè-L!,ÃÊålqQ©fY¶íaÝy jÌ«ÞÂÛ¼Y‡ôsîÍÉO‘™…¹{»ÔãÛEDzřÉÒ s6]?¢(-QÏ @(‰Ú·oß«W¯?þØÌÌLQÇÝ»w/;;ûÉ“'zÎdš˜˜è‚iii.\8~üx@@@QQ‘‘‘‘©©©! €wŠã¸–-[RõèÑ#=·:òL%"G+SšÈ¤¬/R÷NŽg¬» ±ë;Ji”ĨÞÌŸv,‘'Ç —EæV„¦²¿¯Ù§Ä×pÔúÌ A§F†‰‹‹+,,|ñâ…pw EQÕªUKOOÏÏÏ/qQU\\œ‘‘!yËÈÈH,ó×>¡T*ÅbqjjêÇlÐÆ€wI$5jÔÈÌÌìæÍ›úyæÕªW3ÊW(‹Yn\טôœ›/’K\ª´â×Ï"„âØ7']k}2µ8#YxÚ¾ßh¡ŒR–A8RÍÑ¥àù#~ %6¦DÚCžAã¸ÄÄÄüüü—/_B(Š¢iºuëÖ-[¶´··ðàAvvv‰•ùÄÄÄ$===..Ž*‘a˜GõíÛwÊTºúõë7jÔ( À(H‘¯¸öÈÖÌxfç&‰Ò¼£^¾‹}9§rÜeTñƧӟLïÃýó.V^˜è_gôü‚gåi‰æîmí}ÉküÝЛeärù«W¯úôéãààÀ²¬¥¥e§N?~ìïïmÈÃõÖÖÖ …"77—BQ”‡‡‡H$"„©ž8566‹K}/+T,{{{WW×ÀÀ@Cux… æUv^çúöÅ fwh\ŽÜ ðYvUoúê´S¿%¾Ðœ™°ea½¯rßzPt~ô=Ù –­ºj­ÆÐ“““³wïÞFuïÞÝÑÑ1//oÿþý±±±ÅÅÅ%ž5æ9::~òÉ'§OŸ.((¨W¯ž©½½}çÎÏ;WPP`mm=pà@­ÏWÀ{cggשS§°°0©TjøR!ÆbQ‹Ú6‡#ã_Hó(Šz§g÷Ì·±ðô’X×0soC©VÓ‰’5\y4Ýÿwéí³lAÞËõ³â7úÒÕL˜¼\ÇIß1…yZŸE44r'“Éîß¿åããÓ«W¯ÌÌÌ¢"m·úèXœ¦éž={¶hÑB.—ó7šrGQ”X, 2 óðáÃ/^à à=‰DÍš5ËÊÊŠŽŽÖzÙK÷u+þi’žWHSGˆÊsë¼3·î2Dbm/ :ÏqÌ?žŽçÿ~;Ÿf=׈ͭ!òĸgÿ^ø*FkcJwèJQÔÀ‡.‹óòò6nÜøäÉC®š››·oßÞÇÇÇÚÚš¿k”¦i~ƒrDz,Ã0ÅÅÅÙÙÙ7nÜ 1üÚ,Tš¦[´hajjÌ0ZÞÃï´ûôésóæMÕ£ #‡&Ó~2¶u š«sl±4ãɦEòŒ=«¦DbŽe…ÇáõÏâß»&<>¡R”¦hŠZNQ”H$25',Çäq«ë%m¥~ÅZ^^ÿÀŸ\.7üa^^Þµk×nÞ¼iooocccaa!‘Hhš&„°,«P(òòò233322Š‹‹q,ðþÕ­[·N:J¥²gÏžºöÃütµ¹LQAÆýë´‘±Ö÷H³ŠbeI©'ø·ƒ8‹Óuôűœjpä8N©T攜šÔ3ÍÍÍ{õêåæævûöíàà`ýùµ¯RÇ‘5â@%266‰D%Þ´ÏçHPßcS”î€Â}à) ËrWV“?¥Yá €wŠ211©ì6T¸²¼t›2nõ‰êæfÛý6NëÏjfŸ(ŸRg¨çÊ㥠B8B¨· …˜ªú‘SùƒüóoòvYÕÕ¦ü=ñƒÎáÿZe „˲ büë•92KWlSÞ¿²êO(ognÌ’™'/±*×Z–EŠ$iAÙZPe „˱šÿøT“ºV?}ÑUÉ0+ŽÜ ‘ÁqZ/þBÈçŒêî‘'WNßv9#G®í’!QùPÁÊxz“eYŽe8–áX–ûûoþ#ãdgNäy7|Õ×ÃXL½- ZŒáXÆÙÁìãÎÓ¿_f&&Ãh”ùGùŠí6¯<§FµÏ²25jél#W²¢Úµ#Ã~ý²s²4—/Ìrœê ÕFNù2éÑ#%3§™“m@T"î €÷¬<7Ëh9Ûib$úî“6¶¯_än9B8Nzà€Iûöµ EŠ"üRŠ¢(ŠPTannñãÇÕ:v=~z4Ãqo¦¼ýÏ|äÈÚÇŽ14ÍÌ Lžúõç^ †µw&§Zÿ›µ¼¢²-Ö°}Ÿ|Á#„ã8nJŸf­k˜¦Žû’ÉÈx3•ŽyLLaX›Ÿ¯:‘#D‘’R¡HJú{Êë×Eáám'ÑäQB&!,_3ïuØE¼^*\Ùo–!,!Ô›ØôE÷&^õí3çÏeišªUëÍTŽ#„È !”ƒaYÕ+Š,ÃÈ_¾$ÖÖBIÂqE11©sæ þùg‰˜Ú-šã¸÷s‰pÛ¶m...ýúõctÅ€ÿ¨2_#dÞ bVMÒÓÓYbZ­æ¶mpÐFQ„¦û´¨2èYnA±O~÷Ýw}ûö¥¨7a3+++11q÷îÝwîÜÑÿà?ÏÝÝÝÃÃCXü½5jÔŒ3öíÛ·eË–eKìÅòåË{÷îÍà8.333&&fË–-OŸ>5¤› ©O¼½l—W ÷y6¸]ÃÔys‹BBÇQoï%*ü#̨øçc«WŸ }‘[ çXŽ•×zëV·nÝ&MšÊd2Bˆ••Uÿþý?úè£~øá×_eKºÄH©5¯4¼xñâ'N¬Y³¦Ä©±¶¶vssspp0°uêÔqss ÈÉÉ¡(ÊÁÁaÔ¨QÇŸ4iÒùóç Ê ¼Ïš‹§ lÝ¢¶E‘šk×&ÏŸ_póf™ M;vtX½š•ËûµmP¿¦åÏǃ‹Š•üUÈc!EQ¿ýöÛÙ³gùxдiÓ3gÎÌš5kÛ¶mEEEek!,--ÝÜÜjÕªU¶ÅÕp‰½ (jÇŽ/^ä :ô÷ߟ9sæÅ‹q^  Êüf™7/|éÔ¸Vãü´„O?‰ëÙ3?"ÂþÇ%Í›³ÅRÚÿ$nnv+V䇅½ü裗½{×/ÈìÔ¤&áŽe | ‚eYæ­ÈÈÈððp›¦M›Rµxñâ 6Ðôßý]´hѯ¿þª:ÅÙÙùçŸ>uêÔ®]»ºwﮢ,,,æÍ›wäÈ‘“'O®ZµÊÅÅ…Ÿ»hÑ¢>úˆ¦é¶mÛnÚ´©S§Nüt]åËÙ Í'NœÈÊÊrrr2°rPSÞÇ'Z5ª“sæ¬"#C‘—'=q"»°ØaíZ‰‡CQ !†ÿ'vuµûå—%'=q¢X&+ÎÉ‘þõW»Fu Ë•íñ ŽãLMM9ŽËÈÈà8nРA#GŽT { PBQÔÉ“' P«V­!C†>|xèС|ì±··?}úô·ß~ëææV»ví &\ºt©cÇŽE5iÒ¤AƒEÕ¬Y³U«VöööúË—³š<==­¬¬J[3ðʹ7G„1¥,,à锹¹ÅJå©XÛÕk$Mš~\(vq±ÿå׳ñòb…²°P¨M"ú{E¥jž™™ÙìÙ³Û´isùòåDþ¶U«€jS(Š ðôôôòòš8q¢H$š;w.&—.]Ú²eËíÛ··iÓÆËËkæÌ™666«W¯¦iúË/¿\»v-˲gΜñööö÷÷ç8NOùrö‚×»wï9sæÌ;÷§Ÿ~:tèPJJʲeËJ{yxå½FȲ,ËßBÊq !,Ãøß‰få€5?§Í#Žæ8Nÿq¤~}ûõÎ=Œ?ô¬CS'†aXŽ#ÇÒ4Ëw|ÅqË–-¿üò EQÕ«W‹ÅW®\™2eŠWÎX–]°`B¡ „œ:ujòäÉ^^^íÛ·¿sç΀RSS—-[ÆÏ=xðàgŸ}æããÓ¹sçÀÀ@>qÇ0 ßTýåKìN‰½?~¼ð7MÓáááe¾B e½Føö@eF©Ží–eå© èóaÏmW­¹º²zÏ‘Šœí×­¿õêø­'ŒRÁð—¿aa)JX‹G„ׯ_?~üø±cÇŽ=šššÚ­[·1cÆ~&—¿ÉžÈq\dd$!ÄÕÕµY³f666111ªs=zDiÞ¼¹æÙΦM›–ª|z1jÔ(;;;[[[—I“&ÙØØlÛ¶­Gïÿñ€ÿ€ò>>Á2,óöh…#„eŽeY–;~û !\ÕkRçÎ)~ñ‚¼=.T=2ªWÏnÍÏWŸ¼:vë\Å2oÂ*GKÓ,ÕêˆðرcÂý– 6¼|ùòŒ36mÚT†Ó†™™™„5j˜››BòóóUçæææBªU«¦¹`iË—¡ Ã(•Jþ9Â?ÿü³¨¨hÏž=ãÆ»~ý:n(­rÜ,ñDz,˾="d(Šý{:sìÖãkQ¯ìW­;;³o…cG‘££ýêÕמ½>r3ša”Bm|Xeù#·µx×(÷¦A,˲Ϟ=‹ŒŒ´³³suu¥(J©TŠÅb‰Db`íìì!©©©ñññ,ËÖ¬YSuníÚµ)ŠJMMÕ Ò¥-_ª^h-|ïÞ=BÎŽ”M™á›3– ÉâfÍøûbDuê$¤JߦØeXFy$ðQÀÓD»ŸVŠêÕS½;FT§ŽÃÊU7b’>a” Žeø¥âS2Œš6}S¦V­W©™eNÌËqXV½zuBHjjªH$jÙ²%NlllìììÔn–éܹ³0¥sçÎ ÃDDD$''?~ü¸iӦ‰M33³nݺ^¿~¿4HN]¦¤¤è/_ž^hÅ¿Œ&))©T5¯ìi˜øƒ´€ð¸öŸô#Å)VÆ=úæík„B,LåÅÊB;¬X‘<¾âÕ+Bˆ¤vm‡U«rhI‚±13JÏ.xSš#WBc§JLMicc‹o¾Á2L™_—Â_¥³µµ%„\½zµG?þøãÞ½{«U«6jÔ( ÕÂÅÅÅÛ¶mÛ±cGVVÖ AƒÜÝÝ/]ºôøñcŽã6mÚ´uëÖÝ»woݺ5//oäÈ‘NNN;vìàïä|þü9Çq^^^cÇŽ xùò¥þòåé¯wïÞîîXìââ2hР¢¢¢ßÿ7Ž”AY¯roó¾L‘®?yÇ«©‡‰‘äÚ±[1‰ì›ÀÅÑõ¿‘]%"ŠpŸ~Zã§Ÿ’, ,[sÅ BÓÅìöjêÞjXÇe{¯Á.úeÊæKlÇ&­ ¡®î¿ö2EÊ¿»lŒŠŠðûûû:ô—_~™>}z||¼þòåé?E¸k”eÙÌÌÌ{÷îmذáÆxÅ@”ñ>ÃOË–ÿ]EQ„#Ü?_­æQ¿æ¸¦Iÿ›OÆÈÅ¥æÊUl^.!Ddi•øõWLZ‰œ6oþ-äEäóîmf Š"Q©ímšúè3[ô\)¤iš¦iáÕ‰üÅ6þ£­­mÓ¦MããããããùçùP'‰!ÇÕ¨QÃÝÝ=555::šŸ%TeddÔªU+ccã‡J¥RÕ¨&‰š5kfbb"¬KOy=-Ôß þoÕø’lin)Ue¾k”QÍP¯u\ÛÖ\žšÂ°,á¸ÂçÏ Ë„%f1,ÛÞÝ\Á¿'E©,ˆ­ck—$¼MT{m%íä…X¢g"˲éééZœ„›-“““SRRÈÛ£ºlQQÑ;w4gñ‹?|øPu–þòzZ¨¿Z @y”÷¡þ2,õv·Íq Ë^ {ÎrlëÆNìÛÐÆ2 K—î©ùr*qEz ”vŽÒ>|eŽe9áKŽã(Šâ÷ûOd†úûvO–eYFÉŽdž Ër„á8-¯“ œÀ»TŽS£ÿ¼$(ü-üQX$'VÆüûÒˆHÄrœ\QÌ0,ËN"a•JB's¬ÊU1•4ö×PïFy³Oèù/âÙ+‘[cQ: !}ú¼JÏΔåeåäÇ%g˜õìÉд¸~}IÆ‘±‰üûhÞüÇi«Í°êJ«œ×Ußþ>j{3E–[p%ô©Ï²ï%…RJ|.ð!Ë0á.?Þo`½bÉ•¨ÙùÜ?ý¨þ!LÇQ!T¼2>>ѼÏèåIäz‹ÖS¬œÆtÍ)jÓux'Êsjô½ÔáÞ…2~Qõ¾#2¡Zý_Ùm¨4bJTÆgêþ(B0˜««+E•1ç3€.WðŽÐ•ÝøÂÞ ÞŒ+xG JC €* ª4B¨Ò JC €* ª4B¨Ò JC €* ª4B¨Ò JWv>8îîîÓ§O¿páBvvöçŸNQTqqq\\ÜîÝ»³³³}||FŒAQ”\.‹‹ûã?¤Rie7*S«V­&MšDÓÿ¦Ü½{·B¡˜8q"MÓ,Ë&%%?>44”㸺uë.^¼øÑ£G[·nõóó«Y³¦jUñññ+W®dYö‹/¾èÙ³§‘‘у¶nÝ*•J…µ°,›‘‘qáÂ…   ŽãÞ{wá«]»ö”)S5j”ŸŸöìÙS§Nñ_ô¤I“:uêDQThhèöíÛår¹®Q¡:ÌZ´h!ŒÏìììÐÐÐ#GŽp·lÙ2­Ã¯fÍšZ×UK¯^½¤RéÒ¥K'Mš$“É?~!•JÍÌÌ&NœÈO|ðàL&»uëVµjÕ*»Éœ† VŒ9Æ “J¥/^¼¸÷Vÿþý?úè#~âýû÷“’’’““§OŸNÓt³fͤRéÑ£GE"ÑÑ£GïÝ»›““óøñã{÷îíÛ·O$­_¿^&“EEEÝ»wO&“]¿~½ZµjÂZîß¿ÿúõëÌÌÌ)S¦¨Fߪ *Œ+{{û{÷§_¾|ùÑ£G2™lîܹ4MïØ±C&“Ëd²?ÿüS$éªÃLu|ÆÆÆfggïܹ“¦i­Ã¯FZ×^Ù[Þ»^½zÉd2??¿É“'gggOž>žeYooïÞ½{gdd¸¹¹ùøø´hÑB$]¿~]©T2 ³zõê9sæäççó‹2*ø2ùùù¯_¿¦(ÊÞÞ^ëðÓºv†aÞ_ÿ+ a ¦M›vóæÍéÓ§ŸýìÙ3ì’`äÈ‘¡¡¡ááá;wîTûÍqÿk©zõê%ÖcggGÉÎÎæ?¾~ýšã8>‚öîÝûúõë7nÜ(((à¯&V|O Rݽ{wÅŠööö 3gÇqVVV„¼¼<¾ÌíÛ·wïÞÀ4dT¸¹¹-Y²dãÆ}úôyùò%ÅÚÀµ¿³¾~@p³L ¤RiFF†“““§§§°?Ú³gϽ{÷ºuë6räÈ   ;wb—TÅ]¾|Ùßߟ㸔”ÍÁ`ddD1d( BˆXüæfµjÕ(ŠR*•üÇüüü””SSSWW×–-[ž;w®Šì§ªŽãÖ®]»ÿþQ£F}üñÇ‹/®W¯ÿCJ¸V'œšâiŽ Íj›7oÞ¨Q£‚‚‚›7o®X±¢¨¨ÈðµÏ˜1ã?¿Ãa <8räÈuëÖ¹¸¸ôëׄϞ=;~üø’%KX–mÛ¶me·*_RRÒöïßåÊÍàäááAQT\\\‰qëùóç„777þ£——!$>>ž_0((hôèÑüý\Ÿ}öÙþ‚Y4qâÄ£Gººº®_¿¾k×®III}ûö'„4hЀ/óý÷ßGDD´k׎†ŒŠ£G6jÔÈÃÃã“O>¹ÿ¾®q¨uíUa˜áˆ°ü¹õäädº´%¡ IDATŠ¢¬­­ !-Z´˜2eJÛ¶mE"Qllle·*Ÿ³³óäÉ“ùýËõë×ù‰õêÕûꫯ<==ûõë~þüùÆë¯ç¯¿þš;wîgŸ}–’’’––6cÆ …BÁßÎGÞŽF™L&•Jííí«ÂªªQ(=zô°°°Ø¾}»½½½­­í‹/Î;çëë;bĈW¯^Œ5J$=}ú´N:İQÁqœR©,ñÀNëÚßI??0„yùò%˲Mš4 '„Œ3†eYþ¾¬_~ùå?ÞJäããÓ¥Kþïo¾ù¦  €âííÝ©S§ŒŒŒS§N-]ºT8é‡L&ûæ›o~þùç… R•ššº`Á‚;wî 2DµXjjª««kÛ¶mïÞ½‹³£ÿ%üñGƒ F½k×.BHLLÌÂ… ÓÒÒ¾ù曟~úé‡~ iúÕ«W~~~999jË £B¸šX!kÇþ­*¢(J,Ó4MÓ4ÿ‡æDž°Ñª*Üæ.àdž*Š¢T'ŠD"aœðÓUï¦QfB‘HäêêÚ¼ysÍÈ—‰DüŠÞcG+_W4M‹D¢Æ;::òOã·£ÂÑÑÑÅÅEu¢ÖQ¡:ÌÔÊh®Km®Öµ@©U‘Ö;ÅïÎ*»–*5®*·§Ug;ópjàC„žU\倪6üpfª4B¨Ò JC €* ª4B¨Ò JC €* ª4B¨Ò JC €*  BUµ.ð~`\T<ªÕ_ñ•Ýø¯ Ö€c”•Ý ƒˆ)ró@Õ…›e JC €* çEá0oÚžà?¨PyQÁæîí0® Â!Â;ÑðÇC¸ü +|¨ Ƽ FT8ŽQb\A…ø€ÿŒ›É¬­„¦+»ïÒ?ãJØ£iDAøïûg¼Cä€*MüOŽ®dÆB¸Jj À»W¯y'|R „¯Ÿš&4EU Íx?^Å‘ÄgÂAŸJÌ£hD@¨8B8¶²UU†e$ÉüùóišŽ=|ø0ÇqÞ,(¿Zµj%''Wv+tRkÞܹsMMM_¿~½gÏ–e+±a%³°°ËåÑÑÑ«V­¢iú=¬ñøñã_ýõ»^ׄ üýýE"Ñ{[£åi€D"9zôèºuëô/^â*ªU«véÒ¥Ï>ûŒ¢ÊòƒI%¡¡¡ãÆÖ~æÌ™äääàà`~û¼7eÜÑÓ4½{÷îÅ‹³,ûìÙ³ÜÜÜÜÜ\™L»}ûv;;»Šm¥‰‰‰D"©Ø:5¹ººz{{óûkÕ5¶oßÞËË«<Á  é²®†­\¹²Q£F«V­bYVOãK\…D"éÚµ«““Syú®«’åË—¯Y³¦cÇŽüô!C†„……½ç PF …Â××—ÿ9Ÿ˜˜¸oß>//¯Î;Ïœ93++k÷îÝû»^$½‡ƒ³•+WJ¥R±X¬¶Æ .¾ç#Cº¬µa-[¶ÌÍÍýä“Oø ¢§ñ%®Bí‹.]•Påïï ´íÌ™3!!!8"€÷¬,;ccãÿýïW¯^½sçÇqsæÌ‰ŒŒÜ¹sgBBBHHˆ››[çÎ7mÚdnn¾pᤤ$BH—.]ÆŒsëÖ-±X¼dÉ’´´´Ï?ÿ|ܸqõë׿ÿ>Çq‰DëtBȼyó,,,âââô”!„Œ;vêÔ©Í›7ýúõŒ3nÞ¼©výràÀ³fÍòòò’J¥©©©üÄÉ“'Oœ8±Aƒ–––­[·^³f ˲§OŸÞ³gO+++[[Ûèèè¼¼¼Θ1£_¿~ Ã<þœ·J*•Nš4©yóæªM"„L˜0aâĉ^^^ R©”Ÿ8|øðéÓ§ûøødff¦¤¤hÖ0wî\Õ.ÇÆÆNŸ>}̘1vvv>ä8N³a|ÍË—/·´´œ9s&˲ªebccgÏž­gš[Uí‹öõõussã×®µS<µ¾<|øpþüù;w3fL5}ºfÍÕCŸÃ‡§§§;vìáÇiiiü&]¾|yAAÁ… nݺ%“ÉzõêU½zuµÔºüìÙ³+W®ÜºuK©T®\¹R³aÂ7õôéÓ]»vñmP-ãááQ\\¬gZ¿á‹^³fM^^ÞàÁƒ)ŠÒÚ)Õá¡ÚKKK…B‘ššzãÆ€€…BñóÏ?óÍ322JKK®eâˆ*‡ƒƒCDDDaaáÅ‹?þøc~¦u¢@3,]ºtÙ²eÌÊÊúòË/)ŠrttT(Ó§Oç‹-Y²¤¨¨ˆ„ …bóæÍ‰D$íÚµ+))IÏtBHZZÚ† „]³fKKË”””ýû÷‰D¢;wªB''§ÌÌ̵k×ò †……9r¤^½zÙÙÙBm‡–Édjk¤iúòåË·oß622rttÌÌÌÜ´i_þ÷ßOII±··ç[µoß>###Õ(X­Zµ‚‚???‰Dbee4oÞ<©Tºf;’Û·oŸ8qÂÊÊJ­µ.oÙ²…/àÀŒŒ {{{Õ† _™™YaaáÒ¥KùJTËT¯^]ÿ*t}#¾¾¾ŸþyAAÁ’%KD"‘ÖN©öZmkðÿøãþ«ÙµkWVVV­ZµøÂ§OŸæƒ!T :--­uëÖC‡ÍÈÈØ¾}{xxøÔ©S3224'ê¹PäììÜ«W¯îÝ»{{{geeñgºô{ùò%Ã0 ÃÄÅÅÙÚÚ–8]ÿ²­[·¶³³;zô¨B¡`&&&FmoooKKK''§Í›7oÝºÕØØØÕÕµC‡fffP*• ü|ùRó¤˲ÇqÇ0LçÎ---ÿøã¾üÁƒíììÚµkÇÇ¡ÈÈH¥R©zëQQÑ“'OF5þ|GGÇ.]º¬[·®S§NÕ«W?tè_É”)SV¬XÁ/¥Yƒf—8`eeÕ¶m[î-†a„f×®]["‘dddh6ž/cÈ*Ô¶|Ÿ>}6lØpîܹ•+W2 £µSšª­èÑ£G|8P½zõ¶mÛòM*•Z[[ký–ÞšÂ0Ì¥K—fÏž½qãÆÚµk?ž¢(­uÕrþüùîÝ»wíÚÕÃÃ#??Ù²e†ß^Á²¬Öº¦k-S»vmBÈ«W¯øéšñÌÖÖ–¢(š¦ÍÍÍÍÍÍ>|P£F Š¢´Æ?­ììì(Šzýú5_>%%…âàà k¥„Aƒùûû><$$äòåËÎÎÎ666ü²|ù¨¨(ᚢžf³^¾|I©Y³fÙn°4¤§j[ÞÚÚÚÔÔ477—a]ÒlŒÚŠ„ü$¡ý¸•Ž&„ôèÑcß¾}ÑÑÑcƌٱcÇ Aƒ†Ñ:QW-ü1Ã02™,$$¤^½zE¥§§+•J33³÷Ð >6hÐ@WçÏŸs÷ÇŒ;v̘1£Gž7o^bb"Çq760¨ÄÅÅq׺uk¾|óæÍ !ÑÑѺÊ7hÐ`È!«W¯nÛ¶­———››Û’%Kø¸ëééÉW2hРÏ?ÿÜð¨æææF‚±š¤¤$…BQ±¯üùçŸ?üðÃèѣǎKQ”ÖN•ø“Eè`Æ ùvòí·¶¶–ÉdØZ€Ò¢ëׯöìÙ† .Z´¨qãÆK—.MNNvvvÖœh`EEEÆÆÆü/^¼àïZôðð1bÄ»{"$$$>>~ÆŒõë×wqq1b„Zh¹zõ*Û¤ƒƒƒD"3fÌ Aƒ®_¿ž––¶páBGGÇÆ4Hk óóómmmΟ?íëë[§N''§Y³f………Ý»wO×a™™ÙÚµkçÌ™Ãq\aa!ÇqÅÅÅ/^|þüùܹsíìì7n¼nÝ:Ÿá€lmmkÕª5gΜ¤¤¤Û·os'4Lµ© ÎÎΚ7|cªá8nýúõçÎ[µj•»»»¹¹¹f§ø›‡ûöí««#_|ñEÆ œœ|}}“’’„zkÕªƒãB¨Dtvvö!C:uê´cÇ…BÁ_ÔÉÉÉÑœh ¨¨([[[þÉôåË—7oÞ<99ùÚµkü-øï¨………sæÌ©_¿þÓ§OÃÂÂÔnèç L›6­fÍšqqq™™™+V¬¨[·nvv¶¯¯¯‡‡G\\ÜÝ»wÕ{œ8qÂÉÉéåË—îîîÓ§O·³³‹‰‰‰‰‰177Ÿ5k–žåÈÈH??¿‰'Êd²ˆˆˆ—/_®X±¢¨¨hæÌ™... ÏŸ?÷óó3d ?yòäùóç®®®sçÎÍÏÏWmXÓ¦M…tëÖ-á²¥jÃ|5±,;uêÔüüü;v<{öL³S,ËΟ?¿_¿~ºVפI“¹sçæääBú÷ïokkëïï@•LëÎKÏNSí®Q±X¬z EÓ´X,æ§(ÊÄĤM›6666üt¾Œê"¥®« EQb±ØÓÓÓÂÂbÅŠ£ñª=‰DžžžmÛ¶•H$|%üR­[·vpp‰DZ×HQTݺu›5kFÓ4_I‹-š7o.tSs#¨n “–-[Ö«WO¸’¯¤uëÖªÕj>ò[{þüùÖÖÖ-Z´H$ÂJU&,غuë¼¼¼¡C‡ _PF×* Üò"‘ˆo­ÖNéªMøX£F6mÚ¨¶ÿðáÃ7nÜÖ…»Fà_ƒß5çåå:tÈÝÖûyoVß¾}çÍ›7`À€ñãÇ'$$\¾|YkÛ(ŠÒl!-T-£µ—-ÕJÉ?vREQëׯˆˆàïÊ)ÕºJ¥ uª.Ò¯_¿´´4þiNBHll¬\.¿wï!ü;tëÖ­{÷îÎË!?ùä“ÈÈÈœœœÔÔÔ3gÎ4iÒäÃi[y˜™™½xñbÊ”)†_a¥iúøñãk×®­Ä—†—(44t„ B ½½½»wï.܈ð¡£Þªì†ü?ß(‹Åb±H$ú ÚVNexÕªH$Zÿ0ÕªUKµSàˆèfòÓÊÌÌlóæÍááá¿þúë©S§ÊŸê¯Ä5»#‘Hœœœ*»£b®!©fòÓjΜ9ãÆ»páÂ¥K—ŒËŸ\°Ä5VŠJÉ\XN±±±|:ɬ¬¬'Ožüøãz~£8::ž8qB*•ÆÅÅ¥¤¤è)|óæÍœœœ\ BBÁ˜1c²³³ÕŠmÛ¶MkÍBksrr^½zuæÌ™V­ZiÝàLjˆ~*EFF oß¾}åÊü€ £šÉO«“'O†††ò·ÎWHrÁ×X)*%sa9%''óé$}||üüü -Z¤ë :uêT\\\Ïž=mllfΜYPP +[a³fÍ:tèСC‡C‡%&&vêÔ‰ÿhaa¡VÒÞÞ¾}ûöÞZ¾|yqqñ§Ÿ~ª5¼ ­íСçŸ~úàÁƒèèh+++Í’Ë—/—ËåŽŽŽ„''§¢¢"†aøúXXXäææª¦L€ª¬\dòäÉ-[¶|òä‰ÚeàÀýû÷—J¥ÇŽ‹ˆˆøæ›o\]]MMM—,Y²víÚÉ“'GFF^¼xQ,/Z´èÈ‘#=zôhÚ´iTTÔ–-[„GËÕ*៹ֵFÁرc;uê”pèС1cÆüðÃ|…jµ•jÕ|á“'O<˜ÏVÁ²ì°aúvíÊ0ÌéÓ§øNNNFFF~~~[·nMNN8p`ß¾}9Ž;}úôåË—ùœ‹šUM˜0¡U«VR©tÏž=ü[ÜæÌ™óøñã‹/jæSÔZa©¶¡¦ÜÜÜàà`–eoÞ¼Ù§OooïU«Vi-Ù¾}ûãÇ_¿~a˜7véÒ¥[·nëÖ­Ó,%TÎ0LHHˆR©$Ú^.šžž.¼%¼~ýúãÇ?tèÐñãÇKlmppp~~þ©S§¼½½Ïœ9£VþÆ ,èÙ³çž={ À²¬L&ÿŸ«ÖL¸zõêììì¿þúëÆEEE_|ñEQeË\¨5·_JJÊ/¿ü¢ì-Z¤«B÷¡æ÷˜œœ,Õ©S'11qëÖ­º~g„„„>ÞÀc÷Ó§OÇÅÅÕ¨QCWÕÖB|||”Jå°aô>š‘‘Á>tèЃÏŸ?/‰~üñÇ‚‚‚Š}#+ü»-\¸ð;“'O¦iZJBGGG­™ü´¦ý“H$.\¸{÷®‘‘1 ^isòt¥$ÔZŸ-ÖÀUó…U3ùíß¿Μ9|™ .ðç{K›¹PWn?Í÷Ôè¯ÐÀŽh ZÉÉÉ wîÜ NKK ׇ|||bcc³³³Ïœ93~üxþ ÕÏð@øõ×_ >\ÏEÖäää;wÖ«WÏÑÑÑÛÛ›Ïn¯+]×õë×oݺ%‰âââ6oÞ¼|ùòôôt±X|æÌ™°°°×lxwÄ„Íó`,Ëòy {öì9vìØíÛ·ûí·;vìØ¶mÚ­}ûöB&?Žã„LFªiÿ!|Ú?Õ¬xš-àÓà±,+¤ÁÓZ‰jî@Õ5 TSr'¤$ÔZ¿«5pÕšé¿øâ‹6mÚŒ;¶zõêb±˜‡‹®Ì…Ç­Ò¥K—ÂÃÃcbb¦N:~üøíÛ·óeteòSMûGyøðarr²{! žÖJJ̨+%¡!MÒ¿jµd‰dÿþý½{÷ÎË˳µµMMMUkŒá™  4{öìáÇûí·wïÞ0a‹/4û¨¿ÂRuDSLLÌúõëùè{ãÆ ÿ#F8p@³<ÇqYYY¿þúëÆ[µjuòäÉüqäÈ‘zÞlذºuë¾ÓWÀÀ¿Ë›Khªg®¤R)¿—éѣǸqãø»-vìØ±yófa'ÅïU7n¬¶{Òþ={Vˆ¥J^¡«’¡C‡j]£@HI^bmº²$R¸W¯^}ôѤI“öïßÏqÜ™3g4OÍ ™ ùÄ{º26hРwïÞ«W¯^°`§§çÙ³g—,Y2qâDÍ```…ú;¢ë‹àgñs£££)в²²¢(Jm;wëÖí÷ߟ8qâõë×Y–½ÿþÝ»wùüˆå4kÖ¬®]»Ž1"33³ÄÂ,Ë ‡æú]¾|9//¯gÏž!!!|¼¼}ûv=X–½pá!üÒ@qvv.** þꫯ„\ ++«¤¤¤Ë—/;995nÜ8**Š¿uÅÄÄ$:::  víÚÕªUûòË/‡ BQÔùóçïܹÃ_•Q»F(Ü¿páB…B¡«kkk­kšdbbwóæM—°°0–euÕV½zuÃW­V¸ÿþJ¥ræÌ™¶¶¶³gÏÎÍͽÿ>ßµ“'O>yò¤V­ZE=zôèæÍ›uëÖurr ‹Åj]öôô,((X±bMÓ7~ýúõöíÛišÖÌíg`…ú;Ò¼yó;wº»»«Ö¬zÕ­M›6'OžÌÉÉñðððôôT+\½zõ„„„   æÍ›SÕ¥K—ׯ_ó·VyxxhÖÌS»F¨YÒÝÝ=##cÿþýÎÎÎŽoÕ¨QC³Dãf®±,;}út~þ,tTT.@Élllúôé£+»!dÔ¨Q))) …B&“íÝ»W¸u¥gÏžÑÑÑ………ùùùÉÉÉß|ó MÓ¥ „º*ѵFÁ!CùW¯^å¡ÖÚtBC SuòäI¥RY\\|ùòåS§N=}ú”ïÚ˜1còóóåryÓ¦M»uëöäÉ“ÂÂB¹\þøñcþA{µ.Såë뛞žž““STTtûöm>§®Ö»F»víZb…ú;2lØ0…BÑ¥KµÐÂ0ŒR©T(999| å¡C‡jîÔ©Óõë×‹ŠŠd2Yaaá_ýÅŸžÕZ˜§5KΛ7¿ÀÉ·6|øp­­Õu5`ãÆ………uëÖå?š››K¥Ò}ûö!€Aô¿!EW&?­iÿTï³70¹ á¹Õ𤙒Pkm¥ZµÚ‘HÔ AƒfÍšñ/øVM4XÚÌ…%æöSí]‰êŸ_xx¸Úvÿ“ð¾r­…ù:Ú¶mkee%4XkaÍ&i-ÉÐl†®Öjýe¦«jkçk@€Š¤+XVH&ÒæÔŸ’°TM*±°žj§4 Yi6LOùµk×ò<² þÂjÓ ¯ù]”,ma€ÿ¬ÿjJŠ¢+µïû,ü.J–¶0€ªÿÔ¾ƒ`€ß!꿱*_æÎ­U«Öž‰Þ)|ûeVÂ]Ç·µµ «ÄC«ò´áCh¿V‰äÏ?ÿlÖ¬™ê+NêׯÏqœ\.׺ˆ®¹BUß~ûmqqñÇ+°³‰¤nݺÙÙÙUá‡ïCoe¨çÆ …¢b¿}€*‚&„<{öŒÏñ&“Ébcc·oß.¼ØÄĤü¹UžONйsçFé)ð>Û_QV®\Ù¨Q£U«Vñ†/[¶,)))&&&%%åÆjï:×?W¨êûï¿_³ff¿¶mÛÊd2>íÿªnCr–˜z°ÄŒƒ†$,q<’V°C‡j4¼~MÂx+± š–/_®õÛƒ$&&ò9Þ:wîͯ‹¢¨(ŠAƒñŸiÓ¦7öîÝ[XPØ)Lž<ù«¯¾Ö;a„©S§Ò4ýŽÚ/пìÀ·lÙòã?¶lÙ’¢¨Ñ£G ìСÃܹsù¿ÝÜܾûî»ÆSõÛo¿=~ü˜¾ÍÂÂ"==ý÷ßç ¤(ªaÆüû<ùwè™KQ­ŠòÑGwíÚUí)x™LÖ¤I¹\Þ¶m[Š¢T¿š¦ƒ‚‚øüDjßÔ¦M›ø‰4M?~üܹsš£PÅ?2Ïg]Vûº…2...III{÷îÕ\‹žñ@éÕ«ä(Šúúë¯ 233¿ýö[š¦¬T*GŽÙ¹sgµþ«ÇÑ„jclÀ€~~~ÖÖÖ„›¥K—<˜¢(­ß>„ÿ‡-ü«;vìØ£GøØ)))%æÔ•PëëQôä“Óšo¨ì¶lÙ’››Ë¿\ÛÂÂ"##c÷îÝÂŽ©ÂÛ/(UοիWgdd˜˜˜BöîÝ«P(Z·nMQÔÂ… óòòøÆ?}út×®]| }ûöU*•Ÿ}ö™°ó¢(êÚµkAAA"‘Hÿ\µª!FFFiiiëÖ­SÝìîîîßÿ½¥¥å† ø¥ ÉAhxêAC-éJ4Xb~AÊ€´‚M›6Uë !õ°ãü3jޱæÍ›geeñ+Z·nL&ãÿÖo ’˜˜°‹“u^ IDATtéÒeË–|(‰ôÏU«ŠqúôiµC7¾€PÌ„†§,1êI4hH~ÁÓ jv°Äú?äñ¦ZÖ1&‹ýüüd2Yÿþýe2ÙO?ý$|Ýšß>”èÍŽÃÙÙ¹W¯^Ý»w÷ööÎÊÊŠ×ZšÏ{Ç0Œ÷N5 Ã0B@Bˆ®ãÇ‹‹{þü¹¿¿?!„Ï'§šoa˜ƒÚÙÙµk×Nu×Þ¿Š¢øôéÓëׯó÷Ƚ‹ö—¸¬jο­[·ò9ÿ}||úöíkkk{üøñ=zPåééÈq\íÚµ%IFFF ߌ´V%•Jù“f!ï„ê×ñìÙ³'N=zt÷îÝöööGUÛ{ò©ýüüªU«¶qãÆ   !5c©”˜hPëxP-Ú¤I!­àÉ“'­­­ù´‚ü}•Z;¨¿þ¼ñ´Ž1Žã~øá‡èèèƒ>þÜÏÏOHW¢ùí@‰ÞÂóçÏwïÞ½k×®ùùùË–-ÓvEÈ{§+  ;wî455511qppèÖ­Û78Ž3$ßÇq'Nœèرc:uºtérîÜ9aÇ÷>Û¯5矹¹ùÇX–½{÷nÛ¶m‡ rÿþýÇ{zzzyy9;;Ÿ9sF³þœœBHÍš5U'ÚØØðÁ@ÿ\­ ¼{žÏA¸nݺ… Nž<¹cÇŽ#FŒP BêÁ>}útíÚµfÍšZo.-Q‰‰µŽÕ–––BZÁ°°°R¥üW7­cŒüªÏN”Á›½|^u†ad2YHHH½zõ üí/d4|•|žÃ0ü?]!ß¿^]ùööìÙÃ0̪U«,,,öîÝ+ü³Ÿí9ÿÆŽ;f̘ѣGÏ›7eÙ+W®4kÖÌËËëÒ¥KÁÁÁ/_¾œ?~bbâÝ»w9ŽKJJR( ÷wïÞÍËËS½Á¡N:žžžüaúçªUų¶¶–Éd%6^ÈAȲ¬jB~n·nÝž?Þ½{w~Ö9õ ŸhÐ××WO¢A­ãAU9Ó þ«Ç›®1Ö¢E‹É“'_¹reܸqB/ˆÁß>¨Òò3¶¨¨ÈØØØÀåCBBâããg̘Q¿~}Õ£ ­wêrþüùèèh__ß:uê899Íš5+,,ìÞ½{j»¹”””«W¯>üÞ½{Ož<Ѻ|oí¿zõjllììÙ³$ɘ1cøÛýýý«U«Ö Aƒ?ÿü“a˜«W¯öèÑãîÝ»üñD~~~BBŸn‰’™™¹wïÞ±cÇΘ1ÃÚÚºM›6û÷ï·²²Ú¾};ÇqúçªUÅ«U«VLL ÇqzrB$ Ÿù¯M›6k×®-((¸qãF³fÍøEBCCÅbñòåËù¼½½;vìEtgþš6múí·ß;v,<<¼nݺú ꪄ¢¨ÂÂÂÇ;::^¹r…ÿƯ\¹R§NgÏžñGrz–ÕUÿ¿e¼éc6lxõêÕ Aƒž>}ªzKšðíØ ZaTT”­­­Ú ºΙ3§~ýúOŸ> “J¥Â¬ùóç÷ë×ÏÀ@ÈqÜ´iÓìììbbbbbbÌÍÍgÍš¥õdÚŸþIÓô‰'tå(oí/,,œ6mZÍš5ãââ233W¬XQ·n]Š¢ÒÓÓÃÃÃ###ùKGÇŽ322vâ„[·n©^Žš={öž={¾ûî»ÔÔÔ;wšæççÿöÛoüQýsÕªêß¿¿­­­¿¿?Çq 4øòË/ÕŽ•³k×®Õ¯_Ê”)QQQ...ü"¹¹¹#FŒËåÁÁÁR©ôâÅ‹¡¡¡³gÏfFµ„¡@ÿþý­­­GŽûü­óçÏ7lØP ª•ðCCCårùÉ“'ù/Ýßß?777,,Ìeµú·Œ7­cìÿûŸ———ŸŸŸB¡X¼xqË–-/^LÓ´ê·_bKà43ä éî ̨5  Ö»Fõdú¥ Kàçëë+“ÉTïr|í/UòBòχ øúU[غuë¼¼¼¡C‡ }¤iÚÚÚºC‡ŽŽŽ"‘¨OŸ>÷ïßçÓ?W­ªÃ‡߸qƒožž†ä ¤ N=HëÈ8HhÐÀü‚tiÒ R?ù÷Œ7Í1¦ºFÕÑ¥úíÀ{¥? `ii>”-°³³8p`||üÁƒ+ðñò·_O›u•_¿~}DD„Útá!8韫ZU¿~ýÒÒÒ:wîÌÏ*CŠ>­‹¨},±Úò0°L…,ûoo%Ž1µoÞ«÷–ðã?ÎÎξ}û¶““SV[)Y ù' ×®][þgŸ…ªÂÃÃ'L˜ zRÚŽ²H‰eÊ_ÀÀ2ïbYUÿ®ñªúíÀ{Å ¨d{G+ÒsB¬<Õ¾Ÿö«‰D•:‡¯ªV­ZØV ×x÷P5”}ûøñã¶¶¶aaaÇi-P­ZµsçÎ?~ü¸Ì(U%––––––ùùùjÓíììLMM ÊÜŒ2+q+}È+š0aÂwß}wôèÑë4díºÊ”vÙò÷Ôð~@GBÚ·oïååEQ”æl‰D¢gy‰DÒµkW'''­‹ÈÀJZ´h˜œœüêÕ«ÐÐÐ6mÚðå;vìx÷îÝW¯^%%%………uèС<)ƒ·REéܹs£F*¶NWWWoooC¶˜!ÝT-£:® YVµwåߤ†÷«BèùGT¶ecccssssss³²²žýôSŠ¢jÔ¨ñêÕ« 6DEEqwáÂ…/¿üRõÇõèÑ£ÍÍÍwìØÁ²l‡:uê´~ýz–eÝÜÜFŒqøðá§OŸr7lذ®]»2 súô退ŽãÔ¹cÇŽ hÝn¥±cÇvêÔ)!!áСCcÆŒùá‡X–:¨vO³=ªsÕÚ¶yóf–eØ¿©TzìØ±ˆˆ~]õLž<¹eË–Ož<ö­“'O¦išßP„ &ÿŸ½óˆâÚþøÝÅHQ¤¨‚%– Å.±÷‚šÄË/b‰øbb¢I4‰ña Ö(Ï®Ï. (X@A@AŠQ@@)²€€ô¶í÷Ç}N&;egwv—59Ÿ¿àî½gÎ=÷Ü;³3wçûξ}ûHÿùt“¬óÅ_yµwïÞ9sæàrn¯HH;ýúõ7nu@CBB&&fÁ‚ÏŸ?W³Ìöovv6B¨uëÖA¨Õ±³³;~üxnn®¯¯/õòâÅ‹7"„^½zµzõêÍ›7‘fcbbÜÝÝ›7oþðáÃÓ§O/Z´hàÀÎÎÎÁÁÁøáÍñãÇGUÕªU«ÂÂBÑP‹w|¿177—Û&†Û*¤V­Z!‰š5k†JNN–J¥‰äèÑ£t;öööøË1=þ.\øæ›o†J>¦ÕŸPèÐ;*¿þú«››ÛÔ©Sñ°2ö—­_$-[¶Dà üñBï1~ùò%.,((@ÙÙÙqô‘1·µí Ÿ ={ö ?ÏFEDD\¾|ÙÛÛ›zý€^ÐÏ#‡3gÎüøãsæÌ™;w.A;vœ2eʯ¿þêîî>pàÀ.]º|ûí·§=y_¨sçΡüü|ú„ ´°°˜={vYY.éѣǕ+Wúõë§R©”Je~~~Ó¦MñúHîêê:pàÀ7nÄÆÆ¾xñbíÚµyyy111*•jÔ¨QÓ§O_µjÕĉ?úè#!?ˆdŸ;vìȧ²þdee©Tª£GÎ;÷ÓO?3gΚ5kFŒÁhG*•ªTª®]»Ò÷úÿç?ÿQ([¶l±´´}úPÓöêÕ«gÏžÔüaë#cnS;˧ƒj¹A¶¥F[­×pS Ž!¦™6uvß Ô­­ðæ;vìš5k&L˜0þüœœœ°°0î·è潇µr›‰'fggŸÌœ93%%¥¢¢¢°°088¸[·n¦¶ð͘1£¼¼<**ÊÉÉ©±}0¦µÿÁÛýñÉï4µ‡=ø!þA[cû€Q=B=z„뀡n˜™™á ±íü=B=z„Œu@PH[GGÇ .¼~ý:33³  ôÀ°€¡@@±è i{éÒ¥ÌÌÌ‘#GZ[[¯X±¢¦¦Fà,€ Ð#=BÐ#4E=ÂþýûŸ?þöíÛ …b÷îÝC‡õôôܶmc§è"Ð#=BÓÓ#Œ‹‹{üøqçÎq õ‡ùèÐ#D Gz„¦§G8lذŒŒŒòòòàààùóç7iÒDÇ€&@ôAÐõ###ûõë7wî܉'îÞ½{Ù²eü±Ú#ôÃs}é^¾|ÙËË+...,,ÌÙÙ™¾¡Ž¡Zn=ÂeË–,\¸ÐÆÆ†jëN™2뺹¹©éž|hccCh¯GÈ‘Û<;¨1h*•ª´´t×®]cÆŒ>|xëÖ­aã(Ð#=Â?=BÑ#ôôôÌÊÊúðÃñ7ŇÆÄÄtéÒEShô=BÐ#41=Âøøx‰D²iÓ&|Ú2dÈ€þøãn;èè‚!èšœaEE…··w}}}llìëׯ¯_¿¿jÕ*x , 6Ý8z„ GHôÉ¿ Gˆ½²³³swwoÑ¢üvŒ!^F¥›¢žÎÇÒ})ä±z„<½ÒÖ8ÝŽFËzq‰ÍˆnÖØ r”¼e€!€ibZkñßô05@P€¡Æ: G€Éz„zô뀡ÎmïÞ½[QQQIcÀ€¦öhþ&€¡@@±èêÜÖÕÕÕÃÃÃÃÃãÔ©Syyyƒ Âÿêý® Ð#=BÐ#D¦§GH¾D¿¿7..¿Ynó€A=Bz„ Ghzz„˜dggí{-üC=Bz„ Ghzz„8€=BÐ#=BSÔ#Àh0\iêKpÕªU^^^ëׯ‰‰Y°`Áá8£¡Zn=B„ЫW¯V¯^½yóf,\‡(z„Í›7Çz„‹-RÓ#<~üøèÑ£ccc«ªªZµjUXX¨1Õ#äð‡ £!B(99Y*•J$’£GÒípë~óÍ7X|L«mõyöŽ Ö#œ:u*]ì¯z„!¼ÇX[=BznkÛA­‚€A=BÐ#üÐ#4=BŒ è"z„ Ghbz„Ð#=BÐ#49=BŒ ›n=BÐ#¤z„äßFÐ#¤WÀàâRT7E=%¤ úRÈcôyz¥­qº–õâ›ݬ±øûz„¦‰i­ÅcÐ#ÀÔ=B=z„ë€!& èêÐ#d¬z„:·ýôÓOËËËÕÄ÷íÛ/£Cz„=BÆ: G¨s[[[Ûþýû{¼aÓ¦M XwL.ð?@ôAÐäô_½zU\\Œåââ2þüS§N?nó€A=Bz„ Ghªz„¡   ÌÌLÆW @!蚪áÒ¥Këêê¼¼¼à¦(Ð#=BÐ#4Q=Â÷Þ{oãÆ§NºtéÜÃz„ Gø§5Ð#4)=Â]»vUVVúùùÁ+À €!èþ 蚎áÊ•+‡îççWRR¢›xz„!蚘a÷îÝׯ_îܹGµk×g;ì—z„ Gz„&§G8~üø–-[~òÉ'd¯³²²®]»fäÈÀ?6Ý8z„ GHôÉ¿ ­GHï5Ùq ˆ!ög릨§ó±„tA_ yl€!O¯´5N·£Ñ²^\b3¢›56ƒ@À41­µøo z„˜ G¨@PcÐ#Àd=B=z„Œu@PHÛŒŒ ,CXQQ‘››Ü»woS{® @P  GÈXô…´•J¥ÇŽ8p ‡‡Ç¬Y³’’’RSS[´h¡'øÐ#=BÐ#49=BLeeell¬R©Œ­®®¾téÒ!Cð r»€Ž€!=BÐ#4==B©TºgÏ2þXMlÚ´ipwôè"Ð#=BÓÓ#”J¥lß¾½££ã!C"##³³³Ù”¿è‚!蚨áüùóçÍ›§R©*++?~ìããSZZÊ+tôAðOk GhRz„ôõõÅ£`š/a€¿ Gz„z„¦£GˆR*•ò7п/ /@!Ð#=BÓ#À˜€!è‚¡Éé`lØtãè‚!Ð#$ÿ6´!}|0†¸ÕMQOçc 邾òØ=Bž^ikœnG£e½¸ÄfD7klþ>€!€ibZkñßô05@P€¡Æ: G€Éz„zÃÈ{ IDATô뀡ÎmÏŸ?Ÿ˜˜HnYŠŽŽNII!ÿŠŠ 7²ÖüÍ=B€!cÐ#Ô¹í¦M›êëëBNNNuuu …¿ÇÒÒ²²²’*L€@@ôAÐäô#""¾úê«‘#Gþç?ÿ™0a‚R©,++›|hccCh¯GÈ‘Û<;¨1h‘‘‘VVV‹-zõêÕõëײ²²¦M›Ö®]»û÷ïÉôè‚ៀ¡é膅…UUU92..kŒŠŠ1b„R© …!èÐ#DôAÐôôkkkŸó÷÷OJJbÜmˆ:yòdEEùêíÏ>û¬¼¼œ<ùÎO­¼­¨¨ÈÍÍ îÝ»·¶g,mX[[ÛÐÐ@•6☣£ã… ªªªd2YAAÁæÍ›µŠáÁƒŸ?^YY™““£¶ÝqëÖ­¥¥¥2™¬¢¢‚T[ÔK KKKŸ>}ª­«lÑcs3mÚ´ââbú[Ñ1ŒùcˆaÒKþ¨%v÷îÝïÞ½[SSS]]âèèÈÓΧŸ~Jífß¾}ZK¯^½"##kjjêëëããã…O·»wïVTTTÒ0`Ÿˆ1úãëëKï)ùâuhœe:¤ÛÔÓ9nçÏŸOLL$+GGG§¤¤ÿFEE…‡‡kµMï#‹¯W]‡g W>ûàƒ*++gΜɈ©S§â“ýܰaCQQÑ‚ æÍ›7oÞ¼)S¦ð ÕÛY³f%%%¥¦¦âʨ1nܸ#F0Zf“6âØ¥K—233GŽimm½bÅŠšš­d½¼¼V¬Xž——Glj‹z‰á°aÃ6lØP[[ûõ×_ówU7aH‚ ._¾|çÎú\eËC “^òCOì»wï>|øðý÷ß÷ððHMM=sæ Ï…ÉÖÖ¶ÿþäÜ´iSCCìY³èGçð*:::))©wïÞݺuKII¹uë–Àp¹ººbN:•——7hÐ ü/ÏëtFZ·níAa×®]R©”¿†¨ÆY¦Cš±M=ã¶iÓ¦úúz¼|;99ÕÕÕ) üJ#KKËÊÊJF]cŽ,¼^t6ÂoÞ<‚ –.]ZSSSRR²~ýz‘H4yòd¹\þÉ'ŸðÏ7CŒ,ÏHr77Ð:lœy¤ÆŸÖñ+ð+ݽ{÷Ýwß%ÿMMM;w.uoá!C¢¢¢ßE²~ýzKKË;wöë×,´³³+..^¼x±­­-Ö ¤6±¶¶¶µµ3fŒ••UTTT}}}qq±šYÒÛªª*‚ ÏÁX ˆ^^XX8nÜ8rߦ³³3~ý¦@Çrss‡Þ¡C‡ŒŒ ¥R9kÖ,„ÿ˜ª7P ---Û·oðàÁáÇwîÜ9)))::¤¯¶mÛÖÉÉ)((ˆç.V¶èq¸J\VV6yòdò­¡Æü1Ð0QûŽtÊ =±ñObðMU*UNN޹¹y÷îÝSRRð±¸#²sçÎÚÚÚµk×2&›WÕÕÕ]ºt!ßÍÝ©S§ÜÜ\ᢿ–ÿVgH#[¶l :þùKDášø_êTnÇ0K—.­««óòòRKWžY™1cFmm-ùàMH¸0ø!ã2Ç50>>>¥¥¥ôz™eÚ¦¢M=$,n·o߯7ú2336mÚ„¿î'$$Pk¬‘ÕÉÆZ‡ :¸J¥Ož<¹|ùò¥K—.]ºôã?ªÙÑ ~Ú¹sg¹\¾lÙ2º7AAAaaa‰D­3ëÖ­333kÚ´éÕ«W ¨ùG„§§geee]]Ý”)SÔ¾ØJ¥R…B!—Ëe2Yiiidd¤Ú=~ø!'''77·®®®ºº:77777ËŽSí¸¸¸üðÃûöí+--%5â…8F„µµõÊ•+ÃÃë««>|Ø©S'µa¸råJÜsñDxèÐ!¬æºcÇ|yH„À†‡‡ûùù­Y³fË–-yyy‘‘‘ju¸]¥GÃUjCr K8òÇä—üaLl˜Û1„Ð{ï½WXXHÿˆgV#„\]]_¾|yôèQ2&BÂ…á8jLiº?˜›7o^¼x‘~8á³ iŸfˆéD($nÿþ÷¿KJJ<<<ärùĉûôé#—Ë'Mš”ýûï¿S}h¬‘ÕÉÆZ‡ :GÆJ¥Ò½{÷âõK,Ó ++«ˆÂÍ›7ùd˜··wCCÃŽ;üüüöïßõ}FïÈ“•±ºÚû¾/^¼xêÔ©³gÏÒ`ß¾}Mš4!ß<©6 È·SÆÄÄ„††¾óÎ;Œ¯m$ÝøñÇ«««ñ¾d!Ž‘G‹Åîîîyyyôg¼Ÿþùš7¸¸¸h<ÚØØ444`Õx„Ѐärùœ9s„ÇpïÞ½8,"‘hüøñ2™ ›åé*=z®RÞºuK«JïÃ$<Ø{æÌ™ô üÁðÏŸÐÐÐŒŒ Æ­ä<³ÚÎÎ.111&&†ºmAxVsœ¹ó„Ñ„½½}eeåêÕ«]à,CÚ§b: ‰~xèÐ!©TŠŸ­¦§§>|X¡P,X°€j¤qG–;’²Ϙ1Ãpó±dìÿF¿O„Mp`íÚµÔüxýú5µf~~¾L&£ÕÉÉ)>>?A±´´$bäÈ‘%%%ááᇠ9wîœJ¥277W©Tԛ澾¾r¹ÜÜÜ\©TÒïð*•Jªj<ýSRËT¥RÉår5 =zôؼyóæÍ›ãââT*)mXTT¤³cžžž‡Z¸páíÛ·•JåÇcbbºt颿Ûï¿ÿNþÍç‰ ‡Ú¢ÀâG8P©©©A´hÑ‚ (!³¹Ê=|µÄ- ‰jÙ²åË—/©%lùcˆaÂ̶ľqãB¨}ûö÷îÝCµmÛ¶¡¡!--§c+W®>|¸··wII‰^a-,,¼¼¼¨,ÃÅ wJ3úƒruu577òä ã8Ë6iƸ………UUU92..?‹ŠŠ1b„R© ¥i”‘åÉFY‡Ÿ={† 6GÆâý?lJˆ²‡moRZZÚáÇé7TÅo˜3gŽ\.8p >{ß»wïÞ½{mÛ¶uppxðàÚMsêqé…½%¹ÿ>ãfH›¢¢¢{{{{{ûÈÈÈôôtŽ5oÞ<'''::ºgÏžA :ôåË—'NœÐöíÕŒ÷g ===›7o~õêÕììl¬´.0†äýý¾}û^¼x±¢¢¢G|î§sDÍU*Û·o‰D=zô8xð Þ7Ϙ?†&¤üaKl‚ âãã###Û´iãââ’œœÌ¶m˜îX÷îÝ‹‹‹?îìììøÆ·l^!„JKKÇŽëää„-4mÚ F·g„lþ „||| …««+ÇA…Ì2þiFí£ÚÔ·èèh¥R¹|ùr|Dü8ù?þ`[Œ9²Z­WF^‡3àß%6:ôøñcŽE_í>ï!Cþøãšššººº'Ož 6Œÿ#MþÞ⥊ñ£)S¦`jkkÓÒÒÆŒ#ܱAƒݾ}»®®®¬¬¬¶¶öÊ•+:¼‚>mll‚‚‚ð}ö¬¬¬©S§ê%†äýýŠŠŠÄÄDoooþ À=6WIð=Xü,aêÔ©2™lèСA°å!†I/ùC¢–Øýû÷OLLÄŽEEEñµúš5kð-<(Æu몪*|éMZ˜1cABÂ…ÑíDÈæBhéÒ¥ …ÂÅÅE+ƒˆß,Ó6ÍÈ>ªM=qÛ½{wmmm»víð¿Íš5{ýúõ±cÇØ0òÈ \¯ ºa1 \ù¬OŸ>UUUô…„ ªÒAb±¸K—.;v”°(Î[Òº´¡Çp[;;;ww÷-Zhû]#¢ÈÔ‘ˆ™ÔÆ ýþ>7lÑcs•äôéÓ¸ƒ6lxôèþ›- 1Lzɪ‡tÇ:uê„¥ ù;F>PQ­œ¡[À Õ=m[±ùCÔÁ>³LÛ4£ºD?–Îq£ÔaLɆzYë•ÖáÆšGºCÄöíÛ­­­µj¥ÃLÐ#ltÌ2«BÐÖ¥qãÆ <êïïOîçÎì;7&ë•i:¦l}Ñ9Í8dâq3ÁõJ[Ø&¸ñŠH$:þ¼¿¿¿/·¿ñññ , ÓCôF”Šüò¤ÐȈÅb};Ј´iÓ†{õü„i¦H£z’ Ð$‰ Cƒ+m|gÐÛ£ÌǦ&DM ¡^ê¿ßbA!ŠhRzÓcR5"¦&šÈ¶Ìo¬Á¦ä§s’°­3&²þ6þlr\C‡¯¯¯¯¯¯Çb60ŒÒhtFŽùøñãúúúòòòÇó_—õ.ЦwÙ6y¢E4¶ÔY SzÓ(¨¦CR ”Ѥõ4"$[Ê=²e>ÇJ¥Ãi‚"’„m1…õÇñg€MŽ+!!!))©gÏžýúõËÈÈ ãé·@³·H™M' Ch/¦†µµõóçÏoܸáìì<}úôââbü3a>¾é]Mï²móD/Šhl#¨³"¦ô¦QPM‡¤â(:F“ÖÓˆl$SÇžùlå|0&(FÛ$a[gŒ¿þ0bˆø3@°ÈqUWWÿý÷øg{öìÉÍÍ¥Lï2fþ_™ÞŠZ¡F¢­4šÞÞÞøÅ%¸_iiiôä6‚(2€lÏ<1œ"Û TD¨ôF†…MPMÛ¤â¨Æ•ÖÓè‰ÀlÑUØ2Ÿ­œ?BV©N­’„m1þúÈ!⯆±ËqåääôîÝ!$‘H\]]srr¨u $cÆæ‘•ùè­”J%Ý›N‰¶ÒhjØÚÚ‘žžŽÛæçç·nÝš:¨FEc!ñט'†VDcSz¨ˆ&PéM£ šnIÅ(SÖÓè‰ÀlÑUØ2Ÿ­œ?T Ú®<R$Z% Û:cüõÇÈñg€þ†!OOÏgÏž=}ú4--íÉ“'jwó -cÖ¸Ê|ôVÞÞÞv×0:H£‘Œ7N.—{{{c³ûöí«©©¡ÆÓø¢hú•m#m2æ‰qÑ0Ô¨ˆ&Pé Ã-¨¦URi ”)HëñŒnÙÂ'ªÜÐ3Ÿ»ÜÐ+£T'þI¶Îmý1~üµ8̶mÛ ÷íÛ·ÿþââbü­–ü”0°ŒYã*óÑ[qØaS\Ãh%¦‘HñòåËmÛ¶8q¢´´´¶¶–ï !Ц_Ù6Ò&cžh;½(¢!Ú TD#„)½!M‚jHˤÒ(ãgÛ”1\¶hŒª¶+’ÆrC¯<ŒRTø' AŒë [9Ï>òÏãÇŸ5s¬¯¯Ÿ?¾X,‰D_}õUee¥ÚvpÃɘÑý1¾2½£6Å5­¤ÑèaiÑ¢ÅO?ýtåÊ•½{÷îܹ³¼¼\-žÆE£ 2°ÜÑè#(\ PzCšÕ–I¥1PÜþGZgd®Ù‚t’©S;®V 1·?ÂW‚Iª“ŠVI¶Îgý1~üÕ`½iéââ"‹?~ŒïDgdd˜››;88PïéNÆŒŽñ•ùè­í°)®‘h%FKYYÙúõë ‚P©T§NÊÏÏW‹•1EÑ1¨ÜAÑ0ôLOOGº*¢ WzÓ(¨†´×Ûã·?Æ‘Öãã‰F "S'­<RTûZ% Û:cœõ5Fü™Q;¯º¸¸”••]¸pÁÆÆÆÎÎîÆùùùxǦwÛõøŒ5’2ãö3ªKlŠk$:H£Qqww·µµEÍ™3§ªªjË–-Œ­ØFA¢h½Ë¶!yÂ6vÑËÑ*½ñTÓ*©øÊYÄgÊpx‚tÊA2u”ãjû„Í$låáꤢU’°­3F^8Ðoüù† ˆ¹sçfeeÕÖÖÖÖÖfddL›6MÛ'Ìú=š 2‡âF7i4µ8ÔÔÔ”——WUU8pÀÜÜœ§o=Š¢‘þèW¶ éš'zQDcAÑ0¥7>‚jÚ&•pÁQ#HëñwF‡l$SG9®n 1#Ò%Ñ6IØÖ#¯?è7þ¬ˆØå¸ºví*1¢ŒG[±‰)óIh¨5×MŠH$rrrrww÷ÝwuXËèa”èâÈãËÝ YÜI#Œ#H誈F¶ÕMéMÄCPMÛ¤(=f‘Æ)£ƒ3<›pGUçãꜽBV‚]£m’°­3¦³þè7þZC„K›á`óÇÔüDz•F3µ®Ñ1Áø G` ½ëío/l“Nˆö'Ûôê8ðO¤Ñ½Ih’0!@ Ð;T€F I=Ê^@#©F@÷Mj˜™™µk×®¼¼\ˆ›wß}·¦¦F_^ñÇÊÊÊÊʪººZ­<""B&“%''3þ®ÅÌÌìÌ™3®®®aaaô mÚ´©ªªR+´±±‹Å *7l±â………££#ýgdlå& [(Ø:Â[æs§zC 2–õ5ny-ƒú¯wMA6•,6‰;}•óÁ ±â £¨$[¹ à zG|}}ézxxÿ‚a9ô†@e,þêk*eÜòZõ_ïš‚l*Ylwú*oôX‘p 4›¨$[yãA]=ÆŽ´nÝڃ®]»¤R)þHga9ô ·2‰@õ5Ä®RÆG^‹Û“Ò$˜T²Ø$îôUn"±Âpˆ²‰J2–7Jøt„#l$Þ0pàÀ’’’Y³f‰D"!Ârè‹?§]‹üH ú õíÌT4Êk½]š‚Œ*YlwX—@x9O©‰D.../_¾Ü¸q#u}=zôªªª”JåÓ§Oÿõ¯íß¿Ÿ¬àççwèС‡Þ½{÷Â… ÇWÛ¼0zôèÞ½{acccaañ¯ýK¥REFFFGG“[¡PôêÕë—_~±³³k×®Øü§·*++Û¿¿šòœ=cÆŒ?üpÉ’%j綆††üüüÎ;S/É-,,œœœNœ8Á3Ðø…ФeÜñwß}W_å¦+mkkkffæããƒOB]»vݱcÇ×_ÍVnä ðï¢\êQCÁÖÒ¸Ïûï¿?{öl²9wæ#–ô@üïD˜žž~ýúu•Jekk;{öì³gÏzzz’sõÌ™3………W®\133û裂ƒƒ©s522²_¿~sçÎ8qâîÝ»—-[öñÇgff’KÆàÁƒ?ûì3‚ lmm ÅÒ¥KB555÷ïß§^á–——ÇÅÅÙÙÙ9;;;ûÃÇ6ÿ[0ÚquuݹsçÙ³gOœ8A¿î~ýú5~Á7IÛ¶mÍÌÌxI—FŒÏ~ðà>møûû/_¾<00P.—3–9dÂóì[(è!5¾ç΋Þ¨F82CO?ô ‡2YGˆúO•2‚S^ë-ÒĨ½ –MâN_å<Ë ±Ò8Ðl¢’¶¶¶Œå3gÎ4rxv„-ª™!{{ûÊÊÊÕ«W«™âÎ|Ä”~è‘ÿ-Ó*e,òÊTˆúšF•2>òZo‘¦ #lwØáåÔï+Í&*ÉVž——gä ` :ëêq¨f"„\]]ÍÍÍŸÜÁÁá?þÐh¦ó[ ׉pÁ‚7n<{ö¬J¥ÒÊèùóç[µj•ÀÝÐÌ̬]»vååå:´Õˆ¡Ž™™Ù™3g\]]ÃÂÂt8–?ÖGmaŒ‰‹‹‹J¥ª¯¯glÂö)ijýúõ ÉÉÉzì,cêþ½1…|ÓÁNDD„L&Óyô-,,BBBËËËoÞ¼©R©Ø¦-÷tf|øðý÷ß÷ððHMM=sæ vO_å|à“íDGG'%%õîÝ»[·n)))·nÝb<ô¸qãFŒÁxŽ\µjUyyù’%KZ´h1tèÐîÝ»ãjlå†Â_P;—|þùç{÷îõõõýõ×_©ç’‰'îÙ³góæÍ|ðÙ±iÓ¦íܹsÛ¶mžžžd!5_W¯^=vìXµ@H¥Òß~û Q$?þêÕ«ø_???\ßÌÌlÆ ®®®«W¯Þ¿ÿâÅ‹E"ш#~ûí·7ÚÙÙÁyìL·nݾøâ‹½{÷~ñÅÔ jÆçÌ™³dÉ\ÁÃÃãË/¿ÄwéÒeãÆ]»v%â÷ßòä éžT*ݳgX,Æ ÷„ d2Ù¤I“°W'Nüí·ßvïÞ=zôhºŸŸþ9y8„Ђ –-[&‰òòòH›"‘(00ðÙ³gŒAfë×ܹs÷ïßÿÍ7ßtèÐaÆ ÆŒ‰¥¥å«W¯:$‘HpL:wî\ZZºk×.‘HÄý)BH-¼Ó§Oohh>|85 TVVÖ­[·úúzwww‚ ¨£ ‰¢££¯]»¦6©8RC¼áÀÙÙÙfffø_ª²N‡òóó9B? G> „F…n‚ –.]ZSSSRR²~ýz‘H4yòd¹\þÉ'Ÿ >>øHÔ|-((عs§ZNÇÅÅ=~ü¸sçθ¾X,&#UPP€ï~XZZÖ××§¦¦†††ÆÆÆÊåòÓ§Ogdd„„„¼zõ*::71¨ó$Ø™ÄÄÄðððëׯ×ÕÕ8pסÿõ×_‹‹‹ÍÍÍBGŽ‘Éd}úôÁƒTUUÕ¶m[„PZZÚáÇɣà¤$ÿ6l˜\.Ÿ6mA_ýuMMÍ7nݺU[[KÞ·!ýܳgOee%6kiiY\\H.L¤ÍsçÎ=~üJ-ÈŒýúþûï"##oß¾‘‘¡P(ÔÒË 1;v¬\.ÿè£ÈÜ%âÖ­[xܹ?¥‡·I“&EEEÛ¶m£k÷îÝøá++«;vàVÔQpppÈËËÛ»w/ÿÔUŸ¹ïIeffÒï³qäÙßââb\çÔ©SIII‘‘‘x!Û¼ysMMÍû￯ÖA>öM6ßÐ_ç&=ÇzöìYZZŠ´mÛ¶²²2|Jã3úôdÀ¨ÕòŠ„­sàÀê‰púôér¹|ذax4gÏž-—ËÝÜÜôUN&‰µµu—.]Ž?îàà@Þ©¦ç5Ûé­íP¿å‡„„ÄÅÅ1N„û÷ïÓ¯&q`kkk¿üòËQ£F-[¶Œ¼wÍVn  üò\‚Ÿ ˜™™‰ÅâÓ§O—••I$''§’’\žðßÿþW,?~|õêÕ¸0...44w˜š¯‰„žÆ ËÈÈ(//ž?~“&MÈȶ8wíÚ…í'&&ÖÔÔôîÝ["‘,\¸P.—ãó™A§›L&#>|8??ŸÍø‡~(—Ë'L˜@Ä‹/^¾|ùÓO?áo÷ïߋŵµµß}÷õDxðàÁöíÛ;::2$222;;»U«VŽŽŽ%%%¿ýö¶èС‚‚[[[ªŸ2™låÊ•"‘hÁ‚ …bÔ¨QAäååݹsç»ï¾ûþûïOždÈêEÜÿûßääd±XÌý)=¼¡ÄÄÄ   µ¯n¸urrrîß¿TôèÑ#ú)Š#uÕÐx"\ºti]]——ãÕ:c>Pëܾ}ûÞ½{b±8333 `Ó¦M¯^½’H$ÁÁÁ ä•>µƒí›r¾Qí0æ˜D"Ù°aCYYÙøñãËÊÊ~úé'r¸5Ž>[¬¨'BƼB±•S3z"üä“O¨Ù‹ÿõððÐW9™NüqEEE~~~^^^EEÅÒ¥KÕn3f;½•··7‡3fÔÖÖ’_$0£Gþꫯ֭[÷ìÙ³ää䯿þzݺuÔ'µ:tËåÉÉÉIII‰‰‰uuu¿üò‹H$b+7PHþ’jýû÷·°°8qâ„\.W©T/^¼ÀÛŸ† beeåää€zçw:uê„òññéÛ·ïܹs›7o.‘H¬­­éËåôÂÈÈÈ~ýúÍ;wâĉ»wï^¶lÙÇœ™™Ißm•››«P(”Jå³gÏÌÍÍ“““åryRRB¨cÇŽQQQu^/^`g233ñªÄh<222//oذaJ¥²U«V#FŒøöÛoÝÜÜ.\¸ R©Ú¶mkffV\\L5>þüyóæ©TªÊÊÊÇûøø”––Ž=ÚÊÊêèÑ£¸S'OžôññéׯßÕ«WɆ±±±=?~üîÝ»'Nœ˜––vûömÜwggçQ£Fá?JKK³³³yö«OŸ>666gÏž•Éd*•êÙ³gÝ`4õúõk|ÓŒD¥Rá()•J²0==ýúõë*•ÊÖÖvöìÙgÏžõôôT(dþ©ËÍ{ï½·qãÆS§N]ºt‰±-c>P+ÄÇÇÏ›7ÏÝݽ}ûö×®]“J¥_}õÕ¸qãzôè7.2vÛ¾éç†1ÇT*Õ?þ8nܸ“'Ofeemذ8£Ï+ [Šê1uõË™3g ¯\¹bfföÑG«õŽ1Û[0ÚquuݹsçÙ³gOœ8AMãÁƒãË [[[…B±téR„PMMÍýû÷©Õ¼uëÖ÷,ᙉÃ{å›4iB½1šó!¥R‰½e4®T*cbbÜÝݧL™òðáÃÓ§O»¹¹ 8ÐÙÙ988˜mżGÕÕÕßÿ=wÉ~á_¹¹¹ä!Œ“ŠŠ „PëÖ­©…ÖÖÖødÀý)#}úäçç«Tªž={"„RSSÕÜøÏþóÕW_mÙ²ÅÒÒòÈ‘#d÷U*¾ô.++‹‹‹£î}à/I;v|ôèQ£Ä$&&¦ªªjøðáçÏŸÇFÜÜÜNŸ>­R©¸?e oË–-_¾|©Ñyì*…ÔÔT‚ Z´hA>оRwåʕÇ÷öö.))a«Ã˜TªªªFާT*U*UTTÔˆ#”Jehh¨Æ¥ÿ­Î7¶ëÕ«×çŸ>oÞ¼'N<|øÊsô¹aÌ+Žr6ÒÓÓBíÛ·¿wïB¨mÛ¶ iiiøÌ-¼œ:ôøenn®T*é—\lÙNoÅh'00ÐÂÂÂËË‹þk?Ò,þö"—ËÕŽ^\\\TTÔ±cGü/Þ±üúõk¶ò¼¼<ó—ëµ[·n­[·ÎÑѱk×®“&MÂ×k7oÞÌÈÈXµj•™™Ù§Ÿ~Š7˜Péëë;xð`Æ«?ú®Ñøøx‰D²iÓ&üHsÈ!  ¾µA7Œã¼lÆ/_¾Ü´iÓŽ;ž9sF¡PܼysĈ11189ª««srrœ5vêÚµk©©©~~~NNN+W®LHHxðàÚ2WPPpóæM//¯<}ú”q¬««{çw4—íëëëââÒ¡Cê·"ãĤ¤¤äÈ‘#sçÎõõõmÙ²eß¾}?Þ¢E‹ýû÷«T*îOÃÛ¦M›gÏž©Tª=zœ½½½››·µ£ÔÖÖ>yòÄÑÑ1<<xxx¸ƒƒCzz:þ&ÇÑ–ÍþÛ’ol9¶cÇŽÜÜÜI“&¥¥¥Q÷èñ}z¬¨…lÓ–ÿtƤ¤¤$%%}þùç­[·vqq™;wî;wêëëõUN=Vnn®T*}þüù‹/èž0f»J¥¢·¢— 0`ùòå2™ iÚ´)Ï`._¾|øÓ§OkkkëëëŸÐs쫯¾jhh˜:u*A£F"7°ð}ÆX5oÞœê°Z^‘°•cÔ6Ë „ú÷ïwÿÕÕÕEEEuëÖ û£¯r>°e;ÏæUUUø«™Ã3fÌ c[µMPPP]]]uuuVV8ŽrCÕW‚ $IŸ>}ìììÄb19xAˆÅb777www333/±XܱcGWWW‰DB5BÝ)ʸk[³³³swwoÑ¢5RlméN’>Çyêß"‘ˆÛ8‡Ã˜>}úTUU‘cÌ%ªý^½zõìÙÿlŽ1°~~~eeeÔ]Žj°ÏôÃqôK"‘¸¹¹YZZþüóÏä2l³eË–ŽŽŽb±x̘1>$ Êñ©š©Ó§OGDD`÷6lØðèÑ#ÆÍœ’¿‚7^ª5aK]ºYj@¨p9ýXT lù vµCà†lëûèíÉ7zŽQHÍ.ž£Ï+µ37=E1låônRïÔ©SûöíÉ4Óc9ز]·æÔTáv/ÂÔæŒå†‚Ølá;ŠÜ%z9Œæ¼SAlß¾=11‘ÏnUnû666'NÌÎÎ>yò$Û"¨cÇŽ]³fÍ„ æÏŸŸ““¦­q}ÅD-ãéƒHÿ”jjܸqEEEøÇ6!µ­Þal¢ö¯F³Â+𬣗¶oK¾iÌ1ÝFŸ¬†O„UUU§NÂÙÅ–¢ZMg²•AËß ØF£œÍŽž=Œþ¿¿¿{©Ì˜1£¼¼<**ÊÉÉI_¾!„fΜ™’’RQQQXX¬û mÐWL¨¦=zD½+‰´íŸ&ë¯À³Ž!ÚRy»ò->>^‡Ñ§VóôôüðÃ{ôèAÞ‡`LQ=¦.ü³‹Åø™–ð] =^›“fñíen›A/1¡šjÓ¦ ¬MzäíÊ7á£O¼,aKQ=¦.pÁ–gZåŸ^Œÿ( ñSòS z¾¬c“§b—bÃÆÆæÝwß­©©Q+gSã©:¦›–˜iÂ"!—ÙcÔ]Óvô[ôØ\5~âb| J#ªâ!}ãéCøÃ1=ea4qb­‡@ 0†CžŠ..åëëK—dÃO§ S[[ÛÐÐ@}kbWc+WC+-1’“'OVTT=úì³Ï¨ÎãWeòŒ’:ptØB$Ä12{ܰé®!i1½ÄP·tåH06u4dÜÄ3Äøê%ñHÔf„΂p|¤5¶òè.Š’:øÃ±âñqIãô4f~²MvÎG\S«[ñ:¦a*q)6y*Fq©Ö­[{Pصk—T*Å=}ú4::ºG®®®)))øµÂäQu1¶r*Új‰a¦NÚÐРR©ÈõhÆ EEE ,˜7oÞ¼yó¦L™ÂAá¯Çj¶ qL£Ì7lºklÒbz‰¡n:jlÑcscÌÄ3Äøê%ñ0ô¡³ iF^±­<:‡K£¢$7Œþp¬x|ljœžÆÌO¶É®sÀùˆkÒ'¸þS‚ †M\ŠCžŠMtŠ|=pàÀ’’’Y³f‰D"{{û7nŒ?ïÚÚºu+~¡>õXŒêbå$Új‰!„š6múøñãû÷ï+•JrÚïÙ³'))IòF ñp|4À&9¶Ps„H cÜ2{ÜLºkˆ}ôõCît¥Ã=6WIŒ“x†_‰‡¡Ï‚pd_ؤ¹½âXytYŸCQ’ W<žQâ3=¶0²MvÎG\“¢ê–v¿®mÛ¶NNNAAAŒ÷”ñ¯VéåÕÕÕ]ºtÁo®CuêÔ)77W¥RYZZ¶oßþàÁƒÃ‡ïܹsRRRtt4y8üÇ–-[‚‚‚Ο?¯T* LJ_œˆrvvV{q(B(88¸¬¬lòäÉ‘‘‘ÔØÊI† Ey#[9Bhýúõ–––;wîìׯYhggW\\¼xñb[[Ûˆˆˆ;wîP›X[[ÛÚÚŽ3ÆÊÊ***ª¾¾žþZzòíáUUUA0žƒÙBÍ"!Žåææ>¼C‡J¥rÖ¬Y!¶÷òÑQ½ZÈ1úúŠ!wºÒa‹‡«$ÆI</5hH§ÄÃÐgþÃóçϱñœœssóîÝ»§¤¤àcq;FFlçεµµk×®eÌ:mW!áRDzbsÀáãŠÇÇÄozmadœìH@ÀÃÃñxä‘#G†úìÙ³òòr|;·ÿþ 7nÜ Nï)¡Y†M£¸ª<›¸Y‹¿¨ý ©W¯^¡¡¡ EEEãÆ£…®.Æ]ŽØ5Ã8´Äºwï^ZZºpáB,öH~#ŒˆˆÀï¸{ñâE]]Ýš5k¨m5j€qëÌñ 5cˆ„8Æ_fµWIqŒ¾ÀjT ä†=‰Š1Nâ1z(„·±±ihhÀbÖ¡ÈårÒ²½½}eeåêÕ«ÕLá{Ð"‘èǬ®®V“CCݺu‹q\ÙÊ‘öãíííÝÐаcÇ??¿ýû÷+Š-[¶`YêWr¬ÐݵkWjR^¼xñÔ©S!!!gÏž¥¯GûöíkÒ¤ Û‡y†š1DB#.‹ÝÝÝóòòè[>ÿüó5opqqÑx"ä}1äNW®Ò£Ç¨$FH<6‘°ñžxl3bæÌ™ô!ù>XŽ!„BCC322eŒt^y† Ãq"äN0FûŠÇÓî鉌˜ŸˆéD($àøYà¡C‡¤R)~(›žž~øða…B±`Áª¥ÄÿºÁ-æQ\ C—§b—Âÿºººš››?yò„¼ÿÛ£GÍ›7oÞ¼9.. Ë5mÚ´Y³fEEEÔ±©‹q¨Ži«%æää„XZZ1räÈ’’’ðððLJ„„œ;wN¥R™››«TªŠŠ þòWÜ:sCÍ"ã)³÷ûï¿“óypÂ1úcÈ®®²E/++‹#QIŒx†_ŒÀÄc›7nÜ@ḥu^yàã†{.° õÑW<*§'2J~r $àüÅ5 ˜Ôç}ûö½xñbEEùn=*÷ïßgÛ¡PZZ:vìX'''ªpà@ìɽ{÷îÝ»×¶m[‡¨ÝÂ&a¼gÍ!£[¨9B¤³cÍ›7ÏÉÉ‰ŽŽîÙ³'AC‡}ùòå‰'´}ãÝÆÑCžéJ‡#z‰Jb„Ä3Äøñ¼Ô IDAT"}$ÛŒ ">>>22²M›6...ÉÉÉlûéŽuïÞ½¸¸øøñãÎÎÎŽo`|â«ÃÊ#$\Ýž²ùƒ˜V<>þðŸžFÈOúdðèèh¥R¹|ùr|Düú?þ`[…ôŸü…©ð4`t‹MžŠM\ !´téR…BáââBµ3eÊ”?þø£¦¦¦¶¶6--m̘1j£ª‹±•3ªŽé¦%†h=† ‚=¬««{òäɰaÃø,ÁþëG¨ÙB$Ä1…HþÐçÛè Œ¡5¶èq$*Æh‰gˆñÕK⑨ÍáÖ¬YÃ(ÍHw@‡•GH¸0º9„úW<>ð™žF^é“]`Àµ×D†H É_¡??àƒ„iDÌ":%¢è‡‘!‹;wîüÞ{ïÑ?EUc+gTÓMK ½yË0õá¿X,îÒ¥KÇŽ=ä€ñv¶¶°…Hˆc»B$D4Ý5Ä)-¦s …¤+G‚±%*Æh‰gˆñÕKâQ=¤;¦ƒ ù¼Gm@µr†må.ª{Ú¶âX W<>ð™žF^éÁpºA’lh ” AÚ®VŒõÕÔÅØÊÙäô«%Öqäá€@Ç Ñ)¹*m]2~â™`и1Y¯LÓ1Ý`ë ,Œü1}5£¦.ÆV.bQ– x€)ùùÏ‚M]Œ¿ê˜´ÄíÄLÈOø›šj€éÙ¨cffF'‘±±±aüQ‹ Ï·ÂëÆlÆ¿Î6¾3ˆÅ ‹:˜Ô=q+++Æ-©ñññóæÍc¼½ÃX®†™™ÙÙ³g·mÛ¦V“­œuŒÆßo¹dz!³Ø@«“ñ³‘-÷L$'Mí¤nÔ³’@™:ƒÊï5– ›×СCãããëëëëë뱌Ïž Ô?{‹´9D+Q#‰M’Œ9òñãÇõõõåå凿¿.ë]MMïzoL/³˜mèužÅHØê¤q0f6²åž)ä$[6r,;¸Œ<+é‚@™:ƒÊïA69®„„„¤¤¤ž={öë×/###,,Œ§?õÏÞ"-@60 at±Ikkëçϟ߸qÃÙÙyúôéÅÅÅŒ?LfDïjjz×{˜`z™ÅlC¯ó,FÂV'‹€Ñ²‘-÷ŒŸ“Œ°e#[9.#üÇ]£¸¦:eêŒ/¿g4F9®êêêï¿ÿwvÏž=¹¹¹<ý!ÑAÿŒÃãkÒ[QK8tÂHŒ)6IÅÛÛ¿*$000--gžëWM @ïg‚n³ ½ÀY,puÒ¸'ÙrÏø9É[6²•kô ñ–.žÊ-®IE"P«±ä÷Œ£‚Æ›WNNÎÿ³wÞQ$Ù" &`0Š(bŽ`XÝ€ \½u(Þêªè-®i1¬ ®xk0¢‚‘ ¨€ ’2C`Bÿþ¨»þõÍtÏ4Qtßç/èyõêUõëªÕý>|8†a<ÏÂÂ"''‡jÓJúgLñ´± b)™L¦è‡I'Œ¤-Å&©tíÚÇñ´´4ä­ b)%~˜¤Úm£©&ן',,ìãǼpáBYY™H$bß-­¡¦Ö²zo¤OÚk›£SØõÍ<Š›9:aª¬M²ÇqÚÜcÚβuìskÒp§|{Ó†–ÅUîwö ù?4Së“ÈïÍŸ?¿õTаÆkïÙÛÛ×××/[¶ŒËår8œŸ~ú©ªªJnuoëéŸ)ÆÓöZ€Š¥hý0Iµ‘´¦šbêèèüú믷oß>vìØ‘#G***ävD[ª©a-­÷FúdJ°68Šw}ób¬£¦jÀÚ*™r¯mrküð¢r»òØØHŠ6g¿³?ÊHxX³u°>‰ü^zz:Öj*hXãµ÷LMM¹\îÛ·oÑãÌŒŒ uuõž={Rƒµžþ™"m¯¨XŠÖ“TIÛhª)ö§P(ܶmŽãA\ºt)??_®“ÛRM–VØkÕ£¡¸ëÓÒÒ°¦ÅÍTX[e#SîµMNb^ØÐLIÑæì÷æeÍ•©£½ýÚzò{x›¨ )AîTÈÔÔT(^¿~]__ßÀÀàÁƒùùùhŦÊx¨>[ê!ö‰´i׿QCb’j#iKM5*¶¶¶]»vÅ0lÑ¢EÕÕÕûöí£-Å´ûZPM Ñâzo‹k¥£cØõÍ9Š›9:±Ú&™r¯sR M¸"T{IÑfîw•G[š)Sתò{m ‚¦¹ ÀqÜÍÍ-++K$‰D¢ŒŒŒ¹sç6v NËN„íP P‰T¢íÅ&Iüýýkkk+**ª««ýýýÕÕÕY6 Ñ‚jjd<-«÷†55ÁZä(fÚõM>бæNl6ËF¦ÜkãœTB“'BZš9Œ°ßï*2¶àÍ“©Syg–} LòlŸJÃ,Ç5`À^êŸ))ËmgZ€ŠÝ.W¼íÅ&I8ޱ±±­­m§Nš´Šýß„¤Rî°9;ŽÉ'Zä(fÚõM>бæNl6ËF¦Ük?9É”9MΨæ #Íœ•šEŽº€6†O˜Lq~*”ô[»Škšjí­Oi‡;®ù4³E­Ñ!ŸD’6’/ow·Ð3ÀhªíÈF> ©´ öH‚­ËÄØ¸qãöíÛ—-[Æáp gà ‡Ið¯ hÏuŸ¦niç´·3¦Äf™]AAA ::šËå²L<>?˜ÿØðÅÔ5Gt­Åé”w‹š£<×J2ŸP·Lyb³Ì..—{÷îݘ˜.—Ë2ñøü`ücÃ#PÇ^tM‘W¤SÞ-JhŽò\+É4~BÝ2å‰Í>»‚‚‚ÐDÈ&ñøü`ü“3ûâêXŠ®µ"›naŠÿ/MSž#‹· L#Óv6ñ4'»Ø$6Ëì"'B%Eø|á1 þ‘+:%¢km¦HÇ$ÞÆ&’f*Ï©ThSB[ê–±É.•‰5)»T&Ÿ+Š‚äO:•¢km¯HÇÔ-­§<‡hY™FåÛ[;»”$6‚MvQ¯•àóFQðü ÿ{Ô©]SÞ­¡HÇÔ-Ê#A4Myk™FåÛ[;»”$6‚MvÉM„J€Ï\AðúëßA N¥èšò~hqE:åÝÒJÊsXKË4ªÜ®<žæg—òÄÆØe—ÜD¨$ñøáYYYy{{+ þ‘F:L•èšò~hqE:åÝÒJÊs-.ÓØÌx°fd“’%5±±&e—’ŸøáåççÛÙÙíØ±cÙ²e†¹¸¸dff~øðj”››‹aNQM¤ÂçóŒŒd2™¡¡áÏ?ÿ\[[F„b)Å-¾¾¾£FZ°`X,F¯×ÕÕQýwïÞ=44T±jr»¥¥åÚµk:”œœŒÌjjjrrrLLLäŠ0mg‰’~‰DïÞ½³³³ûí·ßЯ=ruuMMM-((hlE*»EùiZ+ ´mÛ¶k×®ÅÅÅ‘Ò- ………¤’³„&ÓJÙ%T&6Æ"»CRòŸ+L‚løbêØ‹®1Ñ‚Št*»E%MPžk ™F•Û•ÓÌìR™Øl² ûß[£LEø¼ÁÿØÐLe)&•2’6“£}P×(ZPýKe·4!–Ewh‹Ôû uË”$6›ìÂþw"d*À—í›×Ÿ–ö P|î0%6ËìÊÈȨ¯¯ùò%—Ëe*ÐZ€$Ðz°Ì.‡ &X[[ã8ÎT µI0 õ`™]äg甀¿9?üðƒr5på6¦¦¦;vlè>îîî·nÝâr¹ÔlzImmmÅíúúúZZZ´EºwïÞ¨P>/1†¶6#GŽ´··ÇqÃ0uuu>Ÿ¯Ü~̘1ýúõSÜîíí-ÒÒÒJKKÃÂÂìììÏŒŒŒªªªªªª²²²äääÝ»w7j iq¨íUIŸ>}äŒÙôÉСCÃÃÃAnnîëׯmll·AƒEDDäääܽ{×ÈÈÙŸ8qâýû÷UUUÑÑÑ<¯1-šDpppxx8ºèár¹*g©¢¢¢Ã‡Ë™íÙ³§¦¦ÆËË«W¯^£FzùòeZZšŽŽ†aàܹsöööŽŽŽ^^^"‘hëÖ­Ÿp.¤¶W%{÷î-//—›ØôÉóçÏß¼y3|øð&&&>yòUñêÕ«ÁƒÛÙÙ¥¤¤\¾|mŸ7oÞºuë=z”——!_>îîî¾¾¾ÞÞÞ}úô!/;œœœüüüvïÞ=lØ0rãŠ+Ž?¾qãF++«õë×s8---//¯#F ›±cÇnÛ¶ åœðù|//¯®^½úرc«W¯F–kÖ¬y÷î]FFÆ¿þõ¯îÝ»{zzN›6¬tîܹGŽ9xðàøñãÉŠaÇŽ‹ŠŠÎž=‹®“pŸ0a‚D"™5kŽãÀÏÏËåâ8Îápž?~ÿþ}ÅyH.à™3gzyyéêêbÖ¥K—;v oLý3oÞÇq¦Î‘k¯’Þ>vìØÚµk÷ï߯8’½ÄÔ«$+W®DÍ?räˆ@ àñx‹ÅK–,áp88ŽoÙ²¥ªª Õ‚zéĉ´!ªÑÂÂÂÃÃãøñã+W®äp8'Nüã?vîÜI½ûJ›Zí‹€€€âââk×®%$$¡›f›7o®®®¾{÷ntttIIɘ1cp?zôh]]]HHHDDÄû÷ï³³³y<ž‘‘Q}}=9ønÛ¶­¶¶ ŠN:wî\__ÿèÑ£ºº:‡ãçç———WPPpóæM33³ÂÂÂC‡!‡û÷ﯨ¨¸}ûvXXX]]ÝâÅ‹Ñxª8Ž5J"‘¸»»“qŸÏårccc¯\¹Ò»w ???´100ðÇh"‹ÅkÖ¬AãìöíÛëêêx<ž±±±¢mmm±Xìëë‹6ž}úØÙÙihh\¸pA"‘QZZªÜµƒƒƒ¢4ÂfggK¥R™L–™™©§§‡a˜L&#‚ ©TJÕÏâÅ‹mllÜÜÜ:wîÌãñºté¦aK—.%¯ÿ6mÚ„bHKK !¢k×® .¼zõêøñã¥R©’€ ‚øå—_¦OŸ~ñâŬ¬,///©TJkéààйsçK—.¡þY¹r¥ºººL&£ Ú^Zor½-×-Š(öª"G޹zõê… T:TInn.ª1==]]]=!!A"‘¼yóÃ0ssóÈÈHÅÔbê€OÃ0ggç 6Ì›7oÛ¶mQQQîîîúúú葦¦&†a ÀÐÐÇq6#2BOOOщ\Y™L¦üÏçŸ?~Ê”)ÑÑÑÕÕÕzzz………LÆUUU†uéÒÇñ7n¼|ù²S§NÏŸ?'/hÒÓÓ:„Æâ°°°[·n¹¸¸SSÀ2™,44ÔÖÖ6<<Íš´–èlAAò–””„aX¯^½šÖQím*L½j``pþüùÜÜܵk×J$ ÃÍêëë[#š­Q¨¨8º²WL­÷ïß7hAx}úô™yòä7ß|ãáá¡¥¥Õ¡C777‡SYY‰ ø|¾‘‘‘‘‘‘OmmmXX9è3|øðáÜÜ\ggçÔÔÔ#GŽp8ZËdeemܸQ__À€ttt¬¯¯§íj{•ôö–-[ŒŒŒ àììÜ̧k¾¾¾£FZ³fX,FбcÇÄÄÄ7oÞ¬X±¢[·n¦¦¦nnn¡¡¡M¸"¤…6µàr€vŽãžžžÅÅÅ•••uuu‘‘‘&&&†Mš4)%%E$ÕÔÔ‚ü‘Ãá,\¸°   ¶¶-6ÉÉÉAw,XP\\\___\\ü×_Õ××£íŠN:wî,‹===Ѱ¾e˱XŒŒ]]]kjjêëë\\\Œ– ›œ‰¤¡¡ááÇ7oÞLMMeZ,ƒa‡Ã9pà@IIIMM ªtß¾}È¿@ J¥‰D,WVVÆÇÇS§%„bÀ?ýôSCCZ€3yòd‘H´cLJCÛ?Ó§OÏÌ̉Duuu<@‹q˜:‡ÚÞÉ“'3õ¶X, …èWùbÚ^%©®®&51þ|ÇGމ–º ½?pà@êÉŠòÅ2d—.]JIIAûÅÊÊJ"‘|ÿý÷\.—6µÚG]]}ذa½{÷&ß«ÃqœËåZYYÙÚÚòù|4Þá8Îãñ†ª¥¥uâÄ ´jmWWW·±±éÒ¥ ‡Ã!ÇMZ'hÍ$Y5Õ¸W¯^h#iÃårÍÍÍ-,,x<—Ë%#¤ÚÈ5GSSsäÈ‘d¥Èž z£N®¬bÀ(d‰šOvmÿp¹\kkk¹ždê²½JzÛÚÚÚÀÀ€Ëå*ÎFÔ`êUª±d£¸\nŸ>}PÌr}BëJ±Fê~¡ömj´ShoZâ8N;[`æïïON„J<09i~*ý4ù•5öe•ô›rÛÙ{kqZµxw€öÌÿOc´o”l,++“[5Ãôø§Q…؇Ñ?-^¶±¦|{Kµ½ ´j-ð\€/‡7»:¨jy*•ó”0IèµgZJ> }}}}}}Åí={öl¾s€¿­øáGª^ “v ­1 “„Þ'¡å—,YRQQQõ_^¼x¦ÕQ£FEEEåæææççÇÆÆ’ß4iÒÛ·o³²²***Nž<ɤ² ÈÑŠ:sÔ5*×aÒøùùihhŒ3F$]¹reÿþý“'OþTß%ÙµkW§N¨ß&UmsœÑ§jØT×»wïúúú-[¶ û²²2ôÇÉ“'ËËËGŒAÄ¥K—~ûí7GGGmmí'N¤§§;99 >Üßß¿¢¢bãÆðaO•ðø|þÖ­[ÿýï/^¼ØÄÄäÅ‹gΜ!йsçŽ7N*•Þ¹s'44” dãÆY³f!y™L¦h¦¼V''§3f”——_»v->>žÖ^CCÃÀÀàÀoÞ¼‘ÉdOž<ùæ›og9W3f̰±±ùý÷ßËËË»té²zõêøøø;wîA[é¼yó&NœX]]§©©éááqÿþý—/_1vìØ±cÇþúë¯?þø£±±±ššš——×±cÇ­·+V 6,99™öþ§‡‡GbbbHHÇÛºuë•+W&Nœ8xðत$???¹IËÐÐP œ9s†œw ‚044ÌÍÍ=|øpRRAÁÁÁK–,Áq|êÔ©FFF .üðáÇœg̘±iÓ&ÒÚkS¦Léß¿llì‰'Æ?wîÜ’’??¿¢¢"déîî>|øðòòòÓ§Ogff‚O¾|°\ZZÚ£Gž={&‘HöîÝ«D¢KMM=pà‡Ãa£Hý›VÉö31´zTƒ/X>ðÚµk?þñÇwîÜI•#¦¾ó~õêÕ„„.—»víZ©TJ>5ܽ{·\í ÀúV©2xáÂ…’’’®]»b B€ÈþܹsjjjìõÉ¿iµ÷¸\.íDHB•Ð#7~Ùòaaaõõõ‰‰‰ÙÙÙuuuT%¿¡C‡ÇÆÆMŸ>ÇñéÓ§K$Ô?þù'©LÝË  ÈÆJRÊîÂ… ß~û­­­íýû÷•&&&J$t7¯Qz´Ú{ÊCd’Ðû²åß¾}üÛo¿q¹ÜëׯoÚ´éðáÃ(¼ŠŠŠ˜˜“iÓ¦…„„GFFþöÛo¶¶¶†††hvT¬äùÏDHŽÚÙÙÙ†uëÖÏçŸ;wŽI´o”^ ÆN¤Š¢„žJW_†|àš5kÐOb±800pêÔ©}úôAIÙÙÙ;wîÄ0¬¸¸ØÃÃc÷îÝEEE³gÏÞ¼y³……ÅÇÏ;·dÉ%5‚| ‰üªÑþýûcöñãG–B€Ò Ę5ÿ˜ì%ôTºú2äOž>>`ÆŒ?ÖÒÒjíÈ `£T×XÑAZ=øŒiAA€Oœi› IDATJSnuòùüÍ›7s8œŒŒŒ€€ø hû¤{÷îàSGÁˆ\x7nìÔ©ÓÇOŸ>-“É>a`ª!?Oºoß¾¶y"00ð‡~híºÜÝÝoݺ…ÖµMJhN|>ÿêÕ«T^\e;v|ðàÁ·ß~ÛœgÃLN^¿~½téR²ö   @M®Ãhš8Ðs8œS§NýüóÏ2™,--­ªªªªªJ(fdd?~\__¿e£lÕÃ>}ú888 ñšZãÈ‘#íííÛx¡›&3¶wïÞ~ýúíÛ·O&“) ^e|>ܸqÆÆÆÍi;“ooïŒ5 mŸ={vll,¬Æàó}_ÛÓÓÎçåå;wÎÞÞ~̘1ëÖ­+++;uêTËž×·êáÞ½{ËËËÑ[ÔƒƒƒÃÃÃÛøJ…M“i6lXUUÕ×_&%Á«¬BnG7 &'8Žßºu+44”Œ-(((&&®hcš2ètèÐáŸÿüçãÇ_¼xA„‡‡Gbbâ‰'rrrbbbú÷ï?f̘?þøCSSsË–-"‘(??ð±cǺºº>{öŒÇãÑ**Q4d©zèææ¶jÕª!C†|üøqíÚµrÏ/œœÖ¯_ooo_^^N~.uÅŠË—/777×ÖÖ¶¶¶>pà€L&#k\³fͤI“tttôôôRRRª««œœÖ®];}út©Tš••…aŠª¼¼üûï¿2dˆœ£»»ûòåËííísrrÊËËÑÆyóæ­Y³ÆÑѱ´´´  @ÑÃÆ©MÎÈÈX³f«««¾¾~BBAŠ!ÏÞÞÞÚÚÚëÖ­“ÉdT›ŒŒŒ 6(©B±Wåv´§§gÿþýQí´Bȵ%!!aóæÍ¡¡¡cÆŒquu544|óæ Ᶎ†† 6„‡‡#yË hhhüõ×_ðÔ€6ÅÈÈèäÉ“666Ô»R´I¯ýüüÈóýk×®½}û–ËåÕ×ׯ^½ý´mÛ¶ÚÚZǤ\¨DÑêá®]»ÂÃß>}š‘‘!•JåÞèß¼ysuuõÝ»w£££KJJ¼ÔÑ£Gëë럌ŒŒTSS322*--ýã?ý_ýUPPеkWÕ¹sçÔÔÔ¨³`ÇŽkkk½¼¼ø|¾ŽŽÎóçÏ7mÚdffV^^~àÀä$22òúõë:::räšìçç‡ì/\¸PRRÒµkWj`äÒÐЉD;vì@N¨6;wV^Óñôôüî»ïjkk·oßÎåriEmµ\o Ïž=‹vÍÉ“'ËÊʺwãããïܹƒ&?˜ø$pŠŠŠ¬­­çÌ™SRRrüøñ¸¸¸U«V•””(nTò ÈÄÄdòäÉ&Lppp(++Cwº”ƒ” ¥R©œr!Óvåe­­­õõõ¯^½*‹¥Rizzº\mmmccc__ßcÇŽuèСOŸ>vvv.\H$R©4;;[ñ¦œL&CºTR©t̘1ÚÚÚgÏžEö/^Ô××1bš‡% ué]]]rròÂ… 7oÞldd4vìØƒŽ=ºsçΗ.]BNV®\¹gÏTJуb“/\¸ ££ckkKü©TJ†Ý£G>Ÿ_RR¢<²aS…\ÏO:õðáÃ÷îÝÛ»w¯T*¥m”¢C¹ŠÞ¾}‹Ú{áÂ…Î;ÛÚÚ¢N+//×ÕÕ¥ÝËmÃ0©TúàÁƒ 6=z´GË–-Ãqœv#“—û÷ïO˜0aܸq–––555»víb¿¼‚I¹¢!iÓ£G ÃrssÑvÅùLOOÇq‡£©©©©©™jhhˆã8íüG‹¾¾>Žã?~Dö†0UŠa˜³³ó­[·æÍ›óðáC¤i\PP€ì“’’ÈgŠJ ÊÎÎÆ0¬[·nM[`ɦ¥r=¯««Û©S§ªª*©TÊÔ(Å`ä*"ÿE'Idüð8€Oð‰'ž;w.%%ÅÕÕÕßßßÙÙY*•Òndò‚®9¤R©P(Œ‰‰éÝ»7ŽãÅÅʼnDCC£ š¦@sss&ƒ¬¬,‚ Ξ=ëæææêêºhÑ¢M›6ååå1`À–“Jff&AÖÖÖÈ~È!†¥¤¤0Ù›››Ïž={ÿþý¶¶¶öööýû÷ß¾};šw­¬¬ggçï¾ûŽý¬Ö¿ ÃÈÉXŽüü|±Xܲ¯¯\¾|ù—_~Y´h‘››Žã´RyÊB6°oß¾(N¿®®®P(lÁh ÇÔÔôîÝ»}ûöݺuë€vìØ!LLL7²ôXWWסCôÇû÷ïѪEKKK—Ö{"&&æÃ‡k×®555533sqq‘›Z?~Œ–Mðù|WWWggç§OŸmÙ²ÅÈÈhÀ€ÎÎδÖÔÔèééÜ¿?%%ÅÓÓ³gÏžÆÆÆëׯ}ùò%Óe†††‡‡A"‘ˆ ˆ†††¬¬¬7êëë0ààÁƒŽŽŽ*'™3gêééuïÞÝÃÃ#???22’ 20j¨999&&&ŠÁ³ïL9‚8tèн{÷öíÛ7hÐ MMMÅF¡ÅÃÓ¦McjÈâÅ‹ûöíkllìé陟ŸO.èíÞ½{zz:\ð áTTTÌž={ôèÑþþþb±=Ô©¬¬TÜÈ’¤¤$===ôfº··÷!CÁ“'OÐüVj†H$òðð055MMM•[Ð V¯^Ý­[·ÌÌÌÒÒÒ={öôêÕ«¢¢ÂÓÓÓÒÒ2333**Jîµ’ëׯggg4hÍš5úúúééééééšššëׯWr¡œ˜˜èååµ|ùr¡PŸ½gÏžºººuëÖ™™™åääÄÇÇgeeyyy±éáää䬬¬>}úlܸ±¦¦†ØàÁƒÉèÙ³gäcKª û _Ed2ÙªU«jjjüýýÓÒÒ%“É6oÞ<}út¦*BCC£££333¸qãÆÊÊJ Ãf̘¡§§wëÖ-˜øÄÐ^JM¹U£TBì¿J„¨8Žãêêê666]ºt¡*2)²ÙÎdƒÔ­¬¬´´´öìÙC¾Om—˵²²²µµåóùÈ *emmm``ÀårikÄq¼W¯^9:tè!CÈf*vµ7ÔÕÕ‡ Ö»woªÐ#—˵¶¶¦n”ó@þ‹z{óæÍºººC‡åóùd¥ÔÀÈ‚ÖÖÖÕÕÕsæÌ!wiÃTËž'u(iÅäü×ÐÐÐÆÆ†@@@XXY¬à³ ÍÕÕÕ—.]b3lµÍw³¦M›¶iÓ¦™3g.[¶,''çáÇ´±Ñª*²‰jÓXiÆÆžjP¡žv°ñƒãø¡C‡âããѪœFÕÕ(šà“ZdúôéEEEèmN Ã222êëë_¾| !ŸãÇŸ0a‚¥¥eûù8ä×_˜˜XYYYXX4pàÀö[sÐÐÐxÿþýÊ•+Ù?aåp8>>>Ÿð£á*yýúµ»»;¡ƒƒÃ„ È…Híü¿|ê@þt¿‘Çãñx<.—Û®bk&MøÔ*—Ë%_ZoŸtïÞÚ¨v˜Q°ƒªäG‹†††¯¯o\\Üï¿ÿ~óæÍæKý©¬h=ø|¾±±ñ§Ž eh™gHT%?Z<<<–.]üàÁƒ:4_\PeŸ„O¢\ØL222œdYYYrròîÝ»•œ£]¿~½¼¼<33³  @‰qDDDeee•¤!‰««kEE…œÙŸþI뙌¶²²2777((høðá´Ož*=þ<11‘ü722òÑ£Gp"@‹AUò£åƯ_¿FKç[D\PeŸ„O¢\ØL’“tttôòò‰D[·neÚA7oÞÌÌÌœ4iR—.]Ö­[W[[ˤVhaaagggggwéÒ¥¼¼¼Ñ£G£µ´´ä,»ví:räH»ÿâííÝÐÐðÍ7ßÐNod´vvvß|óÍ›7oRRRttt-½½½ëë댌0 366®««“J¥èƒ>ZZZUUUTÉþÎ4k"Y±bŰaÃ’““å''§3f”——_»v->>þÇìÓ§O§N¶oßîãã³bÅŠÄÄÄ·uëÖ+W®Lœ8qðàÁIII~~~ä«årNÐ;×L5’¸¹¹=:''çÒ¥K®®®¿üò r(ç­QU#ã7nÌš5 ©UÈd²¹sçŽ7N*•Þ¹s'44 «©©yyy;vL 899M›6 ˆ;wî<|øi.*ºrww>|xyyùéÓ§ÑWÜ<<<Þ½{¢¨§Hë°Q}¨HUUUtt´L&‹ˆˆ˜:uªƒƒÃ¾}ûh-GŽøôéS©TzôèѱcÇŽ?þàÁƒŠ–III¤s©T#‘H0º‹“_ 755]¶lÙ¥K—UF]SSsóæM‡   9û°°°Ÿ~úiÒ¤I§OŸž9s¦L& …³fÍzûöíøñãÕÕÕŸ={/òð"""^S¸páRT"Iˆa“’Ÿ¢ìŸ¯¯onnnaaáÍ›7 UŠ 6J;„I’PÑÒÿcYµ¢Xàþýû+**nß¾VWW·xñbÇ›¦\H«íWPPpäȹÉ~ëÖ­LÙ÷¡â~äµQÏž=óòòŽ;ÆtžóöíÛ¾}û"Wä+öJð÷÷ÿðáËk÷;wîdff2P£Å0ÌÑÑQ"‘Ì;—öÝÐ’’d|éÒ¥7oÞ„‡‡ß¿ŸËåîÞ½»¶¶¶e¿È ÀçÍ–-[vRX±b‡ÃQ.IhddD«äG+ûÇç󃃃£¢¢ÔÔÔ02xÕD0IÒzCj±,«FÆT%¿óçÏ{xx ›˜˜˜àà`t¿·±Ê…LÚ~Šß©QîeCh'-@““óâÅ‹èè袢¢¸¸8%ó££cFFFEEEPPвeËÐUû‰ð‡~¨««›7ož’‡¬àĉ½{÷622rpp@êöLr]OŸ>}öì—ËÍÌÌôõõõöö...æñxAAA±±±Ÿ×lZ†aŠ÷Ád2Ò)œ4i’››ÛñãÇ·mÛæïïÿ矢Ûn#GŽ$•ü‚ •Œ¨²†!Ù?ª*žbHO&“‘2x´N¨ÚÔI¨’„A’„´ÞÐP˲jE¹ÁÅ‹ÛØØ¸¹¹uîÜ™Çã¡o¸0)qñâÅÅ‹1"""‚êŠÔö“H$·oß;v¬ì¿Èõ’r‡,”iiiè6l×®].\xõêÕñãÇÓî¬ððð#F¸¹¹999=ztÕªUß}÷ºËäœ%ýúõÛ¹sç¥K—nÞ¼©ÜÛ²eË–.]JDUUÕÛ·o/^\VVFkùúõë¥K—ÚÚÚöîÝûþýûà§Ÿ~š>}º¥¥%º±Ü̘ø2àa–‘‘¡©©InJLLœ2e ’UzðàA\\\zzúªU«–-[vüøqdääG•ýÃ0,!!A °qHŸþüù)S¦DGGWWWëééÊÃ^¹ÐÙÙyÆ óæÍÛ¶m[TT”»»ûû÷ïÛ¨Üa£¢Hzzú¡C‡ÐìvëÖ-— .(ÚQVVöûï¿=ztøðá7nÜØ½{÷‚ ”|yœ%¿ÿþ{UU•§§§JW'NœX»v-Š– tþAk¾~ýúï¿ÿ¾¸¸8$$D"‘deeÍ;·W¯^­ú x>/þóz窼¼2'N\ºt)ZmáïïïëëKRhT0`€ÜðJÊþݽ{—œ?%^ÁädΜ9´5’’„qqq*½1©$²1ž|hll<`À€¤¤$´tE]]=%%%44´G;v\²dÉìÙ³q¿ÿþ‹/ÐS¹g„äúû-[¶ˆÅb&'ººº´5’!©««gffFDD˜™™™™™ÅÆÆÊd2&o;wf_µœñŒ3$ɺuëôôô6lØPUUõêÕ+Ô´7n$''wïÞÇñ·oßFDDôêÕËØØ8&&&&&†ÇãÉ5ÙÊʪ¶¶vÏž=gÀ€?~<~ü8‡ÃQÔöcéPyC† râĉAƒQ=SŸºÙØØÜ¸q£²²ÒÒÒÒÊÊJθsçÎ999ÏŸ?2dŽãcÇŽýøñ#ZZeii©è!÷ŒPÑrРA%%%çÏŸ7111ú/†††Š` ‹eH˜xþü¹L&[³f *‚îB'%%ÁBTÓ¥K—©S§2© a¶pá‚‚±X, Ïœ9C.]™4iRJJŠH$ª©©?þø#‡ÃiÔDÈä„©F’Ù³gçåå!ƒÇ£‰ÖÓDÈÆÇñ7nH$’†††‡Þ¼y3555ÍÕÕµ¦¦¦¾¾~ðàÁãÇONN‰DõõõïÞ½C/ÚË5ÇqOOÏâââÊÊʺººÈÈH¤©K»jtܸq**oÈܹsÅbñرc妩T*‘HÄbqeee||<’Pž3gŽ¢ñèÑ£Ÿ>}ZWW' E"ÑíÛ·ÑíYZc„ÜD¨h¹iÓ&ô€Å€ˆ7om´´!SG‰D½zõBÿjjj–——Ÿ;w&BX¡ü )LJ~´²Ôuö,ÅÙkÊ…¤(IHë­QUËp¹\sss ôoªÐ`c• UjûQ[§Ò¡ò†xyyÅÅÅÉõï!¿WNkŒ|ØÚÚêèèÓ+†Dk‰ Ã`Š–öÌŒ)¹Ú‘˜hI˜&ËQh¬v rIÂF…¤ÒX‰Ü-M6•¶``Jì}||Ð+l *7–ÛÎÞskX6Öà‹åK•$l)˜¤}ÛÒ¸5,k @å‹;Ð h@T¾°€OO jçvïÞ½+ñ­ ì}h2*V êééÅÆÆ~ÂK«æÄÐâ§…Ïç_¾|Ù‚ú‰SSS‚ êëëi‹0ýJºÚ¶m[CCCBBB 6–Ïç÷êÕ«¢¢¢¥¶ÚC¾5ÁOXX˜X,nÙ½8†¥¥¥!7¡P˜‘‘qüøqò{ÄêêêÍפÂ^OŽd̘1ýúõSbЖñ·{÷îíׯ߾}ûЋá»víÊÏÏOOO/(( “ûÖ¹ò_IWÿú׿8 (øgkk+ ‘ìúT7 B•Òƒ*Ù ªÌ6²‚vvvr dï_‘öo*cPÄÛÛ›vïÀм¼<¤ñ6f̘uëÖ•••:u 5-¢H…½ž ùÞa{ˆ¿E6lXUUÕ×_Ƭ_~ù¥¦¦ÆÛÛÛÂÂÂÙÙ9666''ÇÌ̌ͯTW8Žßºu+44Tîõ€Q£FI$’¥K—J$ôQo6„*¥U*²T™ldG-×@öþiù¦2E˜ö>¬ÈËËóóóC/q8œS§N¥§§£ÃÉÓÓ}â„Ïç{yy 8põêÕÇŽ[½z5õ(EæþùçŸÍÌ̼¼¼ÐOŠŸGÁþûB4ª Çñ™3gŠÅbgggdæääôÇ=ztÊ”)dArPX±bÅ?þñ²^ww÷U«Vq8œVŠŸDyY'''??¿Ý»w6 ÇñE‹‘AÚÙÙmܸýÝ¿ÿ;w0ÇñÿûßïÞ½Cï·iiiÿõ×_èÕ@Çûö틾牾9 äW è®0 ûꫯÆ'÷¼P(8p`}}½­­-ŽãÔ½Àápž?Žô‰äöÔü6r8œÀÀÀ{÷î)¾Ž‚ã8ze©.ËínÒÆÌÌ,??ÿÌ™3е(É Ã&OžŒ&9Çøá‡ÚÚÚÒÒÒmÛ¶q8œY³fI$’ Œ3F®Ÿu¾a ¡\ŽÍœ9ÓËËKWWð.]ºìرcÖ¬Y8ŽÓî}Xlò¨»víÚÛ·oÑ]PP R;Iöó(Jôähõö0Ê àççWUU…>®­¥¥URRrêÔ)r`jñøI¥ù·ÿþ’’uuu ÃΜ9#‹­­­qß²eKuu5 >55õäÉ“ÈôiÓ$É·ß~K^8Ž?yòäùóç\.Wù¯r®0 SSS+**:xð µÛ ô¯ýK[[ûðáè BöÒƒl„–˜„Uê â,d,×@6þÛm¾aÿ;*æØ!CÊÊÊPE …hú§Ýû°"///44tÇŽ»víºxñbYYÙ’%KÐH¤R;Icø“ž“Þ5;;;±X¼~ýz‡ãîî.•J'OžŒãx+ÅOÒ(Í¿ &H$’™3gâ8žýñãÇ_ý]Q¡ÌihhˆD¢;v Îqqq‘H$Ô³ø+W®$$$p¹\å¿Ê¹BÄÇÇß¹sGîÒ fl4ÙKªœ• ²ÑT)+¨Ø@•þÛs¾QýÐæÇóòò …3fÌ …¿þú+¹»÷>*ùÏÀabb2yòä &888”••}øðÖéÞI¥RR÷Žª(•JI@ Ø$–-[–™™™••uëÖ- ÞUoO*•^¼xQ__ĈÔ¡3:::..nÆŒ8Ž;99¥¦¦>}ú­‘køU–¥jþ;v iþ…‡‡çåå9::N›6MOO/00pâĉ8Ž[YY…‡‡Ñ£G>Ÿ_RR¢bϰ€ÖUyy9ºiFBêNPwGZZÚõëׯ^½zêÔ©®]»^½zUnôDÒƒ^^^;v}Z*•îÛ·OKKëÌ™3äaß–ñ“šnnn®®®‹-Ú´i“L&{ôè‘………½½ýƒ¢££³³³7oÞœ——ED~~¾X,&ÜGEEUWWS8ôìÙÓÊÊ ½¦üW9W]]]¡P¨2xRƒP&“Q5ѯãÇÏÊÊš0aêØ&K"¡AOOO%Bƒ´ù@¥™²‚Ÿu¾1åØÐ¡CW¬XñèÑ£¥K—’­ÀXï}¨ÐœÆÖÕÕuèÐeù˜˜˜>¬]»ÖÔÔÔÌÌŒzUA»j”‰û÷理¤xzzöìÙÓØØxýúõ±±±/_¾”æ ?~)ÿÙØØøøøÔÖÖ†……YXX "¯_¿æñxÞÞÞèE‡Q£F%%%aÌÊ$¤ÁàÁƒ·mÛvíÚµ¸¸¸^½z)dr‚ã¸H$z÷î‘‘Ñ£GÐôèQÏž=ÓÒÒЕœ’²Lþ?—|cʱÇçææ:;;§¦¦R—¤‘{Ÿe<`´aRR±%j^ IDAT’žžžÜ &D"‘‡‡‡©©ijjjlllyy9ùÓæÍ›§OŸÎr"$bõêÕúúúééééééšššëׯ§½™vùòe‡sýúu&ò6‹_$­^½º[·n™™™¥¥¥{öìéÕ«ŽãÅÅÅqqq‰‰‰èÑѵk×ÔÔÔÈAðgÏžQGmذáôéÓ;wî,,,|ñâE§Njjjþýï£;¢Ê•s5cÆ ==½[·nann¾dɹëEòÉÙ“'OLMMW®\™””dff†ŠTUU¹¸¸Ô××GGG———‡„„¼~ýzÆ R©T¹[ ÃHƒ3fèêê.X° ###ë¿Ü¿¿oß¾Ê=P _¿~]__ãÆ ´ÓoݺUUU˦,-ŸK¾ÑæØ?ÿùO{{{///±XüóÏ?6ìçŸæp8Ô½¯2þE…Ÿ|SÌ1jÔì¢î}Úå*€Eñ¥l}}}''§>\¼x±ˆ7?~%13Ù:t(>>¾K—.rÛÉ?ÈÉIù¯TWÓ§O/**3f ú© }´EäþUé¶ù,mZ¤ìç’o*sLnïЦ´™ àüùó+**"##[Ðí'Q1Doúøø4ÿÝgÒU\\œ»»;õ*¤± aSD¥Mó XÚ´FY*ŸW¾½~ýšº÷hSЊÜM¶VªHÉ ±æ¸m›øåàr¹-%ƒ\uïÞÆÁäóÊ7ØûT¨oêééÅÆÆAkбcÇ{÷î544¼{÷®ÉA4ʉ¶¶¶¶¶vMMÜv}}ýN:ÕÖÖ69Œ&£²—ÚsEîîî;wî¼zõªJŸljg²ilÙæ·”}»ø›ÃÁ0läÈ‘ööö8Ž+þ¬®®Îçó•”çóùãÆ366¦-ΖN†.rss_¿~mccƒìG•›››ŸŸkggל`š€Ê^j)ƌӯ_¿–õÙ§O6=Ʀ™Tj^±)Km]ó»”}»Z%QÓÊfddTUUUUU•••%''ïÞ½›Ãá´P°(ÎåÒ\r¹\凟–––X,öôôlÎQÊÒÉóçÏß¼y3|øð&&&>yòÅœœœüüùsKKK ‹ÄÄÄgϞѶ¥õPÙK-EQQÑáÇ[¶®½{÷–——óx<•–lšIµ¡æ›²ÔÖ5¿KÙ·«EPr5­¬@ 8w½½£££———H$Úºu+Ì…ÐðÖ­[gll¬¦¦æååuâĉe˖ݸqcÖ¬Y¾¾¾‰‰‰!!!<oëÖ­W®\™8qâàÁƒ“’’üüüd2™œ;OOÏ’’’3gÎÈd2ww÷áÇ———Ÿ>}:33“z‡ŠÏçoݺ•¬èìÙ³†q¹ÜþóŸ&&&111§NBÎ=<<Þ½{Ò©S'ƒ¼yóF&“=yòä›o¾ÁqÜÐÐ077÷ðáÃIIIA/Y²„zr½hÑ"MMM™Lfgg7zôèC‡Éd²þýû»¸¸¤¦¦1wîÜqãÆI¥Ò;w†!¤¿¿ÿO?ýDÛ,{ÉÍÍmôèÑ999—.]ruuýå—_d2Ù@¹;xŠñP•‹Í××W&“999͘1£¼¼üÚµkñññ¨“Ÿ+V 6,99™[W¬XÁápPGaæîîÞ¡C‡?ÿü“ŒŸM3I›Õ«W“yuìØ±E‹¡íÊ£"!ýŒ1búôéÔz÷îÝ—/_AÛ^ÅvÉ1oÞ¼‰'VWWÄÅÅ¡RNNNÓ¦M#âÎ;>$÷>Ó®”Ëm¹Æ ¦tRt¸f͹²d¨UUUÑÑÑ2™,""bêÔ©ûöí£mÍâÏ?ÿÌËË+((¸y󦥥eCCCJJJjjê8NAAÁ¡C‡8Ž––V}}}||ü£GBBBêêêüýýÑvòbîÀÕÕÕ³fÍÂq<  ¸¸øÚµk EEEämLòFV¤­­-‹ ÃÂÂBCCÅbño¿ý†²‚‚‚#GŽ(^%ܽ{7&&†¼Ú _½z5!!zr½oß¾’’uuu ÃΜ9#‹­­­qß²eKuuu=0 Û¿EEÅíÛ·ÃÂÂêêê/^Œã¸b´=€‚TÞK†íÚµ«¡¡!<<üéÓ§R©]¬PHBF¹f’‹ÃálÞ¼¹ººúîÝ»ÑÑÑ%%%cÆŒÁqœÉÏÑ£GëëëŸÍÊÊ’J¥ß~û-Žã´í¥mµc½½½kkkƒƒƒŸ={& 'OžŒãøÖ­[kkkŒŒŒTSSëܹ³X,>wš:ä¨#¯X,öõõåóù\.÷äÉ“ùùù<œ¿ûî»ÚÚÚíÛ·s¹ÜŽ;ÖÖÖzyyñù|çÏŸoÚ´‰z £RdEèß³gϪ©©!çeeeÝ»wÇ0ŒÇã)üóçωDäŠaØÐ¡Cƒƒƒccc‹ŠŠä. %ÉÌ™3qÏÎÎþøñ㯿þÊáp_¼x¦ÌóçÏ{xx ¦ÅÄÄs¹\Ú {€M/ikkœ?5ðĉäDHÛ@Úx+"c366.--õññAEbcc¯\¹Âåriý¡‹H´= @(òx<;;;±X¼~ýz‡ãîî.•JÑ{ö,ÚxñâÅÅ‹1"""‚¶uuu´¹Mm¬’*:TÒQiii(“»víºpá«W¯Ž?^*•*é.šÍR6ËÍe2õ:FWW·S§NUUUäQêìì¼aÆyóæmÛ¶-**ÊÝÝýýû÷rž™þýðá†aݺuÃq\ÎÆÀÀàüùó¹¹¹k×®¥N!ÙÙÙ;wîÄ0¬¸¸ØÃÃc÷îÝEEE¤Û¨¨([[ÛÎ;¿zõ* àûï¿···711 BoΟ??eÊ”èèèêêj==½ÂÂB•½!×ÊmÐýÆÜÜ\å>Êã¡BúÑÓÓÃqœÃáhjjb– x<ÞÙ³gý¢‹cÅþ¿~ýúÏ?ÿܳgϱcÇ’iU¦+šÐ:*û÷ï·²²š3gÚ­´íej‰®®.†aÈ )) Ã0´ÆøãÇhcAA†aJÚH›Ûm ›NKOOGϳ1 »uë–‹‹ õü€¡e9\¾|ù—_~Y´h‘››Žãæææ³gÏÞ¿¿­­­½½}ÿþý·oß®ò°'ï õíÛðüü|ÅþÔ©S . …h‹¥¥åíÛ·GŒA„L&ËÏÏïØ±#I=zdaaaooÿàÁƒèèèìììÍ›7çååEEE1yò䯾újÆ NNNß~ûms^ˆdMææælŒ›OVVAgÏžusssuu]´hѦM›&NœHëG 1`Àŵþ§OŸ–J¥ûöíÓÒÒ:sæLk ¸MhÝüùóW®\¹gÏžððpm{óòò˜Ú…@§bVVVÈÀÙÙù»ï¾C®Ðcc Æ ‚aXJJ S0*s»Ó ¥4"%%Çq6~5þp0 «©©ÑÓÓS< fA‡ºwïÞ¾}û ¤©©éãããááA„H$"¢¡¡ iÓ¦1É‹/îÛ·¯±±±§§g~~~DD„\__ßQ£F­Y³F,uìØQ ØÙÙíØ±ÃÀÀÀÐÐÐÅÅ%33]S’ܺu«cÇŽæææ—/_–J¥?ž8qbTTyŃã8zOíÚµcÆŒiñ% 111>|X»v­©©©™™™‹‹ Ù ´}ÒØx?~œ‘‘±aÃ>ŸïêêêììŒã8­Ÿ'OžmÙ²ÅÈÈhÀ€ÎÎΤÿ‚‚‚ÇÏ›7ïåË—ÉÉÉÍœ™òªQ­377?tèPxxx@@@=ŒŒŒºtéBÛÞ§OŸ2µ ’••µqãF}}ý>>`ÆŒ?ÖÒÒjZ'0!‰<<>>õõõŠí­¨¨PÒ. ÃÖ­[gff–““Ÿ••ååå%•JW¯^­¯¯Ÿžžžžž®©©¹~ýz%Ïáis›llNNNPPP£vmGa¶lÙ2”êOž<155]¹r%zGHu×ÐXpïÕ«—……‡Ã‘[ÄHý—ú7²TÜŽø!uuõaÆõîÝ›|™Éù¯¡¡¡ ŸÏ'‡¹"r 3´°°oß¾ýúõ#7ÊA†ìåjçr¹æææ<j©¤7˜z€ÉUjee¥¥¥µgÏò]oÚU£lâ‘+ˆ:ÁÊÊÊÖÖ–Ïç“/œÐúAÁX[[p¹\êÒJOOO¡PH»@±±ÉÀ”Wj*KÙÓ¶WI»¨½dmmMMK´qèСC† ¡æSis›ÚX6 ”Ë ²,µ·åZ 7E Õiì >›ºØ´²Í/®’iÓ¦mÚ´iæÌ™Ë–-ËÉÉyøð¡ò¯4-ÅRJüÈm×××wrrúðáÃÅ‹[ðÓ<´µ·ToÓúQé¹EBbrÒ4oL¾¾þúëÄÄÄÊÊÊ   ¶·oþüù‘‘‘ÆÆÆŸ:€¶£}Å_0h¹?šüÐjÀöö°Ý!D/´}êXh@°=B•6 GØ4ø|>Zû©€/Ð#l@Öô›SÖÈÈèúõëååå™™™ G­ è6Ð#¤µ=Âæ”½yófffæ¤I“ºté²nݺÚÚÚfe0z„ Gz„íQpäÈ‘OŸ>•J¥G;vìøñãFÕ4E½&×Õœ&´”B GÈ2ªÆ:Wô£Òs‹„Ää¤iÞ˜*Ùð™z„í“ö5Áà G@{ô[Ð#Tiz„´[@°=BZÐ#lrÙˆˆˆÊÊÊ*FÕÞ-Àè6Ð#¤µ=Â&—µ°°°³³³³³»téR^^Þèѣѿ-þ†+è‚!èbíOüˆ ú~oLL ú².Üæ€Vô1Ð#=Âö§Gˆð÷ÿ?öÎ; Šk}Øgv#°‚b‰%X¢¢Ø%–Ø»Þ%¶/c4ÑÄ“h“kØ¢þìz ((( h H_`—Ýïs;™™3;»3»,æ}þÒ³3gÞyÏ{ÎlæÙöìÙ3«}®€(à#Dà#¡íù1p!+>Bð‚Ð}„X žwšrù?ÿüó &,_¾üÆ3gÎÄñúYÛûB/^¼X´hѪU«°¸1|„uëÖÅ>ÂO>ù„å#Ü·oß!CbbbJJJêׯŸm4õ ÄÄ×GˆJLLT«Õ*•jÏž=Ü~„}„ß|ó öÒ?ÓÅT¡È³c‚}„cÇŽåúéó5ÃGˆÂ÷›ê#äÖ¶©'hRÒ°(à#áÿ¡ø°&à#D|„à#´1!Ö|„à#¡Íù°6$o!ø€þ·|„ÜͰ8–x+jžQÏìcI9¹ y$ÀG(2*S;çöc´gYB"ub^o¤^ÀG`›ØÖZüC[|„2>B£Û€›|„2>BÞmÀGhö¾}ôQaa!KF¸eËx X ðJ|„¼Û€Ðì}ÝÜÜzôèáûŠ•+WVVVbï˜|!ð_ÀG>BðÚœðÅ‹¹¹¹øX^^^3fÌ8xðàÑ£Gák^°à#Dà#¡­úB§OŸ~ôèï#ð"ð‚ÐV}„óæÍ+//Ÿ0a|) –|„à#¡úßzë­+VÂ… 0`É’%yyyæõ€HÀGˆøÁGhc>ÂöíÛ/_¾üÏ?ÿ¼sçNÓ¦MqµÃý2`!ÀG>BðÚœpøðáõêÕûàƒè³~üøñÙ³g­ü²ð‚äCà#!ðÒÿ¶´{Öô‰`A,q¶yF=³%åä2䑡ȨLíœÛÑže ‰Ô‰y½‘:x}!€mb[kñk >Bl ðÊøn>BlðÊøy·¡”}SSS±†°¨¨(===$$¤K—.¶ö»2¼>€P"à#äÝ|„RöU«Õ{÷îíÕ«—¯¯ïäÉ“’’’œeŠ€ÿ>Bð‚Ðæ|„˜ââ☘½^SZZzâĉ¾}ûâäòžf>B>BðÚžP­VÓùÇ6±qãÆÁ·£ ?à#Dà#¡íùÕjõöíÛ›5kæááÑ·oßÈÈÈgÏž‘Ì_H|„à#¡úg̘1}útƒÁP\\|ïÞ½iÓ¦åçç ä ó!øÿ×ømÊG¸}ûö€€< ¶ùx=!øÿømÇGˆÒëõºWp?/ à#D|„à#´1!Ö|„à#¡Íù°6$o!ø€þ·¥}„ÜñÀXâ­¨yF=³%åä2䑡ȨLíœÛÑže ‰Ô‰y½‘:x}!€mb[kñk >Bl ðÊøn>BlðÊøy·¡Ùû=z4>>ž¾e)::úîÝ»ô£¢¢ÂÃíì€×ðJ|„¼Û€Ðì}W®\YQQáááòôô,//¯ªªÂÏÄqtt,..fŠ)øÁG>B›óFDD,]ºtРAÿ÷ÿ7bĽ^_PP0zôè{÷îùùùÙÛÛ_»v ¾òÙ!!ømÌGHQTnn.þØwðàÁ„„„ÈÈȳgÏ*•ÊU«V•••¹ººJùЀ|„¶ç#¼|ù2þ’ÿÑ£GAAA+W®|ñâ…J¥ ¹}û6ü@2>Bð‚Ð}„qqqÓ§O÷ññiÖ¬ÙÙ³gÕjõÒ¥K‡ Ö¡Cüå­@Ò0 žßQäòžBÖ.Â>ÂùóçÍš5‹ùÅí#3f övìØ‘å#Â[·n¹ººR¦ûj[ä MZdd¤““Ó'Ÿ|òâÅ‹sçÎݾ}ûñãÇãÆkÚ´éõë×áB2>BðþðÚŽðÂ… %%%ƒ ŠÅŸ£¢¢¨×ëÃÂÂàB2>B„ÀG>BÛój4šû÷ï{xxо°ððð&M𤤤à­ÈøÁG>BõÆÅÅUTT?~ÅÉ“'‹‹‹oß¾m4ó˜ ɇÀG>Bà#¤ÿm!kº¸_,ˆ%FežQÏìcI9¹ y$ÀG(2*S;çöc´gYB"ub^o¤^ÀG`›ØÖZüC[£æùIÞAúï ­ øn>Bl–šä#ðþöÛoéééÉÉÉ………V6Ô€wðJÙ755µøï|ùå— ^KQS|„$ïàçŸ^XX8wî\ggç~ýúµoßÞÊ÷¡€wðJÙW­VïÝ»·W¯^¾¯Àê@vjŒÐÝÝäœ3gΩS§vìØ¡Õjñ³’™Ç!ø™Ô!¦¸¸8&&†>(|Ç –¢fùéNhï £££F£ùâ‹/<þüÞ½{³>‚|„45ÅGˆR«Õ ¡+Q³|„\ï`‹-t:]bbbBBB|||yyù/¿üÂÜ|„à#ÄÔ,¡Z­Ž‰‰ùý÷ß7mÚ´iÓ¦O?ý.Š`!j˜ëÄí7oÞœ;w®^¯_³fÍ‚ víÚ•’’‚O|„à#ÄÔ,!BÈÑÑÑÃÃ7VËíÐðçV¹|„Ÿþù„ –/_~ãÆ™3gb ŽÀx}„¬m°w!ôâÅ‹E‹­Zµª¨¨H¯×ß½{¯/‡þôÓO}||RRRèn±°nݺØGøÉ'Ÿ°|„ûöí2dHLLLIIIýúõ³³³fâ>Bxx3Æôó!„ÕjµJ¥Ú³g·aá7ß|ƒ}„ôÏ´F1ÕG(òì˜`áØ±c¹>Bú|Íð"„ð½Ç¦ú¹µmê ŠIZDDD@@ü£‰À jŒäÌÍÍÍÉÉ¡UÎÎÎ!¦Þ|„¡šæ#D¯> cà*–£Æø¼ƒ'OžœBT}„X’7Ù˜"{•Je«V­°Žw)!øé½j„·0°,–x+jžQÏè–PÜÉeÈ#>B‘Q™Ú9·1%$=$R'æõFêàõ|„¶‰m­Å¯1øþ àÇÁ1µõHÊ ¨NìììŽ9²víÚô ¿««««««¼}ÚÙÙIüj‘w–:880Di ²G 5..núôé¤ò¨K “Equu•ýÆcñ899ÙÔ_bX"Yfv™!›¿@Z9“Vƒ4Á­=d1Ÿ­Y³&!!÷nC„ÐŠŠŠèGoüñÇ………ôáèg~šmQQQzzzHHH—.]L½B`µ¡F£©¬¬dª ¥æááqìØ±’’­V›••µjÕ*“r¸}ûö'Ož§¥¥±nwüí·ßòóóµZmQQm[”%‡ùùù<05TRöH¡bÆ—››Ë}*:†·~,1L²Ô «°Û·oõêÕ²²²ÒÒÒÐÐP‘ý|ôÑGÌ3ÂlٲŤqéܹsdddYYYEEE\\œôévõêÕ¢¢¢b={ö“1Þx¸gJ?xÝ(Fg™eFšzfçíèÑ£ñññôÆÑÑÑwïÞ¥ÿnÒýh²,’¼^Yt®žy$Ý|öÎ;ïOš4‰7cÇŽÅtLŸg```NNÎÌ™3§OŸ>}úô1cÆˆÏ 3ÚÉ“''$$$%%áʰ6lØÀy{&© ¥vâĉG 4ÈÅÅå³Ï>+++3IÓ8a„Ï>û,<<<##ƒ9I¶EYrØ¿ÿÀÀ@Fóõ×_‹Õ<1$EQ'Ož¼rå w®’êÇÃ$Ký`¸…}õêÕ[·n½ýöÛ¾¾¾III‡¹0¹¹¹õèуž€+W®¬¬¬œ¢¨yóæ•••ååå-_¾\¡PŒ=Z§Ó}ðÁâëÍ#+2“»[h¶Î}úèѣ̡—>ËL*3D˜zRò^PPàãã³{÷î~ýú=|ø°°°[Û£GÊÊÊóçÏsgÍ‘“ÉêZ‡­3x0j>[¶lÙ XeN¿êàà Ñh¾ûî;îÙ¶oß>??Ö¬YX[C"Œˆˆ¨¨¨¸{÷îÓ§OËËËY¶Â÷ß¿¨¨(333##£¨¨hÞ¼yÌWÕjõöíÛ›5kæááÑ·oßÈÈÈgÏž15@C† Yºté²eË>|˜˜˜øõ×_/[¶Œû›Wm(1°þýû§¦¦†„„̘1£V­Z¢²ÿw¶mÛÆ|[*`[”˜Ã´´´ëׯÇÄÄäääܹs‡ôã. 3ĘøøøÓ§O3ߣ Ô蘭»ôúá-ì>ø+¢ð–ø¿ÌP…ÃÌ›7¯¼¼|„ ¬rYÕ˜‰'j4ú‡7)éÂàO„¼ËœXñ`¦M›–ŸŸÏ½SC–Yfj™!ÎÔCÒòvùòeüEߣG‚‚‚V®\‰?î„„„ܾ}›Xu¬ÑLV×:lÑy$„Z­¾ÿþÉ“'Oœ8qâĉü‘Õ¯‚óÕÖ­[ëtºùóçs£9}úô… T*ëd‚‚‚–-[fggW»ví3gÎdee1ë¢(??¿âââòòò1cư>تÕꪪ*N§Õjóóó###YßüðÃiiiéééåå奥¥ééééééX;ÎìÇËËë‡~زeK~~>툗EQ... . /--½uëV«V­XÃpêÔ©ØWðÖ:ï…pÇŽØæº~ýzüö¢(‰9 _²dÉâÅ‹W¯^‘‘ÉÚF8TnöBeîH/t‹@ýXb˜d©ÞÂ6:…C½õÖ[ÙÙÙ»víâ¾$²ªBÞÞÞÏŸ?ß³g)éÂ\–47ÌÅ‹?Î=œôY†L/3Äw!”’·ÿûßyyy¾¾¾:näÈ‘]»vÕét£FzöìÙüÁŒ¡ºFÖh&«k¶èC† ÁßÈÓc:ëyßÇ?xð`hhè‘#G¸°eË–ZµjÑOždMúé”7nÜ {ã7xÛH‡ñã?–––âû’¥F]©Túøødddpã={öâWxyy½ºººVVVbk>þÆÌÛ¤WµÀ…P¸NxãA5hР¸¸xÑ¢E¼ƒ.q–!ÓË ñ]¥ä ÿ¸cǵZ[MIIÙ¹sgUUÕÌ™3™TïÈ g²ZÖá‰'Zn!BÅþwÔñóDHÂ/¿ü’Y/_¾dn™™™©Õj¹GõôôŒ‹‹Ã¿ 8::R5hР¼¼¼ððð;w†††þù矃ÁÞÞÞ`01¿4Ðétöööz½žû ¯^¯gZ㹯Ò.SƒÁ ÓéX=tèÐaÕªU«V­Š5 ´Ú0''ÇìÀüüüvìØ1k֬˗/ëõú[·nݸq£M›6¬Øþøãúßb~q°-JÌ!þÉ'*))‰¢(gggŠaB&…JÊ~·$,†DÕ«WïùóçÌRýXb˜0ë‡TØçÏŸG5kÖìÚµk¡ÆWVV&''‹ láÂ… ð÷÷ÏËË3#*Ì®]»&L˜À°HL—0Â%ÍBÈÛÛÛÞÞþþýû¼S@â,C¦”™RòváÂ…’’’AƒÅÆÆâŸÁ¢¢¢¨×ëØTËÈŠÌdµ¬Ã>D›GH bñý?¤7JˆqéÞ¤äää;wr¿PU¾bÊ”):®W¯^øê}íÚµk×®5nܸI“&7oÞd}iÎ<.·Ñh´4ׯ_ç½ÒÕÕ5'''44´Aƒ 4ˆŒŒLII‘XݺuÓÒÒ¢££;uêDQT¿~ýž?¾ÿ~SŸ^ÍûýLvv¶ŸŸ_ݺuÏœ9óìÙ3lZ—˜Cúûýnݺ?~¼¨¨¨C‡b¾OÈ)T&YYYëÖ­S(:tؾ};¾ož·~,1LHŽú!6EQqqq‘‘‘5òòòJLL$Ý6Ì ¬}ûö¹¹¹ûöíkÞ¼¹Ç+x¸%E… ÊÏÏ:t¨§§'î¡víÚHZº0æýFHŠ!4mÚ´ªª*oooƒJ™eâËŒyެ©'1oÑÑÑz½~Á‚øˆøçä¿þú‹´&XsdMZ¯¬¼[gñ þ”HìØ±ãÞ½{‹>ë{Þ¾}ûþõ×_eeeååå÷ïßïß¿¿øŸ4ÅG‹—*Þ—ÆŒƒÐh4ÉÉÉï½÷žôÀz÷î}ùòåòòò‚‚FsêÔ)3Á®®®§OŸÆß³?~üxìØ±²äþ~¿¨¨(>>Þßß_|²G •‹K;v¬V«íׯEQ¤ú±Ä0ÉR?4¬ÂîÑ£G||<,**Jü£Õ/^Œ¿’Áƒ‚á]×¢*))Áo½é&NœHQ””taÌ»’âAÍ›7¯ªªÊËËˤ‘¸Yfj™ÑçÈšzó¶iÓ&FÓ´iSüß7ß|óåË—{÷î%`å‘•¸^Yt¶Â<âAºù¬k×®%%%Ü…†¢(¦é¢(¥RÙ¦M›–-[ªAËEKÀUJ ïëîîîãããììlêgAŒ‚¡©£QòÙ%æ ÷û}aHÙ#…JsèСˆˆ|‚wîÜÁÿ&Õ%†I–úaFÈ ¬U«VXU(>0úÖ¸˜ ·€”t1Ã3u/R|øàÁƒäääû÷ﳾͷ´Æ¬zÍ|ܽüýýúá5®aÌP£Ñ 6L§Óùûûãn·lÙRVVÆÌ§õ¥hòjÛè>yëÄ:F4 s%Ñ$šÞ0ÂB5“ŠÊh¢lA­'>3æU‹˜¬ í|ávK¯<¼ªN&â‹„´ÎXmý±~þM8ÌÚµk³³³·lÙ²uëÖÜÜ\ü©–~•²°Æ¬zÍ|ܽú!×0&©ÑXiQ(ÏŸ?_»víþýûóóó5ø³³„M^mÝ'o;YŒhˆ3‚h”4Ó2&TC&•ÑDY¿ŠHSÆrÕb4«¦®HFÛ-½òðª:™ˆ/Š¢x×R»Ès_9ÖÏ?Vw½zõª¨¨˜1c†R©T(K—.-..fÝn97ë›ù¸{ñöC2®Ñ˜¤Fã¦ÅÙÙù§Ÿ~:uêÔæÍ›7lØPXXÈʧ5¥hÜqAÖÝYÁˆÆAéF4$Áô†Œ Õ‰Ee4QÂñXG­'23ÈÜjAfiêXÇ5i!ŽGúÊCñ©:™˜T$¤uÆ:ëõóÏ‚ø¥¥———R©¼wïþ&:55ÕÞÞ¾I“&Ìïô-§1ãb}3w/Þ~HÆ5“ÔhÜ´,_¾œ¢(ƒÁpðàÁÌÌLV®¬)EãÅ¢º;‹Ñ0ÜLIIAæѤ›ÞŒ Õé¾=áD Çcµž˜HŒbM,´ò¨:™ý›T$¤uÆ:몎üóú®zyy;vÌÕÕÕÝÝýüùó™™™øŽMß¶Ëø!ª&3ïígÌHÆ53ÔhL|||ÜÜÜBS¦L)))Y½z5ï^¤QQІ‘]Û†DÔ iì$Ña) F4‰¦7‘B5“ŠJ|¢¬PEb¦Œ@$Ȭj‘¤©c×ÔO$¤x´•G@ÕÉĤ"!­3V^7ÿbCQÔÔ©S?~¬Ñh4Mjjê¸qãLý…YÞ ¡ šùŒkóÔh¬<”••–””lÛ¶ÍÞÞ^dl¥ht<òjÛ¹u"‹4‚fÑ4Ó›¡š©E%]8jµžø`̨Iš:ÆqÍ[ˆy±”ÆÔ"!­3V^7ÿDdWÛ¶mUVÔ˜ ì«´13ŸŠkwóÔhL …§§§O:uÌX˸iTIt Ô‰õuwRwºÞ¤Ì5¢ÑûšgzSˆª™ZTÒ%c2f#rᬚ}\³«WÊÊC‘ S‹„´ÎØÎú#oþM†¢(3–6ËAŠÇÖâD²ªÑlíÔ¸Ø`þ¥#ñŒ,‘Ù}{@Í…4餸?I’5pàŸ¨ÑÙ¢ŒEØ FdŠ 0  3`öª(-°æß4ÁÂÎήiÓ¦………R:quu­S§NYY™\Q‰ÇÉÉÉÉÉ©´´”Õ¡Õjyÿ®ÅÎÎîðáÃÞÞÞ.\ànШQ£’’V£«««R©¬¬¬´P» åJ<Ü?##µÛ`0¤TN„©ò…ËÙhÆ’b_£ÖkY4~Ù‚$KIq'W»,š+‘ðJ%Ií6˜Œ@*¸'Àõááû¤ˆå ‰f,ñö5K™°^Ë¢ñËî$Y²HŠ;¹Ú«=W4M’J’Ú«7 fxõxO¤aƾ 6nܨV«ñKf‹åa3Dû"[ÊÄ资°)§ ÅgÉ")îäj·‘\a¤†$©$o{µ$Ả¤‚t‚Ô+zõê•——7yòd…B!E,€\üoÊqÍXôKík4̧331ª×ªYNA^KIq‡½ÒÛEªò,+á&I%Ií¦&MbÄŸÉ«'`ͤû_½zõéÓ§=ª×륈å‹ÿ^GŽùÎ;ï( //¯çÏŸ¯X±‚¹¾2dÛ¶m%%%z½þÁƒ_}õÕÖ­[é –,Y²cÇŽ[·n]½zõرcûöícݼ0dÈ.]ºPåêêêààðÕW_ †ÈÈÈèèhzbWUUuîÜù—_~qwwoÚ´é´iÓÄ@ŠŸ»WAAÁÖ­[YýÐ×ì‰'¾ûî»sçÎe]Û*++333[·nÍ|Kîàààéé¹ÿ~‘‰ÆT¤{Æ'^§N¹Úm!WFÚÍÍÍÎÎnÚ´iø"Ô¶mÛõë×ýõפv+'Aü‰ Æ[=f*H'Bw>mÚ´·ß~ûÃ?¤w®|D(?dä¿”””sçÎ 77·?üðÈ‘#~~~ô\=|øpvvö©S§ìììþõ¯…„„0çjddd÷îݧN:räÈM›6ÍŸ?ÿý÷ßôè½dôéÓçã?¦(ÊÍÍ­ªªjÞ¼y¡²²²ëׯ3ßáÆÆÆº»»7oÞ|èС81âçÝ+++‹·ooï 69rdÿþýÜ÷Ý/_¾Äø¦iܸ±(å±u©Æ\‰è›7oâËÆš5k,X°k×.NÇÛnå$Ð/òDH©àžíøž:u*¼1;¨| ·ü3½ûšHK%¨×ªANA ëQ°$Å\í"Ë¢¹2:Ð$©¤››oû¤I“¬œ‘'BJ…€5!Ô AƒâââE‹±º®|ÄW~ÈÈ—iÁŒE¿3•b_3j)£×ªANA^HŠ;ƒôvægˆêÊ•Ñ&I%IíVNîÁl¯ž€5!äíímooÿþ}:N³ÅrÈŒQ3 ·Å$ûÉR&R¯Å€˜ø…OÄBNA®ÖŠWq'W»íä ÓÑñJ%yÛ«+ "O„7¤DM›6­ªªÊÛÛ›>©b9nȃD3–xûš€¥Ì¨^Ërñ[È)ȵd‘wrµÛB®0M’J’Ú«7 fxõH'‚š7o^UU•——³“Är"O“‘ÅŒež}Õ‰€^K‰ñ¤™ç$yû¸Š;¹ÚÍ8YÙs%^©$©Ý“ÀÛ 3fÒ â’`Ëhå3Ë[Gú;Væ Û²ëßH'(W{€4Ðí¤~dŽL&L­dÒö¬ò¨ÀìT#¬ò¨ÀìT#FËþ‰(«;€:5*))©î(l sÒ¨Q#GGGÈð?‰µdgg·lÙ²4iÒ䯿þ2Ú-LçŠÐ…pæÌ™+V¬8räˆÁ`0©Ó£GÖ¯_ÿöíÛÂ;ÚÙÙ5mÚ´°°ÐŒ}béà¥cggwøðaooï .˜q,)qZíM…7'^^^ƒ¡¢¢‚wÒ«tWË—/¯¬¬LLL”ñdyK÷õÆêÍŒ~"""´Z­Ù£ïààêááQXXxñâEƒÁ@š¶ÂÓ™÷éêêªT*+++-ÔnœœœœœœJKKÍîÁÁÁÁÃã  @d»“pþüù¥’}QüùçŸóóóU*•©fgg¯[·N¡P6ððð8vìXII‰V«ÍÊÊZµj½ñ™3gö­öàåbÍš5 4@¥¦¦¥§§‡„„téÒ…¢()q¦¤¤à> RSS·nÝêêêŠ_25ÉVƒ™„Ð÷ߟ™™©Óé4MDDD·nݘ9~•îjܸq¹¹¹½{÷fåÓÇǧ  à£>*,,üì³Ï = ùùù<`–%@éb®^½ZTTTÌ¡gÏž8|DÖ«[¶laöc´Ž=O—}ttôÝ»wéÿFEE…‡‡ûúú²NP|ÿ\l¡Þ̘›"G¿G¼¹rttÔjµ_}õ½’°J”†·}ûöíOž<)..NKKc®EíÛ·¿zõjYYYii)¾ÐÊÛ.1Õ.@çÎ###ËÊÊ***âââX³O$¿ýö[~~¾V«-**bVo»%’ð7®]»vñâEîµä—_~yùò¥×’œœœõë× ¤õĉ=4h‹‹ËgŸ}VVV¶dɼ½R©4i<¬¼,¼óÎ;ÅÅÅ“&MÂÕ£V«÷îÝÛ«W/__ßÉ“''$$$%%9;;K‰3##÷Ù§OŸÏ>û,??×®]8Q¦&Ù:°ròã?–––®\¹ÒÛÛ{Ô¨Q·oßNKKkÑ¢…˜W™]QuòäÉ+W®°Š¤gÏž:núôé:nñâÅ …‚…þýûj4š¯¿þš•(ÒÅx{{ûúúúúúŒÃ“«] bª]€èèè„„„.]º´k×îîÝ»—.]â=ô°aÃÈ{üüóÏ çÎëììܯ_¿öíÛãÍHí–HÂß`]KfÏž½y󿀀€_ý•y-9rdppðªU«ÞyçúÄÆ·aƵk×úùùÑÌz]´hÑСCY‰P«Õ¿ÿþ;>¢B¡8zôè™3gð—,Y‚··³³ ôöö^´hÑÖ­[çÌ™£P(øû￯X±ÂÝÝÝ ÁÓà`Úµk÷é§ŸnÞ¼ùÓO?enÀê|Ê”)sçÎÅøúú~ñÅøßmÚ´Y±bEÛ¶m)Šúã?îß¿O‡§V«ƒƒƒ•J%^¸GŒ¡ÕjG…£9räï¿ÿ¾iÓ¦!C†pãœ={6}8„ÐÌ™3çÏŸ4)eF IDAT¯P(222è> Å®]»>|È›dÒyM:uëÖ­ß|óM‹-­™GGÇ/^ìØ±C¥R᜴nÝ:??ãÆ …BøU„+½ãǯ¬¬0`³{÷î]PPЮ]»ŠŠ Š¢˜£ P(¢££Ïž=ËšT¥‹¡^±mÛ¶gÏžÙÙÙáÿ2;¡·iÑ¢EffæîÝ»¹G¨„ÐàÁƒñÂMQÔ¼yóÊÊÊòòò–/_®P(F­Óé>øàƒ>}ú°NPdÿ¶Yoˆ37Y56bĈÀÀÀzõê!„\\\¾ûî»Ñ£GS%fôI¹b]YuECjǩؾ};óBØ®];­VûñÇ+ Š¢–-[V\\¬R©äjgÅ0zôhÖÛ,n p«»³ÅÁÁ!55uΜ9x÷ 6¨ÕjÞOQQQ¡¡¡¼W¦¤¤¤½{÷ÚÙÙ¡W3B ÝBIøÌkɦM›***.]ºtõêÕìììÂÂBÜé—_~YRR“››Û§OŠ¢~ýõ×ÂÂÂS§NEDD”——O›6 ‰Y¯YYY6l`Õtllì½{÷Z·n·W*•t¦²²²ð·ŽŽŽIIIaaa111:îСC©©©¡¡¡/^¼ˆŽŽÆ»X4xL|||xxø¹sçÊËË·mÛ†·ávþë¯¿æææÚÛÛ#„vïÞ­Õj»v튩¤¤¤qãÆ¡äää;wÒGÁEIÿ·ÿþ:nܸqE}ýõ×eeeçÏŸ¿té’F£¡¿·¡ã ...ÆÝ:::æææîÚµ‹^˜è>ÿüóÏ{÷îáD±’Ì{^ßÿ}eeeddäåË—SSS«ªªXåeÑœ :T§Óýë_ÿ¢k—¢¨K—.áq~•›ÞZµjåää¬]»–9¬íÛ·ÿᇜœœÖ¯_÷bŽB“&M2226oÞ,¾tYà ¡ðw§OŸ~ôè÷{6z Ï777osðàÁ„„„ÈÈH¼­Zµª¬¬ÌÕÕõí·ßf ˜þm¶ÞÐßç&·Æ:uꔟŸ´víÚ‚‚|I3úÜbÀ°.„¬º¢!µc¶mÛÆ¼Ž?^§Óõïßæ‡~¨Óé:vì(W;]$...mÚ´ Ú·o_“&Mèoª¹5À¬vî^¼ý0?准†ÆÆÆòN„ëׯsßMâÄj4š/¾øbðàÁóçϧ¿»&µ[( ƒ¾–àß„ƒ‚‚ììì”Jå¡C‡ T*•§§g^^Þš5kpûíÛ·ÿóŸÿ(•Ê}ûö-Z´7ÆÆÆ†……áfÖ«J¥âÖGÿþýSSS CBBf̘Q«V-ú%z_\‚7nÄýÇÇÇ—••uéÒE¥RÍš5K§Óáë™Eƒg›V«¥;ß¹sgff&©ówß}W§Ó1‚¢¨§OŸ>þü§Ÿ~Ÿ®_¿®T*4Íwß}Ǽnß¾½Y³f}ûöŒŒ|öìYýúõ=<<òòò~ÿýwÜÿŽ;²²²ÜÜܘqúúújµÚ… *Š™3gVUU <˜¢¨ŒŒŒ+W®|÷Ýwßÿýòóó?þøcÖÅžt^NNNYYYûöí«U«–R©Ü¾};ï…Ðr9ñ÷÷×ét}ûöe¾‰ûÏþ“˜˜¨T*…_å¦!úôiÖG7¼sÒÒÒ®_¿“““sçÎî%J tY½Λ7¯¼¼|„ ¼ïÖyë¹ÍåË—¯]»¦T*=z´råÊ/^¨TªÛ·oÓïô™'h´[®7f?¼5¦R© †^PPðÓO?ÑÃmtôI¹b^yë !DjgVóBøÁ0«ÿ×××W®vºœÞÿý¢¢¢ÌÌÌŒŒŒ¢¢¢yóæ±¾ç­vî^þþþýLœ8Q£ÑÐ$0C† Yºté²eË>|˜˜˜øõ×_/[¶ŒùKm‹-t:]bbbBBB|||yyù/¿ü¢P(HíJÍßJ­Gû÷ï×étƒáéÓ§øö§¾}û:99yzz!„ÞxãV­Z!„¦M›Ö­[·©S§Ö­[W¥R¹¸¸p Ó鸑‘‘Ý»wŸ:uêÈ‘#7mÚ4þü÷ßÿÑ£GÜ»­ÒÓÓ«ªªôzýÇíííu:]BBB¨eË–QQQ žÅÓ§Oq0=«oç‘‘‘ýû÷×ëõõë×ßµk×À¿ýöÛŽ;;vÌ`04nÜØÎÎ.77—ÙùŒ3¦OŸn0Š‹‹ïÝ»7mÚ´üüü!C†899íÙ³ŸÔ¦M›Ö½{÷3gÎÐ;ÆÄÄܹsgøðá›6m9rdrròåË—ñ¹7oÞ|ðàÁøùùùÏž=y^]»vuuu=räˆV«5 >¬–œ˜oW/_¾Ä_šÑ œ%½^O7¦¤¤œ;wÎ`0¸¹¹}øá‡GŽñó󫪪¢7_ºÂ¼õÖ[+V¬8xðà‰'x÷å­æqqqÓ§O÷ññiÖ¬ÙÙ³gÕjõÒ¥K‡ Ö¡C|ã"ï ÷oûõ†á­1ƒÁðã?6ìÀ? ¤Îèè ç C*QKW^>œ}êÔ);;»ýë_!!!¬³ã­vÞ½²²²xûñööÞ°aÑ#GöïßÏ,ã>}úà·AnnnUUUóæÍC•••]¿~¹ÙÍ›7çΫ×ë׬Y³`Á‚]»váë·ÝrIÀüíÚØ Aü†53ëׯß1½ùæ›o¾ùfbbâ•+WT*ÕÂÂÂ&MšÔ»woÖÛUa þEç½÷Þ0`@Æ Þ³„g& ß+_«V-æ{«Òëõ8ZÞÎõzý7|||ÆŒsëÖ­C‡uìØ±W¯^Í›7 !­˜Û·o¯S§Ž½½½»»»ŸŸ_DD„Á`puu¥(êùóçx¯¬¬,„ýû(ÌcÇŽõìÙ³I“&ýúõ;sæ =ÒgÏž}÷Ýw СC‡ÒÒÒï¿ÿ^8Éôyá/¾ÒÓÓéCX9'EEE¡† 2]\\ðÅ@øU^D^¨>|¸nݺµk×.[¶löìÙ={öô÷÷g–™¥ËËÆ‹‹‹—,Y¼Ê2á­æ‘‘‘NNNŸ|òÉ‹/Î;wûöíÇ7®iÓ¦¬åF|ÿ5¥ÞxkÌ`0èõú+W®8::FFF2kS&Ä{‹EE…\íô¿ C@@@HHÈÅ‹§L™Âݘ·ÚB¬½Hý¸»»ïÛ·/=== €õgÅŠ-Z´ðòòŠ¿zõj«V­¼¼¼6mÚD—JQQ‘^¯¿{÷nUUUUUÕáÇßxã R»V«µP0ûD¨V« CÛ¶mñ?èöÇ †={ö„††âvƒÁ0tèÐñãÇòÉ'ûöí3 !!!"/'~~~;vì˜5kÖåË—õzý­[·nܸѦM1û `àYðv®×ëÃÃÃþùçúõ냗¤–-[Þ¹s§ZrrãÆ’’’=zwÒ¤I“Ž;:tÈ`0¿Ê›Þzõê=þÜhð8T< IIIE9;;S…"Wé.\¸pÀ€þþþyyy¤mxëÉ… JJJ «×ë CTTÔÀõz}XX˜Ñ¥¿FשÆ:wî<{öìðððéÓ§ïß¿ÿÖ­[øU‘£/ o] ´“HIIA5kÖìÚµk¡ÆWVV&''ã+·ôvæÐãK”½½½^¯ç¾å"U;w/Þ~víÚåàà0aÂî_ûÑÝâO/:ŽuôÜÜÜœœœ–-[âÿâ;–_¾|IjÏÈȰP0{¿véÒ¥œœœeË–yxx´mÛvÔ¨QøýÚÅ‹SSS?ÿüswww;;»>úß`FQþƒÊ€€€>}úð¾ûãÞ5§R©V®\‰ÒìÛ·oÏž=™Om0ëÏ‚ÔùÉ“'k׮ݲeËÇWUU]¼xqàÀ7nÜÀÅQZZš––Ö¼ys£'uöìÙ¤¤¤%K–4iÒÄÓÓsáÂ…·oß¾yó&k™ËÊʺxñâ„ nÞ¼ùàÁÞE°¼¼ü7Þ0zDLllì³gϼ¼¼Z´hÁüTdœäååíÞ½{êÔ©õêÕëÖ­Û¾}ûœ·nÝj0„_åMo£F>|h0:tè°}ûvúžlvvvݺu[³fMYYYDD„··7ÞE t…»enðöÛo/_¾üÏ?ÿ¼sçNÓ¦Mñá4hбcGáXGÑh4÷ïß÷ððÇ#Þ¤I“””üIN`_Rÿ5¥ÞH5¶~ýúôôôQ£F%''3ïÑ9úÜ\1IÓVütÆÜ½{7!!aöìÙ 6ôòòš:uê•+W***äjg+==]­V?yòäéÓ§ÜHx«Ý`0p÷â¶õìÙsÁ‚Z­wR»vm‘Àœ}º¼¼¼´´ôñãÇxàÚ-‘b¬E©Tª®]»º»»+•Jzð(ŠR*•;vôññ±³³ÃùR*•-[¶ôööV©TÌN˜wŠòÞ5Š{sww÷ññqvvffŠ´/7H:ëÏü·B¡î\ `L×®]KJJè1æÍ³ÿÎ;wêÔ ÿÙob—,YRPPÀ¼Ë‘µŽ™{8óR©T;vtttüùçŸé?Ê´ZNpŸõêÕóõõõððP*•ï½÷Þ­[·è¿x•ÕÕ¡C‡"""pxwîÜá½™Sõwð—¬]H¥Ëí–™æ¸{,f¤z`…u¼#iÝÓ?ª9õÆ­1æ™Õ%rôysźrsKCjçž&3øV­Z5kÖŒ.3ÛÅ@ªvóvg–ŠxpðxfîÎÛn‰$ÔþFQ¸E–IÁjÁK銢¨uëÖÅÇÇ‹¹[U¸WWב#G>{öìÀ¤EÐ †ºxñâ#F̘1#--íÂ… ¦v.WNXÏDî«Ì®† –““ƒÿØ!´fÍÖ­ÞFáÝ…õ_£ÝJß@ä6²ì[SêÍh™7úôføBXRRrðàA\]¤5i:Ó{Y´½F@AvR?2GXüWtkÖ¬1ãžC&'N,,,ŒŠŠòôô”+6„ФI“îÞ½[TT”bþ¦ WN˜]ݹs‡ù¬B¡0õDÄìbtéˆÜÆû2©YõgÆè37óóó{÷Ýw;tè@Á[¢2–.ü³P*•ø7-)àod|oNw‹¿^6ãk)È’fW5‚µIFjV½I}êt ©De,]‚Tg&ÕŸ,ÿ( ð[êS"2¿­#é©Hr)®®®uêÔ)++cµ“ìb"­cæ¹ÄlRФ ]³Çë]3uô­){¤P­_x–_‹RV<$‡O^,Àô¬–…ÑÆ-Ä&D1F@OÅ•Kp•lø×éž={Þ¸qC£ÑTVVÞ¾}›ùÔ8D¶‹‘ÚY˜ä£9pà@QQ}Fü13xü¨L‘Y2ÃÇ…”")Õì Cò®!‚ZL–šW®F²£!ëž%ÆW–£aͳ…pbÔŒF!­fÌñ Šxœ@ªI)’˜QÍž0$ïI-&KÍ󨑲G cÍÂ³ÄøÊRxîŒ0['FÍh4*ÒÊcvºŒ%…áG`ÅÓ§ÑéiÍú$Mv³.F®Éàò—„ †$—ÐS‘¤SôOнzõÊËË›}š÷;eüW«ÜöÒÒÒ6mÚà'×!„Zµj•žžn0›5k¶}ûö´nÝ:!!!::š>þÇêÕ«OŸ>}ôèQ½^Ÿ=lØ0üàD„PóæÍYE…„„Œ=:22’ù©¦oß¾QQQ܇7’ÚBË—/wttܰaC÷îÝéFww÷ÜÜÜ9s渹¹EDD\¹r…¹‹‹‹‹››Û{ï½çääUQQÁ},=ýôð’’Š¢x¯Á¤T ¤HJ`ééé hÑ¢Ejjª^¯Ÿ.†W0F_® —+RöB¥±NáYh|™ICf†;#ðß9§”™5‘í¡Ö­[ëtºùóç³z#µ#„NŸ>}á•JÅšÛAAAË–-³³³«]»ö™3g²²²˜Õ@Q”ŸŸ_qqqyyù˜1cXÁ0Ÿï—ŸŸÉúÊBdªyS$%0Š¢\\\.\^ZZzëÖ­V­Z±jëÔ©S±¯à­<Þ !ïèKÌ¡p¹ •›=£…бNáñFˆl ðxg„Ñ ¡p`¡·Þz+;;{×®]Ü—Ì^y$¦ #p!4:¸ñ`xW<£ñˆ™žÈŠõ‰ø.„Rþïÿ;//Ï××W§Ó9²k×®:nÔ¨QÏž=ûã?˜1X®$Z­Þ¼y3~4ŸâÕ3j§L™B'Zñêéˆ7nÜ {ã7xŸUèîîãÆ úGxWW×ÊÊJ,³FõìÙS§ÓÑ=7hР¸¸xÑ¢E¬®ðwÐ …âÇ,--eéÐB—.]âWR;2}¼ýýý+++ׯ_¿dÉ’­[·VUU­^½ke˜ɱ¡»mÛ¶Ì¢<~üøÁƒCCC9Â]¶lÙR«V-Ò‹L5oФF]©Túøødddpoy˜={öâWxyy½ Œ¾Ä —«ÑP¹Ù.T+)B$m|¥iFLš4‰{!¤Ÿk40„PXXXjj*¯ÆÈì•Gbº0Báã‘W<‘ñOOdÅúD|B) Ç¿îØ±C­VãeSRRvîÜYUU5sæLf'*‰ÿž†°†Í¨\ ÃÕS‘äRø¿ÞÞÞööö÷ïß§¿ÿíСêU«V­Z‹Årµk×~óÍ7srr˜"ÙŬc¦ºÄ<==ãââð!ŽŽŽE 4(///<<|çΡ¡¡þù§Á`°··7 EEEâõWž9£©H‘Ù‰ÔìýñÇô¿Åüp"0ús(\®¡’²÷øñcB¥±BáYb|1 4#Ο?$á„ÕŒf¯


îŠÇDâôDV©O¤$\¼\Ó‚%Áüý [·nÇ/**¢Ÿ­Çäúõë¤;ô‚‚‚òóó‡êééÉÔSeggûùùÕ­[÷Ì™3Ïž=«W¯ÞeÚ´iUUUÞÞÞô\]]srrBCC4hРAƒÈÈÈ””îá²²²Ö­[Ç}@·óZÇ’““wîÜÉÝ‹·¿ùÂL™2E§ÓõêÕ GríÚµk×®5nܸI“&7oÞd}…MÃûµ€þ†)Õ)2;°ºu릥¥EGGwêÔ‰¢¨~ýú=þ|ÿþý¦>F‹÷ÛÞÑ—˜C‘åÊE {…Jc…Â³Äø"9 4#(ŠŠ‹‹‹ŒŒlÔ¨‘——Wbb"é~cn`íÛ·ÏÍÍÝ·o_óæÍ=^Áû‹¯+”taÌûâ[ñÄÄ#~zZ¡>i¸“]b£££õzý‚ ðñïÐýõi’¿$Ä‹©ð4à ‹¤§"É¥BóæÍ«ªªòòòbö3f̘¿þú«¬¬L£Ñ$''¿÷Þ{¬Ä1íb¤v^ë˜y.1ÄùÙ£oß¾8Âòòòû÷ï÷ïß_ÌŒ¿ ¤š”") "Åäї˜C)5Rö cµÂ³ÄøÊRx4¬a¶nñâżjFnf¬ÿYìbâ­cJp‰¦…Ø2PŸðšN5Àv€jØØÙÙqŸ de\]]yÿ¨ÅÕÕUäSáe‡·šñ_g[?DˆÇÁÁ¡E‹6õ¸““ï-©qqqÓ§Oçýz‡·…Ý‘#GÖ®]ËÚ’ÔÎK“&MŒnc5^¿å’4ôRf±…V'ëW#©öl¤&mí¢nÕ«’DMEõ{ÕeA#é¸úõëWQQQQQ5:"ÏT¢ÿ¬¹¤•¨šd“4ƒ ºwï^EEEaaáÎ;ů˲ÛÔd÷½I,0Yf1ièÍžÅHÚêdt°f5’jÏj’TËŽQ$.#¯Jæ QSgQýž,h¼t\·oßNHHèÔ©S÷îÝSSS/\¸ 2‰þ³ä$yÂ0”Õe“4...Ož<9þ|óæÍÇŸ››Ëû‡É¼ÈnS“Ý÷&±Àd™Å¤¡7{#i«“ÑEÀjÕHª=ë×$/¤j$µ‹Aâ2"~ÜÊ5ÙHÔÔY_¿g /AÇUZZúý÷ßã“ NOOŒþ3x¬ïäîÅlð„ÑXS6ÉÄßß?*'d×®]ÉÉÉ"ë\^›²€ïMdYn“†^â,–¸:]¬S¤Ú³~MòBªFR»ÑØh¥¨tyª°\“‰J¢«ºô{Ö± ñBÒq¥¥¥uéÒ!¤R©¼½½ÓÒÒ˜ÛXÈFŠÇÊ.@î^z½žÛÉFcMÙ$777Š¢RRRpç™™™ 6d½m·ŽM YÀ÷f´À,=‹IŠ8‰³Xâêdt°N5’jÏú5É ©IíFccõÀ«•Kž*0ËØøûûKñ`U—~Ï¢41pŸ0äçç÷ðáÃ$''ß¿Ÿõ˜¥ýgÕëäî%\W¼ª6Œ5j4Æ Óétþþþ8ž-[¶”••1Âú65y}otŸ¼fYŒa½ÄY,quÂ/V¨FRíY­&ÅÀ­Fáv‰JQ‰ãnRAþJšKxwËé÷,jAC¦»÷Bk×®ÍÎÎÞ²eËÖ­[sssñ"E÷i¶ÿ¬z]€Ü½ú!©Ú0Öqª±ò©P("""ž?¾víÚýû2áS¯ IDAT÷çççk4ñi±„MM^ßÝ'oYg#ÎÐKœÅW'dl@V©FŠ¢xkÔ.òìÄ×$2k¹n7o¹»Ñq_C¢«Zô{'N´œ ™îÞëÕ«WEEÅŒ3”J¥B¡Xºtiqq1ëî^ËùϸñXßÈÝ‹·’ªÆ:N5n>úé§S§NmÞ¼yÆ ………¬°¦M Éí{£û$˜f1wè¥Ïb$auBÆd­j$Õžuj™¾¼mŽMŒRTʸ‹Ÿe4*$ÙƒU-ú½‡"‹YÐéî=///¥RyïÞ=üsfjjª½½}“&M˜?ƒYÎÆÅú.@î^¼ýTm4ÖqªqóYPP°|ùrŠ¢ ÃÁƒ333YI¶¦M‹ ö,:‹1Ü¡OIIAæÎbé«“ÑEY«IµgšD¦//b¨•2îRf™TMïׯ–ÓïQV±  Àz+äååUPPpìØ1WWWww÷óçÏgffâ;6ÆÃìS®ßQ5¹yïÍc†DRµÑXÓ©ÆÄÇÇÇÍÍ !4eÊ”’’’Õ«WóîE>mjÙ}oHDYh#ÂÐK™ÅW'‘‹€uª‘T{V®IÌøD(›x¥¨Äq7:ËÄ"QSgQýž,h°*€¢¨©S§>~üX£Ñh4šÔÔÔqãÆ™z޼Bt ¨Ú0Ö—MÒlÛ¶­¬¬¬°°°¤¤dÛ¶mööö"O #£MŽG^ß2·Àd™Å¤¡7{#i«“˜EÀjÕHª=+פf_y‘¸Œˆw£³L,”4MÑofÅÇ@Ò³U—MAÖqµmÛVeEÿ™À¾JsrÓÎÚÝú²I…BáéééããS§N3Š–›3ŠJ¸C)GêS ²ÌbÒЛ=‹‘´ÕIÌ"`µj$ÕžíÔ$©rÌ®()ˈī’$̘u²ÀCµÆ‚gu!7›ŠÙ†SÍÖrÂÅN:ÏÈ ©%o$¯ßpËdx §`;@5P €S ° [”`€åY_|ñÅ·ß~;cÆ …B5¯9$៰eA]5BJ‹ckïo½õ·}åÊ•jµ:%%%///""Â××÷™ššZ\\\\\œŸŸÿàÁƒU«V™t ‘æù¥U«V}ûöem,&K4;wŽŒŒT«ÕéééqqqݺuýµoßþêÕ«iiiYYY¡¡¡x{R;`)ÂÂÂ"##ñ‡¥Riô*•““³~ýzÖf?ÿüsiii```Ó¦M{öìyóæÍ””ggg„Z­Þ»wo¯^½ú÷ï¨Ñh¾þúëj¼2Ï×(¿üòËË—/U*³QL–h¢££ºtéÒ®]»»wï^ºt úêÕ«·nÝzûí·}}}“’’>,Üðz2sæÌ   •+W¶jÕŠþØ1räÈàààU«V½óÎ;tãìÙ³·nÝúÅ_tìØqáÂ… …ÂÑÑ100°{÷îx›~ýú-_¾œ^ YØÙÙ¶k×îÓO?ݼyó§Ÿ~Š·\°`Áýû÷SSSøá‡F-Y²dèСôAÇ·aƵk×úùùÑÜ aíÚµsrröìÙƒ?'Qõî»ïêtºÑ£GS¥V«ƒƒƒ•J%EQ …"::úìÙ³ÜÅðˆ#ëÕ«‡rqqùî»ïpo¤üL˜0!88ø×_íÒ¥ EQ¤ä°ÎW Û›7oøõ×_¹B:K¤¬Ò888¤¦¦Î™3Ÿþ† ÔjµJ¥j×®V«ýøã EQË–-+..h§;ÄGôöö^´hÑÖ­[çÌ™£P(øû￯X±‚ùí+oi؇zñâÅŸþ™˜˜˜““ƒ¿4ûòË/KJJBCCcbbrssûôéCQÔ¦M›ÊËËÏ;wõêÕ'Ož<}úT¥RyxxTTTЋïòåËËÊÊð¢Éí¤nݺñññáááçÎ+//ß¶m›B¡ÎÈÈÈÊÊ:qâD‹-²³³×­[‡;üõ×_ O:Q^^>mÚ4¼žr/„={öÔét3gΤ)Šzûí·éO„ÁÁÁø¥&MšdddlÞ¼™uÁàÜ©S§üü|ÌÚµk |||HùY¹reYYYXXصk× ìééÉ›Öù~õÕW¼Ù®¨¨¸téÒÕ«W³³³ Y¬¬,˜££#oV™3?>†††ÆÆÆ*•ÊñãÇëtºþýûã”~øá‡:®cÇŽ¤vúJ†˜””£Óé:”ššúâÅ‹èèhüƒ·´d*[™¨]»vYYY`` ³³sttôâÅ‹›5k–——·fÍ;;;¥Ryûöíÿüç?Íš5+,, ÆG}öì¾jµÚ àuöÛo¿-//W©TžžžÜNœœœ´ZmPPnܹsgff¦J¥R(.\ˆŠŠªU«EQܾ̋}û-Z„· Ë,÷B8tèPN7vìXæjKÿ[­V§¥¥]¿~=&&&''çÎ; 4`¦‚7`•JXPP0|øð‚‚‚Ÿ~úI©TònÙ²eË—/_þöÛo¸1**êØ±cÍš5ãMó|y{ÃÙ¦uèС‚‚օ΀££#oVyG|âĉ¿Ÿøàƒt:ýë#þ¯¯¯/©y!Ôjµ7nÄGŒ/++ëÒ¥‹J¥š5k–N§ëÓ§½½=·´ª÷wY.ªòòòà·ü§NêׯŸ^¯÷÷÷wrròôô B½ñÆ­ZµòõõuppØ¿¿N§3 yyyÂ]÷íÛ—Û ^IŸ>}ZUU¥×ë=zT¿~}„^¯7 ƒ¡ªªÊ`00û™6mZ·nݦNZ·n]•Jåââ"æÄ¦OŸNþ[¼x1Ž!%%åܹsƒÁÍÍíÃ?e¥… 7«\¼½½7lØpäÈ‘ýû÷íÐ(éééøˆ>´··OLLÔét ¡–-[FEEqK‹”€êB…5jÔçŸ>a„å˗߸qcæÌ™®®®ø‡´7ß|!”˜˜¨V«4h@Q”˜S¿~}n'¬}õz½ðG;;»}ûö 2$&&¦¤¤¤~ýúÙÙÙ¤‹‹‹B...E?~üæÍ›uêÔ‰ŽŽ¦?=|øpݺux-Žˆˆ8yò¤¿¿?}I ¬×ë¯\¹âã㉯š¼[â/`³²²poýõB¨iÓ¦æ%ÊÔl3!eÕÝÝ}ß¾}ééé:!TYYÉݬ¢¢‚ÔN:"¾ZãPñfø“=·´žGåààpâÄ ÞäMÎvÛ¶m¹ïÌf×®]&L(((À-)))¡fÍš]»v !Ô¸qãÊÊÊääd|½ç¶›IË–- Ä*­Y³fÑÁl…ƒƒÃš5k-Zd04Á`¨¬¬¼xñbjjêçŸîîîngg÷ÑG5êòåË999K–,©W¯^‹-è¿+//òäÉ Aƒœ;tèàïï?Žðv"p¯Diiiýúõ¹îMQ”“““““S@@@Ÿ>}>A–””ìܹsòäÉ‹-rüÿíw@GûÇw¯ (UD„DTÄŠ¢±+v4–˜Ø@bÄØ°1*øª)%’W‰"XbBDAT¤EA‘v4á¨ÇnÌ›ým¶Ý^á3Ÿ¿`vöÙ™gž™¹Ý¯HôÞ{ïy{{óx¼ÚÚZA(ÚÙÙÙÙÙ 4hÿþýqqqøàÎTàƒzyyegg:tˆÇãÑæ¼uëV^^Þ† ,,,\\\80jÔ(™LFëb}Y¼`ggçâââåå¥ãÛµ£G:tõêÕ …8¡}ûöiii~~~;wvttôööŽ•ÉdLé]‘6´àí iu (ºiÓ¦ŠŠŠÚÚÚ¦¦¦„„AÆŸ••%•JÄbñÊ•+y<Þ‚ JKKÁb“‚‚ðÔqþüù2™¬¢¢âĉ2™ ¤S˜˜˜(ŠM›6a= @¡P€Ì‹-jhhÉd½{÷®¨¨Ë@ÀCN¥R)—Ë£££¯^½šÍ´XA·oß¾ÊÊʆ†pÑï¿ÿØ‹ÅÍÍÍJ¥R¡PÔÖÖ¦¦¦§%µÀ[¶l‘Ëå`ާ§§T*ݱcÇ£õÏäÉ“sss¥RiSSÓ­[·Àb&çëëééÉäm…B!‘HÀ=.ûbZ¯âÔ××cª˜3gŠ¢C† K]@ë÷ìÙüXaJ®xöìÙ¬¬,Ð.nnnJ¥réÒ¥|>Ÿ6´ ¤ÕÁãñŒŒŒú÷ïß­[7ü»:Eù|¾›››»»»P(㊢ _¿~"‘($$¬éFFFƒ 233ãñxøLk¬™Ä/MÌܵkWWWWˆçáóùNNN®®®€Ïçã%$æ!U§C‡C† quuÅ/ ò_Ô‘Î¥äÕÇ]Aë>Ÿ?pà@’'™œƒ×—ÅÛ´²²âóùÔU D0y•˜™^)>Ÿïìì ÊŒû„)öêÄv!z‰6´ ¤•BûÐEQÚÙAãÇã!‹&#ºC­­?Yã~.‹¸$’Ò¹[Ó;\ЧwãÒøÿiŒöå KbUUiÕ Óë^ q/†vô~®¦NcO×Wݵ@/m§©qiÛðx<ø° @ @Ú0-uKçèèˆa˜¦ î!ióìܹ³¤¤D©TJ¥Ò¸¸8.û,k¤Ì§Çs!Ñ3»víjhhؽ{·«««——WJJJAAA÷îÝÙ'*”ùôx.@ ÿ›?–,YòÅ_ 6¬   ºº$N›6míڵÆ «®®ÆwøôóóóóóëÑ£GCCüyó’““ñ5"‘èôéÓ—.]Ú¸qcYYÙ‹/îܹ³råÊ÷ßÿæÍ›:tJ¥%%%‚Œ9rÑ¢E÷ïß_µjØxÅÜÜl°’““³zõêE‹YXX¤§§c&‰Ôž›••µlÙ2SSÓÜÜ\C{@ mõq;@éÓO?%~”}çΠNÇ$[HTæëÓ§\.ñâELLÌýû÷•Jåwß}Çãñ¸œ T ÁhoÅi“è®Gˆ›š7oQÄðûï¿§§§ƒ‰P­2Ø€ ¿Dxxxee¥¥¥%—s‰š@ ‘Ô#äU‰×Õ ÿôÓOÝÝÝ333¹œ ¤… áA//¯?þøcöìÙÉÉÉÑÑÑD=Â:¤§§ÇÆÆªUÈ";w&&š™™566jT&Ü~~~>Õ @ z„çìì±±±–––666÷îÝ+((ºíjÏEdýúõ“&M‚ßB Dô¢GˆÃãñŽ9"‘Här¹B¡HII=z4¾€E­2Ÿ»»»R©Œ­¬¬”J¥b±ø“O>U?¸j@ Ú »!ÉZ§N<<<>øà\ô·É®ÌVnÞ¼¹S§Nýúõ …Ä/1ÔªúÁU£ÑÝõÕžÈr!NÔ=×ZÕ@ îèSPí‰ì‡0 S©TEEE`õ©Öª~‚Ò#äóùðñ&@ †ö3ø’]EiQ³±±±©¯¯[WoèÑ'`a0ôð¿cI(Œ=ÚÖÖö¯¿þRkvgGþ" …]»v­©©!¾té’¹¹yJJŠŽ“Ó’%K‚‚‚.\¸ ©}@-B¡ðüùó®®®ÑÑÑZ\K—r¬ŽšBëv¥I¦£¸©mÛ¶Éår°—ºËI Ýw›ÖoZ؉‹‹S(Z·¾±±qdd¤]MMÍíÛ·1 cê¶:vgLMMMMM´¶`aañþûïS·aJ×È2ŸÏ—ËåZ[øWcggwùòåúúz…BQZZºgÏüáäŸþéïïÏýYå­[·"""¨L¿ýöÛªª*¦•5,”••ýøãxXºÿþ´´4kkkArrrêêêêêêjkk #"" À¾Gm9_¼xlJ$’œœœcÇŽYXX€Cš:Ù`}‚¨Sšd?Š›š9sfeeåG}Dò§»»»D"Y´hQMMÍš5kx<Þ UUUÏŸ?'†%KèîÝ»W[[[GaèС àФ£ÿýï‰vÔÆÃ¥K—RSSñ°OLLÌÈÈÀÿMHHˆ‰‰ñðð U»}*­!Þ´è›[È!´¾‹é¾úê+|$!…(m:—ˆb¡_¿~ñññ2™ìÉ“'\”VI :ôáÇR©T.—§¤¤xxx Léccã¼¼<ð!ÙâÅ‹‰áúàÁf½zõºwï^cccCCø­À½T:ºåÝáêÕ«¹¹¹ãÇ733[³fMcc#X·‰hþÆîþýû·oߦN„ß}÷]uuµayyùÁƒ[ºaú÷ï_WW‡³(‹OŸ>=lØ0¹s禥¥eeeuìØQ—r›Ã‡_³fMUUÕ©S§€£ZçkQ’OØ•&ÙM¡(úÇÄÆÆ’‚dèСJ¥Ò××W©Tnܸ‘Çãá­0jÔ¨ÀÀ@©TºuëV’£XBàêêêáááááqöìÙ¢¢¢>úü+‰@KKË!C†xüÍîÝ»årùܹs‰#‘Úxؽ{·L&£½½}SSSss³››X]WWüÑG‘*ÈÝ>•ÖoZôMŽ­Ïä+âªr„¢8Lé\"Š…ÄÄÄ´´´ôìÙ3##ãÎ;´‹$&Ož°À”X¶lY~~¾P(D$00°¼¼|É’%¾¾¾¾¾¾3f̺wïÞãÇ{÷îíáá‘••uþüyî 8¸»…¥jïb±ø§Ÿ~Žãñx—.]úóÏ?Á¿›6m{µ…ÂÀÀ@WW×õë×;vlÙ²e<oܸq?ýôSPP••0Ešýüü~þùgÿ½{÷'ÂiÓ¦ïÙ³§ÿþ¸[gΜyèСŒ3O¤íl 0={ö\µjÕÏ?ÿŒË3Ñ_¸pá—_~ 2xxxlذüÝ£G   Eùå—gÏžáÅ‹ÅÁÁÁ|> ÜS§NU(^^^ TÓ¦Mûé§ŸŽ92aÂj9ýüüðË!²dÉ’+Vðx¼¢¢"Ü&Ç;uêÔË—/iÌT/ooïcÇŽ}ýõ×Ý»w 4¤OD"ØÇ|Š¢è|PUUuøðaÇ~A’{gÍš%—ˉ[ñ!òÑGI$’ž={‚}P%¶ÇKLL¼qã©{³„.ýðµø2•Ô“ñ<Ý»w/)) ¥^…%ñôô7Š¢Ë—/oll|óæÍ¶mÛx<ÞôéÓ•Jåüùó‡Nª Gû­3ÞJß$ÅØÔ©S;uê„ ˆ™™ÙŽ;¦OŸŽ¢(—Ögòi"$ÅS:{DMŸ>ôˆ˜bllœ““³lÙ2pú¡C‡Äb1í/û„„„ÈÈHêgc‰¼¾••• ÏÙ³gÓÒÒâããÁh²gÏžÆÆF ‹Þ½{“*ÈÅ~«7äŸ}“c}ûö­ªª:pà€D"S—Ö§€4’â ‡))¢ÌÌÌzôèqôèѰ°0[[[ j òÏ;éÈÈÈäädÚ`{ðàÓD&ð÷… €>K:‚ ={ölhh‚ÚGùÏ;'‘H½½=UéÏ燅…­_¿$&''GEEw3M„ …7~òäÉ’’&ãcÇŽU*•S§NEQ4??¿¸¸ø›o¾wà »±±±T*ݱcq" éÖ­›Ýˆ#âãã_¿~mnnngg÷æÍ›Ÿ~ú Ø?qâDii©¥¥%±œ …bíÚµ<oÉ’%ÍÍÍžžž(ŠÅÆÆîرcçÎgΜ©ªªZ¼x1i²gª—©©iiiiXXX»víø|~HHíDØr>aWšd?Ju/‚ ©©©×¯_'Ý”J IDATº ÄV(((xðàARRØÒ:E±„. µáòåË›ššfÏžMû“™6ˆyîÞ½ žhåææ=zt÷îÝàw}DDDJJ þs›XAµö[s¼íÐÆ˜@  ”H$S¦L‘H$ß|ó ÞÜj[ŸÉWĉ6®aJG˜#ê³Ï>«­­-))1/_¾|Þ¼y¤¢µ9sæH¥RüÇ:`„ [¶l xùòezzúÖ­[¨oCûõë•’’R^^>yòdü(Sú?ü˜˜ˆ;?..N&“eddäçç755çÆóçÏ'v@ð/ñE#µ‚¤'óìcÕÚ4Aâããìíí=mÚ´#GެX±â³Ï>ËÍÍ¥®¶*,,J/_¾422JOOW*•iii‚899%$$à9‡ B/ÄÅ›FŒAU:DÄÇÇgРAÞÞÞ&&&ÀÌÌLmÑqÙÂÜÜ\0*Ñ/**5j”J¥277?uêÔ¸qã¶oßîæævùòe úté" +++‰Æ?ÿüs___ Ãêêê233}||ªªª&L˜`jjúÛo¿J9sÆÇÇgðàÁþù'~bRRÒÓ§O§L™räÈ‘iÓ¦eggß½{ÔÝÁÁÁÓÓüQUUõúõkŽõ8p ……Å…  †a/_¾|+>ÑZSÕÕÕà¡þÙŒJ¥Â_¼xqóæM Ã,--,XpáÂ…1cÆ477㸇.;~øaPPÐÙ³g¯^½J{.m<3}ÀÂEÚ ²Ûoýñ 1 ÃvíÚ5yòä3gÎäååâ §¶õÙ}` QöÐ¥¨óçÏ—••]»vM(~úé§*•ª´´””,¸ºº:tèÂ… áááÄP>|8ø©aiiÙÜܼ|ùrAoÞ<Ü †ñÉ›7oBCC½½½ýýýÒdXXXÇŽ;†aûQZ÷ÚØØ¼|ùð>}ú„„„àŠ•$„B¡Ý AƒöïßߨØçêê Nyòä Sè²›%fèÝ»÷¶mÛ.^¼øôéÓ®]»‚ËY[[»¹¹±[ ]E*•>{öÌÎÎ.&&´xLLŒ­­í‹/À˹LöÛJ¼1ÅØÁƒ ½¼¼²³³‰úh[Ÿê+b"S·eïδ…aXaa¡X,~õêU~~>ÈIM9zôèСCW¯^­P(€‘öíÛ«u&ŽX,öððرc‡•••µµõ¼yórss_¿~]RRB›ncc3nܸ°°0âÏ#ggç5kÖØØØØÚÚúøø¤§§—••¥§§§¥¥ùùùuîÜÙÑÑÑÛÛ;66–´©µ:\ܽvï}ôÑÝ»w›šš$‰T*½víþø…ô^_¯uöìÙ¬¬,ðºÛÍÍM©T.]º”ÇãWñB…B!‘HBCCÁb„NéÏç_¹rE©TÊåòèèè«W¯fggSË”––‚îD*L@@€B¡`2òÄÇÇ?|øØ=z´R©\²d Þ3Oœ8¯©C(«øˆŒ=úùóçR©T&“={ölذa´«[çΫT*ñÏ!­âûòË/ X÷Åädb½f̘QTTœyûöm•JÒ æÞ?•&“’’ª««­¯€L^`R\á0¥3EË¥‰Ô×׃û!QAOQ:äóùNNN®®®€h„©Ä¿yÿ”'¤g)0`àÀõõõ Ó’ŒÓúª_¿~}ûö%ª-’NÙ´i“D"!.¾"ee¦^Ž¥^ÀÍÍM$}ûí·øG™ó BPš´³³ãóù'N|üø1þ%(ËQ’©sçÎÅÅÅâ>}ú”v1§àŸàK̉§0….Õ,Ñ!Ä z-¢¦x ]…t p"ÓÀÁÅ>ÒvâcÄ+£‹cëÓúŠ4sSCÀ”ÎQ¡Æ‰¦Ë&—>øàƒ?üx:múµkרŸo‚œ=zôprr¢Zpvvš²ºÔKÓÓßAZ¢þL6ÁãPö].ª‘)EüñÇÔÔT.«UÙí[XXL›6íõë×gΜÑ㯧I“&mܸqêÔ©ŸþyAAAtt´¦ÆõåRߣ6"õ(ÑÔäÉ“ËËËÁÇ6‚ìß¿Ÿ´ ]-´§þUkV÷ óèåܶojcL»Ödz‰°¾¾þìÙ³ º˜BT£îl`˜¼DJç3oÄbA_…„üK_Ñíß¿Ÿû£ZæÌ™SSS“`oo¯¯²!òÉ'ŸdddÔÖÖ–••EDDhôèCkô墩§OŸÀò˜ÙM©=EmÝ3pÌÓçi[ñöäÉ-ZŸ˜m̘1cÇŽíÓ§þ‚6DõºÈ¿ >ŸÞiéx ¤÷'éàËðÏ.ôâ¢)86é‘¶oº·>ú7x Sˆê1t!w¦î¡Q·Ñ‹ˆ.Àv„€!ÑŽÿÿ!ɤ³elllggGýn† Tµh•3™Tµô•Î$ŠÆQ,M 4ƒ æé.–¦5¶¶¶uuu\r2²õ·£.è®6‡´V¥YÝ£NS ïFH°Ã½C1…–¦C÷¿­}ûöUUUeµ@ÃÌßߟªß^esWÕ yõêU]]]AAqÍ“ª–¾ÒL¢hLé$4’@S+˜Ç“ü€èR]ÄÒt$?~|ff¦L&«©©9yò$®pĽ­¼ÕвCÛ/XúÕoLý…=<ØÑ‹ mƒjT5¦ÐNxÏ`!ÁEÆ’;gΜ©­­ÅëνC± ¹Ô¡›caþ½ò„L:[ëÖ­«©©ùòË/;vì8räHðÝkçÎ=>|X,ƒCÜUµfÏž½fÍš˜˜˜¢¢"bÇfRÕÒW:eEcJ'¢©šZÁ}xœø‚_=lذ7oÞÌ;—Çãi¤ª…¢(Ç !vl&U-}¥kM+ŠÆ’Ž£…»`;´òcT—rKÓ]Œ žz£(zêÔ)|3Ž…lýíˆ;ŸEÔ –~AÛ¨~Cú ¢.<-§BÇu«ÆbAká=ƒum¼`L2–ìÞ´oß>33óÁƒ*• L„Ü;Kh1 ÝD ø ---11œƒ?%ÿþûï¯_¿~éÒ%•JUVV6yòd|3bâ.£={ö2dÈ–-[ð­ñ=»qÀíW¯^CFFF½zõrvvÖKzFF~ňˆ‰D2}úôøøxb1˜ÒqFŒ‘@Ýs’)½°°pôèÑÝ»wÏÉÉQ©TsçÎE„ûN}VVV•••Ë–-³´´Œ‹‹‹%º w)S#â™ÍÌÌ,--'Nœhjjš “ɨÛówuéÒÅÞÞþúõëß…XZZ¢(úâÅ ¿¤¤¤sçÎxïâRHMÛÝðíH²@ ]Xúm?¢ú aè/kx úktðu<5%ê8VÅmÕ˜Bå­tmÜÈ¡C‡¤RéæÍ›iû5“÷Û¶m‰D‡}úôâÅ‹Á!Úv§²M´£ZXaV¡£íGû ÂøóI¨Ð1E÷ªÑZÐNx`°`‘±Të½yóæMœ8188xݺuà-ÀÌ™3MLL¢££5êPÔÐbº(OHÇÿ&BªÎVeeeyy¹““ø·cÇŽ‚àÊX®®®FFFÏž=Ãc‹Im‹VU‹ÐNTU-dº§“º“(‹Xš¦hó~ùåüoÒ« Zù1 Ãh]Ê"–†è&HÆ^H‰D²mÛ6ùìÙ³@<AŽ…Ô´Ý ßŽ\`òK¿@èúÂà7Z˜ÂÏ`:¦¨ã^5Z Z ï!† vKµÞ³··òä x5(‰P?~ü›7obbb8v(¦ÐÊËËcºPž†£GVUUMš4ÉÞÞž¨³uôèѲ²²1cƘ˜˜üù矯_¿Æ,øøø477»ººâ·íååå‘‘‘ÖÖÖÖÖÖñññ/^¼»ÕÔÔL›6úhþøñãÄUp(Š>yò$>>ÞÆÆÆÑÑ1==,°ÔW:éꥥ¥¤uɤtZ±´ììì“'ORÏ¢M711)((HLLìÛ·/Š¢#GŽ,..ç¾Îêþýû÷ïßïÒ¥‹­­í£GRRR˜\ÊÔˆ$h_ˆÅânݺA²+W®ÔÖÖâÛ9ªÅÝÝÝÒÒA… Ö××ÿý÷<{![;â´œ¸ÀÔ/ÀQj?âÞ_†ð –AÇFðàÓºA–¨ãX5& ´Uk=!Ñ«W¯ÊÊʰ°0»¿¡~€Èâ=Çÿ›… ‚•¢ ÇÅZ,C7‘– Œ6 “Ζ……Åõë×›ššòòòˆ²&Ë—/onnvtt$Ú᮪ vl&U-}¥ãEјÒiÅÒ4•@cÑzä­ü­K9Š¥Ñ¢£NÛñãÇkjjêëë?ndd„ ˆF…lýíˆ×TÓ‰aV¡Cèú‘Fý…IŽ zQ¡c‰:ŽUc² µðžaBbãÆ´2–ÔÓY¼‡3þ|¥R‰ϽC1…ËЭ–¯Ÿ™œœÌçó9Æ-„ “ÚS:€$£…0‹cZB—®•ˆ“!/¹s禥¥eee=¸Àä:ö&à"Y—’’’––Ö·oßÁƒçääDGGsjuÑ)d)“Ôœáã`°8Ù½{·L&#½½}SSSss³››Š¢"‘¨®®×]"¢úFëaí˜ÚHSsA/BwLf ¦Š´žÁJ_Á&B.q ¡eP;cJGèd´¸ëêK—®U‰“E¼P:uªB¡ðòòâò£Œ]²Ž© n’u ;wî .,,¤Úi B–"ÑJÍ>~ˆE5Lœxzz*•J___E—/_ÞØØøæÍ›mÛ¶ñx¼éÓ§+•ÊùóçS/Ä¢úFëaî‚vL4õ0©T-*tG[`¦àaªHë¬ôœøDÈr „ ¬vÆ”ŽÐÉhq×#Ô—.]ëÑ«#y AúúzEiŸ'Sa—¬cjŽ’u @D ¸ººó´œN!K‘h¥æ ?†°¤»»{hhèÈ‘#_¾|YSSa 2D.—ߺu‹zÕ7Zs´c² ©‡qO@莶ÀLÁÃT‘Ö3XµPpª[ ·É@d´Môõ¢K×ÚÄÉ„B¡J¥rppصkWqq1÷(d—¬£…£dÝŠ+Ž?ž™™Éãñš››½½½ £SÈ“Šžã‡X$ÃÄ †aàYèàÁƒ£¢¢ª««—-[†¢hß¾}³²²ˆ;#k­ú¦‘ y˜Xæ·%tÇ>>UUUÄ ZKÖÑÂQ²ÎËËËÄÄäÊ•+(ŠÎž={Ò¤IÄA°åt Y`QÑ{‹ñc˜8+úÜÝÝ»uëvãÆ ±X¼eË–É“'÷éÓ'::šX ­Uß´PˆdBS¿]¡;–D[‘V8X1¡Ep²‚PÑx"d‘ÑÂ0Œ»¡îºt­Mœ,$$Äßß(Á¼àh'YG GɺaÆ­\¹rùòå¡¡¡†½zõê믿þí·ß @¬Åt Y`QÑ3düR 'ñññk×®]ºtiEEÅÍ›7•Je^^ÞÌ™3»víJîµV}Ã4Tˆd‚»‡‰—~‹BwL=ˆI1±5 V-œð‰¨Fh<2Éh•••íÚµ‹»¡îºt­M¯lEÏÒiµ“¬£…£d££#ŸÏÏÌ̳rNNŽ‘‘‘­­-xÏò´œN!´Rs}úôÙ½{·!ãç­ÄIttt}}ýøñã“““A£$$$Œ7N¥REEE‹¤‹ê›F ‘Lp÷0±ØoE莽Q+¢©xjË V-œ,‡ lPE^hÓ™d´4Ò#Ô‹.S:©ü†Ñ«+â´ûˆ•]²ŽÚÜ%ë%ÉåË—-,,¬¬¬nݺURRB|c„Cû.AGBÚ"! Rs†R9 ¦k˜˜˜¨R©V¯^ Ž.X°@©Tþõ×_LËqÕª¾Q=Ì]!’É‚F¦IÇpÒ´ÊìÊ|ÔŠ´žÁJ_Á‰üsÕ(Ë)5pœ‰d´¸ëêK—®•ˆ“!ºM„L®Ã’š€»dŠ¢ÞÞÞyyyR©T*•æääÌœ9“û4¦£N!m‘f=ÃÇŽ!u 9"•J»ví þíСCuuõéÓ§™Æ}ð£S#s´c² ©‡¹ G¡;j™zSEZÏ`¥—àDþ92Q“Ö‹úO-”³¡€ÈŒ¶YÝA@ Ë/Z×áš@;É:ªevHm¤2w=ÃÇŽ!u ©è eGk» K‘4ò0ôNLfêAìi ƒ•^‚ùçDÈt Äp (JlKþÛÓ#lsâd$×1¡K[ÛoC¦">~Ú\œp„TT-<ÉÑrëAÓ8o=ƒ•ŽÁ™““#“É=zÄçó™NüKâd.À8´Z8çˆ#ÆŽ;pà@E™NüKâd.À8´Z8'ú7,§@ ÐÓ‚Û“_ºtÉÜÜìcBü[mfÒ!SSSSSÓ†††–+ªÞY²dIPPÐ… ˆÕQëîÛÙÙá_5áXXXðù|Ú¯t!BK ÞA>üÃ?¤þ­63P‹Å………D%°·Â!CÀŽþ\2;;;1‚”ÙÈȈö>Z˜DûÙ·o_aaavvvMM¿¿?x TÍ JKK5Šƒ@ 3-¸¾–¸"Kíj.Ú ÁÁÁÆÆÆÃ‡—J¥¿ÿþûÞ½{===¹ï¯¡_vîÜùþûï“vÚd‚¶:^^^ØßÛØ«¥[·n2™, 䯪ª¬[·ÎÏÏ﫯¾:w›[ee%¸¿½¦¦æèÑ£*•ŠšýªÓ¦M›2eJuuõÅ‹SSSióYí_<@¾ FIDATÛ·/--M¥Rݹs‡VäŒdjÊ”)ƒ :|øpuuµ™™ÙªU«RSSÚ íEgÏž=nܸúúúsçÎ=}ú´C‡ëׯ¿qãÆ£G0 9räÈ‘#¿ù曕+WÚÛÛ·k×.00ð矋ŴÖüüüú÷ïÿüùsÚ—ÕëׯÏÈȸyó¦@ غuëï¿ÿ>nܸ޽{ÿõ×_ÁÁÁ¤ ÒÚÚZ,‡††â“¸Ä²eË®]»vâÄ …BqïÞ=Þ³gO¥K—>þðÐÐЭ[·}ZíÒ¥K&LèÑ£GJJJHHȘ1c€˜upp0¾Û’%K P]]ýë¯¿æææÂ !È»H$’Éd/^¼ˆ‰‰¹ÿ¾R©üî»ïÀ8¾wïÞšššk×®ÅÅÅ555¨@þ¬¬¬ììì}ûöñx<Úl‚”——hÅ7=>LMM‰‰¹yófSSÓñãÇIu¿xñâíÛ·W®\4fÌàR‘H$•J7lØàéé¹bÅ e‡ ȬY³”J%¾E ص Èý[9+++***))I©Tž;w.'''22²¢¢"11ÿ·¢¢ââÅ‹éééåååo÷Y4‘H¤P(‚ƒƒ…B!ŸÏ¯¬¬†……­_¿¤'''GEEñù|ÿôéÓíÚµc7m6„a"´··óæÍþýûAþ”””ßÿÏçÓN„8sæÌ‘J¥¤Ï™iM ‚ÀÀ@‰D2eʉDòÍ7ßðù|ÚœNNNÕÕÕûöí‰ —/_îÖ­›B¡À÷ܾ}{SSØ5&:::!!¡]»v´ÖºuëîAâ¹sç$ i"Äë|ˆg>yòdII )s\\œL&ËÈÈÈÏÏojjÚ¸q#ÇëÞ½»R©LOOOKKKMMmjj¿ZÀ^wø[IÒÖwx+>|\lé4`À@ðÅ_(•ÊáÇ566 …ÂŽ;&&&‚‹ê/Ö ¤5ò¿Á7??(ž„‡‡úé§îîî7nÜðññ4h···‰‰‰@ î‘‘‘‘+-°d£2bÄSSS{{û£G"òÞ{ï9;;³‘I ŒÖ†a»víš}z„ IIIõõõæææeeeøix~¡PÆ”Š¹¹9Š¢<¯C‡‚¤§§‹Åb–9ƒIKŒÅ”J¥Šuww/ØhsvìØAÒÒRpõ¿þú A|+dM«`mm¢(—ùŠJ¥¢ÞxÑŠöUVVªTªŒŒ 0Ÿ?~ÕªUîîîT3„NÕ ÌÖ ¨ [»víPõòòZ·nÝìÙ³·mÛöðáÃ%K–¼zõ ¾&„@ ï6äU£=zô@¤¸¸ØÓÓsÖ¬YK—. Ã0,""‚zׂ Çl8yyy†ýöÛo‘‘‘`„e_HIUSkª_¿~~~~111¾¾¾ááá?¦Í9uêT ÃÜÜÜÀôéååell|õêU¥Rill¬i>þøc Ã\\\ØçuîЊöUVV–——;99<`.¯®®.**B8¨š±ãää4~üø½{÷nÙ²ÅÍÍ-22rûöí_|ñ\z @Þmþw#2uêTsss›õë×—””$$$`†¢(ø˜ÝßßøðáL¯‹8fܾ};''gݺuVVVB¡pÑ¢E^^^L+2Ž=:tèÐÕ«W+ \ L­©ƒzyyegg:tˆÇãÑæ¼uëV^^Þ† ,,,\\\80jÔ(™LöêÕ«ñãÇwìØ±OŸ>D™˜††sss+++ZkwïÞ-//°³³sqqñòòÒñíš³³óš5kllllmm}||ÒÓÓÁ­öü1wîÜQ£F™˜˜¬^½º¸¸811¼5ôóóëܹ³£££··wll,Ë!-ÆÆÆû÷ï_¿~=†aR©Ã0¹\o!È»XFY)•JÅbñ'Ÿ|>ƒ»råŠR©”ËåÑÑÑW¯^ÍÎÎÆËlÚ´ ôLÙæU£ãÇÏÊÊ’J¥ b±xåÊ•<v± “žjjË–-r¹ÈßxzzJ¥Ò;vðx<Ú‹Nž<977W*•655ݺuËÚÚAùóçWTTÈd²ŠŠŠ'NÈd2°ŒeÑ¢E 2™¬wïÞžžžTk ,(--U(‰$44Tíb܇ …‚”™I´ÏÂÂâúõëMMM yyy¸Ð»ªéŠgÏžÍÊÊÍäææ¦T*—.]Êçó7mÚTQQQ[[ Œ888è/Ð ¤µ†ÈÍ›7wêÔ©_¿~B¡@ù|¾“““««+Ã?] iïqÉFüèo¹¹¹¹»» …B. ÓócRášBeèß‚a¸YÚ‹‚Ä%0ܦ‘‘Ñ AƒÌÌ̈²g(ŠvíÚÕÕÕ¨ÐZ´²²âóùT10&‡Ð*>¢ ¢}ÀáÎÎÎÀáÄ- ØU͈W$6ÑK<ÏÈȨÿþD‡@ È;ñ^:zrÔ÷ÒBîN‹St7E›“ö\.²aÜ­i SÕXÒõrQÝ@ H[A R©ŠŠŠjkkÂZPޝˆ´x“¤Ç—OÜMÑæäžHJ×èDíàR ½_¾„@ ÿ:ô(] @ @ 6ƒ® "ô¨±@ ˆáÑõ‰¨F{¼kÀ÷‹iÓð…BáöíÛß¼y³páÂÅ‹ÛÚÚ>}útìØ±6l} Ó‹¥ÙH]Èü ðtÝ¢(''§aÆ…††ŠD"-÷ÊÌÌ455íÖ­Û•+W8Ž«(Ù'Ÿ|bnnžžž®ö·€:DQ”£££§§gFF†êv¦±UÇOC#Cm˦ˆ4 )Ú²COÓf®lIQÖ£la~ÝdZ :Bssó‘#Gº»»0àÈ‘#EEEÚ-¹\. }||^½zEÓ´™™™±±±BˆeÙ‚‚‚œœ–e»té" e2™>— &YZZzzz–oÌ0Æ ­z1´P4ƒhúŸô]>Ç["“ä¼x¬6R<>ßšߨ ¿‰MqFRaòëwATãK1rtç™6yûæ8®¸0÷Ñ cçÖ”ºµZB†a|||>ÿüóaÆ™˜˜(CÆøáÇr¹üÅ‹z2ŒŒ4GÁ¬¬¬K—.?~üÆEEEÆÆÆÚd @·k׎¢¨˜˜ S c>ÓÌܘF(:=çfb&Â5ÒžiÜókËþõ.~Q|ÇYëR¶ýRœ‘¬:Œ˜ÿ:²a‹öÅ „E™´hŸÿ «hÔªk”eY¡PXXX˜˜˜¨œCQTƒ ²³³óóó+}ƒ(Š*))‹Åü÷ x<_š}:$72ܼSß„U“Ùâ„1抳Nnw[º‡ih¦È-{EÚBŒ±L&{ôèÑóçÏ{õêõùçŸK$’¢"uS}*ئé¾}ûz{{“‰¦cŠ¢x<ÞW_}Õ©S§¼¼¬Œ©ªb• ÿ½ßWuÇ2[þÙøA?ÃÀ–žsÇBlðŸ§w d1GWoV€Ú§‹Póå-b„$yŕʭi£‚¢Òti~9ªBß@ˆ9Ì•ü#R-íÍW~ÿ©‚eW¹÷4QŒ±ÚÁ?„ÙÍÕÿ3¯¼bÅŒà+âÜbuC†HåO šéÙ½ÉqæX̱˜ãð?ÿ&²– QqAÞŸ§ð2äQï¨&c1Ç:Y™ ëÞ"{ù2Â,[.Í¿ÒWïeDUºFÕ¿dnlÐÎÉ¢XÁ1¶¶†ÑO6íž!}Ks«v¨6w°Ê?|ШOŸLInk‡&7ž¿¹¡jYU&˨éí42`–ïØ$-ñí–#céþýF>>¶††ˆ¢E!ÒCJQE!Š*|û¶$6¶Á'Ÿ0±±ÓüüL ˜s“0æÔ­¸j„žã8Ľû·2òhzñÐöÙi¢¦â‚„¸èÕ+ÄVбÉ0H¡Èð!”çΘ …O?HÀ˜SŸ¨nz޾ä0Ç!òÌÍý²[9uŠ"/å8–ãXŒmi8z4‹ñ»-ïÿkèçg{ìKÓäϼ[·2¦ý0²«ë'„±êñߨŒ~»¹ûôÏ/%~!Œ1žÒ¿ukcѸ±¬Xün+B¡â¸¸Â'O¸ü|Õ¡ÒÌÌÂÈÈÒôô¶¤¥=}Úiòh†F1)„8rd"íÉe¸½ €j§ÿdÄ!D½‹MßÖ²«³@òÓ<ަ©¦MßmÅ!Tüæ Bˆ²²B§:¢È±lqRjÜX™a\'š;÷«uëøpàÀo¾ùfÅŠ›6mâ*b¤ÊdO_}õÕâÅ‹Oœ8ñÇTz¢27nìááaee¥åUØÙÙyxxܸq#77—¢(+++ÿ¡C‡Nš4éâÅ‹ @U]GhlÈ›2¨ƒ·­9E!›õë3~ú© <\ïv¡ñ'ŸX­]Ëûvru¶i´îxDQ‰‚ŒBV )ŠÚ±cÇùóçIA›6mÌÍÍSRRt=2Bß@ˆßµù}ª÷%}Çß7Ô8Že eÛŽå8ŽUœºûòâ“„&kÖ2nnœÆ>RÆÉIð.?O=~û«(eÉðB,BE)Ï¢e‹ðúõëÇ?vìØÑ£GE"QïÞ½¿ûî;íÛaÅÅïžžˆ1ŽŽŽF¹¹¹µnÝÚÂÂ"..NõÕ˜˜„PÛ¶mË÷v¶jÕJ§ôz\…¿¿¿¥¥e“&M\\\&MšdaaܧOŸÚ_þª.ŸàXŽ}ßZÁq,‹9Žãðñ;/Â}Öþ!š7·$1½oª¶† -ÿXwíEê±Û¯I»Šcß…UŒGÓ‹uj;vL9ßÒÝÝýÊ•+3gÎܼy³݆‰!dmmݰaC„P~~¾ê«oß¾E5hРüŽº¦×ã*X–U(dááÇ‹ŠŠvïÞ=nܸëׯÃÄQÐU&Ë`cŽã8î}‹¥(îŸíì±Û±aÏSkþà99qʶ#Ó¬™`íÚ°×iGÂ_²¬By4V9Ò"|4-gâwâ8Ž{ýúutt´¥¥¥››EQ …‚Çãñù|-/ÐÒÒ!$‰’““9޳±±Q}ÕÖÖ–¢(‘HT>Hëš^§«P›øáÇ!èýèßõX¦dˆy­[“y1Œ]ŠHúþ»,Ç*ŽÜйñêåÊÕŒ££êìÆÎÎjõš›qGo½`¥˜cÉ^É™bƒV­Þ¥iÚ4U$ÑûÁ¼cÒ,333C‰D"†aÚµkG‰………¥¥e™É2Ý»wWnéÞ½;˲‘‘‘±±±­ZµRvlš˜˜ôîÝ»°°ðúõëdh!¤ìºÌÌÌÔœ¾*W¡¹MzzºNG@èÿ&ÒH»ñTè3ÜQ.-52äèÅÇïBÈÔØ°¸D‘‹h«U«2~ú©45!Ä·µµZ³&—攲&Ùò‚w©1ºú8~ÆàÁÈØ˜6444(üÐMŽeõ¾] ¥kÒ¤ BèÚµk}úôùý÷ß÷ìÙÓ ASSSÕÄ%%%ÁÁÁÛ¶mËÉÉùòË/===ÿþûïØØXŒñæÍ›ƒ‚‚víÚ”——ççççàà°mÛ62“3!!cܵk×1cÆÜ¸q#))Isúª\ѯ_?OOO„ÇsqqùòË/‹ŠŠBBB`â(èAß1BüîÁ¼I™Ò 'ïumåedÀ;v;î˜{¸0MQ ý>åÇD¸GŒ°^¹2# qœÍªUˆ¦KBwumåÙ~È'Ëö\U»—I™ýÍ}Ò²BÔµ}aI™Rr7ný2ùüùó¯¾úꫯ¾º|ùrPP‡‡‡¿¿```IIÉÁƒ%I=”‰###ïÞ½;þ|„ÐÇ,X P(B‡633[°`Áš5kB;vì '""âôéÓƒ œ1cFrr²æôU¹ ²E9k”ã8‰DòðáÃ7Þ¼yn±zÐsža—a?Ê‹ÿ9EQ#üï[«y9ÛŒke•¾ð'IJ..6«×pyoBL#ó7?Le³²Ã8üõ׎‰Ñ ™øý“)( QHåhïSÿòÜ #…4MÓ4­\À º‘ ¶‘?›4iÒªU«äääääd²Ž„:†aBckkkOOO‘HôòåKò’òPíÛ·744ŒŠŠ’J¥ªQa˜Ö­[=xð@y. é5äPóU«¤ät™R@•Þ³FYÕ'Ô«­ƒm›4,e²‡0.LH@ûäMËq>ž KÉ}RŠ‚øx»&æÑÂtåÝDÕ­²J^K4lä8.;;[mËI9Ù2###33½0ªûÝ»w¯üKd÷¨¨(Õ—4§×CÍW¡6€ª¨ê¡æ4õ¾ÚƘ師O8ÌuháÀ½mËr´n«æ«¨ÒiH ëKÐJ€Ÿþë9+çXbŒ)Š"õþ?9–¥þ™îÉqÇ*8„É’y"XŽÃˆÅXM $ÇDNÔ¤*tþ{HPùoå? ‹Š‘¹!¹_bãâÒ–å8Œ0ŸÏ)!Ì0……%˜SSyŒý?LJP fTõéþ‹|Êx´`ììX„Lû÷OÍ–Kdy9¹ù ±Iß¾,MóœùîîÑñoÈýhÞý‡ÕM»õ€®ª8F¨Ò|û§Õön‹ìmÁÕǯz-[Î/,R¼ ·¢8–Åÿ;Ôwã_”òøWŸ'Šåùø_M?êßÿPn‡V!€ê§çò‰¶ýGçW™(Š24`ì“3$Š÷¬ (DÓ´£EfNnaQ©–C€ 7À`!€j§ÿ¡6Q cTXÄÆ§Šð¿7r—ð& €:W•®Qm™Út|ªò&Õ ,j»Xq¹íå·”Ù^Q FT¥k´VuЂPôl~QUÛ‘ fÊ@/Tû3Éu Îð(FÏ5õÀG€‚@´æææFQz>ó€Š@¹5„®ë €ÔV &@¹5!€z !€z !€z !€z !€z !€z !€z !€z !€z !€z !€z !€z !€zW×øàxzzΘ1ãÒ¥Kr¹|äÈ‘E•””…Â]»vÉåò^½z5Š¢¨ââb¡P*•Jë:Ë .µoß~Ò¤I4ýÏoÊ]»v•––Nœ8‘¦iŽãÒÓÓ/^¼øøñcŒ±½½ýâÅ‹cbb‚‚‚~ûí7ÕC%''¯^½šã¸ï¿ÿ¾o߾Ϟ= ’J¥Ê³p'‹/]ºt÷î]Œq­_.¨q¶¶¶S¦LiÞ¼y~~þùóçO:E>èI“&uëÖ¢¨Çoݺµ¸¸¸¢R¡Z̼½½•åS.—?~üøÈ‘#ãeË–©-~666jÏê—Ï?ÿ\*•þú믓&M’Éd±±±‘‘‘R©ôÖ­[&&&'N$Ÿ={&“Én߾ݠAƒºÎòÇÝݽþ<1gÈ!R©411ñá{üæ›oÈÆG¥§§gdd̘1ƒ¦éÖ­[K¥Ò£G2 sôèчÆÇÇçææÆÆÆ>|øpïÞ½ ÃlذA&“=þüáÇ2™ìúõë 4PžåÑ£Giii‰dÊ”)ªÑ·>¨åJ <|ø0;;ûÊ•+1112™lÞ¼y4MoÛ¶M&“EDDDDDÈd²Ã‡3 SQ©P-fªå3>>^.—oß¾¦iµÅÏÚÚZíÙëú]µîóÏ?—Éd¿ýöÛäÉ“årùäÉ“ù|þºuëd2™¯¯¯êÆÍ›7Ëåò=z|ô_N]Õ‡ KiÈ!2™lóæÍ|>Ÿa†a(Š"ƒ‚‚ø|~óæÍ£££333ÝÜܼ¼¼d2Ù±cǘ÷–/_.—˧M›Fv÷ññ‹ÅW¯^533cfýúõ2™lÁ‚C‡Už¥M›6YYYwîÜa¦®¯¾VÕ‡r5räH™L¶iÓ&>Ÿ/âãão߾ݻwœÓ§O0 sæÌ¹\Þ²eKÕ²§Z*Z·n­,fªiLLL®_¿.—Ë=<|Ø»wo??¿»wïnß¾ª¤zîÊ•+§OŸÆgff–/ !m Iii)BˆÇ{÷ÅlРEQ …‚ü™ŸŸŸ™™illìææÖ®]» .Ô“zªþÀ¯_¿~ß¾}þþþÆ [¼x±££#ù!¥«SvMåKEùömÛ¶yóæááá«V­***Òþì3gÎüèë7hVâÀ~~~ÿ÷ÿçâââëëKáëׯ?þË/¿pשS§ºÎ#¨{éééû÷ïß·oßÕ«WË'///Š¢„Ba¥q+!!!äááAþìÚµ+B(99™ìx÷îÝÑ£G“ù\ß~ûíG?`VMœ8ñèÑ£nnn6løôÓOÓÓÓ œœŒruu%i–/_Ù¹sgR´)GmÞ¼¹——×ðáÃ=zTQ9T{öúPÌ EX Ò·ž‘‘AQTãÆ BÞÞÞS¦LéÔ©ÃX IDAT0ñññuGP÷œœœ&OžLê—ëׯ“ŽŽŽS§NmÓ¦¯¯ïÓ§O/^¼Ø¢E ÍÇ9sæÌ¼yó¾ýöÛÌÌ̬¬¬™3g–––’é|è}i”ÉdR©T Ô‡ª¾)--íÓ§©©éÖ­[A“&M/\¸°`Á‚Q£F¥¦¦øûû3 óêÕ+;;;¤]©À+ŠJvjÏ^#×ù@¨•¤¤$ŽãZ¶lùôéS„Ðwß}Çq™—øÑ÷€JõêÕ«gÏžäßÓ§O/((@õèÑ£[·nb±øÔ©S¿þú«²‡S™L6}úôuëÖýüóÏE‰D¢€€€{÷î}ýõתÉD"‘››[§Nîß¿½£“ÐÐPWW×Ñ£Gïܹ!÷óÏ?geeMŸ>}åÊ•+V¬ i:55õ·ß~ËÍÍ-³¯²T(G«åìP¿ÕGEñx<š¦iš&ÿ(¿Q VبU¦¹+‘²¡Š¢(Õ Ã(Ë Ù®:›Fµ˜)Ó0 ãææÖ¶mÛò%¤a†œ¨/´îÕ“rEÓ4Ã0-Z´hÖ¬YƒÞ—ŠfÍš¹¸¸¨nT[*T‹Y™4åÏUæUµg謞TX5ŠTgu‹K½*Wu{¥õç}& k€txÖsu[ê[ñƒž=õBõBõBõBõBõBõBõBõBõBõBõB€jUßžáj”+€ê¿°@hwRH1ð´KPžqŬ¢®s>BPUA1<„€ÿ˜, ^ƒ@ ^ã5lÝ¥®ó>6yÏ#ê: àãÔ°•‚¹£ ºñš¯:R×y›§ƒ]ê: àãäþûA{ÕŽ‚RªfP®@µƒr –¬X±âêÕ«^^^”ÏIÙ²eËÕ«W†©Þ<ÿý÷ßÕ~X«ê¼•»››[§NÌÌÌ´IܲeËöíÛk2uâéé©e$öO¨ÿꫯ""".\HÓî2gΜŽ;>yòc\é)Šª‰pUC‡ð±Ò¶EبQ#¦M›jH“™™)‰´‰‚ÀB«@¸hÑ¢N:Ñ4Ý©S§Í›7ïß¿ÿîÝ» .466Þ±cǼyólmmGŽ9a„6mÚlذ!!!c`dd´qãÆ3fx{{Ëd²Ó§OŸ9sFm¤9rd÷îÝ£££·oßÎqœ»»û”)Sœóòònß¾Âq\ù½Êälwrrš:uª››[NNξ}û®_¿á€þöîÝõöí[¡PxÿþýÁƒSuëÖ­ÔÔÔððp™LÅ0ÌÁƒåry·nÝHçä­[·Þ?‘““3vìXòê7rssy<B¨S§N)))IIIíÚµ£(ª{÷îIII"‘èÆÏŸ?—ËåÇW;ÿ¥|ÂÃÃåryttô‹/"""$IVVÖ!C ¿€þ†ùþûïåry`` ŸÏ'A%<<<77wçÎvvv$J:t(77WI‚Å‹óù|†a  ‹oß¾M+¡……Åýû÷srrüüüÈäÑ£Gsss Àãñ4hpâÄ ¹\>bĈòÁ¬|È–?ÿü“œtÈ!‰DyR  ­&˰,Kz&1Æ,Ë*»9Ž›={vZZ˲jwä8î?þ(--eYöòåË)))eâÙºuëZ¶l¹uëÖÇ“³4lØcœ••ŲlQQÑŠ+~ú駸¸¸ŠNQ&Ç“ž:uêÁƒ^^^>>>Ð(Pž¶³F+RPP 9rlcœŸŸobb¢úê;w†zûöí_ýUÉöìÙS\\|úôéC‡Íš5K.—ïØ±#22²¢q¾òy(..Vž4::!äææ¦ã•¨ª«èÍ›7,Ë򯯬ÈÇûúúž;wÎÃÃcÙ²ewîÜY¹r¥Þí9‰D‚²¶¶†!€òê8úùùíÙ³ÇÕÕuíڵʊã'OžLŸ>½C‡¾¾¾±±±S¦L?~¼†%ŒXZZ"„`]µ´ -¤ßR¿P¤ù°‹/ŽŽŽ1bĘ1c(Š255MHH¸|ù2EQ,ËÞ¿ïÞ½EyyyiyL2ïTÙþëÞ½;˲‘‘‘Õ›smYصk×1cÆ899Uc fÍšõöíÛ¥K—¶jÕ*//ïùóç>>>ÁÁÁC† 3fÌ?ü€ºuëÆø÷ß¿ÿ~ÇŽ5ôs–””Ï™3gìØ±Ç÷ôô¼víZll,´袨={öÈår¹\NšndõYH”_>Q&Axx¸D"![T×R5}út¹\~ýúõ ØÛÛ‡††J$™L&—Ë…BáܹsÉú‡ÐÐP¹\Þ«W/ §¸råʲeËÒÓÓIn¯^½Z½‘ÀÇD‡ù# ônÝÚÈÈèÁƒÇ1 CQ”B¡PM@ú3IÛ«¢dK™Wiš¦iš,Ï ¯š™™µnÝ:???**Šã82ûT›S „0ÆÖÖÖžžž"‘èåË—ª ýÕò-­«x:¸7€Ji' ?ûŒ÷ß(Faa &ðoZÝt›GQA ÊÓ*¼}Qšƒ*7äðÑ+ìþµŽ¢ €^™`WÇ·XêÖ¿&Ë4jÔÈÇǧ®²ÔsssÕ?ÿÕ<„®QõÜt¨mÛ¶ …"‘èÁƒÆ ««ÚÙÚÚnÚ´)::Z$eee½zõêøñã €ìðŸ5ŒÞ>Üœ}|(Šb!„1æ8®ïtGÓ4EQ¤\’lÔm~U5 jÔž={RRR$‰T*?~xð`>Ÿß¼yó‰'¾|ù2--í“O>ÑõËðã?Êåò‰'êúΛ7O.—Ož<ÙØØ¸M›6YYY÷ïß711)“’¢(Wç?”jZÛ¶mcccÃÂÂN;º»»¿xñ"&&fðàÁM›63fLbb¢jÍ[imò@QTëÖ­cbbnݺ¥k‰ùóçËåòõë×Ó4}òäÉÜÜÜÏ?ÿ\YÞžÇÓþKÍ+gíÚµr¹|„ Zà*~7#""ÂÂÂÔføÅ‹‡"/iþ,ªj]é}™ÚP~yµ)É<-:iÒ$Š¢vìØ¡Ü2uêTŽãBÛ¶m›U‹Ù…ã8…B¡ÓסLAíÔ©Ówß}wûöí={öèôvéýÝLKKóððPû’……EFF9‚6ŸEÕA óP~yµ)„ÚÆaŽãÊ|-iš&Y–Õ&žŸ>}úܹsööö¡¡¡‰‰‰¤ÙÞ³gÏ:Y\B¦ÇÆÆbŒ---•ypssÛ³gO|||vvvllìüajjªå1½¼¼D"ÑîÝ»Ëü¹sçÎË—/4h 6)))!+++e‚ƒƒ“““I‡Õ‚ ʼ·¡¡¡>;vì½{÷233“““ÿþûï2ocçÎOž<) •ÝnR©T(òxZýîÑæ/^¼ÈÎÎ&S...$Abb↠H¶ƒ‚‚rrrÈŸG޹uë–òý™6mšOPPÐË—/u­&z÷îpùòeRÊ1Æ»wï.,,üèÑ#†a5j$‹çÏŸOöjÑ¢…D"9räˆÌß|ó\.ß²eK™7çâÅ‹¹¹¹VVV•& jŸŠ¢=zW½ÃáOž<ÉÍÍUþª“Éd—.]j×®ö¥ÚÐÐðÚµkr¹üáÇ ,hÚ´©Þ™Y¶l™\.>|¸Þ4ŽŽŽqqq="Õ“ö*ýnj6bĹ\>bÄŠ¢îܹ“””tôèQ†aÆŒ#—Ë•¿ÃjÔ0º¾c]¦æ†¤ùæ›o$ɪU«ÈˆorrrÛ¶mõþ õÿ©k×(Bˆ¢¨Œ±NíÒó^ž®½@{÷î‰Dááá3fÌ:t(é:@õèÑ#))éîÝ»ä&Ç…††"„|}}µ|8™™©ÚùÖ·oßgÏž=zôHõ‡ÉúõëE"ÑÝ»wüñǹsçþøãº6‰ÎŸ?ϲ,yÉïMGGGrR333„Pii©ê ô(NÑ¿ÿâââ“'O*»ã?~Œ"3Ÿ?ngggnnÞ³gO†aΜ9ãìì,|||x<ÞãÇIƼ½½y<^™F›–ŒŒŒP¹¡)å33³J Ñ>äM°¶¶¶±±Ñ5·š¥¤¤ØØØÿ ;v¬oß¾Z~dÅÅÅC† 477_²dÉãÇ·oßîääT½™ÔÒÒ¥K---—.]ª_KKÃwS³/^`Œííí=<<Ξ=Û¡CŠ¢ìì슊ŠÈ«zäG?PÃT憤9yòä¾}ûÆ·lÙ²O?ýô÷߉‰Ñûƒ®Õ¼¼ôôôÚ]&Z/X°ÀÚÚ:88ØÈÈÈØØX/>>^¹)âÊiÐdÚá÷ßß¹sg[[Û¥K— ‚+W®èz §°³³322JKKS6eN:Å0 i<}ú”a˜Ž;vîÜ999ùæÍ›EuïÞ½uëÖ………ÊY¤í’––¦ëµ#„ 0Æå$x<Æ833³ÒzäA$!„ÜÜܪ½yA~Òeee]¸paÒ¤IÆÆÆ‹/Ö¾Q˜››»téR//¯éÓ§?{ölĈ§OŸV¶zkÍ—_~ùõ×_ŸÒüÝÔc,‰A·nÝbbbbcc?ûì3+++25¦6A Suške2++«&Mšp׬Y³*ŽYè6Ég„ Ê«å8ެ©@ï2Ô¨Š†.ªqŽ\ff¦ê(4BÈÊÊÊÌÌL§VKttôýû÷ûõëgfföé§ŸÞ¼y³¢…™™™ûöí›5kÖÌ™3W®\Yň ™|þùçqqqÊN˜ê:8B(##£yóææææ™™™å_-))INNvrrrssÛ·oÆøÕ«W-Z´hذáëׯ•õÙ×ÖÖV w".‹CCC›4iRÓßMLL"##Û¶m)•Jsrr„BáÎ;Ëß]ìüùó"‘hóæÍºžzÛ¶m·oßþá‡æÎëîîîèèøý÷ßÿý÷ß;v$ñÅ‹:uÊÏÏ¿ÿ>ÆøÑ£Gvvv666Ož¬J蔇®]»º»»ß¼ySí§9zôh‰DrïÞ½ªôϘššöíÛwëÖ­<ïÏ?ÿ,Sä*:ņ ,XУG¦M›ºººŽ?~É’%ÉÉÉ;wîÔòÚ«è+V¬`æ—_~©tö|Íå!55ÕÍͼ„1¾páEQÍš5Óã‡Kµ|šjA £¥Jk˜®]»Îœ9óÆ»wïfYö×_MKK[½zµÞsÙ þ#33søðáQQQOž< 8s挟Ÿ_ii)I0~üøøøø´´4²ló?þHMM …3fÌPý¤É€¶©©é… *-ß›6mÊÈÈ9r$:th\\\ZZÚ_ýEÓôÏ?ÿüæÍ¡PøË/¿hY˜vìØñå—_Nœ8ÑÉÉI xzz.\¸Ð××÷·ß~+s²"E¯Gqqñ¨Q£vïÞíïïçÎ{÷îÍ›7ïÍ›7Ê_ß‘‘‘¦¦¦¯_¿&—ûömÒyp÷î]å—c|âÄ 333ýn¹ûêÕ«‘#G¾zõjóæÍ¯^½ ÊËË5j”òê4Ny?~É›R‡ iš¬ŒÑ†¬n$+†)óÒ4­v9cùOzÍš5‰ÄÓÓ³ÌéHÔ’R5jOQþmT½g MNNΖ-[TKEQª·tQ=”ÚµN¡öÝ(ó^‘ôª§#ÉÊœˆ¦é›7o&%%é×Aªú^:tH.—ÿôÓOe²¡9–y0`€X,Þ¹sgEß±°°°””=†åÊÖ Ã¨ÍFE§(S&É¡ÓT¥ù ¢öªw+--Ú_E¥ßMÍG(_äT¿V:ÑûÓ„FËFËËÔPÔÿpËbÀ€µ³Š”Õ Aƒ˜˜˜ãÇ—¯úkš@ H$›6mR-4VVV)))çÎû+uéÒE(^¾|Y×GO”áààðèÑ#©TZQ?Œ†šóàîîùàÁƒŠæÔ4iÒD$­[·®æfiVýp„çU5Œ–È—÷CËÕGÎÞÞ¾K—.ŽŽŽÁÁÁÝ»w¯“_"gÏžMHHðóó³¶¶&÷Û ‹ÅU¹cHÍ¡(ª[·n¯_¿>{ö,Y¨«7— .¬Y³¦¢*¬¢òàêêúðáÃ{÷¸h8µÚŸ½Õ«ê§€#|8§ÐÔ0:Q~y!Ö*ooo¡P˜••õèÑ£o¿ý¶®¾KöööýõWLLLVVVvvöëׯO:5hРó»Þ÷ÕTKa-ßפe‚ŠòPy Š †Ñ‰N_Þ(€ÿ×)ïžJVÕÔá¤m2J¤ºZ¼nó¨:¨a€êƒ5bàÀ—.]***R.lðaú°†7µ±fÍšš{ÀØÊ•+%IHHMÓ×®]ËÉÉ!7·%¯Î™3G"‘ÅÂ"‘èÙ³g[¶lQûÈ4Š¢ •÷kÿÐh¾Ìÿ–-€ú@Ûe(¤ÒDMœ8QysQµk”““Óøñãoܸ]ÇÏÉÉáñx2™ !”››ËãñÈÃw²XuÁ‚ûöísss8pàܹsÛ·oß§OŸüü|Õã\¸pÁÉÉ©o^½4_æHM—@} m $šØ±c‡rKHHÈÔ©SIE¿mÛ6-ŸÄTE¾¾¾5wüììl„¹›»T*E•¿y1yäMtttLL YFãëë[æžXãJï»X‡´¹Lm´k×î믿 $©}5]õ¶]£ä^‘ÿÚS—'Ôïß¿?""bÒ¤IYYYIII¡¡¡ª·ê %Íå–Aƒ‰Åbåð‚‚‚bbbV­ZEÓôÁƒ•w5lܸ±rww÷Ý»w¿zõ*+++11ñîÝ»:=à!$‰0Æäf‰¤´´´¢{’Ìä¹wVVVÊ®¹àààäädr÷È ”9{hhèÇÇŽ{ïÞ½ÌÌÌäää¿ÿþ»gÏžª={;w>yò¤P(T½s£P(,s‰Í›7gffΜ9SåŽüL› IDAT;Ú_¦f­Zµš5k–~ áOŸ>}îÜ9{{ûÐÐÐÄÄDÒÕ\æ­Ð@›òàææ¶gÏžøøøìììØØØ?þøC×|kY¢V¯^‘‘¡ka| jé{Ë0LóæÍçÎèãã³råʾ}ûîØ±C¹Ú±Òû[NŸ>½mÛ¶AAAä¡”VVVäªm‘:Ìž=ÛÛÛ{úôéñññärÚ»|ù²¥¥%¹üÂ… ­­­ 5¤wvvFEEE)£È´iÓ\]]gÏžMÓ´ÚÛxº¹¹-_¾üСCݺu›„ •þœ'c~Ê?•7Í«(½e×®]ëҥˌ3ž?>|øðK—.Mš4©Ú;¬ÈÏÿ7J$’iÓ¦5lØP×#H$’Š^JMM6mš³³óùóçŸ>}:xðà5kÖlÚ´éƒjm°,«P(”m 2j¯¦/ª|ÐÒ5ŒÕN‰Ô-ݾÒeé7nœêS¿5pwwWÖDvvvèýôE„9Bƒ ”‰-,,ÊW[šF¤ójß¾}ƒ4h™·YC?á333÷íÛçèè¨ß¼M FŒ!—Ë{ôèaooß¡C‡Õ«WÈ+1ê–†ò™™Ù¤IÕ-VVVfffiii:¿ÖJ ®èVƒ—ù ¯\>¡åî}úôQV"½{÷¦(*<<œÔeéééãvíÚ)téÒ¥|CÀin„‘ÊëþýûQQQj£iuÙ´iSVVÖøñã­­­«ñ°ÎÎÎÙÙÙ¥¥¥54ÌY]¢££×¯_Oæ× åáÆŽŽŽÝºuSŠ¢ôèg®µ¨µ×Ƀ1ž1c†¿¿¿ƒƒÃ¸qãFŽyÿþý .ZéäÉ“ÅÅÅK–,iÛ¶­»»û¢E‹¾øâ‹ò5ÎÍ›7 ÇŒãââÒ¢E‹~øAÙûúë¯Ïœ93f̘fÍš‘åÝ»w¿}ûvÍ®‰ÅâÐÐÐ&Mš”Ÿª7“ÈÈȶmÛFFFJ¥Òœœ¡P¸sçNKKË2)«²Ž°º<{öìÿûŸ\.¯¹Sœ?^$UôÜy åaíÚµ ƒ rpp;vì¬Y³îÝ»GhsjíKÔ¡C‡rrrFŒ1P¡C‡¥§§Ï;÷Ñ£Gb±855õàÁƒªÓ(Šò÷÷ˆˆÈÈÈÈÈÈ zôH$edd<|øP9”èååuþüy¡P(‘H233£¢¢6nÜX½m5åò e–5jôòåËÌÌÌ–-[R5tèи¸¸´´4©Túöí[™L–žž. •·¨t•ÈÁƒ† fnnÎãñlll† –‘‘ñ矖‰[¶l‹ÅdÁb5^c­9wîÜ›7oÊ,-ïÒ¥K‰dË–-=P·¢ò€ruuݳgOBB‚X,~ùòå¦M›,,,´Ï¡ö%*:::))ÉÈÈHûƒêC‡I¥R²p^íêc²NKùj™õ%+³]õ¥jj—‹‘3’¦€jÞT)wÑ|ß›œœœ-[¶”¹®ˆˆˆ[·n•yÇþëk×Ê¿’i¸ÌŠÊCù—t}¯´,Q...Ê•$:ðÐö^£UGQTùû´©*¿’Lí$‘ŠœUûB´òÔÞD[õ¤•æ¡ü«ªw%%‹ ɺ:e@дiÓ¨¨(m2ó¢å‡Ui2 ïy‹„–»÷èÑC¡P}PK\œC‡Éd2mZõÜÙ³güüü¬­­É½ÃÂÂÄbñðáÃaü©ºtíÚ•Ü ¶"ÉÉÉÚ—UÒ4‡OP „Z²··ÿ믿bbb²²²²³³_¿~}êÔ©AƒA·[5"ÝÑšÕuµ§–~Æ’1?X§ roLÒÂP½ÑZ]ç |$þ{]³fMVVyº:PE:ÌŽ !s• ,¿¥¦999?þÆÑÑѵp:à>ŸOn´Bþ_fK-dã‡~¨è‰ä€´]6iÒ$ò0–eI+¦iåÓ'*]å¶ÿþˆˆˆI“&EDDdee%%%…††ÚÚÚ*„††æä䨮ß4hX,VÞ¥3(((&&fÕªU4M}zÛ¶mƒ‚‚8Ž=z4yBº@ J¥Ê]BBB:tè0{ölooïéÓ§ÇÇÇ 5×LÓjov  Òù¤!¨Ç™†ùóÏ?>̲ìŽ;Z¶l9nÜ8__ßóçÏk³ZœœTõ‘èeö­[·>|øðßÿͲlFFÆåË—1Æås°hÑ¢ÿú½:T Ýúõk*………)ãYXXB¨W¯^Õ5Ú—žžîëë;mÚ4SSSrÇdµ¡Žã8…BQÒ)†„„L:µ´´T¿3aŒ…B¡²—’’‚²±±©Æi/³gÏÎÎÎ^±bųgÏ‚ƒƒ½½½aN Í´í%sD·oßN"Ùĉ'L˜°}ûv2†§M3‘Œù)ã(¢ÓÐ)ªÇÞµk׺téâçç7bĈáÇ<ø×_ݱc4þTDÛ@8iÒ$ÕÖ {ÊZv–º»»GGG“àggg‡‰DäO 4h——G[XX”oÏiM$Ý¡ûöí;pà@çÎwîܹ`Á‚-¯@=¤Ã¬QVE™Z¤OŸ>ÊØÖ»woŠ¢ÂÃÃIlKOOÇ·k×N™ K—.åavv6B¨aÆÎBÂáýû÷£¢¢ÔFS ¶:tH.—'$$|÷ÝwãÆKOO¿|ù²rÉD§N²²²._¾ìíííîî¾hÑ¢´´´·oßþöÛoª«ý¼½½333Ïž=ëêêÚ¢E‹~øAùê×_}æÌ™1cþŸ½3kâêÿLqÃ* DE6A´Q¬­m-b±ê§ˆ * ˆèÛŠ-u_~EJµ@] *¡ZµŠ(jE5lʾ[$û6hµ>Bæ÷Ç}ŸùÌ›@2I `{¿ÁdæÎ¹gÎÝï=gý¸qãÆŒØÖÖvíÚ5Õ)Öôôt©Têëë ÛHˆôôt.—»cÇŽ’’±XÌápÒÒÒ¬­­‰Põóó+,,äñx</;;{Ù²eb±X©!DQ4  ¤¤D ðx¼ââb¢sqqÉÌÌd³Ù‰„ÏçWTTÄÆÆZYY© SYYÙÜÜB’1ègprr‰D>>>(ŠzzzŠÅâÉ“'“]˜þذaƒƒƒÃ¡C‡h4ššoƒ¢¨©©©©©©êuccãþ\<Èt— ‚ï¿ÿ~Ê”)ªŸØÈȨÿ×Y†¤;Eõ+vïÞ½dÉ’¨¨¨)S¦„„„Ü¿¸à7$o»EQ¬úK· –M}„$£…é0 %"ô„êõ|ôÑG‚€ò3wî\>ŸÿôéS×¥^èA£#ò›7oÚÙÙ)Š·Úe¹ú\ØÙÙmذ!''§²²Òð²½E¼-Šš1cFkkë/¿üòæÍ‡ ˆ ïÛ¢(5P¬úúÔQËfOU¤Z„a /‹ ‰Wº¢±-œ9s&‹Å’Ëå‚LŸ>½ªªêÖ RÇñŽŽŽ¾–B_ÔçÂËËkÀ€†”ç-åmQÔˆ#0 E¾OJîÛ¢¨oEÕSBR´nܸñÍ›7`¨zE ÍÍÍ2™Ì×××ÅÅE,Ëd2Å‹‹ÅâƒR;;99ýòË/OŸ> …MMM=Ú³gñ¬™™YDDÄýû÷E"QCCCrr² 9ww÷«W¯²Ùl©T*û/l6›˜T177‹‹«­­‰Dl6;%%ÅÁÁ¡g'¬Îž=ÛÒÒ”®1ï‘‘‘‰$&&†¸“¢'Ožäóù[·nÕjj¢©©‰x×™3g¤RiDDø÷âÅ‹yyy ³ú\œ9s¦ªªêèÑ£4---Ðöˆ#ˆ{ Ň~x÷î].—ÛÒÒrçέT­ç×LNN...`2™|>¿K4ªúÚµk7nܰ¶¶NNNnjjåååD"m’Š¢ÏŸ?ßÐÐ ‰jjj~øá333²ÔË€h*8ùñÇëêê„B¡Í{ï½>ºL&[´hñ ý…TOX”ž¥;55µ°°pãÆ………B¡°¹¹999y̘1ä{4êA ...à—_~Q uþðáúºº"ÔŒV ‹-Ÿþymm-›Íö÷÷ mll¬­­]¶l‘ˆúÒM¥¦Õ£^H²¢z%t¼jœú.#×+alllllÌçó·mÛ6`À€Y³fÉår///ê2//¯²²ÒËËk̘1‹/NNNŽ%?ž——wüøñÙ³g;6,,L"‘¤¦¦Z°°°¨ªª*,,œ?¾]TT†a'Nœptt7˜˜˜dffÖÖÖ®^½ÚÆÆfåÊ•,«¤¤Ä‚ªvþË—_~‰aXpp°jîh4š±±ñÚµk1 ûæ›o”n˜>}º\.'òuèÐ!™LvâÄ ¢r§.äéÓ§Åbñ¶mÛ´jóòò®_¿”–ŸŸÏçó/\¸þ---MJJ©©ÏF322:zô(†aÞÞÞ&&&ÀˆRSS¥RiEEEXXØøñã===+**jkkÍÍÍ)Ê©ÿ×LMM•Éd­­­ÝÉ@EÕ7nÜ(..ÎÈÈŸ4iÒ|––fiiIÖ§›Ô¨(kkë²²²'Ož,[¶lüøñ!!!---W®\!—m*2¨/8êBWUU1™LSSS $Q%õˆTdÐÇ¢ô/Ýééé2™¬¶¶vÍš5ööö!!!\.÷æÍ›D6©èÐeý€¢è­[·ž={FVˬY³d2Ù©S§ÀV½ ^^^r¹üÒ¥Kï½÷ÞíÛ·ëêê®\¹2yòäû÷ï“ õ¥ÑdÕê³I£^H²¢ze‘2))I)êWºdÊ”)r¹ÜÛÛEQ???¹\>zôhêïµ°°J¥gΜïBQÔÈÈH)‡à (Ÿ4íæÍ›DiñññÁ0lË–- Æf³Év*—Ëýüü@²(ŠîܹS.—wi êÑhkÖ¬QÓ?~œF£íÝ»W&“>}š\à© E[ÉÏ;WQQadddffÆçóûí·’’##£wÞyG,ïÚµ‹œ`w¹|÷Ýw†yyy©vºSSSÛÛÛ###A}Š¢èöíÛ1 [½z5źþ_S£ TT}ãÆ Ã"""ˆD”Ê‚z›Ô¨¨¸¸8 Ã<<<@"4m×®]r¹<00¢ T Eªªª=z¤ZØõ’"úX”þ¥;==½½½lr111DFQ€îꇀ€ ÃvìØA\Å0ìý÷߯ИMõ2€†p÷îÝFFFß|ó †a`Kç?ü ”ÌRMé¦bÕj²IŠÓdEQyvò1 ¥µ@Õ+Ý1iÒ$EËÊÊp···—J¥B¡ú«E"—ËõòòÚ²e‹™™ŽãJ ¤à X½P(<oÔ¨QC† ¿6 A7oÞ7à8N.Qžžž¯_¿¾zõ*± òøñcA¦M›fàí|ýõ×®]»vìØ‘žž¾uëVò$8u! EGG‡¶kÈÕÕÕcÇŽ>|¸‡‡‡‘‘Ñõë×ííí-,,fÍšellüøñã\ÊÌÌìììÄqÇñ¦¦&Çmmm)ªº§¾¦(¦€¢è… :::@"JeA½MjdþüùÍÍÍ=‰(ŠäädA”52P)8z¢¿=…þ_S#ÙÙÙ …B‘ È|R ¨5\¸pÏç“g)?ùä“òòò’’r¹S“M*2p¹\…B!•JiiiÁqüÅ‹³¯TÐÓª)¢¿ÁEQ¹S»]£¡¡¡oÞ¼QsE  ñãóù‚ØØØp¹\ê¯lÛ¶íèÑ£GŽÙ¾}û;wΞ=[^^N¶ooo??¿I“&1|WÐ'¿Þ½{W&“ùûûWVV¶¶¶†„„XXXœ>}šHaìØ±ƒ jkk#ÝÁƒk+ªžLš4iÁ‚"‘èÛo¿UZ îm!KKKŒŒf̘áîîÞÒÒ’››‹¢è¼yólll^½zUXX؃ aCC‘°WêÛ {êkª‘b /^¼PcÌêmR#t:½¶¶–¬s¡Pˆa˜µµ5u4=é!{ý¿¦zpg³ÙÄ+Z[[¡Óé ¡¨5üç?ÿÉÌÌ œ5k“É\²d‰µµuRR’RÇEM6©ÈðŸÿüùïv§¿ÿþ›ø[ã žVMý †¬(õh±kÔÄÄ$!!¤¯t¥»¶755ÕËË Œ¦E"‚ `+‹ëëëgÏžM±Ñ¾wïÞûï¿¿fÍ__ß+V,[¶lÿþýçÎVâïïìØ±ÆÆÆÓ§O———?{ö,22rùòåÄãgË–- ™™™<ïûï¿ÿé§Ÿ#CQT*•Nœ8Q©íé¥Þ«>ú裼¼¼>ú(&&FI±½-ä£G^¾|éìììââRWWÇãñZZZ¦OŸ>jÔ¨¦¦¦×¯_ëÿ ‰D¢ó³=õ5ÕÈ@15£+6IÕÁ„êõ#<õ§GÐ_ÈAÿ¯©pÌ—èúƒzŒ\ÕRуz~ùåÿµk×,[¶ìåË—¿þú«’êÔ2èÙꫦ‚þC½†¡Únܸ‘¬ÍÎÎNÕ+Ý=»~ýzE™Lfiié—_~©P(šššNœ8 6R”˜ì¯¿þzáÂww÷ÄÄÄððpƒ~õ÷÷§ÑhkÖ¬s8ŽƒÙ32¾¾¾†-\¸°¾¾ž˜: ~åñx&L>|8¶ö!iiiÛ·o‰‰Y·n]mmí±cÇ9{[Èÿüç?---vvvŽŽŽ¿þú+ŽãOŸ>8qâСCY,–VE¨·wØ÷ö×Ô?*6‰¨UŸÏ9r$ùŠ¥¥å°aÃÈ#¨/8úÓ#BRA‹ê©‚ãääTYY $;v,‚ üÛ#z¨¬¬,((øôÓO‡ öá‡æææŠÅbêà[P´ê· ªƒY…BÑI¢Ë+ÝÑÙÙ‰¢èرcŸ>}ÚÑÑ1uêT33³ÊÊJpúB[‰A©.((¨¨¨077'cccãçÏŸ·´´€:‘N§»¸¸(u…ìííE"ÑË—/Á«•zwïÞEdãÆ}îñ¡£££³³sçÎL&s×®]K—.%2b!Ÿ>}jgg7nÜ8&“‰ãxUU•½½ýرckjj´JŒþ‡Ú;böú×Ô?*6‰¨UTNNŽ­­íܹs‰§üüüP½{÷®¶­BwGzPHõècQ=Up>þøc"› ,@Q4??d³Gô€ãøÅ‹-,,öìÙ3räÈß~ûM«‘¾E«~»0P?mÚ´Áƒƒž”««kGG‡¶«MK—.½~ýúúõëÇ7f̘€€€yóæ=xð€H¤¤¤dĈaaaVVV ,8þ¼R2dHYYÙÔ©SËÊÊd2™T*e³Ù‰‰‰£F7ÄÇÇ?xð`óæÍ;vìprr²µµõ÷÷¿sçÎŒ3úä3¿~ý:$$„Çã?~œXÒ§.¤nç©­­9sæ_ýUPP€ãxIIÉØ±cétú“'O´úd¹¹¹¯^½Z¿~½ƒƒÃĉ7oÞ܃·¾¦þ)h´I€EEGG766ÆÅÅy{{ÛØØ„……1™LÕu£îÐXpôG!)¢EõHéÆqü«¯¾òóó³±± \µjUAAÁÍ›72{Jiii\.wõêÕ---7nÜÐêKà[P´jHŠD¢áÇ#òã?–••i»yÚÅÅ%33“ÍfK$>Ÿ_QQkeeEÜ0bĈ„„à˜Åb9s&((Ã0âÈmZZZcc£ÏðáÃétºÇ;qâQœ† YZZ* ¹\nEEEbb¢Ò™Y5lذ¡¡¡¡­­M&“=þ\&“µµµ±Ù쯾ú ¼â‹/¾¨¯¯'nËå\.—ÍfïÛ·Ü tŽAyóæq8œ¢¢"â E!u;Gˆ ˆ§§§\.ÏÎÎßhèС|>_(Û 4怢h@@@II‰@ àñxÅÅÅÄG››É;›—,Y"—Ë8@QZý¿&4ªúÆÏž=ën‹¶F›Ô¨(AÆþüùÆÆF±X\WW÷ÓO?)¶T/ƒÆ‚CîŽOè/$Eô´(=Kwzz:—ËݱcGII‰X,æp8iiiJaÔëAcý@pìØ1 ⢢º< >›jdÇ'ÀY‹àà` ÃÀØqÿþý„Yj,Ý­šz6Õ Þ`4 ©ª¨~8ÓFü­Ã"°Å ì566îò,qòüJ~)N—J¥§OŸ&¿EÑÂÂBÂ[ŠR"ݽE}6‰gɉ€\¨¿Aé𸢤1*BêvްË7*^Ö˜‹.ï$'¨ê"Y5ãj葯IQõªÖèëYM*½ºKE©þÔå¡.52P)8é¨y‹ÎBRGO‹Ò§tƒõ èîK©Š§æíê Î÷ß/‘HÞ}÷]¥Ñ*•lª‘ÜLœÿSú[õñî„ToÕÔ³©*V­æÚÚ›L²STÝFèT6w©¦L\ÇnÀ‘âW ‹Ñ£GWTT¨O„:ŸÕ˜ \Åužê*/Bþ¯ÎµBõ:o´ëîNÕ‹]f³;zäkR”A½õ±I¥Ww—”Fmk´¨žÚó¬&=…¤Žž¥çô Š¢`o„¶âiõö~öÙg999ªÛÓ¨dS½-7+ÕÉÄßzÖ´]þªzZµ¶öÖÏF޽†H$zôè‘··wAAÁ½{÷†êææ:xðàóçÏ¿Îà!ðkBþyX[[[[[óx¼o¿ýväÈ‘111>µùW`mm}êÔ©ªª*¡Ü¬… IDATP(‰X,ÖüáííÝç{D!:¿&ÄÀ¤§§Ëåò™àí’iÓ¦±Ùl¡PXRR²råJhɆäíÞóª-À?˜'üõöq7H/¿&Ä¡(Ú{‘‰wšàD,´d@ @ B°xñb6›ÒKhçÏŸomm•H$2™ Ä'2| 2:îÔÔT±XL}A÷_ôŠ‹‹‰ÀÖ"‘¨±±1;;[[cuwwOII©©©grY,VVVÅH.®®®Dto%X,ų•l6»Ë²²²(¦BÞz¨¯¯¿|ù2pEQ€”””.ß•››ûçŸêpH‚ ÈÌ™3kkkoݺüN899=yò$??x¶ì%œœœD"‘Š¢žžžb±xòäÉýÐoŠ¢¦¦¦j¢”|ÿý÷S¦LÑMò 6888:tœë“s¡O6ß"4~îîè©s«]À`0’’’ˆ0¼Jÿöž>ž¢ÀiVÀ‘#G0 [¹r%ˆµM]‡ªgH£££1 ¢Xð@0÷eË–™˜˜L˜0!88¸®®®­­möìÙTôPXXH8Q¢¶¶6==ým±‡~ÅÔ©Skjj²³³U¦£(úÞ{ïUUUåååQ§®-›6m‰DÀ_óáÇ«ªªzo{¤>¨w¼`gg'‰¨Çÿë}ÂÉöH sÑ#Ù|+ÐÊÏm·øj†)44œÐŠcÕ…Bþ}[޼Ö|>_ ´··ßºuËÓÓ3%%…ŠüëÖ­1bÄêÕ«  …P(|òä Bù©ÒiV俱sµÚ¦´imæÌ™ëÖ­{ðà¶çç:;;;::êëë:;;ccc׬YCÅl[[›³³s—?™››óx<¸ÛM¢££ÍÌÌV¬X¡jÇñêêê½{÷2Œlݺµ7JΜ9“ÅbÉårA¦OŸ^UUÕ?¿£zÇ ^^^ 0¤<½Æ\ü3²I­ül(¡U1¡ÚÒnܸøøïììísPP¸B±¹vtt<þ|CCƒH$ª©©ùá‡ÌÌ̈_“““‹‹‹˜L&ŸÏoii¹s率‡¹ËcnnW[[+‰ÀƒƒƒÎ}"Çä/^¼ XæAf‡C¹ÖÙ{KOqøðaÇ÷îÝ«[Gd¡¦¦ÇñQ£FQQf[[›•••j9tpp055åp8:ˆ¡×®]»qㆵµurrrSS“@ (//W²õ¸»»_½z•Ífsæ2™ŒÍfIõ&GÅhœœ~ùå—§OŸ …¦¦¦GíÙ³G©ÈlÙ²eÖ¬YgΜ©««ëÒq¿víZFFÆêÕ«»Ë`TTÇSM\#ÍÍÍ2™Ì×××ÅÅLÝ{xx,^¼X,$$¤¥¥åÊ•+dŸ¹2™¬µµ5,,lüøñžžžµµµ„»X“ÌÌÌÚÚÚÕ«WÛØØ¬\¹’Åb•””PŸ,S£àï¼óއ‡GVVV}}=u÷ó[·nÅ0ìäÉ“ú¯:tð+Vè3¹±yóf¹\~äÈ­¾4˜]²d ñjà~722’J¾ÂÃÃ1 suuEQ466V*•¿Þü±\.ÿâ‹/¨äèÊ•+䶇 ::Z+·¼ÅÅÅááá“&MúàƒÒÒÒ×ä±°°¨ªª*,,œ?¾Pˉ'Á MN£Ñ"’——WYYéåå5f̘ŋ'''“=ªîß¿ÿìÙ3"nFw|ðÁr¹<>>¾KEGG‹D¢ýû÷kkœ`‚ÏçoÛ¶mÀ€³fÍ’Ëå^^^&&&Ô“Ú±c‡T*ýã?-Zdgg·nݺ[·n‘¿E^^ÞñãÇgÏž=vìØ°°0‰D’ššJØ-pãY[[»fÍ{{û.—{óæM%·±ÆÆÆk×®Å0ì›o¾éÒçÑ£G1 óöö+J3cêe 轩Q¥1o ROêSpPÍÍÍmjj£€»»»L&;{ö,‘_ªÖ(ƒúÏ­ñéé醱X¬µk×öÊ2yQ|ƒ¡±"Ž‹‹Ã0ÌæÑh»ví’Ëådgá‘‘‘À,Š¢Û·oÇ0 8JG$44T.—ûùùûQݹs§\.ïRG]òäÉ“ööv¢Î•ËåYYY®®®ÔÍÝÔÔôÞ½{†‡‡‡=šâƒªèßÚÚÚÖ××—””A!(B4„ pvvÞ´i‹Åª©©±µµ¥ò8‡ëëë‹¢èÇ›››/]ºddd´~ýz Ã(.àwé0WÛÅ€7n`AØŒV ölÙž¢Ñhl6›\ùj49Fkaa!•JÏœ9Ò*åqâĉ‰äâÅ‹…GQ´¤¤¤¾¾¾Ë;uö±Ž È”)Sär¹··7Š¢~~~r¹\+Û7n‡Ãa2™ Wý ã„‹ç›7o6665xzzz{{;ù[ÄÄÄ"‘ÓY³fMw5#‚ ß}÷†aÝ-ž©— ÷BŠ•˜ú\¨¿Ê+ô,8_ý5†a Ü:¸rüøq Ã>úè#âŠFUS”AÍç¦bQ_}õŬi÷¥ y9øŸ¥b.óçÏonn~ôèI<99A¥o™™™ ü)ã8ÂÛÚÚ‚<==_¿~}õêUbZòñãÇ‚Pܱ hmm¥ÓéÎÎÎ~~~üý÷ß?ùäŠ)¼~ýzùòåqqqÇß»wïãÇììì(¾½g9xðà¨Q£<øêÕ+OIIùùù_}õU~~þ_|ÑÚÚJåÁÚÚZÇ­­­mmm322ÜÜÜP;vìßÿ ~Õ˜X¡TEÛyfE/\¸ÖYµõ. Âj¿yó†ì•†l MNÑŠD".—ëååµeË333 ¡R§M›fll\__¯Qo }+++:®ú+XoÖm¢~Ò¤I(Š–••á8noo/•J…B!õÇ/^Ÿ ˆ¶*}Áææf5"y{{ûùùMš4iĈ8p ˜"nÀqœÍf)€nNïÁ†P£ ½MOUbú¿BŸ‚Ãáp=z4wîÜ‘#G …ÂE‹ÙØØœ:uŠ\ö©¨Z¨¼ÇqÕðݡŮQ“„„.õ3 Ç)6‡ª­zE"‘¨y\*•Nœ8Qç@Jà8ÞÐÐÀápœµ*l …âï¿ÿNMMMKK;pà@XXXpppTT”ÁÚ€!C†ìß¿_&“8p@çͺ`L¦CeŠã¸@ 1ªªªjjjššš>úè#KKKê½+W®|øá‡ªjOHHˆˆˆ ®I}tÎáp¶lÙ’™™ÙÑÑÁãñ¾ÿþûŸ~ú‰H“¢É©1ZAîÝ»÷þûï¯Y³Æ××wÅŠË–-Û¿ÿ¹sçÈoAþë+•"=Xw§¦¦zyyY&‘H„ ˜J‹Åõõõ³gϦ^´Õ| ÿcÇŽ566ž>}º¼¼üÙ³g‘‘‘Ë—/WJÄØØ˜èg^7õÈœÖ2ô6=^‰éü =+«k×®}üñÇ«V­:yòä_|¡P(RSS‰EQÕúÈ ƒE©‡jC¸qãFrµÕÙÙ®Pù„|>Q"°´´6lÅŽ0‚ <o„ ÇýÖÇq—U€a]ºtiëÖ­ãÆë)‘¨ðí·ß:99EDDP×^ÏÂãñÌÍÍmll®_¿®P(ŠŠŠf̘addÄãñ(¦ÐÝâ¨wá‚õÎ… Ö×דöį=brÀN~ýõ× .¸»»'&&†‡‡3 â8Å8é`Ëyä¤'`¥‡Éd–––~ùå— …¢©©éĉ±±±`‹8•DÀVáqãÆ¡(Ú¥`þþþ4mÍš5`êÇq0/­„““See%HxZåTÍÍeèU(Z•Ir=_¡'/^Ü¿ÿâÅ‹O:õá‡>yò„<ö2€ªu°(õPmÀr ù •ÇsrrlmmçÎKT~~~(ŠÞ½{—¢¡ß½{A7ö`wØÙÙÙÚÚº»=ëT{C yf`úôé £¯Nn€vvvþù'Žã999“&M²°° >_×Sk„zboo/‰^¾| )½½M4‡æææäN@uuµB¡ptt¤2-aoo/‘Hz°ÔÙÙ ÖwŸ>}ÚÑÑ1uêT33³ÊÊJ Š‰ÜºuëåË—ä}ÈJ?þ¼¥¥ô6ètº‹‹‹êÍü1q¸:ÊÏÏתl‚AíСCu–¡W¡hQjr¡ñ†Þ¨'UyõêUvv¶››ÛÊ•+---A‡˜øÕªÖÁ¢Ôc ùñèèèÆÆÆ¸¸8ooo›€€€°°0&“™””D±î‹ðàÁæÍ›wìØáäädkkëïïçÎÕÃk×®•H$L&SÍ~!33³O>ùäçŸ666>qâ„’ Ý¥>þüÑ£G?~Æ {÷îmiiILL¤˜uºK–Ø·oŸÆs¦½'‡Ãqtt?á8~óæMEÇ×W#Tõdff ÕC/C† )++›:ujYY™L&“J¥l6;11‘8Æ@Ýäºcéҥׯ__¿~ý¸qãÆŒ0oÞ¼+÷ŠŠŠšššyóæ‘ÕvÉœ9sœœœrss»lÒÓÓ¥R)ØÍKE6‚iÓ¦ <tœ]]];::¨øU ÓÔÔtúôé©S§&''{xxŒ;ÖÛÛ;--mÞ¼y@˜’’’#F„……YYY-X°àüùóª•8Žã_}õ•ŸŸŸM``àªU« nÞ¼©•$¹¹¹¯^½Z¿~½ƒƒÃĉ7oÞL|t*2ô6-JM.4Þ ¿ÑRä÷ß711 û믿ÒÓÓÉ T­•E¸»£ñãÇŸ?¾±±Q,×ÕÕýôÓOäãV`':yí’%Kärùˆo>>ª]§îR8uêTMM ŸÏ—ÉdB¡°²²òìٳı3*)h<>Ñe ...2™ìùóçr¹\£·ÒîdP=GØÝ¥€a85®dff¶··/_¾Ü6wãÆgÏžiô¢”••%‘HNŸ>­”‹´´´ÆÆFŸáǯ{>>><ïĉMN£Ñº¸¸dff²Ùl‰DÂçó+**bcc­¬¬”$ܹs'†a;vìPß‹?wî8á×¥’+++››› ¤^ªŠD"ààôÇ,++Ó¡çD£Ñsrrž={&‹³²²&NœD1bDBB›Í‹Å,ëÌ™3AAA†ÇÀÓÓÓ¹\îŽ;JJJÄb1‡ÃIKK#ï¤ûâ‹/êëëÛÚÚûçr¹l6{ß¾}d¥¡(PRR"x<^qq1‘2lذ¡¡¡x…L&kkkc³Ù_}õÅÑ•¨TbjrA寠XpÔƒ¢hii)†a¿ýö›’xU­QŸ›ŠEåäälß¾½·Ôë Ø¼Ž‹©ž¦Rõ‘Švåeœ\ì.@vvvkk«êºêÙ5i“z ä·h•9)p€¦»ºL%y+UÍ õ\¨µÆ€ä7µ¸çEѯ.¸MÉTètºT*=}ú49(Šæåå)ãîÎä4-°yK£Ñrss›››ÕL.Z´H,'&&vYªd2™n®€=3«m rW-\„È/Eþ{ ~À€d]©I\ÍÁS¥zF)§jdP*Ýj^ÑS R‰©É•Ô¿¢§RÊTýI½ª5Ê@ås«(wúØóÛÍÈ‘#Á±cÇtž"‡)ôT ý ‰DòÓO?‘sgiiÙÚÚzãÆ Ãž÷ߟÍfß¾}[)ôÀÉÉ©¬¬¬¨¨¨»=5þþþ"‘¨Æ‹ ‚¶.’!ˆ´êÄÁz5…þLFFFccãš5k¬¬¬Æïëë›-‹õô{§(ŠÎ;—Åbedd(í?~|qq1“Étppèîqê£üþ l!¤°¶¶>uêTUU•P(‰D,ë?þðööî«¶Ÿ˜G¥xýŸl!}ËÛÚ…„@ô,ñ’´N› †,(êp@ @ @ H¿ÆÉÉI$ùøø (êéé)‹ûÕ†ï!C†°X¬¶¶63V"‘p8œ»wïRß§P\\LÄ›qº³³³7lØ Õþ ww÷”””ššp–ÅbeeeQ Ôâêê b:«¢zâ¾;Ølv—)deeQL!22R"‘z¨¯¯¿|ù2pšEQ€”””.ß•››ûçŸþ³wŽô3gά­­½uë–Ò! ''§'Ožäç矤[@|øpUUUÛ'Nh9rð•+Wš˜˜hUç>yò¤ªªÊÔÔÔØØ˜N§{zz‚X?Û77·–––üü|///++«3f„††ÆÇÇSƒ|âžœ‹îνv‰ê9Öèèh ‚‚(¶èÀyͲeËLLL&L˜\WW×ÖÖ6{öl*z(,,ÌÎÎîRàÚÚÚôôtØêÀÔ©Skjj²³³ÉÁÊ(о÷Þ{UUUyyyª¿B ÿ„aÛ¸É-ƒÁHNN¦X1;wîáÇàæ7nôÛMçðñ !$2…¢èìÙ³åryZZÅœÆÆÆ¶··Ï™3‡0 œ&h›D\(1sæL—™™I½×BöⲈaÙ{™®\¹R]]Ý¥ÆALLÌ?øtcïqûöm‡ÓÝ Š¢Ë–-“H$º¹§@Þj¨ZüÆCzrHzª—Š—úææf™Læëëëââæî<<</^,‹<ttt<þ|CCƒH$ª©©ùá‡Ènˆ“““‹‹‹˜L&ŸÏoii¹s率‡¹T›››ÇÅÅÕÖÖŠD"0½æààЇS¯8Žƒ¬½xñ‚â¦|a™Ãᦠ™H•Çã8¾wï^ã>*ŠššÇGEås€è Pºîàà`jjjÈX×®]»qㆵµurrrSS“@ (//W²:õ¸»»_½z•Ífsæ2™ŒÍf½ õFKÅ윜~ùå—§OŸ …¦¦¦GíÙ³G©1Û²eˬY³Îœ9Ó]¬ǯ]»–‘‘±zõêî2ÅãñT‡@Þv´Ãþ ¦§ÑhëhGGG ‹—/_îß¿ßÊÊjÑ¢E …„ð8|ø°B¡°¶¶þý÷ß]\\víÚõþûïÇÆÆúúúž?ž9::>|8==}îܹ!!!t:ýçŸ&¼¬š˜˜¤¤¤|ú駇vssÛ½{÷¬Y³.^¼H00ï¼óއ‡Ç¾}ûD"ÑÏ?ÿL±!A¾ùæ›~R×lÞ¼yöìÙ £¢¢BŸv H ¦ñæÖÖVà²966V*•nÛ¶F£ÙÛÛ#ÒÒÒB%‘+W®Û‚èèhêº522²²²:sæLeeåâÅ‹}}}kjj¨Çí²°°þަOŸþóÏ?Óh´_ýÕÓÓœ™Óh´ÍAƒáææ¶mÛ¶iÓ¦ýÏÿüOCCƒêôæŠ+^¼x¯¦7ƒã8XøX³fM— !ð_Ó?gq ƒB¬‚ÉRòõL™2E.—{{{£(êçç'—ËGMü‡a˜‡‡8ãL£ÑvíÚ%—ËAµ<ýGFFWR(Šnß¾ðիWƒB*—ËýüüˆIÅ;wÊår}¦FÉ.äryVV–««+uLMMïÝ»‡aXqqqxx8YEÚ¢ÿÔ¨­­m}}}IIÉàÁƒµz˜0`€³³ó¦M›X,VMM­­-•ÇA¼\QèáÇÍÍÍ ÒÅúõë1 1 5&Ò¥Ó^mÆÝ¸qðˆˆÂê´j|||0 Û²e xŠF£±Ùì›7o‰h4Zfoaa!•JÏœ9Ò*åqâĉ‰äâÅ‹…GQ´¤¤¤¾¾¾;OÊÿl¯{-ÚÙ41­`BBh©ì—™4iŠ¢eee8ŽÛÛÛK¥R¡PHü:þüæææG“““Q :“™™ÙÙÙ Bƒá…­­-¸ÁÓÓóõë×W¯^%&?~Œ Åý–=Ekk+N·°°pvvöóó8pàï¿ÿþÉ'ŸP”áõë×Ë—/‹‹>|øÞ½{?~œ`gg×ËRwÍÁƒGuðàÁW¯^éðxJJŠ@ ÈÏÏÿꫯòóó¿øâ‹ÖÖV*ÖÖÖâ8nmmmkkëì윑‘áææâÇþý÷ßàW‰ôTì_E/\¸ÐÑѬN«ùaà5ôÍ›7d·5dK h´jÌ^$q¹\//¯-[¶˜™™ •ò8mÚ4ccãúúz*¡Ï›šš¬¬¬ètºê¯ …ÂðÁ“! Å¦M°"øæÍA6nÜHÔsçΓ¥jŸÏGÄÆÆ†Ëå’¥ÓéJœP(Ä0Œ“ A††âðFSSSðïØ±c DŽ zÇÚŽfô§£££³³S(Þ¼y“ÅbåååíÙ³çÞ½{ëÐöööƒFFFúøøøùùùúúº»»/\¸Üo0K–,YºtéÕ«Woݺ¥Û¤h@@@ff&þ¡ò`UUÕ«W¯ètú¢E‹^½z•°víÚ Œ=Z$¸"~ñâ…’­Rìö÷÷¯¬¬lmm ±°°8}ú4¡ŠF«ÆìÙ¶mÛÑ£G9²}ûö;wîœ={¶¼¼œ¬j0¯@1l²@ @ÄÑÑ‘ËåBos TBbÊFpp0¹ZW_7¥¦¦zyy‘H„ >ŠÅâúúúÙ³gƒ¤TÇLªW$IwoAQT*•Nœ8QÉc¡¶½øÇñ††‡ãìì¬Õ¨T¡Püý÷ß©©©iii ŽŠŠ2X0dÈýû÷Ëd²è¬=0&Ó¡2Åq\ XXXŒ=ºªªª¦¦¦©©é£>²´´¤Þ¸råʇ~¨ªö„„„ˆˆêšÔGçgË–- ™™™<ïûï¿ÿé§Ÿˆ4)­³GäÞ½{ï¿ÿþš5k|}}W¬X±lÙ²ýû÷Ÿ;wŽüä¿ÎT)ç?!ÿ*¨6„ä! òßn) ((H}e±~ýzE™Lfiié—_~©P(šššNœ8 ¶¡"ÂçóÁùBKKËaÆQìÆ"Âãñ&L˜0|øp0èì'à8®ó² ¨ /]º´uëV51~{ƒo¿ýÖÉÉ)""‚ºþ{gnnnccsýúu…BQTT4cÆ ###G1…îG ¼ ¬w.\¸°¾¾ž˜ö'~í£vò믿^¸pÁÝÝ=111<<œÁ`7€Ä»‹e¨ØhÃf³ápòïA‹]£$”~Rÿlgg'XàyúôiGGÇÔ©SÍÌÌ*++Áy pONNŽ­­íܹs‰ÊËÏÏEÑ»wïR,wïÞEdãÆýª3ëììlmmM}Ÿ¡*`oˆ!Ï LŸ>=00°  €Á`ôÕ‚8Aagg÷çŸâ8ž““3iÒ$ êóu=µF¨'ööö"‘èåË—ÀÚ•ÞÞƒF šÃ‚‚‚ŠŠ sssr' ººZ¡P8::R™–°··—H$}Õ‚@úµÓ¦M>þÁƒ›7oÞ±c‡“““­­­¿¿ÿ;wf̘¡Tþ×®]+‘H˜L¦ÎÁ©¤`fföÉ'ŸüüóÏÆÆÆ'NœPÊEw)ÄÄÄ„‡‡ÏŸ?ôèÑãÇß°aÃÞ½{[ZZP\ôX IDAT)¦ .Ž9bdd´oß>aqzO‡ãèè~ÂqüæÍ›(ŠŽ7®VЙ™™@õ(ú!CÊÊʦNZVV&“ɤR)›ÍNLL$NGP7ÚîXºtéõë×ׯ_?nÜ8pNcÞ¼y< ®ŠŠŠšššy󿑿vÉœ9sœœœrss»ìm¤§§K¥R°›—ŠlÈÛ‚<œ½÷Þ{oÞ¼)**ÂqüÝwß}öì†aäø|þŠ+öïß7lØ0±X|ýúõƒ‚½9TxýúõêÕ«#""üüü¾þú뎎±X\RR¢:†puu566Vk2¤´´tðàÁC‡¥Ñh?ÿüó?þX[[ëåå¥4î.AlllÄb1øûÕ«W,+$$äÊ•+e0`@``àÎ;MMMß¼y#rss;¦:u¦FŠt™‚‹‹Ëœ9sºLY$Mš4‰¬Š^’A––“ÒÒRp½½½½¬¬lþüùpTCuTwîܹY³fÿùçŸ/^¼5jÔ¼yóNœ8ñ×_………) êFÛFFFˆ‰‰yóæP(¼téÒÑ£GÉŸ Çñ+W®ìᨒ ±±±jz–6l@Qô·ß~ëòí“'OnooÏÈÈ臟y 'ˆ¿»@€ýrà°—êY(ð“ÒýªµH¼»DÙÙÙ­­­]®º©>ëRÔîRèòñ.»ÏÝ¥@–ŸÈ‚V)“‡Ïº»¡ËÈÞJ5ªBM.Ô¿Zc @ òZ <Qµ:5·)N—J¥§OŸ&çEѼ¼<òE5F«Ñì‰øõêmžF£åææ677«™ ]´h‘X,NLLìÒæd2tÀü9r¤@ 8vì˜Îå¦ÐRèÏXXXH$’Ÿ~ú‰œ;KKËÖÖÖ7nÞ?Ëûï¿Ïf³oß¾­zàääTVVVTTÔÝž‘HÔ¯ÂÅ@ ÝÑß;L¡ÿ¤ÐŸÉÈÈhll\³f••Õøñã}}}³³³Åb±þžÐuEѹsç²X¬ŒŒ pÒŸ`üøñÅÅÅL&ÓÁÁ¡»Ç©ò!ù_¬­­O:UUU% E"‹Åúã?¼½½ûªí'æQ)^‡@þ%ÀþÒ‹€%^ò‘vpš°¯å‚@ @ @ @ äߊ›e ØíF„ž ® *ñ( ùGÂ0=Ö /ù Üx @ ·-Â0. Á(F£½%@ ½Õ†h žÁ`t§@ ,III`"4))Ii²´¯Eƒ@ ¤—ë‚ào²›(¢u„@ ä ¹ÿl!ò–Bõøh 7‰ÁÁÁ8Ž'$$€qaHHõºô¨6„JáaÁÖâ"Ü)@ @ @ @ @ @ @ @ @ @þ•XZZ&''³Ùl±XÜÚÚzîÜ9r‹QQQ‰dÅŠdÇuU ¢z ¨I¤; ÝíÞ½{É’%QQQS¦L ¹ÿ>ðâMôìÙ³ëׯ÷m8 [[[‹%“Éèt:ùúÇ¥R©ŒÄÖ­[uh˱±qkk«¶FFFJ$ðj‘HT__ùòå ²v³´´W”››[KKK~~¾———••ÕŒ3BCCããã oWê­ÚÁÁ¡¤¤¤´´4((ÈÎÎÎÅÅå³Ï>#ç±Ï5ùäÉ“ªª* N÷ôô¼{÷®L& èW&§Q“ˆ¾€0Läxô #99\¤žNuuõ£Gº|$99Y.—Ÿ:uªºººo•+WJ¥Ò‹/¶··+5„‡>¥999r¹œÇãH$’‡ŠÅb Ã)¦ Â%K–€nF Ä0ìĉÚJåêêzðàÁ#Fh› {{{777### ÃàÁƒÙlvaa!ù“õ¹¢bccÛÛÛçÌ™îº2üø@£U§¥¥±Ùl'''BN¥º»Ï5 BBrEgÏž-—ËÓÒÒ VH©˜œFMB ÝaLñ¾7* ð7°3D1 á?þ¸xñbssóAƒá8.‹ÁõÕ«Wß¾}ÌŽ¾xñâĉ‡ª®®Ö:=‡……ÅÞ½{™L&—ËUš¶533:t¨L&Ó9ñðððqãÆ1bÇŽ&&&/_¾Üµk—D"ijjRzpÇq¼¦¦ÇñQ£Fi[ì'Ož–””¤mŽšššš›› _¾|ùüùó!C†7ôEy8°[ +åÑõVíää´páÂÄÄÄÆÆFBNò ýA“Jà8j€/^L¥MN£& ¢¢¢üýýOžŸíÚµáÇWUUÕ××;;;SÌS£ pvvÞ´i‹Åª©©±µµÕJ AÖ­[‡a˜Ðét__ßÇ———OŸ>ÈEP”©©é½{÷0 +..=z´vyëiº´j`cL&“Ïç·¶¶^½zôlÀ ýA“Ož>>OŸ>-((8p ¸¡?h’¼YÆÒÒò³Ï>ËÉÉa³ÙŸ~ú©áÔ˜œFMB =¹Dþ‰ aTT”P(œ7o(Þª !‚ 4 ü æoݺ%“É´j‡P%&]i4šê¬F!‰]£`†‡‰"ÄÐÙßßÃ0†Î KK˹sçÆÅʼnÅb¥Ý:}®(BŒ®]»öÖ­[†•——[ZZR<..Ni¾½Ë]ûTèÒª/]ºÔÞÞîç箣(ºmÛ6¹\¾fÍ"³}®IÕÍ2NNN</77—z!íMª19*š„@ºƒêjhÀL}pppPP±™X5ìC®\¹òᇪ}BBBDD„Æ•ƒ9sæ&%%1™L5+D:`óEiiéœ9s¦NZWWGQNÇ ]é¼VßÙÙÙÑÑ¡Û ÒÛARº¥# E"“É5jÔºuë’’’JKKTýDQ …âï¿ÿNMMMKK;pà@XXXpppTTÅ·oß¾sçN¥{p‡Å_ý¥P(®^½ rŠãxqq1‚ &L@Q´_i’œZCC‡ÃÑj~µG4©Æä¨hé-v’Xq±Ï[AAºs™A±¼-[¶làÀ¡¡¡!!!à è8×ÕÕI$ggç.[ Ðýü믿ô“ý-ÔÎl6 JKK»¼­oZ‚K—.mݺuܸqÔìÙfO•¦¦&Eˆ­+ä]ÒLÇqm§zP“]šœš„@´Ø5ÚIBéb¯‰§`d£ Åâ1räÈ‘#GZü—_ýÇñÉ“'­ ¹¹¹ÒS®®®ÏŸ?ôèÑÛØå¬¬¬<~ü¸\.×öÁ‘#G*]™4i‚ Ä.¾þ©¨)S¦ (ÊápúJU®]»öæÍ›µk×}8ࡨ¨(ªjÒÙÙÙÚÚº®®Î`2h49š„@Ô ËA…$ª=VP~È3‡_ýõ;3––V]]íààäîî~ìØ1}Žyõ!ååå:ôÓÿý÷G]¿~½¡¡ÁÎÎnݺu .üý÷߉ÎxPTLL —Ë-((hhhh49¥Ûº»ÁÁÁA&“ŸÃá0™LUù>Tr¢¿uëVäÆÆÆ­­­Ú>)‘HÀ«E"Q}}ýåË—,XÐW¥ÚÖÖ–ÅbÉd2¥0fff±±±õõõB¡°´´T7-!z(ŠÍf«Fi–ÉdYYY†<¥ªÑªûÖ¢\]]Åbq—Šb±XýGQ999]†Ý>uê”¶ºÒÙ¢qwwOII©©© …\.—ÅbeeeM›6 ¶©ÿ" žø›€b™yðàAyy9ç„¢(a@Ë—/—H$/^ôððpvvf02™lݺu†´°øøøæææ}ûöMœ8ñÝwß=þ¼\.ß±c¹¤ÕÖÖ^¾|ÄfÓ!zQPPŸŸßÈ‘#W­Z%—ËÍÍÍmmm7mÚ´|ùrŠ9%‡aš0aBppp]]][[ð¬¨užõ&%%E,?þ\©!d0Ïž=[¿~ý˜1cvïÞ-‘H6mÚD]Wú+J5Dstt4†aAAAë`Q±ê¾µ(E‰÷9rð•+W¾tɳNhT”ê¡þÿùŸÿÁ0ÌÏÏ¢=èoQnnn---ùùù^^^VVV3fÌ ïÞ? „a"âÑPõÓ©®®îÒÅŠ¢&&& u433c³Ù÷îÝ3¤‘ÙÛÛ»¹¹¯(Š<˜Íf’eàp8Dð)ÈÉÉ‘Ëå<¯  @"‘<|øP,c–˜˜H1M²‹5 .00Ã0¥p€Tpuu=xðàˆ#tÊ ‚ ÈÊ•+¥RéÅ‹•|ÑqÆñãÇêh4Úõë×É1í4¢¿¢”˜9s&ÇËÌÌÔÁ?™ÎŠ¢bÕ}nQ‡Â0¬Oæ u(þÙÙÙ555Ô¿¦þŠŠmooŸ3g¸”¾çÊÎ?-Â0vi4ˆ; ƒÁ yóæúÇüñÇÅ‹›››4Çq±X ®¯^½úöíÛ ®Ê/¿üBL“>þ\ Œ;V—<éJSSSss3!ÃË—/Ÿ?Næbff6tèP}ü‡‡‡7nĈ;vì011yùòå®]»$ISS“þÞjjjp5j”¶õ×äÉ“ÃÂÂ’’’tË‘……ÅÞ½{™L&—ËU~ñâÅ&&&wîÜ6£P(òòò>øàƒO>ùDÕ r—ô¬¢9|ø0Žã{÷îÕ!XŠÎŠÒhÕýÍ¢ú m‹ÿܹs§M›vîÜ9ê^¿õW¨ 8x)(}]ÞåïïòäÉ£Göï5h† üZ>¢6¢ÆÇwíÚ5yòä1cÆ´´´TWWÓétê´‚à%«²°°À0Œj>äÊ•+]®"DGGSﵑe˜>}ºµµ5çA[[[E¥R)u©”())¹zõê˜1cètzbb¢««k{{{ff&áD_\\\PÕ¡â]ZÝ^Š È¡C‡ÌÍÍwïÞ­êyø¶~üø1!RCCŽã@T*‰÷¬¢6oÞ<{ölƒQQQ¡Ããú(J½U÷O‹ê´*þ …‚ÜvjDEUVVâ8þÍ7ßh4à¿N™þ“!/‚9R­§}AU«VaK½R]EÐaÅ@§Ó}}}?~\^^>}út¢î^¸p¡\.olläp8mmmEEE;wî455Õ*qOOO>ŸíÚµáÇWUUÕ××k雘0`€³³ó¦M›X,VMM­­­v™DuëÖa¦Ãƒ‚,Z´H,ïÙ³ÇÈÈèäÉ“JS£`KqeΜ9r¹üرcÔ?‡žŠ"°µµ­¯¯/))zôèîî !œ5ýÇ¢ÔòQß#C@¥!¤ÓéeeeÍÍÍ}4‡ÅbÉår Ãòóó?ÿüs²5[YYEGGûùùY[[Ï;÷ìÙ³r¹\Û K—.e2™Ÿþ9Š¢»víº}ûöœ9s´mår9ˆ.TUUÅ`0&MšD=bèŒaØóçÏARZ ‡ RTT”›› ŒA5^Õ­[·ÚÚÚÈõÔŒ3är¹V^ÿõT˜ÒôööÖöYýE¦K«îEÐOBÅÿ믿Öj› þŠ6lØáÇëëë1 ãr¹ vvvZÉyëQÿõRCxåʹ\Ð']*###KK˹sçÆÅʼnÅb¥M(D(0]vëÖ-™L¦U;ë€ûAÔ­Š"yרnÑ…ˆ¡³¿¿?†aÚ£¢¢„Bá¼yóÀ{UÂëׯë?"ÔSQ€%K–H¥ÒÄÄDæ©ôW™î¬ºÏ-Š@Ÿ†0..NiaBõèE4ÿ¢¢"­¶Éôˆ¢h4ÚÀ×®]{ëÖ- ÃÊËË---µMÒß j© LHHÐê°„ÄÄÄ|üñÇgΜIIIÑj¹GÖéìì …=Ú¾}ûíÛ·×­[G>'¤P(ÀŠŽã …¢´´”F£M:•zú8Žwvv‚DÀž#Ör:;;;::::::;; ‘´}¨Wé_Ì™3'000))‰Édv÷^‰D2pàÀwÞy‡¸baa ˆH$¢.§þŠ2dÈþýûe2ÙtØ#£§¢È¨±ê~bQz²}ûvKKK Zíd!ÐXü—,YâäätãÆ ïE)Š¿ÿþ;55ÕÛÛ;..ÎÎÎ.88΂¾íh±k”Ü{ÕJPPPÏî‰Ú¹sg``àåË—÷íÛ§mÍÕ]OV¡PèVfpg³Ù(Š:99•––vyèüõ×_Ú¦ÿö²lÙ²††††„„€+ g]WW'‘Hœ;::ž>}Š ˆ««ë½{÷@]3~üxEÁWƒ‰úí·ß:99EDD´µµ쥪heÕo©EéVÊ” ¢(??¿ÎÎN­¶Éô M½téÒÖ­[Çׇ’@ÞJÔLúùù‰D¢k׮鼩AOFŽ©tåÒ¥K†M™24±æææJ7ܹsçÙ³gªöäs„z&5mÚ´ýû÷“ÇmTÈœ>}º½½}ìØ±ÄlÕ{ï½'‰¾ÿþ{¢§üÇ444 4HO™©3}úô¶¶¶¬¬,m÷s©¢›¢ê­º?XAß®R)þ@‡m2½„ŸŸ†a»wï†#Bˆvt×~üñÇ'''§OªÀýû÷¿ûî»Y³f9ÒÍÍ-66V.—3 BÚ¨¨¨3gÎxxxŒ9ræÌ™`kÃÞ½{ Y z°!Ôóøê!Š¢gΜáp8«W¯¶´´üúë¯e2Yxx¸!•™™ÉçógΜهŠÒhÕýÁ¢ú°!¤Xüÿßÿûºm“ébbbÂÃÃçÏŸ?zôèñãÇoذ¡¶¶¶¢¢Bɧ‚ éééR©Ô××·Ï÷ßBú)Ý5„©©©ííííííJ+|ûöí3X¥°gÏ&“ÙÔÔ$‘HÚÚÚ˜LfDD¹ïéíí••<†·µµååå¸sÚƒ aO¡Ú"2xðàãÇ××׋ÅâÊÊJ%Mö6...2™Œ¼Õ³O\hj´êþ`Q}ØR)þ&&&ÕÕÕºm“éN:USSÃçóÁ†íÊÊʳgÏv¹µµ²²²¹¹Ùó=1´Åƒ:Hu »\=²ö@°,’ßNŒ À=ª7FHÖ'"ºˆÔÑÑ¡zèÓðŠû»ü ¬îF VÝ,Š M‹bñï®ö0 ]Öªþe?~œššºuëVèV@ ÿ:üýýE"ÑäÉ“ûÏœ @ †ì&ƒ­ @ @ @ @þ‹¥¥err288ÕÚÚª­£ý QQQ‰¤Ï=ý÷úƒ¢úƒ oPQŠê)zJ“†n„vïÞ½dÉ’¨¨¨)S¦„„„Ü¿œÂ±´´ßÜܼoß¾‰'¾ûî»çÏŸ—Ëå;vì0|[øÝwß/”™™©š¯ÚÚÚË—/›ššêø7((ÈÏÏoäÈ‘«V­’Ëåæææ¶¶¶›6mZ¾|9•ʱ°°0;;»Km×ÖÖ¦§§¦0,_¾\"‘\¼xÑÃÃÃÙÙ™Á`Èd²uëÖ‘³Ð·ŠBÄÍÍ­¥¥%??ßËËËÊÊjÆŒ¡¡¡ñññÔU¤¿ ä˜Y&L®««kkk›={¶ÁÚB*%‹Á`<{ölýúõcƌٽ{·D"Ù´iõ勵¢TãiGGGcdà@}ñ¿ÿ>‹ÅZ¾|¹µµuhh¨@ Ð*ĦžŠBQ”ÐÏ‘#G0 [¹r%ŽMë¬ê‡zE988””””––ÙÙÙ¹¸¸|öÙgýª~ІÉÈÈÈÈȸßT½B%êêê.]¬ÙÛÛ»¹¹èÿgïÜÚ¸ÒÇ?ˆP-^¸„ˆ(ˆ¥ˆT+ µàжÊzYéê¶KUä&ˆõW«–‹Íª©¨¥R¶Þ­1€¸.¶V\A«VQð†Š\„1$„Ìe­óûã<;O¾IÈL.Ôùü¥ÃÉ9ï¼ï¹Ÿ3ï ÃÇçóù÷ïß7³³³³9tèÇÓj`¡PÈáp nœ………‚ˆÅâ{÷îÉåò;wîÈd2E322Èä™››Ëãñ´ê¤½½=--M/Á¼½½ÇŒ£Ç @A0 GFFÒét`,>Ÿ_PP *Øà* ‚ ôôt¥Réïï»nžSÌ)ƒª?< @dd$Š¢jA.É`°±[Xg¤¦¦‚'4-//¯ººš|Ó3^QjÌœ9S,_¼xÑÌÞÔt7…B±gÏ\QgÏžmjj"/¤ 5¸Ò ûÉœœ>Ÿïî>59½PC0L¸» PF1½ð':Ø»wï’%Klmmßzë- Ãd2x¾råÊ+W®`&š››qgEÝÝÝ]]]#FŒ0à•ŒáéÓ§عs'ÇÓü«ÍÛo¿­P( Î?!!aüøñcÆŒ‰¥ÓéÝÝÝñññr¹\ ñk%‰Ôê… IDAT† ößÿþWõ¹›››•••P(ÔK//¯M›6îzýÃ0Õ88]]]íííãÆÃ º¢ •G(‚z«é Ë 2¨¨ìííõí¿ 6aËZ²d Nÿý÷ߢúúúnÞ¼9wîÜ üþûïdÞÔ´Š‚ h×®]†mß¾ÝÌÞÔt7kkk†ñø‘}}}0 ¿ýöÛäó7¹¢ ÝŠrww ÌÈÈhjjÂ[Ÿj‚¡Ð?¨AvðÄGA.—ÓÛÛuìØ1°5 žèøy||¼———““SKK Çc2™ z'AÕðññqvv®­­%ÿ&& Ì»aÆ;v¼|ùRë,ÏÅņáÎÎNòR©QVVvîÜ9'''&“™‘‘áíí­T*/^¼ÈãñÈØ¯µµ•N§Ož<†áôôôÎÎÎÍ›7Óh´‰'BÔÒÒ¢W%0&ú„ZA(ŠâÿtEATUU…aØ7ß|cð;/ƒ&S§N…aØ€æj*ci¶,à6úÁƒx²ÆÆF À¨dò7­¢Ö¯_ïççÇår+++Í<<ènþ%%%ýë_ÝÜÜ`þè£fÏž]VVF^ȨQƒ‚nE-^¼˜N§õçju(ôÆ‚Ÿ¶5ª#!€Éd?xð ¢¢ÂÇLJüÄÙÂÂBó¤Aß­g>Ÿ¯¹ä D¤©©I(ŠD¢’’’¸¸8+++½r^¸p¡D"9þüèÑ£«««<<d³Ù‡Òëõ­­­—ËEQ4++«©©‰|ÆÚÚZ Ü]\\<<<òóó}}}a7nÜóçÏÁ_ 3Á—Îàœ¿¢¢Â€¥3“Éd±X 7\Õƒ®(‚þøãåË—ïÛ·oôèÑÛ·oðà‡ÃquuÕë팔pòäÉööö[·n}õÕW·nÝúôÓOÉ_r3•±t´,KKKµÈ!/^¼€ ÈÚÚš|þ&QA‰‰‰ööö‰‰‰j›ÿC„ .\¾|™Éd†††ZYYíß¿¿®®N¯%ˆ©5”'Ù±±±\.÷Ã?Œ2e ‡ÃÁ‡º¡Ð?XâÿU½,Jþâ¨î¡……ƒÁ˜={ö¾}ûd2™w LESBŠúßVÕ¥K— …§§'ù™ˆÒÓh´þÐô÷[±Xœ’’òÅ_…ÂiÓ¦)ŠÀÀÀýû÷“¿Ý€/ÃÃÃQuss3f霛›‹ HDD„ÚÏWQªbX[[¯^½úÒ¥K(ŠVTT0 ò?7RÕ[£àj®’˜ÊX:ZV^^žñ+B“+((¨³³3##ð+rûöíS;1ø,­ÍĈ¿ýö›\.ÿî»ï>ùä“»wï*Ф¤$½Š0‰¢ ãV„­¨3gÎ(•Êð†áÍ›7#²jÕ*\Ú!Ò?à½,FA‡¦?ÑÑÑQQQøµÂ3B’ôöövttH¥Òââb{{ûÐÐÐÌÌÌòòr’ yóæiê‚Ãá°X,S­ ñ|À݇òòrÿ÷ß¿®®Ždªñðô• ðööv‡±cÇVWW×ÔÔ‚?þ˜Á`tttÌD­t°’ÖK œ´´´ùóç>|øäÉ“jï2¸ŠRãùóç§NÊÉÉÙ±cǦM›¢££“““Ifh€† ;º0•±t´,¹\nmm=jÔ(¹\;88@$•JÉço¼¢FŒñí·ß*Š;vÖ™|ýõ×qqqªOLÍtݺuþþþ©©©{öìéíí-,,ÌÉÉY¿~ýõëׯ_¿NÒ¾&©QF2ЊzöìY__ß¹sçÀ›bVZZ AÐ»ï¾ ¢“BC¦ÀÑãÖ¨ê$ÀšörP ŸÏ‡aØÝݽ¼¼œÌ¯ú› hh_0åyöìÙ寉X,¶µµ0aB^^^___IIÉŒ3,,,Äb±ÙdÄÅÅEFFž={–ÍfVó+JÐfΜ9³qãÆñãÇŠ C­-ëñãÇy{{€NjÒ¤I0 ƒ ®f“íÿø‡»»;‹Å‰D†å0ÐA¼§OŸŽaØáÇÁ\D©T;vlöìÙúÓŸpÇ ¯­(@ð››~u…ðþÿàö^·F{UP{h¼šÛ»žžž‘¿8j†3B[[[µ'ÞÞÞ]]]wïÞ5[3‰DŽŽŽ®®®×®]Ã0¬°°ÐÓÓÓÁÁ¡­­M_ªªªRSS1@Œ‹UTT´aÃÍ5ÊPP”&à2‘¾™  6a˺pá‹/ñyd@@€T*Ì8©ÉâããyïÞ=.—;d£ºwuuÑh4üɘ1c`&¿ó†pþüùžžžÕ«Wã5 x())5jhöf¥¿3Â7n$%%Íš5ËÎÎÎ××7==Aò—QMŽÖ½ïäää#GŽØÙÙÍœ9óèÑ£‚l߾ݜ™;vìÉdàPgäÈ‘"‘Að…^Y|#þüùB¡°°°°¿Óé¡ ¨´´´„„„9sæŒ;vÒ¤IkÖ¬©­­­¬¬d2™f“Aõƒz#³2ØX„- †á#GŽ…•+W2Œ-[¶(Š„„sëâÅ‹‰dæÌ™CÄ÷¦Öæ?{öl±Xœ——÷á‡:::._¾¼ªªêÑ£GƒrÛe(ß…axÿþýmmmÑÑÑŽŽŽaaaÍÍÍ—.]ÂÏ¡‡Bÿ0Èô7nÛ¶­¸¸X Èår‘HT\\Ìb±ÌìWB­^ºtéåË—Çp‘HtóæÍèèh3 ¢(øj<¹xñ¢R©pßB*œ:uJ©T*•JµO6Ùl6¨ÊCAQ‡ª©©‘H$ …¢£££ªªêèÑ£à›9³aÂÐ`È´¬áǧ¦¦644Èd²ªª*37½©S§*Š®®.A†‚ M¨ÿþ}Á‚yyyÀ)kMM ‡Ã1sÂÊ!A4m×®]<O&“ñù|‡ãèèˆÿu(ôj˜[‰@eš»©ànTp˜1ˆ›$ZåÄgå@ÎAÜ•R=(×¥z{{Ͷ«Ðß-üìa((Jk2À¿Œ‘2Ðh4sšF« dZžÌüÆUZëŸTë¹9鯛R­ØƒR£p†BÕ‚úW¤³F …þ‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚‚bÀa0ÙÙÙà ’ÖÖÖãÇ¿AQêCrr²\.ô>CAQCA†W‚¡ ¨¡ ÅPÃ܃ÐÖ­[ƒ‚‚’““§M›£ÕGŸ‹‹K}}½B¡0§Sáîîž““ÓÜÜÜÞÞ^ZZeØH×àóù'OžÔúUVQQѵk×ÌüyrTTÔ“'Oòòò4˽s玚 ü7 +Ãåíí-“É4Ã8ö·a2@ôý÷ßËårP®T*mhh8{öìG}dæ>ú“O>ÉÏÏonnnkk»ÿþš5kÔ acc“žž>$///7ÌRŠ‚ èƒ>8yòdMMMGGG[[[}}ýåË—§OŸ®¯® –Ïçk­0—/_,Xƒ—Ëñèq«k>!äöíÛ œ“êw¾ªœ¿  7X=§¦¦‚'4-//|üKÈŠJOOW*•þþþ¸GàZ…ükš°ÂfΜ)‹/^¼8¸¾Á(L‚a˜p8x/¢OàOt°wïÞ%K–ØÚÚ¾õÖ[†Éd2ð|åÊ•W®\ÁwG¶oß^\\l@,…¡ÀôéÓûúúòóó®À¿çÍ›·dÉ’sçΑy£„„„ñãÇ3&66–N§wwwÇÇÇËår@@æç"‘( `ذaj¾ÝÜܬ¬¬ô ¼àååµiÓ¦ÌÌL…B¡×!zúôévîÜÉãñ4ÿjccóöÛo-Ž‘Š2 ¦•8šÁìííõ• 6†aYYY¸À]]]íííãÆÃ,Y²„N§ÿþûïx­¾yóæÜ¹s,Xðûï¿›¡VCÿ‹ã# 863y…Ùµk†aÛ·o×t0–œœ~ðàÁ={öPžÃ^ ôÃþÁår ÃïåååääÔÒÒÂãñ˜L¦ƒƒƒƒƒƒê(AÐÎ;mmm·nÝj@¸áÜÜ\µ3'@JJŠÙ6.h4ZOOÏ‹/ð'‰Ã0ò‘—ËÊÊÎ;çääÄd2322¼½½•JåÅ‹ñÈ^ºimm¥Óé“'O†a8==½³³D¥˜8q"A---zµyƒ#@´aÆ;v¼|ùRë|ÙÅņáÎÎNÃ2‡ŒV”I¦N ð½³1ÆR+ËÁÁEQü¿À¯ôƒðd†QÉäo¼¢ªªª0 ûæ›o ~GÓkýúõ~~~\.·²²Róç4M¯=vŠWüDF£ág„ÙÙÙ$­Þ_ô ‚-Z$“ɶmÛfaaqðàA}·F-,,47ñõ=y2’¤¤$Eð<ùá‡È‹±páB‰DrþüùÑ£GWWW744xxxìq‚ƒƒQ †aøÎ;ÍÍÍ NEXXŠ¢ ù× EQÔÅÅ…üO4ÑêŸ>00A¦¦&¡P(‰JJJââ⬬¬ôÊÙE©bŒ##eÀ·F‡ æáá±nݺúúúšštncA´bÅ EÓÓÓñ›ŸŸ.˜àiüýýùñÇÍS«!²²²*((@Q´´´4!!aìØ±z½”IdÀqqqihh(++>|¸Ö` ¤_!ô3•êr°¯¯oíÚµÑÑÑÑÑÑÆ{ˆ1bÛ‘’’ÒÛÛk@í4C`^B222 Åž={\]]Y,VHHF{þü9ùL¬­­—ËEQ4++«©©‰|À³ÚÚZ Ü]\\<<<òóó}}}a7nÜóçÏÁ_ 3Á×Ö¤Ñh&_[WVV;vŒÍfûùù?|øÍf:tH¯üQ”©0‰ 'Ožloo¿uëÖW_}uëÖ­O?ý”üFÓ‹Éd²X,Þp,--Õb/ƒ=ò'ßÑŠúã?–/_¾o߾ѣGoß¾ýÁƒÇÕÕ•|ÆË€“˜˜hooŸ˜˜¨vÓ××g枇Â|€Û1ZŸ¿"LNNîèèøÓŸþ†ÀC‡ Êe™}ûö©í¯ÆÄÄïP`ž;wî•+WZZZ$ɵk×¶mÛ†¢è¦M›ôÊߦÑhzíÃ0,‹SRR¾øâ ¡P8mÚ4…B¸ÿ~ò·ðµuxx8Š¢nnnƬ­uD,ïöô.]º¤P(Èï!CÆ)JcV„FÊ zkl¦áj!‰i•››‹ HDD„êÏóòòŒ_šÄX4ÍÚÚzõêÕ—.]BQ´¢¢‚Á`ÿ¹Id êììÌÈÈ v>_'È^–£ ‡ÃK ° är¹ >EEE³(ô÷÷ŒŒÌÌÌ,..6øp%77wÞ¼yš5›Ãá°X,’³³¯¿þ:..Nõ c †Ý¼yóöíÛxœ­-[¶@¤×9„j 6}'•†µ··;88Œ;¶ººº¦¦F |üñÇ £££ƒd&j¥ƒ¥¶^b5pñ¡¼¼Üßßÿý÷߯««#™ƒ1Š2&‘hذšoBc¥¥¥ÍŸ?ÿðáÃ'OžT}¹\nmm=jÔ(¹\ž888@$•JÉgnEõõõ=þüÔ©S999;vìØ´iStttrr2É —aĈß~û­B¡Ø±cÇ J¤ ô¸5ª:Æ€J€?4²N,[¶ÌÚÚú‹/¾ˆ‰‰OÀd­®®N.—{xxiÛýÍèõÉôJ¬µP¢3fÌhoo/,,4Û ±Xlkk;a„¼¼¼¾¾¾’’’3fXXXˆÅbó``~ýìÙ³Áä %...22òìÙ³l6[­9?~ü‚ ooï‚‚P'MšÃ0¸àj~QA;sæÌÆÇo΢ÿñ¸»»³X,‘HdÎr)=nöª öÐH!X,–Ãÿø×¿þ…a˜——ÉQg„jÌ;wΜ9gÏž5§ "‘ÈÑÑÑÕÕõÚµk†zzz:88ðEJUUUjj*‚ &ÒÖÖV퉷·wWW×Ý»w_ÅÏf†Æ+$$„ÅbmذA³¹]¸páÅ‹øD3 @*•‚ f¬Ü†n~éûE1øøøDFFÞ»wËåRçF¡ãÖ¨*ƒuFh<Ë–-›0a¤I“6nÜØØØxíڵѣG›S€;vÈd²ÆÆFp¨3räH‘H„ øŽB¯¬Œ¹‘£õŒ099ùÈ‘#vvv3gÎ[&ÉíÛ·7lØ™™9jÔ¨?þøƒÏçÇÇÇgeeQmƒ1ØXkÖ¬5j”Occ£êó½{÷&%%õõõa×Ýݽk×®ˆÅâ~ø!--ÍœÆ6lXdd$øÆ¦§§§½½½¨¨èÇ”H$æ`êÔ©þþþ–––W¯^UÓ³T*õôôTÝóòòR*•ùùùÔö…v€K6ÂdàC3Ècrð[|à ù^4U• D¬É©V‹ƒû{ƒ®+¨lƒ¢ŸA,‡ä¸àZÜ` /]µÂ˜SoªÎiÕP«Þnnnø×,f‚‚‚‚‚b¨.•J½¼¼¨}Q Š7‘¡°Ê§                            J0Œììl>Ÿ/“ÉZ[[?þZ^2NNN–Ëåƒòöb(èa(ÈðJ`EA‹bP0÷ ´uëÖ   äääiÓ¦ÅÄÄܸqÿæôÎ;j‘6nÜhÎaòûï¿—Ëå h©TÚÐÐpöìÙ>úÈ€6 ¼õ“¦àóù'OžÔúeQQѵk×Ìæðþ“O>ÉÏÏonnnkk»ÿþš5k 3„azðöö–Édš1– E}}½¾J0L‚ø|¾V._¾lþÈQQQOž<ÉËËë¯h„¬¨ÒÒR¼åJ¥Ò¦¦¦ëׯk­3„Eô—€Á`ìÙ³§¤¤D"‘…Âââb½ÂÂPP˜<¯j3ÓúP7·oß®¨¨áœ`VcjkkÏž=kee5(1u¡ÿçÝwßŽŽ®««‰D~~~$Ǩ¨¨;;»+V bkkëââ²nݺåË—“Éáþýûׯ_תÌÚÚÚÓ§O›§ÿ]¾|¹\.ÿå—_<<<¸\®B¡ %?!0Rª/ïÞ½EÑÏ?ÿTd Òüt:%%EѨ¨(3×̤¤$0Òh hE&ŒWÔÇ«««AËe2™ .¼zõªB¡ˆˆˆ9A˜àرcÍÍÍl6{òäÉS¦L9qâ‚ ±±±ÔXHaV233étº……—Ë- fþAð‡„ðx¼þ| …B‡3ˆ5[Õñ#ð܉¢èHJUXXˆ ˆX,¾wïž\.¿sçŽL&CQ4##ƒL¹¹¹<O«rÚÛÛÓÒÒôRŽ··wbbâ˜1cÈÿÃpdd$Nz°±±áóùä{X#õ ŠÁŽ@M(`æÌ™b±øâÅ‹föy” È¡C‡x<žÖqŽ0nŒWñraöóóC$''<$,‚0Áĉ}}}AP†‡Îçóïß¿O¤0 d›tTTp-ˆ· ¢O¨>ì½{÷.Y²ÄÖÖö­·ÞÂ0L&“ç+W®¼rå †a666o¿ý¶B¡0ð=L ðÜÍØÛÛ“ì…Æ?fÌ˜ØØX:ÞÝÝ/—˯ƒ"‘( `ذaj‘¯ÝÜܬ¬¬ôu´ïååµiÓ¦ÌÌL}µŠaXVV.pWWW{{û¸qãÈç`¤L‚Éeصk†aÛ·o7s º§OŸ8p`çÎ<ϰº1¹¢0 ÂÓ§OA„E&ÍÍ͸<ÝÝÝ]]]#FŒÐ,=999<<üàÁƒ{öì¡\×RD0L`#4&&Æ€Ž >>ÞËËËÉÉ©¥¥…Çã1™Ln Œ‚¹¸¸À0ÜÙÙ©oÎ8¹¹¹jGŒ€””ƒW™S§N…a˜|PVVvîÜ9'''&“™‘‘áíí­T*/^¼H20okk+NŸ>>š À@HRè…Õl„P «¬¬tèùâL˜÷äÉ“ííí·nÝúꫯnݺõé§ŸêuÎÚÚZ p¹\E³²²šššú ó¦Imm-†aÎÎÎ...ùùù¾¾¾0 7îùóç௄™à+càÿ¾¢¢Â˜•1“Éd±X 7½4iŒL…©dHLL´··OLLTÛ²~m0^Q­­­`›ÇÃÃ#$$ÄÚÚú×_]°`>PAF†úúúºº:‡ÓÝÝÍf³=z¤Ù"úúú77ÅëŒæBд+B‚ð¸*`OïÒ¥K …ÂÓÓÓl_©Þ58Ô 0~ÖÐäs€aX,§¤¤|ñÅB¡pÚ´i …"00pÿþýª—tƒ¯ŒÃÃÃQuss3æ nnn.‚ õ5Xª³"4‰ AAA†í¶íÛ·OmÇÞà{ÿ·"4RQš—eÜÝÝÅbqQQ‘êCÝE‘Á‚Á`Ìž={ß¾}2™Œü-6 Ý=T Ñh\.Ã0üŒ0** ¿äiØÁ¡ø$\T)//÷÷÷ÿý÷ëêêÈü<77wÞ¼yš‡Ãá°X,ò3D°²4øÃ0\úNK1 koowpp;vluuuMM@ øøã FGGÉLÔJ¯£—8iiióçÏ?|øðÉ“' xƒõ`*Œ—aĈß~û­B¡Ø±c‡a5üë¯¿Ž‹‹S}Ò××7ÔÖ+¦5†aB¡Puo“°22ôöövttH¥Òââb{{ûÐÐÐÌÌL<5…ÁèqkÔiÕʺvíZµ‡&Ì%Ÿ={F2}‹†!Øïè@,ÛÚÚN˜0!//¯¯¯¯¤¤dÆŒb±ØÌ’ÄÅÅEFFž={–Íf›ùžäÐáÿø‡»»;‹Å‰D†åðjU?SaØÀÔ‰2ŸÏKÏòòò(…âB[£½½½j¢Ö‡†akk«öÄÛÛ»««ëîÝ»$§{¦:#\Ží„» IDATD"‘£££««ëµk×0 +,,ôôôtpphkkÓwÚ[UU•ššŠ ˆb„„„°X¬¢¢¢ 6¼ |Õñññ‰ŒŒ¼wï—Ë}µjÑ ãáááìì\WWgªµšæy¡§§'AZ/ŽRPèËPÙaß²eË‘#GìììfΜyôèÑ>øàèÑ£CçËBó  ßyç¹\^\\ŒaØo¿ýÃðøñã X‘TTT|÷Ýwz}ö˜?~rr2Ç[³fMww·¾?mؽ{·……›Í~c§`cc³`Á‚Ÿ~úÉÒÒòÀ¦š@üúë¯III³fͲ³³óõõMOO üõ×_5¿ñ8}útgg'¸zm’¢)ÞÌê#C·oßÞ°aCffæ¨Q£þøã>ŸŸ••õ¦ÍÄ[ZZèt:~ì¡T*=z4gÎ}?"„þ·ƒd€ kÖ¬5j”Occ£êó½{÷&%%½!™:uª¿¿¿¥¥åÕ«WÕÔ(•J===ߨíb­L˜0÷’ñßÿþ·¾¾>&&&77×T+Âk×®-]ºtÕªU#GŽ|þüykkkrrò?þ¨i///¥R™ŸŸOR ]€K6ÍçàÎ~ãÜØ4³là ¤ÁH7›ª*:1§TÆ‘iBË(ªþNÕ¬µûk;ä šÆàKÂý毵6º¹¹á™°t ŠWƒððp©TêååEí‹RPPPP¼‰ …M Šÿ ƒÁÈÎÎæóù2™¬µµõøñãoæEçääd¹\n˜/é7 3(в`(¨š²Å `îAhëÖ­AAAÉÉÉÓ¦M‹‰‰¹qã†êw¯L&3--­¼¼\,wttìÞ½ÛÌä»»{NNNsss{{{iiiTT”š„ HÒÞÞnii©W€'‚ø|þÉ“'µ~+VTTtíÚ53FõäÉ“¼¼¼þÊ%L@HŠ*--Å£:H¥Ò¦¦¦ëׯ¯Y³Æsf À|pòäÉšššŽŽŽ¶¶¶úúúË—/OŸ>Ýlý8ƒÁسgOII‰D" …ÅÅÅG·0XämAX„ŽŸ|òI~~~sss[[Ûýû÷ ³5…VÈz–ár¹ ÚEGGošOÈ0cÆŒÖÖÖ¬¬¬žžàHÝÜÜ~ùå ‹ƒØØØL˜0Áœî!ìììrrr† öÕW_UTT¬]»ö‡~a7€;„DEE=þüòåËb±ð††† &,Z´¨££ã?ÿùáËÊd²qãÆiýƒÁ¨¨¨Ð÷•!))iýúõÀ‚a t@¨( ‹¶¶6__ßÞÞ^{{û÷ß?>>>55µ¯¯ïĉdª‘¶€ È××÷Ì™3­­­qqq>?~üŒ3|||ªªªÌVo¿ûî»?ÿùÏ\.÷Ì™34í›o¾IIIyûí·ÓÓÓÍS'!"´a„ –/_~üøñ‚‚‚°°°ööö-[¶¤¦¦öôôüë_ÿ¢<ÈP˜ÌÌL:®¡øz ‰Àãñú‹G˜““ÃçóÝÝÝÁø ð™·GbccùüóÏ4íüùó?¶¶¶&™€ÂÂBAÄbñ½{÷ärù;wd2Š¢d¦·¹¹¹<O«öÚÛÛÓÒÒÌ6GÎÎÎFäСC<Ok <º!T”f '÷îÝ»dÉ[[Û·Þz Ã0Ü-áÊ•+¯\¹‚a˜»»{```FFFSSÈÙü½éÓ§÷õõåççÀ¿çÍ›·dÉ’sçÎaF˜€°ˆ„„„ñãÇ3&66–N§wwwÇÇÇËår@@æç"‘( `ذaj¡ÒÝÜܬ¬¬„B¡¡¯®7OŸ>=pàÀÎ;y<ža t£¯¢0 5óéÓ§$kŽ‘¶€ hĈ …B¼Æ\i½¼¼6mÚ”™™©¯—y@ÐÜÜŒ—ÛÝÝÝÕÕ#‰ñzPCÓ„E&À0,++ —§«««½½]ëîHrrrxxøÁƒ÷ìÙó†øÅ¥0=Â0q¹ÜÌÌLÃbðÆÇÇ{yy999µ´´ðx<&“éàààààFA‚/^L§Ó‹ŠŠ ®»¹¹¹j¡À)))$'¶4­§§çÅ‹ø‰D‚a˜§§'8[wBÊÊÊÎ;çääÄd2322¼½½•JåÅ‹5èk¥µµ•N§Ož<†áôôôÎÎÎÍ›7Óh´‰'Bd€cnƒÙ°aÃŽ;^¾|ii©}.E˜@7z)jÔ¨Ql6[*•þôÓO$•`¤- [ ß|óñ q°š4ì·ªÒúøø8;;ëœÈx=¨¢Õ„E‘AM­‘U€sj¥H1P€½P|k ïÖhuuµÖ­Ñƒ*•ÊÈÈÈââb‰DÒÚÚzîܹ©S§’ß5ÞUtRRŠ¢x¡à 8$“€ .”H$çÏŸ=ztuuuCCƒj oÝ£( BÌܹs§¹¹ùÌ™3aaa(ŠN›6Íüwíø|¾îOÂý¡[Q>T*•øtAË—/{{{ë5œc ‚¬¬¬ P---MHH;v¬¾ïˆŠ¢¨‹‹‹Á90™ÌàààTTTøøøèUŒÔ[¡— +V¬@Q4==]ÓÜ` ¤îÑPè…Õ„á NGbcc¹\î‡~;eʇceeE2ãófdd(Š={ö¸ºº²X¬öüùs’ È`mm-¸\.Š¢YYYMMMšAGû£¶¶Ã0gggüü|___†Ç÷üùsðWò’ qÕÚÚ ¶<<þøcƒÑÑÑA>Ÿ¯¿þ:..NõI__ßP›Dë¥( Ã…B¡^{zÆØ§¯¯ïùóç§NÊÉÉÙ±cǦM›¢££“““Éd¨V:ØÕ0@†ÞÞÞŽŽ©TZ\\loo𙙉‡w&Ä$zPÍMÓ„E”!--mþüù‡>yòäP«±¯.zÜuZmÄo“‰@ €aØÍÍ TôºùAPÞ(ôêâU[#A3fÌhoo/,,T=±×` ‹Å¶¶¶&LÈËËëëë+))™1c†……ø(“$CpØ3 ÃñpTŒ3gÎlܸqüøñƒ%†a|>¬ÉÊËËE hÀlyöìY6›=ÓqŠ7=nöööjV>Sõ§çÏŸïééY½z5>˜ùùùÁ0\RRBrŒ1þŒP¹sçΙ3çìÙ³ýå@˜` ‰DŽŽŽ®®®×®]Ã0¬°°ÐÓÓÓÁÁ¡­­íu: 4gg纺ºAÔ¸¯dÀw,UUU©©©‚èûC̓4OOO‚ôº8jrÂ!!!,«¨¨hÆ †­›)(† ýÂ0¼ÿþ¶¶¶èèhGGǰ°°æææK—.vùÞ`–-[6a„I“&mܸ±±±ñÚµk£GÖ+Á@³cÇ™LÖØØ43räH‘H„ øŽÂœ’îŒP7ªçR666 ,(,,ììì4§›Ê´´´„„„9sæŒ;vÒ¤IkÖ¬©­­­¬¬d2™úfeðç7nÜHJJš5k–¯¯ozz:‚ jW»3ØbþüùB¡°°°ðÏéÓ§;;;ÁÍj“MAazú!¢Ñh»víâñx2™ŒÏçs8GGG3‹÷ïÿ[&“‰ÅâÒÒÒ;wÚØØè›` ‰ˆˆ@Q|5ž\¼xQ©T._¾|PZþ „ªWöÛÚÚ ?ûì3sÎ:TSS#‘H EGGGUUÕÑ£Gßyç³ AжmÛŠ‹‹\.‰DÅÅÅ,ËÌÓG3ØâÔ©SJ¥Rµ›ÍV+¥ªªª¹¹ù­·Þ2UѦÇÂÂBGŸn‹ïae}ƒßâëO Ãjß ‘kþ«Û d\®Ú£†Ýù4¼ºªV‰¡ ƒ9€Ìb ’_ »¹¹áߢ˜°t ŠWƒððp©TêååEí‹RPPPP¼‰·2Ô(HAAAAAAAAAAAAAAAAAAAAAAAAAAAA1”`0ÙÙÙ|>_&“µ¶¶?~œºè<@$''ËåòýÀœ°3Èð†@i’‚bà0÷ ´uëÖ   äääiÓ¦ÅÄÄܸq8a®(4Ãê:tÈü#eTTÔ“'Oòòò4?€³±±IOOohhèèè(//߸q£šxfH@’öövKKËÖÖV}XZZŠÛB*•655]¿~}Íš5šb¡#Á'Ÿ|’ŸŸßÜÜÜÖÖvÿþ}­ù›&“™––V^^.‹;::vïÞ­&†î¯“52æÖ¡jÂþÁ`ìÙ³§¤¤D"‘…ÂââbƒªPPô O¯tIëCÝܾ}»¢¢‚N§CÃ0>½Õü`öË/¿DQ4$$ÄÌSत$Ðä´úCár¹Ož< srrÚºu«\._·nj{3CÝDEE…„„ØÙÙ­X±A[[[—uëÖ‘w=ŸïîîŽK¥66èNðzX“<«šŒ¹ m¡†Zÿ0qâD___àцááÇóùüû÷ï›Óç*Å«‹3ÓžžÕõk×®OÈ„­ß»wo]]]GGÇ„ Þ{ï=™Lv6-Z¤µºÏž={úôé.\0s´ §OŸ8p`Ó¦MZà%K–ÐéôßÿHÕ××wóæÍñãÇ㑸̀„„„5kÖlß¾ÝÆÆ†N§wwwÇÇǯ^½zïÞ½†…À0 Ø÷éÓ§ Â"`–••ÕÓÓ"uuuµ··7Îñ¼¼¼6mÚ4räH}èîîxöìÙ¦¦& m ù¯‡5Éc°ª ÍM¨j54û@ððáÃÞÞ^ðÃîîî®®.­¡Ü’““Åbñ¶mÛ¨Å"Ža˜ÀF(˜¯‚\.—0Zo||¼———““SKK Çc2™W®\ÑZÝ###ûúú²²²È·ÕÜÜ\­§)))äkü† vìØñòåK­!ð§üàÁ\ªÆÆF æN ú53$ ¤¬¬ìܹsNNNL&3##ÃÛÛ[©T^¼xQ¯èÁ8£F `³ÙR©ô§Ÿ~9AF5aPÕW<Ȉ¸ ‹/¦ÓéEEEýM¶¼Ö$Áª†ˆÌM¨j5´öªÿöññqvvÖ‹ xŸ¡VŠªèQ­×®]}ôèQµ:D£Ñ«/g¢ˆa† ÔÚ ÆÂ… ïÞ½[__O¾­þýïg0 OË©#±½½ýóçÏUƒÆ¸ðxØ3$ ð?ÿùÏ_~ùåíÛ·%É?üàîîNòç€ &€U{sss^^AÁÁÁ>Ä×sº‹ÐW†+V0Œââbs†|÷Ýwaf0wïÞ•H$­­­çÎS¢¼Ö4?šæ&Tµ*ºû&“ÌápD"Ñž={4›3‹Å;vìwß}÷úŦ¦0=B0˜©M É,õ%""bäÈ‘?ÿü³^Ùš<0¯&–––jA_¼xAµµµÙÁÚÚZ p¹\E³²²ššš£¸©ÑÚÚ Ví!!!ÖÖÖ¿þú«ê†aäe`2™,  o,|„¨¨¨ÐwœuÅÆÆr¹Ü?ü066vÊ”)ÇÊÊŠd‚ׯšº1^Õªh57¡ªUÑÑ?Ô×××ÕÕq8œîîn6›ýèÑ#Í‘²¯¯Ï´ÝÅ~FõŽ(¸/£W>:ââ”””˜ÿšŒZ£èååå[ìøA~üñGÐ#˜!`Æãà€0=zÝÔ¼^áîî.‹‹ŠŠTê.‚¼ ¹¹¹‚DDDèÕ«â×ÃÃÃQussÓ—GgΜQ*•!!!à¥`Þ¼y3‚ «V­¢&xm¬©ãU­ŠVsªZýƒ……ƒÁ˜={ö¾}ûd2Ù¨ƒ@ 2lh4—ËÅ0 _ÿQÃá€9Wtt´IÖ…AAAîîîGß)[nnî¼yó4› ‡ÃÑkwTr¹ÜÚÚzÔ¨Qr¹|øäÉ“z‰ª–9¾ñNžgÏžõõõ;wd…aXii)ô¿m: ü6ÖÔñªÆéÏÜ„ªÆSêîz{{;::¤Riqq±½½}hhhfffyyù`mS¼*£¢¢@³Á[ÅÚµkU’©vGCBBz{{õº&èÏé†îc?½xüø1AÞÞÞ@¼I“&Á0\SSþk†ƒ†a¯työìY6›mÚÝu2†ÝÜÜð‹'j— PÖÔ æ&T5™þ\åóù`ù[^^nÚ¡xýÐãÖ(øRBó‰Úscpssûè£ô½&0Ãá… ^¼xˆ¸R©ôÚµk@Z3$<<<œëêêL(CHH‹Å***Ú°aƒÁ+ ‚ªªªRSSU/¤äüùó===«W¯ÆUíççÃpII xMÂoš5 V5DdnBUtôšç¦žžži½8JA1Èè>#üî»ïÅ›Œ&ZÏa>räˆP(\¹r%ƒÁزe‹B¡HHHÀ'×fH`TO•lll,X\™ÐÑåüùó…Baaa¡¾÷>41øN? Ãû÷ïokk‹ŽŽvtt knn¾té~øD&ÁeMƒUMhnBUtô7nÜHJJš5k–¯¯ozz:‚ Z}œ>}º³³388xÐ;Š7!Nçñxƒ~M u „ høðá©©© 2™¬ªªŠÅb©Ik†ÍÇ•J%þ!f[[[aaágŸ}fÂîûÔ©SJ¥Rµ›Í6ç A£ÑvíÚÅãñd2ŸÏçp8ŽŽŽz% ¬I2æ&TµîþaÛ¶mÅÅÅ@.—‹D¢âââþT]UUÕÜÜüÖ[o Ä›R¼¢˜{N†–þ¶RuÿÕœè„F£7Nà(BsëÕ Í{‰@îæõwõÑ„º$¡¬9(2ÔÌM¨(2­ü·¿ÜÜÜ¿  €ülÇÛÛ;11„<Õ‹‰'úúúo 0 >œÏçß¿—0—/_nhhxûí·U …B‡Ó_3óöö–Éd©©© O–——§ª|BUM¡¹Éc°-ÈÔ‡œœ>ŸïîîŽW!Ý«ZÃ1‰5³³³9tèÇÓ ­i†¦‚L'Fù^n€X¿~=Š¢ºB -à}¾Ô|¢ƒææf…B¡êoÿwbb"FÛ»wo]]]GGGWW—ªOÂE‹i5ÕìÙ³;;; ‹‘m0j=#A¼CŸ9sæßþö·¨¨(§T*¯^½ôÞ{ï· LAÚûÞ½{·®®Î€6³zõj…BáââbÀ›ªÉðèÑ#µ'L€óÁtvvª…¢µ±±Ñâ|Û¶m(Š.\¸/(>>^í‰nȨZ7„æ& m¡VÜÝÝe2YJJ É¢µáiM‚>¼{÷nKKËÇk„„Ö4Cœääd±X¼mÛ6}H؉æ@¦—;þü… œ³³³A{{{EEE@@H`ccÃb±nܸÑÔÔ$•J³³³'L˜ VЊ+®\¹ÒÒÒ¶ô¯^½ ¢y@täÈ‘êêjAºººÁeP¥=z´¥¥E&“)úñÿÎ;ïœ8q¢±±Q*•ÖÔÔüóŸÿ´±±Áÿš]ZZQ\\,‘HZZZ~ÿýwüîîîYYY?îèèwïÞ%o@––9r¤³³“ÅbÿþòË/7oÞÕÒÄ‹%°ª’^óI€=‰D²yóæaÆ͚5 AÅ‹Óétð ô¶¥¥euuuqq1¾cÖ_Ÿuüøq™L6eÊò3šÜÜ\­‡%äGSÕžqÔ¨Q`v\¶lÙ¤I“bbbZZZrssqN:¥P(Z[[7mÚ4iÒ¤… VVVÖÖÖÚÚÚª¾EUUÕâÅ‹œœ–,Y’žžNR7oÞÄÏ¡oݺ%‘Hþýïƒÿ–——gffÒh4U!M¼êTÝÕ|¢ƒiÓ¦!²téR†CBB;v¬f2Ýqš C(æååé5$Nî IDATÔk–h=šÒš#A._¾ìíí­šÃÂ… %ÉùóçG]]]ÝÐР œ0*+V¬@Q”|QÅøÎ—Éd?xð ¢¢ÂÇÇGSHÂÀRgΜQ³T`` ‚ MMMB¡P$•””ÄÅÅ©ËçççƒK.øA4×":ÐKÕš17IL5jÖ‡ƒ*•ÊÈÈH0ûnmm=wîÜÔ©Sµ¾¦î†c°5UÑ:ZÓ p@/oØNÉNŒ½Ü… P¡3ÀdN-™……>Ÿ£Ñh¿ýö[SSþâãÇ7ž† †ÏÎ5 JJJ"Ü]µj•Öpß¾}(Š1h4Z||<‚ ‘‘‘ %6òý÷ßã¯ðõ×_£(ºråJPœƒƒCggç‘#G€`@Bò9~üxee¥………D"ùùçŸËÊÊ,,,F%“ÉÀÔGUH2yêQ@$^Õ|5ŸèÌ"=z„aØÄ‰;;;;::È—®JDDÄÈ‘#þùg½âT˜$rokk+“Étppððð ±¶¶þõ×_,X€×'kkk@ÀårQÍÊÊjjjR‹ÁF˜‡Éd²X,…BqðàAòBâ ߃Òh´ŠŠ }¾€úúúºº:‡ÓÝÝÍf³áôJAPTTÔÈ‘#Oœ8¡f©ÊÊÊcÇŽ±Ùl??¿ààà‡²ÙlÕ À–––já[_¼xAµµ5ùW ¯êþ 4·nLe €Öúv´bcc¹\î‡~;eʇ£õ²ŸŽ†cŒ5 !´¦àôõõ¯Û„˜`þ÷¿ÿýòåKCCMÛ½½½xð¾¾>±Xloo?bÄð×%K–Œ9òüùóàçiæ`$sæÌinn¾{÷.£¯¯/;;‚ µaõâÅ‹½½½à†a... T*mkk[¼xñÿûÿÏÆÆHHÞ"<oܸq£G°°°ÈËË›8q¢ƒƒÃ¬Y³,--~ü‚ ooo¼6Oš4 †áššózŒ3@æ&DG}0 »¹¹áŠÂwÉÔ ÓpLeM5­i†FbÚNÌ`ÂÃÃi4ÚªU«Ž?^RR"‰FŽ©š@(B4~üxÝÀ1:‘H$jG cäÈ‘"‘ˆ|&`’ú¯ýkÙ²eK—.×SI]/^¼hiiquu}çw*++1 {üøñäÉ“]]]ëëëÁ«i ©²MªÚ[óIôööÂ0œ?¾§§gõêÕ¸¢ÀEù’’U!u4ã­I¡5ÍÀHL؉ƒ¥¥eWWWKK 8Ÿc2™j£.]ºÔÝݤ{P‹ZµAIRXXèââ2{öl¼àœáêÕ«úª ‡÷îÝ«¬¬´µµ%¿†{üø±««ëøñã‹‹‹1 «®®ž8qâ¸qãjjjúrH0sæLAþüç?Ã0-“É4»B€î3Âï¾ûÎÌÞdTQ=4²±±Y°`ð_eB?–óçÏ …………ú^ëМ½ðÃ7n$%%Íš5ËÎÎÎ××7==AÕ»Á„ Ú¿¿\.ïχSrrò‘#GìììfΜyôèQA¶oߎ Ãð‘#G„BáÊ•+ Æ–-[úû¤ià0¡¹ ¶a}€axÿþýmmmÑÑÑŽŽŽaaaÍÍÍ—.]R;dÒÑpŒ·¦*ZÏ ­i†8§OŸîìì Ö׈ä;1BtŸ>yò¤¿3½{÷¢(çèèøÑG]¹rE"‘¨ž‚O† Å©S§ÆÎÿô§?©¾ïôéÓ%I~~þ¤I“&Ož¬é'êÿŒÉd>|ø°¼¼<((h„ ÍÍÍ—/_Æ¿£g„ª¯ vFø×¿þ5///,,lüøñNNN‘‘‘"‘èüùóäô¾ùæ¡PøäÉPè¢E‹:::är9~‘MUÈ!4FFFJ¥ÒÑ£GC´wïÞGõ÷Î:ªNçñxƒrM vŸ¾­­­°°ð³Ï>3aï êj)6›m¶1`Û¶mÅÅÅ@.—‹D¢ââbp™›|‚Q£F555?¾?K-]ºôòåËÀé°H$ºyóftt´Zâáǧ¦¦644Èd²ªª*µ"Ì€ÌM™ú@£ÑvíÚÅãñd2ŸÏçp8ª÷ ¢†c¼5UÑ:B$¬i†€ªªªæææ·Þz‹ð]Ô ß‰bð@8ḟN}}ý‘#G¢¢¢PUýžF£EFF>yòD&“555]¾|yòäɪã Ãeeeíííb±¸´´æÓO?mhh‰D …|tßÖÖÆçóU«Ü¤I“Nœ8ÑÔÔ$“Éêêêöï߯:' §NzñâE>Ÿ/—Ë%IeeezzºZ¥ÕÍÂ… ÁÞ¾ýöÛ‰¤££Ü”Q’L½5ÓP ¾·;àº`û àÅ ûë@£y휩˜p³®¿›}}}}Ž ¤zý¼&ù‘¥ðÈDkªõ—`@1ƒ¹  V¥ÃÆ[Sß‚ 6·ñ ÜÜÜô?¿ øŸ²³³¿üòËœœœ¶¶¶“S7$ß‚ooïÄÄDU÷Nú2Њèú@AAñ G&àg]õ‡Ëå~ñÅdÖ‚ÍÍÍ …"88xêÔ©2™L¡P,Y²D&“%&&Òh´S§NÝ¿íÚµ÷ïßïèèhnnÎÎÎvrrÂsÈÎÎëüÉÒ¥Ke2îïÈ‘#ÕÕÕ{öì¡Ñh999 2¸B¡Pí¦ÝÝݳ²²?~ÜÑÑ!îÞ½»mÛ6½¥ÚÛÛ1 a©åryOOOKK Þ}ïÝ»·®®®££c„ ï½÷xS…B±hÑ"|kîéÓ§Ø´iÓ`yL%| òxyymÚ´I- Ì (2õáwÞ9qâDcc£T*­©©ùç?ÿicc£W)$kTrr²X,Ö·²QPP 9¸\nff¦êúĦ'¡æ–H$›7o6lجY³Y¼x1N]ÃéÓ§ EmmíªU«&NœÓÖÖöÛo¿á9:r!ÈA€æ¥K—ÒétP¨ª7oÞ¬ªªZ¼x±““Ó’%K²³³ÓÓÓõê›`Æ#Ò/ª2XZZVWW[YYT¨€ÇB¨÷ĺÉÍÍÅûtURRRô Ý®ã-ÈŠ¢¨‹‹‹¾?4ƒ¢냳³ó£G>|¸lÙ²I“&ÅÄÄ´´´äææêUÉ•’’"•J¿ýö[j ¤ ‚èÑ®]»†ácÇŽAòGƒ½|ùrÚ´iÖÖÖ===ï¼óA=R êkaaqàÀŸþ¹··÷øñãžžž‘‘‘‹/¾xñ"™Å Ø^S ®ö+‡÷Þ{ïçŸþý÷ß{{{Åbñ•+WôuöŠaîÂUÓ¶êAJMýé9º¿@zyåÖýfÀ Š"¬ 'N º}û6†a`äȑ۷o #~–|b±X[·nUSPP¢ÇüDâSZp4ÈápÀrP-z™V<==a~ôè†a'Nììì[sª\¿~ï¿®_¿AÐܹsMußO*•þöÞ<¬©k{ü>'€â€ŠDP@0Šm§úx{‹•Ö‚„«T‹µ¥¥Nü)”ÖéjÁ DE¨Ö±‡zAE JBæÐjäýc¿=ßÜ’“Ðõyúô‘svö^{\gk/‡ãïïkccƒn.ïs“)Ü ë 1+=xð …B)//×cVÚãÌ;·¡¡¡¨¨]Ì/—˳³³1 ó÷÷'ÙäÈ·(¹\næ:€4ÖS©T¡P¨úhÒ¤IB¡ðîÝ»„~EWįÐs ‹¢z©¿víÚŒ36lØðèÑ£   K—.EGG÷¡I f¤=B!f¥Ê }qÆ£®´tUc¯@‹€ìaTT#Ôg~QQQšGÀ°°0Ç‹‹‹ËÊÊÖ¯_/—Ëëëë8°oß>B•"h4Zee%R~ÎÎÎØßç1 C»‰ÖÖÖmmm(ððáÃÕ‡-Í»‰hñêØ±cÇŸ6mÚáÇãããét:¹2èeðõAC{hnn¶³³S~âàà0dȦ¦&âïë- ²Ÿ®Ä°ËWšÛÙى㸳³óãÇ;::|||lll*++‘=†rÈ… £ü‚ pÿý÷ßÑXÆáp ÅäÉ“‰3fÌPW ÈBnðàÁäAƒ×;w***ºÔ¦½™Þ°GHPYY¹{÷ndÚ;ÑÐnܸáêê:{öl¢ {m®^½ª«%IŸnQ˜‰©S§J¥ÒþóŸ8ޝY³F(>\9@^^žL&c±X«V­rqq‰ˆˆàp8—/_&K§NÊçó/_¾ìëëK£Ñ6oÞÜÔÔÔÚÚJ˜O |}}›››óóó=<<<==×­[G¼]ºtéùóçÃÂÂFíääÑÔÔtîÜ9S\ïRUUUTT¤9fý¬z8ޏ hxAðx‰DíäääççªITTÔÓ§OÏŸ?o:dxï½÷òóó8NII‰é:Cw2888$&&Þ½{·¹¹ùÉ“'ÅÅÅ111f–AWWךš‰DB¥RÍ,Ãÿû_±X¬Üæ?ùäS…ær R©{÷î-++ãr¹|>ÇŽæ”áÆ*…€øé§ŸÈ‹±k×.åž GÏÕ F~ø!Žã‹- …^^^¦HHo,,,,--?ùä™L¶fÍõÔ ÷@¦óÈ÷ßoÌ Óé™™™™™™Ê#{—»ƒÁ`Ü¿¿ÿþ–J˜¿’¾üòK™L¶|ùr+++½¸}ûvyy¹••†a8Ž«TÞÎ;Q·/((0"ìN†÷ß_$8qbÞ¼yãǧÓé‰dÕªU¦èÌÝÉ––ÖÐаmÛ6OOÏ7ÞxãÈ‘#R©tÓ¦M¦¨nÍu8zô¨P(lmm5‘"Ô ƒÁ8uê”r³7Q›× ƒ»»{iiiYYYTT”››Ûĉß}÷]s¶44+óñÇËd2> …‚~»cÇ™L¶dÉSdá_ÿú—@ °³³Ã0ì»ï¾«ªª²´ÔÁi«ÙX¿~½f=§5@o€Lç5777@@¦ÉÖ1…B‰‰‰‘Ëåiii111t:ÝÊÊ ¹ç%é}B¡PtttôWr¹¼££C¡Pè÷s[[[™L†ü«D’ýÞ{ïåää¼ýöۆ˩‡ gÏž6lرcÇ:::0 Û¸qãÛo¿½zõêãǽ仓!11ñ?ÿùÏÇÑ«uëÖÍ™3gùòåû÷ï7®d X¾|ù»ï¾ûÛo¿ùùù=u­2 |ÿþý C 0™Ì£Gº»»+×Ô¹sç.\¸0jÔ¨ìììúúzW^^>oÞloo'ƒ½½½··÷Ï?ÿ|åÊ•ÎÎN.—{ùòe…B¡,IYYƒÁ(,,ܼysrr2š„……ísÁ‚Š¿9pàÀ¢E‹fΜiÄÖ5{öì?þøçŸ–ËåOž<5jÔ¶mÛ"##øáBÔqãÆ:ujïÞ½ÕÕÕ·oß6âÊ™£¹´µ®«è:|4¡½@åï ôDå¡jkk©Tª½$µ †a]a6-Ø¡R© ‰äàÁƒæ/¨šššêêêôôôçÏŸoÛ¶íáÇæÜn4hÐwß}÷èÑ£äääÎÎÎ9øWQQ‘––¶mÛ¶™3g?xð`Û¶m:•4[[[ Ã6mÚD§Óg̘±iÓ¦7Þx#==½ÿþf“A™Õ«W2äçŸ6Ñ– ÚþׯµO˜0ÇqÔPÇŒ#‹ù|>ùŸ ‡ãïïkcc£P(:;;U$áp8r¹\,cÖØØ¨P(ÚÚÚ¬­­­­­QôÔSär9—Ë1b„·-ZôòåË3gÎëä÷ïßÇ0Ì××W¹à8~üøqteÄXDs9)j Û!étºáëZHù+Ñ&%%%ÅÍÍí›o¾a±XæO}„ ãÆ[¼xñƒ>¼ÿ~s*€mÛ¶¹¹¹mÙ²êx<^BBÂñãÇŸ>}ZTT[\\¼lÙ²ñãÇ›M1£ÃIII™™™ §NJMMõôôüàƒzäãàÃ?Ôõ˜ŒÙ@ʯ¹¹Ã0‡£k 7n;vì(//?tèŠvÁ0쯿þÂþ§Û¯ï IDAT>òâÅ âßÄ–S@@@nnîÇy<2ä0bÇqvv0`@SS±»töìY ‹*kkkÓ#ûFDk9h-jÐáÔ(NW(ÄhTTTzz:’ŒÌº¨œ>}úí·ßVÏjzzzBBÌ ÕÙ»wïÂ… SRRŽ=Ú#åÓÙÙÉçóAqqñˆ#V­Z•™™YVVf†pÖ¬Y™™™ÅÅÅ=;à%¾¬ËÊÊfÍšåããS]]mž={&—ËÏœ9ƒz¨B¡¸wïö÷’©™ gÉ’%4-==½·uØœœ …"0 CßýB¡°¶¶væÌ™$Ç·k׮͘1#$$$888(((00pûöíÊÍ@ÃÏÃÃÃüñG‹•’’R^^þôéÓ]»v½ÿþûçïÿÀq\,{zzª| ªLûz¶‚È”ƒÖ¢Ö ²Š0** )!¢°är9Ú5ĺ:mtzÃaâ³Ï>‹ˆˆ8uêÔ¶mÛzöX/RL&ÇqVVVf†D­­­×®]ƒžXXXà8^]]-‰ÆßSÓD4¼>{öÌl)Ö××ã8îîîþèÑ#4 ÷ø®N„††vvvfeeõ¶é Ú¥+...++[¿~½\.¯¯¯?pàÀ¾}ûÐîÉx:9vìØñãǧM›vøðáøøx:Nòçááá %$$¤¾¾uœ!C†è›§®ár¹ãÆ6lšøöNÈ”™¢&ßÌÈθ‰í@­Mì’'444!!áæÍ›ëׯï‘Ù#+3a à †yHHH°³³³³³#v£;¦P(¼¼¼Ì©‡®òdòäÉ­­­EEEfÓçÎkoo_¹r%ñ‰ܽ{×ÌÚÈÝÝ}Á‚¦;&chÙÙÙùñãÇ>>>666•••ú™‡¡1úÎ;Ç'¿dgiiÙÚÚÚØØˆ¶Ç¨Têĉ»‚}õêU ⣣{³¡=ùrÐ\ÔhrO†Þ[¯6+W®‰DÊǦÅÂ… “’’=zùüùó‘á—_~Ù¹sçôéÓíììÞ|óÍ}ûö½óÎ;¿üò 1)1µ èÄ„ún4úœR lºrøâ‹/RSSçÍ›ggg7uêÔC‡M›6íСCê–…¦“¡¼¼üøñãaaa‘‘‘ŽŽŽaaaEEEW®\1O]DFFZ[[›î˜ "//O,ëª?|}}XYY©P(&OžÜÑÑQRR¢“Â^ºtéùóçÃÂÂFíää´zõê9sæÜ¾}›|$¥¥¥¶¶¶qqqŽŽŽ ,8räÈàÁƒuÊ…VÒÒÒnß¾½nݺM›6Ñh4WW×ððð+W®¼õÖ[º–˜éŒÖr YÔ7oÞüóÏ?ɤØoz˜šNò˜N†Û·o¯_¿>33sèС/_¾d2™ŸþyVV–ú2†édP(7n”J¥Ÿ~úiRR’L&»zõêÖ­[Õ?LZVVVï¿ÿ¾ŽÉxyyµ´´äçç뚊··w{{;š(¿ñÆOŸ>•Éd:ÅÀb±,,,¾þúë½{÷¶··óùü“'O&&&’Wü;vì°±±‰ýꫯÄbñµk×Nœ8±gÏ"@ddäæÍ› 0pà@ …òÃ?|ûí·/^¼Ø·oßO?ý$—˵xùòåŠ+BCC¿øâ‹ŽŽ¡PXZZªÇ¦k0ZËdQ———'$$ô®+_,,,Lwñ&y 1¨' “Ía ÙlöèÑ£.ƒú½ŽÝ]qi:ƒY:ƒÐe ¦“A]¤îìjM'ŽãèU—Q#=(ƒ±F õîîîÈXHu?傊K×4W7Žã„Í8JKùßÊb(×Two»ëÝZ¨Soè•Öüš´Áh.ò=‹ä8o¾aïRˆA&/ÂØÙÙyyy=z´©©Éè2,g“Ê@rãÖ¤2¨‹Ô¥T&•¤–ÊAk˜A3ŒsçÎíèèHMMÕcŽ¢ÜBô;y ¹º‘ñX—i)'§ž´æ·ë¬74ZÍå@Þ´±·íF÷ÐŒP&“â†Épºœ¢ Ãk.ƒ7L2™¬µµµË¡òL 05½¼ÁèÄk×bˆ»@`}}•ž‹®tïAyTqppÈÎÎf2™B¡Ífgdd˜Wdz› =HNNŽP($c°xñb&“óZ•IñóóÓÉ¿ñ+FèñE‹ …B///âˆWUU•ºßÝ´´43—]||<:œfȱÒ}ûöI$’èèh'''??¿ÐÐP•H¢¢¢ž>}zþüyÓÙVjá½÷ÞËÏÏohhàp8%%%‘‘‘&*äîdpppHLL¼{÷nssó“'OŠ‹‹M7îh­ Ã\]]kjj$‰q=÷’‘á¿ÿý¯ŠÇéO>ùÄE¡¹¨TêÞ½{ËÊʸ\.ŸÏß±c‡N2G:¦8º©yÑL^^žT*%£ß}÷ݧOŸnذFmcœ÷Ýw}¾H‘{zÂ=ñ'™ý_ÿú—@ @Q~÷ÝwUUUÊí’Á`Ü¿ŸðVܸ©AöË—/·²²Ò[€Û·o———#×*8Ž«ôÕ;w¢±Ï.ìµÊðþûï‹D¢'NÌ›7oüøñt:]"‘¬ZµÊ#Ww2¤¥¥544lÛ¶ÍÓÓó7Þ8räˆT*Ý´i“)ª[s] Ž=* [[[M¤5ÈÀ`0N:¥ÜìMÔæ5Èàîî^ZZZVVåææ6qâD]=Ú#»KKË;vhpo šÍW„Èò½ÏÙ½‰Þ¯upÃ#—Ë‘3zÂï†a$Ý0M:µ¦¦F*•b6eÊuÙd\®›tY¥Þç³mmme2áúRùUvvö{ï½—““óöÛo.§2œ={vذaÇŽCæ½7n|ûí·W¯^}üøq£—|w2$&&þç?ÿyøð!zµnݺ9sæ,_¾|ÿþýÆ@ƒ Ë—/÷Ýwûí7???£§®U†Áƒ‹ÅâöövS›ñhaçζ¶¶~~~L&S.—ã8®«ÿz ɤ¹Ð:€h†¤lÊ–ï€Qèý†.dõsTTºˆ©tÂïÒ‹íííšÞÐÐ ‘H‚ƒƒ'Nœ( %ɼyó/^üŠ-ïÙ³§ººšÏ绸¸x{{£œJ$???⻡­­íÀqqqä?f+ƒB¡ÈÊÊjooGþMZ[[y<ž³³³9e¨¯¯ðà2S(ÏŸ?omm5®{ 2ua˜½½ýÖ­[‹‹‹õ¸kÑplll¬~·9e Ñhï¼óΩS§X,¡&M4r%%%q¹Ü-[¶èÚå2€´··¯]»¶´´”Ïç744dgg;99)8tèPcc#Š?>>^=ÚiÓ¦9s†Éd*¯f3™L¢/k 0|øðýû÷3 @Àd2=êîî®Ü Ï;wáÂ…Q£Fegg×××óx¼òòòyóæk†}ïÞ½Õ«W777766^¹rE%~­Bj àããsþüù¦¦&.—{óæMOOOùi4ZVVÖãÇù|~}}}QQùVáççÇãñÞ{ï=ƒÁd2ÃÃÃ×®]Ëb± F`` ‘ÐØ±c9RWWgä‘-‡ž”$EѲIssóÆûõë7}út©TêïïoeeEdžÁ`”––ê½Txúôi•½Drr²N½ÎËH‰ûñªªªŠ‹‹‰õ.娻`&“iŠ¥Q22¨P[[[RRbDIt•aÊ”)B¡ðäÉ“æ—!%%¥©©ÉÇÇçÀ---Æ]Õ*ƒ···T*MHH0Ý· V>ùä™L¦ëZhwh¸ðääd@°}ûv]óKfÑL^^žL&«©©Y¹rå˜1cbbb8ÎÅ‹•›Zà]¹r¥L&ûòË/Ub¶··¯ªª*))™;w®››ºÁüÀcÇŽ%ÀÊʪ  €Á`¬X±ÂÅÅeùòå555¥¥¥öööD*.\¸wï^~~~||ü„ æÏŸŸ››ëàà Sqi ''G"‘°Ù츸8E‹UTT0 Âe˜V!µ°··¯¨¨¨®® 7nÜ_|ÁápZ[[•—FoݺUYYéïïïää´xñâììì}ûö‘¬J´ÐzòäIooïË—/WWWŸ>}ÚËËëúõë„+ŒQ£F=|øðÁƒʪÑ8 E§Ó‰¦C§ÓUô¢&Mš$•JÑ.zhh¨T*9r¤rƒÑÒÒ¢¢ÆÈgƒüeÓš1Ê­ÜUUUEEEš‡u)BdÀ0ì£>’Édä[¡qe R©ÁÁÁ÷ïß///Ÿ2eŠ)6–4È€³mÙ²ÅÂÂâàÁƒFW„Zexçw¤R)‹ÅzòäISSÓÝ»w?ûì³þýû›S”ñˆˆ4E`³ÙgΜÑÛ žfEˆ4~-M뢙¼¼¼––– 6  P({÷î%"TÒ¥"üðÃe2Yll,“ÉTV¥Z¬]»V*•†††¢˜qÿì³Ï¤R©rZ.\Éd ècÝ.­GquGNNNKKË®]»ˆø?ýôS™L¶bÅ TZ…Ô`óæÍ2™,::yæP(---„"´··‹Å©©©(k(ä[R„›7o¶°°@Ã5:î÷Ã?ðx<4ÿÛ¿¿L&›7oÉhuh‘h9T9^ …B~K`„ 8Ž?|øP¡PŒ3F,óù|•0µµµT*Õ^‰sçΑ\¥Ͻz@¥R$ÉÁƒÍ_P555ÕÕÕéééÏŸ?ß¶mjfK}РAß}÷Ý£G’““‘_V³%MPQQ‘––¶mÛ¶™3g?xð`Û¶m?ýô“97 lmm1 Û´iNŸ1cƦM›ÞxãôôtSèc´õ®_K#3€h¥°°ØË,,,Ä0lþüù$«9IG{ (…B¡ü[­-ZôòåË3gÎKÐ÷ïßÇ0Ì××W9ŽãÇGgÈß.­ÄÆòïêêŠdÐ*¤ÖÓ¦M“Ëå'OžDIÈårÏŽ€ÃáøûûÇÆÆÚØØ <êÚ*8Ž\.‹Å†566*ж¶6kkkkkk ÃæÎÛÐÐPTTD2Z²‹§t:䉘î@m·¹¹Ã0‡£¦÷–yMHIIqssÛ¸q#‹Å2ê&L°³³£ÑhÁÁÁ‡ÎÍÍ‹‹3›>Þ¶m›››Û|Ѓ'#x<^BBšššŠ‹‹]]]—-[¶{÷îêêjó|ôë×𤤤¼¼¼ÎÎÎÆÆÆQ£F}óÍ7|ðAnnnï9æ@fÑŒB¡¨©©!rÄf³1 £R©$áÕ«W‘=Uee%›Íމ‰±··OII!"ÔÀÙÙyÀ€ÊîÐdhàÀÊ µµµé‘;¨««#¤Bã-ñÝ£UH­[[[ÛÚÚˆ<O¥!mܸ111qÇŽŸ~úé•+W:T^^®Scû믿°¿á¼xñ‚ø7Z¤¤R© ƒ|„:œ¥Óé …Bu˜““ãïï&¿Ã04# …µµµ3gÎ4Šæ;}úôÛo¿­Þ¦ÓÓÓ`^¨ÎÞ½{.\˜’’rôèÑ)ŸÎÎN>Ÿ/Š‹‹GŒ±jÕªÌÌ̲²23 ¾³fÍŠˆˆÈÌÌ,..îÙ±ž(y¤ËÊÊfÍšåããS]]mž={&—ËÏœ9ƒº¡B¡¸wï†aãÆÃq¼7(Bc È.‚8Ù‡"!ŸÁ'OžÄÆÆ¦§§tttp¹Üï¿ÿþßÿþ7QƒZà8.‹===U¾½T¦}fèŒ"‘¨»WZ…$“ •RU¯ k׮͘1#$$$888(((00pûöíäó®µâtZã!«£¢¢P¼ÊYŠŠŠ"#wXXŽãÅÅÅeeeëׯ—ËåõõõØ·o:zJ^\ t·«þ%ºä³Ï>‹ˆˆ8uêÔ¶mÛzv Ž“ÉÄqœF£•••™!ÑÀÀ@kkëµkׯÄÄ 'h?£ººZ$?¾§¦‰ht~öì™ÙR¬¯¯ÇqÜÝÝýÑ£Ghp1îñ]Ã1âB£Ñ*++Q6ÑIiõÉŠ‚ƒƒe2Ù;ï¼S[[‹V>UÆÍ¸\î¸qㆠ†æµ½­Bj ÆommML GŒ¡28#­yìØ±ãÇO›6íðáÃñññt:ÝX¹hnnFö¦$!»AØK¨<$ó[´ãììüøñ㎎›ÊÊJdA^V­©À!IBCCnÞ¼¹~ýúñÕÛè„ 0 c0æ !!ÁÎÎÎÎÎŽØ>vì˜B¡ðòò2§$ŽêLž<¹µµµ¨¨ÈlS±sçε··¯\¹’ªfΜ‰ãøÝ»w{Ãt3ê²páB"› ,Àqü÷ß'ŸÍ1cÆ‚çÏŸ£¤ÕÇÍ®^½ŠaXttto6Ó*¤ÖèðPPà­·Þêr–‚Ôá;w***†nÄ}ú7n¸ººÎž=›dœfª__ߢo±É“'wtt¨lŸ*¬\¹R$§ÈÂ… “’’=zùüùó‘á—_~Ù¹sçôéÓíììÞ|óÍ}ûö½óÎ;¿üò 1)1µ èÔ†2(]ô9¥ØtåðÅ_¤¦¦Î›7ÏÎÎnêÔ©‡š6mÚ¡C‡Ô- M'CyyùñãÇÃÂÂ"##ÃÂÂ"""ŠŠŠ®\¹bôš——'‹ƒƒƒuòŒ2€(Š 6„††º¸¸DDD|ôÑGwîܹxñ"Éx ôðáCŸ‡J$±XÌd2>,,lôèÑNNN«W¯ž3gÎíÛ·ØÞ’““Y,ÖþýûIÞög›nu¼½½ÛÛÛÑ7æo¼ñôéS™Lfž¤û(“'O¶´´¼zõªÑ£ÈÈÈ¡C‡N™2¥®®Nùùž={vîÜ©ü k:~ûí·€€€!C†¼xñ‚Íf'%%ýøãêø¦“<¦“áöíÛëׯÏÌÌ:tèË—/™LæçŸž••¥>Õ0 …bãÆR©ôÓO?E¦oW¯^ݺu«)¦Å^^^---ùùùºæÂ(HYYÙ¹sçâââöîÝûçŸÞ¼y3>>žÈæ²eË’’’8pà@ …òÕW_ÅÅÅýùçŸYYY¨_dddLŸ>}Íš5¿ýö[[[Ûˆ#æÌ™sàÀgÏž¡C^Z¼|ùrÅŠ ¡¡¡_|ñEGG‡P(,--Õã2Óµ­Bj ÀápÂÃÿýöÛŒŒ ÇkjjâââÒÒÒˆ$X,–……Å×_½wïÞööv>ŸòäÉÄÄD#.677mß¾}ÿþý¿þúko¹*Ùÿîò+ÆÂÂÂtFuä1Š!™¼hSXXÈf³GmtÈ\šNÂÊ¡ÁŠÈt2¨‹ÔÝ ¦“·#Š¢˨,ºÔÑ`GèîîŽ uôˆŸÌ¢”}冧 ª‹îú•J‹Å)))Ê¿Âq¼¤¤äÖ­[Z(çEC£WZ³£w{P¿Ë»U5 ©5€ra¢Ýwå$È7û.A±¡††ò¿Õe §™f„Ê'VºÛ´{•¬&ÈäEC;;;//¯£G*ŸQ6– $ËÙ¤2ܸ5© ê"u)•Ie i%f†r0ÃVúܹs;::RSSõ˜Ä@4£µœ5×2‰S¹ØÞÞ~äÈ‘d(çÅ91ÃÚƒzü]Þ­ªµ5P/Lå$ 4ŽTX¥a(Ke"Ì×4#”Éd†¸a2½/à@óC¸a’Éd­­­]Ε?Þû"ùùù,+$$ÄÑÑÑÃÃ#88¸°°P(«GZ‘^Þ€>áPF¿Úà5D¥×ô]m§Q£FýôÓOUUUÈøµ¦¦æìٳġ5ÐkyÛ+€) P(„+Gå{ÔÈ€W dÝìêêÚ]‡ììl&“) ÙlvFF†Ê¾‘Ö´¢5 € 009tÕo/sñâÅL&3&&Jø•¡ïUä÷ß?iÒ$íÆ£Ãot:B¡\»vM,+_=…aXUU•ºïß´´4sv ­BšÞPFÄÓÓ3++ë?þ ãÁQdؤ!ÀæÍ›—,Y’””4iÒ¤˜˜˜ëׯ«ìiA+Z“ЊI{–á°Ùìòòòµè *mdߦßÏû÷ïo ›ª©S§2Œ_ýuذaÊÏ ïÝZc Ñh<øý÷ßÑm«¦“&4Æ­Y³†0Îèò¡Iqss‹ŒŒ¼qãFee¥)â‹Å–––R©ð––KKK§À‚ÅbÍš5Kå¶xsÞhªUH3ÐÊÁˆ¤¥¥988ÄÇÇß½{×-ù­·Þb³ÙYYYííí\.ÓÅéy’0uÏ2œÙ³g¿óÎ;‰‰‰C† ‰ŒŒ4¤šÎž=›ŸŸ¯ws½xñ¢›››!­ÝÇÇçÈ‘#\.7,, udÃ{·ÖêêêÂÂÂòòòrss—-[†z¼æý~§P(111kÖ¬IKKCŸÌt:}íÚµkÖ¬Q~hjüýý‘û4Ú„P(Ä0 Ý÷øäÉ•0Èœ³ïõ&#$&OžüÍ7ß ¿¬zÐãå`,ììì¼½½ïÝ»÷믿šè“ÂÖÖy;Âþö¶ÑÛ’0uÏ2œ'Oždee±X¬)S¦jºz7WŽaXrr²Í† P/VÆðÞ­5…BñèÑ£­[·zyy}ýõ×}tǸ-‚¨¨(tŸ:QjÈ==rI¡µ(srrJJJ¢££KJJø|~CCCvv¶““ ;;}ÈO„Bá¶mÛPä©©©UUU‰‰‰ %77W,£å8åqœF£eee=~ü˜Ïç×××mÙ²E§jF>Yçk‘HÔÞÞŽ|“Á KH//¯¸¸8äVÛœøùùñx¼÷Þ{Á` ­šµkײX,ƒˆÖplll®_¿Îb±A]]]vv¶‹‹ ‰ÖEžP(S(ò={öTWWóù|ooo¡Pˆ­ŸŸŸ±V O‚LÏ;vì‘#GêêêÁüñÃ?ØØØè$§á}ûûªt½×$/\¸Àb±8²ýW¿ìMk6:ÔØØˆ 9>>^åçÙÙÙ÷îÝ[½zuqqqsssccã•+WæÍ›§R±±±Ó§OOMMíÒ÷²á½›L …âܹsùùù+V¬P—‘””Äårõ¨¦W:ž™™‰üÿb»êÍÌÌT~Øyyy‰„Á`„„„Œ3&&&†Ãá\¼x‘˜Gæää Y<ñ“%K–H¥Râƒ]m—˜˜(“ɬ¬¬é®r*·nݪ¬¬ô÷÷wrrZ¼xqvvö¾}ûô¸ÅŽHQ}Û†Á` '#äãTæôéÓÄ@£Lrr2y9µ I’U«VÉd2ýhRþþþR©ôäÉ“ÞÞÞ—/_®®®>}ú´——×õëוoÓ¿uëÖîÝ»gΜéìì'‰rrrˆ·Z[yF%•J333õîðÝ•$qcUUUqqqÿþý»³7×».È'¡9 =kÔ¨Q>|ðàA`` ‡‡GLLLccãéÓ§u*jÃû&â÷߯©©Ñ¯á—[úøøH¥Ò””eÈdu·•+WÊd²/¿üREþœœ‰DÂf³ãââ<<<-ZTQQÁ`0Tœm]¿~ýéÓ§ÝítÞ»ÉÇ0þ|©TÚÝÖ~rr²@ ؾ};(Âÿu:N,ZYY¡»S‰‡Ý‘——×ÒÒ‹‚Q(”½{÷J¥RÂG†VEˆØ¹s§L&ó÷÷Wïçöööb±855%n\5z2Œ––5FÌc´BþÂk3` "Ô»"ܼy³……ºÐ.22’B¡üðÃ<h¨úˆët/^¼Èb±ˆ·Z[y&Mš¤>,ê„Ö’¬ªªÒ| Ǻ ™„f4ô¬ýû÷Ëd²yóæ¡ê P(Ÿþ¹T*ˆˆ YbFì›W¯^mll4ð`‘···z“ÏfHHHwа¥¥e×®]èCÇñO?ýT&“­X±‚(UOOO‘HtâĉÞà`ÇñÒÒÒÚÚÚînÆ}®ÖÒ!“h!T¿¥QDaa!Z}’Ëå………†ÍŸ?ßXkD€ÃáøûûÇÆÆÚØØ WM±kU[[K¥Rí•8wîɵ‹Þà=˜˜•¢¥¡òòr=f¥˜aå€a‡Ã‘Ëåb±Ã0´tÓÖÖfmmmmm ê#®çàr¹#FŒPqžn`‹¢R©ÿüç?wíÚÕÑÑqéÒ¥Þ¶ÞK˜;wnCCCQQár=;;ð.µf—±o^¹reèС‡š3gŽN.ȵbx6èn…BQ__¯P(\]]‰|}}---kkk{CcC:::R©Tõ·h!ºnüë ÙOëœO+ …‚ÉdÕÏf³1 £R©F<®½qãF@°cÇŽòòòC‡ùúúšâ,¸ú!‘ÞЦÉäàà`ooÿ÷eõ IDATÉ'ŸÈåò)S¦ 5– S£7°þúë/ìï“/^¼ þM,³äææ>|ø°±±‘Çã}øá‡è;]YCZ”MUUÕ‰'h4Zttô… úV=š *•* • ‡ÏçËd²Q£F‘ÄX}s÷îÝÛ·o÷óó»páBaa¡çUFÉ&†auuuD$èh«ò¦æÈ‘#1 3Ä‹ˆqA§ÃÆŽÛkÍf̃§FÑŽ`LL ªÝ¨¨¨´´4´GH<Ô€Š¥jÁ†=šøµk×f̘±aÆG]ºt)::ºWMí²Gh Ĭ©=•?͆f­ž™™éîîž’’|8>>žN§“Ì£èÎ!KßµÀ3ááá %$$-.)Š.O·jhQdhlld³Ù<ïâÅ‹}ôÑýû÷{Ûe64d¼¹¹YeÒÁÁaÈ!:MkŒÕ7CBB:;;Þ={fÜÊ2J6ɤ‚a˜~Ç›M½½=†aÊ++¯'d?ˆí@­5°páBB ,X°ÇñßÿU‡ÃQ(“'O&̘1C]g ™ÁƒkHu¹;wîTTTt©M{Þ°GHPYY¹{÷n{Þ^‚¥¥ekkkcc#Ú°¡R©'NT¯J -Š$ …­©êmOùj ¡gݸqÃÕÕuöìÙDQ‡††â8~õêU]GOÃûæÐ¡CÛÚÚþüóO£ÜF̦=z$—Ë{ÏRä˜1cD"QïYªí)Ì7#V(6l uqq‰ˆˆøè£îܹsñâEÔÈΜ9óòåË­[·úøøÐh´Í›7¿ûî»êmåæÍ›þùgXX˜»»»§§çºuëˆIýÒ¥KÏŸ?6zôh''§Õ«WÏ™3çöíÛ¯ù—ŽÊËËÿßÿû2™ÌtIðx{öìàÁƒqqq<øî»ïnÞ¼ÕÑÑÞ–––~úé§Ã† ûõ×_oݺõüãã?~ùò¥J$ååå #GŽ,**º~ýzdd$QI,ËÂÂâ믿FÆ@Ÿ~úéÉ“'Él^¾¶ £q&M™‹è±±cÇŽ'NÄÆÆ>zôè?ÿù‹ÅÚ²e‹Š´š[ ‚æºÐÐ³š››ƒ‚‚***öïßÿàÁƒ„„„óçχ„„ í 2˜³oêÝä´fsÙ²eµµµMMM?ýô…Bùꫯž>}Êd2‰K?È P(NŸ>n‰3dgnòäÉ–––ÎVQ-ÿüóÏ]FâååÕÒÒ’ŸŸs £ÌŸûõëGÒ©È ë"â­²Y¨†`*Ï•_™b%aôhû$Ë¡ËQ Õ,a ¨òo"a*ŽªRå-™Ekkk§l­¯+Z­µ—áv„Z“Ъ!ºëYê¯tíYFì›%%%šor £‘¡ú¬Qs6•ßviŒÞªüD] …róæÍ††CH ÙlöèÑ£õû9†a~~~B¡ððáÃ]¦»»{——J˜/“8Ž£=E´+¦þ1ˆöˆ·Ý]è§Lå¹ò+SLwtÚ}…!Y¨:T*Õ,a ¨òo"ÑZPUª¼ÅH´(’¼xñâÎ;3fÌX²d‰áž ºÄ ÍFk]Ö…2Ýõ,õWºö,£ôÍQ£Fýë_ÿòððм ¬5›(*ìo{u9»Rùm—üè­ÊOÔ…‘Ëå_~ùeggçO?ý4tèPYWÅÎÎÎËËëĉzïíÑh´¤¤$‹µuëÖ.›Íܹs;::RSSa:hLòòò¤R©÷Aq[”‹‹ ºró¿ÿý¯óBÃçs†ÇÐ#Ìš5‹¸Ý´K ¿†€Íf߿׮] Ðãç[·n]´h‘££ãÌ™3oܸÑÐÐàééÙS»_8ŽÏž=»¦¦&??_¿Ë~ ¹óÅÃÃãÞ½{ÅÅÅîîîÝ…Q^ªyÍ›Íþøãu²0 +..îòReŒµkëîîŽ iô[éAn $•J?~YSSÓSÓ…BQTT4aÂLßöfH©²X¬3fhNúu3è2“ÂG{~p0½ªE¡Ý#C„1<@3Ênx‘6…E?àu¦ï™Ä}ÿý÷|>ù_!{j”N§£ÓºkÖ¬!ÎuùФ¸¹¹EFFÞ¸q£²²Ò ÉÀÿOff&òG¯Ÿ‡zc±nݺîüh€5ÉŒŠŠjoo×ÛC}NNNIIItttII ŸÏohhÈÎÎVöE’-‹•mo„B!q²wNLL¤P(¹¹¹„W?e§4-++ëñãÇ|>¿¾¾¾¨¨hË–-¯ÉA€~èà†IÅ1¯NXXXŒ7nÓ¦Mû÷ïŸ>}ú®]»þñdddóH­×ô}üñÇ>>>©©©r¹|åÊ•ÈǺ½½½D"!~B§Óß|óÍ7úúú~üñÇuuuÈÛt‡7Ë 7¼iiiHFEE¥§§#EEòþåüüóÏ&Lˆˆˆð÷÷/(( cÙŠ®9Pvª®ò+{{{ooïŸþùÊ•+\.÷òåËfp°ôitX6D ¡Ä y¨_³f ù“2………„>+,,Ä0lþüùÆÚíÇßß?66ÖÆÆÝ ZÐ YEØåq¤ÓÒÒÈÌ “É$¦qèêw*•jÄc/7n;vì(//?t误/œ©4Cvi”B¡Ðét…B¡¼GˆÌ',,,¢¢¢´N ÑžáåéN ‹¢zC½víÚŒ3BBB‚ƒƒƒ‚‚·oßž‘‘óB ;È*¨¨(õ»ùÑ®!FúuVYY‰”Ÿ³³3†a<ý‰¤µµu[[ <|øpõùœæÝD´zìØ±ãÇO›6íðáÃñññt:d€×Nª{þìò¡.\Hè¶ à8NøØäp8 …bòäÉD€3f¨+B@€aØàÁƒ5¤‚Ôá;w***ºÔ¦`nòòòd2‹ÅZµj•‹‹KDD‡Ã¹|ù2a21uêT>Ÿùòe___¶y󿦦¦ÖÖÖ¯¿þZÙÐ××·¹¹9??ßÃÃÃÓÓsݺuÄÛ¥K—ž?>,,lôèÑNNNMMMçÎ3¥?h"//ÃálÚ´©´´T(>yò$77wÔ¨QDÇCCCKJJ¸\.—Ë-,,  …*ŠÇñÕ«W—––òx<.—{ïÞ=BÏMœ8±  €ÉdŠD¢æææŠŠŠ}ûö9::š;« N^^žD"éׯ2œ·´´TŸ¨!ߤÄ[ƒúî‚©33®1^ ètzvv6R{t:ÝÊÊ ]æÒ¥·Bèýè`GH§Ó×®]KÜÞB¡Pïp™ÐGÑA!Íg:QÀüU„t:]Ù7=¼R„h;0==‹Aà•ÔµgÑÑÑ„Ÿ÷ŒŒ ˜¯ ¤¡ÊÖ ú3***==“Õ¼.(¥P(È|¢åè9²³³™L¦P(d³Ù}Ñ©ïâÅ‹™LfLLŒVáýüü„Bá7ß|cÄl9r„Íf‹D"‰DÙ  ÷`î1tóæÍK–,IJJš4iRLLÌõë× …™e0Çû÷ïß¿2!---««"##ÝÝÝ¿ýö[ …¢9æ©S§2Œ_ýuذa:%±k×.‘HD§Ó)ʵk×ÄbñÊ•+ $dNUU•D´´4ò…I£ÑŸïâââíí- ÑJ—ŸŸŸq×Ó4sîܹ .Œ5*;;»¾¾žÇã•——Ï›7¼ ‡jllDòÇÇÇ«­>>>çÏŸojjâr¹7oÞôôôT‰|øðáû÷ïg0€Éd=zÔÝÝccc“pýúu‹%êêê²³³]\\tÍillìôéÓSSS«««õPÆ<O¡Pðù| ÃD"Q{{{cc£rí3™Á`´´´¨|÷걄€ãxiiimmm—‚9hAxm!Õù‘LOOGjN§›„íìììè ]«à8~üøñŽŽ´CI~u— Ó¦M“Ëå'OžìììT(r¹¼¤¤DyÁpÑ¢E/_¾}úôÛo¿­¾,–žžž@^$S ¯2Ȫ â8Ž‹ÅbOOÏŽŽ•_¡ááá?þø#‹ÅJII)//úôé®]»Þÿ}d@¥ý:°þ €::ŸqˆŠŠRÖ%*šŽ   .7‡zʘ¯KÁøñã­­­‰Iáˆ#”Åær¹ãÆ6lXsss—1„‡‡S(”úúz´x;dÈ]Å@‘;99镉Wt‰ÉdÂ÷*èüÜS³CcíštÊ1((ˆ˜y¼õÖ[ÊŠðêÕ«†EGGw75±´´lmmmllDÛ„T*uâĉºyôè‘\.;v¬9MSz9cÆŒ‰D¯Àr1FVŠº   €ÇãŸ____TT´eË‘]>Ÿa˜H$jooollÔiðõññ9þ|SS—˽y󦧧§Ê¢ÜðáÃ÷ïßÏ`0“É|øàÁƒÀÀ@˜˜˜ÆÆÆÓ§OëtÁ)É&—œœ,¶oߊ^_òòòZZZbccÑ(C¡PöîÝ+•JÐЦU"vîÜ)“ɺt#`oo/‹SSSQèòk;Ý)ÂÍ›7Ëd²èèhtÝ6…BÉÈÈhii!áÚµk¥Rihh(úÇñÏ>ûL*•~ùå—„¨Hl3…B¹xñ"‹ÅRWEZ!R`=;òê­ tW¢¡Áìß¿_&“Í›7•6…BùüóÏ¥RiDDÉB#ßäzC]Ðfí™………ÄîZaa!†aóçÏ7Öq>@Àápüýýcccmll Egg§™ÝöN›6M.—Ÿ}-E"¯åååhY299¹÷(ƒ¹sç644¡Ò–ËåÙÙÙ†uç­IòM®ë­˜oTR(L&“Ð l6Ã0*•jÄsí7n;vì(//?tè²v1ŽŽŽ­­­mmmÄ´ÙFüéìì<`ÀäMqöìY ‹arss>|ØØØÈãñ>üðCâÎ̾BPPƒƒƒ½½ý'Ÿ|"—˧L™boooooŸÐ{”•J …ʵÃçóe2Ù¨Q£ÈGÒãMÃ1ßðŠ¶ˆ?Ñj’†óz¬†]»vmÆŒ6lxôèQPPÐ¥K—¢££Í¬BTr¤r¦Çq±X\}TÒ¬ÐÚÔ±cÇ$I||¼9¿Ðr.FŒ¡,—˵µµ6lXÇÿBèËððp …’‘‘q÷îݦ¦¦žò ôj ¡Á477ÛÙÙ)?qpp2dHSS“Nñ÷l“Àp̪.\HŒ ,Àqü÷ßGC‡ÃQ(“'O&̘1C}@AömƒÖ ›îܹSQQÑ¥65¥¥¥AAAĜ୷ÞRàêÕ«†i˜4XZZ¶¶¶666¢+*•:qâľ;°VVVîÞ½æ÷Ì7\]]gÏžMohh(ŽãW¯^Õu ÞƒM€>C^^žL&c±X«V­rqq‰ˆˆ@…‹¥S§Nåóù—/_öõõ¥Ñh›7onjjjmmU95êëëÛÜÜœŸŸïáááéé¹nÝ:âíÒ¥KÏŸ?6zôh''§ˆˆˆ¦¦¦sçÎé}àPÝurrb0üñÇ»ï¾ëææ¶~ýz6›­l>Ñ¿ÿ‚‚‡óùçŸÓh4WW×ððð+W®úrÏž=2™ì³Ï>stt\°`ÁåË—›››[[[ÕmÒµž5ÄŽÐX¾»©õÔhAAÇC§rÔßjh0T*õÁƒeeeK–,qqqY½zuCCÃ¥K—¬¬¬HÊF¾Éååå‰Åâàà`Бðú’——Çáp6mÚTZZ* ŸE}…Y³f?^ÃL´¥¥ÅÃãË5uŽ=š““ƒîX0žŒ P„ Jqq1•JÕ†¤Ä^•©9†‚öQzZ ”ùä'lc*¦NÀ«Íÿê;%µG¡€^}þWßæ^kþפaôXì“ ³_àÕÅuö„Iü¥¤›j0 £àä¯.O˜ØÓbÒ§¤óp h@àµ@a ¸ò à5?~|OË=†%ŽÃÆ ðúv„Àk (BàµÆ¼f¯30#^k@¯Ü™!b IDAT5–*=zÊ”)––ªÏÍFGGGiiiSSSw@B­€„†Hh8¯€„6l˜9E"ƒD"ùóÏ?‰?ÿ§ø …›››H$2»TÿŽãnnnÝ+HHÐp@Bà çðåË—l6»WFÁq¼ÿþ …‚°T]•ËÍ}÷š………••ñ§âoº of ­¬¬T¾¶z¡„ʈõ> Õ õÀÚz¦dõÛ %T¡·I¨2Ô`½OÂÞ?ÚXXXè$¡B¡xñâE¯Ò‚†)Š?ÿüSYªÿ95*—ËÍ&ñw#FXZYYXXpššêYL"i ÅjN ‡ÛÙã>`à@ Þ?Æb2¥I¯’ÐÎn„«›ÛÀAƒ0 {ñâÅ6›×ÌíU"p÷™¯¶¦¥ÞK$ô Ñ¨Ô‘ÊOÊÜþìÖk$¤P(cÇÚ;8ZXX(Ц§OêY½§ =ÆÒ¨#Gª<är8¨G÷ 1 6lØwAƒã8þâŋƆz>‡^õ ‡æîî1hð` ÃZZdÌÚÚgÏžõ* ÛØ¸{Œ2d†am­­,f]KK‹V {› TFYì;,caAA²P(½ñÀNÿþýiãÆ4H$J¥ÒÁƒmh´q½êž~ýú7nÐàÁb‘H$0`ìØ±¨#õ6\]]‡ jaa÷¾º¶îomaañ¬­­åo:;:zZ¨ÿaœ§çH'çÎÎ>'‰^üï—lóçŸÏ%b1ñ_û_!…ÝÓrýciãl† ‘ɤB¡`À€ciýúõëi¡þ++«qãÇÛ "‹e2é°a¶c{ÙhƒaظñžÃ† “HÄR‰dÈСÿ{÷Gq÷|f¯ßIw:õ®Sµån°lË•0ØÓܰq( 8à4x ðÀ~à„PL „ؘâ`šé‚»å^$«X½œºNºÞvç÷ÇàåmYÒ´#Ý÷ý¯åt>}4{»ßÙÙÝÜ1c8™LêP!#Ù)ÖªÊJ„PÞ˜± ‰‰ReèCLl¬R©´Y­å¥¥„3 5Z­N§³ÛíRGûJ¥vØí]wUe%!dÒ”)C”^op0“ÒêtÉ©i‚ °yÄCÇÊÊËJÝn7}…©¸.""66ŽçùÇ»œNÄX<„¹©©Ùl¦ËQQÆñ'Úí¶úº:vrª5V+ÂÉâbA" "4ZmDDdW—”§ÖÅÆÆ©Õ‡Ý^z²„R0c†!**R¯·öôHíFc´N§s:¥%%„ ¦èt±1±mm­RG É !;ÛÉYu´·Ûl6¿Ï'‚J¥’+„ŸÏ'u®ÙlÖ’â!BˆB¡P*U!Ûu¾7Ü23³0ÆqqñRg9 …B!ð¼1:Z£ÑºÝn³¹ ±ôÍ4 c»Ý¦Ñhý~_Ks3SßCtz[æ8.;7rª¢‚çêU{<ŸÏ§P( QQn—K¡T ‚àbiKQ(•!·ÇMëÜn·Z­‰ÐE°SµZ-BÈãñЄ.—S§Ó©5©s…Œd…q^¯×ëõÒåÌìlŽã:;:ÄWA‰ŒÔç/—Ëe2YcC½åôYLF$&%EÇÄÔ×Õ* DR(•œL–•CG¢bcc;ÊÎQšŒ“!„´Z]þ¸ñÇB>Äó¼ÔÑzKKO×jµfs“Ýf“:ËOA¨®¬ÌÊÉ7~Bc\S]E»×Œð¸Ý!­VGGMèÆÂÔ GÏd~t;F!„9aÌÔã 1ÔÖlÊ0™âãã].WUå)vö"AœN§ÇãÆG½&ÅIK¡Pd˜L6[e0ÇY­=ÝËáC:èóù QQ±qqRç €BÈïó•Ÿ8zøÇãÖêtIÉÉRÇ:‹øøBH‹ÙÌຎ‹S*•·Ûn·cŒcãâ™ÚRÚÚÛœN§F£¹°  `ÆLÚýà a_“’ÒÒ3|>YéIñS{ɉã‡ìêꌈˆLJNÚ$—žaR©Ôr¹|Ò”)±q±!£1:3+›YDJNœ8qü˜Óá°ÛíVkBH«Õ±Ó†~¿!äñxº-«ÕÚméF©5vÚ2DE©5Ç#ÎudGbRRLl¬Ãn?tðÀ±#‡;;:ôz}rj*b¦ ‰ ”œ8ÞÚlö¸=m­-6› !DCÇO/Ò8=±„øÑÑD½.Ÿèû‚•!ø«ûžŒ;|'ÄÆfee#„*OUô¬g!a|BBrJŠÍj«®ªÏ_rpaÄ ![&ãd2µL&GÉd2¥RI+ ###323}^_Ey!„†ôû|„}Ƕ„ôBz2†"WÈB>ŸŸ6¤t§¯áéõ{YH¨T*1B^¯—^làõzBr™±Ô†.—«¼¼!$“É.,˜Žr9ä|É ß÷ÐéD©”*úU*ÍÜŸ„ÃopcÃ9³Óêt¹ycä …Ó鈎‰1FG#„º-–Ö–©£ýÀãñDFêée ‘ØØ8BHw·…o^uUeuU%]ÎÊÎIMKëèh¯(+c'¡ÇãÑë r¹c,|TTÏóìL&Duww[­VƒÁ0~âD·ËÃó|gG;;mH)ärŒ‘ßÏÖ,ª««+5-=ÊhÌ3Öï÷Ç'$BlV+SmhŒŽNHHt»]QQFµZm·Ûººº¤õ#‹¥Ëétêtº1ùùˆ ˆˆH·ËÕ%émB áÙi5Zz¥‘V«ÓjuôEžçÛZ[Ù~zº»«*+ÓÒÓé#ÇÓX_ÏÔWó¬ ÅHëQ^¯·êÔ© “‰^Ããñxêjjœ,M£@UVTäæåÑ8Ó„¶Ó23sa"0´rE6«µ¦ª*-=^øïózê[›÷¯Õhcãâè%˜]]]U§Øš‘@©(/ËÎÉOÀ;ŽÊÊS~Æ®¸ †Ä…°¼¬´¼¬1¶Dut´ïÜþý™¯3•ÓÜÔØlnÒh4„ ·›­ë¬{{‡¬…lmmikkÕh4(`¨‡)v»íè‘Ãjµ†ã°óôpkêjkêjk{ë—2››š›Íjµš“ÉœΓ:ÔO455¶µµª5·Ëå÷ûlFkOÏÑÇT*½;ƒ ƒ!q!d¹5YÎ&"„°Öƒ9+–“ý6$„¸\¬'”:ÂyBŸ6À ŸÏÇÚ¢½BØœ3<˜5 ¬eÖ¨ä3³Ï;K ž$ $ $ ÞHO8Ìaú/06ô„5(„ÂBa ®#ŒŸÞ¦œ¾(–F: 4 ¡,„\pÉdâyþäÉ“•••ñññ)))!›ÍVYY9üßÚÌÌL£Ñˆòz½%%%4€\.Ÿ8q"Ƹ¹¹YòÈ#„¿ß/“Éššš}ôÑ¥K—Î;—çy„}'](y¯ïôà¾âééé«W¯NOO§Çà .ܱc!dþüùãÊÊʧžzªÿŸÜ÷±^ÿ?gæÌ™—^z)ÆØëõÞwß}^¯!4uêԻ㸃¾úê«ô bÑ¢ES¦LÁ···÷§†*a ™L¶lÙ²Y³fч^ÒϱX,ï¿ÿþ Æ÷†"!BhÑ¢Eô0‚ž~[¼x±\.?|øð áP$¼ë®»t:x<8f̘¼¼¼–––‡~xò„«W¯6 çúé@74 o¼ñƬ¬,ºãþÃþ ~Â’%KÒÒÒBmÌ!ú"„fÏž}ùå—ÓΟÿüçêêêÁ}Ú%¼å–[æÏŸ¯V«Åa ¯×»gÏžwß}w •&ä Å­¸¢¢¢¦¦æ²Ë.£§! .ܸqcEEE¨¾‡ýœ,C«àÌ™3ׯ_o0xž§UPüžçßÿ}¹\þ»ßýN&“™Íæx ¢¢bÉ’%´;HË c‡ G¨V«ï¾ûnÚùÿª‹.ºÈn·Ëd2$ÝUyyùe—]ÆqœZ­ÎËË£G¸&LÉdãÜÜ\ñIII4j}}½$QBwß}÷´iÓ;õ㘘˜Ûo¿ÝívKÛO ŒD§êÆë¯¿^¡P „¬Ì<ã”ã¸^ (“² W<‰ë·W£Ñ×K£Í½f2åÎ;ï,,,ìµ®U*ÕE]óÜsÏI{RSlºÌÌ̼¼<1'Æ8))é®»îzòÉ';‡ñɦ´7}úô_|‘VA:_F$­›6mB-_¾|Íš5555Ï<ó̬Y³èûA‡F‘!…𪫮JNN¦Ëf³yß¾}r¹|úô鉉‰Áx0Š‹‹½^¯Z­Feff–”” „ÆŒC7£Ñ8a„'N¨Õ길8úO¤›š?¾XÍfóþýû5ÍܹsµZ­J¥ºîºëŽ?ÎH±¡hÏÆf³y<žž—:[¶lQ(K—.¥-Y]]½wï^v¦>|X¼!$“ɦL™B&xžß¶m#9A0æÌ™3sæLú lmmÝ·oŸßïŸ1cFjj*ÆxâĉW^yå_|ÁºV©T]]]û÷ïw8Ó§O§þ˜˜˜k®¹fÓ¦MÓּ‚‚‚_|1**êÌ*H ¡ kÖ¬Á¿õÖ[Ÿ~ú)Bhݺu………t˜T|'’°^pÁ´´¸Ýîõë×·´´ „¶oßþÄOhµÚà?Ð<O}}}nn.Æ8%%…‰5!4eÊ”'NäææÒî !äĉ’|AçÍ›G·»Ýþì³Ïvtt „œNçu×]‡16™Liiiuuuìüñ'Ÿ|ø”ÜŽ;B·Þz+mL‹ÅòÝwßÑ‘©£!„ЦM›{0+W®¤CR¡mÛ¶ª×ëBS¦Lyë­·†'!!D§Ó=öØcF£QœüÒ Bˆ–^{íµ[·nmooŸ7o­‚ljx0…0Øšˆˆˆ¤¤$º\UUÕÚÚJ£wvvz<ž ?ù„Nåba“¦Î,Éìi„xl+ÂìÙ³çÌ™C×iEEÅ–-[à€Q """##ƒ®Öòòòææfú ìêê*..¦_ÅÄÄÄÀIòûý â[œe4Å=ÒPÃ;Žçž{ŽžJãyþ̾ -xÍÍÍk×®u»Ý—\rÉ®]»žyæñ¼ 9=qtÐÛ{°=„„qˆ¹¥¥…UVVFϨ'$$ „ÆŒƒ¢k=666%%%%%%55•¾Yª.WRR’Ø3?~üË/¿L—Å3!:—)¬­ë$##㦛n¢ãÝÝÝ6lÜT7ÀšÄÄDq[îµ? <ƒ’’ÒØØÈÚ˜0))©¾¾~B0ÆÛ¶m{àþú׿jµZ¿ß8:J7æææûï¿¿¶¶ö©§žš={ö‹/¾¸yóf™Löë_ÿZ¼ âÑŒÁö?GŸrÅÅÅt^µZ­ž4i=Xkjj:rämµ .¸ ))I<0—ä«xÞH.—«O§"–&)€ )•ÊU«VÑ1(žçßyçIÆ!ÀPÜ–{]Ѹ{ |;l6›¸<œ !Ç}ÿý÷k×®µÛítî í Ò*HyüñÇ+**þò—¿Ìž=Ûï÷ßsÏ=Ë—/ß²eËþóÚe r×}–'ÔèߎªÕês}€>¹74¡×ë­¯¯;v,ÆøòË/§Nžlk9°øy<žP%ìÏ'ðnˆzùúë¯ÇŒ£P(”Jåš5kNž<éóù&L˜@ïQGùöÛo%ÿ6R …â(--õûýyyyQQQôõÇK•^G¸gÏž%K–h4šŽaŒ}>_ww÷@o áÖ­['OžœžžŽŠŠŠ¢ƒ¶ètW7øÏ’ßﯯ¯ÇE:D_///ïèè {Lžç¥½býàÁƒ_ýõ•W^ÉqœB¡?~<}fÎÍ͉‰aä(’}ÅÅÅôG.—Ož<¹³³sóæÍ’ïzâââÄñ„PttttttàO/IeïÞ½—_~9Í©×ëé¶ì÷ûOœ8!vh@ߎ?þùçŸ/\¸ã¸ÈÈHñ$ýé÷ß¿sçNÉ¿” :®  $lkkûðÃ%< £§ú†ù¾¬ù©A|„ÇãY¿~ýÑ£Gi‡cìv»?øàƒAoؤOƒøÀêêjºÐÑÑqòäIrz®­8jÚÜÜ< vyBBÈ–-[Þ|óM:©Z¼7˜Ûí...~å•Wzþ2ä Cnèþç?ÿÙ¿?uÄÓù™’'Šfyúýþ—_~Y5Á[,– 6ìß¿Ð_ìpûB>üðà 6nË¡¶¶¶Í›7oÚ´i 5fèÚÐãñ¼÷Þ{‡ƒ&¡¼¼|ýúõ‹EÚ„ÃóÝ š§O´µµ=ÿüóqqqéééôô›Óé¼ä’KBòáÁû÷¿ÿýÁ ÓsÄ×7nÜøæ›ožùº$!Û·oß±cGRRRrr²L&ëîª¯0•6õüóÏ‹±JÞbçb·Û_}õU£Ñh2™8Ž«©©a!jssóÏþó>:UŒ4iKKËÓO?–––””d·ÛËËËéî®]»èÔB"„6oÞüÞ{ïÑe¦îê€"„ìܹs×®])))‰‰‰ǵ¶¶ÒËò˜Ê‰úæ›ovìØ‘——§R©ZZZY¿Ã,da¡µµµ­­ ±7¿‘œ¾*³ÖV9ÝNšššèm™{-ÉZ‹‹ ´—ÏNŽ Ö«««£wÞ[f¤ÎµQ3‚nË ˆ½ÖBœNç±cÇÃ!‡AˆÌÎMBÐŒ!Í h½Í8"B)¦  5(„ÂZ°·XëÃSO=E/W÷x<Í?W vÎ6CÂàAÂàAÂà…[Â7ß|“^äÂó¬}$ Éç…ÀÖ ñ9Â@ì<¯5œOŸ)`h@XƒB ¬A!Ö†p²Ì õö$ $ $ ÞHO8Ìaú/06ô„5(„ÂBa !€°…@XƒY£ƒ ƒ ƒ ƒ ƒ³F€‘­w!d¹€S0x0x0x0xì'~R !.—KÚ–%„8Î>~ Ï o¤'Dùýþa Ó‚ þ/NKKÿ‡¢Ñh233u:ݰûÓ鬪ªr»Ýã3 ûo$ôz½ …B&“ ¶sñûý>ŸO¥R‰™RB<Ïû|¾^Õr8q×w«AÂó‚„Áƒ„Áƒ„Á ½^¯„ ÏÄqœR© ÌŒSSS% H fkP„5(„š\Ú©·€´ G ¬A!Ö kP„5(„ÂÌÖ G ¬É‡ôÓ322 äò¡ý-}ðûýEEE çzû ÑH Ï ï¼ õz}BBÂY%1jBZZZl6›øÊ®BHfff{{ûÐýŠóÂgffžk­³Ÿ„°? að aðΛcÜØØ8ºO™aŒ•J%ýcé+C;4*ù£7èêìc¥²ŸIsœF«ÿ—fìõð; )¥R©P(_a-á™ aðFABÇ3º« Bˆâv»ÿÌ!œ,C ,¹Rá\#û Ѱ‡4DEeçäèõŽãÇþ}{i6é›ãÉ“§DÇÄ<_[SSWWÛëçÒ'D!¤R©ÆOœh0D!„ÚÛÚJŠOˆ©IØH¼‘žp˜ÃHˆ®º “eÀÔjõ„ Æèn‹¥©±¡«³SêD?JLLЉ->q¼½½=ÝdÂ'§¤^X0]òÝJ/&S¦ÑÝÓÝm³ÙSàyŸ£”B¡HLLŠ“:ÉÎÙ%&%©Ôên‹åø±£ý³N …‚ÒÓÝ!“qJ¥Òd2™Íf©sõF‡”kkªÕ^¯W«5cvšQ”˜˜Dimm‘:ÈH¥ÓéòÇ·Ûm ®_0 PÁâbãâ1Æã¬ì„PWW';B‹¥Kàù‰“§hÔj›Õ–“ë÷ûëêjYÛÙì¶˜ØØÔ´ôˆÈAÚÛÚXK¨Öhü>_BR¢À cŸÏ'u¨‰n,R§!…ü@¥TÑùr…\§Ó!„l6«Ô¡~d·ÙŽ?ßmé²ÙlùãÆ?v”H=õàLõõ©©iqññ>¯·¼¬´§§[êD½™L¦„Ä$"!…³ç464ÔÖT³V­§±V§Ó32""" 9ÆX¥Rçjh¨·YÚ^À€@!?pºœ^[«Õz=Þîn BÈãöHê',]]Ý ¸ `zkK‹\&ÏÉÍs:fs“ÔÑ~ —ËÇOœ$—Ë !Çy½^V;eêÔö¶öªÊSR§ûAuU• i顺ÚZs‹såçÌ›/v¶víØîõz¥Í(*ÊO—•JeRr2B¨£½ áÈ5´³F'™úž"ÅrB4Œ!#t:•ZMQkÔ11±!¯Çk±t7äp6#!$3;[®ÛlÖq&X{zRRS•jumu ÓÒÓ£ †®ÎÎÎÎŽ¬ìœ±ù㚛͆¡ï ÃÙ†^ŸÏÝÝmQ«5¦×ty"„šÍMb!äyž©„5ÕU jfÌØ±.—óTy!Äjíµä Ï f¢ŸÎ…!øA]]'“gff:ÎcG~KØ™‘aª(/‹Ž‰ñ¸ÝGž8yJLL4-„’SªTc§ÓQ_W§TªÒ32L&“ ÖÖVv“BcCƒÅbÑiu3ºï++-—YKhµZBF£!$L– ‚BÚÚZÓÒÓÑÑùãÇ»œ.„HM5[gL&S·ÅÒl6 ¹B¡P(r9ïç¥Îõƒžîîä䔄Ä$ž … /¾y IDATǹœ‡Ý.u´Ÿhlh@±–*Sß:0êA!?²Ûl'Kг²²1B.—«¦ºZêP?Q^V&“É!ÑÑ1³æÌ¡´¤„‘ýf³Ù¬ÓE¤¥§§gdB¬==˜ãôzýØüq¥'K¤NBÉb±ü÷Ûmjö¨0äw–¢P tŽ/+û Ѱ‡lkmmokS(ÖårŠw„b¤ÅIÖžž=»wEDFºœN:«‘„•§*ª*OEDFº]®ÀéŽbÉö"ÌY_”<á%—]ÞëÒŽ“ÅÅÍÍæó&žxŒ€s„àœ!^¯—©yzg%‚µ§Gê½ÑƒÁ@X175õ*„‡Cª0ìƒB£MyYi¯W­·7 P`´²7 pÓma !€°³F™y.}Ç`?$$ì'HñÄ===ƒžS0rWô¨O¸}ûö;vÐå ‡pö ChØÊd2žçcccyä‘+¯¼’¾L”ÉdQQQc‹Åä8vàËVYaH­VÓŽ‚ÅbéééýBˆpšÔYÀp ¹<ÏnÞ¼yÁ‚tÕÓo ?Ö`0üóŸÿ|óÍ7ãââB–á¡ÑÌÌÌqãÆEEEùý~³Ù|èÐ!§Ó)u¨Ÿ˜6mšÉdR©T‡£¦¦æøñã îÁ§OŸž™™Éóü‘#Gª{”ĸqãt:³‡R(Ó¦M#„Ô××3u"}Ú´iYYY„âââ²²²„„„´´4„ÓédgÒBÈh4FEEutt8p€©y¤‰‰‰´ÑBUUUŒÏÏÔëõyyyôøÌï÷=z”µ<"ÐáP¹\þË_þòž{îQ©T~¿Ÿ>7†N¥m; ¹£ôÍr¹<""B¡PÈd²f±šL¦+VŒ;VüS !v»ýã?þì³ÏXøF,[¶,!!A<åKill|çwŽ;ÆBB„Édºûî»M& yýõ×õÕWL£^¾|yff¦8Nÿý÷#„Þzë­/¾ø‚…fLMMýÅ/~A'ò „®¿þúíÛ·Ûíö«¯¾c\__ÿàƒ²!tñÅ/Y²$""!D¹ñÆ7nܸwï^FâMŸ>ýÖ[o¥_¿õë׳ì¬V®\YXXHÓnß¾zD U0##ã±Ç›5k!„çyŽãÄS<ÏÓÙpjUúf¿ß?ƒFÌÂÄÄÄßþö·±±±»lŒ±^¯_¶l™ ’ï"'Ož|Ï=÷hµÚÀ1ÆééékÖ¬ùÛßþV\\,ùf£V«ï½÷ÞÔÔTñ¹\¾`ÁɃ¢ƒ'¯Ðÿe¤Z+•Ê{ï½7##CÌ#“É.¾øb«ÕJÑɉŠˆˆXµj•Ø·ÆÓIêµµµf³YÚl]×b?@ê8}™6mÚÌ™3é*nll|ë­·`8w@A¸êª«~øáøøx¿ßO×;ù鳟bccÅ>b??cì÷ûiiý…ðšk®«à_|qâĉôôôë®»N­Vs·`Á‚/¿üRÚ½ù¢E‹èe­V«uÆ åååË—/W(Z­öÚk¯-aà9±‹-JII¡Ëf³yÏž=J¥röìÙ111Ò ôÉ'Ÿ †E‹ÑTŸ~ú)!„‘«é¯¾új± ¶´´ìÚµK.—Ïœ9311Qêh½©Õê–––¢¢"Ç3cÆŒŒŒ „PddäÅ_üî»ï²Ð˜#…Z­^¶l™\.Gy<ž 6°vF†qÇ=öØc·Ür Bˆçyq8TìB´Zí?ÿùÏ^¯£Ó·¼éõæ^ !Fãr¹B›¹[¬ñ<_UUE'mÚ´I„C‡¥¥¥Íš5 cßÜÜ’ƒK˜˜˜HwŽûöíãyþË/¿ÌËË£³{­Ú :ä´iÓhH·Ûý—¿ü…v ¶oßþøãëtºA|rÈ›!´wï^„Ðå—_Nÿ×ívõÕWâõ~ZÈN›6.x½Þgžy¦¾¾!ôÕW_=ýôÓz½~Ÿ<mHY­ÖG}´»»!´gÏž§Ÿ~Z¥R¡Ó3rYHxæG îÓ†4!!äÖ[oMJJ¢ÿûÉ'Ÿ””” ´;8ÒÛ0¸\ˆÒÖÖæ÷û …8†yfm£Ã§=Erúv3g¾™܉F·Û’KÿXæz„7n—ů`à©uƒÁÐÒÒªïÓ Øívzs–üüüË.»lçÎN§sýúõâ$H‰ŒŒ»ƒÍÍÍ´¹\.—X%wæJ áž"HJ¥2--LTVV644Ð`v»],„Œðz½ô²„Ùl¶X,´ÛÊZN–aŒ/½ôÒK.¹„®ôâââ>ø@òmy$zùå—<øÄO¤§§û|>qh”B‹ŸÃá¸ë®»š››åòÁôÄèihç‚1WA C:yyyÑÑÑ*• cÉÎy…ï¿ÿþ¶Ûnã8N§ÓÝ~ûíË—/7›Í»víª¨¨`a?ž””$ž{P““ém<ÑlC·ÛMÄ?œ—J¥Z½z5Ýpìvû?þñ–o·Æ,ÚÛ+**Z±bÅŸþô§‹.ºˆçy:MTìÞ ‚ÐÒÒÒÞÞ.uØ1W'Mšt÷ÝwÓ.bò¼:­CÏlq§R©233M&Ó¥—^ZTTô÷¿ÿ]Ü I%p"Ýng¡68âÝB‡Ú0ˆ‡Z­6--MJB父´´Ü{ï½wÞyç/~ñ ¹\Ng͈žô,,;·Þf«*Š;3^)éñx¾ýöÛÚÚZŸÏWPP Îf–!äË/¿üî»ïfΜ9nܸìììÔÔTŽãärù¬Y³<Ïk¯½&툊Çã—wè ÿoù­ÑhØÙbÁñù|;vì˜?¾\.ç8nùòåeee===Rç‘Ä3ý¯½öÚ‰'yä‘ääd¯×K‡IÏJôlM–™X^^Ž1ÎÏχ‘ÒþÛ·o_zz:ÆX­Vÿþ÷¿/++!??ŸÞ½ŒJN§sÓ¦Mk×®U(Ç-[¶¬´´´³³Sê\#íRó<ÿꫯ?ôÐC:Ž…d ¶z„§N¢muõÕW/X° 11±¨¨Hl¸ÐÞku ü~ÿ¦M›èåœ111K–,¹ÿþûo¹åÚÓr8ÿú׿XXÇ~øa]]]6 Ó¦MÓjµbOœ×'Ÿ|R]]Mצ^¯/((˜1c†Á`ðù|RGCèðáÃÛ·o§ë=66våÊ•¬=3h$¢Nìܹó®»îÚ³gkýl¶V0!䥗^:~ü8=ˆ Wœ¼ýöÛï¼óŽ8yA¼®TŠŠŠÖ­[WVVF{ýôô¯Ïç;qâÄÿûÿ…û«!„Ün÷3Ï€ !ôÝwß12Z € !çTQQ›’’8œe6›¿üò˯¿þš©s]l¢w ¦­çñx¾ûî;F¦UhÏR,|éûÎÀ~Âþ¼aŒôfDÂ-[¶¼ÿþû&“)33S£Ñ8ÎÚÚÚÚÚÚAÏŠ ·6¬­­}饗"##ív{qqqWWWðÝÁpká í9BFŒŒs„HŽ¼ššššššÀ%Œ4²X­VzBí…€ó€=x0 õûغ fP„5(„ÂÚÐÎeáôÀyïÛ2œaΕaDL3ÑÍ ûoD'd!Þ° üc¡G ¬A!Ö kP„5(„ÂÌe=! !!a@ÂàAÂàîY£J¥ò®»î¿þúëwÜqGàÂK/½x«Ûá»×( â)”Ãý„h$„„„Áƒ„Áƒ„!”ššJùÌ…sÂBHq»ÝFÂOq¹\}ü”ñ„h$„„„ý ƒ ƒwÞŽÏçS(Ö'ä¼^ïC=„áÌñm½ž¡† Ã"„èõú¬¬,­V;D¿â¼\.Wee¥Íf;ë7ý„h$„„„ý ƒ ƒwÞ„cN'—æç1ø|>§ÓØ;ÂBˆA Ç1ÆÇqÜ9籟„ð¼ að aðú“çùQp²°c™LØX¯×K\> ¬A!Ö kP„5(„ÂÚÐÞb `ô„5(„ÂBa !€°“e„µÞ·‰‰ÉÈÈèûÐÃL„úúúŽŽŽs½Ád2JøèŸÏ·gÏžºººs½ž$ $ $ ÞyJ^eά)?)„„FÓÔÔÄT7c¬V«Ïõ@KBHNNN[[ÛðaŒ³³³Ïµâ!a@ÂàAÂàAÂà7¡äUæÌšÂõú±×ëeª "„!^¯÷\?Å>nQ}·$ìH<bŽ›0qÒ˜ü|ºÇa*á¤ÉSÆž&b*áY‚„’W™3k CC #kGg‚„Áƒ„5nÜø¤¤¤žîn1; »»-馜ÜÜÕB@ƒB±±±)©©fsSkK‹ÔY΢¾®®££ÃdÊŒˆˆ”:ËY(•ʸøø¨¨(©ƒœ“R¥JHHLNNf³¤÷d€L&›>s&Bhßž=lÛ²Ÿ!”šžŽ1®«­e6acC}\\œÉd*.>ÁZHF“ãt:zzzXˆŠŽ‰ÉÎΖË!–fs]]ƒ9ûiÄ\>ÑGÎáÿ0Æ©iiÉ)) M4 ccãLYYÍfsScÙ$O¨V«/œVÐk$êÐÁ.— ±‘P©Ç÷Š ÄhŒ¶Ûív»Ù„m­­>Ÿ/*::0S Éig¾ØÇ?ú\(11I.WÔ××;ìöœÜÜĤd³Ùìñxú“ ¡G80&-=#99Y¥VcŒêë¥NÔ ‰‰‰‰‰‰ÉÎÉi6›êëÝn—Ô‘~c|ÖÙ¿Lñûý_ùbøTû µZ­B¡°Z­Ré !ÄãvGDFÊårŸÏ'uœ‘¤¡¾®Y.·X,„·Ë©×k4Z±Ž8P '//Ó”ÉÉd.—«¾¾¾ÙÜÔm±Hê':::ŠöíMJN‰‹ËÊÎ6™LMæ¦Ò’Fv—n·{÷®½^d$[/l¦ ÄxB•Zò3_]|~BH­VC!ñ':&F«Óy½^›éƒž¾A!ƒÞ “Ë{}}½¹±‘Í-§ÛbééîîNJ2ef Q1Ñ1R'ú‘Z­.˜>£WðÀþ":4 Föûý? ‡#%-cbbb²²s!ÕUU<ÏKgð @å© Ç“0vl~NNnWgguuUOw·Ô¹~¤V«³²sâããéñxG{{C}=S]¿ß?bv‘ n—!$—îþ&ýDºÙ;ãyÁív3>ؘža’Ëå'KŠ{zz¤Î”Ñ0YfØôôôX‹O”—•¦gd$'§$$&¶··‰……„z½!-=ÝãñÔ××××Õ9½ç)H˜ !äv»÷íÝÓëE¦R}ÌÉd$¡F«8i’×ã=vô› N‡×ëU)•gþˆ‘„”R©t9~¿?ðEÚlÖ£GŸ+ B­--ã³VAFö&Ë !ÄçóUWUUWU%$$º›Šâv»ÊNžlhl ‚Àæ‘ÍT½`ŒõzƒÔ)ú"—ÉŒÆhÇ-u¾ôtwÇÅÇ«T*·›Ñœ±qqJ¥ÒÜÔ$u³Ðjµén—‹åË"""Btö²ÔY‚…p0èZoii–:HoV«•ñyz#ûs2é%Ì]]RéKccCl\œ)3«¼¬”Í–LMM#„Ô׳Xi …ÑíPÚ¥Òctô鳬#B΂Á=c C”A„ššj–s¶µ¶¶´4§¦¥uv´···K§·ä”Ôø„„†úz+“ç·zzzèy–Wñþ¢}ˆí„ý…€‘§ºªª¶¦†Ù!GQiI‰\&‹Oèèè`mw™˜˜Øl63Û[E#¡À°Ÿ°Ÿ 0òôñ<¦ø|¾#‡aŽcpyôèfO¥ƒa6f²ð'°pÓ£¾AÂàAÂA „ €±“ÿéLÑÀ Œ$ì#ÈNȈÀ„ðô am¨ ሸ¥$€‘e(ŠËœ#¤A !£àú†Ž^¯W(!BHWÓ×BÀ‚!*.¡/„Ç ‚ðàƒ ‚°nÝ:Œ±p† º÷Þ{§M›†1v:+V¬Ñwk`¨ ]q q!¤AûÛß._¾cìóùž}öYúbh£ÇqÇaŒ9ÎÖЗ!-.¡œ5*½ýöÛ !‚ Ð…çž{.ø¸#z–$ì0O’‰vaÞ†! ƒòY£CQ\†dÖh`PŽã^{íµ×_rûí·¯Y³†¾!T¿ @˜†âš¡Ñ^Aßxã—^zIŽãV­ZµjÕ*BÈ /¼c¤úoxŠK !M°víZ1èsÏ=G{Ï?ÿÿüóÛn»Í`0ˆ©Þxã}ûöѹtEB>ü׿þÕáp sT0hÃY\‚ZËõêÕ«9ŽÛ°aC`P„]X¿~ýÆ !+V¬¸çž{Ôç 8@çéÉd²3fˆ¯Ožû¬ßïïUiô_|ñÿø‡ +V¬øå/9è¸!ñßÿþ×ãñÐå‰'ÒÍX¥RåååÑ庺:iGÌ!o¾ù&=zå8nÑ¢Ejµú²Ë.£ñššš6oÞ,ù5g7Þxã”)Sèz¬®®Þ´iÓÖ­[éhžB¡¸é¦›¤-„»wï/Q?~¼&77—.———wvvJ–ï§8Žëîîþè£Þzë-q(Âh4ÞtÓMŒì»cbb<ÏG}ôÎ;ïˆ[‡R©¼ôÒK%\ÑÝÝÝ[¶lyï½÷:::ħNZZZúöÛoóÍ7>Ÿ!„1ž3gŽ\†¿¸ òò z%£tË–-o¿ýv\\œ×ëíîîÜGËd²¨¨(¥R¹eË–ÈÈÈÅ‹/_¾œòꫯhd/„e©»»»¸¸˜^Èœ““£ÕjívûÌ™3#""è80ˆþuh gccãÖ­[o½õVŒñäÉ“W­ZGË»ï¾ër¹ñ™¡MxñÅÓ/œÅbyôÑG{zz0ÆV«uéҥ㴴´ôôôÚÚZ©BŽ?~ñÅcŒ³²²d2™ ÙÙÙ´Bû÷ïį¢Ã#ŸÏ÷ä“OVVV ‚ðé§Ÿ®_¿>>>!DYHèt:y䑦¦&BÈwß}÷â‹/j4„PFFÆ@?*„ =Ï#<ÒÚÚŠjhhxàèw²¼¼üá‡æyc¬R©è ¹Á`ÈÎÎîϹFÆ ú0Š[q |à !¿ûÝïn»í6„ —]vÙW\ÁqœÅbYµjU[[›øÎ¨¨¨üãF£QŸÏG/Y¾|¹L&{饗¤Z{÷µZ]XX¸mÛ¶©S§Ò=Ïóß}÷ ß³÷Þ{oæÌ™™™™r¹üª«®¢ñ8°{÷nÉ㥤¤¤¤¤ÐåãÇ[­VzåPQQÑĉéÎH¥RI{sïÞ½t„V¯×O™2åàÁƒb]ñx<ÒŽ~÷âóùªªªèFît:=zùå—cŒF£ÉdOcKÈãñ˜Ífz€ØÖÖÖÙÙ™ššŠÒjµ¦ây¾½½6Α#GÄVêêê~'kkkçÎK_OHH(++“,.èIŠË€»t?²zõê+VØív»Ýîp8ÔjµL&Óh4ƒNñÉd²ÈÈHFCßàp8œN§Íf»å–[è $Wùþûï­V+]ž_\\Ü믿ŽÎèÓ÷»\®{î¹§½½]¡PÐ7Ð×Ï|ÿððù|ÇŽ›7oÆ8??üøñâˆYQQ‘äGߢ#GŽ´··‹3&*œ:IDAT++¥š°Þ‹Z­—ÇiC~G‰`BŽ=JÏ­æçç#„²³³é·npã¢ÃÆf³‰ˆ´]®Q‰Ã2 ‹Ë`†F !gö™xž§9Òbq¡½½½½½}¿nˆìÚµ‹ž9ˆ¿úê«Å3FÆE©o¼111Qüß &îÙ³Gò„6›M\¦—ë±iÏž=t6Gffæ´iÓ¢¢¢B.—‹ù¢gEO¿QâÄ.F=©ŠKæPÑó@r¹œöè脸—ñûýôu:_KòKßDEEEííí ¡3fÐ6=yòdww·ÔÑ~’’ríµ×Ò`.—K£Ñp·bÅŠC‡I~©u]]ýj¢Óätµ&''_ýõ4óÖ­[ëêê¤ÍyèÐ!º– Å•W^)®åÀBΠ¤¤¤À‘già •a+.!¸é¶Ø¥s´bbbxž§Éü~LL Bˆž¸FA „öñ÷™„C‡ÑI(â¤ê½{÷ŠQúi!O¸råJ:‘Õår­_¿ž^bŸ’’²dÉ’7t^kh¶··×ÔÔäää`Œ'Nœ˜˜˜ØÔÔ„š={öW\!Â}ìP´!!äÈ‘#?ûÙÏèä[¬¨¨ˆµL©TªI“&Ñé±±±tJ3BÈf³UTTô]]Â>>|@ãá!O8 Tä´áLH£Ñˆcݽæ@ößÐ%Ôëõ≘¶¶6‹Å2¸Ï Õ)’!-.ïÙU5cžçµZí+¯¼˜Œ^âÊæ ¶oß.öB6›™„sçÎ-(( ÙvíÚµ{÷î+®¸‚îÊ,X°cÇÉï öÙgŸÝwß}cN÷ç?ÿùرcZ­ö /¤ÝÄÚÚZFî·k×.Z›éD §Ó¹sçNFÖ²H&“=øàƒ'NœðxQ­V¯^½ZòÓþß~ûí¶mÛè—266ö’K.™9s&-6v»ý7Þ`aB;v,pt±¸¸˜ÁÃ2³Ù¬T* æÌ™#VÁŽŽŽwÞy áh‚OßÓª×HFˆ·ìOȱ`ŠKÈz„ÝÝÝwÜq‡B¡8s»Åû|¾A÷²‡!äàÁƒt•³p}µtéRq€b÷îÝô&‡.))¡·Â™8qâ•W^ùÅ_H˜òâ‹/šÍæ«®º*!!¶¡ ¥¥¥7n”ðN­½ÐÑQñ¬S³‚EGŽ©««[ºt)ÎC)//ýõ×™š_‚X]7>††¡¸„¬Ò+[CõiÆÞã!ÔÙÙÉN!ܰaÃÆé2!„®~BÈÃ?,nH,lE‚ üç?ÿùàƒrrrA¨¬¬¤8Kž-Ðßÿþ÷×^{.³Ðn¢'žxBœùFùïÿ;aµZ]WWרØÈB3>ôÐCâW.ð„Öo~ó1ùð÷YÅvë•êæ›o¦ ©¾øâ‹¯¾úŠ.K¾öÅܺº:FÎÚ¹sçîÝ»é²äm%†âÖwÞKOO§·àB=z”1¨s%a'¡ˆî¬O:uêÔ)ÄêŸl7ªW0—ËuðàAÄR3²ùU<×o?ëÜ:Õbˆõ—Éd¢;œ?þ˜µ,bª­†S˜ÂyóæMš4iÊ”)z½!ä÷û?ûì3¿—#4]¨@KŽb&99!T[[+ùsÊ@ 0-„³gÏ.,,ïõí·ßJ> 0º¥¤¤TUUq·uëVfG)ÂS®#¡½n&11QœÜ±sçοÿýïAÎ;ÒkB/œVVVþñ<ï¯8¯‘Þ†Œ’ëG–W^y%;;ÛívWWW×ÖÖÂÑ`¨ˆòžÂ´–••‰Oc¯&„³0-„PüP¬ŸB¡ÐGÈd²‚‚‚~öIyžïééè3|>ß¹Ö.!Äívk4šþã#„ôÑy‡„ý ƒ ƒ ƒwÞ„ª2ý¬/­,½jÊOª(!D­VGEEÉå ÝŒÛçóuww{<ž³®ZBHtttVV–V«þl”Ë媬¬´X,pÐ að að aðΛPò*sfMéݤE’©Î5ÍÚÇ!c,afúÛ!a0 að að aðú“IZeά)¡?cŒ p€°…@XƒB ¬A!Ö k2 ¯»$=Ba !€°…@XƒB ¬A!Özßÿ;>>>77—©ò<êÔ©¶¶¶s½AòÌ#=¡Édš;w.S`øùýþ;wÖÖÖöñÆ·e ûáÌ„?Ù÷B ƒÙlfíéƒá\ÍÊBæ2f̘~>€Q cœ››ÛG!d|[F°ÎL(ï•Æëõ²ve!!ÄëõöÑj’gé yžgm¥0üÈi}¼‡ñmAÂ~83!œ#€05† œ¶(Šø„kO^op:‹EêD£ÂQB¡Pdeg'&&©ÕjŒ±Ëåjmi©¬<å÷û¥Ž­N7yò”S§*²²²[[[º»»¡«:¤ Ž*•jZÁt¹\^S]ÕÚÚJ‰OHÈÌÌ2DEí/Ú›#Ƙ÷û1Æ<ÏKeôƒs„£ÁøñäryѾ½õõõjµ:""²±¡aÑ>N—•aqü~_cc#!¤±¡Že‡ôG<½Á˜xìØQÇsá´‚„„žçÝn÷žÝ»’““««*¥Î›Õºsǯ׻kç‡Ã!uœÑz„#^B|‚ßïo6›M&S||üÁûOªÐjµ~¿ßÚcÕj5R Œ N§!Upx@!ñ4Z­ËåD%$&Ùl¶ööv…BAçÈøy?ưŠ /°—ñdÇûy„ötET*•>Ÿ!¤Õh½^¯Äù€mPG<Ÿß§P*B<ïר5:]DT”QàŽãRÓÒÚÛÛ¥LƒB8âõôôèt:N×Pß©×Ïž3§³£CqÉ¥— ª¢¦œ@~r¯QÆçÙŸu‡ÎTfI656æææÍwøÐÁ¦¦FBˆÏç«««åyÞãñôŠtfB¦œëØ‘©EÚýá‚«¯ ü]6›mçŽíçÝÛ VÛ.ŸñA()>1yÊÔ™…³šÍMN§K¥Vi4šŠrè †DUee`Is{<† ÂÑ µµuïž=™™™é2™Üï÷u´wH 0jUT”÷zeDvC!%l6ë‰Ç_ÑßKËFÙî áè1ʾš0<`Ö(€°…@XƒBø#¥RÉÔì^C-¼ !Çq²³‘Ëå¡uëÖ].ÿÕ¯~5}út½^ßØØ¸aÆиæŽ;î(,,Ôëõmmm}ôÑÖ­[‡ô0–çùææf«ÕJK!„~ !ÆétÒÿÅwuu544´µµ‰ æÎK–””ÔÕÕI'Ñ]Ø©S§Bô Þd2 †âââ^…B¿`ýßå%$$Œ?¾µµµ«««?ŸÓ÷¯ ?…¢È,x,L¨ÄÆÆþêW¿R«Õ7nt÷`…ðæ›o~üñÇår¹ÕjÍÍÍ-((ÈÊÊZ»vmaaáâÅ‹éÖØÔÔøO^ýõÙ³gûý~§Ó™ŸŸ?gΜիWvìØ9sæÆM›6 ]-ôz½/¿üò¹~Š1¦ƒ;wîܽ{7S££ãÆËËË£¼}{ï{úáÔÝÝM÷ˆ1îèèÈÉÉÉÉÉ©­­k¡ÓéìììÔh4G¡PÄÅÅÑרØÈq\rr2}›ßﯯ¯‹‹‹ŒŒlnnæ8.66¶µµµ±±Ñd2Ñ_dµZµZ­Ãá0 QQQbͳÛí‹E­V»\.­VXéOU*•Ó錋‹ÓjµÃØ< _ŠŠŠ`+‰Ç{lòäÉ÷ÝwßþýûKJJת8`¼úê«årù_|1cÆŒ‡z!tÕUWéõúýë_÷Ýw߯{%¸è¢‹fÏžÍóüÏþó9sæ>|X£ÑЩ(“'Ož9s&!äŽ;î˜5kÖ¿ÿýoŽã/^<Ô°r¹\¥R ‚°páÂãǯ[·!¤P( ÏóGŽéêê*--A.—Ó³qŒX´hÝÏú|¾O>ù„ Î!6›Íb±DFFêõzú¢Ë劌Œ\°`ÁÂ… ¯¿þú‰'ºÝnú£yóæÍž=[¬XF£qÁ‚¹¹¹¡+®¸bêÔ©ãÂÂÂ[o½•ã8‡Ã‘••uà 7,Z´hñâÅYYYâ(½Ó錎Ž^°`ýѸqãèÓÌ)¿ßŸ––výõ×/\¸ðÊ+¯4 L l„!äã?†B‚ ¼ùæ›:î®»îô˜óöõO=õTDDD}}½ÏçÛ±c!D¡P$''ŸþøãtB Ëåê0"Ž‹ž8q¢¾¾^ê8àG‡C«Õêt:Z¨"##ÇŽËó|EE…V«MIIñûýcŽãzíû8Ž£‘‘‘---ô™!&“)))©££Ãf³ †¬¬,­VKG\ŒFcnn.Ïó§NR«Õ©©©¡ÖÖVú Ñétuuu2™,111++«¦¦â!‚Ïç«®®>räÂ~úúë¯#""þð‡?ìÚµë¬öÙgŸ=üðÃóæÍÓjµât¶@!,++C§ïãµjÕ*ŒqSSSEEŹz'Û¶mûöÛoB‚  †3f`Œ‹‹‹BV«õرc¡E‹ †eË–aŒ·mÛ6¤ß •JµfÍšää䯾úŠÖ9‡Ã‘ŸŸ¿lÙ2—ËEgëÑ“.‚ Èd2§Óùì³Ï²P'Nœ˜ýÿÛ»·(Ú?àÏìùè!]MÍ׳•X"YiÔE…˜ÒUD]”$D…–éJeQ]DetíEat‚¢0°T¨ÌvuMS3]m×vvgvç½xx‡mu×ÃßÃøßïçjœ™vŸvçy~ÏyÓh1÷òåKäI¡)ZÁòz½‰‰‰n·»½½ÎÉr»Ý111´75›Í¦P( ß?è¡Édr8:nllL.— :Ÿ9!!A„/_¾Ð¬§R©ÒÒÒÆÇÇi´s»Ýf³™¶=Ott´Ñh]‚ftûöí;wîBÐLŸ½˜˜£Ñ¨V«Ýàr¹ºººrssóòòž={6rP|õ'N9rÄår]¼x1È×I‡ëéquuu||¼Åb¹{÷®8W…RSSC×°wvv^½zu±{üh\œ/J¡õtßó4ÞˆUu)(..¦ý´n·ý¢RC¿úØèt:Fòl\\½ªR©T*•^¯Ÿ˜˜˜ÓËr“žžÞ××7888>>N'”êt:µZm·ÛÅÇàû÷ï###b ¥Ë0è1í2U©T ðÿ„…€Ì;999„ÚWWVV¦Ñhèù÷ïß¿}û–æ4ÑÅo‹©œ‚ ô÷÷ÛívƒÁ`4£¢¢’’’4Íàà í·÷íh¥“T¤Ó‡+Ž\.×h4~÷¾©­­¥%6!äÓ§ObyH»=‚׃˜s ¬¨¨ ÛÙDÁ={öTUU)•ʆ††––ñŸìß¿ÿÌ™36›­¤¤ÄétÒu r¹\©T.j [ss3µåõzé;Êd²œœ“É”••õøñc·Û½ìõ jß¾}ôqD¿¨DpG$úädgg3 c³Ù!‡C¡PÐQ=ZoeYÖétšL&BˆL&S(v»]£Ñð<ï;v@þ+tX–åy^§Óåçç ŽŽÒ¹6‰‰‰±±±ÃÃÃv»ŽšÍfƒÁàñx"""6mÚÔßß/…ñlX¡‡Ùlö „Á¶—Ess³ïŸb¢Ùmddd~M…9ÂúúúÜÜÜ–––†††à…rrrr]]N§³ÛíÛ¶m£ë%!ÇokkS©Tééé<°X,ùùù2™¬µµuQs²J¥*--Õëõ4Ùt;+Bˆ ¦¹¹™¨LNNìܹsdd¤©©Iœû¾\òóóis°½½}hhhyä¿'‡ÎÉüçŸÔjuWW—˜ýl6[lllFFFoo/Ã0±±±qqqf³Y–e£¢¢âãã"""²³³}+°G­Vk4šŸ?*а°0½^ït:GGG⣣ŞUú)))V«U§Óedd(•ÊePaE{ýúuQQÑÔóRhÌ8k”'ƒ9s„111IIIQQQ3Þi2™ÂÃà !F£qûöíây•JÕÛÛ[UUuêÔ© 6lܸ‘ã¸'OžÔ××/ê‡.—ËÅ-ÖÄót‹5ƒÁ@?bA¢££SSSµZí²÷ ää䤤¤ÐãçÏŸ£_tyéõúU«VíØ±ƒ"ÇqÝÝÝ¾Ëø¬V«L&KKKËÌÌ$„x<ºv‚övjµÚììlûúúÒÓÓ].½úëׯիW¯[·.33³µµÕl6'%%mݺ•Â0ŒÝn·X,ô K#Ö®]»~ýzBˆÝnïîÂÃÃ}+õr¹<22ÒívÏo„A¤ó¦5ã¬Ñäää””‹Åòõë×ù=ç¢3 “œœ|h]œ]éפÓ/‰O B<ã‡Þ@¯ÆÅÅ™L¦®®.–eƒ™ÚGx6iöM| K Ã477gee566^¾|Y&“Íig™…J¡ŸšššC‡ÑÉ»vížÇ‹O!Ã0»wïÆ|ŠÙ´™ÙÔÛär¹^¯ÁápøvÒ6Q«Õ“““GÜäO¼j0xž§]# ÃÐŽV–eÝn·ïÑK´Éè{Éï§=Ax½Þ ë¸þ—¼¼€©´Y@ ›BqmR ï¥ººúðáÃ.\hjjše¡í—Â9·½ÍÔ Eð*½Úßß?00°”¹tÚ/€îdmµZ³²²¬V+°dI B܈äÇ~ó/`éÍòAçùi×K‚àr¹Äp¿¤[ÕøþIÓ¾Çqããã3¦!VºàMÕ¼¼¼’’’?Þ»wo)ö]$K™QƒL•••çÏŸÿýû· R˜/š——G÷œ$˜/ 0£GVVVÎ{Ê(‘B ”–e%5ã °°öå²,ûðáCÌðsíÚµžžßqúy@ ”.q¾h[[úE¦ò]M8o„ÛÖÖFg?}úÍA€©dÌP¢†‡‡Å½ßüV^ÀB ”.´–6'€†@! B!„4Bi„Ò ¤!@HC €†@! B!„4Biøõ ø?¡R©Ž;Æ0Lcccii©ïÁ7ý¤!A†YîT,€5kÖÐmêA BAxžW*•‹šÊyày>Ð/ÓJ$Í+7…‚ °,«Õj !Ä ‚àt:ƒß å¼LBBÜn÷¹sç!^¯wêA ú—}Z­622R¡PK‘ã8›ÍƲl –=Í+=…QQQ©©©:n‰S )N§óÛ·occcAî‘x^&Há,LM!@!hBµcVˆç¢Û¥ètIEND®B`‚jas-2.5/images/edu_jas_poly_classes.gif0000644000175000017500000001512407773340004020500 0ustar giovannigiovanniGIF89aØÖñïïïÿÿÿ„„„!ù,ØÖþ„©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡Ä¢ñˆL*—̦ó U¦ÔªõŠÍj·Ö¨÷ ‹ÇdN@€N«×ì¶û OåºýŽÏëoç¸ÿØ6·GXhxˆ˜hÐØèè6¨(9IYiÙÃø¨ùyéù *Š‘¹iú×9ªºÊÚªX*WµvëW—ꪻËÛÛt›ÉØw Gü–뛬¼Ì<¬&ŒF =<+'P‹ÜÜÍõ ¾ÕMN|­­=ÞŽ>,¿IW^n|š/WoßOö ­;yðJ£"O?ËðéËÇ¡Ä_f ,ˆQ]Aþu '6|²£Ç‘YŒ60eÊRÄ"’\å0¤&—/kþ8‡N ÊœÁx¾;¶Ð&«˜2ÑŠÑ¢Ž&µÔRVÀ¥Kg}Š•S™N³JjÐ  ªÐ®z= ƒìÖbfÑRËq#Ow>³µlë6/ µkééõU®Xkƒ ëú7q¾}Ù VŒ®]bW"Ô)²fŒ—ÝüõØIÊ;+'ô :õbq¬[sÁ«úŽäx(3 4¶î zûþ <¸ðáăϾ»P`” çÆö“mòéFPå"ìëÜkPén¨svmÛÁ›wñý¼ñÙ«?º|ø²Ç›rO?¿óþõÿ³¿ ~þ Huü-B`ìy&`‚6``„záZ…RQÞ„2`ànèDq'b‰&bŠtèá‡*‚Áâ‹2ò‹1ÎøË8îèL1ÞÈ#éIä ?úX¤ó™d“Ü¥“ÕȤ”V>ye¶˜e—ûyYÄ–U‚I&c–©Ôž‰f›jºéƒ5ÂIçlÖù‚œoâ9Ò…~¶ö%Ÿ69gú J8S†Ü©h „î©&£œ8i 6Ö`¡™Æ%’•ZÚH§Ÿ‚Jj©˜rxjš¦ÚÔª­:ëX²*é¬{=°i_¦êÊB¯kýÊ%°iñZþ+*·ÛÂr,aVL€ËzÊlžÈ "ÕdF]Z-&¢Åu.Ònk·!œ Psá¢Â­¹:ÌV6´¶™‘ò ¢úêûÖµŽáOOÚ^6ϼŽMë® ©»ÒA·–›åŽ!l²ûL‚.$ÑÑÕpÁ¶A|pš~kïǤI…±‹Q±Åäaì¯ES\F—Ý%²R$Üq¼˜¥Œ°‹‡´l1±ÆŒÏ&_d´ç<èÎéø,˜JëZE.v.‡dt›4óà otµ4AC Âr]ÄÜ:Б}ï++¸5×gý*¶ÎÕÜ6Á7GŒ6­uÇmÁÜ0n{JNLu Å׃c¸àþ&±ÖMUd ƒw{ôäŒGžÑ\mødL¯¼S߬x]FmÞxçºÜ“CºåkŸÌÕp[m›Ì”¿"ûà´×^èvgÈÛ³8<ÊkÿýœóÔûŽßþ2òyrÿtîÍLÍ¿ÿ .ðÇÀrÍñLl»ûÞ¯¸oýUn9Á©‹.sÁC«?·…¯y¼²Ÿ³7? œh QIˆC#¢ªŒ˜¼%&Ñ#b—þ ¸Ã¯”pKSdH]xE,â¿Ø"»HŽ5Qª@9#áÂ#D5¢ñÔZÙ½æF[ñ}VÚçx =ÑLmÌãðF?²“ä£ y½t=D’€ƒl Á?æÇ€œä‚(Y,B†sNSž+‰+Man T%|L9ùqNTÔåÅe˜’M­|´¡…ÍÚ†J5¹r•8¤åyËöì± wæR ƒT£w¹l_ÿʆ;ašc1]J¦æZÑLHVOlK+g²ZæA“ÎÔ79µÌ¨°‰¸¤Ù.{Æ¿ÿÎ‡Û ”•Þé«xRlž¬çm˜†Ï„þ®#üT7þ³äKÅ%M †t†BPådîyéÛ Õšƒ˜tr¤$-©IOŠÒ”ª”5=å°°©²,£æàJÑèÐÐ~Ò4Iìà˜Òîé°^zlêsXHeª ®‡k.ëDN×ùÐ+õ”š@õeϬ ·ÿ‘mH…‘R×iÈ‹jS§%”ªÛÌi΄ °¨•å@ËJϰ¾ÑFíÄDTÿ‰¾†¥u¯¦±¨;ºjº¯FF®¨IåSgêO)õô U(ÿNƒÀâ‰%l6…yCy&ÖI‹ jKåÒØ·õ.¤žšdgIYå¬Ô¤ ¹a]íºÙ&nv§\Ââ|0·¼íŽ™»*¶Tž«­öþËLà¦=™]p9kY·"v¹ÿ@ghо*•ºEè°Œë„pÖ![rˆvu¢ÝàÆ–§Ñook:‰Î¼ç݆rQ _Ù¶œÈ-É1è+8ùÊç¾ïí/ŽV{@þæ×tÿ¥Ûô|D`-=×I¼Ýmo/¬`îR,› „𫤠Gêµ^4pxA±çIÄSZ¯ XœñÚ})¦Fò"'¿Çh‘ñxƒQ'Ž, ¦c<Q5>f&ÊK‚#O@O‚ñ»’\§%§¦Éo}²6‚¬•ºZyPX†ÓAÃå¤ Ƀ’+Ç,v¶êÌ›IóŒÙìK¦ÇÁ*s›äþÊ›£A3Ÿwåb3×̓~eá|9gJÖ‹m›HxÁŠ®¥”•qéðöøÐ~¶å‹Yi·„š–&µ†§—3Œ=lNŸZ7ËvE³]h£ºsÞMµƒM£dhšU‰æÓµA 쇻!ã>&·Ounq§›ñ®É¸yÝmjÏûÊiŒS„ñ ooïÛU÷¨÷Š• ðOœßVÑÂîfd»éáÌø'(ŽíB)ᓸ´Ž•ôZ¢õMÔ•vϺ×%71QòEãþ¡9¡MÛþœOöå˜-—Í7ÙrLò\çú¹©u}l]} _7 ‡Î!„kéŸyЍn§)?ëçáúÅ­þC;òÓëà!{ Á.©?ÏPåe2;TÐibÇÜ Ú–jЋ ·«sºD·"Û„àÀªË.ßÞ÷Î2®üï5·ìw /tà ɹô±Èeä]1J7ÏßÅáÓVùró§îÝÉ<7]¸CцÈf!ØQö·¾=z¦½o×+û¬¤œdE¬P|v=‘ï‘çþûÞH¢æ ™E/·é÷˜i™æUç‘UäX€–Ñ=j~ôWö—zø·veG|øÄWç“A~e ¢uPl“~ñ§€ xssÇ}v"|OÑY&3ˆ^Ò´~53Q\yxÇHg}&~Øñ,¥‘O9X}ieO7S/EÎw\^1ƒ‘¦T@þCä³4ÄLì·?ã7„lÔ€øE<Çâ€4XgˆãxcT…°6{oE,GxÄõ…z†+6† rnfXl5ÈLkXÚ§…x]rmr*hè º§Cxh-óW{©f…þF‡f‡ËÃ|0È ‹èU[˜m’è_HQ(!ˆþH)'qmf‰Z"x£ø š˜v†Ø}m¨E§È‰’2‚ª`a&‹³H‹ªxt¬h‹Yw”ˆ €ø¡hm­HnNÆtˆ&ŒÅÆHÀH¤h@—‹ÌØŒBðŠC£Œ€Ñˆ„¸e˜x€Ò8‘Qw¦cÚˆÐó  ˆ[QŽ]ˆ‰í¸gé¸g²Ž‹#ŽQìxU&Ó¡£ãŒLGŽûC"WÀ ´;q|‰‹Y}RC^Ö—8© çÈWSÑr5ïD iŒŸ4‘ÉL !™\ÿa/²U>åYµQ~»t~«3TkeZI’2y~S¥39 5‰U¿d"þi„ÿè‹ÞY(HU>iMø”7¨’w‹g%•å#ýgMiTTEðgI™,im5N(=z¥ƒÑó`ù{Ué?PHé§‚È–c”g(–®$/yM-X'˜ƒn9ŽõXä´–ƒ™—y²—ñA– g–¹‚8h—ŠÉ^†©VŒÕƒ‰™“_ј©H$~IT¤:JÈ6›yAšŸR˜“éS/% Sù‹K÷™×á]Ù·˜!g)ºyq·ypxKʤ“ ÞD˜Üœ"QáXœêXC±œ£ç%éˆã5~︛yטÓiÖ™’Û¹‡©½ ‘ÞÙuÎI•䩞(|þè©ÐX?â™qŸ$Ÿóé ®ö˜‹´èŸ Ÿ ñŸÚ[öiúß8`zˆ•Àb Ÿ_Ft¡ š/tõbú>ªkûi¡7¡‘˜e‹" Ff‰Š<4¢ 9¢ZÒ¢&ŠkºJnV¡¸9_.JdÒGu¡‚x2ú†Q‡¢Þp£B2¤ùW£¨J>šmr¤h†b¸ö¤äržB—¤J:–k¤ÌÖ`«´¥«¡¬´hVúlæØ¤ªÖ¥Òx¦dZwvmbÚ,¯µ¢É‘2\Z Gi8lj{nj$Ÿ§L† tš¦481ƒšuzº§s¸!â œ‰ò¦8ÆgUj¨ŽY‰.‰i È&>'þE‘º‹|P¦@T©šò °†Dš*©ôÖ©üù©¦šS¹Ò§šzª–¥9„Á¶qGªœQƒ—— ©J«z«óø>¯Šn³&ßqŸã€FÂ*¥Çú'«¸€Ê‰+0”œRÅ’à™‰ºX`ŠX%ÖúFÞó˜Üš8ôÙÙjxw®—å­ûy®ã҉䊣à3­Ý…¢ëŠBíÊjzBñŠLYJ¯í€ÏJ¢gé‘ y­µ£¬ d|&|1d¯ÏtbI2"UD‘s°‘V’èt‡‹9úú£{‰Ÿ5šq!0Sh/f8»ä§K‹5Ùe¦©:Ø>⺉İQØVcÓW¼“N"£²’þÂui“R€Ù7=»p„³ï*™¥)˜Ô-± !h˜œ ZU“šcc³ ²ø:™,ø„Ó4(ë.Ak$y¥••9€R;Ahû¯îJ¤Iã“Cû´®)·Ì¢¶Á¶$˜jåWq»´Õ´u[=4›÷Ä%[³JÒtÔfú7†Ù„;Ë„aá—WÆŸ¬ÕÆR‚p]2¤‰™=!—rýÆN­p[ NyE¶cëÖƒ[J¾WœÕ;VÆ)è3U¥A{m‘‘eÖ0­vik•?郣—Óó< £š9M׊’Öî8°·{Ù€Ö‚ˆU­ÚMÝØhrÚ~JX~É¥=q®ý·½Ø`[ÔYÆÛ‘8Ôs«Ûï»ÆÅ-«¬­¿ „Ò¬ñÛÝk¿á¼BókÝÀ±Ú³ÍSÃýʄ٠ÍÝÝíÝÌÝ—á-Þþã­Ýà}ÞTtÖ€gÞëÍ+íýÂï ßñýÝ€Wß(LÞœßúÞîÝßö&ß]Gßžtû=ßÎz÷Mà þt nÁžiÞÁN‚®l‚ÿá~á®lîá8Ý;âDˆáº{â2˜âª&â+NÊ5Mµ 㥌àhöâ5®‡'·«:ž =4îãÁm㯗ãCÁ}WáH^¼ ÎBGÎäÇø×ÔåQ.å¹ãV®@.hZ¾å-^À^^g`žŸbÎhNÎÀUnæ yÜO¾æLFæ=üæŽæì6çúVçîyçí\ä¾çx~ãþûçrçö9èA^è¿yèÏ—èP¡æ‹þfyé‘èÌFé•n錚^zNž^v þÄ¢þ¤¾N™nêK\ââ¦ê«ÎêDîy¯ë±Þç GëÿôÜ$¥Y—Ž1¹nVÚȆ(ë°Xë>"ìÃŽ€œÞ<ÀÞMÉÎÔËÞæêìÕ íb5‰¾^êÇÎ!×LXØê€Qím‡“ÅÀ(©º'±ÔØX’¾ÑÜn&Vc¶9œè®Ø¹nê8îg86@ To ³sÙQ¥•]´™íÌŽðNº¨„m[´ƒUH ÚE…ÛÍwëIÌð ß:“–m¸ÖÓ7êwïÄžñ´ï<}·\‹˜n˃ˆ}2Ñ-†Ú__8o{•"þëòšé¸%/íá¾BÎËî§Ooͳ¯I¤Õ?™;2ï†îÆ6:¾Â¼ø.¡.õSÏŽùêô®ðÏ”ò½æí…•ðÓ¾sY¯õc®à^ì‰ö‹¡ö?[ö@ÿîo÷qHíNómüav¯¦»ÎI]‹mõöÂÝ×­ø¼eõ…fÄB¿Æ&…y¨¾i§ÌÊ’¯t”ïÉ™zÇ'ÕÍšoŽ o˜Ÿß\žw=·Ã%%ꦯnM‚¤ï÷$Nø¡Î+Éë±z{ÿ{µ?зû”§ûÊ©ªÿûtõ‚ q¾_ü ø­Ío?Ë?Á†tñ‹àÛc…úÒooÔÿÛýªì2§ý)ÇýþÕ›GÜpø¸ïýdl×ÏœáoCã_ìuî¿ýÐtî;ÿ÷Ú”ä KÃ1/´ýa”“V{qÖ›wÿÁPÉÒä!ØVm××eãÙ¾q< ŒÓv4Œh«åI"ï×t>¡Qé”Zµ^±Á×*Ð~½ÂX°Þî¸4ó®‡Õh¹án<–mï*»W®Þ·Ý dø¾îàÄ– ÑgÒ˜!&‹ì"-÷&ãô,]05SUWY[]_?DçèjKmogû2_ÑÊúüp1ÁˆswQa•—™›ŸOd/‹¥…«‰y]É:g©s¯ÃÙ ËÍÏÑÓ•­‹º§±ÅáþÉaÙßÝ=ãómµÕûýÿ!­”)|žÆ ,¦§?VZ(;BÊÛÂ5ð’I&cGÕMT¢DäH“*6ª*yÉJ–-S‚”9“fÍB._:ÊyÒa†pîÔ)”dL›G‘&U"(Q§Iz"肨éS«9¢.Õº•k×EWÁšŒ:5QÕ°g³zU»–­@³gŸ:$«è-\«iÛæÕ»wY]»;ùýLå÷¯P¼|'VLˆVcÇ!G–<r›¹ƒ)gÖ¼™³ÑÅŸA‡~2€tiÓ§Q§V½šuëŽ[¹–=›vmÏ¢qçÖíQ0É»><ÝåM‘‰'W¾œùã&7—>zþu Ïcý¶¾{÷нD÷>ž|ùšØ©h7¿ž}{fè‰w?Ÿ~}+ષ¿Ÿ›òý PÀCBŽÀL°ýlÐÁ³` )¬-ÌPà +ÃAÜÃI,ñÁMLQÅQ\ÑÅÛóÆiä®ÅqÌQ¹uìÑGÜxüQÈ!÷’‘È#‘ô*È$™l’¦%ŒRJ€ œÒÊ+¡1Ë-¹ìKË.Á S“*Å,ÓLç NXãô()èá…ۦ:Üx!F2ÞXå'êÉH}^f8`Z(6xå›GÞkƉ“#eœ‰¡åŠ-ºÇgŒÊ¸¡–¡‹ŽÚ‚H†á ’/2Æe‚RCà}¥;ƒr±j\¨ÅN»C¸ÈÆlµ?áÞÄì¹MA;î»h›n¢ÞÆÛo½÷Ìn¿ñ<ð—ú&<îeo¼ñÁÛ¶É)¯œ¶È1Ï\óÍ9ïÜóÏÑ);jas-2.5/images/edu_jas_ring_classes.gif0000644000175000017500000000522007773340004020450 0ustar giovannigiovanniGIF89a-Îñïïïÿÿÿ„„„!ù,-Îþ„©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡Ä¢ñˆL*—̦SˆJ§ÔªõŠÍRŸÜö g»äŽøŒNKû Ëçôºý”÷˜öý8—ÇWHá'˜¨¨H¨€¸¹ØhHéð‰ 8YÉ™p™ ʨçZZ·Ù™úijŠšÊ¹Ê*ç ;‹Yûjx‹ ©»Ë×ëÛ:êI\¬Š\ ¬L6ÌœY-0E÷éW}jüÌ;%(å6êìýÔV®nÝÎx-Þ}P¸Ý{?¿€¾´ª Î%€ ÎÙê§D¹€xh-ü%Žœ>[š®¨Ðþuïì8‹‚0á ‡åJÊ!¸ÎÝFléñ ‰$£¶v&jt÷è]Ç99ª›X¯¡Ð™$½£ $Ì$ÿŽÞ´w²cÑ¡ƒZ*]zD¦M¨´¤>h4çT’@Ùé¤6­SnŽ^b ®'Á›_é^ÜèÕš¾«oøˆVíÜ»äÖ9´ìŸS¹Š¥‹tžÛ¾YG:V[%XÈ'%Sfªñ²]ª™7gÛ¼U⾊¦Çέ»ØßÏE𖆬ùöت.iÃÍýøî×GmkSŒ4j¸Á$G¶5Ùwí‘Í¾Ž—#àzfK’ñiMì)¯íD¼½0XjÒ ªy?¾üùôëok;þýüþûû‡Ÿ,ìøKwÑ}'Ä} d ‚~-ÈÊ€ÊÓ›ƒ N˜È$ÞYȃ‚²´Ú‡šHv ‡9x!*šxŠ"2â‹Åb‡2>çH;¸x£„7ò¶O‰:ÆÀc€I 9ä E¾HÍõµdÀŠI²àä“– 9¥ U:ÙÒ^~ f˜bŽIæy”‰¦—`™e R¤éå™pÎI'˜lÔ& uîÉgŸ_™'S@Á&h¢# ªh‹kT¸¦ Œ6Jé“Vê AB1Ã¥˜~Ê)¨6hÚ€”9v*jªxªª¤>À£¬Š0k«©Öjë!‚g¨¨æ l¤Áz±«/MŠþ+É›è²Ì¾ÚG”8ëµÌNi­ªÐZ*-¯-^ n¶˜nk=Óâ .¸&¦›çnš{.ºêËîä.Š€§õj°ï¼´õëà½ï¯¼þÚ ð¿Å¶0« _ððÁ0E<ñÂJæíŽß ª»5D7+ÅÆnÜ1¥KzêÈ’ü©È”œLõº\0ËŠÒ Å§¬r8Ûür0ë 3¿?ü t!Hû5ôÊ<÷ìsÒ.DÓGïÃ-TKN_VWÍFÖZsmŦƶØW“m/:_g•¶Ñ ²­ãÖJê M©«a7Ý~Áò¶ zïÍ·ßöMBà]®6؆œóÙA3þÞ¸ãcU´'Yá½ ›Ô"îíåK¬9xœ?ƒ¥µ O°ºè1—NpåÕ*Þ‰ç´î«ë5Œq¹Êž>±°¾Ã­ûî½w+;ÄÀc.üðÄï6ÁÎ&K{?†f‹;ëÐ[/=áÆ.ïÛâf¯ýöÞ‹|—VÿÖõ^n>ê-{=û”¹ÿ¾?ñËkòQ‚/´ÜU« äÛß H9—H®l… عRÎ~‡+_þAUðËc­’•1˜Á˜mi?ÀòàAB"ýˆ-ùB`’•¸.ÐuKj0\¸®ÐÑ*o)„A ¥a VP‡\\3µB•°f;äá©”D åj}‡ÚÃþ Ç#Ù¤ PÔšèÄ'¦ ‹Bñ…AnöE0†QŒ‡ŠTQ bTQ@Æâ4']DcÕX†+’-‹ Ì’ÎØ.:ÖÑŽwt“S›iK‘‹dd#iõÈÖDR}L$%«8¹K*+“ÛÑ E2-UBIû!3Ù¶Œá¢eiÑÉÊm–´¬¥n‰Ë–©o¬ /-LU W+¦óŽ ±dâ!—&1_á̃¹çÀ¡ñv9ÆÎA³#ŒP¼ê1,Ùœ—ŸÞùN¥Pð›Ö¼¦8ǹv:­žö¼'>¹p,} œªT†@ÿÉ8trÏ{ýô'BþQø¿ƒÆ0n-¨A±öпI¢Ê¢hEÃy¾§etn¥âè3cÇÏ¥¡LßHÁ+!®Ñ¥)U©KMúEœâ³~:%b¯üHÒ9ô§/%)dª¿•U¼»(K‹:¶iõÔJ]j›ÊΪB5ªR*ÏT—©î…”¦[UR-GÔ³>µ’nñê•0êÖ²®iªmmáGAŠ>l-®r+NóJ(«¾«å_ûZ(µ~+ '¥ÒüÜV×Ã"6±ú‰b1J¤Ëʱ“…lm4+ÒLv³DílaY™.»IV}«5­®ÊŸ. ¶ïÑmÕàZbJS5ELÜnõr´ßÂ2·ü.5}þŠÉÝWIÆ%.›ÛÑç*÷¸>„®s9ÝÞú6»>Ø&1–{ÝiY·±‹ïŽÌ^[æ'Þ æí´t˜¼¢½Àí.j#ßûNƒºé=„GÖ²ÅY€—ª eƒ~¹9ßN.­'+Ñä)’Ñßä2Ärq …-2£÷ÎÎúEŒB–£ Ïä 9Î[%˜çF%x±pƒC£Ì«—:¹Ícˆ’acÞNHÎÉ Q–³GÆŒF<Ódƒj×c7fɤ‘Ê€eÌáSœÅLŽ/€Ý[à“¢Œ8aŽ’íb××®£B²) IeÝty-O†²Ì•&'ÀJÌrtéq_!¹Æ¢É‰gÐeþæÒÄ™ÉÁ¡ó˜Ý¼ªÿn2Ä…>pgÈû;ö¯}õ˜z0$Nr÷¿O÷ðsºÑ8uŒÑ¯÷¸kd'Öritáü“ ùÒö×ãõñO|êIÚv~˜[”kرkSù5mÈ5Ï× Þ'­$|x9h¨,Ã\ôƒ—#H7!¸_&h@»Çp*h@ƒaâ‚3Hƒ5hƒ7¨ ;jas-2.5/images/edu_jas_classes-full.gif0000644000175000017500000003141307773340004020374 0ustar giovannigiovanniGIF89a~Dñïïïÿÿÿ„„„!ù,~Dþ„©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡Ä¢ñˆL*—̦ó J§ÔªõŠÍj·Ü®÷ ‹Çä²ùŒN«×ì¶û ËçôºýŽÏë÷ü¾ÿ(8HXhxˆ˜¨¸ÈØèø)9IYiy‰™©¹ÉÙéù *:JZjzŠšªºÊÚêú +;K[k{‹›«»ËÛëû ,N^n~Žž®¾ÎÞîþ/?O_oŸ¯¿Ïßïÿ0 À <ˆJ€… :|1¢Ä‰+Z¼ˆ1£Æþwpü2¤È‘$Kš<‰2eÉ„Ux 3¦Ì™4kÚ¼‰3§Î<{úü3À.=Š4©Ò¥L›:} 5©P–SŠF½Š5«ÖšSsXÝ 6¬Ø±dË–íJÊW³lÛŠE{c­Û¹tëÚ½‹nÚ&rñúý{So¾€ >Œ˜©à½J'~ìvñ Ç+[¾ X2ã#”2Ûð¬]Í1:cþëð¥éœECë\}Ú/éÍD`K•¹Ú6n²ºÃÎ~Ñ;6ݯÁg¶†™[¸åß´ƒÿI|¡j.?S—®:zuäÔƒvŸþ½ºxäV·[?Ožûs Ì[¬W.Z½üë䵃;üÇíþ ©ü`€!Éð^OÄ¥çÝwá·Ýtç5x}ÒEØÚZ.ˆŸ‚Zõ·Bûù„î†ay%2øabâaŠx­B‹;™xßuº6â…'îX!vö)8"†[Áˆ‚Œ.^u ®Ùˆ¢AydfCIbd”‘M ÜX7ê·e‚Çéød“:Ù$5fEä UZÙT’]r)&‰a²)–¬I'ovº§å}4¾Y&qúg‚;š©!š{–ç‹^ú)g¡pÚèp‹6‚g¥ ]ªB¦ÆaW¦“~‚jŸm9'“â8ê¤CrJ ¦u¹Yc©8Š[~gÊjVšxÊ+’°©œ Á6þ, ÀËl³Ð%‹È²<•ªXl¾r -’¤:‹,QÜ~ î[Ð’-kHZ;. å†Ûkº,¬Ën¼Á^Û¼6ɵí„=Ö7_vó:½Ø+ï¦ÞŒpÂ> ¼Á\=*aƒ“VÈ#”W–¦ð‡ ‡àpÆ ·qÓTzJâ:çÔ¶²#¬˜»ÂLóÇ-ßñ²qg¦\hª9'3ÇMtÑ)‚ÑJ/ÍtÓN?]Òü ñÄ=_Mæ]7S@uÍìI­¦×b¼uTSk²Êúþ‰àª³ v]=-´ðIwÞÜ–MÇÜKù-UÜØêÍß° ¹8áŠo(x½.&~ß@þ¾xPœžeåšÓ)¹”‡ÛùŸk.æÊnŽz”¡Ã1ú·«7ÐúâzÝ=Yê¶kÜ8±;û:ûâ§+N+kû6h…¡ez¬˜¥–({Ùÿð®·WÖ{»7[½`î,½¡Ý“o*•|í zæ½Q€ÞÛöôËåÞ0ÔòÏ?ül¿júI>ï ª¶Úg¢±­;új›y|„+úô-ô‹{¾ä/þ©J‘óN#8Aÿq)xs_á&q=fe/øÛ_óÀgªH]-€¬˜„Äd!H•Hbz@ù”‡BW)pL]Ó÷j%¢P!Š€Xó¡3B5„ðXI<À>’éÇmj Sþ ‹ø<0%gír"íÌ'A~Õª>%«¢ψB(-)mYÄ¢Ž8>Â1rö»À§xBeíP1\йØG>bí,{º!ÞŠ‡HCõq}!ú”%µHI¹ÑˆsDMñ°Äy]²wÔa`d(Ȫ+G\œ¢YCíá0ƒÜ_$÷ˆFVâñ”ë XÉÑlÒ™äU ÐÉöÍ`ZÜ"©¶ÕFTA2¢:™'Åå»/â-‡­¢"GeÄÎÐÊšmÔ`®YÍ\"q—fçÂÈ)LKa¤1dØÌ OKÉñ4ûMÿ†ÎÉ9©ü4 !! ͤÅs p›§ñª•÷@ïY#è«þæÐˆŒJ\à1GÁð}ÓAãie¾ÀID RÒ@ù¨DÑ“ª*¿¼úí°)‡¹ÔA˜¯=ÖïNµ”Ýtb6W£¼&{<×…ÚÊOm)kúãð:YÈ<žd‘·¸âÇ%Y‰lÝñ6!lÛ=Ò²ÀC6k]gJ)$Ì«Åí«‹¹‚¯¯Z{Ctóß´þæwy¯|å‘SDØ1l—Mf.ŠK,¨@+i–è=òˆ÷|ca¥tetÍòž›Çi)Û•Ï©ò³}gW5Ù–þtTU7æ4,ÚJf>Õ® wÔ7ÎÖ£‘¶õ€—YL5Z6•8 ñ„¹ÙÌ2B–º’tì“7ª^y¸»Vª)}}A>6ö©— )­c†YÃz³ˆ.bS ÚûØœ‰ƒaw[]õåÑ6î§½ýI츤;²æh»Ã/#yJ¡Õ-¸m¸ï¸~8áœý7ŠC¨ûï˜öåoz­í^w›‡EÙÁï òWäàAexºþc{×–2Ì&³5<ãQÇœB‡fŠôqþ“ÿÝ:+ʽëV:õ¢ØTö’Ylelº¹ŒÄ4—rÞsá‘<«Q?ìÏ» q²º2¬ Æ YQÌ׳¾R´ÜqÕCËó³;xêdz§A ÉOYhµ'´Ýí<ï¸SêjZÚû®Ò«sAåý=z²µ\\&]ØkSõ(?ŠVœÜ€ÿ¹¸/æ31¸§Ã¼åþ^î]ß³¶ÌÖ³F{.ø-\>Þ/âûeà­سtZŸ_8oêÜ…Á]ÝÙÊtDS¯…Õ#Úõjnî©9#ñAgò¶g|‰îQ{Þw¿4²×‘ÙÞÕ7’Pô9Û]fâÏèùFÿ_Åÿ;ñú2)ÛÓgõ|åó •þõ‹Bß'!‹©Íò¬¹üå3Ïÿ)Ã~WMgs“æ}šxâwB!v-·lÈ•B5v"æ/2vsYG€4Ç#õ‡n‡LE‡xÍe„1eÝäMÚçg«‚\KZ|Y | ÖyxÕ”õkô6yi‹·eèÕfw÷epHèD^G„†S]—QE8‚‘×gwJág€'UkŽ”F˜jV8Vªæj\÷GaviK§BL†`uÕ…Šg†Þ#i­fw’´n>W-ˆ/¸f‚”Fj»—‡Ñ“ƒÈ…=ØQ¥¦ xwdˆp‰WxHedÌ„„‚hx·âC©)؇qG˜q[E‡W`þ‡ð‡ † GUmŽø=hDÆdt4¨LÚlbY¤‚ˆèyô„ˆXgbÉ·nÇG{ºˆc1/ýöAÍ7‹µ‰Và{¼ˆ[¸7n¾è:3H‹ 7ŒñTŒ-Q‚P51æ§W-×k/ø‰˜gyѸRÓ¨ÚÈ„uGˆàSÄu‡ØwߎTX‹ƒgˆå‡fI÷I¯–yÌè±øŽðØUN…åh[ø8|”׎üØ¿ª7`HaC0˜9ÃèŽ IŒ | ™L6}Ij •Šù8‘³X‘)é‚R¨•‡¯'zò–‚¥0¹Õ&²§Œ0yz¬’u¨’#‰gX†‹Â“[²è[Åþ–\è󈸌ž–”Çe.Ș‹È\²á';ɉ=‰8Ý3]õrQ™0%9-ä^—ô/!i}…}&qé×>¾æmÜ´^ÑÇ/ìçm¤ô~ýáDC¡H‚ÎH~ô7…Uodù#æ‘q܆f¤bA'B-é\ hŽŸÆ‹ùqb“9iØbȃ ø€Èec6–ŽI„x…£Fv7ViŒXyH”™}¨Ù„uæ—vŒŒ™¡†‚6¸T}h›REÀ£™øl‡çG¼7m4¸W?¨‘“¨‡1 ­9˜ Ù]€ø‡ÉXYvŽL„t–š¹‚[è‘Kˆ‰˜Yj¨ˆ‚æ‡þÞ¹{\6‚nhhp˜…Ú¤wâX°ù.†˜jšI]ÛiŸà¹i78ƒxÇH¼é€mˆJNˆÙžÑ% +ÈžƒBŸe7 ùiw¦ŸR@”½˜9ÃÆžÜIvðg™v$¶mL§t ˜fÍvQÝ7VØQ¡2Š©øxg†œ¼vm3÷/®ØŠÎÔ3r‰*x—®IšÈwÙGLI—lؤ…h®™ ×”7©N „¤ã‚²•Ó {S¥eæŒhr¦HTP¿E¤7 3aZ“öb“y–&)N«8]mÚ¢4§jW§vZIxª•øg?z¢SU"Ǩºe*¨sD¨O`‚¶$úþ•$7›Ê©ê©Ÿ ª¡*ª£Jª¥jª§Šª©ªª«ú©Ð©Ó3©N€™ìƒ©«Ó𡯪5[ºŸäI«a¦¼Š ¹ª«³"¬yzk¦7L=:XÇj ÄZ¬㬔ʟÍQ†ºç”Wz¥ÐÊp·ÊÜJ=ÓJ °1›×–­ó[,(®¸ÊˆìÅ3G‰DTwp‚Q麦‘®á­Ñðjˆ s¥‰–ê%¬‰¯ùz'Õj­:f[Di‰Ÿ‰z°r¶®CÕ¯Ð@ˆ| €äWß9±ÐT±kg­…‡»C©Ž2÷±ûûŒ#»ŒøŠˆJs‡iž˜è•+ûSíú­ Û_ª³tþs±IP©9k´Rù”ß³ö'KA+´<»pF[I”˸´×ê´›3´H §³‡2º3óÚmóe—åµ›µ¨³µœa¨^+‚´¹”Kj}ikË .›¶,u¶DÛM+‡êeЗ›êzµ‰˜·²³·\»‡û·ê Õi¶…‹µ‡K8v[ê©•zç¸é±–$¹†K¹zc¹µqkMø‰‡6$³;NŸ‹·¡[” «¤®»|ë’4{¸;{'—¸l;»’K®…Ö•ñõ¢ÇõóºÅÒ»^aR¿[¸8º/6‹`ØÈ?Ù¶§:8½dY½ýr—•–—ôJ_|y´’º¼^PLË®´û†þIµaîɺÁišÑ9`£°.˜¼¦-ç;¹" ¼0ÔXLÙˆ“Uš2yŠØœƒHÐ)¥èP£ë盿¯¥¾úŸY˜À™6¢ñÙ™óÙ aø†ˆ)èk±å« Û¾š{ÁQ¹Á JSFÀ…†¡{‘Ž`:ÌyÏ+³0¦£7ŠT7k†A ½ÛÈš{œÈ¹}Ù:¨& ‡ƒÃžû¿P)¦JìZT<±ŽŠÅ$á«èúÄRWÁºËZK iºüNüÂkÒÅÝŰ›7fÌ7ì¤õmM¥¨LŒ kìÆjµåsšÊYs™ª¾{<6p\l$Û~øY«òbÈÅ Ç„¬“‰àNì×þ±k3x| Élìü;„‰<ÀÊN˜l š¼ÉhçÍ¶Š¨ºv<ʃ|ÊoJÊgì³´Ñ"·LUÈË¥¯µ¼ƒ‹“Ɉ”»œ³ì¦,­´K½ˆyq÷¾u|½اĬ>ÆÜÈL¸W „9U}ùÇ@RKͯaÍqìËŒdùXÌYÉ‹<Μ,»éÅxç  ‡–üÎ$u\ÎÁ°>aø¯)EîœÏ$ÓÏ®Êσ<œëÃJXgÛXмÏ% ËÍ.|Ì4%{Ê:¼÷÷ ªÍ}n!‹Ž»H¼ÅûÑÏØÆ" :íYåJ}'‹~Ò¼€AÜÊd˽ɼÒ,M¥ÿþh„”²Šáœ²êüÁ´)O;ÍÓ¼ãÒF©fÜ6³á¬˜¸Ã97= ØLÍVm΃æ]ZÓ  µ©¥ÔسÔúÆÕ6êÕ³úžø,ΫÃeÝÓlZÇ 9¡È–H6 ’«K°ÿ„Ôr­Iû\í?™{©H«†£ËÒgÅg§ÕqÎ{±ÏTºêÖÖ¹™nj’Ѓש»Ð)g¨²Ý;Ä׆…Þ Ñ‘ÊÙæ›Å¯MgÍ é)†!\ÚýGžÜ¶oM‘²m¬ ÜÁ-ÜÃ}ªBAÜ ªÐ1\Ï¢,të«Ü/©3íy­ žü¹ƒ³ÜÙíÀç¥Ý%ʶm‘Ôí qÝ" ·þÝ͸ދÞõ ‘ÌýŽâÝ ä]Þ1²e‚k@Mº}€i¯ƒo—·uÓsÊ’ q7>ß`,Å€ ²aàÖ}àœ4$Xð­ ´ƒáŽÝ Ž¢L®áÃáfíá nC!ž¾Ë~ Òäâ(nG#ÞáñâNã.#ãJã$Äã7>*Ë,^ Eä>þã9Ø!ÁªdäªlÒÔt»·Øe-äÞä1žÒymŽ‹ÙÚjÑUž ~åTG—øÃLHÔ”,Ú_ÇÒ`Ž b>æÚ#v¦&Õ0gÔtÎÓnÞâq[3fø,wD=¥ ä•£ç¦ç|þÉÖÑ-èNþå¾Í ‰®è‰Èèxî…çíÀy.é«@éŠ~Ú®ˆFy ŸWv*4ªàÄ|èC^éú¤‹©Žä­GŸÎç÷ëG²ê¤@ëq^蛜룰ëcÞëüë¢ìW>ì„\ì¡pìMžì{¼ì ÐìFþìníŸ0í>^í°{íží7¾íeÜéVÞꢣÄoÛÑŠˆÒ·îw,ñí0ž›èYT›åìnг^îæ~—”˜ßºÂÞÕà8:¾A>îažïu纶b•ŒÞ4ð¾^ðo~ð%·Î ¼Â`=ÕˆîWñ{>ñˆ¼ž ?ÔµMÛ€Ýíðî(¾Sø¸é$¯‚߬øþñr.œc+ÚÁ€bþ‹ê, ̧|òœò!Þ°nïÙ\â3³EÏ]îŽô$¬ô¸ÞñˆÞôIÿôV‹A¯á0Ÿ·?¿ XáZŸ¶\¯ ^à`ŸµbŸ d?ßfï´h j_Þl´n pÝñŽØP饨Ñto v_Áæªî ^çénÙùì÷•øó<¥Ôïà$_ ¶h¥ó½öÃr¯›2?õ–îÍÎi1&¡Eœfçíð˜oõG?õŒg¢k¶Ý*\ç lß/¨‰O ‹ÿÙÍ&òÛ¸m͹:÷QÏê›oé¸Â~ëú%êÖ¾¯³´BÂ?üªhùF`_ݶúSù̺‘²o§ÌO%Î?ô¦ßÛšŸúþU¯´L/üàÅÀ¯ëÞÛíïþï/rêìÎÀmÜÇÿù¯ÿûÏÿýïÿ¢JÙ1u¹ý“V{qÖ›wÿÁPÉÒÔ‚S]ÙÖ}áXžÍ”¾ñ\ßG›ÿAáØ+‘IåRp2¡Qiï9µ^±Ù•OÛõ~Á'7\6¿Ægõš}#·áqy)UŸßçö7žßWïýÍô µ —!ƒl&#+…(-79:?AY05CKEFMSU)HW]?}b_g9d%Zisýpu{¹€}{ƒ'x…ÏŒ‘—Ùˆo™_3¡©Û”«±³È¶³C¹Y»Ã»®ÅË“¾‹Í7ÑŸÕÝßãþ¥Þèåë+Èí÷UôùÿiøxGà@ƒ§&”¤0RA†/8„8EE->Ę‘ãFŽX<~R¤Æ’»N¦Œ¨’å’-‘¼„iNæL{5m.ÌYçNu=}êtÙP¢ÙŒm¢ÔbR¦Ìœ>mUª+ªU‡a§UáU®³¼~ V,'²eMEërí?µm;½…+fîͺåÞm§÷'_€yõö‹GðàA…ç"6 Gñb>×Bvœlr<Ée/W“YóÎ\?wÖ&š&i¡¦¡¢+kÕP\¿){FlÚ1oS³Ítwî!½}+NtxpÅA¾syr7Î…5·)zþ êÕs\o©»¨î¹¸« ÿ½y°æ¢«~Õø“îÙ€ŸýóíWÌ Çýúûï>1À½l(Á|4ÄÀ„p Q¢ð $0C 9´ð1/êÄMÐóÎ}±ÝãôÝùS‡Ex›§t:êa…>7æÝxÞûB•ßez„ϵþ܇á5¸|äñ0îú^þYµ7küg¶þÝt;®÷zÇÝçøÕf~ìSýÖ!C6Ä…äÖ QG4èpŒ4ž ýf>ÿ…Œ’<£dŸ·Fk’“WÒdd®ØGQV2f‘¼™Ó>èÇ:¦Òˆˆ|Ä;YÀO¢E‘ß%+!iÆ¢ï–yd!.™ XƲ•p %$C…Ã(Þ0‹#»ÖÒh¼iýQˆZ„b0ÓBLm^Ê•¤©åT(5Ì.IQœœåd—Nu®“pëþfäÕNy¶›}Ûæ=Ï)–oŠâžÚÌ'!úéÏwvfŸ[h,ÿY†rÔt ÕJAûÁPN:t3è@;wB‹¢_XèF+×Q©@ôiãD:Ž“¶1¥¼ÑèJëY»À¹0…5ú_¾¨‡Bk ï£ä„™µ0Z’Ö¦ êaN¥Âœêñ† ZªÄ,ùT[’xÒ:ªî^š¸4T4…êž¼zSž]5°<ÿ–V¨ _¤*»ºµ¢5òšïrëÁW»Ö•®m•+ÂÈj˜¡Ò!©k2)ÑÜ4U©rUˆ8-V`û@2Ä23‚¹Ä«XÑH&¢õޏ $S÷'¯Î2ò’2ƒ¬þ³*±1Ê5‹‹Õ᪮k:lšEkÔž™­„©/¶{µ&3W»ÚV˜a®.Ø×äj‹¦<eS‘©4iö²’ Å!m§[<ê¢ë´|©d)‹Wh^VgÔüÿX°iª×9+e½jkÇõÞÔ‰vå_þºKµîº"loõÈÅÜô’v’ú+íGhÝÿ¸²žÍ¯uæa Ox‹3®Zû»Ü¥a׃[}]7ìÙSÒ¶i’tdþÂjb7›Çuq}shÙ ×Õfšuï[¼âO–À9­Ž[êÃ5pFÓãó’hoŒE¼ã7ö¿QÝxüØâ‚vÀ]؈þUiÊ6¬‰7öò2gËW&Vº¥”nk¯—[¸ËÈ‹$òü‚œ1cXÉf60SŒÛíR·¼õ5s–«U§²Îl¼³yÚhp>ú{yv—G Â7‡øw›kvÕ§ÛIúÖ¸¾mfÁ<߻ى¨óÃ$Ý JS9t–vɬcŠTŽÔƒ±ö ®3éëˆ[އÏ$ Äî­Q0Ó¾¾V»U}àé ]8gß.ÛÇÞ6·™MØ¿ú…æ1ûÎp3éÛ‘Þr»³g…tKê|z}sQ¹f&¯5ió†Þ=àï|‡òÜfE+hRê¸Íº,2À .ÁuW4â7ø¸ýþüeµªÔ ®ö¾“7ñsT<¤"÷‚¿In©nGäàWx‚Nn6wÐäG@yÊ'µr&˜Õ©´Æ¹­j.Ÿ–çØ¿;&´ÌÉk¹ +ççˆÓ9»ó•î›;ûé¬z9ìÅBëÛÀ D:—®ç¯Ž½éÿnñ´v;jäþÃe?äÅÝþpÌ)ÀqGTÕGn_>&ªŸµ»'Ã^‹¿‡âzŸvÕ>xEþâ®6:b©ø*áý’W:Ä[]å™[TŒŸÂxýþKBs~op'ýã<¯í·^7»§7lê½ÙЯrô®§³ém0ÊÐÇ8Þ|îó{Øä5š˜æúž¿û©?VÂÊ[þeægðÝÓß–ò)œ}íov˜¯7ŽoýæW_ü°R~ù¯ï|Þ¡ßüê·ûÛ{ø«à®›ÿÉ„É}ýïŸÿ6r1îmþ/~þR0p°ð!0%på¯e÷,Èém¿æó40ç80?ðC°‡oï®å Mpç‹ÇÔ$¬Ê À<,1 ÛTÐÎXO\ðßoƒh±¾*¾„°˜æ®ÁjÐæI¶Hl‹ÒÇÞ¤Ëái¾È(ÑúÌšhP O é§ £aŽŒ½~¬ã¢*Óð(ò˜JÕ0)ؾP§<­çˆ°â~P ƒ…”зxÉÜÊþlõmò­Ò˜pÒÆÎ÷ʰïñPϬì¹ÞKÑþ0Ê,‰ ‡ ± ¡(߯ÎèÕÑn˜"q—-+±ö.±ù©á˜löÊLNGqrôŽ,«T²ð·æ WMa¦Ì¼¸ðmLJmÕ°Œ‰ËoqýèíîÐìÑ ‘¨/MôÎî®1ã§ÿÄ‘Gñ ¬}‰öº1î¾E ÃpîrË|îí®¨çøÚŽ]Ñ›Ëf“‘Úü‘›øQzrñâ­rY² ßq!g°!±"#Ò!í‡"_/!1rX$Ò"mi#;O#Aòí<²–O þÛ±FÒM:²$ *yœ‹±®Mm Å“(%Oa%ÇÏ%¤°†° aÝ|îëp—R$yð|ò'ÇI¸ê1üR ׋7¾ÈÌ÷±ß„ñÅöǵ¬ð¬ß´, ›’$ŸR#Ÿl+ÏèŽRÓÚê-sÉÆà2ߊ.i¶¹Ì°ZR%cÅé®*…òÎtr-wù¢0ÕŽ+ÔÓÃ2O“‹L±Äþ0û(ÐÀo»þ21y®0mEê¶í0N ÉŠrÉ1Ɇ±ÇjÏ.; )Qc‘3ëOÓ¬¶Ä’f:qíH-g4KSÈfl1AN™vÊÔ”rá\Ž.‘36ÑþÑ®l3¬3ǵ2:Ñn‹tQ•fñ¹€M8‡Sð0íÃ4Í1ƒ± '2³°Ú¦ßTlã”,ÄÜp2÷ ô^ͪ0Oã6q›q;™±¨Äs<£--= ¨öóå¨3¸¸3«Å)­@ ´@”g–mAó;Ÿæ O&ÕÞ 4×^µÙžIÆB?%Ó÷ГõJ‘?Uµ¦œ±‡õ×ôtOKäŒA¥Ó5Íh=ÑU«õŠnü1Y+O[Å‹[QÆ<\%”Zǵٮ]3RUÍFˆµH,ÏìÓZô®ZU–jJ×ôQmôÑÏ^ó`i5a[pa 6I¯[uMOv-Víuc 0cŸÒc?vbþÉcIVFE6;¶bAÖ'sò©5.qneëõdGt:¹ÒEqm6X¶g•bä üÎú°_‰1;_ôïhÖd½%eñ¯ñ\îVX÷òVY+U4Sfu*‹íiwéñ‘ï ?4@ÝŽf%l_hˆüug15k‰clC0ZkSm#tZ›neCÕ+¬·Œ67]ô*õè_YŠnƒj‰t­Aƒµ×Q5“|U¾6t eæ Ñ654lwÅq%æná³lï³5IqyörÆ@ )ñÚzòøG8iS]½ÖL!—R!’msŠ.{¯[µoÓÖC‘0U&uþÉx7)-ö #…:¥¯9Ÿõ8WZ+wy3…ÕÈì ­2®ð’rɶb»´HY·X?m_“ iÙN>qó ùUlÕs픽L?+0K›Vå$9lEÅèÄ4î\L÷g!|8wa±½öW‚kÌwc¯føF[v&"1Z.oh1xK˜q}¢³ÞWÃ+o§í|˜„«tƒa‚t'O„†¥T†·Ãn‰ÖMó§€4‰,€ËT‡Y‚†§T?.í3{Šk©Žq‘XüŒXã‰ùá9þß=þãç\ÌqœÌ rÜ™–«{ä¥7Ð¥n¹™‹z׎U^TXžK±|µœ¹e­©I­3ÌÛºä]ÞNPÝ8·ø¶ÚwõÚ͉›™‰>°uå[ÜΛ³;ÍÝwÔ‘]o>J·Ìݲ—ÓÐîèó.¾ïœàíÓ§Ö±ÔÅ}q5´/¾Ð15]í1Ý MVã^×guî1Èoç—·ƒ A9¾NµÍIÙéÿzêÑy›Í¶}^’ÿñä~³=²©šï« ‹}fHÿØ¿ì' û‚^…«+ëÐ[gûUµ~®…¾´)ý™W5&9MÀc·S ŸÄ)ºklØþèsÿ¿í}Ýe;Ùõá]õõ˜â•Ü¿<•ð‹š»³ÿùÿĸ‘äµ]vÞ,£«àÍóç½ÛþE¼¿ø[ÞäXâs÷=w—(©üûâ;šþ‘Q @þE.¶¨‹o€j/Îzó~¡Š#Yš'šª+Û:åÉ3]Ûèê;ßû?0»‹Æ#2©\2›³@î‘€P UvºÈZ­ ,Ì)®Dƒæ3:­…Çngy-ŸÓë¦ö;¯ßóûþW—”Ø`a•!¢¢—ÕÐßMœä$eÞ#fFd%g§'Êe¦è(ii¢aס*¡ *Ô¬à„©Ìæ'n®nhmß­.p°ooþ±ñqï—+ka+×"ëì,ñño,”4 •lIÎ÷N”µ05²Ø8¹úzùù;|<“rjýà4Ãë2—ã;*~uè#‹_º Ù¹p'ÉB†'²ñ÷ð"ÆŒ€ºÝˆÁ½ô:zye"ŠÙ*šJŽ-?ª\9ž¸‰@ʤXî¤F#}õé0(ҤƆÖ9jª @pZ¸íËWõÙ¾+V¯mɪ­(§Jµè®,G¦ r‚ý!v,ܸ|ÔÎy;êUZ!¡µŒ ›×TPþ­Ú6,P¹Š`ìƒ.OÈ$æ—X1æÌèÖ PªàZiRAf\˜`{°Ösþ\yÛeÍRœš­LÌ•Óæþ¦ŒªNÓÁݤüš–ìäÊ—GãÊÓ¡÷$ÝÚðuÕ8 —þz\…Ý̃©‹v•2döÛYù’D?ýåéïec/¯o_g ÐkìVÓ%{¼í¶Û ¾éeà{öW“|àѧ^¹•WR|þugOjäýÂZ| :xˆ!âŸ&žÓœ‡)žfÖa'\zò…[uÜÅ螊=("-bó#A 9$‘DúcâR9*¹Ë޲¹¨”§Izlmx£kK®Öd]*…¢xìW–er¢b §Êb(K^è&K Ц¦™:z¹'„$މRžþ6Å¥x€)¨¡„ò¹h<‡–S$¤‘JZ$¢•Z¢hš†ZzšŒzš¤:aüI榥>†©\Žš*h§Ÿºú‰d ꪵ¶礹êº+¯½úú+°ÁêŠê«Åf¢ê©³ÍÊŸ­Í~¸çÑJ;-µÕZ{-¶Ùj»-·Ýzû-¸áŠ;n´Æš+S”±µÖIËÂê,¼Þ{.½õÚ{¯é5£ÞµMjêRxÇÀÞ¥°®©­â»0à 7¬Õ"ÛéÔž„3½p™¿˜dùÂÄ·{ žU«Â›|2Ê‹§‡uu#»¶ÀÊKqFŸ_A…`”ÚHµSq¶–œ2ÑE­ÙxN†¥þwCï‘tÇ5ãŒL[ å{-cm©ÓG{ý5ØÒt!WSâØõ)Åõõ›1¹ÉÍÛTʽ´ÙÈ5oØyë½÷¿$޵@uO†÷\ÒÕxàUÓ)möVW N2á|K>9åó”7# Vlrb|ø„Ö1.£â¿ýùë¿¿(âÛ_þø'ÀÐrÿ³^ ¨À2þ; EØÀ Rþ€„ D$XÁ r0~jù‘éR0ƒLÁ%Ûè×À×Á²ð|ÓÜÄNø9®„l_BSa s¨CáÑF ¶߈s5‹á„gTƒ¡y"sAahp‡N|¢× †¸©LÍgTÒË$¶šÓÍmSM„"Ãø0µñ„mÊYk,d5öÐt#ãÈ=Ãm%ttDÝãØÈ±Ç‡rü# ‹õ¤¨΄xt£CÃÇ„ù1Ž|d—f÷Ÿ)Fåvpû ïäT§úN‰7„$(Cé°%b0V¢<%*EÊR’ã‹©|%,ϱJVÕ±¼%.ûFË7æ²—¾lÑ.?ùËa3(³ &.lYÌe2ÓþÇD¦'”ÙÌiR?ÐL]#«©ÍmZóš)ä&8ù™€G!È2ä1½`Sœî|§PBÈ6yzƒŽ[ Ž y Ï}òÓWÓÍ^‚³êŒ&FN•º9‘}³Ÿ}(¤8!F¬ÌŠÙÜ´¸4˜t±¡ýè;ÏXFJ’±$ëù[Õê¸ÅE¶¤. ç 'zQ+Íq£±꼘͗ò4Ž1%ÏKwQD µlnìcO“:MIþ즾óË%k¸ÉÜe®c¿c¤R³ZÌgz“ÒÔ*XÈÕ®Jâ«a=ëÇJÖA¡µ­©ô\ã*×¹Òµ®°Ø©[óZÀõñµ¯~ý+`+X¼êµ°†=,b«ØÅ2¶±Že;jas-2.5/images/overview-recursive.png0000644000175000017500000023060310405002534020166 0ustar giovannigiovanni‰PNG  IHDR®ôé½ IDATxœìÝy\MùÿðÏç¶/Z(”D*²$d)K²5LdŠŒ,EÙׯ¥BcO̯!Ù’-3–,ÃØ¿CC)’}7ŒYZîýüþøÌœïuo%­wy=þ8åsιçú|ÎûóyŸ{(cŒ”¥ÿL°„ç¸cæü3õ T9ÔQ˜SÌÔQ„PDP>(ý_ -.(ÔQPÔQ„BDU}PÅ@C'(2ÔQ„DPn04Š u@±¨;DPÁ„ß~P@¨£!ˆ  Ü¿õ €PG Q€ºCT…1öñcÞŠ»Zµ­§çQ­Z¯N&îÛw®\J‹%11‡_¾Ì.{iÜ¡C¿‹D]ž>}QÂ7xðõ)uþéèô¨_ßgÚ´599c|…G2Jw<{ö$È”Ïÿ¹ºŽ“.¼Þ7RèEü²ýâ÷=@!¡ŽBõÔQ„B4«ú@U|úûŒ±7oÞ{xÌøð!7,ld«Vöïßçnß~|Рùáá3fø”eW”Ò£G/Ž³â«¯Ú0Æh™SB¥Û’”&¬Ÿ˜¸®n]s>ýñcÞÅ‹7§L‰zþ<3..¤GÖϞś››”â…òÏž]egWGz‘¶¶–ôŸe?÷âeg¿+ê"NŸî]Ñ{(O¨£PG@±@… ”Κµîõë7ÉÉŒŒôyÕ¼dÉè¼¼‚ÐП.uëÖ,uáŒ1¡M*—J_º’4Â ææÆµkWþ´±±ÈÊÊ™8ñ‡µk§U«¦gaQ£ŒÇcföIùòÊå†CZ~~Á¾}碢ö=»Š"\Dcc¾ÂÒ¥c„‹heeîæ6i„tÒÔÔ@ Juê( "¨o߾ߺõø„ „æ–B)=Û÷Ô©ÈZµªË ïˆ,Øfc3XG§‡½ýЕ+wK$Œ1vðàï"Q—á­lXØfCÞ7n<öò fŒY[{SêÎ+js>Šw²E ]ÝNNþ§O_á{ÌÏ/Þha1@OÏ£Gé·o?&.îd³f#´µ»×®ÝßßyVVŽÌÑÕoljD “H$¿ür s b±$,l³•Õ@]Ý;NXºt‡|†€|3VÂŽïwëÖã-[èêö°µõÝ·ïÜáÛ7¥£Ó£qc¿'’…¢cÿµxqœ­­ï„ ‘íÛ7#„ää|àQhnùšÂE$„´oßl„H[[ߥK,2Y-1(ÔQ¨£þu!Q”›Oß#-íann¾«kS™ÃÜܤ}û¦ÚÚš2 ÕäÉ«üñäºuÓïÝÛ±dÉèeËv,X°…RêåÕ>(Èë?ÿYûôéßgϦ-Z´ý‡&5mZÛ¶`JiJÊÆôô½„B7Ê_µjïºuÓ““7è~ûíb±XÂ÷{dýú·nmóôt ÝÄW¾wïÙˆK r¿woG|ü‚ÿþ7eΜ 2g!sð|¢ @œºpáÖ=ZK7QÅÃìÙë׬9°zõäÛ··Ô%,l ‘#Ÿ+s0ÅŸ{DÄO‘‘¯^µ¶®9rä²°°Íë×O¿zu“••¹ŸßbÞ6§¦Þ=:¢^=ŸÎ……|òdwxx ¥T¸ˆ2wÒqÙ²1Ožì ¹ÿYkk婩÷åϠꡎB…:  XÈ ‚ ‘ýŽbjjøÙácÆØ‹Y6:yr¥»{ BHݺæé靿ÎÝräâ¬Yë==]å?™c¨QÃhìX¯ffÆ-ZØ=š}@fµ—/³ÿúëµL9ü‡5¸Rœ»|?œôŸ;;¹¹5ÿãç|~1‘§ Ü»·£~ýÚò'+sæ Eƒ:Jþ3A æ@9¡îÒô”ÒêÕ«?¿féÒ¸Ù³×ÿñÇsmmÍV­îÝ»€?¸&1¶~ý këíÁÁŸ={Y³¦IP×wß"„Ì›·éÆÇ—/oÔÔÔ033^·nzÿþ¡_}Õ¶ÿN_Ýnøð¥„{÷vµ¹ô.dvºdÉccÃÿügí‹™mÛ6 1kÖzBHË–vqq¡K–Ä99ùëëëtíÚê—_–‰DÅý¾‡ð§††hÓ¦™-[Œÿ£F}-š2s""ÆV«¦?~üÿ½|™íìÜhÖ,ß… ·éèüï@nn“d?fJ³³KÏùÒs—o€å3’…F´F £B/b¿~ùVŸonê(ÔQP,Zè0"À£T&m>ëäÉäfÍlø‹„cÑÑ?Ïšµ.;ûˆ††j¥öQwôÃAÕCõåPG¨Õú  <cññg|}^ºtûñã¿ømñâí~~_©ZsKðûJ u€ºÁX”—3U}Ê'++gæÌužýú­••ù°aÁÁßʼ>I%t®ê ¨£Ju€ZATå-.-.(ÔQPÔQ„ ƒ*œªu+€jA@Áo©© ªñ$” ÔQ•Qº*÷Ö‘º—s ÎPGT.d@ÃÃK ÈPGB@¹ÁÐ<(2ÔQÅB|ÞºuccܺõG^^Aݺæ^^BCýLM ùq:aŒž%0Æ44ºÆ iC¤šd©uŠßª5!’‚S[·ïÔÉѾ᷄1![7ÍêÔÉÑήu)¦±X²uëñNþáv„Ðb÷N©;!$‰Ö’Ó"Q—¦?·ÕgæðwâŸÐ¥Îs* ê(ÔQå0@í!*€ÏX¸pÛüù›54DmÛ6655¼|ù^ddü¹si¿ÿ¾FSSC¶Ñ•ê£ôßß½MZÇZ7¢…­SèV}ûv „˜FŒ%¶–-ü¯_”˜¸–INBZ:ù_Xž˜¸–úšÒç0ÆZ¶ ¸~ýQbÒ:ÚÆ¡¨}ñ5ÿ9…ĵ|ï|ºø­J=Z˜ „PJ% !dûöã—/ß“H˜î‘#቉kœl…ö騱¤Ž'èëehØÓÝ}òùó×É¿cìÖ­':MÔÓóptyòd2Ÿ)u‰ºüøã¯|Q“&Ãú—F©;¥î—.ÝÖÐèÊWnÛ6ˆÏä+´mÄ=z”Ñ¿h^ZZÝ,-¿?>òÝ»Œ1ù5ÏKëÒeŠAOccϯ¿ž•’r—¯À[Vé;aZ~~0>äÚØ nÑÂ?;ûŸÈÍͯðË öPGÔQP¡¨!BKþ÷öíц ëÖ¬iúôé>‘™ù‹DrZ"9=þpþU¡”š››ôë×qíÚiÙÙG$’Ó|ÛcÇ"44D”ÒŽ[µjH)54Ô{ðà'‰ä4oÀôõuÝÝ[X[×¢”V¯nôáà ‰ä4/ÓØØÀÍÍÉÊÊœRZ­š~NÎ1a«¤¤uýúuäÓîî-úõëØ¯_G¾ÿS"9ݺu#Jiýúµ==]ÌÍM(¥žÉi™5ÏœY¥­­%‰:thæææ¤¡!20ÐMK‹åÇÏ×LJZ'URÒº¢6áŸÉŽs)¥sæ &„OãŸøŸP¨£PG@¥C½ –>mq%’Ó}(¥k×N&„&D,>½fÍTkéΪ:uÌ„æ§cGGJéܹ~|ýQ£¾0ÀíÔ©ÿ°ùó‡K$§>ü‰7Ÿ×®mšU¾èÖ­m|M^f¡M ß—Ðó}éëëRJ.ôÏÊ:|÷n\däÄÓ§#eÖ”HNwéÒ’R;‹oµeËJéàÁ]åצ…Mø:Â&ÂgââÒDSSã·ß¢øÄùókÐâ”ÔQ¨£ Ò!ƒHzú«˜˜ÃººÚÝ»;ó ?¿¯„öU$¢ãÆõ½ukÛ½{;6ož=rd/}}ôôW&üÀÛ§Ë—ïB<<Ú0Æ!›6ÍÜ»wA—.-É¿ƒÝ]»:B¬­kñïÜÇyä߉/²³«Ã×äÃÜÒCäÂ4Ÿà[ ›Ožü clîÜMff^>>ß½|™Åï ¤×$„$%Ý"„Œ·øGŒXJ9{6M~Ma:)éclÔ¨pžE0bÄRÆØÙ³i|©HD'MúF,–Ì»‰O„†ÆTʵPG¨£PG@%ÀÓÆ@,-kL™2ðûï÷<ø;ŸX·îàÔ© !—.ÝY¹rW~~Á¾} mm-mm-GŒèéåÕaÀ€¹ÉÉw˜Ô3pb±„7>äêèh‹Dÿ4f„==mBŸCþ}ZŽOëéiSJ555„v”H=NG>}´ŽH=È'/èÝ»ýÞ½gRÓÒ¤¦ÞߺõøíÛÛy±B! #„tîìdjZM˜©¥¥)S¦ô´DÂ(¥nnÍe6Naýúƒ" õ[°`‹HDçÎõ+ÛE€"¡Žf¢Ž€Šƒ± |€»qãz‹oŸ:Õ›O¼~ý–R£†Q|ü™~Û°á¾2c,5õ!¤ví꼫E ;BÈáÃx'Ö! Œ¿^±b“zH®˜/>Qhß!D$QJys.Ì‹%Œ±?þx>nÜÿ-Z´Í×·{ròú{÷v0Æž>}qÿþ3òoÛ)K!ÎÎ !={¶Û·oá¾} ‡ ûªysÛ¡C{sTÂ&û÷/Ú¿‘° _aÏž3gϦM›æýòe6ŸpwoQñ @M¡ŽB•’{’±„¤¤uZZšS¦ &øü)S -kŸ>í›6­O)‰D;vÌåù¬‡-åíbûöÍÚ´q ”èÞ½WLÆ­|ö­ôšÒÓµj™RJ´oßìÝ»ãÒfgiÑÂŽRjllЫW;{{+Jiƒ–?ž”ÙpïÞ…üYÃÖ­uëÖŠÿ„ùºuÓ‹9ª#G‹ÚäÇ66Í›Ûfeæ>œý<ñ?  ,PG¡Ž€J‡ "øG›6yyÿåÓÂclåÊñMšÔß²åØõë®]{hbbؽ»óôé>­y_—§§Ë‹/Þ~ùò] ‘»{‹Å‹ììê¹ÁtV‚aw™éðð ¹s7ݹóÔÊÊ<3ó­ôŸoß¾?qbEpðÆ_~¹pòd²‰‰á AîË–ÑÑÑ’Ù°]»Æ‡‡/]wùò½ÜÜü¦MëO™2høð¯Š9ªž=ÛÊo2bDOBˆ®®öÇ?ñÕ„ ¨h¨£ê(¨HŸ¼ÔE¡/Ý„rDÝ þg”ꨊ†: äà¹u‡¨@Ý!*Pwˆ Ô¢u‡¨@Ý!*Pwˆ Ô¢(½˜˜Ã"QJÝ…FF_wï>íæÍ?ø«³oÞüC$ꢣÓãíÛ÷¥~_ÞãÇÉì…ÿ‰º\»öðöí'"Q-­n99Ê÷ì@ñUN-ÄëùZhÀ€¹¥.“1&K¶n=Žw‰€‚ЬêeÅ»té6!¤I“únnÍ !â‹ož:ueРù×®m¦”¼yó.0°……™¡¡¥´t{IL¼E122ðõí&½HKK³iS›íÛOðc04Ô+‡³åQɵ©i5Ÿ.Ò‹úôéPê2SSïDèþU)J(wˆ  ”(¥‰‰7 !ß~Ûcöl_Þ4¾|™]³f¿[·þxô(ÃÖÖÒÅ¥‰‹K“2îåÒ¥[„¶m¢£§Ê7ÀÂRÆXéšgPR R •®Ì~ˆ¿råÞŒ>¨»@A ƒJ)'çà !NNv¼IcŒ½zõ†Úó?Û·/u‰ŽþY˜ŽˆØéållìilì¹xqœ0tÆÁa˜¡aÏ  •—.݉ºØÙùò¢’’nBZ¶´—o8…¥­[;B²³ßÍž½ÞÞ~¨®nKËofÍZŸ››ÏKHH‰º4nìß Á}ý¯úô™óüyæÄ‰?ÔªÕßаçŒÑÄP:•\ 5iR¿ÐZ(/¯`Á‚m ÓÖîÎó—ÒÒò¥ïßç.X°ÍÁa˜¶vwKËofÎ\——WÀ³±¼mÛ ÆXDÄNoï0ÆØßgM˜imí­£Ó£^=Ÿàà?æñ½[Z~#uÙ³'ÁÅe¬ŽNž¼ôóÏçùÒ7kiuÓÒêvíÚÃÊúà@5!*€Ò`Œ¥¤Ü-(3Æš7o ‘°œœII·‡ [L)µ³«ccc‘Ÿ/¾rå!¤m[a:4tÓÛ·ïÛ´iôöíûyóbŸ={É;~ü’Ïw÷î=óðhsôh’¿ÿrBHÛ¶ !âË—ïBoû½ô¿ììw¹¹ùW¯>à»xóæ}çΓ–/ßibb8xpW±X±3$d#!„·è÷îý¹víÏ..Mrs󾨦M`RÒíví¿{÷qåÊÝfTÝÇ _¬Òj!¡žqp¨'ß}@)3&",lóÇyß~Û£^½Z§N]8pcìÝ»]»N Ûüþ}î!Ýc+Vì ÉÍÍwssâEùûíç÷Õ«WoÚ·ý³¶¶¦O—ÜܼeË~ ZIyòäÅ_½‰hPÐ÷ææ&ÁÁßöëבRzÿþ3J)¥tæÌub±dìØ¾ÍšÙTîUƒ "( JiRÒ-J)c¬nÝAÒ‹ÌÍM¶n ¦”\½z?77_WW»ysÛ«Wïü˜GY´ÈÆ Ÿ÷ïs«UëÅËÍÍ'„,Z´16uê +Æ&'ßiÛ6ˆâì܈rýú£÷ïscgÏ^={öª°KK³èè©/ÞÌÏ/Ð××iÖÌ&8xcZÚÃ~ý:ÆÇ/ ”;–äé9;.îdDÄØääÛ„fÍlΟ_£¯¯“˜xëÑ£Œ–-í÷ï_ôîÝccOBˆŽŽV%~~PV•V ]¹r/?¿€1¸"0p…°—€Ï f0FúõëÔ¡ƒcÏžm­¬ÌÏœ¹ÚµëÔgÏ^BV¬Ø•”tÛÆÆ"9y½‰‰á©SW¾ûnKnn¾ŽŽÖðá=·o?aiYcãÆÿB¦Nzð ½iÓú.Dè^½ú U«Ñqq'W®Ÿ”t‹"‘°Õ«'óg«æÏßüóÏçªÐºu#BÈοBÆëgbbH)íÖ­U·n­¤ÜÅ¥ ßÑÏ?Ÿ'„Lž<ÐÀ@—âà`Í‹Ù_½æk¶oß”‡Œ1>&pïÞŸŒ‘™3×B,U½zµ ÿÄ@Õ!*€Òà½t„‘#{ñ&vøð¥qq'®Œ×—Âã=ômÛ:Bø´‡GkÞ^¼x“Òºu#JɳgK$ŒÒ¨Q]BÈÇé„ ‘³sCaÃ6m y˜˜R*½‹¿þzM)ýæ733caSÓjÏŸg>yò‚Ò¹s BHbâ-‰„™šVãíý… 7 !mÛ6ÆÊ¥’k¡Ž }ÔxôèˆíÛOêyzºtéÒêñã¿^½zÓµk+Bȃé|ïòuWJÊBHÛ¶MxQzú+BH³f6|ÍÔÔû”R‘ˆZZÖàçèåÕ‘×Q”ÒæÍm !fìÚu*-í¡““íèѽQƒ@Ùá¹(ŒŒWüV›÷uQJ¿ûn¤††(>þÌï¿ß ÿü6È-òïsÀ|ÚÅ¥é¿îñôhLÑÖÖâ3y s˜Ò¤I}}}aCgçF…>ä'½ [[KBˆ‡G›µk§­];­^½ÚÖÖµ|}»ó‡ jÕ2mÐÀ‚RÊoÚ¶uàåñ0iÓF¶ÙWɵ‹KÓBk¡={!;wÎÿñǹþþ_óÜ!>&`jZòæÍ{ÆØ;OÍ̼œœüÿøã9c,9ùù'&¡”R>V™šzŸ¿Ä`áÂm„¯¾j[­š~JÊ]BHÇŽŽÂãÔvvuôõuÒÓ_þßÿí!„DFNÔС€²ÃX”¿ÕÖÒÒtvnÄû¨ll,ú÷ï&<üÇeg¿»{÷OBHÛ¶…ia¸œÖó¦ÚÆÆ¢AËG2úö nÒ¤þ¡C¿BÚ´iDyûöí[B®ð´AãÆõ}}»ñޮϚå;jTø¤I«NºüäÉ‹ nÔ®]}Ø0ÞÏçâòOŸ\RÒMBH»v¥cJ§rj¡W¯Þðz¦}û¦…ŽXZY™ß¿ÿlãÆC·o?Ù´é0J¡eK{BȰa=¾ÿ~ÏèÑÝ»;>|13óí€nõêÕ"„dd¼"„,]—žþrèÐî&ôŸ>=zêÔ¨³g¯>x~éÒmss“U«&ݸñøÝ»šš-[Ú c"iÚÔ&)éÖ¥K·îêæÖu” Œ@ið_ïnÞ¼žž¶Ðƒ5fLBÈ/¿\xð =)é6cÌÔ´š½}©i+ÆØë×oïÜyJþX‰èO?ÍkÒ¤ÞŸþÍk×®1!¤]»&„ää; ã?²nÝAáßúõ‡þúëURÒmJiÍš¦66µ)¥#Fôܾ=ÄÁÁzß¾s·o?ñõíváBt:fB oPùD»vMceð¼£6m ‹EV9µ¯g455„®iŒ±-[æ4n\ïðá‹7<¸+sxûö=!dñâÑ3g&„ìÜyÊÜÜxùò µk§ñæÌùÖØØàÌ™«bBÈ”)׬™booµÿ¹G2†í~ñbtƒ|˜Âѱ®®¶°wJ)Ï520Ð BÝå…âgÚÕ¥„%TõAü#(heݺµ¨^Uü¡šPN+åfŸ€BÚŒ4TSJ Q( ëiûR¸áPpˆ ÔùÜT¢P2?û­> ž2€òRÏØÕ€J@TJEhrä!•|kô©ÞÙ¨*µŠ PM¨ D œ„@Uû¨Ôä~@…©ö‹ ª)Uƒ¨”“ô‹…9ªD¾¡UÉÁ•§Â±ª)ÕBþ÷‚2Rφ=s øÔ³~P~x_€ò@C  àTrL ð9(!DJEõ^‡ 2ÐGÎáCPNˆ @ ¡éPdè¿PBˆ ” š[„Þ ø4” ¢å„ÀÊ¢P6è#è„P0¨—@ù!*eƒ¦—ÃçåQ@` T¢¨Hx @ *(- ”~9 @ *€Š‡À@±!*P~hkª J€ÂCTJ·¿J yDŠ Q(tËm-@åCT:¨¬¢•€Àâ(†¨à a  ÔÐ… ¨€’@üYhk* ª£2Be x¨´µ àS($D*m-(Œm(Dªm-(TV Q(=€²CET9ЋP¥€Àð&@•BTŠ ýsPµ0PP™TDêQ@0PPù0\PE¨JÑЀr@`P¨ôw|) T-• Q€Ú@÷( Äc•Q(*Ü¿@Â@A•CG@åBT NÐÊ€rA•PY¨´²Ÿ…E€«P‰€BÂØ}ÅÁ J#œ•Q€úA+ JU@¥@T î€âAŸP%@ß(TYQ($ä¾W´² ,Ð.T0Dê M,€ Äɠƨ1 Ê!Q(ü&)T T> Þ¨7 ¢@ÿ( ” ú2*¢P*䨈 @‘ »*j%…À \!*eƒ@ ¼!*5†å…<"€r…¨ Úæ*‡&”€òƒ¨Ô þ…¨¤ ã ” j-€r‚¨ä ‰u€•À < *€Oá> ”€²ATrÐñ**W Ì€bÀ=(”º3ÊQí+¨6t-«*T\¥…¨†òÚWP"hJÊQí+(Œs”¢(ÚWP:èÑ(DPÕ>PÕ@±0\ª_f€" *€À½¨|І¨>)^ 2ðeV7J QT)SÈ?áGŽ2dˆ««ëàÁƒ“““ù:QQQ®®®ãÆ{üø±P¦““Sxx¸WÓ¦›7oÎÊÊæSJÿYäåËShäÏâÝ»w‡òöö600î¿)¥#FŒX·n]5йáþlù2Œ0¡««K‹ÅçÎRzÄbñúõë{õêåêê:jÔ¨ØØXù,)™E"cL"‘BrrrV¬XáåååââÒ©S§€€€””ÆØ´iÓcžžžmÚ´‘Î ‹Å111½{÷vqqùæ›oöíÛÇÒ ½ …î¢ÐGu õƒ "¨H&P wîÜÙ½{÷Ñ£Gmmm{öì©­­ÍoXåéèèFEEÍš5«E‹¿ýöÛÊ•+cÞÞÞ2…ïܹ388XOOoñâÅ¡¡¡‡‰D§OŸ ±··OHHXµj•°þĉ§N=¶o_|||LLL¯^½¼½½6lH)4iR``à±cǤ5jÔHØ–1vïÞ½üüüæÍ›ËôÖ›šššššÿ9”¤|aš—Ï{ôèQ\\ÜðáÃõõõ¥K[½zõ¡C‡BCC5j$sŽÒòrÄbñ•+WbbbÚµkW­Z5Bȼyó222,X`aañòåËÈÈÈ3fœ8qâ»ï¾›?~\\œ™™ÙÍ›7…¢V¬XqòäÉF;w.<<yò$..N>*;v¬££#!dРAóæÍËÊÊÒÔÔY³fMBH^^Þ­[·V¯^*=p÷îÝüüü-ZçØ²eK™¨€"‹“’’¢¢¢\]]gÏž­££Ã×÷öö>sæÌñãÇ322ž={öàÁBˆäÓg-<`Œ #$Œ1''§;w )XòWáKw¡R€:AT ¹¹ªe̘1#FŒ8qâÄÎ;cbbzöìÉ3g(¥….âŠD"á6”ßtÊ?ù*EOÓñ…m55ÿ×lÝÒ×ßýÝwÇ·±± úꫯ´´´øš·nÝÚ½{·ô"mmm™}ÙÛÛëêꦥ¥5kÖLz¿ÿýwhhh```Ë–-…ýîØ±CúÀnß¾ýÙòù„………¥¥%ÿÓÖÖöãÇáááÒ?**‹eÎQþ) ‹:uêBêׯomm=eÊ”¼¼¼ˆˆBHAAAPPPzzº‡‡‡³³óÀ_¼x1wîÜ¢® p+/!|w"‘¨¨« ‹¿h*¨DPÁÐÙ¦B(¥:::}úôéÝ»÷åË—wíÚåçç—””Ä—òE}úôIIIá‹ù¢ëׯ׫Wßq¦¦¦Z[[ó®h27ÄöööZZZ)))666|Ûëׯÿ³L$Þ¦û»wQQQÂí»PÈðáÃÝÝÝ£¢¢ZµjUÔ¹èèèxzzîÙ³§_¿~úúúÒ@jjjÍš5¥Ó¤ÇJR~¡ SJ e²•6l¨©©™––VÈ9~Z _êââ´fÍšýû÷÷ë×ïêÕ«©©©[¶liÖ¬_mãÆ2û•fkkK)MKKkР_?--­zõêFFF…/ßÙÙ¹U«Vœ¨¨(###;;»„„„½{÷†……U¬ôŸFFF¾¾¾ÑÑÑÆÆÆŽŽŽçÏŸçéCÜ,-- -äÀÅ?-À7n\rrr@@ÀèÑ£›4i’}ðàÁ]»vMš4ÉÊʪ˜sÿlù¢ÌÌLþÔ5cìõë×{öìéÖ­›ôÓÆÆÆÆŒŽŽ611iÔ¨‘pŽò¯w&üüüΟ?¿jÕªŽ;Ö¨QƒRzèСjÕª1Æø°Æ‡ø~¯]»&]N5z÷îellìààpþüùøøø‰'º/a“¢vQô§«ZЩêQT< ¨®BïË !”RéE‘‘‘éééõë×_´hQ÷îÝ ÝJ>yfüøñ‘‘‘™™™M›6 ü')_"±,ú¦¼¨£’9B##£ØØØÍ›7¯^½:##CKKËÁÁ!""‚?ø[ŒÏ–ÏO„*ð9ZZZµjÕrww3fŒÌÊS¦L100à/8kܸñðáÃcbbdR’¤C/ yóæùúú.[¶lÅŠ¡¡¡[¶lÙ¿¿‰‰‰»»{llì!C®_¿Þ­[·:ÌŸ?Ÿ2}út¡¨9s昙™EDDdffZ[[Ïš5«ÿþò/¨W¯^Q»066.þs%Bå«`€ À 0/^´³³333#„0ÆöìÙ³jÕª3gΔïKÇŠ‡·˜AC:æ§„W={öL~©ô›†¾¨´bÞÃú¥rss·mÛæëëëêêÚ©S'ÿS§N•K÷ÁYccþû†ÎÎέ[·nÛ¶mŸ>}Ö¬Y“››+ý±³/¾š³”Ö­[»¸¸ôîÝûûï¿/æ=¯ä߇&÷ïßÏß9UÌU(Ó9VL± Âc¿þúkHHÈ7ÒÓÓ6mÚäéé‰*2ˆ*•Ì3‘2¶k×îØ±c¦¦¦%üõôbJ+œœœqãÆåææ:88|üøñÈ‘#³fÍš8qâ°aÃÊR>cŒ]WW÷³ç.œ¯©©)O·à,--ß¾}»|ùòàà`ƒ¢¶6/ÅG]¸‡ƒÒ©V­ZhhhU” 2!Au!ƒ*˜ÔžŒ±ÌÌÌM›6yyy…‡‡Ë¼ó533366VX$Ì¿pá‚««ë€vïÞÍïY…ü>qäÈ‘!C†¸ºº<899™¯SPPåáááêê:~üøÇ e:99…‡‡{yyÅÆÆò<á…E›7o^W$sïß¿?tè···ôOF2ÆFŒ±nÝ:þ;$E}%)ŸEé_SÑÕÕ%„ˆÅbé "±X¼~ýú^½z¹ººŽ5*66V>KJæ—E"cL"‘0ÆrrrV¬XáåååââÒ©S§€€€””BÈÔ©ScžžžÎÎÎ2»‹‰‰éÝ»·‹‹Ë7ß|³oß>^l1W¡Ð]`¬ 2 ô‚ª…*Õ…±€2¹sçÎîÝ»=jkkسgOáWïÞ½+³HúGE¢¢¢fÍšÕ¢E‹ß~ûmåÊ•Œ1ooo™Âwîܬ§§·xñâÐÐÐÇ‹D¢ˆˆˆÓ§O‡„„ØÛÛ'$$/IåyÇŽ‹‰‰éÕ«—ð†©‰'Ê/jذ¡ô ú½{÷òóó›7o.º@)555^a[¨–ÿÏÚ2J)c„‡ÆÅÅ >\ú‡ !«W¯>tèPhhh£F¤ÏQf§üs–H$W®\‰‰‰i×®gæÍ›—‘‘±`Á ‹—/_FFFΘ1ãĉ ,˜?~\\œ™™ÙÍ›7…¢V¬XqòäÉF;w.<<}ú”ÿº9¿•×ÑÑéÛ·oß¾}¯\¹2þüŸþùÒ¥KüåG|‘——Wjj*_”œœ,ì‹÷BŒŒŒJ‘ S’òù„íØ‘têTPPŸŸoii9tèPé¢rrrvíÚ5sæLwww~ŽþùçîÝ»¥×ñññ277×ÐÐÐÍÍmòäÉ|Gü™fþVÝš5kz{{Ï™3'33³Zµj„“5jEeffÆÇLJ„„ð£ôöö~úôé–-[„¨@þ*˜ššò]ð°§V­ZÂ.¾ôse…ÀT¢¨0êQcŽ=zïÞ½¡¡¡ èß¿¿‰‰‰Ð‡-³ˆw· 7ÇÎÎΚ͛7ÿé§Ÿ²³³e ¯[·._‡wY³fMBH^^Þ­[·V¯^*=p÷îÝüüü-ZgÔ²eK™¨€"‹“’’¢¢¢\]]gϞ͓‘!ÞÞÞgΜ9~üxFFƳgÏÔ£Jå€<"PEˆ Ê$00pĈ'NœØ¹sgLLLÏž=½½½(¥cÆŒ‘_Ä;° !<žß†òPAþ‡…Eœôs¶ƒŌ±Û·oïÞ½ûøñã666AAA_}õÏY*t‘–––Ì#ÑöööºººiiiŽŽŽÒó_¾|تU+áÀøËM·nÝúlù|¢N:|ÚÎÎîãÇáááï߿֋Å2ç(Ÿ¯oaaaiiI)µ±±±¶¶ž2eJ^^ÞòåËùæAAAéééÎÎÎ|ñâÅܹs‹º‚­¼„ð݉D¢¢®Â—îTòˆ@å *(+>}úôéÓ'%%e×®]~~~‰‰‰BÒNŸ>}z÷î}ùòeaßêúõëõë×'„0ÆRSS­­­¥ŸñÈôÙÛÛÛkii¥¤¤4hЀo{ýúuaéðáÃÝÝÝ£¢¢„Ûw¡aQË–-‹ú mmmOOÏ={öôë×Oø%¤¦¦Ö¬YSºïßÚÚZzó’”/L å0Æ eÖoذ¡¦¦fZZZ¡ç(_ ««kPPК5k8Я_¿«W¯¦¦¦nÙ²¥iÓ¦| 6úar¶¶¶”Ò´´4~ÕÒÒÒªW¯nddTèÁB„]ðÌ"ÆØÆåK†ò„Û/PLøf‚ ATPnœ[µj•‘‘!ÿ“£ü•[éééĄ̂¨(###;;»„„„½{÷†……Z¦L7¹‘‘‘¯¯ott´±±±££ãùóçyúwàÀ ù{_ÆØ,--‹?~Jé¸qã’““FݤI“ìììƒîÚµkÒ¤IuêÔ)æ7ˆ>[¾p"™™™ÂÙ¯_¿Þ³gO·nݤŸ66668p`tt´‰‰I£F„s”Ù»tháççwþüùU«VuìØ‘ÿVÒ¡C‡ªU«ÆKHHàÃ>|àû½víšt95jÔèÝ»wTT”±±±ƒƒÃùóçããã'NœXèÁ ›µ‹b?`P-È#Õ‚¨*†ºvŸPJ‹¹9¶´´î/"##ÓÓÓëׯ¿hÑ¢=zU ÌœñãÇDFFfff6mÚ400'å³ëâJš±±qllìæÍ›W¯^‘‘¡¥¥åààÁü-j«’”/l>|øpþ§¦¦f­œwÿ1cÆÈ¬<&&Fúœ¤ ä?K:oÞ<__ßeË–­X±"44tË–-û÷ï711qww2dÈõë×»uëÖ¡C‡ùóçB¦OŸ.5gÎ33³ˆˆˆÌÌLkkëY³fõëׯÐ}qõêÕ+jÆÆÆÅPêZŸ€@¨BvÊjI(!¹¯ c,11ÑÎÎNxCÂîÝ»W­ZuæÌ‘H„7…©#Ô' Èx¥„¯((?¼Å ªš\ÂÕ¯¿þróæÍôôôÓ§OoÚ´ÉÓÓ!šBH ßOP+€ €V¾È§_þæ„~øáìÙ³ÙÙÙµjÕúúë¯G%“Aêõ (|QAù!*€ €Ê¾¾3P(|1@‰àë JDêQ(üÀÈCÏ+(Ôc ä@@C¥ƒ”š?Pfˆ @1 5i(¨\ˆ @a`ü Š *Ń€Ê…¨ † ª¢P< @Ù¡eƒ¨Ê*A(;¤Ž€ ÀÈ'(DP~ð›!P^К€ @UJQ( ÜBTD 00ުà<T $@9A'”êPm @á!*¨HˆxA *€ª†PyÈ#…‡¨Êj:¨Pø‚€j@m Q”ôóAÅA›jÃ@¨ |ÏA±!*¨èㆨ”šRU…PC¨Í@!!*€2C£•M)(;´˜ ¨(÷ÊQT|ÙT .(”#¡×€%ü;Çs0çŸ9¨jJQ”Úu¨Lø¾©\M(G”þï.@¢‚’AT„ŠQ” Úu¨dxì¾nTJF³ª@Õ©Ešã;噃zƒkêB IDATªÔŽ*;\A(wH(䆅lÕÊþýûÜíÛ4?<ÆØÑ£‰cƬøê«6e)G ]cì³eò(¥/®­[לÏüø1ïâÅ›S¦D=žÒ£GëgÏâÍÍMJq„BùgÎü`gWGz‘¶¶–ôŸ%9ÚRcŒ½y󾨋8c†OíWm!*¨`ÔID•Œ16kֺׯß$'o066à3—.“—WããÓÅÊʼԷ³”þï'Ëå¶Xº;¿$¥ ë››Ôæ×¯_;++gâÄÖ®fd¤/½¨tÇcff,_È—íí· @¼oß¹¨¨}çέ¦” ÑÈHŸïkÉ’ÑÒÑÍmÒ„  褥…{Ú²BT @%ÊÉù°uëñ !!„16{¶ï©S‘µjU—éž/(/X°ÍÆf°ŽN{û¡+Wî–HcìàÁßE¢.7þÂ× ÛlhØóúõG}û†0Ƭ­½54º³9Ï´‰‹;Ù¢…¿®n''ÿÓ§¯0ÆcùùÁÁ-,èéyxx̸}û‰p0qq'›5¡­Ý½víþþþ˳²rdÎNæà¥ç‹D"‰„I$!ɧ˜c‹%aa›­¬êêöèØqÂÒ¥;䳘äJøÑñýnÝz¼eË]ݶ¶¾ûö;|øbóæ£ttz4nìwâD²t±ÿµdÉ[[ß "Û·oÆ{ûö=¿ˆBHÀ÷.\DBHûöÍ&Lˆ´µõ]²dG‘ ]È5-D•­|2äŠ(YHs,{iœæX¬D¾¾tbQiŽ¥;ž={dÊçÿdÒ+á-嫊Û#€rôéo¥¥=ÌÍÍwum*sÓlnnÒ¾}SmíOú•)¥“'¯þñÇ“ëÖM¿woÇ’%£—-Û±`ÁBHŸ>®AA^ÿùÏÚ'O^œ9suÑ¢í?ü0©iÓú[·Î¡”¦¤l|ö,žRÔæÜªU{×­›žœ¼ÁÀ@÷ÛoK$Œo{dýú·nmóôt ÝÄW¾wïÙˆK r¿woG|ü‚ÿþ7eΜ 2í‹|o=¿;?}úÊÂ…[{ôh- s ³g¯_³æÀêÕ“oßÞ>hP—°°-DŽüh€ÌÁî?EFN¼z5ÖÚºæÈ‘ËÂÂ6¯_?ýêÕMVVæ~~‹Åb c,5õ~@Àòzõ|86òÉ“ÝË–‘¾ˆ2Ç \DJixxà“'»ÃÂFîßÖÚÚ{ôèˆÔÔûòg%Ñ– öiúP…fÈQJ½ÈÓ«v@31qÝgÓKq„BùgÏ®*>ͱâr¹ŠËUPYø•+;û!ÄÔÔ°$uòóç™6:yreçÎN”Rkëšé靿ÎÝ(ì¨\ŽVºð>üDþ­%…?ml,„4ÇjÕôJæ(hföIùòÊýá§üüžæxöì*BÈgsU…4GMM  •Ù)Š*‘™™1!äÕ«7vvŸicW¯>‹%½{ÏÖ‹%?æýùçß XèëëÄÅ…¶mhii=U¾´b6çÚÙÕá‹x«‘Ÿ_póæã‚±‹K¡§¿CG´oßlàÀÎ+CBbºwwöòêðÍ7n2íšÐÜÿò˲:uÌ Ä¿þzyΜ mÖ¬™ª¯¯#šòÇpûö“¼¼áFœ1Ö©““LT°wï ,¤çÔ®]ý‹Î½I“z|‘.!ÄÆÆ‚~¼+,l$RATPÁŠHs,&CN˜É+4WRêåÕž§9>}ú÷Ù³iBšã¶mÁ<Í1=}/ùÂ4GžÛ÷EiŽEURDê½ @œZÂ4G~ %Is,þá§Ïž{ñiŽ<~HM½?zt„tšcxx ¥ô³¹ª”ÒeËÆH§9,Gš#¨;ôÕAåÒÕÕ6Ì#:úÀ›7ï…™”Òï¿ßuþüõ:ṳï›6­O)}òä9¿ñµ³«sáÂÍùó7óîÞýsÚ´5aa#½½»øù-ái-ÒŽ°¹p-½¹°kéMš7·ÕÖÖÉ(†/‚ ¢JU 9Bc¬˜\=ù4Gÿ¯IiŽòY’| ú»¸4!…¥9zyµ'„ðÃbÒ‹Ðü¢4G™cÒû÷ïD™4i@YÒ‹:÷%KÆtîìD¤Òùa𿨱££ô9–$W•×e£Fõ9²ço¿]Cšc%áøûT4(€ª@)]´( !!ÕÍmâ¼y#Z·nôúõ›ØØ#QQûÃÃ4°±·²26¬GHHŒ‰‰aûöÍoMšôàAîZZùùâo¿]Ô¬™ÍÌ™ƒ³²rGN˜¹}{ˆžž!äâÅ›..MŠÙ\8™Î,SSÃ)S†„ÄT¯näâÒäèÑDÞÚB õbbK$lÚ4ïüü‚ŸþÍÁÁÚÔ´št›[hŠ/cì?ÿ|äÈÅY³Ö{zºÊ&2ÇP£†Ñر^!!ÍÌŒ[´°;z41:ú€Lá/_fgd¼’)‡Šs¥8w™ÖSæ¼:wvêÜÙéñã¿øVÅ\D[[KBȽ{;êÕ«õ™d]4 %ƒ¨ R•0CŽB)-&WÏÆ¦¶žž¶tš£|ßyIÒùVòiŽü¿(¥´ø4Ç¢Æ MsÔÓÓ–?MùcÒ…c¨ 4G¾_!Í‘¯YL𣙙1?ž’çªþýwÒ«j„+•@îA5j?¿féÒ¸Ù³×ÿñÇsmmÍV­îÝ»€?\ûɦ”®_?ÃÚz{pðÆgÏ^Ö¬iäõÝw£!óæmºqãñåË54D5þŸ½û‹âjûüœÄJQAcWŒFÄ€ ‚ ‚F±E±ƒ5ŠK"–„ £ˆhLb¢Ñ ~*‚â+vDc‰1ÑX_#+mÏ÷ljóŽ»Ë²RwÙß}yy-»3眙9ÏœgfªY¬_?³ÿÀž=Ûôïß©wï¶~~_Ñßç5»¼ •ö~þùKËÊŸ~úÍ£GimÚ¼»hѨٳ¿%¢V­mÛøùçÛZ¶[±¢y—.ïÿüór‘x#Í«q¬€1¦PЦM³Zµ7yòWcÆôV]CjmX¹rb•*'Oþêñã gg‡Ù³‡-Y²U:ÝÎ9ws›¦¾¦ÿùç€üÏ·]víA‚P¯^Mñ¢jÕ*¿DqêP>%¢‚b–GšcÛ¶ïÊ÷îý=|ø’  1:µ"~)W¯I“7BéÁ+ò4ÇNUjÖ2ûåË·ˆH¡Pѓҥ6HiŽ&&Š;]¹òçÿ9|øìÈ‘ŸGD8xp¥ÆTݺ¶õëÛQÓ¦uš4y§oßÏ23³÷ìY¬¾zÔÛ ¥9JmИæ¨VÉ'ËwÙMLòzÓ°“Z´hôgŸ ß¾ýÈš5QK–l:´ëäÉý[µj$}‰bxAªýþý'Ò—xîܵk£·o?òî»uƒ‚FÚUå.xP\pu¾Á×¥ªjÕ*+WN\¹rb¾Sš››-^ýôÓ!âÅ!]† 颥µŒ1•’¥÷7®ýìY¬øSLP¿¾Æ6pÎãã/Lšä³xñqL\»6¦bEóªU-ˆhÐ wž÷cXåµçµê´,»úŸZ–T÷/ ×”¨|3ää¿–\=ÎùµkwäiŽâÚ_i޳$¥ªå½a)ÍQºðHJ1LHH XݨQ­O>üË/+Dšã“'Oµ\a,ÞéÞÝY¤9Šk£Õ׉J¤4Gõ6¨Ì¥òN!—]=둈DšãÙ³¤4GÒ!W•diŽgÎ|+ÒóÜ„"„À@ß` @/1Ævï>6lØ’3g®ýñǃèèÄe˾9²§Ê »²{!Ýàüe‰âœç›!'yçÅæ¨ò³/@š£.šÚÓUÚ cšãƒOTÊyÛ4Ç·Ðìܹ¥››ãŸ>ïkÏU%¢7¾ÏL‰.P敱Žè¹¼OlƒFœóà`ÿY³Ö{yÍyòäiíÚÕÇï;wî‡e-$!*(fo¦9Š0írÎy¾iަ¦&66–NsT?ãþViŽ …¶{Iš˜(´¤9ª·A{š#©§92Æ22Þ¸åÂÛ.»–‹Ÿ¤ ¤Ž~¾¹ªHs,e¸ìXà[ÐWŒ1+«Ê6|²aÃ'¥ÝÐ îM E‰1œ½x[‡yï½úâagœóuë~š={}FÆ“²•ðÆÜÑa*^ J—ˆ«ñ@É9VÚ }…®n0Vú…s¾{÷±Ï?ß¶bE@õêVçÏßiŽe-$ ô–À`#7,e o§á cÅ §.ÞZzú³Y³ÖïÝ{B¤9ŽÑcîÜUñV&t.í ”"¬|ƒcèƒÛjw&øÆ tƒ¨ ¸!*€¼ *(~HbТ(³pÀÕI™ËÊ0emèC/!0 ×ç û)€R„ûæþï éàkœïˆœ©‡#íùÈ2ˆŠyÌš¤9–Dº0ô "Ã!Þ2ˆJ ö×%« ?ˆ Šλ€ñ` Ì(\WP"ô'ѰtßAš#Ò¡Ìö `˜p]2)KÒÊ6\ÂaÐp4,KpÀ…·‡ "(  ¢0&ÈzÐQÅQô\4ATFF~#,(((»bc“==?­ZÕË̬k>^^sŽ»XÈû”0æ.ý37ï^³fÿÑ£—gd<×}ÞÓ§¯–ú½Rti ç\¡ðP(<Äd …‡|ÙË—ï^·îàI“¾JK{ª{™Åw& ‚‚¶E‘“S#[[ë””ß÷ïÿOllòöí  èÄ ]sÎÅŒ;·´´¬”‘ñ<)éò–-ÓÒžFG/Õ^¦4/¬ö¢Â9÷ñéHDÖÖU´´„±7îô(^»»;YYU&¢—/3OœH]¿~ï;öîýœˆt) øàΤ¸[ ÂÒ@àôvQÁš,3Þ<>|®{÷™ææfÑÑK==ÛQffö¨Q_ìØqôwjܺµ±vÍs'¢ääõ..D´oßIoï¹Dtÿ~”­­µö2åóê×™snbÒ…ˆNúÆÅÅAzݺuSñéÉ“W:t˜LDwïî±³«Z”K„.¼=d€±Òû.@) ÝCDÓ¦} B"277 và@pròzñëILLñð˜^©’§¥eŸÞ½gŸ={]:Õ(’a~øáp§NS+TèѬ™ß¾}Iœsq¾_tÅ‹=\Ä‹‡ÓÄû/ÞìÛ÷3 ‹Þ+öìØqʧD™òy}| 3ÂD™ÙÙ95jø(ÿ÷g9çyÕ.ÊÑR¾Høùþûÿss›V¡BGÇ1çÏßX¾ü{û*Uòôöž÷ßÿ¦‹å©A¹¹Ê  - 33ëZ©’g›6±±Éôz¬@ªWz-þgŒ995Kôøq©¤)*‹ •³eËA‡*ôps›öã‡ÅòãÖÆQfœsÉ”…,SÊ)T(<äÉ”ùŽØÈw@…iCáéÞì¤@¯á,Z‘À@AÙ•””JD]º¼/?BU¯nåéÙÆÖÖšˆ/uë63!!¥U«FNNââNwî<-5õ–¼ë?iÒ— …ÂÆÆòêÕÛÇ/}ñ"“ÞìsÎãâΑBÁjÕ²áœ_¸ð[ûö“8Õ ]ëÖM“’.{yÍùá‡Ãôf'{ìØ>D´cÇQ¥’ÑáÃç?Ψ[×¶K—÷éu¼¡^»Žå¬655±´¬”šz«K—K–lmÞ¼žR©Ü·/iÑ¢HQ¸¼»º'((òñ㌞=[שSãÌ™kÌw)Œ‘Z%^+•<=ýÙʕۉÈ¢bãÆµäkFz­²ÏŸ¿âœïÚulÔ¨/®_¿ãäÔèåËÌ€€/å%¢ 8ç‹oíÕkÖÁƒ§ëÕ«Ù­›³™™éþýÿéÖíã={ \¬”_èîîÔ¯_ûöí›§¥=۲堟ßçùþ˜å; ÒMúbŒy{wðöî`m]Eû%VØI¾ÃeÇyKOFD––•Äž|âÄ/å'¶Îœ¹¶hÑæììœððO×ÄLJlÚ4ûÅ‹ÌÏ?ß&ï4OŸ>0>>äСÕDôìÙËß¿G¯;dzf­0`¾‡ÇôAƒÑt®VÍ‚ˆfÏþöåËL?¿ž.l:vì멜ó™3׿ääÊ,½{·­UËæÁƒ'GŽœ#¢]»â‰Èϯ§B‘Oíº”?kÖÐÇ¿üöÛO8çééÏvìX·jÖ¬¡DtáÂo*#Däââ°|¹ÿ¡C«÷íû"!!”sþòeæ< Mý6m kë¾AA‘ff¦¡¡•/_ŽÞ Äki8çOŸ¾‹°zõÆØ´i$%­MN^?lXWy-†¨@ƒ#GÎE–/_î—_Vœ=»áÀàßÿqð`Ü\åǯ§% @Ú‰¬X³ìèÑ]»‚ˆhïÞ¤žè8/•ö%VD½4:zi£Fµò½Ä ;)€² eš%=zôoÂŒ£cCoïârX±oONþ•s>fL°@5ê ÎyBBмÓÜ¥‹35jTK¼™™™M¯;ÇññbbŽ'%]¶±± è·iÓ,1Kbb ÙSL6z´'çüÁƒ'7nüE²N¶‰‰bôè^D´}û‘¬¬œèèDÆØÈ‘žùÖ®Kù­ˆÈήš(§k×÷‰ÈÖ¶*eee«tìØÂѱÁ?rs›V¿þ1AVV6iêè»»;¹»;•+gÆ{ï½úW®l1¢»z™âµ´b±—.ýND¸‰7}}=pŠ¢ ¤dÊž=[‹_Z¹r¦R2¥BÁHS2¥˜—ç ¨r¾ŸsÞ£‡‹xñðašx¡žìÈ_gJóz{ÏÉ”¢F•dJ홈y•O¯~´'SʧԒL©~@Oa¸ :9Qlì)±3Ÿ8Ñ;:ziTÔiß®TrÆXçÎ-}|:Jÿ:txOÞÁ­P¡™˜(¤7éuç89y=çñYYÿw÷îîuëfT®\þ=†¾Ñ‡æüßLv)‚˜`ôè^Œ±¨¨„½{O¤§?ëܹeýú5ó­]—òÍÍÍèß°W”c.? ©ãfÌëÝ{vRÒe__Ç¿RïÜË_¯XpäÈWññ!+š§¦Þš5k=çʯ+T(Ç355á¯É¿#•NEQ~ý`”h %SÊœòdÊ„„õdJ»K;#¹€*û¸¸3Œ1E­Z6DtñâMõdÇ<¢²³’)ss•œs•dJ-µëR¾ödJõÝ–ÆdÊþyAØIA`P((ë¦N@Dááû¥ÔÙÜ\åÆû¥}»³s"òôl+GŒèéèØpøðî*G y7]”#ï˪TÊkÓæ]"úî»81Ydd,ÙÛWkܸ6½yd)¾Ï?þx-ùùyе׮{ùg×øfxø~"Z´hô”)ý¥ÚŇê}ñÂÕµù† ŸQttbHÈníkIåÈëäÔˆˆ¢¢Ä›ßHþ)@!*Ð@J¦?ʼn¿”?väôé«R2åñãaÇŽ}-%Sʺsųf­ïß?ÐÝý#)™ÒÆÆ’1&%;ž?"%;ææ*I¶ƒÈ+™Rì´Ô®KùR2%ed{ÊËË•16q¢÷ĉÞôúá)D$.8îܹ¥µui.33Sé,Éséõ¾ÿ{…–æÇ¯HÉŽ¯'&yò]Òèѽ–-Û•àéÙ&=ý™»»Sƒv${î£ÆÚu)_J¦o¾¾+¿õª´„s>cFXhh”‹‹Ãˆ=V­šäê:Ij¤ú€aéÖ͹[7ç¼>íÙ³uÏž­ÕßgŒ)•GåïpÙóѸÖ'‡2Æ\\~úi™ÆOUæ½ÿï§O_,}(ßÚ‰HÇò[·n*/Gê ¨OéìÜ$9y½Æå%¨´Š1V±¢ù¥K›5–©Òfù¼›7ÿòèQúW_MéÛוˆ¢¢‰¨fͪ ;Œh %SFE%Š=7W¹aÃÏR¤.%SFE-‰ŠZ"%Sj<“¡å<ç\Jv“EFÆ2ÆjղɎòyë×·SI¦”ú÷Zj×±|©=\‡aS•dÊ×þ7q~/ÅÛ*€áàœ?~iðà öí'geå´iÓ´cǥݨÂ9¿}ûáœ9||»t™Ñ£Ç'#G~NDƒ¹—vÓÀàa¬@ƒŽ[^° bàÀ-[6¬U«zJÊÍ»wQÍšUE2¥—ל¹s7îÙsÌÒ²Ò±css•ß|ó±üÔ;i:Ç/?Ë®0Æ–-çá1=22öܹëVV•/‰dG…ʼD4vlŸ¸¸Óýõ_ ‹JbèS¥XõÚu,?¯Ù5¾Y§ŽíÕ«·Gú¢U«Æ‰‰)&& ñdÂXƘ™™éÏ?Ÿäœwëæ,Ž¿FrÐaŒÍ™óavvή]ÇNž¼Ì9Õ®]}ð`ùóG–vÓÀà!*Ѐ18ÂÕµùš5Q'O^¾råOkë*ݺ9÷íÛ~ôhÏÊ•+¼óNõýûƒ¿øbWóª IDATÛ¹s723³›7¯7}ú ?¿žê 6ôfçX¥Ë®ÂÕµùñãaK–l=~üÒõëµoß|þ|¿=\HSwßÛ»ƒåßÿãëë^©Ry飼jgŒéX~^×øæwßÍ›8ñË‹oŠdʳg¯íÞ},1ñb÷îÎ((ƒpë!ÐmÛ¾ûüyli·¢t”+gºt鸥KÇ•vC ¬aèºc¤5ÇQqÎÿüóaÓ¦#²²rBÅý¡K»Q:`îèO6De˜ !O8àÂÛÃXá9~üÒš5Q‰‰)"™Ò`B0t Ê.D†s®’L‰ ˆ¡ï ÆQaŒs2%@I/@` ë LÃIŒ¢5xÚ± ”uˆ ò€ÀŒ¢Mpj\‚#€¨ È#£¨ò†ã€;“ä w)£ÂÜK»PjäÇh£]pãd ßµn¥h6èdh…C €Þ2Ð+D³ ®ñ"$0¸fƒÎäÇ8„8)zΕʼnqìô±[)IØÞÀ@aÙ ˆtÞÚà.þ1Ж˛j@͆·ë ô¾Ÿªç¿=4Œ„a¿‹„Q-,q.¯llŸ†²cQi¤¡4Þ2ˆô›žçðéyó=olN¥Kw¤þ¨ÁuL¥Î´ÁµŒ¢(»¤ƒzrP$p(]eòü´þ¤4®výo6¼=DzL~FA{zÞ<9ýo!в×#0ZBCÙɗɨÊDúJcŸþÐóæ©Óÿ@^ÊvZŸPe !*€2ªlBŒGÙØŸk_ ýìaç»æõ³ÙPPˆ ô’žçðéyóò¢ÿ-(uø€*!€!ÀI¡p âŽÊ%úß`ÐB}O®ç»wõ¶éÿ"èþf½j6¢ý“o_éþöô¼y‚A4 ]ÙÛÊÞè YzõÔØì%Ê4dé=ÏáÓóæéÈ  P‚€QB`…Wƶ"œC‘×¶Š  pA¤Oô<‡OÇJK=EGcí38 i(è=ÏáÓ½zÒ`I;§ ú£ÌlZú³Ÿ€R‚ "(sй’Tfƒ€ Ø *0nèf¢€ÂÂp>D`Ðoƒbe¸ À€`s(Nˆ Œ¢€¢`ˆÃ8ó ¯!*(: ±Å Q C<• †Å°º,èc€ ¢€¢ƒà ¢£„0 Ú(~ˆ Šú.`€€~C° Pü@áÖžÚ°Z eŽG ;DÆ·HM}ë‚ãF.DÅIßÂ_@IATÆÇ(1zub7DP8èah‡§Xe±[ýƒ¨À”áÞD`”p’J† @ï!*ãƒ3¦P*J10@L†\% Q@ñ+õÎM©7ô¢€QZyD( *(ë0PéC%Q%\ý ¥¢ä7 —°»×{z¾»Ôóæé¨l,9ƈÇËß§ÌOú¦uë¦DÄ9ßµëØ!A+š?{û–e»QròzÑ•OJºÜ±ã"úë¯ÝööÕÞjÞâÃ971éBDJåQY Üñ“"cœ{`]jm6èD¸´t%2vèõ cìÅ‹WDÔ¤É;“y¶l9èà0¢B…nnÓ~üñ°øTLÉzñ?çÜÉ©‘øèñã Îyn®2(hKÆÃÌ̺VªäÙ¦M@ll2ç\„DÔ¦M€‰IñŽ”¶Ä9¿xñfß¾ŸYXô®X±gÇŽS8%ýSþðÃáN¦V¨Ð£Y3¿}û’Ä\«£×c8Pæ!ƒ@W¢?kÖz‘ö“‘ñüøñKõëÛmÚ4KêÜ‹)Å0ÂèÑˉ¨mÛw_¾Ì øRŠ%T¦äœþùçù×_ïaŒYXTlܸ…†î ЬR¥bÏž­oÞ¼wæÌµæß¿åãÓ1&æ8½Nd’ .^¼Ù¡Ã”—/3XZVNLLñòšóÝwó†í"M9iÒ—-[6²±±¼zõöðáKïߪXÑ<¯ê,,*÷p5œ{Ј t%ºòññ¤wc¹¹¹·n=prjDovÐW¯ÞADS§øúë©D4qâ—ß~»dã œó6mäå—+gúQ… æDäââ°|¹¿»»SëÖgØÚöõ*ë?DE-)=+VH‰LR ³gûòe¦Ÿ_ψˆÙD´fMôôékfÎ\ëëënb¢SNŸ>páÂQ×®ÝiÖÌïÙ³—¿ÿ~ï½÷ê«TW£†ÏË—™üñÀѱ Œ2ˆt%Ò~’“×+•GsrŽ<|óÉ'ƒoß~4vlð«WY$K1"¢K—~'¢ÜÄ›¾¾oäI.»»;•+gÆkÑ¢Á•+[FŽì!fïÔÉÑѱÁ?rs›V¿þ1oVV6½™È$OF"¢ÄÄ"9²§xsôhO"zø0íÆ¿¤öwéâLDÕ³gffQÇŽ-äÕ‰)Euòò ¬BT@D¸´t"ïô›˜(jÔ°Z¸ped<¿yóåÑ–_B ¥é‹×+V9òU||HÅŠæ©©·fÍZ¯Tþ[þôékz÷ž”tÙ××ãðá¯ä%k,P|¤P0yS9ÿ_ä ½Y¡B9Ñ~y|2cF˜¼:y™¸®Š Ò‡ô ¢]©_"|ûöCÑi®VÍ‚Þì@‹œ¢¨¨ñæ÷ßR+¦l×®Ù† ŸrΣ¢BBv‹ÂÃ÷Ñ¢E£§LéÏÿ‡¤Úss•êcmÚ¼KDß}'ÞŒŒŒeŒÕªeÓ¸qmÒN¨T÷z‚7–Ê0\W +ч–®6ÎÌÌ>}ú*cÌÓ³MÍšUéÍë >ýtÈ€óCC÷œ>}533ûêÕÛòëŒå'þ‰hèÐ.ññçÃÃ÷ÏŸ¿©OŸvMšÔ®SÇöêÕÛ£F}ѪUãÄÄ…RÉÓÓŸQõê–¥O˜°ªJ•Ї­–ŸÈ_¶lœ‡ÇôÈÈØsç®[YUNL¼¤P°¯¾šbb¢ 7/qVi­Ju “ªÃ@€1ÀX€®D7:>þBLÌñ˜˜ã‡ÉÍUúúºoÝ:Wýì»OLjˆÙ ÚŸ?ÃʪòÆŸÒ›y;Òµ¢ä©Í›×{ù2s̘`¥’÷Ý<‡ŒŒç©©·.5`€%&^$¢àà€Úµ«_»vçÁƒ'iiOå#®®ÍóòjçΓ“¯¶oßüÀƒ¹ÓëG§å5V ¥:Œ@±@ú€žÁSÌôžžï7õ¼yo¥,-  µ§˜éŽsûèQz³fu½¼ÚÑž= ƒ-¬UËæöíßÉÆSÌ ðŒ|—k ‹o ÍÝ ƒà5qÁ1öwPc·o? ÚÂsss455IJºLDƒ¹|HP$°³Åô ¢€¢Ç9Ÿ3çÃììœ]»Žô¢MðÔÐcÿëñ”V×GTZ°íVe.lùF Q@AIñ@!CùŒ…ŒH H㈠Œ ¢€‘ºÑ…/G * 3{BlE éC†W¼%ñ@Áú=ÅÔ§/@±êsÉctéÊ:D:+Ú.r^}÷Âߨï,„ØÀ8 ƒ ¸àäT.!Pÿ´TzÌZê-À¬eäA!}À@ *ýÂ9OHHpqq¹{÷®ú§ÒG:>“[*íÁƒEÕÂÌÌÌ­[·6ÌÕÕµS§NcÇŽ=räH‘<#\4ÕÙÙÙÙÙÙÅÅ¥M›6^^^k×®ÍÌÌ”¯-u‰Éœe\\\Úµk×·oß/¿üòÅ‹ÚçÍÍÍŽŽNOO×þ-~‹¼Øâ%u…óZ{Å‘;T˜[”¦í³ 6€@H` Aú…Ézœs•?Û¶mkmmÍtë”h)­`ž={6iÒ¤ÌÌLÿ¦M›¾zõêÀ³gÏž:uêˆ# S¾Ô_ß²eKÍš5‰(++ë·ß~ NOOŸ;w®.Ë.>bŒEFFŠBˆ(33óÒ¥K«W¯þûï¿—-[¦eÞ¤¤¤eË–¹ººZZZJÕÉzSYFCRL™3ê!A1O-އ”!§ ,ÂX”œœœœ¸¸¸±cǪô9ç?RéŒ2ÆÌÍÍmllLLLt¬Q¥¢±cÇÆÅÅåää¨O)}¤ýlzhhè?ÿü³iÓ¦.]ºØÛÛ7hÐ`Ê”)Æ ûæ›o>|¨eÞ|Ë—ÖÚÚºZµj666ööö:u=zôÞ½{333uYv©pkkk›×jÕªÕ³gÏ &ÄÅÅ=þ\˼ÒìòU]T!©}¡@KÊÊ4oK—Yò=Ó¯cÕ»ìX—É”!ˆ  ØqÎÓÒÒ6mÚÔ¯_¿ààà–-[Ê{‡iiiÒGÒû'Ož}ú8;;«TÞ·oßvíÚ}ðÁQQQ¢X-ß‚Æ* o¬ 8úÜŪ¨.†Ñ«…€ "(^×®]Û¹sç/¿üÒ°aCOOOsss"âœ_¿~]å£råÊI3†……Íž=ÛÉÉéøñã«W¯æœûúúª¾}ûö¹sçV¨PaÙ²eû÷ïW(+W®|¸¼¨gÏžíØ±cÖ¬Yîîîbÿúë¯;wʧ‘ !¢ÌÌÌÊ•+»¹¹}ôÑG¢"qM³ƒƒÕ¨QÃ××wΜ9iiiUªT!"++«jÕªIE¥¥¥íÞ½{Þ¼yDäëë{çÎÈÈH)*Pÿ¬­­E"ì±µµ•ªxÛõV¢Ð£-<ù3’@;üL@Ï *€â5~üø={ö0 ÿþVVVÒ9l•Äév©sììì,Méèèøã?fdd¨þÎ;ïˆiÄ)𜜜[·nåææ¶hÑBš·eË–"*ÞIOOŽŽÞ³gOvvöøñãUҙ䩌 XYYQFFF¾àrÎÝÜܤ?ÄôÚË/BBBjÔ¨ADYYY¿þúëš5kå£ׯ_ÏÎÎvrr’–¨U«V*Q($777999,,ÌÕÕõ³Ï>ÉHDäëë{ìØ±ƒÞ¿ÿîÝ»7oÞ$"¥R©qYnÞ¼)¾ÑZÆXË–-·oß.åA© Œ±·ª¢ô¡#[„p-2HiDP¼üýýG·}ûöððpOOO__ߦM›2Æ&L˜ þ‘8MD"^tCE¨ ~¡­ô‘ ¿N@š×ÔÔTzóêÕ«;wî}zVVÖŠ+Äì÷îÝëÑ£‡³³óÀ=z4þü¼¾A©+/!¢:…B‘×·ð¶U”&=é¼–½ÎbCƒ¨Š¹¹¹—————×Ù³gwìØ1räÈS§NII;^^^}ûö=wîœô‘˜+55µ^½zDÄ9¿páB:uä×øJTÎÙ7nÜØÌÌììÙ³ 4󦦦JŸúùù¹»»‡……IÝw©é£V­Z©Ž0Fœ3ÆÊ•+×§OŸ]»vùøøTªTIš÷ûï¿¿páB5äçþëÔ©#/C[ùj "•Ã9¯\¹²ÊôMš4155MIIѸŒêººº¬]»6&&ÆÇÇçâÅ‹.\ˆŒŒlÞ¼¹˜fÆ W¦Ð°aCÆXJJJýúõÅ·–’’RµjU '"© ‘YÄ9߸q£zÉ¥¬¬vX‹ãV¤†ØÀ˜éÏvºAT%ÇÙÙùý÷ß¿ÿ¾ú-GÅ#·îÝ»'½faaѨQ£øøø={ö,Z´Hc™*§É-,,† ¶nÝ:KKË-Zœ8qB¤ 111vvvê}_ÎyLLŒ½½½öö3Æ&MštæÌ™qãÆ?¾Y³f{÷îݱcÇ´iÓjÕª¥åDù–/-HZZštAö“'OvíÚÕµkWùÕÆ–––\·n•••ƒƒƒ´Œ*µËC‹‘#Gž8q"44´cÇŽâ^Iûöí«R¥ ç<>>^ k¼|ùRÔ{éÒ%y9ÕªUëÛ·oXX˜¥¥eÓ¦MOœ8±{÷î©S§jl¼4K^Uh]Á%ýÔ’„ØÀ *€ÅÓÒ9¶··—ú—ãÆ ¹wï^½zõ–.]Ú½{÷¼ TygòäÉ•*U IKKkÞ¼¹¿¿¿HÊ×RµöVÉYZZFDDlÞ¼yÍš5÷ïß733kÚ´éÊ•+Å…¿yÍ¥KùÒì~~~âOSSS[[[ww÷ &¨L<}úôJ•*‰œ½ûî»~~~áááò;8É ·%]°`Á°aÖ/_¾jÕªÀÀÀÈÈÈèèh+++ww÷ˆˆˆ¡C‡¦¦¦víÚµC‡ .$¢™3gJEÍ™3ÇÆÆfåÊ•iiiuêÔ™={¶Æº„ºuëæU…¥¥¥öõPìÐ7--ˆ ô›†ŒdÐ/z>«çÍ+z¶ŒœóS§N5jÔHzBÂÎ;CCC;¦P( ïIa%FŸû£E»éÙ«>P$ô#Ô†¸– ±Í 3<Å ?Eõd¨"Â;|øð¼yó®\¹rïÞ½£GnÚ´©OŸ> òĘNO)†#¾ ñ½ùCÕ?•?4ð­JSyvaadffnݺuذa®®®:u;vì‘#GŠä¼¡hªHuqqiÓ¦——×Úµk333å«Eûsåœe\\\Úµk×·oß/¿üòÅ‹ÚçÍÍÍŽŽO®Ôò-~‹¼X€† "Ã9Ÿ6mÚ×_=cÆŒŒŒ [[Ûþýû3!qNºÈϽéÕÇZè ‹ŽÆÛ H¶mÛ666ÖÚÚZÇ_±–Ò æÙ³g“&MÊÌÌô÷÷oÚ´é«W¯80{öì©S§Ž1¢0åKýõ-[¶Ô¬Y“ˆ²²²~ûí7‘9wî\]–]|Ä‹ŒŒ…Qffæ¥K—V¯^ý÷ß/[¶L˼IIIË–-suuµ´´”ª+’õ¦²Œ†Q€aŒU©R%00°´b ôÿ€­ÿ-­rrrŽ9²cÇŽððp•þznn®ô‘ô¾úíÌÍÍŵþ:R醎;vðàÁ]ºt‘nĬþ‘‰‰‰–Û!„††þóÏ?Û¶m“nõ6eÊ”ìììo¾ù¦G¶¶¶yÍ«¹|YP*½imm-%=ÚÙÙ=zôhåÊ•3gÎ,_¾|¾Ë.-¯µµµô¾½½ýÓ§OW¬X1wî\é¾pêórYcÞvUëgd Ì@”]èpÃé`qÎÓÒÒ6mÚÔ¯_¿àà`•g´§¥¥EDDHIïŸ___ùÝŸ9ç£FZ¿~½Ô•×8¯.åK¯å·@UÌÍÍ•gåææ~ûí·½zõruu3fLDD„z–”JâÉ6J¥R<~~ÕªUýúõk×®]§NÆwöìY"š1cç¼OŸ>ÎÎÎ*Õ…‡‡÷íÛ·]»v|ðATT”(VË· ± Œ@™±ÝDJ@`y_×®]Û¹sç/¿üÒ°aCOOOé†Âׯ_WùH~°°°°Ù³g;99?~|õêÕœs___•·oß>wîÜ *,[¶,00pÿþý …båÊ•G7o^ãÆããã¥ç3ƦM›æïï»{÷îððð^½z‰'B2ƦNªþQ“&Mäô7ndggKÏ/—Þ·¶¶œÏKžå1Ù4ÒôRù¿ÿþû¶mÛüüüä÷\&¢5kÖìÛ·/00ÐÁÁA¾Œ*•Š¢”JåùóçÃÃÃÛ¶m+â™ Ü¿ñâÅvvv? ùä“Oâââ/^¼páÂmÛ¶ÙØØ\¹rE*jÕªU‡š7ožƒƒCbbbpppVVÖàÁƒµ| yU¡e-D:г ŽACèJ–Ã]Ò Lõû >|¸½½ýºu뜜œäï3ƤTF„É“'{zz2Æ tûöímÛ¶©G'NO4hЂ ÒÓÓMMMcbbæÍ›çææÆ6lØ;wăJDWÛÜÜÜÛÛÛÛÛûüùó .üé§ŸNŸ>-=,ÒÛÛ»_¿~.\9sFªKœÿ&" ‹dÂh(?&挦GÎTeffV®\ÙÍÍí£>‰kšˆ¨F¾¾¾sæÌIKK«R¥ YYYU«VM**--m÷îÝóæÍóðð "__ß;wîDFFJQú·`mm-ªa•­­­TÅÛ®7ý„¨ Ÿ~÷ á­é}l0~üø={ö0 ÿþVVVÒ9l•Äév©sììì,Méèèøã?fdd¨þÎ;ïˆiÄ)𜜜[·nåææ¶hÑBš·eË–òÇrÎÓÓÓ£££÷ìÙ“=~üx•t&ùG*cVVVD”‘‘‘︜s777éÏ„„1ýåß¿¯R¾xR£F "ÊÊÊúõ×_׬Y( ¸~ýzvv¶“““´D­ZÂM.™ IDATµR‰ D!¹¹¹ÉÉÉaaa®®®Ÿ}ö™HF""__ßcÇŽ%%¥E‹ò÷?~èïïÿþûïK Ï)—üú믪四«”/^ØÙÙÕªUK¼nԨѫW¯‚ƒƒ_¼x!M™››«²ŒêùúvvvöööŒ±úõëשSgúôéYYY+V¬³Ü»w¯GÎÎÎ|ôèÑüùóóú¥®¼„ˆê E^ßÂÛV`p€aÒ¿žbAàz•|ékl`nnîåååååuöìÙ;vŒ9òÔ©SRÒŽ——Wß¾}Ï;'}$æJMM­W¯qÎ/\¸P§Nù5¾•sö7633;{ölƒ ļ©©©Ò§~~~îîîaaaR÷]*Dú¨U«VÇcåÊ•ëÓ§Ï®]»|||¤;ùˆàÂ… 5jÔŸû¯S§Ž|vÕòÕ¶g×pÎ+W®¬Òž&Mš˜šš¦¤¤h\Fõ]]]Ö®]ãããsñâÅ .DFF6oÞ\L³aÃ+Shذ!c,%%¥~ýúâ[KII©Zµª………ÆÆ‘T…È,âœoܸQ½dÃ…¨@7†rxc g½C( òØ@Ͼzggç÷ßÿþýûê·ܺwïžôfXX˜……E£Fâãã÷ìÙ³hÑ"eªœ&·°°6lغuë,--[´hqâÄ ‘>$ÄÄÄØÙÙ©÷}9ç111öööÚÛÏ›4iÒ™3gÆ7~üøfÍšeddìÝ»wÇŽÓ¦M«U«––{å[¾´ iiiÒÙOž<ÙµkW×®]åWZ8pݺuVVVÒ2ªÔ.-FŽyâĉÐÐÐŽ;Š{%íÛ·¯J•*œóøøx1¬ñòåKQï¥K—äåT«V­oß¾aaa–––M›6=qâÄîÝ»§Nª±ñÒ,yU¡u D`89)6 ýÚ cZ:ÇöööRÿrܸq!!!÷îÝ«W¯ÞÒ¥K»wïžW*ïLž<¹R¥J!!!iiiÍ›7÷÷÷IùZªÖÞ*9KKˈˆˆÍ›7¯Y³æþýûfffM›6]¹r¥¸ð7¯¹t)_šÝÏÏOüijjjkkëîî>a•‰§OŸ^©R%ñ€³wß}×ÏÏ/<<\~'yⶤ ,6lØòåËW­Zmeeåîî1tèÐÔÔÔ®]»vèÐaáÂ…D4sæL©¨9sæØØØ¬\¹2--­N:³gÏöññÑX—P·nݼª°´´Ô¾ ‚†¼=Ð/úwbì zÞ¼¢eT «‡ô¯/XŠu£*Û[l™ÜŒçüÔ©S5’ž°sçÎÐÐÐcÇŽ)вù¤0Cü…b›AgxŠè=)oG#`{([c‡ž7oÞ•+WîÝ»wôèÑM›6õéӧ̆úczOÏãr=o^‘3¶å-ueû|pqoNØ\Ápˆ''|ýõ× ¶¶¶½{÷3fŒJQ™bˆ¿PCl3è QÞÓó_ ž7@Ÿ!*(rF¸È`¸ qs5Ä6ƒÎAPFá3¹Å"ÛR܃Ê}½O€žÃXºPTpŠЏUÉÀJ.@AÏ`¬JNëB1Á¸€Î@é1æî.Ú+1ˆ t€ "€·„±ò¢‚^Z 0 Žó‚œ¢b‚ø ¬ÀX”8ÄPZ0nDoIœnD¢`Ð} ÅØ^CÆâAG"sCdqèlŠ…‡Èª0p=ƒ¨Š†ô2ˆ 8!Ш$ϰ"çMwØ\Àˆ!*(t³t„µ¤V‹~µÈo»A€²DoB€2 ÷0£„¨ŠzQPf 6#ƒ "("è<é-ŒnrŠò‚ô!€2QúLP¶!6#€ "€©€§€ñbüö ,ÂXΛR/ —J``´ß#¶a€²Q¼=#ï £=wn´ NF¼ìØïAÙ…¨ÞâЈǗv Šs/í#\WPPÆvi.!0tFµ¹À[ÂXäãe¢(NÆpnÒ–Q(ÃKŠ€Œ¢(fÈ6=W‰¸y è%\W`ŒíJxˆ Œ¢(äB  g;DÆQ@I)õá‚cÈ¢c‡¨ÀØ!*€ÂA6¨áœÇÆ&{z~Zµª—™Y×5|¼¼æ;v±e*Œ¹3æ®Px˜›w¯Y³ÿèÑË32žóüò²Ä¼ …ÇéÓW Ó†ÂÓ½%bIOŸ¾Ê9¯¥e/_¾{ݺƒ'Mú*-í)ç¼d–N¥ ææÝëÖüñÇk_¼È,Â6äæ*#"~¹qã¯X®Òß*p=ƒg™b¾¼s¾xñÖE‹6Q«Vmm­SR~ß¿ÿ?±±ÉÛ·/üෂ˽ww'KËJÏ“’.oÙr0-íiLÌ2çÍc¥×cŒy{w "kë*ZZ¢ò‘xݹsK+«ÊDôòe扩ë×ï½sçѾ}_‘.eLbbJÇŽ-TÚÀ9ñ"óĉÔÝééÏ""fI8ç­ZKM½uêÔ7¢„â[.RÛ*Ž¿Ô±c‹RÜ6JË÷ ”²R¿ý¥¨:ÓêµùVáââ`bÒ¥yózãÇ{ÑÝʪ²æÚ‹vw¡';„·bˆm!ƒ ¤ÇÑ44tM›öAÏž­cŒ±råLCC§8œœ¼^„‰‰)Ó+Uò´´ìÓ»÷ì³g¯‹y¥¤Ž~8Ü©ÓÔ z4kæ·o_½>³+Îd‰=z¸ˆ¦‰/ÞìÛ÷3 ‹Þ+öìØqʧÄôòy½½ç)3f„‰³³sjÔðQ(<þïÿÎj©]TšWùô:ÁæûïÿÏÍmZ… =Çœ?cùòìí?¨TÉÓÛ{Þÿ›.ŸR¤åæ*ƒ‚¶4l8Ì̬k¥JžmÚÄÆ&‹¦ŠU÷z–_‹ÿ9çNNÄdgH)Fòt#•EÚ¹eËA‡*ôps›öã‡ÅòÊO™'&¦øù}Q»öÀ3Â._þ£Y³º*í‘ÚðâÅ+"jÒä×ïÿ¯ œs•ŠÄ§¢–¼–Zš M›“.*Ë¥ËúW_ê¼V²ÊVAD-Z4¸|ùéÓ×Ô®=hìØ'O^.‚€AAT% ÙÆ…o‰ü0©Ë”…Ï–¯añOžÖœï¼R¢ðÛ¶¿`Š»|ÈWRR*uéò¾¼S[½º•§g[[k"JHHéÖmfBBJ«VœœÅÅîÜyÚ¥K¿“¬£6iÒ— …ÂÆÆòêÕÛÇ/}þü•JÇ”1w†1fb¢¨Uˆˆ.^¼Ù¾ýäN5h`׺uÓ¤¤Ë^^s~üñˆJ§vìØ>D´cÇÑÜ\%çüðásgÔ­kÛ¥Ëûô:ÞÐX».å¬655±´¬”šz«K—K–lmÞ¼žR©Ü·/iÑ¢Hõî~hèž  ÈÇ3zöl]§N3g® 0ÿŸ^H-“ÉÃ!¥’gd<_¹r;cÌÒ²RãÆµH6H¯UAüêwîŒ=zù995zù23 àK©ID²»E‹ÑnnÓ¶n=X½ºÕ¬YCÏÛxéÒfQ ˜rÖ¬õýûöïصëÇ&¬ª_ßnÓ¦Yê˵k×±Q£¾¸~ýŽT‘¼¼–Úǧ£˜ÝÝÝIäÉËÔeý«/u^+Y ä[ÔÅ‹›ÎÛ8s¦¯µuåÈÈØ¦89 ‹.¦Ÿ €BT%‡s¾xñÖ^½fÞ³'¡ÀÅʳûõkß¾}ó´´g[¶ôóû<ßh•³nCá‰lcoï"ƒ6¯ÉÔÏØ©KLL‘&ÝÝ||:öë×¾sç–g„„ìž2%D|¤KôæöñéèãÓÑÝÝéɓ֯ß;räçùÎÛªÕ¸qãV¤§?­%X[W)Žô•®IbbJ‘WQ󦞞þŒˆ,-+‰o|âÄ/å!åéÓW-ÚœþéñãaÇŽ}½iÓì/2?ÿ|›|»>}`||È¡C«9çOŸ¾øý÷{ôºs,:¦îî ´ˆ>ø ³%clöìo_¾Ìôóëyþ|x||HHÈTÎùÌ™kss•$ëX÷îݶV-›ž9rŽˆvíŠ'"?¿žb«ÑR».åÏš5ôðá/¿ýö"ÊÈx¾cǸ¸U³f %¢ ~“÷ŒÅºrqqX¾ÜÿСÕûö}‘JD¯^eýñÇRëèQ›6 …‡‰‰‡µußE‹6›™™††~T¡‚¹J™âµ´DôìÙK±«Wï ¢©Sœ<¹îôéo‡ ë*oÒǯ½råϺumùeÅ­[Ûƒƒý[µj, ˆññbbŽÇÄ?zô|vvNnnî­[Ô—kõꌱiÓ>HJZ›œ¼~ذ®ò/7¯¥ŽŠZ"&X±" :z©J™º¬K­RçüåËL±’UöÿNNV¬øóÏ{÷~^§N‹oNúu‘ÿ@ô¢(9GŽœ Š,_¾Ü/¿¬8{vÃÁ¿ÿþãàÁ¹¹Ê?^«T°§"iV¬ˆ‰YvôhÈ®]AD´woÒƒOtœ—òîd—˜èè¥ÑÑK5ª¥¥%Z˜'Ož†„ì~ï½Q;$?H¯Xµ$&fY\ܪ͛?#¢;Šyu©‘Þ\Ãb–_~Yqðà*ÎùÏ?Ÿ¼ÿ‰ö0&5õ–ÔxƘTéÛ¬]©t#:wþ¨E‹Ñ¡¡QùŽi@²±±$¢GÒÅ7îèØP„‚Òo-9ùW"3&XÄ £F}AD )òí¶Kg"'c,33›^ÿHãã/üôÓ‰¤¤Ë66–ý¤sÕ"9²§˜eôhO"zø0MŒSIµ›˜(FîEDÛ·ÉÊʉŽNdŒé™oíº”ïáÑŠˆì쪉rºv}Ÿˆlm«QVV¶¼g,féÔÉÑѱÁ?rs›V¿þ1AVV6©‘»»“»»S¹rfŒ±-\¹²eäȤ ‹×Ò"ˆrÄ"ˆ™ÜÄ›¾¾ò&uîÜ’ˆnß~4tè≿”Õìõ©ääõJåÑœœ#Æ|úéÛ·üòe¦J¤ŠÄ›¾¾Òê%"]–Ze]é¸þ5.uÇŽ-äÕ‰)Eu*ûÎùþseÚ´ÐQ£¾øóχbú`0@ÉA¶qÑfK‡±âÎVEcNNDùgPÞ‰Â"9˜sÞ¦Mcî\-mI}Õåûk©N¥Ñ¢EƒÔÔ[}Z»ö 1c‚Ož¼¬%€¢Ò©“#ÅÆþû+˜8Ñ[„‚ÒV$NtîÜRD >>½½;tèðžü¬P¡cÌÔÔ„¿F¯7¿ääõ¹¹G²²þïîÝÝëÖͨ\¹‚˜EºˆYšC*ÞìdÝ‹1•°wï‰ôôg;·lÐÀŽdÝkµëR¾¹¹1öow³|ùr$»ÿ¤<ð³LŸ¾¦wïÙII—}}=þJ½s/½bEÀ‘#_ÅLJT¬hžšzkÖ¬õbM2Mc*”#"…¼;.‘ï¤O ¹reËŒƒLL7þܹóG RM|bŒ™˜(ªW·\¸pç<=ýÙÍ›ÿÉQÙä +­+]–Ze]é¸þ5.õŒaòêÔוx´ÅÁaDûö“×­‹!¢3ýúëÖ#G¾Òa“(#@ÉA¶qÑfsÎK,X>¥RÉÓÓŸ­\¹ˆ,,*Š´æ¼ìíÝAÌ+²TÚáÂoê«î‡çûë˜}áBøùóáŸ|2ØÚºòæÍ¿´o?¹U«q¥–(\ÚƒQ%fêÔD¾?**Q|¹¹Ê ~–¶"gç&DäéÙ6*jITÔ’#z::6>¼»z§™k: NšFö8çmÚ¼KDß}'&‹ŒŒeŒÕªeÓ¸qm•yë×·ëÖÍ9#ãùǯ%"??O®vš@½vË—Ú£2»Æ7ÃÃ÷Ñ¢E£§LéÏÿçËg¯Ûµk¶açœó¨¨„ÝÚ×’JÇÚÉ©EE%ˆ7¿ÿþ4»˜ iÓ:«VM¼sg×–-s:vlñÛow-ŠTÿ^Dá·o?U«f¡²¤ŠÄ›ßH^ˆ–¥%ˆpÁÖ¿úR«T÷zRisPPäo¿ÝíÐá½ÈÈ9wîìúòËÉM›ÖQßÒÊ2zNÏ¿#íÍ#â<^úgjjÂ;yrRyT©<ÐO¾)&'¯÷ðhÅ‹ˆ˜-¦ŒœÃ2¤‹˜^ì¾.ôS*þúëV1WJJ„¸k½Îzïܹ¥a÷õõåôèÑš16j”§(ç믧1ÆjÖ¬š}Xš79y}vöáÚµ«3ÆââV)•GÇŒé-U§½v]Ê_¼xŒRy4&f™(gß¾/”Ê£ ø1ÆÚ·O´Sj‰Ry4!!488àÔ©õJåÑGbÄ\.l’Z"&¯EpnîQùÚŸªÿäëֵݳg‰zmڼ˛6í•oG>¥c¬\9³-[æŠéU,¦ –×¢Ò~iÕ‰ZTV–u®Ëú‘¯œœ#ûö}Q·®íëÁÿ>*¡Ÿ˜žÿ éÍ_ºRytñâ1âûjÙ²aïÞíÄ/‹1fgWíÏ?w8,Îæº¸8tíú¾Ø3¬_?Se QßJå¯ßøy<çñIIkÍÍÍc-[6ìܹ¥B¡01QìܹH½¥ò莋Ä;•ž=‹•ÿjòª]÷ò““׋rD]ëÖÍ «>å»ïÖeŒU¯nÕ£Gë ÌÅj9xp•Æ_ºÔ*¥òèøñ}c+–¿zõ;•5£åµD|êêÚüý÷›T¬X^j§úúT*¦¦F~ôÑòr¤‹‹zõj+.çèÕ«­úrIWHÉ÷'Z–ÚÖÖš1Ö¢Eƒöíß{þü`ÁÖ¿ÊRk©N>×”)ý/^ŒP_Ÿ»0ÄÝ‚!¶t†±(9È6.òlã’É–¦”§5¿÷^ý+W¶Œñïù]3wÙ›çð¤U'Þ=Ú“sþàÁ±êòZç:®©–“'/‹DáÛ·I+ Šc,0pÄ¡C«ûõëpïÞ߇ÉÊÊéÖÍ9$dêµkß½óNuOÏ6û÷»¹9^»v'1ñRóæõ""fO˜ÐWe Qù]Ö±"rum~üx˜—Wû;wþ›œ|µ}ûæ¬4ÈÔ® bŒy{wZ__÷J•ÊKåçU»èàêR¾ Þxo~÷Ý<‡ŒŒç©©·.5`€%&^¤<Æ øëóô!!S›7¯÷òeæ˜1ÁJ¥®c>>#"f7lhþü +«Ê7~J¯óm4~Í›× ™*/G\müÓO':“›«ôõuߺu®úºê߿ӦM³4°“*b²Œ,-KP»võk×îך59:6Ègã(Óðlc(9:9îÞ},6ö”——+clâDéõckH–mlm]EšËÌÌT:‘<ß—^#¥î¯ÆßȳQ‰Hd£JJG"=º×²eÛ¢¢<=Û¤§?sww’gçU».å˳‰H=ÛXÞÎùŒa¡¡Q..#FôXµj’«ë$©‘òcÿÑ£!W¯ÞÞ¸ñç-[b7nüyãÆŸ6´ÿðÃî ø©LibÂDðÊ•ÛEpóæõäË.‘7C¥m+V¸¸8üç?WºwŸ)Òšwí "ú7sWÞàví&j/På«y] Éû|y­s×mùþûC¿ýv—ˆªV­2}úÀ ¼š6­£¾Ôƨ8ŸFÄëÖ͹[7ç¼&èÙ³µxÀ™:•±)é„®Êk\\~úIÃsŽcòy9ç÷ïÿýôé z>$m6Zj×½üÖ­›ÊË‘öuêe:;7IN^¯qYä%¨×U¬h~éÒfeª´Yš—sûèQúW_MñòjODâæo5kV•¯¼h3”“×»yó/¢¢¾}]‰(**QTÄ^§åµÔ~~=ýüzæµ,:®•Öj©.ß- À¨`¬J²5ήñM]²Åÿ%“¬rÆnÆO‰(::1$d·øHKæ®B¡`Œåæ*ÕÏáI«N¼KDööÕĪӲÎuÌÆ^´hóµoß|óæÏîÜÙµzõ$„püø¥!C·o?9++§M›¦:¼—o‡¸l{€9s6øøzxLïÞ}æÈ‘ŸÑ AîE»8çRE]ºÌèÑã©"g"@O`¬JNÇŽ-‚‚F/X1pà‚–-ÖªU=%åæÝ»‰¨fͪ¶¶UçÎýÐËkÎܹ÷ì9fiY騱‹¹¹Êo¾ùXå³ú9~ùÙh•ÃclÙ²qÓ##cÏ»neU91ñ’BÁ¾újЉ‰‚ÔÎdÛ'.îô_ý×¢ÒÀ¥º´Ô®cùyÍ®ñÍ:ul¯^½=jÔ­Z5NLL11Qˆk|Õ׃xQ¡‚ùˆ=>ü°û•+nܸO¾ÆfÍZoeU™ˆ23³Å<=ÛØÙUS©ñÓO‡|ðÁ‚5k¢NŸ¾š™™}õêm#*bU Ö5>þ|xøþùó7õéÓ®I“Ú* V(˜ÔàêÕ-=JŸ0aU•*Z-ÿ‚òZub AË:×eýÑ”)ýÇ÷jÑ¢¾‘tû _œs33ÓŸ>É9ïÖÍù›o>6žmƒs>g·ÙÙ9»v;yò2çT»võÁƒ=æÏ©ËXîcyUd™‡¼ÐF›ADE×0üÒÁH”ÀîBÏéíÞ Š®60vˆ Œ¢€â¤Ïîâ‚cDðÿìÝg\G𙣣H±aWP‘^ŒØÅ{AQ°—Ä+XP,‘ lØKì-6°G všÄ^£`¸ÛçÅÄ}Ö½ã8úq÷û~xql™™Ùÿm9DºQ n?È   að{:¬°~ËŒúBf ä *(Jû¨q!Ò…}Ðv¸ƒ@×!*Ðu”Õ_ §É/;'¹eRA© É‡h+ ß•*yµá¹(JZßwèBÿȇvZ¿§: wŒÖ_áƒJµgt¢€ÓúsepÜo±Dx >”ˆ ò‹¿}ˆ+k7~Yl  »\pºpƒh D…ÿ]‹‰"œïhD#ú]»ƒ\i}h¤ÅPqº ï (T,0ÐÖïÑsÝ;6 —J\+È'ÇÚ}Å@½ãŸ= O'” ˆ LñD¿$€ÒQ@Ñ@` Zá€ÃsEF»o©ÏßÂåù§´µR©{¼D»‰€ÜàZ@Þ)žyòä\·Â'N)]»v-K„òéÓ§Ë—//Z´èßÿ3gŽŠuO:5gÎ777ssó¼¶^un (*xyQaÀøˆñã£úŠt|ĵ‚‚â8.;;ûàÁƒƒ Rœ«t–blgdddmm­§§§f‹ÝAƒš5¿Š¥¥eùòå­­­+Uªäìì|âĉwïީȳb"ŃRÊW´ŠeøÏ¢ÚTlKü¾W®\ÙËË+88xçΟ>}Êu+ÂÄ---­?«R¥J›6m† rðàAÕeȯ.Ü©B,O5[xÉÀ ˆ@ÿø®`|Ì=}‰ã#Áø˜E:>"*(W¯^ÅÇÇDEE999ñUÂqÜ«W¯V¯^ÍÏâW9}útïÞ½ÝÜܺuë¶uëV6‘¿Ä>ìÝ»·OŸ>nnn½{÷>ofÆ–ÉÎÎ^ºtiëÖ­ÝÜ܆ öÏ?ÿði:99EEE¬Y³&==ŸN)ågÅÇdzëYŠ{ñîÝ»]»võìÙ³L™2|k£”ÅÅÅ•/_>§¦F)u:p ×ô³²²6oÞܳgÏ*UªˆZóŒ3¢££ÙQ$“ÉV¬XÑ©S'WW×.]ºlذA.—óà¾(“óç•v^ì$ŸK™L¶jÕªŽ;ººº~ýõ× äËÃiñâÅmÚ´‘Édì_¹\°bÅ ¥[dË(M“¯Á]»v±KÌGŽIIIéÕ«[òôéÓ¢k—oß¾]¸pa@@€«««——WHHHjjªâ~©hK¢}766f9nE&“-_¾¼]»vnnnŒgÖ…‰ˆ6*‘H8Žc…¯4“„±cÇrסC©T*ÚœŠòQ¬DuÊäÜÂ4ƒϊc|üÜ3kèø¨FúY”–²ñÑÜã£6äË7fÎœéææÖ¯_¿¤¤¤?²V¢t›~üøq©Têãã³wïÞGmݺµE‹›7o–ËålÖƒ؇þýû_ºtéÖ­[AAAm7ÎÎΖËå‘‘‘þþþÇŽ{øðá¦M›Z´h!•J?~,—ËårùÇ“’’úõëçææ6sæÌ7nðùQœ%ܹ\þÇH¥ÒË—/ç§ É5ý«W¯J¥Ò .¨Niîܹ]»v=uêÔãÇ<زe˸¸8¾p¾(“6m²³³ùBã÷ôæÍ›Ý»w:t(+“yóæ}õÕWGŽyøðáæÍ›]\\~ùåaiß¾}›´lù³gÏ:;;?~ü8§-æšf=Ο?ÿ÷ß2ÄËË«_¿~/^üûᅦêïï/Êóرc{÷îýÇ>x€ñ±ˆÆGê§ —T*íÔ©ÓüÁ7;F.—ó³DÓY-nݺ•Ÿ²páÂŽ;*öz§NbËìÙ³GÚ¬Ù‹/ÒÓÓ]\\vìØÁ¯;oÞ<Ö|E[¹páB§N¤R©bžùY¢<§¤¤H¥Ò»w«E0Ôå”þ‰'Dé/\¸ÐSàéÓ§/^¼hÞ¼ùï¿ÿÎ/³iÓ&OOO¾õQ&Ré‹/Øt–ˆ«««‹‹Ë¨Q£ž>}*—Ëÿý÷_ggçÄÄD¾d,XЦMQ§§NbåÃiîåð¹SæÓTÑ¡èÒÉnAéLlP|ã£TªÑã£éŸ(W®”ææ%?>>x€ñ±ˆÆGQF&“………=zô¨uëÖR©´{÷îÏž=›6mšh]ÕmI¸ï?~ŒŠŠzÿþ½p+|>Ùîp ç%¶¶¶•+W¦”Ö¨QÃÞÞ~̘1™™™óçÏW3“B¹–(Ç©¹ ¥-<§l”2Z÷ü:ÆGöï7rM¿Îû÷E0>’’ä¥ÔÈȨS§N;v¼pá–-[Ï;Çæ²Y:uJMMe³Îž=Ëf]¹r¥Zµj¬ ¦¥¥ÙÛÛ³¸PDÔ:k×®m``ššZ£F ¶î•+Wø¹ ðõõ]ºt)ß=ñ‰ð³š5k–Ó¾uèÐaÛ¶m]ºt155vpiii+VäÓ¤” ¿/á8n@ݺ¾ïÞåš~¯^½6mÚÔºuk[[[aj?fŸÙ·OžÇa|Qg\`û…ñ‘öøˆ¨  (¥R©T*•>zôHñð“J¥Íš5ãmBÈÒ¥KË•+çààpìØ±íÛ· jQ²ÂË•+×·oßeË–™››7nÜøäÉ“ìò(“””T¹re¥‰$%% ;¥8Ž6lØùóçCBBÜ AƒŒŒŒ;wnÙ²eÔ¨Qvvv*ö=éêUÛÔÔ\ÓÂãmOûhp—¢||Ôà ç ÆG¥p­t×›7oRSSOž<Éq\»ví”~§RªQJ>¼fÍšQ£FYZZÞ¼ysõêÕ:tÐå. Ÿ¶œ%h(áÕíº€š ã£nµ§á#®†g/gǽ~ýºcÇŽ3fÌJ¥šØøZÁÛ·oüñÇää䌌ŒJ•*µoß~àÀ¢+¤¥¶Á-KqBik¬MUã£Ff80>*…¨@ãiø¨áÙÓ(aÍºÈ J JݱSê2 y;ˆJ9Ü\†¨ ”ÓÒ—@qBT ÙØ/a€u <€üBTƒØU!<€{ö'–Hµ4F´#))—XÛSº$ß2!Wº “R“Âí¤Ø\ ö*r’×Á^i½ð¨+ «WO jwÐÂVvíš«zݦMCبÀQs(ÊQùœ8q™o{Š„-4ÇáÃ""Ö$&ÎnÛÖ…òéSVPÐÜ-[ŽŽÛµ«!ùi9|Û˜??ÌÙ¹.!d×®Ó;OÞ±ãäÓ§¯*U²,ÈqWl(¥‰‰³s]L”Iöyþü0*swúô5á»wŸ~üø¥­­•:iªã¸W¯Þ®_`ÕªÝ׮ݕɎBŽù#"b­±±abâì6mšB23³…Õ*‘¨ÿç÷nçÎS]ºLÙ¹óÔ“'/ml¬ÔY—”tÿOQ§ T´Ã—/ßð.—%ŸCAÖÚÙ’[·ëÝ;bëÖ£«WOP³!e%¬Ø~Tœ!\¹ò7Ÿy5w3ßDÁ°Ïè† «Ü©KK3Ñ’*悈®ÜAÄwRûöÍOM]±woÔ_ýÒ«—ŸL&7.V.Ïçå'vQJçÏKJšsôhô¶m„ÖI©¹.ÑŒN*1q¶ƒC•\KvŠ.ؽ|ù&:ú×F‚||F³øÁ~ïÞ¨ VîÛ7_Xà'NAM|æÏKLœ}äÈâmÛ"8Žcƒ½ê4U俘±>š¸ŠÅrj!DZoÜ8ØÇg4Û)¾&&ÎNJšsàÀ‚5k&B¶n=Êf©³Eòe '$ÌJLœ½ÿ‚Böì9óèÑ¿ª×½|ù/a «Ó®òMX>„ŸÑŽŽcb^½z#ª_ŽãTÌ…B–—_8މÙN5êkBŒŒ bbFíÝuî\K&%咟ߘ2eÚš›whß~bjêŸ| ²[~þù°—×H“Ö  صë”ðˆ „°­[;³OŸ¾bÓ/^¼Ó±ã¤råÚ›š¶ñô±wïÙÏÙÿÿº]ºL•HüÆŽ]ÊÒÌÊÊ®X±‹Dâ÷Ûo©Çå´u–ŽŠôÙí›6ýæí=ÊĤµ£ãÀ?þ¸5oÞÏ•+]¦LÛΧ<ž.ºñƒÝž±®V­¾_•)ÓÖÅ%lÿþsäËž¥/<)¥Mš8°=zñ"ƒ"ºÝH"ñíŸÎºuêÖíobÒÚÛ{Ô/¿fû+¬¾””KAAóììº{íÚÝ ª± ñÕÚ¦Ms6ÅÐPŸ¯V(V«¨|s%êÃ9ŽkÝÚ™}`ý?ÇqŠÅΗ¿nçÎSXµ²-ŠªUu™ä”>ßUW«pIժ؆ÙÖSR. 0×ήûرK¯^ý§Aƒj9-ùþýGBH:U?OÿÿUÔ¬â(©Ø~rÊ0»^Íqœ‹K¥¾œÂmK¹JË\ò!„4n\óÊ•¿Gޱ³ë1p`ÔéÓW…G„й Æi+B8îÿàA)0¡\~”M‘Ë>{–´oßü'OÙ”ää_ß&¦¦ÆåÊ•i×®Åùó+ø%YãÛ´iš§gcccÃúõ«íÜÉæ²bÛ–“sçâø­''Ƕ111b)4lX-ɸ°øgË(¸(ç¢]Vš‡²)ii«ÙÅÕ£°ÀYš¢Ïiëj¦¯ºÀE{‘S+Ö ßJY³6¬žÓ’kÖL¢”6mZ[i¹­]û}:U ½¼þy››S-¿{w€¥ñb¼Š"ìXXj¢£#×¶ª´ÆÕ,GÇZ,禦ÆÁÁíNж=ÕsÿûË©?Ôâ~²ˆ¨(±/{fkksJéþý ø– ü“Ë?chh ‘H<<y{;ééIÊ”1¾t)^ØVÍÍËx{;ÙÙU ”š™™¾}»_±ííØI)ÕÓ“<¾C.?úÇ«LM)¥NNµ¼½(¥‰dÓ¦i¢vÅÖ²µ-Ÿ}D.?ºoß|Jiõê62Y.[W'ý²eMüüš² eMM[µ’RJ‡ ë¢ØÂøa8¥´\¹2:¸Ö«gO)511JOß#êO„Ÿe²£¯^ífù|ÿþ€¨dØg¥»°eK8›ëêÚÀÙ¹n¹re„½ÄâÅ#6¬Î¦ØÛWš0¡Ï… +ùZã«UÉQÆã¸c9U«p¯•æJÔ;©Y­¢žMuµªØº:é«®VÅþ_Eµ kŠ8›Â¸¨ÿôõmÒ¥‹g—.ž~~M ôk̖֬mQuÍæÚ~rÊp—.žl]– QþÕ9"”–¹šåÃ6ñÝw½ªT±fÓœj-Y2šo“*ææÒÿëí-…ÆtRÅÓIa°/ôÁ^õ0,ìŽE£‚â·l gË󣛫¸d^Gáà$Ê¿:m5¯£‚èèãû}6õû| T:7÷QCE>¨èëëQJOŸ^Æþ  ‚Û<΋óókJ)ŸÈÚÉÚµßSJ{÷n)l«3f Ë^¿¾žÕ,ëF„G„“¡¡¥´gO?–NëÖÍ)¥AAmY:?þ8ŠRjcc••uXØ®²²³ÖxðàB¹üèÀí)¥3f Èuëê¤?sæ@¹ü(¯é®]såò£Ó§ ”º»7R왓“c¢¢ÂΞ“Ë>{–ÄÖb_? Y¢€Rjhh°nÝdÅ4Ùg~Øòl\\êSJGúš­ ØKT«Viß¾ù¬ÛTZ­¢uù|òÕÊIÁªU˜C¥¹ö0ÂjeéðÅÎÒ;¿õœª5×­«“>_­,³ˆX IDATQµ*ö±¢jek±jU¬)¾ÀEã)Uvu®ZµJÛ·ÏRÜ¢:5«¢ý¨ÙEùWçˆPZæê”°4²³ìÚ5·ZµJl®¨eŠæ"*P¤½¥Ã؃Nªx:) öE4Øç4 +íÊÙ¨ ¸E~TÖ|W¤˜¸Ï×+Ô즅ùW§­*-s5ˇo{|¿ÏæŠZ¦Š¹ˆ ÚQ¥tÇŽÿ® -[6–…µ|Í–)c¬Ø+W¶¶êãÇcäò£YY‡ÙÜß_.:960Я\ÙzèÐÎoÞìcÛeWÛŽYÌÒyýz/[òÚµu¢v5mZ ¥tàÀö?²´4“H$wîü’ëÖÕI?%e‰\~ôìÙ8– ¹ccÇRJë*ArùÑ}ûæýµ§gã2eŒ{cág_ß&¾¾MX÷ظqÍÛ·–+\£æsÂï[W¸ ÇŽýÈÖ:rd±°—ðõmÂÖµ°(;dH§ääá1ÈW+›ÂW+ŸO–QU¹²µ0‡Js%G„ÕÊrÅ;Kçõë½l]VìÂRRZ­¹n]ôùje鈪UÔ³t„ÕªX;쳯o¶_àŠý?ñùéÓ¤ñã{³…Y„û®ºfsm?ê´CÅ\©sD(–¹úåÖ'”R//GGÇš?ÿ|ÈÛ{T½Ù™™YDpÇ*!„½»éÞ½g}úÌ:ô–†RÊ8[ÅѱVçÎl°g)œ;wã¸£Ø …AAs9ŽKN¾$Ì¿Ël"Ûeöùر´¤¤ÂÿÜ#ÿW l±àà¶Ç=yò’Ÿÿœ <×­«“>_à,Q ë”—§gca³XóõBaÃðÝ»OYŸ8q™Ü7)ìšÙ¨ðÝw½îÝ{6hPÔÇ™¢º»|ù/BH·nÞlbÏž~Âç>?¸,®][Øš­®N µ+5ÛªÒ2W§|èç»iÏœ¹6jTLPÐÜ»wŸ²½–’â\5:(BìÅ û÷ŸeU9thçÄÄÙ ³øš•Ë9J©ë±ÙŸ‡G#áqdbbHÑÓ“0DpܱÌÌß>üuÙ²±eËšÿîcþÿÉ%¥”ãþû@"°‚ƒÛQJ’wî<™žþÖÇÇ©F ›\·®NúFFä¿76±tŒ›Ur»´}û‰§N]íÙÓïðáÅÂ#ZñóüùaGŽ,>v,ÚÔÔèÊ•¿'Lˆã¿¦É>›˜RJõõõ¸Ï„u¤ô >rdñõëëÇë©§'Y±b—·÷¨:uú±×KPJùje+²jMLœÍ'ÅžåVkç΄›Pš+î¿á#N&;"¬V¶ _ìü|‚¢RR¬Öš5m‰ /UºuuÒç«•¥cllH?y"l9l•1c–«U±v؇£G£¯][7vl==ÉÊ•»}|F×®ýMDÄZQRJõô$*˜Ï˜Äq\zúÛ;w‰ö]uÍæÚ~Ôi‡Š-M#B±ÌÕ,BHDĺ:uúyxŒøé§„1cº_»¶îèÑh–sADW¢tRÅÜIa°/ôÁ^õ0,\ROOR±¢ÅŒA„ŒŒwlTn‘'ʹ0oŠ£ÿP¾š-D”+uÚªÒ2WsŠˆXW·nw÷áË–%BÆŽíqýúzö5!$§¹Š‚ÚÙ²jÕžíÛ“Ù™L¾rå¾f¥Ò:„¶m[°»ÿ6ŽŽµ¾ùÆ_t)¶7Q-D)uq©OÙ°á [líÚý„Ê•Ë×®mG¾<îªW·iÕJš‘ñnܸXBÈ€mù«bëꧯtu¥W­ÚC 1¢+÷ÿs¸ÿ/,\‘}psk¸bÅxBHbbJtô¯ªKIÔ/5iâ@IHHf7m:$<*)¥õêÙ/Z4ìþýmë×Oöòr¼sçQDÄ:–_­ )lŠL&_±b7Ÿ>_­ ³fñÕ*Ê¡b®„{'ªVŽãøbg‹­]»ŸRZ¥Š5+váº5jØŠª•ß/[W3}aÙæ:QT­|÷¨Ø†ëÕ³_¸pèýûÛÖ­ûÞÓ³ñíÛÃÃ×*–Ëɽ{OÙ¬òåˉò¦¢fE­ZiûQÑ% ¥T&“çûˆÈ_ùBÂÃ×ܺõÀݽáš5“îßß¶hѰzõìù6£b.ˆèJT€NJéêJ'J'…Á^éêJ'ª3س*†aQ;ä8îÞ½§l„[äG6qÓ¦CÂD„Kºº6X±b<Çq ÉÑÑ¿²Y*ZÛºL&Ïw[Í_ùB""ÖÞ¾ýÐãÑÚµßß¿¿í‡†³‡È1CŽs¡yy9FDggËzô˜Ñ¤É &U¯Þ+4t!!ÄÖ¶|¥JV“'÷“HèäÉ+›7mÕj\¯^á³f­òäe{æ9sB õ×®Ýß´iˆŸß˜±c—J$tñâ,vµÆAƒ:B>|affÚ½»§FϬfú|~85zf{ûJ„  ¹mÛNhÙr,K*=ý-ùòèõ}û~Ò2mÚê›7ï«(%Ñq7~|oBÈ’% îîÃ¥Ò!¿ür„Ï’°0MLŒú÷oœsùòšQ£º±t<=GDgeewï>½iÓŽ¿¯^½WXØ"Bˆ•°Z]\Âüý¿å«U±7£yéÿùboÒd¯ïh¾ØÙ ¢ú4¨Çq„#º^¼Ÿ’²dÀ€ÿÞÆ!<”TÌ]‰ ÐI)]]éÄ‚wRƒ½ mä:QÁ^XeJ‡a¶ä„ q]»NíÚuj‡“¼½GQJÛµkÁ^ã-Üâøñ½9Ž‹‰Ùîá1ÂÙ9ô—_Ž•RŸ>-îH)6mõŸ>PÝBøQÁÓs䇙ùh«ù+BÈðá]ÒÒVŸ8±”õû¢#QÅ\(YÓ¦<¸°S'÷Gþ=tè|ff¶¿¿ó?Žºysƒ½}ÅvíZìÙåííxóæý””Ë VŸÚ‰äÖ7ªî™]]œ8±´S'÷û÷ŸŸ;wÃݽáÞ½óY¯«Ø;wö`¡uÏž¾¦¦FêôÌj¦ÏçG‰6Lqv®›‘ñîÊ•¿gÌêÖÍ›’’r‘|yt‹zHŽã¢£G6lXýÇOFÉÿ Øs¹V@)íÚÕkõê 5kÚþñÇ- ‹²+WާŸ/V+­Ç† «GGäó0ujÿC‡xðÕÚª•4:zäÍ›ªV­Ð¶­‹bµÒ± ý?!ÄÍ­¡b±÷èá«´¾:wö`oÅèÙÓ—¿a]ÅÖ)¥j¦/,Û\'ª¨VÕm˜¸°Äص;vœw"ÂuY'õ￯;)¥[ç;©\ÓÏ)óJ'nØ0eèÐ.^¼ÃÂÔÔ›¿þz<%墿¿T˜Q:|'ÅO™6-PTàþþάÀÍÌLíí+*xPP[¥%#ìUçu=¢ñ÷—*­G6س ö9m]ÍôsZ]éD®ºuñÎòÌF6K__ÏÌÌ´gOߥKÇ(n±KÏøø‰sæløã[îîV®߯ßlvv®X”Òèè‘§O_½zõŸ£’“cTd8**Œ}¥dgWáÕ«7ùh«ù.Ÿ%KF+OõÜѼýL/äO«VÒV­¤9ÍmÓ¦9û%,*xû-#|ì^é#øÂuëîØ¡ü·&Eë>~üï›7ï‰àŠb®['„¨™~óæõ„é ÚyèÐÎJ—”Jëœ;§4Aa ¢\QJMM._^£4MQž…ë®Y³ïÙ³ôÅ‹GtìèFIHH!„°Çˆ•æA„Rš¿jU+¹²—, åTì¢úâ8NX­Â.HÅÖÕO¿yózÂtDÕ*\REµªnÃyZRýšÍµý¨Èð€m h“S®Ô?â ½|@}”ÓÖ1RRªZ Çqwï>­W¯ffvrr »Ã¾¤3¥åþùç _àìwãuÇqk×îö,½Aƒj:¹B¶oOîÑcF•*Ö÷îmÕéVG}Å1¢‚‚PZz¥§gæ8îäÉ+K–$¤¤\zò䥋K½3g~*éLŽãfÎ\±ŽRêíí¨¯¯wêÔÕ>Ó}Ñ¢a¥½—8qâ²°ZOŸ^VÚ÷H}Ú]³¢Øÿë$]¹V áøN*33ÛÅ¥B‚"%ìYëNH@>?ˆ&!=zø¢Õð(¥ú»wŸæ8®U+éO?S¼>©­(¥ßß/++{Û¶ã§O_å8bgW¡W/?öBÏ’Î]p'ªÖÒ¾Gy¢Å5 …× JÇqçÎÝhÙr,Çqžžúi\­Z•K:SZîìÙë¯YÓVw:DŽã²²d3g®Ý¶íøÝ»O„£û©µ’Î`ÉÁµ‚ÂUʯ€ÁµB¢€ÿ *(\ˆ  ´@T@Ñw@Nä_§îo™€&@T ë@ÑÀÅ€ÒQ€®CT ëè:D ðòÐ1ˆ t~Ig´—â/Sß’É ¨D9m}sn€¼âûCÅsYÈ”$€6Á­Õ´÷ZÖ´ZPz±_8F' ñð\€®CTð%|· ºQ€®CTE ¯Ðxˆ  (áv,€ÒQ€®CT ëàD “@c¿e Q€®CT ëè:DºQ€^@TDðÀ1€fCTÅ€CT ëè:DºQ€®CTð^’º Q!„Jñ’œ"‡¸ @S!*Ðuˆ  ár€FBTÅ÷hh*DºQ€®CT€€®CTňãðÀ1€BT ëè:DºQ€®CT:/ *fxà@ó *Ðuˆ t¢]‡¨@×!*‡G‹8Ð0ˆ  $ Ð$ˆ t¢]‡¨@×!*Ðuˆ @·áM8%… 1€£o ˆ Q”ü–€Æ@T ëè:DºQè*¼€à3DPrðÀ1€f@T ëè:DºQ€®CT: / Òxà@ *Ðuˆ t¢]‡¨t*@T% A@ICT ëè:DºQ€®CTº¿¤ ð%D ­”DºQèJñv|D 87”DºQ€®CT ëè:D Kð" ‡ŽJ¢]‡¨@×!*Ðuˆ t¢Ð$xà $ *äQ€®CT ë€ÎÀíC¥-(vú%Ò€œ¸cŸ§øß>%²uLÉu N4ŠŽ,€âE9ô¼¹¢ô‹st¢ÐxgƒVÃDºQ@à+Ð ˆ Ô€Û‡@«!*Ý€wÚ”:¨2€b„¨ pÖZQø÷Qh#D ð6=•äÇq?f.\¸¥Y³Á&&­ÍÌÚyyLHH)””e2ùªU{^¼È(xjÌ®]§$¿û÷Ÿ©ùÛlyJ}ù?##ÿêÕ{ûöíŽãØÿý8ùÙ¶í˜(}öçæ6L˜x1ü’†ÒJÌÛvq¢ Ptð ÇÅ¿m¬†/ßAÄqÜë×ï[·þîÇOááÁÍšÕ~ÿþÓ† zô˜úÝw½ ²)Jé¾}g† YئMsŽãhGDá9®:©ñËŸ=WµjöùãÇÌ3g®³ôéÓW7Nñ÷w~øð× ,ò‘C>ýää‡*ÂY††Â ¾ïªed¼Ë©¿ý¶gQo@£ *È3Jéĉq/_¾>~E¹r¦ìô12rpfföÔ©«zõò«Zµb¾ç8Ž?o.”Sa"êœÄó T¨`nccÅÿ[£†mzúÛ‘#üé§qff&¶¶å ˜kë/ÒWT(A‘PVVvBBÊÒ¥ ÉÉ1„¾ÍÍ˰æÎÂW¢]oïQ#FtëÖÍK__Ah7ÜA”goÞ¼_·îÀˆÝø€B)4©ï‘#Ñ•*Y‰nAÉΖ͜¹¾FÞFFþµk³hÑV¹œã8nçÎS‰ßÊ•»Y$¾¦lÙ¶W¯þ0™ã8{ûž”úr—ÓêìN›5i2ÈØØßÉiÐÑ£°-feeOž¼ÒÖ¶›‰IkÿooܸÇgfãÆC¶²±é:hÐüôô·¢Üætmã8‰D"—sr¹|÷îÓì&yÉäáákììºû{zŽ˜;w“â]LЧÚjÛîºuš6 16ö¯U«oBBÊž=gùׯxðày>)Žãž?OŸ3gc­Z}GŒˆvwoDyûö«D>$`Kò•Hqwo4bDt­Z}çÎý9Ǻ-€V@T †/ßAtéÒ_Ÿ>e¹¹5ÔV¨`áîÞÐÐP_t2=zô’Ÿ>÷í­[›"#Ï›·iæÌµ”Ò€÷°°€ñãºÿyrò¥Ù³7üøã¨† «¯_?™Rššºòѣ턥«óéÇÄl‹ûöüùeÊ÷ë7G&“³-ÆÇï]¾ü»ë××wèà6uêj¶ð­[ƒ‚æöèá{ëÖ¦_ùÛo©ß¿B´¢Ì³ÙÙ²cÇÒfÍZçïï,ßÀïîããD)µ·¯È¯Î61kÖ WׄaúF¾x‘¡¯¯·jÕžåË¿ p'„ŒýõíÛ–-ÛAyúô¥\ÎU®lmgWÁÞ¾âΑ”RÑ^ðgÉóÓ?~Ì47/Ó©“ûüùaŠ»©˜##ƒ%K–.Óµ«!dÔ¨n·o?ˆM®Õ¼y¨¨ôV®ß«—ÿo®û9ÄÇljзſt ‡±l„„tìÓgæ³g¯ll¬š5\½ºÍÁƒ == ÷‘¯D5H)5118°]ppÛ'.07>~Ÿ\~4§åAsáD¥{àÕPô䙵µ9!äß_×®m§zIJéÅ‹wd2yÇŽ“ø³O™LþñcæƒÏkÔ°111ܸqª‹KhåÊÖË–Uüî\Åêì_‡*l-ö~VVöµkÿdgË\]°Ó}J©‡Gc¸»7êÞÝ'4tÑ”)«Zµ’x|ýµwN× vïžW¥Šuv¶ìðá ß¿¢uëæ±±cML wS17nÜËÌÌöðhÄçÁËËIlß>«fM[á«<í{ƒÕØvË”1&„Ô¨aË–455"„dgË!Ó§._¾«_¿Ù¡¡!!¬­ÍY~øJtpÈ%´{þ<}Õª=qq;33³¦OÏÆÉ hDjøòD×055:}új‹õ…'”ýûÍ7³""zy5fÓ9Ž“Ëå„-[ÂëÔù"„°³«À–IM½)‘H?þ7-í¶——£hË*V¿zõoBˆDB•>OÌq„σÁµ¬§'Ùº5üÚµ»{÷ž9|85002>~ï ”^+¨V­R¶„zõìëÔ©Ú±ã¤OŸ²¶oŸ©X<Šy`gäÂ<(<ööÃ*áb¹î»žžD¸]JÅ·$QJÃÃ'Múfóæ#K–$Ìšµ¾OŸ¯†ïÚ´©_‰ìò¿õÇ_ò•xáÂ­ØØÄ͛ԯ_-""¸OŸ¯ q¼€vÂsyfbbÔ¿ëeË’Þ¼ù |¤õ‡¶œ}mÆŒ5l•›7ïܳ§_``${öWx¦Ë¯ÎÖup¨Â¯Îs;:Ö24Ô?~jÔ=zøèeeÉúõ›Ý¨Q z§§¿mÜ8xĈè ¦˜˜BΜ¹æêÚÀήBN«ó›ªZZ–3¦û”)«¬¬Ê¹º6Ø·ï,»}ˆR¶¬ÉªU{ärnܸžYYÙ;vœ¨WÏÞÒÒLéµaÊ”Òñã{ïÝ{fâÄå:¸)–‰(åË—:4`Ê”•ÖÖæMš8ìÛwvÙ²$Ñb/^d|Q±¢EXX@DÄ@BÈô髯^ýçÂ…•úúzÖÖæqqßví:µM—®]½Ú·o1`À\BÈ­[›rZ]¸ ÑF##‡˜›—?þ§gÏ^¹¸Ôš8q9!¤iS‡§FFntrdjjÔ²e³Ý»çI$ªÞAÄÿ«§'Y½zBÓ¦!Ç/8°½ânЦ,X0ÔÌÌtøðÅ/^dH¥u'Nì;kÖz#£ÿÿN™·÷(q1Sš‘±G8%¯û®$(>5ÁŸè—/_Ni%véâÉÖÊ=$€b€_8(Té !ðJE@®:ߨQ öcgÇ-[¶câĸŒŒ½zzÚuÓõÅW˜š_3kT"€†ÀÁ¨Õ´ë 4Çq¿þz¼oßY¿ÿ~㟞$%˜3gC``m ÞAZ× Ôq¼¤3Pú¤§¿0!nçΓ/_¾±³«Ð¿ëÉ“û‰~âM+ø”t 7øfK  ñã);ÿ£«˜‚)ùš‚¨@ˆ 'ˆ  $àöf(\ÔWëîè(NÚvét”>NkÔ‚p´Çé‚SÞÜð·^hœ¼AaÃD€Çr@+ *PÂqÐb”â·ÕVÒ¯‹Ò”)ìw»þÿB´Ï_–ëòÐXx£¥6AmQ_|k …‹rß…C^à×|¡Áy¤6AmáͤP¸ðfRíÆqÜÇ™ niÖl°‰Ik3³v^^#R %e™L¾jÕž/2 ž³k×)‰Äïþýgjþ¦[žR_þÏÈÈ¿zõ^ãÆÅ¾}ûã8¶Àß?Î_~¶m;&JŸý¹¹ &^ ¿¦´ m»ÿ½ƒ@ûàµË ÅÔ¾PÀqÜë×ï[·þîÇOááÁÍšÕ~ÿþÓ† zô˜úÝw½ ’ Jé¾}g† YئMsŽãh;^á9®:©ñËŸ=WµjöùãÇÌ3g®³ôéÓW7Nñ÷w~øð× ,ò‘C>ýää‡*ÂY††Â ¾ïªed¼Ë©¿ý¶g¡lQh/Üp¢MØM¨S€Üp—-KHXŸå× IDATHYº4!%e ¥tâĸ—/_Ÿ?¿¢\9Svú9833{êÔU½zùU­Z± ÛâÏ› åÄT˜ˆ:'ñü*˜ÛØXñÿÖ¨a›žþväÈúiœ™™‰­mùæÇÚú‹ôJP$”••Í*199†ÂW¢¹y¶ÀܹCøJ´³«àí=jĈnݺyéë뉊‘Ÿe` êÌwh‰çÏÓ##7ÕªÕwĈhw÷Fǽyó~ݺ#FtãCB¥tÒ¤¾GŽDWªd%º%;[6sæú5zù×®ýÍ¢E[årŽã¸;OI$~+Wîf‘@xøš²eÛ^½úO@ÀdŽãìí{RêË¥«³;m6n<Ô¤É cc'§AGþÁ¶˜••=yòJ[Ûn&&­ýý¿½q㟙5jdhØÊƦë AóÓÓߊr›ÓµŽã$‰\ÎÉåòÝ»O³›|TäA&“‡‡¯±³ënlìïé9bîÜMŠw1)žô«Ytl»ëÖhÚ4ÄØØ¿V­¾ ){öœqthdä_¿~àÁƒçù¤8Ž{þ<}Μ|%BÞ¾ýÀ*‘ Ø’|%BÜÝ]«Vß¹sÞÐE)ågEFnzñ"CùMG”"*(m~b5-ívHÈüjÕz%%¥„‡ß»·uÞ¼!„K—þúô)ËÍ­¡è¤¶B w÷†††ú¢“éÑ£—üü󡸸ooÝÚ9xÞ¼M3g®¥”¸‡…ŒÿÓýûÏ““/Íž½áÇG5lX}ýúÉ”ÒÔÔ•m'„(]O?&f{\Ü·çϯ(SƸ_¿92™œm1>~ïòåß]¿¾¾C·©SW³…oÝz4·Gß[·6ýúëÌß~Kýþû¢½ež}ÈΖ;–6kÖ:gái´Š})—s•+[ÛÙU°·¯¸sg$¥T´üYrãÆÁüô3ÍÍËtêä>~˜ân*æÁÈÈ`É’„¥KÇtíêE5ªÛíÛbc“„k5o**½•+Ç÷êåÇÿ›ë¾GFññq"„„†ôí;káÂa,!!ûô™ùìÙ++¾== ÷‘¯D5H)5118°]ppÛ'.07>~Ÿ\~”Íe³l—’rI4‹‡¨J|áûïW´nÝ<6v¬‰‰¡ân*æáÆ{™™Ùøü±zz’­[ï]»»wï™Ã‡S#ãã÷8°@鵂jÕ*Õ¨aK©WϾNª;Núô)kûö™Š%§˜vF.̃bÀco_Q1¬.–ë¾ëéI„Û¥T|K¥4<R¿~µˆˆà>}¾âoKMýS4ËÈè‹(ýW2Š“Øföï?×¶íx+«N_U¬Ø¥S§ï¿¨tá<‰‹ÛéâffÖÎÈÈßÁ¡ï¸q±/_¾QóM«ìí°¿ÿ~#ßofU‚:ésÇ¿³V"ñ32ò·±é‚ܰauJé½{OªÔ®mW»¶ÝéÓ×fÌXÃV¹yóþ¸q±ááÁ={úF²g…gºüêl]‡*üê<Ñ9·£c-CCýãÇÓØDJéÙ³×Ø¬ääKaa‹ª|÷]¯}ûæÇÄŒúí·TÑy£b„@)õ÷—Μ9011…=­XV¢<89Õ20Ð?}úªbDk)–yAö]¥Ï*15u_‰l"«Ä×¯ß Wç+‘âê:ôõëwû÷/8~yPP[##>Èág¥¦®`³÷Ž(½ƒˆã¸™3ׇ‡¯!„4mZ»R%ËK—þÚ³çÌþýç6ožñõ×ÞJRǬYëgÌX£§'qq©oiYöÂ…[ÑÑ¿¦¤\:u*Vô%¥¹¶Ú|l]u j¦Ïnh#„øú617/“‘ñîÔ©«ëÖxõêMRÒÕà×m®øQJ;wö „XZš©ÈIÉfòRêããäããôÏ?O؉ÇìÙ!ÇŽ¥y{œ>=ÈÙ¹îË—¯ãã÷.]šZ«VeáºU«VìßßÊ”UeÝÝ={}Ô¨{ôð50ÐËÊ’õë7»Q£&ôNOÛ¸qðˆÑ6L111"„œ9sÍÕµ]…œVfO¸EK˲cÆtŸ2e••U9W×ûöe·BÊ–5Yµj\Î×3++{ÇŽõêÙ[Zš)½V L™R:~|ï½{ÏLœ¸¼C7¥E$ü·|ùrC‡L™²ÒÚÚ¼I‡}ûÎ.[–$ZìÅ‹Œ'O^ŠÒa/ÿaò±ïŠ× „ÿúø8y{;Þ½û”MWQ‰ìÖ¦[·6U¯n£tgoÝÚT­Z¥\Nê(U9òGDÄZccÃÄÄÙmÚ4'„dffÍݲåè¸q±]»zI$ù<)_²$òë¯3Ù)éÛ·Z´ššúgJÊå–-›ª^½à§ÔªSP3}~ÖüùaÍ›×#„ìÜyªK—);wžzòä¥è³œÖ%EÿS¹JLœë2Â2 B}sý!3þÑÊÊìäÉØ¹s7Nš´üîݧ††úÍšÕÙ¾}&{¸Vˆã¸åË¿³·ß0yòʇ_T¬h12}úê«Wÿ¹pa¥¾¾žµµy\Ü·]»NmÓÆ¥kW¯öí[ 0—rëÖ¦œVnB´ÑÈÈ!ææeÇÿéÙ³W..õÃÃ&N\NiÚÔaãÆ©‘‘œ™šµlÙl÷îy¢³Ðœ~ß@OO²zõ„¦MC†_xð ­iSÛêÕÿÍü.]úñý÷?KLLÍÉÉíܹÅܹ£û÷ï*/ùôé n‹K™3gäL$"ΩE‹ÿûé§?DרÕ|ٲ푑‡ýõ¾©©I»v—,'ÒQÂgŸ½³ukì¹s74¨5gÎ(ñ½¼|GÇV'O^V4°s碆⎚””MŽŽ­ˆ(33»R¥>Dtñb˜]S"JM½­hB¿~NŠu—-Û~à@ò[o Y³fegçÔ«7ôáÃŒ#GVõìÙYGrÎó-ÿóÏç}úéþ3g®·hQÛ¶÷>º/#ãi¯^[¶¼#?’·"ß{é)uæ‰3 ÀDÞ\„¥]‰ŠãèѳíÛ7?vÆ9ß°á«9s6edÄÌ—ø3O-MMN¾BD=zt–ŸØ®YÓÚÛÛI¤‰‰©½z½˜˜Ú©SóŽ›9r¦{÷é—/ߦg—9çS¦|¬R©ll¬®_ÿõÿþoÙÓ§ÿpΧMÄ9ß·/ÑÑqR:ƒžèÐéV­J)ÁÅ‹?të656ötÓ¦u»tiœü½¯ï{_|qL^2MžìGDÛ·ÉÍUщúé[Û¸Qhè¾Å‹#>ÌèÛ·KƵΞ½1xð|q–(!(hun®ÚήÙ?ü>qâGÛ·Q”Ÿ”tY³W®ü$n/Ž9Ë32R‰›º.]úQ³ ;wW¬;~¼íÞ/¾%÷رóf4jT»GÎR=µö¡>å­666²²²¼rå§=f.]Ù®]cµZ}à@ò¢EŠšèÓcŵÿ”6ÎùÞ½ £F-=sæúÏ?ß‹‰9¹|ùö1cúPJ@Dœkimzú"²²²#Â7ÞøXp`…øèþÉúùç{ôb?}úS§6œ>½qÊ”D²W1P–˜”´öĉ©b±ðìÙ› šçéùÖk¯-$¢!Cº‹o’špá–'B¤&ˆFd÷ïßµ^=›{÷?~žˆöì9ADcÇöu}¨Où³gn\°ø¢ž€€œóÄÄT)y ¢'.~õÕ·ÉÉßÛØXù……Ís¥&ˆ2½‰èþý4Ñ©ŒTýˆh×®ãYY9ÑÑIŒ±1c¼u÷!éS¾—W'"ª[·†(§gÏÎô☬¬lÍ+ùöX±ìzÅw˜@AX[WÞ¼ù÷îEge}sûöÎÅ‹¥ïð1Zž6vw·Û»7!.î´¯¯ cì7¾ñÆ@zq':©Õœˆºw·¯V­Š´–‰‰1ñuNDT©’)cÌØØHL䜧¤\_½zwvvNTÔÒfÍl›5³ ðöós¯>$"=Ë—ê£X]ëÄ|{Lÿ=  Ø!(•eŒá¯¤þtè{ûfõêÕLMýñ÷ßQ:Õk×®>wîë¾¾ïÍûÙ¾} VV– —rsÕ7ÎRœqWœ“nÚ´îôéƒ?ùd_PÐêc4¨uûöÝ«WaŒ-]:^,¶|ù/¯qçÏß´¶®œ”tY¥bkÖL'È%Ožì·gωôô'õë×ìß¿«4Òmذöõ뿬èÔ©ERRª‘‘J­æâa ±âîÝñçÎݬTÉLGŽœùí·?«Vµ:´»T~^}¨£‹å絺։ùö€¾p¿{É@VEM˵ÆØ¼y£]íçç*žèÍÊÊéÕË!$äÍ7¶7hPÓÛÛéàÁ`»7î$%]n×®qxøœI“è¾V@D«WOýôÓ·]\ÚݾýGlìw÷î=êÕË!66xäÈb1gç¶'O®óõívçΟ))×»uk»R —%QăËãÇ÷—~Dšs¾}ûûŽŽ­22ž^¹òÓÂ…ƒ{QRÒ%©J6Ì´²²<þf‹õ##çä¦(_k'Oö¥Cö¼®‘‹K;Í&¼öš§æºŒ±]Å3ÊÆyZZšKýŸW2Æô,_ÐóZA¾=V¨] Ê Îµü^” Îù/¿ÜoÝztVVNbb¨«kûòqb¿Wyaø}€rª»–;ˆ œç\¥òKªT^ff½ëÔøaFÆÓ|k%ÖU©¼Îœ¹^¸úýk"ïñZj»¹yïF†O™²&-í1ç¼ì´ÎÐàWÌ XpΗ,‰\´h+uêÔ¢víj©©·ü...e×®…C†xºä¥K#.Üjd¤rrjS­Zåóço…„ìMJJMN^ollÄt¦‹œsiÝK®=ËgŒ‰Ñ¿§gG++ËŒŒ§ÉÉßoÛv8-íqLÌrÝÖUl®ä1Æt%¢jժ訉b–xݽ»½µue"zþ<óÛo¯lÚ´ÿά "}Ê„"‡¬* |@süø…Å‹#ÌÍM££—õíÛ…ˆ²²rVìÞ?kÖúAƒÜUªBÊ×®"¢½{—ˆáã“'Ï»v}ãܹ›II—{ôè¤{õWRë.AÏò¥Y+WuéÒšˆöïOö÷ÿþä{÷Õ©S]G^=±)BÑÑËò]FÞ'D$^¯\äèØJÔ?9ù{7·i~w÷î_¶¶5ô)ŠÇþ úP6aç4@xÓË"ÎOH~~®Œ±Ù³GªÕñbŠZÿàAÌ¡C+ïÝ‹SC==;ZX˜W­jÙ¯_׳g7KK2Æc;vÌwsë`nnÚ¦M£ýû?skÔ¨Ê2ÄãܹÏrsãÕêøŸÞ’²éáÃýÒ¶.^ óñq®RÅ¢R%3W×ö+JNIÙÔ¯_WÆØ»ïŽR«ãÕêøÜÜø¦MmcQQKÕêøœœã‹6mjklldaaÞ¥KëC‡VŠ%E [¶ÌvumonnÚ¢Eý-[fk–¯VÇk6Pª¡‰‰ÅÔêøçψ)/†‰)šMÐ\WtòŒCÅô¬¬ojÖ´fŒ=ºZwêSþçŸÏsw·377íСéùóŸ­X1©nÝæ~~®Äh¶"ß‹I¯¥š<}zX”séR¸Z//S¼V4AªgDÄ{-[6077uw·ûâ‹ù¢dùNˆ(¡?ôT™‡á8€žð1@xÓËš—³+ÆX\ÜG/Òd ¡¦¦&*•ÊÕµ½‡‡½‘‘ÊÒÒ<55\>Ü´²²ôð°¯_¿&c¬J‹'OâÔêø… ÇŠ¹Œ±š5­ýýÝ6nœ•‘+ /\Øbaaγ·oæáaÏS©T;vÌW dcb–3ÆêÕ³ÉÎ>¦VÇ;¶Fü›•õZÿñÇScU«Zúø8·nÝ1V©’YzúAi¨jlläìÜÖÉ©ŒFFÎU”ŸWe±ÖW_}À32RýùçWju|^MP¬+Öª[·FNÎqµ:þС•Œ±ÆëˆdIGêS~åÊ•¼¼:Õ®]1fm]Ù¼W/ssSÆØ”)þšÃý|{L>ЯssãÓÒ¾^´(1feeùìÙa­)„Ö&ìÞ½HÌuvnëèØªjUËOy#+(ôT™'O pÚ@|" Þ÷2å噸ÅÿÔ© bøä'¿[!%e“—W'ÆXxøé¼/clĈòáæÂ…cÕêøk×"ÅZbH›¿~ýL1î”Òƒzõl¤wŸ>]cÞ¢äO>™Î«S§ºýKƒÎììc ÖfŒÅÆ«ÕñcÆôeŒ-X0VºŽtúô&q‰C¬%Nä‹×³f KNêÏëܹ¥b ,5PL—(O<=;úû»uïnojjÂ6ÌKÌ•š ÖU4AêÃììcb¬|äÈ*µ:~ܸþR§éîC}Ê_²dœZ/r'ÆØ+Ôêø Æ2ƺuk¯y­ ß“ú¤ÁÔÔdÛ6eZ%ÕDj‚(G4AäcÓ§kùáZÁ«Àw•yÒ}xâžiÅcÿý”%66VDôàAº«ÙÙ5ó÷wó÷wÿQJÊ5"7.X|M@À "JLL}1¶ãœó=ˆ¨yózbbff6cL¥bS¦ ¼v-òÖ­[·¾ØÏÂÂìîÝ¿¦MûD,–””JDcÆô…zsÎïÝ{tëÖoôb˜HDFFª |ˆ(2òðãÇÏ÷íKP©Ø¸qýÅ\ww;;»¦_|qÔÃcz“&#ÄZYYÙR þþnâÅ!݉èêÕŸå5 äœ,¾T' `ç<11U, :áĉ‹_}õmrò÷66VAA~aa³Å\© ¢ÌÀ@o"º?M4AêC##U``?"ÚµëxVVNttclÌoÝ}HDú”ïåÕ‰ˆêÖ­!ÊéÙ³3Õ®]ˆ²²²¥Vˆš0Æòí1±cðY{zv¹P‡M¯^Ý6fL1W*Sª‰ÔQŽhÂåË·‰hð`1qØ0/ùV  ð´q9‘×ða×€²ÊÝÝnïÞ„¸¸Ó¾¾.Œ±7ÞøÆ‰ˆ1O±€Z͉¨{wûjÕªHk™˜‹VªdÊ3669ç))×W¯Þµ´Y3ÛfÍl¼ýü\žöì ±˜ô³(„s’F®ôòº&ø,[¶}ÿþdW×ÃÏžeúø87lXK,0cÆÚÐÐ(GÇV£G÷YµjŠ‹Ëi-±@vvî‹¡¹©ä5 dŒyxØ)ø¢V"sØ$=t+'5áEÃI^¸|ìØoùòÏ£¢½½ÒÓŸxzvlÚ´.½^kíC=Ë733!ç™››Š_îÛÿÆú3g®ÓÝcò×âiãï¾»Ú»÷ÛW®ü4{ö¦={«Tÿ&3ÒÂâu¥J¦¢‡5›//\ëUЮ”"%@ >#eÏ›o&¢-[FE%‰“¸¹¹êÍ›¿–Î;8´$"oï®QQK£¢–ŽÝ×ήÙÿý_oÅwÅ9é5ªîÝ›sróæ¯Å†8ç/Þ"¢:uª‹ÅœœÚÑöíGĺqDdk[£E‹úôòyë:uªûû»=ž¹`A8Mœè+;·l9HD‹N›6HvŸI%ìÜùx“DDööÍ5—½,:z™Ô@ͳ슮ãœKM‹EDÄ1ÆêÕ³M¯Û¤IÝ^½22žÎšµžˆÆŽõ–Æ÷yõ!éY¾TÅêZ'æÛcòÅkgç¶›7¿Ã9ŠJ Ù«Y¦¼¥òQǎ͉(**QLܱã(®¼ \+€ ‡ƒ…·¾ ssë°xqà‚áC‡.°·oñ©]@ IDATV¯^ÍÔÔÿý!Õ©S½víêsç¾îëûÞܹŸíÛ—`ee™p)7W½qã,ÅwÅéá¦MëNŸ>ø“Oö­Þ¸1¦AƒZ·oß½zõÆØÒ¥ãÅbË—OðòšwþüMkëÊII—U*¶fÍ4q‚\QòäÉ~{öœHOR¿~Íþý»J£Ò† k_¿þk@ÀŠNZ$%¥©ÔjžžþDZq÷îøsçnVªd–œ|…ˆÞ~{¸¢æy5Pó,»"1`ŒåÕ##•b]"?ÞçÈ‘3¿ýögÕª–C‡v—ÊÏ«ut‘¢ü¼V×:1ß“¯(½9²Ç‰¶l98~˜sË–õ5¯H/äå¼óΈÁƒç‡†î;sæzfföõë¿âZÁ«Àµ(Œ±yóF=ºÚÏÏõîÝ¿Ž=›••Ó«—CHÈ›7nloР¦··ÓÁƒÁv7nÜIJºÜ®]ãðð9“& Ð}­€ˆV¯žúé§o»¸´»}ûØØïîÝ{Ô«—CllðÈ‘=ÄbÎÎmOž\çëÛíÎ?SR®wëÖ.6v¥.+J&¢=:µn݈Æï/¿Geûö÷[ed<½rå§… ö ¢¤¤KR•6l˜ieeyþüÍ-êGFÎ4ÈMQ¾ÖNžìK/ß=¯u,ëâÒN³ ¯½æ©¹.clà@WñOÆyZZšKýŸW2Æô,_ÐóZA¾=&_‘dý7Ûµküüyæ¸qÁâ¶+}®øû»…‡ÏiÖÌöÂ…[ÖÖ•?ûì"Y ÂKwnA™¦¸AB|Zðö@ÙÁ½ø(1œó_~¹ßºõ謬œÄÄPW×ö†pÊœs÷àAzÛ¶|}»Ѿ}‰¯½¶°^=›;wöü·óÄ`IO¸ƒ¨Ü»8î¥0`'O^^»6*))5++ÇÉ©µ¤DÄûõ×û‹ocŒyxØ%'ODâr²‚òCë3ÇxÀPqÎMLŒ¿þúç¼W/é‰CÀ9ï½×³³söìI8uê{Ω~ýšÃ‡{ÍŸ?¦´«V^á¢r%¯w@Y€;ˆ ¬ÁDzÃåŠî_-0˜ÓJØùûÀ«AVPQH?u P@È ÊÝWÁ@Á!+¨pDb€Üô†¬ "Âc`hp¥àÕ +¨ ð˜|9/À+CVP¡!1= +¨èpòƒ¬ÀÐ!+€ ÷L¼Æq‡ ”kxÚ$ØJ3(ƒôc\Ú€'B6>!Päpp)§ôOçðW\È ô3gø`C€=àÕéHo+:ð8»Dÿ=|(¥¸P`3"Â%ƒ†ß+œ 0Lyå )ÎdPáà6H_<š¤Y”Oö†û  ²C‡¬ô†S³²Лø5äåŽÚPÈ   ðkP.H¿É`°ðÅ£P@È  €”eÒ“!%€‚À¯˜AÁágΠÔa÷Ð á Y–tÑ Ôá  ¯wÁ+ÀÝD¥· AQ@V¯‰”Mxà .@ÁDðÊð˜@ÉC>E Yeî ‚Ò€Ÿ‚BÞ…€ÝÊ&¤P–àZ”)1@4ýá*ThPÆàZ”én"Cƒ”ÊdPª8ÇÝD¥Y”H J²(@ñA„Ò…ŸëòOC™;, ‚Á÷j@ù¬Ê |_”#È ¼ÁDE )”C¸VeB*”;8xA¹…kPVá×  ác(âFG¤P>áZ”aRb€ e.@ù‡¬Ê”AH  AVå3wáÕ!†@ÂSP± +€òC_Ô p0zƒ¢…= *dPÞ 1(jÈ  ÂcPÂpЊŽq\ÿ‚r Ïx@ÉÀWáÀµ(·ðü17qi)ü^”gÓPLpE ®¼ )\+xù*d`Hp8äù6ÜAž?®xðžBÂož€VH ÀàáZT8Ò!Áò…CáZTLøÒÒŠ÷{@ñAYTXH _È^@V—8ýƒÄ ?È  ¢‰rà|€d`p7à €NÈ À0 10X"ÀSÅ:!+ƒÇ Ê#|¼"|ñ(€~€AbBA…‡K_1ß9œ ¨Øä × À áPPQ!%(\+C…@ƒ|à +€ò_Nðjp”U8ÆC±Â£†ôT1¼d/`|Pîà[†Š²€pâ ÜA>PDÈ 10(P¼€¬àe"1@nP`Ä ÎÅY€1ű LAX(NÈ  ¸$&&:::þþûïüå3¾œsiVAK»wï/ŠóÇœóÌÌÌÈÈÈQ£F¹¸¸¸»»?þøñãò% w7‘hƒŒ“““¯¯ïúõë333õo»XL^޳³ó€>þøãgÏžé^7777:::==]¾¹"é7y ú@qÐýy,hJ»wï^QÕPk°-pD’¾eH¶¢88ØÏÏoëÖ­éééÒtƘ4+<<\\ÕÕlÅÓ§O80lØ0KKK)æ2Æ6mÚT£F åZ/3Ч|E#½077'¢ÜÜܤ¤$é¢vnnî§Ÿ~Ú¯_?—qãÆ…‡‡kÞ%¥(P¥RqÎÕj5=yòdÕªU~~~ÎÎÎîîî&L8wîç|Ö¬YœsŸ.]ºÈ¯¡çæænÙ²eÀ€ÎÎÎC† ‰ŠŠG5ï‚ÖMhÙ3ʯ²7ðÒŒ¨ò8 ˆÃÒôS§N >\ ¶òOw^ÁV,#¶S§NÕlsžW–·âÙ³g"ØV®\Y>] ¶:®yÚ>üÎ;~ÞÞ[ÃÂò*_z-äR°UD?­ÁVGR°åœç gΜ)‚­ƒƒƒî`+ŠÕñ.äϵö@qáz¸~ýú’%K\\\^ýõ˜˜˜þùGÄJ­³Äô„„‡îÝ»ÇÆÆÞ½{÷Ë/¿ìÚµë®]»Ôjµ˜õÛo¿‰£GNMM½uëV@@@ß¾}srrÔjõ|лwï'Nüþûï;vìèÚµ«ƒƒÃü¡V«Õjõ?ÿüóú믻¸¸,Y²äúõëR}4gÉ¢V«/\¸àààpùòå÷‘>åK­“¦üøãÇ_¿~½|®Z­^³fM=Ž?®ÙFùb¢œœœœ3gÎx{{O™2EL™9sæˆ#.\¸pïÞ½+W®L˜0ÁÓÓ3++ë믿vpp¸víÚŸþ)/çÃ?ìÙ³§ØÜ®]»œœœvîÜ)mKë»×&m,ˆNPbÊÒΖWDU«ÕZã°ô.ò`+¶›WÄÓ‡)Ø*¦çHM”oùšqòU‚­Ô.y°=\Áƒ-À e(BYæàààëë{áÂEPV«ÕÒ,ÅtˤSVjµzÕªU ÐzôH­VçææîØ±C~˜û%Ï"èåÛñ¥uÿÛW¯]»öå—_>|¸I“&AAA}ûö511KjÎ255Ul«E‹æææ©©©íÛ·—o÷Ï?ÿœ7oÞäÉ“;uê$mwÇŽòŠ]¿~ýËE‹ûøè(_¼¨[·®­­­ø·Y³fÿüóOpp°üKEsssmäãàºuëÖ«Wˆ7nܰaÃ3fdee}ôÑGD”““t÷îÝ>}ú888 :ôÁƒóçÏÏ딎.ÒJlN¥Råõ.äææhðê´FÔÖ­[3ÆòŠÃbEq¼üÓ­5ØÊãŒ<ØJëJÁö߈§-¢j%Åaiu)ØvèÐA>ýáÇ"Øv™S©v˜™ÑÍ›Òb:â¼¢òRœ$¢æÍ›ë¶Šþ‘“"v“&M¤`»råJ±zá‚­"¶Ëƒ­â]@°…2YèE|Á‚¯¯ï€Ο?¿{÷î1cƤ¤¤ˆ¹b–¯¯ï¹sçĬӧO‹YW®\iÔ¨‘Ä/^lذ¡ü±3‰"F·hÑÂÄÄäܹsMš4ë^¹rEš;vìXOOÏuëÖIÃw©i–t°Ñdffæãã³gÏ ypñâÅZµjÉÏEɯ'èS>Ïã¸Ê•++N•µlÙÒØØ855UkåйÎÎÎAAAë×¯ŽŽö÷÷¿téÒÅ‹#""Ú·o/ûì³ÏÛ•kÖ¬c,55µiÓ¦bùÔÔÔêÕ«W­ZUkå‰HÚD»víD™›7oÖÞ§Pt´FT4ã°<Ø6nܘˆ8ç:‚­">HÁVŠ Zƒ­"â1ÆòŠÃòeLMM¥`kii)M—‚íçþ9W\ºÕ§|éµüôŠŽ`«µšº¸¸ˆ`#¶š‘Pw°•b»f°U¬¨#ž”$dP0Œ1ñS/wïÞÕ¼(ìààйsç?þøCš²nݺªU«6oÞüĉûöí[´hQ^ÅÊÿ­Zµê¨Q£6lØ`eeÕ¡C‡o¿ýV\ÑbbblmmµS·nÝ|/UO™2åìÙ³&L˜8qbÛ¶m322öïß¿{÷îéӧׯ__GÛó-_š•––fff&6÷èÑ£={öôìÙÓÂÂBZÒÊÊjèС6l°¶¶nÕª•ÔFEáòÔb̘1ß~ûmhh¨›››øúŽT©R…s~âÄ qYãùóçb»—/_–—S£F¬[·ÎÊʪuëÖß~ûíÞ½{ß|óM­Û’VÉky÷.@9Tð_&)RDÕ R–&êlɾÁVkÄãœç‡õÔlëÕ«—W,Õ§|©!Elå©Eq[Å»€` e²(¤¼â5cL>k„ !!!wïÞmܸñ²eËzõê¥u-Íë¹S§Nµ´´ IKKk×®ÝäÉ“¥ûDu*ò=J‰V­Z5<<|ëÖ­k×®ýã?LLLZ·nýÑGyyyé^WKù/NtÉ"®*ˆ)&&&µk×öôôœ4i’bÕ3fXZZŠßÜiÓ¦ÍØ±c·lÙ¢¸%Ižz-X°`Ô¨Q~øáªU«æÍ›mmmíéé>räÈ+W®ôìÙÓÕÕuáÂ…DôöÛoKE½÷Þ{666}ôQZZZÆ çÌ™3hРŶäÿ6jÔ(¯MXYYéî((Šˆª`kk+}lÁ¶wïÞy¨˜’W°Õ±iݵ’³²²Òl===uŸ^Ñ'å/D°÷>½J°•Ÿ‚Q©TElýýýµnK@°…2BËÝuP0/'úûî»ïš7onccCDœó={ö„††&$$펕KeòÄ-TdØåJLaf¡qÎOŸ>ݼysé¾üòKl¥'߀ð+fE€óï@(ØJüرcï¿ÿþ÷ß÷îÝ'N„……ùøø %Àø  ÂŸî’ý€3ÆD°½zõêÝ»wãããE°EJ €kE§€ÃÙÇòÉ'‰‰‰µk×îß¿ÿ¸qãß³aˆ@©ÀŽW¬Jü„sþäÉÍ`«¸ƒ©Ò;òUœA©ÀŽWLÊ ÜAP¤Ä‘ÏÀOöH ÊdE ‰c¥ò¾™ H‰‡`hp} |µ€b#¾˜ ©”–‚“h” ÜBVPœp7Ü2PÎá;ˆŠNžé× ^²P€òAÊjÖ¬õ=Ös]•ÊK¥ò:sæz¡·®£ýËgÌSú33ë]§Î ÀÀ32žêS±Ö™3×_±'_>5‘÷‰x-o»¹yïF†O™²&-í±þe¾ Í:˜™õnÔhø¬YëŸ=Ë,ª:pÎssÕáá‡nÝú­¨ÊÔ­ììe\Ú€Š,..%$dOJÊõÇŸU«V¥k×6ÿûß;ÆX¡ËäœúéððØk×~ÉÊÊiР¦ŸŸë¼ycªW¯¢ÏºFF=ˆèôé]º´.ÜÖu” ùŒyJ¯MMMªU«Ü¯_×7­¬,ó­ƒX7%e“£c«WéÉW§OMôﱤü8jjjR§Nõ!C<–-›`aa¦çåu{ñš™š×®]ÝÇÇyùò ÖÖ•u¯››«Þ¶í°»{‡æÍëÑ+î3º½ú>©Å‹·-^AD;6¯]»Zjê탿‹‹KÙµkáàÁî…Û‹8çË–m_¸p«‘‘ÊÉ©Mµj•ÏŸ¿²7))59y½‰I>Ƙô^sÎ QÝ%èY¾4«{w{++ËŒŒ§ÉÉßoÛv8-íqtô2ݵ’[ºŸDι¿¿U«VEGMä}"Ö""OÏŽÖÖ•‰èùóÌo¿½²iÓþ;wìßÿéSfáj{òäeww;©>¢œógÏ2¿ýöJHÈÞôô'aa³‹¤Œ±NÆ_¹òÓéÓſЩ]‚bgKJJuw·+ò­dP\0Á@„ôè“â"È{XsÄsàÀ Ýëvê4AŒ!D!ºŠnŸÑMÑ?'O^vsëP´[9vìüâÅff&ÑÑ˼½ˆ(33; `ÅîÝñ³f­4ȨŸ…µk£ˆhïÞ%~~݈èéÓºv}ãܹ›II—½¼:÷ž¬»=Ë—úåÊ GÇVDtàÀ©ç~õÕ·÷ï§Õ®]íUöíËŽ^–ïbŠJŠ×+W‰t”s~êÔUWש_}ê?Õ­[]Ÿ2õÇ9OK{yxË–¯¯^ý%7÷¸Ö:ìÙ“0bÄâ/¿ŒŸCD¯^Îù•+?‰×bsEÛ.EêÕ½û[íÚ5ž8ÑwôèÞÕªåê  tá"(Ò@$66øüùÏZyûöÎáýrsÕ³f­çœ wiU>9yrí+nÞü¼M›Fb ’o™â ( ¯2É«=ˇ ÎùÊ•AÑÑËŽ_³gÏbιˆèn…´.Q!û°¨ˆHtô2qB=/yõ çüÑ£Ç!!{;tìÞý-Ñ(±¤è–˜˜å‡´uë»Dôå—ñb–>[¤—{8*jitô²¸¸^ED~w÷î_º×½|ù¶¼‡¥ß™E©äîÝß²³•–ö¸¨ÞßÐÐ}D4}ú‘‘™™IhèôØØà””MbËII©^^3,-½­¬|ú÷ŸsîÜMiëâvˆ/¾8æîþf¥J}Ú¶{à@²è^µZMDÛ·¾páÎÉÒÒ<66øôéööÍD‹8ç—.ý8`À»U«ö·°èëæ6-6ö´(Y¾'÷ï?G¥òzï½Íb‹j5oÖl”Jå$nÿX¼x[³f£LLzZZz;9ÅÅ¥ÈKHM½íæ6­R¥>-[¾«Y>ç\³šý/^ôéã(^Ü¿Ÿ&¦k6As]ÿy*•×Ì™ëÄF³³sjÕòW©¼¾ùæç<¯>åè(_Üð³cÇ7Ó+Uêcg7îÂ…[~ø…­íKKïßÿóÏt±Eù­Aùö˜T¾|?gŒuìØ\´èáà "RÜn¤Ry)š •³mÛáV­FWªÔÇÃcúÎÇD{å;aRRj@À‡õë5kýÕ«¿´mÛHlH³ÏžýCD-[6P´K”£Ø˜+–ÔÚjþâ $çÜÉ)ˆ1OÍ2óí­­ÎksŠOt‡M¯\ùé­·Bë×mܸàS§¾/ݸ P$ˆ8?!ýùù¹2ÆfÏ)ŸøàAÌ¡C+ïÝ‹V«ãÕêøÄÄPOÏŽæU«Zöë×õìÙÍju¼XRìœ;vÌwsë`nnÚ¦M£ýû?kÕ¨Q•16dˆÇ¹sŸåæÆ«Õñ?ÿ¼;%eÓÇûźjuüÅ‹a>>ÎUªXTªdæêÚþàÁ`EÉ))›úõëÊ{÷ÝQbznn|Ó¦¶Œ±¨¨¥ju|NÎñE‹›6µ566²°0ïÒ¥õ¡C+å%lÙ2ÛÕµ½¹¹i‹õ·l™­Y¾ÖJ5‡””MbÊóçGÄ”‹ÃÄÍ&h®+:yÆŒ¡¢g²²¾©YÓš1vôèjµ:>¯>Ô³üÏ?ŸçîngnnÚ¡CÓóç?[±bRݺ5,,Ìýü\<ˆ[”j¢O‰ÅÄ”ÄÄÐ1cúVªd&Jh×®q^KnÝú.c¬S§Š-йïµlÙÀÜÜÔÝÝî‹/拹Z—T«ãŸ>=,Ê¿t)<¯ Ký&£iNÞIDATˆÒäµÒgïÒºßêÙ?vvÍDÍ-,Ìû%'¯—‚þýË7n¿üa´±±bŒÅÅ}$ÕSþ§VÇ'$„ššš¨T*W×ööFF*KKóÔÔpyOZYYzxØ×¯_“1V¥ŠÅ“'qjuüÂ…c¥ÑOÍšÖþþn7ÎÊȈ•J¾pa‹……9cÌÞ¾™‡‡=cL¥RíØ1_ñÅÄ,gŒÕ«g“}L­Ž?vlø7+ëµ:þã§2ƪVµôñqnݺ!c¬R%³ôôƒR ÆÆFÎÎmœÚˆšDFÎU”ŸW5û_­Žÿê«cFFª?ÿüJG늵êÖ­‘“s\­Ž?th%c¬qã:"FéèC}ʯ\¹’—W'qáÂÚº²……y¯^ææ¦Œ±)Sü5[‘o‰Åä¯ssãÓÒ¾^´(PÔóٳÊ=_¼ÖÚ„Ý»‰¹ÎÎm[U­j)ÿ$®Y3­]»ÆbJƵgÏyþügŠhãéÙÑßßÍßßÍË«“‰‰qÓ¦¶Ò2ò:ìÞ½H,/mèÅ0æç'òjµ¿¿›|+ŠvéÓÿZ[­£“{Ô… [þ÷¿áõêÙˆéööÍÖ®}«`Ÿh€’‚}Š"ˆè1)±!‚|I­#c±®4†×_Ÿ½« c©|Qsi !¦f ñò‡ÑØØˆ1vêÔñoP“ÝZ“’²ÉË«c,<|ŽhEDÄ{Œ±#zÈ{rá±juüµk‘¢V⣚›¿~ýÌÖ­’L½z6Ò~Þ§OÆX@€·(ù“O¦3ÆêÔ©.>tÒ{”}¬aÃÚŒ±ØØ`µ:~̘¾Œ± ÆJ§‚ƒƒNŸÞ¤VÇ?x#Öºx1L*aÖ¬abÉ©Sýc;·TìR¥dR4Pþ®‰·»{w{SSÆØ°a^b®Ô±®¢ Ò{—}L¼ãGެR«ãÇëÏ[¸pl¾}¨OùK–ŒS«ãcb–‹rX¡VÇ/X0–1Ö­[{Í=ß“ôåc¦¦&Û¶)£™ôZj‚X^4ÁÉ© clúô!b­  ?ÍOb£FµZ)B“|çÔZ‡FjïÛ·T³Ò†ä{2{‘~èÙjE™úô¿ÖV+6'–›S|¢Å_NÎñV4jT[ÌEVeöE("ˆ` ¢÷@¤†LÛÝ>bÄÃ_\¯Ðó .¯¿>{—Ö>׳¤ICˆ¹¯’Ô©S1öÕWÿ^µØ°a¦Hº¤íZZškö•­­¼ÏBÕêøììcbî™3ŸÊkûÃ_lÝún``?KKsƘ‡‡½XW\:~|Xòï¿cEiW¯nS¼›K–ŒŒŒXKKs##ÕÏ?ï–Ê?thå[o qsë ÊW UCŒǯaŒ™››*ö±–b¿²µµÑÜëLLŒmmmÞxcàãLJÄ\© ¢Ì¿ÿŽKŠ&Èß»ùóÇ0ÆÆëÿÏ?G«U«¢R©~üqg¾}¨OùIIkÕêøÓ§7‰rDZ»~ýLƘ£c+­'t÷˜üµ§gGOÏŽ"uèÐô‡¾Pk»ò)^KMëÊ›pâÄ'òwAú$zzvëZ[Wž4É711T¾çÈë““süþý˜wÞÁ³¶®¬y½BÚ(ùøñ5òO‡>­Öl—>ý¯ÙjQŽ|sš}%ÿD''¯Ÿ2Å_\è}ެÊ&å{yu"¢ºukˆrzöìLDµkW'¢¬¬ly+Ä;žo‰ÅÄá—_î¹ä7>>yò¿§A¤:ˇÿûßð_}0~|ð?ÿdÉÛND—/ß&¢Áƒ=ÄÄaüä ç/\–x®^Ý6fL±º»»¼Âb]Qai+Š÷TÞu:ö.­}®Oÿ°÷â÷ÝÕéÓCVüòË}©Ó M|J\Üi±¡7Þ½,*j©´]µš3ƺw·Ù‚øsum/—+U2»œ4ñÌ™Ç/5kfà6ûóÏçÑÙ³7Äb*“Þ\Ñ©R—*ÞÍ |LLŒ÷ïOŽŒ<üìYf¿~]EFÄ9Ÿ9s]ÿþs’“¿6ÌëØ±5òµÄëìì\ñÂÈÈHQI±¤Z͉HÞÀ]]]ÛËß_1dÌÊúæ÷ß÷nØ0³råJôïåÿÎ`Œqþï &{A,Ø1•¸ÿ·ééOºw·oÒ¤Žî>$"}Ê733!"ÆèE9f²ÍjÙKóí1ùë•+ƒŽ_sâDˆ……Ù•+?Íž½Iþ61öRõ*U2eŒ½xC_ºE^ëçøñ5×®EΚ5ÌÈHµyóé-[¾.¾ˆBCŒŒTµjY/\@DOüñ®¢‡%Šþ…èÓjÍvéÓÿš­æœÏ˜±V¾9;¯/ÞÖ²åë®®Ó6nüŠˆfÌzõê¶øø(“@±À@­‘"ˆ×š#ñ¾‘>uÅ{*ï:{—Ö>×sȲxñ¶V­Fwë6uÆ"š9óµk×"¥s¢…óæ›ƒ‰hË–ƒûö%Š)¹¹êÏ>;(m×Á¡%y{wÏUÝ×ήÙÿý_oÅ»¬è5ªîÝ›sR%¸xñÕ©S],&n±Û¾ýßÇf""âcõêÙ´hQ_ÑÏuëÖð÷w{þc¬u놫WO¹sgOdä\ww»¼»xñ6ͽKþë¯÷Ŭ5ª*z@Ú˜¸cÇQy!:Z­R©c¹¹êB÷¿f«›{u^´hë­[¿uëÖnëÖwïÜÙ³zõÅ…n€2Y D0шˆ%3D/éìÜvóæw8çQQ‰!!{Å,u±õÜ\µæP@ÿ½«ýCD‹GüðÃï®®í#"Þ»sgÏÇO!hý”éÉÝÝnñâÀœœÜ×^[رãxŸw7>yò*"ª[·FíÚÕçÎ}]¥bsç~Ö¥Ëä^½f ¾héÒÈ{÷iî«òÞhÚ´îôéƒ9ç“'¯êÜy¢ŸßÜöí–,‰dŒ-]:^,¶|ùSS㈈¸ŽÇ{z¾5sæ:•Š­Y3M¤LŠ’'Oö㜧¥=®_¿fÿþ]¥} aÃÚD°ÂÛ{v3Eb–žþDZq÷îøÎ'ººN ÙKDo¿=\Qs©NNA½{¿-5Pë^'Ç9—šÐ©Ó/¯RD5ïøøñ>Dôûï«T±:´»OòêC"Ò³|©>ŠÕµNÌ·Çä+Ò‹(4jTOqùtþü°7îpm× HÛ¾ýÎ;#ˆhíÚ¨nݦ:8LÚ¹ó¸T%ygVªd6ztŸÄÄÐË—·NŸ>X^ÎìÙ› š7hÐ<Ÿw=<¦3ÆúõëZ§NuE¼óÎÎyhè>W×iŽŽ“wî<./DG«kÖ´"¢I“V¹ºN{ö,³ý¯ÙjÅæÄ.-6'/Ú´A—.…'%­;ößïWÈãc P& +€b"¤1á²¼¢¸‡Š^9²Çĉcóç‡Ý¼ù›f…åui áæöæóçYò¡@ö®B Ô¦Nõ¿x1ìäÉub ¡÷.óç9rd•¯o·»wÿ:zôlVVNïÞŽŸ|2ýÆí ÖêׯëÁƒÁv7nÜIJºÜ®]ãðð9“'ûR~éåêÕS7oþ_·níoßþ#6ö»{÷õêåÔ³|©>úLÌ·Çä+’,  y³]»ÆÏŸgެþ7)ÎçZclÐ ÷°°ÙM›Ö½pá–µuåÏ>{‡½¸ßFëÞØ®]ã7¥ž!"q/eLÌÉ£GÏææª‡ 󌌜«Ù.·ðð9ÍšÙJ"ÙE9­ª_¿æwîÝ{$¾ó· ý¯ù‰Ö±9yùk×¾eg×”!€r‚åõ¹(ÆHãiÑo¾9·vmÔ©Sß§§?©V­Š½}³ºzW©bAD‡ŸY±âóóçoeff·iÓpƌ׼‰ˆküÚ«üm9§°°ƒqW®üôôéskëÊ;·|ûíá}ûv‘¶{öì¥K#Ož¼üüy¦ƒCËùóÇöé㨵dÎy»vׯÿºpáXq³ŠpîÜÍ7ÞøøÒ¥ml¬¦Orîܽ{Þÿõ%KƉ"#熅ü Ôš?ÌèÑ}å;:¶:r䬢cÇö}q(ý¯Eš Îù¹s7MèÝÛAs]"ÊÊÊ©_è_ý=~|ÿÍ›ÿ'àuô¡h >åŸ={£k×7ˆHüäЦMû§N qphyæÌ§Š%ÏŸ¿¥»Ç ñÛÆÆÆFUªXôéã¸nÝ ñ¤Š¢qË—oÿý÷‡Ýºµ?Þçõ×—©ÄÓœš=üìYf×®Aßÿ³‹K»ÄÄЋȫ‘‘GæÏ»?­~ýš‰‰¡ ¼&¯¿þ{WÑöϘ'éŽÛÚ>ŒP~þù^ëÖ£³²rCÝÜ:”vuJÈÖ­‡N^n~Žž®¾ÎÞîþ/?O_o_þƒÏßïÿ0 9:<ˆ0¡Â… :|1¢Ä‰+Z¼ˆ1£Æþ Ð×£ Ç‘$Kš<‰R€Ç9"Sº| 3¦Ì™4U~¹£eÍ<{’\)G§Ï¡D‹=j(ÎB‘:}*S)œ¦P«Z½ŠµãÍ¥8¨fý Ö¡Ô7^Ú=‹väX®4ʦ}[um·p{Ò…(®®^¹lcÜ=ûWl`½ ù®L¦×¿ˆ?5Ü×E㬋#NvŒršË˜KŠ,ø9oÒ– ÇÖ)Z%çΞ·Fž±:nR•§;’V-Ú´íݬm²ìí’êçÑ´‹=;áðŽÉ…îúµ_´ÎƒN~œ¸qæÛ—WÝMìçÊS×nŽþôòî¹3ëÆ]~<ùÌá¥Kûþ|öý¸þ×£no[jùÁ‡_}lÈGžyÚe–Þm bç݃ )¨Ú|if ¾Da‡ r¢ƒëmWžBÆeàa^¨à{'”ƒû¡fb‹'®X†š°¡b6Š˜‰2¾ˆ]€ñ™¥£=ZX‘¤È^nOŽ"Ž%¹ãKÆÔdSBèž”F’Xd¿Y‰fš?¥˜å [ª –d¼ g¬ÉÙætÚéžbìÉg pù™'€ :(››!ʨ „ªÁ¡‚w椖¢ù(¤HzéW™zÁi§¢õ©¦„:*Š•¦ÊjŸŠšªg«p–ʪ²ÞŠ­°F`+®DéªE¯¾«°»: þ,±;‹E²Ê>+³Ç.à,´\¾zFµPÝXeŽê1´deˆJ;mÚþÄmÄ}g%¹Uœ‹•Êeäß„3Ák”»å€o±Þ–I¯««òI#m¡=ÉrcŠx[Ãì%\Zs2ªï¾ýb$ܵé†0Œ¸¶JRü €/šüál6|ÝŒS)o—{ñEM f3® ð[3GQ³OÙ„KŒrv8ïÌßÑ㊼¯Aÿ[ò·0r7´Ó1§õ3Só44Öeʘ²ØJ§¼ôÒŽB5_Ot³ÎWë ³Ü‰LpÎL‡8/e6ڳݶoÃÝwÝ9‡]5™>þç¤æýþ÷e” ««·€×á4u½«çÑ Hyæ¼U^/a ;!º£ÖF yá´þzޱƒA»¹‡,;»×nÙí_ü|§«›J|ñ… ªòÎ/Ë|ïæ>ŸØñL$OýÚÒ{€}öIE_«÷âç þötï½õKÄ~ûî¿üò—SþöóßþÕŸúã§©¾BùzLÂÿ‡£¶é€ÎSàˆÀù8pG,Þ‹PÁƉ½Ë`í.Hj°3 ”Ž­UB!œp„Õã ìVø¬¡1å¸]ÃÂ;¹°p1#Ç·Ô"ËPMy2B` æ/Çu \0_Ù‚Ãî,Î=x¢þwø®1Ud1rØËF4œƒñÆ`~Ëa]žÈÍIˆqlì›·¸ ŽqQ‰–BcH'E³‰©sERXÚˆdÆ3b1j€ä\Ùö.<ªMbtl”yp2§õQ’‹LÝÁ,HÕ ÒbzË£~Ú(E" u=«ã&¥°HO I}œâ*í–IJ™o`¬ÈVH‰²Œ©4Þ)vHUƈ•^"&ßKÊüòXµ|e1çvÃ]*.——zdN´è¢nQ’nHä"”à˜L®-3tŒ´š‡ÔE]†‰Šc¬\Ѷ&¹q²Îá¡5õÑDbÝ“)ú©§=å‰<:eŸ]h, ê| ¡6P¨AþU5ËH=4_½ÞDÍÈPn8WmËEsØQmlôV!•ÁH?Z”’b㤭R) XŠR¡UR0M•K_PÓ˜B/¢ÕéNƒb‘aFKˆò©8yšxNk’ %Er•™*áˆíLºâÕñÝ´Ñô˜Ü®ŠLu:QªĦá(%w*®ªŸ«QeŠÔM­•[l¦Pß89tb3¬Õ$+wµëµ—ólâJùÖ_ù5K€ [Ë´öÀ¦9Y}êbI(–”ˆ´—aÏÏÄÂ5®R3ØÛ¸ÂHÓj ­/ÏTH/2° ú,mE;ZÒº®l´kdWûJjÚô² ææfþ ËÆ·GÙ*5šÙ4í0NµÈíìmEå\¨ubα‹ÅBã¥ØxV9†$bGOêÞI=‰­˜+Ëp¼¤r«t[äàÁcKt²½†<à ïV¾‰¼ò…ˆÚU&ÛŒ¨@æòo¿7å8ZîhDÓ¦Êú‰eŠj™_ï›ÑZ!”ý7¯r´í’ÿ¦þç¶®SÍP/æžlg¯*šŒ­-²þXÝ<'—©eŒsJýÜ k®.“´u¢[]?Fù“hC-p¿éeb¦Îo‘l¦ j¤9)˜ê®¥íòêL3`Õ’´¬· gUï²h.Ó왕 lV›ÓK¹nèWñé.ÛúÖ?3Ä¡^Ÿº“Ö5æaCýLoÏMÈâo¿Mšf× ¶Ð¾n´©M*usuzãîõÞkèÎ ܆^ë]ðÝ]³=ÛÕin­!ÍäYÃ[±ÖÞµ¦ùÕIî.w»œ¥– Ùz“޳q«Ñ‘“Ý1ŽcMÞ°¡òÂHrk`^¶’Ï aì¦Yùä{1ǵóqþ›ççüâùù|®óždçCú8n^ôŸ'=èJ?:Ñntl?]êQxÕ‘õ¦S]ëVç:Ö·Îô°ç37É€‚Sö#%(åÓ¡ù¨`®Œ•»]Êž{_N-«ïXMp/ÁÞ©Ýwblý|v,Û_Zø»ãÎÙNüòZìx¾žƒÏyä'4ùû\ÞÁÖ®üµ7¯œÌ·àï·|/º¾kÐÓò Gò„ÒuijoÞôÉ8òS\EYy©ÎíT†Êm%ûǹ'=¦D? ׿¨I\>ðì í‰ö!Ø.h™ú±¤Ùrжµ\¥güó\a‹ØÙ¼9h•£¯°†EHn Ò‚yt‚)¤Úy—|i¥y‘U9£ý‰¥ÕÈ íH£`Øqþ&Ӥަ¥+ó–ÓuKÆô–M¦7ú9ejÑ™;ºFkz…ÿ©‰1h¡(éõ‰æ1äÇ^Áå’(õ¤®0%Œê^íÙþ™×—9nõŸã©L׉§¾¨¥ úzZ’Èø©¦Ê”¢ªªÀɪ‚äªÓ «±Jåùª¥j«²Š«´ª«»z«Ê9ª-´ªÀÚ\¨”¹ú{ÆšœÂª¬daŸðùžÎØ–¶:©­EžÑ˜7ø‰©j±{ÞºD€ø¦=:WÅŒÌ:€Î:­“¡1П ÊW44®cf;¿1†ûøf89Ìx¨Œv™Äx­¬rHs}Œz’ü cTW%Ú‡„¦©î ›h ±ÛŠÈ:˜äI‰•©f±.:¬äÉ®a¹ht³(‡({€‘ 0Ȳ!¤¡Wp#¨˜È7„¾Ú›qÙ©5Ù—bþvTiq_:¥ÅF´±¶”4;¤1«³ré—j8¦‘7°«`²Tɑߚ¦X¨:ŽBK„?¨îª±h)¥ ¶¥Å÷´SëxUU#kk´eá§}i’tÚ®aÛµu‹bbx:‰•ùJOùÁ±îd‹n› Žº~ýw‚(8–™J¡¥v8¢¤ƒ¤›zpxIw¿v±›ˆ‹ #Ë;µê”ˆ1¦ëv { ¢Ë«œ«®`¡º¦ÀºÍº¬¯š=û¬âa»ÖÙ«ÙY»» »e‹ ³¬¿ ¼¡Ú»ª7°ÄkT±[ ÌË»®{¼Å®¾ ­‘õŒäX,ÙkŸ±W­’*¼©y/ÝzŸ˜Ÿüe‘j›þ뫚”dÐ{ÎK òÊD*Žô‹@%¸ÿŠZü 1 IW{~š*ƒHÚ¿é·Žák üÊg e¹D¸‘ïj˜DÉi‹º´{½k²(ÉhVZ Ù¢>9¸§ã€3›> Lœ%Ì—Pè|0«l-+¨ÄÚ´hë³ÈUqäŸZni§$¿£YNB”Ú×£HËÃuØÃL‚ÂèJáÖƒ“%¦Rû±Ò&·&œ=?, Piw´?(¶^ SËÛÄ4¼ZZLÅR µg|³eù?X Z¬6\<¥^¼· 8¨ugrZ‚?j˜ï•†kܯ^‰À…ûFµÄºÇðÅ©ƒÁLJŠ6¹w,½ñkþ–¦Ù¹‘9«egb¬{_›L‡ü¡Ðoœ<½È[½Ê+ʳxÊ€¹Ê:š»sÑʨŒ»<{½³ÜªÉ z¦ŒËY¦ËàW¬½Ì!¯ ¥±| ÂL½µl½º«Úˆ® IÉ·çbn ì`Ó RÄlyÍìYˆ¥¹À·ÃšìaÔü ¨bºÐkÊ \l4‰³ÉΉjëɰ§V1ìÃÚŒ­$,Àl™‰ÚŸ <œ¬‡D‘, \.›¶Óä¾§‰Ïk—6Ú¢ —09V‹·zÄô©¤7i•Ò¤l›Í™Ì ÝÑlРͦXI[W;ÂLš¶ûöQäì ,MÒQlÅú9ÃüLÐ=LÈðþ÷¸wÚÎIÊ™¼¥]£Bax¼q…ª¨gH˜%²W‚æ™…ù®jÖV.Ó mµVÈw&Ä­‡¶Mºõ*4¯+Ó­¥ŒÒð 6𛿩̭4ÇËÈ|¬D½ËkM×¥ÕokËÌœ×uýË—7×ov ÌcMØ8º×‰kÌ*’Ø—fØ‚×]ØMµxM¯ò•®_–“M€r,±…{áj¾ßZ‰ÝZÚd}-é‹ÍØË°¥ÉÈ’m×Ë茭¯×œÖ zÍ京”ù¯ÜZ”ÉÔê×Ï„yÓ¥·Ø¡{9ú(¸À½°º1|‡g•®ÃNl¢õÇ¡ô‚Ù¤l °!|€½´ wÖþœ€3Ù'ÂC¸Åuüi߬²íí´ïݦ°ƒMÒÝWÓkèÖž’Ü«+8©[KlWY´ ™žC{ÄÒK¨@M‚ú­Ã}Ø% ÞïÆì­¦ó·ÒÊ¥_Ì·jÑÝ`L¤%^Ów=«éÔdâþ…am®zËáH}¯3¬ÔÈÝÕfqØ4}Û—-ÒLqâ5®Í¹ïÉŒiV—«q™‹Ð5>É»MÙ&òß²ëÙ‹’Øç½ ý¼Á<åahÙm;Ùa^mʬÊ`næ6SåÏ{åhàå#ÙæóûæÙ²æ³Ù@ŽØw^p]áÆËçŠ1ç@\ç#Ó3»^^_JV› ¾ynþ¿¶}¾OEÚž6éÅ›Á®çáÑéÊÖ-é,Äåš°îšD¹}¿RNË™ŽU¿°:¹¤ÐÝÜúíž “Ã3ëöì+£ž ü(¡é'¡Åí p±‰ ÝðAIhÁ´#ÐÞM¥†ê™ ×X,ˆ¦í¸;ýìÄë˜à¨ôj/#ÞµF+è£î ÑfÒ´‰þ‚«Ç•ÀÒŽŽ{éîÛà8máþ¸ß¥Ç-Ìàc\¤;ëËåJâ/ £Ãž—_Jîí.±kÙÆƒžÅhlâ`ù7üþâg›Ò¹Óì¿“ÃÎÜ-ðÃÇñLí¯â¦UÿÆŸïJ´ïñ^ñ nÇ_nã‡ã=~I¶þ¾|‡¯þ}qE DzHϪý<Û~ `äãÖ7ñ4X/J.Õ+¹ø®ëyªæŸôÛ²bBo q¾ê~¿Ñ8ˆñiòÕ\èe€õd é‰7؃cnöeŽöÃ\öRÈömŸå__Îa?'r¿Új÷Q÷§÷vwö}¿&oø#dÞ»½åk馽éÔŠÚ‹?õoG÷3dú¿‚¡øfÈø‰ÿøšùÜÍÚRO–AE5øëV™ýôŸ|„ÿmÿ¨üyÛÜŒêœÎÍPÞÛUåêi°Y¹×í°¬Ý]ÚÇŽÝ«~Û=c)~’ü|"ïÜŽN¢«ÏÇO¡Æ¾‡ÑÝ«åL+ð/ÞÍßúúæÂþ\éi^˜à+ûÂ2[ß¼Ù«*’*îÕ›>þ­Â. á.þÝ‚šñênÔ>JϨFŠ c/]{†Í&/ÔZÂL—ɉ8¥"ÇM]ÙÖ}áXÀ¾ñ\ßùÞÿAáX4‘IåÒöqZDOÒ'µé@ATŒ(r’VUWCëá^¼X™§Æt¿á¼/VZ§Ÿ¹àùh›¢ÞÕXÄöúPÇÖchâ #%')+-ßìùþÄò4Í¢ðª¾>K¬ =óöfÚ.c/ 9k5;þZUE {CsW®hGýt}‘“•ƒaeŸ¡£¥'3;M7yÃR}WI…ÕNQEs½‹K_§×•´BLÞÓþ ½Þá­9êAyÙ(Dé‡pYC‡Œ±“8‘bÅX™”ébΞ¶}ÿðiä0œž`ù‰92`¢ˆaêçpæC›7qæÔ¹SÙ˘?ZÓe ¢<‘&MêShÅ£ó)•:•jU«lšfÕºõÙSG‚®†›Œ)×i^ǦU»–í²²fáÆ•+m[»w!6›Ûo_¿ÿ¾Ý;˜0ܺ€Ö[ØÒáÄ!G^#˜qeËKÖ|•òe8™7‡ ¸³gÓ§/ŽVm·4ê$ WÇ–mµµkÛ·—Àž½»QmÜCtó>¼¡ïßÇ‘÷Nœ¹ ÅÉ,o>ºþsè×±ÿ^½¹ñì9“éxb7G5A£‰ê±'Xîa½—o½yk3ÉÈ×)˜Îü/öC@µâ›ï©A¾!Ÿ¯e2bÌãi»÷)p¾ «oœõzÐAˆ>ŒÁ+¤ÊÂïþY)¿BBiÕ+ï4B"¦ Mø“1£{6bB¥NÄPȸbüÈÈŒDüÄ Z(¡á1ÆÇ%£lÒ3Šò¹!e²œ([t%Bo¨L¡Ø"„:î)'Äw ’Ë9›ú²š7<3\èÈ‘Åþ¸Á¨>ÇðÓÄ-él¢O'Ïó`Æ´±#–Ø\è‰;õ<N©äLÔSÌŽÄ´Á<ÕþSéyDr•R!d% l´ütŒHÁƒE1Ç™gcÜDÓ_ßܧNe-ö,/9…T)]5PUUðÅ=­vBýM”V†•ö˜ÌéõÅ^M=Xa9ÍÖØuc:×U@¥ý’Zo±!ÊNfé%7Ø›ˆM.Å#7buaò´‚PG5%OS3ºÒ–W¯E×(uÙ­x¢³TXá“V“#'QŲÃÖ§aÿÕ5]‹å•X?—Uë×â™#‰æÍd>.Ë›âY´œiš ›}† h܈.Zi)Ú鯖ÞôèÛ’ŽÚꪦ~Zë ÈèÚë¯Á[ì±É.Ûì³ÑN[íµÃnzȪþ¯Ž{)··®ûðÎ[ï½ùîÛï¿\ðÁ /ÜðÃO’¹ä!i"ÇB.’‘˜@ä#G×HIN’/´dë(™IMJâ—”› 7Ê>fÆ äX˜ –=‰§wnù$A)JYÎñxÞŠà›‡d¤J•6é¤Äb9KaŽ‘ˆEša÷¤” Œ|MbXŽ”¾­ažT€"‡™ÍQ¢°[~ºe´ÈT ýùJ}þKˆ¾¬Lm®Ó…„þVöWÃï‚î,çaAXb“ý$c íÇ(HåJ#âÒ¡µÀ‡ÏmíÓŸ¨aÛC!Q‰N”¢µèE»€–D{ÉËe jÃƒŽ‡ò¤:*‹_Zs5(¥ ÀŠX2óHD2%YùnzÊÎK|‚:"K]šR¨±TtA}¶R<U¨Ô jQùiјݙc¶v²!#ûØ`öí©Ž6Öè$»["¦ÀŒÅýÑg·ÞîkW:š˜¬Õ"ÙNÐl8oïþMðƒ¿Úµ –÷ |qŒ÷„ÜË/®¦(Î,¯Vä?Ô848ëñ¡¼¤.j9ŸÍÝ(*x߀ÂgÊo^î—S6æ2g¢ÅÁÍeš=x9ÿñ<›+b£SêLç@ÆÛlðYqf¸Vú»<)hÓ/‰I¢ÀaúÓq3}ØB-ºŽ9Õk¯»ëž; ‡î”»?ºî[ßûÍÚÎ_ÿÝ }‡;áYkø¡ñ×vã?÷RCþ1³¦¼¬ÿrÆ7Þò—çNà‰íyÒdÞè¢ÿ<é ¾yÄwÞôÝA½»=1Þ]·¾8¯W=íwùú['éÔÆ½ÃÁ>*)‹}DÔýýÈ%_ðZñO† •ûñŸþs…w´ö*ôéž|å3±—¦ 9ö±ât”±Wâî]‘}Í{£ÛÃV÷¤N w þ“|ù6æÇ‘ìýõ[ôÈå}ãOþÂïáNFÀ\ECÜEc–ŽóÚ¯ÏþÏúlN0øžŽÁZLáæçah¯ÿ\mèL¯îñ€0f0ë†6lïcƒ7M ÛMúœï´ïs¢pe ° %ƒ çF¹°òŠPÌ\pîXï Go SÇ ã$ ÕÐhÂPÉÆÐëʰ ñB ×êÀ!%¾¸Žoéþ5Þ0ÇX¬  ,=6 ›g‡þŠŽ ÙÞ*®v©¯€köquPÝ ñ Ñ0ñ†lE‰fÌÐ “„±ÄAÄ ‘[.ÑyŒM—œG×.ÓÂÅêRTƉTˆFªnÙðü"Žß,|ÔO¦@æÏýË·š+™Bq±œḋ±¢iA¦‰úbJ,h«l‘¾@°YŽ…0O‘üÌeœl±Ù¤ÁdŒÉÌñ„ÐqÞr0Æœ,K,Á§Q˜¿ðT-dè­¶8 dòÙî€âžè~žî2‚ ’œ¦.ÄVqXìÂðѹ qÚÅ/"d!al¤>¬æ2°w‡þD*%gŽ$UÌÌ6QZâè²àOF*3­YrTZ%$Uºº !wmÈP²çZ(w)²±©l’íñÙVnš¶ËÊ„Q žr>&ßfì †±ì¯L®r$Tb˜æ%9q&¹ lDÏ»ãŒ\Ï,aîùeÍ-ß.)K.}‰.õ²+Rðúò×®00Û")ÝŽ0Ý‚/s¹þ2ô3÷Hñ1±±1ýO2—-2- ñ2/3óë@¥3g‘2;0TNîQÙ4»p3SÃÁv.A°õR6Hq‰ïc“,$Q‚ëút³û®7‘5‡jYô±÷îÅŒLo6ÓŒCþe1*þðd:§¤:kÏ8gºg}.žpï+e½îcA ’ï¼hЙþí¹²M’^n«Ù“çKë+>“qÀhs¹³æ«ä„SOÆ'U0±2LO³͉ÞsVS5V‡ÆViUït5Vpõ±zuþN5XçòW•X£‘Õ?z´»²š>mW˜“7É9•UE:vQ:_Ñ|%äqf™–‡ØLsj•Þ×RqR~/…~õÓ?Óì쎈 ±2ƒÅE™ð÷ Øч?þZ³ž•R¤aX­j9’Ö„¶ˆ?Ò‰åøŒ—”dÔ¥1˜dkºCŸØ´Hú01’žó…¨eø§ 7Š3tŠYÔ‰ÝsAÒ¦‘tˆF_:ÿŽXTs9Iyêƒ\v=U©]š©k9Ï´üи—6l¹‹ã42 ™P릚»´JÉ §€gÚE˜’¹öy¶×Ž»Ø5KP×/®×‰™óZ¬»wQØú<«Ì%¹afµÙ+[n9l&S®ƒšS'u“½æšñ/–xì—kYY]é{a Å\ûsm9›ey«m¶q›s—ùµƒ¯·ù¸»Úœy˜[þ›Š[ÙŽ»—“;›–;Øšû–Ÿ{˜¤ùvº&O!™|Qû¶…[Xu»z·8‚‡“†y[µcšxÏÜuQ¶‹£xÝ )Õ|Ù™&´k´ÓUž#»¨ÇžW:¸s½…Ö½ûÙ¾Ë[ÝŒ{·—ÀeØÙ´³º…©< ÐFô)—:¬é/¤÷z>a˜}v“¢·+ï3|Ù³E:±BÜ£¹hÖ£+Û€Ñ5¼ˆ |–<\uNµ„ìe›¹yzlwšŠUòSî_* È”›9ìãÂîÀ24ÈUX}Úð{pOLJ/Çw¬{Üh¥ø†›Z¤žúӳ߆w¼+a|ÒB1Kˆ2GÁUªþ<š¹ú5ïX![н|©Á¼¬eši¡Z„ñ¼ÀÐD=ÓT­ÐÛšIÉ–Ê z®Ïø¦x‡Äï:ºkÏÃteû::ÿú°ñØ$=êî<Ñ0­8Ž‘–J/`Îå¸?ƒ˜#v¤OQ¼E“þi»º1zH½›yÜx\ÛÙ4ã§ý‘6ž’$\Ô=y¹ü˜úÔÃù7€Y|£3X» ¢…qÞà]²¶xÂy yœæïÔ‚Ê™üçËQd¡œc<Ÿ­JÙ‡:¢uœv騼)0á¼f«X‡oÔEÉÚ#‰ÐÆ]¹ë|¿O°L‘º±1=+G’ì_LJïúîU]¿Úº™®U´œA^ªõ\÷ZÓS}_ˆü¬Q½ñÁ˜åÿÞºË}òBPe}=Þ– þ;ÛÔÙn÷Ùl]›Ùφ¡×½äñš5˜{ò#¼ò³ŠÛW®Ûõmö·ïÜ[UëÕÝŽLÿ÷?ø…ŸmlßþÝq_"'ù•ù™ph ù¡?ú¥úçí’˜è=­åÃú HëŠùøÛ¨‚ˆûuû1Mû©Æ„ÈûÓwg í‘•ŽCvì<_À› ý]°ˆü;7&Þ @Š¥bòµqlFeïuxóî?Š#ùª+Ûº/Ë3]Û7ž·’Þû?0(tÃ#2©\2›MJåYH«Ð)F#‰F¡[*1)–Êæ3:>9Ûî·Ss€Óëö•ñ®ßóûþëØUÅ—”œÜ™WaÖÆ£šä$eå›_¦æ’á¦çgLè(ii&àbªbÕ¢…!kWbìcc«%n®î¦©¯ïáÜïðžþ(ñ1r2ͪ¢*—à-!#ap˜íî6wwŠrø¶°¸9RÞ¹úº§—c³v49,ü—»Ç=¹÷>¿Z/;À!óÄa¬ „è"Ì:ð¬Z¡Yª¢9ƒèpš˜†Ž"Yìçñ#‰ G†ÂGò$”*W¾Ð·k¢K2gÒÄŽåJ—ép&<ÈógO‡0‡-jô(Ò¤J—­éô©H ™JíYõ*»˜O·ríº-*V…;ÃöKö¬)­^ײmò&Ú¸r™k—Z·z÷ò{÷/`;>n“—/âÄ[ýnìøHÝÇ’}Vlùr?Æ“7sž1¸3h•1“.Ksèv©ÃE^þ½z´éز͠výÇv²Ï¸AÃvÅK#ˆÞ³‡‡»[õñcº“?.ü•o|ħ[ªÍ¼Nëë ²kÿK!ã-Ãg„žM(5g È_¤îžƒõîn¸Ë×´¼þ\HaÄØòR^§+ä#ËEϽ§X|ø1AŸ‚·5è]*‰ È‘64ô …Þs ‡÷ ˆdÝ¢TÌôwb†ð±2!‹Ñu8]‚$Êxƒ3¢d¢†(Rd^‹9¦øâ{1Ú8dA#I’ E‚CSÈc^Dd2ž“.9›Gj¹N[dà•a¶•¥—Ë”ÙN—gŠSmºù¦›bÂø¡š?¤Ygx–'Ÿ}úù' þ :(¡JÑ©gw"ʉ¢‹’¦œ‘Bu¨£54Z):˜ž©¤ÊD¦¦—j*¨£ã)ª—Ši©¦a¤«›pš*­Ü¬+®ØåšV­½ºuë®ÁÆÑª°IÌê+²“[,³Æ6{JiJJ7?Á%{ ¥Ïj ¬ÛrÂϱ‡u”AÏíØë²ˆëí ë²klF´^ ë¡q Cø6i/†í=Àß¿}—¯•©¦«§»ï.“°Â0óp„.¹!µÈk4(f<ï¼Ø¸ñµãÉpâ•ü„z)·"A¿²<ž!ÀÝROzù&YåŠ.N( ºÙ KòÉ}²~ˆ‹,ÃwˆþFIÇCËÊ8c̳TÓ*rCÝÒÖ©Lp*?ýJÓ273uÀb4ö¹;KÖjjÝõs{ ñÑí‰÷ò”;ê““M“Í2ÒÕü¤ÒoÃí3ÝSæxŠCum´ŒC~9¼v7+¹SœSn«å˜‹î™æ?~:Hqîxé»zŽ:섎kë«wËz칃®pí«Ðû¨¯ë»êeoûñŽ ?<êÅ{™¼í¾§°<óŸ;¿%ôÈûN}õ!ÏköÛÛm¿*V|¯µåÖ¢lb×Kùíïrouân´¾ è¯QB¼¹ÿ>üàW¿ùËeTâÒÀ‹ Ç^ƒ°†ØÒV¾%5¢þ^d‹`W&¯Ì|€ Eøˆ„7‚J3aÁ\–³Þ¬?þ¡ÚǤá±&Q¤m.¬Ú>þ÷ÁË…ÐF{Ü;èõ2h´¬l# ›"ø†ÄQì<5\_…2CEqwòÛ!^zH¢¢9ZÙÐ<˜æ4$†ƒ,”%CÝ„T,X.t8$-~0~¦£—˜´U|IPJ[âÌ8µA¦…SŒ"€ÞˆB+²‹Ž;t$~ŽX¸)Ñ ü£ÅZ¦ÀÐ’Al"ÙÈD"".ƒ–y‡Eû@²;óËŒªªÇOuÐT­|dÃ^ .Ë€IqLåW)«[G—Ý«•…)¾»³™þ¼¨¥2£ÙbºÆ˜ÎôT2¥½gYóš’ʦ6GgÇEuÓ›rçùf•ÓœaBgˆ¨©ÍqfÍö„4C¥ÎG«÷úeÞàx‰{>"Ÿ¬Úç£äé˜ù…k ¥_ ºƒVJ¡û¤§–âE@˜)Pf"З&‰h´"¦ç\î„'ˆ,ŠP•B( 8ÛâéÒ<¢2”?dí‰R„J£>ìcHI9ÄS.¥Ùm¦G¶It¢<}ª@Bµ¯ˆQm'Ì‚1‰T@ŽQ¦‹Ô)E¡*Öß±-?T]åþEüy– Þ¼ìûh%<õc³÷ÎjŸ=B’Ž»°½ß¯¾üU u£9­ð–`»«MØ¿§Âçw’@Éõèüíb,3Àçêb ‹2îÕ?ÿ®eþ â(^¿$·ZÓ¾nH~’ÃLzô»¶öÊy‰ùÈU±^ ­˜¿9ßј] õñ_]…”›ÆiŒÅÌý\Í \ñ›–Y¼]Öþ¥Z…îÞÀñÕ%ÑŸÚLÕiÕMÕÙhüŃ” Úï•`@ø_³M6`<éàT\ŒˆÖê\ !—¡èùÊ6†éÕ6!²ˆŽð­ »ÑïÉÂ5ˆGŠâ[$!æFè!Á•ÅåŸôQbAYâ%*G&–œlP"Áœ-(VâŽ"&ž`Ö©âKá"õX+b ,®ÿi¢(ÍS™æbqìâé-â”h¹qÔ‘ûc1c–áb@ãi¢4B›,zÅZ£+6R6Þ5zc`#i…#)n#9¦Ý+¢c”ã:Ή(ºã'Àa<Êc;Òã:©ã=–ã<ê£}Àc?®–9dV…äþ7¤ Ùãñ "mÀÝ=ò!C@æ^Þ¬^wY›7RdEÔ6^ÝCPƒ# š ]_%d÷xä]$â¼õ¢*:ÜœB:U>~dÀd” ‚Ô)YLÒâM"Ö?êä8”¢0ÖŒMҤѩ$®¥QêŠ,jŸ} %S&™SþZAÖVTdHÞ-(‰ñÍÙ[¡âP¾ÂVʇKv›žšŸ%Nv%sõb7¦N]$KÊ¥Ü\$\"HZêeNÒ^_v`Ê_f_ü%|&^&bêE^æcƒc>æ˜(&‚Mf§U¦e®EdRšf%?v¦tAeh:ËhÞ&e̵^ꬦr™æiBþ_&”ôOH”Û´5ÕgÎ& "dIÈ NÙL_V­X`ÕÊ)ñ&fúf®ð¤FPNm¢ƒí\pb-efAçXñ šmàó}U®âU¥jzânyçSMa)\yZ嵡'0Ž|Æf`²gT©ã{jàL‚ î(å•zvg~êç«db3 ÌHVeÉMÌ%a]×1ÀEbV‚šl"¨8dç@(ö¦Yiè‚p&,UÇ]öˆ žˆr‰’æbÞ•  Ð… ¡©¢.ªì5êMçbç…Ô¤RêBiJ:£ ÕZ-i§zêþè¦æâ©þš›’’XœvC«FªÂ ”Î*­Îi¦Ý*®¦¦®2éúª Äj°J)¯®±zF®+d%«¬-«É«³©´d‰T+7B뵆µjkêpk·fæ·ª™bdÁæYÖê¸Ri£’ê?M º>&»Ò^»~é Šd¿Ù§r"`¿òkºZc½æÄ½¦ßþ»Z˜Y'¤Ž_M"ꇊ+o¬â*È0à}Þ¦¹Å'4¬J¼ê®©©œÕw2e„ãÃv©§‚ì,ŠìÅ:˜L™,%rìHlJ„dÂn].côcQ­£ÌÒ¬½–ëí•h<þ,Ðvl³ÞߘþÓªV!Ämh+¸vÔz˜ÐNm=-gxì¬I-Ö>+ÊRª×~í5†í¢Ž-ÙN›Ö2*ТmÚ*ËÚZÔºíÛúCÜVjÛ^$ÜåÅv½^pH¤¬¨VV­Ùî Î¨+!b)GÒd*.îS.8æëýkËyX„Rî»…*îkåNâèAnäê¾¥ ŸºƒLF¨À%, ª-šþî ¥Þ­è¦êÁVlÆåO¦Æa¥@á_Ë:máÖ©ÊÖ }:è{*ËÞ¢jÚ_¤zÏðziñÙËžHþ î6eúX¬ìrá°.+xÞ¬ñv]…ˆep~ Žü$ŒQõÚ`ÓîjôV)Ý&.7¢­äŽÑ‚\Þ^ío@àÆÑÒÊáèÒìüÖí3Õî¶°×í"0`(ð/¤ÿLÒF°.N0;U°—KCáÜjð›@ÛîþjÃï÷+ÏDâ켆)ýFWþ¶ÚÑ®p-˜Ô ªOµUÆû–f û*xö+œö×õîG$Ž”êb U±X®o3Ͱ –p¶Ë ±Ïoþž'7¬7A1oŠ‚š%„òQuš¢‰]\óbeA*þŽð‡è»b±/z™ë`"ù®w±¿±»’îΉñg\ÉÝc±€:Úó1 ~eQÍ_ìn]P-13 JâùvTƒöðLxq‘|p¹‚–&îß*‡FVm"{‡'›ð E*·ä*Oq+»rü:)Ï2>ÝV¡ì2/÷²/ÿ20³031«BË2.ÇĆr2ëßòo3óÏ2G31²ä-S3Q*6·¢5ƒð6s3o3vrçO&É«à¾ðM‚³8Çì+K§~©³Õœr8{/1Ôój!ÐKZruó•ö¬÷1#þœIÌ¥ZÐ:Os£‰âæÎZˆG5Ôî9ç3“îúfŸ!Éñ´<2\²³ ŸëoðXÛâ> —?ûñ)å® é纜à ,B÷ó~X/ë†_åjtްG>ü‡×õ)"Oôƒ_ù-e}j'*ßVG?¨Þ8Í)nŸM'uùʳû4PؤM 襆t÷º´Qô[m'ýER•OblÆ`® ¿ó>\Ib² ‚´£Ž‹Ï¾´n½5»AZWMEoàpæ5ômµ>—7c3G÷sPy  Ÿ1 š'®ôá<¶j•42·³!vµ‘ÞaQ“3+cök³©_]Sµ«‚¶Ýj6jSþ¡eWõjg¶h¿v¶öiË6«¶m3m£VnK3n÷¶Ýí6¸÷ßs17r'·r/7s7w¡°54÷awpC·I–R­ßBKµãv¤]S÷­ ·`šóø`D›½~7x£šxÇÖI†eT'%úZòIj>›_l¯÷«µwǪ‘ú†l!koLß÷Ñý¶~'´uÿ4..(Qc´yŽ'ó=xx'¸kÛ±Á·ìâqVÃ,k#´´Q¸ÁXxmoUÈVXFrðš!G‡¸ˆ·¡g+x1ö–•ÍQ1PD5r&sµhåŸo^3Rò‹_‰óv‘£eWs8s¢·€+t’ï¨i#y”þsiË1e¯î—ey•wçV—Ëé’;ø ò/†9†Æø…wy‹“ùïæ1U¢¹”«ym³9ˆóØŸ˜vP\빜{ù‘w˜Owór·núŸ[+Sy•³³s J¢ +aG7pz¤ö65[ú¥Oõ¢ :Cow:›«<{W5«w§÷ô§÷jæp²¡3O+ïÆ¢zª?q ³º”Ü× ÚWœGߺiÛJŸº×ú1}9Ü ê‡‰_ñƒ=uKo!§ûJÞº{;o#fn-â÷jl!F»´‹ò¤³2ŽÀç›J«8«Òúvÿ/y‹ú·ûµ÷÷VÜ™oõ¹oqºûBó-yåþ»OÊ” º —ΟyKYúº_„K¸Ž]®  ›à¹pŠoàþ; ‡ûeŸÝƒ »6§.:¿Ð Ø\[<¸Ä;˜ÃÍ)ø˜ï.z_µXC#?;ɧöªW{£ß9·ç±^™ž²ñÌ·žÉû ã|ƒò9øÂozÐ# šöÞôµ¬>£Ž—’X¦üÏÔÒWÓ«{û\}Ö<«ß¼¾w½×_|¦Szo{{Ù'‹±3ýÐýÚÏ.Ø»÷CDÝ3†eÇsDbïßZ½ßq}ÜÛóÙ'…Î;½nwã›Ó™KâO;Ü~Î}~ýþ»Õ4 YÐrZîç{e>ä¸äƒùæŸ{é¶þ.Ñééž1êçül~èÃ8Ư¹óá H üŒ¹9[{‡–ÚÇþf½XPîòÍåk¬î·ûòºþzêØiøm²ù=ðsðè ýÞ ÷^lò§øò}óÓÅi¸;KO¿Ù‰ä|º}%!/vûÎ;ùz¸§O¸ÃózÐ=À*<ù—Vhz¡™:ÈÇÔåö‡QÎÀYoÞý½@Ò4ËÓYÏ@MIT¦WêÆs}ç{ÿ…=KÈxD&eÓù„jF/jÕzÅfµ[n×ûýÅcråE?a®×ÌÍ:¸â3Xí]Æçõ{~ß+J”"4<<²ù[dlt D”ÄX£»S¬þp“³ã¬{ü Õ‰œ< aB]%Ä$}… 2e¬ìLpÍÕœÃõ•Þ¡­­U=VnÒ%v~~5^vÚLicShiëÝô¤²„•ž–L>W!owÿ3__’Uù~¿ÇÏ牗·íÿÏÐLß@‚,ÎD"p‘½‚ >ä‡PÄ~ ^Ä‘"%Œ=~ä£qc‘ê,‚D9L$E0-]¾„SæLš5mÞÄ™SçΗKFI÷™µmsìuÛ…¢Z.† lœ”ð´BSR÷T`õÑJ‰PS~ –«ÐAÉ¢òDC†Özqä,EànU sï<°›-ëÞ y“– ÐkXÂ…þ!ú<«ÄlbtoÞþmƒÓd^tŠV+JbÊåǽ(«ívÙsækœª½4ÚšjÉ1Šœ qâØ†mßv˜1€Å» Õóæ˜ÛÚ_®Ž‚ç«ÅpÍ«n›Â)åéÐñZ¯.]8¸Ì¥fŸ­[üx•ß}è}ÞVêå•£GŸlüo|ÐÇY§=M7î~äl¬ß¯Ì©ù‚ó/­ì|Э"òd07óÔã =b/)¤ÞKN>þ2DnÃñSJ@ ôl»âð¸ÚûeŸ ¯Ag„çÅ )¹ñüàcN93ɾ7¬õ ’ÄÔìPÄ9’Éã²q¤)AéÉvŒŠþªÔ5Ë ËTŒ¨ÑHÈÕ.ÁÊ2­ÞlNÌFdê5:áÄÆÎ¿´‚›îž2ÍÏ»¶¬r£+ëDi-Ë0¼Ê­11J64Y4¤Jè4PK”¥-oá 8K‹á¾×:c3²:_½³NâBÔÆ¨ÍäÔîR‡2oÓõx"¶XcE¶&Õ£É\? î³CKŒ¬H˸³ÃV¡ÌVWåvå²E_–¬3…g\u,µ«¸mÓÎTåõ/O Îû*áq_5}´ÖÇøþst]ÑÝà\„Ñ3¸aD™mmU<—ŒvªlæŒ6\1­Õ6àp9ÆV`“sør…Rþxá²Jf9‚“§Ñ†Ð¥¢¬Ø-™õ«Uc«FÙÂy:äQ[näå’RV9a¢—6b-‰40U}Uˆ´wëEÖ%5+m®x§³•g®ûšé“æ mfÌf›„v*»°ãn[£­T;ͺ—¾ûºÃ ïï½ï雥¼“|p g%qÅÇômßÎûÊA§’t>1óòé͉f|Ç!'½ Ð;`Ý‹7í±{ùŸþyߤÔ‘2ä[eÏZE›½×Ÿ@0濱H}ã©ßoæ·ÀÛ$f÷K—Ðø¹­ Pn"ž“¶Ó™âåoAäEH*ƒ{IkÏðÄv¤­_)š ’DÀ²‚†)aâ7†ÌÑ®/dAçn¸¥I¹n„¢êcN¨2YÝJ}3ËS›¨r³HI D2“âå®fE.~0‰ÛëCÙÎ7D׊/ŸË_ÊxDvu‚©ÅK½¢¡6؉tÌHÄá8/l5ˆY餧k¥o, ¯°ÅBTý‡Þqã†%•Ðñ‹ëh–ÏVõ±^ÁŽZ’ZЈÃÈ ‚L)®ú*·Hœ©þ’Œ4H$%¹2X"ð’&Ùb.û÷/®Ñ }ºœ˜ù'‘Ícþ²ƒ(WH°×­°–Cá,ÙñL÷ÝòMlß.;X3¦\ †bv:&ÁU¢ŠœÊ$™&¹IͬXFÒ¤%;qèÎeR—T'í¦˜¹Šu=h'„Îõ9+|òl§,á„ÎÓi° Þ=íÓK4f…E¥¨=3 ™oò]áÔW¯ ÔŸ Z°¡.£'Þ*…“’0¥~3ÛÜZš:6n¥,éWj 9^$p9åBWÚS ~b§j(jRcqTÜÝ”¡c“JSüøBÌUÍ“s|/5øJ ÄI†>4êK‡¢T²–Cþ¬]q*G´ùÄ MK.`½ê½4¸f5vwu’EäÈÔµ•Õ¯[9+ÜÒÊelƒjÞ ×ôÑèl?S¬¡\cFm•ôCÇ‹X׸(ÆÀ¢å¯Ÿe_Ñ1Xç¹dë|U Ké°å9ãckùZûºÔ~ȆìDÜD‹8Ðö6ŒýÇÆ¥œÕöŸ–5éØ ›Néy.…Iš¨m«¹ç¦/ºà„p«ç[î"Q¨ %®ú¨êîo€úÛ.ÎËÁó’o«å¥ê'Ñ; í6¦»÷ÃnuDÚ¶¾µSí '&®æ¶°Gñ]n,]óÂÀ ª/ür#@VÕð:ü„D¿JÛ²ê÷7þüU®c¬¶Íx%4ÌklŸXwQ¨ Å”í¢"°xb긊ù°ŽÂØ(ÚÊ4l'±KƒäÍlòï¤nˆa!dPUH†#ðøã©Né¹UÎO¬‰QÊê…G‚ #»™o^®%”ý‘V2'ËÍo†sœe’݇Ú5jé\m&eW-¡¡³²ät¢!Á—ÛäQŒ¹ËÛæ¡å©f*¿&˱9ij­>gžt0[;LdbkEêô“:µù¦×¼Ìäê#mGG?º«¦e–dA:EÆëíd€è‚윿~0®JT‡Áš§­võ8Œ­´Ls™Ö1&F5)]×–ØœþLì°¯-¢QuÙÔ@v²Ãñí§Bt“å4Õ,:¢3k4º—&³>k50‘þÚÔµ÷»é²YÜ;±âcgtü®g¸ÿ]p„¯‡i?}²_É­…/¼u·ý\š¢Tp.|ïµR€S&ßÍw)”ãœê D9Iü½>:w•§v$×ɈkëÆ»3*ûÙyžöD€Ø™6ùÿ‰Ï¬»]ðQº­í¢ŽT½«œïKðþ;´Yˆ'Ó"^î0{ìOåýÕ˜ç#óláYh8ˆÍrÉç÷øT(™ºž±‹k¬bÚß%öŠ”ÿHöÅScÇ¢÷øU=¦®–2àÑÞûêUÜøÂ0»m<ˆFþ²±|ì—aeÏBYú²3ó[Ä\ô/³›_Í õYo&ç“!úFdàôí,b<'¯T¦ŸÉv\ˆÿ[…N´{šˆ@¬¡õCökQû4®”9btF; 3Úï´¬ñ?‚Iâó!6Y ”,W‘5Ä‹JÌ€gD–óÃ7j39þ³ÌËÄL0¨Jul–gÁ¶ÃAA9'ýK:¶2¥Jü?n I°êFþ;GB»"·»Ø;tŒÌ¦‰¦+ÄÈߪ³ ,,K©=AB~Ü´© D5§ì?“$µ¡IîÐGÖ 1ΣD•LÊéÄ ÔÈÜtªÛ4AÏ[Ì,)íTAü/q4´Q ÁdÎö42ÁúcHMü/ËËÇ‹ãΛòÎl@xyÀôÿ\H¹Ç'DÏ~rO4<¦|ͱ=øÛ:”/÷.„ÙÏÆ»ÈŠ%tkÎâ³ji·1TÆŽ*±3t¡Ê7ëÄë‹Nº-3B2J‰bºXÜÌüªÝ€lþ‚û š”¾¸DœµäÑ®"Ò V$PQR?°P#=Ò6 ¸)ÍH"U»î4±ƒÄĨ<ɲÌÄSÁIŸT— µRoÃÒ¾ãÈ^TEÙÂ>·Ç}4"½ê¼$=S‰KSÈ[ÓË«_TÏ`ζK&㲬Ƽѣ«½'Å3½Ó–ŠR¡TÈ“ÇBrWzÈïGñ)Jû#o¾ò\9[ÝÑ%-ÅU[£KdÄW²ÄËDÍ,=Ú$L ðLoÌŠt,%ϬZ RÛI>H?Vj*äd=予c*ªÖ°BÒsÂà¥Gu¯Jîµ–]eBfã‚$ÕNF)ýÀ¨ μåÖ£[[~Ã5Ñ,Û›·c»À¶à[íC…YYžeÎÃÉu2²ÚäÂeæfžœ˜‚æhVªivÜjN(göfï}å$þÕ@¹š½ŒS®ÛGë¹à%Eáp~nn]°=O}ZçÙ5ËÚEØAŒgyzàPîÔ¬Z-¿%L¢üeDB> æ›èºh fâr%T6¬Ç­SQ)YÛ¶X` 爞çq¾PtQÖ+è|ŽÚºs݈dåƒS^‘¾â îžðMiôÖ·£Ö”6a5N\ˆ–é™Væ­-Õ;6ÛμÑEéú=cŽé }`²Œ`ÒàÓ}¶»uE›«Nd®êw^–¡v[vƘXQgÂÜRÜã“.Ú½Öå’ià±ÌÊ.†`WYlK ³W¬ ²Jñjh²\7†¾^—·îP/Ó#º¦ÅAÕ¾,ã>¾þä`J-¿gA͉=0û<ÞÍZ،Ѽð“XP#aY¥i‚ª*&í˜pêæPÏLOÐܰ<&0–ßuUìÉ.c–=åSâר ìÞ>º}:€ûëXêªsfš­4:k;†ÁâäÙbº4<¦ä}Ãy$Né†7ì>Nêî@˜èš.n;\Z¨Åß¶Ùó~äbŽdõDåí>[\iõ.aý}oKm°æÝð6îke‹FÛ[åi‹Áõ6аUå)Ôi©%p§½í³œÐf"ýÞoßÙDÕ¾t³Û ˶Y¨Yhòζ©|"bö²1\¾p`Fh_Ê0&ü_ý&ìγê }hþ. ŸñaR¿q7dj __Çг²‹¾NãèÉ©~S4jrníª(·«³Am"‡i çäj}1ÌöFº¢Ý²|Î9M쪮r6s¥½r,ÿi#7饖7.$áœÁ,!^lôC,:æÇ,^‰¼¬='^//†!gó2%éI<è§§|žM?miVºj1¬ÞÚ,ã¹kôærÁõä§.tî[-jA´opñl‘Õ¸ïíÒFù”Wy,øêeŸ?$ÞâC“k×®ô IcÙNY–õhKmå’gxPïþåäÆe dîôöì<îÙèæc›çî¡•õû2ùòñ~AbgpÌIa—ï“]tŸvïdŸ¿õMìz¾êb§YWðùvpÉãnŸîןÿ× Çb¹âåWUr4ÓåLw)3¤÷Ê>ã2Tøºþ/{49{Hœø1Q\Õú¯zZìl–|»_f¼wf¯ÓÅ/“|öôj×é¥òæg#9}®îç2ßN—÷ü"×rjæòyv)ˬîJ}Mw9EøÁPÒ€ýjýytÝCʯsÃtº›ÎÁåçsÌÆ÷¦^ÅÚ«Ç~/*þ)­>BWí¤Þ¤ôëÍ}Iÿ×¼^Ì+pLåMËÏ~¼Ó|¢ý]Gz ~õnåé@¶W=uœŽÂa#€Xh‘Œþ0ÊùÂ8ëÍ»ÿ ·Pdižhª®lë¾p,ÏtmCV¨ï|¯¾ pHÔŒFŽR)`6Ë òÙ|:«•,”šÄJ¦^l4ªµn¹‘þãY-Æ­o¥\q>Ãïø¼~Ïïûÿ4rtƒ„@…ˆ‰?\WldgaeUdc]’”h“SfT˜^vnm¥Ž¤§‚Ь£€1$¯'l–& ¯´-º·°¿ÀÁ¼­Å;‡ÆÉ„G ¾`Ÿb²‘¹”ÒŒÒØIœ’M¹–ÍÝáÞ·Ù‘ÓÖéÛØÍ¶}«Êƒ»7ó,îi/ÌÚ(ЙpKõ„  ^¼xÈ*ôXÃXJ¤GlᜇÔèK kœ5{Zœx¬DNÛÆ’#·qìR‰Ó%ŽÌÝ›H³&ƒ[%ÌɳLj@ƒ J´¨Ñ£H“*]Ê´©Ó ~pö<ö¥j˜ŽŒÌ”"%%dþª˜oÚ0yV“X–"¡ÀܣͷpqUœÊj'Ý©nãêÝË·ÉÜ»TMâ0g%eavÏ>‚ÒÊ +GÇÍzûî«©¶*Cê˹s…¿€—…¾›×³éÓQA±r0¾r¨´~±ó‘›¨Í·C2‹yÚË—ƒGM®ÔÕu÷,]¼¹sÇ•cp™ø´TçÆ=îš;8lÝÂ{ƒ“ ¼¼øçèƒE—ÎÃ.ûdÌÓËŸŸFõ{WV¹:ÞþØ–æ×³ØÆßd  –U¢AX(%…‡ @ôE˜Ú}E¸Ga]f¨aö½߆ù„∦­w¡'*ó!‰,êe"r+¶È 1ÊhãM¦þˆ¢ŽÅÔxãêå(@i¤|/ò8’:õGÖL•yÔÝ`Šè\eTe–çÜä\’£yä˜d–($“K¢™ˆ;¡UFdþ`ÔO~µøÒMvr7‹ˆ|š˜e*è[~êh¡šD°9ÞU¦…›J v§N¤Ùx¤R–¥-q §vqJÚ ¤–šž¨'Ѝ1¶˜~[é‚U›‹*º†›]&ØI¬eå¶Ñ<úÌdÜ™0šjì±f®úªÊöp©¯w~Ã+ŒÞÐ~Ðvy…•Õ’4™­ÞÛ«‹Ä®(²è¦H¹J2Ûl`O.ª`lqféß”Õz—-¸òzÝ›™á©/¹íþªkðÁ¡z¡»ï†ð,ƒÊÛ Kãk)n»m²oÅÿ~wÊîŸ_Š‹¥oµ€š'tz>´åÊ3~«ç ·¨0… 7¼,‚¯J«ëk™š$SmTlù: ÑZ- Ä~¼×Í<«± ÂÂ\gƒ/ÃÊ­—WÒ;ó RßyǶ Rí¡Îvfõ×'#\_Áö|zí€]ã¢[«­™¥ÎIȘ·¼9½d2noÆœRÜàÏj9®‰Kh¡„wØó©Í^ÎlsðÓS ‡.ú褗ÎÔÔ#6Êê>ꪶ Gî d¿I&ž£@9Ï:hå¯m™gí/ wxÔ˜#™zŠœwn„ÜþÐç³<]ÔýªÌü]{wÓ¿¿.­öµ7B;ö– ?ÜØ-ží÷Bß:þ§½a‡>‹šé<«ÑçOöôxõí´3v’ß&hÓ¯õe‘ÁݸÊ¿úN}´xÜt ó90kªŸršw?üèïƒr¡Û€.÷Zå T* ØxÁNkv- YÅ\ˆ@äI*†Â‘aÔA†€ð‡›àßr¨u´êñl{¬‹ƒ€8Å&ÁáêASÜë¸V(.meéàäð†­¾aJŠòkG®$´CsõÐY@L#„X55Æçm™KcÃtÆö¨ñŽ~á™G$¹‘k«ã"ð(G@Z¤„Läæø'þA’n0" '…z k\âYì’‘â0ÒˆT¤(IôIÒ8Òa×+Ê6V¯Ì nWË•œ´f¶Lº²/¥lÒ(w ½\âå” Wú®7Ã'. RÓ;$—­òMR” Åúu–H‰L¼Ì&º|¹`îl‹ÃLš Ó0+ž§MÆœ œÂÕ+tb.Xœ7פÍznÓöó¦O²Â pÍ[¶!ܼW~APrìóÒ¬NBáS!¡´§D‰3Ïœpð~+f´ÊBŽu” ø0è%<ñÑõÑò×äQD'ÊR·=”‡úô?ºÊq.®Ÿ“ °Ð6Rœv ¤c»®Ë…#y½ù }_®â–1öÊ^™|:ÍOKz/ðåK€ “›ÏúæF× Îø+Û2ã³\ÖuçÛ³qû|Pû¹¶¶»¤G#fÒwVqÑËp´ª5ÛCHy¦u.u’Y‰è‰…“þÓýó§e8èÅø”Ðæ êdQ­W²ÙòÄÖ]µ=!Ý#Wëª' ° ½bj÷ÎÌ=VšZ° VG5€Öqu¤HÅ.Ÿ Äm̸æ²zt[ÙÙd6|$­&7·“{°«KE˜Õ(Í0³5Ü3Ý ïèÉ[EήãçËð†;üá]ºe;\+ÏÚ´Ó¬¡° ~°ƒ$á´7Çi4ñàŽ¶Ð’™Ÿqé,>Œ¼ã%ÿÈ'ýòd©”†¼± °sNÜš#Ì㥷‡"Nô¢ýèyxA_Íé>ï¥Òa4se àêXϺַÎõ®{ýë`»ØÇNö²›ýìhO»ÚÑÎoÁ |þÚQ VÛGð¨ß“¹O:Þ÷Î÷ÎQóÁnµû®ºª÷ýðˆou`!¢‘ þKS_˜ÞOùÊëñ5'<Õ'oùÎ{¢˜Ï|äUÊùÏ›þôŒýÈ5?ôÒ£þõ°Œê Îzœ¹>ö¸Ï}sg¯ìÚKþöº¾çÏûxþ]†¾ò—¿ûâ;Ú÷¤>ó§X·ü=­ÚECì|AŸIɧ¾ø;¿ýºÒd'ñ»ÿ‹ï£Iãÿð³áý ÜÆo¿D9× ¹õ³î‡(á'øj×1Ø‚V‡9ôêU€Ó1€8 ç>Š"I–V_TqH?ÇLH"HsLÇþJ%¸rÅ%k Ö€:#ƒEC)7[ 8N:ç,˜oèT!(ƒ@Y\ômtWd´¡EÓâ㳃:ÔƒÕ÷ƒA…tl¨mLØ„RhÒ—…\Øf‹W…v…dä„Ü…FÐ…h¨Kb¸_d¸wf˜&i‡Å¶†õå‚Ïf†[(‡A¨ƒthpmˆx?˜‡z(ƒ|؇rc‡R&‚8ˆ"Xˆ†sŒ¸,ª²ˆ‘X€Žøˆê‚ˆxƒžS‰žÈ˜H^šÈw†G‰ŸH}³TK VIÚÇuGÈFNaŠöð‡¯Ç‰pxŠžÈ„b«ø!üG-Àè`´X ¶{ gŠº¨|RþT)Zæ-|•@4Ö¤†iWŒû³ŒíájÊè¹g+RCAˆE9PG'ÍO(Ŭ&ŽÇ€‹ò˜†ë€Ó˜JÕè5*øŽBS ñX†‰t™ I ÁWe=lµóté@ê7‘þ(Ã@¹€J‚7Š$#/¾‘—ÑŠ74\7øB9ˆ‘4sŒËw‰Ú䑪ã?QTâù¨QOSA¿“E¥f*99Hv“£’AšDaGù“”²uDI=™3‹ô •JÉ,ÉŒ÷”ýS•ª¥•–ç’JôŠJ„}ôá•mÄ•©e–”–zÃx$9†ºÇ–h $j™xriTþÐx8ä¨dGÖu WsùYyxwÙ``Á;—<Æyq˜™5˜}W˜3“Paæ=8FQW‰3މYIŠ_"æä'è—™y’¹™XÈ”BIQ ©g%ùW˜Ù˜íÅ}uC–±ˆšžÑ™nø™R‘<9„Ähº ë¶¹Š•„›Œ©š9”¥é!°8×Ñ)ÊÔ3|éEY¦œ±ÉœÁ”•Ϲ9Ù-õÇ;=c>.§Ãß䜲yrÄD™Ã‘„G’è¹oê Šì9Ž4ÈUMg“ÃÄaõÙ'߉{§IHà JûÙšìôšs’ZVŠŒÞ)›Ld~àtfKp”󠹡°· þ¢Eç¡æB…ZH÷‰ŸNI¢aò…'zG:_ªŸ/ú’,zzŠG1ª†5ºK;j€ùI =j|)ºOy£19¤>ФŸ—£0ʤP©¤£ô£Õ7BPô›ÍI²È4ÉävFe$TÚdRªHaSˆk;6F&Ÿ(hb¤¥[9¦‰T¦Ï6E¾±Zƒa©JIöLH¡&xrªó œT ¯°„9£Ðúhú±*¯½u¤€ZVÿz©ÅzJ»Gûq D!ëH# B)\';x%뙩/›?-[3[±5ë‡Û|¢×±;ûs1»›¶ªmu³K´R׳ I…´ø£´K«±íxEŒƒB±á§µA°²æz›_ËxUɵ3ˆe¸sžî赤 ´)Ón;4ÌÄ]³VþõjœÅi©ÅH¶r5Ÿz«ªÊKzkGwË郶xë–`‹oJ¸$/ ê·J¦CKœÕº¯úòŸÄ@Ñš•Kž¦p©çw¾ßõæ†ZÊÈ£Þl ê² º”Œ»øŠV^”5“ÆQ(tç Ê×}ÍçéIÊXýèWËeE«Ëkø ÝV6Ý”þŒé¨®é8|Ëÿ¦E¼-hd™ÖM¤¶ü?öiëÉÚ’Û“Ž’ŽìÛÜ^©Àý©çiÝÆþ~ >ÀÉnô‹Î¿Š=9íÙóÎç½çWö®Ž=î„ìàð­æµ‰ãœêQ*à}âÞ÷ßöÞϧä->Ê/Žïžð—]ð ð îð Ÿ©Óñ¿Zâ,ñ¾ñÞñ#íñùò.nñU·çgÔ’ê‹ñMrCmò$òBø1þ`[=ãN‹b|”ñ¸0·.?@9/ó!Ôñ³™ëA.í;cÁÓUvä>ìe|}š=KIíÉ–Z¬ñõžáI´¡×&’p½ÅENŽæÙ¹X¼e—Uþ2Ýo½™½YS؈e lòþ§vN„ã̽ë¢xÞ¥5ÏV¨@i ˧žGÙë›R¯èk)½*æ"~÷Cô8þ£Ì/Ô=¸—8Wº/ª/Ô^>Ÿ¥ÎCVé² Ò’¿«y@6Ô¯Nbé„m³ž¬‘mk×e•È=Ø Ê™ç©ŸÑ«Ÿ®ÈîíL„ÌÌŽ—£žåâî×é»ÍÿúqëJ£1åhú‰†ú‡?Óï âEÄ“`dµìŸÓÅõºKóJýýæÈ0MôI þwÍþä×xý­õèŸþîÏO ÿx%ÿS—Û-9iµg½y÷ Å1žMÕ•m£Žå™þ®íÏõˉEcâÕS.™ÍÎï•N‘Në›Õn¹[(UÉîÝý’Ùíj—ÏéõÍÚ×ïËvÿŸÄ„oÊ ð1Qqqð²Í‘’Î1³¯r“³ÓSç2St4h’#Õô´ñéó/”4ö@ÕµÖö¶Vv—wÖ#‰¶U5&WI·7Óø8ƒ˜¸9Zš'YÙz¹Z:u˜Õ{x{˜üû;â¥{º©úšy\þ"ÞœFÝù—Õ£ž #wïîéwÐ\7qÊãGÎa@& æçÂ?z8Ìh´`èá9‰#Q¬xRLÃTýæS‰\Ȇ$w˜Dþ9æbÄ–ÀêÄ·p^9‘;³ÅLiK¥‹:<ª“fÔ96oV5ò2£È§3±æó)” «.æ)P¨híÑcYÖܵþÞÂt9l^/bÇöM™¤Ö¯lgb¬·U¿G&å\j÷nÜ}’w†¯ü­·Vø=ìX]Óf]‚Ù ¸}‰ ÌàèîJ߀î×à·{k`vå{8[Î4»Íßp=sxa§Êmvb +¶'†OÞoãeõ%ù㟙…lä’k–‹éFRöuÖ¢‡-ŒT–aÎT襥M6çÿvæ9ŒQµù¼ëXÅÙÓ±ËuWµgÊÌw5c?º™hrz›¼Ëž~5ê´„¥×c¢ùu W©9¦ºkö¾[AR=‘84<÷nTìxMC.«xç~Û;soÉîRºÙí}WnqÆ¥HØþÈ”\u@ïˆÃõÓsN=ö«lGw¿œ²öÝÓí=÷!‚þŽÉÿ<ùæÏT¾øH˜wþ#èÁœžúìAŒþ$ìµßÆz-½ÿžüˆçÞ…òÛ ŸÊñÕ?@öÑ×Ã}êÏ·ª~øõgNþùÝÈ¿y÷³ÐþúoK$pç¦ò4Éá€(`)Xœþ! tÊGe¾_è) ó‰`÷b•+Ðq,iââÓì*¸œbp•c]d4e©Ì´ls›šÔ¹Ö6¨öð`übÕn~ÄUÕ]ø J¤‘`u…P¤”~Z•Âð V3Ž`ˆ¸ž”®o•JVO^æ8ŸpŠjf;αŒþ俟ô Zi3bæò•ªÈðð[M #LfXE8-‹ÓÖ¶­eMij›Ñê´ÁFfïâÚk™¢ë¨K šgF©MÒ7`ô#M®HøL=ãºÚ#åf¸1¾’;X3£+! ËYe¤’BJ$°$‰´Kõ‡ƒt™L@9Êi”Ò”s×KV²–±4ãhi²£ù#—"ª&*W³¦ò–+\1I±lš²2¼¡KTs/îØÍsglÛ/ß7ß”mˆòÄÀò&Kð¹±7hSæuÍOnš5+'@HRb‚ÚÞü`ÃËE.…)Ô¼Ûè µ-5Šqk3[¨9ÑYþ¥´Aôãk¨5":R®†-µL{!S—¦´iârº‹Þ´|=¥(P'tN6©7*ú~z;£Æ(©Q•ÍSK „¦Nl©¤¸ªT…—ÕèmuW^X¹z:±æŽ¬o:ëœÊÚVRµª,”¬%ºQ)ÕV·X«ôÜÚ×äÅ5LÝH8™+JQˆ®Ø+$ú¸²Bްn‰" ‰+ÁÞs²~U*\›lÍËŽÕâ¦ÇÖVC"îQŽí;iø ÎVÇšì4'ùŒIÊŒ5Ihf5›«×v¶4àDdF85hŠ4”Â} ² ø[çl!cdi¹ˆÏ}´—@”ŒjeÛ¬þÒ>4"}ìí[ËÖH± ˜ˆ»&ËC¸äîä„ siÝÉD‹ à­îÇ>‰_㈲‹ø%™W<Þ¢–—¯Ë=(àÖ;ÚeÒl—Ã=,ʬî-u$të)PІW¹äQ/B#k`gÐÁY”°@IìOû.·aãŒp‹wû¼ SYâሉ;à§1 !>®ŒKlâ6¦¬µÜ£0g*÷ŠQsj['F¹k)%o4­J¼ñlÙ¸–-F–{l¦‚kµÍŽA¸ÈF¦$’“\Ú-i±Ž[ñ…Y›%Ê ÄaªÊƒÄaæ“+w“Û€³@³¹`)ÔB]qç6ëLÍŠ=4› Í%Gþ‡+Ñô¦9ÝiOÔ¡õ¨I]jSŸº²‘>1¢…jW¿Ö±–õ¬i êIûNÕ}½´ÅÐk_ÿØÁ¶°K0lcÙÉVö²™}ìb7ÚЮp®ËºkVC€`¸6*MíYûÚÚVÙ¶çm©‚›Õ↹§Ðms{éÖì^]¶åw¿{EèF´ºùVoÆà;ªú¦4½ýÎ ¿w¹•  ðÖÅ»àDà7å".ñƒ'öØBÆ~LˆW¼¹UW›Z„\”n~æ.µå㎓t䙸òbNrqòÒ^ªrW±2Iæ2¾üá5/ÈÌåDt¡;@˜Š²Îg 2þ]G²ÑÅwtëLÒÌoô¯g õfH=ÅToŸÕ5áI®gýì÷z%ÀŽ`±;éíd‡Ž:Yh1×é»cÜ(H×t¹×Täo@ðîÝ÷M´½¼qç‘âå¹â~Hˆ.ãaDy«ò¼ú¸àxÎ+ó™GÝæ?Ï—:¢¯ ä;kù¡>†ªo!ëëzmÂô²_=éqoû ù>æ¡×½^hWàÇ÷°>Nyûãèùo,v6ùàŒóÖÔwä=¶¿|ß&§w¾- jÆ—ø¶1V{¬„_ÎâW5ú×ÿÜ ]=†¶ºdS¹i³›¦«üT~hý¼OËæ±Äþõ^¬µtµªF´xš¶.º °ÀP‰ÿÊÉKÃÚKTRiæ n<ìé¶®ë>쟠ùp?O½éŽÈ©ÇÌçÆìšnÈRpÕ2Zób«ÁÎ ‘®Éú€Lšp0‘tyðW|Pð¦ÊÐ^J§Päå_.jÏò)=¬ ’M U 1Í ÿ®ý6î Õd9p ï¼jÍ ßeí ±) ›pÜ ° çæêÐ"ÖìòPK" ]Ð//íg°ÑïøðQèÑ% ûðç+ñqñ %±æ6‘9áýJ*þ`+Ól3ŽÑT貊ãñþîjÉë%ƒok ㄞ€œ±Dq÷j±@Ï«KnÎ@ 冉º>ˇ†Ã`l —)tx¨üt°uÊôà}' “xî Š™žeÄÜéËi•Èè ·ÑºqŠ.ïL¹.ÿ(ã¼Ú‘üÜÌ3ŒÉøñçãqòzêÑìð¡0ÃÙQ¾dÑ!%Òå”° )Ê3’“‘ÎЮ &ƈ°È˜ïD*£ÄÉ"=‘ò£%åMÄ2˜8ŠúªQ£â‰ M+]€>Ч¶*ÖVžŒyð áD['—~’xƒN—uüDÒ¸h×aó¯ˆtžNÆÿP<[î^÷+ WÏÍwÛåu-Wak ­;IK“ÀóäL…§QcW‹zWmÇq‹–mFöf¿õ™¦ÃøsaüCís¼Zþ7Ñ87p=×åfbM'CKöEGd-0BiÐZ 6{ÿ§rËÀ7›3xw ØY68˜…Ò”‹L €[–$æ¶x?÷„¤SÉ´Oj«†tðÅj«¶¼U¡ )‰^¸…ù,Z+8vLx$P8 ¤Û€xq'X€6i˜4ŽN’`mÍôöT…׊¯XN±‰/F‰sˆÀzXŠÀìj.ý °sés¸}§–åøL-žŠÿ®1j˜z½\ú¬™êŽx‡8ÕxËБ¹<©¿*¶a‘W¿‚p}'lW†[Ñø3w‹3H‘ox?ÓcÆW‘ Ø[Ò3„Ǩ90’%Wm= þ6¡Pµìضh¬•¡dFÙKÙDJ¸’Syg‰éBSÔ‡p Æø‘þ‰Š!Ù–]vãIz]XÏÔˆP§(ʘ¶Ÿ@׋“Wš‘·þˆùŒ‹÷˜1—¥*{•L&j›ý8i¢ë‰I—Œ?“ƒR×~Ç6MŒ;Óˆ¿´R©‚œ•êGˆIÙvßø‹¥¸tÆ?zñ•™ãjsy¾Ù}a÷D›7]÷ô¯».V»>w(´À«Ç–×8^>zÍ—9ç9T''°X¥WÚÕhù_”½FÆlp.`Ó¤ý}mÔ;Ç·¦Ëw9qº#¥Ç ÚŠÚ¨©“Z©—Ø™›?Ìjê×þbE s®fÿS¦»”£ªú%ô·Ïxj¨‰Ñ§.˜w6k–Á¤ú¬5ت-”CëR¬Ãî5²–ẓËlzÑ:šðú—gWBi4¨k„w€çÚ‚íÛ̹²âkSp7ŽcI›ö'›t˜q›Éµ™ÛK²:§Ùé¨p¦Â±5P±I„›O˜>êù„I»´{!Q;µádµ«Íµ_Û[·ý¹›‘·'(¹·½æ¶›~‚{¶‡{µ‹Û¸1Ñ)W¹—»¹[,¡;º‡¹§Û«»[¯[ºµ»öâÒº½{ôÀ;¼-sß„´±-º[ОcSž£Ø¹šÝ¹tÙ¯ì[²lþ7žñûO—ÍÛøÈZïÚ‰\S_¾ z"vqvõ;”±F¡ š¿\ÂýãÀXšÃ;|0L;QÈ™—YŽïˆ‰åP ETi°™Ø£M¤sì<鉤I\+Æ›Œj§£I4E÷²›Y{: NÄršWg:fÈ·?~úŒyËh§K¦}º»€Úƒ3Y£!°§£|˧œ<½—4|˜‚õó³·ëB=ï7~Ó®³ÐÊû“·zÎßṴ́ší÷’ë“Îû\f†Íh{é"ÙÍ×:ƒéL•]­C ³^pB{¢'g]Ìܺ«5ÝÌæÐoÂÈþ=Ĺ,¿r T¶g³Ù¯û5»ƒ[=Mû< ÕôÒ»üšlÝÐG„]{U8tŸy ƒ5²gØo¶ÍmXO±LÈùo³7¦³½8c”iÿhŽýP¥lI—ÝÚß\w-È×}P§ÔZ•ò|J]œu‹k›MÇ]æ/gÑ$maÖÃïßó]ß÷ýlÍÞ¯AøN´Gô¢d^É[óþ ž½§ËÉ>7‰ür“rK/;Ï#x*"^â^á^Þ7膧Q¾ãAã°ý-à/~ä!½äaöäËûãYêðu\»ýÒ=æe~ækJÍ“xçQžâÛÖ˜tþZis*“œã[ãéÙþ„Ô9„ý;1–Ø”{Þç}Í3KLD>¯WyéOtý¾þÂüGR¾ÞÔ}•Ž…O«—;š‡?:Å}Û{(È–£gÇQ¼ÇIô¾ìª Þn­þêšrÕ·ÀÜ&›üÇ1ÌALÊ¿ˆÉGR|>ò˱ç(Ö¿mè·@9~× ”ï<Õ©™š‹ÏñqŸÍõ\ÐW_—¿Þ Ÿø÷¯XôOÐÇ$4@˜ÆÔuÏ!¯?ýÕCˆ?¼;ôàdzŸ@ ø9j‡¿ÆXÔ9ƒ“±_í7Ëö}êç¹8Ï pž¬”…uX†·ç©=AóÜ¡Tc´²ÛŸ†«þЮ½é‰;üM ëžäcêrûÃ(U˜ö✫îþƒa €y¢©º²­û±<Óµ}ã¹Îr¢ÿƒBigì “Jré6ŸÒé´h¼b³Ú-·ëåQÃâqÃú…EÉê5»í~‡Íç9½n¿ßÓð="ÇŸèõ B•.26:: "Jªý-FNbfjn®U>~‚†ŠÎ\rš&~–ž®²¶º–)ŽÊÎÒ†ª¾âFxâÝæúþïíÖgõÛ%+?CG1W[_·8K»RÓioƒ‡‹3tc›Ÿo–ŸqÀ#¼ÃÏ#ÕôÆ3Ñ“ÿèi¢J_~èøoÁ…þú5”§p:y±Ða̘n]´v_ÞÁ2$È‘%”tˆ!ešŠN>HIÑ`–O* ©òË™N\¹¨q(ÑT¡yôÒó Nœ"™B5I¦I¨þú‰œ'O_M¬$³F=Ø5WˆOñMM`ï«Øšc½šª•-S§h³â,yÕªÚ¾OíîM;7nW±`¿Ú›WjaI‹BŽŒèÑC¹,íYX&U¿R«ò5ZïaŠGc%«ô_•sI[… »nÕÓ²ËD½ï¯ìϺ5ׯû÷êÐŽ…JN®\ åÊ….oÉ QzÛ¦Ï×{ÕmÙØÝI÷þm=wnìÔŽ¿ý=¸øöÕ»þnʘåöù MßÏŸ½ûñåþÿáÜ2Èržg³éFDr±&ß‚äåž„úµæk2ø`q½MØ^xU˜ ƒÂž~b¸²Ø"Á£Œ3ÒX£7☣Ž;òØ£+æqᆮŸ_aØ…nv¢“a©!‘CR av$>ÙánH6˜!–Rréa– @碙5'`e"W—{Y]jéf}hqWœh^Ò÷%w€ÙIQï½—XžPî¦[~âéT- „Þ¹ÕYMÂõ!z”±y¦§¥©¦0@6#ª‚K„:Fª¹¬ŠÊ§¯¶Øª©ZG^>âš«®»òÚþ«¯¿¬°ÃúÚ¬Çú'ë¬dtz…²ËB­Í"[í,ÏJ;m­ÞdÛ­·†Pk­¸ `ûmáêP®¹ë²Ó¶ãÂKŒº žÊÄ ˆŽpIC…P º9ÌÛ®Àÿ¯Á¶R"hL#¾ä‡ž!~SCø¼ëÎÀc,DÁs¬Ô]™ÆÕT‚ WXÝc¥pšüæƒi™LÖ¤PâWhÅeœ³ÎÆvÜ3-œ}¦Zœ^iI‘(.(%vI‹ Ÿ’> ]ÓÍï\µÕ~Lí³ÖÜž<¦\ü¡— Ñ`Ú×õ‘L{æa¥^.4ÛÆ68óèNhßÊ“¾4±¼ô 1t·rÎíXàÒ¾½µáp¯þ†´{%2\oÓæútÚZ&®÷ÙÙeO§-ÑZ·½ÛCl[> ¾‘‹¾RãœCÁná‡ÃÐMkz¹ä—»W¹íg˜dÒ~»yt$-†Úõž¼wK½<ȃÊÛa´%&Üw0óÛ|ʉƶUfo!f)ñ¢m07ÂÇž>Às?Ú¾þ*} Ä?û}N÷ðûHŽ<=óB}m  Ä¡Öl{ñ!߉G¾Øæ>Ä¡Y—÷šzí5«Kµ5Ü}ëuê! \b¾Í5ì\b¡ g N)wL;O¥Â¦õÀvÂ!½®äúàІÔá~@-’p„&\SþÜÎuBŠ…ˆ˜2Q[‚XAÝMñ@»#›½æÀfñw[d” 3B&1Ù¸Ú¨¢È!·1éRfÄ]åÈÅ/)¯Œ" ] ©Â8 úPŠO2Õ;b!2‘Š\¤ŒÐè¬8ÒPQg“Ôíöå=<%ndå™òÚç6ø! R3Ôd&õ¨0í‡Qù{â* iÈà –²œ%-kiË[â2—ºÜ%/{éË_3˜µŒb¿z81vŽ#pä+›éÌž…ŠoªÓ+'QÍ#2ó™ÚÜfµ®©Ìo*ÕÜ'9‰âMp¢“UÙ,';Û™s¦3ž¬§;ëiOYÀSžúdÇ:ïéÏÖ"Ÿû¨$þè Ѓ"g](áú™Ð‡B”k ¨© Ñ‹b´…(D[éêö¿.lŽ#ÓàÈÒiŠ´s{+)!šÑ—´M<GÙ’ÖÑ”w•¼INCd!”Zn^=…EcjÔŒš¦xà¹øºè<@²GR¥©_§ç(ñq”¢ä4Ø?›RU~¤VqsÃÒ­«¨G]ëC=ØARÑ«˜² Ñ0ø¸·FÐ}!«NÍfÅîÝÕxÖ“à^9TS¨•­Šý§ÃX3ÊͰ5<^þÄÓXûEir’e«è¤Ë~͈-],iK‹8AŽé‹‘Í£ïøY/Â6u/´#_‹Ú],±¦Ý-7'þÄÃÚÍQiulœï ZÜò‘µbt­c Yé–·Òmfí"I[ _–Ä$a.Ù]:Ñ‹¥Üè7JSz7zà‘x5ÊŒEwºòMb4ùSL–ùU|çëߨÕ÷¾,%Ä~áPàŠºô¿ Þæ)êà&xÁ~eƒlá›DxÂ&a…/ìá!ôwÃ"îæ‡K,8ÅŸê°‰[¼· «8Æc±‹k¼Ë8Ç㢱{¬ ë8ÈÇÚÞ+ §|œ…)­©AF:$§pÉhÝHcåcJ¹¯Ué2…ìeg‘Aà»ÔR§ä ò”ÉJ0–Ñü“ž^qÊ #–‹)þ9Ï ê£U‡ó4íÙiÌaõÍX¯z?2†yœÄâSI¶'õ¶ÐcåžÌí²Õæ«^õnUébèç)u~ý²žK½œÙÎé­L>Šˆ×Áêõƒkά_[ÁWï6…ýãI/8œ[ 6ׄ•µO_lêcr³€Ûª›4›Çɱ³u.wÿH×gs6ÚUµ«yFA[=¾¥vhëŒR#;ݙ톋éÚ’®¸T<éC+–¯9¤÷¯íî?×;ªäNQ—Õmðƒ…9{ƒDŸ— ï0ßvI´6î¥ómqIF|â{øÿ†FñŒ‹–'è>8É«Ad|+[»‘"åÉX~Êþðªl›²´ÊÏ[íô®­dT`?Ô•£—»>t =¹C¡ºäJ'1ßLÔd"ÏKŸz©iõ«c=ëZß:׋E¦‘S=ìÄô1Ùù)ö³ˆÇe_»EÐîvå¨íl—úÛë¾>¹ã\`·;ß5—÷¿¯iï}ü#oø7ÐðŠÃáO«ÅC~#)\õ?žŒäÔ°¹_WFIe«,¸Ì—=ñ‘üLýUyÞΜW½h+².›ð¢ý⓪դžÕÓæòûÌ2٘˕«Œ.Ÿ 9-ÖTOZ0¡fößgO{»5°Ávª½Ý ]¿Œ¶l\'¨]ƒïÎÇF×Ëoþóþ£?ýô85¹Å„\½Ýðõ³b ¿-Ál‹Û¶ ºø·ÃÅã=‡àq¹ŸÄÁ_ÅÍ•ÇeßO±[¼ܾ \œ…©¬ßÖ ÂøÝ€o%õ[ÇáÛZI–YÃ]×A¿…\íW æ žYÃx”Ê-Êͱ Iy­W)ñ` m*µ“¼Wó!ǾĠ b Ê”BâÊÓX”eV1•Pu$´L¥F)õùÏé°Z–¸š-‚_÷[VYÑøöý$¦mbvß`Fß+RÓEÅSÞå4Pæd¤¥@›ý¹þÝß3î_ÎNyi$'¾Ì_õÔ~¦D†¦þµ_ÎTff„e^&@Ðf€ì¥î1,rœ¾ñšNš£Åf=^pÊk×ÅÙãpœeä&:ØæmÞYt¦ \ê¢ Š r6ÜþQ`p:Üü‘éþñ‰qþ&=:çRR$ºç{Âg|âˆuÞÝ‘1d(­RG áw-d(!ð¹—¬‰%b4^Š^ "dý Ý&ú'Ì¡¥Ì%a)Ú%uªI^Êβ¨ËtZÑ'ùYè…~hV‘|šè‰¢hŠÊˆEVhˆV†¢‹Þ%ŒþŒŒ¾èˆž–²#^‹Žr®‘b#އ )Càhé/©(Ìèm€#ÞB–M]úX“ª€‘.)^&é1|!I¡¤N %ê–¦€–n©‡V¨YÍ7"ñéNwÊ ¡\§•[ã™i ¥)*æé#D¦íä¢o¢€|*#° >Vd2æã©WÞ}ªíYÑñtb¦…c’ÌàV>ÑA耨³~"T _ M•ñšW¶œõä^¢ÈšæcN%{µß£>±v)U"b æsš&>:ͰéIi–EáÖ…Ü_ª °=¦€¦F jœ8ìª% ¡ÀÚU)‰}î%e)h&(šzj»ê¥ŠfœÍ«gg­©f£ì„r†Öìè£gÆ_z¼æ,B£lÅÁÈ M Kêh±Æ&lÒÚÆúþQbzg˜¢Œ|,ëîá½Ý'sqH¹Rà8¸,/”¨ŠFâáѬeå¤z‘xN묥H¯í¢&QÒÑo2ç9Vº:GÒɞΡªÚàf]WBJµ"cÌDΌҜ(BkÉDlÌàܤ8èË¡k„Ž×¤Þh‹šm8Yl†Âj§FQn@.R<.SJ¡âZFââå@‘m©D®áªjçÊàæ" èÃÓ’®Š®DnNnL®.ê¶.>½®:}îìÊ^ì)bEjË€¡¬^ªI½áD(ÝNžÆH©ÈÕ®í²+á¢ÊDØ[ëá û¬!!6ï!þ*æòãàî;*o™n¯-D)XþQdU¡ð-XA+ôl‡&²\ï4•Ï)ßíq’@Œâzd›ê\B†Oò}Ç÷ži÷Þ.óâjYJfö¤µù«„ ÏÕbÀrÛ-ë’TU‰@ðóJ*æý†ÿê)¡g:¤½­’mªðvŽåõ ¿¤c€$ÝP$"%•r*Ôh°Ÿ¦—¨,W:¨ÐÕp ëiYp4cþ©ìh¾mça\Ü–…ñ‰Ì0£b§p.à–ØêêíT®ÂÙ“¦‰6$G†©Q’*M¸Yõ¦®òîuÔ ÕN¡ßöÙ7¢ q±¡Úl¯Æi‹mr…íh4±0V¥•³)ëµ>S\–¢…¢Ðýnï™%þgh´æoÇR«ôZë[*i«øºå ï/¨Éïfä1¯Ö0ói­ ² )RŽÔ­*©Ö -Ûâ¯+Ã)—lä1ªñ1ì%°]9&{Èå°l«¼Ök¬Ý«æ+í+¸õU.ÿ÷ñr,ö"…±™&îm¶áê¡þ°$_ó~òß2¨´Ê­*yÖŸ‰Œ¹æ'qÆvé+Ò=-¿ŠÌ2Þ©¿h¶fÇÖ7û!ÃÑ_'uðÕŽð»yZ%"sÐF’kÞóÇfÿ p6Yn©E-·±¤õ&£I\8Jf9Êq±% ÇùsF÷.VúlÇí±lM4F{'¢×'#ìD©ÅÞ„K´Ðþmxþíf§>ʱµ¤G“àÎ&g«þ Im­žtw~í,K¿,·ÒL;lΚæ„r3"ó­Ë™×M:wÐs&·ò ‚Ž*iŠ‘ÑÌ%nµçmW2¨lÎ/ÄÜq9Os{:õS'¯®Z±<‚i㢠S+m]§£/2í`vavùùuÙ6{¾ÓbÏ]bs®c³hrÀ´d³nC[öÞuf›Ø×!gGÝLƒ¶‹y¶"Nq ö߈vj—XiŸ¢¬ª!kãæf˶ƒ¹¶5^0¡µ¸Ö6¬vo?ØmûݾPe3¢éФ£B)³.÷–4övq] ÷?*õ6÷""·ïº*ï¢csþƒHWojO7Fª2R7Ï4¶\¾Q¸z+¶®%œb2v¥˜}k®±·l÷ÕÄíy»#eG3¼ì2¿ `ì3Cf€ë›xCöèZ’üiš«6ÚæsÆ®&s¬<Ÿ¬B›*ËZv~k¦„#TW8>›ônŽrJ¯gÁ6ˆ?Ò°ˆøQ¸ñD­V5Š£tRÃr>¶‹ëfŒ³Á;5¶­mÞr7ë/Š3\“ó̱¶ïÀunveHw#'5cùã8tSêån¹±iy˜«Êo“y:Aùuž9„ÑöšÛdƒ«®›cX›Ë¹TÂ9×¹¶ÐyžÏà¶HNá^g/èR9ŸÛ9þf·Mínê9v¡ºÎ¤ùÝ%JÊ$PŸñC.úé:ú£Ã—Ÿ+qoí Ò· µ8T³óúÊsHº0Þoåz·ô¾:Ô<7㢶ÕD:ðOÇri,Üb yÖšëǺ,S¯|åwŸ¶˜f³±Ô­“h±-qÁªô wî¯ßr‚Úð{_ò¦er²ò/¸ÒœZÚWÇ·j²'rò\Rûzúkãô° õ®w¯µ§-¶Sžü(ðçP/ÇÚ/÷73ëš3ï;4¿ë‚듳×`[[u\v4¦K9M’xÊn$fѳălBíÊz›n¦†d°q ^ Â+i•szDÏ8wæ¸ã8R‹ç´Cþ£É¢çEÑN7{»ãöJÜþâ»ÓSw¥ÒzQ~9unºãs)¹–¯ ·Î”›9æ7”]JU Ld,ú<'æzä^>è#˜æ3 \•í˜iç‘®¾——A¦òä¬ ztKöà»kª ²`Úûõª.éí'wV »•Kñ²«Ðyÿź|¨“•¼óeþÚ>‰3<ªo»¸k|s»|¿å&ƒe'W¾tC>y¯¼.}¿Âqš¾3Ì»ÿ¿ø¿ ü|¥smO?â€" EÓ»´XcÐÔT-žWófëF²4O4UW¶u_8 ¶o<×w¾÷}H0"3âh´)z‚Žc(‰§×íwͽ篯¢¿(À¨&A-A¬‰ÀÀEÇ&<ÉIÊÊ»³¾LÍÍM8ËOÐPÑÑLÎÓ>GUEOÆC-E®ØŽ+.HÚGÒ]ÞÞK=Ô`áaW_ãcädÓáf D¨-)A ŠÚeC ‹h¦jî¥íDêUþh¨beôt^fçv÷´suùyú2ö÷÷øëz0}þ€Êîá#XÐ_@„ ù ,HlE4…f"N¤¸XCŒù*n䈎aÆS;Ž$YòÓG)5‰4ÙÒe”*S½¤YÓfœ˜2uú¹ÙÓ§™‹;;ý$ZÔh‚ B•ò<ÚôgÎ¥ðœN¥:jT¬5X‚Ûj§ë>U^ÍÊã«X´iG‘-«4Ò‰l2^ø«&æ¬Ú]lÛ⸋×ï_:z÷Ê|à­[B2þö`DoÞÆ}’¨.ày‚è‹Ùóç<›Es†)ܾʦÛºU…õ ¸@ËÓ<øI6Mno‹üðÜÙÝ…Èxy¶Üiþˆ Ÿ­¢öhƒÔz·F M\®ÒÙáêâÞÜcRèf­·&’X ÝÄ`çÂRx–‰·í%R—/§sÚçá5ÒÅ?îëTÃ.¾kd»Ï»:ò+K7ëÊ›åÔð4áO?¡<.®ÿúƒÑEÊÆû»×bôEÁ¬ldÐ1 ß{8 40¶,<òÃÉaε­‘Í csì*ÍKOÈ f¤Q§‰À²/$J7oñİ™"2‡4óL­´ËDAL¹7ÁÌðOCqy²»o”TÏH*ät08 +µ”7óþ$’Ï`ÌóS6 Ò%Ýì±»Gý«1uYôUÄŽ½Y+…õRPkÙ“ÓŒ<ÍõW¸v=Ó–*µ¬Õc©+¶TA|óÖ o °Uf‹µWl}¥JT^‡öÛ9¸uKšf•e3ÅਫLí4,¾; íXs”TwÍwÝm×ÞåmSÐ?µJÜng÷àá„¥QàŽžÈa„ .xˆUb4¥ÈmcŽ;öøcCyd’K6ùd”SVye•Åxb6*¶XS…õ“yfœ7zæ7rö9Ԛûùg¢Ú™g4†.Ú³£ARzi¨Ói鞎¯©1²új®{Éšj€3®”õþ¾±kP¾Žm¶]Rì2=®\²CÕvë¶uï¼ûÆãm¸ûdÃA“ˆŒÝ ©|íÔ;Çöû—½—üá ç„TÆQû’0éîKU&ÿ»òÑD4àËRw.TÑ'Ös÷ûu¸¯ÕÎÚ“¿ÝváuG:öÏe•¾=<×MSä›?˜øÈýó‘yåÇ|wíí#]´ ÷e-ÚãÃoÒÑò?å~÷Ù7²^I/gî°ç{øómÆxøšûže»sY)~¹šßóÈÀÚÆNý=×>òYê´\Cþ·Á†Ep/½K•² Åœ[~ þôNyöAVÄ…Â0œ6‚s=ÂQÏz9ÌäCÐÌpb0bD„ˆ "±|GìV•&^î‰S Œ;Ø'R±Qô–½.ò)‹_TG31F2æÍŒ Kã_ÖÈ4¶moš±fÅÙQÎÁã{æu%«NÛ1[}öh€>b%އ\¡óÃÏq)’̲›=¹„DŽê’›,“ñQÞNv´+\)ãô¥r1.M‹$š#±ÈINº}ª¢à¿X‹Í‰ï[Še&—’$Q u€8|~„Dñ¯WŠUð`ÙIOº#vñ¢å-“¼ ^R–L!Õˆ¼é» R™ó™þÓ íN]2ó™Û” ÷v:ð¹›ñìe÷lyoNðEu0g¿C’<ò’±•ÊZìP§üçÙ9BZÉK…ÖÌfè¹É‡&–ôi 'iÁIá2ž¹”dçj˜®VAZ)E%3šG騝Zù2¡@å4Nõ–/}FM“I@bPßK¦þÐÑ(^Tj0… IòT‘Ï<ŠTÅãSþ¢€µ j­Ê¹8Z¬[À“g–´hÕ_RÕ(h QùÙ>€)®÷ŒÞ±XÅѦŽ…y¨C}ͰR­“`k€™Jnàï¦MB)8"™À©Ï±ìžYf¯„æôDûšþT7XØv°£ëÞgD;Ú`¶§Em#Ç2ØÆV¶³¥mmg{Ö¿ª–/­í hãÆÛ6ú–0Àµ‰pûD\¿ê¶¬EîŒKšæâV¹‰nKžËÜê1·Ó…. ЉYB±ä ù®ð®›Ý)>×iéŒ^(Ã[·‡x÷nQÝnÆÐ«Dõöê ;Lìj¢4©y­FM•-)µÌU¿ÏÖw¸÷-b~µ¶Ñ’”X%jjäZW^Æï¼+\×*ÕÌù0-ö tú¨±fðÃ)NE›·a²ºw2ñ¯ˆñ£`ÝO¢H²,='|ÍSX{–ñûšµ,r)t±ûE§eˆcÕê¸Â-š2ªþ~ìb8ex‰P^ï‘·¹R¬n²“Èåh®R¦”$©¡üeÃýÅù£9å쉌Ï.y4ÆJ…¬gÍœ¯-mv.šœÏgéy¯@Ö ¡CÈÝN‰»i¼ó´°„è=3:tŽÖ™¡ý8iNËÈž¿£º*£CÍúÎ~õ=}EP·“¥•uëMXךԵ­_ÝÁ\÷ƽ–Ü­?IlWÓÙ}3ö~–]Æ_ûÙ„4§ me_»kÍ–&L ¡÷†¾ì]ÝG]mgk{Žè.¹ÇAêªÄf ¦%_ÌîÕª»mÜÎ÷à>Ð_Sý×p¾0Šô·&§ÁæÅ·3‚þ­o’ðÛáæ„«-Ì]h«á4ѦEGä'gÍ/bµãÌ_‘9ã”÷¼[+ñ嚟<Þ’ŠªAYÍS¯¾uMÖr8u÷2iìÌ—7œ×ål蜥×+?ýÂÜùÇ•N]ºJRCVòg Áì^ÐÑNá$BñÁy!´Ô8dòÛs¬›3ã’‰z£ëþã©gÙ¬¹«4£òùõ´ƒÔI#uUAJk±W¬­h)áNC‡\mø›#EàÊWht*Ã{ž(}òØ›j¬ŸVŒÔ¢†5¯ÓÌûê#eJ·k·Ú!‘4Ä quÈcµô[G4“$ŠÐ”¿KîÓ²]/êþq/>>Ò¡ˆ=~q¿ünþ>CÈš« ñŒ,¼/ž«Æß9ò¥;û.ÚÞkÏ·¶ÚM§J76¡¥))?¼PŸø(wç×¾ðË–ˆÊ/¿øÇŸíó¿p!¿&Àÿ£ÛJ@\@lÀŽ .䕿 µa3ÀŸá?Ú³@R¸.ì@ü@ AAœ­ä” ä4õlA|AŒAœA¬A¼AÌAÜAìAüA B!B",Bð ? L›q(¾bDBŒDIœÄv2ª™[‘ë¾› pR,£6J EQE&”²¸=ŠÚ»»ÖsºFã9RŒEYœE`#º¸r•U´²‹S •b4«£E` Fa–È˹]2=‚³ÄwJ4ÃÀ)ª3XFiœFj ­ÚÓ@ ¬FmÜF$¬$ÌFn Gq£$\ HGtLÇ#,AvlGw|Gxü˜sTGz¬GÕ*B|ÌG}ÜG~ìGüÇ´GH‚,Hƒ¼6æÄ‰+<žÏýûOßñ·\X~B¼¹?yy_3³¡3gn*/¯¢”² wî—AGGMOO“{in®_ZZ>uê†-[fªª*êëk}`{´µÿTCÿHÈ$©®NtôhÒ?½té{àN¢šš2˰|ùî$éxyM 4hPW>†!„š;œ›„ÐêõëÊݻτ†â „DF^¸°¾ukM©É-"QýâÅ{Ì͇ÉËûZYX»ö'±˜RJþù ç³}û/,NˆŠúQE¥WVÖ]ÿ9”R“!„xSJßVœÍቋ;çä4VAÁ×Ñqìo¿¥³=ÖÕ‰æÌÙ®¯?HQÑÏ×7,7·ˆkL\Ü9{û`9¹zzÇŽ]UZZ.ÕÚ·KPJy<žXLÅbñ/¿\eÓ‡šhC}½8*êG#£¯|»t ]¾|_ÃùQ ;âïøÑ±ýîÞ}ÆÙyœ‚‚¯…EàÑ£I'O^kß~Œ¼¼¯­mÐÙ³)\U”ÒgÏJ—.³° ]ß©“=”—W±“È ,'w S'ûÐÐõË—ïëT1Œ%B53 ô/ûós“®_¿]SS×±c;©.¯ŽŽz§Níääd¤ºÚÓ§oÜ¿ÿÜÖ­aû–-¿bžŋwBüý;Mšä?kÖ–û÷Ÿ]ºt=:zï† ÓÚµ3Û³g!$5uûÇG Ñâ\ýßdëÖ°””mÊÊ #G.­¯³=îÜy*&&<'gOŸ>çÍÛÁ2/ð.(Øwøðâ_M={›ÔQH5žmˆDõ‰‰K–ìöõu•ìd7цÈȘM›ŽmÜ8=7wo@€OTÔ.h áÊ©Æ4}ì«Wÿoýú©™™;MLtCBVDEý–™¹ÃÈH'(h)‹.22 Ç_mj:ôر¤¨¨¢¢ŸV®œHáN¢T #yW¬˜PTôSTTH|ü%“!ãÆ­ÊÈ(lx!„P³€s“úO••U€††Ê_Nž¡”>}ZºmÛ‰sçÖz{;€±±ÎÇ/æÏß1gÎ(YYþš5S3Æ[•Ÿøð/ÆŽýÔÕUàÍÔ ®x·nŽ„]®8ÛÅ’%c==í`Ê”AAËž?/“‘áÇÆžŒ‰ ó÷ïÓ§.,|°yóqxòä¥XL ´ŒtLLtþy!Dê(¸>´ƒC—^]]«¦¦Ü¯_§U«&5<̆m——ݸñè?Ì8°+L›6¨°ðÁ¦MÇ$K¹¹M”úô¶oŸ5t¨÷ò/}Ù² ݺ9ÀĉþKÖ¬™Âš1n\ßáÃ?}Z¢§§Ù¡Ãx33½³g×téâ yŒÜIlâ BåÇŒéÒë÷ßoŒ½|çαø··åG!„>e3 ôŸÒÖV€/^YY5“’™y«¾^Ü·o$×7­¯WW×>xðÌÜ\OQQ..nž»ûDíÍ›¿ixß½‰â쥥¥!+Ånÿ×Õ‰²³ïŠDõžžv, „tîìÀb†Nì¿úªÛĉkçÎíÑÃÅß¿óàÁ^ogøå—††Ú"Qýùói³goóósÛ´éEE¹†‡Ù° ¹¹Eµµ¢Îí¹6tíê(39²¤M}É==Í¿uìvv¦l¿ÊÊ `n®Ïr*)É€HT ÅÄœ92zâDÿqãúhk«±öp'ÑÒò/¿gÏJccOnÝúsmmÝ‚AÒoãs“B53 ô/ûós“Ì•”ä¯^Íòð°•ìn>|øbĈ%‹éÚÕ¥SJÅb1<Õ¶íŸ ##–'55Çã=zô"#£°k×öR{n¢xVÖàñH£«œ)® ²²\%ø|ÞO?Eegß;uêÚùó©AAËvîAAËØŠdÉ~0Wœ•µ´4äŠs¤zäíÛ[ÈÉÉ\¼˜Á !A6{ëÒ¥ë“&­µ´4 š°êûï§ýúkêË—¯›X÷ÌR|}]/ŸÄVl7üL¤Úàèh!++sõjVÃ6H•’JùÀcgcRõ+(È÷JMÝ–°ª¬¬ÜÃcKd'ñÕ«JÉâÜIOÏɯ^Uœ>½:%%&8¸—¼¼,>= !„Pó…÷½úOQJ££Ç%&fxyM]° ØÕÕúåËW;wžúá‡ø•+'ZXHf66Ö5ÊwîÜXuu•N삜iÓ6xËÊòëêêGŽŒ¶·7ÿöÛa¥¥å!¡¡ë÷(×®e{zÚé¼­8· ©Ž¬††ÊŒ_Í«©ÙÊÓÓ.!AÀ&&€ŠŠblìI±˜Îœ9¤®Ntüøï66&ªŽ3HÖL™5kØ©S×""búôéØð3‘jƒ–V«É“ýçÎÝ®­­æäd™ ؼù˜T¶çÏË?~)U{`óÇÞpœAòe·nŽ^^íïÝ{ÂÒ›8‰lÒTAÁ>33½†+uä8= !„P³€1Bÿ2â-9=‰¢©©zùò¦åËã"#cîÝ{"''Ó¡CÛ#G³%¿’(¥11á&&{çÌÙ^\ü\WW}Ò$ÿE‹ÆÀ‚;²²î¦¥m—‘ákk«mÝ6p༞=Ýìúå—£G/€‚‚}o+.¹ ©.[6AMMeÖ¬-OŸ–¸»ÛFEGDÄ€³³e\ܼeËâÇ*)ÉwïÞá—_VðxM=7‰{ÉçóvìøÖÙyÜ×_7fÌ— S*eõêɪªJ_ýÝóçe..ÖK–ì‘—ÿÿ_móòš&ý1RVvR2åï{âáj . ÐÒjÕèI0  +õ×B!Ô|F§ „þ1„H-i@éܹ{{söÓo”ÒÍ›GDl-+;Åç·¬é”ÄÇB5 -ë !ÔüQJ¾¸$99÷îÝÇÇŽý¾téÞ  ž--`|nB¡fÇú·]üØ h~JKË¿ývëÏ?_~ùòµ‘‘ΨQ~s挔úÁ»¡ÛÇnB!ôN0f@è߆1zŒB5-n¬!„š‹–6l‚B¨ÅÂç&µØùø”áh„B5g3´ Ø1ý4ïÝ„B¡‚s“Bè#Áåd!„š Œú—áøB!„š9œ›„>E”Ò˜˜;wžÊɹW[+26Öñ÷ïy3 O!dãÆ£pøðbÿNPQQíá1955?)é†SÓwî'GšîâK•Šæ^Þ¸q›«nÞ¼Ãek¢Jé»ç”ÌðAB!„Ð ×3 †R*äÈÉõ ÛÌmPJ)¥b±öî=“ž^H)(++œ:µR ØâèhÁ:Ö”ÒÓ§…]º„*)õTQéåí=ýò囬,!„’“Säå5MQÑÏÁ!äܹ¶GB¼ ñÞ¿ÿ|×®SýììFŸ8q…•âñ|x<Ÿää\òf"»û$–È2¸»O"Ä›RzçΣçiiùËÊ~a`0øë¯×WTT³éFR9“’®ûøÌPVÖçË/#RSóYÂÉØ†m7Z„婪ª17æä4¶¬¬‚mÔÔÔá2"„Bè¿¿ÝRÒ¼ÖÚRJ+*ª]\&”––§¦nûâ‹™¥¥åyy{ÕÕU *êÇÅ‹÷°ÿ9utÔ;w¶ïÙÓ=0°G«VJ¬ìÙ³)}úDˆÅ´sgûÊÊšôôee…ÌÌææz<ž())¸»Ûܾýèþý§ªÅŇååeùüîЪ•’££åíÛ‹‹Ÿ«¨(>ztTIIž• ·.[wìØïàííÄsüøeèÖÍQ]]åèÑ%îî“RSóMM[·kg&æ>^6vì—Û¶…4_2ç7ß ñõ ‰ê;v´ãóù—/ßPP»zu³½½9°–[\]­¹íªªÚF‹88´€ýûÏho߆m,[6þcœºÃÖ3 „B¨YÁqôqBÂÃ7™C!„Ðçcôq?=©  ×£‡ Û êÉMÝáñÈ”)ý³³wîÿñÇÈÞÊÊ ¾ ÝÀ:ÐiiàççÆºà;v|{äÈbg®;Þ½» ˜˜´fª«káM`ÀÞ²´4d9kjê@¢ãž,ÄMvâŠOŸ>,Ø©­í?tè¢çÏKmlL¤r€P˜C)3f%›à¼œRzéÒõ†9¹m¡0ÆŒYÉæP/€K—®“?À´iƒëëÅóçï`óæÅþw' !„BŸ1\>CCí3¾Z·îÐÏ?_a[·þ|±šÚ—k×þo%‰;úML‚7¡ H(¥<R_/€{÷žLž¼.:zO``””˜‚‚}ðàÁ36÷I2§‹K[èÕ˃Mp5ªgûö#Fø6Ñ*®ÈÑ£KŽ]ÂaïþôSâ¥K×gÎòüyÛðñqþÎB!„Ž3 ƒ¢  ·kWdçΡkÖ`ÑÑ{Ö­ûºMýiÓ­_xâÄ5[¶36Ö½}ûavö=BÈ’%cYzöìýûÏ]³æàåË7ëêD))yJJòýûw†·ÀŸG à-c  ££öôié„ kTU•Î[+ù2!aÕµkÙ™™·®\¹Ù©“= ÌÍõ­­¥ †… ½z5kΜíGŽ\TSS¾x1³¾^¼eËÌ&Z5gÎÈ~ýf7,Â&PEFÆ88´™;w”³ó8‡6‹¡ïü0Y„B¡1úh!nn6µµ¿²—ܬ]ûµÙ®]§oÞ¼sãÆmuu•=\†öìéÆ2ôíÛñرè¥K÷¦¥åóùk!„j†p=B!„B¨)3 „B!„š‚1B!„B¨)3 „B!„š‚1B!„B¨)3 „B!„š‚1B!„B¨)3 „B!„š‚1j~bcOòx>„xs­Z}Ù£ÇÌìì{”RJivö=ÏG^Þ÷õëÊ÷þÕ»wKí…ýñx>7nÜÎÍ-âñ|de¿(/¯úg!„BèS#ó±€ÐßC)MNÎ;;3/¯ö Õ_»–}áBz@ÀÂ7~$^½ª˜8±Ÿ¾¾¶ŠŠ"!äýö"ä@«VÊ_H¾%++Ó®ùÞ½gYTTÿ£B!„ú„aÌ€šBˆ@ #GúFF²àùó2]Ý99÷îÜydaaàéiçéi÷{INÎww›Í›¿ixpïRJß/,A!„j.pnjfÊË«²²î€££%ë¬SJ_¼xÅf%±—:}ÍãùlÞ|œÛ^½ú€¿ÿ5µ>jj}–.ã&,>|ÑÆf”ŠJ¯I“Ö&'çòx>––¬*¡0œ­†Ü»®®6PVVce5BAÁ×À`pDDLMM¥411ƒÇó±µ Z¿þp›6Õ”zöë7ûÉ“’©S7´n=PE¥Wxøæ÷ž:…B!ôŸ!Øei!šø±ñ¯£”^ºtÝÛ{:Ü¿ÈÀ@»²²:+ëîÔ©RRò,, òòâD¢z5µ/kjê„­íÛ[°mYY™NÚñù¼ Ò !÷î44Ô>{6åË/# ÿΩ©ùjjÊ7oÞ6¬û¾}óD¢z ¾••5]»¶·³3•lÊååeÕÔúÔÕ‰RS·µicЭ۴ë×o»¸´m×Î,!AøìYéÌ™«WO^½ú`dd G,, ]\Ú<ø¥ÔÈHG__«uk'®@aá~ ƒòa~ÄðšƒB5787 5'„¡0‡B)56|KGG}÷î9„@ffaMM‚‚\ûö™™…ÕÕµ=6<|heeªjoJiMMDGï¡”~óMÀš5“SRòÜÝ'€‹‹5ܼy§²²†RzéRæ¥K™Ü^ ´7oþæÚµìº:‘’’¼½½ùœ9Û¯_¿=`@—ǧO ûô‰Œ‹;·zõä””\°·7¿|y“’’¼@sçÎ#gg«øøèŠŠ*5µ> //û~~!„BïcÔœp  mmM»us,,,>>ÏçmØ0mĈjjÊÀÖ.;9YÊÊò‚Bˆ¹¹~xøP(,,€V­”ÌÍõ_¿®ºz5 FîíÛ[°9Hnn6\%¦¦­ïÞ=ذ ìÝÚÊÈðÙèA||ŸïÃå)))¡0¦OÿJIIþÕ«Ê{÷Àœ9# ŒŒBhÝZÃÈHç_þÌB!„>Æ ¨9aã Ò›…£G/‹;—˜˜>eJ ”²»ûîî6À¶ýü\Y|ñÊ•,øã©J9ðfu2Ûöôl÷fY3{Ø‘-ÈÉɲÄ[·@lìI°³3SR’ç º¸X7ºZrl5‚ŸŸÛ–-3·l™ijªgbÒ:0°[$ݺµF›6ú„®¸»Û°úØ£ŸÜÜl0`@!„ЧÇPsÂ:â²²2..Öì½¹¹þÀ]¾¸råþcÇ¢ËÊ*òó€»»-·Í `“‘X_ßÜ\¿Mƒ;wõï?ÇÎÎŒ­Hvs³€×¯«rrî@bb:›Pıµ5 ü‚Íqb±GDDà˜1+§MûþÂ…´¢¢§W¯fééiŽåÇÆ"<=íØc„Âlðð°•l Ž3 „B¨YÀ˜5'ìWÚ·o£¨(Ç=hu„~‡_üå—«·n=¼}û¥TCCÕÊÊðܹÔ7ÛF”Ò’’ò¼¼ûðÇÍ~Büï ÆŒYqëÖC[[S[ ÇÃÃRRòÄbJ)=s&Yrï„ÈÈ@¡0—¢££nn®G î%++³fÍ£G“TT¿Xºt¼¡¡67¦ÁÚÉ¢;Jéݻٌ&7·FÆ1B!„>5ø¬Õ–âóxÖê?hÒ¤µÆÆ­Ç룫«^WWoj:äÉ“’[·ö››ë즵hø¬U„B¨Âqô9b¿ó›[tèÐonn6ééOž”ôêåŽB!„PC8ÎÐRà8Ãß”ž^ðí·[…ÂÜŠŠ*mmµ>}:®Z5ISS' ý»pœ!„j†0fh)0f@ÍÆ !„P3„ÏZE!„B5ÇZ œQƒš ¼æ „BÍ ®nApnúôïÝ„Bým87 !„B!ÔŒB!„BMÁ˜ásG)Ý¿ÿ¼¢¢_YYÅÛòðx>„xâÍãùðùÝy<ƒÁìÝ’’×|~wö®äŸ‚‚oeeͱc¿K•mÕêËîÝ¿¹qã6·–†Rš—w̘•ÆÆ ¾¦¦C§MûþÙ³Ò†-=zùš5+*ªÕÔú?ÿ[«qîÞ}Ìãù<øÀ5<”Ò¸¸s²²_”—W}H=!„BÍÆ Ÿ;BH@@·ÒÒ“jjÊf ”æçÇUTœ®¬b@IIÉmß¾ ÷¡˜¢” Ùîî¶øÌ1„B}&0fhá$ûµ ï¯SJÅbª¥åÿÝw‡(¥»wŸ±·–—÷UUííå5íâÅL©nqNν  ¥ÞÞNëÖ}ͤ¤ä¶mk$//Û°þúzqJJ^‡m¥šqóæEEy%%˜7/ÖÕÕzΜ’å'LèwäÈ%JRZ[+š{v<+k·­­©¿ÿœšš:®TIÉëæii©<¸PVV†«A(Ìqt´l´ûž›[ôêU¥³³`TTTïÚuzåÊý¡¡eeùee¿þš:n\_©¶QJÍÍõËÊ*JKË`ß¾s> ÈÕ£¥¥V^^õêUeÃ#Zµjò‹'””ä%k‹iZZ@XP°²‚Õ–ž^ЭÛt{{ó‚‚}II¯\Éš0a ë÷7L€ŒŒÂšš:ö‰uí:ÕÕÕ¦°p¿@°åÞ½'£F-€{÷žøøÌpv¶ÌË‹»uk¿‰Ÿ_ÊPr IDATxuu-°y\‹í2¤û;¦Oÿ*22æ}Î+B!„П¡%ÓÑéuu"ppa]ägÏŽsØÝwYY™¬òòîSJ·m;accâæfÆå¬¯.yøðùåË›´µÕ¸ô;w=}ZŸÄöű´4¼re“P˜S§n˜9s«äõëʶm—,;mÚ`ÈÍ-ª¯»ºZK…„’’×À&MíÞ}Úß¿³ºº ÷.;(‘¨žR*UVNNúÿjBHvöòòª;#:v´€©S///¯RVV˜:uƒ¯¯ËÚµS!úúZ‘‘#&MZ[SS÷¶t¡0GYY¡];³ž=gx/\8tuÕÆUQQ-Ó˜˜ð¡C}Ø'ܹ³ClìI …9„Í›¿quµfŸNpB!„Чc†–,-m;$&fŒ½üìÙµ::j ÙÉfËyÌåœ,X8wîvÉ>>Î6Lm×ÎŒ»¯?{ö¶³gS~ú)ª}û6\ý”R âã£íìL%w­  Éɹ::ê))1PZZµëö퇿þºNSS•Õüúu%¨ª*Iuý)¥×®eYX()ÉWW×^»–½aÃ4.¥ôùó2>Ÿ§®®ò. šÙhMMÕº°ülB$ª/.~~åJÖ‰˹š55UE¢úüü¦WTT''纸´}ôèÅo¿¥''ç;ö;ÛK]ˆR*ÕËÈð/_¾±qã‘ÊÊšÊÊêž98˜³=&'çzyµg¥4#£ÀÚÚä}N-B!„Ðc†–ÌØX—Rʆôõ5õõµ¤2°q;Ö2Ä{àÀ.{÷ž‹ŒŒñ÷ŸSX¸€@\ܹ5k.X4x°—dq¶°XAAÎÇÇYV–ß°û.æxxØë€‘‘ÎÞ½sí탧Nݰÿ|¶w33=¸s瑉‰®d«JK˸0}ú`ÈË»_[+rr²” u23 íìÌÞqA3k§££¥Œ ŸÕŸ™Y¨££®¦¦œ‘Qööæì „ddhh¨¾|ùªÑtMMU¡0§ÿ.ùùàüùuzzš’;’““õòšjaa>ÌÊÊÈÄD×Ím¢¯¯+O sBCqu 9¶ïr!„B®ghášXÏÀ–ófdººZÿþû OÏÉ ++ÒkÍš)wï>.++€””¼‰×ÔuÁ‚à†59NN– UU5ׯßvs³a¥!ŠŠrß~;üÀ ©©ù,ÅÒÒÐÙÙjÓ¦xÉßj‹éĉk54TgÎ /_¾uÉ</fz{;½ãÄ6ÎPVVÎ"‹Dõ\2ÄØ:쒒׬ý••5»vþê«noK/))/((vuµÖÔT‘¨ÞÈHÇÈHGAA®wïo/_¾)æ=ݲefÿþíìL³²îæç?ðöv€»w?}ZêéiÇꬫ¥¦æ»»cÌ€B¡OÆ -_ïÞbñoúúZ × ddÖÖŠ<<ì\\¬‹ŠžnÜxôÅ‹W<;zô¢££…ººÊãÇ/ šß¶­ÑÖ­a55µÕÕµUU5UU5ÕÕµ¬ó–VСƒ—ÎýÕÕ‰ÒÒ D¢z;Éñ‘#}[µRúþû#\ ±yó7 ‚Q£–fd–”¼þý÷½zÍr~ùe…ªª"°Á>7M(55?'çÞèѽ*55u55u’)”ÒêêÚ7nWVÖìÙs¶  xìØUÕs玀¬,- çÍ‹-.~^XX°°®®~áÂà·¥''çRJ=<ì-mmMçÏßñðá‹ôô¾}gËËËõíÛÑÐP›rèPbiiùùóilUt»vf æBXE)½qãNUU§§Ý¿rÖB!„þ93|¾Ø(A«VJ66&ŠŠr§N­üùçË&&CìíC!ññѰaÃáââç™™·ttú+)õäþÜÜ&ëõnÚtLò-%¥žÊʽví:-äBÜܬ%GTT{:”øâÅ+–îáa+l‰ê¿øb¦®î€±cW¹ºZ§§ÇÚÚš° <Úðòå+.ÌXµêýûwîÐÁJêˆêêDƒ§LùNêÑ®éé…|>ïäɱ±¿8:Žyüøebâ†Ö­5!22ü„„U„›Qnn54T®^Ýl` Õhº¾¾¦@£§§il¬Cœ8±\QQÞÚz¤Ÿ_˜³³åùóë””ä-- ×®²~ý!SÓ¡;vœ\¾|¼*INα¶6nÕJéÍĤlee{{óûD#„B} ‚mi!šø±ñÏ{ó ý¶oŸà II×ýý礥m73ÓûÀ_tFñ¼æ „>eÜ7 ÷­J¼1SþHùŒ¿Â0fh)ZhÌ”ÒaÛ˜è®Z5©ªªÖÍmâ’%cì‚C³ôy_pBÍ@Ëý>Eêóþ ùIèSG3æËÓ§…0yòºÑ£{aÀ€B!ô_Âq†–ï‹ fáó¾Iƒjðû½U·Ý€ ÇB!„ÞÀ€¡Æ`Ì€B!„j Æ !„Bý•Ï{-%Æ !„BopOØDIÀ˜!„B!ÔŒ>w”ÒýûÏ+*ú••U43/ïþ˜1+|MM‡N›öý³g¥Üs·jjêý<='K=‰ëË/#||fPJKJ^óùÝy<B¼¹?ÏGAÁ·²²†+5zôò5kVTT«©õ).~þ·žëu÷îcϧ àÁ> ŒRwNVö‹òòª©!„PËP]]»fÍÁÆ+*ú©ªöîÚuêÑ£IÿÈ“'ëëű±'Ÿ?/ûGj£”ž8q…Çó¹ÿé»ç—ú^–—÷53:sæ¦òò*®Â;w½G )¥‡%JÖÏí¥cÇ)’•ÿýcýÛ-iô$þÝZþÖ52»è##„t<ØK^^¶‰l‡_ Z6t¨ÏñãËÚ´ÑÏË»±ÕÓsÊ•+›tuÕ #£°¦¦.=½ðÒ¥ë^^íÙï'PJ…œqãú€P˜K)½re“££…TäåeYþE‹v¿zU><=íöì93{öˆw<J©P˜«ªªdaaø¿Þ@INÎm×ÎLEEñCêA!Ôü4xnRYY…Ÿ_xUUMTTH‡V••5{÷ž X¸råݰ!òC)MHL˜°¦gO·äw‡$+¡”þe,!äÚµ-ÆÆ:,±ººöÚµì3~xò¤$.n®¯¯kqñaõ÷h!WÿÅ‹,- %ß’“ûS¯ã]ZûÞ(¥¯^U¾í$²^úK3´| ‚>}"‹‹ëéi6úRVö/þ7HMÍ5jéüù£gÏd5¸»Û$$¬ru8wîöØØo@ È‘““6¬ûÚµ»usJiaañË—¯]]mX¾““¥‚‚\£{¹p!}ýúCYY»Ù ww›„Addà;^D!))¹íÛ·áñ>ô¢C)²ÝÝmÿÕKB¡O¥4"bëË—¯RR¶©©)³ÄåË'ÔÖŠæÍ‹:ÔÇÈH罿)ùÿŸÉúG¾q$‡Þ¥6.¿ŽŽš¾¾—nf¦WZZ>uê†-[f¶j¥$ùÖûµG[[­a%·µk¿"QýÑ£I?üp4)i#!„;‰­Z)±}-[6^ò$zyM 4hP׿ì}¶pnR ×ô?HJ©XLµ´ü¿ûî¥t÷î3ööÁòò¾ªª½½¼¦]¼˜I)¥”ΛëêjÍ ¬*¹ ú9rI,¦”Ò””\[[Óqãúž|1›ŽE)MO/èÙs–ªjo%¥žÝºMrX:›‚uò䵑#£54újjö[»ö§÷9s!„>ååU»wŸ Ä @)Œ ¼pa}ëÖšR·öE¢úÅ‹÷˜›“—÷µ²±víOì[ò矯ðx>Û·ÿÂrFEý¨¢ÒëæÍ;ýûÏ¥”š˜ áó»7QœÍቋ;çä4VAÁ×Ñqìo¿¥³ïº:Ñœ9Ûõõ)*úùù…çæq‰‹;go,'×COoàØ±«JKË¥ŽNªñ’é<O,¦b±˜›>ÔDêëÅQQ?}¥ àÛ¥KèòåûÎj8µé?:¶ßÝ»Ï8;SPðµ°>3œ-óòânÝÚoccâç^]] o¦`-Z´kÈîwî˜>ý«ÈȘ÷>}!„þk~nÒõë·kjê:vl'Õ¥ÖÑQïÔ©œÜŸîIB¦O߸ÿ¹­[à ö-[6~ÅŠ}‹ï€~ý:Nšä?kÖ–¢¢§/fFGïݰaZ»vf»wÏ&„¤¦n/.> o+Î|ÿý‘­[ÃRR¶)++Œ¹T,¦¬ÈΧbbÂsröôéÓqÞ¼,sAAqpðò€ï‚‚}‡/þõ×ÔÙ³·I} 7¼±Èúî¿ý–¾dÉn__WÉH©‰6DFÆlÚtlãÆé¹¹{|¢¢vAÞ”|Ùô±¯^ý¿õë§ffî41Ñ YõcLLXfæ##  ¥õõbJiFFá¸q«LM‡;–RTôÓŠ$O¢T¸“HY¹rbQÑOQQ!ññ—LL†Œ¿:#£°áQ|Îpü¥%ÓÑéuu"ppaÿTž=;Îe`÷æeee:t°ÊË»O)ݶ턉››MLLXLLddÖ׋]]­¥†MÙ=u——-))/,,ž9sL:hʔÇéêª 9láîÝÇOŸ–ÆÇ'éêl¡¥¥áÕ«› !»wŸö÷אַ®ÂÒ !¬Ù"Q}ÃáZ©k4ËŸ}§¼¼jçΈŽí`êÔÁÁÁËËË«”•¦NÝàëë²víBˆ¾¾VdäˆI“ÖÖÔÔ½-](ÌQVVh×άgÏYÞ Ž]]õ°°¡C†DUTT‹Å4&&|èPö9tîì{’]ú„ÂBÈæÍ߸ºZ³üG–µ!„ú(ظ´††Ê»Lžyò¤dÛ¶çέíÖÍ‘bb¢ûðá‹ùówÌ™3JV–¿fÍ”ÄÄŒqãVåçß>ü‹1czûâÓÑQÓÓÓ|ú´”÷övcc®8«É’±ì[uÊ”AAËž?/“‘áÇÆžŒ‰ ëׯ#!dÆŒ¯ lÞ|žzôò;ÄâßÞ–ù3„1CK––¶3F^~öìZ5øóŒI¶Ø×ÁÁ\QQÞÉÉòÀ…sçn÷ð˜ìãã¼aÃÔvíÌàõëJPUUjx¡¹v-ËÂÂ@II>)é:¥”]D†ÿbΜíÛ¶ˆˆÌÈ(ìׯ3°IJññÑvv¦’•((ȱG\»–½aÃ4®m”ÒçÏËø|žºú;]¦ÙhMMUvÁ6 !Õ?¿r%ëĉå\Íššª"Q}~þƒFÓ+*ª““s]\Ú>zôâ·ßÒ““sûí¥®NÄnÀÈÈð/_¾±qã‘ÊÊšÊÊêž98˜³=&'çzyµg¥4#£ÀÚÚä}O B¡L[[ ^¼xeiùë (¥™™·êëÅ}ûFr9ëëÅÕÕµ.nž»ûDíÍ›¿iX[ÅÙKKË?òÁnÿ×Õ‰²³ïŠDõžžvÜwYçÎ,fèÔÉþ«¯ºMœ¸vîÜØ=\üý;ìÕðöÛøå—††Ú"Qýùói³goóósÛ´éÉñ|NÃ6äæÕÖŠ¸n:¥´kWG©˜áÈ‘%mÚèK¦èéiþ­c·³3eo)++€¹¹>k<÷u ÅÄœ92zâDÿqãúè訳öp'ÑÊÊèí'ð¾GlìÉ­[®­­[° ¨aŽ&Š·x3´dÆÆºÜ?}}ÍF— …9vì"2dˆ÷À]öî=ãï?§°p?!`f¦wî<26þÓ2¯’’×\˜>}0…¹ÊÊ ööæ //;qb¿ØØ“}út¬©©ã3((Èùø87" ”æåݯ­99YJ3™™…vvf︠™-€vt´”‘áÃîBu55e6¶hooÎŽ‘’‘Q ¡¡úòå«FÓ55U…œþý»äç?€óç×I^×!rr²^^S-, ÃÇYY™˜èº¹Môõue/¡0'4tW'7Ò‚B¨yøós“Ø-¡«W³<=íþ? ¥½1bÉ¢EcØÍo „ˆÅb8x0ªmÛ?õMŒtØwDjjÇ{ôèEFFa—.R{n¢xVÖàñˆäصÄ6à¾w¸%¼<9xpaNNÑ©S×ΟO Z¶s穳g×HÖÌ}íšš¶63Ó#„ØÚš¶mkÜ·odMMÝáË~< ÛÀúë’mh8Ànb¢ËúËcçóyžIÕÈd§… ƒ##G8paãÆ£K–ì>ü‹¯¿èìlÉD[ÉR¾`'±kW‡´´‚M›â¸`kkºhQÈðá_4ý<ÉÏ®ghášXÏÀûfdººZÿþû OÏÉ ++ÒkÍš)wï>.++'„XY9;[mÚ/YU}½xâĵª3g€ää—¶|>],&Mêÿôiɶm?óx„Ýqrœœ, ¬…/_¾uÉÇG\¼˜éííôŽ{Ø8CYY9[G!Õ8paÈoPRR€’’׬ý••5»vþê«noK/))/((vuµÖÔT‘¨ÞÈHÇÈHGAA®wïo/_¾)æ=ݲefÿþíìL³²îæç?ðöv†7S°¸û=uu¢ÔÔ|wwŒB¨¹RP5Êoóæc’ëë!ëÖ¼|ù¦¡¡¶ä7W»vf„¢¢'VVFVVF––†W¯f/\ø#ËŸÿ`æÌMQQ!C†ø-cf$¿[¹â––†¬ÉâÜ®%‹´oo!''sñbw_ Èfo%%ݘ(ÅÏÏuñâ1ññI±±'ýL¤Úàèh!++sõjVÃ6H•’J‘Üû{;ûÆ—zWAA.8¸WJJLBª²²rI„EEyv_¿®’<_ÜIOÏɯ^Uœ>½:5u[pp/ ˜¡åëÝÛC,þM__«á䢌ŒÂÚZ‘‡‡‹‹uQÑÓ¾xñêÁƒgG^tt´ÐÐPJéæÍß$$FŽŒÎÈ(,)y”t½W¯YAÎ/¿¬`  s=<ì¸úõô4‡ ë¾k×i“V­”D¢ú´´‚¬ªªj¤þØl6˜ #Ãç.7©©ù99÷FîÕðSSSWSS'™Âf7ݸq»²²fÏž³ÅcÇ®ª¨¨ž;wtè`eii8o^lqñóÂÂ …uuõ ¿-=99—Rêáaçèhikk:þއ_¤§öí;[^^®oߎ††Ú„C‡KKËÏŸOc«¢Ù<.¡0—âæfÃ.d7nÜ©ªª‘¼5…B¨y!„DG“‘á{yM=z4©¨èiFFá´i߯[whéÒqmÚèKŽéŒå;wnìÿþwþÞ½'‡]œ6mƒ²²‚¬,¿®®~äÈh{{óo¿¶aÃÔêêÚÐÐõ ¨(×®e?xðŒ+~àÀ…{÷žüôS"WœkTGYCCeÆŒ¯æÎ=xð·{÷žÄÄœ`“@EE16ödhèú¼¼û7oÞ9~üw ÕFãèÁSJgÍÖ¥‹CDDÌ£G/~&RmÐÒj5y²ÿܹÛ¿ü¦ Ǥ*þ¼ìÑ£R’wßãØ†’ouëæxøðâ‚‚}¬wããg'qúôì$ZXB ö:´ˆ5j>7 }ž(¥AN«VJ66&ŠŠr§N­üùçË&&CìíC!ññÑìŸ!ÄÝÝF Ø*ÕñÅL]ÝcÇ®ruµNOe‹nß~ôìY)ë(s5O›6¸¶VÄn±ß¸q§²²zÓ¦cJJ=¥því: Úðòå+n«Vý¯ÿÎ:XIµ¹®Nd`0xÊ”ï¤. éé…|>ïäɱ±¿8:Žyüøebâ†Ö­5!22ü„„U„›Qnn54T®^Ýl` Õhº¾¾¦@£§§il¬Cœ8±\QQÞÚz¤Ÿ_˜³³åùóë””ä-- ×®²~ý!SÓ¡;vœ\¾|°¡’ääkkcGB‚lnÊB¡æáÏÏM-­V—/oòõuŒŒ±²ѵëÔÌÌ[GŽ,Úðf\LLxhèÀ9s¶[Y˜9ó‡I“üøa,X°#+ëî?Fòù<-­V[·†íß>.‡í—_zŒ½ÜÚzÔÇ/ÞV\rR;]¶l¬YÃfÍÚbm=rÿþ_£¢‚Yº³³e\ܼkײÇzyMSRRøå—RSz!<Ù±ãÛÚÚº¯¿þ®‘O¨AV¯ž<~|߯¿þÎÚzäÞ½g#"€»UO)õòšf`0Xꯢ¢J²’¿{ì Cˆ†Me®!ššªžÄY³†IælXâ42ç 5K„4üéÊfþñý¶oŸà II×ýý礥mÇÀ-ñþÌ×!„>uÍöûôc¡”þúkª½½9÷Ó±›6‹ˆØZVvŠÇ“Ž.š·Ïû+ ÇÐGÆîgôìé.æPJ++k&MZ·cG !„ЧrøðÅÀÀ%))ywï>ŽOZºtoPPÏ–0ÀçþÜ$gh)šù}‘3g’ÃÃ7_¿¾38xE»væ³fIø¢âó¾Iƒj.~ì43”Ò²²Šo¿ÝúóÏ—_¾|md¤3j”ßœ9#[â2ân»Æ -E3Ðçc„Чcô6ŸuÌ€s“B!„ú+Ÿ÷ üM7„B¨åú¼{9ï Çíjc„B¨EÃðßÒàY«!À¹I!„BýµÏ{=Æ !„Boà° BÁ¹IŸ;JéÿþwaìØ•Ç«©)¿-™Ù0??×mÛÂ%:p༻w§§Ç6QÿþýçYå|>oýúÃsæŒäñþ¿†Ñ£—;8´™<¹¿ÁàììÝZïþˆÕ»w·i3yRrÿþSww[©ßlrúõëD)}Û%›RÊ*—““7nu~þýyóFqï.Z´ûÕ«Šðð¡àéi·gϙٳG¼c³)¥Ba®ªª’…Å @INÎm×Î „úoPJ££÷.\ø#ŸÏsw·ÕÐPIK+X¿þpRÒõ+W6ÉÊ6Õ9‘üÒy÷ë?¥tÀ€. ¡¡ ÎÎãnÞ¼#la58;e/ÿ¿ò†£ 4‘8·ssܪ?r6–ç†üñ,{áVpµ¦<ÖãlºÔ'œÒ »ü9§|®0fhù}úDæ~Ô]JÓWgBHJJxxØqSJiQÑÓÇ_6}‡Â*§”^¹r³oߎ\ .¤¯_(+k7»ªº»Û$$"#ßñ €’’’Û¾}ÉQ‹÷C)²ÝÝm›~Býƒ!7€Ã‡ûûw€ŠŠjÉ©©ùII7||œšþfá~Zêݯۄøøhîå·¹àæÍ;\¶&*¡”¾{NÉ ïä ô©Áõ -œäoö5¼TQJÅbª¥åÿÝw‡(¥»wŸ±·–—÷UUííå5íâÅLJ)¥455OUU©];3É«ž@îÿ˜v IDATî¶%%¯ùüî'O^92ZC£¯¦f¿µkbÙXåóæÅòùÝss‹Ö¬9øÕW )¥µµ¢É“×…… Õ××$„BÚ´1ÈÈ(l´…3flTQéUYY#•.æèêjôï?WQÑÏÕuBnnw°))y~~á**½ÔÕû//+«x[:kLfæ-77¸qãv¿~³UU{«©õ>|ñ³g¥ìHO/èÙs–ªjo%¥žÝºMrXzÇŽBˆHËÉõ ÛÌm°ë§X,€½{Ϥ§R ÊÊ §N­¶8:Zp7§NŸv骤ÔSE¥—·÷ôË—o²²ì‹#'§ÈËkš¢¢ŸƒCȹs)l„xâ½ÿù®]§**úÙÙ>qâ +Åãùðx>ÉɹäÍÜw÷I,‘epwŸDˆ7¥ôÎGÎÓÒò—•ýÂÀ`ð×_¯¯¨¨¦”òùÝ¥r&%]÷ñ™¡¬ÜKM­Ï—_F¤¦æ³o"ØHÆ6ôÍ8CÃ",OUU¹ù0'§±eel£¦¦x}:0fhá¤f5|· àAIÉkwwÛ¬¬»cƬŒˆ|öìxVÖn[[Sÿ955uššïêjÍçó$«JNÎQVVh×ÎL(Ì¥”.Z´kÈîwî˜>ý«ÈȘòò*J)«¼W/„„U„üü¸À¾}ç>|:ûbÐÒR+/¯zõª²a W­šüâÅ %%yɽ‹Å4-­@ ÈŽˆ,(ØG YÁjKO/èÖmº½½yAÁ¾¤¤W®dM˜°†õû¦@FFaMMûºvêêjSX¸_ ØrïÞ“Q£–À½{O||f8;[æåÅݺµßÆÆÄÏ/¼ºº=öòü!„P³E)­¨¨ Z¦¡¡úÍ7lcþü Öã GŽ\rq¯§7pРù kk-­V¬ìÙ³)}ûF^¹’åâÒÖÚÚäÒ¥ë½zͺsç1¼é‚Ož¼NF†¯««‘•uwذÅÕÕµ\81eÊ:§­­–›[4bD4»ëÄuÜÙ$%ðöv0 Ë€]X)ö† ‰:~ür«VJ={º‰Dõ[¶Ÿ1c#ôïßY2gRÒ=Â.]ºîìléädyölr·nÓnÞ¼#ذqÛaƒŠŠòK—Ž¿~ýöÊ•ûÙÆ¢E»p\}:0fhÉttúëèô>|188„èêÐÑé/™Ý­—••éÐÁJ$ª§”nÛv"/¯ÈÄD7&&¬¬ì¤‚‚¤¦æ{zÚI Y9..mù|žP˜CÙ¼ùÿNêê*––†”R¬r—¶×¯ßÒÓÓ´´4”••!„ìÞ}Úß¿³ºº W[]X¤ŽBNNFj­!$;ûnyyÕúõS;v´34Ôž:u°@Õ©S7øúº¬];E__ËÁ¡Mdäˆøø¤ššº·¥ …?Ó§o ð^¸ptëÖÖÖÆaaCÏK­¨¨‹iLLøŠ ´ôô4;wv(/¯úcžjcÇþOŸF„j–!áá› ,Z½‡m°+?¥tÁ‚à~˜accÏž•;öûäÉëìì‚Xš½G,¦óæºtéû””˜Þ~~n÷î=†7]ðY³†^¸ð]bâzJéË—¯ ‹áM`0cÆW‰‰ëÏ[ ååU·o?‰ŽûÑ£KØöªU“âã£ãã£Y©U«&=º²³ïÀر}öí›ùòß}:b„/›Ý$™3*êǺ:Ql쬤¤‰‰ëw숨¬¬Y¶,ŽUÞè8Wä÷߸xqW„e6¬»‡‡íêÕLM[³+W²>™C¨13´diiÛÓÒ¶oÜ8Ξ]Ë^Juý““sÌåœ,XøøñKÉ_|1“»Sòðá‹G^¸¹ÙHÞí¨©©KIÉëØ±$'çzyµwuµJiFFµµ‰¢¢{ËÁÁ\AA.--Ÿ«¡ªªæÚµl//GÉ‹éóçe|>O]]å]î©PJ…Â\MMUîæ…‰ê‹‹Ÿ_¹’5~|?nCSSU$ªÏÏÐhzEEurr®‹KÛG^üö[úÁƒ¿±@KWwÀر+)¥"Q½Œ ÿòå]º„vè0ÞÖ6hÊ”uæJJòìÓkxìÿÔéC¡f­¸øylìI¹=\ØFPPOnêG¦L韽»°pÿ?F†„ôVVVxøðEhèöí“–V~~nì:¿cÇ·GŽ,öñqæºãÝ»»€‰Ik– ÿ²mö»C)ecæo›,$9&À6¦O ìÔÖö:tÑóç¥66& G„ÂJé˜1+Ù§ààå”ÒK—®71Î æÀ˜1+ÙªààåpéÒuò˜6mp}½xþülcÞ¼¦žLˆÐ ×@·dÆÆº”Rmm5Ð××Ô××’ÊÀƸÅÍC†xØeïÞs‘‘1þþs ÷ùù÷ÀÁ¡ •Xý믩ÕÕµ=z¸€P˜:ˆ»> 9¶ÜÅÑÃÃRSóGòcè¼¼ûµµ"''KÉ‹iff¡Ù;.h&„¤¤ä::ZÊÈðY{23 utÔÕÔ”32 ÀÞÞœkOFF††êË—¯M×ÔT sú÷ï’ŸÿΟ_§§§)¹#99Y/¯©†ááìþ½ó‹êèþø™]`—&,M:¢‹QzQ¢`CØlK¢X±ÅÞË‹ Kü©1j‚•hl1M‚%ƲKGq—&H‘^–]˜ßï»/-Ä%óyöɳ™;sî\<ß9Ó®•©¹¹›Ûœ¡C]ɽ´zï¯óÈ( ¥Ó`b¢·xñĽ{/üðÃ}òåË/XºÔ„Bqxøw2™üâÅ-=z÷èaÙ²%‚ÅBë×òzBycÐy†Nj{?Ƹ¡Až””éêjýûï<=瀲²ÒŒÃ÷ì™—“SXYY/¥ËË+fœ LÖ¸}ûi++SÇœœÂ¢¢ OO;ò«L&O'gI¥2RxeemVV9ª!TVV úúÚŠ>úÎdÇ.ì!ó ••5d,G.oŒŒ¼àjj\(/¯&öH$Òˆˆë'z·•^^^“‘‘ïêjMN—ËMMõMMõ¹\•#VÜ»÷X(åæ9²tÌ/;;‹ÔÔœôô<'hëÞ_çyQ(J§c¼uë,[[‹íÛO/Y@¾”–VaŒuu»|ÿý+W~?v,ŠéÐ'%e€¡¡ñ펎|ˆŠz@´còä-ZZ“s&Úš%…ývÁKq$ ƘÅb!„›àÙ³sçîݶíÔ”)CââŽfdœ€¼¼b²öI1§‹KO>܃,p Ö§O©S‡¶csÉ¥K[/]ÚÊ\B~=þöo¿¥,]PRRI¾ èôž…ÒhÌÐù1£©é–‘Qó×¥!„’’2äv..Ö¹¹E^*-­ÊË+¾t鎃CO!äàУÿ>S§n=vìÇû÷S##o°0%%+"b‹…„B1BÈÍ͆¸ÈG²ëꤞžvÀN–9éëk“s'Èd‚’› BâãÓE¢gÁÁÛYR©ŒÌ)3`Œëë=z*‘HOú9##Ö¬]µµõk×€³³Ÿo²nÝñüü’ÌÌ|ÿ2YãÆÓÛJcŒ=<ìø¶¶ëן(((MLÌôó[Íá¨øùõ51ÑC]¸p»¢¢&&&ìŠîÕ«´sï …BAq¹*«ª«%{öD’/Û¶€îÝ-1ž3g³óg£G¯±·Ÿ¾eË)„ÐÖ­³H{õê©¡={¾óòZàîòÃ÷1ÆcÆxAǃv:î ¯¯³gïù装uu ŠÿËãi>|øäúuáàÁKFŽ\åë»,-¬­Íš]¸dI‹…Ö¬9ææ6gÈ¥›¶n=UXXÖŽUäŦkÖsw:ts ‘¶U«ŽöîÝ}íÚ òeË–™J£PÞ4fø÷‚1D]º¨Ùؘ«ªªüôÓÎ~¸gn`o?½Üé¡~øÏ´iCwí:7hÐâùó÷ë _’Îql¬ÈÚÚ¬Kµ—‹sž¨«síí-€)œÏ7qtä÷í;ïòå»`l¬eeULù»v3ÆËÙÙª™…2™ÜØx¼yûðÿîÁHLÌd³YQQ;ŽÿÑÁafaaÙíÛºvå!„””ØäŒ&› 7·9<žÆƒ‡u[M72ÒD††:ffúÁµkaªªkëi¾¾Ëœœø11{ÕÔ8|¾Ixø¼ýû/XXž86ÈTI;÷N¡P( + ¿îÛ·€ùB|fxøü¯¾ZÞ¯ŸýÓ§ÏúéaaaÙ!.?ý´sÊ”ÁäZ?¿¾W®lsw·IHHò$ÇÇÇñ—_­¬L»ã¯<ϰsgˆ©©~ZÚ……eååÕŠÿ[]-ùùç=³f}¬ªÊùå—¸òòjŸ_ WQQjv¡‡‡mTÔÎú¤¥ýq÷î£^½º}ýõÊ9sFÁË5N-­>ܽå%³gû‘øêéÓsÉÉ'´´ÔÉ.W¥åP…òOhÛI@¨•7¾à?ß1êØ±Ïýý}àîݔѣ×$$ëÖÍ:ÇÎò¡ïÔ¤PÞ)ˆ:PÞS¨Ó¦¼„Î3PÞ)! æNŽ›H¤!!{OœXI …B¡P(”÷3PÞ5¡™3?¾~]sçî >nÜG4` P( …Byo¡k“: tö™òA@§¹)”w UÊë@6å%tžB¡P( …B¡´( …B¡P(J{ИB¡P( …B¡´( …B¡P(J{ИB¡P( …B¡´(ïŒñ·ßþ¢¬<¸¦¦î/s‡íÙóÝ9Ñ+-í™3wš™ùs¹C-,-ú¢¸¸‚)9'§Å˜‘‘׬.ŒñÙ³1ªª¾••µ·ÆššºmÛN75áÚÚz-­‘ùù%¿c̘ôwëm Óàôl4 …òrüx‹5!æÓ¥ËÇC†,}òäyaó“'ÏX¬ÎÐêjÉ+û1±8·Y-ä3~üúW.cÜØØtòä ê])ÿ*”þi(ÿ B±±â^½ºih¨¶“ c¼eË©ªªÚeË^ÿ ßç“Oþ8ðêÕÿtïn”–öÇÊ•_zzλÿ6…bMMµ=LšÕ…ò÷÷ž0a‡£ü·jć†LOÿcíÚijjOO»S§n¬Z5¥ƒ÷‚bL¿N `ŒIƒ««sé»/(ÊûñQ`g×mÀ€> —7>|øäæÍDÿ}ƒTUÕΙ3ÊÈHOCCõÕüÆX §8Pñ§Q£¼^¹Ì¤¤ÌO?Ý­®Î ö %P((4fèüDG FŽ\•Ÿÿ½¡¡Î?Õ}Ä OÜÝmÛé cŒoÝJÚ¿ÿBjêÉ×·3>>=(hûúõÁ«WÿÙeww·‰ŽÞåê:gíÚcǯ€¸8qŸ>ÝY¬VêRV~•¡û÷ûùõU¨Q°zõÔ^Ž1&&!¯Ù!Òà4` P(ï!ÄGÀ´iC™•’’Jƒ±"ѳììç=z{zÚyzÚ½f-±±"pw·9|xÉñ‡¡¾OLÌX¾<ð5w(” º6©“£8sÚ–k{ôèé¨Q«55Ghiœ×Ô¡¦6ÌÛ;T ‘< òää,778yò†½ýtg¨¦æˆݹ“LòÈdsçî]¶,ÐØXþì@§ùú.×Ю­=rúô°ÊÊÚ–‹ˆ/>¨¡1\"‘6K_·î¸««50ÛçrUfÏuñâoMMc,Š xcƬUUõuu-çK›´µGÜÝÔTÿÎäAƒ–ƒ+öìùN([ZÅÅÕÖÖ¸y3qóæ©TÆá(?}úgccÝcÇ>€%Kþ/+« W¯nVWç&'g9;öí·¿„‡Ï EÐÔ„ 2e0lÜøÍÕ«÷²²ò1Æ¿ü-ÐÕí²iÓ ºÀ‰òA@c†ÎLBÂ1¸};)88ìçŸÃõõµ€éFcŒóòŠoÝJŒ_¹ò;¹„¸×œœÂß~K¹xq ““ËUáp”ù ˆ||I9ds³»» ()±ïÝ{tðàE‰D*‘Ôçå÷îmIfbcÅ..=•”ØŽŽüÈÈk×óð˜;p Ó {õêõõ >9p`©1/¯øþýÔkטZtt4åòÆÚÚzG¹}÷Š1®®–€¦¦ZËÎúÇ©=z«©q„B±ŽŽ&õb§\ÞH¬ur²***oµqòóKbb"#7´ HÒÉr bsII%›ÍÒÖÖèÈšW²š˜DúèŒIùù%­¶Fzz^[­DüùóÒVoA.olõa©ªªÛ0 ‹KObsRR†µµyûÆS(JÇa6@ÛÚZx{;dfæÇÄ$°Ù¬M:DKKÈjIGG¾²2[ ‘YâåË 33ºtQ³´4ª®®{𠂃‡@Ÿ>=ˆã"KaI!ššjS§Q4 0pÈåEE¦FG ªªjÉŒ„««5DFÆÀ¼ycµµ5Bƒ;ì¬h¹§§©èêÕ{:Q] 66æãÆF\XXFröë׋ c2Ÿ‘‘‡1¬Xq¶l™©££ùÖ[œByИ¡3cff€1ÖÓÓ####]Å_Bééy³×ÐPG1=-ípr²b:£qqiŽŽ|%‰DúøqöŠ“‰»¬¯o¸{7eñbÿºº†öèa²|ù$++Sss7·9C‡º’î¯P(3æ#RZ@€Ï¸q>ý˪UGG^“™y!HKû£¡AîèÈ'ù‰$ØÛ[2AKRR§©££Ù‘Îw·n†ýÜÌL_1yyudäÍÐÐ 'vpà+)±IùÉÉ™úúÚD«„BQÿþ}Újr6«£ã×à>yòÌÈH—ÇÓˆO òeÒ““3íìºupC3Ƙ˜Äf³H~Ƥ¤¤ÌV[£¬¬ª­V" ÞÖ-¨¨(·ú°H9B¡hÁ‚ñL™ˆÌ/Q(ÊÌ3ÀŒ#Höí·¿Ü¾8oÞxé€ H‘ï¾¾ú¨‡Ÿ€««5BŸ_ÜÔ„ÀÚÚ ž>-6›E¦IÉ…}Ô»Õ ÐŸ}¶ûôéŸ54TGŽô8Ð9'§°´´jÐ gÈÊ* µ·xŠOww;¢V¥ à‡“’2B,26Ö%÷8zôGŒ’öéÓž>}þÝw7SRž:8ôøì3¿Ž *Q(ït?C'§ý c2¼!—7š™˜™p¹*#F¬¸wﱪ*ÊË«ÉåååÕß|M:ŽOžä4669;÷$ëìºRYYëîn#Šrs‹ŽY:fŒ—EjjNzzž”—×dd仺Zÿþû#OϹ ¬¬4cÆð={æåäVVÖ@YY5èëkǪ¦Æ%õ’Zêê""®OœèÝAÇjeeêäduèÐåf»æÌ çñ4—. ¡P\YYCÊ—Ë##oø@}}CJÊS77[¦qLMõMMõ™ÆápT€l†Ãgdä;:ΊŠzPYY›•U@Ά"-çN²cm&ó ••5$¿L&gLj«5ÚJg¼­çË<¬±c?êÕ«ó°0ÆÙÙÏ‹Š*<=혖‰O'+ƒ) åðüyinn¼­GmÞ<ƒÍf}ÿýû÷SáÏS•DàêúßéOÏ^/·5“£l@EE™$’^þñãQ`g×ÌÓ2¶ôÃã n@d䯳g×Ïšõ1Y•DæxêÍ Áðù&jjœ‚‚’}û.Àþý ™A" åý‡Æ Ÿ#<ššné¶/qpàÛÚZ¬_"?¿$!!ÃÏo5‡£âç××ÙÙÊÈHwýú¥ÉÉY~~«KJ*Éè†9ßdݺã¥YYþþe²Æ§7 {¤RYÏÚ ŒñáÃK¢£Ó¦mKJÊ,/¯¾{7eøðÏÑ?îÐÔT­¯oxôè©D"=uê猌üY³vÕÖÖ¯] ry£‡‡-Ó8¥‰‰™L㸸ô45Õß¼9¢°°,!!câÄ ^^öS¦ ![5ôõµÉiHqqi"ѳààá-C5bv³ôº:)1éäÉééyŠ&µÕm¥3 ÞÖóeVyyõ¯¿Æ+>,¡PŒrs³!røèQv]ô5;¤P(EÈYFÊÊJ..ÖÄZZ×vî<‹1®¨¨!Ó¤îî¶••µä;`ÅH$œ°´4êÞÝ!4fÌš±cב¾¸››5”–VefæcŒûõëÕêhÒÝk>Ð IDAT?vìÚ¾}ß¼”¨‰““ €Ï>ÛÖ¯ßü²²j[ ‹®¡çÏK ,ìÛo¿ýc¼`Á8X²äÿ¦NÝÖ¯ßüèh¾¾ö_,JMÍ©­­WRb;9ñ™$ õêeY_ß+ 8`@0P> hÌð¯†ÅB×®…©ªr¬­§ùú.srâÇÄìUWçr¹*W¯n/,,ëÞ}Ò¼yût2Ïзo¯9sFÍŸ¿ðà¥ÊÊJ³fäóMtt4ù|“ððyû÷_°°ßÄё߷ï¼Ë—ïÀ®]çÆŒñrrâ7›ê‘ˉÙÍÒ[5‰¼R£­Öh+4¸¹¹A[Ï×ÊÊ´­‡+²¶6#k´0ÆÁuu.=ÓƒB¡¼AÈ;úôéΜ‡1ž={üøãƒ¬¬rz§iee¢ðÝc\VVMVÏ’…C,:wnƒE^^1Ƙ蔇‡¼QRb{x´ò¦ŒqDÄj[[‹¨¨‡ÇŽ]›4i#²nûöÏV¬˜‘‘7õõµví 9rd)ɰzõ4--õ;w’Éþ·Å‹':´ØÊÊôòå»ÙÙϧNòðááîÝÈGïÞݹÜÿž‡"«˜ÔÕ¹;w†Ð€òaZö·($¾ý6 ÆoÞqøðÕ/.¿=×ØØ¤«;êØ±Ï;¾é-¸¹¾¾áêÕí¯\Æø÷ß½&!ᘥ¥Ñ´­3€|€ú å]òÖÔá} $$Ü̬맟Ž40ЖÉ-,^¼(ÏÊ:û~úÞ²²jgçOss‹6mš±aÃ'ÿ´9ƒ:mÊKèhÊ_@Ö•¶Ü öfa³Yƹ …"Ÿ·WK;ÙðÒÒª7„»wÏ}åMid_AHÈÞ'V¾Ÿ¢E¡P(Œño¿¥ˆÅ¹.Ürs³ILÌxñ¢|øp÷÷Í÷bŒe²Æ‘#W>yòìùóRó+&Ñ­Ï”º6‰ò45a¡PLŽ}{µ`ŒgÎüøúuá?5ñ…š4iK¯^Ó}}Ý>ùdØ+»r„Ðܹ{ƒƒ‡ßÿÍZH¡P(EBgά<Ø9;»ð›o¢óòŠgÌqúôÚ÷mB¨´´òÉ“g%%•}ûöºreû_N¡¼‡ÐµI…N=ûLé<Ðin åCÕò:P§My g P( …B¡P(íA÷3P( …Ò©A>ÿ´ åƒ‡Æ  …B¡tjèÚ$Ê+CNÊKèÚ$ …B¡P( …Ò4f P( …B¡P(íAc†;ãýû¿×ÒÙØØônJ»{7eâÄ ††ãTT†˜™ùÏŸ¿¿¤¤òoßUSS§¬<øÜ¹˜¿¼ c¶gÏwµµõZZ#óóK:^ ÆøìÙUUßÊÊÚvòÔÔÔu¼L …BéÜÔÔÔmÛvº© cŒÍÌüY¬ù äÃb d³±X'œååÕlö ò«â‡Ë*‘H¯\ù½Ùµ]º|}nfÖuæÌÚÚ#utFíÙóókbbưaŸkjŽPSæí*ˆ˜Ož¼ao?ê©9bÀ€Ewî$ÿeiÛ¶vqé¹jÕÆ„±±îùó›¼½0Æqqi¾¾Ë54†kkœ>=ŒY”šš3jÔjuõá'Nü—FÂŒñ£GOGZ­©9BKkääÉ[Š‹+HºLÖ8wîÞeËuIíÝ»'%e¶*‹ÔÐ.‘H§¼›š°®îè}û. ô¨¨‡Ó¦mãñüttF…‡ŸÇU°ÙƒÒÒþx#OŠB¡PÞ%í«!55çãWª© ³´œq=$$|Ò¤ÍmùÞ¢¢ „|ÄâÜððó&lP,G$zöÉ'Û}|÷îÏÌÄʼn{ö4mõÈMqqiÎÎ=›ùøq¶ª*GM ëÖwuµ^³fªâ…ªªœÙ³G]¼øÆ€1nh!02Ò! ‚VÕ‚fé­*—‰‰^Ú˜BéTИ¡“£è[v—BB¡ºúh…E×ÌÌ3ÑÑ»þïÿ.EG \]m 55§ÿ…®®6™™g‚#Ïž½ ÚN„áÌ™_ J,Gî!¤««USSW]Ý|Æx×®¹¥¥×TUU%!##¯¼¼ÚÝÝ–L oÞ0(;ûÏ›ª­­×ÓÓŠŽÞõ柅B¡¼}ÚW‰žõï¿ÐÆÆ<;;òüùM[·žºt鮋‹5´á{õô´®_ßJK;¹)³¼¼zìØuººZß}·QYY‰©](98ð[í¾‹Å¹UU''+&À¨­­ˆ¸¾sçÙ Æ)+³++ký5þÓOýZúsKK£ÊÊÚŠŠ`„€)‡AU•¤ek!PSã(–Ö–rQ(ÿBèû:3úúc@&“@ïÞ3ˆÓ,.¾ÊdÀÇÆŠØlÖ… ›íì,ÀÒÒ!DÜzS>zty`à@’ÓË«÷ñãQÄ?Ëå㯾ºfccîêj}ôè²£G—µ_šXœÛÔ„==í0Æ­ŠÄÂ…†u Ÿ‡22Ò]µjjHH¸T*[´è —ž†’ôÏ?ŸßäþýCB¡.<°té!RHuµ¤gO³­[g-Z4ÄâÜÆÆ&WWë–þ¼¼¼ȲR"ÚÚ̯Œ´T¢–B€j_¹(”4fèÌ$$€Û·“‚ƒÃ~þ9\__ ™g4È™tñ1ÆIIöö–ÄÛ*)±ïÝ{tðàE‰D*‘Ôçå÷îmIÆ`zDFn\»ö˜‡ÇÜXhooÙ~iä|!mmV†üü’û÷S¯] cºø::šrycFF^LLÂåËÛ˜tRš»»m^^ñ­[‰±±â+W~'åÈdrŒ±\ÞX_ßððá“)ÞiII%›ÍÒÖÖèˆë'›¹{÷¶ärUbcÅôqqéI®JJʰ¶6'íN”B¡P> ÚWŒqvváo¿¥(údO“ÅB..=Ûñ½Ä%*–³zõW?ÿwþü¦>}º3µcŒ\¾¼è—«±±b}}í¸¸£PQQ³iSÄÓ§¿þºWGG“”\]-MMµfþcüðajÆjjFía„ #s2^óS(3tfÌÌ 0ÆdhÇÈHÇÈH·YŒql¬xùòIÄ¥"„>|B†ðëê XØ£‡Éò哬¬LÍÍ ÜÜæ êÊäô÷÷7î£Ó§YµêèèÑk23Ï"­–F\­¾¾6¼xQnjª¯è|ÃÂÎÜ»÷hÉ’°··d®MJÊàñ4‹‹+ÀёϤ'&¦[Y™òx‰‰³Wq¤!¤¥¥žœœÕÐ g®"wšœœig× ¡6Wî6k¡PäáaB¡hÁ‚ñL9ÈÃÖLˆÇǧù¾ÖC¢P(”wNûê€zú´z÷î®è{­­Í54TÉÔV}/q‰Œ·üöÛ_öìùnÆO&LЬü¸81—«2p “²2»¥O E¶ff`jªúôZ{ûé 8{v=)¹[7CÈÎ~nnnÀ\…1®¨¨‰Œ¼:ÒÒþ B 8xD„ ƒ Bí(×êÕSÛ¾”Bé„Ðý œvV¬bŒ33óKK«˜n½T*KLÌps³¡P”›[täÈÒ1c¼ìì,RSsÒÓó||œàîÝOϹ ¬¬4sæˆ={æåäVVÖ´UÙ0׫W7ccÝsçbMÊÊ*ر㬓“•¦¦”—W“_%iDÄõ‰½É˜“^VV}âÄOîî6 ££ ry£©©¾©©>—«2bÄŠ{÷“l ¯¯­(wî$ûø8v0`hh'%eººZçäU‰i2Ÿîîn ••µYYä;…B¡|X´¯<ž&W0ãú'OÞps³†¶}/㉷Œ‹K›3'|üøþ6LoY¾@ rtä·0ÔÕISRž’ù b§ªªÊŠ“##oÆÇ§“>ßÄÉÉêСËÍ®˜3'œÇÓ\º4„@1‚ž›Ô¾ru¤ ¥3Ac†ÎψMM·ŒŒt[®û Åd®™¸øää,©Tæéi&&z¡ nWTÔÄÄ$m€^½º€‹‹unnÑÿýßåÒÒª?þ(ºt鎃Cmm¶J#cTl6k÷î¹_|qqóæˆ?þ(*+«>þ¶O¨··ÃúõÁÎÎV|¾ÉºuÇóóK23óýý7Êd7NwrâhoÜøM~~É“'Ï7U¨ÆÁokk±~ý‰‚‚ÒÄÄL?¿ÕŽŠŸ__ cHJJlFââÒD¢gÁÁÃ[J—T*“JeÍNçHJÊlh{xØ …b„›› ¹‹G²ëꤤ‰?ÎÆ“Q( …BùàhGzðù&kÖËË+NNÎ;v]~~ ÙÝ–ïe\¢D"-,,?~}Ïž¦_~¹L*m¨¯o¨«“ÖÕIÉ)rycBB†³³“Î|d2yBB†\Þ¨ø„дiC»tQûâ‹‹L qøð’èhAPÐö¤¤Ìòòêß4|øçèÇwhjª‚‚0óññéDZ*Dš%¶¯\oå‘P(ï14fø÷B¶,ÛÙuÓÐP%bàI—.j66æÀ盄‡ÏÛ¿ÿ‚…Eà‰Qaa³ ¬¬!¤¦Æùé§?üpÏÜ<ÀÞ~BèòåmÐViŒ‹Ÿ4iÐ?î¸};ÉÎ.ØÄdÂîÝçÖ® º|y›ŠŠ’’;:zBÈÆ&ÈÍm§ñàÁacc]UUÎåËÛrs_ôè1yÖ¬³fÄ“y„àÚµ0UU޵õ4_ßeNNü˜˜½d›±±”•U1R±k×¹1c¼œœþçŒ"]ÆÆæÍÛ×,] ãccEÖÖfäµncà‰º:×ÞÞ’4‘£#¿oßyïî™Q(Ê;AI‰}åÊv‰¤žÏŸ´ ”í[mù^Æ%^¾|÷ÀïóóK’“³ôõǨ© c>nns€ ¾:tEñ'5µaêêÃ#"® "„››µâPކ†ê”)C.\¸]ZZEÒ=@}…ò.y%u(*ª‹sûöµSRbÀ–-§öï¿ðâÅ•–‡ ½Ÿà?ß±3êØ±Ïýý}àîÝ"ݺÒ Íê´)/¡ó ”N›Í6ÌœÖWWײ÷ĉ•4` P(”Ž€1ÎÏ/öñ Œ¼YSSwïÞã/¿¼ºpáø%`„‹…ˆ`Œ%)0P(¯ (ŒñÌ™_¿.€¹s÷?¾ÿ?m…B¡| „ù»v…lÚ¡§7fÊ”­!!£7lþ°& „š Á¸qÑ€ByeèÚ¤Î]›Dù  ÓÜÊ;†ªåu N›ò:Ï@¡P( …B¡PÚƒÆ  …B¡P( ¥=hÌ@¡P( …B¡PÚƒÆ  …B¡P( ¥=hÌ@¡P( …B¡PÚƒÆ ”Œ±‘Ñx„|š}X¬††ãššð_ž¶gÏwoÊž»wS&NÜ`h8NEeˆ™™ÿüùûKJ*1ƵµõZZ#óóKþÖédgÏÆ¨ªúVVÖ¶sUMMÝ›0œB¡PÞ055uÛ¶VôÃiiÌœ¹ÓÌÌŸËja¸hÑÅÅ̯R©LUÕ×Ósn3÷ñÇ+\Œ1./¯f³±X›y{.w¨D"e®"^ýÕ¼.¡¥'½– P:4f |x „ž>='‘ÜHnlÚ4CI‰]ZzM"¹Q[{ýÙ³óAû'poÞ|²ªªvùòÀ7bÌŽg}|óxš×¯ï..¾zéÒÖ¸¸´ÕÔÔ©©q<=íNºÑñÁ1ÆþþÞQ]º¨µuÆ84ôà1žB¡PÞ Ä;ݸ!düð÷ßßqrúc|õê /Ÿ?¿)%%ËÓs^QQÆcœ””)•Ê3û-…éècŒ…B‘‡‡-…bŒñýû‡ˆÏ'ŸÚÚëQªª*¤Æ«««sÿ®×%´êÉßtóP(64fèüDG X¬ÏŸ—v¦wq¨ªrÈ'%%«W¯n::šä9åö¥âæÍÄýû/:´ä´Æ­[‰k×ߺuÖW_-wtäki©»ºZ_º´5+«àäÉàîn-èx]!ee¥öï!tÿþã×7žB¡üËyãê@¼“§§ñ`ññéAAÛ×­ûäë¯W:;[ikk¸»ÛDGïârUÖ®=†B "¥É“…‡G®Âgfæ—•U»ºÚ€@ RRb;:ò·O>\¢WÇÿ]¯ m{ò7Ò&J§Æ E¿ÙV7455güøõ<ž‡3ÔÕuö±$=..Í×w¹†Æpmí‘Ó§‡UVÖ’ô ¾¶°þx¥šÚ0KËI×CBÂ'MÚL<|KçÌx§ððó&lÀ¯[wÜÕÕzõêÿñ\®ÊìÙ£.^ü¬_Š‹ÛÚZ|ú©_TÔÃ'Ož‘<Ä“y†¸8qÏž¦\®J«6óê¡¿ëuÛòä&&zíþÓ¥PþuИ¡“£è7[wyôèi¿~ó»u3|ü8"7÷¼››Íĉê꤉‰ÞÞ¡öö–gîÞ=xÿ~êìÙ{ˆT…¢ÊÊš˜˜øŸ~Úùã;~øá~ß¾ó¬¬ÌD¢S«WOÛºõTU•¤¡Až˜˜qñâ°°Ùg`úô0bLNNáÀ‹œøiißfeµ±1÷õ]^W'Å?^–—Wüõ×?­\9%#ãŒyÿþ ]]m23Ï Gž={´]qòº°°,/¯ØÅÅZñ6Û±üÌ™_ J,×¾%-Ûp×®¹¥¥×ÔÔ8ŠYYY{çNÒgŸù±X¨Yþ1c¼z÷Z55uUU’–™‘‘W^^íînK¦ã7oŽ”:qÕª£µµõzzZׯïþ»Óî”÷Œé‡~Þî§ þRD¢gýû/´±1ÏÎŽ<~ÓÖ­§.]ºëâb ©©9-3ãÒÒNGFn¨¬¬ýõ×øO?õkæ¯B––F••µ5 ˆ\\zzyÙ;8ôØ·ï<ñÕqqb##]SS} EüV-léÕ1Æ×ë¶åÉ)J3”þi(o}ý1 “É wïÄ¥_e2`Œ—-;ìåe>üzäÈÒ#G–bŒ.<0t¨ I72Ò]µjjHH¸T*ãp”ccÓúöíõõ×+@.o€1‹m%UUY¢úÅ¡}ûÚÀÂ…¦O«©©SWç65á£G—ø½¼z?Eä@ x;w† äÓ§ïð÷÷Ù°á„P×®¼eË6ÕÖÖ««sÉxRllyF0Ú±üäÉë£G{ikkœmY”Ơ¢Òü_ BH,Îmjžžv-ó3yHãËå,S()++9;[íÙóBèðá%®®ÖÀç›`ŒY,B’’eh¨Óñ? …BiFGÔaîܽŒ:tíÊ[½zêìÙ{ÜÜl 4ô ¿¿ÏÆÁ`` Mœ³DRO¼“••)ˆÅ¹M®®ÖͼÙÖ ŽryyMffþÒ¥°páøyóömÛö©¶@ðçf†œœÂ¢¢ŠË—ïŒU´ŸÏ7yðà0BHÑ«Ã+yÝ¿ôä …@c†ÎLBÂ1¸};)88ìçŸÃõõµ@±{ýâEyLLBdä†f=?¿äþýÔkטœ::šrycmm}nnQyyõüùãȨP(f³Y3gŽx¹z5ÍÁ¯¬Ì E††:~~}Iº¦¦*466€’ûÞ½G^”H¤I}^^qïÞ–ªª*+æóMFŒp€¼¼â[·ccÅW®üN “Éäc¹¼‘±*>>ÃQîÝ»;“ÒŽå㇟8°ˆ´B¨-K:"crx‘¶¶F;›•KJ*ÙlV;yšå÷îmÉåªÄÆŠ èCŒqRR†µµ9i¥„„t"Û …òjü¥:dgþö[Š¢/åñ4Y,äâÒ³çL¼Q‡êj hj6?Î!ôðajÆjjœ»wS0Æ$<˜·vmÐåËÛTT”B»v3ÆËÙ٪م­–I ué¢fcc+²¶6#šŠž0Ó÷|¾‰£#¿oßyoâùS(Jë()±¯\Ù.‘ÔóùS‚‚¶“1 ²“ !héœÕÔ8Œwº|ù.ñ]îî6Á—ryãàÁK ÆÎšµËÕÕ:1ñ8ÙœðôéóââŠfsÅ‹Mhh“©ÔG²%’úC‡®¨© kö‰ˆ¸ͼúßõº„v<ù[ma åƒupþŽò¾ƒàÛÿ´/Ϻ>q"*;;òýÙRFNIÒÕuìØçþþ>ï Æ»wSF^“p¬[7Ã÷§þyO;‡?R(”7Ï+©CQQ…XœÛ·¯’¶l9µÿ…/®´ºLè¡¥W§^÷­@6å%tžò†AÅÅ¥‘¹ˆÚ–ÿ‚b±Ð°aîB¡èÄɉ4$dï‰+©tQ(”Œq~~±OhdäÍššº{÷ùåÕ… Ç¿?´ðêÔëR(o3PÞ0d{±‹‹õû6……š9óãë×…o[NȹæÁÁÃÇûˆJ…Bùà@9:òwí Ù´)BOoÌ”)[CBFoØüÞzu ^—ByÛеI…÷fm…Òtš›ByÇPu ¼ÔiS^Bç( …B¡P(J{ИB¡P( …B¡´( …B¡P(J{ИB¡P( …B¡´( …B¡P(J{ИÒ:ão¿ýEYypMMÝÛ(?88lÏžïjkëµ´Fæç—¼Âù]wï¦Lœ¸ÁÐpœŠÊ33ÿùó÷¿ ;) åß ÆX.oœ:u›šÚ0mí‘·o'½Ùò{öœ6cÆŽöóÔÔÔmÛvº© ¿ƒ31ÆD˜0ÆgÏÆ¨ªúVVÖþe½oC+1ÆŒ8¾ÂµT)o 3PZ!+îÕ«›††ê/|óæ“UUµË—ª«s==íNºñwOÔÞ±ã¬ÏbOóúõÝÅÅW/]Ú—öÆí¤P(”-¡;w’Ï‹‰ŽÞ%Ÿöð°}ƒ÷’’ÊÌÌ|7·öÊㆼqCˆ¼ƒ÷êlÙrªªªvÙ²ð÷÷®¨ˆêÒEí/ë}Z‰RSãqü[mŽ1Þ¹óGÊ[‚Æ Ÿèh‹5ðùóÒ¿ëz‚'îîoR$7o&îßáС%cŒ±»»Mt´àoÕrëVâڵǷnõÕWËùZZê®®Ö—.m}³vR(Jç¦}uÀß»÷¸kWÞ€} uTU9oªãŽ1 ÅàînÓN™¡û÷{zÚ½ƒ€áÖ­$"L!„²²‡£Ü‘zß’V"„ˆ8vüÞ1Æ·o'q¨¡1\"‘6Kß¶í´‹KÏU«¦0W!„LLôÞDƒQ(Ê¿‚öÕ¡© ëéÙ¸ñëÂÂ26{н{ÍÍöí»à뻜Ëzî\L«º€1Þ°ák ‹À3g~íÙsšªªïرkKK«,د§7šÇóÛ¸ñRPø„ËUéÓ§G[RRTTXœ~~„ ã–²BjLMÍùøã•jjÃ,-'ED\ Ÿ4i3¹‹¶”¨Ù½ÈdD˜ŒuɽëêŽÞ·ïB³0€‘$&ýõµ²UãÉ}ql5ii iUFÓ©8RÞ4fèä(*A«®çÑ£§ýúÍïÖÍðñãˆÜÜónn6'n¨¯oHJÊ”Jeîî¶II™ÞÞ¡öö–gîÞ=xÿ~êìÙ{@(cŒ7oŽ”:qÕª£µµõãdzû÷_èêj“™yV 8òìÙ‹  íÄ ž9óKAAÉ‚ãˆac]]­ššºª*IKËwíš[ZzMM£x ••µwî$}ö™‹õvGž( ¥Ó¾:°X(/ï‚o󿙵µ×--òòŠ¿þú§•+§ddœéÑä¥.a ¡PTYYÿÓO;üqÇ?ÜïÛwž••™Htjõêi[·ž"=i¡Pìäd¥¬ÌnKJôô´®_ßJK;¹!55§¥¬€XœÛ¿ÿBóììÈóç7mÝzêÒ¥»..Öí(QAA©â½L˜àÍÑ©ŒŒ¼òòjwwÛfMD$IUUEq¸êu´R$zÖªñ¤%‰8VW×5{:­Z5DßÁR.Ê¿¥ÚÊ[D_ ÈdrèÝ{q"ÅÅW™ ãeË{yÙ‡‡Ï#¿9²ôÈ‘¥c¡P¤®ÎíÕ«›OèС.{÷ÎCCU«¦†„„K¥2¡P„:|x‰‹KOàóM0Æ, BCúûûlØð B¨kWÞ²e›jkëÕÕ¹'O^=ÚK[[ƒ€"æÉåãfnNE¥ùß'BH,Îmjžžv-óS( ¥#tD ËŠ‹+úõëÅåªO`çÎÁƒ`òä--u¡¾¾ÃQŽMë۷׉+@.o€1¡¡ÀÀ@[EEIU•B¡è“O†‘/DJ\]­AAJ‚””,CC++Sx)+7“rY™;w¯——=±ÄÀ@{õꩳgï!£þm)Q³{ÁaÒÒR'í Š”••œ­U!ÔR’^S+‰ñD»vå1Æ“ ÇfJ×–%Œ8Re¤¼%hÌЙIH8·o'‡ýüs¸¾¾0NcüâEyLLBd䆖.)6VìâÒ³°°ìþýÔk×ÂÈU!M¹¼±¶¶>6V<`@—žäÚ¤¤ kksUU•¼¼â[·ccÅW®üNJ“Éääüúú†‡Ÿ8°Hц’’J6›¥­­ÑÁ•£älŠæ§P(JKÚWøsù!Dúß±±b>ßäã= /¯¸-]ÈÍ-*/¯ž?ÜËη˜ÍfÍœ9‚t‚ããÓøÊÊ쌌ü²²jW×?K0  0ÆŒ”@BB:é@·%+y¿ý–¢h §Éb!—ží(‘â½`ŒabT)6VÜ»·%—«ò—*ó:Z™]HŒgêeŒ')Œ8vd€ !Ĉ#P£¼%hÌЙ133Àëéi€‘‘Ž‘‘®â¯!‘èÆØÑ‘Ï¸˜ÔÔ##]OC(óQff>ØÛ[2N-))ƒÇÓÔÑÑ E ŒgÒ‘‡‡-¤§ç@LÌ^CCź´´Ô““³䎎|EYJNδ³ëÖÁ…F!}}mxñ¢ÜÔT_Ñ-†…Y½zêë4…B¡üKh_c'¶±1ïÒE „BÑ!.¤ëߎ.DG X,4`€É+rpèÁŒß32AFúÉw"%LW›ä!ùããÓƒ‚|¡mY‹s wïîŒ%‰‰éÖÖæªdu«JÄÜ ©1-í"LLŠP(òðèÐh=™gx5­|ú´€ÏÔKŒ×ÔT#9‰8vp¡ƘG33Åô;ÎRq¤¼è~†NN;+V1ÆŽ 44ÈI¶ôô>¡ÞÞo¯ ) ¥óÑ–:€\Þ˜îæf bqnU•„éø¶¥ Š™€ $À'&fÊdr„"ò…‘’GQJ?Î&c牔‘•‚‚ÒÄÄLFVzðù&kÖËÏ/IIy:vìºüükh[‰ïBŒ0’’2äÍæ0ÆD’ðÿžSôzZù§ñyyÅÉÿÏÞ‡5um _; ³f™§ A Ȥµ¬uªÎV¯¾´úÕŠ¶hªVÑgm­õZÔ+z«·jë€¶å ¯µ5TL˜°Ê,aL`ìš› ˜bAŸ~ì³Î>Ág¯³ÎÞç$«@ÕyvÜ´´–Ûßìk߆Çã²ä¸n]°õª !€cBÏSÏ ¥´¬¬F&+8P¤£Ã€µkãwî<ñàÁinçsJKK+KL'?ÏLôða5ë<Ç€uë©:ÿË/7Xrtq±ynýy"´Ñc8Ï€žvãgĈ@‰DJ)­¯oš3gûþýK±`@!ô´!%%e!!QÇŽý»¶¶þ—_nüýïß/X0þ© àr9,1=ÏLD)Uu^.o¸r妪ó Í,9öˆ‚!58Ï -^’;I/¦.^üõõëÞ£§§Ë’%S°`xµà-+„ž³—$;ü5[·~»gÏ÷ÅÅe}ú˜ÎšõîÊ•3ØmûΣ”þøcKLϹlضíx›Îs¹–?ýô½çÖ“?ƒ6z km¡ÕYiL?=g˜PWà õI!„B!M°f@!„Bi‚5B!„BH¬B!„Bš`Í€B!„ÒkôüÈå ë×nm¥ú¶.JiDDìÖ­ßÖÕ5òù£KJÊŸöX”ÒË—¯Oœ¸ÚÚzœ®î;“æÍÛùW;ŽB¨PJåò¡ IÝ“å‹.¾’Rzôh’Áðšš: mT‰L•žþÂq1=¡—Ö è9¡”FEíºxQBh~6¥tݺCÕEGO64Ô0@tèÐŧ”)¥›6%„„,255¾paKYÙ÷'OƤ¥åtù$Býu„k×r[ZZƒ‚DÝòªwõ|ÑÅ_W „Lš\]}ŽÏ7ÒІ%2‡é³ôô´Çݸñ(¦'ô2šAû%&Š9œ!÷ïW¼Øßâ „üúëÍDZ0\º”¹sç‰Ý»?&„B…‰‰âÎÊ”ÒääÌ•+÷ÅÄÌŠ‹[âã#àó„'OÆtÇy „–xþÙR*‘H--M\\¬»þjmòE×»§£ÃÓÓÓÑ|D–È(¥”R–žžêÛ»t)ƒ¥§o¾YÌÒ“¿¿;¦'ôRÀšAË©eí‡TJiUU-—ûö¹sW§O_ojjf6fÛ¶ãªOoܸ=fÌrcãQ|þè©Sו•U³2;»ðÝw—ŽpqyïàÁ sæl{ï½µl¯ŒŒ¼#–24%K)¥V"“mÛv|„Õ"+-‘‘Û££§ØÚš³>¸ºÚffæw8(/Z´«W¯‘õõMmNsýúÃ~~}—-›¦¾ÝÎ΢›¾T„zéiÎŒ£ãä;N ¾X_XBBR‡ÃûŸæ‘ììÂ1c–tršrà@bZZN` 1--gøðŽz41ýþû±ªEA«WpršräÈÏ}ûN70>vìÊŠŠGóçï´°35 ]³ææ‹»ÑÉÜA)mm¥ææa;vœxRœ‡«¹Ü·e²¢­[¿8q °ôÔanU¢ÍvUzRíEÁô„^ X3h9õ±¬ýÐI‘Hd”ÒµkNžüö;Ç¢¢&.[¶W.o`ý[o-ð÷æç‹÷ܽû`ÆŒ “½õÖ¡ÐñÎcÇsèäÉË~~î”ÒÂÂ߇ Yäë+ÈÉùgAÁQ¡ÐqøðÅÍü ¶Brr;¶ºÃÈlVáÈ‘ŸJKËçÏÇzK17çËå µµ múO)ݼ9²¢âŒ®úiVWËSR2?ü0ôOA!„Ð+Ksv€ÒÒŠââ²Î/]:-/¿{‡Ã;hÈ#2YÑ›oÎwrꓟ$1qóW_LLûû )¥yÁÁQýú¹äå¹|yׯ¿fÏž½•‰´¦Fž”tíüùMgÏnüá‡_œëææ •Z¾|zLÌ¡Gê@=_PJ;ìF]]cgr!$/¯¸ªª60ÐãIq,,ø‰‰› !¹¹ÿ!ΉL °c1Ué‰RÚæ(íAQ¥§öíêù°fÐfééqœœûãÛ,-ù >TBRSeƒ¿ÎzJiffž»»£nqqÙ¥K©©²Ó§a %¥4/¯øÿþïú™3±,!ÄÔÔ˜Ã!llåñ¸W®Üصë»úú¦úúÆââ2//]HOÏ RJŸY©lill¾zõÖ_,Tïayy —Ë11éÕ™A–"—7@'Û#„Ð+¨“ÙA °{÷Ý öQ‡Ã;»þ¤Ï å4¬Xe<|X­ZÆ£P(¯]Ë ô33cP*[ìí-íí-õõuGúôÊ•›¦¦Æ zdY.oˆ¿à‰´¨èáž=ŸŒû¦§§svvannqHˆ/¥´ºZ^PPª92TVÖ€¥¥‰ú½®””¬ŸNÞ•!„xz:ÛÚš'$$©?Üvûöýví»D!í¡9;´¶Ò´´œ  ‘êrœ ïááƒD"'Õðòˆ¾¾.TUÕ>~TZ¾ÿùÀ@!ê³Ø^õõM^˜81ÒÒd"‘sïÞ†ðŸKö?ÞSÔØØœ•Uàï/„vùâÎû¬¬¥RÙºÑÉ‚¡¹Y™™™ïïï®:6q ¦¦Ž%2U9ÁÒS‡OƒtxUzRïUAA)¦'ôRÀšAûÔÚzÉÆÆ¼ýšN‰DFaK†(¥7nÜihh0@ÞÞ§U«ö—–Vdd䇆.×ÓÓ èíýš@`·bE\IIùõë·ÇŽý¬¤¤ÜÏÏìì,!'N$WUÕþüó5öÀ´§§3ܼy‡ÍÔ×7=)2°»5<W5§¥åH¥w#"F¶OiMMЦ&EûÁšÇãnÙùå—ß­[ïÞÃÊÊÚ'RBB¢‚ƒ½ŸÍŒB/% ÙA&+zô¨^ué¬Þ««åIIéêû†<âë+°²2Y³æ¥¥RiÑ”)Ÿ?|Xàýû» vŸ}¶¯¤¤>‚çž:uùI‘ÀÖÖ*+©îâlÞœ>È×WÐæ–˜RÙbk;aîÜÞCš:uèÙ³““3E¢;» [¶$¬\9ãÔ©õÏãkE¡—»»ojjìæfϲƒ@`÷¤á]CÑ××=uj}Qу×^›:kÖ¦Y³FSJÙ‹Vy<.{‘P8# à#SÓ^¿ýöµ™BÑ’™™ß¦H`KƒØcÙ|¾‘»»#üw¾ „°n°Ÿcc-Y7:“;Øùöîm(:>)üw"–žú÷wkóí)Jvˆö·´!ï½÷6¦'ô’"œSC=!@“ŸõA(¥ee52YÑÀ"¬]¿sç‰Nëèp»þPWKK«¹ù˜¸¸%l†ú—_n„…­HOsq±é†Þ£ž€„Ž9=OÏ%;<êùâùT* Í IDAT?R|ùòu–žœ»áÇéz4´Ñc8Ï€ž!¤¤¤,$$êØ±×ÖÖÿòË¿ÿýû ÆwKÁ\.gĈ@‰D Ísælß¿) !„ÚPå‹çÉ^_ßÄÒ“ö ©Áš=__·Í›ç|þùA ‹ðiÓbæÌ [½:¢»MJéÌ™ï^¸ €ÈÈí#Ç«["#„Ò&ª|ñœ—KPJYz7îM,Ð+×&i -}FÚ§¹zÎ0; ®ÀA=†ó !„B!M°f@!„Bi‚5B!„BH¬B!„Bš`Í€B!„ÒkôlQJ#"b·ný¶[ÞÐE)½|ùúĉ«­­Çéê¾ãà0iÞ¼åå5”ÒººF>tIIy·ÄìzWBuf „z>¬Ð3D)]·îУGuÑÑ“»þkJé¦M !!‹LM/\ØRVöýÉ“1ii9ƒ/”Ë õ :tñ©RΓbv±«!„: 3B/¬´_b¢˜Ãrÿ~Åóÿá›K—2wî<±{÷ÇÝ’’“3W®Ü3+.n‰€Ï7 ž<SPP…‰‰âÎKCÌ.ö!„z¾•Ôa¦@èe5ƒ–SÏO"ãã/öë÷¾žÞ0cãQƒ/LIÉ¢”Þ¼y‡ÃòÛoÙ¬MMM÷vBB¥tõêNNSŽù¹oßéÃÇŽ]YQñhþüa¦¦¡kÖüƒRJ)U(Z"#·GGO±µ5g=ÉÈÈ1b‰±ñ(CÃÁÁQb±´ÃDµhÑ®^½FÖ×7µéüúõ‡ýüú.[6M}»ÅñãŸ{€««mff~·ÄìÜ·‹B/«Îd‡ììÂñãW™š†êé ó÷Ÿ}ñb*Ûž––3|øâ^½Fš˜Œ~ÿýØšš:¶ý7æEG¥¯?, à#™¬ˆm_¹rßë¯ÏT·ºZާϸ͛a¦@è%‚5ƒ–SÏ‘7oÞ™9sÓÒ¥ÓÊʾÏÎŽ÷ðp [ÑÔ¤‹¥ºº<__7VH$ÒÖV艴¦Fž”tíüùMgÏnüá‡_œëææ •Z¾|zLÌ¡GêàÈ‘ŸJKËçÏÇ"ܽû`ÈE¾¾‚œœ ‡_ÜØØÜ¦W”ÒÍ›#+*Îèªw¾ºZž’’ùᇡ„´Moáჼ¼\ !ææ|¹¼¡¶¶¡ë1BH»ýiv¸qãöoÌsv¶¾yó`QÑñ€áĉ«š22ò‚ƒ£úõsÉË;rùò®_Íž={+¥´©I‘‘‘÷Ýw)±±³óòŽÀûïDzñ_$rÎÏ/iiieÇ]·.ÞĤWTÔÀLÐ˃÷¢;€ž!KËpP(”àåõìÊʾW5 ”*•-”Òo¾9#:úû»ïݽwo4¥45Uêë릧§Ãöºzõ–…ÿµ×l 55gà@Ï–€RÙsæ„/\8¬¬Ltuyz!,lŸoÄ"´¶Ò½{O™2„wÐ ¯}ûÎQÚv&„èê¶ýoI)•ÉŠZ[逢' Ù”Rv¦JeKwÅD!­Ô™ìýõ Aý¶m›Ë>ݳç“={>¡”.XðŰa~l»ù²e›3g[S“âúõÛMMŠ/¿Œzã OX°`ÂûïÇÖÕ5é÷ëçÒØØ\Xø»««LV´{÷éï¾[dže̽,°fÐfééqœœûãÛ,-ù@)U |„oï׎[³re\PPä!¾_|± _?BˆX, ña-)¥©©²À@!¥4/¯¤ªªvÞ¼qìD"ãr93gŽb-¯]Ëñöèèp›¯^½õÅ Ux<î•+7víú®¾¾©¾¾±¸¸ÌËËÅÐP¯3'B‘ËÀĤ—zÿÛ´)/¯ár9Ú>¡¡¡yðàÙÙ…‹¿wøðÊÔÔ½öö–ÆùwòÁ;J©¥¥ Q55)ššíï*ñxÜ-["¿üò»uëâïÝ{XYY{âDJHHTp°÷ªU”Ò´´©ônDÄÈn‰Ù_3oÞΡC?ÑÑáÍš5Z °333V(Z23óÛ AA,a‹oñùFîîŽ`kk••XKÀnÛ¶¹;wžprš²ÿ¹ØØÙPYYÛæF—RÙbk;aîÜÞš:uèÙ³““3E¢;» [¶$¬\9ãÔ©õ::\ؼ9!<|¯¯ [bvóB/==sç6–•U»¸¼7jÔ§ÁÁÞgÎÄr¹›˜¸™"ÎøÈÔ´×o¿}mcc–ššC)=s&vß¾³¯¿>³¸¸ìÒ¥}ú˜²hìn}S“"&f–êqgJ)f „^"¤“ËQOGÐä݉ÿhii57·dâÄàgýÐ¥ô—_n„…­HOsq±y¦ÇB]EBÇ„ž§ç’bbíß®°ðÛ?¥”FDÄÞºU(ÿËýÏÍJÌ/´Ñc8Ï€ž .—3bD D"}i ¡¡yΜíû÷/Å4€BÏ[óÃ^›ÑþÓý+eíڃǎýûë¯?Q/3B/¬Ð3A)9óÝ $Ïz"‹¹="bäøño=Ó!„ê{|ÙÏϽý¥?¥tÖ¬ÍqqçXÊžvkó)f „^¸6I[ô°µIu §¹zÎ0; ®ÀA=†ó !„B!M°f@!„Bi‚5B!„BH¬B!„Bš`Í€B!„Òkôt(¥……¿s8CòòŠÛ*—7¬_¸µ•vËû¸ÚGc? ´uë·ÝŸRzùòõ‰W[[ÓÕ}ÇÁaÒ¼y;ËËk(¥uu|þè’’òn‰Ùõ®"„Ð+¥»Fû²²êO>Ùíæö7}ýa|þè  ÈíÛO(Jöé“r¥ôèÑ$ƒá55u¡ç˜AVš=BˆD"366|í5»öƒlTÔ®‹%„@× §}4Jéºu‡=ª‹ŽžÜ-ñ7mJ Ydjj|á–²²ïOžŒIKËßèiJÁ ‚´Ö Ú/1QÌá ¹¿¢»îͧ¥É^ݵÃAö×_o ê–_ôlRzéRæÎ'vïþ¸[ †ääÌ•+÷ÅÄÌŠ‹[âã#àó„'OÆ”ÆÇ_€À@ab¢¸óÇÒ³‹½E¡g¡{³Cwé®ÑžRšš*ËÎ.ܱc¾Ÿ__ccCó3†ÇÆÎ>xðB]]#hÈY::<==¿vhBf¤}°fÐrê™àIƒW|üÅ~ýÞ×ÓflaÂjJ©£ãä;N ¾X_XBBRFFÞˆKŒGŽŽ‹¥ªfgŽ¿ÊÔ4TOo˜¿ÿì‹SÛGS(Z"#·GGO±µ5g{µØaÚ[´hW¯^#ëë›Ú|ë×öóë»lÙ4õívvÇì ®®¶™™ùÝóOÿL!ôœu&;¼ñƼè诃ƒ£ôõ‡|$“©öÕ0·ü;L1”Ò7n³ÜØxŸ?zêÔueeÕl{ûѾÃmÎE5,«Ÿ”•• lß~œU̬Yï*IõõMÎ'嬣G“ÌÍÃvì8QUUËå¾}îÜÕéÓ×›š†š™Ù¶í¸êèÙÙ…ï¾»ÔÐp„‹Ë{^˜3gÛ{ï­egi¬´œz&èpðºyóÎÌ™›–.VVö}vv¼‡‡SXØŠ¦&…X,ÕÕåùúº±áO"‘¶¶ÒÀ@ÖVšžž'ßZºtZ^ÞBÈl þ… [!99‡[}ÿ~eqqÙçY3÷!Cùú rrþYPpT(t>|qCC+NÞxcž³³õÍ›‹ŠŽ'N\Ý«—z48rä§ÒÒòùóDZþܽû }ÀÆÆæö‰dóæÈŠŠ3ºê_Euµ<%%óÃCÛÏ–„‡òòr%„˜›óåò†ÚÚ†®ÇD¡žæO³CS“"##ï»ïRbcgçå€÷ßýÓ¸´´B}ð ;L1ÙÙ…o½µÀß_˜ŸT,Þs÷îƒ36B!mFûììÂ#´¹àfò¡¡žú)¸¹ÙoØðÿöî=ãìuêºÂÂ߀Ã!rVFFžŽ¯7‰DJùúëÇŒÈç v”R‡‘‘Û ê·mÛÜ>}L„Ë—ÿ­¼¼& @øx¶3Ò6¼Ýô ¥§Ç@rrfDDì?n³´ä¥T5$B¼½_;vlÍÊ•qAA‘C†ø~ñÅ‚~ý\!b±4$ÄGõ,Ajª,0P‰ÌÌÌxìØ7Ù½vSG©l€ôô\6\@jªL °5*Eàñ¸W®Üصë»úú¦úúÆââ2//ݪ’’Ò[­Þ+vDõhÍW¯Þúâ‹…ªþt°Í¦'!„Èå `bÒ«ÍqÕÛ”—×p¹ mž6&BõɉÔÚÚ,4t ‡  ¥¥ž0¤³˜ þï¾ÄâøøÚ¤OOçââ²K—2RSe§Oÿš)Jv«Íhÿ¤O5ÆöïïvèЊ­[ç~ùåwÛ¶}›•UpëV½qãvXØŠÖVZW×xóæÀ@v¿¤©Iqùòõ€HK“y{ ¸\»”••oiibbÒ‹ríZ®¿ÿÓ²‰ôwüرêë›^]¸xñ{‡¯LMÝkoo9l˜?H¥w)¥>>Õ°›]XYY êÑrrî57+}|¬? Íìäc|”RKKxð ªM¡{$4t»­•••/9wršXsÌÎô !„ž›?ÍìV‘HäÄÆ@6Ú÷écÚ»·¡†˜-d}ç?õÑxòäõC)äæ@RÒöôô8öïÆçóÔG{ þt´gÙä³Ïö©#õécºaÃÿÛ°áÜœ{ÕÕrøï,£ž³ØY‰@"‘úŸíb±4(Ènß.//WUüŒŒ\wwGccCøc–3Ò6X3h9 +V)¥—/_0 ttx3gŽÚºunaáï55ò[· [ZZû÷ïËÓÝ»O×ÔÔ©æjjä,¬B¡;öMOOçììÂÜÜâ_ÐÓÓ€æf%k™—Wâã3ëܹßjjêTÑ(¥¬Š°´4Q î,`xø ‘ÈI°“÷f!žžÎ¶¶æ Iªï„Rzûöýúúºñx\BHJJ–j¦¥‹1;!„ž'ÍÏ3°‘¶±±™5kjR>üÓäÉCàI#0´¶R6ø³½ÔSÌŒT¥33cP*[ìí-íí-õõuGúôÊ•› >ÚkˆÐ™;÷<÷СÙ= Õiéêê«g™69«¹Y™™™ïïï^XøûÇÕü±]©l¹v-70ÐLM ¬¬šõ¤¶¶>>þb@€»ª„À ‚´Ö ÚoÔ¨ ÖÖK66æígüüÜ‹Š~õÕ©ŠŠG÷î=3oÞΡC?ÑÑáÍš5Z °333ÎÈÈçr9çÎmܷ﬷÷Ì߯LNþÂÚÚŒ"Øùøœ{êÔe±XjjjìæfφE77ûmÛæîÜyÂÉiÊþýçbcgÃã›Iºº¼sç6–•U»¸¼7jÔ§ÁÁÞgÎÄr8ÿ lm- ²ò¸»¶¹m¦T¶ØÚN˜;wG‡wz¦NzöìÆääL‘(ÂÎn–- +WÎ8uj½Ž6oNäë+è–˜Ýù7C¡gŒRšššC)=s&vß¾³¯¿>³¸¸ìÒ¥}ú˜j@5ø³±ÚÀ@·ÃCœ9k` çî>}øðh__ARÒvö8D›Ñ¾Ãm.¸ %–Û_ Ÿ>½A(tœ1cƒ•ÕX`ÚþýçöìùdéÒ©r[€Ô»·¡P蘚*uww`?ëF)‹oé³Gþx<îéÓêë‚i3fl`…„êhÌ H+‘N.G=!@“_t'ž•––Vsó1qqK&N ~Ö‡QJùåFXØŠôô8›gz¬W szžþRvˆ‰9´ÿ¹ÂÂoŸA‡4yž£}W<|X-“ (âñ¸°nÝ¡;O>‚Í›ç|þùA ‹ðiÓbæÌ [½:0ƒ -†k“´…V¯MBÚ§¹zÎ0; ®ÀA=†¿é†Bi5ò¢{€zéaÍ€Bi/¼IüR ÿR¨‡ÃçB!„^V0ôàǾ¬B!„BšaÍ€B!ô‚¨V%áTêÙ°f@]õÏþ¤£3T.oËÖ¯?ÜÚJ)¥G& ¯©©{Ò^”RÕŽšãSJ#"b·ný¶[ÞñE)½|ùúĉ«­­Çéê¾ãà0iÞ¼åå5”ÒººF>tIIy·ÄìzWBi¹61`Ù€z0¬P—PJSSežžÎFFúQQ».^”p8„2iRpuõ9>ßèI;BØŽ½zhŽ¿nÝ¡Gꢣ'wýMá”ÒM›BB™š_¸°¥¬ìû“'cÒÒr^(—7ê  :tèâS'OŠÙÅ®"„BõX3h¿ÄD1‡3äþýŠgñ[„±øV` üúëÍDì(::<== ;RJÙŽzE)½t)sçλwÜ-CrræÊ•ûbbfÅÅ-ññðùF“'c Jãã/@` 01QÜùciˆÙÅÞ"„Òr¾+ §PO…5ƒ–S¿"Ò¥ðêÕœœ¦9òsß¾Ó †»²¢âÑüù;-,ÂLMC׬ù¥ôæÍ;Îß~˦”RJkjêx¼·’ššYYÎÎ6\îÛ2YÑÖ­ßNœ¸¦µ•š›‡íØq‚RúÆ󢣿ŽÒ×ð‘LVÄ"47+³² „Ÿ}¶ÿõ×gªz[]-ïÓgÜæÍÇ(¥ EKdäöèè)¶¶æìÓŒŒ¼#–24%K;,9-ÚÕ«×Èúú¦6§¿~ýa?¿¾Ë–MSßnggqüøçÁÁÞàêj›™™ß-1;÷÷A!„z `Í åÔë„/…)¥‰´¦Fž”tíüùMgÏnüá‡_œëææ •Z¾|zLÌ¡GêÅb©®.Ï××B‘H¤­­40Ð#33¿©Iñî»A‰‰› !¹¹ÿ2d‘¯¯ 'çŸG…BÇáÃ766·9/JéæÍ‘g tÕO¿ºZž’’ùᇡ„´-ŸÂÃyy¹BÌÍùryCmmC×c"„BO¤ápªõHø›nÚÌÒ2 %xy}À.jËʾWoCIMÍ8ÐóÀ¥ T¶Àœ9á Ž++]]ž^jªÔ××M__(¥W¯Þ²°à»ºÚœ?ÕÈH¿_?—Ÿ~J³¶6ì@"‘êèðú÷wËÊ*hjR|ùeÔÀ"X°`ÂûïÇÊå FFú‰ÔÈHßÓÓ› wuµ‘ÉŠvï>ýÝwëtuy!,lŸoÄzÞÚJ÷î]PJÕ/pss‹«ªjçÍÇî¬K$2.—3sæ(ÖæÚµooŽW,–†„ø°}ÙãËBHM•ùùõår9éé¹B¶WjªÌËËE__W"‘Z[›…†dÛ €M)¨v y¦½{ªï¨«ËëÛ×>'§èܹ«?ÿ|mÛ¶¹¬'99÷š›•>>³¡¡yðàÙÙ…‹¿wøðÊÔÔ½öö–ÆùwòÁnJ©¥¥ H$rÊÎ.ÌÍ- ñíäÝ}Bˆ§§³­­yBB’ê{ ”Þ¾}ãÆ£¾¾n<—’’’âÓ-1;!„Ð+‡ÒþiØŽPÏ€5ƒö5*¨µõ’yûKaJ©D"c/HU l>’‘‘¯P(…ÍÍJøí·ì‚‚Ò þyð`"z¤¦Ê(¥AA¢›7ï°›îõõM™™ùÍÍÊ  Quµ<7·8?¿$>þb~~ÉìÙ[›W¬˜ªÙqE"—ƒ/TWË?ûìØÅ7!„ÍNðx\ÖÆÎ΂râDruµ<))}ÆŒ àééÜþaå¦&ES“¢}Äãq·l‰üòËïÖ­‹¿wïaeeí‰)!!QÁÁÞ«VEPJÓÒr¤Ò»#»%f—ÿn!„B=Ö ¯.ö2ÓÌÌü6EBP»L‹oñùFîîŽz~ôјyóvú‰Žo֬љ™±X,µ¶6sp°ì||Î=uê²X,íÝÛP(tLMÍ¡”ž9»oßÙ×_ŸY\\véÒN++PíÈŽëééÜÔ¤ˆ‰™¥zÜ™Rjkk••XÀnÛ¶¹;wžprš²ÿ¹ØØÙPYYÛf"E©l±µ0wîŽç ¦NzöìÆääL‘(ÂÎn–- +WÎ8uj½Ž6oNäë+è–˜Ýü×B!„zqȳø/ô4ùEwâ?(¥ë×Þ¿ÿÜ;Ç4/õ¡”FDÄÞºU(ÿËýOÛÒÒjn>&.nÉĉÁÏúñbJé/¿Ü [‘žçâbóLõª#!8ÛŽBmá[’P‡ïMBÏ!$--GõØô“üë_)7oÞ>vìß¿üò•zÁ\.gĈ@‰D:iRÈ3í*{ÀzΜíû÷/Å‚!„B¨=\›„ž öö$??w Y”ÒY³6ÇÅ;p`){sk›OgÎ|÷Âɳž #„DFnˆ9~ü[Ïô@!„B/)\›¤-zØÚ$„:†k“B¨=\›„z<œg@!„Bi‚5B!„BH¬B!„Bš`Í€B!ôBáà ¨ÇÚ!„B!¤ Ö ¯:JéÑ£IÃkjê^t_Úb?÷¶uë·uu|þè’’ò¿áòåë'®¶¶§«ûŽƒÃ¤yóv>‹®"„Bi1¬^u„I“‚««ÏñùF/º/ÿ…RºnÝ¡Gꢣ'ê  :tèâS½˜RºiSBHÈ"SSã ¶”•}òdLZZγë3B!„VšAû%&Š9œ!÷ïW<é‚[G‡§§§óœ{¥¥ôÒ¥Ì;OìÞý1!„(LLkþUé6’“3W®Ü3+.n‰€Ï7 ž<óL{ŽB!¤}°fÐrêuBû nJik+57Û±ãDUU-—ûö¹sW§O_ojjf6fÛ¶ã”RJéøñ«¦N]§ UUUke5öÿ÷¥ôÆÛcÆ,76Åçž:u]YY5kãè8yÇŽÇ/Ö×–±_¿÷õô†þ8ÖgBˆ¹9_.o¨­mhs”ÒÍ›#+*Î誟luµ<%%óÃC é XB!„zÌS¨Çã½è gÈÒ2 %xy}À.ËʾW5 ”J$R^ÿþn[·~Kùúëýüú€@`G)åp8 :mÛv¼¥¥•Ã!ùù%_}uêØ±5zz:QQ»&M Y½ú!}ú˜FGO™<ùóººF±ølÚ4gèÐþPQñˆRúÍ7g„BÇ€áÞ½Ñ{÷FÛ}Íš°²2a»Ëå FFúññÂÂñùFªB……RÙÒ¦ „èê¶ýoL)•ÉŠZ[é€",B!„ºkm–žÉÉ™±?þ¸ÍÒ’”RÕe4!$5Uæå墯¯›š*<øu?¿¾ìÓÌÌtIIù_xWXû˜ÝÕ[„B¡žkô_(¥×®å¶´´‰`Ò¤àêês½{BÚ7&„°|¾Q›íª z¾vmü£Gu‹Oé–þoÜx4$d‘©©ñ… [Êʾ?y2&--gðà…ryƒ¡¡Þ€¢C‡.vx.O³[z‹B!ôRÀšAû%&Š9œ!÷ïWtæþ:!D"‘ZZš¸ºÚBttxzz:.²Yƒ6)¥,ˆ‹‹µæ ôÿ;cçλwÜ-¿réRÆÊ•ûbbf}óÍbŸoäïï~òdLAAi|üE &&ŠŸêXOŠÙõÞ"„BÀg@=Ö ZNýúøI—ïÙÙ…cÆ,72éä4eÿþóii9BJik+57Û±ãÄøñ«¦N]§ UUUke5öÿ÷ˆª¥T=ȉ,;â·ÇŒYnl<ŠÏ=u꺲²j§¹Y¹=:zŠ™ªehè2#£‘ŽŽ“HŒŽþzÆŒ m.ñ)¥‹íêÕkd}}S›íë×öóë»lÙ4Õ™BlmÍÿ<8Ø\]m33óÛOÓÎ΢ó„B¡—Ö ZNýú¸ÃûëRéÝ7ßœïäÔ'?ÿHbâæ¯¾:™˜(ö÷@^^qUUm` ‡§§³LVÄBQJ7l8Ü»·á'ŸLR5ÉŠ: B)½yóÎ[o-ð÷æç‹÷ܽû€•”Ò#G~*--Ÿ?‹|ýúíAƒæ;;[çå9~ÓŽÇÿõ¯”€6—ø„Í›#+*Î꩟ZMM]JJ懆r8mÛ‡‡òòrss¾\ÞðèQ}ûoé©b"„B½R°fÐf––á––áS§®/¯¬¬ÆZZ†«7 ”.\ø¥Ÿ_ß]»¢llÌE"§%K¦Êå AA ‘Hutxýû» …N99÷ZZZ)¥ùù%_}ujëÖ¹zz:ª,ÈW_-²±1÷ðpTµkÒ¤Õ«ÿ§OS¡Ð1:zÊO?]««k€øø aaƒLLz=îÉAA»vEÙÚš÷ëçòé§SïÝ{äѾÔÑÕm» Š"“µ¶Òžø!D¡P€RÙÒ]1B!„^¼Ýô ¥§Ç@rrfDDì?n³´ä¥T5cPZZ‘””~êÔzÕvÝè©©2//}}]OOçÆÆæÂÂß]]m–-û&8ØgìØ7U *+kY™¢ R\\véRFjªìôé_X— %¥T©lill¾zõÖ_,d—ãÅÅeÿ÷׿ûnª'úúºzz:>>‚Î<²ÌÞÔ&&½žÔžRZ^^Ãår4´yÚ˜!„B¯¬´™ƒƒ¥Ô‚66f66æêŸBrrî€@u¹Ÿ‘‘ëæfoff ‰”½=ÉÝÝËåÈdE÷î=½rå&;XZš°½ ôÔ{RUUû$v¸0©C”ROOg[[ó„„$õS.((ݸñ¨¯¯—Ë€””¬Ÿn‰Ù™!„P§àl6êñ°fÐ~£Fµ¶^²±1oÿ0±¯¯ÀÊÊdÍš”””ߺuwÊ”Ï>¬ð€ÌÌüæfePˆÝõ‰œöí;wçÎýÕ«#ØUUÒÒ ©´H=ˆ··ÀÃÃiÕªý%%åééy¡¡ËõôtCC»ÙÏãqY´þýÝllÌW­Ú_ZZ‘•Uº¼¼¼¦ýÐÐÔ¤hjR´ÙHár9[¶D~ùåwk×¼wïaeeíñãÉ!!QÁÁÞ«VEÀµk¹Ré݈ˆ‘ݳ‹„B¡—Ö ¯4½S§Ö=xíµ©³fmš5k4¥”MˆÅÒÞ½ …BG6àéé|ãÆí˜˜Y¦¦Æ@)U5Ð××í0!„Ã!gÎÄè¹»O><Ú×W”´ÝÈHŸbkk••Ø]}}Ýï¿ßðûï•®®ïÍ»cÈh?Ï P(mm'Ì»£ý\!ä½÷Þ>{vcrr¦Hag7aË–„•+gœ:µ^W—GÙ¼9!<|Pÿþnmvük1»óÏ€B!Ô³|!Œ– hò‹îDg=þñ‡1qqK&M iÿéÚµ¿þúûNu×ÃÇ—/_ [‘žçìü'?3‡ž-‚?]„Bm‚c#êápž½l bĈ@‰DÚáÝ}±XªúI¸®«¯oš3gûþýK±`@!„ú °f@/!dæÌw/\´¿ˆom¥‰, @Ø-“`”ÒÈÈí#Ç{ „B¡¿×&i‹—jmzuáÚ$„j×&¡çB!„Bš`Í€B!„Òk„B!„&X3 „B!„4Áš!„B!¤ Ö èù9z4ÉÀ`xMM]'ßÖE)•Ëtt†&$$=í±(¥±[·~Û]/l½|ùúĉ«­­Çéê¾ãà0iÞ¼åå5”ÒººF>tIIy·ÄìzWB!„ºÖ è9¡”Nš\]}®woÃNþN!äڵܖ–Ö  ÑS]úSJ×­;ôèQ]tôä®ÿ&¥tÓ¦„E¦¦Æ.l)+ûþäɘ´´œÁƒÊå ††zˆºø´=ì0f»ŠB!ô,`Í ýÅÎû÷+^ìoqBttxzz:¿ˆ§”J$RKK—§øýfJé¥K™;wžØ½ûãn)’“3W®Ü3+.n‰€Ï7 ž<SPP…‰‰â§êá“bv±·!„BÏÖ ZN½NxÒE­£ãä;N ¾X_XBBÒ·ÇŒYnl<ŠÏ=u꺲²jJ)¥tõêNNSŽù¹oßéÃÇŽ]YQñhþüa¦¦¡kÖüƒEËÈÈ1b‰±ñ(CÃÁÁQb±”mom¥ææa;vœ¨ªªårß>wîêôéëMMCÍÌÆlÛv\ÕÛììÂ1c–tršrà@bZZN` õ¼}Ç:ì¿Bѹ=:zŠ­­9‹yãÆíÐÐeFF#'8ýõŒÚ‹íêÕkd}}S›/mýúÃ~~}—-›¦¾ÝÎÎâøñσƒ½ÀÕÕ633¿Ã’ìic>ñ‰B!ôâ`Í åÔë„/jKK+Š‹Ë8¿té´¼¼#B¡ã[o-ð÷æç‹÷ܽû`ÆŒ „BˆD"­©‘'%];~ÓÙ³øá×纹9H¥‡–/Ÿs¨¦¦®°ð÷!Cùú rrþYPpT(t>|qCC¥4/¯¸ªª60ÐC"‘QJ×®=8yòÛwš¸lÙ^¹¼R*“½ùæ|'§>ùùG7õÕÉÄD±¿¿Rzóæö£”¶éÿ„ ÁGŽüTZZ>þ8VêܸqgРùÎÎÖyyGΟߴcÇñý+% À£Í·A)ݼ9²¢âŒ®ú—V]-OIÉüðÃPBÚ]áჼ¼\ !ææ|¹¼¡¶¶¡ë1B!„z Þ‹îz†,-Ã@¡P€—×ìò´¬ì{UJéÿgïÎãjÊÿ?€>·å–¤=¥¤(”¥²•-YŠìŒB’ì†Â-»Š² ÙFC²¯ƒLB„2fdß½’µî½ŸßŸ™ó»î½Ý®õåõ|øãvîç|Îç¼ÏG}Þç|Î9ééBæÍ nݺ!dР¨ž=½§OH±´4?¾w¯^¯^½50Ð;{öJãÆµÖ¬™H‘H¤„àà.£GÇKêêjë닟??¡W/o¾­¦Më¬^½—¤Ïœ¹¬££]¯žÓ‚‰”ÒåËÇ6hPƒâèhÉD„Q£–Õ¯_=&f !ÄÊÊô‡ú0ÛÃÙ2zttÏžÞÓ¦PJ+V4á {ýúBûc :wnjddÀÛ0jÔRg^§µµéĉ}œëáá¬0X§”êê*þwàiŒLÆ<=]ŠÜ3Æx„%é窠LAÎð5;~!$%%sàÀ¹‡-´°0"„0Æ„¡*¥ôìÙlGG›öí=!÷î=9vìÂÙ³Ù;vœà %Œ1‰DzíÚƒœœü#ºñuÏœÉÖÒúñ3ëçÎ]quuÔÑÑÒÖÖJKû#::éÍ›÷oÞ¼»ÿi:úúº„³g³ëÔqÐÓÓ={6ÛË«.Oc™™×jÔ°Ó××}øðù‘#ç““góRJÅbBH£FÎ÷ï?-ªaòígŒ½{Wpúô_K—Žâí¼wïÉï¿_LJš)Ô©§§+븹9ÊÇ¡(”ÒW¯ÞBŒËUžRúìYž––HM™­¾-¥zÃ!€&3|Í*W¶dŒ™›B¬­M­­Í ð›ŒÛ´©Ï‡þW¯Þ'„9²ÈÊÊT(C)522سç”HD½¼\yɳg/»ºVÎå§§_öðp~û¶ÀËkdµj6&ôqr²µ³³lØp˜OƒÓŒË.üChhwaÏ×%„\¹râææÈË3Æ.\¸êädkbRþÂ…kE5Lh?¯íÊ•{ž{äîî$Ô™‘qÅÍÍQWW[“Á:c̘òøqNåÊ–òË£¢6§¥ý±cÇ--QVÖu{ '©¯3<¼±5|a¸Ÿá+§æ~ƘLÆ22®xx¸ð·©©!!D"‘ÚÚZØÚZèééúùMLK»DÉÈÈvq±74Ô—èÿ3µæíÛ÷YY74¨yæÌå»wŸ¬X1®k×fµjÙÿùçí«Wï{{»3ÆÞ¿/Ì̼ޠAÛ·=y’+LË),”œ;wµQ#gBˆžž.!$''Ÿß‡“ójÍš}Õ$„ «\Ù²reK¡aòíç{ôâE>!Ę·S__,_gnk÷+OLR½Zµì+U2ûå—#Bôc7oþµÙÝÝI[[‹Rzüx–··Ûg©S“¾0ä _???™ì˜µµ™òlûìì»/_¾ñôtáCjWWGgç*?þ¸æáÃç.\ïØ1\,ÖíØ±1!äÌ™la Ï“„FœùZ.\/,”4jTÓÆÆœRºukJNNþo¿ãÏ&ªUËž’™y½ @âááræL6¥´aÚ Êoß¾÷ôt!„¸»;ZZOŸ¾öáÃç—/ßíÝ;âɓ܆ !BîV­oPм  Œ1þ U‘ˆªl˜|ûùUªdNyñâ¥pGÄÎs=zQµjŸÅ-[ºB®3ðû"*Uú.$d±Êk}û¶Þ³'*%%ÓÅe Íwóçÿ2eŠròl-BÈO?ýÒ¥KSwwÇÏRçg=Ÿ-Ý÷|ÁgC)a)¥ÝˆÒ'•ÊÌÌ:­ZõC-”ëk—/ßùäɎϲ-ÆØ‰tî<ùüùUÖŸ¥Î¯õÆ­~ÿsp¾*ZZ¢¶m9sY9aà×U5ªùYòdÆØÛ·ÁÁ‹Ö¬™„„> ž¡erøª0ÆÛ8pFùîÆÈ™3Ù Öü,7¥”¾hàÀvÝ»7ÿôÚÊ2ÌMúZ`nüOÀÜ$e”âw#”qȾ¸¬ ÿ+ð;@r(óðN·¯~×|Åð·Jîg(Ûx€ëHPz3€:ÈÊ0aV.5@éAÎPV)ÜÆ€´J rP9@™¤òYI¸Ô¥9¨ƒœ ìQóB\j€/9@SìÜ6À—…œÔÑ.í€~A“ËÅ^ŽøL3”%H ìÁÜ$P9@™‡;ž¾n¸È erP9¨ƒœÔAÎê gu3”*<Ê<ä  rõ IDATP9¨ƒœÔAÎê gu3€:È@ä  rP9¨ƒœ Ìc¬´[ß4ä  rP9¨ƒœÔAÎê g(ó(-íÀ Ïǃ29¨ƒœÔAÎê gu3€:ÈJžerP9¨ƒœÔAÎê gu3€:È@ä  rP9¨ƒœÔAÎPæ1VÚ-€orP9¨ƒœÔAÎê gu3”y”–v à¿„çãA™‡œÔAÎê gu3€:È@ä ¥ Ïǃ29¨ƒœÔAÎê gu3€:È@ä  rP9¨ƒœÔAÎêh—v 8Œ•v €JÿùÀRþ]â%XòÏü'€¯eøMP,JÿŒ 9|:JÑ‹ ŒÃÜ$P9À'Àéaø gÐ&&À7 9¨ƒœàÏÔ(1Ìpƒ29€„'l|{3€:ÈJèÝ»‚ ëÕû^_ß×ÐЯyó‘Û·§~–—ÞH¥²Õ«÷>{–÷YjcŒíÞ}R$jyïÞÍËSê-ü‰ZŠÅ>öö½Ç‹}õê­Pá­[— …Œ±­[Säë¶Ò¸qˆ|忯ݕñckùoZP†à=ÐPznR^Þk_ß oß¾ˆ\¯žÓ›7ï7l8سçôyó†ß‹~ÂwÆØþýéC‡.hÛ¶á§Ô#¯„1Vl¼¥ôôé•+[ð…ïÞœ>ýט11çlÜ8ÅǧÁƒÛ,,ŒKÐB¡þãÇ—::ÚÈ¥««#ÿ£&­-1ÆØË—oŠ:ˆ&ôþ¶ ð¿9ÀGcŒMš÷âÅËŒŒ•FF|áܹC $S§®îÝ»¥­­E‰»”Ráäýg4Ë_ Ф6¡¼……‘µµ™°ÜÞÞ*7÷ÕÈ‘KW¬W¡B9ù¯JÖss#åJ>¶µµ]‰Dº}{jLÌöÔÔhJ©p+T(Ç·ù½üAôòÚ½{÷æ::øs ß4ÌMøh¯^½MH8Ú]H!Œ±°°~G.©XÑTáÔ¾D"9s½ƒC±ØÇÉ©ÿÂ…¿ÊdŒ1¶k×I‘¨åªU{xɈˆµåË·»téV—.Scvv½´´Z©YÏáÙ¸ñ°›[žž«kбccŒ±ÂBÉäÉ«¬­»ëëûúúNÈξ+4fãÆÃµkÒÕmceÕ-(è§ÜÜW {§Ðxùå"‘H&c2™L˜>¤¦ R©,"b­­m==ŸfÍBçÎݤDOϧZµ~Û·§îÝ{ºnÝ@±ØÇÙ9àС ùjŸ>ÍŒÜT­Z¿ÐÐ%MšÔfŒåç¿áQHøÖ…ƒHiÒ¤vhè’jÕúEFn*rªž›Ÿ½Ê<ä øð¹I/Þ|ÿ¾°qãZ Cj ã&Mjéê~pNšR:ztôæÍ‡ãâÆ_»¶)2òû¨¨M3g®#„têÔ88¸ó?¬¸{÷ÉñãY³goXºtT­Zö á”ÒsçV=x°RÔêܲeIqqã32Vè 0G&c|•ŸÞ?áòåõ:4ž:u /|íÚƒAƒæöìé}íÚ¦mÛfþöÛ¹ðð• Caå3ý|ì~ìØ…Y³||ÈgJjÚ»#:ztvö†ž=[FD¬#J”¯$(4Fý¾ÏŸÿË’%#³²~¶³³<8*"bm|üø¬¬5¶¶s¤Rc,3óú!?U©Ò{ÇŽÔˆˆÁwïþ5Tþ *´A8ˆ”Òyó†Ý½ûkDÄàääßíìz}ÿýüÌÌëÊ{ðÕÃÅV€–—÷šbbR^“É3ç¬\¹ûðá…-Z¸RJíì,>|þãk&Oö×ÑÑZ° $%%sÈŸ®^½×·oëÀ@?Bˆ±qyBˆ……‘••é“'¹|uoo7BHåÊÂê¼þY³‚<<œ !!!]"Ÿ=ËÓÖÖZ½zo|üøNSJÇŒéqýúýåËwB?~!“±J•Ìmm-ìì,w튤”*ì…ðc:ƒ…ÏïÞtêÔä§Ÿ‚•÷Q¹ b±Ntôö˜˜1]»6£”ŽýÝõë÷ccwȯհá0…M¯ZõCïÞ-…‹Ý÷ÈÈ¡^^u !Æuî×oÖ‚!×"„ Ò±oß™OžäXY™Ö«÷½½½Õ¡C š6­-¿9á ªŸ¦¯/ ô ôKM½8pàÜŸÞ/“+ª0À× 9ÀG377"„<þÒѱ˜û cYY7¤RYÇŽaBI©Töî]ÁýûO«Vµ.WN¼qãÔF†Uªd¾|ùXåÚÔ¬Îtt´á_ñÓÿ……’¿þº-‘H==]„«M›Öá9C“&µ{ôh1lØÂ)SV·iS¿sç¦ß}ç¥0hÎôïÙecc.‘H9¾Ò×·alìØråÄÊ»©Ü†ìì»a˜ÎkÞÜU!gHJšUµªµü++ÓÚw—*ü+=Bˆƒƒ5o€„1öìYÞêÕ{ãâvN› \BÍê_ä øð¹Iuê8”+'>uêOOO—ÿ/ÂØß¿èßÖŒüä7!„R*“É!‰‰Õ«06µµµàÜs箈D¢¿ÿ~ž™y½Y³: [V³úŸÞ"„ˆDT~>0öÏgJ©p ¯HD§_¾|wß¾ÓGŽœ ˆüùç}‡-¯Y W©RÑÞÞŠRêì\¥zõÊ;†½_¸mÛ åð(·×åÛ |3€¥l¨Tì¾ki‰>œI¥b²ÓôéƒÂÂúoÙr4:zû¬Yëûöm=bD7wwGá zx8˯õðás~›7¯sþüµØØä-[Ž:;W™1cpß¾­ÅbðíÁý MOO×ßßwùò/_¾RJ-JLK»dcc.ÿà£Zµì)¥wï>vr²ur²ut´9uê¯éÓ×òW¯Þ7.6"bp¯^-"ù„ù!¬°º££ ¯A~uaÓò«Ô­[MWWûøñLázú_ü«ÔÔ?†_äèh3~|¯}ûæ-[6ê·ßÎ=þR¾6•O.òõm0sf`rrêêÕ{UÆD¡ ®®Õtt´OúS¹ k),‘ßz öß~­ð­žžî Aí22â÷ïÿ)/G0¥T__Ìb~þ[ùã%DBˆ§çð—/_80ÿܹ•ƒµCÂß,\gøh”ÒÙ³‡¤¤dzyœ6mPƒ5^¼xùóÏûbb’çÍVµªµüsxlm-üý}¦LYml\¾I“Úéé—GZÚ³§·ŽŽVa¡tÀ€Ùµk;LœØ'7÷U:ƒCC—lØ0E__L9}ú/OO5« íQ8…obR~̘S¦¬65­àéé²:Ÿ˜D)_^õê½27®Wa¡dçÎ5kÚ™˜ÊOORù>ÆØ?ôÙ·ïô¤Iñ:4VމBÌÌ* ÞyÊ”UææFnnŽû÷§/_¾C¡ògÏòþþû¹B=üE\ ö]! Qد-\[´p½}û_KÍA¬V­!äÚµMUªT,æ®J1= ¾zÈ4@½¦'™™UHK‹;wcXXü;uuµëÕ«ž”4“ßòûÁª”ÆÇO°³Û0yòªžYZwž1#2mÚš?ÿ¼}þü*--‘™Y…¸¸ñݺMmÛ¶Q·nÍÛ·÷8p.!äÚµME­.¿ …öFF52*ÿÃ+ž<ÉiÔÈ9"bФIñ„wwǧFFntu *WNܪU½={¢¦ô¨¼Î@)‰Èš5Ý݇Œ±80°½b„”Ú0þpCÃr#F,~ö,¯~ý“&õ›5k½pªž1æå5J9Ò/_î“ÿñc÷]} ÁÙÛ[ñ¦¦†*b·nÍJ|ãTL0E”*¿ Ô`ŒýöÛ¹Úµ¬¬þy[ElìŽI“âòòö‰DŠOjúßF½q>®VA™‡ûàó£”nÛv¼_¿YWnß~”œœ:gΆ€€¶_[Â@ðÜ$ø&à:€&Ž—vþÇ0Æòò^Oœ·kWÚ‹ù¶¶þþ¾“'øo#nQÚ €ÿ}¸ÎerM g€¢ g€O†œÊ<ÌMø_ÙT+U´ñË@#¸¾UÚ„à!@q¨wi· Ô`nÀ'À4tø gЮÇÀ7 ï†RsàÀ™%K¶ž9“ŸÿÆÄÄÐÃÃy„>^^u?åÙíTn‰®®Ž‰Iy??%KFh¸î™3q Ô(ÝçÇkÒƘ–V+BHzúІ k~Éæ}Ó„&¤ßæþ3¡s 'Ú¿å%_5ä P:fÌH˜1c!ÄÍͱbE“‹oîÝ{úÀ3[¶LïÞ½yɆìŒ1¾b‹®FFyy¯Ožü3!á`NN~ròlõu ëBJ7a`ŒuíÚŒbbb¨¦%”âAÉ¥AùjÃ7½D©~ËK>z”yÈ 9r~ÆŒub±NròìvíBÞ¿/4hnbâ±qãb»ukN+ÁÀ]FÿôSpƒ5!»wŸêÒeòÎiçT¬h¢á\>øò(¥Éɳ‹-Vº€o îg€R°lY!dÔ¨ïxÂ@‹u–-µoß¼3gâøH85õbË–c Úuhß~Ò¹sW…1=¥Þ”zoÞ|¤yó‘úú¾..wï>ÉãÃh>’æ|}ðçðåYY7:v «P¡}¹rm›5 Ý·/×)¿n×®SE¢–cÇÆð: %––]E¢–¿ývŽ1VÔÖy=jê‰ZŠD-7múÍËk”¾¾oݺ.\‹ŠÚ\©Òwíºt™òôi.ß"/yöl6cL*•͘‘P­Z?Öí5 >pà ù7ÉÁ¥ø3@)8yò!¤U«zòC^ ãvíU¬hBIMý£M›ñ¿ÿ~ÑÝÝÑÍÍñС³-ZŒºté–|b²H$™›egßíßö›7ï !Â0š8t(ƒ"QsÆXfæõ&MFìÛ—^µªuÆ5Ožü³S§ðÍ›‡àAA!‰‰Çd2F9räü³gyUªTlÕªù7QÞº†õ/ÔÖÖ222¸téV«VcgÍZ_«–½L&Û½ûdDÄ:^¹|2°lYÒŒëž=ËkÛ¶¡eFÆ•îÝÌË{-Ÿäü§3@)ÈÍ}E122àCÞáÉD-ùù{‘¨eFÆ•ˆˆµ……’Õ«HMNIY²fͤ7oÞGFn”RÓ#%eÉáà !¯^½½yó!ùw@?qb\÷î?¶l9¦gÏé„ï¾kafV2iRüÛ·ïl›™¹æøñ¥K–ŒdŒ+‘Hå‡àíÛ{ØØ˜?zôâèÑó„­[S!¶‰ŠÙº&õOœØ÷È‘Eññc¹¹¯§:´`âľ„ÌÌë WK! ÔˆŠvøðÂÝ»çþþû2ÆØÛ·ïoß~Dä$€ÿr(ææF„'Oþ™ŠS·nµ.]šòù øÌ™ËŒ±ÀÀy|–ΠAsc¿ÿ~Q~HݪU}Bˆ££ _øþ}!ùw’’¹clj“'ÿ477 î¼fÍD¾JjêEBH@@[^lðàvŒ±G^\»vŸÈ Áµ´DƒûB¶l9ZP INN¥”´+vëšÔß²¥;!ÄÚÚŒ×Óºu=BHÅŠ¦„‚‚Båë ÍšÕ©[·êæÍ‡½¼F98ôá É¿ Ò=rðMÂ=ÐP š7¯»mÛñÒ;wnB>¼Ëðá]Ø¿%„ÈdŒRêåU×ÄÄPXKGG›‘ùxZ__—¢¥%’_È?«|ü(cL$úàÉHŒáæòáã’ö›3gãöí¿·k×(7÷•··›ƒƒU±[פ~±X‡B©P˜|ðØF¦Ð’±cc–-ÛÞ A ß B<=‡ËïÑG‡Ê Jñè$(ãpJÁÈ‘Ý !«WïMJú/‘Je«Víίׯ_Ò®GròìääÙþþmëÖ­Ö¿¿ÂÔå³òò÷3(l”RÚ¨‘3!dÆC¼Øºu!•*™99Ù’§úØÛ[µiS?/ïõ¸q±„Û ¹š­k^¿ÊÕU.\½z/!$"bphh7aëüK\g€/× 4o^wÆŒÁÓ§¯íÙszݺUml,.^¼qÿþSBˆµµYÅŠ¦“'èÔ)|òäUIIÇŒ ŽÏ’Je+VŒ“?©OT•>+¦csæ iÙr̺uΟ¿jl\>5õ‘ˆ.^ʯ(¬Ôáðጞ–ëÑ£…Üx½È­kXQ««\hgW1;ûî AsÝÝRS/ŠDT&cü†\g€/× tüøcÀ¡C :ujòðáóÇ3 $>> –.uåÊ;;K??½{çyyÕ½rå^jêµjÙÿüó¤aÃ:‘âÎô«¿ÎàéérâDL§NMîÝ{zæLv“&µöíû©G õð]º4åwN÷êå]®œX“ë Ö/´G“…6LiРF^ÞëK—nMŸ>¨{w/BHjjÁuøR(#ªÞî ðÍ»}ûQÍšþ’ß_Ö¬YÒn@YB½1÷àsÂý PæanÀcii—¢£·§¦^,(4jT |ã3|€Rª££½gÏ)ÆX›6õW¬Çç#•v»J æ&ÀGÂÜ$€Ï s“ ÌÃ=РEV  çD>#\g€2O›ÌM€A½K»ðEan¨ƒœÔù¤œA"‘®^½·E‹Ñ&&Åb;»^νxñfÉjcŒíÞ}’Ro៮n›*Uz/ÌÉÉW¿îîÝ'E¢–·ný­üößÿo3ß´æerròkÖô¿zõ~‰[Ë+*ø%®“7’G^$j)|5ujÿŽ&Ç]¾Œü>òb±½}ïqãb_½zûéû²º·÷h‰Dú…û!Àªäïgxÿ¾°K—É™™×'Nì3ÚȨüõëbc“==‡<8¿yóº[!>¥ôôé•+[B¤RÙÕ«÷£>|¾s眢ž‘/?>ûÂÏѧ”úø4xð`›……qQOñ—_È›:aŠnÝš;9Ù”¬µŒ±‚‰šà7kVçckb˜ž§ü]»"‹ZQaï¾dücBð5éa !ïÞœ>ýט11çlÜ8¥Ø£©žŸŸÇòå;¢£·Ûóc×(³ŠÌvï>٥˔;wmm-”OŒ±¹s7ž9“‘±²jUk¾ÐÎβeK·öí'……­B¬ss_¹tÅŠq††úê+T16eŠûö“ jgbbXâzÊÕs“Ôc……Òèèä#º ƒPxíÚ°={æòµ$éÌ™ëúˆÅ>NNý.üU&c »¹ééù¸º;vAecúúba‰D"={ƒ½}o±ØÇÙ9`åÊ=Œ1ùÖN˜°¢R¥ïøäƘLƪVí;cF‚Ê-ò2EÕÉWIH8èî>DOϧZµ~Û·§îÝ{ºnÝ@^òС ùÙ,Œ±¼¼×cÆDW«ÖO,ö14ôóòuüx–Bô–,Ùêç×Șü;mfêÔÕÆÆLM;)L‰)jâMA„_H„Xñà û¥yðUqJ©|•RèãÇ/çÁç?ª>/£²Naß?=øEÍRˆ›H$’ɘL&Û³ç¯PM›¥RYDÄZ[Ûzz>Íš…λI$jyïÞ^­‡‡³……ñš5û0= ¾ªsåé4 ß^¼x#''ß×·¡ò·VV¦ü +clôèèÍ›ÇÅ¿vmSdä÷QQ›fÎ\'”\¶,).n|FÆJ½æÈdŠÃVÆØÅ‹7çÍÛܪ•»‘‘¥t̘èeË’–,yåʆ#º…†.‰‰I–ßz``ûG^Í%„<cãÆÅ®^½W(“½A[[kåÊ݇/ôöv#„T®lñðáó\3y²?/3kV‡‡3!$$¤k@@ä³gy|y:ƒyµ……™Œùø4X¹rcìéÓ¼¸¸]ññºtiJ) ívíÚý¨¨Í¡¡Ý„íº¸TiÒ¤ÖúõÛ·÷ „$$ðõmX¹²EVÖu•[¤”ª¯32rh‹®„aÃ:÷ë7kÁ‚OOBÈ!ûöùäIŽ\XH«VõZ´puss$„ØØ˜‡†vëÝ{wùò—/ßÔ©ã ? œ<ÙßÅ¥Šr râ ¥T¾0kìØ˜¢‚ߢ…+¥ÔÎÎR9ø|G4 >!D~×®Í!#FtUüS¦¬66.ߤIíôôË£F-íÙÓ[GGK¨§¨söÊçÝ)¥+š´ _ifVÁÝÝiÿþô¸¸]QQCŠB‚‚:4n"‰/U¨Ga‹š×Yl›+V4¡”®[·ßظ¼L&Û¹3mÑ¢DBÈë×o…25jT622È̼®ðþ •×Þ½+ÈÉÉ·°0V¸ÖÁû,Á/*QQ¹ÜÊÊ´Ø@ñÈÈ_!V 5k|õ5ÈWUlðUÖC)ýá‡>ûöž4)¾C‡ÆÅFÃ̬Âðá§LYennäææ¸úòåÿÜÌ ¤/Þ¨_¿†–^²_‰’ߣ)ë$'Ïþõ×cëÖíŸ?K~þ3³ Î[¶LëÞ݋֟`g·aòäU<³´4îBÞ½+8}ú¯1cb?ÎÙ¸qJ±=°Tð÷øúNxûö}DÄàzõœÞ¼y¿aÃÁž=§Ï›7l„ÞÿõÖù‡ß_æèh#ÿ•®®N ¢D) êпÿìÓ§ÿòôtj ”&$hÓ¦~µj•>¶ÎýûÓ‡]жmÃý_Ó®]£åËwDGo3¦GÙ9âðu+2gؽûd—.SîÜI´µµPþ³Ä›;wã™3Ù+«Vµæ íì,[¶tkß~RXØÊ'¢K0lå,,Œ¬­Íøg[[‹ðð!!‹óóßõnÝRBôôt…Öª¤0¼xñæ–-GoßÞRâvRJ…à;8Xñzìì,[µr÷ó›¶2--¦u¦¥]úã›.¬®[·*¥ÔÖÖbá³g³cb’{ôhñ_$ljÖÕä˜ -,Œ¬¬Lù66æ¼Ã¼|ù¦B…rŸ½ÍŸˆRZl‡QÙ$ù}$„88Xçæ¾9réŠã õÕWX*(¥“&Žxñ2#ce… åxË##¿/(Lººwï–•+[þ§[çÌÍ?ˆ[‰1ƺuknfVaÓ¦Ã×–_¿þ 5õ-[¦•à7ÐKlO™âß¾ý¤AƒÚ—GÚ_€ê¹IêUŒ±ÂBittòˆ]…„A(¼vmØž=sùZ‰tæÌõ}Äb'§þ þ*“1a6ÅÆ‡ÝÜ‚ôô|\]ƒŽ» ²Œ1}}±°D"‘Ξ½ÁÞ¾·Xìãì°råƘ|k'LXQ©Òw‰”/—ÉXÕª}gÌHP¹E^¦¨:ù* Ý݇èéùT«ÖoûöÔ½{O×­ÈK:”!?3„1–—÷z̘èjÕú‰Å>††~^^£ŽÏRˆÞ’%[ýüYX“§ LºÚظƒ©i'…é%EMb)(ðà ƒ+|a¿4>cÌа!$1ñha¡”o‘Ršš}üøRáh*J¡{ º víABkß¿/47ï#c¥Þ€säǼŒ±‹oΛ·¹U+w##Jé˜1ÑË–%-Y2òÊ• #Ft ]“,¿õÀÀö½8xð,¥”RzìØ…»wì§f‹êëœ?ÿ—%KFfeýlgg9xpTDÄÚøøñYYklm-æ(Œc"SR2ׯŸ|ãÆæ£GSJ»wÿ±°ðÿ§K¥²ääÔV­êË‹SR2ÓÒb÷îrpøÿL˜ÄR¹²¥ÂႯ|nžŸïûÇ¿^=§  öQQ›­­»÷ê±lÙö+WîÉ'oÊŠŽÞ.ßöûë¯;çÏ_ã{·gÏ©—/ßø™ðð•aaý¯\Ù8ztqãbccw(t*õûBäziVÖ ÞaøE†bÛ,tÞfõF*•‡ÏÛaTî£D"MIÉœ5+Áǧ‘‘B1•m ‹Ý=:;{CÏž-#"Ö)Ô©rs#F,Ž‹ÛµpaHvöú  óîoQÛKo¾_ظq-…^jaaܤI-]]m5ƒÝ¢z¯rb rëDƒß`:5îüÃ+îÞ}rüxÖìÙ–.U«–=/0vlÌøñ½¯\Ù0aBï±ccV¬ø'm lÿüùË}ûN §$ÔŽïNQm.*’ á”ÒsçV=x°×W~K0ÆZ·®—”t\ÍøŒTÌM24ô#„H¥2Bˆ³sÿ뛟¿_(À{ú4—"\ôgŒ»zõ^¡Lvömm­•+w>¼ÐÛÛR¹²ÅÇÏüqÍäÉþ¼Ì¬YA΄®‘Ïžåñåuê æÕJd2æãÓ`åÊ Œ±§OóââvÅÇOèÒ¥)¥44´Ûµk÷£¢6‡†v¶ëâR¥I“Zë×lßÞƒ’pÀ×·aåÊYY×Un‘Rª¾ÎÈÈ¡-Z¸B† ëܯ߬ B<=]!C†tìÛwæ“'9ra!­ZÕkÑÂÕÍÍ‘bccÚ­wïL¹Ã„}$„¼{W`ddЩS“Ÿ~ V.©Üf±X':z{L̘nÝšBFê~ýú}ž˜©™röìYÞºuV®œÀ×?¾WA„±&Ò¨é¥yy¯ !&&åK0içñãœ¢Ž¸ŽŽV±['ryBÆÃ¶¾jÕ}ú´¢”.X’’’9dÈOW¯ÞëÛ·u` ŸPfÊÿAƒÚB‚ƒ;_½zoÁ‚ÄààΔÒZµì›6­½qãa“#GÎÝ¿ÿ4(¨cLM/ÍË{¥2’ÆÆåÉ¿³ÎŠí« ¿%(¥µkW]³fŸD"ÕÑ)ùmiRñÇæüùU„cÇ2ƒƒîßÿ“••)!Š~%!7÷_N) ÒUXQ&“eeÝ–Je;† +J¥²wï îßÊttüç&`~®´°P—ïÙeccNÑÕÕ©XÑDOO—7àÒ¥[2Î\2Æš6­½]H6¸ÀÀ#F,ÎÉy¥¥%JJú}ݺ0á+å-^½z_}..UøøÃÀ@âà`ÍK–+'&„È?º„RÒe×®“¿üräÎG·n=ºté!D&“ e>|Ná·« ?êfhƘ|¡Í% >oƒ ^²uëz­[×cŒÝ¹óø×_SfÍJèÓgFjj´|ራ þ A~ &þôSð‹ùû÷ŸILœ®Id¼½Ý„}iܸöÒ¥IÏŸ¿êÌʺ¡~_:ŒXüÏM®¶™w˜/òUv…( ¦¨:…Ðax %ë0¾‰ôÈ‘óáá+}}ÆÆŽÕ××U.©Üæìì»’¦Mk mnÞÜ•ç E è)¥—.Ý’Ježž.ÂZ“'÷W.©cÌÜ܈òüùK''[ ×ÖUsÄ&CEX1)i–Â*B²]®œxãÆ© «TÉ|ùò±òqðñ©/ì5ï¹¹¯ø?(¨CpðÂçÏ_šš&$hݺ¿ûYM›ïÜy¤2’»wŸ¶Xl_Uø-Á³°0*,”Ö¬iW½zåŽÃÞ¿/LJš©\R¹ÍuêOgù>|Þ¿ÿ¬3›7Wýt/áºÊ#®áÿaíì,‹JZcçÎ]‰Dÿý<3óz³fu„¯tt´b¥­ýÏõž=½ÇŽIL<Ö·o«ääÔuëÂùr5m¾yó¡°kE5¸Ø~¥ð[‚Rª¥¥E‰p?| %¼ŸA,Ö í¶hѯ·o?’ÿŠŸŸæŸkÕ²§”Þ½ûØÑÑÆÉÉÖÉÉöÔ©¿¦O_«PUQã…%Œ±ÚµD"zêԟŸՓ'/U¬hbjj(_ÒÀ@¯oßÖ‰‰G·n=æïï««ûA^¤°EMê”c©ióÉ“ž8ñǶm3çÏܹE WþÈvùøñ3‚¿P®S¹Â¢èééòàß¹óX¡åàóÈ;:Ú(_¡ wîý—«´´?œ«ð'B ôú÷o³eË‘_M©P¡\×®Íx´Õ´¹¨HªüE¤¾_É·ÿ￟ëêjó§)ü׊œÛ©S™ìXQßRJ§MxéÒ-ácÇölÛ¶¡‰‰áÕ«÷lÙr´aÃšÆÆåË—×÷÷÷™2eµ±qù&Mj§§_5jiÏžÞ::ÿ ¹¨!‹òÙD> h¾Ò̬‚»»Óþýéqq»¢¢†*#„uhÜ8D$-^ªPÂ5¯³Ø6W¬hB)]·n¿±qy™L¶sgÚ¢E‰„×¯ß ejÔ¨ldd™y]áý*Ïž¾{W““oaa¬p­ƒ1öY‚¯°Å°°þ»wŸôö3}ú g™LöÛoç¦M[3uj€X¬ceeZl xd j׿ÿìׯ߭[Æ—™ðð•&&åëÔ©ºcljøøÝëÖ…ËWkkkñ±ûÂiÞfù£p|j֤è¯A¾ªb;ŒÊz(¥?üÐgß¾Ó“&ÅwèÐXMIÎ̬Âðá§LYennäææ¸úòåÿÜÌÀyôèŸùrò×v!ÖÖfþþ>áá+ÍÍœívîLÛ±ãÄž=Q }UM/={HJJ¦—×ÈiÓ5hPãÅ‹—?ÿ¼/&&yÞ¼aU«ZËdìñã|ÓòëRJ‹:â ù¿ú­óÏžå=zôB)ò¦‰tÀ€Ùµk;LœØ'7÷U:ƒCC—lØ0… ‹75­àêZm×®´øøÝ áÂ^3Æ‚‚:4l8ìÕ«·ƒµî¯PÓæ¢"ÉïCà/|°µµÐ¤_ÉGéâÅõë×P8jð¿ Ï3€2¯ä7ωÅ:ÉɳýõغuûçÏß’ŸÿÆÌ¬‚‡‡ó–-Óºw÷âWÌãã'ØÙm˜¬X1ÎÚ:aäÈ¥OŸæV¯^96vÌ!äËð?« Ô¨UË^__\»¶)îÁ‹šÔ©I›kÔ¨¼jÕQQ›V­ÚcnnÔ¥KÓ´´X7· ôôËffx--Ñwßy~•––È̬B\Üønݦ¶mۈߴðã§M[sùò]''›õë'÷êå-?Xwss¬W¯ú¹sW§Ë//ªÍ„•‘|ýú]ûöÎ%„\»¶é£ú•LÆÎ9²»æÓ>e„–RÚÍøÌ %}""µ/kPÿúëNýúß߸ñ‹µõgxÕ|:>ãŸw…tñ«qøpFíÚüCŒ±åËwNš——·O$¢64hî“';ø]Ë_Òúõ‡ø¦ÍÌ*”…ÿ Œ±={N©LBÊÆXJJfïÞ3®_ß\Ô‹ ÿsÔ§E¾)ªïgøÅËÍ}µsgZhèRÆH¿~mÊÂ@D‹K•|/þµ ¶í”›ûj×®“B‡)êšÀÿ4ÆØ¶mÇûõ›uölöíÛvì81gΆ€€¶"-(,X°eòäþ_>axÿ¾oºŒ$ Dƒ» ÊJéüù[ÂÃû—ZÂßž¯êÁÞ”R©Tæï?Ç̬¦MSùÓ-ËÆØ‚!žžÃ‡íô±¡„Ï‹?Hè0úúºedðúyQJçÍ6qb\§Ná/^äÛÚZ|ÿ}ÇÉ“BtuµOZÎ û…‰Å:§N-/WN\vb^âÇ|až}÷®`Ô¨ï01 ¾˜¯snü‡07 àóUÍMøßƒk†Pæ!gu3€:È@ä  ŽŠœ¿0ÈÙ9€1Æsqxøp†ÂÓÊùk°V¯ÞÛ¢Åh“Žb±]¯ç^¼x³ÄÏ5ß½û¤HÔ’RoJ½E¢–ººmªTé¼0''_MŒ1¾â­[—l»ŸBØ´šÊ—aŒåää׬éõêýOÙnQÁ/Ym<†<òüŸ|ðÕ¯«Iþ šwù2Êû(µ‹}ìí{ûêÕ[…Â_r_>ÖÓ§¹£GGW­ÚW,ö13ëìë;aÿþôj3ÈìêÕ{Ÿ=ËûØ­ó(Ý»÷„ÐÑiýäI®°uÆX~þƒv¼L‰#¹º·÷h‰DZÆÀ7BEÎ@)MO¿ìááLÉË{}íÚý† k*¼í¨ @Ò±cØÔ©«»tiöûïË®]Û´n]ø«Wo==‡Ÿ8ñG þÌ «¤§Ç=|˜ôàÁ¶›7Y»6ìÀ3ÎUó òR| cÌǧÁƒÛ*W¶,ª… O|§”N˜°¢[·æÕ«—üÍ ïßüÔÔ‹%¨7žRʃÿða’|ðÕ'l •|1”R!øEµP¹IòûøàÁ¶ììõsçÝ´é·aÃBŠ=šeAa¡¤M›ñçÏ_]·.üÆÍ))Kj×vèØ1|Û¶ãš÷JéþýéC‡.xûöýÇ& KD"Qrrª1Jé®]'ß½+~Ô¼ry~~††å¢£·—åcðíPñN7ÆØÙ³—½½Ý !gÎd;9Ù——/@);wã™3Ù+¬øu;;ËV­Üýü&†…­LK‹ùØv# #++Sþ£yxø€Å/_¾)ê§¥;lÕÓÓµ¶6S_FøÌ»xñæ–-GoßÞRâ—11Æ„àW­jÍÚÙY¶léÖ¾ý¤°°•'NDlÍB -,Œ„ݱµµàÁÏÏkh¨¯²N…½ûÂñ/6ø*GÃòûH±··ÊÍ}5räÒ+ÆU¨PN}…¥Ž1––vé?n^¸°ÚÕµ!ÄÖÖbÑ¢gÏfÇÄ$÷ìé­y=Bp>ê¨)nݺÞöí¿Ú‘ÅÛºõX³fuxúú)ý|Êÿöí' ÔÎÄİ5Àg¤xÏÙHJú}äÈ¥"Q˶m'\¾|‡Roù2’èèä#º Ç[»6lÏž¹|D"‘HgÎ\ïàÐG,öqrê¿pá¯2f€lÜxØÍ-HOÏÇÕ5èØ± *‡þ”R}}1ùwˆ#‘HgÏÞ`oß[,öqvX¹rùp3~üòJ•¾“H¤üG™ŒU­ÚwÆŒ•[äeTÖIþ€‘pÐÝ}ˆžžOµjý¶oOÝ»÷tݺ¼ä¡C ³Yòò^]­Z?±ØÇÐÐÏËkÔñãY ÃÖ%K¶úù527761uêjc㦦ä§Ä5ñ†1VX(åÁ!V<ø< |…M„à« ”ü¸“2a |¾\}ð‹: |ùç >)‚Bg‰D2“ÉdB…jÚ,•Ê""ÖÚÚöÐÓóiÖ,tîÜMÅNÂÑdwŠZKa¢¥Ôа!$1ñhADXžš}üøRòï¤A5QåýÍ̬sçΓcvv½(õ.ê+¯¼°P2yò*këîúú¾>>ã³³ïÊ·³GïcÇ.¼x‘Ï·’—÷úС ù쥨ÿ¼=ëתSg°XìS­Z¿åËwÊ漢‡³……ñš5û0=  Ô)æ &ýñÇZmm­Û·>LêÐÁsæÌÀ‡“䇒/ÞÈÉÉ÷õm¨p‘RjeejbbÈ'ጽyóḸñ×®mŠŒü>*jÓÌ™ë„ÂË–%ÅÅÏÈXi` 7`Àa€Bä†tYY7æÍÛܪ•;¿È0fLô²eIK–Œ¼reÈÝBC—DGo—O¶ôèÅÁƒgùð娱 wï><ØOå¥RcL}óçÿ²dÉȬ¬Ÿíì,ŽŠˆX?>+k­­E@Àm&„D¦¤d®_Ò™R9 IDAT?ùÆÍG.¦”vïþca¡T( •Ê’“S[µªÏãæ¤d¦¥ÅîÝeoo%Ÿ,©œxC)‚¯<âÁç,qð…³Å/ÞäÁ722 ”**&&Y~ëBðùÞ©>ߢú:?oðå û(‘H»0kV‚O##…b*Û»#:ztvö†ž=[FD¬“¯S™†}I*•)¬UÔD©úõ«µŠÚlmݽgÏéË–m¿råžü®©ªÐßÖ¯ŸL)=wnÕÇI„•†ÿ?=:úçŸ÷ÅÇO¸|y}‡§N]#ßž-\ÍÌ*ìØq‚÷;ÓÜݪT©¨á¡;6füøÞW®l˜0¡÷ر1+V|6´n]/)é8¦'”:ÅœÁÊÊôÑ£NN¶vv–VV¦W¯ÞoÚ´Ž0YˆB)}ú4——ÆCcÇÆú ÿy’#”dŒ´jUoݺð&MjÙÚZ4lX34´[NN>wùò—/ßÔ©ã †~òdÿZµì7®¥00âo´µµ®äÁ¾ÊÁò$—¿mÛ†vv–=z´P¾Çÿ±wçq9eÿÀÏyžê)­ª'¥§’RŠP„ÂÄØJ–”%cÚ²Tf&"™F¢ÍPaì‘¥¡1F4#cÉÒ„I¨¨Ä žç9¿?Îüî÷ºÏR²›Ïû5¯ï«îsî9Ÿó¹·¯sî=÷>®v:YÊ&ŸV¢¡1I>!¤²²–&ÊÇÇÝÒÒ8,ÌWIòiïd“Ïi‘I¾¢:ãâ¦{x8ÙÚš1Éws³·µ5S’|ww‘HØ­›­lòLut†hh 3æk/¯n[¶DË–”¹®îIbâ^æ„™5kÔôéØC#[bÍ%š<—8“Cæ­3-m^^Þª1c<þøãzxx¢]ÀÀååUÍ9RÌùFÒ¥€Ì #û×úða}zú¡å˧{{÷¢]þüó¡ì`x<ƒöQ,–üüó¹ÈÈÔ»'%ͦurÈÆ\Rr»¡AìîîÀÄܧSRÒ>ÔŒû MžK/u5}À€®tEݼyoçÎã±±ãÆ->y2±É#EÏ7NmÅÅ¥ŠN˜[·î‰Å77{öß{BhôhÏO?W[û˜tìØ©©óΞ½J?jòÐxy¹05÷ìéðÝw{jkëéiÑ-B¡nc£¸²²–ž–xW¸smíÁt´ŽÎº*ÝÂÂ!T_ŸK `Œ­µµ[;öG·n¶ôŸv##=##=B³Ö™Ž vìˆá¼ H$^ºT†âñ0~q*B°°hceõÂJ}ú)3È`Ctï…[%~~žsæ¬Û±ãŸÏ×ÔT÷övg>’m±É:ù|Þ‹W ÅbÉ€snÞ¼çççééÙ%8Ø¢¼¼Êß» Ý—Ç{¡NÎå!Lò»wïH7Òä#„^*ùìØÉg/‘bÂfÅ ïZ|N‹MÖÉçóØ‘`¬ðZ~s’Ï`úhggÑ¡ƒÙ°a Ÿ?oܽ{±lIÙ˜éD…nÌL/d+a66y.5sê¿íùóÆ¯¿žDµ´4ž7o¬ººZxxbmíã&³*÷|SrÂܾ}Ÿv™ùQUåþŸFŸ> tsr èìÂÄDŸù¨ÉC£ªªÂùëc"$„ðù|„k“€wŒ»6éܹ4ýï¿_pî\ÚŒ#‡ ëyî\Ú¹siìᎺºZX˜ï·ßî¼uë>gAÅ­[÷éÏ:YbŒoß¾oc#²±Y[›ž>}ùë¯7±Ûb/ÑálçlÁ;8XñxøôéKôSŒqAÁÅ6mZëëk³‹iii|öÙ€;ŽíÚ•ïï?¹M!·ÅfÖ©¤FAÁ¥_ýs÷î%+W†y÷íÛ¹´´!Ä.K¯•Þ¿ÿP¶NÙ å ª4ù7oÞcD‘M¾µµ)Í¿lò91°·s¶B˜D1ƒ9ÙD!„45ÕÙÉWS{apÉi±9ur²­(f&ù ÁAAÞN²É—ÛÇ»-Y25;ûdzú!E%Ù-:9µWUUaÇ\XxYQÞ˜.(ªM¶wòÃ}±¶[·î­\¹ýîÝœ[µ´j¥Þü¬²›Sò×Ú¹s{55•'Î3#L—Ìò¤Ý»³&¡fü]œ9s™©ùÔ©?íì,èCÞtËÝ»ÔÔT„B½&3€7Š{ɰuk튊ÞÞ½´´4þúë®§gî7 B¾újÒÅ‹e®®Á³g4¨{ëÖÚ×®•gdü¸}û±îÝ;êéiiiiøû{EG§ëéiõêåPXxeæÌïÆŒñTUýßúlEƒ$¹ÛõEF¦ètéb“›[˜œœ?B(0phÏž!<oõê0ÎpœSs›6­›Yg“1·iÓc¼ys®žž–T*Ý¿ÿÔ·ßî@=yò”)ckk¦««yþüÞ½•×Iyþ¼±¦¦^(Ôã¬hÇ¿–ä+š¨È^íÆ7'Qt/vòe¯£s2ÖÌ:›Œ¹9É—ÛGBȼyã>³`AÊС=å–dÿj` ìfh¨ëìl›[¸~ý¿ “¤RrÿþC„P¨Ç¾C¢dr¨ü>óg ôàÔ¶pá„ <=ÿþz²««T*ýé§³_}µqÑ¢55•æg•¾ëÌ™Ënnö"‘Pî £¦¦¢¯¯>:::]__ÇÍÍ>7·³0‰¢Ë“x<œ•õ“!Mš… SôõuœœÚçäœJI9‘É>:.”º¸ØòùðuõÀ;Æ3œ9s¹S'K-- „ÐéÓ—ÂÃGËDª©©dg/ݹ3óæÜ„„íõõÿ踺ÚmßþÕÈ‘}é¿ñ))ææYQQiwîTéy/^<•]Oó‡­tㆠsLL2fÌø®ªª¶C³¤¤ðÀÀ!œÀB..:u²ÔÐЫ§Ê[lfMÆlkk––6/>~kZÚACC]÷S§’œ ¯èÐ2|>oÔ¨¾GŽü6cÆHåýÅçåùøD—–n“],$¨*I>]ÈÑdò_j†1–MÔ´i/< K{Ñ­›-M¾ƒƒ’¹ÊΩ¶9u6'ææ$_n=cmÜ8¿K—i¡¡«§N¢¨$#!!X[»Uhèêêê:Û ÆÇÆf ªuuMMG#„JK·±×)É€’ÞB˜€³TÏ¢Ío¿¥¬X±-&fSyyŸÏsrjŸ”4{üø´†ffÕÕÕnÈ×I“–#„®_ß*÷„¡%ãâ¦ëêjÍ›·¡²²¦G»˜˜É ¤pÒÒ»·£¾¾vçÎíé{„Mš/¿œôÕW¯\¹mccš™åççÉZª„òòŠfÌÙüÅ{xC0A‘ãï:Œ×†.:·²3…3Tzç!W®Üvqù¼´ô‡¶mßëïk±ÆF1M~`ào¨Gùé§³VÌ{«’’ö-X\Ww˜ÇÃYYy“'/¯¬Üg` óñõýõ"„1~|lQÑÕ›7ïegŸ\¶,+ `‡Ä+WnŠš†æhòyBHBÂöÈÈ 0aÞܵI.BˆD"õ÷_f` ³uë" µ÷p¨1^¹2ÄÍ-xúôáÌ«}fìÝ{òÛjh¶P]Ýë›o¶3?{z΢iQ´×«äM"‘¦§ª®®cö­©©ïØÑÿÚµrBHnn¡§ç,±XÒ‚šßD~À[Ö’ïgPþnõ`WâåÕíÎÝB¡ÞËÖÌDUX˜lf&D=ÞøçŸ……}W]]—’2÷Õã䨫{2p`ÄÓ§Ïcb¦tíjóÏ?ϳ²ŽŒóõŠ_ÌëײÌBNúóðá½{cûõëÂüÜ«—ƒD" õ!rßgÿ*yËÍ-œ>}å AÝ龄ˆˆ ¾¾}llL1ƃ»®_¿/1qïìÙc^ªæ7‘ðö)œ38Pàã}ëÖ‘HÈÞq¾ÃõÕìIˆººš‰‰A *a uõé¯mîÜ©ž9síêÕa¯÷‹Æ! $?|ø¨¨(UWW“n\¾|zCƒxÑ¢ô±cûÉæ­™½xòäBÈÅ¥ƒŽN+æg¡PWImãWÉ“úÃ… mß~ìæÍíÌ":ÚÈ“'Úºµv3«m2?ffF-ˆ¼}ò×&5ù-­ì_ÅbÉ’%™VVã/› «Ví”Jÿ-PW÷$<<±}ûñ—¶öà¾}gž8QL!„46Š£¢ÒLLFjh 80¢¤ä6Ý…YcCز%ÏÙ9P]ÝËÉ)0?ÿº¯D"‰Ù$VW÷êÝ;lùò­t]“lÌãV­ÔB‰„¢$ž-[ò&«©}blìøMmícº]nï!?ÍÈ86’ÓÌ,\8þر5mÚèÓÌ,]šei9V ð²³ HM=ȤNQµ{I17÷ãñú1?33ª´tÛ±c«1Æ#G~ÙØ(¡{}ÿýá””ˆ+W2‡í¹hÑF¹‘¬]»'9ynQQª¦¦úĉËèldᔤ¤}‰‰³JJ²ÆŒé³™³óåË·V­Ú1þ8-- „¢x®_¿3yòò1c<¯_ߺ{÷’Ÿ~:™Š1ÆËíBèÂ…¿ž?oìÙ³g~%êõêÕIMMcž¸víž5kf\½šê¶fݺlšEÕVTìÉ̌Ÿ=›Æþ™Ý»ÐÐÕÉÉ9«V…””d:uÅ?þÖäQ’ÒŒŒHÚÊ;»%ivöÉþý]8ý0 ëž='dï8Ñ5QffFœòMæGîáï!9C7míÁ!‰Dв³  ÃÄúú\¦{XYY›šz /o•‡‡ÆØÜܨ¢âÁ—_nŒŠòWQá÷ïßÕÃÃÉÙÙ!djjæ;vì⪪ZuuµôôC))s‡ï‰1}ãFùúõûeƒ‰ tuµC…„Œˆ«®®T÷®[>bDoŒñ¬Y£nÜ(OJÚÇìâè8…ÆÜØ(nh[ZÏ™3!DRÏýû¥RÒ¶­¡H$477Êɉ£+v”ô®®î B¨uk-EK†*+k““sRR"||Ü1Æaa¾×¯—ÇÇo óeªõôtF™™ ™jõõô´Ðÿ¯°b~¾s§ŠV[]]·yó©©¾¾}Bsçú54ˆÙÓ:%13)us³g§”ÝâÅ‹eýãèhÅ™7:8´Û¸ñpc£XUõ…sFîš(zKGy~À‡BΜáܹ4„P~þù  U¹¹ß룟[`‹‹K%é°a ™‰ôÙ³†òò*++㟜œ‚~øùÖ­{ee÷.^,CI¥Ò JÅb‰››=³bÞÝÝQîœÁÚÚ”–¡K\Å%%·Äîî̾}ú8±ç Æ›š"„ž=k8{öÚÂ…)&Ä>¼c¤(ž^½Föøâ‹UÑÑéŸ|ââíí>jT_å½34ÔE=xðÈÚZþCÉ/–I¥¤gÏNì>&&î­®®Sž4åìâÅ2‰DêæfOÆ8*jBèÀ‚&“R:ëcRÊ®¿¢âBˆó°5ÆX(ÔmlWVÖ¶mkÐä4c¬_v_E!ŽŽVÊóÓ·oç&ëïƒW}ž¡S'KŒñíÛ÷mlD66"kkÓÓ§/ýõ&„PAÁ¥_ýs÷î% ÁAAÞN¥¥!BPçÎíÕÔTNœ8Ï\ƒ/,¼¬(D:àf~urj¯ªªrúô%%û²_¤««EÀJâùå— AA«¬­M#"Æææ~³víÌŸ~:ûða½’Þ©««ùû\¿~ߣGÿ°CýöÛ§N]455tp°âñ0;΂‚‹mÚ´Ö××fªµ¶6¥53Õ6‰îûûïW™>ŽýUhèšæv~=æNoÑÜ¿ÿSàîÝjj*ôþC“AÒ÷8)ÏOs: Þ E>¼—Tš/÷#ö¨Q$úû{EG§ëéiõêåPXxeæÌïÆŒñTUå·iÓc¼ys®žž–T*Ý¿ÿÔ·ßî@=yòÔÌL>:::]__ÇÍÍ>7·PîÂ$ÙæB:ÁÁÞÑÑi††ºÎÎÖ¹¹…ë×ïC¬oUUººBˆTYY³~}ö¨QZZJâÑÒÒHO?$•’9süÅû÷ÿÚ±£yëÖÚúúÚr{Gá]ºtÚñãçûöñÕW“»u³}øðÑ÷ß^·.{ÅŠ/Úµ3A ŠŒL50ÐéÒÅ&7·099'>~:ÆØÌÌHQÒš<`ÆÆúþþ^‘‘©††ºvvæû÷ŸÚ·ï׃ã™%FJŽS ç^††!tæÌe77{[[3]]Íóçoôéó¿û„ J]\lù|îý‡çÏkjê…B=•‚Ç7™ðAhÉëk8#Δ”s󬨨´;wªŒô‚‚¼/žŠ²µ5KK›¿5-í ¡¡®û©SIÎÎ……W:v4‹›®««5oÞ†ÊÊš=ìbb&/XÒœæB ÁÚÚ­BCWWW×¹¸Ø.X0>66S P¥ŸººѽTUUÌÌ„>>½cb&+gÒ¤A[¶,Š‹Ûâäت• ÿ®ÆóxXQïèr#S§’–/ß²paÊ­[÷ÕÔTºví°gÏúp6BhÆ9&&3f|WUUÛ¡ƒYRRø´iCB„¹Õ6sÝròÜÅ‹7ñÅÊû÷k:tmÙ²hРîžnòˆ08Ó0WW»!C\'MZŽº~}ë¨Q}ù-,Ì—¹CBÊË+š1c¤ì{“òòŠ||¢KK·YZs>m2?àƒ€ Bˆ×a¼BÈO?up°b¾¸-)iß‚Éuu‡›¹Ú(wùò-—ÏKK01ù7ÃùùŒ»øÆmÚÚaž¨ËÍ…1üM÷œüçÞgãÝ»OŒ[TtõæÍ{ÙÙ'—-Ë †×ÅÞÞbâD¯Õ«w2÷¶GFN€ ÀÓyŸ¡®îÉüùÉ99§>¬‰„þþ£¢&2k“À+"„xï}xsïÌx½`ÎÞ{på  ÌÊÀœà‚…Ià½s€20g(ÓÂ9Ã<^¿²²»äuÜM#„Ð ÿþ»òUj&„ìÚucOÎ<^¿ž=CZÛ'ŸÌéØÑ_vû¦M¹|~ÿÒÒŠ—Š“"‘HÓÓUW×½l$„ššúŽý¯]+'„äæzz΋%/[Ï®]Çy¼~²YêÙ3¤e9§)âìKaRô²u2)z-gxE*-؇=’{-_òÅ®ÄË«Û;»…B½ÔLwÁŸ8ñµµ)û#55UBÈËÖI :aÂÒÓ§/õìÙ‰½=#ãÇO>qi×Îä¥êÄçæž™>}å AÝ_6ŒqDÄ_ß>:ˆBŸ~Úcýú}‰‰{ÃÃG7¿æØýòËZÙµ,ç4EgÎ\vs³gjÀÓµoßö¥*¤Ó!š"ø 9€÷Âû Ì…Ùk½ì‘ÜëºÏÀü¬®®fbb ¢Â•z uML Øÿè´l@ìëÛÇÀ@gëÖ<¦rBHiiÅÉ“N›6´“¦ž—Ý·¸¸tûöcsæøÑ0ÆÑÑþ±±™µµ›˜F uõ9)z©x(B“"vnܸCSô²gƘê„^/ùsåw8#9±X²dI¦•Õ8ÀËÆfªU;¥Ò ÔÕ= Olß~¼@७=¸oß™'NÓqsc£8**ÍÄd¤†ÆÀ#JJnÓ]˜µIô‡-[òœÕÕ½œœóóÿ ûJ$Ò˜˜M"Ñhuu¯Þ½Ã–/ßJ§7J‚¤rr x¼~iii=11›´´>½x±Œ¶•™yÔÑqŠ@àÕ¾ýøõë÷ÓÔÕÕíØ‘ßÐ fë™™GŒŒô||zBävŸjhÇÄlj×î3ÀËÎ. #ãBÈÛ;Šbn'Ý}éÒ,K˱´Lj꿱Ñ-J×Óª¯?¼¬ìîš5»îah¨Ë77{¡PoãÆÃ²ÇHѯ&,“"ºEyŠh%*MÑóçL=LŠ”Ÿ!²)"„øøDÓñùý妈ÝG&E²‡ø0À}uðÞ“¿6‰s'3¸äü:kVâÏ?ŸMNžkggQXx9$du}ý“¯¿žŒ ˆ»uë^ff”…E›»wDDl9òË»w÷ªªògÍJÜ»÷—ÔÔy;·Û·ï× RäF²vížää¹ZZÓ§¯œ8qÙíÛ;y<¼paÊæÍ?¦¦Ftéb³ÿ©ùó“•wáíÝ+(È{Þ¼ ƒõ(+»»tiVJJD§N–eewB³g¯[µ*ÄÓÓ97·0<|Æ((È!4uêÕ«w>|Æ×·BH"‘fd™<ùSUU¾¢îÇÄLA…†®>p `Æ9ÎÎÖ{öü2uê ##½Į̀I“–¥š˜è#„ÂÃwî<žšáìl}ðàé°°5ÏŸ7„…ùÒ€?êTÒ£GOÌÌŒ²³OÆÅM皺îÙsbî\?ÎvEK¼š<²Ã‡÷|©û`Œ™Ñ!$•š"55ågˆÜedD¶ ErÏðêäÌ´µ#„$)BÈÎ.€+ëës™ìkÕ••µ©©òòVyx8aŒÍÍ**|ù寍(~ÿþ]=<œœ­B¦¦†aa¾cÇ.®ªªUWWKO?”’2wøðžãððÑ7n”ÓëÖ±±®®v¡qÕÕujbâÞuëÂGŒè1ž5kÔåIIûØ{uïþg4œ–6oìØ~¡•+CŽ??mÚ7×®ýýÙg‡0e¢£ý'M„1ö¹víï•+wû „ìí-ÜݶlÉ£âŸ>W^^8”Ý}OOg„™™é~]Ýc:±¡qFDŒmh‚ôô´BB¡®±±~UU]rrNJJ„;Æ8,Ì÷úõòøømÌ€8*Ê¿S'K„ПþõèÑ?ŽŽVì>ÆØÁ¡ÝƇÅb‰Š Ÿ½.ñ’Í'sìä¦hܸþcNЦNÌNÑäÉŸ"„‚‚¼iŠ‚‚¼1Æ:YÒÑiÕÏ?Ÿ¥)"„(9C˜ѽæÎõS’"šüÐв)¡»È¸ IDAT²··€'Þ9s†sçÒBùù烂Våæ~cl¬^¼&ÍŸ—J$ÒaÃ2%é³g ååUVVÆ!!>99?üðó­[÷ÊÊî]¼X†’J¥.”ŠÅæ‘YBˆ»»£Ü9ƒµµ)-£««‰jl—”Ünh»»;0ûöéãÄ™3ìÙÛ® {‹±±>-¯¡¡¶eË¢=¾hÛÖpýúÙìù—— SgÏžß}·§¦¦¾ukmú˜oPЪ‡ëõõµ32~0 +}€XI÷oݺ'‘HÙGEM „¦C|š¢1)¢O?7'ELQQBȦˆ)#›"˜0¼Qræ 66"B}ÀÀÒÒØÌ̈S€=ΖJ¥¡;bèË|"‘P,– 0çæÍ{~~žžž]‚ƒ-ÊË«üý—¡ÿ¹‚˜ ªªüUR<f7GW·sö•}tÁÜ܈™lp`ŒÏž½ÊãñîÞ}pþü>}:3©ªªpêTQáÓÆŒñœ={ÝŽùŸ}Ö?;ûäæÍ‘t»’îÿõW³Üé³;S†i—Çû÷9æîý_Ç©Ïç3YjÎЙɕ¹¹‘HQvŠz÷vd§ˆ™Þ0)¢[dSD·7'EJžªgRÄi—¢¼ 4Ÿüg •¿‰ýi§N–ãÛ·ïÛØˆllDÖÖ¦§O_þúëM¡‚‚K¿þúçîÝK‚ƒ‚¼=<œè«ú A;·WSS9qâ<3,,¼¬(D:˜f~urj¯ªªrúô%åû*D^½ú÷œ9I11Süüúı_:tæÌe¦ÎS§þ´³³ÐÒÒ ­·j%˜0á“íÛÞ¹ó¸ŽN+ºÜˆ®É¡Ý·¶6¥`ºO?úý÷«L£G²š˜ƒƒ‡Ù})(¸Ø¦Mk}}mvþ !ô6Âýû9‡æîÝjj*Í5­ò#K7^»VÎNQ]Ýÿ8sæ2ó 8M‘¶v+ú‘¦¦:'E4r%g“"&’Ñ£¿ ]#7EL»²)‚ À¥ðû†ï%•æËýˆ=Ö‰„þþ^ÑÑézzZ½z9^™9ó»1cmÚPv»´-þ¨Q}ùmÆŒ‘ÌGR)ÉË+š1c$gÐLÉË+òñ‰.-ÝfeõÂC L1ÙaŒëê1)âóy:ÊSäççÉžÀ8;[3)bo—›":{iYŠØO®Ë=CÀk„ Bˆ×a¼BÈO?up°bkNJÚ·`Ar]Ýa·løxà@a[Z¿ŸPBÈ•+·]\>/-ý¡m[ºåøñócÇ.¾qc›ŽN«7ÝúÁƒ§åNBÿEØÁW.ða Sà=§ð{ ß[ãÝ»OŒ[TtõæÍ{ÙÙ'—-Ë Ôâ ƒò¯9{O`ŒíìÌ'NôZ½z'³²?!a{dä„7=a@oà›¿ÀäÛ3BV¬øÂÆF4|xd‡çÎ]ÿùçÃV¯kñpÿCcŒW® 9xðôw!GŽüþìYÃÌ™£ÞBÌÄ´ ¼!ÞÚ$ï¬Màõ‚µIà½÷áÝg¼M0g(s€20g(s€2-œ38PÀãõ++»ûZ^ôI¡þýwå«ÔL÷UUPYYËÞ^_ÿ¦æ§´þWöe1½++»Ûü255õ;ú_»VNÉÍ-ôôœ%KÞçWÁ€UKæ ¯ýmýìJ¼¼ºÝ¹³ÛÌÌèekf¢âñxÙÙ'™_ !99Ïž5pн5c¦SŠZç|G!$"bƒ¯oSŒñàÁ®ÚÚ­÷Âw#!¸&Þ{ ç Ì…Ùaîkÿ4v%êêj&&**ü—­„‰jÀ€®{÷þÂüŠ1Þµ+¿woGN±·‰é”¢Ö9i¼pá¯íÛÍ™ãGËB¢£ýcc3kjêßF¸°ÈŸ3(¿“ÀàŠÅ’%K2­¬Æ ^66V­Ú)•þ[ ®îIxxbûöã/míÁ}ûÎ~ë’%›é: îøñó™™Q¥¥ÛŽ[19òËÆF Ýëû理D\¹’9thÏE‹6ÊdíÚ=ÉÉs‹ŠR55Õ'N\Fg# ¦$%íKLœUR’5fL¿˜˜Íì]<<œ töíû•ưÿ©.]l,,Ú0ÂÃ׮ݳfÍŒ«W³BC}ÃÂÖ$&îeº)·EÙ]Ö­Ëf*LHøaÍšÅÅß››M™³)%enqñF‘H°Œ™AQJrBI$Òìì“ýû»pfntݳç,Oo™œ9ƒ¶ö`míÁcÇ.FÙÙèè ÑÖÌ.ÀËVVÖ¦¦HNž;p`7ss£1c<- øöÛ]BPÿþ]7oŽtww‰„ݺن…ùÖÔÔWUÕ>|XŸž~hùòéÇ÷´´4ýùçCåÆèêjש“eHȈ»wTW×ÕÕ=ILÜ»|ùô#z[ZÏš5júôa/t‰‡GêK—'Ñ…I~~ý˜O«ªê’“s˜ÝCCGûÄÇoSÒ"³‹»¥¥qX˜/g—¸¸éN¶¶f_|á]_ÿÏÊ•!nnö¶¶fÓ¦ «¬¬­¬¬a¥NaN˜2W®ÜzôèGG+ÎÌÍÁ¡Ý¹s×Å &o€Šì¦sçÒBùù烂Våæ~cl¬"„°Ÿ` —J$ÒaÃ2%é³g ååUVVÆ!!>99?üðó­[÷ÊÊî]¼X†’J¥.”ŠÅ77{f½¾»»ãúõûeƒ±¶6¥etu5Bâ’’Û bwwfß>}œ’’ö±÷=ÚóÓOçÕÔÔ‚Žû#5uÞÙ³WéG/–I¥¤gÏN´GcwwÇÄĽÕÕuŠZ¼v­œîÂŽ–½‹½½Gijª#„¬¬LhÉV­!±ø÷0FŠr”©¨x€ õ89 uÅ••µ¦¦†JŽ(¯—œ9ƒˆB0°´4633â`ßg ƒÝ;b:t±ËˆDB±X2`Àœ›7ïùùyzzv ¶(/¯ò÷_†þÖAbr"Añx˜Ý}´€³¯ìê©>}:èæäЙ‰‰‰>'`V „îÎãñµÈìÂi‘Ù…Ïç±çQ+|4\INX»cZ9ç>ŸÏ§áÉ­*ŒáÕIà='¤Î­rÖгíÔÉc|ûöý¡CÝhᬬ¼,ܼ9² àÒ¯¿þyæÌ†îÝmé.K–d"„A;·WSS9qâ¼½½Ý«°ð²¢9­;9µWUU9}ú’’}™åI ì…I!+Ÿ>}ÉÎΜN .¶iÓZ__[Q‹Ì.L‹²»p& Šž:P’½pÿþCú¢U¦Â»w¨©©0FðvÈŸ3 „†ï%•æËýˆ=>‰„þþ^ÑÑézzZ½z9^™9ó»1cÙ^¸PêâbËçÃWw€·JáœA Îø8%%ÂÜ<+**íÎj##½  ïÅ‹§"„lmÍÒÒæÅÇoMK;hh¨ëãã~êT’³s`aᕎÍãâ¦ëêjÍ›·¡²²¦G»˜˜É ¤4§9„PBB°¶v«ÐÐÕÕÕu..¶ ŒÍTÙez÷vÔ××îܹ½g÷ 昘d̘ñ]UUm‡fIIáC”·(»Ë´i/<´ÝÌû JrÂÄÉçóFê{äÈoaa¾¬T(/¯hÆŒ‘ðÞ$ð–a‚"Çßu/òÓOg¬Œõé:)iß‚Éuu‡y<üq ©/_¾åâòyié&&ÿö1?ÿ±c߸±M[[ããè#à†=aí5¯<ÏÞ{ÞBŒñîÝ'Æ-*ºzóæ½ìì“Ë–e úh& !{{‹‰½V¯ÞÉÜgHHØ9& àíû ï3ÔÕ=™??9'çÔÇõ"‘Ðß`TÔDÎÚ¤!äÑ£ÜÜ‚sr⬭M-Z±b[^Þ*x˜ð^€û ¼^pŸ¼÷>¼9€w æ ¼^0gï=¸n Pæ e`ÎPæ e`ÎP¦…s† x¼~eewÉë{ÌŸ"‘HÓÓUW×B˜&ä–¬©©ïØÑÿÚµrBHnn¡§ç,±XòRm)©ŸbÓ’þðQhÉœ=†~_1†1ÎÍ-œ>}åÓ§Ï5Ç”ŒˆØàëÛ§CÆøÓO{hk·JLÜÛüÁ=ÆØË«Û;»ÍÌŒäîE§"4ø5ð_¦pÎ@/Ãÿýw¥Ü!;óóë½Ï ·6Ù!{qqéöíÇæÌñ£å1ÆÑÑþ±±™µµ›ººš‰‰Š _î”cÌT÷À™ü9ƒò; œ1´X,Y²$ÓÊjœ@àec3aÕªR)aÿlÙ’ç쨮îå䘟ÿÝE"‘ÆÄl‰F««{õî¶|ùV¯_yy•·w!ÄÜÜÇëGKæäØÙ¨«{uë6½ àW¬Y³kðà††ºLlnnöB¡ÞƇe£U´ŒŠÙ.7NBˆO4 †ÏïÿrIà#"ΠüNg\>kVâ¶myÉÉs¯_ß÷y|üÖ%K63Ÿ®]»'9ynQQª¦¦úĉË$)!dᔤ¤}‰‰³JJ²ÆŒéóoùÌÌ(ŒñÙ³i{è–ÔÔ©©¿ÿž¢¦¦:~ü„D"ÍÎ>Ù¿¿ 'ȺîÙs‚-!„Yƒ¤¼Sœ8¥R’‘Iƒ¹sg·âð‘S‘ݤ­=!$‘HBvvt¨]_ŸË`¸++kSSäå­òðp››UT<øòËQQþ´@ll ››=B($dD@@\uu@ š˜¸wݺp_ß>¡™3GÞ¸Qž”´!¤§§… uõéî Á½{;"„ÂÂFNœ¸´ººîÞ½‡ýãèhEa¦c‡v7‹%ìåFcº‰ÓGÙÛ²q2ÁÈîðÚÀ*hðÞ“3g8w. !”Ÿ>(hUnî7tøÎ 3…‹‹K%é°a ™‰ôÙ³†òò*ú«µµ)cèêj"„Å%%·Äîî´NŒqŸ>NtÎ ‹>åŒÒÖÖ@=ÞXQñ!$êqî…ºâÊÊZSSÃ&»-{ŸA6Nvax ügÉ™3ØØˆ!%%·B––ÆffFœì·T*EíØÓ¡ƒˆ]F$^ºT†âñ0gpO_ŠJÈ¿sE>S|>ý)3|çñxœi ŸÏ§Í5gˆ/[@6N%…øïxÕç:u²Äß¾}߯Fdc#²¶6=}úò×_ob—çÌ œœÚ«ªªœ>}‰yëQaáeÙšÙͱ·ÓÛ÷ï?äy÷î55ÎýE½_UîTÞ›þ˾kuøð^Ri>çÑaŠ=†‰„þþ^ÑÑé?üðó­[÷wí:1sæwššêªª|¦ gÐo` ì–“SpëÖýääœõë÷Ñb„Й3—™¥MHf(okk¦««yþü ÎøþÂ…R[•ÿµK={Öp÷î±XÒä­Nœrƒ࿦%ßéÆp§¤D„…ùFE¥ÙØL˜3g]P÷ºuá첫‚?ÿ|Xhèj[Û‰YYG,T]]í† q4i¹­­?}nÉ åù|Þ¨Q}ù½Q*%yyE£G{Ⱦ7)/¯ÈÔtôßW6ùµœ8ÙÁ4;7|l0A‘ão¹Õ¼¼"+ú>"BÈúõû,H®«;Ìç7=‡!„\¹rÛÅåóÒÒÚ¶ý·†ãÇÏ»øÆm::­Þxôð‡=á5/¼NÃßxϵä>Ã+"„ìÞ}büøØß/¹yóÞ¾}¿.[–0¨9„ÆØÎÎ|âD¯Õ«w2OD$$lŒœ^»wsŸ¡¶öñüùÉ99§>¬‰„þþ£¢&ª©©4ÿ EuuOÜÜ‚sr⬭M-Z±b[^Þ*λ¼pŸ€× î3€÷Þ»™3ø€Áœ€× æ à½÷Ö&> 0g(s€20g(s€2oiÎ@‘H¤é釪«ë^Wðxýþþ»’~sMM}ÇŽþ×®•¿Jb±$=ý‡Ç¬Ö­‡ ^ææ~“&-¿pᯖÕF9p cOæ?5µO,,Æ­ª©©W¾/í]YÙ]¹_YýæÐ˜iÓÍ)#ÛG¯Ÿ@àei9vΜ¤ÇŸr ¿Í8_¶¿¿¢v9ƒÚ³g¯xOºB,–pR¡èLcÿªüHÉ=%ŠÆæêj'êmÜx˜Óœù/uæ#„^êÌ>zòç œ‘lBȬY‰Û¶å%'Ͻ~}k\Üçññ[—,ÙŒ1ööîä=oÞ†¿ÿ®úå— K—f}÷ÝÌN,33£0ÆgϦUTìAÉÝ©íÚ=ÉÉs‹ŠR55Õ'N\&‘Hi‹ß8%%âʕ̡C{.Z´‘–H¤ÙÙ'û÷wÁ3‘?~þÔ©¤C‡â--™Ìò33#Î÷Â…Òššú»ËöרXŸ^µUÔkEaK¥Ü©½%²bŶþý»èêjbŒÃÃ׮ݳfÍŒ«W³BC}ÃÂÖ¬[—Ín}êÔ!÷î=8!¤§§… uõ™Ý=<œ0ÆææFÌî´‰ØØ@77{„PHȈ€€¸êê:~zú¡””¹ÞÞ½B³fºq£|ýúý¡+Wn=zô££{Ðåß©“¥lïä.? „TUÕ"„Œõ™!Μ9Ié釘2%%Y**|E½fÂvuµc‡M·;:N¡Õ66Š¥RâåÕ-55‚RUU—œœ“’áããŽ1 ó½~½<>~[X˜/Ó®½½E¯^23 âŠÊÈøqàÀîffÂââr[Ä+¯3.nº‡‡Bè‹/¼Ç]¹2„¦zÚ´aŸ}¶¤²²†•Ô¿W'ggk„©©aX˜ïر‹i®8˜>"„ž=kÐÕÕ>¼×7ßÉ–”Y PMLÜ»n]øˆ½1Æôà&%íCЍ(ZÄ‚1–{ˆe+‘=ǘSTù&úùs×§O_9uêào¾ ’¡¢3ù¹É£/!“(_ß>¡™3G2‰bÎ[‡v7nl«ª¾ð× gþ:ó€ÿ9s†sçÒBùù烂Våæ~cl¬d†eÅÅ¥‰tذ…ÌF‰DúìYCyy•••±††Ú–-‹zôø¢m[ÃõëgË^¿T²;ýÕÚÚ”îE¯R76Š/_¾)KÜÜìi$cwwG:g¨¨x€â99?üðó­[÷ÊÊî]¼X†’J¥²9¤}‹%?ÿ|.22uàÀîII³i²1—”Ünh»»;01÷éãÄ ËjÎò9Eå™08ç»p“íúû/{þ¼Ñ¸™ç˜l¨M}Ù™D1g)“(f‹P¨ÛØ(®¬¬mÛÖ ÉØàÌG¯|æÿræ 66"B}ZÀÒÒØÌ̈S€Bÿíܱ#†óž"æé³g¯òx¼»wœ?Cö½+Jv¿t© !Äãaöp‡Ãò¿ë©ÌeTº…Çã±Ç…**üææ!ÎÎÖÚÚ­Žû£{÷Žt£‘‘ž‘‘Bˆyp¢9a³c`~¶°hÃ^"Å„Í A˜áÝ…Ç{a͘ŸŸçœ9ÓÃ_t IDATëvì8Æçó55Õ½½Ý™d[l²N>ŸÇŽc…OvŠÅ’æÜ¼yÏÏÏÓÓ³Kp°Eyy•¿ÿ2¹…™>ÚÙYtè`6lØÂçÏwï^,[R6f:\#„3zùû ŠÈ=Ç”–ý(*jâ³gÏ##S?ý´‡µµ©òÖå¶Òä‘’IóWÀTÈláóù²û*‰Î|Y/uæÿ-yžcÜ©“%ÆøöíûÖÖ¦66"ÑéÓ—¿þz-õêßsæ$ÅÄLñóëÇ\Âdj`v§ûZ[›2»³Ûe7ݹs{55•'Î3ë¶ /Óè…Ìû÷Ò‚’ÈÁ ªaa¾ß~»óæÍ{œ0nÝºÏ [¶×쪚ã25;8XñxøôéKÌ€¯ àb›6­õõ_x馦úgŸ Ø±ãØ®]ùþþÕÔ^˜éqZlNœÜ*й àÒ¯¿þ¹{÷’„„à  o§ÒÒ „¢¼2• ØmÉ’©ÙÙ'ÙK\”ÄìäÔ^UU…3spßÜ}$/J s>š0á“E‹,,ÚLº‚.äkŽWPSS¡¯”mNðÑSø®ÕáÃ{I¥ùŠ>533ò÷÷ŠŽN×ÓÓêÕË¡°ðÊÌ™ß㩪Êol”Lœ¸ÔÁÁjþüqµµ§„…­ÉÊŠ¦¯L9sæ²››½H$T´;ÓçßòÖ­µÂÃGGG§ëë븹ÙçæÒ…I![[3]]ÍóçoôîíÈÞEî`åùóÆššz¡POö¡Õ¯¾štñb™«kðìÙc êÞºµöµkå?nß~¬{÷ŽzzZZZM†­h &{-cܦM뀀A‘‘©:]ºØäæ&'çÄÇO—íE`àО=Cx<ÞêÕaœz8-6¿Î&cnÓ¦5Æxóæ\==-©Tºÿ©o¿Ýzòä©ò>BæÍwøð™ R†í)·$ûWà`ïèè4CC]ggëÜÜÂõëÿ]˜$•’û÷"„„B=öub%÷ž=k ‡XQyEy`Ÿ¢¦¦Â&ÛTÓÓç÷î¶zõ®¹sý8!É=ÓØoÁ‘R’(&ó.”º¸Ør®©Ã™/7Ÿ¯ëÌ€W×$À{¯…ßéFII‰07ÏŠŠJ»s§ÚÈH/(È{ñâ©¡¯¾ÚxéÒÍsçÒTTø††ºÉÉs}} ÔÃ×·Ï!®“&-G]¿¾UÑîì&8ÆÅM×ÕÕš7oCeeMv11“,HAñù¼Q£ú9òÛŒ#95ÈVòòŠ||¢KK·É.™T³³—îÜ™¿ysnBÂöúú t\]í¶oÿjäȾ<F5¶¢kފƬ6Ì11ɘ1㻪ªÚÌ’’§M*Û‹nÝl;u²ÔÐ88Xq’#[ssêlN̶¶fiióâã·¦¥44Ôõñq?u*ÉÙ9°°ðŠŽ’>bŒy<´qãü.]¦…†®ž:uH“ÙHHÖÖnººººÎÅÅvÁ‚ñ±±™j]ÝcSÓÑ¡ÒÒmVVÿ{¨¢ B˜C¬¨¼¢®®vÌ)úûï)ŽŽSšl×ÍÍ~öì1_}õý!nvvæì È=Ó8Ù#¥$Q´$!(/¯hÆŒ‘pæ¿Í3øèa‚"Çßu¯„råÊm—ÏKKhÛöõwØû ±Qle5.&fJ`àæ,Åù°B~ú鬃ƒóöž¤¤} $×ÕæñpVVÞäÉË++÷è°û¾o߯#G~ùº¾vPVfæQ¹í¾[yyEVô H„õë÷ÓDñù<„P~þcÇ.¾qc›¢/Mûà|Ügþ {ÂeQøO‘ÿ<Çclgg>q¢×êÕ;›ÿ ÃR[ûxÿþSaaß‚Æÿä£6aŒwï>1~|lQÑÕ›7ïegŸ\¶,+ `‡Ä+WnŠšÀ¸_¾|ëçŸÏÒ…ûo"'ÏŸ7Êm÷Ý"„ÐDýþ{ÉÍ›÷öíû•&ŠN! Û##'|†ÿÈ™|(>†û T]Ý7·àœœ8æ%Œ‡YY30ÐÙ´i!};þLJRW÷dþü䜜SÖ‹DBÿQQU„Г'ÏZµ°©TJÌÌÆ<~ü4:Úþüqo(*ÙvßµµeE>z´hÅŠmyy«èâC÷_8ó?`pŸþc>ž9€·æ ðó1\ø€½g÷´s€20g(s€20g(óŽç „‰Dšž~¨ººîMÔF©©©ïØÑÿÚµòW©Y,–¤§òð˜Õºõ0ÀËÜÜoÒ¤å.üÕâ8(ÀØ“ùOMí ‹±AA«jjê•ï{à@ׯ¬ìî[þ& 3mº9edûÈãõ¼,-ÇΙ“ôøñSNáÄ“›[èé9K,–´ ªª*+k™v !õõÿhj~ÊãõûûïÊì[>^Ñ;ž3`Œss §O_ùôéóW¨ÉÖ†1ŽˆØàëÛ§CQ‹«}þ¼qذ…‹¥ûøôþ嗵ׯoݼ9òñã§nnÁ'O^hYœô “+*öTTìùë¯6mZøã¿Mš´\Iؽåï À{yu»sg·™™‘¢eCb÷ñÎÝ%%™Ë—Oߺõ§/¾X…b*lA_0ÆŸ~ÚC[»UbâÞæŸ9LC</;û$ó+Æ8'§àÙ³Eø/S8g —cßô5WBSÿ«Ôdk+..ݾýØœ9~-î!dùò-¿ýVRP°~Μ1ŽŽíÌÍú÷ï²{÷b§… S[vœþ Ꚙ˜˜ˆDÂþý»DFNòç M^Ï&„„†®NNÎYµ*¤¤$30pèÔ©+rs !áá‰k×îY³fÆÕ«Y¡¡¾aakØ«G֮ݓœ<·¨(USS}âÄeR)É̌Ÿ=›VQ±‡–9~üü©SI‡Å[ZÄ?~>33ª´tÛ±c«1Æ#G~ÙØ(AÉð㿱k“H¤ÙÙ'û÷wÁ3=bWÎ^š"wá ÆøÂ…Òššú»ËæÁØX¿ukmšY³·mËKNž{ýúÖ¸¸Ïãã·.Y²™))ÛkNª !.üµbŶþý»èêjbŒeÓ¸n]6»õ©S‡Ü»÷ðÈ‘ßiïòóÿ¸}ûþ”)ƒ•´¨¼Î„„Ö¬™Q\ü½¹¹Ñ”)ñ11›RRæo‰„/ÄŒRr\NtÒ’ŸÿGll†—W7]]MN1¹1/\˜’”´/1qVIIÖ˜1ýbb6sê0 ëž='8G‡"wáSÌÃÃÉÀ@gß¾_iööï?Õ¥‹…E›fvpöìus玽z5+"bììÙë6l€i>f*²›´µ#„$)BÈÎ.€¹êës™„êêºÍ›LMðõ탚;ׯ¡ALªªªKNÎII‰1¢7B(4tÄõëåññÛÂÂ|é¾±±®®v¡qÕÕuzzZ!¡PרXŸ–‰Šò···@‚ú÷ïêááäìl255 ó;vqUU­šš `ĈÞ㈈±4vm/–=zô££{@åß©“¥l¯é:ÎFBHUU-BÈØXŸ¤Î™“”ž~ˆ)SR’¥¢ÂOM=—·ÊÓÓ!df&¬¨xðå—£¢üõšnwtœB«mlK¥ÄË«[jj!„I£;Æ8,Ì—“F„½½E¯^23 âŠÊÈøqàÀîffÂââr[Ä+¯3.nº‡‡Bè‹/¼Ç]¹2ÄÍÍ!4mÚ°Ï>[RYYÃJ‹Âã"›X¦¡gÏtu5‡ïõÍ7A²%ecT÷®[Nò¬Y£nÜ(OJÚGî;8´Û¸ñ°X,a/šÂË= ¬çð¨Q}÷îýeêÔÁ¡]»òýüúÉvÐÉ©=ÆX$r:í?yòÿ±wßqQïÀgî¨"Rº‚ ¢¨hÀŽ4¢±F,Xb‰¿%*FFD5ö+T{Cш±#±+Mîn~L²¿Ë5N4ràçýÊ+¯»½ÝÙ™gOg÷Ù½O !Çw¾~ý9s6ÞwA@e¥&g8wn !äàÁóÇÏMOÿŽOåù¯@)½xñ¦L& ô¦n11ý!ü*—³&MêË›5«›˜¸U˜%{z:ñvøiæ’©j¼¼œþÙ9²KZÚ‰õë¹}ûÁÍ›.^¼I‘ËåB„^ÅÄôcŒíÚuRhçÞ½'„‰ÄRq2çåå¤8í(¥üJ¯˜ç#ŠŽî?rdW!Dr¹<;û–L&ïÔ)JhV&“¿zUœ——¯}Ô»v%89ÙBŒŒ íí­LLŒx¨/^¼ÉÃ($*Jaäî1ïÙ³b±hË–#+VD ©îñúõ<ímúø¸ñäÊÌÌ„âááÈ׬RŘ¢øx"J‰¦ã¢C>F©TöË/碣SÛµkœ”ôoS‰jŸ¯^½S\,mÖÌWès‹~RÝc©mŠÅ"ÅžPªñV`-ÇE•0Foo·š5]:uŠzýºdóæ©ªkªö™'*Œ)÷Yqb±XضÔ#«¸B‹õll,ÒÒNH¥²À@GGkÝhhh ô /óÜúOMÎ@T2ÕIm:î”Ò3g®Õ®íÊ?ýüó)vvVS¦ ‰èÉ“—¼½]ù”îĉ‹ööVÖÖæjW}«¸ðĉKÇŽývêÔâÆkñ%Ó¦­"„0F„x{ó*&Ö³ç7vvV!!B#üÄóÇO•¦òotÁØØ02²Û÷ßoêÝ»µ»»ƒb#·o?ä¯ygîÜyÀ[^µjÿÞ½™+VDk¦ÚåŒ1__Æj´˜j !ff&}ú´Ý¸ñ€¡¡Ahh;#£M¥–uiS)IÐÔg-ÇEûÛµk4mÚà˜˜%K—î2¤c©Ñðó«ahh ØçÌÌËŠk2Æîßbdd t5IÅ åIÅÅ%Š…IŠüøãÚ|«øøÕŠg „|öYS¹ü ¦OmBCƒ££Smm-¼½]wì8¾}û±]»ìí­ÂÂÚGG§ÚØTkÐÀ+==399-!a¨â¶JSþ° S§.óêyÅuìí­(¥+V¤[ZV•Ëå;vÿþû„—/ÿª]ÛUm „ÖjÕr±°0;þ†ð MNí4ýõë’gÏŠ$K¥Æ”Ò)S\¼x3 `ÄW_õlß¾±••ùõëy+Wîݰá@ãÆµ--«V­j»ÔÒ²jÓ¦¾™™WFþ¡gÏ CC±â.ÔFRmJ¦KùVáá›4)‰æÍ‹TjGiº·YjŸµícdŒMœøÅž=§&MJ騱‰Ú5ßÚØT1¢slì[[‹úõ=ÓÓ3-ú»0I¸ÎpáB®¿-ÕÓü¯^óªxýDi€¼JƒøMöª©À‡i,F€2 ¦@ÏiüèJ€RêííÚ¿ð¼y›4•ÙTPŒ±‚‚;vŒü1Ò·ï'•/a „PJ7o>Ü·o|VÖµ[·lÛvtúôÕaaíE"^—DgÏÞÝïý$ ¤¼‡ ¼TæœB)3gä®]'oܸ[™&y”R™L:}ÿþ3k×NVûèÒJ€16kÖ0//çÏ>‹®Y³ÿøñ‹¾ü²“pçÆ¾}g^½*=ºÇ{;²ÚK¿Ê¨MQ ²ªÌµIðŸ@mÀ¦’_g€·„œ´AÎÚ gm3”+<‹ô^s™L¾téîÇ K}Ìe~~Á˜1‰Õ«÷16¶±éܮ݄ôôLÆcLhDu«;OˆD­oÞ¼_æÇh>{VT»vèõëyŒ±ôôÌ  1R©ìZcŒ©í<ÿTScBçËÖs½R–œÏ‡ó×_¯µ?¥¾¤DúÉ'ãÏ»¾bEtnîºC‡æûúztê½yóaBˆÐˆê´;8¸ÑÝ»›]\ìÊö|ÆØ„ ‹»ukáååD)íÐ!ÀܼJbâVÝ[cŒI¥2µÿé§CZ"@):_™~>Xs~²ü?©N|)¥ÂB-ÓbÆØñãûí÷… ǶlYÏÙYR·nõï¿hÚ´ÎÂ…Û·Uv›˜9:ÚˆË0$ÆØ… ¿oØp`ܸ^¼eÆXllh|üªgÏŠtl„R*t¾E‹º¼ósçŽTí¼j„Îãg¿ PŸ3hÿ½[ÆX—.±Œ1W×^bq~JþÛoW»»÷66ööKMÝÅ747¯BÙ¸ñ@q±TØüèÑÄÇ ”vîá4ˆ§(“'/µ´ìhmýYbâV^ÞׯY“Q¿~¸‰I°Ÿ_øÁƒ¿ ¥MqqË?71 nÞñÿñÇINN¶Šð–cbB}|Ü!»vTìR||x@€7!däÈ®aa3?.466LLܺpáØ®]›SJÇŒéqãF^RÒvBÈ•+·Ÿ?ÿ³n]¥ÌÇ×·ú²e{JJ¤††ÿ5/%R¥45u‚Ðy~Fpp#-¯SDzsç ¥Îú¨í|·n-!£Gw: oÔ\g8wnɹsKæÏEIOÿŽ¿ÕR­tñâM¹œ5iRG8߬YÝû÷ŸÏjÛ¶aròø7Öýþûú„„a'O^úâ‹©j{ÃoYV­†òôü{¹……!¤¤Dš[\,mÖÌW¸c¡E ?¾ò½{O!‰¥RŸ%‹’é£GºßšÌ¯N$'ÏÉY{óæ†Y³†kïk*—Tû Œ1SScBÈ©S—óòòíí­ÂÂÚGG§îØqüöí‡ÉÉiÉÉi_݇ÕÏÂÂ,(hìºu¿äæÞËÉÉ[¼xÇ”)Ë&O322PlD±q]¦Ý66ÕFŒè»„ï4%eç¢EÛ !”ÒZµ\,,ÌΟ¿¡”ù\¸ëï_K,V¾þðêUñýûOø¹ÅåBçׯ?À;Ÿœœ¦½ó:&ÑOJÚ>iRraᑈ^¹rÇßÿËÜÜõŽŽzð௽{O½qc¹¹©>œÎÏÈÈòõõàÏkbŒ-Z´ƒw^,.Ë/s¼W4ˆà.,€wˆRü™=WQg¨”ÒÍ›÷ퟕuíÖ­Û¶>}uXX{~ñ[ÿþÁóæm®3Ìž½!:ºŸž$ Œ1Þù3g®Þºõ`ûöc¼óH@Uàë ……/¿þ:9-íøÓ§EÎÎ’ÐÐv11ýyycìùó?G¤¥ÍðôtÚ¿?kÖ¬usõgR^PðBµóFFúÒ”×Þ-\g½WQs(7ÈÞ-ä  ÷ôå¼;è'ä   r€r…Â$Ð{È@ä  Ms™L¾téîÇ 5ýò± ?¿`̘ÄêÕûÛØtn×nBzz&cŒ1&4¢ºÕÎ'D¢Ö7oÞ/µ}Mž=+ª];ôúõ¼2·À1ÆÔª)Œ1aeØczz&¥A”µn=ÖܼÍ£‘žž4F*•½Ñ¸Þÿ( Ò(KÎÀg®C‡Îùë¯×ÚO ¤DúÉ'ãÏ»¾bEtnîºC‡æûúztê½yóaBˆÐˆêT58¸ÑÝ»›]\ìÊö{Œ± wëÖÂËËém~ñ€1&•ÊÔá§Ÿi‰¥T›&-¼)Jivö›7O»qcݪU1ÂÂÌÍ«$&nÕ}\å2 ¨44æ üóaÚ­݇ “Écš† ØÕcA)mÛ¶á–-‡u,%*÷Q@…¦&g07ï`nÞ¡wï©„oï°jÕBÌÍ;(®ÀãÕ2‰…ƒƒu~~arrÚÌ™C»vmîîîÑuĈ. ëø”tÉ’‰s{ölõë¯9cÇ&z{‡µk7ŸJWl„·êããè£Ô¥øøð€ï:uÜGŽìzÿþ“Ç _&&nv:fL¡C;ñ•¯\¹ýüùŸuëzð w` ÛÚµ<…X½z_HH€ƒƒµÒ„[S¥45u‚0„1cÔ®Ú¾ýļ¼|¥8C¨SǽI“:ªC ôñõõPB·n-ÜÝFî. A1Ôª×|c¾¾ÕÏË))‘*­¯Ÿ£€ MMÎpîÜ’sç–ÌŸ?Š’žþ«¥ZéâÅ›r9kÒ¤ŽpÞºY³º|BÉ—´mÛ09yüë~ÿ}}B°“'/}ñÅTµ½á·,«VCyzþ½ÜÂÂŒRR"ÍÎÎ-.–6kæ+L£[´ðã+ß»÷„"‘X ý8°Ãúõ¿ÈdòüüÂôôÓvx£ê|~^?9y|NÎÚ›77Ìš5\û”&úÂørÕ!ý† ¸kµ×$‹’é£Gºßš\Ž£€ Í@u‘——3cìêÕ;„ww;¥”¦’r¹œ¿¦ï|‘H4kÖúׯK¾ùf_ÁÝÝaâÄÞ&&FcÇ&¼PÓ±ÚI°HD—ó;(!ŒÆŸX+ÝQ-‰„þ„†¶‹]ºÖõëX[›wìÈ·*5:Œ1>„)SÂø^Üݾþú íCPÛ²H¤<û† 7¥(¾Ö‹Åªmêí( B+ãý Š+øúzˆDôäÉK™æ'.ÚÛ[Y[›ß¾ý`Μ ÷ï?Qj¹Jã*ULÔÎJÕ^gP]îçWÃÐÐàäÉKÂT53ó2ÿÈÉÉ–òðáS¡?vv–:5Ù¸ñÀúõ¿„…µ×ý)@”R>„ž*=\HË4Í›•– Cú) AÓ¨…5ïßbdd \KÑóQ@…¦ñY«Ÿ}ÖT.?¨öc¦¦Æ„S§.çååÛÛ[……µŽNݱãøíÛ““Ó’“Ó¾þº!$*ªŸ……YPÐØuë~Éͽ—““·xñŽ)S–Mžfdd ØˆbãºLUmlªÑ96v ßiJÊÎE‹¶B(¥µj¹XX˜?Cè9¥tàÀO·m;š•umàÀOÕŽèÕ«âû÷Ÿð³æŠË…!¬_€!99MûtL{„!¤¥àq† iÔB‚táB®¿-±X¤´²~Ž*45µI¥¢”x‡„ 0“’“³vñâqŽŽ+Gú!?¿ fM—¤¤±áá!”R77ûÓ§SfÍZ·L©5aŒñ!œ9sõÖ­Û·†ÀWÈÏ/|ú´èÑ£á6e^ª4{ö†èè~z’0h€J£_g(,|ùõ×ÉiiÇŸ>-rv–„†¶‹‰éÏKbcÏŸÿ8"-m†——sywV£‚‚ªC022Ø»÷tÇŽQ„V­ü²²®½|ùŠÂ+ŽöïÏš5k]FÆ\ý™”k…>¤4ðŸÀu€w ×@ïUÔœÊ r€w 9è=}9W ú 9hƒœ´AÎÚ gmÊ-g`ŒíÜyB$jýÇø’gÏŠj×½~=OÓ/¿iûR©léÒÝ­Z±²êdlìêÚkÀ€™.ü^æöy‡) ¢4H$jmdô‰›[ïáÃç>{V¤¥Ma¤7oÞ/ëhÊNص–*®“žž4F*••!Jš^¶žó¸ñhóÿ®}[]Fý_ÐåX—ï÷  Ê-gP|x?ÿ©² wëÖÂËËéíŸëÏ+.–vê5yòÒ.]š9² 'gíŠÑ/^ü8âØ±ßÊ0•6ÉÌL¾woËÝ»›ÿ}ýòåQ{÷ž0`¦–>+´ Ã)3ÆXpp£»w7»¸Øiê¡b—(¥:˜›WILÜú¦GáõëM?zôB:Ï;@)å¿wo‹bÀµ'iJ¼7”R!àšzˆŸ­exÐ*è=MìÜy¢K—ØÛ·7:;Kþ‹YŽÒŒêÂ…ß7l8pëÖ†w²/JéÌ™kNŸ¾š••êááÀÛtuµkÓ¦A‡_GE¥?¾° mò‰…ƒƒ5ëädÝäÈyÏŸÿY­Zµ–ïÖÄÄÈÑÑFû:ÂkÞÕØØÐI~jee®ãŽcBÀ«Wwä ]]íZ·®2)**õرÄ7»7‰ÄB‚³³„¼¨è/M¿„­4¢÷óRþžóF€·§þ:ƒ.Ó\™L·ÜÙùs“àæÍ#gÎ\Ë ø9þ¸¸åÕ«÷16öö[¹r¿’PR"‰YâèØÝÔ´]»v®^½#´6þO:|,‘X’~ãyìØÄ5ú››whÙrôáÃÙª}ÐT‚R\,MLÜÑUH„q-_µk×LÞ©T6mÚ*/Œƒ½¼úÍ»I.gBéÈš5õ뇛˜ûù…<ø«Ú˜PJMMÉ?—J¤RÙ·ß®vwïÍžšºK)€ãÇ/úè£R©Œ¿•ËYõê}¦N]©v|µm c_¹r_ƒCLL‚kÔè»uëÑÝ»OÕ«7˜¯¹–bŒ¦¨*‹Rà-‘X.[¶G)ªšŠjc%%2p!aäçAx£€+íBx!\mpø6œ0a18_®=àš"_þ®®ú5Ðsês†RËicQQ)IIÛÇ\½ººgÏÖqq+„O#"æ%'§Í;òêÕUáážµwïiBȘ1‰?þ¸'%e•+«:vl2yò2¾¾L&ß¶íh›6þ|_”Ò°°‡_µ*&7wÝó(¥Ý»ÿ¯¸XªÔµ…7Œ± rŸ=+j×®±RÂC)up°¶²2ç“ã1c×­ËHNŸ“³vÆŒ/ÖN›öÿ£X°`Kròø¬¬T33“þý§ËåLqüEvvî¬YëÚ´iÀ/2Œ›¸`Á–ùóG]»¶:"¢[däüÄÄ­Š<8äÁƒ§ûöáÓЃ½sçá AÔîQ&“3Æ´·9{öúùóGegÿèêj7hPB\Üò””ñÙÙËœ%aaÿê3!DmTKJdJ㢔¶mÛp˖êÑS[xC)®úmáç—9à¼'Œ± ~ç·°0£”ªgáÂmŠ{θö€ó=joóÝ BPS›dnÞ"“É !ÞÞa|ºVT”.¬ÀO &&n]¸pl·n-!£Gw¿q#/)i;!äñãÂ+ö¦¦NèÚµ9¥t„ÞÅÅRÆÈÓ§EK—îNIÿÙgM(¥cÇ~~ãFÞ¢E;!W®Ü~þüϺu=ø¾ärÖ¦MÃV­üüüjPJ%‘‘Ýz÷žšŸ_ðÑG6ŠçøÕÖPJóó !ÖBiÊW_-\ºt·°ÎÕ«« Ä©©;32æ¶jåG)uuµ»wïÉÿþ·,&&”¯èC9²kXØŒÇ ùòºuñ6KJ¤r9 n”š:’Ÿ_˜œœ–’2¡k׿„ˆˆ®99y ë"#» ûõñqkڴΪUû:v $„¬\¹·]»Æ..’ììj÷H)ÕÞæŒC[¶¬G6¬sß¾ñsæŒlÒ¤!dÈN}úL{ôè™ÂQ#š¢ª:~|}}«/[¶§¤Djhø¯oˆÚ€3Æ„€ -Œ—¤)àAAõ !..Õ€xëpƘð.]šQJ##»i xHH€Ú€+íQ¸¦6gÌÚª•ŸbÀù!Óðúõ= !NN¶ª¨Ôä çÎ-!„>n|ïff&„GÞB•*Æ„¡ŠB)ÑUÅÐñ½H$%%ÒGþ•¤iB).´P¶€ó´ÜÄĈwU¸â7JSÀŸ={¡6àJ{®©M7a!à|Ͳ BP“3xy93ÆøÍîî..vJ+ðšoBcÿfZ(Já(ˆJšñÏšÿ?1ÎaóD"‘p:¹mÛq·n=èÕ+((¨Áˆnyyù¡¡Ó•ÚÔ„RZ¿¾§¹y•~mԨߗ¥¥0.òÏÔmãÆ¸š57wv–\ºt“"Qµ5ZnnöÿªÚçŸ sA¥˜ˆDÿ*ëÕ+hܸ…7‹Åff&;7>RÝc©mŠÅ¢— i¼ÿD*•iŠªbèø^Äb±j4aŒ oܸ6_ÈNy£€+ŽE1àîîJ=¡” Á¾Qe¸ÒKmS,)ö„R÷4ëpBþþ礼; úç&)Í\U§k~~5 Nž¼äííʧV™™—ù§uê¸SJÏœ¹æííÆ7ïÙó;;«o¿bddpøðyŸ¿— ›ð³È>õòr"„œ8q騱ßNZüñǵùšññ«‰BŠR*£ÈÈnß¿©wïÖnnöŠ©ËíÛûyçÎC^&Ä[½:cïÞÌ+¢Ç®¶}µ1ñõõ‰¨bLNœ¸hooemm®¸ZÕª¦}ú´Ý¸ñ€¡¡Ahh;ccC¥–ßêØ¦–Z¢ª4.JéýûOŒŒ „+?jT쀱±¡pwwÅUÀÛ\µj¿RÀ5íKu9cLŽðR !ÄÌÌD1àFFÿúÎ+µ¬K›JÖÔg!à×âëL›¶ŠàyzPi|ÖêgŸ5•ËjúÔÖÖbĈα±Klm-ê×÷LOÏ\´h;ùç&ãÐÐàèèT[[ oo×;Žoß~l×®+«ªcÇ~»ÔÚºZ` Ozz&/L"„Ôªåbaavþü-êBìí­(¥+V¤[ZV•Ëå;vÿþû„—/ÿRšÂ¾zUüìY‘Db©tö—16eÊ€‹oŒøê«žíÛ7¶²2¿~=oåʽ6hܸ¶¥eÕªUMCCƒcc—ZZVmÚÔ73óÊèÑ?ôìdh(ÚÑ} Kqp° kjcS­A¯ôôÌää´„„¡ŠëðéfxxÇ&MFŠD¢yó"µO@íí­tl³Ô>k‰ªÒ¶ü&rÿZªQ}ýº„ÜÀ@¬Ø8¥ôü’4]‚÷R ¸öK÷6Kí³.¨4æ Ú1ÆfÏan^%"bÞãÇ…þþµ&M꿊Ÿ5ON?uêŠaÃæ<|ø¬fMç5k&úéÇ„3†ZXT8qñ£GÏ>þØ;.nà¤I)„±XÔ£GË}ûNGFv£”Ö®íºdÉÄ„„µK–ì²µµèÒ¥ÙñãIõë‡gf^á×.„>dddué››»N©XˆRjdd°mÛ·›6\±"}öì EEÚØT ðÞ°aJ÷î-Åb!$%e‚«ëꘘ%wï>¶³³>¼óÔ©ƒ•†©iøjÏ|/^<ÎÑqå¨Q?äçԬ钔46<S—/ßö÷ÿ27w½££µŽH¿ÄÃ㋸¸AJ“Q=qð௽{O½qc¦M«pJJ¤<àáá!•cD匡Ìà]Âý  ÷Ê2¿'„0Æ6o>Ü·oü™3WoÝz°}û±éÓW‡…µ/[Â@ññqëß?xÞ¼M•{JWPð"-íDd䌑¾}?ÑtM 1ÆfÏÞݯ$ Œ±‚‚;v^ÑGP.Ê~¡ àÅ×_'§¥ú´ÈÙYÚ.&¦¿‘‘AÙ¦eŒ±çÏÿ ‘–6ÃË˹ô * ÆØÓ§E_ØØT[¾<Šÿ.Dywê_cû÷gÍšµ.#cn™Ó?½òäÉs!àüw!àÀu€w ×@ï•=g€r€w 9è½Êp.þ;È@ä   rÐ9h£G9ÃÎ'D¢Öüñˆ1Æ_ß¼y_?ÁàÙ³¢ÚµC¯_Ïû/Ú—JeK—înÕjŒ•U'cã`W×^̼pá÷²µÆƒIiðŸ‘Ñ'nn½‡ŸûìY‘ömËë((~tY‡1–žž4F*••a_š^æQóŽñh‹D­®¥M]FýßÑåX—c÷ |éKΠi¦¢o¿`@¡”N˜°¸[·5k¾ûß‘xýº¤S§¨É“—véÒüÈ‘99kW¬ˆ~ñâ¯ÀÀG^([oùÿ33“ïÝÛrïÞ–ß_¿|yÔÞ½§ ˜©} «ÔÈ{C) nt÷îf;¿Ÿ~ú±¹y•ÄÄ­o4ÑgŒK5üرßÊ6›ð€ß½»Y1àZ"©øÑûOÒ„€kê¡fïðÞhú`çÎ]ºÄÞ¾½ÑÙYò¦ŒZf*ú–6dgçnØpàÖ­ ï¼oŒ±™3ל>}5++µzuG¾ÐÕÕ®uëú!!“¢¢RK|Ó= S=‰ÄÂÑц¿vv–DG÷9r^QÑ_š~ïYi ûž‚‰‰‘Ð[µTSšØØÐI~jiYUÇÞRJ…€{x8ð­\]íÚ´iСÃ×QQ©Ç/|Óž »–H,¬ù[''[ðçÏÿ¬V­ŠŽ#zo(¥¥\ßþÀû¤þ:ƒöé‹PD±rå¾ †˜˜רÑwëÖ£»wŸªWo°±q°·wØþýYŒ1^øñí·«ÝÝ{óå©©»„ÆKJ¤11K»›š¶ õêµáûZ³&£~ýp“`?¿ðƒeŒ :Ç×w ÐÚë×%¶¶gÍZÏw:mÚ*/Œƒ½¼úÍ»I.gB·'O^jiÙÑÚú³›7ï¯Y“áë;ÐÈè‡nááß¼à­ij16þO:|lkk!ô­Ô8¨žRc¬¤D–˜¸-"¢«0‡`ùò¨]»þ>K­}tJR{Xc¦¦ÆÂµÇH±Û&,þè£R©Œ/—ËYõê}¦N]©éÐh:îºsKe _Ž›X£F_cã`só-[Ž>|8[u\>‰å²e{T¿±š oŠ‹¥<àB 4È.ŒE÷€«ý³C)®68äßÐÆ_ÄÎßj¸ðUmS÷¯h©Çu€™úœA{™„ðéìÙëçÏ•ý£««Ý A qqËSRÆgg/sv–„…M—Ë!dìØÄ ¶ÌŸ?êÚµÕÝ"#ç/\¸ÏœÆŒIüñÇ=))®\YÕ±c“É“—iéè‚[’“Çge¥š™™ôï?].gƒu¸|ùö¹s9¼µ]»N>þgXX;BȘ1‰ëÖe$'ÏÉY;cÆ— k§M[!4uèÐùãÇ“vïN()‘ 8³gÏ œœµ›7Oûùç³ÑÑ©BßÔ¶ “É·m;Ú¦?¥T÷8(Í#ÕÞPJ/\È}ö¬¨]»Æª1wp°¶²2ç‡CûèT¥tàc.ü>kÖº6mXX˜QJÕ#ŽòàÁÓ}ûÎðQ<øë; ê eÚÛÔå›# ›qèÐùU«brs×80RÚ½ûÿJJþÿÖa\mÛ6ܲå°j’¦¶ð†1&\)Í ”ò€óñ–9àBO²³syÀùEÕà(UU çßFí—ÉäŒ1ím¾Û€À‡FMm’¹yBˆL&'„x{‡ñéTQQº°‚0™1ch«V~„aÃ:÷í?gÎÈÀ@BÈ!úô™öèÑ3±Xœœœ–’2¡K—f”ÒÈÈn99y ë"#»=}Z´téî””ñ;7%„ŒÓãÆ¼E‹vhêh||8o|äÈ®aa3?. ôññq[»6Ãß¿&!dõê}!!Ö¤¦îÌȘTŸââ"¹wïÉÿþ·,&&”7êããF9vì7¹œ}ô‘­³³ÄÕÕ.-m¬–®]»óüùŸuëz(ÎðJƒRÕ‡Ú:ÆX~~!D(haŒ—´téna«WWˆµ.>>< À[1P|yݺƒx³%%R¹œ7JMÀËÏ/ÔtŒ„ýúø¸5mZgÕª}!!„•+÷¶kרÅE’}Cí)¥ÚÛ,5b a!mÚ4lÕʯ~}OBˆ““mdd·Þ½§òX ¡ã“{_ßêË–í‘JebÅsüjN)._}õÕBMoÕÊRêêj§p¥o¦–€B„€wíÚœÑUKÀ;v Tp¥= ×ÔæŒC[¶¬§ð&Mêh¸Ÿ_ J©³³D5àðŽáZ.è=59ùsK!ž>|nzúwÖäßí 7>u633!„xx8òªT1&„H¥²+WîÈå¬I“:Â$¸Y³º‰‰[?.¼xñ¦T* ô&|ÍšÕÕ’3xz:ñ}YX˜BJJ¤„;Ì»ñ»ï†?}Z”ž~zãÆo!ÙÙ¹2™¼S§(¡Ÿ2™üÕ«â¼¼|þÖËˉÔ´©ï矷6lnlìÒO>ñïܹY-µ·pïÞBˆDb©xfºÔ8èr?¥”_I((x!Ä$:ºÿÈ‘]…Ã!—˳³oi§çߣS !d×®''[Bˆ‘‘¡½½•‰‰?"/ÞÔtŒ»7xpLjˆyÏž½‹E[¶Y±"JñÐ(íñúõ<ím–1…°‘#»¤¥X¿þ—Û·ܼùàâÅ›„¹\®:¾‰Ä¢¤DúèQ©vŒ1!àB e ¸ê7S5àÆÆ†¼!àŠß|Mú´HmÀ•ö(\S›>>n|ïBÀy e 8|hÔä ^^ÎŒ1~w»»ƒ‹‹Ò Â)v±X¤8¦T¹I˜gS¾‚H$úg–öÿ>CC7dBD"ª¸/ÞNhh»ØØ¥û÷g]¿þ‡µµ9?)ËwºqcœÒsœ%—.Ý$„ˆyÄbÑÆß\¹rgÏžS¿ür6,lÆ?îÙ·o¶–nܸËû¯8ÒRã Ëý£Œ±úõ=ÍÍ«8ðkãÆµùB;;K;;KBˆp³G©£‰¨âÞ…×nnöîîJ=¡”j9FŠköê4n܈Åb33“Λ ©î±Ô6K˜@*•µm;îÖ­½z51Â-//?4tºRèø^Äb±Ð]’4!àÕâ-ð€ ߢ[ÀÕÖò¹¹Ù{xüë¾¥àßü2\i¥¶)ÿëK©Æï¤.€Í[ÝÏ@f'ÂGŠŸúúzˆDôäÉKÂTæÄ‰‹ööVÖÖæõêÕ0228|ø<ßœRš™yY{_U÷eoo#úÈ IDATÕ©S“¬_ÿKXX{CCJi:î”Ò;wzz:yy9{y9Ÿ}Z¤¥~æøáçJ#Õ]FFvûþûM·n=PøíÛùkG§vF¨º1¦å)®iffÒ§OÛüôÓÁÐÐvFFÿJðt?Ö1Á‰—Žûmóæi³g>¼s«V~¹¹÷È¿¯â {¹ÿ‰‘‘ÒU -LLŒxÀoß~¨ÔÕ€óh{z:©\i,ŠË•–PJ…àß|ÕàPJ«V5U ¸p™BíulSK !àsæŒ>¼sË–õT§ö?û¬©\~PíGJ³+MBìí­ÂÂÚGG§ÚØTkÐÀ+==399-!a(¥ÔÚÚ|ìØÏcc—Z[W ôIOÏÔR˜¤e_~گ߷/_¾Z±"ŠŸ]vq± Ž]jiYµiSßÌÌ+£Gÿгg¡¡XiÛªUM—.Ý-—³qãz•”Hwì8V»¶«••¹µµ¹¦jÕr±°0;þFóæuKí›ÚOc¯_—<{V$‘Xˆ•V›2eÀÅ‹7F|õUÏöí™_¿ž·råÞ 4n\ÛÒ²jÕª¦:ŽN•êÙwžw©=FªýïØ¤ÉH‘H4o^dÙŽ»îSlŠRºbEº¥eU¹\¾cÇñï¿ßHyùò/¥qQJ/\Èõ÷¯¥UBÈ«WÅ<àJ×7cï$àšRµË¬K †bÀµ_¹Ò%à:^ûÒ%àð¡ÑV¤‰–3誑ŋÇ9:®5ê‡üü‚š5]’’ÆÒ‘o8cÆP ‹ª'.~ôèÙÇ{ÇÅ œ4)EË~Õî«C‡€jÕªÔ«W½vmWá|sJÊW×Õ11KîÞ}lgg9|xç©S«nÛ çš5“gÌXãç^¥Šq›6 wíJà#PÛ¥ÔÀ@Ü£GË}ûNÕ½Ô¾)~*,¡”fddué››»NµXÈØØpÛ¶o7m:¸bEúìÙŠŠþ´±©à½aÔîÝ[ŠDTSß´-Ë)¥šŽ‘Rÿ5ªU§Ž»©©±¯¯Ñš:ÍÇ]Lj jÕrY²dbBÂÚ%KvÙÚZtéÒìøñ¤úõÃ33¯ØØTSÜV.gY£FuWJcBÀ•Š…(¥FFZ.‹ˆ×=Iã Uƒ¢ ÿš<àüZ‡ö=êØf©}Ö%à𡡌•w7* ÆØ•+wüý¿ÌÍ]ÿÑGÚ~«ò))‘zx|7(<$¸ÎoK\g€Š—ô2€J ×à­á K•rxGP°PI¡6 *”'T È* \g€ÿ –t„3b ÷3@…‚ß„¨pP°Pñ!g€÷? Pa!g€÷Kr¨hPžP  `  BAÎåKr¨€p© ’AÁ€~CÎúKú 9è,èä P1¡<  ÒCÁ€Þ@Îz Kz9T(X(?È ÂByÀKå9T4(Xx¿DåÝ€·À/5À‹±¿ÿÀ_ÿ%\g€ Kÿ1ä P) ` à?ƒÚ$¨àPžJP°ð®á:TFx6+T zòýÿ¿Cÿ, Â,áK(Ó“¯)ÀÛÀCWÞ¥ÿ?GPDƒP›Ú gÍCΕî„xK(LÍ3€6È ²À¥€ÿ¥È@á ›*3€6È AyÀ»Ã{õªxΜ ~ijÚÎܼC‹£¶n=úNZ–ÉäK—î~ü¸ðí[ãvîå§8Ö¥5aýÌÌd ýêUñ©S—ÇŽ]øðá³5kbƒƒݽ»Y"±,C…öYàé餸‘‘‘¡âÛ·»v……/5Äñã{é¾wä  ŒR:iRòӧϳ²R«U«Â'—3f|Y\,}M}##ç7mêKyñâ/~…„¯)DBHÓ¦¾‘‘ókÔè;sæ:¥bxn¢üܤ ~ýº¤I“:JS^‰Ä²iÓ:FFJSí1c×­ËHNŸ“³vÆŒ/ÖN›¶‚RÚ¹sÓáÃ;Oœ¸ø?ò¹ðí·«øat:î«VÅPJÏž]rïÞBˆÚÍ…ö,Ø’œ<>++ÕÌ̤ÿé2™œïñÇ÷¤¤L¸reUÇŽM&O^ÆWÎɹ;pàÌž=ƒrrÖnÞ<íçŸÏFG§*B©óü…T*;tè||üÊààFŠ“l-}ˆŠJIJÚž˜8æêÕÕ={¶Ž‹[AT¨Þ9 ÔícŸ={ýüù£²³tuµ4(!.nyJÊøììeÎÎ’°°é<»8þÆ—_Îvsë½}ûѸ¸Awîlš5k¥T8ˆJ9ŒâALHzçΦ¸¸AÛ¶quí5dÈwçÏßPj“ Òá—þû;Š*±Â—„+«ª¥Ï0Æ=*HMÝ™‘17(¨>!ÄÅErïÞ“ÿýoYLL¨¡¡xΜ‘‡2ä»ë×ÿèÓ§mxx!ÄÒ²*ù§4HؼU+?J©««°9ßE||x` !däÈ®aa3?.40/]º;%e|çÎM !cÆô¸q#oÑ¢„‡ŸÊåì£l%®®vii3(¥J£æÐuë–¿zUlaaöÙgM¿ûn¸ê0Uû`ll˜˜¸uá±ݺµ „ŒÝýƼ¤¤íŠ[5n=vì·fþøcº\~Pi5ä  ÌÖÖ‚òäÉs//gíkRJ³³se2y§NQÂÜT&“¿zUœ——ïáá`jj´fÍä?öÑG¶‹}¥zÞ]Ëæü­§§ߊŸþ/)‘^¾|K*•úðd€RÚ¬Y]ž34mêûùç­† ›»ô“Oü;wnÖ£GKM×víJpr²•Je¿ür.::µ]»ÆII_™š©SµW¯Þ).–6kæ+ô¡E ?¥œaË–øêÕ—88X¿ÑØ}|Üø~ÍÌL!Ž|Í*UŒ !R©Œ2eJXJÊÎþý¿6¬ó!mm-x„ƒèéYJâ—Ÿ_°téîää´ââ’)S”?Æs“€åç&Õ­ëQ¥ŠñÉ“—¼§›÷î=é×/~êÔÁ-ZÔåËcr¹œ²qc\ÍšÿJ0œ%|³g¯‰D¢û÷Ÿœ?£E‹zJ{Ö²ù¥K7 !"U{—3cD胡áßÓZ±X´iSÜåË·÷ì9õË/gÃÂfüøãž}ûf«½ÎàæfïááH©]ÛµfM—N¢^¿.Ù²ešjxTûÀçëŠ}PM‡\]íT“.ÅÕJ»X,RÜ/¥ÊÅN”Ò¸¸AQQý6l8˜¸5>~UŸ>m#"º5hà)D~iBØûýûO…ƒxî\NRÒ¶ x{»M:¨OŸ¶FFjÜÏ•î„x;¦¦Æ¡¡í-Ú^Tô—â¶ß¿ñøñ‹NN¶Š7FשãN)½sç¡§§“——³——óÉ“—¿ùf9ßäÚµ?ÆKŠ‹Ô«Wë°°üŽdÅy°°9ßÖÓÓIØ\ 4#¯W¯†‘‘ÁáÃçùBJifæeþÑ‘#†Ÿëéé4aBïôôï,ýóÏgŸ>-Òrß3_ì?mÚàmÛŽò;¶Uc¢Ô?¿††'O^RíƒÒVJKÞrìü‚Rû&&F~zöljzúw……/†ó…ü >þ§âæÂA$„ŽxþüåÞ½³³²RüÔØØPí \geŒ±o¿rèÐù–-GM™2°Q£ZOŸ>ÿñÇ= n›5kX)®ìâb»ÔÒ²jÓ¦¾™™WFþ¡gÏ CCqI‰¬ÿo}}=¾þú‹‚‚u늌œ¿zu¬©©1!äÔ©Ë>ÎÎM› »PšÈZYU;öóØØ¥ÖÖÕ}ÒÓ3ya!¤jUÓ¥KwËålܸ^%%Ò;ŽÕ®íjee®ö:ƒb˔҉¿Ø³çÔ¤I);6Q‰RllªÑ96v‰­­Eýúžé陋mWZíñãž*µÃXÄ•aìª×ß¶jåײe½Û·òåZ"/šÊÉYëîî :X¥‘#g€J wB¼¤XžD)µ¶6?~}ˆ¥eUBˆžŒÞ¡BIH!>Ì%4è_¥ Âc?Ô%ÈàÀÿÌã¡« ÆØ´i«ââ–B4ð²··ºpá÷Ý»OíÝ{zÆozôhY¶f)ýûåAAõ-,Ì _ž8qiåÊ}Ïžmß>]Çmy÷ÊñÙí”Ò.]šB¬¬ÌµôDé#þºU+?ž!üõ×ëãÇ/&'§ýñÇ£;gBti*Õ« ô•ÉǺ¿Ïä ÿJq9ôÍ/¿œ oll¸mÛ·íÛ7&„Kœ¹qãA»›77ˆDe™Ôªž¡OK;ѵk,!äÞ½-Öo´­þS½ÎÀ_ó”àĉKÍ›GBòò6ô‘M¹öà?À¯3À?p?|p'4À‡dÁ‚-„Ñ£{´oߘRÊki,½gϬӧ“yÂpôè…Ö­Çš™}jaÑ1$dÒÙ³×ù¶Œ1‘¨µHÔzݺ_Z´ejÚÎÇgÀÎ'È?× ø¹6þ¢]»FüÅÃ‡Ïø‹ììÜN¢ªU ©R¥}óæ‘{öd µL¶]ºÄŠD­¿új!ßcI‰Ôή«HÔúçŸÏjÙ;ß©¦ö !”Q´víÏ-[Ž65mW¯Þà_ÍIHX÷ÑG=ÌÌ>íÒ%6?¿@qÍ3g®2Æd2ùÔ©+kÔèkhØÖÌìÓ?¾wïiÞUº6ùû5ÿ?c¬~}O¾ÚãÇ…Œ1Å6ùk¥!ý\¹r_­Z¡¦¦íZ¶½~ý/|¼ÿíÞr¨lNœ¸HiÓ¦¡â”W"±üôÓíí­!GŽ\øä“ñGŽ\hÐÀ³~}ÏýûÏ´j5ú·ß~' “û‘#¿‰D¶¶W¯Þé×ïÛ—/_)N£ù‹ýû³(¥b±ÈÉÉ–’Û´iÄž=™Õ«;6n\ûĉKŸ}½~ý¥)xxxGBÈÆe29cì—_Î=~\èæfߦMCòO6¢vﺴ?|ø\±……ÙÅ‹7Û´ù*>~U:îr¹|çÎqq+T“ ¶LºâñãÂöí»ºÚee]ëÞýÏŸÿ)ô„¯¦˜,É嬰ðåìÙ(¥f^^ND!©^+ áÏ?_3Æ6m:4hPBNN^ýúžýõzøðï÷z 9ü{çSúð÷.SRSjRšRÊ¥,¶\ [ånµ emº¬–\*k£E–6$*Y•[-É%B»b]£]jíÊmú%Tb·Ë̼¿?ÞÝósfN#ã²y¾ŸÓ9ïyÞçyÞ÷Ì<ÏyŸsšUUÏBGgÎü–Þùfî…GGonh§¦Î=yrÝñãk6mšÿ×_uË–m• ©ÃÂÆ;¶:??ŽRSó×ÜCÿ†Îóæ%½ÐÍmÖøñ_!„ÆŽu51`ŒçÏOþûïº)S†\¸zìØêÕ«C !sæ$J$R$v{z:[X˜@¬4!ôá‡<Þ@ FF#¢£7kii®];KW—/'“n3& „ž=û›š—… sæÌúóç“}|ËöÀ; ä À{”'À{ƒ‰‰!ôðaG»uk?jT¿Q£ú1áé¹s—Bþþ+h1uêr„ÐO?•Ȇԃõ@ÙÚZÐuu èßÐùر‹{÷ž:}ú7A` ×¦Móè)'N” „üü†ÐS¦MŠ*/¯¼ví’ Á54xÓ¦ Cef­¯çäœÀûù m´wUäØ!dnnLå üB¨uëV¡úú¹uŒqÿþݺuk·}{þ€ŸÛØ|LÔ×7 Ö:BÈÍÍÉÍÍI[[ cܵk»ßO÷óó@ÿ>0-·ÎÀ˜@åPèbΘ1èÎ Â:ü'€÷&Íþý»íÚuüС‘#{cŒgÎôž9ÓýûP/BH*%!WWG##}æ,--Mòï³!]]mŒ±¦¦S“Ãü/û(°,Ì£Õÿ6F²e#ãiÓ†-]ºu÷ý°ªê™››S»væHæmE {WE>Ÿ¯…ÂøŸ::ÚH敉ršB¾øbÝÚµ»{öìèëë±jUPïÞAŒ’²Òío¾ ìÙ³ãÙ³¿»»Ï¹t©lÞ¼¤;óxÿ¤:Lcº­««ÒÐà±Í—‹ ðŸÖ€÷ Xj€÷ƒÐÐ1¡ÔÔ»wŸ ·±%iJJ.s/¼G¡¡CwïŽÙ½;Æ×wH·ní?ùÄ]®t‡]ý/{‡^®SBȇÚ#„¶l9B›¥¥Â[X˜ØÙ‰äε±1ÿè£ÕÕÏgÏNDM™2”‰þ9zWQ>£Üé w¦¦@EGO MþÏÿËžH·]\RRæBvïþiõê]Ü^Â/–-99Ù"„vïþ‰îܶ-Öà?¬3Í~ýº.^>DCƒ'w.B( `ø‘#çïÜ©00Ð7Ε鋣wå+;]áN+«Ö¥¥·§N]Þ½»Ý‰%<©”ÐBØë ÌÆ¤IƒŽ»šzàË/7 îÒ¡ƒH™—ääÌûñ˜1_®]›}þ|i]]CiémXg€ÿ°Î470Æ úæçÇyyõ½wïq~~Q}½ø£z¬^zåÊKKáС8°bÀ€nW®üyâį;[÷Ýü3F¼Ê:B¨wïÎ'O®9²ÏŸVœ;WÚ§O烿?Þ ½XñO7¼½ûÒ'§'LpÓÓÓaä+ëc¬¢|ŠŠë [¶DõìÙ±ºúù¥Ke_}5u̘¡'Š‘’u& X½:´sgë¿ÿ®ó÷_!•ªºÎ0jT¿ï¾›ß¾}› ®¶Ü¸q.Bˆæ<¼ËÀoºïðûnê~Ó ^BÈ­[å:ùÖ׋úimß¾]Þ‡Ûí„´´CV98´9²B(;û§ñ㿲°0ùóÏo[;xøM·Ú$x£œ<ùkBÂî'JêëÅ~Øé=IBãÛ·Ë/NÇÐMSSãôéßBt©€wÈ€÷ú$4Ü<àm@ÑÒÒÌÍ=Cùè£6Ì~O„!$"brCƒxçÎãgÎüF‰„'üòK¿·­µIÀ{ ä jj“€æÔ&½ßÝÚzâìىϞý-׸iZUVÖtêä{õê&H „ìÜyLVCFÏ'Jš¦Šý¾VϨ×.BˆD"MM=ðèQõËžû&Qe~2†Ð{ÎË+ts›%KÞ¤ž¼àyà=~¨á­RW×àíyñâõyó|Ö­›%´¼~ýnbbŽ‹ËÌÇWöïßíeÒ—ÜcŒÏžÝ`i)DI$Ò«WïøûÇÞ»÷xïÞ¥ÊÞ‚/A¾á7åcŒÝÝ{Þ½»K(4$„(ì½SÖF„PmmýÙ³¿‡…­+/¯Üº5ŠØ4[!ááFîoggÑ Ì(?¾ÆÖÖBö±±@™¯{ô‘Z=£^»0ÆyyggÌX5dH¯×ç“W§ÑùI“j=:tè‡ë×ïIHØ6îµ €&9¯…ýûO{{Gݺ•% †Ë—o=w®´¨(¥];sºÓÊÊtà@'OÏù ¤œ<™ð²ú …sscº- #"&Å×Ôü­¯¯ÛhPþæ8mF[…(¼).k#BÈÚÚ¬ªêYhèš f´àÈÝWIÉ™™GoÞÌlrÊA7LLMVãUú}}ž¡j±‹Þ’§Ûïx`Í=?1þÿÛ鵃1ŽŠòõôœ?uêPCÖï¸u¨Ô& ~¸ïÜB$ 9ÁÁ£˜„i¼yó‚ÜÜåô,±X²dI†ÍÇ|¾»Ý'qqßK¥„©—غ5ßÉ)@GÇÝÑ1  à‚B!ºº|fX,ùúë-ÖÖù|w{{¿””\Ùè !¾¡M›±b±„î—JI»v“/NWØ#m£L&=%=ýp÷îÓutÜÛ·÷Ù½ûÄg»uó§-)’+˜©®~–о½Ÿï®¯?lÀ€Ï/VÑÉ<O*%R©”È¡³D"ŽÞ,ÓÑqï×/dùòm<ÞÀ?ÿ|ˆZ½zç°a …†´‹úzqtôæví&QÓÓsXX [m…6R™ û’3YY©Œ²~Õè5Ú…òòŠ$„XYMÀØ­ÑY´paª¡áðV­FŽ»Háüä˜$^,e…[:ÍÛ;Š¢¡1ˆžëââ nÚthN@μßÀ“ЯîÀc\Rr£²²ÆÃ£û¨™Y+##}zâ¬Y Û·ç'%͹vmÛ²eŸÆÆn[²$i¹vmvRÒœ¢¢==É“—J¥ò‰ ½k¾bÅöAƒº zã°°„µk³W¯½reKpðèÕëÖåÈöîïïùàÁ“ÇÏÓ;¦nß.Ÿ6mGÜ2W®Ü±zuhqñwVV¦Ó¦ÅFGoNNžS\¼I$úù½ 3BÈÏoÙ±c32"oÜØ~ôh<Æx̘/—†36ŠÅ’‚‚ 11éîî==¹f u^° 91qOB¬ÒÒ-ãÇŒŽþÇ«‰4'çÄ A=˜ 88>)i_\\PiiF@Àpÿ‡Sfµ\¦0]ä°Qa_ri©Œ¥¥);x­ža{þíÊȈÄÿüóÆ{÷²•ù“‘ìØÅS§ˆ]²Ä_áüTö„£ªœ±‰TNƱÜ/ÛiééÔ»ww1ž<øƒììãoøé ^+P›€šÑ׆¢A‰½½ #jjò˜„ŠŠ*„™Y+&Ș=;15õÓ¦´t‹¦¦FJÊþüü877'„¥¥ðÞ½Ç_~¹)2Ò—¶‰‰ pv¶Gòó[Æ}:gdöôtF¥§òðèei),.¾®°GŒ1·ÌeËf¸º:"„>ûÌËÇ'fÕª „Ðôé#&MZòða¥Œ[РA¸º::9Ù"„,,LBBFOœ¸˜úJÆF„Pmm½@ 7rdŸo¾ d·dëÌçk%$ì^·.lÔ¨~ãY³Æ^¿~'1qBèòå[OŸþÕµ« ^QQ•–v(%%œ¶ ŸX_/&)ódhè¦ß^½>“>W­ š1c‡ÚÚš û’ Е•Ê0Í^“gÔn—¡aK„P(03kÕèÌŒŒôíÜÙ!DQ8?}V'&&€N<ÆXSÓÿ?×1VèX¶X¶ÆætŒq—.í6m:(K´´ Ì€f\ÌÀ{< ­n~ùe#B¨ àb``\^Þ7ff­Ð‹Ï `ŒéJBUÕ3¦:"brPÐ(æD©TZ\|S"‘ޱ€9Q"‘ÖÖÖß¹SAÿ´µýç!]z ¹¡AL÷çæÆZX˜ „´µµZ·6ÒÑѦ \ºT&•’Þ½;3‰Jß¾]v˽»Æßxpp|eå3 ^vöOii ˜Cì¯^½Ã-ÓÁ¡-ÛôôtB66æ´e‹|„ìëe0FAAÞûöÞ±ãÇ[·”•=¸t© !$•¾pKXÖF±Xòã¿DD¤xxôJLü‚Ê”ƒ­siéíúzqß¾]û÷w¤‘ñ½{BôW„Ð¥Ke‰ÔÅÅ‚ÈÈO!Z]QQeb" -³³cd Ïh±‡ ûb›£ &8~MžaP‹]„ÜÜ3ŒFg¦s¥°ç'G sÈÖÖ‚ºˆ1V•Â!öB[ŽlcF¡PÐÐ ~ø°Š^‰4 g@ÍØÙ‰!¥¥·BÖÖf––¦r !NN¶úú-Ž½Ð«W'ºÓÔÔÐÔÔ!DODÿÆÊYYÑ:ˆdO‰„¿ýV†âñ°lLÃl·mÛÚÚÚL.$Â3Á7~ÑSx¼ª4'Lp›={]VÖQ ==/¯¾Ì!vÊÔÐàÉj‚±âjx„X,sfÛ;w*|}—*lÌØhoß¶CË#ÔÕ5ìÚµ˜Ý’­3MT‘×ýbòxÿèÌT°È¥|ªxÒÊÊ” Êe»Vf£Â¾T‡9å5yF½vÉب?555˜pœ=?9<ÆèÏãa9Uñ3»[»1ÆXCCƒ6æ–ÀxžõÃ]1æóµBBFûí÷7o>=D¹u«œnwîl1¾}»ÜÖÖÂÎNdg':sæ÷¯¾Ú,'JaÜ£°â¼KŸ9ó~>}©uk£V­ôe[êééLš48+ëèξ¾ÚÚ/Ü[‘ëQ™ì*…:Ÿ>ýÛÉ“¿îÚµdåÊ™^®®Ž7nÜCHé#Äãç’%þ99'd‹»8tvtl¯¥¥)«saáïô½+\^þ„êL‡àüù+LËqãÅ«èIvÚÆa£²¾T¬‰W¼ªÑ3j·« ³ˆöÅžŸª¬3 EóPÙYr²w*”Ãì$„Ü¿ÿX[[“.ÂÐ<€u€ò¤×ÂÈ‘}¤ÒeG1Æ‹M¹t©ÌÙyæ_Œ2¤—‘‘þÕ«wÒÓefíÕ«“¡aË–-u}}Ý£¢R [öéÓ¥°ðò矯?ÞMKKƒ‘£, dßCÅ·nmäç7$""ÅØØ {w»¼¼Â¤¤}±±3äš!„†÷îÄãñâãCääÈõ¨ºÌFunÝÚcœ––ghØR*•îÝ{êÛo³BÏŸÿÍm#!dîÜ<;~òðá½¶”ýÓØØ`æL¯¨¨&&''Û¼¼Âõë÷P=;v´ô.^¼NÃ̬•¯¯{DDЉ‰ÀÞÞjïÞS{öœÌÍUf5ÛR¹˜•ÃÆN¬ö%'¡®®¡²²F(4ÔÔÔíK®™Ú=£v»h¡ÿÙ³¿»¸8ˆDBÕgƘ=?¥RR^þ!$çŽ$AΊÚÚzêXÙ•1Urú^2Æš†•”ÜèÑ££ÜðŸrÞ|¾VNÎ×ß_––·refMÍ_ÆÆÎÎö™™‹ÆŒ@«’“í¬¶DFn¼{÷‘©©a` ×âÅþ²B”Ý+UëlØ0ÛÜ<=4tMEEU‡–‰‰aÓ§—mC©ž=;vîl­«ËïÒÅ5öêXUdª¢sÇŽ–7Îݶqc®‰‰ÀÛ»ï©S‰NN……— 8lÄóxhÓ¦yÝ»OŽ÷÷÷lÔ+WÎÔ×oÿèQuçÏ÷‰‰Éàóµ44xcÇ8|ø\HÈhü%%ÍY¼8í³ÏV•—Wvè ÚºuáСrXÍá+š“(³±S'+e}ÉJÈÏ/òöŽºqc»\ù™²"uy†ã¬&Ø5dH¯çÏk==§LYŽºvm›Š3“n³çguõ³6mÆ"„þøc‡¬g8Vüä1޵±1WvŠÂÎÎö²†´icLÊÏ/ Ó´23ÞMkÀ{ ,54 Œ9ö¶•P3 b›££§x6¿ ‡òÃ?wébü·*1qÏüùIÕÕy<|ùòí=>½qc‡¹y«æg;7Üžyw¼ÁžŸ„-[ò§N]þðáæ1ô·!䨱‹'.¾~}»A‹·¨ ¼*Ø ¢Yày€ „TU=Û»÷THÈBÏGïN˜¨F0Æ»v÷ñ‰)*ºróæƒœœK—nñóBÃb‡¶“'»ÇÇß,mç†Û3o[;¥ó“R_/^µ*32ò“·›0 „0Æ+WfFD| 43`þÖšFóZgxüø©ÍÇÆÆ›7/ ¿ Ñü „TW?Ÿ7/iß¾SOžÔˆDB__ÈÈÉ´‡òôé_..3÷í[fg'jTZs‚Û3ïÊæ'!䯿êèû|ß.‡Ÿ_±b{~~Ü;’h@Óu†œd€´¡ 4¯œ‚œA¨M€ ÈàrþP ä p9¼,5¼ä ¼5ÄbIjêW×YFF#ø|w+« S¦,/)ù£iÒ!û÷ŸÆØù§­ýQÛ¶ã*+k¸ÏÝ¿ÿ47°¬ìþ~•Õ™v­J¶<Þ@>ßÝÚzâìىϞý-׸iZUVÖtêä{õê&H „ìÜyLVCFÏ'Jš¦Šý¾VϨ×.BˆD"MM=ðèQõËžû&Qe~2†pxU½öBx¼ì± ÿ^]¾ÂëêV­ÊêÞ}ºžÞPOW×Y™™GU—@ÝøçŸ_jîå庹͋%ðŠKà]@óm+À{J]]ƒ·wäÅ‹×çÍóY·n–@Ðòúõ»‰‰9..3^Ù¿·—H_1>{vƒ¥¥!$‘H¯^½ãï{ïÞã½{—*{[¼ì÷ñ~£<ÆØÝ½çÝ»»„BCBˆÂÞÙ;emDÕÖÖŸ=û{XغòòÊ­[£M³…¾aôèþvvMÀŒÂñãklm-d ”Ùøê°G©Õ3êµ cœ—wvÆŒUC†ôz}>yuŸ„¼¼Bj‡êµc|÷î.ºýÃ?O™²¼¨(Åܼ£’zýI©­­:tÞíÛå_~9ÅÕÕQ,–äæžùôÓ•Gþ’’®ŠYåUïzØ0çõë÷$$ìþâ‹ñMQÔ ä À‚–'Á}WcÿþÓÞÞQ·ne‰DB…¡Æòå[Ï+-*Ji×Μ28ÐÉÓsþ‚)'O&¼ì?óÅ, ÌÍé¶H$Œˆ˜_Só·¾¾n£Aù›àtt´m¢ð£¬!kk³ªªg¡¡k6l˜m`Ђ[ w_%%df½y3³É)Ý014YWé÷õy†n¨Å.B#ðM(ÜóãÿÿÊǵ£v{• ["„„B™Y«×—Ž.Zô]YÙýóç“MMÿI8;tõîÝÙÕõó'OvoT³ýRŸ0„¨(_OÏùS§52Òo²   6 õÃ}_ÒÐ IHÈ Å$ LãÍ›äæ.§g‰Å’%K2ll>æóÝíì>‰‹û^*%L½ÄÖ­ùNN::*@ÑÕå3{ÄbÉ×_o±¶žÈç»ÛÛû¥¤äÊF3¡ðð mÚŒ¥Å„©”´k7iñât…=Ò6ÊdÒSÒÓwï>]Gǽ}{ŸÝ»O8p¶[7ÚòÈ‘"¹‚™êêçaa íÛûðùîúúà øüøñbÌãñ¤R"•J:K$ÒèèÍ"Ñ8÷~ýB–/ßF 'B«Wï6ìC¡ÐvQ_/ŽŽÞÜ®Ý$ªszúa«+§´ôö˪WVvcììl/nÚtÊ“€·ä  xúÕà1Æ%%7*+k<1Æ\¸}»|Ú´a=rË\¹rÇêÕ¡ÅÅßYY™N›½99yNqñ&‘Hèç÷‚Î!?¿eÇŽ]ÌȈ¼qcûÑ£ñã1c¾lhp8™†_bbÒÝÝ{ zrÍê¼`Arbâž„„Y¥¥[ÆýW%iNΉAƒz0 @pp|RÒ¾¸¸ ÒÒŒ€€áþþ+:§Ìj¹LaºÈa£Â¾äÒRKKSv:ñZ=Ãöü+Ú•‘‰1þùç÷îe+ó'#ÿر‹§N%8»d‰¿Âùɬ+4V"‘ÊéÏ8–ûâe;-==‚r÷î.ŽuUìe©B­„ìmîÏ Æ™ÖÖfH…+ô×_ÿxþ¼¶_¿®r:`Œüà矯ÔÖÖ³%Ïš•ðÝw““Ã/_Î>¼÷Â…›˜_J=ŒñàÁdgÇ×£€÷¨M@ÍèëCÑ ÄÞÞ~ÕÕÔä1 !U!¦œ€2{vbjê¦MiéMM””ýùùqnnN!KKá½{¿ürSd¤/màìl åç·Œy¼²k×iTlCƒX*%îî=SR !ÕIIû’“ý½ûbŒCBF_»v'6v{HÈh¦_‡¶}útÎÈ8ìééŒJO?äáÑËÒRX\|]acn™Ë–ÍpuuD}ö™—O̪UA..¡éÓGLš´äáÃJ· Aƒ>puutr²EYX˜„„Œž8q1õ•Œ¡ÚÚz@oäÈ>ß|ÈnÉÖ™Ï×JHؽn]بQý0Ƴf½~ýNbâ„ÐåË·ž>ý«kW*¼¢¢*-íPJJ8m>±¾^LRæÉÐÐ1L¿½z}&å¬Z4cƵµ5ö%*)+•aš½&ϨÝ.Ù¢šFgfd¤oçÎÖ!BˆÂùÙè³:11tâ1ÆÊÝ5WèX¶X¶Æî&Uì•?Z±­C2‰âÇUÜŸ‘‘¾mB¹¹g W(ý`166++"„˜˜¤RRUõLNò“'5©©’“çxyõAщ´~ý^„£ž««#ÆØÊÊ”­k¦—.]ÚmÚt°¡A¬¥1ð6ù€šùå—¡‚‚‹qyyߘ™µB/VñbŒéJBUÕ3ºc19(hs¢T*-.¾)‘HGŒXÀœ(‘HkkëïÜ© ÚÚþó.½…ÜÐ ¦ûssc-,LBÚÚZ­[éèhS.]*“JIïÞ™ð¢oß® »åÞåâï?<88¾²ò™†/;û§´´Ì!vW¯Þá–éàЖF6zz:!sÚ²E >BH,þÿÆ((È{ß¾Ó;vüxëÖƒ²²—.•!„¤Òn ËÚ(K~üñ—ˆˆ^‰‰_P™r°u.-½]_/îÛ· £sÿþŽ42¾wï1Bˆ>ðŠºt©L"‘º¸80Cù !¤ à¢B«+*ªLL´evvŒlá-vâ°Qa_ls”Á„¯É3 j±‹BVJ£3ÓÎ΂¹RØó“ûácÆXê"ÆXUî[³×Ørd7šºpÛ[QQEý©"ìç0ÆÅÅ7¸?7äîoô ¥–>}ú{áÉ“§<ZÊI.)¹!K\\­úöíJsUÔ“û´  ⇫èǼ- g%À“ÐMÅÎND¡õ»ÖÖf––¦r !NN¶úú-Ž½Ð«W'ºÓÔÔÐÔÔ!ÄþÒX9++ºC‘ìé"‘ð·ßÊB<–E˜í¶m[[[›±¿à™à›ù"§§ðx/TiN˜à6{öº¬¬£zz:^^}™Cì•©¡Á“ÕcÅÕð!±X2xðì›7L˜àææÖ}æÌ¶wîTøú.Uؘ±ÑÞ¾m‡–#F,¨«kصk1»%[gš¨"¯3ú7ãñþÑ™©`‘ bTñ¤••)”Ëv­ÌF…}©sÊkòŒzí’3°Qjjj0á5{~ª¬óxXNgUüÌnÀ–ÃÑXÙ!{_jô®34ú¹¡©©!{b£W¨““mË–ºÇðœí?ýTܽ»®®6ÝÃHþW™ÿkÅ,¨¢ž\/!j“€· <Ï€úQU0Gù|­Ñß~ûýÍ›dBnÝ*§Û;[cŒoß.·µµ°³ÙىΜùý«¯6ˉRa°wBºt±áñð™3¿1_ä§O_jÝÚ¨U«^H¢§§3iÒବ£;wøúzhk¿poE®GUd²«üê|úôo'Oþºk×’•+gz¹º:Þ¸q!¥y+#Äãç’%þ99'd‹»8tvtl¯¥¥)«saáïô½‘Y^þ„êL‡àüù+LËqãÅ«èIvÚÆa£²¾T|ôSaðªFϨݮ&Ì"Ú{~ª¬7ú´ …ÎW&‡c¤ä2{_*]dÎ`Œ›ð¹Á}…êèhz­Z•yÿþÙ§&Î+ÍÊ* Ë–Ü­[{mmÍãÇ/2Z1‰QêfkkÁVON™û÷kkk¾Ô ¼`”K ¯ÀÈ‘}¤ÒeG1Æ‹M¹t©ÌÙyæ_Œ2¤—‘‘þÕ«wÒÓefíÕ«“¡aË–-u}}Ý£¢R [öéÓ¥°ðò矯?ÞMKKƒ‘£,Laß­Ä·nmäç7$""ÅØØ {w»¼¼Â¤¤}±±3äš!„†÷îÄãñâãCääÈõ¨ºÌFunÝÚcœ––ghØR*•îÝ{êÛo³BÏŸÿÍm#!dîÜ<;~òðá½¶”ýÓØØ`æL¯¨¨&&''Û¼¼Âõë÷P=;v´ô.^¼NÃ̬•¯¯{DDЉ‰ÀÞÞjïÞS{öœÌÍUf5ÛR¹ÈŒÃÆN¬ö%'¡®®¡²²F(4ÔÔÔíK®™Ú=£v»èç³gwqq‰„ªÏ"Œ1{~J¥¤¼ü BHÎ3I‚œµµõÔ±²÷ÝUIÈé{ɨ!BF 99²Í”ÙËîN¡VÜÖYZš¾ìçF£Whtô´sç.÷é=mÀÇúú†ÎÆÄ¤Ožìîçç!w.ƸU+ý°°qQQ©­Z¸¸8äåÒÂ$„H$lT=¹ÙURr£GŽp“xË@ÎÀÛÏ×ÊÉùúûï ÒÒòV®Ì¬©ùËØØÀÙÙ>3sј1èB|rr¸•Õ–ÈÈwï>255 ôZ¼Ø_Vˆ²»’Êb f››§‡†®©¨¨êÐÁ211lúôá²mèW~Ïž;w¶ÖÕåwébƒ+ÀPE¦*:wìh¹qãÜØØm7暘¼½ûž:•èäPXxÙØØ€ÃFŒ1‡6mš×½ûôààxÏF½±råL}ýÁÁñU÷èÑqþ|Ÿ˜˜ >_KCƒ7vì€Ã‡Ï…„Œ¦wL“’æ,^œöÙg«ÊË+;tmݺpèÐ9¬æðÍI”ÙØ©“•²¾d%äçy{Gݸ±]®üLa¿jô ÇYM°kÈ^ÏŸ×zz:O™²!tíÚ6g&ÝfÏÏêêgmÚŒEýñÇYÏp¬øÉbkcc®ì…;íCΟOîÚuBˆ-G¶™*örh¥Ì&Q|ÙÏF¯P]]í#Gâv¯^½300NSS£GŽë×ÏöñŒÍ=BȲe3‚–sçnxø°òÃí££§ÎŸŸLÛ4ªž¬-„ üü¢ÐÐ1/µ¯ÅšüXghŒ9ö¶•P3 b›££§x6¿¯jBÈ?üÜ¥‹ óÞªÄÄ=óç'UWäñðåË·{ôøôÆææ¯ëG²ÞY¸=óîxƒ=? ![¶äOºüáÃ=Ìcèo…ŒŒ#T ccƒwÇcÿ] .Lœ¸øúõíÊ~’x`7d¥.à~¨á}‚RUõlïÞS!!kA>>5Ë/iŒñ®]Ç}|bŠŠ®Ü¼ù 'çÄÒ¥[üü†Ð°ØÁ¡íäÉîññß7KÛ¹áöÌÛÖNéü$„Ô׋W­ÊŒŒüäí& uu T HÔ!dåÊ̈ˆO aÞ`,ÎÆ7 IDAT–¸i^ë ?µ±ùØØØ`óæôýîÍBHuõóyó’öí;õäIH$ôõõˆŒœL+p!OŸþåâ2sß¾evv¢F¥5'¸=ó. l~Bþú«Ž¾-ôíòüym‹|pÕÂáÃçW¬ØžŸ3¼`áE g€Æ€œ›æ•3B3È™+4”'ð~9\@Î*K ¼Ç@Î3Àä  Pžô‹%©©\]gàóÝ­¬&L™²¼¤ä¦I#„ìßc7柶öGmÛN Œ«¬¬á>wÿþÓ<ÞÀ²²ûoøUrTgÚµ*mØ6òxù|wk뉳g'>{ö·\ã¦iUYYÓ©“ïÕ«wš ²sç1Y =Oœ(iš>*öûZ=£^»!‰45õÀ£GÕ/{î›D•ùÉÂáUõÚKáñ²Ç‚þ{uù {¬«kXµ*«{÷ézzC <]]gefU]uãŸ>|G^VYQQ5kVB»v“ø|wcc/ð¼¼BB÷H½Ê”—WÈã äñ¦¯?ŒnSQyy…nn³Äb‰:,^#šo[ÞSêê¼½#/^¼>ožÏºu³‚–ׯßMLÌqq™yøðÊþý»½¬@úJxŒñÙ³,-…!‰DzõêÿØ{÷ïÝ»TÙ;ãe¿ÿÞð{å1Æîî=ïÞÝ%BöÎÞ)k#B¨¶¶þìÙßÃÂÖ•—WnÝÅlš-„ðð £G÷·³³h‚fŽ_ckk!{ÈØX ÌÆW‡=úH­žQ¯]ã¼¼³3f¬2¤×ëóÉ«Óèü¤5„à õÚ‹1¾{wÝþᇟ§LY^T”bnÞŠQI½þ$„ÔÖÖ:ïöíò/¿œâêê(KrsÏ|úéÊ£GII WE‚¬òjÔ­i44ˆ?úhŽA‹´´ˆvíÌ++k6oÎ1""3sѸq®Ì€Êy’Òä+ˆñÀÅ‹›,,LÄbÉ‘#ç§LYNwúáúõ{v‡…{ü(rPºÔðnÜ%z÷Ù¿ÿ´·wÔ­[Y"‘Pa¨±|ùÖsçJ‹ŠRÚµ3§;­¬Ltòôœ¿`AÊÉ“ MþZ ææÆt[$FDL Н©ù[Ùo©Ê}/¾á/-mF[…(¼¥'k#BÈÚÚ¬ªêYhèš f´àÈÝWIÉ™™GoÞÌlrÊA7LLMVãUú}}ž¡j±‹ÞÐ¥ÛïxÄ=?1þÿ¯ÙÔôŸp¹CQïÞ]]?0Àqòd÷F%0Ûo=E$„œ:ué×_ÿ¸p!Õѱ=BH$~ûmðùó¥ëÖåŒçªl¤0Æ~X)ƒ% ZµÒGÿs(*Ê×ÓsþÔ©C [¾ãWÄû Ô& ~¸ï«B$ 9ÁÁ£˜„i¼yó‚ÜÜåô,±X²dI†ÍÇ|¾»Ý'qqßK¥„©—غ5ßÉ)@GÇÝÑ1  à‚B!ºº|fX,ùúë-ÖÖù|w{{¿””\Ùh!¾¡M›±b±„î—JI»v“/NWØ#m£L&=%=ýp÷îÓutÜÛ·÷Ù½ûÄg»uó§-)’+˜©®~–о½Ÿï®¯?lÀ€Ï/VÑÉ<O*%R©”È¡³D"ŽÞ,ÓÑqï×/dùòm´p!´zõÎaÃ> iõõâèèÍ´†ÁÞÞ/=ý0‡Õˆ±ÕVh#•©°/9“••Ê(ëWžQ£]!/¯HBˆ•ÕŒÝE ¦oÕj䨱‹ÎOŽIÒèÅBQVvÒ¨Ó¼½£¨!ƒ”•¬`ŒU±Wu­Ø!;¸?7g&$ìVå ­«kHJÚ÷ùçc™„v×»·Ã¸q® »Ù’ËÊî74ˆ##7š›ÑÕõpwŸSZzûeÕSVF™1cU—.SóëêLL¼V¬Ø¡lì䥯ß!”•u´¾^Ìì?q"áøñ5r#¥Ðc¯xaŒÙW«‹‹ƒPh¸iÓAHÞe g@ýpŽã’’••5½ØGÍÌZéÓgÍJؾ=?)iεkÛ–-û46vÛ’%iL˵k³“’æ¥èééLž¼T*• è]ó+¶Ô] ÐÇ…%¬]›½zuè•+[‚ƒG‡„¬^·.G¶wÏž>|ž~±\¸}»|Ú´a=rË\¹rÇêÕ¡ÅÅßYY™N›½99yNqñ&‘Hèç÷‚Î!?¿eÇŽ]ÌȈ¼qcûÑ£ñã1c¾lhP\æËØ(K .ÄĤ»»÷ôäš)ÔyÁ‚äÄÄ= ³JK·Œ?0:ú¯J$Òœœƒõ`€ààø¤¤}qqA¥¥ÃýýW:tN™Õr ˜Ât‘ÃF…}É ¤Õ––¦ìtâµz†íùW´+##cüóÏïÝËVæOFþ±cOJ

¼÷Â…›˜_J=…VO›6ì÷ßoýòË5zÅåæžyúô/??…¥DlïõèÑ! À36v»¹ù˜ñã¿Z»v÷•+*)•šv)ü” „ üAvöqe3x€Ú$x }:gdöôtF¥§òðèei),.¾®°GŒ1·ÌeËf¸º:"„>ûÌËÇ'fÕª „Ðôé#&MZòða¥Œ[РA¸º::9Ù"„,,LBBFOœ¸˜úJÆF„Pmm½@ 7rdŸo¾ d·dëÌçk%$ì^·.lÔ¨~ãY³Æ^¿~'1qBèòå[OŸþÕµ« ^QQ•–v(%%œ¶ ŸX_/&)ódhè¦ß^½>“TV­ š1c‡ÚÚš û’ w”UG0Í^“gÔn—lQM£332Ò·sgk„!DáülôY˜˜:ñcåîš+t,[,[cw “*öÊέØÖ!™ÐóáÃ*îÏÈH_‡¶¡ÜÜ3H…+”~°V}¿‰‰@*%UUÏä$?yR“šz 9yŽ—W„Hë×ïE1깺:bŒ­¬LÙêѱæ wïÎm·mËïÑ£Bh˖ÞžÎrŽâöÞÆs?þxðÎ?üðsvöO¡>êñÝwó-,LdGJ¡ÇšvÉM*êUŒq—.í6m:(K´´ 4}G@ÍüòËF„PAÁÅÀÀ¸¼¼oèì×-Ƙ®$TU=c¾0""&bN”J¥ÅÅ7%éˆ ˜%immý;ôO[ÛÒ¥·þYgÏ͵°0Aikkµnm¤££M¸t©L*%½{wf‹¾}»&$ì–{Cˆ¿ÿðààøÊÊg¼ììŸÒÒ0‡Ø=^½z‡[¦ƒC[Ùèéé „llÌiË-ø!ÙW…`Œ‚‚¼÷í;½cÇ·n=(+{péRBH*}á–°¬b±äljˆHñð蕘ø•)[çÒÒÛõõâ¾}»0:÷ïïH¿×ïÝ{Œ¢¼"„.]*“H¤..ÌDF~B)(¸¨Ðꊊ*m™#[xF‹8lTØÛe0áãkò ƒZì¢÷†!ÎL;; æJaÏOŽræ­­uc¬*E 웾l9²M]¸í­¨¨¢þT¹žú§¸ø÷ç†ÜÃý^¡ÔÒ§Oÿb¯3yR“—w.+ë«FÏ’cðàþ!tóæƒï¿?“þñÇ‹OœH`·Tö:„¦]Ar“i) ÄVÑOoàrxI`©¡1ììD„Z¿kmmfii*×€âäd«¯ßâèÑ ½zu¢;MM MM BLá/•³²¢;tÉž. û­ !ÄãaÙ¯f»mÛÖÖÖfì/x&øf¾Èé)<Þ Uš&¸Íž½.+먆††žžŽ—W_æ»ÇFejhðd5ÁXq5=D¹u«œnwîl1¾}»ÜÖÖÂÎNdg':sæ÷¯¾Ú,'Já7%{'!¤KŸ9óóE~úô¥Ö­è{<ôôt&Mœ•utçÎ__míî­Èõ¨ŠLvý®BOŸþíäÉ_wíZ²råÌÀ@/WWÇ7î!¤4?e„xxô\²Ä?'ç„lq‡ÎŽŽíµ´4eu.,ü¢wøÊËŸPéœ?…i9nÜ¢  x=ÉNÛ8lTÖ—ŠõÍ ƒW5zFív5aѾØóSÅ`]a97 ¯LÇHÉeö¾TºÈþœÁ7ásƒû ÕÑÑ ôZµ*óþý'L3Bȹs¥YY¡¡cÙ’»uk¯­­yüøEF+f"1êQÝlm-Øê©2ç[·61¢wVÖÑ;~ôó¢z=!äÖ­«VeÞ¿ÿXVm„P‹ü-t”}¢ª²_•+Háü!„Ü¿ÿX[[󥚀7 ¬3ðZ9²TZ ì(ÆxÑ¢)—.•9;Ïüâ‹ñC†ô22Ò¿zõNzú¡ÌÌ£½zu24lÙ²¥®¯¯{TTª¡aË>}º^þüó5ãÇ»iii0r”}¹²ïVbŒ[·6òó‘bllн»]^^aRÒ¾ØØrÍBÃ{÷âñxññ!ì»b²ª.³Q[·6§¥å¶”J¥{÷žúöÛ,„ÐóçsÛH™;÷ãƒÏΟŸ<|xo…-eÿ466˜9Ó+*j£‰‰ÀÉÉ6/¯pýú=TÏŽ-½‹¯ÓßÇ03kåëë‘bb"°··Ú»÷Ôž='ssc•Y­ð¢ìŸ6vêd¥°/9 uu ••5B¡¡¦¦†l_rÍÔîµÛEƒ¼³gwqq‰„ªÏ"Œ1{~J¥¤¼ü BHÎ3I‚œµµõÔ±²÷ÝUIÈé{ɨ!BF 99²Í”ÙËîN¡VÜÖYZš¾ìçF£Whtô´sç.÷é=mÀÇúú†ÎÆÄ¤Ožìîçç!w.ƸU+ý°°qQQ©­Z¸¸8äåÒÂ$„H$lT=î1e:š:uè'Ÿ|ýüymZÚ…ë3ÊÆtÁ‚Oöï?íæöÕWSí¥Ré?ü¼hѦ… ý´µ5eGŠÃ' ÷«r)[g()¹Ñ£GG¶¥À»ä ðò@y’:àóµrr¾þþû‚´´¼•+3kjþ266pv¶ÏÌ\4f̺Bœneµ%2rãÝ»LM ½/ö—¢ì®¤²XgÃ†Ùææé¡¡k**ª:t°LL ›>}¸lúÖ³gÇέuuù]ºØ Æ 0T‘©ŠÎ;ZnÜ876vÛÆ¹&&oï¾§N%:9^666à°cÌã¡M›æuï>=88Þßß³Qo¬\9S_¿Eppü£GÕ=ztœ?ß'&&ƒÏ×ÒÐà;àðás!!£éyRҜŋÓ>ûlUyye‡¢­[ú!‡Õ¾¢9‰2;u²RÖ—¬„üü"oï¨7¶Ë•Ÿ)ìWžá8« v ÒëùóZOOgú³V×®mSqfÒmöü¬®~Ö¦ÍX„ÐìõŒ2±1޵±1WvŠÂÎÎöŒ!çÏ'wí: !Ä–#ÛL{9´Rf“(¾ìçF£W¨®®ö‘#q »W¯Þ§©©Ñ£GÇõëgûø FŠæ!dÙ²A˹s7<|Xùá‡öÑÑSçÏO¦mUÚ¢lL™Ž† s60hÑ­[»N¬&Tʼ׶mësç’W¬Ø½ùÎ ž£cûÄÄ/¨9²#¢Ì'Êö7z)ô¶TJòó‹BCǼTqð†QPj@ã@ÎÀ€1"ÇÞ¶j¦¡Alcóqtô´€Ïæ÷Fùᇟ»t±aÞ[•˜¸gþü¤êêƒ<¾|ùvŸÞ¸±ÃÜüuýHÖ; ·gÞo°ç'!dË–ü©S—?|¸‡y ý­‘q„ªallðîxì¿È»3¦ªÃq9r~øðwïr¢?úI“„бc'N\|ýúvƒoÙY°|ÑËÏ3ü!¤ªêÙÞ½§BBÖ‚||>j–AÆx×®ã>>1EEWnÞ|“sbéÒ-~~ChXìàÐvòd÷øøï›¥íÜp{æmk§t~BêëÅ«VeFF~òvƒËººª$ ¯Î;2¦/ÇDTTT?~ü´¼¼’yØš®g®\™ñÉ»•0,`š ,5Pš×:ÃãÇOml>666ؼy}¿{óƒR]ý|Þ¼¤}ûN=yR# }}="#'ÓúBÈÓ§¹¸ÌÜ·o™¨QiÍ nϼ (›Ÿ„¿þª£o }»<^Û¢†WçÝSÕQvikk:tÎÓs>BÈÍÍ©¨èʳg£Ë®Ž)Z±b{~~Ü;’œÿXgxÈ ©@Î@i^9 9ƒ ÐÜœ. g€ Èà€ò$Þ g€ ÈàÕ€¥†· !D"‘¦¦xô¨úuH#„TVÖtêä{õêýûOóxËÊî«øº9îöì¾òò ÝÜf‰Å’&¼ÎN,–¤¦pued4‚Ïw·²š0eÊò’’?^V£Ûþý§1vcþikÔ¶íÄÀÀ¸ÊÊîs_ÖKê‚êL»V¥ ÛFo Ÿïnm=qöìÄgÏþ–kü&mxœ€ÿ0ã¼¼Â3VýýwÝ«vliãðð £G÷·³³pwïy÷î.KKSUÞ NánÏîkØ0g}ý »_ö åuu #F,X¸0ÕÛ»ßO?­½vm[ZZijg»¸Ì‹C½Ôˆ4o4ß¶4Oöï?ííuëV–H$|}!!„ _½¶´ââ™™GoÞÌDéèh››«( cÌÝžÝ!$*Ê×ÓsþÔ©CŒôU×yùò­çΕ¥´kgNwZY™èäé9Á‚”“'^Ö3ŒbB¡€1A$FDL Н©ù[__WY"$+ä ‡ÚÂ\BÖF„µµYUÕ³ÐÐ56Ì60h¡úˆ4o`^(Ob¡Êýæúzqtôæví&ñùîöö~éé‡é~±Xòõ×[¬­'Òý))¹t?-Ùº5ßÉ)@GÇÝÑ1  àBÈË+’be5c7ÚfáÂTCÃá­Z,+»_]ý<,,¡}{>ß]_Ø€Ÿ?^Lãu… ÈJ#„¬^½sذMLH¦êFÎÒF÷«¢9u”³³½Ph¸iÓA¹è–£—†IBBNpð(&a`ܾyó‚ÜÜåÔÿb±dÉ’ ›ù|w;»Oââ¾—J #–­{( !ºº|f{˜d³ „Pxø†6mÆÒR+BˆTJÚµ›´xqºÂie2é)é釻wŸ®£ãÞ¾½ÏîÝ'8Û­›?myäH‘\)‘ÂqW8kºòx<©”H¥RI$ÒèèÍ"Ñ8÷~ýB–/߯ã üóχÊúø9êGî~3»!$88>)i_\\PiiF@Àpÿyy…„°°„µk³W¯½reKpðèÕ »!k×f'%Í)*JÑÓÓ™@3j“@Ð¥xP!„¾þ0„D"EÙÛûÑ€¬¦&i@yô¨:-íPJJøèÑýBsæL¨¯‚**ª“’ö%'‡Õ!<êÚµ;±±ÛCBFÓscbœíBAA£üü–=zTmhØ!$ ÌÌZÑ6‘‘¾mB„ Aƒ>puutr²EYX˜„„Œž8qqEE•¶¶&U`Ô¨~ãðð‰TYi—.•=}úW×®6rá¸\@¯°$†Ásk΄­]º´Û´é`CƒXKë…Ïge½TTT!„d%Ìž˜šz€iSZºESS#%e~~œ››BÈÒRxïÞã/¿Üé«L7º¿k×iTlCƒX*%îî=SR !Ì0y{÷Ň„Œ–&„ƒCÛ>}:gdöôtF¥§òðèei),.¾®°GŒ1·ÌeËf¸º:"„>ûÌËÇ'fÕª „Ðôé#&MZòða¥Œ[”Ž;bÁ؈ª­­ôFŽìóÍ7ì–lù|­„„ÝëÖ…ÑY4kÖØë×ï$&îaŸ ð_rÔÌ/¿lD\ ŒËËû††ò²ÕíãK—Ê$©‹‹Ý1ŽŒü!tôè©”ôîÝ™Ùß·oׄ„ÝLkkkAåÐÛÀ b¶vvÿöE‚‚¼÷í;½cÇ·n=(+{péRBH*•2 0ZEF~BÉÍ=Ãȹwï1BH(4”KT©Ôg7àÐ\Ö3B¡ ¡AüðaU›6ƪôBWªªž1‹ˆ˜4 ý;R©´¸ø¦D"1b#P"‘ÖÖÖß¹SÁ­[nn¬…… BH[[«uk#mjþ¥Ket˜˜DEn˜(þþÃã++Ÿihð²³JK[Àá«WïpËtphK31==„9mÙ¢!$ÿ c¤lÜÙ>¤6ŠÅ’ü%""ÅãWbâTf£#XZz»¾^Ü·oFçþý!g Y9jÆÎND)-½²¶6³´4•k@«Àé¶\ÍÕ1A y¼ )y<,{ _aᓦ¦Ss?xðì›7L˜àææÖ}æÌ¶wîTøú.Eÿ.ƒ V2#+‡þÉãñ¸×ÂVŒCsFBˆ††m¬b/NN¶úú-Ž½Ð«W'ºÓÔÔÐÔÔ!D‡ý+geEwè ’=]$þö[‡nmÛ¶¶¶6c»…&&Q‘&Ê„ n³g¯ËÊ:ª¡¡¡§§ãåÕ—ÃÊÔÐàÉj‚±âÑGœãΆ±ÑÞ¾m‡–#F,¨«kصk1»%[gš¨"¯3@óžg5OBËÀý<ƸsgkŒñùóW˜£ãÆ- ^Ý¥‹ ‡Ïœù©ï?}úRëÖF­ZéËžþbì¨ø>ãÓ§;yò×]»–¬\930ÐËÕÕñÆ{!B£¬·(((^V½Å^^þ„ãyU<Шæ²÷ï?ÖÖÖ Uì…Ï× ýí·ßß¼ù@ö!äÖ­rºM½}»ÜÖÖÂÎNdg':sæ÷¯¾ÚÌ¡‡!„f˜ﱇ !¤§§3iÒବ£;wøúzhk¿p—J®GUdÊ=f­LgŽqW#Äãç’%þ99'd‹»8tvtl¯¥¥)«saáïŠûøë ¼FŽì#•(;jnnìëë‘bb"°··Ú»÷Ôž='ssc[·6òó‘bllн»]^^aRÒ¾ØØ²çÊÓôe>gÏþN«ÛeÛ´nm„1NKË34l)•J÷î=õí·Y¡çÏÿîÔÉJ¡ô)*­cGK@ïâÅëýúu•íQ.¨«k¨¬¬ 555”)É­9Bˆ®ÆBJJnôèÑQ²^¨2‹M¹t©ÌÙyæ_Œ2¤—‘‘þÕ«wÒÓefíÕ«“¡aË–-u}˜hMé IDAT}Ý£¢R [öéÓ¥°ðò矯?ÞMK«…‘¢B,Œ±*ÃDÏ Þ»wÇ‹a—xÉþ©ºÌFuæwn !sç~|ðàÙùó“‡ï­°¥ìŸÆÆ3gzEEm4189Ùæå®_¿‡­'@3rPð$´ÊB’’æ,^œöÙg«ÊË+;tmݺpÈ^¡ f››§‡†®©¨¨êÐÁ211, ÀSö\¹€ÌÙÙÞÓÓyÊ”å¡øøÙ6;ZnÜ876vÛÆ¹&&oï¾§N%:9^îÔÉJ¡ÏŸ×2Ò®]Û6vì€Ã‡Ï…†Ž‘S^ve ?¿ÈÛ;êÆí²e<ªÜ³—ÕüÚµmmÚ‚òó‹BCǰÃt…½Pø|­œœ¯¿ÿ¾ --oåÊÌšš¿Œ œí333€Çáääp+«-‘‘ïÞ}djjèµx±?‡nÜû1Æìaš>}8ÛK={vìÜÙZW—ߥ‹ jì%¼ªÈTEgŽq766à°cÌã¡M›æuï>=88ÞßßSYK†•+gêë·Žô¨ºGŽóçûÄÄdðùZ øïÅ— VÞÜcD޽m%^ „Ë—o÷èñé;Ú´y¿íUPpaâÄÅׯoWö£iÿ9Ä66GGO ðlÉBùᇟ»t±aÞ[•˜¸gþü¤êêƒPú ÿq°Û{÷…Î |¨(cloo5y²{|ü÷oàö !dåÊ̈ˆOšAÂ@©ªz¶wï©5„ Ÿþë)c¼k×qŸ˜¢¢+7o>ÈÉ9±té?¿!tm 9ë  nÞ·¥†æ»Î@©®~îâ2sß¾eÌ«6_„#GŠV¬ØžŸ×]Gǽ}{ŸÝ»O8p¶[7ÚòÈ‘"¹R¢êêçaa íÛûðùîúúà øüøñb…ó ±¦%Ç“J‰T*åAª›D"ŽÞ,ÓÑqï×/dùòm´°MY_Í ÈP?r÷¡Ù !³f%lßžŸ”4çÚµmË–}»mÉ’4Œ±—WŸÀ@¯¹s7üùgÅO?•|ýõ–5k>ïÜÙ:##cüóÏïÝËF)<‘¿vmvRÒœ¢¢==É“—J$RÚãwßLN¿|9cøðÞ n¢%iNΉAƒz`Œ•iΔÄXZšrgDr]K¥DVsz.ÆxðಳËÎÑKIÉÿ±wßqQmÀgîhŠH/J,ˆb;¢`ÇÞ{CT쾊bÁØPDQ±K"bǒذaÔˆ±—Ø{[înÞ?&Ùœw°œ¨ ðû~ü÷vgž™›ƒyvg÷^½zãí][½?­¬LøõŠœzU$6•†ðK.sælðô¬nh¨O) Œ\¼81"bÄÕ«k‡ï±dI’ríýû·züøåÞ½¿óÞ;xð»wŸôë×R¤Fñ2çÎÝ1"-m¥E¿~á¡¡«bbƦ¥­°±1÷óû$fBˆŸß¬C‡Î­Y|óæ†RJ;vü_V–œdGh£L&?xð°°Õ^^µ õs} !“&ÅDEmŒuåÊÚ.]š„†Æ«—Pˆam|e- !r¹‚R©’Ÿ¨½y“,ìÀ{ú4=6vÇþýó=<ªBlmÍ>|ñ¿ÿ­öÕ֖Λçèйºví^M hE12*A177´²2oÜØ•Rjgg!Ϋ àîîLñ÷oïç7ëùó --i\Ü®˜˜±>>õ!£FuºqãþÒ¥Û!—/ßyýú}•**Óq• }¶KbÔgðaaÜÜ*)W­¹0muq)»bÅî¬,™¶ö'¿‡sªåÙ³tBˆr cÆDÅÅíö¹re­––4§^Í)6¾½J•~¼Ø¬,™BÁ¼¼jÅÆŽcŒ={–½=&f\»võ)¥®_¿¾!  ƒP¯³s™zõ*¯Y³·U+7BÈêÕ{¼½kÛÚš§¥ÝȶFJ©x™³f nÜØ•2dˆOÏžaóæùó·ràÀ6=zLúô•R·OÏ»V«æH±¶6 èЭÛ4ÞW*„6B>|È44ÔoÛ¶ÞO? UßS=f]]íÈÈ-K–¶o߀RÊOTÔVõc +ä ßR‘¼úìÙ儃Ï :?9ù'++òéªwJiZÚM¹\ѦÍ$a£\®øð!óþýgVÅŠé¬[7¹N!¥K›-]:Z}^.r8ÿ¯££5?ŠŸEÎÊ’]ºt[&“»»;óH(¥õëWá9ÃÇ/!ê·Àj²R_}GGk¾Q¨Z}gJ©¹¹aV–ìéÓôÒ¥M5©…_IHO+ÄÔÛß¿½ÐÕ …"-ív®Ý’ml;w†[[›Btt´--õôtxó/\¸¥P°ºu+ ‰JýúU"#·¨<½ªÿÖÇ/|õê­T*IL<?I¤7®]»/^¦³sþÞéëëBJñ=‹×%„Èdÿ]C ”øû·Û¾ýøÆ¿Ý¹óøÖ­Ç.Ü"„( õ>äm”Éä¿ýv6((ÖÛ»vTÔh^f®ïà•+w33eõë»17l芜Šä ð•99Ù0ÆøÝööV¶¶*;0Æø¬.!!´|yå—„¦Ïœ¹*‘H=zqîÜ õ'‰~ñâ-BˆD¢ºÊèßÙÞ T„ü|‹D"¿Î-õ|F"¡ÊU~j—J¥êqŠÔR­š£Añþ¨]»"ßhaadaaDnÌФ[²­LK{{+õ…RÂä[HTø!É'ëZ»võ3fIB©Tª¯¯çãS_¤7r-S*•(GBiöËÛ!2™¼iÓ1·o?îÚÕÃãú°aeîßæë;3Û…6VªT¦|yÛ6m&}ü˜µyó4õ=Õcæ‰ cª1¸Ÿà+’wB‹ßÏ@)­\ÙžRz÷îGGk''''›'.MºŠïõê½1c¢BCûuíÚÄÏo–pr](A8œëèh-®\¯rÕU«–ÓÑÑ:|øœpGAjê%þ?ÅþäÉK‘û4i©òÆOg½Tý‡G^èèhñ†jR‹®®v@@‡ ~¾}û±J3ïÜyÂéÕœbicÌÅÅA"¡'N\RãÇ/XZ›˜|ò¸'}}½=š&$øå—ƒ¾¾Þ::ŸœR©Q“2UÞ»œb>~üâÑ£nÞ<}îÜaC‡ú4nìzóæCBr¼°'âí]kúôþII)Ê‹»Dbvu-§­­¥³0xŠ\g€o¢mÛz ÅÁœ^µµµðõõ ‰32*Q¯žKjêå‘#uéâ¡­-ÍÊ’÷î=ÃÅÅa„îééo«Té±vm˜ÏÉ“—ÜÝmlÌs:\¨Be–il\"0°sHHœ‰IIwwçääT¾0‰R¡‚­¡¡þ¹s74¨¢|ˆJþðñcÖ«WoÌÍ´´¤ÊÛÕ[§²Qˆœ7œüs«ñÍš5+¨œSϩ̔)}.\¸åæ6lôè.Í›×666¸víþêÕ{6m:P»vE#£%J˵[rJQÔbQJ--ýüšÅšš–¬^Ý)995:z{xø`õ^0 uݺþ‰dáÂõ%^ÊÿÕ¼Ì\c¶´4¦”ÆÇ'•P(Û¶[° òîÝßâmdŒß}÷î“'Æ´n]7Û=•ÿkjZrØ0Ÿåff†Õª9&'§.]ºU=N€B 9ÆXLÌ8;»µÁÁËpøð…ýû·Êµ7æÎf`P|øð…ÏŸgÔ¬YaâÄžaaktuµ³  ðÁ¢L€|Qˆï„¦”°CÄaŒ]¾|·fÍA7on,]:?¾ÛëàÁ?ºu›vãÆ†œ¾4퇓•%spèÚoÀ€V…£EÊc¿þzÆÅÅAxnUTÔÖ‰£32vK¥Xâ PHQBû‡;OðËŠ:Ji¥Jv½{{-\øs>œFaŒÍ»)(¨W!Hcééo·m;°ˆ1Ò³g³½EÙ¢”nÞ|¸gϰӧ¯Þ¾ý8))eæÌµ~~Íùµ€¢×ò®3|÷22Þ¹»Û¾}–ð¨Ío1¶oßé9s6ìß?¿pœ¢~ñⵃCwSÓ’«VMâß Qøð/œž0!zûöc/_¾±±1÷õõîµI…®3| 9@~)¬iCaÉþƒœáS…á,|;ÈòK‘ü¢(3€ä 9@>Âò$ø!g€ —+ââv=ž‘ë£Ûž=K5*²lÙºº^¦¦>ÞÞã’“ScŒ1¡õ£vì8.‘4¹uëQž ÷êÕ›Š}¯]»ÏKNNõð%“É?«4ÆX¶ÁóWsêƘ|Þ"øê3ä/\j „Ïž÷÷ßÅ¿ !+KÖ¬ÙØ³g¯ÅÇݼ¹áС‡6m‚6o>L QŸv{yÕzð`³­­EÞ¾i16nܲ:9YSJ[¶t30(¹EóÒc2™<ÛàùåHPJ…àñ,løN g€o‚Ÿ,¿wï©úÄ—Òÿ¾FdZÌ;vìŸþµdI`£FUmlÌ«T)»`Áðzõ*/Y’¤|¬ú´[OO§T)S--i"gŒ?ÿצMÆŒéÊKfŒ…„ø†…­yõꆅPJ…à6¬ÂƒŸ?ß_=xõ‚/”ß© ?"ä ðõ)σÕ'¾Œ±víBcvv]¥RO~J~ÆŒµööÝtu½*Uò‹ÝÉ40(NIH8™)OI‰<|x¥ÔÇ'˜B©OQ&OŽ32jmbÒ62r _Þ÷¯[·¿Zµzz^®®üCXÚºÊƦ³žžWƒ³g¯çI!$"â—–-똛 Mps«dnn´bÅn —1ƄೲþYÔD)åÁB”{ೂçå‹ðÕ!gÈwE`y’ržíu†Õ«ƒ(¥gÎ,ð`3!$00rñâĈˆW¯®>¼C@@DdäBHÍšå h¾¡T©Ž]ºL]¼xËÕ«÷„b׬ æ…<|˜È7:tîØ±¨]»Âíí­”k\¼81:zìéÓ±úúz½{ÏT(!dÒ¤˜¨¨­‘‘£®\YÛ¥K“ÐÐx¾³\®HJJñô¬©’ù4mZ#1ñ°†K‰(¥5j8 Áwíʃ’•Ð|{{«ñã»éééF¦§¿U¯ZKKší„^"¡ÊÛù„ÆcŒ§*wTK$•ë R©”¥É­ÉŒ1ü”)~¼|{{« º‹ŸmÉ*5*¯Òcß®3À×—ëý Ê;¸¸8H$ôĉ‹ÂYóãÇ/XZ›˜ܹóxÞ¼M½P)¹xqÝâÅõ²ag{A}»«k9mm­'. ÓîÔÔKü%kk3BÈ“'/U®3aBBȤI½ õ=<7løíæÍ‡×¯ß_¶lÛ”)+&OöÓÑÑR.D¹pM¦Ý¦¦%‡ ó YÎ+‰Ù±téVB¥´B[CCýsçn¨d>çÏ߬Y³‚TªzýáÇÌG^ðsÿÊÛ…à7n<ÀƒŽÞ.¼† üöíÇy Á‹¼#y†µIßø£K[µrëÓg6!äúõõË–)Ujõˆ‹ž=K/_Þ6**pÀ€V”Ò2e,OŠ™3gChèªû÷ŸI¥W×rQQ£{ölJQ.dá¡ðœ*UÙ2wî0ƒâÇ/|þ<£fÍ 'ö [£««-•J:uj´wï)~6ù'ß û÷Ÿ1¢£ús“öï?Ý®]ÈÍ›ìí­„W)¥vvÙß«W³œ‚Ïé †úöœ‚×ìø…œ  ýèiÙ3ˆAÎð©ïåœ|Ÿ3€ä  wBÀ÷ 9ˆAÎðÀ¥øŽ!g€BbÇŽãI“{÷ž~•ÇÁ1Æ^½zS±¢ïµk÷yÉ·n=ÊCÉŒ1áðœö‘Ëqq»ž?Ï)_“r¾E½"%ß»÷´`#É›ÌLY›6“ôô¼<þ¯<÷ïpJ=(õHšèè4+S¦ÛСó_½zóÇØ×¥É§¬Ãä P(Ï3¾ÊwPJÇ[Ö¡CC''ë/)™RêåUëÁƒÍ¶¶ÙN†øtsðàyÿýQ¤|å—4™J~­z¿çHò€1vìØŸ»w§nÚ4uР¶ÂÆ<”£3¥´E‹:Å##·|nÆs˜É“ãÚµkpäÈâë××Çǽ}û·»û°£GÿÌ[lü‡ÔÔè‡<Øü×_W­š´gÏ©>}fÅ1ö1Æ„A’S„x4<@ÁBÎð}(tË“¾îYÿ\}õéNZÚÍM›ŒÓUycÞJÖÓÓ)UÊTKKšídˆÒÿ¾'Gü°ò!ùVï÷IPJß½û@©Y³|É’Å…y(G%fJiHˆoXØšôô·š·‚R:{öºS§®?¾tôèÎUª”µ³³ðô¬ž˜8½qc×I“bóÿÁÜÜÐÊʤT)Só&MªõÞµëäë×ïs:ð«'Þš£” ƒDdŸü T g€¯O|ò!,˜<9ÎȨµ‰IÛ[·ed¼ Œ,W®§®®—AËFF>œ&ì¹nÝþjÕèéy¹º8xð^NV–,8xy©R‹óöò{åÊ]¡ ™L>cÆZ{ûnºº^•*ùÅÆîä Hxi«Wï­^} žžW¹r=·lIÙµëdÕªýùžûöæ{FDüÒ²e33C•àÏœ¹fjêÓ¿ÿ™L®25Ìiq…°=Û¶0ÆÚµ aŒÙÙu•J=sšnŠ$Eß´^^rW{{º:ÿ#ÉÌ”MºÊÞ¾[ñâÍ==G/^¼%ÛÔ4§H(õhÛ6ˆ×¥\¬ú€^ÊidªÇìîîlnn´bÅnõ1ŸS<™™²ÈȤáÃÛ;8X©¼Å«VMÚ¹s62™|úô5Ýuu½œœzÍŸÿ³BñßxVïO¥öRá‡bÅtyÉ9µW9€±c—–.ÝIXj¥P°²e{L›¶Zäó˜Sjø¡Sú<§ù9Àw£]j?ë/¼zèйcÇ¢ví ···òó›uèй5k‚oÞÜpàÀBJiÇŽÿËÊúgʲxqbtôØÓ§cõõõz÷ž)—+c£FE®\¹;&fÜåËkZ·®;yò ¡ŠÀÀÈÅ‹#"F\½ºvøðK–$ ¯Î»1"bDZÚJ;;‹~ýÂCCWÅÄŒMK[accîç7S¡`r¹"))ÅÓ³&_v"xöìuoïqÝ»{ÆÅMJ%*ÍÌvq…zóUÚ¢P°Õ«ƒ(¥gÎ,ð`³& 3ò³^^]N]]‘,^¶l[DĈ‹ã½¼jÅ~V$&®YÌëR.Y}ÀDFnáÅæ42ÕcfŒ5mZ#1ñ°J“Eâ9þæ«Wo¼½k«´šRjeebllÀGà¨Q‘6ìŽ{ýúúY³…‡¯Ÿ>=^¤?Õ;?-íæœ9<=«ó«+Ù¶W9ìþý[=~ürïÞßyŽqðàwï>éׯe¶5òÏ£x™¹~è”›/þÛ røÊ Z´ìÖm!¤R%¿’%[´TÞA˜FûV®l_·neƈ§gøø zõ*ÛØ˜×®]1  Ã«Wož=Kç{†… pwwvqqð÷oÿèÑ‹çÏ3^¾|·köìÁ>>õìí­Fê4hPk¾ó³gÑÑÛgÏÜ®]}{{«€€Ƶ ß 0kÖàÆ]+T°2ÄçÍ›÷óæù»»;W¨`;p`›§OÓŸ>}uùòׯßW©âÀ'Lü(ž0ôïß2**P"¡ê“¼lW¨Ï€ÕÛbdT‚bnnXª”iN½šÓ,ü[×Kyñâ5ïê¶mëÚÛ[vº:Ÿ#yö,}ÅŠÝüup(Ô«{wÏÏŠÄÊÊD¨K©ØLûö ìí­†oÏ cL¡`9Lõ˜)¥..eÏž½®r J$>­*5Ô² IDAT¬L„ýG^Â?Aü߃ÏŸtuëV®XÑNøÐ {æúÛ „VA…ÍÙ³Ë !ž:t~ròOVV&„Ƙò2 þƒ““5ß.‘PÿvÛ·߸ñ·;wߺõøÂ…[„…BÁ÷tt´æ“*CC}BHV–ìÒ¥Û2™ÜÝÝ™—@)­_¿ÊÒ¥Û!.ÜR(Xݺ•…³¿õëW‰ŒÜ"Ì¥œËðÒôõõ!¥øžÅ‹ëBd2ùÇ/!ææFÊó]_ß™?f•)c¥Ü–\©ŸeWo‹òΟ{!ê=þ&ïjåþä]Ï‘\¸pK&“׫÷ß;ëéYcÕªd #Éi7aÀ(%>`ÌÌ ÅG¦rÌŒ1ssì,ÙÓ§éÖÖf¹Ã366 „¤§¿J êíïßžüû R(ii·årE›6“„àårŇ™÷ï?ãÿÍ©?wî çaèèh[ZëêjóDÚ«^ÿþ­‡_øòå©T’˜x$>~’ð’z×®Ý/ÓÙ¹ ¯]øÐñ„Ò{DrísÈȾ'|yÒ¾l×ÉɆ1Æ—¼ÛÛ[ÙÚZ¨ì L"…›b³²dM›Ž¹}ûq×®Õ‡ +sÿþ3_ß™Â!*çõ•fiD˜likÿó M˜[Ó^£DòÏ•U•eE”ªÎkù«‰Dy{ppï>ŶhQ§\¹Òyž¤ª·Edçl_Ò$iùŠõ ]-ô§ÐÕùÉ¿ûÿ‰®®¶æ‘ì¢4`„±$ ™L.>2•£”J¥RÞ@ {¦Z5GƒâüQ«VÞ" # #á$„—Z¾¼òá66æ/Þ"9÷g™2–¥Ô{@¤½Ê{víê1fÌ’„„R©T__Ïǧ¾ð’z¹–)•J>}£s|¯5ésÈÈàëŸàªÏoŽ¿xôèŸ'O.«S§"ß¶–O²'•Ù^Õªått´>W©’Ÿl¥¦^â/¹¸8H$ôĉ‹ÎÎeøÇ_°´4611È©4•ùÙÙ'O^*ÏÒzõjVª”éÖ­Gû÷Ÿsð`„D’dzì"µÓë y®Wèj¡?…®ÎçHªUsT‰ääÉ‹šG’Ón€Æ’0`Ž9ŸÓÈT™1öèÑ -•+T"ôôt:,Xðs·nMÊ”±TN?îÜy®\ÙžRz÷î“Ö­Ýy-k×îß³'•/4bȶül?}"íUÞ­D‰b=z4MH8 ­­åëë-¤gÙÖ¨a™"%4ùmù9|mÛÖS(fû’úô×ÒÒ˜RŸldTB¡PlÛvlÁ‚BÈ»w«ì)06.Ø9$$ÎĤ¤»»srr*_-ÃKóókkjZ²zu§ääÔèèíáვŸ¾T¨`kh¨îÜ ª(o×ÕÕŽ‹›Ð AÀÂ…¿Œ×M¥]>d¾zõÆÜÜHù:F¶sG•ü6'O^rww¶¶6òä%!D¤•‰à·®W¤«ó9#£ãÇw"Ù³ç”pk»&‘æ©"Fdd*ÇlccÎ'ÊçÏ߬Y³‚úCEâ™2¥Ï… ·Ü܆Ý¥yóÚÆÆ×®Ý_½zϦMj×®hdT¢D‰b¾¾^!!qFF%êÕsIM½‡«XÑnùòñ¿þz¦rå>MšÞºõðر(©T’šzYyO•9ǬYƒÇï>~ü² zoØðkhh_á¥eËÆ ÔfĈE*ô^ºtkTTàèÑ]TêUI]”_•J%:5Ú»÷”ÊvBˆ›[¥Ñ£»L™²òÒ¥;ÊÛcû÷Ÿ¶¶î|ïÞÓ\'©*µ»¹UjÕÊ­OŸÙ*ø^¾|ÇÚº³x9*Û¿i½¼ºœº:ÿ#™>½ÿÔ©}CB–W¨Ð{åÊÝ&ôÐ<’ó|ÁS(Øþý§;wn¬Òdñxtt´’’f,Z4âС?š5[¾|ï>}f½{÷÷¦MSŽ20(N)‰Ð!8x¹“S¯1c– ê³dI HæÚùÙ¶W%0JiÍšå+W¶¯QÉ_ëùåÔ‡êeæs… ¶¹þ6€üG³ýÄ@Aú±ni ”°CÄWÆ»|ùnÍšƒnÞÜXº´Ø“|¾…5köõí;ûéÓ­¦¦%5\âòC×û%‘ìØq¼]»;wø™þ|‹PcìСsݺM»qcƒðmq?4ƘL&wpèÚoàÀÖ@¾£?Òßâo×¾?EàRÃwŽRZ©’]ïÞ^ þœÏ'V>~Ìš7oSpp¯|ž¸T½_ÉçÞãñMQJçÎÝÔ«p$ ééo·o?°ˆ1Ò³g3œ^ÜÏ Jé¼yþîîÃnëèhoSR]]í'–/®›Ï“à‚ª÷K"¹Ç#ÿíÝûû‡™#Gv*ðH¾cL.WøúÎ45-¹~ýäbÅt~ôÀ—ÃÚ$€ïÒ´<©0®M€¢k“>…µIß%,O€ïrƒœà{…K ð}@Îb3€ä ß1,O€ïrƒœàû†K PÐ3€ä †2|-6À÷Òï÷ì±t ¥ïö/oAÐ*èà‡_©EÍ÷|¾ ¬Mñ„Šä ?ü…€‚ƒœ4#¬J‰ €"9À¡ `©ÜÆ€_JE rƒœr“í³’p© È@ÎðãÀŸg(È@”È2à\@Ñ€œà‡‚?ÏÏrý7ü^(3€­‚¾Wü‚&—r½?2Êð øáào3 ü (z°6 Ä gøáŽCÈGÈ@ rƒœàÇ„åI_3€ä 9À Ë“ _ g1È~d¸ÔßrƒœÄ gøÁay|cÈ@ r€.5À·„œÄ g1È ,O€o9ˆAÎPXàR|È@ rƒœ Áò$ø3€ä 9@á‚åIðµ!g1È \j€¯ 9ˆAÎb3FXž_rƒœ Â¥øJ3€ä 9@á…åIð5 g1È 5\j€/†œÄ g1È ;,O€/ƒœÄ g1ÈŠ,O€/€œÄ g(p©ò 9ˆAÎb3Xžy‚œÄ g(Jp©>rƒœÄ g(b°< >rƒœ èÁ¥øÈ@ rƒœ HÂò$ÐrƒœÄ g(ª°< 4ƒœÄ g(Âp©4€œÄ g1ÈŠ6,O€Ü g1ÈŠ<\jQZä!9d‡þÝâ-ØòÏÆ@(Ãï€"‚ÒÿæˆÊ>+g  @QƒµI 9@‘‡ë 9@‘…I'È@ r€"\QÈŠ á ›Ÿ9ˆAÎPt1Æ>|Èœ7/¡FAÅŠy´lØpÄ–-)_¥d¹\·ëùóŒ//Û±ã¸DÒäÞ½§~³ߟR៮®—½}·1c¢Þ¾ý›1Æw¸uëQÞâùå—C*åóuëú+ž߃”í›øyõâ¹I ß Pd|úÜ$ÆØë×ï½½Çýý÷ÇÐÐ~5j8½ÿqíÚ½]ºL3gȸqݾ¤*JiròÉÁƒç5o^›1F¿x¹¼ò X“Ò„ýSS£mmÍùÏ>dž}ú‡îºº^NN½æÏÿY¡`Œ±íÛK$M–/ßÉó„ÐÐU%J´¸xñ¶O0cÌή+¥Œ±œçkxÖ­Û_­Ú==/W×þÁkÌÊ’//Uªc±bÞ^^c¯\¹+³nÝ~—¾::ͬ¬: ðSzú[•hsº.Á“H$ S(;wžàˇDbË¡¡«ll:ëéy5h0{özõõQêq »Ž×»zõÞêÕêéy•+×sË–”]»NV­Ú_W׫R%¿}ûN E1Æž=KŸ9s]¹r="êÕs!„¼}û7…„ï)¼‰„zõ\"Ê•ë9{ö†—Š!—QÈŠŒOŸ›tþü_?fÕ­[YeÊknnT¯^e-•©ö¨Q‘6ìŽ{ýúúY³…‡¯Ÿ>=žRêãSoèPŸñã—Ý»÷ìÈ‘ó3f¬]´hdåÊökÖSJÏœYþða"!$ÛÃ…ò/NŒŽ{út¬¾¾^ïÞ3år¯qåÊÝ11ã._^ÓºuÝÉ“Wð¯_зïì.]<®__¿yóô_=«Ò •àù2™üСsaa«½¼j)O²Eb˜4)&*jkdä¨+WÖvéÒ$44ž¨Q¿s@%ñ¶Ï»1"bDZÚJ;;‹~ýÂCCWÅÄŒMK[accîç7“gçÎÝ4hn™2ݶnM íw÷îÏsæ ¡” o¢J£ü&†‡¾{÷çÐÐ~IIGììºøÓ¹s7Ô[ k“ЍŒŒw„cã¹.žaŒ=}š»cÿþùÕ!¶¶æ¾øßÿVûjkKçÍó?tèÜÀ?]»v¯G¦´"„• ÿ. oÜØ•Rjgg!Ϋ àîîLñ÷oïç7ëùó --i\Ü®˜˜±>>õ!£FuºqãþÒ¥Û!Ož¼T(XéÒf66ævvÛ·Ï¢”ª´B˜CW©ÒOØþáC¦¡¡~Û¶õ~úi¨z3ÕcÐÕÕŽŒÜ²dI`‡ !#Gv¼qã~TÔVå£j×¢Ò{Ë—ïÖ­‰ðß\Û>kÖàÆ] !C†øôì6ož?càÀ6=zLúô•••Iƒìí­öí›× Aå6 o¢È;H)-VL·ÿ–ýúµ8zôÏ>}f¯\™¬PÌiuÈŠ(33CBÈ‹¯œlÄ÷¤”¦¥Ý”ËmÚLæ¦r¹âÇÌû÷Ÿ98X+¦³nÝä:u†”.m¶téhõóî"‡óÿ::Zó£øéÿ¬,Ù¥K·e2¹»»3O(¥õëWá9C½z.;72d~HH\³f5}|êwêÔ(§ë ;w†[[›Édòß~;ëí];*jt±b:êÍTáÊ•»™™²úõ]„6tUÉÃÊ–-¥¼ÅÊÊä³Úîì\†×«¯¯Gqp(Å÷,^\—"“É !S¦øÅÄìèÝ{Æ!>¶633äño¢£c.‰ß³géqq»¢£·gffM™â§ú2ž›¢3Ÿ>7©J‡âÅuOœ¸èæVIyºùðá‹^½Â¦Mëß°a¾1¦P(! ¡åË’`ØØ˜ó}Μ¹*‘H=zqî܆ «ªÔ,røÅ‹·! Íö.gƈƒ¶ö?³¤RÉÏ?‡^ºtg÷î“¿ývÆÏoÖÊ•»÷î›íu†2e,JB*V´+_Þ¶M›I?f%&NWïõø|]9õtÈÎÎB=éRÞ-×¶K¥åz)U]ìD) í7iR¯M›DFn [Ó£GÓáÃ;T¯î(¼‰üÒ„Pû£G/…7ñìÙëQQI›6¨T©Ì´iýzôhª£ƒ¿þðyp?@U¬˜®¯¯÷Ò¥[ß¼ù[ùFÛ Ž»`mm¦|ctåÊö”Ò»wŸ8:Z;9Ù89Ùœ8qiêÔUü«WïÚ¯k×&~~³øÉÊó`áp~¬££µp¸@eF^µj9­Ã‡Ïñ”ÒÔÔKü¥#GÎ:ßÑÑzܸnÉÉ?-^<ò×_ϼ|ùFä¾g¾ÅË«æôéý“’RøÛê}¢ƒ«k9mm­'.ªÇ r”Ê–/l;¿† R¾žžNß¾-Μ‰MNþ)#ã­›ÛP¾‘¿‰¯_¿W>\x !îîÃ^¿~·gÏÜÓ§cúöm¡««§'À癀"Š16cÆÀC‡Î5j4bÊ”¾µjUxùòõÊ•»—,Iš3gH¹r¥•w¶µµðõõ ‰32*Q¯žKjêå‘#uéâ¡­-ÍÊ’÷î=ÃÅÅa„îééo«Té±vmH±bº„“'/¹»;ÛØ˜çt¸P…ÊDÖØ¸D``ç8“’îîÎÉÉ©|a!¤D‰bqq» 6fL׬,Ù¶mG+V´366Èö:ƒrÉ”Òñã»ïÞ}râĘ֭ëª÷‰J ¦¦%‡ ó YnffX­šcrrêÒ¥[Uv{þ<ãñã—*åðqyh»úuåÿ6nìÚ¨QÕ;wžðí"o"_4uýúz{{+õƪ´Ë“@r€"ƒz(/O¢”š˜;5{öºI“bîÜy¢££U£FùÄÄéü–_eŒ±˜˜qvvkƒƒ—?xðÜÂÂhèPŸiÓúB¦LYqñâí³g—kiIÍÌ ££Çvè0¹yó::4lÕÊ­OŸÙ„ë××çt¸r*•Κ5ØÐ°ÄøñËž>}U§N¥Ðо'ÆBªWw\·nò¬Yë\]/®ëéYcçÎp‰Dì¹IÂ¥RÉŠªW8|øÂþý[©7SeËܹà Š¾ðùóŒš5+LœØ3,l®îßÚÖ¨ÑHÕn¦4#c—ò–Ïm»z ¡~·†˜š–ÌöMlß¾?*÷„ 74¾Ó¾ ”ªÜÒ¹Ú¿ÿ´‹‹ÿê7ÆØÒ¥Û&NŒÎÈØ-•®Å½Ôã3®3à¢@ÑS¸~å|=Œ±Í›÷ìöûïWnß~¼uëÑ™3×úù5/l Ás“ ¸ÎPt.è~<ééo'LˆÞ¾ýØË—ollÌ}}½ƒƒ{«|á]¡Ðø3öÅu€¢9@Ñœr‚œÄº««ð¹ ÛeøÊ´ðk Á=Ððù´ÁŸ€¢ztðCÂÚ$€"÷'€(ä E®*@žà{ ¡`0Æöîý="â—S§®¼yóÞØØÀÍ­Ò¸qÝ7výÂ’££·¯\¹ûòå;™™2[[sŸú“'û—ÐäÁˆ”zBNŠ®U«BÞ¤(^‚&å3ƤROþ@3J©¶¶–±q‰–-Ý""F”,Y\<*~,!$5uYíÚóÿ×¢y$BŸlÀE‹°BIH!Šæþ-fÂgJ8Ñ^”·ä9ÆØôékBCWBªWw²´4>þ¯]»NîÙsjÓ¦©:5ÊsÉaak¦N]%•JêÔ©dl\âìÙë›SRÎ?¥¥%ÍuÂ-ì·„A¼ ˧ôŸ' {xT34ÔÏÈxwüøÅÕ«÷¾zõfëÖ™âǪT—ÿ(¥íÚÕ'„ˆDR°A]êWŠôµérQÞä PøcÚ´x==¤¤Í›×&„dfÊúöpp̘¨J$yœ²GFn!„lÞ„µk÷Éå BÈ¡CçnÝzTº´i›6u !‹'N›ÿüyFóæµíì,NŸ¾Ú±ãÿ^¿~Oþå:_.WT­ZîÆƒÍ]»vŸJù))ª7ðÂ…[*Óhþþ}§)¥R©ÄÚÚŒ’–vS½ 7P9vÀ€Ö„„„ƒr¹‚1öÛogŸ?Ï(SÆÒÓ³†g¶}¨IùC‡Î×Ò’ê_¸pËÓstXؚʕí ÅŽÇCCãÕ“\{,¿†är(ééo !††ú|¾8lØ~NZ83º*+K7þèÑ%‡/Z±bâû÷gÍZ§< ì|èPÄþýócoÞ¼ÿ믇„)SúFE®XÑŽòìYúÖ­Gýý:;û Óñ‰cþþûcŸ>ÍÏ[qøð¢ˆˆŒ±±c£d2ù§×Ümm->|±ÿiBÈêÕ{!´ÖÖÖ¢”ÖªU!<|Èþýówì˜}äÈbBȇ™·o?&ÿÎòGŽìtâÄÒÔÔeþþí!›U¦ÑBSR"ŠÈwà;O˜Ý¡ÃdQ]ºL%„têÔØÌÌR*4á?⊚ÀÓa Þª•›µµÙãÇ/8Kùå—C„>}šói¼HjRþ„ =~ûmALÌ8BHFÆ»„„©ûöÍ›0¡!äܹÊ­àïx®=–?ò933CBÈÓ§é|¾Xµj¹öí´oß@˜>ž:u™Ò¿ÿžEôí;›räÈyåɨ§gMBˆ££5ßøñc¥T"¡þþí._^sýúúU«&õëײxq݇_,⻥¤œ'„øù5ç…ôëׂ1öøñËë×ï¥ ·T*8°5!dÍš½oÞü˜xX"¡ýû·â¯6lXµjÕ²6ìoÔh¤ƒCw~Tff–PBûö ø:5&„\ºt[e}êÔeÆXÿþsø¡¾}g3ÆŽ9/¤„C‡ÎmÛvìøñ‹ff†C‡ú¬X1¿*4—Ù¯_ BÈ“'¯x„>”J%ýúµ$„lÚt 3S–””B)õók!Þ‡„MÊoÒ¤:!¤T)S^NÓ¦5!––&„ÌÌ,õ«%¹öX¾Œ;È#Ü  aê›7Þ³'µmÛº”ÒaÃÚ ÖŽüûØMBˆBÁ!»Gikk±WíBŠÓ¡”jiIÙ¿KÿOº2~BV–lË–°råJ—+Wºoß>>õ;vüßéÓWùnÂÝÕ¼ƈ0¯%ŸÞ7Ô°|]]mB¥ÿlÔÓÓ!JmT‰„16zôñ€ï®3@1¢#!$.n×–-)ü4³\®ˆÝ)œ™®Y³~l|üBHéÒ¦NN6äÓsÞVVá#Jœ IDAT&íÛ7øûïS¦¬$„ ÔV˜ ÇÅí"„„†öã·Oü‹%lÜø+ÿaëÖBˆ««£JäB“’f$%ͨ~†^¥ëcBønññ{(¥ÖÖf¼ ÊÇ:8”jÖ¬fFÆ»1c¢!}ú´fÿ9õ!!DÃò…x˜Ú}Ìêsí±¼&øöp @ƒU¦Më7eÊÊΧ¸º–³¶6?þæƒÏ !VV&––&ÁÁ½Û¶ ^ž˜xØÐPÿðá4¹\±lÙ•³õ*ç³Ë–-5rdÇE‹‡¿lÙV[[‹¿þzxéÒJiXؾÛÌ™›4 Œßsöì5#£))J$táÂ~r]¥ä!C|~ùåPzú[óV­Ü„y°å•+wûö]½ºSJÊy©T¢P0~“?0!áà™3׊Óåw{ÛM%òœ¨~†^%m ”æÔ©T¢r,!dÀ€Öûöý~ÿþ³’%õ;wn,”ŸSŠt‘Jù9žíÆ\{ ¾g¸Î€R:y²ïþýó}|êóûŒ33eÍšÕŒˆqõêZ[[ó-êìÚ5§Q£ªW¯ÞKIù³reû•+'ÜFü:!dþüá11cëÖ­ü×_vï>ùøñËfÍjîÞ=§GO¾›»»óÑ£KÚ¶­wïÞ³S§®Ô«Wy÷îŸødZ¥dBˆ§gu~;õ€­¤R‰0^»6¤V­ ï.\¸5ujߎBRRÒ„–.mh¨öì5''›5k‚;th R~¶ 2¤-ùô‘¬ÙΧëÖ­¬Þ„.]<Ô¥”¶kWŸß9ݵ«‡¾¾žÐÿ9õ!¥TÃò9 ¯3äÚc_e\À7BÉî{1àÇÇ»sçIÅŠ¾™™²#Gׯúÿ¡ø"ä<¢]PÔ`m@átô蟑‘[RRÎgfÊêÔ©ˆ„ò 9@!ÄÓÖÖÚ¹óc¬Y³šÂy€µIP$amRžam@у{ @ ʼn(¢p²wîÆ„ =—,ehXâÆQQIîîÃöîÛ A•Ï}ë[Äü…c^^µ<Ølnn”k»È¿¡Ž·¬C‡†åËÛä¹Þ³DLÆUóPfV–,§Ó¹scÍ[§9‘c5yOùFJéÉ“ËÔ̶m3¿EÌ_ˆR* ñv©lÚHùð!óäÉKKžÈ>g`ŒíÜy¢]»;wlm-Ôw ”Ξ½îÔ©+§OÇ:8Xñ?ÛvvžžÕ[¶œ0iRì±cK>7Jé±cþüó¯?þˆ«Zµ,¥ÔÆÆ|þ|ÿß¿²dIÒ÷<$„˜›ZY™ðÿZ[›õö÷_øúõû’%‹õ˜¿¥TOO§T)Sñ}„ŸcçÏÿµiÓÛ·7å9½aŒ ¦lÙR|£E“&ÕZµš8iRìÑ£‘yxï„ãêZŽbcc¾`Áp>`¾ó$ÓÜÜPx llÌù€yóæoƒb¹NÊó9É$„ä:`²½\ ÜFBˆ½½UzúÛ#-[6¦dÉâ⊣”†„ø¶j5±oßFF%6|kÙ¯MÊi&$ÈÌ”EF& Þ^H„W­š´sçl¾ E&“OŸ¾ÆÁ¡»®®—“S¯ùóV(˜°2aݺýÕª ÐÓórupðàŒ1ƒâ„„„YYr^/¥4%%òðáE¼™L>cÆZ{ûnºº^•*ùÅÆîT‰vðày..}…˜?~Ì23ó™3g#c,#ã]``d¹r=uu½ Z6j4òðá4áÀ½{¯Zµ¿žžWÅŠ¾QQ[yüÊMΩ-êF)-VL—÷ïñ˜ÇŽ]Zºt'a¡…BÁÊ–í1mÚêl{IF½Lòïò•Õ«÷V¯>POÏ«\¹ž[¶¤ìÚu²jÕþ|Ï}ûN«¬ ɶ[TÚñKË–uÌÌ …*&OŽ32jmbÒVyyIN‹XcYYr>`„„Aè+>`„÷WóCLf¦L(“òï•+•ŽRyg‡ ™ïâÒWˆ3×#»wïï®®„CÔ>5Ù¶E¥[„„“훫ó¸qËø€áÛÅLNƒoÿZ†ä@å"‘H ¦P(„Eb–Ë¡¡«ll:ëéy5h0{öz‰¤É½{Oy™îîÎææF+VìF²ÏÄϘ2ÆÎŸ¿ùêÕoïÚêçæ­¬LŒ (¥”ÒQ£"7lØ=öúõõ³f _?}z¼°óâʼnÑÑcOŸŽÕ××ëÝ{¦BÁjÔp0 Uxø†R¥:víºxñ–«Wï)O­#/NŒˆqõêÚáÃ;DDFnQ޶_¿–—.Ý9{ö:ŸvìÜyâõë÷~~Þ„?¿Y‡[³&øæÍ ,¤”vìø¿¬¬fêAA±“&õºzuݨQÇŒ‰â³@eâmQî´´´›sælðô¬Î/2äsÿþ­?~¹wïï<æƒÿ¸{÷I¿~-³í%¹\‘k?Ì»1"bDZÚJ;;‹~ýÂCCWÅÄŒMK[accîç7Seæ*Þ-„¹\‘””âéY“¿§|ã¡C王ڵ+ÜÞÞJ9YâkNlm-T†0`ÔSP>`x~É€éÒe*0ÊõªwÔ’%IʵósæÌ5¾žÌ’%I*MËuÀð~ã—qø€14Ô×$faÀðwD|Àð·[¼Ì¯;`²m£L&?xð°°Õ^^µ õUvË6æI“b¢¢¶FFŽºrem—.MBCãUÊlÚ´Fbâá|¾» hÊfm’AKBˆ\® „TªäÇÿB¿~½[yjøìY:!ÄÊÊDX&1zô’¸¸]B!W®¬ÕÒ’ÆÆîØ¿~ãÆ®”R;;‹‡_üï+‚ƒ}ù>aaÜÝ !þþíýüf=žaaa;®{÷¦¿ürð×_ÏlÞ|˜âåUkåʉÖÖfÏžeDGo‰×¾}BÈðáí¯_¿¾!  ƒP¯»»³³s™õë÷׬Yž²víÞV­Ü¬¬L#žž57v­VÍ‘bmmС[·i¼!„™3õèáI)6¬Ýµk÷æÏO>¼½PìÓ§éâm©R¥,™BÁ¼¼jÅÆŽ#„h³³s™zõ*¯Y³·ukwBÈêÕ{¼½kÛÚš§¥Ýȶ—(¥âeΚ5¸Q£ª„!C|zö ›7Ï¿nÝÊ„Ûôè1ýéÓWBÕB·¸º–ã‹ÁTº…rùòׯßW©â <9 ö­\Ù^}ðd»ˆ…1& aÂ7fLTNÆÃ£!ÄÖÖ\}À¸¹URî KKãåËÇ &1ñ!¤Y³š*¦]»ú”Ò€€"¦F §lLN=3sæ ž=›B†õ09µ%ÛÃÓ$faÀ´jå–í€Qé%aÀäTæ¬Yƒ7vU0|ȉ ˜œ>GÊ„6B>|È44ÔoÛ¶ÞO? UßS=f]]íÈÈ-K–¶o߀R:jT§7îóLžÿΡ”º¸”]±b·L&×ÖÎã}Y ¡lþÖž=»œrð๡Cç''ÿdeeBÔÖ]ðÃééo…)`PPoÿö …"-í¶\®hÓf’p¬\®øð!óþýgü¿ŽŽÖ|ÊÏ;feÉøžM›ÖhÚ´cìÎ'?ÿ|(,lu÷îÓRR"/\¸¥P°ºu+ “†úõ«DFnyþMç= ßN69ƒ““ !äÊ•»„{{+sõHÕª9?pàZµ*ði“……‘……cŒHþF$$„ª~ÌÚ¼yšúžê1óD…1Õ˜•[!•Jù±ÙÖ_Q^îg „èéétX°àç;wž¨ì|çÎþsåÊö”Ò»wŸ89Ù89Ù8:ZŸ8qiêÔU*)~çÎãyó6=~üRy~@)^\·xq=‰„ž8q‘ý{{ôñã,-ML ”°´4nÓ¦nBÂóók®­­E)=~üâÑ£nÞ<}îÜaC‡ú4nìzóæCBˆPù©SW„)àÑ£çœl”W]kØ•^¢”js‰Åzôhšpà—_úúz —)²í% Ë)A t˼yþC‡ú4jTU¥[!ü$î“'/ÕËT/0[”R]]m>`nß~¬ü¿šÄ:ÙÑÑš÷³z'«ÄÀÌ£G/”w jFxgÕ;Šbaa¤<`øÔ?מ9uêŠÐÿ"F¼-*ÅÓ0f}}=壣óIò¯ÒKš”©2BTJäú9R!âí]kúôþII)Ê ÒDbvu-§­­¥sjê%å2c½ÐÑÑ277ʾnøz²_L)mÛ¶žBq0§ÃcS¦ô¹pá–›Û°Ñ£»4o^ÛØØàÚµû«WïÙ´é@íÚŒJ”(QÌ××+$$ÎȨD½z.©©—GŽ\Ô¥‹‡¶¶T¹"åb'MêµcÇqÀ©Sûº¹UR(¿þzfÊ”“'ûéêj[Y™øù5 Š55-Y½ºSrrjtôöððÁ*Búömѫ׌wï>ÄÇOâ[,-)¥ññÉFF% ŶmÇ,H „¼{÷7?0((ÖØ¸D•*e·n=³#>>H¹XóÏm §yÌ´®[×_"‘,\ 2W)ÙÒÒXÃ2ÅcÓ¤[!*ØêŸ;w£Aƒ*âe2Æ>~Ìzõê¹¹‘òIw¾óW0*í0::Zšto…ò€á[òaÀ¨/î⯆1+•rTzIó2s*A¹¨\ŒJ9Âüøî»wŸœ81¦uëºÙî©ü_SӒÆù„„,733¬VÍ199uéÒ& ×Ο¿Y³f•‘ßB樂êèh%%ÍøùçƒññÉsçnz󿽩iI7·J›þÏÞ™ÇÕ”ÿüó¹·º•öº-ÓŽ¨”"¦ì‘2… ¢P†´Œ-´X²×([E £…²diÒŒBdÉX!“,¡ƒºÝÏïÏ8ß3çÞ{î-3Ão|žþ¸ûù¼Ïûýþ¼î½ŸÏ9ïsNÎÒ1cr¹@JJ˜‰IVddÚ£GÏuu5=—/÷§ÛaLLLt/\H‰ÍŽŽÞQSSÇårìì:%%Í4i(n¼uë<ƒŒÐÐMuu ]º'%Í ð`8pwwTSSîÞ½£¥¥ ÞÒµ«qZÚ‚˜˜]iiGttÔ½¼ú•”$ÙÛ”–ÞÒÖV,Yâ·`ÁÖû÷ŸXZšìÚµXôîþ²Ä"v-£Ï]ºu3SRâáCÔ,YÈh“ÅFjZ\.çÛo^ Ã/„°¨¨ÌË+ªª*[´ð†Ç“g ®0‘šd†MI‚ññqÁ-E5}úpÑÌP‚±²2ÅÛ--MÚ$˜±c1rÛÖX¨²ø !ìÕ«+Œ9øë‹Z–1ì¾Ù#Ö„ÃÛ·/ìÑczpðI-)Ö­›¥ªª¼áùóF‡®‹ù¬\™I‚ QQQYhèÙ¯«!Ðn  “ŸÚ/\Àmn>!:zc2÷ÉAݺõÐÁỪªÝ_}Õþçpþ^ZZX0ÿ½I3BèçŸ/ÙØ˜S÷ÚJJ:¸hQrcã1¼¼A[[mÇŽpüü‡Oí”ß89ÍÊÏ_CÝ“ð©xñâ%üü‡ÿ¡ÆÆ7 &çç—¼|ÙddÄ÷õu‹ŒœÌãÉ /ÆÆfÅ3î*F ´ rž¡Ýó —Y3á‹„¬Ú Y3_¤6‰@ @ °AÖ @  ²f @ l5@ @`ƒ¬@ í_3àÇmÛvtРٚš#xÆçGö¸p„P}}“¥¥oeeÍÇìW’`>ƦXÁHU ,hk_YÆ·ÁjÁtÁüs> ²ÇE¹Çˆ‘ÃÌ㹚™yÏ›—ôúõ[Fã3Yx÷®9..·gÏï””ÜTUÝ Ý¿ÿô¿à'BhïÞ“ô¼QÙëÓ'¨}6‡gié+º}ÇŽ.wHUUm›âBµ¶ ·m;úüyc[=)((uvž-´~†#N Yk_7„Ps³ÀË+òêÕ» ú$&ÎVWW¹{÷QRÒ'§Y……ëú÷·më}Óñ"dèÐùjjÊéé;Ô×7íØQ0bDDNÎÒqãœ%u¤ï!Ô¦ý²ô¥ÿ¶I²Iµ)-M66æZ[…••5þþ1µµ/òó×ü>$!W×^íãó5¤Æ>¸¶uôè]ºµ{¿ïß·°fÀ€îí°ÙÒ"$˜±cÉì°ô•eLñFáùó[EsèÐêÂçBH †=.Æ*FÀ»wÍçÏßœ3'ñéÓú;£¤*ðSÑØøÆÍ-ìíÛ÷ÑÑÓzö´øã÷YY…ãÆ-‹9þøÔ[J§NmêÜÙþ–‚‚|;¾%BÃ'MZuîÜ>}ºÑ·gdü4t¨CÇŽmý¶,(8?cFܰa½Ûê»»ã–-öÏ;® 1á³Aüš!täÈ9/¯¨êê\cc]ѵkw^¸PQV–jn®_##>LSÓ[UU%©“òy‘ *±é1ÌÌô^‡†nÚºužšš2»ÁOBhÑ¢ä—/_••¥ª«wÀ×®ÑÜ,X¼x›·÷`##þ?—y*‡::êKr „£GÐÖVÛµ«ÈÉÉ{Žªªª=}ú·œœ¥íøÄQN¶£oT”¯‡Ç¢©S¿ÑÔTmS_@ |ˆ¯M’4¢hn$$E-¨Æ;v„9²ÿº­+Vdš›Oàñ\-,&ÅÇï U™°sg‘½}€¢¢«]@qñ„ªª2 7÷DKËŸ§°!„§O'œ:µ ïE h]µ*ËÌÌ›Çsµ²òKM=ÂðvÆŒ8›©”Ïïß·èèxÆÆîÆ•3'¡S'ÏUUÕ}àÀïO*§:^ìÞÝ_QÑÕÒÒ7)é ý×#)ѤA•”xàÃO¬TŸçÏßòÕWß ­ø_¡uì8qùò ±Y¢œµ >”¯ddöè1]QѵS'ŸýûO=z¾{wÜòøñ2FeˆØ´0b߸q¯»û×::êÔ./Þ¦¡1\Kk$½¼DR B¨¥¥ †Z0P¹Â‚¡ÆWvÁ(Á47 (›X0àÙ+F¢#;sf¼ÍTÊO©‚¡ú^´³  D>5bca¤…zA Fìà2| ÛŠƒ·³ F’ñö¿K0@Œ‡Ã ‘P(¤ ²øÜÚ*ŒŽÞad4VQѵÿµkwq8ƒÿýKq >ÿ½תYYùedÊXB†zýúmFFaHÈjÁ€·‡‡ûœ8±QOO‹}¢,õ+#©ÐKê·n~þYgpZÚŸc½CEå›ë×ïcƒ™™Çmm§ñx®:ùlÙr[PTTðó–›[ÜÜ, ¾Q33 uu5¼¼ú³|E‹Í$ÀÓ3!db2Bg©º¢K­ø|íÛ±Œ @ >[įؘ"„®]«ª¯orsë-zl^__KSSB!œ=;!;»(9yþ;»Ö¬ù.&f׊éTãÍ›ó’“ç—•¥vè 8yòj¡õìià“m`0füøèÍ›÷ß¾ý;}j5gNÂæÍy7†Þ¾<:$dcBÂ~º·Ó¦¹ß¼Y}ùòüÓuäȹW¯þðósøù­9yòjffdUUö‰ „cÆ,iiùs¦‘>éöí³g7/ Ïé°ÇBOZyyUllö!=ðI©>ûû{}±„kNŒu¢#:]À‚Á üÁŒ· †¾_ÑD%& ï æÒ¥Jܾ݂IL<ÀMª`¨ã¾×®ÝÂQWï ‹Ï”`ðˆ° 7»Í¿W0bcZ‹‹¯¬\™áêÚ‹>#gñ9<<%)é`BÂ슊¬qãGG§ÓmJÚ]pð†ääüøø ŠŠÌ€€áþþ±?ýt¡FÉ*½÷þ}KŸ>ÝÛù|¾}»)(°UrJR¯¨·b÷d8OåéÙ70ÐsÁ‚­¿ÿ^÷ë¯×V­ÊÚ´éûnÝÌð»sç&Οï}ûvVX˜÷ܹ‰ÉÉùøûÄßßãÅ‹WÇŽÇ6[[……S§~#/ÏTŠu%6“™™‘ÂK—Òjkó€4]1¾% „..=óòN}ni@1¿‚ªªî€ÖV!ÀÊÊ¿¿zuŒ>5¬«kèëk¡esç&nÛv”2RQ‘%'ÇMM=\T?h„ÐÄD·¶öÅ’%Û##ÿ¼&oåÊ''k@PÐ(?¿5ÏŸ7êêj¤¦†M˜à²woñÏ?_Ú·ïÀÕµ×?.24Ô©«kLNÎOI 5ª? 8xÔ;511Ù!!£©ý:9Y[[›îÚUäàЕUèáᨯ¯…2¤ç Avöö††:!!£½½—ã@«W7qâá¬Y^••¿ÇÇç¢Ì>{ÖÀ‹­í4œ‡–Pˆ\]{¥¦†dñÙÚÚ´oßn™™…Ç;22~rsëmlÌ//¿+6KBv›kÖÌ8°;`æLOŸ•qqA¸šyúô'®xö¬žÚ5•;»N¸Œ‘À­[Õ¯^ýakkNŸÓDFúR“:b‹XB”`¨Iä¼yI’ãìl06æ‹ ÆÑÑŠž ==Í´´”`òò~ êÀŒ—W?aHÈhÁôìi!V0’2³zõw>>.€À@OÁHŠE¬`B²øL ÆÃÃQ¬`Y¢#Éæš53 ²£ KŽE0’>Gt¨ïÞ5««w9²ï?жõ™Ç“OHØŸ˜8gÔ¨þÂÙ³¿½{·¯ä‘äÒ¬ºº†ôôÁ’³ IDATŸRSÃp¯°0ïæfBÌ)¸$•66¾hjª´£ð†eÄ‹ I…^ÔN{÷žÉp -m·÷`@\\ÐÉ“W§Oÿ¡²ò÷‰]<¨6QQ¾S¦ £¾ÁâârgÍòX[›öëg³sgþºøå—Ë55uëJ_‹Í¤†† øPŠ)U«Œo „MÇíÛµ´äåÛy)@ >b¾¸/_N_ Œ/(øA__ ˆœ7dž^SSÀˆˆÉAA£¨ŽB¡°¼üAk«pĈpªok«ðݻ暚:üoçΆxŠ;¶´pK—ž..=BÕÕO÷ì9¹reÆ„ ËOŸN¸~ý¾PˆðQ@|Ôª_?Û„„ýŒ›xLêŸûÃ/_6\ÈÍ]€yåçŸÝ½û—êê'÷ï?¹~ý>@(â^ÎÎöT,}úØlÚ”÷âÅ+Êfyy{,GŽÄêäõô4yã… BLŸäó B|v”¥ ![[seeÞ¹s7ðijûãÇ/'MZ¹|¹?>}'¶/ˈËèå°‰‰.µˆmséÒm‡óøñ‹«WïÒï6&//'ú †_Œçwè H £ú…‘%Yl2°@!õsÄ€2âæÖkÅ ÿNÓ ÒX|¶³ë$//G÷¹´ô¦¤¼Q!à´_¼x›ê5vìÒ   ²hB¨¨¨àëë¶eËÁW¯þ o_¿>·¤äº¡¡Ž$;BYFœ©ßº€Û·Ÿ7/):zÚøñƒýüÖàwø­óçoRQ—”üfeeª¢¢„³ª¬Ì›4ihNÎ/{öœTSSÆåFì>KÊd;tEêñã r|¾†ìi!Âg‚ø¢RáÈ‘}…ÂbIÝBK—N¹~ý¾£ã¬¹sÇ Ö[SSµ²²&#ã§œœ½{[jh¨¨¨(ùúºFEmÓÐPéÛצ´ôÖ÷ßo7Î_{Gíˆn6<|ÒáÃgç,[6ÕÑÑJ(þüó¥¥K·/^ìÇãÉëëkùù ‹ˆHÕÖVëÑâ  499?&fÃ1ÀÔ©ßLš´êÍ›wééáx‹žž&„0=½@CCE(:T²~}.àÍ›·¸cDDª¦¦Š­mǃϤ¤NO ›52â·5Œì> ïÓ'ˆÃálؘš0,ëéiÊh“Ý7YÒèÚÕX]½ÃÕ«wû÷·e·‰zÿ¾¥¾¾‰Ï× tÇÿÁ0âbŒ‚‚œ,‰ÂQЃ·ü ‚=ŽW¼2úL Ã#K²Û”dnJª`v¨ 傎;¿hQÊðá}ͤÿ«­­6k–gTTšŽŽº½}ç‚‚Ò-[þ,L ÑÓ§/|¾ý „P__Ë××5""UGGÝÊÊäС’ƒÏ9ÃX벨tÕªé'O^80téÒ©½zu}ùòÕ?KL<;³cG„À“'–ê1úëJqÌ»wÍ’öŽ_<ÞH_ȼ–@Ð:yò*ó… '44¼¶µ²1++ 7OÑÒR³³ë”Ÿ_’’r8##‚ž™€€á½{Ï|ýúíÔ©ßP+LŸ%e_‡pþüM''k##~›t…ºv­ÊÁ¡+—Ûþg‰áSÑÎ Ñ „ r¬Ú³§8=½`ݺœ¦¦?´µÕ­rr–Ž3ÿ*¤¤„™˜dEF¦=zô\WW#0ÐsùrºÆDÁÄD÷Â…”ØØìèè55u\.ÇήSRÒÜI“†âÆ[·Î30È ÝTW×Ð¥‹qRÒúU€àÃO”»»£ššr÷î--Mð–®]ÓÒÄÄìJK;¢££îåÕ¯¤$ÉÞ> ´ô–¶¶`É¿ ¶Þ¿ÿÄÒÒd׮Ţw÷—%±Óh}vpèÒ­›™’ácÉ@F›,0RÓàr9ß~;°°ðBhèöx!„EEe^^QUUÙ¢…7<ž<‹`p¹‚Ô$3lJŒ n)š¨éÓ‡‹f†Œ••)ÞniiÒ&ÁŒ;ˆ‘Û¶ÆBm”Åga¯^]±`llÌ´£Ô2æÝ7 ›`ÄÚr8`ûö…=zLÞàïï!©%źu³TU•ƒƒ7<ÞèàÐuÑ"Ÿ•+3y<ùÆÆ×††cUUÙŒ‚@aròüåËÓgÎŒ{ú´¾K£;óÍ׌6,*ÕÖV+)IZ»vgxxJuõS¹ž=»äå­À76¾þê«o÷îífôE‰qѸ$íBhàÀïE3ùêÕ±Õ«³nÜxpùršœWGG=9yþèÑ‹‡ û_—¼dÉ”¥K·ßºõÐÂÂ033_3MÑ£‡EÏž].]ªÌÍ]F_ȱø,šÉaÃz¿yóÎÃÃqÊ”µ€;wvɨUðç‰,PTT:F’ºð9üÔn|éànsó ÑÑÓ?ºŸ„Э[¾«ªÚýÕWŸÝs¸¾XZZX0ÿ½IBèçŸ/ÙØ˜S—ÿ&%\´(¹±ñ‡³²Š¦N]ûìÙAmmµ3v„µk|ÁôçÀáÃg%->+Š‹¯x{/¿{7[Òƒ ?ÐYb]Iê„/ rŽøÓÓÐð:?ÿlHÈ&„€ÏPÙ¯øw€ZY™LžìºaÞÏÍ·/„PCÃëC‡J(Á|.Ó¯¿á¾}§||V–•Ý~ðàɧW¯ÎòóÆáÀæfA\\Ndä¤Á@íúóY0ÈrÄçBhݺœˆˆIŸÑ‚@ mÜ$ûƒjmúú®ÖÖVÛµk±’’Âgøƒ !Œ‹ rrš5cÆHIwt!ü;@é‚{ëÒÿ¡ØØ™ &ñòe“‘ÿ»ïFDFNÆ×ÓŸ;·EY™÷/ëdž;·ß‘ö3QÝôy~6BÇ—½{×üý÷ß~žA*¤6‰@ _$¤6©ÝÚ$á˃Ô&@ 6Èš@ @ °AÖ @  ²f @ l5@ @`CüšáäÉ«VV~øµµõ”¢¢2Ñ6Aë¶mG š­©9‚Çs51?eÊÚk×î}Œ7uu ³g'tì8‘ÇsÕÖöts +((•úL€Ã‡Ïr8ƒïßÜŽ§HꋢޒԷЙúSPjjê__ßôÏùü1ȽM}}“¥¥oeeM»½Å­+˜±)V0R{IÍ@ûúÊ2¦¸ V ‡3˜.–^ãóÇ#{\¸ =FüÇ㹚™yÏ›—ôúõÛO‹ì´O]¢´¶ ·m;úüyc›tNeé÷ߟáòò.Ïž5ÐÛ45ýÑ¡Ã7¸M[½¢öRPPêì<[ hmŸ@ |9ˆY3 „JKo9:Zá§GݹSÓ»·%ãïýû–#Â/ÞæåÕÿ×_7ß¹³+==âõë·NN³NŸ¾Ö>WZZC‡Î¿|¹2==¢ª*ûäÉ66æ#FDìÛwŠ}:E½në¿Yú2îz.¶;n!,-M®­Í«­Í»wo÷Žá?ýtaÊ”µÿÏ „ÐÕµ×£GûŒuÙã „Baa[G`aÑÎ'3à‡aIÌ™3¿µcÙ€!b³wïI–޲Œl;úÊ2¦T,˜GöÑÃ’Ûñù#AQ‚‘êCQ[›WQ‘¹víŒ]»~ž93 UŸœv«KÔNAAéŒqoß¾oÓgG´1‡Ã9pà4•1„P~þÙwïš©e7NßË7ß|­ªªœ°ÿ³ @ |&ˆy¦„ðâÅ[ÎÎ=.TXX©«w`ÌZÖ®ÝyáBEYYjÇŽx£‰‰îàÁö‹ÂÃSÏœIhÇô½¤äúo¿Ý»re›]'€‘ýúà‹+Œç,©ãÇ<Òˆ¥o›¦€|¾º6~mdĈ˜´¡©é­¤'ž~ÚÇ0)**PÞŠ…1{¸ví^NΉrÚí'„Œ¹¹>¶cb¢;dHw÷…áá©%%‰í°I ¦{÷ŽB##~||ÌØ±ƒd™àþs‹LöqçóÕõõµð¿††:X0¯^ý¡¦¦ü·ûü‘@¥ F¬Kôææ ¯CC7mÝ:OUU‰Ýà'§ÝêµCŸåË>v¢3x—žû÷ÿ:sæHÊòÞ½ÅýûÛâc4óÙŒŠòõðX4uê7*äk@ó<.*ÈËû54t‡3xذ°[·ª¹Ü!ô_¾––Ö„„ÁÁ£¨B¸cGø‘#1ZW¬È47ŸÀã¹ZXLŠß#"êœûÎEööŠŠ®vvÅÅWªªÊ€ÜÜÍÍÊæéÓ §NmŽü­Z•efæÍã¹ZYù¥¦ÁGÁ©Æ3gÆÛØL¥ü|ÿ¾EGÇ36v7B¨±ñÍœ9 :ùðx®ªªî~êT9Õ·°ð¢]€¢¢«¥¥oRÒA 2 =vz~””xÔ©>‡…mýê«o‚V¼](D;N\¾” ,^¼MCc¸–ÖHFy‰¤"–æf µ` r…CÅ%»`B”`ZZZñ!„X0”‰bŒìŒq66S)o¥ †êXXx±{wJ0Œ1’ÅO5 Ü€R‚;¸ ŸçÏß‚ƒÿe 匨Mj¼>^02ž°âp8B! …GŽœÃY|nmFGï02«¨èÚ¿ÈÚµ»Ø‹pd׿Ø^ %·[]@ä3âå…21¿E% !ÔÒ"ˆŒL30£¤äææVQñîÒØ±ÎÅÅW^¼x…ÿmhx}üxu0…eh°?™™Çmm§ñx®:ùlÙrˆž''k>_cûöcdÁ@ ˜k†GöýöÛ99µµyÇ;­XáÿèÑ>úçÚµªúú&7·Þ¢s}}-MMUBhöì„ìì¢ääùwîìZ³æ»˜˜]+V¤S-7oÎKNž_V–Ú¡ƒâäÉ«…BÔ³§E@€GLL¶Á˜qã–mÞ¼ÿöíß©öÂ9s6oÎÛ¸1ôöí¬ààÑ!!Ð÷>mšû͛՗.UâöGŽœ{õê??7€Ÿßš“'¯ffFVUeŸ8±B8fÌ’––?'^©áá“nßÞ9{öØyó’0Bc|˜!„®]»›=dH|rFªÏþþOž¼,,¼!„_yøðé´iî’²`·¹nÝîCËË41Ñ6-&:zGJÊüòòíFF|?¿ÕŒ¥{Z­­ÂNâ@ŸŸÝŒôµ¶6]ˆ-bR‚¡Ê3æÎM”$˜Aƒì „&&º¢‚ÁP©ÐÕÕHM £³oß)€«k/†`FêÅ"‡.b#)3«W7qâá¬Y^,‚‘‹XÁdñ™ÌðáNbÃÈ%I6׬™1p`wº`úôéÆ.IŸ#:TŒ€wïšÕÕ;ŒÙ÷‡E[ŠúÌãÉ'$ìOLœ3zôÀ÷ß¹{·Fô j¾+Uÿ ‰Jª¼‚~Œºðgðüy#øP©ÅòMÒÔôǶmGSRæÙB8gÎØ»wk¶l9DùÃáÀo¿¸ÿ¯€½{‹Ç,:4’å;eÊ0J±qq¹³fyQ‘ÚØtܾý˜@Ð*//¦Z•@  ºf@•—WuïÞ!ôúõÛ{÷jíí;Ó+q!„øLBCÃk¼B19(h ¸øj``¼P(,/ÐÚ*1"œêØÚ*|÷®¹¦¦ÿÛ¹óŸÔâãŽ--lÍÅ¥§‹KOÀƒOöì9¹reÆ„ ËOŸN¸~ý¾PˆúôéF-Túõ³MHØ’)¦NuÏýá‡À—/› .äæ.ƒB‚‚¼òóÏîÞýKuõ“û÷Ÿ\¿~  q/gg{*–>}l6mÊ£jååUì±9ch¨PP×ÓÓTTTÀÊ賿ÿðàà õõ¯¹\N^Þ¯ééáÔ[¢Yª¬¬a·immŠçO:(ÌÍ pKee€~ƒ©iÔÖ¾ðùôcmº!D †ò¹}‚Á>P©À-±`BÕÕOÅ †Y#Kfœí©X>^0<ž|ŠC¦t%zÈÀ€îÚÚêùùgñêÂÀ@‹zKêÐÈËˉ*–ÚÂår¹ž@ a^ÏpùršÖ?.º|9-4ẗ}._N»|9~žÇ“ ½~ýžžÐûâ£qøu·nf‡ŸvîlhaadaatîÜÍeËvÐÛãŸ+êßêê'qq9¿ 7(+ó”•mlÌ9xîÜ êGúìÙëzzšZZªt›ºº#FôÉÍ=±{÷/~~ÃðLîìÙgÎü¶oߊ¸¸ À@Ï»WUÕ¨ßô *ЇËÏœ¹†oEÙ”1F&B2úÜ¡ƒâĉ.¹¹'öî-öõuSPøË\‘%YlÒçX¢(¨´¬[7+0ÐsÐ ;FZø¸ãÓ§/EmŠ”„¢¢LuõS†QÁà wîl(šd†X0Ož¼¤WfÁP#+š(¡žž&]0òòrB©™¹p¡‚Ê?‹`Øcad B(£Ï**JtÁP§)ÄfIF›,(¤~ŽP{tuuX±ÂÿÀÓiiGÄZfìÑή“¼¼ÝçÒÒ›’òF… ÉšhtâÝý«µ¿E]Œ]³|“tïÞIAAîÔ©«”®¨)¨ò¤}ûNÒ “€ ŸåóçoR–KJ~³²2UQQ¢¶<~üBAAßç€@ ±0eijªÖÖ¾ðôì«¢¢tïÞcgçTy „péÒ)ׯßwtœ5wî¸aÃzkjªVVÖddü”“s¢woK %__ר¨m*}ûÚ”–ÞúþûMãÆ9ËËÿïp,ãÇ;<|ÒáÃgç,[6ÕÑÑJ(þüó¥¥K·/^ì§  §§§éç7,""U[[­G‹‚‚Òääü˜˜ ÇS§~3iÒª7oÞ¥§ÿY §§ !LO/ÐÐP …‡•¬_Ÿ xóæ-©©bkÛñàÁ3))‡ÓÓ#èfŒø²Ä"š%Ù}Þ§O‡ÃÙ°!„a‡‘%ÙmJ²@7Åž@×®Æêê®^½;`@w†MÑeûwÍõõM|¾ãX/Bèo c,‚áñäõõµ¤& g†.¼å_ŒØE—ì>ÓÃ~]ÁÈx$^Áˆµ!\°`±cç-J>¼KKŒ¶¶Ú¬YžQQi::êöö J·lùób„À“'ÖËÑÏí°,hY¢C½ß‚E˰öw© ßëüù›NNÖ,ÂÐÔT™3glTÔ6--5''ë‚‚RFa—'q80++о]êЄ‡§hi©ÙÙuÊÏ/II9Œ¯Ì¦ríZ•ƒCWz@`À\3œ?³[73|ŸÁsçnÌ™3Vì‚Ç“?p`Õž=ÅééëÖå45ý¡­­æèh•“³t̘øwJJ˜‰IVddÚ£GÏuu5=—/÷§aX61ѽp!%66;:zGMM—˱³ë””4×ÇǷܺužAFh覺º†.]Œ“’æLŸ>œnÿH»»;ª©)wïÞÑÊÊo·´4IK[³+-íˆŽŽº—W¿’’${û€ÒÒ[ÚÚj€%Kü,ØzÿþKK“]»;ˆo[c¡6Êâ3„°W¯®Ýº™))ñllÌëHö<°ûèÚÕ˜=-.—óí· /Ð/Ãk!TTTæåUU•Í(¼*(ȱ†Ëå’̈K’`&MŠ‹& _?ʈ‚Œ¥¥ Þ"53 Áˆ>?D–XÄæPFŸº`ÁàC×,Yâ#Ö&‹Œ,‚‘#—ËÙ¾}aÓƒƒ7øû{©À IDATˆ¶dlY·n–ªªrpð†çϺ.Zä³re&'ߨøú«¯¾Ü»·›^Èr&A4:z/J´ k—º­<<§LY ¸sg—Xaà–kÖÌPWWY°`ë³gõ_m=uÑ¢FZú÷·ÕÒRíÞ½#á2(vÊÒ¥ÛoÝzhaa˜™éíý¿ÓB!*** #{Á!@ ¾@  “ŸÚ/–¹ù„èèiŸÛÏöÍ›ÕßUUí60ÐúÜ|û2ÁÿX0Œå↢¢2s|G#„Ж-‡-Jnl<ÆáÀ¬¬¢©S×>{vPGGýS»ùÿ€Ã‡ÏŠ.Š(B'O^õö^~÷n¶¤G þ—ÎKëì@HRG |i0¯g ü› „^:T² !àã3ô3œ”[[›NžìºaÞÏз/††×ùùg)ÁÈRÿÿ„о}§||V^¼XñàÁ“ƒϬ^åç7ŒÃÍÍ‚¸¸œÈÈIdÁ R¯A‚®[—1éK\0¡-»qJ „­­B_ßÕÚÚj»v-Æ·ƒüÜ@ÅÅ99Íš1c¤……‘ô„ „]0JJ ÿÉ…„06væÂ…É#GF¼|ÙddÄÿ‘“ rçÎmÁ÷Q%H…Q²%ª–‹ïÞ5ÿý·¤0‰@ ìÚ$@ |‘Ú¤vCj“„/R›D @ Ø k@ ÀY3@ 6Èš@ @ °AÖ @ O³f8|ø,‡3øþýÇ­­ÂmÛŽ>Þˆ¢6Jê%KL}}“¥¥oeeÍßr÷zü­mÛŽ4[Ssçjb2~Ê”µ×®Ýk·}„P]]ÃìÙ ;Näñ\µµ=ÝÜ J¥ö’1míK½Ån¡3„ÎÎ`…¡¦¦ÞñõõM,½>ÆçGö¸p›‚‚RgçÙAk;FV’H>Ʊ"‘ê›,Q·µ¯ìŸP¬üGÉ?çóÇð÷~óð_å¬ès‚‚‚Ò3âÞ¾}puíõèÑ>cc]I“ƽÆY쇅m=z€……áÇßq!ÔÜ,1"|ñâm^^ýýuó;»ÒÓ#^¿~ëä4ëÌ™ßÚ1ÅÁ‹¡Cç_¾\™žQU•}òäFó#"öî=ÉÒQÆ ´µ¯Ô?ÑÛ”–&×Öæ=z´ïÞ½Ý;v„ÿôÓ…)SÖ²äùc|þHB”¨¤Æ€º»;ªª*'$ìo«rÞ¿o‘$’Ó§¯µÏÿ–X‘ìÛwŠ]ÿôˆÚ´G–¾²Œ#n!Ä"©­Í£‹äòù#¶é›‡@ „/ñÏtC9rÎË+ªº:רX÷ïÝ¥ØÉ„PQQÁÀ@›¥£ŒSÛk×îåäœxð çoù¥‡®]»óÂ…Š²²Tss}lÓÄDwÈîî ÃÃSKJÛa³¤äúo¿Ý»re[÷î!„FFüøø ‹+Œ;HÆ n›v*ûtPÒóbñ >_]__ ÿkh¨19(hëWHzŽì§J•¨£¢|=<Mú¦¦ªŒ;BQ"éØÑo41Ñ<ØÞÃcQxxê™3 í/J$vvFFüõ냱HÆs–1¢6í—¥o›–|¾:•v##>ISÓ[UU%vuµÃç§Mß<@ |™ˆ?Ï õ˜">SŸ‘QØ£ÇtEE×N|öï?}ôèùîÝýypà÷§N•KŠH´4¢¹Yp 8xµ` Ò²cGø‘#kBø¼ÁŠ™ææx_cûöc2ç „ZZZ±H¨e‹„SÙE DÒÜ, lb‘€g«ÉaŒæÌ™ñ66S)?¥Š„ê[XxÑÎ.€ ùN #-Ô J$b”ásXØV,¼]$’„‡·ÿ]"@ |ñˆ_3°S¤Þ]·n÷Æ¡åå?š˜èN›½#%e~yùv##¾ŸßjúBtbŠÉÌŒ„^º”V[›ÇxkîÜÄùó½oßÎ óž;7qëÖCt þþOž¼,,¼ˆ-_yøðé´iî­­ÂNâ@MÄýüÖœéöí³g7/ Ïé°ÇB@yyUllö!=ðI©>K5±YjmJÍƒì ”š*.¡‹Kϼ¼S¢#.¶ˆBH‰DTäX$ØøÇˆdܸeX$ôýŠ&'1ñ}ïX$—.UâöíIbâFhRE‚³‡Ïûa‘¨«wÅgJ$ø“Å.<Äì6ÿ^‘ðe"fÍ ªê®¦æáí½`e姪ꮪê.v±fÍŒ»wéb4s¦gSÓqqA}út³´4™>}ijg ÏžÕÓ»ˆ­7ÐÐPÊ]oEEùNú™™~` gPW\\.ý]kkÓ¾}»efbË?¹¹õ66æßºUýêÕ¶¶æxwB!2¤gzzD߾݌Œø½{[†„Œ®¯oª«k`D„ëää¸ô½@ëêúúZTû¹sqNðߣGÏŸ>­OM=œœ<ßÍ­—‰‰î¸q΋û­_¿—šj¬\àädmcc4êñãÏŸ7RSÊŠâÇtåÊÙ³7[Zú¶ ¦¦!TWטœœ¿víŒQ£ú›™éš5Ë+&&›î›““µµµé®]E8YY…ŽúúZr¿~6FFü^½ºR!㎫W7qâSS½Y³¼‚‚¼âãÿ’ØgÏØc±µ¦¦æ¡ªê®¨èÚ»÷L33ýôô€,>K5IY’jSvRiU}¸!›Ž—/ßiiùËÂ|(b‘“ã2–”H( ¢"¡;lXoݱc‰ŠÄÑѪ[73*|aZÚJ$sæ$XYù¹¹…a‘<{Ö€“ãåÕÏÌL?$d4‹Hð"MT$’²±zõw>>.¦¦zøÓ'I$’b±µ†WRr£D"£Ï”H°Ï¢"ad‰‰$›kÖÌ4È®kWcJ$NNÖ]»³ˆDÒg‡@ „/1×3\¾œ(.¾_PðžÍ‹­V²¶6ÅÛ;tP˜›à·”•yª€ö»º:àÊfaŸ>6›6å54¼¦7ð÷¼áåË&.—“—÷kzz8 ¶ö€Ï×À}9䕟v÷î_ª«ŸÜ¿ÿäúõû¡P(KÍ4B$nhxMM#"&¢R$ ËË´¶ GŒ§l¶¶ ß½k®©©Ãÿvîlˆ3 ®ÞÐÒ"À-]\zº¸ôDUW?ݳçäÊ•&,?}:áúõûB!êÓ§•~ýlöãÅÅÔ©îññ¹?üøòeSAÁ…ÜÜe¤q/gg{*œØ/^Q6ËË«Øc9r$ÆÐP   ¯§§ÉãÉã–2ú,vÔ$e©²²†Ý¦ì ”šð¡’BÈç«·´ž=køê+m©:R"¡,´O$ø-*|l ‹ðàÁ±"¡FSF‘àõ»T‘0>}#EE졌>c‘Ô׿+F–(‘H²immŠUA‰·lŸH@ø2³f°°0TT<˜™éñE‹4ð .—ó×£õ/®Å/ÚtŠ_^^Žšà½0NŒïqâJ¯^]ñJWWCWW!„S>L)rs£»t1¢w72â߸qÀáüå4 B(&&ûýû–¥Ký°M33ý… '(**Ì™“ÐÐ𚚣02Àáü弯¯[TÔ¶ãÇË*+×ÒR>Ü ´J Ãá@j:(šX©±˜šê™›ÿ¥j{(£ÏbGrŒ‘%©6¥*BjZè{ár¹¢þH!D‰¤woK¼‹|øÙDB!»ûýû–e˦à-ffú x‹Š„1šRE‚/*–OŸ,"13Ó‡"ß2úÌ.F–¤Úär9tO ”xC‘ðe"ñ¾IÔkÑiË»Œcy@cã¼ýîÝG S,s²óçovíjŒ'%%¿YY™ª¨(Ñ;ª¨(Mœè’›{B^^Î××Ç“ࣛOŸ¾´°0œ={ãÌ™ßΟßúõזؽ•+³ÉzEE…Ñë×ïñöljªG_UW?ů»u3ƒ>|øÏÚBYYE?ýTŠ‹vÄf¦ºúÉÎE3fŒ ´”•yÊÊŠ66æAgƼ¥kWcuõW¯Þ0 ;@OOB˜ž^ ¡¡" *Y¿>ðæÍ[ÆtðÝ»æúú&>_ƒqT!´té”ë×ï;:Κ;wܰa½55U++k22~ÊÉ9Ñ»·¥††ŠŠŠ’¯¯kTÔ6 •¾}mJKo}ÿý¦qãœååÿwh–‘™ððI‡Ÿuvž³lÙTGG+¡PøóÏ—–.ݾx±'¯¯¯åç7,""U[[­G‹‚‚Òääü˜˜¢˜:õ›I“V½yó.==oa wŒˆHÕÔT±µíxðà™””ÃôyÀȈßÖX0²û,:j’,ëéiÊh“Ý7YÒhç®]«rpè*ª„÷ï[°HD¯{ù[Dˆ…E$ r²$ûO Þò/ˆDìÂRvŸé"a_ÊnS’º)©"!áËDüšÙÏ3èëkmß¾pÙ²¶¶Ó´[´È'$d#½££•‡‡ã”)k6„ÐßZ²dÊÒ¥ÛoÝzhaa˜™9~¼3ý]¼_‡.ݺ™))ñðO—ËùöÛ……BBFC--MÒÒÄÄìJK;¢££îåÕ¯¤$ÉÞ> ´ô–••)Ýí¢¢2/¯¨ªªlFá „PAAîÀU{ö§§¬[—ÓÔô‡¶¶š££UNÎÒ1cr¹@JJ˜‰IVddÚ£GÏuu5=—/÷gÉŒ‰‰î… )±±ÙÑÑ;jjê¸\Ž]§¤¤¹“& Å·ng`º©®®¡K㤤9¢pwwTSSîÞ½£¥¥ ÞÒµ«±¤µµÕK–ø-X°õþý'––&»v-½Ó¿,±ˆ=Š,£Ï¢£&)Km²XÀHM Õ!PTT:FtÊK‰D´ð†Ç“g ‡eI,æ$‘øø¸à–¢É™>}¸h6(‘Pšgù\ˆÉرƒùlk,ÔFY|†öêÕ‹ÄÆÆ°~çÈžv߀l"!áË":ù©ÝøèÃãäD§ï¢-‚Vsó ÑÑÓèS„›7«¾«ªÚm` %cá_CÒ¨}>_ñö^~÷n¶¤þZZX$dÿЙTžµIê„/öœgøGaTƒHš.44¼>uªüرóŸ¡ô–ÖÖ¦“'»nذgݺYÿ†Ç™aµÏ„кu9“Ȃᓀjl|C @ >>»5{Õ¦µUèë»Z[[m×®ÅJJ Œ•F\\“Ó¬3Fâ{@>ØGís!tüxÙ»wÍßÿíçæÛ„.|;T@ ŸœÏ®6‰@ „R›ÔnHmðå!æ9Ð@ @AÖ @  ²f @ l5@ @`ƒ¬@ ŸfÍpøðYgðýû[[…Û¶}þ¼!Dm”ÔK–6{÷žäpߺU-éyÀbinŒ®¨è“ý¡öX_ßdié[YY#»5I „Þ½kŽ‹ËíÙó;%%7UU÷B÷ï?M½[PPêì<[ hm‡e uÛ¶£ƒÍÖÔÁ㹚˜ŒŸ2eíµk÷Ú”:8Õ:CèÌá VPjjê__ßÄbS–1úç vÍâá't@ áÿ)Ÿ`Í@ŸÏ”Θ÷öí{€«k¯GöëJšð1ÂÀnYöûë#„JJ~;v¬4'g™‰‰ö›‚†…m=z@—.ûœ„ЫW 4;3³pñb¿[·2KK“û÷·7nY\\.Þ×7ß|­ªªœ°¿M}„^ó,^¼ÍË«ÿ¯¿n¾sgWzzÄë×oœf9ó[;– T—ÒÒäÚÚ¼GöÝ»·{ÇŽðŸ~º0eÊZ–ÜJ£„%!–'{ü›.@ ü7ÿL7„Б#ç¼¼¢ª«suÿÞ]ŠVB ´Y:J]Èø iÑ^oÞ¼88t¹zõ.ÝTyyUNΉr>þ‰ÅÂE‹’_¾|UV–ª¦¦Œ­­Yó]s³`ñâmÞÞƒñL7*Ê×ÃcÑÔ©ßhh¨ÈîÿÚµ;/\¨(+K57×ǽLLt‡ éáî¾0<<µ¤$±Þâ|¾º¾¾þ×ÐP'"brPІW¯þPSSÛ±}˶¿Y$DžÔF ÐÄŸgz´xddöè1]QѵS'ŸýûO=z¾{wÏÕÊÊïøñ2Ñ2üïï¿?£ìxzF"„LLÆCèL5Æ/23ÛÚNãñ\;uòÙ²åëùó·|õÕ·TPˆ:vœ¸|y†Ø0A늙ææx_cûöc¢þK²ÜÜ,HH8<ŠZ0P·cGø‘#kB¸xIløØìÎEööŠŠ®vvÅÅWÄNý!„JJ|:mš»Øð¿³g'dg%'Ï¿sgך5ßÅÄìZ±"P[›G¹A÷§µUxàÀé!CpBÁÁ’“óããƒ**2†ûûÇ”2ö"¶<!tíÚ½÷ï[úôéÆÈ'Ÿ¯Ñ·o79j/..=óòN‰ú/ÙrU}}“›[o†e¡¾¾–¦¦*„B()|ÌæÍyÉÉóËÊR;tPœ<™9vøEyyUllö!=ðI†9s6oÎÛ¸1ôöí¬ààÑ!!UUìcÄØck«!ÄnSv½üüÖœ>+ãâ‚úôé˜>}Äĉ+ž=«§lJª ÑÐP `oEEùNú 0г²ò÷¸¸ÜÀ@Oê]kkÓ¾}»efîÈÈøÉÍ­·±1¿ôÞ1±~ö¬!5õpQQ¼³³=Àؘ_[ûbÉ’í‘‘¾úúZ”t®_¿ÿêÕ¶¶æxÎúüyczúO©©a£GÌŸ?¾¹Y€Ð_Š $•Ç@ß45UØËœ „66·o?&´ÊÉqe±\W×Ð××¢,Ï›¸mÛQªMEE–œ‡?h„ÐÄD— ·Y¹2ÀÉÉ4ÊÏo u¸­í4l³¥E "W×^©©a€ººÆääü””°Q£ú‚ƒGݹS“2Zê•—ß»G!»MÙõ†2¤ç Avvv „FFüÑÞÞËq®@ mBÌšáòå4@qñÕÀÀø‚‚ðl^lµ’µµ)ÞÞ¡ƒ"ÀÜÜ¿¥¬ÌÐïÿÓŽšWW< †öéc³iS^CÃkzÿáÁÁ^¾lâr9yy¿¦§‡ÓßeLåËË«Z[…#F„S[[…ïÞ5×ÔÔ™›ë‹u ¶ö€Ï×À]®_¿ßÚ*tr²¦¼ŠŒœ$c,!uÀ‹¯,,Ø.§Fñùê--‚gÏ ud±¬©© hhxM©ˆˆ˜4 |D¡PX^þ@RøøßÎ ñ©«w´´ðö#Gb° òzzš<ž<• ¡õéÓÊF¿~¶ û©Å†eŒD÷XYYÃnSv½A‚‚¼òóÏîÞýKuõ“û÷Ÿ\¿~  ¥¦”@ À@ÌšOj+*ÌÌôŒø¢E/ø—Ëùkó|ãÔD›*CäåÿW®ƒ÷"'Ç¥7?ÞyÞ¼ÄÜÜ\.·CEOÏ~bw-àÉbnn4ãHFF|I` Ο1â/ ]×ÑBmmÍ••yçÎÝpt´¢[¨­}1iÒÊåËý °Åe.— àp ,^Cíí;«ª*Ÿ8q¥W¯®Ø‚®®†®®B"ø0Wþ÷ñîÄ. MMõÌÍ ;¥òIeƒ#ç/Õn,c$ºG©6¥êB huq™÷àÁ“ñã{ÌšeZSSçë»ZR @ ,|Ôõ ø]ÆÌþ®‚‚< ±ñ Þ~÷î#†)–9ñùó7©ž–”üfeeª¢¢D諸¢4q¢Kn{‹}}ݨCàbìÖÍ BøðáÓÎ -,Œ,,ŒÎ»¹lÙðñõ§O_â±…‹oS–ÇŽ]´A’ÿ ””x¾¾n[¶ljzKY@­_Ÿ[RrÝÐP‡š(?~üBAAŽ:¿!EE…Ñë×ï©®~ʈººú)~M…cïÜÙP4|Iלˆn„ÚØ˜s8ðܹÔ={]OOSKK•ÞLêÑËh“ÅÅÙ³7Μùmß¾qqAžv¯ªªK  @ Úø{­BGŽì+Kz—z͘±1¦¹¶¶ærrÜØØì•+**&%`˜Â÷á9þ&.m§ž¢¥¥fg×)?¿$%åpFFý]¼ß€€á}úq8œ Bèžœ9óÛƒO¨õô´zôèìëëµMCC¥o_›ÒÒ[ß¿iÜ8gyù¿œ» ûÓµ«±ºz‡«Wïöïo !40ÐöõuˆHÕÑQ·²29t¨äàÁ3GŽÄ0μ{×\_ßÄçkp¹F¢V­š~òäÕC—.Ú«W×—/_ýøã±Äı±3;uúŠJàµkU]'UØ-/]:åúõûŽŽ³æÎ7lXoMMÕÊÊšŒŒŸrrNôîm©¡¡¢¢¢$5|IK±Ûõõµüü†ED¤jk«õèaQPPšœœ3Cö1µ¬§§)£M©>ëéiBÓÓ 44T„Bá¡C%ë×çÞ¼y+¶=@ ñkvXÎB0¦túúZÛ·/\¶l‡­í´í-ò ÙHoàèhåáá8eÊZÀ† !ô·–,™²téö[·ZXffFŽïLï×Á¡K·nfJJ<|zwÆŒ8zK/¯~û÷¯LI 31ÉŠŒL{ôè¹®®F` çòåþ ÿéþܹ³ëÛo^ ƒCKNž¿|yúÌ™qOŸÖwéb´sçâaÃz3¦ïEEe^^QUUÙŒ’¡––jIIÒÚµ;ÃÃSª«Ÿ*(ÈõìÙ%/o¾¨#¢¢¢²ÐÐ1Œ¥»e¹VíÙSœž^°n]NSÓÚÚjŽŽV99KÇŒÈårbÃg;úv±çš¶ng`º©®®¡K㤤9²‘Ø=ÊhSªÏ­„n½ IDAT]»§¥-ˆ‰Ù•–vDGGÝË«_II’½}@ié-mm5±]@ ’€€N~j7þ½;«iëã¾ÖiŽ44…̳2+ÜkV\’ÌS3çÊ5F%W á."!cf2׬ÌÎzÿX¯}Ï=vGBêûyîó>§=¬ý[kïí]¿³ÖÞç_ìóÏÉåîçÞ2;;ÇÚºWP×€¿E$W®Ü«[÷·›77”+'öKa…xÄÄÄÔž=§Ý¸±>¯Mû¹|ësPpÔ  ˆR4@I£øy†Hd⓬ôô·Û·õ÷_ÄéÓ§õ·ø­.J©U¿~. lüå+<â¼y1}‹GÂðÎ|E.güZØ&'Gêî>kïÞ“ëÖMÒÒR/À»Œ”A) ñ‹?vãÆÃïÐåݳçäǙÆýR º×ßíÀ·Väæ&|˜›T`˜›Pò¹q(R3€ä 9ˆAÎb~LΰcÇQ‰Äùöírr¤‘‘;Ÿ?Ï`Œ óÚK™m6mJ”Hœ¯\¹ûE¯+ÍÌÌîÔ)@SÓ%8x=G8â«WoªVuOK{ |iyaŒmÚ”H©“܉sãÆ~+³uëQU«ºç^¾jU‚ŠJË›7}Q;ð¤Ê¶€òRœœ†ggçàE±ÙÙ9‘‘;[´®¯ßICÃÅʪGÿþsΟ¿õ¥åÈzö,}øð%+öÖÐp14tmÓfLBBJ¾± Xj‘×¾Ê_Û²W…ºzëòå{úúÎõêÍ·‹ùkÖ= EßÈd{6 )†|øð‰ââRïáÃÍ––&yu}òý¹7e~ÛAá^ÉÉvíJ‰‰™jeeÊãáEQJÇŒYÞµkóÊ•-”,M‰RzøðâGâ„ÿ>Ü\€cÌǧcZÚƒcÇ.É-ŽÞݺuÝŠË~ѯ"PJ…3ò¥ñ´oßPGG{É’-_ú; Ÿ>euê0iR¤›[³Ã‡_¿¾.**ðíÛ NJ:ÿEE ²²²[·}æLZTTàÍ›ëÖ¨aÝ©SàæÍ‡DêU°ë'ß}•ù™BáÚHI ãWÅ­[V­ ؽûDÿþs¾QÌ_‰RúE÷,ü¼T.eŒÅÇss›x÷n¬¥¥IáRaŠRª©©^¶¬¡ÈŽùväJV²¿B)}÷î#!¤nÝÊ©©7d‹:wîfLÌ;wb”/M„¿‘‘®xM•D)íÚµ¹¡a™uëö5jTGÈ»yóQRÒ…˜˜)èøÊž‘/ÝwâD÷Æ{z¶Ó××Q~¯9sÖž8qõÔ©ˆŠËò…VV&Îε:tqäÈ’D’œ|ñÂ…[gÏF:8T"„XXÿñÇ“'¯.]ºµ{w§¼v,Øõ“ï¾JþL!ÿ`lüïµaaaØÏÏoÁ›7tt´ ñš/,_tÏÀÏKñ8C¾ßŒòùÑÑ{j× ©éR©RŸ-[’vî<^³¦·††‹ÇÞ½§rOKàÞ¿ÿT(ÇÕucÌʪ¥NÂÆüÃêÕ{íí½44\*Uê³lÙ_rQ½¬\¹_²³søŸR)«X±÷´iÑ «ÀegçLŸ¾ÚÚº—††‹­mßùó7J¥Œ1F©SçÎ< Ùxc njß¾‘‘./-¯d"2#ßVݾý¨Dâ¼bE<ï»­*]ºÝÅ‹·6/ASSÝãmlìÁÌÌlaldõê=&&znnÍcyÅÌËÌÌ ZÅgïØÙyDGï‘;#|÷™3×T¨Ð“oñÿØxH“&Eêéu40èÌ+Û°¡±±ÞÊ•»”lÆXVVÎ’%[‡ é"$ B[­Z?G¼åy±k×î«UËGSÓÅÁÁçàÁ³„mBHlìÌÌl¡Ì¤¤%‡-âÇÍ«^ÂÆƒͯQÃSˆóÓ§,##×¹s70Æ22Þ±¤R¥>.::í‡:tNØwÏž“>šš.U«º‡†nË}ÞÖE®Y„ZZÂ’|c3f9¿)ørá¦PØJ|ñó«ü žW³ä¾Èàg¤8gÿfTX;oÞ†… ‡ž;÷§••‰—WpPЪððÑçέ´°0öð˜%Û’ëÜV¯ž@)=}zÅ£Gqr«FŽ\:ztÏk×ÖŒÓsäȥ˗ÿ%[‚·w‡Ç_îÙs’—|ðàÙ{÷žxyµWXþçðáKÖ¯ß6úúõu³gÿ¼núô(BÈ£GqB²ñääH·nMjÙ²®ðý½ÂrODÉkÂF¾ß7»º6ñõu;vùýûÏ>?sæšE‹†U¯^Aaƒ„…mçu÷öîðâÅë]»Žó2sr¤ÑÑ{<=Û©©©BòŠ™R:dÈ‚°°íóçû]½ºÚǧ£·÷ÜÝ»OÈ‘#–,^·páÐk×Ö ÒÕßáÒ¥[…€S““Cwî ®PÁŒ—ÙªU¸¸CJ¶ ¥ôüù›¯^½iÓ¦~îËÃÌÌ€Wˆœ;nñ⸰°Ñ§NE”*¥Ù¯ß,©”Õ©cëãÓ!8x}ٲݺwŸºxñ–k×îËW¼^„/¯ö—/ß=}:oìõë÷m!³SW¯žpóæúPJ»u›œ•õÿô500"  ïµkk‡ÿuԨХK·ÊUM¼.µÁ;þÖܹë[¶¬­«[J™˜…›‚Ÿ ¹›"w+å{~•¿Áómø©)˜›¤£Óž’“#%„ØÙyðÌë×»„Ž ðaö쎎5 !ƒ¹öé3#$įqãê„:õî=ýéÓWB™yM™ÐÓ+M16Ö533[5q¢»§g;Bˆ¯¯kZÚýX__Wamµjå›4©¾zõžŽB¢£w·iSßÒÒ8%EÁcOŸ¦GDìØ·o¾“S-Bˆ¥¥ñ£G/&O^9a‚»™™†l</Þ~ýú½½½5ï󉔠®þŸfÌk†RýúƒädÅŠ±={:BBBüS ø=-í~ïÞ­||:È6Hÿþm)¥ƒ»ñ<Ø7EÓ¦5Ö®Ý×¥K3BÈþýgÆÍ­)¥Ôß¿ëõ낃×ûûwå!M˜à.¤4¼kÔ¨¸r宬¬l5µüÛ„1öìY:!ÄÌÌ@è(¹SØæêÕ5ªª*yÕ‚o3c†OÆv„?¿.³Ÿ?Ï05Õ_±bl¯^­6m:ø÷ß§ãâBZ·®ûçŸãÍÍò­!¤Q£jÕª•_·n_:¶„5kötèÐÐÌÌ€1Ò²e-*QJ-,Œýý»öì9W„2kÖo}ú´"Ÿ¯Ûùóc‡ é"+rFøöö^¼)²²²¥RæâR/"b cL™˜…›¢C‡†Dæ¦8wî†ÂV¢”Š—9{öÀ-ˆÌ Þ¨Q5¢èš¥V-Bˆ¹¹‘\³ÀOMAÎpæÌ BÈÁƒ©¾¾ó~ç½y…ójªU+Ï——*¥I±¶.ËWikkB„‰C¤@Óš]\êòùÙ”ÒÆk,Z—žþVvoïŽC†,xùòŠŠ$.îpTT€ìZٹݔÒsçnæäH;u æäH?~Ì|ðà™µµ™Â=zA16Öžm)A™yäB#ÄÅÍ›Š#tšµ´Ô×®Ô Á r化-)Ûn..ÿŽxðyõê¾¾¥Ôǧ£¯ïü—/ßèDGïnÕªŽ¹xÌwï>ÎÉ‘ OAB&LèËŸcŽxñâm©”5n\]8nÓ¦öK–lÞªdkk.×ÎÆÆºYYÙOŸ¦—+g˜o›PJùHBzú[á\öóóëB>_R©ôܹ;yÕ‚ÿiccÎWéê–"„deeóÒZµªÓªUBÈ;7nLœ1#ºW¯iIIKò­çéÙ~þüØß÷}ùòMBÂ‰ØØ©”RJ‰ŸŸÛöíG7lØ÷îãÛ·_¼x›"•Jù^NNµä®Û/^ eŠœþg||°¹¹!D]]ÍÔT_SSG¨dÌü¦xõêmî›"w+¥¥=/³Zµòü np¾eî<ßf€Ÿš‚œÁÖÖ‚rõê=BH… fƹ§šð**’ÿN5Éó1Ÿ¿:ý‚‰ jjªBW†EUUEvƒ=œFZ{@EE¥T)MWצ ÍKà}—ØØ ¹7 YXç/A"ùEJPþakþÁÊÊDèÀåÞæôék‰äŸ^¤¦ÞhÞ¼¦°JMMUèŒ Â?tïî4räÒØØƒ½{·Üº5)**0ߘoÝz$4Nî$NèðÉW"ùÿ”6UU¹vVQQ!„H$TÉ$ªV-íÎÖ¯_•/41Ñ31Ñ#Ÿ¯@ñZ\ºt›Nö:dŒÍ»áÓ§¬©Sûó%*˜ÛSSS}Ĉ%ééoó­çîÞfâÄȽ{O¥¥Ý70Ð騱 U«Qwî<îÑÃÉÉ©öàÁåKØK¨»Âë6ߺ”/oÊ'zÉ®¥”*³ÈM‘»•ò-SEE" ¥y&ÿù6 üÔ¾êy¾V®×(»V]]’‘ñŽ/¿qã¡\Q"=ËãÇ/³Ïõ&'_°³+_º´–쎥KkõîÝ*6öÀ¦MÝÝÛhh¨) áW¯^RzïÞs[[ [[‹cÇ.OºJ$þuï“'/yEJPr%ßç!×®Ý5*4(È«GgÙü x¡A„ΨР<6mm¾}[ÇÄì߸1±Lm>ÝH ‰ùçŸr ®­­¡­­©L½!&&z:5Ž=°aÃ~¶¼ëôè¥#G.lÞ<=$ÄÏ××ÕѱæÍ›!BuOœ¸*\·GŽœ·µµàßëQ]äŠ1¦dÌ¥JiÊÞr³æäZIÉó+r¿ „f™7o°¯¯k‹rÍ?5ÅïZ¥”vîÜD*=˜×Zá³\×P®?aoo­ªª2wîú3|®^½úŸG6 !üµ0Ç_æó¤e„”qp¨´}{rxøŽèè@Ùµü¸>>7ö“H$ øËFräÈÙ>¨©©AíÚ6îî.'Fêé•nÒ¤FJÊ•aÃuïîÄVO•*–ºº¥RSo4kfO)µ´4É«¹ùô)ëÕ«7ÆÆzr#ÂfÏŸgÈvg… ³³súõ›Y£†õ¸q½ÒÓßÚÛ{ùû/\³fb^ ";>àãÓ±~ýAoß~ðôl'ôEb633pww Œ02Òµ³³úë¯ämÛŽÄÇóçx XX{x´ Œ04,S»¶mBBJXØöàà +EþÿØîͺu«È}?-Þ&S¦ô¿xñvƃGŽìÞ¶m}}}´´ÑÑ»cbÔ¯_UO¯téÒZùž;¹ë0  ïŽGœFLêÙ°¡T*ýûïÓS¦¬œ4ÉC]]ÕÔT_Ézyz¶ëÛwæ»w£¢þ?›ÈÔTŸR• §WZ*•þõWòÄBÞ½ûÀw ŒÐ×/mo_qÛ¶#áá;¢¢þsÝZX+S—Üã ÊÇ,{SÈ•#×JÊ—™W ²E‰7 üÔç âD¾/—ëR˜™¬\9nêÔUöö^ŽŽãÇ÷ñ÷_(»AÆv:4ìß!dÁÙU“'÷Ÿ2eå•+÷lmÍW¯žÐ£‡“ìZ~ܺu+W¯^AKKƒ}+¬80DvK7·¦[¶Ìceµf„>71Ñóõu6Í[.~Ùx®__÷Ë/Ž{öœ:´¯š2%PJ÷í;åæ6ñæÍõr“Lxã0ƇånÕׯwÍšµæÒ¥;gάPUU12Ò ݵ뤶mðç’å„?3-¨]Û¶NʧO§ÅÆN:â1‡…ž6-jР'O^U®l±ví¤¶më¿{÷Q¶–/U¶lôС‹ž=K¯\Ù24tÄ€åθÌT²oß©¡C»)ß&„ µ­[gnÜx0**aÞ¼˜7oÞ–iØÐ.&fJ·nŽ %„(¬EîëA`eerâDøÜ¹ëƒ‚V=xðLEEâàP)4tdŸ>­ø–ÊÔ‹Ò¾}Ã2e´kÖ¬hgWž/¯ZÕjÅŠ±ÁÁëV¬ˆ72ÒuskšœZ«–OJÊCÃ2„É“=ÆŽ]~ûöãªU­Ö­›ôë¯-äNô—ÖEX¨ä¹¨W¯ ¿)jÔ°&ùn)Ùâ±BªT±oø©QFa‰?:Œ±Ï?'wóæzkë²â[fgçX[÷ ò’ëèV$W®Ü«[÷·›77”+W?ÁV`;vÍ«Ã]¤>ÓÒ?~Y®Ù££w·n]·R¥r_¡p1|Q<”Òvíèèh/Y²åK“ ž+NšéæÖìðáÅׯ¯‹Š |ûöC£Fƒ¹P°T*;;§uëÑgΤEEÞ¼¹>1qaÖ:nÚ”(^ ÙB¾è "û*ùk'üCJJØ£Gqn¾ukêU»wŸèߎȹø¿Âþ¹È·^ðõT.eŒÅÇss›x÷n¬¥¥IáRaWƒRª©©^¶¬¡ÈŽùv€äJV²ëI)}÷î#!¤nÝÊ©©7d‹:wîfLÌ;wb”/Mä(ãLJ½|ùúÔ©ˆ2e´yi³gÿ–™™=iRdϞ΅ÞÎrG猌tÍÌ ¾þg×c]»674,³nݾƫ ËoÜx˜”t!&fÊ—¶¥T8¿ØwâD÷Æ{z¶ÓÓ+­üyŸ3gí‰WOа¶6ã{YY™´lY»}ûqÉÉK•A(39ùâ… ·Îž¬Y³"¥ÔÂÂxþ|¿“'¯.]ºõ×_[(ÓÁýÒ³#²¯2w„°ÐØøßkÃÜÜ(0°ŸŸß‚ׯߗ)£]è1%eþ¹Ào "Åã ù~ƒÈý££÷Ô®=@SÓ¥R¥>[¶$íÜy¼fMo ;;½{O垺Àÿ¼ÿ©PŽ«ëƘ•UJ„ù‡Õ«÷ÚÛ{ih¸TªÔgÙ²¿ä¢=zY¹r¿ÓQ¤RV±bïiÓ¢VËÎΙ>}µµu/ [Û¾óço”JcŒR§Îy²ñ0Æ.ÜÔ¾}##]^ZffvPÐ*>çÄÎÎ#:zO^-“{ÊÄ›7÷øûwd@@ŸššˆOQ¼òGïÞ1ƶo?*‘8¯XÏ—­*]ºÝÅ‹·EÎ…††š‡GÛØØƒŸ>e å¬^½ÇÄDÏÍ­Y^ ηÌÝ’Œ17·‰¼ñUTZò*Ïœ¹¦B…ž|›ˆˆxÙ:Nš©§×ÑÀ 3¿º5ªfl¬·rå®ÜµË«M23³—,Ù:dH!aj±jU@|üÆX^-/\Ûk×î«UËGSÓÅÁÁçàÁ³Œ1mBHl쬬a´*)iÉ¡C‹øQÖK6€CjÔð¢ýô)ËÈÈuîÜ Œ±ŒŒw#F,©T©††‹ŽN{GÇa‡vܳçdÍšÞšš.U«º‡†nãñËV9¯ºä¾6(¥ZZ¼5ò:ÊÜ [IFäü*ÿoK^Í‚q€B¤8gÈ·‹É?Ì›·aá¡çÎýieeâå´*<|ô¹s+-,Œ==ŠòèQœ†l<99Ò­[“Z¶¬Ë[€16dÈ‚°°íóçû]½ºÚǧ£·÷\¹yêyM™`Œ?ëÓ§¬Æ«Ëµ§±±^“&ÕÕÕUÅ'( >wóš°!žRJ;wnìëë:vìò{÷ž:tnæÌ5‹ «^½B^ç‚ïåíÝáŋ׻vçgA*eÑÑ{<=Ûñêä³Â–ܽûDtt oü‡7BFŒX²xqÜÂ…C¯][3dHWÿ…²³S““Cwî ¶¶.Ë+ÕªU¸¸CJ¶ cìüù›¯^½iÓ¦~î¶233Ð×ס”æU aãÅ‹ãÂÂFŸ:Qª”f¿~³¤RV§Ž­O‡ààõeËvëÑ#hñâ-׮ݗB¯!ÄË«ýåËwÏœ¹ÎÛ*>þØë×ï=<ÚB<ü×Q£BCC·ÉhñºÈ^çÎÝœ;w}Ë–µù C¾1‹ßr­”“#Í·”ÿ·%ßf€¯§`n’ŽN{BHNŽ”bgçÁ{T¯_ï’ý’˜={ £cMBÈ A®}úÌ ñãÓT èÔ»÷ô§O_ eæÕ!ÖÓ+M>OŠ[5q¢»§g;Bˆ¯¯kZÚýX__Wamµjå›4©¾zõžŽB¢£w·iSßÒÒ8ås^®ƒøôizDÄŽ}ûæ;9Õ"„XZ?zôbòä•&¸›™aÈÆsñâíׯßÛÛ[ó~ÌóçQQ»#"ÆtíÚœ2ztÌÌlÆþ3å#¯)”ÒŒŒw„}ýÒ˜æôäÉ+|‹”R++!x55•|Ndú‚õë’;úŠc{õjI) ñKLL0à÷´´û½{·òöþ7Sx.(¥Õ«WhÚ´ÆÚµûx›ìßúÁƒg>>e{–N133ÎÈÈ‘K##w Û\½ºFUU%¯ZðmfÌðiÔ¨!Äϯ‹‡ÇìçÏ3LLô""ÆôêÕjÓ¦ƒÿ}zóæC„—zþ9ÞÜÜ(ßzB5ªV­ZùuëöÕ­[™²fÍžš™0FZ¶¬Ó¢…C­Z6„ss#ÿ®={Nã!„Ìšõ[ïÞ-)¥ƒ»¥¥ÝŸ??vÈ.B±"g„o`oïÅÛ!++[*e..õ""ÆB”‰9¯ûñܹ [‰R*^¦òÿ¶ÍâàP‰O“køz r†3gVBLõõŸð;ïÍ+ü¢Zè´•*¥I±¶.ËWikkBdßcS€y..uygŽRÚ¸qE‹âÒÓßÊnàíÝqÈ/_¾QQ‘ÄÅŽŠ ]+ו?wîfNŽ´S§aaNŽôãÇÌžY[›) àÑ£„cc=¾ËÅ‹·sr¤U¢š0¡¯’uaŒéB^¼xmkûeS3ÆD‚¯X±¬2…;ÆÅÍÛEè4kkk¬];©AƒAåÊ-[6RöŒ+<¼‹ïãÓÑ×wþ‹¯ t¢£w·jU‡?ý,óÝ»¶äŽG…#^¼x[*eW¶iÚÔ~É’-Â+­lmÍå®Iccݬ¬ì§OÓÍÍ”iU}}BHzú[a)0°ŸŸ_òùâ—J¥çÎÝÉ«üOs~mëê–"„deeó-[µªÓªUÆØÝ»O6nLœ1#ºW¯iIIKò­çéÙ~þüØß÷}ùòMBÂ‰ØØ©„J‰ŸŸÛöíG7lØ÷îãÛ·_¼x›"•Jù^NNµ„ºðÓôâÅk¡L‘3ÂÿŒæM§®®fjª¯¡¡&\ùÊÄ,r?æn¥´´âe*ÿoK¾Í_OAÎÀ;µW¯Þ#„T¨`faaœ×DÉg1åùæçï/¿`¶€ššªÐâGQUU‘Ý G§Q£–ÆÆPQQ)UJÓÕµ©ÂCóx"66Hî HÆyÀKHþ_G>ðBò_‡¾3 IDAT3A)µ··ÖÖÖ8vìRÆv²%>ë×ôöíOÏvÂó"1çÕ’jjªBã[X{x´ Œ04,S»¶mBBJXØöààr×€l+?³nÝ*rƒQâm2eJÿ‹o7l8xäÈîmÛÖ×××IK{½;&æ@ýúUõôJ—.­•ïe#wÍôݱ㨓ӈ©S=6´“J¥ÿ}zÊ”•“&yhh¨™™(S/Bˆ§g»¾}g¾{÷1**€/15Õ§”FE%èé•–J¥ý•üDZ„wï>ð#ôõKÛÛWܶíHxøŽ¨¨ÿÜ2y‘ºpÊÇœ×ý˜»dSS}%ËM™f€¯§8g'2 !÷óff+WŽ›:u•½½—££Ãøñ}üýÊnа¡]‡ û÷ŸCY°À_vÕäÉý§LYyåÊ=[[óÕ«'ôèá$»–·nÝÊÕ«WÐÒÒàß¡ k ‘ÝÒÍ­é–-3ÂÃÇXY­™0aÅÇÏMLô|}]§Mó–‹_6žë××ýò‹ãž='†íÆ«6zÚ´¨AƒBže…„ÄL˜Ð·ˆ$ DésñÃQJçÍ‹ ì‹„áGù÷#ü@™›ôM‰?~-l““#uwŸehXfݺIZZêߨ“M) ñkÔhðÀmlÌ¿iW^CCíØ±eÚÚE$a Ê‹¢`Ïž“?fö‹’o‘‚ÂõÝîGøQŠÜÜ$€ïs“ s“Jž"77 Šä 9ˆAÎb3€ä 9ˆAÎb3€ä †âÇß „bøÿÀ¡MPÒ¨â¶ô@æ&!ŒJtPD!g1È€‚¡Èrø i(‚œd m€\3€ä ð_j€ÿBι mÈ@ rPC ðrÈÒ „ g1H9ˆC΢0ÔPâ!g€ü m(Ù3€6”`È@ rP†J*ä  4¤ %rƒœ¾†Jä ð…6”0ÈàË!m(I3€ä P j(13@A!m(3€ä ð0ÔP g€¯ƒ´ ¸CÎ_ i@±†œÄ g€Â€¡€â 9¤ År(_ŒÒ{{_¯Øå ˜›b3ªâ5È@3`b€8ä 9@¡*v¿ùƒœJ<á]™ rƒœà 0Æ>~Ì ‰­Sç7-­6::í›7ºeKR¡”œ“#ŒÜùüyÆ×—ÆíØqT"q¾ÿ©’?ÉÅ·§ÔIøOCÃ¥B…ž£F…¾}û1Æ7¸}ûŸ‚ųiS¢\ùü¿Æýd ÿ? ¦ð$Úq‹Ý{“ð;ÐPâ)ýÞ$ÆØë×ïÛ´óáç  ¯:ulß¿ÿ´fÍžîݧÎ;h̘ž_¥4!áøÀ!mÛÖgŒÑ¯ž/ÛV¦4aû””0KKcþùãÇÌãÇ/±ôÉ“Wk×Ntq©÷ðáfcc½D(”øðbsÙUêêj²~}ÝÅed¼Ëë$ŽÝã[ýg„œ OŒ±ììœ-[’–.Ý’”´„R:~|ØË—¯OŠ(SF›w.gÏþ-33{ҤȞ=--M¾æXB¯ºPº­²…(ÓÅ606Ö533þ´¶.›žþvèÐEË—ÒÑÑ*[Öð+ã12úOù¹JÊ$+++›ŸÄÇB„“¨«[Šo0gÎ@á$ZX;:ó÷ïÖ­[sUU¹fV©©• Ž4æ&(öìYúìÙë*Uêãï¿°I“Œ±7oÞGGïñ÷ï&$ „Ji@@ŸššÈMnÉÎΙ>}µµu/ [Û¾óço”Jclûö£‰óŠñ}H$†œiPÐ* ‹_55]š5óŸ3g]îùQ¹S%›Ž7:zOíÚ45]*Uê³eKÒÎÇkÖôÖÐp±³óØ»÷”PcìÙ³ôY³Ö '‘òöí~…„o)œDBH“&5üýVªÔgΜõ²SÅ(¥ÂªÙ³×=ž¡x:S±©@Î%^®÷&¥¦Þ0à÷òå{nÛ–äuïÞÆàà„óço}ú”Õ¸qu¹.¯±±^“&ÕÕÕUåºÚÇ/Y¿~_XØèë××Ížý[pðºéÓ£(¥®®M|}]ÇŽ]~ÿþ³Ã‡ÏÏœ¹fÑ¢aÕ«WX½z¥ôôéÅBî.”¿xq\XØèS§"J•Òì×oVNŽ”ñÏ?w…‡¹reuÇŽ'MZÉ7¾~ý¡§çœîÝ®__·yóô¿ÿ>!W ¹àù‡ììœÄÄÔ3¢]\êÉv²Eb ݶdÉð«W×tïîErÉÝÕ– F¼îóæmX¸pè¹sZY™xy­ }îÜJ cY<»HM½ñÛoódOâܹƒ(¥ÂI”ËadObpðÀ{÷6ymÝzØÊªÇ€¿§¦ÞàÛÏ;HvÕo¿ÍKM½‘»‚ÅL RPR:¿U¨`¶woHÓ¦5dû²ï!úú¥ó<Ã{ú4="bǾ}óœjB,-=z1yòÊ ÜÕÔTBBüS ø=-í~ïÞ­||:BôôJ“ÏSƒ„Ý[´p ”ZY™»óC̘áÓ¨Q5BˆŸ_ÙÏŸg¨ªªDFî íêÚ„2|ø/7nxðÌÚÚLKK}íÚI  *WÎhÙ²‘¹¿wÙÿiccÎ÷â_ÿgee_¾|';;§Q£j< ”6mjÏs†&Mjüúk‹AƒæOœÙºu]Wצ¿üâ˜×8C||°¹¹QvvÎþýg#Ú´©:RKK=w5sÇpõê½ÌÌì¦Mk14oî —3ÄÅͨX±¬ì33ƒ/ª{µjåùqK•Ò$„X[—å[jkkB²³sH®“hd¤ËãN¢M>‰ß³gé‘‘;ögffM™â!¤XŒ±çÏ3dWÉï‰÷&7¹Þ›4uªg@@ߘ˜K–l™1cuïÞ­† éZ»¶½½µ¶¶Æ±c—6´“ín>zô¢oßÓ¦y7on/t+¥R)!$66¨råÿ$Æ|›Ó§¯I$’þy‘šz£yóšr1ˆì~éÒmBˆDB>åÌbžÓUQ‘lÜtùòÝ]»ŽïßÚÃcöŸîÚ³gžÂq†òåM­­ËBªVµª\Ù²S§€OŸ²ââ¦çn¹Ü1ðþºl ¹Ó!++“ÜI—ìfùÖ]EE"{\Jå';QJƒ‚¼ÄO"šŽþÏ?/…“xæÌõÐЭ11ììÊO›æÕ»w+aâÙéÓir«44þóÒ§b Ï3È£”jjª{z¶;u*Ý{ëÖ$þÄvî¶’‹ÁÁ¡’ššê±c—rÇ ·Wî6ÿšºó1¹òùI<}:B8‰|!?‰¯_¿—Ý]8‰„F¿~ýn÷îy§N…{z¶ÓÐPR aÕéÓ|UîÚ?gÈ¥´E ‡-îÜyÌ»¡3gHLLut:eŠg½zU^¾|ý矻–.Ý:wî J•ÊÉîkiiâîî2qb¤ž^é&Mj¤¤\6lQ÷îNjj*YY9ýúͬQÃzܸ^ééoíí½üý®Y3QKKƒrüøåFªYXçµ»lx²GÔ×/=bį'F”iÔ¨ZBB Ÿ˜D)]Z+2r§TÊFê‘••ý×_GªVµÒ××Q8Î [2¥tìØ^»v?>¼cÇÆ ›HöOCÃ2ƒ»Nœ¸ÂÈH·V-›„„”e˶ÉmöüyÆãÇ/åÊá/,â P÷Üã ²¶háàèXóîÝ'|¹ÈI䓦®__W¡‚™ÂÊ^¿¾®|yÓ|^Ki1›ž„œJ<ê”ïϺ =HääÐ9sÖ„ß½ûD]]µNÊqqÓù#¿²cáác¬¬ÖL˜°âáÃç&&z¾¾®Ó¦yB¦LYyéÒ3gV¨ªª醅îÚuRÛ¶ ºvmÞ¡CÃþýçB®__—×;èìÙuuK»üéÓW ØyŽN©]ÛfíÚI³g¯upðÑÖÖhÙ²N||°D"öÞ$áOÉÊ•ãj×0dÈo﹫)·dÞ¼Á::ÚC†,xþ<£nÝ*ãÇ÷™1cµì÷ñŽŽÃäv¡”fdì”]ò¥uÏBä~ZC8‰††ežÄ.]šñ½& œÈªbŒ~‡Ÿæ(Ò(Uþ§ !_ûöªQÚÿôclÙ²¿ÆËÈØ¥¢RbfÅS§b6ÎPbÎ|{Œ±Í›õé3ãäÉ«wî<Þ¶íȬYk<<Ú– „Ã÷&aœàРXIO;n\ØöíÉ/_¾±°0vwo3aB?¹¼+îZüè rä P¸Š[ÎP’‰¾ƒb7¢‚÷&•ÅîÚ(Lx oÈJük uúÑi˜›P¨ŠÝÃÈ ÄÃP<€(ÌM€bh÷î n:qâê›7ïõõu6´3¦—£cͯyÍc,<|ÇŸîºrånff¶¥¥±«kÓI“< t”ÙWE¥%!$%eyýúU vt‘”/ŸÊLÀPWWÓ×/ݾ}Ã… ‡êê–Ê7¾ï‰aõêUù±/LT&Ù6©W¯ŠŠJKÙ÷jh¨™štìØhÖ¬úú:J– ÅŸpƒ)–(^òùnn,Q¸¤AÎÅÍ´iÑÓ¦EBjÕ²15Õ?þÖÎÇwï>3µ[·æë2ÆfÎ\3uê*Iƒvúú¥Ïœ¹¾páæ¤¤óG†ª©åóo)¥ÿ¾Øš1V€ÄKP²|aU‹ºº¥22Þ=z):zÏ«Wo¶n)•l±?¶KÍëÒ¥!D__G$Ù6á{Bœœjéé•&„|øð)9ùbXØöû÷Ÿnß>›¢L™PüåmÀ¹%r?oœ»sŒ%År(Vöï?3mZ”††ÚÖ­3Ûµk@ùô)ËÓsNlìÁQ£B»vmNH»ìK–l!„lÞ<ÝÕµ !äÝ» >}:-)邳s­oÝá/AÉò…nôï¿ûÖ«W…²cÇ17· ý•üäÉ+SS}%»àK{ ¥tëÖ™ùn&$ÿüûï¾|†1vìØå¦M‡ÄÇû矗eË(S&@‰…ç XY¼8Ž2lØ/dRÒygç¥JµÓÕíØ¡ÃøÓ§Ó„Þ0¥N”:­_¿¿yó¡ZZmªUë¿cÇQÆcL*•BÖ¬Ùsöì ÆH©Rš»vÍMIYîàP‰÷GcçÎÝìÔ) L™ÚÚm›5óßµ+…—Ì;Üüs‡ã%çÀÀ~D©”UªÔG"qÞº5‰1–“#6-ºR¥>jj­J•j× ïîÝ'dK8þV³fþZZm*Wî·rå®Üå3ÆrW‹w£y´üC›6õø‡'O^ñ幫{ß.]&I$Î#G.åÍÊÊ61é"‘8ÿý÷iÆX^mÈË)_"q–Hœ×­ûÛÑq˜–V›š5½Ïž½¼¾\¹_J•jçæ6ñÙ³t~D¾åÉ“W•i1¡|¡}øÚZµlxž?Ï „È–É?ËUA(':zO•*îZZm‡mذŸ×·0/b€¢9+G^$„´lYGv^б±^»v LMõ !IIZ·}øðùÚµmjÕ²Ù»÷d‹Ã.^¼Íû”¼éç÷‡D"12Ò½zõ^ß¾3ß¿ÿDñ÷ïJ‰‹;\·îoff]»u›œR¥Š•¡aò9ahÒdÈ®])+–­_¿êÑ£—:wܰá€lÉ„Aƒ\ !kÖìÍÎÎaŒ%&¦Þ¾ýO¹r†:5&„,^7mZÔóçmÛÖ·²29uêZ·n“32Þ %øúÎÏɑ֬Yéúõü¾ví>¹òVðÂ…[$WjÁÛ»÷!D"¡ææFŒ±ÔÔ¹«°~ý~¹}}|:BbcJ¥Œ²ÿ™çÏ3Ê—7mÙ²ùœänC%Ë÷õ¯ªª¢«[êâÅÛ-[Žœ1cuõê¤RéŽGƒ‚¢xá²É@¾-Æ7“ý,•²ôô·óæÅBʔѶµ5'2I…ðY® ïÞ}dŒmÚtÈÓsNZÚýZµl>|øäëû‡lÉÅr(VÒÓßBtuKñnÜàÁH$Îü›`‰ÄùÔ©kAA«²²²##Ç&%-IL\¸råø÷ï?Íž½V¶3:b቉ ÷í›Oyûöí[!S¦x.]:¢jU+BȳgéÛ¶<øjÕ<„îøøñá>|êß¿íÙ³‘‰‰ .Ê=:4'GJdº¤;6²´4yôèž}§!ÑÑ» !>>UUU!õêU ´oßü;æ>¼˜1öáç;w % öËÑ£¡Ç/2¤ ¥táÂÍrÝh¡‚GŠs IDATŽ,=th‘PAÙÔbܸ°nÝ&;;èÞ}*!ä—_ZðÌG¨BjêÊC‡ UàéÐ9îС¡¹¹ÑãÇ/8CÙ´)‘Ò¿[‰$Ÿ6T¦üqãzïßÿGxøÆXzúÛØØ©{÷†Œ×›’šzC.AR¦Åøfüsƒ¾‰³ŠŠ³¾~§iÓ¢ÔÔT/®©©Nþ›TðÏBcoÞ¼çU˜??–RÊωa}ú´’= @q…œŠ##]BÈÓ§ÿŸÄR³f%7·¦üñVÞ±;qâ cÌÛ{.Ÿâé9‡1vøðyÙÎhË–u !66æ|á§OY„‰„úù¹]¾}ãÆúU«¼¼Ú—*¥ùèÑ ÿE|³¤¤ó„¶¼/¯v„'O^]¿þ€ÈtIUT$t$„¬^½çÍ›qq‡$êíÝoЬ™}Íšׯßçè8ÌÚº_˜™™%”Ð¥K3þá—_ZB._¾#×>qâ !ÄÛ{.Ï”<=çB>/›Z$&¦nÛväèÑKFFº¾¾®+WŽãk…*ðͼ¼Ú1Æ?~É« tŽUT$^^í !1123³·nM¢”zx´Ë· •)ßÙ¹6!¤lYC^N«Vu!¦¦„Ì̬Üã ù¶ߌvrªåäTK]]RZ£†õåËÑîî.¹Ë䟅*ð xxŠØ­›#_Ø£‡3Æ $À3ÐP¬4o^sóæC»w§ð'•v<Ø}~í&!D*e”RGÇšü ›œšš*ýüL!DKK¢¢"ž´mÛ^ß 5õ:!ÄÌÌàó¼;BÈš5{ù¾QQ»)¥ææF¶¶Dæ;oJiÙ²†]º4ûðáÓ”)B~û­³PfdäNBHP—¿W!Þ)åŸ7lø›ض-‰âà`#¹PÁ-[flÙ2C¨ \r÷t)¥BøfQQ» !åÊò*È~_¡‚YëÖu32ÞJéß¿äÕ†„åËW¸»Â…ù¶˜ìŽüCãÆÕ#"ÆB¶nMÊ=¹K6¹¶%„ÔªeCÙ²å0_¸nÝ>Œ3@I€q(Vš7¯9mš×Ô©«ºwŸZ³fEssãóço>xðŒR¶¬¡©©Á„ ý:wœ0aE\Ü!]ÝR‡ËÉ‘._>JîÛz¹ï³+V,;lX·… 7²|ù6KK“[·]¾|—R:c†ßlÖ¬ÎÎ#¢¢vŸ9“¦§W:)é‚DB,ðWQ‘ä.yÐ ×¾zõÆÒÒ¤C‡†ÂÑ­¬L¯^½çé9§vmÛ¤¤ó åì ;ÆÆ<}:MKKãØ±K„Ñ£{ÊEžWåj”»›ËË« ||@n_ŸŽûözøð¹ŽŽö¯¿¶é¯+nC‘&’+?¯Ý.Ì·Ådw$Ÿ³š>}Z%&žŒÜ9yòÊŽU®l‘{œü;òo9cÇöúå—)K–l9yòê§OYW¯ÞÃ8”g€âfòd½{C:wnŸ3ÎÌÌvq©·hѰk×ÖXY™´oßpçÎ¹ŽŽ5¯]»Ÿ”t¡zõ þ9~РÎ$¿ïÈçÏ1¦I“·ný³k×ñÇ_¶n]w×®¹}ú´â4n\ýÈ‘¥;7¹ÿÙ‰W›4©¾k×ïÝ»;),ÙÙ¹–]yJ©Oþô3_µfÍÄzõªdd¼»xñöÔ©žÝº9B’’Î ;.[6RW·Ô™3i66æÑÑݺ5—+¿]»¹+8p`'eÆ5ª–» ¿þÚ"÷¾Œ17·¦üÉé=œ´µ5”gP²|!eæÛb²;™4`á¡իWøðá“·÷\©”)3Î@)íÚµùÊ•ã*V,{öìu=½Ò+VŒ¥” g ¸úÏÏdBqF©‚t(¨;wW­êž™™}øðâfÍìt8ßɪU OŸ¦W«Vž¿wË–¤îݧš›Ý¿¿éG‡ð]Èý4”˜›_€1–œ|qÉ’-IIç33³4¨ZrÆØ½{O¦M‹¦”::ÖTUU9zô!„&cÈà PJÕÔTãã1ÆZ·®ËŸ”(!SJûeeeoÚtèØ±KŒ ãž='OöøÑ¡|[˜›Tb`n|%ÌM*©ð 4ˆÁ8C‰Q2fÀ·…®c‰„çJÌM€¯A~tðc`nˆAÎb3@>cÙÙ9‘‘;[´®¯ßICÃÅʪGÿþsΟ¿Uà‡acÏž¥¾¤bÅÞ.††®mÚŒIHHÉw¯;ŽJ$ηoÿS€#Šì+¬©߆R'J$guõÖåË÷ôõÿêÕ‘½¾&毧|½ø6²uäÿih¸T¨ÐsԨзo?|}]c¯^½©ZÕ=-íAÁJØ´)Q.Bþ_RÒùoúhÖ·n™Â­WNŽ42rçóçEüq5ñë“1&T„/IHHqržSÄëP,áyÃËÌÌvs›šzcܸ>K—×Õ-}ãÆÃÐЭ Þ³g^³fö_ú^vž„´n=ºLí¨¨ÀŠ˾zõfÕª„Ncb¦ˆü4’ì¾ô}ð"ûÊö?ò*SØ&%%ÌÒÒ˜’“#MK{àíüèÑ‹íÛg‹˜¿cÌÅ¥ÞÇ›õò­—,¡Ž„3¿¼ØÆÆ\v•¡¡î·kÛÜgŸjËn½c )†´m[¿(ÿfB¾×'¥4!á8¯oÕöí.[¶mÉ’-#Gvÿþ”pÈJ4ÆX|ü17·‰wïÆZZšäÞ€R:gÎÚ'®ž:ammÆÿ¯ÝÊʤeËÚíÛ ˆHN^ú¥¥”&'_¼páÖÙ³‘5kV¤”ZXÏŸïwòäÕ¥K·þúk e:¸î–åÞW™n½°ÐØX×ÌÌ€ÿinnØÏÏoÁë×ïË”Ñ.ô˜¿¥TSS½lYCñmr/”­#!ÄÚºlzúÛ¡C-_>JGGK¼@qçÎÝŒ‰9pçNLSþÁÈè?~k Ï>)¼–)ÜzQúïÛðŠòO­å{}2Æ„ŠðZ0ö?öÎ<®‰ãmà3 @î›9D ¨ª Š"xß ‚µ¨xs¨E©Šê( VðD)Ò‚Öµ*Ö*¢±hÅ´H2ïÓîo»I6Q°ø–ù~øƒlfžyžgggç™yvƒbc†_4LWWó_R”@ ’›ÔÉ‘µÜNÑÒ"LN>>Š ¨Â;wFåç¯Å÷u¡P´jÕ.+«I<žÀÆfjRÒ±Q {ö9;‡¨ª œœBJJ®#„45Õ99Å­­¥@ÏžM>sfnE(}õÕnKˉ<žÀÎ.0==Ÿ¡í¬Y‰A”ÎÍÍ­~ëÖíG½|ù:22¹{÷)<ž@SÓgР¹gΔQ ¯8:«ª lmRRŽÒç%Y¶H: B¨¦ÆOnäê¼páÖ>+ŠðG±uë6yåÊ,©^¢”‘” þNêÈÊ*tq™©ª*èÞ}ÊáÃgOœ¸äèŒKž:u•ž0#Ë-²r<çšÃáˆÅH,çç_ÄYt‰Äqq;ÍÍÇ©ª ŒX»v/‡óéo¿=EmÜxÐÇçcƒ¿ÖÎ[Z„qq;q~š]`VV!»Õìû©—ÕY©2²ÚmGÏ´£]!ÿX„Ÿ?Ë,«gRö.[–¡£3BOo䨱+¤öO¹‰m’8C©‰[ô㲜æçƒ Ð ;ÇÍÍÎÐPgÇŽ“$=‰@ þeHÌЩ‘;Y¹y³²¾¾ÉÛ›™ä!41ÑÓÕÕ„BçÍKÞ·¯(5uá½{{׬ùL×vÆ ŸÛ·«¯]»‡çëùùÿ ô®9}úÆ®]1••ûŠ‹7@ÇŒYÞÚú×L(::=*jêÝ»{æÍ·`AJJÊQ†Õì¶ÐVVV¹nݾÁƒ]ð&ƒ\ƒƒ‡?yRWXxë\RrýáÃÚ3|¤zI$ËõÃúõû7nœSVö-Ÿo4cFB\Üδ´…ee;ÌÍ W‹Åÿ˜T±»EVÇ E§O߈Ïújkwa“ªsTTZJÊÑääyåå»Çÿ4.î/ï‰Dâ#GÎìJ­‡‡oHMÍKJ +/ß2"8x]AA©,«¼B(ÕÆ–¡¬¶&ãT #ö¨v÷ŒTÏ¿³]ß}w9++BøÓOÛ=:äõÌÓ§oœ?ŸrâDªUÁRû§Ü}?É œ1°PŽep$åìÚƒ yü8—Z\2¤Onî™vÿ„@ þ«Ü¤Î‹¦¦@$ììñ=¸±ñ$}ýÙ³€‰‰•ä0þ–ŒŒ”òòÝJJÜôôãEEIžžNB>ßèñã˗ ÀeâãCÜÝíaa£×<þÒÈH'=}ѤIC,ùþûŸ:ú~ûíR33ƒgÏ^¦¦æ¥¥-5j <|Ô½{5 û""FSíº»ÛÛÛwÝ»·ÈÕµ`÷îÂáÃÝLLôƒ÷ñôtrv¶˜™DDŒž8q%6°zõç“'†Ξí_Qñ[RRNxø(JìÓ§ ì¶ôî=û¡µU(# ozú"€":ÛÛwí߿׮]…#F¸²²¾óöîgaaXVv_ª— „ì2׬™5h#à‹/ü¦L‰OL óðè˜9ÓwòäUOŸÖSMSnqrꎓÁn¡CÙxó¦E[»ËÈ‘ý¿þ:T²¤¤Î<žrròá-["Gþ0wî˜û÷kp`vçNucã½{[áÉßóç/33¿KO_„K.\8¡¥EˆBžì×ï ú”111lÖ,_UT”¤¶EOÝaI•¡fºïÉ3ín—ŽŽø;“J®?cbìí»âv%û'Ÿ/%e‘òe¬››ÝXcc]zI©Ž•ŒŽ$åÐ ¡BM‡n;vœlm*+“û@ ü{1·óríÚv@IÉÐФ‚‚¯MLô€Ä’*NnhxEݰ££§……¢*ŠÅâ²²"‘Ø×7Šª+‰ß¼i©©y†?Z[›áù^Žmmâ’C†ô2¤B¨ººöÀÓññY“&­<{6ùÖ­*±yxôÂS:ွ““S¯OÁù$%å|ýuh]]SAÁ圜/‚°0ÿ¼¼ û÷ÿP]ý¤ªêÉ­[U±XŒkyy9S¶xx8lÚ”ûâE#%³¬¬’Ý–üü33€ŠŠ²±±.§ŒK*¨spðˆðð uuM\.'7÷ÇÌÌ(ê+I/UT԰ˤ¦z]º¨¬¬L±uu€J2QÄ-t°B¡è‡®EG§{{÷KI™¯¦¦"YRRçòò‡--Â(?ùÄ ÏŒ?~ x½u«J$»»ÛS%cb¦Š‹¯Ë²ÚÀ@·››ß­›)¥–Éb£¬¶„ê ïÉ3íe×ñã(!r{¦uEHöO–'"¨I¿µõ_(cyŽB²€¤ÉÂBCCíÖVáÓ§ øJ$¿‰:/66æ€òò‡KKssCÉ” ggkMMõââë}ûöÄ####„®þžwæäÄ1^†cnnøË/U2B‘„„}ÍÍ­+Vb™––&K–LRUU‰ŒLnhxEMd©© žp8ÿH¥ ðŽÍ8uêjEÅozzšxqT( ²àÁƒ'&xyy¹ÌžÝµ¦æY@Àjª‡©É«¤Ä¥¾•kK×®ÆVV¦àŸ „Ôy¯ ¶ääs¹Ü.]TýüÐcxI®L.—óÏd™YËu ÊF[[~¾¾QÍÍ­¹¹«$KJꌄ˜:SVp8éŒ7¸€D˜ªˆ'ù|#Ü{é´¶ eÙ(µ-Å¡LxOži_»båúSI‰K]’ý“ÅcÔWøš¢+ ˆŸ%Í—”#)!Äårqa¹M¡!Ï3tjØÓ‹ªª*£¿ùæ@uu-£puu-þ¿W/Káǵ66æ66æÖÖf/ÞþòËŒ†èÕ««Ÿ$&f?yRG† ®ÎSWWup°âpàÅ‹¿PÌ.Ü26ÖÕÓûß›R „ÆÆº¾¾99Åû÷ÿ8TYY BxáÂ/çÎý|èЪõëg‡†úyz:UV>P_¾\NM>λiccNOFWІ— „ ꬡ¡6yòœœâƒK¼©m ©^RP&‹ Ê-‰‰a¡¡~ƒ92Ü€jQ p]µ*øÈ‘³Û·çK•ÌhÑÉ©»²²]çÒÒÛø+¼*\[[‡uÆ®¾rå.U}ܸááeY­¯¯Å23F±Ø(µ­°° Ò—@²Ýöõ £Ví ßHWXÁ^„ÿ‘ìŸ,na ,gG*R†úöõÏï¿¿PQQ24Ô‘Û@ Ú²ÏЩŽÙ_,.‘U!´bÅô[·ªÜÜfÏŸ?~èÐ~ººš5YYßeg÷ëg«££¡¡¡ ˆÍÐÑÑèßß¡´ôÎܹ›Æ÷RVæÒ¢‹Ššzüø/¯È/¿ rs³‹ÅßÿÓŠ;–- äñ”MLô‡FG§ëëk¹¸Ø”¦¦æ%$Ìb( 6uêW¯_¿ÁIcc]affŽŽ†X,>vìü7ßä^¿þWŒŽN×ÕÕèÝ»ÛÑ£çÒÒŽgfFÓÅš›¾­-Åu ááÆáp6lˆ`L­’u”É®›"na@Ÿ¢-^<éäÉKK—¦áÁR£¯¯5{¶_lìvmggë‚‚Ò­[âb={Zhkw¹qã>þMSSý€Attº¶ÿرóGžËÏOe5»¥8†”e£­-_j[Œñ7oZêë› u¸\ެðûðL»Û…ý/]ºíînonn¨H/¢iÉþ‰¨­­0<Ã$0¾jnnÅŽ¥ïéÉ ´èñ{É.]º À/ƒFݼYéêÚ“Ë% ^ð¯BbB¥#G¾:p $3³`ýú즦?ôõµÜÜì²³WŒ3ß¹ÓÒñù»cb¶?zôÜÈH'4ÔoåÊ`ºÆT€Ï7º|9mݺ}qq;kjžq¹'§î))ó§Ný Þ¶m©iÖœ9›ž=kèÑÃ"%%2$d8C1€›––º£c7[[>>Ò³§Åöí‹önßžo` íï?àüùgçÒÒ;úúZ€åË/ÞVUõÄÖ–¿wï2ÉŸSÄÉ©¹â:»ºöèÕËRM‡‰Y¼PP&‹Œ\·HšCIær9;v,qq™¾!8x¸dIÆ‘õëgkjª‡‡oxþü¥«kÏ¥K§ÄÇïâñ”¹\ÎØ±ƒ /Ï™3WLM]¸reæ_$ÖÖÖ÷èa¾gϲ¡CûɲZÒRÆ[[¾,mmùRÛbLm‹Š®úûÇVVîc¤Ÿ1е»gÚÝ®×¯ß î6}úZÀ½{{ïEBÉþÙÐÐdf6Àð Ë.%úçÃå”c--M¤†²ä¸¹ÙÑ ùè#}„@QÑÕ9sƼ[š@ Þ(k’Aø¯!@§;Z‰ÎÎk·²š7cæÌ­Î{¡¨èªƒƒ~OBhëÖcK—¦¾|y’Ãwîœ%sYýs×®SAAkŸ>=ÊÈû÷))¹>qâÊû÷÷ijª‘°@è —ÌÄVšå^E üçihx•—w!"bB`Ê”Ïþ“á:BèС3S¦Ä_¹RþàÁ“£GÏ­^½;0p(Îi±³ãO›&ذáÀÒvvX<ÓѪý…¬þÙÜÜš˜˜3µÃ„ÐúõÙÑÑSIÀ@ ÿ>dŸ¡Ó@ö:„P]]“•Õ$}}­;£ðï?t´Rï…††WK–¤æå¯«k277 ðŽ‰™¦¢¢„í}ùòµ»ûì¼¼5Ô‹5;ìžéXØûçë×oÔÕy0œ:uuݺ}EEIN E tFÈ>Cg…Ä 3@h#$fè¬Õ@ À‰@ $f @ l˜@ @ °Ab@ À‰rÀ?ó”‘qÂÓsž®®/'àó'LŸ¾öæÍ_ßù¥[¡gÏæÍKîÖm2'Ð×÷óö^TPP*·Öñã8œO«ª~‡YêR_±X„Ë@衇ó©ŠÊg]»N Mª¯ob©ÕÛŽâvá2tñ'°´œ¸`AÊ«W¶Ý„P}}“­m@EEÍ»I8xð4CCüwöìÍ÷ú ¸÷í™öµK$gdœxþüåþZ<öþ‰¢ a—Ó¾öJžêªo»p©47·&&游ÌìÒe˜–ÖpOÏyÙÙÅ ÚBõ½ß~{ªx‹¡‚‚R/¯yB¡è]µ&¥ŽV€ðAƒjiúûÇܸqÉ’)[¶ÌÓÖÖ¸ÿQJÊw÷Ù……ëìý¶omÇAÈgŸ-ÔÒRÏÌŒîÖÍ´¾¾içÎ_ßèììãÇ{ɪHo!ôVí²Ô¥ß›eɤʔ–¦ZXD"qEEMppÂãÇ/òòÖ¼ÛBH èûèÑ!CC¹vÑ¡l¼yÓréÒíÈÈ-µµõ{öÄRßÍá¢EÛFþ¤Gó·­K×öÇ7[[›Ñ¿Ò××~¾•<û ]=Ó¾váéà¬Y‰C‡öû~ùArû'„° à6„Å«ík/Bèñã\üÿ÷ßÿ4}úÚ«WÓMMõÚ(–…?ÿl6lÉǵ˗O÷ôt Eùù?ÿ|}qñµ´´…r-z·B8lØÇ[·MN>9îCî'áÃÄ „P~þEÿØêê #ɵk÷\¾\~õjº•• ¾µðùFƒ»øø,‰ŠJ?~ËÛ6 !<þÖÏ?ÿzýz†£c7¡¹¹aRRØ•+å[¶7ÎS‘ î;OË$ë*rÓ¥j›˜èáffÑÑÓÂÂ646þ¡¥¥Þî:·¡ªªŠ©©>{ɃtVV¦ ¯æÌÙ´mÛMM5v씕Ufg?xýÎ!þÇÀà¾o¤ž}Ð~ži_» ü߯îüËaê[!·"„(CX¬h_{!„X%„ŽŽÀÐP»-}ž„ЊßVUý~åJš±±.>س§…‡G/OϹƒ9Mú»Eï<Â@cc†_4LGGãƒí'áÃä&ujd-·S´´““„‡¢ªðÎQùùkñ}](­ZµËÊj'°±™š”t@,FÔ¦ùž=EÎÎ!ªª'§’’ë!MMu@NNqk«· !<{6ùÌ™M¸¡PôÕW»--'òx;»Àôô|†¶³f%:8Q:77·ø­[·!ôòåëÈÈäîݧðxMMŸAƒæž9SFU,,¼â謪*°µ HI9JŸ—`dÙ"é4¡šü=¹‘«óÂ…[?úh,• £nÝ&¯\™%ÕK”2’2ÁßIYY…..3UUÝ»O9|øì‰—ƒqÉS§®Òfd¹EVþã\s8±‰Åâüü‹X ‹Î"‘8.n§¹ù8UUÁÀk×îʼn¡úø|l`ð×ÚyK‹0.n'ÎO³³ ÌÊ*d·š}zÄ~êeµEGVªŒ¬vÛÑ3íhBÈß?!ÄçOàrËê™”½Ë–eèèŒÐÓ9vì ©ýSnb›äÎÐ_jâý¸,§ùùÅ`C ô’¥ƒâö*¢•ÔAIØÇ:Ê™Éɇ¹B[Z„©©ys玥Lÿþ½ÆóLN>,yšªª~omÆÄl75£¦æíí½¨¼üáÛª‡­vw·74ÔÙ±ã$ ‚"˜¡S#w²rófe}}“·7sÓBhb¢§«« !„Λ—¼o_QjêÂ{÷ö®YóyBÂÞU«2©Â›7禦.¼z5½KÕiÓV‹Å¨O›á ûLMÇL˜·yóá»w£ß˜##“7oÎݸqÎÝ»»ÃÃGGDlLN>L×vÆ ŸÛ·«¯]»‡çëùùÿ ô®9}úÆ®]1••ûŠ‹7@ÇŒYÞÚú×L(::=*jêÝ»{æÍ·`AJJÊQ†Õì¶ÐVVV¹nݾÁƒ]ð&ƒ\ƒƒ‡?yRWXxë\RrýáÃÚ3|¤zI$ËõÃúõû7nœSVö-Ÿo4^úšú IDATcFB\Üδ´…ee;ÌÍ W‹Åÿ˜º±»EVÇ E§O߈Ïújkwa“ªsTTZJÊÑääyåå»Çÿ4.î/ï‰Dâ#GÎìŠûB(<|Cjj^RRXyù®ÁÁë JeY ä…¸B©6¶´eµÅ0§ÊXX±ïDµ»g¤zþíúî»ËYYÑŸ~ÚþèÑ! ¯gž>}ãüù”'V­ –Ú?åîûI^àŒ…r,û€#)g×®lÈãǹ,ñ­"öJÖ’ª•ÔA_&`(gZZš®ÐŸþõõë7ö– ´>ý´ÏO?Ý}ó¦ERò¼yÉß~{2-mÑ;»FŒðX¶lUQAõ¬¬Lq+C†ôÉÍ=ÃÉMê¼hjúD"1ÀÎ.ßOÒoÏž5LLô¨Mÿùó·ddœ „”—ïVR⦧/*Jòôt‚òùF¿X¾|GLL.âîn ¸æùó—FF:éé‹&Mrð`É÷ßÿtèЀ@Ð÷Ûo—š™<{ö255/-mѨQáá£îÝ«IHØ1šj×ÝÝÞÞ¾ëÞ½E®®=»wîfb¢‡<¸§§“³³5ÀÌÌ "bôĉ+±!€Õ«?Ÿm`·¥wïØ­­B± }ÓÓÑÙÞ¾kÿþ½ví*1•õ·w? ò²ûR½!d—¹fͬAƒ_|á7eJ|bb˜‡G/ÀÌ™¾“'¯zú´žjšr‹“Swœ Æp ÊFÀ›7-ÚÚ]FŽìÿõס’%%uæñ”““oÙ9zô'€¹sÇÜ¿_ƒ³;wªÿèÝÛ OPž?™™ù]zú"\rá --B„òd¿~_Ðgœ‰‰a³fù²Ø¨¢¢$µ-z* Kª 5£zOžiw»¨¤=¹þŒ‰ °·ïŠÛ•ìŸ|¾””EÊc”±nnvtc«æR+9O•”C7„%tQÐ^†öÌ(©)‹µµõìãCLL@¯^–€ãÇ/®Püx·¾¾–d˜j` -£††W É/^4fdœHK[8r¤„02rÜýû5[·´áËËË`aa(©u®q+Ývì8)Š”•Éd€@ È —k×¶JJn„†&|mb¢$ºš€††WÔÚptô´°°QTE±X\Vö@$ûúFQuE"ñ›7-55ÏðGkk3C†ôAUW×8p:>>kÒ¤•gÏ&ߺU%#^øV !0 wròaÆëS‚‚|’’r¾þ:´®®© àrNΗAX˜^Þ…ýû¨®~RUõäÖ­*€X,Ƶ¼¼œ)[<<6mÊ}ñ¢‘’YVVÉnK~~‚™™@EEÙØX—ÇSÆ%Ô98xDxø†ºº&.—“›ûcffõ•¤—**jØeR·ÿ.]TVV¦X‚º:@#Š\·ÐÁ6 …¢~¸îíÝ/%e¾ššŠdIIË˶´ p tþä'<3~üø€zàõÖ­*‘HìînO•Œ‰™ (.¾.ËjmÜnnn|·n¦”X&‹²ÚRª3¼'ÏP´—]xŠ‘Û3ml̨+B²"Ö‡)cqÊX–Z’^¥;!‡¥°¬¯X쥒âAê>ƒÜñÁÆÆŒ^QîŠ-mlüI¼˜¡®®‘ÃÚÚ É7oV …"ww{ê¬ ÐÇ Š¨ÇhÅÐP»µUøôiÖ3t^llÌ8ÖÒÒÄÜÜPr­ËÙÙZSS½¸øzß¾=ñ ØÈHÇÈH!D%ÑâygNNãe8ææ†¿üRàp ãF•°¯¹¹uÅŠ@,ÓÒÒdÉ’Iªª*‘‘É ¯¨‰,uSÄ7Kç©tÞ±±§N]­¨øMOO/Ž …¢!Cx°$ À›Ú¦ê%e²H  Ü’˜ê7h#Ã- ¨×U«‚9»}{¾¬´oúq'§îÊÊJtKKoã¯ðBfmmÖ»úÊ•»TõqãV„‡o”e5#ƒ¡ BˆÅF©m……mn¼’í¶¯gµÚhWxøFºÂ ö"üdÿdq c@`9;R‘:à0äÐg·,r±W__K®Jt¤Žï0Ö±_¡ªª*¡¡~‰‰ÙxŽ¢´ôNNNÉœ9c%%;:vWQQ:sæ5ŽQ‰RÏÚÚ k(©C™ß¡¢¢dh¨óVÎ!²ÏЩŽÙ_,.‘U!´bÅô[·ªÜÜfÏŸ?~èÐ~ººš5YYßeg÷ëg«££¡¡¡ ˆÍÐÑÑèßß¡´ôÎܹ›Æ÷RVæÒ¢‹Ššzüø/¯È/¿ rs³‹ÅßÿÓŠ;–- äñ”MLô‡FG§ëëk¹¸Ø”¦¦æ%$Ìb( 6uêW¯_¿ÁIcc]affŽŽ†X,>vìü7ßä^¿þWŒŽN×ÕÕèÝ»ÛÑ£çÒÒŽgfFÓÅš›¾­-Åu ááÆáp6lˆ`L­’u”É®›"na@Ÿ«-^<éäÉKK—¦áÁR£¯¯5{¶_lìvmggë‚‚Ò­[âb={Zhkw¹qã>þMSSý€Attº¶ÿرóGžËÏOe5»¥8†”e£­-_j[ŒÕë7oZêë› u¸\”1~žiw»ðÂó¥K·ÝÝíÍÍ éEÔT²"jkë ϰ Œ¯š›[±cé{z²-úGü^²K—nÌÌ )5r¨b,ö"‰ä©ZÉ2|‡ñAî7ãòå;ýû‡ÅÅÍ4È©¥¥õĉKññYÓ¦ ’uuu5"#ÇÅÆfèéi¹»Û”âÄ$Õcì3ܼYéêÚSª‰l@UT”ŽùêÀ’ÌÌ‚õë³›šþÐ××rs³ËÎ^1fÌ .—HK[ÄçÙþèÑs##ÐP¿•+ƒér7N>ßèòå´uëöÅÅí¬©yÆårœœº§¤ÌŸ:õ3\xÛ¶¦¦Ysælzö¬¡G‹””Èá Å>>nZZꎎÝlmùøHÏžÛ·/NHØ»}{¾¶¿ÿ€óçSœCJKïà…ÆåË/ÞVUõÄÖ–¿wï2ÉŸSÄÉ¿â:»ºöèÕËRM‡Y¼PP&‹Œ\·HšCIær9;v,qq™¾!8x¸dIÆ‘õëgkjª‡‡oxþü¥«kÏ¥K§ÄÇïâñ”¹\ÎØ±ƒ /Ï™3WLM]¸reæ_$ÖÖÖ÷èa¾gϲ¡CûɲZÒRÆ[[¾,mmùRÛbÌ ‹Š®úûÇVVîc¤ŸI>¶£gÚÝ®×¯ß î6}úZÀ½{{ïEBÉþÙÐÐdf6Àð Ë.%cbJ9ÖÒÒDjÈ!KŽ››eÈ•+iA€_ÝÏC/&Ë^É`LªVìÖAßv¬“B¨«óNJJN>¼qãÁÐÐ$%%®«kÏ­[àW5HzB¸fÍ,mmÅ‹·=}ZÿñÇvqqAK—¦á2rգˋQQÑÕ9sÆ(˜NF :9PÖ$ƒð_B€Nw´„P(²²š7cæÌ­Î{¡¨èªƒƒõÃX[·[º4õåË“¼sç¡«ëç••û?úè}ýHÖ‡Œ,ÏàÀûC@VÿܵëTPÐÚ§OJ¾áçßÔm÷î"¬õ4<áA>}câÄ•÷ïï“õ“”‚t —ÌÄVšå^E üçihx•—w!"bB`Ê”Ïþ“á:BèС3S¦Ä_¹RþàÁ“£GÏ­^½;0p(Îi±³ãO›&ذáÀÒvvX<ÓѪý…¬þÙÜÜš˜˜3µc†–!Vƒ í„pýúìèè©$`  Bö: dŸ¡CAÕÕ5YYMÒ××Ú¹3 ¿ß½£•z/44¼Z²$5/ï|]]“¹¹a@€wLÌ4%lïË—¯ÝÝgçå­¡^¬Ùy`÷LÇÂÞ?_¿~£®ÎëX=BüÑŒ_ZJh;……WÖ­ÛWT”ÄxÇ ²ÏÐY!1C§Ä @ Ú‰:+ʶ8@ @ø0!1@ @`ƒÄ @  3@ 6HÌ@ @ Ø 1Aøgž22NxzÎÓÕõåñ|þ„éÓ×Þ¼ùë;¿t !ôìYüyÉݺMæñúú~ÞÞ‹ JåÖ:~ü‡óiUÕïïÐ"K]ê+‹p½ ôâp>UQù¬k׉¡¡IõõM,µÚ¢sÛQÜ.\†n#þãñ––,Hyõê϶ۂª¯o²µ ¨¨¨y7 žfhˆÿΞ½ù^_÷¾=Ó¾v‰D⌌ÏŸ¿üÀ_‹ÇÞ?B”!ìrÚ×^ɳ@]õm.•ææÖÄÄ—™]º ÓÒîé9/;»XA[¨¾÷ÛoOß“zìí¾UŸg¿Ž©Ë>šÑ{‚"åeÁÒKéÇ÷UAA©—×<¡Pô_¹„N‹RG+@ø Á?¥äïsãÆý%K¦lÙ2O[[ãþýG))GÜÝg®8°÷Û¾Û!Ÿ}¶PKK=33º[7Óúú¦; |}£³³WŒï%«"½!„Ð[µËR—>:Ë’I•)-Mµ°0ˆD⊊šàà„Ç_äå­y:·„@Ð÷Ñ£C††:rí¢CÙxó¦åÒ¥Û‘‘[jkë÷쉥¾›-ÂE‹¶ýIæo[—®í?n¶¶6£¥¯¯ýþ|+yöA»z¦}íB”Κ•8th¿ù½ûrû'„° à6„Å«ík/Bèñã\üÿ÷ßÿ4}úÚ«WÓMMõÚ(–…?ÿl6lÉǵ˗O÷ôt Eùù?ÿ|}qñµ´´…r-ê¨æÚUä:Rd¤R¤'äŽ~,z²ôwÐPq_ùø¸mÝz49ùðüùãßJgáßÄ „P~þEÿØêê #ɵk÷\¾\~õjº•• ìø|£Áƒ]||–DE¥Ÿ?¿åm…ž?ë矽~=Ãѱ„ÐÜÜ0))ìÊ•ò-[ŽŒçÙ–Û†,Ú8 S µMLôðG33ƒèèiaaÿõ[ªmѹ@UUULMõÙËH¤Û°²2mhx5gΦmÛhjª± d§¬¬2;»øÁƒìw9ð?ÿÐð}#õìƒöóLûÚáÿ~uç_Sß ¹ý!DÂbEûÚ !Ä*!„tt4††Úméóì „V¬ø¶ªê÷+WÒŒuñÁž=-<åðá³'N\rt Æ%OºÊØ—êY;àŒsÍápÄb$‹óó/b,:‹D⸸ææãTUF¬]»'N „6n<èãó±Á_kç--¸¸8?ÍÎ.0+«Ýjö[/û©—Õ–Ô‚÷í™v´ !äï‹âó'p¹ƒeõLÊÞeË2ttFèé;v…Ôþ)7Cògè/51ƒ~\–Óüüb°!zÉÒAq{ÑJꉠÇ$ìcåÌääÊ\¡--ÂÔÔ¼¹sÇR¦ÿ^ãÆy&'–pàtzú"ggëüü‹››[""FS-ΘᓑqâÚµ{}úØòó/66þè  \S]ýd×®˜®]ÿýÅ¢EÛÆŒYþûï‡qÅèèô””ù8œ¬1ç¬ì¾T/q8]æúõûSR曘腆&͘‘У‡yZÚB]]Í9s6®~ô(—n»[$O=¼={3>>K è«­Ý…QLªÎQQi™™ß¥§/rq±9vìü’%©¸°H$>räìš5³¨³¾áøñ Û¶-pv¶ÎÍý18x‘‘ΰaKµzΜ1ìkBY6*+s¥¶åããF(+™Aj»í詞o‹]YYÑô„ ö^túôóçS_kiuéÝ{†dÿ”»ï'ÍØ„ÖR·$ÅJÊÙµ+†2„euY{çÌèŞN&k™€}| œ‰ŸÁ{…þüó¯¯_¿8°·äÊô§Ÿö9xð›7oZ’--MÂÃ7>üczúbGÇnGž[º4ª¨ zVV¦ìç”Þ\DÄ&ö!‘¡ù;_GxQ_î dfôžpõê]ª<û% Ùñ¸\Kx·˜¸¸”ü!CúäæžY´h¢ÔsD t $fè¼hjúD"1ÀÎ.‰'éƒã³g “ÿݰçÏß’‘q‚R^¾[I‰›ž~¼¨(ÉÓÓ BÈç=~übùò11¸L||ˆ»»= ,lT`àšçÏ_餧/š4iÈÁƒ%ßÿÓ¡CgAßo¿]jffðìÙËÔÔ¼´´E£F „‡ºw¯&!a}þíînooßuïÞ"W׀ݻ ‡w31ÑC ÜÇÓÓÉÙÙ`ff1zâÄ•ØÀêÕŸOž<B8{¶EÅoII9ôýéÓv[z÷žýÐÚ*‹‘@Ð7=}@íí»öïßk×®Â#ÜYYßy{÷³°0Ä1ƒ¤— „ì2׬™5h#à‹/ü¦L‰OL óðè˜9ÓwòäUOŸÖSMSnqrꎓÁn¡CÙxó¦E[»ËÈ‘ý¿þ:T²¤¤Î<žrròá-["Gþ0wî˜û÷kðbÛ;Õôîm…ïÄÏŸ¿Äh\rá --B„òd¿~_Ð牉a³fù²Ø¨¢¢$µ-ÆVV25uxOžiw»¨„ =¹þŒ‰ °·ïŠÛ•ìŸ|¾””EÊc”±nnvtc«æR+¹Œ*)‡nK袠½ ì¹+R'¸µµõìãCLL@¯^–€ãÇ/®PZèëkIN¯ ´ÅbÔÐðŠ!ùŋƌŒii GŽô€FFŽ»¿fëÖc€6|yy9,, %Õ£Î5»Õ¸¤"2h·ë!$w¬£½'På©.áï?B1šq H½CA¥ö±±¥«W>eÊ@h¨Ë-FÒŸ**J¸!‡n;vœlm*+“áÂôÈÎ˵kÛ%%7BC“ ¾Æƒ,c”Ä)• ¯¨µáèèiaa£¨Šb±¸¬ìH$öõ¢êŠDâ7oZjjžáÖÖføn—c[[…¸ä!}† 郪®®=pàt||Ö¤I+ÏžM¾u«J,F½ð0 !0 wròaÆëS‚‚|’’r¾þ:´®®© àrNΗAX˜^Þ…ýû¨®~RUõäÖ­*Þõxy9S¶xx8lÚ”ûâE#%³¬¬’Ý–üü33€ŠŠ²±±.§ŒK*¨spðˆðð uuM\.'7÷ÇÌÌ(ê+I/UT԰ˤnÿ]º¨¬¬L±uu€J2QÄ-t°B¡è‡®EG§{{÷KI™¯¦¦"YRRçòò‡--Â(?ùÄ ÏŒ?~ Voݪ‰ÄîîöTɘ˜©€ââ벬60ÐÆíææÆwëö¿…R,“ÅFYm)ÕÞ“g(ÚË.C]]#‡µµ5’oÞ¬ EîîöÔY0 7ŽQÝ”òTI¹2ëÙ¡£Èu¤Xso1šZ— {Œ~ ȺCIí”{‹¡úÞ[Ýbp0„ÐÐP»µUøôi¾×$fè¼ØØ˜p.¬¥¥‰¹¹¡äZ—³³µ¦¦zqñõ¾}{âáÌÈHÇÈH!D%Ñâ±2''Žñ2ssÃ_~©p8Ì›„„}ÍÍ­+Vb™––&K–LRUU‰ŒLnhxE ¾ÔÀÇnçßxÇÆfœ:uµ¢â7==M¼8*І YðàÁ“ ¼¼¼\fÏîZSó, `5U‹ÃÔ€ŽÅ*)q©oåÚÒµ«±ä¶>BHA'LðZ°`KNN1—ËíÒEÕÏo]1†—äÊär9ÿ¼«É¼yËu ÊF[[~¾¾QÍÍ­¹¹«$KJꌄ˜:SVp8éŒ7¸€D˜ªˆ'ù|#Ü{é´¶ eÙ(µ-Å¡LxOži_»båúSI‰K]’ýS‘É:¾¦è (âgIó%å("Sq{ßêì3\ ÿZc–3>()qéå^¡ÎÎÖjgΔáýRzë?þXæâbCE¤”ä¿íÔY£V£QýìP_á’ŠÈoÆY®#Eš{«Ñ кcä§.É«•*I?ÿÞa–{‹aô=o1T-.—‹åÈu)ð/CžîÔH]G¡£ªª1ú›oTW×2 WW×âÿ{õ²„>|Xkccnccnmmvñâí/¿ÜÉhˆ^½ºúIbbö“'uÔAjùM]]ÕÁÁŠÃ/þ‚þ~,ìÂ…[ÆÆºzzÿ{„ÐØX×××#'§xÿþ‡*++A/\øåܹŸZµ~ýìÐP?OO§ÊÊǪñË—Ë©¡ùܹ›66æôdtmax B¨ Îj“'ÉÉ)>x°$ À›Ú¦ê%e²H  Ü’˜ê7h#Ã- ¨×U«‚9»}{¾TÉŒœº+++Ñu.-½¿ÂkfµµuXgìê+WîRÕÇ[¾Q–ÕŒü †2!¥¶¶AºñH¶Û¾žaÔj£]ááé +Ø‹ð?’ý“Å-ŒåìHEê€ÃCýÏ>ÍUÄ^}}-¹*Ñ‘:6¾ÃXÇ~…ªªª„†ú%&fã]8ŠÒÒ;99%s挕”ìèØ]EEéÌ™Ô8Fu$J=kk3¬¡¤zì“{IÍÛ.Sj1Yב"f¹"¤jBu Êc’—€äY“ôw=b._.§¬c¹ÅHú“ªõûï/TT” uñ*ðoBö:5‘#û‹Å%² „V¬˜~ëV•›ÛìùóÇÚOWW³¢¢&+ë»ììâ~ýlut444Ô±±::ýû;”–Þ™;wÓøñ^ÊÊ\zCt±QQS¿àåùå—Annvb±øûïZ±bDze<ž²‰‰^`àÐèèt}}-›‚‚ÒÔÔ¼„„Y ÅAAæNýêõë78‰`l¬ !ÌÌ,ÐÑÑ‹ÅÇŽÿæ›Àë×ý`Pttº®®FïÞÝŽ=—–v<33š.ÖÜÜðmmÁ(®sHÈ0‡³aCcjÅll¬« LvÝq ú\mñâI'O^Zº4mÄ–’}}­Ù³ýbc·h;;[”nÝú×›Czö´ÐÖîrãÆ}ü›¦¦ú‚èètm;;þ±cç=—ŸŸ ËjvKq )ËF[[¾Ô¶ë£oÞ´þìœé IDATÔ×7êp¹ÉùÍûóL»Û…ž/]ºíînonn¨H/¢¦D’ý!P[[`x†%H`|ÕÜÜŠK_p•hÑ?â÷’]ºt`ffH©ÁCc±I$ÿHÕJ– øã;Œr¯Ð¸¸—/ßéß?,.nÆ AN--­'N\ŠÏš6M ¬«««9.66COOËÝݾ  '&)¨Þ[S¡……‘"2Ûë:RÄ–+‚Þèåå^’gMê>ûõˆK¾ó-†ºoÞ¬tu퉟Ã&>(HÌ@`B¨¢¢täÈW”df¬_ŸÝÔô‡¾¾–››]vöŠ1cáq--mŸ¿;&fû£GÏŒtBCýV® ¦ËaÜ8ù|£Ë—ÓÖ­Û·³¦æ—Ëqrêž’2êÔÏpámÛ˜šfÍ™³éÙ³†=,RR"CB†3øø¸ii©;:v³µåã#={Zlß¾8!aïöíùÚþþΟOqv)-½ƒ—/\¼x[UÕ[[þÞ½Ë$BN[$oüŠëìêÚ£W/K55^pbñ@A™,0rÝ"i%™ËåìØ±ÄÅefxø†ààá’%GÖ¯Ÿ­©©¾áùó—®®=—.¿‹ÇSær9cÇ*,¼Œß`ƒJM]¸reæ_$ÖÖÖ÷èa¾gÏ2ücLR­–zS§±µå˲ÑÖ–/µ-Æœ ¨èª¿leå>Fú™Ôéc;z¦ÝízýúÍðánÓ§¯Ü»·Wñ^!”ìŸ Mffã ϰìRÒ­€R޵´4Ò¦§²ä¸¹ÙQ†\¹’æàøõ×ý 9ôb²ì• ƤjÅn„ðmÇ:¹!„º:ïÔ©¤ääÃ7 MRR⺺öܺu~Uƒ¤W!„kÖÌÒÖÖX¼xÛÓ§õlD½:I®zo{NB ʤ$´å::|8^ns,£Ù¸qžTOذ!‚ª"Ù%fÎÁ~^¤z°^Ro1ãÆy‚"Õ@ªE„@QÑUÆkâ„(k’Aø¯!@§;Z‰ÎBH(YYMŠ‹›Á¸iýg(*ºêà`Eý(ÒÖ­Ç–.M}ùò$‡ïÜyèêúyeåþ>z_?’õ!#Ë3΂¢¬þ¹kש  µOŸ•|ÃÏ¿©ÛîÝEX êixÂ;ó!œS‚$%%×'N\yÿþ>Y?o÷A½d&¶þÓ|(÷*á?OCë¼¼ ›S¦|öŸ ×B‡™2%þÊ•òž=znõêÝCq–‚Ú4Á† þ“¶³Ã♎Ví/dõÏææÖÄÄ옘©0´´±$`h;Â9%H‚Z¿>;:zê0:1dŸ¡Ó@ö:„P]]“•Õ$}}­;£ðÛÇ;Z©÷BCë%KRóòÎ×Õ5™›xÇÄLSQQÂö¾|ùÚÝ}v^ÞêÅšvÏt,ìýóõë7ê꼎Õ!ôÇÍø¥¥„¶ó!œS„ЩSW×­ÛWT”ôá,%H‡ì3tVHÌÐi 1@ „6Bb†ÎʇË@ „Ž†Ä @  3@ 6HÌ@ @ Ø 1@ @`ƒÄ „vF$gdœxþüe»¼’ !tüøçÓß~{ŠÔ×7ÙÚTTÔàãUU¿¿•–òtÍB¥^^ó„BÑ;è,Š22NxzÎÓÕõåñ|þ„éÓ×Þ¼ùë;û!ôìYüyÉݺMæñúú~ÞÞ‹ JåÖz+/)^—úŠÅ"\B/½8œOUT>ëÚubhhR}}K­¶èÜv· —¡Ûˆÿx<¥åÄ R^½ú³cm!¡!1¡=ÁSíY³ÿü³¹]ÞüM‚§ò‹m=ú3 ï£G‡,,Œ™ˆCÙË34‡ö±¦¦zròá·šèãŸòõZ¶,Ãßà?n¾wooffô«Wº»Ï>wîçwpòÙg ¯]«ÈÌŒ®¬ÜwúôF+_ßèƒO³[MòV²Ô¥”u–©2¥¥©ç>ztè×_÷ïÜõÝw—§O_ËÒ7Ú¢sAQD®]t°ø¯¼|×Úµ³öîýþ‹/’oÕK @ø`Qêh B(?ÿ¢¿luuŽ……QÛBø¿_ü@µ=l`Ì´nÞü5;»øÁƒl¡ªªŠ©©¾â¢ØËKj!Œ >|iPÐ0 m®]»çòåò«WÓ­¬Lp->ßhð`Ÿ%QQéçÏoQ\gJæùó·~þù×ë×3»AÍÍ “’®\)ß²åȸqžŠLpßö\°ÔeLë¥J¦j›˜èáffÑÑÓÂÂ646þ¡¥¥Þî:·E:•T•è6¬¬L^Í™³iÛ¶ššjoÕK @ø0!û ¹kºx…{Õª]VV“x<ÍÔ¤¤b1Båå]àp>ݾ=—Œ‹Û©¡1ìÖ­*ÿX„Ÿ?ËÌRçlìÙSä좪*pr ))¹ŽwZ[…11ÛMMǨ©y{{/*/Hé³qãAŸ u€ì4¹Çe5ÍÐàînoh¨³cÇIÉ™¢¬VZZ„ÉÉGÂÃGQåÉ;£òó×bßÖ-ššê€œœâÖVnBxölò™3›p+B¡è«¯v[ZNäñvvééùŒó;kV¢ƒC¥mss«ßºuûB/_¾ŽŒLîÞ} 'ÐÔô4hî™3eTÅÂÂ+ŽŽÁªª[Û€””£XºÉ²l‘ìfB55ø{ËH®Î ný裱Tz˜XŒºu›¼re–T/QÊHʤÎWVV¡‹ËLUUA÷îS>{âÄ%GÇ`\òÔ©«ôT"Yn‘µ]À8×G,Fb±8?ÿ"K¯ÃåE"q\ÜNsóqªª‚#Ö®ÝKOÆ#áC€Ä ¹kºÂyó’÷í+JM]xïÞÞ5k>OHØ»jU&`äHÐP¿Å‹·=|øôÌ™²¯¾Ú½iÓÜ^½,³²¢!„?ý´ýÑ£CYÕ1›7禦.¼z5½KÕiÓV‹ÅWùöÛ“ii‹îÜÙ5b„Dze;pa‘H|äÈÙÁƒ]ÓVÆtMjz‰äTO²iºæ¸.BhÈ>¹¹g$“sdµrófe}}“·w?ɵy=]]M¼ƒñ¶néÓÇ&$dxBÂ>SÓ1&ÄmÞ|øîÝßè#‘‘É›7çnÜ8çîÝÝáá£#"62²ªfÌð¹}»úÚµ{Ø{ùùÿ ô®9}úÆ®]1••ûŠ‹7@ÇŒYÞÚú×L=::=*jêÝ»{æÍ·`AJJÊQ†'Ùm¡;¿¬¬rݺ}ƒ»àM¹:ò¤®°ð Ö¹¤äúǵ3føHõ’H$–ë‡õë÷oÜ8§¬ì[>ßhÆŒ„¸¸ii ËÊv˜›þÕý(ØÝ€jB(>}#>>K è«­Ý…QLªÎQQi))G““ç•—ï?þÓ¸¸L¦t@ :’›ÔyÑÔôˆDb€] žã66þcM½¶¶>=ýxQQ’§§„Ï7züøÅòå;bb”•¹‰‰a§Oߘ9ó늊ß&OìÐÑÑgk<}Ú€«{y9,, ©êX~||ˆ›› ,lT`àšçÏ_*)q32N¤¥-9ÒB9îþýš­[îÜ©nlü£wo+Ætœž#+½D2"Šqw·§7MiNU‡:8tÛ±ã¤P(RRâ*Òʳg =J«ùó·ddœ Ê”—ïVRâÊòª,ÝŒŒtÒÓMš4äàÁ’ï¿ÿéС3 ï·ß.533xöìejj^ZÚ¢Q£ÂÃGÝ»W“°/"b4Õ®»»½½}×½{‹\]{vï.>ÜÍÄD!0xpOO'ggk€™™ADÄè‰WbC«W>yò`áìÙþ¿%%儇¢ÄR§X–-½{ÏÀ~hmŠÅH 蛞¾ ˆÎöö]û÷ïµkWáˆ¬ï¼½ûYX–•Ý—ê%!»Ì5kf äøâ ¿)SâÃ<þø‹>2غu¾ä¼œ¥:þhmm†¿Â+²­­ÂÛ·…"ww{j¥À€Þ8fxüøÀÐP‡±ê¯HÖ»ä>ƒµµ>H5M/Lµnh¨ÝÚ*|ú´ÁÌÌ@‘Vtu5 ¯( ÑÑÓÂÂF¿]-‹ËÊÈu C7\rÈ>C†ôAUW×8p:>>kÒ¤•gÏ&ߺU%#^Ô“ôNN>üüùKºzAA>II9_ZW×TPp9'çK„ ,Ì?/ïÂþý?TW?©ªzrëV@,ãZ^^Δ-›6å¾xÑHÉ”{Šóó°ëTT”uy|Xkccnccnmmvñâí/¿Ü‰ TTÔ,X7c„O×¼|ùš!‡ªnmm†%ЫSíÒ«8:vWQQ:sæ5…*-½¿ÂËÕµµu,Ï3(b)ý T9ôç~ÿý…ŠŠ’¡¡Ž"­TUU""FóÍêêZ†ðêêZü?»W¥êV]ý$11ûÉ“:ºnuužººªƒƒ‡/^ü…z<úÂ…[ÆÆºzzštŒu}}=rrŠ÷ïÿ!0p¨²²„ðÂ…_ÎûùСUë×Ï õóôtª¬|  ¿|¹œ:çÎÝ´±1§§é+h ÃKBuÖÐP›wLÌöGž鄆ú­\ X±bÇ/¿<¸vm;—ËÑ××JM]8zô²¡C?=ú“áÃݦO_ ¸wo¯¬êô&®Y3K[[cñâmOŸÖü±]\\ÐÒ¥i.—3vì ÂÂËôÇdBEEWýýc++÷ÑSbd­øÒ?º¹ÙÑ5ÿè#}„@QÑÕ9sÆ0ÂY­`eTT”ŽùêÀ’ÌÌ‚õë³›šþÐ××rs³ËÎ^1fÌ .—ë†n|¾ÑåËiëÖí‹‹ÛYSóŒËå89uOI™?uêg¸ð¶m LM³æÌÙôìYC))‘!!Ã%½äã㦥¥îèØÍÖ–ôìi±}ûâ„„½Û·çhûû8>ÅÙ9¤´ô޾¾`ùòÀÅ‹·UU=±µåïÝ»lüx/†±Eê.–‚:»ºöèÕËRM‡÷4X¼PP&‹Œ\·HšCIær9;v,qq™¾!8x¸dIÆ‘õëgkjª‡‡oxþü¥«kÏ¥K§ÄÇïâñ”¥*F B‡eÝ2 ÿ5 ètG+ÑVnß®vuý¼²r¿©©Þû^ˆE>}câÄ•÷ïï“õd„÷ Îø·²š7cæÌ­Î{¡¨èªƒƒ~ BhëÖcK—¦¾|y‡—ða½d¦iþÓ{áÿöö]§MlØpà_ÈÜ€®_Ÿ=• ECë¼¼ ›S¦|öŸ\à@:tfÊ”ø+WÊ(È>C§á?±Ï€jlüÃÝ}v^ÞüÞ§÷Gaá•uëö%1ÞuCøw@ÕÕ5YYMÒ××Ú¹3 ÿþCG+õ^hhxµdIj^Þùºº&ssÀi**JÿU{ ÂÿoÈ>Cg…Ä †ÿDÌ@ ¡#!1Cg…l@ 6HÌ@ @ Ø 1@ @`ƒÄ @  3@ 6HÌ@ø—‰Ä'ž?Ù.¯ê’”V_ßdkPQQsüøçÓªªß‘ƒ’[žÞB¨  ÔËkžP(z[ñÏ“edœðôœ§«ëËã øü Ó§¯½yó×wö BèÙ³†yó’»u›Ìã ôõý¼½”Ê­õV^R¼.õ‹E¸ „^zq8Ÿª¨|ÖµëÄÐФúú&–Zmѹí(n.C·ÿñxKˉ ¤¼zõgÇÚB Â;@b¿žjÏš•øçŸÍm뼤4„ТEÛFþÄÆÆL èûèÑ! #E&âBöòŒ¶ „Æ}¬©©žœ|ø­&ú¡–¡¯oÔ²eþþüqó½{{33£_½úÓÝ}ö¹s?¿CØ€ƒÏ>[xíZEffteå¾Ó§7:8XùúFƒÍ=s¦ ë Uº4ÀÆ}|>64Ô²ÓHäWDs\×ÝÝÞÐPgÇŽ“’3EY­´´““„‡¢ÊÃ;wFå篥¼ºjÕ.+«I<žÀÆfjRÒ±˜Í«ššê€œœâÖVnBxölò™3›p+’§‰qÞgÍJtp¢´mnn50ð[·n?Bˆå¤ ¯8:«ª lmRRŽbýé&˲E²ûAÕÔxØR»Cç… ·~ôÑX*=L,þ¿öî?®¦ûøû}o¿D¿»ýX·”U*%d+¿›ÄÂ$ó;Ý!ý¢ù]ÑÑj¥¹•‘¢I´däãG"&kDõI$RRa£î½ïïïíì~îSÛwfôz>ö‡ÎyŸ÷y×¹ÇÞ¯ó~Ÿ{I¯^3֮ݭ0KL0ò}2÷k÷îüþýçihx¾ûîÌC‡Î;v±oß¹´å‰%ÒK‰”¥EÙt̽æp8 ‘H$¹¹E,Ÿ:Ú^,–DFîâó'khx¼qc:‡óÁ½{žx¥ fèÒ:|v‹1 Š sbbËË÷øû›;wÓ÷ß_B…†&ÄÇgÅŅܺ•ä·uëaæÀøø,¡pIIIr÷î³f­—HÈîÝaã+WRîß?HÛ^;>ñرhKK`Caáµ={«ª2NŠÅOšôE[›ˆ¢0éÞÄbÉáÃgGŽt‘¶Ê ×./‘ê±GÎ,…òð•uF~q޲³\¿^õäÉÓѣߓ6ob¢¯§§Eg0-JÈÈ( —TT¤oØðittúºu©,± `ãï?6::ÃÔtÒÔ©‘ññ‡nݺ'=1"›dVUÍ™ãuãFÍÕ«4{¹¹E­­¿£B oJ{ûo#õ°°ä•+}oÝÚ»hÑäÅ‹³e2É~-ÒÉ/-­Ú´)cäÈþt’¡Ã˜çÎûðaS~þeóéÓ?Þ½[?gŽ—Â,‰Å’ó°y󾸸ÒÒFsæDGFîJJZRZºƒÏç ë%’ÿ¹Ëìi‘ÁœB$^‹ŠÚíé9PG§»L3…1¯\™”˜˜°¨¼O~Ù …@rÏì™3 ¡#ç·Õnîðe æ }{»ÈÃcñ;§Nuwwïг¶¶ÁÏo=ú}±¾zAwq8–yeä°D..—Kwò,ýúYkiiž:õãÀ½iÆŒŒtŒt !ô ßÇ™™‘¶¶|éÃù|ÞÏ?W+Œ-::ãåËöÕ«´OKK“å˧kh¨…†&47?cn3¸—¹M”Ÿß興í'N”ܾ}O__‹>¼‰ÄÊn “(™»¯¢Âeövx-={[Y™Ê$ŠÒɘ§Nu_¼xkfæ).Àa\WIDAT—Û½»Æ„ C¤“ÉR‡}r¹œÿ½ÑJ ÎÓ"¹F;; [[óñãW¾|Ùž•µN¾¥|Ì´P!D6fീ÷º4ö÷!}úXbŒ/_¾Å \&O^ëèhÅáࢢŸ™í.”ëéëkIÞáû´Í… ?Ÿ;÷ÓÁƒë¶l \°`Âðá}«ªêB„ &¦«É“WÅI÷FW××7uæŒ,è0ré÷uÎÎ着ªHÇ\\|Cñ9€Wæº4ŒñG –HN+Ûkb¢ïçç–lh¨cooqäÈùììs¹¹ÑÆÆzÁ˜°°díþýmòòŠ…ÂœèèÏd—þ“~1ÎÅ‹7èºmé6ÆÆzãÔÔ<]݉äÈ‘ó_‰zþüW;; …¨ªª0½õîm®£ÓýÚµÊaÃúJŸQfàÅ‹¶'Ožòxº\î3 Gü,‘ÓÙŒñõëU..½¥Ÿ¬³œ…³zõ'eeÕ®®Ÿ>e̘÷ôô´n߮ݽûûýûO½÷ž®n=ºùùyFDl×Õí1x°cqñÍ… ¿™2Å]Uõ³ÈĶr¥ïÑ£ÜÝC׬™íêj/‘HNž¼²zõŽU«êêª&&úÞ&:$=ûC_ß/Ÿ?‘šº’na¹)ôÀ°°d=½NN½²³Ï%%MM “î–ÏçýÙk¡:³¿ÿ¸Aƒ9Nll0û²´Î|\;¹°­Ã´Èþ¤-[6ýøñ‹+V$7ˆ¥%e` 0!""ÅÐP§_?ë¼¼âo¿Íf x¥ fl0ÆBá’µkSçÏßR_ÿÄÖ–¿wïª?|!´mÛbSÓÝ!!ß444ÛÚš'&†Î›7NúX™A˜««ýر®Ÿ|²!Ì´ÁÛÙY¤¤,‹ŽNOIÉ54Ôñörþ|b¿~þÅÅ7íì,ä3æ½çÏ_0½UT¤üñðüüKÒ¯É"¹åL%ÞÞUUÒKb”=ñUyEEú;ï‚ JBB&É”%ÊÎBƒQSS9|øËï¾;šš·yóþ§O10Ðvuµß¿õ¤Iù\B()i©…EZxxÊýûFFº LX»v.KlF—.%mÚ”¹«¶¶Ëå8;¿›˜ø¹¯ï(ÚXþ6ùû•Ï’——«¶¶fß¾½ìì,è–޽͕Ým„Ð_–-ÛV]ýÐÎÎ"=}Õ”)î2iì̵(œÝêdÌ..¶}úXvë¦Nç4X²„}\öÉÒÕaZä/‡é™ËåìØ±¼ÿyAA±s玕o)³eóæ--Í  ØÆÆ—Þ+VÌŒŠÚ£®®ª00à•ÂÊþ×Þ6#RøºƒxUnܨqqù´ªjŸ©©þ«~K),¼6mÚÚÊÊ e?@^5ºâßÊjzdä™bõ­QPPâèhE¿†‹òí·GV¬¶´§å%¼Ø]érLðVƒÿ÷€·ƒCÏY³!ž™93êòåò;wfgŸ[¿>M €×溌·zžÒÚú‹›[@NÎú}P¯N~þåM›2 bd¾ëü3!MMO­¬¦hïÚµ’þþÃëê•hn~¶|¹0'ç|SÓS>Ÿçç7:<|–ššÊÛz½€7Ì3tUP3touÍ€Ô ]LsØ@Í`5€ Ô 6P3Ø@Í”"„ˆÅ’íÛ56¶tز¡¡yÑ¢„^½f¨«{L=zi^^1ÝËt"ó%]„£G/p8TW?øË>yòÔÎÎïöíZBH^^±»û"‘HügûQÆøÃß×ÒÒLH8ô§zko) þàÁ3!e „0ÁÃ÷åàí5C—Æ<é¿wÌ@™eXŒ1>¾ì§Ÿþ»ukè°aN|>ÏÉ©WLLààÁ}¶n=Lûa:”9VCCÍÔÔ@E…û׆ݥ¥Uû÷ŸZ¼x*ícáµ§¹ùY'ËBüðá}ið_$¼|ÁÃÿ"xƒ@ÍÐ¥IƒåÙã  !S1v§ó _~™fi9M]ÝÓÞ^œœKë --M„Pfæ©öv13|?{6áÌ™oBÞÞ´.w$-QV­Ú®«;N_ÿ£„„CtyݾwoA¿~þžÎÎþ§OÿHË%‘‘»øüÉžC‡oܘN‹BH\Ü/¯÷ u˜ qssàñtwì8._„(\J„1f‚ok1Ûið2øSÁ3K›ÿ7Ý@€Ô ]šÌèY~ïž=áã+WRêê²B¡¡ ññYqq!·n¥ùÇчñØøûŽÎ054ujd|ü¡[·î1ÅÃîÝa´“û÷Òž ¯?ŸxìX´¥¥‰ôã㳄Â%%%ÉÝ»kÌšµ^,–BV®LJLÌNHXT^ž6eÊ‘‘©´±X,9|øìÈ‘.2•‡Ç€¬¬3_JäâbË?eʼ² t>x‰„ „”ðQyÝ€×FKË !$KBöö:’nmýã =ÆXW·BˆÇÓ11Ñohh s’’–z{ÁûTTÔFGg„„LB%'/>ÝãÀÓ'O^¡oxzܹs…™™¡t'´çðp¿>},BG^)*ÊßÍÍ!8Q ØÐØØ¢®®šphëÖPŸa¡… 'UVÖ&&f#„nÞ¬imýÅÉÉŠ"³£c¯;Ž‹Dbé%OÌR"…©HIYÆŸ•õ„ШQ.,Á;8ôDåæÉïêj¯0ø‰‡bŒ-ú˜ à ó ]×Õ«)W¯¦ÄÅ… „òò¾¢²¬V*+«–HÈ A}hBÈ!NB¨¼ü.BÈÒÒ„ÏçÉ¿æ+ý§D"¡ÿ Ïõ1ÆtÏáp¢£3^¾l_½Z@·[Zš,_>]CC-44¡¹ù™ü©•½ôÌá`™€~q*!ˆv˼”Ìápdæ¸\.íJz; üš5ŸÐ?--M–-›Æ¼Â¬é/“1€7 Ì3ti¾Ï ½ÑÑÑŠÃÁEE?3Ã÷ ÊŒõôõµjjnÙ²ÿáÃ&™¯HÒÔT×ÔÔP8pW8Ï ¿ÝÙù]UU•¢¢Ÿ™y†âât—™™!B¨¾¾I¦ÌxðౚšŠÌüKhð<–IKð çä·3Á3c‚xƒ@ÍÐ¥aŒ?úh°DrÚÜÜHáÞnÝÔB/Þ¨­m06ÖÆ„…%ggŸ«©©OJ:*æ,_>!´r¥¯ŽNww÷Ð}ûNUUÕUTÔ …9«WïXµJ ¦¦"݉tçvhLˆˆHÉɹPSS/æ|ûm6mÖ»·¹ŽN÷k×*e*Ÿë׫\\zËê‹m<‰Ä2í™à32~ ÁoÛv„=øNŸçç7:<|–šš }rßÒòÜÍ- 'gƒµµÙ‰%›6eÄÈ|ÿÒëBiiy.<¬Mð¦‚y†® j†.ã­ðo5CWk“l f°šÀj¨l fJB޽Àá|P]ý Ã–"‘˜ÏŸ¬¦6ª®îñ?öe\‰"K¶o?ÖØØÒù+béíÉ“§vv~·o×BòòŠÝ݉Dâ¿7æ?‹é¾ ¯Ô @)Œ±§çÀû÷š›±F1ÆÇŽ]|ò䙉‰~JÊÑì·:!Æ8/¯ø³Ï¶üúëK„P'¯ˆåŒK—nóñfkËÇøáûZZš ‡:ß›trþ–!¾t'ÿ†_¥ÀÛj†.yæ}ïÞ#… 44ÔLM TT¸ìƒQBÈÎÇÝÜ||†¥¤ä¶·‹^M¼%BB3ªÆwòŠ”)-­Ú¿ÿÔâÅS™_žŽˆð‹ŠÚÓÜü¬“Àß>ÄÿÛ‹P3ti7¥½ìÝ[àè8[Mm”‰‰¿ÿWÍÍϘÛâè8›‰óåËvCà ›6í£ë¬Ö­Ûce5]]ÝÓÆÆ7&æ;‰„–$.×û††:LêÜÜx<Ý;ŽË — 1Íòó/÷í;WCÃÓÎÎ/11›iÃ’ù]Òs¸|ðt—Âü09Ü»· _? OggÿÓ§„ò ¨º4ögÞÒ{+*îÏž½qÊ÷ŠŠôƒ×ÏÂÂ('gƘ6HHjjÞðáÎff†¡™3Gmܘ^VVݧ¥Â£”õ†jhh s’’–Nœ8!4±¢¢6::#8ا±±%5õûää¥'Å/]:­­M$=J'9`Äç~ý¬Bff†ÁÁ>Ó¦­mhhÖÕíâñtLLô™önn=ÓÓ \\lBiiùcǺš˜è?zÔœœ|´  ÆÝ½BÈÜœWW÷ø‹/v„‡ûݺu·µõ''+Bˆt–{íØq\$K/ybÖAɤi°~ý§3fŒÄxß¾}/&&3(h"K˜]ÞÞC0ÆÁÁ>Ì.¦s&ø#œ1ÆFLð**\eù¡ÇFEù»ºÚ#„' [ŒõþÒ' o˜g躮^M¹z5%..!”—÷ýSÙj¥Áƒ'O1~Œ©é$_ß/oÞ¬±·· O¯OŸþ±ªªnútZE̘áڶ툲£X¶—•UK$dР>Ì Æ!N}­›[àìÙÑ!‰D¢,³g{íÛ÷ƒH$~ô¨9/ïÒìÙ^¡ÒÒ*±X2~üJ--/--/mí±aaÉÏžýZ[ÛPW÷!ÄãéÊd‰ÇÓio=zÔÜ™÷˜¬º»÷£í !ƒ9ÖÔÔ?~ÜÊžº‹9ŠÙÅtί­=–ÆÏßa~¬­ÍèÔÑéŽú'_JÀ¿Ì3t]66|„Pyù]„¥¥ ŸÏ“òJÿÉáàÌÌ57oÞ=~üâ?\6ìÜyüĉ-¡;#„‚‚bƒ‚b™öii'6løT[[SáQ\®‚Þòó73ãWfXL‡Î‡Î‡Ð gBD"±‡Çâ;wNêîîÞ?  gmmƒŸßz– øùŽˆØ~âDÉíÛ÷ôõµÆsC¿¡33#mmùÒù|^eå}ŒL \.—¦Hz»2L¦=Ƙ^¦Š —%Ì.™£8œ?*–à;̇ùÞg溴οÏpöìO_[[›-Y2õøñMññ Ož¼òøqkSÓÓÇÏNž<‚NSÐÿ6mšÿìÙ¯{öä+;ê?ÿ¹.¿½©é©££‡ƒ‹Š~fž²_¸Pfl¬§¯¯Õ§%Æøòå[Ì`zòäÕT).ü|îÜO®Û¼9`Á‚ #F8WUÕ!„QüõDccc½ñãefžÚ·ï`Œªª ƘžèîÝzkk3¾ ¿¨èÆš5»BtñU}}“Ì<ÃÕÔTdæ:Ìù¥Kå̵œ;wÝÆ†¯£Ó%Ì.æ(fÓ9<ÜÚÚŒ ž%?Ò9ok€<˜gèÒ0Æ}4X"9­l/óï=ºmß~L"!‹Omo9rÎÎÎBOO+!áЋmË—ÏprêÅ4¶µ5Ï sÒÒ"¥¬7Œ‘@0&,,ÙÀ@»›¼¼b¡0':ú3„‰‰¾ŸŸgXX²¡¡Ž½½Å‘#ç³³ÏåæF3KhŒõ0Æ©©yºº=$É‘#ç¿þ:!ôüù¯Ýº©#„.^¼áææÀIå³gèëûåóç/RSWÒç÷ææF~~žÛuu{ ìX\|sáÂo¦LqWUåöîm®£ÓýڵʡC¤ç®_¯rq魢•Ià‹mOž<åñt¹\ŽüÜHXX²ž^'§^ÙÙç’’Ž¦¦†aŒMLô•eÀØXOÙ.ŸÏS!$?ÿò‹m ~ óux‹ÁÚ¤.Ö&àÿ Ö&uU0Ï`5€ Ô 6P3Ø@Í`5€ Ô 6P3Ø@Í`5€ &ðà]Ư;¼ù`èØ%ýX¦/¨>-²IEND®B`‚jas-2.5/images/device-2012-11-18-jas-trinks-thumb.png0000644000175000017500000007543312054221644022020 0ustar giovannigiovanni‰PNG  IHDRÈU%µ7àsBITÛáOà pHYsÄÄ•+ IDATxœì}w|TUÚÿ™Þ{ÏL2“I2é½'„šÐApD–¤H¨«¨ìîëê.⢫¯?p]éUš„š@¤Jzïe2I¦ýþ8ë}w&Éà‚çûñãg89sžçÜ{æÞó|ÏSp‰Çþß$ŸÏïëëÃZ´Zm__ŸÉdÐétµZÝÞÞþ«êèį@000`µ–ÊÃmÚ"ÞßÒ`5›v2îßîîî¾¾¾õõõ7oÞ„- …bÁ‚V«•@ X­ÖsçΕ••=‚8ñôÉdzyyegg[I$Ÿå;tJYS쨜ÏþØ–sÀ‹J!qømçöcà·øqLÝí…*VÛ»²Ñq9Nkkkll,Ö8zôh•J¥ÕjÅbq~~>ú''ž'P(…BQ]] ÿI"—DëØ´ÿ{ôtfþHÉÑ,Ÿp“Ãô pET©ÊP]B•ºÂÎ,¬ªª*ww÷ÀÀÀãÇck×®=}úteeå?üP__ÿ¸gèį"‘¨Ñhîß¿µX­ÖŒŠF£Ù2Ä·ô…·$“_éo¨¢ÊTÀl&³¸V“þéWayy9ÀÓÓ000°sçÎþþ~«Õº{÷¢G9!'žh4šòòr«ÕеX¬àryS»¡í†u€X>áÍǾ¢«<èJ…JH T*ì@À 9r¤——×?ÿùO¬…N§ @GGÇ;w Ãc˜šO "‘ˆÏç÷÷÷ètúýû÷-‚˘Y2XA[N†¡¾Ò¡ˆ$`1?^]øƒ@$‡ïå„N8á„Ï-ð›wÀˆß­µÚkGÑZUT˜qèñ¨äÄó<ó`ªûÌ@&¬˜-ÿ±0Tr߀ þƒØí4  v–ÙØo6Sã<]MÝgê¬V+J~=TòÆñÒî>#ÀbøÕUuâY‚½…5Ðo1ƒPµ îû] ¡þU«ÕÒÛKqskÿâþ/-þŸzоÏdyøSI'~SÀ{7T¡£•ær“µ¦Š [¹\‚Hde³­B!»µ!tbÂÅÂz}k][ùØrªýýýÝÝÝØ sæÌÉËËÃL à·nZ­Öh4FGGÈDbbb¢‹‹KCCƒÙì¤ÚžaØ!±ÌÆþP急¥©õÇ›j9v¬åäÉæC‡ZOŸî*(à”ÝóÓ-f#ÖÙ²eÝÝÝ;wî”H$€Ëå ‚ÄÄĘ˜ƒA$£¢¢$IddäG}D£Ñ<==ýüüàw§OŸ®Ñh°Y,ÖÆ¥ àÄãýWa@ÉÍ6`i\´œ·û¬ÿÙNQ\]ë—®âþq}à ‹3Lÿ·°¨TªB¡Ðëõ¡¡¡ £««‹ÇãiµZ™LöÎ;ï´´´TVV¾þúë{÷îåp8AAA3fÌèíí½téÒÅ‹q#˜L&NG&“kjjÿÜxŒ°ûÄêèï3™vUö5/\:@&÷`V*¯L[x²¸±ßd2šM諯¯¯¼¼œÁ`"‘ßwEEE‡–H$^^^û÷ï/--5›ÍÕÕÕÞÞÞ'Nœ8xð`DD„íD"ñÂ… Û¶mCÿêijûVa›–B$öÜïºl’ÌX¼¤çÈaó˯^Îk3[,iÓïõY-È«§§çîÝ»eee½½½sçÎíìì<þ¼V«]¿~}IIIMMÍ–-[ärù;wþð‡?ìß¿ùòåF£q×®]‹ÅbµZ±ärybb"—Ëmllüõ®vˆÐÀ´¥ÆŸ÷Í¿$­ -“g3ÒWÞ]¸òlq#¬VÐÝPV›}Æö» c``\nWW€Ãáèõz‹ÅÂb±ôz=F#‰ƒ¹HÀê¿áijû{,³`€`‘xã^e<‡cèï7ÿãƒ>±P Ë®*f-êõztÏ Î%õ|ÀÎÂ2ÿoaéesøž•÷ ãæ•Õ™ÿ¡¯œ<–CÃÞÂêïÅüQëzá‡ì‚´Å8ÔSÇ 'œp 'žÜßþôIëàÄs‚]ÆÁ 'œp‰Ç2ÙŽyû,â¹™Ès¢C§ÓŸ´ ÏÍDž“…åÄÓçÂrâ±À¹°œx,°ãšü¨ —Ë …‡‡GWWWxx¸Á`x|I¨TêÀÀ#‹ï R©ÑÑÑ|>_&“I$’öövµZ­ÓéÔjuOOOPPP¿‡‡‡L&knn~TB1Ñj" %::º³³ÓÕÕU,Óh48:îïïßÕÕ¬V« Cpppggç#¼†‘ÄZ¼xqTTTUU•Õjuqq1›ÍË–-{L²ØlvOOÏðýƒ‹‹ËÎ;wíÚµtéÒ¬¬¬®®.__ßÛ·oÇÆÆÆððp‹UUUuøðá7n<*¹à‘N䥗^ruuíèèhhhèííµZ­"‘H(æåå™Í怀€«W¯ÆÆÆ³Ùì’’’ï¿ÿþ‘ˆ¿Â«ÐÕÕÕ`0ðx¼gˆÍf“ÉäþþþK—.¹¹¹nß¾]QQÁd2¯\¹b±X¨Tª‹‹ËÐ.@OwïÞ5™L¾¾¾555´X,îîî½½ÿñ*ððð8räœÔO?ýd2™ärù#”þ_…\.W¯×ïÛ·O.—›Íæüüü;wî<&YöUH&“=== Coo¯N§Û·o‰D*..&‰çÏŸŸ7oÞ7jjj¾ýö[6›ýhÝóáD …¯¯ï•+Wx<ž··÷Ý»w=*‹kjjÊËËO:•M¥R‰D¢^¯÷õõ-(((--}$¢Ÿ°Ùì'­Â£Ás3§UèÄcsa9ñXà\XN<8–ω3Uªd< èÛÎ?2&éÉ‚ ÏÃC‹éâ¾ê¯OZ‹G€¶‹?€g‰ïdñøŸ´f}WëÙýOZ‹GNðšÜíIká„N8á„N<6P(”!þ9tg'œxžžž<~ž>}:znµcÇÛDÞÿýÇ®œÏðnøä“O”J¥\.?~|{{{YYÙ¢E‹Æg0ÂÂÂ.]º4oÞ¼þþþ%K–ÉdX*ì7ÞÐh4IIIÞÞÞ]]] Oh"N<]x€ÄÊÌÌ<{ölbbâ×_ 3ˆ†‡‡ïܹó¥—^ìØ±ãÖ­[S§NÍËËãr¹ð+‘‘‘ßÿ}ggç‡~ø‡?üá ÌÀ‰§,,«ÕJ"‘¬Vk[[lÑëõ˜/[KK‹@ ¸xñ¢^¯OMM¥R©€ŽŽ‹Åb2™, ‰ô½»œx¶ðÀR0 ±±±¥¥¥¹¹¹|>¿°°Åbåææ …šššüã&LhnnŽÏÊÊrss«««ƒ|||ÆŒsðàÁÊJÇ Û9ñ¼ãýø¿†Ø¡;‚9¹¹ÿ>N00Ð××7qâĪªªööv:n2™ètº»»û† t:“ɬ¬¬”J¥0)ƒÁ`0V«Õb±0 &“I$M¦ÿ«W€v Ñh°È F£P(0òÝjµnݺõöíÛX89`Ö¬YS§NÍÎÎ^¿~=‹ÅJMM½råŠF£yíµ×®\¹B"‘Ö¯__\\ŒKðÅ_DDDääälÙ²Å`0,Z´¨¤¤ûÅËåòÕ«WËÓÚÚ ÉdrllìŽ;ªªª***°¡t:N§{çw®]»†•íxë­·Ôjµ‡‡Vá1!!A£ÑTTTŒ7N ÀªU999èŒ0àF€+Ìl6777¯\¹òĉ …@ X­V:þæ›oººº.\¸ðÒ¥KA"‘Ô×דH$ƒA§ÓF#@àp8t:Ýl6[,L @˜8qâµk×l6Þƒý„ ÅÅÅXÿŽtÊÊÊx<ÇCj111ï¼óNZZ¶Ì"‘hêÔ©S§NÅ*BèõúÛ·o3™L¹\¾~ýúùóç=û+™L~ï½÷ï¿ÿ>@¨­­-//çp8L&sñâÅ*• ðý÷ß;vÓ¦MgÛ¶m›6mJKKCE`x<Þ† ,XššºzõêwÞy'>>~ÅŠ£FÊÎÎniiA¿5zôèÏ?ÿüÂ… “'O&“ÉÉd$iéÒ¥ÿûß­V«ÙlÞµk×âÅ‹q·mûöíŸ}öYKK @àr¹]yD"‘Ãádff¢×Ôd2?¾¡¡«›QPPÐÚÚzùòe\T~MMMaa¡@ @[ÜÝÝß}÷]FS]]é6´iÓfÏž½yófô†‡‡¿ð ...Ë—/äçç÷õõ‘Éd¥R¹råJØá“O>™?þĉÇÿ»ßýî믿‹Å¨,õFJJÊܹsÿøÇ?ŠD¢ôôôÈÈH8ÈÑ£GÑþøH “Éd6›Ñ' 33ó›o¾éëëÃI²ÍóÁf³5ÍÆCCC/^¼¸{÷î & ƒ×ÖÖÆÇÇ—––Z­V¥R™––väÈ‘îîîû÷ïÃ>%%%V«•Ãátww_¿~u #‘HÍÍÍðçÕÙÙ9cÆŒ¢¢¢àà`Ûâ®ðÍb4Y,¬!eµZ‰D"ŸÏÇ6ÍÍÍR©÷Å’’¨›Ùl>|øð½{÷t:ö׺ºº>úhÑ¢E¸Õod2ùÕW_ݳg®]¥RuwwöÙgXKEEň#T*•¯¯oCC¦Ã`ÀFˆ‹‹ûòË/333CCC±¿^¿~>­÷ï߈‰‰ééééèè¸ÿ>6÷³gÏþðÃÁÁÁf³Y$åää æ¨2a„ÖÖÖŠŠ >Ÿÿ·¿ým÷îÝŸ|ò‰m7üÂÊÎÎÎÎÎ>wîÚˆ[g€ÖÖÖ#GŽ9r¤  mïììüé§ŸÚÚÚJJJÂÂÂ’’’òòò¨T*N‡ÏÏo¿ýö½÷ÞƒérÊÊʾýöÛ9sæ à™7@èïï§ÓéwïÞ…ë ::Z$Ÿk<X133333³¯¯¯¦¦F«ÕæææVUU)•JœÂùùùÑÑÑ#GŽŸ¯R©¿¿?yçÎÐùÜ÷|ñÅ"‘H,Ïš5ëÝwßÄÇÇ¿üò˰Ï믿¯£­ë¢OrrrPPÚÃá$$$DEEÁ'↠0OIìRŒ9>ÏBBB’“““““Åb16›ÍvuuŤ`#@A85Pè$)&&F«ÕBCC“““ÃÃÉDâÈ‘#gÍš¯ƒÁ‹Å …êÁãñ¤R)•Juwwï½÷8Îï~÷»ØØXðóîžN§'$$$%%¹¹¹„ˆˆ8e¸‚›ú¡·ö4mÁ‚Žt‰D/¿üò+¯¼WÒCA¡P [tLÌ-V­Vþ¾¾D"y{{?¬ g^^^ ,pÐ}<::zîܹ¯¼ò º¥vìê‘H¤¡O…X,¬ÆK£Ñx<fŽFFFþYt:ã&~ž›êÏìÐ b±¥ k@"‘PóÒjµÎ›7¯§§§»»Ûb±p8ÛŒa˜¡¾téR•JµpáÂŒŒ "‘(‹¡‰Ëd2!Y .ƒM\‹…£6<<<–,Y2wîÜ#GŽ í4M$a#La …B£ÑÐAètúòåË  AÄápL&nû‚ÎÂV' vèl÷7nÜ8kÖ¬÷Þ{ÍfoÙ²ðᇲX¬ØØØ   @÷Úk¯Mž<7ô¶mÛvïÞ ä{÷îõõõ‘H$…B±bÅ @xxøÇüÒK/Mš4i„ sæÌùòË/áö|Μ9¸¡ªªªþ÷ÿîŠ0ÉdN7yòd5·~ýú)S¦Œ9m”Ëå±±±!!!!==}̘1«V­B;àfa«ƒ;tCEE¬[Èdò¾}ûòòò|||àj#]]]ÕÕÕW¯^mjjª¨¨H$¶¯äÒÒRh†"##¡‰[^^Žñ@gÏž=xð`PPÑh”H$˜‰ûÅ_à†¨ªªÂ™Ü,Ë×××ÍÍ g%Ñh´ýû÷Ÿ:u m¬¨¨¨¯¯¿xñ¢ÕjåñxËåè«7 [œx(Ø¡ÚÛÛ¿ûî;´1!!A§ÓUVVÒh4NùÖÖVOOO>ŸO£ÑöìÙ=Ä–ëÔ©Sl6[¡P°Ùl*• ™FÌÄíëë£ÑhÙÙÙpƒ9jÔ(GTïìì> âããáùš@ |>—Ë…ïk'~1†wö›6mÚÁƒ«QQQt:ý›o¾ù5\óù|€Õj½téÒ¯&׉¡0,ÝàÄoxºÁÇLJÅb¡tô& “ÉF£ã3™L‹Å2þ|è©c6›y<f¨³ÙìG˜r݉gxºÁd2ñx<è>7lØ0cÆŒwß}—ÍfoÞ¼ðÁ0™Ìèèh>Ÿ·páÂÔÔTØöìÙ¿òœx ñÀŠˆˆàr¹F£­PB&“¿ùæÝÐÝÝ]SSsíÚµ¦¦¦òòr©TйËýóŸÿü•çàÄSˆÖÍ›7Ï;—““ƒónHLL„t•JõññtCKK‹———@ `0_|ñ)œx€§ŒFcii).nÉ 'vè€ÓÉ 'œp 'œpâ±:§?_ìT‘Éd '\Ü­ãŠÁRÄñ=ü²: T*uÊ”)ÁÁÁ%â—ÍB Ì™3çØ^è•Ä€Þ¬Á0˜žlÞ=<<âââàÿ±F‡óöÛo¿õÖ[8uÙl¶H$‚Y+°°**•*‹á*a±XB¡·óóó±Øh.— £«cbbT*‹Å"“Éd2Y$ÁëK&“qI8¨T*™Læñx …B¡`#0™ÌU«VÁøÇéÓ§‹D"œ«4@ …еA&“¹\®H$‚J 8 &“Éf³aøǃéQ †ªbÓ„I;„B!tðÂ@&“Ç' ëëëa8#T†Áfa÷Jr8ìBAE@{{»J¥‹Å5±Ùlx¡à41ˆD"ÇÃtÀ®$z7Ñ›…B¡°X,8r¯$Úí·™ööv¹\ž——'—˱„A>>>‘‘‘B¡ðæÍ›°‘H$îܹ“@ ´·· …ˆˆˆ%K–œ:ujãÆ cùòå?ýôÓ[o½åêêêêꊣÄ&MštâÄ ÀÈ‘#“““/_¾ ÃDçÏŸíÚµåË—3ŒßýîwçÏŸwqq A=cccµZí§Ÿ~ÚØØH§Ó½¼¼àr¹|áÂ…%%%555o¾ùfccã‹/¾xáÂì‹©©©+W®&—Á`Œ5ŠF£Ý»woܸq¾¾¾Ó¦MËÎÎ^³f :òÛÅíÛ·í^Éýû÷·¶¶Îœ9³¸¸xùòå®®®b±¸¬¬,..îÞ½{]]];vì8}úô‡~ØÚÚŠM300êP[[»zõê™3gFEE9s»jµ»›èÍBoÁ«¯¾J§ÓËÊʤRéºuë:‘žžŽ¦o°C7DFF¢«/""¢¯¯Á` ¹,KYYY```__ŸB¡€ 0ùŽP(<~üxpp0…B:šaaíÚµ{÷îíé鉌Œ$‘H0¶§¦¦wž——7cÆŒüüü”””‚‚l„êêêÆÆÆ+W®X­Ö’’’cÇŽážPÏìì즦&TĹsçŽ=0vìØîîîòòr˜åç‡~øñÇy<žZ­†!¨‡säÈ©T S›?~::zß¾}YYYÁÁÁ˜´³ÝY„„„ؽ’eee‡–Ëå¡¡¡—.]úâ‹/ÆŽ‹ýÕl6WWW'&&[­Vlš˜ð[[[ÛÒÒB&“±+‰ÞÍÁn\ffæ÷ßßßß_YY‰ÅÞáî”¬,´Sww÷Ñ£G322ššš°F&“yõêÕªªªàààqãÆedd@=`2–ššš’’‹ÅrûöíÛ·o£"ø|>ƒÁD"Q$±X,øjزeË¢E‹ØlvEEEQQÑO?ýH$ða†¡££C§Ó}õÕW¦¯ÀF0™L0îºâ^F£‘B¡ÀD¨¬sNNÎÀÀ@fffMM ŽáååÕÛÛ‹eÎÀD˜Ífÿ˜¦þ•Åb}ýõ׃mFKJJFŒ /š$ƒí,Š‹‹í^INØÛÛ[TTž’’rç΃Áb±‰DúöÛo·oß~àÀt4L˜:GÁ×¼’èÝÄnNIlÊ|>ŸN§Ã×ôC{w*•JìŽD"EDDÀ0=.—íããC¥RwîÜI§Ó?úè#€««ktt4îH¥RcbbâââT*•L&c±X2™L(²Ùìèèhè+Áf³an#0"ÞÛÛ —Ë£¢¢0  ©ÀxyóæÅÄÄ`"8ŽX,¦R©0%ApppHH‘HÄCBXX˜N§ƒûLŸÏŽŽ†¹$°ÎB¡0&&ÆÍ _kˆDbXX í,öÄî,ì^É¿þõ¯QQQp‡¤Õjá½pqq‰‹‹ƒåjètúÎ;è41(ŠR©Ôh4nnnt:»’ØÝ„i5àÍBåÂ78üìïï EØÑ£ÁôéÓçÌ™c7UË“Exxøœ9sæÍ›÷°) žZL™2eˆ¿Òh´yóæ :õŒA"‘H$Ì›‚@ ˆD"Ìø‚ ÓéR©T*•â~ˆ°·üY,–mO,½Ç™ÓÁqÀlw†ËfcÛ“ÉdþÅüüü0SÑ–ÝsçεeÆÛ3àF “É0òUB&“aavvè†ÈÈH4\ðq¹\±X ônÀ©û§?ý)00ðƒ>@çΛ’’2jÔ(4÷&Ç3fÌÚµke2ÚY«ÕÿéOBßzë­øøø­[·¢oÆ5kÖ@é¸`y»€F²D"!˜2—ËÅ–¬H$‚ë&|ÈCÍ_zé%xÿÁ† àPd2ÙvEFFΙ3gÍš5¸-0ǃ\“Ʉ܅BáóùðåÙ¸ƒÑjµ‹-‚÷zSÚÛÛ•J¥íK§´´sÜÅf@&“.\èççs`X,‡ÃÁY9ðRP©T†) ~¾Ý0¹¦$ÖA£Ñà-;Þ eeehžÙ™3gŽ?>==Ïçÿë_ÿЉ‰Ù´i“@ X½zõ´iÓpn€ C¡P`ÅÃþ#ƒHd³Ù?þø#šÀ­±±ñöíÛ•••%%%hçëׯ‡††ÂŒ’(ªªªz{{Ñ¥ÙÕÕ•œœ¼`ÁÜâž0aÂÔ©Sq¯ã¨¨¨õë×'$$ .—»qãÆ7ß|3%%e„ “&MÚ´i“D"Á¦I$ß}÷Ý‘#GÊd2–‘‘hhh(--…is¤R)JûAŒ;’Fèƒ-""béÒ¥ÉÉÉT*5222**jÅŠa¡b8 IDATaaüãçÎ;vìX:>þ|øã Q«Õ0@JJÊË/¿ ÷^v( ³ÀF Óé¡¡¡îîîl6í°nݺqãÆáòÛ®ZµJ ,\¸ÐÃÃS°gÏž¨¨(­V‹*‰vHHH@Çy`aEFFr8Ô»!**ê›o¾Frqqñ±cÇx<´»ººp¦MUULï‰6îÛ·/??ÿƒ>p$[@@ÀÀÀšÒÂÅÅeÏž=hu±âââ9sæÈd2\Œ«õgàFÈÊÊ:pàÚ†$õöö^¿~=%%¥§§§¼¼œÍfcÓ´X,¥¥¥ÁÁÁ}}}*• ÍžXPPó¼ÕÕÕáX¡P¨V«…Baoo/šŽ6%%åÛo¿Ý¿¿N§‰Dp§éÒ¥ýë_ ===UUUØì õÊãñ4 FƒÍÐÀÍŽÐÓÓSWWwóæÍ––´•J=xðàÙ³gÑ>œ––æãã“bJÖÖÖž>cbbsss |ãÀTì2™ÌÍÍÍÓÓ£< _<°aI$’X,f³ÙL&6 ©©É××W(¢ìRÙÙÙ ð‡*‰]=TI´ÃC§=#‰¡¡¡P?ø£©5T*F¥¾ýöÛðí—ň#à€J¥Š‰‰f6‘Hܾ};™ÉdÂåˆ@"‘bccccc£££ÑÜÜܰw 6Fswwçr¹¶99mÁårÑBTЄ†Ù(%ÉÖ­[ B```pp0‘HĦI"‘‚‚‚°Í$™Ølö‡~Uš1c†m2;¥Ri›àëëN"‘ÔjuHHˆJ¥ŠŽŽ^ºtiXX‘H”Ëå111ÑÑÑ™óóóÓjµ!$$ÄËË æw„ÐÌM4 ^vøËÄfûDFFòù|ÛiÚÂÃÃÞMLIìÖP%±^ ¿éy>ŸŸ––F$/]º„KYcd2Y¥RUTTÀ5ŠÛJþ2h4.—{÷îÝÿ~¨§ -,6›m±X ƒíÆeÀV{{;ÊÉÂÆ®®.ƒÁðJÐÀliiÁD0 h 쌎@ , zÀf³Ùl6®'Ìæ ÿŠ+ ð˜ùˆ®®.:nµZÍ'OðtC||<…Bé~ x<ÞÛo¿½jÕ*˜ A*•BϘM>rÅb±-¹’˜˜¸jÕ*§õÁøúú~øá‡hã‹/¾8zôè„„tëÀáp’““±Ó~ & Çh¬\¹:@ùˆÕ«WÃWØ[o½5ì…€™«¥R)Žàñxr¹.qlš0Í0|AÂÒ óæÍƒÎ'<oýúõQn¿<À²”•• …ÂøøxÔ€wuu¥Ñh|>ŸÃá¬X±"+++((èüùó¯¾úê7ZZZŒF£H$ ܹsgss3öż¼<™L†>BL&S©TbÕA0p¹Üï¿ÿå#šššîܹ#‹KKKÑž7nÜxûí·mùˆššƒÁ`ËGÀã´ç„ h4š^¯G­¹ÈÈȉ'Þ¼yóĉØ“®£Ñ˜Ý×ׇM󫯾ڵkWllìæÍ›ß}÷ÝsçÎeff¶¶¶†††~ýõ×€ÆÆÆ’’’¨¨¨ëׯK$[câù†º¡¶¶ÝFEEõ÷÷³X¬þþ~6›}üøqø9þü‰'üýýÇŒ£×ëïß¿ïÈﲪªêûï¿Çñß|óMnnîûï¿ï]*pì@&“}öÙg(QTT4wî\‰DbËG„ûÁ••uðàA´³ÑhäóùƒáÆè4‹‹‹?ùˆâââÐÐÐþþ~qïÞ=˜½¾¾þ·¶ª€]º¡¤¤ääÉ“XcOOϱcÇ wƒÉd ‚—³É³³³M&SNNNmm-ó9‹Å01 ,, ZI C©TÂGǃ)h}||ÚÚÚ0>®×"@ ¼ùæ›G•Ëå耜œlUÁjjj(Jcc£-qèС¡ùˆéÓ§Ã …rïÞ=*•ŠN›;‹ÅÊÊʪªª Äñjµò...O2¹þS ˜8ÿ</""û¢J¥‚ÇàÐ&'‰° 22;“_»v-´`a#|2ÅÇÇúg*•*** 2èL&£à°òBtt4¤¡±\]]Q>ŽIEù‡ƒòp)@>B*•B>›&¤N´Z-‰D ÄøxùHðØå#ž{ü¦é†aÁçóSSS‰DbFF†ƒ|„R©¬¬¬ …V«µ½½ýWPÒ '~CÀçnËåmmml6;++ëIéäÄs¼wÃÀÀ€B¡ÚÙÈ '†žn`³Ù0sß“RÈ 'œp 'œpâ9iø.xxxŒ5ª¥¥¥··W$¡Ž CC(ÂÃr¹­¸ !‰t:]cc#Ú(“Éx<žÉd²-Dm ‰DÂd2{{{JŒã “ɸòévA"‘°:Ð\.—ÇãéõzÌKLÝÑÑúßBÅX,–#¾!ðŒßjµÂ¤R)‰DzF]$ð•)üüüÜÜÜh4ælÄápÖ¯_úô鯯ÆQ£FýùÏÞ·oŸ#C …Â'NìÝ»wÔ¨QèµV«7o^rr²ÑhDÃÌ?ýôÓššš×_WN£Ñtww£÷F*•ÂŽŽŽÇElݺµ««K"‘ ‹ƒáí·ßNII9{ö¬F£Y°`AoooUUÕÆëêêúûû±XVÀĉ,X³tuuÁÆäää‘#G P7oÞZV||¼J¥Z¼xñéÓ§_xá777ƒÁÐÒÒ#Až­zv臃s8‡Ãd2M&Svv¶íÕ š:uêÔ©Sq!A¿ÿýïag@Àd2q~5•••|>ŸH$fff¢íF£±±±çÀçóçÏŸ¯ÕjÑPˆ¦¦¦3gΓÉôP"à‰ä7†¹6>ÿüsè¿;kÖ¬ššèÄ`0\]]QO @ff¦Ñh„ù?Ðv±X¬Ñh0?ñ!péÒ%Ìýz̘1f³^±Xü ê?YØ¡êëëQº¡®®®±±ñæÍ›F£æ;p‰‰‰íííF£Q >|xïÞ½³gÏFéÍfó'Ÿ|òÎ;ïà^^0ðhÓ¦Mh#—Ëåp8r¹jÇãñº»»%ÉC‰Ø¼y3ŸÏÇN$!ø|þÔ©Sm˶´´`¹hnÞ¼îææöî»ï^¸paݺuhÏÎÎÎõë×ïÙ³wæ}ýúõÿ÷ÿþêâð÷÷Ÿ:u*̘B,FƒA£Ñ.\¸°dÉ@}}ýùóçÁ3…ü±~Û~÷î][ÏÚÒÒR½^ÊãñD",ÙŠ†¬°„6(zzz²³³qUUU_}õUaa!zÏ`<¸^¯g³Ùîî€Ù`mD ‡bš—/_öóóãr¹===¾¾¾}}}¨“ `°žH$òððÀù¥åçç£Ii ÂÂÂÚÚÚh4‘H,**òðð€? ¥R) sss‡P«««ÝÏÃú>…ÂÐÐPG|­ÀàI lA§ÓCBB ãÀC‰ð÷÷ Ec'‡6e???è¡ s%8­Ïåra’ G8g™L÷! #$$º¸MŸ>ÝöÙæ„¿E<ÝH$ƒÁn d2Ƹ¸¸8ÈÈår>Ÿo4¡à þ€®8ÓÉ®•J“Ù¡6Ýã³Ù쇚@€"¸\.f:"B H$××ׇ¾ô#Md2…Bqœýù5§üýýa"ØÈårׯ_æÌ™ÆÆÆ‰'J¥ÒQ£F »“J¥£GNNN†\€ŸŸ_GGŽ ˜?~rr²Éd*++ÃÚwíÚUUUµlÙ2Ýàî"‘èøñã{÷î1bDtttjjê¥K—°>ƒ‰ðôôtqqY±bÅ‘#G†Á`0f̘1bĈÖÖÖ°°0gA"‘<==·mÛ–““ƒ³mŠ ‰R©tÅŠW¯^Å6‹ƒÍbÛ¶mb±¸ªªŠB¡°Ùì§ŠñÂÓ ýýýUUUh$4‹Åb³Ùt:Ýd28pàÚµk8u»tCSSÓÙ³gI$ä0T •••<H$âÌ~“É„A‚ùóç{xxà¬Â%K–À%>f̘½{÷ÖÕÕÁ¢èC‹ÈÎÎŽ‰‰Á…cØa0¾üò˺º:çø,Ìfó­[·Z[[m­[ "ªªªòòòplÜ`³ P($ 2)b±8<<|XY¿&° !Ý •JQ+¯¾¾¾©©éÖ­[V«•L&¯Y³æïÿ»#Cs8œÎÎN©Tzøða°mÛ¶{÷îaN•f³ùã?6™L¸7 LfK¹b`³Ù0WLuu5Æk'%%uttH¥R˜QŒ£Á[ƒ‰îééAýƒ‰¸¹¹ìÛ·///ÏñYØŸÏOJJêììÄ¥9ÀD&Mš„ !bË–-)))Û·o_»vm}}ý°Æ_G7¤§§_¿~·û±K7¨T*ßÂd2ÝÝÝa–`÷Zèõzôy Q]]ýÕW_¡;âââîîn˜NîòåËiiiæË/¿ZL±cÇWW×êêê¡Ep¹Ü­[·îܹ“ÃḺº:> »°Ëh ":;;“““m >ÚV^^é±g•À¢@áVcدÐéô   h$ …¹Grª Àb~üüüpïh» ‘Háááaaa¡¡¡Ãvf±X°³B¡x¨Y‡'‚ŠØfš ~~~!!!4™6mºp‰çÑ žžž£Fjnn¦P(‰¤··×ºfúïëë£Óé...L&—@A$y{{£ü5ƒÁ ‘Hf³fŽ–q€é{ôz½ã"ÀÏÙál õ˜˜x …µÀø6(Âß…BaµZàgÛ e+‚Á`¸¸¸ðx<‰äqÏCÍf3FS(8b®6› ³Éä‡A  ô°puuåóùz½7£1cÆ üìÐ l6ÛÛÛ;4…aægΜihhHKKãñx'N¼~ýú°ú½ýöÛ£G>{ölJJН¯o{{;zâ¡Õj,X€³¢améòòò±cDzÙlô@Æ.0}úôøøø¶¶¶ÐÐPE¶mÛÖÚÚ u¬ú&¸¸¸ÔÖÖbä“¿¿ÿÂ… y<^hh(.¶——.ÛL||¼L&[²dÉéÓ§W¯^mµZSRRÐm«],K¥RMœ8Q&“¡‰ïíB.—öÙg555UUUéééýýýiii×®]Z‡Ã1bÄ”)Srss‡Î¼1gÎøóhmm}ï½÷ŠŠŠZZZÐuü‡?ü!--M"‘ܺu 7ŽºÅb¡I5aêp …b2™:d6›q$ä`Þ ÿøÇ?àêæóù¸ôT€ÊÊJøË@­èêêj?þX­V£>-`Á‚^^^èÁˆÁ`øê«¯¸\®ã" …J¥âÜ4233ûúúø|>n§ÜÛÛÛÕÕ…ó¶P©T¯½ö–Ü âÒ¥KuuupéK$’S§NáÎaìŠèìì,,,T©Tß}÷]]]ß|ó ül6›½½½qO »"Z[[ jkk1× EŒ3†@ ÀŠ) ÅvÿWYYI ìãÅÓ ,«­­ ¥Úšššrrr¬V+tq0wJkk+¼GŽÁ uìWn6›ÿú׿â¬èÊÊÊ#F †ÀÀÀÝ»wcí0·=Ì‹ŠP«Õ~~~{÷îE¹€¡E6oÞœ’’²mÛ¶µk×b6l P(¸7 “É,,,Äèb˜YŸÏçã¹¹\®Édb0vß›ƒ‰øýïÿùçŸãýýý½¼¼ Ь™½½½ØJb2™uuu¸Å=˜»V…B9wîÜÖ­[W®\¹nݺ¨¨¨Y³fíÝ»ë|ýúõK—.án ÄÃÑ QQQííí¸ã[»t ˜TÎjµân0në0›Í®®®‹/Þµkzojjj¾üòËââb»\—Ë…çÄŽˆDFFVVVâüXŒF£m(úÞ½{¸Æ¼¼¼={ö ===T*•H$vttDGGã–]:N¥RõööŠÅbô=n×ý•J½}û6.Þ`³°‹aEz{{www‹D"­V«V«q'ÇeÙF7xyy¢¹h†L"‚ƒƒ¬\W!.i¸]°X¬ÐÐÐÐÐP…BñP"|||‚‚‚yî2 Çù©T Ód2™L/”H$‚³€ù †<åðùüÀÀ@}4 7¶#=Q #00Öó÷÷‡)Bp⩇——×Ì™3áo·µX@§^ÛÊR±±±¸Gæ j[$È.¸\.– _£Ñà, »"Øl¶F£Ñh4¶:Ûª-|>ßnO»`±XØ4ô¼V‘HT*•*• —UP,ÛÒ¹jµVÂqDŸ_xº! fÀÅLq>ŸÑ &“iÇŽgXÃx0lÚ´É`0Œ7õCŸ4iÒ‚  j$§§§Ã]k×®…0èt:ÜÛÉÕÕÕUUUëׯ///ïëëC÷[vEp8œØØØÉ“'ß¹sõð|ýõ×ÓÒÒ¤R)j9®Y³f```Á‚………hg˜ç“––& ÇŽ›ŸŸ¿nÝ:…Ba±XPKÍ®ˆùóç‹D"©TZZZŠóÑHJJ‘&F&“½ñÆG¥R©Ç‘ £_ xº¡¯¯D"aç$yK£Ñ8vìXôàb0ºÁ.X,VFF®Â7 ƒ­>vìØ×^{ g껺º¾ú꫸ª`¨‘Ì`0<==qû»"Z[[ ëêêp‘V«ÕvÏÞÝÝ KÉa-°\ÅŒ3pÕ~ø!++K"‘øùùݾ}ûðáÃh1ÁÁDôõõ)•Ê7n 6Ê`¤É;wFŒ±cÇðó¡xš`‡n(--õôôÄ._cccssóíÛ·Y,ÖäÉ“O:åà)ØØ±c™Læ?þˆ>98––†3†a•JEÛ‹ŠŠfÍšUTT„s3‚¯<ܦ5’ÿøÇ?Z­Ö÷Þ{ïõ×_ZÄ`¸víš]+šÁ`üíoƒ‰ !Èd2‡Ã5ÜО eÍš5Ÿ|ò‰‹‹‹­ÛÅ`"þý†nß¾}Ë–-˜[ŸÙlþè£Ìf3îP!44´³³²Þ víß'ûtÃ?ü`ÛÕl6ïÙ³ÇÇÇ—y0ºáÌ™3¶µµµ|>—¦Ñh4ÚæL¯©©!‘Hõõõ¸ J~~þž={l'`…ôö&b0 Ö³  Ç èõúŒŒŒ¢¢"­º~ýzø€)((HMMe±X¸·¹]f³¹¹¹·àp¾£"‘øæ›o¾ÿþû¦¢¢B¥R …Âg/Y<ÊÂÙ-¹ùPC9xO¥R•J%ô‘r¤?—Ë…{sµZíïïï`Â:îàø¶ÁgCÀÏÏ/88zÈår§,“É‚‚‚pœ§]‰Äààààà`XbcêÔ©¸ÂŸN8ñ†N§›5k–D"‹ÅZ­çžk°@·m¸0·`g|¸Ã>»`³ÙjµÚ–°ˆ‹‹Ã± G«ÕjµZÛg’­‰vvþÅ^Ðd2+e;´±XìîîŽ}뀱 4M­VÛ–bxñÀ]ŒŒR©¥¤êëë׬YSVVf0†õÄõóó›7o›ÍŽˆˆ@=B—-[–ššŠ3³ÓÓÓ/\¸@ Ö¬YƒîE  Î’Ÿ4iÇ?~¼-a;Õ‡µŸÓÒÒnß¾bWXu"===##cØÙ?þý÷߇ÎÄëÖ­5jn×hWĶmÛJJJ^y啪ªª_|vhoo‡.F£Q&“‰D¢¥K—Â@™LæˆÇóÓ‰L•ÒÒRÈ Ìȇ1ïúíååkSaŒn0 8+¬¼¼Üb±à¶Þ å7Þ=z4º¦Óé3fÌÀ=Æ}úåË—1J«Õ¾üò˸CûØØXL1nÜ8èz;´”uëÖ%''Ÿ={V¡PìÞ½z7`EEÌŸ?¿°°šú˜òvulß¾½®®ŽÏç×ÔÔ â<==;;;qé*ãããazÔœ\¶l™­ó¶mÛ0^|ñEØ¡½½Ó†Å¾úê«pc'—˰xºÉd–••¡„¬§j2™ŒFã¨Q£h4š#tƒT*­ªªÊÊÊJIIñôôÌÈÈ0¨ bee%¬ŒüTWW{zz~ú駸`ŠÁð駟•ÚÑÑa›A$===¡©?´Àãñîܹƒ6ŠÅâùóçûùù¡i±ššš®\¹B§Óq.+ååå&“ 绌ê€u¨¨¨ÀtÈÎÎ>{ö,6~BB°Wà©…º€Æ~455µ¶¶æååY­V"‘xúôéíÛ·Û†ãPPP Óébcc»ººöïß?f̵Zþþ ™m2™ÐFLÑÓÓøé§Ÿbíƒe=hoo‡”Á`°õFBE@SúÚ^¼xq[¶lINNÞ¾}ûêÕ«±Fø£Ñh8rB¡´´´(•JÔ‚n€:àèL‡9sæ`Y!‰ÛyjaŸn, @QQQ`` Ž ·K7X,–û÷ï{zz~ûí·F£±¤¤ÄÃÃ÷fA«…cßR*•‹-Ú½{7úÆ6ã`ÀDOOOµZ{ÙêˆmnnÆ…ËÖ××õÕW¥¥¥(Uæêê cpGLƒÑ ˜vé†ÄÄÄ={öP©Ô´´´£G>Ü„Ÿ-`ûM:îëë‹{oooxHÇd2}}}<ƒƒ1FäÌŽÃá á3­T*ÖÓÓÓÏÏÏlæããã`zËauP(4Ëå¾öÚkŽ ë„¿!8”»ÁÇÇænÉdð°vØHm…B‰DÅV«Õæqpssëéé±X,"‘H$Á+ÖA"‘øúúâ|è<<zôhàÏ) IDATJJ Úû:´ÃM&Ž àr¹¾¾¾MMMh‡ëׯ÷ôôp¹ÜÚÚÚC‡ݽ{ÇâJ$’ øûû£dN§‹Å0.cƌ𑠰«$:Zyy¹Ñh´e¼¼¼¸\.ºª FddäÌ™3q¨uuueee===­­­ÇÇéòù|›{÷TO7 †ÈÈHt{ÞÜÜÜÚÚšŸŸë'NLOOwdhŒ Àï‰Dìý ~À:`_7›ÍùË_lƒªªª¾ýöÛ¿þõ¯‹ëŸ= Åb±P©ÔÕ«WôÑGè·H$ü… d—˽ÿ~nnî¼yó¸\îwß}7sæLH¬ØUÃåË—/\¸`—M Óé(£“j@éhgLI¥R‰éðÉ'Ÿ¤¥¥Á·@èéé˱±±Ñgž§ çÝàææÖÜÜŒË63l/NŸ>]­V—””´µµ9²ºº:///55•Ãá\¸pÍfcÐ/Ú†šŸŸX0k#ÚÛömÚ´)33wRÞÐÐðÕW_•••¡dÁ½{÷RSSƒ‚‚*++ £££…Bagg§]%ÑÑìn1 ‚N§swwG¯FooïÕ«WKJJp¼¦$ª !!r„#GŽìêꂳpuu‰D¸’H$˜¡Žu>>>~~~C¸Gët:??? ˆÅbOOOø@ÒjµðU8˜’CÃÅÅÖNs¤3ª$ªÆìh4L‡)S¦8ó&8áÒ "‘ˆF£Á àqãÆùûûWWWkµZ±XL$qY„m!—ËQ;|„ ÐP‡Âuuud2Y£ÑX­VG‚Ä¡MÞÓÓcµZÕj5‡ÃÁ¸©Tª×ëe2Ü  ±X,‹qªÃ`J .—‹‘ C£Ñèõz¸‹Å,€JBóf®ƒµÐ`<”æ@•Ôh4/ƒu°«‘HäóùÐm÷õõ…Ü#þòL&&•d³Ù!!!8ÎÿvèµZ- ±=B¡X½zuLLL^^žD"yýõ×=ÚÕÕÅçóÃÂÂ<<<†ÍýÎ;ïäææ¾òÊ+5550ˆ@&“µµµÁS}£ÑKÆa§úè´m õÔÔT …2uêÔ’’’èèè„„½^ߨØH$7oÞüã?®[·.??¿··—H$®Y³F$Ù% d2º§D•DCØÕa„ L&sÒ¤IYYYééé T*•Á`,[¶ìÊ•+£F‚JÂ<Ž+V¬(**âr¹Ÿ~ú)tÁX»vmWWWjjj~~>¦¤¿¿¿ŸŸÆËÀ7nÜ Ñh0·9ªÃ˜1c’’’&L˜‘‘->‘H”žž~îܹÚÚZÇápø|~ww7Ü¥ÁY(•J©TÚÕÕüâ‹/VTTtww«Õê˜+ÏÝÝL&÷öö* ¹\n4¤R©\.G:›Í&r¹Üd2Q©T@€.e;tü?ÖЛH$šÍf¥sïÞ=???ÜaÖ„ ¦NŠ3ΉD¢··7—Ëmii)//ïïïÏÏϯ¨¨`±XF£ñÚµkÙÙÙ.\Àù0ŒèèèY³fá\@Ož< Ëà477gff²X,øÈLNN†>t:= €ÇãÁ¼ ÇŽ³%  ƒ)9¬‡ÊÍÍåóù^^^b±žÒÔ××———C²SüâÛÐÐÐÖÖ†¹`…‹/jµZÈh@%“’’ íâåå…uðù|ÛèÁÁÁÐ`G L’k4W®\SÒŽ?>...>>~æÌ™D"Q&“1 ¸·“ÉdÓ¦M¼ôÒKË—/‹ÅŸþ¹B¡Ø°a‘Hܲe‹F£Ac•“’’öíÛ7vìØQ£Fáü]XXn€ÿÇamHXýáþýûmmm0•¥@ 0›Í¸4Ôq‰¡~ýúõàààŒŒŒ×_=''Çl6ÿùÏÞ¼y3\æ/¾øâ?þˆ»FD"‘@ ؆*À»°OCCÜ/;öôéÓ€íÛ·ŸjÔ(·ueeeÌÀLñ–––ŽŽ˜ZþäÉ“ãÇÇùÏ˜ÍæÖÖVhXUTT´··Cc§³³Ó–JŒ°ÀF@{b†ŠaEÔÕÕ555ÕÖÖúùù]»víûï¿Ç@gÑÔÔtùòå!® vaß»å©{zzNœ8áííÝÔÔäã㓘˜ØÞÞ^WW7qâDì@º¯¯/..îêÕ«,ëøñãIIIçÎûe ᜽†€Á`¸qãFYY™]'[Œ;677·¾¾¾¥¥E¥RùúúæååÍŸ?_"‘@Ž: 777‘Hd[›Ó‰ÿ(Ýð—¿üÅÓÓî|U*•R©„/ŸÏ‡>z0-âÐĄùíx¹„‡‚]2™ #÷]]]á¦^*•j42™ìû3”J%:‹É“';èÝàÄ/ǘ1cž´ $I÷3Ìðá„N<<°±ŒŒ„‡Yt:}XoR'œvè@àäø/§z{{kkk‡­ì„N8á„N8áÄ>˜‚Ãáèt:©TÚÝÝËìc ˜}Åjµâ",üýýG =üÕjµmtЉ'úûûººº …Â!òD°X¬Ù³gÓh´öövOOO‹Å2D:ªÇc0CÄn`:øúúÊåòŽŽŽÁ‚0êêê¤R©B¡"Ý!¦t„âóù¨o1 ;z‰„N§÷÷÷?Ô>855U,WWW …Bèçþ°Å ÑiÚí@§ÓÑå÷n JHH@CÝãââÂÃ܉F£™={6îH$’åË—ß¿FìÞ½Ûöüƒ§§çìÙ³KJJ F\\ÜÔ©Sa"»3™9s¦@ ¨¯¯ ãóùï¼óÎ`â:„­[·Ž?~X‹/bî¨ÞÞÞ/¾øâ5ªC¿ÉdZ¾|9ÚÁb±¸¹¹½ð ðŸ¶!Š*•jݺuk×®ÅùA/E&“É4 Œ†‰D¾¾¾ðȤ°°0&&ÐÖÖ&ài/L/Ïåd2™——×`Ñšè4áê‡42›Íöõõ‰D ã7Þ@o+žn Óé úb€õ´Ð¯‰D"˜¯ÁÖÉ:£-f³ÙjµÂT0—.]ÊÎζ«=ÄÀÀ@gg§Á`ø÷¿ÿEÛÞìÎÎΞžž+W®X­V\ˆö`:Lš4iè<”˜°6bxxø`yÂQ¦M›ÖÞÞ>D™tT‡û÷ﻹ¹€’þ82är9{E|ZZÚºuëèiÜÈF˜Äï‘#G† H¥Ò””ù°dɺÑ!›F£!òÝ¡(JJR‰D“ÿ2Ë l6ÆYp=zB¶ªT*òÈ#ð¿t7rSM&SaaaZZ‚ 2™L"‘À•™J¥‚!–ÁõôOp64hœ»¡ó ƒ[¥Åb|Ê”)Á`pôèÑp?ûÒK/©ÕêÒÒRN·xñâñãÇ2äá‡4hÐÒ¥KFã²e˲³³\Œþüç?+•Ê—_~9>>þé§ŸÎÊÊš>}:ùkÖ¬Ñh4f³j4`\c‚³páÂßþö· .´Ûí”!UݵÒdíêèÑ£A\\œP(ôûý;wîŒkÀ,Ôß ( dÌ2”——ßqÇÌ©¬¦NJ¹®©‹ŠŠ¦L™rìØ1½^íñ¥R©X,v¹\(ŠÂeYuuu\\Ü¡C‡ …Ãáhnn&»0…l8™ rîÜ9 B¾Ìž¯P(Z[[kkkéèΜ9CñtŠ µZMlqYFs„xá…ÆŒC×›“oBü.-- ¹Å…a|„¤¤$±XŒ¢(Ô&‡»­Ñh´Z­°¹ Š‹‹ ƒët"Ê P(l6œ "Ê ‹­V+e%•J|ðAB›0sæL ÜÔd–Á`HLLDD¥R%%%Ùív Ã^ýu ÃþøÇ?>ðÀcÆŒ1›ÍP‡n2™Ìf3ôØ#n²`¨Òh46› LÜÃ0«Õ £‘'&&šL&ò #Ôjµ^¯‡D”97ìLÔwÀ3)" ±Xl6›[[[û2´¸÷Þ{u:]uuõŋǎ+:tÛW™LF™q)HJJ2›Íb±X©Tæäääää°Q´ †¸¸8ºŠ5$† ’““ÓG¿“É•¥dA0 {òÉ'¡r¹°°~hH.@§(À*•*Ü Ì˜1cèé¹6®/C¶¤T*5„“÷À%Ý ¡nÈÎÎ5jqÑ`0$''CYá–Òl6ËåòeË–Ý}÷ÝEÑôôt²AÄË/¿\ZZŠaXaa!ÌÆ&Å<Œ%9qâDÊõŒŒ z?^²d ´ ®@-³Éd‚m—œœœžž#OA†@ X¹r%}sZXXÉd0÷'̪’ŸŸOéX” ž{î9¸}6™Lô ÖJ¥2++‹àÅ_¤·IFFTñÀ¦†Ï`0@ \.·Ùlƒ†KþE‹ÁY)dKÆ9sæ¬\¹€ ÈK/½Y2™¬ã…P7H$òÆþ™gžÉÈÈxöÙgu:T;½ð 0óLWW—Ïç5jTqq1]+³jÕª 6À³É¤¤¤œœr¼špö[¶lùðÃ)©úL&ÓìÙ³óóó)k N—““CŽ_3þüuëÖ-X°žu“Ÿ‚|ƒÁÐÖÖ.l ðù|­­­á4¨á À(x===6›mæÌ™™™™”cìåË—Ãt:ä‹.—«»»›®yïêê‚ÌÙ³g'&&.Z´(..Îãñ<õÔS€¬¬¬+VÀôʰ“ÁÔy![²¦¦æí·ß†ÁŽŽŽS§NÁOH¡Pô¯_nuCOOYŠ¢èÞ½{ËËˉðb(ŠB«’«W¯vwwÿðÃz½~øðá”[·¶¶'Þìí#œNgww7åMà ‹ô1¯¦¦fçÎäL;€††¸6ÅÅÅñññ0ƒ0ñDIAž~úiJC2¼^¯Ãáhjj ×±Âp8mmm‡###ãøñã»ví*(( صkLÝK¹á… èÙäjkkaÓeddìÛ·ïÔ©SÐü8tèбcÇìv{BB¡£Ù’@ ³³“x/0§$ ¹¹™¢/è#B¨(Ö 8Ž?üðþté‚ ÷Þ{/\ÓÔÔÔ'$$Æ#Gް œO€“}Dkkëßþö·ŠŠ ‹«’’Šò×`0¸Ýn¸u ?ùÑ^ýuúò(j2@Ñ!C†À}øôéÓ)Ê?½^¿oß>ºÅUvvöÆáozûþûïzè¡üüüsçÎ%''ët:¨‘' !g4½^?~üxúõAƒÁã›ÍFëׯ‡¹Î06œÂaP™LƒT‘ç# X¦¤Í…X,†{`N§Ñh1™L±±±†‘Ÿ‚ E7nÜH?3 ò‘…_¶l}ÿA.e€¿ ¬N¯×›L&¡P˜{V«5&&&11‘r– ÓéÞxã â¿ð–J¥r¹ü­·Þ b6›aS hy!‘H0 p7oÞˆ#(BQ.ÆÄĬ[·®\'NœÈ>ùhÿ€„íöÃS@;ÊEhÈKA^^^ÔÆ!pÁnÏ+—Ëé]Ü`0L:•Ë9bEá AéÕÝŠžÉÕ <~É f¦ˆÏÈÈ€ñ¥0=\.w:&“ ¦9ðûýÏ>û¬H$êèèðz½éééZ­–ùƒÇ/ TuƒD"ñûý „ò~éÒ¥iiiË–-ÓétK—.¬Zµ*hµZ§Ó Oò‹ŠŠX²æñ AuCcccww7q~‰¢è¾}ûèê§ÓY[[ÛÝÝ}êÔ)NG_0òø%#„º¡½½ýÓO?%.â8>mÚ4BÝpÿý÷ÃÝJuuõÝwßm4ÍfóñãÇù‹7¬_¿>!!n4 …Ùl†»h¡Ph±X ¢ÅbùyXjó¸yéă?nP7`VTTMè uQà=ò¨Q£PíîîîêêB„ëÇ#jÜ0bµµµI$’®®.¥RÉÙcš}®^:FŒA¶…š2eJ¸’™™™dŸZ›ÍFqj5ð\0hÐ «Õ.2`ذayyy”S­VË«s7é`vÏ=÷$''“­ŒFãÒ¥Kkkkb’ '&&R+0 “ÉdÐøS£Ñäää@Ÿ“É4dÈEe2YNN´A=þúè¸qã ûåªU«.\È`T4oÞ¼¦¦&JÜ‘@ ðâ‹/N»Sý‚:Ö=÷Ü£P(*++É–]]]n·»ººšl΢´´4--VÏçóÝu×]ÐCfÍš5B¡Ðl6'$$Ìž=Ûn·Ïœ9S«Õ ‚+VP§'Ÿ|ò½÷Þ£H¼yóæ>øàÃ?¬X±âw¿ûC‰‰ÉËË£øR:Γ'OB‹J ÃøSÎÀ z¬#GŽÀÁ†]„p:.—«®®ŽZK |õÕWo*¯×K¸h"òý÷ß×××§§§c&‰ªªª† f·Û¡ý.9È\.'»vAe‹8ˆBo úõªªªœœœƒ¶´´„ ÉÄ£/¸aÄjkkûî»ï¹BãØívèQg6›,“É<ϸqãâããÏž=‹ HGGǵk×222*++áR)===&&f˜îêêbo;;jÔ(†=¤¥¥ÁàXIIIýèLÁƒè†ØlJJ$ø_ ÃL&“Ñh …2™,!!º(•Jè ‹ ŠØØXèÈÈÈxþùç"Ò±páBJ¬@ÈEzllìk¯½íª'L˜ÀÕ¿ˆÇÏ Î?QC&“Ñ» [r¹œÙ™"--Íf³‰Åb­V›——GŽ3FÉOFffæœ9sn ?–º¥R9{ölºu+=Xþ±„ÉdJOO‡NgpÖ°Ùl†-_¾|ôèÑ0»}vvvzz:…¸bÅŠ ÈåòÞÞÞ‡~ú×k4š¡C‡Ž=`6›³³³Q•ËåÐÛpþüù¼¼" DîX¥¥¥V«µ´´T¯×ÃØNË—/÷ù|†555õôôÜsÏ=ùùùtoñ+V¬_¿¾££Ãív»\.LlÍš5ÐëÒh4Μ9311qÖ¬Yp%´|ùrÊr Ã0úKýë_ÿº}ûv¨n `µZgÏž]XXH^ìû|>§ÓY__OqB¤§§§µµ5RßWšIDAT))é±Ç³Z­?þ8ErEáÉår†à€<Â!rÇBQôÀv»¾x@àõz»ººšššz{{Ož<©Õj鎶ô‚œ:uª¾¾>--M¡PH$’ÊÊÊáÇCu¹°Ãáøþûï)wèî îèèèì쬯¯'k+|>_[[[kk+%~ŒéØÖÖ–––vâĉ/¾ø‚â]þÉ'Ÿ<øàƒ‹ÐÒÒÂg1Ž‘;Žã=ö‘aܸqpޏråÊ}÷Ýg2™OŸ>ͰèÑjµDXXÇSRRæÌAœN§ÃáHOO¿rå T7dddÄÆÆÂÂ&“‰P‰Û¶m«ªªbÈõ0iÒ$¨ u86›mèСeeeÅÅųfÍ:p๤Édúúë¯áÉë# ëׯ…й\g.@`0$‰T*MHH`XÃ0X |ï P( ƒX,‹Åƒnõz½Ñh„ºr‘HEø22È!™Ôj5ÝJ¯×Ã'R«Õ±±±"‘hÄuÀþP0@II ºxô3èsÜÏ(Š&\>ÝÐög(7¿thãÁÏ GÏßîø‰¥áñ³AÑðÑFrî(7†G?!§"tý}‡p ãxðPeß½ ~’gýBXËïðûýÁ`Pˆã¸F£¡ç §@"‘Š%â.—«©©©¢¢À†%‹e2¹Ëålll䯒Ë]Nn,€L&óù|õõõìYR©T,‘¸{{kkkÙ³„B¡B¡p¹\ ìYJ¥AQ¯ÇSSS3Э!‹e2™Óéäô¾D"‘\.w¹\D]·ÛÍÉuAA„ÇÒ»A„›Í~ºìâ V‚Ñ" Ä10–N¯‰Ä‰„K(ÎR~á>&ºÂ¯PYYIÎîŽãxèŽ%rssáDV]]MÉRP˜¦ºº:33³¬¬lèСÕÕÕD–©p,ˆÌÌÌØØØÓ§O“ËGd 6 .¢Cö’,­V;yòäžžžk×®Ñ]ñ’““¡;šÏç;uêå¯áXv»EÑÊÊʼ¼¼Ë—/Sªcx®††§Óò½2°222 Ã… èIVñ`ráØØØ†††+7.þˆÂ8Ž“íÅÍfó»ï¾›˜˜xäÈ‘ŒŒŒ³gϦ¦¦Êd²_ýêW{öì!sCO…£Fš1cF^^Þ’%K(Vçá¤4›ÍO<ñÄ Aƒ–,Y¢Óé-ZDNPÃÐ"wÞyçܹs‡ ²råJrBCf`ÆŒ³fÍ¢ç¥a`Éår…B¡R©èÉsX‹%;;ûÉ'Ÿ7nË^(..¾çž{sæÌ¡˜ 2?W~~þ<@¿ÎÀ*,,œ?~rròË/¿LIDÅÜò ,ÈÈÈXµjÅ8¤`±±±[·nMLL ƒ‹eíÚµßÿ½X,ôò¡õX0ÛýÖ­[Ùžƒaøðágüøñ0âˆ#`pÊ„„–{ ìܹóðáÃìË××××ÔÔüøã,eƒ8xðàÉ“'ƒÁàÖ­[9‰wÓPPPpüøñ-[¶tww“Ýì"âÒ¥K›7oîèè »*Ñáv»[ZZü~¿×ë½råŠÑhììììíí ™8WHž) ƒA‘HuóàÆþK¦°ZZZ:;; vìØ1uêÔ²²2ÊÎ?$ \÷¥9vìØ©S§ÚÛÛÙÔE ä·ÂÌ 9õ3³bccgÍšõ÷¿ÿÞX@ž²Áa˜Ósq•ÐëõJ$A ²€}](Š""ü~81º\®Å‹ÿá€K—3f´¶¶x8H‘<´ºáÛo¿;w®Íf é’®-.\¸`±X:4uêÔ‹/²dí߿ѢE<òH0yò$q‘5uêT…BñÐCMš4é•W^aÉ:wîÜÂ… W¯^Ò¿£Ÿkß¾}‹/NMM…hX²pOKK[»v­@ (++cÃêìì,--…îäôUxhéÉ“'«««À† BÊ’µ}ûv˜fgÅŠá²ôÒY/^|ùå—µZmsss¸S£ùÊ+¯¸I*J–¬Ý»wŸ8q¢9ü¹ µmÛ¶÷ß?Ü Ã±ÊÊÊþïÿþÏãñøýþp*Ç7üì³Ï˜]Ìé¬ŠŠŠW^yE£Ñ\»v-\Úu•——ÿë_ÿ‚I~Y²z{{Ù¤`«n€M_UUÕÓÓr¤³ˆ×L tÆÌ8ÎI—™YôZذü~]]'V¸FX}ƒÆ†îké÷6lmmu»Ý ̬(vÄ"°~ýzN£›*yÖ-ÂúòË/£¸KDPÒüÌßM8ð¬[Å<³G=bA.¤Ã³¿¸#žÅ‰Å2ê.x½^¿ßÏòÄÒ’gýXQXÂòŒ“Á¾c’{=ÏúÙ³ðë¦>ì¢(Š¢œ§ÂÕó¬Ÿ1‹Y©®"¶6ïø—.]‚‹¾èXR©Æe‡ÃõÚ<«ï,Eû‡Œ Çãñx"ŒXZ­†_g Ãà)Rt, Ã"²$‰Élilhðù|Ðc." EQK¢µ¥Ùáñxسjµ&&6¦êÊN,7‡%ë„;aŒÐää6[c%%§ (ê÷sp9rLžh¥f‹­N§Tª(aQ#B.—[mö(¼QhŒT*UZzºPÈÍ•’ŽX¡8#Àu]'DÇb@“U³‡×ë­­©AÄh2sL¡À‚Á íFûÅJ•* F.J†aIÉ)\ÛM£ÕÊår™LʉEGÿv)xÏS!׊qR¯âÊ,>ªª+&“Y$sbš9&' ‘åtºd2™ßçãÄêhoïèèÀƒANº\.—«‚R8"«öêÕÎŽh Åž¥P(ÅqOO ½/f WàPóÎ\‚Óíšår:ËÔ´PYt“6¬êªÐþÌÀq°>ëpŸH÷vuá ¿;‘Õ ·Zß"Jò¬èX.— …Õ¿À#.Þo‘^5þüpé*C²bbbJKKCúºD!!ëî»ï¾ï¾û¸² ù‹C²ŠŠŠ`fÚ(êšuêÔwÞy‡’ ˆ™ÅŒp,³Ù¼nݺ‚‚ŸÏ'‰(§Ñùùù‚|ñÅ!¹œ×X¹¹¹ÈËË{øá‡7nÜH)n^›7oÞG}¤T*333 ¥\DÖ”)S´ZíŽ;î¼óNú·ŽuíÚ5èŸ~ñâEúÓ…cMž+))q¹\Û¶mcϲX,.\8uêTH ép¬ÞÞ^§Ó‰ '‡}³Ù|áÂ…²²2"B ©©©¬¬ÌãñPR¬G|Óô‹YYYYb±øí·ßæÄŠXW8<ÿüóK—.}â‰'ÀêÕ«é^ wˆ°Æ¢@­V—””ìÙ³çêÕ«ì•b±8%%eÓ¦MN§óþûïW ÐÔƒ‡Ãn·§¥¥ ö,œÔÊìY---III©©©Dè6öu1ר_â8^VVvâĉٳg÷o]x˜þáv»ßxãåË—·¶¶²g6»B :::öíÛ7nÜ¸ÆÆÆpK%:<Ï™3g¦OŸ.>ÿüsi(WvìØ¢è„ ¾ûî»®0ñ&C>^]]]¸ÕC]8ŽÃÝS¸&£_¯¯¯‡ Íóçχô¾ât7æ¿644TWWoݺ5 4ˆý=›ššè1?XÇñ¯¾úê©§žbH«œÍf¶lÙ‚¢h¸Uj¸»íÙ³gïÞ½! 0°ššš^{í5Àq„|öÙgáþŽ… Hcc£@ !]éC²ˆ¥ë믿ξ.«Õš›› 3ƒ²gíÝ»þX¿~={ààÁƒáþÄòí‡ôÄdÝ‘N8[UÊhÜ/,†Ï ,ƒZ¡P¬Y³†òÊû½.¡PXVV¶ÿ~†Ï¬¿êbÉbIa[Îꆟ+ºººþýïßœº._¾|ùòå›S×O…þ<Ò!.<ë6bõïˆØ,Þ£«’gÝ^¬@šÍüTëžÕGVß1lØ0h¨“Ãã×Xáv.tà8N„‰Ž—Ï §7!ãY}gù|>6‘‰pâÄ øÃëõB+gD¥R18õh¸6:ÖM®ŽgEÍbsÛ#Vt®ûѱnru<«ï,ð~…<|Çâ1 $I||<'šËå‚¶Z­?±Auuuyy9ωD8Ž_¾|™= Rü~ÿOò\œzìÿ]c1G‰¥ƒ8Ÿ …ì' +Ä[%ǰžîî›ÃJNI¹ôãœX8ާ¤*¿xK&“~¯×ˉ¥Vk´­­l5ʾ‡À¾!ŒZ™Á^Õ‹a˜ÙbikkkjjbÏÒÇÄèõ1õuuœÔÊf‹E¡P464rª ‹»»º¸ª°£`¡( 㪳gù|>"^<{–J¥êu÷ÂÈïìYB¡@ÛÞÞAV1S(À#B30ÙW)Ç0±Dâ#9è±aù|>‰TªR)¹=Àÿ4…%ºtj½7&|cÃB'‰È¾.Ç 8–,·»×çõr­«§§GìtƒèÈâ3j4;-ÍÍ\=Áݽ½çÏžáN®®ŽÉ ‹b‰„!ìvHH¥R³ÙréGj"fAXê0 Àò\[#£y¹HGgè”Rìý®Ó”ã¸×ëáÄ ™”“´œXm×­ÈÙ³Ün÷åK?RF6u]¹|w`Ï…QÔEI‡Î’ÕÝý?›Ê¨'´¾šÍ Ü›¾ÕX°+PÒGÑ«Àõ…0'–÷úgö“´F`±,XøË_þÂ\ëíØK¢`͘1C­V¿ùæ›·¬„Ê¢ƒ¡{à qÞçÏŸ¯T*årùÓO?Í©bµZ 3‡i4Š—#ó©T*©T*4 §¬…2™Œ’k/"‹,!%ÞK(ŠD¢˜˜‰D¾.™L&“É´Z­\.gÉR©T"‘È`0 (ªT*)‡¹·H_ŒØ=BO…óæÍS©T¿ÿýïK–,™3gλï¾ËRš5kÖ?~üìÙ³¿ùÍo,X@Od<òˆÙl>sæÌ]wݵbÅ –«Ôôôô—^zÉï÷_¾|9¤%xH¬Zµê‡~8}úôÚµkçÍ›ÎMƒŽìììuëÖV®\Îu‚‚'Ÿ|277EQ™L¶lÙ2J–¬Ø¸q£Ó錯©©Q*•±±±«V­bö ¹É`Ó=Pzgœ;wîÌ™3á׌¢¨V«}ôÑGg̘A.ƒ“@¡9r$??Ĉ!Óã†d}ðÁv»}Ú´iï½÷^HϾ¬‡zèØ±c+W®ìéé‘J¥,YÇ:thnnîÅ‹é½* P^^¾dɱXœŸŸÏ’%jkkŸ}öY Ã`*åˆ,‘Hôé§ŸnÛ¶Íb±,_¾¼½½}èС,%d@_Xä+»¤„˜ ?þøã‰'Êår°ðG}t×®],Eùæ›o’““‹ŠŠ¾þúköÐÓÓÓÖÖ&‰8å>Å0¬«««££cçÎì•òGŽIMM6lØ7ß|þ.€×ëõù|.—K©TrbÁärìU ^¯×årƒAŸÏçv»E¢¾Æìë#È=„e÷±x‡ƒ¼Ûí^½zu0ôz½!püú†ˆr‡ÃQQQ‘ššzôèQÊŸˆÂtÖØ±c1 ûúë¯çÍ›÷ꫯ²d;vlÒ¤I*•jøðáóæÍ#ÿ•ÕÜÜ\YY™’’òꫯ²—‘‘1wî\“ÉtöìY–u‘Û Üø†Xôòä uéõú¹sç¾õÖ[” ‰Ì¬‘#GæääЗá! ³é8ƒºáµ×^ƒKo®žŠ€ªªªÎÎNNúÆÖÖÖ 6´´´ :T*•²<™Ú½{wsssBBÂ?ÿùOúÊ€-[¶èt:N{‹\½^Ÿ““Ã5—D}}=×)2b÷«n€¡ò+L›6íÞ{ïýõ¯ÍþÛ;v þøê«¯Ø³p?räW ”èlX0ÕïéÓ§9± uã5’ELа?}÷Ýw,ë‚Í›73' ¦³®^½.pPtÝïû‘»oß¾ýû÷ÓrÆgcSϊȺpáB¸°[7MBˆþwXe©_àñóF_­—î̳n_{@Vè©’¥Apñ£î—<ëöeá7暃z %ôˆå÷ûÉ;&‘HDϵBÞ¾²ôñ ¾žu{±(@„ð`&‹)ÄÿER©”“×ë…}EQNÇ’ër¹ gÝ^,À¥‡À¾vŽãÁ£/ô»§"€Û,ûÛBŠ¢†ÓÐÕÝÝMÌÙì¹}d) J_ ˆÕíMkù(XBÇ¥R)sh:P…ñI8qûȲÛí œäüùÁívãž›ÙòQ°¢<Ò‰BÛÆ‰%‘Hâââ×®5‘M¦¢SÃü,Á¦)¬6į^­è÷EgÝ¢k,Kb"‚ ‚M¦ŸZ–Û­--ô7·hp[Ç1 ^_¿å*þ‚½Õu¿£ü ‚…Äãñø~˜¦€ŸÉèÜÔÔAÁ`°²òr_êºEG¬+W*u:ÛíöpŒV£ï¸|9¬±{ `Ç‚¢ãƒÁ–––þ•‡KôËüÐÏ‹w«Õš=a„çž{În·s¢O™2eûöíý+'™LÂ4.åTŸ¤Ü °Ùl‡º™5ÆÆÆ†¼~Èe4×®]ëõz?ÿüó… Nœ8±´´433s÷îÝ6›mðàÁß|óMÈu‚Á Ñhììì$Ûq’rÒ¤IGåDé_ÄÄÄtvv †öööÞÞ^™LÖÛÛ s¡(*‘H”JeSS¼€?T*U ðx\ùý~½^/‹¯]»¦P(d2™ÇãéééÕÏç“J¥Ðü EQ—Ëe0|>ô<‹ÂOîV€Ãá9r$à|kÑ¢E›6mhµÚúúzz€a×à¶]]]ðÄŠÎ…ë ­V«×ë)^V ¬˜˜˜o¾ù¦¤¤„î|G°rrrBÆÿøE¡¬¬ êö8½5†–ï#kܸqeeeä<ßÕÿ긟jkkcHM‡^¯ÿÓŸþÄÒ¥“Ç­ƒ={ö„¼~«(H+** G(ŸnÑCh·;øŽÅc@Àw,‚[eÅã¶±['¶‡B£sTî1ƒ8qûÈêííå çgljÀW7³å#²‡Õ`0È)ž ˜”©Øž^¿®«9µ«Ô¨l§¦E÷¶-[¸fï…‹·dÙº]Of] 8®³¹[¹æª.b¾ïîæ}|q¯ÙÅjé&lðeÍœ§£ÌXcȤùI®û·ïÕÍý®f]ô3åÔ¡Ù.[ÙiÆhåjnmøµV·Uƒ®-ïvîåÅv#=žræÔ9Ž={Q}Õ»»®=<ôéÞËß/>=oîæÛûB¯>þSòî뻂/?ÿLúöþû§Â¯_€ ñç_¤(`‚4±g`ƒ­ ¨`„è`…›@(a†Qha‡–`8h¶×›†ðpèaŠ‘€8B•!Š*ÎÈ‹A¡U˜jYGXk‰˜ŸŒ4yˆ9ÉôV’¯ÅV›E($‘R b$NH¶µã’sýh“ F9e˜}T¹ßqObæ[𾑹ƒb¾YcŒ–y飚tªù¥›pîY¤†-–%šNþÖå‹‚Ég¢p°ib£í ªh¤k0êh¥pé)i¦zPji§j ªœvZé§¡žÚŨ¤6j*ª®b¡êª~búj­iÄ*«„­ÚÊë¸æªà®½«Ä¯À (þ,±Êaì±ú%»l´@4ë¬|ÐJ‹íÔV«ÞµÙ~kö܊ç-¸æÆ î¸Ú•{n»,¤«.vìºKï ðÆ;­õî;-¾þÚ¦/¿kûoÁ—Œp¿/ußVÿM¸=†+€xâ-Ó-CãŽ'þ'x ’O¾såƒp9æî,ž@çž#­ùæˆ>ºh¥«€º]ˆ …9èD·žúv=Ð^—fîÞtÞrÿ|ðÂOüðHà^»T«§€<>iJŽ[<7ýZÍK·<çÉ{.{×Þ=ÙÕþ¹¦Z‚•ÏÚ÷'fóö±³¯‘ûyÞ>>úJ>9XúÆ9ë»üއÿõ½~ü³Ÿ·Ô$Cɪþ#ÓÖÀgÁ¯üÜïW§ÕÜi|ŒI÷@½}0>¬à£^G=ô 8,D`®è/ò‰H™qQÁBÈ&®„Ãs×Á ü09.œÓY6d0.`ˆ{ãá ix"(r †øº_þbô§B]¥…E—7BQL £êjPÆÆ °I®ùÍš¢gÄŽqiäÛµgF¢ñ†Ôþ0Ø#ݩ닡Ë#¹îØ>C‹Šñäeêt>6ª0†ˆDA³æDE¾°’¸¤m.x@IŠòdœ4‰&³SÂâ©r•¬l¥+QÊ¢=1ƒâ’×ÈB8Êñžì],qvÊMîñh½ Ù/GPL e2˜ž:&’))º%cæs–iMG12›Itf 93lrsVÃ'ü‰GsNŒ€ê$gÝÚÙM^Âs2èìäèžã|þß1—ÏrF³šãùß67y½Ú%îa\Ú*‹˜Ï‚>³—£›çJãÆ€¦o¥U[cH*Ù{ŠÖÚ¨;[j73¾ÓÃò—WÕÒr®f–ð{3aN´Ì³¦²^›{Ú%AXؾnê~Mšj°±9Ù[µœH¨ßOâ-ÚŸ;u™}6kºv™µ–yóm ;Ňឡd mŽj›„Þ•/µé[Eg§ûPÖ†à¼C²î´¿Ûåè‰BêÎéÞYõáÀí’ïuĆipE.üá w f톭{½n\½üÝ8>þÝù{Ð2–u¦Í—å>BÖÓ7†+”äíñCv<æëílDåþ+æüÉõýt ¯¬Z÷™Ë*Í9Žì£SŽ€u®¡Ÿ;ÃÅRš«›¶,¦/íÞ Á\鋞9×Ïrž'wåŽmô¤O®çª“}Ïhwy°¶þu<‡­»Ýï~ /õÅ®®5°áKaZÄÈåŒô–ë[ˆóÛZp—W»}ú(ìf=ðmäÜË÷j/YïFoBN5¡L^Ìúíèèáýðn]Œ™”ÞUnÙüJèo½ÌðŠ¿TñXü‚a]¾§ó>-º×0ÅUïõÖWåõÊ75è]\™ âðŽ%É[ng«è¸íT½´G¯¹úB6ÿŒ‰¿.i´î<¸Ð v]íçÇHþ’¹±ïzZÁ,Ûu…Éæ_þæû7«Ötß%|e'u4•};•göG ˜vfqÈ—t¨ÌG"obgxf€wvX—@>g}S÷€v&g2—t8ÒpÚws•W_DA*vó|/xUÀ%a%7"½–ee6b?çFÑ…S¼Flwuò²}u]hi/y΃8ƒÑx‡b-Wt)è„‘[Bè~=õƒ vqM$…S¨8UÈnˆC{õyZRÅu&GØv¡„}w#ƒãñx‹ŸEL¤qføYnÈ„¿…sDG‚@÷wÛVså‡4¢Ço÷……pôf{€ÈIØY[!šþe†8‡Vc…S†ŠµpíGx»÷`wŠÆ·EZ4ˆ‚GU®†:h‰ãÕOš¸i×ç‰ “‡RÌ}]EvÓç‚6UC»ˆ‹Âè$n'F•X‹¤s‹b¸‚ËU=`Y~„€:õeßNawsøj¾gfgG`"˜ƒˆXZQu‚š¦uÐNƒ‰i6…„…$q–Pw€[È€ƒj›ø„´Duïˆ`ñ˜9É×|fŽ9ŒùgŽ"‚Žùˆ'âÈr)7‚ÏXˆÌRÀhƒL]9k;X„!h„·RP(ÙB­C‹n–‡kènðfzv„Êw‡A‰˜õrðèˆþöˆùµ‡zèÐþ„n3˜“é!“|˜.K‰‚è§p7¥V'y"Ù{z•k„§€k7†RæEó¨ˆüĈ‰pŒ#‡ŒÔ§•#(u˜iˆGiÝçÍt“­—”dI~Pù™?䨗xˆ÷k£D„ýÖ_Y—™w—xy0´5€ ©v‘æ“ù‰Ö¨‹i˜"8E`Ù‘ÿǘ`7R¸Œ½èB€Y™”Å‹†ˆ™›™˜q·˜ŸY5¸;7’ÜX"âV’äƒAW¹fu‘•FÉ™H9аi;,Éo­ùu¯ ›/NÙd±W*ÃyΉ1é4¢è“ƉÌÉuØé`@iaÙ˜zéÎ'ˆû¨›þÂ…zÿ–Gâ)Œ,¥sT pVI|ÇŸ$拤ÔëI…uikº¶„0hF)u–^Ø„·inÜ—–Çce…†ŠoÓ}NÕ…k'˜9’xZ‰žgsÆ—…·~$Ús èw¶d‘: DºŒÆSÞˆ™•—dÈt÷È;j”É7ÊV÷Ÿb©ž0ªnÊ… ÆT§Ç€&Z¤. Ž(:v‘ég{™¢‡i¥™1—ŠœHúíÙ¤?2vå©¢tB9› epXŒÕç{AgŠäbß àv¥Ÿ¢*¦·–¡ó•¥îx‘vXœÐ6”ô¥±ofj˜ãIÄ4œö †ïI©Ùèþ¡¿÷\Ú¥v:–È©’69/ºRÙ\ø_©(W^ùƒ¾¶‹::HŸdÙbY¨Ævø•U Ø (G‚àc²z¨Þéd Y¥É~T¦§},9|¯j¨à©t³ª‘oÆ£N7¤Éu*hÄ(¤zh“± €ÔjÅJ¥ƒHšoh¬¨ißÚ§1*®ýG®ñX«kJˆmŠ’!÷…nzxvkTqܬã:¬ÆIªÑ©hGyûœª”¡:O +¬ž9‰¥ýu°`Ú+¯ÃZk«{Ú©Á”±ëzÒzt™äR:²EAÆZw…a«8q­øA%k² ¯æGXT‡‹rX}ÇØ–>þF6{³ŸÁ±:›oy5Wph£©ùjJÛ¥Àz§E{²9;~;Ëi4Û€ƒêe[ª¯þC´TëV›I;‘Z‹¦õ§™é:²ÿã°b«yªlb±y ®4n TU¢²sª’œŠˆµkÃÆ§µ;µÙi·Nyvkvo:H“:ž …”/˜z–˧@)¢ŸŠ1çeMakCäi¹æ)y—;“"»Yœ™%ö=¯»•+;³L §0«Š²ÛŸ '‰Û},X Õ#•§a÷"¸™M%®»‚Û …ú‰%5ê„ÖÈ›7ˆq¥hxð¹ºJ a°ËcAKdªaÉè½ÉˆºŸØ„âÛ¶óþõG·Ú¾W7cÓ'}oéµì(luè³æ%¹Îj+Ú¯ë$ßê¿O+_¶¢çË¢¹·#¶æº¯¥ãhš©Õ¬½ªªÈ¥…–¶Ù+ˆò˳&È¿jÛµl+™½Å <¿w;¶ LµÖºÇj‚@ñ˜Cç­N›uA7¤r”y˜>Ê•ªiÃ$ì¸Ùš‹À™µº±+ ¾'xW²÷…Y‚=üµ€Úµaµ¿×{š…ÁÏ —CH¸Àg¸\¦‚[8˜®È´©»Â ·ì Á÷:e¶‰¹P,Ç^ì¯g™8·’œE…²öåy“+LŸj²¢Ëb¬RR8Ï´[`/åÈ”@ñÓþÀo‘ “½$;Í`o ›6Ì@ÉuŠ ŒÊ†B9Ÿ– ·8«È]Á[ž¼DSAɨ¨–•šK¹òI¡‰›ÊǹÊÅÁz®Ü[?­û{,»ø‰»þ¹– ¸eÅ7»@–†ÜÂJ†$ą̂V±Ìw-'—Ý÷¤àkŒ9Æ¿ͨ¼Ëéy8¢„À ‘Ú<Î<Ëkg,tŒWv\ˆv¤ç¼ˆ½€Í­,™¿»Ú½ï,dCKͬœ×^½Px}Óm,€ÞG›ãûªôÏØ ¶Ô Ê7·Ûy Z“·$2Çr÷É6=8•ŒÖgÊÇÎ娫)ħÜŒ\×ň 59ºO¸¹Óv$.ƒÚ–#Ù«­ÖhZÃ=&m°½Ò ʺÉ[Ìk½Ÿ2›»Á+‰]I§¹È»]廉çÖ –T„¬±o†ów¯ªÅÆþZv’¬:B;¼Íd ¸¤=ÐZeÝqY¨úJF ´m«lÞ ¦Ò ºYìÁ˜ÙrhW\ÚP[ÒeZ˜ÃßHêß!ÉﺑD€ÃTÜE ÄZº§'Œß¾-wynöŸÕÅÒöu±FêÒ/½t¼ÅúÈ« ¼šÒ¶€ ΄$ŒY‡º8-ŸX}Ë¡]‘4þã·â,¾Ï.[9m’;­Þ=Í¥À °¬†Ì´†Æ‰xâûM06¥äa˜’JKÄiìÌÑ=ßq]aÐ Ý9Štùläy‰äGRÔSM?âèŽ?º}*gÙäÌ”zçò-j¾æèì<{fÅL|êØ³%)Âý[Ï <ÄŽþ¯ŽN~þçkèÿ\~‚ív‰ŠNëÃ^ËZÛŒ§Ëú,±L铟NzîµN̵ŒžÜIé•~l‰é,|y\e{lÇ>må@ÞaöÀ^iàÃ>éE®ßºÍ¹&gÊûtê«Äÿ-Õ¼-Èó“‘Æò±ãæ¤Y­Üs<„wãNîÔÐçENיʽªØÖÑûÖ_nåa~æµ-¥àîqê[‹àÍFšÎ½ny™…­äð=à<–:ÑŽ´ÓN¬“-鎒®]º*ÚèÿKá0M¶8ɰŸ©ï)ì®!Ü´®>ê´W{ñŒ™ñ îéï¤ÈÐôço—#—0ÁnMàÁµ‰ø§ þÔùЏ.¯˜0O«Tý%Õ.µ>ïš@_­B$Ž\¼ŠŠë;Ó—Ça±p=!ÀÒ·§KÊ@®Nî×öníGÄí÷|Õ™‹O†NöUœª¶<Ê›]ê笰T¹îL^Š3†ÕÕ³ƒ‹€µÔÜÝ“‰FÌ­êܸ‡»ó.Ý\™•Õ=MJïöY,dï=Œú¸µ 9çì«êƒµÌH"Ý¡òý²ôíŒÛÃõßÍøk›¬’ßé7ŽèúðHŒí Ìð]à%À¬øm¿Ëìýâ:M€Œú1.öhGä9Àê?ëG8ãòúý=ú'_šRl«›þh«¸Ji¶ˆ}ßÅ¿ášÉöDmëoOó^Ç}Gâþ-›§,ÆÔmòËÞu©Nˆ[|þ¦x÷€{¿Š7ñaZëˆöÞ¾†õ/ÉO?‰ãAò1u¹ýa”3 pqÖ›wÿ¯`G‘<]ÙÖ}S œéÙT\ÐÏ€Ï0áX4+5å’©ùQŽÈg”Z•$›ÙìÔêãR½Vñ,Óž7¢°ÁÇF¬Õ;7î~ßõ¸œÞ&ÿKÌÐ ·£° Ó#%'µnòìèò2wö<=Sð>7Aí(SUW,/];¾VegË^]cisuS[mkD5QC7‹T…‰åv›g{}mq©« £›¦­¹»a°³a‡Q™“—E‚ϽÝÉÀÃþ ·ßëUãåmì÷ù{ó=¬ãÄŒ :vÖ•;Øá |5”xïÄ_1J|Ð\©OÍóã‘ÔG]ÕùާM}C‘)jThR§U–fkŠP¥˜5OeF5*kWV5·BBXB‡\SSŒ|‚Ö+B°/Ù¶• HkX'sñ¶´{ô”‚%GõKÁÚ¼-êJ;¼øÙÛ½ â2ž˜˜ãß«ËHrªc’\Ád}ÒVè™Ø µ ;iŠ\ò-ɯ'µ¶»6?Ùáö68¤0ßAB%oá¼VízÛíÚϯ8~:þ^æÑ2!3{ns;톑‡ÿ²›|§íåºË½^Èyu÷פOç>p„«TÙäüþ«|®ÂË+I Î”I®Â ï·ðôj=˜ø‹ðˆ-¢¯°³Hè(( áóo¾9 <ï$ß0.ÁÐp7ÑJÍÁøzâPFš<\´ïÞh±¬kúÈO üÌÇó€q+ ½ÈMI•˜<)Œó+pHÊR˼…pRËöÜ¡“Ô~êÂ>+¯!2/+q¸5Ë4‘Áâ’;ŽH4á2¸Ð²“!:™@±¿±À RtÈL·jT"Ë„üÜ/8 ¥4å¼F#äsž’ÌTÓM9íÔÓOA UÔQIþMR=#qã ”Ï~,æF0µÌŒX¡©4ZQ‹D=OMô"¥¯P6;J'´e´”½C%TöWí¸+%¸áTÔÊÉDç¸j=âµ-g} p¡úÆýëÀcœÜ/™åo]ÈÆ91AL¹ƒ4V7¹ýN[{ÛMUõ匤½,×bÁ\4Þ9ÿ…«ß÷Þ½iá|½Ã—Pdå–Åt5|˜†åóÖcE"îsdèJþÄŒ1«µ³âÀ£ØÜ`/>¹H_iÙæ;A†Hç½IùÙe¶ØÓVæÉÈTµb\“þ+¡/zÏžÓ´z1ªïZäç<µÖ gxÃÞ‡k¾Êžël ¤ÎQäûþzP.í›Ç–xn¢°ŽÑEzé…»* ÿ¼{ˆµCœáºí6œ©¬·sc‰©í‡Ÿ\ñ~׿òÅó–G$RÐ{™<úJ7Ï¡ó:S¯tõ#[§&ó¡QŒšŒÕ”Y齯ÓG¹JÕ´ §¸2«@¹1#êFœD0€¼`¤†øÁ!KI´Ú0­:6²•ß3…ÆføaÍz˜ÁŒ%1É ŒÖÝ.3§¦²&$Q;ãÚÈøÆ?©ñt‹Ì3ëtÇkªQ›ìÛè9Ƀq••¬Co·¤ h”þWû;*cÙ>G/™«åóMEšdª@^¦ø–c† ¸È#/ª0Yf&.šé’c¯‘Œ v^aZ2HH\¾¦–€ô’7x䙯áý³~ΪªÓUÃLXŠcyÙ ¦Ñrt¦‰#àB ÚÑ» 2aŒÝ/7Èœ@uc€ŸRjN…Òn¬w[ýAKã×8“M¥EUÍÏ-;©ÇŒö3~‰ÈaR’²·¾¾ä)r…>`Û¿ÃàPWÄÌžú”¨œ>틎;¿Ûјe•¥jÏý[Vs»1Þqj¡é¦d?9š»ÄµStÍË‘2·>·]‘sçMïU¼Ú½n’,åm!N,“oÜÚ³¿þmëeðåŽw|®pa{[rEøN™Ì­Ž¯s¥ÃÛ¶È+ñ˜ª£×Ô-udµêq7»û­l®bwCÎgüX¶Àƒ»`BKˆj÷Zä7¿óú÷ò0[|µ>l 5S×Ù[ÈùsºRj®È°ƒÜĬòyò"üÉAÓâìòXAyì&ÒŠCLWø×a~T-£QåTçÝ­[nVc®xÏE]ºÌùÛt™wý»¹´=%«À˜\˜–,"›+ÎxW#þ®0Ç{Þ«{Ø!Ê/òßn%tö ×ó Vü•A¯ß%ÈUµÛøäwub¾ÝÕ±;½?{«YÚ%Ý@x‹N8ÅyíMK¥Z¶þ|æë¾ðûC|Ö,ºÒ$·þⱯwÑS•üå7ÿù«ê®ÖÛØóà´ËtäK™°ê zø³Ðf®/Ñ\Mãõž¦½’í,;ªÙ‚°ÅÇýPh°lrÉ€Nåv)¡N 羪£® /¢*&Ü ±Íä­ÿä°Ìf浪¤îk%‹’ê÷‘Ä.1 yêvÐnÖÑ[ððBö/mžýeçI{øîÁŒ»èŠƒíÁñ ¤ÑÜܧŽtòðpq‘Ø@Û1ŒÔì¼ò)Î Î_f‹æ«ªoóN÷q÷qøè0Qñ!Õáþ(RöŒp!G°¡ 8€è‰>²Án BR®þ ëþò"ýA!Ûï ]äs¬% çñéÏ/p/éj’&¯Àk,R%ƒâL#Ÿ°ýR„¤•2o– Hâ0m “rV òš‰*ìçbPô|²ŒXòõÌÐöp **­¨œ¦I—&*ÕN¤,UD» ï†R2+£c+ïn#_’ ÁÙþHÙê2/Ñp/‹m­\¬çp/²ÕÔ1é’(w…X ÷tçíˆÑ/¹ŒDZò“ 7.R..û’÷âõ"Ó2'2™K2ƒi0³ z’3W2#[²+9ò­8`²è#‘M¡&½$ÐùHq YÞZQÏ<Êq®œ(ïí6} þ$#å¨ðDÒ!h‹Lió€1} …95èÐ&ã5aòX®CÌÐè$Ïs'sråt²à¸[ ýìó>ñ3?ÑŽ3»bò ›Ï òÍPçµÆ ”)£3‰n×íÔnA‘ÓZç ´ 3QÓ@ßqþ¦mâ€àm¶®*Ár ±Ö`ñÅ3EómEÙÍ1ò`SuÄñC©ôfr- ´5cÌ9‡É’Zô4¡oãxË“îQúië1CkdCCë8×dZ”4§°IùªDo%ÖæÏQ–åàÑïŒß4îß“­h´F Ë00½tÔJ9®÷²HC¤ ùH5 ®¨Nþpß¾´ßòLÅo´ÔtMgãÅÐkÔ«”D ½²¤oõG·ñùjqÇêÇ&5zѪ SqH«;³ò-µCd“+ÓtPIµTmôTçRTë¯Päï€ VÍdUY•P¥ Jh"ÅS:PFá«ä˜Wsµ®<“ÛPž2ìÝèŽ kÑ+”*õ²Œ(³Êç55’uÓNÑ/qð—X“­óâ6s[ÅU?ó¸v3Së0…´M¯e°ñQñ(]Õµ"»U1]r\'ñ Ÿl5)Q\ä4 ±r_¯§_íÙ!8VÖó2Ë5N#ö[´UaÝ‘amY•‘VåJRZþóB׫Z7ŒR3ÓvCâoLhU‘l5ÙUY}uÀ-±ŒU$•q0…UʈõkÖ[aUFÁ®³äëò$EÎ"´ £U¡ÒŽZ 8!ÊhŸ#1öf9³ VyzÉ½Ö %‘Gk;Vkár‘ÞõSã•ÏÉ?Í‘yz_‘cÑŒ!ÛQJÏ1`ÕÐi±`/¶Ïì¶Áó:3$;Gg­ mGõ“ðà°Tbc‘`Á#×þWqã3ƒŠnŠ I£ÌPUYÍÅÒTü‘ŽjySVzetV–õðˆ°uçГÈ./µÅ‹¢6°X÷^ Šq}rÛ‹W-‘Nq³-ãDþZXtyÊ2I_tJQŒnë-tÕÔxcy“wv•ö/¡,ÜæJIò ¬KÐ6…6pgYµDÁ·ïÀöoM3åôÔ»!øÆƒ{Å,c5–#R4%5)7fcÑOÍÔj¯7MIw×—û×}U8爬&VSqVâ.•ÎW!×z“Œ}KÕlïñ2š°O„E7s«ìäHË~_U û×T#2¿•zc·]ex†[µ†…2tM×RWÑ_ûÑùTÖoÆ$¥f-R—ƒƒ¢‰§Ss ×ÈX8„‰W%¹ö?_¤êU'Ûã&—Ó‰>M2pfÔÒô· S5{;T‹Q9$°‡¶ƒô,þØvš5Û°•Zå¸^r°vŸ6ôÐøûŠö"³8G‹Íãz6ZLYÌ𞵑ØPów’G›Ä¼ªØä®ØqŸUç(s\}Œ|CNU®”tíUž¢°Ã r%²)Òñv§t­ðkÁ÷Ž]t”ÏOÅV^Too5yh‰xkôÏk‹}®`å˜õÍ™£p~Yù}E¹k;Ó˜³––²?Áu+tîÌ“7÷”t%uwŸvm%xnû²jÿ¸H—iÎ`íŒÃ+m°“kÙsöWÃX0\öéîWym˜›2Çôó :¡z¡á/›}x6y>Ö¤F„ŸX‰1w‡yXW+hµÈ0þ¢Xxiî\ÝÀ—¤-Z5tP¢žye](íwÿ3xÑy¬¡¶¬ô¬Y'³\É{U—©©MdÙ(n]}'Ǹ‹[}ŠÇ“%Ù)·ÑÛÆ™×+÷§š÷Å¡bÃCÄ[Ü(¿2~“h_þ8,Ûˆ«yÌ3˜Ý›˜²zmAu³ïü›ÍwO1´½}ßý*‰Ü½±òVä½ÿn®“ަþÏ¿=š™»ž6¦³ÛÅy{|ût·þE Ô±ÍM}*EQI2-]Ùœ&Kµ Ÿ†hàJ¾ã{áûO;ͺç—f<m™’UY`éI˜[/»Ø †ùÚÛ)RÇ|8+õÇÃêáà»÷û韲šù“ÉI¼ÜwµK1€¡ðr­™¸-VÂ/¼Ô?žÐ×ø‘tÖZ¼íåç!”4¶ZQÏ›ä£Ož_z½7̱žÆ-ý$ï·{Ë^Äûžç Â?ññÓå÷~·;$Ì™¢¡Øk&_vᜇå<=s`]e¦ÃXë<Ÿpý¿ÃbôÍœÏmv(·ØËâøÝ«rêÏúÖ«~©õ¸­õþòg8ó!ñ[1°_ºÝ1¹®± ëþþ°¿^ oßÈYŸÊé<·†3#Ó±ùEåã‰úÁ½}kQŸh×¹¡»°e¾šÇv¹“÷¸ûyÅ©TÒ?šè“šb]{za;ý•ÿÈu?oØ|É© @ Ú)†ùв±ô,„J^íñЇE~Ù–ª+Ûº/PÛ7žë;k1PÖø¥DV‰£ ¶ŽÌ'4*R´6«ÝæœÕ/8,“Ÿ3.:Íó–ìà;—µëí³:ÛãFÊS`ŸÝ!âà•ccab¤ä$åâ#¦ŽÑg§ç'h¨è(i©é)*E%%^fãGɬI…GDQIÆnÑïíÅï&¡þ .nÒªre««óÞr´ôôWós&$µö6÷”õ5Wq`¹ˆ®ð±à¸9Ò/{º¸¬ oz·}õ%¸þã}¿?s¾}z²ý+hpÙ7=âÁ{wbÄyß©ø±‰~&ìØ$ Bg=’,™0d¸’*WN:‰Ë2)±Èы͆Jr.ñ¥“¥G—/j”›Ð¡kŽ2mê ¤R1oR5ÆafOš%NxÕ©¿¤QÑkV’ر>βmËêXXètªêðÇWZ!ê:ÉÕ«C¬½}*ëö\µd3Ž–V1Ã'S{R²dV”7[ì(èТG“.mút¨Äžùqnþ}вB̯3»~­z5–ºwóîíû7ðà‡/nü8òäÊ—+ǽpíÁ€jS·ä“V9n•"E0štÛKú8¤@Úx$’I¾âމÇd„"t;iÛuBNy%tF*¹%—]Â4—}…5©ZaiŒØø×^Ì-uUôל|”¥K2mf%gRbåþiz9(¡ Úy&‘‚~ö DÒÉE ~õæ•U•šÁdŸYɃS5šN£–…Š:ª‚oð‰èŠŠ. Šê€)&”û©!0Å©'OoÒô¤³ºyW-=î$X°Ó¨J*²ÉÆ…*³E„*ÐLJÇΰ ‹kU›j‹Ì°Ý"ñW¬²Ú­…ŽJ ª²éª; Írvì@kVkŽ÷aDk¦9ú%显úe“rúp›åN*©4ð®»0ÃD¹ë®ÂjôgN¹õÎK®¦:Ú»•Æ­ZÚ1›ü‚Œ°£×"ôlÃ)«¬æÃÌFœ†¾yÕ.É'Ú|³Ç{âÌñÎ53™³2/¯<4Ñí¶Ü˜Ð)uUbþ±dž³°ÀÊ[ð¦þ>ZùÑ9u¯Uó ¦­åÔt0ÓŽ¡L4Úi/u4¢Ioa4Z«D7zg«}÷Ýt³Í–ÛZƒà >8á€k7Þ‰ïU±é)_"´wEˆßH9æ)¾9ç]«Q"gl©Ì¤ÃaÞÃ}g¡wæç©Þ9ì5N¼í0Z•-+¯µÎUl/Rc¬{³¯?×:ñÖÅ~|Þ=V¼ñ­ßF:®èüó¹[îbñÄ <÷†Š;³`²òHðÌVÛõýøÓc¹ýxÙk}÷ñ#9UÈèÀÉ)ùâÿ¬«éc?Ë܇9öɯ€ß¡]ôW²ü¡oBK_ÿ@L°Nþ€­! 3ˆ­1m`úׂ¥@¾ìâk˜â™õªBà™ j²8¶ “'€AáO[;áÑ0¨Áª¥‚ƒè”ý4ÁEë'±–Î<å3Úø`¡á™tÈÃ)©……»"Eñ?1zöËǾ6+Çõ.†OÛV˜ˆEÂa\M‰‡‘"㨞 rެYGõtw1 EÎàƒÙ¼.FE/fÕ±£é Ò‘Jô™Z]u.âl_âúŠùæÑ3¬‰q`ÔA¤"Cé°F‘³£GýªF­|Qåy®ì+ø@2² %.CÊÿ˜ò& ä–ѸIaÊ2–#»°j‰”!æ²™þ—Ù%/™9Êæa„.üœïú(B¯áŽvi"žJ”Iq–0Ù¹¥3Ó© h¶§—¯Y ;„NuÒ“5ìÔN/³¨Ï}òÓŸ”f=:JJêžÛp§AÛP2T—-ÝCɔР-TbUhC3ÚÃÀ0ÎWĨ]&/*·ŠÂL¤ë#©FSú%õëi~þÙ¦ÿÊŠÀò5~U,ÜyÔnît‰…l$ÜÚØ>³r`lû”jD6ºÊdžuÏfS[ÒÓ%¨#KåKíÊZ™ª¶¶N-P\»—ªîèy¸©mƒ+Øßþˆ‹ce¡8Êj+âRT¸Îõs‹ûÈènF³Ïå\g© ЮS»“±îuÇ8ÂZÖyÕ%yWW¹Ý¢‡ã¢wÞðâ·.ñ'‡õO¿¨Ód~×‹Ú ÆiÜ¥oõ×Ók&Õ|À³$Ø&È®1¯„¤°·ÂˆGyñôW—EÂWZàº!ع .íÆdøJnÒ—¡cCeÉüÁT½ ücÇ2C×(Ä%Žþ߉[6b¾6"¬rí&\äqz Ç ›Œ‘,Døòø,óýqÑÌ#/ðÉü³ÐØ’èed"lÈJ¾Æ2<åéVÙÊ>Æ2òì[Y1óËü›ó™É—æ3>qÌe*3>¨Üæí¼αo™ÏN³ò–wå¼ä µ9NFãÊ„ü¡Ó¤ÃVéË ÐØùÔZ)©ÍÓ¡nhïš\Ã7zÚÐØ­ U]…xÎ5ÖeØñ]?Ì•âÙ‰^õj<=Z·åÊ®nØßú©ìe3{ÙOo' ûÑXxô_~Pa1̵3^ûÈÖKÔPMèco6»ƒv–q+KÙ$ûVÅD¶³‹ï›ßAÒR´ôwþ±[MîúžÛ]1¿¾ý8ŸÂ×´O+ÙaØîŠÓ¹Õ÷¾Õfî~Àïþã„:Á†¬X–@»ø)µ K¾A<âh›8ÅukXf|×÷²ÇM r4û™Ä&—*Êû-Y› —¬ g¤1MÆó•Ï›Yƒ©ŽŸÒ»…º–îÍqšósãú*™:˜µñKqEzí,*»ÙÆmPÏÉíÛm»Ý¡÷†¦‘šk”yÞß‚÷ÀwÄØ{/T´^8rÂWnðŒo+ܯ,éËÒÿ…§Ç~ù,Ižï­c ÿõÍû;ò'åAïp»žôË<½@þÍ9ðGïÎõ™®¤Sýà¦%}OaÇáé.\§óþÞ½‡¸Ó |7PÁð°ß’æG,YŠ¡PÑü p›¿ü^/0צv¯¯ýg?ŸžÑ/ðôÙâ‹78Úß.cÕŒ»(¿ßïM‡·9õHFû›ùîåWçùÅWúõÇúI‰IÉú•C¯™ ½µJfàÙÍ>ºýŸcÙSWÒ“„]Ž-ÜÁM€”áWå]Ø染ù’ΜÀÕéa`— wMßÒÙÛþÁt\Í¥ ^S¢ÙË­Rõ-žÄ  BŸfV湎©ÛSn_Í¡žEa‘ÕÙš%!.Ñ v¥_ŠþõܰPÓ Ó]ÃI˨ÙbÝË®Øä𤙡‘a 6Ûqa.a"´žcÈ x¡ñÙêá‘btåS³-"#6¢#rÙ¢(%׿0`ÿ¡&_Âhbá5!†E!J"x‘“Ä’ZùàøáÏyߪ­ ¬mŸÙ8Þ'¾—(&’Š ÑžQM…}ÐߥX½•φ9šðu`ÚÍö¢0‚P zâ,–^-Ú¢ò4 Œ5 õYa„ôÞðÜJOQ#‹áàE36ãë=cÝ¢™t,Õ!a-ÅÑÑJÀaáN1Y .£,’cs™ãTE㽨¢ÊÛÜ-Q‘˜ bþÙþAÞÚ8êce„"?2ˆÍ#Já„Ḛ́¤BÞYŸäEÊV$²™C>dDNQr‘/,šÒ¥# ÉÞî £.\KƤ ]£Íä ~êÆÉqeâ%Hc’±bAÁ¢›•$1`dÙÚ¯™Ú¬õ¡SΕ'^#R©‘â½£)¢â¥ÔNèÏZQ†ó)¥|$Û#ž%Zže T%õ=á ¡¹_Â~KiK¶¹\[’ "n!YrÖH®eº•¢è¼¥à/R`š)LÝ[UâÊDþeY¦‡T%1ÖÏ \ Òœ”fØkeP_— ª’f2OkÒcŠ\1µþ¥©°\;”¦dž&`Z&>â£H OBÉî”Ò&€ýR”à&«é¦ü¤æo!&O–¢2ΡÈ0o}“–]Eú"½x%_V×d2gx8'nù!RbL%yz‡yΖ"¦¥|Χ™f{ÆYXž¢~¢_Cò&pÝçñT¼ç” §€¨X½„H`ã´Qõðg>hV%è¡Ùå½U crãWžgRèZhçp&‰¶‘¢~(ˆöáxŠ(‰4PBZ>§Š®h…ºèæPdŒ.d‡ÂgÚ(‚â¨xùœ†MÒ¦‘•×afpJ#—õ_ü!e&ŸPZàPæ›)†¤ÅY%—þn¤®"Wþ+n%”–Ú9µè•.K–æá–§úéelv§ƒqØ0ÞÊÜ£·Í%ÿ âw¡iš*žÖ†Ï*iœ2ÂäY£›67.¤bâÛ!ùéŸVÑšúß–f&êå%jd<¶ãcærÑa·jóIê¤>S¥IºÝ`±'Àf£! BÚ ç?jÚ*f ꛓ«ž§æ"¦t$<¦ º{â*ª¦* °%6±dè¤dï©àìÙ‡Õ$ÐAš 5vâ“©*«€0k§M¨±Lå­ÑQ²‚뉫W4!}¾kZž©º®ÌxukyY"°Fé4nªcp"IŠ$»Šã¼rYþúÚ+ò©˜dÂV)åS2’¬–¬Ül}d¥°^ëƒ-¸ýêÆÎi2Ò)¡âžN 2ö"ÎÃR,ùYìÅ&P¦âb6r£¢újªMk¼£Œuc ÎXŽÁ ¹ºlÅÂlºÔ«;&¿ö ;º!Ò½#Ì5-œ|jE.Y´­ÞZÑ^¦ÑÆlÈ1æ‘ñZŒnìwBí:~ä,©£Ev§ÃÞžÖnmovíÑ,q"lÔ¢m˜1ìݲmÚ‚jÝZ•N,ܶ«Üª‹øØër%­ÎR˜LÒÞ\>©u²N^k1Ú¤ä:®'Yê‹R©˜ RP TþTºgTߥ.P™ëËnn”~þ ±eçÖÔè’n¼À+îæ.³±éæ¢,kV˜‡É_Ãa[ýiì¢Õ·Ú®E ®àùf…,Í¢æâN ‘ièRÕ®ò®óºmïNÄÔÞ¥Ôº"ý颞e.òf/êmoÅu/ÇÝY2…ß6˜­ž/úŠŠ®B¯ú®É›1y$<ŠnòÖïV©oþîÚþÕ)¶RZÈ`çr®a¯¯Žúr¯gâýnQÊÿ•à"Ä”&ik0Úíï~:Ñ7l™~˜òEëóÊ.£žðÉ íƒX{É@¢°wÚm­èŸCæ3¡ ÏpãÕ0—ôñì³~&„6hŒ=¨‡E¨šíÎÏM[Æj[Hþâ1æñ{oVV,Œ™„¤‘vüVí÷Ðφ¶[?t0S°ÛHêÉìͶd‰S“aŸºí1pvê6þs1Ïqƒ$ž½jüâ_°ŠÖ~: e•ü1‹nq˱!ÏHÓL±úíl^•~B²#Ë(ŠÞà q!gò§=.ÂÕ‚õ…ççñ;%¢bÊš! ®$ÃAÞNF²4NJzoÎ>%Ý!ßçšiW^P«ò*«æ ÿk›ö**É$AbŸù‰ ›ø©®X.³*op^åoÏn£(sñêi»±@Ò¤06‰[n2³ìLp)КÖ'fõ’­»Áå.æ»xsþ&ƒ³\휪ñóœ RnÿæéûÕ#Öö˜<Ï3³%«Zeœ®,Õj'ççá'wsE"=;k—ú*^ߨŽ-¬Ö-ÌtIkòIæF£Ï+{gäÆòº‘h«$,/ݶf'w*óLA³Õ)ÇÍÕeO*tM?’îNu#õQ‡H-ëžñ 3% Á¾æ«ó+P=s¿í%ëUƒÈD*Õ—¢nÛ’iQ%±Á5WÎÃ.uT§õ‚ ãh¤.Cˆ¬Ô”ó_W+ñÅldP‹/"¶k-d$µô ´!óõá¾0ÈÝ3‡êIÍÆÌÛ%fkãg–âõEëµDúc>›þ­Ú£;êí:º6Õg\^í(«*Àž5á¢v©¨6OÃöÚnÞ¾ôhñ­“rª_{ËD¯oë¶æòve^U¬ªqùâm÷yòt‹²5û¯pÇu³Zr?ue)¤I+¢Rn¶rØuÞŽå7-³³É¶÷a®¨B¶b ×šŠ÷3¥°n #36ïðøóH˜¶éÀð,ê·›%U7¸ƒï6·/\¯d7’‚ñ…?ÕÎE¦®h†×ð†_/J²Kf1…†x¸P0u'7ˆSö~ç5û:ªmöh3ªx³8¦µâq+#ø'êxó8í¶¬ o-‘ °‘¯'’+ôö.yýfÃqþ“£3¯”£/•» o^ùàfyöþ8µvù“;7&C·x ˆp:¤—Ã-˜+¯š«>¶¹’Ëø‚÷–œ[y™;÷›Ûnœ›ï¹n÷9éŠy¥¥¸’ú²§BP_'³ç::€û0I£9»„i¥Š³›¤{7÷½µâŽ)Äþ7[©¥G7Y©¦K3ðQïb¶íéûÊ©\Æz:+,EŸz|49ýFs¦ÚK^.böÎòmg«ÏZ¯Lë:|ðºH4Ø;Š!v34h~œÂ¡`C›o<3{šÓ¸„Ggô¾R[›ˆGO¡·¯H+g·{;x8ûE¹ø2r5·t#§ûÞÆtŸºû·Ÿ¶þóÞô¢«ö$2pþôâ²rø‚ _r´©óû{d<½Ä¿»Äß·=8Ç_‘x^|ÄCqÁHçVû«4ú6³—X'Œ Ÿ5¡.Eôì\÷Ãâ:óieÄú·§ƒµç¶™sÈw‡Ç„ø$· v,ƒ±=É6}bÓ;Ç6½`ëíËËíÐO ÍN/!ñìor6×Ò.³4ª0Œ6‚W½Ë^}×Ù°¦#v鉖-p[m”Å|Ü×öÝßuË_2Û­Û+º"«m7ÍÓ6rj7±îmwÛ÷Fýüný¿ë¨#×=ÍY÷¿øßÊ*ü2-æGøÄC>ËJ¾M7Íáþ‰yÇz+ð{Çò¥¥÷|‹yÖŸw¦Árëx¢WþmûäWÌ”ÞÉ©­<“¾ëšî€—pèró¹žnÜÖ8†*„²´¨“zŸ€czÙ¹†o|Çw¿÷Âs‡~Joë« ;0ž³­¿³:_¤ÈÞrô/;ñKx”—¸´×¤(­ïëœõì:sf“3H1¼Tó‡QNZí¥aÞýCq$KóDSue[÷…cyìÆs}ç{ÿ3L@:ËÄâ¨l2Ÿ‡ädzeØÓE›mv3áoY¹%g¹BvÛJ,ÆåszÝ~ÇçU6wßÿ ÄÐÐ3yj8ºâBtJã{0óûš´”„þ„ÀL³ãä˵(44=EMU]e }…•ý+eåÀ\ »üÔÕäÝÞô”–$®ì]®µu~†Ž–6u]¶¾ÆÎnnÕe⤬B†JDO¬"§BïN?OòŽÔ4?;v§¿'ÎÝžî÷ÿ@5} dÃOA„ÊZ Âð! …-^Ę‘†Ä‰=6¬ˆjÉ’%MžD™RåJ–-]¾„SæG7!5ÞÄ™3'Çb;$ò¤ôšMjBE¨N¦M>êKGT©T“^õ Ç–U¬]½ZúTìX²t¡‰É¹wXÒAq¤ÎáWº<ÂæáZWïÞ©ZËþ8†¢ªÞþpQ¹¯p§¼|¿ÞÅÓØñdÊJü ÆœY3ˆ5hýJ/˜äÊH!ß!]Z5ÝÓ›]¿ÆÉôlaskÛ^í¸uÔ¹}›¾ [øðÝhVõ[ïßw›m=÷sâÕ­¯êŒ†ÑZ¸²CWR,/u9Q!…B/^½ ò×Ý¿·Ã|ýüˆÁS™Ç W©|úëÛÃ0ÀÁú#p(ûDŠb$^<#-ù+°¹ÿ¤°Â Œ0Ã! !ìÚjc+? GLà@ OD‘ Idq“ ÄoX¤Ñ²oÄQÅwÂE`4NÆNxlÑÄ#¥A Å´¸ÑÀ‰Ò‰ÐnXãO‚Ò«ô‚K÷(5Õ¾2eÏ(áYGÊDg<4.}5VøÃ1w<5…&?©V&YQ–­Ð¹'»@}TžŸz9šCFzŽ¢õ!méñêoª)ÑUÄPõó!<Ÿ«–¸ëœÞê¤ÇžT&³ÏF;mµIâñèôÕ­}CL«ÖjÁ™¶]vÆÙ9ã»[7æ3ø†lQÜ&;ñ7;Vlèóð6!mMWÚNÁ|¸Ö«…þ{FÌsÑ\5Ä']XÆu\i‹ùÝ%Æ­A#óÖÛ·ÚZ-ÜuXvÊF/½÷šO§‘wÔmgÁ1E­ørW¯}öåŸG®2á}§~xà‹<Ø ];—ÕR‰üŠ—\|éS¯>ý®'qú[þe­îÕþy«p|JÞž»é_ë—ñ»·íˆ}êCà Ǿ‡¸o mˆSø³T90Š› â@?ù¬G=óˆüJeÁ ’Íf¸B¡ÿ4h®p„,a 9öµ©ñÌ…iá #EB†  jÝÜG92 †ë+¢žxØC†uˆZË׃’¨#¾hŠsZ"ïe¾M|ꊰÈá©”E-‚‹‹Éóœ_F5¶­Šedb¡ä²Íµ‘=ot’G>.nSñ{Ôíôh4<Á~aB‡Énw(rÎ6ü“O¹Ÿú©eh4UÐ,I¢¥«}L`=8ÈYä0`bÝž)®‘þêZ˜×Ò8%SÉr–ÃY'7J^Æ+!‘$e)?éÇSªL•á»xòçÜÑí°D¡2óÖ s Q~S£7Nýêšžìe8ÌÒ˜ò¨¤2Õ·cP tÙTá&-¶¿i¥Ìj–KÎçúº]ŠÓŸÖ#çù²7]%²~€Œàìb‡»é7ÆXhüèEŒMó~ÜÛNöOŽ>0 »fŸ¼©?qTZÃè9¦®›eS{Ü#_;_7¹9²”^åh?*ÁêHØ|ž>»&>‰’¯¥eô’:†˜®t©7Å©?uºSötÆdÔ["J²!RpˆT&= è©J~“þšÝ I×å¡óL’v`% X#÷†¨J•ªº±*ªºR´ÔL:%c]“t×§•mm‡Elb»XÆ6±tl/ ÅÍ ZÅÐd<ýɾåRfõlØFØþ6²7‚R*;ó+VÆ2´Y{dó^KÃXrm¶=Ê«éH[ÚÜžÖŒK†jç7šíQv«jUÌw&ªÒk.²²R8ª4™Ë«Â9ªÎðën…é[P¦6AEé!ëYÔzʳÊ{§RzOôîó¤°ëÖhµ«Ór×B“õªP+™R£²m›W«#Qõõ Ùµ2©îÈ›Fm•ùrɾ|T®I¡çßÖ6u¸Ê…§K—ÊO»ØÂþeõCØØàèÔ÷Á°ò„:Ô_6Ÿmeñ‡]Œa[ X4îçVHLßÞž8S4®f¯ÔÊÚg^sÏ\ ³4 Ú´j5ÉF†qg›<®'Ÿ5¾ Æe4™ºãöØÇ„Êî(u9¾ˆ”yMËš—K`7NÚË Qó—í4ÇÖÙÎwÆsž_’cnœÕ™ÍÝß› bb9»'Ì‚'–£HD‡!šŠ…–á¡}] )Á·œ4!!CIg:qA?„iO‹vÓìt©ê·Y:™´T5-X}j¥ºÔa,0•[æ«Xo—Ö´µ§GÜëºú×° v¦‡Mlƒ;}¶u1³2kÎH{/Æþvöf ÝMkO[¾ÝÞ+µ³M!Ê"™¢à^–ÑîqSã^·]Ä Ðx_ÛíÌ[]ïtc—ßöž7¾]%c[þ²þ6øQî-ð¿Ø8á øû.”…3œ,®n'ªˆ{4Ðþ‹ g‹|Þ6K’™µì–¥Æc‹cpãkì8›kéf¦zø¶ *¸‚× k2K§â-/ÔËMpÁý™ºáy·•¹Y`£«øÆËݦ•y +”ûæç@oJ²'mÎIÐ-z$Ÿ§;Ý‹Ôʵ7«ï…\†KÜq¬¿FëŽæz/=\²Nê¹Ë_Íaç\õf”çxm{ÒÞŽè¸3÷ÕšýŒÙ ®óÄÃÔ|>gþ{àÕ$ôÃÅ’;ÞLϸøÚ¶¸ïð–Pä%™Á × eÇ®) Š@¢Þ¿Û‘+t£Ûz%çŸü+½·GßDÊŸÙòÉ}î“rõÝgDø;^¶6@üåo‹øÅ¿HàœÞ½sU=O"ùÍÏlýAÿ¾÷]†þ‰\²ç9ËbÖ¬.¿çÚ£bRï=Oá¿ý}Š>ü?Zøg +=QG²®J±Ô›.´º‰.¨k„dë2 ²¿û —ïê:"ê·‚/ò"°I¢$þг+¯QÁ§ôÁüŒÀî£Àoqâ‘=×é¿èy=¸Ê‡ó<Œû¯h›ÁyªÁÿÓ9Jë³þ¬¿D–ÕZžTƒõ#8{ò›Á†ê¿qé¼&Lºôã3ì B 4ÂcAÂ<²ì¯)tä¼§;»æÙ<˜ú»"º-|´.d•â;¿1™rp2t17#û?£=ÙCÿ›½<Äæz«(­R‹œ‰ëk>,„?‘-T9ÚʤýJ9`²DÝ“CL 34c¿W23öEIQ´ˆqºUR» Ó¾™SÃ*lE€±WD?“«ªNü1úѳ]äÅ^ôE—€¸ìAÅÌ“)銺¯š:mòž\+[ºòS=4t¼e2¨½ñ¦ªK3\ôD8¼ÅS¼À/¼%³*F´›«+»(Ä¥ñ"C°3þ*±›~êFm¼“ã#1S"¨cêCäù)¾ÃCL?ˆâGtü*³¨»k(wáDyLzl0s"¿e¼@}|)§²°öcÅs8‰4Šü:ÜRÈy䯄ì³òÒ/´BϳÈ3äÀvÔ<”|<üÈ… I˜D8þ²“a=B,—´JF¼¡–I̾\㟑™(Ù‹¦?ÜIÛS1¶áç‹I-œIKQÁ¿’¾ê{›™ |J`Èùj¡_˰˱ľ¬ØJ,አ´e›Ê¨#­<ËdQ¿íÛº¶tË¡‹ËZƒêÈÏñ:SË»J¾»ô½¼,Èy¢ÃÀÉaä/Ó³K”?ÃÔK•,@$þÊÀ¤ªÁ„LŠ€KÉŒ“;f„Ç7ÓÌÍܬÎôLoÍ4ü8ÌÜ©Ò4Íš@ÍÔ¬´°‚²Ëb:ózÄÝ‚ÍJ,9øÛ8§¤Í¨‰Í`T7[ü+Q,8UÎá|œâ$„ß“‚{lÀq¢´§g\·ætÎò€Nލŀ¨´{GQY¥®¤îìÎ"@OÞ”NyZÍ+ŸxSÏõ´¢ï|@aÌÁ§ª;HdÎÙ´Ï¢ÀÏ+«ItÌÈþlCÂÐÕƒö$-®C¿C.à2Gt¢ÏeÐÈP­´ =Í …%¬ÞôP³QCCC묔¤…sŒ­¡à>M;ÎÉ ©b‚ âµþULɦôÆÓD÷ÓGßLPð¬Q5E­ÆD¯ »B2®:¤NkšB+­.Ý\Ñ$Àˆ<À.5?7ìP&¥I'ÍQ|)‰2J \¯•<¥xhÄ~<ÏÕa¼»~Œ!„J4MS5E665›„.&d©lC¼ýD™¤;1Ä;jDH¥xL@í7ATGHÌ>=N±5<äZV®MF¾<¿×Ò„Ú6ÿtÅ÷CR’åÐ!ôàüᛀRÛ#F*aþÖ7o=®æ*¾Í+]–íßfS¾S)èÝ>àsm–ÉG%Uª±Ó’\¯ fGÅ$ǃ%=-ÏÏ[ÚÓ•Ü'&Ö(vÇsêÔ7MÕƒ¤TFQ.j2¡|¿DcÜib6cXEãûÆÖÉ@ïÚ£¤R­ÕSÔ6žO²— ¥mf'\ÄUþ@Dº»¦kMå(7bf'µæ/ÂX*N#*00eŒ:e˜­ÞyigõæèÖV•/–]gE!¡¬‡ä•ß$Õàè‰¦èŠ¶è‹ÆèŒÖèæèŽöh‹Ö€é‘&é’6i’ƇäÈEkh@æHJnLnéglV“Ó:ŒIcZ­äZZ~†hšN‘-ˆ,¬¢3¬¡ãÅÔM>\Ô¸*Ê@®RŸê¡F‚¡6ÿêº €Ðj¬Öæ€öêÂ-ן¾jrÓê¬æêŽÎ±î(³fë³FëVkɺ…¹Žªw®G±ŽkC»Ú½Æ)»nH¼Îë'žÁ^ë·¦áÀî.¦ëœ2l¸þFì8zÞÈfìÆþàÇŽ4ÉæëÚ6‰õЙ¶lããŒÐÖìP@4õìÏÆ›¶,X–Ï =mÔŽ ÕFh‡vË׆m0kÁêaÌcRÛ¾mŒÈí³~Iõíß¶ˆà®kžîmÀ6n×@î¾0fëâ,îæˆç.lÊ\ë¾lªÖî‚åîP’íï~ÝðînÝ&ïe6ïóvëô6Óõoïvï÷†oõÁîÉžoÑ­ïøFïüÖïý¶ïñžïêð­p1c‹R×ßÜD æ™Ûmð!ðÇŽÏ¥ÒfÅ#fœÃWiŽ¿•‘ §ðûí„®2 vXgroÀ%seŒñÔcãge;·Æ³…áµ{óÒ¹ïÑ ¬,"*ôø°ð}˜îAkt„AôD7‹EÿîH—ôò tí¶ôKgÏL§ìMçôñôÆõPŒQ7ìR7uBõ·VõUï“VGëW‡õ«*ñmÕe;ü·bONóBeJ\W_ð^†ð_‡×Z·—A·«œî°–¢™rá ÿMÏ𧡇EjoáÃVv3ºþryufhG$–¾fbñcuñT®Fn“ñ ƇE÷ˆqúþöVavqjÓÌûc™b§ÃÁ|ÆBqx|¶Õ/þqœN/(LÜ{÷Â['hE¬bsîérSè&25÷Ö\_hô©ãJxlmx‡ŸÃ+Wi}¢ç! ŒDÉo¼—®ÈŠ),Þ7Ç&y0 ÷9¥ùËád˜¯ùP=ä4Wò1äò‘¿yœ/s-5q©œÔ_°ej?§Ã±}z>ww7û…Pí¯fû¶ØdOûAÉ÷pòk¯Dû¸?…¹—,·çû¾çæ»Ç{+?­“&üÂ7üÃGüÄþ§èVüÆGüÀGzÈÉo;½§ü˜êË·8˧|¡Ö|†ã|ÈÏêÑÿ| ýÀ'ýÓ/}ûRý´oë­^}gk}°ýÙ}¬¾}ÅÎmÛÏýœê}Ø~Þÿ}ºÿýà6þá‡4áWväf~ä—3å¯õæWlç0è_õçÆ~ê?1ëwxî×þVðûðïûñýþØ]AZOï/ÿûØBô7¡õϺöüº†ö•û­ÿf]üÏÿØØ« &ù˜ºî,ÊI«]a€Í»ÿ`(Ždižhª®lë²Á+Ïtmßx®ï|ï× pØ(J $Q¡¬4—Ð("ó«Z¯Ø,LËíz¿à°xÜyJÏBþ¥úð0"ÕÆ³-g ÖÓù;Žî©d‚ƒW1„‡ˆ‰Š‹Œ$f~I|x”oFwn™˜wMsš—‘¡I¥¦‹†§ª«¬­®Ž¢± ”š´›œq•¹Sy“v²À ¤¯ÄÅ;©ÆÉÊËÌ>Á~¶ÒŸf¶¿ Ïxб€ÍÞß!ÈàãäåÞÏÛgӛ뷵³¼×ñèéêÃæøÆâùüýþ„ôê-¡s‹ŽµN“js‡«Ž,Üo¹áÒýAO~¢õxÜÑË,r¾»÷ ÍË/¿¾¹5rùÂÔIN8aÓ {ì¸cÐ'ºÑŸïQŸ}ÍÐá„Ö‘_wp8O;Ù]³ 'rÈ„ë´'Ùƒ&#aŠ,ÓÎ!²ñ¡† ¹·`Œ8.þ”]‰ 4ˆxU!&äDiä‘HÖâ’e¼“£“Ú,P”¿ðHcO^é£Mp™¸å—¡ È¤sV–IM‚XT%”îÈf`ÞäbqÖ9”˜c÷bùg‰Œbƒ•4Âø§z‚zˆx"gç£45šçn^Ž”€•BÊ%Z™jê)|sN*ÝI–jj’J:Ú§¬B£ª¨­uÚꧯ®$ë6¡3SšCº(˜µÂ*Ú­³¦êRÄ£ãˆp6ûÇCG¬°š%[lÓNWÛAÈ`Aÿêá,z4´í±ÔòfíµÀ¢{ÔºÜì'"¡•0D¨“=¦–mºŽÁË®û·í›1þÁ˜%B÷âr£¿Ü¸Ë/l ÿë]À¹ |°š…|&´ZêëðæE,±rc$r4gy1Žvx2$%ƒÌé¶û1+ ^½³+¢~ÜÓËÕl0¦Ô,ˆð¡Õèdzg1ËlÕ.ëÞÔQ8å 7T?+L—qíiÓNÇ%~™›krÜÒâmÙæ‚H ½å î{È(d“-.;>; ð¯#ƒö¨b˜G›ôæëlÛ%þi4Á7²Œñ…‚hÍÔ²ãx-}çäuà¿=8Vx“ùÑ{£þíÞ†¯¥Ü £û%Ï åδëzç«‚îûw£“Éöð-÷ا$×µn&ÆkÚ«^6þ¹»Þfš §,ºx¿gïÁÓUú€hV³1ø¬Ïc}ôÍ‹·ËéŸï úË_ÿœöôoÚ½º…£7#ãCïÏ1ëÃWWg0¸*w¯£\uµÚ°ܳթ&HÁ Zð‚x‰àýÎò9©ã_ÕРkêG­mR[Âv§©]Éï'%$á Oè·n†øè  ¿‚C²D‡; ׂø»úP%@$b¤D¨-%‚ΈGl¢‹ÅùLñ†LŒbo®HÅ, LkùS ‡‚‘Œª¢MÆÅY©ñ^ŠcÖ´v(Êtq¥Ib¥âÅŠñ§nŒ{›æÂÅ?Ùhsß»\ñ4§(þ= äxü‡K&¹ÇÈ@²B–«cˆ6W9ÉÙ \ ’^)¢¯õ1’5É(YIû=M€Ý*ZâÐÈ<¦l”¢lÕ%Q™Ì©-!Ík¥mNy‘ø¹ïJS‚Ÿû8ÂÉR¶˜¼´U‚ާHaÞ šæYæ-¥­Zj3ZËÓ%6£)E[έšÖ Ê.—±'Fo;‰<Ý ÞI»X>➇«'+/5Nr~q›­KçSÖ©Œ“ù‹hÖ$¨?áh¾X–íˆBõ¡0 Zô¢â\hcÈø3¢íçü@j,*fŸ$ˆHa˜RF­Ô¤Ø3UK_2ѦÌ[/…)Ko:±œÞ‡§íÒé\P Ô^þù´D-*LŽ*Tr$U©Úaª¡úžš6õO¥*¨†¨U’Iõªçè*m¬ŠUšEŽ|ÝÌÎÒ ³1.îG`}¥X=ÆUWÁ ¢R{«*õº>¬-M;løj\Ù9WºÎ¬WzSÑ&ËZèçu$àCEªL ðnËìÕ¾e ½qÖ„ƒÍ uþÇWøÌªduô˜U.-Írµ’0§Ž^k¡€60|µ­œ;›µÙn5Ó ‚ -E߇¾äݵ°©mÅ÷$ÛȪ®m«3_Ž(KÛBÍoÕƒeãÆ˜]Q&W¸ŒÈœÛ†FÀ‡êNhnêwWÁQâõVy¤ýÕ¢ÌdNïwµ²½e7³[¦à‚þ·¬Å»—•xõÛŽQu½ªXnyu×¾|ÍdgÆdY„OǾoæÕ¶ –†ÿ«Üæ*SeX §X| ØêOJ Y œ¦„^zÁN³úDšéØFJ@Ølh­nC Èa:óÃÎä…ˆ»JbSd& a·øco‚ØM+›k‘Kqä4¤—ˆ.Üð’KLã—O¾Ÿô2rµ\ІŽÌ[®ÈÍŒ+4—͆M³OÎSåVNYÍp޳œS™gºÙ¦}fÚŸ÷|ˆ:³ùÎá ´  ý3E¯Ѩpô‰ÍhAÚÌVÄ¥ûœéJBÒ^éôVöšVPÌҞ楌ê[j•¦\ª¥ërÕþ¡•-Û…k†VÏú h»2©rZ.ŠºÐÓÜ:ymÔ_#¢Ô£G’ìköžW–Ëföªíl-äZ³¾±C¦Q»¾2RŸÔ®ë€Õ·ê+»Û¡g'mÙYFf[Mæ»q[‡:¯´Ú%·áýés¦îÚ­÷“G4äJîÛÒ4ÎØb.…‡œ “pûêo(wÜá72Åm}q62O€òæïôàÑð=Zœ ¾:ÒÈ›]òb6ÒÆ¶Ë§“Å ­Öæ<¡!§òÌ…XsŠ´›ÈAÇóЗXt£/]¢IOôÓiõ¦Ûeꬺ¦±Î­[ã\çg]Ã.ö¯”ì:óú¨ÑÎG³Ÿíþ7S;²áÞf·ï”î²æ [ÑHçb#Ýî½Ä{ÜÇNàøfêè]“;àU€ø+žßv÷u¬¾w.LØJ}ùâaQ5Ìßlͤáã!` ã«pÞµV5¿y¨ÞÜë,òŽ›=Ö‡áò“ׯÇß”gÛ·ž,…´[#ßQá?6²ÁŸ­þt]>ßùØÒeðÇY®{Lþ÷#ÐñÉ‹LÖr²ô¸|[%ö|/ÜvùÕ§~”á\~ì ÝŧÆxúr‡8ý#k?8š+Rö“‰‚nœv}î7>}woÅ7}ùG€ªz‚WˆIg… ì†)‡8+'døG~x8³þ‚È7—YòQ›tb»unîf¸G?úçm$( 5Øz‡Z&;8b=X?XT9ˆC¸zAX€GÈSEXp7&Iè~KxSMhS˜yQˆ}WØRU¨O8x'HX_h„7†—…¿·…)Õ…?líÑw¥oh¨ƒfx†C„¯ç ‡Ç…s¸yjHRlè ÁHâ6^ï`‹t@—RøuÖaF!‡¡÷LwØdBo —[»Vcž”naXf¥µY±wFG°‡¢W‰~rpÈq¼wëQhußöÃÇ|q³ ß—,¨p•793xЇuVÇ#¬¸pêç€rø‰ X_ÛׂÜþ4nÈ}6.ÈhJ¨øo³4Æè¯è‰ÊhÏÕ] øa’S_ª—zH+}è„—OÍ'4Áf˜ó‹€¸Ž€w€']Ϩr‰¨l¦Õr¬‹ÇP‡Ñ`v‡Ï8ŽãHï%qÌ”K×":ð‡Thn÷‹óäés~‚„^w#ÏCi‘‚H*õof’½V†*¹’(é"-Isz“Kõ’0I“#A’=@‘3%‘5Ç“Þ(W8)“6É @™N>‰GYE©ZCU,ù”ÛÓ”®&•SyX0áya2‚Ki‡TimVy•3 ¢˜3²WFÓCIyq]ig:ɳx‹Rn‡ct™|þæey)XBkIp¾‰a4l£mµ÷–99¸¥<ßW#’0›ˆ|ãç|†Ytyˆ˜¤è¦ˆe“oGŽ )O‚ˆ ÷’ù•Öv6u‰kw9qìÁyé‹{D}‰Å¬ù…x‘õ3›Ý¦}ˆØ˜c9éˆo­¸C¾9); V]Ê7yœ4¸™%ÒG]vz»·2DW'€Éš-èa.¦s=§s‹Ø›Þé—µy&¹9a» Ý•aéJ¦‰gèÙÙÇ(j¹ž´YŸÀsŸ"žI4*cÖ€+›È  `' =C *¡%HŸ*'*t:ªœ*þpªt!šœ2ЖA9¢k¢Š•,ê¡*i/j¢/€¢Hù¡¿f£mD£. £É£‰à£î†£5ZqZ‰+\YDDšjB:E<Ú•Y–{w™³‡2¥ ¤+Z¢K ¥ƒ˜IsIH‚‹ Ššòœz)€O´¥•öˆa´,V“¤²©¦+œçioášYœœÈ€…¥sG–܈(½8™iCO édúHŽÌhŽñIšn$§„—© ¦üƒ×¦f ›hj¨’šËÙŒxºs‰™®X‘ê§Ú`òžHœÐiœÜ©=‡:§íÙ}‹ ~ø–ÔôÚ§ªJzá(}Ça¸$Ÿ´ú©þa !)^õòcHsyÉ >—ž ¬×ŒÖ;/rL§êŸê‰¡Z«“z«V¬Þº‘Y˜â*¡äºgé ì¦X–© <ç`èÙ||©¬'Ф.ǯ[æ¯Jô®Ëú¢0Š­ °šÙ®J°i¦°qʰõé°k°[뤻dë©–ÛcûŸk•!Ëa#»¯%‹VgùjUãw‹°0g±Ëy€Zœ©‡iil5‹²4Ë5d¦Ò°šƒX7þVª"©±2;³ÄöW P-kZ³UÕ³®÷ªòV%èho7†zü¹°K+‚¡H|,ôz\‡…ŠS׸•Hûy޼éD'û_þ”j|ŠHn¾UnLJc¶h‰è'fidµá`®4ŽðùV[[™á¶·‡µÆ™¸†«8ÎÙµ6¹%Œãœo‹³–›².ɸЗ¨ÕË(÷Šä·ý9« 2·ƒË¬¶; */õD­ù]J º¡›ŸTBºó—o½úµÑ©ºU»²Oɺªùåo"ö»¨Ú¹”è¢Û¢¸Ûñ}…k™ýJ©¸ EC»d«¯A½?;½Ô)g¼À½E¾åKSç+¸¨¾ë˾68£ð›¾ò‹¾ƒå¹‹;“ù{¿û;¾þ«¾úWü;Ä;” Vœ¬ œ¹PK˜\jÇ®ô›,W7+H“EþµhI{r ÀœÁ²Ñ¥ºh©gƒ©Õ‘¯i4I ¶ì„áVù9¥ rk,eCۉˇªó÷Á|u¯#ȇk›½¤ÊÃé:šÀK²Bl…&œkÙà\-¬µŠÄ˜+¹1f¬Æú­ÂÛ¿Q\’Z§àz½ëz£9|›¯Ú­¨Ë@,Æc —1F¬¸É¹ö"ÌÕ‹|ZkÅÝÈ}Ô?JËáÏ$gÕWýÉ®Òr¯ßk»zlÌ&Ö ¥Ö#Ù%Õ×~ý×€í/}Ëé¬p؈؊½ØŒÝØŽýØÙ’=Ù”]Ù–}٘وÍÖ ÚÌœýٖآ=Ú¤ƒ Ú5§Ùª½Ú¬ÝÚ®ýÚ°Ù¨=Û´]Û¶}Û¸ÛöQ;jas-2.5/images/edu_jas_arith_classes.gif0000644000175000017500000000554707773340004020634 0ustar giovannigiovanniGIF89ai•ñïïïÿÿÿ„„„!ù,i•þ„©Ëí£œ´Ú‹³Þ¼û†âH–扦êʶî ÇòL×öçúÎ÷þ ‡Ä¢ñˆL*—Ìæ'J§ÔªõŠÍjÜ®÷ ä²ùŒN«×ì6;0Ëçôºý5vë÷üþ~(8HX¸ç—¨¸hèøy„¸Xiù'©¹ÉÙéBy*ÚèYjzŠJê¶ê%ªFš:K[ÛÙú«‡ + k ,\Ç«ë{ìûJ¦|,µÌœ\½÷;l}=‰Öš×=Ö-½ü,þGN¾½™ÍÞõÇŒŽž¬o&üL?½ïkÝ» ¦ø¶j²záô5\hŽß¶„ß¼ˆ1#†þxÿè3*ßG‰CÒ³¨1¥Ê•¦aÈ£=J΢õ‹øPJ–<{,Ö+h›j>‹T¨RuG›:–t©Ô€O«Z-uªR¢W»z ”UkP®_ËšõV,,²gÛºÕ¦6î²oëÚ’V®%¶wûú¥‘W/#º nXp"¾‡;‘ +os†bü8³æ Q󊼼‹ðæÑ¤#$åFÓ™¬Ã©f%º´ìÙ-Y¥ƒˆ;fD˜¯ìa¢ <8‚Ó·UÏlH³ïЛÓ&^.7Hä+ÃÛ¹ö¿£ûÖ=2üÈÎÙ·›¯ÙŸ>|9‚dþ÷ùù†+¾þ®öþïS+¿_€Oõçlè¦(c "a6«9@ ƒk°Õ[„Z“Z‡X¸ÕNy¸a‰PM”€*®Èb‹V$™/&ÎX .Q0@Ž:îÈc>þdBi€BËЈ$*@=ˆV1$& %'KÊád”Vj “b\xe—ps˜ZzI&1ÊVH-=Yf›\Ü€š„Д"›nÞÙ†Äóœxþ Ã%ó%š¦ h¢ŸZ'–Œ* )ˆ"e~FŠ©“&¸i¦ž2ÐiU¡~ é¨W™Jjª_¡ª*”—:Æj«¾ºY¬²ÞZ”­¸§+i´î*\¯Ï ¬_Ä‹þì5ÇÒ÷k²o-+`³Îz­‰ÕNËεQj‹m0Ü^ùm·J>º«´âžÛ޹èŽKîºîÒ¢î»q†+o½ƒÄk/ôæËïû¾‹o¿Dü›oÀzð 'ìÁ ÒîÃxD,1 WŒñglÁÆ«àñÇ ^,rÉ&ϲÄ$Ÿ 5êò/aï<±ôÒUFÕÚ3Õ=¬ßKþúÕéý‘7úÎó™õáÉt;ÿäOλ{X¦»`„Nì×Ï€æ? ¸Ž1l´Àò!°0é!ЙäÓ0é 7ÖƒMšA@Ôo‚F™ßR¨¼ rP<Óñ¨3Rð|amVÈAhè} e9¯<„ˆð¦ƒCãIˆv1aˆˆ˜Ä"'Š8\"þŸÕº,®è‡qªì¦H½÷Àð/Dá2¤4îjl#ms3žñ1ƒSØPŒ9Îñ0Ž…¢Ç=Rpt7¢ )’ Ù–EÖìE !‰ž"i2PZìä‰ÉUmr’'hcØhÊTê(”Ïi‰+ßÄJŸ g–y"d,ŸEËM2¡·lŽ~¹Ë8 ³—ÛJ‘1— IbºJ~ÌL‰ž©L/‘rÐf4­4Íb5«Ü*WåÕ¯Þ%ªˆ+QÃjV\þ4­tD+[ÏBVÄõ­™+Èèš»¯m]+_¹ãÖ¿ž*°‚mª_ ÛDÂ"¶)z¥äb{ØÇâ4²’5KcOpÙÊzK±š…g;»’Ì–@´ EÙgK«Ò¶ µ“õkázÚ×Dµ~”íóbkÛŸà6·sÛ-o³åÛßbƒ¶®UˆþÛ@ãÖµÊu rŸÐ\ç7ºP™.ukdÝëš–²ÚÍÈsÖÝe7¼¦ønÌKÞñʽée®{Û›ZõÂKòo$Ø«)ûÆ—»ú.û;Üú¸øµÔ€g+à ¢ÀQ0AÌëö¿¶„;VáÞR8ÃÛ}/‡9”à‡X®"ð†KŒ•£ø›^1vOìâ­©8ÆÈœ1iãO"Ç:¾{¬±9®@‘‡Œ!#ÙGž@“—¬0%C™šRž²@alå0U9ËÅ2—Í´å/×4Ìb6ª—Ë|f"£ù¾d^sYÓìf'<Ù4qvÄœWWç=µ9ÏŽ…3Ÿqìþç?ï8Ђö1¡ äC#ZÍŠ^ôîÜ'GcÏ’†n£+MåKcúÊ-Þ´œ)íéüj:Ô!5©ÇlêS›¹ÓªF¤)ÔêO§:Öof5­ê[ÓyÖºÞ+¯{Ù\»¯&ö°mëc÷ Ø R¶¡“ílx;Úóì³c}í{RûÑÓÞv¶å¹m&w›Ú߯g¸¥ýëss ÜÕV7§Ñâîe;Úìg¼šî{G8ßú6ò¼]ïsö»ÔÐx­ámð.<áwå7Ã#íð‡;â§Å+nkc|Õ߸T/îq³8äQ¹ÇðM£œä×8ËK¾ð—ƒ×ä_¹Ì}óþ›oÀæ:7Ï{n±+ûç@¯-Í1Nô¢'÷èOºÒgžó§«BèÇvºÔwNõa[ýêfºÄ·Îõ}G=ì;Ù'nö³[<íjÏøÈÛ.öŽÃ=î.Ÿ;Ýßnw'gØ`Ï;Úåîw ô=ðÚ®;áwÍv»þðí–5ãñìõ‡/þñ“g|åyÂg>ð›÷{çóþyÅï½×¡Ÿ{éá~ú¶§^í«?{ëÉþú°Çžë³¿zí¥~û§çžÜžì=Þ®ôJêå’ˆ/ºðåB|Èß|H~ÙÏ|öyùÑ7Ðô¡?"Ôm¥&Ò¶îÇw›ð_",Ý‘ïÏŸ7R5 yí¼è‘ïþèp5‡ìbõñJ Ó_Šë‡!ø<ç@å÷!÷×|ù×cýGEá³CƱÁ“?1$?X€¡†€à³?î“ÉQ˜"Ø}˜VR„Dþ÷9$ñç "Èž¶_¤Aþ£B;„äDÑ‚6‚G%ˆd”ηdÝ1~ôó!ß±'„8‘ õ·hN’ƒ»Ð„ã—‚ 8<îç¹Bññ~Ñ >ˆdÇ—GQèT4FÃc#XE a€:æ…jaƒ èEtDU$ƒò€Jˆhk:C(‚qȇ"Ø€EÈ…C†‡‹…~¨D(‡ïSÈ‚èçˆY†ùãA 8=qHFX‡ÉˆC¦CJ艦4€§C€›H{oð„ÚCж§‚Ö÷x‚·Š‡ÓŠ®øŠ¾‹ 2‹ÌS‹‡òˆ»‰¹ŸŒÁH$¾HŒÅhŒ,S;jas-2.5/GBManifest.MF0000644000175000017500000000014411505133310014535 0ustar giovannigiovanniManifest-Version: 1.0 Class-Path: lib/log4j.jar lib/junit.jar Main-Class: edu.jas.application.RunGB jas-2.5/sample.jythonrc0000644000175000017500000000045511334631304015410 0ustar giovannigiovanni#!/bin/bash # # this is a sample rc file for jython # modifiy it and place it as .jythonrc in your home directory # export CLASSPATH="$HOME/java/lib/junit.jar:$HOME/java/lib/log4j.jar:$HOME/java/lib/tnj.jar:." export BASE_OPTIONS="-Xms300M -Xmx600M -XX:+AggressiveHeap -XX:+UseParallelGC -verbose:gc" jas-2.5/algo-ca-book.html0000644000175000017500000003756712137677610015520 0ustar giovannigiovanni JAS - Algorithms for Computer Algebra book

Algorithms for Computer Algebra book and JAS methods

Summary of algorithms from the Algorithms for Computer Algebra book and corresponding JAS classes and methods.

Algorithms for Computer Algebra book

The JAS base package edu.jas name is omitted in the following table. JAS also contains improved versions of the algorithms which may be located through the links. A short explanation of code organization with interfaces and several implementing classes can be found in the API guide.

Algorithms for Computer Algebra JAS interfaces, classes and methods remarks
2.1 Euclidean Algorithm, Euclid structure.RingElem.gcd all classes which implement this interface
2.2 Extended Euclidean Algorithm, EEA structure.RingElem.egcd all classes which implement this interface
2.3 Primitive Euclidean Algorithm, PrimitiveEuclidean ufd.GreatestCommonDivisorPrimitive
 
4.1 Multiprecision Integer Multiplication, BigIntegerMultiply BigInteger.multiply adapter for native Java implementation in java.math.BigInteger.multiply
4.2 Karatsuba's Multiplication Algorithm, Karatsuba not visible
4.3 Polynomial Trial Division Algorithm, TrialDivision not implemented see GenPolynomial.divide and PolyUtil.basePseudoDivide
4.4 Fast Fourier Transform, FFT not implemented
4.5 Fast Fourier Polynomial Multiplication, FFT_Multiply not implemented
4.6 Newtons's Method for Power Series Inversion, FastNewtonInversion not implemented see UnivPowerSeries.inverse() and MultiVarPowerSeries.inverse()
4.7 Newtons's Method for Solving P(y) = 0, NewtonSolve not implemented see UnivPowerSeriesRing.solveODE()
 
5.1 Garner's Chinese Remainder Algorithm, IntegerCRA ModIntegerRing.chineseRemainder() only for two moduli
5.2 Newtons Interpolation Algorithm, NewtonInterp not implemented see PolyUtil.chineseRemainder() and PolyUtil.interpolate()
 
6.1 Univariate Hensel Lifting Algorithm, UnivariateHensel HenselUtil.liftHensel()
6.2 Multivariate Polynomial Diophantine Equantions, MultivariateDiophant HenselMultUtil.liftDiophant()
6.3 Univariate Polynomial Diophantine Equantions, UnivariateDiophant HenselUtil.liftDiophant()
6.4 Multivariate Hensel Lifting Algorithm, MultivariateHensel HenselMultUtil.liftHensel()
 
7.1 Modular GCD Algorithm, MGCD GreatestCommonDivisorModular.baseGcd()
7.2 Multivariate GCD Reduction Algorithm, PGCD GreatestCommonDivisorModEval.gcd()
GreatestCommonDivisorSubres.gcd() many more algorithms, for example using polynomial remainder sequences (PRS), in particular a sub-resultant PRS
7.3 Extended Zassenhaus GCD Algorithm, EZ-GCD GreatestCommonDivisorHensel. recursiveUnivariateGcd() not complete in all cases
7.4 GCD Heuristic Algorithm, GCDHEU not implemented
 
8.1 Square-Free Factorization, SquareFree SquarefreeFieldChar0.squarefreeFactors()
8.2 Yun's Square-Free Factorization, SquareFree2 not implemented
8.3 Finite Field Square-Free Factorization, SquareFreeFF SquarefreeFiniteFieldCharP .squarefreeFactors()
SquarefreeInfiniteFieldCharP .squarefreeFactors() Algorithm for infinite fields of characteristic p, not in the book.
8.4 Berlekamp's Factorization Algorithm, Berlekamp not implemented
8.5 Form Q Matrix, FormMatrixQ not implemented
8.6 Null Space Basis Algorithm, NullSpaceBasis not implemented
8.7 Big Prime Berlekamp Factoring Algorithm, BigPrimeBerlekamp not implemented
8.8 Distinct Degree Factorization I, PartialFactorDD FactorModular.baseDistinctDegreeFactors()
8.9 Distinct Degree Factorization II, SplitDD FactorModular.baseEqualDegreeFactors()
FactorInteger.factorsSquarefree() Algorithm of P. Wang, not presented in the book.
8.10 Factorization over Algebraic Number Fields, AlgebraicFactorization FactorAlgebraic.baseFactorsSquarefree()
 
9.1 Fraction-Free Gaussian Elimination, FractionFreeElim not implemented but see GroebnerBasePseudoSeq.GB()
9.2 Nonlinear Elimination Algorithm, NonlinearElim not implemented Based on iterated resultant computations. See also the characteristic set method CharacteristicSetSimple.characteristicSet()
9.3 Solution of Nonlinear System of Equations, NonlinearSolve not implemented Based on resultant computations and algebraic root substitution. See also the ideal complex and real root computation and decomposition methods PolyUtilApp.complexAlgebraicRoots()
 
10.1 Full Reduction Algorithm, Reduce Reduction.normalform() all classes which implement this interface
10.2 Buchbergers's Algorithm for Gröbner Bases, Gbasis not implemented
10.3 Construction of a Reduced Ideal Basis, ReduceSet GroebnerBase.minimalGB() all classes which implement this interface
10.4 Improved Construction of a Reduced Gröbner Basis, Gbasis GroebnerBaseSeq.GB() can be parametrized also with different strategies, e.g. Gebauer & Möller
10.5 Solution of System P in Variable x, Solve1 Ideal.constructUnivariate() univariate polynomials of minimal degree in the ideal
10.6 Complete Solution of System P, GröbnerSolve Ideal.zeroDimDecomposition(), univariate polynomials in the ideal are irreducible
10.7 Solution of P using Lexicographic Gröbner Basis, LexSolve Ideal.zeroDimRootDecomposition() additionally to 10.6, the ideal basis consists of maximally bi-variate polynomials
 
11.1 Hermite's Method for Rational Functions, HermiteReduction ElementaryIntegration.integrateHermite()
11.2 Horowitz's Reduction for Rational Functions, HorowitzReduction ElementaryIntegration.integrate()
11.3 Rothstein/Trager Method, LogarithmicPartIntegral ElementaryIntegration.integrateLogPart()
11.4 Lazard/Rioboo/Trager Improvement, LogarithmicPartIntegral not implemented


Heinz Kredel

Last modified: Tue Apr 30 10:16:18 CEST 2013

jas-2.5/README0000644000175000017500000000540512066051026013225 0ustar giovannigiovanni JAS: Java Algebra System ======================== Version 2.5, January 2013 by Heinz Kredel, University of Mannheim, kredel at rz.uni-mannheim.de Copyright (c) 2005-2013 by Heinz Kredel. Programms released under GPL or LGPL, see COPYING.jas or COPYING.lgpl.jas. Web home-page: http://krum.rz.uni-mannheim.de/jas/ Requirements ------------ A Java JDK 1.6 or JDK 1.7. Documentation see index.html. Required libraries are log4j.jar (from Apache Log4j, or mylog.jar, droidlog.jar) and junit.jar (from Junit for tests in trc) Usage ----- javac -cp {other_jar_files}:jas--bin.jar:. java -cp {other_jar_files}:jas--bin.jar:. or jython examples/ or jruby examples/ Versions and jar files ---------------------- JAS is distributed in 3 jar files: jas--bin.jar: the Java class files jas--src.zip: the java source code jas--doc.zip: the Java doc, epydoc, jrdoc and more info files optional jar files: jas-meditor.jar: the interface to meditor jas-jython.jar: an interface for Java scripting jas-mpj.jar: MPI Java depending code mylog.jar: a substitute for log4j to use Java logging droidlog.jar: a substitute for log4j to use Android logging jlinalg_adapter.jar: an adaptor to parts of JLinAlg commons-math_adapter.jar: an adaptor to parts of Apache commons.math There is a GIT repository for the scource code, which can be cloned with git clone http://krum.rz.uni-mannheim.de/jas.git jas The version is specified by a two digit major.minor number and a subversion revision number. For example in jas-2.2.2088-bin.jar "2.2" is the JAS version number and "2088" is the subversion revision number The jas-*-bin.jar and jas-*-doc.jar can be generated from jas-*-src.jar. The fastest way to get a complete JAS install, is > jar -xf jas--src.zip > cd > jar -xf jas--bin.jar > jar -xf jas--doc.zip If you have a working ant, the last two steps can be replaced by > ant compile > ant doc provided you have setup build.xml and the required libraries. Directory structure ------------------- . main directory, with html documentation +doc javadocs, jython docs, jruby docs +edu Java class files +examples examples for jython, jruby and jas +images images for html docs +jython JSR 233 scripting interface +meditor JSR 233 scripting interface for meditor +mpj MPI Java versions of distributed Groebner bases +src source code +test junit test output and log4j output +trc junit test sources ../lib directory for required libraries, not included $Id: README 4321 2012-12-24 13:01:11Z kredel $ jas-2.5/COPYING.lgpl.jas0000644000175000017500000006420211512323746015117 0ustar giovannigiovanni This is the Java Computer Algebra System (JAS) Copyright (C) 2000-2011, Heinz Kredel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or any later version. GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! jas-2.5/Makefile0000644000175000017500000004017412063333630014010 0ustar giovannigiovanni# # $Id: Makefile 4319 2012-12-16 11:59:20Z kredel $ # # Makefile with default rules for the Java-Algebra-System # by Heinz kredel # # created 2.6.2000 hk # modified 1.1.2003 hk # todo # set this to your jdk binaries path #JDK=/usr/lib/jvm/java/bin #JDK=/usr/java/jdk1.6.0_02/bin #JDK=/usr/lib/java/bin JDK=/usr/java/latest/bin #JDK=/usr/lib/jvm/java-1.5.0-sun-1.5.0/bin #JASPATH=$(HOME)/jas SVNREPO=/home/SUBVERSION LIBPATH=$(HOME)/java/lib JUNITPATH=$(LIBPATH)/junit.jar LOG4JPATH=$(LIBPATH)/log4j.jar #LOG4JPATH=$(LIBPATH)/mylog.jar JOMPPATH=$(LIBPATH)/jomp1.0b.jar TNJPATH=$(LIBPATH)/tnj.jar LINTPATH=$(LIBPATH)/lint4j.jar PYPATH=$(LIBPATH)/jython.jar # --- syncing ---------- DRY=--dry-run DELETE= RSYNC=rsync -e ssh -avuz $(DRY) $(DELETE) --exclude=*~ --include=svn_change.log --include=jdepend-report.txt --exclude=*.log* --exclude=*.out* --exclude=*.txt* --exclude=.svn ####--exclude=./test ####--exclude=*.ps --exclude=*.pdf --exclude=spin* ####--exclude=*/.jxta/ PART=jas.j16 VERSION=jas-2.4 #BRANCH=2.3 SVNVERSION=`grep committed-rev .svn/entries |head -1|awk -F = '{ print $2 }'|sed 's/"//g'` all: home: $(RSYNC) krum:java/$(PART)/ . heinz: $(RSYNC) ./ heinz@heinz2:$(PART) krum: $(RSYNC) -e 'ssh -p 2222' ./ krum:java/$(PART) pub: $(RSYNC) --exclude=*ufd* --exclude=DTD --exclude=lisa* --exclude=*xml ./ krum:htdocs/$(PART) compute: $(RSYNC) ./ compute:java/$(VERSION) # --- end syncing ---------- # no need to change below this line # command line arguments cl= #.EXPORT_ALL_VARIABLES : #DEFS=$(JASPATH)/arith:$(JASPATH)/poly:$(JASPATH)/ps:$(JASPATH)/vector:$(JASPATH)/gb:$(JASPATH)/ufd:$(JASPATH)/gbmod:$(JASPATH)/util:$(JASPATH)/application:$(JASPATH)/root DOCCLASSES=$(JUNITPATH):$(LOG4JPATH):$(JOMPPATH) #:$(TNJPATH) #DOCOPTS=-package #DOCOPTS=-package -version -author DOCOPTS=-public -protected -package -author -version #MYCLASSPATH = .:$(DEFS):$(JUNITPATH):$(JOMPPATH) #MYCLASSPATH = $(LOG4JPATH):.:$(DEFS):$(JUNITPATH):$(JOMPPATH):$(PYPATH) MYCLASSPATH = $(LOG4JPATH):.:$(JUNITPATH):$(JOMPPATH):$(PYPATH) #:$(TNJPATH) #JAVA_MEM=-Xms1100M -Xmx1900M JAVA_MEM=-Xms350M -Xmx800M #SOPTS="-J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc -J-Xms1100M -J-Xmx1900M" SOPTS="-J-cp ../lib/log4j.jar:../lib/junit.jar:. -J-verbose:gc -J-Xms350M -J-Xmx800M" JAVAC=$(JDK)/javac -classpath $(MYCLASSPATH) -d . -Xlint:unchecked #-Xlint:unchecked #-Djava.util.logging.config.file=logging.properties #JAVA=$(JDK)/java -classpath $(MYCLASSPATH) -verbose:gc JAVA=$(JDK)/java -classpath $(MYCLASSPATH) -server $(JAVA_MEM) -XX:+AggressiveHeap -XX:+UseParallelGC -XX:ParallelGCThreads=2 -verbose:gc #-Xrunhprof:cpu=samples,heap=sites,force=n #-Xbatch #JAVA=$(JDK)/java -classpath $(MYCLASSPATH) -verbose:gc -Xrunhprof:cpu=times,format=a #JAVA=$(JDK)/java -classpath $(MYCLASSPATH) -verbose:gc -verbose:class -verbose:jni DOC=$(JDK)/javadoc -classpath $(DOCCLASSES) usage: echo; echo "usage: make cl='cmd'"; echo FIX = fixm2j GETC = getc.pl #JOPT = -prof:gb.prof -tm #-mx100000000 .SUFFIXES : .SUFFIXES : .class .java .PRECIOUS : %.java %.class edu/jas/arith/%.class edu/jas/poly/%.class edu/jas/ps/%.class edu/jas/gb/%.class edu/jas/vector/%.class edu/jas/ufd/%.class edu/jas/gbmod/%.class edu/jas/structure/%.class edu/jas/util/%.class edu/jas/application/%.class edu/jas/kern/%.class edu/jas/root/%.class edu/jas/%.class .PHONY : clean doc all: $(JAVAC) src/edu/jas/*/*.java src/edu/mas/*/*.java trc/edu/jas/*/*.java trc/edu/mas/*/*.java %.class: %.java $(JAVAC) $< edu/jas/%.class: src/edu/jas/%.java $(JAVAC) $< edu/jas/arith/%Test.class: trc/edu/jas/arith/%Test.java $(JAVAC) $< edu/jas/arith/%.class: src/edu/jas/arith/%.java $(JAVAC) $< edu/jas/poly/%Test.class: trc/edu/jas/poly/%Test.java $(JAVAC) $< edu/jas/poly/%.class: src/edu/jas/poly/%.java $(JAVAC) $< edu/jas/ps/%Test.class: trc/edu/jas/ps/%Test.java $(JAVAC) $< edu/jas/ps/%.class: src/edu/jas/ps/%.java $(JAVAC) $< edu/jas/gb/%Test.class: trc/edu/jas/gb/%Test.java $(JAVAC) $< edu/jas/gb/%.class: src/edu/jas/gb/%.java $(JAVAC) $< edu/jas/ufd/%Test.class: trc/edu/jas/ufd/%Test.java $(JAVAC) $< edu/jas/ufd/%.class: src/edu/jas/ufd/%.java $(JAVAC) $< edu/jas/vector/%Test.class: trc/edu/jas/vector/%Test.java $(JAVAC) $< edu/jas/vector/%.class: src/edu/jas/vector/%.java $(JAVAC) $< edu/jas/gbmod/%Test.class: trc/edu/jas/gbmod/%Test.java $(JAVAC) $< edu/jas/gbmod/%.class: src/edu/jas/gbmod/%.java $(JAVAC) $< edu/jas/gbufd/%Test.class: trc/edu/jas/gbufd/%Test.java $(JAVAC) $< edu/jas/gbufd/%.class: src/edu/jas/gbufd/%.java $(JAVAC) $< edu/jas/structure/%Test.class: trc/edu/jas/structure/%Test.java $(JAVAC) $< edu/jas/structure/%.class: src/edu/jas/structure/%.java $(JAVAC) $< edu/jas/util/%Test.class: trc/edu/jas/util/%Test.java $(JAVAC) $< edu/jas/util/%.class: src/edu/jas/util/%.java $(JAVAC) $< edu/jas/application/%Test.class: trc/edu/jas/application/%Test.java $(JAVAC) $< edu/jas/application/%.class: src/edu/jas/application/%.java $(JAVAC) $< edu/jas/root/%Test.class: trc/edu/jas/root/%Test.java $(JAVAC) $< edu/jas/root/%.class: src/edu/jas/root/%.java $(JAVAC) $< edu/jas/kern/%Test.class: trc/edu/jas/kern/%Test.java $(JAVAC) $< edu/jas/kern/%.class: src/edu/jas/kern/%.java $(JAVAC) $< edu/jas/integrate/%Test.class: trc/edu/jas/integrate/%Test.java $(JAVAC) $< edu/jas/integrate/%.class: src/edu/jas/integrate/%.java $(JAVAC) $< edu/mas/kern/%Test.class: trc/edu/mas/kern/%Test.java $(JAVAC) $< edu/mas/kern/%.class: src/edu/mas/kern/%.java $(JAVAC) $< edu.jas.%: edu/jas/%.class $(JAVA) $@ $(cl) edu.jas.arith.%: edu/jas/arith/%.class $(JAVA) $@ $(cl) edu.jas.poly.%: edu/jas/poly/%.class $(JAVA) $@ $(cl) edu.jas.ps.%: edu/jas/ps/%.class $(JAVA) $@ $(cl) edu.jas.gb.%: edu/jas/gb/%.class $(JAVA) $@ $(cl) edu.jas.ufd.%: edu/jas/ufd/%.class $(JAVA) $@ $(cl) edu.jas.gbufd.%: edu/jas/gbufd/%.class $(JAVA) $@ $(cl) edu.jas.vector.%: edu/jas/vector/%.class $(JAVA) $@ $(cl) edu.jas.gbmod.%: edu/jas/gbmod/%.class $(JAVA) $@ $(cl) edu.jas.structure.%: edu/jas/structure/%.class $(JAVA) $@ $(cl) edu.jas.util.%: edu/jas/util/%.class $(JAVA) $@ $(cl) edu.jas.application.%: edu/jas/application/%.class $(JAVA) $@ $(cl) edu.jas.root.%: edu/jas/root/%.class $(JAVA) $@ $(cl) edu.jas.kern.%: edu/jas/kern/%.class $(JAVA) $@ $(cl) edu.jas.integrate.%: edu/jas/integrate/%.class $(JAVA) $@ $(cl) edu.mas.kern.%: edu/mas/kern/%.class $(JAVA) $@ $(cl) FILES=$(wildcard src/edu/jas/structure/*.java src/edu/jas/arith/*.java src/edu/jas/poly/*.java src/edu/jas/ps/*.java src/edu/jas/gb/*.java src/edu/jas/application/*.java src/edu/jas/vector/*.java src/edu/jas/gbmod/*.java src/edu/jas/gbufd/*.java src/edu/jas/util/*.java src/edu/jas/ufd/*.java src/edu/jas/kern/*.java src/edu/jas/root/*.java src/edu/jas/integrate/*.java) TESTFILES=$(wildcard trc/edu/jas/structure/*.java trc/edu/jas/arith/*.java trc/edu/jas/poly/*.java trc/edu/jas/ps/*.java trc/edu/jas/gb/*.java trc/edu/jas/application/*.java trc/edu/jas/vector/*.java trc/edu/jas/gbmod/*.java trc/edu/jas/gbufd/*.java trc/edu/jas/util/*.java trc/edu/jas/ufd/*.java trc/edu/jas/kern/*.java trc/edu/jas/root/*.java trc/edu/jas/integrate/*.java) LIBS=$(JUNITPATH) $(LOG4JPATH) $(JOMPPATH) $(TNJPATH) CLASSES=edu/jas/structure/ edu/jas/arith/ edu/jas/poly/ edu/jas/ps/ edu/jas/gb/ edu/jas/gbufd edu/jas/application/ edu/jas/vector/ edu/jas/gbmod/ edu/jas/util/ edu/jas/ufd/ edu/jas/kern/ edu/jas/root/ edu/jas/integrate/ PYS=$(wildcard *.py) EXAMPY=$(wildcard examples/*.py) DOCU=$(wildcard jas-log.html index.html problems.html design.html COPYING* sample.jythonrc overview.html) # */package.html doc: $(FILES) $(TESTFILES) $(DOC) $(DOCOPTS) -d doc/api $(FILES) $(TESTFILES) epydoc: examples/jas.py epydoc -o doc/jython -n "Python to JAS" -u ../../index.html examples/jas.py rdoc: examples/jas.rb jrdoc -o doc/jruby -U -S -N -t "Ruby to JAS" examples/jas.rb texdoc: $(FILES) $(TESTFILES) mkdir -p doc/tex rm -f doc/tex/* $(DOC) $(DOCOPTS) -doclet TexGen -docletpath ~/java/lib/texgen.jar -dest doc/tex $(FILES) $(TESTFILES) ls doc/tex/* | grep -v Test | grep -v allclasses | xargs cat > doc/tex/allclasses.tex sed -i -f doc/totex.sed doc/tex/allclasses.tex cd doc; pdflatex jas_texgen.tex ALLJAR=$(FILES) $(TESTFILES) $(DOCU) Makefile build.xml log4j.properties $(PYS) jas-all.jar: $(ALLJAR) $(JDK)/jar -cvf jas.jar $(ALLJAR) edu/ cp jas.jar $(LIBPATH)/ mv jas.jar /tmp/jas-`date +%Y%j`.jar jas.tgz: $(FILES) $(TESTFILES) *.html TODO tar -cvzf jas.tgz $(FILES) $(TESTFILES) *.html TODO cp jas.tgz /tmp/jas-`date +%Y%j`.tgz # cp jas.jar ...../jas-`date +%Y%j`.jar #jas-run.jar: GBManifest.MF $(TOJAR) # $(JDK)/jar -cvfm jas-run.jar GBManifest.MF $(TOJAR) TOJAR=$(FILES) $(TESTFILES) $(CLASSES) Makefile build.xml log4j.properties $(EXAMPY) examples/machines.test $(wildcard COPYING*) jas.jar: $(FILES) $(TESTFILES) Makefile build.xml log4j.properties $(EXAMPY) $(JDK)/jar -cf jas.jar $(TOJAR) cp jas.jar $(LIBPATH)/ # $(JDK)/jar -cf jas.jar $(filter-out %/ufd/, $(filter-out src/edu/jas/ufd/%.java, $(TOJAR))) jas-doc.jar: $(DOCU) doc/ $(JDK)/jar -cvf jas-doc.jar $(DOCU) doc/ dist: jas.jar jas-run.jar jas-doc.jar $(LIBS) tar -cvzf jas-dist.tgz jas.jar jas-run.jar jas-doc.jar $(LIBS) # jars: jas-run.jar jas-doc.jar #jars: jas.jar jas-run.jar jas-doc.jar lint: $(JDK)/java -jar $(LINTPATH) -v 3 -classpath $(DOCCLASSES):jas.jar -sourcepath src edu.jas.* # $(JDK)/java -jar $(LINTPATH) -v 5 -exact -classpath $(DOCCLASSES) -sourcepath src edu.jas.* clean: find . -name "*~" -follow -print -exec rm {} \; #rm -f application/application arith/arith kern/kern gbmod/gbmod poly/poly ps/ps gb/gb structure/structure ufd/ufd util/util vector/vector tests: ant test 2>&1 | tee t.out ant exam 2>&1 | tee e.out find examples -name "*.py"|grep -v jas.py |grep -v plot|grep -v versuch|sort|xargs -L 1 echo "time jython $(SOPTS)" | awk '{ printf "echo %s\n", $$0; printf "%s\n", $$0 }' > ./all_jython.sh time bash all_jython.sh 2>&1 | tee tjy.out find examples -name "*.rb"|grep -v jas.rb |grep -v versuch|sort|xargs -L 1 echo "time jruby $(SOPTS)" | awk '{ printf "echo %s\n", $$0; printf "%s\n", $$0 }' > ./all_jruby.sh time bash all_jruby.sh 2>&1 | tee tjr.out make edu.jas.application.RunGB cl="seq examples/trinks6.jas" | tee tr.out make edu.jas.application.RunGB cl="seq+ examples/trinks6.jas" | tee -a tr.out make edu.jas.application.RunGB cl="par examples/trinks6.jas 4" | tee -a tr.out make edu.jas.application.RunGB cl="par+ examples/trinks6.jas 4" | tee -a tr.out cd jython; make tests | tee jsr.out cd mpj; make tests | tee mpj.out cd ../jas-versions/jlinalg_adapter; make tests | tee ja.out cd ../jas-versions/commons-math_adapter; make tests | tee ja.out -grep FAIL t.out -grep Exception e.out | grep -v GCDProxy | grep -v GBProxy -grep File tjy.out -grep -i error tjr.out -grep -i error jython/jsr.out -grep -i error mpj/mpj.out -grep -i error ../jas-versions/jlinalg_adapter/ja.out -grep -i error ../jas-versions/commons-math_adapter/ja.out -egrep '(Exception|Usage)' tr.out metrics: ant jdepend ../java/javancss-32.53/bin/javancss -all -recursive -out test/javanccs-`date +%Y-%m-%d`.out src findbugs: cd ~/java/findbugs; bin/fb analyze -sortByClass -medium -html -nested:false /home/kredel/jas/edu/jas/ > jas.findbugs-report.medium.html #svn copy file:///$(SVNREPO)/jas/trunk file:///$(SVNREPO)/jas/tags/$(VERSION) SVNREV=svnlook youngest $(SVNREPO)/jas SVNDATE=svnlook date $(SVNREPO)/jas # Jan 2008 SVNSRT=1584 # Jun 2008 SVNSRT=1882 # Sep 2008 SVNSRT=2118r # jan 2009 SVNSRT=2288 # jun 2009 SVNSRT=2668 # jan 2010 SVNSRT=2978 # jun 2010 SVNSRT=3188 # jan 2011 SVNSRT=3458 # jul 2011 SVNSRT=3688 # dec 2011 SVNSRT=3838 export: rm -rf ~/jas-versions/$(VERSION) svn export --quiet file:///$(SVNREPO)/jas/trunk ~/jas-versions/$(VERSION) cd ~/jas-versions/$(VERSION); jas_dosed $(VERSION) `$(SVNREV)` download.html svn log -v -r HEAD:$(SVNSRT) file:///$(SVNREPO)/jas/trunk src trc examples > ~/jas-versions/$(VERSION)/svn_change.log cd ~/jas-versions/; jar -cfM $(VERSION).`$(SVNREV)`-src.zip $(VERSION)/ cd ~/jas-versions/$(VERSION)/; ant compile > ant_compile.out cd ~/jas-versions/$(VERSION)/; jar -cfm ../$(VERSION).`$(SVNREV)`-bin.jar GBManifest.MF edu/ COPYING* log4j.properties cd ~/jas-versions/$(VERSION)/; jar -uf ../$(VERSION).`$(SVNREV)`-bin.jar -C ~/jas-versions/$(VERSION)/examples jas.rb -C ~/jas-versions/$(VERSION)/examples jas.py cd ~/jas-versions/$(VERSION)/; ant doc > ant_doc.out cd ~/jas-versions/$(VERSION)/; epydoc -v -o doc/jython -n "Python to JAS" -u ../../index.html examples/jas.py > epydoc.out cd ~/jas-versions/$(VERSION)/; jrdoc -o doc/jruby -U -S -N -t "Ruby to JAS" examples/jas.rb > rdoc.out 2>&1 cd ~/jas-versions/$(VERSION)/; jar -cfM ../$(VERSION).`$(SVNREV)`-doc.zip doc/ *.html *.css cd ~/jas-versions/$(VERSION)/; ant test > ant_test.out cd ~/jas-versions/$(VERSION)/; sh ./jython_tests.sh >jython_tests.out 2>&1 cd ~/jas-versions/$(VERSION)/; sh ./jruby_tests.sh >jruby_tests.out 2>&1 cp ~/jas-versions/$(VERSION).`$(SVNREV)`-bin.jar $(LIBPATH)/jas.jar cp ~/jas-versions/$(VERSION).`$(SVNREV)`-bin.jar ~/jas-versions/$(VERSION)/jas.jar mv ~/jas-versions/$(VERSION).`$(SVNREV)`-*.jar ~/jas-versions/$(VERSION)/ mv ~/jas-versions/$(VERSION).`$(SVNREV)`-*.zip ~/jas-versions/$(VERSION)/ cd ~/jas-versions/$(VERSION)/jython; make > ~/jas-versions/$(VERSION)/make_jython.out cd ~/jas-versions/$(VERSION)/mpj; make > ~/jas-versions/$(VERSION)/make_mpj.out cd ~/jas-versions/$(VERSION)/meditor; jas_dosed $(VERSION) `$(SVNREV)` manifest.mf cd ~/jas-versions/$(VERSION)/meditor; make > ~/jas-versions/$(VERSION)/make_meditor.out cd ~/jas-versions/log4j_adapter; make > ~/jas-versions/$(VERSION)/make_mylog.out cp ~/java/lib/mylog.jar ~/jas-versions/$(VERSION)/ cd ~/jas-versions/log4j_droid_adapter; make > ~/jas-versions/$(VERSION)/make_droidlog.out cp ~/java/lib/droidlog.jar ~/jas-versions/$(VERSION)/ cd ~/jas-versions/jlinalg_adapter; make > ~/jas-versions/$(VERSION)/make_jlinalg.out cp ~/java/lib/jlinalg_adapter.jar ~/jas-versions/$(VERSION)/ cd ~/jas-versions/commons-math_adapter; make > ~/jas-versions/$(VERSION)/make_commons-math.out cp ~/java/lib/commons-math_adapter.jar ~/jas-versions/$(VERSION)/ deploy: $(RSYNC) -e 'ssh -p 2222' --delete-after --exclude=DTD --exclude=*xml ~/jas-versions/$(VERSION)/ krum:htdocs/$(VERSION) git-export: cd ~/jas-versions/jas-git/jas; git svn rebase > ~/jas-versions/$(VERSION)/git_svn.out cd ~/jas-versions/jas-git/jas; git push -v deploy > ~/jas-versions/$(VERSION)/git_push.out git-deploy: $(RSYNC) -e 'ssh -p 2222' --delete-after ~/jas-versions/jas-git/jas.git/ krum:htdocs/jas.git cd ~/jas-versions/jas-git/jas; git push -v $(DRY) google >> ~/jas-versions/$(VERSION)/git_push.out jas-bin.jar: jar -cfm $(VERSION).`$(SVNREV)`-bin.jar GBManifest.MF edu/ COPYING* log4j.properties jar -uf $(VERSION).`$(SVNREV)`-bin.jar -C examples jas.rb -C examples jas.py young: echo youngest revision `svnlook youngest $(SVNREPO)/jas` subst: cd ~/jas-versions/$(VERSION); jas_dosed $(VERSION) `$(SVNREV)` download.html # lines of code and number of classes loc: young (find src -name "*.java"; find trc -name "*.java")| wc -l find src -name "*.java" | grep -v Test | wc -l find trc -name "*.java" | grep Test | wc -l (find src -name "*.java"; find trc -name "*.java") | xargs cat | wc find src -name "*.java" | grep -v Test | xargs cat | wc find trc -name "*.java" | grep Test | xargs cat | wc find trc -name "*.java" | grep Test | xargs cat | grep "void test" | wc -l find ~/jas-versions/log4j_adapter -name "*.java" | wc -l find ~/jas-versions/log4j_adapter -name "*.java" | xargs cat | wc find ~/jas-versions/jlinalg_adapter -name "*.java" | wc -l find ~/jas-versions/jlinalg_adapter -name "*.java" | xargs cat | wc find ~/jas-versions/commons-math_adapter -name "*.java" | wc -l find ~/jas-versions/commons-math_adapter -name "*.java" | xargs cat | wc find jython -name "*.java" | wc -l find jython -name "*.java" | xargs cat | wc find mpj -name "*.java" | wc -l find mpj -name "*.java" | xargs cat | wc cat examples/jas.py | wc find examples -name "*.py" | grep -v jas.py | xargs cat | wc cat examples/jas.rb | wc find examples -name "*.rb" | grep -v jas.rb | xargs cat | wc # -eof- jas-2.5/intro.html0000644000175000017500000005562412137571562014411 0ustar giovannigiovanni JAS Project

Java Algebra System (JAS) Project

Introduction. The Java Algebra System (JAS) is an object oriented, type safe and multi-threaded approach to computer algebra. JAS provides a well designed software library using generic types for algebraic computations implemented in the Java programming language using the JVM runtime infrastructure. The library can be used as any other Java software package or it can be used interactively or interpreted through a jython (Java Python) or jruby (Java Ruby) front end, there is also an Android App based on Ruboto (jruby for Android). The focus of JAS is at the moment on commutative, solvable and non-commutative polynomials, power series, Groebner bases, factorization, real and complex roots and applications. By the use of Java as implementation language JAS is 64-bit and multi-core CPU ready and can make use of mutiple CPUs where available.

The library contains at the moment of the following packages:

edu.jas.structure:
contains interfaces for the most general algebraic structures like RingElem and RingFactory.
edu.jas.arith:
contains classes for arithmetic in the basic coefficient rings like BigRational, BigInteger, ModInteger, BigDecimal or BigComplex.
edu.jas.poly:
contains classes for commutative polynomial, solvable polynomial and free non-commutative polynomial arithmetic like GenPolynomial, GenSolvablePolynomial, GenWordPolynomial and others such as AlgebraicNumber and a polynomial parser GenPolynomialTokenizer.
edu.jas.vector:
contains classes for vectors and lists of polynomials and solvable polynomials like GenVector or GenMatrix.
edu.jas.gb:
contains classes for polynomial and solvable polynomial reduction, Gröbner bases over fields and ideal arithmetic as well as thread parallel and distributed versions of Buchbergers algorithm like ReductionSeq, GroebnerBaseAbstract, GroebnerBaseSeq, GroebnerBaseParallel and GroebnerBaseDistributedHybridEC. There are also Gröbner bases in polynomial rings over principal ideal domains and Euclidean domains, so called D- and E-Gröbner bases, e.g. EGroebnerBaseSeq. New are Gröbner bases in free non-commutative polynomial rings over (skew) fields, see WordGroebnerBaseSeq.
edu.jas.gbmod:
contains classes for module Gröbner bases and syzygies over polynomials and solvable polynomials like ModGroebnerBase or SolvableSyzygy.
edu.jas.application:
contains classes with applications of Gröbner bases such as ideal intersections and ideal quotients implemented in Ideal or SolvableIdeal. Comprehensive Gröbner bases for polynomial rings over parameter rings are contained in class ComprehensiveGroebnerBaseSeq. Latest additions are zero and arbitrary dimensional radical-, irreducible-, prime- and primary-decomposition implemented in class Ideal.
edu.jas.ufd:
contains classes for unique factorization domains. Like the interface GreatestCommonDivisor, the abstract class GreatestCommonDivisorAbstract and various implementations, e.g. polynomial remainder sequences and modular algorithms. The package now contains factorization algorithms for univariate polynomials over several coefficient rings: modulo primes in class FactorModular, over integers in class FactorInteger, over rational numbers in class FactorRational and over algebraic numbers in class FactorAlgebraic<C>.
edu.jas.gbufd:
contains classes for Gröbner base computation using classes from the edu.jas.ufd package for polynomial coefficients. The main classes deal with pseudo reduction PseudoReduction, PseudoReductionSeq and greatest common divisors computation on coefficients GroebnerBasePseudoSeq. Multiplicative sets of polynomials with several simplifications, e.g. maintaining co-prime factors or co-prime and squarefree factors, are contained in classes MultiplicativeSet, MultiplicativeSetCoPrime or MultiplicativeSetSquarefree. Also contained are Gröbner bases for polynomial rings over regular rings (direct products of fields or integral domains) in RGroebnerBaseSeq and RGroebnerBasePseudoSeq.
edu.jas.root:
contains classes for real root computations. Like the interface RealRoots, the abstract class RealRootsAbstract and at the moment of a single implementation based on Sturm sequences RealRootsSturm. The package further contains an implementation for real algebraic numbers RealAlgebraicNumber with a corresponding factory RealAlgebraicRing. For complex root isolation there are ComplexRoots interface, ComplexRootsAbstract and ComplexRootsSturm classes. The implementation provides an exact infallible method which follows the numeric method of Wilf. It uses Sturm sequences following the Routh-Hurwitz Method to count the number of complex roots within a rectangle in the complex plane. There is also an implementation for complex algebraic numbers ComplexAlgebraicNumber with a corresponding factory ComplexAlgebraicRing.
edu.jas.ufdroot:
contains classes for factorization in structures used in root computation, for example FactorRealAlgebraic.
edu.jas.ps:
contains univariate and multivariate power series arithmetic in classes UnivPowerSeries and MultiVarPowerSeries. There is an initial implementation of Mora's tangent cone reduction algorithm in class ReductionSeq and a standard bases computation in StandardBaseSeq with method STD().
edu.jas.integrate:
contains methods for the elementary integration of univariate rational functions. The main class is ElementaryIntegration with method integrate().
edu.jas.util:
contains further utilities for parallel and distributed computations like ThreadPool, DistThreadPool or DistHashTable. Part of this package has become obsolete with JDK 1.5.

This page contains documentation and the implementation for the new version which is designed using type parameters and requires at least Java 6 (JDK 1.6). It will also compile on Java 7 (JDK 1.7). Older versions (no more supported) can be found here: JAS 2.4, JAS 2.3, JAS 2.2, JAS 2.1, JAS 2.0, JAS using JDK 1.5 and JAS using JDK 1.4.

Documentation

For informations on how to get started with JAS see the users guide. For frequently asked question see FAQ. There is an index of algorithms for the book Gröbner bases and their JAS equivalents. An index of algorithms for the book Algorithms for Computer Algebra and their JAS equivalents is also available.

The JAS API guide describes the interface and class design considerations and contains an overview of the most important classes and methods. An online Javadoc documentation of the API together with source code is contained in the API documentation (also available as jas-doc.jar). Some design considerations for the new generic version.

README and COPYING.jas (GPL) or COPYING.lgpl.jas (LGPL)

Published papers and talks about JAS

Design and experiences using MPJ and high speed InfiniBand networking for algebraic computations are described in Heinz Kredel, Distributed Gröbner bases computation with MPJ, to appear in proceedings of the EOOPS Workshop at AINA-2013, March 25-28, 2013, Barcelona, Spain (slides)

Some ideas on categories and mixin composition in ScAS and JAS are presented in the poster Raphael Jolly, Heinz Kredel, Categories as classes and mixin composition, Poster at CASC 2012, September 3-6, 2012, Maribor, Slovenia

A comparison of API interfaces for computer algebra is presented in the paper Heinz Kredel, Fostering Interoperability in Java-Based Computer Algebra Software, Proceedings FINA Workshop AINA-2012, March 26-29, 2012, Fukuoka, Japan (slides)

The design of algebraic extension structures in JAS and ScAS is presented in the talk Raphael Jolly, Heinz Kredel, Algebraic Structures as Typed Objects, at the Workshop on Computer Algebra in Scientific Computing CACS 2011, Kassel, Germany, 2011. (slides)

An early description of the JAS package for unique factorization domains (greatest common divisors, square-free decomposition, factorization) is contained in the article Heinz Kredel, Unique Factorization Domains in the Java Computer Algebra System, Special issue on Automated Deduction in Geometry, Lecture Notes in Computer Science volume 6301, pages 86-115, Springer, 2011

The design of JAS and ScAS is presented together with examples in the talk Raphael Jolly, Heinz Kredel, Generic, Type-safe and Object Oriented Computer Algebra Software, at the Workshop on Computer Algebra in Scientific Computing CACS 2010, Tsakhkadzor, Armenia, 2010. (slides)

Performance meassurements for the distributed hybrid Gröbner bases implementation are contained in the paper Parallel and distributed Gröbner bases computation in JAS, avaliable as arxiv:1008.0011, 2010.

The new distributed hybrid Gröbner bases implementation is explained in the talk Distributed hybrid Groebner bases computation, at the CISIS 2010 Workshop on Engineering Complex Distributed Systems (ECDS 2010), Krakow. (slides)

A description of the JAS comprehensive Gröbner bases package is be contained in the talk Comprehensive Gröbner bases in a Java Computer Algebra System, at the Asian Symposium on Computers and Mathematics (ASCM 2009), Fukuoka.

Some unique factorization domain algorithms in JAS are contained in the seminar presentation Tools for the integration of rational functions in Java, during the Computer-Algebra Seminar, University of Mannheim, FMI 2009

More background information on the python scripting interface for JAS and ScAS can be found in the article Raphael Jolly, Heinz Kredel, Symbolic Script Programming for Java, avaliable as arXiv:0906.2315v2, 2009.

The parallel and distributed Gröbner bases implementations are explained in the talk Distributed parallel Groebner bases computation, at the CISIS 2009 Workshop on Engineering Complex Distributed Systems (ECDS 2009), Fukuoka. (slides)

The Gröbner bases implementation of JAS is explained in the seminar presentation Gröbner bases and applications in Java, during the Computer-Algebra Seminar, University of Mannheim, FMI 2008

A description of the JAS greatest common divisor package is contained in the talk Multivariate Greatest Common Divisors in the Java Computer Algebra System, at the International Workshop on Automated Deduction in Geometry (ADG 2008), Shanghai.

Some background information on the python scripting interface for JAS can be found in the article Raphael Jolly, Heinz Kredel, How to turn a scripting language into a domain specific language for computer algebra, avaliable as arXiv:0811.1061v1, 2008. Previous title was Computer algebra in Java: libraries and scripting.

A comparison of JAS to other Computer Algebra Systems is contained in the talk Evaluation of a Java Computer Algebra System, at the Asian Symposium on Computer Mathematics (ASCM 2007), Singapore.
It has been published as paper in Heinz Kredel, Evaluation of a Java Computer Algebra System, Special issue Computer Mathematics of ASCM 2007 Revised and Invited Papers in Lecture Notes in Computer Science, volume 5081/2008, pages 121-138, Springer Berlin / Heidelberg

An article On a Java Computer Algebra System, its Performance and Applications, in Science of Computer Programming (2008).

At the PPPJ 2006 conference in Mannheim I presented the design of the JAS types, classes and implementation "On the Design of a Java Computer Algebra System" (slides).

At the A3L conference in Passau, 2005 I gave some background information on the development from MAS to JAS "A Systems Perspective on A3L" (slides).

The history of the JAS project can be found in the Web-Log. See also the related projects and credits.

Download, installation and unit tests

See Download page.

Usage with the JEclipse IDE

See Download page.

Usage with the Jython interpreter

See Download and Users guide pages.

jython examples

Commutative: trinks.py, katsura.py

Solvable: wa_32.py, u_sl_3_prod.py, u_sl_3.py

Modules: armbruster.py, syz.py, syzy2.py

Usage with the JRuby interpreter

See Download.

jruby examples

Commutative: trinks.rb, all_rings.rb, gbs.rb

Usage of the Android App

See Download. As the Android app is based on Ruboto (jruby IRB for Android) the usage is the same as with JRuby. There is a "Scripts" button in the app where all ruby examples can be accessed.

The main Ruboto screen with the "trinks.rb" example and its output looks as follows.

   

RunGB Examples

The following are examples which can be executed with the class edu.jas.application.RunGB. E.g.
java -cp .:log4j.jar:jas.jar:... edu.jas.application.RunGB <args>

Commutative: gbks.jas, katsura2.jas, katsura3.jas, katsura4.jas, katsura5.jas, katsura5s.jas, katsura5w.jas, katsura6.jas, katsura6w.jas, katsura7.jas, katsura8.jas, rose.jas, trinks6.jas, trinks7.jas, vw.jas,

Solvable: kw_18.jas, ore_t.jas, sgb.jas, u_sl_3.jas, wa_1.jas, wa_32.jas, wa_34.jas, wa_39.jas, wa_41.jas, wa_61.jas


Heinz Kredel

Last modified: Tue Apr 30 00:24:21 CEST 2013

Valid XHTML 1.0! Valid CSS!

jas-2.5/faq.html0000644000175000017500000000621311140417152013776 0ustar giovannigiovanni Frequently asked questions

Frequently asked questions

In this page we give answers to frequently asked questions about JAS.

  1. When using the bytecode from *-bin.jar, I get "Bad version number in .class"
  2. When trying to compile JAS with "ant compile", I get NoClassDefFoundError: org/apache/tools/ant/launch/Launcher
  3. When compiling a sample code I get '(' or '[' expected errors
  4. After compiling a sample code I get NoClassDefFoundError: org/apache/log4j/Logger
  5. I can not use Apache log4j in my project for some reason.

When using the bytecode from *-bin.jar I get "Bad version number in .class"

This error occurs if your Java virtual maschine is older than the Java used in compiling the classes. Use the JAS source to compile the .class files with your version of the Java VM. See e.g. Eclipse.

When trying to compile JAS with "ant compile", I get NoClassDefFoundError: org/apache/tools/ant/launch/Launcher

Ant uses a wrong Java version. Define the Java home directory in the environment. E.g. in Linux use
export JAVA_HOME=/usr/java/jdk1.6.0_02
or the directory of your installed Java version.

When compiling a sample code I get '(' or '[' expected errors

JAS uses the new generic type parameters, which where introduced in Java version 5. So you must use at least a Java Development Kit 5 or later. See Java.sun.com for the latest Java releases.

After compiling a sample code I get NoClassDefFoundError: org/apache/log4j/Logger

You must include the Log4j classes in the classpath. e.g.
java -cp log4j.jar:. mysample

I can not use Apache log4j in my project for some reason.

We provide an adapter package for Java logging with mylog.jar. The package contians classes which delegate all logging calls to java.util.logging classes. Java logging must be configured to your needs - we do not provide sample configurations. You use it inplace of log4j.jar, for example
java -cp mylog.jar:. mysample


Heinz Kredel

Last modified: Thu Jan 29 22:23:30 CET 2009

jas-2.5/related.html0000644000175000017500000003713612070355336014667 0ustar giovannigiovanni Related projects

Related projects

Computer Algebra Systems using Java

  • ScAS is a computer algebra system developed in Scala. Scala has some more features than Java to optimally support the implementation of a computer algebra system. The basic structure of ScAS is developed in cooperation with the basic structure of JAS, see the co-authored papers in the Documentation section. ScAS is also a successor of jscl-meditor.

  • jscl-meditor Java symbolic computing library and mathematical editor. The goal of this project is to provide a Java symbolic computing library and a mathematical editor acting as a front-end to the former. There are several computer algebra systems available on the market, most of them developed in other languages, mainly C/C++ and Lisp. But the benefits of using Java in symbolic computation are great. Aside from being widely used and to comply with various standards, this language has two features of concern: readability and portability.

  • MathEclipse is a Java Computer Algebra system. MathEclipse has functions for arbitrary-precision integer arithmetic, matrices, vectors, finite sets, derivatives, pattern-matching rewriting rules and functional programming.

  • Symja - a symbolic math system written in Java based on the MathEclipse libraries. Features: arbitrary precision integers, rationals and complex numbers, polynomials, differentiation, pattern matching and linear algebra.

  • GeoGebra is dynamic mathematics software for all levels of education that joins arithmetic, geometry, algebra and calculus. On the one hand, GeoGebra is an interactive geometry system. You can do constructions with points, vectors, segments, lines, conic sections as well as functions and change them dynamically afterwards. On the other hand, equations and coordinates can be entered directly. Thus, GeoGebra has the ability to deal with variables for numbers, vectors and points, finds derivatives and integrals of functions and offers commands like Root or Extremum. These two views are characteristic of GeoGebra: an expression in the algebra view corresponds to an object in the graphics view and vice versa.

  • MathPiper is a new mathematics-oriented programming language which is simple enough to be learned as a first programming language and yet powerful enough to be useful in any science, mathematics, or engineering related career. MathPiper is also a Computer Algebra System (CAS) which is similar in function to the CAS which is included in the TI 89 and TI 92 calculators.

  • Jasymca: Programmable Java calculator. CAS (Computer Algebra System), provides exact and symbolic datatypes, interactive graphics display of functions. The user interface can be selected from either a Matlab/Octave/SciLab-style, or a GNU-Maxima-style. Runs on any Java SE- and ME-platform: Windows, MacOS, Linux, Cellphone, PDA and others.

  • JGEX: Java Geometry Expert is an ongoing developing system which initially began in early 2004 in Wichita State Univerisity. JGEX is a system which combines our approach for visually dynamic presentation of proofs (VDDP), dynamic geometry software (DGS), automated geometry theorem prover (GTP). The VDDP part is the most distinctive part of JGEX. It is based on our work on DGS and GTP. JGEX can be used to create proofs either manually and automatically. It provides a seris of visual effects for presenting of these proofs. With the applet version of JGEX, the user may create beautiful examples and put them on the web to share with others

  • JLinAlg is an open source and easy-to-use Java-library for linear algebra that is licensed under the GNU General Public License (GPL).

  • The Apache Commons Mathematics Library is a library of lightweight, self-contained mathematics and statistics components addressing the most common problems not available in the Java programming language or Commons Lang.

  • java.symcomp.org Java Library for SCSCP and OpenMath. The libraries org.symcomp.openmath and org.symcomp.scscp were developed in the SCIEnce Project, an Integrated Infrastructure Initiative, funded by the European Commission under the Research Infrastructures Action of Framework 6. WUPSI is a Universal Popcorn SCSCP Interface - The SCSCP Swiss Army Knife.

  • The Orbital Library is a Java class library providing object-oriented representations and algorithms for logic, mathematics, and artificial intelligence. It comprises theorem proving, computer algebra, search and planning, as well as machine learning algorithms.

  • Redberry is an open source Java framework providing capabilities for manipulation with tensors. The framework contains wide spectrum of algorithms required by tensor algebra. It is designed to find analytical solutions of complicated mathematical and physical problems.

  • Jscience is a set of Java Tools and Libraries for the Advancement of Sciences. The system is not limited to computer algebra.

Other Open Source Computer Algebra Systems

  • Singular is a Computer Algebra System for polynomial computations with special emphasis on the needs of commutative algebra, algebraic geometry, and singularity theory.

  • CoCoA Computations in Commutative Algebra.

  • Risa/Asir is an open source general computer algebra system.

  • Mathemagix is a free computer algebra and analysis system under development. Standard libraries are available for algebraic computation (large numbers, polynomials, power series, matrices, etc. based on FFT and other fast algorithms) for exact and approximate computation. This should make Mathemagix particularly suitable as a bridge between symbolic computation and numerical analysis. The packages are written in C++. They can both be used from the new compiler mmc, from the old interpreter Mmx-light, or as standalone C++ libraries.

  • Pari/GP is a widely used computer algebra system designed for fast computations in number theory (factorizations, algebraic number theory, elliptic curves...), but also contains a large number of other useful functions to compute with mathematical entities such as matrices, polynomials, power series, algebraic numbers, etc., and a lot of transcendental functions.

  • Reduce is an interactive system for general algebraic computations of interest to mathematicians, scientists and engineers. It has been produced by a collaborative effort involving many contributors. Its capabilities include: expansion and ordering of polynomials and rational functions; substitutions and pattern matching in a wide variety of forms; automatic and user controlled simplification of expressions; calculations with symbolic matrices; arbitrary precision integer and real arithmetic; facilities for defining new functions and extending program syntax; analytic differentiation and integration; factorization of polynomials; facilities for the solution of a variety of algebraic equations; facilities for the output of expressions in a variety of formats; facilities for generating optimized numerical programs from symbolic input; calculations with a wide variety of special functions; Dirac matrix calculations of interest to high energy physicists.

  • FLINT is a C library for doing number theory. FLINT provides types and functions for computing over various base rings. FLINT uses many new algorithms and is sometimes orders of magnitude faster than other available software. FLINT is written in ANSI C and runs on many platforms, but is currently mostly optimised for x86 and x86-64 architectures. It is designed to be threadsafe. FLINT depends on the MPIR (GMP) and MPFR libraries.

  • Maxima is a system for the manipulation of symbolic and numerical expressions, including differentiation, integration, Taylor series, Laplace transforms, ordinary differential equations, systems of linear equations, polynomials, and sets, lists, vectors, matrices, and tensors. Maxima yields high precision numeric results by using exact fractions, arbitrary precision integers, and variable precision floating point numbers. Maxima can plot functions and data in two and three dimensions.

  • Macaulay 2 is a software system devoted to supporting research in algebraic geometry and commutative algebra, whose creation has been funded by the National Science Foundation since 1992. Macaulay2 includes core algorithms for computing Gröbner bases and graded or multi-graded free resolutions of modules over quotient rings of graded or multi-graded polynomial rings with a monomial ordering. The core algorithms are accessible through a versatile high level interpreted user language with a powerful debugger supporting the creation of new classes of mathematical objects and the installation of methods for computing specifically with them. Macaulay2 can compute Betti numbers, Ext, cohomology of coherent sheaves on projective varieties, primary decomposition of ideals, integral closure of rings, and more.

  • Axiom is a general purpose Computer Algebra system. It is useful for research and development of mathematical algorithms. It defines a strongly typed, mathematically correct type hierarchy. It has a programming language and a built-in compiler. In 2007, Axiom was forked into two different open source projects: OpenAxiom, and FriCAS.
    FriCAS is an advanced computer algebra system. Its capabilities range from calculus (integration and differentiation) to abstract algebra. It can plot functions and has integrated help system.
    OpenAxiom is an open source platform for symbolic, algebraic, and numerical computations. It offers an interactive environment, an expressive programming language, a compiler, a large set of mathematical libraries of interest to researchers and practitioners of computational sciences.

  • More open source mathematical programs.

  • to be continued

Computer Algebra Systems using other Object Oriented Programing Languages

  • Sage is an Open Source Mathematics Software creating a viable free open source alternative to Magma, Maple, Mathematica, and Matlab. Sage is written in Python and Cython as an interface to other open source CAS Singular, PARI/GP, GAP, gnuplot, Magma, and Maple.

  • SymPy is a Python library for symbolic mathematics. It aims to become a full-featured computer algebra system (CAS) while keeping the code as simple as possible in order to be comprehensible and easily extensible. SymPy is written entirely in Python and does not require any external libraries.

  • GiNaC has been developed to become a replacement engine for xloops which in the past was powered by the Maple CAS. Its design is revolutionary in a sense that contrary to other CAS it does not try to provide extensive algebraic capabilities and a simple programming language but instead accepts a given language (C++) and extends it by a set of algebraic capabilities. The name GiNaC is an iterated and recursive abbreviation for GiNaC is Not a CAS, where CAS stands for Computer Algebra System.

  • Cadabra is a computer algebra system (CAS) designed specifically for the solution of problems encountered in field theory. It has extensive functionality for tensor polynomial simplification including multi-term symmetries, fermions and anti-commuting variables, Clifford algebras and Fierz transformations, implicit coordinate dependence, multiple index types and many more. The input format is a subset of TeX. Both a command-line and a graphical interface are available.


Heinz Kredel

Last modified: Sat Jan 28 15:07:25 CET 2012

jas-2.5/html.css0000644000175000017500000000067611764621254014042 0ustar giovannigiovanni body { background-color: #FFFFF5; margin-right: 1em; margin-left: 0.5em; } body.main { margin-top: 2.5em; } pre { background-color: silver; margin-left: 1em; margin-right: 1em; padding: 1em; } dt { font-weight: bolder; margin-top: 1em; } nav { line-height: 1.4em; } h1 { text-align: center; } .center { text-align: center; } .note { color: maroon; } jas-2.5/TODO0000644000175000017500000001254012132311140013021 0ustar giovannigiovanniList of things to be resolved or accomplished: issues to consider: - implement Berlekamp-Zassenhaus for modular factorization - implement IDEALDIV2 with extGB - implement Musers multivariate factorization, evtl. with sparse Hensel lifting - implement real roots with other methods, e.g. after Uspensky or Rolle - implement complex roots with other methods, e.g. after Collins and Krandick - implement involutive bases computation - implement signature based GB computation - make hashCode to reuse computed value --> not immutable - use further util.concurrent algorithms where possible, e.g. in DHT - make polynomial chinese remainder generic (?) - test caching results of gcd computation - refactor BigDecimal to RingElem and RingFactory, make precision variable - refactor from BasicLinAlg to GenMatrix and GenVector - implement univariate power series composition and power - make final variables public (?) - define quotientRemainder in RingElem interface (?) - make use of gcd in pseudo reduction, needs other coefficient type - implement matrices to vector - implement Boolean with RingElem interface (?) - check solvable polynomials with integral domain coefficients - refactor method names for groovy operator overloading, make examples for usage partially resolved and completed issues: - provide all Jython examples also for JRuby - implement multivariate Hensel lifting for multivariate polynomial factorization - implement 0-dim ideal complex root selection - refactor package structure to reduce circular dependences - implement parallel proxys for GB computation - rework parallel GB algorithms - implement FGLM GB algorithm - implement other term orders for multivariate power series - check the 693 exceptions (including 473 runtime exceptions) that are thrown, reduce number of runtime exceptions - check for safe publication in constructors, check wrt. the (new) Java memory model - check and fix Findbugs warnings - implement squarefree decomposition over fields of characteristic p - implement absolute polynomial factorization - implement univaiate and multivariate polynomial factorization - let arith implementations extend Power as abstract class add divide, subtract, abs, remainder to Power, name e.g RingElemAbstract clean structure of compareTo, signum and equals - is not possible - define power(n) in RingElem (not done) and implement in edu.jas.structure.Power and classes, done - add product category to applications - implement direct products of ring elements - define FieldElem and Field factory interfaces and use them for GB coefficients - refactor Hensel lifting to ufd package, not possible because of coefficient replacement trick !must be done some how! - check correct term order in recursive algorithms, in GCD ModEval only univariate cases are used, so term order is not a problem - add assertions to check for number of polynomial variables and term order, nvar in GenPolynomial and GenSolvablePolynomial done resolved and completed issues: - refactor unit tests to a different source code tree to avoid circular dependencys - implement AlgebraicNumber primitive element computation, done - implement prime and primary ideal decomposition for non-zero-dimensional ideals, done - implement prime and primary ideal decomposition for zero-dimensional ideals, done - implement multivariate power series, done - implement univariate power series, done - develop modifiable polynomial constructor or put method and iterators - rework junit tests to stop failing in case of zero polynomials - using git to publish the repository, done - rename divideAndRemainder to quotientRemainder - refactor the Quotient class to edu.jas.ufd package, done - implement d- and e-reductions and d-/e-Groebner bases, done - implement Groebner bases for regular rings, done - implement comprehensive GB, done - implement term order optimization from MAS, also for coefficients and solvable polynomials, done - implement complex roots, done - implement ModLong for faster modular arithmetic, done - implement construction of univariate polynomials in zero-dimensional ideals done - implement a global variable name generator in edu.jas.kern and use it in extend() and contract() done in GenPolynomialRing - implement RealAlgebraicNumber and RealAlgebraicNumberRing, done - implement real roots with Sturm sequence, done - refactor univPoly in solvable implementations, done - add missing comments in edu.jas.Algebra*, done - let inverse() throw a runtime exception, done; throw a checked exception (?, no) - split ModInteger to ModIntegerRing factory, done - make logger variables also final, done - rename getval() to getVal() in ExpVector, done - refactor ExpVector for different array element types, done - incorporate gcd() in the Quotient class in edu.jas.application - implement BigDecimal with RingElem interface, done - make examples with rational function field coefficients, e.g. Raksanyi example - replace thread-and-network-programming algorithms with util.concurrent, done - implement multivariate polynomial greatest common divisors, done - add methods to GenPolynomialRing to construct x_i polynomials, done - add version information in jas jar-file names, done - split RingFactory to ElemFactory, done - split AlgebraicNumber to AlgebraicNumberRing factory, done $Id: TODO 4369 2013-04-13 17:14:08Z kredel $ jas-2.5/overview.html0000644000175000017500000000422512132511474015102 0ustar giovannigiovanni Java Algebra Aystem

Java algebra system.

The Java Algebra System (JAS) is an object oriented, type safe and multi-threaded approach to computer algebra. JAS provides a well designed software library using generic types for algebraic computations implemented in the Java programming language using the JVM runtime infrastructure. The library can be used as any other Java software package or it can be used interactively or interpreted through an jython (Java Python) or jruby (Java Ruby) front ends. The focus of JAS is at the moment on commutative, solvable and non-commuative polynomials, power series, Groebner bases, factorization, real and complex roots and applications. By the use of Java as implementation language JAS is 64-bit and multi-core cpu ready and can make use of mutiple CPUs where available. JAS can run on a wide variety of devices ranging from Android (using the jruby Ruboto App and others) to compute clusters (using MPJ a Java Message Passing Interface (MPI)).

Static package structure overview
Package structure overview

See weblog for the latest changes.

See design for an overview on the design of the package and class structure.

See introduction as starting point for further information.

See more API documents: MPJ, JSR223, Findbugs, Jdepend, Licence etc.


Heinz Kredel

Last modified: Sun Apr 14 13:27:12 CEST 2013

$Id: overview.html 4370 2013-04-14 11:30:05Z kredel $

jas-2.5/jas-log.html0000644000175000017500000021555212137541066014604 0ustar giovannigiovanni JAS project web-log

JAS project web-log

For a detailed list of the latest changes see the Subversion change log.

2013, April - May
New algorithms for ideals in solvable polynomial rings in class SolvableIdeal, and new structures for solvable polynomial rings in classes SolvableQuotient, SolvableResidue and the corresponding factories SolvableQuotientRing, SolvableResidueRing. New theme for Ruby rdoc documentation. Adaption to a newer version of jruby (1.7.3). Further small fixes and improvments.
2013, January
New version number 2.5. The JAS Java API will be more stable from now on. Fixed a race condition in distributed (hybrid) Gröbner bases implementations. Improved MPJ version of GBs. Refactoring of GBFactory and added new option to select Gebauer & Möller critical pair handling in GBAlgorithmBuilder. Switch to DECIMAL128 as default in BigDecimal. Improved GreatestCommonDivisorHensel by using integer evaluation points and other optimizations.
2012, December
Mostly performance optimizations and small improvements and fixes. The optimizations include combined methods for polynomials like scaleSubtractMultiple(b, g, a, e, S) to compute the expression b xg this - a xe S in one rush. There is now first version of an Android App. The JAS App uses its JRuby scripting interface and runs within the Ruby IRB Android App Ruboto.
2012, November
New distributed Gröbner base algorithms based on MPI as communication middle-ware. The implementation uses the MPJ (MPI Java) API and can be run with both MPJ Express or FastMPJ. The implementing classes are GroebnerBaseDistributedMPJ for the pure distributed version and GroebnerBaseDistributedHybridMPJ for the distributed and multi-threaded version.
2012, October
New parts for free non-commutative Gröbner base computation and polynomial reduction. New interface WordGroebnerBase and new classes WordGroebnerBaseAbstract and WordGroebnerBaseSeq. jython and jruby access to non-commutative polynomials in WordPolyRing and WordIdeal. Improved selection of (commutative) Gröbner base algorithm implementations in class GBAlgorithmBuilder. For example in case of rational number coefficients a fraction free algorithm with optimization of the variable order can be requested by gbab.fractionFree() .optimize() .build().
2012, September
Refactorings to further reduce Findbugs issues. Removed Clonable from Element and renamed clone() to copy(). New classes for free non-commutative associative rings in GenWordPolynomial and GenWordPolynomialRing.
2012, August
Fixed most severe and many medium Findbugs issues. Remaining programming issues and possible bugs are listed in the Findbugs report.
2012, July
More JRuby examples. Bug fixes for right module Gröbner bases and multiple roots computation. Bug fixes for meaningful problems spotted by findbugs.
2012, June
Improved root bounds for real root computation. Added missing methods for real root computation. Fixed complex root selection of zero dimensional ideals. Small fixes and more missing methods.
2012, May
More, refactored and fixed algorithms for Wu-Ritt characteristic sets in class CharacteristicSetWu. Unit tests are in CharSetTest. jython and jruby script access to characteristic set algorithms in methods CS(), isCS(), csReduction(). Small fixes and improvements.
2012, March
The Jython and JRuby scripting classes PolyRing are now injecting the polynomial ring variables into the top level interpreter environment by default. New class GroebnerBaseFGLM to compute a Gröbner base according to the "FGLM" algorithm. It computes a Gröbner base with respect to a graded term order and then constructs the Gröbner base with respect to the requested term order via linear algebra in the residue class ring. Changes from '{}' to '()' in GenPolynomial to string conversion. New launcher shell script jas. Small fixes, improvements and a missing method implemented and in PolyUtilApp.
2012, February
Refactorings to simplify type parameters and loosen type conditions. New package edu.jas.ufdroot to remove cyclic package dependencies again. Improved selection of factorization implementations in FactorFactory classes and better suited constructors of the factorization implementations. Small fixes and improvements.
2012, January
Some algorithms for Wu-Ritt characteristic sets and unit tests in class PolyGBUtil. Small fixes and improvements.
2011, Sylvester
Modular variants and parallel proxy versions of resultant algorithms implemented. Cleanup and filled missing methods in GreatestCommonDivisor* classes in the edu.jas.ufd package. Fixed ModLong to ModInteger conversion. Small fixes, improvements and refactorings of methods to right classes.
2011, December
Switched to Java 7 for development. JAS will still compile and run on Java 6 and Java 5. A new online repositoriy for JAS on Google code which contains a bug-tracker. Definition of variables for polynomial ring generators in the jython and jruby scripting interface. More JRuby examples.
2011, October
Separated test classes to new test source tree (trc). New scripting classes for Gröbner base computations according to Eder and Perry (F5, Arri, GGV) and adapted jas.py in JAS for the required methods. More JRuby examples. Small improvements and fixes.
2011, September - October
Release 2.4 updates all depending packages to the latest version and prepares for JAS 3.0. Updates for Jython 2.5.2 and JRuby 1.6.4. A new index of all algorithms from the book Algorithms for Computer Algebra by Geddes & Czapor & Labahn to their JAS equivalents. Small improvements and fixes again in multivariate integral polynomial factorization.
2011, September
Bug fixes and missing cases for multivariate integral polynomial factorization with multivariate Hensel lifting. Further improvements and fixes.
2011, August
Experimental multivariate integral polynomial factorization with multivariate Hensel lifting in method factorsSquarefreeHensel() in class FactorInteger. Improved multivariate Hensel lifting in class HenselMultUtil. Small improvements and fixes.
2011, June
Experimental ideal complex root computation in method complexAlgebraicRoots() in class PolyUtilApp. Simple isolating interval refinement for real and complex roots. Alternative factoring of univariate polynomials over algebraic number fields via prime ideal decomposition in class FactorAlgebraicPrim. Improved parsing of complex numbers. Forced term orders in some situations and further small improvements and fixes.
2011, May
Complex roots represented by ideal real roots, uses new class RealAlgebraicNumber and RealAlgebraicRing in package edu.jas.application. New experimental RootFactory with methods to compute complex roots for polynomials with coefficients in some complex algebraic extension field of the rational numbers. Uses the respective classes form package edu.jas.root in a recursive setting. New generic factorization classes FactorRealAlgebraic and FactorRealReal. Small improvement for reduced / minimal Gröbner base computation.
2011, April
Multivariate algebraic ring / field extensions using class ResidueRing. Jruby and Jython versions and examples of the extension field builder. Small improvements and bug fixes for latest Eclipse and Java 1.7 version.
2011, March
Easy to use construction of towers of extension fields in class ExtensionFieldBuilder with methods for algebraic and transcendental field extensions. Improvements in real and complex algebraic numbers. Improved polynomial parser for recursive representations. Small bug fixes.
2011, February
New class HenselMultUtil for multivariate Hensel lifting. Will be used in polyomial factorization in the future. Some parts of greatest common divisor using multivariate Hensel lifting. The JAS source (r3408) compiles on Apache Harmony 6.0 (r991881). The unit tests pass with the exception of test cases involving object serialization.
2011, January
New scripting interface to Ruby (JRuby). Ruby allows rational number literals as p/q, which are better than the Python tuple form (p,q). Some toScript() methods rewritten to reflect the Ruby language requirements and to differentiate between Ruby and Python. More precise exceptions for modular computations to return also the discovered factors.
2010, December, 28
Cleanup of package structure so that all cyclic dependencies have been removed, see diagram. Split factory parsing parts from GenPolynomialTokenizer to RingFactoryTokenizer. Some artificial code was required to use solvable polynomials as ring elements since solvable polynomials cannot implement RingElem<GenSolvablePolynomial<C>>. This resulted in some cases in wrong method dispatch for the multiply() method due to compiler optimizations. A work around to detect and repair this is now implemented in class GenPolynomial.
2010, December, 18
New critial pair selection for Gröbner base computation with syzygy based algorithm after Gebauer and Möller in class OrderedSyzPairlist. Refactoring of Gröbner base classes to optionally use the new pair selection. Back port of some JDK 1.6 constructs to be again compatible with JDK 1.5. Small improvements in Kronecker factor combination in class FactorAbstract. Fixed race condition in ThreadPool and improved termination detection in Terminator. Fixes in parallel reduced Gröbner base computations. Fixed univariate polynomial construction in Ideal.
2010, October
Multivariate Taylor series expansion interface and implementation. Improved multivariate power series for standard base computation. Refactored methods to better suited classes and moved classes to decouple packages, e.g. Quotient* to package edu.jas.ufd. Fixed small bugs and cosmetic.
2010, September
Multivariate power series in classes MultiVarPowerSeries and MultiVarPowerSeriesRing. Mora's tangent cone reduction algorithm and standard base computation for power series in package edu.jas.ps. Iterator over exponent vectors.
2010, August, 28
Iterators for finite and some infinite structures and finite and infinite cartesian products of them. Fixed constructors to comply with the (new) Java memory model. Small bug fixes and improvements. More meaningful exceptions and some renamings.
2010, August, 8
Improved the polynomial parser to accept rational numbers denoted with decimal points and to accept BigDecimal coefficients. Removed the use of the underscore for algebraic number coefficients in the polynomial parser. Now every recursive call of parse() from a ring factory is triggered by braces which can be nested to any depth. Fixed synchronization bug in solvable polynomial relation tables and a parallelization bug in parallel solvable polynomial Gröbner base computation. Use of unbounded thread pools to avoid dead-locks. Added remaining parts for the square-free decomposition in polynomial rings of characteristic p > 0. Changed the script representation of AN (AlgebraicNumbers).
2010, July
Downgraded for Java 5 language and run-time system for use with systems relying on older Java versions, for example MathPiper and GeoGebra. New class edu.jas.kern.TimeStatus to provide user feedback for long running tasks via method checkTime(). Implemented some missing extGB() methods. GBFactory for the selection of appropriate Gröbner base implementations. New method isFinite() for all ElemFactorys and usage in SquarefreeFactory. Added some missing parts for the factorization in polynomial rings of characteristic p > 0 and ideal decomposition.
2010, June
Factory for Gröbner base algorithm implementations in class GBFactory. New GBProxy like GCDProxy to run a sequential and a parallel Gröbner base computation concurrently. Primitive element computation via normalPositionFor() in methods primitiveElement() together with several conversion methods convertToPrimitiveElem(). A new index of all algorithms from the book Gröbner bases to their JAS equivalents.
2010, May, 28
Implementation of arbitrary dimensional ideal radical-, irreducible-, prime- and primary-decomposition in class Ideal with methods radicalDecomposition(), decomposition(), primeDecomposition() and primaryDecomposition(). Computation of extension and contraction ideals. Unit tests for the decomposition methods. Fixed a bug in multivariate polynomial factorization in Kronecker's method. Fixed a bug in squarefree decomposition in inseparable case. Added NO_THREADS flag to edu.jas.kern.ComputerThreads to avoid (some) thread creation for usage in Google app engine.
2010, May, 8
Implementation of zero dimensional ideal radical-, prime-, primary- and root-decomposition in class Ideal with methods zeroDimRadicalDecomposition(), zeroDimDecomposition(), zeroDimPrimeDecomposition(), zeroDimPrimaryDecomposition() and zeroDimRootDecomposition(). Exact 0-dim ideal real root computation and approximation in methods PolyUtilApp.realAlgebraicRoots() and decimalApproximation(). Small enhancements to Javadoc comments.
2010, April
Some more documentation for package edu.jas.ufd, simplified and improved the factory classes. Refactorings of parallel Gröbner bases computations for solvable polynomial rings. Improved logging for distributed Gröbner bases and distributed middle-ware.
2010, March
Decimal approximations for real and complex roots based on Newton-Raphson iteration restricted to isolating intervals or rectangles. Small enhancements for partial Gröbner bases. Added some Mersenne primes to PrimeList. Construction of minimal univariate polynomials in zero dimensional ideals. Supersets of complex and real roots of zero dimensional ideals. More unit tests for real and complex roots of univariate polynomials and zero dimensional ideal roots. Minor enhancements and fixes.
2010, February
Gröbner bases for sub-sets of variables in class GroebnerBasePartial. Small enhancements: polynomial recursive coefficient parser and a matrix parser. Book-keeping of all used polynomial variable names. New and improved unit tests.
2010, January
Factorization for polynomials with Complex coefficients via algebraic coefficients in Q(i). New classes ModLong and ModLongRing for faster modular arithmetic. New interfaces Modular and ModularRingFactory implemented also by ModInteger to make both interchangable. Improved factorization and serveral refactorings. Factorization mod p = 2 is now implemented.
2009, December
Added a Git repository and a link to Ohloh code analysis of JAS. Cosmetic, small updates and a simple Java scripting interface. New classes for complex root isolation ComplexRoots, ComplexRootsAbstract, ComplexRootsSturm. The implementation provides an exact infallible method which follows the numeric method of Wilf. It uses Sturm sequences following the Routh-Hurwitz Method to count the number of complex roots within a rectangle in the complex plane.
2009, November
New package for the elementary integration of rational functions developed together with Axel Kramer during the computer algebra seminar 2009. The implementation is based on the book Bronstein: Symbolic Integration I. New adapter (commons-math_adapter.jar) for JAS to the Apache Commons Math library version 2.0 by Axel Kramer. Cosmetic, small updates and a jython example for integration.
2009, September
Improved comprehensive Gröbner bases with explicit classes for several alternative implementations of multiplicative sets. Base class is MultiplicativeSet, in sub-classes polynomials made co-prime in MultiplicativeSetCoPrime, polynomials made co-prime and squarefree in MultiplicativeSetSquarefree and polynomials made irreducible in MultiplicativeSetFactors. New distributed hybrid Gröbner base computation with new class TaggedMesageChannel to handle multiple message types and partners over one socket connection. Improved object serialization in distributed hash table. Adapter updated for JLinAlg version 0.6.
2009, August
New adaptor classes (jlinalg_adapter.jar) to use the linear algebra library JLinAlg from JAS. Improvements in the distributed Gröbner bases algorithms. Minor fixes and improvements.
2009, July
Code and output cosmetic, minor fixes and improvements. New interface ToRational used for BigRational and RealAlgebraicNumber to remove type case distinctions in Interval. clone() removed from Element interface because of compiler changes.
2009, June and July
Improved absolute factorization for splitting fields. Fixes and further improvements. Implemented factorization over inseparable field extensions. Fixed squarefree factorization and added unit test. Refactored squarefree tests to separate classes. Refactored squarefree algorithms to separate classes. Interface is Squarefree, abstract class is SquarefreeAbstract. Other main classes are SquarefreeFieldChar0, SquarefreeFiniteFieldCharP and SquarefreeInfiniteFieldCharP.
2009, June
Improved algebraic and absolute factorization. FactorAlgebraic can now also handle factorizations over multiple algebraic extensions like for example Q(i)(sqrt(2)). Class FactorAbsolute is now also extended by FactorAlgebraic, so that absolute factorizations can be computed over algebraic extensions of Q. Added new containers for absolute factorization results and tests for correct absolute factorizations. More toScript() methods and improvements in Jython script interface. Minor additions and fixes.
2009, May
Improved Jython script interface to handle most of the implemented rings, developed in cooperation with Raphael Jolly. New or improved Python functions ZZ, ZM, QQ, DD, CC, Quat, Oct, PolyRing, AN, RealN, RF, RC, LC, SolvPolyRing and RR, PS, Vec, Mat for the construction of rings and elements. Added generic Complex class and ComplexRing factory. Fixed a programming bug in factorization code.
2009, April
Added factory() method to Element interface to have an uniform way to obtain a corresponing ring object. Improved RealAlgebraicNumber so that it can be used as polynomial coefficients, for example GenPolynomial<RealAlgebricNumber<BigRational>>. Real root isolation can now also be used for polynomials with real algebraic coefficients, for example RealRootsSturm<RealAlgebraicNumber<BigRational>>.
2009, March
Implemented univariate polynomial real root isolation algorithms and real algebraic numbers in package edu.jas.root during CISIS/ECDS 2009. Reached 100.000 lines of Java code.
2009, February
Finished first version of polynomial factorization algorithms. Refactored package names edu.jas.ring to edu.jas.gb and edu.jas.module to edu.jas.gbmod.
2009, January
Switch to version 2.3 with experimental factorization of polynomials. Factorization interface with FactorAbstract class for common codes. Factorization of univariate polynomials with several coefficient rings: modulo primes in class FactorModular, over integers in class FactorInteger, over rational numbers in class FactorRational and over algebraic numbers in class FactorAlgebraic<C> (where C can be ModInteger or BigRational). Multivatiate polynomials are reduced to the univariate polynomials via Kronecker substitution and are therefore not very efficient. Refactorings and fixes.
2008, December
Fixed squarefree part and factor computation for modular coefficients. Fixed polynomial compareTo to be transitive as required by Javas SortedMap implementations. Implemented an adaptor package for Apache Log4j to delegate logging calls to native Java logging.
2008, September
Implemented univariate power series during ADG2008 as RingElem and RingFactory types in package edu.jas.ps in classes UnivPowerSeries and UnivPowerSeriesRing. The implementation follows the "Infinite Streams in Java" paper of D. Gruntz in PPPJ2006.
2008, August, 11
Added jython html documentation generated by epydoc. Added jython module to allow native polynomial expression input.
2008, August, 8
New release 2.2. Implemented interface to use JAS as an meditor engine, see jscl-meditor.
2008, July
Finished implementation of comprehensive Groebner bases via Groebner systems. Object oriented class layout uses Condition and ColoredSystem classes. Conditions consist of an ideal (with lazy Groebner base computation) for the conditions equal to zero and a multiplicative set for the conditions not equal to zero. Non-zero condition polynomials are reduced modulo the ideal of condition zero polynomials. The squarefree part from both condition polynomials is used. It differs from the MAS implementation by Schoenfeld, Pesch and others by the ideal used to store the zero conditions and some more details.
2008, June
Added dimension computation to Ideal. Added term order optimization method to Ideal. Refactored ExpVector for different storage unit implementations of the exponent arrays. Supported storage units are long, int (now the default, as seems to be the fastest), short and byte. The respective classes are ExpVectorLong, ExpVectorInteger, ExpVectorShort and ExpVectorByte.
2008, January and February
Added Groebner bases for polynomial rings over regular rings RGroebnerBaseSeq and RGroebnerBasePseudoSeq. Refactorings and fixes.
2007, November and December
Added von Neuman regular rings as (finite) direct products of rings, Product and RegularRingElem. Added fraction free pseudo reduction and Groebner bases GroebnerBasePseudoSeq. Minor refactorings and fixes.
2007, October
Added Groebner bases in polynomial rings over principal ideal domains and Euclidean domains, so called D- and E-Groebner bases, DGroebnerBaseSeq and EGroebnerBaseSeq. Added test methods for reducibility and refactored sequential Groebner base implementations.
2007, September
Minor refactorings and fixes. Modular rational functions and related conversions.
2007, August, 19
Added term order optimization for polynomial and rational function coefficients.
2007, August, 12
Cleanup of UFD code and subversion exports. Term order optimization also available in jython.
2007, July, 28
Added term order optimization class from old DIP/MAS system. This introduced a dependency on JDK 1.6. Refactored source tree to allow fully functional subversion exports.
2007, July, 12
New global class edu.jas.kern.ComputerThreads to represent a thread pool. To stop JAS, when the pool has been started, it is required to call ComputerThreads.terminate().
2007, July, 11
New preemptive cancellation handling. Introduced class PreemptingException as runtime exception and a global class PreemptStatus to allow or deny preemption cancellation. GenPolynomialRing queries PreemptStatus upon creation. GenPolynomial checks preempt cancellation handling and thread interrupt status on construction. If preemption is requested, it throws PreemptingException. This allows e.g. GCDProxy to ignore the respective sub-task and get the thread free. Removed explicit isInterrupted() checks in edu.jas.ufd package.
2007, July, 10
Refactored generation of (lists of) univariate polynomials from SolvableGroebnerBase* to GenSolvablePolynomialRing and GenPolynomialRing. Implemented generic Power class in edu.jas.structure, refactored power() in subresultant PRS.
2007, July, 9
Added unit tests for distributive law in arith and poly packages. Review of all documentation comments.
2007, July, 8
Added assertions to check for number of polynomial variables in GenPolynomial. In ModInteger and AlgebraicNumber inverse() now throws a NotInvertibleExecption, which extends runtime exception. Fixed some correctness bugs detected by Findbugs.
2007, July, 7
Refactored ModInteger for ModIntegerRing factory. Changed all depending classes. Refactored GenPolynomial.getMap() to return unmodifiable SortedMap. Refactored GenPolynomial.val using methods from jas.ufd package to jas.poly package. ExpVector.getVal() renamed and made package private. Logger variables now also final.
2007, June, 10
Improved InterruptedException handling. Refactored use of edu.ky.parallel package to use edu.jas.util and java.util.concurrent. Refactored project web-site.
2007, April and May
Implementation of greatest common divisor algorithms. Using recursive types. Implemented remainder sequences: primitive, monic, subresultant. Implemented modular methods with chinese remaindering for ModIntegers and evaluation in finite fields to reduce the number of variables. Implemented Hensel lifting: linear and quadratic; mod ideal is still missing. Factory classes to select "best" implementations. Proxy classes to run probable good implementations in parallel, taking the result of the first terminating algorithm. Refactored many classes to fit for the new requirements. New method characteristic() in RingFactory and implementing classes. Changed Quotient (rational function) to use new gcd algorithms. Can compute GBs for polynomials with rational function coefficients.
2006, March
Refactored ring package to separate application package with more application of Groebner bases oriented classes. The ring package could now be renamed to gb package. Cosmetic and documentation improvements, e.g. javadoc package descriptions and type parameter tags, removed all tabs in all java files. Implemented generic Quotient(Ring), Residue(Ring) and Local(Ring).
2006, February, 27
Implemented parallel solvable Groebner base algorithms and tests. New class distributed ThreadPool. Cosmetic and code improvements spotted by eclipse, lint4j and jdepend. Refactored module package to separate vector package with basic linear algebra and list handling classes. Refactored to allow different Groebner base or reduction engines where appropriate. Split Syzygy etc. to an interface and a class. Factored basic linear algebra out of Syzygy etc. Adapted jython files to Jave code refactorings. Reorganized jar files and documentation.
2006, February, 12
Moved old examples to MAS subdirectory and new examples to examples directory. Implemented some right version algorithms using opposite rings. Switched to subversion from cvs. Fixed bugs in new left syzygy algorithm.
2006, January
More documentation and cosmetic. Implementation of an extended Groebner Base algorithm and arbitrary base syzygy computation. GenPolynomialTokenizer enhanced to parse algebraic number and Galois field coefficients. Fixed an error in leftNormalform.
2005, 12, 30
New classes CriticalPair and CriticalPairList replace OrderedPairlist. Reworked GB parallel and distributed versions to better respect sequential version critical pair sequences. Fixed some race conditions in parallel and distributed algorithms.
2005, 12, 28
Refactored all classes to remove static methods. So to use any method at first an appropriate object is required. Also class organization has changed to interfaces, abstract classes and concrete classes, e.g. GroebnerBase, GroebnerBaseAbstract, GroebnerBaseSeq, GroebnerBaseParallel and GroebnerBaseDistributed.
2005, 12, 27
Implemented new Ideal class with some ideal operations like sum, product, intersection and quotient. Added TermOrder extension and contraction.
2005, 11-12
Updated documentation comments.
2005, 7, 24
Updated old Java JDK 1.4 branch. Bugfixes (in twoSidedGB), minor changes and cosmetic.
Updated documentation for new Java JDK 1.5 branch.
2005, 5-7
Working through all classes to introduce type parameters and making all implied modifications.
2005, 5, 5
Switched to Java 1.5. Now using covariant returns for implemented interfaces.
2005, 3, 25-29
Some module algorithms implemented. Activated project web pages.
2005, 3, 12-19
Some Syzygy algorithms implemented. Cosmetic on comments and forked web-log.
2005, 3, 5
For the python languege and interpreter exists also a Java version named jython. This system can directly access Java classes and execute Java methods. Added some jython modules Ring, Ideal, SolvRing and SolvIdeal, to access jas GB algorithms from jython.
2005, 2, 25-28
Penality of commutative GB computed as non-commutative left GB is about 24% for (graded) Katsura 6 to 74% for (graded) Katsura 5. Commutative GB computed as non-commutative twosided GB is about a factor of 4 for (graded) Katsura 5 to a factor of 9 for (graded) Katsura 5. Penality for weighted degree term order compated to graded Term order is not measurable or sometimes better. Fixed error in polynomial getONE() to correct term order. Parser for non-commutative problems with relation tables (but only commutative representations) and RunSGB main routine.
2005, 2, 14-21
New TermOrder with direct generation of Comparators for ExpVector comparisons. Split term orders (elimination orders) and weighted degree orders.
2005, 2, 4-8
New unit test case for TermOrder. Fixed weak point in polynomial getONE() to correct number of variables, e.g. correct exponent vector size. Polynomial constant ONE still has wrong exponent vector size. Deleted many old polynomial classes.

Implemented noncommutative product for solvable polynomials, together with relation tables. SolvableOrderedMapPolynomial extends OrderedMapPolynomial. RatSolvableOrderedMapPolynomial extends SolvableOrderedMapPolynomial. Interface SolvablePolynomial extends Ordered Polynomial. Some more left multiplication methods, left reduction and left Groebner Bases, twosided Groebner Base test and computation. Pairlist class changed to avoid usage of criterion 4 if running for SolvablePolynomials, also criterion4() method itself checks for SolvablePolynomials.

RelationTable timings I, U(sl_3)
run / n 2 3 4 5 6 7 8 9 10 11 12 13 14 15
first 3 13 32 92 128 188 274 420 683 1126 1795 2793 4380 6741
second 0 1 2 3 4 5 6 8 10 13 16 21 27 35

Timings in ms on AMD XP 2800+. Computation of (Y^n) * (X^n) with respect to the relation Y * X = X Y - H. In the first run the relation table is populated with the products Y^i * X^i, i = 2,...,n. In the second run the relations are reused, showing almost no computing time anymore for the products.

RelationTable timings II, U(sl_3)
run / n 2 3 4 5 6 7
first 28 94 303 1234 5185 24647
second 1 12 107 782 4569 23897

Second example shows the computation of ( Xa + Xb + Xc + Ya + Yb + Yc + Ha + Hb )^n in U(sl_3). Since in the relation table only products of two variables are stored, the improvement is minimal (for low n).

2005, 1, 24-31
Removed old deprecated classes. Todo: let DistHashTable implement Map Interface. Reimplemented Reduction.Normalform so that asynchronous update of the polynomial list is possible and respected. In case a new polynomial arrives, the reduction is restarted from the beginning. Continuing with the done work and rereducing so far irreducible terms would be an alternative. Todo: use JDK 1.5 java.util.concurrent with interference free Lists, BlockingQueues.
Distributed computation timings, Katsura 6 (G)
# Threads
CPUs
# JVMs time (sec) #put #remove % total
1, seq 1 160.2 70 327 13.5
1, par 1 157.0 70 327 13.5
2, par 1 82.2 72 329 12.7
1, dist 1 177.2 77 334 11.4
2, dist 2 92.2 90 347 8.6
4, dist 2 56.2 112 369 5.9
8, dist 2 58.9 255 516 1.5
4, dist 4 51.2 117 374 5.5
6, dist 4 43.7 129 386 4.6
8, dist 4 62.9 259 519 1.5

Timings taken on a 16 CPU Intel Xeon SMP computer running at 2.7 GHz and with 32 GB RAM. JVM 1.4.2 started with AggressiveHeap and UseParallelGC.
#JVMs = number of distinct Java virtual machines. #put = number of polynomials put to pair list. #remove = number of pairs removed from pair list, i.e. after application of criterions, but including nulls up to now. % total = per cent of removed pairs from total pairs generated, #remove / ( #put * (#put-1) / 2 ) * 100.

Distributed computation timings, Katsura 7 (G)
# Threads
CPUs
# JVMs time (sec) #put #remove % total
1, dist 1 24726.2 140 781 8.0
2, dist 2 12356.1 165 806 5.9
4, dist 4 6859.3 218 859 3.6
8, dist 4 7465.1 411 1054 1.2
8, dist 8 6412.9 344 986 1.6
8, dist 8 7173.3 399 1041 1.3

Overhead for distributed variant is about 10% in Katsura 6 (G). Distributed 1 means one distributed process is running for the reduction of S-polynomials. There is always a master process handling polynomial input / output, setup and management of distributed workers and handling of the pair list. Communication between master and workers is always via TCP/IP with object serialization, even if running on one computer.

2005, 1, 15-16
Further things to improve in GB algorithms (from tsp): local work queues, i.e. local Pairlists, improve data locality in polynomials and lists, communication using message types, reduce object serialization in DL-broadcast by using MarshalledObjects, reduce communication in Pair send by not sending polynomials but indicies (requires distributed hashtable instead of DL), interleave communication and computation by adding a communication thread in the distributed client.

New classes implementing a distributed hash table to hold the polynomials in distributed GB. Index of polynomials in Pairlist is used as hash key. Communication is now using message types GBTransportMess. Now polynomials are only transported once to each reducer since only polynomial hash indexes are transported. Distributed list is asynchronous and late updated, so some duplicate H-polynomials (head terms) could be (are) produced. Solution by local put to hash table with dummy index? Timings are not dramatically better.

Todo: check reduction algorithm to use later arriving polynomials.

2005, 1, 9-14
Introduced all direct improvements in util classes found so far. (ChannelFactory and others) On parallel computers the following JVM options (1.4.2) must be used:
  -Xms200M -Xmx400M -XX:+AggressiveHeap -XX:+UseParallelGC
Memory must be adjusted with respect to your situation.

Seperated versions with Pair Sequence Respecting Order (PS) and normal versions. PS versions try to keep the order of reduced polynomials added to the ideal base the same as in the sequential version. Normal versions now running OK on parallel computer with the right JVM options. Refactoring with Eclipse (organize imports, static methods).

Parallel computation timings, Katsura examples
# Threads
CPUs
Katsura 6 TO(G)
load*
Katsura 6 TO(G)
empty*
Katsura 7 TO(G)
load*
Katsura 7 TO(G)
empty*
seq 184.5 153.3
1 181.5 4% / 159.7 28418.6
2 118.6 s2.02 / p2.11 / 75.6 p2.06 / 13760.0
4 76.8 s3.79 / p3.95 / 40.4 6256.9 p4.56 / 6225.1
8 43.2 s7.19 / p7.49 / 21.3 3240.7 p8.56/ 3318.8
10 42.5
12 40.5 2288.1 p9.90 / 2868.4
14 31.2
16 51.9 s8.19 / p8.54 / 18.7 5376.4 p12.59 / 2256.1

Timings taken on a 16 CPU Intel Xeon SMP computer running at 2.7 GHz and with 32 GB RAM. JVM 1.4.2 started with AggressiveHeap and UseParallelGC.
*) timing taken with other load on the CPUs. +) timing taken with no other load on the CPUs.
Speedup: s = relative to sequential, p = relative to parallel with one thread / CPU.
Scaling from 8 to 16 CPUs is bad, but also observed on non CA / GB Examples (Java and C/FORTRAN).

2004, 10, 3
Generator for Katsura examples (from POSSO / FRISCO examples). Timings on an AMD Athlon XP 2800 (2086MHz) with log level INFO. Log level WARN would gain 10-20 %.
Timings Katsura examples
N
vars = N+1
TermOrder Seconds TermOrder Seconds
7 G 32044.204 L
6 G 112.641 L
5 G 4.195 L
4 G 0.431 L 11.650
3 G 0.153 L 0.310
2 G 0.031 L 0.032
2004, 9, 20-26
Changed OrderedPairlist to record the sequence of pairs taken from the list. New methods putParallel(), removeParallel() and helper methods. Sequence numbers are generated and reduced polynomials are only put to the pair list if corresponding pair number is in correct (sequential) sequence. The ordered list / queue pairsequence (TreeMap/SortedMap) keeps track of the polynomials not yet put to the pairlist.
Parallelism is possible as long there are pairs to be reduced. But non zero reduced polynomials are only put into the pairlist if the polynomial would be put into the pairlist in the sequential Buchberger algorithm. GroebnerBase algorithms had to be modified to record that a polynomial reduced to zero.
2004, 9, 19
Changed order of Pair inserts for pairs with same LCM of HTs. Added sequence number to each Pair and indicator if Pair did not reduce to zero.
2004, September
Implemented Java server (ExecutableServer) for remote execution of objects implementing the RemoteExecutable interface.

New setup for the distributed computation of GBs: the GB master now sends the client code to some ExecutableSevers based on a maschine file with host and port infos about the distributed environment.

Improved the PolynomialTokenizer so that it can read almost unedited old MAS GB input files: ** exponents and parenthesis around polynomials. Lines starting with # are treated as comments. Comments (* *) and parenthesis within polynomials are still not supported.

Implemented a common driver for GB computations RunGB. Sequential, thread parallel and distributed computation can be selected by command line parameters. The input is taken from a file. The number of threads respectively the number of distributed clients can be specified. For distributed execution the host and port information is taken from a maschines file.

Usage: RunGB [seq|par|dist|cli] <file> #procs [machinefile]

Added methods putCount() and remCount() in OrderedPairlist to count the number of polynomials put and get from the pair data structure.

pairlist put and remove, trinks6
# Threads 1 seq 1 par 2 par 2 par 3 par 4 par 5 par 1 dist 2 dist 3 dist 4 dist 4 dist 4 dist 5 dist
# put 22 22 43 26 28 28 28 22 25 28 37 40 33 27
# remove 25 25 61 30 32 32 41 26 33 42 47 61 54 69

Timings @ 500 MHz on one CPU and one maschine and log4j level INFO are:
ca. 2.5 - 3.5 seconds for sequential GB,
ca. 2.5 - 6 seconds for parallel GB,
ca. 5.5 - 9 seconds plus 5 seconds sync time for distributed GB.
Network shuffling of polynomials seems to account for 3 seconds in this example.

Problem uncovered: the distributed version of GB needs an avarage of 5 seconds to sync with all clients (on one maschine). This is way to much for execution times in the range of 2 to 8 seconds.

Redesign of DistributedList, now using TreeMap to keep the list entries in proper sequence. As key a natural number is used, which is assigned by the server to successive add() requests. The server now also holds a copy of the list by itself. So the retransmission of list elements to late arriving clients is possible. This doubles the space required to store polynomials, but removes initial delays to sync all clients to receive all list elements.
By retransmission the DistributedList synchronization delay during DistributedGB could be removed. However the problem of about 5 seconds delay in startup of DistributedGB still remains. It is not visible where and why this delay occurs.
Further improvements would be the removal of list elements or the clearing of the list. Next steps could be distributed HashMap or TreeMap.
An important improvement would be to keep serialized copies of the list elements (polynomials) at the server and to avoid many time serialization during broadcast.

2004, 2, 26
Ideas to implement: a distributed task launcher like mpirun, a daemon to run on a distributed system to work with the launcher, solvable polynomials and non-commutative GBs.
2004, 2, 1
Parallel computations with the Rose example are at ?? h with 3 threads on 2 Pentium 4 @ 3.0 GHz hyperthreading CPUs.

With one thread the time is 30.6 h. Besides the better CPU speed, this makes a 5 % improvement on JDK 1.4 compared to the older timings from a JDK 1.3 and the new polynomial implementation.

2004, 1, 25
Spin model checker: Setup Promella description of parallel and distributed GB algorithm. Used to verify the safety and liveness properties of the algorithms.
2004, 1, 17
New (minimal) class DistributedList in preparation of a distributed GB algorithm. Made all mutually transported objects Serializable. Fixed ChannelFactory and other classes in edu.unima.ky.parallel to be interuptable. Moved Semaphore back to edu.unima.ky.parallel. First version of a distributed memory GB. One problem was inner class Pair results in serialization of outer class OrderedPairlist, which is not intented. So Pair is now a proper class. Distributed version mainly working. Problem with signaling and termination if 1 in GB.
2004, 1, 10
Refactored Groebner base for new OrderedPolynomials and split sequential and parallel GB implementations. New unit tests for sequential and parallel GBs. GB now works for arbitrary Coefficients.
2004, 1, 5
New coefficient domains BigComplex and BigQuaternion. New test unit for all coefficients. Based on these coefficients are new polynomials, e.g. ComplexOrderedMapPolynomial and QuatOrderedMapPolynomial together with unit tests. Problem: RatPolynomial requires DEFAULT_EVORD be set correctly in ExpVector. This is now solved for the new OrderedMapPolynomials.
2003, 12, 29
New organization of polynomials:
2 interfaces: UnorderedPolynomial and OrderedPolynomial. Ordered polynomials have a term order and are implemented using some SortedMap (e.g. TreeMap). Unodered polynomials are implemented using some HashMap (e.g. LinkedHashMap).
2 abstract classes: UnorderedMapPolynomial and OrderedMapPolynomial. Both implement all algorithms which do not need an explicit coeficient domain, i.e. they are formulated in terms of the Coefficient interface from jas.arith.
2 or more classes which extend the respective abstract classes: RatUnorderedMapPolynomial and RatOrderedMapPolynomial both need explicitly coefficients from BigRational or others.

Multiplication with ordered polynomials is about 8-10 times faster than the multiplication with unordered polynomials. Also the multiplication with semi-ordered polynomials (LinkedHashMap) with orderpreserving addition is about 7-8 times slower than multiplication with ordered polynomials.

All implementations are based on Map interface and classes. The Map maps exponent vectors (from some monoid) to coefficients (from some domain). This is in sync with the mathematical definition of multivariate polynomials as mappings from some monoid to some domain. Term orders are represented by a TermOrder class which provides the desired Comparator classes for the SortedMap implementation.

2003, 12, 28
Things to do: refactor and test HashPolynomial, check performance. Improve the parallel GB algorithm, e.g. parallelize the reduction algorithm. Develop a distributed memory version of the parallel GB algorithm.
2003, 12, 27
Using ArgoUML to produce class diagramms for jas. Refactoring GB from edu.jas.poly to edu.jas.ring.
2003, 12, 21
Setup for JUnit version 3.8.1. Added JUnit testing with Apache Ant version 1.6.0 to build.xml.
2003, September
Experimented with LinkedHashMap instead of TreeMap (SortedMap) for the representation of polynomials. Algorithms which work also with LinkedHashMap have 1 or 2 in their names (now in new class HashPolynomial). LinkedHashMap has the property of using the insertion order for the iterator order. With LinkedHashMap the add() and subtract() can be reformulated to use a merging algorithm as in the original DIP implementation. Assuming the Map insertion order is the the same as the polynomial term order.

However the merging add/subtact implementation is a factor of 2 slower than the TreeMap implementation. Complexity for a+b is
2*(length(a)+length(b)) for access and merging pre sorted polynomials and
2*length(a)+length(b)+length(b)*log2(length(a+b)) for TreeMap clone, access and insertion.

The merging multiplication implementation is by a factor of 10 slower than the TreeMap implementation. Polynomial size was ~100 terms and the product contained ~8000 terms. Complexity for a*b is
lab = length(a)*length(b) coefficient multiplications for both implementations
plus 2*length(a*b)*length(b) for merging summands, respectively
plus length(a)*length(b)*log2(length(a*b)) for TreeMap insertion. Since for sparse polynomials length(a*b) = lab, the TreeMap complexity is asymptotically better in this case:
2*length(a)*length(b)*length(b) =>= length(a)*length(b)*log2(length(a*b))
For dense polynomials with length(a*b) ~ length(a)[+length(b)], then the LinkedHashMap complexity is asymptotically better:
2*length(a)*length(b) =<= length(a)*length(b)*log2(length(a*b))

2003, 3, 15
Some testing with new AMD Athlon XP 2200+ @ 1.8 GHz, 133x2 MHz memory access.
Trinks 6: 1.013 sec with log4j level WARN, parallel 1.058 - 1.740 sec.
Trinks 7: 0.553 sec with log4j level WARN.
2003, 2, 2
Replacing all System.out.println by Log4j logging calls. adding some Junit tests.
2003, 1, 28
Some testing with gcj (Gnu Java Compiler). this compiler gernerates native executable binaries. the timings are not better than with a jit, often worser.

Parallel computations with the Rose example are at 18 h with 4 threads on 2 Pentium 4 @ 2.4 GHz hyperthreading CPUs. With one thread the time is 40 h.

2003, 1, 26
timings with JDK 1.3 (from IBM) are 30% to 40% faster than with JDK 1.4.1 (from Sun). timings on PowerPC 604 @ 200MHz JDK 1.3 (from IBM) JDK 1.2 (from Sun) are a factor 3.5-4.5 slower than on Intel PIII @ 450 MHz. on PowerPC not using jit is faster than using a jit, ca. 20% - 30%.
2003, 1, 12
General differences between sequential and parallel GB algorithms
  • The parallelization is achieved by doing the normal form reductions in parallel.
  • Since the reductions may require different times to complete the normal forms may be entered into the list of polynomials in different (time) order than in the sequential case. So the pairs may be generated in different order. However since the list of pairs is ordered wrt. the lcm of the head terms this seems not to be a big issue.
  • Since several reductions are scheduled in parallel the pairs are taken from the list of pairs in different order than in the sequential case. One should not take more pairs from the list than can be reduced in parallel.

Does this influence the validity of criterion 3? Access to pairlist is synchronized. Pairs are marked as reduced as soon they are taken from the list. But the algorithm terminates only after all reductions of pairs have terminated. So criterion 3 holds.

New implementation of parallel version of GB. Removal of pairs is now also in parallel. But ordering of pair insertion is no more preserved

Timings are more stable and slightly better than that of sequential GB.

Todo: unit tests, comments, ...

2003, 1, 7-11
Renamed jas to mas2jas, new cvs repository for jas, import and checkout.

Improved parallel version of GB.

  • The sequence of polynomials added to the pair list is kept stable. i.e. a pair scheduled for reduction at time t will (if non zero) enter the list before any pair scheduled at time t+x.
  • This limits the parallelism since polynomials which reduce to zero keep a reducer thread occupied until older polynomials are finally reduced. One could eventualy hand over the blocking object to the next thread.
  • The number of pairs scheduled for reduction is now also limited to the number of parallel reduction threads. this avoids that to many pairs with high lcm will be scheduled before eventually new created pairs with lower lcm.
  • The limiting of scheduled pairs could also be implemented using a BoundedBuffer/Queue for the ThreadPool workpile. then addJob() would block until free Threads are avalilable.
  • The sequencing and limiting could eventually also achieved when the reducing threads take the pairs by themselves instead of the master thread. The main thread should then simply wait until all threads are idle.
  • The final reduction of the GB to a minimal GB is now also parallelized.

Todo: CVS, comments, polynomial implementation using LinkedList, parallel GB simplify

With the improved algorithm the running time of the parallel GB becomes more stable and not slower than the sequential GB. However there is still no significant speedup.

parallel GB on one cpu
# Threads 1 2 3 4 5 6 7 8 16
# Reductions 25 25 27 25 25 25 25 25 25

parallel GB on 4 cpus
# Threads 1 2 3 4 5 6 7 8 16
# Reductions 22 24 30, 28, 24, 29 28 29 42 32 32 37

2003, 1, 6
implemented parallel version of GB using ThreadPool from tnj

parallel results:
Trinks 7: mas 0.598 sec, jas 0.918 sec, jas par 0.955 sec
Trinks 6: mas 26.935 sec, jas 3.211 sec, jas par 3.656 sec
mas: including startup and gc time, jas: excluding startup of jvm and including gc time, jas par on single processor timing on P-3@450

this make for a penality of 12 percent, all tests with output to files,
2003, 1, 5
timing benchmarks between BigRational and Coefficient versions of the algorithms, the difference seems to be less than 1 percent with no clear advantage of one side
the sum and product algorithms have not jet optimal complexity, sum has 2 l log(l) instead of 2 l because of TreeMap.remove() and because of TreeMap.put(), prod has l^2 log(l^2/2) instead of l^2 because of TreeMap.put()
TreeMap cannot used for this, some kind of SortedLinkedList or SortedHashMap would be required, the last would in turn require a hashValue() of an ExpVector

implemented edu.jas.arith.BigInteger which implements Coefficient, tested with IntPolynomial which extends Polynomial

todo: alternative Implementations, cleanup RatPolynomial, parallel GB, conversion RatPolynomial <--> IntPolynomial
2003, 1, 4
added reading of PolynomialLists and Variable Lists to PolynomialTokenizer, implemented PolynomialList
refactoring RatPolynomial to extend Polynomial, implementing IntPolynomial extends Polynomial
to make BigInteger implement Coefficient will require a delegation extension of BigInteger
2003, 1, 3
implemented PolynomialTokenizer to read RatPolynomials
2003, 1, 2
file RatPolynomial split into RatGBase, criterion 3 implemented with BitSet

second results (with new criterion 3 in jas):
Trinks 7: mas 0.598 sec, jas 1.159 sec
Trinks 6: mas 26.935 sec, jas 6.468 sec
mas: including startup and gc time, jas: excluding startup of jvm and including gc time

implemented DIGBMI, H-polynomal was not monic in DIRPGB

third results (with new criterion 3 in jas and GBminimal):
Trinks 7: mas 0.598 sec, jas 0.918 sec
Trinks 6: mas 26.935 sec, jas 3.211 sec
mas: including startup and gc time, jas: excluding startup of jvm and including gc time timing on P-3@450

this makes for a factor of 8-9 better, all tests with output to files, startup of JVM is approx. 1.0-1.2 sec, most time is spent in BigInteger:

java -Xrunhprof:cpu=times,format=a

CPU TIME (ms) BEGIN (total = 136) Thu Jan  2 18:33:53 2003
rank   self  accum   count trace method
   1 15,44% 15,44%  596610    21 java.math.MutableBigInteger.rightShift
   2 13,24% 28,68%  582132    15 java.math.MutableBigInteger.difference
   3 12,50% 41,18%  612760    19 java.math.MutableBigInteger.getLowestSetBit
   4  9,56% 50,74%       2     9 java.lang.Object.wait
   5  9,56% 60,29%    5271    22 java.math.MutableBigInteger.binaryGCD
   6  6,62% 66,91%  612760    23 java.math.BigInteger.trailingZeroCnt
   7  5,88% 72,79%  592152    18 java.math.BigInteger.bitLen
   8  5,88% 78,68%    6018    20 java.math.MutableBigInteger.binaryGCD
   9  5,15% 83,82%  578887    25 java.math.MutableBigInteger.normalize
  10  4,41% 88,24%  550992    24 java.math.MutableBigInteger.primitiveRightShift
  11  4,41% 92,65%       1    10 java.lang.Object.wait
  12  3,68% 96,32%  582132    12 java.math.MutableBigInteger.compare
  13  0,74% 97,06%   35965    13 edu.jas.poly.ExpVector.EVILCP
  14  0,74% 97,79%   11612    14 java.math.BigInteger.divide
  15  0,74% 98,53%    5866    11 java.math.MutableBigInteger.divide
  16  0,74% 99,26%    9032    16 java.math.MutableBigInteger.divide
  17  0,74% 100,00%   9032    17 java.math.BigInteger.divide
CPU TIME (ms) END
2003, 1, 1
renaming packages to edu.jas, renaming to arith, poly and ring, new Makefile, project dokumentation in XHTML, using JDK 1.4 with JIT

first results (without criterion 3 in jas):
Trinks 7: mas 0.598 sec, jas 1.373 sec
Trinks 6: mas 26.935 sec, jas 30.935 sec
mas: including startup and gc time, jas: excluding startup of jvm and including gc time. timing on P-3@450

2002, 12, 31
starting with extraction of relevant files in new directory
2000, 7, 21
keySet/get replaced by entrySet/getval.
Implemented S-Polynomial, normal form, irreducible set. Implemented Groebner base with criterion 4. Criterion 3 left to to.
2000, 7, 16
Implemented and tested BigRational based on Javas BigInteger.
With and without I/O BigRational addition, multiplication and comparison is approx. 10 times faster than respective SACRN functions.

Implemented and testet ExpVector based on Javas int arrays.

Implemented and testet RatPolynomial based on Javas TreeMap.
static methods: DIRPDF, DIRPWR via toString, DIRPON, DIRPMC, DIRPPR, DIRPSM, DIRRAS.
Consider replacing keySet/get by entrySet/getval where appropriate. Can there be an generic Polynomial class?

2000, 7, 15
Some testing with Javas builtin BigInteger class.
Without I/O builtin multiplication is approx. 15 times faster than SAC product.
With much I/O builtin multiplication is approx. 3 times faster than SAC product.
Builtin uses also twos-complement representation, which is bad for decimal printing.

This will be the end of list processing for Jas.

DIPRNGB needs DIRPDF, DIRPWR, DIRPON, DIRPMC, DIRPPR, DIRPSM.
These need RNDIF, RNDWR, RNINT, RNSIGN, ISRNONE, RNONE, RNZERO, RNINV (and DIRPRP), RNPROD, RNSUM.

2000, 7, 14
Class BigInteger based on SACI with toString().
Class List based on MASSTOR with toString().
Problem with Modula-2 module initialization with main(args) method: initialization of static variables.
2000, 7, 5
Finished testing most of masarith.
2000, 7, 2
Finished porting masarith. Testing needs still to be done. MASAPF is ok.
2000, 6, 24
Perl script getc.pl to grab comments in Modula-2 source and add to Java source. Comments grabbed on most working files so far. Generated new documentation.
2000, 6, 22
Future directions:
  • Parallel GB.
  • Move to Java without Modula-2.
  • Develop an applet version.
  • Implement more of Mas.
  • Replace SACI by Java BigInteger.
  • Setup for real objects:
    implement constructor,
    implement methods: a.method(b) as STATIC_METHOD(a,b),
    use real objects instead of only Cell objects
    define interfaces e.g. for ring, polynomial ring, module, group, field
  • Small additions:
    toString equivalents of xWRITEs
Problems identified:
  • LISTs over Beta-Integers are diffrent to LISTs over LISTs, when implementing LISTs as Java Types LISTs over other types will require also special handling.
2000, 6, 22
GB running on Trinks (small and big). Jas ist about 5-8 times slower than MAS in GB computation. Using JDK 1.1.7 without JIT on Linux, PII-300. Using JDK 1.2.2-RC3 without JIT on Linux, PII-300 is about 6-9 times slower. Using JDK 1.2.2-RC4 with JIT (sunwjit) on Linux, PII-300 is about 2-4 times slower. Implemented Java input via BufferedReader.
2000, 6, 21
Got GB running. Problem was in EQUAL.
2000, 6, 17
Placed under control of CVS. Begining with a clean version from Uni Passau. Incorporated Java specific changes up to now.
2000, 6, 10
Transformation of DIPRNGB finished. Important parts of maspoly finished.
2000, 6, 4
Transformation of SACPRIM finished. Most of maskern finished. Important parts of masarith finished.
2000, 5, 29
MASSTOR: Mapping MAS list direkt to a Java list class and using of the garbage collector from Java. Data types LIST and GAMMAINT are now distinct. Buying the MHC Compiler (UK Pound 59).
2000, 5, 28
MASSTOR: First attempt to use list class with own garbage collection. Using the constructor to record list pointers.
2000, 5, 27:
Beginning of the first tests. Conversion of .md to .def, .mi to .mod.
2000, 5, 26:
Discovery of the MHC Modula-2 to Java compiler. Mill Hill & Canterbury Corporation, Ltd, URL http://www.mhccorp.com

Done bevore 2003

  • JUnit checker for every class.
  • Switching to Java and abandoning Modula-2.
  • Removal of the mas prefix in directory names.
  • Improved Makefiles.

Heinz Kredel

Last modified: Mon Apr 29 20:46:06 CEST 2013

jas-2.5/COPYING.lgpl0000644000175000017500000006350010376071250014340 0ustar giovannigiovanni GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! jas-2.5/src/0000755000175000017500000000000012140140254013123 5ustar giovannigiovannijas-2.5/src/edu/0000755000175000017500000000000012140140260013675 5ustar giovannigiovannijas-2.5/src/edu/jas/0000755000175000017500000000000012140140260014452 5ustar giovannigiovannijas-2.5/src/edu/jas/root/0000755000175000017500000000000012140140260015435 5ustar giovannigiovannijas-2.5/src/edu/jas/root/ComplexRoots.java0000644000175000017500000000417112000264162020744 0ustar giovannigiovanni/* * $Id: ComplexRoots.java 3989 2012-07-14 12:39:14Z kredel $ */ package edu.jas.root; import java.io.Serializable; import java.util.List; import edu.jas.arith.Rational; import edu.jas.arith.BigRational; import edu.jas.poly.Complex; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.structure.GcdRingElem; /** * Complex roots interface. * @param coefficient type. * @author Heinz Kredel */ public interface ComplexRoots & Rational> extends Serializable { /** * Root bound. With f(-M + i M) * f(-M - i M) * f(M - i M) * f(M + i M) != 0. * @param f univariate polynomial. * @return M such that root(f) is contained in the rectangle spanned by M. */ public Complex rootBound(GenPolynomial> f); /** * Complex root count of complex polynomial on rectangle. * @param rect rectangle. * @param a univariate complex polynomial. * @return root count of a in rectangle. */ public long complexRootCount(Rectangle rect, GenPolynomial> a) throws InvalidBoundaryException; /** * List of complex roots of complex polynomial a on rectangle. * @param rect rectangle. * @param a univariate squarefree complex polynomial. * @return list of complex roots. */ public List> complexRoots(Rectangle rect, GenPolynomial> a) throws InvalidBoundaryException; /** * List of complex roots of complex polynomial. * @param a univariate complex polynomial. * @return list of complex roots. */ public List> complexRoots(GenPolynomial> a); /** * Complex root refinement of complex polynomial a on rectangle. * @param rect rectangle containing exactly one complex root. * @param a univariate squarefree complex polynomial. * @param len rational length for refinement. * @return refined complex root. */ public Rectangle complexRootRefinement(Rectangle rect, GenPolynomial> a, BigRational len) throws InvalidBoundaryException; } jas-2.5/src/edu/jas/root/ComplexRootsAbstract.java0000644000175000017500000007310312013672444022443 0ustar giovannigiovanni/* * $Id: ComplexRootsAbstract.java 4108 2012-08-18 10:57:40Z kredel $ */ package edu.jas.root; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; import org.apache.log4j.Logger; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.UnaryFunctor; import edu.jas.ufd.Squarefree; import edu.jas.ufd.SquarefreeFactory; /** * Complex roots abstract class. * @param coefficient type. * @author Heinz Kredel */ public abstract class ComplexRootsAbstract & Rational> implements ComplexRoots { private static final Logger logger = Logger.getLogger(ComplexRootsAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Engine for square free decomposition. */ public final Squarefree> engine; /** * Constructor. * @param cf coefficient factory. */ public ComplexRootsAbstract(RingFactory> cf) { if (!(cf instanceof ComplexRing)) { throw new IllegalArgumentException("cf not supported coefficients " + cf); } engine = SquarefreeFactory.> getImplementation(cf); } /** * Root bound. With f(-M + i M) * f(-M - i M) * f(M - i M) * f(M + i M) != * 0. * @param f univariate polynomial. * @return M such that root(f) is contained in the rectangle spanned by M. */ public Complex rootBound(GenPolynomial> f) { if (f == null) { return null; } RingFactory> cfac = f.ring.coFac; Complex M = cfac.getONE(); if (f.isZERO() || f.isConstant()) { return M; } Complex a = f.leadingBaseCoefficient().norm(); for (Complex c : f.getMap().values()) { Complex d = c.norm().divide(a); if (M.compareTo(d) < 0) { M = d; } } M = M.sum(cfac.getONE()); //System.out.println("M = " + M); return M; } /** * Magnitude bound. * @param rect rectangle. * @param f univariate polynomial. * @return B such that |f(c)| < B for c in rect. */ public C magnitudeBound(Rectangle rect, GenPolynomial> f) { if (f == null) { return null; } if (f.isZERO()) { return f.ring.coFac.getONE().getRe(); } //System.out.println("f = " + f); if (f.isConstant()) { Complex c = f.leadingBaseCoefficient(); return c.norm().getRe(); } GenPolynomial> fa = f.map(new UnaryFunctor, Complex>() { public Complex eval(Complex a) { return a.norm(); } }); //System.out.println("fa = " + fa); Complex Mc = rect.getNW().norm(); C M = Mc.getRe(); //System.out.println("M = " + M); Complex M1c = rect.getSW().norm(); C M1 = M1c.getRe(); if (M.compareTo(M1) < 0) { M = M1; Mc = M1c; } M1c = rect.getSE().norm(); M1 = M1c.getRe(); if (M.compareTo(M1) < 0) { M = M1; Mc = M1c; } M1c = rect.getNE().norm(); M1 = M1c.getRe(); if (M.compareTo(M1) < 0) { //M = M1; Mc = M1c; } //System.out.println("M = " + M); Complex B = PolyUtil.> evaluateMain(f.ring.coFac, fa, Mc); //System.out.println("B = " + B); return B.getRe(); } /** * Complex root count of complex polynomial on rectangle. * @param rect rectangle. * @param a univariate complex polynomial. * @return root count of a in rectangle. */ public abstract long complexRootCount(Rectangle rect, GenPolynomial> a) throws InvalidBoundaryException; /** * List of complex roots of complex polynomial a on rectangle. * @param rect rectangle. * @param a univariate squarefree complex polynomial. * @return list of complex roots. */ public abstract List> complexRoots(Rectangle rect, GenPolynomial> a) throws InvalidBoundaryException; /** * List of complex roots of complex polynomial. * @param a univariate complex polynomial. * @return list of complex roots. */ @SuppressWarnings("unchecked") public List> complexRoots(GenPolynomial> a) { List> roots = new ArrayList>(); if (a.isConstant() || a.isZERO()) { return roots; } ComplexRing cr = (ComplexRing) a.ring.coFac; SortedMap>, Long> sa = engine.squarefreeFactors(a); for (Map.Entry>, Long> me : sa.entrySet()) { GenPolynomial> p = me.getKey(); Complex Mb = rootBound(p); C M = Mb.getRe(); C M1 = M.sum(M.factory().fromInteger(1)); // asymmetric to origin //System.out.println("M = " + M); if (debug) { logger.info("rootBound = " + M); } Complex[] corner = (Complex[]) new Complex[4]; corner[0] = new Complex(cr, M1.negate(), M); // nw corner[1] = new Complex(cr, M1.negate(), M1.negate()); // sw corner[2] = new Complex(cr, M, M1.negate()); // se corner[3] = new Complex(cr, M, M); // ne Rectangle rect = new Rectangle(corner); try { List> rs = complexRoots(rect, p); long e = me.getValue(); // sa.get(p); for (int i = 0; i < e; i++) { // add with multiplicity roots.addAll(rs); } } catch (InvalidBoundaryException e) { //logger.error("invalid boundary for p = " + p); throw new RuntimeException("this should never happen " + e); } } return roots; } /** * Complex root refinement of complex polynomial a on rectangle. * @param rect rectangle containing exactly one complex root. * @param a univariate squarefree complex polynomial. * @param len rational length for refinement. * @return refined complex root. */ public Rectangle complexRootRefinement(Rectangle rect, GenPolynomial> a, BigRational len) throws InvalidBoundaryException { ComplexRing cr = (ComplexRing) a.ring.coFac; Rectangle root = rect; long w; if (debug) { w = complexRootCount(root, a); if (w != 1) { System.out.println("#root = " + w); System.out.println("root = " + root); throw new ArithmeticException("no initial isolating rectangle " + rect); } } Complex eps = cr.fromInteger(1); eps = eps.divide(cr.fromInteger(1000)); // 1/1000 BigRational length = len.multiply(len); Complex delta = null; boolean work = true; while (work) { try { while (root.rationalLength().compareTo(length) > 0) { //System.out.println("root = " + root + ", len = " + new BigDecimal(root.rationalLength())); if (delta == null) { delta = root.corners[3].subtract(root.corners[1]); delta = delta.divide(cr.fromInteger(2)); //System.out.println("delta = " + toDecimal(delta)); } Complex center = root.corners[1].sum(delta); //System.out.println("refine center = " + toDecimal(center)); if (debug) { logger.info("new center = " + center); } Complex[] cp = (Complex[]) copyOfComplex(root.corners, 4); // cp[0] fix cp[1] = new Complex(cr, cp[1].getRe(), center.getIm()); cp[2] = center; cp[3] = new Complex(cr, center.getRe(), cp[3].getIm()); Rectangle nw = new Rectangle(cp); w = complexRootCount(nw, a); if (w == 1) { root = nw; delta = null; continue; } cp = (Complex[]) copyOfComplex(root.corners, 4); cp[0] = new Complex(cr, cp[0].getRe(), center.getIm()); // cp[1] fix cp[2] = new Complex(cr, center.getRe(), cp[2].getIm()); cp[3] = center; Rectangle sw = new Rectangle(cp); w = complexRootCount(sw, a); //System.out.println("#swr = " + w); if (w == 1) { root = sw; delta = null; continue; } cp = (Complex[]) copyOfComplex(root.corners, 4); cp[0] = center; cp[1] = new Complex(cr, center.getRe(), cp[1].getIm()); // cp[2] fix cp[3] = new Complex(cr, cp[3].getRe(), center.getIm()); Rectangle se = new Rectangle(cp); w = complexRootCount(se, a); //System.out.println("#ser = " + w); if (w == 1) { root = se; delta = null; continue; } cp = (Complex[]) copyOfComplex(root.corners, 4); cp[0] = new Complex(cr, center.getRe(), cp[0].getIm()); cp[1] = center; cp[2] = new Complex(cr, cp[2].getRe(), center.getIm()); // cp[3] fix Rectangle ne = new Rectangle(cp); w = complexRootCount(ne, a); //System.out.println("#ner = " + w); if (w == 1) { root = ne; delta = null; continue; } if (true) { w = complexRootCount(root, a); System.out.println("#root = " + w); System.out.println("root = " + root); } throw new ArithmeticException("no isolating rectangle " + rect); } work = false; } catch (InvalidBoundaryException e) { // repeat with new center delta = delta.sum(delta.multiply(eps)); // distort //System.out.println("new refine delta = " + toDecimal(delta)); eps = eps.sum(eps.multiply(cr.getIMAG())); } } return root; } /** * List of complex roots of complex polynomial. * @param a univariate complex polynomial. * @param len rational length for refinement. * @return list of complex roots to desired precision. */ @SuppressWarnings("unchecked") public List> complexRoots(GenPolynomial> a, BigRational len) { ComplexRing cr = (ComplexRing) a.ring.coFac; SortedMap>, Long> sa = engine.squarefreeFactors(a); List> roots = new ArrayList>(); for (Map.Entry>, Long> me : sa.entrySet()) { GenPolynomial> p = me.getKey(); Complex Mb = rootBound(p); C M = Mb.getRe(); C M1 = M.sum(M.factory().fromInteger(1)); // asymmetric to origin if (debug) { logger.info("rootBound = " + M); } Complex[] corner = (Complex[]) new Complex[4]; corner[0] = new Complex(cr, M1.negate(), M); // nw corner[1] = new Complex(cr, M1.negate(), M1.negate()); // sw corner[2] = new Complex(cr, M, M1.negate()); // se corner[3] = new Complex(cr, M, M); // ne Rectangle rect = new Rectangle(corner); try { List> rs = complexRoots(rect, p); List> rf = new ArrayList>(rs.size()); for (Rectangle r : rs) { Rectangle rr = complexRootRefinement(r, p, len); rf.add(rr); } long e = me.getValue(); // sa.get(p); for (int i = 0; i < e; i++) { // add with multiplicity roots.addAll(rf); } } catch (InvalidBoundaryException e) { throw new RuntimeException("this should never happen " + e); } } return roots; } /** * Invariant rectangle for algebraic number. * @param rect root isolating rectangle for f which contains exactly one * root. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @return v with v a new rectangle contained in iv such that g(w) != 0 for * w in v. */ public abstract Rectangle invariantRectangle(Rectangle rect, GenPolynomial> f, GenPolynomial> g) throws InvalidBoundaryException; /** * Get decimal approximation. * @param a complex number. * @return decimal(a). */ public String toDecimal(Complex a) { C r = a.getRe(); String s = r.toString(); BigRational rs = new BigRational(s); BigDecimal rd = new BigDecimal(rs); C i = a.getIm(); s = i.toString(); BigRational is = new BigRational(s); BigDecimal id = new BigDecimal(is); //System.out.println("rd = " + rd); //System.out.println("id = " + id); return rd.toString() + " i " + id.toString(); } /** * Approximate complex root. * @param rt root isolating rectangle. * @param f univariate polynomial, non-zero. * @param eps requested interval length. * @return a decimal approximation d such that |d-v| < eps, for f(v) = 0, * v in rt. */ public Complex approximateRoot(Rectangle rt, GenPolynomial> f, C eps) throws NoConvergenceException { if (rt == null) { throw new IllegalArgumentException("null interval not allowed"); } Complex d = rt.getDecimalCenter(); //System.out.println("d = " + d); if (f == null || f.isZERO() || f.isConstant() || eps == null) { return d; } if (rt.length().compareTo(eps) < 0) { return d; } ComplexRing cr = d.ring; Complex sw = rt.getSW(); BigDecimal swr = new BigDecimal(sw.getRe().getRational()); BigDecimal swi = new BigDecimal(sw.getIm().getRational()); Complex ll = new Complex(cr, swr, swi); Complex ne = rt.getNE(); BigDecimal ner = new BigDecimal(ne.getRe().getRational()); BigDecimal nei = new BigDecimal(ne.getIm().getRational()); Complex ur = new Complex(cr, ner, nei); BigDecimal e = new BigDecimal(eps.getRational()); Complex q = new Complex(cr, new BigDecimal("0.25")); e = e.multiply(d.norm().getRe()); // relative error //System.out.println("e = " + e); // polynomials with decimal coefficients GenPolynomialRing> dfac = new GenPolynomialRing>(cr, f.ring); GenPolynomial> df = PolyUtil. complexDecimalFromRational(dfac, f); GenPolynomial> fp = PolyUtil.> baseDeriviative(f); GenPolynomial> dfp = PolyUtil. complexDecimalFromRational(dfac, fp); // Newton Raphson iteration: x_{n+1} = x_n - f(x_n)/f'(x_n) int i = 0; final int MITER = 50; int dir = -1; while (i++ < MITER) { Complex fx = PolyUtil.> evaluateMain(cr, df, d); // f(d) //BigDecimal fs = fx.norm().getRe(); //System.out.println("fs = " + fs); if (fx.isZERO()) { return d; } Complex fpx = PolyUtil.> evaluateMain(cr, dfp, d); // f'(d) if (fpx.isZERO()) { throw new NoConvergenceException("zero deriviative should not happen"); } Complex x = fx.divide(fpx); Complex dx = d.subtract(x); //System.out.println("dx = " + dx); if (d.subtract(dx).norm().getRe().compareTo(e) <= 0) { return dx; } // if ( false ) { // not useful: // Complex fxx = PolyUtil.> evaluateMain(cr, df, dx); // f(dx) // //System.out.println("fxx = " + fxx); // BigDecimal fsx = fxx.norm().getRe(); // System.out.println("fsx = " + fsx); // while ( fsx.compareTo( fs ) >= 0 ) { // System.out.println("trying to increase f(d) "); // if ( i++ > MITER ) { // dx > right: dx - right > 0 // throw new NoConvergenceException("no convergence after " + i + " steps"); // } // x = x.multiply(q); // x * 1/4 // dx = d.subtract(x); // //System.out.println(" x = " + x); // System.out.println("dx = " + dx); // fxx = PolyUtil.> evaluateMain(cr, df, dx); // f(dx) // //System.out.println("fxx = " + fxx); // fsx = fxx.norm().getRe(); // System.out.println("fsx = " + fsx); // } // } // check interval bounds while (dx.getRe().compareTo(ll.getRe()) < 0 || dx.getIm().compareTo(ll.getIm()) < 0 || dx.getRe().compareTo(ur.getRe()) > 0 || dx.getIm().compareTo(ur.getIm()) > 0) { // dx < ll: dx - ll < 0 // dx > ur: dx - ur > 0 if (i++ > MITER) { // dx > right: dx - right > 0 throw new NoConvergenceException("no convergence after " + i + " steps"); } if (i > MITER / 2 && dir == 0) { Complex cc = rt.getCenter(); Rectangle nrt = rt.exchangeSE(cc); Complex sd = nrt.getDecimalCenter(); d = sd; x = cr.getZERO(); logger.info("trying new SE starting point " + d); i = 0; dir = 1; } if (i > MITER / 2 && dir == 1) { Complex cc = rt.getCenter(); Rectangle nrt = rt.exchangeNW(cc); Complex sd = nrt.getDecimalCenter(); d = sd; x = cr.getZERO(); logger.info("trying new NW starting point " + d); i = 0; dir = 2; } if (i > MITER / 2 && dir == 2) { Complex cc = rt.getCenter(); Rectangle nrt = rt.exchangeSW(cc); Complex sd = nrt.getDecimalCenter(); d = sd; x = cr.getZERO(); logger.info("trying new SW starting point " + d); i = 0; dir = 3; } if (i > MITER / 2 && dir == 3) { Complex cc = rt.getCenter(); Rectangle nrt = rt.exchangeNE(cc); Complex sd = nrt.getDecimalCenter(); d = sd; x = cr.getZERO(); logger.info("trying new NE starting point " + d); i = 0; dir = 4; } if (i > MITER / 2 && (dir == -1 || dir == 4 || dir == 5)) { Complex sr = rt.randomPoint(); BigDecimal srr = new BigDecimal(sr.getRe().getRational()); BigDecimal sri = new BigDecimal(sr.getIm().getRational()); Complex sd = new Complex(cr, srr, sri); d = sd; x = cr.getZERO(); logger.info("trying new random starting point " + d); if (dir == -1) { i = 0; dir = 0; } else if (dir == 4) { i = 0; dir = 5; } else { //i = 0; dir = 6; // end } } x = x.multiply(q); // x * 1/4 dx = d.subtract(x); //System.out.println(" x = " + x); //System.out.println("dx = " + dx); } d = dx; } throw new NoConvergenceException("no convergence after " + i + " steps"); } /** * List of decimal approximations of complex roots of complex polynomial. * @param a univariate complex polynomial. * @param eps length for refinement. * @return list of complex decimal root approximations to desired precision. */ @SuppressWarnings("unchecked") public List> approximateRoots(GenPolynomial> a, C eps) { ComplexRing cr = (ComplexRing) a.ring.coFac; SortedMap>, Long> sa = engine.squarefreeFactors(a); List> roots = new ArrayList>(); for (Map.Entry>, Long> me : sa.entrySet()) { GenPolynomial> p = me.getKey(); List> rf = null; if (p.degree(0) <= 1) { Complex tc = p.trailingBaseCoefficient(); tc = tc.negate(); BigDecimal rr = new BigDecimal(tc.getRe().getRational()); BigDecimal ri = new BigDecimal(tc.getIm().getRational()); ComplexRing crf = new ComplexRing(rr); Complex r = new Complex(crf, rr, ri); rf = new ArrayList>(1); rf.add(r); } else { Complex Mb = rootBound(p); C M = Mb.getRe(); C M1 = M.sum(M.factory().fromInteger(1)); // asymmetric to origin if (debug) { logger.info("rootBound = " + M); } Complex[] corner = (Complex[]) new Complex[4]; corner[0] = new Complex(cr, M1.negate(), M); // nw corner[1] = new Complex(cr, M1.negate(), M1.negate()); // sw corner[2] = new Complex(cr, M, M1.negate()); // se corner[3] = new Complex(cr, M, M); // ne Rectangle rect = new Rectangle(corner); List> rs = null; try { rs = complexRoots(rect, p); } catch (InvalidBoundaryException e) { throw new RuntimeException("this should never happen " + e); } rf = new ArrayList>(rs.size()); for (Rectangle r : rs) { Complex rr = null; while (rr == null) { try { rr = approximateRoot(r, p, eps); rf.add(rr); } catch (NoConvergenceException e) { // fall back to exact algorithm BigRational len = r.rationalLength(); len = len.multiply(new BigRational(1, 1000)); try { r = complexRootRefinement(r, p, len); logger.info("fall back rootRefinement = " + r); //System.out.println("len = " + len); } catch (InvalidBoundaryException ee) { throw new RuntimeException("this should never happen " + ee); } } } } } long e = me.getValue(); // sa.get(p); for (int i = 0; i < e; i++) { // add with multiplicity roots.addAll(rf); } } return roots; } /** * Copy the specified array. * @param original array. * @param newLength new array length. * @return copy of this. */ public Complex[] copyOfComplex(Complex[] original, int newLength) { Complex[] copy = new Complex[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; } /** * Invariant rectangle for algebraic number magnitude. * @param rect root isolating rectangle for f which contains exactly one * root. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @param eps length limit for rectangle length. * @return v with v a new rectangle contained in rect such that |g(a) - * g(b)| < eps for a, b in v in rect. */ public Rectangle invariantMagnitudeRectangle(Rectangle rect, GenPolynomial> f, GenPolynomial> g, C eps) throws InvalidBoundaryException { Rectangle v = rect; if (g == null || g.isZERO()) { return v; } if (g.isConstant()) { return v; } if (f == null || f.isZERO() || f.isConstant()) { // ? return v; } GenPolynomial> gp = PolyUtil.> baseDeriviative(g); //System.out.println("g = " + g); //System.out.println("gp = " + gp); C B = magnitudeBound(rect, gp); //System.out.println("B = " + B + " : " + B.getClass()); BigRational len = v.rationalLength(); BigRational half = new BigRational(1, 2); C vlen = v.length(); vlen = vlen.multiply(vlen); //eps = eps.multiply(eps); //System.out.println("v = " + v); //System.out.println("vlen = " + vlen); while (B.multiply(vlen).compareTo(eps) >= 0) { // TODO: test squared len = len.multiply(half); v = complexRootRefinement(v, f, len); //System.out.println("v = " + v); vlen = v.length(); vlen = vlen.multiply(vlen); //System.out.println("vlen = " + vlen); } //System.out.println("vlen = " + vlen); return v; } /** * Complex algebraic number magnitude. * @param rect root isolating rectangle for f which contains exactly one * root, with rect such that |g(a) - g(b)| < eps for a, b in * rect. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @return g(rect) . */ public Complex complexRectangleMagnitude(Rectangle rect, GenPolynomial> f, GenPolynomial> g) { if (g.isZERO() || g.isConstant()) { return g.leadingBaseCoefficient(); } RingFactory> cfac = f.ring.coFac; //System.out.println("cfac = " + cfac + " : " + cfac.getClass()); Complex c = rect.getCenter(); Complex ev = PolyUtil.> evaluateMain(cfac, g, c); return ev; } /** * Complex algebraic number magnitude. * @param rect root isolating rectangle for f which contains exactly one * root, with rect such that |g(a) - g(b)| < eps for a, b in * rect. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @param eps length limit for rectangle length. * @return g(rect) . */ public Complex complexMagnitude(Rectangle rect, GenPolynomial> f, GenPolynomial> g, C eps) throws InvalidBoundaryException { if (g.isZERO() || g.isConstant()) { return g.leadingBaseCoefficient(); } Rectangle v = invariantMagnitudeRectangle(rect, f, g, eps); //System.out.println("ref = " + ref); return complexRectangleMagnitude(v, f, g); } } jas-2.5/src/edu/jas/root/RealRoots.java0000644000175000017500000000705312000264162020222 0ustar giovannigiovanni/* * $Id: RealRoots.java 3989 2012-07-14 12:39:14Z kredel $ */ package edu.jas.root; import java.io.Serializable; import java.util.List; import edu.jas.arith.Rational; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.structure.GcdRingElem; /** * Real roots interface. * @param coefficient type. * @author Heinz Kredel */ public interface RealRoots & Rational> extends Serializable { /** * Real root bound. With f(M) * f(-M) != 0. * @param f univariate polynomial. * @return M such that -M < root(f) > M. */ public C realRootBound(GenPolynomial f); /** * Isolating intervals for the real roots. * @param f univariate polynomial. * @return a list of isolating intervalls for the real roots of f. */ public List> realRoots(GenPolynomial f); /** * Isolating intervals for the real roots. * @param f univariate polynomial. * @param eps requested intervals length. * @return a list of isolating intervals v such that |v| < eps. */ public List> realRoots(GenPolynomial f, C eps); /** * Isolating intervals for the real roots. * @param f univariate polynomial. * @param eps requested intervals length. * @return a list of isolating intervals v such that |v| < eps. */ public List> realRoots(GenPolynomial f, BigRational eps); /** * Sign changes on interval bounds. * @param iv root isolating interval with f(left) * f(right) != 0. * @param f univariate polynomial. * @return true if f(left) * f(right) < 0, else false */ public boolean signChange(Interval iv, GenPolynomial f); /** * Number of real roots in interval. * @param iv interval with f(left) * f(right) != 0. * @param f univariate polynomial. * @return number of real roots of f in I. */ public long realRootCount(Interval iv, GenPolynomial f); /** * Refine interval. * @param iv root isolating interval with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param eps requested interval length. * @return a new interval v such that |v| < eps. */ public Interval refineInterval(Interval iv, GenPolynomial f, C eps); /** * Refine intervals. * @param V list of isolating intervals with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param eps requested intervals length. * @return a list of new intervals v such that |v| < eps. */ public List> refineIntervals(List> V, GenPolynomial f, C eps); /** * Real algebraic number sign. * @param iv root isolating interval for f, with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @return sign(g(v)), with v a new interval contained in iv such that g(v) != * 0. */ public int realSign(Interval iv, GenPolynomial f, GenPolynomial g); /** * Real algebraic number magnitude. * @param iv root isolating interval for f, with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @param eps length limit for interval length. * @return g(iv). */ public C realMagnitude(Interval iv, GenPolynomial f, GenPolynomial g, C eps); } jas-2.5/src/edu/jas/root/package.html0000644000175000017500000000432311313514110017720 0ustar giovannigiovanni Real and Complex Root Computation package

Real and Complex Root Computation package.

This package contains classes for the computation of isolating and refining intervals of real roots and complex roots of univariate polynomials.

For the computation of real roots the main interface is RealRoots and main implementing class is RealRootsSturm. The implementation follows in part section 8.8 "Computation of real zeroes of Polynomial Systems" in Gröbner Bases, A computational Approach to Commutative Algebra, by Becker et al.
The class RealAlgebraicNumber is based on AlgebraicNumber with factory class RealAlgebraicRing based on AlgebraicNumberRing. They implement real algebraic numbers, which are algebraic numbers plus an isolating interval for a real root of the generator. RealRootsSturm can be applied to polynomials with real algebraic numbers.

For the computation of complex roots the main interface is ComplexRoots and the main implementing class is ComplexRootsSturm. The implementation provides an exact infallible method which follows the numeric method of Wilf (see Wilf: A global bisection algorithm for computing the zeros of polynomials in the complex plane). It uses Sturm sequences following the Routh-Hurwitz Method to count the number of complex roots within a rectangle in the complex plane. For a (eventually) more efficient method see: Collins and Krandick: An efficient algorithm for infallible polynomial complex root isolation, in ISSAC'92.


Heinz Kredel

Last modified: Sun Dec 20 22:33:25 CET 2009

$Id: package.html 2910 2009-12-20 21:34:00Z kredel $

jas-2.5/src/edu/jas/root/RealAlgebraicRing.java0000644000175000017500000002434312000257334021611 0ustar giovannigiovanni/* * $Id: RealAlgebraicRing.java 3987 2012-07-14 11:58:20Z kredel $ */ package edu.jas.root; import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.Random; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Real algebraic number factory class based on AlgebraicNumberRing with * RingElem interface. Objects of this class are immutable with the exception of * the isolating intervals. * @author Heinz Kredel */ public class RealAlgebraicRing & Rational> /*extends AlgebraicNumberRing*/ implements RingFactory> { /** * Representing AlgebraicNumberRing. */ public final AlgebraicNumberRing algebraic; /** * Isolating interval for a real root. Note: interval may shrink * eventually. */ /*package*/Interval root; /** * Precision of the isolating rectangle for a complex root. */ public static final int PRECISION = 9; //BigDecimal.DEFAULT_PRECISION; /** * Precision of the isolating interval for a real root. */ protected C eps; /** * Real root computation engine. */ public final RealRootsSturm engine; /** * The constructor creates a RealAlgebraicNumber factory object from a * GenPolynomial objects module. * @param m module GenPolynomial. * @param root isolating interval for a real root. */ public RealAlgebraicRing(GenPolynomial m, Interval root) { algebraic = new AlgebraicNumberRing(m); this.root = root; engine = new RealRootsSturm(); if (m.ring.characteristic().signum() > 0) { throw new RuntimeException("characteristic not zero"); } C e = m.ring.coFac.fromInteger(10L); e = e.inverse(); //C x = Power.positivePower(e, BigDecimal.DEFAULT_PRECISION); e = Power.positivePower(e, PRECISION); // better not too much for speed eps = e; } /** * The constructor creates a RealAlgebraicNumber factory object from a * GenPolynomial objects module. * @param m module GenPolynomial. * @param root isolating interval for a real root. * @param isField indicator if m is prime. */ public RealAlgebraicRing(GenPolynomial m, Interval root, boolean isField) { algebraic = new AlgebraicNumberRing(m, isField); this.root = root; engine = new RealRootsSturm(); if (m.ring.characteristic().signum() > 0) { throw new RuntimeException("characteristic not zero"); } C e = m.ring.coFac.fromInteger(10L); e = e.inverse(); e = Power.positivePower(e, PRECISION); //BigDecimal.DEFAULT_PRECISION); eps = e; } /** * Get the module part. * @return modul. public GenPolynomial getModul() { return * algebraic.modul; } */ /** * Get the interval for the real root. Note: interval may shrink * later. * @return real root isolating interval */ public synchronized Interval getRoot() { return root; } /** * Set a refined interval for the real root. Note: interval may * shrink eventually. * @param v interval. */ public synchronized void setRoot(Interval v) { // assert v is contained in root this.root = v; } /** * Get the epsilon. * @return eps. */ public synchronized C getEps() { return this.eps; } /** * Set a new epsilon. * @param e epsilon. */ public synchronized void setEps(C e) { this.eps = e; } /** * Set a new epsilon. * @param e epsilon. */ public synchronized void setEps(BigRational e) { this.eps = algebraic.ring.coFac.parse(e.toString()); } /** * RealAlgebraicRing half interval. */ public void halfInterval() { Interval v = engine.halfInterval(root, algebraic.modul); //System.out.println("old v = " + ring.root + ", new v = " + v); setRoot(v); } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return algebraic.isFinite(); } /** * Copy RealAlgebraicNumber element c. * @param c * @return a copy of c. */ public RealAlgebraicNumber copy(RealAlgebraicNumber c) { return new RealAlgebraicNumber(this, c.number); } /** * Get the zero element. * @return 0 as RealAlgebraicNumber. */ public RealAlgebraicNumber getZERO() { return new RealAlgebraicNumber(this, algebraic.getZERO()); } /** * Get the one element. * @return 1 as RealAlgebraicNumber. */ public RealAlgebraicNumber getONE() { return new RealAlgebraicNumber(this, algebraic.getONE()); } /** * Get the generating element. * @return alpha as RealAlgebraicNumber. */ public RealAlgebraicNumber getGenerator() { return new RealAlgebraicNumber(this, algebraic.getGenerator()); } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List> agens = algebraic.generators(); List> gens = new ArrayList>(agens.size()); for (AlgebraicNumber a : agens) { gens.add(getZERO().sum(a.getVal())); } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return algebraic.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return algebraic.isAssociative(); } /** * Query if this ring is a field. * @return true if algebraic is prime, else false. */ public boolean isField() { return algebraic.isField(); } /** * Assert that this ring is a field. * @param isField true if this ring is a field, else false. */ public void setField(boolean isField) { algebraic.setField(isField); } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return algebraic.characteristic(); } /** * Get a RealAlgebraicNumber element from a BigInteger value. * @param a BigInteger. * @return a RealAlgebraicNumber. */ public RealAlgebraicNumber fromInteger(java.math.BigInteger a) { return new RealAlgebraicNumber(this, algebraic.fromInteger(a)); } /** * Get a RealAlgebraicNumber element from a long value. * @param a long. * @return a RealAlgebraicNumber. */ public RealAlgebraicNumber fromInteger(long a) { return new RealAlgebraicNumber(this, algebraic.fromInteger(a)); } /** * Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { return "RealAlgebraicRing[ " + algebraic.modul.toString() + " in " + root + " | isField=" + algebraic.isField() + " :: " + algebraic.ring.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "RealN( " + algebraic.modul.toScript() + ", " + root.toScript() //+ ", " + algebraic.isField() //+ ", " + algebraic.ring.toScript() + " )"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object b) { if (!(b instanceof RealAlgebraicRing)) { return false; } RealAlgebraicRing a = null; try { a = (RealAlgebraicRing) b; } catch (ClassCastException e) { } if (a == null) { return false; } return algebraic.equals(a.algebraic) && root.equals(a.root); } /** * Hash code for this RealAlgebraicNumber. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * algebraic.hashCode() + root.hashCode(); } /** * RealAlgebraicNumber random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random integer mod modul. */ public RealAlgebraicNumber random(int n) { return new RealAlgebraicNumber(this, algebraic.random(n)); } /** * RealAlgebraicNumber random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random integer mod modul. */ public RealAlgebraicNumber random(int n, Random rnd) { return new RealAlgebraicNumber(this, algebraic.random(n, rnd)); } /** * Parse RealAlgebraicNumber from String. * @param s String. * @return RealAlgebraicNumber from s. */ public RealAlgebraicNumber parse(String s) { return new RealAlgebraicNumber(this, algebraic.parse(s)); } /** * Parse RealAlgebraicNumber from Reader. * @param r Reader. * @return next RealAlgebraicNumber from r. */ public RealAlgebraicNumber parse(Reader r) { return new RealAlgebraicNumber(this, algebraic.parse(r)); } } jas-2.5/src/edu/jas/root/RootFactory.java0000644000175000017500000003332111774041270020572 0ustar giovannigiovanni/* * $Id: RootFactory.java 3974 2012-07-01 12:29:44Z kredel $ */ package edu.jas.root; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.Map; import edu.jas.arith.Rational; import edu.jas.arith.BigRational; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.FactorAbstract; import edu.jas.ufd.FactorFactory; import edu.jas.ufd.SquarefreeAbstract; import edu.jas.ufd.SquarefreeFactory; /** * Roots factory. * @author Heinz Kredel */ public class RootFactory { /** * Is real algebraic number a root of a polynomial. * @param f univariate polynomial. * @param r real algebraic number. * @return true, if f(r) == 0, else false; */ public static & Rational> boolean isRoot(GenPolynomial f, RealAlgebraicNumber r) { RealAlgebraicRing rr = r.factory(); GenPolynomialRing> rfac = new GenPolynomialRing>(rr,f.factory()); GenPolynomial> p; p = PolyUtilRoot. convertToRealCoefficients(rfac,f); RealAlgebraicNumber a = PolyUtil.> evaluateMain(rr,p,r); return a.isZERO(); } /** * Real algebraic numbers. * @param f univariate polynomial. * @return a list of different real algebraic numbers. */ public static & Rational> List> realAlgebraicNumbers(GenPolynomial f) { RealRoots rr = new RealRootsSturm(); SquarefreeAbstract engine = SquarefreeFactory. getImplementation(f.ring.coFac); Map,Long> SF = engine.squarefreeFactors(f); Set> S = SF.keySet(); List> list = new ArrayList>(); for (GenPolynomial sp : S) { List> iv = rr.realRoots(sp); for (Interval I : iv) { RealAlgebraicRing rar = new RealAlgebraicRing(sp, I); RealAlgebraicNumber rn = rar.getGenerator(); long mult = SF.get(sp); for ( int i = 0; i < mult; i++ ) { list.add(rn); } } } return list; } /** * Real algebraic numbers. * @param f univariate polynomial. * @param eps rational precision. * @return a list of different real algebraic numbers. */ public static & Rational> List> realAlgebraicNumbers(GenPolynomial f, BigRational eps) { RealRoots rr = new RealRootsSturm(); SquarefreeAbstract engine = SquarefreeFactory. getImplementation(f.ring.coFac); Map,Long> SF = engine.squarefreeFactors(f); Set> S = SF.keySet(); List> list = new ArrayList>(); for (GenPolynomial sp : S) { List> iv = rr.realRoots(sp,eps); for (Interval I : iv) { RealAlgebraicRing rar = new RealAlgebraicRing(sp, I); rar.setEps(eps); RealAlgebraicNumber rn = rar.getGenerator(); long mult = SF.get(sp); for ( int i = 0; i < mult; i++ ) { list.add(rn); } } } return list; } /** * Real algebraic numbers from a field. * @param f univariate polynomial. * @return a list of different real algebraic numbers from a field. */ public static & Rational> List> realAlgebraicNumbersField(GenPolynomial f) { RealRoots rr = new RealRootsSturm(); FactorAbstract engine = FactorFactory. getImplementation(f.ring.coFac); Map,Long> SF = engine.baseFactors(f); Set> S = SF.keySet(); List> list = new ArrayList>(); for (GenPolynomial sp : S) { List> iv = rr.realRoots(sp); for (Interval I : iv) { RealAlgebraicRing rar = new RealAlgebraicRing(sp, I, true);//field RealAlgebraicNumber rn = rar.getGenerator(); long mult = SF.get(sp); for ( int i = 0; i < mult; i++ ) { list.add(rn); } } } return list; } /** * Real algebraic numbers from a field. * @param f univariate polynomial. * @param eps rational precision. * @return a list of different real algebraic numbers from a field. */ public static & Rational> List> realAlgebraicNumbersField(GenPolynomial f, BigRational eps) { RealRoots rr = new RealRootsSturm(); FactorAbstract engine = FactorFactory. getImplementation(f.ring.coFac); Map,Long> SF = engine.baseFactors(f); Set> S = SF.keySet(); List> list = new ArrayList>(); for (GenPolynomial sp : S) { List> iv = rr.realRoots(sp,eps); for (Interval I : iv) { RealAlgebraicRing rar = new RealAlgebraicRing(sp, I, true);//field rar.setEps(eps); RealAlgebraicNumber rn = rar.getGenerator(); long mult = SF.get(sp); for ( int i = 0; i < mult; i++ ) { list.add(rn); } } } return list; } /** * Real algebraic numbers from a irreducible polynomial. * @param f univariate irreducible polynomial. * @return a list of different real algebraic numbers from a field. */ public static & Rational> List> realAlgebraicNumbersIrred(GenPolynomial f) { RealRoots rr = new RealRootsSturm(); List> list = new ArrayList>(); List> iv = rr.realRoots(f); for (Interval I : iv) { RealAlgebraicRing rar = new RealAlgebraicRing(f, I, true);//field RealAlgebraicNumber rn = rar.getGenerator(); list.add(rn); } return list; } /** * Real algebraic numbers from a irreducible polynomial. * @param f univariate irreducible polynomial. * @param eps rational precision. * @return a list of different real algebraic numbers from a field. */ public static & Rational> List> realAlgebraicNumbersIrred(GenPolynomial f, BigRational eps) { RealRoots rr = new RealRootsSturm(); List> list = new ArrayList>(); List> iv = rr.realRoots(f,eps); for (Interval I : iv) { RealAlgebraicRing rar = new RealAlgebraicRing(f, I, true);//field rar.setEps(eps); RealAlgebraicNumber rn = rar.getGenerator(); list.add(rn); } return list; } /** * Is complex algebraic number a root of a polynomial. * @param f univariate polynomial. * @param r complex algebraic number. * @return true, if f(r) == 0, else false; */ public static & Rational> boolean isRoot(GenPolynomial f, ComplexAlgebraicNumber r) { ComplexAlgebraicRing cr = r.factory(); GenPolynomialRing> cfac = new GenPolynomialRing>(cr,f.factory()); GenPolynomial> p; p = PolyUtilRoot. convertToComplexCoefficients(cfac,f); ComplexAlgebraicNumber a = PolyUtil.> evaluateMain(cr,p,r); return a.isZERO(); } /** * Is complex algebraic number a root of a complex polynomial. * @param f univariate complex polynomial. * @param r complex algebraic number. * @return true, if f(r) == 0, else false; */ public static & Rational> boolean isRootComplex(GenPolynomial> f, ComplexAlgebraicNumber r) { ComplexAlgebraicRing cr = r.factory(); GenPolynomialRing> cfac = new GenPolynomialRing>(cr,f.factory()); GenPolynomial> p; p = PolyUtilRoot. convertToComplexCoefficientsFromComplex(cfac,f); ComplexAlgebraicNumber a = PolyUtil.> evaluateMain(cr,p,r); return a.isZERO(); } /** * Complex algebraic numbers. * @param f univariate polynomial. * @return a list of different complex algebraic numbers. */ public static & Rational> List> complexAlgebraicNumbersComplex(GenPolynomial> f) { ComplexRoots cr = new ComplexRootsSturm(f.ring.coFac); SquarefreeAbstract> engine = SquarefreeFactory .> getImplementation(f.ring.coFac); Map>,Long> SF = engine.squarefreeFactors(f); Set>> S = SF.keySet(); List> list = new ArrayList>(); for (GenPolynomial> sp : S) { List> iv = cr.complexRoots(sp); for (Rectangle I : iv) { ComplexAlgebraicRing car = new ComplexAlgebraicRing(sp, I); ComplexAlgebraicNumber cn = car.getGenerator(); long mult = SF.get(sp); for ( int i = 0; i < mult; i++ ) { list.add(cn); } } } return list; } /** * Complex algebraic numbers. * @param f univariate polynomial. * @param eps rational precision. * @return a list of different complex algebraic numbers. */ public static & Rational> List> complexAlgebraicNumbersComplex(GenPolynomial> f, BigRational eps) { ComplexRoots cr = new ComplexRootsSturm(f.ring.coFac); SquarefreeAbstract> engine = SquarefreeFactory .> getImplementation(f.ring.coFac); Map>,Long> SF = engine.squarefreeFactors(f); Set>> S = SF.keySet(); List> list = new ArrayList>(); for (GenPolynomial> sp : S) { List> iv = cr.complexRoots(sp); for (Rectangle I : iv) { Rectangle Iv = I; try { Iv = cr.complexRootRefinement(I,sp,eps); } catch (InvalidBoundaryException e) { e.printStackTrace(); } ComplexAlgebraicRing car = new ComplexAlgebraicRing(sp, Iv); car.setEps(eps); ComplexAlgebraicNumber cn = car.getGenerator(); long mult = SF.get(sp); for ( int i = 0; i < mult; i++ ) { list.add(cn); } } } return list; } /** * Complex algebraic numbers. * @param f univariate (rational) polynomial. * @return a list of different complex algebraic numbers. */ public static & Rational> List> complexAlgebraicNumbers(GenPolynomial f) { if ( f.ring.coFac instanceof Complex ) { throw new IllegalArgumentException("f already has Complex coefficients " + f.ring); } if ( f.ring.coFac instanceof ComplexAlgebraicRing ) { throw new UnsupportedOperationException("unsupported ComplexAlgebraicRing coefficients " + f.ring); } ComplexRing cr = new ComplexRing( f.ring.coFac ); GenPolynomialRing> fac = new GenPolynomialRing>(cr,f.ring); GenPolynomial> fc = PolyUtil.complexFromAny(fac,f); return complexAlgebraicNumbersComplex(fc); } /** * Complex algebraic numbers. * @param f univariate (rational) polynomial. * @param eps rational precision. * @return a list of different complex algebraic numbers. */ public static & Rational> List> complexAlgebraicNumbers(GenPolynomial f, BigRational eps) { if ( f.ring.coFac instanceof Complex ) { throw new IllegalArgumentException("f already has Complex coefficients " + f.ring); } if ( f.ring.coFac instanceof ComplexAlgebraicRing ) { throw new UnsupportedOperationException("unsupported ComplexAlgebraicRing coefficients " + f.ring); } ComplexRing cr = new ComplexRing( f.ring.coFac ); GenPolynomialRing> fac = new GenPolynomialRing>(cr,f.ring); GenPolynomial> fc = PolyUtil.complexFromAny(fac,f); return complexAlgebraicNumbersComplex(fc,eps); } } jas-2.5/src/edu/jas/root/ComplexRootsSturm.java0000644000175000017500000003571612003277306022017 0ustar giovannigiovanni/* * $Id: ComplexRootsSturm.java 4025 2012-07-23 16:41:43Z kredel $ */ package edu.jas.root; import java.util.ArrayList; //import java.util.Arrays; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.Rational; import edu.jas.arith.BigRational; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.RingElem; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.util.ArrayUtil; /** * Complex roots implemented by Sturm sequences. Algorithms use exact method * derived from Wilf's numeric Routh-Hurwitz method. * @param coefficient type. * @author Heinz Kredel */ public class ComplexRootsSturm & Rational> extends ComplexRootsAbstract { private static final Logger logger = Logger.getLogger(ComplexRootsSturm.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. * @param cf coefficient factory. */ public ComplexRootsSturm(RingFactory> cf) { super(cf); //ufd = GCDFactory.> getImplementation(cf); } /** * Cauchy index of rational function f/g on interval. * @param a interval bound for I = [a,b]. * @param b interval bound for I = [a,b]. * @param f univariate polynomial. * @param g univariate polynomial. * @return winding number of f/g in I. */ public long indexOfCauchy(C a, C b, GenPolynomial f, GenPolynomial g) { List> S = sturmSequence(g, f); //System.out.println("S = " + S); if (debug) { logger.info("sturmSeq = " + S); } RingFactory cfac = f.ring.coFac; List l = PolyUtil. evaluateMain(cfac, S, a); List r = PolyUtil. evaluateMain(cfac, S, b); long v = RootUtil. signVar(l) - RootUtil. signVar(r); //System.out.println("v = " + v); // if (v < 0L) { // v = -v; // } return v; } /** * Routh index of complex function f + i g on interval. * @param a interval bound for I = [a,b]. * @param b interval bound for I = [a,b]. * @param f univariate polynomial. * @param g univariate polynomial != 0. * @return index number of f + i g. */ public long[] indexOfRouth(C a, C b, GenPolynomial f, GenPolynomial g) { List> S = sturmSequence(f, g); //System.out.println("S = " + S); RingFactory cfac = f.ring.coFac; List l = PolyUtil. evaluateMain(cfac, S, a); List r = PolyUtil. evaluateMain(cfac, S, b); long v = RootUtil. signVar(l) - RootUtil. signVar(r); //System.out.println("v = " + v); long d = f.degree(0); if (d < g.degree(0)) { d = g.degree(0); } //System.out.println("d = " + d); long ui = (d - v) / 2; long li = (d + v) / 2; //System.out.println("upper = " + ui); //System.out.println("lower = " + li); return new long[] { ui, li }; } /** * Sturm sequence. * @param f univariate polynomial. * @param g univariate polynomial. * @return a Sturm sequence for f and g. */ public List> sturmSequence(GenPolynomial f, GenPolynomial g) { List> S = new ArrayList>(); if (f == null || f.isZERO()) { return S; } if (f.isConstant()) { S.add(f.monic()); return S; } GenPolynomial F = f; S.add(F); GenPolynomial G = g; //PolyUtil. baseDeriviative(f); while (!G.isZERO()) { GenPolynomial r = F.remainder(G); F = G; G = r.negate(); S.add(F/*.monic()*/); } //System.out.println("F = " + F); if (F.isConstant()) { return S; } // make squarefree List> Sp = new ArrayList>(S.size()); for (GenPolynomial p : S) { p = p.divide(F); Sp.add(p); } return Sp; } /** * Complex root count of complex polynomial on rectangle. * @param rect rectangle. * @param a univariate complex polynomial. * @return root count of a in rectangle. */ @Override public long complexRootCount(Rectangle rect, GenPolynomial> a) throws InvalidBoundaryException { C rl = rect.lengthReal(); C il = rect.lengthImag(); // only linear polynomials have zero length intervals if ( rl.isZERO() && il.isZERO() ) { Complex e = PolyUtil.> evaluateMain(a.ring.coFac, a, rect.getSW()); if ( e.isZERO() ) { return 1; } return 0; } if ( rl.isZERO() || il.isZERO() ) { //RingFactory cf = (RingFactory) rl.factory(); //GenPolynomialRing rfac = new GenPolynomialRing(cf,a.ring); //cf = (RingFactory) il.factory(); //GenPolynomialRing ifac = new GenPolynomialRing(cf,a.ring); //GenPolynomial rp = PolyUtil. realPartFromComplex(rfac, a); //GenPolynomial ip = PolyUtil. imaginaryPartFromComplex(ifac, a); //RealRoots rr = new RealRootsSturm(); if ( rl.isZERO() ) { //logger.info("lengthReal == 0: " + rect); //Complex r = rect.getSW(); //r = new Complex(r.ring,r.getRe()/*,0*/); //Complex e = PolyUtil.> evaluateMain(a.ring.coFac, a, r); //logger.info("a(re(rect)): " + e); //if ( !e.getRe().isZERO() ) { // return 0; //} //C ev = PolyUtil. evaluateMain(rp.ring.coFac, rp, rl); //logger.info("re(a)(re(rect)): " + ev); //Interval iv = new Interval(rect.getSW().getIm(),rect.getNE().getIm()); //logger.info("iv: " + iv); //long ic = rr.realRootCount(iv,ip); //logger.info("ic: " + ic); Complex sw = rect.getSW(); Complex ne = rect.getNE(); C delta = sw.ring.ring.parse("1"); // works since linear polynomial Complex cd = new Complex(sw.ring,delta/*, 0*/); sw = sw.subtract(cd); ne = ne.sum(cd); rect = rect.exchangeSW(sw); rect = rect.exchangeNE(ne); logger.info("new rectangle: " + rect.toScript()); } if ( il.isZERO() ) { //logger.info("lengthImag == 0: " + rect); //Interval rv = new Interval(rect.getSW().getRe(),rect.getNE().getRe()); //logger.info("rv: " + rv); //long rc = rr.realRootCount(rv,rp); //logger.info("rc: " + rc); Complex sw = rect.getSW(); Complex ne = rect.getNE(); C delta = sw.ring.ring.parse("1"); // works since linear polynomial Complex cd = new Complex(sw.ring,sw.ring.ring.getZERO(),delta); sw = sw.subtract(cd); ne = ne.sum(cd); rect = rect.exchangeSW(sw); rect = rect.exchangeNE(ne); logger.info("new rectangle: " + rect.toScript()); } } return windingNumber(rect, a); } /** * Winding number of complex function A on rectangle. * @param rect rectangle. * @param A univariate complex polynomial. * @return winding number of A arround rect. */ public long windingNumber(Rectangle rect, GenPolynomial> A) throws InvalidBoundaryException { Boundary bound = new Boundary(rect, A); // throws InvalidBoundaryException ComplexRing cr = (ComplexRing) A.ring.coFac; RingFactory cf = cr.ring; C zero = cf.getZERO(); C one = cf.getONE(); long ix = 0L; for (int i = 0; i < 4; i++) { long ci = indexOfCauchy(zero, one, bound.getRealPart(i), bound.getImagPart(i)); //System.out.println("ci["+i+","+(i+1)+"] = " + ci); ix += ci; } if (ix % 2L != 0) { throw new InvalidBoundaryException("odd winding number " + ix); } return ix / 2L; } /** * List of complex roots of complex polynomial a on rectangle. * @param rect rectangle. * @param a univariate squarefree complex polynomial. * @return list of complex roots. */ @Override public List> complexRoots(Rectangle rect, GenPolynomial> a) throws InvalidBoundaryException { ComplexRing cr = (ComplexRing) a.ring.coFac; List> roots = new ArrayList>(); if ( a.isConstant() || a.isZERO() ) { return roots; } //System.out.println("rect = " + rect); long n = windingNumber(rect, a); if (n < 0) { // can this happen? throw new RuntimeException("negative winding number " + n); //System.out.println("negative winding number " + n); //return roots; } if (n == 0) { return roots; } if (n == 1) { roots.add(rect); return roots; } Complex eps = cr.fromInteger(1); eps = eps.divide(cr.fromInteger(1000)); // 1/1000 //System.out.println("eps = " + eps); //System.out.println("rect = " + rect); // construct new center Complex delta = rect.corners[3].subtract(rect.corners[1]); delta = delta.divide(cr.fromInteger(2)); //System.out.println("delta = " + delta); boolean work = true; while (work) { Complex center = rect.corners[1].sum(delta); //System.out.println("center = " + toDecimal(center)); if (debug) { logger.info("new center = " + center); } try { Complex[] cp = (Complex[]) copyOfComplex(rect.corners, 4); // (Complex[]) new Complex[4]; cp[0] = rect.corners[0]; // cp[0] fix cp[1] = new Complex(cr, cp[1].getRe(), center.getIm()); cp[2] = center; cp[3] = new Complex(cr, center.getRe(), cp[3].getIm()); Rectangle nw = new Rectangle(cp); //System.out.println("nw = " + nw); List> nwr = complexRoots(nw, a); //System.out.println("#nwr = " + nwr.size()); roots.addAll(nwr); if ( roots.size() == a.degree(0) ) { work = false; break; } cp = (Complex[]) copyOfComplex(rect.corners, 4); cp[0] = new Complex(cr, cp[0].getRe(), center.getIm()); // cp[1] fix cp[2] = new Complex(cr, center.getRe(), cp[2].getIm()); cp[3] = center; Rectangle sw = new Rectangle(cp); //System.out.println("sw = " + sw); List> swr = complexRoots(sw, a); //System.out.println("#swr = " + swr.size()); roots.addAll(swr); if ( roots.size() == a.degree(0) ) { work = false; break; } cp = (Complex[]) copyOfComplex(rect.corners, 4); cp[0] = center; cp[1] = new Complex(cr, center.getRe(), cp[1].getIm()); // cp[2] fix cp[3] = new Complex(cr, cp[3].getRe(), center.getIm()); Rectangle se = new Rectangle(cp); //System.out.println("se = " + se); List> ser = complexRoots(se, a); //System.out.println("#ser = " + ser.size()); roots.addAll(ser); if ( roots.size() == a.degree(0) ) { work = false; break; } cp = (Complex[]) copyOfComplex(rect.corners, 4); cp[0] = new Complex(cr, center.getRe(), cp[0].getIm()); cp[1] = center; cp[2] = new Complex(cr, cp[2].getRe(), center.getIm()); // cp[3] fix Rectangle ne = new Rectangle(cp); //System.out.println("ne = " + ne); List> ner = complexRoots(ne, a); //System.out.println("#ner = " + ner.size()); roots.addAll(ner); work = false; } catch (InvalidBoundaryException e) { // repeat with new center delta = delta.sum(delta.multiply(eps)); // distort //System.out.println("new delta = " + toDecimal(delta)); eps = eps.sum(eps.multiply(cr.getIMAG())); } } return roots; } /** * Invariant rectangle for algebraic number. * @param rect root isolating rectangle for f which contains exactly one root. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @return v a new rectangle contained in rect such that g(w) != 0 for w in v. */ @Override public Rectangle invariantRectangle(Rectangle rect, GenPolynomial> f, GenPolynomial> g) throws InvalidBoundaryException { Rectangle v = rect; if (g == null || g.isZERO()) { return v; } if (g.isConstant()) { return v; } if (f == null || f.isZERO() || f.isConstant()) { // ? return v; } BigRational len = v.rationalLength(); BigRational half = new BigRational(1,2); while (true) { long n = windingNumber(v, g); //System.out.println("n = " + n); if (n < 0) { // can this happen? throw new RuntimeException("negative winding number " + n); } if (n == 0) { return v; } len = len.multiply(half); Rectangle v1 = v; v = complexRootRefinement(v,f,len); if ( v.equals(v1) ) { //System.out.println("len = " + len); if ( !f.gcd(g).isONE() ) { System.out.println("f.gcd(g) = " + f.gcd(g)); throw new RuntimeException("no convergence " + v); } //break; // no convergence } } //return v; } } jas-2.5/src/edu/jas/root/RealRootsSturm.java0000644000175000017500000002567712014156146021300 0ustar giovannigiovanni/* * $Id: RealRootsSturm.java 4111 2012-08-19 12:30:30Z kredel $ */ package edu.jas.root; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.PolyUtil; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Real root isolation using Sturm sequences. * @param coefficient type. * @author Heinz Kredel */ public class RealRootsSturm & Rational> extends RealRootsAbstract { private static final Logger logger = Logger.getLogger(RealRootsSturm.class); private static boolean debug = logger.isDebugEnabled(); /** * Sturm sequence. * @param f univariate polynomial. * @return a Sturm sequence for f. */ public List> sturmSequence(GenPolynomial f) { List> S = new ArrayList>(); if (f == null || f.isZERO()) { return S; } if (f.isConstant()) { S.add(f.monic()); return S; } GenPolynomial F = f; S.add(F); GenPolynomial G = PolyUtil. baseDeriviative(f); while (!G.isZERO()) { GenPolynomial r = F.remainder(G); F = G; G = r.negate(); S.add(F/*.monic()*/); } //System.out.println("F = " + F); if (F.isConstant()) { return S; } // make squarefree List> Sp = new ArrayList>(S.size()); for (GenPolynomial p : S) { p = p.divide(F); Sp.add(p); } return Sp; } /** * Isolating intervals for the real roots. * @param f univariate polynomial. * @return a list of isolating intervals for the real roots of f. */ @Override public List> realRoots(GenPolynomial f) { List> R = new ArrayList>(); if (f == null || f.isConstant()) { return R; } if (f.isZERO()) { C z = f.ring.coFac.getZERO(); R.add(new Interval(z)); return R; } if (f.degree(0) == 1L) { C z = f.monic().trailingBaseCoefficient().negate(); R.add(new Interval(z)); return R; } GenPolynomial F = f; C M = realRootBound(F); // M != 0, since >= 2 Interval iv = new Interval(M.negate(), M); //System.out.println("iv = " + iv); List> S = sturmSequence(F); //System.out.println("S = " + S); //System.out.println("f_S = " + S.get(0)); List> Rp = realRoots(iv, S); if (logger.isInfoEnabled() && !(((Object) f.ring.coFac) instanceof BigRational)) { //logger.info("realRoots bound: " + iv); logger.info("realRoots: " + Rp); } R.addAll(Rp); return R; } /** * Isolating intervals for the real roots. * @param iv interval with f(left) * f(right) != 0. * @param S sturm sequence for f and I. * @return a list of isolating intervals for the real roots of f in I. */ public List> realRoots(Interval iv, List> S) { List> R = new ArrayList>(); GenPolynomial f = S.get(0); // squarefree part if (f.isZERO()) { C z = f.leadingBaseCoefficient(); if (!iv.contains(z)) { throw new IllegalArgumentException("root not in interval: f = " + f + ", iv = " + iv + ", z = " + z); } Interval iv1 = new Interval(z); R.add(iv1); return R; } if (f.isConstant()) { return R; //throw new IllegalArgumentException("f has no root: f = " + f + ", iv = " + iv); } if (f.degree(0) == 1L) { C z = f.monic().trailingBaseCoefficient().negate(); if (!iv.contains(z)) { return R; //throw new IllegalArgumentException("root not in interval: f = " + f + ", iv = " + iv + ", z = " + z); } Interval iv1 = new Interval(z); R.add(iv1); return R; } //System.out.println("iv = " + iv); // check sign variations at interval bounds long v = realRootCount(iv, S); //System.out.println("v = " + v); if (v == 0) { return R; } if (v == 1) { R.add(iv); return R; } // now v > 1 // bi-sect interval, such that f(c) != 0 C c = bisectionPoint(iv, f); //System.out.println("c = " + c); // recursion on both sub-intervals Interval iv1 = new Interval(iv.left, c); Interval iv2 = new Interval(c, iv.right); List> R1 = realRoots(iv1, S); //System.out.println("R1 = " + R1); if (debug) { logger.info("R1 = " + R1); } List> R2 = realRoots(iv2, S); //System.out.println("R2 = " + R2); if (debug) { logger.info("R2 = " + R2); } // refine isolating intervals if adjacent if (R1.isEmpty()) { R.addAll(R2); return R; } if (R2.isEmpty()) { R.addAll(R1); return R; } iv1 = R1.get(R1.size() - 1); // last iv2 = R2.get(0); // first if (iv1.right.compareTo(iv2.left) < 0) { R.addAll(R1); R.addAll(R2); return R; } // now iv1.right == iv2.left //System.out.println("iv1 = " + iv1); //System.out.println("iv2 = " + iv2); R1.remove(iv1); R2.remove(iv2); while (iv1.right.equals(iv2.left)) { C d1 = bisectionPoint(iv1, f); C d2 = bisectionPoint(iv2, f); Interval iv11 = new Interval(iv1.left, d1); Interval iv12 = new Interval(d1, iv1.right); Interval iv21 = new Interval(iv2.left, d2); Interval iv22 = new Interval(d2, iv2.right); boolean b11 = signChange(iv11, f); boolean b12 = signChange(iv12, f); // TODO check unnecessary //boolean b21 = signChange(iv21, f); // TODO check unused or unnecessary boolean b22 = signChange(iv22, f); if (b11) { iv1 = iv11; if (b22) { iv2 = iv22; } else { iv2 = iv21; } break; // done, refine } if (b22) { iv2 = iv22; if (b12) { iv1 = iv12; } else { iv1 = iv11; } break; // done, refine } iv1 = iv12; iv2 = iv21; //System.out.println("iv1 = " + iv1); //System.out.println("iv2 = " + iv2); } R.addAll(R1); R.add(iv1); R.add(iv2); R.addAll(R2); return R; } /** * Number of real roots in interval. * @param iv interval with f(left) * f(right) != 0. * @param S sturm sequence for f and I. * @return number of real roots of f in I. */ public long realRootCount(Interval iv, List> S) { // check sign variations at interval bounds GenPolynomial f = S.get(0); // squarefree part //System.out.println("iv = " + iv); RingFactory cfac = f.ring.coFac; List l = PolyUtil. evaluateMain(cfac, S, iv.left); List r = PolyUtil. evaluateMain(cfac, S, iv.right); long v = RootUtil. signVar(l) - RootUtil. signVar(r); //System.out.println("v = " + v); if (v < 0L) { v = -v; } return v; } /** * Number of real roots in interval. * @param iv interval with f(left) * f(right) != 0. * @param f univariate polynomial. * @return number of real roots of f in I. */ @Override public long realRootCount(Interval iv, GenPolynomial f) { if (f == null || f.isConstant()) { // ? return 0L; } if (f.isZERO()) { C z = f.leadingBaseCoefficient(); if (!iv.contains(z)) { return 0L; } return 1L; } List> S = sturmSequence(f); return realRootCount(iv, S); } /** * Invariant interval for algebraic number sign. * @param iv root isolating interval for f, with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @return v with v a new interval contained in iv such that g(w) != 0 for w * in v. */ @Override public Interval invariantSignInterval(Interval iv, GenPolynomial f, GenPolynomial g) { Interval v = iv; if (g == null || g.isZERO()) { //throw new IllegalArgumentException("g == 0"); return v; } if (g.isConstant()) { return v; } if (f == null || f.isZERO()) { // ? || f.isConstant() throw new IllegalArgumentException("f == 0"); //return v; } List> Sg = sturmSequence(g.monic()); Interval ivp = invariantSignInterval(iv, f, Sg); return ivp; } /** * Invariant interval for algebraic number sign. * @param iv root isolating interval for f, with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param Sg Sturm sequence for g, a univariate polynomial with gcd(f,g) == * 1. * @return v with v a new interval contained in iv such that g(w) != 0 for w * in v. */ public Interval invariantSignInterval(Interval iv, GenPolynomial f, List> Sg) { Interval v = iv; GenPolynomial g = Sg.get(0); if (g == null || g.isZERO()) { return v; } if (g.isConstant()) { return v; } if (f == null || f.isZERO()) { // ? || f.isConstant() return v; } RingFactory cfac = f.ring.coFac; C two = cfac.fromInteger(2); while (true) { long n = realRootCount(v, Sg); logger.debug("n = " + n); if (n == 0) { return v; } C c = v.left.sum(v.right); c = c.divide(two); Interval im = new Interval(c, v.right); if (signChange(im, f)) { v = im; } else { v = new Interval(v.left, c); } } // return v; } } jas-2.5/src/edu/jas/root/Boundary.java0000644000175000017500000001264512014234362020102 0ustar giovannigiovanni/* * $Id: Boundary.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.root; import java.io.Serializable; import edu.jas.arith.Rational; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisor; /** * Boundary determined by a rectangle and a polynomial. * * For a given complex polynomial A a closed path throught the corners * of the given rectangle is constructed. The path is represented by * four polynomials, one for each side of the rectangle. For a real t * in [0,1] the i-th polynomial describes the path of A from corner[i] * to corner[i+1]. In particular polys[i](0) = A(corner[i]) and * polys[i](1) = A(corner[i+1]), with corner[4] = corner[0]. If A * would be zero on a point of the path, an InvalidBoundaryException * is thrown. * @param coefficient type. * @author Heinz Kredel */ public class Boundary & Rational> implements Serializable { /** * Rectangle. */ public final Rectangle rect; /** * Polynomial. */ public final GenPolynomial> A; /** * Boundary polynomials. */ public final GenPolynomial>[] polys; /** * Factory for real polynomials. */ GenPolynomialRing rfac; /** * Constructor. * @param r rectangle of of corners. * @param p non constant polynomial. */ @SuppressWarnings("unchecked") public Boundary(Rectangle r, GenPolynomial> p) throws InvalidBoundaryException { if ( p.isConstant() || p.isZERO() ) { throw new InvalidBoundaryException("p is constant or 0 " + p); } rect = r; A = p; GreatestCommonDivisor> ufd = GCDFactory.> getImplementation(A.ring.coFac); polys = (GenPolynomial>[]) new GenPolynomial[5]; Complex[] corner = rect.corners; for (int i = 0; i < 4; i++) { Complex t = corner[i + 1].subtract(corner[i]); GenPolynomial> tp = A.ring.univariate(0, 1L).multiply(t); //System.out.println("t = " + t); GenPolynomial> pc = PolyUtil.> seriesOfTaylor(A, corner[i]); pc = PolyUtil.> substituteUnivariate(pc, tp); GenPolynomial> gcd = ufd.gcd(A, pc); if (!gcd.isONE()) { //System.out.println("A = " + A); //System.out.println("PC["+i+"] = " + pc); //System.out.println("gcd = " + gcd); throw new InvalidBoundaryException("A has a zero on rectangle " + rect + ", A = " + A); } polys[i] = pc; } polys[4] = polys[0]; // setup factory for real and imaginary parts ComplexRing cr = (ComplexRing) A.ring.coFac; RingFactory cf = cr.ring; rfac = new GenPolynomialRing(cf, A.ring); } /** * Constructor. * @param r rectangle of of corners. * @param p polynomial. * @param b boundary polynomials. */ protected Boundary(Rectangle r, GenPolynomial> p, GenPolynomial>[] b) { rect = r; A = p; polys = b; // setup factory for real and imaginary parts ComplexRing cr = (ComplexRing) A.ring.coFac; RingFactory cf = cr.ring; rfac = new GenPolynomialRing(cf, A.ring); } /** * String representation of Boundary. * @see java.lang.Object#toString() */ @Override public String toString() { return rect.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Boundary. */ public String toScript() { // Python case return rect.toScript(); } /** * Get real part for polynomial i. * @param i index of polynomial. * @return real part for polynomial i. */ public GenPolynomial getRealPart(int i) { GenPolynomial f = PolyUtil. realPartFromComplex(rfac, polys[i]); return f; } /** * Get imaginary part for polynomial i. * @param i index of polynomial. * @return imaginary part for polynomial i. */ public GenPolynomial getImagPart(int i) { GenPolynomial g = PolyUtil. imaginaryPartFromComplex(rfac, polys[i]); return g; } /** * Copy this. * @return a copy of this. */ public Boundary copy() { return new Boundary(rect, A, polys); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { Boundary a = null; try { a = (Boundary) b; } catch (ClassCastException e) { } if (a == null) { return false; } return rect.equals(a.rect) && A.equals(a.A); } /** * Hash code for this Rectangle. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int hc = 0; hc += 37 * rect.hashCode(); return 37 * hc + A.hashCode(); } } jas-2.5/src/edu/jas/root/RealAlgebraicNumber.java0000644000175000017500000002711212014234362022140 0ustar giovannigiovanni/* * $Id: RealAlgebraicNumber.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.root; // import edu.jas.structure.RingElem; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.kern.PrettyPrint; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; import edu.jas.structure.NotInvertibleException; /** * Real algebraic number class based on AlgebraicNumber. Objects of this class * are immutable. * @author Heinz Kredel */ public class RealAlgebraicNumber & Rational> /*extends AlgebraicNumber*/ implements GcdRingElem>, Rational { /** * Representing AlgebraicNumber. */ public final AlgebraicNumber number; /** * Ring part of the data structure. */ public final RealAlgebraicRing ring; /** * The constructor creates a RealAlgebraicNumber object from * RealAlgebraicRing modul and a GenPolynomial value. * @param r ring RealAlgebraicRing. * @param a value GenPolynomial. */ public RealAlgebraicNumber(RealAlgebraicRing r, GenPolynomial a) { number = new AlgebraicNumber(r.algebraic, a); ring = r; } /** * The constructor creates a RealAlgebraicNumber object from * RealAlgebraicRing modul and a AlgebraicNumber value. * @param r ring RealAlgebraicRing. * @param a value AlgebraicNumber. */ public RealAlgebraicNumber(RealAlgebraicRing r, AlgebraicNumber a) { number = a; ring = r; } /** * The constructor creates a RealAlgebraicNumber object from a GenPolynomial * object module. * @param r ring RealAlgebraicRing. */ public RealAlgebraicNumber(RealAlgebraicRing r) { this(r, r.algebraic.getZERO()); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public RealAlgebraicRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public RealAlgebraicNumber copy() { return new RealAlgebraicNumber(ring, number); } /** * Return a BigRational approximation of this Element. * @return a BigRational approximation of this. * @see edu.jas.arith.Rational#getRational() */ public BigRational getRational() { return magnitude(); } /** * Is RealAlgebraicNumber zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return number.isZERO(); } /** * Is RealAlgebraicNumber one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return number.isONE(); } /** * Is RealAlgebraicNumber unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { return number.isUnit(); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { if (PrettyPrint.isTrue()) { return "{ " + number.toString() + " }"; } return "Real" + number.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return number.toScript(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * RealAlgebraicNumber comparison. * @param b RealAlgebraicNumber. * @return real sign(this-b). */ //JAVA6only: @Override public int compareTo(RealAlgebraicNumber b) { int s = 0; if (number.ring != b.number.ring) { // avoid compareTo if possible s = number.ring.modul.compareTo(b.number.ring.modul); System.out.println("s_mod = " + s); } if (s != 0) { return s; } s = this.subtract(b).signum(); // TODO //System.out.println("s_real = " + s); return s; } /** * RealAlgebraicNumber comparison. * @param b AlgebraicNumber. * @return polynomial sign(this-b). */ public int compareTo(AlgebraicNumber b) { int s = number.compareTo(b); System.out.println("s_algeb = " + s); return s; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof RealAlgebraicNumber)) { return false; } RealAlgebraicNumber a = null; try { a = (RealAlgebraicNumber) b; } catch (ClassCastException e) { } if (a == null) { return false; } if (!ring.equals(a.ring)) { return false; } return number.equals(a.number); } /** * Hash code for this RealAlgebraicNumber. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * number.val.hashCode() + ring.hashCode(); } /** * RealAlgebraicNumber absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public RealAlgebraicNumber abs() { if (this.signum() < 0) { return new RealAlgebraicNumber(ring, number.negate()); } return this; } /** * RealAlgebraicNumber summation. * @param S RealAlgebraicNumber. * @return this+S. */ public RealAlgebraicNumber sum(RealAlgebraicNumber S) { return new RealAlgebraicNumber(ring, number.sum(S.number)); } /** * RealAlgebraicNumber summation. * @param c coefficient. * @return this+c. */ public RealAlgebraicNumber sum(GenPolynomial c) { return new RealAlgebraicNumber(ring, number.sum(c)); } /** * RealAlgebraicNumber summation. * @param c polynomial. * @return this+c. */ public RealAlgebraicNumber sum(C c) { return new RealAlgebraicNumber(ring, number.sum(c)); } /** * RealAlgebraicNumber negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public RealAlgebraicNumber negate() { return new RealAlgebraicNumber(ring, number.negate()); } /** * RealAlgebraicNumber signum. Note: Modifies ring.root eventually. * @see edu.jas.structure.RingElem#signum() * @return real signum(this). */ public int signum() { Interval v = ring.engine.invariantSignInterval(ring.root, ring.algebraic.modul, number.val); ring.setRoot(v); return ring.engine.realIntervalSign(v, ring.algebraic.modul, number.val); } /** * RealAlgebraicNumber half interval. */ public void halfInterval() { Interval v = ring.engine.halfInterval(ring.root, ring.algebraic.modul); //System.out.println("old v = " + ring.root + ", new v = " + v); ring.setRoot(v); } /** * RealAlgebraicNumber magnitude. * @return |this|. */ public BigRational magnitude() { Interval v = ring.engine.invariantMagnitudeInterval(ring.root, ring.algebraic.modul, number.val, ring.getEps()); //System.out.println("old v = " + ring.root + ", new v = " + v); ring.setRoot(v); C ev = ring.engine.realIntervalMagnitude(v, ring.algebraic.modul, number.val); //, ring.eps); //if ((Object) ev instanceof Rational) { // always true by type parameter BigRational er = ev.getRational(); return er; //} //throw new RuntimeException("Rational expected, but was " + ev.getClass()); } /** * RealAlgebraicNumber magnitude. * @return |this| as big decimal. */ public BigDecimal decimalMagnitude() { return new BigDecimal(magnitude()); } /** * RealAlgebraicNumber subtraction. * @param S RealAlgebraicNumber. * @return this-S. */ public RealAlgebraicNumber subtract(RealAlgebraicNumber S) { return new RealAlgebraicNumber(ring, number.subtract(S.number)); } /** * RealAlgebraicNumber division. * @param S RealAlgebraicNumber. * @return this/S. */ public RealAlgebraicNumber divide(RealAlgebraicNumber S) { return multiply(S.inverse()); } /** * RealAlgebraicNumber inverse. * @see edu.jas.structure.RingElem#inverse() * @throws NotInvertibleException if the element is not invertible. * @return S with S = 1/this if defined. */ public RealAlgebraicNumber inverse() { return new RealAlgebraicNumber(ring, number.inverse()); } /** * RealAlgebraicNumber remainder. * @param S RealAlgebraicNumber. * @return this - (this/S)*S. */ public RealAlgebraicNumber remainder(RealAlgebraicNumber S) { return new RealAlgebraicNumber(ring, number.remainder(S.number)); } /** * RealAlgebraicNumber multiplication. * @param S RealAlgebraicNumber. * @return this*S. */ public RealAlgebraicNumber multiply(RealAlgebraicNumber S) { return new RealAlgebraicNumber(ring, number.multiply(S.number)); } /** * RealAlgebraicNumber multiplication. * @param c coefficient. * @return this*c. */ public RealAlgebraicNumber multiply(C c) { return new RealAlgebraicNumber(ring, number.multiply(c)); } /** * RealAlgebraicNumber multiplication. * @param c polynomial. * @return this*c. */ public RealAlgebraicNumber multiply(GenPolynomial c) { return new RealAlgebraicNumber(ring, number.multiply(c)); } /** * RealAlgebraicNumber monic. * @return this with monic value part. */ public RealAlgebraicNumber monic() { return new RealAlgebraicNumber(ring, number.monic()); } /** * RealAlgebraicNumber greatest common divisor. * @param S RealAlgebraicNumber. * @return gcd(this,S). */ public RealAlgebraicNumber gcd(RealAlgebraicNumber S) { return new RealAlgebraicNumber(ring, number.gcd(S.number)); } /** * RealAlgebraicNumber extended greatest common divisor. * @param S RealAlgebraicNumber. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ @SuppressWarnings("unchecked") public RealAlgebraicNumber[] egcd(RealAlgebraicNumber S) { AlgebraicNumber[] aret = number.egcd(S.number); RealAlgebraicNumber[] ret = new RealAlgebraicNumber[3]; ret[0] = new RealAlgebraicNumber(ring, aret[0]); ret[1] = new RealAlgebraicNumber(ring, aret[1]); ret[2] = new RealAlgebraicNumber(ring, aret[2]); return ret; } } jas-2.5/src/edu/jas/root/ComplexAlgebraicNumber.java0000644000175000017500000003101612014234362022662 0ustar giovannigiovanni/* * $Id: ComplexAlgebraicNumber.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.root; // import edu.jas.structure.RingElem; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.kern.PrettyPrint; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; import edu.jas.structure.NotInvertibleException; /** * Complex algebraic number class based on AlgebraicNumber. Objects of this * class are immutable. * @author Heinz Kredel */ public class ComplexAlgebraicNumber & Rational> /*extends AlgebraicNumber*/ implements GcdRingElem> { /** * Representing AlgebraicNumber. */ public final AlgebraicNumber> number; /** * Ring part of the data structure. */ public final ComplexAlgebraicRing ring; /** * The constructor creates a ComplexAlgebraicNumber object from * ComplexAlgebraicRing modul and a GenPolynomial value. * @param r ring ComplexAlgebraicRing. * @param a value GenPolynomial. */ public ComplexAlgebraicNumber(ComplexAlgebraicRing r, GenPolynomial> a) { number = new AlgebraicNumber>(r.algebraic, a); ring = r; } /** * The constructor creates a ComplexAlgebraicNumber object from * ComplexAlgebraicRing modul and a AlgebraicNumber value. * @param r ring ComplexAlgebraicRing. * @param a value AlgebraicNumber. */ public ComplexAlgebraicNumber(ComplexAlgebraicRing r, AlgebraicNumber> a) { number = a; ring = r; } /** * The constructor creates a ComplexAlgebraicNumber object from a * GenPolynomial object module. * @param r ring ComplexAlgebraicRing. */ public ComplexAlgebraicNumber(ComplexAlgebraicRing r) { this(r, r.algebraic.getZERO()); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public ComplexAlgebraicRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public ComplexAlgebraicNumber copy() { return new ComplexAlgebraicNumber(ring, number); } /** * Is ComplexAlgebraicNumber zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return number.isZERO(); } /** * Is ComplexAlgebraicNumber one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return number.isONE(); } /** * Is ComplexAlgebraicNumber unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { return number.isUnit(); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { if (PrettyPrint.isTrue()) { return "{ " + number.toString() + " }"; } return "Complex" + number.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return number.toScript(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * ComplexAlgebraicNumber comparison. * @param b ComplexAlgebraicNumber. * @return sign(this-b). */ //JAVA6only: @Override public int compareTo(ComplexAlgebraicNumber b) { int s = 0; if (number.ring != b.number.ring) { // avoid compareTo if possible s = number.ring.modul.compareTo(b.number.ring.modul); System.out.println("s_mod = " + s); } if (s != 0) { return s; } s = number.compareTo(b.number); // TODO //System.out.println("s_real = " + s); return s; } /** * ComplexAlgebraicNumber comparison. * @param b AlgebraicNumber. * @return polynomial sign(this-b). */ public int compareTo(AlgebraicNumber> b) { int s = number.compareTo(b); //System.out.println("s_algeb = " + s); return s; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof ComplexAlgebraicNumber)) { return false; } ComplexAlgebraicNumber a = null; try { a = (ComplexAlgebraicNumber) b; } catch (ClassCastException e) { } if (a == null) { return false; } if (!ring.equals(a.ring)) { return false; } return number.equals(a.number); } /** * Hash code for this ComplexAlgebraicNumber. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * number.val.hashCode() + ring.hashCode(); } /** * ComplexAlgebraicNumber absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public ComplexAlgebraicNumber abs() { if (this.signum() < 0) { return new ComplexAlgebraicNumber(ring, number.negate()); } return this; } /** * ComplexAlgebraicNumber summation. * @param S ComplexAlgebraicNumber. * @return this+S. */ public ComplexAlgebraicNumber sum(ComplexAlgebraicNumber S) { return new ComplexAlgebraicNumber(ring, number.sum(S.number)); } /** * ComplexAlgebraicNumber summation. * @param c complex polynomial. * @return this+c. */ public ComplexAlgebraicNumber sum(GenPolynomial> c) { return new ComplexAlgebraicNumber(ring, number.sum(c)); } /** * ComplexAlgebraicNumber summation. * @param c algebraic number. * @return this+c. */ public ComplexAlgebraicNumber sum(AlgebraicNumber> c) { return new ComplexAlgebraicNumber(ring, number.sum(c)); } /** * ComplexAlgebraicNumber summation. * @param c coefficient. * @return this+c. */ public ComplexAlgebraicNumber sum(Complex c) { return new ComplexAlgebraicNumber(ring, number.sum(c)); } /** * ComplexAlgebraicNumber negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public ComplexAlgebraicNumber negate() { return new ComplexAlgebraicNumber(ring, number.negate()); } /** * ComplexAlgebraicNumber subtraction. * @param S ComplexAlgebraicNumber. * @return this-S. */ public ComplexAlgebraicNumber subtract(ComplexAlgebraicNumber S) { return new ComplexAlgebraicNumber(ring, number.subtract(S.number)); } /** * ComplexAlgebraicNumber division. * @param S ComplexAlgebraicNumber. * @return this/S. */ public ComplexAlgebraicNumber divide(ComplexAlgebraicNumber S) { return multiply(S.inverse()); } /** * ComplexAlgebraicNumber inverse. * @see edu.jas.structure.RingElem#inverse() * @throws NotInvertibleException if the element is not invertible. * @return S with S = 1/this if defined. */ public ComplexAlgebraicNumber inverse() { return new ComplexAlgebraicNumber(ring, number.inverse()); } /** * ComplexAlgebraicNumber remainder. * @param S ComplexAlgebraicNumber. * @return this - (this/S)*S. */ public ComplexAlgebraicNumber remainder(ComplexAlgebraicNumber S) { return new ComplexAlgebraicNumber(ring, number.remainder(S.number)); } /** * ComplexAlgebraicNumber multiplication. * @param S ComplexAlgebraicNumber. * @return this*S. */ public ComplexAlgebraicNumber multiply(ComplexAlgebraicNumber S) { return new ComplexAlgebraicNumber(ring, number.multiply(S.number)); } /** * ComplexAlgebraicNumber multiplication. * @param c coefficient. * @return this*c. */ public ComplexAlgebraicNumber multiply(Complex c) { return new ComplexAlgebraicNumber(ring, number.multiply(c)); } /** * ComplexAlgebraicNumber multiplication. * @param c polynomial. * @return this*c. */ public ComplexAlgebraicNumber multiply(GenPolynomial> c) { return new ComplexAlgebraicNumber(ring, number.multiply(c)); } /** * ComplexAlgebraicNumber monic. * @return this with monic value part. */ public ComplexAlgebraicNumber monic() { return new ComplexAlgebraicNumber(ring, number.monic()); } /** * ComplexAlgebraicNumber greatest common divisor. * @param S ComplexAlgebraicNumber. * @return gcd(this,S). */ public ComplexAlgebraicNumber gcd(ComplexAlgebraicNumber S) { return new ComplexAlgebraicNumber(ring, number.gcd(S.number)); } /** * ComplexAlgebraicNumber extended greatest common divisor. * @param S ComplexAlgebraicNumber. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ @SuppressWarnings("unchecked") public ComplexAlgebraicNumber[] egcd(ComplexAlgebraicNumber S) { AlgebraicNumber>[] aret = number.egcd(S.number); ComplexAlgebraicNumber[] ret = new ComplexAlgebraicNumber[3]; ret[0] = new ComplexAlgebraicNumber(ring, aret[0]); ret[1] = new ComplexAlgebraicNumber(ring, aret[1]); ret[2] = new ComplexAlgebraicNumber(ring, aret[2]); return ret; } /** * ComplexAlgebraicNumber signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { try { Rectangle v = ring.engine.invariantRectangle(ring.root, ring.algebraic.modul, number.val); ring.setRoot(v); Complex c = v.getCenter(); return c.signum(); } catch (InvalidBoundaryException e) { // should not happen e.printStackTrace(); throw new RuntimeException(e); } } /** * ComplexAlgebraicNumber magnitude. * @return |this| as complex rational number. */ public Complex magnitude() { try { Rectangle v = ring.engine.invariantMagnitudeRectangle(ring.root, ring.algebraic.modul, number.val, ring.getEps()); ring.setRoot(v); //System.out.println("new v = " + v); Complex ev = ring.engine.complexRectangleMagnitude(v, ring.algebraic.modul, number.val); //, ring.eps); //C re = ev.getRe(); //if ( (Object) re instanceof Rational) { // true by type parameter BigRational er = ev.getRe().getRational(); BigRational ei = ev.getIm().getRational(); ComplexRing cr = new ComplexRing(er.factory()); return new Complex(cr, er, ei); //} else { // throw new RuntimeException("Rational expected, but was " + ev.getClass()); //} } catch (InvalidBoundaryException e) { // should not happen e.printStackTrace(); throw new RuntimeException(e); } } /** * ComplexAlgebraicNumber magnitude. * @return |this| as complex big decimal. */ public Complex decimalMagnitude() { Complex cr = magnitude(); ComplexRing dr = new ComplexRing(BigDecimal.ZERO); return new Complex(dr, new BigDecimal(cr.getRe()), new BigDecimal(cr.getIm())); } } jas-2.5/src/edu/jas/root/RealRootTuple.java0000644000175000017500000001235312014234362021054 0ustar giovannigiovanni/* * $Id: RealRootTuple.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.root; import java.io.Serializable; import java.util.List; import java.util.ArrayList; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.structure.ElemFactory; import edu.jas.structure.RingElem; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * RealAlgebraicNumber root tuple. * @param coefficient type. * @author Heinz Kredel */ public class RealRootTuple & Rational> implements Serializable { /** * Tuple of RealAlgebraicNumbers. */ public final List> tuple; /** * Constructor. * @param t list of roots. */ public RealRootTuple(List> t) { if ( t == null ) { throw new IllegalArgumentException("null tuple not allowed"); } tuple = t; } /** * String representation of tuple. * @see java.lang.Object#toString() */ @Override public String toString() { return tuple.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Rectangle. */ public String toScript() { // Python case StringBuffer sb = new StringBuffer("["); boolean first = true; for (RealAlgebraicNumber r : tuple) { if ( first ) { first = false; } else { sb.append(","); } sb.append(r.toScript()); } return sb.toString(); } /* * Contains a point. * @param c point. * @return true if c is contained in this rectangle, else false. public boolean contains(Complex c) { Complex ll = getSW(); Complex ur = getSW(); return c.getRe().compareTo(ll.getRe()) < 0 || c.getIm().compareTo(ll.getIm()) < 0 || c.getRe().compareTo(ur.getRe()) > 0 || c.getIm().compareTo(ur.getIm()) > 0; } */ /* * Random point of recatangle. * @return a random point contained in this rectangle. public Complex randomPoint() { Complex sw = getSW(); Complex se = getSE(); Complex nw = getNW(); Complex r = sw.factory().random(13); C dr = se.getRe().subtract(sw.getRe()); // >= 0 C di = nw.getIm().subtract(sw.getIm()); // >= 0 C rr = r.getRe().abs(); C ri = r.getIm().abs(); C one = ((RingFactory)dr.factory()).getONE(); if ( !rr.isZERO() ) { if ( rr.compareTo(one) > 0 ) { rr = rr.inverse(); } } if ( !ri.isZERO() ) { if ( ri.compareTo(one) > 0 ) { ri = ri.inverse(); } } // 0 <= rr, ri <= 1 rr = rr.multiply(dr); ri = ri.multiply(di); Complex rp = new Complex(sw.factory(),rr,ri); //System.out.println("rp = " + rp); rp = sw.sum(rp); return rp; } */ /** * Copy this. * @return a copy of this. */ public RealRootTuple copy() { return new RealRootTuple(new ArrayList>(tuple)); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { RealRootTuple a = null; try { a = (RealRootTuple) b; } catch (ClassCastException e) { } if (a == null) { return false; } return tuple.equals(a.tuple); } /** * Hash code for this Rectangle. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return tuple.hashCode(); } /** * Rational approximation of each coordinate. * @return list of coordinate points. */ public List getRational() { List center = new ArrayList(tuple.size()); for ( RealAlgebraicNumber rr : tuple ) { BigRational r = rr.getRational(); center.add(r); } return center; } /** * Decimal approximation of each coordinate. * @return list of coordinate points. */ public List decimalMagnitude() { List center = new ArrayList(tuple.size()); for ( RealAlgebraicNumber rr : tuple ) { BigDecimal r = rr.decimalMagnitude(); center.add(r); } return center; } /** * Rational Length. * @return max |v_i|; */ public BigRational rationalLength() { BigRational len = new BigRational(); for ( RealAlgebraicNumber rr : tuple ) { BigRational r = rr.ring.root.rationalLength(); int s = len.compareTo(r); if ( s < 0 ) { len = r; } } return len; } /** * Signum. * @return ?; */ public int signum() { int s = 0; for ( RealAlgebraicNumber rr : tuple ) { int rs = rr.signum(); if ( rs != 0 ) { s = rs; } } return s; } } jas-2.5/src/edu/jas/root/RealRootsAbstract.java0000644000175000017500000005775212063147054021732 0ustar giovannigiovanni/* * $Id: RealRootsAbstract.java 4315 2012-12-15 19:23:25Z kredel $ */ package edu.jas.root; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.UnaryFunctor; /** * Real roots abstract class. * @param coefficient type. * @author Heinz Kredel */ public abstract class RealRootsAbstract & Rational> implements RealRoots { private static final Logger logger = Logger.getLogger(RealRootsAbstract.class); //private static boolean debug = logger.isDebugEnabled(); /** * Real root bound. With f(M) * f(-M) != 0. * @param f univariate polynomial. * @return M such that -M < root(f) < M. */ public C realRootBound(GenPolynomial f) { if (f == null) { return null; } RingFactory cfac = f.ring.coFac; C M = cfac.getONE(); if (f.isZERO()) { return M; } if (f.isConstant()) { M = f.leadingBaseCoefficient().abs().sum(cfac.getONE()); return M; } C a = f.leadingBaseCoefficient().abs(); for (C c : f.getMap().values()) { C d = c.abs().divide(a); if (M.compareTo(d) < 0) { M = d; } } // works also without this case, only for optimization // to use integral number interval end points // could be obsolete: can fail if real root is in interval [r,r+1] // for too low precision or too big r, since r is approximation /* if (false&&(Object) M instanceof RealAlgebraicNumber) { RealAlgebraicNumber Mr = (RealAlgebraicNumber) M; BigRational r = Mr.magnitude(); //logger.info("rational root bound: " + r); BigInteger i = new BigInteger(r.numerator().divide(r.denominator())); i = i.sum(BigInteger.ONE); //logger.info("integer root bound: " + i); //M = cfac.fromInteger(r.numerator()).divide(cfac.fromInteger(r.denominator())); M = cfac.fromInteger(i.getVal()); M = M.sum(f.ring.coFac.getONE()); logger.info("root bound: " + M); //System.out.println("M = " + M); return M; } */ BigRational r = M.getRational(); logger.info("rational root bound: " + r); BigInteger i = new BigInteger(r.numerator().divide(r.denominator())); i = i.sum(BigInteger.ONE); // ceiling M = cfac.fromInteger(i.getVal()); M = M.sum(f.ring.coFac.getONE()); logger.info("integer root bound: " + M); //System.out.println("M = " + M); return M; } /** * Magnitude bound. * @param iv interval. * @param f univariate polynomial. * @return B such that |f(c)| < B for c in iv. */ public C magnitudeBound(Interval iv, GenPolynomial f) { if (f == null) { return null; } if (f.isZERO()) { return f.ring.coFac.getONE(); } if (f.isConstant()) { return f.leadingBaseCoefficient().abs(); } GenPolynomial fa = f.map(new UnaryFunctor() { public C eval(C a) { return a.abs(); } }); //System.out.println("fa = " + fa); C M = iv.left.abs(); if (M.compareTo(iv.right.abs()) < 0) { M = iv.right.abs(); } //System.out.println("M = " + M); RingFactory cfac = f.ring.coFac; C B = PolyUtil. evaluateMain(cfac, fa, M); // works also without this case, only for optimization // to use rational number interval end points // can fail if real root is in interval [r,r+1] // for too low precision or too big r, since r is approximation if ((Object) B instanceof RealAlgebraicNumber) { RealAlgebraicNumber Br = (RealAlgebraicNumber) B; BigRational r = Br.magnitude(); B = cfac.fromInteger(r.numerator()).divide(cfac.fromInteger(r.denominator())); } //System.out.println("B = " + B); return B; } /** * Bi-section point. * @param iv interval with f(left) * f(right) != 0. * @param f univariate polynomial, non-zero. * @return a point c in the interval iv such that f(c) != 0. */ public C bisectionPoint(Interval iv, GenPolynomial f) { if (f == null) { return null; } RingFactory cfac = f.ring.coFac; C two = cfac.fromInteger(2); C c = iv.left.sum(iv.right); c = c.divide(two); if (f.isZERO() || f.isConstant()) { return c; } C m = PolyUtil. evaluateMain(cfac, f, c); while (m.isZERO()) { C d = iv.left.sum(c); d = d.divide(two); if (d.equals(c)) { d = iv.right.sum(c); d = d.divide(two); if (d.equals(c)) { throw new RuntimeException("should not happen " + iv); } } c = d; m = PolyUtil. evaluateMain(cfac, f, c); //System.out.println("c = " + c); } //System.out.println("c = " + c); return c; } /** * Isolating intervals for the real roots. * @param f univariate polynomial. * @return a list of isolating intervalls for the real roots of f. */ public abstract List> realRoots(GenPolynomial f); /** * Isolating intervals for the real roots. * @param f univariate polynomial. * @param eps requested intervals length. * @return a list of isolating intervals v such that |v| < eps. */ public List> realRoots(GenPolynomial f, C eps) { List> iv = realRoots(f); return refineIntervals(iv, f, eps); } /** * Isolating intervals for the real roots. * @param f univariate polynomial. * @param eps requested intervals length. * @return a list of isolating intervals v such that |v| < eps. */ public List> realRoots(GenPolynomial f, BigRational eps) { C e = f.ring.coFac.parse(eps.toString()); return realRoots(f, e); } /** * Sign changes on interval bounds. * @param iv root isolating interval with f(left) * f(right) != 0. * @param f univariate polynomial. * @return true if f(left) * f(right) < 0, else false */ public boolean signChange(Interval iv, GenPolynomial f) { if (f == null) { return false; } RingFactory cfac = f.ring.coFac; C l = PolyUtil. evaluateMain(cfac, f, iv.left); C r = PolyUtil. evaluateMain(cfac, f, iv.right); return l.signum() * r.signum() < 0; } /** * Number of real roots in interval. * @param iv interval with f(left) * f(right) != 0. * @param f univariate polynomial. * @return number of real roots of f in I. */ public abstract long realRootCount(Interval iv, GenPolynomial f); /** * Half interval. * @param iv root isolating interval with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @return a new interval v such that |v| < |iv|/2. */ public Interval halfInterval(Interval iv, GenPolynomial f) { if (f == null || f.isZERO()) { return iv; } C len = iv.length(); C two = len.factory().fromInteger(2); C eps = len.divide(two); return refineInterval(iv, f, eps); } /** * Refine interval. * @param iv root isolating interval with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param eps requested interval length. * @return a new interval v such that |v| < eps. */ public Interval refineInterval(Interval iv, GenPolynomial f, C eps) { if (f == null || f.isZERO() || f.isConstant() || eps == null) { return iv; } if (iv.length().compareTo(eps) < 0) { return iv; } RingFactory cfac = f.ring.coFac; C two = cfac.fromInteger(2); Interval v = iv; while (v.length().compareTo(eps) >= 0) { C c = v.left.sum(v.right); c = c.divide(two); //System.out.println("c = " + c); //c = RootUtil.bisectionPoint(v,f); if (PolyUtil. evaluateMain(cfac, f, c).isZERO()) { v = new Interval(c, c); break; } Interval iv1 = new Interval(v.left, c); if (signChange(iv1, f)) { v = iv1; } else { v = new Interval(c, v.right); } } return v; } /** * Refine intervals. * @param V list of isolating intervals with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param eps requested intervals length. * @return a list of new intervals v such that |v| < eps. */ public List> refineIntervals(List> V, GenPolynomial f, C eps) { if (f == null || f.isZERO() || f.isConstant() || eps == null) { return V; } List> IV = new ArrayList>(); for (Interval v : V) { Interval iv = refineInterval(v, f, eps); IV.add(iv); } return IV; } /** * Invariant interval for algebraic number sign. * @param iv root isolating interval for f, with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @return v with v a new interval contained in iv such that g(v) != 0. */ public abstract Interval invariantSignInterval(Interval iv, GenPolynomial f, GenPolynomial g); /** * Real algebraic number sign. * @param iv root isolating interval for f, with f(left) * f(right) < 0, * with iv such that g(iv) != 0. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @return sign(g(iv)) . */ public int realIntervalSign(Interval iv, GenPolynomial f, GenPolynomial g) { if (g == null || g.isZERO()) { return 0; } if (f == null || f.isZERO() || f.isConstant()) { return g.signum(); } if (g.isConstant()) { return g.signum(); } RingFactory cfac = f.ring.coFac; C c = iv.left.sum(iv.right); c = c.divide(cfac.fromInteger(2)); C ev = PolyUtil. evaluateMain(cfac, g, c); //System.out.println("ev = " + ev); return ev.signum(); } /** * Real algebraic number sign. * @param iv root isolating interval for f, with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @return sign(g(v)), with v a new interval contained in iv such that g(v) * != 0. */ public int realSign(Interval iv, GenPolynomial f, GenPolynomial g) { if (g == null || g.isZERO()) { return 0; } if (f == null || f.isZERO() || f.isConstant()) { return g.signum(); } if (g.isConstant()) { return g.signum(); } Interval v = invariantSignInterval(iv, f, g); return realIntervalSign(v, f, g); } /** * Invariant interval for algebraic number magnitude. * @param iv root isolating interval for f, with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @param eps length limit for interval length. * @return v with v a new interval contained in iv such that |g(a) - g(b)| * < eps for a, b in v in iv. */ public Interval invariantMagnitudeInterval(Interval iv, GenPolynomial f, GenPolynomial g, C eps) { Interval v = iv; if (g == null || g.isZERO()) { return v; } if (g.isConstant()) { return v; } if (f == null || f.isZERO() || f.isConstant()) { // ? return v; } GenPolynomial gp = PolyUtil. baseDeriviative(g); //System.out.println("g = " + g); //System.out.println("gp = " + gp); C B = magnitudeBound(iv, gp); //System.out.println("B = " + B); RingFactory cfac = f.ring.coFac; C two = cfac.fromInteger(2); while (B.multiply(v.length()).compareTo(eps) >= 0) { C c = v.left.sum(v.right); c = c.divide(two); Interval im = new Interval(c, v.right); if (signChange(im, f)) { v = im; } else { v = new Interval(v.left, c); } //System.out.println("v = " + v.toDecimal()); } return v; } /** * Real algebraic number magnitude. * @param iv root isolating interval for f, with f(left) * f(right) < 0, * with iv such that |g(a) - g(b)| < eps for a, b in iv. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @return g(iv) . */ public C realIntervalMagnitude(Interval iv, GenPolynomial f, GenPolynomial g) { if (g.isZERO() || g.isConstant()) { return g.leadingBaseCoefficient(); } RingFactory cfac = f.ring.coFac; //if (false) { // C c = iv.left.sum(iv.right); // c = c.divide(cfac.fromInteger(2)); // C ev = PolyUtil. evaluateMain(cfac, g, c); // return ev; //} C evl = PolyUtil. evaluateMain(cfac, g, iv.left); C evr = PolyUtil. evaluateMain(cfac, g, iv.right); C ev = evl; if (evl.compareTo(evr) <= 0) { ev = evr; } //System.out.println("ev = " + ev + ", evl = " + evl + ", evr = " + evr + ", iv = " + iv); return ev; } /** * Real algebraic number magnitude. * @param iv root isolating interval for f, with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @param eps length limit for interval length. * @return g(iv) . */ public C realMagnitude(Interval iv, GenPolynomial f, GenPolynomial g, C eps) { if (g.isZERO() || g.isConstant()) { return g.leadingBaseCoefficient(); } Interval v = invariantMagnitudeInterval(iv, f, g, eps); return realIntervalMagnitude(v, f, g); } /** * Approximate real root. * @param iv real root isolating interval with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param eps requested interval length. * @return a decimal approximation d such that |d-v| < eps, for f(v) = 0, * v real. */ public BigDecimal approximateRoot(Interval iv, GenPolynomial f, C eps) throws NoConvergenceException { if (iv == null) { throw new IllegalArgumentException("null interval not allowed"); } BigDecimal d = iv.toDecimal(); if (f == null || f.isZERO() || f.isConstant() || eps == null) { return d; } if (iv.length().compareTo(eps) < 0) { return d; } BigDecimal left = new BigDecimal(iv.left.getRational()); BigDecimal right = new BigDecimal(iv.right.getRational()); BigRational reps = eps.getRational(); BigDecimal e = new BigDecimal(reps); BigDecimal q = new BigDecimal("0.25"); //System.out.println("left = " + left); //System.out.println("right = " + right); e = e.multiply(d); // relative error //System.out.println("e = " + e); BigDecimal dc = BigDecimal.ONE; // polynomials with decimal coefficients GenPolynomialRing dfac = new GenPolynomialRing(dc, f.ring); GenPolynomial df = PolyUtil. decimalFromRational(dfac, f); GenPolynomial fp = PolyUtil. baseDeriviative(f); GenPolynomial dfp = PolyUtil. decimalFromRational(dfac, fp); // Newton Raphson iteration: x_{n+1} = x_n - f(x_n)/f'(x_n) int i = 0; final int MITER = 50; int dir = 0; while (i++ < MITER) { BigDecimal fx = PolyUtil. evaluateMain(dc, df, d); // f(d) if (fx.isZERO()) { return d; } BigDecimal fpx = PolyUtil. evaluateMain(dc, dfp, d); // f'(d) if (fpx.isZERO()) { throw new NoConvergenceException("zero deriviative should not happen"); } BigDecimal x = fx.divide(fpx); BigDecimal dx = d.subtract(x); //System.out.println("dx = " + dx + ", d = " + d); if (d.subtract(dx).abs().compareTo(e) <= 0) { return dx; } while (dx.compareTo(left) < 0 || dx.compareTo(right) > 0) { // dx < left: dx - left < 0 // dx > right: dx - right > 0 //System.out.println("trying to leave interval"); if (i++ > MITER) { // dx > right: dx - right > 0 throw new NoConvergenceException("no convergence after " + i + " steps"); } if (i > MITER / 2 && dir == 0) { BigDecimal sd = new BigDecimal(iv.randomPoint().getRational()); d = sd; x = sd.getZERO(); logger.info("trying new random starting point " + d); i = 0; dir = 1; } if (i > MITER / 2 && dir == 1) { BigDecimal sd = new BigDecimal(iv.randomPoint().getRational()); d = sd; x = sd.getZERO(); logger.info("trying new random starting point " + d); //i = 0; dir = 2; // end } x = x.multiply(q); // x * 1/4 dx = d.subtract(x); //System.out.println(" x = " + x); //System.out.println("dx = " + dx); } d = dx; } throw new NoConvergenceException("no convergence after " + i + " steps"); } /** * Approximate real roots. * @param f univariate polynomial, non-zero. * @param eps requested interval length. * @return a list of decimal approximations d such that |d-v| < eps for * all real v with f(v) = 0. */ public List approximateRoots(GenPolynomial f, C eps) { List> iv = realRoots(f); List roots = new ArrayList(iv.size()); for (Interval i : iv) { BigDecimal r = null; //approximateRoot(i, f, eps); roots.add(r); while (r == null) { try { r = approximateRoot(i, f, eps); roots.add(r); } catch (NoConvergenceException e) { // fall back to exact algorithm //System.out.println("" + e); C len = i.length(); len = len.divide(f.ring.coFac.fromInteger(1000)); i = refineInterval(i, f, len); logger.info("fall back rootRefinement = " + i); } } } return roots; } /** * Test if x is an approximate real root. * @param x approximate real root. * @param f univariate polynomial, non-zero. * @param eps requested interval length. * @return true if x is a decimal approximation of a real v with f(v) = 0 * with |d-v| < eps, else false. */ public boolean isApproximateRoot(BigDecimal x, GenPolynomial f, C eps) { if (x == null) { throw new IllegalArgumentException("null root not allowed"); } if (f == null || f.isZERO() || f.isConstant() || eps == null) { return true; } BigDecimal e = new BigDecimal(eps.getRational()); e = e.multiply(new BigDecimal("1000")); // relax BigDecimal dc = BigDecimal.ONE; // polynomials with decimal coefficients GenPolynomialRing dfac = new GenPolynomialRing(dc, f.ring); GenPolynomial df = PolyUtil. decimalFromRational(dfac, f); GenPolynomial fp = PolyUtil. baseDeriviative(f); GenPolynomial dfp = PolyUtil. decimalFromRational(dfac, fp); // return isApproximateRoot(x, df, dfp, e); } /** * Test if x is an approximate real root. * @param x approximate real root. * @param f univariate polynomial, non-zero. * @param fp univariate polynomial, non-zero, deriviative of f. * @param eps requested interval length. * @return true if x is a decimal approximation of a real v with f(v) = 0 * with |d-v| < eps, else false. */ public boolean isApproximateRoot(BigDecimal x, GenPolynomial f, GenPolynomial fp, BigDecimal eps) { if (x == null) { throw new IllegalArgumentException("null root not allowed"); } if (f == null || f.isZERO() || f.isConstant() || eps == null) { return true; } BigDecimal dc = BigDecimal.ONE; // only for clarity // f(x) BigDecimal fx = PolyUtil. evaluateMain(dc, f, x); //System.out.println("fx = " + fx); if (fx.isZERO()) { return true; } // f'(x) BigDecimal fpx = PolyUtil. evaluateMain(dc, fp, x); // f'(d) //System.out.println("fpx = " + fpx); if (fpx.isZERO()) { return false; } BigDecimal d = fx.divide(fpx); if (d.isZERO()) { return true; } if (d.abs().compareTo(eps) <= 0) { return true; } System.out.println("x = " + x); System.out.println("d = " + d); return false; } /** * Test if each x in R is an approximate real root. * @param R ist of approximate real roots. * @param f univariate polynomial, non-zero. * @param eps requested interval length. * @return true if each x in R is a decimal approximation of a real v with * f(v) = 0 with |d-v| < eps, else false. */ public boolean isApproximateRoot(List R, GenPolynomial f, C eps) { if (R == null) { throw new IllegalArgumentException("null root not allowed"); } if (f == null || f.isZERO() || f.isConstant() || eps == null) { return true; } BigDecimal e = new BigDecimal(eps.getRational()); e = e.multiply(new BigDecimal("1000")); // relax BigDecimal dc = BigDecimal.ONE; // polynomials with decimal coefficients GenPolynomialRing dfac = new GenPolynomialRing(dc, f.ring); GenPolynomial df = PolyUtil. decimalFromRational(dfac, f); GenPolynomial fp = PolyUtil. baseDeriviative(f); GenPolynomial dfp = PolyUtil. decimalFromRational(dfac, fp); for (BigDecimal x : R) { if (!isApproximateRoot(x, df, dfp, e)) { return false; } } return true; } } jas-2.5/src/edu/jas/root/PolyUtilRoot.java0000644000175000017500000003334412004511002020727 0ustar giovannigiovanni/* * $Id: PolyUtilRoot.java 4063 2012-07-27 13:05:07Z kredel $ */ package edu.jas.root; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.Rational; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.UnaryFunctor; /** * Polynomial utilities related to real and complex roots. * @author Heinz Kredel */ public class PolyUtilRoot { private static final Logger logger = Logger.getLogger(PolyUtilRoot.class); private static boolean debug = logger.isDebugEnabled(); /** * Convert to RealAlgebraicNumber coefficients. Represent as polynomial with * RealAlgebraicNumber coefficients, C is e.g. ModInteger or BigRational. * @param pfac result polynomial factory. * @param A polynomial with C coefficients to be converted. * @return polynomial with RealAlgebraicNumber<C> coefficients. */ public static & Rational> GenPolynomial> convertToAlgebraicCoefficients( GenPolynomialRing> pfac, GenPolynomial A) { RealAlgebraicRing afac = (RealAlgebraicRing) pfac.coFac; if (debug) { logger.info("afac = " + afac); } return PolyUtil.> map(pfac, A, new CoeffToReAlg(afac)); } /** * Convert to recursive RealAlgebraicNumber coefficients. Represent as * polynomial with recursive RealAlgebraicNumber coefficients, C is e.g. * ModInteger or BigRational. * @param depth recursion depth of RealAlgebraicNumber coefficients. * @param pfac result polynomial factory. * @param A polynomial with C coefficients to be converted. * @return polynomial with RealAlgebraicNumber<C> coefficients. */ public static & Rational> GenPolynomial> convertToRecAlgebraicCoefficients( int depth, GenPolynomialRing> pfac, GenPolynomial A) { RealAlgebraicRing afac = (RealAlgebraicRing) pfac.coFac; return PolyUtil.> map(pfac, A, new CoeffToRecReAlg(depth, afac)); } /** * Convert to RealAlgebraicNumber coefficients. Represent as polynomial with * RealAlgebraicNumber coefficients, C is e.g. ModInteger or BigRational. * @param pfac result polynomial factory. * @param A recursive polynomial with GenPolynomial<BigInteger> * coefficients to be converted. * @return polynomial with RealAlgebraicNumber<C> coefficients. */ public static & Rational> GenPolynomial> convertRecursiveToAlgebraicCoefficients( GenPolynomialRing> pfac, GenPolynomial> A) { RealAlgebraicRing afac = (RealAlgebraicRing) pfac.coFac; return PolyUtil., RealAlgebraicNumber> map(pfac, A, new PolyToReAlg(afac)); } /** * Convert to AlgebraicNumber coefficients. Represent as polynomial with * AlgebraicNumber coefficients. * @param afac result polynomial factory. * @param A polynomial with RealAlgebraicNumber<C> coefficients to be * converted. * @return polynomial with AlgebraicNumber<C> coefficients. */ public static & Rational> GenPolynomial> algebraicFromRealCoefficients( GenPolynomialRing> afac, GenPolynomial> A) { AlgebraicNumberRing cfac = (AlgebraicNumberRing) afac.coFac; return PolyUtil., AlgebraicNumber> map(afac, A, new AlgFromRealCoeff( cfac)); } /** * Convert to RealAlgebraicNumber coefficients. Represent as polynomial with * RealAlgebraicNumber coefficients. * @param rfac result polynomial factory. * @param A polynomial with AlgebraicNumber<C> coefficients to be * converted. * @return polynomial with RealAlgebraicNumber<C> coefficients. */ public static & Rational> GenPolynomial> realFromAlgebraicCoefficients( GenPolynomialRing> rfac, GenPolynomial> A) { RealAlgebraicRing cfac = (RealAlgebraicRing) rfac.coFac; return PolyUtil., RealAlgebraicNumber> map(rfac, A, new RealFromAlgCoeff( cfac)); } /** * Convert to RealAlgebraicNumber coefficients. Represent as polynomial with * RealAlgebraicNumber coefficients, C is e.g. BigRational. * @param pfac result polynomial factory. * @param A polynomial with C coefficients to be converted. * @return polynomial with RealAlgebraicNumber<C> coefficients. */ public static & Rational> GenPolynomial> convertToRealCoefficients( GenPolynomialRing> pfac, GenPolynomial A) { RealAlgebraicRing afac = (RealAlgebraicRing) pfac.coFac; return PolyUtil.> map(pfac, A, new CoeffToReal(afac)); } /** * Convert to ComplexAlgebraicNumber coefficients. Represent as polynomial * with ComplexAlgebraicNumber coefficients, C is e.g. BigRational. * @param pfac result polynomial factory. * @param A polynomial with C coefficients to be converted. * @return polynomial with ComplexAlgebraicNumber<C> coefficients. */ public static & Rational> GenPolynomial> convertToComplexCoefficients( GenPolynomialRing> pfac, GenPolynomial A) { ComplexAlgebraicRing afac = (ComplexAlgebraicRing) pfac.coFac; return PolyUtil.> map(pfac, A, new CoeffToComplex(afac)); } /** * Convert to ComplexAlgebraicNumber coefficients. Represent as polynomial * with ComplexAlgebraicNumber coefficients, C is e.g. BigRational. * @param pfac result polynomial factory. * @param A polynomial with C coefficients to be converted. * @return polynomial with ComplexAlgebraicNumber<C> coefficients. */ public static & Rational> GenPolynomial> convertToComplexCoefficientsFromComplex( GenPolynomialRing> pfac, GenPolynomial> A) { ComplexAlgebraicRing afac = (ComplexAlgebraicRing) pfac.coFac; return PolyUtil., ComplexAlgebraicNumber> map(pfac, A, new CoeffToComplexFromComplex(afac)); } } /** * Polynomial to algebraic functor. */ class PolyToReAlg & Rational> implements UnaryFunctor, RealAlgebraicNumber> { final protected RealAlgebraicRing afac; public PolyToReAlg(RealAlgebraicRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } afac = fac; } public RealAlgebraicNumber eval(GenPolynomial c) { if (c == null) { return afac.getZERO(); } return new RealAlgebraicNumber(afac, c); } } /** * Coefficient to algebraic functor. */ class CoeffToReAlg & Rational> implements UnaryFunctor> { final protected RealAlgebraicRing afac; final protected GenPolynomial zero; public CoeffToReAlg(RealAlgebraicRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } afac = fac; GenPolynomialRing pfac = afac.algebraic.ring; zero = pfac.getZERO(); } public RealAlgebraicNumber eval(C c) { if (c == null) { return afac.getZERO(); } return new RealAlgebraicNumber(afac, zero.sum(c)); } } /** * Coefficient to recursive algebraic functor. */ class CoeffToRecReAlg & Rational> implements UnaryFunctor> { final protected List> lfac; final int depth; @SuppressWarnings("unchecked") public CoeffToRecReAlg(int depth, RealAlgebraicRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } RealAlgebraicRing afac = fac; this.depth = depth; lfac = new ArrayList>(this.depth); lfac.add(fac); for (int i = 1; i < this.depth; i++) { RingFactory rf = afac.algebraic.ring.coFac; if (!(rf instanceof RealAlgebraicRing)) { throw new IllegalArgumentException("fac depth to low"); } afac = (RealAlgebraicRing) (Object) rf; lfac.add(afac); } } @SuppressWarnings("unchecked") public RealAlgebraicNumber eval(C c) { if (c == null) { return lfac.get(0).getZERO(); } C ac = c; RealAlgebraicRing af = lfac.get(lfac.size() - 1); GenPolynomial zero = af.algebraic.ring.getZERO(); RealAlgebraicNumber an = new RealAlgebraicNumber(af, zero.sum(ac)); for (int i = lfac.size() - 2; i >= 0; i--) { af = lfac.get(i); zero = af.algebraic.ring.getZERO(); ac = (C) (Object) an; an = new RealAlgebraicNumber(af, zero.sum(ac)); } return an; } } /** * Coefficient to algebraic from real algebraic functor. */ class AlgFromRealCoeff & Rational> implements UnaryFunctor, AlgebraicNumber> { final protected AlgebraicNumberRing afac; public AlgFromRealCoeff(AlgebraicNumberRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } afac = fac; } public AlgebraicNumber eval(RealAlgebraicNumber c) { if (c == null) { return afac.getZERO(); } return c.number; } } /** * Coefficient to real algebriac from algebraic functor. */ class RealFromAlgCoeff & Rational> implements UnaryFunctor, RealAlgebraicNumber> { final protected RealAlgebraicRing rfac; public RealFromAlgCoeff(RealAlgebraicRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } rfac = fac; } public RealAlgebraicNumber eval(AlgebraicNumber c) { if (c == null) { return rfac.getZERO(); } return new RealAlgebraicNumber(rfac, c); } } /** * Coefficient to real algebraic functor. */ class CoeffToReal & Rational> implements UnaryFunctor> { final protected RealAlgebraicRing rfac; final protected AlgebraicNumber zero; public CoeffToReal(RealAlgebraicRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } rfac = fac; AlgebraicNumberRing afac = rfac.algebraic; zero = afac.getZERO(); } public RealAlgebraicNumber eval(C c) { if (c == null) { return rfac.getZERO(); } return new RealAlgebraicNumber(rfac, zero.sum(c)); } } /** * Coefficient to complex algebraic functor. */ class CoeffToComplex & Rational> implements UnaryFunctor> { final protected ComplexAlgebraicRing cfac; final protected AlgebraicNumber> zero; final protected ComplexRing cr; public CoeffToComplex(ComplexAlgebraicRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } cfac = fac; AlgebraicNumberRing> afac = cfac.algebraic; zero = afac.getZERO(); cr = (ComplexRing) afac.ring.coFac; } public ComplexAlgebraicNumber eval(C c) { if (c == null) { return cfac.getZERO(); } return new ComplexAlgebraicNumber(cfac, zero.sum(new Complex(cr, c))); } } /** * Coefficient to complex algebraic from complex functor. */ class CoeffToComplexFromComplex & Rational> implements UnaryFunctor, ComplexAlgebraicNumber> { final protected ComplexAlgebraicRing cfac; final protected AlgebraicNumber> zero; //final protected ComplexRing cr; public CoeffToComplexFromComplex(ComplexAlgebraicRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } cfac = fac; AlgebraicNumberRing> afac = cfac.algebraic; zero = afac.getZERO(); //cr = (ComplexRing) afac.ring.coFac; } public ComplexAlgebraicNumber eval(Complex c) { if (c == null) { return cfac.getZERO(); } return new ComplexAlgebraicNumber(cfac, zero.sum(c)); } } jas-2.5/src/edu/jas/root/Interval.java0000644000175000017500000001103312014234362020071 0ustar giovannigiovanni/* * $Id: Interval.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.root; import java.io.Serializable; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Interval. For example isolating interval for real roots. * @param coefficient type. * @author Heinz Kredel */ public class Interval & Rational > implements Serializable { //findbugs /** * left interval border. */ public final C left; /** * right interval border. */ public final C right; /** * Constructor. * @param left interval border. * @param right interval border. */ public Interval(C left, C right) { this.left = left; this.right = right; } /** * Constructor. * @param mid left and right interval border. */ public Interval(C mid) { this(mid, mid); } /** * String representation of Interval. * @see java.lang.Object#toString() */ @Override public String toString() { return "[" + left + ", " + right + "]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Interval. */ public String toScript() { // Python case return "[ " + left.toScript() + ", " + right.toScript() + " ]"; } /** * Copy this. * @return a copy of this. */ public Interval copy() { return new Interval(left, right); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof Interval)) { return false; } Interval a = null; try { a = (Interval) b; } catch (ClassCastException e) { return false; } return left.equals(a.left) && right.equals(a.right); } /** * Hash code for this Interval. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * left.hashCode() + right.hashCode(); } /** * Test if an element is contained in this interval. * @param c element to test. * @return true, if left <= b <= right; */ public boolean contains(C c) { return left.compareTo(c) <= 0 && c.compareTo(right) <= 0; } /** * Test if an interval is contained in this interval. * @param vc interval to test. * @return true, if left <= vc.left and vc.right <= right; */ public boolean contains(Interval vc) { return contains(vc.left) && contains(vc.right); } /** * Length. * @return |left-right|; */ public C length() { C m = right.subtract(left); return m.abs(); } /** * BigRational Length. * @return |left-right|; */ public BigRational rationalLength() { return length().getRational(); } /** * BigDecimal representation of Interval. */ public BigDecimal toDecimal() { BigDecimal l = new BigDecimal(left.getRational()); BigDecimal r = new BigDecimal(right.getRational()); BigDecimal two = new BigDecimal(2); BigDecimal v = l.sum(r).divide(two); return v; } /** * Rational middle point. * @return (left+right)/2; */ public BigRational rationalMiddle() { BigRational m = left.getRational().sum(right.getRational()); BigRational t = new BigRational(1L,2L); m = m.multiply(t); return m; } /** * Middle point. * @return (left+right)/2; */ public C middle() { C m = left.sum(right); C h = left.factory().parse("1/2"); m = m.multiply(h); return m; } /** * Random point of interval. * @return a random point contained in this interval. */ public C randomPoint() { C dr = right.subtract(left); RingFactory fac = (RingFactory)dr.factory(); C r = fac.random(13); r = r.abs(); if ( !r.isZERO() ) { if ( r.compareTo( fac.getONE() ) > 0 ) { r = r.inverse(); } } // 0 <= r <= 1 dr = dr.multiply(r); C rv = left.sum(dr); //System.out.println("rv = " + new BigDecimal(rv.getRational()) ); return rv; } } jas-2.5/src/edu/jas/root/Rectangle.java0000644000175000017500000002525312014234362020222 0ustar giovannigiovanni/* * $Id: Rectangle.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.root; import java.io.Serializable; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.structure.ElemFactory; import edu.jas.structure.RingElem; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Rectangle. For example isolating rectangle for complex roots. * @param coefficient type. * @author Heinz Kredel */ public class Rectangle & Rational> implements Serializable { /** * rectangle corners. */ public final Complex[] corners; /** * Constructor. * @param c array of corners. */ @SuppressWarnings("unchecked") /*package*/ Rectangle(Complex[] c) { if (c.length < 5) { corners = (Complex[]) new Complex[5]; for (int i = 0; i < 4; i++) { corners[i] = c[i]; } } else { corners = c; } if (corners[4] == null) { corners[4] = corners[0]; } } /** * Constructor. * @param mid corner. */ @SuppressWarnings("unchecked") public Rectangle(Complex mid) { this(mid, mid); } /** * Constructor. * @param sw corner. * @param ne corner. */ @SuppressWarnings("unchecked") public Rectangle(Complex sw, Complex ne) { this(new Complex(sw.ring, sw.getRe(), ne.getIm()), sw, new Complex(sw.ring, ne.getRe(), sw.getIm()), ne); } /** * Constructor. *
     *  nw|0 ne|3
     *  sw|1 se|2
     * 
* @param nw corner. * @param sw corner. * @param se corner. * @param ne corner. */ @SuppressWarnings("unchecked") public Rectangle(Complex nw, Complex sw, Complex se, Complex ne) { this((Complex[]) new Complex[] { nw, sw, se, ne }); } /** * String representation of Rectangle. * @see java.lang.Object#toString() */ @Override public String toString() { //return "[" + corners[0] + ", " + corners[1] + ", " + corners[2] + ", " + corners[3] + "]"; return "[" + corners[1] + ", " + corners[3] + "]"; //return centerApprox() + " = [" + corners[0] + ", " + corners[1] + ", " + corners[2] + ", " + corners[3] + "]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Rectangle. */ public String toScript() { // Python case //return "(" + corners[0] + ", " + corners[1] + ", " + corners[2] + ", " + corners[3] + ")"; return "(" + corners[1].toScript() + ", " + corners[3].toScript() + ")"; } /** * Get north west corner. * @return north west corner of this rectangle. */ public Complex getNW() { return corners[0]; } /** * Get south west corner. * @return south west corner of this rectangle. */ public Complex getSW() { return corners[1]; } /** * Get south east corner. * @return south east corner of this rectangle. */ public Complex getSE() { return corners[2]; } /** * Get north east corner. * @return north east corner of this rectangle. */ public Complex getNE() { return corners[3]; } /** * Exchange NW corner. * @param c new NW corner. * @return rectangle with north west corner c of this rectangle. */ public Rectangle exchangeNW(Complex c) { Complex d = getSE(); Complex sw = new Complex(c.factory(), c.getRe(), d.getIm()); Complex ne = new Complex(c.factory(), d.getRe(), c.getIm()); return new Rectangle(c, sw, d, ne); } /** * Exchange SW corner. * @param c new SW corner. * @return rectangle with south west corner c of this rectangle. */ public Rectangle exchangeSW(Complex c) { Complex d = getNE(); Complex nw = new Complex(c.factory(), c.getRe(), d.getIm()); Complex se = new Complex(c.factory(), d.getRe(), c.getIm()); return new Rectangle(nw, c, se, d); } /** * Exchange SE corner. * @param c new SE corner. * @return rectangle with south east corner c of this rectangle. */ public Rectangle exchangeSE(Complex c) { Complex d = getNW(); Complex sw = new Complex(c.factory(), d.getRe(), c.getIm()); Complex ne = new Complex(c.factory(), c.getRe(), d.getIm()); return new Rectangle(d, sw, c, ne); } /** * Exchange NE corner. * @param c new NE corner. * @return rectangle with north east corner c of this rectangle. */ public Rectangle exchangeNE(Complex c) { Complex d = getSW(); Complex nw = new Complex(c.factory(), d.getRe(), c.getIm()); Complex se = new Complex(c.factory(), c.getRe(), d.getIm()); return new Rectangle(nw, d, se, c); } /** * Contains a point. * @param c point. * @return true if c is contained in this rectangle, else false. */ public boolean contains(Complex c) { Complex ll = getSW(); Complex ur = getNE(); // ?? Fix ?? getSW(); C cre = c.getRe(); C cim = c.getIm(); return cre.compareTo(ll.getRe()) >= 0 && cim.compareTo(ll.getIm()) >= 0 && cre.compareTo(ur.getRe()) <= 0 && cim.compareTo(ur.getIm()) <= 0; } /** * Contains a rectangle. * @param r rectangle. * @return true if r is contained in this rectangle, else false. */ public boolean contains(Rectangle r) { return contains(r.getSW()) && contains(r.getNE()); // && contains(r.getSE()) && contains(r.getNW()) } /** * Random point of recatangle. * @return a random point contained in this rectangle. */ public Complex randomPoint() { Complex sw = getSW(); Complex se = getSE(); Complex nw = getNW(); Complex r = sw.factory().random(13); C dr = se.getRe().subtract(sw.getRe()); // >= 0 C di = nw.getIm().subtract(sw.getIm()); // >= 0 C rr = r.getRe().abs(); C ri = r.getIm().abs(); C one = ((RingFactory) dr.factory()).getONE(); if (!rr.isZERO()) { if (rr.compareTo(one) > 0) { rr = rr.inverse(); } } if (!ri.isZERO()) { if (ri.compareTo(one) > 0) { ri = ri.inverse(); } } // 0 <= rr, ri <= 1 rr = rr.multiply(dr); ri = ri.multiply(di); Complex rp = new Complex(sw.factory(), rr, ri); //System.out.println("rp = " + rp); rp = sw.sum(rp); return rp; } /** * Copy this. * @return a copy of this. */ public Rectangle copy() { return new Rectangle(corners); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof Rectangle)) { return false; } Rectangle a = null; try { a = (Rectangle) b; } catch (ClassCastException e) { } for (int i = 0; i < 4; i++) { if (!corners[i].equals(a.corners[i])) { return false; } } return true; } /** * Hash code for this Rectangle. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int hc = 0; for (int i = 0; i < 3; i++) { hc += 37 * corners[i].hashCode(); } return 37 * hc + corners[3].hashCode(); } /** * Complex center. * @return r + i m of the center. */ public Complex getCenter() { C r = corners[2].getRe().subtract(corners[1].getRe()); C m = corners[0].getIm().subtract(corners[1].getIm()); ElemFactory rf = r.factory(); C two = rf.fromInteger(2); r = r.divide(two); m = m.divide(two); r = corners[1].getRe().sum(r); m = corners[1].getIm().sum(m); return new Complex(corners[0].factory(), r, m); } /** * Complex of BigRational approximation of center. * @return r + i m as rational approximation of the center. */ public Complex getRationalCenter() { Complex cm = getCenter(); BigRational rs = cm.getRe().getRational(); BigRational ms = cm.getIm().getRational(); ComplexRing cf = new ComplexRing(rs.factory()); Complex c = new Complex(cf, rs, ms); return c; } /** * Complex of BigDecimal approximation of center. * @return r + i m as decimal approximation of the center. */ public Complex getDecimalCenter() { Complex rc = getRationalCenter(); BigDecimal rd = new BigDecimal(rc.getRe()); BigDecimal md = new BigDecimal(rc.getIm()); ComplexRing cf = new ComplexRing(rd.factory()); Complex c = new Complex(cf, rd, md); return c; } /** * Approximation of center. * @return r + i m as string of decimal approximation of the center. */ public String centerApprox() { Complex c = getDecimalCenter(); StringBuffer s = new StringBuffer(); s.append("[ "); s.append(c.getRe().toString()); s.append(" i "); s.append(c.getIm().toString()); s.append(" ]"); return s.toString(); } /** * Length. * @return |ne-sw|**2; */ public C length() { Complex m = corners[3].subtract(corners[1]); return m.norm().getRe(); } /** * Rational Length. * @return rational(|ne-sw|**2); */ public BigRational rationalLength() { //BigRational r = new BigRational(length().toString()); return length().getRational(); } /** * Length real side. * @return |re(ne)-re(sw)|; */ public C lengthReal() { C m = corners[3].getRe().subtract(corners[1].getRe()); return m.abs(); } /** * Length imaginary side. * @return |im(ne)-im(sw)|; */ public C lengthImag() { C m = corners[3].getIm().subtract(corners[1].getIm()); return m.abs(); } } jas-2.5/src/edu/jas/root/InvalidBoundaryException.java0000644000175000017500000000123311315175510023261 0ustar giovannigiovanni/* * $Id: InvalidBoundaryException.java 2925 2009-12-25 17:50:01Z kredel $ */ package edu.jas.root; /** * Invalid boundary exception class. Exception to be thrown when a valid * boundary cannot be constructed. * @author Heinz Kredel */ public class InvalidBoundaryException extends Exception { public InvalidBoundaryException() { super("InvalidBoundaryException"); } public InvalidBoundaryException(String c) { super(c); } public InvalidBoundaryException(String c, Throwable t) { super(c, t); } public InvalidBoundaryException(Throwable t) { super("InvalidBoundaryException", t); } } jas-2.5/src/edu/jas/root/NoConvergenceException.java0000644000175000017500000000120111344250240022711 0ustar giovannigiovanni/* * $Id: NoConvergenceException.java 3019 2010-03-05 18:42:41Z kredel $ */ package edu.jas.root; /** * No convergence exception class. Exception to be thrown when an * iteration does not converge. * @author Heinz Kredel */ public class NoConvergenceException extends Exception { public NoConvergenceException() { super("NoConvergenceException"); } public NoConvergenceException(String c) { super(c); } public NoConvergenceException(String c, Throwable t) { super(c, t); } public NoConvergenceException(Throwable t) { super("NoConvergenceException", t); } } jas-2.5/src/edu/jas/root/RootUtil.java0000644000175000017500000000755412004511002020067 0ustar giovannigiovanni/* * $Id: RootUtil.java 4063 2012-07-27 13:05:07Z kredel $ */ package edu.jas.root; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.Rational; import edu.jas.poly.Complex; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Real root utilities. For example real root count. * @author Heinz Kredel */ public class RootUtil { private static final Logger logger = Logger.getLogger(RootUtil.class); private static boolean debug = logger.isDebugEnabled(); /** * Count changes in sign. * @param coefficient type. * @param L list of coefficients. * @return number of sign changes in L. */ public static > long signVar(List L) { long v = 0; if (L == null || L.isEmpty()) { return v; } C A = L.get(0); for (int i = 1; i < L.size(); i++) { C B = L.get(i); while (B == null || B.signum() == 0) { i++; if (i >= L.size()) { return v; } B = L.get(i); } if (A.signum() * B.signum() < 0) { v++; } A = B; } return v; } /** * Parse interval for a real root from String. * @param s String, syntax: [left, right] or [mid]. * @return Interval from s. */ public static & Rational> Interval parseInterval(RingFactory fac, String s) { int r = s.length(); int el = s.indexOf("["); if (el >= 0) { int ri = s.indexOf("]"); if (ri > 0) { r = ri; } } else { el = -1; } //System.out.println("s = " + s); String iv = s.substring(el + 1, r).trim(); //System.out.println("iv = " + iv); int k = iv.indexOf(","); if (k < 0) { k = s.indexOf(" "); } if (k < 0) { C mid = fac.parse(iv); return new Interval(mid); } //System.out.println("k = " + k + ", len = " + iv.length()); String ls = iv.substring(0, k).trim(); String rs = iv.substring(k + 1, iv.length()).trim(); //System.out.println("ls = " + ls + ", rs = " + rs); C left = fac.parse(ls); C right = fac.parse(rs); if (debug) { logger.debug("Interval: left = " + left + ", right = " + right); } return new Interval(left, right); } /** * Parse rectangle for a complex root from String. * @param s String, syntax: [south-west, north-east] or [mid]. * @return Interval from s. */ public static & Rational> Rectangle parseRectangle(RingFactory> fac, String s) { int r = s.length(); int el = s.indexOf("["); if (el >= 0) { int ri = s.indexOf("]"); if (ri > 0) { r = ri; } } else { el = -1; } //System.out.println("s = " + s); String iv = s.substring(el + 1, r).trim(); //System.out.println("iv = " + iv); int k = iv.indexOf(","); if (k < 0) { k = s.indexOf(" "); } if (k < 0) { Complex mid = fac.parse(iv); return new Rectangle(mid); } //System.out.println("k = " + k + ", len = " + iv.length()); String ls = iv.substring(0, k).trim(); String rs = iv.substring(k + 1, iv.length()).trim(); //System.out.println("ls = " + ls + ", rs = " + rs); Complex sw = fac.parse(ls); Complex ne = fac.parse(rs); if (debug) { logger.debug("Rectangle: sw = " + sw + ", ne = " + ne); } return new Rectangle(sw, ne); } } jas-2.5/src/edu/jas/root/ComplexAlgebraicRing.java0000644000175000017500000002443012000257334022332 0ustar giovannigiovanni/* * $Id: ComplexAlgebraicRing.java 3987 2012-07-14 11:58:20Z kredel $ */ package edu.jas.root; import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.Random; import edu.jas.arith.Rational; import edu.jas.arith.BigRational; import edu.jas.arith.BigDecimal; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Complex algebraic number factory class based on AlgebraicNumberRing with RingElem * interface. Objects of this class are immutable with the exception of the * isolating intervals. * @author Heinz Kredel */ public class ComplexAlgebraicRing & Rational> /*extends AlgebraicNumberRing*/ implements RingFactory> { /** * Representing AlgebraicNumberRing. */ public final AlgebraicNumberRing> algebraic; /** * Isolating rectangle for a complex root. Note: interval may shrink * eventually. */ /*package*/Rectangle root; /** * Epsilon of the isolating rectangle for a complex root. */ protected C eps; /** * Precision of the isolating rectangle for a complex root. */ public static final int PRECISION = 9; //BigDecimal.DEFAULT_PRECISION; /** * Complex root computation engine. */ public final ComplexRootsSturm engine; /** * The constructor creates a ComplexAlgebraicNumber factory object from a * GenPolynomial objects module. * @param m module GenPolynomial<C>. * @param root isolating rectangle for a complex root. */ public ComplexAlgebraicRing(GenPolynomial> m, Rectangle root) { algebraic = new AlgebraicNumberRing>(m); this.root = root; engine = new ComplexRootsSturm(m.ring.coFac); if (m.ring.characteristic().signum() > 0) { throw new IllegalArgumentException("characteristic not zero"); } C e = m.ring.coFac.fromInteger(10L).getRe(); e = e.inverse(); e = Power.positivePower(e, PRECISION); eps = e; } /** * The constructor creates a ComplexAlgebraicNumber factory object from a * GenPolynomial objects module. * @param m module GenPolynomial<C>. * @param root isolating rectangle for a complex root. * @param isField indicator if m is prime. */ public ComplexAlgebraicRing(GenPolynomial> m, Rectangle root, boolean isField) { algebraic = new AlgebraicNumberRing>(m, isField); this.root = root; engine = new ComplexRootsSturm(m.ring.coFac); if (m.ring.characteristic().signum() > 0) { throw new IllegalArgumentException("characteristic not zero"); } C e = m.ring.coFac.fromInteger(10L).getRe(); e = e.inverse(); e = Power.positivePower(e, PRECISION); eps = e; } /* * Get the module part. * @return modul. public GenPolynomial getModul() { return * algebraic.modul; } */ /** * Set a refined rectangle for the complex root. Note: rectangle may * shrink eventually. * @param v rectangle. */ public synchronized void setRoot(Rectangle v) { // assert v is contained in root this.root = v; } /** * Get rectangle for the complex root. * @return v rectangle. */ public synchronized Rectangle getRoot() { return this.root; } /** * Get epsilon. * @return epsilon. */ public synchronized C getEps() { return this.eps; } /** * Set a new epsilon. * @param e epsilon. */ public synchronized void setEps(C e) { this.eps = e; } /** * Set a new epsilon. * @param e epsilon. */ public synchronized void setEps(BigRational e) { this.eps = algebraic.ring.coFac.parse(e.toString()).getRe(); } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return algebraic.isFinite(); } /** * Copy ComplexAlgebraicNumber element c. * @param c * @return a copy of c. */ public ComplexAlgebraicNumber copy(ComplexAlgebraicNumber c) { return new ComplexAlgebraicNumber(this, c.number); } /** * Get the zero element. * @return 0 as ComplexAlgebraicNumber. */ public ComplexAlgebraicNumber getZERO() { return new ComplexAlgebraicNumber(this, algebraic.getZERO()); } /** * Get the one element. * @return 1 as ComplexAlgebraicNumber. */ public ComplexAlgebraicNumber getONE() { return new ComplexAlgebraicNumber(this, algebraic.getONE()); } /** * Get the i element. * @return i as ComplexAlgebraicNumber. */ public ComplexAlgebraicNumber getIMAG() { ComplexRing cr = (ComplexRing) algebraic.ring.coFac; Complex I = cr.getIMAG(); return new ComplexAlgebraicNumber(this, algebraic.getZERO().sum(I)); } /** * Get the generating element. * @return alpha as ComplexAlgebraicNumber. */ public ComplexAlgebraicNumber getGenerator() { return new ComplexAlgebraicNumber(this, algebraic.getGenerator()); } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List>> agens = algebraic.generators(); List> gens = new ArrayList>(agens.size()); for (AlgebraicNumber> a : agens) { gens.add(getZERO().sum(a.getVal())); } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return algebraic.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return algebraic.isAssociative(); } /** * Query if this ring is a field. * @return true if algebraic is prime, else false. */ public boolean isField() { return algebraic.isField(); } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return algebraic.characteristic(); } /** * Get a ComplexAlgebraicNumber element from a BigInteger value. * @param a BigInteger. * @return a ComplexAlgebraicNumber. */ public ComplexAlgebraicNumber fromInteger(java.math.BigInteger a) { return new ComplexAlgebraicNumber(this, algebraic.fromInteger(a)); } /** * Get a ComplexAlgebraicNumber element from a long value. * @param a long. * @return a ComplexAlgebraicNumber. */ public ComplexAlgebraicNumber fromInteger(long a) { return new ComplexAlgebraicNumber(this, algebraic.fromInteger(a)); } /** * Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { return "ComplexAlgebraicRing[ " + algebraic.modul.toString() + " in " + root + " | isField=" + algebraic.isField() + " :: " + algebraic.ring.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "ComplexN( " + algebraic.modul.toScript() + ", " + root.toScript() //+ ", " + algebraic.isField() //+ ", " + algebraic.ring.toScript() + " )"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object b) { if (!(b instanceof ComplexAlgebraicRing)) { return false; } ComplexAlgebraicRing a = null; try { a = (ComplexAlgebraicRing) b; } catch (ClassCastException e) { } if (a == null) { return false; } return algebraic.equals(a.algebraic) && root.equals(a.root); } /** * Hash code for this ComplexAlgebraicNumber. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * algebraic.hashCode() + root.hashCode(); } /** * ComplexAlgebraicNumber random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random integer mod modul. */ public ComplexAlgebraicNumber random(int n) { return new ComplexAlgebraicNumber(this, algebraic.random(n)); } /** * ComplexAlgebraicNumber random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random integer mod modul. */ public ComplexAlgebraicNumber random(int n, Random rnd) { return new ComplexAlgebraicNumber(this, algebraic.random(n, rnd)); } /** * Parse ComplexAlgebraicNumber from String. * @param s String. * @return ComplexAlgebraicNumber from s. */ public ComplexAlgebraicNumber parse(String s) { return new ComplexAlgebraicNumber(this, algebraic.parse(s)); } /** * Parse ComplexAlgebraicNumber from Reader. * @param r Reader. * @return next ComplexAlgebraicNumber from r. */ public ComplexAlgebraicNumber parse(Reader r) { return new ComplexAlgebraicNumber(this, algebraic.parse(r)); } } jas-2.5/src/edu/jas/vector/0000755000175000017500000000000012140140256015761 5ustar giovannigiovannijas-2.5/src/edu/jas/vector/Examples.java0000644000175000017500000000304311506111626020406 0ustar giovannigiovanni/* * $Id: Examples.java 3454 2010-12-27 13:24:38Z kredel $ */ package edu.jas.vector; import edu.jas.arith.BigRational; import edu.jas.arith.BigInteger; //import edu.jas.arith.ModInteger; /** * Examples for basic linear algebra. * @author Heinz Kredel. */ public class Examples { /** * main. */ public static void main (String[] args) { example1(); example2(); // ComputerThreads.terminate(); } /** * example1. */ public static void example1() { System.out.println("\n\n example 1"); BigInteger cfac; GenMatrixRing mfac; cfac = new BigInteger(); System.out.println("cfac = " + cfac); mfac = new GenMatrixRing( cfac, 5, 5 ); System.out.println("mfac = " + mfac); GenMatrix m; m = mfac.random(3,0.4f); System.out.println("\nm = " + m); m = m.multiply(m); System.out.println("\nm = " + m); } /** * example2. */ public static void example2() { System.out.println("\n\n example 2"); BigRational cfac; GenMatrixRing mfac; cfac = new BigRational(); System.out.println("cfac = " + cfac); mfac = new GenMatrixRing( cfac, 5, 5 ); System.out.println("mfac = " + mfac); GenMatrix m; m = mfac.random(3,0.4f); System.out.println("\nm = " + m); m = m.multiply(m); System.out.println("\nm = " + m); } } jas-2.5/src/edu/jas/vector/package.html0000644000175000017500000000151110653065136020252 0ustar giovannigiovanni Generic vector and matrix package

Generic vector and matrix package.

This package contains classes for vectors, matices and lists of polynomials and solvable polynomials, e.g. GenVector, GenMatrix or ModuleList.


Heinz Kredel

Last modified: Mon Jul 9 23:04:48 CEST 2007

$Id: package.html 1265 2007-07-29 10:22:22Z kredel $

jas-2.5/src/edu/jas/vector/GenVector.java0000644000175000017500000002410712014234362020526 0ustar giovannigiovanni/* * $Id: GenVector.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.vector; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.kern.PrettyPrint; import edu.jas.structure.ModulElem; import edu.jas.structure.RingElem; /** * GenVector implements generic vectors with RingElem entries. Vectors of n * columns over C. * @author Heinz Kredel */ public class GenVector> implements ModulElem, C> { private static final Logger logger = Logger.getLogger(GenVector.class); public final GenVectorModul modul; public final List val; /** * Constructor for zero GenVector. */ public GenVector(GenVectorModul m) { this(m, m.getZERO().val); } /** * Constructor for GenVector. */ public GenVector(GenVectorModul m, List v) { if (m == null || v == null) { throw new IllegalArgumentException("Empty m or v not allowed, m = " + m + ", v = " + v); } modul = m; val = v; logger.info(modul.cols + " vector constructed"); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer(); s.append("[ "); boolean first = true; for (C c : val) { if (first) { first = false; } else { s.append(", "); } s.append(c.toString()); } s.append(" ]"); if (!PrettyPrint.isTrue()) { s.append(" :: " + modul.toString()); s.append("\n"); } return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer(); s.append("( "); boolean first = true; for (C c : val) { if (first) { first = false; } else { s.append(", "); } s.append(c.toScript()); } s.append(" )"); return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public GenVectorModul factory() { return modul; } /** * clone method. * @see java.lang.Object#clone() */ @Override @SuppressWarnings("unchecked") public GenVector copy() { //return modul.copy(this); ArrayList av = new ArrayList(val); return new GenVector(modul, av); } /** * test if this is equal to a zero vector. */ public boolean isZERO() { return (0 == this.compareTo(modul.getZERO())); } /** * equals method. */ @Override public boolean equals(Object other) { if (!(other instanceof GenVector)) { return false; } GenVector ovec = (GenVector) other; if (!modul.equals(ovec.modul)) { return false; } if (!val.equals(ovec.val)) { return false; } return true; } /** * Hash code for this GenVector. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * val.hashCode() + modul.hashCode(); } /** * compareTo, lexicographical comparison. * @param b other * @return 1 if (this < b), 0 if (this == b) or -1 if (this > b). */ //JAVA6only: @Override public int compareTo(GenVector b) { if (!modul.equals(b.modul)) { return -1; } List oval = b.val; int i = 0; for (C c : val) { int s = c.compareTo(oval.get(i++)); if (s != 0) { return s; } } return 0; } /** * sign of vector. * @return 1 if (this < 0), 0 if (this == 0) or -1 if (this > 0). */ public int signum() { return compareTo(modul.getZERO()); } /** * Sum of vectors. * @param b other vector. * @return this+b */ public GenVector sum(GenVector b) { List oval = b.val; ArrayList a = new ArrayList(modul.cols); int i = 0; for (C c : val) { C e = c.sum(oval.get(i++)); a.add(e); } return new GenVector(modul, a); } /** * Difference of vectors. * @param b other vector. * @return this-b */ public GenVector subtract(GenVector b) { List oval = b.val; ArrayList a = new ArrayList(modul.cols); int i = 0; for (C c : val) { C e = c.subtract(oval.get(i++)); a.add(e); } return new GenVector(modul, a); } /** * Negative of this vector. * @return -this */ public GenVector negate() { ArrayList a = new ArrayList(modul.cols); for (C c : val) { C e = c.negate(); a.add(e); } return new GenVector(modul, a); } /** * Absolute value of this vector. * @return abs(this) */ public GenVector abs() { if (signum() < 0) { return negate(); } return this; } /** * Product of this vector with scalar. * @param s scalar. * @return this*s */ public GenVector scalarMultiply(C s) { ArrayList a = new ArrayList(modul.cols); for (C c : val) { C e = c.multiply(s); a.add(e); } return new GenVector(modul, a); } /** * Left product of this vector with scalar. * @param s scalar. * @return s*this */ public GenVector leftScalarMultiply(C s) { ArrayList a = new ArrayList(modul.cols); for (C c : val) { C e = s.multiply(c); a.add(e); } return new GenVector(modul, a); } /** * Linear combination of this vector with scalar multiple of other vector. * @param s scalar. * @param b other vector. * @param t scalar. * @return this*s+b*t */ public GenVector linearCombination(C s, GenVector b, C t) { List oval = b.val; ArrayList a = new ArrayList(modul.cols); int i = 0; for (C c : val) { C c1 = c.multiply(s); C c2 = oval.get(i++).multiply(t); C e = c1.sum(c2); a.add(e); } return new GenVector(modul, a); } /** * Linear combination of this vector with scalar multiple of other vector. * @param b other vector. * @param t scalar. * @return this+b*t */ public GenVector linearCombination(GenVector b, C t) { List oval = b.val; ArrayList a = new ArrayList(modul.cols); int i = 0; for (C c : val) { C c2 = oval.get(i++).multiply(t); C e = c.sum(c2); a.add(e); } return new GenVector(modul, a); } /** * Left linear combination of this vector with scalar multiple of other * vector. * @param b other vector. * @param t scalar. * @return this+t*b */ public GenVector linearCombination(C t, GenVector b) { List oval = b.val; ArrayList a = new ArrayList(modul.cols); int i = 0; for (C c : val) { C c2 = t.multiply(oval.get(i++)); C e = c.sum(c2); a.add(e); } return new GenVector(modul, a); } /** * left linear combination of this vector with scalar multiple of other * vector. * @param s scalar. * @param b other vector. * @param t scalar. * @return s*this+t*b */ public GenVector leftLinearCombination(C s, C t, GenVector b) { List oval = b.val; ArrayList a = new ArrayList(modul.cols); int i = 0; for (C c : val) { C c1 = s.multiply(c); C c2 = t.multiply(oval.get(i++)); C e = c1.sum(c2); a.add(e); } return new GenVector(modul, a); } /** * scalar / dot product of this vector with other vector. * @param b other vector. * @return this . b */ public C scalarProduct(GenVector b) { C a = modul.coFac.getZERO(); List oval = b.val; int i = 0; for (C c : val) { C c2 = c.multiply(oval.get(i++)); a = a.sum(c2); } return a; } /** * scalar / dot product of this vector with list of other vectors. * @param B list of vectors. * @return this * b */ public GenVector scalarProduct(List> B) { GenVector A = modul.getZERO(); int i = 0; for (C c : val) { GenVector b = B.get(i++); GenVector a = b.leftScalarMultiply(c); A = A.sum(a); } return A; } /** * right scalar / dot product of this vector with list of other vectors. * @param B list of vectors. * @return b * this */ public GenVector rightScalarProduct(List> B) { GenVector A = modul.getZERO(); int i = 0; for (C c : val) { GenVector b = B.get(i++); GenVector a = b.scalarMultiply(c); A = A.sum(a); } return A; } } jas-2.5/src/edu/jas/vector/BasicLinAlg.java0000644000175000017500000001313311543350172020743 0ustar giovannigiovanni/* * $Id: BasicLinAlg.java 3584 2011-03-26 11:39:39Z kredel $ */ package edu.jas.vector; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.log4j.Logger; import edu.jas.structure.RingElem; /** * Basic linear algebra methods. Implements Basic linear algebra computations * and tests. Note: will use wrong method dispatch in JRE when used with * GenSolvablePolynomial. * @param coefficient type * @author Heinz Kredel */ public class BasicLinAlg> { private static final Logger logger = Logger.getLogger(BasicLinAlg.class); //private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public BasicLinAlg() { } /** * Scalar product of vectors of ring elements. * @param G a ring element list. * @param F a ring element list. * @return the scalar product of G and F. */ public C scalarProduct(List G, List F) { C sp = null; Iterator it = G.iterator(); Iterator jt = F.iterator(); while (it.hasNext() && jt.hasNext()) { C pi = it.next(); C pj = jt.next(); if (pi == null || pj == null) { continue; } if (sp == null) { sp = pi.multiply(pj); } else { sp = sp.sum(pi.multiply(pj)); } } if (it.hasNext() || jt.hasNext()) { logger.error("scalarProduct wrong sizes"); } return sp; } /** * Scalar product of vectors and a matrix of ring elements. * @param G a ring element list. * @param F a list of ring element lists. * @return the scalar product of G and F. */ public List leftScalarProduct(List G, List> F) { List sp = null; //new ArrayList(G.size()); Iterator it = G.iterator(); Iterator> jt = F.iterator(); while (it.hasNext() && jt.hasNext()) { C pi = it.next(); List pj = jt.next(); if (pi == null || pj == null) { continue; } List s = scalarProduct(pi, pj); if (sp == null) { sp = s; } else { sp = vectorAdd(sp, s); } } if (it.hasNext() || jt.hasNext()) { logger.error("scalarProduct wrong sizes"); } return sp; } /** * Scalar product of vectors and a matrix of ring elements. * @param G a ring element list. * @param F a list of ring element lists. * @return the right scalar product of G and F. */ public List rightScalarProduct(List G, List> F) { List sp = null; //new ArrayList(G.size()); Iterator it = G.iterator(); Iterator> jt = F.iterator(); while (it.hasNext() && jt.hasNext()) { C pi = it.next(); List pj = jt.next(); if (pi == null || pj == null) { continue; } List s = scalarProduct(pj, pi); if (sp == null) { sp = s; } else { sp = vectorAdd(sp, s); } } if (it.hasNext() || jt.hasNext()) { logger.error("scalarProduct wrong sizes"); } return sp; } /** * Addition of vectors of ring elements. * @param a a ring element list. * @param b a ring element list. * @return a+b, the vector sum of a and b. */ public List vectorAdd(List a, List b) { if (a == null) { return b; } if (b == null) { return a; } List V = new ArrayList(a.size()); Iterator it = a.iterator(); Iterator jt = b.iterator(); while (it.hasNext() && jt.hasNext()) { C pi = it.next(); C pj = jt.next(); C p = pi.sum(pj); V.add(p); } //System.out.println("vectorAdd" + V); if (it.hasNext() || jt.hasNext()) { logger.error("vectorAdd wrong sizes"); } return V; } /** * Test vector of zero ring elements. * @param a a ring element list. * @return true, if all polynomial in a are zero, else false. */ public boolean isZero(List a) { if (a == null) { return true; } for (C pi : a) { if (pi == null) { continue; } if (!pi.isZERO()) { return false; } } return true; } /** * Scalar product of ring element with vector of ring elements. * @param p a ring element. * @param F a ring element list. * @return the scalar product of p and F. */ public List scalarProduct(C p, List F) { List V = new ArrayList(F.size()); for (C pi : F) { if (p != null) { pi = p.multiply(pi); } else { pi = null; } V.add(pi); } return V; } /** * Scalar product of vector of ring element with ring element. * @param F a ring element list. * @param p a ring element. * @return the scalar product of F and p. */ public List scalarProduct(List F, C p) { List V = new ArrayList(F.size()); for (C pi : F) { if (pi != null) { pi = pi.multiply(p); } V.add(pi); } return V; } } jas-2.5/src/edu/jas/vector/GenVectorModul.java0000644000175000017500000001733612014234362021535 0ustar giovannigiovanni/* * $Id: GenVectorModul.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.vector; // import java.io.IOException; import java.io.Reader; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.StringUtil; import edu.jas.structure.ModulFactory; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * GenVectorModul implements a generic vector factory with RingElem entries. * Vectors of n columns over C. * @author Heinz Kredel */ public class GenVectorModul> implements ModulFactory, C> { private static final Logger logger = Logger.getLogger(GenVectorModul.class); public final RingFactory coFac; public final int cols; public final GenVector ZERO; public final List> BASIS; private final static Random random = new Random(); public final static float DEFAULT_DENSITY = 0.5f; private final float density = DEFAULT_DENSITY; /** * Constructor for GenVectorModul. */ @SuppressWarnings("unchecked") public GenVectorModul(RingFactory b, int s) { coFac = b; cols = s; ArrayList z = new ArrayList(cols); for (int i = 0; i < cols; i++) { z.add(coFac.getZERO()); } ZERO = new GenVector(this, z); BASIS = new ArrayList>(cols); List cgens = coFac.generators(); ArrayList v; for (int i = 0; i < cols; i++) { for (C g : cgens) { v = (ArrayList) z.clone(); v.set(i, g); BASIS.add(new GenVector(this, v)); } } logger.info(cols + " module over " + coFac + "constructed"); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer(); s.append(coFac.getClass().getSimpleName()); s.append("[" + cols + "]"); return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer("Vec("); String f = null; try { f = ((RingElem) coFac).toScriptFactory(); // sic } catch (Exception e) { f = coFac.toScript(); } s.append(f + "," + cols + " )"); return s.toString(); } /** * getZERO. * @return ZERO. */ public GenVector getZERO() { return ZERO; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { return BASIS; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return coFac.isFinite(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object other) { if (!(other instanceof GenVectorModul)) { return false; } GenVectorModul omod = (GenVectorModul) other; if (cols != omod.cols) { return false; } if (!coFac.equals(omod.coFac)) { return false; } return true; } /** * Hash code for this vector module. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = cols; h = 37 * h + coFac.hashCode(); return h; } /** * Get the vector for a. * @param a long * @return vector corresponding to a. */ public GenVector fromInteger(long a) { C c = coFac.fromInteger(a); return BASIS.get(0).scalarMultiply(c); } /** * Get the vector for a. * @param a long * @return vector corresponding to a. */ public GenVector fromInteger(BigInteger a) { C c = coFac.fromInteger(a); return BASIS.get(0).scalarMultiply(c); } /** * From List of coefficients. * @param v list of coefficients. * @return vector from v. */ public GenVector fromList(List v) { if (v == null) { return ZERO; } if (v.size() > cols) { throw new IllegalArgumentException("size v > cols " + v + " > " + cols); } List r = new ArrayList(cols); r.addAll(v); // pad with zeros if required: for (int i = r.size(); i < cols; i++) { r.add(coFac.getZERO()); } return new GenVector(this, r); } /** * Random vector. * @param k size of random coefficients. * @return random vector. */ public GenVector random(int k) { return random(k, density, random); } /** * Random vector. * @param k size of random coefficients. * @param q density of nonzero coefficients. * @return random vector. */ public GenVector random(int k, float q) { return random(k, q, random); } /** * Random vector. * @param k size of random coefficients. * @param random is a source for random bits. * @return a random element. */ public GenVector random(int k, Random random) { return random(k, density, random); } /** * Random vector. * @param k size of random coefficients. * @param q density of nonzero coefficients. * @param random is a source for random bits. * @return a random element. */ public GenVector random(int k, float q, Random random) { List r = new ArrayList(cols); for (int i = 0; i < cols; i++) { if (random.nextFloat() < q) { r.add(coFac.random(k)); } else { r.add(coFac.getZERO()); } } return new GenVector(this, r); } /** * copy vector. * @param c vector. * @return copy of vector c. */ public GenVector copy(GenVector c) { if (c == null) { return c; } return c.copy(); } /** * Parse a vector from a String. Syntax: [ c, ..., c ] * @param s String with vector. * @return parsed vector. */ public GenVector parse(String s) { int i = s.indexOf("["); if (i >= 0) { s = s.substring(i + 1); } i = s.indexOf("]"); if (i >= 0) { s = s.substring(0, i); } List vec = new ArrayList(cols); String e; C c; do { i = s.indexOf(","); if (i >= 0) { e = s.substring(0, i); s = s.substring(i + 1); c = coFac.parse(e); vec.add(c); } } while (i >= 0); if (s.trim().length() > 0) { c = coFac.parse(s); vec.add(c); } return new GenVector(this, vec); } /** * Parse a vector from a Reader. * @param r Reader containing a vector. * @return parsed vector. */ public GenVector parse(Reader r) { String s = StringUtil.nextPairedString(r, '[', ']'); return parse(s); } } jas-2.5/src/edu/jas/vector/GenMatrixRing.java0000644000175000017500000003503712014234362021354 0ustar giovannigiovanni/* * $Id: GenMatrixRing.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.vector; // import java.io.IOException; import java.io.Reader; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.StringUtil; import edu.jas.structure.AlgebraFactory; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * GenMatrixRing implements a generic matrix algebra factory with RingFactory. * Matrices of n rows and m columns over C. * @author Heinz Kredel */ public class GenMatrixRing> implements AlgebraFactory, C> { private static final Logger logger = Logger.getLogger(GenMatrixRing.class); public final RingFactory coFac; public final int rows; public final int cols; public final int blocksize; public final static int DEFAULT_BSIZE = 10; public final GenMatrix ZERO; public final GenMatrix ONE; private final static Random random = new Random(); public final static float DEFAULT_DENSITY = 0.5f; private final float density = DEFAULT_DENSITY; /** * Constructors for GenMatrixRing. * @param b coefficient factory. * @param r number of rows. * @param c number of colums. */ public GenMatrixRing(RingFactory b, int r, int c) { this(b, r, c, DEFAULT_BSIZE); } /** * Constructors for GenMatrixRing. * @param b coefficient factory. * @param r number of rows. * @param c number of colums. * @param s block size for blocked operations. */ @SuppressWarnings("unchecked") public GenMatrixRing(RingFactory b, int r, int c, int s) { if (b == null) { throw new IllegalArgumentException("RingFactory is null"); } if (r < 1) { throw new IllegalArgumentException("rows < 1 " + r); } if (c < 1) { throw new IllegalArgumentException("cols < 1 " + c); } coFac = b; rows = r; cols = c; blocksize = s; ArrayList z = new ArrayList(cols); for (int i = 0; i < cols; i++) { z.add(coFac.getZERO()); } ArrayList> m = new ArrayList>(rows); for (int i = 0; i < rows; i++) { m.add((ArrayList) z.clone()); } ZERO = new GenMatrix(this, m); m = new ArrayList>(rows); C one = coFac.getONE(); ArrayList v; for (int i = 0; i < rows; i++) { if (i < cols) { v = (ArrayList) z.clone(); v.set(i, one); m.add(v); } } ONE = new GenMatrix(this, m); logger.info(rows + " x " + cols + " with blocksize " + blocksize + " matrix ring over " + coFac + "constructed"); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer(); s.append(coFac.getClass().getSimpleName()); s.append("[" + rows + "," + cols + "]"); return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer("Mat("); String f = null; try { f = ((RingElem) coFac).toScriptFactory(); // sic } catch (Exception e) { f = coFac.toScript(); } s.append(f + "," + rows + "," + cols + ")"); return s.toString(); } /** * Get the constant one for the GenMatrix. * @return ZERO. */ public GenMatrix getZERO() { return ZERO; } /** * Get the constant one for the GenMatrix. * @return 1. */ public GenMatrix getONE() { return ONE; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List rgens = coFac.generators(); List> gens = new ArrayList>(rows * cols * rgens.size()); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { for (C el : rgens) { GenMatrix g = ZERO.set(i, j, el); // uses clone() gens.add(g); } } } return gens; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return coFac.isFinite(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object other) { if (!(other instanceof GenMatrixRing)) { return false; } GenMatrixRing omod = (GenMatrixRing) other; if (rows != omod.rows) { return false; } if (cols != omod.cols) { return false; } if (!coFac.equals(omod.coFac)) { return false; } return true; } /** * Hash code for this matrix ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = rows * 17 + cols; h = 37 * h + coFac.hashCode(); return h; } /** * Query if this ring is a field. May return false if it is to hard to * determine if this ring is a field. * @return true if it is known that this ring is a field, else false. */ public boolean isField() { return false; } /** * Query if this monoid is commutative. * @return true if this monoid is commutative, else false. */ public boolean isCommutative() { return false; } /** * Query if this ring is associative. * @return true if this monoid is associative, else false. */ public boolean isAssociative() { return (rows == cols); } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return coFac.characteristic(); } /** * Transposed matrix ring. * @return transposed ring factory. */ public GenMatrixRing transpose() { if (rows == cols) { return this; } return new GenMatrixRing(coFac, cols, rows, blocksize); } /** * Product matrix ring for multiplication. * @param other matrix ring factory. * @return product ring factory. */ public GenMatrixRing product(GenMatrixRing other) { if (cols != other.rows) { throw new IllegalArgumentException("invalid dimensions in product"); } if (!coFac.equals(other.coFac)) { throw new IllegalArgumentException("invalid coefficients in product"); } if (rows == other.rows && cols == other.cols) { return this; } return new GenMatrixRing(coFac, rows, other.cols, blocksize); } /** * Get the matrix for a. * @param a long * @return matrix corresponding to a. */ public GenMatrix fromInteger(long a) { C c = coFac.fromInteger(a); return ONE.scalarMultiply(c); } /** * Get the matrix for a. * @param a long * @return matrix corresponding to a. */ public GenMatrix fromInteger(BigInteger a) { C c = coFac.fromInteger(a); return ONE.scalarMultiply(c); } /** * From List of coefficients. * @param om list of list of coefficients. */ public GenMatrix fromList(List> om) { if (om == null) { return ZERO; } if (om.size() > rows) { throw new IllegalArgumentException("size v > rows " + om + " > " + rows); } ArrayList> m = new ArrayList>(rows); for (int i = 0; i < rows; i++) { List ov = om.get(i); ArrayList v; if (ov == null) { v = ZERO.matrix.get(0); } else { if (ov.size() > cols) { throw new IllegalArgumentException("size v > cols " + ov + " > " + cols); } v = new ArrayList(cols); v.addAll(ov); // pad with zeros if required: for (int j = v.size(); j < cols; j++) { v.add(coFac.getZERO()); } } m.add(v); } return new GenMatrix(this, m); } /** * Random matrix. * @param k size of random coefficients. */ public GenMatrix random(int k) { return random(k, density, random); } /** * Random matrix. * @param k size of random coefficients. * @param q density of nozero coefficients. */ public GenMatrix random(int k, float q) { return random(k, q, random); } /** * Random matrix. * @param k size of random coefficients. * @param random is a source for random bits. * @return a random element. */ public GenMatrix random(int k, Random random) { return random(k, density, random); } /** * Random matrix. * @param k size of random coefficients. * @param q density of nozero coefficients. * @param random is a source for random bits. * @return a random element. */ public GenMatrix random(int k, float q, Random random) { ArrayList> m = new ArrayList>(rows); for (int i = 0; i < rows; i++) { ArrayList v = new ArrayList(cols); for (int j = 0; j < cols; j++) { C e; if (random.nextFloat() < q) { e = coFac.random(k); } else { e = coFac.getZERO(); } v.add(e); } m.add(v); } return new GenMatrix(this, m); } /** * Random upper triangular matrix. * @param k size of random coefficients. * @param q density of nozero coefficients. */ public GenMatrix randomUpper(int k, float q) { return randomUpper(k, q, random); } /** * Random upper triangular matrix. * @param k size of random coefficients. * @param q density of nozero coefficients. * @param random is a source for random bits. * @return a random element. */ public GenMatrix randomUpper(int k, float q, Random random) { ArrayList> m = new ArrayList>(rows); for (int i = 0; i < rows; i++) { ArrayList v = new ArrayList(cols); for (int j = 0; j < cols; j++) { C e = coFac.getZERO(); if (j >= i) { if (random.nextFloat() < q) { e = coFac.random(k); } } v.add(e); } m.add(v); } return new GenMatrix(this, m); } /** * Random lower triangular matrix. * @param k size of random coefficients. * @param q density of nozero coefficients. */ public GenMatrix randomLower(int k, float q) { return randomLower(k, q, random); } /** * Random lower triangular matrix. * @param k size of random coefficients. * @param q density of nozero coefficients. * @param random is a source for random bits. * @return a random element. */ public GenMatrix randomLower(int k, float q, Random random) { ArrayList> m = new ArrayList>(rows); for (int i = 0; i < rows; i++) { ArrayList v = new ArrayList(cols); for (int j = 0; j < cols; j++) { C e = coFac.getZERO(); if (j <= i) { if (random.nextFloat() < q) { e = coFac.random(k); } } v.add(e); } m.add(v); } return new GenMatrix(this, m); } /** * Copy matrix. * @param c matrix to copy. * @return copy of the matrix * */ public GenMatrix copy(GenMatrix c) { if (c == null) { return c; } return c.copy(); } /** * Parse a matrix from a String. Syntax: [ [ c, ..., c ], ..., [ c, ..., c ] * ] * @param s input String. * @return parsed matrix */ public GenMatrix parse(String s) { int i = s.indexOf("["); if (i >= 0) { s = s.substring(i + 1); } ArrayList> mat = new ArrayList>(rows); ArrayList v; GenVector vec; GenVectorModul vmod = new GenVectorModul(coFac, cols); String e; int j; do { i = s.indexOf("]"); // delimit vector j = s.lastIndexOf("]"); // delimit matrix if (i != j) { if (i >= 0) { e = s.substring(0, i); s = s.substring(i); vec = vmod.parse(e); v = (ArrayList) vec.val; mat.add(v); i = s.indexOf(","); if (i >= 0) { s = s.substring(i + 1); } } } else { // matrix delimiter if (i >= 0) { e = s.substring(0, i); if (e.trim().length() > 0) { throw new RuntimeException("Error e not empty " + e); } //s = s.substring(i + 1); } break; } } while (i >= 0); return new GenMatrix(this, mat); } /** * Parse a matrix from a Reader. * @param r Reader. * @return parsed matrix */ public GenMatrix parse(Reader r) { String s = StringUtil.nextPairedString(r, '[', ']'); return parse(s); } } jas-2.5/src/edu/jas/vector/GenMatrix.java0000644000175000017500000004530712014234362020535 0ustar giovannigiovanni/* * $Id: GenMatrix.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.vector; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.kern.PrettyPrint; import edu.jas.structure.AlgebraElem; import edu.jas.structure.RingElem; /** * GenMatrix implements a generic matrix algebra over RingElem entries. Matrix * has n columns and m rows over C. * @author Heinz Kredel */ public class GenMatrix> implements AlgebraElem, C> { private static final Logger logger = Logger.getLogger(GenMatrix.class); public final GenMatrixRing ring; public final ArrayList> matrix; private int hashValue = 0; /** * Constructor for zero GenMatrix. * @param r matrix ring */ public GenMatrix(GenMatrixRing r) { this(r, r.getZERO().matrix); } /** * Constructor for GenMatrix. * @param r matrix ring * @param m matrix */ public GenMatrix(GenMatrixRing r, List> m) { ring = r; matrix = new ArrayList>(r.rows); for (List row : m) { ArrayList nr = new ArrayList(row); matrix.add(nr); } logger.info(ring.rows + " x " + ring.cols + " matrix constructed"); } /** * Constructor for GenMatrix. * @param r matrix ring * @param m matrix */ public GenMatrix(GenMatrixRing r, ArrayList> m) { if (r == null || m == null) { throw new IllegalArgumentException("Empty r or m not allowed, r = " + r + ", m = " + m); } ring = r; matrix = new ArrayList>(m); logger.info(ring.rows + " x " + ring.cols + " matrix constructed"); } /** * Get element at row i, column j. * @param i row index. * @param j column index. * @return this(i,j). */ public C get(int i, int j) { return matrix.get(i).get(j); } /** * Set element at row i, column j. Mutates this matrix. * @param i row index. * @param j column index. * @param el element to set. */ public void setMutate(int i, int j, C el) { ArrayList ri = matrix.get(i); ri.set(j, el); hashValue = 0; // invalidate } /** * Set element at row i, column j. * @param i row index. * @param j column index. * @param el element to set. * @return new matrix m, with m(i,j) == el. */ public GenMatrix set(int i, int j, C el) { GenMatrix mat = this.copy(); mat.setMutate(i, j, el); return mat; } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer(); boolean firstRow = true; s.append("[\n"); for (List val : matrix) { if (firstRow) { firstRow = false; } else { s.append(",\n"); } boolean first = true; s.append("[ "); for (C c : val) { if (first) { first = false; } else { s.append(", "); } s.append(c.toString()); } s.append(" ]"); } s.append(" ] "); if (!PrettyPrint.isTrue()) { s.append(":: " + ring.toString()); s.append("\n"); } return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer(); boolean firstRow = true; s.append("( "); for (List val : matrix) { if (firstRow) { firstRow = false; } else { s.append(", "); } boolean first = true; s.append("( "); for (C c : val) { if (first) { first = false; } else { s.append(", "); } s.append(c.toScript()); } s.append(" )"); } s.append(" ) "); return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public GenMatrixRing factory() { return ring; } /** * clone method. * @see java.lang.Object#clone() */ @Override @SuppressWarnings("unchecked") public GenMatrix copy() { //return ring.copy(this); ArrayList> m = new ArrayList>(ring.rows); ArrayList v; for (ArrayList val : matrix) { v = (ArrayList) val.clone(); m.add(v); } return new GenMatrix(ring, m); } /** * Test if this is equal to a zero matrix. */ public boolean isZERO() { for (List row : matrix) { for (C elem : row) { if (!elem.isZERO()) { return false; } } } return true; } /** * Test if this is one. * @return true if this is 1, else false. */ public boolean isONE() { int i = 0; for (List row : matrix) { int j = 0; for (C elem : row) { if (i == j) { if (!elem.isONE()) { return false; } } else if (!elem.isZERO()) { return false; } j++; } i++; } return true; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object other) { if (!(other instanceof GenMatrix)) { return false; } GenMatrix om = (GenMatrix) other; if (!ring.equals(om.ring)) { return false; } if (!matrix.equals(om.matrix)) { return false; } return true; } /** * Hash code for this GenMatrix. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { if (hashValue == 0) { hashValue = 37 * matrix.hashCode() + ring.hashCode(); if (hashValue == 0) { hashValue = 1; } } return hashValue; } /** * compareTo, lexicogaphical comparison. * @param b other * @return 1 if (this < b), 0 if (this == b) or -1 if (this > b). */ //JAVA6only: @Override public int compareTo(GenMatrix b) { if (!ring.equals(b.ring)) { return -1; } ArrayList> om = b.matrix; int i = 0; for (ArrayList val : matrix) { ArrayList ov = om.get(i++); int j = 0; for (C c : val) { int s = c.compareTo(ov.get(j++)); if (s != 0) { return s; } } } return 0; } /** * Test if this is a unit. I.e. there exists x with this.multiply(x).isONE() * == true. Tests if all diagonal elements are units and all other elements * are zero. * @return true if this is a unit, else false. */ public boolean isUnit() { int i = 0; for (ArrayList val : matrix) { int j = 0; for (C el : val) { if (i == j) { if (!el.isUnit()) { return false; } } else { if (!el.isZERO()) { return false; } } j++; } i++; } return true; } /** * sign of matrix. * @return 1 if (this < 0), 0 if (this == 0) or -1 if (this > 0). */ public int signum() { return compareTo(ring.getZERO()); } /** * Sum of matrices. * @return this+b */ public GenMatrix sum(GenMatrix b) { ArrayList> om = b.matrix; ArrayList> m = new ArrayList>(ring.rows); int i = 0; for (ArrayList val : matrix) { ArrayList ov = om.get(i++); ArrayList v = new ArrayList(ring.cols); int j = 0; for (C c : val) { C e = c.sum(ov.get(j++)); v.add(e); } m.add(v); } return new GenMatrix(ring, m); } /** * Difference of matrices. * @return this-b */ public GenMatrix subtract(GenMatrix b) { ArrayList> om = b.matrix; ArrayList> m = new ArrayList>(ring.rows); int i = 0; for (ArrayList val : matrix) { ArrayList ov = om.get(i++); ArrayList v = new ArrayList(ring.cols); int j = 0; for (C c : val) { C e = c.subtract(ov.get(j++)); v.add(e); } m.add(v); } return new GenMatrix(ring, m); } /** * Negative of this matrix. * @return -this */ public GenMatrix negate() { ArrayList> m = new ArrayList>(ring.rows); //int i = 0; for (ArrayList val : matrix) { ArrayList v = new ArrayList(ring.cols); for (C c : val) { C e = c.negate(); v.add(e); } m.add(v); } return new GenMatrix(ring, m); } /** * Absolute value of this matrix. * @return abs(this) */ public GenMatrix abs() { if (signum() < 0) { return negate(); } return this; } /** * Product of this matrix with scalar. * @return this*s */ public GenMatrix scalarMultiply(C s) { ArrayList> m = new ArrayList>(ring.rows); //int i = 0; for (ArrayList val : matrix) { ArrayList v = new ArrayList(ring.cols); for (C c : val) { C e = c.multiply(s); v.add(e); } m.add(v); } return new GenMatrix(ring, m); } /** * Left product of this matrix with scalar. * @return s*this */ public GenMatrix leftScalarMultiply(C s) { ArrayList> m = new ArrayList>(ring.rows); //int i = 0; for (ArrayList val : matrix) { ArrayList v = new ArrayList(ring.cols); for (C c : val) { C e = s.multiply(c); v.add(e); } m.add(v); } return new GenMatrix(ring, m); } /** * Linear compination of this matrix with scalar multiple of other matrix. * @return this*s+b*t */ public GenMatrix linearCombination(C s, GenMatrix b, C t) { ArrayList> om = b.matrix; ArrayList> m = new ArrayList>(ring.rows); int i = 0; for (ArrayList val : matrix) { ArrayList ov = om.get(i++); ArrayList v = new ArrayList(ring.cols); int j = 0; for (C c : val) { C c1 = c.multiply(s); C c2 = ov.get(j++).multiply(t); C e = c1.sum(c2); v.add(e); } m.add(v); } return new GenMatrix(ring, m); } /** * Linear combination of this matrix with scalar multiple of other matrix. * @return this+b*t */ public GenMatrix linearCombination(GenMatrix b, C t) { ArrayList> om = b.matrix; ArrayList> m = new ArrayList>(ring.rows); int i = 0; for (ArrayList val : matrix) { ArrayList ov = om.get(i++); ArrayList v = new ArrayList(ring.cols); int j = 0; for (C c : val) { C c2 = ov.get(j++).multiply(t); C e = c.sum(c2); v.add(e); } m.add(v); } return new GenMatrix(ring, m); } /** * Left linear combination of this matrix with scalar multiple of other * matrix. * @return this+t*b */ public GenMatrix linearCombination(C t, GenMatrix b) { ArrayList> om = b.matrix; ArrayList> m = new ArrayList>(ring.rows); int i = 0; for (ArrayList val : matrix) { ArrayList ov = om.get(i++); ArrayList v = new ArrayList(ring.cols); int j = 0; for (C c : val) { C c2 = t.multiply(ov.get(j++)); C e = c.sum(c2); v.add(e); } m.add(v); } return new GenMatrix(ring, m); } /** * left linear compination of this matrix with scalar multiple of other * matrix. * @return s*this+t*b */ public GenMatrix leftLinearCombination(C s, C t, GenMatrix b) { ArrayList> om = b.matrix; ArrayList> m = new ArrayList>(ring.rows); int i = 0; for (ArrayList val : matrix) { ArrayList ov = om.get(i++); ArrayList v = new ArrayList(ring.cols); int j = 0; for (C c : val) { C c1 = s.multiply(c); C c2 = t.multiply(ov.get(j++)); C e = c1.sum(c2); v.add(e); } m.add(v); } return new GenMatrix(ring, m); } /** * Transposed matrix. * @return transpose(this) */ public GenMatrix transpose(GenMatrixRing tr) { GenMatrix t = tr.getZERO().copy(); ArrayList> m = t.matrix; int i = 0; for (ArrayList val : matrix) { int j = 0; for (C c : val) { (m.get(j)).set(i, c); //A[j,i] = A[i,j] j++; } i++; } // return new GenMatrix(tr,m); return t; } /** * Multiply this with S. * @param S * @return this * S. */ public GenMatrix multiply(GenMatrix S) { int na = ring.blocksize; int nb = ring.blocksize; //System.out.println("#blocks = " + (matrix.size()/na) + ", na = " + na // + " SeqMultBlockTrans"); ArrayList> m = matrix; //ArrayList> s = S.matrix; GenMatrixRing tr = S.ring.transpose(); GenMatrix T = S.transpose(tr); ArrayList> t = T.matrix; //System.out.println("T = " + T); GenMatrixRing pr = ring.product(S.ring); GenMatrix P = pr.getZERO().copy(); ArrayList> p = P.matrix; //System.out.println("P = " + P); for (int ii = 0; ii < m.size(); ii += na) { for (int jj = 0; jj < t.size(); jj += nb) { for (int i = ii; i < Math.min((ii + na), m.size()); i++) { ArrayList Ai = m.get(i); //A[i]; for (int j = jj; j < Math.min((jj + nb), t.size()); j++) { ArrayList Bj = t.get(j); //B[j]; C c = ring.coFac.getZERO(); for (int k = 0; k < Bj.size(); k++) { c = c.sum(Ai.get(k).multiply(Bj.get(k))); // c += Ai[k] * Bj[k]; } (p.get(i)).set(j, c); // C[i][j] = c; } } } } return new GenMatrix(pr, p); } /** * Multiply this with S. Simple unblocked algorithm. * @param S * @return this * S. */ public GenMatrix multiplySimple(GenMatrix S) { ArrayList> m = matrix; ArrayList> B = S.matrix; GenMatrixRing pr = ring.product(S.ring); GenMatrix P = pr.getZERO().copy(); ArrayList> p = P.matrix; for (int i = 0; i < pr.rows; i++) { ArrayList Ai = m.get(i); //A[i]; for (int j = 0; j < pr.cols; j++) { C c = ring.coFac.getZERO(); for (int k = 0; k < S.ring.rows; k++) { c = c.sum(Ai.get(k).multiply(B.get(k).get(j))); // c += A[i][k] * B[k][j]; } (p.get(i)).set(j, c); // C[i][j] = c; } } return new GenMatrix(pr, p); } /** * Divide this by S. * @param S * @return this / S. */ public GenMatrix divide(GenMatrix S) { throw new UnsupportedOperationException("divide not yet implemented"); } /** * Remainder after division of this by S. * @param S * @return this - (this / S) * S. */ public GenMatrix remainder(GenMatrix S) { throw new UnsupportedOperationException("remainder not implemented"); } /** * Inverse of this. * @return x with this * x = 1, if it exists. */ public GenMatrix inverse() { throw new UnsupportedOperationException("inverse not yet implemented"); } /** * Greatest common divisor. * @param b other element. * @return gcd(this,b). */ public GenMatrix gcd(GenMatrix b) { throw new UnsupportedOperationException("gcd not implemented"); } /** * Extended greatest common divisor. * @param b other element. * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). */ public GenMatrix[] egcd(GenMatrix b) { throw new UnsupportedOperationException("egcd not implemented"); } } jas-2.5/src/edu/jas/gbufd/0000755000175000017500000000000012140140254015544 5ustar giovannigiovannijas-2.5/src/edu/jas/gbufd/RGroebnerBaseSeq.java0000644000175000017500000002631512014164600021550 0ustar giovannigiovanni/* * $Id: RGroebnerBaseSeq.java 4116 2012-08-19 13:26:25Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.log4j.Logger; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.Pair; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RegularRingElem; /** * Regular ring Groebner Base sequential algorithm. Implements R-Groebner bases * and GB test. * @param coefficient type * @author Heinz Kredel */ public class RGroebnerBaseSeq> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(RGroebnerBaseSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Reduction engine. */ protected RReduction rred; // shadow super.red ?? /** * Constructor. */ public RGroebnerBaseSeq() { this(new RReductionSeq()); } /** * Constructor. * @param rred R-Reduction engine */ public RGroebnerBaseSeq(RReduction rred) { super(rred); this.rred = rred; assert super.red == this.rred; } /** * R-Groebner base test. * @param modv module variable number. * @param F polynomial list. * @return true, if F is a R-Groebner base, else false. */ @Override public boolean isGB(int modv, List> F) { if (F == null) { return true; } if (!rred.isBooleanClosed(F)) { if (debug) { logger.debug("not boolean closed"); } return false; } GenPolynomial pi, pj, s; for (int i = 0; i < F.size(); i++) { pi = F.get(i); for (int j = i + 1; j < F.size(); j++) { pj = F.get(j); if (!red.moduleCriterion(modv, pi, pj)) { continue; } // red.criterion4 not applicable s = red.SPolynomial(pi, pj); if (s.isZERO()) { continue; } s = red.normalform(F, s); if (!s.isZERO()) { if (debug) { logger.debug("p" + i + " = " + pi); logger.debug("p" + j + " = " + pj); logger.debug("s-pol = " + red.SPolynomial(pi, pj)); logger.debug("s-pol(" + i + "," + j + ") != 0: " + s); } return false; } } } return true; } /** * R-Groebner base using pairlist class. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a R-Groebner base of F. */ public List> GB(int modv, List> F) { /* boolean closure */ List> bcF = rred.reducedBooleanClosure(F); logger.info("#bcF-#F = " + (bcF.size() - F.size())); F = bcF; /* normalize input */ List> G = new ArrayList>(); OrderedRPairlist pairlist = null; for (GenPolynomial p : F) { if (!p.isZERO()) { p = p.monic(); //p.abs(); // not monic, monic if boolean closed if (p.isONE()) { G.clear(); G.add(p); return G; // since boolean closed and no threads are activated } G.add(p); //G.add( 0, p ); //reverse list if (pairlist == null) { pairlist = new OrderedRPairlist(modv, p.ring); } // putOne not required pairlist.put(p); } } if (G.size() <= 1) { return G; // since boolean closed and no threads are activated } /* loop on critical pairs */ Pair pair; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; //GenPolynomial D; GenPolynomial H; List> bcH; //int len = G.size(); //System.out.println("len = " + len); while (pairlist.hasNext()) { pair = pairlist.removeNext(); //System.out.println("pair = " + pair); if (pair == null) continue; pi = pair.pi; pj = pair.pj; if (logger.isDebugEnabled()) { logger.debug("pi = " + pi); logger.debug("pj = " + pj); } if (!red.moduleCriterion(modv, pi, pj)) { continue; } // S-polynomial ----------------------- // Criterion3() Criterion4() not applicable S = red.SPolynomial(pi, pj); if (S.isZERO()) { pair.setZero(); continue; } if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(G, S); if (H.isZERO()) { pair.setZero(); continue; } //H = H.monic(); // only for boolean closed H if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } if (H.isONE()) { // mostly useless G.clear(); G.add(H); return G; // not boolean closed ok, since no threads are activated } if (logger.isDebugEnabled()) { logger.debug("H = " + H); } if (!H.isZERO()) { logger.info("Sred = " + H); //len = G.size(); bcH = rred.reducedBooleanClosure(G, H); logger.info("#bcH = " + bcH.size()); for (GenPolynomial h : bcH) { h = h.monic(); // monic() ok, since boolean closed G.add(h); pairlist.put(h); } if (debug) { if (!pair.getUseCriterion3() || !pair.getUseCriterion4()) { logger.info("H != 0 but: " + pair); } } } } logger.debug("#sequential list = " + G.size()); G = minimalGB(G); //G = red.irreducibleSet(G); logger.info("" + pairlist); return G; } /** * Minimal ordered Groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. */ @Override public List> minimalGB(List> Gp) { if (Gp == null || Gp.size() <= 1) { return Gp; } // remove zero polynomials List> G = new ArrayList>(Gp.size()); for (GenPolynomial a : Gp) { if (a != null && !a.isZERO()) { // always true in GB() // already positive a = a.abs(); G.add(a); } } //if (G.size() <= 1) { //wg monic do not return G; //} // remove top reducible polynomials GenPolynomial a, b; List> F; List> bcH; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); b = a; if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { // drop polynomial if (logger.isInfoEnabled()) { List> ff; ff = new ArrayList>(G); ff.addAll(F); a = red.normalform(ff, a); if (!a.isZERO()) { // happens logger.info("minGB not zero " + a); bcH = rred.reducedBooleanClosure(G, a); if (bcH.size() > 1) { // never happend so far System.out.println("minGB not bc: bcH size = " + bcH.size()); F.add(b); // do not replace, stay with b } else { //System.out.println("minGB add bc(a): a = " + a + ", bc(a) = " + bcH.get(0)); F.addAll(bcH); } } else { //System.out.println("minGB dropped " + b); } } } else { F.add(a); } } G = F; //if (G.size() <= 1) { // wg monic return G; //} Collections.reverse(G); // important for lex GB // reduce remaining polynomials int len = G.size(); int el = 0; while (el < len) { a = G.remove(0); b = a; //System.out.println("doing " + a.length()); a = red.normalform(G, a); bcH = rred.reducedBooleanClosure(G, a); if (bcH.size() > 1) { System.out.println("minGB not bc: bcH size = " + bcH.size()); G.add(b); // do not reduce } else { G.addAll(bcH); } el++; } // make monic if possible F = new ArrayList>(G.size()); for (GenPolynomial p : G) { a = p.monic().abs(); if (p.length() != a.length()) { System.out.println("minGB not bc: #p != #a: a = " + a + ", p = " + p); a = p; // dont make monic for now } F.add(a); } G = F; /* stratify: collect polynomials with equal leading terms */ ExpVector e, f; F = new ArrayList>(G.size()); for (int i = 0; i < G.size(); i++) { a = G.get(i); if (a == null || a.isZERO()) { continue; } e = a.leadingExpVector(); for (int j = i + 1; j < G.size(); j++) { b = G.get(j); if (b == null || b.isZERO()) { continue; } f = b.leadingExpVector(); if (e.equals(f)) { //System.out.println("minGB e == f: " + a + ", " + b); a = a.sum(b); G.set(j, null); } } F.add(a); } G = F; /* info on boolean algebra element blocks Map>> bd = new TreeMap>>(); for ( GenPolynomial p : G ) { C cf = p.leadingBaseCoefficient(); cf = cf.idempotent(); List> block = bd.get( cf ); if ( block == null ) { block = new ArrayList>(); } block.add( p ); bd.put( cf, block ); } System.out.println("\nminGB bd:"); for( C k: bd.keySet() ) { System.out.println("\nkey = " + k + ":"); System.out.println("val = " + bd.get(k)); } System.out.println(); */ return G; } } jas-2.5/src/edu/jas/gbufd/OrderedRPairlist.java0000644000175000017500000001132011571751640021640 0ustar giovannigiovanni/* * $Id: OrderedRPairlist.java 3652 2011-06-02 18:17:04Z kredel $ */ package edu.jas.gbufd; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.gb.OrderedPairlist; import edu.jas.gb.Pair; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.RegularRingElem; /** * Pair list management for R-Groebner bases. * Implemented using GenPolynomial, TreeMap and BitSet. * @author Heinz Kredel */ public class OrderedRPairlist > extends OrderedPairlist { private static final Logger logger = Logger.getLogger(OrderedRPairlist.class); protected final RReduction rreduction; /** * Constructor for OrderedRPairlist. * @param r polynomial factory. */ public OrderedRPairlist(GenPolynomialRing r) { this(0,r); } /** * Constructor for OrderedRPairlist. * @param m number of module variables. * @param r polynomial factory. */ public OrderedRPairlist(int m, GenPolynomialRing r) { super(m,r); rreduction = new RReductionSeq(); } /** * Remove the next required pair from the pairlist and reduction matrix. * Appy the criterions 3 and 4 to see if the S-polynomial is required. * @return the next pair if one exists, otherwise null. */ @Override public synchronized Pair removeNext() { if ( oneInGB ) { return null; } Iterator< Map.Entry>> > ip = pairlist.entrySet().iterator(); Pair pair = null; boolean c = false; int i, j; if ( ip.hasNext() ) { Map.Entry>> me = ip.next(); ExpVector g = me.getKey(); LinkedList> xl = me.getValue(); if ( logger.isInfoEnabled() ) { logger.info("g = " + g); } pair = null; if ( xl.size() > 0 ) { pair = xl.removeFirst(); // xl is also modified in pairlist i = pair.i; j = pair.j; // System.out.println("pair(" + j + "," +i+") "); if ( useCriterion4 ) { c = rreduction.criterion4( pair.pi, pair.pj, g ); } else { c = true; } pair.setUseCriterion4(c); //System.out.println("c4 = " + c); if ( c ) { c = criterion3( i, j, g ); //System.out.println("c3 = " + c); pair.setUseCriterion3(c); } red.get( j ).clear(i); // set(i,false) jdk1.4 } if ( xl.size() == 0 ) { ip.remove(); // = pairlist.remove( g ); } } remCount++; // count pairs return pair; } /** * GB criterium 3. * @return true if the S-polynomial(i,j) is required. */ @Override public boolean criterion3(int i, int j, ExpVector eij) { // assert i < j; boolean s; s = red.get( j ).get(i); if ( ! s ) { logger.warn("c3.s false for " + j + " " + i); return s; } s = true; boolean m; GenPolynomial A; ExpVector ek; C ci = P.get(i).leadingBaseCoefficient(); C cj = P.get(j).leadingBaseCoefficient(); C c = ci.multiply(cj); // a guess C ck; for ( int k = 0; k < P.size(); k++ ) { A = P.get( k ); ek = A.leadingExpVector(); m = eij.multipleOf(ek); if ( m ) { ck = A.leadingBaseCoefficient(); C r = c.multiply(ck); // a guess m = r.isZERO(); } if ( m ) { if ( k < i ) { // System.out.println("k < i "+k+" "+i); s = red.get( i ).get(k) || red.get( j ).get(k); } if ( i < k && k < j ) { // System.out.println("i < k < j "+i+" "+k+" "+j); s = red.get( k ).get(i) || red.get( j ).get(k); } if ( j < k ) { //System.out.println("j < k "+j+" "+k); s = red.get( k ).get(i) || red.get( k ).get(j); } //System.out.println("s."+k+" = " + s); if ( ! s ) return s; } } return true; } } jas-2.5/src/edu/jas/gbufd/Examples.java0000644000175000017500000001464312003770200020173 0ustar giovannigiovanni/* * $Id: Examples.java 4036 2012-07-25 13:11:28Z kredel $ */ package edu.jas.gbufd; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.gb.GroebnerBase; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; /** * Examples for Groebner base usage. * @author Christoph Zengler. * @author Heinz Kredel. */ public class Examples { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); //example1(); //example2(); //example3(); exampleGB(); //exampleGB1(); //exampleGBTrinks(); } /** * example1. Coefficients in Boolean residue class ring. * */ public static void example1() { // moved to edu.jas.application.Examples } /* * example2. Coefficients in Boolean residue class ring with cuppling of * variables. * */ public static void example2() { // moved to edu.jas.application.Examples } /** * example3. Coefficients in Boolean ring and additional idempotent * generators. * */ public static void example3() { String[] vars = { "v3", "v2", "v1" }; ModIntegerRing z2 = new ModIntegerRing(2); GenPolynomialRing z2p = new GenPolynomialRing(z2, vars.length, new TermOrder( TermOrder.INVLEX), vars); List> fieldPolynomials = new ArrayList>(); //add v1^2 + v1, v2^2 + v2, v3^2 + v3 to fieldPolynomials for (int i = 0; i < vars.length; i++) { GenPolynomial var = z2p.univariate(i); fieldPolynomials.add(var.multiply(var).sum(var)); } List> polynomials = new ArrayList>(); GenPolynomial v1 = z2p.univariate(0); GenPolynomial v2 = z2p.univariate(1); GenPolynomial v3 = z2p.univariate(2); GenPolynomial notV1 = v1.sum(z2p.ONE); GenPolynomial notV2 = v2.sum(z2p.ONE); GenPolynomial notV3 = v3.sum(z2p.ONE); //v1*v2 GenPolynomial p1 = v1.multiply(v2); //v1*v2 + v1 + v2 + 1 GenPolynomial p2 = notV1.multiply(notV2); //v1*v3 + v1 + v3 + 1 GenPolynomial p3 = notV1.multiply(notV3); polynomials.add(p1); polynomials.add(p2); polynomials.add(p3); polynomials.addAll(fieldPolynomials); //GroebnerBase gb = new GroebnerBaseSeq(); GroebnerBase gb = GBFactory.getImplementation(z2); List> G = gb.GB(polynomials); System.out.println(G); } /** * Example GBase. * */ @SuppressWarnings("unchecked") static public void exampleGB1() { BigRational coeff = new BigRational(); GroebnerBase gb = GBFactory.getImplementation(coeff); String exam = "(x1,x2,y) G " + "( " + "( x1 + x2 - 10 ), ( 2 x1 - x2 + 4 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); PolynomialList F = null; try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { e.printStackTrace(); return; } catch (IOException e) { e.printStackTrace(); return; } System.out.println("F = " + F); List> G = gb.GB(F.list); PolynomialList trinks = new PolynomialList(F.ring, G); System.out.println("G = " + trinks); } /** * Example GBase. * */ @SuppressWarnings("unchecked") static public void exampleGB() { BigRational coeff = new BigRational(); GroebnerBase gb = GBFactory.getImplementation(coeff); String exam = "(x,y) G " + "( " + "( y - ( x^2 - 1 ) ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); PolynomialList F = null; try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { e.printStackTrace(); return; } catch (IOException e) { e.printStackTrace(); return; } System.out.println("F = " + F); List> G = gb.GB(F.list); PolynomialList trinks = new PolynomialList(F.ring, G); System.out.println("G = " + trinks); } /** * Example Trinks GBase. * */ @SuppressWarnings("unchecked") static public void exampleGBTrinks() { BigRational coeff = new BigRational(); GroebnerBase bb = GBFactory.getImplementation(coeff); String exam = "(B,S,T,Z,P,W) L " + "( " + "( 45 P + 35 S - 165 B - 36 ), " + "( 35 P + 40 Z + 25 T - 27 S ), " + "( 15 W + 25 S P + 30 Z - 18 T - 165 B**2 ), " + "( - 9 W + 15 T P + 20 S Z ), " + "( P W + 2 T Z - 11 B**3 ), " + "( 99 W - 11 B S + 3 B**2 ), " + "( B**2 + 33/50 B + 2673/10000 ) " + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); PolynomialList F = null; try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { e.printStackTrace(); return; } catch (IOException e) { e.printStackTrace(); return; } System.out.println("F = " + F); List> G = bb.GB(F.list); PolynomialList trinks = new PolynomialList(F.ring, G); System.out.println("G = " + trinks); } } jas-2.5/src/edu/jas/gbufd/RGroebnerBasePseudoSeq.java0000644000175000017500000004004612014164600022725 0ustar giovannigiovanni/* * $Id: RGroebnerBasePseudoSeq.java 4116 2012-08-19 13:26:25Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.gb.Pair; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RegularRingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisorAbstract; /** * Regular ring Groebner Base with pseudo reduction sequential algorithm. * Implements R-Groebner bases and GB test. * @param coefficient type * @author Heinz Kredel */ public class RGroebnerBasePseudoSeq> extends RGroebnerBaseSeq { private static final Logger logger = Logger.getLogger(RGroebnerBasePseudoSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Greatest common divisor engine for coefficient content and primitive * parts. */ protected final GreatestCommonDivisorAbstract engine; /** * Pseudo reduction engine. */ protected final RPseudoReduction red; /** * Coefficient ring factory. */ protected final RingFactory cofac; /** * Constructor. * @param rf coefficient ring factory. */ public RGroebnerBasePseudoSeq(RingFactory rf) { this(new RPseudoReductionSeq(), rf); } /** * Constructor. * @param red R-pseudo-Reduction engine * @param rf coefficient ring factory. */ public RGroebnerBasePseudoSeq(RPseudoReduction red, RingFactory rf) { super(red); this.red = red; cofac = rf; engine = GCDFactory. getImplementation(rf); // not used: engine = // (GreatestCommonDivisorAbstract)GCDFactory.getProxy( rf ); } /** * R-Groebner base using pairlist class. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a R-Groebner base of F. */ @Override public List> GB(int modv, List> F) { if (F == null) { return F; } /* boolean closure */ List> bcF = red.reducedBooleanClosure(F); logger.info("#bcF-#F = " + (bcF.size() - F.size())); F = bcF; /* normalize input */ List> G = new ArrayList>(); OrderedRPairlist pairlist = null; for (GenPolynomial p : F) { if (!p.isZERO()) { p = engine.basePrimitivePart(p); // not monic, no field p = p.abs(); if (p.isConstant() && p.leadingBaseCoefficient().isFull()) { G.clear(); G.add(p); return G; // since boolean closed and no threads are activated } G.add(p); // G.add( 0, p ); //reverse list if (pairlist == null) { pairlist = new OrderedRPairlist(modv, p.ring); } // putOne not required pairlist.put(p); } } if (G.size() <= 1) { return G; // since boolean closed and no threads are activated } /* loop on critical pairs */ Pair pair; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; // GenPolynomial D; GenPolynomial H; List> bcH; while (pairlist.hasNext()) { pair = pairlist.removeNext(); // System.out.println("pair = " + pair); if (pair == null) continue; pi = pair.pi; pj = pair.pj; if (logger.isDebugEnabled()) { logger.info("pi = " + pi); logger.info("pj = " + pj); } if (!red.moduleCriterion(modv, pi, pj)) { continue; } // S-polynomial ----------------------- // Criterion3(), Criterion4() not applicable S = red.SPolynomial(pi, pj); if (S.isZERO()) { pair.setZero(); continue; } if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(G, S); if (H.isZERO()) { pair.setZero(); continue; } if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = engine.basePrimitivePart(H); H = H.abs(); // not monic, no field if (H.isConstant() && H.leadingBaseCoefficient().isFull()) { // mostly useless G.clear(); G.add(H); return G; // not boolean closed ok, no threads are activated } if (logger.isDebugEnabled()) { logger.debug("H = " + H); } if (!H.isZERO()) { // logger.info("Sred = " + H); // len = G.size(); bcH = red.reducedBooleanClosure(G, H); // logger.info("#bcH = " + bcH.size()); // G.addAll( bcH ); for (GenPolynomial h : bcH) { h = engine.basePrimitivePart(h); h = h.abs(); // monic() not ok, since no field logger.info("bc(Sred) = " + h); G.add(h); pairlist.put(h); } if (debug) { if (!pair.getUseCriterion3() || !pair.getUseCriterion4()) { logger.info("H != 0 but: " + pair); } } } } logger.debug("#sequential list = " + G.size()); G = minimalGB(G); // G = red.irreducibleSet(G); // not correct since not boolean closed logger.info("" + pairlist); return G; } /** * Minimal ordered Groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. */ @Override public List> minimalGB(List> Gp) { if (Gp == null || Gp.size() <= 1) { return Gp; } // remove zero polynomials List> G = new ArrayList>(Gp.size()); for (GenPolynomial a : Gp) { if (a != null && !a.isZERO()) { // always true in GB() a = a.abs(); // already positive in GB G.add(a); } } // remove top reducible polynomials logger.info("minGB start with " + G.size()); GenPolynomial a, b; List> F; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); b = a; if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { // try to drop polynomial List> ff; ff = new ArrayList>(G); ff.addAll(F); a = red.normalform(ff, a); if (a.isZERO()) { //if (false && !isGB(ff)) { // is really required, but why? // logger.info("minGB not dropped " + b); // F.add(b); //} else { if (debug) { logger.debug("minGB dropped " + b); } //} } else { // happens logger.info("minGB not zero " + a); F.add(a); } } else { // not top reducible, keep polynomial F.add(a); } } G = F; Collections.reverse(G); // important for lex GB // reduce remaining polynomials int len = G.size(); int el = 0; while (el < len) { el++; a = G.remove(0); b = a; a = red.normalform(G, a); a = engine.basePrimitivePart(a); // not a.monic() since no field a = a.abs(); if (red.isBooleanClosed(a)) { //List> ff; //ff = new ArrayList>(G); //ff.add(a); //if (true || isGB(ff)) { if (debug) { logger.debug("minGB reduced " + b + " to " + a); } G.add(a); //} else { // logger.info("minGB not reduced " + b + " to " + a); // G.add(b); //} continue; } logger.info("minGB not boolean closed " + a); G.add(b); // do not reduce } /* stratify: collect polynomials with equal leading terms */ ExpVector e, f; F = new ArrayList>(G.size()); List> ff; ff = new ArrayList>(G); for (int i = 0; i < ff.size(); i++) { a = ff.get(i); if (a == null || a.isZERO()) { continue; } e = a.leadingExpVector(); for (int j = i + 1; j < ff.size(); j++) { b = ff.get(j); if (b == null || b.isZERO()) { continue; } f = b.leadingExpVector(); if (e.equals(f)) { // System.out.println("minGB e == f: " + a + ", " + b); a = a.sum(b); ff.set(j, null); } } F.add(a); } //if (true || isGB(F)) { G = F; //} else { // logger.info("minGB not stratified " + F); //} logger.info("minGB end with #G = " + G.size()); return G; } /* * Minimal ordered Groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. * @todo use primitivePart */ List> minimalGBtesting(List> Gp) { if (Gp == null || Gp.size() <= 1) { return Gp; } // remove zero polynomials List> G = new ArrayList>(Gp.size()); for (GenPolynomial a : Gp) { if (a != null && !a.isZERO()) { // always true in GB() // already positive a = a.abs(); G.add(a); } } //if (G.size() <= 1) { // wg monic do not return G; //} // remove top reducible polynomials GenPolynomial a, b; List> F; List> bcH; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); b = a; if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { // drop polynomial if (logger.isInfoEnabled()) { List> ff; ff = new ArrayList>(G); ff.addAll(F); a = red.normalform(ff, a); if (!a.isZERO()) { System.out.println("minGB nf(a) != 0 " + a); bcH = red.reducedBooleanClosure(G, a); if (bcH.size() > 1) { // never happend so far System.out.println("minGB not bc: bcH size = " + bcH.size()); F.add(b); // do not replace, stay with b } else { // System.out.println("minGB add bc(a): a = " + a + ", // bc(a) = " + bcH.get(0)); F.add(b); // do not replace, stay with b // F.addAll( bcH ); } } else { if (!isGB(ff)) { System.out.println("minGB not dropped " + b); F.add(b); } else { System.out.println("minGB dropped " + b); } } } } else { // not top reducible, keep polynomial F.add(a); } } G = F; //if (G.size() <= 1) { // wg monic return G; //} Collections.reverse(G); // important for lex GB // reduce remaining polynomials int len = G.size(); int el = 0; // System.out.println("minGB reducing " + len); while (el < len) { el++; a = G.remove(0); b = a; // System.out.println("minGB doing " + el + ", a = " + a); a = red.normalform(G, a); // not bc: a = engine.basePrimitivePart(a); // not a.monic() since no field if (red.isBooleanClosed(a)) { List> ff; ff = new ArrayList>(G); ff.add(a); if (isGB(ff)) { System.out.println("minGB reduced " + b + " to " + a); G.add(a); } else { System.out.println("minGB not reduced " + b + " to " + a); G.add(b); } continue; } System.out.println("minGB not bc: a = " + a + "\n BC(a) = " + red.booleanClosure(a) + ", BR(a) = " + red.booleanRemainder(a)); bcH = red.reducedBooleanClosure(G, a); if (bcH.size() > 1) { System.out.println("minGB not bc: bcH size = " + bcH.size()); G.add(b); // do not reduce } else { // G.addAll( bcH ); G.add(b); // do not reduce for (GenPolynomial h : bcH) { h = engine.basePrimitivePart(h); h = h.abs(); // monic() not ok, since no field // G.add( h ); } } } // make abs if possible F = new ArrayList>(G.size()); for (GenPolynomial p : G) { a = p.abs(); F.add(a); } G = F; //if (false) { // return G; //} // stratify: collect polynomials with equal leading terms ExpVector e, f; F = new ArrayList>(G.size()); for (int i = 0; i < G.size(); i++) { a = G.get(i); if (a == null || a.isZERO()) { continue; } e = a.leadingExpVector(); for (int j = i + 1; j < G.size(); j++) { b = G.get(j); if (b == null || b.isZERO()) { continue; } f = b.leadingExpVector(); if (e.equals(f)) { // System.out.println("minGB e == f: " + a + ", " + b); a = a.sum(b); G.set(j, null); } } F.add(a); } G = F; // info on boolean algebra element blocks Map>> bd = new TreeMap>>(); for (GenPolynomial p : G) { C cf = p.leadingBaseCoefficient(); cf = cf.idempotent(); List> block = bd.get(cf); if (block == null) { block = new ArrayList>(); } block.add(p); bd.put(cf, block); } System.out.println("\nminGB bd:"); for (Map.Entry>> me : bd.entrySet()) { System.out.println("\nkey = " + me.getKey() + ":"); System.out.println("val = " + me.getValue()); } System.out.println(); // return G; } } jas-2.5/src/edu/jas/gbufd/RReductionSeq.java0000644000175000017500000005331712045447732021166 0ustar giovannigiovanni/* * $Id: RReductionSeq.java 4286 2012-11-04 11:22:02Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.gb.ReductionAbstract; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.structure.RegularRingElem; /** * Polynomial Regular ring Reduction sequential use algorithm. Implements * normalform and boolean closure stuff. * @param coefficient type * @author Heinz Kredel */ public class RReductionSeq> extends ReductionAbstract implements RReduction { private static final Logger logger = Logger.getLogger(RReductionSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public RReductionSeq() { } /** * Is top reducible. Condition is a b != 0, for a=ldcf(A) and b=ldcf(B) and * lt(B) | lt(A) for some B in F. * @param A polynomial. * @param P polynomial list. * @return true if A is top reducible with respect to P. */ @Override public boolean isTopReducible(List> P, GenPolynomial A) { if (P == null || P.isEmpty()) { return false; } if (A == null || A.isZERO()) { return false; } boolean mt = false; ExpVector e = A.leadingExpVector(); C a = A.leadingBaseCoefficient(); a = a.idempotent(); for (GenPolynomial p : P) { mt = e.multipleOf(p.leadingExpVector()); if (mt) { C b = p.leadingBaseCoefficient(); //C r = a.multiply( b ); //C r = a.multiply( b.idempotent() ); C r = a.idempotentAnd(b); mt = !r.isZERO(); if (mt) { return true; } } } return false; } /** * Is strong top reducible. Condition is idempotent(a) == idempotent(b), for * a=ldcf(A) and b=ldcf(B) and lt(B) | lt(A) for some B in F. * @param A polynomial. * @param P polynomial list. * @return true if A is string top reducible with respect to P. */ public boolean isStrongTopReducible(List> P, GenPolynomial A) { if (P == null || P.isEmpty()) { return false; } if (A == null || A.isZERO()) { return false; } boolean mt = false; ExpVector e = A.leadingExpVector(); C a = A.leadingBaseCoefficient(); a = a.idempotent(); for (GenPolynomial p : P) { mt = e.multipleOf(p.leadingExpVector()); if (mt) { C b = p.leadingBaseCoefficient(); mt = a.equals(b.idempotent()); if (mt) { return true; } } } return false; } /** * Is in Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @return true if Ap is in normalform with respect to Pp. */ @Override @SuppressWarnings("unchecked") public boolean isNormalform(List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return true; } if (Ap == null || Ap.isZERO()) { return true; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RegularRingElem[l]; // want GenPolynomial[] p = new GenPolynomial[l]; Map.Entry m; int i; int j = 0; for (i = 0; i < l; i++) { if (P[i] == null) { continue; } p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; boolean mt = false; Map Am = Ap.getMap(); for (Map.Entry me : Am.entrySet()) { ExpVector e = me.getKey(); C a = me.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { //C r = a.multiply( lbc[i] ); //C r = a.idempotent().multiply( lbc[i].idempotent() ); C r = a.idempotentAnd(lbc[i]); mt = !r.isZERO(); if (mt) { return false; } } } } return true; } /** * Normalform using r-reduction. * @param Ap polynomial. * @param Pp polynomial list. * @return r-nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenPolynomial[]) new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } //System.out.println("l = " + l); Map.Entry m; ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RegularRingElem[l]; // want GenPolynomial[] p = (GenPolynomial[]) new GenPolynomial[l]; int i; int j = 0; for (i = 0; i < l; i++) { if (P[i] == null) { continue; } p[i] = P[i].abs(); m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e, f; C a, b; C r = null; boolean mt = false; GenPolynomial R = Ap.ring.getZERO(); GenPolynomial Q = null; GenPolynomial S = Ap; while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); if (debug) { if ( a.isZERO() ) { throw new RuntimeException("a.isZERO(): S = " + S); } } for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { //r = a.multiply( lbc[i] ); //r = a.idempotent().multiply( lbc[i].idempotent() ); r = a.idempotentAnd(lbc[i]); mt = !r.isZERO(); // && mt if (mt) { b = a.divide(lbc[i]); if (b.isZERO()) { // strange case in regular rings System.out.println("b == zero: r = " + r); continue; } f = e.subtract(htl[i]); //logger.info("red div = " + f); Q = p[i].multiply(b, f); S = S.subtract(Q); // not ok with reductum f = S.leadingExpVector(); if (!e.equals(f)) { a = Ap.ring.coFac.getZERO(); break; } a = S.leadingBaseCoefficient(); } } } if (!a.isZERO()) { //! mt ) { //logger.debug("irred"); R = R.sum(a, e); S = S.reductum(); } } return R; //.abs(); // not monic if not boolean closed } /** * GB criterium 4. Use only for commutative polynomial rings. Note: * Experimental version for r-Groebner bases. * @param A polynomial. * @param B polynomial. * @param e = lcm(ht(A),ht(B)) * @return true if the S-polynomial(i,j) is required, else false. */ @Override public boolean criterion4(GenPolynomial A, GenPolynomial B, ExpVector e) { if (logger.isInfoEnabled()) { if (!A.ring.equals(B.ring)) { logger.error("rings equal"); } if (A instanceof GenSolvablePolynomial || B instanceof GenSolvablePolynomial) { logger.error("GBCriterion4 not applicabable to SolvablePolynomials"); return true; } } ExpVector ei = A.leadingExpVector(); ExpVector ej = B.leadingExpVector(); ExpVector g = ei.sum(ej); // boolean t = g == e ; ExpVector h = g.subtract(e); int s = h.signum(); if (s == 0) { // disjoint ht C a = A.leadingBaseCoefficient(); C b = B.leadingBaseCoefficient(); C d = a.multiply(b); if (d.isZERO()) { // a guess //System.out.println("d1 = " + d + ", a = " + a + ", b = " + b); return false; // can skip pair } } return true; //! ( s == 0 ); } /** * GB criterium 4. Use only for commutative polynomial rings. Note: * Experimental version for r-Groebner bases. * @param A polynomial. * @param B polynomial. * @return true if the S-polynomial(i,j) is required, else false. */ @Override public boolean criterion4(GenPolynomial A, GenPolynomial B) { if (logger.isInfoEnabled()) { if (A instanceof GenSolvablePolynomial || B instanceof GenSolvablePolynomial) { logger.error("GBCriterion4 not applicabable to SolvablePolynomials"); return true; } } ExpVector ei = A.leadingExpVector(); ExpVector ej = B.leadingExpVector(); ExpVector g = ei.sum(ej); ExpVector e = ei.lcm(ej); // boolean t = g == e ; ExpVector h = g.subtract(e); int s = h.signum(); if (s == 0) { // disjoint ht C a = A.leadingBaseCoefficient(); C b = B.leadingBaseCoefficient(); C d = a.multiply(b); if (d.isZERO()) { // a guess return false; // can skip pair } } return true; //! ( s == 0 ); } /** * Normalform with recording. * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return Ap - row*Pp = nf(Pp,Ap) , the normal form of Ap wrt. Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(List> row, List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenPolynomial[]) new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } //System.out.println("l = " + l); Map.Entry m; ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RegularRingElem[l]; // want GenPolynomial[] p = (GenPolynomial[]) new GenPolynomial[l]; int i; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e, f; C a; C r = null; boolean mt = false; GenPolynomial fac = null; GenPolynomial zero = Ap.ring.getZERO(); GenPolynomial R = Ap.ring.getZERO(); GenPolynomial Q = null; GenPolynomial S = Ap; while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { //r = a.idempotent().multiply( lbc[i].idempotent() ); //r = a.multiply( lbc[i] ); r = a.idempotentAnd(lbc[i]); //System.out.println("r = " + r); mt = !r.isZERO(); // && mt if (mt) { a = a.divide(lbc[i]); if (a.isZERO()) { // strange case in regular rings System.out.println("b == zero: r = " + r); continue; } f = e.subtract(htl[i]); //logger.info("red div = " + f); Q = p[i].multiply(a, f); S = S.subtract(Q); // not ok with reductum fac = row.get(i); if (fac == null) { fac = zero.sum(a, f); } else { fac = fac.sum(a, f); } row.set(i, fac); f = S.leadingExpVector(); if (!e.equals(f)) { a = Ap.ring.coFac.getZERO(); break; } a = S.leadingBaseCoefficient(); } } } if (!a.isZERO()) { //! mt ) { //logger.debug("irred"); R = R.sum(a, e); S = S.reductum(); } } return R; //.abs(); not for recording } /** * Irreducible set. May not be boolean closed. * @param Pp polynomial list. * @return a list P of polynomials which are in normalform wrt. P. */ @Override public List> irreducibleSet(List> Pp) { ArrayList> P = new ArrayList>(); if (Pp == null) { return null; } for (GenPolynomial a : Pp) { if (!a.isZERO()) { P.add(a); } } int l = P.size(); if (l <= 1) return P; int irr = 0; ExpVector e; ExpVector f; GenPolynomial a; logger.debug("irr = "); while (irr != l) { //a = P.get(0); a = P.remove(0); e = a.leadingExpVector(); a = normalform(P, a); // no not make monic because of boolean closure logger.debug(String.valueOf(irr)); if (a.isZERO()) { l--; if (l <= 1) { return P; } } else { f = a.leadingExpVector(); if (e.equals(f)) { // lbcf(a) eventually shorter // correct since longer coeffs can reduce shorter coeffs irr++; } else { irr = 0; } P.add(a); } } //System.out.println(); return P; } /* * -------- boolean closure stuff ----------------------------------------- */ /** * Is boolean closed, test if A == idempotent(ldcf(A)) A. * @param A polynomial. * @return true if A is boolean closed, else false. */ public boolean isBooleanClosed(GenPolynomial A) { if (A == null || A.isZERO()) { return true; } C a = A.leadingBaseCoefficient(); C i = a.idempotent(); GenPolynomial B = A.multiply(i); // better run idemAnd on coefficients if (A.equals(B)) { return true; } return false; } /** * Is boolean closed, test if all A in F are boolean closed. * @param F polynomial list. * @return true if F is boolean closed, else false. */ public boolean isBooleanClosed(List> F) { if (F == null || F.size() == 0) { return true; } for (GenPolynomial a : F) { if (a == null || a.isZERO()) { continue; } //System.out.println("a = " + a); if (!isBooleanClosed(a)) { return false; } } return true; } /** * Is reduced boolean closed, test if all A in F are boolean closed or br(A) * reduces to zero. * @param F polynomial list. * @return true if F is boolean closed, else false. */ public boolean isReducedBooleanClosed(List> F) { if (F == null || F.size() == 0) { return true; } GenPolynomial b; GenPolynomial r; for (GenPolynomial a : F) { //System.out.println("a = " + a); if (a == null) { continue; } while (!a.isZERO()) { if (!isBooleanClosed(a)) { b = booleanClosure(a); b = normalform(F, b); if (!b.isZERO()) { //F.contains(r) return false; } } r = booleanRemainder(a); r = normalform(F, r); if (!r.isZERO()) { //F.contains(r) return false; } //System.out.println("r = " + r); a = r; } } return true; } /** * Boolean closure, compute idempotent(ldcf(A)) A. * @param A polynomial. * @return bc(A). */ public GenPolynomial booleanClosure(GenPolynomial A) { if (A == null || A.isZERO()) { return A; } C a = A.leadingBaseCoefficient(); C i = a.idempotent(); GenPolynomial B = A.multiply(i); return B; } /** * Boolean remainder, compute idemComplement(ldcf(A)) A. * @param A polynomial. * @return br(A). */ public GenPolynomial booleanRemainder(GenPolynomial A) { if (A == null || A.isZERO()) { return A; } C a = A.leadingBaseCoefficient(); C i = a.idemComplement(); GenPolynomial B = A.multiply(i); return B; } /** * Boolean closure, compute BC(A) for all A in F. * @param F polynomial list. * @return bc(F). */ public List> booleanClosure(List> F) { if (F == null || F.size() == 0) { return F; } List> B = new ArrayList>(F.size()); for (GenPolynomial a : F) { if (a == null) { continue; } while (!a.isZERO()) { GenPolynomial b = booleanClosure(a); B.add(b); a = booleanRemainder(a); } } return B; } /** * Reduced boolean closure, compute BC(A) for all A in F. * @param F polynomial list. * @return red(bc(F)) = bc(red(F)). */ public List> reducedBooleanClosure(List> F) { if (F == null || F.size() == 0) { return F; } List> B = new ArrayList>(F); GenPolynomial a; GenPolynomial b; GenPolynomial c; int len = B.size(); for (int i = 0; i < len; i++) { // not B.size(), it changes a = B.remove(0); if (a == null) { continue; } while (!a.isZERO()) { //System.out.println("a = " + a); b = booleanClosure(a); //System.out.println("b = " + b); b = booleanClosure(normalform(B, b)); if (b.isZERO()) { break; } B.add(b); // adds as last c = a.subtract(b); // = BR(a mod B) //System.out.println("c = " + c); c = normalform(B, c); a = c; } } return B; } /** * Reduced boolean closure, compute BC(A) modulo F. * @param A polynomial. * @param F polynomial list. * @return red(bc(A)). */ public List> reducedBooleanClosure(List> F, GenPolynomial A) { List> B = new ArrayList>(); if (A == null || A.isZERO()) { return B; } GenPolynomial a = A; GenPolynomial b; GenPolynomial c; while (!a.isZERO()) { //System.out.println("a = " + a); b = booleanClosure(a); //System.out.println("b = " + b); b = booleanClosure(normalform(F, b)); if (b.isZERO()) { break; } B.add(b); // adds as last c = a.subtract(b); // = BR(a mod F) //System.out.println("c = " + c); c = normalform(F, c); //System.out.println("c = " + c); a = c; } return B; } } jas-2.5/src/edu/jas/gbufd/PseudoReductionPar.java0000644000175000017500000001667712045530372022217 0ustar giovannigiovanni/* * $Id: PseudoReductionPar.java 4291 2012-11-04 18:16:27Z kredel $ */ package edu.jas.gbufd; import java.util.List; import java.util.ArrayList; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.gb.ReductionAbstract; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Polynomial pseudo reduction sequential use algorithm. Coefficients of * polynomials must not be from a field, i.e. the fraction free reduction is * implemented. Implements normalform. * @param coefficient type * @author Heinz Kredel */ public class PseudoReductionPar> extends ReductionAbstract implements PseudoReduction { private static final Logger logger = Logger.getLogger(PseudoReductionPar.class); /** * Constructor. */ public PseudoReductionPar() { } /** * Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @return nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } GenPolynomial[] P = new GenPolynomial[0]; List> Ppp; synchronized (Pp) { Ppp = new ArrayList>(Pp); // sic } P = Ppp.toArray(P); int ll = Ppp.size(); GenPolynomial Rz = Ap.ring.getZERO(); GenPolynomial R = Rz.copy(); GenPolynomial S = Ap.copy(); while (S.length() > 0) { if (Pp.size() != ll) { //System.out.println("Pp.size() = " + Pp.size() + ", ll = " + ll); //long t = System.currentTimeMillis(); synchronized (Pp) { Ppp = new ArrayList>(Pp); // sic } P = Ppp.toArray(P); ll = Ppp.size(); //ll = P.length; // wrong //t = System.currentTimeMillis()-t; //logger.info("Pp.toArray(): size() = " + l + ", ll = " + ll); S = Ap.copy(); // S.add(R)? // restart reduction ? R = Rz.copy(); } boolean mt = false; Map.Entry m = S.leadingMonomial(); ExpVector e = m.getKey(); C a = m.getValue(); ExpVector f = null; int i; for (i = 0; i < ll; i++) { f = P[i].leadingExpVector(); mt = e.multipleOf(f); if (mt) break; } if (!mt) { //System.out.println("m = " + m); //logger.debug("irred"); //R = R.sum(a, e); //S = S.subtract(a, e); R.doPutToMap(e, a); S.doRemoveFromMap(e, a); //System.out.println(" S = " + S); } else { e = e.subtract(f); //logger.info("red div = " + e); C c = P[i].leadingBaseCoefficient(); if (a.remainder(c).isZERO()) { //c.isUnit() ) { a = a.divide(c); S = S.subtractMultiple(a, e, P[i]); } else { R = R.multiply(c); //S = S.multiply(c); S = S.scaleSubtractMultiple(c, a, e, P[i]); } //Q = p[i].multiply(a, e); //S = S.subtract(Q); } } return R; } /** * Normalform. * @param Pp polynomial list. * @param Ap polynomial. * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor * for Ap. */ @SuppressWarnings("unchecked") public PseudoReductionEntry normalformFactor(List> Pp, GenPolynomial Ap) { if (Ap == null) { return null; } C mfac = Ap.ring.getONECoefficient(); PseudoReductionEntry pf = new PseudoReductionEntry(Ap, mfac); if (Pp == null || Pp.isEmpty()) { return pf; } if (Ap.isZERO()) { return pf; } GenPolynomial[] P = new GenPolynomial[0]; List> Ppp; synchronized (Pp) { Ppp = new ArrayList>(Pp); // sic } P = Ppp.toArray(P); int l = Ppp.size(); boolean mt = false; GenPolynomial Rz = Ap.ring.getZERO(); GenPolynomial R = Rz.copy(); //GenPolynomial T = null; GenPolynomial Q = null; GenPolynomial S = Ap.copy(); while (S.length() > 0) { if (Pp.size() != l) { //long t = System.currentTimeMillis(); synchronized (Pp) { Ppp = new ArrayList>(Pp); } P = Ppp.toArray(P); l = Ppp.size(); //t = System.currentTimeMillis()-t; //logger.info("Pp.toArray() = " + t + " ms, size() = " + l); S = Ap.copy(); // S.add(R)? // restart reduction ? R = Rz.copy(); } Map.Entry m = S.leadingMonomial(); ExpVector e = m.getKey(); C a = m.getValue(); ExpVector f = null; int i; for (i = 0; i < l; i++) { f = P[i].leadingExpVector(); mt = e.multipleOf(f); if (mt) break; } if (!mt) { //logger.debug("irred"); //R = R.sum(a, e); //S = S.subtract(a, e); R.doPutToMap(e, a); S.doRemoveFromMap(e, a); //System.out.println(" S = " + S); } else { e = e.subtract(f); //logger.info("red div = " + e); C c = P[i].leadingBaseCoefficient(); if (a.remainder(c).isZERO()) { //c.isUnit() ) { a = a.divide(c); S = S.subtractMultiple(a, e, P[i]); } else { mfac = mfac.multiply(c); R = R.multiply(c); //S = S.multiply(c); S = S.scaleSubtractMultiple(c, a, e, P[i]); } //Q = p[i].multiply(a, e); //S = S.subtract(Q); } } if (logger.isInfoEnabled()) { logger.info("multiplicative factor = " + mfac); } pf = new PseudoReductionEntry(R, mfac); return pf; } /** * Normalform with recording. Note: Only meaningful if all divisions * are exact. Compute first the multiplication factor m with * normalform(Pp,Ap,m), then call this method with * normalform(row,Pp,m*Ap). * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(List> row, List> Pp, GenPolynomial Ap) { throw new RuntimeException("normalform with recording not implemented"); } } jas-2.5/src/edu/jas/gbufd/RReduction.java0000644000175000017500000000423211505076162020500 0ustar giovannigiovanni/* * $Id: RReduction.java 3423 2010-12-24 10:56:50Z kredel $ */ package edu.jas.gbufd; import java.util.List; import edu.jas.structure.RegularRingElem; import edu.jas.gb.Reduction; import edu.jas.poly.GenPolynomial; /** * Polynomial R Reduction interface. Defines additionally boolean closure * methods. * @param coefficient type * @author Heinz Kredel */ public interface RReduction> extends Reduction { /** * Is strong top reducible. Condition is idempotent(a) == idempotent(b), for * a=ldcf(A) and b=ldcf(B) and lt(B) | lt(A) for some B in F. * @param A polynomial. * @param P polynomial list. * @return true if A is string top reducible with respect to P. */ public boolean isStrongTopReducible(List> P, GenPolynomial A); /** * Is boolean closed, test if A == idempotent(ldcf(A)) A. * @param A polynomial. * @return true if A is boolean closed, else false. */ public boolean isBooleanClosed(GenPolynomial A); /** * Is boolean closed, test if all A in F are boolean closed. * @param F polynomial list. * @return true if F is boolean closed, else false. */ public boolean isBooleanClosed(List> F); /** * Boolean closure, compute idempotent(ldcf(A)) A. * @param A polynomial. * @return bc(A). */ public GenPolynomial booleanClosure(GenPolynomial A); /** * Boolean remainder, compute idemComplement(ldcf(A)) A. * @param A polynomial. * @return br(A) = A - bc(A). */ public GenPolynomial booleanRemainder(GenPolynomial A); /** * Reduced boolean closure, compute BC(A) for all A in F. * @param F polynomial list. * @return red(bc(F)) = bc(red(F)). */ public List> reducedBooleanClosure(List> F); /** * Reduced boolean closure, compute BC(A) modulo F. * @param A polynomial. * @param F polynomial list. * @return red(bc(A)). */ public List> reducedBooleanClosure(List> F, GenPolynomial A); } jas-2.5/src/edu/jas/gbufd/package.html0000644000175000017500000000205111505123724020032 0ustar giovannigiovanni Groebner bases using unique factorization

Groebner bases using unique factorization package.

This package contains classes for polynomial pseudo reduction and Groebner bases using pseudo reduction GroebnerBasePseudoSeq and GroebnerBasePseudoRecSeq. Groebner bases for polynomial rings over regular rings (direct products of fields or integral domains) are implemented in RGroebnerBaseSeq and RGroebnerBasePseudoSeq.


Heinz Kredel

Last modified: Fri Dec 24 15:00:40 CET 2010

$Id: package.html 3430 2010-12-24 14:01:57Z kredel $

jas-2.5/src/edu/jas/gbufd/GroebnerBaseSeqQuotient.java0000644000175000017500000001214512045500020023145 0ustar giovannigiovanni/* * $Id: GroebnerBaseSeqQuotient.java 4290 2012-11-04 14:47:45Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.PolyUfdUtil; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; /** * Groebner Base sequential algorithm for rational function coefficients, * fraction free computation. Implements Groebner bases. * @param Quotient coefficient type * @author Heinz Kredel */ public class GroebnerBaseSeqQuotient> extends GroebnerBaseAbstract> { private static final Logger logger = Logger.getLogger(GroebnerBaseSeqQuotient.class); private final boolean debug = logger.isDebugEnabled(); public final GroebnerBaseAbstract> bba; /** * Constructor. * @param rf quotient coefficient ring factory. */ public GroebnerBaseSeqQuotient(QuotientRing rf) { super(); bba = new GroebnerBasePseudoRecSeq(rf.ring); } /** * Get the String representation with GB engines. * @see java.lang.Object#toString() */ @Override public String toString() { return this.getClass().getSimpleName() + "(" + bba.toString() + ")"; } /** * Groebner base using fraction free computation. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ @Override public List>> GB(int modv, List>> F) { List>> G = F; if (F == null || F.isEmpty()) { return G; } GenPolynomialRing> rring = F.get(0).ring; QuotientRing cf = (QuotientRing) rring.coFac; GenPolynomialRing> iring = new GenPolynomialRing>(cf.ring, rring); List>> Fi = PolyUfdUtil. integralFromQuotientCoefficients(iring, F); //System.out.println("Fi = " + Fi); logger.info("#Fi = " + Fi.size()); List>> Gi = bba.GB(modv, Fi); //System.out.println("Gi = " + Gi); logger.info("#Gi = " + Gi.size()); G = PolyUfdUtil. quotientFromIntegralCoefficients(rring, Gi); G = PolyUtil.> monic(G); return G; } /** * Minimal ordered Groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. */ @Override public List>> minimalGB(List>> Gp) { if (Gp == null || Gp.size() <= 1) { return Gp; } // remove zero polynomials List>> G = new ArrayList>>(Gp.size()); for (GenPolynomial> a : Gp) { if (a != null && !a.isZERO()) { // always true in GB() // already positive a = a.abs(); G.add(a); } } if (G.size() <= 1) { return G; } // remove top reducible polynomials GenPolynomial> a; List>> F; F = new ArrayList>>(G.size()); while (G.size() > 0) { a = G.remove(0); if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { // drop polynomial if (debug) { System.out.println("dropped " + a); List>> ff; ff = new ArrayList>>(G); ff.addAll(F); a = red.normalform(ff, a); if (!a.isZERO()) { System.out.println("error, nf(a) " + a); } } } else { F.add(a); } } G = F; if (G.size() <= 1) { return G; } // reduce remaining polynomials GenPolynomialRing> rring = G.get(0).ring; QuotientRing cf = (QuotientRing) rring.coFac; GenPolynomialRing> iring = new GenPolynomialRing>(cf.ring, rring); List>> Fi = PolyUfdUtil.integralFromQuotientCoefficients(iring, F); logger.info("#Fi = " + Fi.size()); List>> Gi = bba.minimalGB(Fi); logger.info("#Gi = " + Gi.size()); G = PolyUfdUtil. quotientFromIntegralCoefficients(rring, Gi); G = PolyUtil.> monic(G); return G; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { bba.terminate(); } /** * Cancel ThreadPool. */ @Override public int cancel() { return bba.cancel(); } } jas-2.5/src/edu/jas/gbufd/GroebnerBasePseudoRecSeq.java0000644000175000017500000001717712023071546023254 0ustar giovannigiovanni/* * $Id: GroebnerBasePseudoRecSeq.java 4179 2012-09-09 10:45:58Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import org.apache.log4j.Logger; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.OrderedPairlist; import edu.jas.gb.Pair; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisorAbstract; /** * Groebner Base with pseudo reduction sequential algorithm for integral * function coefficients. Implements polynomial fraction free coefficients * Groebner bases. * @param base coefficient type * @author Heinz Kredel * * @see edu.jas.application.GBAlgorithmBuilder * @see edu.jas.gbufd.GBFactory */ public class GroebnerBasePseudoRecSeq> extends GroebnerBaseAbstract> { private static final Logger logger = Logger.getLogger(GroebnerBasePseudoRecSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Greatest common divisor engine for coefficient content and primitive * parts. */ protected final GreatestCommonDivisorAbstract engine; /** * Pseudo reduction engine. */ protected final PseudoReduction> red; /** * Coefficient ring factory. */ protected final RingFactory> cofac; /** * Base coefficient ring factory. */ protected final RingFactory baseCofac; /** * Constructor. * @param rf coefficient ring factory. */ public GroebnerBasePseudoRecSeq(RingFactory> rf) { this(new PseudoReductionSeq>(), rf); } /** * Constructor. * @param red pseudo reduction engine. * @param rf coefficient ring factory. Note: red must be an instance * of PseudoReductionSeq. */ public GroebnerBasePseudoRecSeq(PseudoReduction> red, RingFactory> rf) { super(red); this.red = red; cofac = rf; GenPolynomialRing rp = (GenPolynomialRing) cofac; baseCofac = rp.coFac; //engine = (GreatestCommonDivisorAbstract)GCDFactory.getImplementation( baseCofac ); //not used: engine = GCDFactory. getProxy(baseCofac); } /** * Groebner base using pairlist class. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ //@Override public List>> GB(int modv, List>> F) { GenPolynomial> p; List>> G = new ArrayList>>(); OrderedPairlist> pairlist = null; int l = F.size(); ListIterator>> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = engine.recursivePrimitivePart(p); //p.monic(); p = p.abs(); if (p.isConstant()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); if (pairlist == null) { pairlist = new OrderedPairlist>(modv, p.ring); } // putOne not required pairlist.put(p); } else { l--; } } if (l <= 1) { return G; // since no threads are activated } Pair> pair; GenPolynomial> pi; GenPolynomial> pj; GenPolynomial> S; GenPolynomial> H; while (pairlist.hasNext()) { pair = pairlist.removeNext(); if (pair == null) continue; pi = pair.pi; pj = pair.pj; if (debug) { logger.debug("pi = " + pi); logger.debug("pj = " + pj); } S = red.SPolynomial(pi, pj); if (S.isZERO()) { pair.setZero(); continue; } if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(G, S); if (H.isZERO()) { pair.setZero(); continue; } if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = engine.recursivePrimitivePart(H); //H.monic(); H = H.abs(); if (H.isConstant()) { G.clear(); G.add(H); return G; // since no threads are activated } if (debug) { logger.debug("H = " + H); } if (H.length() > 0) { l++; G.add(H); pairlist.put(H); } } logger.debug("#sequential list = " + G.size()); G = minimalGB(G); logger.info("" + pairlist); return G; } /** * Minimal ordered Groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. */ @Override public List>> minimalGB(List>> Gp) { if (Gp == null || Gp.size() <= 1) { return Gp; } // remove zero polynomials List>> G = new ArrayList>>(Gp.size()); for (GenPolynomial> a : Gp) { if (a != null && !a.isZERO()) { // always true in GB() // already positive a = a.abs(); G.add(a); } } if (G.size() <= 1) { return G; } // remove top reducible polynomials GenPolynomial> a; List>> F; F = new ArrayList>>(G.size()); while (G.size() > 0) { a = G.remove(0); if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { // drop polynomial if (debug) { System.out.println("dropped " + a); List>> ff; ff = new ArrayList>>(G); ff.addAll(F); a = red.normalform(ff, a); if (!a.isZERO()) { System.out.println("error, nf(a) " + a); } } } else { F.add(a); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB // reduce remaining polynomials int len = G.size(); int i = 0; while (i < len) { a = G.remove(0); //System.out.println("doing " + a.length()); a = red.normalform(G, a); a = engine.recursivePrimitivePart(a); //a.monic(); was not required a = a.abs(); //a = red.normalform( F, a ); G.add(a); // adds as last i++; } return G; } } jas-2.5/src/edu/jas/gbufd/MultiplicativeSetFactors.java0000644000175000017500000000727112004501610023403 0ustar giovannigiovanni/* * $Id: MultiplicativeSetFactors.java 4061 2012-07-27 12:03:20Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.FactorAbstract; import edu.jas.ufd.FactorFactory; /** * Multiplicative set of irreducible polynomials. a, b in M implies a*b in M, 1 * in M. * @param coefficient type * @author Heinz Kredel. */ public class MultiplicativeSetFactors> extends MultiplicativeSet { private static final Logger logger = Logger.getLogger(MultiplicativeSetFactors.class); //private final boolean debug = logger.isDebugEnabled(); /** * Factors decomposition engine. */ protected final FactorAbstract engine; /** * MultiplicativeSet constructor. Constructs an empty multiplicative set. * @param ring polynomial ring factory for coefficients. */ public MultiplicativeSetFactors(GenPolynomialRing ring) { super(ring); engine = FactorFactory.getImplementation(ring.coFac); } /** * MultiplicativeSet constructor. * @param ring polynomial ring factory for coefficients. * @param ms a list of non-zero polynomials. * @param eng factorization engine. */ protected MultiplicativeSetFactors(GenPolynomialRing ring, List> ms, FactorAbstract eng) { super(ring, ms); engine = eng; } /** * toString. * @see java.lang.Object#toString() */ @Override public String toString() { return "MultiplicativeSetFactors" + mset; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof MultiplicativeSetFactors)) { return false; } return super.equals(B); } /** * Add polynomial to mset. * @param cc polynomial to be added to mset. * @return new multiplicative set. */ @Override public MultiplicativeSetFactors add(GenPolynomial cc) { if (cc == null || cc.isZERO() || cc.isConstant()) { return this; } if (ring.coFac.isField()) { cc = cc.monic(); } GenPolynomial c = removeFactors(cc); if (c.isConstant()) { logger.info("skipped unit or constant = " + c); return this; } List> list = engine.factorsRadical(c); logger.info("factorsRadical = " + list); if (ring.coFac.isField()) { list = PolyUtil. monic(list); } List> ms = new ArrayList>(mset); for (GenPolynomial p : list) { if (!p.isConstant() && !p.isZERO()) { if (!mset.contains(p)) { logger.info("added to irreducible mset = " + p); ms.add(p); } } } return new MultiplicativeSetFactors(ring, ms, engine); } /** * Replace polynomial list of mset. * @param L polynomial list to replace mset. * @return new multiplicative set. */ @Override public MultiplicativeSetFactors replace(List> L) { MultiplicativeSetFactors ms = new MultiplicativeSetFactors(ring); if (L == null || L.size() == 0) { return ms; } for (GenPolynomial p : L) { ms = ms.add(p); } return ms; } } jas-2.5/src/edu/jas/gbufd/CharacteristicSetWu.java0000644000175000017500000001721212004501610022326 0ustar giovannigiovanni/* * $Id: CharacteristicSetWu.java 4061 2012-07-27 12:03:20Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.OrderedPolynomialList; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisorAbstract; /** * Characteristic Set class acccording to Wu. Implements methods for * Characteristic Sets and tests. * @param coefficient type * @author Heinz Kredel */ public class CharacteristicSetWu> implements CharacteristicSet { private static final Logger logger = Logger.getLogger(CharacteristicSetWu.class); private static boolean debug = logger.isDebugEnabled(); /** * Characteristic set. According to Wu's algorithm with rereduction of * leading coefficients. * @param A list of generic polynomials. * @return charSetWu(A). */ public List> characteristicSet(List> A) { List> S = new ArrayList>(); if (A == null || A.isEmpty()) { return S; } GenPolynomialRing pfac = A.get(0).ring; if (pfac.nvar <= 1) { // take gcd GreatestCommonDivisorAbstract ufd = GCDFactory. getImplementation(pfac.coFac); GenPolynomial g = ufd.gcd(A).monic(); logger.info("charSet base gcd = " + g); S.add(g); return S; } // sort polynomials according to the main variable GenPolynomialRing> rfac = pfac.recursive(1); List>> positiveDeg = new ArrayList>>(); List> zeroDeg = new ArrayList>(); for (GenPolynomial f : A) { if (f.isZERO()) { continue; } f = f.monic(); if (f.isONE()) { S.add(f); return S; } GenPolynomial> fr = PolyUtil. recursive(rfac, f); if (fr.degree(0) == 0) { zeroDeg.add(fr.leadingBaseCoefficient()); } else { positiveDeg.add(fr); } } if (positiveDeg.isEmpty() && zeroDeg.isEmpty()) { return S; } // do pseudo division wrt. the main variable OrderedPolynomialList> opl = new OrderedPolynomialList>(rfac, positiveDeg); List>> pd = new ArrayList>>(opl.list); Collections.reverse(pd); // change OrderedPolynomialList to avoid if (debug) { logger.info("positive degrees: " + pd); } //System.out.println("positive degrees: " + pd); //System.out.println("zero degrees: " + zeroDeg); while (pd.size() > 1) { GenPolynomial> fr = pd.remove(0); GenPolynomial> qr = pd.get(0); // = get(1) logger.info("pseudo remainder by deg = " + qr.degree() + " in variable " + rfac.getVars()[0]); GenPolynomial> rr = PolyUtil. recursiveSparsePseudoRemainder(fr, qr); if (rr.isZERO()) { logger.warn("variety is reducible " + fr + " reduces to zero mod " + pd); // replace qr by gcd(qr,fr) ? continue; } if (rr.degree(0) == 0) { zeroDeg.add(rr.leadingBaseCoefficient().monic()); } else { pd.add(rr); pd = OrderedPolynomialList.sort(rfac, pd); Collections.reverse(pd); // avoid } } // recursion for degree zero polynomials List> Sp = characteristicSet(zeroDeg); // recursion for (GenPolynomial f : Sp) { GenPolynomial fp = f.extend(pfac, 0, 0L); S.add(fp); } //logger.info("charSet recursion, Sp = " + Sp); if (pd.isEmpty()) { return S; } // rereduction of leading coefficient wrt. characteristic set according to Wu GenPolynomial> rr = pd.get(0); GenPolynomial sr = PolyUtil. distribute(pfac, rr); sr = PolyGBUtil. topCoefficientPseudoRemainder(Sp, sr); logger.info("charSet rereduced sr = " + sr); if (sr.isZERO()) { return S; } long d = sr.degree(pfac.nvar - 1); //System.out.println("deg(sr): " + d + ", degv(sr): " + sr.leadingExpVector()); if (d == 0) { // deg zero, invalid characteristic set, restart S.add(0, sr); logger.warn("reducible characteristic set, restarting with S = " + S); return characteristicSet(S); } sr = sr.monic(); S.add(0, sr); return S; } /** * Characteristic set test. * @param A list of generic polynomials. * @return true, if A is (at least a simple) characteristic set, else false. */ public boolean isCharacteristicSet(List> A) { if (A == null || A.isEmpty()) { return true; // ? } GenPolynomialRing pfac = A.get(0).ring; if (pfac.nvar <= 1) { //System.out.println("CS: pfac = " + pfac + ", A = " + A + ", A.size() = " + A.size()); return A.size() <= 1; } if (pfac.nvar < A.size()) { logger.info("not CS: pfac = " + pfac + ", A = " + A); return false; } // select polynomials according to the main variable GenPolynomialRing> rfac = pfac.recursive(1); List> zeroDeg = new ArrayList>(); int positiveDeg = 0; for (GenPolynomial f : A) { if (f.isZERO()) { logger.info("not CS: f = " + f); return false; } //f = f.monic(); GenPolynomial> fr = PolyUtil. recursive(rfac, f); if (fr.degree(0) == 0) { zeroDeg.add(fr.leadingBaseCoefficient()); } else { positiveDeg++; if (positiveDeg > 1) { logger.info("not CS: f = " + f + ", positiveDeg = " + positiveDeg); return false; } } } return isCharacteristicSet(zeroDeg); } /** * Characteristic set reduction. Pseudo remainder wrt. the main variable * with further pseudo reduction of the leading coefficient. * @param P generic polynomial. * @param A list of generic polynomials as characteristic set. * @return * characteristicSetReductionCoeff(A,characteristicSetRemainder(A,P)) */ public GenPolynomial characteristicSetReduction(List> A, GenPolynomial P) { if (A == null || A.isEmpty()) { return P.monic(); } if (P.isZERO()) { return P; } GenPolynomial R = PolyGBUtil. topPseudoRemainder(A, P); //System.out.println("remainder, R = " + R); if (R.isZERO()) { return R; } List> Ap = PolyGBUtil. zeroDegrees(A); //System.out.println("Ap = " + Ap); R = PolyGBUtil. topCoefficientPseudoRemainder(Ap, R); //System.out.println("R = " + R); return R; } } jas-2.5/src/edu/jas/gbufd/CharacteristicSetSimple.java0000644000175000017500000001503312004501610023163 0ustar giovannigiovanni/* * $Id: CharacteristicSetSimple.java 4061 2012-07-27 12:03:20Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.OrderedPolynomialList; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisorAbstract; /** * Characteristic Set class acccording to the simple algorithm, where the * leading coefficients are not rereduced. Implements methods * for Characteristic Sets and tests. * @param coefficient type * @author Heinz Kredel */ public class CharacteristicSetSimple> implements CharacteristicSet { private static final Logger logger = Logger.getLogger(CharacteristicSetSimple.class); private static boolean debug = logger.isDebugEnabled(); /** * Characteristic set. According to the simple algorithm. The leading * coefficients are not rereduced. * @param A list of generic polynomials. * @return charSetWu(A). */ public List> characteristicSet(List> A) { List> S = new ArrayList>(); if (A == null || A.isEmpty()) { return S; } GenPolynomialRing pfac = A.get(0).ring; if (pfac.nvar <= 1) { // take gcd GreatestCommonDivisorAbstract ufd = GCDFactory. getImplementation(pfac.coFac); GenPolynomial g = ufd.gcd(A).monic(); logger.info("charSet base gcd = " + g); S.add(g); return S; } // sort polynomials according to the main variable GenPolynomialRing> rfac = pfac.recursive(1); List>> positiveDeg = new ArrayList>>(); List> zeroDeg = new ArrayList>(); for (GenPolynomial f : A) { if (f.isZERO()) { continue; } f = f.monic(); if (f.isONE()) { S.add(f); return S; } GenPolynomial> fr = PolyUtil. recursive(rfac, f); if (fr.degree(0) == 0) { zeroDeg.add(fr.leadingBaseCoefficient()); } else { positiveDeg.add(fr); } } if (positiveDeg.isEmpty() && zeroDeg.isEmpty()) { return S; } // do pseudo division wrt. the main variable OrderedPolynomialList> opl = new OrderedPolynomialList>(rfac, positiveDeg); List>> pd = new ArrayList>>(opl.list); Collections.reverse(pd); // change OrderedPolynomialList to avoid if (debug) { logger.info("positive degrees: " + pd); } //System.out.println("positive degrees: " + pd); //System.out.println("zero degrees: " + zeroDeg); while (pd.size() > 1) { GenPolynomial> fr = pd.remove(0); GenPolynomial> qr = pd.get(0); // = get(1) logger.info("pseudo remainder by deg = " + qr.degree() + " in variable " + rfac.getVars()[0]); GenPolynomial> rr = PolyUtil. recursiveSparsePseudoRemainder(fr, qr); if (rr.isZERO()) { logger.warn("variety is reducible"); // replace qr by gcd(qr,fr) ? continue; } if (rr.degree(0) == 0) { zeroDeg.add(rr.leadingBaseCoefficient().monic()); } else { pd.add(rr); pd = OrderedPolynomialList.sort(rfac, pd); Collections.reverse(pd); // avoid } } // recursion for degree zero polynomials List> Sp = characteristicSet(zeroDeg); // recursion for (GenPolynomial f : Sp) { GenPolynomial fp = f.extend(pfac, 0, 0L); S.add(fp); } //logger.info("charSet recursion, Sp = " + Sp); if (pd.isEmpty()) { return S; } GenPolynomial> rr = pd.get(0); GenPolynomial sr = PolyUtil. distribute(pfac, rr); sr = sr.monic(); // no rereduction of leading coefficient wrt. characteristic set. S.add(0, sr); return S; } /** * Characteristic set test. * @param A list of generic polynomials. * @return true, if A is (at least a simple) characteristic set, else false. */ public boolean isCharacteristicSet(List> A) { if (A == null || A.isEmpty()) { return true; // ? } GenPolynomialRing pfac = A.get(0).ring; if (pfac.nvar <= 1) { return A.size() <= 1; } if (pfac.nvar < A.size()) { return false; } // select polynomials according to the main variable GenPolynomialRing> rfac = pfac.recursive(1); List> zeroDeg = new ArrayList>(); int positiveDeg = 0; for (GenPolynomial f : A) { if (f.isZERO()) { return false; } //f = f.monic(); GenPolynomial> fr = PolyUtil. recursive(rfac, f); if (fr.degree(0) == 0) { zeroDeg.add(fr.leadingBaseCoefficient()); } else { positiveDeg++; if (positiveDeg > 1) { return false; } } } return isCharacteristicSet(zeroDeg); } /** * Characteristic set reduction. Pseudo remainder wrt. the main variable. * @param P generic polynomial. * @param A list of generic polynomials as characteristic set. * @return characteristicSetRemainder(A,P) */ public GenPolynomial characteristicSetReduction(List> A, GenPolynomial P) { if (A == null || A.isEmpty()) { return P.monic(); } if (P.isZERO()) { return P; } GenPolynomial R = PolyGBUtil. topPseudoRemainder(A, P); R = R.monic(); //System.out.println("remainder, R = " + R); return R; } } jas-2.5/src/edu/jas/gbufd/GroebnerBaseRational.java0000644000175000017500000001204412045530372022450 0ustar giovannigiovanni/* * $Id: GroebnerBaseRational.java 4291 2012-11-04 18:16:27Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; /** * Groebner Base sequential algorithm for rational coefficients, fraction free * computation. Implements Groebner bases. * @param BigRational coefficient type * @author Heinz Kredel */ public class GroebnerBaseRational extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBaseRational.class); private final boolean debug = logger.isDebugEnabled(); public final GroebnerBaseAbstract bba; /** * Constructor. */ public GroebnerBaseRational() { super(); bba = new GroebnerBasePseudoSeq(new BigInteger()); } /** * Constructor. */ public GroebnerBaseRational(int threads) { super(); bba = new GroebnerBasePseudoParallel(threads,new BigInteger()); } /** * Get the String representation with GB engines. * @see java.lang.Object#toString() */ @Override public String toString() { return this.getClass().getSimpleName() + "(" + bba.toString() + ")"; } /** * Groebner base using fraction free computation. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ @Override public List> GB(int modv, List> F) { List> G = F; if (F == null || F.isEmpty()) { return G; } GenPolynomialRing rring = F.get(0).ring; BigInteger cf = new BigInteger(); GenPolynomialRing iring = new GenPolynomialRing(cf, rring); List> Fi = PolyUtil.integerFromRationalCoefficients(iring, F); //System.out.println("Fi = " + Fi); logger.info("#Fi = " + Fi.size()); List> Gi = bba.GB(modv, Fi); //System.out.println("Gi = " + Gi); logger.info("#Gi = " + Gi.size()); G = PolyUtil. fromIntegerCoefficients(rring, Gi); G = PolyUtil. monic(G); return G; } /** * Minimal ordered Groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. */ @Override public List> minimalGB(List> Gp) { if (Gp == null || Gp.size() <= 1) { return Gp; } // remove zero polynomials List> G = new ArrayList>(Gp.size()); for (GenPolynomial a : Gp) { if (a != null && !a.isZERO()) { // always true in GB() // already positive a = a.abs(); G.add(a); } } if (G.size() <= 1) { return G; } // remove top reducible polynomials GenPolynomial a; List> F; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { // drop polynomial if (debug) { System.out.println("dropped " + a); List> ff; ff = new ArrayList>(G); ff.addAll(F); a = red.normalform(ff, a); if (!a.isZERO()) { System.out.println("error, nf(a) " + a); } } } else { F.add(a); } } G = F; if (G.size() <= 1) { return G; } // reduce remaining polynomials GenPolynomialRing rring = G.get(0).ring; BigInteger cf = new BigInteger(); GenPolynomialRing iring = new GenPolynomialRing(cf, rring); List> Fi = PolyUtil.integerFromRationalCoefficients(iring, F); logger.info("#Fi = " + Fi.size()); List> Gi = bba.minimalGB(Fi); logger.info("#Gi = " + Gi.size()); G = PolyUtil. fromIntegerCoefficients(rring, Gi); G = PolyUtil. monic(G); return G; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { bba.terminate(); } /** * Cancel ThreadPool. */ @Override public int cancel() { return bba.cancel(); } } jas-2.5/src/edu/jas/gbufd/MultiplicativeSetSquarefree.java0000644000175000017500000000730412004501610024101 0ustar giovannigiovanni/* * $Id: MultiplicativeSetSquarefree.java 4061 2012-07-27 12:03:20Z kredel $ */ package edu.jas.gbufd; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.SquarefreeAbstract; import edu.jas.ufd.SquarefreeFactory; /** * Multiplicative set of squarefree and co-prime polynomials. a, b in M implies * a*b in M, 1 in M. * @param coefficient type * @author Heinz Kredel. */ public class MultiplicativeSetSquarefree> extends MultiplicativeSet { private static final Logger logger = Logger.getLogger(MultiplicativeSetSquarefree.class); //private final boolean debug = logger.isDebugEnabled(); /** * Squarefree decomposition engine. */ protected final SquarefreeAbstract engine; /** * MultiplicativeSet constructor. Constructs an empty multiplicative set. * @param ring polynomial ring factory for coefficients. */ public MultiplicativeSetSquarefree(GenPolynomialRing ring) { super(ring); engine = SquarefreeFactory.getImplementation(ring.coFac); } /** * MultiplicativeSet constructor. * @param ring polynomial ring factory for coefficients. * @param ms a list of non-zero polynomials. * @param eng squarefree factorization engine. */ protected MultiplicativeSetSquarefree(GenPolynomialRing ring, List> ms, SquarefreeAbstract eng) { super(ring, ms); engine = eng; } /** * toString. * @see java.lang.Object#toString() */ @Override public String toString() { return "MultiplicativeSetSquarefree" + mset; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof MultiplicativeSetSquarefree)) { return false; } return super.equals(B); } /** * Add polynomial to mset. * @param cc polynomial to be added to mset. * @return new multiplicative set. */ @Override public MultiplicativeSetSquarefree add(GenPolynomial cc) { if (cc == null || cc.isZERO() || cc.isConstant()) { return this; } if (ring.coFac.isField()) { cc = cc.monic(); } List> list; if (mset.size() == 0) { list = engine.coPrimeSquarefree(cc, mset); if (ring.coFac.isField()) { list = PolyUtil. monic(list); } return new MultiplicativeSetSquarefree(ring, list, engine); } GenPolynomial c = removeFactors(cc); if (c.isConstant()) { logger.info("skipped unit or constant = " + c); return this; } logger.info("added to squarefree mset = " + c); list = engine.coPrimeSquarefree(c, mset); if (ring.coFac.isField()) { list = PolyUtil. monic(list); } return new MultiplicativeSetSquarefree(ring, list, engine); } /** * Replace polynomial list of mset. * @param L polynomial list to replace mset. * @return new multiplicative set. */ @Override public MultiplicativeSetSquarefree replace(List> L) { MultiplicativeSetSquarefree ms = new MultiplicativeSetSquarefree(ring); if (L == null || L.size() == 0) { return ms; } for (GenPolynomial p : L) { ms = ms.add(p); } return ms; } } jas-2.5/src/edu/jas/gbufd/GBFactory.java0000644000175000017500000003603612070662204020245 0ustar giovannigiovanni/* * $Id: GBFactory.java 4346 2013-01-01 22:34:44Z kredel $ */ package edu.jas.gbufd; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.gb.DGroebnerBaseSeq; import edu.jas.gb.EGroebnerBaseSeq; import edu.jas.gb.GBProxy; import edu.jas.gb.GroebnerBase; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.GroebnerBaseParallel; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.gb.ReductionSeq; import edu.jas.gb.OrderedSyzPairlist; import edu.jas.gb.OrderedPairlist; import edu.jas.gb.PairList; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Groebner bases algorithms factory. Select appropriate Groebner bases engine * based on the coefficient types. * @author Heinz Kredel * @usage To create objects that implement the GroebnerBase * interface use the GBFactory. It will select an * appropriate implementation based on the types of polynomial * coefficients C. The method to obtain an implementation is * getImplementation(). getImplementation() * returns an object of a class which implements the * GroebnerBase interface, more precisely an object of * abstract class GroebnerBaseAbstract. * *
 *
 * GroebnerBase<CT> engine;
 * engine = GBFactory.<CT> getImplementation(cofac);
 * c = engine.GB(A);
 * 
* * For example, if the coefficient type is BigInteger, the usage looks * like * *
 *
 * BigInteger cofac = new BigInteger();
 * GroebnerBase<BigInteger> engine;
 * engine = GBFactory.getImplementation(cofac);
 * c = engine.GB(A);
 * 
* * @see edu.jas.gb.GroebnerBase * @see edu.jas.application.GBAlgorithmBuilder */ public class GBFactory { private static final Logger logger = Logger.getLogger(GBFactory.class); /** * Algorithm indicators: igb = integerGB, egb = e-GB, dgb = d-GB, * qgb = fraction coefficients GB, ffgb = fraction free GB. */ public static enum Algo { igb, egb, dgb, qgb, ffgb }; /** * Protected factory constructor. */ protected GBFactory() { } /** * Determine suitable implementation of GB algorithms, no factory case. * @return GB algorithm implementation for field coefficients. */ public static > GroebnerBaseAbstract getImplementation() { logger.warn("no coefficent factory given, assuming field coeffcients"); GroebnerBaseAbstract bba = new GroebnerBaseSeq(); return bba; } /** * Determine suitable implementation of GB algorithms, case ModLong. * @param fac ModLongRing. * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(ModLongRing fac) { return getImplementation(fac, new OrderedPairlist()); } /** * Determine suitable implementation of GB algorithms, case ModLong. * @param fac ModLongRing. * @param pl pair selection strategy * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(ModLongRing fac, PairList pl) { GroebnerBaseAbstract bba; if (fac.isField()) { bba = new GroebnerBaseSeq(pl); } else { bba = new GroebnerBasePseudoSeq(fac,pl); } return bba; } /** * Determine suitable implementation of GB algorithms, case ModInteger. * @param fac ModIntegerRing. * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(ModIntegerRing fac) { return getImplementation(fac, new OrderedPairlist()); } /** * Determine suitable implementation of GB algorithms, case ModInteger. * @param fac ModIntegerRing. * @param pl pair selection strategy * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(ModIntegerRing fac, PairList pl) { GroebnerBaseAbstract bba; if (fac.isField()) { bba = new GroebnerBaseSeq(pl); } else { bba = new GroebnerBasePseudoSeq(fac,pl); } return bba; } /** * Determine suitable implementation of GB algorithms, case BigInteger. * @param fac BigInteger. * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(BigInteger fac) { return getImplementation(fac, Algo.igb); } /** * Determine suitable implementation of GB algorithms, case BigInteger. * @param fac BigInteger. * @param a algorithm, a = igb, egb, dgb. * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(BigInteger fac, Algo a) { return getImplementation(fac, a, new OrderedPairlist()); } /** * Determine suitable implementation of GB algorithms, case BigInteger. * @param fac BigInteger. * @param pl pair selection strategy * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(BigInteger fac, PairList pl) { return getImplementation(fac, Algo.igb, new OrderedPairlist()); } /** * Determine suitable implementation of GB algorithms, case BigInteger. * @param fac BigInteger. * @param a algorithm, a = igb, egb, dgb. * @param pl pair selection strategy * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(BigInteger fac, Algo a, PairList pl) { GroebnerBaseAbstract bba; switch (a) { case igb: bba = new GroebnerBasePseudoSeq(fac,pl); break; case egb: bba = new EGroebnerBaseSeq(); // pl not suitable break; case dgb: bba = new DGroebnerBaseSeq(); // pl not suitable break; default: throw new IllegalArgumentException("algorithm not available for BigInteger " + a); } return bba; } /** * Determine suitable implementation of GB algorithms, case BigRational. * @param fac BigRational. * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(BigRational fac) { return getImplementation(fac, Algo.qgb, new OrderedPairlist()); } /** * Determine suitable implementation of GB algorithms, case BigRational. * @param fac BigRational. * @param a algorithm, a = qgb, ffgb. * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(BigRational fac, Algo a) { return getImplementation(fac, a, new OrderedPairlist()); } /** * Determine suitable implementation of GB algorithms, case BigRational. * @param fac BigRational. * @param pl pair selection strategy * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(BigRational fac, PairList pl) { return getImplementation(fac, Algo.qgb, pl); } /** * Determine suitable implementation of GB algorithms, case BigRational. * @param fac BigRational. * @param a algorithm, a = qgb, ffgb. * @param pl pair selection strategy * @return GB algorithm implementation. */ public static GroebnerBaseAbstract getImplementation(BigRational fac, Algo a, PairList pl) { GroebnerBaseAbstract bba; switch (a) { case qgb: bba = new GroebnerBaseSeq(pl); break; case ffgb: bba = new GroebnerBaseRational(); // pl not possible break; default: throw new IllegalArgumentException("algorithm not available for BigRational " + a); } return bba; } /** * Determine suitable implementation of GB algorithms, case Quotient coefficients. * @param fac QuotientRing. * @return GB algorithm implementation. */ public static > GroebnerBaseAbstract> getImplementation(QuotientRing fac) { return getImplementation(fac, Algo.qgb, new OrderedPairlist>()); } /** * Determine suitable implementation of GB algorithms, case Quotient coefficients. * @param fac QuotientRing. * @param a algorithm, a = qgb, ffgb. * @return GB algorithm implementation. */ public static > GroebnerBaseAbstract> getImplementation(QuotientRing fac, Algo a) { return getImplementation(fac, a, new OrderedPairlist>()); } /** * Determine suitable implementation of GB algorithms, case Quotient coefficients. * @param fac QuotientRing. * @param pl pair selection strategy * @return GB algorithm implementation. */ public static > GroebnerBaseAbstract> getImplementation(QuotientRing fac, PairList> pl) { return getImplementation(fac, Algo.qgb, pl); } /** * Determine suitable implementation of GB algorithms, case Quotient coefficients. * @param fac QuotientRing. * @param a algorithm, a = qgb, ffgb. * @param pl pair selection strategy * @return GB algorithm implementation. */ public static > GroebnerBaseAbstract> getImplementation(QuotientRing fac, Algo a, PairList> pl) { GroebnerBaseAbstract> bba; switch (a) { case qgb: bba = new GroebnerBaseSeq>(new ReductionSeq>()); break; case ffgb: bba = new GroebnerBaseSeqQuotient(fac); break; default: throw new IllegalArgumentException("algorithm not available for Quotient " + a); } return bba; } /** * Determine suitable implementation of GB algorithms, case (recursive) * polynomial. * @param fac GenPolynomialRing<C>. * @return GB algorithm implementation. */ public static > GroebnerBaseAbstract> getImplementation(GenPolynomialRing fac) { GroebnerBaseAbstract> bba; bba = new GroebnerBasePseudoRecSeq(fac); return bba; } /** * Determine suitable implementation of GB algorithms, case regular rings. * @param fac RegularRing. * @return GB algorithm implementation. */ public static > GroebnerBaseAbstract> getImplementation(ProductRing fac) { GroebnerBaseAbstract> bba; if (fac.onlyFields()) { bba = new RGroebnerBaseSeq>(); } else { bba = new RGroebnerBasePseudoSeq>(fac); } return bba; } /** * Determine suitable implementation of GB algorithms, other cases. * @param fac RingFactory<C>. * @return GB algorithm implementation. */ public static > // interface RingElem not sufficient GroebnerBaseAbstract getImplementation(RingFactory fac) { return getImplementation(fac, new OrderedPairlist()); } /** * Determine suitable implementation of GB algorithms, other cases. * @param fac RingFactory<C>. * @param pl pair selection strategy * @return GB algorithm implementation. */ @SuppressWarnings("unchecked") public static > // interface RingElem not sufficient GroebnerBaseAbstract getImplementation(RingFactory fac, PairList pl) { logger.debug("fac = " + fac.getClass().getName()); if (fac.isField()) { return new GroebnerBaseSeq(pl); } GroebnerBaseAbstract bba = null; Object ofac = fac; if (ofac instanceof GenPolynomialRing) { GenPolynomialRing rofac = (GenPolynomialRing) ofac; GroebnerBaseAbstract> bbr = new GroebnerBasePseudoRecSeq(rofac); bba = (GroebnerBaseAbstract) bbr; } else if (ofac instanceof ProductRing) { ProductRing pfac = (ProductRing) ofac; if (pfac.onlyFields()) { bba = new RGroebnerBaseSeq>(); } else { bba = new RGroebnerBasePseudoSeq>(pfac); } } else { bba = new GroebnerBasePseudoSeq(fac, pl); } logger.debug("bba = " + bba.getClass().getName()); return bba; } /** * Determine suitable concurrent implementation of GB algorithms if * possible. * @param fac RingFactory<C>. * @return GB proxy algorithm implementation. */ public static > // interface RingElem not sufficient GroebnerBaseAbstract getProxy(RingFactory fac) { return getProxy(fac, new OrderedPairlist()); } /** * Determine suitable concurrent implementation of GB algorithms if * possible. * @param fac RingFactory<C>. * @param pl pair selection strategy * @return GB proxy algorithm implementation. */ public static > // interface RingElem not sufficient GroebnerBaseAbstract getProxy(RingFactory fac, PairList pl) { if (ComputerThreads.NO_THREADS) { return GBFactory. getImplementation(fac,pl); } logger.debug("fac = " + fac.getClass().getName()); int th = ( ComputerThreads.N_CPUS > 2 ? ComputerThreads.N_CPUS-1 : 2 ); if (fac.isField()) { GroebnerBaseAbstract e1 = new GroebnerBaseSeq(pl); GroebnerBaseAbstract e2 = new GroebnerBaseParallel(th,pl); return new GBProxy(e1, e2); } else if (fac.getONE() instanceof GcdRingElem && fac.characteristic().signum() == 0) { GroebnerBaseAbstract e1 = new GroebnerBasePseudoSeq(fac,pl); GroebnerBaseAbstract e2 = new GroebnerBasePseudoParallel(th,fac,pl); return new GBProxy(e1, e2); } return getImplementation(fac); } } jas-2.5/src/edu/jas/gbufd/PseudoReduction.java0000644000175000017500000000141511505076162021536 0ustar giovannigiovanni/* * $Id: PseudoReduction.java 3423 2010-12-24 10:56:50Z kredel $ */ package edu.jas.gbufd; import java.util.List; import edu.jas.gb.Reduction; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Polynomial pseudo reduction interface. Defines additionaly normalformFactor. * @param coefficient type. * @author Heinz Kredel */ public interface PseudoReduction> extends Reduction { /** * Normalform with multiplication factor. * @param Pp polynomial list. * @param Ap polynomial. * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor * for Ap. */ public PseudoReductionEntry normalformFactor(List> Pp, GenPolynomial Ap); } jas-2.5/src/edu/jas/gbufd/CharacteristicSet.java0000644000175000017500000000304611751462066022035 0ustar giovannigiovanni/* * $Id: CharacteristicSet.java 3930 2012-05-06 11:44:55Z kredel $ */ package edu.jas.gbufd; import java.io.Serializable; import java.util.List; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Characteristic Set interface. Defines methods for Characteristic Sets and * tests. * @param coefficient type * @author Heinz Kredel */ public interface CharacteristicSet> extends Serializable { /** * Characteristic set. According to the implementing algorithm (simple, Wu, etc). * @param A list of generic polynomials. * @return charSet(A) with at most one polynomial per main variable. */ public List> characteristicSet(List> A); /** * Characteristic set test. * @param A list of generic polynomials. * @return true, if A is (at least a simple) characteristic set, else false. */ public boolean isCharacteristicSet(List> A); /** * Characteristic set reduction. Pseudo remainder wrt. the main variable. * With further pseudo reduction of the leading coefficient depending on the implementing algorithm. * @param P generic polynomial. * @param A list of generic polynomials as characteristic set. * @return characteristicSetRemainder(A,P) or * characteristicSetReductionCoeff(A,characteristicSetRemainder(A,P)) depending on the algorithm. */ public GenPolynomial characteristicSetReduction(List> A, GenPolynomial P); } jas-2.5/src/edu/jas/gbufd/GroebnerBaseFGLM.java0000644000175000017500000003657512023071360021434 0ustar giovannigiovanni/* * $Id: GroebnerBaseFGLM.java 4177 2012-09-09 10:44:00Z suess $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.PairList; import edu.jas.gb.Reduction; import edu.jas.gb.ReductionSeq; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Groebner Base sequential FGLM algorithm. Implements Groebner base computation * via FGLM algorithm. * @param coefficient type * @author Jan Suess * * @see edu.jas.application.GBAlgorithmBuilder * @see edu.jas.gbufd.GBFactory */ public class GroebnerBaseFGLM> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBaseFGLM.class); //private final boolean debug = logger.isDebugEnabled(); /** * The backing GB algorithm implementation. */ private GroebnerBaseAbstract sgb; /** * Constructor. */ public GroebnerBaseFGLM() { super(); sgb = null; } /** * Constructor. * @param red Reduction engine */ public GroebnerBaseFGLM(Reduction red) { super(red); sgb = null; } /** * Constructor. * @param red Reduction engine * @param pl pair selection strategy */ public GroebnerBaseFGLM(Reduction red, PairList pl) { super(red, pl); sgb = null; } /** * Constructor. * @param red Reduction engine * @param pl pair selection strategy * @param gb backing GB algorithm. */ public GroebnerBaseFGLM(Reduction red, PairList pl, GroebnerBaseAbstract gb) { super(red, pl); sgb = gb; } /** * Constructor. * @param gb backing GB algorithm. */ public GroebnerBaseFGLM(GroebnerBaseAbstract gb) { super(); sgb = gb; } /** * Groebner base using FGLM algorithm. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a inv lex term order Groebner base of F. */ public List> GB(int modv, List> F) { if (modv != 0) { throw new UnsupportedOperationException("case modv != 0 not yet implemented"); } if (F == null || F.size() == 0) { return F; } List> G = new ArrayList>(); if (F.size() <= 1) { GenPolynomial p = F.get(0).monic(); G.add(p); return G; } // convert to graded term order List> Fp = new ArrayList>(F.size()); GenPolynomialRing pfac = F.get(0).ring; if (!pfac.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field: " + pfac.coFac); } TermOrder tord = new TermOrder(TermOrder.IGRLEX); GenPolynomialRing gfac = new GenPolynomialRing(pfac.coFac, pfac.nvar, tord, pfac.getVars()); for (GenPolynomial p : F) { GenPolynomial g = gfac.copy(p); // change term order Fp.add(g); } // compute graded term order Groebner base if (sgb == null) { sgb = GBFactory. getImplementation(pfac.coFac); } List> Gp = sgb.GB(modv, Fp); logger.info("graded GB = " + Gp); if (tord.equals(pfac.tord)) { return Gp; } if (Gp.size() == 0) { return Gp; } if (Gp.size() == 1) { GenPolynomial p = pfac.copy(Gp.get(0)); // change term order G.add(p); return G; } // compute invlex Groebner base via FGLM G = convGroebnerToLex(Gp); return G; } /** * Algorithm CONVGROEBNER: Converts Groebner bases w.r.t. total degree * termorder into Groebner base w.r.t to inverse lexicographical term order * @return Groebner base w.r.t to inverse lexicographical term order */ public List> convGroebnerToLex(List> groebnerBasis) { if (groebnerBasis == null || groebnerBasis.size() == 0) { throw new IllegalArgumentException("G may not be null or empty"); } int z = commonZeroTest(groebnerBasis); if (z != 0) { throw new IllegalArgumentException("ideal(G) not zero dimensional, dim = " + z); } //Polynomial ring of input Groebnerbasis G GenPolynomialRing ring = groebnerBasis.get(0).ring; int numberOfVariables = ring.nvar; //Number of Variables of the given Polynomial Ring String[] ArrayOfVariables = ring.getVars(); //Variables of given polynomial ring w.r.t. to input G RingFactory cfac = ring.coFac; //Main Algorithm //Initialization TermOrder invlex = new TermOrder(TermOrder.INVLEX); //Polynomial ring of newGB with invlex order GenPolynomialRing ufac = new GenPolynomialRing(cfac, numberOfVariables, invlex, ArrayOfVariables); //Local Lists List> newGB = new ArrayList>(); //Instantiate the return list of polynomials List> H = new ArrayList>(); //Instantiate a help list of polynomials List> redTerms = new ArrayList>();//Instantiate the return list of reduced terms //Local Polynomials GenPolynomial t = ring.ONE; //Create ONE polynom of original polynomial ring GenPolynomial h; //Create help polynomial GenPolynomial> hh; //h as polynomial in rfac GenPolynomial> p; //Create another help polynomial redTerms.add(t); //Add ONE to list of reduced terms //create new indeterminate Y1 int indeterminates = 1; //Number of indeterminates, starting with Y1 GenPolynomialRing cpfac = createRingOfIndeterminates(ring, indeterminates); GenPolynomialRing> rfac = new GenPolynomialRing>(cpfac, ring); GenPolynomial> q = rfac.getZERO().sum(cpfac.univariate(0)); //Main while loop z = -1; t = lMinterm(H, t); while (t != null) { //System.out.println("t = " + t); h = red.normalform(groebnerBasis, t); //System.out.println("Zwischennormalform h = " + h.toString()); hh = PolyUtil. toRecursive(rfac, h); p = hh.sum(q); List> Cf = new ArrayList>(p.getMap().values()); Cf = red.irreducibleSet(Cf); //System.out.println("Cf = " + Cf); //System.out.println("Current Polynomial ring in Y_n: " + rfac.toString()); z = commonZeroTest(Cf); //System.out.println("z = " + z); if (z != 0) { //z=1 OR z=-1 --> Infinite number of solutions OR No solution indeterminates++; //then, increase number of indeterminates by one redTerms.add(t); //add current t to list of reduced terms cpfac = addIndeterminate(cpfac); rfac = new GenPolynomialRing>(cpfac, ring); hh = PolyUtil. toRecursive(rfac, h); GenPolynomial> Yt = rfac.getZERO().sum(cpfac.univariate(0)); GenPolynomial> Yth = hh.multiply(Yt); q = PolyUtil. extendCoefficients(rfac, q, 0, 0L); q = Yth.sum(q); } else { // z=0 --> one solution GenPolynomial g = ufac.getZERO(); for (GenPolynomial pc : Cf) { ExpVector e = pc.leadingExpVector(); //System.out.println("e = " + e); if (e == null) { continue; } int[] v = e.dependencyOnVariables(); if (v == null || v.length == 0) { continue; } int vi = v[0]; vi = indeterminates - vi; C tc = pc.trailingBaseCoefficient(); if (!tc.isZERO()) { tc = tc.negate(); GenPolynomial csRedterm = redTerms.get(vi - 1).multiply(tc); //System.out.println("csRedterm = " + csRedterm); g = g.sum(csRedterm); } } g = g.sum(t); g = ufac.copy(g); H.add(t); if (!g.isZERO()) { newGB.add(g); logger.info("new element for GB = " + g.leadingExpVector()); } } t = lMinterm(H, t); // compute lMINTERM of current t (lexMinterm) } //logger.info("GB = " + newGB); return newGB; } /** * Algorithm lMinterm: MINTERM algorithm for inverse lexicographical term * order. * @param t Term * @param G Groebner basis * @return Term that specifies condition (D) or null (Condition (D) in * "A computational approach to commutative algebra", Becker, * Weispfenning, Kredel, 1993, p. 427) */ public GenPolynomial lMinterm(List> G, GenPolynomial t) { //not ok: if ( G == null || G.size() == 0 ) ... GenPolynomialRing ring = t.ring; int numberOfVariables = ring.nvar; GenPolynomial u = new GenPolynomial(ring, t.leadingBaseCoefficient(), t.leadingExpVector()); //HeadTerm of of input polynomial ReductionSeq redHelp = new ReductionSeq(); // Create instance of ReductionSeq to use method isReducible //not ok: if ( redHelp.isTopReducible(G,u) ) ... for (int i = numberOfVariables - 1; i >= 0; i--) { // Walk through all variables, starting with least w.r.t to lex-order GenPolynomial x = ring.univariate(i); // Create Linear Polynomial X_i u = u.multiply(x); // Multiply current u with x if (!redHelp.isTopReducible(G, u)) { // Check if any term in HT(G) divides current u return u; } GenPolynomial s = ring.univariate(i, u.degree(numberOfVariables - (i + 1))); //if not, eliminate variable x_i u = u.divide(s); } return null; } /** * Compute the residues to given polynomial list. * @return List of reduced terms */ public List> redTerms(List> groebnerBasis) { if (groebnerBasis == null || groebnerBasis.size() == 0) { throw new IllegalArgumentException("groebnerBasis may not be null or empty"); } GenPolynomialRing ring = groebnerBasis.get(0).ring; int numberOfVariables = ring.nvar; //Number of Variables of the given Polynomial Ring long[] degrees = new long[numberOfVariables]; //Array for the degree-limits for the reduced terms List> terms = new ArrayList>(); //Instantiate the return object for (GenPolynomial g : groebnerBasis) { //For each polynomial of G if (g.isONE()) { terms.clear(); return terms; //If 1 e G, return empty list terms } ExpVector e = g.leadingExpVector(); //Take the exponent of the leading monomial if (e.totalDeg() == e.maxDeg()) { //and check, whether a variable x_i is isolated for (int i = 0; i < numberOfVariables; i++) { long exp = e.getVal(i); if (exp > 0) { degrees[i] = exp; //if true, add the degree of univariate x_i to array degrees } } } } long max = maxArray(degrees); //Find maximum in Array degrees for (int i = 0; i < degrees.length; i++) { //Set all zero grades to maximum of array "degrees" if (degrees[i] == 0) { logger.info("dimension not zero, setting degree to " + max); degrees[i] = max; //--> to "make" the ideal zero-dimensional } } terms.add(ring.ONE); //Add the one-polynomial of the ring to the list of reduced terms ReductionSeq s = new ReductionSeq(); //Create instance of ReductionSeq to use method isReducible //Main Algorithm for (int i = 0; i < numberOfVariables; i++) { GenPolynomial x = ring.univariate(i); //Create Linear Polynomial X_i List> S = new ArrayList>(terms); //Copy all entries of return list "terms" into list "S" for (GenPolynomial t : S) { for (int l = 1; l <= degrees[i]; l++) { t = t.multiply(x); //Multiply current element t with Linear Polynomial X_i if (!s.isReducible(groebnerBasis, t)) { //Check, if t is irreducible mod groebnerbase terms.add(t); //Add t to return list terms } } } } return terms; } /** * Internal method to create a polynomial ring in i indeterminates. Create * new ring over coefficients of ring with i variables Y1,...,Yi * (indeterminate) * @return polynomial ring with variables Y1...Yi and coefficient of ring. */ GenPolynomialRing createRingOfIndeterminates(GenPolynomialRing ring, int i) { RingFactory cfac = ring.coFac; int indeterminates = i; String[] stringIndeterminates = new String[indeterminates]; for (int j = 1; j <= indeterminates; j++) { stringIndeterminates[j - 1] = ("Y" + j); } TermOrder invlex = new TermOrder(TermOrder.INVLEX); GenPolynomialRing cpfac = new GenPolynomialRing(cfac, indeterminates, invlex, stringIndeterminates); return cpfac; } /** * Internal method to add new indeterminates. Add another variabe * (indeterminate) Y_{i+1} to existing ring * @return polynomial ring with variables Y1,..,Yi,Yi+1 and coefficients of * ring. */ GenPolynomialRing addIndeterminate(GenPolynomialRing ring) { String[] stringIndeterminates = new String[1]; int number = ring.nvar + 1; stringIndeterminates[0] = ("Y" + number); ring = ring.extend(stringIndeterminates); return ring; } /** * Maximum of an array. * @return maximum of an array */ long maxArray(long[] t) { if (t.length == 0) { return 0L; } long maximum = t[0]; for (int i = 1; i < t.length; i++) { if (t[i] > maximum) { maximum = t[i]; } } return maximum; } /** * Cleanup and terminate ThreadPool. */ public void terminate() { if ( sgb == null ) { return; } sgb.terminate(); } /** * Cancel ThreadPool. */ public int cancel() { if ( sgb == null ) { return 0; } return sgb.cancel(); } } jas-2.5/src/edu/jas/gbufd/PseudoReductionEntry.java0000644000175000017500000000115411505076162022560 0ustar giovannigiovanni/* * $Id: PseudoReductionEntry.java 3423 2010-12-24 10:56:50Z kredel $ */ package edu.jas.gbufd; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Polynomial reduction container. * Used as container for the return value of normalformFactor. * @author Heinz Kredel */ public class PseudoReductionEntry> { public final GenPolynomial pol; public final C multiplicator; public PseudoReductionEntry(GenPolynomial pol, C multiplicator) { this.pol = pol; this.multiplicator = multiplicator; } } jas-2.5/src/edu/jas/gbufd/MultiplicativeSet.java0000644000175000017500000001746612004501610022070 0ustar giovannigiovanni/* * $Id: MultiplicativeSet.java 4061 2012-07-27 12:03:20Z kredel $ */ package edu.jas.gbufd; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; /** * Multiplicative set of polynomials. a, b in M implies a*b in M, 1 in M. * @param coefficient type * @author Heinz Kredel. */ public class MultiplicativeSet> implements Serializable { private static final Logger logger = Logger.getLogger(MultiplicativeSet.class); //private final boolean debug = logger.isDebugEnabled(); /** * Data structure. */ public final List> mset; /** * Polynomial ring factory. */ public final GenPolynomialRing ring; /** * MultiplicativeSet constructor. Constructs an empty multiplicative set. * @param ring polynomial ring factory for coefficients. */ public MultiplicativeSet(GenPolynomialRing ring) { this(ring, new ArrayList>()); if (ring == null) { throw new IllegalArgumentException("only for non null rings"); } } /** * MultiplicativeSet constructor. * @param ring polynomial ring factory for coefficients. * @param ms a list of non-zero polynomials. */ protected MultiplicativeSet(GenPolynomialRing ring, List> ms) { if (ms == null || ring == null) { throw new IllegalArgumentException("only for non null parts"); } this.ring = ring; mset = ms; } /** * toString. * @see java.lang.Object#toString() */ @Override public String toString() { return "MultiplicativeSet" + mset; } /** * Equals. * @param ob an Object. * @return true if this is equal to o, else false. */ @Override @SuppressWarnings("unchecked") public boolean equals(Object ob) { MultiplicativeSet c = null; try { c = (MultiplicativeSet) ob; } catch (ClassCastException e) { return false; } if (c == null) { return false; } if (!ring.equals(c.ring)) { return false; } return mset.equals(c.mset); } /** * Hash code for this condition. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = h << 17; h += mset.hashCode(); return h; } /** * Is set. * @return true if this is the empty set, else false. */ public boolean isEmpty() { return mset.size() == 0; } /** * Test if a polynomial is contained in this multiplicative set. * @param c polynomial searched in mset. * @return true, if c = prod_{m in mset} m, else false */ public boolean contains(GenPolynomial c) { if (c == null || c.isZERO()) { return false; } if (c.isConstant()) { return true; } if (mset.isEmpty()) { return false; } GenPolynomial d = c; for (GenPolynomial n : mset) { // System.out.println("mset n = " + n); if (n.isONE()) { // do not use 1 continue; } GenPolynomial q, r; do { GenPolynomial[] qr = d.quotientRemainder(n); q = qr[0]; r = qr[1]; // System.out.println("q = " + q + ", r = " + r + ", d = " + d + // ", n = " + n); if (!r.isZERO()) { continue; } if (q.isConstant()) { return true; } d = q; } while (r.isZERO() && !d.isConstant()); } return d.isConstant(); // false } /** * Test if a list of polynomials is contained in multiplicative set. * @param L list of polynomials to be searched in mset. * @return true, if all c in L are in mset, else false */ public boolean contains(List> L) { if (L == null || L.size() == 0) { return true; } for (GenPolynomial c : L) { if (!contains(c)) { return false; } } return true; } /** * Add polynomial to mset. * @param cc polynomial to be added to mset. * @return new multiplicative set. Note: must be overridden in * sub-classes. */ public MultiplicativeSet add(GenPolynomial cc) { if (cc == null || cc.isZERO() || cc.isConstant()) { return this; } if (ring.coFac.isField()) { cc = cc.monic(); } List> list; if (mset.size() == 0) { list = new ArrayList>(1); list.add(cc); return new MultiplicativeSet(ring, list); } GenPolynomial c = removeFactors(cc); if (c.isConstant()) { logger.info("skipped unit or constant = " + c); return this; } if (ring.coFac.isField()) { c = c.monic(); } if (mset.size() == 0) { logger.info("added to empty mset = " + c); } else { logger.info("added to mset = " + c); } list = new ArrayList>(mset); list.add(c); return new MultiplicativeSet(ring, list); } /** * Replace polynomial list of mset. * @param L polynomial list to replace mset. * @return new multiplicative set. Note: must be overridden in * sub-classes. */ public MultiplicativeSet replace(List> L) { MultiplicativeSet ms = new MultiplicativeSet(ring); if (L == null || L.size() == 0) { return ms; } for (GenPolynomial p : L) { ms = ms.add(p); } return ms; } /** * Remove factors by mset factors division. * @param cc polynomial to be removed factors from mset. * @return quotient polynomial. */ public GenPolynomial removeFactors(GenPolynomial cc) { if (cc == null || cc.isZERO() || cc.isConstant()) { return cc; } if (mset.size() == 0) { return cc; } GenPolynomial c = cc; for (GenPolynomial n : mset) { if (n.isConstant()) { // do not use 1, should not be in mset continue; } GenPolynomial q, r; do { GenPolynomial[] qr = c.quotientRemainder(n); q = qr[0]; r = qr[1]; if (r != null && !r.isZERO()) { continue; } if (q != null && q.isConstant()) { return q; } c = q; } while (r.isZERO() && !c.isConstant()); } return c; } /** * Remove factors by mset factors division. * @param L list of polynomial to be removed factors from mset. * @return quotient polynomial list. */ public List> removeFactors(List> L) { if (L == null || L.size() == 0) { return L; } if (mset.size() == 0) { return L; } List> M = new ArrayList>(L.size()); for (GenPolynomial p : L) { p = removeFactors(p); // nono, really: if ( !p.isConstant() ) { M.add(p); } return M; } } jas-2.5/src/edu/jas/gbufd/GroebnerBasePseudoParallel.java0000644000175000017500000003435512045500020023607 0ustar giovannigiovanni/* * $Id: GroebnerBasePseudoParallel.java 4290 2012-11-04 14:47:45Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.OrderedPairlist; import edu.jas.gb.Pair; import edu.jas.gb.PairList; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisorAbstract; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; /** * Groebner Base with pseudo reduction multi-threaded parallel algorithm. * Implements coefficient fraction free Groebner bases. * @param coefficient type * @author Heinz Kredel * * @see edu.jas.application.GBAlgorithmBuilder * @see edu.jas.gbufd.GBFactory */ public class GroebnerBasePseudoParallel> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBasePseudoParallel.class); private final boolean debug = logger.isDebugEnabled(); /** * Number of threads to use. */ protected final int threads; /** * Pool of threads to use. */ protected transient final ThreadPool pool; /** * Greatest common divisor engine for coefficient content and primitive * parts. */ protected final GreatestCommonDivisorAbstract engine; /** * Pseudo reduction engine. */ protected final PseudoReduction red; /** * Coefficient ring factory. */ protected final RingFactory cofac; /** * Constructor. * @param threads number of threads to use. * @param rf coefficient ring factory. */ public GroebnerBasePseudoParallel(int threads, RingFactory rf) { this(threads, rf, new PseudoReductionPar()); } /** * Constructor. * @param threads number of threads to use. * @param rf coefficient ring factory. Note: red must be an instance * of PseudoReductionPar. * @param red pseudo reduction engine. */ public GroebnerBasePseudoParallel(int threads, RingFactory rf, PseudoReduction red) { this(threads, rf, red, new ThreadPool(threads)); } /** * Constructor. * @param threads number of threads to use. * @param rf coefficient ring factory. Note: red must be an instance * of PseudoReductionPar. * @param red pseudo reduction engine. * @param pool ThreadPool to use. */ public GroebnerBasePseudoParallel(int threads, RingFactory rf, PseudoReduction red, ThreadPool pool) { this(threads, rf, red, pool, new OrderedPairlist()); } /** * Constructor. * @param threads number of threads to use. * @param rf coefficient ring factory. Note: red must be an instance * of PseudoReductionPar. * @param pl pair selection strategy */ public GroebnerBasePseudoParallel(int threads, RingFactory rf, PairList pl) { this(threads, rf, new PseudoReductionPar(), new ThreadPool(threads), pl); } /** * Constructor. * @param threads number of threads to use. * @param rf coefficient ring factory. Note: red must be an instance * of PseudoReductionPar. * @param red pseudo reduction engine. * @param pool ThreadPool to use. * @param pl pair selection strategy */ public GroebnerBasePseudoParallel(int threads, RingFactory rf, PseudoReduction red, ThreadPool pool, PairList pl) { super(red, pl); if (!(red instanceof PseudoReductionPar)) { logger.warn("parallel GB should use parallel aware reduction"); } this.red = red; cofac = rf; if (threads < 1) { threads = 1; } this.threads = threads; engine = GCDFactory. getImplementation(rf); //not used: engine = (GreatestCommonDivisorAbstract)GCDFactory.getProxy( rf ); this.pool = pool; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { if (pool == null) { return; } pool.terminate(); } /** * Cancel ThreadPool. */ @Override public int cancel() { if (pool == null) { return 0; } int s = pool.cancel(); return s; } /** * Groebner base using pairlist class. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> GB(int modv, List> F) { GenPolynomial p; List> G = new ArrayList>(); PairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = engine.basePrimitivePart(p); //p.monic(); p = p.abs(); if (p.isConstant()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); if (pairlist == null) { //pairlist = new OrderedPairlist(modv, p.ring); pairlist = strategy.create(modv, p.ring); } // putOne not required pairlist.put(p); } else { l--; } } if (l <= 1) { return G; // since no threads are activated } logger.info("start " + pairlist); Terminator fin = new Terminator(threads); PseudoReducer R; for (int i = 0; i < threads; i++) { R = new PseudoReducer(fin, G, pairlist, engine); pool.addJob(R); } fin.waitDone(); if (Thread.currentThread().isInterrupted()) { throw new RuntimeException("interrupt before minimalGB"); } logger.debug("#parallel list = " + G.size()); G = minimalGB(G); logger.info("" + pairlist); return G; } /** * Minimal ordered Groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. */ @Override public List> minimalGB(List> Gp) { if (Gp == null || Gp.size() <= 1) { return Gp; } // remove zero polynomials List> G = new ArrayList>(Gp.size()); for (GenPolynomial a : Gp) { if (a != null && !a.isZERO()) { // always true in GB() // already positive a = a.abs(); G.add(a); } } if (G.size() <= 1) { return G; } // remove top reducible polynomials GenPolynomial a; List> F; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { // drop polynomial if (debug) { System.out.println("dropped " + a); List> ff; ff = new ArrayList>(G); ff.addAll(F); a = red.normalform(ff, a); if (!a.isZERO()) { System.out.println("error, nf(a) " + a); } } } else { F.add(a); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB // reduce remaining polynomials @SuppressWarnings("cast") PseudoMiReducer[] mirs = (PseudoMiReducer[]) new PseudoMiReducer[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); // System.out.println("doing " + a.length()); mirs[i] = new PseudoMiReducer(R, a, engine); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } } /** * Pseudo GB Reducing worker threads. */ class PseudoReducer> implements Runnable { private final List> G; private final PairList pairlist; private final Terminator fin; private final PseudoReductionPar red; private final GreatestCommonDivisorAbstract engine; private static final Logger logger = Logger.getLogger(PseudoReducer.class); PseudoReducer(Terminator fin, List> G, PairList L, GreatestCommonDivisorAbstract engine) { this.fin = fin; this.G = G; pairlist = L; red = new PseudoReductionPar(); this.engine = engine; fin.initIdle(1); } /** * to string */ @Override public String toString() { return "PseudoReducer"; } public void run() { Pair pair; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial H; //boolean set = false; int reduction = 0; int sleeps = 0; while (pairlist.hasNext() || fin.hasJobs()) { while (!pairlist.hasNext()) { // wait //fin.beIdle(); set = true; try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } else { logger.debug("r"); } Thread.sleep(100); } catch (InterruptedException e) { break; } if (!fin.hasJobs()) { break; } } if (!pairlist.hasNext() && !fin.hasJobs()) { break; } fin.notIdle(); // before pairlist get pair = pairlist.removeNext(); if (Thread.currentThread().isInterrupted()) { fin.initIdle(1); throw new RuntimeException("interrupt after removeNext"); } if (pair == null) { fin.initIdle(1); continue; } pi = pair.pi; pj = pair.pj; if (logger.isDebugEnabled()) { logger.debug("pi = " + pi); logger.debug("pj = " + pj); } S = red.SPolynomial(pi, pj); if (S.isZERO()) { pair.setZero(); fin.initIdle(1); continue; } if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(G, S); //mod reduction++; if (H.isZERO()) { pair.setZero(); fin.initIdle(1); continue; } if (logger.isDebugEnabled()) { logger.info("ht(H) = " + H.leadingExpVector()); } H = engine.basePrimitivePart(H); //H.monic(); H = H.abs(); // System.out.println("H = " + H); if (H.isONE()) { // putOne not required pairlist.put(H); synchronized (G) { G.clear(); G.add(H); } fin.allIdle(); return; } if (logger.isDebugEnabled()) { logger.debug("H = " + H); } synchronized (G) { G.add(H); } pairlist.put(H); fin.initIdle(1); } fin.allIdle(); logger.info("terminated, done " + reduction + " reductions"); } } /** * Pseudo Reducing worker threads for minimal GB. */ class PseudoMiReducer> implements Runnable { private final List> G; private GenPolynomial H; private final PseudoReductionPar red; private final Semaphore done = new Semaphore(0); private final GreatestCommonDivisorAbstract engine; private static final Logger logger = Logger.getLogger(PseudoMiReducer.class); PseudoMiReducer(List> G, GenPolynomial p, GreatestCommonDivisorAbstract engine) { this.G = G; this.engine = engine; H = p; red = new PseudoReductionPar(); } /** * to string */ @Override public String toString() { return "PseudoMiReducer"; } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenPolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException e) { throw new RuntimeException("interrupt in getNF"); } return H; } public void run() { if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } try { H = red.normalform(G, H); //mod H = engine.basePrimitivePart(H); //H.monic(); H = H.abs(); done.release(); //done.V(); } catch (RuntimeException e) { Thread.currentThread().interrupt(); //throw new RuntimeException("interrupt in getNF"); } if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } jas-2.5/src/edu/jas/gbufd/GroebnerBaseFGLMExamples.java0000644000175000017500000012423512013670560023130 0ustar giovannigiovanni/* * $Id: GroebnerBaseFGLMExamples.java 4106 2012-08-18 10:41:52Z suess $ */ package edu.jas.gbufd; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.math.BigInteger; import java.util.Arrays; import java.util.Collections; import java.util.List; import junit.framework.Test; import junit.framework.TestCase; import junit.framework.TestSuite; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.gb.GroebnerBase; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.Monomial; import edu.jas.poly.OrderedPolynomialList; import edu.jas.poly.PolyUtil; import edu.jas.poly.PolynomialList; /** * Groebner base FGLM examples with JUnit. * @author Jan Suess. */ public class GroebnerBaseFGLMExamples extends TestCase { /** * main */ public static void main(String[] args) { //BasicConfigurator.configure(); junit.textui.TestRunner.run(suite()); } /** * Constructs a GroebnerBaseFGLMExamples object. * @param name String. */ public GroebnerBaseFGLMExamples(String name) { super(name); } /** * suite. */ public static Test suite() { TestSuite suite = new TestSuite(GroebnerBaseFGLMExamples.class); return suite; } //field Q String all = "Zahlbereich | Ordnung | Elements G | Elements L | bitHeight G | bitHeight L | Deg G | Deg L | Time G | Time FGLM | Time L"; String grad = "Zahlbereich | Ordnung | Elements G | bitHeight G | Deg G | Time G | vDim"; String lex = "Zahlbereich | Ordnung | Elements L | bitHeight L | Deg L | Time L"; String fglm = "Zahlbereich | Ordnung | Elements G | Elements L | bitHeight G | bitHeight L | Deg G | Deg L | Time G | Time FGLM"; //MOD 1831 String modAll = "Zahlbereich | Ordnung | Elements G | Elements L | Deg G | Deg L | Time G | Time FGLM | Time L"; String modGrad = "Zahlbereich | Ordnung | Elements G | Deg G | Time G"; String modfglm = "Zahlbereich | Ordnung | Elements G | Elements L | Deg G | Deg L | Time G | Time FGLM"; @Override protected void setUp() { System.out.println("Setup"); } @Override protected void tearDown() { System.out.println("Tear Down"); } //Test with five variables and different variable orders public void xtestFiveVarsOrder() { String polynomials = "( " + " (v^8*x*y*z), ( w^3*x - 2*v), ( 4*x*y - 2 + y), ( 3*y^5 - 3 + z ), ( 8*y^2*z^2 + x * y^6 )" + ") "; String[] order = new String[] { "v", "w", "x", "y", "z" }; //String order1 = shuffle(order); String order2 = shuffle(order); //String order3 = shuffle(order); //String order4 = shuffle(order); //String order5 = shuffle(order); //String order6 = "(z,w,v,y,x)"; //langsam //String order7 = "(v,z,w,y,x)"; //langsam //String order8 = "(w,z,v,x,y)"; //langsam /* String erg1 = testGeneral(order1, polynomials); String erg2 = testGeneral(order2, polynomials); String erg3 = testGeneral(order3, polynomials); String erg4 = testGeneral(order4, polynomials); String erg5 = testGeneral(order5, polynomials); */ String ergM13 = modAll(order2, polynomials, 13); String ergM7 = modAll(order2, polynomials, 7); /* String ergOnlyL_1 = testOnlyLex(order1, polynomials); String ergOnlyL_2 = testOnlyLex(order2, polynomials); String ergOnlyL_3 = testOnlyLex(order3, polynomials); String ergOnlyL_4 = testOnlyLex(order4, polynomials); String ergOnlyL_5 = testOnlyLex(order5, polynomials); String erg6 = testGeneral(order6, polynomials); String erg7 = testGeneral(order7, polynomials); String erg8 = testGeneral(order8, polynomials); */ //langsam: (z,w,v,y,x), (v,z,w,y,x) /* System.out.println(categoryLex); System.out.println(ergOnlyL_1); System.out.println(ergOnlyL_2); System.out.println(ergOnlyL_3); System.out.println(ergOnlyL_4); System.out.println(ergOnlyL_5); System.out.println(category); System.out.println(erg6); System.out.println(erg7); System.out.println(erg8); System.out.println(erg1); System.out.println(erg2); System.out.println(erg3); System.out.println(erg4); System.out.println(erg5); */ System.out.println(all); System.out.println("Mod 13"); System.out.println(ergM13); System.out.println("Mod 7"); System.out.println(ergM7); } //=================================================================== //Examples taken from "Efficient Computation of Zero-Dimensional Gröbner Bases by Change of Ordering", // 1994, Faugere, Gianni, Lazard, Mora (FGLM) //=================================================================== public void xtestCAP() { String polynomials = "( " + " (y^2*z + 2*x*y*t - 2*x - z)," + "(-x^3*z + 4*x*y^2*z + 4*x^2*y*t + 2*y^3*t + 4*x^2 - 10*y^2 + 4*x*z - 10*y*t + 2)," + "(2*y*z*t + x*t^2 - x - 2*z)," + "(-x*z^3 + 4*y*z^2*t + 4*x*z*t^2 + 2*y*t^3 + 4*x*z + 4*z^2 - 10*y*t -10*t^2 + 2)" + ") "; String orderINV = "(x,y,z,t)"; String orderL = "(t,z,y,x)"; //Tests String erg_deg = grad(orderINV, polynomials); System.out.println(grad); System.out.println(erg_deg); String erg1 = all(orderINV, polynomials); String erg2 = all(orderL, polynomials); String ergMod1 = modAll(orderINV, polynomials, 1831); String ergMod2 = modAll(orderL, polynomials, 1831); System.out.println(all); System.out.println(erg1); System.out.println(erg2); System.out.println("\n"); System.out.println(modAll); System.out.println(ergMod1); System.out.println(ergMod2); } public void xtestAUX() { String polynomials = "( " + " (a^2*b*c + a*b^2*c + a*b*c^2 + a*b*c + a*b + a*c + b*c)," + "(a^2*b^2*c + a*b^2*c^2 + a^2*b*c + a*b*c + b*c + a + c )," + "(a^2*b^2*c^2 + a^2*b^2*c + a*b^2*c + a*b*c + a*c + c + 1)" + ") "; String orderINV = "(a,b,c)"; String orderL = "(c,b,a)"; //Tests String erg_deg = grad(orderINV, polynomials); System.out.println(grad); System.out.println(erg_deg); String erg1 = all(orderINV, polynomials); String erg2 = all(orderL, polynomials); String ergMod1 = modAll(orderINV, polynomials, 1831); String ergMod2 = modAll(orderL, polynomials, 1831); System.out.println(all); System.out.println(erg1); System.out.println(erg2); System.out.println("\n"); System.out.println(modAll); System.out.println(ergMod1); System.out.println(ergMod2); } public void testC5() { String polynomials = "( " + " (a + b + c + d + e)," + "(a*b + b*c + c*d + a*e + d*e)," + "(a*b*c + b*c*d + a*b*e + a*d*e + c*d*e)," + "(a*b*c*d + a*b*c*e + a*b*d*e + a*c*d*e + b*c*d*e)," + "(a*b*c*d*e -1)" + ") "; String orderINV = "(a,b,c,d,e)"; String orderL = "(e,d,c,b,a)"; //Tests String erg_deg = grad(orderINV, polynomials); //System.out.println(grad); //System.out.println(erg_deg); String erg1 = all(orderINV, polynomials); String erg2 = all(orderL, polynomials); String ergMod1 = modAll(orderINV, polynomials, 1831); String ergMod2 = modAll(orderL, polynomials, 1831); System.out.println(grad); System.out.println(erg_deg); System.out.println(""); System.out.println(all); System.out.println(erg1); System.out.println(erg2); System.out.println("\n"); System.out.println(modAll); System.out.println(ergMod1); System.out.println(ergMod2); } public void xtestModC5() { String polynomials = "( " + " (a + b + c + d + e)," + "(a*b + b*c + c*d + a*e + d*e)," + "(a*b*c + b*c*d + a*b*e + a*d*e + c*d*e)," + "(b*c*d + a*b*c*e + a*b*d*e + a*c*d*e + b*c*d*e)," + "(a*b*c*d*e -1)" + ") "; String orderINV = "(a,b,c,d,e)"; String orderL = "(e,d,c,b,a)"; //Tests String erg_deg = grad(orderL, polynomials); System.out.println(grad); System.out.println(erg_deg); /* String ergOnlyFGLM_1 = fglm(orderINV, polynomials); System.out.println(fglm); System.out.println(ergOnlyFGLM_1); //Tests MODULO String ergOnlyG_1 = modGrad(orderINV, polynomials, 1831); System.out.println(modGrad); System.out.println(ergOnlyG_1); String erg1 = modfglm(orderINV, polynomials, 1831); System.out.println(modfglm); System.out.println(erg1); */ } public void xtestC6() { String polynomials = "( " + " (a + b + c + d + e + f)," + "(a*b + b*c + c*d + d*e + e*f + a*f)," + "(a*b*c + b*c*d + c*d*e + d*e*f + a*e*f + a*b*f)," + "(a*b*c*d + b*c*d*e + c*d*e*f + a*d*e*f + a*b*e*f + a*b*c*f)," + "(a*b*c*d*e + b*c*d*e*f + a*c*d*e*f + a*b*d*e*f + a*b*c*e*f + a*b*c*d*f)," + "(a*b*c*d*e*f - 1)" + ") "; String orderINV = "(a,b,c,d,e,f)"; String orderL = "(f,e,d,c,b,a)"; //Tests /* String erg2 = modAll(orderINV, polynomials, 1831); System.out.println(modAll); System.out.println(erg2); String ergOnlyG_1 = modGrad(orderINV, polynomials, 1831); System.out.println(modGrad); System.out.println(ergOnlyG_1); String erg1 = modfglm(orderINV, polynomials, 1831); System.out.println(modfglm); System.out.println(erg1); */ } //=================================================================== //Examples taken from "Der FGLM-Algorithmus: verallgemeinert und implementiert in SINGULAR", 1997, Wichmann //=================================================================== public void xtestIsaac() { String polynomials = "( " + " (8*w^2 + 5*w*x - 4*w*y + 2*w*z + 3*w + 5*x^2 + 2*x*y - 7*x*z - 7*x + 7*y^2 -8*y*z - 7*y + 7*z^2 - 8*z + 8)," + "(3*w^2 - 5*w*x - 3*w*y - 6*w*z + 9*w + 4*x^2 + 2*x*y - 2*x*z + 7*x + 9*y^2 + 6*y*z + 5*y + 7*z^2 + 7*z + 5)," + "(-2*w^2 + 9*w*x + 9*w*y - 7*w*z - 4*w + 8*x^2 + 9*x*y - 3*x*z + 8*x + 6*y^2 - 7*y*z + 4*y - 6*z^2 + 8*z + 2)," + "(7*w^2 + 5*w*x + 3*w*y - 5*w*z - 5*w + 2*x^2 + 9*x*y - 7*x*z + 4*x -4*y^2 - 5*y*z + 6*y - 4*z^2 - 9*z + 2)" + ") "; String orderINV = "(w,x,y,z)"; String orderL = "(z,y,x,w)"; //Tests String erg_deg = grad(orderL, polynomials); System.out.println(grad); System.out.println(erg_deg); /* String erg3 = all(orderINV, polynomials); System.out.println(all); System.out.println(erg3); String ergOnlyLex_1 = lex(orderINV, polynomials); String ergOnlyLex_2 = lex(orderL, polynomials); System.out.println(lex); System.out.println(ergOnlyLex_1); System.out.println(ergOnlyLex_2); String ergOnlyFGLM_1 = fglm(orderINV, polynomials); String ergOnlyFGLM_2 = fglm(orderL, polynomials); System.out.println(fglm); System.out.println(ergOnlyFGLM_1); System.out.println(ergOnlyFGLM_2); String ergm1 = modAll(orderINV, polynomials, 2147464751); String ergm2 = modAll(orderL, polynomials, 2147464751); System.out.println(modAll); System.out.println(ergm1); System.out.println(ergm2); */ } public void xtestNiermann() { String polynomials = "( " + " (x^2 + x*y^2*z - 2*x*y + y^4 + y^2 + z^2)," + "(-x^3*y^2 + x*y^2*z + x*y*z^3 - 2*x*y + y^4)," + "(-2*x^2*y + x*y^4 + y*z^4 - 3)" + ") "; String orderINV = "(x,y,z)"; String orderL = "(z,y,x)"; //Tests String erg_deg = grad(orderINV, polynomials); System.out.println(grad); System.out.println(erg_deg); /* String erg1 = fglm(orderINV, polynomials); String erg2 = fglm(orderL, polynomials); System.out.println(fglm); System.out.println(erg1); System.out.println(erg2); */ String ergm1 = modfglm(orderINV, polynomials, 1831); String ergm2 = modfglm(orderL, polynomials, 2147464751); System.out.println(modfglm); System.out.println(ergm1); System.out.println(ergm2); } public void ytestWalkS7() { String polynomials = "( " + " (2*g*b + 2*f*c + 2*e*d + a^2 + a)," + "(2*g*c + 2*f*d + e^2 + 2*b*a + b)," + "(2*g*d + 2*f*e + 2*c*a + c + b^2)," + "(2*g*e + f^2 + 2*d*a + d + 2*c*b)," + "(2*g*f + 2*e*a + e + 2*d*b + c^2)," + "(g^2 + 2*f*a + f + 2*e*b + 2*d*c)," + "(2*g*a + g + 2*f*b + 2*e*c + d^2)" + ") "; String orderINV = "(a,b,c,d,e,f,g)"; String orderL = "(g,f,e,d,c,b,a)"; //Tests //String ergm1 = modAll(orderINV, polynomials, 2147464751); //String ergm2 = modfglm(orderL, polynomials, 1831); //System.out.println(modfglm); //System.out.println(ergm1); //System.out.println(ergm2); String erg2 = fglm(orderL, polynomials); System.out.println(fglm); System.out.println(erg2); } public void ytestCassouMod1() { String polynomials = "( " + " (15*a^4*b*c^2 + 6*a^4*b^3 + 21*a^4*b^2*c - 144*a^2*b - 8*a^2*b^2*d - 28*a^2*b*c*d - 648*a^2*c + 36*c^2*d + 9*a^4*c^3 - 120)," + "(30*b^3*a^4*c - 32*c*d^2*b - 720*c*a^2*b - 24*b^3*a^2*d - 432*b^2*a^2 + 576*d*b - 576*c*d + 16*b*a^2*c^2*d + 16*c^2*d^2 + 16*d^2*b^2 + 9*b^4*a^4 + 5184 + 39*c^2*a^4*b^2 + 18*c^3*a^4*b - 432*c^2*a^2 + 24*c^3*a^2*d - 16*b^2*a^2*c*d - 240*b)," + "(216*c*a^2*b - 162*c^2*a^2 - 81*b^2*a^2 + 5184 + 1008*d*b - 1008*c*d + 15*b^2*a^2*c*d - 15*b^3*a^2*d - 80*c*d^2*b + 40*c^2*d^2 + 40*d^2*b^2)," + "(261 + 4*c*a^2*b - 3*c^2*a^2 - 4*b^2*a^2 + 22*d*b - 22*c*d)" + ") "; String orderINV = "(a,b,c,d)"; String orderL = "(d,c,b,a)"; //Tests String ergm1 = modfglm(orderL, polynomials, 1831); String ergm2 = modfglm(orderINV, polynomials, 1831); System.out.println(modfglm); System.out.println(ergm1); System.out.println(ergm2); } public void ytestOmdi1() { String polynomials = "( " + " (a + c + v + 2*x - 1)," + "(a*b + c*u + 2*v*w + 2*x*y + 2*x*z -2/3)," + "(a*b^2 + c*u^2 + 2*v*w^2 + 2*x*y^2 + 2*x*z^2 - 2/5)," + "(a*b^3 + c*u^3 + 2*v*w^3 + 2*x*y^3 + 2*x*z^3 - 2/7)," + "(a*b^4 + c*u^4 + 2*v*w^4 + 2*x*y^4 + 2*x*z^4 - 2/9)," + "(v*w^2 + 2*x*y*z - 1/9)," + "(v*w^4 + 2*x*y^2*z^2 - 1/25)," + "(v*w^3 + 2*x*y*z^2 + x*y^2*z - 1/15)," + "(v*w^4 + x*y*z^3 + x*y^3*z -1/21)" + ") "; String orderINV = "(a,b,c,u,v,w,x,y,z)"; String orderL = "(z,y,x,w,v,u,c,b,a)"; //Tests String erg_deg = grad(orderL, polynomials); System.out.println(grad); System.out.println(erg_deg); /* String ergm1 = modfglm(orderL, polynomials, 1831); String ergm2 = modfglm(orderINV, polynomials, 1831); System.out.println(modfglm); System.out.println(ergm1); System.out.println(ergm2); */ } public void ytestLamm1() { String polynomials = "( " + " (45*x^8 + 3*x^7 + 39*x^6 + 30*x^5 + 13*x^4 + 41*x^3 + 5*x^2 + 46*x + 7)," + "(49*x^7*y + 35*x*y^7 + 37*x*y^6 + 9*y^7 + 4*x^6 + 6*y^6 + 27*x^3*y^2 + 20*x*y^4 + 31*x^4 + 33*x^2*y + 24*x^2 + 49*y + 43)" + ") "; String orderINV = "(x,y)"; String orderL = "(y,x)"; //Tests String erg_deg = grad(orderINV, polynomials); System.out.println(grad); System.out.println(erg_deg); String erg1 = all(orderINV, polynomials); String erg2 = all(orderL, polynomials); String ergMod1 = modAll(orderINV, polynomials, 1831); String ergMod2 = modAll(orderL, polynomials, 1831); System.out.println(all); System.out.println(erg1); System.out.println(erg2); System.out.println("\n"); System.out.println(modAll); System.out.println(ergMod1); System.out.println(ergMod2); } //=================================================================== //Examples taken from "Some Examples for Solving Systems of Algebraic Equations by Calculating Gröbner Bases", 1984, Boege, Gebauer, Kredel //=================================================================== public void xtestEquilibrium() { String polynomials = "( " + " (y^4 - 20/7*z^2)," + "(z^2*x^4 + 7/10*z*x^4 + 7/48*x^4 - 50/27*z^2 - 35/27*z - 49/216)," + "(x^5*y^3 + 7/5*z^4*y^3 + 609/1000 *z^3*y^3 + 49/1250*z^2*y^3 - 27391/800000*z*y^3 - 1029/160000*y^3 + 3/7*z^5*x*y^2 +" + "3/5*z^6*x*y^2 + 63/200*z^3*x*y^2 + 147/2000*z^2*x*y^2 + 4137/800000*z*x*y^2 - 7/20*z^4*x^2*y - 77/125*z^3*x^2*y" + "- 23863/60000*z^2*x^2*y - 1078/9375*z*x^2*y - 24353/1920000*x^2*y - 3/20*z^4*x^3 - 21/100*z^3*x^3" + "- 91/800*z^2*x^3 - 5887/200000*z*x^3 - 343/128000*x^3)" + ") "; String order = "(x,y,z)"; //Tests String ergOnlyG_1 = grad(order, polynomials); System.out.println(grad); System.out.println(ergOnlyG_1); } public void xtestTrinks2() { String polynomials = "( " + " (45*p + 35*s - 165*b - 36)," + "(35*p + 40*z + 25*t - 27*s)," + "(15*w + 25*p*s + 30*z - 18*t - 165*b^2)," + "(-9*w + 15*p*t + 20*z*s)," + "(w*p + 2*z*t - 11*b^3)," + "(99*w - 11*s*b + 3*b^2)," + "(b^2 + 33/50*b + 2673/10000)" + ") "; String order1 = "(b,s,t,z,p,w)"; String order2 = "(s,b,t,z,p,w)"; String order3 = "(s,t,b,z,p,w)"; String order4 = "(s,t,z,p,b,w)"; String order5 = "(s,t,z,p,w,b)"; String order6 = "(s,z,p,w,b,t)"; String order7 = "(p,w,b,t,s,z)"; String order8 = "(z,w,b,s,t,p)"; String order9 = "(t,z,p,w,b,s)"; String order10 = "(z,p,w,b,s,t)"; String order11 = "(p,w,b,s,t,z)"; String order12 = "(w,b,s,t,z,p)"; //Tests String erg_1 = all(order1, polynomials); String erg_2 = all(order2, polynomials); String erg_3 = all(order3, polynomials); String erg_4 = all(order4, polynomials); String erg_5 = all(order5, polynomials); String erg_6 = all(order6, polynomials); String erg_7 = all(order7, polynomials); String erg_8 = all(order8, polynomials); String erg_9 = all(order9, polynomials); String erg_10 = all(order10, polynomials); String erg_11 = all(order11, polynomials); String erg_12 = all(order12, polynomials); System.out.println(all); System.out.println(erg_1); System.out.println(erg_2); System.out.println(erg_3); System.out.println(erg_4); System.out.println(erg_5); System.out.println(erg_6); System.out.println(erg_7); System.out.println(erg_8); System.out.println(erg_9); System.out.println(erg_10); System.out.println(erg_11); System.out.println(erg_12); } public void xtestHairerRungeKutta_1() { String polynomials = "( " + " (a-f),(b-h-g),(e+d+c-1),(d*a+c*b-1/2),(d*a^2+c*b^2-1/3),(c*g*a-1/6)" + ") "; String[] order = new String[] { "a", "b", "c", "d", "e", "f", "g", "h" }; String order1 = shuffle(order); String order2 = shuffle(order); String order3 = shuffle(order); String order4 = shuffle(order); String order5 = shuffle(order); // langsam (e,d,h,c,g,a,f,b), (h,d,b,e,c,g,a,f) um die 120 // sehr langsam (e,h,d,c,g,b,a,f) um die 1000 // sehr schnell (g,b,f,h,c,d,a,e), (h,c,a,g,d,f,e,b) 1 millisec String ergOnlyG_1 = grad(order1, polynomials); System.out.println(grad); System.out.println(ergOnlyG_1); String ergOnlyL_1 = lex(order1, polynomials); String ergOnlyL_2 = lex(order2, polynomials); String ergOnlyL_3 = lex(order3, polynomials); String ergOnlyL_4 = lex(order4, polynomials); String ergOnlyL_5 = lex(order5, polynomials); System.out.println(lex); System.out.println(ergOnlyL_1); System.out.println(ergOnlyL_2); System.out.println(ergOnlyL_3); System.out.println(ergOnlyL_4); System.out.println(ergOnlyL_5); //String ergGeneral = all(order, polynomials); //System.out.println(all); //System.out.println(ergGeneral); } //================================================================================================= //Internal methods //================================================================================================= @SuppressWarnings("cast") public String all(String order, String polynomials) { GroebnerBaseFGLM IdealObjectFGLM; BigRational coeff = new BigRational(); GroebnerBase gb = GBFactory.getImplementation(coeff); String polynomials_Grad = order + " G " + polynomials; String polynomials_Lex = order + " L " + polynomials; Reader sourceG = new StringReader(polynomials_Grad); GenPolynomialTokenizer parserG = new GenPolynomialTokenizer(sourceG); PolynomialList G = null; Reader sourceL = new StringReader(polynomials_Lex); GenPolynomialTokenizer parserL = new GenPolynomialTokenizer(sourceL); PolynomialList L = null; try { G = (PolynomialList) parserG.nextPolynomialSet(); L = (PolynomialList) parserL.nextPolynomialSet(); } catch (IOException e) { e.printStackTrace(); return "fail"; } System.out.println("Input " + G); System.out.println("Input " + L); //Computation of the Groebnerbase with Buchberger w.r.t INVLEX long buchberger_Lex = System.currentTimeMillis(); List> GL = gb.GB(L.list); buchberger_Lex = System.currentTimeMillis() - buchberger_Lex; //Computation of the Groebnerbase with Buchberger w.r.t GRADLEX (Total degree + INVLEX) long buchberger_Grad = System.currentTimeMillis(); List> GG = gb.GB(G.list); buchberger_Grad = System.currentTimeMillis() - buchberger_Grad; //PolynomialList GGG = new PolynomialList(G.ring, GG); //PolynomialList GLL = new PolynomialList(L.ring, GL); IdealObjectFGLM = new GroebnerBaseFGLM(); //GGG); //IdealObjectLex = new GroebnerBaseSeq(GLL); long tconv = System.currentTimeMillis(); List> resultFGLM = IdealObjectFGLM.convGroebnerToLex(GG); tconv = System.currentTimeMillis() - tconv; OrderedPolynomialList o1 = new OrderedPolynomialList(GG.get(0).ring, GG); OrderedPolynomialList o2 = new OrderedPolynomialList( resultFGLM.get(0).ring, resultFGLM); //List> resultBuchberger = GL; OrderedPolynomialList o3 = new OrderedPolynomialList(GL.get(0).ring, GL); int grad_numberOfElements = GG.size(); int lex_numberOfElements = resultFGLM.size(); long grad_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(GG); // IdealObjectFGLM.maxDegreeOfGB(); long lex_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(GL); // IdealObjectLex.maxDegreeOfGB(); int grad_height = bitHeight(GG); int lex_height = bitHeight(resultFGLM); System.out.println("Order of Variables: " + order); System.out.println("Groebnerbases: "); System.out.println("Groebnerbase Buchberger (IGRLEX) " + o1); System.out.println("Groebnerbase FGML (INVLEX) computed from Buchberger (IGRLEX) " + o2); System.out.println("Groebnerbase Buchberger (INVLEX) " + o3); String erg = "BigRational |" + order + " |" + grad_numberOfElements + " |" + lex_numberOfElements + " |" + grad_height + " |" + lex_height + " |" + grad_maxPolyGrad + " |" + lex_maxPolyGrad + " |" + buchberger_Grad + " |" + tconv + " |" + buchberger_Lex; assertEquals(o2, o3); return erg; } @SuppressWarnings("cast") public String fglm(String order, String polynomials) { GroebnerBaseFGLM IdealObjectGrad; //GroebnerBaseAbstract IdealObjectLex; BigRational coeff = new BigRational(); GroebnerBase gb = GBFactory.getImplementation(coeff); String polynomials_Grad = order + " G " + polynomials; Reader sourceG = new StringReader(polynomials_Grad); GenPolynomialTokenizer parserG = new GenPolynomialTokenizer(sourceG); PolynomialList G = null; try { G = (PolynomialList) parserG.nextPolynomialSet(); } catch (IOException e) { e.printStackTrace(); return "fail"; } System.out.println("Input " + G); //Computation of the Groebnerbase with Buchberger w.r.t GRADLEX (Total degree + INVLEX) long buchberger_Grad = System.currentTimeMillis(); List> GG = gb.GB(G.list); buchberger_Grad = System.currentTimeMillis() - buchberger_Grad; //PolynomialList GGG = new PolynomialList(G.ring, GG); IdealObjectGrad = new GroebnerBaseFGLM(); //GGG); long tconv = System.currentTimeMillis(); List> resultFGLM = IdealObjectGrad.convGroebnerToLex(GG); tconv = System.currentTimeMillis() - tconv; //PolynomialList LLL = new PolynomialList(G.ring, resultFGLM); //IdealObjectLex = new GroebnerBaseSeq(); //LLL); OrderedPolynomialList o1 = new OrderedPolynomialList(GG.get(0).ring, GG); OrderedPolynomialList o2 = new OrderedPolynomialList( resultFGLM.get(0).ring, resultFGLM); int grad_numberOfElements = GG.size(); int lex_numberOfElements = resultFGLM.size(); long grad_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(GG); //IdealObjectGrad.maxDegreeOfGB(); long lex_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(resultFGLM); //IdealObjectLex.maxDegreeOfGB(); int grad_height = bitHeight(GG); int lex_height = bitHeight(resultFGLM); System.out.println("Order of Variables: " + order); System.out.println("Groebnerbases: "); System.out.println("Groebnerbase Buchberger (IGRLEX) " + o1); System.out.println("Groebnerbase FGML (INVLEX) computed from Buchberger (IGRLEX) " + o2); String erg = "BigRational |" + order + " |" + grad_numberOfElements + " |" + lex_numberOfElements + " |" + grad_height + " |" + lex_height + " |" + grad_maxPolyGrad + " |" + lex_maxPolyGrad + " |" + buchberger_Grad + " |" + tconv; return erg; } @SuppressWarnings("cast") public String grad(String order, String polynomials) { BigRational coeff = new BigRational(); GroebnerBase gb = GBFactory.getImplementation(coeff); String polynomials_Grad = order + " G " + polynomials; Reader sourceG = new StringReader(polynomials_Grad); GenPolynomialTokenizer parserG = new GenPolynomialTokenizer(sourceG); PolynomialList G = null; try { G = (PolynomialList) parserG.nextPolynomialSet(); } catch (IOException e) { e.printStackTrace(); return "fail"; } System.out.println("Input " + G); //Computation of the Groebnerbase with Buchberger w.r.t GRADLEX (Total degree + INVLEX) long buchberger_Grad = System.currentTimeMillis(); List> GG = gb.GB(G.list); buchberger_Grad = System.currentTimeMillis() - buchberger_Grad; //PolynomialList GGG = new PolynomialList(G.ring, GG); OrderedPolynomialList o1 = new OrderedPolynomialList(GG.get(0).ring, GG); GroebnerBaseFGLM IdealObjectGrad; IdealObjectGrad = new GroebnerBaseFGLM(); //GGG); long grad_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(GG); //IdealObjectGrad.maxDegreeOfGB(); List> reducedTerms = IdealObjectGrad.redTerms(GG); OrderedPolynomialList o4 = new OrderedPolynomialList( reducedTerms.get(0).ring, reducedTerms); int grad_numberOfReducedElements = reducedTerms.size(); int grad_numberOfElements = GG.size(); int grad_height = bitHeight(GG); System.out.println("Order of Variables: " + order); System.out.println("Groebnerbases: "); System.out.println("Groebnerbase Buchberger (IGRLEX) " + o1); System.out.println("Reduced Terms" + o4); String erg = "BigRational |" + order + " |" + grad_numberOfElements + " |" + grad_height + " |" + grad_maxPolyGrad + " |" + buchberger_Grad + " |" + grad_numberOfReducedElements; return erg; } @SuppressWarnings("cast") public String lex(String order, String polynomials) { //GroebnerBaseAbstract IdealObjectLex; BigRational coeff = new BigRational(); GroebnerBase gb = GBFactory.getImplementation(coeff); String polynomials_Lex = order + " L " + polynomials; Reader sourceL = new StringReader(polynomials_Lex); GenPolynomialTokenizer parserL = new GenPolynomialTokenizer(sourceL); PolynomialList L = null; try { L = (PolynomialList) parserL.nextPolynomialSet(); } catch (IOException e) { e.printStackTrace(); return "fail"; } System.out.println("Input " + L); //Computation of the Groebnerbase with Buchberger w.r.t INVLEX long buchberger_Lex = System.currentTimeMillis(); List> GL = gb.GB(L.list); buchberger_Lex = System.currentTimeMillis() - buchberger_Lex; //PolynomialList GLL = new PolynomialList(L.ring, GL); //IdealObjectLex = new GroebnerBaseAbstract(GLL); OrderedPolynomialList o3 = new OrderedPolynomialList(GL.get(0).ring, GL); int lex_numberOfElements = GL.size(); long lex_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(GL); //IdealObjectLex.maxDegreeOfGB(); int lexHeigth = bitHeight(GL); System.out.println("Order of Variables: " + order); System.out.println("Groebnerbase Buchberger (INVLEX) " + o3); String erg = "BigRational" + order + "|" + lex_numberOfElements + " |" + lexHeigth + " |" + lex_maxPolyGrad + " |" + buchberger_Lex; return erg; } @SuppressWarnings("cast") public String modAll(String order, String polynomials, Integer m) { GroebnerBaseFGLM IdealObjectFGLM; //GroebnerBaseAbstract IdealObjectLex; ModIntegerRing ring = new ModIntegerRing(m); GroebnerBase gb = GBFactory.getImplementation(ring); String polynomials_Grad = "Mod " + ring.modul + " " + order + " G " + polynomials; String polynomials_Lex = "Mod " + ring.modul + " " + order + " L " + polynomials; Reader sourceG = new StringReader(polynomials_Grad); GenPolynomialTokenizer parserG = new GenPolynomialTokenizer(sourceG); PolynomialList G = null; Reader sourceL = new StringReader(polynomials_Lex); GenPolynomialTokenizer parserL = new GenPolynomialTokenizer(sourceL); PolynomialList L = null; try { G = (PolynomialList) parserG.nextPolynomialSet(); L = (PolynomialList) parserL.nextPolynomialSet(); } catch (IOException e) { e.printStackTrace(); return "fail"; } System.out.println("G= " + G); System.out.println("L= " + L); //Computation of the Groebnerbase with Buchberger w.r.t INVLEX long buchberger_Lex = System.currentTimeMillis(); List> GL = gb.GB(L.list); buchberger_Lex = System.currentTimeMillis() - buchberger_Lex; //Computation of the Groebnerbase with Buchberger w.r.t GRADLEX (Total degree + INVLEX) long buchberger_Grad = System.currentTimeMillis(); List> GG = gb.GB(G.list); buchberger_Grad = System.currentTimeMillis() - buchberger_Grad; //PolynomialList GGG = new PolynomialList(G.ring, GG); //PolynomialList GLL = new PolynomialList(L.ring, GL); IdealObjectFGLM = new GroebnerBaseFGLM(); //GGG); //IdealObjectLex = new GroebnerBaseAbstract(GLL); long tconv = System.currentTimeMillis(); List> resultFGLM = IdealObjectFGLM.convGroebnerToLex(GG); tconv = System.currentTimeMillis() - tconv; OrderedPolynomialList o1 = new OrderedPolynomialList(GG.get(0).ring, GG); OrderedPolynomialList o2 = new OrderedPolynomialList(resultFGLM.get(0).ring, resultFGLM); List> resultBuchberger = GL; OrderedPolynomialList o3 = new OrderedPolynomialList( resultBuchberger.get(0).ring, resultBuchberger); int grad_numberOfElements = GG.size(); int lex_numberOfElements = resultFGLM.size(); long grad_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(GG); //IdealObjectFGLM.maxDegreeOfGB(); long lex_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(GL); //IdealObjectLex.maxDegreeOfGB(); System.out.println("Order of Variables: " + order); System.out.println("Groebnerbases: "); System.out.println("Groebnerbase Buchberger (IGRLEX) " + o1); System.out.println("Groebnerbase FGML (INVLEX) computed from Buchberger (IGRLEX) " + o2); System.out.println("Groebnerbase Buchberger (INVLEX) " + o3); String erg = "Mod " + m + " |" + order + " |" + grad_numberOfElements + " |" + lex_numberOfElements + " |" + grad_maxPolyGrad + " |" + lex_maxPolyGrad + " |" + buchberger_Grad + " |" + tconv + " |" + buchberger_Lex; assertEquals(o2, o3); return erg; } @SuppressWarnings("cast") public String modGrad(String order, String polynomials, Integer m) { //GroebnerBaseFGLM IdealObjectFGLM; ModIntegerRing ring = new ModIntegerRing(m); GroebnerBase gb = GBFactory.getImplementation(ring); String polynomials_Grad = "Mod " + ring.modul + " " + order + " G " + polynomials; Reader sourceG = new StringReader(polynomials_Grad); GenPolynomialTokenizer parserG = new GenPolynomialTokenizer(sourceG); PolynomialList G = null; try { G = (PolynomialList) parserG.nextPolynomialSet(); } catch (IOException e) { e.printStackTrace(); return "fail"; } System.out.println("G= " + G); //Computation of the Groebnerbase with Buchberger w.r.t GRADLEX (Total degree + INVLEX) long buchberger_Grad = System.currentTimeMillis(); List> GG = gb.GB(G.list); buchberger_Grad = System.currentTimeMillis() - buchberger_Grad; //PolynomialList GGG = new PolynomialList(G.ring, GG); //IdealObjectFGLM = new GroebnerBaseFGLM(); //GGG); OrderedPolynomialList o1 = new OrderedPolynomialList(GG.get(0).ring, GG); int grad_numberOfElements = GG.size(); long grad_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(GG); //IdealObjectFGLM.maxDegreeOfGB(); System.out.println("Order of Variables: " + order); System.out.println("Groebnerbases: "); System.out.println("Groebnerbase Buchberger (IGRLEX) " + o1); String erg = "Mod " + m + " |" + order + " |" + grad_numberOfElements + " |" + grad_maxPolyGrad + " |" + buchberger_Grad; return erg; } @SuppressWarnings("cast") public String modfglm(String order, String polynomials, Integer m) { GroebnerBaseFGLM IdealObjectFGLM; //GroebnerBaseAbstract IdealObjectLex; ModIntegerRing ring = new ModIntegerRing(m); GroebnerBase gb = GBFactory.getImplementation(ring); String polynomials_Grad = "Mod " + ring.modul + " " + order + " G " + polynomials; Reader sourceG = new StringReader(polynomials_Grad); GenPolynomialTokenizer parserG = new GenPolynomialTokenizer(sourceG); PolynomialList G = null; try { G = (PolynomialList) parserG.nextPolynomialSet(); } catch (IOException e) { e.printStackTrace(); return "fail"; } System.out.println("G= " + G); //Computation of the Groebnerbase with Buchberger w.r.t GRADLEX (Total degree + INVLEX) long buchberger_Grad = System.currentTimeMillis(); List> GG = gb.GB(G.list); buchberger_Grad = System.currentTimeMillis() - buchberger_Grad; //PolynomialList GGG = new PolynomialList(G.ring, GG); IdealObjectFGLM = new GroebnerBaseFGLM(); //GGG); long tconv = System.currentTimeMillis(); List> resultFGLM = IdealObjectFGLM.convGroebnerToLex(GG); tconv = System.currentTimeMillis() - tconv; //PolynomialList LLL = new PolynomialList(G.ring, resultFGLM); //IdealObjectLex = new GroebnerBaseAbstract(LLL); OrderedPolynomialList o1 = new OrderedPolynomialList(GG.get(0).ring, GG); OrderedPolynomialList o2 = new OrderedPolynomialList(resultFGLM.get(0).ring, resultFGLM); int grad_numberOfElements = GG.size(); int lex_numberOfElements = resultFGLM.size(); long grad_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(GG); //IdealObjectFGLM.maxDegreeOfGB(); long lex_maxPolyGrad = PolyUtil. totalDegreeLeadingTerm(resultFGLM); //IdealObjectLex.maxDegreeOfGB(); System.out.println("Order of Variables: " + order); System.out.println("Groebnerbases: "); System.out.println("Groebnerbase Buchberger (IGRLEX) " + o1); System.out.println("Groebnerbase FGML (INVLEX) computed from Buchberger (IGRLEX) " + o2); String erg = "Mod " + m + " |" + order + " |" + grad_numberOfElements + " |" + lex_numberOfElements + " |" + grad_maxPolyGrad + " |" + lex_maxPolyGrad + " |" + buchberger_Grad + " |" + tconv; return erg; } //Method shuffle returns a random permutation of a string of variables public String shuffle(String[] tempOrder) { Collections.shuffle(Arrays.asList(tempOrder)); StringBuffer ret = new StringBuffer("("); ret.append(ExpVector.varsToString(tempOrder)); ret.append(")"); return ret.toString(); } //Method bitHeight returns the bitlength of the greatest number occurring during the computation of a groebnerbase public int bitHeight(List> list) { BigInteger denom = BigInteger.ONE; BigInteger num = BigInteger.ONE; for (GenPolynomial g : list) { for (Monomial m : g) { BigRational bi = m.coefficient(); BigInteger i = bi.denominator().abs(); BigInteger j = bi.numerator().abs(); if (i.compareTo(denom) > 0) denom = i; if (j.compareTo(num) > 0) num = j; } } int erg; if (denom.compareTo(num) > 0) { erg = denom.bitLength(); } else { erg = num.bitLength(); } return erg; } } jas-2.5/src/edu/jas/gbufd/GroebnerBasePartial.java0000644000175000017500000005340312014164600022270 0ustar giovannigiovanni/* * $Id: GroebnerBasePartial.java 4116 2012-08-19 13:26:25Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.log4j.Logger; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.OptimizedPolynomialList; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.poly.TermOrderOptimization; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Partial Groebner Bases for subsets of variables. Let pvars be a * subset of variables vars of the polynomial ring K[vars]. Methods * compute Groebner bases with coefficients from K[vars \ pvars] in the * polynomial ring K[vars \ pvars][pvars]. * @param coefficient type * @author Heinz Kredel */ public class GroebnerBasePartial> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBasePartial.class); //private final boolean debug = logger.isDebugEnabled(); /** * Backing Groebner base engine. */ protected GroebnerBaseAbstract bb; /** * Backing recursive Groebner base engine. */ protected GroebnerBaseAbstract> rbb; // can be null /** * Constructor. */ public GroebnerBasePartial() { this(new GroebnerBaseSeq(), null); } /** * Constructor. * @param rf coefficient ring factory. */ public GroebnerBasePartial(RingFactory> rf) { this(new GroebnerBaseSeq(), new GroebnerBasePseudoRecSeq(rf)); } /** * Constructor. * @param bb Groebner base engine * @param rbb recursive Groebner base engine */ public GroebnerBasePartial(GroebnerBaseAbstract bb, GroebnerBaseAbstract> rbb) { super(); this.bb = bb; this.rbb = rbb; //if (rbb == null) { //logger.warn("no recursive GB given"); //} } /** * Groebner base using pairlist class. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> GB(int modv, List> F) { return bb.GB(modv, F); } /** * Groebner base test. * @param F polynomial list. * @return true, if F is a partial Groebner base, else false. */ public boolean isGBrec(List>> F) { return isGBrec(0, F); } /** * Groebner base test. * @param modv module variable number. * @param F polynomial list. * @return true, if F is a partial Groebner base, else false. */ public boolean isGBrec(int modv, List>> F) { if (F == null || F.isEmpty()) { return true; } if (true) { rbb = new GroebnerBasePseudoRecSeq(F.get(0).ring.coFac); } return rbb.isGB(modv, F); } /** * Partial permuation for specific variables. Computes a permutation perm * for the variables vars, such that perm(vars) == pvars ... (vars \ pvars). * Uses internal (reversed) variable sorting. * @param vars names for all variables. * @param pvars names for main variables, pvars subseteq vars. * @return permutation for vars, such that perm(vars) == pvars ... (vars \ * pvars). */ public static List partialPermutation(String[] vars, String[] pvars) { return partialPermutation(vars, pvars, null); //no: return getPermutation(vars,pvars); } /** * Permutation of variables for elimination. * @param aname variables for the full polynomial ring. * @param ename variables for the elimination ring, subseteq aname. * @return perm({vars \ ename},ename) */ public static List getPermutation(String[] aname, String[] ename) { if (aname == null || ename == null) { throw new IllegalArgumentException("aname or ename may not be null"); } List perm = new ArrayList(aname.length); // add ename permutation for (int i = 0; i < ename.length; i++) { int j = indexOf(ename[i], aname); if (j < 0) { throw new IllegalArgumentException("ename not contained in aname"); } perm.add(j); } //System.out.println("perm_low = " + perm); // add aname \ ename permutation for (int i = 0; i < aname.length; i++) { if (!perm.contains(i)) { perm.add(i); } } //System.out.println("perm_all = " + perm); // reverse permutation indices int n1 = aname.length - 1; List perm1 = new ArrayList(aname.length); for (Integer k : perm) { perm1.add(n1 - k); } perm = perm1; //System.out.println("perm_inv = " + perm1); Collections.reverse(perm); //System.out.println("perm_rev = " + perm); return perm; } /** * Index of s in A. * @param s search string * @param A string array * @return i if s == A[i] for some i, else -1. */ public static int indexOf(String s, String[] A) { for (int i = 0; i < A.length; i++) { if (s.equals(A[i])) { return i; } } return -1; } /** * Partial permuation for specific variables. Computes a permutation perm * for the variables vars, such that perm(vars) == pvars ... (vars \ pvars). * Uses internal (reversed) variable sorting. * @param vars names for all variables. * @param pvars names for main variables, pvars subseteq vars. * @param rvars names for remaining variables, rvars eq { vars \ pvars }. * @return permutation for vars, such that perm(vars) == (pvars, {vars \ * pvars}). */ public static List partialPermutation(String[] vars, String[] pvars, String[] rvars) { if (vars == null || pvars == null) { throw new IllegalArgumentException("no variable names found"); } List variables = new ArrayList(vars.length); List pvariables = new ArrayList(pvars.length); for (int i = 0; i < vars.length; i++) { variables.add(vars[i]); } for (int i = 0; i < pvars.length; i++) { pvariables.add(pvars[i]); } if (rvars == null) { rvars = remainingVars(vars, pvars); } List rvariables = new ArrayList(rvars.length); for (int i = 0; i < rvars.length; i++) { rvariables.add(rvars[i]); } if (rvars.length + pvars.length == vars.length) { //System.out.println("pvariables = " + pvariables); return getPermutation(vars, rvars); } logger.info("not implemented for " + variables + " != " + pvariables + " cup " + rvariables); throw new UnsupportedOperationException("not implemented"); /* if (!variables.containsAll(pvariables) || !variables.containsAll(rvariables)) { throw new IllegalArgumentException("partial variables not contained in all variables "); } Collections.reverse(variables); Collections.reverse(pvariables); Collections.reverse(rvariables); System.out.println("variables = " + variables); System.out.println("pvariables = " + pvariables); System.out.println("rvariables = " + rvariables); List perm = new ArrayList(); List pv = new ArrayList(); for (String s : variables) { int j = pvariables.indexOf(s); if (j >= 0) { perm.add(j); } } int i = pvariables.size(); for (String s : variables) { if (!pvariables.contains(s)) { pv.add(i); } i++; } System.out.println("perm, 1 = " + perm); //System.out.println("pv = " + pv); // sort perm according to pvars int ps = perm.size(); // == pvars.length for (int k = 0; k < ps; k++) { for (int j = k + 1; j < ps; j++) { int kk = variables.indexOf(pvariables.get(k)); int jj = variables.indexOf(pvariables.get(j)); if (kk > jj) { // swap int t = perm.get(k); System.out.println("swap " + t + " with " + perm.get(j)); perm.set(k, perm.get(j)); perm.set(j, t); } } } //System.out.println("perm = " + perm); // sort pv according to rvars int rs = pv.size(); // == rvars.length for (int k = 0; k < rs; k++) { for (int j = k + 1; j < rs; j++) { int kk = variables.indexOf(rvariables.get(k)); int jj = variables.indexOf(rvariables.get(j)); if (kk > jj) { // swap int t = pv.get(k); //System.out.println("swap " + t + " with " + perm.get(j)); pv.set(k, pv.get(j)); pv.set(j, t); } } } //System.out.println("pv = " + pv); perm.addAll(pv); System.out.println("perm, 2 = " + perm); return perm; */ } /** * Partial permuation for specific variables. Computes a permutation perm * for the variables vars, such that perm(vars) == (evars, pvars, (vars \ { * evars, pvars }). Uses internal (reversed) variable sorting. * @param vars names for all variables. * @param evars names for elimination variables, evars subseteq vars. * @param pvars names for main variables, pvars subseteq vars. * @param rvars names for remaining variables, rvars eq {vars \ { evars, * pvars } }. * @return permutation for vars, such that perm(vars) == (evars,pvars, {vars * \ {evars,pvars}}. */ public static List partialPermutation(String[] vars, String[] evars, String[] pvars, String[] rvars) { if (vars == null || evars == null || pvars == null) { throw new IllegalArgumentException("not all variable names given"); } String[] uvars; if (rvars != null) { uvars = new String[pvars.length + rvars.length]; for (int i = 0; i < pvars.length; i++) { uvars[i] = pvars[i]; } for (int i = 0; i < rvars.length; i++) { uvars[pvars.length + i] = rvars[i]; } } else { uvars = pvars; } //System.out.println("uvars = " + Arrays.toString(uvars)); List perm = partialPermutation(vars, evars, uvars); return perm; } /** * Remaining variables vars \ pvars. Uses internal (reversed) variable * sorting, original order is preserved. * @param vars names for all variables. * @param pvars names for main variables, pvars subseteq vars. * @return remaining vars = (vars \ pvars). */ public static String[] remainingVars(String[] vars, String[] pvars) { if (vars == null || pvars == null) { throw new IllegalArgumentException("no variable names found"); } List variables = new ArrayList(vars.length); List pvariables = new ArrayList(pvars.length); for (int i = 0; i < vars.length; i++) { variables.add(vars[i]); } for (int i = 0; i < pvars.length; i++) { pvariables.add(pvars[i]); } if (!variables.containsAll(pvariables)) { throw new IllegalArgumentException("partial variables not contained in all variables "); } // variables.setMinus(pvariables) List rvariables = new ArrayList(variables); for (String s : pvariables) { rvariables.remove(s); } int cl = vars.length - pvars.length; String[] rvars = new String[cl]; int i = 0; for (String s : rvariables) { rvars[i++] = s; } return rvars; } /** * Partial recursive Groebner base for specific variables. Computes Groebner * base in K[vars \ pvars][pvars] with coefficients from K[vars \ pvars]. * @param F polynomial list. * @param pvars names for main variables of partial Groebner base * computation. * @return a container for a partial Groebner base of F wrt pvars. */ public OptimizedPolynomialList> partialGBrec(List> F, String[] pvars) { if (F == null || F.isEmpty()) { throw new IllegalArgumentException("empty F not allowed"); } GenPolynomialRing fac = F.get(0).ring; String[] vars = fac.getVars(); if (vars == null || pvars == null) { throw new IllegalArgumentException("not all variable names found"); } if (vars.length == pvars.length) { throw new IllegalArgumentException("use non recursive partialGB algorithm"); } // compute permutation (in reverse sorting) List perm = partialPermutation(vars, pvars); GenPolynomialRing pfac = TermOrderOptimization. permutation(perm, fac); if (logger.isInfoEnabled()) { logger.info("pfac = " + pfac); } List> ppolys = TermOrderOptimization. permutation(perm, pfac, F); //System.out.println("ppolys = " + ppolys); int cl = fac.nvar - pvars.length; // > 0 int pl = pvars.length; String[] rvars = remainingVars(vars, pvars); GenPolynomialRing cfac = new GenPolynomialRing(fac.coFac, cl, fac.tord, rvars); //System.out.println("cfac = " + cfac); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, pl, fac.tord, pvars); if (logger.isInfoEnabled()) { logger.info("rfac = " + rfac); } //System.out.println("rfac = " + rfac); List>> Fr = PolyUtil. recursive(rfac, ppolys); //System.out.println("\nFr = " + Fr); if (true) { rbb = new GroebnerBasePseudoRecSeq(cfac); } List>> Gr = rbb.GB(Fr); //System.out.println("\nGr = " + Gr); //perm = perm.subList(0,pl); OptimizedPolynomialList> pgb = new OptimizedPolynomialList>(perm, rfac, Gr); return pgb; } /** * Partial Groebner base for specific variables. Computes Groebner base in * K[vars \ pvars][pvars] with coefficients from K[vars \ pvars] but returns * polynomials in K[vars \ pvars, pvars]. * @param F polynomial list. * @param pvars names for main variables of partial Groebner base * computation. * @return a container for a partial Groebner base of F wrt pvars. */ public OptimizedPolynomialList partialGB(List> F, String[] pvars) { if (F == null || F.isEmpty()) { throw new IllegalArgumentException("empty F not allowed"); } GenPolynomialRing fac = F.get(0).ring; String[] vars = fac.getVars(); // compute permutation (in reverse sorting) //String[] xvars = remainingVars(vars, pvars); //System.out.println("xvars = " + Arrays.toString(xvars)); List perm = partialPermutation(vars, pvars); //System.out.println("pGB, perm = " + perm); //System.out.println("pGB, perm,1 = " + getPermutation(vars, xvars)); GenPolynomialRing pfac = TermOrderOptimization. permutation(perm, fac); if (logger.isInfoEnabled()) { logger.info("pfac = " + pfac); } List> ppolys = TermOrderOptimization. permutation(perm, pfac, F); //System.out.println("ppolys = " + ppolys); int cl = fac.nvar - pvars.length; if (cl == 0) { // non recursive case //GroebnerBaseSeq bb = new GroebnerBaseSeq(); List> G = bb.GB(ppolys); OptimizedPolynomialList pgb = new OptimizedPolynomialList(perm, pfac, G); return pgb; } // recursive case int pl = pvars.length; String[] rvars = remainingVars(vars, pvars); GenPolynomialRing cfac = new GenPolynomialRing(fac.coFac, cl, fac.tord, rvars); //System.out.println("cfac = " + cfac); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, pl, fac.tord, pvars); if (logger.isInfoEnabled()) { logger.info("rfac = " + rfac); } //System.out.println("rfac = " + rfac); List>> Fr = PolyUtil. recursive(rfac, ppolys); //System.out.println("\nFr = " + Fr); if (true) { rbb = new GroebnerBasePseudoRecSeq(cfac); } List>> Gr = rbb.GB(Fr); //System.out.println("\nGr = " + Gr); List> G = PolyUtil. distribute(pfac, Gr); //System.out.println("\nG = " + G); OptimizedPolynomialList pgb = new OptimizedPolynomialList(perm, pfac, G); return pgb; } /** * Partial Groebner base for specific variables. Computes Groebner base with * coefficients from K[pvars] but returns polynomials in K[pvars, evars]. * @param F polynomial list. * @param evars names for upper main variables of partial Groebner base * computation. * @param pvars names for lower main variables of partial Groebner base * computation. * @return a container for a partial Groebner base of F wrt (pvars,evars). */ public OptimizedPolynomialList elimPartialGB(List> F, String[] evars, String[] pvars) { if (F == null || F.isEmpty()) { throw new IllegalArgumentException("empty F not allowed"); } GenPolynomialRing fac = F.get(0).ring; String[] vars = fac.getVars(); // compute permutation (in reverse sorting) //System.out.println("vars = " + Arrays.toString(vars)); //System.out.println("evars = " + Arrays.toString(evars)); //System.out.println("pvars = " + Arrays.toString(pvars)); List perm = partialPermutation(vars, evars, pvars); //System.out.println("perm = " + perm); GenPolynomialRing pfac = TermOrderOptimization. permutation(perm, fac); if (logger.isInfoEnabled()) { logger.info("pfac = " + pfac); } List> ppolys = TermOrderOptimization. permutation(perm, pfac, F); //System.out.println("ppolys = " + ppolys); int cl = fac.nvar - evars.length - pvars.length; if (cl == 0) { // non recursive case TermOrder to = pfac.tord; int ev = to.getEvord(); //ev = TermOrder.IGRLEX; TermOrder split = new TermOrder(ev, ev, pfac.nvar, evars.length); pfac = new GenPolynomialRing(pfac.coFac, pfac.nvar, split, pfac.getVars()); if (logger.isInfoEnabled()) { //logger.info("split = " + split); logger.info("pfac = " + pfac); } List> Fs = new ArrayList>(ppolys.size()); for (GenPolynomial p : ppolys) { Fs.add(pfac.copy(p)); } List> G = bb.GB(Fs); OptimizedPolynomialList pgb = new OptimizedPolynomialList(perm, pfac, G); if (logger.isInfoEnabled()) { logger.info("pgb = " + pgb); } return pgb; } logger.warn("not meaningful for elimination " + cl); // recursive case int pl = pvars.length + pvars.length; String[] rvars = remainingVars(vars, evars); rvars = remainingVars(rvars, pvars); String[] uvars = new String[evars.length + pvars.length]; for (int i = 0; i < pvars.length; i++) { uvars[i] = pvars[i]; } for (int i = 0; i < evars.length; i++) { uvars[pvars.length + i] = evars[i]; } GenPolynomialRing cfac = new GenPolynomialRing(fac.coFac, cl, fac.tord, rvars); //System.out.println("cfac = " + cfac); TermOrder to = pfac.tord; int ev = to.getEvord(); TermOrder split = new TermOrder(ev, ev, pl, evars.length); //GenPolynomialRing sfac = new GenPolynomialRing(pfac.coFac, pfac.nvar, split, pfac.getVars()); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, pl, split, uvars); //System.out.println("rfac = " + rfac); List>> Fr = PolyUtil. recursive(rfac, ppolys); if (logger.isInfoEnabled()) { logger.info("rfac = " + rfac); logger.info("Fr = " + Fr); } if (true) { rbb = new GroebnerBasePseudoRecSeq(cfac); } List>> Gr = rbb.GB(Fr); //System.out.println("\nGr = " + Gr); List> G = PolyUtil. distribute(pfac, Gr); //System.out.println("\nG = " + G); OptimizedPolynomialList pgb = new OptimizedPolynomialList(perm, pfac, G); return pgb; } } jas-2.5/src/edu/jas/gbufd/PolyGBUtil.java0000644000175000017500000002740312004024230020401 0ustar giovannigiovanni/* * $Id: PolyGBUtil.java 4049 2012-07-25 17:10:49Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; /** * Package gbufd utilities. * @author Heinz Kredel */ public class PolyGBUtil { private static final Logger logger = Logger.getLogger(PolyGBUtil.class); private static boolean debug = logger.isDebugEnabled(); /** * Test for resultant. * @param A generic polynomial. * @param B generic polynomial. * @param r generic polynomial. * @return true if res(A,B) isContained in ideal(A,B), else false. */ public static > boolean isResultant(GenPolynomial A, GenPolynomial B, GenPolynomial r) { if (r == null || r.isZERO()) { return true; } GroebnerBaseAbstract bb = GBFactory. getImplementation(r.ring.coFac); List> F = new ArrayList>(2); F.add(A); F.add(B); List> G = bb.GB(F); //System.out.println("G = " + G); GenPolynomial n = bb.red.normalform(G, r); //System.out.println("n = " + n); return n.isZERO(); } /** * Top pseudo reduction wrt the main variables. * @param P generic polynomial. * @param A list of generic polynomials sorted according to appearing main variables. * @return top pseudo remainder of P wrt. A for the appearing variables. */ public static > GenPolynomial topPseudoRemainder(List> A, GenPolynomial P) { if (A == null || A.isEmpty()) { return P.monic(); } if (P.isZERO()) { return P; } //System.out.println("remainder, P = " + P); GenPolynomialRing pfac = A.get(0).ring; if (pfac.nvar <= 1) { // recursion base GenPolynomial R = PolyUtil. baseSparsePseudoRemainder(P, A.get(0)); return R.monic(); } // select polynomials according to the main variable GenPolynomialRing> rfac = pfac.recursive(1); GenPolynomial Q = A.get(0); // wrong, must eventually search polynomial GenPolynomial> qr = PolyUtil. recursive(rfac, Q); GenPolynomial> pr = PolyUtil. recursive(rfac, P); GenPolynomial> rr; if (qr.isONE()) { return P.ring.getZERO(); } if (qr.degree(0) > 0) { rr = PolyUtil. recursiveSparsePseudoRemainder(pr, qr); //System.out.println("remainder, pr = " + pr); //System.out.println("remainder, qr = " + qr); //System.out.println("remainder, rr = " + rr); } else { rr = pr; } if (rr.degree(0) > 0) { GenPolynomial R = PolyUtil. distribute(pfac, rr); return R.monic(); // not further reduced wrt. other variables = top-reduction only } List> zeroDeg = zeroDegrees(A); GenPolynomial R = topPseudoRemainder(zeroDeg, rr.leadingBaseCoefficient()); R = R.extend(pfac, 0, 0L); return R.monic(); } /** * Top coefficient pseudo remainder of the leading coefficient of P wrt A in the main variables. * @param P generic polynomial in n+1 variables. * @param A list of generic polynomials in n variables sorted according to appearing main variables. * @return pseudo remainder of the leading coefficient of P wrt A. */ public static > GenPolynomial topCoefficientPseudoRemainder(List> A, GenPolynomial P) { if (A == null || A.isEmpty()) { return P.monic(); } if (P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; GenPolynomialRing pfac1 = A.get(0).ring; if (pfac1.nvar <= 1) { // recursion base GenPolynomial a = A.get(0); GenPolynomialRing> rfac = pfac.recursive(pfac.nvar - 1); GenPolynomial> pr = PolyUtil. recursive(rfac, P); // ldcf(P,x_m) = q a + r GenPolynomial> rr = PolyGBUtil. coefficientPseudoRemainderBase(pr, a); GenPolynomial R = PolyUtil. distribute(pfac, rr); return R.monic(); } // select polynomials according to the main variable GenPolynomialRing> rfac1 = pfac1.recursive(1); int nv = pfac.nvar - pfac1.nvar; GenPolynomialRing> rfac = pfac.recursive(1 + nv); GenPolynomialRing>> rfac2 = rfac.recursive(nv); if (debug) { logger.info("rfac =" + rfac); } GenPolynomial> pr = PolyUtil. recursive(rfac, P); GenPolynomial>> pr2 = PolyUtil.> recursive(rfac2, pr); //System.out.println("recursion, pr2 = " + pr2); GenPolynomial Q = A.get(0); GenPolynomial> qr = PolyUtil. recursive(rfac1, Q); GenPolynomial>> rr; if (qr.isONE()) { return P.ring.getZERO(); } if (qr.degree(0) > 0) { // pseudo remainder: ldcf(P,x_m) = a q + r rr = PolyGBUtil. coefficientPseudoRemainder(pr2, qr); //System.out.println("recursion, qr = " + qr); //System.out.println("recursion, pr = " + pr2); //System.out.println("recursion, rr = " + rr); } else { rr = pr2; } // reduction wrt. the other variables List> zeroDeg = zeroDegrees(A); GenPolynomial> Rr = PolyUtil.> distribute(rfac, rr); GenPolynomial R = PolyUtil. distribute(pfac, Rr); R = topCoefficientPseudoRemainder(zeroDeg, R); return R.monic(); } /** * Polynomial leading coefficient pseudo remainder. * @param P generic polynomial in n+1 variables. * @param A generic polynomial in n variables. * @return pseudo remainder of the leading coefficient of P wrt A, with * ldcf(A)m' P = quotient * A + remainder. */ public static > GenPolynomial>> coefficientPseudoRemainder( GenPolynomial>> P, GenPolynomial> A) { if (A == null || A.isZERO()) { // findbugs throw new ArithmeticException(P + " division by zero " + A); } if (A.isONE()) { return P.ring.getZERO(); } if (P.isZERO() || P.isONE()) { return P; } GenPolynomialRing>> pfac = P.ring; GenPolynomialRing> afac = A.ring; // == pfac.coFac GenPolynomial>> r = P; GenPolynomial> h; GenPolynomial>> hr; GenPolynomial> ldcf = P.leadingBaseCoefficient(); long m = ldcf.degree(0); long n = A.degree(0); GenPolynomial c = A.leadingBaseCoefficient(); GenPolynomial> cc = afac.getZERO().sum(c); //System.out.println("cc = " + cc); ExpVector e = A.leadingExpVector(); for (long i = m; i >= n; i--) { if (r.isZERO()) { return r; } GenPolynomial> p = r.leadingBaseCoefficient(); ExpVector g = r.leadingExpVector(); long k = p.degree(0); if (i == k) { GenPolynomial pl = p.leadingBaseCoefficient(); ExpVector f = p.leadingExpVector(); f = f.subtract(e); r = r.multiply(cc); // coeff cc h = A.multiply(pl, f); // coeff ac hr = new GenPolynomial>>(pfac, h, g); r = r.subtract(hr); } else { r = r.multiply(cc); } //System.out.println("r = " + r); } if (r.degree(0) < P.degree(0)) { // recursion for degree r = coefficientPseudoRemainder(r, A); } return r; } /** * Polynomial leading coefficient pseudo remainder, base case. * @param P generic polynomial in 1+1 variables. * @param A generic polynomial in 1 variable. * @return pseudo remainder of the leading coefficient of P wrt. A, with * ldcf(A)m' P = quotient * A + remainder. */ public static > GenPolynomial> coefficientPseudoRemainderBase( GenPolynomial> P, GenPolynomial A) { if (A == null || A.isZERO()) { // findbugs throw new ArithmeticException(P + " division by zero " + A); } if (A.isONE()) { return P.ring.getZERO(); } if (P.isZERO() || P.isONE()) { return P; } GenPolynomialRing> pfac = P.ring; GenPolynomialRing afac = A.ring; // == pfac.coFac GenPolynomial> r = P; GenPolynomial h; GenPolynomial> hr; GenPolynomial ldcf = P.leadingBaseCoefficient(); long m = ldcf.degree(0); long n = A.degree(0); C c = A.leadingBaseCoefficient(); GenPolynomial cc = afac.getZERO().sum(c); //System.out.println("cc = " + cc); ExpVector e = A.leadingExpVector(); for (long i = m; i >= n; i--) { if (r.isZERO()) { return r; } GenPolynomial p = r.leadingBaseCoefficient(); ExpVector g = r.leadingExpVector(); long k = p.degree(0); if (i == k) { C pl = p.leadingBaseCoefficient(); ExpVector f = p.leadingExpVector(); f = f.subtract(e); r = r.multiply(cc); // coeff cc h = A.multiply(pl, f); // coeff ac hr = new GenPolynomial>(pfac, h, g); r = r.subtract(hr); } else { r = r.multiply(cc); } //System.out.println("r = " + r); } if (r.degree(0) < P.degree(0)) { // recursion for degree r = coefficientPseudoRemainderBase(r, A); } return r; } /** * Extract polynomials with degree zero in the main variable. * @param A list of generic polynomials in n variables. * @return Z = [a_i] with deg(a_i,x_n) = 0 and in n-1 variables. */ public static > List> zeroDegrees(List> A) { if (A == null || A.isEmpty()) { return A; } GenPolynomialRing pfac = A.get(0).ring; GenPolynomialRing> rfac = pfac.recursive(1); List> zeroDeg = new ArrayList>(A.size()); for (int i = 0; i < A.size(); i++) { GenPolynomial q = A.get(i); GenPolynomial> fr = PolyUtil. recursive(rfac, q); if (fr.degree(0) == 0) { zeroDeg.add(fr.leadingBaseCoefficient()); } } return zeroDeg; } } jas-2.5/src/edu/jas/gbufd/MultiplicativeSetCoPrime.java0000644000175000017500000000716112004501610023336 0ustar giovannigiovanni/* * $Id: MultiplicativeSetCoPrime.java 4061 2012-07-27 12:03:20Z kredel $ */ package edu.jas.gbufd; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisorAbstract; /** * Multiplicative set of co-prime polynomials. a, b in M implies a*b in M, 1 in * M. * @param coefficient type * @author Heinz Kredel. */ public class MultiplicativeSetCoPrime> extends MultiplicativeSet { private static final Logger logger = Logger.getLogger(MultiplicativeSetCoPrime.class); //private final boolean debug = logger.isDebugEnabled(); /** * Gcd computation engine. */ protected final GreatestCommonDivisorAbstract engine; /** * MultiplicativeSet constructor. Constructs an empty multiplicative set. * @param ring polynomial ring factory for coefficients. */ public MultiplicativeSetCoPrime(GenPolynomialRing ring) { super(ring); engine = GCDFactory.getProxy(ring.coFac); } /** * MultiplicativeSet constructor. * @param ring polynomial ring factory for coefficients. * @param ms a list of non-zero polynomials. * @param eng gcd computation engine. */ protected MultiplicativeSetCoPrime(GenPolynomialRing ring, List> ms, GreatestCommonDivisorAbstract eng) { super(ring, ms); engine = eng; } /** * toString. * @see java.lang.Object#toString() */ @Override public String toString() { return "MultiplicativeSetCoPrime" + mset; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof MultiplicativeSetCoPrime)) { return false; } return super.equals(B); } /** * Add polynomial to mset. * @param cc polynomial to be added to mset. * @return new multiplicative set. */ @Override public MultiplicativeSetCoPrime add(GenPolynomial cc) { if (cc == null || cc.isZERO() || cc.isConstant()) { return this; } if (ring.coFac.isField()) { cc = cc.monic(); } List> list; if (mset.size() == 0) { list = engine.coPrime(cc, mset); if (ring.coFac.isField()) { list = PolyUtil. monic(list); } return new MultiplicativeSetCoPrime(ring, list, engine); } GenPolynomial c = removeFactors(cc); if (c.isConstant()) { logger.info("skipped unit or constant = " + c); return this; } logger.info("added to co-prime mset = " + c); list = engine.coPrime(c, mset); if (ring.coFac.isField()) { list = PolyUtil. monic(list); } return new MultiplicativeSetCoPrime(ring, list, engine); } /** * Replace polynomial list of mset. * @param L polynomial list to replace mset. * @return new multiplicative set. */ @Override public MultiplicativeSetCoPrime replace(List> L) { MultiplicativeSetCoPrime ms = new MultiplicativeSetCoPrime(ring); if (L == null || L.size() == 0) { return ms; } for (GenPolynomial p : L) { ms = ms.add(p); } return ms; } } jas-2.5/src/edu/jas/gbufd/RPseudoReduction.java0000644000175000017500000000063511505076162021663 0ustar giovannigiovanni/* * $Id: RPseudoReduction.java 3423 2010-12-24 10:56:50Z kredel $ */ package edu.jas.gbufd; import edu.jas.structure.RegularRingElem; /** * Polynomial R pseudo reduction interface. Combines RReduction and * PseudoReduction. * @param coefficient type * @author Heinz Kredel */ public interface RPseudoReduction> extends RReduction, PseudoReduction { } jas-2.5/src/edu/jas/gbufd/RPseudoReductionSeq.java0000644000175000017500000002734512004501610022325 0ustar giovannigiovanni/* * $Id: RPseudoReductionSeq.java 4061 2012-07-27 12:03:20Z kredel $ */ package edu.jas.gbufd; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RegularRingElem; /** * Polynomial regular ring pseudo reduction sequential use algorithm. Implements * fraction free normalform algorithm. * @param coefficient type * @author Heinz Kredel */ public class RPseudoReductionSeq> extends RReductionSeq implements RPseudoReduction { private static final Logger logger = Logger.getLogger(RPseudoReductionSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public RPseudoReductionSeq() { } /** * Normalform using r-reduction. * @param Ap polynomial. * @param Pp polynomial list. * @return r-nf(Ap) with respect to Pp. */ @Override @SuppressWarnings("unchecked") public GenPolynomial normalform(List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenPolynomial[]) new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } //System.out.println("l = " + l); Map.Entry m; ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RegularRingElem[l]; // want GenPolynomial[] p = (GenPolynomial[]) new GenPolynomial[l]; int i; int j = 0; for (i = 0; i < l; i++) { if (P[i] == null) { continue; } p[i] = P[i].abs(); m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e, f; C a; C r = null; boolean mt = false; GenPolynomial R = Ap.ring.getZERO(); GenPolynomial Q = null; GenPolynomial S = Ap; while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); //System.out.println("--a = " + a); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { C c = lbc[i]; //r = a.idempotent().multiply( c.idempotent() ); r = a.idempotentAnd(c); mt = !r.isZERO(); // && mt if (mt) { f = e.subtract(htl[i]); if (a.remainder(c).isZERO()) { //c.isUnit() ) { a = a.divide(c); if (a.isZERO()) { throw new ArithmeticException("a.isZERO()"); } } else { c = c.fillOne(); S = S.multiply(c); R = R.multiply(c); } Q = p[i].multiply(a, f); S = S.subtract(Q); f = S.leadingExpVector(); if (!e.equals(f)) { a = Ap.ring.coFac.getZERO(); break; } a = S.leadingBaseCoefficient(); } } } if (!a.isZERO()) { //! mt ) { //logger.debug("irred"); R = R.sum(a, e); S = S.reductum(); } } return R.abs(); // not monic if not boolean closed } /** * Normalform using r-reduction. * @param Pp polynomial list. * @param Ap polynomial. * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor * for Ap. */ @SuppressWarnings("unchecked") public PseudoReductionEntry normalformFactor(List> Pp, GenPolynomial Ap) { if (Ap == null) { return null; } C mfac = Ap.ring.getONECoefficient(); PseudoReductionEntry pf = new PseudoReductionEntry(Ap, mfac); if (Pp == null || Pp.isEmpty()) { return pf; } if (Ap.isZERO()) { return pf; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenPolynomial[]) new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } //System.out.println("l = " + l); Map.Entry m; ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RegularRingElem[l]; // want GenPolynomial[] p = (GenPolynomial[]) new GenPolynomial[l]; int i; int j = 0; for (i = 0; i < l; i++) { if (P[i] == null) { continue; } p[i] = P[i].abs(); m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e, f; C a; C r = null; boolean mt = false; GenPolynomial R = Ap.ring.getZERO(); GenPolynomial Q = null; GenPolynomial S = Ap; while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); //System.out.println("--a = " + a); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { C c = lbc[i]; //r = a.idempotent().multiply( c.idempotent() ); r = a.idempotentAnd(c); mt = !r.isZERO(); // && mt if (mt) { f = e.subtract(htl[i]); if (a.remainder(c).isZERO()) { //c.isUnit() ) { a = a.divide(c); if (a.isZERO()) { throw new ArithmeticException("a.isZERO()"); } } else { c = c.fillOne(); S = S.multiply(c); R = R.multiply(c); mfac = mfac.multiply(c); } Q = p[i].multiply(a, f); S = S.subtract(Q); f = S.leadingExpVector(); if (!e.equals(f)) { a = Ap.ring.coFac.getZERO(); break; } a = S.leadingBaseCoefficient(); } } } if (!a.isZERO()) { //! mt ) { //logger.debug("irred"); R = R.sum(a, e); S = S.reductum(); } } pf = new PseudoReductionEntry(R, mfac); //.abs(); // not monic if not boolean closed return pf; } /** * Normalform with recording. Note: Only meaningfull if all divisions * are exact. Compute first the multiplication factor m with * normalform(Pp,Ap,m), then call this method with * normalform(row,Pp,m*Ap). * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. */ @Override @SuppressWarnings("unchecked") public GenPolynomial normalform(List> row, List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenPolynomial[]) new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } //System.out.println("l = " + l); Map.Entry m; ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RegularRingElem[l]; // want GenPolynomial[] p = (GenPolynomial[]) new GenPolynomial[l]; int i; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e, f; C a, b; C r = null; boolean mt = false; GenPolynomial fac = null; GenPolynomial zero = Ap.ring.getZERO(); GenPolynomial R = Ap.ring.getZERO(); GenPolynomial Q = null; GenPolynomial S = Ap; while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { C c = lbc[i]; //r = a.idempotent().multiply( c.idempotent() ); r = a.idempotentAnd(c); //System.out.println("r = " + r); mt = !r.isZERO(); // && mt if (mt) { b = a.remainder(c); if (b.isZERO()) { a = a.divide(c); if (a.isZERO()) { throw new ArithmeticException("a.isZERO()"); } } else { c = c.fillOne(); S = S.multiply(c); R = R.multiply(c); } f = e.subtract(htl[i]); if (debug) { logger.info("red div = " + f); } Q = p[i].multiply(a, f); S = S.subtract(Q); // not ok with reductum fac = row.get(i); if (fac == null) { fac = zero.sum(a, f); } else { fac = fac.sum(a, f); } row.set(i, fac); f = S.leadingExpVector(); if (!e.equals(f)) { a = Ap.ring.coFac.getZERO(); break; } a = S.leadingBaseCoefficient(); } } } if (!a.isZERO()) { //! mt ) { //logger.debug("irred"); R = R.sum(a, e); S = S.reductum(); } } return R; //.abs(); // not monic if not boolean closed } /* * -------- boolean closure stuff ----------------------------------------- * -------- is all in superclass */ } jas-2.5/src/edu/jas/gbufd/GroebnerBasePseudoSeq.java0000644000175000017500000001632212067050600022605 0ustar giovannigiovanni/* * $Id: GroebnerBasePseudoSeq.java 4325 2012-12-27 13:47:44Z kredel $ */ package edu.jas.gbufd; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import org.apache.log4j.Logger; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.Pair; import edu.jas.gb.PairList; import edu.jas.gb.OrderedPairlist; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisorAbstract; /** * Groebner Base with pseudo reduction sequential algorithm. Implements * coefficient fraction free Groebner bases. * @param coefficient type * @author Heinz Kredel * * @see edu.jas.application.GBAlgorithmBuilder * @see edu.jas.gbufd.GBFactory */ public class GroebnerBasePseudoSeq> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBasePseudoSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Greatest common divisor engine for coefficient content and primitive * parts. */ protected final GreatestCommonDivisorAbstract engine; /** * Pseudo reduction engine. */ protected final PseudoReduction red; /** * Coefficient ring factory. */ protected final RingFactory cofac; /** * Constructor. * @param rf coefficient ring factory. */ public GroebnerBasePseudoSeq(RingFactory rf) { this(new PseudoReductionSeq(), rf, new OrderedPairlist()); } /** * Constructor. * @param rf coefficient ring factory. * @param pl pair selection strategy */ public GroebnerBasePseudoSeq(RingFactory rf, PairList pl) { this(new PseudoReductionSeq(), rf, pl); } /** * Constructor. * @param red pseudo reduction engine. * @param rf coefficient ring factory. Note: red must be an instance * of PseudoReductionSeq. */ public GroebnerBasePseudoSeq(PseudoReduction red, RingFactory rf, PairList pl) { super(red,pl); this.red = red; cofac = rf; engine = GCDFactory. getImplementation(rf); //not used: engine = (GreatestCommonDivisorAbstract)GCDFactory.getProxy( rf ); } /** * Groebner base using pairlist class. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> GB(int modv, List> F) { GenPolynomial p; List> G = new ArrayList>(); PairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = engine.basePrimitivePart(p); //p.monic(); p = p.abs(); if (p.isConstant()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); if (pairlist == null) { //pairlist = new OrderedPairlist(modv, p.ring); pairlist = strategy.create(modv, p.ring); } // putOne not required pairlist.put(p); } else { l--; } } if (l <= 1) { return G; // since no threads are activated } Pair pair; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial H; while (pairlist.hasNext()) { pair = pairlist.removeNext(); if (pair == null) continue; pi = pair.pi; pj = pair.pj; if (debug) { logger.debug("pi = " + pi); logger.debug("pj = " + pj); } S = red.SPolynomial(pi, pj); if (S.isZERO()) { pair.setZero(); continue; } if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(G, S); if (H.isZERO()) { pair.setZero(); continue; } if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = engine.basePrimitivePart(H); //H.monic(); H = H.abs(); if (H.isConstant()) { G.clear(); G.add(H); return G; // since no threads are activated } if (logger.isDebugEnabled()) { logger.debug("H = " + H); } if (H.length() > 0) { l++; G.add(H); pairlist.put(H); } } logger.debug("#sequential list = " + G.size()); G = minimalGB(G); logger.info("" + pairlist); return G; } /** * Minimal ordered Groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. */ @Override public List> minimalGB(List> Gp) { if (Gp == null || Gp.size() <= 1) { return Gp; } // remove zero polynomials List> G = new ArrayList>(Gp.size()); for (GenPolynomial a : Gp) { if (a != null && !a.isZERO()) { // always true in GB() // already positive a = a.abs(); G.add(a); } } if (G.size() <= 1) { return G; } // remove top reducible polynomials GenPolynomial a; List> F; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { // drop polynomial if (debug) { System.out.println("dropped " + a); List> ff; ff = new ArrayList>(G); ff.addAll(F); a = red.normalform(ff, a); if (!a.isZERO()) { System.out.println("error, nf(a) " + a); } } } else { F.add(a); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB // reduce remaining polynomials int len = G.size(); int i = 0; while (i < len) { a = G.remove(0); //System.out.println("doing " + a.length()); a = red.normalform(G, a); a = engine.basePrimitivePart(a); //a.monic(); was not required a = a.abs(); //a = red.normalform( F, a ); G.add(a); // adds as last i++; } return G; } } jas-2.5/src/edu/jas/gbufd/PseudoReductionSeq.java0000644000175000017500000002244412045500020022175 0ustar giovannigiovanni/* * $Id: PseudoReductionSeq.java 4290 2012-11-04 14:47:45Z kredel $ */ package edu.jas.gbufd; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.gb.ReductionAbstract; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Polynomial pseudo reduction sequential use algorithm. Coefficients of * polynomials must not be from a field, i.e. the fraction free reduction is * implemented. Implements normalform. * @param coefficient type * @author Heinz Kredel */ public class PseudoReductionSeq> extends ReductionAbstract implements PseudoReduction { private static final Logger logger = Logger.getLogger(PseudoReductionSeq.class); /** * Constructor. */ public PseudoReductionSeq() { } /** * Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @return nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } Map.Entry m; GenPolynomial[] P = new GenPolynomial[0]; synchronized (Pp) { P = Pp.toArray(P); } int l = P.length; ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RingElem[l]; GenPolynomial[] p = new GenPolynomial[l]; int i; int j = 0; for (i = 0; i < l; i++) { if (P[i] == null) { continue; } p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; boolean mt = false; GenPolynomial R = Ap.ring.getZERO().copy(); GenPolynomial S = Ap.copy(); while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) break; } if (!mt) { //logger.debug("irred"); //R = R.sum(a, e); //S = S.subtract(a, e); R.doPutToMap(e, a); S.doRemoveFromMap(e, a); //System.out.println(" S = " + S); } else { e = e.subtract(htl[i]); //logger.info("red div = " + e); @SuppressWarnings("cast") C c = (C) lbc[i]; if (a.remainder(c).isZERO()) { //c.isUnit() ) { a = a.divide(c); S = S.subtractMultiple(a, e, p[i]); } else { R = R.multiply(c); //S = S.multiply(c); S = S.scaleSubtractMultiple(c, a, e, p[i]); } //Q = p[i].multiply(a, e); //S = S.subtract(Q); } } return R; } /** * Normalform. * @param Pp polynomial list. * @param Ap polynomial. * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor * for Ap. */ @SuppressWarnings("unchecked") public PseudoReductionEntry normalformFactor(List> Pp, GenPolynomial Ap) { if (Ap == null) { return null; } C mfac = Ap.ring.getONECoefficient(); PseudoReductionEntry pf = new PseudoReductionEntry(Ap, mfac); if (Pp == null || Pp.isEmpty()) { return pf; } if (Ap.isZERO()) { return pf; } Map.Entry m; GenPolynomial[] P = new GenPolynomial[0]; synchronized (Pp) { P = Pp.toArray(P); } int l = P.length; ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RingElem[l]; // want C[] GenPolynomial[] p = new GenPolynomial[l]; int i; int j = 0; for (i = 0; i < l; i++) { if (P[i] == null) { continue; } p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; boolean mt = false; GenPolynomial R = Ap.ring.getZERO().copy(); GenPolynomial S = Ap.copy(); while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) break; } if (!mt) { //logger.debug("irred"); //R = R.sum(a, e); //S = S.subtract(a, e); R.doPutToMap(e, a); S.doRemoveFromMap(e, a); //System.out.println(" S = " + S); } else { e = e.subtract(htl[i]); //logger.info("red div = " + e); C c = lbc[i]; if (a.remainder(c).isZERO()) { //c.isUnit() ) { a = a.divide(c); S = S.subtractMultiple(a, e, p[i]); } else { mfac = mfac.multiply(c); R = R.multiply(c); //S = S.multiply(c); S = S.scaleSubtractMultiple(c, a, e, p[i]); } //Q = p[i].multiply(a, e); //S = S.subtract(Q); } } if (logger.isInfoEnabled()) { logger.info("multiplicative factor = " + mfac); } pf = new PseudoReductionEntry(R, mfac); return pf; } /** * Normalform with recording. Note: Only meaningful if all divisions * are exact. Compute first the multiplication factor m with * normalform(Pp,Ap,m), then call this method with * normalform(row,Pp,m*Ap). * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(List> row, List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } GenPolynomial[] P = new GenPolynomial[0]; synchronized (Pp) { P = Pp.toArray(P); } int l = P.length; ExpVector[] htl = new ExpVector[l]; Object[] lbc = new Object[l]; // want C GenPolynomial[] p = new GenPolynomial[l]; Map.Entry m; int j = 0; int i; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; boolean mt = false; GenPolynomial zero = Ap.ring.getZERO(); GenPolynomial R = Ap.ring.getZERO().copy(); GenPolynomial fac = null; GenPolynomial S = Ap.copy(); while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) break; } if (!mt) { //logger.debug("irred"); //R = R.sum(a, e); //S = S.subtract(a, e); R.doPutToMap(e, a); S.doRemoveFromMap(e, a); // System.out.println(" S = " + S); //throw new RuntimeException("Syzygy no GB"); } else { e = e.subtract(htl[i]); //logger.info("red div = " + e); C c = (C) lbc[i]; if (a.remainder(c).isZERO()) { //c.isUnit() ) { a = a.divide(c); S = S.subtractMultiple(a, e, p[i]); //System.out.print("|"); } else { //System.out.print("*"); R = R.multiply(c); //S = S.multiply(c); S = S.scaleSubtractMultiple(c, a, e, p[i]); } //Q = p[i].multiply(a, e); //S = S.subtract(Q); fac = row.get(i); if (fac == null) { fac = zero.sum(a, e); } else { fac = fac.sum(a, e); } row.set(i, fac); } } return R; } } jas-2.5/src/edu/jas/ps/0000755000175000017500000000000012140140256015101 5ustar giovannigiovannijas-2.5/src/edu/jas/ps/UnivPowerSeries.java0000644000175000017500000005354012014234362021066 0ustar giovannigiovanni/* * $Id: UnivPowerSeries.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.ps; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.BinaryFunctor; import edu.jas.structure.RingElem; import edu.jas.structure.Selector; import edu.jas.structure.UnaryFunctor; /** * Univariate power series implementation. Uses inner classes and lazy evaluated * generating function for coefficients. All ring element methods use lazy * evaluation except where noted otherwise. Eager evaluated methods are * toString(), compareTo(), equals(), * evaluate(), or they use the order() method, like * signum(), abs(), divide(), * remainder() and gcd(). * @param ring element type * @author Heinz Kredel */ public class UnivPowerSeries> implements RingElem> { /** * Power series ring factory. */ public final UnivPowerSeriesRing ring; /** * Data structure / generating function for coeffcients. Cannot be final * because of fixPoint, must be accessible in factory. */ /*package*/Coefficients lazyCoeffs; /** * Truncation of computations. */ private int truncate = 11; /** * Order of power series. */ private int order = -1; // == unknown /** * Private constructor. */ @SuppressWarnings("unused") private UnivPowerSeries() { throw new IllegalArgumentException("do not use no-argument constructor"); } /** * Package constructor. Use in fixPoint only, must be accessible in factory. * @param ring power series ring. */ /*package*/UnivPowerSeries(UnivPowerSeriesRing ring) { this.ring = ring; this.lazyCoeffs = null; } /** * Constructor. * @param ring power series ring. * @param lazyCoeffs generating function for coefficients. */ public UnivPowerSeries(UnivPowerSeriesRing ring, Coefficients lazyCoeffs) { if (lazyCoeffs == null || ring == null) { throw new IllegalArgumentException("null not allowed: ring = " + ring + ", lazyCoeffs = " + lazyCoeffs); } this.ring = ring; this.lazyCoeffs = lazyCoeffs; this.truncate = ring.truncate; } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public UnivPowerSeriesRing factory() { return ring; } /** * Clone this power series. * @see java.lang.Object#clone() */ @Override public UnivPowerSeries copy() { return new UnivPowerSeries(ring, lazyCoeffs); } /** * String representation of power series. * @see java.lang.Object#toString() */ @Override public String toString() { return toString(truncate); } /** * To String with given truncate. * @return string representation of this to given truncate. */ public String toString(int truncate) { StringBuffer sb = new StringBuffer(); UnivPowerSeries s = this; String var = ring.var; //System.out.println("cache = " + s.coeffCache); for (int i = 0; i < truncate; i++) { C c = s.coefficient(i); int si = c.signum(); if (si != 0) { if (si > 0) { if (sb.length() > 0) { sb.append(" + "); } } else { c = c.negate(); sb.append(" - "); } if (!c.isONE() || i == 0) { if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) { sb.append("{ "); } sb.append(c.toString()); if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) { sb.append(" }"); } if (i > 0) { sb.append(" * "); } } if (i == 0) { //skip; sb.append(" "); } else if (i == 1) { sb.append(var); } else { sb.append(var + "^" + i); } //sb.append(c.toString() + ", "); } //System.out.println("cache = " + s.coeffCache); } if (sb.length() == 0) { sb.append("0"); } sb.append(" + BigO(" + var + "^" + truncate + ")"); //sb.append("..."); return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer sb = new StringBuffer(""); UnivPowerSeries s = this; String var = ring.var; //System.out.println("cache = " + s.coeffCache); for (int i = 0; i < truncate; i++) { C c = s.coefficient(i); int si = c.signum(); if (si != 0) { if (si > 0) { if (sb.length() > 0) { sb.append(" + "); } } else { c = c.negate(); sb.append(" - "); } if (!c.isONE() || i == 0) { if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) { sb.append("{ "); } sb.append(c.toScript()); if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) { sb.append(" }"); } if (i > 0) { sb.append(" * "); } } if (i == 0) { //skip; sb.append(" "); } else if (i == 1) { sb.append(var); } else { sb.append(var + "**" + i); } //sb.append(c.toString() + ", "); } //System.out.println("cache = " + s.coeffCache); } if (sb.length() == 0) { sb.append("0"); } // sb.append("," + truncate + ""); return sb.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Get coefficient. * @param index number of requested coefficient. * @return coefficient at index. */ public C coefficient(int index) { if (index < 0) { throw new IndexOutOfBoundsException("negative index not allowed"); } //System.out.println("cache = " + coeffCache); return lazyCoeffs.get(index); } /** * Get a GenPolynomial<C> from this. * @return a GenPolynomial<C> from this up to truncate parts. */ public GenPolynomial asPolynomial() { GenPolynomial p = ring.polyRing().getZERO(); for (int i = 0; i <= truncate; i++) { C c = coefficient(i); ExpVector e = ExpVector.create(1, 0, i); p = p.sum(c, e); } return p; } /** * Leading base coefficient. * @return first coefficient. */ public C leadingCoefficient() { return coefficient(0); } /** * Reductum. * @return this - leading monomial. */ public UnivPowerSeries reductum() { return new UnivPowerSeries(ring, new Coefficients() { @Override public C generate(int i) { return coefficient(i + 1); } }); } /** * Prepend a new leading coefficient. * @param h new coefficient. * @return new power series. */ public UnivPowerSeries prepend(final C h) { return new UnivPowerSeries(ring, new Coefficients() { @Override public C generate(int i) { if (i == 0) { return h; } return coefficient(i - 1); } }); } /** * Shift coefficients. * @param k shift index. * @return new power series with coefficient(i) = old.coefficient(i-k). */ public UnivPowerSeries shift(final int k) { return new UnivPowerSeries(ring, new Coefficients() { @Override public C generate(int i) { if (i - k < 0) { return ring.coFac.getZERO(); } return coefficient(i - k); } }); } /** * Select coefficients. * @param sel selector functor. * @return new power series with selected coefficients. */ public UnivPowerSeries select(final Selector sel) { return new UnivPowerSeries(ring, new Coefficients() { @Override public C generate(int i) { C c = coefficient(i); if (sel.select(c)) { return c; } return ring.coFac.getZERO(); } }); } /** * Shift select coefficients. Not selected coefficients are removed from the * result series. * @param sel selector functor. * @return new power series with shifted selected coefficients. */ public UnivPowerSeries shiftSelect(final Selector sel) { return new UnivPowerSeries(ring, new Coefficients() { int pos = 0; @Override public C generate(int i) { C c; if (i > 0) { c = get(i - 1); // ensure coeffs are all generated } do { c = coefficient(pos++); } while (!sel.select(c)); return c; } }); } /** * Map a unary function to this power series. * @param f evaluation functor. * @return new power series with coefficients f(this(i)). */ public UnivPowerSeries map(final UnaryFunctor f) { return new UnivPowerSeries(ring, new Coefficients() { @Override public C generate(int i) { return f.eval(coefficient(i)); } }); } /** * Map a binary function to this and another power series. * @param f evaluation functor with coefficients f(this(i),other(i)). * @param ps other power series. * @return new power series. */ public > UnivPowerSeries zip(final BinaryFunctor f, final UnivPowerSeries ps) { return new UnivPowerSeries(ring, new Coefficients() { @Override public C generate(int i) { return f.eval(coefficient(i), ps.coefficient(i)); } }); } /** * Sum of two power series. * @param ps other power series. * @return this + ps. */ public UnivPowerSeries sum(UnivPowerSeries ps) { return zip(new Sum(), ps); } /** * Subtraction of two power series. * @param ps other power series. * @return this - ps. */ public UnivPowerSeries subtract(UnivPowerSeries ps) { return zip(new Subtract(), ps); } /** * Multiply by coefficient. * @param c coefficient. * @return this * c. */ public UnivPowerSeries multiply(C c) { return map(new Multiply(c)); } /** * Negate. * @return - this. */ public UnivPowerSeries negate() { return map(new Negate()); } /** * Absolute value. * @return abs(this). */ public UnivPowerSeries abs() { if (signum() < 0) { return negate(); } return this; } /** * Evaluate at given point. * @return ps(c). */ public C evaluate(C e) { C v = coefficient(0); C p = e; for (int i = 1; i < truncate; i++) { C c = coefficient(i).multiply(p); v = v.sum(c); p = p.multiply(e); } return v; } /** * Order. * @return index of first non zero coefficient. */ public int order() { if (order < 0) { // compute it for (int i = 0; i <= truncate; i++) { if (!coefficient(i).isZERO()) { order = i; return order; } } order = truncate + 1; } return order; } /** * Truncate. * @return truncate index of power series. */ public int truncate() { return truncate; } /** * Set truncate. * @param t new truncate index. * @return old truncate index of power series. */ public int setTruncate(int t) { if (t < 0) { throw new IllegalArgumentException("negative truncate not allowed"); } int ot = truncate; truncate = t; return ot; } /** * Signum. * @return sign of first non zero coefficient. */ public int signum() { return coefficient(order()).signum(); } /** * Compare to. Note: compare only up to truncate. * @return sign of first non zero coefficient of this-ps. */ //JAVA6only: @Override public int compareTo(UnivPowerSeries ps) { int m = order(); int n = ps.order(); int pos = (m <= n) ? m : n; int s = 0; do { s = coefficient(pos).compareTo(ps.coefficient(pos)); pos++; } while (s == 0 && pos <= truncate); return s; } /** * Is power series zero. Note: compare only up to truncate. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return (compareTo(ring.ZERO) == 0); } /** * Is power series one. Note: compare only up to truncate. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return (compareTo(ring.ONE) == 0); } /** * Comparison with any other object. Note: compare only up to * truncate. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { UnivPowerSeries a = null; try { a = (UnivPowerSeries) B; } catch (ClassCastException ignored) { } if (a == null) { return false; } return compareTo(a) == 0; } /** * Hash code for this polynomial. Note: only up to truncate. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = 0; //h = ( ring.hashCode() << 23 ); //h += val.hashCode(); for (int i = 0; i <= truncate; i++) { h += coefficient(i).hashCode(); h = (h << 23); } return h; } /** * Is unit. * @return true, if this power series is invertible, else false. */ public boolean isUnit() { return leadingCoefficient().isUnit(); } /** * Multiply by another power series. * @return this * ps. */ public UnivPowerSeries multiply(final UnivPowerSeries ps) { return new UnivPowerSeries(ring, new Coefficients() { @Override public C generate(int i) { C c = null; //fac.getZERO(); for (int k = 0; k <= i; k++) { C m = coefficient(k).multiply(ps.coefficient(i - k)); if (c == null) { c = m; } else { c = c.sum(m); } } return c; } }); } /** * Inverse power series. * @return ps with this * ps = 1. */ public UnivPowerSeries inverse() { return new UnivPowerSeries(ring, new Coefficients() { @Override public C generate(int i) { C d = leadingCoefficient().inverse(); // may fail if (i == 0) { return d; } C c = null; //fac.getZERO(); for (int k = 0; k < i; k++) { C m = get(k).multiply(coefficient(i - k)); if (c == null) { c = m; } else { c = c.sum(m); } } c = c.multiply(d.negate()); return c; } }); } /** * Divide by another power series. * @return this / ps. */ public UnivPowerSeries divide(UnivPowerSeries ps) { if (ps.isUnit()) { return multiply(ps.inverse()); } int m = order(); int n = ps.order(); if (m < n) { return ring.getZERO(); } if (!ps.coefficient(n).isUnit()) { throw new ArithmeticException("division by non unit coefficient " + ps.coefficient(n) + ", n = " + n); } // now m >= n UnivPowerSeries st, sps, q, sq; if (m == 0) { st = this; } else { st = this.shift(-m); } if (n == 0) { sps = ps; } else { sps = ps.shift(-n); } q = st.multiply(sps.inverse()); if (m == n) { sq = q; } else { sq = q.shift(m - n); } return sq; } /** * Power series remainder. * @param ps nonzero power series with invertible leading coefficient. * @return remainder with this = quotient * ps + remainder. */ public UnivPowerSeries remainder(UnivPowerSeries ps) { int m = order(); int n = ps.order(); if (m >= n) { return ring.getZERO(); } return this; } /** * Differentiate. * @return differentiate(this). */ public UnivPowerSeries differentiate() { return new UnivPowerSeries(ring, new Coefficients() { @Override public C generate(int i) { C v = coefficient(i + 1); v = v.multiply(ring.coFac.fromInteger(i + 1)); return v; } }); } /** * Integrate with given constant. * @param c integration constant. * @return integrate(this). */ public UnivPowerSeries integrate(final C c) { return new UnivPowerSeries(ring, new Coefficients() { @Override public C generate(int i) { if (i == 0) { return c; } C v = coefficient(i - 1); v = v.divide(ring.coFac.fromInteger(i)); return v; } }); } /** * Power series greatest common divisor. * @param ps power series. * @return gcd(this,ps). */ public UnivPowerSeries gcd(UnivPowerSeries ps) { if (ps.isZERO()) { return this; } if (this.isZERO()) { return ps; } int m = order(); int n = ps.order(); int ll = (m < n) ? m : n; return ring.getONE().shift(ll); } /** * Power series extended greatest common divisor. Note: not * implemented. * @param S power series. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ //SuppressWarnings("unchecked") public UnivPowerSeries[] egcd(UnivPowerSeries S) { throw new UnsupportedOperationException("egcd for power series not implemented"); } } /* arithmetic method functors */ /** * Internal summation functor. */ class Sum> implements BinaryFunctor { public C eval(C c1, C c2) { return c1.sum(c2); } } /** * Internal subtraction functor. */ class Subtract> implements BinaryFunctor { public C eval(C c1, C c2) { return c1.subtract(c2); } } /** * Internal scalar multiplication functor. */ class Multiply> implements UnaryFunctor { C x; public Multiply(C x) { this.x = x; } public C eval(C c) { return c.multiply(x); } } /** * Internal negation functor. */ class Negate> implements UnaryFunctor { public C eval(C c) { return c.negate(); } } /* only for sequential access: class Abs> implements UnaryFunctor { int sign = 0; public C eval(C c) { int s = c.signum(); if ( s == 0 ) { return c; } if ( sign > 0 ) { return c; } else if ( sign < 0 ) { return c.negate(); } // first non zero coefficient: sign = s; if ( s > 0 ) { return c; } return c.negate(); } } */ jas-2.5/src/edu/jas/ps/Examples.java0000644000175000017500000004340012000257334017524 0ustar giovannigiovanni/* * $Id: Examples.java 3987 2012-07-14 11:58:20Z kredel $ */ package edu.jas.ps; import edu.jas.arith.BigComplex; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.structure.BinaryFunctor; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.Selector; import edu.jas.structure.UnaryFunctor; /** * Examples for univariate power series implementations. * @author Heinz Kredel */ public class Examples { public static void main(String[] args) { example2(); example4(); example6(); example8(); example9(); example10(); example11(); example1(); example3(); example5(); example7(); if ( args.length > 0 ) { example12(); } example13(); } static UnivPowerSeries integersFrom(final int start) { UnivPowerSeriesRing pfac = new UnivPowerSeriesRing(new BigInteger()); return new UnivPowerSeries(pfac, new Coefficients() { @Override public BigInteger generate(int i) { return new BigInteger(start + i); } }); } //---------------------- static class Sum> implements BinaryFunctor { public C eval(C c1, C c2) { return c1.sum(c2); } } static class Odds> implements Selector { C two; RingFactory fac; public Odds(RingFactory fac) { this.fac = fac; two = this.fac.fromInteger(2); //System.out.println("two = " + two); } public boolean select(C c) { //System.out.print("c = " + c); if (c.remainder(two).isONE()) { //System.out.println(" odd"); return true; } //System.out.println(" even"); return false; } } //---------------------- public static void example1() { UnivPowerSeries integers = integersFrom(0); BigInteger e = new BigInteger(1); BigInteger v = integers.evaluate(e); System.out.println("integers(" + e + ") = " + v); e = new BigInteger(0); v = integers.evaluate(e); System.out.println("integers(" + e + ") = " + v); e = new BigInteger(2); v = integers.evaluate(e); System.out.println("integers(" + e + ") = " + v); } public static void example2() { UnivPowerSeries integers = integersFrom(0); System.out.print("integer coefficients = "); UnivPowerSeries s = integers; for (int i = 0; i < 20; i++) { BigInteger c = s.leadingCoefficient(); System.out.print(c.toString() + ", "); s = s.reductum(); } System.out.println("..."); } public static void example3() { RingFactory fac = new BigInteger(1); UnivPowerSeriesRing ups = new UnivPowerSeriesRing(fac); System.out.println("ups = " + ups); System.out.println("ups.isCommutative() = " + ups.isCommutative()); System.out.println("ups.isAssociative() = " + ups.isAssociative()); System.out.println("ups.isField() = " + ups.isField()); System.out.println("ups.getZERO() = " + ups.getZERO()); System.out.println("ups.getONE() = " + ups.getONE()); UnivPowerSeries rnd = ups.random(); System.out.println("rnd = " + rnd); System.out.println("rnd = " + rnd); System.out.println("rnd.isUnit() = " + rnd.isUnit()); } public static void example4() { UnivPowerSeries integers = integersFrom(0); System.out.println("integers = " + integers); } public static void example6() { UnivPowerSeriesRing pfac = new UnivPowerSeriesRing(new BigInteger()); UnivPowerSeries integers; integers = pfac.fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries ps) { return ps.map(new UnaryFunctor() { public BigInteger eval(BigInteger s) { return s.sum(new BigInteger(1)); } }).prepend(new BigInteger(0)); } }); System.out.println("integers1 = " + integers); System.out.println("integers2 = " + integers); } public static void example8() { final BigInteger z = new BigInteger(0); final BigInteger one = new BigInteger(1); UnivPowerSeriesRing pfac = new UnivPowerSeriesRing(z); UnivPowerSeries fibs; fibs = pfac.fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries ps) { return ps.zip(new Sum(), ps.prepend(one)).prepend(z); } }); System.out.println("fibs1 = " + fibs.toString(/*20*/)); System.out.println("fibs2 = " + fibs.toString(/*20*/)); } public static void example9() { UnivPowerSeries integers = integersFrom(0); System.out.println(" integers = " + integers); UnivPowerSeries doubleintegers = integers.sum(integers); System.out.println("doubleintegers = " + doubleintegers); UnivPowerSeries nulls = integers.subtract(integers); System.out.println("null integers = " + nulls); doubleintegers = integers.multiply(new BigInteger(2)); System.out.println("doubleintegers = " + doubleintegers); nulls = integers.multiply(new BigInteger(0)); System.out.println("null integers = " + nulls); UnivPowerSeries odds = integers.select(new Odds(new BigInteger())); System.out.println("odd integers = " + odds); } public static void example10() { final BigInteger fac = new BigInteger(); UnivPowerSeriesRing pfac = new UnivPowerSeriesRing(fac); UnivPowerSeries integers = integersFrom(0); System.out.println(" integers = " + integers); UnivPowerSeries ONE = new UnivPowerSeries(pfac, new Coefficients() { @Override public BigInteger generate(int i) { if (i == 0) { return fac.getONE(); } return fac.getZERO(); } }//, null ); System.out.println("ONE = " + ONE); UnivPowerSeries ZERO = new UnivPowerSeries(pfac, new Coefficients() { @Override public BigInteger generate(int i) { return fac.getZERO(); } }//, null ); System.out.println("ZERO = " + ZERO); UnivPowerSeries ints = integers.multiply(ONE); System.out.println("integers = " + ints); UnivPowerSeries nulls = integers.multiply(ZERO); System.out.println("null integers = " + nulls); UnivPowerSeries nints = integers.negate(); System.out.println("-integers = " + nints); UnivPowerSeries one = ONE.multiply(ONE); System.out.println("integers one = " + one); UnivPowerSeries ints2 = integers.multiply(integers); System.out.println("integers 2 = " + ints2); UnivPowerSeries inv1 = ONE.inverse(); System.out.println("integers inv1 = " + inv1); UnivPowerSeries int1 = integers.reductum(); System.out.println("integers int1 = " + int1); UnivPowerSeries intinv = int1.inverse(); System.out.println("integers intinv = " + intinv); UnivPowerSeries one1 = int1.multiply(intinv); System.out.println("integers one1 = " + one1); UnivPowerSeries ii = intinv.inverse(); System.out.println("integers ii = " + ii); UnivPowerSeries rem = integers.subtract(integers.divide(int1).multiply(int1)); System.out.println("integers rem = " + rem); } public static void example11() { //final BigInteger fac = new BigInteger(); UnivPowerSeries integers = integersFrom(0); System.out.println(" integers = " + integers); UnivPowerSeries int2 = integers.multiply(new BigInteger(2)); System.out.println(" 2*integers = " + int2); System.out.println("integers < 2*integers = " + integers.compareTo(int2)); System.out.println("2*integers > integers = " + int2.compareTo(integers)); System.out.println("2*integers == integers = " + int2.equals(integers)); System.out.println("integers == integers = " + integers.equals(integers)); System.out.println("integers.hashCode() = " + integers.hashCode()); } public static void example5() { //final BigInteger fac = new BigInteger(); //UnivPowerSeriesRing pfac = new UnivPowerSeriesRing(fac); UnivPowerSeries integers = integersFrom(0); System.out.println(" integers = " + integers); UnivPowerSeries ints2 = integers.multiply(integers); System.out.println("integers 2 = " + ints2); UnivPowerSeries q1 = ints2.divide(integers); System.out.println("q1 = " + q1); UnivPowerSeries q2 = integers.divide(ints2); System.out.println("q2 = " + q2); UnivPowerSeries r1 = ints2.remainder(integers); System.out.println("r1 = " + r1); UnivPowerSeries r2 = integers.remainder(ints2); System.out.println("r2 = " + r2); UnivPowerSeries qr1 = q1.multiply(integers).sum(r1); System.out.println("qr1 = " + qr1); UnivPowerSeries qr2 = q2.multiply(ints2).sum(r2); System.out.println("qr2 = " + qr2); System.out.println("sign(qr1-ints2) = " + qr1.compareTo(ints2)); System.out.println("sign(qr2-integers) = " + qr2.compareTo(integers)); UnivPowerSeries g = ints2.gcd(integers); System.out.println("g = " + g); } public static void example7() { final BigRational fac = new BigRational(); final UnivPowerSeriesRing pfac = new UnivPowerSeriesRing(fac, 11, "y"); UnivPowerSeries exp = pfac.fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries e) { return e.integrate(fac.getONE()); } }); System.out.println("exp = " + exp); UnivPowerSeries tan = pfac.fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries t) { return t.multiply(t).sum(pfac.getONE()).integrate(fac.getZERO()); } }); System.out.println("tan = " + tan); UnivPowerSeries sin = new UnivPowerSeries(pfac, new Coefficients() { @Override public BigRational generate(int i) { BigRational c; if (i == 0) { c = fac.getZERO(); } else if (i == 1) { c = fac.getONE(); } else { c = get(i - 2).negate(); c = c.divide(fac.fromInteger(i)).divide(fac.fromInteger(i - 1)); } return c; } }); System.out.println("sin = " + sin); UnivPowerSeries sin1 = pfac.fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries e) { return e.negate().integrate(fac.getONE()).integrate(fac.getZERO()); } }); System.out.println("sin1 = " + sin1); UnivPowerSeries cos = new UnivPowerSeries(pfac, new Coefficients() { @Override public BigRational generate(int i) { BigRational c; if (i == 0) { c = fac.getONE(); } else if (i == 1) { c = fac.getZERO(); } else { c = get(i - 2).negate(); c = c.divide(fac.fromInteger(i)).divide(fac.fromInteger(i - 1)); } return c; } }); System.out.println("cos = " + cos); UnivPowerSeries cos1 = pfac.fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries e) { return e.negate().integrate(fac.getZERO()).integrate(fac.getONE()); } }); System.out.println("cos1 = " + cos1); UnivPowerSeries cos2 = pfac.solveODE(sin1.negate(), fac.getONE()); System.out.println("cos2 = " + cos2); UnivPowerSeries sin2 = pfac.solveODE(cos1, fac.getZERO()); System.out.println("sin2 = " + sin2); UnivPowerSeries sinh = new UnivPowerSeries(pfac, new Coefficients() { @Override public BigRational generate(int i) { BigRational c; if (i == 0) { c = fac.getZERO(); } else if (i == 1) { c = fac.getONE(); } else { c = get(i - 2); c = c.divide(fac.fromInteger(i)).divide(fac.fromInteger(i - 1)); } return c; } }); System.out.println("sinh = " + sinh); UnivPowerSeries cosh = new UnivPowerSeries(pfac, new Coefficients() { @Override public BigRational generate(int i) { BigRational c; if (i == 0) { c = fac.getONE(); } else if (i == 1) { c = fac.getZERO(); } else { c = get(i - 2); c = c.divide(fac.fromInteger(i)).divide(fac.fromInteger(i - 1)); } return c; } }//, null ); System.out.println("cosh = " + cosh); UnivPowerSeries sinhcosh = sinh.sum(cosh); System.out.println("sinh+cosh = " + sinhcosh); System.out.println("sinh+cosh == exp: " + sinhcosh.equals(exp)); } public static void example12() { final BigComplex fac = new BigComplex(); final BigComplex I = BigComplex.I; final UnivPowerSeriesRing pfac = new UnivPowerSeriesRing(fac); UnivPowerSeries exp = pfac.fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries e) { return e.integrate(I); } }); System.out.println("exp = " + exp); UnivPowerSeries sin = pfac.fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries e) { return e.negate().integrate(fac.getONE()).integrate(fac.getZERO()); } }); System.out.println("sin = " + sin); UnivPowerSeries cos = pfac.fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries e) { return e.negate().integrate(fac.getZERO()).integrate(fac.getONE()); } }); System.out.println("cos = " + cos); UnivPowerSeries cpis = cos.sum(sin.multiply(I)); System.out.println("cpis = " + cpis); } public static void example13() { BigRational fac = new BigRational(); UnivPowerSeriesRing pfac = new UnivPowerSeriesRing(fac, 11, "y"); UnivPowerSeries exp = pfac.getEXP(); System.out.println("exp = " + exp); System.out.println("exp(1) = " + exp.evaluate(fac.getONE())); System.out.println("exp(0) = " + exp.evaluate(fac.getZERO())); BigDecimal dfac = new BigDecimal(); UnivPowerSeriesRing dpfac = new UnivPowerSeriesRing(dfac, 11, "z"); UnivPowerSeries dexp = dpfac.getEXP(); System.out.println("exp = " + dexp); System.out.println("exp(1) = " + dexp.evaluate(dfac.getONE())); System.out.println("exp(0) = " + dexp.evaluate(dfac.getZERO())); } } jas-2.5/src/edu/jas/ps/TaylorFunctionAdapter.java0000644000175000017500000000317511453152070022236 0ustar giovannigiovanni/* * $Id: TaylorFunctionAdapter.java 3342 2010-10-06 19:55:37Z kredel $ */ package edu.jas.ps; import java.util.List; import edu.jas.poly.ExpVector; import edu.jas.structure.RingElem; /** * Adapter for functions capable for Taylor series expansion. * @param ring element type * @author Heinz Kredel */ public abstract class TaylorFunctionAdapter> implements TaylorFunction { /** * Get the factorial coefficient. * @return factorial coefficient. */ public long getFacul() { return 1L; } /** * Test if this is zero. * @return true if this is 0, else false. */ public boolean isZERO() { throw new UnsupportedOperationException("not implemented"); } /** * Deriviative. * @return deriviative of this. */ public TaylorFunction deriviative() { throw new UnsupportedOperationException("not implemented"); } /** * Multi-partial deriviative. * @param i exponent vector. * @return partial deriviative of this with respect to all variables. */ public TaylorFunction deriviative(ExpVector i) { throw new UnsupportedOperationException("not implemented"); } /** * Evaluate. * @param a element. * @return this(a). */ public C evaluate(C a) { throw new UnsupportedOperationException("not implemented"); } /** * Evaluate at a tuple of elements. * @param a tuple of elements. * @return this(a). */ public C evaluate(List a) { throw new UnsupportedOperationException("not implemented"); } } jas-2.5/src/edu/jas/ps/StandardBaseSeq.java0000644000175000017500000001743011456137602020767 0ustar giovannigiovanni/* * $Id: StandardBaseSeq.java 3349 2010-10-15 20:54:27Z kredel $ */ package edu.jas.ps; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import org.apache.log4j.Logger; import edu.jas.structure.RingElem; import edu.jas.poly.ExpVector; /** * Standard Base sequential algorithm. Implements Standard bases and GB test. * Note: Currently the term order is fixed to the order defined by the * iterator over exponent vectors ExpVectorIterator. * @param coefficient type * @author Heinz Kredel */ public class StandardBaseSeq> /*todo: extends StandardBaseAbstract*/{ private static final Logger logger = Logger.getLogger(StandardBaseSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Reduction engine. */ public final ReductionSeq red; /** * Constructor. */ public StandardBaseSeq() { //super(); this(new ReductionSeq()); } /** * Constructor. * @param red Reduction engine */ public StandardBaseSeq(ReductionSeq red) { this.red = red; //super(red); } /** * Standard base test. * @param F power series list. * @return true, if F is a Standard base, else false. */ public boolean isSTD(List> F) { return isSTD(0, F); } /** * Standard base test. * @param modv module variable number. * @param F power series list. * @return true, if F is a Standard base, else false. */ public boolean isSTD(int modv, List> F) { if (F == null) { return true; } MultiVarPowerSeries pi, pj, s, h; for (int i = 0; i < F.size(); i++) { pi = F.get(i); for (int j = i + 1; j < F.size(); j++) { pj = F.get(j); if (!red.moduleCriterion(modv, pi, pj)) { continue; } // if ( ! red.criterion4( pi, pj ) ) { // continue; // } s = red.SPolynomial(pi, pj); if (s.isZERO()) { continue; } h = red.normalform(F, s); if (!h.isZERO()) { System.out.println("pi = " + pi + ", pj = " + pj); System.out.println("s = " + s + ", h = " + h); return false; } } } return true; } /** * Standard base using pairlist class. * @param F power series list. * @return STD(F) a Standard base of F. */ public List> STD(List> F) { return STD(0, F); } /** * Standard base using pairlist class. * @param modv module variable number. * @param F power series list. * @return STD(F) a Standard base of F. */ public List> STD(int modv, List> F) { MultiVarPowerSeries p = null; List> G = new ArrayList>(); OrderedPairlist pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (!p.isZERO()) { //p = p.monic(); if (p.isUnit()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); if (pairlist == null) { pairlist = new OrderedPairlist(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // putOne not required pairlist.put(p); } else { l--; } } if (l <= 1) { return G; // since no threads are activated } Pair pair; MultiVarPowerSeries pi; MultiVarPowerSeries pj; MultiVarPowerSeries S; MultiVarPowerSeries H; while (pairlist.hasNext()) { pair = pairlist.removeNext(); //logger.debug("pair = " + pair); if (pair == null) { continue; } pi = pair.pi; pj = pair.pj; if ( /*false &&*/debug) { logger.debug("pi = " + pi); logger.debug("pj = " + pj); } S = red.SPolynomial(pi, pj); //S.setTruncate(p.ring.truncate()); // ?? if (S.isZERO()) { pair.setZero(); continue; } if (logger.isInfoEnabled()) { ExpVector es = S.orderExpVector(); logger.info("ht(S) = " + es.toString(S.ring.vars) + ", " + es); // + ", S = " + S); } //long t = System.currentTimeMillis(); H = red.normalform(G, S); if (H.isZERO()) { pair.setZero(); continue; } //t = System.currentTimeMillis() - t; //System.out.println("time = " + t); if (logger.isInfoEnabled()) { ExpVector eh = H.orderExpVector(); logger.info("ht(H) = " + eh.toString(S.ring.vars) + ", " + eh); // + ", coeff(HT(H)) = " + H.coefficient(eh)); } //H = H.monic(); if (H.isUnit()) { G.clear(); G.add(H); return G; // since no threads are activated } if (logger.isDebugEnabled()) { logger.info("H = " + H); } //if (!H.isZERO()) { l++; G.add(H); pairlist.put(H); //} } logger.debug("#sequential list = " + G.size()); G = minimalSTD(G); logger.info("" + pairlist); return G; } /** * Minimal ordered Standard basis. * @param Gp a Standard base. * @return a minimal Standard base of Gp, not auto reduced. */ public List> minimalSTD(List> Gp) { if (Gp == null || Gp.size() <= 1) { return Gp; } // remove zero power series List> G = new ArrayList>(Gp.size()); for (MultiVarPowerSeries a : Gp) { if (a != null && !a.isZERO()) { // always true in GB() // make positive a = a.abs(); ? a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } // remove top reducible power series MultiVarPowerSeries a; List> F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { // drop power series if (debug) { System.out.println("dropped " + a); List> ff = new ArrayList>(G); ff.addAll(F); a = red.normalform(ff, a); if (!a.isZERO()) { System.out.println("error, nf(a) " + a); } } } else { F.add(a); } } G = F; // power series not reduced return G; } } jas-2.5/src/edu/jas/ps/package.html0000644000175000017500000000231711445126622017375 0ustar giovannigiovanni Generic coefficients power series package

Generic coefficients power series package.

This package contains classes for univariate and multivariate power series arithmetic in classes UnivPowerSeries, UnivPowerSeriesRing, MultiVarPowerSeries and MultiVarPowerSeriesRing over coefficient rings which implement the RingElem interface. It contains also classes for reduction (with Mora's tangent cone algorithm) and standard base computations. Currently the term order is fixed to the order defined by the iterator over exponent vectors ExpVectorIterator.


Heinz Kredel

Last modified: Sat Sep 18 14:15:26 CEST 2010

$Id: package.html 3327 2010-09-18 12:16:19Z kredel $

jas-2.5/src/edu/jas/ps/TaylorFunction.java0000644000175000017500000000227511453152070020735 0ustar giovannigiovanni/* * $Id: TaylorFunction.java 3342 2010-10-06 19:55:37Z kredel $ */ package edu.jas.ps; import java.util.List; import edu.jas.poly.ExpVector; import edu.jas.structure.RingElem; /** * Interface for functions capable for Taylor series expansion. * @param ring element type * @author Heinz Kredel */ public interface TaylorFunction> { /** * Get the factorial coefficient. * @return factorial coefficient. */ public long getFacul(); /** * Test if this is zero. * @return true if this is 0, else false. */ public boolean isZERO(); /** * Deriviative. * @return deriviative of this. */ public TaylorFunction deriviative(); /** * Multi-partial deriviative. * @param i exponent vector. * @return partial deriviative of this with respect to all variables. */ public TaylorFunction deriviative(ExpVector i); /** * Evaluate. * @param a element. * @return this(a). */ public C evaluate(C a); /** * Evaluate at a tuple of elements. * @param a tuple of elements. * @return this(a). */ public C evaluate(List a); } jas-2.5/src/edu/jas/ps/MultiVarPowerSeriesRing.java0000644000175000017500000005061112014234362022524 0ustar giovannigiovanni/* * $Id: MultiVarPowerSeriesRing.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.ps; import java.io.Reader; import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Random; import edu.jas.kern.PrettyPrint; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.Monomial; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.UnaryFunctor; import edu.jas.util.ListUtil; /** * Multivariate power series ring implementation. Uses lazy evaluated generating * function for coefficients. * @param ring element type * @author Heinz Kredel */ public class MultiVarPowerSeriesRing> implements RingFactory> { /** * A default random sequence generator. */ protected final static Random random = new Random(); /** * Default truncate. */ public final static int DEFAULT_TRUNCATE = 7; /** * Truncate. */ int truncate; /** * Zero ExpVector. */ public final ExpVector EVZERO; /** * Coefficient ring factory. */ public final RingFactory coFac; /** * The number of variables. */ public final int nvar; /** * The names of the variables. This value can be modified. */ protected String[] vars; /** * The constant power series 1 for this ring. */ public final MultiVarPowerSeries ONE; /** * The constant power series 0 for this ring. */ public final MultiVarPowerSeries ZERO; /** * No argument constructor. */ @SuppressWarnings("unused") private MultiVarPowerSeriesRing() { throw new IllegalArgumentException("do not use no-argument constructor"); } /** * Constructor. * @param fac polynomial ring factory. */ public MultiVarPowerSeriesRing(GenPolynomialRing fac) { this(fac.coFac, fac.nvar, fac.getVars()); } /** * Constructor. * @param coFac coefficient ring factory. */ public MultiVarPowerSeriesRing(RingFactory coFac, int nv) { this(coFac, nv, DEFAULT_TRUNCATE); } /** * Constructor. * @param coFac coefficient ring factory. * @param truncate index of truncation. */ public MultiVarPowerSeriesRing(RingFactory coFac, int nv, int truncate) { this(coFac, nv, truncate, null); } /** * Constructor. * @param coFac coefficient ring factory. * @param names of the variables. */ public MultiVarPowerSeriesRing(RingFactory coFac, String[] names) { this(coFac, names.length, DEFAULT_TRUNCATE, names); } /** * Constructor. * @param cofac coefficient ring factory. * @param nv number of variables. * @param names of the variables. */ public MultiVarPowerSeriesRing(RingFactory cofac, int nv, String[] names) { this(cofac, nv, DEFAULT_TRUNCATE, names); } /** * Constructor. * @param cofac coefficient ring factory. * @param truncate index of truncation. * @param names of the variables. */ public MultiVarPowerSeriesRing(RingFactory cofac, int nv, int truncate, String[] names) { this.coFac = cofac; this.nvar = nv; this.truncate = truncate; vars = names; if (vars == null) { if (PrettyPrint.isTrue()) { vars = GenPolynomialRing.newVars("x", nvar); } } else { if (vars.length != nvar) { throw new IllegalArgumentException("incompatible variable size " + vars.length + ", " + nvar); } GenPolynomialRing.addVars(vars); } EVZERO = ExpVector.create(nvar); ONE = new MultiVarPowerSeries(this, new MultiVarCoefficients(this) { @Override public C generate(ExpVector i) { if (i.isZERO()) { return coFac.getONE(); } return coFac.getZERO(); } }); ZERO = new MultiVarPowerSeries(this, new MultiVarCoefficients(this) { @Override public C generate(ExpVector i) { return coFac.getZERO(); } }); } /** * Fixed point construction. * @param map a mapping of power series. * @return fix point wrt map. */ // Cannot be a static method because a power series ring is required. public MultiVarPowerSeries fixPoint(MultiVarPowerSeriesMap map) { MultiVarPowerSeries ps1 = new MultiVarPowerSeries(this); MultiVarPowerSeries ps2 = map.map(ps1); ps1.lazyCoeffs = ps2.lazyCoeffs; return ps2; } /** * To String. * @return string representation of this. */ @Override public String toString() { StringBuffer sb = new StringBuffer(); String scf = coFac.getClass().getSimpleName(); sb.append(scf + "((" + varsToString() + "))"); return sb.toString(); } /** * Get a String representation of the variable names. * @return names separated by commas. */ public String varsToString() { if (vars == null) { return "#" + nvar; } return ExpVector.varsToString(vars); //return Arrays.toString(vars); } /** * Get the variable names. * @return names. */ public String[] getVars() { return vars; // Java-5: Arrays.copyOf(vars,vars.length); } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer("MPS("); String f = null; try { f = ((RingElem) coFac).toScriptFactory(); // sic } catch (Exception e) { f = coFac.toScript(); } s.append(f + ",\"" + varsToString() + "\"," + truncate + ")"); return s.toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { MultiVarPowerSeriesRing a = null; try { a = (MultiVarPowerSeriesRing) B; } catch (ClassCastException ignored) { } if (a == null) { return false; } if (!coFac.equals(a.coFac)) { return false; } if (Arrays.equals(vars, a.vars)) { return true; } return false; } /** * Hash code for this . * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = coFac.hashCode(); h = h << 7; h += (Arrays.hashCode(vars) << 17); h += truncate; return h; } /** * Get the zero element. * @return 0 as MultiVarPowerSeries. */ public MultiVarPowerSeries getZERO() { return ZERO; } /** * Get the one element. * @return 1 as MultiVarPowerSeries. */ public MultiVarPowerSeries getONE() { return ONE; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List rgens = coFac.generators(); List> gens = new ArrayList>(rgens.size()); for (final C cg : rgens) { MultiVarPowerSeries g = new MultiVarPowerSeries(this, new MultiVarCoefficients(this) { @Override public C generate(ExpVector i) { if (i.isZERO()) { return cg; } return coFac.getZERO(); } }); gens.add(g); } for (int i = 0; i < nvar; i++) { gens.add(ONE.shift(1, nvar - 1 - i)); } return gens; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return false; } /** * Truncate. * @return truncate index of power series. */ public int truncate() { return truncate; } /** * Set truncate. * @param t new truncate index. * @return old truncate index of power series. */ public int setTruncate(int t) { if (t < 0) { throw new IllegalArgumentException("negative truncate not allowed"); } int ot = truncate; truncate = t; ONE.setTruncate(t); ZERO.setTruncate(t); return ot; } /** * Get the power series of the exponential function. * @param r variable for the direction. * @return exp(x_r) as MultiVarPowerSeries. */ public MultiVarPowerSeries getEXP(final int r) { return fixPoint(new MultiVarPowerSeriesMap() { public MultiVarPowerSeries map(MultiVarPowerSeries e) { return e.integrate(coFac.getONE(), r); } }); } /** * Get the power series of the sinus function. * @param r variable for the direction. * @return sin(x_r) as MultiVarPowerSeries. */ public MultiVarPowerSeries getSIN(final int r) { return fixPoint(new MultiVarPowerSeriesMap() { public MultiVarPowerSeries map(MultiVarPowerSeries s) { return s.negate().integrate(coFac.getONE(), r).integrate(coFac.getZERO(), r); } }); } /** * Get the power series of the cosinus function. * @param r variable for the direction. * @return cos(x_r) as MultiVarPowerSeries. */ public MultiVarPowerSeries getCOS(final int r) { return fixPoint(new MultiVarPowerSeriesMap() { public MultiVarPowerSeries map(MultiVarPowerSeries c) { return c.negate().integrate(coFac.getZERO(), r).integrate(coFac.getONE(), r); } }); } /** * Get the power series of the tangens function. * @param r variable for the direction. * @return tan(x_r) as MultiVarPowerSeries. */ public MultiVarPowerSeries getTAN(final int r) { return fixPoint(new MultiVarPowerSeriesMap() { public MultiVarPowerSeries map(MultiVarPowerSeries t) { return t.multiply(t).sum(getONE()).integrate(coFac.getZERO(), r); } }); } /** * Solve an partial differential equation. y_r' = f(y_r) with y_r(0) = c. * @param f a MultiVarPowerSeries. * @param c integration constant. * @param r variable for the direction. * @return f.integrate(c). */ public MultiVarPowerSeries solvePDE(MultiVarPowerSeries f, C c, int r) { return f.integrate(c, r); } /** * Query if this ring is commuative. * @return true, if this ring is commutative, else false. */ public boolean isCommutative() { return coFac.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return coFac.isAssociative(); } /** * Query if this ring is a field. * @return false. */ public boolean isField() { return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return coFac.characteristic(); } /** * Get a (constant) MultiVarPowerSeries<C> from a long value. * @param a long. * @return a MultiVarPowerSeries<C>. */ public MultiVarPowerSeries fromInteger(final long a) { return new MultiVarPowerSeries(this, new MultiVarCoefficients(this) { @Override public C generate(ExpVector i) { if (i.isZERO()) { return coFac.fromInteger(a); } return coFac.getZERO(); } }); } /** * Get a (constant) MultiVarPowerSeries<C> from a * java.math.BigInteger. * @param a BigInteger. * @return a MultiVarPowerSeries<C>. */ public MultiVarPowerSeries fromInteger(final java.math.BigInteger a) { return new MultiVarPowerSeries(this, new MultiVarCoefficients(this) { @Override public C generate(ExpVector i) { if (i.isZERO()) { return coFac.fromInteger(a); } return coFac.getZERO(); } }); } /** * Get the corresponding GenPolynomialRing<C>. * @return GenPolynomialRing<C>. */ public GenPolynomialRing polyRing() { return new GenPolynomialRing(coFac, nvar, vars); } /** * Get a MultiVarPowerSeries<C> from a GenPolynomial<C>. * @param a GenPolynomial<C>. * @return a MultiVarPowerSeries<C>. */ public MultiVarPowerSeries fromPolynomial(GenPolynomial a) { if (a == null || a.isZERO()) { return ZERO; } if (a.isONE()) { return ONE; } GenPolynomialRing pfac = polyRing(); HashMap> cache = new HashMap>(); int mt = 0; for (Monomial m : a) { ExpVector e = m.exponent(); long t = e.totalDeg(); mt = Math.max(mt, (int) t); GenPolynomial p = cache.get(t); if (p == null) { p = pfac.getZERO().copy(); cache.put(t, p); } p.doPutToMap(e, m.coefficient()); } mt++; if (mt > truncate()) { setTruncate(mt); } BitSet check = new BitSet(); for (int i = 0; i <= truncate(); i++) { check.set(i); if (cache.get((long) i) == null) { GenPolynomial p = pfac.getZERO().copy(); cache.put((long) i, p); //System.out.println("p zero for deg i = " + i); } } return new MultiVarPowerSeries(this, new MultiVarCoefficients(pfac, cache, check) { @Override public C generate(ExpVector e) { // cached coefficients returned by get return coFac.getZERO(); } }); } /** * Get a list of MultiVarPowerSeries<C> from a list of * GenPolynomial<C>. * @param A list of GenPolynomial<C>. * @return a list of MultiVarPowerSeries<C>. */ public List> fromPolynomial(List> A) { return ListUtil., MultiVarPowerSeries> map(A, new UnaryFunctor, MultiVarPowerSeries>() { public MultiVarPowerSeries eval(GenPolynomial c) { return fromPolynomial(c); } }); } /** * Get a MultiVarPowerSeries<C> from a univariate power series. * @param ps UnivPowerSeries<C>. * @param r variable for the direction. * @return a MultiVarPowerSeries<C>. */ public MultiVarPowerSeries fromPowerSeries(final UnivPowerSeries ps, final int r) { if (ps == null) { return ZERO; } return new MultiVarPowerSeries(this, new MultiVarCoefficients(this) { @Override public C generate(ExpVector i) { if (i.isZERO()) { return ps.coefficient(0); } int[] dep = i.dependencyOnVariables(); if (dep.length != 1) { return coFac.getZERO(); } if (dep[0] != r) { return coFac.getZERO(); } int j = (int) i.getVal(r); if (j > 0) { return ps.coefficient(j); } return coFac.getZERO(); } }); } /** * Generate a random power series with k = 5, d = 0.7. * @return a random power series. */ public MultiVarPowerSeries random() { return random(5, 0.7f, random); } /** * Generate a random power series with d = 0.7. * @param k bit-size of random coefficients. * @return a random power series. */ public MultiVarPowerSeries random(int k) { return random(k, 0.7f, random); } /** * Generate a random power series with d = 0.7. * @param k bit-size of random coefficients. * @param rnd is a source for random bits. * @return a random power series. */ public MultiVarPowerSeries random(int k, Random rnd) { return random(k, 0.7f, rnd); } /** * Generate a random power series. * @param k bit-size of random coefficients. * @param d density of non-zero coefficients. * @return a random power series. */ public MultiVarPowerSeries random(int k, float d) { return random(k, d, random); } /** * Generate a random power series. * @param k bit-size of random coefficients. * @param d density of non-zero coefficients. * @param rnd is a source for random bits. * @return a random power series. */ public MultiVarPowerSeries random(final int k, final float d, final Random rnd) { return new MultiVarPowerSeries(this, new MultiVarCoefficients(this) { @Override public C generate(ExpVector i) { // cached coefficients returned by get C c; float f = rnd.nextFloat(); if (f < d) { c = coFac.random(k, rnd); } else { c = coFac.getZERO(); } return c; } }); } /** * Copy power series. * @param c a power series. * @return a copy of c. */ public MultiVarPowerSeries copy(MultiVarPowerSeries c) { return new MultiVarPowerSeries(this, c.lazyCoeffs); } /** * Parse a power series. Note: not implemented. * @param s String. * @return power series from s. */ public MultiVarPowerSeries parse(String s) { throw new UnsupportedOperationException("parse for power series not implemented"); } /** * Parse a power series. Note: not implemented. * @param r Reader. * @return next power series from r. */ public MultiVarPowerSeries parse(Reader r) { throw new UnsupportedOperationException("parse for power series not implemented"); } /** * Taylor power series. * @param f function. * @param a expansion point. * @return Taylor series of f. */ public MultiVarPowerSeries seriesOfTaylor(final TaylorFunction f, final List a) { return new MultiVarPowerSeries(this, new MultiVarCoefficients(this) { TaylorFunction der = f; // Map> pderCache = ... final List v = a; @Override public C generate(ExpVector i) { C c; int s = i.signum(); if (s == 0) { c = der.evaluate(v); return c; } TaylorFunction pder = der.deriviative(i); if (pder.isZERO()) { return coFac.getZERO(); } c = pder.evaluate(v); if (c.isZERO()) { return c; } long f = pder.getFacul(); c = c.divide(coFac.fromInteger(f)); return c; } }); } } jas-2.5/src/edu/jas/ps/ExamplesMulti.java0000644000175000017500000004673411456130214020555 0ustar giovannigiovanni/* * $Id: ExamplesMulti.java 3345 2010-10-15 19:50:36Z kredel $ */ package edu.jas.ps; import java.util.ArrayList; import java.util.List; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; /** * Examples for multivariate power series implementations. * @author Heinz Kredel */ public class ExamplesMulti { public static void main(String[] args) { BasicConfigurator.configure(); if ( args.length > 0 ) { example1(); example2(); example3(); example4(); example5(); example6(); example7(); example8(); example9(); example10(); } example11(); } public static void example1() { BigRational br = new BigRational(1); String[] vars = new String[] { "x", "y" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial a = pfac.parse("x^2 + x y"); GenPolynomial b = pfac.parse("y^2 + x y"); GenPolynomial c = pfac.parse("x^3 + x^2"); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.fromPolynomial(a); MultiVarPowerSeries bp = fac.fromPolynomial(b); MultiVarPowerSeries cp = fac.fromPolynomial(c); System.out.println("ap = " + ap); System.out.println("bp = " + bp); System.out.println("cp = " + cp); List> L = new ArrayList>(); L.add(ap); L.add(bp); ReductionSeq red = new ReductionSeq(); MultiVarPowerSeries dp = red.normalform(L, cp); System.out.println("dp = " + dp); } public static void example2() { BigRational br = new BigRational(1); String[] vars = new String[] { "x", "y" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial a = pfac.parse("x - x y"); GenPolynomial b = pfac.parse("y^2 + x^3"); GenPolynomial c = pfac.parse("x^2 + y^2"); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.fromPolynomial(a); MultiVarPowerSeries bp = fac.fromPolynomial(b); MultiVarPowerSeries cp = fac.fromPolynomial(c); System.out.println("ap = " + ap); System.out.println("bp = " + bp); System.out.println("cp = " + cp); List> L = new ArrayList>(); L.add(ap); L.add(bp); ReductionSeq red = new ReductionSeq(); MultiVarPowerSeries dp = red.normalform(L, cp); System.out.println("dp = " + dp); } public static void example3() { BigRational br = new BigRational(1); String[] vars = new String[] { "x", "y", "z" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial a = pfac.parse("x"); GenPolynomial b = pfac.parse("y"); GenPolynomial c = pfac.parse("x^2 + y^2 + z^3 + x^4 + y^5"); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.fromPolynomial(a); MultiVarPowerSeries bp = fac.fromPolynomial(b); MultiVarPowerSeries cp = fac.fromPolynomial(c); System.out.println("ap = " + ap); System.out.println("bp = " + bp); System.out.println("cp = " + cp); List> L = new ArrayList>(); L.add(ap); L.add(bp); ReductionSeq red = new ReductionSeq(); MultiVarPowerSeries dp = red.normalform(L, cp); System.out.println("dp = " + dp); } public static void example4() { BigRational br = new BigRational(1); String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial a = pfac.parse("x + x^3 + x^5"); GenPolynomial c = pfac.parse("x + x^2"); System.out.println("a = " + a); System.out.println("c = " + c); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); //fac.setTruncate(11); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.fromPolynomial(a); MultiVarPowerSeries cp = fac.fromPolynomial(c); System.out.println("ap = " + ap); System.out.println("cp = " + cp); List> L = new ArrayList>(); L.add(ap); ReductionSeq red = new ReductionSeq(); MultiVarPowerSeries dp = red.normalform(L, cp); System.out.println("dp = " + dp); } public static void example5() { BigRational br = new BigRational(1); String[] vars = new String[] { "x", "y" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial c = pfac.parse("x^2 + y^2 - 1"); System.out.println("c = " + c); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); //fac.setTruncate(19); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.getSIN(0); MultiVarPowerSeries bp = fac.getCOS(1); MultiVarPowerSeries ep = fac.getCOS(0); MultiVarPowerSeries cp = fac.fromPolynomial(c); System.out.println("ap = " + ap); System.out.println("bp = " + bp); System.out.println("ep = " + ep); System.out.println("cp = " + cp); System.out.println("ap^2 + ep^2 = " + ap.multiply(ap).sum(ep.multiply(ep))); List> L = new ArrayList>(); L.add(ap); L.add(bp); ReductionSeq red = new ReductionSeq(); MultiVarPowerSeries dp = red.normalform(L, cp); System.out.println("dp = " + dp); } public static void example6() { BigRational br = new BigRational(1); String[] vars = new String[] { "x", "y", "z" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial a = pfac.parse("x^5 - x y^6 + z^7"); GenPolynomial b = pfac.parse("x y + y^3 + z^3"); GenPolynomial c = pfac.parse("x^2 + y^2 - z^2"); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); //fac.setTruncate(11); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.fromPolynomial(a); MultiVarPowerSeries bp = fac.fromPolynomial(b); MultiVarPowerSeries cp = fac.fromPolynomial(c); System.out.println("ap = " + ap); System.out.println("bp = " + bp); System.out.println("cp = " + cp); List> L = new ArrayList>(); L.add(ap); L.add(bp); L.add(cp); StandardBaseSeq tm = new StandardBaseSeq(); List> S = tm.STD(L); for (MultiVarPowerSeries ps : S) { System.out.println("ps = " + ps); } System.out.println("\nS = " + S); boolean s = tm.isSTD(S); System.out.println("\nisSTD = " + s); ReductionSeq red = new ReductionSeq(); s = red.contains(S, L); System.out.println("S contains L = " + s); } public static void example7() { BigRational br = new BigRational(1); String[] vars = new String[] { "x", "y" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial a = pfac.parse("x^10 + x^9 y^2"); GenPolynomial b = pfac.parse("y^8 - x^2 y^7"); System.out.println("a = " + a); System.out.println("b = " + b); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); fac.setTruncate(12); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.fromPolynomial(a); MultiVarPowerSeries bp = fac.fromPolynomial(b); System.out.println("ap = " + ap); System.out.println("bp = " + bp); List> L = new ArrayList>(); L.add(ap); L.add(bp); StandardBaseSeq tm = new StandardBaseSeq(); List> S = tm.STD(L); for (MultiVarPowerSeries ps : S) { System.out.println("ps = " + ps); } System.out.println("\nS = " + S); boolean s = tm.isSTD(S); System.out.println("\nisSTD = " + s); ReductionSeq red = new ReductionSeq(); s = red.contains(S, L); System.out.println("\nS contains L = " + s); } public static void example8() { BigRational br = new BigRational(1); String[] vars = new String[] { "x", "y" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial c = pfac.parse("x^2 + y^2"); System.out.println("c = " + c); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); //fac.setTruncate(19); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.getSIN(0); MultiVarPowerSeries bp = fac.getTAN(0); MultiVarPowerSeries cp = fac.fromPolynomial(c); System.out.println("ap = " + ap); System.out.println("bp = " + bp); System.out.println("cp = " + cp); List> L = new ArrayList>(); L.add(ap); L.add(bp); //L.add(cp); System.out.println("\nL = " + L); StandardBaseSeq tm = new StandardBaseSeq(); List> S = tm.STD(L); for (MultiVarPowerSeries ps : S) { System.out.println("ps = " + ps); } System.out.println("\nS = " + S); boolean s = tm.isSTD(S); System.out.println("\nisSTD = " + s); ReductionSeq red = new ReductionSeq(); s = red.contains(S, L); System.out.println("S contains L = " + s); } public static void example9() { BigRational br = new BigRational(1); String[] vars = new String[] { "x", "y", "z" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial a = pfac.parse("x z - y z - y^2 z"); GenPolynomial b = pfac.parse("x z - y z + y^2 z"); GenPolynomial c = pfac.parse("z + y^2 z"); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); fac.setTruncate(11); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.fromPolynomial(a); MultiVarPowerSeries bp = fac.fromPolynomial(b); MultiVarPowerSeries cp = fac.fromPolynomial(c); System.out.println("ap = " + ap); System.out.println("bp = " + bp); System.out.println("cp = " + cp); List> L = new ArrayList>(); L.add(ap); L.add(bp); L.add(cp); StandardBaseSeq tm = new StandardBaseSeq(); List> S = tm.STD(L); for (MultiVarPowerSeries ps : S) { System.out.println("ps = " + ps); } System.out.println("\nS = " + S); boolean s = tm.isSTD(S); System.out.println("\nisSTD = " + s); ReductionSeq red = new ReductionSeq(); s = red.contains(S, L); System.out.println("S contains L = " + s); } public static void example10() { BigRational br = new BigRational(1); String[] vars = new String[] { "x", "y", "z" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial a = pfac.parse("x^2 z^2 - y^6"); GenPolynomial b = pfac.parse("x y z^2 + y^4 z - x^5 z - x^4 y^3"); GenPolynomial c = pfac.parse("x z - y^3 + x^2 z - x y^3"); GenPolynomial d = pfac.parse("y z + x y z - x^4 - x^5"); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d = " + d); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); fac.setTruncate(9); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.fromPolynomial(a); MultiVarPowerSeries bp = fac.fromPolynomial(b); MultiVarPowerSeries cp = fac.fromPolynomial(c); MultiVarPowerSeries dp = fac.fromPolynomial(d); System.out.println("ap = " + ap); System.out.println("bp = " + bp); System.out.println("cp = " + cp); System.out.println("dp = " + dp); List> L = new ArrayList>(); L.add(ap); L.add(bp); L.add(cp); L.add(dp); StandardBaseSeq tm = new StandardBaseSeq(); List> S = tm.STD(L); for (MultiVarPowerSeries ps : S) { System.out.println("ps = " + ps); } System.out.println("\nS = " + S); boolean s = tm.isSTD(S); System.out.println("\nisSTD = " + s); ReductionSeq red = new ReductionSeq(); s = red.contains(S, L); System.out.println("S contains L = " + s); List> R = red.totalNormalform(S); System.out.println("R = " + R); s = red.contains(R, L); System.out.println("R contains L = " + s); s = red.contains(R, S); System.out.println("R contains S = " + s); } public static void example11() { BigRational br = new BigRational(1); String[] vars = new String[] { "x", "y", "z" }; GenPolynomialRing pfac = new GenPolynomialRing(br, vars); System.out.println("pfac = " + pfac.toScript()); GenPolynomial a = pfac.parse("x^5 - x y^6 - z^7"); GenPolynomial b = pfac.parse("x y + y^3 + z^3"); GenPolynomial c = pfac.parse("x^2 + y^2 - z^2"); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); MultiVarPowerSeriesRing fac = new MultiVarPowerSeriesRing(pfac); //fac.setTruncate(9); System.out.println("fac = " + fac.toScript()); MultiVarPowerSeries ap = fac.fromPolynomial(a); MultiVarPowerSeries bp = fac.fromPolynomial(b); MultiVarPowerSeries cp = fac.fromPolynomial(c); System.out.println("ap = " + ap); System.out.println("bp = " + bp); System.out.println("cp = " + cp); List> L = new ArrayList>(); L.add(ap); L.add(bp); L.add(cp); StandardBaseSeq tm = new StandardBaseSeq(); List> S = tm.STD(L); for (MultiVarPowerSeries ps : S) { System.out.println("ps = " + ps); } System.out.println("\nS = " + S); boolean s = tm.isSTD(S); System.out.println("\nisSTD = " + s); ReductionSeq red = new ReductionSeq(); s = red.contains(S, L); System.out.println("S contains L = " + s); List> R = red.totalNormalform(S); for (MultiVarPowerSeries ps : R) { System.out.println("ps = " + ps); } System.out.println("\nR = " + R); s = tm.isSTD(R); System.out.println("\nisSTD = " + s); s = red.contains(R, L); System.out.println("R contains L = " + s); s = red.contains(R, S); System.out.println("R contains S = " + s); s = red.contains(S,R); System.out.println("S contains R = " + s); s = red.contains(S,L); System.out.println("S contains L = " + s); List> Rs = tm.STD(R); for (MultiVarPowerSeries ps : Rs) { System.out.println("ps = " + ps); } System.out.println("\nRs = " + Rs); s = tm.isSTD(Rs); System.out.println("\nisSTD = " + s); s = red.contains(Rs, R); System.out.println("Rs contains R = " + s); s = red.contains(Rs, S); System.out.println("Rs contains S = " + s); } } jas-2.5/src/edu/jas/ps/Coefficients.java0000644000175000017500000000304312004021316020337 0ustar giovannigiovanni/* * $Id: Coefficients.java 4043 2012-07-25 16:46:06Z kredel $ */ package edu.jas.ps; import java.io.Serializable; import java.util.HashMap; import edu.jas.structure.RingElem; /** * Abstract class for generating functions for coefficients of power series. Was * an interface, now this class handles the caching itself. * @param ring element type * @author Heinz Kredel */ public abstract class Coefficients> implements Serializable { /** * Cache for already computed coefficients. */ public final HashMap coeffCache; /** * Public no arguments constructor. */ public Coefficients() { this(new HashMap()); } /** * Public constructor with pre-filled cache. * @param cache pre-filled coefficient cache. */ public Coefficients(HashMap cache) { coeffCache = cache; } /** * Get cached coefficient or generate coefficient. * @param index of requested coefficient. * @return coefficient at index. */ public C get(int index) { if (coeffCache == null) { return generate(index); } Integer i = index; C c = coeffCache.get(i); if (c != null) { return c; } c = generate(index); coeffCache.put(i, c); return c; } /** * Generate coefficient. * @param index of requested coefficient. * @return coefficient at index. */ protected abstract C generate(int index); } jas-2.5/src/edu/jas/ps/MultiVarCoefficients.java0000644000175000017500000001475512014234362022047 0ustar giovannigiovanni/* * $Id: MultiVarCoefficients.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.ps; import java.io.Serializable; import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.RingElem; /** * Abstract class for generating functions for coefficients of multivariate * power series. This class handles the caching itself. * @param ring element type * @author Heinz Kredel */ public abstract class MultiVarCoefficients> implements Serializable { /** * Ring factory for polynomials. */ public final GenPolynomialRing pfac; /** * Cache for already computed coefficients. */ public final HashMap> coeffCache; /** * Indicator if all coefficients of a homogeneous degree have been * constructed. */ public final BitSet homCheck; /** * Cache for known zero coefficients. Required because zero coefficients are * not stored in the polynomials. */ public final HashSet zeroCache; /** * Public constructor. * @param pf multivariate power series ring factory. */ public MultiVarCoefficients(MultiVarPowerSeriesRing pf) { this(pf.polyRing(), new HashMap>(), new HashSet()); } /** * Public constructor with some pre-filled caches. * @param pf multivariate power series ring factory. * @param hc pre-filled homogeneous check bit-set. */ public MultiVarCoefficients(MultiVarPowerSeriesRing pf, BitSet hc) { this(pf.polyRing(), new HashMap>(), new HashSet(), hc); } /** * Public constructor. * @param pf polynomial ring factory. */ public MultiVarCoefficients(GenPolynomialRing pf) { this(pf, new HashMap>(), new HashSet()); } /** * Public with pre-filled coefficient cache. * @param pf polynomial ring factory. * @param cache pre-filled coefficient cache. */ public MultiVarCoefficients(GenPolynomialRing pf, HashMap> cache) { this(pf, cache, new HashSet()); } /** * Public constructor with pre-filled caches. * @param pf polynomial ring factory. * @param cache pre-filled coefficient cache. * @param zeros pre-filled zero coefficient cache. */ public MultiVarCoefficients(GenPolynomialRing pf, HashMap> cache, HashSet zeros) { this(pf, cache, zeros, new BitSet()); } /** * Public constructor with pre-filled caches. * @param pf polynomial ring factory. * @param hc pre-filled homogeneous check bit-set. */ public MultiVarCoefficients(GenPolynomialRing pf, BitSet hc) { this(pf, new HashMap>(), new HashSet(), hc); } /** * Public constructor with pre-filled caches. * @param pf polynomial ring factory. * @param cache pre-filled coefficient cache. * @param hc pre-filled homogeneous check bit-set. */ public MultiVarCoefficients(GenPolynomialRing pf, HashMap> cache, BitSet hc) { this(pf, cache, new HashSet(), hc); } /** * Public constructor with pre-filled caches. * @param pf polynomial ring factory. * @param cache pre-filled coefficient cache. * @param zeros pre-filled zero coefficient cache. * @param hc pre-filled homogeneous check bit-set. */ public MultiVarCoefficients(GenPolynomialRing pf, HashMap> cache, HashSet zeros, BitSet hc) { pfac = pf; coeffCache = cache; zeroCache = zeros; homCheck = hc; } /** * Get cached coefficient or generate coefficient. * @param index of requested coefficient. * @return coefficient at index. */ public C get(ExpVector index) { //if (index.signum() < 0) { // better assert // throw new IllegalArgumentException("negative signum not allowed " + index); //} //if (coeffCache == null) { // not possible // return generate(index); //} long tdeg = index.totalDeg(); GenPolynomial p = coeffCache.get(tdeg); if (p == null) { p = pfac.getZERO().copy(); coeffCache.put(tdeg, p); } C c = p.coefficient(index); if (!c.isZERO()) { return c; } if (homCheck.get((int) tdeg)) { // rely on p return c; } if (zeroCache.contains(index)) { return c; } C g = generate(index); if (g.isZERO()) { zeroCache.add(index); } else { p.doPutToMap(index, g); } return g; } /** * Homogeneous part. * @param tdeg requested degree. * @return polynomial part of given degree. */ public GenPolynomial getHomPart(long tdeg) { if (coeffCache == null) { throw new IllegalArgumentException("null cache not allowed"); } GenPolynomial p = coeffCache.get(tdeg); if (p == null) { p = pfac.getZERO().copy(); coeffCache.put(tdeg, p); } // trust contents? if (homCheck.get((int) tdeg)) { return p; } // check correct contents or generate coefficients ExpVectorIterable eiter = new ExpVectorIterable(pfac.nvar, tdeg); for (ExpVector e : eiter) { if (zeroCache.contains(e)) { if ( !zeroCache.remove(e) ) { // clean-up unused System.out.println("not removed e = " + e); // cannot happen } continue; } if (!p.coefficient(e).isZERO()) { continue; } C g = generate(e); if (!g.isZERO()) { p.doPutToMap(e, g); } } homCheck.set((int) tdeg); //System.out.println("homCheck = " + homCheck); //System.out.println("coeffCache = " + coeffCache.keySet()); return p; } /** * Generate coefficient. * @param index of requested coefficient. * @return coefficient at index. */ protected abstract C generate(ExpVector index); } jas-2.5/src/edu/jas/ps/OrderedPairlist.java0000644000175000017500000002044512011712554021050 0ustar giovannigiovanni/* * $Id: OrderedPairlist.java 4095 2012-08-12 11:37:17Z kredel $ */ package edu.jas.ps; import java.util.ArrayList; import java.util.BitSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.structure.RingElem; /** * Pair list management. Implemented using MultiVarPowerSeries, TreeMap and * BitSet. * @author Heinz Kredel */ public class OrderedPairlist> { protected final ArrayList> P; protected final TreeMap>> pairlist; protected final ArrayList red; protected final MultiVarPowerSeriesRing ring; protected final ReductionSeq reduction; protected boolean oneInGB = false; protected boolean useCriterion4 = true; protected boolean useCriterion3 = true; protected int putCount; protected int remCount; protected final int moduleVars; private static final Logger logger = Logger.getLogger(OrderedPairlist.class); /** * Constructor for OrderedPairlist. * @param r power series factory. */ public OrderedPairlist(MultiVarPowerSeriesRing r) { this(0, r); } /** * Constructor for OrderedPairlist. * @param m number of module variables. * @param r power series factory. */ public OrderedPairlist(int m, MultiVarPowerSeriesRing r) { moduleVars = m; ring = r; P = new ArrayList>(); pairlist = new TreeMap>>(ring.polyRing().tord.getAscendComparator()); //pairlist = new TreeMap>>(ring.polyRing().tord.getDescendComparator()); red = new ArrayList(); putCount = 0; remCount = 0; reduction = new ReductionSeq(); } /** * toString. */ @Override public String toString() { StringBuffer s = new StringBuffer("OrderedPairlist("); //s.append("ps="+P.size()); s.append("#put=" + putCount); s.append(", #rem=" + remCount); if (pairlist.size() != 0) { s.append(", size=" + pairlist.size()); } s.append(")"); return s.toString(); } /** * Put one power Series to the pairlist and reduction matrix. * @param p power series. * @return the index of the added power series. */ public synchronized int put(MultiVarPowerSeries p) { putCount++; if (oneInGB) { return P.size() - 1; } ExpVector e = p.orderExpVector(); int l = P.size(); for (int j = 0; j < l; j++) { MultiVarPowerSeries pj = P.get(j); ExpVector f = pj.orderExpVector(); if (moduleVars > 0) { if (!reduction.moduleCriterion(moduleVars, e, f)) { continue; // skip pair } } ExpVector g = e.lcm(f); Pair pair = new Pair(pj, p, j, l); // redi = (BitSet)red.get(j); ///if ( j < l ) redi.set( l ); // System.out.println("bitset."+j+" = " + redi ); //multiple pairs under same keys -> list of pairs LinkedList> xl = pairlist.get(g); if (xl == null) { xl = new LinkedList>(); } //xl.addLast( pair ); // first or last ? xl.addFirst(pair); // first or last ? better for d- e-GBs pairlist.put(g, xl); } // System.out.println("pairlist.keys@put = " + pairlist.keySet() ); P.add(p); BitSet redi = new BitSet(); redi.set(0, l); // jdk 1.4 red.add(redi); return P.size() - 1; } /** * Remove the next required pair from the pairlist and reduction matrix. * Apply the criterions 3 and 4 to see if the S-power-series is required. * @return the next pair if one exists, otherwise null. */ public synchronized Pair removeNext() { if (oneInGB) { return null; } Iterator>>> ip = pairlist.entrySet().iterator(); Pair pair = null; boolean c = false; int i, j; while (!c && ip.hasNext()) { Map.Entry>> me = ip.next(); ExpVector g = me.getKey(); LinkedList> xl = me.getValue(); if (logger.isInfoEnabled()) logger.info("g = " + g); pair = null; while (!c && xl.size() > 0) { pair = xl.removeFirst(); // xl is also modified in pairlist i = pair.i; j = pair.j; // System.out.println("pair(" + j + "," +i+") "); c = true; if (useCriterion4) { c = reduction.criterion4(pair.pi, pair.pj, g); } //System.out.println("c4 = " + c); if (c && useCriterion3) { c = criterion3(i, j, g); //System.out.println("c3 = " + c); } red.get(j).clear(i); // set(i,false) jdk1.4 } if (xl.size() == 0) ip.remove(); // = pairlist.remove( g ); } if (!c) { pair = null; } else { remCount++; // count only real pairs } return pair; } /** * Test if there is possibly a pair in the list. * @return true if a next pair could exist, otherwise false. */ public synchronized boolean hasNext() { return pairlist.size() > 0; } /** * Get the list of power series. * @return the power series list. */ public List> getList() { return P; } /** * Get the number of power series put to the pairlist. * @return the number of calls to put. */ public synchronized int putCount() { return putCount; } /** * Get the number of required pairs removed from the pairlist. * @return the number of non null pairs delivered. */ public synchronized int remCount() { return remCount; } /** * Put to ONE-power-series to the pairlist. * @param one power series. (no more required) * @return the index of the last power series. */ public synchronized int putOne(MultiVarPowerSeries one) { putCount++; if (one == null) { return P.size() - 1; } if (!one.isONE()) { return P.size() - 1; } return putOne(); } /** * Put the ONE-power-series to the pairlist. * @return the index of the last power-series. */ public synchronized int putOne() { oneInGB = true; pairlist.clear(); P.clear(); P.add(ring.getONE()); red.clear(); return P.size() - 1; } /** * GB criterion 3. * @return true if the S-power-series(i,j) is required. */ public boolean criterion3(int i, int j, ExpVector eij) { // assert i < j; boolean s = red.get(j).get(i); if (!s) { logger.warn("c3.s false for " + j + " " + i); return s; } // now s = true; for (int k = 0; k < P.size(); k++) { MultiVarPowerSeries A = P.get(k); ExpVector ek = A.orderExpVector(); boolean m = eij.multipleOf(ek); if (m) { if (k < i) { // System.out.println("k < i "+k+" "+i); s = red.get(i).get(k) || red.get(j).get(k); } else if (i < k && k < j) { // System.out.println("i < k < j "+i+" "+k+" "+j); s = red.get(k).get(i) || red.get(j).get(k); } else if (j < k) { //System.out.println("j < k "+j+" "+k); s = red.get(k).get(i) || red.get(k).get(j); } //System.out.println("s."+k+" = " + s); if (!s) { return s; } } } return true; } } jas-2.5/src/edu/jas/ps/UnivPowerSeriesMap.java0000644000175000017500000000077711440760332021533 0ustar giovannigiovanni/* * $Id: UnivPowerSeriesMap.java 3315 2010-09-05 18:26:34Z kredel $ */ package edu.jas.ps; import edu.jas.structure.RingElem; /** * Univariate power series map interface. Defines method for mapping of power * series. * @param ring element type * @author Heinz Kredel */ public interface UnivPowerSeriesMap> { /** * Map. * @return new power series resulting from mapping elements of ps. */ public UnivPowerSeries map(UnivPowerSeries ps); } jas-2.5/src/edu/jas/ps/MultiVarPowerSeries.java0000644000175000017500000012107312014234362021705 0ustar giovannigiovanni/* * $Id: MultiVarPowerSeries.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.ps; import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.BinaryFunctor; import edu.jas.structure.RingElem; import edu.jas.structure.Selector; import edu.jas.structure.UnaryFunctor; import edu.jas.util.MapEntry; /** * Multivariate power series implementation. Uses inner classes and lazy * evaluated generating function for coefficients. All ring element methods use * lazy evaluation except where noted otherwise. Eager evaluated methods are * toString(), compareTo(), equals(), * evaluate(), or methods which use the order() or * orderExpVector() methods, like signum(), * abs(), divide(), remainder() and * gcd(). Note: Currently the term order is fixed to the * order defined by the iterator over exponent vectors in class * ExpVectorIterator. * @param ring element type * @author Heinz Kredel */ public class MultiVarPowerSeries> implements RingElem> { /** * Power series ring factory. */ public final MultiVarPowerSeriesRing ring; /** * Data structure / generating function for coeffcients. Cannot be final * because of fixPoint, must be accessible in factory. */ /*package*/MultiVarCoefficients lazyCoeffs; /** * Truncation of computations. */ private int truncate; /** * Order of power series. */ private int order = -1; // == unknown /** * ExpVector of order of power series. */ private ExpVector evorder = null; // == unknown /** * Private constructor. */ @SuppressWarnings("unused") private MultiVarPowerSeries() { throw new IllegalArgumentException("do not use no-argument constructor"); } /** * Package constructor. Use in fixPoint only, must be accessible in factory. * @param ring power series ring. */ /*package*/MultiVarPowerSeries(MultiVarPowerSeriesRing ring) { this.ring = ring; this.lazyCoeffs = null; this.truncate = ring.truncate; } /** * Constructor. * @param ring power series ring. * @param lazyCoeffs generating function for coefficients. */ public MultiVarPowerSeries(MultiVarPowerSeriesRing ring, MultiVarCoefficients lazyCoeffs) { this(ring, lazyCoeffs, ring.truncate); } /** * Constructor. * @param ring power series ring. * @param lazyCoeffs generating function for coefficients. * @param trunc truncate parameter for this power series. */ public MultiVarPowerSeries(MultiVarPowerSeriesRing ring, MultiVarCoefficients lazyCoeffs, int trunc) { if (lazyCoeffs == null || ring == null) { throw new IllegalArgumentException("null not allowed: ring = " + ring + ", lazyCoeffs = " + lazyCoeffs); } this.ring = ring; this.lazyCoeffs = lazyCoeffs; this.truncate = Math.min(trunc, ring.truncate); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public MultiVarPowerSeriesRing factory() { return ring; } /** * Clone this power series. * @see java.lang.Object#clone() */ @Override public MultiVarPowerSeries copy() { return new MultiVarPowerSeries(ring, lazyCoeffs); } /** * String representation of power series. * @see java.lang.Object#toString() */ @Override public String toString() { return toString(truncate); } /** * To String with given truncate. * @param trunc truncate parameter for this power series. * @return string representation of this to given truncate. */ public String toString(int trunc) { StringBuffer sb = new StringBuffer(); MultiVarPowerSeries s = this; String[] vars = ring.vars; //System.out.println("cache1 = " + s.lazyCoeffs.coeffCache); for (ExpVector i : new ExpVectorIterable(ring.nvar, true, trunc)) { C c = s.coefficient(i); //System.out.println("i = " + i + ", c = " +c); int si = c.signum(); if (si != 0) { if (si > 0) { if (sb.length() > 0) { sb.append(" + "); } } else { c = c.negate(); sb.append(" - "); } if (!c.isONE() || i.isZERO()) { if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) { sb.append("{ "); } sb.append(c.toString()); if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) { sb.append(" }"); } if (!i.isZERO()) { sb.append(" * "); } } if (i.isZERO()) { //skip; sb.append(" "); } else { sb.append(i.toString(vars)); } //sb.append(c.toString() + ", "); } //System.out.println("cache = " + s.coeffCache); } if (sb.length() == 0) { sb.append("0"); } sb.append(" + BigO( (" + ring.varsToString() + ")^" + (trunc + 1) + "(" + (ring.truncate + 1) + ") )"); //sb.append("..."); //System.out.println("cache2 = " + s.lazyCoeffs.coeffCache); return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer sb = new StringBuffer(""); MultiVarPowerSeries s = this; String[] vars = ring.vars; //System.out.println("cache = " + s.coeffCache); for (ExpVector i : new ExpVectorIterable(ring.nvar, true, truncate)) { C c = s.coefficient(i); int si = c.signum(); if (si != 0) { if (si > 0) { if (sb.length() > 0) { sb.append(" + "); } } else { c = c.negate(); sb.append(" - "); } if (!c.isONE() || i.isZERO()) { if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) { sb.append("( "); } sb.append(c.toScript()); if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) { sb.append(" )"); } if (!i.isZERO()) { sb.append(" * "); } } if (i.isZERO()) { //skip; sb.append(" "); } else { sb.append(i.toScript(vars)); } //sb.append(c.toString() + ", "); } //System.out.println("cache = " + s.coeffCache); } if (sb.length() == 0) { sb.append("0"); } sb.append(" + BigO( (" + ring.varsToString() + ")**" + (truncate + 1) + " )"); // sb.append("," + truncate + ""); return sb.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Get coefficient. * @param index number of requested coefficient. * @return coefficient at index. */ public C coefficient(ExpVector index) { if (index == null) { throw new IndexOutOfBoundsException("null index not allowed"); } return lazyCoeffs.get(index); } /** * Homogeneous part. * @param tdeg requested degree. * @return polynomial part of given degree. */ public GenPolynomial homogeneousPart(long tdeg) { return lazyCoeffs.getHomPart(tdeg); } /** * Get a GenPolynomial<C> from this. * @return a GenPolynomial<C> from this up to truncate homogeneous * parts. */ public GenPolynomial asPolynomial() { GenPolynomial p = homogeneousPart(0L); for (int i = 1; i <= truncate; i++) { p = p.sum(homogeneousPart(i)); } return p; } /** * Leading base coefficient. * @return first coefficient. */ public C leadingCoefficient() { return coefficient(ring.EVZERO); } /** * Reductum. * @param r variable for taking the reductum. * @return this - leading monomial in the direction of r. */ public MultiVarPowerSeries reductum(final int r) { if (r < 0 || ring.nvar < r) { throw new IllegalArgumentException("variable index out of bound"); } return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector i) { ExpVector e = i.subst(r, i.getVal(r) + 1); return coefficient(e); } }); } /** * Prepend a new leading coefficient. * @param r variable for the direction. * @param h new coefficient. * @return new power series. */ public MultiVarPowerSeries prepend(final C h, final int r) { if (r < 0 || ring.nvar < r) { throw new IllegalArgumentException("variable index out of bound"); } return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector i) { if (i.isZERO()) { return h; } ExpVector e = i.subst(r, i.getVal(r) - 1); if (e.signum() < 0) { return pfac.coFac.getZERO(); } return coefficient(e); } }); } /** * Shift coefficients. * @param k shift index. * @param r variable for the direction. * @return new power series with coefficient(i) = old.coefficient(i-k). */ public MultiVarPowerSeries shift(final int k, final int r) { if (r < 0 || ring.nvar < r) { throw new IllegalArgumentException("variable index out of bound"); } int nt = Math.min(truncate + k, ring.truncate); return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector i) { long d = i.getVal(r); if (d - k < 0) { return ring.coFac.getZERO(); } ExpVector e = i.subst(r, i.getVal(r) - k); return coefficient(e); } }, nt); } /** * Reductum. * @return this - leading monomial. */ public MultiVarPowerSeries reductum() { Map.Entry m = orderMonomial(); ExpVector e = m.getKey(); long d = e.totalDeg(); MultiVarCoefficients mc = lazyCoeffs; HashMap> cc = new HashMap>(mc.coeffCache); GenPolynomial p = cc.get(d); if (p != null && !p.isZERO()) { p = p.subtract(m.getValue(), e); // p contains this term after orderMonomial() cc.put(d, p); } HashSet z = new HashSet(mc.zeroCache); if (!mc.homCheck.get((int) d)) { z.add(e); //System.out.println("e = " + e); } return new MultiVarPowerSeries(ring, new MultiVarCoefficients(mc.pfac, cc, z, mc.homCheck) { @Override public C generate(ExpVector i) { return coefficient(i); } }); } /** * Shift coefficients. Multiply by exponent vector. * @param k shift ExpVector. * @return new power series with coefficient(i) = old.coefficient(i-k). */ public MultiVarPowerSeries shift(final ExpVector k) { if (k == null) { throw new IllegalArgumentException("null ExpVector not allowed"); } if (k.signum() == 0) { return this; } int nt = Math.min(truncate + (int) k.totalDeg(), ring.truncate); return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector i) { ExpVector d = i.subtract(k); if (d.signum() < 0) { return ring.coFac.getZERO(); } return coefficient(d); } }, nt); } /** * Multiply by exponent vector and coefficient. * @param k shift ExpVector. * @param c coefficient multiplier. * @return new power series with coefficient(i) = old.coefficient(i-k)*c. */ public MultiVarPowerSeries multiply(final C c, final ExpVector k) { if (k == null) { throw new IllegalArgumentException("null ExpVector not allowed"); } if (k.signum() == 0) { return this.multiply(c); } if (c.signum() == 0) { return ring.getZERO(); } int nt = Math.min(ring.truncate, truncate + (int) k.totalDeg()); return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector i) { ExpVector d = i.subtract(k); if (d.signum() < 0) { return ring.coFac.getZERO(); } long tdegd = d.totalDeg(); if (lazyCoeffs.homCheck.get((int) tdegd)) { GenPolynomial p = homogeneousPart(tdegd).multiply(c, k); long tdegi = i.totalDeg(); coeffCache.put(tdegi, p); // overwrite homCheck.set((int) tdegi); C b = p.coefficient(i); //System.out.println("b = " + b + ", i = " + i + ", tdegi = " + tdegi+ ", tdegd = " + tdegd); //System.out.println("p = " + p + ", i = " + i); return b; } return coefficient(d).multiply(c); } }, nt); } /** * Sum monomial. * @param m ExpVector , coeffcient pair * @return this + ONE.multiply(m.coefficient,m.exponent). */ public MultiVarPowerSeries sum(Map.Entry m) { if (m == null) { throw new IllegalArgumentException("null Map.Entry not allowed"); } return sum(m.getValue(), m.getKey()); } /** * Sum exponent vector and coefficient. * @param k ExpVector. * @param c coefficient. * @return this + ONE.multiply(c,k). */ public MultiVarPowerSeries sum(final C c, final ExpVector k) { if (k == null) { throw new IllegalArgumentException("null ExpVector not allowed"); } if (c.signum() == 0) { return this; } long d = k.totalDeg(); MultiVarCoefficients mc = lazyCoeffs; HashMap> cc = new HashMap>(mc.coeffCache); GenPolynomial p = cc.get(d); if (p == null) { p = mc.pfac.getZERO(); } p = p.sum(c, k); //System.out.println("p = " + p); cc.put(d, p); HashSet z = new HashSet(mc.zeroCache); //System.out.println("z = " + z); if (p.coefficient(k).isZERO() && !mc.homCheck.get((int) d)) { z.add(k); } return new MultiVarPowerSeries(ring, new MultiVarCoefficients(mc.pfac, cc, z, mc.homCheck) { @Override public C generate(ExpVector i) { return coefficient(i); } }); } /** * Subtract exponent vector and coefficient. * @param k ExpVector. * @param c coefficient. * @return this - ONE.multiply(c,k). */ public MultiVarPowerSeries subtract(final C c, final ExpVector k) { if (k == null) { throw new IllegalArgumentException("null ExpVector not allowed"); } if (c.signum() == 0) { return this; } long d = k.totalDeg(); MultiVarCoefficients mc = lazyCoeffs; HashMap> cc = new HashMap>(mc.coeffCache); GenPolynomial p = cc.get(d); if (p == null) { p = mc.pfac.getZERO(); } p = p.subtract(c, k); cc.put(d, p); HashSet z = new HashSet(mc.zeroCache); //System.out.println("z = " + z); if (p.coefficient(k).isZERO() && !mc.homCheck.get((int) d)) { z.add(k); } return new MultiVarPowerSeries(ring, new MultiVarCoefficients(mc.pfac, cc, z, mc.homCheck) { @Override public C generate(ExpVector i) { return coefficient(i); } }); } /** * Sum exponent vector and coefficient. * @param mvc cached coefficients. * @return this + mvc. */ public MultiVarPowerSeries sum(MultiVarCoefficients mvc) { MultiVarCoefficients mc = lazyCoeffs; TreeMap> cc = new TreeMap>(mc.coeffCache); TreeMap> ccv = new TreeMap>(mvc.coeffCache); long d1 = (cc.size() > 0 ? cc.lastKey() : 0); long d2 = (ccv.size() > 0 ? ccv.lastKey() : 0); HashSet z = new HashSet(mc.zeroCache); z.addAll(mvc.zeroCache); long d = Math.max(d1, d2); BitSet hc = new BitSet((int) d); for (long i = 0; i <= d; i++) { GenPolynomial p1 = cc.get(i); GenPolynomial p2 = mvc.coeffCache.get(i); if (p1 == null) { p1 = mc.pfac.getZERO(); } if (p2 == null) { p2 = mc.pfac.getZERO(); } GenPolynomial p = p1.sum(p2); //System.out.println("p = " + p); cc.put(i, p); if (mc.homCheck.get((int) i) && mvc.homCheck.get((int) i)) { hc.set((int) i); } else { Set ev = new HashSet(p1.getMap().keySet()); ev.addAll(p2.getMap().keySet()); ev.removeAll(p.getMap().keySet()); z.addAll(ev); } } //System.out.println("cc = " + cc); return new MultiVarPowerSeries(ring, new MultiVarCoefficients(mc.pfac, new HashMap>(cc), z, hc) { @Override public C generate(ExpVector i) { return coefficient(i); } }); } /** * Select coefficients. * @param sel selector functor. * @return new power series with selected coefficients. */ public MultiVarPowerSeries select(final Selector sel) { return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector i) { C c = coefficient(i); if (sel.select(c)) { return c; } return ring.coFac.getZERO(); } }); } /** * Shift select coefficients. Not selected coefficients are removed from the * result series. * @param sel selector functor. * @return new power series with shifted selected coefficients. */ public MultiVarPowerSeries shiftSelect(final Selector sel) { return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { ExpVectorIterable ib = new ExpVectorIterable(ring.nvar, true, truncate); Iterator pos = ib.iterator(); @Override public C generate(ExpVector i) { C c; if (i.signum() > 0) { int[] deps = i.dependencyOnVariables(); ExpVector x = i.subst(deps[0], i.getVal(deps[0]) - 1L); c = get(x); } do { c = null; if (pos.hasNext()) { ExpVector e = pos.next(); c = coefficient(e); } else { break; } } while (!sel.select(c)); if (c == null) { // not correct because not known c = ring.coFac.getZERO(); } return c; } }); } /** * Map a unary function to this power series. * @param f evaluation functor. * @return new power series with coefficients f(this(i)). */ public MultiVarPowerSeries map(final UnaryFunctor f) { return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector i) { return f.eval(coefficient(i)); } }); } /** * Map a binary function to this and another power series. * @param f evaluation functor with coefficients f(this(i),other(i)). * @param ps other power series. * @return new power series. */ public MultiVarPowerSeries zip(final BinaryFunctor f, final MultiVarPowerSeries ps) { int m = Math.min(ring.truncate, Math.max(truncate, ps.truncate())); return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector i) { return f.eval(coefficient(i), ps.coefficient(i)); } }, m); } /** * Sum of two power series, using zip(). * @param ps other power series. * @return this + ps. */ public MultiVarPowerSeries sumZip(MultiVarPowerSeries ps) { return zip(new BinaryFunctor() { //JAVA6only: @Override public C eval(C c1, C c2) { return c1.sum(c2); } }, ps); } /** * Subtraction of two power series, using zip(). * @param ps other power series. * @return this - ps. */ public MultiVarPowerSeries subtractZip(MultiVarPowerSeries ps) { return zip(new BinaryFunctor() { //JAVA6only: @Override public C eval(C c1, C c2) { return c1.subtract(c2); } }, ps); } /** * Multiply by coefficient. * @param a coefficient. * @return this * a. */ public MultiVarPowerSeries multiply(final C a) { if (a.isZERO()) { return ring.getZERO(); } if (a.isONE()) { return this; } return map(new UnaryFunctor() { //JAVA6only: @Override public C eval(C c) { return c.multiply(a); } }); } /** * Monic. * @return 1/orderCoeff() * this. */ public MultiVarPowerSeries monic() { ExpVector e = orderExpVector(); if (e == null) { return this; } C a = coefficient(e); if (a.isONE()) { return this; } if (a.isZERO()) { // sic return this; } final C b = a.inverse(); return map(new UnaryFunctor() { //JAVA6only: @Override public C eval(C c) { return b.multiply(c); } }); } /** * Negate. * @return - this. */ public MultiVarPowerSeries negate() { return map(new UnaryFunctor() { //JAVA6only: @Override public C eval(C c) { return c.negate(); } }); } /** * Absolute value. * @return abs(this). */ public MultiVarPowerSeries abs() { if (signum() < 0) { return negate(); } return this; } /** * Evaluate at given point. * @return ps(a). */ public C evaluate(List a) { C v = ring.coFac.getZERO(); for (ExpVector i : new ExpVectorIterable(ring.nvar, true, truncate)) { C c = coefficient(i); if (c.isZERO()) { continue; } c = c.multiply(i.evaluate(ring.coFac, a)); v = v.sum(c); } return v; } /** * Order. * @return index of first non zero coefficient. */ public int order() { if (order >= 0) { return order; } // must compute it GenPolynomial p = null; int t = 0; while (lazyCoeffs.homCheck.get(t)) { p = lazyCoeffs.coeffCache.get(t); if (p == null || p.isZERO()) { // ?? t++; continue; } order = t; evorder = p.trailingExpVector(); //System.out.println("order = " + t); return order; } for (ExpVector i : new ExpVectorIterable(ring.nvar, true, truncate)) { if (!coefficient(i).isZERO()) { order = (int) i.totalDeg(); //ord; evorder = i; //System.out.println("order = " + order + ", evorder = " + evorder); return order; } } order = truncate + 1; // evorder is null return order; } /** * Order ExpVector. * @return ExpVector of first non zero coefficient. */ @SuppressWarnings("unused") public ExpVector orderExpVector() { int x = order(); // ensure evorder is set return evorder; } /** * Order monomial. * @return first map entry or null. */ public Map.Entry orderMonomial() { ExpVector e = orderExpVector(); if (e == null) { return null; } //JAVA6only: //return new AbstractMap.SimpleImmutableEntry(e, coefficient(e)); return new MapEntry(e, coefficient(e)); } /** * Truncate. * @return truncate index of power series. */ public int truncate() { return truncate; } /** * Set truncate. * @param t new truncate index. * @return old truncate index of power series. */ public int setTruncate(int t) { if (t < 0) { throw new IllegalArgumentException("negative truncate not allowed"); } int ot = truncate; if (order >= 0) { if (order > truncate) { order = -1; // reset evorder = null; } } truncate = t; return ot; } /** * Ecart. * @return ecart. */ public long ecart() { ExpVector e = orderExpVector(); if (e == null) { return 0L; } long d = e.totalDeg(); long hd = d; for (long i = d + 1L; i <= truncate; i++) { if (!homogeneousPart(i).isZERO()) { hd = i; } } //System.out.println("d = " + d + ", hd = " + hd + ", coeffCache = " + lazyCoeffs.coeffCache + ", this = " + this); return hd - d; } /** * Signum. * @return sign of first non zero coefficient. */ public int signum() { ExpVector ev = orderExpVector(); if (ev != null) { return coefficient(ev).signum(); } return 0; } /** * Compare to. Note: compare only up to max(truncates). * @return sign of first non zero coefficient of this-ps. */ //JAVA6only: @Override public int compareTo(MultiVarPowerSeries ps) { final int m = truncate(); final int n = ps.truncate(); final int pos = Math.min(ring.truncate, Math.min(m, n)); int s = 0; //System.out.println("coeffCache_c1 = " + lazyCoeffs.coeffCache); //System.out.println("coeffCache_c2 = " + ps.lazyCoeffs.coeffCache); // test homogeneous parts first is slower for (ExpVector i : new ExpVectorIterable(ring.nvar, true, pos)) { s = coefficient(i).compareTo(ps.coefficient(i)); if (s != 0) { //System.out.println("i = " + i + ", coeff = " + coefficient(i) + ", ps.coeff = " + ps.coefficient(i)); return s; } } for (int j = pos + 1; j <= Math.min(ring.truncate, Math.max(m, n)); j++) { for (ExpVector i : new ExpVectorIterable(ring.nvar, j)) { s = coefficient(i).compareTo(ps.coefficient(i)); //System.out.println("i = " + i + ", coeff = " + coefficient(i) + ", ps.coeff = " + ps.coefficient(i)); if (s != 0) { //System.out.println("i = " + i + ", coeff = " + coefficient(i) + ", ps.coeff = " + ps.coefficient(i)); return s; } } } return s; } /** * Is power series zero. Note: compare only up to truncate. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return (signum() == 0); } /** * Is power series one. Note: compare only up to truncate. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { if (!leadingCoefficient().isONE()) { return false; } return (compareTo(ring.ONE) == 0); //return reductum().isZERO(); } /** * Comparison with any other object. Note: compare only up to * truncate. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { if (!(B instanceof MultiVarPowerSeries)) { return false; } MultiVarPowerSeries a = null; try { a = (MultiVarPowerSeries) B; } catch (ClassCastException ignored) { } if (a == null) { return false; } return compareTo(a) == 0; } /** * Hash code for this polynomial. Note: only up to truncate. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = 0; //h = ( ring.hashCode() << 23 ); //h += val.hashCode(); for (ExpVector i : new ExpVectorIterable(ring.nvar, true, truncate)) { C c = coefficient(i); if (!c.isZERO()) { h += i.hashCode(); h = (h << 23); } h += c.hashCode(); h = (h << 23); } return h; } /** * Is unit. * @return true, if this power series is invertible, else false. */ public boolean isUnit() { return leadingCoefficient().isUnit(); } /** * Sum a another power series. * @param ps other power series. * @return this + ps. */ public MultiVarPowerSeries sum(final MultiVarPowerSeries ps) { //final MultiVarPowerSeries ps1 = this; // method name was ambiguous in generate int nt = Math.min(ring.truncate, Math.max(truncate(), ps.truncate())); return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector e) { long tdeg = e.totalDeg(); if (lazyCoeffs.homCheck.get((int) tdeg)) { // generate respective homogeneous polynomial GenPolynomial p = homogeneousPart(tdeg).sum(ps.homogeneousPart(tdeg)); coeffCache.put(tdeg, p); // overwrite homCheck.set((int) tdeg); C c = p.coefficient(e); //System.out.println("c = " + c + ", e = " + e + ", tdeg = " + tdeg); return c; } return coefficient(e).sum(ps.coefficient(e)); } }, nt); } /** * Subtract a another power series. * @param ps other power series. * @return this - ps. */ public MultiVarPowerSeries subtract(final MultiVarPowerSeries ps) { //final MultiVarPowerSeries ps1 = this; // method name was ambiguous in generate int nt = Math.min(ring.truncate, Math.max(truncate(), ps.truncate())); return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector e) { long tdeg = e.totalDeg(); if (lazyCoeffs.homCheck.get((int) tdeg)) { // generate respective homogeneous polynomial GenPolynomial p = homogeneousPart(tdeg).subtract(ps.homogeneousPart(tdeg)); coeffCache.put(tdeg, p); // overwrite homCheck.set((int) tdeg); C c = p.coefficient(e); //System.out.println("p = " + p + ", e = " + e + ", tdeg = " + tdeg); return c; } return coefficient(e).subtract(ps.coefficient(e)); } }, nt); } /** * Multiply by another power series. * @param ps other power series. * @return this * ps. */ public MultiVarPowerSeries multiply(final MultiVarPowerSeries ps) { //final MultiVarPowerSeries ps1 = this; // method name was ambiguous in generate int nt = Math.min(ring.truncate, truncate() + ps.truncate()); return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector e) { long tdeg = e.totalDeg(); // generate respective homogeneous polynomial GenPolynomial p = null; //fac.getZERO(); for (int k = 0; k <= tdeg; k++) { GenPolynomial m = homogeneousPart(k).multiply(ps.homogeneousPart(tdeg - k)); if (p == null) { p = m; } else { p = p.sum(m); } } coeffCache.put(tdeg, p); // overwrite homCheck.set((int) tdeg); C c = p.coefficient(e); return c; } }, nt); } /** * Inverse power series. * @return ps with this * ps = 1. */ public MultiVarPowerSeries inverse() { return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector e) { long tdeg = e.totalDeg(); C d = leadingCoefficient().inverse(); // may fail if (tdeg == 0) { return d; } GenPolynomial p = null; //fac.getZERO(); for (int k = 0; k < tdeg; k++) { GenPolynomial m = getHomPart(k).multiply(homogeneousPart(tdeg - k)); if (p == null) { p = m; } else { p = p.sum(m); } } p = p.multiply(d.negate()); //System.out.println("tdeg = " + tdeg + ", p = " + p); coeffCache.put(tdeg, p); // overwrite homCheck.set((int) tdeg); C c = p.coefficient(e); return c; } }); } /** * Divide by another power series. * @param ps nonzero power series with invertible coefficient. * @return this / ps. */ public MultiVarPowerSeries divide(MultiVarPowerSeries ps) { if (ps.isUnit()) { return multiply(ps.inverse()); } int m = order(); int n = ps.order(); if (m < n) { return ring.getZERO(); } ExpVector em = orderExpVector(); ExpVector en = ps.orderExpVector(); if (!ps.coefficient(en).isUnit()) { throw new ArithmeticException("division by non unit coefficient " + ps.coefficient(ps.evorder) + ", evorder = " + ps.evorder); } // now m >= n MultiVarPowerSeries st, sps, q, sq; if (m == 0) { st = this; } else { st = this.shift(em.negate()); } if (n == 0) { sps = ps; } else { sps = ps.shift(en.negate()); } q = st.multiply(sps.inverse()); sq = q.shift(em.subtract(en)); return sq; } /** * Power series remainder. * @param ps nonzero power series with invertible leading coefficient. * @return remainder with this = quotient * ps + remainder. */ public MultiVarPowerSeries remainder(MultiVarPowerSeries ps) { int m = order(); int n = ps.order(); if (m >= n) { return ring.getZERO(); } return this; } /** * Differentiate with respect to variable r. * @param r variable for the direction. * @return differentiate(this). */ public MultiVarPowerSeries differentiate(final int r) { if (r < 0 || ring.nvar < r) { throw new IllegalArgumentException("variable index out of bound"); } return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector i) { long d = i.getVal(r); ExpVector e = i.subst(r, d + 1); C v = coefficient(e); v = v.multiply(ring.coFac.fromInteger(d + 1)); return v; } }); } /** * Integrate with respect to variable r and with given constant. * @param c integration constant. * @param r variable for the direction. * @return integrate(this). */ public MultiVarPowerSeries integrate(final C c, final int r) { if (r < 0 || ring.nvar < r) { throw new IllegalArgumentException("variable index out of bound"); } int nt = Math.min(ring.truncate, truncate + 1); return new MultiVarPowerSeries(ring, new MultiVarCoefficients(ring) { @Override public C generate(ExpVector i) { if (i.isZERO()) { return c; } long d = i.getVal(r); if (d > 0) { ExpVector e = i.subst(r, d - 1); C v = coefficient(e); v = v.divide(ring.coFac.fromInteger(d)); return v; } return ring.coFac.getZERO(); } }, nt); } /** * Power series greatest common divisor. * @param ps power series. * @return gcd(this,ps). */ public MultiVarPowerSeries gcd(MultiVarPowerSeries ps) { if (ps.isZERO()) { return this; } if (this.isZERO()) { return ps; } ExpVector em = orderExpVector(); ExpVector en = ps.orderExpVector(); return ring.getONE().shift(em.gcd(en)); } /** * Power series extended greatest common divisor. Note: not * implemented. * @param S power series. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ //SuppressWarnings("unchecked") public MultiVarPowerSeries[] egcd(MultiVarPowerSeries S) { throw new UnsupportedOperationException("egcd for power series not implemented"); } } jas-2.5/src/edu/jas/ps/PolynomialTaylorFunction.java0000644000175000017500000000617111547152076023012 0ustar giovannigiovanni/* * $Id: PolynomialTaylorFunction.java 3596 2011-04-06 20:59:42Z kredel $ */ package edu.jas.ps; import java.util.List; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.PolyUtil; import edu.jas.structure.RingElem; /** * Polynomial functions capable for Taylor series expansion. * @param ring element type * @author Heinz Kredel */ public class PolynomialTaylorFunction> implements TaylorFunction { final GenPolynomial pol; final long facul; public PolynomialTaylorFunction(GenPolynomial p) { this(p, 1L); } public PolynomialTaylorFunction(GenPolynomial p, long f) { pol = p; facul = f; } /** * To String. * @return string representation of this. */ @Override public String toString() { return pol.toString(); } /** * Get the factorial coefficient. * @return factorial coefficient. */ //JAVA6only: @Override public long getFacul() { return facul; } /** * Test if this is zero. * @return true if this is 0, else false. */ public boolean isZERO() { return pol.isZERO(); } /** * Deriviative. * @return deriviative of this. */ //JAVA6only: @Override public TaylorFunction deriviative() { return new PolynomialTaylorFunction(PolyUtil. baseDeriviative(pol)); } /* * Partial deriviative. * @param r index of the variable. * @return partial deriviative of this with respect to variable r. public TaylorFunction deriviative(int r) { return new PolynomialTaylorFunction(PolyUtil. baseDeriviative(pol,r)); } */ /** * Multi-partial deriviative. * @param i exponent vector. * @return partial deriviative of this with respect to all variables. */ public TaylorFunction deriviative(ExpVector i) { GenPolynomial p = pol; long f = 1L; if (i.signum() == 0 || pol.isZERO()) { return new PolynomialTaylorFunction(p, f); } for (int j = 0; j < i.length(); j++) { long e = i.getVal(j); if (e == 0) { continue; } int jl = i.length() - 1 - j; for (long k = 0; k < e; k++) { p = PolyUtil. baseDeriviative(p, jl); f *= (k + 1); if (p.isZERO()) { return new PolynomialTaylorFunction(p, f); } } } //System.out.println("i = " + i + ", f = " + f + ", der = " + p); return new PolynomialTaylorFunction(p, f); } /** * Evaluate. * @param a element. * @return this(a). */ //JAVA6only: @Override public C evaluate(C a) { return PolyUtil. evaluateMain(pol.ring.coFac, pol, a); } /** * Evaluate at a tuple of elements. * @param a tuple of elements. * @return this(a). */ public C evaluate(List a) { return PolyUtil. evaluateAll(pol.ring.coFac, pol.ring, pol, a); } } jas-2.5/src/edu/jas/ps/ExpVectorIterable.java0000644000175000017500000001315311505423120021334 0ustar giovannigiovanni/* * $Id: ExpVectorIterable.java 3444 2010-12-25 17:13:53Z kredel $ */ package edu.jas.ps; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.List; import java.util.ArrayList; import edu.jas.poly.ExpVector; import edu.jas.util.CartesianProductLong; import edu.jas.util.LongIterable; /** * Iterable for ExpVector, using total degree enumeration. * @author Heinz Kredel */ public class ExpVectorIterable implements Iterable { protected long upperBound; final boolean infinite; final int nvar; /** * Constructor. * @param nv number of variables. */ public ExpVectorIterable(int nv) { this(nv,true,Long.MAX_VALUE); } /** * Constructor. * @param nv number of variables. * @param ub upper bound for the components. */ public ExpVectorIterable(int nv, long ub) { this(nv,false,ub); } /** * Constructor. * @param nv number of variables. * @param all true, if all elements between 0 and upper bound are enumerated, false, if only elements of exact upper bund are to be processed. * @param ub upper bound for the components. */ public ExpVectorIterable(int nv, boolean all, long ub) { upperBound = ub; infinite = all; nvar = nv; } /** Set the upper bound for the iterator. * @param ub an upper bound for the iterator elements. */ public void setUpperBound(long ub) { upperBound = ub; } /** Get the upper bound for the iterator. * @return the upper bound for the iterator elements. */ public long getUpperBound() { return upperBound; } /** * Get an iterator over ExpVector. * @return an iterator. */ public Iterator iterator() { return new ExpVectorIterator(nvar,infinite,upperBound); } } /** * ExpVector iterator using CartesianProductLongIterator. * @author Heinz Kredel */ class ExpVectorIterator implements Iterator { /** * data structure. */ ExpVector current; Iterator> liter; protected int totalDegree; protected boolean empty; final long upperBound; final boolean infinite; final int nvar; /** * ExpVector iterator constructor. * @param nv number of variables. */ public ExpVectorIterator(int nv) { this(nv,true,Long.MAX_VALUE); } /** * ExpVector iterator constructor. * @param nv number of variables. * @param ub upper bound for the components. */ public ExpVectorIterator(int nv,long ub) { this(nv,false,ub); } /** * ExpVector iterator constructor. * @param nv number of variables. * @param inf true, if all elements between 0 and upper bound are enumerated, false, if only elements of exact upper bund are to be processed. * @param ub an upper bound for the entrys. */ protected ExpVectorIterator(int nv, boolean inf, long ub) { infinite = inf; upperBound = ub; if (upperBound < 0L) { throw new IllegalArgumentException("negative upper bound not allowed"); } totalDegree = 0; if ( !infinite ) { totalDegree = (int)upperBound; } //System.out.println("totalDegree = " + totalDegree + ", upperBound = " + upperBound); LongIterable li = new LongIterable(); li.setNonNegativeIterator(); li.setUpperBound(totalDegree); List tlist = new ArrayList(nv); for (int i = 0; i < nv; i++) { tlist.add(li); // can reuse li } Iterable> ib = new CartesianProductLong(tlist,totalDegree); liter = ib.iterator(); empty = (totalDegree > upperBound) || !liter.hasNext(); current = ExpVector.create(nv); if ( !empty ) { List el = liter.next(); current = ExpVector.create(el); //System.out.println("current = " + current); } nvar = nv; } /** * Test for availability of a next long. * @return true if the iteration has more ExpVectors, else false. */ public synchronized boolean hasNext() { return !empty; } /** * Get next ExpVector. * @return next ExpVector. */ public synchronized ExpVector next() { ExpVector res = current; if ( liter.hasNext() ) { List el = liter.next(); current = ExpVector.create(el); //System.out.println("current, liter = " + current); return res; } if ( totalDegree >= upperBound ) { empty = true; return res; } totalDegree++; //System.out.println("totalDegree,b = " + totalDegree); if ( totalDegree >= upperBound && !infinite ) { throw new NoSuchElementException("invalid call of next()"); } LongIterable li = new LongIterable(); li.setNonNegativeIterator(); li.setUpperBound(totalDegree); List tlist = new ArrayList(nvar); for (int i = 0; i < nvar; i++) { tlist.add(li); // can reuse li } Iterable> ib = new CartesianProductLong(tlist,totalDegree); liter = ib.iterator(); List el = liter.next(); current = ExpVector.create(el); return res; } /** * Remove a tuple if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove elements"); } } jas-2.5/src/edu/jas/ps/UnivPowerSeriesRing.java0000644000175000017500000003512612004504014021677 0ustar giovannigiovanni/* * $Id: UnivPowerSeriesRing.java 4062 2012-07-27 12:22:37Z kredel $ */ package edu.jas.ps; import java.io.Reader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Random; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.Monomial; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Univariate power series ring implementation. Uses lazy evaluated generating * function for coefficients. * @param ring element type * @author Heinz Kredel */ public class UnivPowerSeriesRing> implements RingFactory> { /** * A default random sequence generator. */ protected final static Random random = new Random(); /** * Default truncate. */ public final static int DEFAULT_TRUNCATE = 11; /** * Truncate. */ int truncate; /** * Default variable name. */ public final static String DEFAULT_NAME = "x"; /** * Variable name. */ String var; /** * Coefficient ring factory. */ public final RingFactory coFac; /** * The constant power series 1 for this ring. */ public final UnivPowerSeries ONE; /** * The constant power series 0 for this ring. */ public final UnivPowerSeries ZERO; /** * No argument constructor. */ @SuppressWarnings("unused") private UnivPowerSeriesRing() { throw new IllegalArgumentException("do not use no-argument constructor"); } /** * Constructor. * @param coFac coefficient ring factory. */ public UnivPowerSeriesRing(RingFactory coFac) { this(coFac, DEFAULT_TRUNCATE, DEFAULT_NAME); } /** * Constructor. * @param coFac coefficient ring factory. * @param truncate index of truncation. */ public UnivPowerSeriesRing(RingFactory coFac, int truncate) { this(coFac, truncate, DEFAULT_NAME); } /** * Constructor. * @param coFac coefficient ring factory. * @param name of the variable. */ public UnivPowerSeriesRing(RingFactory coFac, String name) { this(coFac, DEFAULT_TRUNCATE, name); } /** * Constructor. * @param pfac polynomial ring factory. */ public UnivPowerSeriesRing(GenPolynomialRing pfac) { this(pfac.coFac, DEFAULT_TRUNCATE, pfac.getVars()[0]); } /** * Constructor. * @param cofac coefficient ring factory. * @param truncate index of truncation. * @param name of the variable. */ public UnivPowerSeriesRing(RingFactory cofac, int truncate, String name) { this.coFac = cofac; this.truncate = truncate; this.var = name; this.ONE = new UnivPowerSeries(this, new Coefficients() { @Override public C generate(int i) { if (i == 0) { return coFac.getONE(); } return coFac.getZERO(); } }); this.ZERO = new UnivPowerSeries(this, new Coefficients() { @Override public C generate(int i) { return coFac.getZERO(); } }); } /** * Fixed point construction. * @param map a mapping of power series. * @return fix point wrt map. */ // Cannot be a static method because a power series ring is required. public UnivPowerSeries fixPoint(UnivPowerSeriesMap map) { UnivPowerSeries ps1 = new UnivPowerSeries(this); UnivPowerSeries ps2 = map.map(ps1); ps1.lazyCoeffs = ps2.lazyCoeffs; return ps2; } /** * To String. * @return string representation of this. */ @Override public String toString() { StringBuffer sb = new StringBuffer(); String scf = coFac.getClass().getSimpleName(); sb.append(scf + "((" + var + "))"); return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer("PS("); String f = null; try { f = ((RingElem) coFac).toScriptFactory(); // sic } catch (Exception e) { f = coFac.toScript(); } s.append(f + ",\"" + var + "\"," + truncate + ")"); return s.toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { UnivPowerSeriesRing a = null; try { a = (UnivPowerSeriesRing) B; } catch (ClassCastException ignored) { } if (a == null) { return false; } if (!coFac.equals(a.coFac)) { return false; } if (!var.equals(a.var)) { return false; } return true; } /** * Hash code for this . * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = coFac.hashCode(); h += (var.hashCode() << 27); h += truncate; return h; } /** * Get the zero element. * @return 0 as UnivPowerSeries. */ public UnivPowerSeries getZERO() { return ZERO; } /** * Get the one element. * @return 1 as UnivPowerSeries. */ public UnivPowerSeries getONE() { return ONE; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List rgens = coFac.generators(); List> gens = new ArrayList>(rgens.size()); for (final C cg : rgens) { UnivPowerSeries g = new UnivPowerSeries(this, new Coefficients() { @Override public C generate(int i) { if (i == 0) { return cg; } return coFac.getZERO(); } }); gens.add(g); } gens.add(ONE.shift(1)); return gens; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return false; } /** * Get the power series of the exponential function. * @return exp(x) as UnivPowerSeries. */ public UnivPowerSeries getEXP() { return fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries e) { return e.integrate(coFac.getONE()); } }); } /** * Get the power series of the sinus function. * @return sin(x) as UnivPowerSeries. */ public UnivPowerSeries getSIN() { return fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries s) { return s.negate().integrate(coFac.getONE()).integrate(coFac.getZERO()); } }); } /** * Get the power series of the cosine function. * @return cos(x) as UnivPowerSeries. */ public UnivPowerSeries getCOS() { return fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries c) { return c.negate().integrate(coFac.getZERO()).integrate(coFac.getONE()); } }); } /** * Get the power series of the tangens function. * @return tan(x) as UnivPowerSeries. */ public UnivPowerSeries getTAN() { return fixPoint(new UnivPowerSeriesMap() { public UnivPowerSeries map(UnivPowerSeries t) { return t.multiply(t).sum(getONE()).integrate(coFac.getZERO()); } }); } /** * Solve an ordinary differential equation. y' = f(y) with y(0) = c. * @param f a UnivPowerSeries. * @param c integration constant. * @return f.integrate(c). */ public UnivPowerSeries solveODE(final UnivPowerSeries f, final C c) { return f.integrate(c); } /** * Is commutative. * @return true, if this ring is commutative, else false. */ public boolean isCommutative() { return coFac.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return coFac.isAssociative(); } /** * Query if this ring is a field. * @return false. */ public boolean isField() { return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return coFac.characteristic(); } /** * Get a (constant) UnivPowerSeries<C> from a long value. * @param a long. * @return a UnivPowerSeries<C>. */ public UnivPowerSeries fromInteger(long a) { return ONE.multiply(coFac.fromInteger(a)); } /** * Get a (constant) UnivPowerSeries<C> from a java.math.BigInteger. * @param a BigInteger. * @return a UnivPowerSeries<C>. */ public UnivPowerSeries fromInteger(java.math.BigInteger a) { return ONE.multiply(coFac.fromInteger(a)); } /** * Get the corresponding GenPolynomialRing<C>. * @return GenPolynomialRing<C>. */ public GenPolynomialRing polyRing() { return new GenPolynomialRing(coFac, 1, new String[] { var }); } /** * Get a UnivPowerSeries<C> from a GenPolynomial<C>. * @param a GenPolynomial<C>. * @return a UnivPowerSeries<C>. */ public UnivPowerSeries fromPolynomial(GenPolynomial a) { if (a == null || a.isZERO()) { return ZERO; } if (a.isONE()) { return ONE; } if (a.ring.nvar != 1) { throw new IllegalArgumentException("only for univariate polynomials"); } HashMap cache = new HashMap(a.length()); for (Monomial m : a) { long e = m.exponent().getVal(0); cache.put((int) e, m.coefficient()); } return new UnivPowerSeries(this, new Coefficients(cache) { @Override public C generate(int i) { // cached coefficients returned by get return coFac.getZERO(); } }); } /** * Generate a random power series with k = 5, d = 0.7. * @return a random power series. */ public UnivPowerSeries random() { return random(5, 0.7f, random); } /** * Generate a random power series with d = 0.7. * @param k bitsize of random coefficients. * @return a random power series. */ public UnivPowerSeries random(int k) { return random(k, 0.7f, random); } /** * Generate a random power series with d = 0.7. * @param k bit-size of random coefficients. * @param rnd is a source for random bits. * @return a random power series. */ public UnivPowerSeries random(int k, Random rnd) { return random(k, 0.7f, rnd); } /** * Generate a random power series. * @param k bit-size of random coefficients. * @param d density of non-zero coefficients. * @return a random power series. */ public UnivPowerSeries random(int k, float d) { return random(k, d, random); } /** * Generate a random power series. * @param k bit-size of random coefficients. * @param d density of non-zero coefficients. * @param rnd is a source for random bits. * @return a random power series. */ public UnivPowerSeries random(final int k, final float d, final Random rnd) { return new UnivPowerSeries(this, new Coefficients() { @Override public C generate(int i) { // cached coefficients returned by get C c; float f = rnd.nextFloat(); if (f < d) { c = coFac.random(k, rnd); } else { c = coFac.getZERO(); } return c; } }); } /** * Copy power series. * @param c a power series. * @return a copy of c. */ public UnivPowerSeries copy(UnivPowerSeries c) { return new UnivPowerSeries(this, c.lazyCoeffs); } /** * Parse a power series. Note: not implemented. * @param s String. * @return power series from s. */ public UnivPowerSeries parse(String s) { throw new UnsupportedOperationException("parse for power series not implemented"); } /** * Parse a power series. Note: not implemented. * @param r Reader. * @return next power series from r. */ public UnivPowerSeries parse(Reader r) { throw new UnsupportedOperationException("parse for power series not implemented"); } /** * Taylor power series. * @param f function. * @param a expansion point. * @return Taylor series of f. */ public UnivPowerSeries seriesOfTaylor(final TaylorFunction f, final C a) { return new UnivPowerSeries(this, new Coefficients() { TaylorFunction der = f; long k = 0; long n = 1; @Override public C generate(int i) { C c; if (i == 0) { c = der.evaluate(a); der = der.deriviative(); return c; } if (i > 0) { c = get(i - 1); // ensure deriv is updated } k++; n *= k; c = der.evaluate(a); //System.out.println("n = " + n + ", i = " +i); c = c.divide(coFac.fromInteger(n)); der = der.deriviative(); return c; } }); } } jas-2.5/src/edu/jas/ps/Pair.java0000644000175000017500000000675512000527236016656 0ustar giovannigiovanni/* * $Id: Pair.java 3994 2012-07-15 11:50:54Z kredel $ */ package edu.jas.ps; import java.io.Serializable; import edu.jas.structure.RingElem; /** * Serializable subclass to hold pairs of power series. * @param coefficient type * @author Heinz Kredel. */ public class Pair> implements Serializable, Comparable { public final MultiVarPowerSeries pi; public final MultiVarPowerSeries pj; public final int i; public final int j; protected int n; protected boolean toZero = false; protected boolean useCriterion4 = false; protected boolean useCriterion3 = false; /** * Pair constructor. * @param a power series i. * @param b power series j. * @param i first index. * @param j second index. */ public Pair(MultiVarPowerSeries a, MultiVarPowerSeries b, int i, int j) { pi = a; pj = b; this.i = i; this.j = j; this.n = 0; toZero = false; // ok } /** * toString. */ @Override public String toString() { return "pair[" + n + "](" + i + j + ", r0=" + toZero + ", c4=" + useCriterion4 + ", c3=" + useCriterion3 + ")"; } /** * Set removed pair number. * @param n number of this pair generated in OrderedPairlist. */ public void pairNumber(int n) { this.n = n; } /** * Get removed pair number. * @return n number of this pair generated in OrderedPairlist. */ public int getPairNumber() { return n; } /** * Set zero reduction. The S-power-series of this Pair was reduced to zero. */ public void setZero() { toZero = true; } /** * Is reduced to zero. * @return true if the S-power-series of this Pair was reduced to zero, else * false. */ public boolean isZero() { return toZero; } /** * equals. * @param ob an Object. * @return true if this is equal to o, else false. */ @Override public boolean equals(Object ob) { if (!(ob instanceof Pair)) { return false; // throw new ClassCastException("Pair "+n+" o "+o); } return 0 == compareTo((Pair) ob); } /** * compareTo used in TreeMap // not used at moment. Comparison is based on * the number of the pairs. * @param p a Pair. * @return 1 if (this < o), 0 if (this == o), -1 if (this > o). */ public int compareTo(Pair p) { int x = p.getPairNumber(); if (n > x) { return 1; } if (n < x) { return -1; } return 0; } /** * Hash code for this Pair. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return (i << 16) + j; } /** * Set useCriterion4. * @param c boolean value to set. */ public void setUseCriterion4(boolean c) { this.useCriterion4 = c; } /** * Get useCriterion4. * @return boolean value. */ public boolean getUseCriterion4() { return this.useCriterion4; } /** * Set useCriterion3. * @param c boolean value to set. */ public void setUseCriterion3(boolean c) { this.useCriterion3 = c; } /** * Get useCriterion3. * @return boolean value. */ public boolean getUseCriterion3() { return this.useCriterion3; } } jas-2.5/src/edu/jas/ps/ReductionSeq.java0000644000175000017500000002747212004504014020360 0ustar giovannigiovanni/* * $Id: ReductionSeq.java 4062 2012-07-27 12:22:37Z kredel $ */ package edu.jas.ps; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.RingElem; /** * Multivariate power series reduction sequential use algorithm. Implements Mora * normal-form algorithm. * @param coefficient type * @author Heinz Kredel */ public class ReductionSeq> // should be FieldElem> /*todo: extends ReductionAbstract*/{ private static final Logger logger = Logger.getLogger(ReductionSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public ReductionSeq() { } /** * Module criterium. * @param modv number of module variables. * @param A power series. * @param B power series. * @return true if the module S-power-series(i,j) is required. */ public boolean moduleCriterion(int modv, MultiVarPowerSeries A, MultiVarPowerSeries B) { if (modv == 0) { return true; } ExpVector ei = A.orderExpVector(); ExpVector ej = B.orderExpVector(); return moduleCriterion(modv, ei, ej); } /** * Module criterion. * @param modv number of module variables. * @param ei ExpVector. * @param ej ExpVector. * @return true if the module S-power-series(i,j) is required. */ public boolean moduleCriterion(int modv, ExpVector ei, ExpVector ej) { if (modv == 0) { return true; } if (ei.invLexCompareTo(ej, 0, modv) != 0) { return false; // skip pair } return true; } /** * GB criterion 4. Use only for commutative power series rings. * @param A power series. * @param B power series. * @param e = lcm(ht(A),ht(B)) * @return true if the S-power-series(i,j) is required, else false. */ public boolean criterion4(MultiVarPowerSeries A, MultiVarPowerSeries B, ExpVector e) { if (logger.isInfoEnabled()) { if (!A.ring.equals(B.ring)) { logger.error("rings not equal " + A.ring + ", " + B.ring); } if (!A.ring.isCommutative()) { logger.error("GBCriterion4 not applicabable to non-commutative power series"); return true; } } ExpVector ei = A.orderExpVector(); ExpVector ej = B.orderExpVector(); ExpVector g = ei.sum(ej); // boolean t = g == e ; ExpVector h = g.subtract(e); int s = h.signum(); return !(s == 0); } /** * S-Power-series, S-polynomial. * @param A power series. * @param B power series. * @return spol(A,B) the S-power-series of A and B. */ public MultiVarPowerSeries SPolynomial(MultiVarPowerSeries A, MultiVarPowerSeries B) { if (B == null || B.isZERO()) { if (A == null) { return B; } return A.ring.getZERO(); } if (A == null || A.isZERO()) { return B.ring.getZERO(); } if (debug) { if (!A.ring.equals(B.ring)) { logger.error("rings not equal " + A.ring + ", " + B.ring); } } Map.Entry ma = A.orderMonomial(); Map.Entry mb = B.orderMonomial(); ExpVector e = ma.getKey(); ExpVector f = mb.getKey(); ExpVector g = e.lcm(f); ExpVector e1 = g.subtract(e); ExpVector f1 = g.subtract(f); C a = ma.getValue(); C b = mb.getValue(); MultiVarPowerSeries Ap = A.multiply(b, e1); MultiVarPowerSeries Bp = B.multiply(a, f1); MultiVarPowerSeries C = Ap.subtract(Bp); return C; } /** * Top normal-form with Mora's algorithm. * @param Ap power series. * @param Pp power series list. * @return top-nf(Ap) with respect to Pp. */ public MultiVarPowerSeries normalform(List> Pp, MultiVarPowerSeries Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } if (!Ap.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } List> P = new ArrayList>(Pp.size()); synchronized (Pp) { P.addAll(Pp); } ArrayList htl = new ArrayList(P.size()); ArrayList lbc = new ArrayList(P.size()); ArrayList> p = new ArrayList>(P.size()); ArrayList ecart = new ArrayList(P.size()); Map.Entry m; int j = 0; for (int i = 0; i < P.size(); i++) { m = P.get(i).orderMonomial(); //System.out.println("m_i = " + m); if (m != null) { p.add(P.get(i)); //System.out.println("e = " + m.getKey().toString(Ap.ring.vars)); htl.add(m.getKey()); lbc.add(m.getValue()); ecart.add(P.get(i).ecart()); j++; } } //int ll = j; MultiVarPowerSeries S = Ap; //S.setTruncate(Ap.ring.truncate()); // ?? m = S.orderMonomial(); while (true) { //System.out.println("m = " + m); //System.out.println("S = " + S); if (m == null) { return S; } if (S.isZERO()) { return S; } ExpVector e = m.getKey(); if (debug) { logger.debug("e = " + e.toString(Ap.ring.vars)); } // search ps with ht(ps) | ht(S) List li = new ArrayList(); int i; for (i = 0; i < htl.size(); i++) { if (e.multipleOf(htl.get(i))) { //System.out.println("m = " + m); li.add(i); } } if (li.isEmpty()) { return S; } //System.out.println("li = " + li); // select ps with smallest ecart long mi = Long.MAX_VALUE; //String es = ""; for (int k = 0; k < li.size(); k++) { int ki = li.get(k); long x = ecart.get(ki); //p.get( ki ).ecart(); //es = es + x + " "; if (x < mi) { // first < or last <= ? mi = x; i = ki; } } //System.out.println("li = " + li + ", ecarts = " + es); //System.out.println("i = " + i + ", p_i = " + p.get(i)); //if ( i <= ll ) { //} else { // System.out.println("i = " + i + ", ll = " + ll); //} long si = S.ecart(); if (mi > si) { //System.out.println("ecart_i = " + mi + ", ecart_S = " + si + ", S+ = " + S); p.add(S); htl.add(m.getKey()); lbc.add(m.getValue()); ecart.add(si); } e = e.subtract(htl.get(i)); C a = m.getValue().divide(lbc.get(i)); MultiVarPowerSeries Q = p.get(i).multiply(a, e); S = S.subtract(Q); m = S.orderMonomial(); } } /** * Total reduced normal-form with Mora's algorithm. * @param A power series. * @param P power series list. * @return total-nf(A) with respect to P. */ public MultiVarPowerSeries totalNormalform(List> P, MultiVarPowerSeries A) { if (P == null || P.isEmpty()) { return A; } if (A == null) { return A; } MultiVarPowerSeries R = normalform(P, A); if (R.isZERO()) { return R; } MultiVarCoefficients Rc = new MultiVarCoefficients(A.ring) { @Override public C generate(ExpVector i) { // will not be used return pfac.coFac.getZERO(); } }; GenPolynomialRing pfac = A.lazyCoeffs.pfac; while (!R.isZERO()) { Map.Entry m = R.orderMonomial(); if (m == null) { break; } R = R.reductum(); ExpVector e = m.getKey(); long t = e.totalDeg(); GenPolynomial p = Rc.coeffCache.get(t); if (p == null) { p = pfac.getZERO(); } p = p.sum(m.getValue(), e); Rc.coeffCache.put(t, p); // zeros need never update R = normalform(P, R); } R = R.sum(Rc); //System.out.println("R+Rc = " + R); return R; } /** * Total reduced normalform with Mora's algorithm. * @param P power series list. * @return total-nf(p) for p with respect to P\{p}. */ public List> totalNormalform(List> P) { if (P == null || P.isEmpty()) { return P; } //StandardBaseSeq std = new StandardBaseSeq(); List> R = new ArrayList>(P.size()); List> S = new ArrayList>(P); for (MultiVarPowerSeries a : P) { //S.remove(a); //if ( !std.isSTD(S) ) { // System.out.println("a = " + a); //} Map.Entry m = a.orderMonomial(); if (m == null) { //S.add(a); continue; } MultiVarPowerSeries r = a.reductum(); MultiVarPowerSeries b = normalform(S, r); // need also unit of reduction: u r --> b // b = b.multiply(u); b = b.sum(m); if (!b.isZERO()) { R.add(b); } } return R; } /** * Is top reducible. * @param A power series. * @param P power series list. * @return true if A is top reducible with respect to P. */ public boolean isTopReducible(List> P, MultiVarPowerSeries A) { if (P == null || P.isEmpty()) { return false; } if (A == null) { return false; } ExpVector e = A.orderExpVector(); if (e == null) { return false; } for (MultiVarPowerSeries p : P) { ExpVector ep = p.orderExpVector(); if (ep == null) { // found by findbugs continue; } if (e.multipleOf(ep)) { return true; } } return false; } /** * Ideal containment. Test if each b in B is contained in ideal S. * @param S standard base. * @param B list of power series * @return true, if each b in B is contained in ideal(S), else false */ public boolean contains(List> S, List> B) { if (B == null || B.size() == 0) { return true; } if (S == null || S.size() == 0) { return true; } for (MultiVarPowerSeries b : B) { if (b == null) { continue; } MultiVarPowerSeries z = normalform(S, b); if (!z.isZERO()) { System.out.println("contains nf(b) != 0: " + b + ", z = " + z); return false; } } return true; } } jas-2.5/src/edu/jas/ps/MultiVarPowerSeriesMap.java0000644000175000017500000000102111440760332022334 0ustar giovannigiovanni/* * $Id: MultiVarPowerSeriesMap.java 3315 2010-09-05 18:26:34Z kredel $ */ package edu.jas.ps; import edu.jas.structure.RingElem; /** * Multivariate power series map interface. Defines method for mapping of power * series. * @param ring element type * @author Heinz Kredel */ public interface MultiVarPowerSeriesMap> { /** * Map. * @return new power series resulting from mapping elements of ps. */ public MultiVarPowerSeries map(MultiVarPowerSeries ps); } jas-2.5/src/edu/jas/structure/0000755000175000017500000000000012140140256016517 5ustar giovannigiovannijas-2.5/src/edu/jas/structure/UnaryFunctor.java0000644000175000017500000000060112004300754022016 0ustar giovannigiovanni/* * $Id: UnaryFunctor.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Unary functor interface. * @param element type * @param element type * @author Heinz Kredel */ public interface UnaryFunctor, D extends Element> { /** * Evaluate. * @return evaluated element. */ public D eval(C c); } jas-2.5/src/edu/jas/structure/MonoidFactory.java0000644000175000017500000000134312004300754022140 0ustar giovannigiovanni/* * $Id: MonoidFactory.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Monoid factory interface. Defines get one and tests for associativity and * commutativity. * @author Heinz Kredel */ public interface MonoidFactory> extends ElemFactory { /** * Get the constant one for the MonoidElem. * @return 1. */ public C getONE(); /** * Query if this monoid is commutative. * @return true if this monoid is commutative, else false. */ public boolean isCommutative(); /** * Query if this ring is associative. * @return true if this monoid is associative, else false. */ public boolean isAssociative(); } jas-2.5/src/edu/jas/structure/AbelianGroupElem.java0000644000175000017500000000171312004300754022537 0ustar giovannigiovanni/* * $Id: AbelianGroupElem.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Abelian group element interface. Defines the additive methods. * @param element type * @author Heinz Kredel */ public interface AbelianGroupElem> extends Element { /** * Test if this is zero. * @return true if this is 0, else false. */ public boolean isZERO(); /** * Signum. * @return the sign of this. */ public int signum(); /** * Sum of this and S. * @param S * @return this + S. */ public C sum(C S); //public T sum(T S); /** * Subtract S from this. * @param S * @return this - S. */ public C subtract(C S); /** * Negate this. * @return - this. */ public C negate(); /** * Absolute value of this. * @return |this|. */ public C abs(); } jas-2.5/src/edu/jas/structure/ModulElem.java0000644000175000017500000000246212004300754021251 0ustar giovannigiovanni/* * $Id: ModulElem.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; import java.util.List; /** * Module element interface. Defines scalar operations. * @param module type * @param scalar type * @author Heinz Kredel */ public interface ModulElem, C extends RingElem> extends AbelianGroupElem { /** * Scalar multiplication. Multiply this by a scalar. * @param s scalar * @return this * s. */ public M scalarMultiply(C s); /** * Linear combination. * @param a scalar * @param b module element * @param s scalar * @return a * b + this * s. */ public M linearCombination(C a, M b, C s); /** * Linear combination. * @param b module element * @param s scalar * @return b + this * s. */ public M linearCombination(M b, C s); /** * Scalar product. Multiply two vectors to become a scalar. * @param b module element * @return this * b, a scalar. */ public C scalarProduct(M b); /** * Scalar product. Multiply this vectors by list of vectors to become a * vector. * @param b list of module elements * @return this * b, a list of scalars, a module element. */ public M scalarProduct(List b); } jas-2.5/src/edu/jas/structure/package.html0000644000175000017500000000155211461035134021006 0ustar giovannigiovanni Basic structural interfaces

Basic structural interfaces.

This package contains interfaces for the most general algebraic structures used in JAS, e.g. RingElem and RingFactory. The Power class implements exponentation of monoid and ring elements.


Heinz Kredel

Last modified: Sun Oct 24 15:34:56 CEST 2010

$Id: package.html 3368 2010-10-24 13:53:32Z kredel $

jas-2.5/src/edu/jas/structure/AlgebraElem.java0000644000175000017500000000152112004300754021521 0ustar giovannigiovanni/* * $Id: AlgebraElem.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Algabra element interface. * @param algebra type * @param scalar type * @author Heinz Kredel */ public interface AlgebraElem, C extends RingElem> extends RingElem { /** * Scalar multiplication. Multiply this by a scalar. * @param s scalar * @return this * s. */ public A scalarMultiply(C s); /** * Linear combination. * @param a scalar * @param b algebra element * @param s scalar * @return a * b + this * s. */ public A linearCombination(C a, A b, C s); /** * Linear combination. * @param b algebra element * @param s scalar * @return b + this * s. */ public A linearCombination(A b, C s); } jas-2.5/src/edu/jas/structure/AbelianGroupFactory.java0000644000175000017500000000062412004300754023264 0ustar giovannigiovanni/* * $Id: AbelianGroupFactory.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Abelian group factory interface. Defines get zero. * @author Heinz Kredel */ public interface AbelianGroupFactory> extends ElemFactory { /** * Get the constant zero for the AbelianGroupElem. * @return 0. */ public C getZERO(); } jas-2.5/src/edu/jas/structure/MonoidElem.java0000644000175000017500000000232512004300754021414 0ustar giovannigiovanni/* * $Id: MonoidElem.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Monoid element interface. Defines the multiplicative methods. * @param element type * @author Heinz Kredel */ public interface MonoidElem> extends Element { /** * Test if this is one. * @return true if this is 1, else false. */ public boolean isONE(); /** * Test if this is a unit. I.e. there exists x with this.multiply(x).isONE() * == true. * @return true if this is a unit, else false. */ public boolean isUnit(); /** * Multiply this with S. * @param S * @return this * S. */ public C multiply(C S); /** * Divide this by S. * @param S * @return this / S. */ public C divide(C S); /** * Remainder after division of this by S. * @param S * @return this - (this / S) * S. */ public C remainder(C S); /** * Inverse of this. Some implementing classes will throw * NotInvertibleException if the element is not invertible. * @return x with this * x = 1, if it exists. */ public C inverse(); /*throws NotInvertibleException*/ } jas-2.5/src/edu/jas/structure/RingFactory.java0000644000175000017500000000127712004300754021620 0ustar giovannigiovanni/* * $Id: RingFactory.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Ring factory interface. Defines test for field and access of characteristic. * @author Heinz Kredel */ public interface RingFactory> extends AbelianGroupFactory, MonoidFactory { /** * Query if this ring is a field. May return false if it is to hard to * determine if this ring is a field. * @return true if it is known that this ring is a field, else false. */ public boolean isField(); /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic(); } jas-2.5/src/edu/jas/structure/FieldElem.java0000644000175000017500000000050212004300754021205 0ustar giovannigiovanni/* * $Id: FieldElem.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Field element interface. Empty interface since inverse is already in * RingElem. * @param field element type * @author Heinz Kredel */ public interface FieldElem> extends RingElem { } jas-2.5/src/edu/jas/structure/RingElem.java0000644000175000017500000000161612004300754021070 0ustar giovannigiovanni/* * $Id: RingElem.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Ring element interface. Combines additive and multiplicative methods. Adds * also gcd because of polynomials. * @param ring element type * @author Heinz Kredel */ public interface RingElem> extends AbelianGroupElem, MonoidElem { // /** Quotient and remainder. // * @param b other element. // * @return C[] { q, r } with this = q b + r and 0 ≤ r < |b|. // */ // public C[] quotientRemainder(C b); /** * Greatest common divisor. * @param b other element. * @return gcd(this,b). */ public C gcd(C b); /** * Extended greatest common divisor. * @param b other element. * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). */ public C[] egcd(C b); } jas-2.5/src/edu/jas/structure/ElemFactory.java0000644000175000017500000000375512004300754021606 0ustar giovannigiovanni/* * $Id: ElemFactory.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; import java.io.Reader; import java.io.Serializable; import java.math.BigInteger; import java.util.List; import java.util.Random; /** * Element factory interface. Defines embedding of integers, parsing and random * element construction. * @author Heinz Kredel */ public interface ElemFactory> extends Serializable { /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. */ public List generators(); /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. */ public boolean isFinite(); /** * Get the Element for a. * @param a long * @return element corresponding to a. */ public C fromInteger(long a); /** * Get the Element for a. * @param a java.math.BigInteger. * @return element corresponding to a. */ public C fromInteger(BigInteger a); /** * Generate a random Element with size less equal to n. * @param n * @return a random element. */ public C random(int n); /** * Generate a random Element with size less equal to n. * @param n * @param random is a source for random bits. * @return a random element. */ public C random(int n, Random random); /** * Create a copy of Element c. * @param c * @return a copy of c. */ public C copy(C c); /** * Parse from String. * @param s String. * @return a Element corresponding to s. */ public C parse(String s); /** * Parse from Reader. * @param r Reader. * @return the next Element found on r. */ public C parse(Reader r); /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. */ public String toScript(); } jas-2.5/src/edu/jas/structure/NotInvertibleException.java0000644000175000017500000000122212004300754024022 0ustar giovannigiovanni/* * $Id: NotInvertibleException.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * NotInvertibleException class. Runtime Exception to be thrown for not * invertible monoid elements. * @author Heinz Kredel */ public class NotInvertibleException extends RuntimeException { public NotInvertibleException() { super("NotInvertibleException"); } public NotInvertibleException(String c) { super(c); } public NotInvertibleException(String c, Throwable t) { super(c, t); } public NotInvertibleException(Throwable t) { super("NotInvertibleException", t); } } jas-2.5/src/edu/jas/structure/Element.java0000644000175000017500000000336512014237502020763 0ustar giovannigiovanni/* * $Id: Element.java 4128 2012-08-19 19:32:19Z kredel $ */ package edu.jas.structure; import java.io.Serializable; /** * Element interface. Basic functionality of elements, e.g. compareTo, equals, * clone. * Note: extension of Cloneable removed in * 2012-08-18, clone() is renamed to copy(). * @param element type. See the discussion in * Bloch on Cloning. * @author Heinz Kredel */ public interface Element> extends Comparable, Serializable { /** * Clone this Element. * @return Creates and returns a copy of this Element. */ public C copy(); /** * Test if this is equal to b. * @param b * @return true if this is equal to b, else false. */ public boolean equals(Object b); /** * Hashcode of this Element. * @return the hashCode. */ public int hashCode(); /** * Compare this to b. I.e. this < b iff this.compareTo(b) < 0. * Note: may not be meaningful if structure has no order. * @param b * @return 0 if this is equal to b, -1 if this is less then b, else +1. */ public int compareTo(C b); /** * Get the corresponding element factory. * @return factory for this Element. */ public ElemFactory factory(); /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. */ public String toScript(); /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. */ public String toScriptFactory(); } jas-2.5/src/edu/jas/structure/Power.java0000644000175000017500000002346512004300754020470 0ustar giovannigiovanni/* * $Id: Power.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; import java.util.List; import org.apache.log4j.Logger; /** * Power class to compute powers of RingElem. * @author Heinz Kredel */ public class Power> { private static final Logger logger = Logger.getLogger(Power.class); private static boolean debug = logger.isDebugEnabled(); private final RingFactory fac; /** * The constructor creates a Power object. */ public Power() { this(null); } /** * The constructor creates a Power object. * @param fac ring factory */ public Power(RingFactory fac) { this.fac = fac; } /** * power of a to the n-th, n positive. * @param a element. * @param n integer exponent > 0. * @return a^n. */ public static > C positivePower(C a, long n) { if (n <= 0) { throw new IllegalArgumentException("only positive n allowed"); } if (a.isZERO() || a.isONE()) { return a; } C b = a; long i = n - 1; C p = b; do { if (i % 2 == 1) { p = p.multiply(b); } i = i / 2; if (i > 0) { b = b.multiply(b); } } while (i > 0); return p; } /** * power of a to the n-th, n positive. * @param a element. * @param n java.math.BigInteger exponent > 0. * @return a^n. */ public static > C positivePower(C a, java.math.BigInteger n) { if (n.signum() <= 0) { throw new IllegalArgumentException("only positive n allowed"); } if (a.isZERO() || a.isONE()) { return a; } C b = a; if (n.compareTo(java.math.BigInteger.ONE) == 0) { return b; } C p = a; java.math.BigInteger i = n.subtract(java.math.BigInteger.ONE); do { if (i.testBit(0)) { p = p.multiply(b); } i = i.shiftRight(1); if (i.signum() > 0) { b = b.multiply(b); } } while (i.signum() > 0); return p; } /** * power of a to the n-th, n positive, modulo m. * @param a element. * @param n integer exponent > 0. * @param m modulus. * @return a^n mod m. */ public static > C modPositivePower(C a, long n, C m) { if (n <= 0) { throw new IllegalArgumentException("only positive n allowed"); } if (a.isZERO() || a.isONE()) { return a; } C b = a.remainder(m); long i = n - 1; C p = b; do { if (i % 2 == 1) { p = p.multiply(b).remainder(m); } i = i / 2; if (i > 0) { b = b.multiply(b).remainder(m); } } while (i > 0); return p; } /** * power of a to the n-th. * @param a element. * @param n integer exponent. * @param fac ring factory. * @return a^n, with 0^0 = 0 and a^{-n} = {1/a}^n. */ @SuppressWarnings("unchecked") public static > C power(RingFactory fac, C a, long n) { if (a == null || a.isZERO()) { return a; } //return a; return (C) Power. power((MonoidFactory) fac, a, n); } /** * power of a to the n-th. * @param a element. * @param n integer exponent. * @param fac monoid factory. * @return a^n, with a^{-n} = {1/a}^n. */ public static > C power(MonoidFactory fac, C a, long n) { if (n == 0) { if (fac == null) { throw new IllegalArgumentException("fac may not be null for a^0"); } return fac.getONE(); } if (a.isONE()) { return a; } C b = a; if (n < 0) { b = a.inverse(); n = -n; } if (n == 1) { return b; } C p = fac.getONE(); long i = n; do { if (i % 2 == 1) { p = p.multiply(b); } i = i / 2; if (i > 0) { b = b.multiply(b); } } while (i > 0); if (n > 11 && debug) { logger.info("n = " + n + ", p = " + p); } return p; } /** * power of a to the n-th modulo m. * @param a element. * @param n integer exponent. * @param m modulus. * @param fac monoid factory. * @return a^n mod m, with a^{-n} = {1/a}^n. */ public static > C modPower(MonoidFactory fac, C a, long n, C m) { if (n == 0) { if (fac == null) { throw new IllegalArgumentException("fac may not be null for a^0"); } return fac.getONE(); } if (a.isONE()) { return a; } C b = a.remainder(m); if (n < 0) { b = a.inverse().remainder(m); n = -n; } if (n == 1) { return b; } C p = fac.getONE(); long i = n; do { if (i % 2 == 1) { p = p.multiply(b).remainder(m); } i = i / 2; if (i > 0) { b = b.multiply(b).remainder(m); } } while (i > 0); if (n > 11 && debug) { logger.info("n = " + n + ", p = " + p); } return p; } /** * power of a to the n-th modulo m. * @param a element. * @param n integer exponent. * @param m modulus. * @param fac monoid factory. * @return a^n mod m, with a^{-n} = {1/a}^n. */ public static > C modPower(MonoidFactory fac, C a, java.math.BigInteger n, C m) { if (n.signum() == 0) { if (fac == null) { throw new IllegalArgumentException("fac may not be null for a^0"); } return fac.getONE(); } if (a.isONE()) { return a; } C b = a.remainder(m); if (n.signum() < 0) { b = a.inverse().remainder(m); n = n.negate(); } if (n.compareTo(java.math.BigInteger.ONE) == 0) { return b; } C p = fac.getONE(); java.math.BigInteger i = n; do { if (i.testBit(0)) { p = p.multiply(b).remainder(m); } i = i.shiftRight(1); if (i.signum() > 0) { b = b.multiply(b).remainder(m); } } while (i.signum() > 0); if (debug) { logger.info("n = " + n + ", p = " + p); } return p; } /** * power of a to the n-th. * @param a element. * @param n integer exponent. * @return a^n, with 0^0 = 0. */ public C power(C a, long n) { return power(fac, a, n); } /** * power of a to the n-th mod m. * @param a element. * @param n integer exponent. * @param m modulus. * @return a^n mod m, with 0^0 = 0. */ public C modPower(C a, long n, C m) { return modPower(fac, a, n, m); } /** * power of a to the n-th mod m. * @param a element. * @param n integer exponent. * @param m modulus. * @return a^n mod m, with 0^0 = 0. */ public C modPower(C a, java.math.BigInteger n, C m) { return modPower(fac, a, n, m); } /** * Logarithm. * @param p logarithm base. * @param a element. * @return k ≥ 1 minimal with p^k ≥ b. */ public static > long logarithm(C p, C a) { //if ( p.compareTo(a) < 0 ) { // return 0L; //} long k = 1L; C m = p; while (m.compareTo(a) < 0) { m = m.multiply(p); k++; } return k; } /** * Multiply elements in list. * @param A list of elements (a_0,...,a_k). * @param fac ring factory. * @return prod(i=0,...k) a_i. */ public static > C multiply(RingFactory fac, List A) { return multiply((MonoidFactory) fac, A); } /** * Multiply elements in list. * @param A list of elements (a_0,...,a_k). * @param fac monoid factory. * @return prod(i=0,...k) a_i. */ public static > C multiply(MonoidFactory fac, List A) { if (fac == null) { throw new IllegalArgumentException("fac may not be null for empty list"); } C res = fac.getONE(); if (A == null || A.isEmpty()) { return res; } for (C a : A) { res = res.multiply(a); } return res; } /** * Sum elements in list. * @param A list of elements (a_0,...,a_k). * @param fac ring factory. * @return sum(i=0,...k) a_i. */ public static > C sum(RingFactory fac, List A) { return sum((AbelianGroupFactory) fac, A); } /** * Sum elements in list. * @param A list of elements (a_0,...,a_k). * @param fac monoid factory. * @return sum(i=0,...k) a_i. */ public static > C sum(AbelianGroupFactory fac, List A) { if (fac == null) { throw new IllegalArgumentException("fac may not be null for empty list"); } C res = fac.getZERO(); if (A == null || A.isEmpty()) { return res; } for (C a : A) { res = res.sum(a); } return res; } } jas-2.5/src/edu/jas/structure/RegularRingElem.java0000644000175000017500000000331612004300754022411 0ustar giovannigiovanni/* * $Id: RegularRingElem.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Regular ring element interface. Defines idempotent operations and idempotent * tests. * @param regular ring element type * @author Heinz Kredel */ public interface RegularRingElem> extends GcdRingElem { /* Get component. * Not possible to define in interface. * @param i index of component. * @return val(i). public C get(int i); */ /** * Is regular ring element full. * @return If every component is non zero, then true is returned, else * false. */ public boolean isFull(); /** * Is idempotent. * @return If this is a idempotent element then true is returned, else * false. */ public boolean isIdempotent(); /** * Idempotent. * @return S with this*S = this. */ public C idempotent(); /** * Regular ring element idempotent complement. * @return 1-this.idempotent(). */ public C idemComplement(); /** * Regular ring element idempotent and. * @param S Product. * @return this.idempotent() and S.idempotent(). */ public C idempotentAnd(C S); /** * Regular ring element idempotent or. * @param S Product. * @return this.idempotent() or S.idempotent(). */ public C idempotentOr(C S); /** * Regular ring element fill with idempotent. * @param S Product. * @return fill this with S.idempotent(). */ public C fillIdempotent(C S); /** * Regular ring element fill with one. * @return fill this with one. */ public C fillOne(); } jas-2.5/src/edu/jas/structure/FieldFactory.java0000644000175000017500000000044512004300754021740 0ustar giovannigiovanni/* * $Id: FieldFactory.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Field factory interface. Defines test for field and access of characteristic. * @author Heinz Kredel */ public interface FieldFactory> extends RingFactory { } jas-2.5/src/edu/jas/structure/GcdRingElem.java0000644000175000017500000000061512004300754021504 0ustar giovannigiovanni/* * $Id: GcdRingElem.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Gcd ring element interface. Empty interface since gcd and egcd is now in * RingElem. Adds greatest common divisor and extended greatest common divisor. * @param gcd element type * @author Heinz Kredel */ public interface GcdRingElem> extends RingElem { } jas-2.5/src/edu/jas/structure/StarRingElem.java0000644000175000017500000000075312004300754021723 0ustar giovannigiovanni/* * $Id: StarRingElem.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Star ring element interface. Defines norm and conjugation. * @param ring element type * @author Heinz Kredel */ public interface StarRingElem> extends RingElem { /** * Conjugate of this. * @return conj(this). */ public C conjugate(); /** * Norm of this. * @return norm(this). */ public C norm(); } jas-2.5/src/edu/jas/structure/Selector.java0000644000175000017500000000055711107614532021156 0ustar giovannigiovanni/* * $Id: Selector.java 2208 2008-11-15 18:47:54Z kredel $ */ package edu.jas.structure; /** * Selector interface. * @param ring element type * @author Heinz Kredel */ public interface Selector> { /** * Select. * @return true, if the element is selected, otherwise false. */ public boolean select(C c); } jas-2.5/src/edu/jas/structure/AlgebraFactory.java0000644000175000017500000000144512004300754022253 0ustar giovannigiovanni/* * $Id: AlgebraFactory.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; import java.util.List; /** * Algebra factory interface. Defines conversion from list of lists and sparse * random. * @param algebra type * @param coefficient type * @author Heinz Kredel */ public interface AlgebraFactory, C extends RingElem> extends RingFactory { /** * Convert list of list to matrix. * @param m list of list of ring elements. * @return a matrix with the elements from m. */ public A fromList(List> m); /** * Random Matrix. * @param k size of coefficients. * @param q fraction of non zero elements. * @return a random matrix. */ public A random(int k, float q); } jas-2.5/src/edu/jas/structure/BinaryFunctor.java0000644000175000017500000000070412004300754022150 0ustar giovannigiovanni/* * $Id: BinaryFunctor.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; /** * Binary functor interface. * @param element type * @param element type * @param element type * @author Heinz Kredel */ public interface BinaryFunctor, C2 extends Element, D extends Element> { /** * Evaluate. * @return evaluated element. */ public D eval(C1 c1, C2 c2); } jas-2.5/src/edu/jas/structure/ModulFactory.java0000644000175000017500000000143312004300754021773 0ustar giovannigiovanni/* * $Id: ModulFactory.java 4056 2012-07-26 17:44:13Z kredel $ */ package edu.jas.structure; import java.util.List; /** * Module factory interface. Defines conversion from list and sparse random. * @param module type * @param coefficient type * @author Heinz Kredel */ public interface ModulFactory, C extends RingElem> extends AbelianGroupFactory { /** * Convert list to module. * @param v list of ring elements. * @return a module element with the elements from v. */ public M fromList(List v); /** * Random vector. * @param k size of coefficients. * @param q fraction of non zero elements. * @return a random vector. */ public M random(int k, float q); } jas-2.5/src/edu/jas/arith/0000755000175000017500000000000012140140254015564 5ustar giovannigiovannijas-2.5/src/edu/jas/arith/ModIntegerRing.java0000644000175000017500000002447512013666170021331 0ustar giovannigiovanni/* * $Id: ModIntegerRing.java 4105 2012-08-18 10:20:41Z kredel $ */ package edu.jas.arith; import java.io.Reader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; import edu.jas.kern.StringUtil; /** * ModIntegerRing factory with RingFactory interface. Effectively immutable. * @author Heinz Kredel */ public final class ModIntegerRing implements ModularRingFactory, Iterable { /** * Module part of the factory data structure. */ public final java.math.BigInteger modul; private final static Random random = new Random(); /** * Indicator if this ring is a field. */ private int isField = -1; // initially unknown /** * Certainty if module is probable prime. */ private int certainty = 10; /** * The constructor creates a ModIntegerRing object from a BigInteger object * as module part. * @param m math.BigInteger. */ public ModIntegerRing(java.math.BigInteger m) { modul = m; } /** * The constructor creates a ModIntegerRing object from a BigInteger object * as module part. * @param m math.BigInteger. * @param isField indicator if m is prime. */ public ModIntegerRing(java.math.BigInteger m, boolean isField) { modul = m; this.isField = (isField ? 1 : 0); } /** * The constructor creates a ModIntegerRing object from a long as module * part. * @param m long. */ public ModIntegerRing(long m) { this(new java.math.BigInteger(String.valueOf(m))); } /** * The constructor creates a ModIntegerRing object from a long as module * part. * @param m long. * @param isField indicator if m is prime. */ public ModIntegerRing(long m, boolean isField) { this(new java.math.BigInteger(String.valueOf(m)), isField); } /** * The constructor creates a ModIntegerRing object from a String object as * module part. * @param m String. */ public ModIntegerRing(String m) { this(new java.math.BigInteger(m.trim())); } /** * The constructor creates a ModIntegerRing object from a String object as * module part. * @param m String. * @param isField indicator if m is prime. */ public ModIntegerRing(String m, boolean isField) { this(new java.math.BigInteger(m.trim()), isField); } /** * Get the module part. * @return modul. */ public java.math.BigInteger getModul() { return modul; } /** * Get the module part as BigInteger. * @return modul. */ public BigInteger getIntegerModul() { return new BigInteger(modul); } /** * Create ModInteger element c. * @param c * @return a ModInteger of c. */ public ModInteger create(java.math.BigInteger c) { return new ModInteger(this, c); } /** * Create ModInteger element c. * @param c * @return a ModInteger of c. */ public ModInteger create(long c) { return new ModInteger(this, c); } /** * Create ModInteger element c. * @param c * @return a ModInteger of c. */ public ModInteger create(String c) { return parse(c); } /** * Copy ModInteger element c. * @param c * @return a copy of c. */ public ModInteger copy(ModInteger c) { return new ModInteger(this, c.val); } /** * Get the zero element. * @return 0 as ModInteger. */ public ModInteger getZERO() { return new ModInteger(this, java.math.BigInteger.ZERO); } /** * Get the one element. * @return 1 as ModInteger. */ public ModInteger getONE() { return new ModInteger(this, java.math.BigInteger.ONE); } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List generators() { List g = new ArrayList(1); g.add(getONE()); return g; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return true; } /** * Query if this ring is commutative. * @return true. */ public boolean isCommutative() { return true; } /** * Query if this ring is associative. * @return true. */ public boolean isAssociative() { return true; } /** * Query if this ring is a field. * @return true if module is prime, else false. */ public boolean isField() { if (isField > 0) { return true; } if (isField == 0) { return false; } //System.out.println("isProbablePrime " + modul + " = " + modul.isProbablePrime(certainty)); // if ( modul.isProbablePrime(certainty) ) { if (modul.isProbablePrime(modul.bitLength())) { isField = 1; return true; } isField = 0; return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return modul; } /** * Get a ModInteger element from a BigInteger value. * @param a BigInteger. * @return a ModInteger. */ public ModInteger fromInteger(java.math.BigInteger a) { return new ModInteger(this, a); } /** * Get a ModInteger element from a long value. * @param a long. * @return a ModInteger. */ public ModInteger fromInteger(long a) { return new ModInteger(this, a); } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return " bigMod(" + modul.toString() + ")"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python and Ruby case if (isField()) { return "GF(" + modul.toString() + ")"; } return "ZM(" + modul.toString() + ")"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object b) { if (!(b instanceof ModIntegerRing)) { return false; } ModIntegerRing m = (ModIntegerRing) b; return (0 == modul.compareTo(m.modul)); } /** * Hash code for this ModIntegerRing. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return modul.hashCode(); } /** * ModInteger random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random integer mod modul. */ public ModInteger random(int n) { return random(n, random); } /** * ModInteger random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random integer mod modul. */ public ModInteger random(int n, Random rnd) { java.math.BigInteger v = new java.math.BigInteger(n, rnd); return new ModInteger(this, v); } /** * Parse ModInteger from String. * @param s String. * @return ModInteger from s. */ public ModInteger parse(String s) { return new ModInteger(this, s); } /** * Parse ModInteger from Reader. * @param r Reader. * @return next ModInteger from r. */ public ModInteger parse(Reader r) { return parse(StringUtil.nextString(r)); } /** * ModInteger chinese remainder algorithm. This is a factory method. Assert * c.modul >= a.modul and c.modul * a.modul = this.modul. * @param c ModInteger. * @param ci inverse of c.modul in ring of a. * @param a other ModInteger. * @return S, with S mod c.modul == c and S mod a.modul == a. */ public ModInteger chineseRemainder(ModInteger c, ModInteger ci, ModInteger a) { //if (false) { // debug // if (c.ring.modul.compareTo(a.ring.modul) < 1) { // System.out.println("ModInteger error " + c + ", " + a); // } //} ModInteger b = a.ring.fromInteger(c.val); // c mod a.modul ModInteger d = a.subtract(b); // a-c mod a.modul if (d.isZERO()) { return fromInteger(c.val); } b = d.multiply(ci); // b = (a-c)*ci mod a.modul // (c.modul*b)+c mod this.modul = c mod c.modul = // (c.modul*ci*(a-c)+c) mod a.modul = a mod a.modul java.math.BigInteger s = c.ring.modul.multiply(b.val); s = s.add(c.val); return fromInteger(s); } /** * Get a ModInteger iterator. * @return a iterator over all modular integers in this ring. */ public Iterator iterator() { return new ModIntegerIterator(this); } } /** * Modular integer iterator. * @author Heinz Kredel */ class ModIntegerIterator implements Iterator { /** * data structure. */ java.math.BigInteger curr; final ModIntegerRing ring; /** * ModInteger iterator constructor. * @param fac modular integer factory; */ public ModIntegerIterator(ModIntegerRing fac) { curr = java.math.BigInteger.ZERO; ring = fac; } /** * Test for availability of a next element. * @return true if the iteration has more elements, else false. */ public synchronized boolean hasNext() { return curr.compareTo(ring.modul) < 0; } /** * Get next integer. * @return next integer. */ public synchronized ModInteger next() { ModInteger i = new ModInteger(ring, curr); curr = curr.add(java.math.BigInteger.ONE); return i; } /** * Remove an element if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove elements"); } } jas-2.5/src/edu/jas/arith/package.html0000644000175000017500000000210011672466542020062 0ustar giovannigiovanni Basic arithmetic package

Basic arithmetic package.

This package contains classes for arithmetic in the basic coefficient rings, e.g. BigRational, BigInteger, ModLong or ModInteger. All such classes implement the RingElem respectively the GcdRingElem interface. The class PrimeList provides a list of useful prime numbers. The Product class implements a finite product of other ring elements.


Heinz Kredel

Last modified: Thu Dec 15 22:56:05 CET 2011

$Id: package.html 3827 2011-12-15 21:57:54Z kredel $

jas-2.5/src/edu/jas/arith/BigOctonion.java0000644000175000017500000004555012014234362020656 0ustar giovannigiovanni/* * $Id: BigOctonion.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.arith; import java.io.Reader; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.StringUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.StarRingElem; /** * BigOctonion class based on BigRational implementing the RingElem interface * and with the familiar MAS static method names. Objects of this class are * immutable. * @author Heinz Kredel */ public final class BigOctonion implements StarRingElem, GcdRingElem, RingFactory { /** * First part of the data structure. */ public final BigQuaternion or; /** * Second part of the data structure. */ public final BigQuaternion oi; private final static Random random = new Random(); private static final Logger logger = Logger.getLogger(BigOctonion.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor for a BigOctonion from Quaternions. * @param r BigQuaternion. * @param i BigQuaternion. */ public BigOctonion(BigQuaternion r, BigQuaternion i) { this.or = r; this.oi = i; } /** * Constructor for a BigOctonion from BigQuaternion. * @param r BigQuaternion. */ public BigOctonion(BigQuaternion r) { this(r, BigQuaternion.ZERO); } /** * Constructor for a BigOctonion from BigComplex. * @param r BigComplex. */ public BigOctonion(BigComplex r) { this(new BigQuaternion(r)); } /** * Constructor for a BigOctonion from BigRational. * @param r BigRational. */ public BigOctonion(BigRational r) { this(new BigQuaternion(r)); } /** * Constructor for a BigOctonion from long. * @param r long. */ public BigOctonion(long r) { this(new BigQuaternion(r)); } /** * Constructor for a BigOctonion with no arguments. */ public BigOctonion() { this(BigQuaternion.ZERO); } /** * The BigOctonion string constructor accepts the following formats: empty * string, "quaternion", or "quat o quat" with no blanks around o if used as * polynoial coefficient. * @param s String. * @throws NumberFormatException */ public BigOctonion(String s) throws NumberFormatException { if (s == null || s.length() == 0) { or = ZERO.or; oi = ZERO.oi; return; } s = s.trim(); int o = s.indexOf("o"); if (o == -1) { or = new BigQuaternion(s); oi = ZERO.oi; return; } String sr = s.substring(0, o - 1); String so = s.substring(o + 1, s.length()); or = new BigQuaternion(sr.trim()); oi = new BigQuaternion(so.trim()); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public BigOctonion factory() { return this; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List generators() { List qg = or.generators(); List g = new ArrayList(qg.size() * 2); for (BigQuaternion q : qg) { g.add(new BigOctonion(q)); } for (BigQuaternion q : qg) { g.add(new BigOctonion(BigQuaternion.ZERO, q)); } return g; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return false; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public BigOctonion copy() { return new BigOctonion(or, oi); } /** * Copy BigOctonion element c. * @param c BigOctonion. * @return a copy of c. */ public BigOctonion copy(BigOctonion c) { if (c == null) { return new BigOctonion(); } return new BigOctonion(c.or, c.oi); } /** * Get the zero element. * @return 0 as BigOctonion. */ public BigOctonion getZERO() { return ZERO; } /** * Get the one element. * @return q as BigOctonion. */ public BigOctonion getONE() { return ONE; } /** * Query if this ring is commutative. * @return false. */ public boolean isCommutative() { return false; } /** * Query if this ring is associative. * @return false. */ public boolean isAssociative() { return false; } /** * Query if this ring is a field. * @return true. */ public boolean isField() { return true; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return java.math.BigInteger.ZERO; } /** * Get a BigOctonion element from a BigInteger. * @param a BigInteger. * @return a BigOctonion. */ public BigOctonion fromInteger(BigInteger a) { return new BigOctonion(ONE.or.fromInteger(a)); } /** * Get a BigOctonion element from a long. * @param a long. * @return a BigOctonion. */ public BigOctonion fromInteger(long a) { return new BigOctonion(ONE.or.fromInteger(a)); } /** * The constant 0. */ public static final BigOctonion ZERO = new BigOctonion(); /** * The constant 1. */ public static final BigOctonion ONE = new BigOctonion(BigQuaternion.ONE); /** * The constant i. */ public static final BigOctonion I = new BigOctonion(BigQuaternion.ZERO, BigQuaternion.ONE); /** * Get the or part. * @return or. */ public BigQuaternion getR() { return or; } /** * Get the oi part. * @return oi. */ public BigQuaternion getI() { return oi; } /** * Get the string representation. Is compatible with the string constructor. * @see java.lang.Object#toString() */ @Override public String toString() { String s = "" + or; int i = oi.compareTo(BigQuaternion.ZERO); if (debug) { logger.debug("compareTo " + i + " ? 0 = " + oi); } if (i == 0) return s; s += "o" + oi; return s; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case boolean i = oi.isZERO(); if (i && or.isZERO()) { return "0 "; } StringBuffer s = new StringBuffer(); if (!or.isZERO()) { String rs = or.toScript(); rs = rs.replaceAll("Q", "OR"); s.append(rs); s.append(" "); } if (!i) { if (s.length() > 0) { s.append("+ "); } String is = oi.toScript(); is = is.replaceAll("Q", "OI"); s.append(is); } return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return "Oct()"; } /** * Is Octonion number zero. * @param A BigOctonion. * @return true if A is 0, else false. */ public static boolean isOZERO(BigOctonion A) { if (A == null) return false; return A.isZERO(); } /** * Is BigOctonion number zero. * @return true if this is 0, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return or.equals(BigQuaternion.ZERO) && oi.equals(BigQuaternion.ZERO); } /** * Is BigOctonion number one. * @param A is a quaternion number. * @return true if A is 1, else false. */ public static boolean isOONE(BigOctonion A) { if (A == null) return false; return A.isONE(); } /** * Is BigOctonion number one. * @see edu.jas.structure.RingElem#isONE() * @return true if this is 1, else false. */ public boolean isONE() { return or.equals(BigQuaternion.ONE) && oi.equals(BigQuaternion.ZERO); } /** * Is BigOctonion imaginary one. * @return true if this is i, else false. */ public boolean isIMAG() { return or.equals(BigQuaternion.ZERO) && oi.equals(BigQuaternion.ONE); } /** * Is BigOctonion unit element. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { return (!isZERO()); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object b) { if (!(b instanceof BigOctonion)) return false; BigOctonion B = (BigOctonion) b; return or.equals(B.or) && oi.equals(B.oi); } /** * Hash code for this BigOctonion. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = 41 * or.hashCode(); h += 41 * oi.hashCode(); return h; } /** * Since quaternion numbers are unordered, we use lexicographical order of * re, im, jm and km. * @param b BigOctonion. * @return 0 if b is equal to this, 1 if this is greater b and -1 else. */ //JAVA6only: @Override public int compareTo(BigOctonion b) { int s = or.compareTo(b.or); if (s != 0) { return s; } return oi.compareTo(b.oi); } /** * Since quaternion numbers are unordered, we use lexicographical order of * re, im, jm and km. * @return 0 if this is equal to 0; 1 if or > 0, or or == 0 and oi > 0; -1 * if or < 0, or or == 0 and oi < 0. * @see edu.jas.structure.RingElem#signum() */ public int signum() { int s = or.signum(); if (s != 0) { return s; } return oi.signum(); } /* arithmetic operations: +, -, - */ /** * BigOctonion summation. * @param B BigOctonion. * @return this+B. */ public BigOctonion sum(BigOctonion B) { return new BigOctonion(or.sum(B.or), oi.sum(B.oi)); } /** * Octonion number sum. * @param A BigOctonion. * @param B BigOctonion. * @return A+B. */ public static BigOctonion OSUM(BigOctonion A, BigOctonion B) { if (A == null) return null; return A.sum(B); } /** * Octonion number difference. * @param A BigOctonion. * @param B BigOctonion. * @return A-B. */ public static BigOctonion ODIF(BigOctonion A, BigOctonion B) { if (A == null) return null; return A.subtract(B); } /** * BigOctonion subtraction. * @param B BigOctonion. * @return this-B. */ public BigOctonion subtract(BigOctonion B) { return new BigOctonion(or.subtract(B.or), oi.subtract(B.oi)); } /** * Octonion number negative. * @param A is a octonion number * @return -A. */ public static BigOctonion ONEG(BigOctonion A) { if (A == null) return null; return A.negate(); } /** * BigOctonion number negative. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public BigOctonion negate() { return new BigOctonion(or.negate(), oi.negate()); } /** * Octonion number conjugate. * @param A is a quaternion number. * @return the quaternion conjugate of A. */ public static BigOctonion OCON(BigOctonion A) { if (A == null) return null; return A.conjugate(); } /* arithmetic operations: conjugate, absolute value */ /** * BigOctonion conjugate. * @return conjugate(this). */ public BigOctonion conjugate() { return new BigOctonion(or.conjugate(), oi.negate()); } /** * Octonion number norm. * @see edu.jas.structure.StarRingElem#norm() * @return ||this||. */ public BigOctonion norm() { // this.conjugate().multiply(this); BigQuaternion v = or.norm(); v = v.sum(oi.norm()); return new BigOctonion(v); } /** * Octonion number absolute value. * @see edu.jas.structure.RingElem#abs() * @return |this|^2. Note: The square root is not jet implemented. */ public BigOctonion abs() { BigOctonion n = norm(); logger.error("abs() square root missing"); // n = n.sqrt(); return n; } /** * Octonion number absolute value. * @param A is a quaternion number. * @return the absolute value of A, a rational number. Note: The square root * is not jet implemented. */ public static BigRational OABS(BigOctonion A) { if (A == null) return null; return A.abs().or.re; } /** * Octonion number product. * @param A BigOctonion. * @param B BigOctonion. * @return A*B. */ public static BigOctonion OPROD(BigOctonion A, BigOctonion B) { if (A == null) return null; return A.multiply(B); } /* arithmetic operations: *, inverse, / */ /** * BigOctonion multiply. * @param B BigOctonion. * @return this*B. */ public BigOctonion multiply(BigOctonion B) { // (r1,i1)(r2,i2) = ( r1 r2 - i2 i1^, r1^ i2 + r2 i1 ) Baez, jas // (r1,i1)(r2,i2) = ( r1 r2 - i2^ i1, i1 r2^ + i2 r1 ) Dieudonne, mas BigQuaternion r = or.multiply(B.or); r = r.subtract(B.oi.multiply(oi.conjugate())); BigQuaternion i = or.conjugate().multiply(B.oi); i = i.sum(B.or.multiply(oi)); return new BigOctonion(r, i); } /** * Octonion number inverse. * @param A is a non-zero quaternion number. * @return S with S * A = 1. */ public static BigOctonion OINV(BigOctonion A) { if (A == null) return null; return A.inverse(); } /** * BigOctonion inverse. * @return S with S * this = 1. * @see edu.jas.structure.RingElem#inverse() */ public BigOctonion inverse() { BigRational a = norm().or.re; return conjugate().divide(a); } /** * BigOctonion remainder. * @param S BigOctonion. * @return 0. */ public BigOctonion remainder(BigOctonion S) { if (S.isZERO()) { throw new ArithmeticException("division by zero"); } return ZERO; } /** * Octonion number quotient. * @param A BigOctonion. * @param B BigOctonion. * @return R/S. */ public static BigOctonion OQ(BigOctonion A, BigOctonion B) { if (A == null) return null; return A.divide(B); } /** * BigOctonion divide. * @param b BigOctonion. * @return this/b. */ public BigOctonion divide(BigOctonion b) { return this.multiply(b.inverse()); } /** * BigOctonion divide. * @param b BigRational. * @return this/b. */ public BigOctonion divide(BigRational b) { // BigRational bi = b.inverse(); return new BigOctonion(or.divide(b), oi.divide(b)); } /** * BigOctonion random. Random rational numbers A, B, C and D are generated * using random(n). Then R is the quaternion number with real part A and * imaginary parts B, C and D. * @param n such that 0 ≤ A, B, C, D ≤ (2n-1). * @return R, a random BigOctonion. */ public BigOctonion random(int n) { return random(n, random); } /** * BigOctonion random. Random rational numbers A, B, C and D are generated * using RNRAND(n). Then R is the quaternion number with real part A and * imaginary parts B, C and D. * @param n such that 0 ≤ A, B, C, D ≤ (2n-1). * @param rnd is a source for random bits. * @return R, a random BigOctonion. */ public BigOctonion random(int n, Random rnd) { BigQuaternion rr = BigQuaternion.ONE.random(n, rnd); BigQuaternion ir = BigQuaternion.ONE.random(n, rnd); return new BigOctonion(rr, ir); } /** * Octonion number, random. Random rational numbers A, B, C and D are * generated using RNRAND(n). Then R is the quaternion number with real part * A and imaginary parts B, C and D. * @param n such that 0 ≤ A, B, C, D ≤ (2n-1). * @return R, a random BigOctonion. */ public static BigOctonion ORAND(int n) { return ONE.random(n, random); } /** * Parse quaternion number from String. * @param s String. * @return BigOctonion from s. */ public BigOctonion parse(String s) { return new BigOctonion(s); } /** * Parse quaternion number from Reader. * @param r Reader. * @return next BigOctonion from r. */ public BigOctonion parse(Reader r) { return parse(StringUtil.nextString(r)); } /** * Octonion number greatest common divisor. * @param S BigOctonion. * @return gcd(this,S). */ public BigOctonion gcd(BigOctonion S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } return ONE; } /** * BigOctonion extended greatest common divisor. * @param S BigOctonion. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ public BigOctonion[] egcd(BigOctonion S) { BigOctonion[] ret = new BigOctonion[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; return ret; } if (this.isZERO()) { ret[0] = S; return ret; } BigOctonion half = new BigOctonion(new BigRational(1, 2)); ret[0] = ONE; ret[1] = this.inverse().multiply(half); ret[2] = S.inverse().multiply(half); return ret; } } jas-2.5/src/edu/jas/arith/ModularRingFactory.java0000644000175000017500000000157611460603360022221 0ustar giovannigiovanni/* * $Id: ModularRingFactory.java 3355 2010-10-23 16:01:52Z kredel $ */ package edu.jas.arith; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Modular ring factory interface. Defines chinese remainder method and get * modul method. * @author Heinz Kredel */ public interface ModularRingFactory & Modular> extends RingFactory { /** * Return the BigInteger modul for the factory. * @return a BigInteger of this.modul. */ public BigInteger getIntegerModul(); /** * Chinese remainder algorithm. Assert c.modul >= a.modul and c.modul * * a.modul = this.modul. * @param c modular. * @param ci inverse of c.modul in ring of a. * @param a other ModLong. * @return S, with S mod c.modul == c and S mod a.modul == a. */ public C chineseRemainder(C c, C ci, C a); } jas-2.5/src/edu/jas/arith/Roots.java0000644000175000017500000001610712004277700017550 0ustar giovannigiovanni/* * $Id: Roots.java 4054 2012-07-26 17:34:57Z kredel $ */ package edu.jas.arith; // import java.util.Random; import java.math.MathContext; import edu.jas.structure.Power; /** * Root computation algorithms. Roots for BigInteger and BigDecimals. * @author Heinz Kredel */ public class Roots { /** * Integer n-th root. Uses BigDecimal and newton iteration. R is the n-th * root of A. * @param A big integer. * @param n long. * @return the n-th root of A. */ public static BigInteger root(BigInteger A, int n) { if (n == 1) { return A; } if (n == 2) { return sqrt(A); } if (n < 1) { throw new IllegalArgumentException("negative root not defined"); } if (A == null || A.isZERO() || A.isONE()) { return A; } // ensure enough precision int s = A.val.bitLength() + 2; MathContext mc = new MathContext(s); //System.out.println("mc = " + mc); BigDecimal Ap = new BigDecimal(A.val, mc); //System.out.println("Ap = " + Ap); BigDecimal Ar = root(Ap, n); //System.out.println("Ar = " + Ar); java.math.BigInteger RP = Ar.val.toBigInteger(); BigInteger R = new BigInteger(RP); while (true) { BigInteger P = Power.positivePower(R, n); //System.out.println("P = " + P); if (A.compareTo(P) >= 0) { break; } R = R.subtract(BigInteger.ONE); } return R; } /** * Integer square root. Uses BigDecimal and newton iteration. R is the * square root of A. * @param A big integer. * @return the square root of A. */ public static BigInteger sqrt(BigInteger A) { if (A == null || A.isZERO() || A.isONE()) { return A; } // ensure enough precision int s = A.val.bitLength() + 2; MathContext mc = new MathContext(s); //System.out.println("mc = " + mc); // newton iteration BigDecimal Ap = new BigDecimal(A.val, mc); //System.out.println("Ap = " + Ap); BigDecimal Ar = sqrt(Ap); //System.out.println("Ar = " + Ar); java.math.BigInteger RP = Ar.val.toBigInteger(); BigInteger R = new BigInteger(RP); while (true) { BigInteger P = R.multiply(R); //System.out.println("P = " + P); if (A.compareTo(P) >= 0) { break; } R = R.subtract(BigInteger.ONE); } return R; } /** * Integer square root. Uses BigInteger only. R is the square root of A. * @param A big integer. * @return the square root of A. */ public static BigInteger sqrtInt(BigInteger A) { if (A == null || A.isZERO() || A.isONE()) { return A; } int s = A.signum(); if (s < 0) { throw new ArithmeticException("root of negative not defined"); } if (s == 0) { return A; } BigInteger R, R1, d; int log2 = A.val.bitLength(); //System.out.println("A = " + A + ", log2 = " + log2); int rootlog2 = log2 - log2 / 2; R = new BigInteger(A.val.shiftRight(rootlog2)); //System.out.println("R = " + R + ", rootlog2 = " + rootlog2); d = R; while (!d.isZERO()) { d = new BigInteger(d.val.shiftRight(1)); // div 2 R1 = R.sum(d); s = A.compareTo(R1.multiply(R1)); if (s == 0) { return R1; } if (s > 0) { R = R1; } //System.out.println("R1 = " + R1); //System.out.println("d = " + d); } while (true) { R1 = R.sum(BigInteger.ONE); //System.out.println("R1 = " + R1); s = A.compareTo(R1.multiply(R1)); if (s == 0) { return R1; } if (s > 0) { R = R1; } if (s < 0) { return R; } } //return R; } /** * Square root. R is the square root of A. * @param A big decimal. * @return the square root of A. */ public static BigDecimal sqrt(BigDecimal A) { if (A == null || A.isZERO() || A.isONE()) { return A; } // for small A use root of inverse if (A.val.compareTo(BigDecimal.ONE.val) < 0) { BigDecimal Ap = A.inverse(); //System.out.println("A.inverse() = " + Ap); Ap = sqrt(Ap); return Ap.inverse(); } MathContext mc = A.context; // newton iteration BigDecimal Ap = new BigDecimal(A.val, mc); BigDecimal ninv = new BigDecimal(0.5, mc); BigDecimal R1, R = Ap.multiply(ninv); // initial guess BigDecimal d; while (true) { R1 = R.sum(Ap.divide(R)); R1 = R1.multiply(ninv); // div n d = R.subtract(R1).abs(); R = R1; if (d.val.compareTo(BigDecimal.ONE.val) <= 0) { //System.out.println("d = " + d); break; } } return R; } /** * N-th root. R is the n-th root of A. * @param A big decimal. * @param n long. * @return the n-th root of A. */ public static BigDecimal root(BigDecimal A, int n) { if (n == 1) { return A; } if (n == 2) { return sqrt(A); } if (n < 1) { throw new IllegalArgumentException("negative root not defined"); } if (A == null || A.isZERO() || A.isONE()) { return A; } // for small A use root of inverse if (A.val.compareTo(BigDecimal.ONE.val) < 0) { BigDecimal Ap = A.inverse(); //System.out.println("A.inverse() = " + Ap); Ap = root(Ap, n); return Ap.inverse(); } // ensure enough precision MathContext mc = A.context; // newton iteration BigDecimal Ap = A; BigDecimal N = new BigDecimal(n, mc); BigDecimal ninv = new BigDecimal(1.0 / n, mc); BigDecimal nsub = new BigDecimal(1.0, mc); // because of precision nsub = nsub.subtract(ninv); //BigDecimal half = BigDecimal.ONE.sum(BigDecimal.ONE).inverse(); BigDecimal half = new BigDecimal(BigDecimal.ONE.val.divide(java.math.BigDecimal.TEN)); BigDecimal P, R1, R = Ap.multiply(ninv); // initial guess BigDecimal d; while (true) { P = Power.positivePower(R, n - 1); R1 = Ap.divide(P.multiply(N)); R1 = R.multiply(nsub).sum(R1); d = R.subtract(R1).abs(); R = R1; //if ( d.compareTo( BigDecimal.ONE ) <= 0 ) { // System.out.println("d = " + d); if (d.val.compareTo(half.val) <= 0) { //System.out.println("d.val = " + d.val); break; } //} } return R; } } jas-2.5/src/edu/jas/arith/BigInteger.java0000644000175000017500000004417112014234362020461 0ustar giovannigiovanni/* * $Id: BigInteger.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.arith; import java.io.Reader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; import edu.jas.kern.StringUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * BigInteger class to make java.math.BigInteger available with RingElem * respectively the GcdRingElem interface. Objects of this class are immutable. * The SAC2 static methods are also provided. * @author Heinz Kredel * @see java.math.BigInteger */ public final class BigInteger implements GcdRingElem, RingFactory, Iterable, Rational { /** * The data structure. */ public final java.math.BigInteger val; private final static Random random = new Random(); /** * The constant 0. */ public final static BigInteger ZERO = new BigInteger(java.math.BigInteger.ZERO); /** * The constant 1. */ public final static BigInteger ONE = new BigInteger(java.math.BigInteger.ONE); /** * Constructor for BigInteger from math.BigInteger. * @param a java.math.BigInteger. */ public BigInteger(java.math.BigInteger a) { val = a; } /** * Constructor for BigInteger from long. * @param a long. */ public BigInteger(long a) { val = new java.math.BigInteger(String.valueOf(a)); } /** * Constructor for BigInteger from String. * @param s String. */ public BigInteger(String s) { val = new java.math.BigInteger(s.trim()); } /** * Constructor for BigInteger without parameters. */ public BigInteger() { val = java.math.BigInteger.ZERO; } /** * Get the value. * @return val java.math.BigInteger. */ public java.math.BigInteger getVal() { return val; } /** * Get the value as long. * @return val as long. */ public long longValue() { return val.longValue(); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public BigInteger factory() { return this; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List generators() { List g = new ArrayList(1); g.add(getONE()); return g; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return false; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public BigInteger copy() { return new BigInteger(val); } /** * Copy BigInteger element c. * @param c BigInteger. * @return a copy of c. */ public BigInteger copy(BigInteger c) { return new BigInteger(c.val); } /** * Get the zero element. * @return 0. */ public BigInteger getZERO() { return ZERO; } /** * Get the one element. * @return 1. */ public BigInteger getONE() { return ONE; } /** * Query if this ring is commutative. * @return true. */ public boolean isCommutative() { return true; } /** * Query if this ring is associative. * @return true. */ public boolean isAssociative() { return true; } /** * Query if this ring is a field. * @return false. */ public boolean isField() { return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return java.math.BigInteger.ZERO; } /** * Get a BigInteger element from a math.BigInteger. * @param a math.BigInteger. * @return a as BigInteger. */ public BigInteger fromInteger(java.math.BigInteger a) { return new BigInteger(a); } /** * Get a BigInteger element from a math.BigInteger. * @param a math.BigInteger. * @return a as BigInteger. */ public static BigInteger valueOf(java.math.BigInteger a) { return new BigInteger(a); } /** * Get a BigInteger element from long. * @param a long. * @return a as BigInteger. */ public BigInteger fromInteger(long a) { return new BigInteger(a); } /** * Get a BigInteger element from long. * @param a long. * @return a as BigInteger. */ public static BigInteger valueOf(long a) { return new BigInteger(a); } /** * Is BigInteger number zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return val.equals(java.math.BigInteger.ZERO); } /** * Is BigInteger number one. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return val.equals(java.math.BigInteger.ONE); } /** * Is BigInteger number unit. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { return (this.isONE() || this.negate().isONE()); } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return val.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return "ZZ()"; } /** * Compare to BigInteger b. * @param b BigInteger. * @return 0 if this == b, 1 if this > b, -1 if this < b. */ //JAVA6only: @Override public int compareTo(BigInteger b) { return val.compareTo(b.val); } /** * Integer comparison. * @param A BigInteger. * @param B BigInteger. * @return 0 if A == B, 1 if A > B, -1 if A < B. */ public static int ICOMP(BigInteger A, BigInteger B) { if (A == null) return -B.signum(); return A.compareTo(B); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object b) { if (!(b instanceof BigInteger)) { return false; } BigInteger bi = (BigInteger) b; return val.equals(bi.val); } /** * Hash code for this BigInteger. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return val.hashCode(); } /** * Absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public BigInteger abs() { return new BigInteger(val.abs()); } /** * Absolute value. * @param A BigInteger. * @return abs(A). */ public static BigInteger IABS(BigInteger A) { if (A == null) { throw new IllegalArgumentException("null A not allowed"); } return A.abs(); } /* Negative value of this. * @see edu.jas.structure.RingElem#negate() */ public BigInteger negate() { return new BigInteger(val.negate()); } /** * Negative value. * @param A BigInteger. * @return -A. */ public static BigInteger INEG(BigInteger A) { if (A == null) { throw new IllegalArgumentException("null A not allowed"); } return A.negate(); } /** * signum. * @see edu.jas.structure.RingElem#signum() */ public int signum() { return val.signum(); } /** * Integer signum. * @param A BigInteger. * @return signum(A). */ public static int ISIGN(BigInteger A) { if (A == null) return 0; return A.signum(); } /** * BigInteger subtract. * @param S BigInteger. * @return this-S. */ public BigInteger subtract(BigInteger S) { return new BigInteger(val.subtract(S.val)); } /** * BigInteger subtract. * @param A BigInteger. * @param B BigInteger. * @return A-B. */ public static BigInteger IDIF(BigInteger A, BigInteger B) { if (A == null) return B.negate(); return A.subtract(B); } /** * BigInteger divide. * @param S BigInteger. * @return this/S. */ public BigInteger divide(BigInteger S) { return new BigInteger(val.divide(S.val)); } /** * BigInteger divide. * @param A BigInteger. * @param B BigInteger. * @return A/B. */ public static BigInteger IQ(BigInteger A, BigInteger B) { if (A == null) { throw new IllegalArgumentException("null A not allowed"); } return A.divide(B); } /** * Integer inverse. R is a non-zero integer. S=1/R if defined else 0. * @see edu.jas.structure.RingElem#inverse() */ public BigInteger inverse() { if (this.isONE() || this.negate().isONE()) { return this; } return ZERO; } /** * BigInteger remainder. * @param S BigInteger. * @return this - (this/S)*S. */ public BigInteger remainder(BigInteger S) { return new BigInteger(val.remainder(S.val)); } /** * BigInteger remainder. * @param A BigInteger. * @param B BigInteger. * @return A - (A/B)*B. */ public static BigInteger IREM(BigInteger A, BigInteger B) { if (A == null) { throw new IllegalArgumentException("null A not allowed"); } return A.remainder(B); } /** * BigInteger compute quotient and remainder. Throws an exception, if S == * 0. * @param S BigInteger. * @return BigInteger[] { q, r } with this = q S + r and 0 ≤ r < |S|. */ //@Override public BigInteger[] quotientRemainder(BigInteger S) { BigInteger[] qr = new BigInteger[2]; java.math.BigInteger[] C = val.divideAndRemainder(S.val); qr[0] = new BigInteger(C[0]); qr[1] = new BigInteger(C[1]); return qr; } /** * BigInteger compute quotient and remainder. Throws an exception, if S == * 0. * @param S BigInteger. * @return BigInteger[] { q, r } with this = q S + r and 0 ≤ r < |S|. * @deprecated use quotientRemainder() */ @Deprecated public BigInteger[] divideAndRemainder(BigInteger S) { return quotientRemainder(S); } /** * Integer quotient and remainder. A and B are integers, B ne 0. Q is the * quotient, integral part of A/B, and R is the remainder A-B*Q. Throws an * exception, if B == 0. * @param A BigInteger. * @param B BigInteger. * @return BigInteger[] { q, r } with A = q B + r and 0 ≤ r < |B| */ public static BigInteger[] IQR(BigInteger A, BigInteger B) { if (A == null) { throw new IllegalArgumentException("null A not allowed"); } return A.quotientRemainder(B); } /** * BigInteger greatest common divisor. * @param S BigInteger. * @return gcd(this,S). */ public BigInteger gcd(BigInteger S) { return new BigInteger(val.gcd(S.val)); } /** * BigInteger extended greatest common divisor. * @param S BigInteger. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ public BigInteger[] egcd(BigInteger S) { BigInteger[] ret = new BigInteger[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; return ret; } if (this.isZERO()) { ret[0] = S; return ret; } //System.out.println("this = " + this + ", S = " + S); BigInteger[] qr; BigInteger q = this; BigInteger r = S; BigInteger c1 = ONE; BigInteger d1 = ZERO; BigInteger c2 = ZERO; BigInteger d2 = ONE; BigInteger x1; BigInteger x2; while (!r.isZERO()) { qr = q.quotientRemainder(r); q = qr[0]; x1 = c1.subtract(q.multiply(d1)); x2 = c2.subtract(q.multiply(d2)); c1 = d1; c2 = d2; d1 = x1; d2 = x2; q = r; r = qr[1]; } //System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2); if (q.signum() < 0) { q = q.negate(); c1 = c1.negate(); c2 = c2.negate(); } ret[0] = q; ret[1] = c1; ret[2] = c2; return ret; } /** * BigInteger greatest common divisor. * @param A BigInteger. * @param B BigInteger. * @return gcd(A,B). */ public static BigInteger IGCD(BigInteger A, BigInteger B) { if (A == null) { throw new IllegalArgumentException("null A not allowed"); } return A.gcd(B); } /** * BigInteger random. * @param n such that 0 ≤ r ≤ (2n-1). * @return r, a random BigInteger. */ public BigInteger random(int n) { return random(n, random); } /** * BigInteger random. * @param n such that 0 ≤ r ≤ (2n-1). * @param rnd is a source for random bits. * @return r, a random BigInteger. */ public BigInteger random(int n, Random rnd) { java.math.BigInteger r = new java.math.BigInteger(n, rnd); if (rnd.nextBoolean()) { r = r.negate(); } return new BigInteger(r); } /** * BigInteger random. * @param NL such that 0 ≤ r ≤ (2n-1). * @return r, a random BigInteger. */ public static BigInteger IRAND(int NL) { return ONE.random(NL, random); } /** * BigInteger multiply. * @param S BigInteger. * @return this*S. */ public BigInteger multiply(BigInteger S) { return new BigInteger(val.multiply(S.val)); } /** * BigInteger multiply. * @param A BigInteger. * @param B BigInteger. * @return A*B. */ public static BigInteger IPROD(BigInteger A, BigInteger B) { if (A == null) { throw new IllegalArgumentException("null A not allowed"); } return A.multiply(B); } /** * BigInteger summation. * @param S BigInteger. * @return this+S. */ public BigInteger sum(BigInteger S) { return new BigInteger(val.add(S.val)); } /** * BigInteger addition. * @param A BigInteger. * @param B BigInteger. * @return A+B. */ public static BigInteger ISUM(BigInteger A, BigInteger B) { if (A == null) { throw new IllegalArgumentException("null A not allowed"); } return A.sum(B); } /** * BigInteger parse from String. * @param s String. * @return Biginteger from s. */ public BigInteger parse(String s) { return new BigInteger(s); } /** * BigInteger parse from Reader. * @param r Reader. * @return next Biginteger from r. */ public BigInteger parse(Reader r) { return parse(StringUtil.nextString(r)); } /** * Return a BigRational approximation of this Element. * @return a BigRational approximation of this. */ public BigRational getRational() { return new BigRational(val); } private boolean nonNegative = true; /** * Set the iteration algorithm to all elements. */ public void setAllIterator() { nonNegative = false; } /** * Set the iteration algorithm to non-negative elements. */ public void setNonNegativeIterator() { nonNegative = true; } /** * Get a BigInteger iterator. * @return a iterator over all integers. */ public Iterator iterator() { return new BigIntegerIterator(nonNegative); } } /** * Big integer iterator. * @author Heinz Kredel */ class BigIntegerIterator implements Iterator { /** * data structure. */ java.math.BigInteger curr; final boolean nonNegative; /** * BigInteger iterator constructor. */ public BigIntegerIterator() { this(false); } /** * BigInteger iterator constructor. * @param nn true for an iterator over non-negative longs, false for all * elements iterator. */ public BigIntegerIterator(boolean nn) { curr = java.math.BigInteger.ZERO; nonNegative = nn; } /** * Test for availability of a next element. * @return true if the iteration has more elements, else false. */ public boolean hasNext() { return true; } /** * Get next integer. * @return next integer. */ public synchronized BigInteger next() { BigInteger i = new BigInteger(curr); if (nonNegative) { curr = curr.add(java.math.BigInteger.ONE); } else if (curr.signum() > 0 && !nonNegative) { curr = curr.negate(); } else { curr = curr.negate().add(java.math.BigInteger.ONE); } return i; } /** * Remove an element if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove elements"); } } jas-2.5/src/edu/jas/arith/BigRational.java0000644000175000017500000007725412014234362020645 0ustar giovannigiovanni/* * $Id: BigRational.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.arith; import java.io.Reader; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Set; import edu.jas.kern.Scripting; import edu.jas.kern.StringUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Immutable arbitrary-precision rational numbers. BigRational class based on * BigInteger and implementing the RingElem interface. BigInteger is from * java.math in the implementation. The SAC2 static methods are also provided. * @author Heinz Kredel */ public final class BigRational implements GcdRingElem, RingFactory, Rational, Iterable { /** * Numerator part of the data structure. */ public final BigInteger num; /** * Denominator part of the data structure. */ public final BigInteger den; /** * The Constant 0. */ public final static BigRational ZERO = new BigRational(BigInteger.ZERO); /** * The Constant 1. */ public final static BigRational ONE = new BigRational(BigInteger.ONE); private final static Random random = new Random(); /** * Constructor for a BigRational from math.BigIntegers. * @param n math.BigInteger. * @param d math.BigInteger. */ protected BigRational(BigInteger n, BigInteger d) { // assert gcd(n,d) == 1 num = n; den = d; } /** * Constructor for a BigRational from math.BigIntegers. * @param n math.BigInteger. */ public BigRational(BigInteger n) { num = n; den = BigInteger.ONE; // be aware of static initialization order //den = BigInteger.ONE; } /** * Constructor for a BigRational from jas.arith.BigIntegers. * @param n edu.jas.arith.BigInteger. */ public BigRational(edu.jas.arith.BigInteger n) { this(n.getVal()); } /** * Constructor for a BigRational from jas.arith.BigIntegers. * @param n edu.jas.arith.BigInteger. * @param d edu.jas.arith.BigInteger. */ public BigRational(edu.jas.arith.BigInteger n, edu.jas.arith.BigInteger d) { BigInteger nu = n.getVal(); BigInteger de = d.getVal(); BigRational r = RNRED(nu, de); num = r.num; den = r.den; } /** * Constructor for a BigRational from longs. * @param n long. * @param d long. */ public BigRational(long n, long d) { BigInteger nu = BigInteger.valueOf(n); BigInteger de = BigInteger.valueOf(d); BigRational r = RNRED(nu, de); num = r.num; den = r.den; } /** * Constructor for a BigRational from longs. * @param n long. */ public BigRational(long n) { num = BigInteger.valueOf(n); den = BigInteger.ONE; } /** * Constructor for a BigRational with no arguments. */ public BigRational() { num = BigInteger.ZERO; den = BigInteger.ONE; } /** * Constructor for a BigRational from String. * @param s String. * @throws NumberFormatException */ public BigRational(String s) throws NumberFormatException { if (s == null) { num = BigInteger.ZERO; den = BigInteger.ONE; return; } if (s.length() == 0) { num = BigInteger.ZERO; den = BigInteger.ONE; return; } BigInteger n; BigInteger d; s = s.trim(); int i = s.indexOf('/'); if (i < 0) { i = s.indexOf('.'); if (i < 0) { num = new BigInteger(s); den = BigInteger.ONE; return; } if (s.charAt(0) == '-') { // case -0.11111 n = new BigInteger(s.substring(1, i)); } else { n = new BigInteger(s.substring(0, i)); } BigRational r = new BigRational(n); d = new BigInteger(s.substring(i + 1, s.length())); int j = s.length() - i - 1; //System.out.println("j = " + j); //System.out.println("n = " + n); //System.out.println("d = " + d); BigRational z = new BigRational(1, 10); z = Power. positivePower(z, j); BigRational f = new BigRational(d); f = f.multiply(z); r = r.sum(f); if (s.charAt(0) == '-') { num = r.num.negate(); } else { num = r.num; } den = r.den; } else { n = new BigInteger(s.substring(0, i)); d = new BigInteger(s.substring(i + 1, s.length())); BigRational r = RNRED(n, d); num = r.num; den = r.den; return; } } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public BigRational factory() { return this; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List generators() { List g = new ArrayList(1); g.add(getONE()); return g; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return false; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public BigRational copy() { return new BigRational(num, den); } /** * Copy BigRational element c. * @param c BigRational. * @return a copy of c. */ public BigRational copy(BigRational c) { return new BigRational(c.num, c.den); } /** * Return a BigRational approximation of this Element. * @return a BigRational approximation of this. * @see edu.jas.arith.Rational#getRational() */ public BigRational getRational() { return this; } /** * Get the numerator. * @return num. */ public BigInteger numerator() { return num; } /** * Get the denominator. * @return den. */ public BigInteger denominator() { return den; } /** * Get the string representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer(); s.append(num); if (!den.equals(BigInteger.ONE)) { s.append("/").append(den); } return s.toString(); } /** * Get the decimal string representation with given precision. * @param n precission. * @return decimal approximation. */ public String toString(int n) { java.math.MathContext mc = new java.math.MathContext(n); BigDecimal d = new BigDecimal(this, mc); return d.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case: (num,den) or num // Ruby case: num/den or num StringBuffer s = new StringBuffer(); if (den.equals(BigInteger.ONE)) { s.append(num.toString()); return s.toString(); } switch (Scripting.getLang()) { case Python: s.append("("); s.append(num.toString()); s.append(","); s.append(den.toString()); s.append(")"); break; case Ruby: default: s.append(num.toString()); s.append("/"); s.append(den.toString()); } return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return "QQ()"; } /** * Get the zero element. * @return 0 as BigRational. */ public BigRational getZERO() { return ZERO; } /** * Get the one element. * @return 1 as BigRational. */ public BigRational getONE() { return ONE; } /** * Query if this ring is commutative. * @return true. */ public boolean isCommutative() { return true; } /** * Query if this ring is associative. * @return true. */ public boolean isAssociative() { return true; } /** * Query if this ring is a field. * @return true. */ public boolean isField() { return true; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return BigInteger.ZERO; } /** * Get a BigRational element from a math.BigInteger. * @param a math.BigInteger. * @return BigRational from a. */ public BigRational fromInteger(BigInteger a) { return new BigRational(a); } /** * Get a BigRational element from a arith.BigInteger. * @param a arith.BigInteger. * @return BigRational from a. */ public BigRational fromInteger(edu.jas.arith.BigInteger a) { return new BigRational(a); } /** * Get a BigRational element from a math.BigInteger. * @param a math.BigInteger. * @return BigRational from a. */ public static BigRational valueOf(BigInteger a) { return new BigRational(a); } /** * Get a BigRational element from a long. * @param a long. * @return BigRational from a. */ public BigRational fromInteger(long a) { return new BigRational(a); } /** * Get a BigRational element from a long. * @param a long. * @return BigRational from a. */ public static BigRational valueOf(long a) { return new BigRational(a); } /** * Is BigRational zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return num.equals(BigInteger.ZERO); } /** * Is BigRational one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return num.equals(den); } /** * Is BigRational unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { return (!isZERO()); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object b) { if (!(b instanceof BigRational)) { return false; } BigRational br = (BigRational) b; return num.equals(br.num) && den.equals(br.den); } /** * Hash code for this BigRational. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * num.hashCode() + den.hashCode(); } /** * Rational number reduction to lowest terms. * @param n BigInteger. * @param d BigInteger. * @return a/b ~ n/d, gcd(a,b) = 1, b > 0. */ public static BigRational RNRED(BigInteger n, BigInteger d) { BigInteger num; BigInteger den; if (n.equals(BigInteger.ZERO)) { num = n; den = BigInteger.ONE; return new BigRational(num, den); } BigInteger C = n.gcd(d); num = n.divide(C); den = d.divide(C); if (den.signum() < 0) { num = num.negate(); den = den.negate(); } return new BigRational(num, den); } /** * Rational number reduction to lowest terms. * @param n BigInteger. * @param d BigInteger. * @return a/b ~ n/d, gcd(a,b) = 1, b > 0. */ public static BigRational reduction(BigInteger n, BigInteger d) { return RNRED(n, d); } /** * Rational number absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public BigRational abs() { if (this.signum() >= 0) { return this; } return this.negate(); } /** * Rational number absolute value. * @param R is a rational number. * @return the absolute value of R. */ public static BigRational RNABS(BigRational R) { if (R == null) return null; return R.abs(); } /** * Rational number comparison. * @param S BigRational. * @return SIGN(this-S). */ //JAVA6only: @Override public int compareTo(BigRational S) { BigInteger J2Y; BigInteger J3Y; BigInteger R1; BigInteger R2; BigInteger S1; BigInteger S2; int J1Y; int SL; int TL; int RL; if (this.equals(ZERO)) { return -S.signum(); } if (S.equals(ZERO)) { return this.signum(); } R1 = num; //this.numerator(); R2 = den; //this.denominator(); S1 = S.num; S2 = S.den; RL = R1.signum(); SL = S1.signum(); J1Y = (RL - SL); TL = (J1Y / 2); if (TL != 0) { return TL; } J3Y = R1.multiply(S2); J2Y = R2.multiply(S1); TL = J3Y.compareTo(J2Y); return TL; } /** * Rational number comparison. * @param R BigRational. * @param S BigRational. * @return SIGN(R-S). */ public static int RNCOMP(BigRational R, BigRational S) { if (R == null) return Integer.MAX_VALUE; return R.compareTo(S); } /** * Rational number denominator. * @param R BigRational. * @return R.denominator(). */ public static BigInteger RNDEN(BigRational R) { if (R == null) return null; return R.den; } /** * Rational number difference. * @param S BigRational. * @return this-S. */ public BigRational subtract(BigRational S) { return this.sum(S.negate()); } /** * Rational number difference. * @param R BigRational. * @param S BigRational. * @return R-S. */ public static BigRational RNDIF(BigRational R, BigRational S) { if (R == null) return S.negate(); return R.subtract(S); } /** * Rational number decimal write. R is a rational number. n is a * non-negative integer. R is approximated by a decimal fraction D with n * decimal digits following the decimal point and D is written in the output * stream. The inaccuracy of the approximation is at most (1/2)*10**-n. * @param R * @param NL */ // If ABS(D) is greater than ABS(R) then the last digit is // followed by a minus sign, if ABS(D) is less than ABS(R) then by a // plus sign. public static void RNDWR(BigRational R, int NL) { //BigInteger num = R.num; //BigInteger den = R.den; java.math.MathContext mc = new java.math.MathContext(NL); BigDecimal d = new BigDecimal(R, mc); System.out.print(d.toString()); return; } /** * Rational number from integer. * @param A BigInteger. * @return A/1. */ public static BigRational RNINT(BigInteger A) { return new BigRational(A); } /** * Rational number inverse. * @return 1/this. * @see edu.jas.structure.RingElem#inverse() */ public BigRational inverse() { BigInteger R1 = num; BigInteger R2 = den; BigInteger S1; BigInteger S2; if (R1.signum() >= 0) { S1 = R2; S2 = R1; } else { S1 = R2.negate(); S2 = R1.negate(); } return new BigRational(S1, S2); } /** * Rational number inverse. * @param R BigRational. * @return 1/R. */ public static BigRational RNINV(BigRational R) { if (R == null) return null; return R.inverse(); } /** * Rational number negative. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public BigRational negate() { BigInteger n = num.negate(); return new BigRational(n, den); } /** * Rational number negative. * @param R BigRational. * @return -R. */ public static BigRational RNNEG(BigRational R) { if (R == null) return null; return R.negate(); } /** * Rational number numerator. * @param R BigRational. * @return R.numerator(). */ public static BigInteger RNNUM(BigRational R) { if (R == null) return null; return R.num; } /** * Rational number product. * @param S BigRational. * @return this*S. */ public BigRational multiply(BigRational S) { BigInteger D1 = null; BigInteger D2 = null; BigInteger R1 = null; BigInteger R2 = null; BigInteger RB1 = null; BigInteger RB2 = null; BigInteger S1 = null; BigInteger S2 = null; BigInteger SB1 = null; BigInteger SB2 = null; BigRational T; BigInteger T1; BigInteger T2; if (this.equals(ZERO) || S.equals(ZERO)) { T = ZERO; return T; } R1 = num; //this.numerator(); R2 = den; //this.denominator(); S1 = S.num; S2 = S.den; if (R2.equals(BigInteger.ONE) && S2.equals(BigInteger.ONE)) { T1 = R1.multiply(S1); T = new BigRational(T1, BigInteger.ONE); return T; } if (R2.equals(BigInteger.ONE)) { D1 = R1.gcd(S2); RB1 = R1.divide(D1); SB2 = S2.divide(D1); T1 = RB1.multiply(S1); T = new BigRational(T1, SB2); return T; } if (S2.equals(BigInteger.ONE)) { D2 = S1.gcd(R2); SB1 = S1.divide(D2); RB2 = R2.divide(D2); T1 = SB1.multiply(R1); T = new BigRational(T1, RB2); return T; } D1 = R1.gcd(S2); RB1 = R1.divide(D1); SB2 = S2.divide(D1); D2 = S1.gcd(R2); SB1 = S1.divide(D2); RB2 = R2.divide(D2); T1 = RB1.multiply(SB1); T2 = RB2.multiply(SB2); T = new BigRational(T1, T2); return T; } /** * Rational number product. * @param R BigRational. * @param S BigRational. * @return R*S. */ public static BigRational RNPROD(BigRational R, BigRational S) { if (R == null) { return R; } return R.multiply(S); } /** * Rational number quotient. * @param S BigRational. * @return this/S. */ public BigRational divide(BigRational S) { return multiply(S.inverse()); } /** * Rational number quotient. * @param R BigRational. * @param S BigRational. * @return R/S. */ public static BigRational RNQ(BigRational R, BigRational S) { if (R == null) { return R; } return R.divide(S); } /** * Rational number remainder. * @param S BigRational. * @return this-(this/S)*S */ public BigRational remainder(BigRational S) { if (S.isZERO()) { throw new ArithmeticException("division by zero"); } return ZERO; } /** * Rational number, random. Random integers A, B and a random sign s are * generated using BigInteger(n,random) and random.nextBoolen(). Then R = * s*A/(B+1), reduced to lowest terms. * @param n such that 0 ≤ A, B ≤ (2n-1). * @return a random BigRational. */ public BigRational random(int n) { return random(n, random); } /** * Rational number, random. Random integers A, B and a random sign s are * generated using BigInteger(n,random) and random.nextBoolen(). Then R = * s*A/(B+1), reduced to lowest terms. * @param n such that 0 ≤ A, B ≤ (2n-1). * @param rnd is a source for random bits. * @return a random BigRational. */ public BigRational random(int n, Random rnd) { BigInteger A; BigInteger B; A = new BigInteger(n, rnd); // always positive if (rnd.nextBoolean()) { A = A.negate(); } B = new BigInteger(n, rnd); // always positive B = B.add(BigInteger.ONE); return RNRED(A, B); } /** * Rational number, random. Random integers A, B and a random sign s are * generated using BigInteger(n,random) and random.nextBoolen(). Then R = * s*A/(B+1), reduced to lowest terms. * @param NL such that 0 ≤ A, B ≤ (2n-1). * @return a random BigRational. */ public static BigRational RNRAND(int NL) { return ONE.random(NL, random); } /** * Rational number sign. * @see edu.jas.structure.RingElem#signum() */ public int signum() { return num.signum(); } /** * Rational number sign. * @param R BigRational. * @return R.signum(). */ public static int RNSIGN(BigRational R) { if (R == null) { return 0; } return R.signum(); } /** * Rational number sum. * @param S BigRational. * @return this+S. */ public BigRational sum(BigRational S) { BigInteger D = null; BigInteger E; BigInteger J1Y; BigInteger J2Y; BigInteger R1 = null; BigInteger R2 = null; BigInteger RB2 = null; BigInteger S1 = null; BigInteger S2 = null; BigInteger SB2 = null; BigRational T; BigInteger T1; BigInteger T2; if (this.equals(ZERO)) { T = S; return T; } if (S.equals(ZERO)) { T = this; return T; } R1 = num; //this.numerator(); R2 = den; //this.denominator(); S1 = S.num; S2 = S.den; if (R2.equals(BigInteger.ONE) && S2.equals(BigInteger.ONE)) { T1 = R1.add(S1); T = new BigRational(T1, BigInteger.ONE); return T; } if (R2.equals(BigInteger.ONE)) { T1 = R1.multiply(S2); T1 = T1.add(S1); T = new BigRational(T1, S2); return T; } if (S2.equals(BigInteger.ONE)) { T1 = R2.multiply(S1); T1 = T1.add(R1); T = new BigRational(T1, R2); return T; } D = R2.gcd(S2); RB2 = R2.divide(D); SB2 = S2.divide(D); J1Y = R1.multiply(SB2); J2Y = RB2.multiply(S1); T1 = J1Y.add(J2Y); if (T1.equals(BigInteger.ZERO)) { T = ZERO; return T; } if (!D.equals(BigInteger.ONE)) { E = T1.gcd(D); if (!E.equals(BigInteger.ONE)) { T1 = T1.divide(E); R2 = R2.divide(E); } } T2 = R2.multiply(SB2); T = new BigRational(T1, T2); return T; } /** * Rational number sum. * @param R BigRational. * @param S BigRational. * @return R+S. */ public static BigRational RNSUM(BigRational R, BigRational S) { if (R == null) { return S; } return R.sum(S); } /** * Parse rational number from String. * @param s String. * @return BigRational from s. */ public BigRational parse(String s) { return new BigRational(s); } /** * Parse rational number from Reader. * @param r Reader. * @return next BigRational from r. */ public BigRational parse(Reader r) { return parse(StringUtil.nextString(r)); } /** * Rational number greatest common divisor. * @param S BigRational. * @return gcd(this,S). */ public BigRational gcd(BigRational S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } return ONE; } /** * BigRational extended greatest common divisor. * @param S BigRational. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ public BigRational[] egcd(BigRational S) { BigRational[] ret = new BigRational[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; return ret; } if (this.isZERO()) { ret[0] = S; return ret; } BigRational half = new BigRational(1, 2); ret[0] = ONE; ret[1] = this.inverse().multiply(half); ret[2] = S.inverse().multiply(half); return ret; } private boolean nonNegative = true; private boolean duplicates = true; /** * Set the iteration algorithm to all elements. */ public void setAllIterator() { nonNegative = false; } /** * Set the iteration algorithm to non-negative elements. */ public void setNonNegativeIterator() { nonNegative = true; } /** * Set the iteration algorithm to no duplicate elements. */ public void setNoDuplicatesIterator() { duplicates = false; } /** * Set the iteration algorithm to allow duplicate elements. */ public void setDuplicatesIterator() { duplicates = true; } /** * Get a BigRational iterator. * @return a iterator over all rationals. */ public Iterator iterator() { if (duplicates) { return new BigRationalIterator(nonNegative); } return new BigRationalUniqueIterator(new BigRationalIterator(nonNegative)); } /** * Get a BigRational iterator with no duplicates. * @return a iterator over all rationals without duplicates. */ public Iterator uniqueIterator() { return new BigRationalUniqueIterator(new BigRationalIterator(nonNegative)); } } /** * Big rational iterator. Uses Cantors diagonal enumeration. * @author Heinz Kredel */ class BigRationalIterator implements Iterator { /** * data structure. */ BigRational curr; edu.jas.arith.BigInteger den; edu.jas.arith.BigInteger num; Iterator denit; Iterator numit; List denlist; List numlist; Iterator denlistit; Iterator numlistit; final boolean nonNegative; protected long level; /** * BigRational iterator constructor. */ public BigRationalIterator() { this(false); } /** * BigRational iterator constructor. * @param nn, true for indicator for a non-negative iterator, fall for an * all iterator */ public BigRationalIterator(boolean nn) { nonNegative = nn; curr = edu.jas.arith.BigRational.ZERO; level = 0; den = new edu.jas.arith.BigInteger(); // ZERO num = edu.jas.arith.BigInteger.ONE.copy(); if (nonNegative) { den.setNonNegativeIterator(); } else { den.setAllIterator(); } num.setNonNegativeIterator(); denit = den.iterator(); numit = num.iterator(); denlist = new ArrayList(); numlist = new ArrayList(); @SuppressWarnings("unused") edu.jas.arith.BigInteger unused = denit.next(); // skip zero denominator unused = numit.next(); if (unused == null) { // use for findbugs System.out.println("unused is null"); } denlist.add(denit.next()); numlist.add(numit.next()); denlistit = denlist.iterator(); numlistit = numlist.iterator(); } /** * Test for availability of a next element. * @return true if the iteration has more elements, else false. */ public boolean hasNext() { return true; } /** * Get next rational. * @return next rational. */ public synchronized BigRational next() { BigRational r = curr; if (denlistit.hasNext() && numlistit.hasNext()) { BigInteger d = denlistit.next().val; BigInteger n = numlistit.next().val; //System.out.println(d + "//" + n); curr = BigRational.reduction(d, n); return r; } level++; if (level % 2 == 1) { Collections.reverse(denlist); } else { Collections.reverse(numlist); } denlist.add(denit.next()); numlist.add(numit.next()); if (level % 2 == 0) { Collections.reverse(denlist); } else { Collections.reverse(numlist); } //System.out.println("denlist = " + denlist); //System.out.println("numlist = " + numlist); denlistit = denlist.iterator(); numlistit = numlist.iterator(); BigInteger d = denlistit.next().val; BigInteger n = numlistit.next().val; //System.out.println(d + "//" + n); curr = BigRational.reduction(d, n); return r; } /** * Remove an element if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove elements"); } } /** * Big rational unique iterator. Uses Cantors diagonal enumeration, produces * distinct elements. * @author Heinz Kredel */ class BigRationalUniqueIterator implements Iterator { /** * data structure. */ final Set unique; final Iterator ratit; /** * BigRational iterator constructor. */ public BigRationalUniqueIterator() { this(BigRational.ONE.iterator()); } /** * BigRational iterator constructor. * @param nn, true for indicator for a non-negative iterator, fall for an * all iterator */ public BigRationalUniqueIterator(Iterator rit) { ratit = rit; unique = new HashSet(); } /** * Test for availability of a next element. * @return true if the iteration has more elements, else false. */ public synchronized boolean hasNext() { return ratit.hasNext(); } /** * Get next rational. * @return next rational. */ public synchronized BigRational next() { BigRational r = ratit.next(); while (unique.contains(r)) { //System.out.println("duplicate " + r); r = ratit.next(); } unique.add(r); return r; } /** * Remove an element if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove elements"); } } jas-2.5/src/edu/jas/arith/ModularNotInvertibleException.java0000644000175000017500000000545612004277700024436 0ustar giovannigiovanni/* * $Id: ModularNotInvertibleException.java 4054 2012-07-26 17:34:57Z kredel $ */ package edu.jas.arith; import edu.jas.structure.GcdRingElem; import edu.jas.structure.NotInvertibleException; /** * Modular integer NotInvertibleException class. Runtime Exception to be thrown * for not invertible modular integers. Container for the non-trivial factors * found by the inversion algorithm. Note: cannot be generic because of * Throwable. * @author Heinz Kredel */ public class ModularNotInvertibleException extends NotInvertibleException { public final GcdRingElem f; // = f1 * f2 public final GcdRingElem f1; public final GcdRingElem f2; public ModularNotInvertibleException() { this(null, null, null); } public ModularNotInvertibleException(String c) { this(c, null, null, null); } public ModularNotInvertibleException(String c, Throwable t) { this(c, t, null, null, null); } public ModularNotInvertibleException(Throwable t) { this(t, null, null, null); } /** * Constructor. * @param f gcd ring element with f = f1 * f2. * @param f1 gcd ring element. * @param f2 gcd ring element. */ public ModularNotInvertibleException(GcdRingElem f, GcdRingElem f1, GcdRingElem f2) { super("ModularNotInvertibleException"); this.f = f; this.f1 = f1; this.f2 = f2; } /** * Constructor. * @param f gcd ring element with f = f1 * f2. * @param f1 gcd ring element. * @param f2 gcd ring element. */ public ModularNotInvertibleException(String c, GcdRingElem f, GcdRingElem f1, GcdRingElem f2) { super(c); this.f = f; this.f1 = f1; this.f2 = f2; } /** * Constructor. * @param f gcd ring element with f = f1 * f2. * @param f1 gcd ring element. * @param f2 gcd ring element. */ public ModularNotInvertibleException(String c, Throwable t, GcdRingElem f, GcdRingElem f1, GcdRingElem f2) { super(c, t); this.f = f; this.f1 = f1; this.f2 = f2; } /** * Constructor. * @param f gcd ring element with f = f1 * f2. * @param f1 gcd ring element. * @param f2 gcd ring element. */ public ModularNotInvertibleException(Throwable t, GcdRingElem f, GcdRingElem f1, GcdRingElem f2) { super("ModularNotInvertibleException", t); this.f = f; this.f1 = f1; this.f2 = f2; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { String s = super.toString(); if (f != null || f1 != null || f2 != null) { s += ", f = " + f + ", f1 = " + f1 + ", f2 = " + f2; } return s; } } jas-2.5/src/edu/jas/arith/ModLong.java0000644000175000017500000003257212020212506017774 0ustar giovannigiovanni/* * $Id: ModLong.java 4148 2012-08-31 19:49:27Z kredel $ */ package edu.jas.arith; import edu.jas.structure.GcdRingElem; import edu.jas.structure.NotInvertibleException; /** * ModLong class with RingElem interface. Objects of this class are immutable. * @author Heinz Kredel * @see ModInteger */ public final class ModLong implements GcdRingElem, Modular { /** * ModLongRing reference. */ public final ModLongRing ring; /** * Value part of the element data structure. */ public final long val; /** * The constructor creates a ModLong object from a ModLongRing and a value * part. * @param m ModLongRing. * @param a math.BigInteger. */ public ModLong(ModLongRing m, java.math.BigInteger a) { this(m, a.mod(new java.math.BigInteger("" + m.modul)).longValue()); } /** * The constructor creates a ModLong object from a ModLongRing and a long * value part. * @param m ModLongRing. * @param a long. */ public ModLong(ModLongRing m, long a) { ring = m; long v = a % ring.modul; val = (v >= 0L ? v : v + ring.modul); } /** * The constructor creates a ModLong object from a ModLongRing and a Long * value part. * @param m ModLongRing. * @param a Long. */ public ModLong(ModLongRing m, Long a) { this(m, a.longValue()); } /** * The constructor creates a ModLong object from a ModLongRing and a String * value part. * @param m ModLongRing. * @param s String. */ public ModLong(ModLongRing m, String s) { this(m, new Long(s.trim())); } /** * The constructor creates a 0 ModLong object from a given ModLongRing. * @param m ModLongRing. */ public ModLong(ModLongRing m) { this(m, 0L); } /** * Get the value part. * @return val. */ public long getVal() { return val; } /** * Get the module part. * @return modul. */ public long getModul() { return ring.modul; } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public ModLongRing factory() { return ring; } /** * Get the symmetric value part. * @return val with -modul/2 <= val < modul/2. */ public long getSymmetricVal() { if ((val + val) > ring.modul) { // val > m/2 as 2*val > m, make symmetric to 0 return val - ring.modul; } return val; } /** * Return a BigInteger from this Element. * @return a BigInteger of this. */ public BigInteger getInteger() { return new BigInteger(val); } /** * Return a symmetric BigInteger from this Element. * @return a symmetric BigInteger of this. */ public BigInteger getSymmetricInteger() { long v = val; if ((val + val) > ring.modul) { // val > m/2 as 2*val > m, make symmetric to 0 v = val - ring.modul; } return new BigInteger(v); } /** * Clone this. * @see java.lang.Object#clone() */ @Override public ModLong copy() { return new ModLong(ring, val); } /** * Is ModLong number zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return val == 0L; } /** * Is ModLong number one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return val == 1L; } /** * Is ModLong number a unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (isZERO()) { return false; } if (ring.isField()) { return true; } long g = gcd(ring.modul, val); return (g == 1L || g == -1L); } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return "" + val; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * ModLong comparison. * @param b ModLong. * @return sign(this-b). */ //JAVA6only: @Override public int compareTo(ModLong b) { long v = b.val; if (ring != b.ring) { v = v % ring.modul; } if (val > v) { return 1; } return (val < v ? -1 : 0); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object b) { if (!(b instanceof ModLong)) { return false; } return (0 == compareTo((ModLong) b)); } /** * Hash code for this ModLong. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return (int) val; } /** * ModLong absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public ModLong abs() { return new ModLong(ring, (val < 0 ? -val : val)); } /** * ModLong negative. * @see edu.jas.structure.RingElem#negate() * @return -this. */ public ModLong negate() { return new ModLong(ring, -val); } /** * ModLong signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { if (val > 0L) { return 1; } return (val < 0L ? -1 : 0); } /** * ModLong subtraction. * @param S ModLong. * @return this-S. */ public ModLong subtract(ModLong S) { return new ModLong(ring, val - S.val); } /** * ModLong divide. * @param S ModLong. * @return this/S. */ public ModLong divide(ModLong S) { try { return multiply(S.inverse()); } catch (NotInvertibleException e) { try { if ((val % S.val) == 0L) { return new ModLong(ring, val / S.val); } throw new NotInvertibleException(e.getCause()); } catch (ArithmeticException a) { throw new NotInvertibleException(a.getCause()); } } } /** * ModLong inverse. * @see edu.jas.structure.RingElem#inverse() * @throws NotInvertibleException if the element is not invertible. * @return S with S=1/this if defined. */ public ModLong inverse() /*throws NotInvertibleException*/{ try { return new ModLong(ring, modInverse(val, ring.modul)); } catch (ArithmeticException e) { long g = gcd(val, ring.modul); long f = ring.modul / g; throw new ModularNotInvertibleException(e, new BigInteger(ring.modul), new BigInteger(g), new BigInteger(f)); } } /** * ModLong remainder. * @param S ModLong. * @return remainder(this,S). */ public ModLong remainder(ModLong S) { if (S == null || S.isZERO()) { throw new ArithmeticException("division by zero"); } if (S.isONE()) { return ring.getZERO(); } if (S.isUnit()) { return ring.getZERO(); } return new ModLong(ring, val % S.val); } /** * ModLong multiply. * @param S ModLong. * @return this*S. */ public ModLong multiply(ModLong S) { return new ModLong(ring, val * S.val); } /** * ModLong summation. * @param S ModLong. * @return this+S. */ public ModLong sum(ModLong S) { return new ModLong(ring, val + S.val); } /** * ModInteger greatest common divisor. * @param S ModInteger. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ public ModLong gcd(ModLong S) { if (S.isZERO()) { return this; } if (isZERO()) { return S; } if (isUnit() || S.isUnit()) { return ring.getONE(); } return new ModLong(ring, gcd(val, S.val)); } /** * ModInteger extended greatest common divisor. * @param S ModInteger. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ public ModLong[] egcd(ModLong S) { ModLong[] ret = new ModLong[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; return ret; } if (isZERO()) { ret[0] = S; return ret; } if (isUnit() || S.isUnit()) { ret[0] = ring.getONE(); if (isUnit() && S.isUnit()) { //ModLong half = (new ModLong(ring, 2L)).inverse(); //ret[1] = this.inverse().multiply(half); //ret[2] = S.inverse().multiply(half); // (1-1*this)/S ret[1] = ring.getONE(); ModLong x = ret[0].subtract(ret[1].multiply(this)); ret[2] = x.divide(S); return ret; } if (isUnit()) { // oder inverse(S-1)? ret[1] = this.inverse(); ret[2] = ring.getZERO(); return ret; } // if ( s.isUnit() ) { // oder inverse(this-1)? ret[1] = ring.getZERO(); ret[2] = S.inverse(); return ret; //} } //System.out.println("this = " + this + ", S = " + S); long q = this.val; long r = S.val; long c1 = 1L; // BigInteger.ONE.val; long d1 = 0L; // BigInteger.ZERO.val; long c2 = 0L; // BigInteger.ZERO.val; long d2 = 1L; // BigInteger.ONE.val; long x1; long x2; while (r != 0L) { //qr = q.divideAndRemainder(r); long a = q / r; long b = q % r; q = a; x1 = c1 - q * d1; x2 = c2 - q * d2; c1 = d1; c2 = d2; d1 = x1; d2 = x2; q = r; r = b; } System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2); ret[0] = new ModLong(ring, q); ret[1] = new ModLong(ring, c1); ret[2] = new ModLong(ring, c2); return ret; } /** * Long greatest common divisor. * @param T long. * @param S long. * @return gcd(T,S). */ public long gcd(long T, long S) { if (S == 0L) { return T; } if (T == 0L) { return S; } long a = T; long b = S; while (b != 0L) { long r = a % b; a = b; b = r; } return a; } /** * Long half extended greatest common divisor. * @param T long. * @param S long. * @return [ gcd(T,S), a ] with a*T + b*S = gcd(T,S). */ public long[] hegcd(long T, long S) { long[] ret = new long[2]; if (S == 0L) { ret[0] = T; ret[1] = 1L; return ret; } if (T == 0L) { ret[0] = S; ret[1] = 0L; return ret; } //System.out.println("hegcd, T = " + T + ", S = " + S); long a = T; long b = S; long a1 = 1L; long b1 = 0L; while (b != 0L) { long q = a / b; long r = a % b; a = b; b = r; long r1 = a1 - q * b1; a1 = b1; b1 = r1; } if (a1 < 0L) { a1 += S; } ret[0] = a; ret[1] = a1; return ret; } /** * Long modular inverse. * @param T long. * @param m long. * @return a with with a*T = 1 mod m. */ public long modInverse(long T, long m) { if (T == 0L) { throw new NotInvertibleException("zero is not invertible"); } long[] hegcd = hegcd(T, m); long a = hegcd[0]; if (!(a == 1L || a == -1L)) { // gcd != 1 throw new ModularNotInvertibleException("element not invertible, gcd != 1", new BigInteger(m), new BigInteger(a), new BigInteger(m / a)); } long b = hegcd[1]; if (b == 0L) { // when m divides this, e.g. m.isUnit() throw new NotInvertibleException("element not invertible, divisible by modul"); } if (b < 0L) { b += m; } return b; } } jas-2.5/src/edu/jas/arith/Rational.java0000644000175000017500000000060011316612712020203 0ustar giovannigiovanni/* * $Id: Rational.java 2939 2009-12-30 08:56:43Z kredel $ */ package edu.jas.arith; /** * Interface with method to get a BigRational (approximation). * @author Heinz Kredel */ public interface Rational { /** * Return a BigRational approximation of this Element. * @return a BigRational approximation of this. */ public BigRational getRational(); } jas-2.5/src/edu/jas/arith/ModLongRing.java0000644000175000017500000002641412004277700020623 0ustar giovannigiovanni/* * $Id: ModLongRing.java 4054 2012-07-26 17:34:57Z kredel $ */ package edu.jas.arith; import java.io.Reader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; import edu.jas.kern.StringUtil; /** * ModLongRing factory with RingFactory interface. Effectively immutable. * @author Heinz Kredel */ public final class ModLongRing implements ModularRingFactory, Iterable { /** * Module part of the factory data structure. */ public final long modul; /** * Random number generator. */ private final static Random random = new Random(); /** * Indicator if this ring is a field. */ private int isField = -1; // initially unknown /* * Certainty if module is probable prime. */ //private final int certainty = 10; /** * maximal representable integer. */ public final static java.math.BigInteger MAX_LONG = new java.math.BigInteger( String.valueOf(Integer.MAX_VALUE)); // not larger! /** * The constructor creates a ModLongRing object from a long integer as * module part. * @param m long integer. */ public ModLongRing(long m) { modul = m; } /** * The constructor creates a ModLongRing object from a long integer as * module part. * @param m long integer. * @param isField indicator if m is prime. */ public ModLongRing(long m, boolean isField) { modul = m; this.isField = (isField ? 1 : 0); } /** * The constructor creates a ModLongRing object from a Long integer as * module part. * @param m Long integer. */ public ModLongRing(Long m) { this(m.longValue()); } /** * The constructor creates a ModLongRing object from a Long integer as * module part. * @param m Long integer. * @param isField indicator if m is prime. */ public ModLongRing(Long m, boolean isField) { this(m.longValue(), isField); } /** * The constructor creates a ModLongRing object from a BigInteger converted * to long as module part. * @param m java.math.BigInteger. */ public ModLongRing(java.math.BigInteger m) { this(m.longValue()); if (MAX_LONG.compareTo(m) <= 0) { // m >= max System.out.println("modul to large for long " + m + ",max=" + MAX_LONG); throw new IllegalArgumentException("modul to large for long " + m); } } /** * The constructor creates a ModLongRing object from a BigInteger converted * to long as module part. * @param m java.math.BigInteger. * @param isField indicator if m is prime. */ public ModLongRing(java.math.BigInteger m, boolean isField) { this(m.longValue(), isField); if (MAX_LONG.compareTo(m) <= 0) { // m >= max System.out.println("modul to large for long " + m + ",max=" + MAX_LONG); throw new IllegalArgumentException("modul to large for long " + m); } } /** * The constructor creates a ModLongRing object from a String object as * module part. * @param m String. */ public ModLongRing(String m) { this(new Long(m.trim())); } /** * The constructor creates a ModLongRing object from a String object as * module part. * @param m String. * @param isField indicator if m is prime. */ public ModLongRing(String m, boolean isField) { this(new Long(m.trim()), isField); } /** * Get the module part as BigInteger. * @return modul. */ public java.math.BigInteger getModul() { return new java.math.BigInteger("" + modul); } /** * Get the module part as long. * @return modul. */ public long getLongModul() { return modul; } /** * Get the module part as BigInteger. * @return modul. */ public BigInteger getIntegerModul() { return new BigInteger(modul); } /** * Create ModLong element c. * @param c * @return a ModLong of c. */ public ModLong create(java.math.BigInteger c) { return new ModLong(this, c); } /** * Create ModLong element c. * @param c * @return a ModLong of c. */ public ModLong create(long c) { return new ModLong(this, c); } /** * Create ModLong element c. * @param c * @return a ModLong of c. */ public ModLong create(String c) { return parse(c); } /** * Copy ModLong element c. * @param c * @return a copy of c. */ public ModLong copy(ModLong c) { return new ModLong(this, c.val); } /** * Get the zero element. * @return 0 as ModLong. */ public ModLong getZERO() { return new ModLong(this, 0L); } /** * Get the one element. * @return 1 as ModLong. */ public ModLong getONE() { return new ModLong(this, 1L); } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List generators() { List g = new ArrayList(1); g.add(getONE()); return g; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return true; } /** * Query if this ring is commutative. * @return true. */ public boolean isCommutative() { return true; } /** * Query if this ring is associative. * @return true. */ public boolean isAssociative() { return true; } /** * Query if this ring is a field. * @return true if module is prime, else false. */ public boolean isField() { if (isField > 0) { return true; } if (isField == 0) { return false; } //System.out.println("isProbablePrime " + modul + " = " + modul.isProbablePrime(certainty)); java.math.BigInteger m = new java.math.BigInteger("" + modul); if (m.isProbablePrime(m.bitLength())) { isField = 1; return true; } isField = 0; return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return new java.math.BigInteger("" + modul); } /** * Get a ModLong element from a BigInteger value. * @param a BigInteger. * @return a ModLong. */ public ModLong fromInteger(java.math.BigInteger a) { return new ModLong(this, a); } /** * Get a ModLong element from a long value. * @param a long. * @return a ModLong. */ public ModLong fromInteger(long a) { return new ModLong(this, a); } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return " mod(" + modul + ")"; //",max=" + MAX_LONG + ")"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python and Ruby case if (isField()) { return "GFL(" + modul + ")"; } return "ZL(" + modul + ")"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object b) { if (!(b instanceof ModLongRing)) { return false; } ModLongRing m = (ModLongRing) b; return (modul == m.modul); } /** * Hash code for this ModLongRing. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return (int) modul; } /** * ModLong random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random integer mod modul. */ public ModLong random(int n) { return random(n, random); } /** * ModLong random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random integer mod modul. */ public ModLong random(int n, Random rnd) { java.math.BigInteger v = new java.math.BigInteger(n, rnd); return new ModLong(this, v); // rnd.nextLong() not ok } /** * Parse ModLong from String. * @param s String. * @return ModLong from s. */ public ModLong parse(String s) { return new ModLong(this, s); } /** * Parse ModLong from Reader. * @param r Reader. * @return next ModLong from r. */ public ModLong parse(Reader r) { return parse(StringUtil.nextString(r)); } /** * ModLong chinese remainder algorithm. This is a factory method. Assert * c.modul >= a.modul and c.modul * a.modul = this.modul. * @param c ModLong. * @param ci inverse of c.modul in ring of a. * @param a other ModLong. * @return S, with S mod c.modul == c and S mod a.modul == a. */ public ModLong chineseRemainder(ModLong c, ModLong ci, ModLong a) { if (true) { // debug if (c.ring.modul < a.ring.modul) { System.out.println("ModLong error " + c.ring + ", " + a.ring); } } ModLong b = a.ring.fromInteger(c.val); // c mod a.modul ModLong d = a.subtract(b); // a-c mod a.modul if (d.isZERO()) { return new ModLong(this, c.val); } b = d.multiply(ci); // b = (a-c)*ci mod a.modul // (c.modul*b)+c mod this.modul = c mod c.modul = // (c.modul*ci*(a-c)+c) mod a.modul = a mod a.modul long s = c.ring.modul * b.val; s = s + c.val; return new ModLong(this, s); } /** * Get a ModLong iterator. * @return a iterator over all modular integers in this ring. */ public Iterator iterator() { return new ModLongIterator(this); } } /** * Modular integer iterator. * @author Heinz Kredel */ class ModLongIterator implements Iterator { /** * data structure. */ long curr; final ModLongRing ring; /** * ModLong iterator constructor. * @param fac modular integer factory; */ public ModLongIterator(ModLongRing fac) { curr = 0L; ring = fac; } /** * Test for availability of a next element. * @return true if the iteration has more elements, else false. */ public synchronized boolean hasNext() { return curr < ring.modul; } /** * Get next integer. * @return next integer. */ public synchronized ModLong next() { ModLong i = new ModLong(ring, curr); curr++; return i; } /** * Remove an element if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove elements"); } } jas-2.5/src/edu/jas/arith/BigComplex.java0000644000175000017500000004472412014234362020477 0ustar giovannigiovanni/* * $Id: BigComplex.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.arith; import java.io.Reader; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.StringUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.StarRingElem; /** * BigComplex class based on BigRational implementing the RingElem respectively * the StarRingElem interface. Objects of this class are immutable. The SAC2 * static methods are also provided. * @author Heinz Kredel */ public final class BigComplex implements StarRingElem, GcdRingElem, RingFactory { /** * Real part of the data structure. */ public final BigRational re; /** * Imaginary part of the data structure. */ public final BigRational im; private final static Random random = new Random(); private static final Logger logger = Logger.getLogger(BigComplex.class); /** * The constructor creates a BigComplex object from two BigRational objects * real and imaginary part. * @param r real part. * @param i imaginary part. */ public BigComplex(BigRational r, BigRational i) { re = r; im = i; } /** * The constructor creates a BigComplex object from a BigRational object as * real part, the imaginary part is set to 0. * @param r real part. */ public BigComplex(BigRational r) { this(r, BigRational.ZERO); } /** * The constructor creates a BigComplex object from a long element as real * part, the imaginary part is set to 0. * @param r real part. */ public BigComplex(long r) { this(new BigRational(r), BigRational.ZERO); } /** * The constructor creates a BigComplex object with real part 0 and * imaginary part 0. */ public BigComplex() { this(BigRational.ZERO); } /** * The constructor creates a BigComplex object from a String representation. * @param s string of a BigComplex. * @throws NumberFormatException */ public BigComplex(String s) throws NumberFormatException { if (s == null || s.length() == 0) { re = BigRational.ZERO; im = BigRational.ZERO; return; } s = s.trim(); int i = s.indexOf("i"); if (i < 0) { re = new BigRational(s); im = BigRational.ZERO; return; } //logger.warn("String constructor not done"); String sr = ""; if (i > 0) { sr = s.substring(0, i); } String si = ""; if (i < s.length()) { si = s.substring(i + 1, s.length()); } //int j = sr.indexOf("+"); re = new BigRational(sr.trim()); im = new BigRational(si.trim()); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public BigComplex factory() { return this; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List generators() { List g = new ArrayList(2); g.add(getONE()); g.add(getIMAG()); return g; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return false; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public BigComplex copy() { return new BigComplex(re, im); } /** * Copy BigComplex element c. * @param c BigComplex. * @return a copy of c. */ public BigComplex copy(BigComplex c) { return new BigComplex(c.re, c.im); } /** * Get the zero element. * @return 0 as BigComplex. */ public BigComplex getZERO() { return ZERO; } /** * Get the one element. * @return 1 as BigComplex. */ public BigComplex getONE() { return ONE; } /** * Get the i element. * @return i as BigComplex. */ public BigComplex getIMAG() { return I; } /** * Query if this ring is commutative. * @return true. */ public boolean isCommutative() { return true; } /** * Query if this ring is associative. * @return true. */ public boolean isAssociative() { return true; } /** * Query if this ring is a field. * @return true. */ public boolean isField() { return true; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return java.math.BigInteger.ZERO; } /** * Get a BigComplex element from a BigInteger. * @param a BigInteger. * @return a BigComplex. */ public BigComplex fromInteger(BigInteger a) { return new BigComplex(new BigRational(a)); } /** * Get a BigComplex element from a long. * @param a long. * @return a BigComplex. */ public BigComplex fromInteger(long a) { return new BigComplex(new BigRational(a)); } /** * The constant 0. */ public static final BigComplex ZERO = new BigComplex(); /** * The constant 1. */ public static final BigComplex ONE = new BigComplex(BigRational.ONE); /** * The constant i. */ public static final BigComplex I = new BigComplex(BigRational.ZERO, BigRational.ONE); /** * Get the real part. * @return re. */ public BigRational getRe() { return re; } /** * Get the imaginary part. * @return im. */ public BigRational getIm() { return im; } /** * Get the String representation. */ @Override public String toString() { String s = "" + re; int i = im.compareTo(BigRational.ZERO); //logger.info("compareTo "+im+" ? 0 = "+i); if (i == 0) return s; s += "i" + im; return s; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case: re or re+im*i // was (re,im) or (re,) StringBuffer s = new StringBuffer(); boolean iz = im.isZERO(); if (iz) { s.append(re.toScript()); return s.toString(); } boolean rz = re.isZERO(); if (rz) { if (!im.isONE()) { if (im.signum() > 0) { s.append(im.toScript() + "*"); } else { s.append("-"); BigRational ii = im.negate(); if (!ii.isONE()) { s.append(ii.toScript() + "*"); } } } } else { s.append(re.toScript()); if (im.signum() > 0) { s.append("+"); if (!im.isONE()) { s.append(im.toScript() + "*"); } } else { s.append("-"); BigRational ii = im.negate(); if (!ii.isONE()) { s.append(ii.toScript() + "*"); } } } s.append("I"); return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return "CC()"; } /** * Complex number zero. * @param A is a complex number. * @return If A is 0 then true is returned, else false. */ public static boolean isCZERO(BigComplex A) { if (A == null) return false; return A.isZERO(); } /** * Is Complex number zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return re.equals(BigRational.ZERO) && im.equals(BigRational.ZERO); } /** * Complex number one. * @param A is a complex number. * @return If A is 1 then true is returned, else false. */ public static boolean isCONE(BigComplex A) { if (A == null) return false; return A.isONE(); } /** * Is Complex number one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return re.equals(BigRational.ONE) && im.equals(BigRational.ZERO); } /** * Is Complex imaginary one. * @return If this is i then true is returned, else false. */ public boolean isIMAG() { return re.equals(BigRational.ZERO) && im.equals(BigRational.ONE); } /** * Is Complex unit element. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { return (!isZERO()); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object b) { if (!(b instanceof BigComplex)) { return false; } BigComplex bc = (BigComplex) b; return re.equals(bc.re) && im.equals(bc.im); } /** * Hash code for this BigComplex. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * re.hashCode() + im.hashCode(); } /** * Since complex numbers are unordered, we use lexicographical order of re * and im. * @return 0 if this is equal to b; 1 if re > b.re, or re == b.re and im > * b.im; -1 if re < b.re, or re == b.re and im < b.im */ //JAVA6only: @Override public int compareTo(BigComplex b) { int s = re.compareTo(b.re); if (s != 0) { return s; } return im.compareTo(b.im); } /** * Since complex numbers are unordered, we use lexicographical order of re * and im. * @return 0 if this is equal to 0; 1 if re > 0, or re == 0 and im > 0; -1 * if re < 0, or re == 0 and im < 0 * @see edu.jas.structure.RingElem#signum() */ public int signum() { int s = re.signum(); if (s != 0) { return s; } return im.signum(); } /* arithmetic operations: +, -, - */ /** * Complex number summation. * @param B a BigComplex number. * @return this+B. */ public BigComplex sum(BigComplex B) { return new BigComplex(re.sum(B.re), im.sum(B.im)); } /** * Complex number sum. * @param A and B are complex numbers. * @return A+B. */ public static BigComplex CSUM(BigComplex A, BigComplex B) { if (A == null) return null; return A.sum(B); } /** * Complex number difference. * @param A and B are complex numbers. * @return A-B. */ public static BigComplex CDIF(BigComplex A, BigComplex B) { if (A == null) return null; return A.subtract(B); } /** * Complex number subtract. * @param B a BigComplex number. * @return this-B. */ public BigComplex subtract(BigComplex B) { return new BigComplex(re.subtract(B.re), im.subtract(B.im)); } /** * Complex number negative. * @param A is a complex number. * @return -A */ public static BigComplex CNEG(BigComplex A) { if (A == null) return null; return A.negate(); } /** * Complex number negative. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public BigComplex negate() { return new BigComplex(re.negate(), im.negate()); } /** * Complex number conjugate. * @param A is a complex number. * @return the complex conjugate of A. */ public static BigComplex CCON(BigComplex A) { if (A == null) return null; return A.conjugate(); } /* arithmetic operations: conjugate, absolut value */ /** * Complex number conjugate. * @return the complex conjugate of this. */ public BigComplex conjugate() { return new BigComplex(re, im.negate()); } /** * Complex number norm. * @see edu.jas.structure.StarRingElem#norm() * @return ||this||. */ public BigComplex norm() { // this.conjugate().multiply(this); BigRational v = re.multiply(re); v = v.sum(im.multiply(im)); return new BigComplex(v); } /** * Complex number absolute value. * @see edu.jas.structure.RingElem#abs() * @return |this|^2. Note: The square root is not jet implemented. */ public BigComplex abs() { BigComplex n = norm(); logger.error("abs() square root missing"); // n = n.sqrt(); return n; } /** * Complex number absolute value. * @param A is a complex number. * @return the absolute value of A, a rational number. Note: The square root * is not jet implemented. */ public static BigRational CABS(BigComplex A) { if (A == null) return null; return A.abs().re; } /** * Complex number product. * @param A and B are complex numbers. * @return A*B. */ public static BigComplex CPROD(BigComplex A, BigComplex B) { if (A == null) return null; return A.multiply(B); } /* arithmetic operations: *, inverse, / */ /** * Complex number product. * @param B is a complex number. * @return this*B. */ public BigComplex multiply(BigComplex B) { return new BigComplex(re.multiply(B.re).subtract(im.multiply(B.im)), re.multiply(B.im).sum( im.multiply(B.re))); } /** * Complex number inverse. * @param A is a non-zero complex number. * @return S with S*A = 1. */ public static BigComplex CINV(BigComplex A) { if (A == null) return null; return A.inverse(); } /** * Complex number inverse. * @return S with S*this = 1. * @see edu.jas.structure.RingElem#inverse() */ public BigComplex inverse() { BigRational a = norm().re.inverse(); return new BigComplex(re.multiply(a), im.multiply(a.negate())); } /** * Complex number inverse. * @param S is a complex number. * @return 0. */ public BigComplex remainder(BigComplex S) { if (S.isZERO()) { throw new ArithmeticException("division by zero"); } return ZERO; } /** * Complex number quotient. * @param A and B are complex numbers, B non-zero. * @return A/B. */ public static BigComplex CQ(BigComplex A, BigComplex B) { if (A == null) return null; return A.divide(B); } /** * Complex number divide. * @param B is a complex number, non-zero. * @return this/B. */ public BigComplex divide(BigComplex B) { return this.multiply(B.inverse()); } /** * Complex number, random. Random rational numbers A and B are generated * using random(n). Then R is the complex number with real part A and * imaginary part B. * @param n such that 0 ≤ A, B ≤ (2n-1). * @return R. */ public BigComplex random(int n) { return random(n, random); } /** * Complex number, random. Random rational numbers A and B are generated * using random(n). Then R is the complex number with real part A and * imaginary part B. * @param n such that 0 ≤ A, B ≤ (2n-1). * @param rnd is a source for random bits. * @return R. */ public BigComplex random(int n, Random rnd) { BigRational r = BigRational.ONE.random(n, rnd); BigRational i = BigRational.ONE.random(n, rnd); return new BigComplex(r, i); } /** * Complex number, random. Random rational numbers A and B are generated * using random(n). Then R is the complex number with real part A and * imaginary part B. * @param n such that 0 ≤ A, B ≤ (2n-1). * @return R. */ public static BigComplex CRAND(int n) { return ONE.random(n, random); } /** * Parse complex number from string. * @param s String. * @return BigComplex from s. */ public BigComplex parse(String s) { return new BigComplex(s); } /** * Parse complex number from Reader. * @param r Reader. * @return next BigComplex from r. */ public BigComplex parse(Reader r) { return parse(StringUtil.nextString(r)); } /** * Complex number greatest common divisor. * @param S BigComplex. * @return gcd(this,S). */ public BigComplex gcd(BigComplex S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } return ONE; } /** * BigComplex extended greatest common divisor. * @param S BigComplex. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ public BigComplex[] egcd(BigComplex S) { BigComplex[] ret = new BigComplex[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; return ret; } if (this.isZERO()) { ret[0] = S; return ret; } BigComplex half = new BigComplex(new BigRational(1, 2)); ret[0] = ONE; ret[1] = this.inverse().multiply(half); ret[2] = S.inverse().multiply(half); return ret; } } jas-2.5/src/edu/jas/arith/Product.java0000644000175000017500000005062512014234362020063 0ustar giovannigiovanni/* * $Id: Product.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.arith; import java.util.Iterator; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.structure.NotInvertibleException; import edu.jas.structure.RegularRingElem; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Direct product element based on RingElem. Objects of this class are (nearly) * immutable. * @author Heinz Kredel */ public class Product> implements RegularRingElem> { private static final Logger logger = Logger.getLogger(Product.class); //private final boolean debug = logger.isDebugEnabled(); /** * Product class factory data structure. */ public final ProductRing ring; /** * Value part of the element data structure. */ public final SortedMap val; /** * Flag to remember if this product element is a unit in each cmponent. -1 * is unknown, 1 is unit, 0 not a unit. */ protected int isunit = -1; // initially unknown /** * The constructor creates a Product object from a ring factory. * @param r ring factory. */ public Product(ProductRing r) { this(r, new TreeMap(), 0); } /** * The constructor creates a Product object from a ring factory and a ring * element. * @param r ring factory. * @param a ring element. */ public Product(ProductRing r, SortedMap a) { this(r, a, -1); } /** * The constructor creates a Product object from a ring factory, a ring * element and an indicator if a is a unit. * @param r ring factory. * @param a ring element. * @param u isunit indicator, -1, 0, 1. */ public Product(ProductRing r, SortedMap a, int u) { ring = r; val = a; isunit = u; } /** * Get component. * @param i index of component. * @return val(i). */ public C get(int i) { return val.get(i); // auto-boxing } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public ProductRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public Product copy() { return new Product(ring, val, isunit); } /** * Is Product zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return val.size() == 0; } /** * Is Product one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { if (val.size() != ring.length()) { return false; } for (C e : val.values()) { if (!e.isONE()) { return false; } } return true; } /** * Is Product full. * @return If every component is non-zero, then true is returned, else * false. */ public boolean isFull() { if (val.size() != ring.length()) { return false; } return true; } /** * Is Product unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (isunit > 0) { return true; } if (isunit == 0) { return false; } if (isZERO()) { isunit = 0; return false; } for (C e : val.values()) { if (!e.isUnit()) { isunit = 0; return false; } } isunit = 1; return true; } /** * Is Product idempotent. * @return If this is a idempotent element then true is returned, else * false. */ public boolean isIdempotent() { for (C e : val.values()) { if (!e.isONE()) { return false; } } return true; } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { return val.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer("( "); boolean first = true; for (Integer i : val.keySet()) { C v = val.get(i); if (first) { first = false; } else { if (v.signum() < 0) { s.append(" - "); v = v.negate(); } else { s.append(" + "); } } if (!v.isONE()) { s.append(v.toScript() + "*"); } s.append("pg" + i); } s.append(" )"); return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Product comparison. * @param b Product. * @return sign(this-b). */ //JAVA6only: @Override public int compareTo(Product b) { if (!ring.equals(b.ring)) { logger.info("other ring " + b.ring); throw new IllegalArgumentException("rings not comparable " + this); } SortedMap v = b.val; Iterator> ti = val.entrySet().iterator(); Iterator> bi = v.entrySet().iterator(); int s; while (ti.hasNext() && bi.hasNext()) { Map.Entry te = ti.next(); Map.Entry be = bi.next(); s = te.getKey().compareTo(be.getKey()); if (s != 0) { return s; } s = te.getValue().compareTo(be.getValue()); if (s != 0) { return s; } } if (ti.hasNext()) { return -1; } if (bi.hasNext()) { return 1; } return 0; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @SuppressWarnings("unchecked") @Override public boolean equals(Object b) { if (!(b instanceof Product)) { return false; } Product a = null; try { a = (Product) b; } catch (ClassCastException e) { } if (a == null) { return false; } return (0 == compareTo(a)); } /** * Hash code for this local. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = ring.hashCode(); h = 37 * h + val.hashCode(); return h; } /** * Product extend. Add new component j with value of component i. * @param i from index. * @param j to index. * @return the extended value of this. */ public Product extend(int i, int j) { RingFactory rf = ring.getFactory(j); SortedMap elem = new TreeMap(val); C v = val.get(i); C w = rf.copy(v); // valueOf if (!w.isZERO()) { elem.put(j, w); } return new Product(ring, elem, isunit); } /** * Product absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public Product abs() { SortedMap elem = new TreeMap(); for (Integer i : val.keySet()) { C v = val.get(i).abs(); elem.put(i, v); } return new Product(ring, elem, isunit); } /** * Product summation. * @param S Product. * @return this+S. */ public Product sum(Product S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } SortedMap elem = new TreeMap(val); // clone SortedMap sel = S.val; for (Map.Entry is : sel.entrySet()) { Integer i = is.getKey(); C x = elem.get(i); C y = is.getValue(); //sel.get( i ); // assert y != null if (x != null) { x = x.sum(y); if (!x.isZERO()) { elem.put(i, x); } else { elem.remove(i); } } else { elem.put(i, y); } } return new Product(ring, elem); } /** * Product negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public Product negate() { SortedMap elem = new TreeMap(); for (Integer i : val.keySet()) { C v = val.get(i).negate(); elem.put(i, v); } return new Product(ring, elem, isunit); } /** * Product signum. * @see edu.jas.structure.RingElem#signum() * @return signum of first non-zero component. */ public int signum() { if (val.size() == 0) { return 0; } C v = val.get(val.firstKey()); return v.signum(); } /** * Product subtraction. * @param S Product. * @return this-S. */ public Product subtract(Product S) { return sum(S.negate()); } /** * Product quasi-inverse. * @see edu.jas.structure.RingElem#inverse() * @return S with S = 1/this if defined. */ public Product inverse() { if (this.isZERO()) { return this; } int isu = 0; SortedMap elem = new TreeMap(); for (Integer i : val.keySet()) { C x = val.get(i); // is non zero try { x = x.inverse(); } catch (NotInvertibleException e) { // could happen for e.g. ModInteger or AlgebraicNumber x = null; //ring.getFactory(i).getZERO(); } if (x != null && !x.isZERO()) { // can happen elem.put(i, x); isu = 1; } } return new Product(ring, elem, isu); } /** * Product idempotent. * @return smallest S with this*S = this. */ public Product idempotent() { if (this.isZERO()) { return this; } SortedMap elem = new TreeMap(); for (Integer i : val.keySet()) { RingFactory f = ring.getFactory(i); C x = f.getONE(); elem.put(i, x); } return new Product(ring, elem, 1); } /** * Product idempotent complement. * @return 1-this.idempotent(). */ public Product idemComplement() { if (this.isZERO()) { return ring.getONE(); } int isu = 0; SortedMap elem = new TreeMap(); for (int i = 0; i < ring.length(); i++) { C v = val.get(i); if (v == null) { RingFactory f = ring.getFactory(i); C x = f.getONE(); elem.put(i, x); isu = 1; } } return new Product(ring, elem, isu); } /** * Product idempotent and. * @param S Product. * @return this.idempotent() and S.idempotent(). */ public Product idempotentAnd(Product S) { if (this.isZERO() && S.isZERO()) { return this; } int isu = 0; SortedMap elem = new TreeMap(); for (int i = 0; i < ring.length(); i++) { C v = val.get(i); C w = S.val.get(i); if (v != null && w != null) { RingFactory f = ring.getFactory(i); C x = f.getONE(); elem.put(i, x); isu = 1; } } return new Product(ring, elem, isu); } /** * Product idempotent or. * @param S Product. * @return this.idempotent() or S.idempotent(). */ public Product idempotentOr(Product S) { if (this.isZERO() && S.isZERO()) { return this; } int isu = 0; SortedMap elem = new TreeMap(); for (int i = 0; i < ring.length(); i++) { C v = val.get(i); C w = S.val.get(i); if (v != null || w != null) { RingFactory f = ring.getFactory(i); C x = f.getONE(); elem.put(i, x); isu = 1; } } return new Product(ring, elem, isu); } /** * Product fill with idempotent. * @param S Product. * @return fill this with S.idempotent(). */ public Product fillIdempotent(Product S) { if (S.isZERO()) { return this; } SortedMap elem = new TreeMap(val); for (int i = 0; i < ring.length(); i++) { C v = elem.get(i); if (v != null) { continue; } C w = S.val.get(i); if (w != null) { RingFactory f = ring.getFactory(i); C x = f.getONE(); elem.put(i, x); } } return new Product(ring, elem, isunit); } /** * Product fill with one. * @return fill this with one. */ public Product fillOne() { if (this.isFull()) { return this; } if (this.isZERO()) { return ring.getONE(); } SortedMap elem = new TreeMap(val); for (int i = 0; i < ring.length(); i++) { C v = elem.get(i); if (v != null) { continue; } RingFactory f = ring.getFactory(i); C x = f.getONE(); elem.put(i, x); } return new Product(ring, elem, isunit); } /** * Product quasi-division. * @param S Product. * @return this/S. */ public Product divide(Product S) { if (S == null) { return ring.getZERO(); } if (S.isZERO()) { return S; } if (this.isZERO()) { return this; } SortedMap elem = new TreeMap(); SortedMap sel = S.val; for (Integer i : val.keySet()) { C y = sel.get(i); if (y != null) { C x = val.get(i); try { x = x.divide(y); } catch (NotInvertibleException e) { // should not happen any more System.out.println("product divide error: x = " + x + ", y = " + y); // could happen for e.g. ModInteger or AlgebraicNumber x = null; //ring.getFactory(i).getZERO(); } if (x != null && !x.isZERO()) { // can happen elem.put(i, x); } } } return new Product(ring, elem); } /** * Product quasi-remainder. * @param S Product. * @return this - (this/S)*S. */ public Product remainder(Product S) { if (S == null) { return this; //ring.getZERO(); } if (S.isZERO()) { return this; } if (this.isZERO()) { return this; } SortedMap elem = new TreeMap(); SortedMap sel = S.val; for (Integer i : val.keySet()) { C y = sel.get(i); if (y != null) { C x = val.get(i); x = x.remainder(y); if (x != null && !x.isZERO()) { // can happen elem.put(i, x); } } } return new Product(ring, elem); } /** * Product multiplication. * @param S Product. * @return this*S. */ public Product multiply(Product S) { if (S == null) { return ring.getZERO(); } if (S.isZERO()) { return S; } if (this.isZERO()) { return this; } SortedMap elem = new TreeMap(); SortedMap sel = S.val; for (Integer i : val.keySet()) { C y = sel.get(i); if (y != null) { C x = val.get(i); x = x.multiply(y); if (x != null && !x.isZERO()) { elem.put(i, x); } } } return new Product(ring, elem); } /** * Product multiply by coefficient. * @param c coefficient. * @return this*c. */ public Product multiply(C c) { SortedMap elem = new TreeMap(); for (Integer i : val.keySet()) { C v = val.get(i).multiply(c); if (v != null && !v.isZERO()) { elem.put(i, v); } } return new Product(ring, elem); } /** * Greatest common divisor. * @param S other element. * @return gcd(this,S). */ public Product gcd(Product S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } SortedMap elem = new TreeMap(val); // clone SortedMap sel = S.val; for (Map.Entry is : sel.entrySet()) { Integer i = is.getKey(); C x = elem.get(i); C y = is.getValue(); //sel.get( i ); // assert y != null if (x != null) { x = x.gcd(y); if (x != null && !x.isZERO()) { elem.put(i, x); } else { elem.remove(i); } } else { elem.put(i, y); } } return new Product(ring, elem); } /** * Extended greatest common divisor. * @param S other element. * @return [ gcd(this,S), c1, c2 ] with c1*this + c2*b = gcd(this,S). */ @SuppressWarnings("unchecked") public Product[] egcd(Product S) { Product[] ret = (Product[]) new Product[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; return ret; } if (this.isZERO()) { ret[0] = S; return ret; } SortedMap elem = new TreeMap(val); // clone SortedMap elem1 = this.idempotent().val; // init with 1 SortedMap elem2 = new TreeMap(); // zero SortedMap sel = S.val; for (Map.Entry is : sel.entrySet()) { Integer i = is.getKey(); C x = elem.get(i); C y = is.getValue(); //sel.get( i ); // assert y != null if (x != null) { C[] g = x.egcd(y); if (!g[0].isZERO()) { elem.put(i, g[0]); elem1.put(i, g[1]); elem2.put(i, g[2]); } else { elem.remove(i); } } else { elem.put(i, y); elem2.put(i, ring.getFactory(i).getONE()); } } ret[0] = new Product(ring, elem); ret[1] = new Product(ring, elem1); ret[2] = new Product(ring, elem2); return ret; } } jas-2.5/src/edu/jas/arith/ProductRing.java0000644000175000017500000003465112004277700020706 0ustar giovannigiovanni/* * $Id: ProductRing.java 4054 2012-07-26 17:34:57Z kredel $ */ package edu.jas.arith; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Direct product ring factory based on RingElem and RingFactory module. Objects * of this class are mutable. * @author Heinz Kredel */ public class ProductRing> implements RingFactory> { private static final Logger logger = Logger.getLogger(ProductRing.class); //private boolean debug = logger.isDebugEnabled(); /** * Ring factory is n copies. */ protected int nCopies; /** * One Ring factory. */ protected final RingFactory ring; /** * Ring factory list. */ protected final List> ringList; /** * A default random sequence generator. */ protected final static Random random = new Random(); /** * The constructor creates a ProductRing object from an ring factory and a * modul. * @param r ring factory. * @param n number of copies. */ public ProductRing(RingFactory r, int n) { ring = r; nCopies = n; ringList = null; } /** * The constructor creates a ProductRing object from an ring factory and a * modul. * @param l list of ring factories. */ public ProductRing(List> l) { ringList = l; ring = null; nCopies = 0; } /** * Get ring factory at index i. * @param i index. * @return RingFactory_i. */ public RingFactory getFactory(int i) { if (nCopies != 0) { if (0 <= i && i < nCopies) { return ring; } logger.info("index: " + i); throw new IllegalArgumentException("index out of bound " + this); } return ringList.get(i); } /** * Add a ring factory. * @param rf new ring factory. */ public synchronized void addFactory(RingFactory rf) { if (nCopies != 0) { if (ring.equals(rf)) { nCopies++; } throw new IllegalArgumentException("wrong RingFactory: " + rf); } ringList.add(rf); } /** * Contains a ring factory. * @param rf ring factory. * @return true, if rf is contained in this, else false. */ public boolean containsFactory(RingFactory rf) { if (nCopies != 0) { if (ring.equals(rf)) { return true; } return false; // misleading } return ringList.contains(rf); } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { if (nCopies != 0) { return ring.isFinite(); } for (RingFactory f : ringList) { boolean b = f.isFinite(); if (!b) { return false; } } return true; } /** * Copy Product element c. * @param c * @return a copy of c. */ public Product copy(Product c) { return new Product(c.ring, c.val, c.isunit); } /** * Get the zero element. * @return 0 as Product. */ public Product getZERO() { return new Product(this); } /** * Get the one element. * @return 1 as Product. */ public Product getONE() { SortedMap elem = new TreeMap(); if (nCopies != 0) { for (int i = 0; i < nCopies; i++) { elem.put(i, ring.getONE()); } } else { int i = 0; for (RingFactory f : ringList) { elem.put(i, f.getONE()); i++; } } return new Product(this, elem, 1); } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List> gens = new ArrayList>(/*nCopies*ring.generators.size()*/); int n = nCopies; if (n == 0) { n = ringList.size(); } for (int i = 0; i < n; i++) { //System.out.println("i = " + i + ", n = " + n); RingFactory f = getFactory(i); List rgens = f.generators(); for (C c : rgens) { SortedMap elem = new TreeMap(); elem.put(i, c); Product g = new Product(this, elem); //g = g.fillOne(); gens.add(g); } } return gens; } /** * Get an atomic element. * @param i index. * @return e_i as Product. */ public Product getAtomic(int i) { if (i < 0 || i >= length()) { throw new IllegalArgumentException("index out of bounds " + i); } SortedMap elem = new TreeMap(); if (nCopies != 0) { elem.put(i, ring.getONE()); } else { RingFactory f = ringList.get(i); elem.put(i, f.getONE()); } return new Product(this, elem, 1); } /** * Get the number of factors of this ring. * @return nCopies or ringList.size(). */ public int length() { if (nCopies != 0) { return nCopies; } return ringList.size(); } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { if (nCopies != 0) { return ring.isCommutative(); } for (RingFactory f : ringList) { if (!f.isCommutative()) { return false; } } return true; } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { if (nCopies != 0) { return ring.isAssociative(); } for (RingFactory f : ringList) { if (!f.isAssociative()) { return false; } } return true; } /** * Query if this ring is a field. * @return true or false. */ public boolean isField() { if (nCopies != 0) { if (nCopies == 1) { return ring.isField(); } } else { if (ringList.size() == 1) { return ringList.get(0).isField(); } } return false; } /** * Query if this ring consists only of fields. * @return true or false. */ public boolean onlyFields() { if (nCopies != 0) { return ring.isField(); } for (RingFactory f : ringList) { if (!f.isField()) { return false; } } return true; } /** * Characteristic of this ring. * @return minimal characteristic of ring component. */ public java.math.BigInteger characteristic() { if (nCopies != 0) { return ring.characteristic(); } java.math.BigInteger c = null; java.math.BigInteger d; for (RingFactory f : ringList) { if (c == null) { c = f.characteristic(); } else { d = f.characteristic(); if (c.compareTo(d) > 0) { // c > d c = d; } } } return c; } /** * Get a Product element from a BigInteger value. * @param a BigInteger. * @return a Product. */ public Product fromInteger(java.math.BigInteger a) { SortedMap elem = new TreeMap(); if (nCopies != 0) { C c = ring.fromInteger(a); for (int i = 0; i < nCopies; i++) { elem.put(i, c); } } else { int i = 0; for (RingFactory f : ringList) { elem.put(i, f.fromInteger(a)); i++; } } return new Product(this, elem); } /** * Get a Product element from a long value. * @param a long. * @return a Product. */ public Product fromInteger(long a) { return fromInteger(new java.math.BigInteger("" + a)); } /** * Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { if (nCopies != 0) { String cf = ring.toString(); if (cf.matches("[0-9].*")) { cf = ring.getClass().getSimpleName(); } return "ProductRing[ " + cf + "^" + nCopies + " ]"; } StringBuffer sb = new StringBuffer("ProductRing[ "); int i = 0; for (RingFactory f : ringList) { if (i != 0) { sb.append(", "); } String cf = f.toString(); if (cf.matches("[0-9].*")) { cf = f.getClass().getSimpleName(); } sb.append(cf); i++; } sb.append(" ]"); return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer("RR( [ "); for (int i = 0; i < length(); i++) { if (i > 0) { s.append(", "); } RingFactory v = getFactory(i); String f = null; try { f = ((RingElem) v).toScriptFactory(); // sic } catch (Exception e) { f = v.toScript(); } s.append(f); } s.append(" ] )"); return s.toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof ProductRing)) { return false; } ProductRing a = null; try { a = (ProductRing) b; } catch (ClassCastException e) { } if (a == null) { return false; } if (nCopies != 0) { if (nCopies != a.nCopies || !ring.equals(a.ring)) { return false; } } else { if (ringList.size() != a.ringList.size()) { return false; } int i = 0; for (RingFactory f : ringList) { if (!f.equals(a.ringList.get(i))) { return false; } i++; } } return true; } /** * Hash code for this product ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = 0; if (nCopies != 0) { h = ring.hashCode(); h = 37 * h + nCopies; } else { for (RingFactory f : ringList) { h = 37 * h + f.hashCode(); } } return h; } /** * Product random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random product element v. */ public Product random(int n) { return random(n, 0.5f); } /** * Product random. * @param n such that 0 ≤ v ≤ (2n-1). * @param q density of nozero entries. * @return a random product element v. */ public Product random(int n, float q) { return random(n, q, random); } /** * Product random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random product element v. */ public Product random(int n, Random rnd) { return random(n, 0.5f, random); } /** * Product random. * @param n such that 0 ≤ v ≤ (2n-1). * @param q density of nozero entries. * @param rnd is a source for random bits. * @return a random product element v. */ public Product random(int n, float q, Random rnd) { SortedMap elem = new TreeMap(); float d; if (nCopies != 0) { for (int i = 0; i < nCopies; i++) { d = rnd.nextFloat(); if (d < q) { C r = ring.random(n, rnd); if (!r.isZERO()) { elem.put(i, r); } } } } else { int i = 0; for (RingFactory f : ringList) { d = rnd.nextFloat(); if (d < q) { C r = f.random(n, rnd); if (!r.isZERO()) { elem.put(i, r); } } i++; } } return new Product(this, elem); } /** * Parse Product from String. * @param s String. * @return Product from s. */ public Product parse(String s) { StringReader sr = new StringReader(s); return parse(sr); } /** * Parse Product from Reader. Syntax: p1 ... pn (no commas) * @param r Reader. * @return next Product from r. */ public Product parse(Reader r) { SortedMap elem = new TreeMap(); if (nCopies != 0) { for (int i = 0; i < nCopies; i++) { elem.put(i, ring.parse(r)); } } else { int i = 0; for (RingFactory f : ringList) { elem.put(i, f.parse(r)); i++; } } return new Product(this, elem); } } jas-2.5/src/edu/jas/arith/BigDecimal.java0000644000175000017500000003634712063147054020435 0ustar giovannigiovanni/* * $Id: BigDecimal.java 4315 2012-12-15 19:23:25Z kredel $ */ package edu.jas.arith; import java.io.Reader; import java.math.MathContext; import java.util.ArrayList; import java.util.List; import java.util.Random; import edu.jas.kern.StringUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * BigDecimal class to make java.math.BigDecimal available with RingElem * interface. Objects of this class are immutable. Experimental, use with care, * compareTo is hacked. * @author Heinz Kredel * @see java.math.BigDecimal */ public final class BigDecimal implements GcdRingElem, RingFactory { /** * The data structure. */ public final java.math.BigDecimal val; private final static Random random = new Random(); //public static final int DEFAULT_PRECISION = 50; //public static final MathContext DEFAULT_CONTEXT = new MathContext(DEFAULT_PRECISION); public static final MathContext DEFAULT_CONTEXT = MathContext.DECIMAL128; public static final int DEFAULT_PRECISION = DEFAULT_CONTEXT.getPrecision(); public final MathContext context; /** * The constant 0. */ public final static BigDecimal ZERO = new BigDecimal(java.math.BigDecimal.ZERO); /** * The constant 1. */ public final static BigDecimal ONE = new BigDecimal(java.math.BigDecimal.ONE); /** * Constructor for BigDecimal from math.BigDecimal. * @param a java.math.BigDecimal. */ public BigDecimal(java.math.BigDecimal a) { this(a, DEFAULT_CONTEXT); } /** * Constructor for BigDecimal from math.BigDecimal. * @param a java.math.BigDecimal. * @param mc MathContext. */ public BigDecimal(java.math.BigDecimal a, MathContext mc) { val = a; context = mc; } /** * Constructor for BigDecimal from long. * @param a long. */ public BigDecimal(long a) { this(a, DEFAULT_CONTEXT); } /** * Constructor for BigDecimal from long and a context. * @param a long. * @param mc MathContext. */ public BigDecimal(long a, MathContext mc) { this(new java.math.BigDecimal(String.valueOf(a)), mc); } /** * Constructor for BigDecimal from double. * @param a double. */ public BigDecimal(double a) { this(a, DEFAULT_CONTEXT); } /** * Constructor for BigDecimal from double and a context. * @param a double. * @param mc MathContext. */ public BigDecimal(double a, MathContext mc) { this(new java.math.BigDecimal(a), mc); } /** * Constructor for BigDecimal from java.math.BigInteger. * @param a java.math.BigInteger. */ public BigDecimal(java.math.BigInteger a) { this(a, DEFAULT_CONTEXT); } /** * Constructor for BigDecimal from java.math.BigInteger. * @param a java.math.BigInteger. * @param mc MathContext. */ public BigDecimal(java.math.BigInteger a, MathContext mc) { this(new java.math.BigDecimal(a), mc); } /** * Constructor for BigDecimal from BigRational. * @param a edu.jas.arith.BigRational. */ public BigDecimal(BigRational a) { this(a, DEFAULT_CONTEXT); } /** * Constructor for BigDecimal from BigRational. * @param a edu.jas.arith.BigRational. * @param mc MathContext. */ public BigDecimal(BigRational a, MathContext mc) { this((new java.math.BigDecimal(a.num,mc)).divide(new java.math.BigDecimal(a.den,mc), mc), mc); } /** * Constructor for BigDecimal from String. * @param s String. */ public BigDecimal(String s) { this(s, DEFAULT_CONTEXT); } /** * Constructor for BigDecimal from String. * @param s String. * @param mc MathContext. */ public BigDecimal(String s, MathContext mc) { this(new java.math.BigDecimal(s.trim()), mc); } /** * Constructor for BigDecimal without parameters. */ public BigDecimal() { this(java.math.BigDecimal.ZERO, DEFAULT_CONTEXT); } /** * Get the value. * @return val java.math.BigDecimal. public java.math.BigDecimal getVal() { * return val; } */ /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public BigDecimal factory() { return this; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List generators() { List g = new ArrayList(1); g.add(getONE()); return g; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() Note: is actually * finite but returns false. */ public boolean isFinite() { return false; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public BigDecimal copy() { return new BigDecimal(val, context); } /** * Copy BigDecimal element c. * @param c BigDecimal. * @return a copy of c. */ public BigDecimal copy(BigDecimal c) { return new BigDecimal(c.val, c.context); } /** * Get the zero element. * @return 0. */ public BigDecimal getZERO() { return ZERO; } /** * Get the one element. * @return 1. */ public BigDecimal getONE() { return ONE; } /** * Query if this ring is commutative. * @return true. */ public boolean isCommutative() { return true; } /** * Query if this ring is associative. Floating point number addition is not * associative, but multiplication is. * @return true. */ public boolean isAssociative() { return true; } /** * Query if this ring is a field. * @return true. */ public boolean isField() { return true; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return java.math.BigInteger.ZERO; } /** * Get a BigDecimal element from a math.BigDecimal. * @param a math.BigDecimal. * @return a as BigDecimal. */ public BigDecimal fromInteger(java.math.BigInteger a) { return new BigDecimal(new java.math.BigDecimal(a), context); } /** * Get a BigDecimal element from a math.BigDecimal. * @param a math.BigDecimal. * @return a as BigDecimal. */ public static BigDecimal valueOf(java.math.BigDecimal a) { return new BigDecimal(a, DEFAULT_CONTEXT); } /** * Get a BigDecimal element from long. * @param a long. * @return a as BigDecimal. */ public BigDecimal fromInteger(long a) { return new BigDecimal(a, context); } /** * Get a BigDecimal element from long. * @param a long. * @return a as BigDecimal. */ public static BigDecimal valueOf(long a) { return new BigDecimal(a, DEFAULT_CONTEXT); } /** * Is BigDecimal number zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return val.compareTo(java.math.BigDecimal.ZERO) == 0; } /** * Is BigDecimal number one. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return val.compareTo(java.math.BigDecimal.ONE) == 0; } /** * Is BigDecimal number unit. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { return (!isZERO()); } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { //return val.toString() + "(ulp=" + val.ulp() + ")"; return val.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return "DD()"; } /** * Compare to BigDecimal b. Experimental, is hacked. * @param b BigDecimal. * @return 0 if abs(this-b) < epsilon, 1 if this > b, -1 if this < b. */ //JAVA6only: @Override public int compareTo(BigDecimal b) { //if (false) { // return val.compareTo(b.val); //} java.math.BigDecimal s = val.subtract(b.val, context); java.math.BigDecimal u1 = val.ulp(); java.math.BigDecimal u2 = b.val.ulp(); int u = Math.min(u1.scale(), u2.scale()); //System.out.println("u = " + u + ", s = " + s); java.math.BigDecimal eps; if (u <= 0) { eps = u1.max(u2); } else { eps = u1.min(u2); } //eps = eps.movePointRight(1); //System.out.println("ctx = " + context); //System.out.println("eps = " + eps); int t = s.abs().compareTo(eps); if (t < 1) { return 0; } return s.signum(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object b) { if (!(b instanceof BigDecimal)) { return false; } BigDecimal bi = (BigDecimal) b; return val.equals(bi.val); } /** * Hash code for this BigDecimal. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return val.hashCode(); } /** * Absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public BigDecimal abs() { return new BigDecimal(val.abs(), context); } /* Negative value of this. * @see edu.jas.structure.RingElem#negate() */ public BigDecimal negate() { return new BigDecimal(val.negate(), context); } /** * signum. * @see edu.jas.structure.RingElem#signum() */ public int signum() { return val.signum(); } /** * BigDecimal subtract. * @param S BigDecimal. * @return this-S. */ public BigDecimal subtract(BigDecimal S) { return new BigDecimal(val.subtract(S.val, context)); } /** * BigDecimal divide. * @param S BigDecimal. * @return this/S. */ public BigDecimal divide(BigDecimal S) { return new BigDecimal(val.divide(S.val, context)); } /** * Integer inverse. R is a non-zero integer. S=1/R if defined else 0. * @see edu.jas.structure.RingElem#inverse() */ public BigDecimal inverse() { return ONE.divide(this); } /** * BigDecimal remainder. * @param S BigDecimal. * @return this - (this/S)*S. */ public BigDecimal remainder(BigDecimal S) { return new BigDecimal(val.remainder(S.val, context)); } /** * BigDecimal compute quotient and remainder. * @param S BigDecimal. * @return BigDecimal[] { q, r } with q = this/S and r = rem(this,S). */ public BigDecimal[] quotientRemainder(BigDecimal S) { BigDecimal[] qr = new BigDecimal[2]; java.math.BigDecimal[] C = val.divideAndRemainder(S.val, context); qr[0] = new BigDecimal(C[0]); qr[1] = new BigDecimal(C[1]); return qr; } /** * BigDecimal compute quotient and remainder. * @param S BigDecimal. * @return BigDecimal[] { q, r } with q = this/S and r = rem(this,S). * @deprecated use quotientRemainder() */ @Deprecated public BigDecimal[] divideAndRemainder(BigDecimal S) { return quotientRemainder(S); } /** * BigDecimal greatest common divisor. * @param S BigDecimal. * @return gcd(this,S). */ public BigDecimal gcd(BigDecimal S) { throw new UnsupportedOperationException("BigDecimal.gcd() not implemented"); //return new BigDecimal( val.gcd( S.val ) ); } /** * BigDecimal extended greatest common divisor. * @param S BigDecimal. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ public BigDecimal[] egcd(BigDecimal S) { throw new UnsupportedOperationException("BigDecimal.egcd() not implemented"); } /** * BigDecimal random. * @param n such that 0 ≤ val(r) ≤ (2n-1). 0 ≤ exp(r) * ≤ (100-1). * @return r, a random BigDecimal. */ public BigDecimal random(int n) { return random(n, random); } /** * BigDecimal random. * @param n such that 0 ≤ val(r) ≤ (2n-1). 0 ≤ exp(r) * ≤ (100-1). * @param rnd is a source for random bits. * @return r, a random BigDecimal. */ public BigDecimal random(int n, Random rnd) { return random(n, 100, rnd); } /** * BigDecimal random. * @param n such that 0 ≤ val(r) ≤ (2n-1). * @param e such that 0 ≤ exp(r) ≤ (e-1). * @return r, a random BigDecimal. */ public BigDecimal random(int n, int e) { return random(n, e, random); } /** * BigDecimal random. * @param n such that 0 ≤ val(r) ≤ (2n-1). * @param e such that 0 ≤ exp(r) ≤ (e-1). * @param rnd is a source for random bits. * @return r, a random BigDecimal. */ public BigDecimal random(int n, int e, Random rnd) { java.math.BigInteger r = new java.math.BigInteger(n, rnd); if (rnd.nextBoolean()) { r = r.negate(); } int scale = rnd.nextInt(e); if (rnd.nextBoolean()) { scale = -scale; } java.math.BigDecimal d = new java.math.BigDecimal(r, scale, context); return new BigDecimal(d, context); } /** * BigDecimal multiply. * @param S BigDecimal. * @return this*S. */ public BigDecimal multiply(BigDecimal S) { return new BigDecimal(val.multiply(S.val, context)); } /** * BigDecimal summation. * @param S BigDecimal. * @return this+S. */ public BigDecimal sum(BigDecimal S) { return new BigDecimal(val.add(S.val, context)); } /** * BigDecimal parse from String. * @param s String. * @return Biginteger from s. */ public BigDecimal parse(String s) { return new BigDecimal(s, context); } /** * BigDecimal parse from Reader. * @param r Reader. * @return next Biginteger from r. */ public BigDecimal parse(Reader r) { return parse(StringUtil.nextString(r)); } } jas-2.5/src/edu/jas/arith/PrimeList.java0000644000175000017500000002536612040773636020372 0ustar giovannigiovanni/* * $Id: PrimeList.java 4262 2012-10-21 13:24:47Z kredel $ */ package edu.jas.arith; // import java.util.Random; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import edu.jas.structure.Power; /** * List of big primes. Provides an Iterator for generating prime numbers. * Similar to ALDES/SAC2 SACPOL.PRIME list. * * @author Heinz Kredel See Knuth vol 2,page 390, for list of known primes. See * also ALDES/SAC2 SACPOL.PRIME */ public final class PrimeList implements Iterable { /** * Range of probable primes. */ public static enum Range { small, low, medium, large, mersenne }; /** * Cache the val list for different size */ private volatile static List SMALL_LIST = null; private volatile static List LOW_LIST = null; private volatile static List MEDIUM_LIST = null; private volatile static List LARGE_LIST = null; private volatile static List MERSENNE_LIST = null; /** * The list of probable primes in requested range. */ private List val = null; /** * The last prime in the list. */ private java.math.BigInteger last; /** * Constructor for PrimeList. */ public PrimeList() { this(Range.medium); } /** * Constructor for PrimeList. * * @param r size range for primes. */ public PrimeList(Range r) { // initialize with some known primes, see knuth (2,390) switch (r) { case small: if (SMALL_LIST != null) { val = SMALL_LIST; } else { val = new ArrayList(50); addSmall(); SMALL_LIST = val; } break; case low: if (LOW_LIST != null) { val = LOW_LIST; } else { val = new ArrayList(50); addLow(); LOW_LIST = val; } break; default: case medium: if (MEDIUM_LIST != null) { val = MEDIUM_LIST; } else { val = new ArrayList(50); addMedium(); MEDIUM_LIST = val; } break; case large: if (LARGE_LIST != null) { val = LARGE_LIST; } else { val = new ArrayList(50); addLarge(); LARGE_LIST = val; } break; case mersenne: if (MERSENNE_LIST != null) { val = MERSENNE_LIST; } else { val = new ArrayList(50); addMersenne(); MERSENNE_LIST = val; } break; } last = get(size() - 1); } /** * Add small primes. */ private void addSmall() { // really small val.add(java.math.BigInteger.valueOf(2L)); val.add(java.math.BigInteger.valueOf(3L)); val.add(java.math.BigInteger.valueOf(5L)); val.add(java.math.BigInteger.valueOf(7L)); val.add(java.math.BigInteger.valueOf(11L)); val.add(java.math.BigInteger.valueOf(13L)); val.add(java.math.BigInteger.valueOf(17L)); val.add(java.math.BigInteger.valueOf(19L)); val.add(java.math.BigInteger.valueOf(23L)); val.add(java.math.BigInteger.valueOf(29L)); } /** * Add low sized primes. */ private void addLow() { // 2^15-x val.add(getLongPrime(15, 19)); val.add(getLongPrime(15, 49)); val.add(getLongPrime(15, 51)); val.add(getLongPrime(15, 55)); val.add(getLongPrime(15, 61)); val.add(getLongPrime(15, 75)); val.add(getLongPrime(15, 81)); val.add(getLongPrime(15, 115)); val.add(getLongPrime(15, 121)); val.add(getLongPrime(15, 135)); // 2^16-x val.add(getLongPrime(16, 15)); val.add(getLongPrime(16, 17)); val.add(getLongPrime(16, 39)); val.add(getLongPrime(16, 57)); val.add(getLongPrime(16, 87)); val.add(getLongPrime(16, 89)); val.add(getLongPrime(16, 99)); val.add(getLongPrime(16, 113)); val.add(getLongPrime(16, 117)); val.add(getLongPrime(16, 123)); } /** * Add medium sized primes. */ private void addMedium() { // 2^28-x val.add(getLongPrime(28, 57)); val.add(getLongPrime(28, 89)); val.add(getLongPrime(28, 95)); val.add(getLongPrime(28, 119)); val.add(getLongPrime(28, 125)); val.add(getLongPrime(28, 143)); val.add(getLongPrime(28, 165)); val.add(getLongPrime(28, 183)); val.add(getLongPrime(28, 213)); val.add(getLongPrime(28, 273)); // 2^29-x val.add(getLongPrime(29, 3)); val.add(getLongPrime(29, 33)); val.add(getLongPrime(29, 43)); val.add(getLongPrime(29, 63)); val.add(getLongPrime(29, 73)); val.add(getLongPrime(29, 75)); val.add(getLongPrime(29, 93)); val.add(getLongPrime(29, 99)); val.add(getLongPrime(29, 121)); val.add(getLongPrime(29, 133)); // 2^32-x val.add(getLongPrime(32, 5)); val.add(getLongPrime(32, 17)); val.add(getLongPrime(32, 65)); val.add(getLongPrime(32, 99)); val.add(getLongPrime(32, 107)); val.add(getLongPrime(32, 135)); val.add(getLongPrime(32, 153)); val.add(getLongPrime(32, 185)); val.add(getLongPrime(32, 209)); val.add(getLongPrime(32, 267)); } /** * Add large sized primes. */ private void addLarge() { // 2^59-x val.add(getLongPrime(59, 55)); val.add(getLongPrime(59, 99)); val.add(getLongPrime(59, 225)); val.add(getLongPrime(59, 427)); val.add(getLongPrime(59, 517)); val.add(getLongPrime(59, 607)); val.add(getLongPrime(59, 649)); val.add(getLongPrime(59, 687)); val.add(getLongPrime(59, 861)); val.add(getLongPrime(59, 871)); // 2^60-x val.add(getLongPrime(60, 93)); val.add(getLongPrime(60, 107)); val.add(getLongPrime(60, 173)); val.add(getLongPrime(60, 179)); val.add(getLongPrime(60, 257)); val.add(getLongPrime(60, 279)); val.add(getLongPrime(60, 369)); val.add(getLongPrime(60, 395)); val.add(getLongPrime(60, 399)); val.add(getLongPrime(60, 453)); // 2^63-x val.add(getLongPrime(63, 25)); val.add(getLongPrime(63, 165)); val.add(getLongPrime(63, 259)); val.add(getLongPrime(63, 301)); val.add(getLongPrime(63, 375)); val.add(getLongPrime(63, 387)); val.add(getLongPrime(63, 391)); val.add(getLongPrime(63, 409)); val.add(getLongPrime(63, 457)); val.add(getLongPrime(63, 471)); // 2^64-x not possible } /** * Add Mersenne sized primes. */ private void addMersenne() { // 2^n-1 val.add(getMersennePrime(2)); val.add(getMersennePrime(3)); val.add(getMersennePrime(5)); val.add(getMersennePrime(7)); val.add(getMersennePrime(13)); val.add(getMersennePrime(17)); val.add(getMersennePrime(19)); val.add(getMersennePrime(31)); val.add(getMersennePrime(61)); val.add(getMersennePrime(89)); val.add(getMersennePrime(107)); val.add(getMersennePrime(127)); val.add(getMersennePrime(521)); val.add(getMersennePrime(607)); val.add(getMersennePrime(1279)); val.add(getMersennePrime(2203)); val.add(getMersennePrime(2281)); val.add(getMersennePrime(3217)); val.add(getMersennePrime(4253)); val.add(getMersennePrime(4423)); val.add(getMersennePrime(9689)); val.add(getMersennePrime(9941)); val.add(getMersennePrime(11213)); val.add(getMersennePrime(19937)); } /** * Method to compute a prime as 2**n - m. * @param n power for 2. * @param m for 2**n - m. * @return 2**n - m */ public static java.math.BigInteger getLongPrime(int n, int m) { long prime = 2; // knuth (2,390) for (int i = 1; i < n; i++) { prime *= 2; } prime -= m; // System.out.println("p1 = " + prime); return java.math.BigInteger.valueOf(prime); } /** * Method to compute a Mersenne prime as 2**n - 1. * @param n power for 2. * @return 2**n - 1 */ public static java.math.BigInteger getMersennePrime(int n) { BigInteger t = new BigInteger(2); BigInteger p = Power.positivePower(t, n); p = p.subtract(new BigInteger(1)); java.math.BigInteger prime = p.getVal(); // System.out.println("p1 = " + prime); return prime; } /** * Check if the list contains really prime numbers. */ protected boolean checkPrimes() { return checkPrimes(size()); } /** * Check if the list contains really prime numbers. */ protected boolean checkPrimes(int n) { boolean isPrime; int i = 0; for (java.math.BigInteger p : val) { if (i++ >= n) { break; } isPrime = p.isProbablePrime(63); if (!isPrime) { System.out.println("not prime = " + p); return false; } } return true; } /** * toString. */ @Override public String toString() { return val.toString(); } /** * size of current list. */ public int size() { return val.size(); } /** * get prime at index i. */ public java.math.BigInteger get(int i) { java.math.BigInteger p; if (i < size()) { p = val.get(i); } else { p = last.nextProbablePrime(); val.add(p); last = p; } return p; } /** * Iterator. */ public Iterator iterator() { return new Iterator() { int index = -1; public boolean hasNext() { return true; } public void remove() { throw new UnsupportedOperationException("remove not implemented"); } public java.math.BigInteger next() { index++; return get(index); } }; } } jas-2.5/src/edu/jas/arith/ModInteger.java0000644000175000017500000003746612020212506020501 0ustar giovannigiovanni/* * $Id: ModInteger.java 4148 2012-08-31 19:49:27Z kredel $ */ package edu.jas.arith; import edu.jas.structure.GcdRingElem; import edu.jas.structure.NotInvertibleException; /** * ModInteger class with GcdRingElem interface. Objects of this class are * immutable. The SAC2 static methods are also provided. * @author Heinz Kredel * @see java.math.BigInteger */ public final class ModInteger implements GcdRingElem, Modular { /** * ModIntegerRing reference. */ public final ModIntegerRing ring; /** * Value part of the element data structure. */ public final java.math.BigInteger val; /** * The constructor creates a ModInteger object from a ModIntegerRing and a * value part. * @param m ModIntegerRing. * @param a math.BigInteger. */ public ModInteger(ModIntegerRing m, java.math.BigInteger a) { ring = m; val = a.mod(ring.modul); } /** * The constructor creates a ModInteger object from a ModIntegerRing and a * long value part. * @param m ModIntegerRing. * @param a long. */ public ModInteger(ModIntegerRing m, long a) { this(m, new java.math.BigInteger(String.valueOf(a))); } /** * The constructor creates a ModInteger object from a ModIntegerRing and a * String value part. * @param m ModIntegerRing. * @param s String. */ public ModInteger(ModIntegerRing m, String s) { this(m, new java.math.BigInteger(s.trim())); } /** * The constructor creates a 0 ModInteger object from a given * ModIntegerRing. * @param m ModIntegerRing. */ public ModInteger(ModIntegerRing m) { this(m, java.math.BigInteger.ZERO); } /** * Get the value part. * @return val. */ public java.math.BigInteger getVal() { return val; } /** * Get the module part. * @return modul. */ public java.math.BigInteger getModul() { return ring.modul; } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public ModIntegerRing factory() { return ring; } /** * Get the symmetric value part. * @return val with -modul/2 <= val < modul/2. */ public java.math.BigInteger getSymmetricVal() { if (val.add(val).compareTo(ring.modul) > 0) { // val > m/2 as 2*val > m, make symmetric to 0 return val.subtract(ring.modul); } return val; } /** * Return a BigInteger from this Element. * @return a BigInteger of this. */ public BigInteger getInteger() { return new BigInteger(val); } /** * Return a symmetric BigInteger from this Element. * @return a symmetric BigInteger of this. */ public BigInteger getSymmetricInteger() { java.math.BigInteger v = val; if (val.add(val).compareTo(ring.modul) > 0) { // val > m/2 as 2*val > m, make symmetric to 0 v = val.subtract(ring.modul); } return new BigInteger(v); } /** * Clone this. * @see java.lang.Object#clone() */ @Override public ModInteger copy() { return new ModInteger(ring, val); } /** * Is ModInteger number zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return val.equals(java.math.BigInteger.ZERO); } /** * Is ModInteger number one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return val.equals(java.math.BigInteger.ONE); } /** * Is ModInteger number a unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (isZERO()) { return false; } if (ring.isField()) { return true; } java.math.BigInteger g = ring.modul.gcd(val).abs(); return (g.equals(java.math.BigInteger.ONE)); } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return val.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * ModInteger comparison. * @param b ModInteger. * @return sign(this-b). */ //JAVA6only: @Override public int compareTo(ModInteger b) { java.math.BigInteger v = b.val; if (ring != b.ring) { v = v.mod(ring.modul); } return val.compareTo(v); } /** * ModInteger comparison. * @param A ModInteger. * @param B ModInteger. * @return sign(this-b). */ public static int MICOMP(ModInteger A, ModInteger B) { if (A == null) return -B.signum(); return A.compareTo(B); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object b) { if (!(b instanceof ModInteger)) { return false; } return (0 == compareTo((ModInteger) b)); } /** * Hash code for this ModInteger. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { //return 37 * val.hashCode(); return val.hashCode(); } /** * ModInteger absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public ModInteger abs() { return new ModInteger(ring, val.abs()); } /** * ModInteger absolute value. * @param A ModInteger. * @return the absolute value of A. */ public static ModInteger MIABS(ModInteger A) { if (A == null) return null; return A.abs(); } /** * ModInteger negative. * @see edu.jas.structure.RingElem#negate() * @return -this. */ public ModInteger negate() { return new ModInteger(ring, val.negate()); } /** * ModInteger negative. * @param A ModInteger. * @return -A. */ public static ModInteger MINEG(ModInteger A) { if (A == null) return null; return A.negate(); } /** * ModInteger signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { return val.signum(); } /** * ModInteger signum. * @param A ModInteger * @return signum(A). */ public static int MISIGN(ModInteger A) { if (A == null) return 0; return A.signum(); } /** * ModInteger subtraction. * @param S ModInteger. * @return this-S. */ public ModInteger subtract(ModInteger S) { return new ModInteger(ring, val.subtract(S.val)); } /** * ModInteger subtraction. * @param A ModInteger. * @param B ModInteger. * @return A-B. */ public static ModInteger MIDIF(ModInteger A, ModInteger B) { if (A == null) return B.negate(); return A.subtract(B); } /** * ModInteger divide. * @param S ModInteger. * @return this/S. */ public ModInteger divide(ModInteger S) { try { return multiply(S.inverse()); } catch (NotInvertibleException e) { try { if (val.remainder(S.val).equals(java.math.BigInteger.ZERO)) { return new ModInteger(ring, val.divide(S.val)); } throw new NotInvertibleException(e); } catch (ArithmeticException a) { throw new NotInvertibleException(a); } } } /** * ModInteger quotient. * @param A ModInteger. * @param B ModInteger. * @return A/B. */ public static ModInteger MIQ(ModInteger A, ModInteger B) { if (A == null) return null; return A.divide(B); } /** * ModInteger inverse. * @see edu.jas.structure.RingElem#inverse() * @throws NotInvertibleException if the element is not invertible. * @return S with S=1/this if defined. */ public ModInteger inverse() /*throws NotInvertibleException*/{ try { return new ModInteger(ring, val.modInverse(ring.modul)); } catch (ArithmeticException e) { java.math.BigInteger g = val.gcd(ring.modul); java.math.BigInteger f = ring.modul.divide(g); throw new ModularNotInvertibleException(e, new BigInteger(ring.modul), new BigInteger(g), new BigInteger(f)); } } /** * ModInteger inverse. * @param A is a non-zero integer. * @see edu.jas.structure.RingElem#inverse() * @return S with S=1/A if defined. */ public static ModInteger MIINV(ModInteger A) { if (A == null) return null; return A.inverse(); } /** * ModInteger remainder. * @param S ModInteger. * @return remainder(this,S). */ public ModInteger remainder(ModInteger S) { if (S == null || S.isZERO()) { throw new ArithmeticException("division by zero"); } if (S.isONE()) { return ring.getZERO(); } if (S.isUnit()) { return ring.getZERO(); } return new ModInteger(ring, val.remainder(S.val)); } /** * ModInteger remainder. * @param A ModInteger. * @param B ModInteger. * @return A - (A/B)*B. */ public static ModInteger MIREM(ModInteger A, ModInteger B) { if (A == null) return null; return A.remainder(B); } /** * ModInteger multiply. * @param S ModInteger. * @return this*S. */ public ModInteger multiply(ModInteger S) { return new ModInteger(ring, val.multiply(S.val)); } /** * ModInteger product. * @param A ModInteger. * @param B ModInteger. * @return A*B. */ public static ModInteger MIPROD(ModInteger A, ModInteger B) { if (A == null) return null; return A.multiply(B); } /** * ModInteger summation. * @param S ModInteger. * @return this+S. */ public ModInteger sum(ModInteger S) { return new ModInteger(ring, val.add(S.val)); } /** * ModInteger summation. * @param A ModInteger. * @param B ModInteger. * @return A+B. */ public static ModInteger MISUM(ModInteger A, ModInteger B) { if (A == null) return null; return A.sum(B); } /** * ModInteger greatest common divisor. * @param S ModInteger. * @return gcd(this,S). */ public ModInteger gcd(ModInteger S) { if (S.isZERO()) { return this; } if (isZERO()) { return S; } if (isUnit() || S.isUnit()) { return ring.getONE(); } return new ModInteger(ring, val.gcd(S.val)); } /** * ModInteger half extended greatest common divisor. * @param S ModInteger. * @return [ gcd(this,S), a ] with a*this + b*S = gcd(this,S) for some b. */ public ModInteger[] hegcd(ModInteger S) { ModInteger[] ret = new ModInteger[2]; ret[0] = null; ret[1] = null; if (S == null || S.isZERO()) { ret[0] = this; ret[1] = this.ring.getONE(); return ret; } if (isZERO()) { ret[0] = S; return ret; } //System.out.println("this = " + this + ", S = " + S); java.math.BigInteger[] qr; java.math.BigInteger q = this.val; java.math.BigInteger r = S.val; java.math.BigInteger c1 = BigInteger.ONE.val; java.math.BigInteger d1 = BigInteger.ZERO.val; java.math.BigInteger x1; while (!r.equals(java.math.BigInteger.ZERO)) { qr = q.divideAndRemainder(r); q = qr[0]; x1 = c1.subtract(q.multiply(d1)); c1 = d1; d1 = x1; q = r; r = qr[1]; } //System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2); ret[0] = new ModInteger(ring, q); ret[1] = new ModInteger(ring, c1); //assert ( ((c1.multiply(this)).remainder(S).equals(q) )); return ret; } /** * ModInteger extended greatest common divisor. * @param S ModInteger. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ public ModInteger[] egcd(ModInteger S) { ModInteger[] ret = new ModInteger[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; return ret; } if (isZERO()) { ret[0] = S; return ret; } if (this.isUnit() || S.isUnit()) { ret[0] = ring.getONE(); if (this.isUnit() && S.isUnit()) { //ModInteger half = ring.fromInteger(2).inverse(); //ret[1] = this.inverse().multiply(half); //ret[2] = S.inverse().multiply(half); //System.out.println("gcd = " + (ret[1].multiply(this).sum(ret[2].multiply(S)))); // (1-1*this)/S ret[1] = ring.getONE(); ModInteger x = ret[0].subtract(ret[1].multiply(this)); ret[2] = x.divide(S); //System.out.println("gcd, a, b = " + (ret[1]) + ", " + ret[2]); //System.out.println("gcd = " + (ret[1].multiply(this).sum(ret[2].multiply(S)))); return ret; } if (this.isUnit()) { // oder inverse(S-1)? ret[1] = this.inverse(); ret[2] = ring.getZERO(); return ret; } // if ( S.isUnit() ) { // oder inverse(this-1)? ret[1] = ring.getZERO(); ret[2] = S.inverse(); return ret; //} } //System.out.println("this = " + this + ", S = " + S); java.math.BigInteger[] qr; java.math.BigInteger q = this.val; java.math.BigInteger r = S.val; java.math.BigInteger c1 = BigInteger.ONE.val; java.math.BigInteger d1 = BigInteger.ZERO.val; java.math.BigInteger c2 = BigInteger.ZERO.val; java.math.BigInteger d2 = BigInteger.ONE.val; java.math.BigInteger x1; java.math.BigInteger x2; while (!r.equals(java.math.BigInteger.ZERO)) { qr = q.divideAndRemainder(r); q = qr[0]; x1 = c1.subtract(q.multiply(d1)); x2 = c2.subtract(q.multiply(d2)); c1 = d1; c2 = d2; d1 = x1; d2 = x2; q = r; r = qr[1]; } //System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2); ret[0] = new ModInteger(ring, q); ret[1] = new ModInteger(ring, c1); ret[2] = new ModInteger(ring, c2); return ret; } } jas-2.5/src/edu/jas/arith/Modular.java0000644000175000017500000000100511316411566020041 0ustar giovannigiovanni/* * $Id: Modular.java 2934 2009-12-29 14:34:30Z kredel $ */ package edu.jas.arith; /** * Interface with getInteger and getSymmetricInteger methods. * @author Heinz Kredel */ public interface Modular { /** * Return a BigInteger from this Element. * @return a BigInteger of this. */ public BigInteger getInteger(); /** * Return a symmetric BigInteger from this Element. * @return a symmetric BigInteger of this. */ public BigInteger getSymmetricInteger(); } jas-2.5/src/edu/jas/arith/Combinatoric.java0000644000175000017500000000466211676657746021110 0ustar giovannigiovanni/* * $Id: Combinatoric.java 3840 2011-12-28 18:28:55Z kredel $ */ package edu.jas.arith; /** * Combinatoric algorithms. Similar to ALDES/SAC2 SACCOMB module. * @author Heinz Kredel */ public class Combinatoric { /** * Integer binomial coefficient induction. n and k are beta-integers with 0 * less than or equal to k less than or equal to n. A is the binomial * coefficient n over k. B is the binomial coefficient n over k+1. * @param A previous induction result. * @param n long. * @param k long. * @return the binomial coefficient n over k+1. */ public static BigInteger binCoeffInduction(BigInteger A, long n, long k) { BigInteger kp, np; np = new BigInteger(n - k); kp = new BigInteger(k + 1); BigInteger B = A.multiply(np).divide(kp); return B; } /** * Integer binomial coefficient. n and k are beta-integers with 0 less than * or equal to k less than or equal to n. A is the binomial coefficient n * over k. * @param n long. * @param k long. * @return the binomial coefficient n over k+1. */ public static BigInteger binCoeff(int n, int k) { BigInteger A = BigInteger.ONE; int kp = (k < n - k ? k : n - k); for (int j = 0; j < kp; j++) { A = binCoeffInduction(A, n, j); } return A; } /** * Integer binomial coefficient partial sum. n and k are integers, 0 le k le * n. A is the sum on i, from 0 to k, of the binomial coefficient n over i. * @param n long. * @param k long. * @return the binomial coefficient partial sum n over i. */ public static BigInteger binCoeffSum(int n, int k) { BigInteger B, S; S = BigInteger.ONE; B = BigInteger.ONE; for (int j = 0; j < k; j++) { B = binCoeffInduction(B, n, j); S = S.sum(B); } return S; } /** * Factorial. * @param n integer. * @return n!, with 0! = 1. */ public static BigInteger factorial(long n) { if (n <= 1) { return BigInteger.ONE; } BigInteger f = BigInteger.ONE; if (n >= Integer.MAX_VALUE) { throw new UnsupportedOperationException(n + " >= Integer.MAX_VALUE = " + Integer.MAX_VALUE); } for (int i = 2; i <= n; i++) { f = f.multiply(new BigInteger(i)); } return f; } } jas-2.5/src/edu/jas/arith/BigQuaternion.java0000644000175000017500000005746012014234362021216 0ustar giovannigiovanni/* * $Id: BigQuaternion.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.arith; import java.io.Reader; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.StringUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.StarRingElem; /** * BigQuaternion class based on BigRational implementing the RingElem interface * and with the familiar MAS static method names. Objects of this class are * immutable. * @author Heinz Kredel */ public final class BigQuaternion implements StarRingElem, GcdRingElem, RingFactory { /** * Real part of the data structure. */ public final BigRational re; // real part /** * Imaginary part i of the data structure. */ public final BigRational im; // i imaginary part /** * Imaginary part j of the data structure. */ public final BigRational jm; // j imaginary part /** * Imaginary part k of the data structure. */ public final BigRational km; // k imaginary part private final static Random random = new Random(); private static final Logger logger = Logger.getLogger(BigQuaternion.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor for a BigQuaternion from BigRationals. * @param r BigRational. * @param i BigRational. * @param j BigRational. * @param k BigRational. */ public BigQuaternion(BigRational r, BigRational i, BigRational j, BigRational k) { re = r; im = i; jm = j; km = k; } /** * Constructor for a BigQuaternion from BigRationals. * @param r BigRational. * @param i BigRational. * @param j BigRational. */ public BigQuaternion(BigRational r, BigRational i, BigRational j) { this(r, i, j, BigRational.ZERO); } /** * Constructor for a BigQuaternion from BigRationals. * @param r BigRational. * @param i BigRational. */ public BigQuaternion(BigRational r, BigRational i) { this(r, i, BigRational.ZERO); } /** * Constructor for a BigQuaternion from BigRationals. * @param r BigRational. */ public BigQuaternion(BigRational r) { this(r, BigRational.ZERO); } /** * Constructor for a BigQuaternion from BigComplex. * @param r BigComplex. */ public BigQuaternion(BigComplex r) { this(r.re, r.im); } /** * Constructor for a BigQuaternion from long. * @param r long. */ public BigQuaternion(long r) { this(new BigRational(r), BigRational.ZERO); } /** * Constructor for a BigQuaternion with no arguments. */ public BigQuaternion() { this(BigRational.ZERO); } /** * The BigQuaternion string constructor accepts the following formats: empty * string, "rational", or "rat i rat j rat k rat" with no blanks around i, j * or k if used as polynoial coefficient. * @param s String. * @throws NumberFormatException */ public BigQuaternion(String s) throws NumberFormatException { if (s == null || s.length() == 0) { re = BigRational.ZERO; im = BigRational.ZERO; jm = BigRational.ZERO; km = BigRational.ZERO; return; } s = s.trim(); int r = s.indexOf("i") + s.indexOf("j") + s.indexOf("k"); if (r == -3) { re = new BigRational(s); im = BigRational.ZERO; jm = BigRational.ZERO; km = BigRational.ZERO; return; } int i = s.indexOf("i"); String sr = ""; if (i > 0) { sr = s.substring(0, i); } else if (i < 0) { throw new NumberFormatException("BigQuaternion missing i"); } String si = ""; if (i < s.length()) { s = s.substring(i + 1, s.length()); } int j = s.indexOf("j"); if (j > 0) { si = s.substring(0, j); } else if (j < 0) { throw new NumberFormatException("BigQuaternion missing j"); } String sj = ""; if (j < s.length()) { s = s.substring(j + 1, s.length()); } int k = s.indexOf("k"); if (k > 0) { sj = s.substring(0, k); } else if (k < 0) { throw new NumberFormatException("BigQuaternion missing k"); } String sk = ""; if (k < s.length()) { s = s.substring(k + 1, s.length()); } sk = s; re = new BigRational(sr.trim()); im = new BigRational(si.trim()); jm = new BigRational(sj.trim()); km = new BigRational(sk.trim()); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public BigQuaternion factory() { return this; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List generators() { List g = new ArrayList(4); g.add(getONE()); g.add(I); g.add(J); g.add(K); return g; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return false; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public BigQuaternion copy() { return new BigQuaternion(re, im, jm, km); } /** * Copy BigQuaternion element c. * @param c BigQuaternion. * @return a copy of c. */ public BigQuaternion copy(BigQuaternion c) { return new BigQuaternion(c.re, c.im, c.jm, c.km); } /** * Get the zero element. * @return 0 as BigQuaternion. */ public BigQuaternion getZERO() { return ZERO; } /** * Get the one element. * @return q as BigQuaternion. */ public BigQuaternion getONE() { return ONE; } /** * Query if this ring is commutative. * @return false. */ public boolean isCommutative() { return false; } /** * Query if this ring is associative. * @return true. */ public boolean isAssociative() { return true; } /** * Query if this ring is a field. * @return true. */ public boolean isField() { return true; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return java.math.BigInteger.ZERO; } /** * Get a BigQuaternion element from a BigInteger. * @param a BigInteger. * @return a BigQuaternion. */ public BigQuaternion fromInteger(BigInteger a) { return new BigQuaternion(new BigRational(a)); } /** * Get a BigQuaternion element from a long. * @param a long. * @return a BigQuaternion. */ public BigQuaternion fromInteger(long a) { return new BigQuaternion(new BigRational(a)); } /** * The constant 0. */ public static final BigQuaternion ZERO = new BigQuaternion(); /** * The constant 1. */ public static final BigQuaternion ONE = new BigQuaternion(BigRational.ONE); /** * The constant i. */ public static final BigQuaternion I = new BigQuaternion(BigRational.ZERO, BigRational.ONE); /** * The constant j. */ public static final BigQuaternion J = new BigQuaternion(BigRational.ZERO, BigRational.ZERO, BigRational.ONE); /** * The constant k. */ public static final BigQuaternion K = new BigQuaternion(BigRational.ZERO, BigRational.ZERO, BigRational.ZERO, BigRational.ONE); /** * Get the real part. * @return re. */ public BigRational getRe() { return re; } /** * Get the imaginary part im. * @return im. */ public BigRational getIm() { return im; } /** * Get the imaginary part jm. * @return jm. */ public BigRational getJm() { return jm; } /** * Get the imaginary part km. * @return km. */ public BigRational getKm() { return km; } /** * Get the string representation. Is compatible with the string constructor. * @see java.lang.Object#toString() */ @Override public String toString() { String s = "" + re; int i = im.compareTo(BigRational.ZERO); int j = jm.compareTo(BigRational.ZERO); int k = km.compareTo(BigRational.ZERO); if (debug) { logger.debug("compareTo " + im + " ? 0 = " + i); logger.debug("compareTo " + jm + " ? 0 = " + j); logger.debug("compareTo " + km + " ? 0 = " + k); } if (i == 0 && j == 0 && k == 0) return s; s += "i" + im; s += "j" + jm; s += "k" + km; return s; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer(); boolean i = im.isZERO(); boolean j = jm.isZERO(); boolean k = km.isZERO(); if (i && j && k) { if (re.isZERO()) { return "0 "; } if (!re.isONE()) { s.append(re.toScript() + "*"); } s.append("oneQ "); return s.toString(); } if (!re.isZERO()) { if (!re.isONE()) { s.append(re.toScript() + "*"); } s.append("oneQ "); } if (!i) { if (s.length() > 0) { s.append("+ "); } if (!im.isONE()) { s.append(im.toScript() + "*"); } s.append("IQ "); } if (!j) { if (s.length() > 0) { s.append("+ "); } if (!jm.isONE()) { s.append(jm.toScript() + "*"); } s.append("JQ "); } if (!k) { if (s.length() > 0) { s.append("+ "); } if (!km.isONE()) { s.append(km.toScript() + "*"); } s.append("KQ "); } return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return "Quat()"; } /** * Is Quaternion number zero. * @param A BigQuaternion. * @return true if A is 0, else false. */ public static boolean isQZERO(BigQuaternion A) { if (A == null) return false; return A.isZERO(); } /** * Is BigQuaternion number zero. * @return true if this is 0, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return re.equals(BigRational.ZERO) && im.equals(BigRational.ZERO) && jm.equals(BigRational.ZERO) && km.equals(BigRational.ZERO); } /** * Is BigQuaternion number one. * @param A is a quaternion number. * @return true if A is 1, else false. */ public static boolean isQONE(BigQuaternion A) { if (A == null) return false; return A.isONE(); } /** * Is BigQuaternion number one. * @see edu.jas.structure.RingElem#isONE() * @return true if this is 1, else false. */ public boolean isONE() { return re.equals(BigRational.ONE) && im.equals(BigRational.ZERO) && jm.equals(BigRational.ZERO) && km.equals(BigRational.ZERO); } /** * Is BigQuaternion imaginary one. * @return true if this is i, else false. */ public boolean isIMAG() { return re.equals(BigRational.ZERO) && im.equals(BigRational.ONE) && jm.equals(BigRational.ZERO) && km.equals(BigRational.ZERO); } /** * Is BigQuaternion unit element. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { return (!isZERO()); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object b) { if (!(b instanceof BigQuaternion)) return false; BigQuaternion B = (BigQuaternion) b; return re.equals(B.re) && im.equals(B.im) && jm.equals(B.jm) && km.equals(B.km); } /** * Hash code for this BigQuaternion. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = 37 * re.hashCode(); h += 37 * im.hashCode(); h += 37 * jm.hashCode(); h += 37 * km.hashCode(); return h; } /** * Since quaternion numbers are unordered, we use lexicographical order of * re, im, jm and km. * @param b BigQuaternion. * @return 0 if b is equal to this, 1 if this is greater b and -1 else. */ //JAVA6only: @Override public int compareTo(BigQuaternion b) { int s = re.compareTo(b.re); if (s != 0) { return s; } s = im.compareTo(b.im); if (s != 0) { return s; } s = jm.compareTo(b.jm); if (s != 0) { return s; } return km.compareTo(b.km); } /** * Since quaternion numbers are unordered, we use lexicographical order of * re, im, jm and km. * @return 0 if this is equal to 0; 1 if re > 0, or re == 0 and im > 0, or * ...; -1 if re < 0, or re == 0 and im < 0, or ... * @see edu.jas.structure.RingElem#signum() */ public int signum() { int s = re.signum(); if (s != 0) { return s; } s = im.signum(); if (s != 0) { return s; } s = jm.signum(); if (s != 0) { return s; } return km.signum(); } /* arithmetic operations: +, -, - */ /** * BigQuaternion summation. * @param B BigQuaternion. * @return this+B. */ public BigQuaternion sum(BigQuaternion B) { return new BigQuaternion(re.sum(B.re), im.sum(B.im), jm.sum(B.jm), km.sum(B.km)); } /** * Quaternion number sum. * @param A BigQuaternion. * @param B BigQuaternion. * @return A+B. */ public static BigQuaternion QSUM(BigQuaternion A, BigQuaternion B) { if (A == null) return null; return A.sum(B); } /** * Quaternion number difference. * @param A BigQuaternion. * @param B BigQuaternion. * @return A-B. */ public static BigQuaternion QDIF(BigQuaternion A, BigQuaternion B) { if (A == null) return null; return A.subtract(B); } /** * BigQuaternion subtraction. * @param B BigQuaternion. * @return this-B. */ public BigQuaternion subtract(BigQuaternion B) { return new BigQuaternion(re.subtract(B.re), im.subtract(B.im), jm.subtract(B.jm), km.subtract(B.km)); } /** * Quaternion number negative. * @param A is a quaternion number * @return -A. */ public static BigQuaternion QNEG(BigQuaternion A) { if (A == null) return null; return A.negate(); } /** * BigQuaternion number negative. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public BigQuaternion negate() { return new BigQuaternion(re.negate(), im.negate(), jm.negate(), km.negate()); } /** * Quaternion number conjugate. * @param A is a quaternion number. * @return the quaternion conjugate of A. */ public static BigQuaternion QCON(BigQuaternion A) { if (A == null) return null; return A.conjugate(); } /* arithmetic operations: conjugate, absolute value */ /** * BigQuaternion conjugate. * @return conjugate(this). */ public BigQuaternion conjugate() { return new BigQuaternion(re, im.negate(), jm.negate(), km.negate()); } /** * Quaternion number norm. * @see edu.jas.structure.StarRingElem#norm() * @return ||this||. */ public BigQuaternion norm() { // this.conjugate().multiply(this); BigRational v = re.multiply(re); v = v.sum(im.multiply(im)); v = v.sum(jm.multiply(jm)); v = v.sum(km.multiply(km)); return new BigQuaternion(v); } /** * Quaternion number absolute value. * @see edu.jas.structure.RingElem#abs() * @return |this|^2. Note: The square root is not jet implemented. */ public BigQuaternion abs() { BigQuaternion n = norm(); logger.error("abs() square root missing"); // n = n.sqrt(); return n; } /** * Quaternion number absolute value. * @param A is a quaternion number. * @return the absolute value of A, a rational number. Note: The square root * is not jet implemented. */ public static BigRational QABS(BigQuaternion A) { if (A == null) return null; return A.abs().re; } /** * Quaternion number product. * @param A BigQuaternion. * @param B BigQuaternion. * @return A*B. */ public static BigQuaternion QPROD(BigQuaternion A, BigQuaternion B) { if (A == null) return null; return A.multiply(B); } /* arithmetic operations: *, inverse, / */ /** * BigQuaternion multiply. * @param B BigQuaternion. * @return this*B. */ public BigQuaternion multiply(BigQuaternion B) { BigRational r = re.multiply(B.re); r = r.subtract(im.multiply(B.im)); r = r.subtract(jm.multiply(B.jm)); r = r.subtract(km.multiply(B.km)); BigRational i = re.multiply(B.im); i = i.sum(im.multiply(B.re)); i = i.sum(jm.multiply(B.km)); i = i.subtract(km.multiply(B.jm)); BigRational j = re.multiply(B.jm); j = j.subtract(im.multiply(B.km)); j = j.sum(jm.multiply(B.re)); j = j.sum(km.multiply(B.im)); BigRational k = re.multiply(B.km); k = k.sum(im.multiply(B.jm)); k = k.subtract(jm.multiply(B.im)); k = k.sum(km.multiply(B.re)); return new BigQuaternion(r, i, j, k); } /** * Quaternion number inverse. * @param A is a non-zero quaternion number. * @return S with S * A = 1. */ public static BigQuaternion QINV(BigQuaternion A) { if (A == null) return null; return A.inverse(); } /** * BigQuaternion inverse. * @return S with S * this = 1. * @see edu.jas.structure.RingElem#inverse() */ public BigQuaternion inverse() { BigRational a = norm().re.inverse(); return new BigQuaternion(re.multiply(a), im.multiply(a.negate()), jm.multiply(a.negate()), km.multiply(a.negate())); } /** * BigQuaternion remainder. * @param S BigQuaternion. * @return 0. */ public BigQuaternion remainder(BigQuaternion S) { if (S.isZERO()) { throw new ArithmeticException("division by zero"); } return ZERO; } /** * Quaternion number quotient. * @param A BigQuaternion. * @param B BigQuaternion. * @return R/S. */ public static BigQuaternion QQ(BigQuaternion A, BigQuaternion B) { if (A == null) return null; return A.divide(B); } /** * BigQuaternion divide. * @param b BigQuaternion. * @return this/b. */ public BigQuaternion divide(BigQuaternion b) { return this.multiply(b.inverse()); } /** * BigQuaternion divide. * @param b BigRational. * @return this/b. */ public BigQuaternion divide(BigRational b) { BigRational bi = b.inverse(); return new BigQuaternion(re.multiply(bi), im.multiply(bi), jm.multiply(bi), km.multiply(bi)); } /** * BigQuaternion random. Random rational numbers A, B, C and D are generated * using random(n). Then R is the quaternion number with real part A and * imaginary parts B, C and D. * @param n such that 0 ≤ A, B, C, D ≤ (2n-1). * @return R, a random BigQuaternion. */ public BigQuaternion random(int n) { return random(n, random); } /** * BigQuaternion random. Random rational numbers A, B, C and D are generated * using RNRAND(n). Then R is the quaternion number with real part A and * imaginary parts B, C and D. * @param n such that 0 ≤ A, B, C, D ≤ (2n-1). * @param rnd is a source for random bits. * @return R, a random BigQuaternion. */ public BigQuaternion random(int n, Random rnd) { BigRational r = BigRational.ONE.random(n, rnd); BigRational i = BigRational.ONE.random(n, rnd); BigRational j = BigRational.ONE.random(n, rnd); BigRational k = BigRational.ONE.random(n, rnd); return new BigQuaternion(r, i, j, k); } /** * Quaternion number, random. Random rational numbers A, B, C and D are * generated using RNRAND(n). Then R is the quaternion number with real part * A and imaginary parts B, C and D. * @param n such that 0 ≤ A, B, C, D ≤ (2n-1). * @return R, a random BigQuaternion. */ public static BigQuaternion QRAND(int n) { return ONE.random(n, random); } /** * Parse quaternion number from String. * @param s String. * @return BigQuaternion from s. */ public BigQuaternion parse(String s) { return new BigQuaternion(s); } /** * Parse quaternion number from Reader. * @param r Reader. * @return next BigQuaternion from r. */ public BigQuaternion parse(Reader r) { return parse(StringUtil.nextString(r)); } /** * Quaternion number greatest common divisor. * @param S BigQuaternion. * @return gcd(this,S). */ public BigQuaternion gcd(BigQuaternion S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } return ONE; } /** * BigQuaternion extended greatest common divisor. * @param S BigQuaternion. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ public BigQuaternion[] egcd(BigQuaternion S) { BigQuaternion[] ret = new BigQuaternion[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; return ret; } if (this.isZERO()) { ret[0] = S; return ret; } BigQuaternion half = new BigQuaternion(new BigRational(1, 2)); ret[0] = ONE; ret[1] = this.inverse().multiply(half); ret[2] = S.inverse().multiply(half); return ret; } } jas-2.5/src/edu/jas/kern/0000755000175000017500000000000012140140256015416 5ustar giovannigiovannijas-2.5/src/edu/jas/kern/package.html0000644000175000017500000000166310653063206017713 0ustar giovannigiovanni JAS run-time kernel package

JAS run-time kernel package.

This package contains classes used in global execution of all JAS packages. E.g. PrettyPrint is used to control the print (i.e. the toString()) of many classes. PreemptingException and PreemptStatus are used to preemptively cancel long running computations.


Heinz Kredel

Last modified: Wed Jul 11 19:06:14 CEST 2007

$Id: package.html 1249 2007-07-29 10:05:58Z kredel $

jas-2.5/src/edu/jas/kern/PreemptStatus.java0000644000175000017500000000161512004300130021070 0ustar giovannigiovanni/* * $Id: PreemptStatus.java 4055 2012-07-26 17:37:29Z kredel $ */ package edu.jas.kern; /** * PreemptStatus, defines global status for preemtive interruption handling. * @author Heinz Kredel */ public class PreemptStatus { /** * Global status flag. */ private static boolean allowPreempt = true; /** * No public constructor. */ protected PreemptStatus() { } /** * isAllowed. * @return true, preemtive interruption is allowed, else false. */ public static boolean isAllowed() { return allowPreempt; } /** * setAllow, set preemtive interruption to allowed status. */ public static void setAllow() { allowPreempt = true; } /** * setNotAllow, set preemtive interruption to not allowed status. */ public static void setNotAllow() { allowPreempt = false; } } jas-2.5/src/edu/jas/kern/Scripting.java0000644000175000017500000000145612004300130020215 0ustar giovannigiovanni/* * $Id: Scripting.java 4055 2012-07-26 17:37:29Z kredel $ */ package edu.jas.kern; /** * Scripting, defines script language for output in toScript() method. * @author Heinz Kredel */ public class Scripting { public static enum Lang { Python, Ruby }; private static Lang script = Lang.Python; protected Scripting() { } /** * Get scripting language which is in effect. * @return language which is to be used for toScript(). */ public static Lang getLang() { return script; } /** * Set scripting language. * @param s language which is to be used for toScript() * @return old language setting. */ public static Lang setLang(Lang s) { Lang o = script; script = s; return o; } } jas-2.5/src/edu/jas/kern/StringUtil.java0000644000175000017500000000555112004300130020357 0ustar giovannigiovanni/* * $Id: StringUtil.java 4055 2012-07-26 17:37:29Z kredel $ */ package edu.jas.kern; import java.io.IOException; import java.io.Reader; import java.io.StringWriter; /** * Static String and Reader methods. * @author Heinz Kredel */ public class StringUtil { /** * Parse white space delimited String from Reader. * @param r Reader. * @return next non white space String from r. */ public static String nextString(Reader r) { StringWriter sw = new StringWriter(); try { char buffer; int i; // skip white space while ((i = r.read()) > -1) { buffer = (char) i; if (!Character.isWhitespace(buffer)) { sw.write(buffer); break; } } // read non white space, ignore new lines ? while ((i = r.read()) > -1) { buffer = (char) i; if (Character.isWhitespace(buffer)) { break; } sw.write(buffer); } } catch (IOException e) { e.printStackTrace(); } return sw.toString(); } /** * Parse String with given delimiter from Reader. * @param c delimiter. * @param r Reader. * @return next String up to c from r. */ public static String nextString(Reader r, char c) { StringWriter sw = new StringWriter(); try { char buffer; int i; // read chars != c, ignore new lines ? while ((i = r.read()) > -1) { buffer = (char) i; if (buffer == c) { break; } sw.write(buffer); } } catch (IOException e) { e.printStackTrace(); } return sw.toString(); } /** * Parse paired String with given delimiters from Reader. * @param b opposite delimiter. * @param c delimiter. * @param r Reader. * @return next nested matching String up to c from r. */ public static String nextPairedString(Reader r, char b, char c) { StringWriter sw = new StringWriter(); try { int level = 0; char buffer; int i; // read chars != c, ignore new lines ? while ((i = r.read()) > -1) { buffer = (char) i; if (buffer == b) { level++; } if (buffer == c) { level--; if (level < 0) { break; // skip last closing 'brace' } } sw.write(buffer); } } catch (IOException e) { e.printStackTrace(); } return sw.toString(); } } jas-2.5/src/edu/jas/kern/TimeExceededException.java0000644000175000017500000000122212004300130022446 0ustar giovannigiovanni/* * $Id: TimeExceededException.java 4055 2012-07-26 17:37:29Z kredel $ */ package edu.jas.kern; /** * Time exceeded exception class. Runtime Exception to be thrown when the * run-time has exceeded a certain limit. * @author Heinz Kredel */ public class TimeExceededException extends RuntimeException { public TimeExceededException() { super("TimeExceededException"); } public TimeExceededException(String c) { super(c); } public TimeExceededException(String c, Throwable t) { super(c, t); } public TimeExceededException(Throwable t) { super("TimeExceededException", t); } } jas-2.5/src/edu/jas/kern/TimeStatus.java0000644000175000017500000000513412004300130020352 0ustar giovannigiovanni/* * $Id: TimeStatus.java 4055 2012-07-26 17:37:29Z kredel $ */ package edu.jas.kern; import java.util.concurrent.Callable; /** * Run-time status, defines global status and handling for run time limits. * @author Heinz Kredel */ public class TimeStatus { /** * Global status flag. */ private static boolean allowTime = false; /** * Global run-time limit in milliseconds. */ private static long limitTime = Long.MAX_VALUE; /** * Global run-time limit in milliseconds. */ private static long startTime = System.currentTimeMillis(); /** * Call back method. true means continue, false means throw exception. */ private static Callable callBack = null; /** * No public constructor. */ protected TimeStatus() { } /** * isActive. * @return true, if run-time interruption is active, else false. */ public static boolean isActive() { return allowTime; } /** * setAllow, set run-time interruption to allowed status. */ public static void setActive() { allowTime = true; } /** * setNotActive, set run-time interruption to not active status. */ public static void setNotActive() { allowTime = false; } /** * setLimit, set run-time limit in milliseconds. */ public static void setLimit(long t) { limitTime = t; } /** * Restart timer, set run-time to current time. */ public static void restart() { startTime = System.currentTimeMillis(); } /** * set call back, set the Callabe object. */ public static void setCallBack(Callable cb) { callBack = cb; } /** * Check for exceeded time, test if time has exceeded and throw an exception * if so. * @param msg the message to be send with the exception. */ public static void checkTime(String msg) { if (!allowTime) { return; } if (limitTime == Long.MAX_VALUE) { return; } long tt = (System.currentTimeMillis() - startTime - limitTime); //System.out.println("tt = " + tt); if (tt <= 0L) { return; } if (callBack != null) { try { boolean t = callBack.call(); if (t) { return; } } catch (Exception e) { } } if (msg == null) { msg = ""; } throw new TimeExceededException(msg + " over time = " + tt); } } jas-2.5/src/edu/jas/kern/PreemptingException.java0000644000175000017500000000115512004300130022240 0ustar giovannigiovanni/* * $Id: PreemptingException.java 4055 2012-07-26 17:37:29Z kredel $ */ package edu.jas.kern; /** * Preempting Exception class. Runtime Exception to be thrown when a thread is * interrupted. * @author Heinz Kredel */ public class PreemptingException extends RuntimeException { public PreemptingException() { super("PreemptingException"); } public PreemptingException(String c) { super(c); } public PreemptingException(String c, Throwable t) { super(c, t); } public PreemptingException(Throwable t) { super("PreemptingException", t); } } jas-2.5/src/edu/jas/kern/PrettyPrint.java0000644000175000017500000000132512004300130020552 0ustar giovannigiovanni/* * $Id: PrettyPrint.java 4055 2012-07-26 17:37:29Z kredel $ */ package edu.jas.kern; /** * PrettyPrint, defines global pretty print status. * @author Heinz Kredel */ public class PrettyPrint { private static volatile boolean toDo = true; protected PrettyPrint() { } /** * isTrue. * @return true, if to use pretty printing, else false. */ public static boolean isTrue() { return toDo; } /** * setPretty. Set use pretty printing to true. */ public static void setPretty() { toDo = true; } /** * setInternal. Set use pretty printing to false. */ public static void setInternal() { toDo = false; } } jas-2.5/src/edu/jas/kern/ComputerThreads.java0000644000175000017500000001255011435516726021414 0ustar giovannigiovanni/* * $Id: ComputerThreads.java 3295 2010-08-26 17:01:10Z kredel $ */ package edu.jas.kern; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadPoolExecutor; import org.apache.log4j.Logger; /** * ComputerThreads, provides global thread / executor service. * @author Heinz Kredel * @usage To obtain a reference to the thread pool use * ComputerThreads.getPool(). Once a pool has been created * it must be shutdown to exit JAS with * ComputerThreads.terminate(). */ public class ComputerThreads { private static final Logger logger = Logger.getLogger(ComputerThreads.class); // private boolean debug = logger.isInfoEnabled(); //logger.isInfoEnabled(); /** * Flag for thread usage. Note: Only introduced because Google app * engine does not support threads. * @see edu.jas.ufd.GCDFactory#getProxy(edu.jas.structure.RingFactory) */ public static boolean NO_THREADS = false; /** * Number of processors. */ public static final int N_CPUS = Runtime.getRuntime().availableProcessors(); /* * Core number of threads. * N_CPUS x 1.5, x 2, x 2.5, min 3, ?. */ public static final int N_THREADS = (N_CPUS < 3 ? 3 : N_CPUS + N_CPUS / 2); //public static final int N_THREADS = ( N_CPUS < 3 ? 5 : 3*N_CPUS ); /* * Queue capacity. */ //public static final int Q_CAPACITY = 1000; // 10000 /* * WorkQueue. */ //private static BlockingQueue workpile; /* * Saturation policy. */ //public static final RejectedExecutionHandler REH = new ThreadPoolExecutor.CallerRunsPolicy(); //public static final RejectedExecutionHandler REH = new ThreadPoolExecutor.AbortPolicy(); /** * ExecutorService thread pool. */ //static ThreadPoolExecutor pool = null; static ExecutorService pool = null; /** * No public constructor. */ private ComputerThreads() { } /** * Test if a pool is running. * @return true if a thread pool has been started or is running, else false. */ public static synchronized boolean isRunning() { if (pool == null) { return false; } if (pool.isTerminated() || pool.isShutdown()) { return false; } return true; } /** * Get the thread pool. * @return pool ExecutorService. */ public static synchronized ExecutorService getPool() { if (pool == null) { // workpile = new ArrayBlockingQueue(Q_CAPACITY); // pool = Executors.newFixedThreadPool(N_THREADS); pool = Executors.newCachedThreadPool(); // pool = new ThreadPoolExecutor(N_CPUS, N_THREADS, // 100L, TimeUnit.MILLISECONDS, // workpile, REH); // pool = new ThreadPoolExecutor(N_CPUS, N_THREADS, // 1000L, TimeUnit.MILLISECONDS, // workpile); } //System.out.println("pool_init = " + pool); return pool; //return Executors.unconfigurableExecutorService(pool); /* not useful, is not run from jython final GCDProxy proxy = this; Runtime.getRuntime().addShutdownHook( new Thread() { public void run() { logger.info("running shutdown hook"); proxy.terminate(); } } ); */ } /** * Stop execution. */ public static synchronized void terminate() { if (pool == null) { return; } if (pool instanceof ThreadPoolExecutor) { ThreadPoolExecutor tpe = (ThreadPoolExecutor) pool; //logger.info("task queue size " + Q_CAPACITY); //logger.info("reject execution handler" + REH.getClass().getName()); logger.info("number of CPUs " + N_CPUS); logger.info("core number of threads " + N_THREADS); logger.info("current number of threads " + tpe.getPoolSize()); logger.info("maximal number of threads " + tpe.getLargestPoolSize()); BlockingQueue workpile = tpe.getQueue(); if (workpile != null) { logger.info("queued tasks " + workpile.size()); } List r = tpe.shutdownNow(); if (r.size() != 0) { logger.info("unfinished tasks " + r.size()); } logger.info("number of sheduled tasks " + tpe.getTaskCount()); logger.info("number of completed tasks " + tpe.getCompletedTaskCount()); } pool = null; //workpile = null; } /** * Set no thread usage. */ public static synchronized void setNoThreads() { NO_THREADS = true; } /** * Set thread usage. */ public static synchronized void setThreads() { NO_THREADS = false; } } jas-2.5/src/edu/jas/util/0000755000175000017500000000000012140140256015434 5ustar giovannigiovannijas-2.5/src/edu/jas/util/CartesianProductLong.java0000644000175000017500000001471412004530422022375 0ustar giovannigiovanni/* * $Id: CartesianProductLong.java 4065 2012-07-27 15:17:38Z kredel $ */ package edu.jas.util; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; /** * Cartesian product for Long with iterator. Similar to CartesianProduct but * returns only tuples of given total degree. * @author Heinz Kredel */ public class CartesianProductLong implements Iterable> { /** * data structure. */ public final List comps; public final long upperBound; /** * CartesianProduct constructor. * @param comps components of the Cartesian product. * @param ub an upper bound for the total degree of the elements. */ public CartesianProductLong(List comps, long ub) { if (comps == null) { throw new IllegalArgumentException("null components not allowed"); } this.comps = comps; this.upperBound = ub; } /** * Get an iterator over subsets. * @return an iterator. */ public Iterator> iterator() { return new CartesianProductLongIterator(comps, upperBound); } } /** * Cartesian product iterator for Longs. Similar to CartesianProductIterator but * returns only tuples of given total degree. * @author Heinz Kredel */ class CartesianProductLongIterator implements Iterator> { /** * data structure. */ final List comps; final List compit; List current; boolean empty; public final long upperBound; /** * CartesianProduct iterator constructor. * @param comps components of the Cartesian product. * @param un an upper bound for the total degree of the elements. */ public CartesianProductLongIterator(List comps, long ub) { if (comps == null) { throw new IllegalArgumentException("null comps not allowed"); } this.comps = comps; this.upperBound = ub; current = new ArrayList(comps.size()); compit = new ArrayList(comps.size()); empty = false; for (LongIterable ci : comps) { LongIterator it = (LongIterator) ci.iterator(); if (it.getUpperBound() < this.upperBound) { throw new IllegalArgumentException("each iterator (" + it.getUpperBound() + ") must be able to reach total upper bound " + upperBound); } if (!it.hasNext()) { empty = true; current.clear(); return; } current.add(it.next()); compit.add(it); } // start with last component equal to upper bound LongIterator it = compit.get(compit.size() - 1); long d = -1L; while (it.hasNext()) { d = it.next(); if (d >= upperBound) { break; } } if (d >= 0L) { current.set(current.size() - 1, d); } if (totalDegree(current) != upperBound) { empty = true; current.clear(); } //System.out.println("current = " + current); } /** * Test for availability of a next tuple. * @return true if the iteration has more tuples, else false. */ public synchronized boolean hasNext() { return !empty; } /** * Get next tuple. * @return next tuple. */ public synchronized List next() { if (empty) { throw new NoSuchElementException("invalid call of next()"); } List res = new ArrayList(current); //int waist = 0; while (true) { // search iterator which hasNext int i = compit.size() - 1; for (; i >= 0; i--) { LongIterator iter = compit.get(i); if (iter.hasNext()) { break; } } if (i < 0) { empty = true; //System.out.println("inner waist = " + waist); return res; } long pd = 0L; for (int j = 0; j < i; j++) { pd += current.get(j); } if (pd >= upperBound) { if (current.get(0) == upperBound) { empty = true; //System.out.println("inner waist = " + waist); return res; } pd = upperBound; } long rd = upperBound - pd; // update iterators for (int j = i + 1; j < compit.size(); j++) { LongIterator iter = (LongIterator) comps.get(j).iterator(); iter.setUpperBound(rd); compit.set(j, iter); } // update current for (int j = i; j < compit.size(); j++) { LongIterator iter = compit.get(j); Long el = iter.next(); current.set(j, el); } long td = totalDegree(current); if (td == upperBound) { //System.out.println("inner waist = " + waist); return res; } //System.out.println("current = " + current + ", td = " + td); if (td > upperBound) { //waist++; continue; } // adjust last component to total degree LongIterator it = compit.get(compit.size() - 1); long d = -1L; while (td < upperBound && it.hasNext()) { td++; d = it.next(); } //System.out.println("d = " + d); if (d >= 0L) { current.set(current.size() - 1, d); } if (td == upperBound) { //System.out.println("inner waist = " + waist); return res; } //waist++; // continue search } //return res; } /** * Total degree of a tuple. * @param e list of Longs. * @return sum of all elements in e. */ public long totalDegree(List e) { long d = 0L; for (Long i : e) { d += i; } return d; } /** * Remove a tuple if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove tuples"); } } jas-2.5/src/edu/jas/util/Terminator.java0000644000175000017500000000646611776644620020461 0ustar giovannigiovanni/* * $Id: Terminator.java 3979 2012-07-09 21:13:53Z kredel $ */ package edu.jas.util; import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; //import edu.unima.ky.parallel.Semaphore; /** * Terminating helper class. Like a barrier, but with coming and going. * @author Heinz Kredel */ public class Terminator { private static final Logger logger = Logger.getLogger(Terminator.class); private final int workers; private int idler = 0; private final Semaphore fin; private /*volatile*/ boolean done; /** * Terminator. * @param workers number of expected threads. */ public Terminator(int workers) { this.workers = workers; fin = new Semaphore(0); done = false; logger.info("constructor, workers = " + workers); } /** * to string */ @Override public String toString() { return "Terminator(" + done + ",workers=" + workers + ",idler=" + idler + ")"; } /** * beIdle. * Checks for release(). */ public synchronized void beIdle() { idler++; logger.info("beIdle, idler = " + idler); if (idler >= workers) { done = true; fin.release(); //fin.V(); } } /** * initIdle. * No check for release(). * @param i number of idle threads. */ public synchronized void initIdle(int i) { idler += i; logger.info("initIdle, idler = " + idler); if ( idler > workers ) { if (done) { idler = workers; } else { throw new RuntimeException("idler > workers"); } } } /** * beIdle. * Checks for release(). * @param i number of idle threads. */ public synchronized void beIdle(int i) { idler += i; logger.info("beIdle, idler = " + idler); if (idler >= workers) { done = true; fin.release(); //fin.V(); } } /** * allIdle. * Checks for release(). */ public synchronized void allIdle() { idler = workers; logger.info("allIdle"); done = true; fin.release(); //fin.V(); } /** * notIdle. */ public synchronized void notIdle() { idler--; logger.info("notIdle, idler = " + idler); if ( idler < 0 ) { throw new RuntimeException("idler < 0"); } } /** * getJobs. * @return number of possible jobs. */ public synchronized int getJobs() { return (workers - idler); } /** * hasJobs. * @return true, if there are possibly jobs, else false. */ public synchronized boolean hasJobs() { return (idler < workers); } /** * Release if possible. */ public synchronized void release() { logger.info("release = " + this); if ( idler >= workers ) { done = true; fin.release(); } //logger.info("release, idler = " + idler); } /** * Wait until released. */ public void waitDone() { try { fin.acquire(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } logger.info("waitDone " + this); } } jas-2.5/src/edu/jas/util/ExecutableServer.java0000644000175000017500000002154212033403702021552 0ustar giovannigiovanni/* * $Id: ExecutableServer.java 4236 2012-10-04 22:03:47Z kredel $ */ package edu.jas.util; import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.ArrayList; import org.apache.log4j.Logger; import org.apache.log4j.BasicConfigurator; /** * ExecutableServer is used to receive and execute classes. * @author Heinz Kredel */ public class ExecutableServer extends Thread { private static final Logger logger = Logger.getLogger(ExecutableServer.class); private final boolean debug = logger.isDebugEnabled(); /** * ChannelFactory to use. */ protected final ChannelFactory cf; /** * List of server threads. */ protected List servers = null; /** * Default port to listen to. */ public static final int DEFAULT_PORT = 7411; /** * Constant to signal completion. */ public static final String DONE = "Done"; /** * Constant to request shutdown. */ public static final String STOP = "Stop"; private volatile boolean goon = true; private Thread mythread = null; /** * ExecutableServer on default port. */ public ExecutableServer() { this(DEFAULT_PORT); } /** * ExecutableServer. * @param port */ public ExecutableServer(int port) { this(new ChannelFactory(port)); } /** * ExecutableServer. * @param cf channel factory to reuse. */ public ExecutableServer(ChannelFactory cf) { this.cf = cf; cf.init(); servers = new ArrayList(); } /** * main method to start serving thread. * @param args args[0] is port */ public static void main(String[] args) throws InterruptedException { BasicConfigurator.configure(); int port = DEFAULT_PORT; if (args.length < 1) { System.out.println("Usage: ExecutableServer "); } else { try { port = Integer.parseInt(args[0]); } catch (NumberFormatException e) { } } //logger.info("ExecutableServer at port " + port); ExecutableServer es = new ExecutableServer(port); es.init(); es.join(); // do not use terminate() // until CRTL-C } /** * thread initialization and start. */ public void init() { this.start(); logger.info("ExecutableServer at " + cf); } /** * number of servers. */ public int size() { if ( servers == null ) { return -1; } return servers.size(); } /** * run is main server method. */ @Override public void run() { SocketChannel channel = null; Executor s = null; mythread = Thread.currentThread(); while (goon) { if (debug) { logger.info("execute server " + this + " go on"); } try { channel = cf.getChannel(); logger.debug("execute channel = " + channel); if (mythread.isInterrupted()) { goon = false; logger.debug("execute server " + this + " interrupted"); channel.close(); } else { s = new Executor(channel); // ---,servers); if (goon) { // better synchronize with terminate servers.add(s); s.start(); logger.debug("server " + s + " started"); } else { s = null; channel.close(); } } } catch (InterruptedException e) { goon = false; Thread.currentThread().interrupt(); if (debug) { e.printStackTrace(); } } } if (debug) { logger.info("execute server " + this + " terminated"); } } /** * terminate all servers. */ public void terminate() { goon = false; logger.debug("terminating ExecutableServer"); if (cf != null) cf.terminate(); if (servers != null) { Iterator it = servers.iterator(); while (it.hasNext()) { Executor x = it.next(); if (x.channel != null) { x.channel.close(); } try { while (x.isAlive()) { //System.out.print("."); x.interrupt(); x.join(100); } logger.debug("server " + x + " terminated"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } servers = null; } logger.debug("Executors terminated"); if (mythread == null) return; try { while (mythread.isAlive()) { //System.out.print("-"); mythread.interrupt(); mythread.join(100); } //logger.debug("server " + mythread + " terminated"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } mythread = null; logger.debug("ExecuteServer terminated"); } /** * String representation. */ @Override public String toString() { StringBuffer s = new StringBuffer("ExecutableServer("); s.append(cf.toString()); s.append(")"); return s.toString(); } } /** * class for executing incoming objects. */ class Executor extends Thread /*implements Runnable*/{ private static final Logger logger = Logger.getLogger(Executor.class); private final boolean debug = logger.isDebugEnabled(); protected final SocketChannel channel; Executor(SocketChannel s) { channel = s; } /** * run. */ @Override public void run() { Object o; RemoteExecutable re = null; String d; boolean goon = true; logger.debug("executor started " + this); while (goon) { try { o = channel.receive(); logger.info("receive: " + o + " from " + channel); if (this.isInterrupted()) { goon = false; } else { if (debug) { logger.debug("receive: " + o + " from " + channel); } if (o instanceof String) { d = (String) o; if (ExecutableServer.STOP.equals(d)) { goon = false; // stop this thread channel.send(ExecutableServer.DONE); } else { logger.warn("invalid/unknown String: " + d + " from " + channel); goon = false; // stop this thread ? channel.send(ExecutableServer.DONE); } } // check permission if (o instanceof RemoteExecutable) { re = (RemoteExecutable) o; if (debug) { logger.info("running " + re); } try { re.run(); } catch(Exception e) { logger.info("Exception on re.run()" + e); e.printStackTrace(); } finally { logger.info("finally re.run() " + re); } if (debug) { logger.info("finished " + re); } if (this.isInterrupted()) { goon = false; } else { channel.send(ExecutableServer.DONE); logger.info("finished send " + ExecutableServer.DONE); //goon = false; // stop this thread } } } } catch (IOException e) { goon = false; logger.info("IOException " + e); if (debug) { e.printStackTrace(); } } catch (ClassNotFoundException e) { goon = false; logger.info("ClassNotFoundException " + e); e.printStackTrace(); } finally { logger.info("finally " + this); } } logger.info("executor terminated " + this); channel.close(); } } jas-2.5/src/edu/jas/util/MapEntry.java0000644000175000017500000000307311571751640020055 0ustar giovannigiovanni/* * $Id: MapEntry.java 3652 2011-06-02 18:17:04Z kredel $ */ package edu.jas.util; import java.util.Map; /** * MapEntry helper class implements Map.Entry. * Required until JDK 1.6 becomes every where available. * @see java.util.AbstractMap.SimpleImmutableEntry in JDK 1.6. * @author Heinz Kredel. */ public class MapEntry implements Map.Entry { final K key; final V value; /** * Constructor. */ public MapEntry(K k, V v) { key = k; value = v; } /** * Get the key. * @see java.util.Map.Entry#getKey() */ public K getKey() { return key; } /** * Get the value. * @see java.util.Map.Entry#getValue() */ public V getValue() { return value; } /** * Set the value. * Is not implemented. * @see java.util.Map.Entry */ public V setValue(V value) { throw new UnsupportedOperationException("not implemented"); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof Map.Entry)) { return false; } Map.Entry me = (Map.Entry) b; return key.equals(me.getKey()) && value.equals(me.getValue()); } /** * Hash code for this MapEntry. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return key.hashCode() * 37 + value.hashCode(); } } jas-2.5/src/edu/jas/util/package.html0000644000175000017500000000151010653065064017724 0ustar giovannigiovanni Concurrent programming utility classes

Concurrent programming utility classes.

This package contains further utilities for parallel and distributed computations like ThreadPool, DistThreadPool or DistHashTable.


Heinz Kredel

Last modified: Mon Jul 9 22:45:40 CEST 2007

$Id: package.html 1263 2007-07-29 10:21:40Z kredel $

jas-2.5/src/edu/jas/util/LongIterable.java0000644000175000017500000000672412011706250020656 0ustar giovannigiovanni/* * $Id: LongIterable.java 4094 2012-08-12 10:59:52Z kredel $ */ package edu.jas.util; import java.util.Iterator; import java.util.NoSuchElementException; /** * Iterable for Long. * @author Heinz Kredel */ public class LongIterable implements Iterable { private boolean nonNegative = true; private long upperBound = Long.MAX_VALUE; /** * Constructor. */ public LongIterable() { } /** * Constructor. */ public LongIterable(long ub) { upperBound = ub; } /** * Set the upper bound for the iterator. * @param ub an upper bound for the iterator elements. */ public void setUpperBound(long ub) { upperBound = ub; } /** * Get the upper bound for the iterator. * @return the upper bound for the iterator elements. */ public long getUpperBound() { return upperBound; } /** * Set the iteration algorithm to all elements. */ public void setAllIterator() { nonNegative = false; } /** * Set the iteration algorithm to non-negative elements. */ public void setNonNegativeIterator() { nonNegative = true; } /** * Get an iterator over Long. * @return an iterator. */ public Iterator iterator() { return new LongIterator(nonNegative, upperBound); } } /** * Long iterator. * @author Heinz Kredel */ class LongIterator implements Iterator { /** * data structure. */ long current; boolean empty; final boolean nonNegative; protected long upperBound; /** * Set the upper bound for the iterator. * @param ub an upper bound for the iterator elements. */ public void setUpperBound(long ub) { upperBound = ub; } /** * Get the upper bound for the iterator. * @return the upper bound for the iterator elements. */ public long getUpperBound() { return upperBound; } /** * Long iterator constructor. */ public LongIterator() { this(false, Long.MAX_VALUE); } /** * Long iterator constructor. * @param nn true for an iterator over non-negative longs, false for all * elements iterator. * @param ub an upper bound for the entries. */ public LongIterator(boolean nn, long ub) { current = 0L; //System.out.println("current = " + current); empty = false; nonNegative = nn; upperBound = ub; //System.out.println("upperBound = " + upperBound); } /** * Test for availability of a next long. * @return true if the iteration has more Longs, else false. */ public synchronized boolean hasNext() { return !empty; } /** * Get next Long. * @return next Long. */ public synchronized Long next() { if (empty) { throw new NoSuchElementException("invalid call of next()"); } Long res = Long.valueOf(current); if (nonNegative) { current++; } else if (current > 0L) { current = -current; } else { current = -current; current++; } if (current > upperBound) { empty = true; } return res; } /** * Remove a tuple if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove elements"); } } jas-2.5/src/edu/jas/util/DistributedListServer.java0000644000175000017500000002507512004734512022620 0ustar giovannigiovanni/* * $Id: DistributedListServer.java 4074 2012-07-28 10:04:58Z kredel $ */ package edu.jas.util; import java.io.IOException; import java.io.Serializable; import java.util.Iterator; import java.util.List; import java.util.ArrayList; import java.util.SortedMap; import java.util.TreeMap; import java.util.Map.Entry; import org.apache.log4j.Logger; //import edu.unima.ky.parallel.ChannelFactory; //import edu.unima.ky.parallel.SocketChannel; /** * Server for the distributed version of a list. * @author Heinz Kredel * @todo redistribute list for late comming clients, removal of elements. */ public class DistributedListServer extends Thread { private static final Logger logger = Logger.getLogger(DistributedListServer.class); public final static int DEFAULT_PORT = ChannelFactory.DEFAULT_PORT + 99; protected final ChannelFactory cf; protected List servers; private boolean goon = true; private Thread mythread = null; private Counter listElem = null; protected final SortedMap theList; /** * Constructs a new DistributedListServer. */ public DistributedListServer() { this(DEFAULT_PORT); } /** * DistributedListServer. * @param port to run server on. */ public DistributedListServer(int port) { this( new ChannelFactory(port) ); } /** * DistributedListServer. * @param cf ChannelFactory to use. */ public DistributedListServer(ChannelFactory cf) { listElem = new Counter(0); this.cf = cf; cf.init(); servers = new ArrayList(); theList = new TreeMap(); } /** * main. * Usage: DistributedListServer <port> */ public static void main(String[] args) throws InterruptedException { int port = DEFAULT_PORT; if ( args.length < 1 ) { System.out.println("Usage: DistributedListServer "); } else { try { port = Integer.parseInt( args[0] ); } catch (NumberFormatException e) { } } DistributedListServer dls = new DistributedListServer(port); dls.init(); dls.join(); // until CRTL-C } /** * thread initialization and start. */ public void init() { this.start(); } /** * main server method. */ @Override public void run() { SocketChannel channel = null; Broadcaster s = null; mythread = Thread.currentThread(); Entry e; Object n; Object o; while (goon) { // logger.debug("list server " + this + " go on"); try { channel = cf.getChannel(); logger.debug("dls channel = "+channel); if ( mythread.isInterrupted() ) { goon = false; //logger.info("list server " + this + " interrupted"); } else { s = new Broadcaster(channel,servers,listElem,theList); int ls = 0; synchronized (servers) { servers.add( s ); ls = theList.size(); s.start(); } //logger.debug("server " + s + " started"); if ( ls > 0 ) { logger.info("sending " + ls + " list elements"); synchronized (theList) { Iterator it = theList.entrySet().iterator(); for ( int i = 0; i < ls; i++ ) { e = (Entry)it.next(); n = e.getKey(); o = e.getValue(); try { s.sendChannel( n,o ); } catch (IOException ioe) { // stop s } } } } } } catch (InterruptedException end) { goon = false; Thread.currentThread().interrupt(); } } //logger.debug("listserver " + this + " terminated"); } /** * terminate all servers. */ public void terminate() { goon = false; logger.debug("terminating ListServer"); if ( cf != null ) cf.terminate(); if ( servers != null ) { Iterator it = servers.iterator(); while ( it.hasNext() ) { Broadcaster br = (Broadcaster) it.next(); br.closeChannel(); try { while ( br.isAlive() ) { //System.out.print("."); br.interrupt(); br.join(100); } //logger.debug("server " + br + " terminated"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } servers = null; } logger.debug("Broadcasters terminated"); if ( mythread == null ) return; try { while ( mythread.isAlive() ) { // System.out.print("-"); mythread.interrupt(); mythread.join(100); } //logger.debug("server " + mythread + " terminated"); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } mythread = null; logger.debug("ListServer terminated"); } /** * number of servers. */ public int size() { if ( servers == null ) { return -1; } return servers.size(); } } /** * Class for holding the list index used as key in TreeMap. * Implemented since Integer has no add() method. * Must implement Comparable so that TreeMap works with correct ordering. */ class Counter implements Serializable, Comparable { private int value; /** * Counter. */ public Counter() { this(0); } /** * Counter. * @param v */ public Counter(int v) { value = v; } /** * intValue. * @return the value. */ public int intValue() { return value; } /** * add. * @param v */ public void add(int v) { // synchronized elsewhere value += v; } /** * equals. * @param ob an Object. * @return true if this is equal to o, else false. */ @Override public boolean equals(Object ob) { if ( ! (ob instanceof Counter) ) { return false; } return 0 == compareTo( (Counter)ob ); } /** * compareTo. * @param c a Counter. * @return 1 if (this < c), 0 if (this == c), -1 if (this > c). */ public int compareTo(Counter c) { int x = c.intValue(); if ( value > x ) { return 1; } if ( value < x ) { return -1; } return 0; } /** * Hash code for this Counter. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return value; } /** * toString. */ @Override public String toString() { return "Counter("+value+")"; } } /** * Thread for broadcasting all incoming objects to the list clients. */ class Broadcaster extends Thread /*implements Runnable*/ { private static final Logger logger = Logger.getLogger(Broadcaster.class); private final SocketChannel channel; private final List bcaster; private Counter listElem; private final SortedMap theList; /** * Broadcaster. * @param s SocketChannel to use. * @param p list of broadcasters. * @param le counter * @param sm SortedMap with counter value pairs. */ public Broadcaster(SocketChannel s, List p, Counter le, SortedMap sm) { channel = s; bcaster = p; listElem = le; theList = sm; } /** * closeChannel. */ public void closeChannel() { channel.close(); } /** * sendChannel. * @param n counter. * @param o value. * @throws IOException */ public void sendChannel(Object n, Object o) throws IOException { synchronized (channel) { channel.send(n); channel.send(o); } } /** * broadcast. * @param o object to store and send. */ public void broadcast(Object o) { Counter li = null; synchronized (listElem) { listElem.add(1); li = new Counter( listElem.intValue() ); } synchronized (theList) { theList.put( li, o ); } synchronized (bcaster) { Iterator it = bcaster.iterator(); while ( it.hasNext() ) { Broadcaster br = (Broadcaster) it.next(); try { br.sendChannel(li,o); //System.out.println("bcast: "+o+" to "+x.channel); } catch (IOException e) { try { br.closeChannel(); while ( br.isAlive() ) { br.interrupt(); br.join(100); } } catch (InterruptedException u) { Thread.currentThread().interrupt(); } bcaster.remove( br ); } } } } /** * run. */ @Override public void run() { Object o; boolean goon = true; while (goon) { try { o = channel.receive(); //System.out.println("receive: "+o+" from "+channel); broadcast(o); if ( this.isInterrupted() ) { goon = false; } } catch (IOException e) { goon = false; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } } logger.debug("broadcaster terminated "+this); channel.close(); } /** * toString. * @return a string representation of this. */ @Override public String toString() { return "Broadcaster("+channel+","+bcaster.size()+","+listElem+")"; } } jas-2.5/src/edu/jas/util/DistHashTable.java0000644000175000017500000002504312067555012020772 0ustar giovannigiovanni/* * $Id: DistHashTable.java 4336 2012-12-29 11:54:51Z kredel $ */ package edu.jas.util; import java.io.IOException; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; //import java.util.concurrent.ConcurrentSkipListMap; import org.apache.log4j.Logger; /** * Distributed version of a HashTable. Implemented with a SortedMap / TreeMap to * keep the sequence order of elements. * @author Heinz Kredel */ public class DistHashTable extends AbstractMap /* implements Map */{ private static final Logger logger = Logger.getLogger(DistHashTable.class); private static boolean debug = logger.isDebugEnabled(); protected final SortedMap theList; protected final ChannelFactory cf; protected SocketChannel channel = null; protected DHTListener listener = null; /** * Constructs a new DistHashTable. * @param host name or IP of server host. */ public DistHashTable(String host) { this(host, DistHashTableServer.DEFAULT_PORT); } /** * DistHashTable. * @param host name or IP of server host. * @param port on server. */ public DistHashTable(String host, int port) { this(new ChannelFactory(port + 1), host, port); } /** * DistHashTable. * @param cf ChannelFactory to use. * @param host name or IP of server host. * @param port on server. */ public DistHashTable(ChannelFactory cf, String host, int port) { this.cf = cf; cf.init(); // why? see constructor try { channel = cf.getChannel(host, port); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } if (debug) { logger.debug("dl channel = " + channel); } //theList = new ConcurrentSkipListMap(); // Java 1.6 theList = new TreeMap(); listener = new DHTListener(channel, theList); // listener.start() is in initialize() } /** * DistHashTable. * @param sc SocketChannel to use. */ public DistHashTable(SocketChannel sc) { cf = null; channel = sc; //theList = new ConcurrentSkipListMap(); // Java 1.6 theList = new TreeMap(); listener = new DHTListener(channel, theList); // listener.start() is in initialize() } /** * Hash code. */ @Override public int hashCode() { return theList.hashCode(); } /** * Equals. */ @Override public boolean equals(Object o) { return theList.equals(o); } /** * Contains key. */ @Override public boolean containsKey(Object o) { return theList.containsKey(o); } /** * Contains value. */ @Override public boolean containsValue(Object o) { return theList.containsValue(o); } /** * Get the values as Collection. */ @Override public Collection values() { synchronized (theList) { return new ArrayList(theList.values()); //return theList.values(); } } /** * Get the keys as set. */ @Override public Set keySet() { synchronized (theList) { return theList.keySet(); } } /** * Get the entries as Set. */ @Override public Set> entrySet() { synchronized (theList) { return theList.entrySet(); } } /** * Get the internal list, convert from Collection. * @fix but is ok */ public List getValueList() { synchronized (theList) { return new ArrayList(theList.values()); } } /** * Get the internal sorted map. For synchronization purpose in normalform. */ public SortedMap getList() { return theList; } /** * Size of the (local) list. */ @Override public int size() { synchronized (theList) { return theList.size(); } } /** * Is the List empty? */ @Override public boolean isEmpty() { synchronized (theList) { return theList.isEmpty(); } } /** * List key iterator. */ public Iterator iterator() { synchronized (theList) { return theList.keySet().iterator(); } } /** * List value iterator. */ public Iterator valueIterator() { synchronized (theList) { return theList.values().iterator(); } } /** * Put object to the distributed hash table. Blocks until the key value pair * is send and received from the server. * @param key * @param value */ public void putWait(K key, V value) { V o = put(key, value); // = send // assume key does not change multiple times before test: while (!value.equals(getWait(key))) { //System.out.print("#"); } } /** * Put object to the distributed hash table. Returns immediately after * sending, does not block. * @param key * @param value */ @Override public V put(K key, V value) { if (key == null || value == null) { throw new NullPointerException("null keys or values not allowed"); } try { DHTTransport tc = DHTTransport. create(key, value); channel.send(tc); //System.out.println("send: "+tc+" @ "+listener); } catch (IOException e) { logger.info("send, exception " + e); e.printStackTrace(); } catch (Exception e) { logger.info("send, exception " + e); e.printStackTrace(); } return null; } /** * Get value under key from DHT. Blocks until the object is send and * received from the server (actually it blocks until some value under key * is received). * @param key * @return the value stored under the key. */ public V getWait(K key) { V value = null; try { synchronized (theList) { //value = theList.get(key); value = get(key); while (value == null) { //System.out.print("^"); theList.wait(100); value = theList.get(key); } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } return value; } /** * Get value under key from DHT. If no value is jet available null is * returned. * @param key * @return the value stored under the key. */ @Override public V get(Object key) { synchronized (theList) { return theList.get(key); } } /** * Clear the List. Caveat: must be called on all clients. */ @Override public void clear() { // send clear message to others synchronized (theList) { theList.clear(); } } /** * Initialize and start the list thread. */ public void init() { if (listener == null) { return; } if (listener.isDone()) { return; } if (debug) { logger.debug("initialize " + listener); } synchronized (theList) { listener.start(); } } /** * Terminate the list thread. */ public void terminate() { if (cf != null) { cf.terminate(); } if (channel != null) { channel.close(); } //theList.clear(); if (listener == null) { return; } if (debug) { logger.debug("terminate " + listener); } listener.setDone(); try { while (listener.isAlive()) { //System.out.print("+"); listener.interrupt(); listener.join(100); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } listener = null; } } /** * Thread to comunicate with the list server. */ class DHTListener extends Thread { private static final Logger logger = Logger.getLogger(DHTListener.class); private static boolean debug = logger.isDebugEnabled(); private final SocketChannel channel; private final SortedMap theList; private boolean goon; DHTListener(SocketChannel s, SortedMap list) { channel = s; theList = list; goon = true; } boolean isDone() { return !goon; } void setDone() { goon = false; } /** * run. */ @SuppressWarnings("unchecked") @Override public void run() { Object o; DHTTransport tc; //goon = true; while (goon) { tc = null; o = null; try { o = channel.receive(); if (debug) { logger.debug("receive(" + o + ")"); } if (this.isInterrupted()) { goon = false; break; } if (o == null) { goon = false; break; } if (o instanceof DHTTransport) { tc = (DHTTransport) o; K key = tc.key(); if (key != null) { logger.info("receive, put(key=" + key + ")"); V val = tc.value(); synchronized (theList) { theList.put(key, val); theList.notifyAll(); } } } } catch (IOException e) { goon = false; logger.info("receive, IO exception " + e); //e.printStackTrace(); } catch (ClassNotFoundException e) { goon = false; logger.info("receive, CNF exception " + e); e.printStackTrace(); } catch (Exception e) { goon = false; logger.info("receive, exception " + e); e.printStackTrace(); } } } } jas-2.5/src/edu/jas/util/ThreadPool.java0000644000175000017500000002171612036600314020347 0ustar giovannigiovanni/* * $Id: ThreadPool.java 4254 2012-10-14 18:13:32Z kredel $ */ // package edu.unima.ky.parallel; package edu.jas.util; import java.util.LinkedList; import org.apache.log4j.Logger; import edu.jas.kern.PreemptingException; /** * Thread pool using stack / list workpile. * @author Akitoshi Yoshida * @author Heinz Kredel */ public class ThreadPool { /** * Default number of threads to use. */ static final int DEFAULT_SIZE = 3; /** * Number of threads to use. */ final int size; /** * Array of workers. */ protected PoolThread[] workers; /** * Number of idle workers. */ protected int idleworkers = 0; /** * Shutdown request. */ protected volatile boolean shutdown = false; /** * Work queue / stack. */ // should be expressed using strategy pattern // List or Collection is not appropriate // LIFO strategy for recursion protected LinkedList jobstack; // FIFO strategy for GB protected StrategyEnumeration strategy = StrategyEnumeration.LIFO; private static final Logger logger = Logger.getLogger(ThreadPool.class); private static boolean debug = logger.isDebugEnabled(); /** * Constructs a new ThreadPool with strategy StrategyEnumeration.FIFO and * size DEFAULT_SIZE. */ public ThreadPool() { this(StrategyEnumeration.FIFO, DEFAULT_SIZE); } /** * Constructs a new ThreadPool with size DEFAULT_SIZE. * @param strategy for job processing. */ public ThreadPool(StrategyEnumeration strategy) { this(strategy, DEFAULT_SIZE); } /** * Constructs a new ThreadPool with strategy StrategyEnumeration.FIFO. * @param size of the pool. */ public ThreadPool(int size) { this(StrategyEnumeration.FIFO, size); } /** * Constructs a new ThreadPool. * @param strategy for job processing. * @param size of the pool. */ public ThreadPool(StrategyEnumeration strategy, int size) { this.size = size; this.strategy = strategy; jobstack = new LinkedList(); // ok for all strategies ? workers = new PoolThread[0]; } /** * thread initialization and start. */ public void init() { if (workers == null || workers.length == 0) { workers = new PoolThread[size]; for (int i = 0; i < workers.length; i++) { workers[i] = new PoolThread(this); workers[i].start(); } logger.info("size = " + size + ", strategy = " + strategy); } if (debug) { Thread.dumpStack(); } } /** * toString. */ @Override public String toString() { return "ThreadPool( size=" + getNumber() + ", idle=" + idleworkers + ", " + getStrategy() + ", jobs=" + jobstack.size() + ")"; } /** * number of worker threads. */ public int getNumber() { return size; //if (workers == null || workers.length < size) { // init(); // start threads //} //return workers.length; // not null } /** * get used strategy. */ public StrategyEnumeration getStrategy() { return strategy; } /** * Terminates the threads. */ public void terminate() { while (hasJobs()) { try { Thread.sleep(100); //logger.info("waiting for termination in " + this); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } for (int i = 0; i < workers.length; i++) { try { while (workers[i].isAlive()) { workers[i].interrupt(); workers[i].join(100); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } } /** * Cancels the threads. */ public int cancel() { shutdown = true; int s = jobstack.size(); if (hasJobs()) { synchronized (this) { logger.info("jobs canceled: " + jobstack); jobstack.clear(); } } int re = 0; for (int i = 0; i < workers.length; i++) { if (workers[i] == null) { continue; } try { while (workers[i].isAlive()) { synchronized (this) { shutdown = true; notifyAll(); // for getJob workers[i].interrupt(); } re++; //if ( re > 3 * workers.length ) { // break; // give up //} workers[i].join(100); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } return s; } /** * adds a job to the workpile. * @param job */ public synchronized void addJob(Runnable job) { if (workers == null || workers.length < size) { init(); // start threads } jobstack.addLast(job); logger.debug("adding job"); if (idleworkers > 0) { logger.debug("notifying a jobless worker"); notifyAll(); } } /** * get a job for processing. */ protected synchronized Runnable getJob() throws InterruptedException { while (jobstack.isEmpty()) { idleworkers++; logger.debug("waiting"); wait(); idleworkers--; if (shutdown) { throw new InterruptedException("shutdown in getJob"); } } // is expressed using strategy enumeration if (strategy == StrategyEnumeration.LIFO) { return jobstack.removeLast(); // LIFO } return jobstack.removeFirst(); // FIFO } /** * check if there are jobs for processing. */ public boolean hasJobs() { if (jobstack.size() > 0) { return true; } for (int i = 0; i < workers.length; i++) { if (workers[i] == null) { continue; } if (workers[i].isWorking) { return true; } } return false; } /** * check if there are more than n jobs for processing. * @param n Integer * @return true, if there are possibly more than n jobs. */ public boolean hasJobs(int n) { int j = jobstack.size(); if (j > 0 && (j + workers.length > n)) { return true; } // if j > 0 no worker should be idle // ( ( j > 0 && ( j+workers.length > n ) ) || ( j > n ) int x = 0; for (int i = 0; i < workers.length; i++) { if (workers[i] == null) { continue; } if (workers[i].isWorking) { x++; } } if ((j + x) > n) { return true; } return false; } } /** * Implements one Thread of the pool. */ class PoolThread extends Thread { ThreadPool pool; private static final Logger logger = Logger.getLogger(ThreadPool.class); private static boolean debug = logger.isDebugEnabled(); volatile boolean isWorking = false; /** * @param pool ThreadPool. */ public PoolThread(ThreadPool pool) { this.pool = pool; } /** * Run the thread. */ @Override public void run() { logger.info("ready"); Runnable job; int done = 0; long time = 0; long t; boolean running = true; while (running) { try { logger.debug("looking for a job"); job = pool.getJob(); if (job == null) { break; } if (debug) { logger.info("working"); } t = System.currentTimeMillis(); isWorking = true; job.run(); isWorking = false; time += System.currentTimeMillis() - t; done++; if (debug) { logger.info("done"); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); running = false; isWorking = false; } catch (PreemptingException e) { logger.debug("catched " + e); //e.printStackTrace(); } catch (RuntimeException e) { logger.warn("catched " + e); e.printStackTrace(); } } isWorking = false; logger.info("terminated, done " + done + " jobs in " + time + " milliseconds"); } } jas-2.5/src/edu/jas/util/DHTTransport.java0000644000175000017500000001441212040746164020646 0ustar giovannigiovanni/* * $Id: DHTTransport.java 4259 2012-10-21 10:20:37Z kredel $ */ package edu.jas.util; import java.io.Serializable; import java.io.IOException; import java.rmi.MarshalledObject; /** * Transport container for a distributed version of a HashTable. * Note: Contains code for timing of marshalled versus plain * object serialization which can be removed later. * @author Heinz Kredel */ public abstract class DHTTransport implements Serializable { static long etime = 0L; // encode marshalled static long dtime = 0L; // decode marshalled static long ertime = 0L; // encode plain raw static long drtime = 0L; // decode plain raw public static enum Stor { // storage and transport class marshal, plain }; public static final Stor stor = Stor.marshal; //Stor.plain; /** * protected constructor. */ protected DHTTransport() { } /** * Create a new DHTTransport Container. * @param key * @param value */ public static DHTTransport create(K key, V value) throws IOException { switch (stor) { case marshal: return new DHTTransportMarshal(key,value); case plain: return new DHTTransportPlain(key,value); default: throw new IllegalArgumentException("this should not happen"); } } /** * Get the key from this DHTTransport Container. */ public abstract K key() throws IOException, ClassNotFoundException; /** * Get the value from this DHTTransport Container. */ public abstract V value() throws IOException, ClassNotFoundException; /** * toString. */ @Override public String toString() { return this.getClass().getName(); } } /** * Transport container to signal termination for a distributed version * of a HashTable. Contains no objects. * @author Heinz Kredel */ class DHTTransportTerminate extends DHTTransport { /** * Get the key from this DHTTransport Container. */ public K key() throws IOException, ClassNotFoundException { throw new UnsupportedOperationException("this should not happen"); } /** * Get the value from this DHTTransport Container. */ public V value() throws IOException, ClassNotFoundException { throw new UnsupportedOperationException("this should not happen"); } } /** * Transport container for a distributed version of a HashTable. Immutable * objects. Uses MarshalledObject to avoid deserialization on server side. * @author Heinz Kredel */ class DHTTransportMarshal extends DHTTransport { protected final MarshalledObject/**/ key; protected final MarshalledObject/**/ value; /** * Constructs a new DHTTransport Container. * @param key * @param value */ public DHTTransportMarshal(K key, V value) throws IOException { long t = System.currentTimeMillis(); this.key = new MarshalledObject/**/(key); this.value = new MarshalledObject/**/(value); t = System.currentTimeMillis() - t; synchronized( DHTTransport.class ) { etime += t; } //System.out.println(" marshal time = " + t); } /** * Get the key from this DHTTransport Container. */ public K key() throws IOException, ClassNotFoundException { long t = System.currentTimeMillis(); K k = (K) this.key.get(); t = System.currentTimeMillis() - t; synchronized( DHTTransport.class ) { dtime += t; } return k; } /** * Get the value from this DHTTransport Container. */ public V value() throws IOException, ClassNotFoundException { long t = System.currentTimeMillis(); V v = (V) this.value.get(); t = System.currentTimeMillis() - t; synchronized( DHTTransport.class ) { dtime += t; } return v; } /** * toString. */ @Override public String toString() { return super.toString() + "(" + key + "," + value + ")"; } private void writeObject(java.io.ObjectOutputStream out) throws IOException { long t = System.currentTimeMillis(); out.defaultWriteObject(); t = System.currentTimeMillis() - t; synchronized( DHTTransport.class ) { ertime += t; } } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { long t = System.currentTimeMillis(); in.defaultReadObject(); t = System.currentTimeMillis() - t; // not meaningful, includes waiting time synchronized( DHTTransport.class ) { drtime += t; } } } /** * Transport container for a distributed version of a HashTable. Immutable * objects. Uses plain objects. * @author Heinz Kredel */ class DHTTransportPlain extends DHTTransport { protected final K key; protected final V value; /** * Constructs a new DHTTransport Container. * @param key * @param value */ public DHTTransportPlain(K key, V value) throws IOException { this.key = key; this.value = value; } /** * Get the key from this DHTTransport Container. */ public K key() throws IOException, ClassNotFoundException { return this.key; } /** * Get the value from this DHTTransport Container. */ public V value() throws IOException, ClassNotFoundException { return this.value; } /** * toString. */ @Override public String toString() { return super.toString() + "(" + key + "," + value + ")"; } private void writeObject(java.io.ObjectOutputStream out) throws IOException { long t = System.currentTimeMillis(); out.defaultWriteObject(); t = System.currentTimeMillis() - t; synchronized( DHTTransport.class ) { ertime += t; } } private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { long t = System.currentTimeMillis(); in.defaultReadObject(); t = System.currentTimeMillis() - t; synchronized( DHTTransport.class ) { drtime += t; } } } jas-2.5/src/edu/jas/util/CartesianProduct.java0000644000175000017500000000770412004530422021556 0ustar giovannigiovanni/* * $Id: CartesianProduct.java 4065 2012-07-27 15:17:38Z kredel $ */ package edu.jas.util; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; /** * Cartesian product with iterator. * @author Heinz Kredel */ public class CartesianProduct implements Iterable> { /** * data structure. */ public final List> comps; /** * CartesianProduct constructor. * @param comps components of the Cartesian product. */ public CartesianProduct(List> comps) { if (comps == null) { throw new IllegalArgumentException("null components not allowed"); } this.comps = comps; } // /** // * CartesianProduct constructor. // * @param comps components of the Cartesian product. // */ // public CartesianProduct(List> comps) { // this( listToIterable(comps) ); // } /** * Get an iterator over subsets. * @return an iterator. */ public Iterator> iterator() { return new CartesianProductIterator(comps); } /** * Transform list to iterables. * @param comp components of the Cartesian product. * @return iterables taken from lists. */ static List> listToIterable(List> comp) { List> iter = new ArrayList>(comp.size()); for (List list : comp) { iter.add(list); } return iter; } } /** * Cartesian product iterator. * @author Heinz Kredel */ class CartesianProductIterator implements Iterator> { /** * data structure. */ final List> comps; final List> compit; List current; boolean empty; /** * CartesianProduct iterator constructor. * @param comps components of the Cartesian product. */ public CartesianProductIterator(List> comps) { if (comps == null) { throw new IllegalArgumentException("null comps not allowed"); } this.comps = comps; current = new ArrayList(comps.size()); compit = new ArrayList>(comps.size()); empty = false; for (Iterable ci : comps) { Iterator it = ci.iterator(); if (!it.hasNext()) { empty = true; current.clear(); break; } current.add(it.next()); compit.add(it); } //System.out.println("current = " + current); } /** * Test for availability of a next tuple. * @return true if the iteration has more tuples, else false. */ public synchronized boolean hasNext() { return !empty; } /** * Get next tuple. * @return next tuple. */ public synchronized List next() { if (empty) { throw new NoSuchElementException("invalid call of next()"); } List res = new ArrayList(current); // search iterator which hasNext int i = compit.size() - 1; for (; i >= 0; i--) { Iterator iter = compit.get(i); if (iter.hasNext()) { break; } } if (i < 0) { empty = true; return res; } // update iterators for (int j = i + 1; j < compit.size(); j++) { Iterator iter = comps.get(j).iterator(); compit.set(j, iter); } // update current for (int j = i; j < compit.size(); j++) { Iterator iter = compit.get(j); E el = iter.next(); current.set(j, el); } return res; } /** * Remove a tuple if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove tuples"); } } jas-2.5/src/edu/jas/util/PowerSet.java0000644000175000017500000000552012004043370020047 0ustar giovannigiovanni/* * $Id: PowerSet.java 4052 2012-07-25 19:20:25Z kredel $ */ package edu.jas.util; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * Power set with iterator. * @author Heinz Kredel */ public class PowerSet implements Iterable> { /** * data structure. */ public final List set; // Iterable also ok /** * PowerSet constructor. * @param set generating set. */ public PowerSet(List set) { this.set = set; } /** * get an iterator over subsets. * @return an iterator. */ public Iterator> iterator() { return new PowerSetIterator(set); } } /** * Power set iterator. * @author Heinz Kredel */ class PowerSetIterator implements Iterator> { /** * data structure. */ public final List set; final List rest; final E current; private PowerSetIterator recIter; enum Mode { copy, extend, first, done }; Mode mode; /** * PowerSetIterator constructor. * @param set generating set. */ public PowerSetIterator(List set) { this.set = set; if (set == null || set.size() == 0) { current = null; recIter = null; rest = null; mode = Mode.first; return; } mode = Mode.copy; current = this.set.get(0); rest = new LinkedList(this.set); rest.remove(0); recIter = new PowerSetIterator(rest); } /** * Test for availability of a next subset. * @return true if the iteration has more subsets, else false. */ public boolean hasNext() { if (mode == Mode.first) { return true; } if (recIter == null) { return false; } return recIter.hasNext() || mode == Mode.copy; } /** * Get next subset. * @return next subset. */ public List next() { if (mode == Mode.first) { mode = Mode.done; List first = new LinkedList(); return first; } if (mode == Mode.extend) { if (recIter.hasNext()) { List next = new LinkedList(recIter.next()); next.add(current); return next; } } if (mode == Mode.copy) { if (recIter.hasNext()) { return recIter.next(); } mode = Mode.extend; recIter = new PowerSetIterator(rest); return this.next(); } return null; } /** * Remove the last subset returned from underlying set if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove subsets"); } } jas-2.5/src/edu/jas/util/DistHashTableServer.java0000644000175000017500000003147312004734512022160 0ustar giovannigiovanni/* * $Id: DistHashTableServer.java 4074 2012-07-28 10:04:58Z kredel $ */ package edu.jas.util; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; /** * Server for the distributed version of a list. * @author Heinz Kredel * @todo redistribute list for late coming clients, removal of elements. */ public class DistHashTableServer extends Thread { private static final Logger logger = Logger.getLogger(DistHashTableServer.class); public final static int DEFAULT_PORT = 9009; //ChannelFactory.DEFAULT_PORT + 99; protected final ChannelFactory cf; protected List> servers; private boolean goon = true; private Thread mythread = null; protected final SortedMap theList; private long etime; private long dtime; private long ertime; private long drtime; /** * Constructs a new DistHashTableServer. */ public DistHashTableServer() { this(DEFAULT_PORT); } /** * DistHashTableServer. * @param port to run server on. */ public DistHashTableServer(int port) { this(new ChannelFactory(port)); } /** * DistHashTableServer. * @param cf ChannelFactory to use. */ public DistHashTableServer(ChannelFactory cf) { this.cf = cf; cf.init(); servers = new ArrayList>(); theList = new TreeMap(); etime = DHTTransport.etime; dtime = DHTTransport.dtime; ertime = DHTTransport.ertime; drtime = DHTTransport.drtime; } /** * main. Usage: DistHashTableServer <port> */ public static void main(String[] args) throws InterruptedException { int port = DEFAULT_PORT; if (args.length < 1) { System.out.println("Usage: DistHashTableServer "); } else { try { port = Integer.parseInt(args[0]); } catch (NumberFormatException e) { } } DistHashTableServer dhts = new DistHashTableServer/*raw: */(port); dhts.init(); dhts.join(); // until CRTL-C } /** * thread initialization and start. */ public void init() { this.start(); } /** * main server method. */ @Override public void run() { SocketChannel channel = null; DHTBroadcaster s = null; mythread = Thread.currentThread(); Entry e; DHTTransport tc; while (goon) { //logger.debug("list server " + this + " go on"); try { channel = cf.getChannel(); if (logger.isDebugEnabled()) { logger.debug("dls channel = " + channel); } if (mythread.isInterrupted()) { goon = false; //logger.info("list server " + this + " interrupted"); } else { s = new DHTBroadcaster(channel, servers,/*listElem,*/theList); int ls = 0; synchronized (servers) { if (goon) { servers.add(s); ls = theList.size(); s.start(); } } if (logger.isInfoEnabled()) { logger.info("server " + s + " started " + s.isAlive()); } if (ls > 0) { //logger.debug("sending " + ls + " list elements"); synchronized (theList) { Iterator> it = theList.entrySet().iterator(); for (int i = 0; i < ls; i++) { e = it.next(); // n = e.getKey(); // findbugs, already in tc tc = e.getValue(); //DHTTransport tc = (DHTTransport) o; try { s.sendChannel(tc); } catch (IOException ioe) { // stop s } } } } } } catch (InterruptedException end) { goon = false; Thread.currentThread().interrupt(); } } if (logger.isDebugEnabled()) { logger.debug("listserver " + this + " terminated"); } } /** * terminate all servers. */ public void terminate() { goon = false; logger.debug("terminating ListServer"); if (cf != null) { cf.terminate(); } int svs = 0; if (servers != null) { synchronized (servers) { svs = servers.size(); Iterator> it = servers.iterator(); while (it.hasNext()) { DHTBroadcaster br = it.next(); br.closeChannel(); try { int c = 0; while (br.isAlive()) { c++; if (c > 10) { logger.warn("giving up on " + br); break; } //System.out.print("."); br.interrupt(); br.join(100); } if (logger.isDebugEnabled()) { logger.debug("server " + br + " terminated"); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } servers.clear(); } logger.info(svs + " broadcasters terminated"); //? servers = null; } logger.debug("DHTBroadcasters terminated"); long enc = DHTTransport.etime - etime; long dec = DHTTransport.dtime - dtime; long encr = DHTTransport.ertime - ertime; long decr = DHTTransport.drtime - drtime; long drest = (encr * dec) / (enc + 1); logger.info("DHT time: encode = " + enc + ", decode = " + dec + ", enc raw = " + encr + ", dec raw wait = " + decr + ", dec raw est = " + drest + ", sum est = " + (enc + dec + encr + drest)); // +decr not meaningful if (mythread == null) { return; } try { while (mythread.isAlive()) { //System.out.print("-"); mythread.interrupt(); mythread.join(100); } if (logger.isDebugEnabled()) { logger.debug("server terminated " + mythread); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } mythread = null; logger.debug("ListServer terminated"); } /** * number of servers. */ public int size() { if ( servers == null ) { return -1; } synchronized (servers) { return servers.size(); } } /** * toString. * @return a string representation of this. */ @Override public String toString() { return "DHTServer(" + servers.size() + ", " + cf + ", " + super.toString() + ")"; } } /** * Thread for broadcasting all incoming objects to the list clients. */ class DHTBroadcaster extends Thread /*implements Runnable*/{ private static final Logger logger = Logger.getLogger(DHTBroadcaster.class); private final SocketChannel channel; private final List> bcaster; private final SortedMap theList; /** * DHTBroadcaster. * @param s SocketChannel to use. * @param bc list of broadcasters. * @param le DHTCounter. * @param sm SortedMap with key value pairs. */ public DHTBroadcaster(SocketChannel s, List> bc, SortedMap sm) { channel = s; bcaster = bc; theList = sm; } /** * closeChannel. */ public void closeChannel() { channel.close(); } /** * sendChannel. * @param tc DHTTransport. * @throws IOException */ public void sendChannel(DHTTransport tc) throws IOException { channel.send(tc); } /** * broadcast. * @param o DHTTransport element to broadcast. */ @SuppressWarnings("unchecked") public void broadcast(DHTTransport o) { if (logger.isDebugEnabled()) { logger.debug("broadcast = " + o); } DHTTransport tc = null; if (o == null) { return; } //if ( ! (o instanceof DHTTransport) ) { // return; //} tc = (DHTTransport) o; K key = null; synchronized (theList) { //test //Object x = theList.get( tc.key ); //if ( x != null ) { // logger.info("theList duplicate key " + tc.key ); //} try { key = tc.key(); theList.put(key, tc); } catch (IOException e) { logger.warn("IO exception: tc.key() not ok " + tc); e.printStackTrace(); } catch (ClassNotFoundException e) { logger.warn("CNF exception: tc.key() not ok " + tc); e.printStackTrace(); } catch (Exception e) { logger.warn("exception:tc.key() not ok " + tc); e.printStackTrace(); } } logger.info("sending key=" + key + " to " + bcaster.size() + " nodes"); synchronized (bcaster) { Iterator> it = bcaster.iterator(); while (it.hasNext()) { DHTBroadcaster br = it.next(); try { if (logger.isDebugEnabled()) { logger.debug("bcasting to " + br); } br.sendChannel(tc); } catch (IOException e) { logger.info("bcaster, exception " + e); try { br.closeChannel(); while (br.isAlive()) { br.interrupt(); br.join(100); } } catch (InterruptedException w) { Thread.currentThread().interrupt(); } it.remove( /*br*/); //ConcurrentModificationException logger.debug("bcaster.remove() " + br); } catch (Exception e) { logger.info("bcaster, exception " + e); } } } } /** * run. */ @Override public void run() { boolean goon = true; while (goon) { try { logger.debug("trying to receive"); Object o = channel.receive(); if (this.isInterrupted()) { break; } if (logger.isDebugEnabled()) { logger.debug("received = " + o); } if (!(o instanceof DHTTransport)) { logger.warn("swallowed: " + o); continue; } DHTTransport tc = (DHTTransport) o; broadcast(tc); if (this.isInterrupted()) { goon = false; } } catch (IOException e) { goon = false; logger.info("receive, IO exception " + e); //e.printStackTrace(); } catch (ClassNotFoundException e) { goon = false; logger.info("receive, CNF exception " + e); e.printStackTrace(); } catch (Exception e) { goon = false; logger.info("receive, exception " + e); e.printStackTrace(); } } if (logger.isDebugEnabled()) { logger.debug("DHTBroadcaster terminated " + this); } channel.close(); } /** * toString. * @return a string representation of this. */ @Override public String toString() { return "DHTBroadcaster(" + channel + "," + bcaster.size() + ")"; } } jas-2.5/src/edu/jas/util/ChannelFactory.java0000644000175000017500000001566112033071650021212 0ustar giovannigiovanni/* * $Id: ChannelFactory.java 4229 2012-10-03 17:19:36Z kredel $ */ //package edu.unima.ky.parallel; package edu.jas.util; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.net.BindException; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; //import java.util.concurrent.ArrayBlockingQueue; import org.apache.log4j.Logger; /** * ChannelFactory implements a symmetric and non blocking way of setting up * sockets on the client and server side. The constructor sets up a ServerSocket * and accepts and stores any Socket creation requests from clients. The created * Sockets can the be retrieved from the store without blocking. Refactored for * java.util.concurrent. * @author Akitoshi Yoshida * @author Heinz Kredel. * @see SocketChannel */ public class ChannelFactory extends Thread { private static final Logger logger = Logger.getLogger(ChannelFactory.class); private final boolean debug = logger.isDebugEnabled(); /** * default port of socket. */ public final static int DEFAULT_PORT = 4711; /** * port of socket. */ private final int port; /** * BoundedBuffer for sockets. */ private final BlockingQueue buf; /** * local server socket. */ private volatile ServerSocket srv; /** * is local server up and running. */ private volatile boolean srvrun = false; /** * is thread started. */ private volatile boolean srvstart = false; /** * Constructs a ChannelFactory on the DEFAULT_PORT. */ public ChannelFactory() { this(DEFAULT_PORT); } /** * Constructs a ChannelFactory. * @param p port. */ public ChannelFactory(int p) { buf = new LinkedBlockingQueue(/*infinite*/); if (p <= 0) { port = DEFAULT_PORT; } else { port = p; } try { srv = new ServerSocket(port); //this.start(); moved to init and getChannel logger.info("server bound to port " + port); } catch (BindException e) { srv = null; logger.warn("server not started, port used " + port); if (debug) { e.printStackTrace(); } } catch (IOException e) { logger.debug("IOException " + e); if (logger.isDebugEnabled()) { e.printStackTrace(); } } } /** * toString. */ @Override public String toString() { return "" + this.getClass().getSimpleName() + "(" + srv + ", buf = " + buf.size() + ")"; } /** * thread initialization and start. */ public void init() { if (srv != null && ! srvstart ) { this.start(); srvstart = true; logger.info("ChannelFactory at " + srv); } } /** * Get a new socket channel from a server socket. */ public SocketChannel getChannel() throws InterruptedException { // return (SocketChannel)buf.get(); if (srv == null) { if (srvrun) { throw new IllegalArgumentException("dont call when no server listens"); } } else if ( ! srvstart ) { init(); } return buf.take(); } /** * Get a new socket channel to a given host. * @param h hostname * @param p port */ public SocketChannel getChannel(String h, int p) throws IOException { if (p <= 0) { p = port; } SocketChannel c = null; int i = 0; int delay = 5; // 50 logger.debug("connecting to " + h); while (c == null) { try { c = new SocketChannel(new Socket(h, p)); } catch (IOException e) { //System.out.println(e); // wait server ready i++; if (i % 50 == 0) { delay += delay; logger.info("Server on " + h + " not ready in " + delay + "ms"); } System.out.println("Server on " + h + " not ready in " + delay + "ms"); try { Thread.sleep(delay); if (i % 50 == 0 && debug) { throw new Exception("time wait, host = " + h + ", port = " + port); } } catch (InterruptedException w) { Thread.currentThread().interrupt(); throw new IOException("Interrupted during IO wait " + w); } catch (Exception ee) { // debug only ee.printStackTrace(); } } } logger.debug("connected, iter = " + i); return c; } /** * Run the servers accept() in an infinite loop. */ @Override public void run() { if (srv == null) { return; // nothing to do } srvrun = true; while (true) { try { logger.info("waiting for connection"); Socket s = srv.accept(); if (this.isInterrupted()) { //System.out.println("ChannelFactory interrupted"); srvrun = false; return; } //logger.debug("Socket = " +s); logger.debug("connection accepted"); SocketChannel c = new SocketChannel(s); buf.put(c); } catch (IOException e) { //logger.debug("ChannelFactory IO terminating"); srvrun = false; return; } catch (InterruptedException e) { // unfug Thread.currentThread().interrupt(); //logger.debug("ChannelFactory IE terminating"); srvrun = false; return; } } } /** * Terminate the Channel Factory */ public void terminate() { if ( ! srvstart ) { logger.debug("server not started"); return; } this.interrupt(); try { if (srv != null) { srv.close(); srvrun = false; } this.interrupt(); while (!buf.isEmpty()) { logger.debug("closing unused SocketChannel"); //((SocketChannel)buf.get()).close(); SocketChannel c = buf.poll(); if ( c != null ) { c.close(); } } } catch (IOException e) { //} catch (InterruptedException e) { // Thread.currentThread().interrupt(); } try { this.join(); } catch (InterruptedException e) { // unfug Thread.currentThread().interrupt(); } logger.debug("ChannelFactory terminated"); } } jas-2.5/src/edu/jas/util/RemoteExecutable.java0000644000175000017500000000047010653065064021547 0ustar giovannigiovanni/* * $Id: RemoteExecutable.java 1263 2007-07-29 10:21:40Z kredel $ */ package edu.jas.util; import java.io.Serializable; /** * Interface RemoteExecutable. * Used to mark a Serializable and Runnable class. * @author Heinz Kredel */ public interface RemoteExecutable extends Serializable, Runnable { } jas-2.5/src/edu/jas/util/DistThreadPool.java0000644000175000017500000003031312056360024021167 0ustar giovannigiovanni/* * $Id: DistThreadPool.java 4305 2012-12-01 10:46:45Z kredel $ */ package edu.jas.util; import java.io.FileNotFoundException; import java.io.IOException; import java.util.LinkedList; import org.apache.log4j.Logger; /** * Distributed thread pool. Using stack / list work-pile and Executable Channels * and Servers. * @author Heinz Kredel */ public class DistThreadPool /*extends ThreadPool*/{ /** * machine file to use. */ private final String mfile; /** * default machine file for test. */ private final static String DEFAULT_MFILE = ExecutableChannels.DEFAULT_MFILE; /** * Number of threads to use. */ protected final int threads; /** * Default number of threads to use. */ static final int DEFAULT_SIZE = 3; /** * Channels to remote executable servers. */ final ExecutableChannels ec; /** * Array of workers. */ protected DistPoolThread[] workers; /** * Number of idle workers. */ protected int idleworkers = 0; /** * Work queue / stack. */ // should be expressed using strategy pattern // List or Collection is not appropriate // LIFO strategy for recursion protected LinkedList jobstack; // FIFO strategy for GB protected StrategyEnumeration strategy = StrategyEnumeration.LIFO; private static final Logger logger = Logger.getLogger(DistThreadPool.class); private final boolean debug = true; //logger.isDebugEnabled(); /** * Constructs a new DistThreadPool with strategy StrategyEnumeration.FIFO * and size DEFAULT_SIZE. */ public DistThreadPool() { this(StrategyEnumeration.FIFO, DEFAULT_SIZE, null); } /** * Constructs a new DistThreadPool with size DEFAULT_SIZE. * @param strategy for job processing. */ public DistThreadPool(StrategyEnumeration strategy) { this(strategy, DEFAULT_SIZE, null); } /** * Constructs a new DistThreadPool with strategy StrategyEnumeration.FIFO. * @param size of the pool. */ public DistThreadPool(int size) { this(StrategyEnumeration.FIFO, size, null); } /** * Constructs a new DistThreadPool with strategy StrategyEnumeration.FIFO. * @param size of the pool. * @param mfile machine file. */ public DistThreadPool(int size, String mfile) { this(StrategyEnumeration.FIFO, size, mfile); } /** * Constructs a new DistThreadPool. * @param strategy for job processing. * @param size of the pool. * @param mfile machine file. */ public DistThreadPool(StrategyEnumeration strategy, int size, String mfile) { this.strategy = strategy; if (size < 0) { this.threads = 0; } else { this.threads = size; } if (mfile == null || mfile.length() == 0) { this.mfile = DEFAULT_MFILE; } else { this.mfile = mfile; } jobstack = new LinkedList(); // ok for all strategies ? try { ec = new ExecutableChannels(this.mfile); } catch (FileNotFoundException e) { e.printStackTrace(); throw new IllegalArgumentException("DistThreadPool " + e); } if (debug) { logger.info("ec = " + ec); } try { ec.open(threads); } catch (IOException e) { e.printStackTrace(); throw new IllegalArgumentException("DistThreadPool " + e); } if (debug) { logger.info("ec = " + ec); } workers = new DistPoolThread[0]; } /** * String representation. */ @Override public String toString() { StringBuffer s = new StringBuffer("DistThreadPool("); s.append("threads="+threads); s.append(", exchan="+ec); s.append(", workers="+workers.length); s.append(")"); return s.toString(); } /** * thread initialization and start. */ public void init() { if (workers == null || workers.length == 0) { workers = new DistPoolThread[threads]; for (int i = 0; i < workers.length; i++) { workers[i] = new DistPoolThread(this, ec, i); workers[i].start(); } logger.info("size = " + threads + ", strategy = " + strategy); } } /** * number of worker threads. */ public int getNumber() { if (workers == null || workers.length < threads) { init(); // start threads } return workers.length; // not null } /** * get used strategy. */ public StrategyEnumeration getStrategy() { return strategy; } /** * the used executable channel. */ public ExecutableChannels getEC() { return ec; // not null } /** * Terminates the threads. * @param shutDown true, if shut-down of the remote executable servers is * requested, false, if remote executable servers stay alive. */ public void terminate(boolean shutDown) { if (shutDown) { ShutdownRequest sdr = new ShutdownRequest(); for (int i = 0; i < workers.length; i++) { addJob(sdr); } try { Thread.sleep(20); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } logger.info("remaining jobs = " + jobstack.size()); try { for (int i = 0; i < workers.length; i++) { while (workers[i].isAlive()) { workers[i].interrupt(); workers[i].join(100); } } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } else { terminate(); } } /** * Terminates the threads. */ public void terminate() { while (hasJobs()) { try { Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } for (int i = 0; i < workers.length; i++) { try { while (workers[i].isAlive()) { workers[i].interrupt(); workers[i].join(100); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } ec.close(); } /** * adds a job to the workpile. * @param job */ public synchronized void addJob(Runnable job) { if (workers == null || workers.length < threads) { init(); // start threads } jobstack.addLast(job); logger.debug("adding job"); if (idleworkers > 0) { logger.debug("notifying a jobless worker"); notifyAll(); // findbugs } } /** * get a job for processing. */ protected synchronized Runnable getJob() throws InterruptedException { while (jobstack.isEmpty()) { idleworkers++; logger.debug("waiting"); wait(); idleworkers--; } // is expressed using strategy enumeration if (strategy == StrategyEnumeration.LIFO) { return jobstack.removeLast(); // LIFO } return jobstack.removeFirst(); // FIFO } /** * check if there are jobs for processing. */ public boolean hasJobs() { if (jobstack.size() > 0) { return true; } for (int i = 0; i < workers.length; i++) { if (workers[i].working) { return true; } } return false; } /** * check if there are more than n jobs for processing. * @param n Integer * @return true, if there are possibly more than n jobs. */ public boolean hasJobs(int n) { int j = jobstack.size(); if (j > 0 && (j + workers.length > n)) { return true; // if j > 0 no worker should be idle // ( ( j > 0 && ( j+workers.length > n ) ) || ( j > n ) } int x = 0; for (int i = 0; i < workers.length; i++) { if (workers[i].working) { x++; } } if ((j + x) > n) { return true; } return false; } } /** * Implements a shutdown task. */ class ShutdownRequest implements Runnable { /** * Run the thread. */ public void run() { System.out.println("running ShutdownRequest"); } /** * toString. * @see java.lang.Object#toString() */ @Override public String toString() { return "ShutdownRequest"; } } /** * Implements one local part of the distributed thread. */ class DistPoolThread extends Thread { final DistThreadPool pool; final ExecutableChannels ec; final int myId; private static final Logger logger = Logger.getLogger(DistPoolThread.class); private final boolean debug = logger.isDebugEnabled(); boolean working = false; /** * @param pool DistThreadPool. */ public DistPoolThread(DistThreadPool pool, ExecutableChannels ec, int i) { this.pool = pool; this.ec = ec; myId = i; } /** * Run the thread. */ @Override public void run() { logger.info("ready, myId = " + myId); Runnable job; int done = 0; long time = 0; long t; boolean running = true; while (running) { try { logger.debug("looking for a job"); job = pool.getJob(); working = true; if (debug) { logger.info("working " + myId + " on " + job); } t = System.currentTimeMillis(); // send and wait, like rmi try { if (job instanceof ShutdownRequest) { ec.send(myId, ExecutableServer.STOP); } else { ec.send(myId, job); } if (debug) { logger.info("send " + myId + " at " + ec + " send job " + job); } } catch (IOException e) { e.printStackTrace(); logger.info("error send " + myId + " at " + ec + " e = " + e); working = false; } // remote: job.run(); Object o = null; try { if (working) { logger.info("waiting " + myId + " on " + job); o = ec.receive(myId); if (debug) { logger.info("receive " + myId + " at " + ec + " send job " + job + " received " + o); } } } catch (IOException e) { logger.info("receive exception " + myId + " send job " + job + ", " + e); //e.printStackTrace(); running = false; } catch (ClassNotFoundException e) { logger.info("receive exception " + myId + " send job " + job + ", " + e); //e.printStackTrace(); running = false; } finally { if (debug) { logger.info("receive finally " + myId + " at " + ec + " send job " + job + " received " + o + " running " + running); } } working = false; time += System.currentTimeMillis() - t; done++; if (debug) { logger.info("done " + myId + " with " + o); } } catch (InterruptedException e) { running = false; Thread.currentThread().interrupt(); } } logger.info("terminated " + myId + " , done " + done + " jobs in " + time + " milliseconds"); } } jas-2.5/src/edu/jas/util/StrategyEnumeration.java0000644000175000017500000000123612004530422022307 0ustar giovannigiovanni/* * $Id: StrategyEnumeration.java 4065 2012-07-27 15:17:38Z kredel $ */ package edu.jas.util; /** * StrategyEnumeration. This class names possible / implemented strategies for * thread pools. * @author Heinz Kredel. */ public final class StrategyEnumeration { public static final StrategyEnumeration FIFO = new StrategyEnumeration(); public static final StrategyEnumeration LIFO = new StrategyEnumeration(); private StrategyEnumeration() { } /** * toString. */ @Override public String toString() { if (this == FIFO) { return "FIFO strategy"; } return "LIFO strategy"; } } jas-2.5/src/edu/jas/util/TaggedSocketChannel.java0000644000175000017500000003111311777635412022155 0ustar giovannigiovanni/* * $Id: TaggedSocketChannel.java 3982 2012-07-12 21:00:59Z kredel $ */ package edu.jas.util; import java.io.IOException; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; /** * TaggedSocketChannel provides a communication channel with message tags for * Java objects using TCP/IP sockets. * @author Heinz Kredel. */ public class TaggedSocketChannel extends Thread { private static final Logger logger = Logger.getLogger(TaggedSocketChannel.class); private static final boolean debug = logger.isDebugEnabled(); /** * Flag if receiver is running. */ private volatile boolean isRunning = false; /** * End message. */ private final static String DONE = "TaggedSocketChannel Done"; /** * Blocked threads count. */ private final AtomicInteger blockedCount; /** * Underlying socket channel. */ protected final SocketChannel sc; /** * Queues for each message tag. */ protected final Map queues; /** * Constructs a tagged socket channel on the given socket channel s. * @param s A socket channel object. */ public TaggedSocketChannel(SocketChannel s) { sc = s; blockedCount = new AtomicInteger(0); queues = new HashMap(); } /** * thread initialization and start. */ public void init() { synchronized (queues) { if ( ! isRunning ) { this.start(); isRunning = true; } } logger.info("TaggedSocketChannel at " + sc); } /** * Get the SocketChannel */ public SocketChannel getSocket() { return sc; } /** * Sends an object. * @param tag message tag * @param v object to send * @throws IOException */ public void send(Integer tag, Object v) throws IOException { if (tag == null) { throw new IllegalArgumentException("tag null not allowed"); } if (v instanceof Exception) { throw new IllegalArgumentException("message " + v + " not allowed"); } TaggedMessage tm = new TaggedMessage(tag, v); sc.send(tm); } /** * Receive an object. * @param tag message tag * @return object received * @throws InterruptedException * @throws IOException * @throws ClassNotFoundException */ public Object receive(Integer tag) throws InterruptedException, IOException, ClassNotFoundException { BlockingQueue tq = null; int i = 0; do { synchronized (queues) { tq = queues.get(tag); if (tq == null) { if ( ! isRunning ) { // avoid dead-lock throw new IOException("receiver not running for " + this); } //tq = new LinkedBlockingQueue(); //queues.put(tag, tq); try { logger.debug("receive wait, tag = " + tag); i = blockedCount.incrementAndGet(); queues.wait(); } catch (InterruptedException e) { logger.info("receive wait exception, tag = " + tag + ", blockedCount = " + i); throw e; } finally { i = blockedCount.decrementAndGet(); } } } } while ( tq == null ); Object v = null; try { i = blockedCount.incrementAndGet(); v = tq.take(); } finally { i = blockedCount.decrementAndGet(); } if ( v instanceof IOException ) { throw (IOException) v; } if ( v instanceof ClassNotFoundException ) { throw (ClassNotFoundException) v; } if ( v instanceof Exception ) { throw new RuntimeException(v.toString()); } return v; } /** * Closes the channel. */ public void close() { terminate(); } /** * To string. * @see java.lang.Thread#toString() */ @Override public String toString() { return "socketChannel(" + sc + ", tags = " + queues.keySet() + ")"; //return "socketChannel(" + sc + ", tags = " + queues.keySet() + ", values = " + queues.values() + ")"; } /** * Number of tags. * @return size of key set. */ public int tagSize() { return queues.keySet().size(); } /** * Number of messages. * @return sum of all messages in queues. */ public int messages() { int m = 0; synchronized (queues) { for ( BlockingQueue tq : queues.values() ) { m += tq.size(); } } return m; } /** * Run receive() in an infinite loop. * @see java.lang.Thread#run() */ @Override public void run() { if (sc == null) { isRunning = false; return; // nothing to do } isRunning = true; while (isRunning) { try { Object r = null; try { logger.debug("waiting for tagged object"); r = sc.receive(); if (this.isInterrupted()) { //r = new InterruptedException(); isRunning = false; } } catch (IOException e) { r = e; } catch (ClassNotFoundException e) { r = e; } catch (Exception e) { r = e; } //logger.debug("Socket = " +s); logger.debug("object recieved"); if (r instanceof TaggedMessage) { TaggedMessage tm = (TaggedMessage) r; BlockingQueue tq = null; synchronized (queues) { tq = queues.get(tm.tag); if (tq == null) { tq = new LinkedBlockingQueue(); queues.put(tm.tag, tq); queues.notifyAll(); } } tq.put(tm.msg); } else if ( r instanceof Exception ){ if (debug) { logger.debug("exception " + r); } synchronized (queues) { // deliver to all queues isRunning = false; for ( BlockingQueue q : queues.values() ) { final int bc = blockedCount.get(); for ( int i = 0; i <= bc; i++ ) { // one more q.put(r); } if (bc > 0) { logger.debug("put exception to queue, blockedCount = " + bc); } } queues.notifyAll(); } //return; } else { if (debug) { logger.debug("no tagged message and no exception " + r); } synchronized (queues) { // deliver to all queues isRunning = false; Exception e; if ( r.equals(DONE) ) { e = new Exception("DONE message"); } else { e = new IllegalArgumentException("no tagged message and no exception '" + r + "'"); } for ( BlockingQueue q : queues.values() ) { final int bc = blockedCount.get(); for ( int i = 0; i <= bc; i++ ) { // one more q.put(e); } if (bc > 0) { logger.debug("put '" + e.toString() + "' to queue, blockedCount = " + bc); } } queues.notifyAll(); } if ( r.equals(DONE) ) { logger.info("run terminating by request"); try { sc.send(DONE); // terminate other end } catch (IOException e) { logger.warn("send other done failed " + e); } return; } } } catch (InterruptedException e) { // unfug Thread.currentThread().interrupt(); //logger.debug("ChannelFactory IE terminating"); if (debug) { logger.debug("exception " + e); } synchronized (queues) { // deliver to all queues isRunning = false; for ( BlockingQueue q : queues.values() ) { try { final int bc = blockedCount.get(); for ( int i = 0; i <= bc; i++ ) { // one more q.put(e); } if (bc > 0) { logger.debug("put interrupted to queue, blockCount = " + bc); } } catch (InterruptedException ignored) { } } queues.notifyAll(); } //return via isRunning } } if (this.isInterrupted()) { Exception e = new InterruptedException("terminating via interrupt"); synchronized (queues) { // deliver to all queues for ( BlockingQueue q : queues.values() ) { try { final int bc = blockedCount.get(); for ( int i = 0; i <= bc; i++ ) { // one more q.put(e); } if (bc > 0) { logger.debug("put terminating via interrupt to queue, blockCount = " + bc); } } catch (InterruptedException ignored) { } } queues.notifyAll(); } } logger.info("run terminated"); } /** * Terminate the TaggedSocketChannel. */ public void terminate() { isRunning = false; this.interrupt(); if (sc != null) { //sc.close(); try { sc.send(DONE); } catch (IOException e) { logger.warn("send done failed " + e); } logger.debug(sc + " not yet closed"); } this.interrupt(); synchronized(queues) { isRunning = false; for (Entry tq : queues.entrySet()) { BlockingQueue q = tq.getValue(); if (q.size() != 0) { logger.info("queue for tag " + tq.getKey() + " not empty " + q); } int bc = 0; try { bc = blockedCount.get(); for ( int i = 0; i <= bc; i++ ) { // one more q.put(new IOException("queue terminate")); } } catch (InterruptedException ignored) { } if ( bc > 0 ) { logger.debug("put IO-end to queue for tag " + tq.getKey() + ", blockCount = " + bc); } } queues.notifyAll(); } try { this.join(); } catch (InterruptedException e) { // unfug Thread.currentThread().interrupt(); } logger.info("terminated"); } } /** * TaggedMessage container. * @author kredel * */ class TaggedMessage implements Serializable { public final Integer tag; public final Object msg; /** * Constructor. * @param tag message tag * @param msg message object */ public TaggedMessage(Integer tag, Object msg) { this.tag = tag; this.msg = msg; } } jas-2.5/src/edu/jas/util/CatReader.java0000644000175000017500000000315712004530422020134 0ustar giovannigiovanni/* * $Id: CatReader.java 4065 2012-07-27 15:17:38Z kredel $ */ package edu.jas.util; import java.io.IOException; import java.io.Reader; // import org.apache.log4j.Logger; /** * Reader to conncat two readers. Read from first reader until it is empty, then * read from second reader. * @author Heinz Kredel */ public class CatReader extends Reader { // private static final Logger logger = Logger.getLogger(CatReader.class); // private static boolean debug = logger.isDebugEnabled(); private final Reader first; private final Reader second; private boolean doFirst; /** * Constructor. * @param f first Reader. * @param s second Reader. */ public CatReader(Reader f, Reader s) { first = f; second = s; doFirst = true; } /** * Read char array. * @param cbuf array. * @param off start offset. * @param len number of chars to read. * @return number of chars read, or -1. */ @Override public int read(char[] cbuf, int off, int len) throws IOException { int i = -1; if (doFirst) { i = first.read(cbuf, off, len); if (i < 0) { doFirst = false; i = second.read(cbuf, off, len); } } else { i = second.read(cbuf, off, len); } //System.out.println("i = " + i); return i; } /** * Close this Reader. */ @Override public void close() throws IOException { try { first.close(); } finally { second.close(); } } } jas-2.5/src/edu/jas/util/machines.localhost0000644000175000017500000000036010371100532021131 0ustar giovannigiovanni# maschines file for jas localhost:7114 # first host is master localhost:8114 # first client host, master-port+1000 #localhost:9114 # second host with port #localhost:8411 # next host with port #localhost:8411 # last host # eof jas-2.5/src/edu/jas/util/ExecutableChannels.java0000644000175000017500000002003012004756654022045 0ustar giovannigiovanni/* * $Id: ExecutableChannels.java 4078 2012-07-28 12:40:12Z kredel $ */ package edu.jas.util; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; // import edu.unima.ky.parallel.ChannelFactory; // import edu.unima.ky.parallel.SocketChannel; /** * ExecutableChannels used to receive and execute classes. * @author Heinz Kredel */ public class ExecutableChannels { private static final Logger logger = Logger.getLogger(ExecutableChannels.class); /** * default port. */ protected final static int DEFAULT_PORT = 7114; //ChannelFactory.DEFAULT_PORT; /** * default machine file. */ protected final static String DEFAULT_MFILE = "examples/machines.test"; protected final ChannelFactory cf; protected SocketChannel[] channels = null; protected String[] servers = null; protected int[] ports = null; /** * Internal constructor. */ protected ExecutableChannels() { cf = new ChannelFactory(); cf.init(); } /** * Constructor from array of server:port strings. * @param srvs A String array. */ public ExecutableChannels(String[] srvs) { this(); if (srvs == null) { return; } servers = new String[srvs.length]; ports = new int[srvs.length]; for (int i = 0; i < srvs.length; i++) { setServerPort(i, srvs[i]); } } /** * Constructor from machine file. * @param mfile * @throws FileNotFoundException. */ public ExecutableChannels(String mfile) throws FileNotFoundException { this(); if (mfile == null || mfile.length() == 0) { mfile = DEFAULT_MFILE; } InputStreamReader isr = new InputStreamReader(new FileInputStream(mfile),Charset.forName("UTF8")); BufferedReader in = new BufferedReader(isr); String line = null; List list = new ArrayList(); int x; try { while (true) { if (!in.ready()) { break; } line = in.readLine(); if (line == null) { break; } x = line.indexOf("#"); if (x >= 0) { line = line.substring(0, x); } line = line.trim(); if (line.length() == 0) { continue; } list.add(line); } } catch (IOException ignored) { } finally { try { in.close(); } catch (IOException ignore) { } } logger.debug("list.size() in " + mfile + " = " + list.size()); if (list.size() == 0) { return; } servers = new String[list.size()]; ports = new int[list.size()]; for (int i = 0; i < servers.length; i++) { setServerPort(i, list.get(i)); } } /* * internal method */ protected void setServerPort(int i, String srv) { int x = srv.indexOf(":"); ports[i] = DEFAULT_PORT; if (x < 0) { servers[i] = srv; } else { servers[i] = srv.substring(0, x); String p = srv.substring(x + 1, srv.length()); try { ports[i] = Integer.parseInt(p); } catch (NumberFormatException ignored) { } } } /** * String representation. */ @Override public String toString() { StringBuffer s = new StringBuffer("ExecutableChannels("); if (servers != null) { for (int i = 0; i < servers.length; i++) { s.append(servers[i] + ":" + ports[i]); if (i < servers.length - 1) { s.append(" "); } } } if (channels != null) { s.append(" channels = "); for (int i = 0; i < channels.length; i++) { s.append(channels[i]); if (i < channels.length - 1) { s.append(" "); } } } s.append(")"); return s.toString(); } /** * number of servers. */ public int numServers() { if (servers != null) { return servers.length; } return -1; } /** * get master host. */ public String getMasterHost() { if (servers != null && servers.length > 0) { return servers[0]; } return null; } /** * get master port. */ public int getMasterPort() { if (ports != null && ports.length > 0) { return ports[0]; } return 0; } /** * number of channels. */ public int numChannels() { if (channels != null) { return channels.length; } return -1; } /** * open, setup of SocketChannels. * @throws IOException. */ public void open() throws IOException { logger.debug("opening " + servers.length + " channels"); if (servers.length <= 1) { throw new IOException("to few servers"); } channels = new SocketChannel[servers.length - 1]; for (int i = 1; i < servers.length; i++) { channels[i - 1] = cf.getChannel(servers[i], ports[i]); } } /** * open, setup of SocketChannels. If nc > servers.length open in round * robin fashion. * @param nc number of channels to open. * @throws IOException. */ public void open(int nc) throws IOException { logger.debug("opening " + nc + " channels"); if (servers.length <= 1) { throw new IOException("to few servers"); } channels = new SocketChannel[nc]; int j = 1; // 0 is master for (int i = 0; i < channels.length; i++) { if (j >= servers.length) { // modulo #servers j = 1; } channels[i] = cf.getChannel(servers[j], ports[j]); j++; } } /** * close all channels and ChannelFactory. */ public void close() { logger.debug("closing ExecutableChannels"); if (cf != null) { cf.terminate(); } if (channels != null) { for (int i = 0; i < channels.length; i++) { if (channels[i] != null) { try { channels[i].send(ExecutableServer.STOP); } catch (IOException e) { e.printStackTrace(); } finally { channels[i].close(); } channels[i] = null; } } channels = null; } logger.debug("ExecuteChannels closed"); } /** * getChannel. * @param i channel number. */ public SocketChannel getChannel(int i) { if (channels != null && 0 <= i && i < channels.length) { return channels[i]; } return null; } /** * getChannels. */ /*package*/SocketChannel[] getChannels() { return channels; } /** * send on channel i. * @param i channel number. * @param o object to send. */ public void send(int i, Object o) throws IOException { if (channels != null && 0 <= i && i < channels.length) { channels[i].send(o); } } /** * recieve on channel i. * @param i channel number. * @return object recieved. */ public Object receive(int i) throws IOException, ClassNotFoundException { if (channels != null && 0 <= i && i < channels.length) { return channels[i].receive(); } return null; } } jas-2.5/src/edu/jas/util/DistributedList.java0000644000175000017500000001277712011714752021440 0ustar giovannigiovanni/* * $Id: DistributedList.java 4096 2012-08-12 11:56:27Z kredel $ */ package edu.jas.util; import java.io.IOException; import java.util.Iterator; //import java.util.Collection; import java.util.List; import java.util.ArrayList; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; //import edu.unima.ky.parallel.ChannelFactory; //import edu.unima.ky.parallel.SocketChannel; /** * Distributed version of a List. * Implemented with a SortedMap / TreeMap to keep the sequence order of elements. * @author Heinz Kredel */ public class DistributedList /* implements List not jet */ { private static final Logger logger = Logger.getLogger(DistributedList.class); protected final SortedMap theList; protected final ChannelFactory cf; protected SocketChannel channel = null; protected Listener listener = null; /** * Constructor for DistributedList. * @param host name or IP of server host. */ public DistributedList(String host) { this(host,DistributedListServer.DEFAULT_PORT); } /** * Constructor for DistributedList. * @param host name or IP of server host. * @param port of server. */ public DistributedList(String host,int port) { this(new ChannelFactory(port+1),host,port); } /** * Constructor for DistributedList. * @param cf ChannelFactory to use. * @param host name or IP of server host. * @param port of server. */ public DistributedList(ChannelFactory cf,String host,int port) { this.cf = cf; cf.init(); try { channel = cf.getChannel(host,port); } catch (IOException e) { e.printStackTrace(); } logger.debug("dl channel = " + channel); theList = new TreeMap(); } /** * Constructor for DistributedList. * @param sc SocketChannel to use. */ public DistributedList(SocketChannel sc) { cf = null; channel = sc; theList = new TreeMap(); } /** * List thread initialization and start. */ public void init() { listener = new Listener(channel,theList); listener.start(); } /** * Terminate the list thread. */ public void terminate() { if ( cf != null ) { cf.terminate(); logger.warn("terminating " + cf); } if ( channel != null ) { channel.close(); } //theList.clear(); if ( listener == null ) { return; } logger.debug("terminate " + listener); listener.setDone(); try { while ( listener.isAlive() ) { listener.interrupt(); listener.join(100); } } catch (InterruptedException u) { Thread.currentThread().interrupt(); } listener = null; } /** * Get the internal list, convert from Collection. */ public List getList() { return new ArrayList( theList.values() ); } /** * Size of the (local) list. */ public int size() { return theList.size(); } /** * Add object to the list and distribute to other lists. * Blocks until the object is send and received from the server * (actually it blocks until some object is received). * @param o */ public synchronized void add(Object o) { int sz1 = theList.size() + 1; try { channel.send(o); //System.out.println("send: "+o+" @ "+listener); } catch (IOException e) { e.printStackTrace(); } try { while ( theList.size() < sz1 ) { this.wait(100); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); e.printStackTrace(); } } /** * Clear the List. * caveat: must be called on all clients. */ public synchronized void clear() { theList.clear(); } /** * Is the List empty? */ public boolean isEmpty() { return theList.isEmpty(); } /** * List iterator. */ public Iterator iterator() { return theList.values().iterator(); } } /** * Thread to comunicate with the list server. */ class Listener extends Thread { private SocketChannel channel; private SortedMap theList; private boolean goon; Listener(SocketChannel s, SortedMap list) { channel = s; theList = list; } void setDone() { goon = false; } @Override public void run() { Counter n; Object o; goon = true; while (goon) { n = null; o = null; try { n = (Counter) channel.receive(); if ( this.isInterrupted() ) { goon = false; } else { o = channel.receive(); //System.out.println("receive("+n+","+o+" @ "+Thread.currentThread()); if ( this.isInterrupted() ) { goon = false; } theList.put(n,o); } } catch (IOException e) { goon = false; } catch (ClassNotFoundException e) { e.printStackTrace(); goon = false; } } } } jas-2.5/src/edu/jas/util/CartesianProductInfinite.java0000644000175000017500000002247512004530422023246 0ustar giovannigiovanni/* * $Id: CartesianProductInfinite.java 4065 2012-07-27 15:17:38Z kredel $ */ package edu.jas.util; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.NoSuchElementException; /** * Cartesian product of infinite components with iterator. Works also for finite * iterables. * @author Heinz Kredel */ public class CartesianProductInfinite implements Iterable> { /** * data structure. */ public final List> comps; /** * CartesianProduct constructor. * @param comps components of the Cartesian product. */ public CartesianProductInfinite(List> comps) { if (comps == null || comps.size() == 0) { throw new IllegalArgumentException("null components not allowed"); } this.comps = comps; } /** * Get an iterator over subsets. * @return an iterator. */ public Iterator> iterator() { if (comps.size() == 1) { return new CartesianOneProductInfiniteIterator(comps.get(0)); } // if ( comps.size() == 2 ) { // this part is not realy required // return new CartesianTwoProductInfiniteIterator(comps.get(0),comps.get(1)); // } int n = comps.size(); int k = n / 2 + n % 2; // ceiling Iterable> c0 = new CartesianProductInfinite(comps.subList(0, k)); Iterable> c1 = new CartesianProductInfinite(comps.subList(k, n)); return new CartesianTwoProductInfiniteIteratorList(c0, c1); } } /** * Cartesian product infinite iterator, one factor. * @author Heinz Kredel */ class CartesianOneProductInfiniteIterator implements Iterator> { /** * data structure. */ final Iterator compit; /** * CartesianProduct iterator constructor. * @param comps components of the cartesian product. */ public CartesianOneProductInfiniteIterator(Iterable comps) { if (comps == null) { throw new IllegalArgumentException("null comps not allowed"); } compit = comps.iterator(); } /** * Test for availability of a next tuple. * @return true if the iteration has more tuples, else false. */ public synchronized boolean hasNext() { return compit.hasNext(); } /** * Get next tuple. * @return next tuple. */ public synchronized List next() { List res = new ArrayList(1); res.add(compit.next()); return res; } /** * Remove a tuple if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove tuples"); } } /** * Cartesian product infinite iterator, two factors. * @author Heinz Kredel */ class CartesianTwoProductInfiniteIterator implements Iterator> { /** * data structure. */ final Iterator compit0; final Iterator compit1; final List fincomps0; final List fincomps1; Iterator fincompit0; Iterator fincompit1; List current; boolean empty; long level; /** * CartesianProduct iterator constructor. * @param comps components of the Cartesian product. */ public CartesianTwoProductInfiniteIterator(Iterable comps0, Iterable comps1) { if (comps0 == null || comps1 == null) { throw new IllegalArgumentException("null comps not allowed"); } empty = false; level = 0; current = new ArrayList(2); compit0 = comps0.iterator(); E e = compit0.next(); current.add(e); fincomps0 = new ArrayList(); fincomps0.add(e); fincompit0 = fincomps0.iterator(); E d = fincompit0.next(); // remove current compit1 = comps1.iterator(); e = compit1.next(); current.add(e); fincomps1 = new ArrayList(); fincomps1.add(e); fincompit1 = fincomps1.iterator(); //@SuppressWarnings("unused") d = fincompit1.next(); // remove current //System.out.println("current = " + current); } /** * Test for availability of a next tuple. * @return true if the iteration has more tuples, else false. */ public synchronized boolean hasNext() { return !empty; } /** * Get next tuple. * @return next tuple. */ public synchronized List next() { if (empty) { throw new NoSuchElementException("invalid call of next()"); } List res = current; // new ArrayList(current); // copy if (fincompit0.hasNext() && fincompit1.hasNext()) { E e0 = fincompit0.next(); E e1 = fincompit1.next(); current = new ArrayList(); current.add(e0); current.add(e1); return res; } level++; if (level % 2 == 1) { Collections.reverse(fincomps0); } else { Collections.reverse(fincomps1); } if (compit0.hasNext() && compit1.hasNext()) { fincomps0.add(compit0.next()); fincomps1.add(compit1.next()); } else { empty = true; return res; } if (level % 2 == 0) { Collections.reverse(fincomps0); } else { Collections.reverse(fincomps1); } //System.out.println("list(0) = " + fincomps0); //System.out.println("list(1) = " + fincomps1); fincompit0 = fincomps0.iterator(); fincompit1 = fincomps1.iterator(); E e0 = fincompit0.next(); E e1 = fincompit1.next(); current = new ArrayList(); current.add(e0); current.add(e1); return res; } /** * Remove a tuple if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove tuples"); } } /** * Cartesian product infinite iterator, two factors list version. * @author Heinz Kredel */ class CartesianTwoProductInfiniteIteratorList implements Iterator> { /** * data structure. */ final Iterator> compit0; final Iterator> compit1; final List> fincomps0; final List> fincomps1; Iterator> fincompit0; Iterator> fincompit1; List current; boolean empty; long level; /** * CartesianProduct iterator constructor. * @param comps components of the Cartesian product. */ public CartesianTwoProductInfiniteIteratorList(Iterable> comps0, Iterable> comps1) { if (comps0 == null || comps1 == null) { throw new IllegalArgumentException("null comps not allowed"); } current = new ArrayList(); empty = false; level = 0; compit0 = comps0.iterator(); List e = compit0.next(); current.addAll(e); fincomps0 = new ArrayList>(); fincomps0.add(e); fincompit0 = fincomps0.iterator(); List d = fincompit0.next(); // remove current compit1 = comps1.iterator(); e = compit1.next(); current.addAll(e); fincomps1 = new ArrayList>(); fincomps1.add(e); fincompit1 = fincomps1.iterator(); //@SuppressWarnings("unused") d = fincompit1.next(); // remove current //System.out.println("current = " + current); } /** * Test for availability of a next tuple. * @return true if the iteration has more tuples, else false. */ public synchronized boolean hasNext() { return !empty; } /** * Get next tuple. * @return next tuple. */ public synchronized List next() { if (empty) { throw new NoSuchElementException("invalid call of next()"); } List res = current; // new ArrayList(current); if (fincompit0.hasNext() && fincompit1.hasNext()) { List e0 = fincompit0.next(); List e1 = fincompit1.next(); current = new ArrayList(); current.addAll(e0); current.addAll(e1); return res; } level++; if (level % 2 == 1) { Collections.reverse(fincomps0); } else { Collections.reverse(fincomps1); } if (compit0.hasNext() && compit1.hasNext()) { fincomps0.add(compit0.next()); fincomps1.add(compit1.next()); } else { empty = true; return res; } if (level % 2 == 0) { Collections.reverse(fincomps0); } else { Collections.reverse(fincomps1); } //System.out.println("list(0) = " + fincomps0); //System.out.println("list(1) = " + fincomps1); fincompit0 = fincomps0.iterator(); fincompit1 = fincomps1.iterator(); List e0 = fincompit0.next(); List e1 = fincompit1.next(); current = new ArrayList(); current.addAll(e0); current.addAll(e1); return res; } /** * Remove a tuple if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove tuples"); } } jas-2.5/src/edu/jas/util/machines0000644000175000017500000000035710170255502017155 0ustar giovannigiovanni# maschines file for jas 10.1.1.254:7114 # first host is master 10.1.1.254:8114 # first client host, master-port+1000 10.1.1.254:8114 # second host with port #localhost:7411 # next host with port #localhost:7411 # last host # eof jas-2.5/src/edu/jas/util/ListUtil.java0000644000175000017500000000441612004530422020052 0ustar giovannigiovanni/* * $Id: ListUtil.java 4065 2012-07-27 15:17:38Z kredel $ */ package edu.jas.util; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import edu.jas.structure.Element; import edu.jas.structure.UnaryFunctor; /** * List utilities. For example map functor on list elements. * @author Heinz Kredel */ public class ListUtil { //private static final Logger logger = Logger.getLogger(ListUtil.class); // private static boolean debug = logger.isDebugEnabled(); /** * Map a unary function to the list. * @param f evaluation functor. * @return new list elements f(list(i)). */ public static , D extends Element> List map(List list, UnaryFunctor f) { if (list == null) { return null; } List nl; if (list instanceof ArrayList) { nl = new ArrayList(list.size()); } else if (list instanceof LinkedList) { nl = new LinkedList(); } else { throw new RuntimeException("list type not implemented"); } for (C c : list) { D n = f.eval(c); nl.add(n); } return nl; } /** * Tuple from lists. * @param A list of lists. * @return new list with tuples (a_1,...,an) with ai in Ai, * i=0,...,length(A)-1. */ public static List> tupleFromList(List> A) { if (A == null) { return null; } List> T = new ArrayList>(A.size()); if (A.size() == 0) { return T; } if (A.size() == 1) { List Ap = A.get(0); for (C a : Ap) { List Tp = new ArrayList(1); Tp.add(a); T.add(Tp); } return T; } List> Ap = new ArrayList>(A); List f = Ap.remove(0); List> Tp = tupleFromList(Ap); //System.out.println("Tp = " + Tp); for (C a : f) { for (List tp : Tp) { List ts = new ArrayList(); ts.add(a); ts.addAll(tp); T.add(ts); } } return T; } } jas-2.5/src/edu/jas/util/SocketChannel.java0000644000175000017500000000423211236363510021026 0ustar giovannigiovanni/* * $Id: SocketChannel.java 2771 2009-08-05 20:10:49Z kredel $ */ //package edu.unima.ky.parallel; package edu.jas.util; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.net.Socket; /** * SocketChannel provides a communication channel for Java objects using TCP/IP * sockets. Refactored for java.util.concurrent. * @author Akitoshi Yoshida * @author Heinz Kredel. */ public class SocketChannel { /* * Input stream from the socket. */ private final ObjectInputStream in; /* * Output stream to the socket. */ private final ObjectOutputStream out; /* * Underlying socket. */ private final Socket soc; /** * Constructs a socket channel on the given socket s. * @param s A socket object. */ public SocketChannel(Socket s) throws IOException { soc = s; out = new ObjectOutputStream(s.getOutputStream()); out.flush(); in = new ObjectInputStream(s.getInputStream()); } /** * Get the Socket */ public Socket getSocket() { return soc; } /** * Sends an object */ public void send(Object v) throws IOException { synchronized (out) { out.writeObject(v); out.flush(); } } /** * Receives an object */ public Object receive() throws IOException, ClassNotFoundException { Object v = null; synchronized (in) { v = in.readObject(); } return v; } /** * Closes the channel. */ public void close() { if (in != null) { try { in.close(); } catch (IOException e) { } } if (out != null) { try { out.close(); } catch (IOException e) { } } if (soc != null) { try { soc.close(); } catch (IOException e) { } } } /** * to string */ @Override public String toString() { return "socketChannel(" + soc + ")"; } } jas-2.5/src/edu/jas/util/ArrayUtil.java0000644000175000017500000000204611607051076020225 0ustar giovannigiovanni/* * $Id: ArrayUtil.java 3681 2011-07-12 13:55:10Z kredel $ */ package edu.jas.util; //import org.apache.log4j.Logger; /** * Array utilities. * For example copyOf from Java 6. * Note: unused at the moment since it is not working in Java 5. * @author Heinz Kredel */ public class ArrayUtil { //private static final Logger logger = Logger.getLogger(ArrayUtil.class); // private static boolean debug = logger.isDebugEnabled(); /** * Copy the specified array. * @param original array. * @param newLength new array length. * @return copy of original. */ public static T[] copyOf(T[] original, int newLength) { T[] copy = (T[]) new Object[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; } /** * Copy the specified array. * @param original array. * @return copy of original. */ public static T[] copyOf(T[] original) { return (T[]) copyOf(original,original.length); } } jas-2.5/src/edu/jas/util/KsubSet.java0000644000175000017500000001342012004043370017655 0ustar giovannigiovanni/* * $Id: KsubSet.java 4052 2012-07-25 19:20:25Z kredel $ */ package edu.jas.util; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; /** * K-Subset with iterator. * @author Heinz Kredel */ public class KsubSet implements Iterable> { /** * data structure. */ public final List set; // Iterable also ok public final int k; /** * KsubSet constructor. * @param set generating set. * @param k size of subsets. */ public KsubSet(List set, int k) { if (set == null) { throw new IllegalArgumentException("null set not allowed"); } if (k < 0 || k > set.size()) { throw new IllegalArgumentException("k out of range"); } this.set = set; this.k = k; } /** * Get an iterator over subsets. * @return an iterator. */ public Iterator> iterator() { if (k == 0) { return new ZeroSubSetIterator(set); } if (k == 1) { return new OneSubSetIterator(set); } return new KsubSetIterator(set, k); } } /** * Power set iterator. * @author Heinz Kredel */ class KsubSetIterator implements Iterator> { /** * data structure. */ public final List set; public final int k; final List rest; private E current; private Iterator> recIter; private final Iterator iter; /** * KsubSetIterator constructor. * @param set generating set. * @param k subset size. */ public KsubSetIterator(List set, int k) { if (set == null || set.size() == 0) { throw new IllegalArgumentException("null or empty set not allowed"); } if (k < 2 || k > set.size()) { throw new IllegalArgumentException("k out of range"); } this.set = set; this.k = k; iter = this.set.iterator(); current = iter.next(); //System.out.println("current = " + current); rest = new LinkedList(this.set); rest.remove(0); //System.out.println("rest = " + rest); if (k == 2) { recIter = new OneSubSetIterator(rest); } else { recIter = new KsubSetIterator(rest, k - 1); } } /** * Test for availability of a next subset. * @return true if the iteration has more subsets, else false. */ public boolean hasNext() { return recIter.hasNext() || (iter.hasNext() && rest.size() >= k); } /** * Get next subset. * @return next subset. */ public List next() { if (recIter.hasNext()) { List next = new LinkedList(recIter.next()); next.add(0, current); return next; } if (iter.hasNext()) { current = iter.next(); //System.out.println("current = " + current); rest.remove(0); //System.out.println("rest = " + rest); if (rest.size() < k - 1) { throw new NoSuchElementException("invalid call of next()"); } if (k == 2) { recIter = new OneSubSetIterator(rest); } else { recIter = new KsubSetIterator(rest, k - 1); } return this.next(); // retry } throw new NoSuchElementException("invalid call of next()"); } /** * Remove the last subset returned from underlying set if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove subsets"); } } /** * One-subset iterator. * @author Heinz Kredel */ class OneSubSetIterator implements Iterator> { /** * data structure. */ public final List set; private Iterator iter; /** * OneSubSetIterator constructor. * @param set generating set. */ public OneSubSetIterator(List set) { this.set = set; if (set == null || set.size() == 0) { iter = null; return; } iter = this.set.iterator(); } /** * Test for availability of a next subset. * @return true if the iteration has more subsets, else false. */ public boolean hasNext() { if (iter == null) { return false; } return iter.hasNext(); } /** * Get next subset. * @return next subset. */ public List next() { List next = new LinkedList(); next.add(iter.next()); return next; } /** * Remove the last subset returned from underlying set if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove subsets"); } } /** * Zero-subset iterator. * @author Heinz Kredel */ class ZeroSubSetIterator implements Iterator> { /** * data structure. */ private boolean hasNext; /** * ZeroSubSetIterator constructor. * @param set generating set (ignored). */ public ZeroSubSetIterator(List set) { hasNext = true; } /** * Test for availability of a next subset. * @return true if the iteration has more subsets, else false. */ public boolean hasNext() { return hasNext; } /** * Get next subset. * @return next subset. */ public List next() { List next = new LinkedList(); hasNext = false; return next; } /** * Remove the last subset returned from underlying set if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove subsets"); } } jas-2.5/src/edu/jas/integrate/0000755000175000017500000000000012140140256016441 5ustar giovannigiovannijas-2.5/src/edu/jas/integrate/Examples.java0000644000175000017500000002123411460610034021064 0ustar giovannigiovanni/* * $Id: Examples.java 3356 2010-10-23 16:41:01Z kredel $ */ package edu.jas.integrate; import java.util.List; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; /** * Examples related to elementary integration. * * @author Axel Kramer * @author Heinz Kredel */ public class Examples { /** * Main program. * * @param args */ public static void main(String[] args) { example1(); example2(); example3(); } /** * Example rationals. */ public static void example1() { BigRational br = new BigRational(0); String[] vars = new String[] { "x" }; GenPolynomialRing fac; fac = new GenPolynomialRing(br, vars.length, new TermOrder(TermOrder.INVLEX), vars); ElementaryIntegration eIntegrator = new ElementaryIntegration(br); GenPolynomial a = fac.parse("x^7 - 24 x^4 - 4 x^2 + 8 x - 8"); System.out.println("A: " + a.toString()); GenPolynomial d = fac.parse("x^8 + 6 x^6 + 12 x^4 + 8 x^2"); System.out.println("D: " + d.toString()); GenPolynomial gcd = a.gcd(d); System.out.println("GCD: " + gcd.toString()); List>[] ret = eIntegrator.integrateHermite(a, d); System.out.println("Result: " + ret[0] + " , " + ret[1]); System.out.println("-----"); a = fac.parse("10 x^2 - 63 x + 29"); System.out.println("A: " + a.toString()); d = fac.parse("x^3 - 11 x^2 + 40 x -48"); System.out.println("D: " + d.toString()); gcd = a.gcd(d); System.out.println("GCD: " + gcd.toString()); ret = eIntegrator.integrateHermite(a, d); System.out.println("Result: " + ret[0] + " , " + ret[1]); System.out.println("-----"); a = fac.parse("x+3"); System.out.println("A: " + a.toString()); d = fac.parse("x^2 - 3 x - 40"); System.out.println("D: " + d.toString()); gcd = a.gcd(d); System.out.println("GCD: " + gcd.toString()); ret = eIntegrator.integrateHermite(a, d); System.out.println("Result: " + ret[0] + " , " + ret[1]); System.out.println("-----"); a = fac.parse("10 x^2+12 x + 20"); System.out.println("A: " + a.toString()); d = fac.parse("x^3 - 8"); System.out.println("D: " + d.toString()); gcd = a.gcd(d); System.out.println("GCD: " + gcd.toString()); ret = eIntegrator.integrateHermite(a, d); System.out.println("Result: " + ret[0] + " , " + ret[1]); System.out.println("------------------------------------------------------\n"); ComputerThreads.terminate(); } /** * Example rational plus logarithm. */ public static void example2() { BigRational br = new BigRational(0); String[] vars = new String[] { "x" }; GenPolynomialRing fac; fac = new GenPolynomialRing(br, vars.length, new TermOrder(TermOrder.INVLEX), vars); ElementaryIntegration eIntegrator = new ElementaryIntegration(br); GenPolynomial a = fac.parse("x^7 - 24 x^4 - 4 x^2 + 8 x - 8"); System.out.println("A: " + a.toString()); GenPolynomial d = fac.parse("x^8 + 6 x^6 + 12 x^4 + 8 x^2"); System.out.println("D: " + d.toString()); GenPolynomial gcd = a.gcd(d); System.out.println("GCD: " + gcd.toString()); Integral ret = eIntegrator.integrate(a, d); System.out.println("Result: " + ret); System.out.println("-----"); a = fac.parse("10 x^2 - 63 x + 29"); System.out.println("A: " + a.toString()); d = fac.parse("x^3 - 11 x^2 + 40 x -48"); System.out.println("D: " + d.toString()); gcd = a.gcd(d); System.out.println("GCD: " + gcd.toString()); ret = eIntegrator.integrate(a, d); System.out.println("Result: " + ret); System.out.println("-----"); a = fac.parse("x+3"); System.out.println("A: " + a.toString()); d = fac.parse("x^2 - 3 x - 40"); System.out.println("D: " + d.toString()); gcd = a.gcd(d); System.out.println("GCD: " + gcd.toString()); ret = eIntegrator.integrate(a, d); System.out.println("Result: " + ret); System.out.println("-----"); a = fac.parse("10 x^2+12 x + 20"); System.out.println("A: " + a.toString()); d = fac.parse("x^3 - 8"); System.out.println("D: " + d.toString()); gcd = a.gcd(d); System.out.println("GCD: " + gcd.toString()); ret = eIntegrator.integrate(a, d); System.out.println("Result: " + ret); System.out.println("-----"); a = fac.parse("1"); System.out.println("A: " + a.toString()); d = fac.parse("(x**5 + x - 7)"); System.out.println("D: " + d.toString()); gcd = a.gcd(d); System.out.println("GCD: " + gcd.toString()); ret = eIntegrator.integrate(a, d); System.out.println("Result: " + ret); System.out.println("-----"); a = fac.parse("1"); d = fac.parse("(x**5 + x - 7)"); a = a.sum(d); System.out.println("A: " + a.toString()); System.out.println("D: " + d.toString()); gcd = a.gcd(d); System.out.println("GCD: " + gcd.toString()); ret = eIntegrator.integrate(a, d); System.out.println("Result: " + ret); System.out.println("-----"); ComputerThreads.terminate(); } /** * Example quotients with rational plus logarithm. */ public static void example3() { BigRational br = new BigRational(0); String[] vars = new String[] { "x" }; GenPolynomialRing fac; fac = new GenPolynomialRing(br, vars.length, new TermOrder(TermOrder.INVLEX), vars); QuotientRing qfac = new QuotientRing(fac); ElementaryIntegration eIntegrator = new ElementaryIntegration(br); GenPolynomial a = fac.parse("x^7 - 24 x^4 - 4 x^2 + 8 x - 8"); GenPolynomial d = fac.parse("x^8 + 6 x^6 + 12 x^4 + 8 x^2"); Quotient q = new Quotient(qfac, a, d); System.out.println("q = " + q); QuotIntegral ret = eIntegrator.integrate(q); System.out.println("Result: " + ret); System.out.println("-----"); a = fac.parse("10 x^2 - 63 x + 29"); d = fac.parse("x^3 - 11 x^2 + 40 x -48"); q = new Quotient(qfac, a, d); System.out.println("q = " + q); ret = eIntegrator.integrate(q); System.out.println("Result: " + ret); System.out.println("-----"); a = fac.parse("x+3"); d = fac.parse("x^2 - 3 x - 40"); q = new Quotient(qfac, a, d); System.out.println("q = " + q); ret = eIntegrator.integrate(q); System.out.println("Result: " + ret); System.out.println("-----"); a = fac.parse("10 x^2+12 x + 20"); d = fac.parse("x^3 - 8"); q = new Quotient(qfac, a, d); System.out.println("q = " + q); ret = eIntegrator.integrate(q); System.out.println("Result: " + ret); System.out.println("-----"); a = fac.parse("1"); d = fac.parse("(x**5 + x - 7)"); q = new Quotient(qfac, a, d); System.out.println("q = " + q); ret = eIntegrator.integrate(q); System.out.println("Result: " + ret); System.out.println("-----"); a = fac.parse("1"); d = fac.parse("(x**5 + x - 7)"); a = a.sum(d); q = new Quotient(qfac, a, d); System.out.println("q = " + q); ret = eIntegrator.integrate(q); System.out.println("Result: " + ret); System.out.println("-----"); Quotient qi = qfac.random(7); //qi = qi.sum( qfac.random(5) ); q = eIntegrator.deriviative(qi); System.out.println("qi = " + qi); System.out.println("q = " + q); ret = eIntegrator.integrate(q); System.out.println("Result: " + ret); boolean t = eIntegrator.isIntegral(ret); System.out.println("isIntegral = " + t); System.out.println("-----"); ComputerThreads.terminate(); } } jas-2.5/src/edu/jas/integrate/ElementaryIntegration.java0000644000175000017500000004774212014234362023635 0ustar giovannigiovanni/* * $Id: ElementaryIntegration.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.integrate; import java.util.ArrayList; import java.util.List; import java.util.SortedMap; import org.apache.log4j.Logger; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; import edu.jas.ufd.FactorAbstract; import edu.jas.ufd.FactorFactory; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisorAbstract; import edu.jas.ufd.GreatestCommonDivisorSubres; import edu.jas.ufd.PolyUfdUtil; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; import edu.jas.ufd.SquarefreeAbstract; import edu.jas.ufd.SquarefreeFactory; /** * Methods related to elementary integration. In particular there are methods * for Hermite reduction and Rothstein-Trager integration of the logarithmic * part. * * @author Axel Kramer * @author Heinz Kredel * @param coefficient type */ public class ElementaryIntegration> { private static final Logger logger = Logger.getLogger(ElementaryIntegration.class); private final boolean debug = logger.isDebugEnabled(); /** * Engine for factorization. */ public final FactorAbstract irr; /** * Engine for squarefree decomposition. */ public final SquarefreeAbstract sqf; /** * Engine for greatest common divisors. */ public final GreatestCommonDivisorAbstract ufd; /** * Constructor. */ public ElementaryIntegration(RingFactory br) { ufd = GCDFactory. getProxy(br); sqf = SquarefreeFactory. getImplementation(br); irr = /*(FactorAbsolute)*/FactorFactory. getImplementation(br); } /** * Integration of a rational function. * * @param r rational function * @return Integral container, such that integrate(r) = sum_i(g_i) + sum_j( * an_j log(hd_j) ) */ public QuotIntegral integrate(Quotient r) { Integral integral = integrate(r.num, r.den); return new QuotIntegral(r.ring, integral); } /** * Integration of a rational function. * * @param a numerator * @param d denominator * @return Integral container, such that integrate(a/d) = sum_i(gn_i/gd_i) + * integrate(h0) + sum_j( an_j log(hd_j) ) */ public Integral integrate(GenPolynomial a, GenPolynomial d) { if (d == null || a == null || d.isZERO()) { throw new IllegalArgumentException("zero or null not allowed"); } if (a.isZERO()) { return new Integral(a, d, a); } if (d.isONE()) { GenPolynomial pi = PolyUtil. baseIntegral(a); return new Integral(a, d, pi); } GenPolynomialRing pfac = d.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomials " + pfac); } if (!pfac.coFac.isField()) { throw new IllegalArgumentException("only for field coefficients " + pfac); } GenPolynomial[] qr = PolyUtil. basePseudoQuotientRemainder(a, d); GenPolynomial p = qr[0]; GenPolynomial r = qr[1]; GenPolynomial c = ufd.gcd(r, d); if (!c.isONE()) { r = PolyUtil. basePseudoQuotientRemainder(r, c)[0]; d = PolyUtil. basePseudoQuotientRemainder(d, c)[0]; } List>[] ih = integrateHermite(r, d); List> rat = ih[0]; List> log = ih[1]; GenPolynomial pp = log.remove(0); p = p.sum(pp); GenPolynomial pi = PolyUtil. baseIntegral(p); if (debug) { logger.debug("pi = " + pi); logger.debug("rat = " + rat); logger.debug("log = " + log); } if (log.size() == 0) { return new Integral(a, d, pi, rat); } List> logi = new ArrayList>(log.size() / 2); for (int i = 0; i < log.size(); i++) { GenPolynomial ln = log.get(i++); GenPolynomial ld = log.get(i); LogIntegral pf = integrateLogPart(ln, ld); logi.add(pf); } if (debug) { logger.debug("logi = " + logi); } return new Integral(a, d, pi, rat, logi); } /** * Integration of the rational part, Hermite reduction step. * * @param a numerator * @param d denominator, gcd(a,d) == 1 * @return [ [ gn_i, gd_i ], [ h0, hn_j, hd_j ] ] such that integrate(a/d) = * sum_i(gn_i/gd_i) + integrate(h0) + sum_j( integrate(hn_j/hd_j) ) */ public List>[] integrateHermite(GenPolynomial a, GenPolynomial d) { if (d == null || d.isZERO()) { throw new IllegalArgumentException("d == null or d == 0"); } if (a == null || a.isZERO()) { throw new IllegalArgumentException("a == null or a == 0"); } // get squarefree decomposition SortedMap, Long> sfactors = sqf.squarefreeFactors(d); List> D = new ArrayList>(sfactors.keySet()); List> DP = new ArrayList>(); for (GenPolynomial f : D) { long e = sfactors.get(f); GenPolynomial dp = Power.> positivePower(f, e); DP.add(dp); } //System.out.println("D: " + D); //System.out.println("DP: " + DP); // get partial fraction decompostion List> Ai = ufd.basePartialFraction(a, DP); //System.out.println("Ai: " + Ai); List> G = new ArrayList>(); List> H = new ArrayList>(); H.add(Ai.remove(0)); // P GenPolynomialRing fac = d.ring; int i = 0; for (GenPolynomial v : D) { //System.out.println("V:" + v.toString()); GenPolynomial Ak = Ai.get(i++); //System.out.println("Ak: " + Ak.toString()); int k = sfactors.get(v).intValue(); // assert low power for (int j = k - 1; j >= 1; j--) { //System.out.println("Step(" + k + "," + j + ")"); GenPolynomial DV_dx = PolyUtil. baseDeriviative(v); GenPolynomial Aik = Ak.divide(fac.fromInteger(-j)); GenPolynomial[] BC = ufd.baseGcdDiophant(DV_dx, v, Aik); GenPolynomial b = BC[0]; GenPolynomial c = BC[1]; GenPolynomial vj = Power.> positivePower(v, j); G.add(b); // B G.add(vj); // v^j Ak = fac.fromInteger(-j).multiply(c).subtract(PolyUtil. baseDeriviative(b)); //System.out.println("B: " + b.toString()); //System.out.println("C: " + c.toString()); } //System.out.println("V:" + v.toString()); //System.out.println("Ak: " + Ak.toString()); if (!Ak.isZERO()) { H.add(Ak); // A_k H.add(v); // v } } List>[] ret = (List>[]) new List[2]; ret[0] = G; ret[1] = H; return ret; } /** * Univariate GenPolynomial integration of the logaritmic part, * Rothstein-Trager algorithm. * @param A univariate GenPolynomial, deg(A) < deg(P). * @param P univariate squarefree GenPolynomial, gcd(A,P) == 1. * @return logarithmic part container. */ public LogIntegral integrateLogPart(GenPolynomial A, GenPolynomial P) { if (P == null || P.isZERO()) { throw new IllegalArgumentException(" P == null or P == 0"); } if (A == null || A.isZERO()) { throw new IllegalArgumentException(" A == null or A == 0"); } //System.out.println("\nP_base_algeb_part = " + P); GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomials " + pfac); } if (!pfac.coFac.isField()) { throw new IllegalArgumentException("only for field coefficients " + pfac); } List cfactors = new ArrayList(); List> cdenom = new ArrayList>(); List> afactors = new ArrayList>(); List>> adenom = new ArrayList>>(); // P linear if (P.degree(0) <= 1) { cfactors.add(A.leadingBaseCoefficient()); cdenom.add(P); return new LogIntegral(A, P, cfactors, cdenom, afactors, adenom); } List> Pfac = irr.baseFactorsSquarefree(P); //System.out.println("\nPfac = " + Pfac); List> Afac = ufd.basePartialFraction(A, Pfac); GenPolynomial A0 = Afac.remove(0); if (!A0.isZERO()) { throw new RuntimeException(" A0 != 0: deg(A)>= deg(P)"); } // algebraic and linear factors int i = 0; for (GenPolynomial pi : Pfac) { GenPolynomial ai = Afac.get(i++); if (pi.degree(0) <= 1) { cfactors.add(ai.leadingBaseCoefficient()); cdenom.add(pi); continue; } LogIntegral pf = integrateLogPartIrreducible(ai, pi); cfactors.addAll(pf.cfactors); cdenom.addAll(pf.cdenom); afactors.addAll(pf.afactors); adenom.addAll(pf.adenom); } return new LogIntegral(A, P, cfactors, cdenom, afactors, adenom); } /** * Univariate GenPolynomial integration of the logaritmic part, * Rothstein-Trager algorithm. * @param A univariate GenPolynomial, deg(A) < deg(P). * @param P univariate irreducible GenPolynomial. // gcd(A,P) == 1 automatic * @return logarithmic part container. */ public LogIntegral integrateLogPartIrreducible(GenPolynomial A, GenPolynomial P) { if (P == null || P.isZERO()) { throw new IllegalArgumentException("P == null or P == 0"); } //System.out.println("\nP_base_algeb_part = " + P); GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomials " + pfac); } if (!pfac.coFac.isField()) { throw new IllegalArgumentException("only for field coefficients " + pfac); } List cfactors = new ArrayList(); List> cdenom = new ArrayList>(); List> afactors = new ArrayList>(); List>> adenom = new ArrayList>>(); // P linear if (P.degree(0) <= 1) { cfactors.add(A.leadingBaseCoefficient()); cdenom.add(P); return new LogIntegral(A, P, cfactors, cdenom, afactors, adenom); } // deriviative GenPolynomial Pp = PolyUtil. baseDeriviative(P); //no: Pp = Pp.monic(); //System.out.println("\nP = " + P); //System.out.println("Pp = " + Pp); // Q[t] String[] vars = new String[] { "t" }; GenPolynomialRing cfac = new GenPolynomialRing(pfac.coFac, 1, pfac.tord, vars); GenPolynomial t = cfac.univariate(0); //System.out.println("t = " + t); // Q[x][t] GenPolynomialRing> rfac = new GenPolynomialRing>(pfac, cfac); // sic //System.out.println("rfac = " + rfac.toScript()); // transform polynomials to bi-variate polynomial GenPolynomial> Ac = PolyUfdUtil. introduceLowerVariable(rfac, A); //System.out.println("Ac = " + Ac); GenPolynomial> Pc = PolyUfdUtil. introduceLowerVariable(rfac, P); //System.out.println("Pc = " + Pc); GenPolynomial> Pcp = PolyUfdUtil. introduceLowerVariable(rfac, Pp); //System.out.println("Pcp = " + Pcp); // Q[t][x] GenPolynomialRing> rfac1 = Pc.ring; //System.out.println("rfac1 = " + rfac1.toScript()); // A - t P' GenPolynomial> tc = rfac1.getONE().multiply(t); //System.out.println("tc = " + tc); GenPolynomial> At = Ac.subtract(tc.multiply(Pcp)); //System.out.println("At = " + At); GreatestCommonDivisorSubres engine = new GreatestCommonDivisorSubres(); // = GCDFactory.getImplementation( cfac.coFac ); GreatestCommonDivisorAbstract> aengine = null; GenPolynomial> Rc = engine.recursiveUnivariateResultant(Pc, At); //System.out.println("Rc = " + Rc); GenPolynomial res = Rc.leadingBaseCoefficient(); //no: res = res.monic(); //System.out.println("\nres = " + res); SortedMap, Long> resfac = irr.baseFactors(res); //System.out.println("resfac = " + resfac + "\n"); for (GenPolynomial r : resfac.keySet()) { //System.out.println("\nr(t) = " + r); if (r.isConstant()) { continue; } //vars = new String[] { "z_" + Math.abs(r.hashCode() % 1000) }; vars = pfac.newVars("z_"); pfac = pfac.copy(); String[] unused = pfac.setVars(vars); r = pfac.copy(r); // hack to exchange the variables //System.out.println("r(z_) = " + r); AlgebraicNumberRing afac = new AlgebraicNumberRing(r, true); // since irreducible logger.debug("afac = " + afac.toScript()); AlgebraicNumber a = afac.getGenerator(); //no: a = a.negate(); //System.out.println("a = " + a); // K(alpha)[x] GenPolynomialRing> pafac = new GenPolynomialRing>(afac, Pc.ring); //System.out.println("pafac = " + pafac.toScript()); // convert to K(alpha)[x] GenPolynomial> Pa = PolyUtil. convertToAlgebraicCoefficients(pafac, P); //System.out.println("Pa = " + Pa); GenPolynomial> Pap = PolyUtil. convertToAlgebraicCoefficients(pafac, Pp); //System.out.println("Pap = " + Pap); GenPolynomial> Aa = PolyUtil. convertToAlgebraicCoefficients(pafac, A); //System.out.println("Aa = " + Aa); // A - a P' GenPolynomial> Ap = Aa.subtract(Pap.multiply(a)); //System.out.println("Ap = " + Ap); if (aengine == null) { aengine = GCDFactory.> getImplementation(afac); } GenPolynomial> Ga = aengine.baseGcd(Pa, Ap); //System.out.println("Ga = " + Ga); if (Ga.isConstant()) { //System.out.println("warning constant gcd ignored"); continue; } afactors.add(a); adenom.add(Ga); // special quadratic case if (P.degree(0) == 2 && Ga.degree(0) == 1) { GenPolynomial>[] qra = PolyUtil .> basePseudoQuotientRemainder(Pa, Ga); GenPolynomial> Qa = qra[0]; if (!qra[1].isZERO()) { throw new ArithmeticException("remainder not zero"); } //System.out.println("Qa = " + Qa); afactors.add(a.negate()); adenom.add(Qa); } // todo: eventually implement special cases deg = 3, 4 } return new LogIntegral(A, P, cfactors, cdenom, afactors, adenom); } /** * Derivation of a univariate rational function. * * @param r rational function * @return dr/dx */ public Quotient deriviative(Quotient r) { GenPolynomial num = r.num; GenPolynomial den = r.den; GenPolynomial nump = PolyUtil. baseDeriviative(num); if (den.isONE()) { return new Quotient(r.ring, nump, den); } GenPolynomial denp = PolyUtil. baseDeriviative(den); GenPolynomial n = den.multiply(nump).subtract(num.multiply(denp)); GenPolynomial d = den.multiply(den); Quotient der = new Quotient(r.ring, n, d); return der; } /** * Test of integration of a rational function. * * @param ri integral * @return true, if ri is an integral, else false. */ public boolean isIntegral(QuotIntegral ri) { Quotient r = ri.quot; QuotientRing qr = r.ring; Quotient i = r.ring.getZERO(); for (Quotient q : ri.rational) { Quotient qd = deriviative(q); i = i.sum(qd); } if (ri.logarithm.size() == 0) { return r.equals(i); } for (LogIntegral li : ri.logarithm) { Quotient q = new Quotient(qr, li.num, li.den); i = i.sum(q); } boolean t = r.equals(i); if (!t) { return false; } for (LogIntegral li : ri.logarithm) { t = isIntegral(li); if (!t) { return false; } } return true; } /** * Test of integration of the logarithmic part of a rational function. * * @param rl logarithmic part of an integral * @return true, if rl is an integral, else false. */ public boolean isIntegral(LogIntegral rl) { QuotientRing qr = new QuotientRing(rl.den.ring); Quotient r = new Quotient(qr, rl.num, rl.den); Quotient i = qr.getZERO(); int j = 0; for (GenPolynomial d : rl.cdenom) { GenPolynomial dp = PolyUtil. baseDeriviative(d); dp = dp.multiply(rl.cfactors.get(j++)); Quotient f = new Quotient(qr, dp, d); i = i.sum(f); } if (rl.afactors.size() == 0) { return r.equals(i); } r = r.subtract(i); QuotientRing> aqr = new QuotientRing>(rl.adenom.get(0).ring); Quotient> ai = aqr.getZERO(); GenPolynomial> aqn = PolyUtil. convertToAlgebraicCoefficients(aqr.ring, r.num); GenPolynomial> aqd = PolyUtil. convertToAlgebraicCoefficients(aqr.ring, r.den); Quotient> ar = new Quotient>(aqr, aqn, aqd); j = 0; for (GenPolynomial> d : rl.adenom) { GenPolynomial> dp = PolyUtil.> baseDeriviative(d); dp = dp.multiply(rl.afactors.get(j++)); Quotient> f = new Quotient>(aqr, dp, d); ai = ai.sum(f); } boolean t = ar.equals(ai); if (t) { return true; } logger.warn("log integral not verified"); //System.out.println("r = " + r); //System.out.println("afactors = " + rl.afactors); //System.out.println("adenom = " + rl.adenom); //System.out.println("ar = " + ar); //System.out.println("ai = " + ai); return true; } } jas-2.5/src/edu/jas/integrate/package.html0000644000175000017500000000154311304043476020734 0ustar giovannigiovanni Elementary Integration package

Elementary Integration package.

This package contains classes for elementary integration of (univariate) polynomials and rational functions.

The implementation follows Bronstein Symbolic Integration I - Transcendental Functions.


Heinz Kredel

Last modified: Fri Nov 27 22:23:52 CET 2009

$Id: package.html 2885 2009-11-27 21:40:15Z kredel $

jas-2.5/src/edu/jas/integrate/Integral.java0000644000175000017500000001113712004021566021055 0ustar giovannigiovanni/* * $Id: Integral.java 4046 2012-07-25 16:48:54Z kredel $ */ package edu.jas.integrate; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Container for a rational function integral, polynomial version. * integral(num/den) = pol + sum_rat( rat_i/rat_{i+1} ) + sum_log( a_i log ( d_i * ) ) * @author Heinz Kredel * @param coefficient type */ public class Integral> implements Serializable { /** * Original numerator polynomial with coefficients from C. */ public final GenPolynomial num; /** * Original denominator polynomial with coefficients from C. */ public final GenPolynomial den; /** * Integral of the polynomial part. */ public final GenPolynomial pol; /** * Integral of the rational part. */ public final List> rational; /** * Integral of the logarithmic part. */ public final List> logarithm; /** * Constructor. * @param n numerator GenPolynomial over C. * @param d denominator GenPolynomial over C. * @param p integral of polynomial part. n/d = */ public Integral(GenPolynomial n, GenPolynomial d, GenPolynomial p) { this(n, d, p, new ArrayList>()); } /** * Constructor. * @param n numerator GenPolynomial over C. * @param d denominator GenPolynomial over C. * @param p integral of polynomial part. * @param rat list of rational integrals. n/d = */ public Integral(GenPolynomial n, GenPolynomial d, GenPolynomial p, List> rat) { this(n, d, p, rat, new ArrayList>()); } /** * Constructor. * @param n numerator GenPolynomial over C. * @param d denominator GenPolynomial over C. * @param p integral of polynomial part. * @param rat list of rational integrals. * @param log list of logarithmic part. n/d = */ public Integral(GenPolynomial n, GenPolynomial d, GenPolynomial p, List> rat, List> log) { num = n; den = d; pol = p; rational = rat; logarithm = log; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("integral( (" + num.toString()); sb.append(") / ("); sb.append(den.toString() + ") )"); sb.append(" =\n"); if (!pol.isZERO()) { sb.append(pol.toString()); } boolean first = true; if (rational.size() != 0) { if (!pol.isZERO()) { sb.append(" + "); } for (int i = 0; i < rational.size(); i++) { if (first) { first = false; } else { sb.append(" + "); } sb.append("(" + rational.get(i++) + ")/("); sb.append(rational.get(i) + ")"); } } if (logarithm.size() != 0) { if (!pol.isZERO() || rational.size() != 0) { sb.append(" + "); } first = true; for (LogIntegral pf : logarithm) { if (first) { first = false; } else { sb.append(" + "); } sb.append(pf); } sb.append("\n"); } return sb.toString(); } /** * Hash code for Integral. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = num.hashCode(); h = h * 37 + den.hashCode(); h = h * 37 + pol.hashCode(); h = h * 37 + rational.hashCode(); h = h * 37 + logarithm.hashCode(); return h; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { Integral b = null; try { b = (Integral) B; } catch (ClassCastException ignored) { } if (b == null) { return false; } return num.equals(b.num) && den.equals(b.den) && pol.equals(b.pol) && rational.equals(b.rational) && logarithm.equals(b.logarithm); } } jas-2.5/src/edu/jas/integrate/LogIntegral.java0000644000175000017500000002052211435516726021533 0ustar giovannigiovanni/* * $Id: LogIntegral.java 3295 2010-08-26 17:01:10Z kredel $ */ package edu.jas.integrate; import java.io.Serializable; import java.util.List; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Container for the logarithmic part of a rational function integral. num/den = * sum( a_i ( der(d_i) / d_i ) ) integrate(num/den) = sum( a_i log ( d_i ) ) * @author Heinz Kredel * @param coefficient type */ public class LogIntegral> implements Serializable { /** * Original numerator polynomial with coefficients from C and deg(num) < * deg(den). */ public final GenPolynomial num; /** * Original (irreducible) denominator polynomial with coefficients from C. */ public final GenPolynomial den; /** * List of numbers from C. */ public final List cfactors; /** * List of linear factors of the denominator with coefficients from C. */ public final List> cdenom; /** * List of algebraic numbers of an algebraic field extension over C. */ public final List> afactors; /** * List of factors of the denominator with coefficients from an * AlgebraicNumberRing<C>. */ public final List>> adenom; /** * Constructor. * @param n numerator GenPolynomial over C. * @param d irreducible denominator GenPolynomial over C. * @param cf list of elements a_i. * @param cd list of linear factors d_i of d. * @param af list of algebraic elements a_i. * @param ad list of irreducible factors d_i of d with algebraic * coefficients. n/d = sum( a_i ( der(d_i) / d_i ) ) */ public LogIntegral(GenPolynomial n, GenPolynomial d, List cf, List> cd, List> af, List>> ad) { num = n; den = d; cfactors = cf; cdenom = cd; afactors = af; adenom = ad; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); // sb.append("(" + num.toString() + ")"); // sb.append(" / "); // sb.append("(" + den.toString() + ")"); // sb.append(" =\n"); boolean first = true; for (int i = 0; i < cfactors.size(); i++) { C cp = cfactors.get(i); if (first) { first = false; } else { sb.append(" + "); } sb.append("(" + cp.toString() + ")"); GenPolynomial p = cdenom.get(i); sb.append(" log( " + p.toString() + ")"); } if (!first && afactors.size() > 0) { sb.append(" + "); } first = true; for (int i = 0; i < afactors.size(); i++) { if (first) { first = false; } else { sb.append(" + "); } AlgebraicNumber ap = afactors.get(i); AlgebraicNumberRing ar = ap.factory(); //sb.append(" ## over " + ap.factory() + "\n"); GenPolynomial> p = adenom.get(i); if (p.degree(0) < ar.modul.degree(0) && ar.modul.degree(0) > 2) { sb.append("sum_(" + ar.getGenerator() + " in "); sb.append("rootOf(" + ar.modul + ") ) "); } else { //sb.append("sum_("+ar+") "); } sb.append("(" + ap.toString() + ")"); sb.append(" log( " + p.toString() + ")"); } return sb.toString(); } /** * Get the String representation. * @see java.lang.Object#toString() */ //@Override public String toStringX() { StringBuffer sb = new StringBuffer(); sb.append("(" + num.toString() + ")"); sb.append(" / "); sb.append("(" + den.toString() + ")"); sb.append(" =\n"); boolean first = true; for (C cp : cfactors) { if (first) { first = false; } else { sb.append(", "); } sb.append(cp.toString()); } if (!first) { sb.append(" linear denominators: "); } first = true; for (GenPolynomial cp : cdenom) { if (first) { first = false; } else { sb.append(", "); } sb.append(cp.toString()); } if (!first) { sb.append("; "); } first = true; for (AlgebraicNumber ap : afactors) { if (first) { first = false; } else { //sb.append(", "); } sb.append(ap.toString()); sb.append(" ## over " + ap.factory() + "\n"); } if (!first) { sb.append(" denominators: "); } first = true; for (GenPolynomial> ap : adenom) { if (first) { first = false; } else { sb.append(", "); } sb.append(ap.toString()); } return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this container. * @see edu.jas.structure.ElemFactory#toScript() */ public String toScript() { // Python case StringBuffer sb = new StringBuffer(); sb.append(num.toScript()); sb.append(" / "); sb.append(den.toScript()); sb.append(" = "); boolean first = true; for (C cp : cfactors) { if (first) { first = false; } else { sb.append(", "); } sb.append(cp.toScript()); } if (!first) { sb.append(" linear denominators: "); } first = true; for (GenPolynomial cp : cdenom) { if (first) { first = false; } else { sb.append(", "); } sb.append(cp.toScript()); } if (!first) { sb.append(", "); } first = true; for (AlgebraicNumber ap : afactors) { if (first) { first = false; } else { //sb.append(", "); } sb.append(ap.toScript()); sb.append(" ## over " + ap.toScriptFactory() + "\n"); } sb.append(" denominators: "); first = true; for (GenPolynomial> ap : adenom) { if (first) { first = false; } else { sb.append(", "); } sb.append(ap.toScript()); } return sb.toString(); } /** * Hash code for this Factors. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = num.hashCode(); h = h * 37 + den.hashCode(); h = h * 37 + cfactors.hashCode(); h = h * 37 + cdenom.hashCode(); h = h * 37 + afactors.hashCode(); h = h * 37 + adenom.hashCode(); return h; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { if (!(B instanceof LogIntegral)) { return false; } LogIntegral a = null; try { a = (LogIntegral) B; } catch (ClassCastException ignored) { } if (a == null) { return false; } boolean t = num.equals(a.num) && den.equals(a.den); if (!t) { return t; } t = cfactors.equals(a.cfactors); if (!t) { return t; } t = cdenom.equals(a.cdenom); if (!t) { return t; } t = afactors.equals(a.afactors); if (!t) { return t; } t = adenom.equals(a.adenom); return t; } } jas-2.5/src/edu/jas/integrate/QuotIntegral.java0000644000175000017500000001046412004021566021730 0ustar giovannigiovanni/* * $Id: QuotIntegral.java 4046 2012-07-25 16:48:54Z kredel $ */ package edu.jas.integrate; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; /** * Container for a rational function integral, quotient version . * integral(num/den) = pol + sum_rat( rat_i/rat_{i+1} ) + sum_log( a_i log ( d_i * ) ) * @author Heinz Kredel * @param coefficient type */ public class QuotIntegral> implements Serializable { /** * Original rational function with coefficients from C. */ public final Quotient quot; /** * Integral of the polynomial and rational part. */ public final List> rational; /** * Integral of the logarithmic part. */ public final List> logarithm; /** * Constructor. * @param ri integral. */ public QuotIntegral(Integral ri) { this(new QuotientRing(ri.den.ring), ri); } /** * Constructor. * @param r rational function QuotientRing over C. * @param ri integral. */ public QuotIntegral(QuotientRing r, Integral ri) { this(new Quotient(r, ri.num, ri.den), ri.pol, ri.rational, ri.logarithm); } /** * Constructor. * @param r rational function Quotient over C. * @param p integral of polynomial part. * @param rat list of rational integrals. */ public QuotIntegral(Quotient r, GenPolynomial p, List> rat) { this(r, p, rat, new ArrayList>()); } /** * Constructor. * @param r rational function Quotient over C. * @param p integral of polynomial part. * @param rat list of rational integrals. * @param log list of logarithmic part. */ public QuotIntegral(Quotient r, GenPolynomial p, List> rat, List> log) { quot = r; QuotientRing qr = r.ring; rational = new ArrayList>(); if (!p.isZERO()) { rational.add(new Quotient(qr, p)); } for (int i = 0; i < rat.size(); i++) { GenPolynomial rn = rat.get(i++); GenPolynomial rd = rat.get(i); rational.add(new Quotient(qr, rn, rd)); } logarithm = log; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("integral( " + quot.toString() + " )"); sb.append(" =\n"); boolean first = true; if (rational.size() != 0) { for (int i = 0; i < rational.size(); i++) { if (first) { first = false; } else { sb.append(" + "); } sb.append("(" + rational.get(i) + ")"); } } if (logarithm.size() != 0) { if (rational.size() != 0) { sb.append(" + "); } first = true; for (LogIntegral pf : logarithm) { if (first) { first = false; } else { sb.append(" + "); } sb.append(pf); } sb.append("\n"); } return sb.toString(); } /** * Hash code for QuotIntegral. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = quot.hashCode(); h = h * 37 + rational.hashCode(); h = h * 37 + logarithm.hashCode(); return h; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { QuotIntegral b = null; try { b = (QuotIntegral) B; } catch (ClassCastException ignored) { } if (b == null) { return false; } return quot.equals(b.quot) && rational.equals(b.rational) && logarithm.equals(b.logarithm); } } jas-2.5/src/edu/jas/gbmod/0000755000175000017500000000000012140140254015545 5ustar giovannigiovannijas-2.5/src/edu/jas/gbmod/SolvableSyzygyAbstract.java0000644000175000017500000007615112137430660023125 0ustar giovannigiovanni/* * $Id: SolvableSyzygyAbstract.java 4394 2013-04-29 08:39:13Z kredel $ */ package edu.jas.gbmod; import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.gb.Reduction; import edu.jas.gb.ReductionSeq; import edu.jas.gb.SolvableExtendedGB; import edu.jas.gb.SolvableGroebnerBase; import edu.jas.gb.SolvableGroebnerBaseSeq; import edu.jas.gb.SolvableReduction; import edu.jas.gb.SolvableReductionSeq; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingElem; import edu.jas.vector.BasicLinAlg; /** * Syzygy class for solvable polynomials. Implements Syzygy computations and * tests. * @param coefficient type * @author Heinz Kredel */ public class SolvableSyzygyAbstract> implements SolvableSyzygy { private static final Logger logger = Logger.getLogger(SolvableSyzygyAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Solvable reduction engine. */ protected SolvableReduction sred; /** * Reduction engine. */ protected Reduction red; /** * Linear algebra engine. */ protected BasicLinAlg> blas; /** * Constructor. */ public SolvableSyzygyAbstract() { red = new ReductionSeq(); sred = new SolvableReductionSeq(); blas = new BasicLinAlg>(); } /** * Left syzygy for left Groebner base. * @param F a Groebner base. * @return leftSyz(F), a basis for the left module of syzygies for F. */ public List>> leftZeroRelations(List> F) { return leftZeroRelations(0, F); } /** * Left syzygy for left Groebner base. * @param modv number of module variables. * @param F a Groebner base. * @return leftSyz(F), a basis for the left module of syzygies for F. */ public List>> leftZeroRelations(int modv, List> F) { List>> Z = new ArrayList>>(); ArrayList> S = new ArrayList>(F.size()); for (int i = 0; i < F.size(); i++) { S.add(null); } GenSolvablePolynomial pi, pj, s, h, zero; zero = null; for (int i = 0; i < F.size(); i++) { pi = F.get(i); if (pi != null && zero == null) { zero = pi.ring.getZERO(); } for (int j = i + 1; j < F.size(); j++) { pj = F.get(j); //logger.info("p"+i+", p"+j+" = " + pi + ", " +pj); if (!red.moduleCriterion(modv, pi, pj)) { continue; } // if ( ! red.criterion4( pi, pj ) ) continue; ArrayList> row = (ArrayList>) S.clone(); s = sred.leftSPolynomial(row, i, pi, j, pj); //logger.info("row = " + row); if (s.isZERO()) { Z.add(row); continue; } h = sred.leftNormalform(row, F, s); if (!h.isZERO()) { throw new ArithmeticException("Syzygy no leftGB"); } if (logger.isDebugEnabled()) { logger.info("row = " + row); } Z.add(row); } } // set null to zero for (List> vr : Z) { for (int j = 0; j < vr.size(); j++) { if (vr.get(j) == null) { vr.set(j, zero); } } } return Z; } /** * Left syzygy for left module Groebner base. * @param M a Groebner base. * @return leftSyz(M), a basis for the left module of syzygies for M. */ @SuppressWarnings("unchecked") public ModuleList leftZeroRelations(ModuleList M) { ModuleList N = null; if (M == null || M.list == null) { return N; } if (M.rows == 0 || M.cols == 0) { return N; } GenSolvablePolynomial zero = (GenSolvablePolynomial) M.ring.getZERO(); //logger.info("zero = " + zero); //ModuleList Np = null; PolynomialList F = M.getPolynomialList(); int modv = M.cols; // > 0 logger.info("modv = " + modv); List>> G = leftZeroRelations(modv, F.castToSolvableList()); //if (G == null) { // return N; //} List>> Z = new ArrayList>>(); for (int i = 0; i < G.size(); i++) { List> Gi = G.get(i); List> Zi = new ArrayList>(); // System.out.println("\nG("+i+") = " + G.get(i)); for (int j = 0; j < Gi.size(); j++) { //System.out.println("\nG("+i+","+j+") = " + Gi.get(j)); GenSolvablePolynomial p = Gi.get(j); if (p != null) { Map> r = p.contract(M.ring); //System.out.println("map("+i+","+j+") = " + r + ", size = " + r.size() ); if (r.size() == 0) { Zi.add(zero); } else if (r.size() == 1) { GenSolvablePolynomial vi = (GenSolvablePolynomial) (r.values().toArray())[0]; Zi.add(vi); } else { // will not happen throw new RuntimeException("Map.size() > 1 = " + r.size()); } } } //System.out.println("\nZ("+i+") = " + Zi); Z.add(Zi); } N = new ModuleList((GenSolvablePolynomialRing) M.ring, Z); //System.out.println("\n\nN = " + N); return N; } /** * Test if left syzygy. * @param Z list of sysygies. * @param F a polynomial list. * @return true, if Z is a list of left syzygies for F, else false. */ public boolean isLeftZeroRelation(List>> Z, List> F) { List> Fp = PolynomialList. castToList(F); for (List> row : Z) { // p has wrong type: GenPolynomial p = blas.scalarProduct(PolynomialList. castToList(row), Fp); if (p == null) { continue; } if (!p.isZERO()) { logger.info("is not ZeroRelation = " + p); return false; } } return true; } /** * Test if right syzygy. * @param Z list of sysygies. * @param F a polynomial list. * @return true, if Z is a list of right syzygies for F, else false. */ public boolean isRightZeroRelation(List>> Z, List> F) { List> Fp = PolynomialList. castToList(F); for (List> row : Z) { List> yrow = PolynomialList. castToList(row); // p has wrong type: GenPolynomial p = blas.scalarProduct(Fp, yrow); // param order if (p == null) { continue; } if (!p.isZERO()) { logger.info("is not ZeroRelation = " + p); return false; } } return true; } /** * Test if left sysygy of modules * @param Z list of sysygies. * @param F a module list. * @return true, if Z is a list of left syzygies for F, else false. */ public boolean isLeftZeroRelation(ModuleList Z, ModuleList F) { if (Z == null || Z.list == null) { return true; } for (List> row : Z.list) { List> zr = blas.leftScalarProduct(row, F.list); if (!blas.isZero(zr)) { logger.info("is not ZeroRelation (" + zr.size() + ") = " + zr); return false; } } return true; } /** * Test if right sysygy of modules * @param Z list of sysygies. * @param F a module list. * @return true, if Z is a list of right syzygies for F, else false. */ public boolean isRightZeroRelation(ModuleList Z, ModuleList F) { if (Z == null || Z.list == null) { return true; } for (List> row : Z.list) { List> zr = blas.rightScalarProduct(row, F.list); //List> zr = blas.scalarProduct(row,F.list); if (!blas.isZero(zr)) { logger.info("is not ZeroRelation (" + zr.size() + ") = " + zr); return false; } } return true; } /** * Resolution of a module. Only with direct GBs. * @param M a module list of a Groebner basis. * @return a resolution of M. */ public List> resolution(ModuleList M) { List> R = new ArrayList>(); ModuleList MM = M; ModuleList GM; ModuleList Z; ModSolvableGroebnerBase msbb = new ModSolvableGroebnerBaseAbstract(); while (true) { GM = msbb.leftGB(MM); Z = leftZeroRelations(GM); R.add(new SolvResPart(MM, GM, Z)); if (Z == null || Z.list == null || Z.list.size() == 0) { break; } MM = Z; } return R; } /** * Resolution of a polynomial list. Only with direct GBs. * @param F a polynomial list of a Groebner basis. * @return a resolution of F. */ @SuppressWarnings("unchecked") public List // |SolvResPolPart> resolution(PolynomialList F) { List>> Z; ModuleList Zm; List> G; PolynomialList Gl; SolvableGroebnerBase sbb = new SolvableGroebnerBaseSeq(); G = sbb.leftGB(F.castToSolvableList()); Z = leftZeroRelations(G); Gl = new PolynomialList((GenSolvablePolynomialRing) F.ring, G); Zm = new ModuleList((GenSolvablePolynomialRing) F.ring, Z); List R = resolution(Zm); R.add(0, new SolvResPolPart(F, Gl, Zm)); return R; } /** * Resolution of a module. * @param M a module list of an arbitrary basis. * @return a resolution of M. */ public List> resolutionArbitrary(ModuleList M) { List> R = new ArrayList>(); ModuleList MM = M; ModuleList GM = null; ModuleList Z; //ModSolvableGroebnerBase msbb = new ModSolvableGroebnerBaseAbstract(); while (true) { //GM = msbb.leftGB(MM); Z = leftZeroRelationsArbitrary(MM); R.add(new SolvResPart(MM, GM, Z)); if (Z == null || Z.list == null || Z.list.size() == 0) { break; } MM = Z; } return R; } /** * Resolution of a polynomial list. * @param F a polynomial list of an arbitrary basis. * @return a resolution of F. */ @SuppressWarnings("unchecked") public List // |SolvResPolPart> resolutionArbitrary(PolynomialList F) { List>> Z; ModuleList Zm; //List> G; PolynomialList Gl = null; //SolvableGroebnerBase sbb = new SolvableGroebnerBaseSeq(); //G = sbb.leftGB( F.castToSolvableList() ); Z = leftZeroRelationsArbitrary(F.castToSolvableList()); //Gl = new PolynomialList((GenSolvablePolynomialRing)F.ring, G); Zm = new ModuleList((GenSolvablePolynomialRing) F.ring, Z); List R = resolutionArbitrary(Zm); R.add(0, new SolvResPolPart(F, Gl, Zm)); return R; } /** * Left syzygy module from arbitrary base. * @param F a solvable polynomial list. * @return syz(F), a basis for the module of left syzygies for F. */ public List>> leftZeroRelationsArbitrary(List> F) { return leftZeroRelationsArbitrary(0, F); } /** * Left syzygy module from arbitrary base. * @param modv number of module variables. * @param F a solvable polynomial list. * @return syz(F), a basis for the module of left syzygies for F. */ @SuppressWarnings("unchecked") public List>> leftZeroRelationsArbitrary(int modv, List> F) { if (F == null) { return null; //leftZeroRelations( modv, F ); } if (F.size() <= 1) { return leftZeroRelations(modv, F); } final int lenf = F.size(); SolvableGroebnerBaseSeq sgb = new SolvableGroebnerBaseSeq(); SolvableExtendedGB exgb = sgb.extLeftGB(F); if (debug) { logger.info("exgb = " + exgb); } if (!sgb.isLeftReductionMatrix(exgb)) { logger.error("is reduction matrix ? false"); } List> G = exgb.G; List>> G2F = exgb.G2F; List>> F2G = exgb.F2G; List>> sg = leftZeroRelations(modv, G); GenSolvablePolynomialRing ring = G.get(0).ring; ModuleList S = new ModuleList(ring, sg); if (debug) { logger.info("syz = " + S); } if (!isLeftZeroRelation(sg, G)) { logger.error("is syzygy ? false"); } List>> sf; sf = new ArrayList>>(sg.size()); //List> row; for (List> r : sg) { Iterator> it = r.iterator(); Iterator>> jt = G2F.iterator(); List> rf; rf = new ArrayList>(lenf); for (int m = 0; m < lenf; m++) { rf.add(ring.getZERO()); } while (it.hasNext() && jt.hasNext()) { GenSolvablePolynomial si = it.next(); List> ai = jt.next(); //System.out.println("si = " + si); //System.out.println("ai = " + ai); if (si == null || ai == null) { continue; } // pi has wrong type: List> pi = blas.scalarProduct(si, PolynomialList. castToList(ai)); //System.out.println("pi = " + pi); rf = PolynomialList. castToSolvableList(blas.vectorAdd(PolynomialList. castToList(rf), pi)); } if (it.hasNext() || jt.hasNext()) { logger.error("leftZeroRelationsArbitrary wrong sizes"); } //System.out.println("\nrf = " + rf + "\n"); sf.add(rf); } if (!isLeftZeroRelation(sf, F)) { logger.error("is partial syz sf ? false"); } List>> M; M = new ArrayList>>(lenf); for (List> r : F2G) { Iterator> it = r.iterator(); Iterator>> jt = G2F.iterator(); List> rf; rf = new ArrayList>(lenf); for (int m = 0; m < lenf; m++) { rf.add(ring.getZERO()); } while (it.hasNext() && jt.hasNext()) { GenSolvablePolynomial si = it.next(); List> ai = jt.next(); //System.out.println("si = " + si); //System.out.println("ai = " + ai); if (si == null || ai == null) { continue; } //pi has wrong type, should be: List> List> pi = blas.scalarProduct(si, PolynomialList. castToList(ai)); //System.out.println("pi = " + pi); rf = PolynomialList. castToSolvableList(blas.vectorAdd(PolynomialList. castToList(rf), pi)); } if (it.hasNext() || jt.hasNext()) { logger.error("zeroRelationsArbitrary wrong sizes"); } //System.out.println("\nMg Mf = " + rf + "\n"); M.add(rf); } //ModuleList ML = new ModuleList( ring, M ); //System.out.println("syz ML = " + ML); // debug only: //List> F2 = new ArrayList>( F.size() ); /* not true in general List> Fp = PolynomialList.castToList(F); for ( List> rr: M ) { GenSolvablePolynomial rrg = PolynomialList.castToSolvableList(blas.scalarProduct(Fp,PolynomialList.castToList(rr))); F2.add( rrg ); } PolynomialList pF = new PolynomialList( ring, F ); PolynomialList pF2 = new PolynomialList( ring, F2 ); if ( ! pF.equals( pF2 ) ) { logger.error("is FAB = F ? false"); //System.out.println("pF = " + pF.list.size()); //System.out.println("pF2 = " + pF2.list.size()); } */ int sflen = sf.size(); List>> M2; M2 = new ArrayList>>(lenf); int i = 0; for (List> ri : M) { List> r2i; r2i = new ArrayList>(ri.size()); int j = 0; for (GenSolvablePolynomial rij : ri) { GenSolvablePolynomial p = null; if (i == j) { p = (GenSolvablePolynomial) ring.getONE().subtract(rij); } else { if (rij != null) { p = (GenSolvablePolynomial) rij.negate(); } } r2i.add(p); j++; } M2.add(r2i); if (!blas.isZero(PolynomialList. castToList(r2i))) { sf.add(r2i); } i++; } ModuleList M2L = new ModuleList(ring, M2); if (debug) { logger.debug("syz M2L = " + M2L); } if (debug) { ModuleList SF = new ModuleList(ring, sf); logger.debug("syz sf = " + SF); logger.debug("#syz " + sflen + ", " + sf.size()); } if (!isLeftZeroRelation(sf, F)) { logger.error("is syz sf ? false"); } return sf; } /** * Left syzygy for arbitrary left module base. * @param M an arbitrary base. * @return leftSyz(M), a basis for the left module of syzygies for M. */ @SuppressWarnings("unchecked") public ModuleList leftZeroRelationsArbitrary(ModuleList M) { ModuleList N = null; if (M == null || M.list == null) { return N; } if (M.rows == 0 || M.cols == 0) { return N; } GenSolvablePolynomial zero = (GenSolvablePolynomial) M.ring.getZERO(); //logger.info("zero = " + zero); //ModuleList Np = null; PolynomialList F = M.getPolynomialList(); int modv = M.cols; // > 0 logger.info("modv = " + modv); List>> G = leftZeroRelationsArbitrary(modv, F.castToSolvableList()); if (G == null) { return N; } List>> Z = new ArrayList>>(); for (int i = 0; i < G.size(); i++) { List> Gi = G.get(i); List> Zi = new ArrayList>(); // System.out.println("\nG("+i+") = " + G.get(i)); for (int j = 0; j < Gi.size(); j++) { //System.out.println("\nG("+i+","+j+") = " + Gi.get(j)); GenSolvablePolynomial p = Gi.get(j); if (p != null) { Map> r = p.contract(M.ring); //System.out.println("map("+i+","+j+") = " + r + ", size = " + r.size() ); if (r.size() == 0) { Zi.add(zero); } else if (r.size() == 1) { GenSolvablePolynomial vi = (GenSolvablePolynomial) (r.values().toArray())[0]; Zi.add(vi); } else { // will not happen throw new RuntimeException("Map.size() > 1 = " + r.size()); } } } //System.out.println("\nZ("+i+") = " + Zi); Z.add(Zi); } N = new ModuleList((GenSolvablePolynomialRing) M.ring, Z); //System.out.println("\n\nN = " + N); return N; } /** * Right syzygy module from arbitrary base. * @param F a solvable polynomial list. * @return syz(F), a basis for the module of right syzygies for F. */ public List>> rightZeroRelationsArbitrary(List> F) { return rightZeroRelationsArbitrary(0, F); } /** * Right syzygy module from arbitrary base. * @param modv number of module variables. * @param F a solvable polynomial list. * @return syz(F), a basis for the module of right syzygies for F. */ @SuppressWarnings("unchecked") public List>> rightZeroRelationsArbitrary(int modv, List> F) { GenSolvablePolynomialRing ring = null; for (GenSolvablePolynomial p : F) { if (p != null) { ring = p.ring; break; } } List>> Z; if (ring == null) { // all null Z = new ArrayList>>(1); Z.add(F); return Z; } GenSolvablePolynomialRing rring = ring.reverse(true); GenSolvablePolynomial q; List> rF; rF = new ArrayList>(F.size()); for (GenSolvablePolynomial p : F) { if (p != null) { q = (GenSolvablePolynomial) p.reverse(rring); rF.add(q); } } if (logger.isInfoEnabled()) { PolynomialList pl = new PolynomialList(rring, rF); logger.info("reversed problem = " + pl); //System.out.println("reversed problem = " + pl); } List>> rZ = leftZeroRelationsArbitrary(modv, rF); if (debug) { boolean isit = isLeftZeroRelation(rZ, rF); logger.debug("isLeftZeroRelation = " + isit); } GenSolvablePolynomialRing oring = rring.reverse(true); if (debug) { logger.debug("ring == oring: " + ring.equals(oring)); } ring = oring; Z = new ArrayList>>(rZ.size()); for (List> z : rZ) { if (z == null) { continue; } List> s; s = new ArrayList>(z.size()); for (GenSolvablePolynomial p : z) { if (p != null) { q = (GenSolvablePolynomial) p.reverse(ring); s.add(q); } } Z.add(s); } return Z; } /** * Test left Ore condition. * @param a solvable polynomial * @param b solvable polynomial * @param oc = [p,q] two solvable polynomials * @return true if p*a = q*b, else false */ public boolean isLeftOreCond(GenSolvablePolynomial a, GenSolvablePolynomial b, GenSolvablePolynomial[] oc) { GenSolvablePolynomial c = oc[0].multiply(a); GenSolvablePolynomial d = oc[1].multiply(b); return c.equals(d); } /** * Test right Ore condition. * @param a solvable polynomial * @param b solvable polynomial * @param oc = [p,q] two solvable polynomials * @return true if a*p = b*q, else false */ public boolean isRightOreCond(GenSolvablePolynomial a, GenSolvablePolynomial b, GenSolvablePolynomial[] oc) { GenSolvablePolynomial c = a.multiply(oc[0]); GenSolvablePolynomial d = b.multiply(oc[1]); return c.equals(d); } /** * Left Ore condition. * Generators for the left Ore condition of two solvable polynomials. * @param a solvable polynomial * @param b solvable polynomial * @return [p,q] with p*a = q*b */ public GenSolvablePolynomial[] leftOreCond(GenSolvablePolynomial a, GenSolvablePolynomial b) { if (a == null || a.isZERO() || b == null || b.isZERO()) { throw new IllegalArgumentException("a and b must be non zero"); } GenSolvablePolynomialRing pfac = a.ring; GenSolvablePolynomial[] oc = (GenSolvablePolynomial[]) new GenSolvablePolynomial[2]; if ( a.isConstant() ) { oc[1] = pfac.getONE(); C c = a.leadingBaseCoefficient().inverse(); oc[0] = b.multiply(c); return oc; } if ( b.isConstant() ) { oc[0] = pfac.getONE(); C c = b.leadingBaseCoefficient().inverse(); oc[1] = a.multiply(c); return oc; } List> F = new ArrayList>(2); F.add(a); F.add(b); List>> Gz = leftZeroRelationsArbitrary(F); if ( Gz.size() < 0 ) { System.out.println("Gz = " + Gz); } List> G1 = null; GenSolvablePolynomial g1 = null; for (List> Gi : Gz ) { if ( Gi.get(0).isZERO() ) { continue; } if ( G1 == null ) { G1 = Gi; } if ( g1 == null ) { g1 = G1.get(0); } else if ( g1.compareTo(Gi.get(0)) > 0 ) { G1 = Gi; g1 = G1.get(0); } } oc[0] = G1.get(0); oc[1] = (GenSolvablePolynomial) G1.get(1).negate(); return oc; } /** * Right Ore condition. * Generators for the right Ore condition of two solvable polynomials. * @param a solvable polynomial * @param b solvable polynomial * @return [p,q] with a*p = b*q */ public GenSolvablePolynomial[] rightOreCond(GenSolvablePolynomial a, GenSolvablePolynomial b) { if (a == null || a.isZERO() || b == null || b.isZERO()) { throw new IllegalArgumentException("a and b must be non zero"); } GenSolvablePolynomialRing pfac = a.ring; GenSolvablePolynomial[] oc = (GenSolvablePolynomial[]) new GenSolvablePolynomial[2]; if ( a.isConstant() ) { oc[1] = pfac.getONE(); C c = a.leadingBaseCoefficient().inverse(); oc[0] = b.multiply(c); return oc; } if ( b.isConstant() ) { oc[0] = pfac.getONE(); C c = b.leadingBaseCoefficient().inverse(); oc[1] = a.multiply(c); return oc; } List> F = new ArrayList>(2); F.add(a); F.add(b); List>> Gz = rightZeroRelationsArbitrary(F); List> G1 = null; GenSolvablePolynomial g1 = null; for (List> Gi : Gz ) { if ( Gi.get(0).isZERO() ) { continue; } if ( G1 == null ) { G1 = Gi; } if ( g1 == null ) { g1 = G1.get(0); } else if ( g1.compareTo(Gi.get(0)) > 0 ) { G1 = Gi; g1 = G1.get(0); } } oc[0] = G1.get(0); oc[1] = (GenSolvablePolynomial) G1.get(1).negate(); return oc; } } /** * Container for module resolution components. * @param coefficient type */ class SolvResPart> implements Serializable { public final ModuleList module; public final ModuleList GB; public final ModuleList syzygy; /** * SolvResPart. * @param m a module list. * @param g a module list GB. * @param z a syzygy module list. */ public SolvResPart(ModuleList m, ModuleList g, ModuleList z) { module = m; GB = g; syzygy = z; } /** * toString. */ @Override public String toString() { StringBuffer s = new StringBuffer("SolvResPart(\n"); s.append("module = " + module); s.append("\n GB = " + GB); s.append("\n syzygy = " + syzygy); s.append(")"); return s.toString(); } } /** * Container for polynomial resolution components. * @param coefficient type */ class SolvResPolPart> implements Serializable { public final PolynomialList ideal; public final PolynomialList GB; public final ModuleList syzygy; /** * SolvResPolPart. * @param m a polynomial list. * @param g a polynomial list GB. * @param z a syzygy module list. */ public SolvResPolPart(PolynomialList m, PolynomialList g, ModuleList z) { ideal = m; GB = g; syzygy = z; } /** * toString. */ @Override public String toString() { StringBuffer s = new StringBuffer("SolvResPolPart(\n"); s.append("ideal = " + ideal); s.append("\n GB = " + GB); s.append("\n syzygy = " + syzygy); s.append(")"); return s.toString(); } } jas-2.5/src/edu/jas/gbmod/package.html0000644000175000017500000000147110653064164020045 0ustar giovannigiovanni Module Groebner base classes

Module Groebner base package.

This package contains classes for module Groebner bases and syzygies over polynomials and solvable polynomials, e.g. ModGroebnerBase or SolvableSyzygy.


Heinz Kredel

Last modified: Mon Jul 9 20:54:52 CEST 2007

$Id: package.html 1251 2007-07-29 10:14:13Z kredel $

jas-2.5/src/edu/jas/gbmod/ModGroebnerBase.java0000644000175000017500000000164011505424264021421 0ustar giovannigiovanni/* * $Id: ModGroebnerBase.java 3445 2010-12-25 17:24:04Z kredel $ */ package edu.jas.gbmod; import java.util.List; import edu.jas.structure.RingElem; import edu.jas.poly.GenPolynomial; import edu.jas.poly.ModuleList; /** * Module Groebner Bases interface. * Defines Groebner bases and GB test. * @author Heinz Kredel */ public interface ModGroebnerBase> { /** * Module Groebner base test. */ public boolean isGB(int modv, List> F); /** * isGB. * @param M a module basis. * @return true, if M is a Groebner base, else false. */ public boolean isGB(ModuleList M); /** * Groebner base using pairlist class. */ public List> GB(int modv, List> F); /** * GB. * @param M a module basis. * @return GB(M), a Groebner base of M. */ public ModuleList GB(ModuleList M); } jas-2.5/src/edu/jas/gbmod/SyzygyAbstract.java0000644000175000017500000005134412014234362021425 0ustar giovannigiovanni/* * $Id: SyzygyAbstract.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.gbmod; import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.gb.ExtendedGB; import edu.jas.gb.GroebnerBase; import edu.jas.gb.Reduction; import edu.jas.gb.ReductionSeq; import edu.jas.gbufd.GBFactory; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; import edu.jas.vector.BasicLinAlg; import edu.jas.vector.GenVector; import edu.jas.vector.GenVectorModul; /** * SyzygyAbstract class. Implements Syzygy computations and tests. * @param coefficient type * @author Heinz Kredel */ public class SyzygyAbstract> implements Syzygy { private static final Logger logger = Logger.getLogger(SyzygyAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Reduction engine. */ protected Reduction red; /** * Linear algebra engine. */ protected BasicLinAlg> blas; /** * Constructor. */ public SyzygyAbstract() { red = new ReductionSeq(); blas = new BasicLinAlg>(); //gb = new GroebnerBaseSeqPairSeq(); //gb = new GroebnerBaseSeq(); //gb = GBFactory. getImplementation(); } /** * Syzygy module from Groebner base. F must be a Groebner base. * @param F a Groebner base. * @return syz(F), a basis for the module of syzygies for F. */ public List>> zeroRelations(List> F) { return zeroRelations(0, F); } /** * Syzygy module from Groebner base. F must be a Groebner base. * @param modv number of module variables. * @param F a Groebner base. * @return syz(F), a basis for the module of syzygies for F. */ public List>> zeroRelations(int modv, List> F) { List>> Z = new ArrayList>>(); if (F == null) { return Z; } GenVectorModul> mfac = null; int i = 0; while (mfac == null && i < F.size()) { GenPolynomial p = F.get(i); if (p != null) { mfac = new GenVectorModul>(p.ring, F.size()); } } if (mfac == null) { return Z; } GenVector> v = mfac.fromList(F); //System.out.println("F = " + F + " v = " + v); return zeroRelations(modv, v); } /** * Syzygy module from Groebner base. v must be a Groebner base. * @param modv number of module variables. * @param v a Groebner base. * @return syz(v), a basis for the module of syzygies for v. */ public List>> zeroRelations(int modv, GenVector> v) { List>> Z = new ArrayList>>(); GenVectorModul> mfac = v.modul; List> F = v.val; GenVector> S = mfac.getZERO(); GenPolynomial pi, pj, s, h; //zero = mfac.coFac.getZERO(); for (int i = 0; i < F.size(); i++) { pi = F.get(i); for (int j = i + 1; j < F.size(); j++) { pj = F.get(j); //logger.info("p"+i+", p"+j+" = " + pi + ", " +pj); if (!red.moduleCriterion(modv, pi, pj)) { continue; } // if ( ! red.criterion4( pi, pj ) ) { continue; } List> row = S.copy().val; s = red.SPolynomial(row, i, pi, j, pj); if (s.isZERO()) { Z.add(row); continue; } h = red.normalform(row, F, s); if (!h.isZERO()) { throw new RuntimeException("Syzygy no GB"); } if (debug) { logger.info("row = " + row.size()); } Z.add(row); } } return Z; } /** * Syzygy module from module Groebner base. M must be a module Groebner * base. * @param M a module Groebner base. * @return syz(M), a basis for the module of syzygies for M. */ public ModuleList zeroRelations(ModuleList M) { ModuleList N = M; if (M == null || M.list == null) { return N; } if (M.rows == 0 || M.cols == 0) { return N; } GenPolynomial zero = M.ring.getZERO(); //System.out.println("zero = " + zero); //ModuleList Np = null; PolynomialList F = M.getPolynomialList(); int modv = M.cols; // > 0 //System.out.println("modv = " + modv); List>> G = zeroRelations(modv, F.list); //if (G == null) { // return N; //} List>> Z = new ArrayList>>(); for (int i = 0; i < G.size(); i++) { //F = new PolynomialList(F.ring,(List)G.get(i)); List> Gi = G.get(i); List> Zi = new ArrayList>(); // System.out.println("\nG("+i+") = " + G.get(i)); for (int j = 0; j < Gi.size(); j++) { //System.out.println("\nG("+i+","+j+") = " + Gi.get(j)); GenPolynomial p = Gi.get(j); if (p != null) { Map> r = p.contract(M.ring); int s = 0; for (GenPolynomial vi : r.values()) { Zi.add(vi); s++; } if (s == 0) { Zi.add(zero); } else if (s > 1) { // will not happen System.out.println("p = " + p); System.out.println("map(" + i + "," + j + ") = " + r + ", size = " + r.size()); throw new RuntimeException("Map.size() > 1 = " + r.size()); } } } //System.out.println("\nZ("+i+") = " + Zi); Z.add(Zi); } N = new ModuleList(M.ring, Z); //System.out.println("\n\nN = " + N); return N; } /** * Test if sysygy. * @param Z list of sysygies. * @param F a polynomial list. * @return true, if Z is a list of syzygies for F, else false. */ public boolean isZeroRelation(List>> Z, List> F) { for (List> row : Z) { GenPolynomial p = blas.scalarProduct(row, F); if (p == null) { continue; } if (!p.isZERO()) { logger.info("is not ZeroRelation = " + p.toString(p.ring.getVars())); logger.info("row = " + row); //logger.info("F = " + F); return false; } } return true; } /** * Test if sysygy of modules. * @param Z list of sysygies. * @param F a module list. * @return true, if Z is a list of syzygies for F, else false. */ public boolean isZeroRelation(ModuleList Z, ModuleList F) { if (Z == null || Z.list == null) { return true; } for (List> row : Z.list) { List> zr = blas.leftScalarProduct(row, F.list); if (!blas.isZero(zr)) { logger.info("is not ZeroRelation (" + zr.size() + ") = " + zr); return false; } } return true; } /** * Resolution of a module. Only with direct GBs. * @param M a module list of a Groebner basis. * @return a resolution of M. */ public List> resolution(ModuleList M) { List> R = new ArrayList>(); ModuleList MM = M; ModuleList GM; ModuleList Z; ModGroebnerBase mbb = new ModGroebnerBaseAbstract(M.ring.coFac); while (true) { GM = mbb.GB(MM); Z = zeroRelations(GM); R.add(new ResPart(MM, GM, Z)); if (Z == null || Z.list == null || Z.list.size() == 0) { break; } MM = Z; } return R; } /** * Resolution of a polynomial list. Only with direct GBs. * @param F a polynomial list of a Groebner basis. * @return a resolution of F. */ public List // |ResPolPart> resolution(PolynomialList F) { List>> Z; ModuleList Zm; List> G; PolynomialList Gl; GroebnerBase gb = GBFactory.getImplementation(F.ring.coFac); G = gb.GB(F.list); Z = zeroRelations(G); Gl = new PolynomialList(F.ring, G); Zm = new ModuleList(F.ring, Z); List R = resolution(Zm); //// |ResPolPart> R.add(0, new ResPolPart(F, Gl, Zm)); return R; } /** * Resolution of a polynomial list. * @param F a polynomial list of an arbitrary basis. * @return a resolution of F. */ public List // |ResPolPart> resolutionArbitrary(PolynomialList F) { List>> Z; ModuleList Zm; //List> G; PolynomialList Gl = null; //G = (new GroebnerBaseSeq()).GB( F.list ); Z = zeroRelationsArbitrary(F.list); //Gl = new PolynomialList(F.ring, F.list); Zm = new ModuleList(F.ring, Z); List R = resolutionArbitrary(Zm); //// |ResPolPart> R.add(0, new ResPolPart(F, Gl, Zm)); return R; } /** * Resolution of a module. * @param M a module list of an arbitrary basis. * @return a resolution of M. */ public List> resolutionArbitrary(ModuleList M) { List> R = new ArrayList>(); ModuleList MM = M; ModuleList GM = null; ModuleList Z; //ModGroebnerBase mbb = new ModGroebnerBaseAbstract(M.ring.coFac); while (true) { //GM = mbb.GB(MM); Z = zeroRelationsArbitrary(MM); R.add(new ResPart(MM, GM, Z)); if (Z == null || Z.list == null || Z.list.size() == 0) { break; } MM = Z; } return R; } /** * Syzygy module from arbitrary base. * @param F a polynomial list. * @return syz(F), a basis for the module of syzygies for F. */ public List>> zeroRelationsArbitrary(List> F) { return zeroRelationsArbitrary(0, F); } /** * Syzygy module from arbitrary base. * @param modv number of module variables. * @param F a polynomial list. * @return syz(F), a basis for the module of syzygies for F. */ public List>> zeroRelationsArbitrary(int modv, List> F) { if (F == null) { return new ArrayList>>(); //return zeroRelations(modv, F); } if (F.size() <= 1) { return zeroRelations(modv, F); } GroebnerBase gb = GBFactory.getImplementation(F.get(0).ring.coFac); final int lenf = F.size(); ExtendedGB exgb = gb.extGB(F); if (debug) { logger.debug("exgb = " + exgb); if (!gb.isReductionMatrix(exgb)) { logger.error("is reduction matrix ? false"); } } List> G = exgb.G; List>> G2F = exgb.G2F; List>> F2G = exgb.F2G; List>> sg = zeroRelations(modv, G); GenPolynomialRing ring = G.get(0).ring; ModuleList S = new ModuleList(ring, sg); if (debug) { logger.debug("syz = " + S); if (!isZeroRelation(sg, G)) { logger.error("is syzygy ? false"); } } List>> sf; sf = new ArrayList>>(sg.size()); //List> row; for (List> r : sg) { Iterator> it = r.iterator(); Iterator>> jt = G2F.iterator(); List> rf; rf = new ArrayList>(lenf); for (int m = 0; m < lenf; m++) { rf.add(ring.getZERO()); } while (it.hasNext() && jt.hasNext()) { GenPolynomial si = it.next(); List> ai = jt.next(); //System.out.println("si = " + si); //System.out.println("ai = " + ai); if (si == null || ai == null) { continue; } List> pi = blas.scalarProduct(si, ai); //System.out.println("pi = " + pi); rf = blas.vectorAdd(rf, pi); } if (it.hasNext() || jt.hasNext()) { logger.error("zeroRelationsArbitrary wrong sizes"); } //System.out.println("\nrf = " + rf + "\n"); sf.add(rf); } List>> M; M = new ArrayList>>(lenf); for (List> r : F2G) { Iterator> it = r.iterator(); Iterator>> jt = G2F.iterator(); List> rf; rf = new ArrayList>(lenf); for (int m = 0; m < lenf; m++) { rf.add(ring.getZERO()); } while (it.hasNext() && jt.hasNext()) { GenPolynomial si = it.next(); List> ai = jt.next(); //System.out.println("si = " + si); //System.out.println("ai = " + ai); if (si == null || ai == null) { continue; } List> pi = blas.scalarProduct(ai, si); //System.out.println("pi = " + pi); rf = blas.vectorAdd(rf, pi); } if (it.hasNext() || jt.hasNext()) { logger.error("zeroRelationsArbitrary wrong sizes"); } //System.out.println("\nMg Mf = " + rf + "\n"); M.add(rf); } //ModuleList ML = new ModuleList( ring, M ); //System.out.println("syz ML = " + ML); // debug only: /* not true in general List> F2 = new ArrayList>( F.size() ); for ( List> rr: M ) { GenPolynomial rrg = blas.scalarProduct( F, rr ); F2.add( rrg ); } PolynomialList pF = new PolynomialList( ring, F ); PolynomialList pF2 = new PolynomialList( ring, F2 ); if ( ! pF.equals( pF2 ) ) { logger.error("is FAB = F ? false"); } */ int sflen = sf.size(); List>> M2; M2 = new ArrayList>>(lenf); int i = 0; for (List> ri : M) { List> r2i; r2i = new ArrayList>(ri.size()); int j = 0; for (GenPolynomial rij : ri) { GenPolynomial p = null; if (i == j) { p = ring.getONE().subtract(rij); } else { if (rij != null) { p = rij.negate(); } } r2i.add(p); j++; } M2.add(r2i); if (!blas.isZero(r2i)) { sf.add(r2i); } i++; } if (debug) { ModuleList M2L = new ModuleList(ring, M2); logger.debug("syz M2L = " + M2L); ModuleList SF = new ModuleList(ring, sf); logger.debug("syz sf = " + SF); logger.debug("#syz " + sflen + ", " + sf.size()); if (!isZeroRelation(sf, F)) { logger.error("is syz sf ? false"); } } return sf; } /** * Syzygy module from arbitrary module base. * @param M an arbitrary module base. * @return syz(M), a basis for the module of syzygies for M. */ public ModuleList zeroRelationsArbitrary(ModuleList M) { ModuleList N = M; if (M == null || M.list == null) { return N; } if (M.rows == 0 || M.cols == 0) { return N; } GenPolynomial zero = M.ring.getZERO(); //System.out.println("zero = " + zero); //ModuleList Np = null; PolynomialList F = M.getPolynomialList(); int modv = M.cols; // > 0 //System.out.println("modv = " + modv); List>> G = zeroRelationsArbitrary(modv, F.list); //if (G == null) { // return N; //} List>> Z = new ArrayList>>(); for (int i = 0; i < G.size(); i++) { //F = new PolynomialList(F.ring,(List)G.get(i)); List> Gi = G.get(i); List> Zi = new ArrayList>(); // System.out.println("\nG("+i+") = " + G.get(i)); for (int j = 0; j < Gi.size(); j++) { //System.out.println("\nG("+i+","+j+") = " + Gi.get(j)); GenPolynomial p = Gi.get(j); if (p != null) { Map> r = p.contract(M.ring); int s = 0; for (GenPolynomial vi : r.values()) { Zi.add(vi); s++; } if (s == 0) { Zi.add(zero); } else if (s > 1) { // will not happen System.out.println("p = " + p); System.out.println("map(" + i + "," + j + ") = " + r + ", size = " + r.size()); throw new RuntimeException("Map.size() > 1 = " + r.size()); } } } //System.out.println("\nZ("+i+") = " + Zi); Z.add(Zi); } N = new ModuleList(M.ring, Z); //System.out.println("\n\nN = " + N); return N; } } /** * Container for module resolution components. * @param coefficient type */ class ResPart> implements Serializable { public final ModuleList module; public final ModuleList GB; public final ModuleList syzygy; /** * ResPart. * @param m a module list. * @param g a module list GB. * @param z a syzygy module list. */ public ResPart(ModuleList m, ModuleList g, ModuleList z) { module = m; GB = g; syzygy = z; } /** * toString. */ @Override public String toString() { StringBuffer s = new StringBuffer("ResPart(\n"); s.append("module = " + module); s.append("\n GB = " + GB); s.append("\n syzygy = " + syzygy); s.append(")"); return s.toString(); } } /** * Container for polynomial resolution components. */ class ResPolPart> implements Serializable { public final PolynomialList ideal; public final PolynomialList GB; public final ModuleList syzygy; /** * ResPolPart. * @param m a polynomial list. * @param g a polynomial list GB. * @param z a syzygy module list. */ public ResPolPart(PolynomialList m, PolynomialList g, ModuleList z) { ideal = m; GB = g; syzygy = z; } /** * toString. */ @Override public String toString() { StringBuffer s = new StringBuffer("ResPolPart(\n"); s.append("ideal = " + ideal); s.append("\n GB = " + GB); s.append("\n syzygy = " + syzygy); s.append(")"); return s.toString(); } } jas-2.5/src/edu/jas/gbmod/SolvableQuotient.java0000644000175000017500000003735012137713752021737 0ustar giovannigiovanni/* * $Id: SolvableQuotient.java 4406 2013-04-30 10:07:39Z kredel $ */ package edu.jas.gbmod; import org.apache.log4j.Logger; import edu.jas.kern.PrettyPrint; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.structure.GcdRingElem; /** * SolvableQuotient, that is a (left) rational function, based on GenSolvablePolynomial * with RingElem interface. Objects of this class are immutable. * @author Heinz Kredel */ public class SolvableQuotient> implements GcdRingElem> { private static final Logger logger = Logger.getLogger(SolvableQuotient.class); private final boolean debug = logger.isDebugEnabled(); /** * SolvableQuotient class factory data structure. */ public final SolvableQuotientRing ring; /** * Numerator part of the element data structure. */ public final GenSolvablePolynomial num; /** * Denominator part of the element data structure. */ public final GenSolvablePolynomial den; /** * The constructor creates a SolvableQuotient object from a ring factory. * @param r ring factory. */ public SolvableQuotient(SolvableQuotientRing r) { this(r, r.ring.getZERO()); } /** * The constructor creates a SolvableQuotient object from a ring factory and a * numerator polynomial. The denominator is assumed to be 1. * @param r ring factory. * @param n numerator solvable polynomial. */ public SolvableQuotient(SolvableQuotientRing r, GenSolvablePolynomial n) { this(r, n, r.ring.getONE(), true); } /** * The constructor creates a SolvableQuotient object from a ring factory and a * numerator and denominator solvable polynomial. * @param r ring factory. * @param n numerator polynomial. * @param d denominator polynomial. */ public SolvableQuotient(SolvableQuotientRing r, GenSolvablePolynomial n, GenSolvablePolynomial d) { this(r, n, d, false); } /** * The constructor creates a SolvableQuotient object from a ring factory and a * numerator and denominator polynomial. * @param r ring factory. * @param n numerator polynomial. * @param d denominator polynomial. * @param isred unused at the moment. */ protected SolvableQuotient(SolvableQuotientRing r, GenSolvablePolynomial n, GenSolvablePolynomial d, boolean isred) { if (d == null || d.isZERO()) { throw new IllegalArgumentException("denominator may not be zero"); } ring = r; if (d.signum() < 0) { n = (GenSolvablePolynomial) n.negate(); d = (GenSolvablePolynomial) d.negate(); } if (!isred) { // TODO } C lc = d.leadingBaseCoefficient(); if (!lc.isONE() && lc.isUnit()) { lc = lc.inverse(); n = n.multiply(lc); d = d.multiply(lc); } if ( n.compareTo(d) == 0 ) { n = ring.ring.getONE(); d = ring.ring.getONE(); } if ( n.isZERO() ) { d = ring.ring.getONE(); } num = n; den = d; } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public SolvableQuotientRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public SolvableQuotient copy() { return new SolvableQuotient(ring, num, den, true); } /** * Is SolvableQuotient zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return num.isZERO(); } /** * Is SolvableQuotient one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return num.compareTo(den) == 0; } /** * Is SolvableQuotient a unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (num.isZERO()) { return false; } return true; } /** * Is Qoutient a constant. * @return true, if this has constant numerator and denominator, else false. */ public boolean isConstant() { return num.isConstant() && den.isConstant(); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { if (PrettyPrint.isTrue()) { String s = "{ " + num.toString(ring.ring.getVars()); if (!den.isONE()) { s += " | " + den.toString(ring.ring.getVars()); } return s + " }"; } return "SolvableQuotient[ " + num.toString() + " | " + den.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ @Override public String toScript() { // any scripting case if (den.isONE()) { return num.toScript(); } return num.toScript() + " / " + den.toScript(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ @Override public String toScriptFactory() { return factory().toScript(); } /** * SolvableQuotient comparison. * @param b SolvableQuotient. * @return sign(this-b). */ @Override public int compareTo(SolvableQuotient b) { if (b == null || b.isZERO()) { return this.signum(); } if (this.isZERO()) { return -b.signum(); } // assume sign(den,b.den) > 0 int s1 = num.signum(); int s2 = b.num.signum(); int t = (s1 - s2) / 2; if (t != 0) { return t; } if ( den.compareTo(b.den) == 0 ) { return num.compareTo(b.num); } GenSolvablePolynomial[] oc = ring.engine.leftOreCond(den,b.den); if (debug) { System.out.println("den = " + den); System.out.println("b.den = " + b.den); System.out.println("oc[0] = " + oc[0]); System.out.println("oc[1] = " + oc[1]); } GenSolvablePolynomial r, s; r = oc[0].multiply(num); s = oc[1].multiply(b.num); //System.out.println("r = " + r); //System.out.println("s = " + s); return r.compareTo(s); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @SuppressWarnings("unchecked") @Override public boolean equals(Object b) { if (!(b instanceof SolvableQuotient)) { return false; } SolvableQuotient a = null; try { a = (SolvableQuotient) b; } catch (ClassCastException e) { } if (a == null) { return false; } return compareTo( a ) == 0; //return num.equals(a.num) && den.equals(a.den); } /** * Hash code for this element. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + num.hashCode(); h = 37 * h + den.hashCode(); return h; } /** * SolvableQuotient absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public SolvableQuotient abs() { return new SolvableQuotient(ring, (GenSolvablePolynomial) num.abs(), den, true); } /** * SolvableQuotient summation. * @param S SolvableQuotient. * @return this+S. */ public SolvableQuotient sum(SolvableQuotient S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } GenSolvablePolynomial n, d, n1, n2; if (den.isONE() && S.den.isONE()) { n = (GenSolvablePolynomial) num.sum(S.num); return new SolvableQuotient(ring, n, den, true); } if (den.isONE()) { n = S.den.multiply(num); n = (GenSolvablePolynomial) n.sum(S.num); return new SolvableQuotient(ring, n, S.den, false); } if (S.den.isONE()) { n = den.multiply(S.num); n = (GenSolvablePolynomial) n.sum(num); return new SolvableQuotient(ring, n, den, false); } if ( den.compareTo(S.den) == 0 ) { // correct ? //d = den.multiply(den); //n1 = den.multiply(S.num); //n2 = S.den.multiply(num); n = (GenSolvablePolynomial) num.sum(S.num); return new SolvableQuotient(ring, n, den, false); } // general case GenSolvablePolynomial[] oc = ring.engine.leftOreCond(den,S.den); if (debug) { System.out.println("den = " + den); System.out.println("S.den = " + S.den); System.out.println("oc[0] = " + oc[0]); System.out.println("oc[1] = " + oc[1]); } d = oc[0].multiply(den); n1 = oc[0].multiply(num); n2 = oc[1].multiply(S.num); n = (GenSolvablePolynomial) n1.sum(n2); //System.out.println("n = " + n); //System.out.println("d = " + d); return new SolvableQuotient(ring, n, d, false); } /** * SolvableQuotient negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public SolvableQuotient negate() { return new SolvableQuotient(ring, (GenSolvablePolynomial) num.negate(), den, true); } /** * SolvableQuotient signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { // assume sign(den) > 0 return num.signum(); } /** * SolvableQuotient subtraction. * @param S SolvableQuotient. * @return this-S. */ public SolvableQuotient subtract(SolvableQuotient S) { return sum(S.negate()); } /** * SolvableQuotient division. * @param S SolvableQuotient. * @return this/S. */ public SolvableQuotient divide(SolvableQuotient S) { return multiply(S.inverse()); } /** * SolvableQuotient inverse. * @see edu.jas.structure.RingElem#inverse() * @return S with S = 1/this. */ public SolvableQuotient inverse() { if (num.isZERO()) { throw new ArithmeticException("element not invertible " + this); } return new SolvableQuotient(ring, den, num, true); } /** * SolvableQuotient remainder. * @param S SolvableQuotient. * @return this - (this/S)*S. */ public SolvableQuotient remainder(SolvableQuotient S) { if (num.isZERO()) { throw new ArithmeticException("element not invertible " + this); } return ring.getZERO(); } /** * SolvableQuotient multiplication. * @param S SolvableQuotient. * @return this*S. */ public SolvableQuotient multiply(SolvableQuotient S) { if (S == null || S.isZERO()) { return S; } if (num.isZERO()) { return this; } if (S.isONE()) { return this; } if (this.isONE()) { return S; } GenSolvablePolynomial n, d; if (den.isONE() && S.den.isONE()) { n = num.multiply(S.num); return new SolvableQuotient(ring, n, den, true); } if (den.isONE()) { d = S.den; n = num.multiply(S.num); return new SolvableQuotient(ring, n, d, false); } if (S.den.isONE()) { d = den; n = num.multiply(S.num); return new SolvableQuotient(ring, n, d, false); } // if ( den.compareTo(S.den) == 0 ) { // not correct ? // d = den.multiply(den); // n = num.multiply(S.num); // return new SolvableQuotient(ring, n, d, false); // } GenSolvablePolynomial[] oc = ring.engine.leftOreCond(num,S.den); n = oc[1].multiply(S.num); d = oc[0].multiply(den); if (debug) { System.out.println("num = " + num); System.out.println("S.den = " + S.den); System.out.println("oc[0] = " + oc[0]); System.out.println("oc[1] = " + oc[1]); } return new SolvableQuotient(ring, n, d, false); } /** * SolvableQuotient multiplication by GenSolvablePolynomial. * @param b GenSolvablePolynomial. * @return this*b. */ public SolvableQuotient multiply(GenSolvablePolynomial b) { if (b == null || b.isZERO()) { return ring.getZERO(); } if (num.isZERO()) { return this; } if (b.isONE()) { return this; } GenSolvablePolynomial n = num.multiply(b); return new SolvableQuotient(ring, n, den, false); } /** * SolvableQuotient multiplication by coefficient. * @param b coefficient. * @return this*b. */ public SolvableQuotient multiply(C b) { if (b == null || b.isZERO()) { return ring.getZERO(); } if (num.isZERO()) { return this; } if (b.isONE()) { return this; } GenSolvablePolynomial n = num.multiply(b); return new SolvableQuotient(ring, n, den, false); } /** * SolvableQuotient monic. * @return this with monic value part. */ public SolvableQuotient monic() { if (num.isZERO()) { return this; } C lbc = num.leadingBaseCoefficient(); if (!lbc.isUnit()) { return this; } lbc = lbc.inverse(); //lbc = lbc.abs(); GenSolvablePolynomial n = (GenSolvablePolynomial) num.multiply(lbc); //GenSolvablePolynomial d = (GenSolvablePolynomial) den.multiply(lbc); return new SolvableQuotient(ring, n, den, true); } /** * Greatest common divisor. * @param b other element. * @return gcd(this,b). */ public SolvableQuotient gcd(SolvableQuotient b) { if (b == null || b.isZERO()) { return this; } if (this.isZERO()) { return b; } return ring.getONE(); } /** * Extended greatest common divisor. * @param b other element. * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). */ @SuppressWarnings("unchecked") public SolvableQuotient[] egcd(SolvableQuotient b) { SolvableQuotient[] ret = (SolvableQuotient[]) new SolvableQuotient[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (b == null || b.isZERO()) { ret[0] = this; return ret; } if (this.isZERO()) { ret[0] = b; return ret; } GenSolvablePolynomial two = ring.ring.fromInteger(2); ret[0] = ring.getONE(); ret[1] = (this.multiply(two)).inverse(); ret[2] = (b.multiply(two)).inverse(); return ret; } } jas-2.5/src/edu/jas/gbmod/ModSolvableGroebnerBase.java0000644000175000017500000000674711505424264023126 0ustar giovannigiovanni/* * $Id: ModSolvableGroebnerBase.java 3445 2010-12-25 17:24:04Z kredel $ */ package edu.jas.gbmod; import java.util.List; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.ModuleList; import edu.jas.structure.RingElem; /** * Module solvable Groebner Bases interface. * Defines modull solvabe Groebner bases and GB test. * @param coefficient type * @author Heinz Kredel */ public interface ModSolvableGroebnerBase> { /** * Module left Groebner base test. * @param modv number of modul variables. * @param F a module basis. * @return true, if F is a left Groebner base, else false. */ public boolean isLeftGB(int modv, List> F); /** * Module left Groebner base test. * @param M a module basis. * @return true, if M is a left Groebner base, else false. */ public boolean isLeftGB(ModuleList M); /** * Left Groebner base using pairlist class. * @param modv number of modul variables. * @param F a module basis. * @return leftGB(F) a left Groebner base for F. */ public List> leftGB(int modv, List> F); /** * Left Groebner base using pairlist class. * @param M a module basis. * @return leftGB(M) a left Groebner base for M. */ public ModuleList leftGB(ModuleList M); /** * Module twosided Groebner base test. * @param modv number of modul variables. * @param F a module basis. * @return true, if F is a twosided Groebner base, else false. */ public boolean isTwosidedGB(int modv, List> F); /** * Module twosided Groebner base test. * @param M a module basis. * @return true, if M is a twosided Groebner base, else false. */ public boolean isTwosidedGB(ModuleList M); /** * Twosided Groebner base using pairlist class. * @param modv number of modul variables. * @param F a module basis. * @return tsGB(F) a twosided Groebner base for F. */ public List> twosidedGB(int modv, List> F); /** * Twosided Groebner base using pairlist class. * @param M a module basis. * @return tsGB(M) a twosided Groebner base for M. */ public ModuleList twosidedGB(ModuleList M); /** * Module right Groebner base test. * @param modv number of modul variables. * @param F a module basis. * @return true, if F is a right Groebner base, else false. */ public boolean isRightGB(int modv, List> F); /** * Module right Groebner base test. * @param M a module basis. * @return true, if M is a right Groebner base, else false. */ public boolean isRightGB(ModuleList M); /** * Right Groebner base using pairlist class. * @param modv number of modul variables. * @param F a module basis. * @return rightGB(F) a right Groebner base for F. */ public List> rightGB(int modv, List> F); /** * Right Groebner base using pairlist class. * @param M a module basis. * @return rightGB(M) a right Groebner base for M. */ public ModuleList rightGB(ModuleList M); } jas-2.5/src/edu/jas/gbmod/Syzygy.java0000644000175000017500000000776111505424264017753 0ustar giovannigiovanni/* * $Id: Syzygy.java 3445 2010-12-25 17:24:04Z kredel $ */ package edu.jas.gbmod; import java.util.List; import edu.jas.poly.GenPolynomial; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingElem; import edu.jas.vector.GenVector; /** * Syzygy interface. * Defines Syzygy computations and tests. * @param coefficient type * @author Heinz Kredel */ public interface Syzygy> { /** * Syzygy module from Groebner base. * F must be a Groebner base. * @param F a Groebner base. * @return syz(F), a basis for the module of syzygies for F. */ public List>> zeroRelations(List> F); /** * Syzygy module from Groebner base. * F must be a Groebner base. * @param modv number of module variables. * @param F a Groebner base. * @return syz(F), a basis for the module of syzygies for F. */ public List>> zeroRelations(int modv, List> F); /** * Syzygy module from Groebner base. * v must be a Groebner base. * @param modv number of module variables. * @param v a Groebner base. * @return syz(v), a basis for the module of syzygies for v. */ public List>> zeroRelations(int modv, GenVector> v); /** * Syzygy module from module Groebner base. * M must be a module Groebner base. * @param M a module Groebner base. * @return syz(M), a basis for the module of syzygies for M. */ public ModuleList zeroRelations(ModuleList M); /** * Test if sysygy. * @param Z list of sysygies. * @param F a polynomial list. * @return true, if Z is a list of syzygies for F, else false. */ public boolean isZeroRelation(List>> Z, List> F); /** * Test if sysygy of modules. * @param Z list of sysygies. * @param F a module list. * @return true, if Z is a list of syzygies for F, else false. */ public boolean isZeroRelation(ModuleList Z, ModuleList F); /** * Resolution of a module. * Only with direct GBs. * @param M a module list of a Groebner basis. * @return a resolution of M. */ public List> resolution(ModuleList M); /** * Resolution of a polynomial list. * Only with direct GBs. * @param F a polynomial list of a Groebner basis. * @return a resolution of F. */ public List // |ResPolPart> resolution(PolynomialList F); /** * Resolution of a polynomial list. * @param F a polynomial list of an arbitrary basis. * @return a resolution of F. */ public List // |ResPolPart> resolutionArbitrary(PolynomialList F); /** * Resolution of a module. * @param M a module list of an arbitrary basis. * @return a resolution of M. */ public List> resolutionArbitrary(ModuleList M); /** * Syzygy module from arbitrary base. * @param F a polynomial list. * @return syz(F), a basis for the module of syzygies for F. */ public List>> zeroRelationsArbitrary(List> F); /** * Syzygy module from arbitrary base. * @param modv number of module variables. * @param F a polynomial list. * @return syz(F), a basis for the module of syzygies for F. */ public List>> zeroRelationsArbitrary(int modv, List> F); /** * Syzygy module from arbitrary module base. * @param M an arbitrary module base. * @return syz(M), a basis for the module of syzygies for M. */ public ModuleList zeroRelationsArbitrary(ModuleList M); } jas-2.5/src/edu/jas/gbmod/SolvableSyzygy.java0000644000175000017500000001221211505424264021426 0ustar giovannigiovanni/* * $Id: SolvableSyzygy.java 3445 2010-12-25 17:24:04Z kredel $ */ package edu.jas.gbmod; import java.util.List; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingElem; /** * Syzygy interface for solvable polynomials. * Defines syzygy computations and tests. * @param coefficient type * @author Heinz Kredel */ public interface SolvableSyzygy> { /** * Left syzygy for left Groebner base. * @param F a Groebner base. * @return leftSyz(F), a basis for the left module of syzygies for F. */ public List>> leftZeroRelations(List> F); /** * Left syzygy for left Groebner base. * @param modv number of module variables. * @param F a Groebner base. * @return leftSyz(F), a basis for the left module of syzygies for F. */ public List>> leftZeroRelations(int modv, List> F); /** * Left syzygy for left module Groebner base. * @param M a Groebner base. * @return leftSyz(M), a basis for the left module of syzygies for M. */ public ModuleList leftZeroRelations(ModuleList M); /** * Test if left syzygy. * @param Z list of sysygies. * @param F a polynomial list. * @return true, if Z is a list of left syzygies for F, else false. */ public boolean isLeftZeroRelation(List>> Z, List> F); /** * Test if right syzygy. * @param Z list of sysygies. * @param F a polynomial list. * @return true, if Z is a list of right syzygies for F, else false. */ public boolean isRightZeroRelation(List>> Z, List> F); /** * Test if left sysygy of modules * @param Z list of sysygies. * @param F a module list. * @return true, if Z is a list of left syzygies for F, else false. */ public boolean isLeftZeroRelation(ModuleList Z, ModuleList F); /** * Test if right sysygy of modules * @param Z list of sysygies. * @param F a module list. * @return true, if Z is a list of right syzygies for F, else false. */ public boolean isRightZeroRelation(ModuleList Z, ModuleList F); /** * Resolution of a module. * Only with direct GBs. * @param M a module list of a Groebner basis. * @return a resolution of M. */ public List> resolution(ModuleList M); /** * Resolution of a polynomial list. * Only with direct GBs. * @param F a polynomial list of a Groebner basis. * @return a resolution of F. */ public List // |SolvResPolPart> resolution(PolynomialList F); /** * Resolution of a module. * @param M a module list of an arbitrary basis. * @return a resolution of M. */ public List> resolutionArbitrary(ModuleList M); /** * Resolution of a polynomial list. * @param F a polynomial list of an arbitrary basis. * @return a resolution of F. */ public List // |SolvResPolPart> resolutionArbitrary(PolynomialList F); /** * Left syzygy module from arbitrary base. * @param F a solvable polynomial list. * @return syz(F), a basis for the module of left syzygies for F. */ public List>> leftZeroRelationsArbitrary(List> F); /** * Left syzygy module from arbitrary base. * @param modv number of module variables. * @param F a solvable polynomial list. * @return syz(F), a basis for the module of left syzygies for F. */ public List>> leftZeroRelationsArbitrary(int modv, List> F); /** * Left syzygy for arbitrary left module base. * @param M an arbitrary base. * @return leftSyz(M), a basis for the left module of syzygies for M. */ public ModuleList leftZeroRelationsArbitrary(ModuleList M); /** * Right syzygy module from arbitrary base. * @param F a solvable polynomial list. * @return syz(F), a basis for the module of right syzygies for F. */ public List>> rightZeroRelationsArbitrary(List> F); /** * Right syzygy module from arbitrary base. * @param modv number of module variables. * @param F a solvable polynomial list. * @return syz(F), a basis for the module of right syzygies for F. */ public List>> rightZeroRelationsArbitrary(int modv, List> F); } jas-2.5/src/edu/jas/gbmod/ModSolvableGroebnerBaseAbstract.java0000644000175000017500000002265212013663732024603 0ustar giovannigiovanni/* * $Id: ModSolvableGroebnerBaseAbstract.java 4104 2012-08-18 10:00:59Z kredel $ */ package edu.jas.gbmod; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.structure.RingElem; import edu.jas.gb.SolvableGroebnerBase; import edu.jas.gb.SolvableGroebnerBaseSeq; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; /** * Module solvable Groebner Bases class. * Implements module solvable Groebner bases and GB test. * @param coefficient type * @author Heinz Kredel */ public class ModSolvableGroebnerBaseAbstract> implements ModSolvableGroebnerBase { private static final Logger logger = Logger.getLogger(ModSolvableGroebnerBase.class); private final boolean debug = logger.isDebugEnabled(); /** * Used Solvable Groebner base algorithm. */ protected final SolvableGroebnerBase sbb; /** * Constructor. */ public ModSolvableGroebnerBaseAbstract() { sbb = new SolvableGroebnerBaseSeq(); } /** * Module left Groebner base test. * @param modv number of modul variables. * @param F a module basis. * @return true, if F is a left Groebner base, else false. */ public boolean isLeftGB(int modv, List> F) { return sbb.isLeftGB(modv,F); } /** * Module left Groebner base test. * @param M a module basis. * @return true, if M is a left Groebner base, else false. */ public boolean isLeftGB(ModuleList M) { if ( M == null || M.list == null ) { return true; } if ( M.rows == 0 || M.cols == 0 ) { return true; } int modv = M.cols; // > 0 PolynomialList F = M.getPolynomialList(); return sbb.isLeftGB(modv,F.castToSolvableList()); } /** * Left Groebner base using pairlist class. * @param modv number of modul variables. * @param F a module basis. * @return leftGB(F) a left Groebner base for F. */ public List> leftGB(int modv, List> F) { return sbb.leftGB(modv,F); } /** * Left Groebner base using pairlist class. * @param M a module basis. * @return leftGB(M) a left Groebner base for M. */ @SuppressWarnings("unchecked") public ModuleList leftGB(ModuleList M) { ModuleList N = M; if ( M == null || M.list == null ) { return N; } if ( M.rows == 0 || M.cols == 0 ) { return N; } PolynomialList F = M.getPolynomialList(); if ( debug ) { logger.info("F left +++++++++++++++++++ \n" + F); } GenSolvablePolynomialRing sring = (GenSolvablePolynomialRing)F.ring; int modv = M.cols; List> G = sbb.leftGB(modv,F.castToSolvableList()); F = new PolynomialList(sring,G); if ( debug ) { logger.info("G left +++++++++++++++++++ \n" + F); } N = F.getModuleList(modv); return N; } /** * Module twosided Groebner base test. * @param modv number of modul variables. * @param F a module basis. * @return true, if F is a twosided Groebner base, else false. */ public boolean isTwosidedGB(int modv, List> F) { return sbb.isTwosidedGB(modv,F); } /** * Module twosided Groebner base test. * @param M a module basis. * @return true, if M is a twosided Groebner base, else false. */ public boolean isTwosidedGB(ModuleList M) { if ( M == null || M.list == null ) { return true; } if ( M.rows == 0 || M.cols == 0 ) { return true; } PolynomialList F = M.getPolynomialList(); int modv = M.cols; // > 0 return sbb.isTwosidedGB(modv,F.castToSolvableList()); } /** * Twosided Groebner base using pairlist class. * @param modv number of modul variables. * @param F a module basis. * @return tsGB(F) a twosided Groebner base for F. */ public List> twosidedGB(int modv, List> F) { return sbb.twosidedGB(modv,F); } /** * Twosided Groebner base using pairlist class. * @param M a module basis. * @return tsGB(M) a twosided Groebner base for M. */ @SuppressWarnings("unchecked") public ModuleList twosidedGB(ModuleList M) { ModuleList N = M; if ( M == null || M.list == null ) { return N; } if ( M.rows == 0 || M.cols == 0 ) { return N; } PolynomialList F = M.getPolynomialList(); GenSolvablePolynomialRing sring = (GenSolvablePolynomialRing)F.ring; int modv = M.cols; List> G = sbb.twosidedGB(modv,F.castToSolvableList()); F = new PolynomialList(sring,G); N = F.getModuleList(modv); return N; } /** * Module right Groebner base test. * @param modv number of modul variables. * @param F a module basis. * @return true, if F is a right Groebner base, else false. */ public boolean isRightGB(int modv, List> F) { return sbb.isRightGB(modv,F); } /** * Module right Groebner base test. * @param M a module basis. * @return true, if M is a right Groebner base, else false. */ public boolean isRightGB(ModuleList M) { if ( M == null || M.list == null ) { return true; } if ( M.rows == 0 || M.cols == 0 ) { return true; } int modv = M.cols; // > 0 PolynomialList F = M.getPolynomialList(); //System.out.println("F test = " + F); return sbb.isRightGB( modv, F.castToSolvableList() ); } /** * Right Groebner base using pairlist class. * @param modv number of modul variables. * @param F a module basis. * @return rightGB(F) a right Groebner base for F. */ public List> rightGB(int modv, List> F) { if ( modv == 0 ) { return sbb.rightGB(modv,F); } throw new UnsupportedOperationException("modv != 0 not jet implemented"); // return sbb.rightGB(modv,F); } /** * Right Groebner base using pairlist class. * @param M a module basis. * @return rightGB(M) a right Groebner base for M. */ @SuppressWarnings("unchecked") public ModuleList rightGB(ModuleList M) { ModuleList N = M; if ( M == null || M.list == null ) { return N; } if ( M.rows == 0 || M.cols == 0 ) { return N; } if ( debug ) { logger.info("M ====================== \n" + M); } TermOrder to = M.ring.tord; if ( to.getSplit() <= M.ring.nvar ) { throw new IllegalArgumentException("extended TermOrders not supported for rightGBs: " + to); } List>> mlist = M.castToSolvableList(); GenSolvablePolynomialRing sring = (GenSolvablePolynomialRing)M.ring; GenSolvablePolynomialRing rring = sring.reverse(true); //true sring = rring.reverse(true); // true List>> nlist = new ArrayList>>( M.rows ); for ( List> row : mlist ) { List> nrow = new ArrayList>( row.size() ); for ( GenSolvablePolynomial elem : row ) { GenSolvablePolynomial nelem = (GenSolvablePolynomial)elem.reverse(rring); nrow.add( nelem ); } nlist.add( nrow ); } ModuleList rM = new ModuleList( rring, nlist ); if ( debug ) { logger.info("rM -------------------- \n" + rM); } ModuleList rMg = leftGB( rM ); if ( debug ) { logger.info("rMg -------------------- \n" + rMg); logger.info("isLeftGB(rMg) ---------- " + isLeftGB(rMg)); } mlist = rMg.castToSolvableList(); nlist = new ArrayList>>( rMg.rows ); for ( List> row : mlist ) { List> nrow = new ArrayList>( row.size() ); for ( GenSolvablePolynomial elem : row ) { GenSolvablePolynomial nelem = (GenSolvablePolynomial)elem.reverse(sring); nrow.add( nelem ); } nlist.add( nrow ); } ModuleList Mg = new ModuleList( sring, nlist ); if ( debug ) { logger.info("Mg -------------------- \n" + Mg); logger.info("isRightGB(Mg) --------- " + isRightGB(Mg)); } return Mg; } } jas-2.5/src/edu/jas/gbmod/SolvableQuotientRing.java0000644000175000017500000002473612137713752022563 0ustar giovannigiovanni/* * $Id: SolvableQuotientRing.java 4406 2013-04-30 10:07:39Z kredel $ */ package edu.jas.gbmod; import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.StringUtil; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.application.SolvableIdeal; /** * SolvableQuotient ring factory based on GenPolynomial with RingElem interface. Objects * of this class are immutable. * @author Heinz Kredel */ public class SolvableQuotientRing> implements RingFactory> { private static final Logger logger = Logger.getLogger(SolvableQuotientRing.class); //private boolean debug = logger.isDebugEnabled(); /** * Solvable polynomial ring of the factory. */ public final GenSolvablePolynomialRing ring; /** * Syzygy engine of the factory. */ public final SolvableSyzygyAbstract engine; /** * The constructor creates a SolvableQuotientRing object from a GenSolvablePolynomialRing. * @param r solvable polynomial ring. */ public SolvableQuotientRing(GenSolvablePolynomialRing r) { ring = r; engine = new SolvableSyzygyAbstract(); logger.debug("quotient ring constructed"); } /** * Least common multiple. * @param n first solvable polynomial. * @param d second solvable polynomial. * @return lcm(n,d) */ protected GenSolvablePolynomial syzLcm(GenSolvablePolynomial n, GenSolvablePolynomial d) { List> list = new ArrayList>(1); list.add(n); SolvableIdeal N = new SolvableIdeal(n.ring, list, true); list = new ArrayList>(1); list.add(d); SolvableIdeal D = new SolvableIdeal(n.ring, list, true); SolvableIdeal L = N.intersect(D); if (L.getList().size() != 1) { throw new RuntimeException("lcm not uniqe"); } GenSolvablePolynomial lcm = L.getList().get(0); return lcm; } /** * Greatest common divisor. * @param n first solvable polynomial. * @param d second solvable polynomial. * @return gcd(n,d) */ protected GenSolvablePolynomial syzGcd(GenSolvablePolynomial n, GenSolvablePolynomial d) { if (n.isZERO()) { return d; } if (d.isZERO()) { return n; } if (n.isONE()) { return n; } if (d.isONE()) { return d; } GenSolvablePolynomial p = n.multiply(d); GenSolvablePolynomial lcm = syzLcm(n, d); // divide List> Q = new ArrayList>(1); Q.add(ring.getZERO()); List> V = new ArrayList>(1); V.add(lcm); GenSolvablePolynomial x = engine.sred.leftNormalform(Q,V, p); GenSolvablePolynomial y = Q.get(0); // GenSolvablePolynomial gcd = divide(p, lcm); return y; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return ring.isFinite(); } /** * Copy SolvableQuotient element c. * @param c * @return a copy of c. */ public SolvableQuotient copy(SolvableQuotient c) { return new SolvableQuotient(c.ring, c.num, c.den, true); } /** * Get the zero element. * @return 0 as SolvableQuotient. */ public SolvableQuotient getZERO() { return new SolvableQuotient(this, ring.getZERO()); } /** * Get the one element. * @return 1 as SolvableQuotient. */ public SolvableQuotient getONE() { return new SolvableQuotient(this, ring.getONE()); } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List> pgens = PolynomialList. castToSolvableList(ring.generators()); List> gens = new ArrayList>(pgens.size()); for (GenSolvablePolynomial p : pgens) { SolvableQuotient q = new SolvableQuotient(this, p); gens.add(q); } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return ring.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return ring.isAssociative(); } /** * Query if this ring is a field. * @return true. */ public boolean isField() { return true; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return ring.characteristic(); } /** * Get a SolvableQuotient element from a BigInteger value. * @param a BigInteger. * @return a SolvableQuotient. */ public SolvableQuotient fromInteger(java.math.BigInteger a) { return new SolvableQuotient(this, ring.fromInteger(a)); } /** * Get a SolvableQuotient element from a long value. * @param a long. * @return a SolvableQuotient. */ public SolvableQuotient fromInteger(long a) { return new SolvableQuotient(this, ring.fromInteger(a)); } /** * Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { String s = null; if (ring.coFac.characteristic().signum() == 0) { s = "RatFunc"; } else { s = "ModFunc"; } return s + "( " + ring.toString() + " )"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ @Override public String toScript() { // Python case return "SRF(" + ring.toScript() + ")"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof SolvableQuotientRing)) { return false; } SolvableQuotientRing a = null; try { a = (SolvableQuotientRing) b; } catch (ClassCastException e) { } if (a == null) { return false; } return ring.equals(a.ring); } /** * Hash code for this quotient ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); return h; } /** * SolvableQuotient random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random quotient element. */ public SolvableQuotient random(int n) { GenSolvablePolynomial r = (GenSolvablePolynomial) ring.random(n).monic(); GenSolvablePolynomial s = (GenSolvablePolynomial) ring.random(n).monic(); while (s.isZERO()) { s = (GenSolvablePolynomial) ring.random(n).monic(); } return new SolvableQuotient(this, r, s, false); } /** * Generate a random quotient. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @return a random quotient. */ public SolvableQuotient random(int k, int l, int d, float q) { GenSolvablePolynomial r = (GenSolvablePolynomial) ring.random(k, l, d, q).monic(); GenSolvablePolynomial s = (GenSolvablePolynomial) ring.random(k, l, d, q).monic(); while (s.isZERO()) { s = (GenSolvablePolynomial) ring.random(k, l, d, q).monic(); } return new SolvableQuotient(this, r, s, false); } /** * SolvableQuotient random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random quotient element. */ public SolvableQuotient random(int n, Random rnd) { GenSolvablePolynomial r = (GenSolvablePolynomial) ring.random(n, rnd).monic(); GenSolvablePolynomial s = (GenSolvablePolynomial) ring.random(n, rnd).monic(); while (s.isZERO()) { s = (GenSolvablePolynomial) ring.random(n, rnd).monic(); } return new SolvableQuotient(this, r, s, false); } /** * Parse SolvableQuotient from String. Syntax: "{ polynomial | polynomial }" or * "{ polynomial }" or " polynomial | polynomial " or " polynomial " * @param s String. * @return SolvableQuotient from s. */ public SolvableQuotient parse(String s) { int i = s.indexOf("{"); if (i >= 0) { s = s.substring(i + 1); } i = s.lastIndexOf("}"); if (i >= 0) { s = s.substring(0, i); } i = s.indexOf("|"); if (i < 0) { GenSolvablePolynomial n = ring.parse(s); return new SolvableQuotient(this, n); } String s1 = s.substring(0, i); String s2 = s.substring(i + 1); GenSolvablePolynomial n = ring.parse(s1); GenSolvablePolynomial d = ring.parse(s2); return new SolvableQuotient(this, n, d); } /** * Parse SolvableQuotient from Reader. * @param r Reader. * @return next SolvableQuotient from r. */ public SolvableQuotient parse(Reader r) { String s = StringUtil.nextPairedString(r, '{', '}'); return parse(s); } } jas-2.5/src/edu/jas/gbmod/ModGroebnerBaseAbstract.java0000644000175000017500000000454512023071466023112 0ustar giovannigiovanni/* * $Id: ModGroebnerBaseAbstract.java 4178 2012-09-09 10:45:10Z kredel $ */ package edu.jas.gbmod; import java.util.List; import edu.jas.gb.GroebnerBase; import edu.jas.gbufd.GBFactory; import edu.jas.poly.GenPolynomial; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Module Groebner Bases abstract class. Implements Groebner bases and GB test. * @author Heinz Kredel */ public class ModGroebnerBaseAbstract> implements ModGroebnerBase { //private static final Logger logger = Logger.getLogger(ModGroebnerBase.class); /** * Used Groebner base algorithm. */ protected final GroebnerBase bb; /** * Constructor. */ @Deprecated public ModGroebnerBaseAbstract() { bb = GBFactory.getImplementation(); } /** * Constructor. */ public ModGroebnerBaseAbstract(RingFactory cf) { bb = GBFactory.getImplementation(cf); } /** * Module Groebner base test. */ public boolean isGB(int modv, List> F) { return bb.isGB(modv, F); } /** * isGB. * @param M a module basis. * @return true, if M is a Groebner base, else false. */ public boolean isGB(ModuleList M) { if (M == null || M.list == null) { return true; } if (M.rows == 0 || M.cols == 0) { return true; } PolynomialList F = M.getPolynomialList(); int modv = M.cols; // > 0 return bb.isGB(modv, F.list); } /** * Groebner base using pairlist class. */ public List> GB(int modv, List> F) { return bb.GB(modv, F); } /** * GB. * @param M a module basis. * @return GB(M), a Groebner base of M. */ public ModuleList GB(ModuleList M) { ModuleList N = M; if (M == null || M.list == null) { return N; } if (M.rows == 0 || M.cols == 0) { return N; } PolynomialList F = M.getPolynomialList(); int modv = M.cols; List> G = bb.GB(modv, F.list); F = new PolynomialList(F.ring, G); N = F.getModuleList(modv); return N; } } jas-2.5/src/edu/jas/application/0000755000175000017500000000000012140140256016762 5ustar giovannigiovannijas-2.5/src/edu/jas/application/GroebnerSystem.java0000644000175000017500000001374212003750552022610 0ustar giovannigiovanni/* * $Id: GroebnerSystem.java 4031 2012-07-25 10:58:50Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.log4j.Logger; import edu.jas.poly.PolynomialList; import edu.jas.poly.OrderedPolynomialList; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; /** * Container for a Groebner system. * It contains a list of colored systems and a * list of parametric polynomials representing the * corresponding comprehensive Groebner base. * @param coefficient type */ public class GroebnerSystem> { private static final Logger logger = Logger.getLogger(GroebnerSystem.class); private final boolean debug = logger.isDebugEnabled(); /** * List of colored systems. */ public final List> list; /** * List of conditions for this Groebner system. */ protected List> conds; /** * Comprehensive Groebner base for this Groebner system. */ protected PolynomialList> cgb; /** * Constructor for a Groebner system. * @param S a list of colored systems. */ public GroebnerSystem(List> S) { this.list = S; this.conds = null; this.cgb = null; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer("GroebnerSystem: \n"); boolean first = true; for (ColoredSystem cs : list) { if ( first ) { first = false; } else { sb.append("\n"); } sb.append( cs.toString() ); } sb.append("Conditions:\n"); first = true; for ( Condition cond : getConditions() ) { if ( first ) { first = false; } else { sb.append("\n"); } sb.append( cond.toString() ); } sb.append("\n"); if ( cgb == null ) { sb.append("Comprehensive Groebner Base not jet computed\n"); } else { sb.append("Comprehensive Groebner Base:\n"); first = true; for ( GenPolynomial> p : getCGB() ) { if ( first ) { first = false; } else { sb.append(",\n"); } sb.append( p.toString() ); } sb.append("\n"); } return sb.toString(); } /** * Is this Groebner system equal to other. * @param c other Groebner system. * @return true, if this is equal to other, else false. */ @Override @SuppressWarnings("unchecked") public boolean equals(Object c) { GroebnerSystem cs = null; try { cs = (GroebnerSystem) c; } catch (ClassCastException e) { return false; } if (cs == null) { return false; } boolean t = list.equals(cs.list); return t; } /** * Hash code for this colored system. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = list.hashCode(); return h; } /** * Check invariants. Check if all colored systems are determined and * all invariants are met. * @return true, if all invariants are met, else false. */ public boolean checkInvariant() { for (ColoredSystem s : list) { if (!s.checkInvariant()) { return false; } } return true; } /** * Is each colored system completely determined. * @return true, if each ColoredSystem is determined, else false. */ public boolean isDetermined() { for (ColoredSystem s : list) { if (!s.isDetermined()) { return false; } } return true; } /** * Get list of conditions determining this Groebner system. * @return list of determining conditions. */ public List> getConditions() { if ( conds != null ) { return conds; } List> cd = new ArrayList>( list.size() ); for (ColoredSystem cs : list) { cd.add(cs.condition); } conds = cd; return conds; } /** * Get comprehensive Groebner base. * @return the comprehensive Groebner base for this Groebner system. */ public List>> getCGB() { if ( cgb != null ) { return cgb.list; } // assure conditions are collected List> unused = getConditions(); if ( unused.isEmpty() ) { // use for findbugs logger.info("unused is empty"); } // combine for CGB Set>> Gs = new HashSet>>(); for (ColoredSystem cs : list) { if (debug) { if (!cs.isDetermined()) { System.out.println("not determined, cs = " + cs); } if (!cs.checkInvariant()) { System.out.println("not invariant, cs = " + cs); } } for (ColorPolynomial p : cs.list) { GenPolynomial> f = p.getPolynomial(); Gs.add(f); } } List>> G = new ArrayList>>(Gs); GenPolynomialRing> ring = null; if ( G.size() > 0 ) { ring = G.get(0).ring; } cgb = new OrderedPolynomialList>(ring,G); return G; } } jas-2.5/src/edu/jas/application/RunSGB.java0000644000175000017500000002056112032025370020730 0ustar giovannigiovanni/* * $Id: RunSGB.java 4227 2012-09-30 11:20:24Z kredel $ */ package edu.jas.application; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.StringReader; import java.io.IOException; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.BufferedReader; import java.nio.charset.Charset; import java.util.List; import org.apache.log4j.BasicConfigurator; import edu.jas.gb.SolvableGroebnerBase; import edu.jas.gb.SolvableGroebnerBaseParallel; import edu.jas.gb.SolvableGroebnerBaseSeq; import edu.jas.gb.SolvableGroebnerBaseSeqPairParallel; import edu.jas.gb.SolvableReduction; import edu.jas.gb.SolvableReductionPar; import edu.jas.gb.SolvableReductionSeq; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.util.CatReader; /** * Simple setup to run a solvable GB example.
Usage: RunSGB * [seq|par|par+] [irr|left|right|two] <file> #procs * @author Heinz Kredel */ public class RunSGB { /** * main method to be called from commandline
Usage: RunSGB * [seq|par|par+] [irr|left|right|two] <file> #procs */ @SuppressWarnings("unchecked") public static void main(java.lang.String[] args) { BasicConfigurator.configure(); String usage = "Usage: RunSGB " + "[ seq | par | par+ ] " // + "[ seq | par | dist | cli [port] ] " + "[ irr | left | right | two ] " + " " + "#procs "; // + "[machinefile]"; if (args.length < 3) { System.out.println(usage); return; } boolean pairseq = false; String kind = args[0]; String[] allkinds = new String[] { "seq", "par", "par+" }; // String[] allkinds = new String[] { "seq", "par", "dist", "cli" }; boolean sup = false; for (int i = 0; i < allkinds.length; i++) { if (kind.equals(allkinds[i])) { sup = true; if (kind.indexOf("+") >= 0) { pairseq = true; } } } if (!sup) { System.out.println(usage); return; } String[] allmeth = new String[] { "irr", "left", "right", "two" }; String action = args[1]; sup = false; for (int i = 0; i < allmeth.length; i++) { if (action.equals(allmeth[i])) { sup = true; } } if (!sup) { System.out.println(usage); return; } String filename = args[2]; int threads = 0; if (kind.startsWith("par")) { if (args.length < 4) { System.out.println(usage); return; } String tup = args[3]; String t = tup; try { threads = Integer.parseInt(t); } catch (NumberFormatException e) { e.printStackTrace(); System.out.println(usage); return; } if (threads < 1) { threads = 1; } } Reader problem = null; try { problem = new InputStreamReader(new FileInputStream(filename),Charset.forName("UTF8")); problem = new BufferedReader(problem); } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println(usage); return; } RingFactoryTokenizer rftok = new RingFactoryTokenizer(problem); GenSolvablePolynomialRing spfac = null; try { spfac = rftok.nextSolvablePolynomialRing(); rftok = null; } catch (IOException e) { e.printStackTrace(); return; } Reader polyreader = new CatReader(new StringReader("("),problem); // ( has gone GenPolynomialTokenizer tok = new GenPolynomialTokenizer(spfac,polyreader); PolynomialList S = null; try { S = new PolynomialList(spfac,tok.nextSolvablePolynomialList()); } catch (IOException e) { e.printStackTrace(); return; } System.out.println("S =\n" + S); if (kind.startsWith("seq")) { runSequential(S, action, pairseq); } if (kind.startsWith("par")) { runParallel(S, threads, action, pairseq); } } /** * run Sequential. * @param S polynomial list. * @param action what to to. */ @SuppressWarnings("unchecked") static void runSequential(PolynomialList S, String action, boolean pairseq) { List L = S.list; List G = null; long t; SolvableReduction sred = new SolvableReductionSeq(); SolvableGroebnerBase sbb = null; if (pairseq) { //sbb = new SolvableGroebnerBaseSeqPairSeq(); System.out .println("SolvableGroebnerBaseSeqPairSeq not implemented using SolvableGroebnerBaseSeq"); sbb = new SolvableGroebnerBaseSeq(); } else { sbb = new SolvableGroebnerBaseSeq(); } t = System.currentTimeMillis(); System.out.println("\nSolvable GB [" + action + "] sequential ..."); if (action.equals("irr")) { G = sred.leftIrreducibleSet(L); } if (action.equals("left")) { G = sbb.leftGB(L); } if (action.equals("right")) { G = sbb.rightGB(L); } if (action.equals("two")) { G = sbb.twosidedGB(L); } if (G == null) { System.out.println("unknown action = " + action + "\n"); return; } S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); t = System.currentTimeMillis() - t; if (pairseq) { System.out.print("seq+, "); } else { System.out.print("seq, "); } System.out.println("time = " + t + " milliseconds"); System.out.println(""); } /** * run Parallel. * @param S polynomial list. * @param action what to to. */ @SuppressWarnings("unchecked") static void runParallel(PolynomialList S, int threads, String action, boolean pairseq) { List L = S.list; List G = null; long t; SolvableReduction sred = new SolvableReductionPar(); SolvableGroebnerBaseParallel sbb = null; SolvableGroebnerBaseSeqPairParallel sbbs = null; if (pairseq) { sbbs = new SolvableGroebnerBaseSeqPairParallel(threads); } else { sbb = new SolvableGroebnerBaseParallel(threads); } t = System.currentTimeMillis(); System.out.println("\nSolvable GB [" + action + "] parallel " + threads + " threads ..."); if (action.equals("irr")) { G = sred.leftIrreducibleSet(L); } if (action.equals("left")) { if (pairseq) { G = sbbs.leftGB(L); } else { G = sbb.leftGB(L); } } if (action.equals("right")) { if (pairseq) { G = sbbs.rightGB(L); } else { G = sbb.rightGB(L); } } if (action.equals("two")) { if (pairseq) { G = sbbs.twosidedGB(L); } else { G = sbb.twosidedGB(L); } } if (G == null) { System.out.println("unknown action = " + action + "\n"); return; } if (G.size() > 0) { S = new PolynomialList(G.get(0).ring, G); } else { S = new PolynomialList(S.ring, G); } System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); t = System.currentTimeMillis() - t; if (pairseq) { System.out.print("p+ "); } else { System.out.print("p "); } System.out.println("= " + threads + ", time = " + t + " milliseconds"); System.out.println(""); if (pairseq) { sbbs.terminate(); } else { sbb.terminate(); } } } jas-2.5/src/edu/jas/application/Local.java0000644000175000017500000003043012014234362020661 0ustar giovannigiovanni/* * $Id: Local.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.application; import org.apache.log4j.Logger; import edu.jas.kern.PrettyPrint; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; /** * Local ring element based on GenPolynomial with RingElem interface. Objects of * this class are (nearly) immutable. * @author Heinz Kredel * @fix Not jet working because of monic GBs. */ public class Local> implements RingElem> { private static final Logger logger = Logger.getLogger(Local.class); private final boolean debug = logger.isDebugEnabled(); /** * Local class factory data structure. */ public final LocalRing ring; /** * Numerator part of the element data structure. */ protected final GenPolynomial num; /** * Denominator part of the element data structure. */ protected final GenPolynomial den; /** * Flag to remember if this local element is a unit. -1 is unknown, 1 is * unit, 0 not a unit. */ protected int isunit = -1; // initially unknown /** * The constructor creates a Local object from a ring factory. * @param r ring factory. */ public Local(LocalRing r) { this(r, r.ring.getZERO()); } /** * The constructor creates a Local object from a ring factory and a * numerator polynomial. The denominator is assumed to be 1. * @param r ring factory. * @param n numerator polynomial. */ public Local(LocalRing r, GenPolynomial n) { this(r, n, r.ring.getONE(), true); } /** * The constructor creates a Local object from a ring factory and a * numerator and denominator polynomial. * @param r ring factory. * @param n numerator polynomial. * @param d denominator polynomial. */ public Local(LocalRing r, GenPolynomial n, GenPolynomial d) { this(r, n, d, false); } /** * The constructor creates a Local object from a ring factory and a * numerator and denominator polynomial. * @param r ring factory. * @param n numerator polynomial. * @param d denominator polynomial. * @param isred true if gcd(n,d) == 1, else false. */ protected Local(LocalRing r, GenPolynomial n, GenPolynomial d, boolean isred) { if (d == null || d.isZERO()) { throw new IllegalArgumentException("denominator may not be zero"); } ring = r; if (d.signum() < 0) { n = n.negate(); d = d.negate(); } if (isred) { num = n; den = d; return; } GenPolynomial p = ring.ideal.normalform(d); if (p == null || p.isZERO()) { throw new IllegalArgumentException("denominator may not be in ideal"); } //d = p; cant do this // must reduce to lowest terms //GenPolynomial gcd = ring.ring.getONE(); GenPolynomial gcd = gcd(n, d); if (debug) { logger.info("gcd = " + gcd); } if (gcd.isONE()) { num = n; den = d; } else { // d not in ideal --> gcd not in ideal //p = ring.ideal.normalform( gcd ); //if ( p == null || p.isZERO() ) { // todo: find nonzero factor // num = n; // den = d; //} else { num = n.divide(gcd); den = d.divide(gcd); //} } } /** * Least common multiple. * @param n first polynomial. * @param d second polynomial. * @return lcm(n,d) */ protected GenPolynomial lcm(GenPolynomial n, GenPolynomial d) { GenPolynomial lcm = ring.engine.lcm(n, d); return lcm; } /** * Greatest common divisor. Just for fun, is not efficient. * @param n first polynomial. * @param d second polynomial. * @return gcd(n,d) */ protected GenPolynomial gcd(GenPolynomial n, GenPolynomial d) { if (n.isZERO()) { return d; } if (d.isZERO()) { return n; } if (n.isONE()) { return n; } if (d.isONE()) { return d; } GenPolynomial gcd = ring.engine.gcd(n, d); return gcd; } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public LocalRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public Local copy() { return new Local(ring, num, den, true); } /** * Is Local zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return num.isZERO(); } /** * Is Local one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return num.equals(den); } /** * Is Local unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (isunit > 0) { return true; } if (isunit == 0) { return false; } // not jet known if (num.isZERO()) { isunit = 0; return false; } GenPolynomial p = ring.ideal.normalform(num); boolean u = (p != null && !p.isZERO()); if (u) { isunit = 1; } else { isunit = 0; } return (u); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { if (PrettyPrint.isTrue()) { String s = "{ " + num.toString(ring.ring.getVars()); if (den.isONE()) { return s + " }"; } return s + "| " + den.toString(ring.ring.getVars()) + " }"; } return "Local[ " + num.toString() + " | " + den.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case if (den.isONE()) { return num.toScript(); } return num.toScript() + " / " + den.toScript(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Local comparison. * @param b Local. * @return sign(this-b). */ //JAVA6only: @Override public int compareTo(Local b) { if (b == null || b.isZERO()) { return this.signum(); } GenPolynomial r = num.multiply(b.den); GenPolynomial s = den.multiply(b.num); GenPolynomial x = r.subtract(s); return x.signum(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @SuppressWarnings("unchecked") // not jet working @Override public boolean equals(Object b) { if (!(b instanceof Local)) { return false; } Local a = null; try { a = (Local) b; } catch (ClassCastException e) { } if (a == null) { return false; } return (0 == compareTo(a)); } /** * Hash code for this local. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + num.hashCode(); h = 37 * h + den.hashCode(); return h; } /** * Local absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public Local abs() { return new Local(ring, num.abs(), den, true); } /** * Local summation. * @param S Local. * @return this+S. */ public Local sum(Local S) { if (S == null || S.isZERO()) { return this; } GenPolynomial n = num.multiply(S.den); n = n.sum(den.multiply(S.num)); GenPolynomial d = den.multiply(S.den); return new Local(ring, n, d, false); } /** * Local negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public Local negate() { return new Local(ring, num.negate(), den, true); } /** * Local signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { return num.signum(); } /** * Local subtraction. * @param S Local. * @return this-S. */ public Local subtract(Local S) { if (S == null || S.isZERO()) { return this; } GenPolynomial n = num.multiply(S.den); n = n.subtract(den.multiply(S.num)); GenPolynomial d = den.multiply(S.den); return new Local(ring, n, d, false); } /** * Local division. * @param S Local. * @return this/S. */ public Local divide(Local S) { return multiply(S.inverse()); } /** * Local inverse. * @see edu.jas.structure.RingElem#inverse() * @return S with S = 1/this if defined. */ public Local inverse() { if (isONE()) { return this; } if (isUnit()) { return new Local(ring, den, num, true); } throw new ArithmeticException("element not invertible " + this); } /** * Local remainder. * @param S Local. * @return this - (this/S)*S. */ public Local remainder(Local S) { if (num.isZERO()) { throw new ArithmeticException("element not invertible " + this); } if (S.isUnit()) { return ring.getZERO(); } throw new UnsupportedOperationException("remainder not implemented" + S); } /** * Local multiplication. * @param S Local. * @return this*S. */ public Local multiply(Local S) { if (S == null || S.isZERO()) { return S; } if (num.isZERO()) { return this; } if (S.isONE()) { return this; } if (this.isONE()) { return S; } GenPolynomial n = num.multiply(S.num); GenPolynomial d = den.multiply(S.den); return new Local(ring, n, d, false); } /** * Local monic. * @return this with monic value part. */ public Local monic() { if (num.isZERO()) { return this; } C lbc = num.leadingBaseCoefficient(); lbc = lbc.inverse(); GenPolynomial n = num.multiply(lbc); GenPolynomial d = den.multiply(lbc); return new Local(ring, n, d, true); } /** * Greatest common divisor. * @param b other element. * @return gcd(this,b). */ public Local gcd(Local b) { GenPolynomial x = ring.engine.gcd(num, b.num); GenPolynomial y = ring.engine.gcd(den, b.den); return new Local(ring, x, y, true); // throw new UnsupportedOperationException("gcd not implemented " + this.getClass().getName()); } /** * Extended greatest common divisor. Note: Not implemented, throws * UnsupportedOperationException. * @param b other element. * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). */ public Local[] egcd(Local b) { throw new UnsupportedOperationException("egcd not implemented " + this.getClass().getName()); } } jas-2.5/src/edu/jas/application/OrderedCPairlist.java0000644000175000017500000003035212014237062023031 0ustar giovannigiovanni/* * $Id: OrderedCPairlist.java 4127 2012-08-19 19:27:47Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.ArrayList; import java.util.BitSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Pair list management. Implemented for ColorPolynomials using TreeMap and * BitSet. * @author Heinz Kredel */ public class OrderedCPairlist> implements Serializable { private static final Logger logger = Logger.getLogger(OrderedCPairlist.class); protected final GenPolynomialRing> ring; protected final List> P; protected final SortedMap>> pairlist; protected final List red; protected final CReductionSeq reduction; protected boolean oneInGB = false; protected boolean useCriterion4 = false; // unused protected int putCount; protected int remCount; protected final int moduleVars; // unused /** * Constructor for OrderedPairlist. * @param r polynomial factory. */ public OrderedCPairlist(GenPolynomialRing> r) { this(0, r); } /** * Constructor for OrderedPairlist. * @param m number of module variables. * @param r polynomial factory. */ public OrderedCPairlist(int m, GenPolynomialRing> r) { moduleVars = m; ring = r; P = new ArrayList>(); pairlist = new TreeMap>>(ring.tord.getAscendComparator()); // pairlist = new TreeMap( to.getSugarComparator() ); red = new ArrayList(); putCount = 0; remCount = 0; if (ring instanceof GenSolvablePolynomialRing) { useCriterion4 = false; } RingFactory> rf = ring.coFac; GenPolynomialRing cf = (GenPolynomialRing) rf; reduction = new CReductionSeq(cf.coFac); } /** * Internal constructor for OrderedPairlist. Used to clone this pair list. * @param m number of module variables. * @param r polynomial factory. */ private OrderedCPairlist(int m, GenPolynomialRing> ring, List> P, SortedMap>> pl, List red, CReductionSeq cred, int pc, int rc) { moduleVars = m; this.ring = ring; this.P = P; pairlist = pl; this.red = red; reduction = cred; putCount = pc; remCount = rc; } /** * Clone this OrderedPairlist. * @return a 2 level clone of this. */ public synchronized OrderedCPairlist copy() { return new OrderedCPairlist(moduleVars, ring, new ArrayList>(P), clonePairlist(), cloneBitSet(), reduction, putCount, remCount); } /** * Clone this pairlist. * @return a 2 level clone of this pairlist. */ private SortedMap>> clonePairlist() { SortedMap>> pl = new TreeMap>>( ring.tord.getAscendComparator()); for (Map.Entry>> m : pairlist.entrySet()) { ExpVector e = m.getKey(); LinkedList> l = m.getValue(); l = new LinkedList>(l); pl.put(e, l); } return pl; } /** * Count remaining Pairs. * @return number of pairs remaining in this pairlist. */ public int pairCount() { int c = 0; for (Map.Entry>> m : pairlist.entrySet()) { LinkedList> l = m.getValue(); c += l.size(); } return c; } /** * Clone this reduction BitSet. * @return a 2 level clone of this reduction BitSet. */ private List cloneBitSet() { List r = new ArrayList(this.red.size()); for (BitSet b : red) { BitSet n = (BitSet) b.clone(); r.add(n); } return r; } /** * bitCount. * @return number of bits set in this bitset. */ public int bitCount() { int c = 0; for (BitSet b : red) { c += b.cardinality(); } return c; } /** * toString. * @return counters of this. */ @Override public String toString() { int p = pairCount(); int b = bitCount(); if (p != b) { return "OrderedCPairlist( pairCount=" + p + ", bitCount=" + b + ", putCount=" + putCount + ", remCount=" + remCount + " )"; } return "OrderedCPairlist( pairCount=" + p + ", putCount=" + putCount + ", remCount=" + remCount + " )"; } /** * Equals. * @param ob an Object. * @return true if this is equal to o, else false. */ @Override @SuppressWarnings("unchecked") public boolean equals(Object ob) { OrderedCPairlist c = null; try { c = (OrderedCPairlist) ob; } catch (ClassCastException e) { return false; } if (c == null) { return false; } boolean t = getList().equals(c.getList()); if (!t) { return t; } t = pairCount() == c.pairCount(); if (!t) { return t; } return true; } /** * Hash code for this pair list. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = getList().hashCode(); h = h << 7; h += pairCount(); // findbugs return h; } /** * Put one Polynomial to the pairlist and reduction matrix. * @param p polynomial. * @return the index of the added polynomial. */ public synchronized int put(ColorPolynomial p) { putCount++; if (oneInGB) { return P.size() - 1; } ExpVector e = p.leadingExpVector(); // System.out.println("p = " + p); int l = P.size(); for (int j = 0; j < l; j++) { ColorPolynomial pj = P.get(j); // System.out.println("pj = " + pj); ExpVector f = pj.leadingExpVector(); if (moduleVars > 0) { if (e.invLexCompareTo(f, 0, moduleVars) != 0) { continue; // skip pair } } // System.out.println("e = " + e + ", f = " + f); ExpVector g = e.lcm(f); // EVLCM( e, f ); CPair pair = new CPair(pj, p, j, l); // redi = (BitSet)red.get(j); // /if ( j < l ) redi.set( l ); // System.out.println("bitset."+j+" = " + redi ); // multiple pairs under same keys -> list of pairs LinkedList> xl = pairlist.get(g); if (xl == null) { xl = new LinkedList>(); } // xl.addLast( pair ); // first or last ? xl.addFirst(pair); // first or last ? better for d- e-GBs pairlist.put(g, xl); } // System.out.println("pairlist.keys@put = " + pairlist.keySet() ); P.add(p); BitSet redi = new BitSet(); redi.set(0, l); // jdk 1.4 red.add(redi); return P.size() - 1; } /** * Remove the next required pair from the pairlist and reduction matrix. * Appy the criterions 3 and 4 to see if the S-polynomial is required. * @return the next pair if one exists, otherwise null. */ public synchronized CPair removeNext() { if (oneInGB) { return null; } Iterator>>> ip = pairlist.entrySet().iterator(); CPair pair = null; boolean c = false; int i, j; while (!c && ip.hasNext()) { Map.Entry>> me = ip.next(); ExpVector g = me.getKey(); LinkedList> xl = me.getValue(); if (logger.isInfoEnabled()) logger.info("g = " + g); pair = null; while (!c && xl.size() > 0) { pair = xl.removeFirst(); // xl is also modified in pairlist i = pair.i; j = pair.j; // System.out.println("pair(" + j + "," +i+") "); //if (useCriterion4) { // c = reduction.criterion4( pair.pi, pair.pj, g ); // c = true; //} c = true; // System.out.println("c4 = " + c); //if (c) { // c = criterion3( i, j, g ); // System.out.println("c3 = " + c); //} red.get(j).clear(i); // set(i,false) jdk1.4 } if (xl.size() == 0) ip.remove(); // = pairlist.remove( g ); } if (!c) { pair = null; } else { remCount++; // count only real pairs } return pair; } /** * Test if there is possibly a pair in the list. * @return true if a next pair could exist, otherwise false. */ public synchronized boolean hasNext() { return pairlist.size() > 0; } /** * Get the list of polynomials. * @return the polynomial list. */ public List> getList() { return P; } /** * Get the number of polynomials put to the pairlist. * @return the number of calls to put. */ public synchronized int putCount() { return putCount; } /** * Get the number of required pairs removed from the pairlist. * @return the number of non null pairs delivered. */ public synchronized int remCount() { return remCount; } /** * Put to ONE-Polynomial to the pairlist. * @param one polynomial. (no more required) * @return the index of the last polynomial. */ public synchronized int putOne(ColorPolynomial one) { putCount++; if (one == null) { return P.size() - 1; } if (!one.isONE()) { return P.size() - 1; } oneInGB = true; pairlist.clear(); P.clear(); P.add(one); red.clear(); return P.size() - 1; } /** * GB criterium 3. * @return true if the S-polynomial(i,j) is required. */ public boolean criterion3(int i, int j, ExpVector eij) { // assert i < j; boolean s = red.get(j).get(i); if (!s) { logger.warn("c3.s false for " + j + " " + i); return s; } // now s = true; for (int k = 0; k < P.size(); k++) { if (i != k && j != k) { ColorPolynomial A = P.get(k); ExpVector ek = A.leadingExpVector(); boolean m = eij.multipleOf(ek); // EVMT(eij,ek); if (m) { if (k < i) { // System.out.println("k < i "+k+" "+i); s = red.get(i).get(k) || red.get(j).get(k); } else if (i < k && k < j) { // System.out.println("i < k < j "+i+" "+k+" "+j); s = red.get(k).get(i) || red.get(j).get(k); } else if (j < k) { // System.out.println("j < k "+j+" "+k); s = red.get(k).get(i) || red.get(k).get(j); } // System.out.println("s."+k+" = " + s); if (!s) { return s; } } } } return true; } } jas-2.5/src/edu/jas/application/IdealWithComplexAlgebraicRoots.java0000644000175000017500000001101112004024570025641 0ustar giovannigiovanni/* * $Id: IdealWithComplexAlgebraicRoots.java 4050 2012-07-25 17:14:32Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import edu.jas.arith.BigDecimal; import edu.jas.arith.Rational; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; //import edu.jas.root.RealAlgebraicNumber; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; /** * Container for Ideals together with univariate polynomials and complex algebraic * roots. * @author Heinz Kredel */ public class IdealWithComplexAlgebraicRoots & Rational> extends IdealWithUniv { /** * The list of complex algebraic roots. */ public final List>>> can; /** * The list of decimal approximations of the complex algebraic roots. */ protected List>> droots = null; /** * Constructor not for use. */ protected IdealWithComplexAlgebraicRoots() { throw new IllegalArgumentException("do not use this constructor"); } /** * Constructor. * @param id the ideal * @param up the list of univariate polynomials * @param cr the list of complex algebraic roots */ public IdealWithComplexAlgebraicRoots(Ideal id, List> up, List>>> cr) { super(id, up); can = cr; } /** * Constructor. * @param iu the ideal with univariate polynomials * @param cr the list of real algebraic roots */ public IdealWithComplexAlgebraicRoots(IdealWithUniv iu, List>>> cr) { super(iu.ideal, iu.upolys); can = cr; } /** * String representation of the ideal. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(super.toString() + "\ncomplex roots:\n"); sb.append("["); boolean f1 = true; for (List>> lr : can) { if (!f1) { sb.append(", "); } else { f1 = false; } sb.append("["); boolean f2 = true; for (Complex> rr : lr) { if (!f2) { sb.append(", "); } else { f2 = false; } sb.append(rr.ring.toScript()); } sb.append("]"); } sb.append("]"); if (droots != null) { sb.append("\ndecimal complex root approximation:\n"); for (List> d : droots) { sb.append(d.toString()); sb.append("\n"); } } return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ @Override public String toScript() { // Python case return super.toScript() + ", " + can.toString(); } /** * Get decimal approximation of the real root tuples. */ public synchronized List>> decimalApproximation() { if (this.droots != null) { return droots; } List>> rroots = new ArrayList>>(); ComplexRing cfac = new ComplexRing(new BigDecimal()); for (List>> rri : this.can) { List> r = new ArrayList>(); for (Complex> rr : rri) { BigDecimal dr = new BigDecimal(rr.getRe().magnitude()); BigDecimal di = new BigDecimal(rr.getIm().magnitude()); Complex d = new Complex(cfac,dr,di); r.add(d); } rroots.add(r); } droots = rroots; return rroots; } /** * compute decimal approximation of the real root tuples. */ public void doDecimalApproximation() { List>> unused = decimalApproximation(); if ( unused.isEmpty() ) { // use for findbugs System.out.println("unused is empty"); } return; } } jas-2.5/src/edu/jas/application/Examples.java0000644000175000017500000004743411713531570021427 0ustar giovannigiovanni/* * $Id: Examples.java 3879 2012-02-05 16:51:04Z kredel $ */ package edu.jas.application; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.List; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.gb.GroebnerBase; import edu.jas.gbufd.GBFactory; import edu.jas.gbufd.RGroebnerBasePseudoSeq; import edu.jas.gbufd.RReductionSeq; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; /** * Examples for application usage. * @author Christoph Zengler. * @author Heinz Kredel. */ public class Examples { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); if (args.length > 0) { example1(); example2(); example3(); example4(); } example5(); example6(); ComputerThreads.terminate(); } /** * example1. cyclic n-th roots polynomial systems. */ public static void example1() { int n = 4; BigInteger fac = new BigInteger(); GenPolynomialRing ring = new GenPolynomialRing(fac, n); //,var); System.out.println("ring = " + ring + "\n"); List> cp = new ArrayList>(n); for (int i = 1; i <= n; i++) { GenPolynomial p = cyclicPoly(ring, n, i); cp.add(p); System.out.println("p[" + i + "] = " + p); System.out.println(); } System.out.println("cp = " + cp + "\n"); List> gb; //GroebnerBase sgb = new GroebnerBaseSeq(); GroebnerBase sgb = GBFactory.getImplementation(fac); gb = sgb.GB(cp); System.out.println("gb = " + gb); } static GenPolynomial cyclicPoly(GenPolynomialRing ring, int n, int i) { List> X = /*(List>)*/ring .univariateList(); GenPolynomial p = ring.getZERO(); for (int j = 1; j <= n; j++) { GenPolynomial pi = ring.getONE(); for (int k = j; k < j + i; k++) { pi = pi.multiply(X.get(k % n)); } p = p.sum(pi); if (i == n) { p = p.subtract(ring.getONE()); break; } } return p; } /** * example2. abtract types: * List>>>. */ public static void example2() { List>>> L = null; L = new ArrayList>>>(); BigRational bfac = new BigRational(1); GenPolynomialRing pfac = null; pfac = new GenPolynomialRing(bfac, 3); List> F = null; F = new ArrayList>(); GenPolynomial p = null; for (int i = 0; i < 2; i++) { p = pfac.random(5, 4, 3, 0.4f); if (!p.isConstant()) { F.add(p); } } //System.out.println("F = " + F); Ideal id = new Ideal(pfac, F); id.doGB(); if (id.isONE() || id.isZERO()) { System.out.println("id zero or one = " + id); return; } ResidueRing rr = new ResidueRing(id); System.out.println("rr = " + rr); ProductRing> pr = null; pr = new ProductRing>(rr, 3); String[] vars = new String[] { "a", "b" }; GenPolynomialRing>> fac; fac = new GenPolynomialRing>>(pr, 2, vars); GenPolynomial>> pp; for (int i = 0; i < 1; i++) { pp = fac.random(2, 4, 4, 0.4f); if (!pp.isConstant()) { L.add(pp); } } System.out.println("L = " + L); //PolynomialList>> Lp = null; //Lp = new PolynomialList>>(fac,L); //System.out.println("Lp = " + Lp); GroebnerBase>> bb = new RGroebnerBasePseudoSeq>>( pr); System.out.println("isGB(L) = " + bb.isGB(L)); List>>> G = null; G = bb.GB(L); System.out.println("G = " + G); System.out.println("isGB(G) = " + bb.isGB(G)); } /** * example3. abtract types: GB of List>>. */ public static void example3() { List>> L = null; L = new ArrayList>>(); BigRational bfac = new BigRational(1); GenPolynomialRing pfac = null; pfac = new GenPolynomialRing(bfac, 2); List> F = null; F = new ArrayList>(); GenPolynomial p = null; for (int i = 0; i < 2; i++) { p = pfac.random(5, 5, 5, 0.4f); //p = pfac.parse("x0^2 -2" ); if (!p.isConstant()) { F.add(p); } } //System.out.println("F = " + F); Ideal id = new Ideal(pfac, F); id.doGB(); if (id.isONE() || id.isZERO()) { System.out.println("id zero or one = " + id); return; } ResidueRing rr = new ResidueRing(id); System.out.println("rr = " + rr); String[] vars = new String[] { "a", "b" }; GenPolynomialRing> fac; fac = new GenPolynomialRing>(rr, 2, vars); GenPolynomial> pp; for (int i = 0; i < 2; i++) { pp = fac.random(2, 4, 6, 0.2f); if (!pp.isConstant()) { L.add(pp); } } System.out.println("L = " + L); GroebnerBase> bb; //bb = new GroebnerBasePseudoSeq>(rr); bb = GBFactory.getImplementation(rr); System.out.println("isGB(L) = " + bb.isGB(L)); List>> G = null; G = bb.GB(L); System.out.println("G = " + G); System.out.println("isGB(G) = " + bb.isGB(G)); } /** * example4. abtract types: comprehensive GB of * List>>. */ public static void example4() { int kl = 2; int ll = 3; int el = 3; float q = 0.2f; //0.4f GenPolynomialRing cfac; GenPolynomialRing> fac; List>> L; ComprehensiveGroebnerBaseSeq bb; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; BigRational coeff = new BigRational(kl); String[] cv = { "a", "b" }; cfac = new GenPolynomialRing(coeff, 2, cv); String[] v = { "x", "y" }; fac = new GenPolynomialRing>(cfac, 2, v); bb = new ComprehensiveGroebnerBaseSeq(coeff); L = new ArrayList>>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = a; //c = fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); System.out.println("CGB exam L = " + L); L = bb.GB(L); System.out.println("CGB( L ) = " + L); System.out.println("isCGB( L ) = " + bb.isGB(L)); L.add(b); System.out.println("CGB exam L = " + L); L = bb.GB(L); System.out.println("CGB( L ) = " + L); System.out.println("isCGB( L ) = " + bb.isGB(L)); L.add(c); System.out.println("CGB exam L = " + L); L = bb.GB(L); System.out.println("CGB( L ) = " + L); System.out.println("isCGB( L ) = " + bb.isGB(L)); } /** * example5. comprehensive GB of * List>> and GB for regular ring. */ public static void example5() { int kl = 2; int ll = 4; int el = 3; float q = 0.3f; //0.4f GenPolynomialRing cfac; GenPolynomialRing> fac; List>> L; ComprehensiveGroebnerBaseSeq bb; GenPolynomial> a; GenPolynomial> b; GenPolynomial> c; BigRational coeff = new BigRational(kl); String[] cv = { "a", "b" }; cfac = new GenPolynomialRing(coeff, 2, cv); String[] v = { "x", "y" }; fac = new GenPolynomialRing>(cfac, 2, v); bb = new ComprehensiveGroebnerBaseSeq(coeff); L = new ArrayList>>(); a = fac.random(kl, ll, el, q); b = fac.random(kl, ll, el, q); c = a; //c = fac.random(kl, ll, el, q ); if (a.isZERO() || b.isZERO() || c.isZERO()) { return; } L.add(a); L.add(b); L.add(c); System.out.println("CGB exam L = " + L); GroebnerSystem sys = bb.GBsys(L); boolean ig = bb.isGB(sys.getCGB()); System.out.println("CGB( L ) = " + sys.getCGB()); System.out.println("isCGB( L ) = " + ig); List>>> Lr, bLr; RReductionSeq>> res = new RReductionSeq>>(); Lr = PolyUtilApp. toProductRes(sys.list); bLr = res.booleanClosure(Lr); System.out.println("booleanClosed(Lr) = " + bLr); if (bLr.size() > 0) { GroebnerBase>> rbb = new RGroebnerBasePseudoSeq>>( bLr.get(0).ring.coFac); System.out.println("isRegularGB(Lr) = " + rbb.isGB(bLr)); } } /** * Example GBase and real root. */ @SuppressWarnings("unchecked") public static void example6() { BigRational coeff = new BigRational(); GroebnerBase gb = GBFactory.getImplementation(coeff); String exam = "(x,y,z) L " + "( " + "( x^2 - 2 ), ( y^2 - 3 ), ( z^2 + x * y )" + ") "; Reader source = new StringReader(exam); GenPolynomialTokenizer parser = new GenPolynomialTokenizer(source); PolynomialList F = null; try { F = (PolynomialList) parser.nextPolynomialSet(); } catch (ClassCastException e) { e.printStackTrace(); return; } catch (IOException e) { e.printStackTrace(); return; } System.out.println("F = " + F); List> G = gb.GB(F.list); PolynomialList Gp = new PolynomialList(F.ring, G); System.out.println("G = " + Gp); // compute real roots of the ideal Ideal I = new Ideal(Gp); List> Ir = PolyUtilApp. realAlgebraicRoots(I); for (IdealWithRealAlgebraicRoots R : Ir) { R.doDecimalApproximation(); for (List Dr : R.decimalApproximation()) { System.out.println(Dr.toString()); } System.out.println(); } } /** * example7. Coefficients in Boolean residue class ring. */ public static void example7() { String[] vars = { "v3", "v2", "v1" }; ModIntegerRing z2 = new ModIntegerRing(2); GenPolynomialRing z2p = new GenPolynomialRing(z2, vars.length, new TermOrder( TermOrder.INVLEX), vars); List> fieldPolynomials = new ArrayList>(); //add v1^2 + v1, v2^2 + v2, v3^2 + v3 to fieldPolynomials for (int i = 0; i < vars.length; i++) { GenPolynomial var = z2p.univariate(i); fieldPolynomials.add(var.multiply(var).sum(var)); } Ideal fieldPolys = new Ideal(z2p, fieldPolynomials); ResidueRing ring = new ResidueRing(fieldPolys); String[] mvars = { "mv3", "mv2", "mv1" }; GenPolynomialRing> ringp = new GenPolynomialRing>(ring, mvars.length, mvars); List>> polynomials = new ArrayList>>(); GenPolynomial> v1 = ringp.univariate(0); GenPolynomial> v2 = ringp.univariate(1); GenPolynomial> v3 = ringp.univariate(2); GenPolynomial> notV1 = v1.sum(ringp.ONE); GenPolynomial> notV2 = v2.sum(ringp.ONE); GenPolynomial> notV3 = v3.sum(ringp.ONE); //v1*v2 GenPolynomial> p1 = v1.multiply(v2); //v1*v2 + v1 + v2 + 1 GenPolynomial> p2 = notV1.multiply(notV2); //v1*v3 + v1 + v3 + 1 GenPolynomial> p3 = notV1.multiply(notV3); polynomials.add(p1); polynomials.add(p2); polynomials.add(p3); //GroebnerBase> gb = new GroebnerBasePseudoSeq>(ring); GroebnerBase> gb = GBFactory.getImplementation(ring); List>> G = gb.GB(polynomials); System.out.println(G); } /** * example8. Coefficients in Boolean residue class ring with cuppling of * variables. */ public static void example8() { String[] vars = { "v3", "v2", "v1" }; ModIntegerRing z2 = new ModIntegerRing(2); GenPolynomialRing z2p = new GenPolynomialRing(z2, vars.length, new TermOrder( TermOrder.INVLEX), vars); List> fieldPolynomials = new ArrayList>(); //add v1^2 + v1, v2^2 + v2, v3^2 + v3 to fieldPolynomials for (int i = 0; i < vars.length; i++) { GenPolynomial var = z2p.univariate(i); fieldPolynomials.add(var.multiply(var).sum(var)); } Ideal fieldPolys = new Ideal(z2p, fieldPolynomials); ResidueRing ring = new ResidueRing(fieldPolys); String[] mvars = { "mv3", "mv2", "mv1" }; GenPolynomialRing> ringp = new GenPolynomialRing>(ring, mvars.length, mvars); List>> polynomials = new ArrayList>>(); GenPolynomial> v1 = ringp.univariate(0); GenPolynomial> v2 = ringp.univariate(1); GenPolynomial> v3 = ringp.univariate(2); GenPolynomial> notV1 = v1.sum(ringp.ONE); GenPolynomial> notV2 = v2.sum(ringp.ONE); GenPolynomial> notV3 = v3.sum(ringp.ONE); //v1*v2 GenPolynomial> p1 = v1.multiply(v2); //v1*v2 + v1 + v2 + 1 GenPolynomial> p2 = notV1.multiply(notV2); //v1*v3 + v1 + v3 + 1 GenPolynomial> p3 = notV1.multiply(notV3); polynomials.add(p1); polynomials.add(p2); polynomials.add(p3); List> gens = ring.generators(); System.out.println("gens = " + gens); GenPolynomial> mv3v3 = v3.subtract(gens.get(1)); GenPolynomial> mv2v2 = v2.subtract(gens.get(2)); GenPolynomial> mv1v1 = v1.subtract(gens.get(3)); System.out.println("mv3v3 = " + mv3v3); System.out.println("mv2v2 = " + mv2v2); System.out.println("mv1v1 = " + mv1v1); polynomials.add(mv3v3); polynomials.add(mv2v2); polynomials.add(mv1v1); //GroebnerBase> gb = new GroebnerBasePseudoSeq>(ring); GroebnerBase> gb = GBFactory.getImplementation(ring); List>> G = gb.GB(polynomials); System.out.println(G); } /** * example9. Groebner base and dimension. */ public static void example9() { String[] vars = { "d1", "d2", "d3", "p1a", "p1b", "p1c", "p2a", "p2b", "p2c", "p3a", "p3b", "p3c", "p4a", "p4b", "p4c", "A", "B", "C", "D" }; BigRational br = new BigRational(); GenPolynomialRing pring = new GenPolynomialRing(br, vars); //GenPolynomialRing pring = new GenPolynomialRing(br, vars.length, new TermOrder(TermOrder.INVLEX), vars); GenPolynomial e1 = pring.parse("A*p1a+B*p1b+C*p1c+D"); // (1) GenPolynomial e2 = pring.parse("A*p2a+B*p2b+C*p2c+D"); // (2) GenPolynomial e3 = pring.parse("A*p3a+B*p3b+C*p3c+D"); // (3) GenPolynomial e4 = pring.parse("A*p4a+B*p4b+C*p4c+D"); // (4) GenPolynomial e5 = pring.parse("p2a-p3a"); // (5) GenPolynomial e6 = pring.parse("p2b-p3b"); // (6) GenPolynomial e7 = pring.parse("p2c-p3c"); // (7) GenPolynomial e8 = pring.parse("(p2a-p1a)^2+(p2b-p1b)^2+(p2c-p1c)^2-d1^2"); // (8) GenPolynomial e9 = pring.parse("(p4a-p3a)^2+(p4b-p3b)^2+(p4c-p3c)^2-d2^2"); // (9) List> cp = new ArrayList>(9); cp.add(e1); cp.add(e2); cp.add(e3); cp.add(e4); cp.add(e5); cp.add(e6); cp.add(e7); cp.add(e8); cp.add(e9); GenPolynomial e10 = pring.parse("(p4a-p1a)^2+(p4b-p1b)^2+(p4c-p1c)^2-d3^2"); // (10) cp.add(e10); List> gb; GroebnerBase sgb = GBFactory.getImplementation(br); gb = sgb.GB(cp); //System.out.println("gb = " + gb); PolynomialList pl = new PolynomialList(pring, gb); Ideal id = new Ideal(pl, true); System.out.println("cp = " + cp); System.out.println("id = " + id); Dimension dim = id.dimension(); System.out.println("dim = " + dim); } } jas-2.5/src/edu/jas/application/IdealWithComplexRoots.java0000644000175000017500000000362312004024570024061 0ustar giovannigiovanni/* * $Id: IdealWithComplexRoots.java 4050 2012-07-25 17:14:32Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.List; import edu.jas.arith.BigDecimal; import edu.jas.poly.Complex; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Container for Ideals together with univariate polynomials and complex roots. * @author Heinz Kredel */ class IdealWithComplexRoots> extends IdealWithUniv { /** * The list of complex roots. */ public final List>> croots; /** * Constructor not for use. */ protected IdealWithComplexRoots() { throw new IllegalArgumentException("do not use this constructor"); } /** * Constructor. * @param id the ideal * @param up the list of univaraite polynomials * @param cr the list of complex roots */ public IdealWithComplexRoots(Ideal id, List> up, List>> cr) { super(id, up); croots = cr; } /** * Constructor. * @param iu the ideal with univariate polynomials * @param cr the list of complex roots */ public IdealWithComplexRoots(IdealWithUniv iu, List>> cr) { super(iu.ideal, iu.upolys); croots = cr; } /** * String representation of the ideal. * @see java.lang.Object#toString() */ @Override public String toString() { return super.toString() + "\ncomplex roots: " + croots.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ @Override public String toScript() { // Python case return super.toScript() + ", " + croots.toString(); } } jas-2.5/src/edu/jas/application/FactorAlgebraicPrim.java0000644000175000017500000001544112014152710023470 0ustar giovannigiovanni/* * $Id: FactorAlgebraicPrim.java 4110 2012-08-19 12:02:16Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.FactorAbsolute; import edu.jas.ufd.FactorAbstract; import edu.jas.ufd.PolyUfdUtil; import edu.jas.ufd.Squarefree; import edu.jas.ufd.SquarefreeFactory; /** * Algebraic number coefficients factorization algorithms. This class * implements factorization methods for polynomials over algebraic * numbers over rational numbers or over (prime) modular integers. The * algorithm uses zero dimensional ideal prime decomposition. * @author Heinz Kredel * @param coefficient type */ public class FactorAlgebraicPrim> extends FactorAbsolute> { //FactorAbstract> private static final Logger logger = Logger.getLogger(FactorAlgebraicPrim.class); //private final boolean debug = logger.isInfoEnabled(); /** * Factorization engine for base coefficients. */ public final FactorAbstract factorCoeff; /** * No argument constructor. Note: can't use this constructor. */ protected FactorAlgebraicPrim() { throw new IllegalArgumentException("don't use this constructor"); } /** * Constructor. * @param fac algebraic number factory. */ public FactorAlgebraicPrim(AlgebraicNumberRing fac) { this(fac, FactorFactory. getImplementation(fac.ring.coFac)); } /** * Constructor. * @param fac algebraic number factory. * @param factorCoeff factorization engine for polynomials over base * coefficients. */ public FactorAlgebraicPrim(AlgebraicNumberRing fac, FactorAbstract factorCoeff) { super(fac); this.factorCoeff = factorCoeff; } /** * GenPolynomial base factorization of a squarefree polynomial. * @param P squarefree GenPolynomial<AlgebraicNumber<C>>. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ @Override public List>> baseFactorsSquarefree(GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List>> factors = new ArrayList>>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing> pfac = P.ring; // Q(alpha)[x] if (pfac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomials"); } AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac; AlgebraicNumber ldcf = P.leadingBaseCoefficient(); if (!ldcf.isONE()) { P = P.monic(); factors.add(pfac.getONE().multiply(ldcf)); } //System.out.println("\nP = " + P); if (logger.isDebugEnabled()) { Squarefree> sqengine = SquarefreeFactory .> getImplementation(afac); if (!sqengine.isSquarefree(P)) { throw new RuntimeException("P not squarefree: " + sqengine.squarefreeFactors(P)); } GenPolynomial modu = afac.modul; if (!factorCoeff.isIrreducible(modu)) { throw new RuntimeException("modul not irreducible: " + factorCoeff.factors(modu)); } System.out.println("P squarefree and modul irreducible via ideal decomposition"); //GreatestCommonDivisor> aengine //= GCDFactory.> getProxy(afac); // = new GreatestCommonDivisorSimple>( /*cfac.coFac*/ ); } GenPolynomial agen = afac.modul; GenPolynomialRing cfac = afac.ring; GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, pfac); TermOrder to = new TermOrder(TermOrder.INVLEX); String[] vars = new String[2]; vars[0] = cfac.getVars()[0]; vars[1] = rfac.getVars()[0]; GenPolynomialRing dfac = new GenPolynomialRing(cfac.coFac, to, vars); // transform minimal polynomial to bi-variate polynomial GenPolynomial Ad = agen.extend(dfac, 0, 0L); // transform to bi-variate polynomial GenPolynomial> Pc = PolyUtil. fromAlgebraicCoefficients(rfac, P); //System.out.println("Pc = " + Pc.toScript()); GenPolynomial Pd = PolyUtil. distribute(dfac, Pc); //System.out.println("Ad = " + Ad.toScript()); //System.out.println("Pd = " + Pd.toScript()); List> id = new ArrayList>(2); id.add(Ad); id.add(Pd); Ideal I = new Ideal(dfac, id); List> Iul = I.zeroDimPrimeDecomposition(); //System.out.println("prime decomp = " + Iul); if (Iul.size() == 1) { factors.add(P); return factors; } GenPolynomial> f = pfac.getONE(); for (IdealWithUniv Iu : Iul) { List> pl = Iu.ideal.getList(); GenPolynomial ag = PolyUtil. selectWithVariable(pl, 1); GenPolynomial pg = PolyUtil. selectWithVariable(pl, 0); //System.out.println("ag = " + ag.toScript()); //System.out.println("pg = " + pg.toScript()); if (ag.equals(Ad)) { //System.out.println("found factor --------------------"); GenPolynomial> pgr = PolyUtil. recursive(rfac, pg); GenPolynomial> pga = PolyUtil. convertRecursiveToAlgebraicCoefficients( pfac, pgr); //System.out.println("pga = " + pga.toScript()); f = f.multiply(pga); factors.add(pga); } else { logger.warn("algebraic number mismatch: ag = " + ag + ", expected Ad = " + Ad); } } f = f.subtract(P); //System.out.println("f = " + f.toScript()); if (!f.isZERO()) { throw new RuntimeException("no factorization: " + f + ", factors = " + factors); } return factors; //return new edu.jas.ufd.FactorAlgebraic(afac).baseFactorsSquarefree(P); } } jas-2.5/src/edu/jas/application/CReductionSeq.java0000644000175000017500000004145512014163702022347 0ustar giovannigiovanni/* * $Id: CReductionSeq.java 4115 2012-08-19 13:18:59Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisor; /** * Polynomial parametric ring reduction sequential use algorithm. Implements * normalform, condition construction and polynomial determination. * @param coefficient type * @author Heinz Kredel */ public class CReductionSeq> implements Serializable /* extends ReductionAbstract */ /* implements CReduction */{ private static final Logger logger = Logger.getLogger(CReductionSeq.class); //private final boolean debug = logger.isDebugEnabled(); private final boolean info = logger.isInfoEnabled(); /** * Greatest common divisor engine. */ protected final GreatestCommonDivisor engine; /** * Polynomial coefficient ring factory. */ protected final RingFactory cofac; /** * Flag if top-reduction only should be used. */ protected boolean top = true; // false; /** * Constructor. * @param rf coefficient factory. */ public CReductionSeq(RingFactory rf) { cofac = rf; // System.out.println("cofac = " + cofac); engine = GCDFactory. getImplementation(cofac); } /** * S-Polynomial. * @param Ap polynomial. * @param Bp polynomial. * @return spol(Ap,Bp) the S-polynomial of Ap and Bp. */ public ColorPolynomial SPolynomial(ColorPolynomial Ap, ColorPolynomial Bp) { if (Bp == null || Bp.isZERO()) { return Bp; } if (Ap == null || Ap.isZERO()) { return Ap; } Map.Entry> ma = Ap.red.leadingMonomial(); Map.Entry> mb = Bp.red.leadingMonomial(); ExpVector e = ma.getKey(); ExpVector f = mb.getKey(); ExpVector g = e.lcm(f); // EVLCM(e,f); ExpVector e1 = g.subtract(e); // EVDIF(g,e); ExpVector f1 = g.subtract(f); // EVDIF(g,f); GenPolynomial a = ma.getValue(); GenPolynomial b = mb.getValue(); GenPolynomial c = engine.gcd(a, b); if (!c.isONE()) { // System.out.println("gcd =s " + c); a = a.divide(c); b = b.divide(c); } ColorPolynomial App = Ap.multiply(b, e1); ColorPolynomial Bpp = Bp.multiply(a, f1); ColorPolynomial Cp = App.subtract(Bpp); return Cp; } /** * Is top reducible. * @param A polynomial. * @param P polynomial list. * @return true if A is top reducible with respect to P. */ public boolean isTopReducible(List> P, ColorPolynomial A) { if (P == null || P.isEmpty()) { return false; } if (A == null || A.isZERO()) { return false; } boolean mt = false; ExpVector e = A.leadingExpVector(); for (ColorPolynomial p : P) { if (p == null) { return false; } ExpVector f = p.leadingExpVector(); if (f == null) { return false; } if (e == null) { return false; } mt = e.multipleOf(f); // EVMT( e, p.leadingExpVector() ); if (mt) { return true; } } return false; } /** * Is reducible. * @param Ap polynomial. * @param Pp polynomial list. * @return true if Ap is reducible with respect to Pp. */ public boolean isReducible(List> Pp, ColorPolynomial Ap) { return !isNormalform(Pp, Ap); } /** * Is in Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @return true if Ap is in normalform with respect to Pp. */ @SuppressWarnings("unchecked") public boolean isNormalform(List> Pp, ColorPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return true; } if (Ap == null || Ap.isZERO()) { return true; } int l; ColorPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = new ColorPolynomial[l]; // P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[l]; ColorPolynomial[] p = new ColorPolynomial[l]; Map.Entry> m; int i; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].red.leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); j++; } } l = j; boolean mt = false; for (ExpVector e : Ap.red.getMap().keySet()) { for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); // EVMT( e, htl[i] ); if (mt) { System.out.println("not normalform " + Ap + ", P[i] = " + P[i]); return false; } } if (top) { return true; } } for (ExpVector e : Ap.white.getMap().keySet()) { for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); // EVMT( e, htl[i] ); if (mt) { System.out.println("not normalform " + Ap + ", P[i] = " + P[i]); return false; } } if (top) { return true; } } return true; } /** * Is in Normalform. * @param Pp polynomial list. * @return true if each Ap in Pp is in normalform with respect to Pp\{Ap}. */ public boolean isNormalform(List> Pp) { if (Pp == null || Pp.isEmpty()) { return true; } ColorPolynomial Ap; List> P = new LinkedList>(Pp); int s = P.size(); for (int i = 0; i < s; i++) { Ap = P.remove(i); if (!isNormalform(P, Ap)) { return false; } P.add(Ap); } return true; } /** * Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @param cond condition for these polynomials. * @return nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public ColorPolynomial normalform(Condition cond, List> Pp, ColorPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } Map.Entry> m; int l; ColorPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = new ColorPolynomial[l]; // P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[l]; Object[] lbc = new Object[l]; // want C[] ColorPolynomial[] p = new ColorPolynomial[l]; int i; int j = 0; for (i = 0; i < l; i++) { if (P[i] == null) { continue; } p[i] = P[i]; m = p[i].red.leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; GenPolynomial a; boolean mt = false; GenPolynomial> zero = p[0].red.ring.getZERO(); ColorPolynomial R = new ColorPolynomial(zero, zero, zero); // ColorPolynomial T = null; ColorPolynomial Q = null; ColorPolynomial S = Ap; while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); Condition.Color col = cond.color(a); if (col == Condition.Color.GREEN) { // move to green terms GenPolynomial> g = S.green.sum(a, e); GenPolynomial> r = S.red; GenPolynomial> w = S.white; if (S.red.isZERO()) { w = w.subtract(a, e); } else { // only in minimalGB logger.info("green_red = " + zero.sum(a, e)); r = r.subtract(a, e); } S = new ColorPolynomial(g, r, w); continue; } //if (col == Condition.Color.WHITE) { // refine condition // System.out.println("white = " + zero.sum(a,e)); // return S; // return for new case distinction //} // System.out.println("NF, e = " + e); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); // EVMT( e, htl[i] ); if (mt) break; } if (!mt) { // logger.debug("irred"); if (top) { return S; } R = R.sum(a, e); S = S.subtract(a, e); // System.out.println(" S = " + S); } else { e = e.subtract(htl[i]); // EVDIF( e, htl[i] ); // logger.info("red div = " + e); GenPolynomial c = (GenPolynomial) lbc[i]; GenPolynomial g = engine.gcd(a, c); if (!g.isONE()) { // System.out.println("gcd = " + g); a = a.divide(g); c = c.divide(g); } S = S.multiply(c); R = R.multiply(c); Q = p[i].multiply(a, e); S = S.subtract(Q); } } return R; } /* * -------- coloring and condition stuff ------------------------------ */ /** * Case distinction conditions of parametric polynomial list. The returned * condition determines the polynomial list. * @param L list of parametric polynomials. * @return list of conditions as case distinction. */ public List> caseDistinction(List>> L) { List> cd = new ArrayList>(); if (L == null || L.size() == 0) { return cd; } for (GenPolynomial> A : L) { if (A != null && !A.isZERO()) { cd = caseDistinction(cd, A); } } // System.out.println("cd = " + cd); return cd; } /** * Case distinction conditions of parametric polynomial list. * @param cd a list of conditions. * @param A a parametric polynomial. * @return list of conditions as case distinction extending the conditions * in cd. */ public List> caseDistinction(List> cd, GenPolynomial> A) { if (A == null || A.isZERO()) { return cd; } if (cd == null) { cd = new ArrayList>(); } if (cd.size() == 0) { // construct empty condition RingFactory> crfac = A.ring.coFac; GenPolynomialRing cfac = (GenPolynomialRing) crfac; Condition sc = new Condition(cfac); cd.add(sc); } GenPolynomial> Ap; GenPolynomial> Bp; List> C = new ArrayList>( /* leer! */); for (Condition cond : cd) { // System.out.println("caseDist: " + cond); Condition cz = cond; Ap = A; while (!Ap.isZERO()) { GenPolynomial c = Ap.leadingBaseCoefficient(); Bp = Ap.reductum(); //System.out.println("to color: " + c); switch (cz.color(c)) { case GREEN: // System.out.println("color green: " + c); Ap = Bp; continue; case RED: // System.out.println("color red: " + c); C.add(cz); // wrong: return C; Ap = A.ring.getZERO(); continue; // break; case WHITE: default: // System.out.println("color white: " + c); Condition nc = cz.extendNonZero(c); if (nc != null) { // no contradiction if (!cz.equals(nc)) { C.add(nc); } else { cz = null; Ap = A.ring.getZERO(); continue; } } else { System.out.println("this should not be printed " + c); } Condition ez = cz.extendZero(c); if (ez != null) { cz = ez; } else { // contradiction cz = null; Ap = A.ring.getZERO(); continue; } Ap = Bp; } } // System.out.println("cond cz: " + cz); if (cz == null || cz.isContradictory() || C.contains(cz)) { // System.out.println("not added entry " + cz); } else { C.add(cz); } } // System.out.println("C = " + C); return C; } /** * Case distinction conditions of parametric polynomial list. * @param A a parametric polynomial. * @param cond a condition. * @return list of case distinction conditions. */ public List> caseDistinction(Condition cond, GenPolynomial> A) { List> cd = new ArrayList>(); if (A == null || A.isZERO()) { return cd; } cd.add(cond); cd = caseDistinction(cd, A); if (info) { StringBuffer s = new StringBuffer("extending condition: " + cond + "\n"); s.append("case distinctions: [ \n"); for (Condition c : cd) { s.append(c.toString() + "\n"); } s.append("]"); logger.info(s.toString()); } return cd; } /** * Determine polynomial list. * @param H polynomial list. * @return new determined list of colored systems. */ public List> determine(List>> H) { if (H == null || H.size() == 0) { List> CS = new ArrayList>(); return CS; } //System.out.println("of determine = " + H); Collections.reverse(H); List> cd = caseDistinction(H); //System.out.println("case Distinction = " + cd); //System.out.println("of determine = " + H); return determine(cd, H); } /** * Determine polynomial list. * @param H polynomial list. * @param cd case distiction, a condition list. * @return new determined list of colored systems. */ public List> determine(List> cd, List>> H) { List> CS = new ArrayList>(); if (H == null || H.size() == 0) { return CS; } for (Condition cond : cd) { logger.info("determine wrt cond = " + cond); if (cond.zero.isONE()) { // should not happen System.out.println("ideal is one = " + cond.zero); // continue; // can treat all coeffs as green } // if ( cond.isEmpty() ) { // do not use this code // continue; // can skip condition (?) // } List> S = cond.determine(H); ColoredSystem cs = new ColoredSystem(cond, S); CS.add(cs); } return CS; } } jas-2.5/src/edu/jas/application/PrimaryComponent.java0000644000175000017500000000434012004330270023130 0ustar giovannigiovanni/* * $Id: PrimaryComponent.java 4058 2012-07-26 21:03:53Z kredel $ */ package edu.jas.application; import java.io.Serializable; import edu.jas.structure.GcdRingElem; /** * Container for primary components of ideals. * @author Heinz Kredel */ public class PrimaryComponent> implements Serializable { /** * The primary ideal. */ public final Ideal primary; /** * The associated prime ideal. */ public final IdealWithUniv prime; /** * The exponent of prime for primary. */ protected int exponent; /** * Constructor not for use. */ protected PrimaryComponent() { throw new IllegalArgumentException("do not use this constructor"); } /** * Constructor. * @param q the primary ideal * @param p the prime ideal. */ protected PrimaryComponent(Ideal q, IdealWithUniv p) { this(q, p, -1); } /** * Constructor. * @param q the primary ideal * @param p the prime ideal. * @param e the exponent of p for q. */ protected PrimaryComponent(Ideal q, IdealWithUniv p, int e) { primary = q; prime = p; exponent = e; } /** * Get exponent. * @return exponent. */ public int getExponent() { return exponent; } /** * Set exponent. * @param e the exponent. */ public void setExponent(int e) { exponent = e; } /** * String representation of the ideal. * @see java.lang.Object#toString() */ @Override public String toString() { String s = "\nprimary:\n" + primary.toString() + "\nprime:\n" + prime.toString(); if (exponent < 0) { return s; } return s + "\nexponent:\n" + exponent; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ public String toScript() { // Python case String s = primary.toScript() + ", " + prime.toString(); if (exponent < 0) { return s; } return s + ", " + exponent; } } jas-2.5/src/edu/jas/application/IdealWithUniv.java0000644000175000017500000000540012004330270022334 0ustar giovannigiovanni/* * $Id: IdealWithUniv.java 4058 2012-07-26 21:03:53Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.List; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Container for Ideals together with univariate polynomials. * @author Heinz Kredel */ public class IdealWithUniv> implements Serializable { /** * The ideal. */ public final Ideal ideal; /** * The list of univariate polynomials. Contains polynomials from serveral * rings, depending on the stage of the decomposition. 1) polynomials in a * ring of one variable, 2) polynomials depending on only one variable but * in a ring with multiple variables, 3) after contraction to a non-zero * dimensional ring multivariate polynomials depending on one significant * variable and multiple variables from the quotient coefficients. */ public final List> upolys; /** * A list of other useful polynomials. 1) field extension polynomials, 2) * generators for infinite quotients. */ public final List> others; /** * Constructor not for use. */ protected IdealWithUniv() { throw new IllegalArgumentException("do not use this constructor"); } /** * Constructor. * @param id the ideal * @param up the list of univariate polynomials */ protected IdealWithUniv(Ideal id, List> up) { this(id, up, null); } /** * Constructor. * @param id the ideal * @param up the list of univariate polynomials * @param og the list of other polynomials */ protected IdealWithUniv(Ideal id, List> up, List> og) { ideal = id; upolys = up; others = og; } /** * String representation of the ideal. * @see java.lang.Object#toString() */ @Override public String toString() { String s = ideal.toString(); if (upolys != null) { s += "\nunivariate polynomials:\n" + upolys.toString(); } if (others == null) { return s; } return s + "\nother polynomials:\n" + others.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ public String toScript() { // Python case String s = ideal.toScript(); if (upolys != null) { s += ", upolys=" + upolys.toString(); } if (others == null) { return s; } return s + ", others=" + others.toString(); } } jas-2.5/src/edu/jas/application/SolvableResidue.java0000644000175000017500000002523712137717062022741 0ustar giovannigiovanni/* * $Id: SolvableResidue.java 4407 2013-04-30 10:34:27Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import edu.jas.kern.PrettyPrint; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.structure.GcdRingElem; import edu.jas.structure.NotInvertibleException; /** * SolvableResidue ring element based on GenSolvablePolynomial with RingElem * interface. Objects of this class are (nearly) immutable. * @author Heinz Kredel */ public class SolvableResidue> implements GcdRingElem> { /** * SolvableResidue class factory data structure. */ public final SolvableResidueRing ring; /** * Value part of the element data structure. */ public final GenSolvablePolynomial val; /** * Flag to remember if this residue element is a unit. -1 is unknown, 1 is * unit, 0 not a unit. */ protected int isunit = -1; // initially unknown /** * The constructor creates a SolvableResidue object from a ring factory. * @param r solvable residue ring factory. */ public SolvableResidue(SolvableResidueRing r) { this(r, r.ring.getZERO(), 0); } /** * The constructor creates a SolvableResidue object from a ring factory and * a polynomial. * @param r solvable residue ring factory. * @param a solvable polynomial. */ public SolvableResidue(SolvableResidueRing r, GenSolvablePolynomial a) { this(r, a, -1); } /** * The constructor creates a SolvableResidue object from a ring factory, a * polynomial and an indicator if a is a unit. * @param r solvable residue ring factory. * @param a solvable polynomial. * @param u isunit indicator, -1, 0, 1. */ public SolvableResidue(SolvableResidueRing r, GenSolvablePolynomial a, int u) { ring = r; val = ring.ideal.normalform(a); //.monic() no go if (u == 0 || u == 1) { isunit = u; return; } if (val.isZERO()) { isunit = 0; return; } if (val.isUnit()) { isunit = 1; //} else { // not possible //isunit = 0; } isunit = -1; } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public SolvableResidueRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public SolvableResidue copy() { return new SolvableResidue(ring, val, isunit); } /** * Is SolvableResidue zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return val.isZERO(); } /** * Is SolvableResidue one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return val.isONE(); } /** * Is SolvableResidue unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (isunit > 0) { return true; } if (isunit == 0) { return false; } // not jet known boolean u = ring.ideal.isUnit(val); if (u) { isunit = 1; // seems to be wrong for solvable polynomial rings } else { isunit = 0; } return isunit > 0; } /** * Is SolvableResidue a constant. * @return true if this.val is a constant polynomial, else false. */ public boolean isConstant() { return val.isConstant(); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { if (PrettyPrint.isTrue()) { return val.toString(ring.ring.getVars()); } return "SolvableResidue[ " + val.toString() + " mod " + ring.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ @Override public String toScript() { // Python case return val.toScript(); // return "PolySolvableResidue( " + val.toScript() // + ", " + ring.toScript() + " )"; } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * SolvableResidue comparison. * @param b SolvableResidue. * @return sign(this-b), 0 means that this and b are equivalent in this * residue class ring. */ @Override public int compareTo(SolvableResidue b) { GenSolvablePolynomial v = b.val; if (!ring.equals(b.ring)) { v = ring.ideal.normalform(v); } return val.compareTo(v); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) * @return true means that this and b are equivalent in this residue class * ring. */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof SolvableResidue)) { return false; } SolvableResidue a = null; try { a = (SolvableResidue) b; } catch (ClassCastException e) { } if (a == null) { return false; } return compareTo(a) == 0; } /** * Hash code for this residue. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + val.hashCode(); return h; } /** * SolvableResidue absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public SolvableResidue abs() { return new SolvableResidue(ring, (GenSolvablePolynomial) val.abs(), isunit); } /** * SolvableResidue summation. * @param S SolvableResidue. * @return this+S. */ public SolvableResidue sum(SolvableResidue S) { return new SolvableResidue(ring, (GenSolvablePolynomial) val.sum(S.val)); } /** * SolvableResidue negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public SolvableResidue negate() { return new SolvableResidue(ring, (GenSolvablePolynomial) val.negate(), isunit); } /** * SolvableResidue signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { return val.signum(); } /** * SolvableResidue subtraction. * @param S SolvableResidue. * @return this-S. */ public SolvableResidue subtract(SolvableResidue S) { return new SolvableResidue(ring, (GenSolvablePolynomial) val.subtract(S.val)); } /** * SolvableResidue division. * @param S SolvableResidue. * @return this/S. */ public SolvableResidue divide(SolvableResidue S) { if (ring.isField()) { return multiply(S.inverse()); } List> Q = new ArrayList>(1); Q.add(ring.ring.getZERO()); List> V = new ArrayList>(1); V.add(val); GenSolvablePolynomial x = ring.bb.sred.leftNormalform(Q, V, S.val); GenSolvablePolynomial y = Q.get(0); return new SolvableResidue(ring, y); } /** * SolvableResidue inverse. * @see edu.jas.structure.RingElem#inverse() * @return S with S = 1/this if defined. */ public SolvableResidue inverse() { GenSolvablePolynomial x = ring.ideal.inverse(val); SolvableResidue xp = new SolvableResidue(ring, x, 1); if ( xp.isZERO() ) { throw new NotInvertibleException("(" + x + ") * (" + val + ") = " + x.multiply(val) + " = 0 mod " + ring.ideal); } return xp; } /** * SolvableResidue remainder. * @param S SolvableResidue. * @return this - (this/S)*S. */ public SolvableResidue remainder(SolvableResidue S) { List> V = new ArrayList>(1); V.add(val); GenSolvablePolynomial x = ring.bb.sred.leftNormalform(V, S.val); return new SolvableResidue(ring, x); } /** * SolvableResidue multiplication. * @param S SolvableResidue. * @return this*S. */ public SolvableResidue multiply(SolvableResidue S) { GenSolvablePolynomial x = val.multiply(S.val); int i = -1; if (isunit == 1 && S.isunit == 1) { i = 1; } else if (isunit == 0 || S.isunit == 0) { i = 0; } return new SolvableResidue(ring, x, i); } /** * SolvableResidue monic. * @return this with monic value part. */ public SolvableResidue monic() { return new SolvableResidue(ring, (GenSolvablePolynomial) val.monic(), isunit); } /** * Greatest common divisor. * @param b other element. * @return gcd(this,b). */ public SolvableResidue gcd(SolvableResidue b) { throw new UnsupportedOperationException("gcd not implemented"); // GenSolvablePolynomial x = ring.engine.gcd(val, b.val); // int i = -1; // gcd might become a unit // if (x.isONE()) { // i = 1; // } else { // System.out.println("SolvableResidue gcd = " + x); // } // if (isunit == 1 && b.isunit == 1) { // i = 1; // } // return new SolvableResidue(ring, x, i); } /** * Extended greatest common divisor. Note: Not implemented, throws * UnsupportedOperationException. * @param b other element. * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). */ public SolvableResidue[] egcd(SolvableResidue b) { throw new UnsupportedOperationException("egcd not implemented"); } } jas-2.5/src/edu/jas/application/FactorRealReal.java0000644000175000017500000001056512004330270022456 0ustar giovannigiovanni/* * $Id: FactorRealReal.java 4058 2012-07-26 21:03:53Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.Rational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.FactorAbstract; /** * Real algebraic number coefficients factorization algorithms. This class * implements factorization methods for polynomials over bi-variate real * algebraic numbers from package * *
 * edu.jas.application
 * 
* * . * @param coefficient type * @author Heinz Kredel */ public class FactorRealReal & Rational> extends FactorAbstract> { // TODO: is absolute possible? and what does it mean? //FactorAbsolute> //FactorAbstract> private static final Logger logger = Logger.getLogger(FactorRealReal.class); private final boolean debug = logger.isInfoEnabled(); /** * Factorization engine for base coefficients. */ public final FactorAbstract> factorAlgebraic; /** * No argument constructor. Note: can't use this constructor. */ protected FactorRealReal() { throw new IllegalArgumentException("don't use this constructor"); } /** * Constructor. * @param fac algebraic number factory. */ public FactorRealReal(RealAlgebraicRing fac) { // ignore recursion, as it is handled in FactorRealAlgebraic: this( fac, FactorFactory.> getImplementation((edu.jas.root.RealAlgebraicRing) (Object) fac.realRing)); } /** * Constructor. * @param fac algebraic number factory. * @param factorAlgebraic factorization engine for polynomials over base * coefficients. */ public FactorRealReal(RealAlgebraicRing fac, FactorAbstract> factorAlgebraic) { super(fac); this.factorAlgebraic = factorAlgebraic; } /** * GenPolynomial base factorization of a squarefree polynomial. * @param P squarefree GenPolynomial<RealAlgebraicNumber<C>>. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ @Override public List>> baseFactorsSquarefree( GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List>> factors = new ArrayList>>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing> pfac = P.ring; // Q(alpha)[x] if (pfac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomials"); } RealAlgebraicRing rere = (RealAlgebraicRing) pfac.coFac; edu.jas.root.RealAlgebraicRing rfac = (edu.jas.root.RealAlgebraicRing) (Object) rere.realRing; RealAlgebraicNumber ldcf = P.leadingBaseCoefficient(); if (!ldcf.isONE()) { P = P.monic(); factors.add(pfac.getONE().multiply(ldcf)); } //System.out.println("\nP = " + P); GenPolynomialRing> arfac = new GenPolynomialRing>( rfac, pfac); GenPolynomial> A = PolyUtilApp. realAlgFromRealCoefficients( arfac, P); // factor A: List>> afactors = factorAlgebraic .baseFactorsSquarefree(A); for (GenPolynomial> a : afactors) { GenPolynomial> p = PolyUtilApp. realFromRealAlgCoefficients(pfac, a); factors.add(p); } if (debug) { logger.info("rafactors = " + factors); } return factors; } } jas-2.5/src/edu/jas/application/RunGB.java0000644000175000017500000003536212061107454020620 0ustar giovannigiovanni/* * $Id: RunGB.java 4314 2012-12-09 13:16:29Z kredel $ */ package edu.jas.application; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.IOException; import java.io.Reader; import java.io.BufferedReader; import java.io.StringReader; import java.nio.charset.Charset; import java.util.List; import org.apache.log4j.BasicConfigurator; //import edu.jas.gb.GBDist; //import edu.jas.gb.GBDistHybrid; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.GroebnerBaseParallel; import edu.jas.gb.GroebnerBaseDistributedEC; import edu.jas.gb.GroebnerBaseDistributedHybridEC; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.gb.OrderedSyzPairlist; import edu.jas.gb.ReductionPar; import edu.jas.gb.ReductionSeq; import edu.jas.gbufd.GBFactory; import edu.jas.gbufd.GroebnerBasePseudoParallel; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.PolynomialList; import edu.jas.util.CatReader; import edu.jas.util.ExecutableServer; /** * Simple setup to run a GB example.
* Usage: RunGB [seq(+)|par(+)|dist(1)(+)|disthyb|cli] <file> * #procs/#threadsPerNode [machinefile] * @author Heinz Kredel */ public class RunGB { /** * Check result GB if it is a GB. */ static boolean doCheck = false; /** * Enable logging. */ static boolean doLog = true; /** * main method to be called from commandline
* Usage: RunGB [seq|par(+)|dist(1)(+)|disthyb|cli] <file> * #procs/#threadsPerNode [machinefile] <check> <log> */ @SuppressWarnings("unchecked") public static void main(java.lang.String[] args) { String usage = "Usage: RunGB " + "[ seq | seq+ | par | par+ | dist | dist1 | dist+ | dist1+ | disthyb1 | cli [port] ] " + " " + "#procs/#threadsPerNode " + "[machinefile] "; if (args.length < 1) { System.out.println(usage); return; } boolean pairseq = false; String kind = args[0]; String[] allkinds = new String[] { "seq", "seq+", "par", "par+", "dist", "dist1", "dist+", "dist1+", "disthyb1", "cli" }; boolean sup = false; for (int i = 0; i < allkinds.length; i++) { if (kind.equals(allkinds[i])) { sup = true; if (kind.indexOf("+") >= 0) { pairseq = true; } } } if (!sup) { System.out.println(usage); return; } //boolean once = false; final int GB_SERVER_PORT = 7114; //inal int EX_CLIENT_PORT = GB_SERVER_PORT + 1000; int port = GB_SERVER_PORT; if (kind.equals("cli")) { if (args.length >= 2) { try { port = Integer.parseInt(args[1]); } catch (NumberFormatException e) { e.printStackTrace(); System.out.println(usage); return; } } runClient(port); return; } String filename = null; if (!kind.equals("cli")) { if (args.length < 2) { System.out.println(usage); return; } filename = args[1]; } for (int i = 0; i < args.length; i++) { if (args[i].equals("check")) { doCheck = true; } } for (int i = 0; i < args.length; i++) { if (args[i].equals("nolog")) { doLog = false; } } int threads = 0; int threadsPerNode = 1; if (kind.startsWith("par") || kind.startsWith("dist")) { if (args.length < 3) { System.out.println(usage); return; } String tup = args[2]; String t = tup; int i = tup.indexOf("/"); if (i >= 0) { t = tup.substring(0, i).trim(); tup = tup.substring(i + 1).trim(); try { threadsPerNode = Integer.parseInt(tup); } catch (NumberFormatException e) { e.printStackTrace(); System.out.println(usage); return; } } try { threads = Integer.parseInt(t); } catch (NumberFormatException e) { e.printStackTrace(); System.out.println(usage); return; } } String mfile = null; if (kind.startsWith("dist")) { if (args.length >= 4) { mfile = args[3]; } else { mfile = "machines"; } } Reader problem = null; try { problem = new InputStreamReader(new FileInputStream(filename),Charset.forName("UTF8")); problem = new BufferedReader(problem); } catch (FileNotFoundException e) { e.printStackTrace(); System.out.println(usage); return; } RingFactoryTokenizer rftok = new RingFactoryTokenizer(problem); GenPolynomialRing pfac = null; try { pfac = rftok.nextPolynomialRing(); rftok = null; } catch (IOException e) { e.printStackTrace(); return; } Reader polyreader = new CatReader(new StringReader("("), problem); // ( has gone GenPolynomialTokenizer tok = new GenPolynomialTokenizer(pfac, polyreader); PolynomialList S = null; try { S = new PolynomialList(pfac, tok.nextPolynomialList()); } catch (IOException e) { e.printStackTrace(); return; } System.out.println("input S =\n" + S); if (doLog) { BasicConfigurator.configure(); } if (kind.startsWith("seq")) { runSequential(S, pairseq); } if (kind.startsWith("par")) { runParallel(S, threads, pairseq); } if (kind.startsWith("dist1")) { runMasterOnce(S, threads, mfile, port, pairseq); } else if (kind.startsWith("disthyb1")) { runMasterOnceHyb(S, threads, threadsPerNode, mfile, port, pairseq); } else if (kind.startsWith("dist")) { runMaster(S, threads, mfile, port, pairseq); } ComputerThreads.terminate(); //System.exit(0); } @SuppressWarnings("unchecked") static void runMaster(PolynomialList S, int threads, String mfile, int port, boolean pairseq) { List L = S.list; List G = null; long t, t1; GroebnerBaseDistributedEC gbd = null; GroebnerBaseDistributedEC gbds = null; System.out.println("\nGroebner base distributed (" + threads + ", " + mfile + ", " + port + ") ..."); t = System.currentTimeMillis(); if (pairseq) { //gbds = new GroebnerBaseDistributedEC(threads,mfile, port); gbds = new GroebnerBaseDistributedEC(mfile, threads, new OrderedSyzPairlist(), port); } else { gbd = new GroebnerBaseDistributedEC(mfile, threads, port); } t1 = System.currentTimeMillis(); if (pairseq) { G = gbds.GB(L); } else { G = gbd.GB(L); } t1 = System.currentTimeMillis() - t1; if (pairseq) { gbds.terminate(); //false); } else { gbd.terminate(); //false); } S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); t = System.currentTimeMillis() - t; if (pairseq) { System.out.print("d+ "); } else { System.out.print("d "); } System.out.println("= " + threads + ", time = " + t1 + " milliseconds, " + (t-t1) + " start-up " + ", total = " + t); checkGB(S); System.out.println(""); } @SuppressWarnings("unchecked") static void runMasterOnce(PolynomialList S, int threads, String mfile, int port, boolean pairseq) { List L = S.list; List G = null; long t, t1; GroebnerBaseDistributedEC gbd = null; GroebnerBaseDistributedEC gbds = null; System.out.println("\nGroebner base distributed[once] (" + threads + ", " + mfile + ", " + port + ") ..."); t = System.currentTimeMillis(); if (pairseq) { //gbds = new GroebnerBaseDisttributedEC(threads, mfile, port); gbds = new GroebnerBaseDistributedEC(mfile, threads, new OrderedSyzPairlist(), port); } else { gbd = new GroebnerBaseDistributedEC(mfile, threads, port); } t1 = System.currentTimeMillis(); if (pairseq) { G = gbds.GB(L); } else { G = gbd.GB(L); } t1 = System.currentTimeMillis() - t1; if (pairseq) { gbds.terminate(); //true); } else { gbd.terminate(); //true); } S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); t = System.currentTimeMillis() - t; if (pairseq) { System.out.print("d+ "); } else { System.out.print("d "); } System.out.println("= " + threads + ", time = " + t1 + " milliseconds, " + (t-t1) + " start-up " + ", total = " + t); checkGB(S); System.out.println(""); } @SuppressWarnings("unchecked") static void runMasterOnceHyb(PolynomialList S, int threads, int threadsPerNode, String mfile, int port, boolean pairseq) { List L = S.list; List G = null; long t, t1; GroebnerBaseDistributedHybridEC gbd = null; GroebnerBaseDistributedHybridEC gbds = null; System.out.println("\nGroebner base distributed hybrid[once] (" + threads + "/" + threadsPerNode + ", " + mfile + ", " + port + ") ..."); t = System.currentTimeMillis(); if (pairseq) { //System.out.println("... not implemented."); //return; // gbds = new GroebnerBaseDistributedHybridEC(mfile, threads,port); gbds = new GroebnerBaseDistributedHybridEC(mfile, threads, threadsPerNode, new OrderedSyzPairlist(), port); } else { gbd = new GroebnerBaseDistributedHybridEC(mfile, threads, threadsPerNode, port); } t1 = System.currentTimeMillis(); if (pairseq) { G = gbds.GB(L); } else { G = gbd.GB(L); } t1 = System.currentTimeMillis() - t1; if (pairseq) { //gbds.terminate(true); } else { //gbd.terminate(true); gbd.terminate(false); // plus eventually killed by script } t = System.currentTimeMillis() - t; S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); if (pairseq) { System.out.print("d+ "); } else { System.out.print("d "); } System.out.println("= " + threads + ", ppn = " + threadsPerNode + ", time = " + t1 + " milliseconds, " + (t-t1) + " start-up " + ", total = " + t); checkGB(S); System.out.println(""); } static void runClient(int port) { System.out.println("\nGroebner base distributed client (" + port + ") ..."); ExecutableServer es = new ExecutableServer(port); es.init(); try { es.join(); } catch (InterruptedException e) { // ignored } } @SuppressWarnings("unchecked") static void runParallel(PolynomialList S, int threads, boolean pairseq) { List L = S.list; List G; long t; GroebnerBaseAbstract bb = null; GroebnerBaseAbstract bbs = null; if (pairseq) { //bbs = new GroebnerBaseSeqPairParallel(threads); bbs = new GroebnerBaseParallel(threads, new ReductionPar(), new OrderedSyzPairlist()); } else { if (S.ring.coFac.isField()) { bb = new GroebnerBaseParallel(threads); } else { bb = new GroebnerBasePseudoParallel(threads,S.ring.coFac); } } System.out.println("\nGroebner base parallel (" + threads + ") ..."); t = System.currentTimeMillis(); if (pairseq) { G = bbs.GB(L); } else { G = bb.GB(L); } t = System.currentTimeMillis() - t; S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); if (pairseq) { System.out.print("p+ "); } else { System.out.print("p "); } System.out.println("= " + threads + ", time = " + t + " milliseconds"); if (pairseq) { bbs.terminate(); } else { bb.terminate(); } checkGB(S); System.out.println(""); } @SuppressWarnings("unchecked") static void runSequential(PolynomialList S, boolean pairseq) { List L = S.list; List G; long t; GroebnerBaseAbstract bb = null; if (pairseq) { //bb = new GroebnerBaseSeqPairSeq(); bb = new GroebnerBaseSeq(new ReductionSeq(), new OrderedSyzPairlist()); } else { bb = GBFactory.getImplementation(S.ring.coFac); //new GroebnerBaseSeq(); } System.out.println("\nGroebner base sequential ..."); t = System.currentTimeMillis(); G = bb.GB(L); t = System.currentTimeMillis() - t; S = new PolynomialList(S.ring, G); System.out.println("G =\n" + S); System.out.println("G.size() = " + G.size()); if (pairseq) { System.out.print("seq+, "); } else { System.out.print("seq, "); } System.out.println("time = " + t + " milliseconds"); checkGB(S); System.out.println(""); } static void checkGB(PolynomialList S) { if (!doCheck) { return; } GroebnerBaseAbstract bb = GBFactory.getImplementation(S.ring.coFac); long t = System.currentTimeMillis(); boolean chk = bb.isGB(S.list,false); t = System.currentTimeMillis() - t; System.out.println("check isGB = " + chk + " in " + t + " milliseconds"); } } jas-2.5/src/edu/jas/application/package.html0000644000175000017500000000211511505123724021247 0ustar giovannigiovanni GB application classes

Groebner base application package.

This package contains classes with applications of Groebner bases such as ideal intersections, ideal quotients or ideal dimension are implemented in Ideal and SolvableIdeal. Class Residue provides polynomials residues modulo an ideal defined in ResidueRing. Comprehensive Groebner bases for polynomial rings over parameter rings are implemented in ComprehensiveGroebnerBaseSeq.


Heinz Kredel

Last modified: Fri Dec 24 15:00:18 CET 2010

$Id: package.html 3430 2010-12-24 14:01:57Z kredel $

jas-2.5/src/edu/jas/application/FactorFactory.java0000644000175000017500000002051112014232356022375 0ustar giovannigiovanni/* * $Id: FactorFactory.java 4124 2012-08-19 18:48:15Z kredel $ */ package edu.jas.application; import org.apache.log4j.Logger; import edu.jas.arith.Rational; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomialRing; import edu.jas.root.RealAlgebraicNumber; import edu.jas.root.RealAlgebraicRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.FactorAbstract; import edu.jas.ufd.FactorAlgebraic; import edu.jas.ufd.FactorComplex; import edu.jas.ufd.FactorQuotient; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; import edu.jas.ufdroot.FactorRealAlgebraic; /** * Factorization algorithms factory. Select appropriate factorization engine * based on the coefficient types. * @author Heinz Kredel * @usage To create objects that implement the Factorization * interface use the FactorFactory. It will select an * appropriate implementation based on the types of polynomial * coefficients C. To obtain an implementation use * getImplementation(), it returns an object of a class * which extends the FactorAbstract class which implements * the Factorization interface. * *
 * Factorization<CT> engine;
 * engine = FactorFactory.<CT> getImplementation(cofac);
 * c = engine.factors(a);
 * 
* * For example, if the coefficient type is BigInteger, the usage looks * like * *
 * BigInteger cofac = new BigInteger();
 * Factorization<BigInteger> engine;
 * engine = FactorFactory.getImplementation(cofac);
 * Sm = engine.factors(poly);
 * 
* * @see edu.jas.ufd.Factorization#factors(edu.jas.poly.GenPolynomial P) * @see edu.jas.ufd.FactorFactory#getImplementation(edu.jas.structure.RingFactory * P) */ public class FactorFactory extends edu.jas.ufd.FactorFactory { private static final Logger logger = Logger.getLogger(FactorFactory.class); /** * Protected factory constructor. */ protected FactorFactory() { } /** * Determine suitable implementation of factorization algorithms, case * AlgebraicNumber<C>. * @param fac AlgebraicNumberRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return factorization algorithm implementation. */ public static > FactorAbstract> getImplementation( AlgebraicNumberRing fac) { return new FactorAlgebraic(fac, FactorFactory. getImplementation(fac.ring.coFac)); } /** * Determine suitable implementation of factorization algorithms, case * Complex<C>. * @param fac ComplexRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return factorization algorithm implementation. */ public static > FactorAbstract> getImplementation(ComplexRing fac) { return new FactorComplex(fac); } /** * Determine suitable implementation of factorization algorithms, case * Quotient<C>. * @param fac QuotientRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return factorization algorithm implementation. */ public static > FactorAbstract> getImplementation(QuotientRing fac) { return new FactorQuotient(fac, FactorFactory. getImplementation(fac.ring.coFac)); } /** * Determine suitable implementation of factorization algorithms, case * recursive GenPolynomial<C>. Use recursiveFactors(). * @param fac GenPolynomialRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return factorization algorithm implementation. */ public static > FactorAbstract getImplementation(GenPolynomialRing fac) { return getImplementation(fac.coFac); } /** * Determine suitable implementation of factorization algorithms, case * RealAlgebraicNumber<C>. * @param fac RealAlgebraicRing<C>. * @param coefficient type, e.g. BigRational. * @return factorization algorithm implementation. */ public static & Rational> FactorAbstract> getImplementation( RealAlgebraicRing fac) { return new FactorRealAlgebraic(fac, FactorFactory.> getImplementation(fac.algebraic)); } /** * Determine suitable implementation of factorization algorithms, case * RealAlgebraicNumber<C>. * @param fac RealAlgebraicRing<C>. * @param coefficient type, e.g. BigRational. * @return factorization algorithm implementation. */ @SuppressWarnings("unchecked") public static & Rational> FactorAbstract> getImplementation( edu.jas.application.RealAlgebraicRing fac) { edu.jas.root.RealAlgebraicRing rar = (edu.jas.root.RealAlgebraicRing) (Object) fac.realRing; return new FactorRealReal(fac, FactorFactory.> getImplementation(rar)); } /** * Determine suitable implementation of factorization algorithms, other * cases. * @param coefficient type * @param fac RingFactory<C>. * @return factorization algorithm implementation. */ @SuppressWarnings("unchecked") public static > FactorAbstract getImplementation(RingFactory fac) { logger.info("app factor factory = " + fac.getClass().getName()); //System.out.println("fac_o = " + fac.getClass().getName()); FactorAbstract/*raw type*/ufd = null; edu.jas.application.RealAlgebraicRing rrfac = null; RealAlgebraicRing rfac = null; AlgebraicNumberRing afac = null; ComplexRing cfac = null; QuotientRing qfac = null; GenPolynomialRing pfac = null; Object ofac = fac; if (ofac instanceof edu.jas.application.RealAlgebraicRing) { //System.out.println("rrfac_o = " + ofac); rrfac = (edu.jas.application.RealAlgebraicRing) ofac; //ofac = rrfac.realRing; ufd = new FactorRealReal/*raw */( rrfac, FactorFactory. getImplementation(rrfac.realRing)); } else if (ofac instanceof edu.jas.root.RealAlgebraicRing) { //System.out.println("rfac_o = " + ofac); rfac = (edu.jas.root.RealAlgebraicRing) ofac; //ofac = rfac.algebraic; ufd = new FactorRealAlgebraic/*raw */(rfac, FactorFactory.> getImplementation(rfac.algebraic)); } else if (ofac instanceof ComplexRing) { cfac = (ComplexRing) ofac; afac = cfac.algebraicRing(); ufd = new FactorComplex(cfac, FactorFactory. getImplementation(afac)); } else if (ofac instanceof AlgebraicNumberRing) { //System.out.println("afac_o = " + ofac); afac = (AlgebraicNumberRing) ofac; //ofac = afac.ring.coFac; ufd = new FactorAlgebraic/*raw */(afac, FactorFactory. getImplementation(afac.ring.coFac)); } else if (ofac instanceof QuotientRing) { //System.out.println("qfac_o = " + ofac); qfac = (QuotientRing) ofac; ufd = new FactorQuotient/*raw */(qfac, FactorFactory. getImplementation(qfac.ring.coFac)); } else if (ofac instanceof GenPolynomialRing) { //System.out.println("qfac_o = " + ofac); pfac = (GenPolynomialRing) ofac; ufd = getImplementation(pfac.coFac); } else { //System.out.println("no fac = " + fac.getClass().getName()); ufd = edu.jas.ufd.FactorFactory.getImplementation(fac); //return (FactorAbstract) ufd; } //logger.info("implementation = " + ufd); return (FactorAbstract) ufd; } } jas-2.5/src/edu/jas/application/GBAlgorithmBuilder.java0000644000175000017500000003264212120175412023302 0ustar giovannigiovanni/* * $Id: GBAlgorithmBuilder.java 4368 2013-03-13 22:17:46Z kredel $ */ package edu.jas.application; import java.io.Serializable; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.gb.GBOptimized; import edu.jas.gb.GBProxy; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.GroebnerBaseParallel; import edu.jas.gb.PairList; import edu.jas.gb.OrderedPairlist; import edu.jas.gb.OrderedMinPairlist; import edu.jas.gb.OrderedSyzPairlist; import edu.jas.gbufd.GBFactory; import edu.jas.gbufd.GroebnerBaseFGLM; import edu.jas.gbufd.GroebnerBasePseudoParallel; import edu.jas.gbufd.GroebnerBaseRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; /** * Builder for commutative Gröbner bases algorithm implementations. * @author Heinz Kredel * @usage To create objects that implement the GroebnerBase * interface one can use the GBFactory or this GBAlgorithmBuilder. * This class will select and compose an * appropriate implementation based on the types of polynomial * coefficients C and the desired properties. To build an implementation start with * the static method polynomialRing() to define the polynomial ring. * Then continue to construct the algorithm with the methods *
    *
  • optimize() or optimize(boolean) for term order (variable order) * optimization (true for return of permuted polynomials), *
  • *
  • normalPairlist() (default), syzygyPairlist() * or simplePairlist() * for pair-list selection strategies, *
  • *
  • fractionFree() for clearing denominators and computing with pseudo reduction, *
  • *
  • graded() for using the FGLM algorithm to first compute a * Gröbner base with respect to a * graded term order and then constructing a Gröbner base * wrt. a lexicographical term order, *
  • *
  • parallel() additionaly compute a Gröbner base over * a field or integral domain in parallel, *
  • *
  • euclideanDomain() for computing a e-Gröbner base, *
  • *
  • domainAlgorithm(Algo) for computing a d- or e-Gröbner base, *
  • *
* Finally call the method build() to obtain an implementaton of * class GroebnerBaseAbstract. For example * *
 *
 * GenPolynomialRing<C> pf = new GenPolynomialRing<C>(cofac, vars);
 * GroebnerBaseAbstract<C> engine;
 * engine = GBAlgorithmBuilder.<C> polynomialRing(pf).fractionFree().parallel().optimize().build();
 * c = engine.GB(A);
 * 
* * For example, if the coefficient type is BigRational, the usage looks * like * *
 *
 * GenPolynomialRing<BigRational> pf = new GenPolynomialRing<BigRational>(cofac, vars);
 * GroebnerBaseAbstract<BigRational> engine;
 * engine = GBAlgorithmBuilder.<BigRational> polynomialRing(pf).fractionFree().parallel().optimize().build();
 * c = engine.GB(A);
 * 
* * Note: Not all combinations are meanigful * * @see edu.jas.gb.GroebnerBase * @see edu.jas.gbufd.GBFactory */ public class GBAlgorithmBuilder> implements Serializable { private static final Logger logger = Logger.getLogger(GBAlgorithmBuilder.class); /** * The current GB algorithm implementation. */ private GroebnerBaseAbstract algo; /** * The current polynomial ring. */ public final GenPolynomialRing ring; /** * Requested pairlist strategy. */ public final PairList strategy; /** * Constructor not for use. */ protected GBAlgorithmBuilder() { throw new IllegalArgumentException("do not use this constructor"); } /** * Constructor. * @param ring the polynomial ring. */ public GBAlgorithmBuilder(GenPolynomialRing ring) { this(ring, null); } /** * Constructor. * @param ring the polynomial ring. * @param algo already determined algorithm. */ public GBAlgorithmBuilder(GenPolynomialRing ring, GroebnerBaseAbstract algo) { this(ring, algo, null); } /** * Constructor. * @param ring the polynomial ring. * @param algo already determined algorithm. * @param strategy pairlist strategy. */ public GBAlgorithmBuilder(GenPolynomialRing ring, GroebnerBaseAbstract algo, PairList strategy) { if ( ring == null ) { throw new IllegalArgumentException("ring may not be null"); } this.ring = ring; this.algo = algo; // null accepted if ( strategy == null ) { strategy = new OrderedPairlist(); } this.strategy = strategy; } /** * Build the GB algorithm implementaton. * @return GB algorithm implementaton as GroebnerBaseAbstract object. */ public GroebnerBaseAbstract build() { if (algo == null) { if ( strategy == null ) { // should not happen algo = GBFactory. getImplementation(ring.coFac); } else { algo = GBFactory. getImplementation(ring.coFac,strategy); } } return algo; } /** * Define polynomial ring. * @param fac the commutative polynomial ring. * @return GBAlgorithmBuilder object. */ public static > GBAlgorithmBuilder polynomialRing(GenPolynomialRing fac) { return new GBAlgorithmBuilder(fac); } /** * Select syzygy critical pair-list strategy. * Gebauer and Möller algorithm. * @return GBAlgorithmBuilder object. */ public GBAlgorithmBuilder syzygyPairlist() { return new GBAlgorithmBuilder(ring, algo, new OrderedSyzPairlist()); } /** * Select normal critical pair-list strategy. * Buchberger, Winkler and Kredel algorithm. * @return GBAlgorithmBuilder object. */ public GBAlgorithmBuilder normalPairlist() { return new GBAlgorithmBuilder(ring, algo, new OrderedPairlist()); } /** * Select simple critical pair-list strategy. * Original Buchberger algorithm. * @return GBAlgorithmBuilder object. */ public GBAlgorithmBuilder simplePairlist() { return new GBAlgorithmBuilder(ring, algo, new OrderedMinPairlist()); } /** * Request term order optimization. * Call optimize(true) for return of permuted polynomials. * @return GBAlgorithmBuilder object. */ public GBAlgorithmBuilder optimize() { return optimize(true); } /** * Request term order optimization. * @param rP true for return of permuted polynomials, false for inverse * permuted polynomials and new GB computation. * @return GBAlgorithmBuilder object. */ public GBAlgorithmBuilder optimize(boolean rP) { if (algo == null) { algo = GBFactory. getImplementation(ring.coFac,strategy); } GroebnerBaseAbstract bb = new GBOptimized(algo, rP); return new GBAlgorithmBuilder(ring, bb); } /** * Request fraction free algorithm. For BigRational and Quotient * coefficients denominators are cleared and pseudo reduction is * used. * @return GBAlgorithmBuilder object. */ @SuppressWarnings("unchecked") public GBAlgorithmBuilder fractionFree() { if (algo != null) { logger.warn("selected algorithm ignored: " + algo + ", use fractionFree before"); } if (((Object)ring.coFac) instanceof BigRational) { BigRational cf = (BigRational) (Object) ring.coFac; PairList sty = (PairList) strategy; GroebnerBaseAbstract bb = GBFactory.getImplementation(cf, GBFactory.Algo.ffgb, sty); GroebnerBaseAbstract cbb = (GroebnerBaseAbstract) (GroebnerBaseAbstract) bb; return new GBAlgorithmBuilder(ring, cbb); } if (((Object)ring.coFac) instanceof QuotientRing) { QuotientRing cf = (QuotientRing) (Object) ring.coFac; PairList> sty = (PairList) strategy; GroebnerBaseAbstract> bb = GBFactory. getImplementation(cf, GBFactory.Algo.ffgb, sty); GroebnerBaseAbstract cbb = (GroebnerBaseAbstract) (GroebnerBaseAbstract) bb; return new GBAlgorithmBuilder(ring, cbb); } logger.warn("no fraction free algorithm implemented for " + ring); return this; } /** * Request e-GB algorithm. * @return GBAlgorithmBuilder object. */ public GBAlgorithmBuilder euclideanDomain() { return domainAlgorithm(GBFactory.Algo.egb); } /** * Request d- or e-GB algorithm. * @param a algorithm from GBFactory.Algo. * @return GBAlgorithmBuilder object. */ @SuppressWarnings("unchecked") public GBAlgorithmBuilder domainAlgorithm(GBFactory.Algo a) { if (((Object)ring.coFac) instanceof BigInteger) { BigInteger cf = (BigInteger) (Object) ring.coFac; GroebnerBaseAbstract bb = GBFactory.getImplementation(cf, a); GroebnerBaseAbstract cbb = (GroebnerBaseAbstract) (GroebnerBaseAbstract) bb; return new GBAlgorithmBuilder(ring, cbb); } logger.warn("no domain algorithm implemented for " + ring); return this; } /** * Request parallel algorithm. * Additionaly run a parallel algorithm via GBProxy. * @return GBAlgorithmBuilder object. */ @SuppressWarnings("unchecked") public GBAlgorithmBuilder parallel() { return parallel(ComputerThreads.N_CPUS); } /** * Request parallel algorithm. * Additionaly run a parallel algorithm via GBProxy. * @param threads number of threads requested. * @return GBAlgorithmBuilder object. */ @SuppressWarnings("unchecked") public GBAlgorithmBuilder parallel(int threads) { if (ComputerThreads.NO_THREADS) { logger.warn("parallel algorithms disabled"); return this; } if (algo == null) { algo = GBFactory. getImplementation(ring.coFac, strategy); } if ( ((RingFactory)ring.coFac) instanceof BigRational) { GroebnerBaseAbstract bb; if (algo instanceof GroebnerBaseRational) { // fraction free requested bb = (GroebnerBaseAbstract) new GroebnerBaseRational(threads); } else { bb = (GroebnerBaseAbstract) new GroebnerBaseParallel(threads,strategy); } GroebnerBaseAbstract pbb = new GBProxy(algo, bb); return new GBAlgorithmBuilder(ring, pbb); } else if (ring.coFac.isField()) { GroebnerBaseAbstract bb = new GroebnerBaseParallel(threads, strategy); GroebnerBaseAbstract pbb = new GBProxy(algo, bb); return new GBAlgorithmBuilder(ring, pbb); } else if (ring.coFac.getONE() instanceof GcdRingElem) { GroebnerBaseAbstract bb = new GroebnerBasePseudoParallel(threads,ring.coFac,strategy); GroebnerBaseAbstract pbb = new GBProxy(algo, bb); return new GBAlgorithmBuilder(ring, pbb); } logger.warn("no parallel algorithm implemented for " + ring); return this; } /** * Request FGLM algorithm. * @return GBAlgorithmBuilder object. */ @SuppressWarnings("unchecked") public GBAlgorithmBuilder graded() { if (ring.coFac.isField()) { GroebnerBaseAbstract bb; if (algo == null) { bb = new GroebnerBaseFGLM(); } else { bb = new GroebnerBaseFGLM(algo); } return new GBAlgorithmBuilder(ring, bb); } logger.warn("no FGLM algorithm implemented for " + ring); return this; } /** * String representation of the GB algorithm implementation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer(" "); if ( algo != null ) { s.append(algo.toString()); s.append(" for "); } s.append(ring.toString()); return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ public String toScript() { // Python case StringBuffer s = new StringBuffer(" "); if ( algo != null ) { s.append(algo.toString()); // nonsense s.append(" "); } s.append(ring.toScript()); return s.toString(); } } jas-2.5/src/edu/jas/application/RealAlgebraicRing.java0000644000175000017500000002755011760654206023147 0ustar giovannigiovanni/* * $Id: RealAlgebraicRing.java 3947 2012-05-28 10:50:47Z kredel $ */ package edu.jas.application; import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.Scripting; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.root.RealRootTuple; import edu.jas.root.PolyUtilRoot; import edu.jas.root.Interval; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Real algebraic number factory class based on bi-variate real algebraic * numbers. Objects of this class are immutable with the exception of the * isolating intervals. Bi-variate ideal implementation is in version 3614 * 2011-04-28 09:20:34Z. * @author Heinz Kredel */ public class RealAlgebraicRing & Rational> implements RingFactory> { /** * Representing ideal with univariate polynomials IdealWithUniv. */ /*package*/final IdealWithUniv univs; /** * Representing ResidueRing. */ /*package*/final ResidueRing algebraic; /** * Isolating intervals for the real algebraic roots of the real and * imaginary part. Note: intervals may shrink eventually. */ /*package*/RealRootTuple root; /** * Recursive real root ring. */ public final edu.jas.root.RealAlgebraicRing> realRing; /** * Epsilon of the isolating rectangle for a complex root. */ protected C eps; /** * Precision of the isolating rectangle for a complex root. */ public final int PRECISION = 9; //BigDecimal.DEFAULT_PRECISION; private static final Logger logger = Logger.getLogger(RealAlgebraicRing.class); /** * The constructor creates a RealAlgebraicNumber factory object from a * IdealWithUniv, ResidueRing and a root tuple. * @param m module IdealWithUniv<C>. * @param a module ResidueRing<C>. * @param r isolating rectangle for a complex root. */ public RealAlgebraicRing(IdealWithUniv m, ResidueRing a, RealRootTuple r) { univs = m; algebraic = a; root = r; if (algebraic.characteristic().signum() > 0) { throw new IllegalArgumentException("characteristic not zero"); } C e = m.ideal.list.ring.coFac.fromInteger(10L); e = e.inverse(); e = Power.positivePower(e, PRECISION); eps = e; edu.jas.root.RealAlgebraicRing rfac1 = root.tuple.get(0).factory(); edu.jas.root.RealAlgebraicRing rfac2 = root.tuple.get(1).factory(); GenPolynomial p0 = PolyUtil. selectWithVariable(univs.ideal.list.list, 0); if (p0 == null) { throw new RuntimeException("no polynomial found in " + (0) + " of " + univs.ideal); } //System.out.println("realRing, pol = " + p0.toScript()); GenPolynomialRing pfac = p0.ring; GenPolynomialRing> prfac = pfac.recursive(1); //System.out.println("prfac = " + prfac); GenPolynomial> p0r = PolyUtil. recursive(prfac,p0); GenPolynomialRing> parfac = new GenPolynomialRing>(rfac1,prfac); GenPolynomial> p0ar = PolyUtilRoot. convertRecursiveToAlgebraicCoefficients(parfac,p0r); Interval r2 = rfac2.getRoot(); edu.jas.root.RealAlgebraicNumber rleft = rfac1.getZERO().sum(r2.left); edu.jas.root.RealAlgebraicNumber rright = rfac1.getZERO().sum(r2.right); Interval> r2r = new Interval>(rleft,rright); edu.jas.root.RealAlgebraicRing> rr = new edu.jas.root.RealAlgebraicRing>(p0ar,r2r); logger.info("realRing = " + rr); realRing = rr; } /** * The constructor creates a RealAlgebraicNumber factory object from a * IdealWithUniv and a root tuple. * @param m module IdealWithUniv<C>. * @param root isolating rectangle for a complex root. */ public RealAlgebraicRing(IdealWithUniv m, RealRootTuple root) { this(m, new ResidueRing(m.ideal), root); } /** * The constructor creates a RealAlgebraicNumber factory object from a * IdealWithUniv and a root tuple. * @param m module IdealWithUniv<C>. * @param root isolating rectangle for a complex root. * @param isField indicator if m is maximal. */ public RealAlgebraicRing(IdealWithUniv m, RealRootTuple root, boolean isField) { this(m, new ResidueRing(m.ideal, isField), root); } /** * Set a refined rectangle for the complex root. Note: rectangle may * shrink eventually. * @param v rectangle. */ public synchronized void setRoot(RealRootTuple v) { // assert v is contained in root this.root = v; } /** * Get rectangle for the complex root. * @return v rectangle. */ public synchronized RealRootTuple getRoot() { return this.root; } /** * Get epsilon. * @return epsilon. */ public synchronized C getEps() { return this.eps; } /** * Set a new epsilon. * @param e epsilon. */ public synchronized void setEps(C e) { this.eps = e; } /** * Set a new epsilon. * @param e epsilon. */ public synchronized void setEps(BigRational e) { edu.jas.root.RealAlgebraicRing r = (edu.jas.root.RealAlgebraicRing) realRing.algebraic.ring.coFac; this.eps = r.algebraic.ring.coFac.parse(e.toString()); } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return realRing.isFinite(); } /** * Copy RealAlgebraicNumber element c. * @param c * @return a copy of c. */ public RealAlgebraicNumber copy(RealAlgebraicNumber c) { return new RealAlgebraicNumber(this, c.number); } /** * Get the zero element. * @return 0 as RealAlgebraicNumber. */ public RealAlgebraicNumber getZERO() { return new RealAlgebraicNumber(this, realRing.getZERO()); } /** * Get the one element. * @return 1 as RealAlgebraicNumber. */ public RealAlgebraicNumber getONE() { return new RealAlgebraicNumber(this, realRing.getONE()); } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List>> agens = realRing .generators(); List> gens = new ArrayList>(agens.size()); for (edu.jas.root.RealAlgebraicNumber> a : agens) { gens.add(getZERO().sum(a)); } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return realRing.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return realRing.isAssociative(); } /** * Query if this ring is a field. * @return true if algebraic is prime, else false. */ public boolean isField() { return realRing.isField(); } /** * Assert that this ring is a field. * @param isField true if this ring is a field, else false. */ public void setField(boolean isField) { realRing.setField(isField); } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return realRing.characteristic(); } /** * Get a RealAlgebraicNumber element from a BigInteger value. * @param a BigInteger. * @return a RealAlgebraicNumber. */ public RealAlgebraicNumber fromInteger(java.math.BigInteger a) { return new RealAlgebraicNumber(this, realRing.fromInteger(a)); } /** * Get a RealAlgebraicNumber element from a long value. * @param a long. * @return a RealAlgebraicNumber. */ public RealAlgebraicNumber fromInteger(long a) { return new RealAlgebraicNumber(this, realRing.fromInteger(a)); } /** * Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { return "RealAlgebraicRing[ " + realRing.toString() + " in " + root + " | isField=" + realRing.isField() + ", algebraic.ideal=" + algebraic.ideal.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "RealRecN( " + realRing.toScript() + ", " + root.toScript() //+ ", " + realRing.isField() //+ ", " + realRing.ring.toScript() + " )"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object b) { if (!(b instanceof RealAlgebraicRing)) { return false; } RealAlgebraicRing a = null; try { a = (RealAlgebraicRing) b; } catch (ClassCastException e) { } if (a == null) { return false; } return realRing.equals(a.realRing) && root.equals(a.root); } /** * Hash code for this RealAlgebraicNumber. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * realRing.hashCode() + root.hashCode(); } /** * RealAlgebraicNumber random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random integer mod modul. */ public RealAlgebraicNumber random(int n) { return new RealAlgebraicNumber(this, realRing.random(n)); } /** * RealAlgebraicNumber random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random integer mod modul. */ public RealAlgebraicNumber random(int n, Random rnd) { return new RealAlgebraicNumber(this, realRing.random(n, rnd)); } /** * Parse RealAlgebraicNumber from String. * @param s String. * @return RealAlgebraicNumber from s. */ public RealAlgebraicNumber parse(String s) { return new RealAlgebraicNumber(this, realRing.parse(s)); } /** * Parse RealAlgebraicNumber from Reader. * @param r Reader. * @return next RealAlgebraicNumber from r. */ public RealAlgebraicNumber parse(Reader r) { return new RealAlgebraicNumber(this, realRing.parse(r)); } } jas-2.5/src/edu/jas/application/RootFactory.java0000644000175000017500000002722012014156146022110 0ustar giovannigiovanni/* * $Id: RootFactory.java 4111 2012-08-19 12:30:30Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import edu.jas.arith.Rational; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.root.Interval; import edu.jas.root.RealRootTuple; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.SquarefreeAbstract; import edu.jas.ufd.SquarefreeFactory; /** * Roots factory. * @author Heinz Kredel */ public class RootFactory { private static final Logger logger = Logger.getLogger(RootFactory.class); private static boolean debug = logger.isDebugEnabled(); /** * Is complex algebraic number a root of a polynomial. * @param f univariate polynomial. * @param r complex algebraic number. * @return true, if f(r) == 0, else false; */ public static & Rational> boolean isRootRealCoeff(GenPolynomial f, Complex> r) { RingFactory cfac = f.ring.coFac; ComplexRing ccfac = new ComplexRing(cfac); GenPolynomialRing> facc = new GenPolynomialRing>(ccfac, f.ring); GenPolynomial> fc = PolyUtil. complexFromAny(facc, f); return isRoot(fc, r); } /** * Is complex algebraic number a root of a polynomial. * @param f univariate polynomial. * @param r complex algebraic number. * @return true, if f(r) == 0, else false; */ public static & Rational> boolean isRoot(GenPolynomial> f, Complex> r) { ComplexRing> cr = r.factory(); GenPolynomialRing>> cfac = new GenPolynomialRing>>( cr, f.factory()); GenPolynomial>> p; p = PolyUtilApp. convertToComplexRealCoefficients(cfac, f); // test algebraic part Complex> a = PolyUtil.>> evaluateMain(cr, p, r); boolean t = a.isZERO(); if (!t) { logger.info("f(r) = " + a + ", f = " + f + ", r = " + r); return t; } // test approximation, not working RealAlgebraicRing rring = (RealAlgebraicRing) cr.ring; RealRootTuple rroot = rring.getRoot(); List> rlist = rroot.tuple; //System.out.println("rlist = " + rlist); Interval vr = rlist.get(0).ring.getRoot(); Interval vi = rlist.get(1).ring.getRoot(); ComplexRing ccfac = new ComplexRing((RingFactory) vr.left.factory()); Complex sw = new Complex(ccfac, vr.left, vi.left); Complex ne = new Complex(ccfac, vr.right, vi.right); Complex epsw = PolyUtil.> evaluateMain(ccfac, f, sw); Complex epne = PolyUtil.> evaluateMain(ccfac, f, ne); int rootre = (epsw.getRe().signum() * epne.getRe().signum()); int rootim = (epsw.getIm().signum() * epne.getIm().signum()); t = (rootre <= 0 && rootim <= 0); //logger.info("p(root): p = " + f + ", r = " + r.getRe() + " i " + r.getIm()); //logger.info("r = " + new BigDecimal(r.getRe().magnitude()) + " i " + new BigDecimal(r.getIm().magnitude())); //logger.info("vr = " + vr + ", vi = " + vi); //logger.info("sw = " + sw + ", ne = " + ne); //logger.info("root(re) = " + rootre + ", root(im) = " + rootim); //logger.info("epsw = " + new BigDecimal(epsw.getRe().getRational()) + " i " + new BigDecimal(epsw.getIm().getRational())); //logger.info("epne = " + new BigDecimal(epne.getRe().getRational()) + " i " + new BigDecimal(epne.getIm().getRational())); return true; } /** * Is complex algebraic number a root of a polynomial. * @param f univariate polynomial. * @param R list of complex algebraic numbers. * @return true, if f(r) == 0 for all r in R, else false; */ public static & Rational> boolean isRoot(GenPolynomial> f, List>> R) { for (Complex> r : R) { boolean t = isRoot(f, r); if (!t) { return false; } } return true; } /** * Complex algebraic number roots. * @param f univariate polynomial. * @return a list of different complex algebraic numbers, with f(c) == 0 for * c in roots. */ public static & Rational> List>> complexAlgebraicNumbersComplex( GenPolynomial> f) { GenPolynomialRing> pfac = f.factory(); if (pfac.nvar != 1) { throw new IllegalArgumentException("only for univariate polynomials"); } ComplexRing cfac = (ComplexRing) pfac.coFac; SquarefreeAbstract> engine = SquarefreeFactory.> getImplementation(cfac); Map>, Long> F = engine.squarefreeFactors(f.monic()); Set>> S = F.keySet(); //System.out.println("S = " + S); List>> list = new ArrayList>>(); for (GenPolynomial> sp : S) { if (sp.isConstant() || sp.isZERO()) { continue; } List>> ls = RootFactory. complexAlgebraicNumbersSquarefree(sp); long m = F.get(sp); for (long i = 0L; i < m; i++) { list.addAll(ls); } } return list; } /** * Complex algebraic number roots. * @param f univariate squarefree polynomial. * @return a list of different complex algebraic numbers, with f(c) == 0 for * c in roots. */ public static & Rational> List>> complexAlgebraicNumbersSquarefree( GenPolynomial> f) { GenPolynomialRing> pfac = f.factory(); if (pfac.nvar != 1) { throw new IllegalArgumentException("only for univariate polynomials"); } ComplexRing cfac = (ComplexRing) pfac.coFac; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing> tfac = new GenPolynomialRing>(cfac, 2, to); //,vars); //tord? //System.out.println("tfac = " + tfac); GenPolynomial> t = tfac.univariate(1, 1L).sum( tfac.univariate(0, 1L).multiply(cfac.getIMAG())); //System.out.println("t = " + t); // t = x + i y GenPolynomialRing rfac = new GenPolynomialRing(cfac.ring, tfac); //tord? //System.out.println("rfac = " + rfac); List>> list = new ArrayList>>(); GenPolynomial> sp = f; if (sp.isConstant() || sp.isZERO()) { return list; } // substitute t = x + i y GenPolynomial> su = PolyUtil.> substituteUnivariate(sp, t); //System.out.println("su = " + su); su = su.monic(); //System.out.println("su = " + su); GenPolynomial re = PolyUtil. realPartFromComplex(rfac, su); GenPolynomial im = PolyUtil. imaginaryPartFromComplex(rfac, su); if (debug) { logger.debug("rfac = " + rfac.toScript()); logger.debug("t = " + t + ", re = " + re.toScript() + ", im = " + im.toScript()); } List> li = new ArrayList>(2); li.add(re); li.add(im); Ideal id = new Ideal(rfac, li); //System.out.println("id = " + id); List> idul = id.zeroDimRootDecomposition(); IdealWithRealAlgebraicRoots idr; for (IdealWithUniv idu : idul) { //System.out.println("---idu = " + idu); idr = PolyUtilApp. realAlgebraicRoots(idu); //System.out.println("---idr = " + idr); for (List> crr : idr.ran) { //System.out.println("crr = " + crr); RealRootTuple root = new RealRootTuple(crr); //System.out.println("root = " + root); RealAlgebraicRing car = new RealAlgebraicRing(idu, root); //System.out.println("car = " + car); List> gens = car.generators(); //System.out.println("gens = " + gens); int sg = gens.size(); RealAlgebraicNumber rre = gens.get(sg - 2); RealAlgebraicNumber rim = gens.get(sg - 1); ComplexRing> cring = new ComplexRing>(car); Complex> crn = new Complex>(cring, rre, rim); //System.out.println("crn = " + crn + " in " + crn.ring); //boolean it; //int count = 0; //do { // refine intervals if necessary, not meaningful // Interval vr = crr.get(0).ring.getRoot(); // Interval vi = crr.get(1).ring.getRoot(); // ComplexRing ccfac = new ComplexRing((RingFactory) vr.left.factory()); // Complex sw = new Complex(ccfac, vr.left, vi.left); // Complex ne = new Complex(ccfac, vr.right, vi.right); // Complex epsw = PolyUtil.> evaluateMain(ccfac, f, sw); // Complex epne = PolyUtil.> evaluateMain(ccfac, f, ne); // int rootre = (epsw.getRe().signum() * epne.getRe().signum()); // int rootim = (epsw.getIm().signum() * epne.getIm().signum()); // it = true || (rootre <= 0 && rootim <= 0); // TODO // if (!it) { // logger.info("refine intervals: vr = " + vr + ", vi = " + vi); // + ", crn = " + crn.ring); // crn.getRe().ring.realRing.halfInterval(); // //System.out.println("crn.re = " + crn.getRe().ring.realRing); // crn.getIm().ring.realRing.halfInterval(); // //System.out.println("crn.im = " + crn.getIm().ring.realRing); // if (count++ > 2) { // //throw new RuntimeException("no roots of " + f); // logger.info("break in root refinement of " + crn + " in " + crn.ring); // it = true; // } // } //} while (!it); list.add(crn); } } return list; } /* todo * Complex algebraic numbers. * @param f univariate polynomial. * @param eps rational precision. * @return a list of different complex algebraic numbers. public static & Rational> List> complexAlgebraicNumbersComplex(GenPolynomial> f, BigRational eps) { } */ } jas-2.5/src/edu/jas/application/PolyUtilApp.java0000644000175000017500000024021712014234362022057 0ustar giovannigiovanni/* * $Id: PolyUtilApp.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.TreeSet; import org.apache.log4j.Logger; import edu.jas.arith.BigDecimal; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.arith.Rational; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; import edu.jas.root.ComplexRoots; import edu.jas.root.ComplexRootsAbstract; import edu.jas.root.ComplexRootsSturm; import edu.jas.root.Interval; import edu.jas.root.InvalidBoundaryException; import edu.jas.root.RealAlgebraicNumber; import edu.jas.root.RealAlgebraicRing; import edu.jas.root.RealRootTuple; import edu.jas.root.RealRootsAbstract; import edu.jas.root.RealRootsSturm; import edu.jas.root.Rectangle; import edu.jas.root.RootFactory; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.UnaryFunctor; import edu.jas.util.ListUtil; /** * Polynomial utilities for applications, for example conversion ExpVector to * Product or zero dimensional ideal root computation. * @param coefficient type * @author Heinz Kredel */ public class PolyUtilApp> { private static final Logger logger = Logger.getLogger(PolyUtilApp.class); private static boolean debug = logger.isDebugEnabled(); /** * Product representation. * @param coefficient type. * @param pfac polynomial ring factory. * @param L list of polynomials to be represented. * @return Product represenation of L in the polynomial ring pfac. */ public static > List>>> toProductRes( GenPolynomialRing>> pfac, List>> L) { List>>> list = new ArrayList>>>(); if (L == null || L.size() == 0) { return list; } GenPolynomial>> b; for (GenPolynomial> a : L) { b = toProductRes(pfac, a); list.add(b); } return list; } /** * Product representation. * @param coefficient type. * @param pfac polynomial ring factory. * @param A polynomial to be represented. * @return Product represenation of A in the polynomial ring pfac. */ public static > GenPolynomial>> toProductRes( GenPolynomialRing>> pfac, GenPolynomial> A) { GenPolynomial>> P = pfac.getZERO().copy(); if (A == null || A.isZERO()) { return P; } RingFactory>> rpfac = pfac.coFac; ProductRing> fac = (ProductRing>) rpfac; Product> p; for (Map.Entry> y : A.getMap().entrySet()) { ExpVector e = y.getKey(); GenPolynomial a = y.getValue(); p = toProductRes(fac, a); if (!p.isZERO()) { P.doPutToMap(e, p); } } return P; } /** * Product representation. * @param coefficient type. * @param pfac product ring factory. * @param c coefficient to be represented. * @return Product represenation of c in the ring pfac. */ public static > Product> toProductRes(ProductRing> pfac, GenPolynomial c) { SortedMap> elem = new TreeMap>(); for (int i = 0; i < pfac.length(); i++) { RingFactory> rfac = pfac.getFactory(i); ResidueRing fac = (ResidueRing) rfac; Residue u = new Residue(fac, c); //fac.fromInteger( c.getVal() ); if (!u.isZERO()) { elem.put(i, u); } } return new Product>(pfac, elem); } /** * Product residue representation. * @param coefficient type. * @param CS list of ColoredSystems from comprehensive GB system. * @return Product residue represenation of CS. */ public static > List>>> toProductRes( List> CS) { List>>> list = new ArrayList>>>(); if (CS == null || CS.size() == 0) { return list; } GenPolynomialRing> pr = null; List>> rrl = new ArrayList>>(CS.size()); for (ColoredSystem cs : CS) { Ideal id = cs.condition.zero; ResidueRing r = new ResidueRing(id); if (!rrl.contains(r)) { rrl.add(r); } if (pr == null) { if (cs.list.size() > 0) { pr = cs.list.get(0).green.ring; } } } ProductRing> pfac; pfac = new ProductRing>(rrl); //System.out.println("pfac = " + pfac); GenPolynomialRing>> rf = new GenPolynomialRing>>(pfac, pr.nvar, pr.tord, pr.getVars()); GroebnerSystem gs = new GroebnerSystem(CS); List>> F = gs.getCGB(); list = PolyUtilApp. toProductRes(rf, F); return list; } /** * Residue coefficient representation. * @param pfac polynomial ring factory. * @param L list of polynomials to be represented. * @return Represenation of L in the polynomial ring pfac. */ public static > List>> toResidue( GenPolynomialRing> pfac, List>> L) { List>> list = new ArrayList>>(); if (L == null || L.size() == 0) { return list; } GenPolynomial> b; for (GenPolynomial> a : L) { b = toResidue(pfac, a); if (!b.isZERO()) { list.add(b); } } return list; } /** * Residue coefficient representation. * @param pfac polynomial ring factory. * @param A polynomial to be represented. * @return Represenation of A in the polynomial ring pfac. */ public static > GenPolynomial> toResidue( GenPolynomialRing> pfac, GenPolynomial> A) { GenPolynomial> P = pfac.getZERO().copy(); if (A == null || A.isZERO()) { return P; } RingFactory> rpfac = pfac.coFac; ResidueRing fac = (ResidueRing) rpfac; Residue p; for (Map.Entry> y : A.getMap().entrySet()) { ExpVector e = y.getKey(); GenPolynomial a = y.getValue(); p = new Residue(fac, a); if (!p.isZERO()) { P.doPutToMap(e, p); } } return P; } /** * Product slice. * @param coefficient type. * @param L list of polynomials with product coefficients. * @return Slices represenation of L. */ public static > Map, PolynomialList>> productSlice( PolynomialList>> L) { Map, PolynomialList>> map; RingFactory>> fpr = L.ring.coFac; ProductRing> pr = (ProductRing>) fpr; int s = pr.length(); map = new TreeMap, PolynomialList>>(); List>> slist; List>>> plist = L.list; PolynomialList> spl; for (int i = 0; i < s; i++) { RingFactory> r = pr.getFactory(i); ResidueRing rr = (ResidueRing) r; Ideal id = rr.ideal; GenPolynomialRing cof = rr.ring; GenPolynomialRing> pfc; pfc = new GenPolynomialRing>(cof, L.ring); slist = fromProduct(pfc, plist, i); spl = new PolynomialList>(pfc, slist); PolynomialList> d = map.get(id); if (d != null) { throw new RuntimeException("ideal exists twice " + id); } map.put(id, spl); } return map; } /** * Product slice at i. * @param coefficient type. * @param L list of polynomials with product coeffients. * @param i index of slice. * @return Slice of of L at i. */ public static > PolynomialList> productSlice( PolynomialList>> L, int i) { RingFactory>> fpr = L.ring.coFac; ProductRing> pr = (ProductRing>) fpr; List>> slist; List>>> plist = L.list; PolynomialList> spl; RingFactory> r = pr.getFactory(i); ResidueRing rr = (ResidueRing) r; GenPolynomialRing cof = rr.ring; GenPolynomialRing> pfc; pfc = new GenPolynomialRing>(cof, L.ring); slist = fromProduct(pfc, plist, i); spl = new PolynomialList>(pfc, slist); return spl; } /** * From product representation. * @param coefficient type. * @param pfac polynomial ring factory. * @param L list of polynomials to be converted from product representation. * @param i index of product representation to be taken. * @return Represenation of i-slice of L in the polynomial ring pfac. */ public static > List>> fromProduct( GenPolynomialRing> pfac, List>>> L, int i) { List>> list = new ArrayList>>(); if (L == null || L.size() == 0) { return list; } GenPolynomial> b; for (GenPolynomial>> a : L) { b = fromProduct(pfac, a, i); if (!b.isZERO()) { b = b.abs(); if (!list.contains(b)) { list.add(b); } } } return list; } /** * From product representation. * @param coefficient type. * @param pfac polynomial ring factory. * @param P polynomial to be converted from product representation. * @param i index of product representation to be taken. * @return Represenation of i-slice of P in the polynomial ring pfac. */ public static > GenPolynomial> fromProduct( GenPolynomialRing> pfac, GenPolynomial>> P, int i) { GenPolynomial> b = pfac.getZERO().copy(); if (P == null || P.isZERO()) { return b; } for (Map.Entry>> y : P.getMap().entrySet()) { ExpVector e = y.getKey(); Product> a = y.getValue(); Residue r = a.get(i); if (r != null && !r.isZERO()) { GenPolynomial p = r.val; if (!p.isZERO()) { b.doPutToMap(e, p); } } } return b; } /** * Product slice to String. * @param coefficient type. * @param L list of polynomials with to be represented. * @return Product represenation of L in the polynomial ring pfac. */ public static > String productSliceToString( Map, PolynomialList>> L) { Set>> sl = new TreeSet>>(); PolynomialList> pl = null; StringBuffer sb = new StringBuffer(); //"\nproductSlice ----------------- begin"); for (Map.Entry, PolynomialList>> en : L.entrySet()) { sb.append("\n\ncondition == 0:\n"); sb.append(en.getKey().list.toScript()); pl = en.getValue(); //L.get(id); sl.addAll(pl.list); sb.append("\ncorresponding ideal:\n"); sb.append(pl.toScript()); } //List>> sll // = new ArrayList>>( sl ); //pl = new PolynomialList>(pl.ring,sll); // sb.append("\nunion = " + pl.toString()); //sb.append("\nproductSlice ------------------------- end\n"); return sb.toString(); } /** * Product slice to String. * @param coefficient type. * @param L list of polynomials with product coefficients. * @return string represenation of slices of L. */ public static > String productToString(PolynomialList>> L) { Map, PolynomialList>> M; M = productSlice(L); String s = productSliceToString(M); return s; } /** * Construct superset of complex roots for zero dimensional ideal(G). * @param I zero dimensional ideal. * @param eps desired precision. * @return list of coordinates of complex roots for ideal(G) */ public static & Rational> List>> complexRootTuples( Ideal I, D eps) { List> univs = I.constructUnivariate(); if (logger.isInfoEnabled()) { logger.info("univs = " + univs); } return complexRoots(I, univs, eps); } /** * Construct superset of complex roots for zero dimensional ideal(G). * @param I zero dimensional ideal. * @param univs list of univariate polynomials. * @param eps desired precision. * @return list of coordinates of complex roots for ideal(G) */ public static & Rational> List>> complexRoots( Ideal I, List> univs, D eps) { List>> croots = new ArrayList>>(); RingFactory cf = (RingFactory) I.list.ring.coFac; ComplexRing cr = new ComplexRing(cf); ComplexRootsAbstract cra = new ComplexRootsSturm(cr); List>> cunivs = new ArrayList>>(); for (GenPolynomial p : univs) { GenPolynomialRing> pfac = new GenPolynomialRing>(cr, p.ring); //System.out.println("pfac = " + pfac.toScript()); GenPolynomial> cp = PolyUtil. toComplex(pfac, p); cunivs.add(cp); //System.out.println("cp = " + cp); } for (int i = 0; i < I.list.ring.nvar; i++) { List> cri = cra.approximateRoots(cunivs.get(i), eps); //System.out.println("cri = " + cri); croots.add(cri); } croots = ListUtil.> tupleFromList(croots); return croots; } /** * Construct superset of complex roots for zero dimensional ideal(G). * @param Il list of zero dimensional ideals with univariate polynomials. * @param eps desired precision. * @return list of coordinates of complex roots for ideal(cap_i(G_i)) */ public static & Rational> List>> complexRootTuples( List> Il, D eps) { List>> croots = new ArrayList>>(); for (IdealWithUniv I : Il) { List>> cr = complexRoots(I.ideal, I.upolys, eps); croots.addAll(cr); } return croots; } /** * Construct superset of complex roots for zero dimensional ideal(G). * @param Il list of zero dimensional ideals with univariate polynomials. * @param eps desired precision. * @return list of ideals with coordinates of complex roots for * ideal(cap_i(G_i)) */ public static & Rational> List> complexRoots( List> Il, D eps) { List> Ic = new ArrayList>(Il.size()); for (IdealWithUniv I : Il) { List>> cr = complexRoots(I.ideal, I.upolys, eps); IdealWithComplexRoots ic = new IdealWithComplexRoots(I, cr); Ic.add(ic); } return Ic; } /** * Construct superset of complex roots for zero dimensional ideal(G). * @param G list of polynomials of a of zero dimensional ideal. * @param eps desired precision. * @return list of ideals with coordinates of complex roots for ideal(G) */ public static & Rational> List> complexRoots( Ideal G, D eps) { List> Il = G.zeroDimDecomposition(); return complexRoots(Il, eps); } /** * Construct superset of real roots for zero dimensional ideal(G). * @param I zero dimensional ideal. * @param eps desired precision. * @return list of coordinates of real roots for ideal(G) */ public static & Rational> List> realRootTuples(Ideal I, D eps) { List> univs = I.constructUnivariate(); if (logger.isInfoEnabled()) { logger.info("univs = " + univs); } return realRoots(I, univs, eps); } /** * Construct superset of real roots for zero dimensional ideal(G). * @param I zero dimensional ideal. * @param univs list of univariate polynomials. * @param eps desired precision. * @return list of coordinates of real roots for ideal(G) */ public static & Rational> List> realRoots(Ideal I, List> univs, D eps) { List> roots = new ArrayList>(); //RingFactory cf = (RingFactory) I.list.ring.coFac; RealRootsAbstract rra = new RealRootsSturm(); for (int i = 0; i < I.list.ring.nvar; i++) { List rri = rra.approximateRoots(univs.get(i), eps); //System.out.println("rri = " + rri); roots.add(rri); } //System.out.println("roots-1 = " + roots); roots = ListUtil. tupleFromList(roots); //System.out.println("roots-2 = " + roots); return roots; } /** * Construct superset of real roots for zero dimensional ideal(G). * @param Il list of zero dimensional ideals with univariate polynomials. * @param eps desired precision. * @return list of coordinates of real roots for ideal(cap_i(G_i)) */ public static & Rational> List> realRootTuples( List> Il, D eps) { List> rroots = new ArrayList>(); for (IdealWithUniv I : Il) { List> rr = realRoots(I.ideal, I.upolys, eps); rroots.addAll(rr); } return rroots; } /** * Construct superset of real roots for zero dimensional ideal(G). * @param Il list of zero dimensional ideals with univariate polynomials. * @param eps desired precision. * @return list of ideals with coordinates of real roots for * ideal(cap_i(G_i)) */ public static & Rational> List> realRoots( List> Il, D eps) { List> Ir = new ArrayList>(Il.size()); for (IdealWithUniv I : Il) { List> rr = realRoots(I.ideal, I.upolys, eps); IdealWithRealRoots ir = new IdealWithRealRoots(I, rr); Ir.add(ir); } return Ir; } /** * Construct superset of real roots for zero dimensional ideal(G). * @param G list of polynomials of a of zero dimensional ideal. * @param eps desired precision. * @return list of ideals with coordinates of real roots for ideal(G) */ public static & Rational> List> realRoots(Ideal G, D eps) { List> Il = G.zeroDimDecomposition(); return realRoots(Il, eps); } /** * Test for real roots of zero dimensional ideal(L). * @param L list of polynomials. * @param roots list of real roots for ideal(G). * @param eps desired precision. * @return true if root is a list of coordinates of real roots for ideal(L) */ public static boolean isRealRoots(List> L, List> roots, BigDecimal eps) { if (L == null || L.size() == 0) { return true; } // polynomials with decimal coefficients BigDecimal dc = BigDecimal.ONE; GenPolynomialRing dfac = L.get(0).ring; //System.out.println("dfac = " + dfac); for (GenPolynomial dp : L) { //System.out.println("dp = " + dp); for (List r : roots) { //System.out.println("r = " + r); BigDecimal ev = PolyUtil. evaluateAll(dc, dfac, dp, r); if (ev.abs().compareTo(eps) > 0) { System.out.println("ev = " + ev); return false; } } } return true; } /** * Test for complex roots of zero dimensional ideal(L). * @param L list of polynomials. * @param roots list of real roots for ideal(G). * @param eps desired precision. * @return true if root is a list of coordinates of complex roots for * ideal(L) */ public static boolean isComplexRoots(List>> L, List>> roots, BigDecimal eps) { if (L == null || L.size() == 0) { return true; } // polynomials with decimal coefficients BigDecimal dc = BigDecimal.ONE; ComplexRing dcc = new ComplexRing(dc); GenPolynomialRing> dfac = L.get(0).ring; //System.out.println("dfac = " + dfac); for (GenPolynomial> dp : L) { //System.out.println("dp = " + dp); for (List> r : roots) { //System.out.println("r = " + r); Complex ev = PolyUtil.> evaluateAll(dcc, dfac, dp, r); if (ev.norm().getRe().compareTo(eps) > 0) { System.out.println("ev = " + ev); return false; } } } return true; } /** * Construct real roots for zero dimensional ideal(G). * @param I zero dimensional ideal with univariate irreducible polynomials * and bi-variate polynomials. * @return real algebraic roots for ideal(G) */ public static & Rational> IdealWithRealAlgebraicRoots realAlgebraicRoots( IdealWithUniv I) { List>> ran = new ArrayList>>(); if (I == null) { throw new IllegalArgumentException("null ideal not permitted"); } if (I.ideal == null || I.upolys == null) { throw new IllegalArgumentException("null ideal components not permitted " + I); } if (I.ideal.isZERO() || I.upolys.size() == 0) { return new IdealWithRealAlgebraicRoots(I, ran); } GenPolynomialRing fac = I.ideal.list.ring; // case i == 0: GenPolynomial p0 = I.upolys.get(0); GenPolynomial p0p = PolyUtil. selectWithVariable(I.ideal.list.list, fac.nvar - 1); if (p0p == null) { throw new RuntimeException("no polynomial found in " + (fac.nvar - 1) + " of " + I.ideal); } //System.out.println("p0 = " + p0); if (logger.isInfoEnabled()) { logger.info("p0p = " + p0p); } int[] dep0 = p0p.degreeVector().dependencyOnVariables(); //System.out.println("dep0 = " + Arrays.toString(dep0)); if (dep0.length != 1) { throw new RuntimeException("wrong number of variables " + Arrays.toString(dep0)); } List> rra = RootFactory. realAlgebraicNumbersIrred(p0); if (logger.isInfoEnabled()) { List> il = new ArrayList>(); for (RealAlgebraicNumber rr : rra) { il.add(rr.ring.getRoot()); } logger.info("roots(p0) = " + il); } for (RealAlgebraicNumber rr : rra) { List> rl = new ArrayList>(); rl.add(rr); ran.add(rl); } // case i > 0: for (int i = 1; i < I.upolys.size(); i++) { List>> rn = new ArrayList>>(); GenPolynomial pi = I.upolys.get(i); GenPolynomial pip = PolyUtil.selectWithVariable(I.ideal.list.list, fac.nvar - 1 - i); if (pip == null) { throw new RuntimeException("no polynomial found in " + (fac.nvar - 1 - i) + " of " + I.ideal); } //System.out.println("i = " + i); //System.out.println("pi = " + pi); if (logger.isInfoEnabled()) { logger.info("pi = " + pi); logger.info("pip = " + pip); } int[] depi = pip.degreeVector().dependencyOnVariables(); //System.out.println("depi = " + Arrays.toString(depi)); if (depi.length < 1 || depi.length > 2) { throw new RuntimeException("wrong number of variables " + Arrays.toString(depi)); } rra = RootFactory. realAlgebraicNumbersIrred(pi); if (logger.isInfoEnabled()) { List> il = new ArrayList>(); for (RealAlgebraicNumber rr : rra) { il.add(rr.ring.getRoot()); } logger.info("roots(pi) = " + il); } if (depi.length == 1) { // all combinations are roots of the ideal I for (RealAlgebraicNumber rr : rra) { //System.out.println("rr.ring = " + rr.ring); for (List> rx : ran) { //System.out.println("rx = " + rx); List> ry = new ArrayList>(); ry.addAll(rx); ry.add(rr); rn.add(ry); } } } else { // depi.length == 2 // select roots of the ideal I GenPolynomial pip2 = PolyUtil. removeUnusedUpperVariables(pip); //System.out.println("pip2 = " + pip2.ring); GenPolynomialRing ufac = pip2.ring.contract(1); TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing> rfac = new GenPolynomialRing>(ufac, 1, to); GenPolynomial> pip2r = PolyUtil. recursive(rfac, pip2); int ix = fac.nvar - 1 - depi[depi.length - 1]; //System.out.println("ix = " + ix); for (RealAlgebraicNumber rr : rra) { //System.out.println("rr.ring = " + rr.ring); Interval rroot = rr.ring.getRoot(); GenPolynomial pip2el = PolyUtil. evaluateMainRecursive(ufac, pip2r, rroot.left); GenPolynomial pip2er = PolyUtil. evaluateMainRecursive(ufac, pip2r, rroot.right); GenPolynomialRing upfac = I.upolys.get(ix).ring; GenPolynomial pip2elc = convert(upfac, pip2el); GenPolynomial pip2erc = convert(upfac, pip2er); //System.out.println("pip2elc = " + pip2elc); //System.out.println("pip2erc = " + pip2erc); for (List> rx : ran) { //System.out.println("rx = " + rx); RealAlgebraicRing rar = rx.get(ix).ring; //System.out.println("rar = " + rar.toScript()); RealAlgebraicNumber rel = new RealAlgebraicNumber(rar, pip2elc); RealAlgebraicNumber rer = new RealAlgebraicNumber(rar, pip2erc); int sl = rel.signum(); int sr = rer.signum(); //System.out.println("sl = " + sl + ", sr = " + sr + ", sl*sr = " + (sl*sr)); if (sl * sr <= 0) { //System.out.println("sl * sr <= 0: rar = " + rar.toScript()); List> ry = new ArrayList>(); ry.addAll(rx); ry.add(rr); rn.add(ry); } } } } ran = rn; } if (logger.isInfoEnabled()) { for (List> rz : ran) { List> il = new ArrayList>(); for (RealAlgebraicNumber rr : rz) { il.add(rr.ring.getRoot()); } logger.info("root-tuple = " + il); } } IdealWithRealAlgebraicRoots Ir = new IdealWithRealAlgebraicRoots(I, ran); return Ir; } /** * Construct real roots for zero dimensional ideal(G). * @param I list of zero dimensional ideal with univariate irreducible * polynomials and bi-variate polynomials. * @return list of real algebraic roots for all ideal(I_i) */ public static & Rational> List> realAlgebraicRoots( List> I) { List> lir = new ArrayList>(I.size()); for (IdealWithUniv iu : I) { IdealWithRealAlgebraicRoots iur = PolyUtilApp. realAlgebraicRoots(iu); //System.out.println("iur = " + iur); lir.add(iur); } return lir; } /** * Construct complex roots for zero dimensional ideal(G). * @param I zero dimensional ideal with univariate irreducible polynomials * and bi-variate polynomials. * @return complex algebraic roots for ideal(G) Note: implementation * contains errors, do not use. */ public static & Rational> IdealWithComplexAlgebraicRoots complexAlgebraicRootsWrong( // Wrong IdealWithUniv I) { List>>> can; can = new ArrayList>>>(); if (I == null) { throw new IllegalArgumentException("null ideal not permitted"); } if (I.ideal == null || I.upolys == null) { throw new IllegalArgumentException("null ideal components not permitted " + I); } if (I.ideal.isZERO() || I.upolys.size() == 0) { return new IdealWithComplexAlgebraicRoots(I, can); } GenPolynomialRing fac = I.ideal.list.ring; if (fac.nvar == 0) { return new IdealWithComplexAlgebraicRoots(I, can); } if (fac.nvar != I.upolys.size()) { throw new IllegalArgumentException("ideal not zero dimnsional: " + I); } // case i == 0: GenPolynomial p0 = I.upolys.get(0); GenPolynomial p0p = PolyUtil. selectWithVariable(I.ideal.list.list, fac.nvar - 1); if (p0p == null) { throw new RuntimeException("no polynomial found in " + (fac.nvar - 1) + " of " + I.ideal); } if (logger.isInfoEnabled()) { logger.info("p0 = " + p0); logger.info("p0p = " + p0p); } int[] dep0 = p0p.degreeVector().dependencyOnVariables(); //System.out.println("dep0 = " + Arrays.toString(dep0)); if (dep0.length != 1) { throw new RuntimeException("wrong number of variables " + Arrays.toString(dep0)); } RingFactory cfac = p0.ring.coFac; ComplexRing ccfac = new ComplexRing(cfac); GenPolynomialRing> facc = new GenPolynomialRing>(ccfac, p0.ring); GenPolynomial> p0c = PolyUtil. complexFromAny(facc, p0); List>> cra; cra = edu.jas.application.RootFactory. complexAlgebraicNumbersSquarefree(p0c); logger.info("#roots(p0c) = " + cra.size()); if (debug) { boolean t = edu.jas.application.RootFactory. isRoot(p0c, cra); if (!t) { throw new RuntimeException("no roots of " + p0c); } } for (Complex> cr : cra) { List>> cl; cl = new ArrayList>>(); cl.add(cr); can.add(cl); } if (fac.nvar == 1) { return new IdealWithComplexAlgebraicRoots(I, can); } // case i > 0: for (int i = 1; i < I.upolys.size(); i++) { List>>> cn; cn = new ArrayList>>>(); GenPolynomial pi = I.upolys.get(i); GenPolynomial pip = PolyUtil.selectWithVariable(I.ideal.list.list, fac.nvar - 1 - i); if (pip == null) { throw new RuntimeException("no polynomial found in " + (fac.nvar - 1 - i) + " of " + I.ideal); } if (logger.isInfoEnabled()) { logger.info("pi(" + i + ") = " + pi); logger.info("pip = " + pip); } facc = new GenPolynomialRing>(ccfac, pi.ring); GenPolynomial> pic = PolyUtil. complexFromAny(facc, pi); int[] depi = pip.degreeVector().dependencyOnVariables(); //System.out.println("depi = " + Arrays.toString(depi)); if (depi.length < 1 || depi.length > 2) { throw new RuntimeException("wrong number of variables " + Arrays.toString(depi) + " for " + pip); } cra = edu.jas.application.RootFactory. complexAlgebraicNumbersSquarefree(pic); logger.info("#roots(pic) = " + cra.size()); if (debug) { boolean t = edu.jas.application.RootFactory. isRoot(pic, cra); if (!t) { throw new RuntimeException("no roots of " + pic); } } if (depi.length == 1) { // all combinations are roots of the ideal I for (Complex> cr : cra) { //System.out.println("cr.ring = " + cr.ring); for (List>> cx : can) { //System.out.println("cx = " + cx); List>> cy; cy = new ArrayList>>(); cy.addAll(cx); cy.add(cr); cn.add(cy); } } } else { // depi.length == 2 // select roots of the ideal I GenPolynomial pip2 = PolyUtil. removeUnusedUpperVariables(pip); GenPolynomialRing> rfac = pip2.ring.recursive(1); GenPolynomialRing ufac = pip2.ring.contract(1); GenPolynomialRing> ucfac = new GenPolynomialRing>(ccfac, ufac); GenPolynomialRing> c2fac = new GenPolynomialRing>(ccfac, pip2.ring); GenPolynomial> pip2c = PolyUtil. complexFromAny(c2fac, pip2); //System.out.println("pip2c = " + pip2c); GenPolynomialRing>> rcfac; rcfac = new GenPolynomialRing>>(ucfac, rfac); GenPolynomial>> pip2cr = PolyUtil.> recursive(rcfac, pip2c); //System.out.println("pip2cr = " + pip2cr); int ix = fac.nvar - 1 - depi[depi.length - 1]; //System.out.println("ix = " + ix); for (Complex> cr : cra) { System.out.println("cr = " + toString(cr)); // <---------------------------------- edu.jas.application.RealAlgebraicRing cring = (edu.jas.application.RealAlgebraicRing) cr.ring.ring; RealRootTuple rroot = cring.getRoot(); List> rlist = rroot.tuple; Interval vr = rlist.get(0).ring.getRoot(); Interval vi = rlist.get(1).ring.getRoot(); logger.info("vr = " + vr + ", vi = " + vi); if (vr.length().isZERO()) { D e = vr.left.factory().parse("1/2"); D m = vr.left; //middle(); vr = new Interval(m.subtract(e), m.sum(e)); logger.info("|vr| == 0: " + vr); } if (vi.length().isZERO()) { D e = vi.left.factory().parse("1/2"); D m = vi.left; //middle(); vi = new Interval(m.subtract(e), m.sum(e)); logger.info("|vi| == 0: " + vi); } Complex sw = new Complex(ccfac, vr.left, vi.left); Complex ne = new Complex(ccfac, vr.right, vi.right); logger.info("sw = " + toString1(sw) + ", ne = " + toString1(ne)); GenPolynomial> pip2cesw, pip2cene; pip2cesw = PolyUtil.> evaluateMainRecursive(ucfac, pip2cr, sw); pip2cene = PolyUtil.> evaluateMainRecursive(ucfac, pip2cr, ne); GenPolynomialRing upfac = I.upolys.get(ix).ring; GenPolynomialRing> upcfac = new GenPolynomialRing>(ccfac, upfac); //System.out.println("upfac = " + upfac); //System.out.println("upcfac = " + upcfac); GenPolynomial> pip2eswc = convertComplexComplex(upcfac, pip2cesw); GenPolynomial> pip2enec = convertComplexComplex(upcfac, pip2cene); //System.out.println("pip2eswc = " + pip2eswc); //System.out.println("pip2enec = " + pip2enec); for (List>> cx : can) { //System.out.println("cxi = " + toString(cx.get(ix))); Complex> cax = cx.get(ix); ComplexRing> car = cax.ring; edu.jas.application.RealAlgebraicRing rar = (edu.jas.application.RealAlgebraicRing) car.ring; //System.out.println("car = " + car); //System.out.println("rar = " + rar); TermOrder to = new TermOrder(TermOrder.INVLEX); String vvr = rar.algebraic.ring.getVars()[0]; String vvi = rar.algebraic.ring.getVars()[1]; String[] vars = new String[] { vvr, vvi }; GenPolynomialRing> tfac = new GenPolynomialRing>(ccfac, to, vars); GenPolynomial> t = tfac.univariate(1, 1L).sum( tfac.univariate(0, 1L).multiply(ccfac.getIMAG())); //System.out.println("t = " + t); // t = x + i y GenPolynomialRing rtfac = new GenPolynomialRing(cfac, tfac); GenPolynomial> su; GenPolynomial re, im; su = PolyUtil.> substituteUnivariate(pip2eswc, t); //su = su.monic(); not here re = PolyUtil. realPartFromComplex(rtfac, su); im = PolyUtil. imaginaryPartFromComplex(rtfac, su); //System.out.println("re = " + re); //System.out.println("im = " + im); edu.jas.application.RealAlgebraicNumber resw, imsw, rene, imne; resw = new edu.jas.application.RealAlgebraicNumber(rar, re); //System.out.println("resw = " + resw); int sswr = resw.signum(); imsw = new edu.jas.application.RealAlgebraicNumber(rar, im); //System.out.println("imsw = " + imsw); int sswi = imsw.signum(); su = PolyUtil.> substituteUnivariate(pip2enec, t); //su = su.monic(); not here re = PolyUtil. realPartFromComplex(rtfac, su); im = PolyUtil. imaginaryPartFromComplex(rtfac, su); //System.out.println("re = " + re); //System.out.println("im = " + im); rene = new edu.jas.application.RealAlgebraicNumber(rar, re); //System.out.println("rene = " + rene); int sner = rene.signum(); imne = new edu.jas.application.RealAlgebraicNumber(rar, im); //System.out.println("imne = " + imne); int snei = imne.signum(); //System.out.println("sswr = " + sswr + ", sswi = " + sswi); //System.out.println("sner = " + sner + ", snei = " + snei); if ((sswr * sner <= 0 && sswi * snei <= 0)) { // wrong ! logger.info(" hit, cxi = " + toString(cx.get(ix)) + ", cr = " + toString(cr)); List>> cy; cy = new ArrayList>>(); cy.addAll(cx); cy.add(cr); cn.add(cy); } else { logger.info("no hit, cxi = " + toString(cx.get(ix)) + ", cr = " + toString(cr)); } } } } can = cn; } IdealWithComplexAlgebraicRoots Ic = new IdealWithComplexAlgebraicRoots(I, can); return Ic; } /** * Construct complex roots for zero dimensional ideal(G). * @param I zero dimensional ideal with univariate irreducible polynomials * and bi-variate polynomials. * @return complex algebraic roots for ideal(G) Note: not jet * completed oin all cases. */ public static & Rational> IdealWithComplexAlgebraicRoots complexAlgebraicRoots( IdealWithUniv I) { List>>> can; can = new ArrayList>>>(); if (I == null) { throw new IllegalArgumentException("null ideal not permitted"); } if (I.ideal == null || I.upolys == null) { throw new IllegalArgumentException("null ideal components not permitted " + I); } if (I.ideal.isZERO() || I.upolys.size() == 0) { return new IdealWithComplexAlgebraicRoots(I, can); } GenPolynomialRing fac = I.ideal.list.ring; if (fac.nvar == 0) { return new IdealWithComplexAlgebraicRoots(I, can); } if (fac.nvar != I.upolys.size()) { throw new IllegalArgumentException("ideal not zero dimnsional: " + I); } // case i == 0: GenPolynomial p0 = I.upolys.get(0); GenPolynomial p0p = PolyUtil. selectWithVariable(I.ideal.list.list, fac.nvar - 1); if (p0p == null) { throw new RuntimeException("no polynomial found in " + (fac.nvar - 1) + " of " + I.ideal); } if (logger.isInfoEnabled()) { logger.info("p0 = " + p0); logger.info("p0p = " + p0p); } int[] dep0 = p0p.degreeVector().dependencyOnVariables(); //System.out.println("dep0 = " + Arrays.toString(dep0)); if (dep0.length != 1) { throw new RuntimeException("wrong number of variables " + Arrays.toString(dep0)); } RingFactory cfac = p0.ring.coFac; ComplexRing ccfac = new ComplexRing(cfac); GenPolynomialRing> facc = new GenPolynomialRing>(ccfac, p0.ring); GenPolynomial> p0c = PolyUtil. complexFromAny(facc, p0); List>> cra; cra = edu.jas.application.RootFactory. complexAlgebraicNumbersSquarefree(p0c); logger.info("#roots(p0c) = " + cra.size()); for (Complex> cr : cra) { List>> cl; cl = new ArrayList>>(); cl.add(cr); can.add(cl); } if (fac.nvar == 1) { return new IdealWithComplexAlgebraicRoots(I, can); } // case i > 0: for (int i = 1; i < I.upolys.size(); i++) { List>>> cn; cn = new ArrayList>>>(); GenPolynomial pi = I.upolys.get(i); GenPolynomial pip = PolyUtil.selectWithVariable(I.ideal.list.list, fac.nvar - 1 - i); if (pip == null) { throw new RuntimeException("no polynomial found in " + (fac.nvar - 1 - i) + " of " + I.ideal); } if (logger.isInfoEnabled()) { logger.info("pi(" + i + ") = " + pi); logger.info("pip = " + pip); } facc = new GenPolynomialRing>(ccfac, pi.ring); GenPolynomial> pic = PolyUtil. complexFromAny(facc, pi); int[] depi = pip.degreeVector().dependencyOnVariables(); //System.out.println("depi = " + Arrays.toString(depi)); if (depi.length < 1 || depi.length > 2) { throw new RuntimeException("wrong number of variables " + Arrays.toString(depi) + " for " + pip); } cra = edu.jas.application.RootFactory. complexAlgebraicNumbersSquarefree(pic); logger.info("#roots(pic) = " + cra.size()); if (depi.length == 1) { // all combinations are roots of the ideal I for (Complex> cr : cra) { //System.out.println("cr.ring = " + cr.ring); for (List>> cx : can) { //System.out.println("cx = " + cx); List>> cy; cy = new ArrayList>>(); cy.addAll(cx); cy.add(cr); cn.add(cy); } } } else { // depi.length == 2 // select roots of the ideal I GenPolynomial pip2 = PolyUtil. removeUnusedUpperVariables(pip); pip2 = PolyUtil. removeUnusedLowerVariables(pip2); pip2 = PolyUtil. removeUnusedMiddleVariables(pip2); GenPolynomialRing> rfac = pip2.ring.recursive(1); GenPolynomialRing ufac = pip2.ring.contract(1); GenPolynomialRing> ucfac = new GenPolynomialRing>(ccfac, ufac); GenPolynomialRing> c2fac = new GenPolynomialRing>(ccfac, pip2.ring); GenPolynomial> pip2c = PolyUtil. complexFromAny(c2fac, pip2); GenPolynomialRing>> rcfac; rcfac = new GenPolynomialRing>>(ucfac, rfac); GenPolynomial>> pip2cr = PolyUtil.> recursive(rcfac, pip2c); //System.out.println("pip2cr = " + pip2cr); int ix = fac.nvar - 1 - depi[depi.length - 1]; //System.out.println("ix = " + ix); for (Complex> cr : cra) { //System.out.println("cr = " + toString(cr)); edu.jas.application.RealAlgebraicRing cring = (edu.jas.application.RealAlgebraicRing) cr.ring.ring; RealRootTuple rroot = cring.getRoot(); List> rlist = rroot.tuple; //System.out.println("rlist = " + rlist); Interval vr = rlist.get(0).ring.getRoot(); Interval vi = rlist.get(1).ring.getRoot(); //logger.info("vr = " + vr + ", vi = " + vi); edu.jas.application.RealAlgebraicNumber vrl, vil, vrr, vir; vrl = new edu.jas.application.RealAlgebraicNumber(cring, vr.left); vil = new edu.jas.application.RealAlgebraicNumber(cring, vi.left); vrr = new edu.jas.application.RealAlgebraicNumber(cring, vr.right); vir = new edu.jas.application.RealAlgebraicNumber(cring, vi.right); ComplexRing> crr; crr = new ComplexRing>(cring); Complex> csw, cne; csw = new Complex>(crr, vrl, vil); cne = new Complex>(crr, vrr, vir); //logger.info("csw = " + toString(csw) + ", cne = " + toString(cne)); Rectangle> rec; rec = new Rectangle>(csw, cne); //System.out.println("rec = " + rec); for (List>> cx : can) { Complex> cax = cx.get(ix); //System.out.println("cax = " + toString(cax)); ComplexRing> car = cax.ring; //System.out.println("car = " + car); GenPolynomialRing>> pcrfac; pcrfac = new GenPolynomialRing>>( car, rcfac); GenPolynomial>> pcr; pcr = evaluateToComplexRealCoefficients(pcrfac, pip2cr, cax); //System.out.println("pcr = " + pcr); ComplexRoots> rengine; rengine = new ComplexRootsSturm>(car); long nr = 0; try { nr = rengine.complexRootCount(rec, pcr); //logger.info("rootCount = " + nr); } catch (InvalidBoundaryException e) { e.printStackTrace(); } if (nr == 1) { // one root logger.info(" hit, cxi = " + toString(cx.get(ix)) + ", cr = " + toString(cr)); List>> cy; cy = new ArrayList>>(); cy.addAll(cx); cy.add(cr); cn.add(cy); } else if (nr > 1) { logger.error("to many roots, cxi = " + toString(cx.get(ix)) + ", cr = " + toString(cr)); } else { // no root logger.info("no hit, cxi = " + toString(cx.get(ix)) + ", cr = " + toString(cr)); } } } } can = cn; } IdealWithComplexAlgebraicRoots Ic = new IdealWithComplexAlgebraicRoots(I, can); return Ic; } /** * String representation of a deximal approximation of a complex number. * @param c compelx number. * @return String representation of c */ public static & Rational> String toString( Complex> c) { edu.jas.application.RealAlgebraicNumber re = c.getRe(); edu.jas.application.RealAlgebraicNumber im = c.getIm(); String s = re.decimalMagnitude().toString(); if (!im.isZERO()) { s = s + "i" + im.decimalMagnitude(); } return s; } /** * String representation of a deximal approximation of a complex number. * @param c compelx number. * @return String representation of c */ public static & Rational> String toString1(Complex c) { D re = c.getRe(); D im = c.getIm(); String s = new BigDecimal(re.getRational()).toString(); if (!im.isZERO()) { s = s + "i" + new BigDecimal(im.getRational()); } return s; } /** * Construct complex roots for zero dimensional ideal(G). * @param I list of zero dimensional ideal with univariate irreducible * polynomials and bi-variate polynomials. * @return list of complex algebraic roots for ideal(G) */ public static & Rational> List> complexAlgebraicRoots( List> I) { List> lic = new ArrayList>(); for (IdealWithUniv iu : I) { IdealWithComplexAlgebraicRoots iuc = PolyUtilApp. complexAlgebraicRoots(iu); //System.out.println("iuc = " + iuc); lic.add(iuc); } return lic; } /** * Construct exact set of complex roots for zero dimensional ideal(G). * @param I zero dimensional ideal. * @return list of coordinates of complex roots for ideal(G) */ public static & Rational> List> complexAlgebraicRoots( Ideal I) { List> Ir = I.zeroDimRootDecomposition(); //System.out.println("Ir = " + Ir); List> roots = PolyUtilApp. complexAlgebraicRoots(Ir); return roots; } /* * Convert to a polynomial in given ring. * @param fac result polynomial ring. * @param p polynomial. * @return polynomial in ring fac Note: if p can not be represented * in fac then the results are unpredictable. */ static > GenPolynomial convert(GenPolynomialRing fac, GenPolynomial p) { if (fac.equals(p.factory())) { return p; } GenPolynomial q = fac.parse(p.toString()); if (!q.toString().equals(p.toString())) { throw new RuntimeException("convert(" + p + ") = " + q); } return q; } /* * Convert to a polynomial in given ring. * @param fac result polynomial ring. * @param p polynomial. * @return polynomial in ring fac Note: if p can not be represented * in fac then the results are unpredictable. */ static > GenPolynomial> convertComplex( GenPolynomialRing> fac, GenPolynomial p) { GenPolynomial> q = fac.parse(p.toString()); if (!q.toString().equals(p.toString())) { throw new RuntimeException("convert(" + p + ") = " + q); } return q; } /* * Convert to a polynomial in given ring. * @param fac result polynomial ring. * @param p complex polynomial. * @return polynomial in ring fac Note: if p can not be represented * in fac then the results are unpredictable. */ static > GenPolynomial> convertComplexComplex( GenPolynomialRing> fac, GenPolynomial> p) { if (fac.equals(p.factory())) { return p; } GenPolynomial> q = fac.parse(p.toString()); if (!q.toString().equals(p.toString())) { throw new RuntimeException("convert(" + p + ") = " + q); } return q; } /** * Construct exact set of real roots for zero dimensional ideal(G). * @param I zero dimensional ideal. * @return list of coordinates of real roots for ideal(G) */ public static & Rational> List> realAlgebraicRoots( Ideal I) { List> Ir = I.zeroDimRootDecomposition(); //System.out.println("Ir = " + Ir); List> roots = PolyUtilApp. realAlgebraicRoots(Ir); return roots; } /** * Construct primitive element for double field extension. * @param a algebraic number ring with squarefree monic minimal polynomial * @param b algebraic number ring with squarefree monic minimal polynomial * @return primitive element container with algebraic number ring c, with * Q(c) = Q(a,b) */ public static > PrimitiveElement primitiveElement(AlgebraicNumberRing a, AlgebraicNumberRing b) { GenPolynomial ap = a.modul; GenPolynomial bp = b.modul; // setup bivariate polynomial ring String[] cv = new String[2]; cv[0] = ap.ring.getVars()[0]; cv[1] = bp.ring.getVars()[0]; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing cfac = new GenPolynomialRing(ap.ring.coFac, 2, to, cv); GenPolynomial as = ap.extendUnivariate(cfac, 0); GenPolynomial bs = bp.extendUnivariate(cfac, 1); List> L = new ArrayList>(2); L.add(as); L.add(bs); List> Op = new ArrayList>(); Ideal id = new Ideal(cfac, L); //System.out.println("id = " + id); IdealWithUniv iu = id.normalPositionFor(0, 1, Op); //System.out.println("iu = " + iu); // extract result polynomials List> Np = iu.ideal.getList(); //System.out.println("Np = " + Np); as = PolyUtil. selectWithVariable(Np, 1); bs = PolyUtil. selectWithVariable(Np, 0); GenPolynomial cs = PolyUtil. selectWithVariable(Np, 2); //System.out.println("as = " + as); //System.out.println("bs = " + bs); //System.out.println("cs = " + cs); String[] ev = new String[] { cs.ring.getVars()[0] }; GenPolynomialRing efac = new GenPolynomialRing(ap.ring.coFac, 1, to, ev); //System.out.println("efac = " + efac); cs = cs.contractCoeff(efac); //System.out.println("cs = " + cs); as = as.reductum().contractCoeff(efac); as = as.negate(); //System.out.println("as = " + as); bs = bs.reductum().contractCoeff(efac); bs = bs.negate(); //System.out.println("bs = " + bs); AlgebraicNumberRing c = new AlgebraicNumberRing(cs); AlgebraicNumber ab = new AlgebraicNumber(c, as); AlgebraicNumber bb = new AlgebraicNumber(c, bs); PrimitiveElement pe = new PrimitiveElement(c, ab, bb, a, b); if (logger.isInfoEnabled()) { logger.info("primitive element = " + c); } return pe; } /** * Convert to primitive element ring. * @param cfac primitive element ring. * @param A algebraic number representing the generating element of a in the * new ring. * @param a algebraic number to convert. * @return a converted to the primitive element ring */ public static > AlgebraicNumber convertToPrimitiveElem( AlgebraicNumberRing cfac, AlgebraicNumber A, AlgebraicNumber a) { GenPolynomialRing aufac = a.ring.ring; GenPolynomialRing> ar = new GenPolynomialRing>(cfac, aufac); GenPolynomial> aps = PolyUtil. convertToAlgebraicCoefficients(ar, a.val); AlgebraicNumber ac = PolyUtil.> evaluateMain(cfac, aps, A); return ac; } /** * Convert coefficients to primitive element ring. * @param cfac primitive element ring. * @param A algebraic number representing the generating element of a in the * new ring. * @param a polynomial with coefficients algebraic number to convert. * @return a with coefficients converted to the primitive element ring */ public static > GenPolynomial> convertToPrimitiveElem( AlgebraicNumberRing cfac, AlgebraicNumber A, GenPolynomial> a) { GenPolynomialRing> cr = new GenPolynomialRing>(cfac, a.ring); return PolyUtil., AlgebraicNumber> map(cr, a, new CoeffConvertAlg(cfac, A)); } /** * Convert to primitive element ring. * @param cfac primitive element ring. * @param A algebraic number representing the generating element of a in the * new ring. * @param a recursive algebraic number to convert. * @return a converted to the primitive element ring */ public static > AlgebraicNumber convertToPrimitiveElem( AlgebraicNumberRing cfac, AlgebraicNumber A, AlgebraicNumber B, AlgebraicNumber> a) { GenPolynomial> aps = PolyUtilApp. convertToPrimitiveElem(cfac, A, a.val); AlgebraicNumber ac = PolyUtil.> evaluateMain(cfac, aps, B); return ac; } /** * Construct primitive element for double field extension. * @param b algebraic number ring with squarefree monic minimal polynomial * over Q(a) * @return primitive element container with algebraic number ring c, with * Q(c) = Q(a)(b) */ public static > PrimitiveElement primitiveElement( AlgebraicNumberRing> b) { GenPolynomial> bp = b.modul; AlgebraicNumberRing a = (AlgebraicNumberRing) b.ring.coFac; GenPolynomial ap = a.modul; // setup bivariate polynomial ring String[] cv = new String[2]; cv[0] = ap.ring.getVars()[0]; cv[1] = bp.ring.getVars()[0]; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing cfac = new GenPolynomialRing(ap.ring.coFac, 2, to, cv); GenPolynomialRing> rfac = new GenPolynomialRing>(a.ring, 1, bp.ring.getVars()); GenPolynomial as = ap.extendUnivariate(cfac, 0); GenPolynomial> bss = PolyUtil. fromAlgebraicCoefficients(rfac, bp); GenPolynomial bs = PolyUtil. distribute(cfac, bss); List> L = new ArrayList>(2); L.add(as); L.add(bs); List> Op = new ArrayList>(); Ideal id = new Ideal(cfac, L); //System.out.println("id = " + id); IdealWithUniv iu = id.normalPositionFor(0, 1, Op); //System.out.println("iu = " + iu); // extract result polynomials List> Np = iu.ideal.getList(); as = PolyUtil. selectWithVariable(Np, 1); bs = PolyUtil. selectWithVariable(Np, 0); GenPolynomial cs = PolyUtil. selectWithVariable(Np, 2); //System.out.println("as = " + as); //System.out.println("bs = " + bs); //System.out.println("cs = " + cs); String[] ev = new String[] { cs.ring.getVars()[0] }; GenPolynomialRing efac = new GenPolynomialRing(ap.ring.coFac, 1, to, ev); // System.out.println("efac = " + efac); cs = cs.contractCoeff(efac); // System.out.println("cs = " + cs); as = as.reductum().contractCoeff(efac); as = as.negate(); // System.out.println("as = " + as); bs = bs.reductum().contractCoeff(efac); bs = bs.negate(); //System.out.println("bs = " + bs); AlgebraicNumberRing c = new AlgebraicNumberRing(cs); AlgebraicNumber ab = new AlgebraicNumber(c, as); AlgebraicNumber bb = new AlgebraicNumber(c, bs); PrimitiveElement pe = new PrimitiveElement(c, ab, bb); // missing ,a,b); if (logger.isInfoEnabled()) { logger.info("primitive element = " + pe); } return pe; } /** * Convert to primitive element ring. * @param cfac primitive element ring. * @param A algebraic number representing the generating element of a in the * new ring. * @param a polynomial with recursive algebraic number coefficients to * convert. * @return a converted to the primitive element ring */ public static > GenPolynomial> convertToPrimitiveElem( AlgebraicNumberRing cfac, AlgebraicNumber A, AlgebraicNumber B, GenPolynomial>> a) { GenPolynomialRing> cr = new GenPolynomialRing>(cfac, a.ring); return PolyUtil.>, AlgebraicNumber> map(cr, a, new CoeffRecConvertAlg(cfac, A, B)); } /** * Convert to RealAlgebraicNumber coefficients. Represent as polynomial with * RealAlgebraicNumber coefficients from package * *
     * edu.jas.root
     * 
* * . * @param afac result polynomial factory. * @param A polynomial with RealAlgebraicNumber<C> coefficients to be * converted. * @return polynomial with RealAlgebraicNumber<C> coefficients. */ public static & Rational> GenPolynomial> realAlgFromRealCoefficients( GenPolynomialRing> afac, GenPolynomial> A) { edu.jas.root.RealAlgebraicRing cfac = (edu.jas.root.RealAlgebraicRing) afac.coFac; return PolyUtil., edu.jas.root.RealAlgebraicNumber> map( afac, A, new ReAlgFromRealCoeff(cfac)); } /** * Convert to RealAlgebraicNumber coefficients. Represent as polynomial with * RealAlgebraicNumber coefficients from package * *
     * edu.jas.application
     * 
* * . * @param rfac result polynomial factory. * @param A polynomial with RealAlgebraicNumber<C> coefficients to be * converted. * @return polynomial with RealAlgebraicNumber<C> coefficients. */ public static & Rational> GenPolynomial> realFromRealAlgCoefficients( GenPolynomialRing> rfac, GenPolynomial> A) { edu.jas.application.RealAlgebraicRing cfac = (edu.jas.application.RealAlgebraicRing) rfac.coFac; return PolyUtil., edu.jas.application.RealAlgebraicNumber> map( rfac, A, new RealFromReAlgCoeff(cfac)); } /** * Convert to Complex<RealAlgebraicNumber> coefficients. Represent as * polynomial with Complex<RealAlgebraicNumber> coefficients, C is * e.g. BigRational. * @param pfac result polynomial factory. * @param A polynomial with Complex coefficients to be converted. * @return polynomial with Complex<RealAlgebraicNumber> coefficients. */ public static & Rational> GenPolynomial>> convertToComplexRealCoefficients( GenPolynomialRing>> pfac, GenPolynomial> A) { ComplexRing> afac; afac = (ComplexRing>) pfac.coFac; return PolyUtil., Complex>> map(pfac, A, new CoeffToComplexReal(afac)); } /** * Evaluate to Complex<RealAlgebraicNumber> coefficients. Represent as * polynomial with Complex<RealAlgebraicNumber> coefficients, C is * e.g. BigRational. * @param pfac result polynomial factory. * @param A = A(x,Y) a recursive polynomial with * GenPolynomial<Complex> coefficients to be converted. * @param r Complex<RealAlgebraicNumber> to be evaluated at. * @return A(r,Y), a polynomial with Complex<RealAlgebraicNumber> * coefficients. */ public static & Rational> GenPolynomial>> evaluateToComplexRealCoefficients( GenPolynomialRing>> pfac, GenPolynomial>> A, Complex> r) { return PolyUtil.>, Complex>> map( pfac, A, new EvaluateToComplexReal(pfac, r)); } } /** * Coefficient to convert algebriac functor. */ class CoeffConvertAlg> implements UnaryFunctor, AlgebraicNumber> { final protected AlgebraicNumberRing afac; final protected AlgebraicNumber A; public CoeffConvertAlg(AlgebraicNumberRing fac, AlgebraicNumber a) { if (fac == null || a == null) { throw new IllegalArgumentException("fac and a must not be null"); } afac = fac; A = a; } public AlgebraicNumber eval(AlgebraicNumber c) { if (c == null) { return afac.getZERO(); } return PolyUtilApp. convertToPrimitiveElem(afac, A, c); } } /** * Coefficient recursive to convert algebriac functor. */ class CoeffRecConvertAlg> implements UnaryFunctor>, AlgebraicNumber> { final protected AlgebraicNumberRing afac; final protected AlgebraicNumber A; final protected AlgebraicNumber B; public CoeffRecConvertAlg(AlgebraicNumberRing fac, AlgebraicNumber a, AlgebraicNumber b) { if (fac == null || a == null || b == null) { throw new IllegalArgumentException("fac, a and b must not be null"); } afac = fac; A = a; B = b; } public AlgebraicNumber eval(AlgebraicNumber> c) { if (c == null) { return afac.getZERO(); } return PolyUtilApp. convertToPrimitiveElem(afac, A, B, c); } } /** * Coefficient to real algebriac from real algebraic functor. */ class ReAlgFromRealCoeff & Rational> implements UnaryFunctor, edu.jas.root.RealAlgebraicNumber> { final protected edu.jas.root.RealAlgebraicRing afac; public ReAlgFromRealCoeff(edu.jas.root.RealAlgebraicRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } afac = fac; } public edu.jas.root.RealAlgebraicNumber eval(edu.jas.application.RealAlgebraicNumber c) { if (c == null) { return afac.getZERO(); } return (edu.jas.root.RealAlgebraicNumber) (Object) c.number; // force ignore recursion } } /** * Coefficient to real algebriac from algebraic functor. */ class RealFromReAlgCoeff & Rational> implements UnaryFunctor, edu.jas.application.RealAlgebraicNumber> { final protected edu.jas.application.RealAlgebraicRing rfac; public RealFromReAlgCoeff(edu.jas.application.RealAlgebraicRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } rfac = fac; } public edu.jas.application.RealAlgebraicNumber eval(edu.jas.root.RealAlgebraicNumber c) { if (c == null) { return rfac.getZERO(); } edu.jas.root.RealAlgebraicNumber> rrc = (edu.jas.root.RealAlgebraicNumber>) (Object) c; // force resurrect recursion return new edu.jas.application.RealAlgebraicNumber(rfac, rrc); } } /** * Coefficient to complex real algebriac functor. */ class CoeffToComplexReal & Rational> implements UnaryFunctor, Complex>> { final protected ComplexRing> cfac; final edu.jas.application.RealAlgebraicRing afac; final GenPolynomialRing pfac; public CoeffToComplexReal(ComplexRing> fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } cfac = fac; afac = (edu.jas.application.RealAlgebraicRing) cfac.ring; pfac = afac.univs.ideal.getRing(); } public Complex> eval(Complex c) { if (c == null) { return cfac.getZERO(); } GenPolynomial pr, pi; pr = new GenPolynomial(pfac, c.getRe()); pi = new GenPolynomial(pfac, c.getIm()); //System.out.println("pr = " + pr); //System.out.println("pi = " + pi); edu.jas.application.RealAlgebraicNumber re, im; re = new edu.jas.application.RealAlgebraicNumber(afac, pr); im = new edu.jas.application.RealAlgebraicNumber(afac, pi); //System.out.println("re = " + re); //System.out.println("im = " + im); return new Complex>(cfac, re, im); } } /** * Polynomial coefficient to complex real algebriac evaluation functor. */ class EvaluateToComplexReal & Rational> implements UnaryFunctor>, Complex>> { final protected GenPolynomialRing>> pfac; final protected ComplexRing> cfac; final protected Complex> root; public EvaluateToComplexReal(GenPolynomialRing>> fac, Complex> r) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } if (r == null) { throw new IllegalArgumentException("r must not be null"); } pfac = fac; cfac = (ComplexRing>) fac.coFac; root = r; //System.out.println("cfac = " + cfac); //System.out.println("root = " + root); } public Complex> eval(GenPolynomial> c) { if (c == null) { return cfac.getZERO(); } //System.out.println("c = " + c); GenPolynomial>> cp; cp = PolyUtilApp. convertToComplexRealCoefficients(pfac, c); Complex> cr; cr = PolyUtil.>> evaluateMain(cfac, cp, root); return cr; } } jas-2.5/src/edu/jas/application/ExtensionFieldBuilder.java0000644000175000017500000001631211571752206024072 0ustar giovannigiovanni/* * $Id: ExtensionFieldBuilder.java 3655 2011-06-02 18:20:54Z kredel $ */ package edu.jas.application; import java.io.IOException; import java.io.Serializable; import java.io.StringReader; import java.util.List; import edu.jas.arith.Rational; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.Complex; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.TermOrder; import edu.jas.root.ComplexAlgebraicRing; import edu.jas.root.Interval; import edu.jas.root.RealAlgebraicRing; import edu.jas.root.Rectangle; import edu.jas.root.RootUtil; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.QuotientRing; /** * Builder for extension field towers. * @author Heinz Kredel */ public class ExtensionFieldBuilder implements Serializable { /** * The current factory. */ public final RingFactory factory; // must be a raw type /** * Constructor not for use. */ protected ExtensionFieldBuilder() { throw new IllegalArgumentException("do not use this constructor"); } /** * Constructor. * @param base the base field. */ public ExtensionFieldBuilder(RingFactory base) { factory = base; } /** * Build the field tower. TODO: build at the end and optimize field tower * for faster computation. */ public RingFactory build() { return factory; } /** * Set base field. * @param base the base field for the extensions. */ public static ExtensionFieldBuilder baseField(RingFactory base) { return new ExtensionFieldBuilder(base); } /** * Transcendent field extension. * @param vars names for the transcendent generators. */ public ExtensionFieldBuilder transcendentExtension(String vars) { String[] variables = GenPolynomialTokenizer.variableList(vars); GenPolynomialRing pfac = new GenPolynomialRing(factory, variables); QuotientRing qfac = new QuotientRing(pfac); RingFactory base = (RingFactory) qfac; return new ExtensionFieldBuilder(base); } /** * Polynomial ring extension. * @param vars names for the polynomial ring generators. */ public ExtensionFieldBuilder polynomialExtension(String vars) { String[] variables = GenPolynomialTokenizer.variableList(vars); GenPolynomialRing pfac = new GenPolynomialRing(factory, variables); RingFactory base = (RingFactory) pfac; return new ExtensionFieldBuilder(base); } /** * Algebraic field extension. * @param var name(s) for the algebraic generator(s). * @param expr generating expresion, a univariate or multivariate polynomial * in vars. */ public ExtensionFieldBuilder algebraicExtension(String var, String expr) { String[] variables = GenPolynomialTokenizer.variableList(var); if (variables.length < 1) { variables = GenPolynomialTokenizer.expressionVariables(expr); if (variables.length < 1) { throw new IllegalArgumentException("no variables in '" + var + "' and '" + expr + "'" ); } } GenPolynomialRing pfac = new GenPolynomialRing(factory, variables); if (variables.length == 1) { // simple extension GenPolynomial gen = pfac.parse(expr); AlgebraicNumberRing afac = new AlgebraicNumberRing(gen); RingFactory base = (RingFactory) afac; return new ExtensionFieldBuilder(base); } GenPolynomialTokenizer pt = new GenPolynomialTokenizer(pfac, new StringReader(expr)); List gen = null; try { gen = pt.nextPolynomialList(); } catch (IOException e) { // should not happen throw new IllegalArgumentException(e); } Ideal agen = new Ideal(pfac, gen); if (agen.isONE()) { throw new IllegalArgumentException("ideal is 1: " + expr); } if (agen.isZERO()) { // transcendent extension QuotientRing qfac = new QuotientRing(pfac); RingFactory base = (RingFactory) qfac; return new ExtensionFieldBuilder(base); } // check if agen is prime? ResidueRing afac = new ResidueRing(agen); RingFactory base = (RingFactory) afac; return new ExtensionFieldBuilder(base); } /** * Real algebraic field extension. * @param var name for the algebraic generator. * @param expr generating expresion, a univariate polynomial in var. * @param root isolating interval for a real root. */ public ExtensionFieldBuilder realAlgebraicExtension(String var, String expr, String root) { String[] variables = new String[] { var }; RingElem one = (RingElem) factory.getONE(); if (!(one instanceof Rational)) { throw new IllegalArgumentException("base field not instance of Rational"); } TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing pfac = new GenPolynomialRing(factory, to, variables); GenPolynomial gen = pfac.parse(expr); RingFactory cf = pfac.coFac; Interval iv = RootUtil.parseInterval(cf, root); //System.out.println("iv = " + iv); RealAlgebraicRing rfac = new RealAlgebraicRing(gen, iv); RingFactory base = (RingFactory) rfac; return new ExtensionFieldBuilder(base); } /** * Complex algebraic field extension. * @param var name for the algebraic generator. * @param expr generating expresion, a univariate polynomial in var. * @param root isolating rectangle for a complex root. */ public ExtensionFieldBuilder complexAlgebraicExtension(String var, String expr, String root) { String[] variables = new String[] { var }; RingElem one = (RingElem) factory.getONE(); if (!(one instanceof Complex)) { throw new IllegalArgumentException("base field not instance of Complex"); } GenPolynomialRing pfac = new GenPolynomialRing(factory, variables); //System.out.println("pfac = " + pfac); GenPolynomial gen = pfac.parse(expr); //System.out.println("gen = " + gen); RingFactory cf = pfac.coFac; Rectangle rt = RootUtil.parseRectangle(cf, root); //System.out.println("rt = " + rt); ComplexAlgebraicRing rfac = new ComplexAlgebraicRing(gen, rt); RingFactory base = (RingFactory) rfac; return new ExtensionFieldBuilder(base); } /** * String representation of the ideal. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer(" "); s.append(factory.toString()); s.append(" "); return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ public String toScript() { // Python case StringBuffer s = new StringBuffer(" "); s.append(factory.toScript()); s.append(" "); return s.toString(); } } jas-2.5/src/edu/jas/application/Condition.java0000644000175000017500000003347112004330270021557 0ustar giovannigiovanni/* * $Id: Condition.java 4058 2012-07-26 21:03:53Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.gbufd.MultiplicativeSet; import edu.jas.gbufd.MultiplicativeSetSquarefree; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; /** * Condition. An ideal of polynomials considered to be zero and a multiplicative * set of polynomials considered to be non-zero. * @param coefficient type * @author Heinz Kredel. */ public class Condition> implements Serializable { private static final Logger logger = Logger.getLogger(Condition.class); //private final boolean debug = logger.isDebugEnabled(); /** * Colors. */ public static enum Color { GREEN, RED, WHITE }; /** * Data structure for condition zero. */ public final Ideal zero; /** * Data structure for condition non-zero. */ public final MultiplicativeSet nonZero; /** * Condition constructor. Constructs an empty condition with squarefree * multiplicative set. * @param ring polynomial ring factory for coefficients. */ public Condition(GenPolynomialRing ring) { this(new Ideal(ring), new MultiplicativeSetSquarefree(ring)); //this(new Ideal(ring),new MultiplicativeSetFactors(ring)); if (ring == null) { throw new IllegalArgumentException("only for non null rings"); } } /** * Condition constructor. Constructs a condition with squarefree * multiplicative set. * @param z an ideal of zero polynomials. */ public Condition(Ideal z) { this(z, new MultiplicativeSetSquarefree(z.getRing())); //this(z,new MultiplicativeSetFactors(z.list.ring)); } /** * Condition constructor. * @param nz a list of non-zero polynomials. */ public Condition(MultiplicativeSet nz) { this(new Ideal(nz.ring), nz); } /** * Condition constructor. * @param z an ideal of zero polynomials. * @param nz a list of non-zero polynomials. */ public Condition(Ideal z, MultiplicativeSet nz) { if (z == null || nz == null) { throw new IllegalArgumentException("only for non null condition parts"); } zero = z; nonZero = nz; } /** * toString. * @see java.lang.Object#toString() */ @Override public String toString() { return "Condition[ 0 == " + zero.getList().toString() + ", 0 != " + nonZero.mset.toString() + " ]"; } /** * equals. * @param ob an Object. * @return true if this is equal to o, else false. */ @Override @SuppressWarnings("unchecked") public boolean equals(Object ob) { Condition c = null; try { c = (Condition) ob; } catch (ClassCastException e) { return false; } if (c == null) { return false; } if (!zero.equals(c.zero)) { return false; } if (!nonZero.equals(c.nonZero)) { return false; } // better: //if ( nonZero.removeFactors(c.nonZero).size() != 0 ) { // return false; //} //if ( c.nonZero.removeFactors(nonZero).size() != 0 ) { // return false; //} return true; } /** * Hash code for this condition. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = zero.getList().hashCode(); h = h << 17; h += nonZero.hashCode(); // h = h << 11; // h += pairlist.hashCode(); return h; } /** * Is empty condition. * @return true if this is the empty condition, else false. */ public boolean isEmpty() { return (zero.isZERO() && nonZero.isEmpty()); } /** * Is contradictory. * @return true if this condition is contradictory, else false. */ public boolean isContradictory() { if (zero.isZERO()) { return false; } boolean t = zero.isONE(); if (t) { logger.info("contradiction zero.isONE(): " + this); return t; } for (GenPolynomial p : zero.getList()) { t = nonZero.contains(p); if (t) { logger.info("contradiction nonZero.contains(zero): " + this + ", pol = " + p); return t; } } for (GenPolynomial p : nonZero.mset) { t = zero.contains(p); if (t) { logger.info("contradiction zero.contains(nonZero): " + this + ", pol = " + p); return t; } } return false; } /** * Extend condition with zero polynomial. * @param z a polynomial to be treated as zero. * @return new condition. */ public Condition extendZero(GenPolynomial z) { // assert color(z) == white z = z.monic(); Ideal idz = zero.sum(z); logger.info("added to ideal: " + z); Condition nc = new Condition(idz, nonZero); //if (true) { return nc.simplify(); //} //return nc; } /** * Extend condition with non-zero polynomial. * @param nz a polynomial to be treated as non-zero. * @return new condition. */ public Condition extendNonZero(GenPolynomial nz) { // assert color(nz) == white GenPolynomial n = zero.normalform(nz).monic(); if (n == null || n.isZERO()) { return this; } MultiplicativeSet ms = nonZero.add(n); logger.info("added to non zero: " + n); Condition nc = new Condition(zero, ms); //if (true) { return nc.simplify(); //} //return nc; } /** * Simplify zero and non-zero polynomial conditions. * @return new simplified condition. */ public Condition simplify() { //if (false) { // no simplification // return this; //} Ideal idz = zero.squarefree(); if (!idz.getList().equals(zero.getList())) { logger.info("simplify squarefree: " + zero.getList() + " to " + idz.getList()); } List> ml = idz.normalform(nonZero.mset); MultiplicativeSet ms = nonZero; if (!ml.equals(nonZero.mset)) { if (ml.size() != nonZero.mset.size()) { logger.info("contradiction(==0):"); logger.info("simplify normalform contradiction: " + nonZero.mset + " to " + ml); return null; } logger.info("simplify normalform: " + nonZero.mset + " to " + ml); ms = nonZero.replace(ml); } List> Z = ms.removeFactors(idz.getList()); if (!Z.equals(idz.getList())) { if (Z.size() != idz.getList().size()) { // never true logger.info("contradiction(!=0):"); logger.info("simplify removeFactors contradiction: " + idz.getList() + " to " + Z); return null; } logger.info("simplify removeFactors: " + idz.getList() + " to " + Z); idz = new Ideal(zero.getRing(), Z); // changes ideal } Condition nc = new Condition(idz, ms); if (nc.isContradictory()) { // evenatually a factor became 1 //logger.info("simplify contradiction: " + nc); return null; } if (idz.equals(zero) && ms.equals(nonZero)) { return this; } logger.info("condition simplified: " + this + " to " + nc); //if (false) { // no further simplification // return nc; //} return nc.simplify(); } /** * Determine color of polynomial. * @param c polynomial to be colored. * @return color of c. */ public Color color(GenPolynomial c) { GenPolynomial m = zero.normalform(c).monic(); //non-sense: m = nonZero.removeFactors(m); if (m.isZERO()) { // zero.contains(m) // System.out.println("m in id = " + m); return Color.GREEN; } if (m.isConstant()) { // System.out.println("m constant " + m); return Color.RED; } if (nonZero.contains(m) || nonZero.contains(c)) { // System.out.println("m or c in nonzero " + m); return Color.RED; } //System.out.println("m white " + m + ", c = " + c); return Color.WHITE; } /** * Determine polynomial. If this condition does not determine the * polynomial, then a run-time exception is thrown. * @param A polynomial. * @return new determined colored polynomial. */ public ColorPolynomial determine(GenPolynomial> A) { ColorPolynomial cp = null; if (A == null) { return cp; } GenPolynomial> zero = A.ring.getZERO(); GenPolynomial> green = zero; GenPolynomial> red = zero; GenPolynomial> white = zero; if (A.isZERO()) { cp = new ColorPolynomial(green, red, white); return cp; } GenPolynomial> Ap = A; GenPolynomial> Bp; while (!Ap.isZERO()) { Map.Entry> m = Ap.leadingMonomial(); ExpVector e = m.getKey(); GenPolynomial c = m.getValue(); Bp = Ap.reductum(); // System.out.println( "color(" + c + ") = " + color(c) ); switch (color(c)) { case GREEN: green = green.sum(c, e); Ap = Bp; continue; case RED: red = red.sum(c, e); white = Bp; return new ColorPolynomial(green, red, white); // since break is not possible default: System.out.println("undetermined cond = " + this); System.out.println("undetermined poly A = " + A); System.out.println("undetermined poly green = " + green); System.out.println("undetermined poly red = " + red); System.out.println("undetermined poly Ap = " + Ap); System.out.println("undetermined coeff c = " + c); throw new RuntimeException("undetermined, c is white = " + c); // is catched in minimalGB } } cp = new ColorPolynomial(green, red, white); // System.out.println("determined = " + cp); return cp; } /** * Determine list of polynomials. If this condition does not determine all * polynomials, then a run-time exception is thrown. The returned list does * not contain polynomials with all green terms. * @param L list of polynomial. * @return new determined list of colored polynomials. */ public List> determine(List>> L) { List> cl = null; if (L == null) { return cl; } cl = new ArrayList>(L.size()); for (GenPolynomial> A : L) { ColorPolynomial c = determine(A); if (c != null && !c.isZERO()) { cl.add(c); } } return cl; } /** * Re determine colored polynomial. * @param s colored polynomial. * @return determined colored polynomial wrt. this.conditions. */ public ColorPolynomial reDetermine(ColorPolynomial s) { ColorPolynomial p = determine(s.getEssentialPolynomial()); // assume green terms stay green wrt. this condition GenPolynomial> g = s.green.sum(p.green); p = new ColorPolynomial(g, p.red, p.white); return p; } /** * Re determine list of colored polynomials. * @param S list of colored polynomials. * @return list of determined colored polynomials wrt. this.conditions. */ public List> reDetermine(List> S) { if (S == null || S.isEmpty()) { return S; } List> P = new ArrayList>(); for (ColorPolynomial s : S) { ColorPolynomial p = reDetermine(s); P.add(p); } return P; } /** * Is determined colored polynomial. * @param s colored polynomial. * @return true if the colored polynomial is correctly determined wrt. * this.condition. */ public boolean isDetermined(ColorPolynomial s) { ColorPolynomial p = determine(s.getPolynomial()); boolean t = p.equals(s); if (!t) { System.out.println("not determined s = " + s); System.out.println("not determined p = " + p); System.out.println("not determined cond = " + this); } return t; } /** * Is determined list of colored polynomial. * @param S list of colored polynomials. * @return true if the colored polynomials in S are correctly determined * wrt. this.condition. */ public boolean isDetermined(List> S) { if (S == null) { return true; } for (ColorPolynomial p : S) { if (!isDetermined(p)) { return false; } } return true; } } jas-2.5/src/edu/jas/application/RealAlgebraicNumber.java0000644000175000017500000002704012014234362023460 0ustar giovannigiovanni/* * $Id: RealAlgebraicNumber.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.application; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigRational; import edu.jas.arith.Rational; import edu.jas.kern.PrettyPrint; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; import edu.jas.structure.NotInvertibleException; /** * Complex algebraic number class based on bi-variate real algebraic numbers. * Objects of this class are immutable. Bi-variate ideal implementation is in * version 3614 2011-04-28 09:20:34Z. * @author Heinz Kredel */ public class RealAlgebraicNumber & Rational> implements GcdRingElem>, Rational { /* * Representing Residue, unused. */ //private Residue numberRes; /** * Representing recursive RealAlgebraicNumber. */ public final edu.jas.root.RealAlgebraicNumber> number; /** * Ring part of the data structure. */ public final RealAlgebraicRing ring; /** * The constructor creates a zero RealAlgebraicNumber. * @param r ring RealAlgebraicRing. */ public RealAlgebraicNumber(RealAlgebraicRing r) { this(r, r.realRing.getZERO()); } /** * The constructor creates a RealAlgebraicNumber object from a GenPolynomial * value. * @param r ring RealAlgebraicRing. * @param a value element . */ public RealAlgebraicNumber(RealAlgebraicRing r, C a) { this(r, r.realRing.parse(a.toString())); } /** * The constructor creates a RealAlgebraicNumber object from a GenPolynomial * value. * @param r ring RealAlgebraicRing. * @param a value GenPolynomial. */ public RealAlgebraicNumber(RealAlgebraicRing r, GenPolynomial a) { this(r, r.realRing.parse(a.toString())); } /** * The constructor creates a RealAlgebraicNumber object from a recursive * real algebraic value. * @param r ring RealAlgebraicRing. * @param a recursive real algebraic number. */ public RealAlgebraicNumber(RealAlgebraicRing r, edu.jas.root.RealAlgebraicNumber> a) { number = a; ring = r; //number = ring.realRing.parse(number.val.toString()); // todo: convert //System.out.println("number = " + number); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public RealAlgebraicRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public RealAlgebraicNumber copy() { return new RealAlgebraicNumber(ring, number); } /** * Return a BigRational approximation of this Element. * @return a BigRational approximation of this. * @see edu.jas.arith.Rational#getRational() */ //JAVA6only: @Override public BigRational getRational() { return magnitude(); } /** * Is RealAlgebraicNumber zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return number.isZERO(); } /** * Is RealAlgebraicNumber one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return number.isONE(); } /** * Is RealAlgebraicNumber unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { return number.isUnit(); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { if (PrettyPrint.isTrue()) { return "{ " + number.toString() + " }"; } return "Complex" + number.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return number.toScript(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * RealAlgebraicNumber comparison. * @param b RealAlgebraicNumber. * @return sign(this-b). */ //JAVA6only: @Override public int compareTo(RealAlgebraicNumber b) { int s = 0; if (number.ring != b.number.ring) { s = (number.ring.equals(b.number.ring) ? 0 : 1); System.out.println("s_mod = " + s); } if (s != 0) { return s; } s = number.compareTo(b.number); // TODO //System.out.println("s_real = " + s); return s; } /** * RealAlgebraicNumber comparison. * @param b AlgebraicNumber. * @return polynomial sign(this-b). */ public int compareTo(edu.jas.root.RealAlgebraicNumber> b) { int s = number.compareTo(b); //System.out.println("s_algeb = " + s); return s; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof RealAlgebraicNumber)) { return false; } RealAlgebraicNumber a = null; try { a = (RealAlgebraicNumber) b; } catch (ClassCastException e) { } if (a == null) { return false; } if (!ring.equals(a.ring)) { return false; } return number.equals(a.number); } /** * Hash code for this RealAlgebraicNumber. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * number.hashCode() + ring.hashCode(); } /** * RealAlgebraicNumber absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public RealAlgebraicNumber abs() { if (this.signum() < 0) { return new RealAlgebraicNumber(ring, number.negate()); } return this; } /** * RealAlgebraicNumber summation. * @param S RealAlgebraicNumber. * @return this+S. */ public RealAlgebraicNumber sum(RealAlgebraicNumber S) { return new RealAlgebraicNumber(ring, number.sum(S.number)); } /** * RealAlgebraicNumber summation. * @param c recursive real algebraic number. * @return this+c. */ public RealAlgebraicNumber sum(edu.jas.root.RealAlgebraicNumber> c) { return new RealAlgebraicNumber(ring, number.sum(c)); } /** * RealAlgebraicNumber negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public RealAlgebraicNumber negate() { return new RealAlgebraicNumber(ring, number.negate()); } /** * RealAlgebraicNumber subtraction. * @param S RealAlgebraicNumber. * @return this-S. */ public RealAlgebraicNumber subtract(RealAlgebraicNumber S) { return new RealAlgebraicNumber(ring, number.subtract(S.number)); } /** * RealAlgebraicNumber division. * @param S RealAlgebraicNumber. * @return this/S. */ public RealAlgebraicNumber divide(RealAlgebraicNumber S) { return multiply(S.inverse()); } /** * RealAlgebraicNumber inverse. * @see edu.jas.structure.RingElem#inverse() * @throws NotInvertibleException if the element is not invertible. * @return S with S = 1/this if defined. */ public RealAlgebraicNumber inverse() { return new RealAlgebraicNumber(ring, number.inverse()); } /** * RealAlgebraicNumber remainder. * @param S RealAlgebraicNumber. * @return this - (this/S)*S. */ public RealAlgebraicNumber remainder(RealAlgebraicNumber S) { return new RealAlgebraicNumber(ring, number.remainder(S.number)); } /** * RealAlgebraicNumber multiplication. * @param S RealAlgebraicNumber. * @return this*S. */ public RealAlgebraicNumber multiply(RealAlgebraicNumber S) { return new RealAlgebraicNumber(ring, number.multiply(S.number)); } /** * RealAlgebraicNumber multiplication. * @param c recursive real algebraic number. * @return this*c. */ public RealAlgebraicNumber multiply( edu.jas.root.RealAlgebraicNumber> c) { return new RealAlgebraicNumber(ring, number.multiply(c)); } /** * RealAlgebraicNumber monic. * @return this with monic value part. */ public RealAlgebraicNumber monic() { return new RealAlgebraicNumber(ring, number.monic()); } /** * RealAlgebraicNumber greatest common divisor. * @param S RealAlgebraicNumber. * @return gcd(this,S). */ public RealAlgebraicNumber gcd(RealAlgebraicNumber S) { return new RealAlgebraicNumber(ring, number.gcd(S.number)); } /** * RealAlgebraicNumber extended greatest common divisor. * @param S RealAlgebraicNumber. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ @SuppressWarnings("unchecked") public RealAlgebraicNumber[] egcd(RealAlgebraicNumber S) { edu.jas.root.RealAlgebraicNumber>[] aret = number.egcd(S.number); RealAlgebraicNumber[] ret = new RealAlgebraicNumber[3]; ret[0] = new RealAlgebraicNumber(ring, aret[0]); ret[1] = new RealAlgebraicNumber(ring, aret[1]); ret[2] = new RealAlgebraicNumber(ring, aret[2]); return ret; } /** * RealAlgebraicNumber signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { // if ( number == null ) { // no synchronization required // GenPolynomial p = number.val; // number = ring.realRing.parse(p.toString()); // todo: convert // //System.out.println("number = " + number); // } return number.signum(); } /** * RealAlgebraicNumber magnitude. * @return |this| as rational number. */ public BigRational magnitude() { // if ( number == null ) { // no synchronization required // GenPolynomial p = number.val; // number = ring.realRing.parse(p.toString()); // todo: convert // //System.out.println("number = " + number); // } return number.magnitude(); } /** * RealAlgebraicNumber decimal magnitude. * @return |this| as big decimal. */ public BigDecimal decimalMagnitude() { BigRational cr = magnitude(); return new BigDecimal(cr); } } jas-2.5/src/edu/jas/application/SolvableIdeal.java0000644000175000017500000010732312137720564022355 0ustar giovannigiovanni/* * $Id: SolvableIdeal.java 4408 2013-04-30 10:48:20Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.gb.SolvableExtendedGB; import edu.jas.gb.SolvableGroebnerBaseAbstract; import edu.jas.gb.SolvableGroebnerBaseSeq; import edu.jas.gb.SolvableReduction; import edu.jas.gb.SolvableReductionSeq; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.structure.GcdRingElem; import edu.jas.structure.NotInvertibleException; /** * Solvable Ideal implements some methods for ideal arithmetic, for example * sum, intersection, quotient. * Note: only left ideals at the moment. * @author Heinz Kredel */ public class SolvableIdeal> implements Comparable>, Serializable { private static final Logger logger = Logger.getLogger(SolvableIdeal.class); private final boolean debug = logger.isDebugEnabled(); /** * The data structure is a PolynomialList. */ protected PolynomialList list; /** * Indicator if list is a Groebner Base. */ protected boolean isGB; /** * Indicator if test has been performed if this is a Groebner Base. */ protected boolean testGB; /** * Indicator if list has optimized term order. */ protected boolean isTopt; /** * Groebner base engine. */ protected final SolvableGroebnerBaseAbstract bb; /** * Reduction engine. */ protected final SolvableReduction red; /** * Constructor. * @param ring solvable polynomial ring */ public SolvableIdeal(GenSolvablePolynomialRing ring) { this(ring, new ArrayList>()); } /** * Constructor. * @param ring solvable polynomial ring * @param F list of solvable polynomials */ public SolvableIdeal(GenSolvablePolynomialRing ring, List> F) { this(new PolynomialList(ring, F)); } /** * Constructor. * @param ring solvable polynomial ring * @param F list of solvable polynomials * @param gb true if F is known to be a Groebner Base, else false */ public SolvableIdeal(GenSolvablePolynomialRing ring, List> F, boolean gb) { this(new PolynomialList(ring, F), gb); } /** * Constructor. * @param ring solvable polynomial ring * @param F list of solvable polynomials * @param gb true if F is known to be a Groebner Base, else false * @param topt true if term order is optimized, else false */ public SolvableIdeal(GenSolvablePolynomialRing ring, List> F, boolean gb, boolean topt) { this(new PolynomialList(ring, F), gb, topt); } /** * Constructor. * @param list solvable polynomial list */ public SolvableIdeal(PolynomialList list) { this(list, false); } /** * Constructor. * @param list solvable polynomial list * @param bb Groebner Base engine * @param red Reduction engine */ public SolvableIdeal(PolynomialList list, SolvableGroebnerBaseAbstract bb, SolvableReduction red) { this(list, false, bb, red); } /** * Constructor. * @param list solvable polynomial list * @param gb true if list is known to be a Groebner Base, else false */ public SolvableIdeal(PolynomialList list, boolean gb) { this(list, gb, new SolvableGroebnerBaseSeq(), new SolvableReductionSeq()); //this(list, gb, GBFactory.getImplementation(list.ring.coFac)); } /** * Constructor. * @param list solvable polynomial list * @param gb true if list is known to be a Groebner Base, else false * @param topt true if term order is optimized, else false */ public SolvableIdeal(PolynomialList list, boolean gb, boolean topt) { this(list, gb, topt, new SolvableGroebnerBaseSeq(), new SolvableReductionSeq()); //this(list, gb, topt, GBFactory.getImplementation(list.ring.coFac)); } /** * Constructor. * @param list solvable polynomial list * @param gb true if list is known to be a Groebner Base, else false * @param bb Groebner Base engine * @param red Reduction engine */ public SolvableIdeal(PolynomialList list, boolean gb, SolvableGroebnerBaseAbstract bb, SolvableReduction red) { this(list, gb, false, bb, red); } /** * Constructor. * @param list solvable polynomial list * @param gb true if list is known to be a Groebner Base, else false * @param bb Groebner Base engine */ public SolvableIdeal(PolynomialList list, boolean gb, SolvableGroebnerBaseAbstract bb) { this(list, gb, false, bb, bb.sred); } /** * Constructor. * @param list solvable polynomial list * @param gb true if list is known to be a Groebner Base, else false * @param topt true if term order is optimized, else false * @param bb Groebner Base engine */ public SolvableIdeal(PolynomialList list, boolean gb, boolean topt, SolvableGroebnerBaseAbstract bb) { this(list, gb, topt, bb, bb.sred); } /** * Constructor. * @param list solvable polynomial list * @param gb true if list is known to be a Groebner Base, else false * @param topt true if term order is optimized, else false * @param bb Groebner Base engine * @param red Reduction engine */ public SolvableIdeal(PolynomialList list, boolean gb, boolean topt, SolvableGroebnerBaseAbstract bb, SolvableReduction red) { if (list == null || list.list == null) { throw new IllegalArgumentException("list and list.list may not be null"); } this.list = list; this.isGB = gb; this.isTopt = topt; this.testGB = (gb ? true : false); // ?? this.bb = bb; this.red = red; } /** * Clone this. * @return a copy of this. */ public SolvableIdeal copy() { return new SolvableIdeal(list.copy(), isGB, isTopt, bb, red); } /** * Get the List of GenSolvablePolynomials. * @return (cast) list.list */ public List> getList() { return list.getSolvableList(); } /** * Get the GenSolvablePolynomialRing. * @return (cast) list.ring */ public GenSolvablePolynomialRing getRing() { return list.getSolvableRing(); } /** * Get the zero ideal. * @return ideal(0) */ public SolvableIdeal getZERO() { List> z = new ArrayList>(0); PolynomialList pl = new PolynomialList(getRing(), z); return new SolvableIdeal(pl, true, isTopt, bb, red); } /** * Get the one ideal. * @return ideal(1) */ public SolvableIdeal getONE() { List> one = new ArrayList>(1); one.add(getRing().getONE()); PolynomialList pl = new PolynomialList(getRing(), one); return new SolvableIdeal(pl, true, isTopt, bb, red); } /** * String representation of the solvable ideal. * @see java.lang.Object#toString() */ @Override public String toString() { return list.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ public String toScript() { // any script case return list.toScript(); } /** * Comparison with any other object. Note: If not both ideals are * Groebner Bases, then false may be returned even the ideals are equal. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof SolvableIdeal)) { logger.warn("equals no Ideal"); return false; } SolvableIdeal B = null; try { B = (SolvableIdeal) b; } catch (ClassCastException ignored) { return false; } //if ( isGB && B.isGB ) { // return list.equals( B.list ); requires also monic polys //} else { // compute GBs ? return this.contains(B) && B.contains(this); //} } /** * SolvableIdeal comparison. * @param L other solvable ideal. * @return compareTo() of polynomial lists. */ public int compareTo(SolvableIdeal L) { return list.compareTo(L.list); } /** * Hash code for this solvable ideal. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = list.hashCode(); if (isGB) { h = h << 1; } if (testGB) { h += 1; } return h; } /** * Test if ZERO ideal. * @return true, if this is the 0 ideal, else false */ public boolean isZERO() { return list.isZERO(); } /** * Test if ONE is contained in the ideal. To test for a proper ideal use * ! id.isONE(). * @return true, if this is the 1 ideal, else false */ public boolean isONE() { return list.isONE(); } /** * Test if this is a left Groebner base. * @return true, if this is a left Groebner base, else false */ public boolean isGB() { if (testGB) { return isGB; } logger.warn("isGB computing"); isGB = bb.isLeftGB(getList()); testGB = true; return isGB; } /** * Do Groebner Base. compute the Groebner Base for this ideal. */ @SuppressWarnings("unchecked") public void doGB() { if (isGB && testGB) { return; } //logger.warn("GB computing"); List> G = getList(); logger.info("GB computing = " + G); G = bb.leftGB(G); //if (isTopt) { // List perm = ((OptimizedPolynomialList) list).perm; // list = new OptimizedPolynomialList(perm, getRing(), G); //} else { list = new PolynomialList(getRing(), G); //} isGB = true; testGB = true; return; } /** * Groebner Base. Get a Groebner Base for this ideal. * @return leftGB(this) */ public SolvableIdeal GB() { if (isGB) { return this; } doGB(); return this; } /** * Solvable ideal containment. Test if B is contained in this ideal. Note: * this is eventually modified to become a Groebner Base. * @param B solvable ideal * @return true, if B is contained in this, else false */ public boolean contains(SolvableIdeal B) { if (B == null || B.isZERO()) { return true; } return contains(B.getList()); } /** * Solvable ideal containment. Test if b is contained in this ideal. Note: * this is eventually modified to become a Groebner Base. * @param b solvable polynomial * @return true, if b is contained in this, else false */ public boolean contains(GenSolvablePolynomial b) { if (b == null || b.isZERO()) { return true; } if (this.isONE()) { return true; } if (this.isZERO()) { return false; } if (!isGB) { doGB(); } GenSolvablePolynomial z = red.leftNormalform(getList(), b); if (z == null || z.isZERO()) { return true; } return false; } /** * Solvable ideal containment. Test if each b in B is contained in this * ideal. Note: this is eventually modified to become a Groebner Base. * @param B list of solvable polynomials * @return true, if each b in B is contained in this, else false */ public boolean contains(List> B) { if (B == null || B.size() == 0) { return true; } if (this.isONE()) { return true; } if (!isGB) { doGB(); } for (GenSolvablePolynomial b : B) { if (b == null) { continue; } GenSolvablePolynomial z = red.leftNormalform(getList(), b); if (!z.isZERO()) { //System.out.println("contains nf(b) != 0: " + b); return false; } } return true; } /** * Solvable ideal summation. Generators for the sum of ideals. Note: if both * ideals are Groebner bases, a Groebner base is returned. * @param B solvable ideal * @return ideal(this+B) */ public SolvableIdeal sum(SolvableIdeal B) { if (B == null || B.isZERO()) { return this; } if (this.isZERO()) { return B; } int s = getList().size() + B.getList().size(); List> c; c = new ArrayList>(s); c.addAll(getList()); c.addAll(B.getList()); SolvableIdeal I = new SolvableIdeal(getRing(), c, false); if (isGB && B.isGB) { I.doGB(); } return I; } /** * Solvable summation. Generators for the sum of ideal and a polynomial. * Note: if this ideal is a Groebner base, a Groebner base is returned. * @param b solvable polynomial * @return ideal(this+{b}) */ public SolvableIdeal sum(GenSolvablePolynomial b) { if (b == null || b.isZERO()) { return this; } int s = getList().size() + 1; List> c; c = new ArrayList>(s); c.addAll(getList()); c.add(b); SolvableIdeal I = new SolvableIdeal(getRing(), c, false); if (isGB) { I.doGB(); } return I; } /** * Solvable summation. Generators for the sum of this ideal and a list of * polynomials. Note: if this ideal is a Groebner base, a Groebner base is * returned. * @param L list of solvable polynomials * @return ideal(this+L) */ public SolvableIdeal sum(List> L) { if (L == null || L.isEmpty()) { return this; } int s = getList().size() + L.size(); List> c = new ArrayList>(s); c.addAll(getList()); c.addAll(L); SolvableIdeal I = new SolvableIdeal(getRing(), c, false); if (isGB) { I.doGB(); } return I; } /** * Product. Generators for the product of ideals. Note: if both ideals are * Groebner bases, a Groebner base is returned. * @param B solvable ideal * @return ideal(this*B) */ public SolvableIdeal product(SolvableIdeal B) { if (B == null || B.isZERO()) { return B; } if (this.isZERO()) { return this; } int s = getList().size() * B.getList().size(); List> c; c = new ArrayList>(s); for (GenSolvablePolynomial p : getList()) { for (GenSolvablePolynomial q : B.getList()) { q = p.multiply(q); c.add(q); } } SolvableIdeal I = new SolvableIdeal(getRing(), c, false); if (isGB && B.isGB) { I.doGB(); } return I; } /** * Intersection. Generators for the intersection of ideals. Using an * iterative algorithm. * @param Bl list of solvable ideals * @return ideal(cap_i B_i), a Groebner base */ public SolvableIdeal intersect(List> Bl) { if (Bl == null || Bl.size() == 0) { return getZERO(); } SolvableIdeal I = null; for (SolvableIdeal B : Bl) { if (I == null) { I = B; continue; } if (I.isONE()) { return I; } I = I.intersect(B); } return I; } /** * Intersection. Generators for the intersection of ideals. * @param B solvable ideal * @return ideal(this \cap B), a Groebner base */ public SolvableIdeal intersect(SolvableIdeal B) { if (B == null || B.isZERO()) { // (0) return B; } if (this.isZERO()) { return this; } int s = getList().size() + B.getList().size(); List> c; c = new ArrayList>(s); List> a = getList(); List> b = B.getList(); GenSolvablePolynomialRing tfac = getRing().extend(1); // term order is also adjusted for (GenSolvablePolynomial p : a) { p = (GenSolvablePolynomial) p.extend(tfac, 0, 1L); // t*p c.add(p); } for (GenSolvablePolynomial p : b) { GenSolvablePolynomial q = (GenSolvablePolynomial) p.extend(tfac, 0, 1L); GenSolvablePolynomial r = (GenSolvablePolynomial) p.extend(tfac, 0, 0L); p = (GenSolvablePolynomial) r.subtract(q); // (1-t)*p c.add(p); } logger.warn("intersect computing GB"); List> g = bb.leftGB(c); if (debug) { logger.debug("intersect GB = " + g); } SolvableIdeal E = new SolvableIdeal(tfac, g, true); SolvableIdeal I = E.intersect(getRing()); return I; } /** * Intersection. Generators for the intersection of a ideal with a * polynomial ring. The polynomial ring of this ideal must be a contraction * of R and the TermOrder must be an elimination order. * @param R solvable polynomial ring * @return ideal(this \cap R) */ public SolvableIdeal intersect(GenSolvablePolynomialRing R) { if (R == null) { throw new IllegalArgumentException("R may not be null"); } int d = getRing().nvar - R.nvar; if (d <= 0) { return this; } List> H = new ArrayList>(getList().size()); for (GenSolvablePolynomial p : getList()) { Map> m = null; m = p.contract(R); if (debug) { logger.debug("intersect contract m = " + m); } if (m.size() == 1) { // contains one power of variables for (Map.Entry> me : m.entrySet()) { ExpVector e = me.getKey(); GenSolvablePolynomial mv = (GenSolvablePolynomial) me.getValue(); if (e.isZERO()) { H.add(mv); //m.get(e)); } } } } GenSolvablePolynomialRing tfac = getRing().contract(d); if (tfac.equals(R)) { // check return new SolvableIdeal(R, H, isGB, isTopt); } logger.info("tfac, R = " + tfac + ", " + R); // throw new RuntimeException("contract(this) != R"); return new SolvableIdeal(R, H); // compute GB } /** * Eliminate. Generators for the intersection of this ideal with a solvable * polynomial ring. The solvable polynomial ring of this ideal must be a * contraction of R and the TermOrder must be an elimination order. * @param R solvable polynomial ring * @return ideal(this \cap R) */ public SolvableIdeal eliminate(GenSolvablePolynomialRing R) { if (R == null) { throw new IllegalArgumentException("R may not be null"); } if (getRing().equals(R)) { return this; } return intersect(R); } /** * Quotient. Generators for the solvable ideal quotient. * @param h solvable polynomial * @return ideal(this : h), a Groebner base */ public SolvableIdeal quotient(GenSolvablePolynomial h) { if (h == null) { // == (0) return this; } if (h.isZERO()) { return this; } if (this.isZERO()) { return this; } List> H; H = new ArrayList>(1); H.add(h); SolvableIdeal Hi = new SolvableIdeal(getRing(), H, true); SolvableIdeal I = this.intersect(Hi); List> Q; Q = new ArrayList>(I.getList().size()); for (GenSolvablePolynomial q : I.getList()) { q = (GenSolvablePolynomial) q.divide(h); // remainder == 0 Q.add(q); } return new SolvableIdeal(getRing(), Q, true /*false?*/); } /** * Quotient. Generators for the solvable ideal quotient. * @param H solvable ideal * @return ideal(this : H), a Groebner base */ public SolvableIdeal quotient(SolvableIdeal H) { if (H == null) { // == (0) return this; } if (H.isZERO()) { return this; } if (this.isZERO()) { return this; } SolvableIdeal Q = null; for (GenSolvablePolynomial h : H.getList()) { SolvableIdeal Hi = this.quotient(h); if (Q == null) { Q = Hi; } else { Q = Q.intersect(Hi); } } return Q; } /** * Infinite quotient. Generators for the infinite solvable ideal quotient. * @param h solvable polynomial * @return ideal(this : hs), a Groebner base */ public SolvableIdeal infiniteQuotientRab(GenSolvablePolynomial h) { if (h == null || h.isZERO()) { // == (0) return getONE(); } if (h.isONE()) { return this; } if (this.isZERO()) { return this; } if ( ! getRing().isCommutative() ) { throw new UnsupportedOperationException("Rabinowich trick only for commutative polynomial rings"); } SolvableIdeal I = this.GB(); // should be already List> a = I.getList(); List> c; c = new ArrayList>(a.size() + 1); GenSolvablePolynomialRing tfac = getRing().extend(1); // term order is also adjusted for (GenSolvablePolynomial p : a) { p = (GenSolvablePolynomial) p.extend(tfac, 0, 0L); // p c.add(p); } GenSolvablePolynomial q = (GenSolvablePolynomial) h.extend(tfac, 0, 1L); GenSolvablePolynomial r = tfac.getONE(); // h.extend( tfac, 0, 0L ); GenSolvablePolynomial hs = (GenSolvablePolynomial) q.subtract(r); // 1 - t*h // (1-t)*h c.add(hs); logger.warn("infiniteQuotientRab computing GB "); List> g = bb.leftGB(c); if (debug) { logger.info("infiniteQuotientRab = " + tfac + ", c = " + c); logger.info("infiniteQuotientRab GB = " + g); } SolvableIdeal E = new SolvableIdeal(tfac, g, true); SolvableIdeal Is = E.intersect(getRing()); return Is; } /** * Infinite quotient exponent. * @param h solvable polynomial * @param Q quotient this : h^\infinity * @return s with Q = this : hs */ public int infiniteQuotientExponent(GenSolvablePolynomial h, SolvableIdeal Q) { int s = 0; if (h == null) { // == 0 return s; } if (h.isZERO() || h.isONE()) { return s; } if (this.isZERO() || this.isONE()) { return s; } //see below: if (this.contains(Q)) { // return s; //} GenSolvablePolynomial p = getRing().getONE(); for (GenSolvablePolynomial q : Q.getList()) { if (this.contains(q)) { continue; } //System.out.println("q = " + q + ", p = " + p + ", s = " + s); GenSolvablePolynomial qp = q.multiply(p); while (!this.contains(qp)) { p = p.multiply(h); s++; qp = q.multiply(p); } } return s; } /** * Infinite quotient. Generators for the infinite solvable ideal quotient. * @param h solvable polynomial * @return ideal(this : hs), a Groebner base */ public SolvableIdeal infiniteQuotient(GenSolvablePolynomial h) { if (h == null) { // == (0) return this; } if (h.isZERO()) { return this; } if (this.isZERO()) { return this; } int s = 0; SolvableIdeal I = this.GB(); // should be already GenSolvablePolynomial hs = h; SolvableIdeal Is = I; boolean eq = false; while (!eq) { Is = I.quotient(hs); Is = Is.GB(); // should be already logger.info("infiniteQuotient s = " + s); eq = Is.contains(I); // I.contains(Is) always if (!eq) { I = Is; s++; // hs = hs.multiply( h ); } } return Is; } /** * Radical membership test. * @param h solvable polynomial * @return true if h is contained in the radical of ideal(this), else false. */ public boolean isRadicalMember(GenSolvablePolynomial h) { if (h == null) { // == (0) return true; } if (h.isZERO()) { return true; } if (this.isZERO()) { return true; } SolvableIdeal x = infiniteQuotientRab(h); // may fail if (debug) { logger.debug("infiniteQuotientRab = " + x); } return x.isONE(); } /** * Infinite Quotient. Generators for the solvable ideal infinite quotient. * @param H solvable ideal * @return ideal(this : Hs), a Groebner base */ public SolvableIdeal infiniteQuotient(SolvableIdeal H) { if (H == null) { // == (0) return this; } if (H.isZERO()) { return this; } if (this.isZERO()) { return this; } SolvableIdeal Q = null; for (GenSolvablePolynomial h : H.getList()) { SolvableIdeal Hi = this.infiniteQuotient(h); if (Q == null) { Q = Hi; } else { Q = Q.intersect(Hi); } } return Q; } /** * Infinite Quotient. Generators for the solvable ideal infinite quotient. * @param H solvable ideal * @return ideal(this : Hs), a Groebner base */ public SolvableIdeal infiniteQuotientRab(SolvableIdeal H) { if (H == null) { // == (0) return this; } if (H.isZERO()) { return this; } if (this.isZERO()) { return this; } SolvableIdeal Q = null; for (GenSolvablePolynomial h : H.getList()) { SolvableIdeal Hi = this.infiniteQuotientRab(h); // may fail if (Q == null) { Q = Hi; } else { Q = Q.intersect(Hi); } } return Q; } /** * Power. Generators for the power of this solvable ideal. Note: if this * ideal is a Groebner base, a Groebner base is returned. * @param d integer * @return ideal(this^d) */ public SolvableIdeal power(int d) { if (d <= 0) { return getONE(); } if (this.isZERO() || this.isONE()) { return this; } SolvableIdeal c = this; for (int i = 1; i < d; i++) { c = c.product(this); } return c; } /** * Normalform for element. * @param h solvable polynomial * @return left normalform of h with respect to this */ public GenSolvablePolynomial normalform(GenSolvablePolynomial h) { if (h == null) { return h; } if (h.isZERO()) { return h; } if (this.isZERO()) { return h; } GenSolvablePolynomial r; r = red.leftNormalform(getList(), h); return r; } /** * Normalform for list of solvable elements. * @param L solvable polynomial list * @return list of left normalforms of the elements of L with respect to this */ public List> normalform(List> L) { if (L == null) { return L; } if (L.size() == 0) { return L; } if (this.isZERO()) { return L; } List> M = new ArrayList>(L.size()); for (GenSolvablePolynomial h : L) { GenSolvablePolynomial r = normalform(h); if (r != null && !r.isZERO()) { M.add(r); } } return M; } /** * Inverse for element modulo this ideal. * @param h solvable polynomial * @return inverse of h with respect to this, if defined */ public GenSolvablePolynomial inverse(GenSolvablePolynomial h) { if (h == null || h.isZERO()) { throw new NotInvertibleException("zero not invertible"); } if (this.isZERO()) { throw new NotInvertibleException("zero ideal"); } if (h.isUnit()) { return (GenSolvablePolynomial) h.inverse(); } doGB(); List> F = new ArrayList>(1 + list.list.size()); F.add(h); F.addAll(getList()); //System.out.println("F = " + F); SolvableExtendedGB x = bb.extLeftGB(F); List> G = x.G; //System.out.println("G = " + G); GenSolvablePolynomial one = null; int i = -1; for (GenSolvablePolynomial p : G) { i++; if (p == null) { continue; } if (p.isUnit()) { one = p; break; } } if (one == null) { throw new NotInvertibleException("h = " + h); } List> row = x.G2F.get(i); // != -1 //System.out.println("row = " + row); GenSolvablePolynomial g = row.get(0); if (g == null || g.isZERO()) { throw new NotInvertibleException("h = " + h); } GenSolvablePolynomial gp = red.leftNormalform(getList(), g); if (gp.isZERO()) { // can happen with solvable rings throw new NotInvertibleException("h = " + h + ", g = " + g); } // adjust leading coefficient of g to get g*h == 1 GenSolvablePolynomial f = g.multiply(h); //System.out.println("f = " + f); GenSolvablePolynomial k = red.leftNormalform(getList(), f); //System.out.println("k = " + k); if (!k.isONE()) { C lbc = k.leadingBaseCoefficient(); lbc = lbc.inverse(); g = g.multiply(lbc); } if (debug) { //logger.info("inv G = " + G); //logger.info("inv G2F = " + x.G2F); //logger.info("inv row "+i+" = " + row); //logger.info("inv h = " + h); //logger.info("inv g = " + g); //logger.info("inv f = " + f); f = g.multiply(h); k = red.leftNormalform(getList(), f); logger.debug("inv k = " + k); if (!k.isUnit()) { throw new NotInvertibleException(" k = " + k); } } return g; } /** * Test if element is a unit modulo this ideal. * @param h solvable polynomial * @return true if h is a unit with respect to this, else false */ public boolean isUnit(GenSolvablePolynomial h) { if (h == null || h.isZERO()) { return false; } if (this.isZERO()) { return false; } List> F = new ArrayList>(1 + list.list.size()); F.add(h); F.addAll(getList()); List> G = bb.leftGB(F); for (GenSolvablePolynomial p : G) { if (p == null) { continue; } if (p.isUnit()) { return true; } } return false; } /** * Ideal common zero test. * @return -1, 0 or 1 if dimension(this) &eq; -1, 0 or ≥ 1. */ public int commonZeroTest() { if (this.isZERO()) { return 1; } if (!isGB) { doGB(); } if (this.isONE()) { return -1; } return bb.commonZeroTest(getList()); } /** * Test if this ideal is maximal. * @return true, if this is maximal and not one, else false. */ public boolean isMaximal() { if (commonZeroTest() != 0) { return false; } for (Long d : univariateDegrees()) { if (d > 1L) { // todo: test if irreducible return false; } } return true; } /** * Univariate head term degrees. * @return a list of the degrees of univariate head terms. */ public List univariateDegrees() { List ud = new ArrayList(); if (this.isZERO()) { return ud; } if (!isGB) { doGB(); } if (this.isONE()) { return ud; } return bb.univariateDegrees(getList()); } /** * Ideal dimension. * @return a dimension container (dim,maxIndep,list(maxIndep),vars). */ public Dimension dimension() { Ideal ci = new Ideal(list); return ci.dimension(); } /** * Construct univariate polynomials of minimal degree in all variables in * zero dimensional ideal(G). * @return list of univariate solvable polynomial of minimal degree in each * variable in ideal(G) */ public List> constructUnivariate() { List> univs = new ArrayList>(); for (int i = getRing().nvar - 1; i >= 0; i--) { GenSolvablePolynomial u = constructUnivariate(i); univs.add(u); } return univs; } /** * Construct univariate polynomial of minimal degree in variable i in zero * dimensional ideal(G). * @param i variable index. * @return univariate solvable polynomial of minimal degree in variable i in * ideal(G) */ public GenSolvablePolynomial constructUnivariate(int i) { doGB(); return bb.constructUnivariate(i, getList()); } } jas-2.5/src/edu/jas/application/ExamplesGeoTheorems.java0000644000175000017500000003305312022704664023561 0ustar giovannigiovanni/* * $Id: ExamplesGeoTheorems.java 4170 2012-09-08 18:08:52Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.List; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigRational; import edu.jas.gb.GBOptimized; import edu.jas.gb.GBProxy; import edu.jas.gb.GroebnerBase; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.GroebnerBaseParallel; import edu.jas.gbufd.GBFactory; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolynomialList; /** * ExamplesGeoTheorems for Groebner base usage. * @author GeoGebra developers. * @author Kovács Zoltán * @author Heinz Kredel. */ public class ExamplesGeoTheorems { /** * main. */ public static void main(String[] args) { BasicConfigurator.configure(); example10(); example11(); example12(); example13(); example14(); example15(); example16(); example17(); ComputerThreads.terminate(); } /** * get Pappus Example. */ public static List> getExample() { String[] vars = { "a1", "a2", "b1", "b2", "c1", "c2", "d1", "d2", "e1", "e2", "f1", "f2", "g1", "g2", "h1", "h2", "i1", "i2", "j1", "j2", "z1", "z2", "z3" }; BigRational br = new BigRational(); GenPolynomialRing pring = new GenPolynomialRing(br, vars); GenPolynomial e1 = pring.parse("(a1*(b2 - c2) + a2*( - b1 + c1) + b1*c2 - b2*c1)"); GenPolynomial e2 = pring.parse("(d1*(e2 - f2) + d2*( - e1 + f1) + e1*f2 - e2*f1)"); GenPolynomial e3 = pring.parse("(a1*( - e2 + h2) + a2*(e1 - h1) - e1*h2 + e2*h1)"); GenPolynomial e4 = pring.parse("(b1*(d2 - h2) + b2*( - d1 + h1) + d1*h2 - d2*h1)"); GenPolynomial e5 = pring.parse("(c1*(d2 - i2) + c2*( - d1 + i1) + d1*i2 - d2*i1)"); GenPolynomial e6 = pring.parse("(a1*( - f2 + i2) + a2*(f1 - i1) - f1*i2 + f2*i1)"); GenPolynomial e7 = pring.parse("(c1*(e2 - j2) + c2*( - e1 + j1) + e1*j2 - e2*j1)"); GenPolynomial e8 = pring.parse("(b1*( - f2 + j2) + b2*(f1 - j1) - f1*j2 + f2*j1)"); GenPolynomial e9 = pring .parse("(a1*(b2*z2 - d2*z2) + a2*( - b1*z2 + d1*z2) + b1*d2*z2 - b2*d1*z2 - 1)"); GenPolynomial e10 = pring .parse("(a1*(b2*z3 - e2*z3) + a2*( - b1*z3 + e1*z3) + b1*e2*z3 - b2*e1*z3 - 1)"); GenPolynomial e11 = pring .parse("(h1*(i2*z1 - j2*z1) + h2*( - i1*z1 + j1*z1) + i1*j2*z1 - i2*j1*z1 - 1)"); List> cp = new ArrayList>(11); cp.add(e1); cp.add(e2); cp.add(e3); cp.add(e4); cp.add(e5); cp.add(e6); cp.add(e7); cp.add(e8); cp.add(e9); cp.add(e10); cp.add(e11); return cp; } /** * Example Pappus, sequential. */ public static void example10() { List> cp = getExample(); BigRational br = new BigRational(); GenPolynomialRing pring = cp.get(0).ring; GroebnerBase sgb = GBFactory.getImplementation(br); List> gb; long t; t = System.currentTimeMillis(); gb = sgb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(gb) = " + t); t = System.currentTimeMillis(); gb = sgb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(gb) = " + t); PolynomialList pl = new PolynomialList(pring, gb); Ideal id = new Ideal(pl, true); System.out.println("cp = " + cp); System.out.println("id = " + id); Dimension dim = id.dimension(); System.out.println("dim = " + dim); } /** * Example Pappus, parallel proxy. */ public static void example11() { List> cp = getExample(); BigRational br = new BigRational(); GenPolynomialRing pring = cp.get(0).ring; GroebnerBaseAbstract sgb = GBFactory.getProxy(br); List> gb; long t; t = System.currentTimeMillis(); gb = sgb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(proxy-gb) = " + t); t = System.currentTimeMillis(); gb = sgb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(proxy-gb) = " + t); PolynomialList pl = new PolynomialList(pring, gb); Ideal id = new Ideal(pl, true); System.out.println("cp = " + cp); System.out.println("id = " + id); Dimension dim = id.dimension(); System.out.println("dim = " + dim); sgb.terminate(); } /** * Example Pappus, optimized term order. */ public static void example12() { List> cp = getExample(); BigRational br = new BigRational(); GenPolynomialRing pring = cp.get(0).ring; GroebnerBaseAbstract sgb = GBFactory.getImplementation(br); GroebnerBaseAbstract ogb = new GBOptimized(sgb, true); // false no change for GB == 1 List> gb; long t; t = System.currentTimeMillis(); gb = ogb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(optimized-gb) = " + t); t = System.currentTimeMillis(); gb = ogb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(optimized-gb) = " + t); PolynomialList pl = new PolynomialList(pring, gb); Ideal id = new Ideal(pl, true); System.out.println("cp = " + cp); System.out.println("id = " + id); Dimension dim = id.dimension(); System.out.println("dim = " + dim); ogb.terminate(); } /** * Example Pappus, optimized term order and parallel proxy. */ public static void example13() { List> cp = getExample(); BigRational br = new BigRational(); GenPolynomialRing pring = cp.get(0).ring; GroebnerBaseAbstract sgb = GBFactory.getProxy(br); GroebnerBaseAbstract ogb = new GBOptimized(sgb, true); // false no change for GB == 1 List> gb; long t; t = System.currentTimeMillis(); gb = ogb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(optimized-proxy-gb) = " + t); t = System.currentTimeMillis(); gb = ogb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(optimized-proxy-gb) = " + t); PolynomialList pl = new PolynomialList(pring, gb); Ideal id = new Ideal(pl, true); System.out.println("cp = " + cp); System.out.println("id = " + id); Dimension dim = id.dimension(); System.out.println("dim = " + dim); ogb.terminate(); } /** * Example Pappus, fraction free. */ public static void example14() { List> cp = getExample(); BigRational br = new BigRational(); GenPolynomialRing pring = cp.get(0).ring; GroebnerBaseAbstract sgb = GBFactory.getImplementation(br, GBFactory.Algo.ffgb); List> gb; long t; t = System.currentTimeMillis(); gb = sgb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(fraction-free-gb) = " + t); t = System.currentTimeMillis(); gb = sgb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(fraction-free-gb) = " + t); PolynomialList pl = new PolynomialList(pring, gb); Ideal id = new Ideal(pl, true); System.out.println("cp = " + cp); System.out.println("id = " + id); Dimension dim = id.dimension(); System.out.println("dim = " + dim); sgb.terminate(); } /** * Example Pappus, optimized and fraction free. */ public static void example15() { List> cp = getExample(); BigRational br = new BigRational(); GenPolynomialRing pring = cp.get(0).ring; GroebnerBaseAbstract sgb = GBFactory.getImplementation(br, GBFactory.Algo.ffgb); GroebnerBaseAbstract ogb = new GBOptimized(sgb, true); // false no change for GB == 1 List> gb; long t; t = System.currentTimeMillis(); gb = ogb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(optimized-fraction-free-gb) = " + t); t = System.currentTimeMillis(); gb = ogb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(optimized-fraction-free-gb) = " + t); PolynomialList pl = new PolynomialList(pring, gb); Ideal id = new Ideal(pl, true); System.out.println("cp = " + cp); System.out.println("id = " + id); Dimension dim = id.dimension(); System.out.println("dim = " + dim); ogb.terminate(); } /** * Example Pappus, proxy, optimized and fraction free. */ public static void example16() { List> cp = getExample(); BigRational br = new BigRational(); GenPolynomialRing pring = cp.get(0).ring; GroebnerBaseAbstract sgb = GBFactory.getImplementation(br, GBFactory.Algo.ffgb); GroebnerBaseAbstract ogb = new GBOptimized(sgb, true); // false no change for GB == 1 GroebnerBaseAbstract pgb = new GroebnerBaseParallel(); GroebnerBaseAbstract opgb = new GBOptimized(pgb, true); // false no change for GB == 1 GroebnerBaseAbstract popgb = new GBProxy(ogb, opgb); List> gb; long t; t = System.currentTimeMillis(); gb = popgb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(proxy-optimized-fraction-free-gb) = " + t); t = System.currentTimeMillis(); gb = popgb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(proxy-optimized-fraction-free-gb) = " + t); PolynomialList pl = new PolynomialList(pring, gb); Ideal id = new Ideal(pl, true); System.out.println("cp = " + cp); System.out.println("id = " + id); Dimension dim = id.dimension(); System.out.println("dim = " + dim); popgb.terminate(); } /** * Example Pappus, optimized and parallel and fraction free. */ public static void example17() { List> cp = getExample(); BigRational br = new BigRational(); GenPolynomialRing pring = cp.get(0).ring; GroebnerBaseAbstract sgb = GBFactory.getImplementation(br, GBFactory.Algo.ffgb); GroebnerBaseAbstract pgb = new GroebnerBaseParallel(); GroebnerBaseAbstract ppgb = new GBProxy(sgb, pgb); GroebnerBaseAbstract ogb = new GBOptimized(ppgb, true); // false no change for GB == 1 List> gb; long t; t = System.currentTimeMillis(); gb = ogb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(optimized-proxy-fraction-free-gb) = " + t); t = System.currentTimeMillis(); gb = ogb.GB(cp); t = System.currentTimeMillis() - t; //System.out.println("gb = " + gb); System.out.println("time(optimized-proxy-fraction-free-gb) = " + t); PolynomialList pl = new PolynomialList(pring, gb); Ideal id = new Ideal(pl, true); System.out.println("cp = " + cp); System.out.println("id = " + id); Dimension dim = id.dimension(); System.out.println("dim = " + dim); ogb.terminate(); } } jas-2.5/src/edu/jas/application/LocalRing.java0000644000175000017500000002012411460633470021507 0ustar giovannigiovanni/* * $Id: LocalRing.java 3358 2010-10-23 19:27:53Z kredel $ */ package edu.jas.application; import java.util.Random; import java.util.List; import java.util.ArrayList; import java.io.Reader; import org.apache.log4j.Logger; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.ufd.GreatestCommonDivisor; import edu.jas.ufd.GCDFactory; /** * Local ring class based on GenPolynomial with RingElem interface. * Objects of this class are effective immutable. * @author Heinz Kredel */ public class LocalRing > implements RingFactory< Local > { private static final Logger logger = Logger.getLogger(LocalRing.class); //private boolean debug = logger.isDebugEnabled(); /** * Greatest common divisor engine for coefficient content and primitive parts. */ protected final GreatestCommonDivisor engine; /** Polynomial ideal for localization. */ public final Ideal ideal; /** Polynomial ring of the factory. */ public final GenPolynomialRing ring; /** Indicator if this ring is a field. */ protected int isField = -1; // initially unknown /** The constructor creates a LocalRing object * from a GenPolynomialRing and a GenPolynomial. * @param i localization polynomial ideal. */ public LocalRing(Ideal i) { if ( i == null ) { throw new IllegalArgumentException("ideal may not be null"); } ideal = i.GB(); // cheap if isGB if ( ideal.isONE() ) { throw new IllegalArgumentException("ideal may not be 1"); } if ( !ideal.isMaximal() ) { //throw new IllegalArgumentException("ideal must be maximal"); logger.warn("ideal not maximal"); } ring = ideal.list.ring; //engine = GCDFactory.getImplementation( ring.coFac ); engine = GCDFactory.getProxy( ring.coFac ); } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return false; } /** Copy Local element c. * @param c * @return a copy of c. */ public Local copy(Local c) { return new Local( c.ring, c.num, c.den, true ); } /** Get the zero element. * @return 0 as Local. */ public Local getZERO() { return new Local( this, ring.getZERO() ); } /** Get the one element. * @return 1 as Local. */ public Local getONE() { return new Local( this, ring.getONE() ); } /** Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List> pgens = ring.generators(); List> gens = new ArrayList>( pgens.size() ); for ( GenPolynomial p : pgens ) { Local q = new Local( this, p ); gens.add(q); } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return ring.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return ring.isAssociative(); } /** * Query if this ring is a field. * @return false. */ public boolean isField() { if ( isField > 0 ) { return true; } if ( isField == 0 ) { return false; } // ?? return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return ring.characteristic(); } /** Get a Local element from a BigInteger value. * @param a BigInteger. * @return a Local. */ public Local fromInteger(java.math.BigInteger a) { return new Local( this, ring.fromInteger(a) ); } /** Get a Local element from a long value. * @param a long. * @return a Local. */ public Local fromInteger(long a) { return new Local( this, ring.fromInteger(a) ); } /** Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { return "Local[ " + ideal.toString() + " ]"; } /** Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "LC(" + ideal.list.toScript() + ")"; } /** Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object b) { if ( ! ( b instanceof LocalRing ) ) { return false; } LocalRing a = null; try { a = (LocalRing) b; } catch (ClassCastException e) { } if ( a == null ) { return false; } if ( ! ring.equals( a.ring ) ) { return false; } return ideal.equals( a.ideal ); } /** Hash code for this local ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ideal.hashCode(); return h; } /** Local random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random residue element. */ public Local random(int n) { GenPolynomial r = ring.random( n ).monic(); GenPolynomial s = ring.random( n ).monic(); s = ideal.normalform( s ); while ( s.isZERO() ) { logger.info("s was in ideal"); s = ring.random( n ).monic(); s = ideal.normalform( s ); } return new Local( this, r, s, false ); } /** * Generate a random residum polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @return a random residue polynomial. */ public Local random(int k, int l, int d, float q) { GenPolynomial r = ring.random(k,l,d,q).monic(); GenPolynomial s = ring.random(k,l,d,q).monic(); s = ideal.normalform( s ); while ( s.isZERO() ) { logger.info("s was in ideal "+ideal); s = ring.random( k,l,d,q ).monic(); s = ideal.normalform( s ); } return new Local( this, r, s, false ); } /** Local random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random residue element. */ public Local random(int n, Random rnd) { GenPolynomial r = ring.random( n, rnd ).monic(); GenPolynomial s = ring.random( n, rnd ).monic(); s = ideal.normalform( s ); while ( s.isZERO() ) { logger.info("s was in ideal"); s = ring.random( n, rnd ).monic(); s = ideal.normalform( s ); } return new Local( this, r, s, false); } /** Parse Local from String. * @param s String. * @return Local from s. */ public Local parse(String s) { GenPolynomial x = ring.parse( s ); return new Local( this, x ); } /** Parse Local from Reader. * @param r Reader. * @return next Local from r. */ public Local parse(Reader r) { GenPolynomial x = ring.parse( r ); return new Local( this, x ); } } jas-2.5/src/edu/jas/application/Ideal.java0000644000175000017500000031432312014234362020653 0ustar giovannigiovanni/* * $Id: Ideal.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import org.apache.log4j.Logger; import edu.jas.gb.ExtendedGB; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.Reduction; import edu.jas.gbufd.GBFactory; import edu.jas.gbufd.GroebnerBasePartial; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.OptimizedPolynomialList; import edu.jas.poly.PolyUtil; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; import edu.jas.poly.TermOrderOptimization; import edu.jas.structure.GcdRingElem; import edu.jas.structure.NotInvertibleException; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; import edu.jas.ufd.FactorAbstract; import edu.jas.ufd.GCDFactory; import edu.jas.ufd.GreatestCommonDivisor; import edu.jas.ufd.PolyUfdUtil; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; import edu.jas.ufd.SquarefreeAbstract; import edu.jas.ufd.SquarefreeFactory; /** * Ideal implements some methods for ideal arithmetic, for example intersection, * quotient and zero and positive dimensional ideal decomposition. * @author Heinz Kredel */ public class Ideal> implements Comparable>, Serializable { private static final Logger logger = Logger.getLogger(Ideal.class); private final boolean debug = logger.isDebugEnabled(); /** * The data structure is a PolynomialList. */ protected PolynomialList list; /** * Indicator if list is a Groebner Base. */ protected boolean isGB; /** * Indicator if test has been performed if this is a Groebner Base. */ protected boolean testGB; /** * Indicator if list has optimized term order. */ protected boolean isTopt; /** * Groebner base engine. */ protected final GroebnerBaseAbstract bb; /** * Reduction engine. */ protected final Reduction red; /** * Squarefree decomposition engine. */ protected final SquarefreeAbstract engine; /** * Constructor. * @param ring polynomial ring */ public Ideal(GenPolynomialRing ring) { this(ring, new ArrayList>()); } /** * Constructor. * @param ring polynomial ring * @param F list of polynomials */ public Ideal(GenPolynomialRing ring, List> F) { this(new PolynomialList(ring, F)); } /** * Constructor. * @param ring polynomial ring * @param F list of polynomials * @param gb true if F is known to be a Groebner Base, else false */ public Ideal(GenPolynomialRing ring, List> F, boolean gb) { this(new PolynomialList(ring, F), gb); } /** * Constructor. * @param ring polynomial ring * @param F list of polynomials * @param gb true if F is known to be a Groebner Base, else false * @param topt true if term order is optimized, else false */ public Ideal(GenPolynomialRing ring, List> F, boolean gb, boolean topt) { this(new PolynomialList(ring, F), gb, topt); } /** * Constructor. * @param list polynomial list */ public Ideal(PolynomialList list) { this(list, false); } /** * Constructor. * @param list polynomial list * @param bb Groebner Base engine * @param red Reduction engine */ public Ideal(PolynomialList list, GroebnerBaseAbstract bb, Reduction red) { this(list, false, bb, red); } /** * Constructor. * @param list polynomial list * @param gb true if list is known to be a Groebner Base, else false */ public Ideal(PolynomialList list, boolean gb) { //this(list, gb, new GroebnerBaseSeqPairSeq(), new ReductionSeq()); this(list, gb, GBFactory.getImplementation(list.ring.coFac)); } /** * Constructor. * @param list polynomial list * @param gb true if list is known to be a Groebner Base, else false * @param topt true if term order is optimized, else false */ public Ideal(PolynomialList list, boolean gb, boolean topt) { //this(list, gb, topt, new GroebnerBaseSeqPairSeq(), new ReductionSeq()); this(list, gb, topt, GBFactory.getImplementation(list.ring.coFac)); } /** * Constructor. * @param list polynomial list * @param gb true if list is known to be a Groebner Base, else false * @param bb Groebner Base engine * @param red Reduction engine */ public Ideal(PolynomialList list, boolean gb, GroebnerBaseAbstract bb, Reduction red) { this(list, gb, false, bb, red); } /** * Constructor. * @param list polynomial list * @param gb true if list is known to be a Groebner Base, else false * @param bb Groebner Base engine */ public Ideal(PolynomialList list, boolean gb, GroebnerBaseAbstract bb) { this(list, gb, false, bb, bb.red); } /** * Constructor. * @param list polynomial list * @param gb true if list is known to be a Groebner Base, else false * @param topt true if term order is optimized, else false * @param bb Groebner Base engine */ public Ideal(PolynomialList list, boolean gb, boolean topt, GroebnerBaseAbstract bb) { this(list, gb, topt, bb, bb.red); } /** * Constructor. * @param list polynomial list * @param gb true if list is known to be a Groebner Base, else false * @param topt true if term order is optimized, else false * @param bb Groebner Base engine * @param red Reduction engine */ public Ideal(PolynomialList list, boolean gb, boolean topt, GroebnerBaseAbstract bb, Reduction red) { if (list == null || list.list == null) { throw new IllegalArgumentException("list and list.list may not be null"); } this.list = list; this.isGB = gb; this.isTopt = topt; this.testGB = (gb ? true : false); // ?? this.bb = bb; this.red = red; this.engine = SquarefreeFactory. getImplementation(list.ring.coFac); } /** * Clone this. * @return a copy of this. */ public Ideal copy() { return new Ideal(list.copy(), isGB, isTopt, bb, red); } /** * Get the List of GenPolynomials. * @return list.list */ public List> getList() { return list.list; } /** * Get the GenPolynomialRing. * @return list.ring */ public GenPolynomialRing getRing() { return list.ring; } /** * Get the zero ideal. * @return ideal(0) */ public Ideal getZERO() { List> z = new ArrayList>(0); PolynomialList pl = new PolynomialList(getRing(), z); return new Ideal(pl, true, isTopt, bb, red); } /** * Get the one ideal. * @return ideal(1) */ public Ideal getONE() { List> one = new ArrayList>(1); one.add(list.ring.getONE()); PolynomialList pl = new PolynomialList(getRing(), one); return new Ideal(pl, true, isTopt, bb, red); } /** * String representation of the ideal. * @see java.lang.Object#toString() */ @Override public String toString() { return list.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ public String toScript() { // Python case return list.toScript(); } /** * Comparison with any other object. Note: If both ideals are not Groebner * Bases, then false may be returned even the ideals are equal. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof Ideal)) { logger.warn("equals no Ideal"); return false; } Ideal B = null; try { B = (Ideal) b; } catch (ClassCastException ignored) { return false; } //if ( isGB && B.isGB ) { // return list.equals( B.list ); requires also monic polys //} else { // compute GBs ? return this.contains(B) && B.contains(this); //} } /** * Ideal list comparison. * @param L other Ideal. * @return compareTo() of polynomial lists. */ public int compareTo(Ideal L) { return list.compareTo(L.list); } /** * Hash code for this ideal. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = list.hashCode(); if (isGB) { h = h << 1; } if (testGB) { h += 1; } return h; } /** * Test if ZERO ideal. * @return true, if this is the 0 ideal, else false */ public boolean isZERO() { return list.isZERO(); } /** * Test if ONE is contained in the ideal. To test for a proper ideal use * ! id.isONE(). * @return true, if this is the 1 ideal, else false */ public boolean isONE() { return list.isONE(); } /** * Optimize the term order. */ public void doToptimize() { if (isTopt) { return; } list = TermOrderOptimization. optimizeTermOrder(list); isTopt = true; if (isGB) { isGB = false; doGB(); } return; } /** * Test if this is a Groebner base. * @return true, if this is a Groebner base, else false */ public boolean isGB() { if (testGB) { return isGB; } logger.warn("isGB computing"); isGB = bb.isGB(getList()); testGB = true; return isGB; } /** * Do Groebner Base. compute the Groebner Base for this ideal. */ @SuppressWarnings("unchecked") public void doGB() { if (isGB && testGB) { return; } //logger.warn("GB computing"); List> G = getList(); logger.info("GB computing = " + G); G = bb.GB(G); if (isTopt) { List perm = ((OptimizedPolynomialList) list).perm; list = new OptimizedPolynomialList(perm, getRing(), G); } else { list = new PolynomialList(getRing(), G); } isGB = true; testGB = true; return; } /** * Groebner Base. Get a Groebner Base for this ideal. * @return GB(this) */ public Ideal GB() { if (isGB) { return this; } doGB(); return this; } /** * Ideal containment. Test if B is contained in this ideal. Note: this is * eventually modified to become a Groebner Base. * @param B ideal * @return true, if B is contained in this, else false */ public boolean contains(Ideal B) { if (B == null || B.isZERO()) { return true; } return contains(B.getList()); } /** * Ideal containment. Test if b is contained in this ideal. Note: this is * eventually modified to become a Groebner Base. * @param b polynomial * @return true, if b is contained in this, else false */ public boolean contains(GenPolynomial b) { if (b == null || b.isZERO()) { return true; } if (this.isONE()) { return true; } if (this.isZERO()) { return false; } if (!isGB) { doGB(); } GenPolynomial z; z = red.normalform(getList(), b); if (z == null || z.isZERO()) { return true; } return false; } /** * Ideal containment. Test if each b in B is contained in this ideal. Note: * this is eventually modified to become a Groebner Base. * @param B list of polynomials * @return true, if each b in B is contained in this, else false */ public boolean contains(List> B) { if (B == null || B.size() == 0) { return true; } if (this.isONE()) { return true; } if (!isGB) { doGB(); } for (GenPolynomial b : B) { if (b == null) { continue; } GenPolynomial z = red.normalform(getList(), b); if (!z.isZERO()) { //System.out.println("contains nf(b) != 0: " + b); return false; } } return true; } /** * Summation. Generators for the sum of ideals. Note: if both ideals are * Groebner bases, a Groebner base is returned. * @param B ideal * @return ideal(this+B) */ public Ideal sum(Ideal B) { if (B == null || B.isZERO()) { return this; } if (this.isZERO()) { return B; } int s = getList().size() + B.getList().size(); List> c; c = new ArrayList>(s); c.addAll(getList()); c.addAll(B.getList()); Ideal I = new Ideal(getRing(), c, false); if (isGB && B.isGB) { I.doGB(); } return I; } /** * Summation. Generators for the sum of ideal and a polynomial. Note: if * this ideal is a Groebner base, a Groebner base is returned. * @param b polynomial * @return ideal(this+{b}) */ public Ideal sum(GenPolynomial b) { if (b == null || b.isZERO()) { return this; } int s = getList().size() + 1; List> c; c = new ArrayList>(s); c.addAll(getList()); c.add(b); Ideal I = new Ideal(getRing(), c, false); if (isGB) { I.doGB(); } return I; } /** * Summation. Generators for the sum of this ideal and a list of * polynomials. Note: if this ideal is a Groebner base, a Groebner base is * returned. * @param L list of polynomials * @return ideal(this+L) */ public Ideal sum(List> L) { if (L == null || L.isEmpty()) { return this; } int s = getList().size() + L.size(); List> c = new ArrayList>(s); c.addAll(getList()); c.addAll(L); Ideal I = new Ideal(getRing(), c, false); if (isGB) { I.doGB(); } return I; } /** * Product. Generators for the product of ideals. Note: if both ideals are * Groebner bases, a Groebner base is returned. * @param B ideal * @return ideal(this*B) */ public Ideal product(Ideal B) { if (B == null || B.isZERO()) { return B; } if (this.isZERO()) { return this; } int s = getList().size() * B.getList().size(); List> c; c = new ArrayList>(s); for (GenPolynomial p : getList()) { for (GenPolynomial q : B.getList()) { q = p.multiply(q); c.add(q); } } Ideal I = new Ideal(getRing(), c, false); if (isGB && B.isGB) { I.doGB(); } return I; } /** * Intersection. Generators for the intersection of ideals. Using an * iterative algorithm. * @param Bl list of ideals * @return ideal(cap_i B_i), a Groebner base */ public Ideal intersect(List> Bl) { if (Bl == null || Bl.size() == 0) { return getZERO(); } Ideal I = null; for (Ideal B : Bl) { if (I == null) { I = B; continue; } if (I.isONE()) { return I; } I = I.intersect(B); } return I; } /** * Intersection. Generators for the intersection of ideals. * @param B ideal * @return ideal(this \cap B), a Groebner base */ public Ideal intersect(Ideal B) { if (B == null || B.isZERO()) { // (0) return B; } if (this.isZERO()) { return this; } int s = getList().size() + B.getList().size(); List> c; c = new ArrayList>(s); List> a = getList(); List> b = B.getList(); GenPolynomialRing tfac = getRing().extend(1); // term order is also adjusted for (GenPolynomial p : a) { p = p.extend(tfac, 0, 1L); // t*p c.add(p); } for (GenPolynomial p : b) { GenPolynomial q = p.extend(tfac, 0, 1L); GenPolynomial r = p.extend(tfac, 0, 0L); p = r.subtract(q); // (1-t)*p c.add(p); } logger.warn("intersect computing GB"); List> g = bb.GB(c); if (debug) { logger.debug("intersect GB = " + g); } Ideal E = new Ideal(tfac, g, true); Ideal I = E.intersect(getRing()); return I; } /** * Intersection. Generators for the intersection of a ideal with a * polynomial ring. The polynomial ring of this ideal must be a contraction * of R and the TermOrder must be an elimination order. * @param R polynomial ring * @return ideal(this \cap R) */ public Ideal intersect(GenPolynomialRing R) { if (R == null) { throw new IllegalArgumentException("R may not be null"); } int d = getRing().nvar - R.nvar; if (d <= 0) { return this; } List> H = new ArrayList>(getList().size()); for (GenPolynomial p : getList()) { Map> m = null; m = p.contract(R); if (debug) { logger.debug("intersect contract m = " + m); } if (m.size() == 1) { // contains one power of variables for (Map.Entry> me : m.entrySet()) { ExpVector e = me.getKey(); if (e.isZERO()) { H.add(me.getValue()); //m.get(e)); } } } } GenPolynomialRing tfac = getRing().contract(d); if (tfac.equals(R)) { // check return new Ideal(R, H, isGB, isTopt); } logger.info("tfac, R = " + tfac + ", " + R); // throw new RuntimeException("contract(this) != R"); return new Ideal(R, H); // compute GB } /** * Eliminate. Generators for the intersection of a ideal with a polynomial * ring. The polynomial rings must have variable names. * @param R polynomial ring * @return ideal(this \cap R) */ public Ideal eliminate(GenPolynomialRing R) { if (R == null) { throw new IllegalArgumentException("R may not be null"); } if (list.ring.equals(R)) { return this; } String[] ename = R.getVars(); Ideal I = eliminate(ename); return I.intersect(R); } /** * Eliminate. Preparation of generators for the intersection of a ideal with * a polynomial ring. * @param ename variables for the elimination ring. * @return ideal(this) in K[ename,{vars \ ename}]) */ public Ideal eliminate(String... ename) { //System.out.println("ename = " + Arrays.toString(ename)); if (ename == null) { throw new IllegalArgumentException("ename may not be null"); } String[] aname = getRing().getVars(); //System.out.println("aname = " + Arrays.toString(aname)); if (aname == null) { throw new IllegalArgumentException("aname may not be null"); } GroebnerBasePartial bbp = new GroebnerBasePartial(bb, null); String[] rname = GroebnerBasePartial.remainingVars(aname, ename); //System.out.println("rname = " + Arrays.toString(rname)); PolynomialList Pl = null; if (rname.length == 0) { if (Arrays.equals(aname, ename)) { return this; } Pl = bbp.partialGB(getList(), ename); // normal GB } else { Pl = bbp.elimPartialGB(getList(), rname, ename); // reversed! } //System.out.println("Pl = " + Pl); if (debug) { logger.debug("elimination GB = " + Pl); } Ideal I = new Ideal(Pl, true); return I; } /** * Quotient. Generators for the ideal quotient. * @param h polynomial * @return ideal(this : h), a Groebner base */ public Ideal quotient(GenPolynomial h) { if (h == null) { // == (0) return this; } if (h.isZERO()) { return this; } if (this.isZERO()) { return this; } List> H; H = new ArrayList>(1); H.add(h); Ideal Hi = new Ideal(getRing(), H, true); Ideal I = this.intersect(Hi); List> Q; Q = new ArrayList>(I.getList().size()); for (GenPolynomial q : I.getList()) { q = q.divide(h); // remainder == 0 Q.add(q); } return new Ideal(getRing(), Q, true /*false?*/); } /** * Quotient. Generators for the ideal quotient. * @param H ideal * @return ideal(this : H), a Groebner base */ public Ideal quotient(Ideal H) { if (H == null) { // == (0) return this; } if (H.isZERO()) { return this; } if (this.isZERO()) { return this; } Ideal Q = null; for (GenPolynomial h : H.getList()) { Ideal Hi = this.quotient(h); if (Q == null) { Q = Hi; } else { Q = Q.intersect(Hi); } } return Q; } /** * Infinite quotient. Generators for the infinite ideal quotient. * @param h polynomial * @return ideal(this : hs), a Groebner base */ public Ideal infiniteQuotientRab(GenPolynomial h) { if (h == null || h.isZERO()) { // == (0) return getONE(); } if (h.isONE()) { return this; } if (this.isZERO()) { return this; } Ideal I = this.GB(); // should be already List> a = I.getList(); List> c; c = new ArrayList>(a.size() + 1); GenPolynomialRing tfac = getRing().extend(1); // term order is also adjusted for (GenPolynomial p : a) { p = p.extend(tfac, 0, 0L); // p c.add(p); } GenPolynomial q = h.extend(tfac, 0, 1L); GenPolynomial r = tfac.getONE(); // h.extend( tfac, 0, 0L ); GenPolynomial hs = q.subtract(r); // 1 - t*h // (1-t)*h c.add(hs); logger.warn("infiniteQuotientRab computing GB "); List> g = bb.GB(c); if (debug) { logger.info("infiniteQuotientRab = " + tfac + ", c = " + c); logger.info("infiniteQuotientRab GB = " + g); } Ideal E = new Ideal(tfac, g, true); Ideal Is = E.intersect(getRing()); return Is; } /** * Infinite quotient exponent. * @param h polynomial * @param Q quotient this : h^\infinity * @return s with Q = this : hs */ public int infiniteQuotientExponent(GenPolynomial h, Ideal Q) { int s = 0; if (h == null) { // == 0 return s; } if (h.isZERO() || h.isONE()) { return s; } if (this.isZERO() || this.isONE()) { return s; } //see below: if (this.contains(Q)) { // return s; //} GenPolynomial p = getRing().getONE(); for (GenPolynomial q : Q.getList()) { if (this.contains(q)) { continue; } //System.out.println("q = " + q + ", p = " + p + ", s = " + s); GenPolynomial qp = q.multiply(p); while (!this.contains(qp)) { p = p.multiply(h); s++; qp = q.multiply(p); } } return s; } /** * Infinite quotient. Generators for the infinite ideal quotient. * @param h polynomial * @return ideal(this : hs), a Groebner base */ public Ideal infiniteQuotient(GenPolynomial h) { if (h == null) { // == (0) return this; } if (h.isZERO()) { return this; } if (this.isZERO()) { return this; } int s = 0; Ideal I = this.GB(); // should be already GenPolynomial hs = h; Ideal Is = I; boolean eq = false; while (!eq) { Is = I.quotient(hs); Is = Is.GB(); // should be already logger.info("infiniteQuotient s = " + s); eq = Is.contains(I); // I.contains(Is) always if (!eq) { I = Is; s++; // hs = hs.multiply( h ); } } return Is; } /** * Radical membership test. * @param h polynomial * @return true if h is contained in the radical of ideal(this), else false. */ public boolean isRadicalMember(GenPolynomial h) { if (h == null) { // == (0) return true; } if (h.isZERO()) { return true; } if (this.isZERO()) { return true; } Ideal x = infiniteQuotientRab(h); if (debug) { logger.debug("infiniteQuotientRab = " + x); } return x.isONE(); } /** * Infinite quotient. Generators for the infinite ideal quotient. * @param h polynomial * @return ideal(this : hs), a Groebner base */ public Ideal infiniteQuotientOld(GenPolynomial h) { if (h == null) { // == (0) return this; } if (h.isZERO()) { return this; } if (this.isZERO()) { return this; } int s = 0; Ideal I = this.GB(); // should be already GenPolynomial hs = h; boolean eq = false; while (!eq) { Ideal Is = I.quotient(hs); Is = Is.GB(); // should be already logger.debug("infiniteQuotient s = " + s); eq = Is.contains(I); // I.contains(Is) always if (!eq) { I = Is; s++; hs = hs.multiply(h); } } return I; } /** * Infinite Quotient. Generators for the ideal infinite quotient. * @param H ideal * @return ideal(this : Hs), a Groebner base */ public Ideal infiniteQuotient(Ideal H) { if (H == null) { // == (0) return this; } if (H.isZERO()) { return this; } if (this.isZERO()) { return this; } Ideal Q = null; for (GenPolynomial h : H.getList()) { Ideal Hi = this.infiniteQuotient(h); if (Q == null) { Q = Hi; } else { Q = Q.intersect(Hi); } } return Q; } /** * Infinite Quotient. Generators for the ideal infinite quotient. * @param H ideal * @return ideal(this : Hs), a Groebner base */ public Ideal infiniteQuotientRab(Ideal H) { if (H == null) { // == (0) return this; } if (H.isZERO()) { return this; } if (this.isZERO()) { return this; } Ideal Q = null; for (GenPolynomial h : H.getList()) { Ideal Hi = this.infiniteQuotientRab(h); if (Q == null) { Q = Hi; } else { Q = Q.intersect(Hi); } } return Q; } /** * Power. Generators for the power of this ideal. Note: if this ideal is a * Groebner base, a Groebner base is returned. * @param d integer * @return ideal(this^d) */ public Ideal power(int d) { if (d <= 0) { return getONE(); } if (this.isZERO() || this.isONE()) { return this; } Ideal c = this; for (int i = 1; i < d; i++) { c = c.product(this); } return c; } /** * Normalform for element. * @param h polynomial * @return normalform of h with respect to this */ public GenPolynomial normalform(GenPolynomial h) { if (h == null) { return h; } if (h.isZERO()) { return h; } if (this.isZERO()) { return h; } GenPolynomial r; r = red.normalform(list.list, h); return r; } /** * Normalform for list of elements. * @param L polynomial list * @return list of normalforms of the elements of L with respect to this */ public List> normalform(List> L) { if (L == null) { return L; } if (L.size() == 0) { return L; } if (this.isZERO()) { return L; } List> M = new ArrayList>(L.size()); for (GenPolynomial h : L) { GenPolynomial r = normalform(h); if (r != null && !r.isZERO()) { M.add(r); } } return M; } /** * Inverse for element modulo this ideal. * @param h polynomial * @return inverse of h with respect to this, if defined */ public GenPolynomial inverse(GenPolynomial h) { if (h == null || h.isZERO()) { throw new NotInvertibleException("zero not invertible"); } if (this.isZERO()) { throw new NotInvertibleException("zero ideal"); } if (h.isUnit()) { return h.inverse(); } doGB(); List> F = new ArrayList>(1 + list.list.size()); F.add(h); F.addAll(list.list); //System.out.println("F = " + F); ExtendedGB x = bb.extGB(F); List> G = x.G; //System.out.println("G = " + G); GenPolynomial one = null; int i = -1; for (GenPolynomial p : G) { i++; if (p == null) { continue; } if (p.isUnit()) { one = p; break; } } if (one == null) { throw new NotInvertibleException(" h = " + h); } List> row = x.G2F.get(i); // != -1 GenPolynomial g = row.get(0); if (g == null || g.isZERO()) { throw new NotInvertibleException(" h = " + h); } // adjust g to get g*h == 1 GenPolynomial f = g.multiply(h); GenPolynomial k = red.normalform(list.list, f); if (!k.isONE()) { C lbc = k.leadingBaseCoefficient(); lbc = lbc.inverse(); g = g.multiply(lbc); } if (debug) { //logger.info("inv G = " + G); //logger.info("inv G2F = " + x.G2F); //logger.info("inv row "+i+" = " + row); //logger.info("inv h = " + h); //logger.info("inv g = " + g); //logger.info("inv f = " + f); f = g.multiply(h); k = red.normalform(list.list, f); logger.debug("inv k = " + k); if (!k.isUnit()) { throw new NotInvertibleException(" k = " + k); } } return g; } /** * Test if element is a unit modulo this ideal. * @param h polynomial * @return true if h is a unit with respect to this, else false */ public boolean isUnit(GenPolynomial h) { if (h == null || h.isZERO()) { return false; } if (this.isZERO()) { return false; } List> F = new ArrayList>(1 + list.list.size()); F.add(h); F.addAll(list.list); List> G = bb.GB(F); for (GenPolynomial p : G) { if (p == null) { continue; } if (p.isUnit()) { return true; } } return false; } /** * Radical approximation. Squarefree generators for the ideal. * @return squarefree(this), a Groebner base */ public Ideal squarefree() { if (this.isZERO()) { return this; } Ideal R = this; Ideal Rp = null; List> li, ri; while (true) { li = R.getList(); ri = new ArrayList>(li); //.size() ); for (GenPolynomial h : li) { GenPolynomial r = engine.squarefreePart(h); ri.add(r); } Rp = new Ideal(R.getRing(), ri, false); Rp.doGB(); if (R.equals(Rp)) { break; } R = Rp; } return R; } /** * Ideal common zero test. * @return -1, 0 or 1 if dimension(this) &eq; -1, 0 or ≥ 1. */ public int commonZeroTest() { if (this.isZERO()) { return 1; } if (!isGB) { doGB(); } if (this.isONE()) { return -1; } return bb.commonZeroTest(getList()); } /** * Test if this ideal is maximal. * @return true, if this is maximal and not one, else false. */ public boolean isMaximal() { if (commonZeroTest() != 0) { return false; } for (Long d : univariateDegrees()) { if (d > 1L) { // todo: test if irreducible return false; } } return true; } /** * Univariate head term degrees. * @return a list of the degrees of univariate head terms. */ public List univariateDegrees() { List ud = new ArrayList(); if (this.isZERO()) { return ud; } if (!isGB) { doGB(); } if (this.isONE()) { return ud; } return bb.univariateDegrees(getList()); } /** * Ideal dimension. * @return a dimension container (dim,maxIndep,list(maxIndep),vars). */ public Dimension dimension() { int t = commonZeroTest(); Set S = new HashSet(); Set> M = new HashSet>(); if (t <= 0) { return new Dimension(t, S, M, this.list.ring.getVars()); } int d = 0; Set U = new HashSet(); for (int i = 0; i < this.list.ring.nvar; i++) { U.add(i); } M = dimension(S, U, M); for (Set m : M) { int dp = m.size(); if (dp > d) { d = dp; S = m; } } return new Dimension(d, S, M, this.list.ring.getVars()); } /** * Ideal dimension. * @param S is a set of independent variables. * @param U is a set of variables of unknown status. * @param M is a list of maximal sets of independent variables. * @return a list of maximal sets of independent variables, eventually * containing S. */ protected Set> dimension(Set S, Set U, Set> M) { Set> MP = M; Set UP = new HashSet(U); for (Integer j : U) { UP.remove(j); Set SP = new HashSet(S); SP.add(j); if (!containsHT(SP, getList())) { MP = dimension(SP, UP, MP); } } boolean contained = false; for (Set m : MP) { if (m.containsAll(S)) { contained = true; break; } } if (!contained) { MP.add(S); } return MP; } /** * Ideal head term containment test. * @param G list of polynomials. * @param H index set. * @return true, if the vaiables of the head terms of each polynomial in G * are contained in H, else false. */ protected boolean containsHT(Set H, List> G) { Set S = null; for (GenPolynomial p : G) { if (p == null) { continue; } ExpVector e = p.leadingExpVector(); if (e == null) { continue; } int[] v = e.dependencyOnVariables(); if (v == null) { continue; } //System.out.println("v = " + Arrays.toString(v)); if (S == null) { // revert indices S = new HashSet(H.size()); int r = e.length() - 1; for (Integer i : H) { S.add(r - i); } } if (contains(v, S)) { // v \subset S return true; } } return false; } /** * Set containment. is v \subset H. * @param v index array. * @param H index set. * @return true, if each element of v is contained in H, else false . */ protected boolean contains(int[] v, Set H) { for (int i = 0; i < v.length; i++) { if (!H.contains(v[i])) { return false; } } return true; } /** * Construct univariate polynomials of minimal degree in all variables in * zero dimensional ideal(G). * @return list of univariate polynomial of minimal degree in each variable * in ideal(G) */ public List> constructUnivariate() { List> univs = new ArrayList>(); for (int i = list.ring.nvar - 1; i >= 0; i--) { GenPolynomial u = constructUnivariate(i); univs.add(u); } return univs; } /** * Construct univariate polynomial of minimal degree in variable i in zero * dimensional ideal(G). * @param i variable index. * @return univariate polynomial of minimal degree in variable i in ideal(G) */ public GenPolynomial constructUnivariate(int i) { doGB(); return bb.constructUnivariate(i, getList()); } /** * Zero dimensional radical decompostition. See Seidenbergs lemma 92, and * BWK lemma 8.13. * @return intersection of radical ideals G_i with ideal(this) subseteq * cap_i( ideal(G_i) ) */ public List> zeroDimRadicalDecomposition() { List> dec = new ArrayList>(); if (this.isZERO()) { return dec; } IdealWithUniv iwu = new IdealWithUniv(this, new ArrayList>()); dec.add(iwu); if (this.isONE()) { return dec; } if (list.ring.coFac.characteristic().signum() > 0 && !list.ring.coFac.isFinite()) { logger.warn("must use prime decomposition for char p and infinite coefficient rings, found " + list.ring.coFac.toScript()); return zeroDimPrimeDecomposition(); } for (int i = list.ring.nvar - 1; i >= 0; i--) { List> part = new ArrayList>(); for (IdealWithUniv id : dec) { //System.out.println("id = " + id + ", i = " + i); GenPolynomial u = id.ideal.constructUnivariate(i); SortedMap, Long> facs = engine.baseSquarefreeFactors(u); if (facs == null || facs.size() == 0 || (facs.size() == 1 && facs.get(facs.firstKey()) == 1L)) { List> iup = new ArrayList>(); iup.addAll(id.upolys); iup.add(u); IdealWithUniv Ipu = new IdealWithUniv(id.ideal, iup); part.add(Ipu); continue; // irreducible } if (logger.isInfoEnabled()) { logger.info("squarefree facs = " + facs); } GenPolynomialRing mfac = id.ideal.list.ring; int j = mfac.nvar - 1 - i; for (GenPolynomial p : facs.keySet()) { // make p multivariate GenPolynomial pm = p.extendUnivariate(mfac, j); // mfac.parse( p.toString() ); //stem.out.println("pm = " + pm); Ideal Ip = id.ideal.sum(pm); List> iup = new ArrayList>(); iup.addAll(id.upolys); iup.add(p); IdealWithUniv Ipu = new IdealWithUniv(Ip, iup); if (debug) { logger.info("ideal with squarefree facs = " + Ipu); } part.add(Ipu); } } dec = part; //part = new ArrayList>(); } return dec; } /** * Test for Zero dimensional radical. See Seidenbergs lemma 92, and BWK * lemma 8.13. * @return true if this is an zero dimensional radical ideal, else false */ public boolean isZeroDimRadical() { if (this.isZERO()) { return false; } if (this.isONE()) { return false; // not 0-dim } if (list.ring.coFac.characteristic().signum() > 0 && !list.ring.coFac.isFinite()) { logger.warn("radical only for char 0 or finite coefficient rings, but found " + list.ring.coFac.toScript()); } for (int i = list.ring.nvar - 1; i >= 0; i--) { GenPolynomial u = constructUnivariate(i); boolean t = engine.isSquarefree(u); if (!t) { System.out.println("not squarefree " + engine.squarefreePart(u) + ", " + u); return false; } } return true; } /** * Zero dimensional ideal irreducible decompostition. See algorithm DIRGZD * of BGK 1986 and also PREDEC of the Gröbner bases book 1993. * @return intersection H, of ideals G_i with ideal(this) subseteq cap_i( * ideal(G_i) ) and each ideal G_i has only irreducible minimal * univariate polynomials and the G_i are pairwise co-prime. */ public List> zeroDimDecomposition() { List> dec = new ArrayList>(); if (this.isZERO()) { return dec; } IdealWithUniv iwu = new IdealWithUniv(this, new ArrayList>()); dec.add(iwu); if (this.isONE()) { return dec; } FactorAbstract ufd = FactorFactory. getImplementation(list.ring.coFac); for (int i = list.ring.nvar - 1; i >= 0; i--) { List> part = new ArrayList>(); for (IdealWithUniv id : dec) { //System.out.println("id.ideal = " + id.ideal); GenPolynomial u = id.ideal.constructUnivariate(i); SortedMap, Long> facs = ufd.baseFactors(u); if (facs.size() == 0 || (facs.size() == 1 && facs.get(facs.firstKey()) == 1L)) { List> iup = new ArrayList>(); iup.addAll(id.upolys); iup.add(u); IdealWithUniv Ipu = new IdealWithUniv(id.ideal, iup); part.add(Ipu); continue; // irreducible } if (debug) { logger.info("irreducible facs = " + facs); } GenPolynomialRing mfac = id.ideal.list.ring; int j = mfac.nvar - 1 - i; for (GenPolynomial p : facs.keySet()) { // make p multivariate GenPolynomial pm = p.extendUnivariate(mfac, j); // mfac.parse( p.toString() ); //System.out.println("pm = " + pm); Ideal Ip = id.ideal.sum(pm); List> iup = new ArrayList>(); iup.addAll(id.upolys); iup.add(p); IdealWithUniv Ipu = new IdealWithUniv(Ip, iup); part.add(Ipu); } } dec = part; //part = new ArrayList>(); } return dec; } /** * Zero dimensional ideal irreducible decompostition extension. One step * decomposition via a minimal univariate polynomial in the lowest variable, * used after each normalPosition step. * @param upol list of univariate polynomials * @param og list of other generators for the ideal * @return intersection of ideals G_i with ideal(this) subseteq cap_i( * ideal(G_i) ) and all minimal univariate polynomials of all G_i * are irreducible */ public List> zeroDimDecompositionExtension(List> upol, List> og) { if (upol == null || upol.size() + 1 != list.ring.nvar) { throw new IllegalArgumentException("univariate polynomial list not correct " + upol); } List> dec = new ArrayList>(); if (this.isZERO()) { return dec; } IdealWithUniv iwu = new IdealWithUniv(this, upol); if (this.isONE()) { dec.add(iwu); return dec; } FactorAbstract ufd = FactorFactory. getImplementation(list.ring.coFac); int i = list.ring.nvar - 1; //IdealWithUniv id = new IdealWithUniv(this,upol); GenPolynomial u = this.constructUnivariate(i); SortedMap, Long> facs = ufd.baseFactors(u); if (facs.size() == 1 && facs.get(facs.firstKey()) == 1L) { List> iup = new ArrayList>(); iup.add(u); // new polynomial first iup.addAll(upol); IdealWithUniv Ipu = new IdealWithUniv(this, iup, og); dec.add(Ipu); return dec; } if (true) { logger.info("irreducible facs = " + facs); } GenPolynomialRing mfac = list.ring; int j = mfac.nvar - 1 - i; for (GenPolynomial p : facs.keySet()) { // make p multivariate GenPolynomial pm = p.extendUnivariate(mfac, j); //System.out.println("pm = " + pm); Ideal Ip = this.sum(pm); List> iup = new ArrayList>(); iup.add(p); // new polynomial first iup.addAll(upol); IdealWithUniv Ipu = new IdealWithUniv(Ip, iup, og); dec.add(Ipu); } return dec; } /** * Test for zero dimensional ideal decompostition. * @param L intersection of ideals G_i with ideal(G) subseteq cap_i( * ideal(G_i) ) and all minimal univariate polynomials of all G_i * are irreducible * @return true if L is a zero dimensional irreducible decomposition of * this, else false */ public boolean isZeroDimDecomposition(List> L) { if (L == null || L.size() == 0) { if (this.isZERO()) { return true; } return false; } // add lower variables if L contains ideals from field extensions GenPolynomialRing ofac = list.ring; int r = ofac.nvar; int rp = L.get(0).ideal.list.ring.nvar; int d = rp - r; //System.out.println("d = " + d); Ideal Id = this; if (d > 0) { GenPolynomialRing nfac = ofac.extendLower(d); //System.out.println("nfac = " + nfac); List> elist = new ArrayList>(list.list.size()); for (GenPolynomial p : getList()) { //System.out.println("p = " + p); GenPolynomial q = p.extendLower(nfac, 0, 0L); //System.out.println("q = " + q); elist.add(q); } Id = new Ideal(nfac, elist, isGB, isTopt); } // test if this is contained in the intersection for (IdealWithUniv I : L) { boolean t = I.ideal.contains(Id); if (!t) { System.out.println("not contained " + this + " in " + I.ideal); return false; } } // test if all univariate polynomials are contained in the respective ideal //List> upprod = new ArrayList>(rp); for (IdealWithUniv I : L) { GenPolynomialRing mfac = I.ideal.list.ring; int i = 0; for (GenPolynomial p : I.upolys) { GenPolynomial pm = p.extendUnivariate(mfac, i++); //System.out.println("pm = " + pm + ", p = " + p); boolean t = I.ideal.contains(pm); if (!t) { System.out.println("not contained " + pm + " in " + I.ideal); return false; } } } return true; } /** * Compute normal position for variables i and j. * @param i first variable index * @param j second variable index * @param og other generators for the ideal * @return this + (z - x_j - t x_i) in the ring C[z, x_1, ..., x_r] */ public IdealWithUniv normalPositionFor(int i, int j, List> og) { // extend variables by one GenPolynomialRing ofac = list.ring; if (ofac.tord.getEvord() != TermOrder.INVLEX) { throw new IllegalArgumentException("invalid term order for normalPosition " + ofac.tord); } if (ofac.characteristic().signum() == 0) { return normalPositionForChar0(i, j, og); } return normalPositionForCharP(i, j, og); } /** * Compute normal position for variables i and j, characteristic zero. * @param i first variable index * @param j second variable index * @param og other generators for the ideal * @return this + (z - x_j - t x_i) in the ring C[z, x_1, ..., x_r] */ IdealWithUniv normalPositionForChar0(int i, int j, List> og) { // extend variables by one GenPolynomialRing ofac = list.ring; GenPolynomialRing nfac = ofac.extendLower(1); List> elist = new ArrayList>(list.list.size() + 1); for (GenPolynomial p : getList()) { GenPolynomial q = p.extendLower(nfac, 0, 0L); //System.out.println("q = " + q); elist.add(q); } List> ogen = new ArrayList>(); if (og != null && og.size() > 0) { for (GenPolynomial p : og) { GenPolynomial q = p.extendLower(nfac, 0, 0L); //System.out.println("q = " + q); ogen.add(q); } } Ideal I = new Ideal(nfac, elist, true); //System.out.println("I = " + I); int ip = list.ring.nvar - 1 - i; int jp = list.ring.nvar - 1 - j; GenPolynomial xi = nfac.univariate(ip); GenPolynomial xj = nfac.univariate(jp); GenPolynomial z = nfac.univariate(nfac.nvar - 1); // compute GBs until value of t is OK Ideal Ip; GenPolynomial zp; int t = 0; do { t--; // zp = z - ( xj - xi * t ) zp = z.subtract(xj.subtract(xi.multiply(nfac.fromInteger(t)))); zp = zp.monic(); Ip = I.sum(zp); //System.out.println("Ip = " + Ip); if (-t % 5 == 0) { logger.info("normal position, t = " + t); } } while (!Ip.isNormalPositionFor(i + 1, j + 1)); if (debug) { logger.info("normal position = " + Ip); } ogen.add(zp); IdealWithUniv Ips = new IdealWithUniv(Ip, null, ogen); return Ips; } /** * Compute normal position for variables i and j, positive characteristic. * @param i first variable index * @param j second variable index * @param og other generators for the ideal * @return this + (z - x_j - t x_i) in the ring C[z, x_1, ..., x_r] */ @SuppressWarnings("unchecked") IdealWithUniv normalPositionForCharP(int i, int j, List> og) { // extend variables by one GenPolynomialRing ofac = list.ring; GenPolynomialRing nfac = ofac.extendLower(1); List> elist = new ArrayList>(list.list.size() + 1); for (GenPolynomial p : getList()) { GenPolynomial q = p.extendLower(nfac, 0, 0L); //System.out.println("q = " + q); elist.add(q); } List> ogen = new ArrayList>(); if (og != null && og.size() > 0) { for (GenPolynomial p : og) { GenPolynomial q = p.extendLower(nfac, 0, 0L); //System.out.println("q = " + q); ogen.add(q); } } Ideal I = new Ideal(nfac, elist, true); //System.out.println("I = " + I); int ip = list.ring.nvar - 1 - i; int jp = list.ring.nvar - 1 - j; GenPolynomial xi = nfac.univariate(ip); GenPolynomial xj = nfac.univariate(jp); GenPolynomial z = nfac.univariate(nfac.nvar - 1); // compute GBs until value of t is OK Ideal Ip; GenPolynomial zp; AlgebraicNumberRing afac = null; Iterator> aiter = null; //String obr = ""; //String cbr = ""; int t = 0; do { t--; // zp = z - ( xj - xi * t ) GenPolynomial tn; if (afac == null) { tn = nfac.fromInteger(t); if (tn.isZERO()) { RingFactory fac = nfac.coFac; //int braces = 2; while (!(fac instanceof AlgebraicNumberRing)) { if (fac instanceof GenPolynomialRing) { GenPolynomialRing pfac = (GenPolynomialRing) (Object) fac; fac = pfac.coFac; } else if (fac instanceof QuotientRing) { QuotientRing pfac = (QuotientRing) (Object) fac; fac = pfac.ring.coFac; } else { throw new ArithmeticException( "field elements exhausted, need algebraic extension of base ring"); } //braces++; } //for (int ii = 0; ii < braces; ii++) { // obr += "{ "; // cbr += " }"; //} afac = (AlgebraicNumberRing) (Object) fac; logger.info("afac = " + afac.toScript()); aiter = afac.iterator(); AlgebraicNumber an = aiter.next(); for (int kk = 0; kk < afac.characteristic().intValue(); kk++) { an = aiter.next(); } //System.out.println("an,iter = " + an); //tn = nfac.parse(obr + an.toString() + cbr); tn = nfac.parse(an.toString()); //System.out.println("tn = " + tn); //if (false) { // throw new RuntimeException("probe"); //} } } else { if (!aiter.hasNext()) { throw new ArithmeticException( "field elements exhausted, normal position not reachable: !aiter.hasNext(): " + t); } AlgebraicNumber an = aiter.next(); //System.out.println("an,iter = " + an); //tn = nfac.parse(obr + an.toString() + cbr); tn = nfac.parse(an.toString()); //System.out.println("tn = " + tn); } if (tn.isZERO()) { throw new ArithmeticException( "field elements exhausted, normal position not reachable: tn == 0: " + t); } zp = z.subtract(xj.subtract(xi.multiply(tn))); zp = zp.monic(); Ip = I.sum(zp); //System.out.println("Ip = " + Ip); if (-t % 4 == 0) { logger.info("normal position, t = " + t); logger.info("normal position, GB = " + Ip); if (t < -550) { throw new ArithmeticException("normal position not reached in " + t + " steps"); } } } while (!Ip.isNormalPositionFor(i + 1, j + 1)); if (debug) { logger.info("normal position = " + Ip); } ogen.add(zp); IdealWithUniv Ips = new IdealWithUniv(Ip, null, ogen); return Ips; } /** * Test if this ideal is in normal position for variables i and j. * @param i first variable index * @param j second variable index * @return true if this is in normal position with respect to i and j */ public boolean isNormalPositionFor(int i, int j) { // called in extended ring! int ip = list.ring.nvar - 1 - i; int jp = list.ring.nvar - 1 - j; boolean iOK = false; boolean jOK = false; for (GenPolynomial p : getList()) { ExpVector e = p.leadingExpVector(); int[] dov = e.dependencyOnVariables(); //System.out.println("dov = " + Arrays.toString(dov)); if (dov.length == 0) { throw new IllegalArgumentException("ideal dimension is not zero"); } if (dov[0] == ip) { if (e.totalDeg() != 1) { return false; } iOK = true; } else if (dov[0] == jp) { if (e.totalDeg() != 1) { return false; } jOK = true; } if (iOK && jOK) { return true; } } return iOK && jOK; } /** * Normal position index, separate for polynomials with more than 2 * variables. See also mas.masring.DIPDEC0#DIGISR * @return (i,j) for non-normal variables */ public int[] normalPositionIndex2Vars() { int[] np = null; int i = -1; int j = -1; for (GenPolynomial p : getList()) { ExpVector e = p.leadingExpVector(); int[] dov = e.dependencyOnVariables(); //System.out.println("dov_head = " + Arrays.toString(dov)); if (dov.length == 0) { throw new IllegalArgumentException("ideal dimension is not zero " + p); } // search bi-variate head terms if (dov.length >= 2) { i = dov[0]; j = dov[1]; break; } int n = dov[0]; GenPolynomial q = p.reductum(); e = q.degreeVector(); dov = e.dependencyOnVariables(); //System.out.println("dov_red = " + Arrays.toString(dov)); int k = Arrays.binarySearch(dov, n); int len = 2; if (k >= 0) { len = 3; } // search bi-variate reductas if (dov.length >= len) { switch (k) { case 0: i = dov[1]; j = dov[2]; break; case 1: i = dov[0]; j = dov[2]; break; case 2: i = dov[0]; j = dov[1]; break; default: i = dov[0]; j = dov[1]; break; } break; } } if (i < 0 || j < 0) { return np; } // adjust index i = list.ring.nvar - 1 - i; j = list.ring.nvar - 1 - j; np = new int[] { j, i }; // reverse logger.info("normalPositionIndex2Vars, np = " + Arrays.toString(np)); return np; } /** * Normal position index, separate multiple univariate polynomials. See also * * mas.masring.DIPDEC0#DIGISM * @return (i,j) for non-normal variables */ public int[] normalPositionIndexUnivars() { int[] np = null; //new int[] { -1, -1 }; int i = -1; int j = -1; // search multiple univariate polynomials with degree >= 2 for (GenPolynomial p : getList()) { ExpVector e = p.degreeVector(); int[] dov = e.dependencyOnVariables(); long t = e.totalDeg(); // lt(p) would be enough //System.out.println("dov_univ = " + Arrays.toString(dov) + ", e = " + e); if (dov.length == 0) { throw new IllegalArgumentException("ideal dimension is not zero"); } if (dov.length == 1 && t >= 2L) { if (i == -1) { i = dov[0]; } else if (j == -1) { j = dov[0]; if (i > j) { int x = i; i = j; j = x; } } } if (i >= 0 && j >= 0) { break; } } if (i < 0 || j < 0) { // search polynomials with univariate head term and degree >= 2 for (GenPolynomial p : getList()) { ExpVector e = p.leadingExpVector(); long t = e.totalDeg(); if (t >= 2) { e = p.degreeVector(); int[] dov = e.dependencyOnVariables(); //System.out.println("dov_univ2 = " + Arrays.toString(dov) + " e = " + e); if (dov.length == 0) { throw new IllegalArgumentException("ideal dimension is not zero"); } if (dov.length >= 2) { i = dov[0]; j = dov[1]; } } if (i >= 0 && j >= 0) { break; } } } if (i < 0 || j < 0) { return np; } // adjust index i = list.ring.nvar - 1 - i; j = list.ring.nvar - 1 - j; np = new int[] { j, i }; // reverse logger.info("normalPositionIndexUnivars, np = " + Arrays.toString(np)); return np; } /** * Zero dimensional ideal decompostition for real roots. See algorithm * mas.masring.DIPDEC0#DINTSR. * @return intersection of ideals G_i with ideal(this) subseteq cap_i( * ideal(G_i) ) and each G_i contains at most bi-variate polynomials * and all univariate minimal polynomials are irreducible */ public List> zeroDimRootDecomposition() { List> dec = zeroDimDecomposition(); if (this.isZERO()) { return dec; } if (this.isONE()) { return dec; } List> rdec = new ArrayList>(); while (dec.size() > 0) { IdealWithUniv id = dec.remove(0); int[] ri = id.ideal.normalPositionIndex2Vars(); if (ri == null || ri.length != 2) { rdec.add(id); } else { IdealWithUniv I = id.ideal.normalPositionFor(ri[0], ri[1], id.others); List> rd = I.ideal.zeroDimDecompositionExtension(id.upolys, I.others); //System.out.println("r_rd = " + rd); dec.addAll(rd); } } return rdec; } /** * Zero dimensional ideal prime decompostition. See algorithm * mas.masring.DIPDEC0#DINTSS. * @return intersection of ideals G_i with ideal(this) subseteq cap_i( * ideal(G_i) ) and each G_i is a prime ideal */ public List> zeroDimPrimeDecomposition() { List> pdec = zeroDimPrimeDecompositionFE(); List> dec = new ArrayList>(); if (pdec.size() == 1) { // already prime IdealWithUniv Ip = pdec.get(0); int s = Ip.upolys.size() - getRing().nvar; // skip field ext univariate polys List> upol = Ip.upolys.subList(s, Ip.upolys.size()); Ip = new IdealWithUniv(this, upol); dec.add(Ip); return dec; } for (IdealWithUniv Ip : pdec) { if (Ip.ideal.getRing().nvar == getRing().nvar) { // no field extension dec.add(Ip); } else { // remove field extension // add other generators for performance Ideal Id = Ip.ideal; if (Ip.others != null) { //System.out.println("adding Ip.others = " + Ip.others); List> pp = new ArrayList>(); pp.addAll(Id.getList()); pp.addAll(Ip.others); Id = new Ideal(Id.getRing(), pp); } Ideal Is = Id.eliminate(getRing()); //System.out.println("Is = " + Is); int s = Ip.upolys.size() - getRing().nvar; // skip field ext univariate polys List> upol = Ip.upolys.subList(s, Ip.upolys.size()); IdealWithUniv Iu = new IdealWithUniv(Is, upol); //,Ip.others); used above and must be ignored here dec.add(Iu); } } return dec; } /** * Zero dimensional ideal prime decompostition, with field extension. See * algorithm mas.masring.DIPDEC0#DINTSS. * @return intersection of ideals G_i with ideal(this) subseteq cap_i( * ideal(G_i) ) and each G_i is a prime ideal with eventually * containing field extension variables */ public List> zeroDimPrimeDecompositionFE() { List> dec = zeroDimRootDecomposition(); if (this.isZERO()) { return dec; } if (this.isONE()) { return dec; } List> rdec = new ArrayList>(); while (dec.size() > 0) { IdealWithUniv id = dec.remove(0); int[] ri = id.ideal.normalPositionIndexUnivars(); if (ri == null || ri.length != 2) { rdec.add(id); } else { IdealWithUniv I = id.ideal.normalPositionFor(ri[0], ri[1], id.others); List> rd = I.ideal.zeroDimDecompositionExtension(id.upolys, I.others); //System.out.println("rd = " + rd); dec.addAll(rd); } } return rdec; } /** * Zero dimensional ideal associated primary ideal. See algorithm * mas.masring.DIPIDEAL#DIRLPI. * @param P prime ideal associated to this * @return primary ideal of this with respect to the associated pime ideal P */ public Ideal primaryIdeal(Ideal P) { Ideal Qs = P; Ideal Q; int e = 0; do { Q = Qs; e++; Qs = Q.product(P); } while (Qs.contains(this)); boolean t; Ideal As; do { As = this.sum(Qs); t = As.contains(Q); if (!t) { Q = Qs; e++; Qs = Q.product(P); } } while (!t); logger.info("exponent = " + e); return As; } /** * Zero dimensional ideal primary decompostition. * @return list of primary components of primary ideals G_i (pairwise * co-prime) with ideal(this) = cap_i( ideal(G_i) ) together with * the associated primes */ public List> zeroDimPrimaryDecomposition() { List> pdec = zeroDimPrimeDecomposition(); if (logger.isInfoEnabled()) { logger.info("prim decomp = " + pdec); } return zeroDimPrimaryDecomposition(pdec); } /** * Zero dimensional ideal elimination to original ring. * @param pdec list of prime ideals G_i * @return intersection of pairwise co-prime prime ideals G_i in the ring of * this with ideal(this) = cap_i( ideal(G_i) ) */ public List> zeroDimElimination(List> pdec) { List> dec = new ArrayList>(); if (this.isZERO()) { return dec; } if (this.isONE()) { dec.add(pdec.get(0)); return dec; } List> qdec = new ArrayList>(); for (IdealWithUniv Ip : pdec) { //System.out.println("Ip = " + Ip); List> epol = new ArrayList>(); epol.addAll(Ip.ideal.getList()); GenPolynomialRing mfac = Ip.ideal.list.ring; int j = 0; // add univariate polynomials for performance for (GenPolynomial p : Ip.upolys) { GenPolynomial pm = p.extendUnivariate(mfac, j++); if (j != 1) { // skip double epol.add(pm); } } // add other generators for performance if (Ip.others != null) { epol.addAll(Ip.others); } Ideal Ipp = new Ideal(mfac, epol); // logger.info("eliminate_1 = " + Ipp); TermOrder to = null; if (mfac.tord.getEvord() != TermOrder.IGRLEX) { List> epols = new ArrayList>(); to = new TermOrder(TermOrder.IGRLEX); GenPolynomialRing smfac = new GenPolynomialRing(mfac.coFac, mfac.nvar, to, mfac.getVars()); for (GenPolynomial p : epol) { GenPolynomial pm = smfac.copy(p); epols.add(pm.monic()); } //epol = epols; Ipp = new Ideal(smfac, epols); } epol = red.irreducibleSet(Ipp.getList()); Ipp = new Ideal(Ipp.getRing(), epol); if (logger.isInfoEnabled()) { logger.info("eliminate = " + Ipp); } Ideal Is = Ipp.eliminate(list.ring); //System.out.println("Is = " + Is); if (to != null && !Is.list.ring.equals(list.ring)) { List> epols = new ArrayList>(); for (GenPolynomial p : Is.getList()) { GenPolynomial pm = list.ring.copy(p); epols.add(pm); } Is = new Ideal(list.ring, epols); //System.out.println("Is = " + Is); } int k = Ip.upolys.size() - list.ring.nvar; List> up = new ArrayList>(); for (int i = 0; i < list.ring.nvar; i++) { up.add(Ip.upolys.get(i + k)); } IdealWithUniv Ie = new IdealWithUniv(Is, up); qdec.add(Ie); } return qdec; } /** * Zero dimensional ideal primary decompostition. * @param pdec list of prime ideals G_i with no field extensions * @return list of primary components of primary ideals G_i (pairwise * co-prime) with ideal(this) = cap_i( ideal(G_i) ) together with * the associated primes */ public List> zeroDimPrimaryDecomposition(List> pdec) { List> dec = new ArrayList>(); if (this.isZERO()) { return dec; } if (this.isONE()) { PrimaryComponent pc = new PrimaryComponent(pdec.get(0).ideal, pdec.get(0)); dec.add(pc); return dec; } for (IdealWithUniv Ip : pdec) { Ideal Qs = this.primaryIdeal(Ip.ideal); PrimaryComponent pc = new PrimaryComponent(Qs, Ip); dec.add(pc); } return dec; } /** * Test for primary ideal decompostition. * @param L list of primary components G_i * @return true if ideal(this) == cap_i( ideal(G_i) ) */ public boolean isPrimaryDecomposition(List> L) { // test if this is contained in the intersection for (PrimaryComponent I : L) { boolean t = I.primary.contains(this); if (!t) { System.out.println("not contained " + this + " in " + I); return false; } } Ideal isec = null; for (PrimaryComponent I : L) { if (isec == null) { isec = I.primary; } else { isec = isec.intersect(I.primary); } } return this.contains(isec); } /** * Ideal extension. * @param vars list of variables for a polynomial ring for extension * @return ideal G, with coefficients in * QuotientRing(GenPolynomialRing(vars)) */ public IdealWithUniv> extension(String... vars) { GenPolynomialRing fac = getRing(); GenPolynomialRing efac = new GenPolynomialRing(fac.coFac, vars.length, fac.tord, vars); IdealWithUniv> ext = extension(efac); return ext; } /** * Ideal extension. * @param efac polynomial ring for extension * @return ideal G, with coefficients in QuotientRing(efac) */ public IdealWithUniv> extension(GenPolynomialRing efac) { QuotientRing qfac = new QuotientRing(efac); IdealWithUniv> ext = extension(qfac); return ext; } /** * Ideal extension. * @param qfac quotient polynomial ring for extension * @return ideal G, with coefficients in qfac */ public IdealWithUniv> extension(QuotientRing qfac) { GenPolynomialRing fac = getRing(); GenPolynomialRing efac = qfac.ring; String[] rvars = GroebnerBasePartial.remainingVars(fac.getVars(), efac.getVars()); //System.out.println("rvars = " + Arrays.toString(rvars)); GroebnerBasePartial bbp = new GroebnerBasePartial(); //wrong: OptimizedPolynomialList pgb = bbp.partialGB(getList(),rvars); OptimizedPolynomialList pgb = bbp.elimPartialGB(getList(), rvars, efac.getVars()); if (logger.isInfoEnabled()) { logger.info("rvars = " + Arrays.toString(rvars)); logger.info("partialGB = " + pgb); } GenPolynomialRing> rfac = new GenPolynomialRing>(efac, rvars.length, fac.tord, rvars); List> plist = pgb.list; List>> rpgb = PolyUtil. recursive(rfac, plist); //System.out.println("rfac = " + rfac); GenPolynomialRing> qpfac = new GenPolynomialRing>(qfac, rfac); List>> qpgb = PolyUfdUtil. quotientFromIntegralCoefficients(qpfac, rpgb); //System.out.println("qpfac = " + qpfac); // compute f GreatestCommonDivisor ufd = GCDFactory.getImplementation(fac.coFac); GenPolynomial f = null; // qfac.ring.getONE(); for (GenPolynomial> p : rpgb) { if (f == null) { f = p.leadingBaseCoefficient(); } else { f = ufd.lcm(f, p.leadingBaseCoefficient()); } } //SquarefreeAbstract sqf = SquarefreeFactory.getImplementation(fac.coFac); //not required: f = sqf.squarefreePart(f); GenPolynomial> fp = rfac.getONE().multiply(f); GenPolynomial> fq = PolyUfdUtil. quotientFromIntegralCoefficients(qpfac, fp); if (logger.isInfoEnabled()) { logger.info("extension f = " + f); logger.info("ext = " + qpgb); } List>> upols = new ArrayList>>(0); List>> opols = new ArrayList>>(1); opols.add(fq); qpgb = PolyUtil.> monic(qpgb); Ideal> ext = new Ideal>(qpfac, qpgb); IdealWithUniv> extu = new IdealWithUniv>(ext, upols, opols); return extu; } /** * Ideal contraction and permutation. * @param eideal extension ideal of this. * @return contraction ideal of eideal in this polynomial ring */ public IdealWithUniv permContraction(IdealWithUniv> eideal) { return Ideal. permutation(getRing(), Ideal. contraction(eideal)); } /** * Ideal contraction. * @param eid extension ideal of this. * @return contraction ideal of eid in distributed polynomial ring */ public static > IdealWithUniv contraction(IdealWithUniv> eid) { Ideal> eideal = eid.ideal; List>> qgb = eideal.getList(); QuotientRing qfac = (QuotientRing) eideal.getRing().coFac; GenPolynomialRing> rfac = new GenPolynomialRing>(qfac.ring, eideal.getRing()); GenPolynomialRing dfac = qfac.ring.extend(eideal.getRing().getVars()); TermOrder to = new TermOrder(qfac.ring.tord.getEvord()); dfac = new GenPolynomialRing(dfac.coFac, dfac.nvar, to, dfac.getVars()); //System.out.println("qfac = " + qfac); //System.out.println("rfac = " + rfac); //System.out.println("dfac = " + dfac); // convert polynomials List>> cgb = PolyUfdUtil. integralFromQuotientCoefficients(rfac, qgb); List> dgb = PolyUtil. distribute(dfac, cgb); Ideal cont = new Ideal(dfac, dgb); // convert other polynomials List> opols = new ArrayList>(); if (eid.others != null && eid.others.size() > 0) { List>> orpol = PolyUfdUtil. integralFromQuotientCoefficients( rfac, eid.others); List> opol = PolyUtil. distribute(dfac, orpol); opols.addAll(opol); } // convert univariate polynomials List> upols = new ArrayList>(0); int i = 0; for (GenPolynomial> p : eid.upolys) { GenPolynomial> pm = p.extendUnivariate(eideal.getRing(), i++); //System.out.println("pm = " + pm + ", p = " + p); GenPolynomial> urpol = PolyUfdUtil . integralFromQuotientCoefficients(rfac, pm); GenPolynomial upol = PolyUtil. distribute(dfac, urpol); upols.add(upol); //System.out.println("upol = " + upol); } // compute f GreatestCommonDivisor ufd = GCDFactory.getImplementation(qfac.ring.coFac); GenPolynomial f = null; // qfac.ring.getONE(); for (GenPolynomial> p : cgb) { if (f == null) { f = p.leadingBaseCoefficient(); } else { f = ufd.lcm(f, p.leadingBaseCoefficient()); } } GenPolynomial> fp = rfac.getONE().multiply(f); f = PolyUtil. distribute(dfac, fp); if (logger.isInfoEnabled()) { logger.info("contraction f = " + f); logger.info("cont = " + cont); } opols.add(f); if (f.isONE()) { IdealWithUniv cf = new IdealWithUniv(cont, upols, opols); return cf; } // compute ideal quotient by f Ideal Q = cont.infiniteQuotientRab(f); IdealWithUniv Qu = new IdealWithUniv(Q, upols, opols); return Qu; } /** * Ideal permutation. * @param oring polynomial ring to which variables are back permuted. * @param Cont ideal to be permuted * @return permutation of cont in polynomial ring oring */ public static > IdealWithUniv permutation(GenPolynomialRing oring, IdealWithUniv Cont) { Ideal cont = Cont.ideal; GenPolynomialRing dfac = cont.getRing(); // (back) permutation of variables String[] ovars = oring.getVars(); String[] dvars = dfac.getVars(); //System.out.println("ovars = " + Arrays.toString(ovars)); //System.out.println("dvars = " + Arrays.toString(dvars)); if (Arrays.equals(ovars, dvars)) { // nothing to do return Cont; } List perm = GroebnerBasePartial.getPermutation(dvars, ovars); //System.out.println("perm = " + perm); GenPolynomialRing pfac = TermOrderOptimization. permutation(perm, cont.getRing()); if (logger.isInfoEnabled()) { logger.info("pfac = " + pfac); } List> ppolys = TermOrderOptimization. permutation(perm, pfac, cont.getList()); //System.out.println("ppolys = " + ppolys); cont = new Ideal(pfac, ppolys); if (logger.isDebugEnabled()) { logger.info("perm cont = " + cont); } List> opolys = TermOrderOptimization. permutation(perm, pfac, Cont.others); //System.out.println("opolys = " + opolys); List> upolys = TermOrderOptimization. permutation(perm, pfac, Cont.upolys); //System.out.println("opolys = " + opolys); IdealWithUniv Cu = new IdealWithUniv(cont, upolys, opolys); return Cu; } /** * Ideal radical. * @return the radical ideal of this */ public Ideal radical() { List> rdec = radicalDecomposition(); List> dec = new ArrayList>(rdec.size()); for (IdealWithUniv ru : rdec) { dec.add(ru.ideal); } Ideal R = intersect(dec); return R; } /** * Ideal radical decompostition. * @return intersection of ideals G_i with radical(this) eq cap_i( * ideal(G_i) ) and each G_i is a radical ideal and the G_i are * pairwise co-prime */ public List> radicalDecomposition() { // check dimension int z = commonZeroTest(); List> dec = new ArrayList>(); List> ups = new ArrayList>(); // dimension -1 if (z < 0) { IdealWithUniv id = new IdealWithUniv(this, ups); dec.add(id); // see GB book return dec; } // dimension 0 if (z == 0) { dec = zeroDimRadicalDecomposition(); return dec; } // dimension > 0 if (this.isZERO()) { return dec; } if (list.ring.coFac.characteristic().signum() > 0 && !list.ring.coFac.isFinite()) { // must not be the case at this point logger.warn("must use prime decomposition for char p and infinite coefficient rings, found " + list.ring.coFac.toScript()); return primeDecomposition(); } Dimension dim = dimension(); if (logger.isInfoEnabled()) { logger.info("dimension = " + dim); } // a short maximal independent set with small variables Set> M = dim.M; Set min = null; for (Set m : M) { if (min == null) { min = m; continue; } if (m.size() < min.size()) { min = m; } } int ms = min.size(); Integer[] ia = new Integer[0]; int mx = min.toArray(ia)[ms - 1]; for (Set m : M) { if (m.size() == ms) { int mxx = m.toArray(ia)[ms - 1]; if (mxx < mx) { min = m; mx = mxx; } } } //System.out.println("min = " + min); String[] mvars = new String[min.size()]; int j = 0; for (Integer i : min) { mvars[j++] = dim.v[i]; } if (logger.isInfoEnabled()) { logger.info("extension for variables = " + Arrays.toString(mvars) + ", indexes = " + min); } // reduce to dimension zero IdealWithUniv> Ext = extension(mvars); if (logger.isInfoEnabled()) { logger.info("extension = " + Ext); } List>> edec = Ext.ideal.zeroDimRadicalDecomposition(); if (logger.isInfoEnabled()) { logger.info("0-dim radical decomp = " + edec); } // remove field extensions are not required // reconstruct dimension for (IdealWithUniv> ep : edec) { IdealWithUniv cont = permContraction(ep); //System.out.println("cont = " + cont); dec.add(cont); } IdealWithUniv extcont = permContraction(Ext); //System.out.println("extcont = " + extcont); // get f List> ql = extcont.others; if (ql.size() == 0) { // should not happen return dec; } GenPolynomial fx = ql.get(0); //System.out.println("cont(Ext) fx = " + fx + ", " + fx.ring); if (fx.isONE()) { return dec; } Ideal T = sum(fx); //System.out.println("T.rec = " + T.getList()); if (T.isONE()) { logger.info("1 in ideal for " + fx); return dec; } if (logger.isInfoEnabled()) { logger.info("radical decomp ext-cont fx = " + fx); logger.info("recursion radical decomp T = " + T); } // recursion: List> Tdec = T.radicalDecomposition(); if (logger.isInfoEnabled()) { logger.info("recursion radical decomp = " + Tdec); } dec.addAll(Tdec); return dec; } /** * Ideal irreducible decompostition. * @return intersection of ideals G_i with ideal(this) subseteq cap_i( * ideal(G_i) ) and each G_i is an ideal with irreducible univariate * polynomials (after extension to a zero dimensional ideal) and the * G_i are pairwise co-prime */ public List> decomposition() { // check dimension int z = commonZeroTest(); List> dec = new ArrayList>(); // dimension -1 if (z < 0) { //List> ups = new ArrayList>(); //IdealWithUniv id = new IdealWithUniv(this, ups); //dec.add(id); see GB book return dec; } // dimension 0 if (z == 0) { dec = zeroDimDecomposition(); return dec; } // dimension > 0 if (this.isZERO()) { return dec; } Dimension dim = dimension(); if (logger.isInfoEnabled()) { logger.info("dimension = " + dim); } // shortest maximal independent set Set> M = dim.M; Set min = null; for (Set m : M) { if (min == null) { min = m; continue; } if (m.size() < min.size()) { min = m; } } //System.out.println("min = " + min); String[] mvars = new String[min.size()]; int j = 0; for (Integer i : min) { mvars[j++] = dim.v[i]; } if (logger.isInfoEnabled()) { logger.info("extension for variables = " + Arrays.toString(mvars)); } // reduce to dimension zero IdealWithUniv> Ext = extension(mvars); if (logger.isInfoEnabled()) { logger.info("extension = " + Ext); } List>> edec = Ext.ideal.zeroDimDecomposition(); if (logger.isInfoEnabled()) { logger.info("0-dim irred decomp = " + edec); } // remove field extensions are not required // reconstruct dimension for (IdealWithUniv> ep : edec) { IdealWithUniv cont = permContraction(ep); //System.out.println("cont = " + cont); dec.add(cont); } IdealWithUniv extcont = permContraction(Ext); //System.out.println("extcont = " + extcont); // get f List> ql = extcont.others; if (ql.size() == 0) { // should not happen return dec; } GenPolynomial fx = ql.get(0); //System.out.println("cont(Ext) fx = " + fx + ", " + fx.ring); if (fx.isONE()) { return dec; } Ideal T = sum(fx); //System.out.println("T.rec = " + T.getList()); if (T.isONE()) { logger.info("1 in ideal for " + fx); return dec; } if (logger.isInfoEnabled()) { logger.info("irred decomp ext-cont fx = " + fx); logger.info("recursion irred decomp T = " + T); } // recursion: List> Tdec = T.decomposition(); if (logger.isInfoEnabled()) { logger.info("recursion irred decomposition = " + Tdec); } dec.addAll(Tdec); return dec; } /** * Ideal prime decompostition. * @return intersection of ideals G_i with ideal(this) subseteq cap_i( * ideal(G_i) ) and each G_i is a prime ideal and the G_i are * pairwise co-prime */ public List> primeDecomposition() { // check dimension int z = commonZeroTest(); List> dec = new ArrayList>(); // dimension -1 if (z < 0) { //List> ups = new ArrayList>(); //IdealWithUniv id = new IdealWithUniv(this, ups); //dec.add(id); see GB book return dec; } // dimension 0 if (z == 0) { dec = zeroDimPrimeDecomposition(); return dec; } // dimension > 0 if (this.isZERO()) { return dec; } Dimension dim = dimension(); if (logger.isInfoEnabled()) { logger.info("dimension = " + dim); } // shortest maximal independent set Set> M = dim.M; Set min = null; for (Set m : M) { if (min == null) { min = m; continue; } if (m.size() < min.size()) { min = m; } } //System.out.println("min = " + min); String[] mvars = new String[min.size()]; int j = 0; for (Integer i : min) { mvars[j++] = dim.v[i]; } if (logger.isInfoEnabled()) { logger.info("extension for variables = " + Arrays.toString(mvars)); } // reduce to dimension zero IdealWithUniv> Ext = extension(mvars); if (logger.isInfoEnabled()) { logger.info("extension = " + Ext); } List>> edec = Ext.ideal.zeroDimPrimeDecomposition(); if (logger.isInfoEnabled()) { logger.info("0-dim prime decomp = " + edec); } // remove field extensions, already done // reconstruct dimension for (IdealWithUniv> ep : edec) { IdealWithUniv cont = permContraction(ep); //System.out.println("cont = " + cont); dec.add(cont); } // get f IdealWithUniv extcont = permContraction(Ext); //System.out.println("extcont = " + extcont); List> ql = extcont.others; if (ql.size() == 0) { // should not happen return dec; } GenPolynomial fx = ql.get(0); //System.out.println("cont(Ext) fx = " + fx + ", " + fx.ring); if (fx.isONE()) { return dec; } // compute exponent not required Ideal T = sum(fx); //System.out.println("T.rec = " + T.getList()); if (T.isONE()) { logger.info("1 in ideal for " + fx); return dec; } if (logger.isInfoEnabled()) { logger.info("prime decomp ext-cont fx = " + fx); logger.info("recursion prime decomp T = " + T); } // recursion: List> Tdec = T.primeDecomposition(); if (logger.isInfoEnabled()) { logger.info("recursion prime decomp = " + Tdec); } dec.addAll(Tdec); return dec; } /** * Test for ideal decompostition. * @param L intersection of ideals G_i with ideal(G) eq cap_i(ideal(G_i) ) * @return true if L is a decomposition of this, else false */ public boolean isDecomposition(List> L) { if (L == null || L.size() == 0) { if (this.isZERO()) { return true; } return false; } GenPolynomialRing ofac = list.ring; int r = ofac.nvar; int rp = L.get(0).ideal.list.ring.nvar; int d = rp - r; //System.out.println("d = " + d); Ideal Id = this; if (d > 0) { // add lower variables GenPolynomialRing nfac = ofac.extendLower(d); //System.out.println("nfac = " + nfac); List> elist = new ArrayList>(list.list.size()); for (GenPolynomial p : getList()) { //System.out.println("p = " + p); GenPolynomial q = p.extendLower(nfac, 0, 0L); //System.out.println("q = " + q); elist.add(q); } Id = new Ideal(nfac, elist, isGB, isTopt); } // test if this is contained in the intersection for (IdealWithUniv I : L) { boolean t = I.ideal.contains(Id); if (!t) { System.out.println("not contained " + this + " in " + I.ideal); return false; } } // // test if all univariate polynomials are contained in the respective ideal // for (IdealWithUniv I : L) { // GenPolynomialRing mfac = I.ideal.list.ring; // int i = 0; // for (GenPolynomial p : I.upolys) { // GenPolynomial pm = p.extendUnivariate(mfac, i++); // //System.out.println("pm = " + pm + ", p = " + p); // boolean t = I.ideal.contains(pm); // if (!t) { // System.out.println("not contained " + pm + " in " + I.ideal); // return false; // } // } // } return true; } /** * Ideal primary decompostition. * @return list of primary components of primary ideals G_i (pairwise * co-prime) with ideal(this) = cap_i( ideal(G_i) ) together with * the associated primes */ public List> primaryDecomposition() { // check dimension int z = commonZeroTest(); List> dec = new ArrayList>(); // dimension -1 if (z < 0) { //List> ups = new ArrayList>(); //IdealWithUniv id = new IdealWithUniv(this, ups); //PrimaryComponent pc = new PrimaryComponent(this, id); //dec.add(pc); see GB book return dec; } // dimension 0 if (z == 0) { dec = zeroDimPrimaryDecomposition(); return dec; } // dimension > 0 if (this.isZERO()) { return dec; } Dimension dim = dimension(); if (logger.isInfoEnabled()) { logger.info("dimension = " + dim); } // shortest maximal independent set Set> M = dim.M; Set min = null; for (Set m : M) { if (min == null) { min = m; continue; } if (m.size() < min.size()) { min = m; } } //System.out.println("min = " + min); String[] mvars = new String[min.size()]; int j = 0; for (Integer i : min) { mvars[j++] = dim.v[i]; } if (logger.isInfoEnabled()) { logger.info("extension for variables = " + Arrays.toString(mvars)); } // reduce to dimension zero IdealWithUniv> Ext = extension(mvars); if (logger.isInfoEnabled()) { logger.info("extension = " + Ext); } List>> edec = Ext.ideal.zeroDimPrimaryDecomposition(); if (logger.isInfoEnabled()) { logger.info("0-dim primary decomp = " + edec); } // remove field extensions, already done // reconstruct dimension List>> upq = new ArrayList>>(); for (PrimaryComponent> ep : edec) { IdealWithUniv> epu = new IdealWithUniv>(ep.primary, upq); IdealWithUniv contq = permContraction(epu); IdealWithUniv contp = permContraction(ep.prime); PrimaryComponent pc = new PrimaryComponent(contq.ideal, contp); //System.out.println("pc = " + pc); dec.add(pc); } // get f IdealWithUniv extcont = permContraction(Ext); if (debug) { logger.info("cont(Ext) = " + extcont); } List> ql = extcont.others; if (ql.size() == 0) { // should not happen return dec; } GenPolynomial fx = ql.get(0); //System.out.println("cont(Ext) fx = " + fx + ", " + fx.ring); if (fx.isONE()) { return dec; } // compute exponent int s = this.infiniteQuotientExponent(fx, extcont.ideal); if (s == 0) { logger.info("exponent is 0 "); return dec; } if (s > 1) { fx = Power.> positivePower(fx, s); } if (debug) { logger.info("exponent fx = " + s + ", fx^s = " + fx); } Ideal T = sum(fx); //System.out.println("T.rec = " + T.getList()); if (T.isONE()) { logger.info("1 in ideal for " + fx); return dec; } if (logger.isInfoEnabled()) { logger.info("primmary decomp ext-cont fx = " + fx); logger.info("recursion primary decomp T = " + T); } // recursion: List> Tdec = T.primaryDecomposition(); if (logger.isInfoEnabled()) { logger.info("recursion primary decomp = " + Tdec); } dec.addAll(Tdec); return dec; } } jas-2.5/src/edu/jas/application/ColoredSystem.java0000644000175000017500000002417012014234362022427 0ustar giovannigiovanni/* * $Id: ColoredSystem.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Container for a condition, a corresponding colored polynomial list and a * Groebner base pair list. * @param coefficient type */ public class ColoredSystem> { private static final Logger logger = Logger.getLogger(ColoredSystem.class); private final boolean debug = logger.isDebugEnabled(); /** * Condition determinig this colored system. */ public final Condition condition; /** * Colored polynomials of this system. */ public final List> list; /** * Groebner base pair list of this system. */ public final OrderedCPairlist pairlist; /** * Constructor for a colored polynomial system. * @param cond a condition. * @param S a list of colored polynomials. */ public ColoredSystem(Condition cond, List> S) { this(cond, S, null); } /** * Constructor for a colored polynomial system. * @param cond a condition. * @param S a list of colored polynomials. * @param pl a ordered pair list. */ public ColoredSystem(Condition cond, List> S, OrderedCPairlist pl) { this.condition = cond; this.list = S; this.pairlist = pl; } /** * Copy this colored polynomial system. * @return a clone of this. */ public ColoredSystem copy() { return new ColoredSystem(condition, list, pairlist.copy()); } /** * Add to list of colored systems. This is added to the list of colored * systems, if a system with the same condition is not already contained. * @param L a list of colored systems. * @return L.add(this) if this not in L, else L. */ public List> addToList(List> L) { List> S = new ArrayList>(L.size() + 1); boolean contained = false; for (ColoredSystem x : L) { if (condition.equals(x.condition) && list.equals(x.list)) { logger.info("replaced system = " + x.condition); S.add(this); contained = true; } else { // copy existing // System.out.println("kept system = " + x); S.add(x); } } if (!contained) { S.add(this); } return S; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer("ColoredSystem: \n"); if (list.size() > 0) { s.append("polynomial ring : " + list.get(0).green.ring + "\n"); } else { s.append("parameter polynomial ring : " + condition.zero.getRing() + "\n"); } s.append("conditions == 0 : " + getConditionZero() + "\n"); s.append("conditions != 0 : " + getConditionNonZero() + "\n"); if (debug) { s.append("green coefficients:\n" + getGreenCoefficients() + "\n"); s.append("red coefficients:\n" + getRedCoefficients() + "\n"); } s.append("colored polynomials:\n" + list + "\n"); s.append("uncolored polynomials:\n" + getPolynomialList() + "\n"); if (debug) { s.append("essential polynomials:\n" + getEssentialPolynomialList() + "\n"); } if (pairlist != null) { s.append(pairlist.toString() + "\n"); } return s.toString(); } /** * Is this colored system equal to other. * @param c other colored system. * @return true, if this is equal to other, else false. */ @Override @SuppressWarnings("unchecked") public boolean equals(Object c) { ColoredSystem cs = null; try { cs = (ColoredSystem) c; } catch (ClassCastException e) { return false; } if (cs == null) { return false; } boolean t = (condition.equals(cs.condition) && list.equals(cs.list)); if (!t) { return t; } // now t == true t = pairlist.equals(cs.pairlist); if (!t) { System.out.println("pairlists not equal " + pairlist + ", " + cs.pairlist); } return true; // if lists are equal ignore pairlists } /** * Hash code for this colored system. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = condition.hashCode(); h = h << 17; h += list.hashCode(); // h = h << 11; // h += pairlist.hashCode(); return h; } /** * Get zero condition. * @return condition.zero. */ public List> getConditionZero() { return condition.zero.getList(); } /** * Get non zero condition. * @return condition.nonZero. */ public List> getConditionNonZero() { return condition.nonZero.mset; } /** * Get list of red coefficients of polynomials. * @return list of all red coefficients of polynomials. */ public List> getRedCoefficients() { Set> F = new HashSet>(); for (ColorPolynomial s : list) { F.addAll(s.red.getMap().values()); } List> M = new ArrayList>(F); return M; } /** * Get list of green coefficients of polynomials. * @return list of all green coefficients of polynomials. */ public List> getGreenCoefficients() { Set> F = new HashSet>(); for (ColorPolynomial s : list) { F.addAll(s.green.getMap().values()); } List> M = new ArrayList>(F); return M; } /** * Get list of full polynomials. * @return list of all full polynomials. */ public List>> getPolynomialList() { List>> F = new ArrayList>>(); for (ColorPolynomial s : list) { F.add(s.getPolynomial()); } return F; } /** * Get list of essential polynomials. * @return list of all essential polynomials. */ public List>> getEssentialPolynomialList() { List>> F = new ArrayList>>(); for (ColorPolynomial s : list) { F.add(s.getEssentialPolynomial()); } return F; } /** * Check invariants. Check if all polynomials are determined and if the * color of all coefficients is correct with respect to the condition. * @return true, if all invariants are met, else false. */ public boolean checkInvariant() { if (!isDetermined()) { return false; } if (!condition.isDetermined(list)) { return false; } // Condition cond = condition; for (ColorPolynomial s : list) { if (!s.checkInvariant()) { System.out.println("notInvariant " + s); System.out.println("condition: " + condition); return false; } for (GenPolynomial g : s.green.getMap().values()) { if (condition.color(g) != Condition.Color.GREEN) { System.out.println("notGreen " + g); System.out.println("condition: " + condition); System.out.println("colors: " + s); return false; } } for (GenPolynomial r : s.red.getMap().values()) { if (condition.color(r) != Condition.Color.RED) { System.out.println("notRed " + r); System.out.println("condition: " + condition); System.out.println("colors: " + s); return false; } } for (GenPolynomial w : s.white.getMap().values()) { if (condition.color(w) != Condition.Color.WHITE) { // System.out.println("notWhite " + w); // System.out.println("condition: " + condition); // System.out.println("colors: " + s); continue; // no error // return false; } } } return true; } /** * Is this colored system completely determined. * @return true, if each ColorPolynomial is determined, else false. */ public boolean isDetermined() { for (ColorPolynomial s : list) { if (s.isZERO()) { continue; } if (!s.isDetermined()) { System.out.println("not simple determined " + s); System.out.println("condition: " + condition); return false; } if (!condition.isDetermined(s)) { return false; } } return true; } /** * Re determine colorings of polynomials. * @return colored system with re determined colored polynomials. */ public ColoredSystem reDetermine() { if (condition == null || condition.zero.isONE()) { return this; } List> Sn = new ArrayList>(list.size()); for (ColorPolynomial c : list) { ColorPolynomial a = condition.reDetermine(c); // if ( !a.isZERO() ) { Sn.add(a); // must also add zeros // } } return new ColoredSystem(condition, Sn, pairlist); } } jas-2.5/src/edu/jas/application/ColorPolynomial.java0000644000175000017500000002703111777641520022771 0ustar giovannigiovanni/* * $Id: ColorPolynomial.java 3984 2012-07-12 21:36:16Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.List; import java.util.Map; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Colored Polynomials with green, red and white coefficients. Not implementing * RingElem. Note: not general purpose, use only in comprehensive GB. * @param coefficient type * @author Heinz Kredel */ public class ColorPolynomial> implements Serializable /* implements RingElem< ColorPolynomial > */ { /** * The part with green (= zero) terms and coefficients. */ public final GenPolynomial> green; /** * The part with red (= non zero) terms and coefficients. */ public final GenPolynomial> red; /** * The part with white (= unknown color) terms and coefficients. */ public final GenPolynomial> white; /** * The constructor creates a colored polynomial from the colored parts. * @param g green colored terms and coefficients. * @param r red colored terms and coefficients. * @param w white colored terms and coefficients. */ public ColorPolynomial(GenPolynomial> g, GenPolynomial> r, GenPolynomial> w) { if (g == null || r == null || w == null) { throw new IllegalArgumentException("g,r,w may not be null"); } green = g; red = r; white = w; } /** * String representation of GenPolynomial. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer(); s.append(":green: "); s.append(green.toString()); s.append(" :red: "); s.append(red.toString()); s.append(" :white: "); s.append(white.toString()); return s.toString(); } /** * Is this polynomial ZERO. * @return true, if there are only green terms, else false. */ public boolean isZERO() { return (red.isZERO() && white.isZERO()); } /** * Is this polynomial ONE. * @return true, if the only non green term is 1, else false. */ public boolean isONE() { return ((red.isZERO() && white.isONE()) || (red.isONE() && white.isZERO())); } /** * Is this polynomial equal to other. * @param p other polynomial. * @return true, if this is equal to other, else false. */ @Override @SuppressWarnings("unchecked") public boolean equals(Object p) { ColorPolynomial cp = null; try { cp = (ColorPolynomial) p; } catch (ClassCastException e) { return false; } if (cp == null) { return false; } return (green.equals(cp.green) && red.equals(cp.red) && white.equals(cp.white)); } /** * Hash code for this colored polynomial. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = green.hashCode(); h = h << 11; h += red.hashCode(); h = h << 11; h += white.hashCode(); return h; } /** * Is this polynomial determined. * @return true, if there are nonzero red terms or if this == 0, else false. */ public boolean isDetermined() { return (!red.isZERO() || white.isZERO()); } /** * Check ordering invariants. TT(green) > LT(red) and TT(red) > LT(white). * @return true, if all ordering invariants are met, else false. */ public boolean checkInvariant() { boolean t = true; ExpVector ttg, ltr, ttr, ltw; Comparator cmp; if (green.isZERO() && red.isZERO() && white.isZERO()) { return true; } if (green.isZERO() && red.isZERO()) { return true; } if (red.isZERO() && white.isZERO()) { return true; } if (!green.isZERO() && !red.isZERO()) { ttg = green.trailingExpVector(); ltr = red.leadingExpVector(); cmp = green.ring.tord.getDescendComparator(); t = t && (cmp.compare(ttg, ltr) < 0); } if (!red.isZERO() && !white.isZERO()) { ttr = red.trailingExpVector(); ltw = white.leadingExpVector(); cmp = white.ring.tord.getDescendComparator(); t = t && (cmp.compare(ttr, ltw) < 0); } if (red.isZERO() && !green.isZERO() && !white.isZERO()) { ttg = green.trailingExpVector(); ltw = white.leadingExpVector(); cmp = white.ring.tord.getDescendComparator(); t = t && (cmp.compare(ttg, ltw) < 0); } if (!t) { System.out.println("not invariant " + this); // throw new RuntimeException("test"); } return t; } /** * Get zero condition on coefficients. * @return green coefficients. */ public List> getGreenCoefficients() { Collection> c = green.getMap().values(); return new ArrayList>(c); } /** * Get non zero condition on coefficients. * @return red coefficients. */ public List> getRedCoefficients() { Collection> c = red.getMap().values(); return new ArrayList>(c); } /** * Get full polynomial. * @return sum of all parts. */ public GenPolynomial> getPolynomial() { GenPolynomial> f = green.sum(red).sum(white); int s = green.length() + red.length() + white.length(); int t = f.length(); if (t != s) { throw new RuntimeException("illegal coloring state " + s + " != " + t); } return f; } /** * Get essential polynomial. * @return sum of red and white parts. */ public GenPolynomial> getEssentialPolynomial() { GenPolynomial> f = red.sum(white); int s = red.length() + white.length(); int t = f.length(); if (t != s) { throw new RuntimeException("illegal coloring state " + s + " != " + t); } return f; } /** * Length of red and white parts. * @return length of essential parts. */ public int length() { int s = red.length() + white.length(); return s; } /** * Get leading exponent vector. * @return LT of red or white parts. */ public ExpVector leadingExpVector() { if (!red.isZERO()) { return red.leadingExpVector(); } return white.leadingExpVector(); } /** * Get leading monomial. * @return LM of red or white parts. */ public Map.Entry> leadingMonomial() { if (!red.isZERO()) { return red.leadingMonomial(); } return white.leadingMonomial(); } /** * ColorPolynomial absolute value. * @return abs(this). */ public ColorPolynomial abs() { GenPolynomial> g, r, w; int s = green.signum(); if (s > 0) { return this; } if (s < 0) { g = green.negate(); r = red.negate(); w = white.negate(); return new ColorPolynomial(g, r, w); } // green == 0 g = green; s = red.signum(); if (s > 0) { return this; } if (s < 0) { r = red.negate(); w = white.negate(); return new ColorPolynomial(g, r, w); } // red == 0 r = red; s = white.signum(); if (s > 0) { return this; } if (s < 0) { w = white.negate(); return new ColorPolynomial(g, r, w); } // white == 0 w = white; return new ColorPolynomial(g, r, w); } /** * ColorPolynomial summation. Note: green coefficients stay green, * all others become white. * @param S ColorPolynomial. * @return this+S. */ public ColorPolynomial sum(ColorPolynomial S) { GenPolynomial> g, r, w; g = green.sum(S.green); r = red.ring.getZERO(); w = getEssentialPolynomial().sum(S.getEssentialPolynomial()); return new ColorPolynomial(g, r, w); } /** * ColorPolynomial summation. * @param s GenPolynomial. * @param e exponent vector. * @return this+(c e). */ public ColorPolynomial sum(GenPolynomial s, ExpVector e) { GenPolynomial> g, r, w; g = green; r = red; w = white; if (green.getMap().keySet().contains(e)) { g = green.sum(s, e); } else if (red.getMap().keySet().contains(e)) { r = red.sum(s, e); } else { w = white.sum(s, e); } return new ColorPolynomial(g, r, w); } /** * ColorPolynomial subtraction. Note: green coefficients stay green, * all others become white. * @param S ColorPolynomial. * @return this-S. */ public ColorPolynomial subtract(ColorPolynomial S) { GenPolynomial> g, r, w; g = green.subtract(S.green); r = red.ring.getZERO(); w = getEssentialPolynomial().subtract(S.getEssentialPolynomial()); return new ColorPolynomial(g, r, w); } /** * ColorPolynomial subtract. * @param s GenPolynomial. * @param e exponent vector. * @return this-(c e). */ public ColorPolynomial subtract(GenPolynomial s, ExpVector e) { GenPolynomial> g, r, w; g = green; r = red; w = white; if (green.getMap().keySet().contains(e)) { g = green.subtract(s, e); } else if (red.getMap().keySet().contains(e)) { r = red.subtract(s, e); } else { w = white.subtract(s, e); } return new ColorPolynomial(g, r, w); } /** * ColorPolynomial multiplication by monomial. * @param s Coefficient. * @param e Expvector. * @return this * (c t). */ public ColorPolynomial multiply(GenPolynomial s, ExpVector e) { GenPolynomial> g, r, w; g = green.multiply(s, e); r = red.multiply(s, e); w = white.multiply(s, e); return new ColorPolynomial(g, r, w); } /** * ColorPolynomial multiplication by coefficient. * @param s Coefficient. * @return this * (s). */ public ColorPolynomial multiply(GenPolynomial s) { GenPolynomial> g, r, w; g = green.multiply(s); r = red.multiply(s); w = white.multiply(s); return new ColorPolynomial(g, r, w); } /** * ColorPolynomial division by coefficient. * @param s Coefficient. * @return this / (s). */ public ColorPolynomial divide(GenPolynomial s) { GenPolynomial> g, r, w; g = green.divide(s); r = red.divide(s); w = white.divide(s); return new ColorPolynomial(g, r, w); } } jas-2.5/src/edu/jas/application/CPair.java0000644000175000017500000000730011505116606020631 0ustar giovannigiovanni/* * $Id: CPair.java 3426 2010-12-24 13:17:58Z kredel $ */ package edu.jas.application; import java.io.Serializable; import edu.jas.structure.RingElem; /** * Serializable subclass to hold pairs of colored polynomials. * @param coefficient type * @author Heinz Kredel. */ public class CPair> implements Serializable, Comparable> { public final ColorPolynomial pi; public final ColorPolynomial pj; public final int i; public final int j; protected int n; protected boolean toZero = false; protected boolean useCriterion4 = true; protected boolean useCriterion3 = true; /** * Pair constructor. * @param a polynomial i. * @param b polynomial j. * @param i first index. * @param j second index. */ public CPair(ColorPolynomial a, ColorPolynomial b, int i, int j) { pi = a; pj = b; this.i = i; this.j = j; this.n = 0; toZero = false; // ok } /** * toString. */ @Override public String toString() { return "pair[" + n + "](" + i + "{" + pi.length() + "}," + j + "{" + pj.length() + "}" + ", r0=" + toZero + ", c4=" + useCriterion4 + ", c3=" + useCriterion3 + ")"; } /** * Set removed pair number. * @param n number of this pair generated in OrderedPairlist. */ public void pairNumber(int n) { this.n = n; } /** * Get removed pair number. * @return n number of this pair generated in OrderedPairlist. */ public int getPairNumber() { return n; } /** * Set zero reduction. The S-polynomial of this Pair was reduced to zero. */ public void setZero() { toZero = true; } /** * Is reduced to zero. * @return true if the S-polynomial of this Pair was reduced to zero, else * false. */ public boolean isZero() { return toZero; } /** * equals. * @param ob an Object. * @return true if this is equal to ob, else false. */ @Override @SuppressWarnings("unchecked") public boolean equals(Object ob) { CPair cp = null; try { cp = (CPair) ob; } catch ( ClassCastException e) { return false; } if ( cp == null ) { return false; } return 0 == compareTo(cp); } /** * compareTo used in TreeMap. * Comparison is based on the number of the pairs. * @param p a Pair. * @return 1 if (this < p), 0 if (this == o), -1 if (this > p). */ public int compareTo(CPair p) { // not used at moment int x = p.getPairNumber(); if (n > x) { return 1; } if (n < x) { return -1; } return 0; } /** * Hash code for this pair. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = getPairNumber(); return h; } /** * Set useCriterion4. * @param c boolean value to set. */ public void setUseCriterion4(boolean c) { this.useCriterion4 = c; } /** * Get useCriterion4. * @return boolean value. */ public boolean getUseCriterion4() { return this.useCriterion4; } /** * Set useCriterion3. * @param c boolean value to set. */ public void setUseCriterion3(boolean c) { this.useCriterion3 = c; } /** * Get useCriterion3. * @return boolean value. */ public boolean getUseCriterion3() { return this.useCriterion3; } } jas-2.5/src/edu/jas/application/IdealWithRealRoots.java0000644000175000017500000000350412004024570023333 0ustar giovannigiovanni/* * $Id: IdealWithRealRoots.java 4050 2012-07-25 17:14:32Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.List; import edu.jas.arith.BigDecimal; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Container for Ideals together with univariate polynomials and real roots. * @author Heinz Kredel */ public class IdealWithRealRoots> extends IdealWithUniv { /** * The list of real roots. */ public final List> rroots; /** * Constructor not for use. */ protected IdealWithRealRoots() { throw new IllegalArgumentException("do not use this constructor"); } /** * Constructor. * @param id the ideal * @param up the list of univaraite polynomials * @param rr the list of real roots */ public IdealWithRealRoots(Ideal id, List> up, List> rr) { super(id, up); rroots = rr; } /** * Constructor. * @param iu the ideal with univariate polynomials * @param rr the list of real roots */ public IdealWithRealRoots(IdealWithUniv iu, List> rr) { super(iu.ideal, iu.upolys); rroots = rr; } /** * String representation of the ideal. * @see java.lang.Object#toString() */ @Override public String toString() { return super.toString() + "\nreal roots: " + rroots.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ @Override public String toScript() { // Python case return super.toScript() + ", " + rroots.toString(); } } jas-2.5/src/edu/jas/application/ResidueRing.java0000644000175000017500000002067612137717062022073 0ustar giovannigiovanni/* * $Id: ResidueRing.java 4407 2013-04-30 10:34:27Z kredel $ */ package edu.jas.application; import java.util.Random; import java.util.List; import java.util.ArrayList; import java.io.Reader; import org.apache.log4j.Logger; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.ufd.GreatestCommonDivisor; import edu.jas.ufd.GCDFactory; /** * Residue ring factory based on GenPolynomial with RingFactory interface. * Objects of this class are immutable. * @author Heinz Kredel */ public class ResidueRing > implements RingFactory< Residue > { private static final Logger logger = Logger.getLogger(ResidueRing.class); //private boolean debug = logger.isDebugEnabled(); /** * Greatest common divisor engine for coefficient content and primitive parts. */ protected final GreatestCommonDivisor engine; /** Polynomial ideal for the reduction. */ public final Ideal ideal; /** Polynomial ring of the factory. * Shortcut to ideal.list.ring. */ public final GenPolynomialRing ring; /** Indicator if this ring is a field. */ protected int isField = -1; // initially unknown /** The constructor creates a ResidueRing object * from an Ideal. * @param i polynomial ideal. */ public ResidueRing(Ideal i) { this(i,false); } /** The constructor creates a ResidueRing object * from an Ideal. * @param i polynomial ideal. * @param isMaximal true, if ideal is maxmal. */ public ResidueRing(Ideal i, boolean isMaximal) { ideal = i.GB(); // cheap if isGB ring = ideal.list.ring; //engine = GCDFactory.getImplementation( ring.coFac ); engine = GCDFactory.getProxy( ring.coFac ); if ( isMaximal ) { isField = 1; return; } //System.out.println("rr engine = " + engine.getClass().getName()); //System.out.println("rr ring = " + ring.getClass().getName()); //System.out.println("rr cofac = " + ring.coFac.getClass().getName()); if ( ideal.isONE() ) { logger.warn("ideal is one, so all residues are 0"); } } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return ideal.commonZeroTest() <= 0 && ring.coFac.isFinite(); } /** Copy Residue element c. * @param c * @return a copy of c. */ public Residue copy(Residue c) { //System.out.println("rr copy in = " + c.val); if ( c == null ) { // where does this happen? return getZERO(); // or null? } Residue r = new Residue( this, c.val ); //System.out.println("rr copy out = " + r.val); //System.out.println("rr copy ideal = " + ideal.list.list); return r; //new Residue( c.ring, c.val ); } /** Get the zero element. * @return 0 as Residue. */ public Residue getZERO() { return new Residue( this, ring.getZERO() ); } /** Get the one element. * @return 1 as Residue. */ public Residue getONE() { Residue one = new Residue( this, ring.getONE() ); if ( one.isZERO() ) { logger.warn("ideal is one, so all residues are 0"); } return one; } /** Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List> pgens = ring.generators(); List> gens = new ArrayList>( pgens.size() ); for ( GenPolynomial p : pgens ) { Residue r = new Residue( this, p ); if ( r.isZERO() ) { continue; } if ( !r.isONE() && r.val.isConstant() ) { continue; } gens.add(r); } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return ring.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return ring.isAssociative(); } /** * Query if this ring is a field. * @return false. */ public boolean isField() { if ( isField > 0 ) { return true; } if ( isField == 0 ) { return false; } // ideal is prime or maximal ? return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return ring.characteristic(); } /** Get a Residue element from a BigInteger value. * @param a BigInteger. * @return a Residue. */ public Residue fromInteger(java.math.BigInteger a) { return new Residue( this, ring.fromInteger(a) ); } /** Get a Residue element from a long value. * @param a long. * @return a Residue. */ public Residue fromInteger(long a) { return new Residue( this, ring.fromInteger(a) ); } /** Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { return "ResidueRing[ " + ideal.toString() + " ]"; } /** Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "RC(" + ideal.list.toScript() + ")"; //return "RC(" + ideal.toScript() + "," + ring.toScript() + ")"; } /** Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if ( ! ( b instanceof ResidueRing ) ) { return false; } ResidueRing a = null; try { a = (ResidueRing) b; } catch (ClassCastException e) { } if ( a == null ) { return false; } if ( ! ring.equals( a.ring ) ) { return false; } return ideal.equals( a.ideal ); } /** Hash code for this residue ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ideal.hashCode(); return h; } /** Residue random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random residue element. */ public Residue random(int n) { GenPolynomial x = ring.random( n ).monic(); return new Residue( this, x ); } /** * Generate a random residum polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @return a random residue polynomial. */ public Residue random(int k, int l, int d, float q) { GenPolynomial x = ring.random(k,l,d,q).monic(); return new Residue( this, x ); } /** Residue random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random residue element. */ public Residue random(int n, Random rnd) { GenPolynomial x = ring.random( n, rnd ).monic(); return new Residue( this, x); } /** Parse Residue from String. * @param s String. * @return Residue from s. */ public Residue parse(String s) { GenPolynomial x = ring.parse( s ); return new Residue( this, x ); } /** Parse Residue from Reader. * @param r Reader. * @return next Residue from r. */ public Residue parse(Reader r) { GenPolynomial x = ring.parse( r ); return new Residue( this, x ); } } jas-2.5/src/edu/jas/application/RingFactoryTokenizer.java0000644000175000017500000007476212041330126023764 0ustar giovannigiovanni/* * $Id: RingFactoryTokenizer.java 4267 2012-10-22 20:45:10Z kredel $ */ package edu.jas.application; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.io.StreamTokenizer; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Scanner; import org.apache.log4j.Logger; import edu.jas.arith.BigComplex; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigInteger; import edu.jas.arith.BigQuaternion; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLongRing; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenPolynomialTokenizer; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.RelationTable; import edu.jas.poly.TermOrder; import edu.jas.structure.RingFactory; import edu.jas.ufd.Quotient; import edu.jas.ufd.QuotientRing; /** * RingFactory Tokenizer. Used to read ring factories from input streams. It can * read also QuotientRing factory. * @author Heinz Kredel */ public class RingFactoryTokenizer { private static final Logger logger = Logger.getLogger(RingFactoryTokenizer.class); private final boolean debug = logger.isDebugEnabled(); private String[] vars; private int nvars = 1; private TermOrder tord; private RelationTable table; //private Reader in; private final StreamTokenizer tok; private final Reader reader; private RingFactory fac; private static enum coeffType { BigRat, BigInt, ModInt, BigC, BigQ, BigD, ANrat, ANmod, RatFunc, ModFunc, IntFunc }; private coeffType parsedCoeff = coeffType.BigRat; private GenPolynomialRing pfac; private static enum polyType { PolBigRat, PolBigInt, PolModInt, PolBigC, PolBigD, PolBigQ, PolANrat, PolANmod, PolRatFunc, PolModFunc, PolIntFunc }; private polyType parsedPoly = polyType.PolBigRat; private GenSolvablePolynomialRing spfac; /** * No-args constructor reads from System.in. */ public RingFactoryTokenizer() { this(new BufferedReader(new InputStreamReader(System.in,Charset.forName("UTF8")))); } /** * Constructor with Ring and Reader. * @param rf ring factory. * @param r reader stream. */ public RingFactoryTokenizer(GenPolynomialRing rf, Reader r) { this(r); if (rf == null) { return; } if (rf instanceof GenSolvablePolynomialRing) { pfac = rf; spfac = (GenSolvablePolynomialRing) rf; } else { pfac = rf; spfac = null; } fac = rf.coFac; vars = rf.getVars(); if (vars != null) { nvars = vars.length; } tord = rf.tord; // relation table if (spfac != null) { table = spfac.table; } else { table = null; } } /** * Constructor with Reader. * @param r reader stream. */ @SuppressWarnings("unchecked") public RingFactoryTokenizer(Reader r) { //BasicConfigurator.configure(); vars = null; tord = new TermOrder(); nvars = 1; fac = new BigRational(1); //pfac = null; pfac = new GenPolynomialRing(fac, nvars, tord, vars); //spfac = null; spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); reader = r; tok = new StreamTokenizer(r); tok.resetSyntax(); // tok.eolIsSignificant(true); no more tok.eolIsSignificant(false); tok.wordChars('0', '9'); tok.wordChars('a', 'z'); tok.wordChars('A', 'Z'); tok.wordChars('_', '_'); // for subscripts x_i tok.wordChars('/', '/'); // wg. rational numbers tok.wordChars(128 + 32, 255); tok.whitespaceChars(0, ' '); tok.commentChar('#'); tok.quoteChar('"'); tok.quoteChar('\''); //tok.slashStarComments(true); does not work } /** * Initialize coefficient and polynomial factories. * @param rf ring factory. * @param ct coefficient type. */ @SuppressWarnings("unchecked") public void initFactory(RingFactory rf, coeffType ct) { fac = rf; parsedCoeff = ct; switch (ct) { case BigRat: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigRat; break; case BigInt: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigInt; break; case ModInt: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolModInt; break; case BigC: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigC; break; case BigQ: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigQ; break; case BigD: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigD; break; case RatFunc: pfac = new GenPolynomialRing>(fac, nvars, tord, vars); parsedPoly = polyType.PolRatFunc; break; case ModFunc: pfac = new GenPolynomialRing>(fac, nvars, tord, vars); parsedPoly = polyType.PolModFunc; break; case IntFunc: pfac = new GenPolynomialRing>(fac, nvars, tord, vars); parsedPoly = polyType.PolIntFunc; break; default: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigRat; } } /** * Initialize coefficient and solvable polynomial factories. * @param rf ring factory. * @param ct coefficient type. */ @SuppressWarnings("unchecked") public void initSolvableFactory(RingFactory rf, coeffType ct) { fac = rf; parsedCoeff = ct; switch (ct) { case BigRat: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigRat; break; case BigInt: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigInt; break; case ModInt: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolModInt; break; case BigC: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigC; break; case BigQ: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigQ; break; case BigD: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigD; break; case RatFunc: spfac = new GenSolvablePolynomialRing>(fac, nvars, tord, vars); parsedPoly = polyType.PolRatFunc; break; case ModFunc: spfac = new GenSolvablePolynomialRing>(fac, nvars, tord, vars); parsedPoly = polyType.PolModFunc; break; case IntFunc: spfac = new GenSolvablePolynomialRing>(fac, nvars, tord, vars); parsedPoly = polyType.PolIntFunc; break; default: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigRat; } } /** * Parsing method for comments. syntax: (* comment *) | /_* comment *_/ * without _ Does not work with this pushBack(), unused. */ public String nextComment() throws IOException { // syntax: (* comment *) | /* comment */ StringBuffer c = new StringBuffer(); int tt; if (debug) logger.debug("comment: " + tok); tt = tok.nextToken(); if (debug) logger.debug("comment: " + tok); if (tt == '(') { tt = tok.nextToken(); if (debug) logger.debug("comment: " + tok); if (tt == '*') { if (debug) logger.debug("comment: "); while (true) { tt = tok.nextToken(); if (tt == '*') { tt = tok.nextToken(); if (tt == ')') { return c.toString(); } tok.pushBack(); } c.append(tok.sval); } } tok.pushBack(); if (debug) logger.debug("comment: " + tok); } tok.pushBack(); if (debug) logger.debug("comment: " + tok); return c.toString(); } /** * Parsing method for variable list. syntax: (a, b c, de) gives [ "a", "b", * "c", "de" ] * @return the next variable list. * @throws IOException */ public String[] nextVariableList() throws IOException { List l = new ArrayList(); int tt; tt = tok.nextToken(); //System.out.println("vList tok = " + tok); if (tt == '(' || tt == '{') { logger.debug("variable list"); tt = tok.nextToken(); while (true) { if (tt == StreamTokenizer.TT_EOF) break; if (tt == ')' || tt == '}') break; if (tt == StreamTokenizer.TT_WORD) { //System.out.println("TT_WORD: " + tok.sval); l.add(tok.sval); } tt = tok.nextToken(); } } Object[] ol = l.toArray(); String[] v = new String[ol.length]; for (int i = 0; i < v.length; i++) { v[i] = (String) ol[i]; } return v; } /** * Parsing method for coefficient ring. syntax: Rat | Q | Int | Z | Mod * modul | Complex | C | D | Quat | AN[ (var) ( poly ) | AN[ modul (var) ( * poly ) ] | RatFunc (var_list) | ModFunc modul (var_list) | IntFunc * (var_list) * @return the next coefficient factory. * @throws IOException */ @SuppressWarnings("unchecked") public RingFactory nextCoefficientRing() throws IOException { RingFactory coeff = null; coeffType ct = null; int tt; tt = tok.nextToken(); if (tok.sval != null) { if (tok.sval.equalsIgnoreCase("Q")) { coeff = new BigRational(0); ct = coeffType.BigRat; } else if (tok.sval.equalsIgnoreCase("Rat")) { coeff = new BigRational(0); ct = coeffType.BigRat; } else if (tok.sval.equalsIgnoreCase("D")) { coeff = new BigDecimal(0); ct = coeffType.BigD; } else if (tok.sval.equalsIgnoreCase("Z")) { coeff = new BigInteger(0); ct = coeffType.BigInt; } else if (tok.sval.equalsIgnoreCase("Int")) { coeff = new BigInteger(0); ct = coeffType.BigInt; } else if (tok.sval.equalsIgnoreCase("C")) { coeff = new BigComplex(0); ct = coeffType.BigC; } else if (tok.sval.equalsIgnoreCase("Complex")) { coeff = new BigComplex(0); ct = coeffType.BigC; } else if (tok.sval.equalsIgnoreCase("Quat")) { coeff = new BigQuaternion(0); ct = coeffType.BigQ; } else if (tok.sval.equalsIgnoreCase("Mod")) { tt = tok.nextToken(); boolean openb = false; if (tt == '[') { // optional openb = true; tt = tok.nextToken(); } if (tok.sval != null && tok.sval.length() > 0) { if (digit(tok.sval.charAt(0))) { BigInteger mo = new BigInteger(tok.sval); BigInteger lm = new BigInteger(ModLongRing.MAX_LONG); //Long.MAX_VALUE); if (mo.compareTo(lm) < 0) { coeff = new ModLongRing(mo.getVal()); } else { coeff = new ModIntegerRing(mo.getVal()); } System.out.println("coeff = " + coeff + " :: " + coeff.getClass()); ct = coeffType.ModInt; } else { tok.pushBack(); } } else { tok.pushBack(); } if (tt == ']' && openb) { // optional tt = tok.nextToken(); } } else if (tok.sval.equalsIgnoreCase("RatFunc")) { String[] rfv = nextVariableList(); //System.out.println("rfv = " + rfv.length + " " + rfv[0]); int vr = rfv.length; BigInteger bi = new BigInteger(); TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing pcf = new GenPolynomialRing(bi, vr, to, rfv); coeff = new QuotientRing(pcf); ct = coeffType.RatFunc; } else if (tok.sval.equalsIgnoreCase("ModFunc")) { tt = tok.nextToken(); RingFactory mi = new ModIntegerRing("19"); if (tok.sval != null && tok.sval.length() > 0) { if (digit(tok.sval.charAt(0))) { mi = new ModIntegerRing(tok.sval); } else { tok.pushBack(); } } else { tok.pushBack(); } String[] rfv = nextVariableList(); //System.out.println("rfv = " + rfv.length + " " + rfv[0]); int vr = rfv.length; TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing pcf = new GenPolynomialRing(mi, vr, to, rfv); coeff = new QuotientRing(pcf); ct = coeffType.ModFunc; } else if (tok.sval.equalsIgnoreCase("IntFunc")) { String[] rfv = nextVariableList(); //System.out.println("rfv = " + rfv.length + " " + rfv[0]); int vr = rfv.length; BigRational bi = new BigRational(); TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing pcf = new GenPolynomialRing(bi, vr, to, rfv); coeff = pcf; ct = coeffType.IntFunc; } else if (tok.sval.equalsIgnoreCase("AN")) { tt = tok.nextToken(); if (tt == '[') { tt = tok.nextToken(); RingFactory tcfac = new ModIntegerRing("19"); if (tok.sval != null && tok.sval.length() > 0) { if (digit(tok.sval.charAt(0))) { tcfac = new ModIntegerRing(tok.sval); } else { tcfac = new BigRational(); tok.pushBack(); } } else { tcfac = new BigRational(); tok.pushBack(); } String[] anv = nextVariableList(); //System.out.println("anv = " + anv.length + " " + anv[0]); int vs = anv.length; if (vs != 1) { logger.error("AlgebraicNumber only for univariate polynomials"); } String[] ovars = vars; vars = anv; GenPolynomialRing tpfac = pfac; RingFactory tfac = fac; fac = tcfac; // pfac and fac used in nextPolynomial() if (tcfac instanceof ModIntegerRing) { pfac = new GenPolynomialRing(tcfac, vs, new TermOrder(), anv); } else { pfac = new GenPolynomialRing(tcfac, vs, new TermOrder(), anv); } if (debug) { logger.debug("pfac = " + pfac); } GenPolynomialTokenizer ptok = new GenPolynomialTokenizer(pfac, reader); GenPolynomial mod = ptok.nextPolynomial(); ptok = null; if (debug) { logger.debug("mod = " + mod); } pfac = tpfac; fac = tfac; vars = ovars; if (tcfac instanceof ModIntegerRing) { GenPolynomial gfmod; gfmod = (GenPolynomial) mod; coeff = new AlgebraicNumberRing(gfmod); ct = coeffType.ANmod; } else { GenPolynomial anmod; anmod = (GenPolynomial) mod; coeff = new AlgebraicNumberRing(anmod); ct = coeffType.ANrat; } if (debug) { logger.debug("coeff = " + coeff); } tt = tok.nextToken(); if (tt == ']') { //ok, no nextToken(); } else { tok.pushBack(); } } else { tok.pushBack(); } } } if (coeff == null) { tok.pushBack(); coeff = new BigRational(); ct = coeffType.BigRat; } parsedCoeff = ct; return coeff; } /** * Parsing method for weight list. syntax: (w1, w2, w3, ..., wn) * @return the next weight list. * @throws IOException */ public long[] nextWeightList() throws IOException { List l = new ArrayList(); long[] w = null; long e; char first; int tt; tt = tok.nextToken(); if (tt == '(') { logger.debug("weight list"); tt = tok.nextToken(); while (true) { if (tt == StreamTokenizer.TT_EOF) break; if (tt == ')') break; if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { e = Long.parseLong(tok.sval); l.add(Long.valueOf(e)); //System.out.println("w: " + e); } } tt = tok.nextToken(); // also comma } } Object[] ol = l.toArray(); w = new long[ol.length]; for (int i = 0; i < w.length; i++) { w[i] = ((Long) ol[ol.length - i - 1]).longValue(); } return w; } /** * Parsing method for weight array. syntax: ( (w11, ...,w1n), ..., (wm1, * ..., wmn) ) * @return the next weight array. * @throws IOException */ public long[][] nextWeightArray() throws IOException { List l = new ArrayList(); long[][] w; long[] e; char first; int tt; tt = tok.nextToken(); if (tt == '(') { logger.debug("weight array"); tt = tok.nextToken(); while (true) { if (tt == StreamTokenizer.TT_EOF) break; if (tt == ')') break; if (tt == '(') { tok.pushBack(); e = nextWeightList(); l.add(e); //System.out.println("wa: " + e); } else if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { tok.pushBack(); tok.pushBack(); e = nextWeightList(); l.add(e); break; //System.out.println("w: " + e); } } tt = tok.nextToken(); // also comma } } Object[] ol = l.toArray(); w = new long[ol.length][]; for (int i = 0; i < w.length; i++) { w[i] = (long[]) ol[i]; } return w; } /** * Parsing method for split index. syntax: |i| * @return the next split index. * @throws IOException */ public int nextSplitIndex() throws IOException { int e = -1; // =unknown int e0 = -1; // =unknown char first; int tt; tt = tok.nextToken(); if (tt == '|') { if (debug) { logger.debug("split index"); } tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) { return e; } else if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { e = Integer.parseInt(tok.sval); //System.out.println("w: " + i); } tt = tok.nextToken(); if (tt != '|') { tok.pushBack(); } } } else if (tt == '[') { if (debug) { logger.debug("split index"); } tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) { return e; } if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { e0 = Integer.parseInt(tok.sval); //System.out.println("w: " + i); } tt = tok.nextToken(); if (tt == ',') { tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) { return e0; // ?? } if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { e = Integer.parseInt(tok.sval); //System.out.println("w: " + i); } } if (tt != ']') { tok.pushBack(); } } } } else { tok.pushBack(); } return e; } /** * Parsing method for term order name. syntax: termOrderName = L, IL, LEX, * G, IG, GRLEX, W(weights) |split index| * @return the next term order. * @throws IOException */ public TermOrder nextTermOrder() throws IOException { int evord = TermOrder.DEFAULT_EVORD; int tt; tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) { /* nop */ } else if (tt == StreamTokenizer.TT_WORD) { // System.out.println("TT_WORD: " + tok.sval); if (tok.sval != null) { if (tok.sval.equalsIgnoreCase("L")) { evord = TermOrder.INVLEX; } else if (tok.sval.equalsIgnoreCase("IL")) { evord = TermOrder.INVLEX; } else if (tok.sval.equalsIgnoreCase("INVLEX")) { evord = TermOrder.INVLEX; } else if (tok.sval.equalsIgnoreCase("LEX")) { evord = TermOrder.LEX; } else if (tok.sval.equalsIgnoreCase("G")) { evord = TermOrder.IGRLEX; } else if (tok.sval.equalsIgnoreCase("IG")) { evord = TermOrder.IGRLEX; } else if (tok.sval.equalsIgnoreCase("IGRLEX")) { evord = TermOrder.IGRLEX; } else if (tok.sval.equalsIgnoreCase("GRLEX")) { evord = TermOrder.GRLEX; } else if (tok.sval.equalsIgnoreCase("W")) { long[][] w = nextWeightArray(); //int s = nextSplitIndex(); // no more return new TermOrder(w); } } } int s = nextSplitIndex(); if (s <= 0) { return new TermOrder(evord); } return new TermOrder(evord, evord, vars.length, s); } /** * Parsing method for solvable polynomial relation table. syntax: ( p_1, * p_2, p_3, ..., p_{n+3} ) semantics: p_{n+1} * p_{n+2} = p_{n+3} The next * relation table is stored into the solvable polynomial factory. * @throws IOException */ @SuppressWarnings("unchecked") public void nextRelationTable() throws IOException { if (spfac == null) { return; } RelationTable table = spfac.table; List rels = null; GenPolynomial p; GenSolvablePolynomial sp; int tt; tt = tok.nextToken(); if (debug) { logger.debug("start relation table: " + tt); } if (tok.sval != null) { if (tok.sval.equalsIgnoreCase("RelationTable")) { GenPolynomialTokenizer ptok = new GenPolynomialTokenizer(pfac, reader); rels = ptok.nextPolynomialList(); ptok = null; } } if (rels == null) { tok.pushBack(); return; } for (Iterator it = rels.iterator(); it.hasNext();) { p = it.next(); ExpVector e = p.leadingExpVector(); if (it.hasNext()) { p = it.next(); ExpVector f = p.leadingExpVector(); if (it.hasNext()) { p = it.next(); sp = new GenSolvablePolynomial(spfac); sp.doPutToMap(p.getMap()); table.update(e, f, sp); } } } if (debug) { logger.info("table = " + table); } return; } /** * Parsing method for polynomial set. syntax: coeffRing varList * termOrderName polyList. * @return the next polynomial set. * @throws IOException */ @SuppressWarnings("unchecked") public GenPolynomialRing nextPolynomialRing() throws IOException { //String comments = ""; //comments += nextComment(); //if (debug) logger.debug("comment = " + comments); RingFactory coeff = nextCoefficientRing(); logger.info("coeff = " + coeff); vars = nextVariableList(); logger.info("vars = " + Arrays.toString(vars)); if (vars != null) { nvars = vars.length; } tord = nextTermOrder(); logger.info("tord = " + tord); // check more TOs initFactory(coeff, parsedCoeff); // global: nvars, tord, vars // now pfac is initialized return pfac; } /** * Parsing method for solvable polynomial set. syntax: varList termOrderName * relationTable polyList. * @return the next solvable polynomial set. * @throws IOException */ @SuppressWarnings("unchecked") public GenSolvablePolynomialRing nextSolvablePolynomialRing() throws IOException { //String comments = ""; //comments += nextComment(); //if (debug) logger.debug("comment = " + comments); RingFactory coeff = nextCoefficientRing(); logger.info("coeff = " + coeff); vars = nextVariableList(); logger.info("vars = " + Arrays.toString(vars)); if (vars != null) { nvars = vars.length; } tord = nextTermOrder(); logger.info("tord = " + tord); // check more TOs initFactory(coeff, parsedCoeff); // must be because of symmetric read initSolvableFactory(coeff, parsedCoeff); // global: nvars, tord, vars //System.out.println("pfac = " + pfac); //System.out.println("spfac = " + spfac); nextRelationTable(); if (logger.isInfoEnabled()) { logger.info("table = " + table + ", tok = " + tok); } // now spfac is initialized return spfac; } private boolean digit(char x) { return '0' <= x && x <= '9'; } //private boolean letter(char x) { // return ('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z'); //} // unused public void nextComma() throws IOException { int tt; if (tok.ttype == ',') { tt = tok.nextToken(); if (debug) { logger.debug("after comma: " + tt); } } } /** * Parse variable list from String. * @param s String. Syntax: (n1,...,nk) or (n1 ... nk), brackest are also * optional. * @return array of variable names found in s. */ public static String[] variableList(String s) { String[] vl = null; if (s == null) { return vl; } String st = s.trim(); if (st.length() == 0) { return new String[0]; } if (st.charAt(0) == '(') { st = st.substring(1); } if (st.charAt(st.length() - 1) == ')') { st = st.substring(0, st.length() - 1); } st = st.replaceAll(",", " "); List sl = new ArrayList(); Scanner sc = new Scanner(st); while (sc.hasNext()) { String sn = sc.next(); sl.add(sn); } vl = new String[sl.size()]; int i = 0; for (String si : sl) { vl[i] = si; i++; } return vl; } } jas-2.5/src/edu/jas/application/SolvableResidueRing.java0000644000175000017500000002211112137717062023545 0ustar giovannigiovanni/* * $Id: SolvableResidueRing.java 4407 2013-04-30 10:34:27Z kredel $ */ package edu.jas.application; import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.gb.SolvableGroebnerBaseAbstract; import edu.jas.gb.SolvableGroebnerBaseSeq; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * SolvableResidue ring factory based on GenSolvablePolynomial with RingFactory * interface. Objects of this class are immutable. * @author Heinz Kredel */ public class SolvableResidueRing> implements RingFactory> { private static final Logger logger = Logger.getLogger(SolvableResidueRing.class); //private boolean debug = logger.isDebugEnabled(); /** * Groebner base engine. */ protected final SolvableGroebnerBaseAbstract bb; /** * Solvable polynomial ideal for the reduction. */ public final SolvableIdeal ideal; /** * Polynomial ring of the factory. Shortcut to ideal.list.ring. */ public final GenSolvablePolynomialRing ring; /** * Indicator if this ring is a field. */ protected int isField = -1; // initially unknown /** * The constructor creates a SolvableResidueRing object from an Ideal. * @param i polynomial ideal. */ public SolvableResidueRing(SolvableIdeal i) { this(i, false); } /** * The constructor creates a SolvableResidueRing object from an * SolvableIdeal. * @param i solvable polynomial ideal. * @param isMaximal true, if ideal is maxmal. */ public SolvableResidueRing(SolvableIdeal i, boolean isMaximal) { ideal = i.GB(); // cheap if isGB ring = ideal.getRing(); bb = new SolvableGroebnerBaseSeq(); if (isMaximal) { isField = 1; return; } if (ideal.isONE()) { logger.warn("ideal is one, so all residues are 0"); } //System.out.println("rr ring = " + ring.getClass().getName()); //System.out.println("rr cofac = " + ring.coFac.getClass().getName()); } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return ideal.commonZeroTest() <= 0 && ring.coFac.isFinite(); } /** * Copy SolvableResidue element c. * @param c * @return a copy of c. */ public SolvableResidue copy(SolvableResidue c) { //System.out.println("rr copy in = " + c.val); if (c == null) { // where does this happen? return getZERO(); // or null? } SolvableResidue r = new SolvableResidue(this, c.val); //System.out.println("rr copy out = " + r.val); //System.out.println("rr copy ideal = " + ideal.list.list); return r; //new SolvableResidue( c.ring, c.val ); } /** * Get the zero element. * @return 0 as SolvableResidue. */ public SolvableResidue getZERO() { return new SolvableResidue(this, ring.getZERO()); } /** * Get the one element. * @return 1 as SolvableResidue. */ public SolvableResidue getONE() { SolvableResidue one = new SolvableResidue(this, ring.getONE()); if (one.isZERO()) { logger.warn("ideal is one, so all residues are 0"); } return one; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List> pgens = ring.generators(); List> gens = new ArrayList>(pgens.size()); for (GenPolynomial p : pgens) { GenSolvablePolynomial s = (GenSolvablePolynomial) p; SolvableResidue r = new SolvableResidue(this, s); if ( r.isZERO() ) { continue; } if ( !r.isONE() && r.val.isConstant() ) { continue; } gens.add(r); } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return ring.isCommutative(); // check also vector space structure } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return ring.isAssociative(); // sufficient ?? } /** * Query if this ring is a field. * @return false. */ public boolean isField() { if (isField > 0) { return true; } if (isField == 0) { return false; } // ideal is (complete) prime or maximal ? return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return ring.characteristic(); } /** * Get a SolvableResidue element from a BigInteger value. * @param a BigInteger. * @return a SolvableResidue. */ public SolvableResidue fromInteger(java.math.BigInteger a) { return new SolvableResidue(this, ring.fromInteger(a)); } /** * Get a SolvableResidue element from a long value. * @param a long. * @return a SolvableResidue. */ public SolvableResidue fromInteger(long a) { return new SolvableResidue(this, ring.fromInteger(a)); } /** * Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { return "SolvableResidueRing[ " + ideal.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ @Override public String toScript() { // Python case return "SRC(" + ideal.list.toScript() + ")"; //return "SRC(" + ideal.toScript() + "," + ring.toScript() + ")"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof SolvableResidueRing)) { return false; } SolvableResidueRing a = null; try { a = (SolvableResidueRing) b; } catch (ClassCastException e) { } if (a == null) { return false; } if (!ring.equals(a.ring)) { return false; } return ideal.equals(a.ideal); } /** * Hash code for this residue ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ideal.hashCode(); return h; } /** * SolvableResidue random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random residue element. */ public SolvableResidue random(int n) { GenSolvablePolynomial x = (GenSolvablePolynomial) ring.random(n).monic(); return new SolvableResidue(this, x); } /** * Generate a random residum polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @return a random residue polynomial. */ public SolvableResidue random(int k, int l, int d, float q) { GenSolvablePolynomial x = (GenSolvablePolynomial) ring.random(k, l, d, q).monic(); return new SolvableResidue(this, x); } /** * SolvableResidue random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random residue element. */ public SolvableResidue random(int n, Random rnd) { GenSolvablePolynomial x = (GenSolvablePolynomial) ring.random(n, rnd).monic(); return new SolvableResidue(this, x); } /** * Parse SolvableResidue from String. * @param s String. * @return SolvableResidue from s. */ public SolvableResidue parse(String s) { GenSolvablePolynomial x = ring.parse(s); return new SolvableResidue(this, x); } /** * Parse SolvableResidue from Reader. * @param r Reader. * @return next SolvableResidue from r. */ public SolvableResidue parse(Reader r) { GenSolvablePolynomial x = ring.parse(r); return new SolvableResidue(this, x); } } jas-2.5/src/edu/jas/application/Dimension.java0000644000175000017500000000407411353363162021567 0ustar giovannigiovanni/* * $Id: Dimension.java 3058 2010-03-27 11:05:23Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.Arrays; import java.util.Set; /** * Container for dimension parameters. * @author Heinz Kredel */ public class Dimension implements Serializable { /** * Ideal dimension. */ public final int d; /** * Indices of a maximal independent set (of variables). */ public final Set S; /** * Set of indices of all maximal independent sets (of variables). */ public final Set> M; /** * Names of all variables. */ public final String[] v; /** * Constructor. * @param d ideal dimension. * @param S indices of a maximal independent set (of variables) * @param M set of indices of all maximal independent sets (of variables) * @param v names of all variables */ public Dimension(int d, Set S, Set> M, String[] v) { this.d = d; this.S = S; this.M = M; this.v = v; } /** * String representation of the ideal. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer("Dimension( " + d + ", "); if (v == null) { sb.append("" + S + ", " + M + " )"); return sb.toString(); } String[] s = new String[S.size()]; int j = 0; for (Integer i : S) { s[j] = v[i]; j++; } sb.append(Arrays.toString(s) + ", "); sb.append("[ "); boolean first = true; for (Set m : M) { if (first) { first = false; } else { sb.append(", "); } s = new String[m.size()]; j = 0; for (Integer i : m) { s[j] = v[i]; j++; } sb.append(Arrays.toString(s)); } sb.append(" ] )"); return sb.toString(); } } jas-2.5/src/edu/jas/application/ComprehensiveGroebnerBaseSeq.java0000644000175000017500000005454312014234362025401 0ustar giovannigiovanni/* * $Id: ComprehensiveGroebnerBaseSeq.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.application; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.log4j.Logger; import edu.jas.gb.GroebnerBase; import edu.jas.gbufd.GBFactory; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.ufd.SquarefreeAbstract; import edu.jas.ufd.SquarefreeFactory; /** * Comprehensive Groebner Base sequential algorithm. Implements faithful * comprehensive Groebner bases via Groebner systems and CGB test. * @param coefficient type * @author Heinz Kredel */ public class ComprehensiveGroebnerBaseSeq> /* extends GroebnerBaseAbstract> */{ private static final Logger logger = Logger.getLogger(ComprehensiveGroebnerBaseSeq.class); private static final boolean debug = logger.isDebugEnabled(); /** * Squarefree for coefficient content and primitive parts. */ protected final SquarefreeAbstract engine; /* * Flag if gcd engine should be used. */ //private final boolean notFaithfull = false; /** * Comprehensive reduction engine. */ protected final CReductionSeq cred; /** * Polynomial coefficient ring factory. */ protected final RingFactory cofac; /** * Constructor. * @param rf base coefficient ring factory. */ public ComprehensiveGroebnerBaseSeq(RingFactory rf) { this(new CReductionSeq(rf), rf); } /** * Constructor. * @param red C-pseudo-Reduction engine * @param rf base coefficient ring factory. */ @SuppressWarnings("unchecked") public ComprehensiveGroebnerBaseSeq(CReductionSeq red, RingFactory rf) { // super(null); // red not possible since type of type cred = red; cofac = rf; // selection for C but used for R: //engine e = GCDFactory. getImplementation(cofac); engine = SquarefreeFactory. getImplementation(rf); } /** * Comprehensive-Groebner base test. * @param F polynomial list. * @return true, if F is a Comprehensive-Groebner base, else false. */ // @Override public boolean isGB(List>> F) { return isGB(0, F); } /** * Comprehensive-Groebner base test. * @param modv module variable number. * @param F polynomial list. * @return true, if F is a Comprehensive-Groebner base, else false. */ // @Override public boolean isGB(int modv, List>> F) { // return isGBcol( modv, F ); return isGBsubst(modv, F); } /** * Comprehensive-Groebner base test using colored systems. * @param F polynomial list. * @return true, if F is a Comprehensive-Groebner base, else false. */ // @Override public boolean isGBcol(List>> F) { return isGBcol(0, F); } /** * Comprehensive-Groebner base test using colored systems. * @param modv module variable number. * @param F polynomial list. * @return true, if F is a Comprehensive-Groebner base, else false. */ // @Override public boolean isGBcol(int modv, List>> F) { if (F == null || F.size() == 0) { return true; } List> CS = cred.determine(F); return isGBsys(modv, CS); } /** * Comprehensive-Groebner system test. * @param CS list of colored systems. * @return true, if CS is a Comprehensive-Groebner system, else false. */ // @Override public boolean isGBsys(List> CS) { return isGBsys(0, CS); } /** * Comprehensive-Groebner system test. * @param modv module variable number. * @param CS list of colored systems. * @return true, if CS is a Comprehensive-Groebner system, else false. */ // @Override public boolean isGBsys(int modv, List> CS) { if (CS == null || CS.size() == 0) { return true; } ColorPolynomial p, q, h, hp; for (ColoredSystem cs : CS) { if (debug) { if (!cs.isDetermined()) { System.out.println("not determined, cs = " + cs); return false; } if (!cs.checkInvariant()) { System.out.println("not invariant, cs = " + cs); return false; } } Condition cond = cs.condition; List> S = cs.list; int k = S.size(); for (int j = 0; j < k; j++) { p = S.get(j); for (int l = j + 1; l < k; l++) { q = S.get(l); h = cred.SPolynomial(p, q); // System.out.println("spol(a,b) = " + h); h = cred.normalform(cond, S, h); // System.out.println("NF(spol(a,b)) = " + h); if (debug) { if (!cred.isNormalform(S, h)) { System.out.println("not normalform, h = " + h); System.out.println("cs = " + cs); return false; } } if (!h.isZERO()) { hp = cond.reDetermine(h); if (!hp.isZERO()) { System.out.println("p = " + p); System.out.println("q = " + q); System.out.println("not zero: NF(spol(p,q)) = " + h); System.out.println("redetermine(NF(spol(p,q))) = " + hp); System.out.println("cs = " + cs); return false; } } } } } return true; } /** * Comprehensive-Groebner base test using substitution. * @param F polynomial list. * @return true, if F is a Comprehensive-Groebner base, else false. */ // @Override public boolean isGBsubst(List>> F) { return isGBsubst(0, F); } /** * Comprehensive-Groebner base test using substitution. * @param modv module variable number. * @param F polynomial list. * @return true, if F is a Comprehensive-Groebner base, else false. */ // @Override public boolean isGBsubst(int modv, List>> F) { if (F == null || F.size() == 0) { return true; } GenPolynomial> f = F.get(0); // assert non Zero GenPolynomialRing> cf = f.ring; List> CS = cred.determine(F); if (logger.isDebugEnabled()) { logger.info("determined polynomials =\n" + CS); } // substitute zero conditions into parameter coefficients and test for (ColoredSystem cs : CS) { Ideal id = cs.condition.zero; ResidueRing r = new ResidueRing(id); GenPolynomialRing> rf = new GenPolynomialRing>(r, cf); List>> list = PolyUtilApp. toResidue(rf, F); //GroebnerBase> bb = new GroebnerBasePseudoSeq>(r); GroebnerBase> bb = GBFactory.getImplementation(r); boolean t = bb.isGB(list); if (!t) { System.out.println("test condition = " + cs.condition); System.out.println("no GB for residue coefficients = " + list); return false; } } // substitute random ideal into parameter coefficients and test GenPolynomialRing ccf = (GenPolynomialRing) cf.coFac; int nv = ccf.nvar - 2; if (nv < 1) { nv = 1; } List> il = new ArrayList>(); int i = 0; int j = 1; while (i < nv) { j++; GenPolynomial p = ccf.random(j + 1); // System.out.println("p = " + p); if (p.isConstant()) { continue; } if (p.isZERO()) { continue; } p = engine.squarefreePart(p); il.add(p); i++; } logger.info("random ideal = " + il); Ideal id = new Ideal(ccf, il); ResidueRing r = new ResidueRing(id); GenPolynomialRing> rf = new GenPolynomialRing>(r, cf); List>> list = PolyUtilApp. toResidue(rf, F); logger.info("random residue = " + r.ideal.getList()); //GroebnerBase> bb = new GroebnerBasePseudoSeq>(r); GroebnerBase> bb = GBFactory.getImplementation(r); boolean t = bb.isGB(list); if (!t) { System.out.println("no GB for residue coefficients = " + list); return false; } return true; } /** * Comprehensive-Groebner system test. * @param F Groebner system. * @return true, if F is a Comprehensive-Groebner system, else false. */ // @Override public boolean isGBsys(GroebnerSystem F) { return isGBsys(0, F.list); } /** * Comprehensive-Groebner base test. * @param F Groebner system. * @return true, if F is a Comprehensive-Groebner base, else false. */ // @Override public boolean isCGB(GroebnerSystem F) { return isGB(F.getCGB()); } /** * Comprehensive-Groebner system and base test. * @param F Groebner system. * @return true, if F is a Comprehensive-Groebner system and base, else * false. */ // @Override public boolean isGB(GroebnerSystem F) { return isGBsys(0, F.list) && isGB(F.getCGB()); } /** * Comprehensive Groebner base system using pairlist class. * @param F polynomial list. * @return GBsys(F) a Comprehensive Groebner system of F. */ // @Override // @SuppressWarnings("unchecked") public GroebnerSystem GBsys(List>> F) { if (F == null) { return null; } List> CSp = new ArrayList>(); if (F.size() == 0) { return new GroebnerSystem(CSp); } // extract coefficient factory GenPolynomial> f = F.get(0); GenPolynomialRing> fac = f.ring; // determine polynomials List> CS = cred.determine(F); // System.out.println("CS = " + CS); // CS.remove(0); // empty colored system if (logger.isInfoEnabled()) { logger.info("determined polynomials =\n" + CS); } // setup pair lists List> CSs = new ArrayList>(); ColoredSystem css; for (ColoredSystem cs : CS) { OrderedCPairlist pairlist = new OrderedCPairlist(fac); for (ColorPolynomial p : cs.list) { // System.out.println("p = " + p); pairlist.put(p); } css = new ColoredSystem(cs.condition, cs.list, pairlist); CSs.add(css); } // main loop List> CSb = new ArrayList>(); List> ncs; List> CSh; //, CSbh; ColoredSystem cs; List> G; OrderedCPairlist pairlist; Condition cond; int si = 0; while (CSs.size() > 0) { cs = CSs.get(0); // remove(0); si++; logger.info("poped GBsys number " + si + " with condition = " + cs.condition); logger.info("poped GBsys (remaining " + (CSs.size() - 1) + ") with pairlist = " + cs.pairlist); if (!cs.isDetermined()) { cs = cs.reDetermine(); } pairlist = cs.pairlist; G = cs.list; cond = cs.condition; // logger.info( pairlist.toString() ); CPair pair; ColorPolynomial pi; ColorPolynomial pj; ColorPolynomial S; // GenPolynomial> H; ColorPolynomial H; while (pairlist.hasNext()) { pair = pairlist.removeNext(); if (pair == null) continue; pi = pair.pi; pj = pair.pj; if (debug) { logger.info("pi = " + pi); logger.info("pj = " + pj); } S = cred.SPolynomial(pi, pj); if (S.isZERO()) { pair.setZero(); continue; } if (debug) { // logger.info("ht(S) = " + S.leadingExpVector() ); logger.info("S = " + S); } H = cred.normalform(cond, G, S); if (H.isZERO()) { pair.setZero(); continue; } if (debug) { logger.info("ht(H) = " + H.leadingExpVector()); } H = H.abs(); if (debug) { logger.debug("H = " + H); } logger.info("H = " + H); if (!H.isZERO()) { //CSh = new ArrayList>(); ncs = determineAddPairs(cs, H); if (ncs.size() == 0) { continue; } cs = ncs.remove(0); // remove other? pairlist = cs.pairlist; G = cs.list; cond = cs.condition; logger.info("replaced main branch = " + cond); logger.info("#new systems = " + ncs.size()); int yi = CSs.size(); for (ColoredSystem x : ncs) { if (!x.isDetermined()) { x = x.reDetermine(); } CSs = x.addToList(CSs); } logger.info("#new systems added = " + (CSs.size() - yi)); } } // all s-pols reduce to zero in this branch if (!cs.isDetermined()) { cs = cs.reDetermine(); } CSb.add(cs); CSs.remove(0); logger.info("done with = " + cs.condition); } // all branches done CSh = new ArrayList>(); for (ColoredSystem x : CSb) { // System.out.println("G = " + x.list ); if (!x.isDetermined()) { x = x.reDetermine(); } cs = minimalGB(x); // System.out.println("min(G) = " + cs.list ); if (!cs.isDetermined()) { cs = cs.reDetermine(); } // cs = new ColoredSystem( x.condition, G, x.pairlist ); CSh.add(cs); logger.info("#sequential done = " + x.condition); logger.info(x.pairlist.toString()); } CSb = new ArrayList>(CSh); return new GroebnerSystem(CSb); } /** * Determine polynomial relative to a condition of a colored system and add * pairs. * @param cs a colored system. * @param A color polynomial. * @return list of colored systems, the conditions extending the condition * of cs. */ public List> determineAddPairs(ColoredSystem cs, ColorPolynomial A) { List> NCS = new ArrayList>(); if (A == null || A.isZERO()) { // NCS.add( cs ); return NCS; } List> S = cs.list; Condition cond = cs.condition; // .clone(); done in Condition // itself OrderedCPairlist pl = cs.pairlist; List> Sp; ColorPolynomial nz; ColoredSystem NS; // if ( A.isDetermined() ) { ... } // dont use this // System.out.println("to determine = " + A); GenPolynomial> Ap = A.getPolynomial(); List> cd = cred.caseDistinction(cond, Ap); logger.info("# cases = " + cd.size()); for (Condition cnd : cd) { //nz = cnd.determine(Ap); nz = cnd.reDetermine(A); if (nz.isZERO()) { logger.info("zero determined nz = " + nz); Sp = new ArrayList>(S); OrderedCPairlist PL = pl.copy(); NS = new ColoredSystem(cnd, Sp, PL); try { if (!NS.isDetermined()) { NS = NS.reDetermine(); } } catch (RuntimeException e) { System.out.println("Contradiction in NS_0 = " + NS); //e.printStackTrace(); continue; } NCS = NS.addToList(NCS); continue; } if (S.contains(nz)) { System.out.println("*** S.contains(nz) ***"); continue; } logger.info("new determined nz = " + nz); Sp = new ArrayList>(S); Sp.add(nz); OrderedCPairlist PL = pl.copy(); PL.put(nz); NS = new ColoredSystem(cnd, Sp, PL); try { if (!NS.isDetermined()) { NS = NS.reDetermine(); } } catch (RuntimeException e) { System.out.println("Contradiction in NS = " + NS); //e.printStackTrace(); continue; } NCS = NS.addToList(NCS); } // System.out.println("new determination = " + NCS); return NCS; } /** * Comprehensive Groebner base via Groebner system. * @param F polynomial list. * @return GB(F) a Comprehensive Groebner base of F. */ // @Override // @SuppressWarnings("unchecked") public List>> GB(List>> F) { if (F == null) { return F; } // compute Groebner system GroebnerSystem gs = GBsys(F); // System.out.println("\n\nGBsys = " + gs); return gs.getCGB(); } /** * Minimal ordered Groebner basis. * @param cs colored system. * @return a reduced Groebner base of Gp. */ // @Override public ColoredSystem minimalGB(ColoredSystem cs) { // List> Gp ) { if (cs == null || cs.list == null || cs.list.size() <= 1) { return cs; } // remove zero polynomials List> G = new ArrayList>(cs.list.size()); for (ColorPolynomial a : cs.list) { if (a != null && !a.isZERO()) { // always true in GB() // already positive a = a.abs(); G.add(a); } } if (G.size() <= 1) { return new ColoredSystem(cs.condition, G, cs.pairlist); } // System.out.println("G check " + G); // remove top reducible polynomials Condition cond = cs.condition; ColorPolynomial a, b; List> F; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); b = a; // System.out.println("check " + b); //if (false) { // if (a.red.leadingBaseCoefficient().isConstant()) { // dont drop // // these // F.add(a); // continue; // } //} if (cred.isTopReducible(G, a) || cred.isTopReducible(F, a)) { // drop polynomial if (debug) { // System.out.println("trying to drop " + a); List> ff; ff = new ArrayList>(G); ff.addAll(F); a = cred.normalform(cond, ff, a); try { a = cond.reDetermine(a); } catch (RuntimeException ignored) { } if (!a.isZERO()) { logger.error("nf(a) != 0 " + b + ", " + a); F.add(b); } } } else { F.add(a); } } G = F; if (G.size() <= 1) { return new ColoredSystem(cs.condition, G, cs.pairlist); } Collections.reverse(G); // important for lex GB // reduce remaining polynomials int len = G.size(); int i = 0; while (i < len) { a = G.remove(0); b = a; ExpVector e = a.red.leadingExpVector(); // System.out.println("reducing " + a); a = cred.normalform(cond, G, a); // unchanged by top reduction // System.out.println("reduced " + a); try { a = cond.reDetermine(a); } catch (RuntimeException ignored) { } ExpVector f = a.red.leadingExpVector(); // a = ##engine.basePrimitivePart(a); //a.monic(); was not required // a = a.abs(); // a = red.normalform( F, a ); if (e.equals(f)) { G.add(a); // adds as last } else { // should not happen if (debug) { logger.error("nf(a) not determined " + b + ", " + a); } G.add(b); // adds as last } i++; } return new ColoredSystem(cs.condition, G, cs.pairlist); } } jas-2.5/src/edu/jas/application/IdealWithRealAlgebraicRoots.java0000644000175000017500000001005512004024570025124 0ustar giovannigiovanni/* * $Id: IdealWithRealAlgebraicRoots.java 4050 2012-07-25 17:14:32Z kredel $ */ package edu.jas.application; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import edu.jas.arith.BigDecimal; import edu.jas.arith.Rational; import edu.jas.poly.GenPolynomial; import edu.jas.root.RealAlgebraicNumber; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; /** * Container for Ideals together with univariate polynomials and real algebraic * roots. * @author Heinz Kredel */ public class IdealWithRealAlgebraicRoots & Rational> extends IdealWithUniv { /** * The list of real algebraic roots. */ public final List>> ran; /** * The list of decimal approximations of the real algebraic roots. */ protected List> droots = null; /** * Constructor not for use. */ protected IdealWithRealAlgebraicRoots() { throw new IllegalArgumentException("do not use this constructor"); } /** * Constructor. * @param id the ideal * @param up the list of univaraite polynomials * @param rr the list of real algebraic roots */ public IdealWithRealAlgebraicRoots(Ideal id, List> up, List>> rr) { super(id, up); ran = rr; } /** * Constructor. * @param iu the ideal with univariate polynomials * @param rr the list of real algebraic roots */ public IdealWithRealAlgebraicRoots(IdealWithUniv iu, List>> rr) { super(iu.ideal, iu.upolys); ran = rr; } /** * String representation of the ideal. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(super.toString() + "\nreal roots:\n"); sb.append("["); boolean f1 = true; for (List> lr : ran) { if (!f1) { sb.append(", "); } else { f1 = false; } sb.append("["); boolean f2 = true; for (RealAlgebraicNumber rr : lr) { if (!f2) { sb.append(", "); } else { f2 = false; } sb.append(rr.ring.toScript()); } sb.append("]"); } sb.append("]"); if (droots != null) { sb.append("\ndecimal real root approximation:\n"); for (List d : droots) { sb.append(d.toString()); sb.append("\n"); } } return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ @Override public String toScript() { // Python case return super.toScript() + ", " + ran.toString(); } /** * Get decimal approximation of the real root tuples. */ public synchronized List> decimalApproximation() { if (this.droots != null) { return droots; } List> rroots = new ArrayList>(); for (List> rri : this.ran) { List r = new ArrayList(); for (RealAlgebraicNumber rr : rri) { BigDecimal d = new BigDecimal(rr.magnitude()); r.add(d); } rroots.add(r); } droots = rroots; return rroots; } /** * compute decimal approximation of the real root tuples. */ public void doDecimalApproximation() { List> unused = decimalApproximation(); if ( unused.isEmpty() ) { // use for findbugs System.out.println("unused is empty"); } return; } } jas-2.5/src/edu/jas/application/PrimitiveElement.java0000644000175000017500000000572411402425234023121 0ustar giovannigiovanni/* * $Id: PrimitiveElement.java 3169 2010-06-05 10:44:44Z kredel $ */ package edu.jas.application; import java.io.Serializable; import edu.jas.structure.GcdRingElem; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; /** * Container for primitive elements. * @author Heinz Kredel */ public class PrimitiveElement> implements Serializable { /** * The primitive element. */ public final AlgebraicNumberRing primitiveElem; /** * The representation of the first algebraic element in the new ring. */ public final AlgebraicNumber A; /** * The representation of the second algebraic element in the new ring. */ public final AlgebraicNumber B; /** * The first algebraic ring. */ public final AlgebraicNumberRing Aring; /** * The second algebraic ring. */ public final AlgebraicNumberRing Bring; /** * Constructor not for use. */ protected PrimitiveElement() { throw new IllegalArgumentException("do not use this constructor"); } /** * Constructor. * @param pe the primitive element * @param A the first element. * @param B the second element. */ protected PrimitiveElement(AlgebraicNumberRing pe, AlgebraicNumber A, AlgebraicNumber B) { this(pe, A, B, null, null); } /** * Constructor. * @param pe the primitive element * @param A the first element. * @param B the second element. */ protected PrimitiveElement(AlgebraicNumberRing pe, AlgebraicNumber A, AlgebraicNumber B, AlgebraicNumberRing ar, AlgebraicNumberRing br ) { primitiveElem = pe; this.A = A; this.B = B; this.Aring = ar; this.Bring = br; } /** * String representation of the ideal. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer("["); s.append(primitiveElem.toString()); s.append(", " + A.toString()); s.append(", " + B.toString()); if (Aring != null) { s.append(", " + Aring.toString()); } if (Bring != null) { s.append(", " + Bring.toString()); } return s + "]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ public String toScript() { // Python case StringBuffer s = new StringBuffer("("); s.append(primitiveElem.toScript()); s.append(", " + A.toScript()); s.append(", " + B.toScript()); if (Aring != null) { s.append(", " + Aring.toScript()); } if (Bring != null) { s.append(", " + Bring.toScript()); } return s + ")"; } } jas-2.5/src/edu/jas/application/Residue.java0000644000175000017500000002217312137717062021245 0ustar giovannigiovanni/* * $Id: Residue.java 4407 2013-04-30 10:34:27Z kredel $ */ package edu.jas.application; import edu.jas.kern.PrettyPrint; import edu.jas.poly.GenPolynomial; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; /** * Residue ring element based on GenPolynomial with RingElem interface. Objects * of this class are (nearly) immutable. * @author Heinz Kredel */ public class Residue> implements GcdRingElem> { /** * Residue class factory data structure. */ public final ResidueRing ring; /** * Value part of the element data structure. */ public final GenPolynomial val; /** * Flag to remember if this residue element is a unit. -1 is unknown, 1 is * unit, 0 not a unit. */ protected int isunit = -1; // initially unknown /** * The constructor creates a Residue object from a ring factory. * @param r residue ring factory. */ public Residue(ResidueRing r) { this(r, r.ring.getZERO(), 0); } /** * The constructor creates a Residue object from a ring factory and a * polynomial. * @param r residue ring factory. * @param a polynomial. */ public Residue(ResidueRing r, GenPolynomial a) { this(r, a, -1); } /** * The constructor creates a Residue object from a ring factory, a * polynomial and an indicator if a is a unit. * @param r residue ring factory. * @param a polynomial. * @param u isunit indicator, -1, 0, 1. */ public Residue(ResidueRing r, GenPolynomial a, int u) { ring = r; val = ring.ideal.normalform(a); //.monic() no go if ( u == 0 || u == 1 ) { isunit = u; return; } if (val.isZERO()) { isunit = 0; return; } if ( val.isUnit() ) { isunit = 1; //} else { // not possible //isunit = 0; } isunit = -1; } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public ResidueRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public Residue copy() { return new Residue(ring, val, isunit); } /** * Is Residue zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return val.isZERO(); } /** * Is Residue one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return val.isONE(); } /** * Is Residue unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (isunit > 0) { return true; } if (isunit == 0) { return false; } // not jet known boolean u = ring.ideal.isUnit(val); if (u) { isunit = 1; } else { isunit = 0; } return (u); } /** * Is Residue a constant. * @return true if this.val is a constant polynomial, else false. */ public boolean isConstant() { return val.isConstant(); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { if (PrettyPrint.isTrue()) { return val.toString(ring.ring.getVars()); } return "Residue[ " + val.toString() + " mod " + ring.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return val.toScript(); // return "PolyResidue( " + val.toScript() // + ", " + ring.toScript() + " )"; } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Residue comparison. * @param b Residue. * @return sign(this-b), 0 means that this and b are equivalent in this * residue class ring. */ //JAVA6only: @Override public int compareTo(Residue b) { GenPolynomial v = b.val; if (!ring.equals(b.ring)) { v = ring.ideal.normalform(v); } return val.compareTo(v); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) * @return true means that this and b are equivalent in this residue class * ring. */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof Residue)) { return false; } Residue a = null; try { a = (Residue) b; } catch (ClassCastException e) { } if (a == null) { return false; } return compareTo(a) == 0; } /** * Hash code for this residue. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + val.hashCode(); return h; } /** * Residue absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public Residue abs() { return new Residue(ring, val.abs(), isunit); } /** * Residue summation. * @param S Residue. * @return this+S. */ public Residue sum(Residue S) { return new Residue(ring, val.sum(S.val)); } /** * Residue negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public Residue negate() { return new Residue(ring, val.negate(), isunit); } /** * Residue signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { return val.signum(); } /** * Residue subtraction. * @param S Residue. * @return this-S. */ public Residue subtract(Residue S) { return new Residue(ring, val.subtract(S.val)); } /** * Residue division. * @param S Residue. * @return this/S. */ public Residue divide(Residue S) { if (ring.isField()) { return multiply(S.inverse()); } GenPolynomial x = PolyUtil. basePseudoDivide(val, S.val); return new Residue(ring, x); } /** * Residue inverse. * @see edu.jas.structure.RingElem#inverse() * @return S with S = 1/this if defined. */ public Residue inverse() { GenPolynomial x = ring.ideal.inverse(val); return new Residue(ring, x, 1); } /** * Residue remainder. * @param S Residue. * @return this - (this/S)*S. */ public Residue remainder(Residue S) { //GenPolynomial x = val.remainder( S.val ); GenPolynomial x = PolyUtil. baseSparsePseudoRemainder(val, S.val); return new Residue(ring, x); } /** * Residue multiplication. * @param S Residue. * @return this*S. */ public Residue multiply(Residue S) { GenPolynomial x = val.multiply(S.val); int i = -1; if (isunit == 1 && S.isunit == 1) { i = 1; } else if (isunit == 0 || S.isunit == 0) { i = 0; } return new Residue(ring, x, i); } /** * Residue monic. * @return this with monic value part. */ public Residue monic() { return new Residue(ring, val.monic(), isunit); } /** * Greatest common divisor. * @param b other element. * @return gcd(this,b). */ public Residue gcd(Residue b) { GenPolynomial x = ring.engine.gcd(val, b.val); int i = -1; // gcd might become a unit if (x.isONE()) { i = 1; } else { System.out.println("Residue gcd = " + x); } if (isunit == 1 && b.isunit == 1) { i = 1; } return new Residue(ring, x, i); } /** * Extended greatest common divisor. Note: Not implemented, throws * UnsupportedOperationException. * @param b other element. * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). */ public Residue[] egcd(Residue b) { throw new UnsupportedOperationException("egcd not implemented"); } } jas-2.5/src/edu/jas/gb/0000755000175000017500000000000012140140254015045 5ustar giovannigiovannijas-2.5/src/edu/jas/gb/DGroebnerBaseSeq.java0000644000175000017500000001454612011775300021040 0ustar giovannigiovanni/* * $Id: DGroebnerBaseSeq.java 4099 2012-08-12 18:49:36Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * D-Groebner Base sequential algorithm. Implements D-Groebner bases and GB * test. Note: Minimal reduced GBs are not unique. see BWK, section 10.1. * @param coefficient type * @author Heinz Kredel */ public class DGroebnerBaseSeq> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(DGroebnerBaseSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Reduction engine. */ protected DReduction dred; // shadow super.red ?? /** * Constructor. */ public DGroebnerBaseSeq() { this(new DReductionSeq()); } /** * Constructor. * @param dred D-Reduction engine */ public DGroebnerBaseSeq(DReduction dred) { super(dred); this.dred = dred; assert this.dred == super.red; } /** * D-Groebner base test. * @param modv module variable number. * @param F polynomial list. * @return true, if F is a D-Groebner base, else false. */ @Override public boolean isGB(int modv, List> F) { GenPolynomial pi, pj, s, d; for (int i = 0; i < F.size(); i++) { pi = F.get(i); for (int j = i + 1; j < F.size(); j++) { pj = F.get(j); if (!red.moduleCriterion(modv, pi, pj)) { continue; } d = dred.GPolynomial(pi, pj); if (!d.isZERO()) { // better check for top reduction only d = red.normalform(F, d); } if (!d.isZERO()) { System.out.println("d-pol(" + i + "," + j + ") != 0: " + d); return false; } // works ok if (!red.criterion4(pi, pj)) { continue; } s = red.SPolynomial(pi, pj); if (!s.isZERO()) { s = red.normalform(F, s); } if (!s.isZERO()) { System.out.println("s-pol(" + i + "," + j + ") != 0: " + s); return false; } } } return true; } /** * D-Groebner base using pairlist class. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a D-Groebner base of F. */ public List> GB(int modv, List> F) { GenPolynomial p; List> G = new ArrayList>(); OrderedDPairlist pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (!p.isZERO()) { p = p.abs(); // not monic if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); //G.add( 0, p ); //reverse list if (pairlist == null) { pairlist = new OrderedDPairlist(modv, p.ring); } // putOne not required pairlist.put(p); } else { l--; } } if (l <= 1) { return G; // since no threads are activated } Pair pair; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial D; GenPolynomial H; //int len = G.size(); //System.out.println("len = " + len); while (pairlist.hasNext()) { pair = pairlist.removeNext(); //System.out.println("pair = " + pair); if (pair == null) continue; pi = pair.pi; pj = pair.pj; if (debug) { logger.debug("pi = " + pi); logger.debug("pj = " + pj); } // D-polynomial case ---------------------- D = dred.GPolynomial(pi, pj); //System.out.println("D_d = " + D); if (!D.isZERO() && !red.isTopReducible(G, D)) { H = red.normalform(G, D); if (H.isONE()) { G.clear(); G.add(H); return G; // since no threads are activated } if (!H.isZERO()) { logger.info("Dred = " + H); l++; G.add(H); pairlist.put(H); } } // S-polynomial case ----------------------- if (pair.getUseCriterion3() && pair.getUseCriterion4()) { S = red.SPolynomial(pi, pj); //System.out.println("S_d = " + S); if (S.isZERO()) { pair.setZero(); continue; } if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(G, S); if (H.isZERO()) { pair.setZero(); continue; } if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } if (H.isONE()) { G.clear(); G.add(H); return G; // since no threads are activated } if (logger.isDebugEnabled()) { logger.debug("H = " + H); } if (!H.isZERO()) { logger.info("Sred = " + H); //len = G.size(); l++; G.add(H); pairlist.put(H); } } } logger.debug("#sequential list = " + G.size()); G = minimalGB(G); logger.info("" + pairlist); return G; } } jas-2.5/src/edu/jas/gb/ReductionPar.java0000644000175000017500000001551012045172206020317 0ustar giovannigiovanni/* * $Id: ReductionPar.java 4281 2012-11-03 10:40:06Z kredel $ */ package edu.jas.gb; import java.util.Collection; import java.util.List; import java.util.Map; //import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.DistHashTable; /** * Polynomial Reduction parallel usable algorithm. * Implements normalform. * @param coefficient type * @author Heinz Kredel */ public class ReductionPar> extends ReductionAbstract { //private static final Logger logger = Logger.getLogger(ReductionPar.class); /** * Constructor. */ public ReductionPar() { } /** * Normalform. Allows concurrent modification of the list. * @param Ap polynomial. * @param Pp polynomial list, concurrent modification allowed. * @return nf(Ap) with respect to Pp. */ public GenPolynomial normalform(List> Pp, GenPolynomial Ap) { if ( Pp == null || Pp.isEmpty() ) { return Ap; } if ( Ap == null || Ap.isZERO() ) { return Ap; } int l; GenPolynomial[] P; synchronized (Pp) { // required, ok in dist l = Pp.size(); P = (GenPolynomial[]) new GenPolynomial[l]; //P = Pp.values().toArray(); for ( int i = 0; i < Pp.size(); i++ ) { P[i] = Pp.get(i); } } Map.Entry m; Map.Entry m1; ExpVector e; ExpVector f = null; C a; boolean mt = false; GenPolynomial Rz = Ap.ring.getZERO(); GenPolynomial R = Rz.copy(); GenPolynomial p = null; GenPolynomial Q = null; GenPolynomial S = Ap.copy(); while ( S.length() > 0 ) { if ( Pp.size() != l ) { //long t = System.currentTimeMillis(); synchronized (Pp) { // required, bad in parallel l = Pp.size(); P = (GenPolynomial[]) new GenPolynomial[ l ]; //P = Pp.toArray(); for ( int i = 0; i < Pp.size(); i++ ) { P[i] = Pp.get(i); } } //t = System.currentTimeMillis()-t; //logger.info("Pp.toArray() = " + t + " ms, size() = " + l); S = Ap.copy(); // S.add(R)? // restart reduction ? R = Rz.copy(); } m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); //System.out.println("S.e = " + e); for ( int i = 0; i < P.length ; i++ ) { p = P[i]; f = p.leadingExpVector(); if ( f != null ) { mt = e.multipleOf( f ); if ( mt ) break; } } if ( ! mt ) { //logger.debug("irred"); //R = R.sum( a, e ); //S = S.subtract( a, e ); R.doPutToMap(e,a); S.doRemoveFromMap(e,a); //System.out.println("R = " + R); } else { //logger.debug("red"); m1 = p.leadingMonomial(); e = e.subtract( f ); a = a.divide( m1.getValue() ); //Q = p.multiply( a, e ); //S = S.subtract( Q ); S = S.subtractMultiple(a,e,p); } //System.out.println("S = " + S); } return R; } /** * Normalform with recording. * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. */ public GenPolynomial normalform(List> row, List> Pp, GenPolynomial Ap) { throw new RuntimeException("normalform with recording not implemented"); } /** * Normalform. Allows concurrent modification of the DHT. * @param Ap polynomial. * @param mp a map from Integers to polynomials, e.g. a distributed hash table, concurrent modification allowed. * @return nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(Map> mp, GenPolynomial Ap) { if ( mp == null || mp.isEmpty() ) { return Ap; } if ( Ap == null || Ap.isZERO() ) { return Ap; } int l; GenPolynomial[] P; //synchronized ( mp ) { // no more required l = mp.size(); P = (GenPolynomial[]) new GenPolynomial[l]; P = mp.values().toArray(P); l = P.length; //} Map.Entry m; Map.Entry m1; ExpVector e; ExpVector f = null; C a; boolean mt = false; GenPolynomial Rz = Ap.ring.getZERO(); GenPolynomial R = Rz.copy(); GenPolynomial p = null; GenPolynomial Q = null; GenPolynomial S = Ap.copy(); while ( S.length() > 0 ) { if ( mp.size() != l ) { //long t = System.currentTimeMillis(); //synchronized ( mp ) { // no more required, ok in distributed P = mp.values().toArray(P); l = P.length; //} //t = System.currentTimeMillis()-t; //logger.info("Pp.toArray() = " + t + " ms, size() = " + l); //logger.info("Pp.toArray() size() = " + l); S = Ap.copy(); // S.add(R)? // restart reduction ? R = Rz.copy(); } m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for ( int i = 0; i < P.length ; i++ ) { p = P[i]; f = p.leadingExpVector(); if ( f != null ) { mt = e.multipleOf( f ); if ( mt ) break; } } if ( ! mt ) { //logger.debug("irred"); //R = R.sum( a, e ); //S = S.subtract( a, e ); R.doPutToMap(e,a); S.doRemoveFromMap(e,a); // System.out.println(" S = " + S); } else { //logger.debug("red"); m1 = p.leadingMonomial(); e = e.subtract( f ); a = a.divide( m1.getValue() ); //Q = p.multiply( a, e ); //S = S.subtract( Q ); S = S.subtractMultiple(a,e,p); } } return R; } } jas-2.5/src/edu/jas/gb/DReductionSeq.java0000644000175000017500000003665612004474232020446 0ustar giovannigiovanni/* * $Id: DReductionSeq.java 4059 2012-07-27 11:16:42Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.structure.RingElem; /** * Polynomial D-Reduction sequential use algorithm. Implements normalform. * @param coefficient type * @author Heinz Kredel */ public class DReductionSeq> extends ReductionAbstract implements DReduction { private static final Logger logger = Logger.getLogger(DReductionSeq.class); //private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public DReductionSeq() { } /** * Is top reducible. * @param A polynomial. * @param P polynomial list. * @return true if A is top reducible with respect to P. */ //SuppressWarnings("unchecked") // not jet working @Override public boolean isTopReducible(List> P, GenPolynomial A) { if (P == null || P.isEmpty()) { return false; } if (A == null || A.isZERO()) { return false; } boolean mt = false; ExpVector e = A.leadingExpVector(); C a = A.leadingBaseCoefficient(); for (GenPolynomial p : P) { mt = e.multipleOf(p.leadingExpVector()); if (mt) { C b = p.leadingBaseCoefficient(); C r = a.remainder(b); mt = r.isZERO(); if (mt) { return true; } } } return false; } /** * Is in Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @return true if Ap is in normalform with respect to Pp. */ @SuppressWarnings("unchecked") @Override public boolean isNormalform(List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return true; } if (Ap == null || Ap.isZERO()) { return true; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RingElem[l]; // want GenPolynomial[] p = new GenPolynomial[l]; Map.Entry m; int i; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; boolean mt = false; Map Am = Ap.getMap(); for (Map.Entry me : Am.entrySet()) { ExpVector e = me.getKey(); C a = me.getValue(); //Am.get(e); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { C r = a.remainder(lbc[i]); mt = r.isZERO(); if (mt) { return false; } } } } return true; } /** * Normalform using d-reduction. * @param Ap polynomial. * @param Pp polynomial list. * @return d-nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenPolynomial[]) new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i).abs(); } } //System.out.println("l = " + l); Map.Entry m; ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RingElem[l]; // want GenPolynomial[] p = (GenPolynomial[]) new GenPolynomial[l]; int i; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; C r = null; boolean mt = false; GenPolynomial R = Ap.ring.getZERO(); GenPolynomial Q = null; GenPolynomial S = Ap; while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { r = a.remainder(lbc[i]); mt = r.isZERO(); // && mt } if (mt) break; } if (!mt) { //logger.debug("irred"); R = R.sum(a, e); //S = S.subtract( a, e ); S = S.reductum(); //System.out.println(" S = " + S); } else { //logger.info("red div = " + e); ExpVector f = e.subtract(htl[i]); C b = a.divide(lbc[i]); R = R.sum(r, e); Q = p[i].multiply(b, f); S = S.reductum().subtract(Q.reductum()); // ok also with reductum } } return R.abs(); } /** * S-Polynomial. * @param Ap polynomial. * @param Bp polynomial. * @return spol(Ap,Bp) the S-polynomial of Ap and Bp. */ @Override public GenPolynomial SPolynomial(GenPolynomial Ap, GenPolynomial Bp) { if (logger.isInfoEnabled()) { if (Bp == null || Bp.isZERO()) { return Ap.ring.getZERO(); } if (Ap == null || Ap.isZERO()) { return Bp.ring.getZERO(); } if (!Ap.ring.equals(Bp.ring)) { logger.error("rings not equal"); } } Map.Entry ma = Ap.leadingMonomial(); Map.Entry mb = Bp.leadingMonomial(); ExpVector e = ma.getKey(); ExpVector f = mb.getKey(); ExpVector g = e.lcm(f); ExpVector e1 = g.subtract(e); ExpVector f1 = g.subtract(f); C a = ma.getValue(); C b = mb.getValue(); C c = a.gcd(b); C m = a.multiply(b); C l = m.divide(c); // = lcm(a,b) C a1 = l.divide(a); C b1 = l.divide(b); GenPolynomial App = Ap.multiply(a1, e1); GenPolynomial Bpp = Bp.multiply(b1, f1); GenPolynomial Cp = App.subtract(Bpp); return Cp; } /** * G-Polynomial. * @param Ap polynomial. * @param Bp polynomial. * @return gpol(Ap,Bp) the g-polynomial of Ap and Bp. */ public GenPolynomial GPolynomial(GenPolynomial Ap, GenPolynomial Bp) { if (logger.isInfoEnabled()) { if (Bp == null || Bp.isZERO()) { return Ap.ring.getZERO(); } if (Ap == null || Ap.isZERO()) { return Bp.ring.getZERO(); } if (!Ap.ring.equals(Bp.ring)) { logger.error("rings not equal"); } } Map.Entry ma = Ap.leadingMonomial(); Map.Entry mb = Bp.leadingMonomial(); ExpVector e = ma.getKey(); ExpVector f = mb.getKey(); ExpVector g = e.lcm(f); ExpVector e1 = g.subtract(e); ExpVector f1 = g.subtract(f); C a = ma.getValue(); C b = mb.getValue(); C[] c = a.egcd(b); //System.out.println("egcd[0] " + c[0]); GenPolynomial App = Ap.multiply(c[1], e1); GenPolynomial Bpp = Bp.multiply(c[2], f1); GenPolynomial Cp = App.sum(Bpp); return Cp; } /** * D-Polynomial with recording. * @param S recording matrix, is modified. * @param i index of Ap in basis list. * @param Ap a polynomial. * @param j index of Bp in basis list. * @param Bp a polynomial. * @return gpol(Ap, Bp), the g-Polynomial for Ap and Bp. */ public GenPolynomial GPolynomial(List> S, int i, GenPolynomial Ap, int j, GenPolynomial Bp) { throw new UnsupportedOperationException("not yet implemented"); } /** * GB criterium 4. Use only for commutative polynomial rings. This version * works also for d-Groebner bases. * @param A polynomial. * @param B polynomial. * @param e = lcm(ht(A),ht(B)) * @return true if the S-polynomial(i,j) is required, else false. */ @Override public boolean criterion4(GenPolynomial A, GenPolynomial B, ExpVector e) { if (logger.isInfoEnabled()) { if (!A.ring.equals(B.ring)) { logger.error("rings equal"); } if (A instanceof GenSolvablePolynomial || B instanceof GenSolvablePolynomial) { logger.error("GBCriterion4 not applicabable to SolvablePolynomials"); return true; } } ExpVector ei = A.leadingExpVector(); ExpVector ej = B.leadingExpVector(); ExpVector g = ei.sum(ej); // boolean t = g == e ; ExpVector h = g.subtract(e); int s = h.signum(); if (s == 0) { // disjoint ht C a = A.leadingBaseCoefficient(); C b = B.leadingBaseCoefficient(); C d = a.gcd(b); if (d.isONE()) { // disjoint hc //System.out.println("d1 = " + d + ", a = " + a + ", b = " + b); return false; // can skip pair } } return true; //! ( s == 0 ); } /** * GB criterium 4. Use only for commutative polynomial rings. This version * works also for d-Groebner bases. * @param A polynomial. * @param B polynomial. * @return true if the S-polynomial(i,j) is required, else false. */ @Override public boolean criterion4(GenPolynomial A, GenPolynomial B) { if (logger.isInfoEnabled()) { if (A instanceof GenSolvablePolynomial || B instanceof GenSolvablePolynomial) { logger.error("GBCriterion4 not applicabable to SolvablePolynomials"); return true; } } ExpVector ei = A.leadingExpVector(); ExpVector ej = B.leadingExpVector(); ExpVector g = ei.sum(ej); ExpVector e = ei.lcm(ej); // boolean t = g == e ; ExpVector h = g.subtract(e); int s = h.signum(); if (s == 0) { // disjoint ht C a = A.leadingBaseCoefficient(); C b = B.leadingBaseCoefficient(); C d = a.gcd(b); if (d.isONE()) { // disjoint hc return false; // can skip pair } } return true; //! ( s == 0 ); } /** * Normalform with recording. * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(List> row, List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } throw new UnsupportedOperationException("not yet implemented"); /* int l = Pp.size(); GenPolynomial[] P = new GenPolynomial[l]; synchronized (Pp) { //P = Pp.toArray(); for ( int i = 0; i < Pp.size(); i++ ) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[ l ]; Object[] lbc = new Object[ l ]; // want GenPolynomial[] p = new GenPolynomial[ l ]; Map.Entry m; int j = 0; int i; for ( i = 0; i < l; i++ ) { p[i] = P[i]; m = p[i].leadingMonomial(); if ( m != null ) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; boolean mt = false; GenPolynomial zero = Ap.ring.getZERO(); GenPolynomial R = Ap.ring.getZERO(); GenPolynomial fac = null; // GenPolynomial T = null; GenPolynomial Q = null; GenPolynomial S = Ap; while ( S.length() > 0 ) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for ( i = 0; i < l; i++ ) { mt = e.multipleOf( htl[i] ); if ( mt ) break; } if ( ! mt ) { //logger.debug("irred"); R = R.sum( a, e ); S = S.subtract( a, e ); // System.out.println(" S = " + S); //throw new RuntimeException("Syzygy no GB"); } else { e = e.subtract( htl[i] ); //logger.info("red div = " + e); C c = (C)lbc[i]; a = a.divide( c ); Q = p[i].multiply( a, e ); S = S.subtract( Q ); fac = row.get(i); if ( fac == null ) { fac = zero.sum( a, e ); } else { fac = fac.sum( a, e ); } row.set(i,fac); } } return R; */ } /** * Irreducible set. * @param Pp polynomial list. * @return a list P of polynomials which are in normalform wrt. P. */ @Override public List> irreducibleSet(List> Pp) { ArrayList> P = new ArrayList>(); if (Pp == null) { return null; } for (GenPolynomial a : Pp) { if (!a.isZERO()) { P.add(a); } } int l = P.size(); if (l <= 1) return P; int irr = 0; ExpVector e; ExpVector f; GenPolynomial a; logger.debug("irr = "); while (irr != l) { a = P.remove(0); e = a.leadingExpVector(); a = normalform(P, a); logger.debug(String.valueOf(irr)); if (a.isZERO()) { l--; if (l <= 1) { return P; } } else { f = a.leadingExpVector(); if (e.equals(f)) { irr++; } else { irr = 0; } P.add(a); } } //System.out.println(); return P; } } jas-2.5/src/edu/jas/gb/WordPairList.java0000644000175000017500000000356212020351336020303 0ustar giovannigiovanni/* * $Id: WordPairList.java 4150 2012-09-01 09:18:23Z kredel $ */ package edu.jas.gb; import java.util.List; import edu.jas.structure.RingElem; import edu.jas.poly.Word; import edu.jas.poly.TermOrder; import edu.jas.poly.GenWordPolynomial; import edu.jas.poly.GenWordPolynomialRing; /** * WordPair list management interface. * @author Heinz Kredel */ public interface WordPairList > { /** * Create a new WordPairList. * @param r word polynomial ring. */ public WordPairList create(GenWordPolynomialRing r); /** * toString. */ @Override public String toString(); /** * Put one Word Polynomial to the pairlist and reduction matrix. * @param p word polynomial. * @return the index of the added word polynomial. */ public int put(GenWordPolynomial p); /** * Put to ONE-Polynomial to the pairlist. * @return the index of the last polynomial. */ public int putOne(); /** * Remove the next required pair from the pairlist and reduction matrix. * Appy the criterions 3 and 4 to see if the S-polynomial is required. * @return the next pair if one exists, otherwise null. */ public WordPair removeNext(); /** * Test if there is possibly a pair in the list. * @return true if a next pair could exist, otherwise false. */ public boolean hasNext(); /** * Get the list of word polynomials. * @return the word polynomial list. */ public List> getList(); /** * Get the number of polynomials put to the pairlist. * @return the number of calls to put. */ public int putCount(); /** * Get the number of required pairs removed from the pairlist. * @return the number of non null pairs delivered. */ public int remCount(); } jas-2.5/src/edu/jas/gb/GBDistSP.java0000644000175000017500000000577212067303544017315 0ustar giovannigiovanni/* * $Id: GBDistSP.java 4334 2012-12-28 11:49:57Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.util.List; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.DistThreadPool; import edu.jas.util.RemoteExecutable; /** * Setup to run a distributed GB example. * @author Heinz Kredel * TODO: to deprecate */ public class GBDistSP> { /** * machine file to use. */ private final String mfile; /** * Number of threads to use. */ protected final int threads; /** * Server port to use. */ protected final int port; /** * GB algorithm to use. */ private final GroebnerBaseSeqPairDistributed bbd; /** * Distributed thread pool to use. */ private final DistThreadPool dtp; /** * Constructor. * @param threads number of threads respectivly processes. * @param mfile name of the machine file. * @param port for GB server. */ public GBDistSP(int threads, String mfile, int port) { this.threads = threads; if (mfile == null || mfile.length() == 0) { this.mfile = "../util/machines"; } else { this.mfile = mfile; } this.port = port; bbd = new GroebnerBaseSeqPairDistributed(threads, this.port); dtp = new DistThreadPool(threads, this.mfile); } /** * Execute a distributed GB example. Distribute clients and start master. * @param F list of polynomials * @return GB(F) a Groebner base for F. */ public List> execute(List> F) { String master = dtp.getEC().getMasterHost(); int port = dtp.getEC().getMasterPort(); GBClientSP gbc = new GBClientSP(master, port); for (int i = 0; i < threads; i++) { // schedule remote clients dtp.addJob(gbc); } // run master List> G = bbd.GB(F); return G; } /** * Terminates the distributed thread pools. * @param shutDown true, if shut-down of the remote executable servers is * requested, false, if remote executable servers stay alive. */ public void terminate(boolean shutDown) { bbd.terminate(); dtp.terminate(shutDown); } } /** * Objects of this class are to be send to a ExecutableServer. */ class GBClientSP> implements RemoteExecutable { String host; int port; /** * GBClient. * @param host * @param port */ public GBClientSP(String host, int port) { this.host = host; this.port = port; } /** * run. */ public void run() { GroebnerBaseSeqPairDistributed bbd; bbd = new GroebnerBaseSeqPairDistributed(1, null, port); try { bbd.clientPart(host); } catch (IOException ignored) { } bbd.terminate(); } } jas-2.5/src/edu/jas/gb/SolvableGroebnerBaseSeqPairParallel.java0000644000175000017500000004705412013663732024724 0ustar giovannigiovanni/* * $Id: SolvableGroebnerBaseSeqPairParallel.java 3990 2012-07-14 12:46:08Z * kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.structure.RingElem; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; /** * Solvable Groebner Base parallel algorithm. Makes some effort to produce the * same sequence of critical pairs as in the sequential version. However already * reduced pairs are not rereduced if new polynomials appear. Implements a * shared memory parallel version of Groebner bases. Threads maintain pairlist. * @param coefficient type * @author Heinz Kredel */ public class SolvableGroebnerBaseSeqPairParallel> extends SolvableGroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(SolvableGroebnerBaseSeqPairParallel.class); //private static final boolean debug = logger.isDebugEnabled(); /** * Number of threads to use. */ protected final int threads; /** * Pool of threads to use. */ protected transient final ThreadPool pool; /** * Constructor. */ public SolvableGroebnerBaseSeqPairParallel() { this(2); } /** * Constructor. * @param threads number of threads to use. */ public SolvableGroebnerBaseSeqPairParallel(int threads) { this(threads, new ThreadPool(threads)); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. */ public SolvableGroebnerBaseSeqPairParallel(int threads, ThreadPool pool) { this(threads, pool, new SolvableReductionPar()); } /** * Constructor. * @param threads number of threads to use. * @param red parallelism aware reduction engine */ public SolvableGroebnerBaseSeqPairParallel(int threads, SolvableReduction red) { this(threads, new ThreadPool(threads), red); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param sred parallelism aware reduction engine */ public SolvableGroebnerBaseSeqPairParallel(int threads, ThreadPool pool, SolvableReduction sred) { super(sred); if (!(sred instanceof SolvableReductionPar)) { logger.warn("parallel GB should use parallel aware reduction"); } if (threads < 1) { threads = 1; } this.threads = threads; this.pool = pool; } /** * Cleanup and terminate ThreadPool. */ public void terminate() { if (pool == null) { return; } pool.terminate(); } /** * Parallel Groebner base using sequential pair order class. Threads * maintain pairlist. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> leftGB(int modv, List> F) { GenSolvablePolynomial p; List> G = new ArrayList>(); CriticalPairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = (GenSolvablePolynomial) p.monic(); if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads activated jet } G.add(p); if (pairlist == null) { pairlist = new CriticalPairList(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // putOne not required pairlist.put(p); } else { l--; } } if (l <= 1) { return G; // since no threads activated jet } Terminator fin = new Terminator(threads); LeftSolvableReducerSeqPair R; for (int i = 0; i < threads; i++) { R = new LeftSolvableReducerSeqPair(fin, G, pairlist); pool.addJob(R); } fin.waitDone(); logger.debug("#parallel list = " + G.size()); G = leftMinimalGB(G); // not in this context // pool.terminate(); logger.info("" + pairlist); return G; } /** * Minimal ordered groebner basis, parallel. * @param Fp a Groebner base. * @return minimalGB(F) a minimal Groebner base of Fp. */ @Override public List> leftMinimalGB(List> Fp) { GenSolvablePolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenSolvablePolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); // no thread at this point } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } SolvableMiReducerSeqPair[] mirs = (SolvableMiReducerSeqPair[]) new SolvableMiReducerSeqPair[G .size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new SolvableMiReducerSeqPair(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } /** * Solvable Extended Groebner base using critical pair class. * @param modv module variable number. * @param F solvable polynomial list. * @return a container for an extended left Groebner base of F. */ public SolvableExtendedGB extLeftGB(int modv, List> F) { throw new UnsupportedOperationException("parallel extLeftGB not implemented"); } /** * Twosided Groebner base using pairlist class. * @param modv number of module variables. * @param Fp solvable polynomial list. * @return tsGB(Fp) a twosided Groebner base of F. */ public List> twosidedGB(int modv, List> Fp) { if (Fp == null || Fp.size() == 0) { // 0 not 1 return new ArrayList>(); } GenSolvablePolynomialRing fac = Fp.get(0).ring; // assert != null //List> X = generateUnivar( modv, Fp ); List> X = fac.univariateList(modv); //System.out.println("X univ = " + X); List> F = new ArrayList>(Fp.size() * (1 + X.size())); F.addAll(Fp); GenSolvablePolynomial p, x, q; for (int i = 0; i < Fp.size(); i++) { p = Fp.get(i); for (int j = 0; j < X.size(); j++) { x = X.get(j); q = p.multiply(x); q = sred.leftNormalform(F, q); if (!q.isZERO()) { F.add(q); } } } //System.out.println("F generated = " + F); List> G = new ArrayList>(); CriticalPairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = (GenSolvablePolynomial) p.monic(); if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); if (pairlist == null) { pairlist = new CriticalPairList(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // putOne not required pairlist.put(p); } else { l--; } } //System.out.println("G to check = " + G); if (l <= 1) { // 1 ok return G; // since no threads are activated } Terminator fin = new Terminator(threads); TwosidedSolvableReducerSeqPair R; for (int i = 0; i < threads; i++) { R = new TwosidedSolvableReducerSeqPair(fin, X, G, pairlist); pool.addJob(R); } fin.waitDone(); logger.debug("#parallel list = " + G.size()); G = leftMinimalGB(G); // not in this context // pool.terminate(); logger.info("" + pairlist); return G; } } /** * Reducing left worker threads. * @param coefficient type */ class LeftSolvableReducerSeqPair> implements Runnable { private final List> G; private final CriticalPairList pairlist; private final Terminator pool; private final SolvableReductionPar sred; private static final Logger logger = Logger.getLogger(LeftSolvableReducerSeqPair.class); private static final boolean debug = logger.isDebugEnabled(); LeftSolvableReducerSeqPair(Terminator fin, List> G, CriticalPairList L) { pool = fin; this.G = G; pairlist = L; sred = new SolvableReductionPar(); } @SuppressWarnings("unchecked") public void run() { CriticalPair pair; GenSolvablePolynomial S; GenSolvablePolynomial H; boolean set = false; int reduction = 0; int sleeps = 0; while (pairlist.hasNext() || pool.hasJobs()) { while (!pairlist.hasNext()) { pairlist.update(); // wait pool.beIdle(); set = true; try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } else { logger.debug("r"); } Thread.sleep(100); } catch (InterruptedException e) { break; } if (!pool.hasJobs()) { break; } } if (!pairlist.hasNext() && !pool.hasJobs()) { break; } if (set) { pool.notIdle(); set = false; } pair = pairlist.getNext(); if (pair == null) { pairlist.update(); continue; } if (debug) { logger.debug("pi = " + pair.pi); logger.debug("pj = " + pair.pj); } S = sred.leftSPolynomial((GenSolvablePolynomial) pair.pi, (GenSolvablePolynomial) pair.pj); if (S.isZERO()) { pairlist.record(pair, S); continue; } if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = sred.leftNormalform(G, S); //mod reduction++; if (H.isZERO()) { pairlist.record(pair, H); continue; } if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = (GenSolvablePolynomial) H.monic(); // System.out.println("H = " + H); if (H.isONE()) { // pairlist.update( pair, H ); pairlist.putOne(); // not really required synchronized (G) { G.clear(); G.add(H); } pool.allIdle(); return; } if (debug) { logger.debug("H = " + H); } synchronized (G) { G.add(H); } pairlist.update(pair, H); //pairlist.record( pair, H ); //pairlist.update(); } logger.info("terminated, done " + reduction + " reductions"); } } /** * Reducing twosided worker threads. * @param coefficient type */ class TwosidedSolvableReducerSeqPair> implements Runnable { private final List> X; private final List> G; private final CriticalPairList pairlist; private final Terminator pool; private final SolvableReductionPar sred; private static final Logger logger = Logger.getLogger(TwosidedSolvableReducerSeqPair.class); private static final boolean debug = logger.isDebugEnabled(); TwosidedSolvableReducerSeqPair(Terminator fin, List> X, List> G, CriticalPairList L) { pool = fin; this.X = X; this.G = G; pairlist = L; sred = new SolvableReductionPar(); } public void run() { GenSolvablePolynomial p, x; CriticalPair pair; GenSolvablePolynomial S; GenSolvablePolynomial H; boolean set = false; int reduction = 0; int sleeps = 0; while (pairlist.hasNext() || pool.hasJobs()) { while (!pairlist.hasNext()) { pairlist.update(); // wait pool.beIdle(); set = true; try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } else { logger.debug("r"); } Thread.sleep(50); } catch (InterruptedException e) { break; } if (!pool.hasJobs()) { break; } } if (!pairlist.hasNext() && !pool.hasJobs()) { break; } if (set) { pool.notIdle(); set = false; } pair = pairlist.getNext(); if (pair == null) { pairlist.update(); continue; } if (debug) { logger.debug("pi = " + pair.pi); logger.debug("pj = " + pair.pj); } S = sred.leftSPolynomial((GenSolvablePolynomial) pair.pi, (GenSolvablePolynomial) pair.pj); if (S.isZERO()) { pairlist.record(pair, S); continue; } if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = sred.leftNormalform(G, S); //mod reduction++; if (H.isZERO()) { pairlist.record(pair, H); continue; } if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = (GenSolvablePolynomial) H.monic(); // System.out.println("H = " + H); if (H.isONE()) { // pairlist.update( pair, H ); pairlist.putOne(); // not really required synchronized (G) { G.clear(); G.add(H); } pool.allIdle(); return; } if (debug) { logger.debug("H = " + H); } synchronized (G) { G.add(H); } pairlist.update(pair, H); for (int j = 0; j < X.size(); j++) { x = X.get(j); p = H.multiply(x); p = sred.leftNormalform(G, p); if (!p.isZERO()) { p = (GenSolvablePolynomial) p.monic(); if (p.isONE()) { synchronized (G) { G.clear(); G.add(p); } pool.allIdle(); return; } synchronized (G) { G.add(p); } pairlist.put(p); } } } logger.info("terminated, done " + reduction + " reductions"); } } /** * Reducing worker threads for minimal GB. * @param coefficient type */ class SolvableMiReducerSeqPair> implements Runnable { private final List> G; private GenSolvablePolynomial H; private final SolvableReductionPar sred; private final Semaphore done = new Semaphore(0); private static final Logger logger = Logger.getLogger(SolvableMiReducerSeqPair.class); private static final boolean debug = logger.isDebugEnabled(); SolvableMiReducerSeqPair(List> G, GenSolvablePolynomial p) { this.G = G; H = p; sred = new SolvableReductionPar(); } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenSolvablePolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException e) { } return H; } public void run() { if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = sred.leftNormalform(G, H); //mod done.release(); //done.V(); if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } jas-2.5/src/edu/jas/gb/GBDist.java0000644000175000017500000000656312067303544017051 0ustar giovannigiovanni/* * $Id: GBDist.java 4334 2012-12-28 11:49:57Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.util.List; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.DistThreadPool; import edu.jas.util.RemoteExecutable; /** * Setup to run a distributed GB example. * @author Heinz Kredel * @deprecated use GroebnerBaseDistributedEC */ @Deprecated public class GBDist> { /** * machine file to use. */ private final String mfile; /** * Number of threads to use. */ protected final int threads; /** * Server port to use. */ protected final int port; /** * GB algorithm to use. */ private final GroebnerBaseDistributed bbd; /** * Distributed thread pool to use. */ private final DistThreadPool dtp; /** * Constructor. * @param threads number of threads respectivly processes. * @param mfile name of the machine file. * @param port for GB server. */ public GBDist(int threads, String mfile, int port) { this(threads, new OrderedPairlist(), mfile, port); } /** * Constructor. * @param threads number of threads respectivly processes. * @param pl pair selection strategy * @param mfile name of the machine file. * @param port for GB server. */ public GBDist(int threads, PairList pl, String mfile, int port) { this.threads = threads; if (mfile == null || mfile.length() == 0) { this.mfile = "../util/machines"; } else { this.mfile = mfile; } this.port = port; bbd = new GroebnerBaseDistributed(threads, pl, this.port); dtp = new DistThreadPool(threads, this.mfile); // findbugs } /** * Execute a distributed GB example. Distribute clients and start master. * @param F list of polynomials * @return GB(F) a Groebner base for F. */ public List> execute(List> F) { String master = dtp.getEC().getMasterHost(); int port = dtp.getEC().getMasterPort(); GBClient gbc = new GBClient(master, port); for (int i = 0; i < threads; i++) { // schedule remote clients dtp.addJob(gbc); } // run master List> G = bbd.GB(F); return G; } /** * Terminates the distributed thread pools. * @param shutDown true, if shut-down of the remote executable servers is * requested, false, if remote executable servers stay alive. */ public void terminate(boolean shutDown) { bbd.terminate(); dtp.terminate(shutDown); } } /** * Objects of this class are to be send to a ExecutableServer. */ class GBClient> implements RemoteExecutable { String host; int port; /** * GBClient. * @param host * @param port */ public GBClient(String host, int port) { this.host = host; this.port = port; } /** * run. */ public void run() { GroebnerBaseDistributed bbd; bbd = new GroebnerBaseDistributed(1, null, null, port); try { bbd.clientPart(host); } catch (IOException ignored) { } bbd.terminate(); } } jas-2.5/src/edu/jas/gb/AbstractPair.java0000644000175000017500000000531412067303544020305 0ustar giovannigiovanni/* * $Id: AbstractPair.java 4334 2012-12-28 11:49:57Z kredel $ */ package edu.jas.gb; import java.io.Serializable; import edu.jas.structure.RingElem; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; /** * Serializable abstract subclass to hold pairs of polynomials. * @param coefficient type * @author Heinz Kredel. */ public abstract class AbstractPair > implements Serializable { public final ExpVector e; public final GenPolynomial pi; public final GenPolynomial pj; public final int i; public final int j; protected int s; /** * AbstractPair constructor. * @param a polynomial i. * @param b polynomial j. * @param i first index. * @param j second index. */ public AbstractPair(GenPolynomial a, GenPolynomial b, int i, int j) { this(a.leadingExpVector().lcm(b.leadingExpVector()),a,b,i,j); } /** * AbstractPair constructor. * @param a polynomial i. * @param b polynomial j. * @param i first index. * @param j second index. * @param s maximal index. */ public AbstractPair(GenPolynomial a, GenPolynomial b, int i, int j, int s) { this(a.leadingExpVector().lcm(b.leadingExpVector()),a,b,i,j,s); } /** * AbstractPair constructor. * @param lcm least common multiple of lt(a) and lt(b). * @param a polynomial i. * @param b polynomial j. * @param i first index. * @param j second index. */ public AbstractPair(ExpVector lcm, GenPolynomial a, GenPolynomial b, int i, int j) { this(lcm,a,b,i,j,0); } /** * AbstractPair constructor. * @param lcm least common multiple of lt(a) and lt(b). * @param a polynomial i. * @param b polynomial j. * @param i first index. * @param j second index. * @param s maximal index. */ public AbstractPair(ExpVector lcm, GenPolynomial a, GenPolynomial b, int i, int j, int s) { e = lcm; pi = a; pj = b; this.i = i; this.j = j; s = Math.max(i,s); s = Math.max(j,s); this.s = s; } /** * Set maximal index. * @param s maximal index for pair polynomials. */ public void maxIndex(int s) { s = Math.max(this.i,s); s = Math.max(this.j,s); this.s = s; } /** * toString. */ @Override public String toString() { return "pair(" + i + "," + j + "," + s + ",{" + pi.length() + "," + pj.length() + "}," + e + ")"; } } jas-2.5/src/edu/jas/gb/SolvableGroebnerBase.java0000644000175000017500000001227512136751756021771 0ustar giovannigiovanni/* * $Id: SolvableGroebnerBase.java 4385 2013-04-27 13:34:38Z kredel $ */ package edu.jas.gb; import java.util.List; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.structure.RingElem; /** * Solvable Groebner Bases interface. Defines methods for left, right and * twosided Groebner bases and left, right and twosided GB tests. * @param coefficient type * @author Heinz Kredel. */ public interface SolvableGroebnerBase> { /** * Left Groebner base test. * @param F solvable polynomial list. * @return true, if F is a left Groebner base, else false. */ public boolean isLeftGB(List> F); /** * Left Groebner base test. * @param modv number of module variables. * @param F solvable polynomial list. * @return true, if F is a left Groebner base, else false. */ public boolean isLeftGB(int modv, List> F); /** * Twosided Groebner base test. * @param Fp solvable polynomial list. * @return true, if Fp is a two-sided Groebner base, else false. */ public boolean isTwosidedGB(List> Fp); /** * Twosided Groebner base test. * @param modv number of module variables. * @param Fp solvable polynomial list. * @return true, if Fp is a two-sided Groebner base, else false. */ public boolean isTwosidedGB(int modv, List> Fp); /** * Right Groebner base test. * @param F solvable polynomial list. * @return true, if F is a right Groebner base, else false. */ public boolean isRightGB(List> F); /** * Right Groebner base test. * @param modv number of module variables. * @param F solvable polynomial list. * @return true, if F is a right Groebner base, else false. */ public boolean isRightGB(int modv, List> F); /** * Left Groebner base using pairlist class. * @param F solvable polynomial list. * @return leftGB(F) a left Groebner base of F. */ public List> leftGB(List> F); /** * Left Groebner base using pairlist class. * @param modv number of module variables. * @param F solvable polynomial list. * @return leftGB(F) a left Groebner base of F. */ public List> leftGB(int modv, List> F); /** * Solvable Extended Groebner base using critical pair class. * @param F solvable polynomial list. * @return a container for an extended left Groebner base of F. */ public SolvableExtendedGB extLeftGB(List> F); /** * Solvable Extended Groebner base using critical pair class. * @param modv module variable number. * @param F solvable polynomial list. * @return a container for an extended left Groebner base of F. */ public SolvableExtendedGB extLeftGB(int modv, List> F); /** * Left minimal ordered groebner basis. * @param Gp a left Groebner base. * @return leftGBmi(F) a minimal left Groebner base of Gp. */ public List> leftMinimalGB(List> Gp); /** * Twosided Groebner base using pairlist class. * @param Fp solvable polynomial list. * @return tsGB(Fp) a twosided Groebner base of Fp. */ public List> twosidedGB(List> Fp); /** * Twosided Groebner base using pairlist class. * @param modv number of module variables. * @param Fp solvable polynomial list. * @return tsGB(Fp) a twosided Groebner base of Fp. */ public List> twosidedGB(int modv, List> Fp); /** * Right Groebner base using opposite ring left GB. * @param F solvable polynomial list. * @return rightGB(F) a right Groebner base of F. */ public List> rightGB(List> F); /** * Right Groebner base using opposite ring left GB. * @param modv number of module variables. * @param F solvable polynomial list. * @return rightGB(F) a right Groebner base of F. */ public List> rightGB(int modv, List> F); /** * Test if left reduction matrix. * @param exgb an SolvableExtendedGB container. * @return true, if exgb contains a left reduction matrix, else false. */ public boolean isLeftReductionMatrix(SolvableExtendedGB exgb); /** * Test if left reduction matrix. * @param F a solvable polynomial list. * @param G a left Groebner base. * @param Mf a possible left reduction matrix. * @param Mg a possible left reduction matrix. * @return true, if Mg and Mf are left reduction matrices, else false. */ public boolean isLeftReductionMatrix(List> F, List> G, List>> Mf, List>> Mg); } jas-2.5/src/edu/jas/gb/SolvableExtendedGB.java0000644000175000017500000000450011506105136021355 0ustar giovannigiovanni/* * $Id: SolvableExtendedGB.java 3451 2010-12-27 12:45:18Z kredel $ */ package edu.jas.gb; import java.util.List; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingElem; /** * Container for a GB and transformation matrices. * A container for F, G, calG and calF. * Immutable objects. * @param coefficient type * @param F an ideal base. * @param G a Groebner base of F. * @param F2G a transformation matrix from F to G. * @param G2F a transformation matrix from G to F. */ public class SolvableExtendedGB> { public final List> F; public final List> G; public final List>> F2G; public final List>> G2F; public final GenSolvablePolynomialRing ring; public SolvableExtendedGB( List> F, List> G, List>> F2G, List>> G2F) { this.F = F; this.G = G; this.F2G = F2G; this.G2F = G2F; GenSolvablePolynomialRing r = null; if ( G != null ) { for ( GenSolvablePolynomial p : G ) { if ( p != null ) { r = p.ring; break; } } if ( r != null && r.getVars() == null ) { r.setVars( r.newVars("y") ); } } this.ring = r; } /** Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { PolynomialList P; ModuleList M; StringBuffer s = new StringBuffer("SolvableExtendedGB: \n\n"); P = new PolynomialList( ring, F ); s.append("F = " + P + "\n\n"); P = new PolynomialList( ring, G ); s.append("G = " + P + "\n\n"); M = new ModuleList( ring, F2G ); s.append("F2G = " + M + "\n\n"); M = new ModuleList( ring, G2F ); s.append("G2F = " + M + "\n"); return s.toString(); } } jas-2.5/src/edu/jas/gb/GBProxy.java0000644000175000017500000001115712045475720017264 0ustar giovannigiovanni/* * $Id: GBProxy.java 4289 2012-11-04 14:29:36Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import org.apache.log4j.Logger; import edu.jas.kern.ComputerThreads; import edu.jas.kern.PreemptingException; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Groebner bases parallel proxy. * @author Heinz Kredel */ public class GBProxy> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GBProxy.class); private final boolean debug = logger.isDebugEnabled(); //logger.isInfoEnabled(); /** * GB engines. */ public final GroebnerBaseAbstract e1; public final GroebnerBaseAbstract e2; /** * Thread pool. */ protected transient ExecutorService pool; /** * Proxy constructor. * @param e1 Groebner base engine. * @param e2 Groebner base engine. */ public GBProxy(GroebnerBaseAbstract e1, GroebnerBaseAbstract e2) { this.e1 = e1; this.e2 = e2; pool = ComputerThreads.getPool(); //System.out.println("pool 2 = "+pool); } /** * Get the String representation with GB engines. * @see java.lang.Object#toString() */ @Override public String toString() { return "GBProxy[ " + e1.toString() + ", " + e2.toString() + " ]"; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { e1.terminate(); e2.terminate(); } /** * Cancel ThreadPool. */ @Override public int cancel() { int s = e1.cancel(); s += e2.cancel(); return s; } /** * Groebner base. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ //JAVA6only: @Override public List> GB( final int modv, final List> F ) { if (F == null || F.isEmpty()) { return F; } // parallel case List> G = null; List>>> cs = new ArrayList>>>(2); cs.add(new Callable>>() { public List> call() { try { //System.out.println("starting e1 " + e1.getClass().getName()); List> G = e1.GB(modv,F); if (debug) { logger.info("GBProxy done e1 " + e1.getClass().getName()); } return G; } catch (PreemptingException e) { throw new RuntimeException("GBProxy e1 preempted " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GBProxy e1 " + e); logger.info("Exception GBProxy F = " + F); throw new RuntimeException("GBProxy e1 " + e); //return P.ring.getONE(); } } }); cs.add(new Callable>>() { public List> call() { try { //System.out.println("starting e2 " + e2.getClass().getName()); List> G = e2.GB(modv,F); if (debug) { logger.info("GBProxy done e2 " + e2.getClass().getName()); } return G; } catch (PreemptingException e) { throw new RuntimeException("GBProxy e2 preempted " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GBProxy e2 " + e); logger.info("Exception GBProxy F = " + F); throw new RuntimeException("GBProxy e2 " + e); //return P.ring.getONE(); } } }); try { G = pool.invokeAny(cs); } catch (InterruptedException ignored) { logger.info("InterruptedException " + ignored); Thread.currentThread().interrupt(); } catch (ExecutionException e) { logger.info("ExecutionException " + e); Thread.currentThread().interrupt(); } return G; } } jas-2.5/src/edu/jas/gb/CriticalPairComparator.java0000644000175000017500000000373212004043370022313 0ustar giovannigiovanni/* * $Id: CriticalPairComparator.java 4052 2012-07-25 19:20:25Z kredel $ */ package edu.jas.gb; import java.io.Serializable; import java.util.Comparator; import edu.jas.structure.RingElem; import edu.jas.poly.ExpVector; import edu.jas.poly.TermOrder; /** * Comparator for critical pairs of polynomials. * Immutable objects. * @param coefficient type * @author Heinz Kredel. */ public class CriticalPairComparator > implements Serializable, Comparator> { public final TermOrder tord; protected final TermOrder.EVComparator ec; /** * Constructor. * @param t TermOrder. */ public CriticalPairComparator(TermOrder t){ tord = t; ec = tord.getAscendComparator(); } /** * Compare. * Compares exponents and if equal, compares polynomial indices. * @param p1 first critical pair. * @param p2 second critical pair. * @return 0 if ( p1 == p2 ), -1 if ( p1 < p2 ) and +1 if ( p1 > p2 ). */ public int compare(AbstractPair p1, AbstractPair p2) { int s = ec.compare( p1.e, p2.e ); if ( s == 0 ) { /* not ok if ( p1.j < p2.j ) { s = -1; } else if ( p1.j > p2.j ) { s = 1; } else if ( p1.i < p2.i ) { s = -1; } else if ( p1.i > p2.i ) { s = 1; } else { s = 0; } */ /* ok */ if ( p1.j > p2.j ) { s = -1; } else if ( p1.j < p2.j ) { s = 1; } else if ( p1.i > p2.i ) { s = -1; } else if ( p1.i < p2.i ) { s = 1; } else { s = 0; } /* */ } return s; } /** * toString. */ @Override public String toString() { return "CriticalPairComparator(" + tord + ")"; } } jas-2.5/src/edu/jas/gb/package.html0000644000175000017500000000261112027161170017332 0ustar giovannigiovanni Groebner bases classes

Groebner bases package.

This package contains classes for polynomial and solvable polynomial reduction, Groebner bases and ideal arithmetic as well as thread parallel and distributed versions of Buchbergers algorithm, e.g. ReductionSeq, GroebnerBaseAbstract, GroebnerBaseSeq, GroebnerBaseParallel and GroebnerBaseDistributed. Moreover there are Groebner bases in polynomial rings over principal ideal domains and Euclidean domains, so called D- and E-Groebner bases, see DGroebnerBaseSeq and EGroebnerBaseSeq. The latest additions include free non-commutative polynomial reduction, S-polynomials and two-sided Groebner bases, see WordReductionSeq and WordGroebnerBaseSeq.


Heinz Kredel

Last modified: Fri Sep 21 21:46:36 CEST 2012

$Id: package.html 4215 2012-09-21 21:56:08Z kredel $

jas-2.5/src/edu/jas/gb/GroebnerBaseSeqPairSeq.java0000644000175000017500000002613711503377332022230 0ustar giovannigiovanni/* * $Id: GroebnerBaseSeqPairSeq.java 3414 2010-12-19 12:47:23Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.RingElem; /** * Groebner Base sequential algorithm. Implements Groebner bases and GB test. * Uses sequential pair list class. * @param coefficient type * @author Heinz Kredel */ public class GroebnerBaseSeqPairSeq> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBaseSeqPairSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public GroebnerBaseSeqPairSeq() { super(); } /** * Constructor. * @param red Reduction engine */ public GroebnerBaseSeqPairSeq(Reduction red) { super(red); } /** * Groebner base using pairlist class. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> GB(int modv, List> F) { GenPolynomial p; List> G = new ArrayList>(); CriticalPairList pairlist = null; int len = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); if (pairlist == null) { pairlist = new CriticalPairList(modv, p.ring); } // putOne not required pairlist.put(p); } else { len--; } } if (len <= 1) { return G; // since no threads are activated } CriticalPair pair; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial H; while (pairlist.hasNext()) { pair = pairlist.getNext(); if (pair == null) { pairlist.update(); // ? continue; } pi = pair.pi; pj = pair.pj; if (debug) { logger.debug("pi = " + pi); logger.debug("pj = " + pj); } S = red.SPolynomial(pi, pj); if (S.isZERO()) { pairlist.update(pair, S); continue; } if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(G, S); if (H.isZERO()) { pairlist.update(pair, H); continue; } if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = H.monic(); if (H.isONE()) { // pairlist.record( pair, H ); G.clear(); G.add(H); return G; // since no threads are activated } if (debug) { logger.debug("H = " + H); } G.add(H); pairlist.update(pair, H); //pairlist.update(); } logger.debug("#sequential list = " + G.size()); G = minimalGB(G); logger.info("" + pairlist); return G; } /** * Extended Groebner base using critical pair class. * @param modv module variable number. * @param F polynomial list. * @return a container for an extended Groebner base of F. */ @Override public ExtendedGB extGB(int modv, List> F) { List> G = new ArrayList>(); List>> F2G = new ArrayList>>(); List>> G2F = new ArrayList>>(); CriticalPairList pairlist = null; boolean oneInGB = false; int len = F.size(); List> row = null; List> rows = null; List> rowh = null; GenPolynomialRing ring = null; GenPolynomial H; GenPolynomial p; int nzlen = 0; for (GenPolynomial f : F) { if (f.length() > 0) { nzlen++; } if (ring == null) { ring = f.ring; } } GenPolynomial mone = ring.getONE(); //.negate(); int k = 0; ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { row = new ArrayList>(nzlen); for (int j = 0; j < nzlen; j++) { row.add(null); } //C c = p.leadingBaseCoefficient(); //c = c.inverse(); //p = p.multiply( c ); row.set(k, mone); //.multiply(c) ); k++; if (p.isUnit()) { G.clear(); G.add(p); G2F.clear(); G2F.add(row); oneInGB = true; break; } G.add(p); G2F.add(row); if (pairlist == null) { pairlist = new CriticalPairList(modv, p.ring); } // putOne not required pairlist.put(p); } else { len--; } } ExtendedGB exgb; if (len <= 1 || oneInGB) { // adjust F2G for (GenPolynomial f : F) { row = new ArrayList>(G.size()); for (int j = 0; j < G.size(); j++) { row.add(null); } H = red.normalform(row, G, f); if (!H.isZERO()) { logger.error("nonzero H = " + H); } F2G.add(row); } exgb = new ExtendedGB(F, G, F2G, G2F); //System.out.println("exgb 1 = " + exgb); return exgb; } CriticalPair pair; int i, j; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial x; GenPolynomial y; //GenPolynomial z; while (pairlist.hasNext() && !oneInGB) { pair = pairlist.getNext(); if (pair == null) { pairlist.update(); // ? continue; } i = pair.i; j = pair.j; pi = pair.pi; pj = pair.pj; if (debug) { logger.info("i, pi = " + i + ", " + pi); logger.info("j, pj = " + j + ", " + pj); } rows = new ArrayList>(G.size()); for (int m = 0; m < G.size(); m++) { rows.add(null); } S = red.SPolynomial(rows, i, pi, j, pj); if (debug) { logger.debug("is reduction S = " + red.isReductionNF(rows, G, ring.getZERO(), S)); } if (S.isZERO()) { pairlist.update(pair, S); // do not add to G2F continue; } if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } rowh = new ArrayList>(G.size()); for (int m = 0; m < G.size(); m++) { rowh.add(null); } H = red.normalform(rowh, G, S); if (debug) { logger.debug("is reduction H = " + red.isReductionNF(rowh, G, S, H)); } if (H.isZERO()) { pairlist.update(pair, H); // do not add to G2F continue; } if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } row = new ArrayList>(G.size() + 1); for (int m = 0; m < G.size(); m++) { x = rows.get(m); if (x != null) { //System.out.println("ms = " + m + " " + x); x = x.negate(); } y = rowh.get(m); if (y != null) { y = y.negate(); //System.out.println("mh = " + m + " " + y); } if (x == null) { x = y; } else { x = x.sum(y); } //System.out.println("mx = " + m + " " + x); row.add(x); } if (debug) { logger.debug("is reduction 0+sum(row,G) == H : " + red.isReductionNF(row, G, H, ring.getZERO())); } row.add(null); // H = H.monic(); C c = H.leadingBaseCoefficient(); c = c.inverse(); H = H.multiply(c); row = blas.scalarProduct(mone.multiply(c), row); row.set(G.size(), mone); if (H.isONE()) { // pairlist.record( pair, H ); // G.clear(); G.add(H); G2F.add(row); oneInGB = true; break; } if (debug) { logger.debug("H = " + H); } G.add(H); pairlist.update(pair, H); G2F.add(row); } if (debug) { exgb = new ExtendedGB(F, G, F2G, G2F); logger.info("exgb unnorm = " + exgb); } G2F = normalizeMatrix(F.size(), G2F); if (debug) { exgb = new ExtendedGB(F, G, F2G, G2F); logger.info("exgb nonmin = " + exgb); boolean t2 = isReductionMatrix(exgb); logger.info("exgb t2 = " + t2); } exgb = minimalExtendedGB(F.size(), G, G2F); G = exgb.G; G2F = exgb.G2F; logger.debug("#sequential list = " + G.size()); logger.info("" + pairlist); // setup matrices F and F2G for (GenPolynomial f : F) { row = new ArrayList>(G.size()); for (int m = 0; m < G.size(); m++) { row.add(null); } H = red.normalform(row, G, f); if (!H.isZERO()) { logger.error("nonzero H = " + H); } F2G.add(row); } exgb = new ExtendedGB(F, G, F2G, G2F); if (debug) { logger.info("exgb nonmin = " + exgb); boolean t2 = isReductionMatrix(exgb); logger.info("exgb t2 = " + t2); } return exgb; } } jas-2.5/src/edu/jas/gb/GroebnerBaseAbstract.java0000644000175000017500000006463312136751756021772 0ustar giovannigiovanni/* * $Id: GroebnerBaseAbstract.java 4385 2013-04-27 13:34:38Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.vector.BasicLinAlg; /** * Groebner Bases abstract class. Implements common Groebner bases and GB test * methods. * @param coefficient type * @author Heinz Kredel * * @see edu.jas.application.GBAlgorithmBuilder * @see edu.jas.gbufd.GBFactory */ public abstract class GroebnerBaseAbstract> implements GroebnerBase { private static final Logger logger = Logger.getLogger(GroebnerBaseAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Reduction engine. */ public final Reduction red; /** * Strategy for pair selection. */ public final PairList strategy; /** * linear algebra engine. */ public final BasicLinAlg> blas; /** * Constructor. */ public GroebnerBaseAbstract() { this(new ReductionSeq()); } /** * Constructor. * @param red Reduction engine */ public GroebnerBaseAbstract(Reduction red) { this(red, new OrderedPairlist()); } /** * Constructor. * @param pl pair selection strategy */ public GroebnerBaseAbstract(PairList pl) { this(new ReductionSeq(), pl); } /** * Constructor. * @param red Reduction engine * @param pl pair selection strategy */ public GroebnerBaseAbstract(Reduction red, PairList pl) { if (red == null) { red = new ReductionSeq(); } this.red = red; if (pl == null) { pl = new OrderedPairlist(); } this.strategy = pl; blas = new BasicLinAlg>(); } /** * Get the String representation with GB engines. * @see java.lang.Object#toString() */ @Override public String toString() { return this.getClass().getSimpleName(); } /** * Groebner base test. * @param F polynomial list. * @return true, if F is a Groebner base, else false. */ public boolean isGB(List> F) { return isGB(0, F); } /** * Groebner base test. * @param modv module variable number. * @param F polynomial list. * @return true, if F is a Groebner base, else false. */ public boolean isGB(int modv, List> F) { return isGB(modv, F, true); } /** * Groebner base test. * @param F polynomial list. * @param b true for simple test, false for GB test. * @return true, if F is a Groebner base, else false. */ public boolean isGB(List> F, boolean b) { return isGB(0, F, b); } /** * Groebner base test. * @param modv module variable number. * @param F polynomial list. * @param b true for simple test, false for GB test. * @return true, if F is a Groebner base, else false. */ public boolean isGB(int modv, List> F, boolean b) { if (b) { return isGBsimple(modv, F); } return isGBidem(modv, F); } /** * Groebner base simple test. * @param modv module variable number. * @param F polynomial list. * @return true, if F is a Groebner base, else false. */ public boolean isGBsimple(int modv, List> F) { if (F == null || F.isEmpty()) { return true; } GenPolynomial pi, pj, s, h; ExpVector ei, ej, eij; for (int i = 0; i < F.size(); i++) { pi = F.get(i); ei = pi.leadingExpVector(); for (int j = i + 1; j < F.size(); j++) { pj = F.get(j); ej = pj.leadingExpVector(); if (!red.moduleCriterion(modv, ei, ej)) { continue; } eij = ei.lcm(ej); if (!red.criterion4(ei, ej, eij)) { continue; } if (!criterion3(i, j, eij, F)) { continue; } s = red.SPolynomial(pi, pj); if (s.isZERO()) { continue; } //System.out.println("i, j = " + i + ", " + j); h = red.normalform(F, s); if (!h.isZERO()) { logger.info("no GB: pi = " + pi + ", pj = " + pj); logger.info("s = " + s + ", h = " + h); return false; } } } return true; } /** * GB criterium 3. * @return true if the S-polynomial(i,j) is required. */ boolean criterion3(int i, int j, ExpVector eij, List> P) { assert i < j; //for ( int k = 0; k < P.size(); k++ ) { // not of much use for (int k = 0; k < i; k++) { GenPolynomial A = P.get(k); ExpVector ek = A.leadingExpVector(); if (eij.multipleOf(ek)) { return false; } } return true; } /** * Groebner base idempotence test. * @param modv module variable number. * @param F polynomial list. * @return true, if F is equal to GB(F), else false. */ public boolean isGBidem(int modv, List> F) { if (F == null || F.isEmpty()) { return true; } GenPolynomialRing pring = F.get(0).ring; List> G = GB(modv, F); PolynomialList Fp = new PolynomialList(pring, F); PolynomialList Gp = new PolynomialList(pring, G); return Fp.compareTo(Gp) == 0; } /** * Common zero test. * @param F polynomial list. * @return -1, 0 or 1 if dimension(ideal(F)) &eq; -1, 0 or ≥ 1. */ public int commonZeroTest(List> F) { if (F == null || F.isEmpty()) { return 1; } GenPolynomialRing pfac = F.get(0).ring; if (pfac.nvar <= 0) { return -1; } //int uht = 0; Set v = new HashSet(); // for non reduced GBs for (GenPolynomial p : F) { if (p.isZERO()) { continue; } if (p.isConstant()) { // for non-monic lists return -1; } ExpVector e = p.leadingExpVector(); if (e == null) { continue; } int[] u = e.dependencyOnVariables(); if (u == null) { continue; } if (u.length == 1) { //uht++; v.add(u[0]); } } if (pfac.nvar == v.size()) { return 0; } return 1; } /** * Groebner base using pairlist class. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> GB(List> F) { return GB(0, F); } /** * Extended Groebner base using critical pair class. * @param F polynomial list. * @return a container for a Groebner base G of F together with * back-and-forth transformations. */ public ExtendedGB extGB(List> F) { return extGB(0, F); } /** * Extended Groebner base using critical pair class. * @param modv module variable number. * @param F polynomial list. * @return a container for a Groebner base G of F together with * back-and-forth transformations. */ public ExtendedGB extGB(int modv, List> F) { throw new UnsupportedOperationException("extGB not implemented in " + this.getClass().getSimpleName()); } /** * Minimal ordered Groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. */ public List> minimalGB(List> Gp) { if (Gp == null || Gp.size() <= 1) { return Gp; } // remove zero polynomials List> G = new ArrayList>(Gp.size()); for (GenPolynomial a : Gp) { if (a != null && !a.isZERO()) { // always true in GB() // already positive a = a.abs(); G.add(a); } } if (G.size() <= 1) { return G; } // remove top reducible polynomials GenPolynomial a; List> F; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { // drop polynomial if (debug) { System.out.println("dropped " + a); List> ff; ff = new ArrayList>(G); ff.addAll(F); a = red.normalform(ff, a); if (!a.isZERO()) { System.out.println("error, nf(a) " + a); } } } else { F.add(a); } } G = F; if (G.size() <= 1) { return G; } // reduce remaining polynomials Collections.reverse(G); // important for lex GB int len = G.size(); if (debug) { System.out.println("#G " + len); for (GenPolynomial aa : G) { System.out.println("aa = " + aa.length() + ", lt = " + aa.getMap().keySet()); } } int i = 0; while (i < len) { a = G.remove(0); if (debug) { System.out.println("doing " + a.length() + ", lt = " + a.leadingExpVector()); } a = red.normalform(G, a); G.add(a); // adds as last i++; } return G; } /** * Test for minimal ordered Groebner basis. * @param Gp an ideal base. * @return true, if Gp is a reduced minimal Groebner base. */ public boolean isMinimalGB(List> Gp) { if (Gp == null || Gp.size() == 0) { return true; } // test for zero polynomials for (GenPolynomial a : Gp) { if (a == null || a.isZERO()) { if (debug) { logger.debug("zero polynomial " + a); } return false; } } // test for top reducible polynomials List> G = new ArrayList>(Gp); List> F = new ArrayList>(G.size()); while (G.size() > 0) { GenPolynomial a = G.remove(0); if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { if (debug) { logger.debug("top reducible polynomial " + a); } return false; } else { F.add(a); } } G = F; if (G.size() <= 1) { return true; } // test reducibility of polynomials int len = G.size(); int i = 0; while (i < len) { GenPolynomial a = G.remove(0); if (!red.isNormalform(G, a)) { if (debug) { logger.debug("reducible polynomial " + a); } return false; } G.add(a); // re-adds as last i++; } return true; } /** * Test if reduction matrix. * @param exgb an ExtendedGB container. * @return true, if exgb contains a reduction matrix, else false. */ public boolean isReductionMatrix(ExtendedGB exgb) { if (exgb == null) { return true; } return isReductionMatrix(exgb.F, exgb.G, exgb.F2G, exgb.G2F); } /** * Test if reduction matrix. * @param F a polynomial list. * @param G a Groebner base. * @param Mf a possible reduction matrix. * @param Mg a possible reduction matrix. * @return true, if Mg and Mf are reduction matrices, else false. */ public boolean isReductionMatrix(List> F, List> G, List>> Mf, List>> Mg) { // no more check G and Mg: G * Mg[i] == 0 // check F and Mg: F * Mg[i] == G[i] int k = 0; for (List> row : Mg) { boolean t = red.isReductionNF(row, F, G.get(k), null); if (!t) { logger.error("F isReductionMatrix s, k = " + F.size() + ", " + k); return false; } k++; } // check G and Mf: G * Mf[i] == F[i] k = 0; for (List> row : Mf) { boolean t = red.isReductionNF(row, G, F.get(k), null); if (!t) { logger.error("G isReductionMatrix s, k = " + G.size() + ", " + k); return false; } k++; } return true; } /** * Normalize M. Make all rows the same size and make certain column elements * zero. * @param M a reduction matrix. * @return normalized M. */ public List>> normalizeMatrix(int flen, List>> M) { if (M == null) { return M; } if (M.size() == 0) { return M; } List>> N = new ArrayList>>(); List>> K = new ArrayList>>(); int len = M.get(M.size() - 1).size(); // longest row // pad / extend rows for (List> row : M) { List> nrow = new ArrayList>(row); for (int i = row.size(); i < len; i++) { nrow.add(null); } N.add(nrow); } // System.out.println("norm N fill = " + N); // make zero columns int k = flen; for (int i = 0; i < N.size(); i++) { // 0 List> row = N.get(i); if (debug) { logger.info("row = " + row); } K.add(row); if (i < flen) { // skip identity part continue; } List> xrow; GenPolynomial a; //System.out.println("norm i = " + i); for (int j = i + 1; j < N.size(); j++) { List> nrow = N.get(j); //System.out.println("nrow j = " +j + ", " + nrow); if (k < nrow.size()) { // always true a = nrow.get(k); //System.out.println("k, a = " + k + ", " + a); if (a != null && !a.isZERO()) { xrow = blas.scalarProduct(a, row); xrow = blas.vectorAdd(xrow, nrow); //System.out.println("xrow = " + xrow); N.set(j, xrow); } } } k++; } //System.out.println("norm K reduc = " + K); // truncate N.clear(); for (List> row : K) { List> tr = new ArrayList>(); for (int i = 0; i < flen; i++) { tr.add(row.get(i)); } N.add(tr); } K = N; //System.out.println("norm K trunc = " + K); return K; } /** * Minimal extended groebner basis. * @param Gp a Groebner base. * @param M a reduction matrix, is modified. * @return a (partially) reduced Groebner base of Gp in a container. */ public ExtendedGB minimalExtendedGB(int flen, List> Gp, List>> M) { if (Gp == null) { return null; //new ExtendedGB(null,Gp,null,M); } if (Gp.size() <= 1) { return new ExtendedGB(null, Gp, null, M); } List> G; List> F; G = new ArrayList>(Gp); F = new ArrayList>(Gp.size()); List>> Mg; List>> Mf; Mg = new ArrayList>>(M.size()); Mf = new ArrayList>>(M.size()); List> row; for (List> r : M) { // must be copied also row = new ArrayList>(r); Mg.add(row); } row = null; GenPolynomial a; ExpVector e; ExpVector f; GenPolynomial p; boolean mt; ListIterator> it; ArrayList ix = new ArrayList(); ArrayList jx = new ArrayList(); int k = 0; //System.out.println("flen, Gp, M = " + flen + ", " + Gp.size() + ", " + M.size() ); while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } //System.out.println("k, mt = " + k + ", " + mt); if (!mt) { F.add(a); ix.add(k); } else { // drop polynomial and corresponding row and column // F.add( a.ring.getZERO() ); jx.add(k); } k++; } if (debug) { logger.debug("ix, #M, jx = " + ix + ", " + Mg.size() + ", " + jx); } int fix = -1; // copied polys // copy Mg to Mf as indicated by ix for (int i = 0; i < ix.size(); i++) { int u = ix.get(i); if (u >= flen && fix == -1) { fix = Mf.size(); } //System.out.println("copy u, fix = " + u + ", " + fix); if (u >= 0) { row = Mg.get(u); Mf.add(row); } } if (F.size() <= 1 || fix == -1) { return new ExtendedGB(null, F, null, Mf); } // must return, since extended normalform has not correct order of polys /* G = F; F = new ArrayList>( G.size() ); List> temp; k = 0; final int len = G.size(); while ( G.size() > 0 ) { a = G.remove(0); if ( k >= fix ) { // dont touch copied polys row = Mf.get( k ); //System.out.println("doing k = " + k + ", " + a); // must keep order, but removed polys missing temp = new ArrayList>( len ); temp.addAll( F ); temp.add( a.ring.getZERO() ); // ?? temp.addAll( G ); //System.out.println("row before = " + row); a = red.normalform( row, temp, a ); //System.out.println("row after = " + row); } F.add( a ); k++; } // does Mf need renormalization? */ return new ExtendedGB(null, F, null, Mf); } /** * Univariate head term degrees. * @param A list of polynomials. * @return a list of the degrees of univariate head terms. */ public List univariateDegrees(List> A) { List ud = new ArrayList(); if (A == null || A.size() == 0) { return ud; } GenPolynomialRing pfac = A.get(0).ring; if (pfac.nvar <= 0) { return ud; } //int uht = 0; Map v = new TreeMap(); // for non reduced GBs for (GenPolynomial p : A) { ExpVector e = p.leadingExpVector(); if (e == null) { continue; } int[] u = e.dependencyOnVariables(); if (u == null) { continue; } if (u.length == 1) { //uht++; Long d = v.get(u[0]); if (d == null) { v.put(u[0], e.getVal(u[0])); } } } for (int i = 0; i < pfac.nvar; i++) { Long d = v.get(i); ud.add(d); } //Collections.reverse(ud); return ud; } /** * Construct univariate polynomial of minimal degree in variable i of a zero * dimensional ideal(G). * @param i variable index. * @param G list of polynomials, a monic reduced Gröbner base of a zero * dimensional ideal. * @return univariate polynomial of minimal degree in variable i in ideal(G) */ public GenPolynomial constructUnivariate(int i, List> G) { if (G == null || G.size() == 0) { throw new IllegalArgumentException("G may not be null or empty"); } List ud = univariateDegrees(G); if (ud.size() <= i) { //logger.info("univ pol, ud = " + ud); throw new IllegalArgumentException("ideal(G) not zero dimensional " + ud); } int ll = 0; Long di = ud.get(i); if (di != null) { ll = (int) (long) di; } else { throw new IllegalArgumentException("ideal(G) not zero dimensional"); } long vsdim = 1; for (Long d : ud) { if (d != null) { vsdim *= d; } } logger.info("univariate construction, deg = " + ll + ", vsdim = " + vsdim); GenPolynomialRing pfac = G.get(0).ring; RingFactory cfac = pfac.coFac; String var = pfac.getVars()[pfac.nvar - 1 - i]; GenPolynomialRing ufac = new GenPolynomialRing(cfac, 1, new TermOrder(TermOrder.INVLEX), new String[] { var }); GenPolynomialRing cpfac = new GenPolynomialRing(cfac, ll, new TermOrder(TermOrder.INVLEX)); GenPolynomialRing> rfac = new GenPolynomialRing>(cpfac, pfac); GenPolynomial> P = rfac.getZERO(); for (int k = 0; k < ll; k++) { GenPolynomial> Pp = rfac.univariate(i, k); GenPolynomial cp = cpfac.univariate(cpfac.nvar - 1 - k); Pp = Pp.multiply(cp); P = P.sum(Pp); } if (debug) { logger.info("univariate construction, P = " + P); logger.info("univariate construction, deg_*(G) = " + ud); //throw new RuntimeException("check"); } GenPolynomial X; GenPolynomial XP; // solve system of linear equations for the coefficients of the univariate polynomial List> ls; int z = -1; do { //System.out.println("ll = " + ll); GenPolynomial> Pp = rfac.univariate(i, ll); GenPolynomial cp = cpfac.univariate(cpfac.nvar - 1 - ll); Pp = Pp.multiply(cp); P = P.sum(Pp); X = pfac.univariate(i, ll); XP = red.normalform(G, X); //System.out.println("XP = " + XP); GenPolynomial> XPp = PolyUtil. toRecursive(rfac, XP); GenPolynomial> XPs = XPp.sum(P); ls = new ArrayList>(XPs.getMap().values()); //System.out.println("ls,1 = " + ls); ls = red.irreducibleSet(ls); z = commonZeroTest(ls); if (z != 0) { ll++; if (ll > vsdim) { logger.info("univariate construction, P = " + P); logger.info("univariate construction, nf(P) = " + XP); logger.info("G = " + G); throw new ArithmeticException( "univariate polynomial degree greater than vector space dimansion"); } cpfac = cpfac.extend(1); rfac = new GenPolynomialRing>(cpfac, pfac); P = PolyUtil. extendCoefficients(rfac, P, 0, 0L); XPp = PolyUtil. extendCoefficients(rfac, XPp, 0, 1L); P = P.sum(XPp); } } while (z != 0); // && ll <= 5 && !XP.isZERO() // construct result polynomial GenPolynomial pol = ufac.univariate(0, ll); for (GenPolynomial pc : ls) { ExpVector e = pc.leadingExpVector(); if (e == null) { continue; } int[] v = e.dependencyOnVariables(); if (v == null || v.length == 0) { continue; } int vi = v[0]; C tc = pc.trailingBaseCoefficient(); tc = tc.negate(); GenPolynomial pi = ufac.univariate(0, ll - 1 - vi); pi = pi.multiply(tc); pol = pol.sum(pi); } if (logger.isInfoEnabled()) { logger.info("univariate construction, pol = " + pol); } return pol; } /** * Cleanup and terminate ThreadPool. */ public void terminate() { logger.info("terminate not implemented"); //throw new RuntimeException("get a stack trace"); } /** * Cancel ThreadPool. */ public int cancel() { logger.info("cancel not implemented"); return 0; } } jas-2.5/src/edu/jas/gb/Katsura.java0000644000175000017500000001061711353363162017341 0ustar giovannigiovanni/* * Created on 03.10.2004 * $Id: Katsura.java 3058 2010-03-27 11:05:23Z kredel $ */ package edu.jas.gb; /** * Class to produce a system of equations as defined by Katsura. * * @author Heinz Kredel * */ public class Katsura { /** * main. */ public static void main(String[] args) { if ( args.length == 0 ) { System.out.println("usage: Katsura N "); return; } int n = Integer.parseInt(args[0]); Katsura k = null; if ( args.length == 1 ) { k = new Katsura(n); } if ( args.length == 2 ) { k = new Katsura("u",n, args[1]); } if ( args.length == 3 ) { k = new Katsura(args[2],n, args[1]); } System.out.println("#Katsura equations for N = " + n + ":"); System.out.println("" + k); } final int N; final String var; final String order; /** * Katsura constructor. * @param n problem size. */ public Katsura(int n) { this("u", n); } /** * Katsura constructor. * @param v name of variables. * @param n problem size. */ public Katsura(String v, int n) { this(v, n, "G"); } /** * Katsura constructor. * @param var name of variables. * @param n problem size. * @param order term order letter for output. */ public Katsura(String var, int n, String order) { this.var = var; this.N = n; this.order = order; } String sum1() { StringBuffer s = new StringBuffer(); for (int i = -N; i <= N; i++) { s.append(variable(i)); if (i < N) { s.append(" + "); } } s.append(" - 1"); return s.toString(); } String sumUm(int m) { StringBuffer s = new StringBuffer(); for (int i = -N; i <= N; i++) { s.append(variable(i)); s.append("*"); s.append(variable(m - i)); if (i < N) { s.append(" + "); } } s.append(" - " + variable(m)); return s.toString(); } /** * Generate variable list. * @param order term order letter. * @return polynomial ring description. */ public String varList(String order) { return varList("Rat",order); } /** * Generate variable list. * @param order term order letter. * @param coeff coefficient ring name. * @return polynomial ring description. */ public String varList(String coeff, String order) { StringBuffer s = new StringBuffer(); s.append(coeff); s.append("("); // for (int i = 0; i <= N; i++) { for (int i = N; i >=0; i--) { s.append(variable(i)); if (i > 0) { s.append(","); } } s.append(") "); s.append(order); return s.toString(); } /** * toString. * @return Katsura problem as string. */ @Override public String toString() { StringBuffer s = new StringBuffer(); s.append(varList(order)); s.append(System.getProperty("line.separator")); s.append(polyList()); return s.toString(); } /** * Generate polynomial list. * @return Katsura polynomials as string. */ public String polyList() { StringBuffer s = new StringBuffer(); s.append("("+System.getProperty("line.separator")); //for (int m = -N + 1; m <= N - 1; m++) { doubles polynomials for (int m = 0; m <= N - 1; m++) { s.append( sumUm(m) ); s.append(","+System.getProperty("line.separator")); } s.append( sum1() ); s.append(System.getProperty("line.separator")); s.append(")"+System.getProperty("line.separator")); return s.toString(); } /** * Generate variable string. * @return varaible name as string. */ String variable(int i) { if (i < 0) { return variable(-i); } if (i > N) { return "0"; } return var + i; } } jas-2.5/src/edu/jas/gb/EReduction.java0000644000175000017500000000065611143275762017777 0ustar giovannigiovanni/* * $Id: EReduction.java 2412 2009-02-07 12:17:54Z kredel $ */ package edu.jas.gb; import edu.jas.structure.RingElem; /** * Polynomial E-Reduction interface. * Empty marker interface since all required methods are already * defined in the DReduction interface. * @param coefficient type * @author Heinz Kredel */ public interface EReduction> extends DReduction { } jas-2.5/src/edu/jas/gb/WordGroebnerBase.java0000644000175000017500000000221312020351336021102 0ustar giovannigiovanni/* * $Id: WordGroebnerBase.java 4150 2012-09-01 09:18:23Z kredel $ */ package edu.jas.gb; import java.util.List; import java.io.Serializable; import edu.jas.structure.RingElem; import edu.jas.poly.GenWordPolynomial; /** * Non-commutative Groebner Bases interface for GenWordPolynomials. * Defines methods for Groebner bases and GB test. * @param coefficient type * @author Heinz Kredel */ public interface WordGroebnerBase> extends Serializable { /** * Groebner base test. * @param F word polynomial list. * @return true, if F is a Groebner base, else false. */ public boolean isGB(List> F); /** * Groebner base using pairlist class. * @param F word polynomial list. * @return GB(F) a non-commutative Groebner base of F. */ public List> GB( List> F ); /** * Minimal ordered groebner basis. * @param Gp a Word Groebner base. * @return a reduced Word Groebner base of Gp. */ public List> minimalGB(List> Gp); } jas-2.5/src/edu/jas/gb/SolvableGroebnerBaseSeq.java0000644000175000017500000006001212013663732022420 0ustar giovannigiovanni/* * $Id: SolvableGroebnerBaseSeq.java 4104 2012-08-18 10:00:59Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.structure.RingElem; /** * Solvable Groebner bases sequential algorithms. Implements common left, right * and twosided Groebner bases and left, right and twosided GB tests. * @param coefficient type * @author Heinz Kredel. */ public class SolvableGroebnerBaseSeq> extends SolvableGroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(SolvableGroebnerBaseSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public SolvableGroebnerBaseSeq() { super(); } /** * Constructor. * @param sred Solvable reduction engine * @param pl pair selection strategy */ public SolvableGroebnerBaseSeq(SolvableReduction sred, PairList pl) { super(sred, pl); } /** * Left Groebner base using pairlist class. * @param modv number of module variables. * @param F solvable polynomial list. * @return leftGB(F) a left Groebner base of F. */ @SuppressWarnings("unchecked") public List> leftGB(int modv, List> F) { List> G = new ArrayList>(); PairList pairlist = null; int l = F.size(); // ListIterator it = F.listIterator(); for (GenSolvablePolynomial p : F) { // p = (SolvablePolynomial) it.next(); if (p.length() > 0) { p = (GenSolvablePolynomial) p.monic(); if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); if (pairlist == null) { //pairlist = new OrderedPairlist( modv, p.ring ); pairlist = strategy.create(modv, p.ring); } // putOne not required pairlist.put(p); } else { l--; } } if (l <= 1) { return G; // since no threads are activated } GenSolvablePolynomial pi, pj, S, H; Pair pair; while (pairlist.hasNext()) { pair = pairlist.removeNext(); if (pair == null) { continue; } pi = (GenSolvablePolynomial) pair.pi; pj = (GenSolvablePolynomial) pair.pj; if (debug) { logger.info("pi = " + pi); logger.info("pj = " + pj); } S = sred.leftSPolynomial(pi, pj); if (S.isZERO()) { pair.setZero(); continue; } if (debug) { logger.info("ht(S) = " + S.leadingExpVector()); } H = sred.leftNormalform(G, S); if (H.isZERO()) { pair.setZero(); continue; } if (debug) { logger.info("ht(H) = " + H.leadingExpVector()); } H = (GenSolvablePolynomial) H.monic(); if (H.isONE()) { G.clear(); G.add(H); return G; // since no threads are activated } if (debug) { logger.info("H = " + H); } if (H.length() > 0) { l++; G.add(H); pairlist.put(H); } } logger.debug("#sequential list = " + G.size()); G = leftMinimalGB(G); logger.info("" + pairlist); return G; } /** * Solvable Extended Groebner base using critical pair class. * @param modv module variable number. * @param F solvable polynomial list. * @return a container for an extended left Groebner base of F. */ @SuppressWarnings("unchecked") public SolvableExtendedGB extLeftGB(int modv, List> F) { List> G = new ArrayList>(); List>> F2G = new ArrayList>>(); List>> G2F = new ArrayList>>(); PairList pairlist = null; boolean oneInGB = false; int len = F.size(); List> row = null; List> rows = null; List> rowh = null; GenSolvablePolynomialRing ring = null; GenSolvablePolynomial H; GenSolvablePolynomial p; int nzlen = 0; for (GenSolvablePolynomial f : F) { if (f.length() > 0) { nzlen++; } if (ring == null) { ring = f.ring; } } GenSolvablePolynomial mone = ring.getONE(); //.negate(); int k = 0; ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { row = new ArrayList>(nzlen); for (int j = 0; j < nzlen; j++) { row.add(null); } //C c = p.leadingBaseCoefficient(); //c = c.inverse(); //p = p.multiply( c ); row.set(k, mone); //.multiply(c) ); k++; if (p.isUnit()) { G.clear(); G.add(p); G2F.clear(); G2F.add(row); oneInGB = true; break; } G.add(p); G2F.add(row); if (pairlist == null) { //pairlist = new CriticalPairList( modv, p.ring ); pairlist = strategy.create(modv, p.ring); } // putOne not required pairlist.put(p); } else { len--; } } SolvableExtendedGB exgb; if (len <= 1 || oneInGB) { // adjust F2G for (GenSolvablePolynomial f : F) { row = new ArrayList>(G.size()); for (int j = 0; j < G.size(); j++) { row.add(null); } H = sred.leftNormalform(row, G, f); if (!H.isZERO()) { logger.error("nonzero H = " + H); } F2G.add(row); } exgb = new SolvableExtendedGB(F, G, F2G, G2F); //System.out.println("exgb 1 = " + exgb); return exgb; } Pair pair; int i, j; GenSolvablePolynomial pi; GenSolvablePolynomial pj; GenSolvablePolynomial S; GenSolvablePolynomial x; GenSolvablePolynomial y; //GenPolynomial z; while (pairlist.hasNext() && !oneInGB) { pair = pairlist.removeNext(); if (pair == null) { //pairlist.update(); // ? continue; } i = pair.i; j = pair.j; pi = (GenSolvablePolynomial) pair.pi; pj = (GenSolvablePolynomial) pair.pj; if (debug) { logger.info("i, pi = " + i + ", " + pi); logger.info("j, pj = " + j + ", " + pj); } rows = new ArrayList>(G.size()); for (int m = 0; m < G.size(); m++) { rows.add(null); } S = sred.leftSPolynomial(rows, i, pi, j, pj); if (debug) { logger.debug("is reduction S = " + sred.isLeftReductionNF(rows, G, ring.getZERO(), S)); } if (S.isZERO()) { pair.setZero(); //pairlist.update( pair, S ); // do not add to G2F continue; } if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } rowh = new ArrayList>(G.size()); for (int m = 0; m < G.size(); m++) { rowh.add(null); } H = sred.leftNormalform(rowh, G, S); if (debug) { //System.out.println("H = " + H); logger.debug("is reduction H = " + sred.isLeftReductionNF(rowh, G, S, H)); } if (H.isZERO()) { pair.setZero(); //pairlist.update( pair, H ); // do not add to G2F continue; } if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } row = new ArrayList>(G.size() + 1); for (int m = 0; m < G.size(); m++) { x = rows.get(m); if (x != null) { //System.out.println("ms = " + m + " " + x); x = (GenSolvablePolynomial) x.negate(); } y = rowh.get(m); if (y != null) { y = (GenSolvablePolynomial) y.negate(); //System.out.println("mh = " + m + " " + y); } if (x == null) { x = y; } else { x = (GenSolvablePolynomial) x.sum(y); } //System.out.println("mx = " + m + " " + x); row.add(x); } if (debug) { logger.debug("is reduction 0+sum(row,G) == H : " + sred.isLeftReductionNF(row, G, H, ring.getZERO())); } row.add(null); // H = H.monic(); C c = H.leadingBaseCoefficient(); c = c.inverse(); H = H.multiply(c); // 1*c*row, leads to wrong method dispatch: row = PolynomialList. castToSolvableList(blas.scalarProduct(mone.multiply(c), PolynomialList. castToList(row))); row.set(G.size(), mone); if (H.isONE()) { // pairlist.record( pair, H ); // G.clear(); G.add(H); G2F.add(row); oneInGB = true; break; } if (debug) { logger.debug("H = " + H); } G.add(H); //pairlist.update( pair, H ); pairlist.put(H); G2F.add(row); } if (debug) { exgb = new SolvableExtendedGB(F, G, F2G, G2F); logger.info("exgb unnorm = " + exgb); } G2F = normalizeMatrix(F.size(), G2F); if (debug) { exgb = new SolvableExtendedGB(F, G, F2G, G2F); logger.info("exgb nonmin = " + exgb); boolean t2 = isLeftReductionMatrix(exgb); logger.debug("exgb t2 = " + t2); } exgb = minimalSolvableExtendedGB(F.size(), G, G2F); G = exgb.G; G2F = exgb.G2F; logger.debug("#sequential list = " + G.size()); logger.info("" + pairlist); // setup matrices F and F2G for (GenSolvablePolynomial f : F) { row = new ArrayList>(G.size()); for (int m = 0; m < G.size(); m++) { row.add(null); } H = sred.leftNormalform(row, G, f); if (!H.isZERO()) { logger.error("nonzero H = " + H); } F2G.add(row); } return new SolvableExtendedGB(F, G, F2G, G2F); } /** * Twosided Groebner base using pairlist class. * @param modv number of module variables. * @param Fp solvable polynomial list. * @return tsGB(Fp) a twosided Groebner base of Fp. */ @SuppressWarnings("unchecked") public List> twosidedGB(int modv, List> Fp) { if (Fp == null || Fp.size() == 0) { // 0 not 1 return new ArrayList>(); } GenSolvablePolynomialRing fac = Fp.get(0).ring; // assert != null //List> X = generateUnivar( modv, Fp ); List> X = fac.univariateList(modv); //System.out.println("X univ = " + X); List> F = new ArrayList>(Fp.size() * (1 + X.size())); F.addAll(Fp); GenSolvablePolynomial p, x, q; for (int i = 0; i < Fp.size(); i++) { p = Fp.get(i); for (int j = 0; j < X.size(); j++) { x = X.get(j); q = p.multiply(x); q = sred.leftNormalform(F, q); if (!q.isZERO()) { F.add(q); } } } //System.out.println("F generated = " + F); List> G = new ArrayList>(); PairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = (GenSolvablePolynomial) p.monic(); if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); if (pairlist == null) { // pairlist = new OrderedPairlist( modv, p.ring ); pairlist = strategy.create(modv, p.ring); } // putOne not required pairlist.put(p); } else { l--; } } //System.out.println("G to check = " + G); if (l <= 1) { // 1 ok return G; // since no threads are activated } Pair pair; GenSolvablePolynomial pi, pj, S, H; while (pairlist.hasNext()) { pair = pairlist.removeNext(); if (pair == null) { continue; } pi = (GenSolvablePolynomial) pair.pi; pj = (GenSolvablePolynomial) pair.pj; if (debug) { logger.debug("pi = " + pi); logger.debug("pj = " + pj); } S = sred.leftSPolynomial(pi, pj); if (S.isZERO()) { pair.setZero(); continue; } if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = sred.leftNormalform(G, S); if (H.isZERO()) { pair.setZero(); continue; } if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = (GenSolvablePolynomial) H.monic(); if (H.isONE()) { G.clear(); G.add(H); return G; // since no threads are activated } if (debug) { logger.debug("H = " + H); } if (H.length() > 0) { l++; G.add(H); pairlist.put(H); for (int j = 0; j < X.size(); j++) { l++; x = X.get(j); p = H.multiply(x); p = sred.leftNormalform(G, p); if (!p.isZERO()) { p = (GenSolvablePolynomial) p.monic(); if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); pairlist.put(p); } } } } logger.debug("#sequential list = " + G.size()); G = leftMinimalGB(G); logger.info("" + pairlist); return G; } /** * Normalize M. Make all rows the same size and make certain column elements * zero. * @param M a reduction matrix. * @return normalized M. */ public List>> normalizeMatrix(int flen, List>> M) { if (M == null) { return M; } if (M.size() == 0) { return M; } List>> N = new ArrayList>>(); List>> K = new ArrayList>>(); int len = M.get(M.size() - 1).size(); // longest row // pad / extend rows for (List> row : M) { List> nrow = new ArrayList>(row); for (int i = row.size(); i < len; i++) { nrow.add(null); } N.add(nrow); } // System.out.println("norm N fill = " + N); // make zero columns int k = flen; for (int i = 0; i < N.size(); i++) { // 0 List> row = N.get(i); if (debug) { logger.info("row = " + row); } K.add(row); if (i < flen) { // skip identity part continue; } List> xrow; GenSolvablePolynomial a; //System.out.println("norm i = " + i); for (int j = i + 1; j < N.size(); j++) { List> nrow = N.get(j); //System.out.println("nrow j = " +j + ", " + nrow); if (k < nrow.size()) { // always true a = nrow.get(k); //System.out.println("k, a = " + k + ", " + a); if (a != null && !a.isZERO()) { // a*row + nrow, leads to wrong method dispatch List> yrow = blas.scalarProduct(a, PolynomialList. castToList(row)); yrow = blas.vectorAdd(yrow, PolynomialList. castToList(nrow)); xrow = PolynomialList. castToSolvableList(yrow); N.set(j, xrow); } } } k++; } //System.out.println("norm K reduc = " + K); // truncate N.clear(); for (List> row : K) { List> tr = new ArrayList>(); for (int i = 0; i < flen; i++) { tr.add(row.get(i)); } N.add(tr); } K = N; //System.out.println("norm K trunc = " + K); return K; } /** * Test if M is a left reduction matrix. * @param exgb an SolvableExtendedGB container. * @return true, if exgb contains a left reduction matrix, else false. */ @Override public boolean isLeftReductionMatrix(SolvableExtendedGB exgb) { if (exgb == null) { return true; } return isLeftReductionMatrix(exgb.F, exgb.G, exgb.F2G, exgb.G2F); } /** * Minimal solvable extended groebner basis. * @param Gp a left Groebner base. * @param M a left reduction matrix, is modified. * @return a (partially) reduced left Groebner base of Gp in a container. */ public SolvableExtendedGB minimalSolvableExtendedGB(int flen, List> Gp, List>> M) { if (Gp == null) { return null; //new SolvableExtendedGB(null,Gp,null,M); } if (Gp.size() <= 1) { return new SolvableExtendedGB(null, Gp, null, M); } List> G; List> F; G = new ArrayList>(Gp); F = new ArrayList>(Gp.size()); List>> Mg; List>> Mf; Mg = new ArrayList>>(M.size()); Mf = new ArrayList>>(M.size()); List> row; for (List> r : M) { // must be copied also row = new ArrayList>(r); Mg.add(row); } row = null; GenSolvablePolynomial a; ExpVector e; ExpVector f; GenSolvablePolynomial p; boolean mt; ListIterator> it; ArrayList ix = new ArrayList(); ArrayList jx = new ArrayList(); int k = 0; //System.out.println("flen, Gp, M = " + flen + ", " + Gp.size() + ", " + M.size() ); while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } //System.out.println("k, mt = " + k + ", " + mt); if (!mt) { F.add(a); ix.add(k); } else { // drop polynomial and corresponding row and column // F.add( a.ring.getZERO() ); jx.add(k); } k++; } if (debug) { logger.debug("ix, #M, jx = " + ix + ", " + Mg.size() + ", " + jx); } int fix = -1; // copied polys // copy Mg to Mf as indicated by ix for (int i = 0; i < ix.size(); i++) { int u = ix.get(i); if (u >= flen && fix == -1) { fix = Mf.size(); } //System.out.println("copy u, fix = " + u + ", " + fix); if (u >= 0) { row = Mg.get(u); Mf.add(row); } } if (F.size() <= 1 || fix == -1) { return new SolvableExtendedGB(null, F, null, Mf); } // must return, since extended normalform has not correct order of polys /* G = F; F = new ArrayList>( G.size() ); List> temp; k = 0; final int len = G.size(); while ( G.size() > 0 ) { a = G.remove(0); if ( k >= fix ) { // dont touch copied polys row = Mf.get( k ); //System.out.println("doing k = " + k + ", " + a); // must keep order, but removed polys missing temp = new ArrayList>( len ); temp.addAll( F ); temp.add( a.ring.getZERO() ); // ?? temp.addAll( G ); //System.out.println("row before = " + row); a = sred.leftNormalform( row, temp, a ); //System.out.println("row after = " + row); } F.add( a ); k++; } // does Mf need renormalization? */ return new SolvableExtendedGB(null, F, null, Mf); } } jas-2.5/src/edu/jas/gb/GBOptimized.java0000644000175000017500000000640512045475720020107 0ustar giovannigiovanni/* * $Id: GBOptimized.java 4289 2012-11-04 14:29:36Z kredel $ */ package edu.jas.gb; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.OptimizedPolynomialList; import edu.jas.poly.TermOrderOptimization; import edu.jas.structure.GcdRingElem; /** * Groebner bases via optimized variable and term order. * @author Heinz Kredel */ public class GBOptimized> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GBOptimized.class); private final boolean debug = logger.isDebugEnabled(); //logger.isInfoEnabled(); /** * GB engine. */ public final GroebnerBaseAbstract e1; /** * Indicator for return of permuted polynomials. */ public final boolean retPermuted; /** * GBOptimized constructor. * @param e1 Groebner base engine. */ public GBOptimized(GroebnerBaseAbstract e1) { this(e1, false); // true ?? } /** * GBOptimized constructor. * @param e1 Groebner base engine. * @param rP true for return of permuted polynomials, false for inverse * permuted polynomials and new GB computation. */ public GBOptimized(GroebnerBaseAbstract e1, boolean rP) { this.e1 = e1; this.retPermuted = rP; } /** * Get the String representation with GB engine. * @see java.lang.Object#toString() */ @Override public String toString() { return "GBOptimized[ " + e1.toString() + " ]"; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { e1.terminate(); } /** * Cancel ThreadPool. */ @Override public int cancel() { int s = e1.cancel(); return s; } /** * Groebner base. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ //JAVA6only: @Override public List> GB(int modv, List> F) { if (F == null || F.isEmpty()) { return F; } if (modv != 0) { throw new UnsupportedOperationException("implemented only for modv = 0, not " + modv); } GenPolynomialRing pfac = F.get(0).ring; OptimizedPolynomialList opt = TermOrderOptimization. optimizeTermOrder(pfac, F); List> P = opt.list; if (debug) { logger.info("optimized polynomials: " + P); } List iperm = TermOrderOptimization.inversePermutation(opt.perm); logger.info("optimize perm: " + opt.perm + ", de-optimize perm: " + iperm); // compute GB with backing engine List> G = e1.GB(modv, P); if (retPermuted || G.isEmpty()) { return G; } List> iopt = TermOrderOptimization. permutation(iperm, pfac, G); if (debug) { logger.info("de-optimized polynomials: " + iopt); } if (iopt.size() == 1) { return iopt; } logger.warn("recomputing GB"); G = e1.GB(modv, iopt); return G; } } jas-2.5/src/edu/jas/gb/GroebnerBaseDistributedEC.java0000644000175000017500000006660012067562026022706 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistributedEC.java 4337 2012-12-29 12:37:43Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.ChannelFactory; import edu.jas.util.DistHashTable; import edu.jas.util.DistHashTableServer; import edu.jas.util.SocketChannel; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; import edu.jas.util.DistThreadPool; import edu.jas.util.RemoteExecutable; /** * Groebner Base distributed algorithm. Implements a distributed * memory parallel version of Groebner bases with executable * channels. Using pairlist class, distributed tasks do reduction, one * communication channel per task. * @param coefficient type * @author Heinz Kredel */ public class GroebnerBaseDistributedEC> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBaseDistributedEC.class); /** * Number of threads to use. */ protected final int threads; /** * Default number of threads. */ protected static final int DEFAULT_THREADS = 2; /** * Pool of threads to use. Note: No ComputerThreads for one node * tests */ protected transient final ThreadPool pool; /** * Default server port. */ protected static final int DEFAULT_PORT = 55711; /** * Default distributed hash table server port. */ protected final int DHT_PORT; /** * Server port to use. */ protected final int port; /** * machine file to use. */ protected final String mfile; /** * Distributed thread pool to use. */ private final DistThreadPool dtp; /** * Distributed hash table server to use. */ private final DistHashTableServer dhts; /** * Constructor. * @param mfile name of the machine file. */ public GroebnerBaseDistributedEC(String mfile) { this(mfile, DEFAULT_THREADS, DEFAULT_PORT); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. */ public GroebnerBaseDistributedEC(String mfile, int threads) { this(mfile, threads, new ThreadPool(threads), DEFAULT_PORT); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. * @param port server port to use. */ public GroebnerBaseDistributedEC(String mfile, int threads, int port) { this(mfile, threads, new ThreadPool(threads), port); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param port server port to use. */ public GroebnerBaseDistributedEC(String mfile, int threads, ThreadPool pool, int port) { this(mfile, threads, pool, new OrderedSyzPairlist(), port); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. * @param pl pair selection strategy * @param port server port to use. */ public GroebnerBaseDistributedEC(String mfile, int threads, PairList pl, int port) { this(mfile, threads, new ThreadPool(threads), pl, port); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param pl pair selection strategy * @param port server port to use. */ public GroebnerBaseDistributedEC(String mfile, int threads, ThreadPool pool, PairList pl, int port) { super(new ReductionPar(), pl); this.threads = threads; if (mfile == null || mfile.length() == 0) { this.mfile = "../util/machines"; // contains localhost } else { this.mfile = mfile; } if (threads < 1) { threads = 1; } if ( pool == null ) { pool = new ThreadPool(threads); } this.pool = pool; this.port = port; logger.info("machine file " + mfile + ", port = " + port); this.dtp = new DistThreadPool(this.threads, this.mfile); logger.info("running " + dtp); this.DHT_PORT = this.dtp.getEC().getMasterPort() + 100; this.dhts = new DistHashTableServer(this.DHT_PORT); this.dhts.init(); logger.info("running " + dhts); } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { terminate(true); } /** * Terminates the distributed thread pools. * @param shutDown true, if shut-down of the remote executable servers is * requested, false, if remote executable servers stay alive. */ public void terminate(boolean shutDown) { pool.terminate(); dtp.terminate(shutDown); logger.info("dhts.terminate()"); dhts.terminate(); } /** * Distributed Groebner base. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs. */ public List> GB(int modv, List> F) { String master = dtp.getEC().getMasterHost(); //int port = dtp.getEC().getMasterPort(); // wrong port GBExerClient gbc = new GBExerClient(master, port, DHT_PORT); for (int i = 0; i < threads; i++) { // schedule remote clients dtp.addJob(gbc); } // run master List> G = GBMaster(modv, F); return G; } /** * Distributed Groebner base. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs. */ public List> GBMaster(int modv, List> F) { ChannelFactory cf = new ChannelFactory(port); cf.init(); logger.info("GBMaster on " + cf); GenPolynomial p; List> G = new ArrayList>(); PairList pairlist = null; boolean oneInGB = false; int l = F.size(); int unused; ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { oneInGB = true; G.clear(); G.add(p); //return G; must signal termination to others } if (!oneInGB) { G.add(p); } if (pairlist == null) { //pairlist = new OrderedPairlist(modv, p.ring); pairlist = strategy.create(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // theList not updated here if (p.isONE()) { unused = pairlist.putOne(); } else { unused = pairlist.put(p); } } else { l--; } } //if (l <= 1) { //return G; must signal termination to others //} logger.debug("looking for clients"); DistHashTable> theList = new DistHashTable>("localhost", DHT_PORT); theList.init(); List> al = pairlist.getList(); for (int i = 0; i < al.size(); i++) { GenPolynomial nn = theList.put(Integer.valueOf(i), al.get(i)); if (nn != null) { logger.info("double polynomials " + i + ", nn = " + nn + ", al(i) = " + al.get(i)); } } // wait for arrival while ( theList.size() < al.size() ) { logger.info("#distributed list = " + theList.size() + " #pairlist list = " + al.size()); GenPolynomial nn = theList.getWait(al.size()-1); } Terminator fin = new Terminator(threads); ReducerServerEC R; for (int i = 0; i < threads; i++) { R = new ReducerServerEC(fin, cf, theList, G, pairlist); pool.addJob(R); } logger.debug("main loop waiting"); fin.waitDone(); int ps = theList.size(); logger.debug("#distributed list = " + ps); // make sure all polynomials arrived: not needed in master G = pairlist.getList(); if (ps != G.size()) { logger.warn("#distributed list = " + theList.size() + " #pairlist list = " + G.size()); } long time = System.currentTimeMillis(); List> Gp; Gp = minimalGB(G); // not jet distributed but threaded time = System.currentTimeMillis() - time; logger.debug("parallel gbmi = " + time); /* time = System.currentTimeMillis(); G = GroebnerBase.GBmi(G); // sequential time = System.currentTimeMillis() - time; logger.info("sequential gbmi = " + time); */ G = Gp; logger.debug("cf.terminate()"); cf.terminate(); logger.debug("theList.terminate()"); theList.terminate(); logger.info("" + pairlist); return G; } /** * GB distributed client part. * @param host the server runs on. * @param port the server runs. * @param dhtport of the DHT server. * @throws IOException */ public static > void clientPart(String host, int port, int dhtport) throws IOException { ChannelFactory cf = new ChannelFactory(port + 10); // != port for localhost cf.init(); logger.info("clientPart connecting to " + host + ", port = " + port + ", dhtport = " + dhtport); SocketChannel pairChannel = cf.getChannel(host, port); DistHashTable> theList = new DistHashTable>(host, dhtport); theList.init(); ReducerClientEC R = new ReducerClientEC(pairChannel, theList); logger.info("clientPart running on " + host + ", pairChannel = " + pairChannel); R.run(); pairChannel.close(); theList.terminate(); cf.terminate(); return; } /** * Minimal ordered groebner basis. * @param Fp a Groebner base. * @return a reduced Groebner base of Fp. */ @Override public List> minimalGB(List> Fp) { GenPolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiReducerServerEC[] mirs = (MiReducerServerEC[]) new MiReducerServerEC[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new MiReducerServerEC(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } } /** * Distributed server reducing worker threads. * @param coefficient type */ class ReducerServerEC> implements Runnable { private final Terminator pool; private final ChannelFactory cf; private SocketChannel pairChannel; private final DistHashTable> theList; //private List> G; private final PairList pairlist; private static final Logger logger = Logger.getLogger(ReducerServerEC.class); ReducerServerEC(Terminator fin, ChannelFactory cf, DistHashTable> dl, List> G, PairList L) { pool = fin; this.cf = cf; theList = dl; //this.G = G; pairlist = L; } public void run() { logger.info("reducer server running with " + cf); try { pairChannel = cf.getChannel(); } catch (InterruptedException e) { logger.debug("get pair channel interrupted"); e.printStackTrace(); return; } if (logger.isDebugEnabled()) { logger.debug("pairChannel = " + pairChannel); } Pair pair; //GenPolynomial pi; //GenPolynomial pj; //GenPolynomial S; GenPolynomial H = null; boolean set = false; boolean goon = true; int polIndex = -1; int red = 0; int sleeps = 0; // while more requests while (goon) { // receive request logger.info("receive request"); Object req = null; try { req = pairChannel.receive(); } catch (IOException e) { goon = false; e.printStackTrace(); } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } //logger.debug("received request, req = " + req); if (req == null) { goon = false; break; } if (!(req instanceof GBTransportMessReq)) { goon = false; break; } // find pair logger.debug("find pair"); while (!pairlist.hasNext()) { // wait if (!set) { pool.beIdle(); set = true; } if (!pool.hasJobs() && !pairlist.hasNext()) { goon = false; break; } try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } Thread.sleep(100); } catch (InterruptedException e) { goon = false; break; } } if (!pairlist.hasNext() && !pool.hasJobs()) { goon = false; break; //continue; //break? } if (set) { set = false; pool.notIdle(); } pair = pairlist.removeNext(); /* * send pair to client, receive H */ logger.debug("send pair = " + pair); GBTransportMess msg = null; if (pair != null) { msg = new GBTransportMessPairIndex(pair); // ,pairlist.size()-1); // size-1 } else { msg = new GBTransportMess(); // not End(); at this time // goon ?= false; } try { pairChannel.send(msg); } catch (IOException e) { e.printStackTrace(); goon = false; break; } logger.debug("#distributed list = " + theList.size()); Object rh = null; try { rh = pairChannel.receive(); } catch (IOException e) { e.printStackTrace(); goon = false; break; } catch (ClassNotFoundException e) { e.printStackTrace(); goon = false; break; } //logger.debug("received H polynomial"); if (rh == null) { if (pair != null) { pair.setZero(); } } else if (rh instanceof GBTransportMessPoly) { // update pair list red++; H = ((GBTransportMessPoly) rh).pol; if (logger.isDebugEnabled()) { logger.debug("H = " + H); } if (H == null) { if (pair != null) { pair.setZero(); } } else { if (H.isZERO()) { pair.setZero(); } else { if (H.isONE()) { // pool.allIdle(); polIndex = pairlist.putOne(); theList.putWait(Integer.valueOf(polIndex), H); goon = false; break; } polIndex = pairlist.put(H); // use putWait ? but still not all distributed theList.putWait(Integer.valueOf(polIndex), H); } } } } logger.info("terminated, done " + red + " reductions"); /* * send end mark to client */ logger.debug("send end"); try { pairChannel.send(new GBTransportMessEnd()); } catch (IOException e) { if (logger.isDebugEnabled()) { e.printStackTrace(); } } pool.beIdle(); pairChannel.close(); } } /** * Distributed clients reducing worker threads. */ class ReducerClientEC> implements Runnable { private final SocketChannel pairChannel; private final DistHashTable> theList; private final ReductionPar red; private static final Logger logger = Logger.getLogger(ReducerClientEC.class); ReducerClientEC(SocketChannel pc, DistHashTable> dl) { pairChannel = pc; theList = dl; red = new ReductionPar(); } public void run() { logger.debug("pairChannel = " + pairChannel + " reducer client running"); Pair pair = null; GenPolynomial pi, pj, ps; GenPolynomial S; GenPolynomial H = null; //boolean set = false; boolean goon = true; int reduction = 0; //int sleeps = 0; Integer pix, pjx, psx; while (goon) { /* protocol: * request pair, process pair, send result */ // pair = (Pair) pairlist.removeNext(); Object req = new GBTransportMessReq(); logger.debug("send request = " + req); H = null; try { pairChannel.send(req); } catch (IOException e) { goon = false; e.printStackTrace(); break; } logger.debug("receive pair, goon = " + goon); Object pp = null; try { pp = pairChannel.receive(); } catch (IOException e) { goon = false; if (logger.isDebugEnabled()) { e.printStackTrace(); } break; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } if (logger.isDebugEnabled()) { logger.debug("received pair = " + pp); } if (pp == null) { // should not happen continue; } if (pp instanceof GBTransportMessEnd) { goon = false; continue; } if (pp instanceof GBTransportMessPair || pp instanceof GBTransportMessPairIndex) { pi = pj = ps = null; if (pp instanceof GBTransportMessPair) { // obsolete, for tests GBTransportMessPair tmp = (GBTransportMessPair) pp; pair = (Pair) tmp.pair; if (pair != null) { pi = pair.pi; pj = pair.pj; //logger.debug("pair: pix = " + pair.i // + ", pjx = " + pair.j); } } if (pp instanceof GBTransportMessPairIndex) { GBTransportMessPairIndex tmpi = (GBTransportMessPairIndex)pp; pix = tmpi.i; pjx = tmpi.j; psx = tmpi.s; pi = theList.getWait(pix); pj = theList.getWait(pjx); ps = theList.getWait(psx); //logger.info("pix = " + pix + ", pjx = " + pjx + ", psx = " + psx); } if (pi != null && pj != null) { S = red.SPolynomial(pi, pj); //System.out.println("S = " + S); if (S.isZERO()) { // pair.setZero(); does not work in dist } else { if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(theList, S); reduction++; if (H.isZERO()) { // pair.setZero(); does not work in dist } else { H = H.monic(); if (logger.isInfoEnabled()) { logger.info("ht(H) = " + H.leadingExpVector()); } } } } else { logger.info("pi = " + pi + ", pj = " + pj + ", ps = " + ps); } } // send H or must send null if (logger.isDebugEnabled()) { logger.debug("#distributed list = " + theList.size()); logger.debug("send H polynomial = " + H); } try { pairChannel.send(new GBTransportMessPoly(H)); } catch (IOException e) { goon = false; e.printStackTrace(); } } logger.info("terminated, done " + reduction + " reductions"); pairChannel.close(); } } /** * Distributed server reducing worker threads for minimal GB Not jet distributed * but threaded. */ class MiReducerServerEC> implements Runnable { private final List> G; private GenPolynomial H; private final Semaphore done = new Semaphore(0); private final Reduction red; private static final Logger logger = Logger.getLogger(MiReducerServer.class); MiReducerServerEC(List> G, GenPolynomial p) { this.G = G; H = p; red = new ReductionPar(); } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenPolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException e) { } return H; } public void run() { if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = red.normalform(G, H); //mod done.release(); //done.V(); if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } /** * Distributed clients reducing worker threads for minimal GB. Not jet used. */ class MiReducerClientEC> implements Runnable { private final List> G; private GenPolynomial H; private final Reduction red; private final Semaphore done = new Semaphore(0); private static final Logger logger = Logger.getLogger(MiReducerClient.class); MiReducerClientEC(List> G, GenPolynomial p) { this.G = G; H = p; red = new ReductionPar(); } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenPolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException u) { Thread.currentThread().interrupt(); } return H; } public void run() { if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + H.leadingExpVector()); } H = red.normalform(G, H); //mod done.release(); //done.V(); if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } /** * Objects of this class are to be send to a ExecutableServer. */ class GBExerClient> implements RemoteExecutable { String host; int port; int dhtport; /** * GBExerClient. * @param host * @param port * @param dhtport */ public GBExerClient(String host, int port, int dhtport) { this.host = host; this.port = port; this.dhtport = dhtport; } /** * run. */ public void run() { //System.out.println("running " + this); try { GroebnerBaseDistributedEC. clientPart(host,port,dhtport); } catch (Exception e) { e.printStackTrace(); } } /** * String representation. */ @Override public String toString() { StringBuffer s = new StringBuffer("GBExerClient("); s.append("host="+host); s.append(", port="+port); s.append(", dhtport="+dhtport); s.append(")"); return s.toString(); } } jas-2.5/src/edu/jas/gb/SolvableGroebnerBaseAbstract.java0000644000175000017500000006206212136751756023454 0ustar giovannigiovanni/* * $Id: SolvableGroebnerBaseAbstract.java 4385 2013-04-27 13:34:38Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.PolynomialList; import edu.jas.poly.TermOrder; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.vector.BasicLinAlg; /** * Solvable Groebner Bases abstract class. Implements common left, right and * twosided Groebner bases and left, right and twosided GB tests. * @param coefficient type * @author Heinz Kredel. */ public abstract class SolvableGroebnerBaseAbstract> implements SolvableGroebnerBase { private static final Logger logger = Logger.getLogger(SolvableGroebnerBaseAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Solvable reduction engine. */ public SolvableReduction sred; /** * Reduction engine. */ public final Reduction red; /** * Strategy for pair selection. */ public final PairList strategy; /** * Linear algebra engine. */ protected final BasicLinAlg> blas; /** * Commutative Groebner bases engine. */ public final GroebnerBaseAbstract cbb; /** * Constructor. */ public SolvableGroebnerBaseAbstract() { this(new SolvableReductionSeq()); } /** * Constructor. * @param sred Solvable reduction engine */ public SolvableGroebnerBaseAbstract(SolvableReduction sred) { this(sred, new OrderedPairlist()); } /** * Constructor. * @param sred Solvable reduction engine * @param pl pair selection strategy */ public SolvableGroebnerBaseAbstract(SolvableReduction sred, PairList pl) { this.red = new ReductionSeq(); this.sred = sred; this.strategy = pl; blas = new BasicLinAlg>(); cbb = new GroebnerBaseSeq(); } /** * Left Groebner base test. * @param F solvable polynomial list. * @return true, if F is a left Groebner base, else false. */ public boolean isLeftGB(List> F) { return isLeftGB(0, F, true); } /** * Left Groebner base test. * @param F solvable polynomial list. * @param b true for simple test, false for GB test. * @return true, if F is a Groebner base, else false. */ public boolean isLeftGB(List> F, boolean b) { return isLeftGB(0, F, b); } /** * Left Groebner base test. * @param modv module variable number. * @param F solvable polynomial list. * @return true, if F is a Groebner base, else false. */ public boolean isLeftGB(int modv, List> F) { return isLeftGB(modv, F, true); } /** * Left Groebner base test. * @param modv module variable number. * @param F solvable polynomial list. * @param b true for simple test, false for GB test. * @return true, if F is a Groebner base, else false. */ public boolean isLeftGB(int modv, List> F, boolean b) { if (b) { return isLeftGBsimple(modv, F); } return isLeftGBidem(modv, F); } /** * Left Groebner base test. * @param modv number of module variables. * @param F solvable polynomial list. * @return true, if F is a left Groebner base, else false. */ public boolean isLeftGBsimple(int modv, List> F) { GenSolvablePolynomial pi, pj, s, h; for (int i = 0; i < F.size(); i++) { pi = F.get(i); for (int j = i + 1; j < F.size(); j++) { pj = F.get(j); if (!red.moduleCriterion(modv, pi, pj)) { continue; } // if ( ! red.criterion4( pi, pj ) ) { continue; } s = sred.leftSPolynomial(pi, pj); if (s.isZERO()) { continue; } h = sred.leftNormalform(F, s); if (!h.isZERO()) { return false; } } } return true; } /** * Left Groebner base idempotence test. * @param modv module variable number. * @param F solvable polynomial list. * @return true, if F is equal to GB(F), else false. */ public boolean isLeftGBidem(int modv, List> F) { if (F == null || F.isEmpty()) { return true; } GenSolvablePolynomialRing pring = F.get(0).ring; List> G = leftGB(modv, F); PolynomialList Fp = new PolynomialList(pring, F); PolynomialList Gp = new PolynomialList(pring, G); return Fp.compareTo(Gp) == 0; } /** * Twosided Groebner base test. * @param Fp solvable polynomial list. * @return true, if Fp is a two-sided Groebner base, else false. */ public boolean isTwosidedGB(List> Fp) { return isTwosidedGB(0, Fp); } /** * Twosided Groebner base test. * @param modv number of module variables. * @param Fp solvable polynomial list. * @return true, if Fp is a two-sided Groebner base, else false. */ public boolean isTwosidedGB(int modv, List> Fp) { if (Fp == null || Fp.size() == 0) { // 0 not 1 return true; } GenSolvablePolynomialRing fac = Fp.get(0).ring; // assert != null //List> X = generateUnivar( modv, Fp ); List> X = fac.univariateList(modv); List> F = new ArrayList>(Fp.size() * (1 + X.size())); F.addAll(Fp); GenSolvablePolynomial p, x, pi, pj, s, h; for (int i = 0; i < Fp.size(); i++) { p = Fp.get(i); for (int j = 0; j < X.size(); j++) { x = X.get(j); p = p.multiply(x); p = sred.leftNormalform(F, p); if (!p.isZERO()) { F.add(p); } } } //System.out.println("F to check = " + F); for (int i = 0; i < F.size(); i++) { pi = F.get(i); for (int j = i + 1; j < F.size(); j++) { pj = F.get(j); if (!red.moduleCriterion(modv, pi, pj)) { continue; } // if ( ! red.criterion4( pi, pj ) ) { continue; } s = sred.leftSPolynomial(pi, pj); if (s.isZERO()) { continue; } h = sred.leftNormalform(F, s); if (!h.isZERO()) { logger.info("is not TwosidedGB: " + h); return false; } } } return true; } /** * Twosided Groebner base idempotence test. * @param F solvable polynomial list. * @return true, if F is equal to GB(F), else false. */ public boolean isTwosidedGBidem(List> F) { return isTwosidedGBidem(0, F); } /** * Twosided Groebner base idempotence test. * @param modv module variable number. * @param F solvable polynomial list. * @return true, if F is equal to GB(F), else false. */ public boolean isTwosidedGBidem(int modv, List> F) { if (F == null || F.isEmpty()) { return true; } GenSolvablePolynomialRing pring = F.get(0).ring; List> G = twosidedGB(modv, F); PolynomialList Fp = new PolynomialList(pring, F); PolynomialList Gp = new PolynomialList(pring, G); return Fp.compareTo(Gp) == 0; } /** * Right Groebner base test. * @param F solvable polynomial list. * @return true, if F is a right Groebner base, else false. */ public boolean isRightGB(List> F) { return isRightGB(0, F); } /** * Right Groebner base test. * @param modv number of module variables. * @param F solvable polynomial list. * @return true, if F is a right Groebner base, else false. */ public boolean isRightGB(int modv, List> F) { GenSolvablePolynomial pi, pj, s, h; for (int i = 0; i < F.size(); i++) { pi = F.get(i); //System.out.println("pi right = " + pi); for (int j = i + 1; j < F.size(); j++) { pj = F.get(j); //System.out.println("pj right = " + pj); if (!red.moduleCriterion(modv, pi, pj)) { continue; } // if ( ! red.criterion4( pi, pj ) ) { continue; } s = sred.rightSPolynomial(pi, pj); if (s.isZERO()) { continue; } //System.out.println("s right = " + s); h = sred.rightNormalform(F, s); if (!h.isZERO()) { logger.info("isRightGB non zero h = " + h + " :: " + h.ring); logger.info("p" + i + " = " + pi + ", p" + j + " = " + pj); return false; } else { //logger.info("isRightGB zero h = " + h); } } } return true; } /** * Right Groebner base idempotence test. * @param F solvable polynomial list. * @return true, if F is equal to GB(F), else false. */ public boolean isRightGBidem(List> F) { return isRightGBidem(0, F); } /** * Right Groebner base idempotence test. * @param modv module variable number. * @param F solvable polynomial list. * @return true, if F is equal to GB(F), else false. */ public boolean isRightGBidem(int modv, List> F) { if (F == null || F.isEmpty()) { return true; } GenSolvablePolynomialRing pring = F.get(0).ring; List> G = rightGB(modv, F); PolynomialList Fp = new PolynomialList(pring, F); PolynomialList Gp = new PolynomialList(pring, G); return Fp.compareTo(Gp) == 0; } /** * Left Groebner base using pairlist class. * @param F solvable polynomial list. * @return leftGB(F) a left Groebner base of F. */ public List> leftGB(List> F) { return leftGB(0, F); } /** * Solvable Extended Groebner base using critical pair class. * @param F solvable polynomial list. * @return a container for an extended left Groebner base of F. */ public SolvableExtendedGB extLeftGB(List> F) { return extLeftGB(0, F); } /** * Left minimal ordered groebner basis. * @param Gp a left Groebner base. * @return leftGBmi(F) a minimal left Groebner base of Gp. */ public List> leftMinimalGB(List> Gp) { ArrayList> G = new ArrayList>(); ListIterator> it = Gp.listIterator(); for (GenSolvablePolynomial a : Gp) { // a = (SolvablePolynomial) it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenSolvablePolynomial a, p; ArrayList> F = new ArrayList>(); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } F = new ArrayList>(); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); a = sred.leftNormalform(G, a); a = sred.leftNormalform(F, a); F.add(a); } return F; } /** * Twosided Groebner base using pairlist class. * @param Fp solvable polynomial list. * @return tsGB(Fp) a twosided Groebner base of Fp. */ public List> twosidedGB(List> Fp) { return twosidedGB(0, Fp); } /** * Right Groebner base using opposite ring left GB. * @param F solvable polynomial list. * @return rightGB(F) a right Groebner base of F. */ public List> rightGB(List> F) { return rightGB(0, F); } /** * Right Groebner base using opposite ring left GB. * @param modv number of module variables. * @param F solvable polynomial list. * @return rightGB(F) a right Groebner base of F. */ @SuppressWarnings("unchecked") public List> rightGB(int modv, List> F) { GenSolvablePolynomialRing ring = null; for (GenSolvablePolynomial p : F) { if (p != null) { ring = p.ring; break; } } if (ring == null) { return F; } GenSolvablePolynomialRing rring = ring.reverse(true); //true //System.out.println("reversed ring = " + rring); //ring = rring.reverse(true); // true GenSolvablePolynomial q; List> rF; rF = new ArrayList>(F.size()); for (GenSolvablePolynomial p : F) { if (p != null) { q = (GenSolvablePolynomial) p.reverse(rring); rF.add(q); } } if (true || debug) { PolynomialList pl = new PolynomialList(rring, rF); logger.info("reversed problem = " + pl); } //System.out.println("reversed problem = " + rF); List> rG = leftGB(modv, rF); if (true || debug) { //PolynomialList pl = new PolynomialList(rring,rG); //logger.info("reversed GB = " + pl); long t = System.currentTimeMillis(); boolean isit = isLeftGB(rG); t = System.currentTimeMillis() - t; logger.info("is left GB = " + isit + ", in " + t + " milliseconds"); } //System.out.println("reversed left GB = " + rG); ring = rring.reverse(true); // true List> G = new ArrayList>(rG.size()); for (GenSolvablePolynomial p : rG) { if (p != null) { q = (GenSolvablePolynomial) p.reverse(ring); G.add(q); } } if (true || debug) { //PolynomialList pl = new PolynomialList(ring,G); //logger.info("GB = " + pl); long t = System.currentTimeMillis(); boolean isit = isRightGB(G); t = System.currentTimeMillis() - t; logger.info("is right GB = " + isit + ", in " + t + " milliseconds"); } return G; } /** * Test if left reduction matrix. * @param exgb an SolvableExtendedGB container. * @return true, if exgb contains a left reduction matrix, else false. */ public boolean isLeftReductionMatrix(SolvableExtendedGB exgb) { if (exgb == null) { return true; } return isLeftReductionMatrix(exgb.F, exgb.G, exgb.F2G, exgb.G2F); } /** * Test if left reduction matrix. * @param F a solvable polynomial list. * @param G a left Groebner base. * @param Mf a possible left reduction matrix. * @param Mg a possible left reduction matrix. * @return true, if Mg and Mf are left reduction matrices, else false. */ public boolean isLeftReductionMatrix(List> F, List> G, List>> Mf, List>> Mg) { // no more check G and Mg: G * Mg[i] == 0 // check F and Mg: F * Mg[i] == G[i] int k = 0; for (List> row : Mg) { boolean t = sred.isLeftReductionNF(row, F, G.get(k), null); if (!t) { System.out.println("row = " + row); System.out.println("F = " + F); System.out.println("Gk = " + G.get(k)); logger.info("F isLeftReductionMatrix s, k = " + F.size() + ", " + k); return false; } k++; } // check G and Mf: G * Mf[i] == F[i] k = 0; for (List> row : Mf) { boolean t = sred.isLeftReductionNF(row, G, F.get(k), null); if (!t) { logger.error("G isLeftReductionMatrix s, k = " + G.size() + ", " + k); return false; } k++; } return true; } /** * Ideal common zero test. * @return -1, 0 or 1 if dimension(this) &eq; -1, 0 or ≥ 1. */ public int commonZeroTest(List> A) { List> cA = PolynomialList. castToList(A); return cbb.commonZeroTest(cA); } /** * Univariate head term degrees. * @param A list of solvable polynomials. * @return a list of the degrees of univariate head terms. */ public List univariateDegrees(List> A) { List> cA = PolynomialList. castToList(A); return cbb.univariateDegrees(cA); } /** * Construct univariate solvable polynomial of minimal degree in variable i * of a zero dimensional ideal(G). * @param i variable index. * @param G list of solvable polynomials, a monic reduced left Gröbner * base of a zero dimensional ideal. * @return univariate solvable polynomial of minimal degree in variable i in * ideal_left(G) */ public GenSolvablePolynomial constructUnivariate(int i, List> G) { if (G == null || G.size() == 0) { throw new IllegalArgumentException("G may not be null or empty"); } List ud = univariateDegrees(G); if (ud.size() <= i) { //logger.info("univ pol, ud = " + ud); throw new IllegalArgumentException("ideal(G) not zero dimensional " + ud); } int ll = 0; Long di = ud.get(i); if (di != null) { ll = (int) (long) di; } else { throw new IllegalArgumentException("ideal(G) not zero dimensional"); } long vsdim = 1; for (Long d : ud) { if (d != null) { vsdim *= d; } } logger.info("univariate construction, deg = " + ll + ", vsdim = " + vsdim); GenSolvablePolynomialRing pfac = G.get(0).ring; RingFactory cfac = pfac.coFac; GenPolynomialRing cpfac = new GenPolynomialRing(cfac, ll, new TermOrder(TermOrder.INVLEX)); GenSolvablePolynomialRing> rfac = new GenSolvablePolynomialRing>( cpfac, pfac); // relations GenSolvablePolynomial> P = rfac.getZERO(); for (int k = 0; k < ll; k++) { GenSolvablePolynomial> Pp = rfac.univariate(i, k); GenPolynomial cp = cpfac.univariate(cpfac.nvar - 1 - k); Pp = Pp.multiply(cp); P = (GenSolvablePolynomial>) P.sum(Pp); } if (debug) { logger.info("univariate construction, P = " + P); logger.info("univariate construction, deg_*(G) = " + ud); //throw new RuntimeException("check"); } GroebnerBaseAbstract bbc = new GroebnerBaseSeq(); GenSolvablePolynomial X; GenSolvablePolynomial XP; // solve system of linear equations for the coefficients of the univariate polynomial List> ls; int z = -1; do { //System.out.println("ll = " + ll); GenSolvablePolynomial> Pp = rfac.univariate(i, ll); GenPolynomial cp = cpfac.univariate(cpfac.nvar - 1 - ll); Pp = Pp.multiply(cp); P = (GenSolvablePolynomial>) P.sum(Pp); X = pfac.univariate(i, ll); XP = sred.leftNormalform(G, X); //System.out.println("XP = " + XP); GenSolvablePolynomial> XPp = PolyUtil. toRecursive(rfac, XP); GenSolvablePolynomial> XPs = (GenSolvablePolynomial>) XPp .sum(P); ls = new ArrayList>(XPs.getMap().values()); //System.out.println("ls,1 = " + ls); ls = red.irreducibleSet(ls); z = bbc.commonZeroTest(ls); if (z != 0) { ll++; if (ll > vsdim) { logger.info("univariate construction, P = " + P); logger.info("univariate construction, nf(P) = " + XP); logger.info("G = " + G); throw new ArithmeticException( "univariate polynomial degree greater than vector space dimansion"); } cpfac = cpfac.extend(1); rfac = new GenSolvablePolynomialRing>(cpfac, pfac); P = PolyUtil. extendCoefficients(rfac, P, 0, 0L); XPp = PolyUtil. extendCoefficients(rfac, XPp, 0, 1L); P = (GenSolvablePolynomial>) P.sum(XPp); } } while (z != 0); // && ll <= 5 && !XP.isZERO() // construct result polynomial String var = pfac.getVars()[pfac.nvar - 1 - i]; GenSolvablePolynomialRing ufac = new GenSolvablePolynomialRing(cfac, 1, new TermOrder( TermOrder.INVLEX), new String[] { var }); GenSolvablePolynomial pol = ufac.univariate(0, ll); for (GenPolynomial pc : ls) { ExpVector e = pc.leadingExpVector(); if (e == null) { continue; } int[] v = e.dependencyOnVariables(); if (v == null || v.length == 0) { continue; } int vi = v[0]; C tc = pc.trailingBaseCoefficient(); tc = tc.negate(); GenSolvablePolynomial pi = ufac.univariate(0, ll - 1 - vi); pi = pi.multiply(tc); pol = (GenSolvablePolynomial) pol.sum(pi); } if (logger.isInfoEnabled()) { logger.info("univariate construction, pol = " + pol); } return pol; } /** * Construct univariate solvable polynomials of minimal degree in all * variables in zero dimensional left ideal(G). * @return list of univariate polynomial of minimal degree in each variable * in ideal_left(G) */ public List> constructUnivariate(List> G) { List> univs = new ArrayList>(); if (G == null || G.isEmpty()) { return univs; } for (int i = G.get(0).ring.nvar - 1; i >= 0; i--) { GenSolvablePolynomial u = constructUnivariate(i, G); univs.add(u); } return univs; } /** * Cleanup and terminate ThreadPool. */ public void terminate() { logger.info("terminate not implemented"); //throw new RuntimeException("get a stack trace"); } /** * Cancel ThreadPool. */ public int cancel() { logger.info("cancel not implemented"); return 0; } } jas-2.5/src/edu/jas/gb/SolvableReductionSeq.java0000644000175000017500000002141512013663732022022 0ustar giovannigiovanni/* * $Id: SolvableReductionSeq.java 4104 2012-08-18 10:00:59Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.Map; import edu.jas.poly.ExpVector; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.structure.RingElem; /** * Solvable polynomial Reduction algorithm. Implements left, right normalform. * @param coefficient type * @author Heinz Kredel */ public class SolvableReductionSeq> extends SolvableReductionAbstract { //private static final Logger logger = Logger.getLogger(SolvableReductionSeq.class); /** * Constructor. */ public SolvableReductionSeq() { } /** * Left Normalform. * @param Ap solvable polynomial. * @param Pp solvable polynomial list. * @return left-nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenSolvablePolynomial leftNormalform(List> Pp, GenSolvablePolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } int l; Map.Entry m; GenSolvablePolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenSolvablePolynomial[]) new GenSolvablePolynomial[l]; //P = Pp.toArray(); for (int j = 0; j < Pp.size(); j++) { P[j] = Pp.get(j); } } int i; ExpVector[] htl = new ExpVector[l]; Object[] lbc = new Object[l]; // want GenSolvablePolynomial[] p = new GenSolvablePolynomial[l]; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; boolean mt = false; GenSolvablePolynomial R = Ap.ring.getZERO(); //GenSolvablePolynomial T = null; GenSolvablePolynomial Q = null; GenSolvablePolynomial S = Ap; while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); //logger.info("red = " + e); a = m.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) break; } if (!mt) { //logger.debug("irred"); //T = new OrderedMapPolynomial( a, e ); R = (GenSolvablePolynomial) R.sum(a, e); S = (GenSolvablePolynomial) S.subtract(a, e); // System.out.println(" S = " + S); } else { //logger.debug("red"); e = e.subtract(htl[i]); //a = a.divide( (C)lbc[i] ); Q = p[i].multiplyLeft(e); a = a.divide(Q.leadingBaseCoefficient()); Q = Q.multiplyLeft(a); S = (GenSolvablePolynomial) S.subtract(Q); } } return R; } /** * LeftNormalform with recording. * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the left normal form of Ap wrt. Pp. */ @SuppressWarnings("unchecked") public GenSolvablePolynomial leftNormalform(List> row, List> Pp, GenSolvablePolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } int l = Pp.size(); GenSolvablePolynomial[] P = (GenSolvablePolynomial[]) new GenSolvablePolynomial[l]; synchronized (Pp) { //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[l]; Object[] lbc = new Object[l]; // want GenSolvablePolynomial[] p = (GenSolvablePolynomial[]) new GenSolvablePolynomial[l]; Map.Entry m; int j = 0; int i; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; boolean mt = false; GenSolvablePolynomial zero = Ap.ring.getZERO(); GenSolvablePolynomial R = Ap.ring.getZERO(); GenSolvablePolynomial fac = null; // GenSolvablePolynomial T = null; GenSolvablePolynomial Q = null; GenSolvablePolynomial S = Ap; while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) break; } if (!mt) { //logger.debug("irred"); R = (GenSolvablePolynomial) R.sum(a, e); S = (GenSolvablePolynomial) S.subtract(a, e); // System.out.println(" S = " + S); // throw new RuntimeException("Syzygy no leftGB"); } else { e = e.subtract(htl[i]); //logger.info("red div = " + e); //a = a.divide( (C)lbc[i] ); //Q = p[i].multiplyLeft( a, e ); Q = p[i].multiplyLeft(e); a = a.divide(Q.leadingBaseCoefficient()); Q = Q.multiply(a); S = (GenSolvablePolynomial) S.subtract(Q); fac = row.get(i); if (fac == null) { fac = (GenSolvablePolynomial) zero.sum(a, e); } else { fac = (GenSolvablePolynomial) fac.sum(a, e); } row.set(i, fac); } } return R; } /** * Right Normalform. * @param Ap solvable polynomial. * @param Pp solvable polynomial list. * @return right-nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenSolvablePolynomial rightNormalform(List> Pp, GenSolvablePolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } int l; Map.Entry m; GenSolvablePolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenSolvablePolynomial[]) new GenSolvablePolynomial[l]; //P = Pp.toArray(); for (int j = 0; j < Pp.size(); j++) { P[j] = Pp.get(j); } } int i; ExpVector[] htl = new ExpVector[l]; Object[] lbc = new Object[l]; // want GenSolvablePolynomial[] p = (GenSolvablePolynomial[]) new GenSolvablePolynomial[l]; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; boolean mt = false; GenSolvablePolynomial R = Ap.ring.getZERO(); //GenSolvablePolynomial T = null; GenSolvablePolynomial Q = null; GenSolvablePolynomial S = Ap; while (S.length() > 0) { m = S.leadingMonomial(); e = m.getKey(); //logger.info("red = " + e); a = m.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) break; } if (!mt) { //logger.debug("irred"); //T = new OrderedMapPolynomial( a, e ); R = (GenSolvablePolynomial) R.sum(a, e); S = (GenSolvablePolynomial) S.subtract(a, e); // System.out.println(" S = " + S); } else { //logger.debug("red"); e = e.subtract(htl[i]); //a = a.divide( (C)lbc[i] ); Q = p[i].multiply(e); a = a.divide(Q.leadingBaseCoefficient()); Q = Q.multiply(a); S = (GenSolvablePolynomial) S.subtract(Q); } } return R; } } jas-2.5/src/edu/jas/gb/WordGroebnerBaseSeq.java0000644000175000017500000001141012020351336021552 0ustar giovannigiovanni/* * $Id: WordGroebnerBaseSeq.java 4150 2012-09-01 09:18:23Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import org.apache.log4j.Logger; import edu.jas.structure.RingElem; import edu.jas.poly.Word; import edu.jas.poly.GenWordPolynomial; import edu.jas.poly.GenWordPolynomialRing; /** * Word Groebner Base sequential algorithm. * Implements Groebner bases and GB test. * @param coefficient type * @author Heinz Kredel */ public class WordGroebnerBaseSeq> extends WordGroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(WordGroebnerBaseSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public WordGroebnerBaseSeq() { super(); } /** * Constructor. * @param red Reduction engine */ public WordGroebnerBaseSeq(WordReduction red) { super(red); } /** * Constructor. * @param red Reduction engine * @param pl pair selection strategy */ public WordGroebnerBaseSeq(WordReduction red, WordPairList pl) { super(red,pl); } /** * Word Groebner base using word pairlist class. * @param F word polynomial list. * @return GB(F) a finite non-commutative Groebner base of F, if it exists. */ public List> GB( List> F ) { GenWordPolynomial p; List> G = new ArrayList>(); WordPairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while ( it.hasNext() ) { p = it.next(); if ( p.length() > 0 ) { p = p.monic(); if ( p.isONE() ) { G.clear(); G.add( p ); return G; // since no threads are activated } G.add( p ); if ( pairlist == null ) { //pairlist = new OrderedPairlist(p.ring ); pairlist = strategy.create( p.ring ); if ( ! p.ring.coFac.isField() ) { throw new IllegalArgumentException("coefficients not from a field"); } } // putOne not required pairlist.put( p ); } else { l--; } } if ( l <= 1 ) { return G; // since no threads are activated } logger.info("start " + pairlist); WordPair pair; GenWordPolynomial pi; GenWordPolynomial pj; List> S; GenWordPolynomial H; while ( pairlist.hasNext() ) { pair = pairlist.removeNext(); //logger.debug("pair = " + pair); if ( pair == null ) { continue; } pi = pair.pi; pj = pair.pj; if ( /*false &&*/ debug ) { logger.debug("pi = " + pi ); logger.debug("pj = " + pj ); } S = red.SPolynomials( pi, pj ); if ( S.isEmpty() ) { continue; } for ( GenWordPolynomial s : S ) { if ( s.isZERO() ) { //pair.setZero(); continue; } if ( debug ) { logger.debug("ht(S) = " + s.leadingWord() ); } H = red.normalform( G, s ); if ( debug ) { //logger.info("pair = " + pair); //logger.info("ht(S) = " + S.monic()); //.leadingWord() ); logger.info("ht(H) = " + H.monic()); //.leadingWord() ); } if ( H.isZERO() ) { //pair.setZero(); continue; } H = H.monic(); if ( debug ) { logger.info("ht(H) = " + H.leadingWord() ); } if ( H.isONE() ) { G.clear(); G.add( H ); return G; // since no threads are activated } if ( debug ) { logger.info("H = " + H ); } if ( H.length() > 0 ) { l++; G.add( H ); pairlist.put( H ); } } } logger.debug("#sequential list = " + G.size()); G = minimalGB(G); logger.info("" + pairlist); return G; } } jas-2.5/src/edu/jas/gb/SolvableReduction.java0000644000175000017500000000776211143275762021367 0ustar giovannigiovanni/* * $Id: SolvableReduction.java 2412 2009-02-07 12:17:54Z kredel $ */ package edu.jas.gb; import java.util.List; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.structure.RingElem; /** * Solvable polynomial Reduction interface. * Defines S-Polynomial, normalform * and irreducible set. * @param coefficient type * @author Heinz Kredel */ public interface SolvableReduction> { /** * Left S-Polynomial. * @param Ap solvable polynomial. * @param Bp solvable polynomial. * @return left-spol(Ap,Bp) the left S-polynomial of Ap and Bp. */ public GenSolvablePolynomial leftSPolynomial(GenSolvablePolynomial Ap, GenSolvablePolynomial Bp); /** * S-Polynomial with recording. * @param S recording matrix, is modified. * @param i index of Ap in basis list. * @param Ap a polynomial. * @param j index of Bp in basis list. * @param Bp a polynomial. * @return leftSpol(Ap, Bp), the left S-Polynomial for Ap and Bp. */ public GenSolvablePolynomial leftSPolynomial(List> S, int i, GenSolvablePolynomial Ap, int j, GenSolvablePolynomial Bp); /** * Left Normalform. * @param Ap solvable polynomial. * @param Pp solvable polynomial list. * @return left-nf(Ap) with respect to Pp. */ public GenSolvablePolynomial leftNormalform(List> Pp, GenSolvablePolynomial Ap); /** * LeftNormalform with recording. * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the left normal form of Ap wrt. Pp. */ public GenSolvablePolynomial leftNormalform(List> row, List> Pp, GenSolvablePolynomial Ap); /** * Left Normalform Set. * @param Ap solvable polynomial list. * @param Pp solvable polynomial list. * @return list of left-nf(a) with respect to Pp for all a in Ap. */ public List> leftNormalform(List> Pp, List> Ap); /** * Left irreducible set. * @param Pp solvable polynomial list. * @return a list P of solvable polynomials which are in normalform wrt. P. */ public List> leftIrreducibleSet(List> Pp); /** * Is reduction of normal form. * @param row recording matrix, is modified. * @param Pp a solvable polynomial list for reduction. * @param Ap a solvable polynomial. * @param Np nf(Pp,Ap), a left normal form of Ap wrt. Pp. * @return true, if Np + sum( row[i]*Pp[i] ) == Ap, else false. */ public boolean isLeftReductionNF(List> row, List> Pp, GenSolvablePolynomial Ap, GenSolvablePolynomial Np); /** * Right S-Polynomial. * @param Ap solvable polynomial. * @param Bp solvable polynomial. * @return right-spol(Ap,Bp) the right S-polynomial of Ap and Bp. */ public GenSolvablePolynomial rightSPolynomial(GenSolvablePolynomial Ap, GenSolvablePolynomial Bp); /** * Right Normalform. * @param Ap solvable polynomial. * @param Pp solvable polynomial list. * @return right-nf(Ap) with respect to Pp. */ public GenSolvablePolynomial rightNormalform(List> Pp, GenSolvablePolynomial Ap); } jas-2.5/src/edu/jas/gb/ReductionAbstract.java0000644000175000017500000003323512045261354021347 0ustar giovannigiovanni/* * $Id: ReductionAbstract.java 4283 2012-11-03 18:31:09Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Polynomial Reduction abstract class. Implements common S-Polynomial, * normalform, criterion 4 module criterion and irreducible set. * @param coefficient type * @author Heinz Kredel */ public abstract class ReductionAbstract> implements Reduction { private static final Logger logger = Logger.getLogger(ReductionAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public ReductionAbstract() { } /** * S-Polynomial. * @param A polynomial. * @param B polynomial. * @return spol(A,B) the S-polynomial of A and B. */ public GenPolynomial SPolynomial(GenPolynomial A, GenPolynomial B) { if (B == null || B.isZERO()) { if (A == null) { return B; } return A.ring.getZERO(); } if (A == null || A.isZERO()) { return B.ring.getZERO(); } if (debug) { if (!A.ring.equals(B.ring)) { logger.error("rings not equal " + A.ring + ", " + B.ring); } } Map.Entry ma = A.leadingMonomial(); Map.Entry mb = B.leadingMonomial(); ExpVector e = ma.getKey(); ExpVector f = mb.getKey(); ExpVector g = e.lcm(f); ExpVector e1 = g.subtract(e); ExpVector f1 = g.subtract(f); C a = ma.getValue(); C b = mb.getValue(); //GenPolynomial App = A.multiply(b, e1); //GenPolynomial Bpp = B.multiply(a, f1); //GenPolynomial Cp = App.subtract(Bpp); GenPolynomial Cp = A.scaleSubtractMultiple(b,e1,a,f1,B); return Cp; } /** * S-Polynomial with recording. * @param S recording matrix, is modified. Note the negative * S-polynomial is recorded as required by all applications. * @param i index of Ap in basis list. * @param A a polynomial. * @param j index of Bp in basis list. * @param B a polynomial. * @return Spol(A, B), the S-Polynomial for A and B. */ public GenPolynomial SPolynomial(List> S, int i, GenPolynomial A, int j, GenPolynomial B) { if (debug) { if (B == null || B.isZERO()) { throw new ArithmeticException("Spol B is zero"); } if (A == null || A.isZERO()) { throw new ArithmeticException("Spol A is zero"); } if (!A.ring.equals(B.ring)) { logger.error("rings not equal " + A.ring + ", " + B.ring); } } Map.Entry ma = A.leadingMonomial(); Map.Entry mb = B.leadingMonomial(); ExpVector e = ma.getKey(); ExpVector f = mb.getKey(); ExpVector g = e.lcm(f); ExpVector e1 = g.subtract(e); ExpVector f1 = g.subtract(f); C a = ma.getValue(); C b = mb.getValue(); //GenPolynomial App = A.multiply(b, e1); //GenPolynomial Bpp = B.multiply(a, f1); //GenPolynomial Cp = App.subtract(Bpp); GenPolynomial Cp = A.scaleSubtractMultiple(b,e1,a,f1,B); GenPolynomial zero = A.ring.getZERO(); GenPolynomial As = zero.sum(b.negate(), e1); GenPolynomial Bs = zero.sum(a /*correct .negate()*/, f1); S.set(i, As); S.set(j, Bs); return Cp; } /** * Module criterium. * @param modv number of module variables. * @param A polynomial. * @param B polynomial. * @return true if the module S-polynomial(i,j) is required. */ public boolean moduleCriterion(int modv, GenPolynomial A, GenPolynomial B) { if (modv == 0) { return true; } ExpVector ei = A.leadingExpVector(); ExpVector ej = B.leadingExpVector(); return moduleCriterion(modv, ei, ej); } /** * Module criterium. * @param modv number of module variables. * @param ei ExpVector. * @param ej ExpVector. * @return true if the module S-polynomial(i,j) is required. */ public boolean moduleCriterion(int modv, ExpVector ei, ExpVector ej) { if (modv == 0) { return true; } if (ei.invLexCompareTo(ej, 0, modv) != 0) { return false; // skip pair } return true; } /** * GB criterium 4. Use only for commutative polynomial rings. * @param A polynomial. * @param B polynomial. * @param e = lcm(ht(A),ht(B)) * @return true if the S-polynomial(i,j) is required, else false. */ public boolean criterion4(GenPolynomial A, GenPolynomial B, ExpVector e) { if (logger.isInfoEnabled()) { if (!A.ring.equals(B.ring)) { logger.error("rings not equal " + A.ring + ", " + B.ring); } if (!A.ring.isCommutative()) { //B instanceof GenSolvablePolynomial ) { logger.error("GBCriterion4 not applicabable to non-commutative polynomials"); return true; } } ExpVector ei = A.leadingExpVector(); ExpVector ej = B.leadingExpVector(); return criterion4(ei,ej,e); } /** * GB criterium 4. Use only for commutative polynomial rings. * @param ei exponent vector. * @param ej exponent vector. * @param e = lcm(ei,ej) * @return true if the S-polynomial(i,j) is required, else false. */ public boolean criterion4(ExpVector ei, ExpVector ej, ExpVector e) { ExpVector g = ei.sum(ej); ExpVector h = g.subtract(e); int s = h.signum(); return s != 0; } /** * GB criterium 4. * @param A polynomial. * @param B polynomial. * @return true if the S-polynomial(i,j) is required, else false. */ public boolean criterion4(GenPolynomial A, GenPolynomial B) { if (logger.isInfoEnabled()) { if (!A.ring.isCommutative() || !B.ring.isCommutative()) { // A instanceof GenSolvablePolynomial logger.error("GBCriterion4 not applicabable to non-commutative polynomials"); return true; } } ExpVector ei = A.leadingExpVector(); ExpVector ej = B.leadingExpVector(); ExpVector e = ei.lcm(ej); return criterion4(ei,ej,e); } /** * Normalform Set. * @param Ap polynomial list. * @param Pp polynomial list. * @return list of nf(a) with respect to Pp for all a in Ap. */ public List> normalform(List> Pp, List> Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isEmpty()) { return Ap; } ArrayList> red = new ArrayList>(); for (GenPolynomial A : Ap) { A = normalform(Pp, A); red.add(A); } return red; } /** * Is top reducible. * @param A polynomial. * @param P polynomial list. * @return true if A is top reducible with respect to P. */ public boolean isTopReducible(List> P, GenPolynomial A) { if (P == null || P.isEmpty()) { return false; } if (A == null || A.isZERO()) { return false; } boolean mt = false; ExpVector e = A.leadingExpVector(); for (GenPolynomial p : P) { mt = e.multipleOf(p.leadingExpVector()); if (mt) { return true; } } return false; } /** * Is reducible. * @param Ap polynomial. * @param Pp polynomial list. * @return true if Ap is reducible with respect to Pp. */ public boolean isReducible(List> Pp, GenPolynomial Ap) { return !isNormalform(Pp, Ap); } /** * Is in Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @return true if Ap is in normalform with respect to Pp. */ @SuppressWarnings("unchecked") public boolean isNormalform(List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return true; } if (Ap == null || Ap.isZERO()) { return true; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[l]; GenPolynomial[] p = new GenPolynomial[l]; Map.Entry m; int i; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); j++; } } l = j; boolean mt = false; for (ExpVector e : Ap.getMap().keySet()) { for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { return false; } } } return true; } /** * Is in Normalform. * @param Pp polynomial list. * @return true if each Ap in Pp is in normalform with respect to Pp\{Ap}. */ public boolean isNormalform(List> Pp) { if (Pp == null || Pp.isEmpty()) { return true; } GenPolynomial Ap; List> P = new LinkedList>(Pp); int s = P.size(); for (int i = 0; i < s; i++) { Ap = P.remove(i); if (!isNormalform(P, Ap)) { return false; } P.add(Ap); } return true; } /** * Irreducible set. * @param Pp polynomial list. * @return a list P of monic polynomials which are in normalform wrt. P and * with ideal(Pp) = ideal(P). */ public List> irreducibleSet(List> Pp) { ArrayList> P = new ArrayList>(); for (GenPolynomial a : Pp) { if (a.length() != 0) { a = a.monic(); if (a.isONE()) { P.clear(); P.add(a); return P; } P.add(a); } } int l = P.size(); if (l <= 1) return P; int irr = 0; ExpVector e; ExpVector f; GenPolynomial a; logger.debug("irr = "); while (irr != l) { //it = P.listIterator(); //a = P.get(0); //it.next(); a = P.remove(0); e = a.leadingExpVector(); a = normalform(P, a); logger.debug(String.valueOf(irr)); if (a.length() == 0) { l--; if (l <= 1) { return P; } } else { f = a.leadingExpVector(); if (f.signum() == 0) { P = new ArrayList>(); P.add(a.monic()); return P; } if (e.equals(f)) { irr++; } else { irr = 0; a = a.monic(); } P.add(a); } } //System.out.println(); return P; } /** * Is reduction of normal form. * @param row recording matrix. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @param Np nf(Pp,Ap), a normal form of Ap wrt. Pp. * @return true, if Np + sum( row[i]*Pp[i] ) == Ap, else false. */ public boolean isReductionNF(List> row, List> Pp, GenPolynomial Ap, GenPolynomial Np) { if (row == null && Pp == null) { if (Ap == null) { return Np == null; } return Ap.equals(Np); } if (row == null || Pp == null) { return false; } if (row.size() != Pp.size()) { return false; } GenPolynomial t = Np; //System.out.println("t0 = " + t ); GenPolynomial r; GenPolynomial p; for (int m = 0; m < Pp.size(); m++) { r = row.get(m); p = Pp.get(m); if (r != null && p != null) { if (t == null) { t = r.multiply(p); } else { t = t.sum(r.multiply(p)); } } //System.out.println("r = " + r ); //System.out.println("p = " + p ); } //System.out.println("t+ = " + t ); if (t == null) { if (Ap == null) { return true; } return Ap.isZERO(); } r = t.subtract(Ap); boolean z = r.isZERO(); if (!z) { logger.info("t = " + t); logger.info("a = " + Ap); logger.info("t-a = " + r); } return z; } } jas-2.5/src/edu/jas/gb/ExtendedGB.java0000644000175000017500000000450511505424264017677 0ustar giovannigiovanni/* * $Id: ExtendedGB.java 3445 2010-12-25 17:24:04Z kredel $ */ package edu.jas.gb; import java.util.List; import edu.jas.structure.RingElem; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.ModuleList; import edu.jas.poly.PolynomialList; /** * Container for a GB and transformation matrices. * A container for F, G, calG and calF. * Immutable objects. * @param coefficient type * @param F an ideal base. * @param G a Groebner base of F. * @param F2G a transformation matrix from F to G. * @param G2F a transformation matrix from G to F. */ public class ExtendedGB> { public final List> F; public final List> G; public final List>> F2G; public final List>> G2F; public final GenPolynomialRing ring; public ExtendedGB( List> F, List> G, List>> F2G, List>> G2F) { this.F = F; this.G = G; this.F2G = F2G; this.G2F = G2F; GenPolynomialRing r = null; if ( G != null ) { for ( GenPolynomial p : G ) { if ( p != null ) { r = p.ring; break; } } if ( r != null && r.getVars() == null ) { r.setVars( r.newVars("y") ); } } this.ring = r; } /** Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { PolynomialList P; ModuleList M; StringBuffer s = new StringBuffer("ExtendedGB: \n\n"); P = new PolynomialList( ring, F ); s.append("F = " + P + "\n\n"); P = new PolynomialList( ring, G ); s.append("G = " + P + "\n\n"); M = new ModuleList( ring, F2G ); s.append("F2G = " + M + "\n\n"); M = new ModuleList( ring, G2F ); s.append("G2F = " + M + "\n"); return s.toString(); } } jas-2.5/src/edu/jas/gb/OrderedWordPairlist.java0000644000175000017500000002145312020721402021642 0ustar giovannigiovanni/* * $Id: OrderedWordPairlist.java 4157 2012-09-02 18:18:43Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.BitSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.SortedMap; import org.apache.log4j.Logger; import edu.jas.poly.Word; import edu.jas.poly.Overlap; import edu.jas.poly.OverlapList; import edu.jas.poly.GenWordPolynomial; import edu.jas.poly.GenWordPolynomialRing; import edu.jas.structure.RingElem; /** * Pair list management of word polynomials. * Implemented using GenWordPolynomial, TreeMap and BitSet. * @author Heinz Kredel */ public class OrderedWordPairlist > implements WordPairList { protected final List> P; protected final SortedMap>> pairlist; protected final List red; protected final GenWordPolynomialRing ring; protected final WordReduction reduction; protected boolean oneInGB = false; protected int putCount; protected int remCount; private static final Logger logger = Logger.getLogger(OrderedWordPairlist.class); /** * Constructor. */ public OrderedWordPairlist() { ring = null; P = null; pairlist = null; red = null; reduction = null; putCount = 0; remCount = 0; } /** * Constructor. * @param r word polynomial factory. */ public OrderedWordPairlist(GenWordPolynomialRing r) { ring = r; P = new ArrayList>(); pairlist = new TreeMap>>( ring.alphabet.getAscendComparator() ); red = new ArrayList(); putCount = 0; remCount = 0; reduction = new WordReductionSeq(); } /** * Create a new WordPairList. * @param r word polynomial ring. */ public WordPairList create(GenWordPolynomialRing r) { return new OrderedWordPairlist(r); } /** * toString. */ @Override public String toString() { StringBuffer s = new StringBuffer(this.getClass().getSimpleName() + "("); //s.append("polys="+P.size()); s.append("#put="+putCount); s.append(", #rem="+remCount); if ( pairlist != null && pairlist.size() != 0 ) { s.append(", size="+pairlist.size()); } s.append(")"); return s.toString(); } /** * Put one Polynomial to the pairlist and reduction matrix. * @param p polynomial. * @return the index of the added polynomial. */ public synchronized int put(GenWordPolynomial p) { putCount++; if ( oneInGB ) { return P.size()-1; } Word e = p.leadingWord(); int l = P.size(); for ( int j = 0; j < l; j++ ) { GenWordPolynomial pj = P.get(j); Word f = pj.leadingWord(); Word g = f.lcm(e); //System.out.println("g = " + g); if ( g == null ) { //System.out.println("criterion 4"); continue; // criterion 4 } WordPair pair = new WordPair( pj, p, j, l); //System.out.println("pair.new = " + pair); //multiple pairs under same keys -> list of pairs LinkedList> xl = pairlist.get( g ); if ( xl == null ) { xl = new LinkedList>(); } //xl.addLast( pair ); // first or last ? xl.addFirst( pair ); // first or last ? better for d- e-GBs pairlist.put( g, xl ); } //System.out.println("pairlist.keys@put = " + pairlist.keySet() ); //System.out.println("#pairlist = " + pairlist.size() ); P.add( p ); BitSet redi = new BitSet(); redi.set( 0, l ); red.add( redi ); //System.out.println("pairlist.set = " + red); //.get( pair.j )); //pair); //System.out.println("pairlist.key = " + pairlist.keySet() ); return P.size()-1; } /** * Remove the next required pair from the pairlist and reduction matrix. * Appy the criterions 3 and 4 to see if the S-polynomial is required. * @return the next pair if one exists, otherwise null. */ public synchronized WordPair removeNext() { if ( oneInGB ) { return null; } Iterator< Map.Entry>> > ip = pairlist.entrySet().iterator(); WordPair pair = null; boolean c = false; int i, j; while ( !c && ip.hasNext() ) { Map.Entry>> me = ip.next(); Word g = me.getKey(); LinkedList> xl = me.getValue(); if ( logger.isInfoEnabled() ) { logger.info("g = " + g); } pair = null; while ( !c && xl.size() > 0 ) { pair = xl.removeFirst(); // xl is also modified in pairlist i = pair.i; j = pair.j; // System.out.println("pair(" + j + "," +i+") "); c = criterion3( i, j, g ); // should be okay //if ( !c ) { // System.out.println("criterion 3"); //} //System.out.println("c3_o = " + c); red.get( j ).clear(i); // set(i,false) jdk1.4 } if ( xl.size() == 0 ) { ip.remove(); // = pairlist.remove( g ); } } if ( ! c ) { pair = null; } else { remCount++; // count only real pairs } return pair; } /** * Test if there is possibly a pair in the list. * @return true if a next pair could exist, otherwise false. */ public synchronized boolean hasNext() { return pairlist.size() > 0; } /** * Get the list of polynomials. * @return the polynomial list. */ public List> getList() { return P; } /** * Get the number of polynomials put to the pairlist. * @return the number of calls to put. */ public synchronized int putCount() { return putCount; } /** * Get the number of required pairs removed from the pairlist. * @return the number of non null pairs delivered. */ public synchronized int remCount() { return remCount; } /** * Put the ONE-Polynomial to the pairlist. * @param one polynomial. (no more required) * @return the index of the last polynomial. */ public synchronized int putOne(GenWordPolynomial one) { if ( one == null ) { return P.size()-1; } if ( ! one.isONE() ) { return P.size()-1; } return putOne(); } /** * Put the ONE-Polynomial to the pairlist. * @return the index of the last polynomial. */ public synchronized int putOne() { putCount++; oneInGB = true; pairlist.clear(); P.clear(); P.add(ring.getONE()); red.clear(); return P.size()-1; } /** * GB criterium 3. * @return true if the S-polynomial(i,j) is required. */ public boolean criterion3(int i, int j, Word eij) { // assert i < j; boolean s = red.get( j ).get(i); if ( ! s ) { logger.warn("c3.s false for " + j + " " + i); return s; } // now s = true; for ( int k = 0; k < P.size(); k++ ) { // System.out.println("i , k , j "+i+" "+k+" "+j); if ( i != k && j != k ) { GenWordPolynomial A = P.get( k ); Word ek = A.leadingWord(); boolean m = eij.multipleOf(ek); if ( m ) { if ( k < i ) { // System.out.println("k < i "+k+" "+i); s = red.get( i ).get(k) || red.get( j ).get(k); } else if ( i < k && k < j ) { // System.out.println("i < k < j "+i+" "+k+" "+j); s = red.get( k ).get(i) || red.get( j ).get(k); } else if ( j < k ) { //System.out.println("j < k "+j+" "+k); s = red.get( k ).get(i) || red.get( k ).get(j); } //System.out.println("s."+k+" = " + s); if ( ! s ) { return s; } } } } return true; } } jas-2.5/src/edu/jas/gb/GroebnerBaseSeqPairParallel.java0000644000175000017500000003056412004474232023225 0ustar giovannigiovanni/* * $Id: GroebnerBaseSeqPairParallel.java 4059 2012-07-27 11:16:42Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; /** * Groebner Base parallel algorithm. Makes some effort to produce the same * sequence of critical pairs as in the sequential version. However already * reduced pairs are not rereduced if new polynomials appear. Implements a * shared memory parallel version of Groebner bases. Slaves maintain pairlist. * @param coefficient type * @author Heinz Kredel */ public class GroebnerBaseSeqPairParallel> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBaseSeqPairParallel.class); /** * Number of threads to use. */ protected final int threads; /** * Pool of threads to use. */ protected transient final ThreadPool pool; /** * Constructor. */ public GroebnerBaseSeqPairParallel() { this(2); } /** * Constructor. * @param threads number of threads to use. */ public GroebnerBaseSeqPairParallel(int threads) { this(threads, new ThreadPool(threads)); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. */ public GroebnerBaseSeqPairParallel(int threads, ThreadPool pool) { this(threads, pool, new ReductionPar()); } /** * Constructor. * @param threads number of threads to use. * @param red parallelism aware reduction engine */ public GroebnerBaseSeqPairParallel(int threads, Reduction red) { this(threads, new ThreadPool(threads), red); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param red parallelism aware reduction engine */ public GroebnerBaseSeqPairParallel(int threads, ThreadPool pool, Reduction red) { super(red); if (!(red instanceof ReductionPar)) { logger.warn("parallel GB should use parallel aware reduction"); } if (threads < 1) { threads = 1; } this.threads = threads; this.pool = pool; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { if (pool == null) { return; } pool.terminate(); } /** * Cancel ThreadPool. */ @Override public int cancel() { if (pool == null) { return 0; } int s = pool.cancel(); return s; } /** * Parallel Groebner base using sequential pair order class. Slaves maintain * pairlist. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> GB(int modv, List> F) { GenPolynomial p; List> G = new ArrayList>(); CriticalPairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads activated jet } G.add(p); if (pairlist == null) { pairlist = new CriticalPairList(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // putOne not required pairlist.put(p); } else { l--; } } if (l <= 1) { return G; // since no threads activated jet } Terminator fin = new Terminator(threads); ReducerSeqPair R; for (int i = 0; i < threads; i++) { R = new ReducerSeqPair(fin, G, pairlist); pool.addJob(R); } fin.waitDone(); if (Thread.currentThread().isInterrupted()) { throw new RuntimeException("interrupt before minimalGB"); } logger.debug("#parallel list = " + G.size()); G = minimalGB(G); // not in this context // pool.terminate(); logger.info("" + pairlist); return G; } /** * Minimal ordered groebner basis, parallel. * @param Fp a Groebner base. * @return minimalGB(F) a minimal Groebner base of Fp. */ @Override public List> minimalGB(List> Fp) { GenPolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); // no thread at this point } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiReducerSeqPair[] mirs = (MiReducerSeqPair[]) new MiReducerSeqPair[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new MiReducerSeqPair(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } } /** * Reducing worker threads. */ class ReducerSeqPair> implements Runnable { private final List> G; private final CriticalPairList pairlist; private final Terminator fin; private final ReductionPar red; private static final Logger logger = Logger.getLogger(ReducerSeqPair.class); ReducerSeqPair(Terminator fin, List> G, CriticalPairList L) { this.fin = fin; this.G = G; pairlist = L; red = new ReductionPar(); } /** * to string */ @Override public String toString() { return "ReducerSeqPair"; } public void run() { CriticalPair pair; GenPolynomial S; GenPolynomial H; boolean set = false; int reduction = 0; int sleeps = 0; while (pairlist.hasNext() || fin.hasJobs()) { while (!pairlist.hasNext()) { pairlist.update(); // wait fin.beIdle(); set = true; try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } else { logger.debug("r"); } Thread.sleep(100); } catch (InterruptedException e) { break; } if (!fin.hasJobs()) { break; } if (Thread.currentThread().isInterrupted()) { throw new RuntimeException("interrupt after sleep"); } } if (!pairlist.hasNext() && !fin.hasJobs()) { break; } if (set) { fin.notIdle(); set = false; } pair = pairlist.getNext(); if (Thread.currentThread().isInterrupted()) { throw new RuntimeException("interrupt after getNext"); } if (pair == null) { pairlist.update(); continue; } if (logger.isDebugEnabled()) { logger.debug("pi = " + pair.pi); logger.debug("pj = " + pair.pj); } S = red.SPolynomial(pair.pi, pair.pj); if (S.isZERO()) { pairlist.record(pair, S); continue; } if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(G, S); //mod reduction++; if (H.isZERO()) { pairlist.record(pair, H); continue; } if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = H.monic(); // System.out.println("H = " + H); if (H.isONE()) { // pairlist.update( pair, H ); pairlist.putOne(); // not really required synchronized (G) { G.clear(); G.add(H); } fin.allIdle(); return; } if (logger.isDebugEnabled()) { logger.debug("H = " + H); } synchronized (G) { G.add(H); } pairlist.update(pair, H); //pairlist.record( pair, H ); //pairlist.update(); } logger.info("terminated, done " + reduction + " reductions"); } } /** * Reducing worker threads for minimal GB. */ class MiReducerSeqPair> implements Runnable { private final List> G; private GenPolynomial H; private final ReductionPar red; private final Semaphore done = new Semaphore(0); private static final Logger logger = Logger.getLogger(MiReducerSeqPair.class); MiReducerSeqPair(List> G, GenPolynomial p) { this.G = G; H = p; red = new ReductionPar(); } /** * to string */ @Override public String toString() { return "MiReducerSeqpair"; } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenPolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException e) { throw new RuntimeException("interrupt in getNF"); } return H; } public void run() { if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } try { H = red.normalform(G, H); //mod done.release(); //done.V(); } catch (RuntimeException e) { Thread.currentThread().interrupt(); //throw new RuntimeException("interrupt in getNF"); } if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } jas-2.5/src/edu/jas/gb/CriticalPair.java0000644000175000017500000000572612004043370020270 0ustar giovannigiovanni/* * $Id: CriticalPair.java 4052 2012-07-25 19:20:25Z kredel $ */ package edu.jas.gb; import java.io.Serializable; import edu.jas.structure.RingElem; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; /** * Serializable subclass to hold critical pairs of polynomials. * Used also to manage reduction status of the pair. * @param coefficient type * @author Heinz Kredel. */ public class CriticalPair > extends AbstractPair { protected volatile boolean inReduction; protected volatile GenPolynomial reductum; //public final ExpVector sugar; /** * CriticalPair constructor. * @param e lcm(lt(pi),lt(pj). * @param pi polynomial i. * @param pj polynomial j. * @param i index of pi. * @param j index pf pj. */ public CriticalPair(ExpVector e, GenPolynomial pi, GenPolynomial pj, int i, int j) { super(e,pi,pj,i,j); inReduction = false; reductum = null; } /** * toString. */ @Override public String toString() { StringBuffer s = new StringBuffer(super.toString() + "[ "); if ( inReduction ) { s.append("," + inReduction); } if ( reductum != null ) { s.append("," + reductum.leadingExpVector()); } s.append(" ]"); return s.toString(); } /** * Set in reduction status. * inReduction is set to true. */ public void setInReduction() { if ( inReduction ) { throw new IllegalStateException("already in reduction " + this); } inReduction = true; } /** * Get in reduction status. * @return true if the polynomial is currently in reduction, else false. */ public boolean getInReduction() { return inReduction; } /** * Get reduced polynomial. * @return the reduced polynomial or null if not done. */ public GenPolynomial getReductum() { return reductum; } /** * Set reduced polynomial. * @param r the reduced polynomial. */ public void setReductum(GenPolynomial r) { if ( r == null ) { throw new IllegalArgumentException("reduction null not allowed " + this); } inReduction = false; reductum = r; } /** * Is reduced to zero. * @return true if the S-polynomial of this CriticalPair * was reduced to ZERO, else false. */ public boolean isZERO() { if ( reductum == null ) { // not jet done return false; } return reductum.isZERO(); } /** * Is reduced to one. * @return true if the S-polynomial of this CriticalPair was * reduced to ONE, else false. */ public boolean isONE() { if ( reductum == null ) { // not jet done return false; } return reductum.isONE(); } } jas-2.5/src/edu/jas/gb/GBDistHybrid.java0000644000175000017500000001055612067303544020210 0ustar giovannigiovanni/* * $Id: GBDistHybrid.java 4334 2012-12-28 11:49:57Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.util.List; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.DistThreadPool; import edu.jas.util.RemoteExecutable; /** * Setup to run a distributed GB example. * @author Heinz Kredel * @deprecated use GroebnerBaseDistributedHybridEC */ @Deprecated public class GBDistHybrid> { /** * machine file to use. */ private final String mfile; /** * Number of threads to use. */ protected final int threads; /** * Number of threads per node to use. */ protected final int threadsPerNode; /** * Server port to use. */ protected final int port; /** * GB algorithm to use. */ private final GroebnerBaseDistributedHybrid bbd; /** * Distributed thread pool to use. */ private final DistThreadPool dtp; /** * Constructor. * @param threads number of threads respectivly processes. * @param threadsPerNode number of threads per node to use. * @param mfile name of the machine file. * @param port for GB server. */ public GBDistHybrid(int threads, int threadsPerNode, String mfile, int port) { this(threads, threadsPerNode, new OrderedPairlist(), mfile, port); } /** * Constructor. * @param threads number of threads respectivly processes. * @param threadsPerNode number of threads per node to use. * @param pl pair selection strategy * @param mfile name of the machine file. * @param port for GB server. */ public GBDistHybrid(int threads, int threadsPerNode, PairList pl, String mfile, int port) { this.threads = threads; this.threadsPerNode = threadsPerNode; if (mfile == null || mfile.length() == 0) { this.mfile = "../util/machines"; } else { this.mfile = mfile; } this.port = port; bbd = new GroebnerBaseDistributedHybrid(threads, threadsPerNode, pl, this.port); dtp = new DistThreadPool(threads, this.mfile); // findbugs } /** * Execute a distributed GB example. Distribute clients and start master. * @param F list of polynomials * @return GB(F) a Groebner base for F. */ public List> execute(List> F) { String master = dtp.getEC().getMasterHost(); int port = dtp.getEC().getMasterPort(); GBClientHybrid gbc = new GBClientHybrid(threadsPerNode, master, port); for (int i = 0; i < threads; i++) { // schedule remote clients dtp.addJob(gbc); } // run master List> G = bbd.GB(F); return G; } /** * Terminates the distributed thread pools. * @param shutDown true, if shut-down of the remote executable servers is * requested, false, if remote executable servers stay alive. */ public void terminate(boolean shutDown) { bbd.terminate(); dtp.terminate(shutDown); } } /** * Objects of this class are to be send to a ExecutableServer. */ class GBClientHybrid> implements RemoteExecutable { String host; int port; //int threads; int threadsPerNode; /** * GBClientHybrid. * @param threadsPerNode * @param host master * @param port */ public GBClientHybrid(int threadsPerNode, String host, int port) { //this.threads = threads; this.threadsPerNode = threadsPerNode; this.host = host; this.port = port; } /** Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return "GBClientHybrid(" + threadsPerNode + ", " + host + ":" + port + " )"; } /** * run. */ public void run() { GroebnerBaseDistributedHybrid bbd; bbd = new GroebnerBaseDistributedHybrid(1, threadsPerNode, null, null, port); try { bbd.clientPart(host); } catch (IOException e) { System.out.println("clientPart, exception " + e); } catch (Exception e) { System.out.println("clientPart, exception " + e); } bbd.terminate(); } } jas-2.5/src/edu/jas/gb/GroebnerBaseDistributedHybrid.java0000644000175000017500000010135412040756652023635 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistributedHybrid.java 4261 2012-10-21 11:34:02Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.ChannelFactory; import edu.jas.util.DistHashTable; import edu.jas.util.DistHashTableServer; import edu.jas.util.SocketChannel; import edu.jas.util.TaggedSocketChannel; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; /** * Groebner Base distributed hybrid algorithm. Implements a distributed memory * with multi-core CPUs parallel version of Groebner bases. Using pairlist * class, distributed multi-threaded tasks do reduction, one communication * channel per remote node. * @param coefficient type * @author Heinz Kredel * @deprecated use GroebnerBaseDistributedHybridEC */ public class GroebnerBaseDistributedHybrid> extends GroebnerBaseAbstract { public static final Logger logger = Logger.getLogger(GroebnerBaseDistributedHybrid.class); public final boolean debug = logger.isDebugEnabled(); /** * Number of threads to use. */ protected final int threads; /** * Default number of threads. */ protected static final int DEFAULT_THREADS = 2; /** * Number of threads per node to use. */ protected final int threadsPerNode; /** * Default number of threads per compute node. */ protected static final int DEFAULT_THREADS_PER_NODE = 1; /** * Pool of threads to use. */ //protected final ExecutorService pool; // not for single node tests protected transient final ThreadPool pool; /** * Default server port. */ protected static final int DEFAULT_PORT = 4711; /** * Server port to use. */ protected final int port; /** * Message tag for pairs. */ public static final Integer pairTag = Integer.valueOf(1); /** * Message tag for results. */ public static final Integer resultTag = Integer.valueOf(2); /** * Message tag for acknowledgments. */ public static final Integer ackTag = Integer.valueOf(3); /** * Constructor. */ public GroebnerBaseDistributedHybrid() { this(DEFAULT_THREADS, DEFAULT_PORT); } /** * Constructor. * @param threads number of threads to use. */ public GroebnerBaseDistributedHybrid(int threads) { this(threads, new ThreadPool(threads), DEFAULT_PORT); } /** * Constructor. * @param threads number of threads to use. * @param port server port to use. */ public GroebnerBaseDistributedHybrid(int threads, int port) { this(threads, new ThreadPool(threads), port); } /** * Constructor. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. * @param port server port to use. */ public GroebnerBaseDistributedHybrid(int threads, int threadsPerNode, int port) { this(threads, threadsPerNode, new ThreadPool(threads), port); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param port server port to use. */ public GroebnerBaseDistributedHybrid(int threads, ThreadPool pool, int port) { this(threads, DEFAULT_THREADS_PER_NODE, pool, port); } /** * Constructor. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. * @param pl pair selection strategy * @param port server port to use. */ public GroebnerBaseDistributedHybrid(int threads, int threadsPerNode, PairList pl, int port) { this(threads, threadsPerNode, new ThreadPool(threads), pl, port); } /** * Constructor. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. * @param port server port to use. */ public GroebnerBaseDistributedHybrid(int threads, int threadsPerNode, ThreadPool pool, int port) { this(threads, threadsPerNode, pool, new OrderedPairlist(), port); } /** * Constructor. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. * @param pool ThreadPool to use. * @param pl pair selection strategy * @param port server port to use. */ public GroebnerBaseDistributedHybrid(int threads, int threadsPerNode, ThreadPool pool, PairList pl, int port) { super(new ReductionPar(), pl); if (threads < 1) { threads = 1; } this.threads = threads; this.threadsPerNode = threadsPerNode; this.pool = pool; this.port = port; //logger.info("generated pool: " + pool); } /** * Cleanup and terminate. */ @Override public void terminate() { if (pool == null) { return; } pool.terminate(); } /** * Distributed hybrid Groebner base. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs. */ public List> GB(int modv, List> F) { long t = System.currentTimeMillis(); final int DL_PORT = port + 100; ChannelFactory cf = new ChannelFactory(port); cf.init(); DistHashTableServer dls = new DistHashTableServer(DL_PORT); dls.init(); logger.debug("dist-list server running"); GenPolynomial p; List> G = new ArrayList>(); PairList pairlist = null; boolean oneInGB = false; int l = F.size(); int unused; ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { oneInGB = true; G.clear(); G.add(p); //return G; must signal termination to others } if (!oneInGB) { G.add(p); } if (pairlist == null) { //pairlist = new OrderedPairlist(modv, p.ring); pairlist = strategy.create(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // theList not updated here if (p.isONE()) { unused = pairlist.putOne(); } else { unused = pairlist.put(p); } } else { l--; } } //if (l <= 1) { //return G; must signal termination to others //} logger.info("pairlist " + pairlist); logger.debug("looking for clients"); //long t = System.currentTimeMillis(); // now in DL, uses resend for late clients //while ( dls.size() < threads ) { sleep(); } DistHashTable> theList = new DistHashTable>( "localhost", DL_PORT); theList.init(); List> al = pairlist.getList(); for (int i = 0; i < al.size(); i++) { // no wait required GenPolynomial nn = theList.put(Integer.valueOf(i), al.get(i)); if (nn != null) { logger.info("double polynomials " + i + ", nn = " + nn + ", al(i) = " + al.get(i)); } } Terminator finner = new Terminator(threads * threadsPerNode); HybridReducerServer R; logger.info("using pool = " + pool); for (int i = 0; i < threads; i++) { R = new HybridReducerServer(threadsPerNode, finner, cf, theList, pairlist); pool.addJob(R); //logger.info("server submitted " + R); } logger.info("main loop waiting " + finner); finner.waitDone(); int ps = theList.size(); logger.info("#distributed list = " + ps); // make sure all polynomials arrived: not needed in master // G = (ArrayList)theList.values(); G = pairlist.getList(); if (ps != G.size()) { logger.info("#distributed list = " + theList.size() + " #pairlist list = " + G.size()); } for (GenPolynomial q : theList.getValueList()) { if (q != null && !q.isZERO()) { logger.debug("final q = " + q.leadingExpVector()); } } logger.debug("distributed list end"); long time = System.currentTimeMillis(); List> Gp; Gp = minimalGB(G); // not jet distributed but threaded time = System.currentTimeMillis() - time; logger.info("parallel gbmi time = " + time); G = Gp; logger.debug("server cf.terminate()"); cf.terminate(); // no more required // logger.info("server not pool.terminate() " + pool); //pool.terminate(); logger.info("server theList.terminate() " + theList.size()); theList.terminate(); logger.info("server dls.terminate() " + dls); dls.terminate(); t = System.currentTimeMillis() - t; logger.info("server GB end, time = " + t + ", " + pairlist.toString()); return G; } /** * GB distributed client. * @param host the server runs on. * @throws IOException */ public void clientPart(String host) throws IOException { ChannelFactory cf = new ChannelFactory(port + 10); // != port for localhost cf.init(); SocketChannel channel = cf.getChannel(host, port); TaggedSocketChannel pairChannel = new TaggedSocketChannel(channel); pairChannel.init(); if (debug) { logger.info("clientPart pairChannel = " + pairChannel); } final int DL_PORT = port + 100; DistHashTable> theList = new DistHashTable>(host, DL_PORT); theList.init(); //HybridReducerClient R = new HybridReducerClient(threadsPerNode, pairChannel, theList); //R.run(); ThreadPool pool = new ThreadPool(threadsPerNode); logger.info("client using pool = " + pool); for (int i = 0; i < threadsPerNode; i++) { HybridReducerClient Rr = new HybridReducerClient(threadsPerNode, pairChannel, i, theList); pool.addJob(Rr); } if (debug) { logger.info("clients submitted"); } pool.terminate(); logger.info("client pool.terminate()"); pairChannel.close(); logger.info("client pairChannel.close()"); theList.terminate(); cf.terminate(); logger.info("client cf.terminate()"); channel.close(); logger.info("client channel.close()"); return; } /** * Minimal ordered groebner basis. * @param Fp a Groebner base. * @return a reduced Groebner base of Fp. */ @Override public List> minimalGB(List> Fp) { GenPolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiReducerServer[] mirs = (MiReducerServer[]) new MiReducerServer[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new MiReducerServer(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } } /** * Distributed server reducing worker proxy threads. * @param coefficient type */ class HybridReducerServer> implements Runnable { public static final Logger logger = Logger.getLogger(HybridReducerServer.class); public final boolean debug = logger.isDebugEnabled(); private final Terminator finner; private final ChannelFactory cf; private TaggedSocketChannel pairChannel; private final DistHashTable> theList; private final PairList pairlist; private final int threadsPerNode; /** * Message tag for pairs. */ public final Integer pairTag = GroebnerBaseDistributedHybrid.pairTag; /** * Message tag for results. */ public final Integer resultTag = GroebnerBaseDistributedHybrid.resultTag; /** * Message tag for acknowledgments. */ public final Integer ackTag = GroebnerBaseDistributedHybrid.ackTag; /** * Constructor. * @param tpn number of threads per node * @param fin terminator * @param cf channel factory * @param dl distributed hash table * @param L ordered pair list */ HybridReducerServer(int tpn, Terminator fin, ChannelFactory cf, DistHashTable> dl, PairList L) { threadsPerNode = tpn; finner = fin; this.cf = cf; theList = dl; pairlist = L; //logger.info("reducer server created " + this); } /** * Work loop. * @see java.lang.Runnable#run() */ //JAVA6only: @Override public void run() { logger.info("reducer server running with " + cf); SocketChannel channel = null; try { channel = cf.getChannel(); pairChannel = new TaggedSocketChannel(channel); pairChannel.init(); } catch (InterruptedException e) { logger.debug("get pair channel interrupted"); e.printStackTrace(); return; } if (debug) { logger.info("pairChannel = " + pairChannel); } // record idle remote workers (minus one?) //finner.beIdle(threadsPerNode-1); finner.initIdle(threadsPerNode); AtomicInteger active = new AtomicInteger(0); // start receiver HybridReducerReceiver receiver = new HybridReducerReceiver(threadsPerNode, finner, active, pairChannel, theList, pairlist); receiver.start(); Pair pair; //boolean set = false; boolean goon = true; //int polIndex = -1; int red = 0; int sleeps = 0; // while more requests while (goon) { // receive request if thread is reported incactive logger.debug("receive request"); Object req = null; try { req = pairChannel.receive(pairTag); } catch (InterruptedException e) { goon = false; e.printStackTrace(); } catch (IOException e) { goon = false; e.printStackTrace(); } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } logger.info("received request, req = " + req); if (req == null) { goon = false; break; } if (!(req instanceof GBTransportMessReq)) { goon = false; break; } // find pair and manage termination status logger.info("find pair"); while (!pairlist.hasNext()) { // wait if (!finner.hasJobs() && !pairlist.hasNext()) { goon = false; break; } try { sleeps++; //if (sleeps % 10 == 0) { logger.info("waiting for reducers, remaining = " + finner.getJobs()); //} Thread.sleep(100); } catch (InterruptedException e) { goon = false; break; } } if (!pairlist.hasNext() && !finner.hasJobs()) { logger.info("termination detection: no pairs and no jobs left"); goon = false; break; //continue; //break? } finner.notIdle(); // before pairlist get!! pair = pairlist.removeNext(); // send pair to client, even if null if (debug) { logger.info("active count = " + active.get()); logger.info("send pair = " + pair); } GBTransportMess msg = null; if (pair != null) { msg = new GBTransportMessPairIndex(pair); } else { msg = new GBTransportMess(); //not End(); at this time // goon ?= false; } try { red++; pairChannel.send(pairTag, msg); int a = active.getAndIncrement(); } catch (IOException e) { e.printStackTrace(); goon = false; break; } //logger.debug("#distributed list = " + theList.size()); } logger.info("terminated, send " + red + " reduction pairs"); /* * send end mark to clients */ logger.debug("send end"); try { for (int i = 0; i < threadsPerNode; i++) { // -1 //do not wait: Object rq = pairChannel.receive(pairTag); pairChannel.send(pairTag, new GBTransportMessEnd()); } // send also end to receiver, no more, did not work //pairChannel.send(resultTag, new GBTransportMessEnd()); } catch (IOException e) { if (logger.isDebugEnabled()) { e.printStackTrace(); } } receiver.terminate(); int d = active.get(); logger.info("remaining active tasks = " + d); //logger.info("terminated, send " + red + " reduction pairs"); pairChannel.close(); logger.info("redServ pairChannel.close()"); finner.release(); channel.close(); logger.info("redServ channel.close()"); } } /** * Distributed server receiving worker thread. * @param coefficient type */ class HybridReducerReceiver> extends Thread { public static final Logger logger = Logger.getLogger(HybridReducerReceiver.class); public final boolean debug = logger.isDebugEnabled(); private final DistHashTable> theList; private final PairList pairlist; private final TaggedSocketChannel pairChannel; private final Terminator finner; private final int threadsPerNode; private final AtomicInteger active; private volatile boolean goon; /** * Message tag for pairs. */ public final Integer pairTag = GroebnerBaseDistributedHybrid.pairTag; /** * Message tag for results. */ public final Integer resultTag = GroebnerBaseDistributedHybrid.resultTag; /** * Message tag for acknowledgments. */ public final Integer ackTag = GroebnerBaseDistributedHybrid.ackTag; /** * Constructor. * @param tpn number of threads per node * @param fin terminator * @param a active remote tasks count * @param pc tagged socket channel * @param dl distributed hash table * @param L ordered pair list */ HybridReducerReceiver(int tpn, Terminator fin, AtomicInteger a, TaggedSocketChannel pc, DistHashTable> dl, PairList L) { active = a; threadsPerNode = tpn; finner = fin; pairChannel = pc; theList = dl; pairlist = L; goon = true; //logger.info("reducer server created " + this); } /** * Work loop. * @see java.lang.Thread#run() */ @Override public void run() { //Pair pair = null; GenPolynomial H = null; int red = 0; int polIndex = -1; //Integer senderId; // obsolete // while more requests while (goon) { // receive request logger.debug("receive result"); //senderId = null; Object rh = null; try { rh = pairChannel.receive(resultTag); int i = active.getAndDecrement(); } catch (InterruptedException e) { goon = false; //e.printStackTrace(); //?? finner.initIdle(1); break; } catch (IOException e) { e.printStackTrace(); goon = false; finner.initIdle(1); break; } catch (ClassNotFoundException e) { e.printStackTrace(); goon = false; finner.initIdle(1); break; } logger.info("received H polynomial"); if (rh == null) { if (this.isInterrupted()) { goon = false; finner.initIdle(1); break; } //finner.initIdle(1); } else if (rh instanceof GBTransportMessEnd) { // should only happen from server logger.info("received GBTransportMessEnd"); goon = false; //?? finner.initIdle(1); break; } else if (rh instanceof GBTransportMessPoly) { // update pair list red++; GBTransportMessPoly mpi = (GBTransportMessPoly) rh; H = mpi.pol; //senderId = mpi.threadId; if (H != null) { if (debug) { logger.info("H = " + H.leadingExpVector()); } if (!H.isZERO()) { if (H.isONE()) { // finner.allIdle(); polIndex = pairlist.putOne(); GenPolynomial nn = theList.put(Integer.valueOf(polIndex), H); if (nn != null) { logger.info("double polynomials nn = " + nn + ", H = " + H); } //goon = false; must wait for other clients //finner.initIdle(1); //break; } else { polIndex = pairlist.put(H); // use putWait ? but still not all distributed GenPolynomial nn = theList.put(Integer.valueOf(polIndex), H); if (nn != null) { logger.info("double polynomials nn = " + nn + ", H = " + H); } } } } } // only after recording in pairlist ! finner.initIdle(1); try { pairChannel.send(ackTag, new GBTransportMess()); logger.debug("send acknowledgement"); } catch (IOException e) { e.printStackTrace(); goon = false; break; } } // end while goon = false; logger.info("terminated, received " + red + " reductions"); } /** * Terminate. */ public void terminate() { goon = false; //this.interrupt(); try { this.join(); } catch (InterruptedException e) { // unfug Thread.currentThread().interrupt(); } logger.debug("HybridReducerReceiver terminated"); } } /** * Distributed clients reducing worker threads. */ class HybridReducerClient> implements Runnable { private static final Logger logger = Logger.getLogger(HybridReducerClient.class); public final boolean debug = logger.isDebugEnabled(); private final TaggedSocketChannel pairChannel; private final DistHashTable> theList; private final ReductionPar red; private final int threadsPerNode; /* * Identification number for this thread. */ //public final Integer threadId; // obsolete /** * Message tag for pairs. */ public final Integer pairTag = GroebnerBaseDistributedHybrid.pairTag; /** * Message tag for results. */ public final Integer resultTag = GroebnerBaseDistributedHybrid.resultTag; /** * Message tag for acknowledgments. */ public final Integer ackTag = GroebnerBaseDistributedHybrid.ackTag; /** * Constructor. * @param tpn number of threads per node * @param tc tagged socket channel * @param tid thread identification * @param dl distributed hash table */ HybridReducerClient(int tpn, TaggedSocketChannel tc, Integer tid, DistHashTable> dl) { this.threadsPerNode = tpn; pairChannel = tc; //threadId = 100 + tid; // keep distinct from other tags theList = dl; red = new ReductionPar(); } /** * Work loop. * @see java.lang.Runnable#run() */ //JAVA6only: @Override public void run() { if (debug) { logger.info("pairChannel = " + pairChannel + " reducer client running"); } Pair pair = null; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial H = null; //boolean set = false; boolean goon = true; boolean doEnd = true; int reduction = 0; //int sleeps = 0; Integer pix; Integer pjx; while (goon) { /* protocol: * request pair, process pair, send result, receive acknowledgment */ // pair = (Pair) pairlist.removeNext(); Object req = new GBTransportMessReq(); logger.info("send request = " + req); try { pairChannel.send(pairTag, req); } catch (IOException e) { goon = false; if (logger.isDebugEnabled()) { e.printStackTrace(); } logger.info("receive pair, exception "); break; } logger.debug("receive pair, goon = " + goon); doEnd = true; Object pp = null; try { pp = pairChannel.receive(pairTag); } catch (InterruptedException e) { goon = false; e.printStackTrace(); } catch (IOException e) { goon = false; if (logger.isDebugEnabled()) { e.printStackTrace(); } break; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } if (debug) { logger.info("received pair = " + pp); } H = null; if (pp == null) { // should not happen continue; } if (pp instanceof GBTransportMessEnd) { goon = false; //doEnd = false; // bug continue; } if (pp instanceof GBTransportMessPair || pp instanceof GBTransportMessPairIndex) { pi = pj = null; if (pp instanceof GBTransportMessPair) { pair = ((GBTransportMessPair) pp).pair; if (pair != null) { pi = pair.pi; pj = pair.pj; //logger.debug("pair: pix = " + pair.i // + ", pjx = " + pair.j); } } if (pp instanceof GBTransportMessPairIndex) { pix = ((GBTransportMessPairIndex) pp).i; pjx = ((GBTransportMessPairIndex) pp).j; pi = theList.getWait(pix); pj = theList.getWait(pjx); //logger.info("pix = " + pix + ", pjx = " +pjx); } if (pi != null && pj != null) { S = red.SPolynomial(pi, pj); //System.out.println("S = " + S); if (S.isZERO()) { // pair.setZero(); does not work in dist } else { if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(theList, S); reduction++; if (H.isZERO()) { // pair.setZero(); does not work in dist } else { H = H.monic(); if (logger.isInfoEnabled()) { logger.info("ht(H) = " + H.leadingExpVector()); } } } } } if (pp instanceof GBTransportMess) { logger.debug("null pair results in null H poly"); } // send H or must send null, if not at end if (logger.isDebugEnabled()) { logger.debug("#distributed list = " + theList.size()); logger.debug("send H polynomial = " + H); } try { pairChannel.send(resultTag, new GBTransportMessPoly(H)); //,threadId)); doEnd = false; } catch (IOException e) { goon = false; e.printStackTrace(); } logger.info("done send poly message of " + pp); try { //pp = pairChannel.receive(threadId); pp = pairChannel.receive(ackTag); } catch (InterruptedException e) { goon = false; e.printStackTrace(); } catch (IOException e) { goon = false; if (logger.isDebugEnabled()) { e.printStackTrace(); } break; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } if (!(pp instanceof GBTransportMess)) { logger.error("invalid acknowledgement " + pp); } logger.info("received acknowledgment " + pp); } logger.info("terminated, done " + reduction + " reductions"); if (doEnd) { try { pairChannel.send(resultTag, new GBTransportMessEnd()); } catch (IOException e) { //e.printStackTrace(); } logger.info("terminated, send done"); } } } jas-2.5/src/edu/jas/gb/WordReductionSeq.java0000644000175000017500000001536412020637744021176 0ustar giovannigiovanni/* * $Id: WordReductionSeq.java 4152 2012-09-02 11:15:48Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.poly.Word; import edu.jas.poly.GenWordPolynomial; import edu.jas.structure.RingElem; /** * Polynomial word reduction sequential use algorithm. * Implements normalform. * @param coefficient type * @author Heinz Kredel */ public class WordReductionSeq> // should be FieldElem> extends WordReductionAbstract { private static final Logger logger = Logger.getLogger(WordReductionSeq.class); private static boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public WordReductionSeq() { } /** * Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @return nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenWordPolynomial normalform(List> Pp, GenWordPolynomial Ap) { if ( Pp == null || Pp.isEmpty() ) { return Ap; } if ( Ap == null || Ap.isZERO() ) { return Ap; } if ( ! Ap.ring.coFac.isField() ) { throw new IllegalArgumentException("coefficients not from a field"); } Map.Entry m; int l; GenWordPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = new GenWordPolynomial[l]; //P = Pp.toArray(); for ( int i = 0; i < Pp.size(); i++ ) { P[i] = Pp.get(i); } } Word[] htl = new Word[ l ]; Object[] lbc = new Object[ l ]; // want C[] GenWordPolynomial[] p = new GenWordPolynomial[ l ]; int i; int j = 0; for ( i = 0; i < l; i++ ) { p[i] = P[i]; m = p[i].leadingMonomial(); if ( m != null ) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; Word e; C a; boolean mt = false; GenWordPolynomial R = Ap.ring.getZERO(); C cone = Ap.ring.coFac.getONE(); //GenWordPolynomial T = null; GenWordPolynomial Q = null; GenWordPolynomial S = Ap; while ( S.length() > 0 ) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for ( i = 0; i < l; i++ ) { mt = e.multipleOf( htl[i] ); if ( mt ) break; } if ( ! mt ) { //logger.debug("irred"); //T = new OrderedMapPolynomial( a, e ); R = R.sum( a, e ); S = S.subtract( a, e ); // System.out.println(" S = " + S); } else { Word[] elr = e.divideWord( htl[i] ); e = elr[0]; Word f = elr[1]; if ( debug ) { logger.info("red divideWord: e = " + e + ", f = " + f); } a = a.divide( (C)lbc[i] ); Q = p[i].multiply( a, e, cone, f ); S = S.subtract( Q ); } } return R; } /** * Normalform with left and right recording. * @param lrow left recording matrix, is modified. * @param rrow right recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. */ @SuppressWarnings("unchecked") public GenWordPolynomial normalform(List> lrow, List> rrow, List> Pp, GenWordPolynomial Ap) { if ( Pp == null || Pp.isEmpty() ) { return Ap; } if ( Ap == null || Ap.isZERO() ) { return Ap; } if ( ! Ap.ring.coFac.isField() ) { throw new IllegalArgumentException("coefficients not from a field"); } int l = Pp.size(); GenWordPolynomial[] P = new GenWordPolynomial[l]; synchronized (Pp) { //P = Pp.toArray(); for ( int i = 0; i < Pp.size(); i++ ) { P[i] = Pp.get(i); } } Word[] htl = new Word[ l ]; Object[] lbc = new Object[ l ]; // want C[] GenWordPolynomial[] p = new GenWordPolynomial[ l ]; Map.Entry m; int j = 0; int i; for ( i = 0; i < l; i++ ) { p[i] = P[i]; m = p[i].leadingMonomial(); if ( m != null ) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; Word e; C a; boolean mt = false; GenWordPolynomial zero = Ap.ring.getZERO(); GenWordPolynomial R = Ap.ring.getZERO(); C cone = Ap.ring.coFac.getONE(); GenWordPolynomial fac = null; // GenWordPolynomial T = null; GenWordPolynomial Q = null; GenWordPolynomial S = Ap; while ( S.length() > 0 ) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for ( i = 0; i < l; i++ ) { mt = e.multipleOf( htl[i] ); if ( mt ) break; } if ( ! mt ) { //logger.debug("irred"); R = R.sum( a, e ); S = S.subtract( a, e ); // System.out.println(" S = " + S); //throw new RuntimeException("Syzygy no GB"); } else { Word[] elr = e.divideWord( htl[i] ); e = elr[0]; Word f = elr[1]; if ( debug ) { logger.info("redRec divideWord: e = " + e + ", f = " + f); } C c = (C) lbc[i]; a = a.divide( c ); Q = p[i].multiply( a, e, cone, f ); S = S.subtract( Q ); // left row fac = lrow.get(i); if ( fac == null ) { fac = zero.sum( cone, e ); } else { fac = fac.sum( cone, e ); } lrow.set(i,fac); // right row fac = rrow.get(i); if ( fac == null ) { fac = zero.sum( a, f ); } else { fac = fac.sum( a, f ); } rrow.set(i,fac); } } return R; } } jas-2.5/src/edu/jas/gb/GroebnerBaseSeqPairDistributed.java0000644000175000017500000007173312014164600023752 0ustar giovannigiovanni/* * $Id: GroebnerBaseSeqPairDistributed.java 4116 2012-08-19 13:26:25Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import java.util.Collections; import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.ChannelFactory; import edu.jas.util.DistHashTable; import edu.jas.util.DistHashTableServer; import edu.jas.util.SocketChannel; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; /** * Groebner Base distributed algorithm. Implements a distributed memory parallel * version of Groebner bases. Using pairlist class, distributed tasks do * reduction. Makes some effort to produce the same sequence of critical pairs * as in the sequential version. However already reduced pairs are not rereduced * if new polynomials appear. * @param coefficient type * @author Heinz Kredel */ public class GroebnerBaseSeqPairDistributed> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBaseSeqPairDistributed.class); /** * Number of threads to use. */ protected final int threads; /** * Default number of threads. */ protected static final int DEFAULT_THREADS = 2; /** * Pool of threads to use. */ protected transient final ThreadPool pool; /** * Default server port. */ protected static final int DEFAULT_PORT = 4711; /** * Server port to use. */ protected final int port; /** * Constructor. */ public GroebnerBaseSeqPairDistributed() { this(DEFAULT_THREADS, DEFAULT_PORT); } /** * Constructor. * @param threads number of threads to use. */ public GroebnerBaseSeqPairDistributed(int threads) { this(threads, new ThreadPool(threads), DEFAULT_PORT); } /** * Constructor. * @param threads number of threads to use. * @param red parallelism aware reduction engine */ public GroebnerBaseSeqPairDistributed(int threads, Reduction red) { this(threads, new ThreadPool(threads), DEFAULT_PORT, red); } /** * Constructor. * @param threads number of threads to use. * @param port server port to use. * @param red parallelism aware reduction engine */ public GroebnerBaseSeqPairDistributed(int threads, int port, Reduction red) { this(threads, new ThreadPool(threads), port, red); } /** * Constructor. * @param threads number of threads to use. * @param port server port to use. */ public GroebnerBaseSeqPairDistributed(int threads, int port) { this(threads, new ThreadPool(threads), port); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param port server port to use. */ public GroebnerBaseSeqPairDistributed(int threads, ThreadPool pool, int port) { this(threads, pool, port, new ReductionPar()); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param port server port to use. * @param red parallelism aware reduction engine */ public GroebnerBaseSeqPairDistributed(int threads, ThreadPool pool, int port, Reduction red) { super(red); if (!(red instanceof ReductionPar)) { logger.warn("parallel GB should use parallel aware reduction"); } if (threads < 1) { threads = 1; } this.threads = threads; this.pool = pool; this.port = port; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { if (pool == null) { return; } pool.terminate(); } /** * Distributed Groebner base. Slaves maintain pairlist. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs. */ public List> GB(int modv, List> F) { final int DL_PORT = port + 100; ChannelFactory cf = new ChannelFactory(port); cf.init(); DistHashTableServer dls = new DistHashTableServer(DL_PORT); dls.init(); logger.debug("dist-list server running"); GenPolynomial p; List> G = new ArrayList>(); CriticalPairList pairlist = null; boolean oneInGB = false; int l = F.size(); int unused; ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { oneInGB = true; G.clear(); G.add(p); //return G; must signal termination to others } if (!oneInGB) { G.add(p); } if (pairlist == null) { pairlist = new CriticalPairList(modv, p.ring); } // theList not updated here if (p.isONE()) { unused = pairlist.putOne(); } else { unused = pairlist.put(p); } } else { l--; } } //if (l <= 1) { //return G; must signal termination to others //} logger.debug("looking for clients"); //long t = System.currentTimeMillis(); // now in DL, uses resend for late clients //while ( dls.size() < threads ) { sleep(); } DistHashTable> theList = new DistHashTable>( "localhost", DL_PORT); theList.init(); List> al = pairlist.getList(); for (int i = 0; i < al.size(); i++) { // no wait required GenPolynomial nn = theList.put(Integer.valueOf(i), al.get(i)); if (nn != null) { logger.info("double polynomials " + i + ", nn = " + nn + ", al(i) = " + al.get(i)); } } Terminator fin = new Terminator(threads); ReducerServerSeqPair R; for (int i = 0; i < threads; i++) { R = new ReducerServerSeqPair(fin, cf, theList, G, pairlist); pool.addJob(R); } logger.debug("main loop waiting"); fin.waitDone(); int ps = theList.size(); //logger.debug("#distributed list = "+ps); // make sure all polynomials arrived: not needed in master // G = (ArrayList)theList.values(); G = pairlist.getList(); //logger.debug("#pairlist list = "+G.size()); if (ps != G.size()) { logger.info("#distributed list = " + theList.size() + " #pairlist list = " + G.size()); } long time = System.currentTimeMillis(); List> Gp; Gp = minimalGB(G); // not jet distributed but threaded time = System.currentTimeMillis() - time; logger.info("parallel gbmi = " + time); /* time = System.currentTimeMillis(); G = GroebnerBase.GBmi(G); // sequential time = System.currentTimeMillis() - time; logger.info("sequential gbmi = " + time); */ G = Gp; //logger.info("cf.terminate()"); cf.terminate(); // no more required // pool.terminate(); logger.info("theList.terminate()"); theList.terminate(); logger.info("dls.terminate()"); dls.terminate(); logger.info("" + pairlist); return G; } /** * GB distributed client. * @param host the server runns on. * @throws IOException */ public void clientPart(String host) throws IOException { ChannelFactory cf = new ChannelFactory(port + 10); // != port for localhost cf.init(); SocketChannel pairChannel = cf.getChannel(host, port); final int DL_PORT = port + 100; DistHashTable> theList = new DistHashTable>(host, DL_PORT); theList.init(); ReducerClientSeqPair R = new ReducerClientSeqPair(pairChannel, theList); R.run(); pairChannel.close(); theList.terminate(); cf.terminate(); return; } /** * Minimal ordered groebner basis. * @param Fp a Groebner base. * @return a reduced Groebner base of Fp. */ @Override public List> minimalGB(List> Fp) { GenPolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiReducerServerSeqPair[] mirs = (MiReducerServerSeqPair[]) new MiReducerServerSeqPair[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List> R = new ArrayList>(G.size()+F.size()); R.addAll(G); R.addAll(F); mirs[i] = new MiReducerServerSeqPair(R,a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } } /** * Distributed server reducing worker threads. * @param coefficient type */ class ReducerServerSeqPair> implements Runnable { private final Terminator pool; private final ChannelFactory cf; private SocketChannel pairChannel; private final DistHashTable> theList; //private List> G; private final CriticalPairList pairlist; private static final Logger logger = Logger.getLogger(ReducerServerSeqPair.class); ReducerServerSeqPair(Terminator fin, ChannelFactory cf, DistHashTable> dl, List> G, CriticalPairList L) { pool = fin; this.cf = cf; theList = dl; //this.G = G; pairlist = L; } public void run() { logger.debug("reducer server running"); try { pairChannel = cf.getChannel(); } catch (InterruptedException e) { logger.debug("get pair channel interrupted"); e.printStackTrace(); return; } if (logger.isDebugEnabled()) { logger.debug("pairChannel = " + pairChannel); } CriticalPair pair; //GenPolynomial pi; //GenPolynomial pj; //GenPolynomial S; GenPolynomial H = null; boolean set = false; boolean goon = true; int polIndex = -1; int red = 0; int sleeps = 0; // while more requests while (goon) { // receive request logger.debug("receive request"); Object req = null; try { req = pairChannel.receive(); } catch (IOException e) { goon = false; e.printStackTrace(); } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } //logger.debug("received request, req = " + req); if (req == null) { goon = false; break; } if (!(req instanceof GBSPTransportMessReq)) { goon = false; break; } // find pair if (logger.isDebugEnabled()) { logger.debug("find pair"); logger .debug("pool.hasJobs() " + pool.hasJobs() + " pairlist.hasNext() " + pairlist.hasNext()); } while (!pairlist.hasNext()) { // wait pairlist.update(); if (!set) { pool.beIdle(); set = true; } if (!pool.hasJobs() && !pairlist.hasNext()) { goon = false; break; } try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } Thread.sleep(100); } catch (InterruptedException e) { goon = false; break; } } if (!pairlist.hasNext() && !pool.hasJobs()) { goon = false; break; //continue; //break? } if (set) { set = false; pool.notIdle(); } pair = pairlist.getNext(); /* * send pair to client, receive H */ if (logger.isDebugEnabled()) { logger.debug("send pair = " + pair); logger.info("theList keys " + theList.keySet()); } if (logger.isDebugEnabled()) { logger.info("inWork " + pairlist.inWork()); } GBSPTransportMess msg = null; if (pair != null) { msg = new GBSPTransportMessPairIndex(pair); } else { msg = new GBSPTransportMess(); //End(); // goon ?= false; } try { pairChannel.send(msg); } catch (IOException e) { e.printStackTrace(); goon = false; break; } // use idle time to update pairlist pairlist.update(); //logger.debug("#distributed list = "+theList.size()); //logger.debug("receive H polynomial"); Object rh = null; try { rh = pairChannel.receive(); } catch (IOException e) { e.printStackTrace(); goon = false; break; } catch (ClassNotFoundException e) { e.printStackTrace(); goon = false; break; } if (logger.isDebugEnabled()) { logger.info("received H polynomial rh = " + rh); } if (rh == null) { if (pair != null) { polIndex = pairlist.record(pair, null); //pair.setZero(); } pairlist.update(); } else if (rh instanceof GBSPTransportMessPoly) { // update pair list red++; H = ((GBSPTransportMessPoly) rh).pol; //logger.info("H = " + H); if (H == null) { if (pair != null) { polIndex = pairlist.record(pair, null); //pair.setZero(); } pairlist.update(); } else { if (H.isZERO()) { polIndex = pairlist.record(pair, H); //pair.setZero(); } else { if (H.isONE()) { // pool.allIdle(); pairlist.putOne(); theList.put(Integer.valueOf(0), H); goon = false; //break; } else { polIndex = pairlist.record(pair, H); // not correct: // polIndex = pairlist.getList().size(); // pairlist.update(); // polIndex = pairlist.put( H ); // use putWait ? but still not all distributed theList.put(Integer.valueOf(polIndex), H); } } } } else { if (pair != null) { polIndex = pairlist.record(pair, null); //pair.setZero(); } if (logger.isDebugEnabled()) { logger.debug("invalid message " + rh); } } } logger.info("terminated, done " + red + " reductions"); /* * send end mark to client */ logger.debug("send end"); try { pairChannel.send(new GBSPTransportMessEnd()); } catch (IOException e) { if (logger.isDebugEnabled()) { e.printStackTrace(); } } pool.beIdle(); pairChannel.close(); } } /** * Distributed GB transport message. */ class GBSPTransportMess implements Serializable { /** * toString. */ @Override public String toString() { return "" + this.getClass().getName(); } } /** * Distributed GB transport message for requests. */ class GBSPTransportMessReq extends GBSPTransportMess { public GBSPTransportMessReq() { } } /** * Distributed GB transport message for termination. */ class GBSPTransportMessEnd extends GBSPTransportMess { public GBSPTransportMessEnd() { } } /** * Distributed GB transport message for polynomial. */ class GBSPTransportMessPoly> extends GBSPTransportMess { /** * The polynomial for transport. */ public final GenPolynomial pol; /** * GBSPTransportMessPoly. * @param p polynomial to transfered. */ public GBSPTransportMessPoly(GenPolynomial p) { this.pol = p; } /** * toString. */ @Override public String toString() { return super.toString() + "( " + pol + " )"; } } /** * Distributed GB transport message for pairs. */ class GBSPTransportMessPair> extends GBSPTransportMess { public final CriticalPair pair; /** * GBSPTransportMessPair. * @param p pair for transfer. */ public GBSPTransportMessPair(CriticalPair p) { this.pair = p; } /** * toString. */ @Override public String toString() { return super.toString() + "( " + pair + " )"; } } /** * Distributed GB transport message for index pairs. */ class GBSPTransportMessPairIndex extends GBSPTransportMess { public final Integer i; public final Integer j; /** * GBSPTransportMessPairIndex. * @param p pair for transport. */ public GBSPTransportMessPairIndex(CriticalPair p) { if (p == null) { throw new NullPointerException("pair may not be null"); } this.i = Integer.valueOf(p.i); this.j = Integer.valueOf(p.j); } /** * GBSPTransportMessPairIndex. * @param i first index. * @param j second index. */ public GBSPTransportMessPairIndex(int i, int j) { this.i = Integer.valueOf(i); this.j = Integer.valueOf(j); } /** * GBSPTransportMessPairIndex. * @param i first index. * @param j second index. */ public GBSPTransportMessPairIndex(Integer i, Integer j) { this.i = i; this.j = j; } /** * toString. */ @Override public String toString() { return super.toString() + "( " + i + "," + j + " )"; } } /** * Distributed clients reducing worker threads. */ class ReducerClientSeqPair> implements Runnable { private final SocketChannel pairChannel; private final DistHashTable> theList; private final ReductionPar red; private static final Logger logger = Logger.getLogger(ReducerClientSeqPair.class); ReducerClientSeqPair(SocketChannel pc, DistHashTable> dl) { pairChannel = pc; theList = dl; red = new ReductionPar(); } public void run() { if (logger.isDebugEnabled()) { logger.debug("pairChannel = " + pairChannel + "reducer client running"); } CriticalPair pair = null; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial H = null; //boolean set = false; boolean goon = true; int reduction = 0; //int sleeps = 0; Integer pix; Integer pjx; while (goon) { /* protocol: * request pair, process pair, send result */ // pair = (Pair) pairlist.removeNext(); Object req = new GBSPTransportMessReq(); if (logger.isDebugEnabled()) { logger.debug("send request = " + req); } try { pairChannel.send(req); } catch (IOException e) { goon = false; e.printStackTrace(); break; } if (logger.isDebugEnabled()) { logger.debug("receive pair, goon = " + goon); } Object pp = null; try { pp = pairChannel.receive(); } catch (IOException e) { goon = false; if (logger.isDebugEnabled()) { e.printStackTrace(); } break; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } if (logger.isDebugEnabled()) { logger.info("received pair = " + pp); } H = null; if (pp == null) { // should not happen //logger.debug("received pair = " + pp); continue; } if (pp instanceof GBSPTransportMessEnd) { goon = false; continue; } if (pp instanceof GBSPTransportMessPair || pp instanceof GBSPTransportMessPairIndex) { pi = pj = null; if (pp instanceof GBSPTransportMessPair) { pair = ((GBSPTransportMessPair) pp).pair; if (pair != null) { pi = pair.pi; pj = pair.pj; //logger.debug("pair: pix = " + pair.i // + ", pjx = " + pair.j); } } if (pp instanceof GBSPTransportMessPairIndex) { pix = ((GBSPTransportMessPairIndex) pp).i; pjx = ((GBSPTransportMessPairIndex) pp).j; //logger.info("waiting for pix = " + pix); pi = theList.getWait(pix); //logger.info("waiting for pjx = " + pjx); pj = theList.getWait(pjx); //logger.info("pix = " + pix + ", pjx = " +pjx); } if (logger.isDebugEnabled()) { logger.info("pi = " + pi.leadingExpVector() + ", pj = " + pj.leadingExpVector()); } if (pi != null && pj != null) { S = red.SPolynomial(pi, pj); //System.out.println("S = " + S); if (S.isZERO()) { // pair.setZero(); does not work in dist H = S; } else { if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(theList, S); reduction++; if (H.isZERO()) { // pair.setZero(); does not work in dist } else { H = H.monic(); if (logger.isDebugEnabled()) { logger.info("ht(H) = " + H.leadingExpVector()); } } } } } else { if (logger.isDebugEnabled()) { logger.debug("invalid message = " + pp); } try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } // send H or must send null //logger.debug("#distributed list = "+theList.size()); if (logger.isDebugEnabled()) { logger.info("send H polynomial = " + H); } try { pairChannel.send(new GBSPTransportMessPoly(H)); } catch (IOException e) { goon = false; e.printStackTrace(); break; } } logger.info("terminated, done " + reduction + " reductions"); pairChannel.close(); } } /** * Distributed server reducing worker threads for minimal GB Not jet distributed * but threaded. */ class MiReducerServerSeqPair> implements Runnable { private final List> G; private GenPolynomial H; private final Semaphore done = new Semaphore(0); private final Reduction red; private static final Logger logger = Logger.getLogger(MiReducerServerSeqPair.class); MiReducerServerSeqPair(List> G, GenPolynomial p) { this.G = G; H = p; red = new ReductionPar(); } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenPolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException e) { } return H; } public void run() { if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = red.normalform(G, H); //mod done.release(); //done.V(); if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } /** * Distributed clients reducing worker threads for minimal GB. Not jet used. */ class MiReducerClientSeqPair> implements Runnable { private final List> G; private GenPolynomial H; private final Reduction red; private final Semaphore done = new Semaphore(0); private static final Logger logger = Logger.getLogger(MiReducerClientSeqPair.class); MiReducerClientSeqPair(List> G, GenPolynomial p) { this.G = G; H = p; red = new ReductionPar(); } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenPolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException u) { Thread.currentThread().interrupt(); } return H; } public void run() { if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = red.normalform(G, H); // mod done.release(); //done.V(); if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } jas-2.5/src/edu/jas/gb/GroebnerBase.java0000644000175000017500000000603212023071546020256 0ustar giovannigiovanni/* * $Id: GroebnerBase.java 4179 2012-09-09 10:45:58Z kredel $ */ package edu.jas.gb; import java.util.List; import java.io.Serializable; import edu.jas.structure.RingElem; import edu.jas.poly.GenPolynomial; /** * Groebner Bases interface. * Defines methods for Groebner bases and GB test. * @param coefficient type * @author Heinz Kredel * * @see edu.jas.application.GBAlgorithmBuilder * @see edu.jas.gbufd.GBFactory */ public interface GroebnerBase> extends Serializable { /** * Groebner base test. * @param F polynomial list. * @return true, if F is a Groebner base, else false. */ public boolean isGB(List> F); /** * Groebner base test. * @param modv module variable number. * @param F polynomial list. * @return true, if F is a Groebner base, else false. */ public boolean isGB(int modv, List> F); /** * Groebner base using pairlist class. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> GB( List> F ); /** * Groebner base using pairlist class. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> GB( int modv, List> F ); /** * Extended Groebner base using critical pair class. * @param F polynomial list. * @return a container for a Groebner base G of F together with back-and-forth transformations. */ public ExtendedGB extGB( List> F ); /** * Extended Groebner base using critical pair class. * @param modv module variable number. * @param F polynomial list. * @return a container for a Groebner base G of F together with back-and-forth transformations. */ public ExtendedGB extGB( int modv, List> F ); /** * Minimal ordered groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. */ public List> minimalGB(List> Gp); /** * Test if reduction matrix. * @param exgb an ExtendedGB container. * @return true, if exgb contains a reduction matrix, else false. */ public boolean isReductionMatrix(ExtendedGB exgb); /** * Test if reduction matrix. * @param F a polynomial list. * @param G a Groebner base. * @param Mf a possible reduction matrix. * @param Mg a possible reduction matrix. * @return true, if Mg and Mf are reduction matrices, else false. */ public boolean isReductionMatrix(List> F, List> G, List>> Mf, List>> Mg); } jas-2.5/src/edu/jas/gb/SolvableReductionPar.java0000644000175000017500000001577712013663732022032 0ustar giovannigiovanni/* * $Id: SolvableReductionPar.java 4104 2012-08-18 10:00:59Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.Map; //import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.structure.RingElem; /** * Solvable polynomial Reduction parallel usable algorithm. * Implements left normalform. * @param coefficient type * @author Heinz Kredel */ public class SolvableReductionPar> extends SolvableReductionAbstract { //private static final Logger logger = Logger.getLogger(SolvableReductionPar.class); /** * Constructor. */ public SolvableReductionPar() { } /** * Left Normalform. * @param Ap solvable polynomial. * @param Pp solvable polynomial list. * @return left-nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenSolvablePolynomial leftNormalform(List> Pp, GenSolvablePolynomial Ap) { if ( Pp == null || Pp.isEmpty() ) { return Ap; } if ( Ap == null || Ap.isZERO() ) { return Ap; } int l; Map.Entry m; GenSolvablePolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenSolvablePolynomial[]) new GenSolvablePolynomial[l]; //P = Pp.toArray(); for ( int j = 0; j < Pp.size(); j++ ) { P[j] = Pp.get(j); } } ExpVector e; ExpVector f = null; C a; boolean mt = false; GenSolvablePolynomial Rz = Ap.ring.getZERO(); GenSolvablePolynomial R = Ap.ring.getZERO(); GenSolvablePolynomial p = null; GenSolvablePolynomial Q = null; GenSolvablePolynomial S = Ap; while ( S.length() > 0 ) { if ( Pp.size() != l ) { //long t = System.currentTimeMillis(); synchronized (Pp) { // required, bad in parallel l = Pp.size(); P = (GenSolvablePolynomial[]) new GenSolvablePolynomial[ l ]; //P = Pp.toArray(); for ( int i = 0; i < Pp.size(); i++ ) { P[i] = Pp.get(i); } } //t = System.currentTimeMillis()-t; //logger.info("Pp.toArray() = " + t + " ms, size() = " + l); S = Ap; // S.add(R)? // restart reduction ? R = Rz; } m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for ( int i = 0; i < P.length ; i++ ) { p = P[i]; f = p.leadingExpVector(); if ( f != null ) { mt = e.multipleOf( f ); if ( mt ) break; } } if ( ! mt ) { //logger.debug("irred"); R = (GenSolvablePolynomial)R.sum( a, e ); S = (GenSolvablePolynomial)S.subtract( a, e ); // System.out.println(" S = " + S); } else { //logger.debug("red"); e = e.subtract( f ); Q = p.multiplyLeft( e ); a = a.divide( Q.leadingBaseCoefficient() ); Q = Q.multiplyLeft( a ); S = (GenSolvablePolynomial)S.subtract( Q ); } } return R; } /** * LeftNormalform with recording. * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the left normal form of Ap wrt. Pp. */ public GenSolvablePolynomial leftNormalform(List> row, List> Pp, GenSolvablePolynomial Ap) { throw new UnsupportedOperationException("normalform with recording not implemented"); } /** * Right Normalform. * @param Ap solvable polynomial. * @param Pp solvable polynomial list. * @return right-nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenSolvablePolynomial rightNormalform(List> Pp, GenSolvablePolynomial Ap) { if ( Pp == null || Pp.isEmpty() ) { return Ap; } if ( Ap == null || Ap.isZERO() ) { return Ap; } int l; Map.Entry m; GenSolvablePolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenSolvablePolynomial[]) new GenSolvablePolynomial[l]; //P = Pp.toArray(); for ( int j = 0; j < Pp.size(); j++ ) { P[j] = Pp.get(j); } } ExpVector e; ExpVector f = null; C a; boolean mt = false; GenSolvablePolynomial Rz = Ap.ring.getZERO(); GenSolvablePolynomial R = Ap.ring.getZERO(); GenSolvablePolynomial p = null; GenSolvablePolynomial Q = null; GenSolvablePolynomial S = Ap; while ( S.length() > 0 ) { if ( Pp.size() != l ) { //long t = System.currentTimeMillis(); synchronized (Pp) { // required, bad in parallel l = Pp.size(); P = (GenSolvablePolynomial[]) new GenSolvablePolynomial[ l ]; //P = Pp.toArray(); for ( int i = 0; i < Pp.size(); i++ ) { P[i] = Pp.get(i); } } //t = System.currentTimeMillis()-t; //logger.info("Pp.toArray() = " + t + " ms, size() = " + l); S = Ap; // S.add(R)? // restart reduction ? R = Rz; } m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for ( int i = 0; i < P.length ; i++ ) { p = P[i]; f = p.leadingExpVector(); if ( f != null ) { mt = e.multipleOf( f ); if ( mt ) break; } } if ( ! mt ) { //logger.debug("irred"); R = (GenSolvablePolynomial)R.sum( a, e ); S = (GenSolvablePolynomial)S.subtract( a, e ); // System.out.println(" S = " + S); } else { //logger.debug("red"); e = e.subtract( f ); Q = p.multiply( e ); a = a.divide( Q.leadingBaseCoefficient() ); Q = Q.multiply( a ); S = (GenSolvablePolynomial)S.subtract( Q ); } } return R; } } jas-2.5/src/edu/jas/gb/WordPair.java0000644000175000017500000000465512020351336017453 0ustar giovannigiovanni/* * $Id: WordPair.java 4150 2012-09-01 09:18:23Z kredel $ */ package edu.jas.gb; import java.io.Serializable; import edu.jas.structure.RingElem; import edu.jas.poly.Word; import edu.jas.poly.GenWordPolynomial; /** * Serializable subclass to hold pairs of word polynomials. * @param coefficient type * @author Heinz Kredel. */ public class WordPair > implements Comparable { public final GenWordPolynomial pi; public final GenWordPolynomial pj; public final int i; public final int j; protected int n; /** * WordPair constructor. * @param a word polynomial i. * @param b word polynomial j. * @param i first index. * @param j second index. */ public WordPair(GenWordPolynomial a, GenWordPolynomial b, int i, int j) { pi = a; pj = b; this.i = i; this.j = j; this.n = 0; } /** * toString. */ @Override public String toString() { return "wordPair(" + i + "," + j + ",{" + pi.length() + "," + pj.length() + "}," + n + ")"; } /** * Set removed pair number. * @param n number of this pair generated in OrderedPairlist. */ public void pairNumber(int n) { this.n = n; } /** * Get removed pair number. * @return n number of this pair generated in OrderedPairlist. */ public int getPairNumber() { return n; } /** * equals. * @param ob an Object. * @return true if this is equal to o, else false. */ @Override public boolean equals(Object ob) { if ( ! (ob instanceof WordPair) ) { return false; // throw new ClassCastException("Pair "+n+" o "+o); } return 0 == compareTo( (WordPair)ob ); } /** * compareTo used in TreeMap // not used at moment. * Comparison is based on the number of the pairs. * @param p a WordPair. * @return 1 if (this < o), 0 if (this == o), -1 if (this > o). */ public int compareTo(WordPair p) { int x = p.getPairNumber(); if ( n > x ) { return 1; } if ( n < x ) { return -1; } return 0; } /** * Hash code for this WordPair. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return (i << 16) + j; } } jas-2.5/src/edu/jas/gb/OrderedSyzPairlist.java0000644000175000017500000002316312067303544021532 0ustar giovannigiovanni/* * $Id: OrderedSyzPairlist.java 4334 2012-12-28 11:49:57Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.BitSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.RingElem; /** * Pair list management. For the Buchberger algorithm following the syzygy * criterions by Gebauer & Möller. Implemented using GenPolynomial, * TreeMap and BitSet. * @author Heinz Kredel */ public class OrderedSyzPairlist> extends OrderedPairlist { private static final Logger logger = Logger.getLogger(OrderedSyzPairlist.class); /** * Constructor. */ public OrderedSyzPairlist() { super(); } /** * Constructor. * @param r polynomial factory. */ public OrderedSyzPairlist(GenPolynomialRing r) { this(0, r); } /** * Constructor. * @param m number of module variables. * @param r polynomial factory. */ public OrderedSyzPairlist(int m, GenPolynomialRing r) { super(m, r); } /** * Create a new PairList. * @param r polynomial ring. */ @Override public PairList create(GenPolynomialRing r) { return new OrderedSyzPairlist(r); } /** * Create a new PairList. * @param m number of module variables. * @param r polynomial ring. */ @Override public PairList create(int m, GenPolynomialRing r) { return new OrderedSyzPairlist(m, r); } /** * Put one Polynomial to the pairlist and reduction matrix. Removes all * unnecessary pairs identified by the syzygy criterion and criterion 4. * @param p polynomial. * @return the index of the added polynomial. */ @Override public synchronized int put(GenPolynomial p) { putCount++; if (oneInGB) { return P.size() - 1; } ExpVector e = p.leadingExpVector(); int ps = P.size(); BitSet redi = new BitSet(); // all zeros //redi.set( 0, ps ); // [0..ps-1] = true, i.e. all ones red.add(redi); P.add(p); // remove from existing pairs: List es = new ArrayList(); for (Map.Entry>> me : pairlist.entrySet()) { ExpVector g = me.getKey(); if (moduleVars > 0) { if (!reduction.moduleCriterion(moduleVars, e, g)) { continue; // skip pair } } ExpVector ge = g.lcm(e); LinkedList> ll = me.getValue(); if (g.compareTo(ge) == 0) { LinkedList> lle = new LinkedList>(); for (Pair pair : ll) { ExpVector eil = pair.pi.leadingExpVector().lcm(e); if (g.compareTo(eil) == 0) { continue; } ExpVector ejl = pair.pj.leadingExpVector().lcm(e); if (g.compareTo(ejl) == 0) { continue; } // g == ge && g != eil && g != ejl red.get(pair.j).clear(pair.i); lle.add(pair); } if (lle.size() > 0) { for (Pair pair : lle) { ll.remove(pair); } if (!es.contains(g)) { es.add(g); } } } } for (ExpVector ei : es) { LinkedList> ll = pairlist.get(ei); if (ll != null && ll.size() == 0) { ll = pairlist.remove(ei); } } // generate new pairs: SortedMap>> npl = new TreeMap>>( ring.tord.getAscendComparator()); for (int j = 0; j < ps; j++) { GenPolynomial pj = P.get(j); ExpVector f = pj.leadingExpVector(); if (moduleVars > 0) { if (!reduction.moduleCriterion(moduleVars, e, f)) { //red.get(j).clear(l); continue; // skip pair } } ExpVector g = e.lcm(f); Pair pair = new Pair(pj, p, j, ps); //System.out.println("pair.new = " + pair); //multiple pairs under same keys -> list of pairs LinkedList> xl = npl.get(g); if (xl == null) { xl = new LinkedList>(); } //xl.addLast( pair ); // first or last ? xl.addFirst(pair); // first or last ? better for d- e-GBs npl.put(g, xl); } //System.out.println("npl.new = " + npl.keySet()); // skip by divisibility: es = new ArrayList(npl.size()); for (ExpVector eil : npl.keySet()) { for (ExpVector ejl : npl.keySet()) { if (eil.compareTo(ejl) == 0) { continue; } if (eil.multipleOf(ejl)) { if (!es.contains(eil)) { es.add(eil); } } } } //System.out.println("npl.skip div = " + es); for (ExpVector ei : es) { LinkedList> ignored = npl.remove(ei); } // skip by criterion 4: if (useCriterion4) { es = new ArrayList(npl.size()); for (Map.Entry>> me : npl.entrySet()) { ExpVector ei = me.getKey(); LinkedList> exl = me.getValue(); //npl.get( ei ); //System.out.println("exl = " + exl ); boolean c = true; for (Pair pair : exl) { c = c && reduction.criterion4(pair.pi, pair.pj, pair.e); } if (c) { if (exl.size() > 1) { Pair pair = exl.getFirst(); // or exl.getLast(); exl.clear(); exl.add(pair); //npl.put(ei,exl); } } else { if (!es.contains(ei)) { es.add(ei); } } } //System.out.println("npl.skip c4 = " + es); for (ExpVector ei : es) { LinkedList> ignored = npl.remove(ei); } } // add to existing pairlist: //System.out.println("npl.put new = " + npl.keySet() ); for (Map.Entry>> me : npl.entrySet()) { ExpVector ei = me.getKey(); LinkedList> exl = me.getValue(); //npl.get( ei ); for (Pair pair : exl) { red.get(pair.j).set(pair.i); } LinkedList> ex = pairlist.get(ei); // wrong in findbugs if (ex != null) { exl.addAll(ex); // add new pairs first ex = exl; //ex.addAll(exl); // add old pairs first } else { ex = exl; } pairlist.put(ei, ex); // replace ex } return P.size() - 1; } /** * Remove the next required pair from the pairlist and reduction matrix. * Appy the criterions 3 and 4 to see if the S-polynomial is required. * @return the next pair if one exists, otherwise null. */ @Override public synchronized Pair removeNext() { if (oneInGB) { return null; } Iterator>>> ip = pairlist.entrySet().iterator(); Pair pair = null; //boolean c = false; int i, j; while (ip.hasNext()) { Map.Entry>> me = ip.next(); ExpVector g = me.getKey(); LinkedList> xl = me.getValue(); if (logger.isInfoEnabled()) logger.info("g = " + g); pair = null; while (xl.size() > 0) { pair = xl.removeFirst(); // xl is also modified in pairlist i = pair.i; j = pair.j; //System.out.println("pair.remove = " + pair ); if (!red.get(j).get(i)) { // should not happen System.out.println("c_red.get(" + j + ").get(" + i + ") = " + g); pair = null; continue; } red.get(j).clear(i); break; } if (xl.size() == 0) { ip.remove(); // = pairlist.remove( g ); } if (pair != null) { break; } } if ( pair != null ) { pair.maxIndex(P.size()-1); remCount++; // count only real pairs if ( logger.isDebugEnabled() ) { logger.info("pair(" + pair.j + "," + pair.i + ")"); } } return pair; } /** * GB criterium 3. * @return true if the S-polynomial(i,j) is required. */ @Override public boolean criterion3(int i, int j, ExpVector eij) { throw new UnsupportedOperationException("not used in " + this.getClass().getName()); } } jas-2.5/src/edu/jas/gb/OrderedPairlist.java0000644000175000017500000002401312067555012021016 0ustar giovannigiovanni/* * $Id: OrderedPairlist.java 4336 2012-12-29 11:54:51Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.BitSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.SortedMap; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.structure.RingElem; /** * Pair list management. * The original Buchberger algorithm with criterions following * Winkler in SAC-1, Kredel in ALDES/SAC-2, Kredel in MAS. * Implemented using GenPolynomial, TreeMap and BitSet. * @author Heinz Kredel */ public class OrderedPairlist > implements PairList { protected final List> P; protected final SortedMap>> pairlist; protected final List red; protected final GenPolynomialRing ring; protected final Reduction reduction; protected boolean oneInGB = false; protected boolean useCriterion4 = true; protected int putCount; protected int remCount; protected final int moduleVars; private static final Logger logger = Logger.getLogger(OrderedPairlist.class); /** * Constructor. */ public OrderedPairlist() { moduleVars = 0; ring = null; P = null; pairlist = null; red = null; reduction = null; putCount = 0; remCount = 0; } /** * Constructor. * @param r polynomial factory. */ public OrderedPairlist(GenPolynomialRing r) { this(0,r); } /** * Constructor. * @param m number of module variables. * @param r polynomial factory. */ public OrderedPairlist(int m, GenPolynomialRing r) { moduleVars = m; ring = r; P = new ArrayList>(); pairlist = new TreeMap>>( ring.tord.getAscendComparator() ); //pairlist = new TreeMap( to.getSugarComparator() ); red = new ArrayList(); putCount = 0; remCount = 0; if ( !ring.isCommutative() ) {//ring instanceof GenSolvablePolynomialRing ) { useCriterion4 = false; } reduction = new ReductionSeq(); } /** * Create a new PairList. * @param r polynomial ring. */ public PairList create(GenPolynomialRing r) { return new OrderedPairlist(r); } /** * Create a new PairList. * @param m number of module variables. * @param r polynomial ring. */ public PairList create(int m, GenPolynomialRing r) { return new OrderedPairlist(m,r); } /** * toString. */ @Override public String toString() { StringBuffer s = new StringBuffer(this.getClass().getSimpleName() + "("); //s.append("polys="+P.size()); s.append("#put="+putCount); s.append(", #rem="+remCount); if ( pairlist != null && pairlist.size() != 0 ) { s.append(", size="+pairlist.size()); } s.append(")"); return s.toString(); } /** * Put one Polynomial to the pairlist and reduction matrix. * @param p polynomial. * @return the index of the added polynomial. */ public synchronized int put(GenPolynomial p) { putCount++; if ( oneInGB ) { return P.size()-1; } ExpVector e = p.leadingExpVector(); int l = P.size(); for ( int j = 0; j < l; j++ ) { GenPolynomial pj = P.get(j); ExpVector f = pj.leadingExpVector(); if ( moduleVars > 0 ) { if ( !reduction.moduleCriterion( moduleVars, e, f) ) { continue; // skip pair } } ExpVector g = e.lcm( f ); Pair pair = new Pair( pj, p, j, l); //System.out.println("pair.new = " + pair); //multiple pairs under same keys -> list of pairs LinkedList> xl = pairlist.get( g ); if ( xl == null ) { xl = new LinkedList>(); } //xl.addLast( pair ); // first or last ? xl.addFirst( pair ); // first or last ? better for d- e-GBs pairlist.put( g, xl ); } // System.out.println("pairlist.keys@put = " + pairlist.keySet() ); P.add( p ); BitSet redi = new BitSet(); redi.set( 0, l ); red.add( redi ); //System.out.println("pairlist.set = " + red); //.get( pair.j )); //pair); //System.out.println("pairlist.key = " + pairlist.keySet() ); return P.size()-1; } /** * Remove the next required pair from the pairlist and reduction matrix. * Appy the criterions 3 and 4 to see if the S-polynomial is required. * @return the next pair if one exists, otherwise null. */ public synchronized Pair removeNext() { if ( oneInGB ) { return null; } Iterator< Map.Entry>> > ip = pairlist.entrySet().iterator(); Pair pair = null; boolean c = false; int i, j; while ( !c && ip.hasNext() ) { Map.Entry>> me = ip.next(); ExpVector g = me.getKey(); LinkedList> xl = me.getValue(); if ( logger.isInfoEnabled() ) { logger.info("g = " + g); } pair = null; while ( !c && xl.size() > 0 ) { pair = xl.removeFirst(); // xl is also modified in pairlist i = pair.i; j = pair.j; // System.out.println("pair(" + j + "," +i+") "); if ( useCriterion4 ) { c = reduction.criterion4( pair.pi, pair.pj, g ); } else { c = true; } //System.out.println("c4_o = " + c); if ( c ) { c = criterion3( i, j, g ); //System.out.println("c3_o = " + c); } red.get( j ).clear(i); // set(i,false) jdk1.4 } if ( xl.size() == 0 ) { ip.remove(); // = pairlist.remove( g ); } } if ( ! c ) { pair = null; } else { pair.maxIndex(P.size()-1); remCount++; // count only real pairs if ( logger.isDebugEnabled() ) { logger.info("pair(" + pair.j + "," + pair.i + ")"); } } return pair; } /** * Test if there is possibly a pair in the list. * @return true if a next pair could exist, otherwise false. */ public synchronized boolean hasNext() { return pairlist.size() > 0; } /** * Get the list of polynomials. * @return the polynomial list. */ public List> getList() { return P; } /** * Get the size of the list of polynomials. * @return size of the polynomial list. */ public int size() { return P.size(); } /** * Get the number of polynomials put to the pairlist. * @return the number of calls to put. */ public synchronized int putCount() { return putCount; } /** * Get the number of required pairs removed from the pairlist. * @return the number of non null pairs delivered. */ public synchronized int remCount() { return remCount; } /** * Put the ONE-Polynomial to the pairlist. * @param one polynomial. (no more required) * @return the index of the last polynomial. */ public synchronized int putOne(GenPolynomial one) { if ( one == null ) { return P.size()-1; } if ( ! one.isONE() ) { return P.size()-1; } return putOne(); } /** * Put the ONE-Polynomial to the pairlist. * @return the index of the last polynomial. */ public synchronized int putOne() { putCount++; oneInGB = true; pairlist.clear(); P.clear(); P.add(ring.getONE()); red.clear(); logger.info("outOne " + this.toString()); return P.size()-1; } /** * GB criterium 3. * @return true if the S-polynomial(i,j) is required. */ public boolean criterion3(int i, int j, ExpVector eij) { // assert i < j; boolean s = red.get( j ).get(i); if ( ! s ) { logger.warn("c3.s false for " + j + " " + i); return s; } // now s = true; for ( int k = 0; k < P.size(); k++ ) { // System.out.println("i , k , j "+i+" "+k+" "+j); if ( i != k && j != k ) { GenPolynomial A = P.get( k ); ExpVector ek = A.leadingExpVector(); boolean m = eij.multipleOf(ek); if ( m ) { if ( k < i ) { // System.out.println("k < i "+k+" "+i); s = red.get( i ).get(k) || red.get( j ).get(k); } else if ( i < k && k < j ) { // System.out.println("i < k < j "+i+" "+k+" "+j); s = red.get( k ).get(i) || red.get( j ).get(k); } else if ( j < k ) { //System.out.println("j < k "+j+" "+k); s = red.get( k ).get(i) || red.get( k ).get(j); } //System.out.println("s."+k+" = " + s); if ( ! s ) { return s; } } } } return true; } } jas-2.5/src/edu/jas/gb/WordReductionAbstract.java0000644000175000017500000002513312020637744022204 0ustar giovannigiovanni/* * $Id: WordReductionAbstract.java 4152 2012-09-02 11:15:48Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.poly.Word; import edu.jas.poly.GenWordPolynomial; import edu.jas.poly.OverlapList; import edu.jas.poly.Overlap; import edu.jas.structure.RingElem; /** * Polynomial word reduction abstract class. Implements common S-Polynomial, * normalform, module criterion and irreducible set. * @param coefficient type * @author Heinz Kredel */ public abstract class WordReductionAbstract> implements WordReduction { private static final Logger logger = Logger.getLogger(WordReductionAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public WordReductionAbstract() { } /** * S-Polynomials of non-commutative polynomials. * @param Ap word polynomial. * @param Bp word polynomial. * @return list of all spol(Ap,Bp) the S-polynomials of Ap and Bp. */ public List> SPolynomials(GenWordPolynomial Ap, GenWordPolynomial Bp) { List> sp = new ArrayList>(); Map.Entry ma = Ap.leadingMonomial(); Map.Entry mb = Bp.leadingMonomial(); Word e = ma.getKey(); Word f = mb.getKey(); C a = ma.getValue(); C b = mb.getValue(); OverlapList oll = e.overlap(f); if ( oll.ols.isEmpty() ) { return sp; } for ( Overlap ol : oll.ols ) { GenWordPolynomial s = SPolynomial(ol, b, Ap, a, Bp); sp.add(s); } return sp; } /** * S-Polynomials of non-commutative polynomials. * @param a leading base coefficient of B. * @param l1 word. * @param A word polynomial. * @param r1 word. * @param b leading base coefficient of A. * @param l2 word. * @param B word polynomial. * @param r2 word. * @return list of all spol(Ap,Bp) the S-polynomials of Ap and Bp. */ public GenWordPolynomial SPolynomial(C a, Word l1, GenWordPolynomial A, Word r1, C b, Word l2, GenWordPolynomial B, Word r2) { C one = A.ring.coFac.getONE(); GenWordPolynomial s1 = A.multiply(a,l1,one,r1); GenWordPolynomial s2 = B.multiply(b,l2,one,r2); GenWordPolynomial s = s1.subtract(s2); return s; } /** * S-Polynomials of non-commutative polynomials. * @param ol Overlap tuple. * @param a leading base coefficient of B. * @param A word polynomial. * @param b leading base coefficient of A. * @param B word polynomial. * @return list of all spol(Ap,Bp) the S-polynomials of Ap and Bp. */ public GenWordPolynomial SPolynomial(Overlap ol, C a, GenWordPolynomial A, C b, GenWordPolynomial B) { C one = A.ring.coFac.getONE(); GenWordPolynomial s1 = A.multiply(a,ol.l1,one,ol.r1); GenWordPolynomial s2 = B.multiply(b,ol.l2,one,ol.r2); GenWordPolynomial s = s1.subtract(s2); return s; } /** * Normalform Set. * @param Ap polynomial list. * @param Pp polynomial list. * @return list of nf(a) with respect to Pp for all a in Ap. */ public List> normalform(List> Pp, List> Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isEmpty()) { return Ap; } ArrayList> red = new ArrayList>(); for (GenWordPolynomial A : Ap) { A = normalform(Pp, A); red.add(A); } return red; } /** * Is top reducible. * @param A polynomial. * @param P polynomial list. * @return true if A is top reducible with respect to P. */ public boolean isTopReducible(List> P, GenWordPolynomial A) { if (P == null || P.isEmpty()) { return false; } if (A == null || A.isZERO()) { return false; } boolean mt = false; Word e = A.leadingWord(); for (GenWordPolynomial p : P) { mt = e.multipleOf(p.leadingWord()); if (mt) { return true; } } return false; } /** * Is reducible. * @param Ap polynomial. * @param Pp polynomial list. * @return true if Ap is reducible with respect to Pp. */ public boolean isReducible(List> Pp, GenWordPolynomial Ap) { return !isNormalform(Pp, Ap); } /** * Is in Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @return true if Ap is in normalform with respect to Pp. */ @SuppressWarnings("unchecked") public boolean isNormalform(List> Pp, GenWordPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return true; } if (Ap == null || Ap.isZERO()) { return true; } int l; GenWordPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = new GenWordPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } Word[] htl = new Word[l]; GenWordPolynomial[] p = new GenWordPolynomial[l]; Map.Entry m; int i; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); j++; } } l = j; boolean mt = false; for (Word e : Ap.getMap().keySet()) { for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { return false; } } } return true; } /** * Is in Normalform. * @param Pp polynomial list. * @return true if each Ap in Pp is in normalform with respect to Pp\{Ap}. */ public boolean isNormalform(List> Pp) { if (Pp == null || Pp.isEmpty()) { return true; } GenWordPolynomial Ap; List> P = new LinkedList>(Pp); int s = P.size(); for (int i = 0; i < s; i++) { Ap = P.remove(i); if (!isNormalform(P, Ap)) { return false; } P.add(Ap); } return true; } /** * Irreducible set. * @param Pp polynomial list. * @return a list P of monic polynomials which are in normalform wrt. P and * with ideal(Pp) = ideal(P). */ public List> irreducibleSet(List> Pp) { ArrayList> P = new ArrayList>(); for (GenWordPolynomial a : Pp) { if (a.length() != 0) { a = a.monic(); if (a.isONE()) { P.clear(); P.add(a); return P; } P.add(a); } } int l = P.size(); if (l <= 1) return P; int irr = 0; Word e; Word f; GenWordPolynomial a; logger.debug("irr = "); while (irr != l) { //it = P.listIterator(); //a = P.get(0); //it.next(); a = P.remove(0); e = a.leadingWord(); a = normalform(P, a); logger.debug(String.valueOf(irr)); if (a.length() == 0) { l--; if (l <= 1) { return P; } } else { f = a.leadingWord(); if (f.signum() == 0) { P = new ArrayList>(); P.add(a.monic()); return P; } if (e.equals(f)) { irr++; } else { irr = 0; a = a.monic(); } P.add(a); } } //System.out.println(); return P; } /** * Is reduction of normal form. * @param lrow left recording matrix. * @param rrow right recording matrix. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @param Np nf(Pp,Ap), a normal form of Ap wrt. Pp. * @return true, if Np + sum( row[i]*Pp[i] ) == Ap, else false. */ public boolean isReductionNF(List> lrow, List> rrow, List> Pp, GenWordPolynomial Ap, GenWordPolynomial Np) { if (lrow == null && rrow == null && Pp == null) { if (Ap == null) { return (Np == null); } return Ap.equals(Np); } if (lrow == null || rrow == null || Pp == null) { return false; } if (lrow.size() != Pp.size() || rrow.size() != Pp.size()) { return false; } GenWordPolynomial t = Np; //System.out.println("t0 = " + t ); GenWordPolynomial r, rl, rr; GenWordPolynomial p; for (int m = 0; m < Pp.size(); m++) { rl = lrow.get(m); rr = rrow.get(m); p = Pp.get(m); if (rl != null && rr != null && p != null) { if (t == null) { t = p.multiply(rl,rr); } else { t = t.sum(p.multiply(rl,rr)); } } //System.out.println("r = " + r ); //System.out.println("p = " + p ); } //System.out.println("t+ = " + t ); if (t == null) { if (Ap == null) { return true; } return Ap.isZERO(); } r = t.subtract(Ap); boolean z = r.isZERO(); if (!z) { logger.info("t = " + t); logger.info("a = " + Ap); logger.info("t-a = " + r); } return z; } } jas-2.5/src/edu/jas/gb/EGroebnerBaseSeq.java0000644000175000017500000000204412011775300021027 0ustar giovannigiovanni/* * $Id: EGroebnerBaseSeq.java 4099 2012-08-12 18:49:36Z kredel $ */ package edu.jas.gb; import edu.jas.structure.RingElem; /** * E-Groebner Base sequential algorithm. Nearly empty class, only the * e-reduction is used instead of d-reduction. Note: Minimal reduced GBs * are again unique. see BWK, section 10.1. * @param coefficient type * @author Heinz Kredel */ public class EGroebnerBaseSeq> extends DGroebnerBaseSeq { //private static final Logger logger = Logger.getLogger(EGroebnerBaseSeq.class); //private final boolean debug = logger.isDebugEnabled(); /** * Reduction engine. */ protected EReduction ered; // shadow super.red ?? /** * Constructor. */ public EGroebnerBaseSeq() { this(new EReductionSeq()); } /** * Constructor. * @param ered E-Reduction engine */ public EGroebnerBaseSeq(EReductionSeq ered) { super(ered); this.ered = ered; assert this.ered == super.red; } } jas-2.5/src/edu/jas/gb/EReductionSeq.java0000644000175000017500000002610712014163702020433 0ustar giovannigiovanni/* * $Id: EReductionSeq.java 4115 2012-08-19 13:18:59Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Polynomial E-Reduction sequential use algorithm. Implements normalform. * @param coefficient type * @author Heinz Kredel */ public class EReductionSeq> extends DReductionSeq implements EReduction { private static final Logger logger = Logger.getLogger(DReductionSeq.class); /** * Constructor. */ public EReductionSeq() { } /** * Is top reducible. * @param A polynomial. * @param P polynomial list. * @return true if A is top reducible with respect to P. */ //SuppressWarnings("unchecked") // not jet working @Override public boolean isTopReducible(List> P, GenPolynomial A) { if (P == null || P.isEmpty()) { return false; } if (A == null || A.isZERO()) { return false; } boolean mt = false; ExpVector e = A.leadingExpVector(); C a = A.leadingBaseCoefficient(); for (GenPolynomial p : P) { mt = e.multipleOf(p.leadingExpVector()); if (mt) { C b = p.leadingBaseCoefficient(); C r = a.remainder(b); mt = !r.equals(a); if (mt) { return true; } } } return false; } /** * Is in Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @return true if Ap is in normalform with respect to Pp. */ @SuppressWarnings("unchecked") @Override public boolean isNormalform(List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return true; } if (Ap == null || Ap.isZERO()) { return true; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RingElem[l]; // want GenPolynomial[] p = new GenPolynomial[l]; Map.Entry m; int i; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; boolean mt = false; Map Am = Ap.getMap(); for (Map.Entry me : Am.entrySet()) { ExpVector e = me.getKey(); C a = me.getValue(); //Am.get(e); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { C r = a.remainder(lbc[i]); mt = !r.equals(a); if (mt) { return false; } } } } return true; } /** * Normalform using e-reduction. * @param Ap polynomial. * @param Pp polynomial list. * @return e-nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") @Override public GenPolynomial normalform(List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = (GenPolynomial[]) new GenPolynomial[l]; //P = Pp.toArray(); for (int i = 0; i < Pp.size(); i++) { P[i] = Pp.get(i).abs(); } } Map.Entry m; ExpVector[] htl = new ExpVector[l]; C[] lbc = (C[]) new RingElem[l]; // want GenPolynomial[] p = (GenPolynomial[]) new GenPolynomial[l]; int i; int j = 0; for (i = 0; i < l; i++) { p[i] = P[i]; m = p[i].leadingMonomial(); if (m != null) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e = null; ExpVector f = null; C a = null; C b = null; C r = null; GenPolynomial R = Ap.ring.getZERO(); GenPolynomial T = Ap.ring.getZERO(); GenPolynomial Q = null; GenPolynomial S = Ap; //try { // required to avoid a compiler error in the while loop while (S.length() > 0) { boolean mt = false; m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for (i = 0; i < l; i++) { mt = e.multipleOf(htl[i]); if (mt) { f = e.subtract(htl[i]); //logger.info("red div = " + f); r = a.remainder(lbc[i]); b = a.divide(lbc[i]); if (f == null) { // compiler produced this case System.out.println("f = null: " + e + ", " + htl[i]); Q = p[i].multiply(b); } else { Q = p[i].multiply(b, f); } S = S.subtract(Q); // ok also with reductum //System.out.println(" r = " + r); a = r; if (r.isZERO()) { break; } } } if (!a.isZERO()) { //! mt ) { //logger.debug("irred"); R = R.sum(a, e); //S = S.subtract( a, e ); S = S.reductum(); } //System.out.println(" R = " + R); //System.out.println(" S = " + S); } //} catch (Exception ex) { // System.out.println("R = " + R); // System.out.println("S = " + S); // System.out.println("f = " + f + ", " + e + ", " + htl[i]); // System.out.println("a = " + a + ", " + b + ", " + r + ", " + lbc[i]); // //throw ex; // return T; //} return R.abs(); } /** * Normalform with recording. * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. */ @Override @SuppressWarnings("unchecked") // not jet working public GenPolynomial normalform(List> row, List> Pp, GenPolynomial Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isZERO()) { return Ap; } throw new UnsupportedOperationException("not jet implemented"); /* int l = Pp.size(); GenPolynomial[] P = new GenPolynomial[l]; synchronized (Pp) { //P = Pp.toArray(); for ( int i = 0; i < Pp.size(); i++ ) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[ l ]; Object[] lbc = new Object[ l ]; // want GenPolynomial[] p = new GenPolynomial[ l ]; Map.Entry m; int j = 0; int i; for ( i = 0; i < l; i++ ) { p[i] = P[i]; m = p[i].leadingMonomial(); if ( m != null ) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; boolean mt = false; GenPolynomial zero = Ap.ring.getZERO(); GenPolynomial R = Ap.ring.getZERO(); GenPolynomial fac = null; // GenPolynomial T = null; GenPolynomial Q = null; GenPolynomial S = Ap; while ( S.length() > 0 ) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for ( i = 0; i < l; i++ ) { mt = e.multipleOf( htl[i] ); if ( mt ) break; } if ( ! mt ) { //logger.debug("irred"); R = R.sum( a, e ); S = S.subtract( a, e ); // System.out.println(" S = " + S); //throw new RuntimeException("Syzygy no GB"); } else { e = e.subtract( htl[i] ); //logger.info("red div = " + e); C c = (C)lbc[i]; a = a.divide( c ); Q = p[i].multiply( a, e ); S = S.subtract( Q ); fac = row.get(i); if ( fac == null ) { fac = zero.sum( a, e ); } else { fac = fac.sum( a, e ); } row.set(i,fac); } } return R; */ } /** * Irreducible set. * @param Pp polynomial list. * @return a list P of polynomials which are in normalform wrt. P. */ @Override public List> irreducibleSet(List> Pp) { ArrayList> P = new ArrayList>(); if (Pp == null) { return null; } for (GenPolynomial a : Pp) { if (!a.isZERO()) { P.add(a); } } int l = P.size(); if (l <= 1) return P; int irr = 0; ExpVector e; ExpVector f; C c; C d; GenPolynomial a; Iterator> it; logger.debug("irr = "); while (irr != l) { //it = P.listIterator(); //a = P.get(0); //it.next(); a = P.remove(0); e = a.leadingExpVector(); c = a.leadingBaseCoefficient(); a = normalform(P, a); logger.debug(String.valueOf(irr)); if (a.isZERO()) { l--; if (l <= 1) { return P; } } else { f = a.leadingExpVector(); d = a.leadingBaseCoefficient(); if (e.equals(f) && c.equals(d)) { irr++; } else { irr = 0; } P.add(a); } } //System.out.println(); return P; } } jas-2.5/src/edu/jas/gb/OrderedMinPairlist.java0000644000175000017500000001640512067303544021471 0ustar giovannigiovanni/* * $Id: OrderedMinPairlist.java 4334 2012-12-28 11:49:57Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.BitSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.structure.RingElem; /** * Pair list management. * The original Buchberger algorithm with criterions * using early pair exclusion. * Implemented using GenPolynomial, TreeMap and BitSet. * @author Heinz Kredel */ public class OrderedMinPairlist > extends OrderedPairlist { private static final Logger logger = Logger.getLogger(OrderedMinPairlist.class); /** * Constructor. */ public OrderedMinPairlist() { super(); } /** * Constructor. * @param r polynomial factory. */ public OrderedMinPairlist(GenPolynomialRing r) { this(0,r); } /** * Constructor. * @param m number of module variables. * @param r polynomial factory. */ public OrderedMinPairlist(int m, GenPolynomialRing r) { super(m,r); } /** * Create a new PairList. * @param r polynomial ring. */ public PairList create(GenPolynomialRing r) { return new OrderedMinPairlist(r); } /** * Create a new PairList. * @param m number of module variables. * @param r polynomial ring. */ public PairList create(int m, GenPolynomialRing r) { return new OrderedMinPairlist(m,r); } /** * Put one Polynomial to the pairlist and reduction matrix. * @param p polynomial. * @return the index of the added polynomial. */ public synchronized int put(GenPolynomial p) { putCount++; if ( oneInGB ) { return P.size()-1; } ExpVector e = p.leadingExpVector(); int l = P.size(); BitSet redi = new BitSet(); redi.set( 0, l ); // [0..l-1] = true red.add( redi ); P.add( p ); for ( int j = 0; j < l; j++ ) { GenPolynomial pj = P.get(j); ExpVector f = pj.leadingExpVector(); if ( moduleVars > 0 ) { if ( !reduction.moduleCriterion( moduleVars, e, f) ) { red.get(j).clear(l); continue; // skip pair } } ExpVector g = e.lcm( f ); //System.out.println("g = " + g); Pair pair = new Pair( pj, p, j, l); boolean c = true; if ( useCriterion4 ) { c = reduction.criterion4( pair.pi, pair.pj, g ); } //System.out.println("c4 = " + c); if ( c ) { c = criterion3( j, l, g ); //System.out.println("c3 = " + c); } if ( !c ) { // skip pair red.get(j).clear(l); //System.out.println("c_skip = " + g); continue; } //multiple pairs under same keys -> list of pairs LinkedList> xl = pairlist.get( g ); if ( xl == null ) { xl = new LinkedList>(); } //xl.addLast( pair ); // first or last ? xl.addFirst( pair ); // first or last ? better for d- e-GBs pairlist.put( g, xl ); } // System.out.println("pairlist.keys@put = " + pairlist.keySet() ); return P.size()-1; } /** * Remove the next required pair from the pairlist and reduction matrix. * Appy the criterions 3 and 4 to see if the S-polynomial is required. * @return the next pair if one exists, otherwise null. */ public synchronized Pair removeNext() { if ( oneInGB ) { return null; } Iterator< Map.Entry>> > ip = pairlist.entrySet().iterator(); Pair pair = null; boolean c = false; int i, j; while ( !c && ip.hasNext() ) { Map.Entry>> me = ip.next(); ExpVector g = me.getKey(); LinkedList> xl = me.getValue(); if ( logger.isInfoEnabled() ) { logger.info("g = " + g); } pair = null; while ( !c && xl.size() > 0 ) { pair = xl.removeFirst(); // xl is also modified in pairlist i = pair.i; j = pair.j; // System.out.println("pair(" + j + "," +i+") "); if ( !red.get(j).get(i) ) { System.out.println("c_y = " + g); // + ", " + red.get(j).get(i)); continue; } c = true; if ( useCriterion4 ) { c = reduction.criterion4( pair.pi, pair.pj, g ); } //System.out.println("c4_x = " + c); if ( c ) { c = criterion3( i, j, g ); //System.out.println("c3_x = " + c); } if ( !c ) { //System.out.println("c_x = " + g); } red.get( j ).clear(i); // set(i,false) jdk1.4 } if ( xl.size() == 0 ) { ip.remove(); // = pairlist.remove( g ); } } if ( ! c ) { pair = null; } else { pair.maxIndex(P.size()-1); remCount++; // count only real pairs if ( logger.isDebugEnabled() ) { logger.info("pair(" + pair.j + "," + pair.i + ")"); } } return pair; } /** * GB criterium 3. * @return true if the S-polynomial(i,j) is required. */ public boolean criterion3(int i, int j, ExpVector eij) { // assert i < j; boolean s; s = red.get( j ).get(i); if ( ! s ) { logger.warn("c3.s false for " + j + " " + i); return s; } s = true; boolean m; GenPolynomial A; ExpVector ek; for ( int k = 0; k < P.size(); k++ ) { A = P.get( k ); ek = A.leadingExpVector(); m = eij.multipleOf(ek) && eij.compareTo(ek) != 0; if ( m ) { if ( k < i ) { // System.out.println("k < i "+k+" "+i); s = red.get( i ).get(k) || red.get( j ).get(k); } if ( i < k && k < j ) { // System.out.println("i < k < j "+i+" "+k+" "+j); s = red.get( k ).get(i) || red.get( j ).get(k); } if ( j < k ) { //System.out.println("j < k "+j+" "+k); s = red.get( k ).get(i) || red.get( k ).get(j); } //System.out.println("s."+k+" = " + s); if ( ! s ) return s; } } return true; } } jas-2.5/src/edu/jas/gb/CriticalPairList.java0000644000175000017500000002267712004024230021122 0ustar giovannigiovanni/* * $Id: CriticalPairList.java 4049 2012-07-25 17:10:49Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.BitSet; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.structure.RingElem; /** * Critical pair list management. * Makes some effort to produce the same sequence of critical pairs * as in the sequential case, when used in parallel. * However already reduced pairs are not re-reduced if new * polynomials appear. * Implemented using GenPolynomial, SortedSet / TreeSet and BitSet. * @author Heinz Kredel */ public class CriticalPairList> extends OrderedPairlist { protected final SortedSet< CriticalPair > pairlist; // hide super protected int recordCount; private static final Logger logger = Logger.getLogger(CriticalPairList.class); /** * Constructor for CriticalPairList. */ public CriticalPairList() { super(); pairlist = null; } /** * Constructor for CriticalPairList. * @param r polynomial factory. */ public CriticalPairList(GenPolynomialRing r) { this(0,r); } /** * Constructor for CriticalPairList. * @param m number of module variables. * @param r polynomial factory. */ public CriticalPairList(int m, GenPolynomialRing r) { super(m,r); Comparator< AbstractPair > cpc; cpc = new CriticalPairComparator( ring.tord ); pairlist = new TreeSet< CriticalPair >( cpc ); recordCount = 0; } /** * Create a new PairList. * @param r polynomial ring. */ public PairList create(GenPolynomialRing r) { return new CriticalPairList(r); } /** * Create a new PairList. * @param m number of module variables. * @param r polynomial ring. */ public PairList create(int m, GenPolynomialRing r) { return new CriticalPairList(m,r); } /** * Put a polynomial to the pairlist and reduction matrix. * @param p polynomial. * @return the index of the added polynomial. */ public synchronized int put(GenPolynomial p) { putCount++; if ( oneInGB ) { return P.size()-1; } ExpVector e = p.leadingExpVector(); int len = P.size(); for ( int j = 0; j < len; j++ ) { GenPolynomial pj = P.get(j); ExpVector f = pj.leadingExpVector(); if ( moduleVars > 0 ) { // test moduleCriterion if ( !reduction.moduleCriterion( moduleVars, e, f) ) { continue; // skip pair } } ExpVector g = e.lcm( f ); CriticalPair pair = new CriticalPair( g, pj, p, j, len ); //System.out.println("put pair = " + pair ); pairlist.add( pair ); } P.add( p ); BitSet redi = new BitSet(); redi.set( 0, len ); // >= jdk 1.4 red.add( redi ); if ( recordCount < len ) { recordCount = len; } return len; } /** * Test if there is possibly a pair in the list. * @return true if a next pair could exist, otherwise false. */ public synchronized boolean hasNext() { return pairlist.size() > 0; } /** * Get and remove the next required pair from the pairlist. * Appy the criterions 3 and 4 to see if the S-polynomial is required. * The pair is not removed from the pair list. * @return the next pair if one exists, otherwise null. */ public Pair removeNext() { CriticalPair cp = getNext(); if ( cp == null ) { return null; } return new Pair(cp.pi,cp.pj,cp.i,cp.j); } /** * Get the next required pair from the pairlist. * Appy the criterions 3 and 4 to see if the S-polynomial is required. * The pair is not removed from the pair list. * @return the next pair if one exists, otherwise null. */ public synchronized CriticalPair getNext() { if ( oneInGB ) { return null; } CriticalPair pair = null; Iterator< CriticalPair > ip = pairlist.iterator(); boolean c = false; while ( !c && ip.hasNext() ) { // findbugs pair = ip.next(); if ( pair.getInReduction() ) { continue; } if ( pair.getReductum() != null ) { continue; } if ( logger.isInfoEnabled() ) { logger.info("" + pair); } if ( useCriterion4 ) { c = reduction.criterion4( pair.pi, pair.pj, pair.e ); // System.out.println("c4 = " + c); } else { c = true; } if ( c ) { c = criterion3( pair.i, pair.j, pair.e ); // System.out.println("c3 = " + c); } red.get( pair.j ).clear( pair.i ); // set(i,false) jdk1.4 if ( ! c ) { // set done pair.setReductum( ring.getZERO() ); } } if ( ! c ) { pair = null; } else { remCount++; // count only real pairs pair.setInReduction(); // set to work } return pair; } /** * Record reduced polynomial. * @param pair the corresponding critical pair. * @param p polynomial. * @return index of recorded polynomial, or -1 if not added. */ public int record(CriticalPair pair, GenPolynomial p) { if ( p == null ) { p = ring.getZERO(); } pair.setReductum(p); // trigger thread if ( ! p.isZERO() && ! p.isONE() ) { recordCount++; return recordCount; } return -1; } /** * Record reduced polynomial and update critical pair list. * Note: it is better to use record and uptate separately. * @param pair the corresponding critical pair. * @param p polynomial. * @return index of recorded polynomial */ public int update(CriticalPair pair, GenPolynomial p) { if ( p == null ) { p = ring.getZERO(); } pair.setReductum(p); if ( ! p.isZERO() && ! p.isONE() ) { recordCount++; } int c = update(); if (c < 0) { // use for findbugs System.out.println("c < 0"); } if ( ! p.isZERO() && ! p.isONE() ) { return recordCount; } return -1; } /** * Update pairlist. * Preserve the sequential pair sequence. * Remove pairs with completed reductions. * @return the number of added polynomials. */ public synchronized int update() { int num = 0; if ( oneInGB ) { return num; } while ( pairlist.size() > 0 ) { CriticalPair pair = pairlist.first(); GenPolynomial p = pair.getReductum(); if ( p != null ) { pairlist.remove( pair ); num++; if ( ! p.isZERO() ) { if ( p.isONE() ) { putOne(); // sets size = 1 } else { put( p ); // changes pair list } } } else { break; } } return num; } /** * In work pairs. List pairs which are currently reduced. * @return list of critical pairs which are in reduction. */ public synchronized List> inWork() { List> iw; iw = new ArrayList>(); if ( oneInGB ) { return iw; } for ( CriticalPair pair : pairlist ) { if ( pair.getInReduction() ) { iw.add( pair ); } } return iw; } /** * Update pairlist, several pairs at once. * This version does not preserve the sequential pair sequence. * Remove pairs with completed reductions. * @return the number of added polynomials. */ public synchronized int updateMany() { int num = 0; if ( oneInGB ) { return num; } List> rem = new ArrayList>(); for ( CriticalPair pair : pairlist ) { if ( pair.getReductum() != null ) { rem.add( pair ); num++; } else { break; } } // must work on a copy to avoid concurrent modification for ( CriticalPair pair : rem ) { // System.out.println("update = " + pair); pairlist.remove( pair ); GenPolynomial p = pair.getReductum(); if ( ! p.isZERO() ) { if ( p.isONE() ) { putOne(); } else { put( p ); } } } return num; } /** * Put the ONE-Polynomial to the pairlist. * @return the index of the last polynomial. */ public synchronized int putOne() { super.putOne(); pairlist.clear(); return 0; } } jas-2.5/src/edu/jas/gb/SolvableGroebnerBaseParallel.java0000644000175000017500000004747712013663732023450 0ustar giovannigiovanni/* * $Id: SolvableGroebnerBaseParallel.java 4104 2012-08-18 10:00:59Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.poly.GenSolvablePolynomialRing; import edu.jas.structure.RingElem; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; /** * Solvable Groebner Base parallel algorithm. Implements a shared memory * parallel version of Groebner bases. Threads maintain pairlist. * @param coefficient type * @author Heinz Kredel */ public class SolvableGroebnerBaseParallel> extends SolvableGroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(SolvableGroebnerBaseParallel.class); //private static final boolean debug = logger.isDebugEnabled(); /** * Number of threads to use. */ protected final int threads; /** * Pool of threads to use. */ protected transient final ThreadPool pool; /** * Constructor. */ public SolvableGroebnerBaseParallel() { this(2); } /** * Constructor. * @param threads number of threads to use. */ public SolvableGroebnerBaseParallel(int threads) { this(threads, new ThreadPool(threads)); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. */ public SolvableGroebnerBaseParallel(int threads, ThreadPool pool) { this(threads, pool, new SolvableReductionPar()); } /** * Constructor. * @param threads number of threads to use. * @param sred parallelism aware reduction engine */ public SolvableGroebnerBaseParallel(int threads, SolvableReduction sred) { this(threads, new ThreadPool(threads), sred); } /** * Constructor. * @param threads number of threads to use. * @param pl pair selection strategy */ public SolvableGroebnerBaseParallel(int threads, PairList pl) { this(threads, new ThreadPool(threads), new SolvableReductionPar(), pl); } /** * Constructor. * @param threads number of threads to use. * @param sred parallelism aware reduction engine * @param pl pair selection strategy */ public SolvableGroebnerBaseParallel(int threads, SolvableReduction sred, PairList pl) { this(threads, new ThreadPool(threads), sred, pl); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param sred parallelism aware reduction engine */ public SolvableGroebnerBaseParallel(int threads, ThreadPool pool, SolvableReduction sred) { this(threads, pool, sred, new OrderedPairlist()); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param sred parallelism aware reduction engine * @param pl pair selection strategy */ public SolvableGroebnerBaseParallel(int threads, ThreadPool pool, SolvableReduction sred, PairList pl) { super(sred, pl); if (!(sred instanceof SolvableReductionPar)) { logger.warn("parallel GB should use parallel aware reduction"); } if (threads < 1) { threads = 1; } this.threads = threads; this.pool = pool; } /** * Cleanup and terminate ThreadPool. */ public void terminate() { if (pool == null) { return; } pool.terminate(); } /** * Parallel Groebner base using sequential pair order class. Threads * maintain pairlist. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> leftGB(int modv, List> F) { GenSolvablePolynomial p; List> G = new ArrayList>(); PairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = (GenSolvablePolynomial) p.monic(); if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads activated jet } G.add(p); if (pairlist == null) { //pairlist = new OrderedPairlist( modv, p.ring ); pairlist = strategy.create(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // putOne not required pairlist.put(p); } else { l--; } } if (l <= 1) { return G; // since no threads activated jet } Terminator fin = new Terminator(threads); LeftSolvableReducer R; for (int i = 0; i < threads; i++) { R = new LeftSolvableReducer(fin, G, pairlist); pool.addJob(R); } fin.waitDone(); logger.debug("#parallel list = " + G.size()); G = leftMinimalGB(G); // not in this context // pool.terminate(); logger.info("" + pairlist); return G; } /** * Minimal ordered groebner basis, parallel. * @param Fp a Groebner base. * @return minimalGB(F) a minimal Groebner base of Fp. */ @Override public List> leftMinimalGB(List> Fp) { GenSolvablePolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenSolvablePolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); // no thread at this point } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } SolvableMiReducer[] mirs = (SolvableMiReducer[]) new SolvableMiReducer[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new SolvableMiReducer(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } /** * Solvable Extended Groebner base using critical pair class. * @param modv module variable number. * @param F solvable polynomial list. * @return a container for an extended left Groebner base of F. */ public SolvableExtendedGB extLeftGB(int modv, List> F) { throw new UnsupportedOperationException("parallel extLeftGB not implemented"); } /** * Twosided Groebner base using pairlist class. * @param modv number of module variables. * @param Fp solvable polynomial list. * @return tsGB(Fp) a twosided Groebner base of F. */ @SuppressWarnings("unchecked") public List> twosidedGB(int modv, List> Fp) { if (Fp == null || Fp.size() == 0) { // 0 not 1 return new ArrayList>(); } GenSolvablePolynomialRing fac = Fp.get(0).ring; // assert != null //List> X = generateUnivar( modv, Fp ); List> X = fac.univariateList(modv); //System.out.println("X univ = " + X); List> F = new ArrayList>(Fp.size() * (1 + X.size())); F.addAll(Fp); GenSolvablePolynomial p, x, q; for (int i = 0; i < Fp.size(); i++) { p = Fp.get(i); for (int j = 0; j < X.size(); j++) { x = X.get(j); q = p.multiply(x); q = sred.leftNormalform(F, q); if (!q.isZERO()) { F.add(q); } } } //System.out.println("F generated = " + F); List> G = new ArrayList>(); PairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = (GenSolvablePolynomial) p.monic(); if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads are activated } G.add(p); if (pairlist == null) { //pairlist = new OrderedPairlist( modv, p.ring ); pairlist = strategy.create(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // putOne not required pairlist.put(p); } else { l--; } } //System.out.println("G to check = " + G); if (l <= 1) { // 1 ok return G; // since no threads are activated } Terminator fin = new Terminator(threads); TwosidedSolvableReducer R; for (int i = 0; i < threads; i++) { R = new TwosidedSolvableReducer(fin, X, G, pairlist); pool.addJob(R); } fin.waitDone(); logger.debug("#parallel list = " + G.size()); G = leftMinimalGB(G); // not in this context // pool.terminate(); logger.info("" + pairlist); return G; } } /** * Reducing left worker threads. * @param coefficient type */ class LeftSolvableReducer> implements Runnable { private final List> G; private final PairList pairlist; private final Terminator pool; private final SolvableReductionPar sred; private static final Logger logger = Logger.getLogger(LeftSolvableReducer.class); private static final boolean debug = logger.isDebugEnabled(); LeftSolvableReducer(Terminator fin, List> G, PairList L) { pool = fin; this.G = G; pairlist = L; sred = new SolvableReductionPar(); } @SuppressWarnings("unchecked") public void run() { Pair pair; GenSolvablePolynomial S; GenSolvablePolynomial H; boolean set = false; int reduction = 0; int sleeps = 0; while (pairlist.hasNext() || pool.hasJobs()) { while (!pairlist.hasNext()) { // wait pool.beIdle(); set = true; try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } else { logger.debug("r"); } Thread.sleep(100); } catch (InterruptedException e) { break; } if (!pool.hasJobs()) { break; } } if (!pairlist.hasNext() && !pool.hasJobs()) { break; } if (set) { pool.notIdle(); set = false; } pair = pairlist.removeNext(); if (pair == null) { continue; } if (debug) { logger.debug("pi = " + pair.pi); logger.debug("pj = " + pair.pj); } S = sred.leftSPolynomial((GenSolvablePolynomial) pair.pi, (GenSolvablePolynomial) pair.pj); if (S.isZERO()) { continue; } if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = sred.leftNormalform(G, S); //mod reduction++; if (H.isZERO()) { continue; } if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = (GenSolvablePolynomial) H.monic(); // System.out.println("H = " + H); if (H.isONE()) { pairlist.putOne(); // not really required synchronized (G) { G.clear(); G.add(H); } pool.allIdle(); return; } if (debug) { logger.debug("H = " + H); } synchronized (G) { G.add(H); } pairlist.put(H); } logger.info("terminated, done " + reduction + " reductions"); } } /** * Reducing twosided worker threads. * @param coefficient type */ class TwosidedSolvableReducer> implements Runnable { private final List> X; private final List> G; private final PairList pairlist; private final Terminator pool; private final SolvableReductionPar sred; private static final Logger logger = Logger.getLogger(TwosidedSolvableReducer.class); private static final boolean debug = logger.isDebugEnabled(); TwosidedSolvableReducer(Terminator fin, List> X, List> G, PairList L) { pool = fin; this.X = X; this.G = G; pairlist = L; sred = new SolvableReductionPar(); } public void run() { GenSolvablePolynomial p, x; Pair pair; GenSolvablePolynomial S; GenSolvablePolynomial H; boolean set = false; int reduction = 0; int sleeps = 0; while (pairlist.hasNext() || pool.hasJobs()) { while (!pairlist.hasNext()) { // wait pool.beIdle(); set = true; try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } else { logger.debug("r"); } Thread.sleep(50); } catch (InterruptedException e) { break; } if (!pool.hasJobs()) { break; } } if (!pairlist.hasNext() && !pool.hasJobs()) { break; } if (set) { pool.notIdle(); set = false; } pair = pairlist.removeNext(); if (pair == null) { continue; } if (debug) { logger.debug("pi = " + pair.pi); logger.debug("pj = " + pair.pj); } S = sred.leftSPolynomial((GenSolvablePolynomial) pair.pi, (GenSolvablePolynomial) pair.pj); if (S.isZERO()) { continue; } if (debug) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = sred.leftNormalform(G, S); //mod reduction++; if (H.isZERO()) { continue; } if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = (GenSolvablePolynomial) H.monic(); // System.out.println("H = " + H); if (H.isONE()) { pairlist.putOne(); // not really required synchronized (G) { G.clear(); G.add(H); } pool.allIdle(); return; } if (debug) { logger.debug("H = " + H); } synchronized (G) { G.add(H); } pairlist.put(H); for (int j = 0; j < X.size(); j++) { x = X.get(j); p = H.multiply(x); p = sred.leftNormalform(G, p); if (!p.isZERO()) { p = (GenSolvablePolynomial) p.monic(); if (p.isONE()) { synchronized (G) { G.clear(); G.add(p); } pool.allIdle(); return; } synchronized (G) { G.add(p); } pairlist.put(p); } } } logger.info("terminated, done " + reduction + " reductions"); } } /** * Reducing worker threads for minimal GB. * @param coefficient type */ class SolvableMiReducer> implements Runnable { private final List> G; private GenSolvablePolynomial H; private final SolvableReductionPar sred; private final Semaphore done = new Semaphore(0); private static final Logger logger = Logger.getLogger(SolvableMiReducer.class); private static final boolean debug = logger.isDebugEnabled(); SolvableMiReducer(List> G, GenSolvablePolynomial p) { this.G = G; H = p; sred = new SolvableReductionPar(); } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenSolvablePolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException e) { } return H; } public void run() { if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = sred.leftNormalform(G, H); //mod done.release(); //done.V(); if (debug) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } jas-2.5/src/edu/jas/gb/GroebnerBaseDistributed.java0000644000175000017500000005754512033125606022476 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistributed.java 4235 2012-10-03 21:17:59Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.ChannelFactory; import edu.jas.util.DistHashTable; import edu.jas.util.DistHashTableServer; import edu.jas.util.SocketChannel; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; /** * Groebner Base distributed algorithm. Implements a distributed memory parallel * version of Groebner bases. Using pairlist class, distributed tasks do * reduction, one communication channel per task. * @param coefficient type * @author Heinz Kredel * @deprecated use GroebnerBaseDistributedEC */ public class GroebnerBaseDistributed> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBaseDistributed.class); /** * Number of threads to use. */ protected final int threads; /** * Default number of threads. */ protected static final int DEFAULT_THREADS = 2; /** * Pool of threads to use. Note: No ComputerThreads for one node * tests */ protected transient final ThreadPool pool; /** * Default server port. */ protected static final int DEFAULT_PORT = 4711; /** * Server port to use. */ protected final int port; /** * Constructor. */ public GroebnerBaseDistributed() { this(DEFAULT_THREADS, DEFAULT_PORT); } /** * Constructor. * @param threads number of threads to use. */ public GroebnerBaseDistributed(int threads) { this(threads, new ThreadPool(threads), DEFAULT_PORT); } /** * Constructor. * @param threads number of threads to use. * @param port server port to use. */ public GroebnerBaseDistributed(int threads, int port) { this(threads, new ThreadPool(threads), port); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param port server port to use. */ public GroebnerBaseDistributed(int threads, ThreadPool pool, int port) { this(threads, pool, new OrderedPairlist(), port); } /** * Constructor. * @param threads number of threads to use. * @param pl pair selection strategy * @param port server port to use. */ public GroebnerBaseDistributed(int threads, PairList pl, int port) { this(threads, new ThreadPool(threads), pl, port); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param pl pair selection strategy * @param port server port to use. */ public GroebnerBaseDistributed(int threads, ThreadPool pool, PairList pl, int port) { super(new ReductionPar(), pl); if (threads < 1) { threads = 1; } this.threads = threads; this.pool = pool; this.port = port; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { if (pool == null) { return; } pool.terminate(); } /** * Distributed Groebner base. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs. */ public List> GB(int modv, List> F) { final int DL_PORT = port + 100; ChannelFactory cf = new ChannelFactory(port); cf.init(); DistHashTableServer dls = new DistHashTableServer(DL_PORT); dls.init(); logger.debug("dist-list server running"); GenPolynomial p; List> G = new ArrayList>(); PairList pairlist = null; boolean oneInGB = false; int l = F.size(); int unused; ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { oneInGB = true; G.clear(); G.add(p); //return G; must signal termination to others } if (!oneInGB) { G.add(p); } if (pairlist == null) { //pairlist = new OrderedPairlist(modv, p.ring); pairlist = strategy.create(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // theList not updated here if (p.isONE()) { unused = pairlist.putOne(); } else { unused = pairlist.put(p); } } else { l--; } } //if (l <= 1) { //return G; must signal termination to others //} logger.debug("looking for clients"); //long t = System.currentTimeMillis(); // now in DL, uses resend for late clients //while ( dls.size() < threads ) { sleep(); } DistHashTable> theList = new DistHashTable>( "localhost", DL_PORT); theList.init(); List> al = pairlist.getList(); for (int i = 0; i < al.size(); i++) { // no wait required GenPolynomial nn = theList.put(Integer.valueOf(i), al.get(i)); if (nn != null) { logger.info("double polynomials " + i + ", nn = " + nn + ", al(i) = " + al.get(i)); } } Terminator fin = new Terminator(threads); ReducerServer R; for (int i = 0; i < threads; i++) { R = new ReducerServer(fin, cf, theList, G, pairlist); pool.addJob(R); } logger.debug("main loop waiting"); fin.waitDone(); int ps = theList.size(); logger.debug("#distributed list = " + ps); // make sure all polynomials arrived: not needed in master // G = (ArrayList)theList.values(); G = pairlist.getList(); if (ps != G.size()) { logger.info("#distributed list = " + theList.size() + " #pairlist list = " + G.size()); } long time = System.currentTimeMillis(); List> Gp; Gp = minimalGB(G); // not jet distributed but threaded time = System.currentTimeMillis() - time; logger.info("parallel gbmi = " + time); /* time = System.currentTimeMillis(); G = GroebnerBase.GBmi(G); // sequential time = System.currentTimeMillis() - time; logger.info("sequential gbmi = " + time); */ G = Gp; logger.debug("cf.terminate()"); cf.terminate(); // no more required // pool.terminate(); logger.info("theList.terminate()"); theList.terminate(); logger.info("dls.terminate()"); dls.terminate(); logger.info("" + pairlist); return G; } /** * GB distributed client. * @param host the server runns on. * @throws IOException */ public void clientPart(String host) throws IOException { ChannelFactory cf = new ChannelFactory(port + 10); // != port for localhost cf.init(); SocketChannel pairChannel = cf.getChannel(host, port); final int DL_PORT = port + 100; DistHashTable> theList = new DistHashTable>(host, DL_PORT); theList.init(); ReducerClient R = new ReducerClient(pairChannel, theList); R.run(); pairChannel.close(); theList.terminate(); cf.terminate(); return; } /** * Minimal ordered groebner basis. * @param Fp a Groebner base. * @return a reduced Groebner base of Fp. */ @Override public List> minimalGB(List> Fp) { GenPolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiReducerServer[] mirs = (MiReducerServer[]) new MiReducerServer[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new MiReducerServer(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } } /** * Distributed server reducing worker threads. * @param coefficient type */ class ReducerServer> implements Runnable { private final Terminator pool; private final ChannelFactory cf; private SocketChannel pairChannel; private final DistHashTable> theList; //private List> G; private final PairList pairlist; private static final Logger logger = Logger.getLogger(ReducerServer.class); ReducerServer(Terminator fin, ChannelFactory cf, DistHashTable> dl, List> G, PairList L) { pool = fin; this.cf = cf; theList = dl; //this.G = G; pairlist = L; } public void run() { logger.debug("reducer server running"); try { pairChannel = cf.getChannel(); } catch (InterruptedException e) { logger.debug("get pair channel interrupted"); e.printStackTrace(); return; } if (logger.isDebugEnabled()) { logger.debug("pairChannel = " + pairChannel); } Pair pair; //GenPolynomial pi; //GenPolynomial pj; //GenPolynomial S; GenPolynomial H = null; boolean set = false; boolean goon = true; int polIndex = -1; int red = 0; int sleeps = 0; // while more requests while (goon) { // receive request logger.debug("receive request"); Object req = null; try { req = pairChannel.receive(); } catch (IOException e) { goon = false; e.printStackTrace(); } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } //logger.debug("received request, req = " + req); if (req == null) { goon = false; break; } if (!(req instanceof GBTransportMessReq)) { goon = false; break; } // find pair logger.debug("find pair"); while (!pairlist.hasNext()) { // wait if (!set) { pool.beIdle(); set = true; } if (!pool.hasJobs() && !pairlist.hasNext()) { goon = false; break; } try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } Thread.sleep(100); } catch (InterruptedException e) { goon = false; break; } } if (!pairlist.hasNext() && !pool.hasJobs()) { goon = false; break; //continue; //break? } if (set) { set = false; pool.notIdle(); } pair = pairlist.removeNext(); /* * send pair to client, receive H */ logger.debug("send pair = " + pair); GBTransportMess msg = null; if (pair != null) { msg = new GBTransportMessPairIndex(pair); } else { msg = new GBTransportMess(); //End(); // goon ?= false; } try { pairChannel.send(msg); } catch (IOException e) { e.printStackTrace(); goon = false; break; } logger.debug("#distributed list = " + theList.size()); Object rh = null; try { rh = pairChannel.receive(); } catch (IOException e) { e.printStackTrace(); goon = false; break; } catch (ClassNotFoundException e) { e.printStackTrace(); goon = false; break; } //logger.debug("received H polynomial"); if (rh == null) { if (pair != null) { pair.setZero(); } } else if (rh instanceof GBTransportMessPoly) { // update pair list red++; H = ((GBTransportMessPoly) rh).pol; if (logger.isDebugEnabled()) { logger.debug("H = " + H); } if (H == null) { if (pair != null) { pair.setZero(); } } else { if (H.isZERO()) { pair.setZero(); } else { if (H.isONE()) { // pool.allIdle(); polIndex = pairlist.putOne(); GenPolynomial nn = theList.put(Integer.valueOf(polIndex), H); if (nn != null) { logger.info("double polynomials nn = " + nn + ", H = " + H); } goon = false; break; } polIndex = pairlist.put(H); // use putWait ? but still not all distributed GenPolynomial nn = theList.put(Integer.valueOf(polIndex), H); if (nn != null) { logger.info("double polynomials nn = " + nn + ", H = " + H); } } } } } logger.info("terminated, done " + red + " reductions"); /* * send end mark to client */ logger.debug("send end"); try { pairChannel.send(new GBTransportMessEnd()); } catch (IOException e) { if (logger.isDebugEnabled()) { e.printStackTrace(); } } pool.beIdle(); pairChannel.close(); } } /** * Distributed clients reducing worker threads. */ class ReducerClient> implements Runnable { private final SocketChannel pairChannel; private final DistHashTable> theList; private final ReductionPar red; private static final Logger logger = Logger.getLogger(ReducerClient.class); ReducerClient(SocketChannel pc, DistHashTable> dl) { pairChannel = pc; theList = dl; red = new ReductionPar(); } public void run() { logger.debug("pairChannel = " + pairChannel + " reducer client running"); Pair pair = null; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial H = null; //boolean set = false; boolean goon = true; int reduction = 0; //int sleeps = 0; Integer pix; Integer pjx; while (goon) { /* protocol: * request pair, process pair, send result */ // pair = (Pair) pairlist.removeNext(); Object req = new GBTransportMessReq(); logger.debug("send request = " + req); try { pairChannel.send(req); } catch (IOException e) { goon = false; e.printStackTrace(); break; } logger.debug("receive pair, goon = " + goon); Object pp = null; try { pp = pairChannel.receive(); } catch (IOException e) { goon = false; if (logger.isDebugEnabled()) { e.printStackTrace(); } break; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } if (logger.isDebugEnabled()) { logger.debug("received pair = " + pp); } H = null; if (pp == null) { // should not happen continue; } if (pp instanceof GBTransportMessEnd) { goon = false; continue; } if (pp instanceof GBTransportMessPair || pp instanceof GBTransportMessPairIndex) { pi = pj = null; if (pp instanceof GBTransportMessPair) { pair = ((GBTransportMessPair) pp).pair; if (pair != null) { pi = pair.pi; pj = pair.pj; //logger.debug("pair: pix = " + pair.i // + ", pjx = " + pair.j); } } if (pp instanceof GBTransportMessPairIndex) { pix = ((GBTransportMessPairIndex) pp).i; pjx = ((GBTransportMessPairIndex) pp).j; pi = (GenPolynomial) theList.getWait(pix); pj = (GenPolynomial) theList.getWait(pjx); //logger.info("pix = " + pix + ", pjx = " +pjx); } if (pi != null && pj != null) { S = red.SPolynomial(pi, pj); //System.out.println("S = " + S); if (S.isZERO()) { // pair.setZero(); does not work in dist } else { if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(theList, S); reduction++; if (H.isZERO()) { // pair.setZero(); does not work in dist } else { H = H.monic(); if (logger.isInfoEnabled()) { logger.info("ht(H) = " + H.leadingExpVector()); } } } } } // send H or must send null if (logger.isDebugEnabled()) { logger.debug("#distributed list = " + theList.size()); logger.debug("send H polynomial = " + H); } try { pairChannel.send(new GBTransportMessPoly(H)); } catch (IOException e) { goon = false; e.printStackTrace(); } } logger.info("terminated, done " + reduction + " reductions"); pairChannel.close(); } } /** * Distributed server reducing worker threads for minimal GB Not jet distributed * but threaded. */ class MiReducerServer> implements Runnable { private final List> G; private GenPolynomial H; private final Semaphore done = new Semaphore(0); private final Reduction red; private static final Logger logger = Logger.getLogger(MiReducerServer.class); MiReducerServer(List> G, GenPolynomial p) { this.G = G; H = p; red = new ReductionPar(); } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenPolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException e) { } return H; } public void run() { if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } H = red.normalform(G, H); //mod done.release(); //done.V(); if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } /** * Distributed clients reducing worker threads for minimal GB. Not jet used. */ class MiReducerClient> implements Runnable { private final List> G; private GenPolynomial H; private final Reduction red; private final Semaphore done = new Semaphore(0); private static final Logger logger = Logger.getLogger(MiReducerClient.class); MiReducerClient(List> G, GenPolynomial p) { this.G = G; H = p; red = new ReductionPar(); } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenPolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException u) { Thread.currentThread().interrupt(); } return H; } public void run() { if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + H.leadingExpVector()); } H = red.normalform(G, H); //mod done.release(); //done.V(); if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } jas-2.5/src/edu/jas/gb/GroebnerBaseParallel.java0000644000175000017500000003167412067140244021745 0ustar giovannigiovanni/* * $Id: GroebnerBaseParallel.java 4329 2012-12-27 21:41:57Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; /** * Groebner Base parallel algortihm. Implements a shared memory parallel version * of Groebner bases. * @param coefficient type * @author Heinz Kredel * * @see edu.jas.application.GBAlgorithmBuilder * @see edu.jas.gbufd.GBFactory */ public class GroebnerBaseParallel> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBaseParallel.class); /** * Number of threads to use. */ protected final int threads; /** * Pool of threads to use. */ protected transient final ThreadPool pool; /** * Constructor. */ public GroebnerBaseParallel() { this(2); } /** * Constructor. * @param threads number of threads to use. */ public GroebnerBaseParallel(int threads) { this(threads, new ThreadPool(threads)); } /** * Constructor. * @param threads number of threads to use. * @param red parallelism aware reduction engine */ public GroebnerBaseParallel(int threads, Reduction red) { this(threads, new ThreadPool(threads), red); } /** * Constructor. * @param threads number of threads to use. * @param pl pair selection strategy */ public GroebnerBaseParallel(int threads, PairList pl) { this(threads, new ThreadPool(threads), new ReductionPar(), pl); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. */ public GroebnerBaseParallel(int threads, ThreadPool pool) { this(threads, pool, new ReductionPar()); } /** * Constructor. * @param pool ThreadPool to use. * @param red Reduction engine */ public GroebnerBaseParallel(int threads, ThreadPool pool, Reduction red) { this(threads, pool, red, new OrderedPairlist()); } /** * Constructor. * @param red Reduction engine * @param pl pair selection strategy */ public GroebnerBaseParallel(int threads, Reduction red, PairList pl) { this(threads, new ThreadPool(threads), red, pl); } /** * Constructor. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param red parallelism aware reduction engine * @param pl pair selection strategy */ public GroebnerBaseParallel(int threads, ThreadPool pool, Reduction red, PairList pl) { super(red, pl); if (!(red instanceof ReductionPar)) { logger.warn("parallel GB should use parallel aware reduction"); } if (threads < 1) { threads = 1; } this.threads = threads; this.pool = pool; } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { if (pool == null) { return; } pool.terminate(); } /** * Cancel ThreadPool. */ @Override public int cancel() { if (pool == null) { return 0; } int s = pool.cancel(); return s; } /** * Parallel Groebner base using pairlist class. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> GB(int modv, List> F) { GenPolynomial p; List> G = new ArrayList>(); PairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { G.clear(); G.add(p); return G; // since no threads activated jet } G.add(p); if (pairlist == null) { //pairlist = new OrderedPairlist( modv, p.ring ); pairlist = strategy.create(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // putOne not required pairlist.put(p); } else { l--; } } if (l <= 1) { return G; // since no threads activated jet } logger.info("start " + pairlist); Terminator fin = new Terminator(threads); Reducer R; for (int i = 0; i < threads; i++) { R = new Reducer(fin, G, pairlist); pool.addJob(R); } fin.waitDone(); if (Thread.currentThread().isInterrupted()) { throw new RuntimeException("interrupt before minimalGB"); } logger.debug("#parallel list = " + G.size()); G = minimalGB(G); // not in this context // pool.terminate(); logger.info("" + pairlist); return G; } /** * Minimal ordered groebner basis, parallel. * @param Fp a Groebner base. * @return minimalGB(F) a minimal Groebner base of Fp. */ @Override public List> minimalGB(List> Fp) { GenPolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); // no thread at this point } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiReducer[] mirs = (MiReducer[]) new MiReducer[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); // System.out.println("doing " + a.length()); mirs[i] = new MiReducer(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } } /** * Reducing worker threads. */ class Reducer> implements Runnable { private final List> G; private final PairList pairlist; private final Terminator fin; private final ReductionPar red; private static final Logger logger = Logger.getLogger(Reducer.class); Reducer(Terminator fin, List> G, PairList L) { this.fin = fin; this.G = G; pairlist = L; red = new ReductionPar(); fin.initIdle(1); } /** * to string */ @Override public String toString() { return "Reducer"; } public void run() { Pair pair; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial H; //boolean set = false; int reduction = 0; int sleeps = 0; while (pairlist.hasNext() || fin.hasJobs()) { while (!pairlist.hasNext()) { // wait //fin.beIdle(); set = true; try { sleeps++; if (sleeps % 10 == 0) { logger.info(" reducer is sleeping"); } else { logger.debug("r"); } Thread.sleep(100); } catch (InterruptedException e) { break; } if (!fin.hasJobs()) { break; } } if (!pairlist.hasNext() && !fin.hasJobs()) { break; } //if ( set ) { //fin.notIdle(); set = false; //} fin.notIdle(); // before pairlist get pair = pairlist.removeNext(); if (Thread.currentThread().isInterrupted()) { fin.initIdle(1); throw new RuntimeException("interrupt after removeNext"); } if (pair == null) { fin.initIdle(1); continue; } pi = pair.pi; pj = pair.pj; if (logger.isDebugEnabled()) { logger.debug("pi = " + pi); logger.debug("pj = " + pj); } S = red.SPolynomial(pi, pj); if (S.isZERO()) { pair.setZero(); fin.initIdle(1); continue; } if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(G, S); //mod reduction++; if (H.isZERO()) { pair.setZero(); fin.initIdle(1); continue; } if (logger.isDebugEnabled()) { logger.info("ht(H) = " + H.leadingExpVector()); } H = H.monic(); // System.out.println("H = " + H); if (H.isONE()) { // putOne not required pairlist.put(H); synchronized (G) { G.clear(); G.add(H); } fin.allIdle(); return; } if (logger.isDebugEnabled()) { logger.debug("H = " + H); } synchronized (G) { G.add(H); } pairlist.put(H); fin.initIdle(1); } fin.allIdle(); logger.info("terminated, done " + reduction + " reductions"); } } /** * Reducing worker threads for minimal GB. */ class MiReducer> implements Runnable { private final List> G; private GenPolynomial H; private final ReductionPar red; private final Semaphore done = new Semaphore(0); private static final Logger logger = Logger.getLogger(MiReducer.class); MiReducer(List> G, GenPolynomial p) { this.G = G; H = p; red = new ReductionPar(); } /** * to string */ @Override public String toString() { return "MiReducer"; } /** * getNF. Blocks until the normal form is computed. * @return the computed normal form. */ public GenPolynomial getNF() { try { done.acquire(); //done.P(); } catch (InterruptedException e) { throw new RuntimeException("interrupt in getNF"); } return H; } public void run() { if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } try { H = red.normalform(G, H); //mod done.release(); //done.V(); } catch (RuntimeException e) { Thread.currentThread().interrupt(); //throw new RuntimeException("interrupt in getNF"); } if (logger.isDebugEnabled()) { logger.debug("ht(H) = " + H.leadingExpVector()); } // H = H.monic(); } } jas-2.5/src/edu/jas/gb/OrderedDPairlist.java0000644000175000017500000001212311503430670021115 0ustar giovannigiovanni/* * $Id: OrderedDPairlist.java 3417 2010-12-19 16:24:24Z kredel $ */ package edu.jas.gb; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.RingElem; /** * Pair list management for d-Groebner bases. * Implemented using GenPolynomial, TreeMap and BitSet. * @author Heinz Kredel */ public class OrderedDPairlist > extends OrderedPairlist { private static final Logger logger = Logger.getLogger(OrderedDPairlist.class); protected final DReduction dreduction; /** * Constructor for OrderedDPairlist. * @param r polynomial factory. */ public OrderedDPairlist(GenPolynomialRing r) { this(0,r); } /** * Constructor for OrderedDPairlist. * @param m number of module variables. * @param r polynomial factory. */ public OrderedDPairlist(int m, GenPolynomialRing r) { super(m,r); dreduction = new DReductionSeq(); } /** * Create a new PairList. * @param r polynomial ring. */ public PairList create(GenPolynomialRing r) { return new OrderedDPairlist(r); } /** * Create a new PairList. * @param m number of module variables. * @param r polynomial ring. */ public PairList create(int m, GenPolynomialRing r) { return new OrderedDPairlist(m,r); } /** * Remove the next required pair from the pairlist and reduction matrix. * The results of the application of the criterions 3 and 4 to see if the S-polynomial * is required are recorded in the Pair. * @return the next pair if one exists, otherwise null. */ @Override public synchronized Pair removeNext() { if ( oneInGB ) { return null; } Iterator< Map.Entry>> > ip = pairlist.entrySet().iterator(); Pair pair = null; boolean c = false; int i, j; if ( ip.hasNext() ) { Map.Entry>> me = ip.next(); ExpVector g = me.getKey(); LinkedList> xl = me.getValue(); if ( logger.isInfoEnabled() ) { logger.info("g = " + g); } pair = null; if ( xl.size() > 0 ) { pair = xl.removeFirst(); // xl is also modified in pairlist i = pair.i; j = pair.j; // System.out.println("pair(" + j + "," +i+") "); if ( useCriterion4 ) { c = dreduction.criterion4( pair.pi, pair.pj, g ); } else { c = true; } pair.setUseCriterion4(c); //System.out.println("c4 = " + c); if ( c ) { c = criterion3( i, j, g ); //System.out.println("c3 = " + c); pair.setUseCriterion3(c); } red.get( j ).clear(i); // set(i,false) jdk1.4 } if ( xl.size() == 0 ) { ip.remove(); // = pairlist.remove( g ); } } remCount++; // count pairs return pair; } /** * GB criterium 3 with coefficient division test. * @return true if the S-polynomial(i,j) is required. */ @Override public boolean criterion3(int i, int j, ExpVector eij) { // assert i < j; boolean s; s = red.get( j ).get(i); if ( ! s ) { logger.warn("c3.s false for " + j + " " + i); return s; } s = true; boolean m; GenPolynomial A; ExpVector ek; C ci = P.get(i).leadingBaseCoefficient(); C cj = P.get(j).leadingBaseCoefficient(); C c = ci.gcd(cj); for ( int k = 0; k < P.size(); k++ ) { A = P.get( k ); ek = A.leadingExpVector(); m = eij.multipleOf(ek); if ( m ) { C ck = A.leadingBaseCoefficient(); C r = c.remainder(ck); m = r.isZERO(); } if ( m ) { if ( k < i ) { // System.out.println("k < i "+k+" "+i); s = red.get( i ).get(k) || red.get( j ).get(k); } if ( i < k && k < j ) { // System.out.println("i < k < j "+i+" "+k+" "+j); s = red.get( k ).get(i) || red.get( j ).get(k); } if ( j < k ) { //System.out.println("j < k "+j+" "+k); s = red.get( k ).get(i) || red.get( k ).get(j); } //System.out.println("s."+k+" = " + s); if ( ! s ) return s; } } return true; } } jas-2.5/src/edu/jas/gb/DReduction.java0000644000175000017500000000232411143275762017770 0ustar giovannigiovanni/* * $Id: DReduction.java 2412 2009-02-07 12:17:54Z kredel $ */ package edu.jas.gb; import java.util.List; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Polynomial D Reduction interface. * Defines additionally D-Polynomial. * @param coefficient type * @author Heinz Kredel */ public interface DReduction> extends Reduction { /** * G-Polynomial. * @param Ap polynomial. * @param Bp polynomial. * @return gpol(Ap,Bp) the g-polynomial of Ap and Bp. */ public GenPolynomial GPolynomial(GenPolynomial Ap, GenPolynomial Bp); /** * D-Polynomial with recording. * @param S recording matrix, is modified. * @param i index of Ap in basis list. * @param Ap a polynomial. * @param j index of Bp in basis list. * @param Bp a polynomial. * @return gpol(Ap, Bp), the g-Polynomial for Ap and Bp. */ public GenPolynomial GPolynomial(List> S, int i, GenPolynomial Ap, int j, GenPolynomial Bp); } jas-2.5/src/edu/jas/gb/Pair.java0000644000175000017500000001161712067303544016624 0ustar giovannigiovanni/* * $Id: Pair.java 4334 2012-12-28 11:49:57Z kredel $ */ package edu.jas.gb; import java.io.Serializable; import edu.jas.structure.RingElem; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; /** * Serializable subclass to hold pairs of polynomials. * @param coefficient type * @author Heinz Kredel. */ public class Pair > extends AbstractPair implements Comparable { protected int n; protected boolean toZero = false; protected boolean useCriterion4 = true; protected boolean useCriterion3 = true; /** * Pair constructor. * @param a polynomial i (must be castable to GenPolynomial<C>). * @param b polynomial j. * @param i first index. * @param j second index. * @deprecated obsolete since Java 1.5 */ @Deprecated public Pair(Object a, GenPolynomial b, int i, int j) { this( (GenPolynomial)a, b, i, j); } /** * Pair constructor. * @param a polynomial i. * @param b polynomial j. * @param i first index. * @param j second index. */ public Pair(GenPolynomial a, GenPolynomial b, int i, int j) { this(a,b,i,j,0); } /** * Pair constructor. * @param a polynomial i. * @param b polynomial j. * @param i first index. * @param j second index. * @param s maximal index. */ public Pair(GenPolynomial a, GenPolynomial b, int i, int j, int s) { this(a.leadingExpVector().lcm(b.leadingExpVector()),a,b,i,j,s); } /** * Pair constructor. * @param lcm of lt(a) lt(b). * @param a polynomial i. * @param b polynomial j. * @param i first index. * @param j second index. */ public Pair(ExpVector lcm, GenPolynomial a, GenPolynomial b, int i, int j) { this(lcm,a,b,i,j,0); } /** * Pair constructor. * @param lcm of lt(a) lt(b). * @param a polynomial i. * @param b polynomial j. * @param i first index. * @param j second index. * @param s maximal index. */ public Pair(ExpVector lcm, GenPolynomial a, GenPolynomial b, int i, int j, int s) { super(lcm,a,b,i,j,s); this.n = 0; toZero = false; // ok } /** * toString. */ @Override public String toString() { return super.toString() + "[" + n + ", r0=" + toZero + ", c4=" + useCriterion4 + ", c3=" + useCriterion3 + "]"; } /** * Set removed pair number. * @param n number of this pair generated in OrderedPairlist. */ public void pairNumber(int n) { this.n = n; } /** * Get removed pair number. * @return n number of this pair generated in OrderedPairlist. */ public int getPairNumber() { return n; } /** * Set zero reduction. * The S-polynomial of this Pair was reduced to zero. */ public void setZero() { toZero = true; } /** * Is reduced to zero. * @return true if the S-polynomial of this Pair was reduced to zero, else false. */ public boolean isZero() { return toZero; } /** * equals. * @param ob an Object. * @return true if this is equal to o, else false. */ @Override public boolean equals(Object ob) { if ( ! (ob instanceof Pair) ) { return false; // throw new ClassCastException("Pair "+n+" o "+o); } return 0 == compareTo( (Pair)ob ); } /** * compareTo used in TreeMap // not used at moment. * Comparison is based on the number of the pairs. * @param p a Pair. * @return 1 if (this < o), 0 if (this == o), -1 if (this > o). */ public int compareTo(Pair p) { int x = p.getPairNumber(); if ( n > x ) { return 1; } if ( n < x ) { return -1; } return 0; } /** * Hash code for this Pair. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return (i << 16) + j; } /** * Set useCriterion4. * @param c boolean value to set. */ public void setUseCriterion4(boolean c) { this.useCriterion4 = c; } /** * Get useCriterion4. * @return boolean value. */ public boolean getUseCriterion4() { return this.useCriterion4; } /** * Set useCriterion3. * @param c boolean value to set. */ public void setUseCriterion3(boolean c) { this.useCriterion3 = c; } /** * Get useCriterion3. * @return boolean value. */ public boolean getUseCriterion3() { return this.useCriterion3; } } jas-2.5/src/edu/jas/gb/WordGroebnerBaseAbstract.java0000644000175000017500000001640112020351336022572 0ustar giovannigiovanni/* * $Id: WordGroebnerBaseAbstract.java 4150 2012-09-01 09:18:23Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.ListIterator; import java.util.Set; import java.util.HashSet; import java.util.Collections; import org.apache.log4j.Logger; import edu.jas.poly.GenWordPolynomial; import edu.jas.poly.GenWordPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.poly.PolyUtil; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.poly.Word; /** * Non-commutative Groebner Bases abstract class. * Implements common Groebner bases and GB test methods. * @param coefficient type * @author Heinz Kredel */ public abstract class WordGroebnerBaseAbstract> implements WordGroebnerBase { private static final Logger logger = Logger.getLogger(WordGroebnerBaseAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Reduction engine. */ public final WordReduction red; /** * Strategy for pair selection. */ public final WordPairList strategy; /** * Constructor. */ public WordGroebnerBaseAbstract() { this( new WordReductionSeq() ); } /** * Constructor. * @param red Word Reduction engine */ public WordGroebnerBaseAbstract(WordReduction red) { this(red, new OrderedWordPairlist() ); } /** * Constructor. * @param red Word Reduction engine * @param pl Word pair selection strategy */ public WordGroebnerBaseAbstract(WordReduction red, WordPairList pl) { this.red = red; this.strategy = pl; } /** * Word Groebner base test. * @param F Word polynomial list. * @return true, if F is a Groebner base, else false. */ public boolean isGB(List> F) { if ( F == null || F.isEmpty() ) { return true; } for ( int i = 0; i < F.size(); i++ ) { GenWordPolynomial pi = F.get(i); for ( int j = i+1; j < F.size(); j++ ) { GenWordPolynomial pj = F.get(j); List> S = red.SPolynomials( pi, pj ); if ( S.isEmpty() ) { continue; } for ( GenWordPolynomial s : S ) { GenWordPolynomial h = red.normalform( F, s ); if ( ! h.isZERO() ) { logger.info("no GB: pi = " + pi + ", pj = " + pj); logger.info("s = " + s + ", h = " + h); return false; } } } } return true; } /** * Groebner base using pairlist class. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public abstract List> GB( List> F ); /** * Minimal ordered Groebner basis. * @param Gp a Groebner base. * @return a reduced Groebner base of Gp. */ public List> minimalGB(List> Gp) { if ( Gp == null || Gp.size() <= 1 ) { return Gp; } // remove zero polynomials List> G = new ArrayList>( Gp.size() ); for ( GenWordPolynomial a : Gp ) { if ( a != null && !a.isZERO() ) { // always true in GB() // already positive a = a.abs(); G.add( a ); } } if ( G.size() <= 1 ) { return G; } // remove top reducible polynomials GenWordPolynomial a; List> F; F = new ArrayList>( G.size() ); while ( G.size() > 0 ) { a = G.remove(0); if ( red.isTopReducible(G,a) || red.isTopReducible(F,a) ) { // drop polynomial if ( debug ) { System.out.println("dropped " + a); List> ff; ff = new ArrayList>( G ); ff.addAll(F); a = red.normalform( ff, a ); if ( !a.isZERO() ) { System.out.println("error, nf(a) " + a); } } } else { F.add(a); } } G = F; if ( G.size() <= 1 ) { return G; } // reduce remaining polynomials Collections.reverse(G); // important for lex GB int len = G.size(); if ( debug ) { System.out.println("#G " + len); for (GenWordPolynomial aa : G) { System.out.println("aa = " + aa.length() + ", lt = " + aa.getMap().keySet()); } } int i = 0; while ( i < len ) { a = G.remove(0); if ( debug ) { System.out.println("doing " + a.length() + ", lt = " + a.leadingWord()); } a = red.normalform( G, a ); G.add( a ); // adds as last i++; } return G; } /** * Test for minimal ordered Groebner basis. * @param Gp an ideal base. * @return true, if Gp is a reduced minimal Groebner base. */ public boolean isMinimalGB(List> Gp) { if ( Gp == null || Gp.size() == 0 ) { return true; } // test for zero polynomials for ( GenWordPolynomial a : Gp ) { if ( a == null || a.isZERO() ) { if (debug) { logger.debug("zero polynomial " + a); } return false; } } // test for top reducible polynomials List> G = new ArrayList>( Gp ); List> F = new ArrayList>( G.size() ); while ( G.size() > 0 ) { GenWordPolynomial a = G.remove(0); if ( red.isTopReducible(G,a) || red.isTopReducible(F,a) ) { if (debug) { logger.debug("top reducible polynomial " + a); } return false; } else { F.add(a); } } G = F; if ( G.size() <= 1 ) { return true; } // test reducibility of polynomials int len = G.size(); int i = 0; while ( i < len ) { GenWordPolynomial a = G.remove(0); if ( ! red.isNormalform( G, a ) ) { if (debug) { logger.debug("reducible polynomial " + a); } return false; } G.add( a ); // re-adds as last i++; } return true; } /** * Cleanup and terminate ThreadPool. */ public void terminate() { logger.info("terminate not implemented"); } /** * Cancel ThreadPool. */ public int cancel() { logger.info("cancel not implemented"); return 0; } } jas-2.5/src/edu/jas/gb/ReductionSeq.java0000644000175000017500000001413712045172206020331 0ustar giovannigiovanni/* * $Id: ReductionSeq.java 4281 2012-11-03 10:40:06Z kredel $ */ package edu.jas.gb; import java.util.List; import java.util.Map; //import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Polynomial Reduction sequential use algorithm. * Implements normalform. * @param coefficient type * @author Heinz Kredel */ public class ReductionSeq> // should be FieldElem> extends ReductionAbstract { //private static final Logger logger = Logger.getLogger(ReductionSeq.class); /** * Constructor. */ public ReductionSeq() { } /** * Normalform. * @param Ap polynomial. * @param Pp polynomial list. * @return nf(Ap) with respect to Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(List> Pp, GenPolynomial Ap) { if ( Pp == null || Pp.isEmpty() ) { return Ap; } if ( Ap == null || Ap.isZERO() ) { return Ap; } if ( ! Ap.ring.coFac.isField() ) { throw new IllegalArgumentException("coefficients not from a field"); } Map.Entry m; int l; GenPolynomial[] P; synchronized (Pp) { l = Pp.size(); P = new GenPolynomial[l]; //P = Pp.toArray(); for ( int i = 0; i < Pp.size(); i++ ) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[ l ]; Object[] lbc = new Object[ l ]; // want C[] GenPolynomial[] p = new GenPolynomial[ l ]; int i; int j = 0; for ( i = 0; i < l; i++ ) { p[i] = P[i]; m = p[i].leadingMonomial(); if ( m != null ) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; boolean mt = false; GenPolynomial R = Ap.ring.getZERO().copy(); //GenPolynomial T = null; GenPolynomial Q = null; GenPolynomial S = Ap.copy(); while ( S.length() > 0 ) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for ( i = 0; i < l; i++ ) { mt = e.multipleOf( htl[i] ); if ( mt ) break; } if ( ! mt ) { //logger.debug("irred"); //R = R.sum( a, e ); //S = S.subtract( a, e ); R.doPutToMap(e,a); S.doRemoveFromMap(e,a); // System.out.println(" S = " + S); } else { e = e.subtract( htl[i] ); //logger.info("red div = " + e); a = a.divide( (C)lbc[i] ); //Q = p[i].multiply( a, e ); //S = S.subtract( Q ); S = S.subtractMultiple(a,e,p[i]); } } return R; } /** * Normalform with recording. * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. */ @SuppressWarnings("unchecked") public GenPolynomial normalform(List> row, List> Pp, GenPolynomial Ap) { if ( Pp == null || Pp.isEmpty() ) { return Ap; } if ( Ap == null || Ap.isZERO() ) { return Ap; } if ( ! Ap.ring.coFac.isField() ) { throw new IllegalArgumentException("coefficients not from a field"); } int l = Pp.size(); GenPolynomial[] P = new GenPolynomial[l]; synchronized (Pp) { //P = Pp.toArray(); for ( int i = 0; i < Pp.size(); i++ ) { P[i] = Pp.get(i); } } ExpVector[] htl = new ExpVector[ l ]; Object[] lbc = new Object[ l ]; // want C[] GenPolynomial[] p = new GenPolynomial[ l ]; Map.Entry m; int j = 0; int i; for ( i = 0; i < l; i++ ) { p[i] = P[i]; m = p[i].leadingMonomial(); if ( m != null ) { p[j] = p[i]; htl[j] = m.getKey(); lbc[j] = m.getValue(); j++; } } l = j; ExpVector e; C a; boolean mt = false; GenPolynomial zero = Ap.ring.getZERO(); GenPolynomial R = Ap.ring.getZERO().copy(); GenPolynomial fac = null; // GenPolynomial T = null; GenPolynomial Q = null; GenPolynomial S = Ap.copy(); while ( S.length() > 0 ) { m = S.leadingMonomial(); e = m.getKey(); a = m.getValue(); for ( i = 0; i < l; i++ ) { mt = e.multipleOf( htl[i] ); if ( mt ) break; } if ( ! mt ) { //logger.debug("irred"); //R = R.sum( a, e ); //S = S.subtract( a, e ); R.doPutToMap(e,a); S.doRemoveFromMap(e,a); // System.out.println(" S = " + S); //throw new RuntimeException("Syzygy no GB"); } else { e = e.subtract( htl[i] ); //logger.info("red div = " + e); C c = (C) lbc[i]; a = a.divide( c ); //Q = p[i].multiply( a, e ); //S = S.subtract( Q ); S = S.subtractMultiple(a,e,p[i]); fac = row.get(i); if ( fac == null ) { fac = zero.sum( a, e ); } else { fac = fac.sum( a, e ); } row.set(i,fac); } } return R; } } jas-2.5/src/edu/jas/gb/GroebnerBaseDistributedHybridEC.java0000644000175000017500000011032012067562026024035 0ustar giovannigiovanni/* * $Id: GroebnerBaseDistributedHybridEC.java 4337 2012-12-29 12:37:43Z kredel $ */ package edu.jas.gb; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.ListIterator; import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; import edu.jas.util.ChannelFactory; import edu.jas.util.DistHashTable; import edu.jas.util.DistHashTableServer; import edu.jas.util.SocketChannel; import edu.jas.util.TaggedSocketChannel; import edu.jas.util.Terminator; import edu.jas.util.ThreadPool; import edu.jas.util.DistThreadPool; import edu.jas.util.RemoteExecutable; /** * Groebner Base distributed hybrid algorithm. Implements a * distributed memory with multi-core CPUs parallel version of * Groebner bases with executable channels. Using pairlist class, * distributed multi-threaded tasks do reduction, one communication * channel per remote node. * @param coefficient type * @author Heinz Kredel */ public class GroebnerBaseDistributedHybridEC> extends GroebnerBaseAbstract { public static final Logger logger = Logger.getLogger(GroebnerBaseDistributedHybridEC.class); public final boolean debug = logger.isDebugEnabled(); /** * Number of threads to use. */ protected final int threads; /** * Default number of threads. */ protected static final int DEFAULT_THREADS = 2; /** * Number of threads per node to use. */ protected final int threadsPerNode; /** * Default number of threads per compute node. */ protected static final int DEFAULT_THREADS_PER_NODE = 1; /** * Pool of threads to use. */ //protected final ExecutorService pool; // not for single node tests protected transient final ThreadPool pool; /** * Default server port. */ protected static final int DEFAULT_PORT = 55711; /** * Default distributed hash table server port. */ protected final int DHT_PORT; /** * machine file to use. */ protected final String mfile; /** * Server port to use. */ protected final int port; /** * Distributed thread pool to use. */ private final DistThreadPool dtp; /** * Distributed hash table server to use. */ private final DistHashTableServer dhts; /** * Message tag for pairs. */ public static final Integer pairTag = Integer.valueOf(1); /** * Message tag for results. */ public static final Integer resultTag = Integer.valueOf(2); /** * Message tag for acknowledgments. */ public static final Integer ackTag = Integer.valueOf(3); /** * Constructor. * @param mfile name of the machine file. */ public GroebnerBaseDistributedHybridEC(String mfile) { this(mfile, DEFAULT_THREADS, DEFAULT_PORT); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. */ public GroebnerBaseDistributedHybridEC(String mfile, int threads) { this(mfile, threads, new ThreadPool(threads), DEFAULT_PORT); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. * @param port server port to use. */ public GroebnerBaseDistributedHybridEC(String mfile, int threads, int port) { this(mfile, threads, new ThreadPool(threads), port); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. * @param port server port to use. */ public GroebnerBaseDistributedHybridEC(String mfile, int threads, int threadsPerNode, int port) { this(mfile, threads, threadsPerNode, new ThreadPool(threads), port); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. * @param pool ThreadPool to use. * @param port server port to use. */ public GroebnerBaseDistributedHybridEC(String mfile, int threads, ThreadPool pool, int port) { this(mfile, threads, DEFAULT_THREADS_PER_NODE, pool, port); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. * @param pl pair selection strategy * @param port server port to use. */ public GroebnerBaseDistributedHybridEC(String mfile, int threads, int threadsPerNode, PairList pl, int port) { this(mfile, threads, threadsPerNode, new ThreadPool(threads), pl, port); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. * @param port server port to use. */ public GroebnerBaseDistributedHybridEC(String mfile, int threads, int threadsPerNode, ThreadPool pool, int port) { this(mfile, threads, threadsPerNode, pool, new OrderedPairlist(), port); } /** * Constructor. * @param mfile name of the machine file. * @param threads number of threads to use. * @param threadsPerNode threads per node to use. * @param pool ThreadPool to use. * @param pl pair selection strategy * @param port server port to use. */ public GroebnerBaseDistributedHybridEC(String mfile, int threads, int threadsPerNode, ThreadPool pool, PairList pl, int port) { super(new ReductionPar(), pl); this.threads = threads; if (mfile == null || mfile.length() == 0) { this.mfile = "../util/machines"; // contains localhost } else { this.mfile = mfile; } if (threads < 1) { threads = 1; } this.threadsPerNode = threadsPerNode; if ( pool == null ) { pool = new ThreadPool(threads); } this.pool = pool; this.port = port; logger.info("machine file " + mfile + ", port = " + port); this.dtp = new DistThreadPool(this.threads, this.mfile); logger.info("running " + dtp); this.DHT_PORT = this.dtp.getEC().getMasterPort() + 100; this.dhts = new DistHashTableServer(this.DHT_PORT); this.dhts.init(); logger.info("running " + dhts); } /** * Cleanup and terminate ThreadPool. */ @Override public void terminate() { terminate(true); } /** * Terminates the distributed thread pools. * @param shutDown true, if shut-down of the remote executable servers is * requested, false, if remote executable servers stay alive. */ public void terminate(boolean shutDown) { pool.terminate(); dtp.terminate(shutDown); logger.debug("dhts.terminate()"); dhts.terminate(); } /** * Distributed Groebner base. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs. */ public List> GB(int modv, List> F) { String master = dtp.getEC().getMasterHost(); //int port = dtp.getEC().getMasterPort(); // wrong port GBHybridExerClient gbc = new GBHybridExerClient(master, threadsPerNode, port, DHT_PORT); for (int i = 0; i < threads; i++) { // schedule remote clients dtp.addJob(gbc); } // run master List> G = GBMaster(modv, F); return G; } /** * Distributed hybrid Groebner base. * @param modv number of module variables. * @param F polynomial list. * @return GB(F) a Groebner base of F or null, if a IOException occurs. */ public List> GBMaster(int modv, List> F) { long t = System.currentTimeMillis(); ChannelFactory cf = new ChannelFactory(port); cf.init(); GenPolynomial p; List> G = new ArrayList>(); PairList pairlist = null; boolean oneInGB = false; int l = F.size(); int unused; ListIterator> it = F.listIterator(); while (it.hasNext()) { p = it.next(); if (p.length() > 0) { p = p.monic(); if (p.isONE()) { oneInGB = true; G.clear(); G.add(p); //return G; must signal termination to others } if (!oneInGB) { G.add(p); } if (pairlist == null) { //pairlist = new OrderedPairlist(modv, p.ring); pairlist = strategy.create(modv, p.ring); if (!p.ring.coFac.isField()) { throw new IllegalArgumentException("coefficients not from a field"); } } // theList not updated here if (p.isONE()) { unused = pairlist.putOne(); } else { unused = pairlist.put(p); } } else { l--; } } //if (l <= 1) { //return G; must signal termination to others //} logger.info("pairlist " + pairlist); DistHashTable> theList = new DistHashTable>( "localhost", DHT_PORT); theList.init(); List> al = pairlist.getList(); for (int i = 0; i < al.size(); i++) { // no wait required GenPolynomial nn = theList.put(Integer.valueOf(i), al.get(i)); if (nn != null) { logger.info("double polynomials " + i + ", nn = " + nn + ", al(i) = " + al.get(i)); } } Terminator finner = new Terminator(threads * threadsPerNode); HybridReducerServerEC R; logger.info("using pool = " + pool); for (int i = 0; i < threads; i++) { R = new HybridReducerServerEC(threadsPerNode, finner, cf, theList, pairlist); pool.addJob(R); //logger.info("server submitted " + R); } logger.info("main loop waiting " + finner); finner.waitDone(); int ps = theList.size(); logger.info("#distributed list = " + ps); // make sure all polynomials arrived: not needed in master // G = (ArrayList)theList.values(); G = pairlist.getList(); if (ps != G.size()) { logger.info("#distributed list = " + theList.size() + " #pairlist list = " + G.size()); } for (GenPolynomial q : theList.getValueList()) { if (q != null && !q.isZERO()) { logger.debug("final q = " + q.leadingExpVector()); } } logger.debug("distributed list end"); long time = System.currentTimeMillis(); List> Gp; Gp = minimalGB(G); // not jet distributed but threaded time = System.currentTimeMillis() - time; logger.debug("parallel gbmi time = " + time); G = Gp; logger.debug("server cf.terminate()"); cf.terminate(); // no more required // //logger.info("server not pool.terminate() " + pool); //pool.terminate(); logger.debug("server theList.terminate() " + theList.size()); theList.terminate(); t = System.currentTimeMillis() - t; logger.info("server GB end, time = " + t + ", " + pairlist.toString()); return G; } /** * GB distributed client part. * @param host the server runs on. * @param port the server runs. * @param dhtport of the DHT server. * @throws IOException */ public static > void clientPart(String host, int threadsPerNode, int port, int dhtport) throws IOException { ChannelFactory cf = new ChannelFactory(port + 10); // != port for localhost cf.init(); logger.info("clientPart connecting to " + host + ", port = " + port + ", dhtport = " + dhtport); SocketChannel channel = cf.getChannel(host, port); TaggedSocketChannel pairChannel = new TaggedSocketChannel(channel); pairChannel.init(); DistHashTable> theList = new DistHashTable>(host, dhtport); theList.init(); ThreadPool pool = new ThreadPool(threadsPerNode); logger.info("client using pool = " + pool); for (int i = 0; i < threadsPerNode; i++) { HybridReducerClientEC Rr = new HybridReducerClientEC(threadsPerNode, pairChannel, i, theList); pool.addJob(Rr); } logger.debug("clients submitted"); pool.terminate(); logger.debug("client pool.terminate()"); pairChannel.close(); logger.debug("client pairChannel.close()"); theList.terminate(); cf.terminate(); logger.info("client cf.terminate()"); channel.close(); logger.info("client channel.close()"); return; } /** * Minimal ordered groebner basis. * @param Fp a Groebner base. * @return a reduced Groebner base of Fp. */ @Override public List> minimalGB(List> Fp) { GenPolynomial a; ArrayList> G; G = new ArrayList>(Fp.size()); ListIterator> it = Fp.listIterator(); while (it.hasNext()) { a = it.next(); if (a.length() != 0) { // always true // already monic a = a.monic(); G.add(a); } } if (G.size() <= 1) { return G; } ExpVector e; ExpVector f; GenPolynomial p; ArrayList> F; F = new ArrayList>(G.size()); boolean mt; while (G.size() > 0) { a = G.remove(0); e = a.leadingExpVector(); it = G.listIterator(); mt = false; while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } it = F.listIterator(); while (it.hasNext() && !mt) { p = it.next(); f = p.leadingExpVector(); mt = e.multipleOf(f); } if (!mt) { F.add(a); } else { // System.out.println("dropped " + a.length()); } } G = F; if (G.size() <= 1) { return G; } Collections.reverse(G); // important for lex GB MiReducerServer[] mirs = (MiReducerServer[]) new MiReducerServer[G.size()]; int i = 0; F = new ArrayList>(G.size()); while (G.size() > 0) { a = G.remove(0); // System.out.println("doing " + a.length()); List> R = new ArrayList>(G.size() + F.size()); R.addAll(G); R.addAll(F); mirs[i] = new MiReducerServer(R, a); pool.addJob(mirs[i]); i++; F.add(a); } G = F; F = new ArrayList>(G.size()); for (i = 0; i < mirs.length; i++) { a = mirs[i].getNF(); F.add(a); } return F; } } /** * Distributed server reducing worker proxy threads. * @param coefficient type */ class HybridReducerServerEC> implements Runnable { public static final Logger logger = Logger.getLogger(HybridReducerServerEC.class); public final boolean debug = logger.isDebugEnabled(); private final Terminator finner; private final ChannelFactory cf; private TaggedSocketChannel pairChannel; private final DistHashTable> theList; private final PairList pairlist; private final int threadsPerNode; /** * Message tag for pairs. */ public final Integer pairTag = GroebnerBaseDistributedHybrid.pairTag; /** * Message tag for results. */ public final Integer resultTag = GroebnerBaseDistributedHybrid.resultTag; /** * Message tag for acknowledgments. */ public final Integer ackTag = GroebnerBaseDistributedHybrid.ackTag; /** * Constructor. * @param tpn number of threads per node * @param fin terminator * @param cf channel factory * @param dl distributed hash table * @param L ordered pair list */ HybridReducerServerEC(int tpn, Terminator fin, ChannelFactory cf, DistHashTable> dl, PairList L) { threadsPerNode = tpn; finner = fin; this.cf = cf; theList = dl; pairlist = L; //logger.info("reducer server created " + this); } /** * Work loop. * @see java.lang.Runnable#run() */ //JAVA6only: @Override public void run() { logger.info("reducer server running with " + cf); SocketChannel channel = null; try { channel = cf.getChannel(); pairChannel = new TaggedSocketChannel(channel); pairChannel.init(); } catch (InterruptedException e) { logger.debug("get pair channel interrupted"); e.printStackTrace(); return; } if (debug) { logger.info("pairChannel = " + pairChannel); } // record idle remote workers (minus one?) //finner.beIdle(threadsPerNode-1); finner.initIdle(threadsPerNode); AtomicInteger active = new AtomicInteger(0); // start receiver HybridReducerReceiverEC receiver = new HybridReducerReceiverEC(threadsPerNode, finner, active, pairChannel, theList, pairlist); receiver.start(); Pair pair; //boolean set = false; boolean goon = true; //int polIndex = -1; int red = 0; int sleeps = 0; // while more requests while (goon) { // receive request if thread is reported incactive logger.debug("receive request"); Object req = null; try { req = pairChannel.receive(pairTag); } catch (InterruptedException e) { goon = false; e.printStackTrace(); } catch (IOException e) { goon = false; e.printStackTrace(); } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } //logger.info("received request, req = " + req); if (req == null) { goon = false; break; } if (!(req instanceof GBTransportMessReq)) { goon = false; break; } // find pair and manage termination status logger.debug("find pair"); while (!pairlist.hasNext()) { // wait if (!finner.hasJobs() && !pairlist.hasNext()) { goon = false; break; } try { sleeps++; //if (sleeps % 10 == 0) { logger.info("waiting for reducers, remaining = " + finner.getJobs()); //} Thread.sleep(100); } catch (InterruptedException e) { goon = false; break; } } if (!pairlist.hasNext() && !finner.hasJobs()) { logger.info("termination detection: no pairs and no jobs left"); goon = false; break; //continue; //break? } finner.notIdle(); // before pairlist get!! pair = pairlist.removeNext(); // send pair to client, even if null if (debug) { logger.info("active count = " + active.get()); logger.info("send pair = " + pair); } GBTransportMess msg = null; if (pair != null) { msg = new GBTransportMessPairIndex(pair); //,pairlist.size()-1); // size-1 } else { msg = new GBTransportMess(); // not End(); at this time // goon ?= false; } try { red++; pairChannel.send(pairTag, msg); int a = active.getAndIncrement(); } catch (IOException e) { e.printStackTrace(); goon = false; break; } //logger.debug("#distributed list = " + theList.size()); } logger.info("terminated, send " + red + " reduction pairs"); /* * send end mark to clients */ logger.debug("send end"); try { for (int i = 0; i < threadsPerNode; i++) { // -1 //do not wait: Object rq = pairChannel.receive(pairTag); pairChannel.send(pairTag, new GBTransportMessEnd()); } // send also end to receiver pairChannel.send(resultTag, new GBTransportMessEnd()); //beware of race condition } catch (IOException e) { if (logger.isDebugEnabled()) { e.printStackTrace(); } } receiver.terminate(); int d = active.get(); if ( d > 0 ) { logger.info("remaining active tasks = " + d); } //logger.info("terminated, send " + red + " reduction pairs"); pairChannel.close(); logger.debug("redServ pairChannel.close()"); finner.release(); channel.close(); logger.info("redServ channel.close()"); } } /** * Distributed server receiving worker thread. * @param coefficient type */ class HybridReducerReceiverEC> extends Thread { public static final Logger logger = Logger.getLogger(HybridReducerReceiverEC.class); public final boolean debug = logger.isDebugEnabled(); private final DistHashTable> theList; private final PairList pairlist; private final TaggedSocketChannel pairChannel; private final Terminator finner; private final int threadsPerNode; private final AtomicInteger active; private volatile boolean goon; /** * Message tag for pairs. */ public final Integer pairTag = GroebnerBaseDistributedHybrid.pairTag; /** * Message tag for results. */ public final Integer resultTag = GroebnerBaseDistributedHybrid.resultTag; /** * Message tag for acknowledgments. */ public final Integer ackTag = GroebnerBaseDistributedHybrid.ackTag; /** * Constructor. * @param tpn number of threads per node * @param fin terminator * @param a active remote tasks count * @param pc tagged socket channel * @param dl distributed hash table * @param L ordered pair list */ HybridReducerReceiverEC(int tpn, Terminator fin, AtomicInteger a, TaggedSocketChannel pc, DistHashTable> dl, PairList L) { active = a; threadsPerNode = tpn; finner = fin; pairChannel = pc; theList = dl; pairlist = L; goon = true; //logger.info("reducer server created " + this); } /** * Work loop. * @see java.lang.Thread#run() */ @Override public void run() { //Pair pair = null; GenPolynomial H = null; int red = 0; int polIndex = -1; //Integer senderId; // obsolete // while more requests while (goon) { // receive request logger.debug("receive result"); //senderId = null; Object rh = null; try { rh = pairChannel.receive(resultTag); int i = active.getAndDecrement(); } catch (InterruptedException e) { goon = false; //e.printStackTrace(); //?? finner.initIdle(1); break; } catch (IOException e) { e.printStackTrace(); goon = false; finner.initIdle(1); break; } catch (ClassNotFoundException e) { e.printStackTrace(); goon = false; finner.initIdle(1); break; } logger.info("received H polynomial"); if (rh == null) { if (this.isInterrupted()) { goon = false; finner.initIdle(1); break; } //finner.initIdle(1); } else if (rh instanceof GBTransportMessEnd) { // should only happen from server logger.info("received GBTransportMessEnd"); goon = false; //?? finner.initIdle(1); break; } else if (rh instanceof GBTransportMessPoly) { // update pair list red++; GBTransportMessPoly mpi = (GBTransportMessPoly) rh; H = mpi.pol; //senderId = mpi.threadId; if (H != null) { if (debug) { logger.info("H = " + H.leadingExpVector()); } if (!H.isZERO()) { if (H.isONE()) { // finner.allIdle(); polIndex = pairlist.putOne(); theList.putWait(Integer.valueOf(polIndex), H); //goon = false; must wait for other clients //finner.initIdle(1); //break; } else { polIndex = pairlist.put(H); // use putWait ? but still not all distributed //GenPolynomial nn = theList.putWait(Integer.valueOf(polIndex), H); } } } } // only after recording in pairlist ! finner.initIdle(1); try { pairChannel.send(ackTag, new GBTransportMess()); logger.debug("send acknowledgement"); } catch (IOException e) { e.printStackTrace(); goon = false; break; } } // end while goon = false; logger.info("terminated, received " + red + " reductions"); } /** * Terminate. */ public void terminate() { goon = false; //this.interrupt(); try { this.join(); } catch (InterruptedException e) { // unfug Thread.currentThread().interrupt(); } logger.debug("HybridReducerReceiver terminated"); } } /** * Distributed clients reducing worker threads. */ class HybridReducerClientEC> implements Runnable { private static final Logger logger = Logger.getLogger(HybridReducerClientEC.class); public final boolean debug = logger.isDebugEnabled(); private final TaggedSocketChannel pairChannel; private final DistHashTable> theList; private final ReductionPar red; private final int threadsPerNode; /* * Identification number for this thread. */ //public final Integer threadId; // obsolete /** * Message tag for pairs. */ public final Integer pairTag = GroebnerBaseDistributedHybrid.pairTag; /** * Message tag for results. */ public final Integer resultTag = GroebnerBaseDistributedHybrid.resultTag; /** * Message tag for acknowledgments. */ public final Integer ackTag = GroebnerBaseDistributedHybrid.ackTag; /** * Constructor. * @param tpn number of threads per node * @param tc tagged socket channel * @param tid thread identification * @param dl distributed hash table */ HybridReducerClientEC(int tpn, TaggedSocketChannel tc, Integer tid, DistHashTable> dl) { this.threadsPerNode = tpn; pairChannel = tc; //threadId = 100 + tid; // keep distinct from other tags theList = dl; red = new ReductionPar(); } /** * Work loop. * @see java.lang.Runnable#run() */ //JAVA6only: @Override public void run() { if (debug) { logger.info("pairChannel = " + pairChannel + " reducer client running"); } Pair pair = null; GenPolynomial pi, pj, ps; GenPolynomial S; GenPolynomial H = null; //boolean set = false; boolean goon = true; boolean doEnd = true; int reduction = 0; //int sleeps = 0; Integer pix, pjx, psx; while (goon) { /* protocol: * request pair, process pair, send result, receive acknowledgment */ // pair = (Pair) pairlist.removeNext(); Object req = new GBTransportMessReq(); logger.debug("send request"); try { pairChannel.send(pairTag, req); } catch (IOException e) { goon = false; if (logger.isDebugEnabled()) { e.printStackTrace(); } logger.info("receive pair, IOexception "); break; } logger.debug("receive pair, goon = " + goon); doEnd = true; Object pp = null; try { pp = pairChannel.receive(pairTag); } catch (InterruptedException e) { goon = false; e.printStackTrace(); } catch (IOException e) { goon = false; if (logger.isDebugEnabled()) { e.printStackTrace(); } break; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } if (debug) { logger.info("received pair = " + pp); } H = null; if (pp == null) { // should not happen continue; } if (pp instanceof GBTransportMessEnd) { goon = false; //doEnd = false; continue; } if (pp instanceof GBTransportMessPair || pp instanceof GBTransportMessPairIndex) { pi = pj = ps = null; if (pp instanceof GBTransportMessPair) { // obsolet, for tests GBTransportMessPair tmp = (GBTransportMessPair) pp; pair = (Pair) tmp.pair; if (pair != null) { pi = pair.pi; pj = pair.pj; //logger.debug("pair: pix = " + pair.i // + ", pjx = " + pair.j); } } if (pp instanceof GBTransportMessPairIndex) { GBTransportMessPairIndex tmpi = (GBTransportMessPairIndex)pp; pix = tmpi.i; pjx = tmpi.j; psx = tmpi.s; pi = theList.getWait(pix); pj = theList.getWait(pjx); ps = theList.getWait(psx); //logger.info("pix = " + pix + ", pjx = " + pjx + ", psx = " + psx); } if (pi != null && pj != null) { S = red.SPolynomial(pi, pj); //logger.info("ht(S) = " + S.leadingExpVector()); if (S.isZERO()) { // pair.setZero(); does not work in dist } else { if (logger.isDebugEnabled()) { logger.debug("ht(S) = " + S.leadingExpVector()); } H = red.normalform(theList, S); //logger.info("ht(H) = " + H.leadingExpVector()); reduction++; if (H.isZERO()) { // pair.setZero(); does not work in dist } else { H = H.monic(); if (logger.isInfoEnabled()) { logger.info("ht(H) = " + H.leadingExpVector()); } } } } else { logger.info("pi = " + pi + ", pj = " + pj + ", ps = " + ps); } } if (pp instanceof GBTransportMess) { logger.debug("null pair results in null H poly"); } // send H or must send null, if not at end if (logger.isDebugEnabled()) { logger.debug("#distributed list = " + theList.size()); logger.debug("send H polynomial = " + H); } try { pairChannel.send(resultTag, new GBTransportMessPoly(H)); //,threadId)); doEnd = false; } catch (IOException e) { goon = false; e.printStackTrace(); } //logger.info("done send poly message of " + pp); try { //pp = pairChannel.receive(threadId); pp = pairChannel.receive(ackTag); } catch (InterruptedException e) { goon = false; e.printStackTrace(); } catch (IOException e) { goon = false; if (logger.isDebugEnabled()) { e.printStackTrace(); } break; } catch (ClassNotFoundException e) { goon = false; e.printStackTrace(); } if (!(pp instanceof GBTransportMess)) { logger.error("invalid acknowledgement " + pp); } logger.info("received acknowledgment "); } logger.info("terminated, done " + reduction + " reductions"); if (doEnd) { try { pairChannel.send(resultTag, new GBTransportMessEnd()); } catch (IOException e) { //e.printStackTrace(); } logger.debug("terminated, send done"); } } } /** * Objects of this class are to be send to a ExecutableServer. */ class GBHybridExerClient> implements RemoteExecutable { String host; int port; int dhtport; int threadsPerNode; /** * GBHybridExerClient. * @param host * @param port * @param dhtport */ public GBHybridExerClient(String host, int threadsPerNode, int port, int dhtport) { this.host = host; this.threadsPerNode = threadsPerNode; this.port = port; this.dhtport = dhtport; } /** * run. */ public void run() { try { GroebnerBaseDistributedHybridEC. clientPart(host,threadsPerNode,port,dhtport); } catch (Exception e) { e.printStackTrace(); } } /** * String representation. */ @Override public String toString() { StringBuffer s = new StringBuffer("GBHybridExerClient("); s.append("host="+host); s.append(", threadsPerNode="+threadsPerNode); s.append(", port="+port); s.append(", dhtport="+dhtport); s.append(")"); return s.toString(); } } jas-2.5/src/edu/jas/gb/PairList.java0000644000175000017500000000441412034237746017461 0ustar giovannigiovanni/* * $Id: PairList.java 4239 2012-10-07 08:40:06Z kredel $ */ package edu.jas.gb; import java.util.List; import edu.jas.structure.RingElem; import edu.jas.poly.ExpVector; import edu.jas.poly.TermOrder; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; /** * Pair list management interface. * @author Heinz Kredel */ public interface PairList > { /** * Create a new PairList. * @param r polynomial ring. */ public PairList create(GenPolynomialRing r); /** * Create a new PairList. * @param m number of module variables. * @param r polynomial ring. */ public PairList create(int m, GenPolynomialRing r); /** * toString. */ @Override public String toString(); /** * Put one Polynomial to the pairlist and reduction matrix. * @param p polynomial. * @return the index of the added polynomial. */ public int put(GenPolynomial p); /** * Put to ONE-Polynomial to the pairlist. * @return the index of the last polynomial. */ public int putOne(); /** * Remove the next required pair from the pairlist and reduction matrix. * Appy the criterions 3 and 4 to see if the S-polynomial is required. * @return the next pair if one exists, otherwise null. */ public Pair removeNext(); /** * Test if there is possibly a pair in the list. * @return true if a next pair could exist, otherwise false. */ public boolean hasNext(); /** * Get the size of the list of polynomials. * @return size of the polynomial list. */ public int size(); /** * Get the list of polynomials. * @return the polynomial list. */ public List> getList(); /** * Get the number of polynomials put to the pairlist. * @return the number of calls to put. */ public int putCount(); /** * Get the number of required pairs removed from the pairlist. * @return the number of non null pairs delivered. */ public int remCount(); /** * GB criterium 3. * @return true if the S-polynomial(i,j) is required. */ public boolean criterion3(int i, int j, ExpVector eij); } jas-2.5/src/edu/jas/gb/SolvableReductionAbstract.java0000644000175000017500000002262112013663732023035 0ustar giovannigiovanni/* * $Id: SolvableReductionAbstract.java 4104 2012-08-18 10:00:59Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenSolvablePolynomial; import edu.jas.structure.RingElem; /** * Solvable polynomial Reduction abstract class. Implements common left, right * S-Polynomial, left normalform and left irreducible set. * @param coefficient type * @author Heinz Kredel */ public abstract class SolvableReductionAbstract> implements SolvableReduction { private static final Logger logger = Logger.getLogger(SolvableReductionAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public SolvableReductionAbstract() { } /** * Left S-Polynomial. * @param Ap solvable polynomial. * @param Bp solvable polynomial. * @return left-spol(Ap,Bp) the left S-polynomial of Ap and Bp. */ public GenSolvablePolynomial leftSPolynomial(GenSolvablePolynomial Ap, GenSolvablePolynomial Bp) { if (logger.isInfoEnabled()) { if (Bp == null || Bp.isZERO()) { if (Ap != null) { return Ap.ring.getZERO(); } return null; } if (Ap == null || Ap.isZERO()) { return Bp.ring.getZERO(); } if (!Ap.ring.equals(Bp.ring)) { logger.error("rings not equal"); } } Map.Entry ma = Ap.leadingMonomial(); Map.Entry mb = Bp.leadingMonomial(); ExpVector e = ma.getKey(); ExpVector f = mb.getKey(); ExpVector g = e.lcm(f); ExpVector e1 = g.subtract(e); ExpVector f1 = g.subtract(f); C a = ma.getValue(); C b = mb.getValue(); GenSolvablePolynomial App = Ap.multiplyLeft(b, e1); GenSolvablePolynomial Bpp = Bp.multiplyLeft(a, f1); GenSolvablePolynomial Cp = (GenSolvablePolynomial) App.subtract(Bpp); return Cp; } /** * S-Polynomial with recording. * @param S recording matrix, is modified. * @param i index of Ap in basis list. * @param Ap a polynomial. * @param j index of Bp in basis list. * @param Bp a polynomial. * @return leftSpol(Ap, Bp), the left S-Polynomial for Ap and Bp. */ public GenSolvablePolynomial leftSPolynomial(List> S, int i, GenSolvablePolynomial Ap, int j, GenSolvablePolynomial Bp) { if (debug /*logger.isInfoEnabled()*/) { if (Bp == null || Bp.isZERO()) { throw new ArithmeticException("Spol B is zero"); } if (Ap == null || Ap.isZERO()) { throw new ArithmeticException("Spol A is zero"); } if (!Ap.ring.equals(Bp.ring)) { logger.error("rings not equal"); } } Map.Entry ma = Ap.leadingMonomial(); Map.Entry mb = Bp.leadingMonomial(); ExpVector e = ma.getKey(); ExpVector f = mb.getKey(); ExpVector g = e.lcm(f); ExpVector e1 = g.subtract(e); ExpVector f1 = g.subtract(f); C a = ma.getValue(); C b = mb.getValue(); GenSolvablePolynomial App = Ap.multiplyLeft(b, e1); GenSolvablePolynomial Bpp = Bp.multiplyLeft(a, f1); GenSolvablePolynomial Cp = (GenSolvablePolynomial) App.subtract(Bpp); GenSolvablePolynomial zero = Ap.ring.getZERO(); GenSolvablePolynomial As = (GenSolvablePolynomial) zero.sum(b.negate(), e1); GenSolvablePolynomial Bs = (GenSolvablePolynomial) zero.sum(a, f1); S.set(i, As); S.set(j, Bs); return Cp; } /** * Left Normalform Set. * @param Ap solvable polynomial list. * @param Pp solvable polynomial list. * @return list of left-nf(a) with respect to Pp for all a in Ap. */ public List> leftNormalform(List> Pp, List> Ap) { if (Pp == null || Pp.isEmpty()) { return Ap; } if (Ap == null || Ap.isEmpty()) { return Ap; } ArrayList> red = new ArrayList>(); for (GenSolvablePolynomial A : Ap) { A = leftNormalform(Pp, A); red.add(A); } return red; } /** * Left irreducible set. * @param Pp solvable polynomial list. * @return a list P of solvable polynomials which are in normalform wrt. P. */ public List> leftIrreducibleSet(List> Pp) { ArrayList> P = new ArrayList>(); for (GenSolvablePolynomial a : Pp) { if (a.length() != 0) { a = (GenSolvablePolynomial) a.monic(); P.add(a); } } int l = P.size(); if (l <= 1) return P; int irr = 0; ExpVector e; ExpVector f; GenSolvablePolynomial a; Iterator> it; logger.debug("irr = "); while (irr != l) { it = P.listIterator(); a = it.next(); P.remove(0); e = a.leadingExpVector(); a = leftNormalform(P, a); logger.debug(String.valueOf(irr)); if (a.length() == 0) { l--; if (l <= 1) { return P; } } else { f = a.leadingExpVector(); if (f.signum() == 0) { P = new ArrayList>(); P.add((GenSolvablePolynomial) a.monic()); return P; } if (e.equals(f)) { irr++; } else { irr = 0; a = (GenSolvablePolynomial) a.monic(); } P.add(a); } } //System.out.println(); return P; } /** * Is reduction of normal form. * @param row recording matrix. * @param Pp a solvable polynomial list for reduction. * @param Ap a solvable polynomial. * @param Np nf(Pp,Ap), a left normal form of Ap wrt. Pp. * @return true, if Np + sum( row[i]*Pp[i] ) == Ap, else false. */ @SuppressWarnings("unchecked") public boolean isLeftReductionNF(List> row, List> Pp, GenSolvablePolynomial Ap, GenSolvablePolynomial Np) { if (row == null && Pp == null) { if (Ap == null) { return Np == null; } return Ap.equals(Np); } if (row == null || Pp == null) { return false; } if (row.size() != Pp.size()) { return false; } GenSolvablePolynomial t = Np; GenSolvablePolynomial r; GenSolvablePolynomial p; for (int m = 0; m < Pp.size(); m++) { r = row.get(m); p = Pp.get(m); if (r != null && p != null) { if (t == null) { t = r.multiply(p); } else { t = (GenSolvablePolynomial) t.sum(r.multiply(p)); } } //System.out.println("r = " + r ); //System.out.println("p = " + p ); } if (debug) { logger.info("t = " + t); logger.info("a = " + Ap); } if (t == null) { if (Ap == null) { return true; } return Ap.isZERO(); } t = (GenSolvablePolynomial) t.subtract(Ap); return t.isZERO(); } /** * Right S-Polynomial. * @param Ap solvable polynomial. * @param Bp solvable polynomial. * @return right-spol(Ap,Bp) the right S-polynomial of Ap and Bp. */ @SuppressWarnings("unchecked") public GenSolvablePolynomial rightSPolynomial(GenSolvablePolynomial Ap, GenSolvablePolynomial Bp) { if (logger.isInfoEnabled()) { if (Bp == null || Bp.isZERO()) { if (Ap != null) { return Ap.ring.getZERO(); } return null; } if (Ap == null || Ap.isZERO()) { return Bp.ring.getZERO(); } if (!Ap.ring.equals(Bp.ring)) { logger.error("rings not equal"); } } ExpVector e = Ap.leadingExpVector(); ExpVector f = Bp.leadingExpVector(); ExpVector g = e.lcm(f); ExpVector e1 = g.subtract(e); ExpVector f1 = g.subtract(f); GenSolvablePolynomial App = Ap.multiply(e1); GenSolvablePolynomial Bpp = Bp.multiply(f1); C a = App.leadingBaseCoefficient(); C b = Bpp.leadingBaseCoefficient(); App = App.multiply(b); Bpp = Bpp.multiply(a); GenSolvablePolynomial Cp = (GenSolvablePolynomial) App.subtract(Bpp); return Cp; } } jas-2.5/src/edu/jas/gb/GroebnerBaseSeq.java0000644000175000017500000003110012067050600020715 0ustar giovannigiovanni/* * $Id: GroebnerBaseSeq.java 4325 2012-12-27 13:47:44Z kredel $ */ package edu.jas.gb; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import org.apache.log4j.Logger; import edu.jas.structure.RingElem; //import edu.jas.poly.ExpVector; import edu.jas.gb.OrderedPairlist; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; /** * Groebner Base sequential algorithm. * Implements Groebner bases and GB test. * @param coefficient type * @author Heinz Kredel * * @see edu.jas.application.GBAlgorithmBuilder * @see edu.jas.gbufd.GBFactory */ public class GroebnerBaseSeq> extends GroebnerBaseAbstract { private static final Logger logger = Logger.getLogger(GroebnerBaseSeq.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public GroebnerBaseSeq() { super(); } /** * Constructor. * @param red Reduction engine */ public GroebnerBaseSeq(Reduction red) { super(red); } /** * Constructor. * @param pl pair selection strategy */ public GroebnerBaseSeq(PairList pl) { super(pl); } /** * Constructor. * @param red Reduction engine * @param pl pair selection strategy */ public GroebnerBaseSeq(Reduction red, PairList pl) { super(red,pl); } /** * Groebner base using pairlist class. * @param modv module variable number. * @param F polynomial list. * @return GB(F) a Groebner base of F. */ public List> GB( int modv, List> F ) { GenPolynomial p; List> G = new ArrayList>(); PairList pairlist = null; int l = F.size(); ListIterator> it = F.listIterator(); while ( it.hasNext() ) { p = it.next(); if ( p.length() > 0 ) { p = p.monic(); if ( p.isONE() ) { G.clear(); G.add( p ); return G; // since no threads are activated } G.add( p ); if ( pairlist == null ) { //pairlist = new OrderedPairlist( modv, p.ring ); pairlist = strategy.create( modv, p.ring ); if ( ! p.ring.coFac.isField() ) { throw new IllegalArgumentException("coefficients not from a field"); } } // putOne not required pairlist.put( p ); } else { l--; } } if ( l <= 1 ) { return G; // since no threads are activated } logger.info("start " + pairlist); Pair pair; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial H; while ( pairlist.hasNext() ) { pair = pairlist.removeNext(); //logger.debug("pair = " + pair); if ( pair == null ) { continue; } pi = pair.pi; pj = pair.pj; if ( /*false &&*/ debug ) { logger.debug("pi = " + pi ); logger.debug("pj = " + pj ); } S = red.SPolynomial( pi, pj ); if ( S.isZERO() ) { pair.setZero(); continue; } if ( debug ) { logger.debug("ht(S) = " + S.leadingExpVector() ); } H = red.normalform( G, S ); if ( debug ) { //logger.info("pair = " + pair); //logger.info("ht(S) = " + S.monic()); //.leadingExpVector() ); logger.info("ht(H) = " + H.monic()); //.leadingExpVector() ); } if ( H.isZERO() ) { pair.setZero(); continue; } H = H.monic(); if ( debug ) { logger.info("ht(H) = " + H.leadingExpVector() ); } H = H.monic(); if ( H.isONE() ) { G.clear(); G.add( H ); pairlist.putOne(); logger.info("end " + pairlist); return G; // since no threads are activated } if ( debug ) { logger.info("H = " + H ); } if ( H.length() > 0 ) { l++; G.add( H ); pairlist.put( H ); } } logger.debug("#sequential list = " + G.size()); G = minimalGB(G); logger.info("end " + pairlist); return G; } /** * Extended Groebner base using critical pair class. * @param modv module variable number. * @param F polynomial list. * @return a container for an extended Groebner base of F. */ @Override public ExtendedGB extGB( int modv, List> F ) { List> G = new ArrayList>(); List>> F2G = new ArrayList>>(); List>> G2F = new ArrayList>>(); PairList pairlist = null; boolean oneInGB = false; int len = F.size(); List> row = null; List> rows = null; List> rowh = null; GenPolynomialRing ring = null; GenPolynomial H; GenPolynomial p; int nzlen = 0; for ( GenPolynomial f : F ) { if ( f.length() > 0 ) { nzlen++; } if ( ring == null ) { ring = f.ring; } } GenPolynomial mone = ring.getONE(); //.negate(); int k = 0; ListIterator> it = F.listIterator(); while ( it.hasNext() ) { p = it.next(); if ( p.length() > 0 ) { row = new ArrayList>( nzlen ); for ( int j = 0; j < nzlen; j++ ) { row.add(null); } //C c = p.leadingBaseCoefficient(); //c = c.inverse(); //p = p.multiply( c ); row.set( k, mone ); //.multiply(c) ); k++; if ( p.isUnit() ) { G.clear(); G.add( p ); G2F.clear(); G2F.add( row ); oneInGB = true; break; } G.add( p ); G2F.add( row ); if ( pairlist == null ) { //pairlist = new OrderedPairlist( modv, p.ring ); pairlist = strategy.create( modv, p.ring ); if ( ! p.ring.coFac.isField() ) { throw new RuntimeException("coefficients not from a field"); } } // putOne not required pairlist.put( p ); } else { len--; } } ExtendedGB exgb; if ( len <= 1 || oneInGB ) { // adjust F2G for ( GenPolynomial f : F ) { row = new ArrayList>( G.size() ); for ( int j = 0; j < G.size(); j++ ) { row.add(null); } H = red.normalform( row, G, f ); if ( ! H.isZERO() ) { logger.error("nonzero H = " + H ); } F2G.add( row ); } exgb = new ExtendedGB(F,G,F2G,G2F); //System.out.println("exgb 1 = " + exgb); return exgb; } Pair pair; int i, j; GenPolynomial pi; GenPolynomial pj; GenPolynomial S; GenPolynomial x; GenPolynomial y; //GenPolynomial z; while ( pairlist.hasNext() && ! oneInGB ) { pair = pairlist.removeNext(); if ( pair == null ) { continue; } i = pair.i; j = pair.j; pi = pair.pi; pj = pair.pj; if ( debug ) { logger.info("i, pi = " + i + ", " + pi ); logger.info("j, pj = " + j + ", " + pj ); } rows = new ArrayList>( G.size() ); for ( int m = 0; m < G.size(); m++ ) { rows.add(null); } S = red.SPolynomial( rows, i, pi, j, pj ); if ( debug ) { logger.debug("is reduction S = " + red.isReductionNF( rows, G, ring.getZERO(), S ) ); } if ( S.isZERO() ) { // do not add to G2F continue; } if ( debug ) { logger.debug("ht(S) = " + S.leadingExpVector() ); } rowh = new ArrayList>( G.size() ); for ( int m = 0; m < G.size(); m++ ) { rowh.add(null); } H = red.normalform( rowh, G, S ); if ( debug ) { logger.debug("is reduction H = " + red.isReductionNF( rowh, G, S, H ) ); } if ( H.isZERO() ) { // do not add to G2F continue; } if ( debug ) { logger.debug("ht(H) = " + H.leadingExpVector() ); } row = new ArrayList>( G.size()+1 ); for ( int m = 0; m < G.size(); m++ ) { x = rows.get(m); if ( x != null ) { //System.out.println("ms = " + m + " " + x); x = x.negate(); } y = rowh.get(m); if ( y != null ) { y = y.negate(); //System.out.println("mh = " + m + " " + y); } if ( x == null ) { x = y; } else { x = x.sum( y ); } //System.out.println("mx = " + m + " " + x); row.add( x ); } if ( debug ) { logger.debug("is reduction 0+sum(row,G) == H : " + red.isReductionNF( row, G, H, ring.getZERO() ) ); } row.add( null ); // H = H.monic(); C c = H.leadingBaseCoefficient(); c = c.inverse(); H = H.multiply( c ); row = blas.scalarProduct( mone.multiply(c), row ); row.set( G.size(), mone ); if ( H.isONE() ) { // G.clear(); G.add( H ); G2F.add( row ); oneInGB = true; break; } if ( debug ) { logger.debug("H = " + H ); } G.add( H ); pairlist.put( H ); G2F.add( row ); } if ( debug ) { exgb = new ExtendedGB(F,G,F2G,G2F); logger.info("exgb unnorm = " + exgb); } G2F = normalizeMatrix( F.size(), G2F ); if ( debug ) { exgb = new ExtendedGB(F,G,F2G,G2F); logger.info("exgb nonmin = " + exgb); boolean t2 = isReductionMatrix( exgb ); logger.info("exgb t2 = " + t2); } exgb = minimalExtendedGB(F.size(),G,G2F); G = exgb.G; G2F = exgb.G2F; logger.debug("#sequential list = " + G.size()); logger.info("" + pairlist); // setup matrices F and F2G for ( GenPolynomial f : F ) { row = new ArrayList>( G.size() ); for ( int m = 0; m < G.size(); m++ ) { row.add(null); } H = red.normalform( row, G, f ); if ( ! H.isZERO() ) { logger.error("nonzero H = " + H ); } F2G.add( row ); } exgb = new ExtendedGB(F,G,F2G,G2F); if ( debug ) { logger.info("exgb nonmin = " + exgb); boolean t2 = isReductionMatrix( exgb ); logger.info("exgb t2 = " + t2); } return exgb; } } jas-2.5/src/edu/jas/gb/GBTransportMess.java0000644000175000017500000000631412067303544020764 0ustar giovannigiovanni/* * $Id: GBTransportMess.java 4334 2012-12-28 11:49:57Z kredel $ */ package edu.jas.gb; import java.io.Serializable; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Distributed GB transport message. This class and its subclasses * are used for transport of polynomials and pairs and as markers in * distributed GB algorithms. */ public class GBTransportMess implements Serializable { public GBTransportMess() { } /** * toString. */ @Override public String toString() { return this.getClass().getName(); } } /** * Distributed GB transport message for requests. */ final class GBTransportMessReq extends GBTransportMess { public GBTransportMessReq() { } } /** * Distributed GB transport message for termination. */ final class GBTransportMessEnd extends GBTransportMess { public GBTransportMessEnd() { } } /** * Distributed GB transport message for polynomial. */ final class GBTransportMessPoly> extends GBTransportMess { /** * The polynomial to transport. */ public final GenPolynomial pol; /** * GBTransportMessPoly. * @param p polynomial to transfered. */ public GBTransportMessPoly(GenPolynomial p) { this.pol = p; } /** * toString. */ @Override public String toString() { return super.toString() + "( " + pol + " )"; } } /** * Distributed GB transport message for pairs. */ final class GBTransportMessPair> extends GBTransportMess { public final Pair pair; /** * GBTransportMessPair. * @param p pair for transfer. */ public GBTransportMessPair(Pair p) { this.pair = p; } /** * toString. */ @Override public String toString() { return super.toString() + "( " + pair + " )"; } } /** * Distributed GB transport message for index pairs. */ final class GBTransportMessPairIndex extends GBTransportMess { public final int i; public final int j; public final int s; /** * GBTransportMessPairIndex. * @param p pair for transport. */ public GBTransportMessPairIndex(Pair p) { this(p.i,p.j,p.s); } /** * GBTransportMessPairIndex. * @param i first index. * @param j second index. */ @Deprecated public GBTransportMessPairIndex(int i, int j) { this(i,j,0); } /** * GBTransportMessPairIndex. * @param i first index. * @param j second index. * @param s maximal index. */ public GBTransportMessPairIndex(int i, int j, int s) { this.i = i; this.j = j; s = Math.max(this.i,s); s = Math.max(this.j,s); this.s = s; } /** * GBTransportMessPairIndex. * @param i first index. * @param j second index. * @param s maximal index. */ public GBTransportMessPairIndex(Integer i, Integer j, Integer s) { this(i.intValue(),j.intValue(),s.intValue()); } /** * toString. */ @Override public String toString() { return super.toString() + "( " + i + "," + j + "," + s + ")"; } } jas-2.5/src/edu/jas/gb/Reduction.java0000644000175000017500000001335512045171432017661 0ustar giovannigiovanni/* * $Id: Reduction.java 4279 2012-11-03 10:34:03Z kredel $ */ package edu.jas.gb; import java.util.List; import java.io.Serializable; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.structure.RingElem; /** * Polynomial Reduction interface. * Defines S-Polynomial, normalform, criterion 4, module criterion * and irreducible set. * @param coefficient type * @author Heinz Kredel */ public interface Reduction> extends Serializable { /** * S-Polynomial. * @param Ap polynomial. * @param Bp polynomial. * @return spol(Ap,Bp) the S-polynomial of Ap and Bp. */ public GenPolynomial SPolynomial(GenPolynomial Ap, GenPolynomial Bp); /** * S-Polynomial with recording. * @param S recording matrix, is modified. * @param i index of Ap in basis list. * @param Ap a polynomial. * @param j index of Bp in basis list. * @param Bp a polynomial. * @return Spol(Ap, Bp), the S-Polynomial for Ap and Bp. */ public GenPolynomial SPolynomial(List> S, int i, GenPolynomial Ap, int j, GenPolynomial Bp); /** * Module criterium. * @param modv number of module variables. * @param A polynomial. * @param B polynomial. * @return true if the module S-polynomial(i,j) is required. */ public boolean moduleCriterion(int modv, GenPolynomial A, GenPolynomial B); /** * Module criterium. * @param modv number of module variables. * @param ei ExpVector. * @param ej ExpVector. * @return true if the module S-polynomial(i,j) is required. */ public boolean moduleCriterion(int modv, ExpVector ei, ExpVector ej); /** * GB criterium 4. * Use only for commutative polynomial rings. * @param A polynomial. * @param B polynomial. * @param e = lcm(ht(A),ht(B)) * @return true if the S-polynomial(i,j) is required, else false. */ public boolean criterion4(GenPolynomial A, GenPolynomial B, ExpVector e); /** * GB criterium 4. * Use only for commutative polynomial rings. * @param A polynomial. * @param B polynomial. * @return true if the S-polynomial(i,j) is required, else false. */ public boolean criterion4(GenPolynomial A, GenPolynomial B); /** * GB criterium 4. * @param ei exponent vector. * @param ej exponent vector. * @param e = lcm(ei,ej) * @return true if the S-polynomial(i,j) is required, else false. */ public boolean criterion4(ExpVector ei, ExpVector ej, ExpVector e); /** * Is top reducible. * Condition is lt(B) | lt(A) for some B in F. * @param A polynomial. * @param P polynomial list. * @return true if A is top reducible with respect to P. */ public boolean isTopReducible(List> P, GenPolynomial A); /** * Is reducible. * @param A polynomial. * @param P polynomial list. * @return true if A is reducible with respect to P. */ public boolean isReducible(List> P, GenPolynomial A); /** * Is in Normalform. * @param A polynomial. * @param P polynomial list. * @return true if A is in normalform with respect to P. */ public boolean isNormalform(List> P, GenPolynomial A); /** * Is in Normalform. * @param Pp polynomial list. * @return true if each A in Pp is in normalform with respect to Pp\{A}. */ public boolean isNormalform( List> Pp ); /** * Normalform. * @param A polynomial. * @param P polynomial list. * @return nf(A) with respect to P. */ public GenPolynomial normalform(List> P, GenPolynomial A); /** * Normalform Set. * @param Ap polynomial list. * @param Pp polynomial list. * @return list of nf(a) with respect to Pp for all a in Ap. */ public List> normalform(List> Pp, List> Ap); /** * Normalform with recording. * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. */ public GenPolynomial normalform(List> row, List> Pp, GenPolynomial Ap); /** * Irreducible set. * @param Pp polynomial list. * @return a list P of polynomials which are in normalform wrt. P and with ideal(Pp) = ideal(P). */ public List> irreducibleSet(List> Pp); /** * Is reduction of normal form. * @param row recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @param Np nf(Pp,Ap), a normal form of Ap wrt. Pp. * @return true, if Np + sum( row[i]*Pp[i] ) == Ap, else false. */ public boolean isReductionNF(List> row, List> Pp, GenPolynomial Ap, GenPolynomial Np); } jas-2.5/src/edu/jas/gb/WordReduction.java0000644000175000017500000001073712020347402020511 0ustar giovannigiovanni/* * $Id: WordReduction.java 4149 2012-09-01 09:01:54Z kredel $ */ package edu.jas.gb; import java.util.List; import java.io.Serializable; import edu.jas.poly.Word; import edu.jas.poly.GenWordPolynomial; import edu.jas.structure.RingElem; /** * Polynomial WordReduction interface. * Defines S-Polynomial, normalform, module criterion * and irreducible set. * @param coefficient type * @author Heinz Kredel */ public interface WordReduction> extends Serializable { /** * S-Polynomials of non-commutative polynomials. * @param Ap word polynomial. * @param Bp word polynomial. * @return list of all spol(Ap,Bp) the S-polynomials of Ap and Bp. */ public List> SPolynomials(GenWordPolynomial Ap, GenWordPolynomial Bp); /** * S-Polynomials of non-commutative polynomials. * @param a leading base coefficient of B. * @param l1 word. * @param A word polynomial. * @param r1 word. * @param b leading base coefficient of A. * @param l2 word. * @param B word polynomial. * @param r2 word. * @return list of all spol(Ap,Bp) the S-polynomials of Ap and Bp. */ public GenWordPolynomial SPolynomial(C a, Word l1, GenWordPolynomial A, Word r1, C b, Word l2, GenWordPolynomial B, Word r2); /** * Is top reducible. * Condition is lt(B) | lt(A) for some B in F. * @param A polynomial. * @param P polynomial list. * @return true if A is top reducible with respect to P. */ public boolean isTopReducible(List> P, GenWordPolynomial A); /** * Is reducible. * @param A polynomial. * @param P polynomial list. * @return true if A is reducible with respect to P. */ public boolean isReducible(List> P, GenWordPolynomial A); /** * Is in Normalform. * @param A polynomial. * @param P polynomial list. * @return true if A is in normalform with respect to P. */ public boolean isNormalform(List> P, GenWordPolynomial A); /** * Is in Normalform. * @param Pp polynomial list. * @return true if each A in Pp is in normalform with respect to Pp\{A}. */ public boolean isNormalform( List> Pp ); /** * Normalform. * @param A polynomial. * @param P polynomial list. * @return nf(A) with respect to P. */ public GenWordPolynomial normalform(List> P, GenWordPolynomial A); /** * Normalform Set. * @param Ap polynomial list. * @param Pp polynomial list. * @return list of nf(a) with respect to Pp for all a in Ap. */ public List> normalform(List> Pp, List> Ap); /** * Normalform with left and right recording. * @param lrow left recording matrix, is modified. * @param rrow right recording matrix, is modified. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. */ public GenWordPolynomial normalform(List> lrow, List> rrow, List> Pp, GenWordPolynomial Ap); /** * Irreducible set. * @param Pp polynomial list. * @return a list P of polynomials which are in normalform wrt. P and with ideal(Pp) = ideal(P). */ public List> irreducibleSet(List> Pp); /** * Is reduction of normal form. * @param lrow left recording matrix. * @param rrow right recording matrix. * @param Pp a polynomial list for reduction. * @param Ap a polynomial. * @param Np nf(Pp,Ap), a normal form of Ap wrt. Pp. * @return true, if Np + sum( row[i]*Pp[i] ) == Ap, else false. */ public boolean isReductionNF(List> lrow, List> rrow, List> Pp, GenWordPolynomial Ap, GenWordPolynomial Np); } jas-2.5/src/edu/jas/poly/0000755000175000017500000000000012140140260015435 5ustar giovannigiovannijas-2.5/src/edu/jas/poly/TermOrder.java0000644000175000017500000014543212137036770020234 0ustar giovannigiovanni/* * $Id: TermOrder.java 4389 2013-04-27 21:07:05Z kredel $ */ package edu.jas.poly; import java.io.Serializable; import java.util.Arrays; import java.util.Comparator; import org.apache.log4j.Logger; /** * Term order class for ordered polynomials. Implements the most used term * orders: graded, lexicographical, weight aray and block orders. For the * definitions see for example the articles Kredel, * "Admissible term orderings used in computer algebra systems" and Sit, * "Some comments on term-ordering in Gröbner basis computations". * Note: the naming is not quite easy to understand: in case of doubt * use the term orders with "I" in the name, like IGRLEX (the default) or * INVLEX. Not all algorithms may work with all term orders, so watch your step. * This class does not jet implement orders by linear forms over Q[t]. Objects * of this class are immutable. * * @author Heinz Kredel */ public final class TermOrder implements Serializable { public static final int LEX = 1; public static final int INVLEX = 2; public static final int GRLEX = 3; public static final int IGRLEX = 4; public static final int REVLEX = 5; public static final int REVILEX = 6; public static final int REVTDEG = 7; public static final int REVITDG = 8; public final static int DEFAULT_EVORD = IGRLEX; //public final static int DEFAULT_EVORD = INVLEX; private final int evord; // for split termorders private final int evord2; private final int evbeg1; private final int evend1; private final int evbeg2; private final int evend2; private static final Logger logger = Logger.getLogger(TermOrder.class); private final boolean debug = logger.isDebugEnabled(); /** * Defined array of weight vectors. */ private final long[][] weight; /** * Defined descending order comparator. Sorts the highest terms first. */ private final EVComparator horder; /** * Defined ascending order comparator. Sorts the lowest terms first. */ private final EVComparator lorder; /** * Defined sugar order comparator. Sorts the graded lowest terms first. */ private final EVComparator sugar; /** * Comparator for ExpVectors. */ public static abstract class EVComparator implements Comparator, Serializable { public abstract int compare(ExpVector e1, ExpVector e2); } /** * Constructor for default term order. */ public TermOrder() { this(DEFAULT_EVORD); } /** * Constructor for given term order. * @param evord requested term order indicator / enumerator. */ public TermOrder(int evord) { if (evord < LEX || REVITDG < evord) { throw new IllegalArgumentException("invalid term order: " + evord); } this.evord = evord; this.evord2 = 0; weight = null; evbeg1 = 0; evend1 = Integer.MAX_VALUE; evbeg2 = evend1; evend2 = evend1; switch (evord) { // horder = new EVhorder(); case TermOrder.LEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return ExpVector.EVILCP(e1, e2); } }; break; } case TermOrder.INVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return -ExpVector.EVILCP(e1, e2); } }; break; } case TermOrder.GRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return ExpVector.EVIGLC(e1, e2); } }; break; } case TermOrder.IGRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return -ExpVector.EVIGLC(e1, e2); } }; break; } case TermOrder.REVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return ExpVector.EVRILCP(e1, e2); } }; break; } case TermOrder.REVILEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return -ExpVector.EVRILCP(e1, e2); } }; break; } case TermOrder.REVTDEG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return ExpVector.EVRIGLC(e1, e2); } }; break; } case TermOrder.REVITDG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return -ExpVector.EVRIGLC(e1, e2); } }; break; } default: { horder = null; } } if (horder == null) { throw new IllegalArgumentException("invalid term order: " + evord); } // lorder = new EVlorder(); lorder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return -horder.compare(e1, e2); } }; // sugar = new EVsugar(); sugar = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return ExpVector.EVIGLC(e1, e2); } }; } /** * Constructor for given exponent weights. * @param w weight vector of longs. */ public TermOrder(long[] w) { this(new long[][] { w }); } /** * Constructor for given exponent weights. * @param w weight array of longs. */ public TermOrder(long[][] w) { if (w == null || w.length == 0) { throw new IllegalArgumentException("invalid term order weight"); } weight = w; this.evord = 0; this.evord2 = 0; evbeg1 = 0; evend1 = weight[0].length; evbeg2 = evend1; evend2 = evend1; horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return -ExpVector.EVIWLC(weight, e1, e2); } }; // lorder = new EVlorder(); lorder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return +ExpVector.EVIWLC(weight, e1, e2); // return - horder.compare( e1, e2 ); } }; // sugar = new EVsugar(); sugar = horder; } /** * Constructor for default split order. * @param r max number of exponents to compare. * @param split index. */ public TermOrder(int r, int split) { this(DEFAULT_EVORD, DEFAULT_EVORD, r, split); } /** * Constructor for given split order. * @param ev1 requested term order indicator for first block. * @param ev2 requested term order indicator for second block. * @param r max number of exponents to compare. * @param split index. */ public TermOrder(int ev1, int ev2, int r, int split) { if (ev1 < LEX || REVITDG < ev1) { throw new IllegalArgumentException("invalid term order: " + ev1); } if (ev2 < LEX || REVITDG < ev2) { throw new IllegalArgumentException("invalid term order: " + ev2); } this.evord = ev1; this.evord2 = ev2; weight = null; evbeg1 = 0; evend1 = split; // excluded evbeg2 = split; evend2 = r; if (evbeg2 > evend2) { throw new IllegalArgumentException("invalid term order split, r = " + r + ", split = " + split); } switch (evord) { // horder = new EVhorder(); case TermOrder.LEX: { switch (evord2) { case TermOrder.LEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.INVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.GRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.IGRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } default: { horder = null; } } break; } case TermOrder.INVLEX: { switch (evord2) { case TermOrder.LEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.INVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.GRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.IGRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVILEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVTDEG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVITDG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } default: { horder = null; } } break; } case TermOrder.GRLEX: { switch (evord2) { case TermOrder.LEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.INVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.GRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.IGRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } default: { horder = null; } } break; } case TermOrder.IGRLEX: { switch (evord2) { case TermOrder.LEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.INVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.GRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.IGRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVILEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVTDEG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVITDG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } default: { horder = null; } } break; } //----- begin reversed ----------- case TermOrder.REVLEX: { switch (evord2) { case TermOrder.LEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.INVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.GRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.IGRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVILEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVTDEG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVITDG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } default: { horder = null; } } break; } case TermOrder.REVILEX: { switch (evord2) { case TermOrder.LEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.INVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.GRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.IGRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVILEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVTDEG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVITDG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRILCP(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } default: { horder = null; } } break; } case TermOrder.REVTDEG: { switch (evord2) { case TermOrder.LEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.INVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.GRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.IGRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVILEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVTDEG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVITDG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } default: { horder = null; } } break; } case TermOrder.REVITDG: { switch (evord2) { case TermOrder.LEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.INVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.GRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.IGRLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVLEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVILEX: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRILCP(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVTDEG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } case TermOrder.REVITDG: { horder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { int t = -ExpVector.EVRIGLC(e1, e2, evbeg1, evend1); if (t != 0) { return t; } return -ExpVector.EVRIGLC(e1, e2, evbeg2, evend2); } }; break; } default: { horder = null; } } break; } //----- end reversed----------- default: { horder = null; } } if (horder == null) { throw new IllegalArgumentException("invalid term order: " + evord + " 2 " + evord2); } lorder = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return -horder.compare(e1, e2); } }; // sugar = new EVsugar(); sugar = new EVComparator() { @Override public int compare(ExpVector e1, ExpVector e2) { return ExpVector.EVIGLC(e1, e2); } }; } /** * Get the first defined order indicator. * @return evord. */ public int getEvord() { return evord; } /** * Get the second defined order indicator. * @return evord2. */ public int getEvord2() { return evord2; } /** * Get the split index. * @return split. */ public int getSplit() { return evend1; // = evbeg2 } /** * Get the weight array. * @return weight. */ public long[][] getWeight() { return weight; } /** * Get the descending order comparator. Sorts the highest terms first. * @return horder. */ public EVComparator getDescendComparator() { return horder; } /** * Get the ascending order comparator. Sorts the lowest terms first. * @return lorder. */ public EVComparator getAscendComparator() { return lorder; } /** * Get the sugar order comparator. Sorts the graded lowest terms first. * @return sugar. */ public EVComparator getSugarComparator() { return sugar; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof TermOrder)) { return false; } TermOrder b = (TermOrder) B; boolean t = evord == b.getEvord() && evord2 == b.evord2 && evbeg1 == b.evbeg1 && evend1 == b.evend1 && evbeg2 == b.evbeg2 && evend2 == b.evend2; if (!t) { return t; } if (!Arrays.equals(weight, b.weight)) { return false; } return true; } /** * Hash code. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = evord; h = (h << 3) + evord2; h = (h << 4) + evbeg1; h = (h << 4) + evend1; h = (h << 4) + evbeg2; h = (h << 4) + evend2; if (weight == null) { return h; } h = h * 7 + Arrays.deepHashCode(weight); return h; } /** * String representation of weight vector. * @see java.lang.Object#toString() */ public String weightToString() { StringBuffer erg = new StringBuffer(); if (weight != null) { erg.append("weight("); for (int j = 0; j < weight.length; j++) { long[] wj = weight[j]; erg.append("("); for (int i = 0; i < wj.length; i++) { erg.append("" + wj[wj.length - i - 1]); if (i < wj.length - 1) { erg.append(","); } } erg.append(")"); if (j < weight.length - 1) { erg.append(","); } } erg.append(")"); } return erg.toString(); } /** * String representation of TermOrder. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer erg = new StringBuffer(); if (weight != null) { erg.append("W("); for (int j = 0; j < weight.length; j++) { long[] wj = weight[j]; erg.append("("); for (int i = 0; i < wj.length; i++) { erg.append("" + wj[wj.length - i - 1]); if (i < wj.length - 1) { erg.append(","); } } erg.append(")"); if (j < weight.length - 1) { erg.append(","); } } erg.append(")"); if (evend1 == evend2) { return erg.toString(); } erg.append("[" + evbeg1 + "," + evend1 + "]"); erg.append("[" + evbeg2 + "," + evend2 + "]"); return erg.toString(); } switch (evord) { case LEX: erg.append("LEX"); break; case INVLEX: erg.append("INVLEX"); break; case GRLEX: erg.append("GRLEX"); break; case IGRLEX: erg.append("IGRLEX"); break; case REVLEX: erg.append("REVLEX"); break; case REVILEX: erg.append("REVILEX"); break; case REVTDEG: erg.append("REVTDEG"); break; case REVITDG: erg.append("REVITDG"); break; default: erg.append("invalid(" + evord + ")"); break; } if (evord2 <= 0) { return erg.toString(); } erg.append("[" + evbeg1 + "," + evend1 + "]"); switch (evord2) { case LEX: erg.append("LEX"); break; case INVLEX: erg.append("INVLEX"); break; case GRLEX: erg.append("GRLEX"); break; case IGRLEX: erg.append("IGRLEX"); break; case REVLEX: erg.append("REVLEX"); break; case REVILEX: erg.append("REVILEX"); break; case REVTDEG: erg.append("REVTDEG"); break; case REVITDG: erg.append("REVITDG"); break; default: erg.append("invalid(" + evord2 + ")"); break; } erg.append("[" + evbeg2 + "," + evend2 + "]"); return erg.toString(); } /** * Extend variables. Used e.g. in module embedding. Extend TermOrder by k * elements. Note: todo distinguish TOP and POT orders. * @param r current number of variables. * @param k number of variables to extend. * @return extended TermOrder. */ public TermOrder extend(int r, int k) { if (weight != null) { long[][] w = new long[weight.length][]; for (int i = 0; i < weight.length; i++) { long[] wi = weight[i]; long max = 0; // long min = Long.MAX_VALUE; for (int j = 0; j < wi.length; j++) { if (wi[j] > max) max = wi[j]; //if ( wi[j] < min ) min = wi[j]; } max++; long[] wj = new long[wi.length + k]; for (int j = 0; j < i; j++) { wj[j] = max; } System.arraycopy(wi, 0, wj, i, wi.length); w[i] = wj; } return new TermOrder(w); } if (evord2 != 0) { logger.debug("warn: TermOrder is already extended"); if (debug) { throw new IllegalArgumentException("TermOrder is already extended: " + this); } return new TermOrder(evord, evord2, r + k, evend1 + k); } //System.out.println("evord = " + evord); //System.out.println("DEFAULT_EVORD = " + DEFAULT_EVORD); //System.out.println("tord = " + this); return new TermOrder(DEFAULT_EVORD/*evord*/, evord, r + k, k); // don't change to evord, cause REVITDG } /** * Extend lower variables. Extend TermOrder by k elements. Note: todo * distinguish TOP and POT orders. * @param r current number of variables. * @param k number of variables to extend. * @return extended TermOrder. */ public TermOrder extendLower(int r, int k) { if (weight != null) { long[][] w = new long[weight.length][]; for (int i = 0; i < weight.length; i++) { long[] wi = weight[i]; //long max = 0; long min = Long.MAX_VALUE; for (int j = 0; j < wi.length; j++) { //if ( wi[j] > max ) max = wi[j]; if (wi[j] < min) min = wi[j]; } //max++; long[] wj = new long[wi.length + k]; for (int j = 0; j < i; j++) { wj[wi.length + j] = min; } System.arraycopy(wi, 0, wj, 0, wi.length); w[i] = wj; } return new TermOrder(w); } if (evord2 != 0) { if (debug) { logger.warn("TermOrder is already extended"); } return new TermOrder(evord, evord2, r + k, evend1 + k); } //System.out.println("evord = " + evord); //System.out.println("DEFAULT_EVORD = " + DEFAULT_EVORD); //System.out.println("tord = " + this); return new TermOrder(evord); } /** * Contract variables. Used e.g. in module embedding. Contract TermOrder to * non split status. * @param k position of first element to be copied. * @param len new length. * @return contracted TermOrder. */ public TermOrder contract(int k, int len) { if (weight != null) { long[][] w = new long[weight.length][]; for (int i = 0; i < weight.length; i++) { long[] wi = weight[i]; long[] wj = new long[len]; System.arraycopy(wi, k, wj, 0, len); w[i] = wj; } return new TermOrder(w); } if (evord2 == 0) { if (debug) { logger.warn("TermOrder is already contracted"); } return new TermOrder(evord); } if (evend1 > k) { // < IntMax since evord2 != 0 int el = evend1 - k; while (el > len) { el -= len; } if (el == 0L) { return new TermOrder(evord); } if (el == len) { return new TermOrder(evord); } return new TermOrder(evord, evord2, len, el); } return new TermOrder(evord2); } /** * Reverse variables. Used e.g. in opposite rings. * @return TermOrder for reversed variables. */ public TermOrder reverse() { return reverse(false); } /** * Reverse variables. Used e.g. in opposite rings. * @param partial true for partialy reversed term orders. * @return TermOrder for reversed variables. */ public TermOrder reverse(boolean partial) { TermOrder t; if (weight != null) { if (partial) { logger.error("partial reversed weight order not implemented"); } long[][] w = new long[weight.length][]; for (int i = 0; i < weight.length; i++) { long[] wi = weight[i]; long[] wj = new long[wi.length]; for (int j = 0; j < wj.length; j++) { wj[j] = wi[wj.length - 1 - j]; } w[i] = wj; } t = new TermOrder(w); logger.info("new TO = " + t); return t; } if (evord2 == 0) { t = new TermOrder(revert(evord)); return t; } if (partial) { t = new TermOrder(revert(evord), revert(evord2), evend2, evend1); } else { t = new TermOrder(revert(evord2), revert(evord), evend2, evend2 - evbeg2); } logger.info("new TO = " + t); return t; } /** * Revert exponent order. Used e.g. in opposite rings. * @param evord exponent order to be reverted. * @return reverted exponent order. */ public static int revert(int evord) { int i = evord; switch (evord) { case LEX: i = REVLEX; break; case INVLEX: i = REVILEX; break; case GRLEX: i = REVTDEG; break; case IGRLEX: i = REVITDG; break; case REVLEX: i = LEX; break; case REVILEX: i = INVLEX; break; case REVTDEG: i = GRLEX; break; case REVITDG: i = IGRLEX; break; default: logger.error("can not revert " + evord); break; } return i; } } jas-2.5/src/edu/jas/poly/GenSolvablePolynomialRing.java0000644000175000017500000005003112137024450023374 0ustar giovannigiovanni/* * $Id: GenSolvablePolynomialRing.java 4388 2013-04-27 19:38:16Z kredel $ */ package edu.jas.poly; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.PrettyPrint; import edu.jas.kern.Scripting; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * GenSolvablePolynomialRing generic solvable polynomial factory implementing * RingFactory and extending GenPolynomialRing factory; Factory for n-variate * ordered solvable polynomials over C. The non-commutative multiplication * relations are maintained in a relation table. Almost immutable object, except * variable names and relation table contents. * @param coefficient type. * @author Heinz Kredel */ public class GenSolvablePolynomialRing> extends GenPolynomialRing { // implements RingFactory< GenSolvablePolynomial > { /** * The solvable multiplication relations. */ public final RelationTable table; /** * The constant polynomial 0 for this ring. Hides super ZERO. */ public final GenSolvablePolynomial ZERO; /** * The constant polynomial 1 for this ring. Hides super ONE. */ public final GenSolvablePolynomial ONE; private static final Logger logger = Logger.getLogger(GenSolvablePolynomialRing.class); private final boolean debug = logger.isDebugEnabled(); /** * The constructor creates a solvable polynomial factory object with the * default term order and commutative relations. * @param cf factory for coefficients of type C. * @param n number of variables. */ public GenSolvablePolynomialRing(RingFactory cf, int n) { this(cf, n, new TermOrder(), null, null); } /** * The constructor creates a solvable polynomial factory object with the * default term order. * @param cf factory for coefficients of type C. * @param n number of variables. * @param rt solvable multiplication relations. */ public GenSolvablePolynomialRing(RingFactory cf, int n, RelationTable rt) { this(cf, n, new TermOrder(), null, rt); } /** * The constructor creates a solvable polynomial factory object with the * given term order and commutative relations. * @param cf factory for coefficients of type C. * @param n number of variables. * @param t a term order. */ public GenSolvablePolynomialRing(RingFactory cf, int n, TermOrder t) { this(cf, n, t, null, null); } /** * The constructor creates a solvable polynomial factory object with the * given term order. * @param cf factory for coefficients of type C. * @param n number of variables. * @param t a term order. * @param rt solvable multiplication relations. */ public GenSolvablePolynomialRing(RingFactory cf, int n, TermOrder t, RelationTable rt) { this(cf, n, t, null, rt); } /** * The constructor creates a solvable polynomial factory object with the * given term order and commutative relations. * @param cf factory for coefficients of type C. * @param n number of variables. * @param t a term order. * @param v names for the variables. */ public GenSolvablePolynomialRing(RingFactory cf, int n, TermOrder t, String[] v) { this(cf, n, t, v, null); } /** * The constructor creates a solvable polynomial factory object with the * given term order and commutative relations. * @param cf factory for coefficients of type C. * @param t a term order. * @param v names for the variables. */ public GenSolvablePolynomialRing(RingFactory cf, TermOrder t, String[] v) { this(cf, v.length, t, v, null); } /** * The constructor creates a solvable polynomial factory object with the * default term order. * @param cf factory for coefficients of type C. * @param v names for the variables. */ public GenSolvablePolynomialRing(RingFactory cf, String[] v) { this(cf, v.length, new TermOrder(), v, null); } /** * The constructor creates a solvable polynomial factory object with the * given term order. * @param cf factory for coefficients of type C. * @param n number of variables. * @param t a term order. * @param v names for the variables. * @param rt solvable multiplication relations. */ public GenSolvablePolynomialRing(RingFactory cf, int n, TermOrder t, String[] v, RelationTable rt) { super(cf, n, t, v); if (rt == null) { table = new RelationTable(this); } else { table = rt; } ZERO = new GenSolvablePolynomial(this); C coeff = coFac.getONE(); //evzero = ExpVector.create(nvar); // from super ONE = new GenSolvablePolynomial(this, coeff, evzero); } /** * The constructor creates a solvable polynomial factory object with the the * same term order, number of variables and variable names as the given * polynomial factory, only the coefficient factories differ and the * solvable multiplication relations are empty. * @param cf factory for coefficients of type C. * @param o other solvable polynomial ring. */ public GenSolvablePolynomialRing(RingFactory cf, GenSolvablePolynomialRing o) { this(cf, o.nvar, o.tord, o.getVars(), null); } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { String res = super.toString(); if (PrettyPrint.isTrue()) { res += "\n" + table.toString(vars); } else { res += ", #rel = " + table.size(); } return res; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ @Override public String toScript() { StringBuffer s = new StringBuffer(); switch (Scripting.getLang()) { case Ruby: s.append("SolvPolyRing.new("); break; case Python: default: s.append("SolvPolyRing("); } if (coFac instanceof RingElem) { s.append(((RingElem) coFac).toScriptFactory()); } else { s.append(coFac.toScript().trim()); } s.append(",\"" + varsToString() + "\","); String to = tord.toString(); if (tord.getEvord() == TermOrder.INVLEX) { to = "PolyRing.lex"; } if (tord.getEvord() == TermOrder.IGRLEX) { to = "PolyRing.grad"; } s.append(to); if (table.size() > 0) { String rel = table.toScript(); s.append(",rel="); s.append(rel); } s.append(")"); return s.toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object other) { if (!(other instanceof GenSolvablePolynomialRing)) { return false; } // do a super.equals( ) if (!super.equals(other)) { return false; } GenSolvablePolynomialRing oring = null; try { oring = (GenSolvablePolynomialRing) other; } catch (ClassCastException ignored) { } if (oring == null) { return false; } // @todo check same base relations //if ( ! table.equals(oring.table) ) { // return false; //} return true; } /** * Hash code for this polynomial ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = super.hashCode(); h = 37 * h + table.hashCode(); return h; } /** * Get the zero element. * @return 0 as GenSolvablePolynomial. */ @Override public GenSolvablePolynomial getZERO() { return ZERO; } /** * Get the one element. * @return 1 as GenSolvablePolynomial. */ @Override public GenSolvablePolynomial getONE() { return ONE; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ @Override public boolean isCommutative() { if (table.size() == 0) { return super.isCommutative(); } // todo: check structure of relations return false; } /** * Query if this ring is associative. Test if the relations define an * associative solvable ring. * @return true, if this ring is associative, else false. */ @Override public boolean isAssociative() { GenSolvablePolynomial Xi; GenSolvablePolynomial Xj; GenSolvablePolynomial Xk; GenSolvablePolynomial p; GenSolvablePolynomial q; for (int i = 0; i < nvar; i++) { Xi = univariate(i); for (int j = i + 1; j < nvar; j++) { Xj = univariate(j); for (int k = j + 1; k < nvar; k++) { Xk = univariate(k); p = Xk.multiply(Xj).multiply(Xi); q = Xk.multiply(Xj.multiply(Xi)); if (!p.equals(q)) { if (debug) { logger.info("Xi = " + Xi + ", Xj = " + Xj + ", Xk = " + Xk); logger.info("p = ( Xk * Xj ) * Xi = " + p); logger.info("q = Xk * ( Xj * Xi ) = " + q); } return false; } } } } return true; } /** * Get a (constant) GenSolvablePolynomial<C> element from a long * value. * @param a long. * @return a GenSolvablePolynomial<C>. */ @Override public GenSolvablePolynomial fromInteger(long a) { return new GenSolvablePolynomial(this, coFac.fromInteger(a), evzero); } /** * Get a (constant) GenSolvablePolynomial<C> element from a BigInteger * value. * @param a BigInteger. * @return a GenSolvablePolynomial<C>. */ @Override public GenSolvablePolynomial fromInteger(BigInteger a) { return new GenSolvablePolynomial(this, coFac.fromInteger(a), evzero); } /** * Random solvable polynomial. Generates a random solvable polynomial with k * = 5, l = n, d = (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3. * @param n number of terms. * @return a random solvable polynomial. */ @Override public GenSolvablePolynomial random(int n) { return random(n, random); } /** * Random solvable polynomial. Generates a random solvable polynomial with k * = 5, l = n, d = (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3. * @param n number of terms. * @param rnd is a source for random bits. * @return a random solvable polynomial. */ @Override public GenSolvablePolynomial random(int n, Random rnd) { if (nvar == 1) { return random(5, n, n, 0.7f, rnd); } return random(5, n, 3, 0.3f, rnd); } /** * Generate a random solvable polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @return a random solvable polynomial. */ @Override public GenSolvablePolynomial random(int k, int l, int d, float q) { return random(k, l, d, q, random); } /** * Random solvable polynomial. * @param k size of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @param rnd is a source for random bits. * @return a random solvable polynomial. */ @Override public GenSolvablePolynomial random(int k, int l, int d, float q, Random rnd) { GenSolvablePolynomial r = getZERO(); //.clone(); // copy( ZERO ); // new GenPolynomial( this, getZERO().val ); ExpVector e; C a; // add random coeffs and exponents for (int i = 0; i < l; i++) { e = ExpVector.EVRAND(nvar, d, q, rnd); a = coFac.random(k, rnd); r = (GenSolvablePolynomial) r.sum(a, e); // somewhat inefficient but clean } return r; } /** * Copy polynomial c. * @param c * @return a copy of c. */ public GenSolvablePolynomial copy(GenSolvablePolynomial c) { return new GenSolvablePolynomial(this, c.val); } /** * Parse a solvable polynomial with the use of GenPolynomialTokenizer * @param s String. * @return GenSolvablePolynomial from s. */ @Override public GenSolvablePolynomial parse(String s) { //return getZERO(); return parse(new StringReader(s)); } /** * Parse a solvable polynomial with the use of GenPolynomialTokenizer * @param r Reader. * @return next GenSolvablePolynomial from r. */ @Override @SuppressWarnings("unchecked") public GenSolvablePolynomial parse(Reader r) { GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r); GenSolvablePolynomial p = null; try { p = (GenSolvablePolynomial) pt.nextSolvablePolynomial(); } catch (IOException e) { logger.error(e.toString() + " parse " + this); p = ZERO; } return p; } /** * Generate univariate solvable polynomial in a given variable. * @param i the index of the variable. * @return X_i as solvable univariate polynomial. */ @Override public GenSolvablePolynomial univariate(int i) { return (GenSolvablePolynomial) super.univariate(i); } /** * Generate univariate solvable polynomial in a given variable with given * exponent. * @param i the index of the variable. * @param e the exponent of the variable. * @return X_i^e as solvable univariate polynomial. */ @Override public GenSolvablePolynomial univariate(int i, long e) { return (GenSolvablePolynomial) super.univariate(i, e); } /** * Generate univariate solvable polynomial in a given variable with given * exponent. * @param modv number of module variables. * @param i the index of the variable. * @param e the exponent of the variable. * @return X_i^e as solvable univariate polynomial. */ @Override public GenSolvablePolynomial univariate(int modv, int i, long e) { return (GenSolvablePolynomial) super.univariate(modv, i, e); } /** * Generate list of univariate polynomials in all variables. * @return List(X_1,...,X_n) a list of univariate polynomials. */ @Override public List> univariateList() { //return castToSolvableList( super.univariateList() ); return univariateList(0, 1L); } /** * Generate list of univariate polynomials in all variables. * @param modv number of module variables. * @return List(X_1,...,X_n) a list of univariate polynomials. */ @Override public List> univariateList(int modv) { return univariateList(modv, 1L); } /** * Generate list of univariate polynomials in all variables with given * exponent. * @param modv number of module variables. * @param e the exponent of the variables. * @return List(X_1^e,...,X_n^e) a list of univariate polynomials. */ @Override public List> univariateList(int modv, long e) { List> pols = new ArrayList>(nvar); int nm = nvar - modv; for (int i = 0; i < nm; i++) { GenSolvablePolynomial p = univariate(modv, nm - 1 - i, e); pols.add(p); } return pols; } /* * Generate list of univariate polynomials in all variables with given exponent. * @param modv number of module variables. * @param e the exponent of the variables. * @return List(X_1^e,...,X_n^e) a list of univariate polynomials. @Override public List> univariateList(int modv, long e) { List> pol = super.univariateList(modv,e); UnaryFunctor,GenSolvablePolynomial> fc = new UnaryFunctor,GenSolvablePolynomial>() { public GenSolvablePolynomial eval(GenPolynomial p) { if ( ! (p instanceof GenSolvablePolynomial) ) { throw new RuntimeException("no solvable polynomial "+p); } return (GenSolvablePolynomial) p; } }; List> pols = ListUtil.,GenSolvablePolynomial>map(this,pol,fc); return pols; } */ /* include here ? * Get list as List of GenSolvablePolynomials. * Required because no List casts allowed. Equivalent to * cast (List<GenSolvablePolynomial<C>>) list. * @return solvable polynomial list from this. public List> castToSolvableList(List> list) { List< GenSolvablePolynomial > slist = null; if ( list == null ) { return slist; } slist = new ArrayList< GenSolvablePolynomial >( list.size() ); GenSolvablePolynomial s; for ( GenPolynomial p: list ) { if ( ! (p instanceof GenSolvablePolynomial) ) { throw new RuntimeException("no solvable polynomial "+p); } s = (GenSolvablePolynomial) p; slist.add( s ); } return slist; } */ /** * Extend variables. Used e.g. in module embedding. Extend number of * variables by i. * @param i number of variables to extend. * @return extended solvable polynomial ring factory. */ @Override public GenSolvablePolynomialRing extend(int i) { GenPolynomialRing pfac = super.extend(i); GenSolvablePolynomialRing spfac = new GenSolvablePolynomialRing(pfac.coFac, pfac.nvar, pfac.tord, pfac.vars); spfac.table.extend(this.table); return spfac; } /** * Contract variables. Used e.g. in module embedding. Contract number of * variables by i. * @param i number of variables to remove. * @return contracted solvable polynomial ring factory. */ @Override public GenSolvablePolynomialRing contract(int i) { GenPolynomialRing pfac = super.contract(i); GenSolvablePolynomialRing spfac = new GenSolvablePolynomialRing(pfac.coFac, pfac.nvar, pfac.tord, pfac.vars); spfac.table.contract(this.table); return spfac; } /** * Reverse variables. Used e.g. in opposite rings. * @return solvable polynomial ring factory with reversed variables. */ @Override public GenSolvablePolynomialRing reverse() { return reverse(false); } /** * Reverse variables. Used e.g. in opposite rings. * @param partial true for partialy reversed term orders. * @return solvable polynomial ring factory with reversed variables. */ @Override public GenSolvablePolynomialRing reverse(boolean partial) { GenPolynomialRing pfac = super.reverse(partial); GenSolvablePolynomialRing spfac = new GenSolvablePolynomialRing(pfac.coFac, pfac.nvar, pfac.tord, pfac.vars); spfac.partial = partial; spfac.table.reverse(this.table); return spfac; } } jas-2.5/src/edu/jas/poly/Local.java0000644000175000017500000002452012014234362017344 0ustar giovannigiovanni/* * $Id: Local.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.poly; import org.apache.log4j.Logger; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; /** * Local element based on RingElem pairs. Objects of this class are (nearly) * immutable. * @author Heinz Kredel * @fix Not jet working because of monic GBs. */ public class Local> implements RingElem> { private static final Logger logger = Logger.getLogger(Local.class); private final boolean debug = logger.isDebugEnabled(); /** * Local class factory data structure. */ protected final LocalRing ring; /** * Numerator part of the element data structure. */ protected final C num; /** * Denominator part of the element data structure. */ protected final C den; /** * Flag to remember if this local element is a unit. -1 is unknown, 1 is * unit, 0 not a unit. */ protected int isunit = -1; // initially unknown /** * The constructor creates a Local object from a ring factory. * @param r ring factory. */ public Local(LocalRing r) { this(r, r.ring.getZERO()); } /** * The constructor creates a Local object from a ring factory and a * numerator element. The denominator is assumed to be 1. * @param r ring factory. * @param n numerator. */ public Local(LocalRing r, C n) { this(r, n, r.ring.getONE(), true); } /** * The constructor creates a Local object from a ring factory and a * numerator and denominator element. * @param r ring factory. * @param n numerator. * @param d denominator. */ public Local(LocalRing r, C n, C d) { this(r, n, d, false); } /** * The constructor creates a Local object from a ring factory and a * numerator and denominator element. * @param r ring factory. * @param n numerator. * @param d denominator. * @param isred true if gcd(n,d) == 1, else false. */ @SuppressWarnings("unchecked") protected Local(LocalRing r, C n, C d, boolean isred) { if (d == null || d.isZERO()) { throw new IllegalArgumentException("denominator may not be zero"); } ring = r; if (d.signum() < 0) { n = n.negate(); d = d.negate(); } if (isred) { num = n; den = d; return; } C p = d.remainder(ring.ideal); if (p == null || p.isZERO()) { throw new IllegalArgumentException("denominator may not be in ideal"); } // must reduce to lowest terms if (n instanceof GcdRingElem && d instanceof GcdRingElem) { GcdRingElem ng = (GcdRingElem) n; GcdRingElem dg = (GcdRingElem) d; C gcd = (C) ng.gcd(dg); if (debug) { logger.info("gcd = " + gcd); } //RingElem gcd = ring.ring.getONE(); if (gcd.isONE()) { num = n; den = d; } else { num = n.divide(gcd); den = d.divide(gcd); } // } else { // univariate polynomial? } else { logger.warn("gcd = ????"); num = n; den = d; } } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public LocalRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public Local copy() { return new Local(ring, num, den, true); } /** * Is Local zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return num.isZERO(); } /** * Is Local one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return num.equals(den); } /** * Is Local unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (isunit > 0) { return true; } if (isunit == 0) { return false; } // not jet known if (num.isZERO()) { isunit = 0; return false; } C p = num.remainder(ring.ideal); boolean u = (p != null && !p.isZERO()); if (u) { isunit = 1; } else { isunit = 0; } return (u); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { return "Local[ " + num.toString() + " / " + den.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "Local( " + num.toScript() + " , " + den.toScript() + " )"; } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Local comparison. * @param b Local. * @return sign(this-b). */ //JAVA6only: @Override public int compareTo(Local b) { if (b == null || b.isZERO()) { return this.signum(); } C r = num.multiply(b.den); C s = den.multiply(b.num); C x = r.subtract(s); return x.signum(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @SuppressWarnings("unchecked") // not jet working @Override public boolean equals(Object b) { if (!(b instanceof Local)) { return false; } Local a = null; try { a = (Local) b; } catch (ClassCastException e) { } if (a == null) { return false; } return (0 == compareTo(a)); } /** * Hash code for this local. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + num.hashCode(); h = 37 * h + den.hashCode(); return h; } /** * Local absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public Local abs() { return new Local(ring, num.abs(), den, true); } /** * Local summation. * @param S Local. * @return this+S. */ public Local sum(Local S) { if (S == null || S.isZERO()) { return this; } C n = num.multiply(S.den); n = n.sum(den.multiply(S.num)); C d = den.multiply(S.den); return new Local(ring, n, d, false); } /** * Local negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public Local negate() { return new Local(ring, num.negate(), den, true); } /** * Local signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { return num.signum(); } /** * Local subtraction. * @param S Local. * @return this-S. */ public Local subtract(Local S) { if (S == null || S.isZERO()) { return this; } C n = num.multiply(S.den); n = n.subtract(den.multiply(S.num)); C d = den.multiply(S.den); return new Local(ring, n, d, false); } /** * Local division. * @param S Local. * @return this/S. */ public Local divide(Local S) { return multiply(S.inverse()); } /** * Local inverse. * @see edu.jas.structure.RingElem#inverse() * @return S with S = 1/this if defined. */ public Local inverse() { if (isONE()) { return this; } if (isUnit()) { return new Local(ring, den, num, true); } throw new ArithmeticException("element not invertible " + this); } /** * Local remainder. * @param S Local. * @return this - (this/S)*S. */ public Local remainder(Local S) { if (num.isZERO()) { throw new ArithmeticException("element not invertible " + this); } if (S.isUnit()) { return ring.getZERO(); } else { throw new UnsupportedOperationException("remainder not implemented" + S); } } /** * Local multiplication. * @param S Local. * @return this*S. */ public Local multiply(Local S) { if (S == null || S.isZERO()) { return S; } if (num.isZERO()) { return this; } if (S.isONE()) { return this; } if (this.isONE()) { return S; } C n = num.multiply(S.num); C d = den.multiply(S.den); return new Local(ring, n, d, false); } /** * Greatest common divisor. Note: Not implemented, throws * UnsupportedOperationException. * @param b other element. * @return gcd(this,b). */ public Local gcd(Local b) { throw new UnsupportedOperationException("gcd not implemented " + this.getClass().getName()); } /** * Extended greatest common divisor. Note: Not implemented, throws * UnsupportedOperationException. * @param b other element. * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). */ public Local[] egcd(Local b) { throw new UnsupportedOperationException("egcd not implemented " + this.getClass().getName()); } } jas-2.5/src/edu/jas/poly/TermOrderOptimization.java0000644000175000017500000004237712022620356022637 0ustar giovannigiovanni/* * $Id: TermOrderOptimization.java 4162 2012-09-08 10:41:51Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.ArrayList; import java.util.Collection; import java.util.Arrays; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.structure.RingElem; import edu.jas.arith.BigInteger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.vector.BasicLinAlg; /** * Term order optimization. * See mas10/maspoly/DIPTOO.m{di}. * @author Heinz Kredel */ public class TermOrderOptimization { private static final Logger logger = Logger.getLogger(TermOrderOptimization.class); //private static boolean debug = logger.isDebugEnabled(); /** * Degree matrix. * @param A polynomial to be considered. * @return degree matrix. */ public static > List> degreeMatrix( GenPolynomial A ) { List> dem = null; if ( A == null ) { return dem; } BigInteger cfac = new BigInteger(); GenPolynomialRing ufac = new GenPolynomialRing(cfac,1); int nvar = A.numberOfVariables(); dem = new ArrayList>( nvar ); for ( int i = 0; i < nvar; i++ ) { dem.add( ufac.getZERO() ); } if ( A.isZERO() ) { return dem; } for ( ExpVector e: A.getMap().keySet() ) { dem = expVectorAdd(dem, e ); } return dem; } /** * Degree matrix exponent vector add. * @param dm degree matrix. * @param e exponent vector. * @return degree matrix + e. */ public static List> expVectorAdd(List> dm, ExpVector e) { for ( int i = 0; i < dm.size() && i < e.length(); i++ ) { GenPolynomial p = dm.get(i); long u = e.getVal(i); ExpVector f = ExpVector.create(1,0,u); p = p.sum( p.ring.getONECoefficient(), f ); dm.set(i,p); } return dm; } /** * Degree matrix of coefficient polynomials. * @param A polynomial to be considered. * @return degree matrix for the coeficients. */ public static > List> degreeMatrixOfCoefficients( GenPolynomial> A ) { if ( A == null ) { throw new IllegalArgumentException("polynomial must not be null"); } return degreeMatrix( A.getMap().values() ); } /** * Degree matrix. * @param L list of polynomial to be considered. * @return degree matrix. */ public static > List> degreeMatrix( Collection> L ) { if ( L == null ) { throw new IllegalArgumentException("list must be non null"); } BasicLinAlg> blas = new BasicLinAlg>(); List> dem = null; for ( GenPolynomial p : L ) { List> dm = degreeMatrix( p ); if ( dem == null ) { dem = dm; } else { dem = blas.vectorAdd( dem, dm ); } } return dem; } /** * Degree matrix of coefficient polynomials. * @param L list of polynomial to be considered. * @return degree matrix for the coeficients. */ public static > List> degreeMatrixOfCoefficients( Collection>> L ) { if ( L == null ) { throw new IllegalArgumentException("list must not be null"); } BasicLinAlg> blas = new BasicLinAlg>(); List> dem = null; for ( GenPolynomial> p : L ) { List> dm = degreeMatrixOfCoefficients( p ); if ( dem == null ) { dem = dm; } else { dem = blas.vectorAdd( dem, dm ); } } return dem; } /** * Optimal permutation for the Degree matrix. * @param D degree matrix. * @return optimal permutation for D. */ public static List optimalPermutation( List> D ) { if ( D == null ) { throw new IllegalArgumentException("list must be non null"); } List P = new ArrayList( D.size() ); if ( D.size() == 0 ) { return P; } if ( D.size() == 1 ) { P.add(0); return P; } SortedMap< GenPolynomial, List > map = new TreeMap,List>(); int i = 0; for ( GenPolynomial p : D ) { List il = map.get(p); if ( il == null ) { il = new ArrayList(3); } il.add( i ); map.put( p, il ); i++; } List> V = new ArrayList>( map.values() ); //System.out.println("V = " + V); //for ( int j = V.size()-1; j >= 0; j-- ) { for ( int j = 0; j < V.size(); j++ ) { List v = V.get(j); for ( Integer k : v ) { P.add( k ); } } return P; } /** * Inverse of a permutation. * @param P permutation. * @return S with S*P = id. */ public static List inversePermutation( List P ) { if ( P == null || P.size() <= 1 ) { return P; } List ip = new ArrayList(P); // ensure size and content for ( int i = 0; i < P.size(); i++ ) { ip.set(P.get(i),i); // inverse } return ip; } /** * Test for identity permutation. * @param P permutation. * @return true , if P = id, else false. */ public static boolean isIdentityPermutation( List P ) { if ( P == null || P.size() <= 1 ) { return true; } for ( int i = 0; i < P.size(); i++ ) { if ( P.get(i).intValue() != i ) { return false; } } return true; } /** * Multiplication permutations. * @param P permutation. * @param S permutation. * @return P*S. */ public static List multiplyPermutation( List P, List S ) { if ( P == null || S == null ) { return null; } if ( P.size() != S.size() ) { throw new IllegalArgumentException("#P != #S: P =" + P + ", S = " + S); } List ip = new ArrayList(P); // ensure size and content for ( int i = 0; i < P.size(); i++ ) { ip.set(i,S.get(P.get(i))); } return ip; } /** * Permutation of a list. * @param L list. * @param P permutation. * @return P(L). */ public static List listPermutation( List P, List L ) { if ( L == null || L.size() <= 1 ) { return L; } List pl = new ArrayList( L.size() ); for ( Integer i : P ) { pl.add( L.get( (int)i ) ); } return pl; } /** * Permutation of an array. * Compiles, but does not work, requires JDK 1.6 to work. * @param a array. * @param P permutation. * @return P(a). */ @SuppressWarnings("unchecked") public static T[] arrayPermutation( List P, T[] a ) { if ( a == null || a.length <= 1 ) { return a; } T[] b = (T[]) new Object[a.length]; // jdk 1.5 //T[] b = Arrays.copyOf( a, a.length ); // jdk 1.6, works int j = 0; for ( Integer i : P ) { b[j] = a[ (int)i ]; j++; } return b; } /** * Permutation of an array. * @param a array. * @param P permutation. * @return P(a). */ public static String[] stringArrayPermutation( List P, String[] a ) { if ( a == null || a.length <= 1 ) { return a; } String[] b = new String[a.length]; // jdk 1.5 //T[] b = Arrays.copyOf( a, a.length ); // jdk 1.6 int j = 0; for ( Integer i : P ) { b[j] = a[ (int)i ]; j++; } return b; } /** * Permutation of a long array. * @param a array of long. * @param P permutation. * @return P(a). */ public static long[] longArrayPermutation( List P, long[] a ) { if ( a == null || a.length <= 1 ) { return a; } long[] b = new long[ a.length ]; int j = 0; for ( Integer i : P ) { b[j] = a[ (int)i ]; j++; } return b; } /** * Permutation of an exponent vector. * @param e exponent vector. * @param P permutation. * @return P(e). */ public static ExpVector permutation( List P, ExpVector e ) { if ( e == null ) { return e; } long[] u = longArrayPermutation( P, e.getVal() ); ExpVector f = ExpVector.create( u ); return f; } /** * Permutation of polynomial exponent vectors. * @param A polynomial. * @param R polynomial ring. * @param P permutation. * @return P(A). */ public static > GenPolynomial permutation( List P, GenPolynomialRing R, GenPolynomial A ) { if ( A == null ) { return A; } GenPolynomial B = R.getZERO().copy(); Map Bv = B.val; //getMap(); for ( Map.Entry y: A.getMap().entrySet() ) { ExpVector e = y.getKey(); C a = y.getValue(); //System.out.println("e = " + e); ExpVector f = permutation(P,e); //System.out.println("f = " + f); Bv.put( f, a ); // assert f not in Bv } return B; } /** * Permutation of polynomial exponent vectors. * @param L list of polynomials. * @param R polynomial ring. * @param P permutation. * @return P(L). */ public static > List> permutation( List P, GenPolynomialRing R, List> L ) { if ( L == null || L.size() == 0 ) { return L; } List> K = new ArrayList>( L.size() ); for ( GenPolynomial a: L ) { GenPolynomial b = permutation( P, R, a ); K.add( b ); } return K; } /** * Permutation of polynomial exponent vectors of coefficient polynomials. * @param A polynomial. * @param R polynomial ring. * @param P permutation. * @return P(A). */ public static > GenPolynomial> permutationOnCoefficients( List P, GenPolynomialRing> R, GenPolynomial> A ) { if ( A == null ) { return A; } GenPolynomial> B = R.getZERO().copy(); GenPolynomialRing cf = (GenPolynomialRing) R.coFac; Map> Bv = B.val; //getMap(); for ( Map.Entry> y: A.getMap().entrySet() ) { ExpVector e = y.getKey(); GenPolynomial a = y.getValue(); //System.out.println("e = " + e); GenPolynomial b = permutation(P,cf,a); //System.out.println("b = " + b); Bv.put( e, b ); // assert e not in Bv } return B; } /** * Permutation of polynomial exponent vectors of coefficients. * @param L list of polynomials. * @param R polynomial ring. * @param P permutation. * @return P(L). */ public static > List>> permutationOnCoefficients( List P, GenPolynomialRing> R, List>> L ) { if ( L == null || L.size() == 0 ) { return L; } List>> K = new ArrayList>>( L.size() ); for ( GenPolynomial> a: L ) { GenPolynomial> b = permutationOnCoefficients( P, R, a ); K.add( b ); } return K; } /** * Permutation of polynomial ring variables. * @param R polynomial ring. * @param P permutation. * @return P(R). */ public static > GenPolynomialRing permutation( List P, GenPolynomialRing R ) { if ( R == null ) { return R; } if ( R.vars == null || R.nvar <= 1 ) { return R; } GenPolynomialRing S; TermOrder tord = R.tord; if ( tord.getEvord2() != 0 ) { //throw new IllegalArgumentException("split term orders not permutable"); tord = new TermOrder( tord.getEvord2() ); logger.warn("split term order '" + R.tord + "' not permutable, resetting to most base term order " + tord); } long[][] weight = tord.getWeight(); if ( weight != null ) { long[][] w = new long[ weight.length ][]; for ( int i = 0; i < weight.length; i++ ) { w[i] = longArrayPermutation(P,weight[i]); } tord = new TermOrder( w ); } String[] v1 = new String[R.vars.length]; for ( int i = 0; i < v1.length; i++ ) { v1[i] = R.vars[ v1.length-1 - i ]; } String[] vars = stringArrayPermutation( P, v1 ); String[] v2 = new String[R.vars.length]; for ( int i = 0; i < v1.length; i++ ) { v2[i] = vars[ v2.length-1 - i ]; } S = new GenPolynomialRing( R.coFac, R.nvar, tord, v2 ); return S; } /** * Optimize variable order. * @param R polynomial ring. * @param L list of polynomials. * @return optimized polynomial list. */ public static > OptimizedPolynomialList optimizeTermOrder( GenPolynomialRing R, List> L ) { List perm = optimalPermutation( degreeMatrix(L) ); GenPolynomialRing pring = TermOrderOptimization.permutation( perm, R ); List> ppolys = TermOrderOptimization.permutation( perm, pring, L ); OptimizedPolynomialList op = new OptimizedPolynomialList(perm,pring,ppolys); return op; } /** * Optimize variable order. * @param P polynomial list. * @return optimized polynomial list. */ public static > OptimizedPolynomialList optimizeTermOrder( PolynomialList P ) { if ( P == null ) { return null; } return optimizeTermOrder( P.ring, P.list ); } /** * Optimize variable order on coefficients. * @param P polynomial list. * @return optimized polynomial list. */ public static > OptimizedPolynomialList> optimizeTermOrderOnCoefficients( PolynomialList> P ) { if ( P == null ) { return null; } List perm = optimalPermutation( degreeMatrixOfCoefficients( P.list ) ); GenPolynomialRing> ring = P.ring; GenPolynomialRing coFac = (GenPolynomialRing) ring.coFac; GenPolynomialRing pFac; pFac = TermOrderOptimization.permutation( perm, coFac ); GenPolynomialRing> pring; pring = new GenPolynomialRing>(pFac, ring.nvar, ring.tord, ring.vars); List>> ppolys; ppolys = TermOrderOptimization.permutationOnCoefficients( perm, pring, P.list ); OptimizedPolynomialList> op = new OptimizedPolynomialList>(perm,pring,ppolys); return op; } } jas-2.5/src/edu/jas/poly/Examples.java0000644000175000017500000004234212004325040020063 0ustar giovannigiovanni/* * $Id: Examples.java 4057 2012-07-26 20:35:44Z kredel $ */ package edu.jas.poly; import java.util.ArrayList; import java.util.List; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; /** * Examples for polynomials usage. * @author Heinz Kredel. */ public class Examples { /** * main. */ public static void main(String[] args) { //example0(); /* example1(); example2(); example3(); example4(); example5(); */ //example6(); example7(); example7(); //example8(); //example9(); //example10(); //example11(); //example12(); } /** * example0. for PPPJ 2006. */ public static void example0() { BigInteger z = new BigInteger(); TermOrder to = new TermOrder(); String[] vars = new String[] { "x1", "x2", "x3" }; GenPolynomialRing ring; ring = new GenPolynomialRing(z, 3, to, vars); System.out.println("ring = " + ring); GenPolynomial pol; pol = ring.parse("3 x1^2 x3^4 + 7 x2^5 - 61"); System.out.println("pol = " + pol); System.out.println("pol = " + pol.toString(ring.getVars())); GenPolynomial one; one = ring.parse("1"); System.out.println("one = " + one); System.out.println("one = " + one.toString(ring.getVars())); GenPolynomial p; p = pol.subtract(pol); System.out.println("p = " + p); System.out.println("p = " + p.toString(ring.getVars())); p = pol.multiply(pol); System.out.println("p = " + p); System.out.println("p = " + p.toString(ring.getVars())); } /** * example1. random polynomial with rational coefficients. Q[x_1,...x_7] */ public static void example1() { System.out.println("\n\n example 1"); BigRational cfac = new BigRational(); System.out.println("cfac = " + cfac); GenPolynomialRing fac; fac = new GenPolynomialRing(cfac, 7); //System.out.println("fac = " + fac); System.out.println("fac = " + fac); GenPolynomial a = fac.random(10); System.out.println("a = " + a); } /** * example2. random polynomial with coefficients of rational polynomials. * Q[x_1,...x_7][y_1,...,y_3] */ public static void example2() { System.out.println("\n\n example 2"); BigRational cfac = new BigRational(); System.out.println("cfac = " + cfac); GenPolynomialRing fac; fac = new GenPolynomialRing(cfac, 7); System.out.println("fac = " + fac); GenPolynomialRing> gfac; gfac = new GenPolynomialRing>(fac, 3); System.out.println("gfac = " + gfac); GenPolynomial> a = gfac.random(10); System.out.println("a = " + a); } /** * example3. random rational algebraic number. Q(alpha) */ public static void example3() { System.out.println("\n\n example 3"); BigRational cfac = new BigRational(); System.out.println("cfac = " + cfac); GenPolynomialRing mfac; mfac = new GenPolynomialRing(cfac, 1); System.out.println("mfac = " + mfac); GenPolynomial modul = mfac.random(8).monic(); // assume !mo.isUnit() System.out.println("modul = " + modul); AlgebraicNumberRing fac; fac = new AlgebraicNumberRing(modul); System.out.println("fac = " + fac); AlgebraicNumber a = fac.random(15); System.out.println("a = " + a); } protected static long getPrime() { long prime = 2; //2^60-93; // 2^30-35; //19; knuth (2,390) for (int i = 1; i < 60; i++) { prime *= 2; } prime -= 93; //System.out.println("prime = " + prime); return prime; } /** * example4. random modular algebraic number. Z_p(alpha) */ public static void example4() { System.out.println("\n\n example 4"); long prime = getPrime(); ModIntegerRing cfac = new ModIntegerRing(prime); System.out.println("cfac = " + cfac); GenPolynomialRing mfac; mfac = new GenPolynomialRing(cfac, 1); System.out.println("mfac = " + mfac); GenPolynomial modul = mfac.random(8).monic(); // assume !modul.isUnit() System.out.println("modul = " + modul); AlgebraicNumberRing fac; fac = new AlgebraicNumberRing(modul); System.out.println("fac = " + fac); AlgebraicNumber a = fac.random(12); System.out.println("a = " + a); } /** * example5. random solvable polynomial with rational coefficients. * Q{x_1,...x_6, {x_2 * x_1 = x_1 x_2 +1, ...} } */ public static void example5() { System.out.println("\n\n example 5"); BigRational cfac = new BigRational(); System.out.println("cfac = " + cfac); GenSolvablePolynomialRing sfac; sfac = new GenSolvablePolynomialRing(cfac, 6); //System.out.println("sfac = " + sfac); WeylRelations wl = new WeylRelations(sfac); wl.generate(); System.out.println("sfac = " + sfac); GenSolvablePolynomial a = sfac.random(5); System.out.println("a = " + a); System.out.println("a = " + a.toString(sfac.vars)); GenSolvablePolynomial b = a.multiply(a); System.out.println("b = " + b); System.out.println("b = " + b.toString(sfac.vars)); System.out.println("sfac = " + sfac); } /** * example6. Fateman benchmark: p = (x+y+z)^20; q = p * (p+1) Z[z,y,x] */ public static void example6() { System.out.println("\n\n example 6"); BigInteger cfac = new BigInteger(); System.out.println("cfac = " + cfac); TermOrder to = new TermOrder(TermOrder.INVLEX); System.out.println("to = " + to); GenPolynomialRing fac; fac = new GenPolynomialRing(cfac, 3, to); System.out.println("fac = " + fac); fac.setVars(new String[] { "z", "y", "x" }); System.out.println("fac = " + fac); GenPolynomial x = fac.univariate(0); GenPolynomial y = fac.univariate(1); GenPolynomial z = fac.univariate(2); System.out.println("x = " + x); System.out.println("x = " + x.toString(fac.vars)); System.out.println("y = " + y); System.out.println("y = " + y.toString(fac.vars)); System.out.println("z = " + z); System.out.println("z = " + z.toString(fac.vars)); GenPolynomial p = x.sum(y).sum(z).sum(fac.getONE()); //BigInteger f = cfac.fromInteger(10000000001L); // p = p.multiply( f ); System.out.println("p = " + p); System.out.println("p = " + p.toString(fac.vars)); GenPolynomial q = p; for (int i = 1; i < 20; i++) { q = q.multiply(p); } //System.out.println("q = " + q.toString( fac.vars ) ); System.out.println("q = " + q.length()); GenPolynomial q1 = q.sum(fac.getONE()); GenPolynomial q2; long t = System.currentTimeMillis(); q2 = q.multiply(q1); t = System.currentTimeMillis() - t; System.out.println("q2 = " + q2.length()); System.out.println("time = " + t + " ms"); } /** * example7. Fateman benchmark: p = (x+y+z)^20; q = p * (p+1) Q[z,y,x] */ public static void example7() { System.out.println("\n\n example 7"); BigRational cfac = new BigRational(); System.out.println("cfac = " + cfac); TermOrder to = new TermOrder(TermOrder.INVLEX); System.out.println("to = " + to); GenPolynomialRing fac; fac = new GenPolynomialRing(cfac, 3, to); System.out.println("fac = " + fac); fac.setVars(new String[] { "z", "y", "x" }); System.out.println("fac = " + fac); long mi = 1L; //long mi = Integer.MAX_VALUE; GenPolynomial x = fac.univariate(0, mi); GenPolynomial y = fac.univariate(1, mi); GenPolynomial z = fac.univariate(2, mi); // System.out.println("x = " + x); System.out.println("x = " + x.toString(fac.vars)); // System.out.println("y = " + y); System.out.println("y = " + y.toString(fac.vars)); // System.out.println("z = " + z); System.out.println("z = " + z.toString(fac.vars)); GenPolynomial p = x.sum(y).sum(z).sum(fac.getONE()); //BigRational f = cfac.fromInteger(10000000001L); // f = f.multiply( f ); //p = p.multiply( f ); // System.out.println("p = " + p); System.out.println("p = " + p.toString(fac.vars)); int mpow = 20; System.out.println("mpow = " + mpow); GenPolynomial q = p; for (int i = 1; i < mpow; i++) { q = q.multiply(p); } //System.out.println("q = " + q.toString( fac.vars ) ); System.out.println("len(q) = " + q.length()); System.out.println("deg(q) = " + q.degree()); GenPolynomial q1 = q.sum(fac.getONE()); GenPolynomial q2; long t = System.currentTimeMillis(); q2 = q.multiply(q1); t = System.currentTimeMillis() - t; System.out.println("len(q2) = " + q2.length()); System.out.println("deg(q2) = " + q2.degree()); System.out.println("LeadEV(q2) = " + q2.leadingExpVector()); System.out.println("time = " + t + " ms"); } /** * example8. Chebyshev polynomials * * T(0) = 1 T(1) = x T(n) = 2x * T(n-1) - T(n-2) */ public static void example8() { int m = 10; BigInteger fac = new BigInteger(); String[] var = new String[] { "x" }; GenPolynomialRing ring = new GenPolynomialRing(fac, 1, var); List> T = new ArrayList>(m); GenPolynomial t, one, x, x2, x2b; one = ring.getONE(); x = ring.univariate(0); //x2 = ring.parse("2 x"); //x2a = x.multiply( fac.fromInteger(2) ); x2b = x.multiply(new BigInteger(2)); x2 = x2b; T.add(one); T.add(x); for (int n = 2; n < m; n++) { t = x2.multiply(T.get(n - 1)).subtract(T.get(n - 2)); T.add(t); } for (int n = 0 /*m-2*/; n < m; n++) { System.out.println("T[" + n + "] = " + T.get(n)); //.toString(var) ); } } /** * example9. Legendre polynomials * * P(0) = 1 P(1) = x P(n) = 1/n [ (2n-1) * x * P(n-1) - (n-1) * P(n-2) ] */ // P(n+1) = 1/(n+1) [ (2n+1) * x * P(n) - n * P(n-1) ] public static void example9() { int n = 10; BigRational fac = new BigRational(); String[] var = new String[] { "x" }; GenPolynomialRing ring = new GenPolynomialRing(fac, 1, var); List> P = new ArrayList>(n); GenPolynomial t, one, x, xc; BigRational n21, nn; one = ring.getONE(); x = ring.univariate(0); P.add(one); P.add(x); for (int i = 2; i < n; i++) { n21 = new BigRational(2 * i - 1); xc = x.multiply(n21); t = xc.multiply(P.get(i - 1)); nn = new BigRational(i - 1); xc = P.get(i - 2).multiply(nn); t = t.subtract(xc); nn = new BigRational(1, i); t = t.multiply(nn); P.add(t); } for (int i = 0; i < n; i++) { System.out.println("P[" + i + "] = " + P.get(i).toString(var)); System.out.println(); } } /** * example10. Hermite polynomials * * H(0) = 1 H(1) = 2 x H(n) = 2 * x * H(n-1) - 2 * (n-1) * H(n-2) */ // H(n+1) = 2 * x * H(n) - 2 * n * H(n-1) public static void example10() { int n = 100; BigInteger fac = new BigInteger(); String[] var = new String[] { "x" }; GenPolynomialRing ring = new GenPolynomialRing(fac, 1, var); List> H = new ArrayList>(n); GenPolynomial t, one, x2, xc, x; BigInteger n2, nn; one = ring.getONE(); x = ring.univariate(0); n2 = new BigInteger(2); x2 = x.multiply(n2); H.add(one); H.add(x2); for (int i = 2; i < n; i++) { t = x2.multiply(H.get(i - 1)); nn = new BigInteger(2 * (i - 1)); xc = H.get(i - 2).multiply(nn); t = t.subtract(xc); H.add(t); } for (int i = n - 1; i < n; i++) { System.out.println("H[" + i + "] = " + H.get(i).toString(var)); System.out.println(); } } /** * example11. degree matrix; * */ public static void example11() { int n = 50; BigRational fac = new BigRational(); GenPolynomialRing ring = new GenPolynomialRing(fac, n); System.out.println("ring = " + ring + "\n"); GenPolynomial p = ring.random(5, 3, 6, 0.5f); System.out.println("p = " + p + "\n"); List> dem = TermOrderOptimization. degreeMatrix(p); System.out.println("dem = " + dem + "\n"); List> polys = new ArrayList>(); polys.add(p); for (int i = 0; i < 5; i++) { polys.add(ring.random(5, 3, 6, 0.1f)); } System.out.println("polys = " + polys + "\n"); dem = TermOrderOptimization. degreeMatrix(polys); System.out.println("dem = " + dem + "\n"); List perm; perm = TermOrderOptimization.optimalPermutation(dem); System.out.println("perm = " + perm + "\n"); List> pdem; pdem = TermOrderOptimization.> listPermutation(perm, dem); System.out.println("pdem = " + pdem + "\n"); GenPolynomialRing pring; pring = TermOrderOptimization. permutation(perm, ring); System.out.println("ring = " + ring); System.out.println("pring = " + pring + "\n"); List> ppolys; ppolys = TermOrderOptimization. permutation(perm, pring, polys); System.out.println("ppolys = " + ppolys + "\n"); dem = TermOrderOptimization. degreeMatrix(ppolys); //System.out.println("pdem = " + dem + "\n"); perm = TermOrderOptimization.optimalPermutation(dem); //System.out.println("pperm = " + perm + "\n"); int i = 0; for (Integer j : perm) { if (i != (int) j) { System.out.println("error = " + i + " != " + j + "\n"); } i++; } OptimizedPolynomialList op; op = TermOrderOptimization. optimizeTermOrder(ring, polys); System.out.println("op:\n" + op); if (!op.equals(new PolynomialList(pring, ppolys))) { System.out.println("error = " + "\n" + op); } } /** * example12. type games. */ public static void example12() { System.out.println("\n\n example 12"); BigRational t1 = new BigRational(); System.out.println("t1 = " + t1); BigInteger t2 = new BigInteger(); System.out.println("t2 = " + t2); System.out.println("t1.isAssignableFrom(t2) = " + t1.getClass().isAssignableFrom(t2.getClass())); System.out.println("t2.isAssignableFrom(t1) = " + t2.getClass().isAssignableFrom(t1.getClass())); GenPolynomialRing t3 = new GenPolynomialRing(t2, 3); System.out.println("t3 = " + t3); GenSolvablePolynomialRing t4 = new GenSolvablePolynomialRing(t2, 3); System.out.println("t4 = " + t4); System.out.println("t3.isAssignableFrom(t4) = " + t3.getClass().isAssignableFrom(t4.getClass())); System.out.println("t4.isAssignableFrom(t3) = " + t4.getClass().isAssignableFrom(t3.getClass())); GenPolynomialRing t5 = new GenPolynomialRing(t1, 3); System.out.println("t5 = " + t5); System.out.println("t3.isAssignableFrom(t5) = " + t3.getClass().isAssignableFrom(t5.getClass())); System.out.println("t5.isAssignableFrom(t3) = " + t5.getClass().isAssignableFrom(t3.getClass())); } } jas-2.5/src/edu/jas/poly/ModuleList.java0000644000175000017500000003010512000362542020364 0ustar giovannigiovanni/* * $Id: ModuleList.java 3992 2012-07-14 21:32:18Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.ArrayList; import java.io.Serializable; import org.apache.log4j.Logger; import edu.jas.kern.Scripting; import edu.jas.structure.RingElem; import edu.jas.vector.GenVector; import edu.jas.vector.GenVectorModul; /** * List of vectors of polynomials. * Mainly for storage and printing / toString and * conversions to other representations. * @author Heinz Kredel */ public class ModuleList > implements Serializable { /** The factory for the solvable polynomial ring. */ public final GenPolynomialRing< C > ring; /** The data structure is a List of Lists of polynomials. */ public final List< List< GenPolynomial > > list; /** Number of rows in the data structure. */ public final int rows; // -1 is undefined /** Number of columns in the data structure. */ public final int cols; // -1 is undefined private static final Logger logger = Logger.getLogger(ModuleList.class); /** * Constructor. * @param r polynomial ring factory. * @param l list of list of polynomials. */ public ModuleList( GenPolynomialRing< C > r, List< List>> l) { ring = r; list = ModuleList.padCols(r,l); if ( list == null ) { rows = -1; cols = -1; } else { rows = list.size(); if ( rows > 0 ) { cols = list.get(0).size(); } else { cols = -1; } } } /** * Constructor. * @param r solvable polynomial ring factory. * @param l list of list of solvable polynomials. */ public ModuleList( GenSolvablePolynomialRing< C > r, List< List>> l) { this( r, ModuleList.castToList(l) ); } /** * Constructor. * @param r polynomial ring factory. * @param l list of vectors of polynomials. */ public ModuleList( GenVectorModul> r, List< GenVector>> l) { this( (GenPolynomialRing)r.coFac, ModuleList.vecToList(l) ); } /** Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object m) { if ( ! (m instanceof ModuleList) ) { //System.out.println("ModuleList"); return false; } ModuleList ml = null; try { ml = (ModuleList)m; } catch (ClassCastException ignored) { } if ( ml == null ) { return false; } if ( ! ring.equals( ml.ring ) ) { //System.out.println("Ring"); return false; } if ( list == ml.list ) { return true; } if ( list == null || ml.list == null ) { //System.out.println("List, null"); return false; } if ( list.size() != ml.list.size() ) { //System.out.println("List, size"); return false; } // compare sorted lists List otl = OrderedModuleList.sort( ring, list ); List oml = OrderedModuleList.sort( ring, ml.list ); if ( ! otl.equals(oml) ) { return false; } return true; } /** Hash code for this module list. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + ( list == null ? 0 : list.hashCode() ); return h; } /** * String representation of the module list. * @see java.lang.Object#toString() */ @Override //@SuppressWarnings("unchecked") public String toString() { StringBuffer erg = new StringBuffer(); String[] vars = null; if ( ring != null ) { erg.append( ring.toString() ); vars = ring.getVars(); } if ( list == null ) { erg.append(")"); return erg.toString(); } boolean first = true; erg.append("(\n"); for ( List< GenPolynomial > row: list ) { if ( first ) { first = false; } else { erg.append( ",\n" ); } boolean ifirst = true; erg.append(" ( "); String os; for ( GenPolynomial oa: row ) { if ( oa == null ) { os = "0"; } else if ( vars != null ) { os = oa.toString(vars); } else { os = oa.toString(); } if ( ifirst ) { ifirst = false; } else { erg.append( ", " ); if ( os.length() > 100 ) { erg.append("\n"); } } erg.append( os ); } erg.append(" )"); } erg.append("\n)"); return erg.toString(); } /** Get a scripting compatible string representation. * @return script compatible representation for this ModuleList. */ public String toScript() { StringBuffer s = new StringBuffer(); if ( ring instanceof GenSolvablePolynomialRing ) { s.append("Solvable"); } switch (Scripting.getLang() ) { case Ruby: s.append("SubModule.new("); break; case Python: default: s.append("SubModule("); } if ( ring != null ) { s.append( ring.toScript() ); } if ( list == null ) { s.append(")"); return s.toString(); } switch (Scripting.getLang() ) { case Ruby: s.append(",\"\",["); break; case Python: default: s.append(",list=["); } boolean first = true; for ( List< GenPolynomial > row: list ) { if ( first ) { first = false; } else { s.append( "," ); } boolean ifirst = true; s.append(" ( "); String os; for ( GenPolynomial oa: row ) { if ( oa == null ) { os = "0"; } else { os = oa.toScript(); } if ( ifirst ) { ifirst = false; } else { s.append( ", " ); } s.append( os ); } s.append(" )"); } s.append(" ])"); return s.toString(); } /** * Pad columns and remove zero rows. * Make all rows have the same number of columns. * @param ring polynomial ring factory. * @param l list of list of polynomials. * @return list of list of polynomials with same number of colums. */ public static > List< List>> padCols(GenPolynomialRing< C > ring, List< List>> l) { if ( l == null ) { return l; } int mcols = 0; int rs = 0; for ( List< GenPolynomial > row: l ) { if ( row != null ) { rs++; if ( row.size() > mcols ) { mcols = row.size(); } } } List< List> > norm = new ArrayList< List> >( rs ); for ( List< GenPolynomial > row: l ) { if ( row != null ) { List> rn = new ArrayList>( row ); while ( rn.size() < mcols ) { rn.add( ring.getZERO() ); } norm.add( rn ); } } return norm; } /** * Get PolynomialList. * Embed module in a polynomial ring. * @see edu.jas.poly.PolynomialList * @return polynomial list corresponding to this. */ public PolynomialList getPolynomialList() { GenPolynomialRing< C > pfac = ring.extend(cols); logger.debug("extended ring = " + pfac); //System.out.println("extended ring = " + pfac); List> pols = null; if ( list == null ) { // rows < 0 return new PolynomialList(pfac,pols); } pols = new ArrayList>( rows ); if ( rows == 0 ) { // nothing to do return new PolynomialList(pfac,pols); } GenPolynomial zero = pfac.getZERO(); GenPolynomial d = null; for ( List> r: list ) { GenPolynomial ext = zero; //int m = cols-1; int m = 0; for ( GenPolynomial c: r ) { d = c.extend( pfac, m, 1l ); ext = ext.sum(d); m++; } pols.add( ext ); } return new PolynomialList(pfac, pols); } /** * Get list as List of GenSolvablePolynomials. * Required because no List casts allowed. Equivalent to * cast (List<List<GenSolvablePolynomial<C>>>) list. * @return list of solvable polynomial lists from this. */ public List< List< GenSolvablePolynomial > > castToSolvableList() { List< List> > slist = null; if ( list == null ) { return slist; } slist = new ArrayList< List> >( list.size() ); for ( List< GenPolynomial> row: list ) { List< GenSolvablePolynomial > srow = new ArrayList< GenSolvablePolynomial >( row.size() ); for ( GenPolynomial p: row ) { if ( ! (p instanceof GenSolvablePolynomial) ) { throw new RuntimeException("no solvable polynomial "+p); } GenSolvablePolynomial s = (GenSolvablePolynomial) p; srow.add( s ); } slist.add( srow ); } return slist; } /** * Get a solvable polynomials list as List of GenPolynomials. * Required because no List casts allowed. Equivalent to * cast (List<List<GenPolynomial<C>>>) list. * @param slist list of solvable polynomial lists. * @return list of polynomial lists from slist. */ public static > List< List< GenPolynomial > > castToList( List< List> > slist ) { List< List> > list = null; if ( slist == null ) { return list; } list = new ArrayList< List> >( slist.size() ); for ( List< GenSolvablePolynomial> srow: slist ) { List< GenPolynomial > row = new ArrayList< GenPolynomial >( srow.size() ); for ( GenSolvablePolynomial s: srow ) { row.add( s ); } list.add( row ); } return list; } /** * Get a list of vectors as List of list of GenPolynomials. * @param vlist list of vectors of polynomials. * @return list of polynomial lists from vlist. */ public static > List< List< GenPolynomial > > vecToList( List< GenVector> > vlist ) { List< List> > list = null; if ( vlist == null ) { return list; } list = new ArrayList< List> >( vlist.size() ); for ( GenVector< GenPolynomial> srow: vlist ) { List< GenPolynomial > row = srow.val; list.add( row ); } return list; } } jas-2.5/src/edu/jas/poly/ExpVectorByte.java0000644000175000017500000006006312042051146021055 0ustar giovannigiovanni/* * $Id: ExpVectorByte.java 4270 2012-10-24 20:41:11Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.ArrayList; /** * ExpVectorByte implements exponent vectors for polynomials using arrays of * byte as storage unit. This class is used by ExpVector internally, there is no * need to use this class directly. * @see ExpVector * @author Heinz Kredel */ public final class ExpVectorByte extends ExpVector /*implements AbelianGroupElem*/{ /** * The data structure is an array of longs. */ /*package*/final byte[] val; /** * Largest byte. */ public static final long maxByte = (long) Byte.MAX_VALUE / 2; /** * Smallest byte. */ public static final long minByte = (long) Byte.MIN_VALUE / 2; /** * Constructor for ExpVector. * @param n length of exponent vector. */ public ExpVectorByte(int n) { this(new byte[n]); } /** * Constructor for ExpVector. Sets exponent i to e. * @param n length of exponent vector. * @param i index of exponent to be set. * @param e exponent to be set. */ public ExpVectorByte(int n, int i, byte e) { this(n); val[i] = e; } /** * Constructor for ExpVector. Sets exponent i to e. * @param n length of exponent vector. * @param i index of exponent to be set. * @param e exponent to be set. */ public ExpVectorByte(int n, int i, long e) { this(n); if (e >= maxByte || e <= minByte) { throw new IllegalArgumentException("exponent to large: " + e); } val[i] = (byte) e; } /** * Internal constructor for ExpVector. Sets val. * @param v internal representation array. */ protected ExpVectorByte(byte[] v) { super(); val = v; } /** * Constructor for ExpVector. Sets val, converts from long array. * @param v long representation array. */ public ExpVectorByte(long[] v) { this(v.length); for (int i = 0; i < v.length; i++) { if (v[i] >= maxByte || v[i] <= minByte) { throw new IllegalArgumentException("exponent to large: " + v[i]); } val[i] = (byte) v[i]; } } /** * Constructor for ExpVector. Converts a String representation to an * ExpVector. Accepted format = (1,2,3,4,5,6,7). * @param s String representation. */ public ExpVectorByte(String s) throws NumberFormatException { super(); // first format = (1,2,3,4,5,6,7) List exps = new ArrayList(); s = s.trim(); int b = s.indexOf('('); int e = s.indexOf(')', b + 1); String teil; int k; byte a; if (b >= 0 && e >= 0) { b++; while ((k = s.indexOf(',', b)) >= 0) { teil = s.substring(b, k); a = Byte.parseByte(teil); exps.add(Byte.valueOf(a)); b = k + 1; } if (b <= e) { teil = s.substring(b, e); a = Byte.parseByte(teil); exps.add(Byte.valueOf(a)); } int length = exps.size(); val = new byte[length]; for (int j = 0; j < length; j++) { val[j] = exps.get(j).byteValue(); } } else { // not implemented val = null; // length = -1; //Vector names = new Vector(); //vars = s; } } /** * Clone this. * @see java.lang.Object#clone() */ @Override public ExpVectorByte copy() { byte[] w = new byte[val.length]; System.arraycopy(val, 0, w, 0, val.length); return new ExpVectorByte(w); } /** * Get the exponent vector. * @return val as long. */ @Override /*package*/long[] getVal() { long v[] = new long[val.length]; for (int i = 0; i < val.length; i++) { v[i] = val[i]; } return v; } /** * Get the exponent at position i. * @param i position. * @return val[i]. */ @Override public long getVal(int i) { return val[i]; } /** * Set the exponent at position i to e. * @param i * @param e * @return old val[i]. */ @Override protected long setVal(int i, long e) { byte x = val[i]; if (e >= maxByte || e <= minByte) { throw new IllegalArgumentException("exponent to large: " + e); } val[i] = (byte) e; hash = 0; // beware of race condition return x; } /** * Set the exponent at position i to e. * @param i * @param e * @return old val[i]. */ protected byte setVal(int i, byte e) { byte x = val[i]; val[i] = e; hash = 0; // beware of race condition return x; } /** * Get the length of this exponent vector. * @return val.length. */ @Override public int length() { return val.length; } /** * Extend variables. Used e.g. in module embedding. Extend this by i * elements and set val[j] to e. * @param i number of elements to extend. * @param j index of element to be set. * @param e new exponent for val[j]. * @return extended exponent vector. */ @Override public ExpVectorByte extend(int i, int j, long e) { byte[] w = new byte[val.length + i]; System.arraycopy(val, 0, w, i, val.length); if (j >= i) { throw new IllegalArgumentException("i " + i + " <= j " + j + " invalid"); } if (e >= maxByte || e <= minByte) { throw new IllegalArgumentException("exponent to large: " + e); } w[j] = (byte) e; return new ExpVectorByte(w); } /** * Extend lower variables. Extend this by i lower elements and set val[j] to * e. * @param i number of elements to extend. * @param j index of element to be set. * @param e new exponent for val[j]. * @return extended exponent vector. */ @Override public ExpVectorByte extendLower(int i, int j, long e) { byte[] w = new byte[val.length + i]; System.arraycopy(val, 0, w, 0, val.length); if (j >= i) { throw new IllegalArgumentException("i " + i + " <= j " + j + " invalid"); } w[val.length + j] = (byte) e; return new ExpVectorByte(w); } /** * Contract variables. Used e.g. in module embedding. Contract this to len * elements. * @param i position of first element to be copied. * @param len new length. * @return contracted exponent vector. */ @Override public ExpVectorByte contract(int i, int len) { if (i + len > val.length) { throw new IllegalArgumentException("len " + len + " > val.len " + val.length); } byte[] w = new byte[len]; System.arraycopy(val, i, w, 0, len); return new ExpVectorByte(w); } /** * Reverse variables. Used e.g. in opposite rings. * @return reversed exponent vector. */ @Override public ExpVectorByte reverse() { byte[] w = new byte[val.length]; for (int i = 0; i < val.length; i++) { w[i] = val[val.length - 1 - i]; } return new ExpVectorByte(w); } /** * Reverse j variables. Used e.g. in opposite rings. Reverses the first j-1 * variables, the rest is unchanged. * @param j index of first variable not reversed. * @return reversed exponent vector. */ @Override public ExpVectorByte reverse(int j) { if (j <= 0 || j > val.length) { return this; } byte[] w = new byte[val.length]; for (int i = 0; i < j; i++) { w[i] = val[j - 1 - i]; } // copy rest for (int i = j; i < val.length; i++) { w[i] = val[i]; } return new ExpVectorByte(w); } /** * Combine with ExpVector. Combine this with the other ExpVector V. * @param V the other exponent vector. * @return combined exponent vector. */ @Override public ExpVectorByte combine(ExpVector V) { if (V == null || V.length() == 0) { return this; } ExpVectorByte Vi = (ExpVectorByte) V; if (val.length == 0) { return Vi; } byte[] w = new byte[val.length + Vi.val.length]; System.arraycopy(val, 0, w, 0, val.length); System.arraycopy(Vi.val, 0, w, val.length, Vi.val.length); return new ExpVectorByte(w); } /** * Get the string representation. * @see java.lang.Object#toString() */ @Override public String toString() { return super.toString() + ":byte"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof ExpVectorByte)) { return false; } ExpVectorByte b = (ExpVectorByte) B; int t = this.invLexCompareTo(b); //System.out.println("equals: this = " + this + " B = " + B + " t = " + t); return (0 == t); } /** * hashCode for this exponent vector. * @see java.lang.Object#hashCode() Only for findbugs. */ @Override public int hashCode() { return super.hashCode(); } /** * ExpVector absolute value. * @return abs(this). */ @Override public ExpVectorByte abs() { byte[] u = val; byte[] w = new byte[u.length]; for (int i = 0; i < u.length; i++) { if (u[i] >= 0L) { w[i] = u[i]; } else { w[i] = (byte) (-u[i]); } } return new ExpVectorByte(w); //return EVABS(this); } /** * ExpVector negate. * @return -this. */ @Override public ExpVectorByte negate() { byte[] u = val; byte[] w = new byte[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (byte) (-u[i]); } return new ExpVectorByte(w); // return EVNEG(this); } /** * ExpVector summation. * @param V * @return this+V. */ @Override public ExpVectorByte sum(ExpVector V) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; byte[] w = new byte[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (byte) (u[i] + v[i]); } return new ExpVectorByte(w); // return EVSUM(this, V); } /** * ExpVector subtract. Result may have negative entries. * @param V * @return this-V. */ @Override public ExpVectorByte subtract(ExpVector V) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; byte[] w = new byte[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (byte) (u[i] - v[i]); } return new ExpVectorByte(w); //return EVDIF(this, V); } /** * ExpVector substitution. Clone and set exponent to d at position i. * @param i position. * @param d new exponent. * @return substituted ExpVector. */ public ExpVectorByte subst(int i, byte d) { ExpVectorByte V = this.copy(); @SuppressWarnings("unused") long e = V.setVal(i, d); return V; //return EVSU(this, i, d); } /** * ExpVector substitution. Clone and set exponent to d at position i. * @param i position. * @param d new exponent. * @return substituted ExpVector. */ @Override public ExpVectorByte subst(int i, long d) { ExpVectorByte V = this.copy(); @SuppressWarnings("unused") long e = V.setVal(i, d); return V; //return EVSU(this, i, d); } /** * ExpVector signum. * @return 0 if this is zero, -1 if some entry is negative, 1 if no entry is * negative and at least one entry is positive. */ @Override public int signum() { int t = 0; byte[] u = val; for (int i = 0; i < u.length; i++) { if (u[i] < 0) { return -1; } if (u[i] > 0) { t = 1; } } return t; //return EVSIGN(this); } /** * ExpVector total degree. * @return sum of all exponents. */ @Override public long totalDeg() { long t = 0; byte[] u = val; // U.val; for (int i = 0; i < u.length; i++) { t += u[i]; } return t; //return EVTDEG(this); } /** * ExpVector maximal degree. * @return maximal exponent. */ @Override public long maxDeg() { long t = 0; byte[] u = val; for (int i = 0; i < u.length; i++) { if (u[i] > t) { t = u[i]; } } return t; //return EVMDEG(this); } /** * ExpVector weighted degree. * @param w weights. * @return weighted sum of all exponents. */ @Override public long weightDeg(long[][] w) { if (w == null || w.length == 0) { return totalDeg(); // assume weight 1 } long t = 0; byte[] u = val; for (int j = 0; j < w.length; j++) { long[] wj = w[j]; for (int i = 0; i < u.length; i++) { t += wj[i] * u[i]; } } return t; //return EVWDEG( w, this ); } /** * ExpVector least common multiple. * @param V * @return component wise maximum of this and V. */ @Override public ExpVectorByte lcm(ExpVector V) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; byte[] w = new byte[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (u[i] >= v[i] ? u[i] : v[i]); } return new ExpVectorByte(w); //return EVLCM(this, V); } /** * ExpVector greatest common divisor. * @param V * @return component wise minimum of this and V. */ @Override public ExpVectorByte gcd(ExpVector V) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; byte[] w = new byte[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (u[i] <= v[i] ? u[i] : v[i]); } return new ExpVectorByte(w); //return EVGCD(this, V); } /** * ExpVector dependency on variables. * @return array of indices where val has positive exponents. */ @Override public int[] dependencyOnVariables() { byte[] u = val; int l = 0; for (int i = 0; i < u.length; i++) { if (u[i] > 0) { l++; } } int[] dep = new int[l]; if (l == 0) { return dep; } int j = 0; for (int i = 0; i < u.length; i++) { if (u[i] > 0) { dep[j] = i; j++; } } return dep; } /** * ExpVector multiple test. Test if this is component wise greater or equal * to V. * @param V * @return true if this is a multiple of V, else false. */ @Override public boolean multipleOf(ExpVector V) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; boolean t = true; for (int i = 0; i < u.length; i++) { if (u[i] < v[i]) { return false; } } return t; //return EVMT(this, V); } /** * ExpVector compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int compareTo(ExpVector V) { return this.invLexCompareTo(V); } /** * ExpVector inverse lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invLexCompareTo(ExpVector V) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; int t = 0; for (int i = 0; i < u.length; i++) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVILCP(this, V); } /** * ExpVector inverse lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invLexCompareTo(ExpVector V, int begin, int end) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; int t = 0; for (int i = begin; i < end; i++) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVILCP(this, V, begin, end); } /** * ExpVector inverse graded lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invGradCompareTo(ExpVector V) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; int t = 0; int i; for (i = 0; i < u.length; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j < u.length; j++) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVIGLC(this, V); } /** * ExpVector inverse graded lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invGradCompareTo(ExpVector V, int begin, int end) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; int t = 0; int i; for (i = begin; i < end; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j < end; j++) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVIGLC(this, V, begin, end); } /** * ExpVector reverse inverse lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvLexCompareTo(ExpVector V) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; int t = 0; for (int i = u.length - 1; i >= 0; i--) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVRILCP(this, V); } /** * ExpVector reverse inverse lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvLexCompareTo(ExpVector V, int begin, int end) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; int t = 0; for (int i = end - 1; i >= begin; i--) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVRILCP(this, V, begin, end); } /** * ExpVector reverse inverse graded compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvGradCompareTo(ExpVector V) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; int t = 0; int i; for (i = u.length - 1; i >= 0; i--) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j >= 0; j--) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVRIGLC(this, V); } /** * ExpVector reverse inverse graded compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvGradCompareTo(ExpVector V, int begin, int end) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; int t = 0; int i; for (i = end - 1; i >= begin; i--) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j >= begin; j--) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVRIGLC(this, V, begin, end); } /** * ExpVector inverse weighted lexicographical compareTo. * @param w weight array. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invWeightCompareTo(long[][] w, ExpVector V) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; int t = 0; int i; for (i = 0; i < u.length; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } for (int k = 0; k < w.length; k++) { long[] wk = w[k]; long up = 0; long vp = 0; for (int j = i; j < u.length; j++) { up += wk[j] * u[j]; vp += wk[j] * v[j]; } if (up > vp) { return 1; } else if (up < vp) { return -1; } } return t; //return EVIWLC(w, this, V); } /** * ExpVector inverse weighted lexicographical compareTo. * @param w weight array. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invWeightCompareTo(long[][] w, ExpVector V, int begin, int end) { byte[] u = val; byte[] v = ((ExpVectorByte) V).val; int t = 0; int i; for (i = begin; i < end; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } for (int k = 0; k < w.length; k++) { long[] wk = w[k]; long up = 0; long vp = 0; for (int j = i; j < end; j++) { up += wk[j] * u[j]; vp += wk[j] * v[j]; } if (up > vp) { return 1; } else if (up < vp) { return -1; } } return t; //return EVIWLC(w, this, V, begin, end); } } jas-2.5/src/edu/jas/poly/WordMonomial.java0000644000175000017500000000255612020707200020717 0ustar giovannigiovanni /* * $Id: WordMonomial.java 4155 2012-09-02 16:51:12Z kredel $ */ package edu.jas.poly; import java.util.Map; import java.util.SortedMap; import java.util.Iterator; import edu.jas.structure.RingElem; import edu.jas.poly.ExpVector; /** * WordMonomial class. * Represents pairs of words and coefficients. * Adaptor for Map.Entry. * @author Heinz Kredel */ public final class WordMonomial > { /** * Word of monomial. */ public final Word e; /** * Coefficient of monomial. */ public final C c; /** * Constructor of word monomial. * @param me a MapEntry. */ public WordMonomial(Map.Entry me){ this( me.getKey(), me.getValue() ); } /** * Constructor of word monomial. * @param e word. * @param c coefficient. */ public WordMonomial(Word e, C c) { this.e = e; this.c = c; } /** * Getter for word. * @return word. */ public Word word() { return e; } /** * Getter for coefficient. * @return coefficient. */ public C coefficient() { return c; } /** * String representation of Monomial. * @see java.lang.Object#toString() */ @Override public String toString() { return c.toString() + " " + e.toString(); } } jas-2.5/src/edu/jas/poly/GenPolynomialTokenizer.java0000644000175000017500000014301112067640742022772 0ustar giovannigiovanni/* * $Id: GenPolynomialTokenizer.java 4338 2012-12-29 19:17:54Z kredel $ */ package edu.jas.poly; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.io.StreamTokenizer; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Scanner; import java.util.Set; import java.util.TreeSet; import org.apache.log4j.Logger; import edu.jas.arith.BigComplex; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigInteger; import edu.jas.arith.BigQuaternion; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLongRing; import edu.jas.structure.Power; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * GenPolynomial Tokenizer. Used to read rational polynomials and lists of * polynomials from input streams. Arbitrary polynomial rings and coefficient * rings can be read with RingFactoryTokenizer. Note: Can no more read * QuotientRing since end of 2010, revision 3441. Quotient coefficients and * others can still be read if the respective factory is provided via the * constructor. * @see edu.jas.application.RingFactoryTokenizer * @author Heinz Kredel */ public class GenPolynomialTokenizer { private static final Logger logger = Logger.getLogger(GenPolynomialTokenizer.class); private final boolean debug = logger.isDebugEnabled(); private String[] vars; private int nvars = 1; private TermOrder tord; private RelationTable table; //private Reader in; private final StreamTokenizer tok; private final Reader reader; private RingFactory fac; private static enum coeffType { BigRat, BigInt, ModInt, BigC, BigQ, BigD, ANrat, ANmod, IntFunc }; private coeffType parsedCoeff = coeffType.BigRat; private GenPolynomialRing pfac; private static enum polyType { PolBigRat, PolBigInt, PolModInt, PolBigC, PolBigD, PolBigQ, PolANrat, PolANmod, PolIntFunc }; private polyType parsedPoly = polyType.PolBigRat; private GenSolvablePolynomialRing spfac; /** * noargs constructor reads from System.in. */ public GenPolynomialTokenizer() { this(new BufferedReader(new InputStreamReader(System.in,Charset.forName("UTF8")))); } /** * constructor with Ring and Reader. * @param rf ring factory. * @param r reader stream. */ public GenPolynomialTokenizer(GenPolynomialRing rf, Reader r) { this(r); if (rf == null) { return; } if (rf instanceof GenSolvablePolynomialRing) { pfac = rf; spfac = (GenSolvablePolynomialRing) rf; } else { pfac = rf; spfac = null; } fac = rf.coFac; vars = rf.vars; if (vars != null) { nvars = vars.length; } tord = rf.tord; // relation table if (spfac != null) { table = spfac.table; } else { table = null; } } /** * constructor with Reader. * @param r reader stream. */ @SuppressWarnings("unchecked") public GenPolynomialTokenizer(Reader r) { //BasicConfigurator.configure(); vars = null; tord = new TermOrder(); nvars = 1; fac = new BigRational(1); pfac = new GenPolynomialRing(fac, nvars, tord, vars); spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); reader = r; tok = new StreamTokenizer(reader); tok.resetSyntax(); // tok.eolIsSignificant(true); no more tok.eolIsSignificant(false); tok.wordChars('0', '9'); tok.wordChars('a', 'z'); tok.wordChars('A', 'Z'); tok.wordChars('_', '_'); // for subscripts x_i tok.wordChars('/', '/'); // wg. rational numbers tok.wordChars(128 + 32, 255); tok.whitespaceChars(0, ' '); tok.commentChar('#'); tok.quoteChar('"'); tok.quoteChar('\''); //tok.slashStarComments(true); does not work } /** * Initialize coefficient and polynomial factories. * @param rf ring factory. * @param ct coefficient type. */ @SuppressWarnings("unchecked") public void initFactory(RingFactory rf, coeffType ct) { fac = rf; parsedCoeff = ct; switch (ct) { case BigRat: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigRat; break; case BigInt: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigInt; break; case ModInt: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolModInt; break; case BigC: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigC; break; case BigQ: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigQ; break; case BigD: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigD; break; case IntFunc: pfac = new GenPolynomialRing>(fac, nvars, tord, vars); parsedPoly = polyType.PolIntFunc; break; default: pfac = new GenPolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigRat; } } /** * Initialize polynomial and solvable polynomial factories. * @param rf ring factory. * @param ct coefficient type. */ @SuppressWarnings("unchecked") public void initSolvableFactory(RingFactory rf, coeffType ct) { fac = rf; parsedCoeff = ct; switch (ct) { case BigRat: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigRat; break; case BigInt: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigInt; break; case ModInt: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolModInt; break; case BigC: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigC; break; case BigQ: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigQ; break; case BigD: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigD; break; case IntFunc: spfac = new GenSolvablePolynomialRing>(fac, nvars, tord, vars); parsedPoly = polyType.PolIntFunc; break; default: spfac = new GenSolvablePolynomialRing(fac, nvars, tord, vars); parsedPoly = polyType.PolBigRat; } } /** * Parsing method for GenPolynomial. syntax ? (simple) * @return the next polynomial. * @throws IOException */ @SuppressWarnings("unchecked") public GenPolynomial nextPolynomial() throws IOException { if (debug) { logger.debug("torder = " + tord); } GenPolynomial a = pfac.getZERO(); GenPolynomial a1 = pfac.getONE(); ExpVector leer = pfac.evzero; if (debug) { logger.debug("a = " + a); logger.debug("a1 = " + a1); } GenPolynomial b = a1; GenPolynomial c; int tt; //, oldtt; //String rat = ""; char first; RingElem r; ExpVector e; int ix; long ie; boolean done = false; while (!done) { // next input. determine next action tt = tok.nextToken(); //System.out.println("while tt = " + tok); logger.debug("while tt = " + tok); if (tt == StreamTokenizer.TT_EOF) break; switch (tt) { case ')': case ',': return a; // do not change or remove case '-': b = b.negate(); case '+': case '*': tt = tok.nextToken(); break; default: // skip } // read coefficient, monic monomial and polynomial if (tt == StreamTokenizer.TT_EOF) break; switch (tt) { // case '_': removed case '}': throw new InvalidExpressionException("mismatch of braces after " + a + ", error at " + b); case '{': // recursion StringBuffer rf = new StringBuffer(); int level = 0; do { tt = tok.nextToken(); //System.out.println("token { = " + ((char)tt) + ", " + tt + ", level = " + level); if (tt == StreamTokenizer.TT_EOF) { throw new InvalidExpressionException("mismatch of braces after " + a + ", error at " + b); } if (tt == '{') { level++; } if (tt == '}') { level--; if (level < 0) { continue; // skip last closing brace } } if (tok.sval != null) { if (rf.length() > 0 && rf.charAt(rf.length() - 1) != '.') { rf.append(" "); } rf.append(tok.sval); // " " + } else { rf.append((char) tt); } } while (level >= 0); //System.out.println("coeff{} = " + rf.toString() ); try { r = (RingElem) fac.parse(rf.toString()); } catch (NumberFormatException re) { throw new InvalidExpressionException("not a number " + rf, re); } if (debug) logger.debug("coeff " + r); ie = nextExponent(); if (debug) logger.debug("ie " + ie); r = Power. positivePower(r, ie); if (debug) logger.debug("coeff^ie " + r); b = b.multiply(r, leer); tt = tok.nextToken(); if (debug) logger.debug("tt,digit = " + tok); //no break; break; case StreamTokenizer.TT_WORD: //System.out.println("TT_WORD: " + tok.sval); if (tok.sval == null || tok.sval.length() == 0) break; // read coefficient first = tok.sval.charAt(0); if (digit(first)) { //System.out.println("coeff 0 = " + tok.sval ); StringBuffer df = new StringBuffer(); df.append(tok.sval); if (tok.sval.charAt(tok.sval.length() - 1) == 'i') { // complex number tt = tok.nextToken(); if (debug) logger.debug("tt,im = " + tok); if (tok.sval != null || tt == '-') { if (tok.sval != null) { df.append(tok.sval); } else { df.append("-"); } if (tt == '-') { tt = tok.nextToken(); // todo: decimal number if (tok.sval != null && digit(tok.sval.charAt(0))) { df.append(tok.sval); } else { tok.pushBack(); } } } else { tok.pushBack(); } } tt = tok.nextToken(); if (tt == '.') { // decimal number tt = tok.nextToken(); if (debug) logger.debug("tt,dot = " + tok); if (tok.sval != null) { df.append("."); df.append(tok.sval); } else { tok.pushBack(); tok.pushBack(); } } else { tok.pushBack(); } try { r = (RingElem) fac.parse(df.toString()); } catch (NumberFormatException re) { throw new InvalidExpressionException("not a number " + df, re); } if (debug) logger.debug("coeff " + r); //System.out.println("r = " + r.toScriptFactory()); ie = nextExponent(); if (debug) logger.debug("ie " + ie); // r = r^ie; r = Power. positivePower(r, ie); if (debug) logger.debug("coeff^ie " + r); b = b.multiply(r, leer); tt = tok.nextToken(); if (debug) logger.debug("tt,digit = " + tok); } if (tt == StreamTokenizer.TT_EOF) break; if (tok.sval == null) break; // read monomial or recursion first = tok.sval.charAt(0); if (letter(first)) { ix = leer.indexVar(tok.sval, vars); //indexVar( tok.sval ); if (ix < 0) { // not found try { r = (RingElem) fac.parse(tok.sval); } catch (NumberFormatException re) { throw new InvalidExpressionException("recursively unknown variable " + tok.sval); } if (debug) logger.info("coeff " + r); //if (r.isONE() || r.isZERO()) { //logger.error("Unknown varibable " + tok.sval); //done = true; //break; //throw new InvalidExpressionException("recursively unknown variable " + tok.sval); //} ie = nextExponent(); // System.out.println("ie: " + ie); r = Power. positivePower(r, ie); b = b.multiply(r); } else { // found // System.out.println("ix: " + ix); ie = nextExponent(); // System.out.println("ie: " + ie); e = ExpVector.create(vars.length, ix, ie); b = b.multiply(e); } tt = tok.nextToken(); if (debug) logger.debug("tt,letter = " + tok); } break; case '(': c = nextPolynomial(); if (debug) logger.debug("factor " + c); ie = nextExponent(); if (debug) logger.debug("ie " + ie); c = Power. positivePower(c, ie); if (debug) logger.debug("factor^ie " + c); b = b.multiply(c); tt = tok.nextToken(); if (debug) logger.debug("tt,digit = " + tok); //no break; break; default: //skip } if (done) break; // unknown variable if (tt == StreamTokenizer.TT_EOF) break; // complete polynomial tok.pushBack(); switch (tt) { case '-': case '+': case ')': case ',': logger.debug("b, = " + b); a = a.sum(b); b = a1; break; case '*': logger.debug("b, = " + b); //a = a.sum(b); //b = a1; break; case '\n': tt = tok.nextToken(); if (debug) logger.debug("tt,nl = " + tt); break; default: // skip or finish ? if (debug) logger.debug("default: " + tok); } } if (debug) logger.debug("b = " + b); a = a.sum(b); logger.debug("a = " + a); // b = a1; return a; } /** * Parsing method for exponent (of variable). syntax: ^long | **long. * @return the next exponent or 1. * @throws IOException */ public long nextExponent() throws IOException { long e = 1; char first; int tt; tt = tok.nextToken(); if (tt == '^') { if (debug) logger.debug("exponent ^"); tt = tok.nextToken(); if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { e = Long.parseLong(tok.sval); return e; } } } if (tt == '*') { tt = tok.nextToken(); if (tt == '*') { if (debug) logger.debug("exponent **"); tt = tok.nextToken(); if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { e = Long.parseLong(tok.sval); return e; } } } tok.pushBack(); } tok.pushBack(); return e; } /** * Parsing method for comments. syntax: (* comment *) | /_* comment *_/ * without _ Does not work with this pushBack(), unused. */ public String nextComment() throws IOException { // syntax: (* comment *) | /* comment */ StringBuffer c = new StringBuffer(); int tt; if (debug) logger.debug("comment: " + tok); tt = tok.nextToken(); if (debug) logger.debug("comment: " + tok); if (tt == '(') { tt = tok.nextToken(); if (debug) logger.debug("comment: " + tok); if (tt == '*') { if (debug) logger.debug("comment: "); while (true) { tt = tok.nextToken(); if (tt == '*') { tt = tok.nextToken(); if (tt == ')') { return c.toString(); } tok.pushBack(); } c.append(tok.sval); } } tok.pushBack(); if (debug) logger.debug("comment: " + tok); } tok.pushBack(); if (debug) logger.debug("comment: " + tok); return c.toString(); } /** * Parsing method for variable list. syntax: (a, b c, de) gives [ "a", "b", * "c", "de" ] * @return the next variable list. * @throws IOException */ public String[] nextVariableList() throws IOException { List l = new ArrayList(); int tt; tt = tok.nextToken(); //System.out.println("vList tok = " + tok); if (tt == '(' || tt == '{') { logger.debug("variable list"); tt = tok.nextToken(); while (true) { if (tt == StreamTokenizer.TT_EOF) break; if (tt == ')' || tt == '}') break; if (tt == StreamTokenizer.TT_WORD) { //System.out.println("TT_WORD: " + tok.sval); l.add(tok.sval); } tt = tok.nextToken(); } } Object[] ol = l.toArray(); String[] v = new String[ol.length]; for (int i = 0; i < v.length; i++) { v[i] = (String) ol[i]; } return v; } /** * Parsing method for coefficient ring. syntax: Rat | Q | Int | Z | Mod * modul | Complex | C | D | Quat | AN[ (var) ( poly ) ] | AN[ modul (var) ( * poly ) ] | IntFunc (var_list) * @return the next coefficient factory. * @throws IOException */ @SuppressWarnings("unchecked") public RingFactory nextCoefficientRing() throws IOException { RingFactory coeff = null; coeffType ct = null; int tt; tt = tok.nextToken(); if (tok.sval != null) { if (tok.sval.equalsIgnoreCase("Q")) { coeff = new BigRational(0); ct = coeffType.BigRat; } else if (tok.sval.equalsIgnoreCase("Rat")) { coeff = new BigRational(0); ct = coeffType.BigRat; } else if (tok.sval.equalsIgnoreCase("D")) { coeff = new BigDecimal(0); ct = coeffType.BigD; } else if (tok.sval.equalsIgnoreCase("Z")) { coeff = new BigInteger(0); ct = coeffType.BigInt; } else if (tok.sval.equalsIgnoreCase("Int")) { coeff = new BigInteger(0); ct = coeffType.BigInt; } else if (tok.sval.equalsIgnoreCase("C")) { coeff = new BigComplex(0); ct = coeffType.BigC; } else if (tok.sval.equalsIgnoreCase("Complex")) { coeff = new BigComplex(0); ct = coeffType.BigC; } else if (tok.sval.equalsIgnoreCase("Quat")) { coeff = new BigQuaternion(0); ct = coeffType.BigQ; } else if (tok.sval.equalsIgnoreCase("Mod")) { tt = tok.nextToken(); boolean openb = false; if (tt == '[') { // optional openb = true; tt = tok.nextToken(); } if (tok.sval != null && tok.sval.length() > 0) { if (digit(tok.sval.charAt(0))) { BigInteger mo = new BigInteger(tok.sval); BigInteger lm = new BigInteger(ModLongRing.MAX_LONG); //wrong: Long.MAX_VALUE); if (mo.compareTo(lm) < 0) { coeff = new ModLongRing(mo.getVal()); } else { coeff = new ModIntegerRing(mo.getVal()); } //System.out.println("coeff = " + coeff + " :: " + coeff.getClass()); ct = coeffType.ModInt; } else { tok.pushBack(); } } else { tok.pushBack(); } if (tt == ']' && openb) { // optional tt = tok.nextToken(); } } else if (tok.sval.equalsIgnoreCase("RatFunc") || tok.sval.equalsIgnoreCase("ModFunc")) { //logger.error("RatFunc and ModFunc can no more be read, see edu.jas.application.RingFactoryTokenizer."); throw new InvalidExpressionException( "RatFunc and ModFunc can no more be read, see edu.jas.application.RingFactoryTokenizer."); } else if (tok.sval.equalsIgnoreCase("IntFunc")) { String[] rfv = nextVariableList(); //System.out.println("rfv = " + rfv.length + " " + rfv[0]); int vr = rfv.length; BigRational bi = new BigRational(); TermOrder to = new TermOrder(TermOrder.INVLEX); GenPolynomialRing pcf = new GenPolynomialRing(bi, vr, to, rfv); coeff = pcf; ct = coeffType.IntFunc; } else if (tok.sval.equalsIgnoreCase("AN")) { tt = tok.nextToken(); if (tt == '[') { tt = tok.nextToken(); RingFactory tcfac = new ModIntegerRing("19"); if (tok.sval != null && tok.sval.length() > 0) { if (digit(tok.sval.charAt(0))) { tcfac = new ModIntegerRing(tok.sval); } else { tcfac = new BigRational(); tok.pushBack(); } } else { tcfac = new BigRational(); tok.pushBack(); } String[] anv = nextVariableList(); //System.out.println("anv = " + anv.length + " " + anv[0]); int vs = anv.length; if (vs != 1) { throw new InvalidExpressionException( "AlgebraicNumber only for univariate polynomials " + Arrays.toString(anv)); } String[] ovars = vars; vars = anv; GenPolynomialRing tpfac = pfac; RingFactory tfac = fac; fac = tcfac; // pfac and fac used in nextPolynomial() if (tcfac instanceof ModIntegerRing) { pfac = new GenPolynomialRing(tcfac, vs, new TermOrder(), anv); } else { pfac = new GenPolynomialRing(tcfac, vs, new TermOrder(), anv); } if (debug) { logger.debug("pfac = " + pfac); } tt = tok.nextToken(); GenPolynomial mod; if (tt == '(') { mod = nextPolynomial(); tt = tok.nextToken(); if (tok.ttype != ')') tok.pushBack(); } else { tok.pushBack(); mod = nextPolynomial(); } if (debug) { logger.debug("mod = " + mod); } pfac = tpfac; fac = tfac; vars = ovars; if (tcfac instanceof ModIntegerRing) { GenPolynomial gfmod; gfmod = (GenPolynomial) mod; coeff = new AlgebraicNumberRing(gfmod); ct = coeffType.ANmod; } else { GenPolynomial anmod; anmod = (GenPolynomial) mod; coeff = new AlgebraicNumberRing(anmod); ct = coeffType.ANrat; } if (debug) { logger.debug("coeff = " + coeff); } tt = tok.nextToken(); if (tt == ']') { //ok, no nextToken(); } else { tok.pushBack(); } } else { tok.pushBack(); } } } if (coeff == null) { tok.pushBack(); coeff = new BigRational(); ct = coeffType.BigRat; } parsedCoeff = ct; return coeff; } /** * Parsing method for weight list. syntax: (w1, w2, w3, ..., wn) * @return the next weight list. * @throws IOException */ public long[] nextWeightList() throws IOException { List l = new ArrayList(); long[] w = null; long e; char first; int tt; tt = tok.nextToken(); if (tt == '(') { logger.debug("weight list"); tt = tok.nextToken(); while (true) { if (tt == StreamTokenizer.TT_EOF) break; if (tt == ')') break; if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { e = Long.parseLong(tok.sval); l.add(Long.valueOf(e)); //System.out.println("w: " + e); } } tt = tok.nextToken(); // also comma } } Object[] ol = l.toArray(); w = new long[ol.length]; for (int i = 0; i < w.length; i++) { w[i] = ((Long) ol[ol.length - i - 1]).longValue(); } return w; } /** * Parsing method for weight array. syntax: ( (w11, ...,w1n), ..., (wm1, * ..., wmn) ) * @return the next weight array. * @throws IOException */ public long[][] nextWeightArray() throws IOException { List l = new ArrayList(); long[][] w = null; long[] e; char first; int tt; tt = tok.nextToken(); if (tt == '(') { logger.debug("weight array"); tt = tok.nextToken(); while (true) { if (tt == StreamTokenizer.TT_EOF) break; if (tt == ')') break; if (tt == '(') { tok.pushBack(); e = nextWeightList(); l.add(e); //System.out.println("wa: " + e); } else if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { tok.pushBack(); tok.pushBack(); e = nextWeightList(); l.add(e); break; //System.out.println("w: " + e); } } tt = tok.nextToken(); // also comma } } Object[] ol = l.toArray(); w = new long[ol.length][]; for (int i = 0; i < w.length; i++) { w[i] = (long[]) ol[i]; } return w; } /** * Parsing method for split index. syntax: |i| * @return the next split index. * @throws IOException */ public int nextSplitIndex() throws IOException { int e = -1; // =unknown int e0 = -1; // =unknown char first; int tt; tt = tok.nextToken(); if (tt == '|') { logger.debug("split index"); tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) { return e; } if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { e = Integer.parseInt(tok.sval); //System.out.println("w: " + i); } tt = tok.nextToken(); if (tt != '|') { tok.pushBack(); } } } else if (tt == '[') { logger.debug("split index"); tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) { return e; } if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { e0 = Integer.parseInt(tok.sval); //System.out.println("w: " + i); } tt = tok.nextToken(); if (tt == ',') { tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) { return e0; } if (tok.sval != null) { first = tok.sval.charAt(0); if (digit(first)) { e = Integer.parseInt(tok.sval); //System.out.println("w: " + i); } } if (tt != ']') { tok.pushBack(); } } } } else { tok.pushBack(); } return e; } /** * Parsing method for term order name. syntax: termOrderName = L, IL, LEX, * G, IG, GRLEX, W(weights) |split index| * @return the next term order. * @throws IOException */ public TermOrder nextTermOrder() throws IOException { int evord = TermOrder.DEFAULT_EVORD; int tt; tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) { /* nop */ } else if (tt == StreamTokenizer.TT_WORD) { // System.out.println("TT_WORD: " + tok.sval); if (tok.sval != null) { if (tok.sval.equalsIgnoreCase("L")) { evord = TermOrder.INVLEX; } else if (tok.sval.equalsIgnoreCase("IL")) { evord = TermOrder.INVLEX; } else if (tok.sval.equalsIgnoreCase("INVLEX")) { evord = TermOrder.INVLEX; } else if (tok.sval.equalsIgnoreCase("LEX")) { evord = TermOrder.LEX; } else if (tok.sval.equalsIgnoreCase("G")) { evord = TermOrder.IGRLEX; } else if (tok.sval.equalsIgnoreCase("IG")) { evord = TermOrder.IGRLEX; } else if (tok.sval.equalsIgnoreCase("IGRLEX")) { evord = TermOrder.IGRLEX; } else if (tok.sval.equalsIgnoreCase("GRLEX")) { evord = TermOrder.GRLEX; } else if (tok.sval.equalsIgnoreCase("W")) { long[][] w = nextWeightArray(); //int s = nextSplitIndex(); // no more return new TermOrder(w); } } } int s = nextSplitIndex(); if (s <= 0) { return new TermOrder(evord); } return new TermOrder(evord, evord, vars.length, s); } /** * Parsing method for polynomial list. syntax: ( p1, p2, p3, ..., pn ) * @return the next polynomial list. * @throws IOException */ public List nextPolynomialList() throws IOException { GenPolynomial a; List L = new ArrayList(); int tt; tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) return L; if (tt != '(') return L; logger.debug("polynomial list"); while (true) { tt = tok.nextToken(); if (tok.ttype == ',') continue; if (tt == '(') { a = nextPolynomial(); tt = tok.nextToken(); if (tok.ttype != ')') tok.pushBack(); } else { tok.pushBack(); a = nextPolynomial(); } logger.info("next pol = " + a); L.add(a); if (tok.ttype == StreamTokenizer.TT_EOF) break; if (tok.ttype == ')') break; } return L; } /** * Parsing method for submodule list. syntax: ( ( p11, p12, p13, ..., p1n ), * ..., ( pm1, pm2, pm3, ..., pmn ) ) * @return the next list of polynomial lists. * @throws IOException */ public List> nextSubModuleList() throws IOException { List> L = new ArrayList>(); int tt; tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) return L; if (tt != '(') return L; logger.debug("module list"); List v = null; while (true) { tt = tok.nextToken(); if (tok.ttype == ',') continue; if (tok.ttype == ')') break; if (tok.ttype == StreamTokenizer.TT_EOF) break; if (tt == '(') { tok.pushBack(); v = nextPolynomialList(); logger.info("next vect = " + v); L.add(v); } } return L; } /** * Parsing method for solvable polynomial relation table. syntax: ( p_1, * p_2, p_3, ..., p_{n+3} ) semantics: p_{n+1} * p_{n+2} = p_{n+3} The next * relation table is stored into the solvable polynomial factory. * @throws IOException */ @SuppressWarnings("unchecked") public void nextRelationTable() throws IOException { if (spfac == null) { return; } RelationTable table = spfac.table; List rels = null; GenPolynomial p; GenSolvablePolynomial sp; int tt; tt = tok.nextToken(); if (debug) { logger.debug("relation table: " + tt); } if (tok.sval != null) { if (tok.sval.equalsIgnoreCase("RelationTable")) { rels = nextPolynomialList(); } } if (rels == null) { tok.pushBack(); return; } for (Iterator it = rels.iterator(); it.hasNext();) { p = it.next(); ExpVector e = p.leadingExpVector(); if (it.hasNext()) { p = it.next(); ExpVector f = p.leadingExpVector(); if (it.hasNext()) { p = it.next(); sp = new GenSolvablePolynomial(spfac, p.val); table.update(e, f, sp); } } } if (debug) { logger.info("table = " + table); } return; } /** * Parsing method for polynomial set. syntax: coeffRing varList * termOrderName polyList. * @return the next polynomial set. * @throws IOException */ @SuppressWarnings("unchecked") public PolynomialList nextPolynomialSet() throws IOException { //String comments = ""; //comments += nextComment(); //if (debug) logger.debug("comment = " + comments); RingFactory coeff = nextCoefficientRing(); logger.info("coeff = " + coeff.getClass().getSimpleName()); vars = nextVariableList(); logger.info("vars = " + Arrays.toString(vars)); if (vars != null) { nvars = vars.length; } tord = nextTermOrder(); logger.info("tord = " + tord); // check more TOs initFactory(coeff, parsedCoeff); // global: nvars, tord, vars List s = null; s = nextPolynomialList(); logger.info("s = " + s); // comments += nextComment(); return new PolynomialList(pfac, s); } /** * Parsing method for module set. syntax: coeffRing varList termOrderName * moduleList. * @return the next module set. * @throws IOException */ @SuppressWarnings("unchecked") public ModuleList nextSubModuleSet() throws IOException { //String comments = ""; //comments += nextComment(); //if (debug) logger.debug("comment = " + comments); RingFactory coeff = nextCoefficientRing(); logger.info("coeff = " + coeff.getClass().getSimpleName()); vars = nextVariableList(); logger.info("vars = " + Arrays.toString(vars)); if (vars != null) { nvars = vars.length; } tord = nextTermOrder(); logger.info("tord = " + tord); // check more TOs initFactory(coeff, parsedCoeff); // global: nvars, tord, vars List> m = null; m = nextSubModuleList(); logger.info("m = " + m); // comments += nextComment(); return new ModuleList(pfac, m); } /** * Parsing method for solvable polynomial list. syntax: ( p1, p2, p3, ..., * pn ) * @return the next solvable polynomial list. * @throws IOException */ @SuppressWarnings("unchecked") public List nextSolvablePolynomialList() throws IOException { List s = nextPolynomialList(); logger.info("s = " + s); // comments += nextComment(); GenPolynomial p; GenSolvablePolynomial ps; List sp = new ArrayList(s.size()); for (Iterator it = s.iterator(); it.hasNext();) { p = it.next(); ps = new GenSolvablePolynomial(spfac, p.val); //System.out.println("ps = " + ps); sp.add(ps); } return sp; } /** * Parsing method for solvable polynomial. syntax: p. * @return the next polynomial. * @throws IOException */ @SuppressWarnings("unchecked") public GenSolvablePolynomial nextSolvablePolynomial() throws IOException { GenPolynomial p = nextPolynomial(); logger.info("p = " + p); // comments += nextComment(); GenSolvablePolynomial ps = new GenSolvablePolynomial(spfac, p.val); //System.out.println("ps = " + ps); return ps; } /** * Parsing method for solvable polynomial set. syntax: varList termOrderName * relationTable polyList. * @return the next solvable polynomial set. * @throws IOException */ @SuppressWarnings("unchecked") public PolynomialList nextSolvablePolynomialSet() throws IOException { //String comments = ""; //comments += nextComment(); //if (debug) logger.debug("comment = " + comments); RingFactory coeff = nextCoefficientRing(); logger.info("coeff = " + coeff.getClass().getSimpleName()); vars = nextVariableList(); logger.info("vars = " + Arrays.toString(vars)); if (vars != null) { nvars = vars.length; } tord = nextTermOrder(); logger.info("tord = " + tord); // check more TOs initFactory(coeff, parsedCoeff); // must be because of symmetric read initSolvableFactory(coeff, parsedCoeff); // global: nvars, tord, vars //System.out.println("pfac = " + pfac); //System.out.println("spfac = " + spfac); nextRelationTable(); if (logger.isInfoEnabled()) { logger.info("table = " + table); } List s = null; s = nextSolvablePolynomialList(); logger.info("s = " + s); // comments += nextComment(); return new PolynomialList(spfac, s); // Ordered ? } /** * Parsing method for solvable submodule list. syntax: ( ( p11, p12, p13, * ..., p1n ), ..., ( pm1, pm2, pm3, ..., pmn ) ) * @return the next list of solvable polynomial lists. * @throws IOException */ public List> nextSolvableSubModuleList() throws IOException { List> L = new ArrayList>(); int tt; tt = tok.nextToken(); if (tt == StreamTokenizer.TT_EOF) return L; if (tt != '(') return L; logger.debug("module list"); List v = null; while (true) { tt = tok.nextToken(); if (tok.ttype == ',') continue; if (tok.ttype == ')') break; if (tok.ttype == StreamTokenizer.TT_EOF) break; if (tt == '(') { tok.pushBack(); v = nextSolvablePolynomialList(); logger.info("next vect = " + v); L.add(v); } } return L; } /** * Parsing method for solvable module set. syntax: varList termOrderName * relationTable moduleList. * @return the next solvable module set. * @throws IOException */ @SuppressWarnings("unchecked") public ModuleList nextSolvableSubModuleSet() throws IOException { //String comments = ""; //comments += nextComment(); //if (debug) logger.debug("comment = " + comments); RingFactory coeff = nextCoefficientRing(); logger.info("coeff = " + coeff.getClass().getSimpleName()); vars = nextVariableList(); logger.info("vars = " + Arrays.toString(vars)); if (vars != null) { nvars = vars.length; } tord = nextTermOrder(); logger.info("tord = " + tord); // check more TOs initFactory(coeff, parsedCoeff); // must be because of symmetric read initSolvableFactory(coeff, parsedCoeff); // global: nvars, tord, vars //System.out.println("spfac = " + spfac); nextRelationTable(); if (logger.isInfoEnabled()) { logger.info("table = " + table); } List> s = null; s = nextSolvableSubModuleList(); logger.info("s = " + s); // comments += nextComment(); return new OrderedModuleList(spfac, s); // Ordered } // must also allow +/- // does not work with tokenizer //private static boolean number(char x) { // return digit(x) || x == '-' || x == '+'; //} private static boolean digit(char x) { return '0' <= x && x <= '9'; } private static boolean letter(char x) { return ('a' <= x && x <= 'z') || ('A' <= x && x <= 'Z'); } // unused public void nextComma() throws IOException { int tt; if (tok.ttype == ',') { tt = tok.nextToken(); if (debug) { logger.debug("after comma: " + tt); } } } /** * Parse variable list from String. * @param s String. Syntax: (n1,...,nk) or (n1 ... nk), parenthesis are also * optional. * @return array of variable names found in s. */ public static String[] variableList(String s) { String[] vl = null; if (s == null) { return vl; } String st = s.trim(); if (st.length() == 0) { return new String[0]; } if (st.charAt(0) == '(') { st = st.substring(1); } if (st.charAt(st.length() - 1) == ')') { st = st.substring(0, st.length() - 1); } st = st.replaceAll(",", " "); List sl = new ArrayList(); Scanner sc = new Scanner(st); while (sc.hasNext()) { String sn = sc.next(); sl.add(sn); } vl = new String[sl.size()]; int i = 0; for (String si : sl) { vl[i] = si; i++; } return vl; } /** * Extract variable list from expression. * @param s String. Syntax: any polynomial expression. * @return array of variable names found in s. */ public static String[] expressionVariables(String s) { String[] vl = null; if (s == null) { return vl; } String st = s.trim(); if (st.length() == 0) { return new String[0]; } st = st.replaceAll(",", " "); st = st.replaceAll("\\+", " "); st = st.replaceAll("-", " "); st = st.replaceAll("\\*", " "); st = st.replaceAll("/", " "); st = st.replaceAll("\\(", " "); st = st.replaceAll("\\)", " "); st = st.replaceAll("\\{", " "); st = st.replaceAll("\\}", " "); st = st.replaceAll("\\[", " "); st = st.replaceAll("\\]", " "); st = st.replaceAll("\\^", " "); //System.out.println("st = " + st); Set sl = new TreeSet(); Scanner sc = new Scanner(st); while (sc.hasNext()) { String sn = sc.next(); if (sn == null || sn.length() == 0) { continue; } //System.out.println("sn = " + sn); int i = 0; while (digit(sn.charAt(i)) && i < sn.length() - 1) { i++; } //System.out.println("sn = " + sn + ", i = " + i); if (i > 0) { sn = sn.substring(i, sn.length()); } //System.out.println("sn = " + sn); if (sn.length() == 0) { continue; } if (!letter(sn.charAt(0))) { continue; } //System.out.println("sn = " + sn); sl.add(sn); } vl = new String[sl.size()]; int i = 0; for (String si : sl) { vl[i] = si; i++; } return vl; } } jas-2.5/src/edu/jas/poly/PolyUtil.java0000644000175000017500000033773112136530130020103 0ustar giovannigiovanni/* * $Id: PolyUtil.java 4378 2013-04-26 16:50:33Z kredel $ */ package edu.jas.poly; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.arith.BigComplex; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.Modular; import edu.jas.arith.ModularRingFactory; import edu.jas.arith.Product; import edu.jas.arith.ProductRing; import edu.jas.arith.Rational; import edu.jas.structure.Element; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.UnaryFunctor; import edu.jas.util.ListUtil; /** * Polynomial utilities, for example conversion between different * representations, evaluation and interpolation. * @author Heinz Kredel */ public class PolyUtil { private static final Logger logger = Logger.getLogger(PolyUtil.class); private static boolean debug = logger.isDebugEnabled(); /** * Recursive representation. Represent as polynomial in i variables with * coefficients in n-i variables. Works for arbitrary term orders. * @param coefficient type. * @param rfac recursive polynomial ring factory. * @param A polynomial to be converted. * @return Recursive represenations of this in the ring rfac. */ public static > GenPolynomial> recursive( GenPolynomialRing> rfac, GenPolynomial A) { GenPolynomial> B = rfac.getZERO().copy(); if (A.isZERO()) { return B; } int i = rfac.nvar; GenPolynomial zero = rfac.getZEROCoefficient(); Map> Bv = B.val; //getMap(); for (Map.Entry y : A.getMap().entrySet()) { ExpVector e = y.getKey(); C a = y.getValue(); ExpVector f = e.contract(0, i); ExpVector g = e.contract(i, e.length() - i); GenPolynomial p = Bv.get(f); if (p == null) { p = zero; } p = p.sum(a, g); Bv.put(f, p); } return B; } /** * Distribute a recursive polynomial to a generic polynomial. Works for * arbitrary term orders. * @param coefficient type. * @param dfac combined polynomial ring factory of coefficients and this. * @param B polynomial to be converted. * @return distributed polynomial. */ public static > GenPolynomial distribute(GenPolynomialRing dfac, GenPolynomial> B) { GenPolynomial C = dfac.getZERO().copy(); if (B.isZERO()) { return C; } Map Cm = C.val; //getMap(); for (Map.Entry> y : B.getMap().entrySet()) { ExpVector e = y.getKey(); GenPolynomial A = y.getValue(); for (Map.Entry x : A.val.entrySet()) { ExpVector f = x.getKey(); C b = x.getValue(); ExpVector g = e.combine(f); assert (Cm.get(g) != null); //if ( Cm.get(g) != null ) { // todo assert, done // throw new RuntimeException("PolyUtil debug error"); //} Cm.put(g, b); } } return C; } /** * Recursive representation. Represent as polynomials in i variables with * coefficients in n-i variables. Works for arbitrary term orders. * @param coefficient type. * @param rfac recursive polynomial ring factory. * @param L list of polynomials to be converted. * @return Recursive represenations of the list in the ring rfac. */ public static > List>> recursive( GenPolynomialRing> rfac, List> L) { return ListUtil., GenPolynomial>> map(L, new DistToRec(rfac)); } /** * Distribute a recursive polynomial list to a generic polynomial list. * Works for arbitrary term orders. * @param coefficient type. * @param dfac combined polynomial ring factory of coefficients and this. * @param L list of polynomials to be converted. * @return distributed polynomial list. */ public static > List> distribute(GenPolynomialRing dfac, List>> L) { return ListUtil.>, GenPolynomial> map(L, new RecToDist(dfac)); } /** * BigInteger from ModInteger coefficients, symmetric. Represent as * polynomial with BigInteger coefficients by removing the modules and * making coefficients symmetric to 0. * @param fac result polynomial factory. * @param A polynomial with ModInteger coefficients to be converted. * @return polynomial with BigInteger coefficients. */ public static & Modular> GenPolynomial integerFromModularCoefficients( GenPolynomialRing fac, GenPolynomial A) { return PolyUtil. map(fac, A, new ModSymToInt()); } /** * BigInteger from ModInteger coefficients, symmetric. Represent as * polynomial with BigInteger coefficients by removing the modules and * making coefficients symmetric to 0. * @param fac result polynomial factory. * @param L list of polynomials with ModInteger coefficients to be * converted. * @return list of polynomials with BigInteger coefficients. */ public static & Modular> List> integerFromModularCoefficients( final GenPolynomialRing fac, List> L) { return ListUtil., GenPolynomial> map(L, new UnaryFunctor, GenPolynomial>() { public GenPolynomial eval(GenPolynomial c) { return PolyUtil. integerFromModularCoefficients(fac, c); } }); } /** * BigInteger from ModInteger coefficients, positive. Represent as * polynomial with BigInteger coefficients by removing the modules. * @param fac result polynomial factory. * @param A polynomial with ModInteger coefficients to be converted. * @return polynomial with BigInteger coefficients. */ public static & Modular> GenPolynomial integerFromModularCoefficientsPositive( GenPolynomialRing fac, GenPolynomial A) { return PolyUtil. map(fac, A, new ModToInt()); } /** * BigInteger from BigRational coefficients. Represent as polynomial with * BigInteger coefficients by multiplication with the lcm of the numerators * of the BigRational coefficients. * @param fac result polynomial factory. * @param A polynomial with BigRational coefficients to be converted. * @return polynomial with BigInteger coefficients. */ public static GenPolynomial integerFromRationalCoefficients( GenPolynomialRing fac, GenPolynomial A) { if (A == null || A.isZERO()) { return fac.getZERO(); } java.math.BigInteger c = null; int s = 0; // lcm of denominators for (BigRational y : A.val.values()) { java.math.BigInteger x = y.denominator(); // c = lcm(c,x) if (c == null) { c = x; s = x.signum(); } else { java.math.BigInteger d = c.gcd(x); c = c.multiply(x.divide(d)); } } if (s < 0) { c = c.negate(); } return PolyUtil. map(fac, A, new RatToInt(c)); } /** * BigInteger from BigRational coefficients. Represent as polynomial with * BigInteger coefficients by multiplication with the gcd of the numerators * and the lcm of the denominators of the BigRational coefficients.
* Author: Axel Kramer * @param fac result polynomial factory. * @param A polynomial with BigRational coefficients to be converted. * @return Object[] with 3 entries: [0]->gcd [1]->lcm and [2]->polynomial * with BigInteger coefficients. */ public static Object[] integerFromRationalCoefficientsFactor(GenPolynomialRing fac, GenPolynomial A) { Object[] result = new Object[3]; if (A == null || A.isZERO()) { result[0] = java.math.BigInteger.ONE; result[1] = java.math.BigInteger.ZERO; result[2] = fac.getZERO(); return result; } java.math.BigInteger gcd = null; java.math.BigInteger lcm = null; int sLCM = 0; int sGCD = 0; // lcm of denominators for (BigRational y : A.val.values()) { java.math.BigInteger numerator = y.numerator(); java.math.BigInteger denominator = y.denominator(); // lcm = lcm(lcm,x) if (lcm == null) { lcm = denominator; sLCM = denominator.signum(); } else { java.math.BigInteger d = lcm.gcd(denominator); lcm = lcm.multiply(denominator.divide(d)); } // gcd = gcd(gcd,x) if (gcd == null) { gcd = numerator; sGCD = numerator.signum(); } else { gcd = gcd.gcd(numerator); } } if (sLCM < 0) { lcm = lcm.negate(); } if (sGCD < 0) { gcd = gcd.negate(); } result[0] = gcd; result[1] = lcm; result[2] = PolyUtil. map(fac, A, new RatToIntFactor(gcd, lcm)); return result; } /** * BigInteger from BigRational coefficients. Represent as list of * polynomials with BigInteger coefficients by multiplication with the lcm * of the numerators of the BigRational coefficients of each polynomial. * @param fac result polynomial factory. * @param L list of polynomials with BigRational coefficients to be * converted. * @return polynomial list with BigInteger coefficients. */ public static List> integerFromRationalCoefficients( GenPolynomialRing fac, List> L) { return ListUtil., GenPolynomial> map(L, new RatToIntPoly(fac)); } /** * From BigInteger coefficients. Represent as polynomial with type C * coefficients, e.g. ModInteger or BigRational. * @param coefficient type. * @param fac result polynomial factory. * @param A polynomial with BigInteger coefficients to be converted. * @return polynomial with type C coefficients. */ public static > GenPolynomial fromIntegerCoefficients(GenPolynomialRing fac, GenPolynomial A) { return PolyUtil. map(fac, A, new FromInteger(fac.coFac)); } /** * From BigInteger coefficients. Represent as list of polynomials with type * C coefficients, e.g. ModInteger or BigRational. * @param coefficient type. * @param fac result polynomial factory. * @param L list of polynomials with BigInteger coefficients to be * converted. * @return list of polynomials with type C coefficients. */ public static > List> fromIntegerCoefficients( GenPolynomialRing fac, List> L) { return ListUtil., GenPolynomial> map(L, new FromIntegerPoly(fac)); } /** * Convert to decimal coefficients. * @param fac result polynomial factory. * @param A polynomial with Rational coefficients to be converted. * @return polynomial with BigDecimal coefficients. */ public static & Rational> GenPolynomial decimalFromRational( GenPolynomialRing fac, GenPolynomial A) { return PolyUtil. map(fac, A, new RatToDec()); } /** * Convert to complex decimal coefficients. * @param fac result polynomial factory. * @param A polynomial with complex Rational coefficients to be converted. * @return polynomial with Complex BigDecimal coefficients. */ public static & Rational> GenPolynomial> complexDecimalFromRational( GenPolynomialRing> fac, GenPolynomial> A) { return PolyUtil., Complex> map(fac, A, new CompRatToDec(fac.coFac)); } /** * Real part. * @param fac result polynomial factory. * @param A polynomial with BigComplex coefficients to be converted. * @return polynomial with real part of the coefficients. */ public static GenPolynomial realPart(GenPolynomialRing fac, GenPolynomial A) { return PolyUtil. map(fac, A, new RealPart()); } /** * Imaginary part. * @param fac result polynomial factory. * @param A polynomial with BigComplex coefficients to be converted. * @return polynomial with imaginary part of coefficients. */ public static GenPolynomial imaginaryPart(GenPolynomialRing fac, GenPolynomial A) { return PolyUtil. map(fac, A, new ImagPart()); } /** * Real part. * @param fac result polynomial factory. * @param A polynomial with BigComplex coefficients to be converted. * @return polynomial with real part of the coefficients. */ public static > GenPolynomial realPartFromComplex(GenPolynomialRing fac, GenPolynomial> A) { return PolyUtil., C> map(fac, A, new RealPartComplex()); } /** * Imaginary part. * @param fac result polynomial factory. * @param A polynomial with BigComplex coefficients to be converted. * @return polynomial with imaginary part of coefficients. */ public static > GenPolynomial imaginaryPartFromComplex(GenPolynomialRing fac, GenPolynomial> A) { return PolyUtil., C> map(fac, A, new ImagPartComplex()); } /** * Complex from real polynomial. * @param fac result polynomial factory. * @param A polynomial with C coefficients to be converted. * @return polynomial with Complex coefficients. */ public static > GenPolynomial> toComplex( GenPolynomialRing> fac, GenPolynomial A) { return PolyUtil.> map(fac, A, new ToComplex(fac.coFac)); } /** * Complex from rational coefficients. * @param fac result polynomial factory. * @param A polynomial with BigRational coefficients to be converted. * @return polynomial with BigComplex coefficients. */ public static GenPolynomial complexFromRational(GenPolynomialRing fac, GenPolynomial A) { return PolyUtil. map(fac, A, new RatToCompl()); } /** * Complex from ring element coefficients. * @param fac result polynomial factory. * @param A polynomial with RingElem coefficients to be converted. * @return polynomial with Complex coefficients. */ public static > GenPolynomial> complexFromAny( GenPolynomialRing> fac, GenPolynomial A) { ComplexRing cr = (ComplexRing) fac.coFac; return PolyUtil.> map(fac, A, new AnyToComplex(cr)); } /** * From AlgebraicNumber coefficients. Represent as polynomial with type * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. * @param rfac result polynomial factory. * @param A polynomial with AlgebraicNumber coefficients to be converted. * @return polynomial with type GenPolynomial<C> coefficients. */ public static > GenPolynomial> fromAlgebraicCoefficients( GenPolynomialRing> rfac, GenPolynomial> A) { return PolyUtil., GenPolynomial> map(rfac, A, new AlgToPoly()); } /** * Convert to AlgebraicNumber coefficients. Represent as polynomial with * AlgebraicNumber coefficients, C is e.g. ModInteger or BigRational. * @param pfac result polynomial factory. * @param A polynomial with C coefficients to be converted. * @return polynomial with AlgebraicNumber<C> coefficients. */ public static > GenPolynomial> convertToAlgebraicCoefficients( GenPolynomialRing> pfac, GenPolynomial A) { AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac; return PolyUtil.> map(pfac, A, new CoeffToAlg(afac)); } /** * Convert to recursive AlgebraicNumber coefficients. Represent as * polynomial with recursive AlgebraicNumber coefficients, C is e.g. * ModInteger or BigRational. * @param depth recursion depth of AlgebraicNumber coefficients. * @param pfac result polynomial factory. * @param A polynomial with C coefficients to be converted. * @return polynomial with AlgebraicNumber<C> coefficients. */ public static > GenPolynomial> convertToRecAlgebraicCoefficients( int depth, GenPolynomialRing> pfac, GenPolynomial A) { AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac; return PolyUtil.> map(pfac, A, new CoeffToRecAlg(depth, afac)); } /** * Convert to AlgebraicNumber coefficients. Represent as polynomial with * AlgebraicNumber coefficients, C is e.g. ModInteger or BigRational. * @param pfac result polynomial factory. * @param A recursive polynomial with GenPolynomial<BigInteger> * coefficients to be converted. * @return polynomial with AlgebraicNumber<C> coefficients. */ public static > GenPolynomial> convertRecursiveToAlgebraicCoefficients( GenPolynomialRing> pfac, GenPolynomial> A) { AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac; return PolyUtil., AlgebraicNumber> map(pfac, A, new PolyToAlg(afac)); } /** * Complex from algebraic coefficients. * @param fac result polynomial factory. * @param A polynomial with AlgebraicNumber coefficients Q(i) to be * converted. * @return polynomial with Complex coefficients. */ public static > GenPolynomial> complexFromAlgebraic( GenPolynomialRing> fac, GenPolynomial> A) { ComplexRing cfac = (ComplexRing) fac.coFac; return PolyUtil., Complex> map(fac, A, new AlgebToCompl(cfac)); } /** * AlgebraicNumber from complex coefficients. * @param fac result polynomial factory over Q(i). * @param A polynomial with Complex coefficients to be converted. * @return polynomial with AlgebraicNumber coefficients. */ public static > GenPolynomial> algebraicFromComplex( GenPolynomialRing> fac, GenPolynomial> A) { AlgebraicNumberRing afac = (AlgebraicNumberRing) fac.coFac; return PolyUtil., AlgebraicNumber> map(fac, A, new ComplToAlgeb(afac)); } /** * ModInteger chinese remainder algorithm on coefficients. * @param fac GenPolynomial<ModInteger> result factory with * A.coFac.modul*B.coFac.modul = C.coFac.modul. * @param A GenPolynomial<ModInteger>. * @param B other GenPolynomial<ModInteger>. * @param mi inverse of A.coFac.modul in ring B.coFac. * @return S = cra(A,B), with S mod A.coFac.modul == A and S mod * B.coFac.modul == B. */ public static & Modular> GenPolynomial chineseRemainder( GenPolynomialRing fac, GenPolynomial A, C mi, GenPolynomial B) { ModularRingFactory cfac = (ModularRingFactory) fac.coFac; // get RingFactory GenPolynomial S = fac.getZERO().copy(); GenPolynomial Ap = A.copy(); SortedMap av = Ap.val; //getMap(); SortedMap bv = B.getMap(); SortedMap sv = S.val; //getMap(); C c = null; for (Map.Entry me : bv.entrySet()) { ExpVector e = me.getKey(); C y = me.getValue(); //bv.get(e); // assert y != null C x = av.get(e); if (x != null) { av.remove(e); c = cfac.chineseRemainder(x, mi, y); if (!c.isZERO()) { // 0 cannot happen sv.put(e, c); } } else { //c = cfac.fromInteger( y.getVal() ); c = cfac.chineseRemainder(A.ring.coFac.getZERO(), mi, y); if (!c.isZERO()) { // 0 cannot happen sv.put(e, c); // c != null } } } // assert bv is empty = done for (Map.Entry me : av.entrySet()) { // rest of av ExpVector e = me.getKey(); C x = me.getValue(); // av.get(e); // assert x != null //c = cfac.fromInteger( x.getVal() ); c = cfac.chineseRemainder(x, mi, B.ring.coFac.getZERO()); if (!c.isZERO()) { // 0 cannot happen sv.put(e, c); // c != null } } return S; } /** * GenPolynomial monic, i.e. leadingBaseCoefficient == 1. If * leadingBaseCoefficient is not invertible returns this unmodified. * @param coefficient type. * @param p recursive GenPolynomial>. * @return monic(p). */ public static > GenPolynomial> monic( GenPolynomial> p) { if (p == null || p.isZERO()) { return p; } C lc = p.leadingBaseCoefficient().leadingBaseCoefficient(); if (!lc.isUnit()) { return p; } C lm = lc.inverse(); GenPolynomial L = p.ring.coFac.getONE(); L = L.multiply(lm); return p.multiply(L); } /** * Polynomial list monic. * @param coefficient type. * @param L list of polynomials with field coefficients. * @return list of polynomials with leading coefficient 1. */ public static > List> monic(List> L) { return ListUtil., GenPolynomial> map(L, new UnaryFunctor, GenPolynomial>() { public GenPolynomial eval(GenPolynomial c) { if (c == null) { return null; } return c.monic(); } }); } /** * Recursive polynomial list monic. * @param coefficient type. * @param L list of recursive polynomials with field coefficients. * @return list of polynomials with leading base coefficient 1. */ public static > List>> monicRec(List>> L) { return ListUtil.>, GenPolynomial>> map(L, new UnaryFunctor>, GenPolynomial>>() { public GenPolynomial> eval(GenPolynomial> c) { if (c == null) { return null; } return PolyUtil. monic(c); } }); } /** * Polynomial list leading exponent vectors. * @param coefficient type. * @param L list of polynomials. * @return list of leading exponent vectors. */ public static > List leadingExpVector(List> L) { return ListUtil., ExpVector> map(L, new UnaryFunctor, ExpVector>() { public ExpVector eval(GenPolynomial c) { if (c == null) { return null; } return c.leadingExpVector(); } }); } /** * Extend coefficient variables. Extend all coefficient ExpVectors by i * elements and multiply by x_j^k. * @param pfac extended polynomial ring factory (by i variables in the * coefficients). * @param j index of variable to be used for multiplication. * @param k exponent for x_j. * @return extended polynomial. */ public static > GenPolynomial> extendCoefficients( GenPolynomialRing> pfac, GenPolynomial> A, int j, long k) { GenPolynomial> Cp = pfac.getZERO().copy(); if (A.isZERO()) { return Cp; } GenPolynomialRing cfac = (GenPolynomialRing) pfac.coFac; //GenPolynomialRing acfac = (GenPolynomialRing) A.ring.coFac; //int i = cfac.nvar - acfac.nvar; Map> CC = Cp.val; //getMap(); for (Map.Entry> y : A.val.entrySet()) { ExpVector e = y.getKey(); GenPolynomial a = y.getValue(); GenPolynomial f = a.extend(cfac, j, k); CC.put(e, f); } return Cp; } /** * Extend coefficient variables. Extend all coefficient ExpVectors by i * elements and multiply by x_j^k. * @param pfac extended polynomial ring factory (by i variables in the * coefficients). * @param j index of variable to be used for multiplication. * @param k exponent for x_j. * @return extended polynomial. */ public static > GenSolvablePolynomial> extendCoefficients(GenSolvablePolynomialRing> pfac, GenSolvablePolynomial> A, int j, long k) { GenSolvablePolynomial> Cp = pfac.getZERO().copy(); if (A.isZERO()) { return Cp; } GenPolynomialRing cfac = (GenPolynomialRing) pfac.coFac; //GenPolynomialRing acfac = (GenPolynomialRing) A.ring.coFac; //int i = cfac.nvar - acfac.nvar; Map> CC = Cp.val; //getMap(); for (Map.Entry> y : A.val.entrySet()) { ExpVector e = y.getKey(); GenPolynomial a = y.getValue(); GenPolynomial f = a.extend(cfac, j, k); CC.put(e, f); } return Cp; } /** * To recursive representation. Represent as polynomial in i+r variables * with coefficients in i variables. Works for arbitrary term orders. * @param coefficient type. * @param rfac recursive polynomial ring factory. * @param A polynomial to be converted. * @return Recursive represenations of A in the ring rfac. */ public static > GenPolynomial> toRecursive( GenPolynomialRing> rfac, GenPolynomial A) { GenPolynomial> B = rfac.getZERO().copy(); if (A.isZERO()) { return B; } //int i = rfac.nvar; //GenPolynomial zero = rfac.getZEROCoefficient(); GenPolynomial one = rfac.getONECoefficient(); Map> Bv = B.val; //getMap(); for (Monomial m : A) { ExpVector e = m.e; C a = m.c; GenPolynomial p = one.multiply(a); Bv.put(e, p); } return B; } /** * To recursive representation. Represent as solvable polynomial in i+r variables * with coefficients in i variables. Works for arbitrary term orders. * @param coefficient type. * @param rfac recursive solvable polynomial ring factory. * @param A solvable polynomial to be converted. * @return Recursive represenations of A in the ring rfac. */ public static > GenSolvablePolynomial> toRecursive( GenSolvablePolynomialRing> rfac, GenSolvablePolynomial A) { GenSolvablePolynomial> B = rfac.getZERO().copy(); if (A.isZERO()) { return B; } //int i = rfac.nvar; //GenPolynomial zero = rfac.getZEROCoefficient(); GenPolynomial one = rfac.getONECoefficient(); Map> Bv = B.val; //getMap(); for (Monomial m : A) { ExpVector e = m.e; C a = m.c; GenPolynomial p = one.multiply(a); Bv.put(e, p); } return B; } /** * GenPolynomial coefficient wise remainder. * @param coefficient type. * @param P GenPolynomial. * @param s nonzero coefficient. * @return coefficient wise remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). */ public static > GenPolynomial baseRemainderPoly(GenPolynomial P, C s) { if (s == null || s.isZERO()) { throw new ArithmeticException(P + " division by zero " + s); } GenPolynomial h = P.ring.getZERO().copy(); Map hm = h.val; //getMap(); for (Map.Entry m : P.getMap().entrySet()) { ExpVector f = m.getKey(); C a = m.getValue(); C x = a.remainder(s); hm.put(f, x); } return h; } /** * GenPolynomial sparse pseudo remainder. For univariate polynomials. * @param coefficient type. * @param P GenPolynomial. * @param S nonzero GenPolynomial. * @return remainder with ldcf(S)m' P = quotient * S + remainder. * m' ≤ deg(P)-deg(S) * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). * @deprecated Use * {@link #baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)} * instead */ @Deprecated public static > GenPolynomial basePseudoRemainder(GenPolynomial P, GenPolynomial S) { return baseSparsePseudoRemainder(P, S); } /** * GenPolynomial sparse pseudo remainder. For univariate polynomials. * @param coefficient type. * @param P GenPolynomial. * @param S nonzero GenPolynomial. * @return remainder with ldcf(S)m' P = quotient * S + remainder. * m' ≤ deg(P)-deg(S) * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). */ public static > GenPolynomial baseSparsePseudoRemainder(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { throw new ArithmeticException(P.toString() + " division by zero " + S); } if (P.isZERO()) { return P; } if (S.isONE()) { return P.ring.getZERO(); } C c = S.leadingBaseCoefficient(); ExpVector e = S.leadingExpVector(); GenPolynomial h; GenPolynomial r = P; while (!r.isZERO()) { ExpVector f = r.leadingExpVector(); if (f.multipleOf(e)) { C a = r.leadingBaseCoefficient(); f = f.subtract(e); C x = a.remainder(c); if (x.isZERO()) { C y = a.divide(c); h = S.multiply(y, f); // coeff a } else { r = r.multiply(c); // coeff ac h = S.multiply(a, f); // coeff ac } r = r.subtract(h); } else { break; } } return r; } /** * GenPolynomial dense pseudo remainder. For univariate polynomials. * @param P GenPolynomial. * @param S nonzero GenPolynomial. * @return remainder with ldcf(S)m P = quotient * S + remainder. * m == deg(P)-deg(S) * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). */ public static > GenPolynomial baseDensePseudoRemainder(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { throw new ArithmeticException(P + " division by zero " + S); } if (P.isZERO()) { return P; } if (S.degree() <= 0) { return P.ring.getZERO(); } long m = P.degree(0); long n = S.degree(0); C c = S.leadingBaseCoefficient(); ExpVector e = S.leadingExpVector(); GenPolynomial h; GenPolynomial r = P; for (long i = m; i >= n; i--) { if (r.isZERO()) { return r; } long k = r.degree(0); if (i == k) { ExpVector f = r.leadingExpVector(); C a = r.leadingBaseCoefficient(); f = f.subtract(e); // EVDIF( f, e ); //System.out.println("red div = " + f); r = r.multiply(c); // coeff ac h = S.multiply(a, f); // coeff ac r = r.subtract(h); } else { r = r.multiply(c); } } return r; } /** * GenPolynomial dense pseudo quotient. For univariate polynomials. * @param P GenPolynomial. * @param S nonzero GenPolynomial. * @return quotient with ldcf(S)m P = quotient * S + remainder. m * == deg(P)-deg(S) * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). */ public static > GenPolynomial baseDensePseudoQuotient(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { throw new ArithmeticException(P + " division by zero " + S); } if (P.isZERO()) { return P; } //if (S.degree() <= 0) { // return l^n P; //P.ring.getZERO(); //} long m = P.degree(0); long n = S.degree(0); C c = S.leadingBaseCoefficient(); ExpVector e = S.leadingExpVector(); GenPolynomial q = P.ring.getZERO(); GenPolynomial h; GenPolynomial r = P; for (long i = m; i >= n; i--) { if (r.isZERO()) { return q; } long k = r.degree(0); if (i == k) { ExpVector f = r.leadingExpVector(); C a = r.leadingBaseCoefficient(); f = f.subtract(e); // EVDIF( f, e ); //System.out.println("red div = " + f); r = r.multiply(c); // coeff ac h = S.multiply(a, f); // coeff ac r = r.subtract(h); q = q.multiply(c); q = q.sum(a, f); } else { q = q.multiply(c); r = r.multiply(c); } } return q; } /** * GenPolynomial sparse pseudo divide. For univariate polynomials or exact * division. * @param coefficient type. * @param P GenPolynomial. * @param S nonzero GenPolynomial. * @return quotient with ldcf(S)m' P = quotient * S + remainder. * m' ≤ deg(P)-deg(S) * @see edu.jas.poly.GenPolynomial#divide(edu.jas.poly.GenPolynomial). */ public static > GenPolynomial basePseudoDivide(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { throw new ArithmeticException(P.toString() + " division by zero " + S); } //if (S.ring.nvar != 1) { // ok if exact division // throw new RuntimeException(this.getClass().getName() // + " univariate polynomials only"); //} if (P.isZERO() || S.isONE()) { return P; } C c = S.leadingBaseCoefficient(); ExpVector e = S.leadingExpVector(); GenPolynomial h; GenPolynomial r = P; GenPolynomial q = S.ring.getZERO().copy(); while (!r.isZERO()) { ExpVector f = r.leadingExpVector(); if (f.multipleOf(e)) { C a = r.leadingBaseCoefficient(); f = f.subtract(e); C x = a.remainder(c); if (x.isZERO()) { C y = a.divide(c); q = q.sum(y, f); h = S.multiply(y, f); // coeff a } else { q = q.multiply(c); q = q.sum(a, f); r = r.multiply(c); // coeff ac h = S.multiply(a, f); // coeff ac } r = r.subtract(h); } else { break; } } return q; } /** * GenPolynomial sparse pseudo quotient and remainder. For univariate * polynomials or exact division. * @param coefficient type. * @param P GenPolynomial. * @param S nonzero GenPolynomial. * @return [ quotient, remainder ] with ldcf(S)m' P = quotient * * S + remainder. m' ≤ deg(P)-deg(S) * @see edu.jas.poly.GenPolynomial#divide(edu.jas.poly.GenPolynomial). */ @SuppressWarnings("unchecked") public static > GenPolynomial[] basePseudoQuotientRemainder(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { throw new ArithmeticException(P.toString() + " division by zero " + S); } //if (S.ring.nvar != 1) { // ok if exact division // throw new RuntimeException(this.getClass().getName() // + " univariate polynomials only"); //} GenPolynomial[] ret = new GenPolynomial[2]; ret[0] = null; ret[1] = null; if (P.isZERO() || S.isONE()) { ret[0] = P; ret[1] = S.ring.getZERO(); return ret; } C c = S.leadingBaseCoefficient(); ExpVector e = S.leadingExpVector(); GenPolynomial h; GenPolynomial r = P; GenPolynomial q = S.ring.getZERO().copy(); while (!r.isZERO()) { ExpVector f = r.leadingExpVector(); if (f.multipleOf(e)) { C a = r.leadingBaseCoefficient(); f = f.subtract(e); C x = a.remainder(c); if (x.isZERO()) { C y = a.divide(c); q = q.sum(y, f); h = S.multiply(y, f); // coeff a } else { q = q.multiply(c); q = q.sum(a, f); r = r.multiply(c); // coeff ac h = S.multiply(a, f); // coeff ac } r = r.subtract(h); } else { break; } } //GenPolynomial rhs = q.multiply(S).sum(r); //GenPolynomial lhs = P; ret[0] = q; ret[1] = r; return ret; } /** * Is GenPolynomial pseudo quotient and remainder. For univariate * polynomials. * @param coefficient type. * @param P base GenPolynomial. * @param S nonzero base GenPolynomial. * @return remainder with ldcf(S)m' P = quotient * S + remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). * Note: not always meaningful and working */ public static > boolean isBasePseudoQuotientRemainder(GenPolynomial P, GenPolynomial S, GenPolynomial q, GenPolynomial r) { GenPolynomial rhs = q.multiply(S).sum(r); //System.out.println("rhs,1 = " + rhs); GenPolynomial lhs = P; C ldcf = S.leadingBaseCoefficient(); long d = P.degree(0) - S.degree(0) + 1; d = (d > 0 ? d : -d + 2); for (long i = 0; i <= d; i++) { //System.out.println("lhs-rhs = " + lhs.subtract(rhs)); if (lhs.equals(rhs)) { //System.out.println("lhs,1 = " + lhs); return true; } lhs = lhs.multiply(ldcf); } GenPolynomial Pp = P; rhs = q.multiply(S); //System.out.println("rhs,2 = " + rhs); for (long i = 0; i <= d; i++) { lhs = Pp.subtract(r); //System.out.println("lhs-rhs = " + lhs.subtract(rhs)); if (lhs.equals(rhs)) { //System.out.println("lhs,2 = " + lhs); return true; } Pp = Pp.multiply(ldcf); } return false; } /** * GenPolynomial divide. For recursive polynomials. Division by coefficient * ring element. * @param coefficient type. * @param P recursive GenPolynomial. * @param s GenPolynomial. * @return this/s. */ public static > GenPolynomial> recursiveDivide( GenPolynomial> P, GenPolynomial s) { if (s == null || s.isZERO()) { throw new ArithmeticException("division by zero " + P + ", " + s); } if (P.isZERO()) { return P; } if (s.isONE()) { return P; } GenPolynomial> p = P.ring.getZERO().copy(); SortedMap> pv = p.val; //getMap(); for (Map.Entry> m1 : P.getMap().entrySet()) { GenPolynomial c1 = m1.getValue(); ExpVector e1 = m1.getKey(); GenPolynomial c = PolyUtil. basePseudoDivide(c1, s); if (!c.isZERO()) { pv.put(e1, c); // or m1.setValue( c ) } else { System.out.println("pu, c1 = " + c1); System.out.println("pu, s = " + s); System.out.println("pu, c = " + c); throw new RuntimeException("something is wrong"); } } return p; } /** * GenPolynomial base divide. For recursive polynomials. Division by * coefficient ring element. * @param coefficient type. * @param P recursive GenPolynomial. * @param s coefficient. * @return this/s. */ public static > GenPolynomial> baseRecursiveDivide( GenPolynomial> P, C s) { if (s == null || s.isZERO()) { throw new ArithmeticException("division by zero " + P + ", " + s); } if (P.isZERO()) { return P; } if (s.isONE()) { return P; } GenPolynomial> p = P.ring.getZERO().copy(); SortedMap> pv = p.val; //getMap(); for (Map.Entry> m1 : P.getMap().entrySet()) { GenPolynomial c1 = m1.getValue(); ExpVector e1 = m1.getKey(); GenPolynomial c = PolyUtil. coefficientBasePseudoDivide(c1, s); if (!c.isZERO()) { pv.put(e1, c); // or m1.setValue( c ) } else { System.out.println("pu, c1 = " + c1); System.out.println("pu, s = " + s); System.out.println("pu, c = " + c); throw new RuntimeException("something is wrong"); } } return p; } /** * GenPolynomial sparse pseudo remainder. For recursive polynomials. * @param coefficient type. * @param P recursive GenPolynomial. * @param S nonzero recursive GenPolynomial. * @return remainder with ldcf(S)m' P = quotient * S + remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). * @deprecated Use * {@link #recursiveSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)} * instead */ @Deprecated public static > GenPolynomial> recursivePseudoRemainder( GenPolynomial> P, GenPolynomial> S) { return recursiveSparsePseudoRemainder(P, S); } /** * GenPolynomial sparse pseudo remainder. For recursive polynomials. * @param coefficient type. * @param P recursive GenPolynomial. * @param S nonzero recursive GenPolynomial. * @return remainder with ldcf(S)m' P = quotient * S + remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). */ public static > GenPolynomial> recursiveSparsePseudoRemainder( GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { throw new ArithmeticException(P + " division by zero " + S); } if (P == null || P.isZERO()) { return P; } if (S.isONE()) { return P.ring.getZERO(); } GenPolynomial c = S.leadingBaseCoefficient(); ExpVector e = S.leadingExpVector(); GenPolynomial> h; GenPolynomial> r = P; while (!r.isZERO()) { ExpVector f = r.leadingExpVector(); if (f.multipleOf(e)) { GenPolynomial a = r.leadingBaseCoefficient(); f = f.subtract(e); GenPolynomial x = c; //test basePseudoRemainder(a,c); if (x.isZERO()) { GenPolynomial y = PolyUtil. basePseudoDivide(a, c); h = S.multiply(y, f); // coeff a } else { r = r.multiply(c); // coeff ac h = S.multiply(a, f); // coeff ac } r = r.subtract(h); } else { break; } } return r; } /** * GenPolynomial dense pseudo remainder. For recursive polynomials. * @param P recursive GenPolynomial. * @param S nonzero recursive GenPolynomial. * @return remainder with ldcf(S)m' P = quotient * S + remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). */ public static > GenPolynomial> recursiveDensePseudoRemainder( GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { throw new ArithmeticException(P + " division by zero " + S); } if (P == null || P.isZERO()) { return P; } if (S.degree() <= 0) { return P.ring.getZERO(); } long m = P.degree(0); long n = S.degree(0); GenPolynomial c = S.leadingBaseCoefficient(); ExpVector e = S.leadingExpVector(); GenPolynomial> h; GenPolynomial> r = P; for (long i = m; i >= n; i--) { if (r.isZERO()) { return r; } long k = r.degree(0); if (i == k) { ExpVector f = r.leadingExpVector(); GenPolynomial a = r.leadingBaseCoefficient(); f = f.subtract(e); //EVDIF( f, e ); //System.out.println("red div = " + f); r = r.multiply(c); // coeff ac h = S.multiply(a, f); // coeff ac r = r.subtract(h); } else { r = r.multiply(c); } } return r; } /** * GenPolynomial recursive pseudo divide. For recursive polynomials. * @param coefficient type. * @param P recursive GenPolynomial. * @param S nonzero recursive GenPolynomial. * @return quotient with ldcf(S)m' P = quotient * S + remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). */ public static > GenPolynomial> recursivePseudoDivide( GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { throw new ArithmeticException(P + " division by zero " + S); } //if (S.ring.nvar != 1) { // ok if exact division // throw new RuntimeException(this.getClass().getName() // + " univariate polynomials only"); //} if (P == null || P.isZERO()) { return P; } if (S.isONE()) { return P; } GenPolynomial c = S.leadingBaseCoefficient(); ExpVector e = S.leadingExpVector(); GenPolynomial> h; GenPolynomial> r = P; GenPolynomial> q = S.ring.getZERO().copy(); while (!r.isZERO()) { ExpVector f = r.leadingExpVector(); if (f.multipleOf(e)) { GenPolynomial a = r.leadingBaseCoefficient(); f = f.subtract(e); GenPolynomial x = PolyUtil. baseSparsePseudoRemainder(a, c); if (x.isZERO() && !c.isConstant()) { GenPolynomial y = PolyUtil. basePseudoDivide(a, c); q = q.sum(y, f); h = S.multiply(y, f); // coeff a } else { q = q.multiply(c); q = q.sum(a, f); r = r.multiply(c); // coeff ac h = S.multiply(a, f); // coeff ac } r = r.subtract(h); } else { break; } } return q; } /** * Is GenPolynomial pseudo quotient and remainder. For recursive * polynomials. * @param coefficient type. * @param P recursive GenPolynomial. * @param S nonzero recursive GenPolynomial. * @return remainder with ldcf(S)m' P = quotient * S + remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). * Note: not always meaningful and working */ public static > boolean isRecursivePseudoQuotientRemainder( GenPolynomial> P, GenPolynomial> S, GenPolynomial> q, GenPolynomial> r) { GenPolynomial> rhs = q.multiply(S).sum(r); GenPolynomial> lhs = P; GenPolynomial ldcf = S.leadingBaseCoefficient(); long d = P.degree(0) - S.degree(0) + 1; d = (d > 0 ? d : -d + 2); for (long i = 0; i <= d; i++) { //System.out.println("lhs = " + lhs); //System.out.println("rhs = " + rhs); //System.out.println("lhs-rhs = " + lhs.subtract(rhs)); if (lhs.equals(rhs)) { return true; } lhs = lhs.multiply(ldcf); } GenPolynomial> Pp = P; rhs = q.multiply(S); //System.out.println("rhs,2 = " + rhs); for (long i = 0; i <= d; i++) { lhs = Pp.subtract(r); //System.out.println("lhs-rhs = " + lhs.subtract(rhs)); if (lhs.equals(rhs)) { //System.out.println("lhs,2 = " + lhs); return true; } Pp = Pp.multiply(ldcf); } return false; } /** * GenPolynomial pseudo divide. For recursive polynomials. * @param coefficient type. * @param P recursive GenPolynomial. * @param s nonzero GenPolynomial. * @return quotient with ldcf(s)m P = quotient * s + remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). */ public static > GenPolynomial> coefficientPseudoDivide( GenPolynomial> P, GenPolynomial s) { if (s == null || s.isZERO()) { throw new ArithmeticException(P + " division by zero " + s); } if (P.isZERO()) { return P; } GenPolynomial> p = P.ring.getZERO().copy(); SortedMap> pv = p.val; for (Map.Entry> m : P.getMap().entrySet()) { ExpVector e = m.getKey(); GenPolynomial c1 = m.getValue(); GenPolynomial c = basePseudoDivide(c1, s); if (debug) { GenPolynomial x = c1.remainder(s); if (!x.isZERO()) { logger.info("divide x = " + x); throw new ArithmeticException(" no exact division: " + c1 + "/" + s); } } if (c.isZERO()) { System.out.println(" no exact division: " + c1 + "/" + s); //throw new ArithmeticException(" no exact division: " + c1 + "/" + s); } else { pv.put(e, c); // or m1.setValue( c ) } } return p; } /** * GenPolynomial pseudo divide. For polynomials. * @param coefficient type. * @param P GenPolynomial. * @param s nonzero coefficient. * @return quotient with ldcf(s)m P = quotient * s + remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). */ public static > GenPolynomial coefficientBasePseudoDivide(GenPolynomial P, C s) { if (s == null || s.isZERO()) { throw new ArithmeticException(P + " division by zero " + s); } if (P.isZERO()) { return P; } GenPolynomial p = P.ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m : P.getMap().entrySet()) { ExpVector e = m.getKey(); C c1 = m.getValue(); C c = c1.divide(s); if (debug) { C x = c1.remainder(s); if (!x.isZERO()) { logger.info("divide x = " + x); throw new ArithmeticException(" no exact division: " + c1 + "/" + s); } } if (c.isZERO()) { System.out.println(" no exact division: " + c1 + "/" + s); //throw new ArithmeticException(" no exact division: " + c1 + "/" + s); } else { pv.put(e, c); // or m1.setValue( c ) } } return p; } /** * GenPolynomial polynomial derivative main variable. * @param coefficient type. * @param P GenPolynomial. * @return deriviative(P). */ public static > GenPolynomial baseDeriviative(GenPolynomial P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { // baseContent not possible by return type throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); } RingFactory rf = pfac.coFac; GenPolynomial d = pfac.getZERO().copy(); Map dm = d.val; //getMap(); for (Map.Entry m : P.getMap().entrySet()) { ExpVector f = m.getKey(); long fl = f.getVal(0); if (fl > 0) { C cf = rf.fromInteger(fl); C a = m.getValue(); C x = a.multiply(cf); if (x != null && !x.isZERO()) { ExpVector e = ExpVector.create(1, 0, fl - 1L); dm.put(e, x); } } } return d; } /** * GenPolynomial polynomial partial derivative variable r. * @param coefficient type. * @param P GenPolynomial. * @param r variable for partial deriviate. * @return deriviative(P,r). */ public static > GenPolynomial baseDeriviative(GenPolynomial P, int r) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (r < 0 || pfac.nvar <= r) { throw new IllegalArgumentException(P.getClass().getName() + " deriviative variable out of bound " + r); } int rp = pfac.nvar - 1 - r; RingFactory rf = pfac.coFac; GenPolynomial d = pfac.getZERO().copy(); Map dm = d.val; //getMap(); for (Map.Entry m : P.getMap().entrySet()) { ExpVector f = m.getKey(); long fl = f.getVal(rp); if (fl > 0) { C cf = rf.fromInteger(fl); C a = m.getValue(); C x = a.multiply(cf); if (x != null && !x.isZERO()) { ExpVector e = f.subst(rp, fl - 1L); dm.put(e, x); } } } return d; } /** * GenPolynomial polynomial integral main variable. * @param coefficient type. * @param P GenPolynomial. * @return integral(P). */ public static > GenPolynomial baseIntegral(GenPolynomial P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { // baseContent not possible by return type throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); } RingFactory rf = pfac.coFac; GenPolynomial d = pfac.getZERO().copy(); Map dm = d.val; //getMap(); for (Map.Entry m : P.getMap().entrySet()) { ExpVector f = m.getKey(); long fl = f.getVal(0); fl++; C cf = rf.fromInteger(fl); C a = m.getValue(); C x = a.divide(cf); if (x != null && !x.isZERO()) { ExpVector e = ExpVector.create(1, 0, fl); dm.put(e, x); } } return d; } /** * GenPolynomial recursive polynomial derivative main variable. * @param coefficient type. * @param P recursive GenPolynomial. * @return deriviative(P). */ public static > GenPolynomial> recursiveDeriviative( GenPolynomial> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { // baseContent not possible by return type throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); } GenPolynomialRing pr = (GenPolynomialRing) pfac.coFac; RingFactory rf = pr.coFac; GenPolynomial> d = pfac.getZERO().copy(); Map> dm = d.val; //getMap(); for (Map.Entry> m : P.getMap().entrySet()) { ExpVector f = m.getKey(); long fl = f.getVal(0); if (fl > 0) { C cf = rf.fromInteger(fl); GenPolynomial a = m.getValue(); GenPolynomial x = a.multiply(cf); if (x != null && !x.isZERO()) { ExpVector e = ExpVector.create(1, 0, fl - 1L); dm.put(e, x); } } } return d; } /** * Factor coefficient bound. See SACIPOL.IPFCB: the product of all maxNorms * of potential factors is less than or equal to 2**b times the maxNorm of * A. * @param e degree vector of a GenPolynomial A. * @return 2**b. */ public static BigInteger factorBound(ExpVector e) { int n = 0; java.math.BigInteger p = java.math.BigInteger.ONE; java.math.BigInteger v; if (e == null || e.isZERO()) { return BigInteger.ONE; } for (int i = 0; i < e.length(); i++) { if (e.getVal(i) > 0) { n += (2 * e.getVal(i) - 1); v = new java.math.BigInteger("" + (e.getVal(i) - 1)); p = p.multiply(v); } } n += (p.bitCount() + 1); // log2(p) n /= 2; v = new java.math.BigInteger("" + 2); v = v.shiftLeft(n); BigInteger N = new BigInteger(v); return N; } /** * Evaluate at main variable. * @param coefficient type. * @param cfac coefficent polynomial ring factory. * @param A recursive polynomial to be evaluated. * @param a value to evaluate at. * @return A( x_1, ..., x_{n-1}, a ). */ public static > GenPolynomial evaluateMainRecursive(GenPolynomialRing cfac, GenPolynomial> A, C a) { if (A == null || A.isZERO()) { return cfac.getZERO(); } if (A.ring.nvar != 1) { // todo assert throw new IllegalArgumentException("evaluateMain no univariate polynomial"); } if (a == null || a.isZERO()) { return A.trailingBaseCoefficient(); } // assert descending exponents, i.e. compatible term order Map> val = A.getMap(); GenPolynomial B = null; long el1 = -1; // undefined long el2 = -1; for (Map.Entry> me : val.entrySet()) { ExpVector e = me.getKey(); el2 = e.getVal(0); if (B == null /*el1 < 0*/) { // first turn B = me.getValue(); //val.get(e); } else { for (long i = el2; i < el1; i++) { B = B.multiply(a); } B = B.sum(me.getValue()); //val.get(e)); } el1 = el2; } for (long i = 0; i < el2; i++) { B = B.multiply(a); } return B; } /** * Evaluate at main variable. * @param coefficient type. * @param cfac coefficent polynomial ring factory. * @param A distributed polynomial to be evaluated. * @param a value to evaluate at. * @return A( x_1, ..., x_{n-1}, a ). */ public static > GenPolynomial evaluateMain(GenPolynomialRing cfac, GenPolynomial A, C a) { if (A == null || A.isZERO()) { return cfac.getZERO(); } GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1); if (rfac.nvar + cfac.nvar != A.ring.nvar) { throw new IllegalArgumentException("evaluateMain number of variabes mismatch"); } GenPolynomial> Ap = recursive(rfac, A); return PolyUtil. evaluateMainRecursive(cfac, Ap, a); } /** * Evaluate at main variable. * @param coefficient type. * @param cfac coefficent ring factory. * @param L list of univariate polynomials to be evaluated. * @param a value to evaluate at. * @return list( A( x_1, ..., x_{n-1}, a ) ) for A in L. */ public static > List> evaluateMain(GenPolynomialRing cfac, List> L, C a) { return ListUtil., GenPolynomial> map(L, new EvalMainPol(cfac, a)); } /** * Evaluate at main variable. * @param coefficient type. * @param cfac coefficent ring factory. * @param A univariate polynomial to be evaluated. * @param a value to evaluate at. * @return A( a ). */ public static > C evaluateMain(RingFactory cfac, GenPolynomial A, C a) { if (A == null || A.isZERO()) { return cfac.getZERO(); } if (A.ring.nvar != 1) { // todo assert throw new IllegalArgumentException("evaluateMain no univariate polynomial"); } if (a == null || a.isZERO()) { return A.trailingBaseCoefficient(); } // assert decreasing exponents, i.e. compatible term order Map val = A.getMap(); C B = null; long el1 = -1; // undefined long el2 = -1; for (Map.Entry me : val.entrySet()) { ExpVector e = me.getKey(); el2 = e.getVal(0); if (B == null /*el1 < 0*/) { // first turn B = me.getValue(); // val.get(e); } else { for (long i = el2; i < el1; i++) { B = B.multiply(a); } B = B.sum(me.getValue()); //val.get(e)); } el1 = el2; } for (long i = 0; i < el2; i++) { B = B.multiply(a); } return B; } /** * Evaluate at main variable. * @param coefficient type. * @param cfac coefficent ring factory. * @param L list of univariate polynomial to be evaluated. * @param a value to evaluate at. * @return list( A( a ) ) for A in L. */ public static > List evaluateMain(RingFactory cfac, List> L, C a) { return ListUtil., C> map(L, new EvalMain(cfac, a)); } /** * Evaluate at k-th variable. * @param coefficient type. * @param cfac coefficient polynomial ring in k variables C[x_1, ..., x_k] * factory. * @param rfac coefficient polynomial ring C[x_1, ..., x_{k-1}] [x_k] * factory, a recursive polynomial ring in 1 variable with * coefficients in k-1 variables. * @param nfac polynomial ring in n-1 varaibles C[x_1, ..., x_{k-1}] * [x_{k+1}, ..., x_n] factory, a recursive polynomial ring in * n-k+1 variables with coefficients in k-1 variables. * @param dfac polynomial ring in n-1 variables. C[x_1, ..., x_{k-1}, * x_{k+1}, ..., x_n] factory. * @param A polynomial to be evaluated. * @param a value to evaluate at. * @return A( x_1, ..., x_{k-1}, a, x_{k+1}, ..., x_n). */ public static > GenPolynomial evaluate(GenPolynomialRing cfac, GenPolynomialRing> rfac, GenPolynomialRing> nfac, GenPolynomialRing dfac, GenPolynomial A, C a) { if (rfac.nvar != 1) { // todo assert throw new IllegalArgumentException("evaluate coefficient ring not univariate"); } if (A == null || A.isZERO()) { return cfac.getZERO(); } Map> Ap = A.contract(cfac); GenPolynomialRing rcf = (GenPolynomialRing) rfac.coFac; GenPolynomial> Ev = nfac.getZERO().copy(); Map> Evm = Ev.val; //getMap(); for (Map.Entry> m : Ap.entrySet()) { ExpVector e = m.getKey(); GenPolynomial b = m.getValue(); GenPolynomial> c = recursive(rfac, b); GenPolynomial d = evaluateMainRecursive(rcf, c, a); if (d != null && !d.isZERO()) { Evm.put(e, d); } } GenPolynomial B = distribute(dfac, Ev); return B; } /** * Evaluate at first (lowest) variable. * @param coefficient type. * @param cfac coefficient polynomial ring in first variable C[x_1] factory. * @param dfac polynomial ring in n-1 variables. C[x_2, ..., x_n] factory. * @param A polynomial to be evaluated. * @param a value to evaluate at. * @return A( a, x_2, ..., x_n). */ public static > GenPolynomial evaluateFirst(GenPolynomialRing cfac, GenPolynomialRing dfac, GenPolynomial A, C a) { if (A == null || A.isZERO()) { return dfac.getZERO(); } Map> Ap = A.contract(cfac); //RingFactory rcf = cfac.coFac; // == dfac.coFac GenPolynomial B = dfac.getZERO().copy(); Map Bm = B.val; //getMap(); for (Map.Entry> m : Ap.entrySet()) { ExpVector e = m.getKey(); GenPolynomial b = m.getValue(); C d = evaluateMain(cfac.coFac, b, a); if (d != null && !d.isZERO()) { Bm.put(e, d); } } return B; } /** * Evaluate at first (lowest) variable. * @param coefficient type. Could also be called evaluateFirst(), but * type erasure of A parameter does not allow same name. * @param cfac coefficient polynomial ring in first variable C[x_1] factory. * @param dfac polynomial ring in n-1 variables. C[x_2, ..., x_n] factory. * @param A recursive polynomial to be evaluated. * @param a value to evaluate at. * @return A( a, x_2, ..., x_n). */ public static > GenPolynomial evaluateFirstRec(GenPolynomialRing cfac, GenPolynomialRing dfac, GenPolynomial> A, C a) { if (A == null || A.isZERO()) { return dfac.getZERO(); } Map> Ap = A.getMap(); GenPolynomial B = dfac.getZERO().copy(); Map Bm = B.val; //getMap(); for (Map.Entry> m : Ap.entrySet()) { ExpVector e = m.getKey(); GenPolynomial b = m.getValue(); C d = evaluateMain(cfac.coFac, b, a); if (d != null && !d.isZERO()) { Bm.put(e, d); } } return B; } /** * Evaluate all variables. * @param coefficient type. * @param cfac coefficient ring factory. * @param dfac polynomial ring in n variables. C[x_1, x_2, ..., x_n] * factory. * @param A polynomial to be evaluated. * @param a = (a_1, a_2, ..., a_n) a tuple of values to evaluate at. * @return A(a_1, a_2, ..., a_n). * @deprecated use evaluateAll() with three arguments */ @Deprecated public static > C evaluateAll(RingFactory cfac, GenPolynomialRing dfac, GenPolynomial A, List a) { return evaluateAll(cfac,A,a); } /** * Evaluate all variables. * @param coefficient type. * @param cfac coefficient ring factory. * @param A polynomial to be evaluated. * @param a = (a_1, a_2, ..., a_n) a tuple of values to evaluate at. * @return A(a_1, a_2, ..., a_n). */ public static > C evaluateAll(RingFactory cfac, GenPolynomial A, List a) { if (A == null || A.isZERO()) { return cfac.getZERO(); } GenPolynomialRing dfac = A.ring; if (a == null || a.size() != dfac.nvar) { throw new IllegalArgumentException("evaluate tuple size not equal to number of variables"); } if (dfac.nvar == 0) { return A.trailingBaseCoefficient(); } if (dfac.nvar == 1) { return evaluateMain(cfac, A, a.get(0)); } C b = cfac.getZERO(); GenPolynomial Ap = A; for (int k = 0; k < dfac.nvar - 1; k++) { C ap = a.get(k); GenPolynomialRing c1fac = new GenPolynomialRing(cfac, 1); GenPolynomialRing cnfac = new GenPolynomialRing(cfac, dfac.nvar - 1 - k); GenPolynomial Bp = evaluateFirst(c1fac, cnfac, Ap, ap); if (Bp.isZERO()) { return b; } Ap = Bp; //System.out.println("Ap = " + Ap); } C ap = a.get(dfac.nvar - 1); b = evaluateMain(cfac, Ap, ap); return b; } /** * Substitute main variable. * @param A univariate polynomial. * @param s polynomial for substitution. * @return polynomial A(x <- s). */ public static > GenPolynomial substituteMain(GenPolynomial A, GenPolynomial s) { return substituteUnivariate(A, s); } /** * Substitute univariate polynomial. * @param f univariate polynomial. * @param t polynomial for substitution. * @return polynomial A(x <- t). */ public static > GenPolynomial substituteUnivariate(GenPolynomial f, GenPolynomial t) { if (f == null || t == null) { return null; } GenPolynomialRing fac = f.ring; if (fac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomial f"); } if (f.isZERO() || f.isConstant()) { return f; } if (t.ring.nvar > 1) { fac = t.ring; } // assert decending exponents, i.e. compatible term order Map val = f.getMap(); GenPolynomial s = null; long el1 = -1; // undefined long el2 = -1; for (Map.Entry me : val.entrySet()) { ExpVector e = me.getKey(); el2 = e.getVal(0); if (s == null /*el1 < 0*/) { // first turn s = fac.getZERO().sum(me.getValue()); //val.get(e)); } else { for (long i = el2; i < el1; i++) { s = s.multiply(t); } s = s.sum(me.getValue()); //val.get(e)); } el1 = el2; } for (long i = 0; i < el2; i++) { s = s.multiply(t); } //System.out.println("s = " + s); return s; } /** * Taylor series for polynomial. * @param f univariate polynomial. * @param a expansion point. * @return Taylor series (a polynomial) of f at a. */ public static > GenPolynomial seriesOfTaylor(GenPolynomial f, C a) { if (f == null) { return null; } GenPolynomialRing fac = f.ring; if (fac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomials"); } if (f.isZERO() || f.isConstant()) { return f; } GenPolynomial s = fac.getZERO(); C fa = PolyUtil. evaluateMain(fac.coFac, f, a); s = s.sum(fa); long n = 1; long i = 0; GenPolynomial g = PolyUtil. baseDeriviative(f); //GenPolynomial p = fac.getONE(); while (!g.isZERO()) { i++; n *= i; fa = PolyUtil. evaluateMain(fac.coFac, g, a); GenPolynomial q = fac.univariate(0, i); //p; q = q.multiply(fa); q = q.divide(fac.fromInteger(n)); s = s.sum(q); g = PolyUtil. baseDeriviative(g); } //System.out.println("s = " + s); return s; } /** * ModInteger interpolate on first variable. * @param coefficient type. * @param fac GenPolynomial result factory. * @param A GenPolynomial. * @param M GenPolynomial interpolation modul of A. * @param mi inverse of M(am) in ring fac.coFac. * @param B evaluation of other GenPolynomial. * @param am evaluation point (interpolation modul) of B, i.e. P(am) = B. * @return S, with S mod M == A and S(am) == B. */ public static > GenPolynomial> interpolate( GenPolynomialRing> fac, GenPolynomial> A, GenPolynomial M, C mi, GenPolynomial B, C am) { GenPolynomial> S = fac.getZERO().copy(); GenPolynomial> Ap = A.copy(); SortedMap> av = Ap.val; //getMap(); SortedMap bv = B.getMap(); SortedMap> sv = S.val; //getMap(); GenPolynomialRing cfac = (GenPolynomialRing) fac.coFac; RingFactory bfac = cfac.coFac; GenPolynomial c = null; for (Map.Entry me : bv.entrySet()) { ExpVector e = me.getKey(); C y = me.getValue(); //bv.get(e); // assert y != null GenPolynomial x = av.get(e); if (x != null) { av.remove(e); c = PolyUtil. interpolate(cfac, x, M, mi, y, am); if (!c.isZERO()) { // 0 cannot happen sv.put(e, c); } } else { c = PolyUtil. interpolate(cfac, cfac.getZERO(), M, mi, y, am); if (!c.isZERO()) { // 0 cannot happen sv.put(e, c); // c != null } } } // assert bv is empty = done for (Map.Entry> me : av.entrySet()) { // rest of av ExpVector e = me.getKey(); GenPolynomial x = me.getValue(); //av.get(e); // assert x != null c = PolyUtil. interpolate(cfac, x, M, mi, bfac.getZERO(), am); if (!c.isZERO()) { // 0 cannot happen sv.put(e, c); // c != null } } return S; } /** * Univariate polynomial interpolation. * @param coefficient type. * @param fac GenPolynomial result factory. * @param A GenPolynomial. * @param M GenPolynomial interpolation modul of A. * @param mi inverse of M(am) in ring fac.coFac. * @param a evaluation of other GenPolynomial. * @param am evaluation point (interpolation modul) of a, i.e. P(am) = a. * @return S, with S mod M == A and S(am) == a. */ public static > GenPolynomial interpolate(GenPolynomialRing fac, GenPolynomial A, GenPolynomial M, C mi, C a, C am) { GenPolynomial s; C b = PolyUtil. evaluateMain(fac.coFac, A, am); // A mod a.modul C d = a.subtract(b); // a-A mod a.modul if (d.isZERO()) { return A; } b = d.multiply(mi); // b = (a-A)*mi mod a.modul // (M*b)+A mod M = A mod M = // (M*mi*(a-A)+A) mod a.modul = a mod a.modul s = M.multiply(b); s = s.sum(A); return s; } /** * Recursive GenPolynomial switch varaible blocks. * @param coefficient type. * @param P recursive GenPolynomial in R[X,Y]. * @return this in R[Y,X]. */ public static > GenPolynomial> switchVariables( GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException("P == null"); } GenPolynomialRing> rfac1 = P.ring; GenPolynomialRing cfac1 = (GenPolynomialRing) rfac1.coFac; GenPolynomialRing cfac2 = new GenPolynomialRing(cfac1.coFac, rfac1); GenPolynomial zero = cfac2.getZERO(); GenPolynomialRing> rfac2 = new GenPolynomialRing>(cfac2, cfac1); GenPolynomial> B = rfac2.getZERO().copy(); if (P.isZERO()) { return B; } for (Monomial> mr : P) { GenPolynomial cr = mr.c; for (Monomial mc : cr) { GenPolynomial c = zero.sum(mc.c, mr.e); B = B.sum(c, mc.e); } } return B; } /** * Maximal degree of leading terms of a polynomial list. * @return maximum degree of the leading terms of a polynomial list. */ public static > long totalDegreeLeadingTerm(List> P) { long degree = 0; for (GenPolynomial g : P) { long total = g.leadingExpVector().totalDeg(); if (degree < total) { degree = total; } } return degree; } /** * Maximal degree of polynomial list. * @return maximum degree of the polynomial list. */ public static > long totalDegree(List> P) { long degree = 0; for (GenPolynomial g : P) { long total = g.degree(); if (degree < total) { degree = total; } } return degree; } /** * Maximal degree in the coefficient polynomials. * @param coefficient type. * @return maximal degree in the coefficients. */ public static > long coeffMaxDegree(GenPolynomial> A) { if (A.isZERO()) { return 0; // 0 or -1 ?; } long deg = 0; for (GenPolynomial a : A.getMap().values()) { long d = a.degree(); if (d > deg) { deg = d; } } return deg; } /** * Map a unary function to the coefficients. * @param ring result polynomial ring factory. * @param p polynomial. * @param f evaluation functor. * @return new polynomial with coefficients f(p(e)). */ public static , D extends RingElem> GenPolynomial map( GenPolynomialRing ring, GenPolynomial p, UnaryFunctor f) { GenPolynomial n = ring.getZERO().copy(); SortedMap nv = n.val; for (Monomial m : p) { D c = f.eval(m.c); if (c != null && !c.isZERO()) { nv.put(m.e, c); } } return n; } /** * Product representation. * @param coefficient type. * @param pfac polynomial ring factory. * @param L list of polynomials to be represented. * @return Product represenation of L in the polynomial ring pfac. */ public static > List>> toProductGen( GenPolynomialRing> pfac, List> L) { List>> list = new ArrayList>>(); if (L == null || L.size() == 0) { return list; } for (GenPolynomial a : L) { GenPolynomial> b = toProductGen(pfac, a); list.add(b); } return list; } /** * Product representation. * @param coefficient type. * @param pfac polynomial ring factory. * @param A polynomial to be represented. * @return Product represenation of A in the polynomial ring pfac. */ public static > GenPolynomial> toProductGen( GenPolynomialRing> pfac, GenPolynomial A) { GenPolynomial> P = pfac.getZERO().copy(); if (A == null || A.isZERO()) { return P; } RingFactory> rpfac = pfac.coFac; ProductRing rfac = (ProductRing) rpfac; for (Map.Entry y : A.getMap().entrySet()) { ExpVector e = y.getKey(); C a = y.getValue(); Product p = toProductGen(rfac, a); if (!p.isZERO()) { P.doPutToMap(e, p); } } return P; } /** * Product representation. * @param coefficient type. * @param pfac product ring factory. * @param c coefficient to be represented. * @return Product represenation of c in the ring pfac. */ public static > Product toProductGen(ProductRing pfac, C c) { SortedMap elem = new TreeMap(); for (int i = 0; i < pfac.length(); i++) { RingFactory rfac = pfac.getFactory(i); C u = rfac.copy(c); if (u != null && !u.isZERO()) { elem.put(i, u); } } return new Product(pfac, elem); } /** * Product representation. * @param coefficient type. * @param pfac product polynomial ring factory. * @param c coefficient to be used. * @param e exponent vector. * @return Product represenation of c X^e in the ring pfac. */ public static > Product> toProduct( ProductRing> pfac, C c, ExpVector e) { SortedMap> elem = new TreeMap>(); for (int i = 0; i < e.length(); i++) { RingFactory> rfac = pfac.getFactory(i); GenPolynomialRing fac = (GenPolynomialRing) rfac; //GenPolynomialRing cfac = fac.ring; long a = e.getVal(i); GenPolynomial u; if (a == 0) { u = fac.getONE(); } else { u = fac.univariate(0, a); } u = u.multiply(c); elem.put(i, u); } return new Product>(pfac, elem); } /** * Product representation. * @param coefficient type. * @param pfac product polynomial ring factory. * @param A polynomial. * @return Product represenation of the terms of A in the ring pfac. */ public static > Product> toProduct( ProductRing> pfac, GenPolynomial A) { Product> P = pfac.getZERO(); if (A == null || A.isZERO()) { return P; } for (Map.Entry y : A.getMap().entrySet()) { ExpVector e = y.getKey(); C a = y.getValue(); Product> p = toProduct(pfac, a, e); P = P.sum(p); } return P; } /** * Product representation. * @param pfac product ring factory. * @param c coefficient to be represented. * @return Product represenation of c in the ring pfac. */ public static Product toProduct(ProductRing pfac, BigInteger c) { SortedMap elem = new TreeMap(); for (int i = 0; i < pfac.length(); i++) { RingFactory rfac = pfac.getFactory(i); ModIntegerRing fac = (ModIntegerRing) rfac; ModInteger u = fac.fromInteger(c.getVal()); if (!u.isZERO()) { elem.put(i, u); } } return new Product(pfac, elem); } /** * Product representation. * @param pfac polynomial ring factory. * @param A polynomial to be represented. * @return Product represenation of A in the polynomial ring pfac. */ public static GenPolynomial> toProduct(GenPolynomialRing> pfac, GenPolynomial A) { GenPolynomial> P = pfac.getZERO().copy(); if (A == null || A.isZERO()) { return P; } RingFactory> rpfac = pfac.coFac; ProductRing fac = (ProductRing) rpfac; for (Map.Entry y : A.getMap().entrySet()) { ExpVector e = y.getKey(); BigInteger a = y.getValue(); Product p = toProduct(fac, a); if (!p.isZERO()) { P.doPutToMap(e, p); } } return P; } /** * Product representation. * @param pfac polynomial ring factory. * @param L list of polynomials to be represented. * @return Product represenation of L in the polynomial ring pfac. */ public static List>> toProduct( GenPolynomialRing> pfac, List> L) { List>> list = new ArrayList>>(); if (L == null || L.size() == 0) { return list; } for (GenPolynomial a : L) { GenPolynomial> b = toProduct(pfac, a); list.add(b); } return list; } /** * Remove all upper variables which do not occur in polynomial. * @param p polynomial. * @return polynomial with removed variables */ public static > GenPolynomial removeUnusedUpperVariables(GenPolynomial p) { GenPolynomialRing fac = p.ring; if (fac.nvar <= 1) { // univariate return p; } int[] dep = p.degreeVector().dependencyOnVariables(); if (fac.nvar == dep.length) { // all variables appear return p; } if (dep.length == 0) { // no variables GenPolynomialRing fac0 = new GenPolynomialRing(fac.coFac, 0); GenPolynomial p0 = new GenPolynomial(fac0, p.leadingBaseCoefficient()); return p0; } int l = dep[0]; // higher variable int r = dep[dep.length - 1]; // lower variable if (l == 0 /*|| l == fac.nvar-1*/) { // upper variable appears return p; } int n = l; GenPolynomialRing facr = fac.contract(n); Map> mpr = p.contract(facr); if (mpr.size() != 1) { System.out.println("upper ex, l = " + l + ", r = " + r + ", p = " + p + ", fac = " + fac.toScript()); throw new RuntimeException("this should not happen " + mpr); } GenPolynomial pr = mpr.values().iterator().next(); n = fac.nvar - 1 - r; if (n == 0) { return pr; } // else case not implemented return pr; } /** * Remove all lower variables which do not occur in polynomial. * @param p polynomial. * @return polynomial with removed variables */ public static > GenPolynomial removeUnusedLowerVariables(GenPolynomial p) { GenPolynomialRing fac = p.ring; if (fac.nvar <= 1) { // univariate return p; } int[] dep = p.degreeVector().dependencyOnVariables(); if (fac.nvar == dep.length) { // all variables appear return p; } if (dep.length == 0) { // no variables GenPolynomialRing fac0 = new GenPolynomialRing(fac.coFac, 0); GenPolynomial p0 = new GenPolynomial(fac0, p.leadingBaseCoefficient()); return p0; } int l = dep[0]; // higher variable int r = dep[dep.length - 1]; // lower variable if (r == fac.nvar - 1) { // lower variable appears return p; } int n = r + 1; GenPolynomialRing> rfac = fac.recursive(n); GenPolynomial> mpr = recursive(rfac, p); if (mpr.length() != p.length()) { System.out.println("lower ex, l = " + l + ", r = " + r + ", p = " + p + ", fac = " + fac.toScript()); throw new RuntimeException("this should not happen " + mpr); } RingFactory cf = fac.coFac; GenPolynomialRing facl = new GenPolynomialRing(cf, rfac); GenPolynomial pr = facl.getZERO().copy(); for (Monomial> m : mpr) { ExpVector e = m.e; GenPolynomial a = m.c; if (!a.isConstant()) { throw new RuntimeException("this can not happen " + a); } C c = a.leadingBaseCoefficient(); pr.doPutToMap(e, c); } return pr; } /** * Remove upper block of middle variables which do not occur in polynomial. * @param p polynomial. * @return polynomial with removed variables */ public static > GenPolynomial removeUnusedMiddleVariables(GenPolynomial p) { GenPolynomialRing fac = p.ring; if (fac.nvar <= 2) { // univariate or bi-variate return p; } int[] dep = p.degreeVector().dependencyOnVariables(); if (fac.nvar == dep.length) { // all variables appear return p; } if (dep.length == 0) { // no variables GenPolynomialRing fac0 = new GenPolynomialRing(fac.coFac, 0); GenPolynomial p0 = new GenPolynomial(fac0, p.leadingBaseCoefficient()); return p0; } ExpVector e1 = p.leadingExpVector(); if (dep.length == 1) { // one variable TermOrder to = new TermOrder(fac.tord.getEvord()); int i = dep[0]; String v1 = e1.indexVarName(i, fac.getVars()); String[] vars = new String[] { v1 }; GenPolynomialRing fac1 = new GenPolynomialRing(fac.coFac, to, vars); GenPolynomial p1 = fac1.getZERO().copy(); for (Monomial m : p) { ExpVector e = m.e; ExpVector f = ExpVector.create(1, 0, e.getVal(i)); p1.doPutToMap(f, m.c); } return p1; } GenPolynomialRing> rfac = fac.recursive(1); GenPolynomial> mpr = recursive(rfac, p); int l = dep[0]; // higher variable int r = fac.nvar - dep[1]; // next variable //System.out.println("l = " + l); //System.out.println("r = " + r); TermOrder to = new TermOrder(fac.tord.getEvord()); String[] vs = fac.getVars(); String[] vars = new String[r + 1]; for (int i = 0; i < r; i++) { vars[i] = vs[i]; } vars[r] = e1.indexVarName(l, vs); //System.out.println("fac = " + fac); GenPolynomialRing dfac = new GenPolynomialRing(fac.coFac, to, vars); //System.out.println("dfac = " + dfac); GenPolynomialRing> fac2 = dfac.recursive(1); GenPolynomialRing cfac = (GenPolynomialRing) fac2.coFac; GenPolynomial> p2r = fac2.getZERO().copy(); for (Monomial> m : mpr) { ExpVector e = m.e; GenPolynomial a = m.c; Map> cc = a.contract(cfac); for (Map.Entry> me : cc.entrySet()) { ExpVector f = me.getKey(); if (f.isZERO()) { GenPolynomial c = me.getValue(); //cc.get(f); p2r.doPutToMap(e, c); } else { throw new RuntimeException("this should not happen " + cc); } } } GenPolynomial p2 = distribute(dfac, p2r); return p2; } /** * Select polynomial with univariate leading term in variable i. * @param i variable index. * @return polynomial with head term in variable i */ public static > GenPolynomial selectWithVariable(List> P, int i) { for (GenPolynomial p : P) { int[] dep = p.leadingExpVector().dependencyOnVariables(); if (dep.length == 1 && dep[0] == i) { return p; } } return null; // not found } } /** * Conversion of distributive to recursive representation. */ class DistToRec> implements UnaryFunctor, GenPolynomial>> { GenPolynomialRing> fac; public DistToRec(GenPolynomialRing> fac) { this.fac = fac; } public GenPolynomial> eval(GenPolynomial c) { if (c == null) { return fac.getZERO(); } return PolyUtil. recursive(fac, c); } } /** * Conversion of recursive to distributive representation. */ class RecToDist> implements UnaryFunctor>, GenPolynomial> { GenPolynomialRing fac; public RecToDist(GenPolynomialRing fac) { this.fac = fac; } public GenPolynomial eval(GenPolynomial> c) { if (c == null) { return fac.getZERO(); } return PolyUtil. distribute(fac, c); } } /** * BigRational numerator functor. */ class RatNumer implements UnaryFunctor { public BigInteger eval(BigRational c) { if (c == null) { return new BigInteger(); } return new BigInteger(c.numerator()); } } /** * Conversion of symmetric ModInteger to BigInteger functor. */ class ModSymToInt & Modular> implements UnaryFunctor { public BigInteger eval(C c) { if (c == null) { return new BigInteger(); } return c.getSymmetricInteger(); } } /** * Conversion of ModInteger to BigInteger functor. */ class ModToInt & Modular> implements UnaryFunctor { public BigInteger eval(C c) { if (c == null) { return new BigInteger(); } return c.getInteger(); } } /** * Conversion of BigRational to BigInteger with division by lcm functor. result * = num*(lcm/denom). */ class RatToInt implements UnaryFunctor { java.math.BigInteger lcm; public RatToInt(java.math.BigInteger lcm) { this.lcm = lcm; //.getVal(); } public BigInteger eval(BigRational c) { if (c == null) { return new BigInteger(); } // p = num*(lcm/denom) java.math.BigInteger b = lcm.divide(c.denominator()); return new BigInteger(c.numerator().multiply(b)); } } /** *  * Conversion of BigRational to BigInteger. result = (num/gcd)*(lcm/denom).   */ class RatToIntFactor implements UnaryFunctor { final java.math.BigInteger lcm; final java.math.BigInteger gcd; public RatToIntFactor(java.math.BigInteger gcd, java.math.BigInteger lcm) { this.gcd = gcd; this.lcm = lcm; // .getVal(); } public BigInteger eval(BigRational c) { if (c == null) { return new BigInteger(); } if (gcd.equals(java.math.BigInteger.ONE)) { // p = num*(lcm/denom) java.math.BigInteger b = lcm.divide(c.denominator()); return new BigInteger(c.numerator().multiply(b)); } // p = (num/gcd)*(lcm/denom) java.math.BigInteger a = c.numerator().divide(gcd); java.math.BigInteger b = lcm.divide(c.denominator()); return new BigInteger(a.multiply(b)); } } /** * Conversion of Rational to BigDecimal. result = decimal(r). */ class RatToDec & Rational> implements UnaryFunctor { public BigDecimal eval(C c) { if (c == null) { return new BigDecimal(); } return new BigDecimal(c.getRational()); } } /** * Conversion of Complex Rational to Complex BigDecimal. result = decimal(r). */ class CompRatToDec & Rational> implements UnaryFunctor, Complex> { ComplexRing ring; public CompRatToDec(RingFactory> ring) { this.ring = (ComplexRing) ring; } public Complex eval(Complex c) { if (c == null) { return ring.getZERO(); } BigDecimal r = new BigDecimal(c.getRe().getRational()); BigDecimal i = new BigDecimal(c.getIm().getRational()); return new Complex(ring, r, i); } } /** * Conversion from BigInteger functor. */ class FromInteger> implements UnaryFunctor { RingFactory ring; public FromInteger(RingFactory ring) { this.ring = ring; } public D eval(BigInteger c) { if (c == null) { return ring.getZERO(); } return ring.fromInteger(c.getVal()); } } /** * Conversion from GenPolynomial functor. */ class FromIntegerPoly> implements UnaryFunctor, GenPolynomial> { GenPolynomialRing ring; FromInteger fi; public FromIntegerPoly(GenPolynomialRing ring) { if (ring == null) { throw new IllegalArgumentException("ring must not be null"); } this.ring = ring; fi = new FromInteger(ring.coFac); } public GenPolynomial eval(GenPolynomial c) { if (c == null) { return ring.getZERO(); } return PolyUtil. map(ring, c, fi); } } /** * Conversion from GenPolynomial to GenPolynomial * functor. */ class RatToIntPoly implements UnaryFunctor, GenPolynomial> { GenPolynomialRing ring; public RatToIntPoly(GenPolynomialRing ring) { if (ring == null) { throw new IllegalArgumentException("ring must not be null"); } this.ring = ring; } public GenPolynomial eval(GenPolynomial c) { if (c == null) { return ring.getZERO(); } return PolyUtil.integerFromRationalCoefficients(ring, c); } } /** * Real part functor. */ class RealPart implements UnaryFunctor { public BigRational eval(BigComplex c) { if (c == null) { return new BigRational(); } return c.getRe(); } } /** * Imaginary part functor. */ class ImagPart implements UnaryFunctor { public BigRational eval(BigComplex c) { if (c == null) { return new BigRational(); } return c.getIm(); } } /** * Real part functor. */ class RealPartComplex> implements UnaryFunctor, C> { public C eval(Complex c) { if (c == null) { return null; } return c.getRe(); } } /** * Imaginary part functor. */ class ImagPartComplex> implements UnaryFunctor, C> { public C eval(Complex c) { if (c == null) { return null; } return c.getIm(); } } /** * Rational to complex functor. */ class ToComplex> implements UnaryFunctor> { final protected ComplexRing cfac; @SuppressWarnings("unchecked") public ToComplex(RingFactory> fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } cfac = (ComplexRing) fac; } public Complex eval(C c) { if (c == null) { return cfac.getZERO(); } return new Complex(cfac, c); } } /** * Rational to complex functor. */ class RatToCompl implements UnaryFunctor { public BigComplex eval(BigRational c) { if (c == null) { return new BigComplex(); } return new BigComplex(c); } } /** * Any ring element to generic complex functor. */ class AnyToComplex> implements UnaryFunctor> { final protected ComplexRing cfac; public AnyToComplex(ComplexRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } cfac = fac; } public AnyToComplex(RingFactory fac) { this(new ComplexRing(fac)); } public Complex eval(C a) { if (a == null || a.isZERO()) { // should not happen return cfac.getZERO(); } else if (a.isONE()) { return cfac.getONE(); } else { return new Complex(cfac, a); } } } /** * Algebraic to generic complex functor. */ class AlgebToCompl> implements UnaryFunctor, Complex> { final protected ComplexRing cfac; public AlgebToCompl(ComplexRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } cfac = fac; } public Complex eval(AlgebraicNumber a) { if (a == null || a.isZERO()) { // should not happen return cfac.getZERO(); } else if (a.isONE()) { return cfac.getONE(); } else { GenPolynomial p = a.getVal(); C real = cfac.ring.getZERO(); C imag = cfac.ring.getZERO(); for (Monomial m : p) { if (m.exponent().getVal(0) == 1L) { imag = m.coefficient(); } else if (m.exponent().getVal(0) == 0L) { real = m.coefficient(); } else { throw new IllegalArgumentException("unexpected monomial " + m); } } //Complex c = new Complex(cfac,real,imag); return new Complex(cfac, real, imag); } } } /** * Ceneric complex to algebraic number functor. */ class ComplToAlgeb> implements UnaryFunctor, AlgebraicNumber> { final protected AlgebraicNumberRing afac; final protected AlgebraicNumber I; public ComplToAlgeb(AlgebraicNumberRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } afac = fac; I = afac.getGenerator(); } public AlgebraicNumber eval(Complex c) { if (c == null || c.isZERO()) { // should not happen return afac.getZERO(); } else if (c.isONE()) { return afac.getONE(); } else if (c.isIMAG()) { return I; } else { return I.multiply(c.getIm()).sum(c.getRe()); } } } /** * Algebraic to polynomial functor. */ class AlgToPoly> implements UnaryFunctor, GenPolynomial> { public GenPolynomial eval(AlgebraicNumber c) { if (c == null) { return null; } return c.val; } } /** * Polynomial to algebriac functor. */ class PolyToAlg> implements UnaryFunctor, AlgebraicNumber> { final protected AlgebraicNumberRing afac; public PolyToAlg(AlgebraicNumberRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } afac = fac; } public AlgebraicNumber eval(GenPolynomial c) { if (c == null) { return afac.getZERO(); } return new AlgebraicNumber(afac, c); } } /** * Coefficient to algebriac functor. */ class CoeffToAlg> implements UnaryFunctor> { final protected AlgebraicNumberRing afac; final protected GenPolynomial zero; public CoeffToAlg(AlgebraicNumberRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } afac = fac; GenPolynomialRing pfac = afac.ring; zero = pfac.getZERO(); } public AlgebraicNumber eval(C c) { if (c == null) { return afac.getZERO(); } return new AlgebraicNumber(afac, zero.sum(c)); } } /** * Coefficient to recursive algebriac functor. */ class CoeffToRecAlg> implements UnaryFunctor> { final protected List> lfac; final int depth; @SuppressWarnings("unchecked") public CoeffToRecAlg(int depth, AlgebraicNumberRing fac) { if (fac == null) { throw new IllegalArgumentException("fac must not be null"); } AlgebraicNumberRing afac = fac; this.depth = depth; lfac = new ArrayList>(this.depth); lfac.add(fac); for (int i = 1; i < this.depth; i++) { RingFactory rf = afac.ring.coFac; if (!(rf instanceof AlgebraicNumberRing)) { throw new IllegalArgumentException("fac depth to low"); } afac = (AlgebraicNumberRing) (Object) rf; lfac.add(afac); } } @SuppressWarnings("unchecked") public AlgebraicNumber eval(C c) { if (c == null) { return lfac.get(0).getZERO(); } C ac = c; AlgebraicNumberRing af = lfac.get(lfac.size() - 1); GenPolynomial zero = af.ring.getZERO(); AlgebraicNumber an = new AlgebraicNumber(af, zero.sum(ac)); for (int i = lfac.size() - 2; i >= 0; i--) { af = lfac.get(i); zero = af.ring.getZERO(); ac = (C) (Object) an; an = new AlgebraicNumber(af, zero.sum(ac)); } return an; } } /** * Evaluate main variable functor. */ class EvalMain> implements UnaryFunctor, C> { final RingFactory cfac; final C a; public EvalMain(RingFactory cfac, C a) { this.cfac = cfac; this.a = a; } public C eval(GenPolynomial c) { if (c == null) { return cfac.getZERO(); } return PolyUtil. evaluateMain(cfac, c, a); } } /** * Evaluate main variable functor. */ class EvalMainPol> implements UnaryFunctor, GenPolynomial> { final GenPolynomialRing cfac; final C a; public EvalMainPol(GenPolynomialRing cfac, C a) { this.cfac = cfac; this.a = a; } public GenPolynomial eval(GenPolynomial c) { if (c == null) { return cfac.getZERO(); } return PolyUtil. evaluateMain(cfac, c, a); } } jas-2.5/src/edu/jas/poly/package.html0000644000175000017500000000265012027161170017730 0ustar giovannigiovanni Generic coefficients polynomial package

Generic coefficients polynomial package.

This package contains classes for polynomial, solvable polynomial and free non-commutative polynomial arithmetic, e.g. GenPolynomial, GenSolvablePolynomial or GenWordPolynomial over coefficient rings which implement the RingElem interface. For arithmetic of commutative exponents and words over arbitrary alphabets are the classes ExpVector and Word with WordFactory. Other classes contained in this package are AlgebraicNumber, PolyUtil and a polynomial parser GenPolynomialTokenizer. Some classes implement quotient rings or residue class rings, etc., based only on the interfaces in the edu.jas.structure package.


Heinz Kredel

Last modified: Fri Sep 21 21:50:21 CEST 2012

$Id: package.html 4215 2012-09-21 21:56:08Z kredel $

jas-2.5/src/edu/jas/poly/Word.java0000644000175000017500000003453412025436454017243 0ustar giovannigiovanni/* * $Id: Word.java 4198 2012-09-16 20:57:16Z kredel $ */ package edu.jas.poly; import java.io.Serializable; import java.util.SortedMap; import java.util.TreeMap; import java.util.List; import java.util.ArrayList; import java.util.Arrays; import edu.jas.structure.MonoidElem; import edu.jas.structure.MonoidFactory; import edu.jas.structure.NotInvertibleException; /** * Word implements strings of letters for polynomials. * @author Heinz Kredel */ public final class Word implements MonoidElem { /** * Defining alphabet in WordFactory. */ public final WordFactory mono; /** * The data structure is a String of characters. */ /*package*/final String val; /** * Stored hash code. */ protected int hash = 0; /** * Constructor for Word. * @param m factory for words. */ public Word(WordFactory m) { this(m, ""); } /** * Constructor for Word. * @param m factory for words. * @param s String */ public Word(WordFactory m, String s) { this(m,s,true); } /** * Constructor for Word. * @param m factory for words. * @param s String * @param translate indicator if s needs translation */ public Word(WordFactory m, String s, boolean translate) { mono = m; hash = 0; if (s == null) { throw new IllegalArgumentException("null string not allowed"); } if ( translate ) { if ( mono.translation != null ) { //System.out.println("s = " + s); String[] S = GenPolynomialTokenizer.variableList(s); //System.out.println("S = " + Arrays.toString(S)); val = mono.translate(S); //System.out.println("val = " + val); } else { val = WordFactory.cleanSpace(s); //?? } } else { val = s; } } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public MonoidFactory factory() { return mono; } /** * Copy this. * @return copy of this. */ @Override public Word copy() { return new Word(mono, val, false); } /** * Get the word String. * @return val. */ /*package*/String getVal() { return val; } /** * Get the letter at position i. * @param i position. * @return val[i]. */ public char getVal(int i) { return val.charAt(i); } /** * Get the length of this word. * @return val.length. */ public int length() { return val.length(); } /** * Get the string representation. * @see java.lang.Object#toString() */ @Override public String toString() { if (val.length() == 0) { return ""; } StringBuffer s = new StringBuffer("\""); String vv; if ( mono.translation == null ) { for (int i = 0; i < length(); i++) { if (i != 0) { s.append(" "); } s.append(getVal(i)); } } else { for (int i = 0; i < length(); i++) { if (i != 0) { s.append(" "); } s.append(mono.transVar(getVal(i))); } } s.append("\""); return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { if (val.length() == 0) { return ""; } StringBuffer s = new StringBuffer(""); if ( mono.translation == null ) { for (int i = 0; i < length(); i++) { if (i != 0) { s.append("*"); // checked for python vs ruby } s.append(getVal(i)); } } else { for (int i = 0; i < length(); i++) { if (i != 0) { s.append("*"); // checked for python vs ruby } s.append(mono.transVar(getVal(i))); } } s.append(""); return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return mono.toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof Word)) { return false; } Word b = (Word) B; // mono == b.mono ?? int t = this.compareTo(b); //System.out.println("equals: this = " + this + " B = " + B + " t = " + t); return (0 == t); } /** * hashCode. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { if (hash == 0) { hash = val.hashCode(); } return hash; } /** * Is Word one. * @return If this is the empty word then true is returned, else false. */ public boolean isONE() { return (0 == this.length()); } /** * Is Word unit. * @return If this is a unit then true is returned, else false. */ public boolean isUnit() { return isONE(); } /** * Word multiplication. * @param V other word. * @return this * V. */ public Word multiply(Word V) { return new Word(mono, this.val + V.val, false); } /** * Word divide. * @param V other word. * @return this / V. */ public Word divide(Word V) { Word[] ret = divideWord(V); // TODO: fail if both non zero? if (!ret[0].isONE() && !ret[1].isONE()) { throw new IllegalArgumentException("not simple dividable: left = " + ret[0] + ", right = " + ret[1] + ", use divideWord"); } return ret[0].multiply(ret[1]); } /** * Word divide with prefix and suffix. * @param V other word. * @return [prefix(this/V), suffix(this/V)] = [left,right] with left * V * right = this. */ public Word[] divideWord(Word V) { int i = this.val.indexOf(V.val); if (i < 0) { throw new NotInvertibleException("not dividable: " + this + ", other " + V); } int len = V.val.length(); String pre = this.val.substring(0, i); String suf = this.val.substring(i + len); Word[] ret = new Word[2]; ret[0] = new Word(mono, pre, false); ret[1] = new Word(mono, suf, false); return ret; } /** * Word remainder. * @param V other word. * @return this (this/V). Note: not useful. */ public Word remainder(Word V) { int i = this.val.indexOf(V.val); if (i < 0) { throw new NotInvertibleException("not dividable: " + this + ", other " + V); } return V; } /** * Word inverse. * @return 1 / this. */ public Word inverse() { if ( val.length() == 0 ) { return this; } throw new NotInvertibleException("not inversible " + this); } /** * Word signum. * @return 0 if this is one, 1 if it is non empty. */ public int signum() { int i = val.length(); if (i > 0) { i = 1; } assert i >= 0; return i; } /** * Word degree. * @return total degree of all letters. */ public long degree() { return val.length(); } /** * Word dependency on letters. * @return sorted map of letters and the number of its occurences. */ public SortedMap dependencyOnVariables() { SortedMap map = new TreeMap(); for ( int i = 0; i < val.length(); i++ ) { String s = String.valueOf( val.charAt(i) ); Integer n = map.get(s); if ( n == null ) { n = 0; } n = n + 1; map.put(s,n); } return map; } /** * Word multiple test. * @param V other word. * @return true if this is a multiple of V, else false. */ public boolean multipleOf(Word V) { return this.val.contains(V.val); } /** * Word divides test. * @param V other word. * @return true if this divides V, else false. */ public boolean divides(Word V) { return V.val.contains(this.val); } /** * Word compareTo. Uses
String.compareTo
. * @param V other word. * @return 0 if U == V, -1 if U < V, 1 if U > V. */ //JAVA6only: @Override public int compareTo(Word V) { return this.val.compareTo(V.val); } /** * Word graded comparison. Compares first be degree, then lexicographical. * @param V other word. * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public int gradCompareTo(Word V) { long e = this.degree(); long f = V.degree(); if (e < f) { return 1; } else if (e > f) { return -1; } return this.compareTo(V); } /** * Word graded comparison. Compares first be degree, then inverse lexicographical. * @param V other word. * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public int gradInvlexCompareTo(Word V) { long e = this.degree(); long f = V.degree(); if (e < f) { return 1; } else if (e > f) { return -1; } return -this.compareTo(V); } /** * Is word overlap. * @param ol = [l1,r1,l2,r2] an Overlap container of four words * @param V word * @return true if l1 * this * r1 = l2 * V * r2, else false. */ public boolean isOverlap(Overlap ol, Word V) { return ol.isOverlap(this,V); } /** * Word overlap list. * @param V other word. * @return list of overlaps [l1,r1,l2,r2] with l1 * this * r1 = l2 * V * r2. * If no such overlaps exist the empty overlap list is returned. */ public OverlapList overlap(Word V) { OverlapList ret = new OverlapList(); Word wone = mono.getONE(); String a = this.val; String b = V.val; int ai = a.length(); int bi = b.length(); int j = b.indexOf(a); if (j >= 0) { while ( j >= 0 ) { String pre = b.substring(0, j); String suf = b.substring(j + ai); Word wpre = new Word(mono, pre, false); Word wsuf = new Word(mono, suf, false); ret.add(new Overlap(wpre,wsuf,wone,wone)); j = b.indexOf(a,j+ai); // +1 also inner overlaps ? } return ret; } j = a.indexOf(b); if (j >= 0) { while ( j >= 0 ) { String pre = a.substring(0, j); String suf = a.substring(j + bi); Word wpre = new Word(mono, pre, false); Word wsuf = new Word(mono, suf, false); ret.add(new Overlap(wone,wone,wpre,wsuf)); j = a.indexOf(b,j+bi); // +1 also inner overlaps ? } return ret; } if ( ai >= bi ) { for ( int i = 0; i < bi; i++ ) { String as = a.substring(0,i+1); String bs = b.substring(bi-i-1,bi); //System.out.println("i = " + i + ", bs = " + bs + ", as = " + as); if ( as.equals(bs) ) { Word w1 = new Word(mono, b.substring(0,bi-i-1), false); Word w2 = new Word(mono, a.substring(i+1), false); ret.add(new Overlap(w1, wone, wone, w2)); break; } } for ( int i = 0; i < bi; i++ ) { String as = a.substring(ai-i-1,ai); String bs = b.substring(0,i+1); //System.out.println("i = " + i + ", bs = " + bs + ", as = " + as); if ( as.equals(bs) ) { Word w1 = new Word(mono, b.substring(i+1), false); Word w2 = new Word(mono, a.substring(0,ai-i-1), false); ret.add(new Overlap(wone, w1, w2, wone)); break; } } } else { // ai < bi for ( int i = 0; i < ai; i++ ) { String as = a.substring(ai-i-1,ai); String bs = b.substring(0,i+1); //System.out.println("i = " + i + ", bs = " + bs + ", as = " + as); if ( as.equals(bs) ) { Word w1 = new Word(mono, b.substring(i+1), false); Word w2 = new Word(mono, a.substring(0,ai-i-1), false); ret.add(new Overlap(wone, w1, w2, wone)); break; } } for ( int i = 0; i < ai; i++ ) { String as = a.substring(0,i+1); String bs = b.substring(bi-i-1,bi); //System.out.println("i = " + i + ", bs = " + bs + ", as = " + as); if ( as.equals(bs) ) { Word w1 = new Word(mono, b.substring(0,bi-i-1), false); Word w2 = new Word(mono, a.substring(i+1), false); ret.add(new Overlap(w1, wone, wone, w2)); break; } } } return ret; } /** * Word pseudo least common multiple. * @param V other word. * @return w = l1*this*r1, with l1*this*r1 == l2*V*r2, if l1, r1, l2, r2 exist, * else null is returned. */ public Word lcm(Word V) { OverlapList oll = overlap(V); if ( oll.ols.isEmpty() ) { return null; } Overlap ol = oll.ols.get(0); Word g = ol.l1.multiply(this).multiply(ol.r1); return g; } } jas-2.5/src/edu/jas/poly/OrderedPolynomialList.java0000644000175000017500000000670312004325040022572 0ustar giovannigiovanni/* * $Id: OrderedPolynomialList.java 4057 2012-07-26 20:35:44Z kredel $ */ package edu.jas.poly; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import edu.jas.structure.RingElem; /** * Ordered list of polynomials. Mainly for storage and printing / toString and * conversions to other representations. Polynomials in this list are sorted * according to their head terms. * @author Heinz Kredel */ public class OrderedPolynomialList> extends PolynomialList { /** * Constructor. * @param r polynomial ring factory. * @param l list of polynomials. */ public OrderedPolynomialList(GenPolynomialRing r, List> l) { super(r, sort(r, l)); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object p) { if (!super.equals(p)) { return false; } OrderedPolynomialList pl = null; try { pl = (OrderedPolynomialList) p; } catch (ClassCastException ignored) { } if (pl == null) { return false; } // compare sorted lists // done already in super.equals() return true; } /** * Hash code for OrderedPolynomialList. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return super.hashCode(); } /** * Sort a list of polynomials with respect to the ascending order of the * leading Exponent vectors. The term order is taken from the ring. * @param r polynomial ring factory. * @param L polynomial list. * @return sorted polynomial list from L. */ @SuppressWarnings("unchecked") public static > List> sort(GenPolynomialRing r, List> L) { if (L == null) { return L; } if (L.size() <= 1) { // nothing to sort return L; } final Comparator evc = r.tord.getAscendComparator(); Comparator> cmp = new Comparator>() { public int compare(GenPolynomial p1, GenPolynomial p2) { ExpVector e1 = p1.leadingExpVector(); ExpVector e2 = p2.leadingExpVector(); if (e1 == null) { return -1; // dont care } if (e2 == null) { return 1; // dont care } if (e1.length() != e2.length()) { if (e1.length() > e2.length()) { return 1; // dont care } return -1; // dont care } return evc.compare(e1, e2); } }; GenPolynomial[] s = null; try { s = (GenPolynomial[]) new GenPolynomial[L.size()]; int i = 0; for (GenPolynomial p : L) { s[i++] = p; } Arrays.> sort(s, cmp); return new ArrayList>(Arrays.> asList(s)); } catch (ClassCastException ok) { System.out.println("Warning: polynomials not sorted"); } return L; // unsorted } } jas-2.5/src/edu/jas/poly/OptimizedPolynomialList.java0000644000175000017500000000207412000260360023146 0ustar giovannigiovanni/* * $Id: OptimizedPolynomialList.java 3988 2012-07-14 12:07:13Z kredel $ */ package edu.jas.poly; import java.util.List; import edu.jas.structure.RingElem; /** * Container for optimization results. * @author Heinz Kredel */ public class OptimizedPolynomialList> extends PolynomialList { /** * Permutation vector used to optimize term order. */ public final List perm; /** * Constructor. */ public OptimizedPolynomialList(List P, GenPolynomialRing R, List> L) { super(R, L); perm = P; } /** * String representation. */ @Override public String toString() { return "permutation = " + perm + "\n" + super.toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof OptimizedPolynomialList)) { return false; } return super.equals(B); } } jas-2.5/src/edu/jas/poly/WeylRelations.java0000644000175000017500000000522012014234362021107 0ustar giovannigiovanni/* * $Id: WeylRelations.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.poly; import org.apache.log4j.Logger; import edu.jas.structure.RingElem; /** * Generate Relation Table for Weyl Algebras * Adds the respective relations to the relation table * of the given solvable ring factory. Relations are of the * form xj * xi = xi xj + 1. * @author Heinz Kredel. */ public class WeylRelations> { /** The factory for the solvable polynomial ring. */ private final GenSolvablePolynomialRing ring; private static final Logger logger = Logger.getLogger(WeylRelations.class); /** The constructor requires a ring factory. * The relation table of this ring is setup to a Weyl Algebra. * @param r solvable polynomial ring factory, * r must have even number of variables. */ public WeylRelations(GenSolvablePolynomialRing r) { if ( r == null ) { throw new IllegalArgumentException("WeylRelations, ring == null"); } ring = r; if ( ring.nvar <= 1 || (ring.nvar % 2) != 0 ) { throw new IllegalArgumentException("WeylRelations, wrong nvar = " + ring.nvar); } } /** Generates the relation table of this ring. */ public void generate() { RelationTable table = ring.table; int r = ring.nvar; int m = r / 2; //ExpVector z = ring.evzero; GenSolvablePolynomial one = ring.getONE().copy(); GenSolvablePolynomial zero = ring.getZERO().copy(); for ( int i = m; i < r; i++ ) { ExpVector f = ExpVector.create(r,i,1); int j = i - m; ExpVector e = ExpVector.create(r,j,1); ExpVector ef = e.sum(f); GenSolvablePolynomial b = one.multiply(ef); GenSolvablePolynomial rel = (GenSolvablePolynomial)b.sum(one); // = (GenSolvablePolynomial)b.subtract(one); if ( rel.isZERO() ) { logger.info("ring = " + ring); logger.info("one = " + one); logger.info("zero = " + zero); logger.info("b = " + b); logger.info("rel = " + rel); //System.exit(1); throw new RuntimeException("rel.isZERO()"); } //System.out.println("rel = " + rel.toString(ring.vars)); table.update(e,f,rel); } if ( logger.isDebugEnabled() ) { logger.debug("\nWeyl relations = " + table); } return; } } jas-2.5/src/edu/jas/poly/Overlap.java0000644000175000017500000000261612020347402017721 0ustar giovannigiovanni/* * $Id: Overlap.java 4149 2012-09-01 09:01:54Z kredel $ */ package edu.jas.poly; import java.io.Serializable; /** * Container for overlap words. * A container of four words l1, r1, l2, r2. * @author Heinz Kredel */ public class Overlap implements Serializable { public final Word l1; public final Word r1; public final Word l2; public final Word r2; /** * Constructor. */ public Overlap(Word l1, Word r1, Word l2, Word r2) { this.l1 = l1; this.r1 = r1; this.l2 = l2; this.r2 = r2; } /** * Is word overlap. * @param u word * @param v word * @return true if l1 * u * r1 = l2 * v * r2, else false. */ public boolean isOverlap(Word u, Word v) { Word a = l1.multiply(u).multiply(r1); Word b = l2.multiply(v).multiply(r2); boolean t = a.equals(b); if ( !t ) { System.out.println("a = " + a + " != b = " + b); } return t; } /** * Get the string representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer("Overlap["); s.append(l1); s.append(", "); s.append(r1); s.append(", "); s.append(l2); s.append(", "); s.append(r2); s.append("]"); return s.toString(); } } jas-2.5/src/edu/jas/poly/Quotient.java0000644000175000017500000002324312014234362020123 0ustar giovannigiovanni/* * $Id: Quotient.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.poly; import org.apache.log4j.Logger; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; /** * Quotient element based on RingElem pairs. Objects of this class are * immutable. * @author Heinz Kredel */ public class Quotient> implements RingElem> { private static final Logger logger = Logger.getLogger(Quotient.class); private final boolean debug = logger.isDebugEnabled(); /** * Quotient class factory data structure. */ public final QuotientRing ring; /** * Numerator part of the element data structure. */ public final C num; /** * Denominator part of the element data structure. */ public final C den; /** * The constructor creates a Quotient object from a ring factory. * @param r ring factory. */ public Quotient(QuotientRing r) { this(r, r.ring.getZERO()); } /** * The constructor creates a Quotient object from a ring factory and a * numerator element. The denominator is assumed to be 1. * @param r ring factory. * @param n numerator. */ public Quotient(QuotientRing r, C n) { this(r, n, r.ring.getONE(), true); } /** * The constructor creates a Quotient object from a ring factory and a * numerator and denominator element. * @param r ring factory. * @param n numerator. * @param d denominator. */ public Quotient(QuotientRing r, C n, C d) { this(r, n, d, false); } /** * The constructor creates a Quotient object from a ring factory and a * numerator and denominator element. * @param r ring factory. * @param n numerator. * @param d denominator. * @param isred true if gcd(n,d) == 1, else false. */ @SuppressWarnings("unchecked") protected Quotient(QuotientRing r, C n, C d, boolean isred) { if (d == null || d.isZERO()) { throw new IllegalArgumentException("denominator may not be zero"); } ring = r; if (d.signum() < 0) { n = n.negate(); d = d.negate(); } if (isred) { num = n; den = d; return; } // must reduce to lowest terms if (n instanceof GcdRingElem && d instanceof GcdRingElem) { GcdRingElem ng = (GcdRingElem) n; GcdRingElem dg = (GcdRingElem) d; C gcd = (C) ng.gcd(dg); if (debug) { logger.info("gcd = " + gcd); } //RingElem gcd = ring.ring.getONE(); if (gcd.isONE()) { num = n; den = d; } else { num = n.divide(gcd); den = d.divide(gcd); } // } else { // univariate polynomial? } else { logger.warn("gcd = ????"); num = n; den = d; } } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public QuotientRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public Quotient copy() { return new Quotient(ring, num, den, true); } /** * Is Quotient zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return num.isZERO(); } /** * Is Quotient one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return num.equals(den); } /** * Is Quotient unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (num.isZERO()) { return false; } return true; } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { return "Quotient[ " + num.toString() + " / " + den.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "Quotient( " + num.toScript() + " , " + den.toScript() + " )"; } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Quotient comparison. * @param b Quotient. * @return sign(this-b). */ //JAVA6only: @Override public int compareTo(Quotient b) { if (b == null || b.isZERO()) { return this.signum(); } C r = num.multiply(b.den); C s = den.multiply(b.num); C x = r.subtract(s); return x.signum(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @SuppressWarnings("unchecked") // not jet working @Override public boolean equals(Object b) { if (!(b instanceof Quotient)) { return false; } Quotient a = null; try { a = (Quotient) b; } catch (ClassCastException e) { } if (a == null) { return false; } return (0 == compareTo(a)); } /** * Hash code for this local. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + num.hashCode(); h = 37 * h + den.hashCode(); return h; } /** * Quotient absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public Quotient abs() { return new Quotient(ring, num.abs(), den, true); } /** * Quotient summation. * @param S Quotient. * @return this+S. */ public Quotient sum(Quotient S) { if (S == null || S.isZERO()) { return this; } C n = num.multiply(S.den); n = n.sum(den.multiply(S.num)); C d = den.multiply(S.den); return new Quotient(ring, n, d, false); } /** * Quotient negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public Quotient negate() { return new Quotient(ring, num.negate(), den, true); } /** * Quotient signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { return num.signum(); } /** * Quotient subtraction. * @param S Quotient. * @return this-S. */ public Quotient subtract(Quotient S) { if (S == null || S.isZERO()) { return this; } C n = num.multiply(S.den); n = n.subtract(den.multiply(S.num)); C d = den.multiply(S.den); return new Quotient(ring, n, d, false); } /** * Quotient division. * @param S Quotient. * @return this/S. */ public Quotient divide(Quotient S) { return multiply(S.inverse()); } /** * Quotient inverse. * @see edu.jas.structure.RingElem#inverse() * @return S with S = 1/this. */ public Quotient inverse() { return new Quotient(ring, den, num, true); } /** * Quotient remainder. * @param S Quotient. * @return this - (this/S)*S. */ public Quotient remainder(Quotient S) { if (num.isZERO()) { throw new ArithmeticException("element not invertible " + this); } return ring.getZERO(); } /** * Quotient multiplication. * @param S Quotient. * @return this*S. */ public Quotient multiply(Quotient S) { if (S == null || S.isZERO()) { return S; } if (num.isZERO()) { return this; } if (S.isONE()) { return this; } if (this.isONE()) { return S; } C n = num.multiply(S.num); C d = den.multiply(S.den); return new Quotient(ring, n, d, false); } /** * Quotient monic. * @return this with monic value part. */ public Quotient monic() { logger.info("monic not implemented"); return this; } /** * Greatest common divisor. Note: Not implemented, throws * UnsupportedOperationException. * @param b other element. * @return gcd(this,b). */ public Quotient gcd(Quotient b) { throw new UnsupportedOperationException("gcd not implemented " + this.getClass().getName()); } /** * Extended greatest common divisor. Note: Not implemented, throws * UnsupportedOperationException. * @param b other element. * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). */ public Quotient[] egcd(Quotient b) { throw new UnsupportedOperationException("egcd not implemented " + this.getClass().getName()); } } jas-2.5/src/edu/jas/poly/GenPolynomialRing.java0000644000175000017500000011053112014234362021705 0ustar giovannigiovanni/* * $Id: GenPolynomialRing.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.poly; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Set; import org.apache.log4j.Logger; import edu.jas.arith.ModIntegerRing; import edu.jas.kern.PreemptStatus; import edu.jas.kern.PrettyPrint; import edu.jas.kern.Scripting; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.util.CartesianProduct; import edu.jas.util.CartesianProductInfinite; import edu.jas.util.LongIterable; /** * GenPolynomialRing generic polynomial factory implementing RingFactory; * Factory for n-variate ordered polynomials over C. Almost immutable object, * except variable names. * @param coefficient type * @author Heinz Kredel */ public class GenPolynomialRing> implements RingFactory>, Iterable> { /** * The factory for the coefficients. */ public final RingFactory coFac; /** * The number of variables. */ public final int nvar; /** * The term order. */ public final TermOrder tord; /** * True for partially reversed variables. */ protected boolean partial; /** * The names of the variables. This value can be modified. */ protected String[] vars; /** * The names of all known variables. */ private static Set knownVars = new HashSet(); /** * The constant polynomial 0 for this ring. */ public final GenPolynomial ZERO; /** * The constant polynomial 1 for this ring. */ public final GenPolynomial ONE; /** * The constant exponent vector 0 for this ring. */ public final ExpVector evzero; /** * A default random sequence generator. */ protected final static Random random = new Random(); /** * Indicator if this ring is a field. */ protected int isField = -1; // initially unknown /** * Log4j logger object. */ private static final Logger logger = Logger.getLogger(GenPolynomialRing.class); /** * Flag to enable if preemptive interrrupt is checked. */ final boolean checkPreempt = PreemptStatus.isAllowed(); /** * The constructor creates a polynomial factory object with the default term * order. * @param cf factory for coefficients of type C. * @param n number of variables. */ public GenPolynomialRing(RingFactory cf, int n) { this(cf, n, new TermOrder(), null); } /** * The constructor creates a polynomial factory object. * @param cf factory for coefficients of type C. * @param n number of variables. * @param t a term order. */ public GenPolynomialRing(RingFactory cf, int n, TermOrder t) { this(cf, n, t, null); } /** * The constructor creates a polynomial factory object. * @param cf factory for coefficients of type C. * @param v names for the variables. */ public GenPolynomialRing(RingFactory cf, String[] v) { this(cf, v.length, v); } /** * The constructor creates a polynomial factory object. * @param cf factory for coefficients of type C. * @param n number of variables. * @param v names for the variables. */ public GenPolynomialRing(RingFactory cf, int n, String[] v) { this(cf, n, new TermOrder(), v); } /** * The constructor creates a polynomial factory object. * @param cf factory for coefficients of type C. * @param t a term order. * @param v names for the variables. */ public GenPolynomialRing(RingFactory cf, TermOrder t, String[] v) { this(cf, v.length, t, v); } /** * The constructor creates a polynomial factory object. * @param cf factory for coefficients of type C. * @param v names for the variables. * @param t a term order. */ public GenPolynomialRing(RingFactory cf, String[] v, TermOrder t) { this(cf, v.length, t, v); } /** * The constructor creates a polynomial factory object. * @param cf factory for coefficients of type C. * @param n number of variables. * @param t a term order. * @param v names for the variables. */ public GenPolynomialRing(RingFactory cf, int n, TermOrder t, String[] v) { coFac = cf; nvar = n; tord = t; partial = false; vars = v; ZERO = new GenPolynomial(this); C coeff = coFac.getONE(); evzero = ExpVector.create(nvar); ONE = new GenPolynomial(this, coeff, evzero); if (vars == null) { if (PrettyPrint.isTrue()) { vars = newVars("x", nvar); } } else { if (vars.length != nvar) { throw new IllegalArgumentException("incompatible variable size " + vars.length + ", " + nvar); } addVars(vars); } } /** * The constructor creates a polynomial factory object with the the same * term order, number of variables and variable names as the given * polynomial factory, only the coefficient factories differ. * @param cf factory for coefficients of type C. * @param o other polynomial ring. */ public GenPolynomialRing(RingFactory cf, GenPolynomialRing o) { this(cf, o.nvar, o.tord, o.vars); } /** * The constructor creates a polynomial factory object with the the same * coefficient factory, number of variables and variable names as the given * polynomial factory, only the term order differs. * @param to term order. * @param o other polynomial ring. */ public GenPolynomialRing(GenPolynomialRing o, TermOrder to) { this(o.coFac, o.nvar, to, o.vars); } /** * Copy this factory. * @return a clone of this. */ public GenPolynomialRing copy() { return new GenPolynomialRing(coFac, this); } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { String res = null; if (PrettyPrint.isTrue() && coFac != null) { String scf = coFac.getClass().getSimpleName(); if (coFac instanceof AlgebraicNumberRing) { AlgebraicNumberRing an = (AlgebraicNumberRing) coFac; //String[] v = an.ring.vars; res = "AN[ (" + an.ring.varsToString() + ") (" + an.toString() + ") ]"; } if (coFac instanceof GenPolynomialRing) { GenPolynomialRing rf = (GenPolynomialRing) coFac; //String[] v = rf.vars; //RingFactory cf = rf.coFac; //String cs; //if (cf instanceof ModIntegerRing) { // cs = cf.toString(); //} else { // cs = " " + cf.getClass().getSimpleName(); //} //res = "IntFunc" + "{" + cs + "( " + rf.varsToString() + " )" + " } "; res = "IntFunc" + "( " + rf.toString() + " )"; } if (((Object) coFac) instanceof ModIntegerRing) { ModIntegerRing mn = (ModIntegerRing) ((Object) coFac); res = "Mod " + mn.getModul() + " "; } if (res == null) { res = coFac.toString(); if (res.matches("[0-9].*")) { res = scf; } } res += "( " + varsToString() + " ) " + tord.toString() + " "; } else { res = this.getClass().getSimpleName() + "[ " + coFac.toString() + " "; // + coFac.getClass().getSimpleName(); if (coFac instanceof AlgebraicNumberRing) { AlgebraicNumberRing an = (AlgebraicNumberRing) coFac; res = "AN[ (" + an.ring.varsToString() + ") (" + an.modul + ") ]"; } if (coFac instanceof GenPolynomialRing) { GenPolynomialRing rf = (GenPolynomialRing) coFac; //String[] v = rf.vars; //RingFactory cf = rf.coFac; //String cs; //if (cf instanceof ModIntegerRing) { // cs = cf.toString(); //} else { // cs = " " + cf.getClass().getSimpleName(); //} //res = "IntFunc{ " + cs + "( " + rf.varsToString() + " )" + " } "; res = "IntFunc" + "( " + rf.toString() + " )"; } if (((Object) coFac) instanceof ModIntegerRing) { ModIntegerRing mn = (ModIntegerRing) ((Object) coFac); res = "Mod " + mn.getModul() + " "; } //res += ", " + nvar + ", " + tord.toString() + ", " + varsToString() + ", " + partial + " ]"; res += "( " + varsToString() + " ) " + tord.toString() + " ]"; } return res; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { StringBuffer s = new StringBuffer(); switch (Scripting.getLang()) { case Ruby: s.append("PolyRing.new("); break; case Python: default: s.append("PolyRing("); } if (coFac instanceof RingElem) { s.append(((RingElem) coFac).toScriptFactory()); } else { s.append(coFac.toScript().trim()); } s.append(",\"" + varsToString() + "\""); String to = tord.toString(); if (tord.getEvord() == TermOrder.INVLEX) { to = ",PolyRing.lex"; } if (tord.getEvord() == TermOrder.IGRLEX) { to = ",PolyRing.grad"; } s.append(to); s.append(")"); return s.toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object other) { if (!(other instanceof GenPolynomialRing)) { return false; } GenPolynomialRing oring = null; try { oring = (GenPolynomialRing) other; } catch (ClassCastException ignored) { } if (oring == null) { return false; } if (nvar != oring.nvar) { return false; } if (!coFac.equals(oring.coFac)) { return false; } if (!tord.equals(oring.tord)) { return false; } // same variables required ? if (!Arrays.equals(vars, oring.vars)) { return false; } return true; } /** * Hash code for this polynomial ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = (nvar << 27); h += (coFac.hashCode() << 11); h += tord.hashCode(); return h; } /** * Get the variable names. * @return vars. */ public String[] getVars() { return vars; // Java-5: Arrays.copyOf(vars,vars.length); } /** * Set the variable names. * @return old vars. */ public String[] setVars(String[] v) { if (v.length != nvar) { throw new IllegalArgumentException("v not matching number of variables: " + Arrays.toString(v) + ", nvar " + nvar); } String[] t = vars; vars = v; // Java-5: Arrays.copyOf(v,v.length); return t; } /** * Get a String representation of the variable names. * @return names seperated by commas. */ public String varsToString() { if (vars == null) { return "#" + nvar; } //return Arrays.toString(vars); return ExpVector.varsToString(vars); } /** * Get the zero element from the coefficients. * @return 0 as C. */ public C getZEROCoefficient() { return coFac.getZERO(); } /** * Get the one element from the coefficients. * @return 1 as C. */ public C getONECoefficient() { return coFac.getONE(); } /** * Get the zero element. * @return 0 as GenPolynomial. */ public GenPolynomial getZERO() { return ZERO; } /** * Get the one element. * @return 1 as GenPolynomial. */ public GenPolynomial getONE() { return ONE; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return coFac.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return coFac.isAssociative(); } /** * Query if this ring is a field. * @return false. */ public boolean isField() { if (isField > 0) { return true; } if (isField == 0) { return false; } if (coFac.isField() && nvar == 0) { isField = 1; return true; } isField = 0; return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return coFac.characteristic(); } /** * Get a (constant) GenPolynomial<C> element from a coefficient value. * @param a coefficient. * @return a GenPolynomial<C>. */ public GenPolynomial valueOf(C a) { return new GenPolynomial(this, a); } /** * Get a GenPolynomial<C> element from an exponent vector. * @param e exponent vector. * @return a GenPolynomial<C>. */ public GenPolynomial valueOf(ExpVector e) { return new GenPolynomial(this, coFac.getONE(), e); } /** * Get a GenPolynomial<C> element from a coeffcient and an exponent * vector. * @param a coefficient. * @param e exponent vector. * @return a GenPolynomial<C>. */ public GenPolynomial valueOf(C a, ExpVector e) { return new GenPolynomial(this, a, e); } /** * Get a (constant) GenPolynomial<C> element from a long value. * @param a long. * @return a GenPolynomial<C>. */ public GenPolynomial fromInteger(long a) { return new GenPolynomial(this, coFac.fromInteger(a), evzero); } /** * Get a (constant) GenPolynomial<C> element from a BigInteger value. * @param a BigInteger. * @return a GenPolynomial<C>. */ public GenPolynomial fromInteger(BigInteger a) { return new GenPolynomial(this, coFac.fromInteger(a), evzero); } /** * Random polynomial. Generates a random polynomial with k = 5, l = n, d = * (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3. * @param n number of terms. * @return a random polynomial. */ public GenPolynomial random(int n) { return random(n, random); } /** * Random polynomial. Generates a random polynomial with k = 5, l = n, d = * (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3. * @param n number of terms. * @param rnd is a source for random bits. * @return a random polynomial. */ public GenPolynomial random(int n, Random rnd) { if (nvar == 1) { return random(3, n, n, 0.7f, rnd); } return random(5, n, 3, 0.3f, rnd); } /** * Generate a random polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @return a random polynomial. */ public GenPolynomial random(int k, int l, int d, float q) { return random(k, l, d, q, random); } /** * Generate a random polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @param rnd is a source for random bits. * @return a random polynomial. */ public GenPolynomial random(int k, int l, int d, float q, Random rnd) { GenPolynomial r = getZERO(); //.clone() or copy( ZERO ); ExpVector e; C a; // add l random coeffs and exponents for (int i = 0; i < l; i++) { e = ExpVector.EVRAND(nvar, d, q, rnd); a = coFac.random(k, rnd); r = r.sum(a, e); // somewhat inefficient but clean //System.out.println("e = " + e + " a = " + a); } // System.out.println("r = " + r); return r; } /** * Copy polynomial c. * @param c * @return a copy of c. */ public GenPolynomial copy(GenPolynomial c) { //System.out.println("GP copy = " + this); return new GenPolynomial(this, c.val); } /** * Parse a polynomial with the use of GenPolynomialTokenizer. * @param s String. * @return GenPolynomial from s. */ public GenPolynomial parse(String s) { String val = s; if (!s.contains("|")) { val = val.replace("{", "").replace("}", ""); } return parse(new StringReader(val)); } /** * Parse a polynomial with the use of GenPolynomialTokenizer. * @param r Reader. * @return next GenPolynomial from r. */ @SuppressWarnings("unchecked") public GenPolynomial parse(Reader r) { GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r); GenPolynomial p = null; try { p = (GenPolynomial) pt.nextPolynomial(); } catch (IOException e) { logger.error(e.toString() + " parse " + this); p = ZERO; } return p; } /** * Generate univariate polynomial in a given variable. * @param i the index of the variable. * @return X_i as univariate polynomial. */ public GenPolynomial univariate(int i) { return univariate(0, i, 1L); } /** * Generate univariate polynomial in a given variable with given exponent. * @param i the index of the variable. * @param e the exponent of the variable. * @return X_i^e as univariate polynomial. */ public GenPolynomial univariate(int i, long e) { return univariate(0, i, e); } /** * Generate univariate polynomial in a given variable with given exponent. * @param modv number of module variables. * @param i the index of the variable. * @param e the exponent of the variable. * @return X_i^e as univariate polynomial. */ public GenPolynomial univariate(int modv, int i, long e) { GenPolynomial p = getZERO(); int r = nvar - modv; if (0 <= i && i < r) { C one = coFac.getONE(); ExpVector f = ExpVector.create(r, i, e); if (modv > 0) { f = f.extend(modv, 0, 0l); } p = p.sum(one, f); } return p; } /** * Get the generating elements excluding the generators for the coefficient * ring. * @return a list of generating elements for this ring. */ public List> getGenerators() { List> univs = univariateList(); List> gens = new ArrayList>(univs.size() + 1); gens.add(getONE()); gens.addAll(univs); return gens; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List cogens = coFac.generators(); List> univs = univariateList(); List> gens = new ArrayList>(univs.size() + cogens.size()); for (C c : cogens) { gens.add(getONE().multiply(c)); } gens.addAll(univs); return gens; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return (nvar == 0) && coFac.isFinite(); } /** * Generate list of univariate polynomials in all variables. * @return List(X_1,...,X_n) a list of univariate polynomials. */ public List> univariateList() { return univariateList(0, 1L); } /** * Generate list of univariate polynomials in all variables. * @param modv number of module variables. * @return List(X_1,...,X_n) a list of univariate polynomials. */ public List> univariateList(int modv) { return univariateList(modv, 1L); } /** * Generate list of univariate polynomials in all variables with given * exponent. * @param modv number of module variables. * @param e the exponent of the variables. * @return List(X_1^e,...,X_n^e) a list of univariate polynomials. */ public List> univariateList(int modv, long e) { List> pols = new ArrayList>(nvar); int nm = nvar - modv; for (int i = 0; i < nm; i++) { GenPolynomial p = univariate(modv, nm - 1 - i, e); pols.add(p); } return pols; } /** * Extend variables. Used e.g. in module embedding. Extend number of * variables by i. * @param i number of variables to extend. * @return extended polynomial ring factory. */ public GenPolynomialRing extend(int i) { // add module variable names String[] v = newVars("e", i); return extend(v); } /** * Extend variables. Used e.g. in module embedding. Extend number of * variables by length(vn). * @param vn names for extended variables. * @return extended polynomial ring factory. */ public GenPolynomialRing extend(String[] vn) { if (vn == null || vars == null) { throw new IllegalArgumentException("vn and vars may not be null"); } int i = vn.length; String[] v = new String[vars.length + i]; for (int k = 0; k < vars.length; k++) { v[k] = vars[k]; } for (int k = 0; k < vn.length; k++) { v[vars.length + k] = vn[k]; } TermOrder to = tord.extend(nvar, i); GenPolynomialRing pfac = new GenPolynomialRing(coFac, nvar + i, to, v); return pfac; } /** * Extend lower variables. Extend number of variables by i. * @param i number of variables to extend. * @return extended polynomial ring factory. */ public GenPolynomialRing extendLower(int i) { String[] v = newVars("e", i); return extendLower(v); } /** * Extend lower variables. Extend number of variables by length(vn). * @param vn names for extended lower variables. * @return extended polynomial ring factory. */ public GenPolynomialRing extendLower(String[] vn) { if (vn == null || vars == null) { throw new IllegalArgumentException("vn and vars may not be null"); } int i = vn.length; String[] v = new String[vars.length + i]; for (int k = 0; k < vn.length; k++) { v[k] = vn[k]; } for (int k = 0; k < vars.length; k++) { v[vn.length + k] = vars[k]; } TermOrder to = tord.extendLower(nvar, i); GenPolynomialRing pfac = new GenPolynomialRing(coFac, nvar + i, to, v); return pfac; } /** * Contract variables. Used e.g. in module embedding. Contract number of * variables by i. * @param i number of variables to remove. * @return contracted polynomial ring factory. */ public GenPolynomialRing contract(int i) { String[] v = null; if (vars != null) { v = new String[vars.length - i]; for (int j = 0; j < vars.length - i; j++) { v[j] = vars[j]; } } TermOrder to = tord.contract(i, nvar - i); GenPolynomialRing pfac = new GenPolynomialRing(coFac, nvar - i, to, v); return pfac; } /** * Recursive representation as polynomial with i main variables. * @param i number of main variables. * @return recursive polynomial ring factory. */ public GenPolynomialRing> recursive(int i) { if (i <= 0 || i >= nvar) { throw new IllegalArgumentException("wrong: 0 < " + i + " < " + nvar); } GenPolynomialRing cfac = contract(i); String[] v = null; if (vars != null) { v = new String[i]; int k = 0; for (int j = nvar - i; j < nvar; j++) { v[k++] = vars[j]; } } TermOrder to = tord.contract(0, i); // ?? GenPolynomialRing> pfac = new GenPolynomialRing>(cfac, i, to, v); return pfac; } /** * Reverse variables. Used e.g. in opposite rings. * @return polynomial ring factory with reversed variables. */ public GenPolynomialRing reverse() { return reverse(false); } /** * Reverse variables. Used e.g. in opposite rings. * @param partial true for partialy reversed term orders. * @return polynomial ring factory with reversed variables. */ public GenPolynomialRing reverse(boolean partial) { String[] v = null; if (vars != null) { // vars are not inversed v = new String[vars.length]; int k = tord.getSplit(); if (partial && k < vars.length) { for (int j = 0; j < k; j++) { v[vars.length - k + j] = vars[vars.length - 1 - j]; } for (int j = 0; j < vars.length - k; j++) { v[j] = vars[j]; } } else { for (int j = 0; j < vars.length; j++) { v[j] = vars[vars.length - 1 - j]; } } } TermOrder to = tord.reverse(partial); GenPolynomialRing pfac = new GenPolynomialRing(coFac, nvar, to, v); pfac.partial = partial; return pfac; } /** * Get PolynomialComparator. * @return polynomial comparator. */ public PolynomialComparator getComparator() { return new PolynomialComparator(tord, false); } /** * Get PolynomialComparator. * @param rev for reverse comparator. * @return polynomial comparator. */ public PolynomialComparator getComparator(boolean rev) { return new PolynomialComparator(tord, rev); } /** * New variable names. Generate new names for variables, * @param prefix name prefix. * @param n number of variables. * @return new variable names. */ public static String[] newVars(String prefix, int n) { String[] vars = new String[n]; synchronized (knownVars) { int m = knownVars.size(); String name = prefix + m; for (int i = 0; i < n; i++) { while (knownVars.contains(name)) { m++; name = prefix + m; } vars[i] = name; //System.out.println("new variable: " + name); knownVars.add(name); m++; name = prefix + m; } } return vars; } /** * New variable names. Generate new names for variables, * @param prefix name prefix. * @return new variable names. */ public String[] newVars(String prefix) { return newVars(prefix, nvar); } /** * New variable names. Generate new names for variables, * @param n number of variables. * @return new variable names. */ public static String[] newVars(int n) { return newVars("x", n); } /** * New variable names. Generate new names for variables, * @return new variable names. */ public String[] newVars() { return newVars(nvar); } /** * Add variable names. * @param vars variable names to be recorded. */ public static void addVars(String[] vars) { if (vars == null) { return; } synchronized (knownVars) { for (int i = 0; i < vars.length; i++) { knownVars.add(vars[i]); // eventualy names 'overwritten' } } } /** * Get a GenPolynomial iterator. * @return an iterator over all polynomials. */ public Iterator> iterator() { if (coFac.isFinite()) { return new GenPolynomialIterator(this); } logger.warn("ring of coefficients " + coFac + " is infinite, constructing iterator only over monomials"); return new GenPolynomialMonomialIterator(this); //throw new IllegalArgumentException("only for finite iterable coefficients implemented"); } } /** * Polynomial iterator. * @author Heinz Kredel */ class GenPolynomialIterator> implements Iterator> { /** * data structure. */ final GenPolynomialRing ring; final Iterator> eviter; final List powers; final List> coeffiter; Iterator> itercoeff; GenPolynomial current; /** * Polynomial iterator constructor. */ public GenPolynomialIterator(GenPolynomialRing fac) { ring = fac; LongIterable li = new LongIterable(); li.setNonNegativeIterator(); List> tlist = new ArrayList>(ring.nvar); for (int i = 0; i < ring.nvar; i++) { tlist.add(li); } CartesianProductInfinite ei = new CartesianProductInfinite(tlist); eviter = ei.iterator(); RingFactory cf = ring.coFac; coeffiter = new ArrayList>(); if (cf instanceof Iterable && cf.isFinite()) { Iterable cfi = (Iterable) cf; coeffiter.add(cfi); } else { throw new IllegalArgumentException("only for finite iterable coefficients implemented"); } CartesianProduct tuples = new CartesianProduct(coeffiter); itercoeff = tuples.iterator(); powers = new ArrayList(); ExpVector e = ExpVector.create(eviter.next()); powers.add(e); //System.out.println("new e = " + e); //System.out.println("powers = " + powers); List c = itercoeff.next(); //System.out.println("coeffs = " + c); current = new GenPolynomial(ring, c.get(0), e); } /** * Test for availability of a next element. * @return true if the iteration has more elements, else false. */ public boolean hasNext() { return true; } /** * Get next polynomial. * @return next polynomial. */ public synchronized GenPolynomial next() { GenPolynomial res = current; if (!itercoeff.hasNext()) { ExpVector e = ExpVector.create(eviter.next()); powers.add(0, e); // add new ev at beginning //System.out.println("new e = " + e); //System.out.println("powers = " + powers); if (coeffiter.size() == 1) { // shorten frist iterator by one element coeffiter.add(coeffiter.get(0)); Iterable it = coeffiter.get(0); List elms = new ArrayList(); for (C elm : it) { elms.add(elm); } elms.remove(0); coeffiter.set(0, elms); } else { coeffiter.add(coeffiter.get(1)); } CartesianProduct tuples = new CartesianProduct(coeffiter); itercoeff = tuples.iterator(); } List coeffs = itercoeff.next(); // while ( coeffs.get(0).isZERO() ) { // System.out.println(" skip zero "); // coeffs = itercoeff.next(); // skip tuples with zero in first component // } //System.out.println("coeffs = " + coeffs); GenPolynomial pol = ring.getZERO().copy(); int i = 0; for (ExpVector f : powers) { C c = coeffs.get(i++); if (c.isZERO()) { continue; } if (pol.val.get(f) != null) { System.out.println("error f in pol = " + f + ", " + pol.getMap().get(f)); throw new RuntimeException("error in iterator"); } pol.doPutToMap(f, c); } current = pol; return res; } /** * Remove an element if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove elements"); } } /** * Polynomial monomial iterator. * @author Heinz Kredel */ class GenPolynomialMonomialIterator> implements Iterator> { /** * data structure. */ final GenPolynomialRing ring; final Iterator iter; GenPolynomial current; /** * Polynomial iterator constructor. */ @SuppressWarnings("unchecked") public GenPolynomialMonomialIterator(GenPolynomialRing fac) { ring = fac; LongIterable li = new LongIterable(); li.setNonNegativeIterator(); List> tlist = new ArrayList>(ring.nvar); for (int i = 0; i < ring.nvar; i++) { tlist.add(li); } CartesianProductInfinite ei = new CartesianProductInfinite(tlist); //Iterator> eviter = ei.iterator(); RingFactory cf = ring.coFac; Iterable coeffiter; if (cf instanceof Iterable && !cf.isFinite()) { Iterable cfi = (Iterable) cf; coeffiter = cfi; } else { throw new IllegalArgumentException("only for infinite iterable coefficients implemented"); } // Cantor iterator for exponents and coeffcients List eci = new ArrayList(2); // no type parameter eci.add(ei); eci.add(coeffiter); CartesianProductInfinite ecp = new CartesianProductInfinite(eci); iter = ecp.iterator(); List ec = iter.next(); List ecl = (List) ec.get(0); C c = (C) ec.get(1); // zero ExpVector e = ExpVector.create(ecl); //System.out.println("exp = " + e); //System.out.println("coeffs = " + c); current = new GenPolynomial(ring, c, e); } /** * Test for availability of a next element. * @return true if the iteration has more elements, else false. */ public boolean hasNext() { return true; } /** * Get next polynomial. * @return next polynomial. */ public synchronized GenPolynomial next() { GenPolynomial res = current; List ec = iter.next(); C c = (C) ec.get(1); while (c.isZERO()) { // zero already done in first next ec = iter.next(); c = (C) ec.get(1); } List ecl = (List) ec.get(0); ExpVector e = ExpVector.create(ecl); //System.out.println("exp = " + e); //System.out.println("coeffs = " + c); current = new GenPolynomial(ring, c, e); return res; } /** * Remove an element if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove elements"); } } jas-2.5/src/edu/jas/poly/PolyIterator.java0000644000175000017500000000243211015275544020754 0ustar giovannigiovanni /* * $Id: PolyIterator.java 1809 2008-05-22 13:55:48Z kredel $ */ package edu.jas.poly; import java.util.Map; import java.util.SortedMap; import java.util.Iterator; import edu.jas.structure.RingElem; import edu.jas.poly.ExpVector; /** * Iterator over monomials of a polynomial. * Adaptor for val.entrySet().iterator(). * @author Heinz Kredel */ public class PolyIterator > implements Iterator< Monomial > { /** * Internal iterator over polynomial map. */ protected final Iterator< Map.Entry > ms; /** * Constructor of polynomial iterator. * @param m SortetMap of a polynomial. */ public PolyIterator( SortedMap m ) { ms = m.entrySet().iterator(); } /** * Test for availability of a next monomial. * @return true if the iteration has more monomials, else false. */ public boolean hasNext() { return ms.hasNext(); } /** * Get next monomial element. * @return next monomial. */ public Monomial next() { return new Monomial( ms.next() ); } /** * Remove the last monomial returned from underlying set if allowed. */ public void remove() { ms.remove(); } } jas-2.5/src/edu/jas/poly/OverlapList.java0000644000175000017500000000213612020347402020552 0ustar giovannigiovanni/* * $Id: OverlapList.java 4149 2012-09-01 09:01:54Z kredel $ */ package edu.jas.poly; import java.io.Serializable; import java.util.List; import java.util.ArrayList; /** * Container for lists of overlap words. * List of Overlaps. * @author Heinz Kredel */ public class OverlapList implements Serializable { public final List ols; /** * Constructor. */ public OverlapList() { ols = new ArrayList(); } /** * Add to list. */ public void add(Overlap ol) { ols.add(ol); } /** * Get the string representation. * @see java.lang.Object#toString() */ @Override public String toString() { return ols.toString(); } /** * Is word overlap list. * @param u word * @param v word * @return true if l1 * u * r1 = l2 * v * r2 for all overlaps, else false. */ public boolean isOverlap(Word u, Word v) { for (Overlap ol : ols ) { if ( !ol.isOverlap(u,v) ) { return false; } } return true; } } jas-2.5/src/edu/jas/poly/AlgebraicNumber.java0000644000175000017500000003022212020212506021321 0ustar giovannigiovanni/* * $Id: AlgebraicNumber.java 4148 2012-08-31 19:49:27Z kredel $ */ package edu.jas.poly; import edu.jas.kern.PrettyPrint; import edu.jas.structure.RingElem; import edu.jas.structure.GcdRingElem; import edu.jas.structure.NotInvertibleException; /** * Algebraic number class based on GenPolynomial with RingElem interface. * Objects of this class are immutable. * @author Heinz Kredel */ public class AlgebraicNumber> implements GcdRingElem> { /** * Ring part of the data structure. */ public final AlgebraicNumberRing ring; /** * Value part of the element data structure. */ public final GenPolynomial val; /** * Flag to remember if this algebraic number is a unit. -1 is unknown, 1 is * unit, 0 not a unit. */ protected int isunit = -1; // initially unknown /** * The constructor creates a AlgebraicNumber object from AlgebraicNumberRing * modul and a GenPolynomial value. * @param r ring AlgebraicNumberRing. * @param a value GenPolynomial. */ public AlgebraicNumber(AlgebraicNumberRing r, GenPolynomial a) { ring = r; // assert r != 0 val = a.remainder(ring.modul); //.monic() no go if (val.isZERO()) { isunit = 0; } if (ring.isField()) { isunit = 1; } } /** * The constructor creates a AlgebraicNumber object from a GenPolynomial * object module. * @param r ring AlgebraicNumberRing. */ public AlgebraicNumber(AlgebraicNumberRing r) { this(r, r.ring.getZERO()); } /** * Get the value part. * @return val. */ public GenPolynomial getVal() { return val; } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public AlgebraicNumberRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public AlgebraicNumber copy() { return new AlgebraicNumber(ring, val); } /** * Is AlgebraicNumber zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return val.equals(ring.ring.getZERO()); } /** * Is AlgebraicNumber one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return val.equals(ring.ring.getONE()); } /** * Is AlgebraicNumber unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (isunit > 0) { return true; } if (isunit == 0) { return false; } // not jet known if (val.isZERO()) { isunit = 0; return false; } if (ring.isField()) { isunit = 1; return true; } boolean u = val.gcd(ring.modul).isUnit(); if (u) { isunit = 1; } else { isunit = 0; } return (u); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { if (PrettyPrint.isTrue()) { return val.toString(ring.ring.vars); } return "AlgebraicNumber[ " + val.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return val.toScript(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * AlgebraicNumber comparison. * @param b AlgebraicNumber. * @return sign(this-b). */ //JAVA6only: @Override public int compareTo(AlgebraicNumber b) { int s = 0; if (ring.modul != b.ring.modul) { // avoid compareTo if possible s = ring.modul.compareTo(b.ring.modul); } if (s != 0) { return s; } return val.compareTo(b.val); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object b) { if (!(b instanceof AlgebraicNumber)) { return false; } AlgebraicNumber a = null; try { a = (AlgebraicNumber) b; } catch (ClassCastException e) { } if (a == null) { return false; } if (!ring.equals(a.ring)) { return false; } return (0 == compareTo(a)); } /** * Hash code for this AlgebraicNumber. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * val.hashCode() + ring.hashCode(); } /** * AlgebraicNumber absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public AlgebraicNumber abs() { return new AlgebraicNumber(ring, val.abs()); } /** * AlgebraicNumber summation. * @param S AlgebraicNumber. * @return this+S. */ public AlgebraicNumber sum(AlgebraicNumber S) { return new AlgebraicNumber(ring, val.sum(S.val)); } /** * AlgebraicNumber summation. * @param c coefficient. * @return this+c. */ public AlgebraicNumber sum(GenPolynomial c) { return new AlgebraicNumber(ring, val.sum(c)); } /** * AlgebraicNumber summation. * @param c polynomial. * @return this+c. */ public AlgebraicNumber sum(C c) { return new AlgebraicNumber(ring, val.sum(c)); } /** * AlgebraicNumber negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public AlgebraicNumber negate() { return new AlgebraicNumber(ring, val.negate()); } /** * AlgebraicNumber signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { return val.signum(); } /** * AlgebraicNumber subtraction. * @param S AlgebraicNumber. * @return this-S. */ public AlgebraicNumber subtract(AlgebraicNumber S) { return new AlgebraicNumber(ring, val.subtract(S.val)); } /** * AlgebraicNumber division. * @param S AlgebraicNumber. * @return this/S. */ public AlgebraicNumber divide(AlgebraicNumber S) { return multiply(S.inverse()); } /** * AlgebraicNumber inverse. * @see edu.jas.structure.RingElem#inverse() * @throws NotInvertibleException if the element is not invertible. * @return S with S = 1/this if defined. */ public AlgebraicNumber inverse() { try { return new AlgebraicNumber(ring, val.modInverse(ring.modul)); } catch (AlgebraicNotInvertibleException e) { //System.out.println(e); throw e; } catch (NotInvertibleException e) { throw new AlgebraicNotInvertibleException(e + ", val = " + val + ", modul = " + ring.modul + ", gcd = " + val.gcd(ring.modul),e); } } /** * AlgebraicNumber remainder. * @param S AlgebraicNumber. * @return this - (this/S)*S. */ public AlgebraicNumber remainder(AlgebraicNumber S) { if (S == null || S.isZERO()) { throw new ArithmeticException("division by zero"); } if (S.isONE()) { return ring.getZERO(); } if (S.isUnit()) { return ring.getZERO(); } GenPolynomial x = val.remainder(S.val); return new AlgebraicNumber(ring, x); } /** * AlgebraicNumber multiplication. * @param S AlgebraicNumber. * @return this*S. */ public AlgebraicNumber multiply(AlgebraicNumber S) { GenPolynomial x = val.multiply(S.val); return new AlgebraicNumber(ring, x); } /** * AlgebraicNumber multiplication. * @param c coefficient. * @return this*c. */ public AlgebraicNumber multiply(C c) { GenPolynomial x = val.multiply(c); return new AlgebraicNumber(ring, x); } /** * AlgebraicNumber multiplication. * @param c polynomial. * @return this*c. */ public AlgebraicNumber multiply(GenPolynomial c) { GenPolynomial x = val.multiply(c); return new AlgebraicNumber(ring, x); } /** * AlgebraicNumber monic. * @return this with monic value part. */ public AlgebraicNumber monic() { return new AlgebraicNumber(ring, val.monic()); } /** * AlgebraicNumber greatest common divisor. * @param S AlgebraicNumber. * @return gcd(this,S). */ public AlgebraicNumber gcd(AlgebraicNumber S) { if (S.isZERO()) { return this; } if (isZERO()) { return S; } if (isUnit() || S.isUnit()) { return ring.getONE(); } return new AlgebraicNumber(ring, val.gcd(S.val)); } /** * AlgebraicNumber extended greatest common divisor. * @param S AlgebraicNumber. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ @SuppressWarnings("unchecked") public AlgebraicNumber[] egcd(AlgebraicNumber S) { AlgebraicNumber[] ret = new AlgebraicNumber[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; return ret; } if (isZERO()) { ret[0] = S; return ret; } if (this.isUnit() || S.isUnit()) { ret[0] = ring.getONE(); if (this.isUnit() && S.isUnit()) { AlgebraicNumber half = ring.fromInteger(2).inverse(); ret[1] = this.inverse().multiply(half); ret[2] = S.inverse().multiply(half); return ret; } if (this.isUnit()) { // oder inverse(S-1)? ret[1] = this.inverse(); ret[2] = ring.getZERO(); return ret; } // if ( S.isUnit() ) { // oder inverse(this-1)? ret[1] = ring.getZERO(); ret[2] = S.inverse(); return ret; //} } //System.out.println("this = " + this + ", S = " + S); GenPolynomial[] qr; GenPolynomial q = this.val; GenPolynomial r = S.val; GenPolynomial c1 = ring.ring.getONE(); GenPolynomial d1 = ring.ring.getZERO(); GenPolynomial c2 = ring.ring.getZERO(); GenPolynomial d2 = ring.ring.getONE(); GenPolynomial x1; GenPolynomial x2; while (!r.isZERO()) { qr = q.quotientRemainder(r); q = qr[0]; x1 = c1.subtract(q.multiply(d1)); x2 = c2.subtract(q.multiply(d2)); c1 = d1; c2 = d2; d1 = x1; d2 = x2; q = r; r = qr[1]; } //System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2); ret[0] = new AlgebraicNumber(ring, q); ret[1] = new AlgebraicNumber(ring, c1); ret[2] = new AlgebraicNumber(ring, c2); return ret; } } jas-2.5/src/edu/jas/poly/WordFactory.java0000644000175000017500000003366612137024450020571 0ustar giovannigiovanni/* * $Id: WordFactory.java 4388 2013-04-27 19:38:16Z kredel $ */ package edu.jas.poly; import java.io.Reader; import java.io.Serializable; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.StringUtil; import edu.jas.structure.MonoidFactory; /** * WordFactory implements alphabet related methods. * @author Heinz Kredel */ public final class WordFactory implements MonoidFactory { /** * The data structure is a String of characters which defines the alphabet. */ /*package*/final String alphabet; /** * The empty word for this monoid. */ public final Word ONE; /** * The translation reference string. */ public static final String transRef = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; /** * The translation array of Strings. */ public final String[] translation; /** * Random number generator. */ private final static Random random = new Random(); /** * Log4j logger object. */ private static final Logger logger = Logger.getLogger(WordFactory.class); /** * Comparator for Words. */ public static abstract class WordComparator implements Comparator, Serializable { public abstract int compare(Word e1, Word e2); } /** * Defined descending order comparator. Sorts the highest terms first. */ private static final WordComparator horder = new WordComparator() { @Override public int compare(Word e1, Word e2) { //return e1.gradCompareTo(e2); return e1.gradInvlexCompareTo(e2); } }; /** * Defined ascending order comparator. Sorts the lowest terms first. */ private static final WordComparator lorder = new WordComparator() { @Override public int compare(Word e1, Word e2) { //return -e1.gradCompareTo(e2); return -e1.gradInvlexCompareTo(e2); } }; /** * Constructor for WordFactory. */ public WordFactory() { this(""); } /** * Constructor for WordFactory. * @param s String of single letters for alphabet */ public WordFactory(String s) { if (s == null) { throw new IllegalArgumentException("null string not allowed"); } alphabet = cleanSpace(s); translation = null; ONE = new Word(this,"",false); } /** * Constructor for WordFactory. * @param S String array for alphabet */ public WordFactory(String[] S) { String[] V = cleanAll(S); if ( isSingleLetters(V) ) { alphabet = concat(V); translation = null; } else { alphabet = transRef.substring(0,V.length); translation = V; logger.info("alphabet = " + alphabet + ", translation = " + Arrays.toString(translation)); } ONE = new Word(this,"",false); } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { if (alphabet.length() == 0) { return true; } return false; } /** * Query if this monoid is commutative. * @return true if this monoid is commutative, else false. */ public boolean isCommutative() { return false; } /** * Query if this monoid is associative. * @return true if this monoid is associative, else false. */ public boolean isAssociative() { return true; } /** * Get the one element, the empty word. * @return 1 as Word. */ public Word getONE() { return ONE; } /** * Copy word. * @param w word to copy. * @return copy of w. */ @Override public Word copy(Word w) { return new Word(this, w.getVal(), false); } /** * Get the alphabet length. * @return alphabet.length. */ public int length() { return alphabet.length(); } /** * Get the alphabet String. * @return alphabet. */ /*package*/String getVal() { return alphabet; } /** * Get the translation array of Strings. * @return alphabet. */ /*package*/String[] getTrans() { return translation; } /** * Get the alphabet letter at position i. * @param i position. * @return val[i]. */ public char getVal(int i) { return alphabet.charAt(i); } /** * Get the string representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer("\""); if ( translation == null ) { for (int i = 0; i < alphabet.length(); i++) { if (i != 0) { s.append(","); } s.append(getVal(i)); } } else { for (int i = 0; i < alphabet.length(); i++) { if (i != 0) { s.append(","); } s.append(translation[i]); } } s.append("\""); return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { return toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof WordFactory)) { return false; } WordFactory b = (WordFactory) B; return alphabet.equals(b.alphabet); } /** * hashCode. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return alphabet.hashCode(); } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. */ public List generators() { int len = alphabet.length(); List gens = new ArrayList(len); //gens.add(ONE); not a word generator // todo for (int i = 0; i < len; i++) { Word w = new Word(this, String.valueOf(alphabet.charAt(i)), false); gens.add(w); } return gens; } /** * Get the Element for a. * @param a long * @return element corresponding to a. */ public Word fromInteger(long a) { throw new UnsupportedOperationException("not implemented for WordFactory"); } /** * Get the Element for a. * @param a java.math.BigInteger. * @return element corresponding to a. */ public Word fromInteger(BigInteger a) { throw new UnsupportedOperationException("not implemented for WordFactory"); } /** * Get the Element for an ExpVector. * @param e ExpVector. * @return element corresponding to e. */ public Word valueOf(ExpVector e) { Word w = ONE; List gens = generators(); int n = alphabet.length(); int m = e.length(); if (m > n) { throw new IllegalArgumentException("alphabet to short for exponent " + e + ", alpahbet = " + alphabet); } for ( int i = 0; i < m; i++ ) { int x = (int) e.getVal(m-i-1); Word y = gens.get(i); Word u = ONE; for ( int j = 0; j < x; j++ ) { u = u.multiply(y); } w = w.multiply(u); } return w; } /** * Generate a random Element with size less equal to n. * @param n * @return a random element. */ public Word random(int n) { return random(n, random); } /** * Generate a random Element with size less equal to n. * @param n * @param random is a source for random bits. * @return a random element. */ public Word random(int n, Random random) { StringBuffer sb = new StringBuffer(); int len = alphabet.length(); for (int i = 0; i < n; i++) { int r = Math.abs(random.nextInt() % len); sb.append(alphabet.charAt(r)); } return new Word(this, sb.toString(), false); } /** * Parse from String. * @param s String. * @return a Element corresponding to s. */ public Word parse(String s) { String st = clean(s); String regex; if ( translation == null ) { regex = "[" + alphabet + " ]*"; } else { regex = "[" + concat(translation) + " ]*"; } if (!st.matches(regex)) { throw new IllegalArgumentException("word '" + st + "' contains letters not from: " + alphabet + " or from " + concat(translation)); } // todo return new Word(this, st, true); } /** * Parse from Reader. White space is delimiter for word. * @param r Reader. * @return the next Element found on r. */ public Word parse(Reader r) { return parse(StringUtil.nextString(r)); } /** * Get the descending order comparator. Sorts the highest terms first. * @return horder. */ public WordComparator getDescendComparator() { return horder; } /** * Get the ascending order comparator. Sorts the lowest terms first. * @return lorder. */ public WordComparator getAscendComparator() { return lorder; } /** * Prepare parse from String. * @param s String. * @return a Element corresponding to s. */ public static String cleanSpace(String s) { String st = s.trim(); st = st.replaceAll("\\*", ""); st = st.replaceAll("\\s", ""); st = st.replaceAll("\\(", ""); st = st.replaceAll("\\)", ""); st = st.replaceAll("\\\"", ""); return st; } /** * Prepare parse from String. * @param s String. * @return a Element corresponding to s. */ public static String clean(String s) { String st = s.trim(); st = st.replaceAll("\\*", " "); //st = st.replaceAll("\\s", ""); st = st.replaceAll("\\(", ""); st = st.replaceAll("\\)", ""); st = st.replaceAll("\\\"", ""); return st; } /** * Prepare parse from String array. * @param v String array. * @return an array of cleaned strings. */ public static String[] cleanAll(String[] v) { String[] t = new String[v.length]; for ( int i = 0; i < v.length; i++ ) { t[i] = cleanSpace(v[i]); if ( t[i].length() == 0 ) { logger.error("empty v[i]: '"+ v[i] + "'"); } //System.out.println("clean all: " + v[i] + " --> " + t[i]); } return t; } /** * Concat variable names. * @param v an array of strings. * @return the concatination of the strings in v. */ public static String concat(String[] v) { StringBuffer s = new StringBuffer(); if ( v == null ) { return s.toString(); } for ( int i = 0; i < v.length; i++ ) { //String a = v[i]; //if ( a.length() != 1 ) { // //logger.error("v[i] not single letter "+ a); // a = a.substring(0,1); //} s.append(v[i]); } return s.toString(); } /** * Trim all variable names. * @param v an array of strings. * @return an array of strings with all elements trimmed. */ public static String[] trimAll(String[] v) { String[] t = new String[v.length]; for ( int i = 0; i < v.length; i++ ) { t[i] = v[i].trim(); if ( t[i].length() == 0 ) { logger.error("empty v[i]: '"+ v[i] + "'"); } } return t; } /** * IndexOf for String array. * @param v an array of strings. * @param s string. * @return index of s in v, or -1 if s is not contained in v. */ public static int indexOf(String[] v, String s) { for ( int i = 0; i < v.length; i++ ) { if ( s.equals(v[i]) ) { return i; } } return -1; } /** * Test if all variables are single letters. * @param v an array of strings. * @return true, if all variables have length 1, else false. */ public static boolean isSingleLetters(String[] v) { for ( int i = 0; i < v.length; i++ ) { if ( v[i].length() != 1 ) { return false; } } return true; } /** * Translate variable names. * @param v an array of strings. * @return the translated string of v with respect to t. */ public String translate(String[] v) { StringBuffer s = new StringBuffer(); for ( int i = 0; i < v.length; i++ ) { String a = v[i]; int k = indexOf(translation,a); if ( k < 0 ) { System.out.println("t = " + Arrays.toString(translation)); System.out.println("v = " + Arrays.toString(v)); logger.error("v[i] not found in t: "+ a); //continue; throw new IllegalArgumentException("v[i] not found in t: "+ a); } s.append(transRef.charAt(k)); } return s.toString(); } /** * Translate variable name. * @param c internal char. * @return the extenal translated string. */ public String transVar(char c) { int k = alphabet.indexOf(c); return translation[k]; } } jas-2.5/src/edu/jas/poly/ExpVectorInteger.java0000644000175000017500000006020312042051146021543 0ustar giovannigiovanni/* * $Id: ExpVectorInteger.java 4270 2012-10-24 20:41:11Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.ArrayList; /** * ExpVectorInteger implements exponent vectors for polynomials using arrays of * int as storage unit. This class is used by ExpVector internally, there is no * need to use this class directly. * @see ExpVector * @author Heinz Kredel */ public final class ExpVectorInteger extends ExpVector /*implements AbelianGroupElem*/{ /** * The data structure is an array of longs. */ /*package*/final int[] val; /** * Largest integer. */ public static final long maxInt = (long) Integer.MAX_VALUE / 2; /** * Smallest integer. */ public static final long minInt = (long) Integer.MIN_VALUE / 2; /** * Constructor for ExpVector. * @param n length of exponent vector. */ public ExpVectorInteger(int n) { this(new int[n]); } /** * Constructor for ExpVector. Sets exponent i to e. * @param n length of exponent vector. * @param i index of exponent to be set. * @param e exponent to be set. */ public ExpVectorInteger(int n, int i, int e) { this(n); val[i] = e; } /** * Constructor for ExpVector. Sets exponent i to e. * @param n length of exponent vector. * @param i index of exponent to be set. * @param e exponent to be set. */ public ExpVectorInteger(int n, int i, long e) { this(n); if (e >= maxInt || e <= minInt) { throw new IllegalArgumentException("exponent to large: " + e); } val[i] = (int) e; } /** * Internal constructor for ExpVector. Sets val. * @param v internal representation array. */ protected ExpVectorInteger(int[] v) { super(); val = v; } /** * Constructor for ExpVector. Sets val, converts from long array. * @param v long representation array. */ public ExpVectorInteger(long[] v) { this(v.length); for (int i = 0; i < v.length; i++) { if (v[i] >= maxInt || v[i] <= minInt) { throw new IllegalArgumentException("exponent to large: " + v[i]); } val[i] = (int) v[i]; } } /** * Constructor for ExpVector. Converts a String representation to an * ExpVector. Accepted format = (1,2,3,4,5,6,7). * @param s String representation. */ public ExpVectorInteger(String s) throws NumberFormatException { super(); // first format = (1,2,3,4,5,6,7) List exps = new ArrayList(); s = s.trim(); int b = s.indexOf('('); int e = s.indexOf(')', b + 1); String teil; int k; int a; if (b >= 0 && e >= 0) { b++; while ((k = s.indexOf(',', b)) >= 0) { teil = s.substring(b, k); a = Integer.parseInt(teil); exps.add(Integer.valueOf(a)); b = k + 1; } if (b <= e) { teil = s.substring(b, e); a = Integer.parseInt(teil); exps.add(Integer.valueOf(a)); } int length = exps.size(); val = new int[length]; for (int j = 0; j < length; j++) { val[j] = exps.get(j).intValue(); } } else { // not implemented val = null; // length = -1; //Vector names = new Vector(); //vars = s; } } /** * Clone this. * @see java.lang.Object#clone() */ @Override public ExpVectorInteger copy() { int[] w = new int[val.length]; System.arraycopy(val, 0, w, 0, val.length); return new ExpVectorInteger(w); } /** * Get the exponent vector. * @return val as long. */ @Override /*package*/long[] getVal() { long v[] = new long[val.length]; for (int i = 0; i < val.length; i++) { v[i] = val[i]; } return v; } /** * Get the exponent at position i. * @param i position. * @return val[i]. */ @Override public long getVal(int i) { return val[i]; } /** * Set the exponent at position i to e. * @param i * @param e * @return old val[i]. */ @Override protected long setVal(int i, long e) { int x = val[i]; if (e >= maxInt || e <= minInt) { throw new IllegalArgumentException("exponent to large: " + e); } val[i] = (int) e; hash = 0; // beware of race condition return x; } /** * Set the exponent at position i to e. * @param i * @param e * @return old val[i]. */ protected int setVal(int i, int e) { int x = val[i]; val[i] = e; hash = 0; // beware of race condition return x; } /** * Get the length of this exponent vector. * @return val.length. */ @Override public int length() { return val.length; } /** * Extend variables. Used e.g. in module embedding. Extend this by i * elements and set val[j] to e. * @param i number of elements to extend. * @param j index of element to be set. * @param e new exponent for val[j]. * @return extended exponent vector. */ @Override public ExpVectorInteger extend(int i, int j, long e) { int[] w = new int[val.length + i]; System.arraycopy(val, 0, w, i, val.length); if (j >= i) { throw new IllegalArgumentException("i " + i + " <= j " + j + " invalid"); } if (e >= maxInt || e <= minInt) { throw new IllegalArgumentException("exponent to large: " + e); } w[j] = (int) e; return new ExpVectorInteger(w); } /** * Extend lower variables. Extend this by i lower elements and set val[j] to * e. * @param i number of elements to extend. * @param j index of element to be set. * @param e new exponent for val[j]. * @return extended exponent vector. */ @Override public ExpVectorInteger extendLower(int i, int j, long e) { int[] w = new int[val.length + i]; System.arraycopy(val, 0, w, 0, val.length); if (j >= i) { throw new IllegalArgumentException("i " + i + " <= j " + j + " invalid"); } w[val.length + j] = (int) e; return new ExpVectorInteger(w); } /** * Contract variables. Used e.g. in module embedding. Contract this to len * elements. * @param i position of first element to be copied. * @param len new length. * @return contracted exponent vector. */ @Override public ExpVectorInteger contract(int i, int len) { if (i + len > val.length) { throw new IllegalArgumentException("len " + len + " > val.len " + val.length); } int[] w = new int[len]; System.arraycopy(val, i, w, 0, len); return new ExpVectorInteger(w); } /** * Reverse variables. Used e.g. in opposite rings. * @return reversed exponent vector. */ @Override public ExpVectorInteger reverse() { int[] w = new int[val.length]; for (int i = 0; i < val.length; i++) { w[i] = val[val.length - 1 - i]; } return new ExpVectorInteger(w); } /** * Reverse j variables. Used e.g. in opposite rings. Reverses the first j-1 * variables, the rest is unchanged. * @param j index of first variable not reversed. * @return reversed exponent vector. */ @Override public ExpVectorInteger reverse(int j) { if (j <= 0 || j > val.length) { return this; } int[] w = new int[val.length]; for (int i = 0; i < j; i++) { w[i] = val[j - 1 - i]; } // copy rest for (int i = j; i < val.length; i++) { w[i] = val[i]; } return new ExpVectorInteger(w); } /** * Combine with ExpVector. Combine this with the other ExpVector V. * @param V the other exponent vector. * @return combined exponent vector. */ @Override public ExpVectorInteger combine(ExpVector V) { if (V == null || V.length() == 0) { return this; } ExpVectorInteger Vi = (ExpVectorInteger) V; if (val.length == 0) { return Vi; } int[] w = new int[val.length + Vi.val.length]; System.arraycopy(val, 0, w, 0, val.length); System.arraycopy(Vi.val, 0, w, val.length, Vi.val.length); return new ExpVectorInteger(w); } /** * Get the string representation. * @see java.lang.Object#toString() */ @Override public String toString() { return super.toString() + ":int"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof ExpVectorInteger)) { return false; } ExpVectorInteger b = (ExpVectorInteger) B; int t = this.invLexCompareTo(b); //System.out.println("equals: this = " + this + " B = " + B + " t = " + t); return (0 == t); } /** * hashCode for this exponent vector. * @see java.lang.Object#hashCode() Only for findbugs. */ @Override public int hashCode() { return super.hashCode(); } /** * ExpVector absolute value. * @return abs(this). */ @Override public ExpVectorInteger abs() { int[] u = val; int[] w = new int[u.length]; for (int i = 0; i < u.length; i++) { if (u[i] >= 0L) { w[i] = u[i]; } else { w[i] = -u[i]; } } return new ExpVectorInteger(w); //return EVABS(this); } /** * ExpVector negate. * @return -this. */ @Override public ExpVectorInteger negate() { int[] u = val; int[] w = new int[u.length]; for (int i = 0; i < u.length; i++) { w[i] = -u[i]; } return new ExpVectorInteger(w); // return EVNEG(this); } /** * ExpVector summation. * @param V * @return this+V. */ @Override public ExpVectorInteger sum(ExpVector V) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int[] w = new int[u.length]; for (int i = 0; i < u.length; i++) { w[i] = u[i] + v[i]; } return new ExpVectorInteger(w); // return EVSUM(this, V); } /** * ExpVector subtract. Result may have negative entries. * @param V * @return this-V. */ @Override public ExpVectorInteger subtract(ExpVector V) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int[] w = new int[u.length]; for (int i = 0; i < u.length; i++) { w[i] = u[i] - v[i]; } return new ExpVectorInteger(w); //return EVDIF(this, V); } /** * ExpVector substitution. Clone and set exponent to d at position i. * @param i position. * @param d new exponent. * @return substituted ExpVector. */ @Override public ExpVectorInteger subst(int i, long d) { ExpVectorInteger V = this.copy(); @SuppressWarnings("unused") long e = V.setVal(i, d); return V; //return EVSU(this, i, d); } /** * ExpVector substitution. Clone and set exponent to d at position i. * @param i position. * @param d new exponent. * @return substituted ExpVector. */ public ExpVectorInteger subst(int i, int d) { ExpVectorInteger V = this.copy(); @SuppressWarnings("unused") long e = V.setVal(i, d); return V; //return EVSU(this, i, d); } /** * ExpVector signum. * @return 0 if this is zero, -1 if some entry is negative, 1 if no entry is * negative and at least one entry is positive. */ @Override public int signum() { int t = 0; int[] u = val; for (int i = 0; i < u.length; i++) { if (u[i] < 0) { return -1; } if (u[i] > 0) { t = 1; } } return t; //return EVSIGN(this); } /** * ExpVector total degree. * @return sum of all exponents. */ @Override public long totalDeg() { long t = 0; int[] u = val; // U.val; for (int i = 0; i < u.length; i++) { t += u[i]; } return t; //return EVTDEG(this); } /** * ExpVector maximal degree. * @return maximal exponent. */ @Override public long maxDeg() { long t = 0; int[] u = val; for (int i = 0; i < u.length; i++) { if (u[i] > t) { t = u[i]; } } return t; //return EVMDEG(this); } /** * ExpVector weighted degree. * @param w weights. * @return weighted sum of all exponents. */ @Override public long weightDeg(long[][] w) { if (w == null || w.length == 0) { return totalDeg(); // assume weight 1 } long t = 0; int[] u = val; for (int j = 0; j < w.length; j++) { long[] wj = w[j]; for (int i = 0; i < u.length; i++) { t += wj[i] * u[i]; } } return t; //return EVWDEG( w, this ); } /** * ExpVector least common multiple. * @param V * @return component wise maximum of this and V. */ @Override public ExpVectorInteger lcm(ExpVector V) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int[] w = new int[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (u[i] >= v[i] ? u[i] : v[i]); } return new ExpVectorInteger(w); //return EVLCM(this, V); } /** * ExpVector greatest common divisor. * @param V * @return component wise minimum of this and V. */ @Override public ExpVectorInteger gcd(ExpVector V) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int[] w = new int[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (u[i] <= v[i] ? u[i] : v[i]); } return new ExpVectorInteger(w); //return EVGCD(this, V); } /** * ExpVector dependency on variables. * @return array of indices where val has positive exponents. */ @Override public int[] dependencyOnVariables() { int[] u = val; int l = 0; for (int i = 0; i < u.length; i++) { if (u[i] > 0) { l++; } } int[] dep = new int[l]; if (l == 0) { return dep; } int j = 0; for (int i = 0; i < u.length; i++) { if (u[i] > 0) { dep[j] = i; j++; } } return dep; } /** * ExpVector multiple test. Test if this is component wise greater or equal * to V. * @param V * @return true if this is a multiple of V, else false. */ @Override public boolean multipleOf(ExpVector V) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; boolean t = true; for (int i = 0; i < u.length; i++) { if (u[i] < v[i]) { return false; } } return t; //return EVMT(this, V); } /** * ExpVector compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int compareTo(ExpVector V) { return this.invLexCompareTo(V); } /** * ExpVector inverse lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invLexCompareTo(ExpVector V) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int t = 0; for (int i = 0; i < u.length; i++) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVILCP(this, V); } /** * ExpVector inverse lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invLexCompareTo(ExpVector V, int begin, int end) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int t = 0; for (int i = begin; i < end; i++) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVILCP(this, V, begin, end); } /** * ExpVector inverse graded lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invGradCompareTo(ExpVector V) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int t = 0; int i; for (i = 0; i < u.length; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j < u.length; j++) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVIGLC(this, V); } /** * ExpVector inverse graded lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invGradCompareTo(ExpVector V, int begin, int end) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int t = 0; int i; for (i = begin; i < end; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j < end; j++) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVIGLC(this, V, begin, end); } /** * ExpVector reverse inverse lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvLexCompareTo(ExpVector V) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int t = 0; for (int i = u.length - 1; i >= 0; i--) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVRILCP(this, V); } /** * ExpVector reverse inverse lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvLexCompareTo(ExpVector V, int begin, int end) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int t = 0; for (int i = end - 1; i >= begin; i--) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVRILCP(this, V, begin, end); } /** * ExpVector reverse inverse graded compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvGradCompareTo(ExpVector V) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int t = 0; int i; for (i = u.length - 1; i >= 0; i--) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j >= 0; j--) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVRIGLC(this, V); } /** * ExpVector reverse inverse graded compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvGradCompareTo(ExpVector V, int begin, int end) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int t = 0; int i; for (i = end - 1; i >= begin; i--) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j >= begin; j--) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVRIGLC(this, V, begin, end); } /** * ExpVector inverse weighted lexicographical compareTo. * @param w weight array. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invWeightCompareTo(long[][] w, ExpVector V) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int t = 0; int i; for (i = 0; i < u.length; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } for (int k = 0; k < w.length; k++) { long[] wk = w[k]; long up = 0; long vp = 0; for (int j = i; j < u.length; j++) { up += wk[j] * u[j]; vp += wk[j] * v[j]; } if (up > vp) { return 1; } else if (up < vp) { return -1; } } return t; //return EVIWLC(w, this, V); } /** * ExpVector inverse weighted lexicographical compareTo. * @param w weight array. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invWeightCompareTo(long[][] w, ExpVector V, int begin, int end) { int[] u = val; int[] v = ((ExpVectorInteger) V).val; int t = 0; int i; for (i = begin; i < end; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } for (int k = 0; k < w.length; k++) { long[] wk = w[k]; long up = 0; long vp = 0; for (int j = i; j < end; j++) { up += wk[j] * u[j]; vp += wk[j] * v[j]; } if (up > vp) { return 1; } else if (up < vp) { return -1; } } return t; //return EVIWLC(w, this, V, begin, end); } } jas-2.5/src/edu/jas/poly/PolynomialList.java0000644000175000017500000003526412137024450021301 0ustar giovannigiovanni/* * $Id: PolynomialList.java 4388 2013-04-27 19:38:16Z kredel $ */ package edu.jas.poly; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.kern.Scripting; import edu.jas.structure.RingElem; /** * List of polynomials. Mainly for storage and printing / toString and * conversions to other representations. * @author Heinz Kredel */ public class PolynomialList> implements Comparable>, Serializable { /** * The factory for the solvable polynomial ring. */ public final GenPolynomialRing ring; /** * The data structure is a List of polynomials. */ public final List> list; private static final Logger logger = Logger.getLogger(PolynomialList.class); /** * Constructor. * @param r polynomial ring factory. * @param l list of polynomials. */ public PolynomialList(GenPolynomialRing r, List> l) { ring = r; list = l; } /** * Constructor. * @param r solvable polynomial ring factory. * @param l list of solvable polynomials. */ public PolynomialList(GenSolvablePolynomialRing r, List> l) { this(r, PolynomialList. castToList(l)); } /** * Copy this. * @return a copy of this. */ public PolynomialList copy() { return new PolynomialList(ring, new ArrayList>(list)); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object p) { if (!(p instanceof PolynomialList)) { System.out.println("no PolynomialList"); return false; } PolynomialList pl = null; try { pl = (PolynomialList) p; } catch (ClassCastException ignored) { } if (pl == null) { return false; } if (!ring.equals(pl.ring)) { System.out.println("not same Ring " + ring.toScript() + ", " + pl.ring.toScript()); return false; } return (compareTo(pl) == 0); // otherwise tables may be different } /** * Polynomial list comparison. * @param L other PolynomialList. * @return lexicographical comparison, sign of first different polynomials. */ public int compareTo(PolynomialList L) { int si = L.list.size(); if (list.size() < si) { // minimum si = list.size(); } int s = 0; List> l1 = OrderedPolynomialList. sort(ring, list); List> l2 = OrderedPolynomialList. sort(ring, L.list); for (int i = 0; i < si; i++) { GenPolynomial a = l1.get(i); GenPolynomial b = l2.get(i); s = a.compareTo(b); if (s != 0) { return s; } } if (list.size() > si) { return 1; } if (L.list.size() > si) { return -1; } return s; } /** * Hash code for this polynomial list. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + (list == null ? 0 : list.hashCode()); return h; } /** * String representation of the polynomial list. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer erg = new StringBuffer(); String[] vars = null; if (ring != null) { erg.append(ring.toString()); vars = ring.getVars(); } boolean first = true; erg.append("\n(\n"); String sa = null; for (GenPolynomial oa : list) { if (vars != null) { sa = oa.toString(vars); } else { sa = oa.toString(); } if (first) { first = false; } else { erg.append(", "); if (sa.length() > 10) { erg.append("\n"); } } erg.append("( " + sa + " )"); } erg.append("\n)"); return erg.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this polynomial list. */ public String toScript() { StringBuffer s = new StringBuffer(); if (ring instanceof GenSolvablePolynomialRing) { switch (Scripting.getLang()) { case Ruby: s.append("SolvIdeal.new("); break; case Python: default: s.append("SolvableIdeal("); } } else { switch (Scripting.getLang()) { case Ruby: s.append("SimIdeal.new("); break; case Python: default: s.append("Ideal("); } } if (ring != null) { s.append(ring.toScript()); } if (list == null) { s.append(")"); return s.toString(); } switch (Scripting.getLang()) { case Ruby: s.append(",\"\",["); break; case Python: default: s.append(",list=["); } boolean first = true; String sa = null; for (GenPolynomial oa : list) { sa = oa.toScript(); if (first) { first = false; } else { s.append(", "); } s.append("( " + sa + " )"); } s.append("])"); return s.toString(); } /** * Get ModuleList from PolynomialList. Extract module from polynomial ring. * @see edu.jas.poly.ModuleList * @param i number of variables to be contract form the polynomials. * @return module list corresponding to this. */ @SuppressWarnings("unchecked") public ModuleList getModuleList(int i) { GenPolynomialRing pfac = ring.contract(i); logger.debug("contracted ring = " + pfac); //System.out.println("contracted ring = " + pfac); List>> vecs = null; if (list == null) { return new ModuleList(pfac, vecs); } int rows = list.size(); vecs = new ArrayList>>(rows); if (rows == 0) { // nothing to do return new ModuleList(pfac, vecs); } ArrayList> zr = new ArrayList>(i - 1); GenPolynomial zero = pfac.getZERO(); for (int j = 0; j < i; j++) { zr.add(j, zero); } for (GenPolynomial p : list) { if (p != null) { Map> r = p.contract(pfac); //System.out.println("r = " + r ); List> row = (ArrayList>) zr.clone(); for (Map.Entry> me : r.entrySet()) { ExpVector e = me.getKey(); int[] dov = e.dependencyOnVariables(); int ix = 0; if (dov.length > 1) { throw new IllegalArgumentException("wrong dependencyOnVariables " + e); } else if (dov.length == 1) { ix = dov[0]; } //ix = i-1 - ix; // revert //System.out.println("ix = " + ix ); GenPolynomial vi = me.getValue(); //r.get( e ); row.set(ix, vi); } //System.out.println("row = " + row ); vecs.add(row); } } return new ModuleList(pfac, vecs); } /** * Get list as List of GenSolvablePolynomials. Required because no List * casts allowed. Equivalent to cast * (List<GenSolvablePolynomial<C>>) list. * @return solvable polynomial list from this. */ public List> castToSolvableList() { return castToSolvableList(list); } /** * Get list as List of GenSolvablePolynomials. Required because no List * casts allowed. Equivalent to cast * (List<GenSolvablePolynomial<C>>) list. * @return solvable polynomial list from this. */ public List> getSolvableList() { return castToSolvableList(list); } /** * Get ring as GenSolvablePolynomialRing. * @return solvable polynomial ring list from this. */ public GenSolvablePolynomialRing getSolvableRing() { return (GenSolvablePolynomialRing) ring; } /** * Get list as List of GenSolvablePolynomials. Required because no List * casts allowed. Equivalent to cast * (List<GenSolvablePolynomial<C>>) list. * @param list list of extensions of polynomials. * @return solvable polynomial list from this. */ public static > List> castToSolvableList( List> list) { List> slist = null; if (list == null) { return slist; } slist = new ArrayList>(list.size()); GenSolvablePolynomial s; for (GenPolynomial p : list) { if (!(p instanceof GenSolvablePolynomial)) { throw new IllegalArgumentException("no solvable polynomial " + p); } s = (GenSolvablePolynomial) p; slist.add(s); } return slist; } /** * Get list of list as List of List of GenSolvablePolynomials. Required * because no List casts allowed. Equivalent to cast * (List<GenSolvablePolynomial<C>>) list. * @param list list of extensions of polynomials. * @return solvable polynomial list from this. */ public static > List>> castToSolvableMatrix( List>> list) { List>> slist = null; if (list == null) { return slist; } slist = new ArrayList>>(list.size()); List> s; for (List> p : list) { s = PolynomialList. castToSolvableList(p); slist.add(s); } return slist; } /** * Get list of extensions of polynomials as List of GenPolynomials. Required * because no List casts allowed. Equivalent to cast * (List<GenPolynomial<C>>) list. Mainly used for lists of * GenSolvablePolynomials. * @param slist list of extensions of polynomials. * @return polynomial list from slist. */ public static > List> castToList( List> slist) { logger.debug("warn: can lead to wrong method dispatch"); List> list = null; if (slist == null) { return list; } list = new ArrayList>(slist.size()); for (GenPolynomial p : slist) { list.add(p); } return list; } /** * Get list of list of extensions of polynomials as List of List of * GenPolynomials. Required because no List casts allowed. Equivalent to * cast (List<GenPolynomial<C>>) list. Mainly used for lists of * GenSolvablePolynomials. * @param slist list of extensions of polynomials. * @return polynomial list from slist. */ public static > List>> castToMatrix( List>> slist) { logger.debug("warn: can lead to wrong method dispatch"); List>> list = null; if (slist == null) { return list; } list = new ArrayList>>(slist.size()); for (List> p : slist) { list.add(PolynomialList. castToList(p)); } return list; } /** * Test if list contains only ZEROs. * @return true, if this is the 0 list, else false */ public boolean isZERO() { if (list == null) { return true; } for (GenPolynomial p : list) { if (p == null) { continue; } if (!p.isZERO()) { return false; } } return true; } /** * Test if list contains a ONE. * @return true, if this contains 1, else false */ public boolean isONE() { if (list == null) { return false; } for (GenPolynomial p : list) { if (p == null) { continue; } if (p.isONE()) { return true; } } return false; } /** * Make homogeneous. * @return polynomial list of homogeneous polynomials. */ public PolynomialList homogenize() { GenPolynomialRing pfac = ring.extend(1); List> hom = new ArrayList>(list.size()); for (GenPolynomial p : list) { GenPolynomial h = p.homogenize(pfac); hom.add(h); } return new PolynomialList(pfac, hom); } /** * Dehomogenize. * @return polynomial list of de-homogenized polynomials. */ public PolynomialList deHomogenize() { GenPolynomialRing pfac = ring.contract(1); List> dehom = new ArrayList>(list.size()); for (GenPolynomial p : list) { GenPolynomial h = p.deHomogenize(pfac); dehom.add(h); } return new PolynomialList(pfac, dehom); } /** * Test if all polynomials are homogeneous. * @return true, if all polynomials are homogeneous, else false */ public boolean isHomogeneous() { if (list == null) { return true; } for (GenPolynomial p : list) { if (p == null) { continue; } if (!p.isHomogeneous()) { return false; } } return true; } } jas-2.5/src/edu/jas/poly/Complex.java0000644000175000017500000004056112014234362017724 0ustar giovannigiovanni/* * $Id: Complex.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.poly; import org.apache.log4j.Logger; import edu.jas.arith.BigComplex; import edu.jas.arith.BigDecimal; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.structure.RingElem; import edu.jas.structure.GcdRingElem; import edu.jas.structure.StarRingElem; /** * Generic Complex class implementing the RingElem interface. Objects of this * class are immutable. * @param base type of RingElem (for complex polynomials). * @author Heinz Kredel */ public class Complex> implements StarRingElem>, GcdRingElem> { private static final Logger logger = Logger.getLogger(Complex.class); private static final boolean debug = logger.isDebugEnabled(); /** * Complex class factory data structure. */ public final ComplexRing ring; /** * Real part of the data structure. */ protected final C re; /** * Imaginary part of the data structure. */ protected final C im; /** * The constructor creates a Complex object from two C objects as real and * imaginary part. * @param ring factory for Complex objects. * @param r real part. * @param i imaginary part. */ public Complex(ComplexRing ring, C r, C i) { this.ring = ring; re = r; im = i; } /** * The constructor creates a Complex object from a C object as real part, * the imaginary part is set to 0. * @param r real part. */ public Complex(ComplexRing ring, C r) { this(ring, r, ring.ring.getZERO()); } /** * The constructor creates a Complex object from a long element as real * part, the imaginary part is set to 0. * @param r real part. */ public Complex(ComplexRing ring, long r) { this(ring, ring.ring.fromInteger(r)); } /** * The constructor creates a Complex object with real part 0 and imaginary * part 0. */ public Complex(ComplexRing ring) { this(ring, ring.ring.getZERO()); } /** * The constructor creates a Complex object from a String representation. * @param s string of a Complex. * @throws NumberFormatException */ public Complex(ComplexRing ring, String s) throws NumberFormatException { this.ring = ring; if (s == null || s.length() == 0) { re = ring.ring.getZERO(); im = ring.ring.getZERO(); return; } s = s.trim(); int i = s.indexOf("i"); if (i < 0) { re = ring.ring.parse(s); im = ring.ring.getZERO(); return; } //logger.warn("String constructor not done"); String sr = ""; if (i > 0) { sr = s.substring(0, i); } String si = ""; if (i < s.length()) { si = s.substring(i + 1, s.length()); } //int j = sr.indexOf("+"); re = ring.ring.parse(sr.trim()); im = ring.ring.parse(si.trim()); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public ComplexRing factory() { return ring; } /** * Get the real part. * @return re. */ public C getRe() { return re; } /** * Get the imaginary part. * @return im. */ public C getIm() { return im; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public Complex copy() { return new Complex(ring, re, im); } /** * Get the String representation. */ @Override public String toString() { String s = re.toString(); //logger.info("compareTo "+im+" ? 0 = "+i); if (im.isZERO()) { return s; } s += "i" + im; return s; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer(); if (im.isZERO()) { s.append(re.toScript()); } else { C mi = im; //s.append(""); if (!re.isZERO()) { s.append(re.toScript()); if (mi.signum() > 0) { s.append(" + "); } else { s.append(" - "); mi = mi.negate(); } } if (mi.isONE()) { s.append("I"); } else { s.append(mi.toScript()).append(" * I"); } s.append(""); } return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return ring.toScript(); } /** * Is Complex number zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return re.isZERO() && im.isZERO(); } /** * Is Complex number one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return re.isONE() && im.isZERO(); } /** * Is Complex imaginary one. * @return If this is i then true is returned, else false. */ public boolean isIMAG() { return re.isZERO() && im.isONE(); } /** * Is Complex unit element. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (isZERO()) { return false; } if (ring.isField()) { return true; } return norm().re.isUnit(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof Complex)) { return false; } Complex bc = null; try { bc = (Complex) b; } catch (ClassCastException e) { } if (bc == null) { return false; } if (!ring.equals(bc.ring)) { return false; } return re.equals(bc.re) && im.equals(bc.im); } /** * Hash code for this Complex. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * re.hashCode() + im.hashCode(); } /** * Since complex numbers are unordered, we use lexicographical order of re * and im. * @return 0 if this is equal to b; 1 if re > b.re, or re == b.re and im > * b.im; -1 if re < b.re, or re == b.re and im < b.im */ //JAVA6only: @Override public int compareTo(Complex b) { int s = re.compareTo(b.re); if (s != 0) { return s; } return im.compareTo(b.im); } /** * Since complex numbers are unordered, we use lexicographical order of re * and im. * @return 0 if this is equal to 0; 1 if re > 0, or re == 0 and im > 0; -1 * if re < 0, or re == 0 and im < 0 * @see edu.jas.structure.RingElem#signum() */ public int signum() { int s = re.signum(); if (s != 0) { return s; } return im.signum(); } /* arithmetic operations: +, -, - */ /** * Complex number summation. * @param B a Complex number. * @return this+B. */ public Complex sum(Complex B) { return new Complex(ring, re.sum(B.re), im.sum(B.im)); } /** * Complex number subtract. * @param B a Complex number. * @return this-B. */ public Complex subtract(Complex B) { return new Complex(ring, re.subtract(B.re), im.subtract(B.im)); } /** * Complex number negative. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public Complex negate() { return new Complex(ring, re.negate(), im.negate()); } /* arithmetic operations: conjugate, absolut value */ /** * Complex number conjugate. * @return the complex conjugate of this. */ public Complex conjugate() { return new Complex(ring, re, im.negate()); } /** * Complex number norm. * @see edu.jas.structure.StarRingElem#norm() * @return ||this||. */ public Complex norm() { // this.conjugate().multiply(this); C v = re.multiply(re); v = v.sum(im.multiply(im)); return new Complex(ring, v); } /** * Complex number absolute value. * @see edu.jas.structure.RingElem#abs() * @return |this|^2. Note: The square root is not jet implemented. */ public Complex abs() { Complex n = norm(); logger.error("abs() square root missing"); // n = n.sqrt(); return n; } /* arithmetic operations: *, inverse, / */ /** * Complex number product. * @param B is a complex number. * @return this*B. */ public Complex multiply(Complex B) { return new Complex(ring, re.multiply(B.re).subtract(im.multiply(B.im)), re.multiply(B.im).sum( im.multiply(B.re))); } /** * Complex number inverse. * @return S with S*this = 1, if it is defined. * @see edu.jas.structure.RingElem#inverse() */ public Complex inverse() { C a = norm().re.inverse(); return new Complex(ring, re.multiply(a), im.multiply(a.negate())); } /** * Complex number remainder. * @param S is a complex number. * @return 0. */ public Complex remainder(Complex S) { if (ring.isField()) { return ring.getZERO(); } return quotientRemainder(S)[1]; } /** * Complex number divide. * @param B is a complex number, non-zero. * @return this/B. */ public Complex divide(Complex B) { if (ring.isField()) { return this.multiply(B.inverse()); } return quotientRemainder(B)[0]; } /** * Complex number quotient and remainder. * @param S Complex. * @return Complex[] { q, r } with q = this/S and r = rem(this,S). */ @SuppressWarnings("unchecked") public Complex[] quotientRemainder(Complex S) { Complex[] ret = new Complex[2]; C n = S.norm().re; Complex Sp = this.multiply(S.conjugate()); // == this*inv(S)*n C qr = Sp.re.divide(n); C rr = Sp.re.remainder(n); C qi = Sp.im.divide(n); C ri = Sp.im.remainder(n); C rr1 = rr; C ri1 = ri; if (rr.signum() < 0) { rr = rr.negate(); } if (ri.signum() < 0) { ri = ri.negate(); } C one = n.factory().fromInteger(1); if (rr.sum(rr).compareTo(n) > 0) { // rr > n/2 if (rr1.signum() < 0) { qr = qr.subtract(one); } else { qr = qr.sum(one); } } if (ri.sum(ri).compareTo(n) > 0) { // ri > n/2 if (ri1.signum() < 0) { qi = qi.subtract(one); } else { qi = qi.sum(one); } } Sp = new Complex(ring, qr, qi); Complex Rp = this.subtract(Sp.multiply(S)); if (debug && n.compareTo(Rp.norm().re) < 0) { System.out.println("n = " + n); System.out.println("qr = " + qr); System.out.println("qi = " + qi); System.out.println("rr = " + rr); System.out.println("ri = " + ri); System.out.println("rr1 = " + rr1); System.out.println("ri1 = " + ri1); System.out.println("this = " + this); System.out.println("S = " + S); System.out.println("Sp = " + Sp); BigInteger tr = (BigInteger) (Object) this.re; BigInteger ti = (BigInteger) (Object) this.im; BigInteger sr = (BigInteger) (Object) S.re; BigInteger si = (BigInteger) (Object) S.im; BigComplex tc = new BigComplex(new BigRational(tr), new BigRational(ti)); BigComplex sc = new BigComplex(new BigRational(sr), new BigRational(si)); BigComplex qc = tc.divide(sc); System.out.println("qc = " + qc); BigDecimal qrd = new BigDecimal(qc.getRe()); BigDecimal qid = new BigDecimal(qc.getIm()); System.out.println("qrd = " + qrd); System.out.println("qid = " + qid); throw new ArithmeticException("QR norm not decreasing " + Rp + ", " + Rp.norm()); } ret[0] = Sp; ret[1] = Rp; return ret; } /** * Complex number quotient and remainder. * @param S Complex. * @return Complex[] { q, r } with q = this/S and r = rem(this,S). * @deprecated use quotientRemainder() */ @Deprecated public Complex[] divideAndRemainder(Complex S) { return quotientRemainder(S); } /** * Complex number greatest common divisor. * @param S Complex. * @return gcd(this,S). */ public Complex gcd(Complex S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } if (ring.isField()) { return ring.getONE(); } Complex a = this; Complex b = S; if (a.re.signum() < 0) { a = a.negate(); } if (b.re.signum() < 0) { b = b.negate(); } while (!b.isZERO()) { if (debug) { logger.info("norm(b), a, b = " + b.norm() + ", " + a + ", " + b); } Complex[] qr = a.quotientRemainder(b); if (qr[0].isZERO()) { System.out.println("a = " + a); } a = b; b = qr[1]; } if (a.re.signum() < 0) { a = a.negate(); } return a; } /** * Complex extended greatest common divisor. * @param S Complex. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ @SuppressWarnings("unchecked") public Complex[] egcd(Complex S) { Complex[] ret = new Complex[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; return ret; } if (this.isZERO()) { ret[0] = S; return ret; } if (ring.isField()) { Complex half = new Complex(ring, ring.ring.fromInteger(1).divide(ring.ring.fromInteger(2))); ret[0] = ring.getONE(); ret[1] = this.inverse().multiply(half); ret[2] = S.inverse().multiply(half); return ret; } Complex[] qr; Complex q = this; Complex r = S; Complex c1 = ring.getONE(); Complex d1 = ring.getZERO(); Complex c2 = ring.getZERO(); Complex d2 = ring.getONE(); Complex x1; Complex x2; while (!r.isZERO()) { if (debug) { logger.info("norm(r), q, r = " + r.norm() + ", " + q + ", " + r); } qr = q.quotientRemainder(r); q = qr[0]; x1 = c1.subtract(q.multiply(d1)); x2 = c2.subtract(q.multiply(d2)); c1 = d1; c2 = d2; d1 = x1; d2 = x2; q = r; r = qr[1]; } if (q.re.signum() < 0) { q = q.negate(); c1 = c1.negate(); c2 = c2.negate(); } ret[0] = q; ret[1] = c1; ret[2] = c2; return ret; } } jas-2.5/src/edu/jas/poly/PolynomialRing.java0000644000175000017500000000533411014364036021260 0ustar giovannigiovanni/* * $Id: PolynomialRing.java 1801 2008-05-19 20:50:39Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.Random; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Polynomial factory interface. * Defines polynomial specific factory methods. * @author Heinz Kredel */ public interface PolynomialRing> extends RingFactory< Polynomial > { /** * Number of variables. * @return the number of variables. */ public int numberOfVariables(); /** Get the variable names. * @return vars. */ public String[] getVars(); /** * Generate a random polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @return a random polynomial. */ public Polynomial random(int k, int l, int d, float q); /** * Generate a random polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @param rnd is a source for random bits. * @return a random polynomial. */ public Polynomial random(int k, int l, int d, float q, Random rnd); /** * Generate univariate polynomial in a given variable. * @param i the index of the variable. * @return X_i as univariate polynomial. */ public Polynomial univariate(int i); /** * Generate univariate polynomial in a given variable with given exponent. * @param i the index of the variable. * @param e the exponent of the variable. * @return X_i^e as univariate polynomial. */ public Polynomial univariate(int i, long e); /** * Generate list of univariate polynomials in all variables. * @return List(X_1,...,X_n) a list of univariate polynomials. */ public List> univariateList(); /** * Extend variables. Used e.g. in module embedding. * Extend number of variables by i. * @param i number of variables to extend. * @return extended polynomial ring factory. */ public PolynomialRing extend(int i); /** * Contract variables. Used e.g. in module embedding. * Contract number of variables by i. * @param i number of variables to remove. * @return contracted polynomial ring factory. */ public PolynomialRing contract(int i); /** * Reverse variables. Used e.g. in opposite rings. * @return polynomial ring factory with reversed variables. */ public PolynomialRing reverse(); } jas-2.5/src/edu/jas/poly/ComplexRing.java0000644000175000017500000001646211713541010020543 0ustar giovannigiovanni/* * $Id: ComplexRing.java 3882 2012-02-05 17:53:12Z kredel $ */ package edu.jas.poly; import java.io.Reader; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.StringUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Generic Complex ring factory implementing the RingFactory interface. Objects * of this class are immutable. * @param base type. * @author Heinz Kredel */ public class ComplexRing> implements RingFactory> { private final static Random random = new Random(); @SuppressWarnings("unused") private static final Logger logger = Logger.getLogger(ComplexRing.class); /** * Complex class elements factory data structure. */ public final RingFactory ring; /** * The constructor creates a ComplexRing object. * @param ring factory for Complex real and imaginary parts. */ public ComplexRing(RingFactory ring) { this.ring = ring; } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List gens = ring.generators(); List> g = new ArrayList>(gens.size() + 1); for (C x : gens) { Complex cx = new Complex(this, x); g.add(cx); } g.add(getIMAG()); return g; } /** * Corresponding algebraic number ring. * @return algebraic number ring. * not jet possible. */ public AlgebraicNumberRing algebraicRing() { GenPolynomialRing pfac = new GenPolynomialRing(ring, 1, new TermOrder(TermOrder.INVLEX), new String[] { "I" }); GenPolynomial I = pfac.univariate(0, 2L).sum(pfac.getONE()); AlgebraicNumberRing afac = new AlgebraicNumberRing(I, ring.isField()); // must indicate field return afac; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return ring.isFinite(); } /** * Copy Complex element c. * @param c Complex<C>. * @return a copy of c. */ public Complex copy(Complex c) { return new Complex(this, c.re, c.im); } /** * Get the zero element. * @return 0 as Complex<C>. */ public Complex getZERO() { return new Complex(this); } /** * Get the one element. * @return 1 as Complex<C>. */ public Complex getONE() { return new Complex(this, ring.getONE()); } /** * Get the i element. * @return i as Complex<C>. */ public Complex getIMAG() { return new Complex(this, ring.getZERO(), ring.getONE()); } /** * Query if this ring is commutative. * @return true. */ public boolean isCommutative() { return ring.isCommutative(); } /** * Query if this ring is associative. * @return true. */ public boolean isAssociative() { return ring.isAssociative(); } /** * Query if this ring is a field. * @return true. */ public boolean isField() { return ring.isField(); } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return ring.characteristic(); } /** * Get a Complex element from a BigInteger. * @param a BigInteger. * @return a Complex<C>. */ public Complex fromInteger(BigInteger a) { return new Complex(this, ring.fromInteger(a)); } /** * Get a Complex element from a long. * @param a long. * @return a Complex<C>. */ public Complex fromInteger(long a) { return new Complex(this, ring.fromInteger(a)); } /** * Get the String representation. */ @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("Complex["); if (ring instanceof RingElem) { RingElem ri = (RingElem) ring; sb.append(ri.toScriptFactory()); } else { sb.append(ring.toString()); } sb.append("]"); return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case StringBuffer s = new StringBuffer(); s.append("CR("); if (ring instanceof RingElem) { RingElem ri = (RingElem) ring; s.append(ri.toScriptFactory()); } else { s.append(ring.toScript()); } s.append(")"); return s.toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof ComplexRing)) { return false; } ComplexRing a = null; try { a = (ComplexRing) b; } catch (ClassCastException e) { } if (a == null) { return false; } if (!ring.equals(a.ring)) { return false; } return true; } /** * Hash code for this ComplexRing<C>. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return ring.hashCode(); } /** * Complex number random. Random base numbers A and B are generated using * random(n). Then R is the complex number with real part A and imaginary * part B. * @param n such that 0 ≤ A, B ≤ (2n-1). * @return R. */ public Complex random(int n) { return random(n, random); // C r = ring.random( n ).abs(); // C i = ring.random( n ).abs(); // return new Complex(this, r, i ); } /** * Complex number random. Random base numbers A and B are generated using * random(n). Then R is the complex number with real part A and imaginary * part B. * @param n such that 0 ≤ A, B ≤ (2n-1). * @param rnd is a source for random bits. * @return R. */ public Complex random(int n, Random rnd) { C r = ring.random(n, rnd); C i = ring.random(n, rnd); return new Complex(this, r, i); } /** * Parse complex number from string. * @param s String. * @return Complex from s. */ public Complex parse(String s) { return new Complex(this, s); } /** * Parse complex number from Reader. * @param r Reader. * @return next Complex from r. */ public Complex parse(Reader r) { return parse(StringUtil.nextString(r)); } } jas-2.5/src/edu/jas/poly/GenWordPolynomial.java0000644000175000017500000012414712031654714021737 0ustar giovannigiovanni/* * $Id: GenWordPolynomial.java 4225 2012-09-29 20:27:56Z kredel $ */ package edu.jas.poly; import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.kern.PreemptingException; import edu.jas.structure.NotInvertibleException; import edu.jas.structure.RingElem; import edu.jas.structure.UnaryFunctor; /** * GenWordPolynomial generic polynomials implementing RingElem. Non-commutative * string polynomials over C. Objects of this class are intended to be * immutable. The implementation is based on TreeMap respectively SortedMap from * words to coefficients. Only the coefficients are modeled with generic * types, the "exponents" are fixed to Word. C can also be a non integral domain, * e.g. a ModInteger, i.e. it may contain zero divisors, since multiply() does * check for zeros. * @param coefficient type * @author Heinz Kredel */ public final class GenWordPolynomial> implements RingElem>, Iterable> { /** * The factory for the polynomial ring. */ public final GenWordPolynomialRing ring; /** * The data structure for polynomials. */ final SortedMap val; // do not change to TreeMap private static final Logger logger = Logger.getLogger(GenWordPolynomial.class); private final boolean debug = logger.isDebugEnabled(); // protected GenWordPolynomial() { ring = null; val = null; } // don't use /** * Private constructor for GenWordPolynomial. * @param r polynomial ring factory. * @param t TreeMap with correct ordering. */ private GenWordPolynomial(GenWordPolynomialRing r, TreeMap t) { ring = r; val = t; if (ring.checkPreempt) { if (Thread.currentThread().isInterrupted()) { logger.debug("throw PreemptingException"); throw new PreemptingException(); } } } /** * Constructor for zero GenWordPolynomial. * @param r polynomial ring factory. */ public GenWordPolynomial(GenWordPolynomialRing r) { this(r, new TreeMap(r.alphabet.getDescendComparator())); } /** * Constructor for GenWordPolynomial c * xe. * @param r polynomial ring factory. * @param c coefficient. * @param e word. */ public GenWordPolynomial(GenWordPolynomialRing r, C c, Word e) { this(r); if (!c.isZERO()) { val.put(e, c); } } /** * Constructor for GenWordPolynomial c * x0. * @param r polynomial ring factory. * @param c coefficient. */ public GenWordPolynomial(GenWordPolynomialRing r, C c) { this(r, c, r.wone); } /** * Constructor for GenWordPolynomial xe. * @param r polynomial ring factory. * @param e word. */ public GenWordPolynomial(GenWordPolynomialRing r, Word e) { this(r, r.coFac.getONE(), e); } /** * Constructor for GenWordPolynomial. * @param r polynomial ring factory. * @param v the SortedMap of some other polynomial. */ protected GenWordPolynomial(GenWordPolynomialRing r, SortedMap v) { this(r); val.putAll(v); // assume no zero coefficients } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public GenWordPolynomialRing factory() { return ring; } /** * Copy this GenWordPolynomial. * @return copy of this. */ public GenWordPolynomial copy() { return new GenWordPolynomial(ring, this.val); } /** * Length of GenWordPolynomial. * @return number of coefficients of this GenWordPolynomial. */ public int length() { return val.size(); } /** * Word to coefficient map of GenWordPolynomial. * @return val as unmodifiable SortedMap. */ public SortedMap getMap() { // return val; return Collections. unmodifiableSortedMap(val); } /** * Put an Word to coefficient entry into the internal map of this * GenWordPolynomial. Note: Do not use this method unless you are * constructing a new polynomial. this is modified and breaks the * immutability promise of this class. * @param c coefficient. * @param e word. */ public void doPutToMap(Word e, C c) { if (debug) { C a = val.get(e); if (a != null) { logger.error("map entry exists " + e + " to " + a + " new " + c); } } if (!c.isZERO()) { val.put(e, c); } } /** * Put an a sorted map of words to coefficients into the internal map of * this GenWordPolynomial. Note: Do not use this method unless you * are constructing a new polynomial. this is modified and breaks the * immutability promise of this class. * @param vals sorted map of wordss and coefficients. */ public void doPutToMap(SortedMap vals) { for (Map.Entry me : vals.entrySet()) { Word e = me.getKey(); if (debug) { C a = val.get(e); if (a != null) { logger.error("map entry exists " + e + " to " + a + " new " + me.getValue()); } } C c = me.getValue(); if (!c.isZERO()) { val.put(e, c); } } } /** * String representation of GenWordPolynomial. * @see java.lang.Object#toString() */ @Override public String toString() { if (isZERO()) { return "0"; } if (isONE()) { return "1"; } StringBuffer s = new StringBuffer(); if (val.size() > 1) { s.append("( "); } boolean parenthesis = false; boolean first = true; for (Map.Entry m : val.entrySet()) { C c = m.getValue(); if (first) { first = false; } else { if (c.signum() < 0) { s.append(" - "); c = c.negate(); } else { s.append(" + "); } } Word e = m.getKey(); if (!c.isONE() || e.isONE()) { if (parenthesis) { s.append("( "); } s.append(c.toString()); if (parenthesis) { s.append(" )"); } if (!e.isONE()) { s.append(" "); } } s.append(e.toString()); } if (val.size() > 1) { s.append(" )"); } return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { if (isZERO()) { return "0"; } if (isONE()) { return "1"; } StringBuffer s = new StringBuffer(); if (val.size() > 1) { s.append("( "); } boolean parenthesis = false; boolean first = true; for (Map.Entry m : val.entrySet()) { C c = m.getValue(); if (first) { first = false; } else { if (c.signum() < 0) { s.append(" - "); c = c.negate(); } else { s.append(" + "); } } Word e = m.getKey(); if (!c.isONE() || e.isONE()) { if (parenthesis) { s.append("( "); } s.append(c.toScript()); if (parenthesis) { s.append(" )"); } if (!e.isONE()) { s.append(" * "); } } s.append(e.toScript()); } if (val.size() > 1) { s.append(" )"); } return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Is GenWordPolynomial<C> zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return (val.size() == 0); } /** * Is GenWordPolynomial<C> one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { if (val.size() != 1) { return false; } C c = val.get(ring.wone); if (c == null) { return false; } return c.isONE(); } /** * Is GenWordPolynomial<C> a unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (val.size() != 1) { return false; } C c = val.get(ring.wone); if (c == null) { return false; } return c.isUnit(); } /** * Is GenWordPolynomial<C> a constant. * @return If this is a constant polynomial then true is returned, else * false. */ public boolean isConstant() { if (val.size() != 1) { return false; } C c = val.get(ring.wone); if (c == null) { return false; } return true; } /** * Is GenWordPolynomial<C> homogeneous. * @return true, if this is homogeneous, else false. */ public boolean isHomogeneous() { if (val.size() <= 1) { return true; } long deg = -1; for (Word e : val.keySet()) { if (deg < 0) { deg = e.degree(); } else if (deg != e.degree()) { return false; } } return true; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { if (!(B instanceof GenWordPolynomial)) { return false; } GenWordPolynomial a = null; try { a = (GenWordPolynomial) B; } catch (ClassCastException ignored) { } if (a == null) { return false; } return this.compareTo(a) == 0; } /** * Hash code for this polynomial. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = (ring.hashCode() << 27); h += val.hashCode(); return h; } /** * GenWordPolynomial comparison. * @param b GenWordPolynomial. * @return sign(this-b). */ public int compareTo(GenWordPolynomial b) { if (b == null) { return 1; } SortedMap av = this.val; SortedMap bv = b.val; Iterator> ai = av.entrySet().iterator(); Iterator> bi = bv.entrySet().iterator(); int s = 0; int c = 0; while (ai.hasNext() && bi.hasNext()) { Map.Entry aie = ai.next(); Map.Entry bie = bi.next(); Word ae = aie.getKey(); Word be = bie.getKey(); s = ae.compareTo(be); //System.out.println("s = " + s + ", " + ae + ", " +be); if (s != 0) { return s; } if (c == 0) { C ac = aie.getValue(); //av.get(ae); C bc = bie.getValue(); //bv.get(be); c = ac.compareTo(bc); } } if (ai.hasNext()) { return 1; } if (bi.hasNext()) { return -1; } // now all keys are equal return c; } /** * GenWordPolynomial signum. * @return sign(ldcf(this)). */ public int signum() { if (this.isZERO()) { return 0; } Word t = val.firstKey(); C c = val.get(t); return c.signum(); } /** * Number of variables. * @return ring.alphabet.length(). */ public int numberOfVariables() { return ring.alphabet.length(); } /** * Leading monomial. * @return first map entry. */ public Map.Entry leadingMonomial() { if (val.size() == 0) return null; Iterator> ai = val.entrySet().iterator(); return ai.next(); } /** * Leading word. * @return first highest word. */ public Word leadingWord() { if (val.size() == 0) { return ring.wone; // null? needs changes? } return val.firstKey(); } /** * Trailing word. * @return last lowest word. */ public Word trailingWord() { if (val.size() == 0) { return ring.wone; // or null ?; } return val.lastKey(); } /** * Leading base coefficient. * @return first coefficient. */ public C leadingBaseCoefficient() { if (val.size() == 0) { return ring.coFac.getZERO(); } return val.get(val.firstKey()); } /** * Trailing base coefficient. * @return coefficient of constant term. */ public C trailingBaseCoefficient() { C c = val.get(ring.wone); if (c == null) { return ring.coFac.getZERO(); } return c; } /** * Coefficient. * @param e word. * @return coefficient for given word. */ public C coefficient(Word e) { C c = val.get(e); if (c == null) { c = ring.coFac.getZERO(); } return c; } /** * Reductum. * @return this - leading monomial. */ public GenWordPolynomial reductum() { if (val.size() <= 1) { return ring.getZERO(); } Iterator ai = val.keySet().iterator(); Word lt = ai.next(); lt = ai.next(); // size > 1 SortedMap red = val.tailMap(lt); return new GenWordPolynomial(ring, red); } /** * Maximal degree. * @return maximal degree in any variables. */ public long degree() { if (val.size() == 0) { return 0; // 0 or -1 ?; } long deg = 0; for (Word e : val.keySet()) { long d = e.degree(); if (d > deg) { deg = d; } } return deg; } /** * GenWordPolynomial maximum norm. * @return ||this||. */ public C maxNorm() { C n = ring.getZEROCoefficient(); for (C c : val.values()) { C x = c.abs(); if (n.compareTo(x) < 0) { n = x; } } return n; } /** * GenWordPolynomial sum norm. * @return sum of all absolute values of coefficients. */ public C sumNorm() { C n = ring.getZEROCoefficient(); for (C c : val.values()) { C x = c.abs(); n = n.sum(x); } return n; } /** * GenWordPolynomial summation. * @param S GenWordPolynomial. * @return this+S. */ public GenWordPolynomial sum(GenWordPolynomial S) { if (S == null) { return this; } if (S.isZERO()) { return this; } if (this.isZERO()) { return S; } assert (ring.alphabet == S.ring.alphabet); GenWordPolynomial n = this.copy(); //new GenWordPolynomial(ring, val); SortedMap nv = n.val; SortedMap sv = S.val; for (Map.Entry me : sv.entrySet()) { Word e = me.getKey(); C y = me.getValue(); //sv.get(e); // assert y != null C x = nv.get(e); if (x != null) { x = x.sum(y); if (!x.isZERO()) { nv.put(e, x); } else { nv.remove(e); } } else { nv.put(e, y); } } return n; } /** * GenWordPolynomial addition. This method is not very efficient, since this * is copied. * @param a coefficient. * @param e word. * @return this + a e. */ public GenWordPolynomial sum(C a, Word e) { if (a == null) { return this; } if (a.isZERO()) { return this; } GenWordPolynomial n = this.copy(); //new GenWordPolynomial(ring, val); SortedMap nv = n.val; C x = nv.get(e); if (x != null) { x = x.sum(a); if (!x.isZERO()) { nv.put(e, x); } else { nv.remove(e); } } else { nv.put(e, a); } return n; } /** * GenWordPolynomial addition. This method is not very efficient, since this * is copied. * @param a coefficient. * @return this + a x0. */ public GenWordPolynomial sum(C a) { return sum(a, ring.wone); } /** * GenWordPolynomial subtraction. * @param S GenWordPolynomial. * @return this-S. */ public GenWordPolynomial subtract(GenWordPolynomial S) { if (S == null) { return this; } if (S.isZERO()) { return this; } if (this.isZERO()) { return S.negate(); } assert (ring.alphabet == S.ring.alphabet); GenWordPolynomial n = this.copy(); //new GenWordPolynomial(ring, val); SortedMap nv = n.val; SortedMap sv = S.val; for (Map.Entry me : sv.entrySet()) { Word e = me.getKey(); C y = me.getValue(); //sv.get(e); // assert y != null C x = nv.get(e); if (x != null) { x = x.subtract(y); if (!x.isZERO()) { nv.put(e, x); } else { nv.remove(e); } } else { nv.put(e, y.negate()); } } return n; } /** * GenWordPolynomial subtraction. This method is not very efficient, since * this is copied. * @param a coefficient. * @param e word. * @return this - a e. */ public GenWordPolynomial subtract(C a, Word e) { if (a == null) { return this; } if (a.isZERO()) { return this; } GenWordPolynomial n = this.copy(); //new GenWordPolynomial(ring, val); SortedMap nv = n.val; C x = nv.get(e); if (x != null) { x = x.subtract(a); if (!x.isZERO()) { nv.put(e, x); } else { nv.remove(e); } } else { nv.put(e, a.negate()); } return n; } /** * GenWordPolynomial subtract. This method is not very efficient, since this * is copied. * @param a coefficient. * @return this + a x0. */ public GenWordPolynomial subtract(C a) { return subtract(a, ring.wone); } /** * GenWordPolynomial negation. * @return -this. */ public GenWordPolynomial negate() { GenWordPolynomial n = ring.getZERO().copy(); SortedMap v = n.val; for (Map.Entry m : val.entrySet()) { C x = m.getValue(); // != null, 0 v.put(m.getKey(), x.negate()); } return n; } /** * GenWordPolynomial absolute value, i.e. leadingCoefficient > 0. * @return abs(this). */ public GenWordPolynomial abs() { if (leadingBaseCoefficient().signum() < 0) { return this.negate(); } return this; } /** * GenWordPolynomial multiplication. * @param S GenWordPolynomial. * @return this*S. */ public GenWordPolynomial multiply(GenWordPolynomial S) { if (S == null) { return ring.getZERO(); } if (S.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } assert (ring.alphabet == S.ring.alphabet); GenWordPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c1 = m1.getValue(); Word e1 = m1.getKey(); for (Map.Entry m2 : S.val.entrySet()) { C c2 = m2.getValue(); Word e2 = m2.getKey(); C c = c1.multiply(c2); // check non zero if not domain if (!c.isZERO()) { Word e = e1.multiply(e2); C c0 = pv.get(e); if (c0 == null) { pv.put(e, c); } else { c0 = c0.sum(c); if (!c0.isZERO()) { pv.put(e, c0); } else { pv.remove(e); } } } } } return p; } /** * GenWordPolynomial left and right multiplication. Product with * two polynomials. * @param S GenWordPolynomial. * @param T GenWordPolynomial. * @return S*this*T. */ public GenWordPolynomial multiply(GenWordPolynomial S, GenWordPolynomial T) { if ( S.isZERO() || T.isZERO() ) { return ring.getZERO(); } if ( S.isONE() ) { return multiply(T); } if ( T.isONE() ) { return S.multiply(this); } return S.multiply(this).multiply(T); } /** * GenWordPolynomial multiplication. Product with coefficient ring element. * @param s coefficient. * @return this*s. */ public GenWordPolynomial multiply(C s) { if (s == null) { return ring.getZERO(); } if (s.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } GenWordPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c1 = m1.getValue(); Word e1 = m1.getKey(); C c = c1.multiply(s); // check non zero if not domain if (!c.isZERO()) { pv.put(e1, c); // or m1.setValue( c ) } } return p; } /** * GenWordPolynomial multiplication. Product with coefficient ring element. * @param s coefficient. * @param t coefficient. * @return s*this*t. */ public GenWordPolynomial multiply(C s, C t) { if (s == null || t == null) { return ring.getZERO(); } if (s.isZERO()||t.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } GenWordPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c1 = m1.getValue(); Word e = m1.getKey(); C c = s.multiply(c1).multiply(t); // check non zero if not domain if (!c.isZERO()) { pv.put(e, c); // or m1.setValue( c ) } } return p; } /** * GenWordPolynomial monic, i.e. leadingCoefficient == 1. If * leadingCoefficient is not invertible returns this unmodified. * @return monic(this). */ public GenWordPolynomial monic() { if (this.isZERO()) { return this; } C lc = leadingBaseCoefficient(); if (!lc.isUnit()) { //System.out.println("lc = "+lc); return this; } C lm = lc.inverse(); return multiply(lm); } /** * GenWordPolynomial multiplication. Product with ring element and word. * @param s coefficient. * @param e left word. * @return this * s e. */ public GenWordPolynomial multiply(C s, Word e) { if (s == null) { return ring.getZERO(); } if (s.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } GenWordPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c1 = m1.getValue(); Word e1 = m1.getKey(); C c = c1.multiply(s); // check non zero if not domain if (!c.isZERO()) { Word e2 = e1.multiply(e); pv.put(e2, c); } } return p; } /** * GenWordPolynomial left and right multiplication. Product with * ring element and two words. * @param e left word. * @param f right word. * @return e * this * f. */ public GenWordPolynomial multiply(Word e, Word f) { if (this.isZERO()) { return this; } if (e.isONE()) { return multiply(f); } GenWordPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c = m1.getValue(); Word e1 = m1.getKey(); Word e2 = e.multiply(e1.multiply(f)); pv.put(e2, c); } return p; } /** * GenWordPolynomial left and right multiplication. Product with * ring element and two words. * @param s coefficient. * @param e left word. * @param f right word. * @return e * this * s * f. */ public GenWordPolynomial multiply(C s, Word e, Word f) { if (s == null) { return ring.getZERO(); } if (s.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } if (e.isONE()) { return multiply(s, f); } C c = ring.coFac.getONE(); return multiply(c,e,s,f); // sic, history } /** * GenWordPolynomial left and right multiplication. Product with * ring element and two words. * @param s coefficient. * @param e left word. * @param t coefficient. * @param f right word. * @return s * e * this * t * f. */ public GenWordPolynomial multiply(C s, Word e, C t, Word f) { if (s == null) { return ring.getZERO(); } if (s.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } GenWordPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c1 = m1.getValue(); C c = s.multiply(c1).multiply(t); // check non zero if not domain if (!c.isZERO()) { Word e1 = m1.getKey(); Word e2 = e.multiply(e1).multiply(f); pv.put(e2, c); } } return p; } /** * GenWordPolynomial multiplication. Product with word. * @param e word (!= null). * @return this * e. */ public GenWordPolynomial multiply(Word e) { if (this.isZERO()) { return this; } GenWordPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c1 = m1.getValue(); Word e1 = m1.getKey(); Word e2 = e1.multiply(e); pv.put(e2, c1); } return p; } /** * GenWordPolynomial multiplication. Product with 'monomial'. * @param m 'monomial'. * @return this * m. */ public GenWordPolynomial multiply(Map.Entry m) { if (m == null) { return ring.getZERO(); } return multiply(m.getValue(), m.getKey()); } /** * GenWordPolynomial division. Division by coefficient ring element. Fails, * if exact division is not possible. * @param s coefficient. * @return this/s. */ public GenWordPolynomial divide(C s) { if (s == null || s.isZERO()) { throw new ArithmeticException(this.getClass().getName() + " division by zero"); } if (this.isZERO()) { return this; } //C t = s.inverse(); //return multiply(t); GenWordPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m : val.entrySet()) { Word e = m.getKey(); C c1 = m.getValue(); C c = c1.divide(s); if (debug) { C x = c1.remainder(s); if (!x.isZERO()) { logger.info("divide x = " + x); throw new ArithmeticException(this.getClass().getName() + " no exact division: " + c1 + "/" + s); } } if (c.isZERO()) { throw new ArithmeticException(this.getClass().getName() + " no exact division: " + c1 + "/" + s + ", in " + this); } pv.put(e, c); // or m1.setValue( c ) } return p; } /** * GenWordPolynomial division with remainder. Fails, if exact division by * leading base coefficient is not possible. Meaningful only for univariate * polynomials over fields, but works in any case. * @param S nonzero GenWordPolynomial with invertible leading coefficient. * @return [ quotient , remainder ] with this = quotient * S + remainder and * deg(remainder) < deg(S) or remiander = 0. * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial). */ @SuppressWarnings("unchecked") public GenWordPolynomial[] quotientRemainder(GenWordPolynomial S) { if (S == null || S.isZERO()) { throw new ArithmeticException(this.getClass().getName() + " division by zero"); } C c = S.leadingBaseCoefficient(); if (!c.isUnit()) { throw new ArithmeticException(this.getClass().getName() + " lbcf not invertible " + c); } C ci = c.inverse(); C one = ring.coFac.getONE(); assert (ring.alphabet == S.ring.alphabet); WordFactory.WordComparator cmp = ring.alphabet.getDescendComparator(); Word e = S.leadingWord(); GenWordPolynomial h; GenWordPolynomial q = ring.getZERO().copy(); GenWordPolynomial r = this.copy(); while (!r.isZERO()) { Word f = r.leadingWord(); if (f.multipleOf(e)) { C a = r.leadingBaseCoefficient(); Word[] g = f.divideWord(e); // divide not sufficient //logger.info("div: f = " + f + ", e = " + e + ", g = " + g[0] + ", " + g[1]); a = a.multiply(ci); q = q.sum(a, g[0].multiply(g[1])); h = S.multiply(a, g[0], one, g[1]); r = r.subtract(h); Word fr = r.leadingWord(); if (cmp.compare(f, fr) > 0) { // non noetherian reduction throw new RuntimeException("possible infinite loop: f = " + f + ", fr = " + fr); } } else { break; } } GenWordPolynomial[] ret = new GenWordPolynomial[2]; ret[0] = q; ret[1] = r; return ret; } /** * GenWordPolynomial division. Fails, if exact division by leading base * coefficient is not possible. Meaningful only for univariate polynomials * over fields, but works in any case. * @param S nonzero GenWordPolynomial with invertible leading coefficient. * @return quotient with this = quotient * S + remainder. * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial). */ public GenWordPolynomial divide(GenWordPolynomial S) { return quotientRemainder(S)[0]; } /** * GenWordPolynomial remainder. Fails, if exact division by leading base * coefficient is not possible. Meaningful only for univariate polynomials * over fields, but works in any case. * @param S nonzero GenWordPolynomial with invertible leading coefficient. * @return remainder with this = quotient * S + remainder. * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial). */ public GenWordPolynomial remainder(GenWordPolynomial S) { if (S == null || S.isZERO()) { throw new ArithmeticException(this.getClass().getName() + " division by zero"); } C c = S.leadingBaseCoefficient(); if (!c.isUnit()) { throw new ArithmeticException(this.getClass().getName() + " lbc not invertible " + c); } C ci = c.inverse(); C one = ring.coFac.getONE(); assert (ring.alphabet == S.ring.alphabet); WordFactory.WordComparator cmp = ring.alphabet.getDescendComparator(); Word e = S.leadingWord(); GenWordPolynomial h; GenWordPolynomial r = this.copy(); while (!r.isZERO()) { Word f = r.leadingWord(); if (f.multipleOf(e)) { C a = r.leadingBaseCoefficient(); Word[] g = f.divideWord(e); // divide not sufficient //logger.info("rem: f = " + f + ", e = " + e + ", g = " + g[0] + ", " + g[1]); a = a.multiply(ci); h = S.multiply(a, g[0], one, g[1]); r = r.subtract(h); Word fr = r.leadingWord(); if (cmp.compare(f, fr) > 0) { // non noetherian reduction throw new RuntimeException("possible infinite loop: f = " + f + ", fr = " + fr); } } else { break; } } return r; } /** * GenWordPolynomial greatest common divisor. Only for univariate * polynomials over fields. * @param S GenWordPolynomial. * @return gcd(this,S). */ public GenWordPolynomial gcd(GenWordPolynomial S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } if (ring.alphabet.length() != 1) { throw new IllegalArgumentException("no univariate polynomial " + ring); } GenWordPolynomial x; GenWordPolynomial q = this; GenWordPolynomial r = S; while (!r.isZERO()) { x = q.remainder(r); q = r; r = x; } return q.monic(); // normalize } /** * GenWordPolynomial extended greatest comon divisor. Only for univariate * polynomials over fields. * @param S GenWordPolynomial. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ @SuppressWarnings("unchecked") public GenWordPolynomial[] egcd(GenWordPolynomial S) { GenWordPolynomial[] ret = new GenWordPolynomial[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; ret[1] = this.ring.getONE(); ret[2] = this.ring.getZERO(); return ret; } if (this.isZERO()) { ret[0] = S; ret[1] = this.ring.getZERO(); ret[2] = this.ring.getONE(); return ret; } if (ring.alphabet.length() != 1) { throw new IllegalArgumentException("no univariate polynomial " + ring); } if (this.isConstant() && S.isConstant()) { C t = this.leadingBaseCoefficient(); C s = S.leadingBaseCoefficient(); C[] gg = t.egcd(s); //System.out.println("coeff gcd = " + Arrays.toString(gg)); GenWordPolynomial z = this.ring.getZERO(); ret[0] = z.sum(gg[0]); ret[1] = z.sum(gg[1]); ret[2] = z.sum(gg[2]); return ret; } GenWordPolynomial[] qr; GenWordPolynomial q = this; GenWordPolynomial r = S; GenWordPolynomial c1 = ring.getONE().copy(); GenWordPolynomial d1 = ring.getZERO().copy(); GenWordPolynomial c2 = ring.getZERO().copy(); GenWordPolynomial d2 = ring.getONE().copy(); GenWordPolynomial x1; GenWordPolynomial x2; while (!r.isZERO()) { qr = q.quotientRemainder(r); q = qr[0]; x1 = c1.subtract(q.multiply(d1)); x2 = c2.subtract(q.multiply(d2)); c1 = d1; c2 = d2; d1 = x1; d2 = x2; q = r; r = qr[1]; } // normalize ldcf(q) to 1, i.e. make monic C g = q.leadingBaseCoefficient(); if (g.isUnit()) { C h = g.inverse(); q = q.multiply(h); c1 = c1.multiply(h); c2 = c2.multiply(h); } //assert ( ((c1.multiply(this)).sum( c2.multiply(S)).equals(q) )); ret[0] = q; ret[1] = c1; ret[2] = c2; return ret; } /** * GenWordPolynomial half extended greatest comon divisor. Only for * univariate polynomials over fields. * @param S GenWordPolynomial. * @return [ gcd(this,S), a ] with a*this + b*S = gcd(this,S). */ @SuppressWarnings("unchecked") public GenWordPolynomial[] hegcd(GenWordPolynomial S) { GenWordPolynomial[] ret = new GenWordPolynomial[2]; ret[0] = null; ret[1] = null; if (S == null || S.isZERO()) { ret[0] = this; ret[1] = this.ring.getONE(); return ret; } if (this.isZERO()) { ret[0] = S; return ret; } if (ring.alphabet.length() != 1) { throw new IllegalArgumentException("no univariate polynomial " + ring); } GenWordPolynomial[] qr; GenWordPolynomial q = this; GenWordPolynomial r = S; GenWordPolynomial c1 = ring.getONE().copy(); GenWordPolynomial d1 = ring.getZERO().copy(); GenWordPolynomial x1; while (!r.isZERO()) { qr = q.quotientRemainder(r); q = qr[0]; x1 = c1.subtract(q.multiply(d1)); c1 = d1; d1 = x1; q = r; r = qr[1]; } // normalize ldcf(q) to 1, i.e. make monic C g = q.leadingBaseCoefficient(); if (g.isUnit()) { C h = g.inverse(); q = q.multiply(h); c1 = c1.multiply(h); } //assert ( ((c1.multiply(this)).remainder(S).equals(q) )); ret[0] = q; ret[1] = c1; return ret; } /** * GenWordPolynomial inverse. Required by RingElem. Throws not invertible * exception. */ public GenWordPolynomial inverse() { if (isUnit()) { // only possible if ldbcf is unit C c = leadingBaseCoefficient().inverse(); return ring.getONE().multiply(c); } throw new NotInvertibleException("element not invertible " + this + " :: " + ring); } /** * GenWordPolynomial modular inverse. Only for univariate polynomials over * fields. * @param m GenWordPolynomial. * @return a with with a*this = 1 mod m. */ public GenWordPolynomial modInverse(GenWordPolynomial m) { if (this.isZERO()) { throw new NotInvertibleException("zero is not invertible"); } GenWordPolynomial[] hegcd = this.hegcd(m); GenWordPolynomial a = hegcd[0]; if (!a.isUnit()) { // gcd != 1 throw new NotInvertibleException("element not invertible, gcd != 1"); } GenWordPolynomial b = hegcd[1]; if (b.isZERO()) { // when m divides this, e.g. m.isUnit() throw new NotInvertibleException("element not invertible, divisible by modul"); } return b; } /** * Iterator over coefficients. * @return val.values().iterator(). */ public Iterator coefficientIterator() { return val.values().iterator(); } /** * Iterator over words. * @return val.keySet().iterator(). */ public Iterator wordIterator() { return val.keySet().iterator(); } /** * Iterator over monomials. * @return a PolyIterator. */ public Iterator> iterator() { return new WordPolyIterator(val); } /** * Map a unary function to the coefficients. * @param f evaluation functor. * @return new polynomial with coefficients f(this(e)). */ public GenWordPolynomial map(final UnaryFunctor f) { GenWordPolynomial n = ring.getZERO().copy(); SortedMap nv = n.val; for (WordMonomial m : this) { //logger.info("m = " + m); C c = f.eval(m.c); if (c != null && !c.isZERO()) { nv.put(m.e, c); } } return n; } } jas-2.5/src/edu/jas/poly/LocalRing.java0000644000175000017500000001526211461027376020201 0ustar giovannigiovanni/* * $Id: LocalRing.java 3367 2010-10-24 13:05:02Z kredel $ */ package edu.jas.poly; import java.util.Random; import java.io.Reader; import java.util.List; import java.util.ArrayList; import org.apache.log4j.Logger; import edu.jas.structure.ElemFactory; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Local ring factory based on RingElem principal ideal. * Objects of this class are immutable. * @author Heinz Kredel */ public class LocalRing > implements RingFactory< Local > { private static final Logger logger = Logger.getLogger(LocalRing.class); //private boolean debug = logger.isDebugEnabled(); /** Ideal generator for localization. */ protected final C ideal; /** Ring factory. */ protected final RingFactory ring; /** Indicator if this ring is a field. */ protected int isField = -1; // initially unknown /** The constructor creates a LocalRing object * from a RingFactory and a RingElem. * @param i localization ideal generator. */ public LocalRing(RingFactory r, C i) { ring = r; if ( i == null ) { throw new IllegalArgumentException("ideal may not be null"); } ideal = i; if ( ideal.isONE() ) { throw new IllegalArgumentException("ideal may not be 1"); } } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return ring.isFinite(); } /** Copy Local element c. * @param c * @return a copy of c. */ public Local copy(Local c) { return new Local( c.ring, c.num, c.den, true ); } /** Get the zero element. * @return 0 as Local. */ public Local getZERO() { return new Local( this, ring.getZERO() ); } /** Get the one element. * @return 1 as Local. */ public Local getONE() { return new Local( this, ring.getONE() ); } /** Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List rgens = ring.generators(); List> gens = new ArrayList>( rgens.size()-1 ); for ( C c: rgens ) { if ( !c.isONE() ) { gens.add( new Local(this,c) ); } } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return ring.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return ring.isAssociative(); } /** * Query if this ring is a field. * @return false. */ public boolean isField() { if ( isField > 0 ) { return true; } if ( isField == 0 ) { return false; } // ?? return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return ring.characteristic(); } /** Get a Local element from a BigInteger value. * @param a BigInteger. * @return a Local. */ public Local fromInteger(java.math.BigInteger a) { return new Local( this, ring.fromInteger(a) ); } /** Get a Local element from a long value. * @param a long. * @return a Local. */ public Local fromInteger(long a) { return new Local( this, ring.fromInteger(a) ); } /** Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { return "Local[ " + ideal.toString() + " ]"; } /** Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "LocalRing(" + ideal.toScript() + ")"; } /** Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object b) { if ( ! ( b instanceof LocalRing ) ) { return false; } LocalRing a = null; try { a = (LocalRing) b; } catch (ClassCastException e) { } if ( a == null ) { return false; } if ( ! ring.equals( a.ring ) ) { return false; } return ideal.equals( a.ideal ); } /** Hash code for this local ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + ideal.hashCode(); return h; } /** Local random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random residue element. */ public Local random(int n) { C r = ring.random( n ); C s = ring.random( n ); s = s.remainder( ideal ); while ( s.isZERO() ) { logger.debug("zero was in ideal"); s = ring.random( n ); s = s.remainder( ideal ); } return new Local( this, r, s, false ); } /** Local random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random residue element. */ public Local random(int n, Random rnd) { C r = ring.random( n, rnd ); C s = ring.random( n, rnd ); s = s.remainder( ideal ); while ( s.isZERO() ) { logger.debug("zero was in ideal"); s = ring.random( n, rnd ); s = s.remainder( ideal ); } return new Local( this, r, s, false ); } /** Parse Local from String. * @param s String. * @return Local from s. */ public Local parse(String s) { C x = ring.parse( s ); return new Local( this, x ); } /** Parse Local from Reader. * @param r Reader. * @return next Local from r. */ public Local parse(Reader r) { C x = ring.parse( r ); return new Local( this, x ); } } jas-2.5/src/edu/jas/poly/WordPolyIterator.java0000644000175000017500000000244312020707200021574 0ustar giovannigiovanni /* * $Id: WordPolyIterator.java 4155 2012-09-02 16:51:12Z kredel $ */ package edu.jas.poly; import java.util.Map; import java.util.SortedMap; import java.util.Iterator; import edu.jas.structure.RingElem; import edu.jas.poly.Word; /** * Iterator over monomials of a polynomial. * Adaptor for val.entrySet().iterator(). * @author Heinz Kredel */ public class WordPolyIterator > implements Iterator< WordMonomial > { /** * Internal iterator over polynomial map. */ protected final Iterator< Map.Entry > ms; /** * Constructor of polynomial iterator. * @param m SortetMap of a polynomial. */ public WordPolyIterator( SortedMap m ) { ms = m.entrySet().iterator(); } /** * Test for availability of a next monomial. * @return true if the iteration has more monomials, else false. */ public boolean hasNext() { return ms.hasNext(); } /** * Get next monomial element. * @return next monomial. */ public WordMonomial next() { return new WordMonomial( ms.next() ); } /** * Remove the last monomial returned from underlying set if allowed. */ public void remove() { ms.remove(); } } jas-2.5/src/edu/jas/poly/InvalidExpressionException.java0000644000175000017500000000127711536654532023660 0ustar giovannigiovanni/* * $Id: InvalidExpressionException.java 3560 2011-03-12 11:30:34Z kredel $ */ package edu.jas.poly; /** * Invalid expression exception class. * Runtime Exception to be thrown for invalid algebraic / polynomial expressions. * @author Heinz Kredel */ public class InvalidExpressionException extends RuntimeException { public InvalidExpressionException() { super("InvalidExpressionException"); } public InvalidExpressionException(String c) { super(c); } public InvalidExpressionException(String c, Throwable t) { super(c, t); } public InvalidExpressionException(Throwable t) { super("InvalidExpressionException", t); } } jas-2.5/src/edu/jas/poly/QuotientRing.java0000644000175000017500000001375111461026666020761 0ustar giovannigiovanni/* * $Id: QuotientRing.java 3365 2010-10-24 12:59:34Z kredel $ */ package edu.jas.poly; import java.util.Random; import java.util.List; import java.util.ArrayList; import java.io.Reader; import org.apache.log4j.Logger; import edu.jas.structure.ElemFactory; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; //import edu.jas.structure.GcdRingElem; /** * Quotient ring factory using RingElem and RingFactory. * Objects of this class are immutable. * @author Heinz Kredel */ public class QuotientRing > implements RingFactory< Quotient > { private static final Logger logger = Logger.getLogger(QuotientRing.class); private boolean debug = logger.isDebugEnabled(); /** Ring factory of this factory. */ public final RingFactory< C > ring; /** The constructor creates a QuotientRing object * from a RingFactory. * @param r ring factory. */ public QuotientRing(RingFactory r) { ring = r; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return ring.isFinite(); } /** Copy Quotient element c. * @param c * @return a copy of c. */ public Quotient copy(Quotient c) { return new Quotient( c.ring, c.num, c.den, true ); } /** Get the zero element. * @return 0 as Quotient. */ public Quotient getZERO() { return new Quotient( this, ring.getZERO() ); } /** Get the one element. * @return 1 as Quotient. */ public Quotient getONE() { return new Quotient( this, ring.getONE() ); } /** Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List rgens = ring.generators(); List> gens = new ArrayList>( rgens.size() ); for ( C c: rgens ) { gens.add( new Quotient(this,c) ); } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return ring.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return ring.isAssociative(); } /** * Query if this ring is a field. * @return true. */ public boolean isField() { return true; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return ring.characteristic(); } /** Get a Quotient element from a BigInteger value. * @param a BigInteger. * @return a Quotient. */ public Quotient fromInteger(java.math.BigInteger a) { return new Quotient( this, ring.fromInteger(a) ); } /** Get a Quotient element from a long value. * @param a long. * @return a Quotient. */ public Quotient fromInteger(long a) { return new Quotient( this, ring.fromInteger(a) ); } /** Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { return "Quotient[ " + ring.toString() + " ]"; } /** Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "QuotientRing(" + ring.toScript() + ")"; } /** Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object b) { if ( ! ( b instanceof QuotientRing ) ) { return false; } QuotientRing a = null; try { a = (QuotientRing) b; } catch (ClassCastException e) { } if ( a == null ) { return false; } return ring.equals( a.ring ); } /** Hash code for this quotient ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); return h; } /** Quotient random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random residue element. */ public Quotient random(int n) { C r = ring.random( n ); C s = ring.random( n ); while ( s.isZERO() ) { s = ring.random( n ); } return new Quotient( this, r, s, false ); } /** Quotient random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random residue element. */ public Quotient random(int n, Random rnd) { C r = ring.random( n, rnd ); C s = ring.random( n, rnd ); while ( s.isZERO() ) { s = ring.random( n, rnd ); } return new Quotient( this, r, s, false); } /** Parse Quotient from String. * @param s String. * @return Quotient from s. */ public Quotient parse(String s) { C x = ring.parse( s ); return new Quotient( this, x ); } /** Parse Quotient from Reader. * @param r Reader. * @return next Quotient from r. */ public Quotient parse(Reader r) { C x = ring.parse( r ); if ( debug ) { logger.debug("x = " + x); } return new Quotient( this, x ); } } jas-2.5/src/edu/jas/poly/ExpVector.java0000644000175000017500000007073412014234362020241 0ustar giovannigiovanni/* * $Id: ExpVector.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.poly; import java.util.Collection; import java.util.List; import java.util.Random; import edu.jas.structure.AbelianGroupElem; import edu.jas.structure.AbelianGroupFactory; import edu.jas.structure.Power; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * ExpVector implements exponent vectors for polynomials. Exponent vectors are * implemented as arrays of Java elementary types, like long, int, short and * byte. ExpVector provides also the familiar MAS static method names. The * implementation is only tested for nonnegative exponents but should work also * for negative exponents. Objects of this class are intended to be immutable, * but exponents can be set (during construction); also the hash code is only * computed once, when needed. The different storage unit implementations are * ExpVectorLong ExpVectorInteger, * ExpVectorShort and ExpVectorByte. The static * factory methods create() of ExpVector select the * respective storage unit. The selection of the desired storage unit is * internally done via the static variable storunit. This varaible * should not be changed dynamically. * @author Heinz Kredel */ public abstract class ExpVector implements AbelianGroupElem /*Cloneable, Serializable*/{ /** * Stored hash code. */ protected int hash = 0; /** * Random number generator. */ private final static Random random = new Random(); /** * Storage representation of exponent arrays. */ public static enum StorUnit { LONG, INT, SHORT, BYTE }; /** * Used storage representation of exponent arrays. Note: Set this * only statically and not dynamically. */ public final static StorUnit storunit = StorUnit.LONG; /** * Constructor for ExpVector. */ public ExpVector() { hash = 0; } /** * Factory constructor for ExpVector. * @param n length of exponent vector. */ public static ExpVector create(int n) { switch (storunit) { case INT: return new ExpVectorInteger(n); case LONG: return new ExpVectorLong(n); case SHORT: return new ExpVectorShort(n); case BYTE: return new ExpVectorByte(n); default: return new ExpVectorInteger(n); } } /** * Factory constructor for ExpVector. Sets exponent i to e. * @param n length of exponent vector. * @param i index of exponent to be set. * @param e exponent to be set. */ public static ExpVector create(int n, int i, long e) { switch (storunit) { case INT: return new ExpVectorInteger(n, i, e); case LONG: return new ExpVectorLong(n, i, e); case SHORT: return new ExpVectorShort(n, i, e); case BYTE: return new ExpVectorByte(n, i, e); default: return new ExpVectorInteger(n, i, e); } } /** * Internal factory constructor for ExpVector. Sets val. * @param v internal representation array. */ public static ExpVector create(long[] v) { switch (storunit) { case INT: return new ExpVectorInteger(v); case LONG: return new ExpVectorLong(v); case SHORT: return new ExpVectorShort(v); case BYTE: return new ExpVectorByte(v); default: return new ExpVectorInteger(v); } } /** * Factory constructor for ExpVector. Converts a String representation to an * ExpVector. Accepted format = (1,2,3,4,5,6,7). * @param s String representation. */ public static ExpVector create(String s) { switch (storunit) { case INT: return new ExpVectorInteger(s); case LONG: return new ExpVectorLong(s); case SHORT: return new ExpVectorShort(s); case BYTE: return new ExpVectorByte(s); default: return new ExpVectorInteger(s); } } /** * Factory constructor for ExpVector. Sets val. * @param v collection of exponents. */ public static ExpVector create(Collection v) { long[] w = new long[v.size()]; int i = 0; for (Long k : v) { w[i++] = k; } return create(w); } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public AbelianGroupFactory factory() { throw new UnsupportedOperationException("no factory implemented for ExpVector"); } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() Note: returns true * because of finite set of values in each index. */ public boolean isFinite() { return true; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public abstract ExpVector copy(); /** * Get the exponent vector. * @return val. */ /*package*/abstract long[] getVal(); /** * Get the exponent at position i. * @param i position. * @return val[i]. */ public abstract long getVal(int i); /** * Set the exponent at position i to e. * @param i * @param e * @return old val[i]. */ protected abstract long setVal(int i, long e); /** * Get the length of this exponent vector. * @return val.length. */ public abstract int length(); /** * Extend variables. Used e.g. in module embedding. Extend this by i * elements and set val[j] to e. * @param i number of elements to extend. * @param j index of element to be set. * @param e new exponent for val[j]. * @return extended exponent vector. */ public abstract ExpVector extend(int i, int j, long e); /** * Extend lower variables. Extend this by i lower elements and set val[j] to * e. * @param i number of elements to extend. * @param j index of element to be set. * @param e new exponent for val[j]. * @return extended exponent vector. */ public abstract ExpVector extendLower(int i, int j, long e); /** * Contract variables. Used e.g. in module embedding. Contract this to len * elements. * @param i position of first element to be copied. * @param len new length. * @return contracted exponent vector. */ public abstract ExpVector contract(int i, int len); /** * Reverse variables. Used e.g. in opposite rings. * @return reversed exponent vector. */ public abstract ExpVector reverse(); /** * Reverse j variables. Used e.g. in opposite rings. Reverses the first j-1 * variables, the rest is unchanged. * @param j index of first variable not reversed. * @return reversed exponent vector. */ public abstract ExpVector reverse(int j); /** * Combine with ExpVector. Combine this with the other ExpVector V. * @param V the other exponent vector. * @return combined exponent vector. */ public abstract ExpVector combine(ExpVector V); /** * Get the string representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer("("); for (int i = 0; i < length(); i++) { s.append(getVal(i)); if (i < length() - 1) { s.append(","); } } s.append(")"); return s.toString(); } /** * Get the string representation with variable names. * @param vars names of variables. * @see java.lang.Object#toString() */ public String toString(String[] vars) { StringBuffer s = new StringBuffer(); boolean pit; int r = length(); if (r != vars.length) { //logger.warn("length mismatch " + r + " <> " + vars.length); return toString(); } if (r == 0) { return s.toString(); } long vi; for (int i = r - 1; i > 0; i--) { vi = getVal(i); if (vi != 0) { s.append(vars[r - 1 - i]); if (vi != 1) { s.append("^" + vi); } pit = false; for (int j = i - 1; j >= 0; j--) { if (getVal(j) != 0) { pit = true; } } if (pit) { s.append(" * "); } } } vi = getVal(0); if (vi != 0) { s.append(vars[r - 1]); if (vi != 1) { s.append("^" + vi); } } return s.toString(); } /** * Get the string representation of the variables. * @param vars names of variables. * @return string representation of the variables. * @see java.util.Arrays#toString() */ public static String varsToString(String[] vars) { if (vars == null) { return "null"; } StringBuffer s = new StringBuffer(); for (int i = 0; i < vars.length; i++) { s.append(vars[i]); if (i < vars.length - 1) { s.append(","); } } return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { return toScript(stdVars()); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ // @Override public String toScript(String[] vars) { // Python case int r = length(); if (r != vars.length) { return toString(); } StringBuffer s = new StringBuffer(); boolean pit; long vi; for (int i = r - 1; i > 0; i--) { vi = getVal(i); if (vi != 0) { s.append(vars[r - 1 - i]); if (vi != 1) { s.append("**" + vi); } pit = false; for (int j = i - 1; j >= 0; j--) { if (getVal(j) != 0) { pit = true; } } if (pit) { s.append(" * "); } } } vi = getVal(0); if (vi != 0) { s.append(vars[r - 1]); if (vi != 1) { s.append("**" + vi); } } return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return "ExpVector()"; } /** * Get the variable name at index. * @param idx index of the variable * @param vars array of names of variables * @return name of variable at the given index. */ public String indexVarName(int idx, String... vars) { return vars[length() - idx - 1]; } /** * Get the array index of a variable at index. * @param idx index of the variable * @return array index of the variable. */ public int varIndex(int idx) { return length() - idx - 1; } /** * Get the index of a variable. * @param x variable name to be searched. * @param vars array of names of variables * @return index of x in vars. */ public int indexVar(String x, String... vars) { for (int i = 0; i < length(); i++) { if (x.equals(vars[i])) { return length() - i - 1; } } return -1; // not found } /** * Evaluate. * @param cf ring factory for elements of a. * @param a list of values. * @return a_1^{e_1} * ... * a_n^{e_n}. */ public > C evaluate(RingFactory cf, List a) { C c = cf.getONE(); for (int i = 0; i < length(); i++) { long ei = getVal(i); if (ei == 0L) { continue; } C ai = a.get(length() - 1 - i); if (ai.isZERO()) { return ai; } C pi = Power. positivePower(ai, ei); c = c.multiply(pi); } return c; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof ExpVector)) { return false; } ExpVector b = (ExpVector) B; int t = this.invLexCompareTo(b); //System.out.println("equals: this = " + this + " B = " + B + " t = " + t); return (0 == t); } /** * hashCode. Optimized for small exponents, i.e. ≤ 24 and * small number of variables, i.e. ≤ 8. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { if (hash == 0) { for (int i = 0; i < length(); i++) { hash = hash << 4 + getVal(i); } if (hash == 0) { hash = 1; } } return hash; } /** * Is ExpVector zero. * @return If this has all elements 0 then true is returned, else false. */ public boolean isZERO() { return (0 == this.signum()); } /** * Standard variable names. Generate standard names for variables, i.e. x0 * to x(n-1). * @return standard names. */ public String[] stdVars() { return STDVARS("x", length()); } /** * Generate variable names. Generate names for variables, i.e. prefix0 to * prefix(n-1). * @param prefix name prefix. * @return standard names. */ public String[] stdVars(String prefix) { return STDVARS(prefix, length()); } /** * Standard variable names. Generate standard names for variables, i.e. x0 * to x(n-1). * @param n size of names array * @return standard names. */ public static String[] STDVARS(int n) { return STDVARS("x", n); } /** * Generate variable names. Generate names for variables from given prefix. * i.e. prefix0 to prefix(n-1). * @param n size of names array. * @param prefix name prefix. * @return vatiable names. */ public static String[] STDVARS(String prefix, int n) { String[] vars = new String[n]; if (prefix == null || prefix.length() == 0) { prefix = "x"; } for (int i = 0; i < n; i++) { vars[i] = prefix + i; //(n-1-i); } return vars; } /** * ExpVector absolute value. * @param U * @return abs(U). */ public static ExpVector EVABS(ExpVector U) { return U.abs(); } /** * ExpVector absolute value. * @return abs(this). */ public abstract ExpVector abs(); /** * ExpVector negate. * @param U * @return -U. */ public static ExpVector EVNEG(ExpVector U) { return U.negate(); } /** * ExpVector negate. * @return -this. */ public abstract ExpVector negate(); /** * ExpVector summation. * @param U * @param V * @return U+V. */ public static ExpVector EVSUM(ExpVector U, ExpVector V) { return U.sum(V); } /** * ExpVector summation. * @param V * @return this+V. */ public abstract ExpVector sum(ExpVector V); /** * ExpVector difference. Result may have negative entries. * @param U * @param V * @return U-V. */ public static ExpVector EVDIF(ExpVector U, ExpVector V) { return U.subtract(V); } /** * ExpVector subtract. Result may have negative entries. * @param V * @return this-V. */ public abstract ExpVector subtract(ExpVector V); /** * ExpVector substitution. Clone and set exponent to d at position i. * @param U * @param i position. * @param d new exponent. * @return substituted ExpVector. */ public static ExpVector EVSU(ExpVector U, int i, long d) { return U.subst(i, d); } /** * ExpVector substitution. Clone and set exponent to d at position i. * @param i position. * @param d new exponent. * @return substituted ExpVector. */ public ExpVector subst(int i, long d) { ExpVector V = this.copy(); @SuppressWarnings("unused") long e = V.setVal(i, d); return V; //return EVSU(this, i, d); } /** * Generate a random ExpVector. * @param r length of new ExpVector. * @param k maximal degree in each exponent. * @param q density of nozero exponents. * @return random ExpVector. */ public static ExpVector EVRAND(int r, long k, float q) { return EVRAND(r, k, q, random); } /** * Generate a random ExpVector. * @param r length of new ExpVector. * @param k maximal degree in each exponent. * @param q density of nozero exponents. * @param rnd is a source for random bits. * @return random ExpVector. */ public static ExpVector EVRAND(int r, long k, float q, Random rnd) { long[] w = new long[r]; long e; float f; for (int i = 0; i < w.length; i++) { f = rnd.nextFloat(); if (f > q) { e = 0; } else { e = rnd.nextLong() % k; if (e < 0) { e = -e; } } w[i] = e; } return create(w); //return new ExpVector( w ); } /** * Generate a random ExpVector. * @param r length of new ExpVector. * @param k maximal degree in each exponent. * @param q density of nozero exponents. * @return random ExpVector. */ public static ExpVector random(int r, long k, float q) { return EVRAND(r, k, q, random); } /** * Generate a random ExpVector. * @param r length of new ExpVector. * @param k maximal degree in each exponent. * @param q density of nozero exponents. * @param rnd is a source for random bits. * @return random ExpVector. */ public static ExpVector random(int r, long k, float q, Random rnd) { return EVRAND(r, k, q, rnd); } /** * ExpVector sign. * @param U * @return 0 if U is zero, -1 if some entry is negative, 1 if no entry is * negativ and at least one entry is positive. */ public static int EVSIGN(ExpVector U) { return U.signum(); } /** * ExpVector signum. * @return 0 if this is zero, -1 if some entry is negative, 1 if no entry is * negative and at least one entry is positive. */ public abstract int signum(); /** * ExpVector total degree. * @param U * @return sum of all exponents. */ public static long EVTDEG(ExpVector U) { return U.totalDeg(); } /** * ExpVector degree. * @return total degree of all exponents. */ public long degree() { return totalDeg(); } /** * ExpVector total degree. * @return sum of all exponents. */ public abstract long totalDeg(); /** * ExpVector maximal degree. * @param U * @return maximal exponent. */ public static long EVMDEG(ExpVector U) { return U.maxDeg(); } /** * ExpVector maximal degree. * @return maximal exponent. */ public abstract long maxDeg(); /** * ExpVector weighted degree. * @param w weights. * @param U * @return weighted sum of all exponents. */ public static long EVWDEG(long[][] w, ExpVector U) { return U.weightDeg(w); } /** * ExpVector weighted degree. * @param w weights. * @return weighted sum of all exponents. */ public abstract long weightDeg(long[][] w); /** * ExpVector least common multiple. * @param U * @param V * @return component wise maximum of U and V. */ public static ExpVector EVLCM(ExpVector U, ExpVector V) { return U.lcm(V); } /** * ExpVector least common multiple. * @param V * @return component wise maximum of this and V. */ public abstract ExpVector lcm(ExpVector V); /** * ExpVector greatest common divisor. * @param U * @param V * @return component wise minimum of U and V. */ public static ExpVector EVGCD(ExpVector U, ExpVector V) { return U.gcd(V); } /** * ExpVector greatest common divisor. * @param V * @return component wise minimum of this and V. */ public abstract ExpVector gcd(ExpVector V); /** * ExpVector dependency on variables. * @param U * @return array of indices where U has positive exponents. */ public static int[] EVDOV(ExpVector U) { return U.dependencyOnVariables(); } /** * ExpVector dependency on variables. * @return array of indices where val has positive exponents. */ public abstract int[] dependencyOnVariables(); /** * ExpVector multiple test. Test if U is component wise greater or equal to * V. * @param U * @param V * @return true if U is a multiple of V, else false. */ public static boolean EVMT(ExpVector U, ExpVector V) { return U.multipleOf(V); } /** * ExpVector multiple test. Test if this is component wise greater or equal * to V. * @param V * @return true if this is a multiple of V, else false. */ public abstract boolean multipleOf(ExpVector V); /** * ExpVector divides test. Test if V is component wise greater or equal to * this. * @param V * @return true if this divides V, else false. */ public boolean divides(ExpVector V) { return V.multipleOf(this); //return EVMT(V, this); } /** * ExpVector compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ //JAVA6only: @Override public int compareTo(ExpVector V) { return this.invLexCompareTo(V); } /** * Inverse lexicographical compare. * @param U * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVILCP(ExpVector U, ExpVector V) { return U.invLexCompareTo(V); } /** * ExpVector inverse lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public abstract int invLexCompareTo(ExpVector V); /** * Inverse lexicographical compare part. Compare entries between begin and * end (-1). * @param U * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVILCP(ExpVector U, ExpVector V, int begin, int end) { return U.invLexCompareTo(V, begin, end); } /** * ExpVector inverse lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public abstract int invLexCompareTo(ExpVector V, int begin, int end); /** * Inverse graded lexicographical compare. * @param U * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVIGLC(ExpVector U, ExpVector V) { return U.invGradCompareTo(V); } /** * ExpVector inverse graded lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public abstract int invGradCompareTo(ExpVector V); /** * Inverse graded lexicographical compare part. Compare entries between * begin and end (-1). * @param U * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVIGLC(ExpVector U, ExpVector V, int begin, int end) { return U.invGradCompareTo(V, begin, end); } /** * ExpVector inverse graded lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public abstract int invGradCompareTo(ExpVector V, int begin, int end); /** * Reverse inverse lexicographical compare. * @param U * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVRILCP(ExpVector U, ExpVector V) { return U.revInvLexCompareTo(V); } /** * ExpVector reverse inverse lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public abstract int revInvLexCompareTo(ExpVector V); /** * Reverse inverse lexicographical compare part. Compare entries between * begin and end (-1). * @param U * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVRILCP(ExpVector U, ExpVector V, int begin, int end) { return U.revInvLexCompareTo(V, begin, end); } /** * ExpVector reverse inverse lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public abstract int revInvLexCompareTo(ExpVector V, int begin, int end); /** * Reverse inverse graded lexicographical compare. * @param U * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVRIGLC(ExpVector U, ExpVector V) { return U.revInvGradCompareTo(V); } /** * ExpVector reverse inverse graded compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public abstract int revInvGradCompareTo(ExpVector V); /** * Reverse inverse graded lexicographical compare part. Compare entries * between begin and end (-1). * @param U * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVRIGLC(ExpVector U, ExpVector V, int begin, int end) { return U.revInvGradCompareTo(V, begin, end); } /** * ExpVector reverse inverse graded compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public abstract int revInvGradCompareTo(ExpVector V, int begin, int end); /** * Inverse weighted lexicographical compare. * @param w weight array. * @param U * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVIWLC(long[][] w, ExpVector U, ExpVector V) { return U.invWeightCompareTo(w, V); } /** * ExpVector inverse weighted lexicographical compareTo. * @param w weight array. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public abstract int invWeightCompareTo(long[][] w, ExpVector V); /** * Inverse weighted lexicographical compare part. Compare entries between * begin and end (-1). * @param w weight array. * @param U * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public static int EVIWLC(long[][] w, ExpVector U, ExpVector V, int begin, int end) { return U.invWeightCompareTo(w, V, begin, end); } /** * ExpVector inverse weighted lexicographical compareTo. * @param w weight array. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ public abstract int invWeightCompareTo(long[][] w, ExpVector V, int begin, int end); } jas-2.5/src/edu/jas/poly/GenWordPolynomialRing.java0000644000175000017500000003562312031654714022557 0ustar giovannigiovanni/* * $Id: GenWordPolynomialRing.java 4225 2012-09-29 20:27:56Z kredel $ */ package edu.jas.poly; import java.io.Reader; import java.io.StringReader; import java.math.BigInteger; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.PreemptStatus; import edu.jas.kern.Scripting; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * GenWordPolynomialRing generic polynomial factory implementing RingFactory; * Factory for non-commutative string polynomials over C. * @param coefficient type * @author Heinz Kredel */ public final class GenWordPolynomialRing> implements RingFactory> /*, Iterable>*/{ /** * The factory for the coefficients. */ public final RingFactory coFac; /** * The factory for the alphabet. */ public final WordFactory alphabet; /** * The constant polynomial 0 for this ring. */ public final GenWordPolynomial ZERO; /** * The constant polynomial 1 for this ring. */ public final GenWordPolynomial ONE; /** * The constant empty word exponent for this ring. */ public final Word wone; /** * A default random sequence generator. */ final static Random random = new Random(); /** * Indicator if this ring is a field. */ private int isField = -1; // initially unknown /** * Log4j logger object. */ private static final Logger logger = Logger.getLogger(GenWordPolynomialRing.class); /** * Flag to enable if preemptive interrrupt is checked. */ final boolean checkPreempt = PreemptStatus.isAllowed(); /** * The constructor creates a polynomial factory object with the default term * order. * @param cf factory for coefficients of type C. * @param wf factory for strings. */ public GenWordPolynomialRing(RingFactory cf, WordFactory wf) { coFac = cf; alphabet = wf; ZERO = new GenWordPolynomial(this); C coeff = coFac.getONE(); wone = wf.getONE(); ONE = new GenWordPolynomial(this, coeff, wone); } /** * The constructor creates a polynomial factory object. * @param cf factory for coefficients of type C. * @param o other polynomial ring. */ public GenWordPolynomialRing(RingFactory cf, GenWordPolynomialRing o) { this(cf, o.alphabet); } /** * The constructor creates a polynomial factory object. * @param fac polynomial ring. */ public GenWordPolynomialRing(GenPolynomialRing fac) { this(fac.coFac, new WordFactory(fac.vars)); } /** * Copy this factory. * @return a clone of this. */ public GenWordPolynomialRing copy() { return new GenWordPolynomialRing(coFac, this); } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer(); s.append("WordPolyRing("); if (coFac instanceof RingElem) { s.append(((RingElem) coFac).toScriptFactory()); } else { s.append(coFac.toString().trim()); } s.append(","); s.append(alphabet.toString()); s.append(")"); return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { StringBuffer s = new StringBuffer(); switch (Scripting.getLang()) { case Ruby: s.append("WordPolyRing.new("); break; case Python: default: s.append("WordPolyRing("); } if (coFac instanceof RingElem) { s.append(((RingElem) coFac).toScriptFactory()); } else { s.append(coFac.toScript().trim()); } s.append(","); s.append(alphabet.toScript()); s.append(")"); return s.toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object other) { if (!(other instanceof GenWordPolynomialRing)) { return false; } GenWordPolynomialRing oring = null; try { oring = (GenWordPolynomialRing) other; } catch (ClassCastException ignored) { } if (oring == null) { return false; } if (!coFac.equals(oring.coFac)) { return false; } if (!alphabet.equals(oring.alphabet)) { return false; } return true; } /** * Hash code for this polynomial ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = (coFac.hashCode() << 11); h += alphabet.hashCode(); return h; } /** * Get the variable names. * @return vars. */ public String getVars() { return alphabet.getVal(); // Java-5: Arrays.copyOf(vars,vars.length); } /** * Get the zero element from the coefficients. * @return 0 as C. */ public C getZEROCoefficient() { return coFac.getZERO(); } /** * Get the one element from the coefficients. * @return 1 as C. */ public C getONECoefficient() { return coFac.getONE(); } /** * Get the zero element. * @return 0 as GenWordPolynomial. */ public GenWordPolynomial getZERO() { return ZERO; } /** * Get the one element. * @return 1 as GenWordPolynomial. */ public GenWordPolynomial getONE() { return ONE; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return coFac.isCommutative() && alphabet.isFinite(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return coFac.isAssociative(); } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return alphabet.isFinite() && coFac.isFinite(); } /** * Query if this ring is a field. * @return false. */ public boolean isField() { if (isField > 0) { return true; } if (isField == 0) { return false; } if (coFac.isField() && alphabet.isFinite()) { isField = 1; return true; } isField = 0; return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return coFac.characteristic(); } /** * Get a (constant) GenWordPolynomial<C> element from a coefficient * value. * @param a coefficient. * @return a GenWordPolynomial<C>. */ public GenWordPolynomial valueOf(C a) { return new GenWordPolynomial(this, a); } /** * Get a GenWordPolynomial<C> element from a word. * @param e word. * @return a GenWordPolynomial<C>. */ public GenWordPolynomial valueOf(Word e) { return new GenWordPolynomial(this, coFac.getONE(), e); } /** * Get a GenWordPolynomial<C> element from a coeffcient and a word. * @param a coefficient. * @param e word. * @return a GenWordPolynomial<C>. */ public GenWordPolynomial valueOf(C a, Word e) { return new GenWordPolynomial(this, a, e); } /** * Get a GenWordPolynomial<C> element from a GenPolynomial<C>. * @param a GenPolynomial. * @return a GenWordPolynomial<C>. */ public GenWordPolynomial valueOf(GenPolynomial a) { if ( a.isZERO() ) { return getZERO(); } if ( a.isONE() ) { return getONE(); } GenWordPolynomial p = this.getZERO().copy(); for (Map.Entry m : a.val.entrySet()) { C c = m.getValue(); ExpVector e = m.getKey(); Word w = alphabet.valueOf(e); p.doPutToMap(w,c); } return p; } /** * Get a list of GenWordPolynomial<C> element from a list of GenPolynomial<C>. * @param A GenPolynomial list. * @return a GenWordPolynomial<C> list. */ public List> valueOf(List> A) { List> B = new ArrayList>(A.size()); if ( A.isEmpty() ) { return B; } for (GenPolynomial a : A) { GenWordPolynomial b = valueOf(a); B.add(b); } return B; } /** * Get a (constant) GenWordPolynomial<C> element from a long value. * @param a long. * @return a GenWordPolynomial<C>. */ public GenWordPolynomial fromInteger(long a) { return new GenWordPolynomial(this, coFac.fromInteger(a), wone); } /** * Get a (constant) GenWordPolynomial<C> element from a BigInteger * value. * @param a BigInteger. * @return a GenWordPolynomial<C>. */ public GenWordPolynomial fromInteger(BigInteger a) { return new GenWordPolynomial(this, coFac.fromInteger(a), wone); } /** * Random polynomial. Generates a random polynomial. * @param n number of terms. * @return a random polynomial. */ public GenWordPolynomial random(int n) { return random(n, random); } /** * Random polynomial. Generates a random polynomial with k = 5, l = n, d = 3. * @param n number of terms. * @param rnd is a source for random bits. * @return a random polynomial. */ public GenWordPolynomial random(int n, Random rnd) { return random(5, n, 3, rnd); } /** * Generate a random polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal length of a random word. * @return a random polynomial. */ public GenWordPolynomial random(int k, int l, int d) { return random(k, l, d, random); } /** * Generate a random polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal length of a random word. * @param rnd is a source for random bits. * @return a random polynomial. */ public GenWordPolynomial random(int k, int l, int d, Random rnd) { GenWordPolynomial r = getZERO(); //.clone() or copy( ZERO ); // add l random coeffs and words of maximal length d for (int i = 0; i < l; i++) { int di = Math.abs(rnd.nextInt() % d); Word e = alphabet.random(di, rnd); C a = coFac.random(k, rnd); r = r.sum(a, e); // somewhat inefficient but clean //System.out.println("e = " + e + " a = " + a); } return r; } /** * Copy polynomial c. * @param c polynomial to copy. * @return a copy of c. */ public GenWordPolynomial copy(GenWordPolynomial c) { return new GenWordPolynomial(this, c.val); } /** * Parse a polynomial with the use of GenWordPolynomialTokenizer. * @param s String. * @return GenWordPolynomial from s. */ public GenWordPolynomial parse(String s) { String val = s; if (!s.contains("|")) { val = val.replace("{", "").replace("}", ""); } return parse(new StringReader(val)); } /** * Parse a polynomial with the use of GenWordPolynomialTokenizer. * @param r Reader. * @return next GenWordPolynomial from r. */ @SuppressWarnings("unchecked") public GenWordPolynomial parse(Reader r) { logger.error("parse not implemented"); throw new UnsupportedOperationException("not implemented"); // GenWordPolynomialTokenizer pt = new GenWordPolynomialTokenizer(this, r); // GenWordPolynomial p = null; // try { // p = (GenWordPolynomial) pt.nextPolynomial(); // } catch (IOException e) { // logger.error(e.toString() + " parse " + this); // p = ZERO; // } // return p; } /** * Generate univariate polynomial in a given variable. * @param i the index of the variable. * @return X_i as univariate polynomial. */ public GenWordPolynomial univariate(int i) { GenWordPolynomial p = getZERO(); List wgen = alphabet.generators(); if (0 <= i && i < wgen.size()) { C one = coFac.getONE(); Word f = wgen.get(i); p = p.sum(one, f); } return p; } /** * Generate list of univariate polynomials in all variables. * @return List(X_1,...,X_n) a list of univariate polynomials. */ public List> univariateList() { int n = alphabet.length(); List> pols = new ArrayList>(n); for (int i = 0; i < n; i++) { GenWordPolynomial p = univariate(i); pols.add(p); } return pols; } /** * Get the generating elements excluding the generators for the coefficient * ring. * @return a list of generating elements for this ring. */ public List> getGenerators() { List> univs = univariateList(); List> gens = new ArrayList>(univs.size() + 1); gens.add(getONE()); gens.addAll(univs); return gens; } /** * Get a list of all generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List cogens = coFac.generators(); List> univs = univariateList(); List> gens = new ArrayList>(univs.size() + cogens.size()); for (C c : cogens) { gens.add(getONE().multiply(c)); } gens.addAll(univs); return gens; } } jas-2.5/src/edu/jas/poly/GenPolynomial.java0000644000175000017500000016217412137242156021105 0ustar giovannigiovanni/* * $Id: GenPolynomial.java 4391 2013-04-28 15:46:54Z kredel $ */ package edu.jas.poly; import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.kern.PreemptingException; import edu.jas.kern.PrettyPrint; import edu.jas.structure.NotInvertibleException; import edu.jas.structure.RingElem; import edu.jas.structure.UnaryFunctor; /** * GenPolynomial generic polynomials implementing RingElem. n-variate ordered * polynomials over C. Objects of this class are intended to be immutable. The * implementation is based on TreeMap respectively SortedMap from exponents to * coefficients. Only the coefficients are modeled with generic types, the * exponents are fixed to ExpVector with long entries (this will eventually be * changed in the future). C can also be a non integral domain, e.g. a * ModInteger, i.e. it may contain zero divisors, since multiply() does now * check for zeros. Note: multiply() now checks for wrong method dispatch * for GenSolvablePolynomial. * @param coefficient type * @author Heinz Kredel */ public class GenPolynomial> implements RingElem>, /* not yet Polynomial */ Iterable> { /** * The factory for the polynomial ring. */ public final GenPolynomialRing ring; /** * The data structure for polynomials. */ protected final SortedMap val; // do not change to TreeMap private static final Logger logger = Logger.getLogger(GenPolynomial.class); private final boolean debug = logger.isDebugEnabled(); // protected GenPolynomial() { ring = null; val = null; } // don't use /** * Private constructor for GenPolynomial. * @param r polynomial ring factory. * @param t TreeMap with correct ordering. */ private GenPolynomial(GenPolynomialRing r, TreeMap t) { ring = r; val = t; if (ring.checkPreempt) { if (Thread.currentThread().isInterrupted()) { logger.debug("throw PreemptingException"); throw new PreemptingException(); } } } /** * Constructor for zero GenPolynomial. * @param r polynomial ring factory. */ public GenPolynomial(GenPolynomialRing r) { this(r, new TreeMap(r.tord.getDescendComparator())); } /** * Constructor for GenPolynomial c * xe. * @param r polynomial ring factory. * @param c coefficient. * @param e exponent. */ public GenPolynomial(GenPolynomialRing r, C c, ExpVector e) { this(r); if (!c.isZERO()) { val.put(e, c); } } /** * Constructor for GenPolynomial c * x0. * @param r polynomial ring factory. * @param c coefficient. */ public GenPolynomial(GenPolynomialRing r, C c) { this(r, c, r.evzero); } /** * Constructor for GenPolynomial xe. * @param r polynomial ring factory. * @param e exponent. */ public GenPolynomial(GenPolynomialRing r, ExpVector e) { this(r, r.coFac.getONE(), e); } /** * Constructor for GenPolynomial. * @param r polynomial ring factory. * @param v the SortedMap of some other polynomial. */ protected GenPolynomial(GenPolynomialRing r, SortedMap v) { this(r); val.putAll(v); // assume no zero coefficients } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public GenPolynomialRing factory() { return ring; } /** * Copy this GenPolynomial. * @return copy of this. */ public GenPolynomial copy() { return new GenPolynomial(ring, this.val); } /** * Length of GenPolynomial. * @return number of coefficients of this GenPolynomial. */ public int length() { return val.size(); } /** * ExpVector to coefficient map of GenPolynomial. * @return val as unmodifiable SortedMap. */ public SortedMap getMap() { // return val; return Collections. unmodifiableSortedMap(val); } /** * Put an ExpVector to coefficient entry into the internal map of this * GenPolynomial. Note: Do not use this method unless you are * constructing a new polynomial. this is modified and breaks the * immutability promise of this class. * @param c coefficient. * @param e exponent. */ public void doPutToMap(ExpVector e, C c) { if (debug) { C a = val.get(e); if (a != null) { logger.error("map entry exists " + e + " to " + a + " new " + c); } } if (!c.isZERO()) { val.put(e, c); } } /** * Remove an ExpVector to coefficient entry from the internal map of this * GenPolynomial. Note: Do not use this method unless you are * constructing a new polynomial. this is modified and breaks the * immutability promise of this class. * @param e exponent. * @param c expected coefficient, null for ignore. */ public void doRemoveFromMap(ExpVector e, C c) { C b = val.remove(e); if (debug) { if ( c == null ) { // ignore b return; } if ( ! c.equals(b) ) { logger.error("map entry wrong " + e + " to " + c + " old " + b); } } } /** * Put an a sorted map of exponents to coefficients into the internal map of * this GenPolynomial. Note: Do not use this method unless you are * constructing a new polynomial. this is modified and breaks the * immutability promise of this class. * @param vals sorted map of exponents and coefficients. */ public void doPutToMap(SortedMap vals) { for (Map.Entry me : vals.entrySet()) { ExpVector e = me.getKey(); if (debug) { C a = val.get(e); if (a != null) { logger.error("map entry exists " + e + " to " + a + " new " + me.getValue()); } } C c = me.getValue(); if (!c.isZERO()) { val.put(e, c); } } } /** * String representation of GenPolynomial. * @see java.lang.Object#toString() */ @Override public String toString() { if (ring.vars != null) { return toString(ring.vars); } StringBuffer s = new StringBuffer(); s.append(this.getClass().getSimpleName() + ":"); s.append(ring.coFac.getClass().getSimpleName()); if (ring.coFac.characteristic().signum() != 0) { s.append("(" + ring.coFac.characteristic() + ")"); } s.append("[ "); boolean first = true; for (Map.Entry m : val.entrySet()) { if (first) { first = false; } else { s.append(", "); } s.append(m.getValue().toString()); s.append(" "); s.append(m.getKey().toString()); } s.append(" ] "); // no not use: ring.toString() ); return s.toString(); } /** * String representation of GenPolynomial. * @param v names for variables. * @see java.lang.Object#toString() */ public String toString(String[] v) { StringBuffer s = new StringBuffer(); if (PrettyPrint.isTrue()) { if (val.size() == 0) { s.append("0"); } else { // s.append( "( " ); boolean first = true; for (Map.Entry m : val.entrySet()) { C c = m.getValue(); if (first) { first = false; } else { if (c.signum() < 0) { s.append(" - "); c = c.negate(); } else { s.append(" + "); } } ExpVector e = m.getKey(); if (!c.isONE() || e.isZERO()) { String cs = c.toString(); if (c instanceof GenPolynomial || c instanceof AlgebraicNumber) { s.append("( "); s.append(cs); s.append(" )"); } else { s.append(cs); } s.append(" "); } if (e != null && v != null) { s.append(e.toString(v)); } else { s.append(e); } } //s.append(" )"); } } else { s.append(this.getClass().getSimpleName() + "[ "); if (val.size() == 0) { s.append("0"); } else { boolean first = true; for (Map.Entry m : val.entrySet()) { C c = m.getValue(); if (first) { first = false; } else { if (c.signum() < 0) { s.append(" - "); c = c.negate(); } else { s.append(" + "); } } ExpVector e = m.getKey(); if (!c.isONE() || e.isZERO()) { s.append(c.toString()); s.append(" "); } s.append(e.toString(v)); } } s.append(" ] "); // no not use: ring.toString() ); } return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case if (isZERO()) { return "0"; } StringBuffer s = new StringBuffer(); if (val.size() > 1) { s.append("( "); } String[] v = ring.vars; if (v == null) { v = GenPolynomialRing.newVars("x", ring.nvar); } boolean parenthesis = false; //if (ring.coFac instanceof GenPolynomialRing || ring.coFac instanceof AlgebraicNumberRing // || ring.coFac instanceof RealAlgebraicRing //) { // inactive: parenthesis = true; //} boolean first = true; for (Map.Entry m : val.entrySet()) { C c = m.getValue(); if (first) { first = false; } else { if (c.signum() < 0) { s.append(" - "); c = c.negate(); } else { s.append(" + "); } } ExpVector e = m.getKey(); if (!c.isONE() || e.isZERO()) { if (parenthesis) { s.append("( "); } s.append(c.toScript()); if (parenthesis) { s.append(" )"); } if (!e.isZERO()) { s.append(" * "); } } s.append(e.toScript(v)); } if (val.size() > 1) { s.append(" )"); } return s.toString(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Is GenPolynomial<C> zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return (val.size() == 0); } /** * Is GenPolynomial<C> one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { if (val.size() != 1) { return false; } C c = val.get(ring.evzero); if (c == null) { return false; } return c.isONE(); } /** * Is GenPolynomial<C> a unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (val.size() != 1) { return false; } C c = val.get(ring.evzero); if (c == null) { return false; } return c.isUnit(); } /** * Is GenPolynomial<C> a constant. * @return If this is a constant polynomial then true is returned, else * false. */ public boolean isConstant() { if (val.size() != 1) { return false; } C c = val.get(ring.evzero); if (c == null) { return false; } return true; } /** * Is GenPolynomial<C> homogeneous. * @return true, if this is homogeneous, else false. */ public boolean isHomogeneous() { if (val.size() <= 1) { return true; } long deg = -1; for (ExpVector e : val.keySet()) { if (deg < 0) { deg = e.totalDeg(); } else if (deg != e.totalDeg()) { return false; } } return true; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { if (!(B instanceof GenPolynomial)) { return false; } GenPolynomial a = null; try { a = (GenPolynomial) B; } catch (ClassCastException ignored) { } if (a == null) { return false; } return this.compareTo(a) == 0; } /** * Hash code for this polynomial. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = (ring.hashCode() << 27); h += val.hashCode(); return h; } /** * GenPolynomial comparison. * @param b GenPolynomial. * @return sign(this-b). */ public int compareTo(GenPolynomial b) { if (b == null) { return 1; } SortedMap av = this.val; SortedMap bv = b.val; Iterator> ai = av.entrySet().iterator(); Iterator> bi = bv.entrySet().iterator(); int s = 0; int c = 0; while (ai.hasNext() && bi.hasNext()) { Map.Entry aie = ai.next(); Map.Entry bie = bi.next(); ExpVector ae = aie.getKey(); ExpVector be = bie.getKey(); s = ae.compareTo(be); //System.out.println("s = " + s + ", " + ae + ", " +be); if (s != 0) { return s; } if (c == 0) { C ac = aie.getValue(); //av.get(ae); C bc = bie.getValue(); //bv.get(be); c = ac.compareTo(bc); } } if (ai.hasNext()) { return 1; } if (bi.hasNext()) { return -1; } // now all keys are equal return c; } /** * GenPolynomial signum. * @return sign(ldcf(this)). */ public int signum() { if (this.isZERO()) { return 0; } ExpVector t = val.firstKey(); C c = val.get(t); return c.signum(); } /** * Number of variables. * @return ring.nvar. */ public int numberOfVariables() { return ring.nvar; } /** * Leading monomial. * @return first map entry. */ public Map.Entry leadingMonomial() { if (val.size() == 0) return null; Iterator> ai = val.entrySet().iterator(); return ai.next(); } /** * Leading exponent vector. * @return first exponent. */ public ExpVector leadingExpVector() { if (val.size() == 0) { return null; // ring.evzero? needs many changes } return val.firstKey(); } /** * Trailing exponent vector. * @return last exponent. */ public ExpVector trailingExpVector() { if (val.size() == 0) { return ring.evzero; // or null ?; } return val.lastKey(); } /** * Leading base coefficient. * @return first coefficient. */ public C leadingBaseCoefficient() { if (val.size() == 0) { return ring.coFac.getZERO(); } return val.get(val.firstKey()); } /** * Trailing base coefficient. * @return coefficient of constant term. */ public C trailingBaseCoefficient() { C c = val.get(ring.evzero); if (c == null) { return ring.coFac.getZERO(); } return c; } /** * Coefficient. * @param e exponent. * @return coefficient for given exponent. */ public C coefficient(ExpVector e) { C c = val.get(e); if (c == null) { c = ring.coFac.getZERO(); } return c; } /** * Reductum. * @return this - leading monomial. */ public GenPolynomial reductum() { if (val.size() <= 1) { return ring.getZERO(); } Iterator ai = val.keySet().iterator(); ExpVector lt = ai.next(); lt = ai.next(); // size > 1 SortedMap red = val.tailMap(lt); return new GenPolynomial(ring, red); } /** * Degree in variable i. * @return maximal degree in the variable i. */ public long degree(int i) { if (val.size() == 0) { return 0; // 0 or -1 ?; } int j; if (i >= 0) { j = ring.nvar - 1 - i; } else { // python like -1 means main variable j = ring.nvar + i; } long deg = 0; for (ExpVector e : val.keySet()) { long d = e.getVal(j); if (d > deg) { deg = d; } } return deg; } /** * Maximal degree. * @return maximal degree in any variables. */ public long degree() { if (val.size() == 0) { return 0; // 0 or -1 ?; } long deg = 0; for (ExpVector e : val.keySet()) { long d = e.maxDeg(); if (d > deg) { deg = d; } } return deg; } /** * Total degree. * @return total degree in any variables. */ public long totalDegree() { if (val.size() == 0) { return 0; // 0 or -1 ?; } long deg = 0; for (ExpVector e : val.keySet()) { long d = e.totalDeg(); if (d > deg) { deg = d; } } return deg; } /** * Maximal degree vector. * @return maximal degree vector of all variables. */ public ExpVector degreeVector() { ExpVector deg = ring.evzero; if (val.size() == 0) { return deg; } for (ExpVector e : val.keySet()) { deg = deg.lcm(e); } return deg; } /** * GenPolynomial maximum norm. * @return ||this||. */ public C maxNorm() { C n = ring.getZEROCoefficient(); for (C c : val.values()) { C x = c.abs(); if (n.compareTo(x) < 0) { n = x; } } return n; } /** * GenPolynomial sum norm. * @return sum of all absolute values of coefficients. */ public C sumNorm() { C n = ring.getZEROCoefficient(); for (C c : val.values()) { C x = c.abs(); n = n.sum(x); } return n; } /** * GenPolynomial summation. * @param S GenPolynomial. * @return this+S. */ //public > T sum(T /*GenPolynomial*/ S) { public GenPolynomial sum(GenPolynomial S) { if (S == null) { return this; } if (S.isZERO()) { return this; } if (this.isZERO()) { return S; } assert (ring.nvar == S.ring.nvar); GenPolynomial n = this.copy(); //new GenPolynomial(ring, val); SortedMap nv = n.val; SortedMap sv = S.val; for (Map.Entry me : sv.entrySet()) { ExpVector e = me.getKey(); C y = me.getValue(); //sv.get(e); // assert y != null C x = nv.get(e); if (x != null) { x = x.sum(y); if (!x.isZERO()) { nv.put(e, x); } else { nv.remove(e); } } else { nv.put(e, y); } } return n; } /** * GenPolynomial addition. This method is not very efficient, since this is * copied. * @param a coefficient. * @param e exponent. * @return this + a xe. */ public GenPolynomial sum(C a, ExpVector e) { if (a == null) { return this; } if (a.isZERO()) { return this; } GenPolynomial n = this.copy(); //new GenPolynomial(ring, val); SortedMap nv = n.val; //if ( nv.size() == 0 ) { nv.put(e,a); return n; } C x = nv.get(e); if (x != null) { x = x.sum(a); if (!x.isZERO()) { nv.put(e, x); } else { nv.remove(e); } } else { nv.put(e, a); } return n; } /** * GenPolynomial addition. This method is not very efficient, since this is * copied. * @param a coefficient. * @return this + a x0. */ public GenPolynomial sum(C a) { return sum(a, ring.evzero); } /** * GenPolynomial subtraction. * @param S GenPolynomial. * @return this-S. */ public GenPolynomial subtract(GenPolynomial S) { if (S == null) { return this; } if (S.isZERO()) { return this; } if (this.isZERO()) { return S.negate(); } assert (ring.nvar == S.ring.nvar); GenPolynomial n = this.copy(); //new GenPolynomial(ring, val); SortedMap nv = n.val; SortedMap sv = S.val; for (Map.Entry me : sv.entrySet()) { ExpVector e = me.getKey(); C y = me.getValue(); //sv.get(e); // assert y != null C x = nv.get(e); if (x != null) { x = x.subtract(y); if (!x.isZERO()) { nv.put(e, x); } else { nv.remove(e); } } else { nv.put(e, y.negate()); } } return n; } /** * GenPolynomial subtraction. This method is not very efficient, since this * is copied. * @param a coefficient. * @param e exponent. * @return this - a xe. */ public GenPolynomial subtract(C a, ExpVector e) { if (a == null) { return this; } if (a.isZERO()) { return this; } GenPolynomial n = this.copy(); SortedMap nv = n.val; C x = nv.get(e); if (x != null) { x = x.subtract(a); if (!x.isZERO()) { nv.put(e, x); } else { nv.remove(e); } } else { nv.put(e, a.negate()); } return n; } /** * GenPolynomial subtract. This method is not very efficient, since this is * copied. * @param a coefficient. * @return this + a x0. */ public GenPolynomial subtract(C a) { return subtract(a, ring.evzero); } /** * GenPolynomial subtract a multiple. * @param a coefficient. * @param S GenPolynomial. * @return this - a xe S. */ public GenPolynomial subtractMultiple(C a, GenPolynomial S) { if (a == null) { return this; } if (a.isZERO()) { return this; } if (S == null) { return this; } if (S.isZERO()) { return this; } if (this.isZERO()) { return S.multiply(a.negate()); } assert (ring.nvar == S.ring.nvar); GenPolynomial n = this.copy(); SortedMap nv = n.val; SortedMap sv = S.val; for (Map.Entry me : sv.entrySet()) { ExpVector f = me.getKey(); C y = me.getValue(); // assert y != null y = a.multiply(y); C x = nv.get(f); if (x != null) { x = x.subtract(y); if (!x.isZERO()) { nv.put(f, x); } else { nv.remove(f); } } else if ( !y.isZERO() ) { nv.put(f, y.negate()); } } return n; } /** * GenPolynomial subtract a multiple. * @param a coefficient. * @param e exponent. * @param S GenPolynomial. * @return this - a xe S. */ public GenPolynomial subtractMultiple(C a, ExpVector e, GenPolynomial S) { if (a == null) { return this; } if (a.isZERO()) { return this; } if (S == null) { return this; } if (S.isZERO()) { return this; } if (this.isZERO()) { return S.multiply(a.negate(),e); } assert (ring.nvar == S.ring.nvar); GenPolynomial n = this.copy(); SortedMap nv = n.val; SortedMap sv = S.val; for (Map.Entry me : sv.entrySet()) { ExpVector f = me.getKey(); f = e.sum(f); C y = me.getValue(); // assert y != null y = a.multiply(y); C x = nv.get(f); if (x != null) { x = x.subtract(y); if (!x.isZERO()) { nv.put(f, x); } else { nv.remove(f); } } else if ( !y.isZERO() ) { nv.put(f, y.negate()); } } return n; } /** * GenPolynomial scale and subtract a multiple. * @param b scale factor. * @param a coefficient. * @param e exponent. * @param S GenPolynomial. * @return this * b - a xe S. */ public GenPolynomial scaleSubtractMultiple(C b, C a, ExpVector e, GenPolynomial S) { if (a == null || S == null) { return this.multiply(b); } if (a.isZERO() || S.isZERO()) { return this.multiply(b); } if (this.isZERO() || b == null || b.isZERO()) { return S.multiply(a.negate(),e); } if (b.isONE()) { return subtractMultiple(a,e,S); } assert (ring.nvar == S.ring.nvar); GenPolynomial n = this.multiply(b); SortedMap nv = n.val; SortedMap sv = S.val; for (Map.Entry me : sv.entrySet()) { ExpVector f = me.getKey(); f = e.sum(f); C y = me.getValue(); // assert y != null y = a.multiply(y); // now y can be zero C x = nv.get(f); if (x != null) { x = x.subtract(y); if (!x.isZERO()) { nv.put(f, x); } else { nv.remove(f); } } else if ( !y.isZERO() ) { nv.put(f, y.negate()); } } return n; } /** * GenPolynomial scale and subtract a multiple. * @param b scale factor. * @param g scale exponent. * @param a coefficient. * @param e exponent. * @param S GenPolynomial. * @return this * a xg - a xe S. */ public GenPolynomial scaleSubtractMultiple(C b, ExpVector g, C a, ExpVector e, GenPolynomial S) { if (a == null || S == null) { return this.multiply(b,g); } if (a.isZERO() || S.isZERO()) { return this.multiply(b,g); } if (this.isZERO() || b == null || b.isZERO()) { return S.multiply(a.negate(),e); } if (b.isONE() && g.isZERO()) { return subtractMultiple(a,e,S); } assert (ring.nvar == S.ring.nvar); GenPolynomial n = this.multiply(b,g); SortedMap nv = n.val; SortedMap sv = S.val; for (Map.Entry me : sv.entrySet()) { ExpVector f = me.getKey(); f = e.sum(f); C y = me.getValue(); // assert y != null y = a.multiply(y); // y can be zero now C x = nv.get(f); if (x != null) { x = x.subtract(y); if (!x.isZERO()) { nv.put(f, x); } else { nv.remove(f); } } else if ( !y.isZERO() ) { nv.put(f, y.negate()); } } return n; } /** * GenPolynomial negation. * @return -this. */ public GenPolynomial negate() { GenPolynomial n = ring.getZERO().copy(); //new GenPolynomial(ring, ring.getZERO().val); SortedMap v = n.val; for (Map.Entry m : val.entrySet()) { C x = m.getValue(); // != null, 0 v.put(m.getKey(), x.negate()); // or m.setValue( x.negate() ) if this cloned } return n; } /** * GenPolynomial absolute value, i.e. leadingCoefficient > 0. * @return abs(this). */ public GenPolynomial abs() { if (leadingBaseCoefficient().signum() < 0) { return this.negate(); } return this; } /** * GenPolynomial multiplication. * @param S GenPolynomial. * @return this*S. */ public GenPolynomial multiply(GenPolynomial S) { if (S == null) { return ring.getZERO(); } if (S.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } assert (ring.nvar == S.ring.nvar); if (this instanceof GenSolvablePolynomial || S instanceof GenSolvablePolynomial) { //throw new RuntimeException("wrong method dispatch in JRE "); logger.debug("warn: wrong method dispatch in JRE multiply(S) - trying to fix"); GenSolvablePolynomial T = (GenSolvablePolynomial) this; GenSolvablePolynomial Sp = (GenSolvablePolynomial) S; return T.multiply(Sp); } GenPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c1 = m1.getValue(); ExpVector e1 = m1.getKey(); for (Map.Entry m2 : S.val.entrySet()) { C c2 = m2.getValue(); ExpVector e2 = m2.getKey(); C c = c1.multiply(c2); // check non zero if not domain if (!c.isZERO()) { ExpVector e = e1.sum(e2); C c0 = pv.get(e); if (c0 == null) { pv.put(e, c); } else { c0 = c0.sum(c); if (!c0.isZERO()) { pv.put(e, c0); } else { pv.remove(e); } } } } } return p; } /** * GenPolynomial multiplication. Product with coefficient ring element. * @param s coefficient. * @return this*s. */ public GenPolynomial multiply(C s) { if (s == null) { return ring.getZERO(); } if (s.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } GenPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c1 = m1.getValue(); ExpVector e1 = m1.getKey(); C c = c1.multiply(s); // check non zero if not domain if (!c.isZERO()) { pv.put(e1, c); // or m1.setValue( c ) } } return p; } /** * GenPolynomial monic, i.e. leadingCoefficient == 1. If leadingCoefficient * is not invertible returns this unmodified. * @return monic(this). */ public GenPolynomial monic() { if (this.isZERO()) { return this; } C lc = leadingBaseCoefficient(); if (!lc.isUnit()) { //System.out.println("lc = "+lc); return this; } C lm = lc.inverse(); return multiply(lm); } /** * GenPolynomial multiplication. Product with ring element and exponent * vector. * @param s coefficient. * @param e exponent. * @return this * s xe. */ public GenPolynomial multiply(C s, ExpVector e) { if (s == null) { return ring.getZERO(); } if (s.isZERO()) { return ring.getZERO(); } if (this.isZERO()) { return this; } if (this instanceof GenSolvablePolynomial) { //throw new RuntimeException("wrong method dispatch in JRE "); logger.debug("warn: wrong method dispatch in JRE multiply(s,e) - trying to fix"); GenSolvablePolynomial T = (GenSolvablePolynomial) this; return T.multiply(s, e); } GenPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c1 = m1.getValue(); ExpVector e1 = m1.getKey(); C c = c1.multiply(s); // check non zero if not domain if (!c.isZERO()) { ExpVector e2 = e1.sum(e); pv.put(e2, c); } } return p; } /** * GenPolynomial multiplication. Product with exponent vector. * @param e exponent (!= null). * @return this * xe. */ public GenPolynomial multiply(ExpVector e) { // assert e != null. This is never allowed. if (this.isZERO()) { return this; } if (this instanceof GenSolvablePolynomial) { //throw new RuntimeException("wrong method dispatch in JRE "); logger.debug("warn: wrong method dispatch in JRE multiply(e) - trying to fix"); GenSolvablePolynomial T = (GenSolvablePolynomial) this; return T.multiply(e); } GenPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m1 : val.entrySet()) { C c1 = m1.getValue(); ExpVector e1 = m1.getKey(); ExpVector e2 = e1.sum(e); pv.put(e2, c1); } return p; } /** * GenPolynomial multiplication. Product with 'monomial'. * @param m 'monomial'. * @return this * m. */ public GenPolynomial multiply(Map.Entry m) { if (m == null) { return ring.getZERO(); } return multiply(m.getValue(), m.getKey()); } /** * GenPolynomial division. Division by coefficient ring element. Fails, if * exact division is not possible. * @param s coefficient. * @return this/s. */ public GenPolynomial divide(C s) { if (s == null || s.isZERO()) { throw new ArithmeticException("division by zero"); } if (this.isZERO()) { return this; } //C t = s.inverse(); //return multiply(t); GenPolynomial p = ring.getZERO().copy(); SortedMap pv = p.val; for (Map.Entry m : val.entrySet()) { ExpVector e = m.getKey(); C c1 = m.getValue(); C c = c1.divide(s); if (debug) { C x = c1.remainder(s); if (!x.isZERO()) { logger.info("divide x = " + x); throw new ArithmeticException("no exact division: " + c1 + "/" + s); } } if (c.isZERO()) { throw new ArithmeticException("no exact division: " + c1 + "/" + s + ", in " + this); } pv.put(e, c); // or m1.setValue( c ) } return p; } /** * GenPolynomial division with remainder. Fails, if exact division by * leading base coefficient is not possible. Meaningful only for univariate * polynomials over fields, but works in any case. * @param S nonzero GenPolynomial with invertible leading coefficient. * @return [ quotient , remainder ] with this = quotient * S + remainder and * deg(remainder) < deg(S) or remiander = 0. * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) * . */ @SuppressWarnings("unchecked") public GenPolynomial[] quotientRemainder(GenPolynomial S) { if (S == null || S.isZERO()) { throw new ArithmeticException("division by zero"); } C c = S.leadingBaseCoefficient(); if (!c.isUnit()) { throw new ArithmeticException("lbcf not invertible " + c); } C ci = c.inverse(); assert (ring.nvar == S.ring.nvar); ExpVector e = S.leadingExpVector(); GenPolynomial h; GenPolynomial q = ring.getZERO().copy(); GenPolynomial r = this.copy(); while (!r.isZERO()) { ExpVector f = r.leadingExpVector(); if (f.multipleOf(e)) { C a = r.leadingBaseCoefficient(); f = f.subtract(e); a = a.multiply(ci); q = q.sum(a, f); h = S.multiply(a, f); r = r.subtract(h); } else { break; } } GenPolynomial[] ret = new GenPolynomial[2]; ret[0] = q; ret[1] = r; return ret; } /** * GenPolynomial division with remainder. Fails, if exact division by * leading base coefficient is not possible. Meaningful only for univariate * polynomials over fields, but works in any case. * @param S nonzero GenPolynomial with invertible leading coefficient. * @return [ quotient , remainder ] with this = quotient * S + remainder and * deg(remainder) < deg(S) or remiander = 0. * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) * . * @deprecated use quotientRemainder() */ @Deprecated public GenPolynomial[] divideAndRemainder(GenPolynomial S) { return quotientRemainder(S); } /** * GenPolynomial division. Fails, if exact division by leading base * coefficient is not possible. Meaningful only for univariate polynomials * over fields, but works in any case. * @param S nonzero GenPolynomial with invertible leading coefficient. * @return quotient with this = quotient * S + remainder. * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) * . */ public GenPolynomial divide(GenPolynomial S) { return quotientRemainder(S)[0]; } /** * GenPolynomial remainder. Fails, if exact division by leading base * coefficient is not possible. Meaningful only for univariate polynomials * over fields, but works in any case. * @param S nonzero GenPolynomial with invertible leading coefficient. * @return remainder with this = quotient * S + remainder. * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) * . */ public GenPolynomial remainder(GenPolynomial S) { if (S == null || S.isZERO()) { throw new ArithmeticException("division by zero"); } C c = S.leadingBaseCoefficient(); if (!c.isUnit()) { throw new ArithmeticException("lbc not invertible " + c); } C ci = c.inverse(); assert (ring.nvar == S.ring.nvar); ExpVector e = S.leadingExpVector(); GenPolynomial h; GenPolynomial r = this.copy(); while (!r.isZERO()) { ExpVector f = r.leadingExpVector(); if (f.multipleOf(e)) { C a = r.leadingBaseCoefficient(); f = f.subtract(e); //logger.info("red div = " + e); a = a.multiply(ci); h = S.multiply(a, f); r = r.subtract(h); } else { break; } } return r; } /** * GenPolynomial greatest common divisor. Only for univariate polynomials * over fields. * @param S GenPolynomial. * @return gcd(this,S). */ public GenPolynomial gcd(GenPolynomial S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } if (ring.nvar != 1) { throw new IllegalArgumentException("not univariate polynomials" + ring); } GenPolynomial x; GenPolynomial q = this; GenPolynomial r = S; while (!r.isZERO()) { x = q.remainder(r); q = r; r = x; } return q.monic(); // normalize } /** * GenPolynomial extended greatest comon divisor. Only for univariate * polynomials over fields. * @param S GenPolynomial. * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S). */ @SuppressWarnings("unchecked") public GenPolynomial[] egcd(GenPolynomial S) { GenPolynomial[] ret = new GenPolynomial[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (S == null || S.isZERO()) { ret[0] = this; ret[1] = this.ring.getONE(); ret[2] = this.ring.getZERO(); return ret; } if (this.isZERO()) { ret[0] = S; ret[1] = this.ring.getZERO(); ret[2] = this.ring.getONE(); return ret; } if (ring.nvar != 1) { throw new IllegalArgumentException(this.getClass().getName() + " not univariate polynomials" + ring); } if (this.isConstant() && S.isConstant()) { C t = this.leadingBaseCoefficient(); C s = S.leadingBaseCoefficient(); C[] gg = t.egcd(s); //System.out.println("coeff gcd = " + Arrays.toString(gg)); GenPolynomial z = this.ring.getZERO(); ret[0] = z.sum(gg[0]); ret[1] = z.sum(gg[1]); ret[2] = z.sum(gg[2]); return ret; } GenPolynomial[] qr; GenPolynomial q = this; GenPolynomial r = S; GenPolynomial c1 = ring.getONE().copy(); GenPolynomial d1 = ring.getZERO().copy(); GenPolynomial c2 = ring.getZERO().copy(); GenPolynomial d2 = ring.getONE().copy(); GenPolynomial x1; GenPolynomial x2; while (!r.isZERO()) { qr = q.quotientRemainder(r); q = qr[0]; x1 = c1.subtract(q.multiply(d1)); x2 = c2.subtract(q.multiply(d2)); c1 = d1; c2 = d2; d1 = x1; d2 = x2; q = r; r = qr[1]; } // normalize ldcf(q) to 1, i.e. make monic C g = q.leadingBaseCoefficient(); if (g.isUnit()) { C h = g.inverse(); q = q.multiply(h); c1 = c1.multiply(h); c2 = c2.multiply(h); } //assert ( ((c1.multiply(this)).sum( c2.multiply(S)).equals(q) )); ret[0] = q; ret[1] = c1; ret[2] = c2; return ret; } /** * GenPolynomial half extended greatest comon divisor. Only for univariate * polynomials over fields. * @param S GenPolynomial. * @return [ gcd(this,S), a ] with a*this + b*S = gcd(this,S). */ @SuppressWarnings("unchecked") public GenPolynomial[] hegcd(GenPolynomial S) { GenPolynomial[] ret = new GenPolynomial[2]; ret[0] = null; ret[1] = null; if (S == null || S.isZERO()) { ret[0] = this; ret[1] = this.ring.getONE(); return ret; } if (this.isZERO()) { ret[0] = S; return ret; } if (ring.nvar != 1) { throw new IllegalArgumentException(this.getClass().getName() + " not univariate polynomials" + ring); } GenPolynomial[] qr; GenPolynomial q = this; GenPolynomial r = S; GenPolynomial c1 = ring.getONE().copy(); GenPolynomial d1 = ring.getZERO().copy(); GenPolynomial x1; while (!r.isZERO()) { qr = q.quotientRemainder(r); q = qr[0]; x1 = c1.subtract(q.multiply(d1)); c1 = d1; d1 = x1; q = r; r = qr[1]; } // normalize ldcf(q) to 1, i.e. make monic C g = q.leadingBaseCoefficient(); if (g.isUnit()) { C h = g.inverse(); q = q.multiply(h); c1 = c1.multiply(h); } //assert ( ((c1.multiply(this)).remainder(S).equals(q) )); ret[0] = q; ret[1] = c1; return ret; } /** * GenPolynomial inverse. Required by RingElem. Throws not invertible * exception. */ public GenPolynomial inverse() { if (isUnit()) { // only possible if ldbcf is unit C c = leadingBaseCoefficient().inverse(); return ring.getONE().multiply(c); } throw new NotInvertibleException("element not invertible " + this + " :: " + ring); } /** * GenPolynomial modular inverse. Only for univariate polynomials over * fields. * @param m GenPolynomial. * @return a with with a*this = 1 mod m. */ public GenPolynomial modInverse(GenPolynomial m) { if (this.isZERO()) { throw new NotInvertibleException("zero is not invertible"); } GenPolynomial[] hegcd = this.hegcd(m); GenPolynomial a = hegcd[0]; if (!a.isUnit()) { // gcd != 1 throw new AlgebraicNotInvertibleException("element not invertible, gcd != 1", m, a, m.divide(a)); } GenPolynomial b = hegcd[1]; if (b.isZERO()) { // when m divides this, e.g. m.isUnit() throw new NotInvertibleException("element not invertible, divisible by modul"); } return b; } /** * Extend variables. Used e.g. in module embedding. Extend all ExpVectors by * i elements and multiply by x_j^k. * @param pfac extended polynomial ring factory (by i variables). * @param j index of variable to be used for multiplication. * @param k exponent for x_j. * @return extended polynomial. */ public GenPolynomial extend(GenPolynomialRing pfac, int j, long k) { if (ring.equals(pfac)) { // nothing to do return this; } GenPolynomial Cp = pfac.getZERO().copy(); if (this.isZERO()) { return Cp; } int i = pfac.nvar - ring.nvar; Map C = Cp.val; //getMap(); Map A = val; for (Map.Entry y : A.entrySet()) { ExpVector e = y.getKey(); C a = y.getValue(); ExpVector f = e.extend(i, j, k); C.put(f, a); } return Cp; } /** * Extend lower variables. Used e.g. in module embedding. Extend all * ExpVectors by i lower elements and multiply by x_j^k. * @param pfac extended polynomial ring factory (by i variables). * @param j index of variable to be used for multiplication. * @param k exponent for x_j. * @return extended polynomial. */ public GenPolynomial extendLower(GenPolynomialRing pfac, int j, long k) { if (ring.equals(pfac)) { // nothing to do return this; } GenPolynomial Cp = pfac.getZERO().copy(); if (this.isZERO()) { return Cp; } int i = pfac.nvar - ring.nvar; Map C = Cp.val; //getMap(); Map A = val; for (Map.Entry y : A.entrySet()) { ExpVector e = y.getKey(); C a = y.getValue(); ExpVector f = e.extendLower(i, j, k); C.put(f, a); } return Cp; } /** * Contract variables. Used e.g. in module embedding. Remove i elements of * each ExpVector. * @param pfac contracted polynomial ring factory (by i variables). * @return Map of exponents and contracted polynomials. Note: could * return SortedMap */ public Map> contract(GenPolynomialRing pfac) { GenPolynomial zero = pfac.getZERO(); TermOrder t = new TermOrder(TermOrder.INVLEX); Map> B = new TreeMap>(t.getAscendComparator()); if (this.isZERO()) { return B; } int i = ring.nvar - pfac.nvar; Map A = val; for (Map.Entry y : A.entrySet()) { ExpVector e = y.getKey(); C a = y.getValue(); ExpVector f = e.contract(0, i); ExpVector g = e.contract(i, e.length() - i); GenPolynomial p = B.get(f); if (p == null) { p = zero; } p = p.sum(a, g); B.put(f, p); } return B; } /** * Contract variables to coefficient polynomial. Remove i elements of each * ExpVector, removed elements must be zero. * @param pfac contracted polynomial ring factory (by i variables). * @return contracted coefficient polynomial. */ public GenPolynomial contractCoeff(GenPolynomialRing pfac) { Map> ms = contract(pfac); GenPolynomial c = pfac.getZERO(); for (Map.Entry> m : ms.entrySet()) { if (m.getKey().isZERO()) { c = m.getValue(); } else { throw new RuntimeException("wrong coefficient contraction " + m + ", pol = " + c); } } return c; } /** * Extend univariate to multivariate polynomial. This is an univariate * polynomial in variable i of the polynomial ring, it is extended to the * given polynomial ring. * @param pfac extended polynomial ring factory. * @param i index of the variable of this polynomial in pfac. * @return extended multivariate polynomial. */ public GenPolynomial extendUnivariate(GenPolynomialRing pfac, int i) { if (i < 0 || pfac.nvar < i) { throw new IllegalArgumentException("index " + i + "out of range " + pfac.nvar); } if (ring.nvar != 1) { throw new IllegalArgumentException("polynomial not univariate " + ring.nvar); } if (this.isONE()) { return pfac.getONE(); } int j = pfac.nvar - 1 - i; GenPolynomial Cp = pfac.getZERO().copy(); if (this.isZERO()) { return Cp; } Map C = Cp.val; //getMap(); Map A = val; for (Map.Entry y : A.entrySet()) { ExpVector e = y.getKey(); long n = e.getVal(0); C a = y.getValue(); ExpVector f = ExpVector.create(pfac.nvar, j, n); C.put(f, a); // assert not contained } return Cp; } /** * Make homogeneous. * @param pfac extended polynomial ring factory (by 1 variable). * @return homogeneous polynomial. */ public GenPolynomial homogenize(GenPolynomialRing pfac) { if (ring.equals(pfac)) { // not implemented throw new UnsupportedOperationException("case with same ring not implemented"); } GenPolynomial Cp = pfac.getZERO().copy(); if (this.isZERO()) { return Cp; } long deg = totalDegree(); //int i = pfac.nvar - ring.nvar; Map C = Cp.val; //getMap(); Map A = val; for (Map.Entry y : A.entrySet()) { ExpVector e = y.getKey(); C a = y.getValue(); long d = deg - e.totalDeg(); ExpVector f = e.extend(1, 0, d); C.put(f, a); } return Cp; } /** * Dehomogenize. * @param pfac contracted polynomial ring factory (by 1 variable). * @return in homogeneous polynomial. */ public GenPolynomial deHomogenize(GenPolynomialRing pfac) { if (ring.equals(pfac)) { // not implemented throw new UnsupportedOperationException("case with same ring not implemented"); } GenPolynomial Cp = pfac.getZERO().copy(); if (this.isZERO()) { return Cp; } Map C = Cp.val; //getMap(); Map A = val; for (Map.Entry y : A.entrySet()) { ExpVector e = y.getKey(); C a = y.getValue(); ExpVector f = e.contract(1, pfac.nvar); C.put(f, a); } return Cp; } /** * Reverse variables. Used e.g. in opposite rings. * @return polynomial with reversed variables. */ public GenPolynomial reverse(GenPolynomialRing oring) { GenPolynomial Cp = oring.getZERO().copy(); if (this.isZERO()) { return Cp; } int k = -1; if (oring.tord.getEvord2() != 0 && oring.partial) { k = oring.tord.getSplit(); } Map C = Cp.val; //getMap(); Map A = val; ExpVector f; for (Map.Entry y : A.entrySet()) { ExpVector e = y.getKey(); if (k >= 0) { f = e.reverse(k); } else { f = e.reverse(); } C a = y.getValue(); C.put(f, a); } return Cp; } /** * Iterator over coefficients. * @return val.values().iterator(). */ public Iterator coefficientIterator() { return val.values().iterator(); } /** * Iterator over exponents. * @return val.keySet().iterator(). */ public Iterator exponentIterator() { return val.keySet().iterator(); } /** * Iterator over monomials. * @return a PolyIterator. */ public Iterator> iterator() { return new PolyIterator(val); } /** * Map a unary function to the coefficients. * @param f evaluation functor. * @return new polynomial with coefficients f(this(e)). */ public GenPolynomial map(final UnaryFunctor f) { GenPolynomial n = ring.getZERO().copy(); SortedMap nv = n.val; for (Monomial m : this) { //logger.info("m = " + m); C c = f.eval(m.c); if (c != null && !c.isZERO()) { nv.put(m.e, c); } } return n; } } jas-2.5/src/edu/jas/poly/ResidueRing.java0000644000175000017500000001513411461027126020536 0ustar giovannigiovanni/* * $Id: ResidueRing.java 3366 2010-10-24 13:02:14Z kredel $ */ package edu.jas.poly; import java.util.Random; import java.util.List; import java.util.ArrayList; import java.io.Reader; import org.apache.log4j.Logger; import edu.jas.structure.ElemFactory; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Residue ring factory based on RingElem and RingFactory module. * Objects of this class are immutable. * @author Heinz Kredel */ public class ResidueRing > implements RingFactory< Residue > { private static final Logger logger = Logger.getLogger(ResidueRing.class); //private boolean debug = logger.isDebugEnabled(); /** Ring element for reduction. */ protected final C modul; /** Ring factory. */ protected final RingFactory ring; /** Indicator if this ring is a field. */ protected int isField = -1; // initially unknown /** The constructor creates a ResidueRing object * from an ring factory and a modul. * @param r ring factory. * @param m modul. */ public ResidueRing(RingFactory r, C m) { ring = r; if ( m.isZERO() ) { throw new IllegalArgumentException("modul may not be null"); } if ( m.isONE() ) { logger.warn("modul is one"); } if ( m.signum() < 0 ) { m = m.negate(); } modul = m; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { throw new UnsupportedOperationException("not implemented"); //return ring.isFinite(); } /** Copy Residue element c. * @param c * @return a copy of c. */ public Residue copy(Residue c) { return new Residue( c.ring, c.val ); } /** Get the zero element. * @return 0 as Residue. */ public Residue getZERO() { return new Residue( this, ring.getZERO() ); } /** Get the one element. * @return 1 as Residue. */ public Residue getONE() { Residue one = new Residue( this, ring.getONE() ); if ( one.isZERO() ) { logger.warn("one is zero, so all residues are 0"); } return one; } /** Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List rgens = ring.generators(); List> gens = new ArrayList >( rgens.size() ); for ( C c: rgens ) { gens.add( new Residue(this,c) ); } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return ring.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return ring.isAssociative(); } /** * Query if this ring is a field. * @return false. */ public boolean isField() { if ( isField > 0 ) { return true; } if ( isField == 0 ) { return false; } // ideal is prime ? return false; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return ring.characteristic(); } /** Get a Residue element from a BigInteger value. * @param a BigInteger. * @return a Residue. */ public Residue fromInteger(java.math.BigInteger a) { return new Residue( this, ring.fromInteger(a) ); } /** Get a Residue element from a long value. * @param a long. * @return a Residue. */ public Residue fromInteger(long a) { return new Residue( this, ring.fromInteger(a) ); } /** Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { return "Residue[ " + modul.toString() + " ]"; } /** Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "ResidueRing(" + modul.toScript() + ")"; } /** Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object b) { if ( ! ( b instanceof ResidueRing ) ) { return false; } ResidueRing a = null; try { a = (ResidueRing) b; } catch (ClassCastException e) { } if ( a == null ) { return false; } if ( ! ring.equals( a.ring ) ) { return false; } return modul.equals( a.modul ); } /** Hash code for this residue ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + modul.hashCode(); return h; } /** Residue random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random residue element. */ public Residue random(int n) { C x = ring.random( n ); // x = x.sum( ring.getONE() ); return new Residue( this, x ); } /** Residue random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random residue element. */ public Residue random(int n, Random rnd) { C x = ring.random( n, rnd ); // x = x.sum( ring.getONE() ); return new Residue( this, x); } /** Parse Residue from String. * @param s String. * @return Residue from s. */ public Residue parse(String s) { C x = ring.parse( s ); return new Residue( this, x ); } /** Parse Residue from Reader. * @param r Reader. * @return next Residue from r. */ public Residue parse(Reader r) { C x = ring.parse( r ); return new Residue( this, x ); } } jas-2.5/src/edu/jas/poly/RelationTable.java0000644000175000017500000005455412137024450021052 0ustar giovannigiovanni/* * $Id: RelationTable.java 4388 2013-04-27 19:38:16Z kredel $ */ package edu.jas.poly; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.kern.PrettyPrint; import edu.jas.structure.RingElem; /** * RelationTable for solvable polynomials. This class maintains the * non-commutative multiplication relations of solvable polynomial rings. The * table entries are initialized with relations of the form xj * * xi = pij. During multiplication the ralations are * updated by relations of the form xjk * * xil = pijkl. If no relation for * xj * xi is found in the table, this multiplication is * assumed to be commutative xi xj. * @author Heinz Kredel */ public class RelationTable> implements Serializable { /** * The data structure for the relations. */ public final Map, List> table; /** * The factory for the solvable polynomial ring. */ public final GenSolvablePolynomialRing ring; private static final Logger logger = Logger.getLogger(RelationTable.class); private final boolean debug = logger.isDebugEnabled(); /** * Constructor for RelationTable requires ring factory. Note: This * constructor is called within the constructor of the ring factory, so * methods of this class can only be used after the other constructor has * terminated. * @param r solvable polynomial ring factory. */ protected RelationTable(GenSolvablePolynomialRing r) { table = new HashMap, List>(); ring = r; if (ring == null) { throw new IllegalArgumentException("RelationTable no ring"); } } /** * RelationTable equals. Tests same keySets only, not relations itself. Will * be improved in the future. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object p) { if (!(p instanceof RelationTable)) { System.out.println("no RelationTable"); return false; } RelationTable tab = null; try { tab = (RelationTable) p; } catch (ClassCastException ignored) { } if (tab == null) { return false; } if (!ring.equals(tab.ring)) { System.out.println("not same Ring " + ring.toScript() + ", " + tab.ring.toScript()); return false; } for (List k : table.keySet()) { List a = table.get(k); List b = tab.table.get(k); if (b == null) { return false; } // check contents, but only base relations if (!a.equals(b)) { return false; } } for (List k : tab.table.keySet()) { List a = table.get(k); List b = tab.table.get(k); if (a == null) { return false; } // check contents, but only base relations if (!a.equals(b)) { return false; } } return true; } /** * Hash code for this relation table. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 31 * h + table.hashCode(); return h; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { List v; StringBuffer s = new StringBuffer("RelationTable["); boolean first = true; for (List k : table.keySet()) { if (first) { first = false; } else { s.append(", "); } s.append(k.toString()); v = table.get(k); s.append("="); s.append(v.toString()); } s.append("]"); return s.toString(); } /** * Get the String representation. * @param vars names for the variables. * @see java.lang.Object#toString() */ @SuppressWarnings("unchecked") public String toString(String[] vars) { if (vars == null) { return toString(); } List v; StringBuffer s = new StringBuffer("RelationTable\n("); if (PrettyPrint.isTrue()) { boolean first = true; for (List k : table.keySet()) { if (first) { first = false; s.append("\n"); } else { s.append(",\n"); } v = table.get(k); for (Iterator jt = v.iterator(); jt.hasNext();) { ExpVectorPair ep = (ExpVectorPair) jt.next(); s.append("( " + ep.getFirst().toString(vars) + " ), "); s.append("( " + ep.getSecond().toString(vars) + " ), "); GenSolvablePolynomial p = (GenSolvablePolynomial) jt.next(); s.append("( " + p.toString(vars) + " )"); if (jt.hasNext()) { s.append(",\n"); } } } } else { boolean first = true; for (List k : table.keySet()) { if (first) { first = false; } else { s.append(",\n"); } v = table.get(k); for (Iterator jt = v.iterator(); jt.hasNext();) { ExpVectorPair ep = (ExpVectorPair) jt.next(); s.append("( " + ep.getFirst().toString(vars) + " ), "); s.append("( " + ep.getSecond().toString(vars) + " ), "); GenSolvablePolynomial p = (GenSolvablePolynomial) jt.next(); s.append("( " + p.toString(vars) + " )"); if (jt.hasNext()) { s.append(",\n"); } } } } s.append("\n)\n"); return s.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this relation table. */ public String toScript() { // Python case String[] vars = ring.vars; List v; StringBuffer s = new StringBuffer("["); boolean first = true; for (List k : table.keySet()) { if (first) { first = false; s.append(""); } else { s.append(", "); } v = table.get(k); for (Iterator jt = v.iterator(); jt.hasNext();) { ExpVectorPair ep = (ExpVectorPair) jt.next(); s.append("" + ep.getFirst().toScript(vars) + ", "); s.append("" + ep.getSecond().toScript(vars) + ", "); GenPolynomial p = (GenPolynomial) jt.next(); s.append("( " + p.toScript() + " )"); if (jt.hasNext()) { s.append(", "); } } } s.append("]"); return s.toString(); } /** * Update or initialize RelationTable with new relation. relation is e * f = * p. * @param e first term. * @param f second term. * @param p solvable product polynomial. */ @SuppressWarnings("unchecked") public synchronized void update(ExpVector e, ExpVector f, GenSolvablePolynomial p) { if (debug) { //System.out.println("new relation = " + e + " .*. " + f + " = " + p); if (p != null && p.ring.vars != null) { logger.info("new relation = " + e.toString(p.ring.vars) + " .*. " + f.toString(p.ring.vars) + " = " + p); //logger.info("existing relations = " + toString(p.ring.vars)); } else { logger.info("new relation = " + e + " .*. " + f + " = " + p); } } if (p == null || e == null || f == null) { throw new IllegalArgumentException("RelationTable update e|f|p == null"); } if (debug) { if (e.totalDeg() == 1 && f.totalDeg() == 1) { int[] de = e.dependencyOnVariables(); int[] df = f.dependencyOnVariables(); logger.debug("update e ? f " + de[0] + " " + df[0]); //int t = ring.tord.getDescendComparator().compare(e,f); //System.out.println("update compare(e,f) = " + t); if (de[0] == df[0]) { // error throw new IllegalArgumentException("RelationTable update e==f"); } if (de[0] > df[0]) { // invalid update logger.error("warning: update e > f " + e + " " + f + " changed"); ExpVector tmp = e; e = f; f = tmp; Map.Entry m = p.leadingMonomial(); GenPolynomial r = p.subtract(m.getValue(), m.getKey()); r = r.negate(); p = (GenSolvablePolynomial) r.sum(m.getValue(), m.getKey()); } } } ExpVector ef = e.sum(f); ExpVector lp = p.leadingExpVector(); if (!ef.equals(lp)) { // check for suitable term order logger.error("relation term order = " + ring.tord); throw new IllegalArgumentException("RelationTable update e*f != lt(p)"); } List key = makeKey(e, f); ExpVectorPair evp = new ExpVectorPair(e, f); if (key.size() != 2) { System.out.println("key = " + key + ", evp = " + evp); } List part = table.get(key); if (part == null) { // initialization only part = new LinkedList(); part.add(evp); part.add(p); table.put(key, part); return; } Object skip; int index = -1; synchronized (part) { // with lookup() for (ListIterator it = part.listIterator(); it.hasNext();) { ExpVectorPair look = (ExpVectorPair) it.next(); skip = it.next(); // skip poly if (look.isMultiple(evp)) { index = it.nextIndex(); // last index of or first index of: break } } if (index < 0) { index = 0; } part.add(index, evp); part.add(index + 1, p); } // table.put( key, part ); // required?? } /** * Update or initialize RelationTable with new relation. relation is e * f = * p. * @param E first term polynomial. * @param F second term polynomial. * @param p solvable product polynomial. */ public void update(GenPolynomial E, GenPolynomial F, GenSolvablePolynomial p) { if (E.isZERO() || F.isZERO()) { throw new IllegalArgumentException("polynomials may not be zero: " + E + ", " + F); } C ce = E.leadingBaseCoefficient(); C cf = F.leadingBaseCoefficient(); if (!ce.isONE() || !cf.isONE()) { throw new IllegalArgumentException("lbcf of polynomials must be one: " + ce + ", " + cf); } ExpVector e = E.leadingExpVector(); ExpVector f = F.leadingExpVector(); update(e, f, p); } /** * Update or initialize RelationTable with new relation. relation is e * f = * p. * @param E first term polynomial. * @param F second term polynomial. * @param p product polynomial. */ public void update(GenPolynomial E, GenPolynomial F, GenPolynomial p) { if (p.isZERO()) { throw new IllegalArgumentException("polynomial may not be zero: " + p); } if (p.isONE()) { throw new IllegalArgumentException("product of polynomials may not be one: " + p); } GenSolvablePolynomial sp = new GenSolvablePolynomial(ring, p.val); update(E, F, sp); } /** * Lookup RelationTable for existing relation. Find p with e * f = p. If no * relation for e * f is contained in the table then return the symmetric * product p = 1 e f. * @param e first term. * @param f second term. * @return t table relation container, contains e' and f' with e f = e' * lt(p) f'. */ @SuppressWarnings("unchecked") public TableRelation lookup(ExpVector e, ExpVector f) { List key = makeKey(e, f); List part = table.get(key); if (part == null) { // symmetric product ExpVector ef = e.sum(f); GenSolvablePolynomial p = ring.getONE().multiply(ef); return new TableRelation(null, null, p); } ExpVectorPair evp = new ExpVectorPair(e, f); ExpVector ep = null; ExpVector fp = null; ExpVectorPair look = null; GenSolvablePolynomial p = null; synchronized (part) { // with update() for (Iterator it = part.iterator(); it.hasNext();) { look = (ExpVectorPair) it.next(); p = (GenSolvablePolynomial) it.next(); if (evp.isMultiple(look)) { ep = e.subtract(look.getFirst()); fp = f.subtract(look.getSecond()); if (ep.isZERO()) { ep = null; } if (fp.isZERO()) { fp = null; } if (debug) { if (p != null && p.ring.vars != null) { logger.info("found relation = " + e.toString(p.ring.vars) + " .*. " + f.toString(p.ring.vars) + " = " + p); } else { logger.info("found relation = " + e + " .*. " + f + " = " + p); } } return new TableRelation(ep, fp, p); } } } // unreacheable code! throw new RuntimeException("no entry found in relation table for " + evp); } /** * Construct a key for (e,f). * @param e first term. * @param f second term. * @return k key for (e,f). */ protected List makeKey(ExpVector e, ExpVector f) { int[] de = e.dependencyOnVariables(); int[] df = f.dependencyOnVariables(); List key = new ArrayList(de.length + df.length); for (int i = 0; i < de.length; i++) { key.add(Integer.valueOf(de[i])); } for (int i = 0; i < df.length; i++) { key.add(Integer.valueOf(df[i])); } return key; } /** * Size of the table. * @return n number of non-commutative relations. */ public int size() { int s = 0; if (table == null) { return s; } for (Iterator it = table.values().iterator(); it.hasNext();) { List list = it.next(); s += list.size() / 2; } return s; } /** * Extend variables. Used e.g. in module embedding. Extend all ExpVectors * and polynomials of the given relation table by i elements and put the * relations into this table, i.e. this should be empty. * @param tab a relation table to be extended and inserted into this. */ @SuppressWarnings("unchecked") public void extend(RelationTable tab) { if (tab.table.size() == 0) { return; } // assert this.size() == 0 int i = ring.nvar - tab.ring.nvar; int j = 0; long k = 0l; List val; for (List key : tab.table.keySet()) { val = tab.table.get(key); for (Iterator jt = val.iterator(); jt.hasNext();) { ExpVectorPair ep = (ExpVectorPair) jt.next(); ExpVector e = ep.getFirst(); ExpVector f = ep.getSecond(); GenSolvablePolynomial p = (GenSolvablePolynomial) jt.next(); ExpVector ex = e.extend(i, j, k); ExpVector fx = f.extend(i, j, k); GenSolvablePolynomial px = (GenSolvablePolynomial) p.extend(ring, j, k); this.update(ex, fx, px); } } return; } /** * Contract variables. Used e.g. in module embedding. Contract all * ExpVectors and polynomials of the given relation table by i elements and * put the relations into this table, i.e. this should be empty. * @param tab a relation table to be contracted and inserted into this. */ @SuppressWarnings("unchecked") public void contract(RelationTable tab) { if (tab.table.size() == 0) { return; } // assert this.size() == 0 int i = tab.ring.nvar - ring.nvar; List val; for (List key : tab.table.keySet()) { val = tab.table.get(key); for (Iterator jt = val.iterator(); jt.hasNext();) { ExpVectorPair ep = (ExpVectorPair) jt.next(); ExpVector e = ep.getFirst(); ExpVector f = ep.getSecond(); GenSolvablePolynomial p = (GenSolvablePolynomial) jt.next(); ExpVector ec = e.contract(i, e.length() - i); ExpVector fc = f.contract(i, f.length() - i); if (ec.isZERO() || fc.isZERO()) { continue; } Map> mc = p.contract(ring); if (mc.size() != 1) { continue; } GenSolvablePolynomial pc = null; for (GenPolynomial x : mc.values()) { if (pc != null) { // should not happen logger.info("e = " + e + ", f = " + f + ", ec = " + ec + ", fc = " + fc); logger.info("p = " + p + ", mc = " + mc); throw new RuntimeException("Map.size() != 1: " + mc.size()); } pc = (GenSolvablePolynomial) x; } this.update(ec, fc, pc); } } return; } /** * Reverse variables and relations. Used e.g. in opposite rings. Reverse all * ExpVectors and polynomials of the given relation table and put the * modified relations into this table, i.e. this should be empty. * @param tab a relation table to be reverted and inserted into this. */ @SuppressWarnings("unchecked") public void reverse(RelationTable tab) { if (tab.table.size() == 0) { return; } // assert this.size() == 0 if (table.size() != 0) { logger.error("reverse table not empty"); } int k = -1; if (ring.tord.getEvord2() != 0 && ring.partial) { k = ring.tord.getSplit(); } logger.debug("k split = " + k); //System.out.println("k split = " + k ); for (List key : tab.table.keySet()) { List val = tab.table.get(key); for (Iterator jt = val.iterator(); jt.hasNext();) { ExpVectorPair ep = (ExpVectorPair) jt.next(); ExpVector e = ep.getFirst(); ExpVector f = ep.getSecond(); GenSolvablePolynomial p = (GenSolvablePolynomial) jt.next(); //logger.info("e pre reverse = " + e ); //logger.info("f pre reverse = " + f ); //logger.info("p pre reverse = " + p ); ExpVector ex; ExpVector fx; GenSolvablePolynomial px; boolean change = true; // if relevant vars reversed if (k >= 0) { ex = e.reverse(k); fx = f.reverse(k); int[] ed = ex.dependencyOnVariables(); // = e if (ed.length == 0 || ed[0] >= k) { // k >= 0 change = false; } int[] fd = fx.dependencyOnVariables(); // = f if (fd.length == 0 || fd[0] >= k) { // k >= 0 change = false; } } else { ex = e.reverse(); fx = f.reverse(); } px = (GenSolvablePolynomial) p.reverse(ring); //System.out.println("change = " + change ); if (!change) { this.update(e, f, px); // same order } else { this.update(fx, ex, px); // opposite order //this.update( ex, fx, px ); // same order } } } return; } } /** * TableRelation container for storage and printing in RelationTable. * @author Heinz Kredel */ class TableRelation> implements Serializable { /** * First ExpVector of the data structure. */ public final ExpVector e; /** * Second ExpVector of the data structure. */ public final ExpVector f; /** * GenSolvablePolynomial of the data structure. */ public final GenSolvablePolynomial p; /** * Constructor to setup the data structure. * @param e first term. * @param f second term. * @param p product polynomial. */ public TableRelation(ExpVector e, ExpVector f, GenSolvablePolynomial p) { this.e = e; this.f = f; this.p = p; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer s = new StringBuffer("TableRelation["); s.append("" + e); s.append(" | "); s.append("" + f); s.append(" = "); s.append("" + p); s.append("]"); return s.toString(); } } jas-2.5/src/edu/jas/poly/Monomial.java0000644000175000017500000000260311107626066020073 0ustar giovannigiovanni /* * $Id: Monomial.java 2209 2008-11-15 20:08:23Z kredel $ */ package edu.jas.poly; import java.util.Map; import java.util.SortedMap; import java.util.Iterator; import edu.jas.structure.RingElem; import edu.jas.poly.ExpVector; /** * Monomial class. * Represents pairs of exponent vectors and coefficients. * Adaptor for Map.Entry. * @author Heinz Kredel */ public final class Monomial > { /** * Exponent of monomial. */ public final ExpVector e; /** * Coefficient of monomial. */ public final C c; /** * Constructor of monomial. * @param me a MapEntry. */ public Monomial(Map.Entry me){ this( me.getKey(), me.getValue() ); } /** * Constructor of monomial. * @param e exponent. * @param c coefficient. */ public Monomial(ExpVector e, C c) { this.e = e; this.c = c; } /** * Getter for exponent. * @return exponent. */ public ExpVector exponent() { return e; } /** * Getter for coefficient. * @return coefficient. */ public C coefficient() { return c; } /** * String representation of Monomial. * @see java.lang.Object#toString() */ @Override public String toString() { return c.toString() + " " + e.toString(); } } jas-2.5/src/edu/jas/poly/OrderedModuleList.java0000644000175000017500000001063712004325040021675 0ustar giovannigiovanni/* * $Id: OrderedModuleList.java 4057 2012-07-26 20:35:44Z kredel $ */ package edu.jas.poly; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import edu.jas.structure.RingElem; /** * Ordered list of vectors of polynomials. Mainly for storage and printing / * toString and conversions to other representations. Lists of polynomials in * this list are sorted according to the head terms of the first column. * @author Heinz Kredel */ public class OrderedModuleList> extends ModuleList { /** * Constructor. * @param r polynomial ring factory. * @param l list of list of polynomials. */ public OrderedModuleList(GenPolynomialRing r, List>> l) { super(r, sort(r, ModuleList.padCols(r, l))); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object m) { if (!super.equals(m)) { return false; } OrderedModuleList ml = null; try { ml = (OrderedModuleList) m; } catch (ClassCastException ignored) { } if (ml == null) { return false; } // compare sorted lists // done already in super.equals() return true; } /** * Hash code for OrderedModuleList. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return super.hashCode(); } /** * Sort a list of vectors of polynomials with respect to the ascending order * of the leading Exponent vectors of the first column. The term order is * taken from the ring. * @param r polynomial ring factory. * @param l list of polynomial lists. * @return sorted list of polynomial lists from l. */ @SuppressWarnings("unchecked") public static > List>> sort(GenPolynomialRing r, List>> l) { if (l == null) { return l; } if (l.size() <= 1) { // nothing to sort return l; } final Comparator evc = r.tord.getAscendComparator(); Comparator>> cmp = new Comparator>>() { public int compare(List> l1, List> l2) { int c = 0; for (int i = 0; i < l1.size(); i++) { GenPolynomial p1 = l1.get(i); GenPolynomial p2 = l2.get(i); ExpVector e1 = p1.leadingExpVector(); ExpVector e2 = p2.leadingExpVector(); if (e1 == e2) { continue; } if (e1 == null && e2 != null) { return -1; } if (e1 != null && e2 == null) { return 1; } if (e1 == null || e2 == null) { // for findbugs continue; // cannot happen } if (e1.length() != e2.length()) { if (e1.length() > e2.length()) { return 1; } return -1; } c = evc.compare(e1, e2); if (c != 0) { return c; } } return c; } }; List>[] s = null; try { s = (List>[]) new List[l.size()]; //System.out.println("s.length = " + s.length ); //s = l.toArray(s); does not work //for ( int i = 0; i < l.size(); i++ ) { // s[i] = l.get(i); //} int i = 0; for (List> p : l) { s[i++] = p; } Arrays.>> sort(s, cmp); return new ArrayList>>(Arrays.>> asList(s)); } catch (ClassCastException ok) { System.out.println("Warning: polynomials not sorted"); } return l; // unsorted } } jas-2.5/src/edu/jas/poly/ExpVectorShort.java0000644000175000017500000006033312042051146021251 0ustar giovannigiovanni/* * $Id: ExpVectorShort.java 4270 2012-10-24 20:41:11Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.ArrayList; /** * ExpVectorShort implements exponent vectors for polynomials using arrays of * short as storage unit. This class is used by ExpVector internally, there is * no need to use this class directly. * @see ExpVector * @author Heinz Kredel */ public final class ExpVectorShort extends ExpVector /*implements AbelianGroupElem*/{ /** * The data structure is an array of longs. */ /*package*/final short[] val; /** * Largest short. */ public static final long maxShort = (long) Short.MAX_VALUE / 2; /** * Smallest short. */ public static final long minShort = (long) Short.MIN_VALUE / 2; /** * Constructor for ExpVector. * @param n length of exponent vector. */ public ExpVectorShort(int n) { this(new short[n]); } /** * Constructor for ExpVector. Sets exponent i to e. * @param n length of exponent vector. * @param i index of exponent to be set. * @param e exponent to be set. */ public ExpVectorShort(int n, int i, short e) { this(n); val[i] = e; } /** * Constructor for ExpVector. Sets exponent i to e. * @param n length of exponent vector. * @param i index of exponent to be set. * @param e exponent to be set. */ public ExpVectorShort(int n, int i, long e) { this(n); if (e >= maxShort || e <= minShort) { throw new IllegalArgumentException("exponent to large: " + e); } val[i] = (short) e; } /** * Internal constructor for ExpVector. Sets val. * @param v internal representation array. */ protected ExpVectorShort(short[] v) { super(); val = v; } /** * Constructor for ExpVector. Sets val, converts from long array. * @param v long representation array. */ public ExpVectorShort(long[] v) { this(v.length); for (int i = 0; i < v.length; i++) { if (v[i] >= maxShort || v[i] <= minShort) { throw new IllegalArgumentException("exponent to large: " + v[i]); } val[i] = (short) v[i]; } } /** * Constructor for ExpVector. Converts a String representation to an * ExpVector. Accepted format = (1,2,3,4,5,6,7). * @param s String representation. */ public ExpVectorShort(String s) throws NumberFormatException { super(); // first format = (1,2,3,4,5,6,7) List exps = new ArrayList(); s = s.trim(); int b = s.indexOf('('); int e = s.indexOf(')', b + 1); String teil; int k; short a; if (b >= 0 && e >= 0) { b++; while ((k = s.indexOf(',', b)) >= 0) { teil = s.substring(b, k); a = Short.parseShort(teil); exps.add(Short.valueOf(a)); b = k + 1; } if (b <= e) { teil = s.substring(b, e); a = Short.parseShort(teil); exps.add(Short.valueOf(a)); } int length = exps.size(); val = new short[length]; for (int j = 0; j < length; j++) { val[j] = exps.get(j).shortValue(); } } else { // not implemented val = null; // length = -1; //Vector names = new Vector(); //vars = s; } } /** * Clone this. * @see java.lang.Object#clone() */ @Override public ExpVectorShort copy() { short[] w = new short[val.length]; System.arraycopy(val, 0, w, 0, val.length); return new ExpVectorShort(w); } /** * Get the exponent vector. * @return val as long. */ @Override /*package*/long[] getVal() { long v[] = new long[val.length]; for (int i = 0; i < val.length; i++) { v[i] = val[i]; } return v; } /** * Get the exponent at position i. * @param i position. * @return val[i]. */ @Override public long getVal(int i) { return val[i]; } /** * Set the exponent at position i to e. * @param i * @param e * @return old val[i]. */ @Override protected long setVal(int i, long e) { short x = val[i]; if (e >= maxShort || e <= minShort) { throw new IllegalArgumentException("exponent to large: " + e); } val[i] = (short) e; hash = 0; // beware of race condition return x; } /** * Set the exponent at position i to e. * @param i * @param e * @return old val[i]. */ protected short setVal(int i, short e) { short x = val[i]; val[i] = e; hash = 0; // beware of race condition return x; } /** * Get the length of this exponent vector. * @return val.length. */ @Override public int length() { return val.length; } /** * Extend variables. Used e.g. in module embedding. Extend this by i * elements and set val[j] to e. * @param i number of elements to extend. * @param j index of element to be set. * @param e new exponent for val[j]. * @return extended exponent vector. */ @Override public ExpVectorShort extend(int i, int j, long e) { short[] w = new short[val.length + i]; System.arraycopy(val, 0, w, i, val.length); if (j >= i) { throw new IllegalArgumentException("i " + i + " <= j " + j + " invalid"); } if (e >= maxShort || e <= minShort) { throw new IllegalArgumentException("exponent to large: " + e); } w[j] = (short) e; return new ExpVectorShort(w); } /** * Extend lower variables. Extend this by i lower elements and set val[j] to * e. * @param i number of elements to extend. * @param j index of element to be set. * @param e new exponent for val[j]. * @return extended exponent vector. */ @Override public ExpVectorShort extendLower(int i, int j, long e) { short[] w = new short[val.length + i]; System.arraycopy(val, 0, w, 0, val.length); if (j >= i) { throw new IllegalArgumentException("i " + i + " <= j " + j + " invalid"); } w[val.length + j] = (short) e; return new ExpVectorShort(w); } /** * Contract variables. Used e.g. in module embedding. Contract this to len * elements. * @param i position of first element to be copied. * @param len new length. * @return contracted exponent vector. */ @Override public ExpVectorShort contract(int i, int len) { if (i + len > val.length) { throw new IllegalArgumentException("len " + len + " > val.len " + val.length); } short[] w = new short[len]; System.arraycopy(val, i, w, 0, len); return new ExpVectorShort(w); } /** * Reverse variables. Used e.g. in opposite rings. * @return reversed exponent vector. */ @Override public ExpVectorShort reverse() { short[] w = new short[val.length]; for (int i = 0; i < val.length; i++) { w[i] = val[val.length - 1 - i]; } return new ExpVectorShort(w); } /** * Reverse j variables. Used e.g. in opposite rings. Reverses the first j-1 * variables, the rest is unchanged. * @param j index of first variable not reversed. * @return reversed exponent vector. */ @Override public ExpVectorShort reverse(int j) { if (j <= 0 || j > val.length) { return this; } short[] w = new short[val.length]; for (int i = 0; i < j; i++) { w[i] = val[j - 1 - i]; } // copy rest for (int i = j; i < val.length; i++) { w[i] = val[i]; } return new ExpVectorShort(w); } /** * Combine with ExpVector. Combine this with the other ExpVector V. * @param V the other exponent vector. * @return combined exponent vector. */ @Override public ExpVectorShort combine(ExpVector V) { if (V == null || V.length() == 0) { return this; } ExpVectorShort Vi = (ExpVectorShort) V; if (val.length == 0) { return Vi; } short[] w = new short[val.length + Vi.val.length]; System.arraycopy(val, 0, w, 0, val.length); System.arraycopy(Vi.val, 0, w, val.length, Vi.val.length); return new ExpVectorShort(w); } /** * Get the string representation. * @see java.lang.Object#toString() */ @Override public String toString() { return super.toString() + ":short"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof ExpVectorShort)) { return false; } ExpVectorShort b = (ExpVectorShort) B; int t = this.invLexCompareTo(b); //System.out.println("equals: this = " + this + " B = " + B + " t = " + t); return (0 == t); } /** * hashCode for this exponent vector. * @see java.lang.Object#hashCode() Only for findbugs. */ @Override public int hashCode() { return super.hashCode(); } /** * ExpVector absolute value. * @return abs(this). */ @Override public ExpVectorShort abs() { short[] u = val; short[] w = new short[u.length]; for (int i = 0; i < u.length; i++) { if (u[i] >= 0L) { w[i] = u[i]; } else { w[i] = (short) (-u[i]); } } return new ExpVectorShort(w); //return EVABS(this); } /** * ExpVector negate. * @return -this. */ @Override public ExpVectorShort negate() { short[] u = val; short[] w = new short[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (short) (-u[i]); } return new ExpVectorShort(w); // return EVNEG(this); } /** * ExpVector summation. * @param V * @return this+V. */ @Override public ExpVectorShort sum(ExpVector V) { short[] u = val; short[] v = ((ExpVectorShort) V).val; short[] w = new short[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (short) (u[i] + v[i]); } return new ExpVectorShort(w); // return EVSUM(this, V); } /** * ExpVector subtract. Result may have negative entries. * @param V * @return this-V. */ @Override public ExpVectorShort subtract(ExpVector V) { short[] u = val; short[] v = ((ExpVectorShort) V).val; short[] w = new short[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (short) (u[i] - v[i]); } return new ExpVectorShort(w); //return EVDIF(this, V); } /** * ExpVector substitution. Clone and set exponent to d at position i. * @param i position. * @param d new exponent. * @return substituted ExpVector. */ public ExpVectorShort subst(int i, short d) { ExpVectorShort V = this.copy(); @SuppressWarnings("unused") long e = V.setVal(i, d); return V; //return EVSU(this, i, d); } /** * ExpVector substitution. Clone and set exponent to d at position i. * @param i position. * @param d new exponent. * @return substituted ExpVector. */ @Override public ExpVectorShort subst(int i, long d) { ExpVectorShort V = this.copy(); @SuppressWarnings("unused") long e = V.setVal(i, d); return V; //return EVSU(this, i, d); } /** * ExpVector signum. * @return 0 if this is zero, -1 if some entry is negative, 1 if no entry is * negative and at least one entry is positive. */ @Override public int signum() { int t = 0; short[] u = val; for (int i = 0; i < u.length; i++) { if (u[i] < 0) { return -1; } if (u[i] > 0) { t = 1; } } return t; //return EVSIGN(this); } /** * ExpVector total degree. * @return sum of all exponents. */ @Override public long totalDeg() { long t = 0; short[] u = val; // U.val; for (int i = 0; i < u.length; i++) { t += u[i]; } return t; //return EVTDEG(this); } /** * ExpVector maximal degree. * @return maximal exponent. */ @Override public long maxDeg() { long t = 0; short[] u = val; for (int i = 0; i < u.length; i++) { if (u[i] > t) { t = u[i]; } } return t; //return EVMDEG(this); } /** * ExpVector weighted degree. * @param w weights. * @return weighted sum of all exponents. */ @Override public long weightDeg(long[][] w) { if (w == null || w.length == 0) { return totalDeg(); // assume weight 1 } long t = 0; short[] u = val; for (int j = 0; j < w.length; j++) { long[] wj = w[j]; for (int i = 0; i < u.length; i++) { t += wj[i] * u[i]; } } return t; //return EVWDEG( w, this ); } /** * ExpVector least common multiple. * @param V * @return component wise maximum of this and V. */ @Override public ExpVectorShort lcm(ExpVector V) { short[] u = val; short[] v = ((ExpVectorShort) V).val; short[] w = new short[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (u[i] >= v[i] ? u[i] : v[i]); } return new ExpVectorShort(w); //return EVLCM(this, V); } /** * ExpVector greatest common divisor. * @param V * @return component wise minimum of this and V. */ @Override public ExpVectorShort gcd(ExpVector V) { short[] u = val; short[] v = ((ExpVectorShort) V).val; short[] w = new short[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (u[i] <= v[i] ? u[i] : v[i]); } return new ExpVectorShort(w); //return EVGCD(this, V); } /** * ExpVector dependency on variables. * @return array of indices where val has positive exponents. */ @Override public int[] dependencyOnVariables() { short[] u = val; int l = 0; for (int i = 0; i < u.length; i++) { if (u[i] > 0) { l++; } } int[] dep = new int[l]; if (l == 0) { return dep; } int j = 0; for (int i = 0; i < u.length; i++) { if (u[i] > 0) { dep[j] = i; j++; } } return dep; } /** * ExpVector multiple test. Test if this is component wise greater or equal * to V. * @param V * @return true if this is a multiple of V, else false. */ @Override public boolean multipleOf(ExpVector V) { short[] u = val; short[] v = ((ExpVectorShort) V).val; boolean t = true; for (int i = 0; i < u.length; i++) { if (u[i] < v[i]) { return false; } } return t; //return EVMT(this, V); } /** * ExpVector compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int compareTo(ExpVector V) { return this.invLexCompareTo(V); } /** * ExpVector inverse lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invLexCompareTo(ExpVector V) { short[] u = val; short[] v = ((ExpVectorShort) V).val; int t = 0; for (int i = 0; i < u.length; i++) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVILCP(this, V); } /** * ExpVector inverse lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invLexCompareTo(ExpVector V, int begin, int end) { short[] u = val; short[] v = ((ExpVectorShort) V).val; int t = 0; for (int i = begin; i < end; i++) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVILCP(this, V, begin, end); } /** * ExpVector inverse graded lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invGradCompareTo(ExpVector V) { short[] u = val; short[] v = ((ExpVectorShort) V).val; int t = 0; int i; for (i = 0; i < u.length; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j < u.length; j++) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVIGLC(this, V); } /** * ExpVector inverse graded lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invGradCompareTo(ExpVector V, int begin, int end) { short[] u = val; short[] v = ((ExpVectorShort) V).val; int t = 0; int i; for (i = begin; i < end; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j < end; j++) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVIGLC(this, V, begin, end); } /** * ExpVector reverse inverse lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvLexCompareTo(ExpVector V) { short[] u = val; short[] v = ((ExpVectorShort) V).val; int t = 0; for (int i = u.length - 1; i >= 0; i--) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVRILCP(this, V); } /** * ExpVector reverse inverse lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvLexCompareTo(ExpVector V, int begin, int end) { short[] u = val; short[] v = ((ExpVectorShort) V).val; int t = 0; for (int i = end - 1; i >= begin; i--) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVRILCP(this, V, begin, end); } /** * ExpVector reverse inverse graded compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvGradCompareTo(ExpVector V) { short[] u = val; short[] v = ((ExpVectorShort) V).val; int t = 0; int i; for (i = u.length - 1; i >= 0; i--) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j >= 0; j--) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVRIGLC(this, V); } /** * ExpVector reverse inverse graded compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvGradCompareTo(ExpVector V, int begin, int end) { short[] u = val; short[] v = ((ExpVectorShort) V).val; int t = 0; int i; for (i = end - 1; i >= begin; i--) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j >= begin; j--) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVRIGLC(this, V, begin, end); } /** * ExpVector inverse weighted lexicographical compareTo. * @param w weight array. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invWeightCompareTo(long[][] w, ExpVector V) { short[] u = val; short[] v = ((ExpVectorShort) V).val; int t = 0; int i; for (i = 0; i < u.length; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } for (int k = 0; k < w.length; k++) { long[] wk = w[k]; long up = 0; long vp = 0; for (int j = i; j < u.length; j++) { up += wk[j] * u[j]; vp += wk[j] * v[j]; } if (up > vp) { return 1; } else if (up < vp) { return -1; } } return t; //return EVIWLC(w, this, V); } /** * ExpVector inverse weighted lexicographical compareTo. * @param w weight array. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invWeightCompareTo(long[][] w, ExpVector V, int begin, int end) { short[] u = val; short[] v = ((ExpVectorShort) V).val; int t = 0; int i; for (i = begin; i < end; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } for (int k = 0; k < w.length; k++) { long[] wk = w[k]; long up = 0; long vp = 0; for (int j = i; j < end; j++) { up += wk[j] * u[j]; vp += wk[j] * v[j]; } if (up > vp) { return 1; } else if (up < vp) { return -1; } } return t; //return EVIWLC(w, this, V, begin, end); } } jas-2.5/src/edu/jas/poly/GenSolvablePolynomial.java0000644000175000017500000003452112016422422022557 0ustar giovannigiovanni/* * $Id: GenSolvablePolynomial.java 4142 2012-08-26 13:30:59Z kredel $ */ package edu.jas.poly; import java.util.Set; import java.util.Map; import java.util.SortedMap; import org.apache.log4j.Logger; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * GenSolvablePolynomial generic solvable polynomials implementing RingElem. * n-variate ordered solvable polynomials over C. * Objects of this class are intended to be immutable. * The implementation is based on TreeMap respectively SortedMap * from exponents to coefficients by extension of GenPolybomial. * Only the coefficients are modeled with generic types, * the exponents are fixed to ExpVector with long entries * (this will eventually be changed in the future). * @param coefficient type * @author Heinz Kredel */ public class GenSolvablePolynomial> extends GenPolynomial { //not possible: implements RingElem< GenSolvablePolynomial > { /** The factory for the solvable polynomial ring. * Hides super.ring. */ public final GenSolvablePolynomialRing< C > ring; private static final Logger logger = Logger.getLogger(GenSolvablePolynomial.class); private final boolean debug = false; //logger.isDebugEnabled(); /** * Constructor for zero GenSolvablePolynomial. * @param r solvable polynomial ring factory. */ public GenSolvablePolynomial(GenSolvablePolynomialRing< C > r) { super(r); ring = r; } /** * Constructor for GenSolvablePolynomial. * @param r solvable polynomial ring factory. * @param c coefficient. * @param e exponent. */ public GenSolvablePolynomial(GenSolvablePolynomialRing< C > r, C c, ExpVector e) { this(r); if ( c != null && ! c.isZERO() ) { val.put(e,c); } } /** * Constructor for GenSolvablePolynomial. * @param r solvable polynomial ring factory. * @param c coefficient. */ public GenSolvablePolynomial(GenSolvablePolynomialRing< C > r, C c) { this(r,c,r.evzero); } /** * Constructor for GenSolvablePolynomial. * @param r solvable polynomial ring factory. * @param v the SortedMap of some other (solvable) polynomial. */ protected GenSolvablePolynomial(GenSolvablePolynomialRing< C > r, SortedMap v) { this(r); val.putAll( v ); // assume no zero coefficients } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public GenSolvablePolynomialRing factory() { return ring; } /** * Clone this GenSolvablePolynomial. * @see java.lang.Object#clone() */ @Override public GenSolvablePolynomial copy() { //return ring.copy(this); return new GenSolvablePolynomial(ring,this.val); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof GenSolvablePolynomial)) { return false; } return super.equals(B); } /** * GenSolvablePolynomial multiplication. * @param Bp GenSolvablePolynomial. * @return this*Bp, where * denotes solvable multiplication. */ public GenSolvablePolynomial multiply(GenSolvablePolynomial Bp) { if ( Bp == null || Bp.isZERO() ) { return ring.getZERO(); } if ( this.isZERO() ) { return this; } assert (ring.nvar == Bp.ring.nvar); if ( debug ) { logger.debug("ring = " + ring); } ExpVector Z = ring.evzero; GenSolvablePolynomial Cp = ring.getZERO().copy(); GenSolvablePolynomial zero = ring.getZERO().copy(); C one = ring.getONECoefficient(); GenSolvablePolynomial C1 = null; GenSolvablePolynomial C2 = null; Map A = val; Map B = Bp.val; Set> Bk = B.entrySet(); for ( Map.Entry y: A.entrySet() ) { C a = y.getValue(); ExpVector e = y.getKey(); if ( debug ) logger.debug("e = " + e); int[] ep = e.dependencyOnVariables(); int el1 = ring.nvar + 1; if ( ep.length > 0 ) { el1 = ep[0]; } int el1s = ring.nvar + 1 - el1; for ( Map.Entry x: Bk ) { C b = x.getValue(); ExpVector f = x.getKey(); if ( debug ) logger.debug("f = " + f); int[] fp = f.dependencyOnVariables(); int fl1 = 0; if ( fp.length > 0 ) { fl1 = fp[fp.length-1]; } int fl1s = ring.nvar + 1 - fl1; if ( debug ) { logger.debug("el1s = " + el1s + " fl1s = " + fl1s); } GenSolvablePolynomial Cs = null; if ( el1s <= fl1s ) { // symmetric ExpVector g = e.sum(f); //if ( debug ) logger.debug("g = " + g); Cs = (GenSolvablePolynomial)zero.sum( one, g ); // symmetric! //Cs = new GenSolvablePolynomial(ring,one,g); // symmetric! } else { // unsymmetric // split e = e1 * e2, f = f1 * f2 ExpVector e1 = e.subst(el1,0); ExpVector e2 = Z.subst(el1,e.getVal(el1)); ExpVector e4; ExpVector f1 = f.subst(fl1,0); ExpVector f2 = Z.subst(fl1,f.getVal(fl1)); //if ( debug ) logger.debug("e1 = " + e1 + " e2 = " + e2); //if ( debug ) logger.debug("f1 = " + f1 + " f2 = " + f2); TableRelation rel = ring.table.lookup(e2,f2); //logger.info("relation = " + rel); Cs = rel.p; //ring.copy( rel.p ); // do not clone() if ( rel.f != null ) { C2 = (GenSolvablePolynomial)zero.sum( one, rel.f ); Cs = Cs.multiply( C2 ); if ( rel.e == null ) { e4 = e2; } else { e4 = e2.subtract( rel.e ); } ring.table.update(e4,f2,Cs); } if ( rel.e != null ) { C1 = (GenSolvablePolynomial)zero.sum( one, rel.e ); Cs = C1.multiply( Cs ); ring.table.update(e2,f2,Cs); } if ( !f1.isZERO() ) { C2 = (GenSolvablePolynomial)zero.sum( one, f1 ); Cs = Cs.multiply( C2 ); //ring.table.update(?,f1,Cs) } if ( !e1.isZERO() ) { C1 = (GenSolvablePolynomial)zero.sum( one, e1 ); Cs = C1.multiply( Cs ); //ring.table.update(e1,?,Cs) } } //C c = a.multiply(b); Cs = Cs.multiply(a,b); // now non-symmetric // Cs.multiply(c); is symmetric! //if ( debug ) logger.debug("Cs = " + Cs); Cp = (GenSolvablePolynomial)Cp.sum( Cs ); } } return Cp; } /** * GenSolvablePolynomial left and right multiplication. Product with * two polynomials. * @param S GenSolvablePolynomial. * @param T GenSolvablePolynomial. * @return S*this*T. */ public GenSolvablePolynomial multiply(GenSolvablePolynomial S, GenSolvablePolynomial T) { if ( S.isZERO() || T.isZERO() || this.isZERO() ) { return ring.getZERO(); } if ( S.isONE() ) { return multiply(T); } if ( T.isONE() ) { return S.multiply(this); } return S.multiply(this).multiply(T); } /** * GenSolvablePolynomial multiplication. * Product with coefficient ring element. * @param b coefficient. * @return this*b, where * is usual multiplication. */ @Override public GenSolvablePolynomial multiply(C b) { GenSolvablePolynomial Cp = ring.getZERO().copy(); if ( b == null || b.isZERO() ) { return Cp; } Map Cm = Cp.val; //getMap(); Map Am = val; for ( Map.Entry y: Am.entrySet() ) { ExpVector e = y.getKey(); C a = y.getValue(); C c = a.multiply(b); if ( !c.isZERO() ) { Cm.put( e, c ); } } return Cp; } /** * GenSolvablePolynomial left and right multiplication. * Product with coefficient ring element. * @param b coefficient. * @param c coefficient. * @return b*this*c, where * is coefficient multiplication. */ public GenSolvablePolynomial multiply(C b, C c) { GenSolvablePolynomial Cp = ring.getZERO().copy(); if ( b == null || b.isZERO() ) { return Cp; } if ( c == null || c.isZERO() ) { return Cp; } Map Cm = Cp.val; //getMap(); Map Am = val; for ( Map.Entry y: Am.entrySet() ) { ExpVector e = y.getKey(); C a = y.getValue(); C d = b.multiply(a).multiply(c); if ( !d.isZERO() ) { Cm.put( e, d ); } } return Cp; } /** * GenSolvablePolynomial multiplication. * Product with exponent vector. * @param e exponent. * @return this * xe, * where * denotes solvable multiplication. */ @Override public GenSolvablePolynomial multiply(ExpVector e) { if ( e == null || e.isZERO() ) { return this; } C b = ring.getONECoefficient(); return multiply(b, e); } /** * GenSolvablePolynomial left and right multiplication. * Product with exponent vector. * @param e exponent. * @param f exponent. * @return xe * this * xf, * where * denotes solvable multiplication. */ public GenSolvablePolynomial multiply(ExpVector e, ExpVector f) { if ( e == null || e.isZERO() ) { return this; } if ( f == null || f.isZERO() ) { return this; } C b = ring.getONECoefficient(); return multiply(b, e, b, f); } /** * GenSolvablePolynomial multiplication. * Product with ring element and exponent vector. * @param b coefficient. * @param e exponent. * @return this * b xe, * where * denotes solvable multiplication. */ @Override public GenSolvablePolynomial multiply(C b, ExpVector e) { if ( b == null || b.isZERO() ) { return ring.getZERO(); } GenSolvablePolynomial Cp = new GenSolvablePolynomial(ring,b,e); return multiply(Cp); } /** * GenSolvablePolynomial left and right multiplication. * Product with ring element and exponent vector. * @param b coefficient. * @param e exponent. * @param c coefficient. * @param f exponent. * @return b xe * this * c xf, * where * denotes solvable multiplication. */ public GenSolvablePolynomial multiply(C b, ExpVector e, C c, ExpVector f) { if ( b == null || b.isZERO() ) { return ring.getZERO(); } if ( c == null || c.isZERO() ) { return ring.getZERO(); } GenSolvablePolynomial Cp = new GenSolvablePolynomial(ring,b,e); GenSolvablePolynomial Dp = new GenSolvablePolynomial(ring,c,f); return multiply(Cp,Dp); } /** * GenSolvablePolynomial multiplication. * Left product with ring element and exponent vector. * @param b coefficient. * @param e exponent. * @return b xe * this, * where * denotes solvable multiplication. */ public GenSolvablePolynomial multiplyLeft(C b, ExpVector e) { if ( b == null || b.isZERO() ) { return ring.getZERO(); } GenSolvablePolynomial Cp = new GenSolvablePolynomial(ring,b,e); return Cp.multiply(this); } /** * GenSolvablePolynomial multiplication. * Left product with exponent vector. * @param e exponent. * @return xe * this, * where * denotes solvable multiplication. */ public GenSolvablePolynomial multiplyLeft(ExpVector e) { if ( e == null || e.isZERO() ) { return this; } C b = ring.getONECoefficient(); GenSolvablePolynomial Cp = new GenSolvablePolynomial(ring,b,e); return Cp.multiply(this); } /** * GenSolvablePolynomial multiplication. * Left product with coefficient ring element. * @param b coefficient. * @return b*this, where * is usual multiplication. */ public GenSolvablePolynomial multiplyLeft(C b) { GenSolvablePolynomial Cp = ring.getZERO().copy(); if ( b == null || b.isZERO() ) { return Cp; } Map Cm = Cp.val; //getMap(); Map Am = val; for ( Map.Entry y: Am.entrySet() ) { ExpVector e = y.getKey(); C a = y.getValue(); C c = b.multiply(a); if ( !c.isZERO() ) { Cm.put( e, c ); } } return Cp; } /** * GenSolvablePolynomial multiplication. * Left product with 'monimial'. * @param m 'monoial'. * @return m * this, * where * denotes solvable multiplication. */ public GenSolvablePolynomial multiplyLeft(Map.Entry m) { if ( m == null ) { return ring.getZERO(); } return multiplyLeft( m.getValue(), m.getKey() ); } } jas-2.5/src/edu/jas/poly/Polynomial.java0000644000175000017500000000464111014364036020440 0ustar giovannigiovanni/* * $Id: Polynomial.java 1801 2008-05-19 20:50:39Z kredel $ */ package edu.jas.poly; import java.util.Map; import java.util.Iterator; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Polynomial interface. * Adds methods specific to polynomials. * @param ring element type * @author Heinz Kredel */ public interface Polynomial> extends RingElem< Polynomial > { /** * Leading monomial. * @return first map entry. */ public Map.Entry leadingMonomial(); /** * Leading exponent vector. * @return first exponent. */ public ExpVector leadingExpVector(); /** * Leading base coefficient. * @return first coefficient. */ public C leadingBaseCoefficient(); /** * Trailing base coefficient. * @return coefficient of constant term. */ public C trailingBaseCoefficient(); /** * Reductum. * @return this - leading monomial. */ public Polynomial reductum(); /** * Extend variables. Used e.g. in module embedding. * Extend all ExpVectors by i elements and multiply by x_j^k. * @param pfac extended polynomial ring factory (by i variables). * @param j index of variable to be used for multiplication. * @param k exponent for x_j. * @return extended polynomial. */ public Polynomial extend(PolynomialRing pfac, int j, long k); /** * Contract variables. Used e.g. in module embedding. * remove i elements of each ExpVector. * @param pfac contracted polynomial ring factory (by i variables). * @return Map of exponents and contracted polynomials. * Note: could return SortedMap */ public Map> contract(PolynomialRing pfac); /** * Reverse variables. Used e.g. in opposite rings. * @return polynomial with reversed variables. */ public Polynomial reverse(PolynomialRing oring); /** * Iterator over coefficients. * @return val.values().iterator(). */ public Iterator coefficientIterator(); /** * Iterator over exponents. * @return val.keySet().iterator(). */ public Iterator exponentIterator(); /** * Iterator over monomials. * @return a PolyIterator. */ public Iterator> monomialIterator(); } jas-2.5/src/edu/jas/poly/PolynomialComparator.java0000644000175000017500000000372712000527236022473 0ustar giovannigiovanni/* * $Id: PolynomialComparator.java 3994 2012-07-15 11:50:54Z kredel $ */ package edu.jas.poly; import java.io.Serializable; import java.util.Comparator; import edu.jas.structure.RingElem; /** * Comparator for polynomials. * @param coefficient type * @author Heinz Kredel. */ public class PolynomialComparator> implements Serializable, Comparator> { public final TermOrder tord; public final boolean reverse; /** * Constructor. * @param t TermOrder. * @param reverse flag if reverse ordering is requested. */ public PolynomialComparator(TermOrder t, boolean reverse) { tord = t; this.reverse = reverse; } /** * Compare polynomials. * @param p1 first polynomial. * @param p2 second polynomial. * @return 0 if ( p1 == p2 ), -1 if ( p1 < p2 ) and +1 if ( p1 > p2 ). */ public int compare(GenPolynomial p1, GenPolynomial p2) { // check if p1.tord = p2.tord = tord ? int s = p1.compareTo(p2); //System.out.println("p1.compareTo(p2) = " + s); if (reverse) { return -s; } return s; } /** * Equals test of comparator. * @param o other object. * @return true if this = o, else false. */ @Override public boolean equals(Object o) { PolynomialComparator pc = null; try { pc = (PolynomialComparator) o; } catch (ClassCastException ignored) { return false; } if (pc == null) { return false; } return tord.equals(pc.tord); } /** * Hash code for this PolynomialComparator. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return tord.hashCode(); } /** * toString. */ @Override public String toString() { return "PolynomialComparator(" + tord + ")"; } } jas-2.5/src/edu/jas/poly/AlgebraicNumberRing.java0000644000175000017500000004222012004325040022142 0ustar giovannigiovanni/* * $Id: AlgebraicNumberRing.java 4057 2012-07-26 20:35:44Z kredel $ */ package edu.jas.poly; import java.io.Reader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.Scripting; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.util.CartesianProduct; import edu.jas.util.CartesianProductInfinite; /** * Algebraic number factory class based on GenPolynomial with RingElem * interface. Objects of this class are immutable. * @author Heinz Kredel */ public class AlgebraicNumberRing> implements RingFactory>, Iterable> { /** * Ring part of the factory data structure. */ public final GenPolynomialRing ring; /** * Module part of the factory data structure. */ public final GenPolynomial modul; /** * Indicator if this ring is a field */ protected int isField = -1; // initially unknown private static final Logger logger = Logger.getLogger(AlgebraicNumberRing.class); // private final boolean debug = logger.isDebugEnabled(); /** * The constructor creates a AlgebraicNumber factory object from a * GenPolynomial objects module. * @param m module GenPolynomial. */ public AlgebraicNumberRing(GenPolynomial m) { ring = m.ring; modul = m; // assert m != 0 if (ring.nvar > 1) { throw new IllegalArgumentException("only univariate polynomials allowed"); } } /** * The constructor creates a AlgebraicNumber factory object from a * GenPolynomial objects module. * @param m module GenPolynomial. * @param isField indicator if m is prime. */ public AlgebraicNumberRing(GenPolynomial m, boolean isField) { ring = m.ring; modul = m; // assert m != 0 this.isField = (isField ? 1 : 0); if (ring.nvar > 1) { throw new IllegalArgumentException("only univariate polynomials allowed"); } } /** * Get the module part. * @return modul. */ public GenPolynomial getModul() { return modul; } /** * Copy AlgebraicNumber element c. * @param c algebraic number to copy. * @return a copy of c. */ public AlgebraicNumber copy(AlgebraicNumber c) { return new AlgebraicNumber(this, c.val); } /** * Get the zero element. * @return 0 as AlgebraicNumber. */ public AlgebraicNumber getZERO() { return new AlgebraicNumber(this, ring.getZERO()); } /** * Get the one element. * @return 1 as AlgebraicNumber. */ public AlgebraicNumber getONE() { return new AlgebraicNumber(this, ring.getONE()); } /** * Get the generating element. * @return alpha as AlgebraicNumber. */ public AlgebraicNumber getGenerator() { return new AlgebraicNumber(this, ring.univariate(0)); } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List> gc = ring.generators(); List> gens = new ArrayList>(gc.size()); for (GenPolynomial g : gc) { gens.add(new AlgebraicNumber(this, g)); } return gens; } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return ring.coFac.isFinite(); } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return ring.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return ring.isAssociative(); } /** * Query if this ring is a field. * @return true if modul is prime, else false. */ public boolean isField() { if (isField > 0) { return true; } if (isField == 0) { return false; } if (!ring.coFac.isField()) { isField = 0; return false; } return false; } /** * Set field property of this ring. * @param field true, if this ring is determined to be a field, false, if it * is determined that it is not a field. */ public void setField(boolean field) { if (isField > 0 && field) { return; } if (isField == 0 && !field) { return; } if (field) { isField = 1; } else { isField = 0; } return; } /** * Get the internal field indicator. * @return internal field indicator. */ public int getField() { return isField; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return ring.characteristic(); } /** * Get a AlgebraicNumber element from a BigInteger value. * @param a BigInteger. * @return a AlgebraicNumber. */ public AlgebraicNumber fillFromInteger(java.math.BigInteger a) { if (characteristic().signum() == 0) { return new AlgebraicNumber(this, ring.fromInteger(a)); } java.math.BigInteger p = characteristic(); java.math.BigInteger b = a; GenPolynomial v = ring.getZERO(); GenPolynomial x = ring.univariate(0, 1L); GenPolynomial t = ring.getONE(); do { java.math.BigInteger[] qr = b.divideAndRemainder(p); java.math.BigInteger q = qr[0]; java.math.BigInteger r = qr[1]; //System.out.println("q = " + q + ", r = " +r); GenPolynomial rp = ring.fromInteger(r); v = v.sum(t.multiply(rp)); t = t.multiply(x); b = q; } while (!b.equals(java.math.BigInteger.ZERO)); AlgebraicNumber an = new AlgebraicNumber(this, v); logger.info("fill(" + a + ") = " + v + ", mod: " + an); //RuntimeException e = new RuntimeException("hihihi"); //e.printStackTrace(); return an; } /** * Get a AlgebraicNumber element from a long value. * @param a long. * @return a AlgebraicNumber. */ public AlgebraicNumber fillFromInteger(long a) { return fillFromInteger(new java.math.BigInteger("" + a)); } /** * Get a AlgebraicNumber element from a BigInteger value. * @param a BigInteger. * @return a AlgebraicNumber. */ public AlgebraicNumber fromInteger(java.math.BigInteger a) { return new AlgebraicNumber(this, ring.fromInteger(a)); } /** * Get a AlgebraicNumber element from a long value. * @param a long. * @return a AlgebraicNumber. */ public AlgebraicNumber fromInteger(long a) { return new AlgebraicNumber(this, ring.fromInteger(a)); // if ( characteristic().signum() == 0 ) { // } // return fromInteger( new java.math.BigInteger(""+a) ); } /** * Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { return "AlgebraicNumberRing[ " + modul.toString() + " | isField=" + isField + " :: " + ring.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { StringBuffer s = new StringBuffer(); s.append("AN("); s.append(modul.toScript()); switch (Scripting.getLang()) { case Ruby: s.append((isField() ? ",true" : ",false")); break; case Python: default: s.append((isField() ? ",True" : ",False")); } s.append(","); s.append(ring.toScript()); s.append(")"); return s.toString(); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object b) { if (!(b instanceof AlgebraicNumberRing)) { return false; } AlgebraicNumberRing a = null; try { a = (AlgebraicNumberRing) b; } catch (ClassCastException e) { } if (a == null) { return false; } return modul.equals(a.modul); } /** * Hash code for this AlgebraicNumber. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 37 * modul.hashCode() + ring.hashCode(); } /** * AlgebraicNumber random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random integer mod modul. */ public AlgebraicNumber random(int n) { GenPolynomial x = ring.random(n).monic(); return new AlgebraicNumber(this, x); } /** * AlgebraicNumber random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random integer mod modul. */ public AlgebraicNumber random(int n, Random rnd) { GenPolynomial x = ring.random(n, rnd).monic(); return new AlgebraicNumber(this, x); } /** * Parse AlgebraicNumber from String. * @param s String. * @return AlgebraicNumber from s. */ public AlgebraicNumber parse(String s) { GenPolynomial x = ring.parse(s); return new AlgebraicNumber(this, x); } /** * Parse AlgebraicNumber from Reader. * @param r Reader. * @return next AlgebraicNumber from r. */ public AlgebraicNumber parse(Reader r) { GenPolynomial x = ring.parse(r); return new AlgebraicNumber(this, x); } /** * AlgebraicNumber chinese remainder algorithm. Assert deg(c.modul) >= * deg(a.modul) and c.modul * a.modul = this.modul. * @param c AlgebraicNumber. * @param ci inverse of c.modul in ring of a. * @param a other AlgebraicNumber. * @return S, with S mod c.modul == c and S mod a.modul == a. */ public AlgebraicNumber chineseRemainder(AlgebraicNumber c, AlgebraicNumber ci, AlgebraicNumber a) { if (true) { // debug if (c.ring.modul.compareTo(a.ring.modul) < 1) { System.out.println("AlgebraicNumber error " + c + ", " + a); } } AlgebraicNumber b = new AlgebraicNumber(a.ring, c.val); // c mod a.modul // c( tbcf(a.modul) ) if deg(a.modul)==1 AlgebraicNumber d = a.subtract(b); // a-c mod a.modul if (d.isZERO()) { return new AlgebraicNumber(this, c.val); } b = d.multiply(ci); // b = (a-c)*ci mod a.modul // (c.modul*b)+c mod this.modul = c mod c.modul = // (c.modul*ci*(a-c)+c) mod a.modul = a mod a.modul GenPolynomial s = c.ring.modul.multiply(b.val); s = s.sum(c.val); return new AlgebraicNumber(this, s); } /** * AlgebraicNumber interpolation algorithm. Assert deg(c.modul) >= * deg(A.modul) and c.modul * A.modul = this.modul. Special case with * deg(A.modul) == 1. Similar algorithm as chinese remainder algortihm. * @param c AlgebraicNumber. * @param ci inverse of (c.modul)(a) in ring of A. * @param am trailing base coefficient of modul of other AlgebraicNumber A. * @param a value of other AlgebraicNumber A. * @return S, with S(c) == c and S(A) == a. */ public AlgebraicNumber interpolate(AlgebraicNumber c, C ci, C am, C a) { C b = PolyUtil. evaluateMain(ring.coFac /*a*/, c.val, am); // c mod a.modul // c( tbcf(a.modul) ) if deg(a.modul)==1 C d = a.subtract(b); // a-c mod a.modul if (d.isZERO()) { return new AlgebraicNumber(this, c.val); } b = d.multiply(ci); // b = (a-c)*ci mod a.modul // (c.modul*b)+c mod this.modul = c mod c.modul = // (c.modul*ci*(a-c)+c) mod a.modul = a mod a.modul GenPolynomial s = c.ring.modul.multiply(b); s = s.sum(c.val); return new AlgebraicNumber(this, s); } /** * Depth of extension field tower. * @return number of nested algebraic extension fields */ @SuppressWarnings("unchecked") public int depth() { AlgebraicNumberRing arr = this; int depth = 1; RingFactory cf = arr.ring.coFac; if (cf instanceof AlgebraicNumberRing) { arr = (AlgebraicNumberRing) (Object) cf; depth += arr.depth(); } return depth; } /** * Degree of extension field. * @return degree of this algebraic extension field */ public long extensionDegree() { long degree = modul.degree(0); return degree; } /** * Total degree of nested extension fields. * @return degree of tower of algebraic extension fields */ @SuppressWarnings("unchecked") public long totalExtensionDegree() { long degree = modul.degree(0); AlgebraicNumberRing arr = this; RingFactory cf = arr.ring.coFac; if (cf instanceof AlgebraicNumberRing) { arr = (AlgebraicNumberRing) (Object) cf; if (degree == 0L) { degree = arr.totalExtensionDegree(); } else { degree *= arr.totalExtensionDegree(); } } return degree; } /** * Get a AlgebraicNumber iterator. Note: Only for finite field * coefficients or fields which are iterable. * @return a iterator over all algebraic numbers in this ring. */ public Iterator> iterator() { return new AlgebraicNumberIterator(this); } } /** * Algebraic number iterator. * @author Heinz Kredel */ class AlgebraicNumberIterator> implements Iterator> { /** * data structure. */ final Iterator> iter; final List> powers; final AlgebraicNumberRing aring; private static final Logger logger = Logger.getLogger(AlgebraicNumberIterator.class); // private final boolean debug = logger.isDebugEnabled(); /** * CartesianProduct iterator constructor. * @param aring AlgebraicNumberRing components of the Cartesian product. */ public AlgebraicNumberIterator(AlgebraicNumberRing aring) { RingFactory cf = aring.ring.coFac; this.aring = aring; long d = aring.modul.degree(0); //System.out.println("d = " + d); powers = new ArrayList>((int) d); for (long j = d - 1; j >= 0L; j--) { powers.add(aring.ring.univariate(0, j)); } //System.out.println("powers = " + powers); if (!(cf instanceof Iterable)) { throw new IllegalArgumentException("only for iterable coefficients implemented"); } List> comps = new ArrayList>((int) d); Iterable cfi = (Iterable) cf; for (long j = 0L; j < d; j++) { comps.add(cfi); } if (cf.isFinite()) { CartesianProduct tuples = new CartesianProduct(comps); iter = tuples.iterator(); } else { CartesianProductInfinite tuples = new CartesianProductInfinite(comps); iter = tuples.iterator(); } if (logger.isInfoEnabled()) { logger.info("iterator for degree " + d + ", finite = " + cf.isFinite()); } } /** * Test for availability of a next tuple. * @return true if the iteration has more tuples, else false. */ public boolean hasNext() { return iter.hasNext(); } /** * Get next tuple. * @return next tuple. */ public AlgebraicNumber next() { List coeffs = iter.next(); //System.out.println("coeffs = " + coeffs); GenPolynomial pol = aring.ring.getZERO(); int i = 0; for (GenPolynomial f : powers) { C c = coeffs.get(i++); if (c.isZERO()) { continue; } pol = pol.sum(f.multiply(c)); } return new AlgebraicNumber(aring, pol); } /** * Remove a tuple if allowed. */ public void remove() { throw new UnsupportedOperationException("cannnot remove tuples"); } } jas-2.5/src/edu/jas/poly/ExpVectorPair.java0000644000175000017500000000422511036131636021050 0ustar giovannigiovanni/* * $Id: ExpVectorPair.java 1888 2008-07-12 13:37:34Z kredel $ */ package edu.jas.poly; import java.io.Serializable; /** * ExpVectorPair * implements pairs of exponent vectors for S-polynomials. * Objects of this class are immutable. * @author Heinz Kredel */ public class ExpVectorPair implements Serializable { private final ExpVector e1; private final ExpVector e2; /** * Constructors for ExpVectorPair. * @param e first part. * @param f second part. */ public ExpVectorPair(ExpVector e, ExpVector f) { e1 = e; e2 = f; } /** * @return first part. */ public ExpVector getFirst() { return e1; } /** * @return second part. */ public ExpVector getSecond() { return e2; } /** * toString. */ @Override public String toString() { StringBuffer s = new StringBuffer("ExpVectorPair["); s.append(e1.toString()); s.append(","); s.append(e2.toString()); s.append("]"); return s.toString(); } /** * equals. * @param B other. * @return true, if this == b, else false. */ @Override public boolean equals(Object B) { if ( ! (B instanceof ExpVectorPair) ) return false; return equals( (ExpVectorPair)B ); } /** * equals. * @param b other. * @return true, if this == b, else false. */ public boolean equals(ExpVectorPair b) { boolean t = e1.equals( b.getFirst() ); t = t && e2.equals( b.getSecond() ); return t; } /** hash code. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return (e1.hashCode() << 16) + e2.hashCode(); } /** * isMultiple. * @param p other. * @return true, if this is a multiple of b, else false. */ public boolean isMultiple(ExpVectorPair p) { boolean w = e1.multipleOf( p.getFirst() ); if ( !w ) { return w; } w = e2.multipleOf( p.getSecond() ); if ( !w ) { return w; } return true; } } jas-2.5/src/edu/jas/poly/AlgebraicNotInvertibleException.java0000644000175000017500000000535011511645432024554 0ustar giovannigiovanni/* * $Id: AlgebraicNotInvertibleException.java 3472 2011-01-07 17:19:22Z kredel $ */ package edu.jas.poly; import edu.jas.structure.NotInvertibleException; /** * Algebraic number NotInvertibleException class. * Runtime Exception to be thrown for not invertible algebraic numbers. * Container for the non-trivial factors found by the inversion algorithm. * Note: cannot be generic because of Throwable. * @author Heinz Kredel */ public class AlgebraicNotInvertibleException extends NotInvertibleException { public final GenPolynomial f; // = f1 * f2 public final GenPolynomial f1; public final GenPolynomial f2; public AlgebraicNotInvertibleException() { this(null,null,null); } public AlgebraicNotInvertibleException(String c) { this(c,null,null,null); } public AlgebraicNotInvertibleException(String c, Throwable t) { this(c,t,null,null,null); } public AlgebraicNotInvertibleException(Throwable t) { this(t,null,null,null); } /** * Constructor. * @param f polynomial with f = f1 * f2. * @param f1 polynomial. * @param f2 polynomial. */ public AlgebraicNotInvertibleException(GenPolynomial f, GenPolynomial f1, GenPolynomial f2) { super("AlgebraicNotInvertibleException"); this.f = f; this.f1 = f1; this.f2 = f2; } /** * Constructor. * @param f polynomial with f = f1 * f2. * @param f1 polynomial. * @param f2 polynomial. */ public AlgebraicNotInvertibleException(String c, GenPolynomial f, GenPolynomial f1, GenPolynomial f2) { super(c); this.f = f; this.f1 = f1; this.f2 = f2; } /** * Constructor. * @param f polynomial with f = f1 * f2. * @param f1 polynomial. * @param f2 polynomial. */ public AlgebraicNotInvertibleException(String c, Throwable t, GenPolynomial f, GenPolynomial f1, GenPolynomial f2) { super(c,t); this.f = f; this.f1 = f1; this.f2 = f2; } /** * Constructor. * @param f polynomial with f = f1 * f2. * @param f1 polynomial. * @param f2 polynomial. */ public AlgebraicNotInvertibleException(Throwable t, GenPolynomial f, GenPolynomial f1, GenPolynomial f2) { super("AlgebraicNotInvertibleException",t); this.f = f; this.f1 = f1; this.f2 = f2; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { String s = super.toString(); if ( f != null || f1 != null || f2 != null) { s += ", f = " + f + ", f1 = " + f1 + ", f2 = " + f2; } return s; } } jas-2.5/src/edu/jas/poly/Residue.java0000644000175000017500000002310312014234362017706 0ustar giovannigiovanni/* * $Id: Residue.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.poly; import org.apache.log4j.Logger; import edu.jas.structure.Element; import edu.jas.structure.NotInvertibleException; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.GcdRingElem; /** * Residue element based on RingElem residue. * Objects of this class are (nearly) immutable. * @author Heinz Kredel */ public class Residue > implements RingElem< Residue > { private static final Logger logger = Logger.getLogger(Residue.class); private boolean debug = logger.isDebugEnabled(); /** Residue class factory data structure. */ protected final ResidueRing ring; /** Value part of the element data structure. */ protected final C val; /** Flag to remember if this residue element is a unit. * -1 is unknown, 1 is unit, 0 not a unit. */ protected int isunit = -1; // initially unknown /** The constructor creates a Residue object * from a ring factory. * @param r ring factory. */ public Residue(ResidueRing r) { this( r, r.ring.getZERO(), 0 ); } /** The constructor creates a Residue object * from a ring factory and a ring element. * @param r ring factory. * @param a ring element. */ public Residue(ResidueRing r, C a) { this( r, a, -1 ); } /** The constructor creates a Residue object * from a ring factory, a ring element and an indicator if a is a unit. * @param r ring factory. * @param a ring element. * @param u isunit indicator, -1, 0, 1. */ public Residue(ResidueRing r, C a, int u) { ring = r; C v = a.remainder( ring.modul ); if ( v.signum() < 0 ) { v = v.sum( ring.modul ); } val = v; if ( u == 0 || u == 1 ) { isunit = u; return; } if (val.isZERO()) { isunit = 0; return; } if ( val.isUnit() ) { isunit = 1; //} else { // not possible //isunit = 0; } isunit = -1; } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public ResidueRing factory() { return ring; } /** Clone this. * @see java.lang.Object#clone() */ @Override public Residue copy() { return new Residue( ring, val ); } /** Is Residue zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return val.equals( ring.ring.getZERO() ); } /** Is Residue one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return val.equals( ring.ring.getONE() ); } /** Is Residue unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ @SuppressWarnings("unchecked") public boolean isUnit() { if ( isunit == 1 ) { return true; } if ( isunit == 0 ) { return false; } // val.isUnit() already tested // not jet known if ( val instanceof GcdRingElem && ring.modul instanceof GcdRingElem ) { GcdRingElem v = (GcdRingElem)val; GcdRingElem m = (GcdRingElem)ring.modul; C gcd = (C) v.gcd( m ); if ( debug ) { logger.info("gcd = " + gcd); } boolean u = gcd.isONE(); if ( u ) { isunit = 1; } else { isunit = 0; } return u; } // still unknown return false; } /** Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { return "Residue[ " + val.toString() + " mod " + ring.toString() + " ]"; } /** Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "Residue( " + val.toScript() + " , " + ring.toScript() + " )"; } /** Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** Residue comparison. * @param b Residue. * @return sign(this-b), 0 means that this and b are equivalent in this residue class ring. */ //JAVA6only: @Override public int compareTo(Residue b) { C v = b.val; if ( ! ring.equals( b.ring ) ) { v = v.remainder( ring.modul ); } return val.compareTo( v ); } /** Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) * @return true means that this and b are equivalent in this residue class ring. */ @SuppressWarnings("unchecked") // not jet working @Override public boolean equals(Object b) { if ( ! ( b instanceof Residue ) ) { return false; } Residue a = null; try { a = (Residue) b; } catch (ClassCastException e) { } if ( a == null ) { return false; } return ( 0 == compareTo( a ) ); } /** Hash code for this local. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + val.hashCode(); return h; } /** Residue absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public Residue abs() { return new Residue( ring, val.abs() ); } /** Residue summation. * @param S Residue. * @return this+S. */ public Residue sum(Residue S) { return new Residue( ring, val.sum( S.val ) ); } /** Residue negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public Residue negate() { return new Residue( ring, val.negate() ); } /** Residue signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { return val.signum(); } /** Residue subtraction. * @param S Residue. * @return this-S. */ public Residue subtract(Residue S) { return new Residue( ring, val.subtract( S.val ) ); } /** Residue division. * @param S Residue. * @return this/S. */ public Residue divide(Residue S) { return multiply( S.inverse() ); } /** Residue inverse. * @see edu.jas.structure.RingElem#inverse() * @return S with S = 1/this if defined. */ @SuppressWarnings("unchecked") public Residue inverse() { if ( isunit == 0 ) { throw new NotInvertibleException("element not invertible (0) " + this); } if ( val instanceof GcdRingElem && ring.modul instanceof GcdRingElem ) { GcdRingElem v = (GcdRingElem)val; GcdRingElem m = (GcdRingElem)ring.modul; C[] egcd = (C[])v.egcd( m ); if ( debug ) { logger.info("egcd = " + egcd[0] + ", f = " + egcd[1]); } if ( ! egcd[0].isONE() ) { isunit = 0; throw new NotInvertibleException("element not invertible (gcd)" + this); } isunit = 1; C x = egcd[1]; return new Residue( ring, x ); } if ( val.isUnit() ) { C x = val.inverse(); return new Residue( ring, x ); } System.out.println("isunit = " + isunit + ", isUnit() = " + this.isUnit() ); throw new NotInvertibleException("element not invertible (!gcd)" + this); } /** Residue remainder. * @param S Residue. * @return this - (this/S)*S. */ public Residue remainder(Residue S) { C x = val.remainder( S.val ); return new Residue( ring, x ); } /** Residue multiplication. * @param S Residue. * @return this*S. */ public Residue multiply(Residue S) { return new Residue( ring, val.multiply( S.val ) ); } /** * Greatest common divisor. * Note: Not implemented, throws UnsupportedOperationException. * @param b other element. * @return gcd(this,b). */ public Residue gcd(Residue b) { throw new UnsupportedOperationException("gcd not implemented " + this.getClass().getName()); } /** * Extended greatest common divisor. * Note: Not implemented, throws UnsupportedOperationException. * @param b other element. * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). */ public Residue[] egcd(Residue b) { throw new UnsupportedOperationException("egcd not implemented " + this.getClass().getName()); } } jas-2.5/src/edu/jas/poly/ExpVectorLong.java0000644000175000017500000005400412042051146021047 0ustar giovannigiovanni/* * $Id: ExpVectorLong.java 4270 2012-10-24 20:41:11Z kredel $ */ package edu.jas.poly; import java.util.List; import java.util.ArrayList; /** * ExpVectorLong implements exponent vectors for polynomials using arrays of * long as storage unit. This class is used by ExpVector internally, there is no * need to use this class directly. * @see ExpVector * @author Heinz Kredel */ public final class ExpVectorLong extends ExpVector /*implements AbelianGroupElem*/{ /** * The data structure is an array of longs. */ /*package*/final long[] val; /** * Constructor for ExpVector. * @param n length of exponent vector. */ public ExpVectorLong(int n) { this(new long[n]); } /** * Constructor for ExpVector. Sets exponent i to e. * @param n length of exponent vector. * @param i index of exponent to be set. * @param e exponent to be set. */ public ExpVectorLong(int n, int i, long e) { this(new long[n]); val[i] = e; } /** * Constructor for ExpVector. Sets val. * @param v internal representation array. */ public ExpVectorLong(long[] v) { super(); if (v == null) { throw new IllegalArgumentException("null val not allowed"); } val = v; } /** * Constructor for ExpVector. Converts a String representation to an * ExpVector. Accepted format = (1,2,3,4,5,6,7). * @param s String representation. */ public ExpVectorLong(String s) throws NumberFormatException { super(); // first format = (1,2,3,4,5,6,7) List exps = new ArrayList(); s = s.trim(); int b = s.indexOf('('); int e = s.indexOf(')', b + 1); String teil; int k; long a; if (b >= 0 && e >= 0) { b++; while ((k = s.indexOf(',', b)) >= 0) { teil = s.substring(b, k); a = Long.parseLong(teil); exps.add(Long.valueOf(a)); b = k + 1; } if (b <= e) { teil = s.substring(b, e); a = Long.parseLong(teil); exps.add(Long.valueOf(a)); } int length = exps.size(); val = new long[length]; for (int j = 0; j < length; j++) { val[j] = exps.get(j).longValue(); } } else { // not implemented val = null; // length = -1; //Vector names = new Vector(); //vars = s; } } /** * Clone this. * @see java.lang.Object#clone() */ @Override public ExpVectorLong copy() { long[] w = new long[val.length]; System.arraycopy(val, 0, w, 0, val.length); return new ExpVectorLong(w); } /** * Get the exponent vector. * @return val. */ @Override /*package*/long[] getVal() { return val; } /** * Get the exponent at position i. * @param i position. * @return val[i]. */ @Override public long getVal(int i) { return val[i]; } /** * Set the exponent at position i to e. * @param i * @param e * @return old val[i]. */ @Override protected long setVal(int i, long e) { long x = val[i]; val[i] = e; hash = 0; // beware of race condition return x; } /** * Get the length of this exponent vector. * @return val.length. */ @Override public int length() { return val.length; } /** * Extend variables. Used e.g. in module embedding. Extend this by i * elements and set val[j] to e. * @param i number of elements to extend. * @param j index of element to be set. * @param e new exponent for val[j]. * @return extended exponent vector. */ @Override public ExpVectorLong extend(int i, int j, long e) { long[] w = new long[val.length + i]; System.arraycopy(val, 0, w, i, val.length); if (j >= i) { throw new IllegalArgumentException("i " + i + " <= j " + j + " invalid"); } w[j] = e; return new ExpVectorLong(w); } /** * Extend lower variables. Extend this by i lower elements and set val[j] to * e. * @param i number of elements to extend. * @param j index of element to be set. * @param e new exponent for val[j]. * @return extended exponent vector. */ @Override public ExpVectorLong extendLower(int i, int j, long e) { long[] w = new long[val.length + i]; System.arraycopy(val, 0, w, 0, val.length); if (j >= i) { throw new IllegalArgumentException("i " + i + " <= j " + j + " invalid"); } w[val.length + j] = e; return new ExpVectorLong(w); } /** * Contract variables. Used e.g. in module embedding. Contract this to len * elements. * @param i position of first element to be copied. * @param len new length. * @return contracted exponent vector. */ @Override public ExpVectorLong contract(int i, int len) { if (i + len > val.length) { throw new IllegalArgumentException("len " + len + " > val.len " + val.length); } long[] w = new long[len]; System.arraycopy(val, i, w, 0, len); return new ExpVectorLong(w); } /** * Reverse variables. Used e.g. in opposite rings. * @return reversed exponent vector. */ @Override public ExpVectorLong reverse() { long[] w = new long[val.length]; for (int i = 0; i < val.length; i++) { w[i] = val[val.length - 1 - i]; } return new ExpVectorLong(w); } /** * Reverse j variables. Used e.g. in opposite rings. Reverses the first j-1 * variables, the rest is unchanged. * @param j index of first variable not reversed. * @return reversed exponent vector. */ @Override public ExpVectorLong reverse(int j) { if (j <= 0 || j > val.length) { return this; } long[] w = new long[val.length]; for (int i = 0; i < j; i++) { w[i] = val[j - 1 - i]; } // copy rest for (int i = j; i < val.length; i++) { w[i] = val[i]; } return new ExpVectorLong(w); } /** * Combine with ExpVector. Combine this with the other ExpVector V. * @param V the other exponent vector. * @return combined exponent vector. */ @Override public ExpVectorLong combine(ExpVector V) { if (V == null || V.length() == 0) { return this; } ExpVectorLong Vl = (ExpVectorLong) V; if (val.length == 0) { return Vl; } long[] w = new long[val.length + Vl.val.length]; System.arraycopy(val, 0, w, 0, val.length); System.arraycopy(Vl.val, 0, w, val.length, Vl.val.length); return new ExpVectorLong(w); } /** * Get the string representation. * @see java.lang.Object#toString() */ @Override public String toString() { return super.toString() + ":long"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object B) { if (!(B instanceof ExpVectorLong)) { return false; } ExpVectorLong b = (ExpVectorLong) B; int t = this.invLexCompareTo(b); //System.out.println("equals: this = " + this + " B = " + B + " t = " + t); return (0 == t); } /** * hashCode for this exponent vector. * @see java.lang.Object#hashCode() Only for findbugs. */ @Override public int hashCode() { return super.hashCode(); } /** * ExpVector absolute value. * @return abs(this). */ @Override public ExpVectorLong abs() { long[] u = val; long[] w = new long[u.length]; for (int i = 0; i < u.length; i++) { if (u[i] >= 0L) { w[i] = u[i]; } else { w[i] = -u[i]; } } return new ExpVectorLong(w); //return EVABS(this); } /** * ExpVector negate. * @return -this. */ @Override public ExpVectorLong negate() { long[] u = val; long[] w = new long[u.length]; for (int i = 0; i < u.length; i++) { w[i] = -u[i]; } return new ExpVectorLong(w); // return EVNEG(this); } /** * ExpVector summation. * @param V * @return this+V. */ @Override public ExpVectorLong sum(ExpVector V) { long[] u = val; long[] v = ((ExpVectorLong) V).val; long[] w = new long[u.length]; for (int i = 0; i < u.length; i++) { w[i] = u[i] + v[i]; } return new ExpVectorLong(w); // return EVSUM(this, V); } /** * ExpVector subtract. Result may have negative entries. * @param V * @return this-V. */ @Override public ExpVectorLong subtract(ExpVector V) { long[] u = val; long[] v = ((ExpVectorLong) V).val; long[] w = new long[u.length]; for (int i = 0; i < u.length; i++) { w[i] = u[i] - v[i]; } return new ExpVectorLong(w); //return EVDIF(this, V); } /** * ExpVector substitution. Clone and set exponent to d at position i. * @param i position. * @param d new exponent. * @return substituted ExpVector. */ @Override public ExpVectorLong subst(int i, long d) { ExpVectorLong V = this.copy(); @SuppressWarnings("unused") long e = V.setVal(i, d); return V; //return EVSU(this, i, d); } /** * ExpVector signum. * @return 0 if this is zero, -1 if some entry is negative, 1 if no entry is * negative and at least one entry is positive. */ @Override public int signum() { int t = 0; long[] u = val; for (int i = 0; i < u.length; i++) { if (u[i] < 0) { return -1; } if (u[i] > 0) { t = 1; } } return t; //return EVSIGN(this); } /** * ExpVector total degree. * @return sum of all exponents. */ @Override public long totalDeg() { long t = 0; long[] u = val; // U.val; for (int i = 0; i < u.length; i++) { t += u[i]; } return t; //return EVTDEG(this); } /** * ExpVector maximal degree. * @return maximal exponent. */ @Override public long maxDeg() { long t = 0; long[] u = val; for (int i = 0; i < u.length; i++) { if (u[i] > t) { t = u[i]; } } return t; //return EVMDEG(this); } /** * ExpVector weighted degree. * @param w weights. * @return weighted sum of all exponents. */ @Override public long weightDeg(long[][] w) { if (w == null || w.length == 0) { return totalDeg(); // assume weight 1 } long t = 0; long[] u = val; for (int j = 0; j < w.length; j++) { long[] wj = w[j]; for (int i = 0; i < u.length; i++) { t += wj[i] * u[i]; } } return t; //return EVWDEG( w, this ); } /** * ExpVector least common multiple. * @param V * @return component wise maximum of this and V. */ @Override public ExpVectorLong lcm(ExpVector V) { long[] u = val; long[] v = ((ExpVectorLong) V).val; long[] w = new long[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (u[i] >= v[i] ? u[i] : v[i]); } return new ExpVectorLong(w); //return EVLCM(this, V); } /** * ExpVector greatest common divisor. * @param V * @return component wise minimum of this and V. */ @Override public ExpVectorLong gcd(ExpVector V) { long[] u = val; long[] v = ((ExpVectorLong) V).val; long[] w = new long[u.length]; for (int i = 0; i < u.length; i++) { w[i] = (u[i] <= v[i] ? u[i] : v[i]); } return new ExpVectorLong(w); //return EVGCD(this, V); } /** * ExpVector dependency on variables. * @return array of indices where val has positive exponents. */ @Override public int[] dependencyOnVariables() { long[] u = val; int l = 0; for (int i = 0; i < u.length; i++) { if (u[i] > 0) { l++; } } int[] dep = new int[l]; if (l == 0) { return dep; } int j = 0; for (int i = 0; i < u.length; i++) { if (u[i] > 0) { dep[j] = i; j++; } } return dep; } /** * ExpVector multiple test. Test if this is component wise greater or equal * to V. * @param V * @return true if this is a multiple of V, else false. */ @Override public boolean multipleOf(ExpVector V) { long[] u = val; long[] v = ((ExpVectorLong) V).val; boolean t = true; for (int i = 0; i < u.length; i++) { if (u[i] < v[i]) { return false; } } return t; //return EVMT(this, V); } /** * ExpVector compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int compareTo(ExpVector V) { return this.invLexCompareTo(V); } /** * ExpVector inverse lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invLexCompareTo(ExpVector V) { long[] u = val; long[] v = ((ExpVectorLong) V).val; int t = 0; for (int i = 0; i < u.length; i++) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVILCP(this, V); } /** * ExpVector inverse lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invLexCompareTo(ExpVector V, int begin, int end) { long[] u = val; long[] v = ((ExpVectorLong) V).val; int t = 0; for (int i = begin; i < end; i++) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVILCP(this, V, begin, end); } /** * ExpVector inverse graded lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invGradCompareTo(ExpVector V) { long[] u = val; long[] v = ((ExpVectorLong) V).val; int t = 0; int i; for (i = 0; i < u.length; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j < u.length; j++) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVIGLC(this, V); } /** * ExpVector inverse graded lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invGradCompareTo(ExpVector V, int begin, int end) { long[] u = val; long[] v = ((ExpVectorLong) V).val; int t = 0; int i; for (i = begin; i < end; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j < end; j++) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVIGLC(this, V, begin, end); } /** * ExpVector reverse inverse lexicographical compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvLexCompareTo(ExpVector V) { long[] u = val; long[] v = ((ExpVectorLong) V).val; int t = 0; for (int i = u.length - 1; i >= 0; i--) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVRILCP(this, V); } /** * ExpVector reverse inverse lexicographical compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvLexCompareTo(ExpVector V, int begin, int end) { long[] u = val; long[] v = ((ExpVectorLong) V).val; int t = 0; for (int i = end - 1; i >= begin; i--) { if (u[i] > v[i]) return 1; if (u[i] < v[i]) return -1; } return t; //return EVRILCP(this, V, begin, end); } /** * ExpVector reverse inverse graded compareTo. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvGradCompareTo(ExpVector V) { long[] u = val; long[] v = ((ExpVectorLong) V).val; int t = 0; int i; for (i = u.length - 1; i >= 0; i--) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j >= 0; j--) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVRIGLC(this, V); } /** * ExpVector reverse inverse graded compareTo. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int revInvGradCompareTo(ExpVector V, int begin, int end) { long[] u = val; long[] v = ((ExpVectorLong) V).val; int t = 0; int i; for (i = end - 1; i >= begin; i--) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } long up = 0; long vp = 0; for (int j = i; j >= begin; j--) { up += u[j]; vp += v[j]; } if (up > vp) { t = 1; } else { if (up < vp) { t = -1; } } return t; //return EVRIGLC(this, V, begin, end); } /** * ExpVector inverse weighted lexicographical compareTo. * @param w weight array. * @param V * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invWeightCompareTo(long[][] w, ExpVector V) { long[] u = val; long[] v = ((ExpVectorLong) V).val; int t = 0; int i; for (i = 0; i < u.length; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } for (int k = 0; k < w.length; k++) { long[] wk = w[k]; long up = 0; long vp = 0; for (int j = i; j < u.length; j++) { up += wk[j] * u[j]; vp += wk[j] * v[j]; } if (up > vp) { return 1; } else if (up < vp) { return -1; } } return t; //return EVIWLC(w, this, V); } /** * ExpVector inverse weighted lexicographical compareTo. * @param w weight array. * @param V * @param begin * @param end * @return 0 if U == V, -1 if U < V, 1 if U > V. */ @Override public int invWeightCompareTo(long[][] w, ExpVector V, int begin, int end) { long[] u = val; long[] v = ((ExpVectorLong) V).val; int t = 0; int i; for (i = begin; i < end; i++) { if (u[i] > v[i]) { t = 1; break; } if (u[i] < v[i]) { t = -1; break; } } if (t == 0) { return t; } for (int k = 0; k < w.length; k++) { long[] wk = w[k]; long up = 0; long vp = 0; for (int j = i; j < end; j++) { up += wk[j] * u[j]; vp += wk[j] * v[j]; } if (up > vp) { return 1; } else if (up < vp) { return -1; } } return t; //return EVIWLC(w, this, V, begin, end); } } jas-2.5/src/edu/jas/ufdroot/0000755000175000017500000000000012140140256016141 5ustar giovannigiovannijas-2.5/src/edu/jas/ufdroot/package.html0000644000175000017500000000146211713215210020423 0ustar giovannigiovanni Unique Factorization Domain and Roots package

Unique Factorization Domain and Roots package.

This package contains classes for factorization in structures used in roots computation, for example FactorRealAlgebraic.


Heinz Kredel

Last modified: Sat Feb 4 12:45:33 CET 2012

$Id: package.html 3870 2012-02-04 11:46:17Z kredel $

jas-2.5/src/edu/jas/ufdroot/FactorRealAlgebraic.java0000644000175000017500000001012212004530770022617 0ustar giovannigiovanni/* * $Id: FactorRealAlgebraic.java 4066 2012-07-27 15:21:28Z kredel $ */ package edu.jas.ufdroot; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.Rational; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.root.PolyUtilRoot; import edu.jas.root.RealAlgebraicNumber; import edu.jas.root.RealAlgebraicRing; import edu.jas.structure.GcdRingElem; import edu.jas.ufd.FactorAbstract; import edu.jas.ufd.FactorFactory; /** * Real algebraic number coefficients factorization algorithms. This class * implements factorization methods for polynomials over real algebraic numbers * from package * *
 * edu.jas.root
 * 
* * . * @param coefficient type * @author Heinz Kredel */ public class FactorRealAlgebraic & Rational> extends FactorAbstract> { // TODO: is absolute possible? and what does it mean? //FactorAbsolute> //FactorAbstract> private static final Logger logger = Logger.getLogger(FactorRealAlgebraic.class); //private final boolean debug = logger.isInfoEnabled(); /** * Factorization engine for base coefficients. */ public final FactorAbstract> factorAlgebraic; /** * No argument constructor. Note: can't use this constructor. */ protected FactorRealAlgebraic() { throw new IllegalArgumentException("don't use this constructor"); } /** * Constructor. * @param fac algebraic number factory. */ public FactorRealAlgebraic(RealAlgebraicRing fac) { this(fac, FactorFactory.> getImplementation(fac.algebraic)); } /** * Constructor. * @param fac algebraic number factory. * @param factorAlgebraic factorization engine for polynomials over base * coefficients. */ public FactorRealAlgebraic(RealAlgebraicRing fac, FactorAbstract> factorAlgebraic) { super(fac); this.factorAlgebraic = factorAlgebraic; } /** * GenPolynomial base factorization of a squarefree polynomial. * @param P squarefree GenPolynomial<RealAlgebraicNumber<C>>. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ @Override public List>> baseFactorsSquarefree( GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List>> factors = new ArrayList>>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing> pfac = P.ring; // Q(alpha)[x] if (pfac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomials"); } RealAlgebraicRing rfac = (RealAlgebraicRing) pfac.coFac; RealAlgebraicNumber ldcf = P.leadingBaseCoefficient(); if (!ldcf.isONE()) { P = P.monic(); factors.add(pfac.getONE().multiply(ldcf)); } //System.out.println("\nP = " + P); GenPolynomialRing> afac = new GenPolynomialRing>( rfac.algebraic, pfac); GenPolynomial> A = PolyUtilRoot. algebraicFromRealCoefficients(afac, P); // factor A: List>> afactors = factorAlgebraic.baseFactorsSquarefree(A); for (GenPolynomial> a : afactors) { GenPolynomial> p = PolyUtilRoot. realFromAlgebraicCoefficients(pfac, a); factors.add(p); } logger.info("real algebraic factors = " + factors); return factors; } } jas-2.5/src/edu/jas/ufd/0000755000175000017500000000000012140140256015235 5ustar giovannigiovannijas-2.5/src/edu/jas/ufd/GreatestCommonDivisorModular.java0000644000175000017500000005056512014156146023733 0ustar giovannigiovanni/* * $Id: GreatestCommonDivisorModular.java 4111 2012-08-19 12:30:30Z kredel $ */ package edu.jas.ufd; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.Combinatoric; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLongRing; import edu.jas.arith.Modular; import edu.jas.arith.ModularRingFactory; import edu.jas.arith.PrimeList; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; /** * Greatest common divisor algorithms with modular computation and chinese * remainder algorithm. * @author Heinz Kredel */ public class GreatestCommonDivisorModular & Modular> extends GreatestCommonDivisorAbstract { private static final Logger logger = Logger.getLogger(GreatestCommonDivisorModular.class); private final boolean debug = logger.isDebugEnabled(); //logger.isInfoEnabled(); /* * Modular gcd algorithm to use. */ protected final GreatestCommonDivisorAbstract mufd; /* * Integer gcd algorithm for fall back. */ protected final GreatestCommonDivisorAbstract iufd = new GreatestCommonDivisorSubres(); /** * Constructor to set recursive algorithm. Use modular evaluation GCD * algorithm. */ public GreatestCommonDivisorModular() { this(false); } /** * Constructor to set recursive algorithm. * @param simple , true if the simple PRS should be used. */ public GreatestCommonDivisorModular(boolean simple) { if (simple) { mufd = new GreatestCommonDivisorSimple(); } else { mufd = new GreatestCommonDivisorModEval(); } } /** * Univariate GenPolynomial greatest comon divisor. Delegate to subresultant * baseGcd, should not be needed. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial baseGcd(GenPolynomial P, GenPolynomial S) { return iufd.baseGcd(P, S); } /** * Univariate GenPolynomial recursive greatest comon divisor. Delegate to * subresultant recursiveGcd, should not be needed. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial> recursiveUnivariateGcd( GenPolynomial> P, GenPolynomial> S) { return iufd.recursiveUnivariateGcd(P, S); } /** * GenPolynomial greatest comon divisor, modular algorithm. * @param P GenPolynomial. * @param S GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial gcd(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } GenPolynomialRing fac = P.ring; // special case for univariate polynomials if (fac.nvar <= 1) { GenPolynomial T = baseGcd(P, S); return T; } long e = P.degree(0); long f = S.degree(0); GenPolynomial q; GenPolynomial r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } r = r.abs(); q = q.abs(); // compute contents and primitive parts BigInteger a = baseContent(r); BigInteger b = baseContent(q); // gcd of coefficient contents BigInteger c = gcd(a, b); // indirection r = divide(r, a); // indirection q = divide(q, b); // indirection if (r.isONE()) { return r.multiply(c); } if (q.isONE()) { return q.multiply(c); } // compute normalization factor BigInteger ac = r.leadingBaseCoefficient(); BigInteger bc = q.leadingBaseCoefficient(); BigInteger cc = gcd(ac, bc); // indirection // compute norms BigInteger an = r.maxNorm(); BigInteger bn = q.maxNorm(); BigInteger n = (an.compareTo(bn) < 0 ? bn : an); n = n.multiply(cc).multiply(n.fromInteger(2)); // compute degree vectors ExpVector rdegv = r.degreeVector(); ExpVector qdegv = q.degreeVector(); //compute factor coefficient bounds BigInteger af = an.multiply(PolyUtil.factorBound(rdegv)); BigInteger bf = bn.multiply(PolyUtil.factorBound(qdegv)); BigInteger cf = (af.compareTo(bf) < 0 ? bf : af); cf = cf.multiply(cc.multiply(cc.fromInteger(8))); //initialize prime list and degree vector PrimeList primes = new PrimeList(); int pn = 10; //primes.size(); ExpVector wdegv = rdegv.subst(0, rdegv.getVal(0) + 1); // +1 seems to be a hack for the unlucky prime test ModularRingFactory cofac; ModularRingFactory cofacM = null; GenPolynomial qm; GenPolynomial rm; GenPolynomialRing mfac; GenPolynomialRing rfac = null; int i = 0; BigInteger M = null; BigInteger cfe = null; GenPolynomial cp = null; GenPolynomial cm = null; GenPolynomial cpi = null; if (debug) { logger.debug("c = " + c); logger.debug("cc = " + cc); logger.debug("n = " + n); logger.debug("cf = " + cf); logger.info("wdegv = " + wdegv); } for (java.math.BigInteger p : primes) { //System.out.println("next run ++++++++++++++++++++++++++++++++++"); if (p.longValue() == 2L) { // skip 2 continue; } if (++i >= pn) { logger.warn("prime list exhausted, pn = " + pn); return iufd.gcd(P, S); //throw new ArithmeticException("prime list exhausted"); } // initialize coefficient factory and map normalization factor if (ModLongRing.MAX_LONG.compareTo(p) > 0) { cofac = (ModularRingFactory) new ModLongRing(p, true); } else { cofac = (ModularRingFactory) new ModIntegerRing(p, true); } MOD nf = cofac.fromInteger(cc.getVal()); if (nf.isZERO()) { continue; } // initialize polynomial factory and map polynomials mfac = new GenPolynomialRing(cofac, fac.nvar, fac.tord, fac.getVars()); qm = PolyUtil. fromIntegerCoefficients(mfac, q); if (qm.isZERO() || !qm.degreeVector().equals(qdegv)) { continue; } rm = PolyUtil. fromIntegerCoefficients(mfac, r); if (rm.isZERO() || !rm.degreeVector().equals(rdegv)) { continue; } if (debug) { logger.info("cofac = " + cofac.getIntegerModul()); } // compute modular gcd cm = mufd.gcd(rm, qm); // test for constant g.c.d if (cm.isConstant()) { logger.debug("cm, constant = " + cm); return fac.getONE().multiply(c); //return cm.abs().multiply( c ); } // test for unlucky prime ExpVector mdegv = cm.degreeVector(); if (wdegv.equals(mdegv)) { // TL = 0 // prime ok, next round if (M != null) { if (M.compareTo(cfe) > 0) { System.out.println("M > cfe: " + M + " > " + cfe); // continue; // why should this be required? } } } else { // TL = 3 boolean ok = false; if (wdegv.multipleOf(mdegv)) { // TL = 2 // EVMT(wdegv,mdegv) M = null; // init chinese remainder ok = true; // prime ok } if (mdegv.multipleOf(wdegv)) { // TL = 1 // EVMT(mdegv,wdegv) continue; // skip this prime } if (!ok) { M = null; // discard chinese remainder and previous work continue; // prime not ok } } //--wdegv = mdegv; // prepare chinese remainder algorithm cm = cm.multiply(nf); if (M == null) { // initialize chinese remainder algorithm M = new BigInteger(p); cofacM = cofac; rfac = mfac; cp = cm; wdegv = wdegv.gcd(mdegv); //EVGCD(wdegv,mdegv); cfe = cf; for (int k = 0; k < wdegv.length(); k++) { cfe = cfe.multiply(new BigInteger(wdegv.getVal(k) + 1)); } } else { // apply chinese remainder algorithm BigInteger Mp = M; MOD mi = cofac.fromInteger(Mp.getVal()); mi = mi.inverse(); // mod p M = M.multiply(new BigInteger(p)); if (ModLongRing.MAX_LONG.compareTo(M.getVal()) > 0) { cofacM = (ModularRingFactory) new ModLongRing(M.getVal()); } else { cofacM = (ModularRingFactory) new ModIntegerRing(M.getVal()); } rfac = new GenPolynomialRing(cofacM, fac); if (!cofac.getClass().equals(cofacM.getClass())) { logger.info("adjusting coefficents: cofacM = " + cofacM.getClass() + ", cofacP = " + cofac.getClass()); cofac = (ModularRingFactory) new ModIntegerRing(p); mfac = new GenPolynomialRing(cofac, fac); GenPolynomial mm = PolyUtil. integerFromModularCoefficients(fac, cm); cm = PolyUtil. fromIntegerCoefficients(mfac, mm); mi = cofac.fromInteger(Mp.getVal()); mi = mi.inverse(); // mod p } if (!cp.ring.coFac.getClass().equals(cofacM.getClass())) { logger.info("adjusting coefficents: cofacM = " + cofacM.getClass() + ", cofacM' = " + cp.ring.coFac.getClass()); ModularRingFactory cop = (ModularRingFactory) cp.ring.coFac; cofac = (ModularRingFactory) new ModIntegerRing(cop.getIntegerModul().getVal()); mfac = new GenPolynomialRing(cofac, fac); GenPolynomial mm = PolyUtil. integerFromModularCoefficients(fac, cp); cp = PolyUtil. fromIntegerCoefficients(mfac, mm); } cp = PolyUtil. chineseRemainder(rfac, cp, mi, cm); } // test for completion if (n.compareTo(M) <= 0) { break; } // must use integer.sumNorm cpi = PolyUtil. integerFromModularCoefficients(fac, cp); BigInteger cmn = cpi.sumNorm(); cmn = cmn.multiply(cmn.fromInteger(4)); //if ( cmn.compareTo( M ) <= 0 ) { // does not work: only if cofactors are also considered? // break; //} if (i % 2 != 0 && !cp.isZERO()) { // check if done on every second prime GenPolynomial x; x = PolyUtil. integerFromModularCoefficients(fac, cp); x = basePrimitivePart(x); if (!PolyUtil. baseSparsePseudoRemainder(q, x).isZERO()) { continue; } if (!PolyUtil. baseSparsePseudoRemainder(r, x).isZERO()) { continue; } logger.info("done on exact division, #primes = " + i); break; } } if (debug) { logger.info("done on M = " + M + ", #primes = " + i); } // remove normalization q = PolyUtil. integerFromModularCoefficients(fac, cp); q = basePrimitivePart(q); return q.abs().multiply(c); } /** * Univariate GenPolynomial resultant. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial baseResultant(GenPolynomial P, GenPolynomial S) { // not a special case here return resultant(P,S); } /** * Univariate GenPolynomial recursive resultant. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return res(P,S). */ public GenPolynomial> recursiveUnivariateResultant(GenPolynomial> P, GenPolynomial> S) { // only in this class return recursiveResultant(P,S); } /** * GenPolynomial resultant, modular algorithm. * @param P GenPolynomial. * @param S GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial resultant(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } GenPolynomialRing fac = P.ring; // no special case for univariate polynomials in this class ! //if (fac.nvar <= 1) { // GenPolynomial T = iufd.baseResultant(P, S); // return T; //} long e = P.degree(0); long f = S.degree(0); GenPolynomial q; GenPolynomial r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } // compute norms BigInteger an = r.maxNorm(); BigInteger bn = q.maxNorm(); an = Power. power(fac.coFac, an, f); bn = Power. power(fac.coFac, bn, e); BigInteger cn = Combinatoric.factorial(e + f); BigInteger n = cn.multiply(an).multiply(bn); // compute degree vectors ExpVector rdegv = r.leadingExpVector(); //degreeVector(); ExpVector qdegv = q.leadingExpVector(); //degreeVector(); //initialize prime list and degree vector PrimeList primes = new PrimeList(); int pn = 30; //primes.size(); ModularRingFactory cofac; ModularRingFactory cofacM = null; GenPolynomial qm; GenPolynomial rm; GenPolynomialRing mfac; GenPolynomialRing rfac = null; int i = 0; BigInteger M = null; GenPolynomial cp = null; GenPolynomial cm = null; GenPolynomial cpi = null; if (debug) { logger.debug("an = " + an); logger.debug("bn = " + bn); logger.debug("e+f = " + (e+f)); logger.debug("cn = " + cn); logger.info("n = " + n); //logger.info("q = " + q); //logger.info("r = " + r); //logger.info("rdegv = " + rdegv.toString(fac.getVars())); //logger.info("qdegv = " + qdegv.toString(fac.getVars())); } for (java.math.BigInteger p : primes) { //System.out.println("next run ++++++++++++++++++++++++++++++++++"); if (p.longValue() == 2L) { // skip 2 continue; } if (++i >= pn) { logger.warn("prime list exhausted, pn = " + pn); return iufd.resultant(P, S); //throw new ArithmeticException("prime list exhausted"); } // initialize coefficient factory and map normalization factor if (ModLongRing.MAX_LONG.compareTo(p) > 0) { cofac = (ModularRingFactory) new ModLongRing(p, true); } else { cofac = (ModularRingFactory) new ModIntegerRing(p, true); } // initialize polynomial factory and map polynomials mfac = new GenPolynomialRing(cofac, fac); qm = PolyUtil. fromIntegerCoefficients(mfac, q); if (qm.isZERO() || !qm.leadingExpVector().equals(qdegv)) { //degreeVector() //logger.info("qm = " + qm); if (debug) { logger.info("unlucky prime = " + cofac.getIntegerModul() + ", degv = " + qm.leadingExpVector()); } continue; } rm = PolyUtil. fromIntegerCoefficients(mfac, r); if (rm.isZERO() || !rm.leadingExpVector().equals(rdegv)) { //degreeVector() //logger.info("rm = " + rm); if (debug) { logger.info("unlucky prime = " + cofac.getIntegerModul() + ", degv = " + rm.leadingExpVector()); } continue; } logger.info("lucky prime = " + cofac.getIntegerModul()); // compute modular resultant cm = mufd.resultant(qm, rm); if (debug) { logger.info("res_p = " + cm); } // prepare chinese remainder algorithm if (M == null) { // initialize chinese remainder algorithm M = new BigInteger(p); cofacM = cofac; //rfac = mfac; cp = cm; } else { // apply chinese remainder algorithm BigInteger Mp = M; MOD mi = cofac.fromInteger(Mp.getVal()); mi = mi.inverse(); // mod p M = M.multiply(new BigInteger(p)); if (ModLongRing.MAX_LONG.compareTo(M.getVal()) > 0) { cofacM = (ModularRingFactory) new ModLongRing(M.getVal()); } else { cofacM = (ModularRingFactory) new ModIntegerRing(M.getVal()); } rfac = new GenPolynomialRing(cofacM, fac); if (!cofac.getClass().equals(cofacM.getClass())) { logger.info("adjusting coefficents: cofacM = " + cofacM.getClass() + ", cofacP = " + cofac.getClass()); cofac = (ModularRingFactory) new ModIntegerRing(p); mfac = new GenPolynomialRing(cofac, fac); GenPolynomial mm = PolyUtil. integerFromModularCoefficients(fac, cm); cm = PolyUtil. fromIntegerCoefficients(mfac, mm); mi = cofac.fromInteger(Mp.getVal()); mi = mi.inverse(); // mod p } if (!cp.ring.coFac.getClass().equals(cofacM.getClass())) { logger.info("adjusting coefficents: cofacM = " + cofacM.getClass() + ", cofacM' = " + cp.ring.coFac.getClass()); ModularRingFactory cop = (ModularRingFactory) cp.ring.coFac; cofac = (ModularRingFactory) new ModIntegerRing(cop.getIntegerModul().getVal()); mfac = new GenPolynomialRing(cofac, fac); GenPolynomial mm = PolyUtil. integerFromModularCoefficients(fac, cp); cp = PolyUtil. fromIntegerCoefficients(mfac, mm); } cp = PolyUtil. chineseRemainder(rfac, cp, mi, cm); } // test for completion if (n.compareTo(M) <= 0) { break; } } if (debug) { logger.info("done on M = " + M + ", #primes = " + i); } // convert to integer polynomial q = PolyUtil. integerFromModularCoefficients(fac, cp); return q; } } jas-2.5/src/edu/jas/ufd/FactorQuotient.java0000644000175000017500000001030512004537436021057 0ustar giovannigiovanni/* * $Id: FactorQuotient.java 4067 2012-07-27 16:17:35Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; /** * Rational function coefficients factorization algorithms. This class * implements factorization methods for polynomials over rational functions, * that is, with coefficients from class application.Quotient. * @author Heinz Kredel */ public class FactorQuotient> extends FactorAbstract> { private static final Logger logger = Logger.getLogger(FactorQuotient.class); //private final boolean debug = logger.isInfoEnabled(); /** * Factorization engine for normal coefficients. */ protected final FactorAbstract nengine; /** * No argument constructor. */ protected FactorQuotient() { throw new IllegalArgumentException("don't use this constructor"); } /** * Constructor. * @param fac coefficient quotient ring factory. */ public FactorQuotient(QuotientRing fac) { this(fac, FactorFactory. getImplementation(fac.ring.coFac)); } /** * Constructor. * @param fac coefficient quotient ring factory. * @param nengine factorization engine for polynomials over base * coefficients. */ public FactorQuotient(QuotientRing fac, FactorAbstract nengine) { super(fac); this.nengine = nengine; } /** * GenPolynomial base factorization of a squarefree polynomial. * @param P squarefree GenPolynomial. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ @Override public List>> baseFactorsSquarefree(GenPolynomial> P) { return factorsSquarefree(P); } /** * GenPolynomial factorization of a squarefree polynomial. * @param P squarefree GenPolynomial. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ @Override public List>> factorsSquarefree(GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } //System.out.println("factorsSquarefree, P = " + P); List>> factors = new ArrayList>>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing> pfac = P.ring; GenPolynomial> Pr = P; Quotient ldcf = P.leadingBaseCoefficient(); if (!ldcf.isONE()) { //System.out.println("ldcf = " + ldcf); Pr = Pr.monic(); } QuotientRing qi = (QuotientRing) pfac.coFac; GenPolynomialRing ci = qi.ring; GenPolynomialRing> ifac = new GenPolynomialRing>(ci, pfac); GenPolynomial> Pi = PolyUfdUtil. integralFromQuotientCoefficients(ifac, Pr); //System.out.println("Pi = " + Pi); // factor in C[x_1,...,x_n][y_1,...,y_m] List>> irfacts = nengine.recursiveFactorsSquarefree(Pi); if (logger.isInfoEnabled()) { logger.info("irfacts = " + irfacts); } if (irfacts.size() <= 1) { factors.add(P); return factors; } List>> qfacts = PolyUfdUtil. quotientFromIntegralCoefficients(pfac, irfacts); //System.out.println("qfacts = " + qfacts); //qfacts = PolyUtil.monic(qfacts); //System.out.println("qfacts = " + qfacts); if (!ldcf.isONE()) { GenPolynomial> r = qfacts.get(0); qfacts.remove(r); r = r.multiply(ldcf); qfacts.add(0, r); } if (logger.isInfoEnabled()) { logger.info("qfacts = " + qfacts); } factors.addAll(qfacts); return factors; } } jas-2.5/src/edu/jas/ufd/Examples.java0000644000175000017500000001656212003277306017675 0ustar giovannigiovanni/* * $Id: Examples.java 4025 2012-07-23 16:41:43Z kredel $ */ package edu.jas.ufd; import java.util.SortedMap; import org.apache.log4j.BasicConfigurator; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.vector.GenMatrix; import edu.jas.vector.GenMatrixRing; /** * Examples for ufd and elementaty integration usage. * @author Heinz Kredel. */ public class Examples { /** * main. */ public static void main(String[] args) { //BasicConfigurator.configure(); //// no go: example6(); //BasicConfigurator.configure(); //example9(); example1(); BasicConfigurator.configure(); example10(); ComputerThreads.terminate(); } /** * example1 with GenMatrix. */ public static void example1() { System.out.println("\n\n example 1"); BigInteger cfac; GenPolynomialRing fac; QuotientRing efac; GenPolynomialRing> qfac; GenMatrixRing>> mfac; cfac = new BigInteger(); System.out.println("cfac = " + cfac); fac = new GenPolynomialRing(cfac,2); System.out.println(" fac = " + fac); efac = new QuotientRing( fac ); System.out.println("efac = " + efac); String[] v = new String[] {"x", "y", "z" }; qfac = new GenPolynomialRing>( efac, 3, v ); System.out.println("qfac = " + qfac); mfac = new GenMatrixRing>>( qfac, 3, 3 ); System.out.println("mfac = " + mfac); GenPolynomial> p; p = qfac.random(3,4,2,0.3f); System.out.println("\np = " + p); GenMatrix>> m; m = mfac.random(3,0.4f); System.out.println("\nm = " + m); } /** * example6. Partial fraction decomposition. */ public static void example6() { System.out.println("\n\nexample 6"); // http://www.apmaths.uwo.ca/~rcorless/AM563/NOTES/Nov_16_95/node13.html TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); //String[] alpha = new String[] { "alpha" }; String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); // ( 7 x^6 + 1 ) / ( x^7 + x + 1 ) GenPolynomial D = pfac.parse("x^7 + x + 1"); GenPolynomial N = PolyUtil. baseDeriviative(D); FactorRational engine = new FactorRational(); PartialFraction F = engine.baseAlgebraicPartialFraction(N, D); System.out.println("\nintegral " + F); } /** * example9. Rothstein-Trager and absolute factorization algorithm. */ public static void example9() { System.out.println("\n\nexample 9"); TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); //String[] alpha = new String[] { "alpha" }; String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); // 1 / ( x^5 + x - 7 ) GenPolynomial D = pfac.parse("( x^5 + x - 7 )"); GenPolynomial N = pfac.getONE(); FactorRational engine = new FactorRational(); PartialFraction F = engine.baseAlgebraicPartialFraction(N, D); System.out.println("\nintegral " + F); //PartialFraction Fa = engine.baseAlgebraicPartialFractionIrreducibleAbsolute(N,D); //System.out.println("\nintegral_a " + Fa); } /** * example10. factorization in Q(sqrt(2))(x)(sqrt(x))[y]. */ public static void example10() { System.out.println("\n\nexample 10"); TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] var_w2 = new String[] { "w2" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, var_w2); System.out.println("pfac = " + pfac.toScript()); GenPolynomial w2 = pfac.parse(" w2^2 - 2 "); System.out.println("w2 = " + w2); AlgebraicNumberRing a2fac = new AlgebraicNumberRing(w2, true); System.out.println("a2fac = " + a2fac.toScript()); String[] var_x = new String[] { "x" }; GenPolynomialRing> apfac = new GenPolynomialRing>( a2fac, 1, to, var_x); System.out.println("apfac = " + apfac.toScript()); QuotientRing> qfac = new QuotientRing>( apfac); System.out.println("qfac = " + qfac.toScript()); String[] var_wx = new String[] { "wx" }; GenPolynomialRing>> pqfac = new GenPolynomialRing>>( qfac, 1, to, var_wx); System.out.println("pqfac = " + pqfac.toScript()); GenPolynomial>> wx = pqfac.parse(" wx^2 - { x } "); System.out.println("wx = " + wx); AlgebraicNumberRing>> axfac = new AlgebraicNumberRing>>( wx, true); System.out.println("axfac = " + axfac.toScript()); String[] var_y = new String[] { "y" }; GenPolynomialRing>>> apqfac = new GenPolynomialRing>>>( axfac, 1, to, var_y); System.out.println("apqfac = " + apqfac.toScript()); // ( y^2 - x ) * ( y^2 - 2 ), need {} for recursive coefficients GenPolynomial>>> f; f = apqfac.parse(" ( y^2 - { { x } } ) * ( y^2 - 2 )^2 "); System.out.println("f = " + f); FactorAbstract>>> engine = FactorFactory .getImplementation(axfac); System.out.println("engine = " + engine); SortedMap>>>, Long> F = engine .factors(f); System.out.println("factors(f) = " + F); } } jas-2.5/src/edu/jas/ufd/GreatestCommonDivisorModEval.java0000644000175000017500000004016412003277306023651 0ustar giovannigiovanni/* * $Id: GreatestCommonDivisorModEval.java 4025 2012-07-23 16:41:43Z kredel $ */ package edu.jas.ufd; import org.apache.log4j.Logger; import edu.jas.arith.Modular; import edu.jas.arith.ModularRingFactory; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; /** * Greatest common divisor algorithms with modular evaluation algorithm for * recursion. * @author Heinz Kredel */ public class GreatestCommonDivisorModEval & Modular> extends GreatestCommonDivisorAbstract { private static final Logger logger = Logger.getLogger(GreatestCommonDivisorModEval.class); private final boolean debug = logger.isDebugEnabled(); /** * Modular gcd algorithm to use. */ protected final GreatestCommonDivisorAbstract mufd = new GreatestCommonDivisorSimple(); // = new GreatestCommonDivisorPrimitive(); // not okay: = new GreatestCommonDivisorSubres(); /** * Univariate GenPolynomial greatest common divisor. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial baseGcd(GenPolynomial P, GenPolynomial S) { // required as recursion base return mufd.baseGcd(P, S); } /** * Recursive univariate GenPolynomial greatest common divisor. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial> recursiveUnivariateGcd( GenPolynomial> P, GenPolynomial> S) { return mufd.recursiveUnivariateGcd(P, S); } /** * GenPolynomial greatest common divisor, modular evaluation algorithm. * @param P GenPolynomial. * @param S GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial gcd(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } GenPolynomialRing fac = P.ring; // recusion base case for univariate polynomials if (fac.nvar <= 1) { GenPolynomial T = baseGcd(P, S); return T; } long e = P.degree(fac.nvar-1); long f = S.degree(fac.nvar-1); if ( e == 0 && f == 0 ) { GenPolynomialRing> rfac = fac.recursive(1); GenPolynomial Pc = PolyUtil. recursive(rfac, P).leadingBaseCoefficient(); GenPolynomial Sc = PolyUtil. recursive(rfac, S).leadingBaseCoefficient(); GenPolynomial r = gcd(Pc,Sc); return r.extend(fac,0,0L); } GenPolynomial q; GenPolynomial r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } r = r.abs(); q = q.abs(); // setup factories ModularRingFactory cofac = (ModularRingFactory) P.ring.coFac; if (!cofac.isField()) { logger.warn("cofac is not a field: " + cofac); } GenPolynomialRing> rfac = fac.recursive(fac.nvar - 1); GenPolynomialRing mfac = new GenPolynomialRing(cofac, rfac); GenPolynomialRing ufac = (GenPolynomialRing) rfac.coFac; //GenPolynomialRing mfac = new GenPolynomialRing(cofac, fac.nvar - 1, fac.tord); //GenPolynomialRing ufac = new GenPolynomialRing(cofac, 1, fac.tord); //GenPolynomialRing> rfac = new GenPolynomialRing>(ufac, fac.nvar - 1, fac.tord); // convert polynomials GenPolynomial> qr; GenPolynomial> rr; qr = PolyUtil. recursive(rfac, q); rr = PolyUtil. recursive(rfac, r); // compute univariate contents and primitive parts GenPolynomial a = recursiveContent(rr); GenPolynomial b = recursiveContent(qr); // gcd of univariate coefficient contents GenPolynomial c = gcd(a, b); rr = PolyUtil. recursiveDivide(rr, a); qr = PolyUtil. recursiveDivide(qr, b); if (rr.isONE()) { rr = rr.multiply(c); r = PolyUtil. distribute(fac, rr); return r; } if (qr.isONE()) { qr = qr.multiply(c); q = PolyUtil. distribute(fac, qr); return q; } // compute normalization factor GenPolynomial ac = rr.leadingBaseCoefficient(); GenPolynomial bc = qr.leadingBaseCoefficient(); GenPolynomial cc = gcd(ac, bc); // compute degrees and degree vectors ExpVector rdegv = rr.degreeVector(); ExpVector qdegv = qr.degreeVector(); long rd0 = PolyUtil. coeffMaxDegree(rr); long qd0 = PolyUtil. coeffMaxDegree(qr); long cd0 = cc.degree(0); long G = (rd0 >= qd0 ? rd0 : qd0) + cd0; // initialize element and degree vector ExpVector wdegv = rdegv.subst(0, rdegv.getVal(0) + 1); // +1 seems to be a hack for the unlucky prime test MOD inc = cofac.getONE(); long i = 0; long en = cofac.getIntegerModul().longValue() - 1; // just a stopper MOD end = cofac.fromInteger(en); MOD mi; GenPolynomial M = null; GenPolynomial mn; GenPolynomial qm; GenPolynomial rm; GenPolynomial cm; GenPolynomial> cp = null; if (debug) { logger.debug("c = " + c); logger.debug("cc = " + cc); logger.debug("G = " + G); logger.info("wdegv = " + wdegv); } for (MOD d = cofac.getZERO(); d.compareTo(end) <= 0; d = d.sum(inc)) { if (++i >= en) { logger.warn("elements of Z_p exhausted, en = " + en); return mufd.gcd(P, S); //throw new ArithmeticException("prime list exhausted"); } // map normalization factor MOD nf = PolyUtil. evaluateMain(cofac, cc, d); if (nf.isZERO()) { continue; } // map polynomials qm = PolyUtil. evaluateFirstRec(ufac, mfac, qr, d); if (qm.isZERO() || !qm.degreeVector().equals(qdegv)) { continue; } rm = PolyUtil. evaluateFirstRec(ufac, mfac, rr, d); if (rm.isZERO() || !rm.degreeVector().equals(rdegv)) { continue; } if (debug) { logger.debug("eval d = " + d); } // compute modular gcd in recursion cm = gcd(rm, qm); //System.out.println("cm = " + cm); // test for constant g.c.d if (cm.isConstant()) { logger.debug("cm.isConstant = " + cm + ", c = " + c); if (c.ring.nvar < cm.ring.nvar) { c = c.extend(mfac, 0, 0); } cm = cm.abs().multiply(c); q = cm.extend(fac, 0, 0); logger.debug("q = " + q + ", c = " + c); return q; } // test for unlucky prime ExpVector mdegv = cm.degreeVector(); if (wdegv.equals(mdegv)) { // TL = 0 // prime ok, next round if (M != null) { if (M.degree(0) > G) { logger.info("deg(M) > G: " + M.degree(0) + " > " + G); // continue; // why should this be required? } } } else { // TL = 3 boolean ok = false; if (wdegv.multipleOf(mdegv)) { // TL = 2 M = null; // init chinese remainder ok = true; // prime ok } if (mdegv.multipleOf(wdegv)) { // TL = 1 continue; // skip this prime } if (!ok) { M = null; // discard chinese remainder and previous work continue; // prime not ok } } // prepare interpolation algorithm cm = cm.multiply(nf); if (M == null) { // initialize interpolation M = ufac.getONE(); cp = rfac.getZERO(); wdegv = wdegv.gcd(mdegv); //EVGCD(wdegv,mdegv); } // interpolate mi = PolyUtil. evaluateMain(cofac, M, d); mi = mi.inverse(); // mod p cp = PolyUtil.interpolate(rfac, cp, M, mi, cm, d); mn = ufac.getONE().multiply(d); mn = ufac.univariate(0).subtract(mn); M = M.multiply(mn); // test for completion if (M.degree(0) > G) { break; } //long cmn = PolyUtil.coeffMaxDegree(cp); //if ( M.degree(0) > cmn ) { // does not work: only if cofactors are also considered? // break; //} } // remove normalization cp = recursivePrimitivePart(cp).abs(); cp = cp.multiply(c); q = PolyUtil. distribute(fac, cp); return q; } /** * Univariate GenPolynomial resultant. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial baseResultant(GenPolynomial P, GenPolynomial S) { // required as recursion base return mufd.baseResultant(P, S); } /** * Univariate GenPolynomial recursive resultant. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial> recursiveUnivariateResultant(GenPolynomial> P, GenPolynomial> S) { // only in this class return recursiveResultant(P,S); } /** * GenPolynomial resultant, modular evaluation algorithm. * @param P GenPolynomial. * @param S GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial resultant(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } GenPolynomialRing fac = P.ring; // recusion base case for univariate polynomials if (fac.nvar <= 1) { GenPolynomial T = mufd.baseResultant(P, S); return T; } long e = P.degree(fac.nvar-1); long f = S.degree(fac.nvar-1); if ( e == 0 && f == 0 ) { GenPolynomialRing> rfac = fac.recursive(1); GenPolynomial Pc = PolyUtil. recursive(rfac, P).leadingBaseCoefficient(); GenPolynomial Sc = PolyUtil. recursive(rfac, S).leadingBaseCoefficient(); GenPolynomial r = resultant(Pc,Sc); return r.extend(fac,0,0L); } GenPolynomial q; GenPolynomial r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } // setup factories ModularRingFactory cofac = (ModularRingFactory) P.ring.coFac; if (!cofac.isField()) { logger.warn("cofac is not a field: " + cofac); } GenPolynomialRing> rfac = fac.recursive(fac.nvar - 1); GenPolynomialRing mfac = new GenPolynomialRing(cofac, rfac); GenPolynomialRing ufac = (GenPolynomialRing) rfac.coFac; // convert polynomials GenPolynomial> qr = PolyUtil. recursive(rfac, q); GenPolynomial> rr = PolyUtil. recursive(rfac, r); // compute degrees and degree vectors ExpVector qdegv = qr.degreeVector(); ExpVector rdegv = rr.degreeVector(); long qd0 = PolyUtil. coeffMaxDegree(qr); long rd0 = PolyUtil. coeffMaxDegree(rr); qd0 = ( qd0 == 0 ? 1 : qd0 ); rd0 = ( rd0 == 0 ? 1 : rd0 ); long qd1 = qr.degree(); long rd1 = rr.degree(); qd1 = ( qd1 == 0 ? 1 : qd1 ); rd1 = ( rd1 == 0 ? 1 : rd1 ); long G = qd0 * rd1 + rd0 * qd1 + 1; // initialize element MOD inc = cofac.getONE(); long i = 0; long en = cofac.getIntegerModul().longValue() - 1; // just a stopper MOD end = cofac.fromInteger(en); MOD mi; GenPolynomial M = null; GenPolynomial mn; GenPolynomial qm; GenPolynomial rm; GenPolynomial cm; GenPolynomial> cp = null; if (debug) { //logger.info("qr = " + qr + ", q = " + q); //logger.info("rr = " + rr + ", r = " + r); //logger.info("qd0 = " + qd0); //logger.info("rd0 = " + rd0); logger.info("G = " + G); //logger.info("rdegv = " + rdegv); // + ", rr.degree(0) = " + rr.degree(0)); //logger.info("qdegv = " + qdegv); // + ", qr.degree(0) = " + qr.degree(0)); } for (MOD d = cofac.getZERO(); d.compareTo(end) <= 0; d = d.sum(inc)) { if (++i >= en) { logger.warn("elements of Z_p exhausted, en = " + en + ", p = " + cofac.getIntegerModul()); return mufd.resultant(P, S); //throw new ArithmeticException("prime list exhausted"); } // map polynomials qm = PolyUtil. evaluateFirstRec(ufac, mfac, qr, d); //logger.info("qr(" + d + ") = " + qm + ", qr = " + qr); if (qm.isZERO() || !qm.degreeVector().equals(qdegv)) { if (debug) { logger.info("un-lucky evaluation point " + d + ", qm = " + qm.degreeVector() + " < " + qdegv); } continue; } rm = PolyUtil. evaluateFirstRec(ufac, mfac, rr, d); //logger.info("rr(" + d + ") = " + rm + ", rr = " + rr); if (rm.isZERO() || !rm.degreeVector().equals(rdegv)) { if (debug) { logger.info("un-lucky evaluation point " + d + ", rm = " + rm.degreeVector() + " < " + rdegv); } continue; } // compute modular resultant in recursion cm = resultant(rm, qm); //System.out.println("cm = " + cm); // prepare interpolation algorithm if (M == null) { // initialize interpolation M = ufac.getONE(); cp = rfac.getZERO(); } // interpolate mi = PolyUtil. evaluateMain(cofac, M, d); mi = mi.inverse(); // mod p cp = PolyUtil.interpolate(rfac, cp, M, mi, cm, d); //logger.info("cp = " + cp); mn = ufac.getONE().multiply(d); mn = ufac.univariate(0).subtract(mn); M = M.multiply(mn); // test for completion if (M.degree(0) > G) { if (debug) { logger.info("last lucky evaluation point " + d); } break; } //logger.info("M = " + M); } // distribute q = PolyUtil. distribute(fac, cp); return q; } } jas-2.5/src/edu/jas/ufd/SquarefreeFactory.java0000644000175000017500000002244612004537436021553 0ustar giovannigiovanni/* * $Id: SquarefreeFactory.java 4067 2012-07-27 16:17:35Z kredel $ */ package edu.jas.ufd; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Squarefree factorization algorithms factory. Select appropriate squarefree * factorization engine based on the coefficient types. * @author Heinz Kredel * @usage To create objects that implement the Squarefree interface * use the SquarefreeFactory. It will select an appropriate * implementation based on the types of polynomial coefficients C. To * obtain an implementation use getImplementation(), it * returns an object of a class which extends the * SquarefreeAbstract class which implements the * Squarefree interface. * *
 * Squarefree<CT> engine;
 * engine = SquarefreeFactory.<CT> getImplementation(cofac);
 * c = engine.squarefreeFactors(a);
 * 
* * For example, if the coefficient type is BigInteger, the usage looks * like * *
 * BigInteger cofac = new BigInteger();
 * Squarefree<BigInteger> engine;
 * engine = SquarefreeFactory.getImplementation(cofac);
 * Sm = engine.sqaurefreeFactors(poly);
 * 
* * @see edu.jas.ufd.Squarefree#squarefreeFactors(edu.jas.poly.GenPolynomial P) */ public class SquarefreeFactory { private static final Logger logger = Logger.getLogger(SquarefreeFactory.class); /** * Protected factory constructor. */ protected SquarefreeFactory() { } /** * Determine suitable implementation of factorization algorithm, case * ModInteger. * @param fac ModIntegerRing. * @return squarefree factorization algorithm implementation. */ public static SquarefreeAbstract getImplementation(ModIntegerRing fac) { return new SquarefreeFiniteFieldCharP(fac); } /** * Determine suitable implementation of factorization algorithm, case * ModLong. * @param fac ModLongRing. * @return squarefree factorization algorithm implementation. */ public static SquarefreeAbstract getImplementation(ModLongRing fac) { return new SquarefreeFiniteFieldCharP(fac); } /** * Determine suitable implementation of squarefree factorization algorithm, * case BigInteger. * @param fac BigInteger. * @return squarefree factorization algorithm implementation. */ public static SquarefreeAbstract getImplementation(BigInteger fac) { return new SquarefreeRingChar0(fac); } /** * Determine suitable implementation of squarefree factorization algorithms, * case BigRational. * @param fac BigRational. * @return squarefree factorization algorithm implementation. */ public static SquarefreeAbstract getImplementation(BigRational fac) { return new SquarefreeFieldChar0(fac); } /** * Determine suitable implementation of squarefree factorization algorithms, * case AlgebraicNumber<C>. * @param fac AlgebraicNumberRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return squarefree factorization algorithm implementation. */ public static > SquarefreeAbstract> getImplementation( AlgebraicNumberRing fac) { PolyUfdUtil. ensureFieldProperty(fac); if (fac.isField()) { if (fac.characteristic().signum() == 0) { return new SquarefreeFieldChar0>(fac); } if (fac.isFinite()) { return new SquarefreeFiniteFieldCharP>(fac); } return new SquarefreeInfiniteAlgebraicFieldCharP(fac); } throw new ArithmeticException("eventually no integral domain " + fac.getClass().getName()); } /** * Determine suitable implementation of squarefree factorization algorithms, * case Quotient<C>. * @param fac QuotientRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return squarefree factorization algorithm implementation. */ public static > SquarefreeAbstract> getImplementation( QuotientRing fac) { if (fac.characteristic().signum() == 0) { return new SquarefreeFieldChar0>(fac); } return new SquarefreeInfiniteFieldCharP(fac); } /** * Determine suitable implementation of squarefree factorization algorithms, * case GenPolynomial<C>. * @param fac GenPolynomialRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return squarefree factorization algorithm implementation. */ public static > SquarefreeAbstract getImplementation(GenPolynomialRing fac) { return getImplementationPoly(fac); } /* * Determine suitable implementation of squarefree factorization algorithms, * case GenPolynomial<C>. * @param fac GenPolynomialRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return squarefree factorization algorithm implementation. */ @SuppressWarnings("unchecked") protected static > SquarefreeAbstract getImplementationPoly( GenPolynomialRing fac) { if (fac.characteristic().signum() == 0) { if (fac.coFac.isField()) { return new SquarefreeFieldChar0(fac.coFac); } return new SquarefreeRingChar0(fac.coFac); } if (fac.coFac.isFinite()) { return new SquarefreeFiniteFieldCharP(fac.coFac); } Object ocfac = fac.coFac; SquarefreeAbstract saq = null; if (ocfac instanceof QuotientRing) { QuotientRing qf = (QuotientRing) ocfac; saq = new SquarefreeInfiniteFieldCharP(qf); } else if (ocfac instanceof AlgebraicNumberRing) { AlgebraicNumberRing af = (AlgebraicNumberRing) ocfac; saq = new SquarefreeInfiniteAlgebraicFieldCharP(af); } if (saq == null) { throw new IllegalArgumentException("no squarefree factorization " + fac.coFac); } SquarefreeAbstract sa = (SquarefreeAbstract) saq; return sa; } /** * Determine suitable implementation of squarefree factorization algorithms, * other cases. * @param coefficient type * @param fac RingFactory<C>. * @return squarefree factorization algorithm implementation. */ @SuppressWarnings("unchecked") public static > SquarefreeAbstract getImplementation(RingFactory fac) { //logger.info("fac = " + fac.getClass().getName()); //System.out.println("fac_o = " + fac.getClass().getName()); SquarefreeAbstract/*raw type*/ufd = null; AlgebraicNumberRing afac = null; QuotientRing qfac = null; GenPolynomialRing pfac = null; Object ofac = fac; if (ofac instanceof BigInteger) { ufd = new SquarefreeRingChar0(fac); } else if (ofac instanceof BigRational) { ufd = new SquarefreeFieldChar0(fac); } else if (ofac instanceof ModIntegerRing) { ufd = new SquarefreeFiniteFieldCharP(fac); } else if (ofac instanceof ModLongRing) { ufd = new SquarefreeFiniteFieldCharP(fac); } else if (ofac instanceof AlgebraicNumberRing) { afac = (AlgebraicNumberRing) ofac; //ofac = afac.ring.coFac; //System.out.println("o_afac = " + ofac); ufd = getImplementation(afac); } else if (ofac instanceof QuotientRing) { qfac = (QuotientRing) ofac; ufd = getImplementation(qfac); } else if (ofac instanceof GenPolynomialRing) { pfac = (GenPolynomialRing) ofac; ufd = getImplementationPoly(pfac); } else if (fac.isField()) { //System.out.println("fac_field = " + fac); if (fac.characteristic().signum() == 0) { ufd = new SquarefreeFieldChar0(fac); } else { if (fac.isFinite()) { ufd = new SquarefreeFiniteFieldCharP(fac); } else { ufd = new SquarefreeInfiniteFieldCharP/*raw*/(fac); } } } else if (fac.characteristic().signum() == 0) { ufd = new SquarefreeRingChar0(fac); } else { throw new IllegalArgumentException("no squarefree factorization implementation for " + fac.getClass().getName()); } logger.debug("ufd = " + ufd); return (SquarefreeAbstract) ufd; } } jas-2.5/src/edu/jas/ufd/package.html0000644000175000017500000000775712027161170017540 0ustar giovannigiovanni Unique Factorization Domain package

Unique factorization domain package.

This package contains classes for polynomials rings as unique factorization domains. Provided methods with interface GreatestCommonDivisor are e.g. greatest common divisors gcd(), primitive part primitivePart() or coPrime(). The different classes implement variants of polynomial remainder sequences (PRS) and modular methods. Interface Squarefree provides the greatest squarefree factor squarefreeFactor() and a complete squarefree decompostion can be obtained with method squarefreeFactors(). There is a Factorization interface with an FactorAbstract class with common codes. Factorization of univariate polynomials exists for several coefficient rings: modulo primes in class FactorModular, over integers in class FactorInteger, over rational numbers in class FactorRational, over algebraic numbers in class FactorAlgebraic<C> and over rational functions in class FactorQuotient<C> (where for the last two classes C can be any other ring for which the FactorFactory. getImplementation returns an implementation). Multivatiate polynomials over the integers (and rational numbers) are factored using the algorithm of P. Wang. For other coeffcients the multivatiate polynomials are reduced to univariate polynomials via Kronecker substitution. The rational function class Quotient computes quotients of polynomials reduced to lowest terms.

To choose the correct implementation always use the factory classes GCDFactory, SquarefreeFactory and FactorFactory with methods getImplementation() or getProxy(). These methods will take care of all possible (implemented) coefficient rings properties. The polynomial coefficients must implement the GcdRingElem interface and so must allow greatest common divisor computations. Greatest common divisor computation is completely generic and works for any implemented integral domain. If special, optimized implementations exist they will be used. Squarefree decomposition is also completely generic and works for any implemented integral domain. There are no special, optimized implementations. Factorization is generic relative to the implemented ring constructions: algebraic field extensions and transcendent field extensions. Implemented base cases are modular coefficient, integer coefficients and rational number coefficients.

The implementation follows Geddes & Czapor & Labahn Algorithms for Computer Algebra and Cohen A Curse in Computational Algebraic Number Theory. See also Kaltofen Factorization of Polynomials in Computing Supplement, Springer, 1982, Davenport & Gianni & Trager Scratchpad's View of Algebra II: A Categorical View of Factorization in ISSAC'91 and the ALDES/SAC2 code as contained in MAS.


Heinz Kredel

Last modified: Fri Sep 21 21:56:48 CEST 2012

$Id: package.html 4215 2012-09-21 21:56:08Z kredel $

jas-2.5/src/edu/jas/ufd/ExamplesPartialFraction.java0000644000175000017500000001416111333540372022672 0ustar giovannigiovanni/* * $Id: ExamplesPartialFraction.java 2996 2010-02-07 13:32:42Z kredel $ */ package edu.jas.ufd; import edu.jas.arith.BigRational; import edu.jas.kern.ComputerThreads; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; /** * Examples related to partial fraction decomposition. * * @author Heinz Kredel */ public class ExamplesPartialFraction { /** * Main program. * * @param args */ public static void main(String[] args) { example11(); example12(); example13(); example14(); // BasicConfigurator.configure(); example15(); example16(); example17(); ComputerThreads.terminate(); } /** * example11. Rothstein-Trager algorithm. */ public static void example11() { System.out.println("\n\nexample 11"); TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); // 1 / ( x^2 - 2 ) GenPolynomial D = pfac.parse("x^2 - 2"); GenPolynomial N = pfac.getONE(); FactorRational engine = (FactorRational) FactorFactory.getImplementation(cfac); PartialFraction F = engine.baseAlgebraicPartialFractionIrreducible(N, D); System.out.println("\nintegral " + F); } /** * example12. Rothstein-Trager algorithm. */ public static void example12() { System.out.println("\n\nexample 12"); TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); // 1 / ( x^3 + x ) GenPolynomial D = pfac.parse("x^3 + x"); GenPolynomial N = pfac.getONE(); FactorRational engine = (FactorRational) FactorFactory.getImplementation(cfac); PartialFraction F = engine.baseAlgebraicPartialFraction(N, D); System.out.println("\nintegral " + F); } /** * example13. Rothstein-Trager algorithm. */ public static void example13() { System.out.println("\n\nexample 13"); TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); // 1 / ( x^6 - 5 x^4 + 5 x^2 + 4 ) GenPolynomial D = pfac.parse("x^6 - 5 x^4 + 5 x^2 + 4"); GenPolynomial N = pfac.getONE(); FactorRational engine = (FactorRational) FactorFactory.getImplementation(cfac); PartialFraction F = engine.baseAlgebraicPartialFraction(N, D); System.out.println("\nintegral " + F); } /** * example14. Rothstein-Trager algorithm. */ public static void example14() { System.out.println("\n\nexample 14"); TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); // 1 / ( x^4 + 4 ) GenPolynomial D = pfac.parse("x^4 + 4"); GenPolynomial N = pfac.getONE(); FactorRational engine = (FactorRational) FactorFactory.getImplementation(cfac); PartialFraction F = engine.baseAlgebraicPartialFraction(N, D); System.out.println("\nintegral " + F); } /** * example15. Rothstein-Trager algorithm. */ public static void example15() { System.out.println("\n\nexample 15"); TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); // 1 / ( x^3 - 2 ) GenPolynomial D = pfac.parse("x^3 - 2"); GenPolynomial N = pfac.getONE(); FactorRational engine = (FactorRational) FactorFactory.getImplementation(cfac); PartialFraction F = engine.baseAlgebraicPartialFraction(N, D); System.out.println("\nintegral " + F); } /** * example16. Rothstein-Trager algorithm. */ public static void example16() { System.out.println("\n\nexample 16"); TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); // 1 / ( x - 1 ) ( x - 2 ) ( x - 3 ) GenPolynomial D = pfac.parse("( x - 1 ) * ( x - 2 ) * ( x - 3 )"); GenPolynomial N = pfac.getONE(); FactorRational engine = (FactorRational) FactorFactory.getImplementation(cfac); PartialFraction F = engine.baseAlgebraicPartialFraction(N, D); System.out.println("\nintegral " + F); } /** * example17. Absolute factorization of example15. */ public static void example17() { System.out.println("\n\nexample 17"); TermOrder to = new TermOrder(TermOrder.INVLEX); BigRational cfac = new BigRational(1); String[] vars = new String[] { "x" }; GenPolynomialRing pfac = new GenPolynomialRing(cfac, 1, to, vars); // 1 / ( x^3 - 2 ) GenPolynomial D = pfac.parse("x^3 - 2"); GenPolynomial N = pfac.getONE(); FactorRational engine = (FactorRational) FactorFactory.getImplementation(cfac); PartialFraction F = engine.baseAlgebraicPartialFractionIrreducibleAbsolute(N, D); System.out.println("\nintegral " + F); } } jas-2.5/src/edu/jas/ufd/NoLiftingException.java0000644000175000017500000000115311317152746021664 0ustar giovannigiovanni/* * $Id: NoLiftingException.java 2952 2009-12-31 16:48:39Z kredel $ */ package edu.jas.ufd; /** * Non existing Hensel lifting. Exception to be thrown when a valid * Hensel lifting cannot be constructed. * @author Heinz Kredel */ public class NoLiftingException extends Exception { public NoLiftingException() { super("NoLiftingException"); } public NoLiftingException(String c) { super(c); } public NoLiftingException(String c, Throwable t) { super(c, t); } public NoLiftingException(Throwable t) { super("NoLiftingException", t); } } jas-2.5/src/edu/jas/ufd/SquarefreeAbstract.java0000644000175000017500000005462412014163702021702 0ustar giovannigiovanni/* * $Id: SquarefreeAbstract.java 4115 2012-08-19 13:18:59Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Abstract squarefree decomposition class. * @author Heinz Kredel */ public abstract class SquarefreeAbstract> implements Squarefree { /** * GCD engine for respective base coefficients. */ protected final GreatestCommonDivisorAbstract engine; /** * Constructor. */ public SquarefreeAbstract(GreatestCommonDivisorAbstract engine) { this.engine = engine; } /** * GenPolynomial polynomial greatest squarefree divisor. * @param P GenPolynomial. * @return squarefree(pp(P)). */ public abstract GenPolynomial baseSquarefreePart(GenPolynomial P); /** * GenPolynomial polynomial squarefree factorization. * @param A GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i^{e_i} and p_i squarefree. */ public abstract SortedMap, Long> baseSquarefreeFactors(GenPolynomial A); /** * GenPolynomial recursive polynomial greatest squarefree divisor. * @param P recursive univariate GenPolynomial. * @return squarefree(pp(P)). */ public abstract GenPolynomial> recursiveUnivariateSquarefreePart( GenPolynomial> P); /** * GenPolynomial recursive univariate polynomial squarefree factorization. * @param P recursive univariate GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i^{e_i} and p_i squarefree. */ public abstract SortedMap>, Long> recursiveUnivariateSquarefreeFactors( GenPolynomial> P); /** * GenPolynomial greatest squarefree divisor. * @param P GenPolynomial. * @return squarefree(P) a primitive respectively monic polynomial. */ public abstract GenPolynomial squarefreePart(GenPolynomial P); /** * GenPolynomial test if is squarefree. * @param P GenPolynomial. * @return true if P is squarefree, else false. */ public boolean isSquarefree(GenPolynomial P) { GenPolynomial S = squarefreePart(P); GenPolynomial Ps = P; if (P.ring.coFac.isField()) { Ps = Ps.monic(); } else { Ps = engine.basePrimitivePart(Ps); } boolean f = Ps.equals(S); //if (!f) { //System.out.println("\nisSquarefree: " + f); //System.out.println("S = " + S); //System.out.println("P = " + P); //} return f; } /** * GenPolynomial list test if squarefree. * @param L list of GenPolynomial. * @return true if each P in L is squarefree, else false. */ public boolean isSquarefree(List> L) { if (L == null || L.isEmpty()) { return true; } for (GenPolynomial P : L) { if (!isSquarefree(P)) { return false; } } return true; } /** * Recursive GenPolynomial test if is squarefree. * @param P recursive univariate GenPolynomial. * @return true if P is squarefree, else false. */ public boolean isRecursiveSquarefree(GenPolynomial> P) { GenPolynomial> S = recursiveUnivariateSquarefreePart(P); boolean f = P.equals(S); if (!f) { System.out.println("\nisSquarefree: " + f); System.out.println("S = " + S); System.out.println("P = " + P); } return f; } /** * GenPolynomial squarefree factorization. * @param P GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i^{e_i} and p_i squarefree. */ public abstract SortedMap, Long> squarefreeFactors(GenPolynomial P); /** * GenPolynomial squarefree and co-prime list. * @param A list of GenPolynomials. * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant * a in A there exists b in B with b|a and each b in B is * squarefree. B does not contain zero or constant polynomials. */ public List> coPrimeSquarefree(List> A) { if (A == null || A.isEmpty()) { return A; } List> S = new ArrayList>(); for (GenPolynomial g : A) { SortedMap, Long> sm = squarefreeFactors(g); S.addAll(sm.keySet()); } List> B = engine.coPrime(S); return B; } /** * GenPolynomial squarefree and co-prime list. * @param a polynomial. * @param P squarefree co-prime list of GenPolynomials. * @return B with gcd(b,c) = 1 for all b != c in B and for non-constant a * there exists b in P with b|a. B does not contain zero or constant * polynomials. */ public List> coPrimeSquarefree(GenPolynomial a, List> P) { if (a == null || a.isZERO() || a.isConstant()) { return P; } SortedMap, Long> sm = squarefreeFactors(a); List> B = P; for (GenPolynomial f : sm.keySet()) { B = engine.coPrime(f, B); } return B; } /** * Test if list of GenPolynomials is squarefree and co-prime. * @param B list of GenPolynomials. * @return true, if for all b != c in B gcd(b,c) = 1 and each b in B is * squarefree, else false. */ public boolean isCoPrimeSquarefree(List> B) { if (B == null || B.isEmpty()) { return true; } if (!engine.isCoPrime(B)) { return false; } return isSquarefree(B); } /** * Normalize factorization. p'_i > 0 for i > 1 and p'_1 != 1 if k > * 1. * @param F = [p_1->e_1;, ..., p_k->e_k]. * @return F' = [p'_1->e_1, ..., p'_k->e_k]. */ public SortedMap, Long> normalizeFactorization(SortedMap, Long> F) { if (F == null || F.size() <= 1) { return F; } List> Fp = new ArrayList>(F.keySet()); GenPolynomial f0 = Fp.get(0); if (f0.ring.characteristic().signum() != 0) { // only ordered coefficients return F; } long e0 = F.get(f0); SortedMap, Long> Sp = new TreeMap, Long>(); for (int i = 1; i < Fp.size(); i++) { GenPolynomial fi = Fp.get(i); long ei = F.get(fi); if (fi.signum() < 0) { //System.out.println("e0 = " + e0 + ", f0 = " + f0); //System.out.println("ei = " + ei + ", fi = " + fi); fi = fi.negate(); if (ei % 2 != 0) { // && e0 % 2 != 0 f0 = f0.negate(); } } Sp.put(fi, ei); } if (!f0.isONE()) { Sp.put(f0, e0); } return Sp; } /** * GenPolynomial is (squarefree) factorization. * @param P GenPolynomial. * @param F = [p_1,...,p_k]. * @return true if P = prod_{i=1,...,r} p_i, else false. */ public boolean isFactorization(GenPolynomial P, List> F) { if (P == null || F == null) { throw new IllegalArgumentException("P and F may not be null"); } GenPolynomial t = P.ring.getONE(); for (GenPolynomial f : F) { t = t.multiply(f); } boolean f = P.equals(t) || P.equals(t.negate()); if (!f) { System.out.println("\nfactorization(list): " + f); System.out.println("F = " + F); System.out.println("P = " + P); System.out.println("t = " + t); } return f; } /** * Count number of factors in a (squarefree) factorization. * @param F = [p_1 -> e_1, ..., p_k -> e_k]. * @return sum_{i=1,...,k} e_i. */ public long factorCount(SortedMap, Long> F) { if (F == null || F.isEmpty()) { return 0L; } long f = 0L; for (Long e : F.values()) { f += e; } return f; } /** * GenPolynomial is (squarefree) factorization. * @param P GenPolynomial. * @param F = [p_1 -> e_1, ..., p_k -> e_k]. * @return true if P = prod_{i=1,...,k} p_i**e_i, else false. */ public boolean isFactorization(GenPolynomial P, SortedMap, Long> F) { if (P == null || F == null) { throw new IllegalArgumentException("P and F may not be null"); } if (P.isZERO() && F.size() == 0) { return true; } GenPolynomial t = P.ring.getONE(); for (Map.Entry, Long> me : F.entrySet()) { GenPolynomial f = me.getKey(); Long E = me.getValue(); // F.get(f); long e = E.longValue(); GenPolynomial g = Power.> positivePower(f, e); t = t.multiply(g); } boolean f = P.equals(t) || P.equals(t.negate()); if (!f) { //System.out.println("P = " + P); //System.out.println("t = " + t); P = P.monic(); t = t.monic(); f = P.equals(t) || P.equals(t.negate()); if (f) { return f; } System.out.println("\nfactorization(map): " + f); System.out.println("F = " + F); System.out.println("P = " + P); System.out.println("t = " + t); //RuntimeException e = new RuntimeException("fac-map"); //e.printStackTrace(); //throw e; } return f; } /** * GenPolynomial is (squarefree) factorization. * @param P GenPolynomial. * @param F = [p_1 -> e_1, ..., p_k -> e_k]. * @return true if P = prod_{i=1,...,k} p_i**e_i, else false. */ public boolean isRecursiveFactorization(GenPolynomial> P, SortedMap>, Long> F) { if (P == null || F == null) { throw new IllegalArgumentException("P and F may not be null"); } if (P.isZERO() && F.size() == 0) { return true; } GenPolynomial> t = P.ring.getONE(); for (Map.Entry>, Long> me : F.entrySet()) { GenPolynomial> f = me.getKey(); Long E = me.getValue(); // F.get(f); long e = E.longValue(); GenPolynomial> g = Power.>> positivePower(f, e); t = t.multiply(g); } boolean f = P.equals(t) || P.equals(t.negate()); if (!f) { //System.out.println("P = " + P); //System.out.println("t = " + t); GenPolynomialRing cf = (GenPolynomialRing) P.ring.coFac; GreatestCommonDivisorAbstract engine = GCDFactory.getProxy(cf.coFac); GenPolynomial> Pp = engine.recursivePrimitivePart(P); Pp = PolyUtil. monic(Pp); GenPolynomial> tp = engine.recursivePrimitivePart(t); tp = PolyUtil. monic(tp); f = Pp.equals(tp) || Pp.equals(tp.negate()); if (f) { return f; } System.out.println("\nfactorization(map): " + f); System.out.println("F = " + F); System.out.println("P = " + P); System.out.println("t = " + t); System.out.println("Pp = " + Pp); System.out.println("tp = " + tp); //RuntimeException e = new RuntimeException("fac-map"); //e.printStackTrace(); //throw e; } return f; } /** * GenPolynomial recursive polynomial greatest squarefree divisor. * @param P recursive GenPolynomial. * @return squarefree(pp(P)). */ public GenPolynomial> recursiveSquarefreePart(GenPolynomial> P) { if (P == null || P.isZERO()) { return P; } if (P.ring.nvar <= 1) { return recursiveUnivariateSquarefreePart(P); } // distributed polynomials squarefree part GenPolynomialRing> rfac = P.ring; RingFactory> rrfac = rfac.coFac; GenPolynomialRing cfac = (GenPolynomialRing) rrfac; GenPolynomialRing dfac = cfac.extend(rfac.nvar); GenPolynomial Pd = PolyUtil. distribute(dfac, P); GenPolynomial Dd = squarefreePart(Pd); // convert to recursive GenPolynomial> C = PolyUtil. recursive(rfac, Dd); return C; } /** * GenPolynomial recursive polynomial squarefree factorization. * @param P recursive GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i^{e_i} and p_i squarefree. */ public SortedMap>, Long> recursiveSquarefreeFactors( GenPolynomial> P) { SortedMap>, Long> factors; factors = new TreeMap>, Long>(); if (P == null || P.isZERO()) { return factors; } if (P.ring.nvar <= 1) { return recursiveUnivariateSquarefreeFactors(P); } // distributed polynomials squarefree part GenPolynomialRing> rfac = P.ring; RingFactory> rrfac = rfac.coFac; GenPolynomialRing cfac = (GenPolynomialRing) rrfac; GenPolynomialRing dfac = cfac.extend(rfac.nvar); GenPolynomial Pd = PolyUtil. distribute(dfac, P); SortedMap, Long> dfacs = squarefreeFactors(Pd); // convert to recursive for (Map.Entry, Long> Dm : dfacs.entrySet()) { GenPolynomial Dd = Dm.getKey(); Long e = Dm.getValue(); GenPolynomial> C = PolyUtil. recursive(rfac, Dd); factors.put(C, e); } return factors; } /** * Univariate GenPolynomial partial fraction decomposition. * @param A univariate GenPolynomial. * @param D sorted map [d_1 -> e_1, ..., d_k -> e_k] with d_i * squarefree. * @return [ [Ai0, Ai1,..., Aie_i], i=0,...,k ] with A/prod(D) = A0 + sum( * sum ( Aij/di^j ) ) with deg(Aij) < deg(di). */ public List>> basePartialFraction(GenPolynomial A, SortedMap, Long> D) { if (D == null || A == null) { throw new IllegalArgumentException("null A or D not allowed"); } List>> pf = new ArrayList>>(D.size() + 1); if (D.size() == 0) { return pf; } //List> fi; if (A.isZERO()) { for (Map.Entry, Long> me : D.entrySet()) { //GenPolynomial d = me.getKey(); long e = me.getValue(); //D.get(d); int e1 = (int) e + 1; List> fi = new ArrayList>(e1); for (int i = 0; i < e1; i++) { fi.add(A); } pf.add(fi); } List> fi = new ArrayList>(1); fi.add(A); pf.add(0, fi); return pf; } // A != 0, D != empty List> Dp = new ArrayList>(D.size()); for (Map.Entry, Long> me : D.entrySet()) { GenPolynomial d = me.getKey(); long e = me.getValue(); //D.get(d); GenPolynomial f = Power.> positivePower(d, e); Dp.add(f); } List> F = engine.basePartialFraction(A, Dp); //System.out.println("fraction list = " + F.size()); GenPolynomial A0 = F.remove(0); List> fi = new ArrayList>(1); fi.add(A0); pf.add(fi); int i = 0; for (Map.Entry, Long> me : D.entrySet()) { // assume fixed sequence order GenPolynomial d = me.getKey(); long e = me.getValue(); // D.get(d); int ei = (int) e; GenPolynomial gi = F.get(i); // assume fixed sequence order List> Fi = engine.basePartialFraction(gi, d, ei); pf.add(Fi); i++; } return pf; } /** * Test for Univariate GenPolynomial partial fraction decomposition. * @param A univariate GenPolynomial. * @param D sorted map [d_1 -> e_1, ..., d_k -> e_k] with d_i * squarefree. * @param F a list of lists [ [Ai0, Ai1,..., Aie_i], i=0,...,k ] * @return true, if A/prod(D) = A0 + sum( sum ( Aij/di^j ) ), else false. */ public boolean isBasePartialFraction(GenPolynomial A, SortedMap, Long> D, List>> F) { if (D == null || A == null || F == null) { throw new IllegalArgumentException("null A, D or F not allowed"); } if (D.isEmpty() && F.isEmpty()) { return true; } if (D.isEmpty() || F.isEmpty()) { return false; } List> Dp = new ArrayList>(D.size()); for (Map.Entry, Long> me : D.entrySet()) { GenPolynomial d = me.getKey(); long e = me.getValue(); // D.get(d); GenPolynomial f = Power.> positivePower(d, e); Dp.add(f); } List> fi = F.get(0); if (fi.size() != 1) { System.out.println("size(fi) != 1 " + fi); return false; } boolean t; GenPolynomial A0 = fi.get(0); //System.out.println("A0 = " + A0); List> Qp = new ArrayList>(D.size() + 1); Qp.add(A0); // List> Fp = engine.basePartialFraction(A,Dp); // System.out.println("fraction list = " + F.size()); // t = engine.isBasePartialFraction(A,Dp,Fp); // if ( ! t ) { // System.out.println("not recursion isPartFrac = " + Fp); // return false; // } // GenPolynomial A0p = Fp.remove(0); // if ( ! A0.equals(A0p) ) { // System.out.println("A0 != A0p " + A0p); // return false; // } int i = 0; for (Map.Entry, Long> me : D.entrySet()) { // assume fixed sequence order GenPolynomial d = me.getKey(); long e = me.getValue(); // D.get(d); int ei = (int) e; List> Fi = F.get(i + 1); // assume fixed sequence order // GenPolynomial pi = Fp.get(i); // assume fixed sequence order // t = engine.isBasePartialFraction(pi,d,ei,Fi); // if ( ! t ) { // System.out.println("not isPartFrac exp = " + pi + ", d = " + d + ", e = " + ei); // System.out.println("not isPartFrac exp = " + Fi); // return false; // } GenPolynomial qi = engine.basePartialFractionValue(d, ei, Fi); Qp.add(qi); // t = qi.equals(pi); // if ( ! t ) { // System.out.println("not isPartFrac exp = " + pi + ", d = " + d + ", e = " + ei + ", qi = " + qi); // } i++; } t = engine.isBasePartialFraction(A, Dp, Qp); if (!t) { System.out.println("not final isPartFrac " + Qp); } return t; } /** * Coefficients greatest squarefree divisor. * @param P coefficient. * @return squarefree part of P. */ public C squarefreePart(C P) { if (P == null) { return null; } // just for the moment: TODO C s = null; SortedMap factors = squarefreeFactors(P); //logger.info("sqfPart,factors = " + factors); System.out.println("sqfPart,factors = " + factors); for (C sp : factors.keySet()) { if (s == null) { s = sp; } else { s = s.multiply(sp); } } return s; } /** * Coefficients squarefree factorization. * @param P coefficient. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i^{e_i} and p_i squarefree. */ public abstract SortedMap squarefreeFactors(C P); /* not possible: { if (P == null) { return null; } SortedMap factors = new TreeMap(); SquarefreeAbstract reng = SquarefreeFactory.getImplementation((RingFactory) P.factory()); System.out.println("fcp,reng = " + reng); SortedMap rfactors = reng.squarefreeFactors(P); for (C c : rfactors.keySet()) { if (!c.isONE()) { C cr = (C) (Object) c; Long rk = rfactors.get(c); factors.put(cr, rk); } } return factors; } */ } jas-2.5/src/edu/jas/ufd/FactorInteger.java0000644000175000017500000017251312070343440020647 0ustar giovannigiovanni/* * $Id: FactorInteger.java 4343 2012-12-31 17:10:56Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.BitSet; import java.util.Iterator; import java.util.List; import java.util.SortedMap; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLongRing; import edu.jas.arith.Modular; import edu.jas.arith.ModularRingFactory; import edu.jas.arith.PrimeList; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.OptimizedPolynomialList; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrderOptimization; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.util.KsubSet; /** * Integer coefficients factorization algorithms. This class implements * factorization methods for polynomials over integers. * @author Heinz Kredel */ /** * @author kredel * * @param */ public class FactorInteger & Modular> extends FactorAbstract { private static final Logger logger = Logger.getLogger(FactorInteger.class); private final boolean debug = logger.isDebugEnabled(); /** * Factorization engine for modular base coefficients. */ protected final FactorAbstract mfactor; /** * Gcd engine for modular base coefficients. */ protected final GreatestCommonDivisorAbstract mengine; /** * No argument constructor. */ public FactorInteger() { this(BigInteger.ONE); } /** * Constructor. * @param cfac coefficient ring factory. */ public FactorInteger(RingFactory cfac) { super(cfac); ModularRingFactory mcofac = (ModularRingFactory) (Object) new ModLongRing(13, true); // hack mfactor = FactorFactory.getImplementation(mcofac); //new FactorModular(mcofac); mengine = GCDFactory.getImplementation(mcofac); //mengine = GCDFactory.getProxy(mcofac); } /** * GenPolynomial base factorization of a squarefree polynomial. * @param P squarefree and primitive! GenPolynomial. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ @SuppressWarnings("unchecked") @Override public List> baseFactorsSquarefree(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List> factors = new ArrayList>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } if (!engine.baseContent(P).isONE()) { throw new IllegalArgumentException(this.getClass().getName() + " P not primitive"); } if (P.degree(0) <= 1L) { // linear is irreducible factors.add(P); return factors; } // compute norm BigInteger an = P.maxNorm(); BigInteger ac = P.leadingBaseCoefficient(); //compute factor coefficient bounds ExpVector degv = P.degreeVector(); int degi = (int) P.degree(0); BigInteger M = an.multiply(PolyUtil.factorBound(degv)); M = M.multiply(ac.abs().multiply(ac.fromInteger(8))); //System.out.println("M = " + M); //M = M.multiply(M); // test //initialize prime list and degree vector PrimeList primes = new PrimeList(PrimeList.Range.small); int pn = 30; //primes.size(); ModularRingFactory cofac = null; GenPolynomial am = null; GenPolynomialRing mfac = null; final int TT = 5; // 7 List>[] modfac = new List[TT]; List>[] intfac = new List[TT]; BigInteger[] plist = new BigInteger[TT]; List> mlist = null; List> ilist = null; int i = 0; if (debug) { logger.debug("an = " + an); logger.debug("ac = " + ac); logger.debug("M = " + M); logger.info("degv = " + degv); } Iterator pit = primes.iterator(); pit.next(); // skip p = 2 pit.next(); // skip p = 3 MOD nf = null; for (int k = 0; k < TT; k++) { if (k == TT - 1) { // -2 primes = new PrimeList(PrimeList.Range.medium); pit = primes.iterator(); } if (k == TT + 1) { // -1 primes = new PrimeList(PrimeList.Range.large); pit = primes.iterator(); } while (pit.hasNext()) { java.math.BigInteger p = pit.next(); //System.out.println("next run ++++++++++++++++++++++++++++++++++"); if (++i >= pn) { logger.error("prime list exhausted, pn = " + pn); throw new ArithmeticException("prime list exhausted"); } if (ModLongRing.MAX_LONG.compareTo(p) > 0) { cofac = (ModularRingFactory) new ModLongRing(p, true); } else { cofac = (ModularRingFactory) new ModIntegerRing(p, true); } logger.info("prime = " + cofac); nf = cofac.fromInteger(ac.getVal()); if (nf.isZERO()) { logger.info("unlucky prime (nf) = " + p); //System.out.println("unlucky prime (nf) = " + p); continue; } // initialize polynomial factory and map polynomial mfac = new GenPolynomialRing(cofac, pfac); am = PolyUtil. fromIntegerCoefficients(mfac, P); if (!am.degreeVector().equals(degv)) { // allways true logger.info("unlucky prime (deg) = " + p); //System.out.println("unlucky prime (deg) = " + p); continue; } GenPolynomial ap = PolyUtil. baseDeriviative(am); if (ap.isZERO()) { logger.info("unlucky prime (a')= " + p); //System.out.println("unlucky prime (a')= " + p); continue; } GenPolynomial g = mengine.baseGcd(am, ap); if (g.isONE()) { logger.info("**lucky prime = " + p); //System.out.println("**lucky prime = " + p); break; } } // now am is squarefree mod p, make monic and factor mod p if (!nf.isONE()) { //System.out.println("nf = " + nf); am = am.divide(nf); // make monic } mlist = mfactor.baseFactorsSquarefree(am); if (logger.isInfoEnabled()) { logger.info("modlist = " + mlist); } if (mlist.size() <= 1) { factors.add(P); return factors; } if (!nf.isONE()) { GenPolynomial mp = mfac.getONE(); //mlist.get(0); //System.out.println("mp = " + mp); mp = mp.multiply(nf); //System.out.println("mp = " + mp); mlist.add(0, mp); // set(0,mp); } modfac[k] = mlist; plist[k] = cofac.getIntegerModul(); // p } // search shortest factor list int min = Integer.MAX_VALUE; BitSet AD = null; for (int k = 0; k < TT; k++) { List ev = PolyUtil. leadingExpVector(modfac[k]); BitSet D = factorDegrees(ev, degi); if (AD == null) { AD = D; } else { AD.and(D); } int s = modfac[k].size(); logger.info("mod(" + plist[k] + ") #s = " + s + ", D = " + D /*+ ", lt = " + ev*/); //System.out.println("mod s = " + s); if (s < min) { min = s; mlist = modfac[k]; } } logger.info("min = " + min + ", AD = " + AD); if (mlist.size() <= 1) { logger.info("mlist.size() = 1"); factors.add(P); return factors; } if (AD.cardinality() <= 2) { // only one possible factor logger.info("degree set cardinality = " + AD.cardinality()); factors.add(P); return factors; } boolean allLists = false; //true; //false; if (allLists) { // try each factor list for (int k = 0; k < TT; k++) { mlist = modfac[k]; if (debug) { logger.info("lifting from " + mlist); } if (P.leadingBaseCoefficient().isONE()) { // monic case factors = searchFactorsMonic(P, M, mlist, AD); // does now work in all cases if (factors.size() == 1) { factors = searchFactorsNonMonic(P, M, mlist, AD); } } else { factors = searchFactorsNonMonic(P, M, mlist, AD); } intfac[k] = factors; } } else { // try only shortest factor list if (debug) { logger.info("lifting shortest from " + mlist); } if (true && P.leadingBaseCoefficient().isONE()) { long t = System.currentTimeMillis(); try { mlist = PolyUtil. monic(mlist); factors = searchFactorsMonic(P, M, mlist, AD); // does now work in all cases t = System.currentTimeMillis() - t; //System.out.println("monic time = " + t); if (debug) { t = System.currentTimeMillis(); List> fnm = searchFactorsNonMonic(P, M, mlist, AD); t = System.currentTimeMillis() - t; System.out.println("non monic time = " + t); if (!factors.equals(fnm)) { System.out.println("monic factors = " + factors); System.out.println("non monic factors = " + fnm); } } } catch (RuntimeException e) { t = System.currentTimeMillis(); factors = searchFactorsNonMonic(P, M, mlist, AD); t = System.currentTimeMillis() - t; //System.out.println("only non monic time = " + t); } } else { long t = System.currentTimeMillis(); factors = searchFactorsNonMonic(P, M, mlist, AD); t = System.currentTimeMillis() - t; //System.out.println("non monic time = " + t); } return normalizeFactorization(factors); } // search longest factor list int max = 0; for (int k = 0; k < TT; k++) { int s = intfac[k].size(); logger.info("int s = " + s); //System.out.println("int s = " + s); if (s > max) { max = s; ilist = intfac[k]; } } factors = normalizeFactorization(ilist); return factors; } /** * BitSet for factor degree list. * @param E exponent vector list. * @return b_0,...,b_k} a BitSet of possible factor degrees. */ public BitSet factorDegrees(List E, int deg) { BitSet D = new BitSet(deg + 1); D.set(0); // constant factor for (ExpVector e : E) { int i = (int) e.getVal(0); BitSet s = new BitSet(deg + 1); for (int k = 0; k < deg + 1 - i; k++) { // shift by i places s.set(i + k, D.get(k)); } //System.out.println("s = " + s); D.or(s); //System.out.println("D = " + D); } return D; } /** * Sum of all degrees. * @param L univariate polynomial list. * @return sum deg(p) for p in L. */ public static > long degreeSum(List> L) { long s = 0L; for (GenPolynomial p : L) { ExpVector e = p.leadingExpVector(); long d = e.getVal(0); s += d; } return s; } /** * Factor search with modular Hensel lifting algorithm. Let p = * f_i.ring.coFac.modul() i = 0, ..., n-1 and assume C == prod_{0,...,n-1} * f_i mod p with ggt(f_i,f_j) == 1 mod p for i != j * @param C GenPolynomial. * @param M bound on the coefficients of g_i as factors of C. * @param F = [f_0,...,f_{n-1}] List<GenPolynomial>. * @param D bit set of possible factor degrees. * @return [g_0,...,g_{n-1}] = lift(C,F), with C = prod_{0,...,n-1} g_i mod * p**e. Note: does not work in all cases. */ List> searchFactorsMonic(GenPolynomial C, BigInteger M, List> F, BitSet D) { //System.out.println("*** monic factor combination ***"); if (C == null || C.isZERO() || F == null || F.size() == 0) { throw new IllegalArgumentException("C must be nonzero and F must be nonempty"); } GenPolynomialRing pfac = C.ring; if (pfac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } List> factors = new ArrayList>(F.size()); List> mlist = F; List> lift; //MOD nf = null; GenPolynomial ct = mlist.get(0); if (ct.isConstant()) { //nf = ct.leadingBaseCoefficient(); mlist.remove(ct); //System.out.println("=== nf = " + nf); if (mlist.size() <= 1) { factors.add(C); return factors; } } else { //nf = ct.ring.coFac.getONE(); } //System.out.println("modlist = " + mlist); // includes not ldcf ModularRingFactory mcfac = (ModularRingFactory) ct.ring.coFac; BigInteger m = mcfac.getIntegerModul(); long k = 1; BigInteger pi = m; while (pi.compareTo(M) < 0) { k++; pi = pi.multiply(m); } logger.info("p^k = " + m + "^" + k); GenPolynomial PP = C, P = C; // lift via Hensel try { lift = HenselUtil. liftHenselMonic(PP, mlist, k); //System.out.println("lift = " + lift); } catch (NoLiftingException e) { throw new RuntimeException(e); } if (logger.isInfoEnabled()) { logger.info("lifted modlist = " + lift); } GenPolynomialRing mpfac = lift.get(0).ring; // combine trial factors int dl = (lift.size() + 1) / 2; //System.out.println("dl = " + dl); GenPolynomial u = PP; long deg = (u.degree(0) + 1L) / 2L; //System.out.println("deg = " + deg); //BigInteger ldcf = u.leadingBaseCoefficient(); //System.out.println("ldcf = " + ldcf); for (int j = 1; j <= dl; j++) { //System.out.println("j = " + j + ", dl = " + dl + ", lift = " + lift); KsubSet> ps = new KsubSet>(lift, j); for (List> flist : ps) { //System.out.println("degreeSum = " + degreeSum(flist)); if (!D.get((int) FactorInteger. degreeSum(flist))) { logger.info("skipped by degree set " + D + ", deg = " + degreeSum(flist)); continue; } GenPolynomial mtrial = Power.> multiply(mpfac, flist); //GenPolynomial mtrial = mpfac.getONE(); //for (int kk = 0; kk < flist.size(); kk++) { // GenPolynomial fk = flist.get(kk); // mtrial = mtrial.multiply(fk); //} //System.out.println("+flist = " + flist + ", mtrial = " + mtrial); if (mtrial.degree(0) > deg) { // this test is sometimes wrong logger.info("degree " + mtrial.degree(0) + " > deg " + deg); //continue; } //System.out.println("+flist = " + flist); GenPolynomial trial = PolyUtil.integerFromModularCoefficients(pfac, mtrial); //System.out.println("+trial = " + trial); //trial = engine.basePrimitivePart( trial.multiply(ldcf) ); trial = engine.basePrimitivePart(trial); //System.out.println("pp(trial)= " + trial); if (PolyUtil. baseSparsePseudoRemainder(u, trial).isZERO()) { logger.info("successful trial = " + trial); //System.out.println("trial = " + trial); //System.out.println("flist = " + flist); //trial = engine.basePrimitivePart(trial); //System.out.println("pp(trial)= " + trial); factors.add(trial); u = PolyUtil. basePseudoDivide(u, trial); //u.divide( trial ); //System.out.println("u = " + u); //if (lift.removeAll(flist)) { lift = removeOnce(lift, flist); logger.info("new lift= " + lift); dl = (lift.size() + 1) / 2; //System.out.println("dl = " + dl); j = 0; // since j++ break; //} logger.error("error removing flist from lift = " + lift); } } } if (!u.isONE() && !u.equals(P)) { logger.info("rest u = " + u); //System.out.println("rest u = " + u); factors.add(u); } if (factors.size() == 0) { logger.info("irred u = " + u); //System.out.println("irred u = " + u); factors.add(PP); } return normalizeFactorization(factors); } /** * Factor search with modular Hensel lifting algorithm. Let p = * f_i.ring.coFac.modul() i = 0, ..., n-1 and assume C == prod_{0,...,n-1} * f_i mod p with ggt(f_i,f_j) == 1 mod p for i != j * @param C GenPolynomial. * @param M bound on the coefficients of g_i as factors of C. * @param F = [f_0,...,f_{n-1}] List<GenPolynomial>. * @param D bit set of possible factor degrees. * @return [g_0,...,g_{n-1}] = lift(C,F), with C = prod_{0,...,n-1} g_i mod * p**e. */ List> searchFactorsNonMonic(GenPolynomial C, BigInteger M, List> F, BitSet D) { //System.out.println("*** non monic factor combination ***"); if (C == null || C.isZERO() || F == null || F.size() == 0) { throw new IllegalArgumentException("C must be nonzero and F must be nonempty"); } GenPolynomialRing pfac = C.ring; if (pfac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } List> factors = new ArrayList>(F.size()); List> mlist = F; MOD nf = null; GenPolynomial ct = mlist.get(0); if (ct.isConstant()) { nf = ct.leadingBaseCoefficient(); mlist.remove(ct); //System.out.println("=== nf = " + nf); //System.out.println("=== ldcf = " + C.leadingBaseCoefficient()); if (mlist.size() <= 1) { factors.add(C); return factors; } } else { nf = ct.ring.coFac.getONE(); } //System.out.println("modlist = " + mlist); // includes not ldcf GenPolynomialRing mfac = ct.ring; GenPolynomial Pm = PolyUtil. fromIntegerCoefficients(mfac, C); GenPolynomial PP = C, P = C; // combine trial factors int dl = (mlist.size() + 1) / 2; GenPolynomial u = PP; long deg = (u.degree(0) + 1L) / 2L; GenPolynomial um = Pm; //BigInteger ldcf = u.leadingBaseCoefficient(); //System.out.println("ldcf = " + ldcf); HenselApprox ilist = null; for (int j = 1; j <= dl; j++) { //System.out.println("j = " + j + ", dl = " + dl + ", ilist = " + ilist); KsubSet> ps = new KsubSet>(mlist, j); for (List> flist : ps) { //System.out.println("degreeSum = " + degreeSum(flist)); if (!D.get((int) FactorInteger. degreeSum(flist))) { logger.info("skipped by degree set " + D + ", deg = " + degreeSum(flist)); continue; } GenPolynomial trial = mfac.getONE().multiply(nf); for (int kk = 0; kk < flist.size(); kk++) { GenPolynomial fk = flist.get(kk); trial = trial.multiply(fk); } if (trial.degree(0) > deg) { // this test is sometimes wrong logger.info("degree > deg " + deg + ", degree = " + trial.degree(0)); //continue; } GenPolynomial cofactor = um.divide(trial); //System.out.println("trial = " + trial); //System.out.println("cofactor = " + cofactor); // lift via Hensel try { // ilist = HenselUtil.liftHenselQuadraticFac(PP, M, trial, cofactor); ilist = HenselUtil. liftHenselQuadratic(PP, M, trial, cofactor); //ilist = HenselUtil. liftHensel(PP, M, trial, cofactor); } catch (NoLiftingException e) { // no liftable factors if ( /*debug*/logger.isDebugEnabled()) { logger.info("no liftable factors " + e); //e.printStackTrace(); } continue; } GenPolynomial itrial = ilist.A; GenPolynomial icofactor = ilist.B; if (logger.isDebugEnabled()) { logger.info(" modlist = " + trial + ", cofactor " + cofactor); logger.info("lifted intlist = " + itrial + ", cofactor " + icofactor); } //System.out.println("lifted intlist = " + itrial + ", cofactor " + icofactor); itrial = engine.basePrimitivePart(itrial); //System.out.println("pp(trial)= " + itrial); if (PolyUtil. baseSparsePseudoRemainder(u, itrial).isZERO()) { logger.info("successful trial = " + itrial); //System.out.println("trial = " + itrial); //System.out.println("cofactor = " + icofactor); //System.out.println("flist = " + flist); //itrial = engine.basePrimitivePart(itrial); //System.out.println("pp(itrial)= " + itrial); factors.add(itrial); //u = PolyUtil. basePseudoDivide(u, itrial); //u.divide( trial ); u = icofactor; PP = u; // fixed finally on 2009-05-03 um = cofactor; //System.out.println("u = " + u); //System.out.println("um = " + um); //if (mlist.removeAll(flist)) { mlist = removeOnce(mlist, flist); logger.info("new mlist= " + mlist); dl = (mlist.size() + 1) / 2; j = 0; // since j++ break; //} logger.error("error removing flist from ilist = " + mlist); } } } if (!u.isONE() && !u.equals(P)) { logger.info("rest u = " + u); //System.out.println("rest u = " + u); factors.add(u); } if (factors.size() == 0) { logger.info("irred u = " + u); //System.out.println("irred u = " + u); factors.add(PP); } return normalizeFactorization(factors); } /** * GenPolynomial factorization of a multivariate squarefree polynomial, * using Hensel lifting if possible. * @param P squarefree and primitive! (respectively monic) multivariate * GenPolynomial over the integers. * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. */ @Override public List> factorsSquarefree(GenPolynomial P) { GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return baseFactorsSquarefree(P); } List> topt = new ArrayList>(1); topt.add(P); OptimizedPolynomialList opt = TermOrderOptimization. optimizeTermOrder(pfac, topt); P = opt.list.get(0); logger.info("optimized polynomial: " + P); List iperm = TermOrderOptimization.inversePermutation(opt.perm); logger.info("optimize perm: " + opt.perm + ", de-optimize perm: " + iperm); ExpVector degv = P.degreeVector(); int[] donv = degv.dependencyOnVariables(); List> facs = null; if (degv.length() == donv.length) { // all variables appear, hack for Hensel, TODO check try { logger.info("try factorsSquarefreeHensel: " + P); facs = factorsSquarefreeHensel(P); } catch (Exception e) { logger.warn("exception " + e); //e.printStackTrace(); } } else { // not all variables appear, remove unused variables, hack for Hensel, TODO check GenPolynomial pu = PolyUtil. removeUnusedUpperVariables(P); GenPolynomial pl = PolyUtil. removeUnusedLowerVariables(pu); // not useful try { logger.info("try factorsSquarefreeHensel: " + pl); facs = factorsSquarefreeHensel(pu); List> fs = new ArrayList>(facs.size()); GenPolynomialRing pf = P.ring; GenPolynomialRing pfu = pu.ring; for (GenPolynomial p : facs) { GenPolynomial pel = p.extendLower(pfu, 0, 0L); GenPolynomial pe = pel.extend(pf, 0, 0L); fs.add(pe); } //System.out.println("fs = " + fs); facs = fs; } catch (Exception e) { logger.warn("exception " + e); //e.printStackTrace(); } } if (facs == null) { logger.info("factorsSquarefreeHensel not applicable or failed, reverting to Kronecker for: " + P); facs = super.factorsSquarefree(P); } List> iopt = TermOrderOptimization. permutation(iperm, pfac, facs); logger.info("de-optimized polynomials: " + iopt); facs = normalizeFactorization(iopt); return facs; } /** * GenPolynomial factorization of a multivariate squarefree polynomial, * using Hensel lifting. * @param P squarefree and primitive! (respectively monic) multivariate * GenPolynomial over the integers. * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. */ public List> factorsSquarefreeHensel(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } GenPolynomialRing pfac = P.ring; if (pfac.nvar == 1) { return baseFactorsSquarefree(P); } List> factors = new ArrayList>(); if (P.isZERO()) { return factors; } if (P.degreeVector().totalDeg() <= 1L) { factors.add(P); return factors; } GenPolynomial pd = P; //System.out.println("pd = " + pd); // ldcf(pd) BigInteger ac = pd.leadingBaseCoefficient(); // factor leading coefficient as polynomial in the lowest! variable GenPolynomialRing> rnfac = pfac.recursive(pfac.nvar - 1); GenPolynomial> pr = PolyUtil. recursive(rnfac, pd); GenPolynomial> prr = PolyUtil. switchVariables(pr); GenPolynomial prrc = engine.recursiveContent(prr); // can have content wrt this variable List> cfactors = null; if (!prrc.isONE()) { prr = PolyUtil. recursiveDivide(prr, prrc); GenPolynomial prrcu = prrc.extendLower(pfac, 0, 0L); // since switched vars pd = PolyUtil. basePseudoDivide(pd, prrcu); logger.info("recursive content = " + prrc + ", new P = " + pd); cfactors = factorsSquarefree(prrc); List> cff = new ArrayList>(cfactors.size()); for (GenPolynomial fs : cfactors) { GenPolynomial fsp = fs.extendLower(pfac, 0, 0L); // since switched vars cff.add(fsp); } cfactors = cff; logger.info("cfactors = " + cfactors); } GenPolynomial lprr = prr.leadingBaseCoefficient(); //System.out.println("prr = " + prr); logger.info("leading coeffcient = " + lprr); boolean isMonic = false; // multivariate monic if (lprr.isConstant()) { // isONE ? isMonic = true; } SortedMap, Long> lfactors = factors(lprr); //System.out.println("lfactors = " + lfactors); List> lfacs = new ArrayList>(lfactors.keySet()); logger.info("leading coefficient factors = " + lfacs); // search evaluation point and evaluate GenPolynomialRing cpfac = pfac; GenPolynomial pe = pd; GenPolynomial pep; GenPolynomialRing ccpfac = lprr.ring; List> ce = lfacs; List> cep = null; List cei = null; List dei = new ArrayList(); BigInteger pec = null; BigInteger pecw = null; BigInteger ped = null; List> ufactors = null; List tParts = new ArrayList(); List> lf = null; GenPolynomial lpx = null; List> ln = null; List> un = null; GenPolynomial pes = null; List V = null; long evStart = 0L; //3L * 5L; List Evs = new ArrayList(pfac.nvar + 1); // Evs(0), Evs(1) unused for (int j = 0; j <= pfac.nvar; j++) { Evs.add(evStart); } final int trials = 4; int countSeparate = 0; final int COUNT_MAX = 50; double ran = 1.001; // higher values not good boolean isPrimitive = true; boolean notLucky = true; while (notLucky) { // for Wang's test if (Math.abs(evStart) > 371L) { logger.warn("no lucky evaluation point for: P = " + P + ", lprr = " + lprr + ", lfacs = " + lfacs); throw new RuntimeException("no lucky evaluation point found after " + Math.abs(evStart) + " iterations"); } if (Math.abs(evStart) % 100L <= 3L) { ran = ran * (Math.PI - 2.14); } //System.out.println("-------------------------------------------- Evs = " + Evs); notLucky = false; V = new ArrayList(); cpfac = pfac; pe = pd; ccpfac = lprr.ring; ce = lfacs; cep = null; cei = null; pec = null; ped = null; long vi = 0L; for (int j = pfac.nvar; j > 1; j--) { // evaluation up to univariate case long degp = pe.degree(cpfac.nvar - 2); cpfac = cpfac.contract(1); ccpfac = ccpfac.contract(1); //vi = evStart; // + j;//0L; //(long)(pfac.nvar-j); // 1L; 0 not so good for small p vi = Evs.get(j); //evStart + j;//0L; //(long)(pfac.nvar-j); // 1L; 0 not so good for small p BigInteger Vi; // search evaluation point boolean doIt = true; Vi = null; pep = null; while (doIt) { logger.info("vi(" + j + ") = " + vi); Vi = new BigInteger(vi); pep = PolyUtil. evaluateMain(cpfac, pe, Vi); //System.out.println("pep = " + pep); // check lucky evaluation point if (degp == pep.degree(cpfac.nvar - 1)) { logger.info("pep = " + pep); //System.out.println("deg(pe) = " + degp + ", deg(pep) = " + pep.degree(cpfac.nvar-1)); // check squarefree if (sengine.isSquarefree(pep)) { // cpfac.nvar == 1 && ?? no, must test on each variable //if ( isNearlySquarefree(pep) ) { //System.out.println("squarefeee(pep)"); // + pep); doIt = false; //break; } } if (vi > 0L) { vi = -vi; } else { vi = 1L - vi; } } //if ( !isMonic ) { if (ccpfac.nvar >= 1) { cep = PolyUtil. evaluateMain(ccpfac, ce, Vi); } else { cei = PolyUtil. evaluateMain(ccpfac.coFac, ce, Vi); } //} int jj = (int) Math.round(ran + 0.52 * Math.random()); // j, random increment //jj = 1; // ...4 test //System.out.println("minimal jj = " + jj + ", vi " + vi); if (vi > 0L) { Evs.set(j, vi + jj); // record last tested value plus increment evStart = vi + jj; } else { Evs.set(j, vi - jj); // record last tested value minus increment evStart = vi - jj; } //evStart = vi+1L; V.add(Vi); pe = pep; ce = cep; } //System.out.println("ce = " + ce + ", pe = " + pe); pecw = engine.baseContent(pe); // original Wang isPrimitive = pecw.isONE(); ped = ccpfac.coFac.getONE(); pec = pe.ring.coFac.getONE(); //System.out.println("cei = " + cei + ", pecw = " + pecw); if (!isMonic) { if (countSeparate > COUNT_MAX) { pec = pe.ring.coFac.getONE(); // hack is sometimes better } else { pec = pecw; } //pec = pecw; //System.out.println("cei = " + cei + ", pec = " + pec + ", pe = " + pe); if (lfacs.get(0).isConstant()) { ped = cei.remove(0); //lfacs.remove(0); // later } //System.out.println("lfacs = " + lfacs + ", cei = " + cei + ", ped = " + ped + ", pecw = " + pecw); // test Wang's condition dei = new ArrayList(); dei.add(pec.multiply(ped).abs()); // .abs() int i = 1; for (BigInteger ci : cei) { if (ci.isZERO()) { logger.info("condition (0) not met for cei = " + cei); // + ", dei = " + dei); notLucky = true; break; } BigInteger q = ci.abs(); //System.out.println("q = " + q); for (int ii = i - 1; ii >= 0; ii--) { BigInteger r = dei.get(ii); //System.out.println("r = " + r); while (!r.isONE()) { r = r.gcd(q); q = q.divide(r); //System.out.println("r = " + r + ", q = " + q); } } dei.add(q); if (q.isONE()) { logger.info("condition (1) not met for dei = " + dei + ", cei = " + cei); if (!testSeparate(cei, pecw)) { countSeparate++; if (countSeparate > COUNT_MAX) { logger.info("too many inseparable evaluation points: " + countSeparate + ", removing " + pecw); } } notLucky = true; break; } i++; } //System.out.println("dei = " + dei); } if (notLucky) { continue; } logger.info("evaluation points = " + V + ", dei = " + dei); //System.out.println("Evs = " + Evs); logger.info("univariate polynomial = " + pe + ", pecw = " + pecw); //pe = pe.abs(); //ufactors = baseFactorsRadical(pe); //baseFactorsSquarefree(pe); wrong since not primitive ufactors = baseFactorsSquarefree(pe.divide(pecw)); //wrong if not primitive if (!pecw.isONE()) { ufactors.add(0, cpfac.getONE().multiply(pecw)); } if (ufactors.size() <= 1) { logger.info("irreducible univariate polynomial"); factors.add(pd); // P if (cfactors != null) { cfactors.addAll(factors); factors = cfactors; } return factors; } logger.info("univariate factors = " + ufactors); // + ", of " + pe); //System.out.println("lfacs = " + lfacs); //System.out.println("cei = " + cei); //System.out.println("pecw = " + pecw); // determine leading coefficient polynomials for factors lf = new ArrayList>(); lpx = lprr.ring.getONE(); for (GenPolynomial unused : ufactors) { lf.add(lprr.ring.getONE()); } //System.out.println("lf = " + lf); if (!isMonic || !pecw.isONE()) { if (lfacs.size() > 0 && lfacs.get(0).isConstant()) { GenPolynomial unused = lfacs.remove(0); //BigInteger xxi = xx.leadingBaseCoefficient(); //System.out.println("xx = " + xx + " == ped = " +ped); } for (int i = ufactors.size() - 1; i >= 0; i--) { GenPolynomial pp = ufactors.get(i); BigInteger ppl = pp.leadingBaseCoefficient(); //System.out.println("ppl = " + ppl + ", pp = " + pp); ppl = ppl.multiply(pec); // content GenPolynomial lfp = lf.get(i); int ii = 0; for (BigInteger ci : cei) { //System.out.println("ci = " + ci + ", lfp = " + lfp + ", lfacs.get(ii) = " + lfacs.get(ii)); if (ci.abs().isONE()) { System.out.println("ppl = " + ppl + ", ci = " + ci + ", lfp = " + lfp + ", lfacs.get(ii) = " + lfacs.get(ii)); throw new RuntimeException("something is wrong, ci is a unit"); //notLucky = true; } while (ppl.remainder(ci).isZERO() && lfacs.size() > ii) { ppl = ppl.divide(ci); lfp = lfp.multiply(lfacs.get(ii)); } ii++; } //System.out.println("ppl = " + ppl + ", lfp = " + lfp); lfp = lfp.multiply(ppl); lf.set(i, lfp); } // adjust if pec != 1 pec = pecw; lpx = Power.> multiply(lprr.ring, lf); // test only, not used //System.out.println("lpx = " + lpx); if (!lprr.degreeVector().equals(lpx.degreeVector())) { logger.info("deg(lprr) != deg(lpx): lprr = " + lprr + ", lpx = " + lpx); notLucky = true; continue; } if (!pec.isONE()) { // content, was always false by hack // evaluate factors of ldcf List> lfe = lf; List lfei = null; ccpfac = lprr.ring; for (int j = lprr.ring.nvar; j > 0; j--) { ccpfac = ccpfac.contract(1); BigInteger Vi = V.get(lprr.ring.nvar - j); if (ccpfac.nvar >= 1) { lfe = PolyUtil. evaluateMain(ccpfac, lfe, Vi); } else { lfei = PolyUtil. evaluateMain(ccpfac.coFac, lfe, Vi); } } //System.out.println("lfe = " + lfe + ", lfei = " + lfei + ", V = " + V); ln = new ArrayList>(lf.size()); un = new ArrayList>(lf.size()); for (int jj = 0; jj < lf.size(); jj++) { GenPolynomial up = ufactors.get(jj); BigInteger ui = up.leadingBaseCoefficient(); BigInteger li = lfei.get(jj); BigInteger di = ui.gcd(li).abs(); BigInteger udi = ui.divide(di); BigInteger ldi = li.divide(di); GenPolynomial lp = lf.get(jj); GenPolynomial lpd = lp.multiply(udi); GenPolynomial upd = up.multiply(ldi); if (pec.isONE()) { ln.add(lp); un.add(up); } else { ln.add(lpd); un.add(upd); BigInteger pec1 = pec.divide(ldi); //System.out.println("pec = " + pec + ", pec1 = " + pec1); pec = pec1; } } if (!lf.equals(ln) || !un.equals(ufactors)) { logger.debug("!lf.equals(ln) || !un.equals(ufactors)"); //System.out.println("pe = " + pe); //System.out.println("#ln = " + ln + ", #lf = " + lf); //System.out.println("#un = " + un + ", #ufactors = " + ufactors); //lf = ln; //ufactors = un; // adjust pe } if (!pec.isONE()) { // still not 1 ln = new ArrayList>(lf.size()); un = new ArrayList>(lf.size()); pes = pe; for (int jj = 0; jj < lf.size(); jj++) { GenPolynomial up = ufactors.get(jj); GenPolynomial lp = lf.get(jj); //System.out.println("up = " + up + ", lp = " + lp); if (!up.isConstant()) { up = up.multiply(pec); } lp = lp.multiply(pec); if (jj != 0) { pes = pes.multiply(pec); } un.add(up); ln.add(lp); } if (pes.equals(Power.> multiply(pe.ring, un))) { //System.out.println("*pe = " + pes + ", pec = " + pec); //ystem.out.println("*ln = " + ln + ", *lf = " + lf); //System.out.println("*un = " + un + ", *ufactors = " + ufactors); //System.out.println("*pe == prod(un) "); isPrimitive = false; //pe = pes; //lf = ln; //ufactors = un; } else { //System.out.println("*pe != prod(un): " + Power.> multiply(pe.ring,un)); } } } if (notLucky) { continue; } logger.info("distributed factors of leading coefficient = " + lf); lpx = Power.> multiply(lprr.ring, lf); if (!lprr.abs().equals(lpx.abs())) { // not correctly distributed if (!lprr.degreeVector().equals(lpx.degreeVector())) { logger.info("lprr != lpx: lprr = " + lprr + ", lpx = " + lpx); notLucky = true; } } } // end determine leading coefficients for factors if (!notLucky) { TrialParts tp = null; if (isPrimitive) { tp = new TrialParts(V, pe, ufactors, cei, lf); } else { tp = new TrialParts(V, pes, un, cei, ln); } //System.out.println("trialParts = " + tp); if (tp.univPoly != null) { if (tp.ldcfEval.size() != 0) { tParts.add(tp); } } if (tParts.size() < trials) { notLucky = true; } } } // end notLucky loop // search TrialParts with shortest factorization of univariate polynomial int min = Integer.MAX_VALUE; TrialParts tpmin = null; for (TrialParts tp : tParts) { logger.info("tp.univFactors.size() = " + tp.univFactors.size()); if (tp.univFactors.size() < min) { min = tp.univFactors.size(); tpmin = tp; } } for (TrialParts tp : tParts) { //logger.info("tp.univFactors.get(0) = " + tp.univFactors.get(0)); if (tp.univFactors.size() == min) { if (!tp.univFactors.get(0).isConstant()) { tpmin = tp; break; } } } // set to (first) shortest V = tpmin.evalPoints; pe = tpmin.univPoly; ufactors = tpmin.univFactors; cei = tpmin.ldcfEval; // unused lf = tpmin.ldcfFactors; logger.info("iterations = " + Math.abs(evStart)); logger.info("minimal trial = " + tpmin); GenPolynomialRing ufac = pe.ring; //initialize prime list PrimeList primes = new PrimeList(PrimeList.Range.medium); // PrimeList.Range.medium); Iterator primeIter = primes.iterator(); int pn = 50; //primes.size(); BigInteger ae = pe.leadingBaseCoefficient(); GenPolynomial Pm = null; ModularRingFactory cofac = null; GenPolynomialRing mufac = null; // search lucky prime for (int i = 0; i < 11; i++) { // prime meta loop //for ( int i = 0; i < 1; i++ ) { // meta loop java.math.BigInteger p = null; //new java.math.BigInteger("19"); //primes.next(); // 2 small, 5 medium and 4 large size primes if (i == 0) { // medium size primes = new PrimeList(PrimeList.Range.medium); primeIter = primes.iterator(); } if (i == 5) { // small size primes = new PrimeList(PrimeList.Range.small); primeIter = primes.iterator(); p = primeIter.next(); // 2 p = primeIter.next(); // 3 p = primeIter.next(); // 5 p = primeIter.next(); // 7 } if (i == 7) { // large size primes = new PrimeList(PrimeList.Range.large); primeIter = primes.iterator(); } int pi = 0; while (pi < pn && primeIter.hasNext()) { p = primeIter.next(); logger.info("prime = " + p); // initialize coefficient factory and map normalization factor and polynomials ModularRingFactory cf = null; if (ModLongRing.MAX_LONG.compareTo(p) > 0) { cf = (ModularRingFactory) new ModLongRing(p, true); } else { cf = (ModularRingFactory) new ModIntegerRing(p, true); } MOD nf = cf.fromInteger(ae.getVal()); if (nf.isZERO()) { continue; } mufac = new GenPolynomialRing(cf, ufac); //System.out.println("mufac = " + mufac.toScript()); Pm = PolyUtil. fromIntegerCoefficients(mufac, pe); //System.out.println("Pm = " + Pm); if (!mfactor.isSquarefree(Pm)) { continue; } cofac = cf; break; } if (cofac != null) { break; } } // end prime meta loop if (cofac == null) { // no lucky prime found throw new RuntimeException("giving up on Hensel preparation, no lucky prime found"); } logger.info("lucky prime = " + cofac.getIntegerModul()); if (logger.isDebugEnabled()) { logger.debug("univariate modulo p: = " + Pm); } // coefficient bound BigInteger an = pd.maxNorm(); BigInteger mn = an.multiply(ac.abs()).multiply(new BigInteger(2L)); long k = Power.logarithm(cofac.getIntegerModul(), mn) + 1L; //System.out.println("mn = " + mn + ", k = " +k); BigInteger q = Power.positivePower(cofac.getIntegerModul(), k); ModularRingFactory muqfac; if (ModLongRing.MAX_LONG.compareTo(q.getVal()) > 0) { muqfac = (ModularRingFactory) new ModLongRing(q.getVal()); } else { muqfac = (ModularRingFactory) new ModIntegerRing(q.getVal()); } //System.out.println("muqfac = " + muqfac); GenPolynomialRing mucpfac = new GenPolynomialRing(muqfac, ufac); List> muqfactors = PolyUtil. fromIntegerCoefficients(mucpfac, ufactors); GenPolynomial peqq = PolyUtil. fromIntegerCoefficients(mucpfac, pe); if (debug) { if (!mfactor.isFactorization(peqq, muqfactors)) { // should not happen System.out.println("muqfactors = " + muqfactors); System.out.println("peqq = " + peqq); throw new RuntimeException("something is wrong, no modular p^k factorization"); } } logger.info("univariate modulo p^k: " + peqq + " = " + muqfactors); // convert C from Z[...] to Z_q[...] GenPolynomialRing qcfac = new GenPolynomialRing(muqfac, pd.ring); GenPolynomial pq = PolyUtil. fromIntegerCoefficients(qcfac, pd); //System.out.println("pd = " + pd); logger.info("multivariate modulo p^k: " + pq); //List Vm = new ArrayList(V.size()); //for (BigInteger v : V) { // MOD vm = muqfac.fromInteger(v.getVal()); // Vm.add(vm); //} //System.out.println("Vm = " + Vm); // Hensel lifting of factors List> mlift; try { mlift = HenselMultUtil. liftHensel(pd, pq, muqfactors, V, k, lf); logger.info("mlift = " + mlift); } catch (NoLiftingException nle) { //System.out.println("exception : " + nle); //nle.printStackTrace(); mlift = new ArrayList>(); throw new RuntimeException(nle); } catch (ArithmeticException aex) { //System.out.println("exception : " + aex); //aex.printStackTrace(); mlift = new ArrayList>(); throw aex; } if (mlift.size() <= 1) { // irreducible mod I, p^k, can this happen? logger.info("modular lift size == 1: " + mlift); factors.add(pd); // P if (cfactors != null) { cfactors.addAll(factors); factors = cfactors; } return factors; } // combine trial factors GenPolynomialRing mfac = mlift.get(0).ring; int dl = (mlift.size() + 1) / 2; GenPolynomial u = P; long deg = (u.degree() + 1L) / 2L; GenPolynomial ui = pd; for (int j = 1; j <= dl; j++) { //System.out.println("j = " + j + ", dl = " + dl + ", mlift = " + mlift); KsubSet> subs = new KsubSet>(mlift, j); for (List> flist : subs) { //System.out.println("degreeSum = " + degreeSum(flist)); GenPolynomial mtrial = Power.> multiply(mfac, flist); if (mtrial.degree() > deg) { // this test is sometimes wrong logger.info("degree > deg " + deg + ", degree = " + mtrial.degree()); //continue; } GenPolynomial trial = PolyUtil.integerFromModularCoefficients(pfac, mtrial); trial = engine.basePrimitivePart(trial); //if ( ! isPrimitive ) { //} if (debug) { logger.info("trial = " + trial); // + ", mtrial = " + mtrial); } if (PolyUtil. baseSparsePseudoRemainder(ui, trial).isZERO()) { logger.info("successful trial = " + trial); factors.add(trial); ui = PolyUtil. basePseudoDivide(ui, trial); //System.out.println("ui = " + ui); mlift = removeOnce(mlift, flist); logger.info("new mlift= " + mlift); //System.out.println("dl = " + dl); if (mlift.size() > 1) { dl = (mlift.size() + 1) / 2; j = 0; // since j++ break; } logger.info("last factor = " + ui); factors.add(ui); if (cfactors != null) { cfactors.addAll(factors); factors = cfactors; } return normalizeFactorization(factors); } } } if (!ui.isONE() && !ui.equals(pd)) { logger.info("rest factor = " + ui); // pp(ui) ?? no ?? factors.add(ui); } if (factors.size() == 0) { logger.info("irreducible P = " + P); factors.add(pd); // P } if (cfactors != null) { cfactors.addAll(factors); factors = cfactors; } return normalizeFactorization(factors); } /** * Test if b has a prime factor different to the elements of A. * @param A list of integer with at least one different prime factor. * @param b integer to test with A. * @return true, if b hase a prime factor different to elements of A */ boolean testSeparate(List A, BigInteger b) { int i = 0; List gei = new ArrayList(A.size()); for (BigInteger c : A) { BigInteger g = c.gcd(b).abs(); gei.add(g); if (!g.isONE()) { i++; } } //if ( i >= 1 ) { //System.out.println("gei = " + gei + ", cei = " + cei + ", pec(w) = " + pec); //} return (i <= 1); } // not useable boolean isNearlySquarefree(GenPolynomial P) { // unused // in main variable GenPolynomialRing pfac = P.ring; if (pfac.nvar >= 0) { // allways true return sengine.isSquarefree(P); } GenPolynomialRing> rfac = pfac.recursive(1); GenPolynomial> Pr = PolyUtil. recursive(rfac, P); GenPolynomial> Ps = PolyUtil. recursiveDeriviative(Pr); System.out.println("Pr = " + Pr); System.out.println("Ps = " + Ps); GenPolynomial> g = engine.recursiveUnivariateGcd(Pr, Ps); System.out.println("g_m = " + g); if (!g.isONE()) { return false; } // in lowest variable rfac = pfac.recursive(pfac.nvar - 1); Pr = PolyUtil. recursive(rfac, P); Pr = PolyUtil. switchVariables(Pr); Ps = PolyUtil. recursiveDeriviative(Pr); System.out.println("Pr = " + Pr); System.out.println("Ps = " + Ps); g = engine.recursiveUnivariateGcd(Pr, Ps); System.out.println("g_1 = " + g); if (!g.isONE()) { return false; } return true; } } /** * Container for factorization trial lifting parameters. */ class TrialParts { /** * evaluation points */ public final List evalPoints; /** * univariate polynomial */ public final GenPolynomial univPoly; /** * irreducible factors of univariate polynomial */ public final List> univFactors; /** * irreducible factors of leading coefficient */ public final List> ldcfFactors; /** * evaluated factors of leading coefficient factors by evaluation points */ public final List ldcfEval; /** * Constructor. * @param ev evaluation points. * @param up univariate polynomial. * @param uf irreducible factors of up. * @param le irreducible factors of leading coefficient. * @param lf evaluated le by evaluation points. */ public TrialParts(List ev, GenPolynomial up, List> uf, List le, List> lf) { evalPoints = ev; univPoly = up; univFactors = uf; //ldcfPoly = lp; ldcfFactors = lf; ldcfEval = le; } /** * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("TrialParts["); sb.append("evalPoints = " + evalPoints); sb.append(", univPoly = " + univPoly); sb.append(", univFactors = " + univFactors); sb.append(", ldcfEval = " + ldcfEval); sb.append(", ldcfFactors = " + ldcfFactors); sb.append("]"); return sb.toString(); } } jas-2.5/src/edu/jas/ufd/FactorFactory.java0000644000175000017500000001620612004537436020664 0ustar giovannigiovanni/* * $Id: FactorFactory.java 4067 2012-07-27 16:17:35Z kredel $ */ package edu.jas.ufd; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomialRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Factorization algorithms factory. Select appropriate factorization engine * based on the coefficient types. * @author Heinz Kredel * @usage To create objects that implement the Factorization * interface use the FactorFactory. It will select an * appropriate implementation based on the types of polynomial * coefficients C. To obtain an implementation use * getImplementation(), it returns an object of a class * which extends the FactorAbstract class which implements * the Factorization interface. * *
 * Factorization<CT> engine;
 * engine = FactorFactory.<CT> getImplementation(cofac);
 * c = engine.factors(a);
 * 
* * For example, if the coefficient type is BigInteger, the usage looks * like * *
 * BigInteger cofac = new BigInteger();
 * Factorization<BigInteger> engine;
 * engine = FactorFactory.getImplementation(cofac);
 * Sm = engine.factors(poly);
 * 
* * @see edu.jas.ufd.Factorization#factors(edu.jas.poly.GenPolynomial P) */ public class FactorFactory { private static final Logger logger = Logger.getLogger(FactorFactory.class); /** * Protected factory constructor. */ protected FactorFactory() { } /** * Determine suitable implementation of factorization algorithm, case * ModInteger. * @param fac ModIntegerRing. * @return factorization algorithm implementation. */ public static FactorAbstract getImplementation(ModIntegerRing fac) { return new FactorModular(fac); } /** * Determine suitable implementation of factorization algorithm, case * ModInteger. * @param fac ModIntegerRing. * @return factorization algorithm implementation. */ public static FactorAbstract getImplementation(ModLongRing fac) { return new FactorModular(fac); } /** * Determine suitable implementation of factorization algorithm, case * BigInteger. * @param fac BigInteger. * @return factorization algorithm implementation. */ public static FactorAbstract getImplementation(BigInteger fac) { return new FactorInteger(); } /** * Determine suitable implementation of factorization algorithms, case * BigRational. * @param fac BigRational. * @return factorization algorithm implementation. */ public static FactorAbstract getImplementation(BigRational fac) { return new FactorRational(); } /** * Determine suitable implementation of factorization algorithms, case * AlgebraicNumber<C>. * @param fac AlgebraicNumberRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return factorization algorithm implementation. */ public static > FactorAbstract> getImplementation( AlgebraicNumberRing fac) { return new FactorAlgebraic(fac); } /** * Determine suitable implementation of factorization algorithms, case * Complex<C>. * @param fac ComplexRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return factorization algorithm implementation. */ public static > FactorAbstract> getImplementation(ComplexRing fac) { return new FactorComplex(fac); } /** * Determine suitable implementation of factorization algorithms, case * Quotient<C>. * @param fac QuotientRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return factorization algorithm implementation. */ public static > FactorAbstract> getImplementation(QuotientRing fac) { return new FactorQuotient(fac); } /** * Determine suitable implementation of factorization algorithms, case * recursive GenPolynomial<C>. Use recursiveFactors(). * @param fac GenPolynomialRing<C>. * @param coefficient type, e.g. BigRational, ModInteger. * @return factorization algorithm implementation. */ public static > FactorAbstract getImplementation(GenPolynomialRing fac) { return getImplementation(fac.coFac); } /** * Determine suitable implementation of factorization algorithms, other * cases. * @param coefficient type * @param fac RingFactory<C>. * @return factorization algorithm implementation. */ @SuppressWarnings("unchecked") public static > FactorAbstract getImplementation(RingFactory fac) { logger.info("factor factory = " + fac.getClass().getName()); //System.out.println("fac_o_ufd = " + fac.getClass().getName()); FactorAbstract/*raw type*/ufd = null; AlgebraicNumberRing afac = null; ComplexRing cfac = null; QuotientRing qfac = null; GenPolynomialRing pfac = null; Object ofac = fac; if (ofac instanceof BigInteger) { ufd = new FactorInteger(); } else if (ofac instanceof BigRational) { ufd = new FactorRational(); } else if (ofac instanceof ModIntegerRing) { ufd = new FactorModular(fac); } else if (ofac instanceof ModLongRing) { ufd = new FactorModular(fac); } else if (ofac instanceof ComplexRing) { cfac = (ComplexRing) ofac; ufd = new FactorComplex(cfac); } else if (ofac instanceof AlgebraicNumberRing) { //System.out.println("afac_o = " + ofac); afac = (AlgebraicNumberRing) ofac; //ofac = afac.ring.coFac; ufd = new FactorAlgebraic/*raw */(afac); } else if (ofac instanceof QuotientRing) { //System.out.println("qfac_o = " + ofac); qfac = (QuotientRing) ofac; ufd = new FactorQuotient/*raw */(qfac); } else if (ofac instanceof GenPolynomialRing) { //System.out.println("qfac_o = " + ofac); pfac = (GenPolynomialRing) ofac; ufd = getImplementation(pfac.coFac); } else { throw new IllegalArgumentException("no factorization implementation for " + fac.getClass().getName()); } //logger.info("implementation = " + ufd); return (FactorAbstract) ufd; } } jas-2.5/src/edu/jas/ufd/Quotient.java0000644000175000017500000003560112137713752017732 0ustar giovannigiovanni/* * $Id: Quotient.java 4406 2013-04-30 10:07:39Z kredel $ */ package edu.jas.ufd; import org.apache.log4j.Logger; import edu.jas.kern.PrettyPrint; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Quotient, that is a rational function, based on GenPolynomial with RingElem * interface. Objects of this class are immutable. * @author Heinz Kredel */ public class Quotient> implements GcdRingElem> { private static final Logger logger = Logger.getLogger(Quotient.class); private final boolean debug = logger.isDebugEnabled(); /** * Quotient class factory data structure. */ public final QuotientRing ring; /** * Numerator part of the element data structure. */ public final GenPolynomial num; /** * Denominator part of the element data structure. */ public final GenPolynomial den; /** * The constructor creates a Quotient object from a ring factory. * @param r ring factory. */ public Quotient(QuotientRing r) { this(r, r.ring.getZERO()); } /** * The constructor creates a Quotient object from a ring factory and a * numerator polynomial. The denominator is assumed to be 1. * @param r ring factory. * @param n numerator polynomial. */ public Quotient(QuotientRing r, GenPolynomial n) { this(r, n, r.ring.getONE(), true); } /** * The constructor creates a Quotient object from a ring factory and a * numerator and denominator polynomial. * @param r ring factory. * @param n numerator polynomial. * @param d denominator polynomial. */ public Quotient(QuotientRing r, GenPolynomial n, GenPolynomial d) { this(r, n, d, false); } /** * The constructor creates a Quotient object from a ring factory and a * numerator and denominator polynomial. * @param r ring factory. * @param n numerator polynomial. * @param d denominator polynomial. * @param isred true if gcd(n,d) == 1, else false. */ protected Quotient(QuotientRing r, GenPolynomial n, GenPolynomial d, boolean isred) { if (d == null || d.isZERO()) { throw new IllegalArgumentException("denominator may not be zero"); } ring = r; if (d.signum() < 0) { n = n.negate(); d = d.negate(); } if (!isred) { // must reduce to lowest terms GenPolynomial gcd = ring.gcd(n, d); if (false || debug) { logger.info("gcd = " + gcd); } //GenPolynomial gcd = ring.ring.getONE(); if (!gcd.isONE()) { //logger.info("gcd = " + gcd); n = ring.divide(n, gcd); d = ring.divide(d, gcd); } } C lc = d.leadingBaseCoefficient(); if (!lc.isONE() && lc.isUnit()) { lc = lc.inverse(); n = n.multiply(lc); d = d.multiply(lc); } num = n; den = d; } /** * Get the corresponding element factory. * @return factory for this Element. * @see edu.jas.structure.Element#factory() */ public QuotientRing factory() { return ring; } /** * Clone this. * @see java.lang.Object#clone() */ @Override public Quotient copy() { return new Quotient(ring, num, den, true); } /** * Is Quotient zero. * @return If this is 0 then true is returned, else false. * @see edu.jas.structure.RingElem#isZERO() */ public boolean isZERO() { return num.isZERO(); } /** * Is Quotient one. * @return If this is 1 then true is returned, else false. * @see edu.jas.structure.RingElem#isONE() */ public boolean isONE() { return num.equals(den); } /** * Is Quotient a unit. * @return If this is a unit then true is returned, else false. * @see edu.jas.structure.RingElem#isUnit() */ public boolean isUnit() { if (num.isZERO()) { return false; } return true; } /** * Is Qoutient a constant. * @return true, if this has constant numerator and denominator, else false. */ public boolean isConstant() { return num.isConstant() && den.isConstant(); } /** * Get the String representation as RingElem. * @see java.lang.Object#toString() */ @Override public String toString() { if (PrettyPrint.isTrue()) { String s = "{ " + num.toString(ring.ring.getVars()); if (!den.isONE()) { s += " | " + den.toString(ring.ring.getVars()); } return s + " }"; } return "Quotient[ " + num.toString() + " | " + den.toString() + " ]"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this Element. * @see edu.jas.structure.Element#toScript() */ //JAVA6only: @Override public String toScript() { // Python case if (den.isONE()) { return num.toScript(); } return num.toScript() + " / " + den.toScript(); } /** * Get a scripting compatible string representation of the factory. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.Element#toScriptFactory() */ //JAVA6only: @Override public String toScriptFactory() { // Python case return factory().toScript(); } /** * Quotient comparison. * @param b Quotient. * @return sign(this-b). */ //JAVA6only: @Override public int compareTo(Quotient b) { if (b == null || b.isZERO()) { return this.signum(); } if (this.isZERO()) { return -b.signum(); } // assume sign(den,b.den) > 0 int s1 = num.signum(); int s2 = b.num.signum(); int t = (s1 - s2) / 2; if (t != 0) { return t; } if ( den.compareTo(b.den) == 0 ) { return num.compareTo(b.num); } GenPolynomial r = num.multiply(b.den); GenPolynomial s = den.multiply(b.num); return r.compareTo(s); } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @SuppressWarnings("unchecked") @Override public boolean equals(Object b) { if (!(b instanceof Quotient)) { return false; } Quotient a = null; try { a = (Quotient) b; } catch (ClassCastException e) { } if (a == null) { return false; } return compareTo( a ) == 0; //return num.equals(a.num) && den.equals(a.den); } /** * Hash code for this quotient. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); h = 37 * h + num.hashCode(); h = 37 * h + den.hashCode(); return h; } /** * Quotient absolute value. * @return the absolute value of this. * @see edu.jas.structure.RingElem#abs() */ public Quotient abs() { return new Quotient(ring, num.abs(), den, true); } /** * Quotient summation. * @param S Quotient. * @return this+S. */ public Quotient sum(Quotient S) { if (S == null || S.isZERO()) { return this; } if (this.isZERO()) { return S; } GenPolynomial n; if (den.isONE() && S.den.isONE()) { n = num.sum(S.num); return new Quotient(ring, n); } if (den.isONE()) { n = num.multiply(S.den); n = n.sum(S.num); return new Quotient(ring, n, S.den, false); } if (S.den.isONE()) { n = S.num.multiply(den); n = n.sum(num); return new Quotient(ring, n, den, false); } if ( den.compareTo(S.den) == 0 ) { n = num.sum(S.num); return new Quotient(ring, n, den, false); } GenPolynomial d; GenPolynomial sd; GenPolynomial g; g = ring.gcd(den, S.den); if (g.isONE()) { d = den; sd = S.den; } else { d = ring.divide(den, g); sd = ring.divide(S.den, g); } n = num.multiply(sd); n = n.sum(d.multiply(S.num)); if (n.isZERO()) { return ring.getZERO(); } GenPolynomial f; GenPolynomial dd; dd = den; if (!g.isONE()) { f = ring.gcd(n, g); if (!f.isONE()) { n = ring.divide(n, f); dd = ring.divide(den, f); } } d = dd.multiply(sd); return new Quotient(ring, n, d, true); } /** * Quotient negate. * @return -this. * @see edu.jas.structure.RingElem#negate() */ public Quotient negate() { return new Quotient(ring, num.negate(), den, true); } /** * Quotient signum. * @see edu.jas.structure.RingElem#signum() * @return signum(this). */ public int signum() { // assume sign(den) > 0 return num.signum(); } /** * Quotient subtraction. * @param S Quotient. * @return this-S. */ public Quotient subtract(Quotient S) { return sum(S.negate()); } /** * Quotient division. * @param S Quotient. * @return this/S. */ public Quotient divide(Quotient S) { return multiply(S.inverse()); } /** * Quotient inverse. * @see edu.jas.structure.RingElem#inverse() * @return S with S = 1/this. */ public Quotient inverse() { if (num.isZERO()) { throw new ArithmeticException("element not invertible " + this); } return new Quotient(ring, den, num, true); } /** * Quotient remainder. * @param S Quotient. * @return this - (this/S)*S. */ public Quotient remainder(Quotient S) { if (num.isZERO()) { throw new ArithmeticException("element not invertible " + this); } return ring.getZERO(); } /** * Quotient multiplication. * @param S Quotient. * @return this*S. */ public Quotient multiply(Quotient S) { if (S == null || S.isZERO()) { return S; } if (num.isZERO()) { return this; } if (S.isONE()) { return this; } if (this.isONE()) { return S; } GenPolynomial n; if (den.isONE() && S.den.isONE()) { n = num.multiply(S.num); return new Quotient(ring, n, den, true); } GenPolynomial g; GenPolynomial d; if (den.isONE()) { g = ring.gcd(num, S.den); n = ring.divide(num, g); d = ring.divide(S.den, g); n = n.multiply(S.num); return new Quotient(ring, n, d, true); } if (S.den.isONE()) { g = ring.gcd(S.num, den); n = ring.divide(S.num, g); d = ring.divide(den, g); n = n.multiply(num); return new Quotient(ring, n, d, true); } if ( den.compareTo(S.den) == 0 ) { // correct ? d = den.multiply(den); n = num.multiply(S.num); return new Quotient(ring, n, d, true); } GenPolynomial f; GenPolynomial sd; GenPolynomial sn; g = ring.gcd(num, S.den); n = ring.divide(num, g); sd = ring.divide(S.den, g); f = ring.gcd(den, S.num); d = ring.divide(den, f); sn = ring.divide(S.num, f); n = n.multiply(sn); d = d.multiply(sd); return new Quotient(ring, n, d, true); } /** * Quotient multiplication by GenPolynomial. * @param b GenPolynomial. * @return this*b. */ public Quotient multiply(GenPolynomial b) { if (b == null || b.isZERO()) { return ring.getZERO(); } if (num.isZERO()) { return this; } if (b.isONE()) { return this; } GenPolynomial gcd = ring.gcd(b, den); GenPolynomial d = den; if (!gcd.isONE()) { b = ring.divide(b, gcd); d = ring.divide(d, gcd); } if (this.isONE()) { return new Quotient(ring, b, d, true); } GenPolynomial n = num.multiply(b); return new Quotient(ring, n, d, true); } /** * Quotient multiplication by coefficient. * @param b coefficient. * @return this*b. */ public Quotient multiply(C b) { if (b == null || b.isZERO()) { return ring.getZERO(); } if (num.isZERO()) { return this; } if (b.isONE()) { return this; } GenPolynomial n = num.multiply(b); return new Quotient(ring, n, den, true); } /** * Quotient monic. * @return this with monic value part. */ public Quotient monic() { if (num.isZERO()) { return this; } C lbc = num.leadingBaseCoefficient(); if (!lbc.isUnit()) { return this; } lbc = lbc.inverse(); //lbc = lbc.abs(); GenPolynomial n = num.multiply(lbc); //GenPolynomial d = den.multiply(lbc); return new Quotient(ring, n, den, true); } /** * Greatest common divisor. * @param b other element. * @return gcd(this,b). */ public Quotient gcd(Quotient b) { if (b == null || b.isZERO()) { return this; } if (this.isZERO()) { return b; } return ring.getONE(); } /** * Extended greatest common divisor. * @param b other element. * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). */ @SuppressWarnings("unchecked") public Quotient[] egcd(Quotient b) { Quotient[] ret = (Quotient[]) new Quotient[3]; ret[0] = null; ret[1] = null; ret[2] = null; if (b == null || b.isZERO()) { ret[0] = this; return ret; } if (this.isZERO()) { ret[0] = b; return ret; } GenPolynomial two = ring.ring.fromInteger(2); ret[0] = ring.getONE(); ret[1] = (this.multiply(two)).inverse(); ret[2] = (b.multiply(two)).inverse(); return ret; } } jas-2.5/src/edu/jas/ufd/Factors.java0000644000175000017500000002404411445457062017522 0ustar giovannigiovanni/* * $Id: Factors.java 3329 2010-09-19 19:02:10Z kredel $ */ package edu.jas.ufd; import java.io.Serializable; import java.util.List; import java.util.ArrayList; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolynomialList; import edu.jas.structure.GcdRingElem; /** * Container for the factors of absolute factorization. * @author Heinz Kredel * @param coefficient type */ public class Factors> implements Comparable>, Serializable { /** * Original (irreducible) polynomial to be factored with coefficients from C. */ public final GenPolynomial poly; /** * Algebraic field extension over C. Should be null, if p is absolutely * irreducible. */ public final AlgebraicNumberRing afac; /** * Original polynomial to be factored with coefficients from * AlgebraicNumberRing<C>. Should be null, if p is absolutely irreducible. */ public final GenPolynomial> apoly; /** * List of factors with coefficients from AlgebraicNumberRing<C>. Should be * null, if p is absolutely irreducible. */ public final List>> afactors; /** * List of factors with coefficients from AlgebraicNumberRing<AlgebraicNumber<C>>. * Should be null, if p is absolutely irreducible. */ public final List>> arfactors; /** * Constructor. * @param p absolute irreducible GenPolynomial. */ public Factors(GenPolynomial p) { this(p, null, null, null, null); } /** * Constructor. * @param p irreducible GenPolynomial over C. * @param af algebraic extension field of C where p has factors from afact. * @param ap GenPolynomial p represented with coefficients from af. * @param afact absolute irreducible factors of p with coefficients from af. */ public Factors(GenPolynomial p, AlgebraicNumberRing af, GenPolynomial> ap, List>> afact) { this(p, af, ap, afact, null); } /** * Constructor. * @param p irreducible GenPolynomial over C. * @param af algebraic extension field of C where p has factors from afact. * @param ap GenPolynomial p represented with coefficients from af. * @param afact absolute irreducible factors of p with coefficients from af. * @param arfact further absolute irreducible factors of p with coefficients from extensions of af. */ public Factors(GenPolynomial p, AlgebraicNumberRing af, GenPolynomial> ap, List>> afact, List>> arfact) { poly = p; afac = af; apoly = ap; afactors = afact; arfactors = arfact; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append(poly.toString()); if (afac == null) { return sb.toString(); } sb.append(" = "); boolean first = true; for (GenPolynomial> ap : afactors) { if (first) { first = false; } else { sb.append(", "); } sb.append(ap.toString()); } sb.append("\n ## over " + afac.toString() + "\n"); if (arfactors == null) { return sb.toString(); } first = true; for (Factors> arp : arfactors) { if (first) { first = false; } else { sb.append(",\n"); } sb.append(arp.toString()); } return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this container. * @see edu.jas.structure.ElemFactory#toScript() */ public String toScript() { // Python case StringBuffer sb = new StringBuffer(); //sb.append(poly.toScript()); if (afac == null) { return sb.toString(); } //sb.append(" =\n"); boolean first = true; for (GenPolynomial> ap : afactors) { if (first) { first = false; } else { sb.append("\n * "); } //sb.append("( " + ap.toScript() + " )"); sb.append(ap.toScript()); } sb.append(" ## over " + afac.toScript() + "\n"); if (arfactors == null) { return sb.toString(); } first = true; for (Factors> arp : arfactors) { if (first) { first = false; } else { sb.append("\n * "); } sb.append(arp.toScript()); } return sb.toString(); } /** * Hash code for this Factors. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = poly.hashCode(); if (afac == null) { return h; } h = (h << 27); h += afac.hashCode(); if ( afactors != null ) { h = (h << 27); h += afactors.hashCode(); } if ( arfactors != null ) { h = (h << 27); h += arfactors.hashCode(); } return h; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { if (!(B instanceof Factors)) { return false; } Factors a = null; try { a = (Factors) B; } catch (ClassCastException ignored) { } if (a == null) { return false; } return this.compareTo(a) == 0; } /** * Comparison. * @param facs factors container. * @return sign(this.poly-facs.poly) lexicographic > * sign(afac.modul-facs.afac.modul) * lexicographic > afactors.compareTo(facs.afactors) * lexicographic > arfactors[i].compareTo(facs.arfactors[i]) */ public int compareTo(Factors facs) { int s = poly.compareTo(facs.poly); //System.out.println("s1 = " + s); if (s != 0) { return s; } if (afac == null) { return -1; } if (facs.afac == null) { return +1; } s = afac.modul.compareTo(facs.afac.modul); //System.out.println("s2 = " + s); if ( s != 0 ) { return s; } GenPolynomialRing> ar = afactors.get(0).ring; GenPolynomialRing> br = facs.afactors.get(0).ring; PolynomialList> ap = new PolynomialList>(ar,afactors); PolynomialList> bp = new PolynomialList>(br,facs.afactors); s = ap.compareTo(bp); //System.out.println("s3 = " + s); if ( s != 0 ) { return s; } if (arfactors == null && facs.arfactors == null) { return 0; } if (arfactors == null) { return -1; } if (facs.arfactors == null) { return +1; } // lexicographic (?) int i = 0; for (Factors> arp : arfactors) { if ( i >= facs.arfactors.size() ) { return +1; } Factors> brp = facs.arfactors.get(i); //System.out.println("arp = " + arp); //System.out.println("brp = " + brp); s = arp.compareTo(brp); //System.out.println("s4 = " + s); if ( s != 0 ) { return s; } i++; } if ( i < facs.arfactors.size() ) { return -1; } return 0; } /** * Find largest extension field. * @return largest extension field or null if no extension field */ @SuppressWarnings("unchecked") public AlgebraicNumberRing findExtensionField() { if (afac == null) { return null; } if (arfactors == null) { return afac; } AlgebraicNumberRing arr = afac; int depth = 1; for (Factors> af : arfactors) { AlgebraicNumberRing> aring = af.findExtensionField(); if (aring == null) { continue; } int d = aring.depth(); if (d > depth) { depth = d; arr = (AlgebraicNumberRing) (Object) aring; } } return arr; } /** * Get the list of factors at one level. * @return list of algebraic factors */ public List>> getFactors() { List>> af = new ArrayList>>(); if ( afac == null ) { return af; } af.addAll(afactors); if ( arfactors == null ) { return af; } for (Factors> arp : arfactors) { af.add( arp.poly ); } return af; } /** * Get the factor for polynomial. * @return algebraic factor */ public Factors> getFactor(GenPolynomial> p) { if ( afac == null ) { return null; } for (Factors> arp : arfactors) { if ( p.equals( arp.poly ) ) { return arp; } } return null; } } jas-2.5/src/edu/jas/ufd/PartialFraction.java0000644000175000017500000002041411435516726021202 0ustar giovannigiovanni/* * $Id: PartialFraction.java 3295 2010-08-26 17:01:10Z kredel $ */ package edu.jas.ufd; import java.io.Serializable; import java.util.List; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Container for the partial fraction decomposition of a squarefree denominator. * num/den = sum( a_i ( der(d_i) / d_i ) ) * @author Heinz Kredel * @param coefficient type */ public class PartialFraction> implements Serializable { /** * Original numerator polynomial coefficients from C and deg(num) < * deg(den). */ public final GenPolynomial num; /** * Original (irreducible) denominator polynomial coefficients from C. */ public final GenPolynomial den; /** * List of numbers from C. */ public final List cfactors; /** * List of linear factors of the denominator with coefficients from C. */ public final List> cdenom; /** * List of algebraic numbers of an algebraic field extension over C. */ public final List> afactors; /** * List of factors of the denominator with coefficients from an * AlgebraicNumberRing<C>. */ public final List>> adenom; /** * Constructor. * @param n numerator GenPolynomial over C. * @param d irreducible denominator GenPolynomial over C. * @param cf list of elements a_i. * @param cd list of linear factors d_i of d. * @param af list of algebraic elements a_i. * @param ad list of irreducible factors d_i of d with algebraic * coefficients. n/d = sum( a_i ( der(d_i) / d_i ) ) */ public PartialFraction(GenPolynomial n, GenPolynomial d, List cf, List> cd, List> af, List>> ad) { num = n; den = d; cfactors = cf; cdenom = cd; afactors = af; adenom = ad; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append("(" + num.toString() + ")"); sb.append(" / "); sb.append("(" + den.toString() + ")"); sb.append(" =\n"); boolean first = true; for (int i = 0; i < cfactors.size(); i++) { C cp = cfactors.get(i); if (first) { first = false; } else { sb.append(" + "); } sb.append("(" + cp.toString() + ")"); GenPolynomial p = cdenom.get(i); sb.append(" log( " + p.toString() + ")"); } if (!first && afactors.size() > 0) { sb.append(" + "); } first = true; for (int i = 0; i < afactors.size(); i++) { if (first) { first = false; } else { sb.append(" + "); } AlgebraicNumber ap = afactors.get(i); AlgebraicNumberRing ar = ap.factory(); //sb.append(" ## over " + ap.factory() + "\n"); GenPolynomial> p = adenom.get(i); if (p.degree(0) < ar.modul.degree(0) && ar.modul.degree(0) > 2) { sb.append("sum_(" + ar.getGenerator() + " in "); sb.append("rootOf(" + ar.modul + ") ) "); } else { //sb.append("sum_("+ar+") "); } sb.append("(" + ap.toString() + ")"); sb.append(" log( " + p.toString() + ")"); } return sb.toString(); } /** * Get the String representation. * @see java.lang.Object#toString() */ //@Override public String toStringX() { StringBuffer sb = new StringBuffer(); sb.append("(" + num.toString() + ")"); sb.append(" / "); sb.append("(" + den.toString() + ")"); sb.append(" =\n"); boolean first = true; for (C cp : cfactors) { if (first) { first = false; } else { sb.append(", "); } sb.append(cp.toString()); } if (!first) { sb.append(" linear denominators: "); } first = true; for (GenPolynomial cp : cdenom) { if (first) { first = false; } else { sb.append(", "); } sb.append(cp.toString()); } if (!first) { sb.append("; "); } first = true; for (AlgebraicNumber ap : afactors) { if (first) { first = false; } else { //sb.append(", "); } sb.append(ap.toString()); sb.append(" ## over " + ap.factory() + "\n"); } if (!first) { sb.append(" denominators: "); } first = true; for (GenPolynomial> ap : adenom) { if (first) { first = false; } else { sb.append(", "); } sb.append(ap.toString()); } return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this container. * @see edu.jas.structure.ElemFactory#toScript() */ public String toScript() { // Python case StringBuffer sb = new StringBuffer(); sb.append(num.toScript()); sb.append(" / "); sb.append(den.toScript()); sb.append(" = "); boolean first = true; for (C cp : cfactors) { if (first) { first = false; } else { sb.append(", "); } sb.append(cp.toScript()); } if (!first) { sb.append(" linear denominators: "); } first = true; for (GenPolynomial cp : cdenom) { if (first) { first = false; } else { sb.append(", "); } sb.append(cp.toScript()); } if (!first) { sb.append(", "); } first = true; for (AlgebraicNumber ap : afactors) { if (first) { first = false; } else { //sb.append(", "); } sb.append(ap.toScript()); sb.append(" ## over " + ap.toScriptFactory() + "\n"); } sb.append(" denominators: "); first = true; for (GenPolynomial> ap : adenom) { if (first) { first = false; } else { sb.append(", "); } sb.append(ap.toScript()); } return sb.toString(); } /** * Hash code for this Factors. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = num.hashCode(); h = h * 37 + den.hashCode(); h = h * 37 + cfactors.hashCode(); h = h * 37 + cdenom.hashCode(); h = h * 37 + afactors.hashCode(); h = h * 37 + adenom.hashCode(); return h; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { if (!(B instanceof PartialFraction)) { return false; } PartialFraction a = null; try { a = (PartialFraction) B; } catch (ClassCastException ignored) { } if (a == null) { return false; } boolean t = num.equals(a.num) && den.equals(a.den); if (!t) { return t; } t = cfactors.equals(a.cfactors); if (!t) { return t; } t = cdenom.equals(a.cdenom); if (!t) { return t; } t = afactors.equals(a.afactors); if (!t) { return t; } t = adenom.equals(a.adenom); return t; } } jas-2.5/src/edu/jas/ufd/SquarefreeFieldCharP.java0000644000175000017500000006351212012003416022065 0ustar giovannigiovanni/* * $Id: SquarefreeFieldCharP.java 4100 2012-08-12 19:42:07Z kredel $ */ package edu.jas.ufd; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Squarefree decomposition for coefficient fields of characteristic p. * @author Heinz Kredel */ public abstract class SquarefreeFieldCharP> extends SquarefreeAbstract { private static final Logger logger = Logger.getLogger(SquarefreeFieldCharP.class); private final boolean debug = logger.isDebugEnabled(); /* * Squarefree engine for characteristic p base coefficients. */ //protected final SquarefreeAbstract rengine; /** * Factory for finite field of characteristic p coefficients. */ protected final RingFactory coFac; /** * Factory for a algebraic extension of a finite field of characteristic p * coefficients. If coFac is an algebraic extension, then * aCoFac is equal to coFac, else * aCoFac is null. */ protected final AlgebraicNumberRing aCoFac; /** * Factory for a transcendental extension of a finite field of * characteristic p coefficients. If coFac is an transcendental * extension, then qCoFac is equal to coFac, else * qCoFac is null. */ protected final QuotientRing qCoFac; /** * Constructor. */ @SuppressWarnings("unchecked") public SquarefreeFieldCharP(RingFactory fac) { super(GCDFactory. getProxy(fac)); if (!fac.isField()) { //throw new IllegalArgumentException("fac must be a field"); logger.warn("fac should be a field: " + fac.toScript()); } if (fac.characteristic().signum() == 0) { throw new IllegalArgumentException("characterisic(fac) must be non-zero"); } coFac = fac; Object oFac = coFac; if (oFac instanceof AlgebraicNumberRing) { aCoFac = (AlgebraicNumberRing) oFac; // is not correct //rengine = (SquarefreeAbstract) SquarefreeFactory.getImplementation(aCoFac.ring); qCoFac = null; } else { aCoFac = null; if (oFac instanceof QuotientRing) { qCoFac = (QuotientRing) oFac; // is not correct //rengine = (SquarefreeAbstract) SquarefreeFactory.getImplementation(qCoFac.ring); } else { qCoFac = null; //rengine = null; //(SquarefreeAbstract) SquarefreeFactory.getImplementation(oFac); } } } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return getClass().getName() + " with " + engine + " over " + coFac; } /** * GenPolynomial polynomial greatest squarefree divisor. * @param P GenPolynomial. * @return squarefree(pp(P)). */ @Override public GenPolynomial baseSquarefreePart(GenPolynomial P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } // just for the moment: GenPolynomial s = pfac.getONE(); SortedMap, Long> factors = baseSquarefreeFactors(P); logger.info("sqfPart,factors = " + factors); for (GenPolynomial sp : factors.keySet()) { s = s.multiply(sp); } return s.monic(); } /** * GenPolynomial polynomial squarefree factorization. * @param A GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i^{e_i} and p_i squarefree. */ @Override public SortedMap, Long> baseSquarefreeFactors(GenPolynomial A) { SortedMap, Long> sfactors = new TreeMap, Long>(); if (A == null || A.isZERO()) { return sfactors; } GenPolynomialRing pfac = A.ring; if (A.isConstant()) { C coeff = A.leadingBaseCoefficient(); //System.out.println("coeff = " + coeff + " @ " + coeff.factory()); SortedMap rfactors = squarefreeFactors(coeff); //System.out.println("rfactors,const = " + rfactors); if (rfactors != null && rfactors.size() > 0) { for (Map.Entry me : rfactors.entrySet()) { C c = me.getKey(); if (!c.isONE()) { GenPolynomial cr = pfac.getONE().multiply(c); Long rk = me.getValue(); // rfactors.get(c); sfactors.put(cr, rk); } } } else { sfactors.put(A, 1L); } return sfactors; } if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } C ldbcf = A.leadingBaseCoefficient(); if (!ldbcf.isONE()) { A = A.divide(ldbcf); SortedMap rfactors = squarefreeFactors(ldbcf); //System.out.println("rfactors,ldbcf = " + rfactors); if (rfactors != null && rfactors.size() > 0) { for (Map.Entry me : rfactors.entrySet()) { C c = me.getKey(); if (!c.isONE()) { GenPolynomial cr = pfac.getONE().multiply(c); Long rk = me.getValue(); //rfactors.get(c); sfactors.put(cr, rk); } } } else { GenPolynomial f1 = pfac.getONE().multiply(ldbcf); //System.out.println("gcda sqf f1 = " + f1); sfactors.put(f1, 1L); } ldbcf = pfac.coFac.getONE(); } GenPolynomial T0 = A; long e = 1L; GenPolynomial Tp; GenPolynomial T = null; GenPolynomial V = null; long k = 0L; long mp = 0L; boolean init = true; while (true) { //System.out.println("T0 = " + T0); if (init) { if (T0.isConstant() || T0.isZERO()) { break; } Tp = PolyUtil. baseDeriviative(T0); T = engine.baseGcd(T0, Tp); T = T.monic(); V = PolyUtil. basePseudoDivide(T0, T); //System.out.println("iT0 = " + T0); //System.out.println("iTp = " + Tp); //System.out.println("iT = " + T); //System.out.println("iV = " + V); //System.out.println("const(iV) = " + V.isConstant()); k = 0L; mp = 0L; init = false; } if (V.isConstant()) { mp = pfac.characteristic().longValue(); // assert != 0 //T0 = PolyUtil. baseModRoot(T,mp); T0 = baseRootCharacteristic(T); logger.info("char root: T0 = " + T0 + ", T = " + T); if (T0 == null) { //break; T0 = pfac.getZERO(); } e = e * mp; init = true; continue; } k++; if (mp != 0L && k % mp == 0L) { T = PolyUtil. basePseudoDivide(T, V); System.out.println("k = " + k); //System.out.println("T = " + T); k++; } GenPolynomial W = engine.baseGcd(T, V); W = W.monic(); GenPolynomial z = PolyUtil. basePseudoDivide(V, W); //System.out.println("W = " + W); //System.out.println("z = " + z); V = W; T = PolyUtil. basePseudoDivide(T, V); //System.out.println("V = " + V); //System.out.println("T = " + T); if (z.degree(0) > 0) { if (ldbcf.isONE() && !z.leadingBaseCoefficient().isONE()) { z = z.monic(); logger.info("z,monic = " + z); } sfactors.put(z, (e * k)); } } // look, a stupid error: // if ( !ldbcf.isONE() ) { // GenPolynomial f1 = sfactors.firstKey(); // long e1 = sfactors.remove(f1); // System.out.println("gcda sqf c = " + c); // f1 = f1.multiply(c); // //System.out.println("gcda sqf f1e = " + f1); // sfactors.put(f1,e1); // } logger.info("exit char root: T0 = " + T0 + ", T = " + T); return sfactors; } /** * GenPolynomial recursive univariate polynomial greatest squarefree * divisor. * @param P recursive univariate GenPolynomial. * @return squarefree(pp(P)). */ @Override public GenPolynomial> recursiveUnivariateSquarefreePart(GenPolynomial> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for multivariate polynomials"); } // just for the moment: GenPolynomial> s = pfac.getONE(); SortedMap>, Long> factors = recursiveUnivariateSquarefreeFactors(P); if (logger.isInfoEnabled()) { logger.info("sqfPart,factors = " + factors); } for (GenPolynomial> sp : factors.keySet()) { s = s.multiply(sp); } return PolyUtil. monic(s); } /** * GenPolynomial recursive univariate polynomial squarefree factorization. * @param P recursive univariate GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i^{e_i} and p_i squarefree. */ @Override public SortedMap>, Long> recursiveUnivariateSquarefreeFactors( GenPolynomial> P) { SortedMap>, Long> sfactors = new TreeMap>, Long>(); if (P == null || P.isZERO()) { return sfactors; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { // recursiveContent not possible by return type throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } // if base coefficient ring is a field, make monic GenPolynomialRing cfac = (GenPolynomialRing) pfac.coFac; C ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient(); if (!ldbcf.isONE()) { GenPolynomial lc = cfac.getONE().multiply(ldbcf); GenPolynomial> pl = pfac.getONE().multiply(lc); sfactors.put(pl, 1L); C li = ldbcf.inverse(); //System.out.println("li = " + li); P = P.multiply(cfac.getONE().multiply(li)); //System.out.println("P,monic = " + P); ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient(); if (debug) { logger.debug("new ldbcf: " + ldbcf); } } // factors of content GenPolynomial Pc = engine.recursiveContent(P); if (logger.isInfoEnabled()) { logger.info("Pc = " + Pc); } Pc = Pc.monic(); if (!Pc.isONE()) { P = PolyUtil. coefficientPseudoDivide(P, Pc); } SortedMap, Long> rsf = squarefreeFactors(Pc); if (logger.isInfoEnabled()) { logger.info("rsf = " + rsf); } // add factors of content for (Map.Entry, Long> me : rsf.entrySet()) { GenPolynomial c = me.getKey(); if (!c.isONE()) { GenPolynomial> cr = pfac.getONE().multiply(c); Long rk = me.getValue(); //rsf.get(c); sfactors.put(cr, rk); } } // factors of recursive polynomial GenPolynomial> T0 = P; long e = 1L; GenPolynomial> Tp; GenPolynomial> T = null; GenPolynomial> V = null; long k = 0L; long mp = 0L; boolean init = true; while (true) { if (init) { if (T0.isConstant() || T0.isZERO()) { break; } Tp = PolyUtil. recursiveDeriviative(T0); T = engine.recursiveUnivariateGcd(T0, Tp); T = PolyUtil. monic(T); V = PolyUtil. recursivePseudoDivide(T0, T); //System.out.println("iT0 = " + T0); //System.out.println("iTp = " + Tp); //System.out.println("iT = " + T); //System.out.println("iV = " + V); k = 0L; mp = 0L; init = false; } if (V.isConstant()) { mp = pfac.characteristic().longValue(); // assert != 0 //T0 = PolyUtil. recursiveModRoot(T,mp); T0 = recursiveUnivariateRootCharacteristic(T); logger.info("char root: T0r = " + T0 + ", Tr = " + T); if (T0 == null) { //break; T0 = pfac.getZERO(); } e = e * mp; init = true; //continue; } k++; if (mp != 0L && k % mp == 0L) { T = PolyUtil. recursivePseudoDivide(T, V); System.out.println("k = " + k); //System.out.println("T = " + T); k++; } GenPolynomial> W = engine.recursiveUnivariateGcd(T, V); W = PolyUtil. monic(W); GenPolynomial> z = PolyUtil. recursivePseudoDivide(V, W); //System.out.println("W = " + W); //System.out.println("z = " + z); V = W; T = PolyUtil. recursivePseudoDivide(T, V); //System.out.println("V = " + V); //System.out.println("T = " + T); //was: if ( z.degree(0) > 0 ) { if (!z.isONE() && !z.isZERO()) { z = PolyUtil. monic(z); logger.info("z,put = " + z); sfactors.put(z, (e * k)); } } logger.info("exit char root: T0 = " + T0 + ", T = " + T); if (sfactors.size() == 0) { sfactors.put(pfac.getONE(), 1L); } return sfactors; } /** * GenPolynomial greatest squarefree divisor. * @param P GenPolynomial. * @return squarefree(pp(P)). */ @Override public GenPolynomial squarefreePart(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return baseSquarefreePart(P); } // just for the moment: GenPolynomial s = pfac.getONE(); SortedMap, Long> factors = squarefreeFactors(P); if (logger.isInfoEnabled()) { logger.info("sqfPart,factors = " + factors); } for (GenPolynomial sp : factors.keySet()) { if (sp.isConstant()) { continue; } s = s.multiply(sp); } return s.monic(); } /** * GenPolynomial squarefree factorization. * @param P GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i^{e_i} and p_i squarefree. */ @Override public SortedMap, Long> squarefreeFactors(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return baseSquarefreeFactors(P); } SortedMap, Long> sfactors = new TreeMap, Long>(); if (P.isZERO()) { return sfactors; } GenPolynomialRing cfac = pfac.contract(1); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1); GenPolynomial> Pr = PolyUtil. recursive(rfac, P); SortedMap>, Long> PP = recursiveUnivariateSquarefreeFactors(Pr); for (Map.Entry>, Long> m : PP.entrySet()) { Long i = m.getValue(); GenPolynomial> Dr = m.getKey(); GenPolynomial D = PolyUtil. distribute(pfac, Dr); sfactors.put(D, i); } return sfactors; } /** * Coefficient squarefree factorization. * @param coeff coefficient. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i^{e_i} and p_i squarefree. */ @Override public SortedMap squarefreeFactors(C coeff) { if (coeff == null) { return null; } SortedMap factors = new TreeMap(); RingFactory cfac = (RingFactory) coeff.factory(); if (aCoFac != null) { AlgebraicNumber an = (AlgebraicNumber) (Object) coeff; if (cfac.isFinite()) { SquarefreeFiniteFieldCharP reng = (SquarefreeFiniteFieldCharP) SquarefreeFactory .getImplementation(cfac); SortedMap rfactors = reng.rootCharacteristic(coeff); // ?? logger.info("rfactors,finite = " + rfactors); factors.putAll(rfactors); //return factors; } else { SquarefreeInfiniteAlgebraicFieldCharP reng = (SquarefreeInfiniteAlgebraicFieldCharP) SquarefreeFactory .getImplementation(cfac); SortedMap, Long> rfactors = reng.squarefreeFactors(an); logger.info("rfactors,infinite,algeb = " + rfactors); for (Map.Entry, Long> me : rfactors.entrySet()) { AlgebraicNumber c = me.getKey(); if (!c.isONE()) { C cr = (C) (Object) c; Long rk = me.getValue(); // rfactors.get(c); factors.put(cr, rk); } } } } else if (qCoFac != null) { Quotient q = (Quotient) (Object) coeff; SquarefreeInfiniteFieldCharP reng = (SquarefreeInfiniteFieldCharP) SquarefreeFactory .getImplementation(cfac); SortedMap, Long> rfactors = reng.squarefreeFactors(q); logger.info("rfactors,infinite = " + rfactors); for (Map.Entry, Long> me : rfactors.entrySet()) { Quotient c = me.getKey(); if (!c.isONE()) { C cr = (C) (Object) c; Long rk = me.getValue(); //rfactors.get(c); factors.put(cr, rk); } } } else if (cfac.isFinite()) { SquarefreeFiniteFieldCharP reng = (SquarefreeFiniteFieldCharP) SquarefreeFactory .getImplementation(cfac); SortedMap rfactors = reng.rootCharacteristic(coeff); // ?? logger.info("rfactors,finite = " + rfactors); factors.putAll(rfactors); //return factors; } else { logger.warn("case " + cfac + " not implemented"); } return factors; } /* --------- char-th roots --------------------- */ /** * GenPolynomial char-th root univariate polynomial. * @param P GenPolynomial. * @return char-th_rootOf(P), or null if no char-th root. */ public abstract GenPolynomial baseRootCharacteristic(GenPolynomial P); /** * GenPolynomial char-th root univariate polynomial with polynomial * coefficients. * @param P recursive univariate GenPolynomial. * @return char-th_rootOf(P), or null if P is no char-th root. */ public abstract GenPolynomial> recursiveUnivariateRootCharacteristic( GenPolynomial> P); /** * Polynomial is char-th root. * @param P polynomial. * @param F = [p_1 -> e_1, ..., p_k -> e_k]. * @return true if P = prod_{i=1,...,k} p_i**(e_i*p), else false. */ public boolean isCharRoot(GenPolynomial P, SortedMap, Long> F) { if (P == null || F == null) { throw new IllegalArgumentException("P and F may not be null"); } if (P.isZERO() && F.size() == 0) { return true; } GenPolynomial t = P.ring.getONE(); long p = P.ring.characteristic().longValue(); for (Map.Entry, Long> me : F.entrySet()) { GenPolynomial f = me.getKey(); Long E = me.getValue(); //F.get(f); long e = E.longValue(); GenPolynomial g = Power.> positivePower(f, e); if (!f.isConstant()) { g = Power.> positivePower(g, p); } t = t.multiply(g); } boolean f = P.equals(t) || P.equals(t.negate()); if (!f) { System.out.println("\nfactorization(map): " + f); System.out.println("P = " + P); System.out.println("t = " + t); P = P.monic(); t = t.monic(); f = P.equals(t) || P.equals(t.negate()); if (f) { return f; } System.out.println("\nfactorization(map): " + f); System.out.println("P = " + P); System.out.println("t = " + t); } return f; } /** * Recursive polynomial is char-th root. * @param P recursive polynomial. * @param F = [p_1 -> e_1, ..., p_k -> e_k]. * @return true if P = prod_{i=1,...,k} p_i**(e_i*p), else false. */ public boolean isRecursiveCharRoot(GenPolynomial> P, SortedMap>, Long> F) { if (P == null || F == null) { throw new IllegalArgumentException("P and F may not be null"); } if (P.isZERO() && F.size() == 0) { return true; } GenPolynomial> t = P.ring.getONE(); long p = P.ring.characteristic().longValue(); for (Map.Entry>, Long> me : F.entrySet()) { GenPolynomial> f = me.getKey(); Long E = me.getValue(); //F.get(f); long e = E.longValue(); GenPolynomial> g = Power.>> positivePower(f, e); if (!f.isConstant()) { g = Power.>> positivePower(g, p); } t = t.multiply(g); } boolean f = P.equals(t) || P.equals(t.negate()); if (!f) { System.out.println("\nfactorization(map): " + f); System.out.println("P = " + P); System.out.println("t = " + t); P = P.monic(); t = t.monic(); f = P.equals(t) || P.equals(t.negate()); if (f) { return f; } System.out.println("\nfactorization(map): " + f); System.out.println("P = " + P); System.out.println("t = " + t); } return f; } /** * Recursive polynomial is char-th root. * @param P recursive polynomial. * @param r = recursive polynomial. * @return true if P = r**p, else false. */ public boolean isRecursiveCharRoot(GenPolynomial> P, GenPolynomial> r) { if (P == null || r == null) { throw new IllegalArgumentException("P and r may not be null"); } if (P.isZERO() && r.isZERO()) { return true; } long p = P.ring.characteristic().longValue(); GenPolynomial> t = Power.>> positivePower(r, p); boolean f = P.equals(t) || P.equals(t.negate()); if (!f) { System.out.println("\nisCharRoot: " + f); System.out.println("P = " + P); System.out.println("t = " + t); P = P.monic(); t = t.monic(); f = P.equals(t) || P.equals(t.negate()); if (f) { return f; } System.out.println("\nisCharRoot: " + f); System.out.println("P = " + P); System.out.println("t = " + t); } return f; } } jas-2.5/src/edu/jas/ufd/Factorization.java0000644000175000017500000000743111360403164020724 0ustar giovannigiovanni/* * $Id: Factorization.java 3068 2010-04-11 17:27:16Z kredel $ */ package edu.jas.ufd; import java.io.Serializable; import java.util.List; import java.util.SortedMap; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Factorization algorithms interface. * @usage To create objects that implement the Factorization * interface use the FactorFactory. It will select an * appropriate implementation based on the types of polynomial * coefficients C. To obtain an implementation use * getImplementation(), it returns an object of a class * which extends the FactorAbstract class which implements * the Factorization interface. * *
 * Factorization<CT> engine;
 * engine = FactorFactory.<CT> getImplementation(cofac);
 * c = engine.factors(a);
 * 
* * For example, if the coefficient type is BigInteger, the usage looks * like * *
 * BigInteger cofac = new BigInteger();
 * Factorization<BigInteger> engine;
 * engine = FactorFactory.getImplementation(cofac);
 * Sm = engine.factors(poly);
 * 
* * @see edu.jas.ufd.FactorFactory#getImplementation * @author Heinz Kredel * @param coefficient type */ public interface Factorization> extends Serializable { /** * GenPolynomial test if is irreducible. * @param P GenPolynomial. * @return true if P is irreducible, else false. */ public boolean isIrreducible(GenPolynomial P); /** * GenPolynomial test if a non trivial factorization exsists. * @param P GenPolynomial. * @return true if P is reducible, else false. */ public boolean isReducible(GenPolynomial P); /** * GenPolynomial test if is squarefree. * @param P GenPolynomial. * @return true if P is squarefree, else false. */ public boolean isSquarefree(GenPolynomial P); /** * GenPolynomial factorization of a squarefree polynomial. * @param P squarefree and primitive! or monic! GenPolynomial. * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. */ public List> factorsSquarefree(GenPolynomial P); /** * GenPolynomial factorization. * @param P GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i**e_i. */ public SortedMap, Long> factors(GenPolynomial P); /** * GenPolynomial factorization ignoring multiplicities. * @param P GenPolynomial. * @return [p_1, ..., p_k] with P = prod_{i=1,...,k} p_i**{e_i} for some e_i. */ public List> factorsRadical(GenPolynomial P); /** * GenPolynomial greatest squarefree divisor. * @param P GenPolynomial. * @return squarefree(P). */ public GenPolynomial squarefreePart(GenPolynomial P); /** * GenPolynomial squarefree factorization. * @param P GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} * and p_i squarefree. */ public SortedMap, Long> squarefreeFactors(GenPolynomial P); /** * GenPolynomial is factorization. * @param P GenPolynomial * @param F = [p_1,...,p_k]. * @return true if P = prod_{i=1,...,r} p_i, else false. */ public boolean isFactorization(GenPolynomial P, List> F); /** * GenPolynomial is factorization. * @param P GenPolynomial. * @param F = [p_1 -> e_1, ..., p_k -> e_k]. * @return true if P = prod_{i=1,...,k} p_i**e_i , else false. */ public boolean isFactorization(GenPolynomial P, SortedMap, Long> F); } jas-2.5/src/edu/jas/ufd/SquarefreeFieldChar0.java0000644000175000017500000004342412014156644022043 0ustar giovannigiovanni/* * $Id: SquarefreeFieldChar0.java 4112 2012-08-19 12:35:48Z kredel $ */ package edu.jas.ufd; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Squarefree decomposition for coefficient fields of characteristic 0. * @author Heinz Kredel */ public class SquarefreeFieldChar0> extends SquarefreeAbstract { private static final Logger logger = Logger.getLogger(SquarefreeFieldChar0.class); //private final boolean debug = logger.isDebugEnabled(); /** * Factory for field of characteristic 0 coefficients. */ protected final RingFactory coFac; /** * Constructor. */ public SquarefreeFieldChar0(RingFactory fac) { super(GCDFactory. getProxy(fac)); if (!fac.isField()) { throw new IllegalArgumentException("fac must be a field"); } if (fac.characteristic().signum() != 0) { throw new IllegalArgumentException("characterisic(fac) must be zero"); } coFac = fac; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return getClass().getName() + " with " + engine + " over " + coFac; } /** * GenPolynomial polynomial greatest squarefree divisor. * @param P GenPolynomial. * @return squarefree(pp(P)). */ @Override public GenPolynomial baseSquarefreePart(GenPolynomial P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } GenPolynomial pp = P.monic(); if (pp.isConstant()) { return pp; } GenPolynomial d = PolyUtil. baseDeriviative(pp); d = d.monic(); //System.out.println("d = " + d); GenPolynomial g = engine.baseGcd(pp, d); g = g.monic(); GenPolynomial q = PolyUtil. basePseudoDivide(pp, g); q = q.monic(); return q; } /** * GenPolynomial test if is squarefree. * @param P GenPolynomial. * @return true if P is squarefree, else false. */ public boolean isBaseSquarefree(GenPolynomial P) { if (P == null || P.isZERO()) { return true; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } GenPolynomial pp = P.monic(); if (pp.isConstant()) { return true; } GenPolynomial d = PolyUtil. baseDeriviative(pp); d = d.monic(); //System.out.println("d = " + d); GenPolynomial g = engine.baseGcd(pp, d); g = g.monic(); return g.isONE(); } /** * GenPolynomial polynomial squarefree factorization. * @param A GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} * and p_i squarefree. */ @Override public SortedMap, Long> baseSquarefreeFactors(GenPolynomial A) { SortedMap, Long> sfactors = new TreeMap, Long>(); if (A == null || A.isZERO()) { return sfactors; } if (A.isConstant()) { sfactors.put(A, 1L); return sfactors; } GenPolynomialRing pfac = A.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } C ldbcf = A.leadingBaseCoefficient(); if (!ldbcf.isONE()) { A = A.divide(ldbcf); GenPolynomial f1 = pfac.getONE().multiply(ldbcf); //System.out.println("gcda sqf f1 = " + f1); sfactors.put(f1, 1L); ldbcf = pfac.coFac.getONE(); } GenPolynomial T0 = A; GenPolynomial Tp; GenPolynomial T = null; GenPolynomial V = null; long k = 0L; boolean init = true; while (true) { if (init) { if (T0.isConstant() || T0.isZERO()) { break; } Tp = PolyUtil. baseDeriviative(T0); T = engine.baseGcd(T0, Tp); T = T.monic(); V = PolyUtil. basePseudoDivide(T0, T); //System.out.println("iT0 = " + T0); //System.out.println("iTp = " + Tp); //System.out.println("iT = " + T); //System.out.println("iV = " + V); k = 0L; init = false; } if (V.isConstant()) { break; } k++; GenPolynomial W = engine.baseGcd(T, V); W = W.monic(); GenPolynomial z = PolyUtil. basePseudoDivide(V, W); //System.out.println("W = " + W); //System.out.println("z = " + z); V = W; T = PolyUtil. basePseudoDivide(T, V); //System.out.println("V = " + V); //System.out.println("T = " + T); if (z.degree(0) > 0) { if (ldbcf.isONE() && !z.leadingBaseCoefficient().isONE()) { z = z.monic(); logger.info("z,monic = " + z); } sfactors.put(z, k); } } // look, a stupid error: // if ( pfac.coFac.isField() && !ldbcf.isONE() ) { // GenPolynomial f1 = sfactors.firstKey(); // long e1 = sfactors.remove(f1); // System.out.println("gcda sqf c = " + c); // f1 = f1.multiply(c); // //System.out.println("gcda sqf f1e = " + f1); // sfactors.put(f1,e1); // } return normalizeFactorization(sfactors); } /** * GenPolynomial recursive univariate polynomial greatest squarefree * divisor. * @param P recursive univariate GenPolynomial. * @return squarefree(pp(P)). */ @Override public GenPolynomial> recursiveUnivariateSquarefreePart(GenPolynomial> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for multivariate polynomials"); } // squarefree content GenPolynomial> pp = P; GenPolynomial Pc = engine.recursiveContent(P); Pc = Pc.monic(); if (!Pc.isONE()) { pp = PolyUtil. coefficientPseudoDivide(pp, Pc); //System.out.println("pp,sqp = " + pp); //GenPolynomial Pr = squarefreePart(Pc); //Pr = Pr.monic(); //System.out.println("Pr,sqp = " + Pr); } if (pp.leadingExpVector().getVal(0) < 1) { //System.out.println("pp = " + pp); //System.out.println("Pc = " + Pc); return pp.multiply(Pc); } GenPolynomial> d = PolyUtil. recursiveDeriviative(pp); //System.out.println("d = " + d); GenPolynomial> g = engine.recursiveUnivariateGcd(pp, d); //System.out.println("g,rec = " + g); g = PolyUtil. monic(g); GenPolynomial> q = PolyUtil. recursivePseudoDivide(pp, g); q = PolyUtil. monic(q); return q.multiply(Pc); } /** * GenPolynomial test if is squarefree. * @param P GenPolynomial. * @return true if P is squarefree, else false. */ public boolean isRecursiveUnivariateSquarefree(GenPolynomial> P) { if (P == null || P.isZERO()) { return true; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for multivariate polynomials"); } // squarefree content GenPolynomial> pp = P; GenPolynomial Pc = engine.recursiveContent(P); if (logger.isInfoEnabled()) { logger.info("recursiveContent = " + Pc); } if (!isSquarefree(Pc)) { return false; } Pc = Pc.monic(); if (!Pc.isONE()) { pp = PolyUtil. coefficientPseudoDivide(pp, Pc); //System.out.println("pp,sqp = " + pp); } if (pp.leadingExpVector().getVal(0) <= 1) { //System.out.println("pp = " + pp); //System.out.println("Pc = " + Pc); return true; } GenPolynomial> d = PolyUtil. recursiveDeriviative(pp); //System.out.println("d = " + d); GenPolynomial> g = engine.recursiveUnivariateGcd(pp, d); if (logger.isInfoEnabled()) { logger.info("gcd = " + g); } //System.out.println("g,rec = " + g); g = PolyUtil. monic(g); return g.isONE(); } /** * GenPolynomial recursive univariate polynomial squarefree factorization. * @param P recursive univariate GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} * and p_i squarefree. */ @Override public SortedMap>, Long> recursiveUnivariateSquarefreeFactors( GenPolynomial> P) { SortedMap>, Long> sfactors = new TreeMap>, Long>(); if (P == null || P.isZERO()) { return sfactors; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { // recursiveContent not possible by return type throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } // if base coefficient ring is a field, make monic GenPolynomialRing cfac = (GenPolynomialRing) pfac.coFac; C ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient(); if (!ldbcf.isONE()) { GenPolynomial lc = cfac.getONE().multiply(ldbcf); GenPolynomial> pl = pfac.getONE().multiply(lc); sfactors.put(pl, 1L); C li = ldbcf.inverse(); //System.out.println("li = " + li); P = P.multiply(cfac.getONE().multiply(li)); //System.out.println("P,monic = " + P); ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient(); } // factors of content GenPolynomial Pc = engine.recursiveContent(P); if (logger.isInfoEnabled()) { logger.info("recursiveContent = " + Pc); } Pc = Pc.monic(); if (!Pc.isONE()) { P = PolyUtil. coefficientPseudoDivide(P, Pc); } SortedMap, Long> rsf = squarefreeFactors(Pc); if (logger.isInfoEnabled()) { logger.info("squarefreeFactors = " + rsf); } // add factors of content for (Map.Entry, Long> me : rsf.entrySet()) { GenPolynomial c = me.getKey(); if (!c.isONE()) { GenPolynomial> cr = pfac.getONE().multiply(c); Long rk = me.getValue(); // rsf.get(c); sfactors.put(cr, rk); } } // factors of recursive polynomial GenPolynomial> T0 = P; GenPolynomial> Tp; GenPolynomial> T = null; GenPolynomial> V = null; long k = 0L; boolean init = true; while (true) { if (init) { if (T0.isConstant() || T0.isZERO()) { break; } Tp = PolyUtil. recursiveDeriviative(T0); T = engine.recursiveUnivariateGcd(T0, Tp); T = PolyUtil. monic(T); V = PolyUtil. recursivePseudoDivide(T0, T); //System.out.println("iT0 = " + T0); //System.out.println("iTp = " + Tp); //System.out.println("iT = " + T); //System.out.println("iV = " + V); k = 0L; init = false; } if (V.isConstant()) { break; } k++; GenPolynomial> W = engine.recursiveUnivariateGcd(T, V); W = PolyUtil. monic(W); GenPolynomial> z = PolyUtil. recursivePseudoDivide(V, W); //System.out.println("W = " + W); //System.out.println("z = " + z); V = W; T = PolyUtil. recursivePseudoDivide(T, V); //System.out.println("V = " + V); //System.out.println("T = " + T); //was: if ( z.degree(0) > 0 ) { if (!z.isONE() && !z.isZERO()) { if (ldbcf.isONE()) { z = PolyUtil. monic(z); logger.info("z,monic = " + z); } sfactors.put(z, k); } } return sfactors; } /** * GenPolynomial greatest squarefree divisor. * @param P GenPolynomial. * @return squarefree(pp(P)). */ @Override public GenPolynomial squarefreePart(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return baseSquarefreePart(P); } GenPolynomialRing cfac = pfac.contract(1); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1); GenPolynomial> Pr = PolyUtil. recursive(rfac, P); GenPolynomial Pc = engine.recursiveContent(Pr); Pr = PolyUtil. coefficientPseudoDivide(Pr, Pc); GenPolynomial Ps = squarefreePart(Pc); if (logger.isInfoEnabled()) { logger.info("content = " + Pc + ", squarefreePart = " + Ps); } GenPolynomial> PP = recursiveUnivariateSquarefreePart(Pr); GenPolynomial> PS = PP.multiply(Ps); GenPolynomial D = PolyUtil. distribute(pfac, PS); if (logger.isInfoEnabled()) { logger.info("univRec = " + Pr + ", squarefreePart = " + PP); } return D; } /** * GenPolynomial test if is squarefree. * @param P GenPolynomial. * @return true if P is squarefree, else false. */ @Override public boolean isSquarefree(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return true; } GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return isBaseSquarefree(P); } GenPolynomialRing cfac = pfac.contract(1); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1); GenPolynomial> Pr = PolyUtil. recursive(rfac, P); return isRecursiveUnivariateSquarefree(Pr); } /** * GenPolynomial squarefree factorization. * @param P GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} * and p_i squarefree. */ @Override public SortedMap, Long> squarefreeFactors(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return normalizeFactorization(baseSquarefreeFactors(P)); } SortedMap, Long> sfactors = new TreeMap, Long>(); if (P.isZERO()) { return normalizeFactorization(sfactors); } GenPolynomialRing cfac = pfac.contract(1); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1); GenPolynomial> Pr = PolyUtil. recursive(rfac, P); SortedMap>, Long> PP = recursiveUnivariateSquarefreeFactors(Pr); for (Map.Entry>, Long> m : PP.entrySet()) { Long i = m.getValue(); GenPolynomial> Dr = m.getKey(); GenPolynomial D = PolyUtil. distribute(pfac, Dr); sfactors.put(D, i); } if (logger.isInfoEnabled()) { logger.info("squarefreeFactors(" + P + ") = " + sfactors); } return normalizeFactorization(sfactors); } /** * Coefficients squarefree factorization. * @param P coefficient. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} * and p_i squarefree. */ @Override public SortedMap squarefreeFactors(C P) { throw new UnsupportedOperationException("method not implemented"); } } jas-2.5/src/edu/jas/ufd/HenselMultUtil.java0000644000175000017500000015152112072075470021034 0ustar giovannigiovanni/* * $Id: HenselMultUtil.java 4355 2013-01-05 19:12:56Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLongRing; import edu.jas.arith.Modular; import edu.jas.arith.ModularRingFactory; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.ps.PolynomialTaylorFunction; import edu.jas.ps.TaylorFunction; import edu.jas.ps.UnivPowerSeries; import edu.jas.ps.UnivPowerSeriesRing; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Hensel multivariate lifting utilities. * @author Heinz Kredel */ public class HenselMultUtil { private static final Logger logger = Logger.getLogger(HenselMultUtil.class); private static final boolean debug = logger.isInfoEnabled(); /** * Modular diophantine equation solution and lifting algorithm. Let p = * A_i.ring.coFac.modul() and assume ggt(A,B) == 1 mod p. * @param A modular GenPolynomial, mod p^k * @param B modular GenPolynomial, mod p^k * @param C modular GenPolynomial, mod p^k * @param V list of substitution values, mod p^k * @param d desired approximation exponent (x_i-v_i)^d. * @param k desired approximation exponent p^k. * @return [s, t] with s A' + t B' = C mod p^k, with A' = B, B' = A. */ public static & Modular> List> liftDiophant( GenPolynomial A, GenPolynomial B, GenPolynomial C, List V, long d, long k) throws NoLiftingException { GenPolynomialRing pkfac = C.ring; if (pkfac.nvar == 1) { // V, d ignored return HenselUtil. liftDiophant(A, B, C, k); } if (!pkfac.equals(A.ring)) { throw new IllegalArgumentException("A.ring != pkfac: " + A.ring + " != " + pkfac); } // evaluate at v_n: List Vp = new ArrayList(V); MOD v = Vp.remove(Vp.size() - 1); //GenPolynomial zero = pkfac.getZERO(); // (x_n - v) GenPolynomial mon = pkfac.getONE(); GenPolynomial xv = pkfac.univariate(0, 1); xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); //System.out.println("xv = " + xv); // A(v), B(v), C(v) ModularRingFactory cf = (ModularRingFactory) pkfac.coFac; MOD vp = cf.fromInteger(v.getSymmetricInteger().getVal()); //System.out.println("v = " + v + ", vp = " + vp); GenPolynomialRing ckfac = pkfac.contract(1); GenPolynomial Ap = PolyUtil. evaluateMain(ckfac, A, vp); GenPolynomial Bp = PolyUtil. evaluateMain(ckfac, B, vp); GenPolynomial Cp = PolyUtil. evaluateMain(ckfac, C, vp); //System.out.println("Ap = " + Ap); //System.out.println("Bp = " + Bp); //System.out.println("Cp = " + Cp); // recursion: List> su = HenselMultUtil. liftDiophant(Ap, Bp, Cp, Vp, d, k); //System.out.println("su@p^" + k + " = " + su); //System.out.println("coFac = " + su.get(0).ring.coFac.toScript()); if (pkfac.nvar == 2 && !HenselUtil. isDiophantLift(Bp, Ap, su.get(0), su.get(1), Cp)) { //System.out.println("isDiophantLift: false"); throw new NoLiftingException("isDiophantLift: false"); } if (!ckfac.equals(su.get(0).ring)) { throw new IllegalArgumentException("qfac != ckfac: " + su.get(0).ring + " != " + ckfac); } GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pkfac); //GenPolynomialRing cifac = new GenPolynomialRing(new BigInteger(), ckfac); //System.out.println("ifac = " + ifac.toScript()); String[] mn = new String[] { pkfac.getVars()[pkfac.nvar - 1] }; GenPolynomialRing> qrfac = new GenPolynomialRing>(ckfac, 1, mn); //System.out.println("qrfac = " + qrfac); List> sup = new ArrayList>(su.size()); List> supi = new ArrayList>(su.size()); for (GenPolynomial s : su) { GenPolynomial sp = s.extend(pkfac, 0, 0L); sup.add(sp); GenPolynomial spi = PolyUtil.integerFromModularCoefficients(ifac, sp); supi.add(spi); } //System.out.println("sup = " + sup); //System.out.println("supi = " + supi); GenPolynomial Ai = PolyUtil.integerFromModularCoefficients(ifac, A); GenPolynomial Bi = PolyUtil.integerFromModularCoefficients(ifac, B); GenPolynomial Ci = PolyUtil.integerFromModularCoefficients(ifac, C); //System.out.println("Ai = " + Ai); //System.out.println("Bi = " + Bi); //System.out.println("Ci = " + Ci); //GenPolynomial aq = PolyUtil. fromIntegerCoefficients(pkfac, Ai); //GenPolynomial bq = PolyUtil. fromIntegerCoefficients(pkfac, Bi); //System.out.println("aq = " + aq); //System.out.println("bq = " + bq); // compute error: GenPolynomial E = Ci; // - sum_i s_i b_i E = E.subtract(Bi.multiply(supi.get(0))); E = E.subtract(Ai.multiply(supi.get(1))); //System.out.println("E = " + E); if (E.isZERO()) { logger.info("liftDiophant leaving on zero E"); return sup; } GenPolynomial Ep = PolyUtil. fromIntegerCoefficients(pkfac, E); //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); logger.info("Ep(0," + pkfac.nvar + ") = " + Ep); if (Ep.isZERO()) { logger.info("liftDiophant leaving on zero Ep mod p^k"); return sup; } for (int e = 1; e <= d; e++) { //System.out.println("\ne = " + e + " -------------------------------------- " + pkfac.nvar); GenPolynomial> Epr = PolyUtil. recursive(qrfac, Ep); //System.out.println("Epr = " + Epr); UnivPowerSeriesRing> psfac = new UnivPowerSeriesRing>(qrfac); //System.out.println("psfac = " + psfac); TaylorFunction> F = new PolynomialTaylorFunction>(Epr); //System.out.println("F = " + F); List> Vs = new ArrayList>(1); GenPolynomial vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); Vs.add(vq); //System.out.println("Vs = " + Vs); UnivPowerSeries> Epst = psfac.seriesOfTaylor(F, vq); //System.out.println("Epst = " + Epst); GenPolynomial cm = Epst.coefficient(e); //System.out.println("cm = " + cm + ", cm.ring = " + cm.ring.toScript()); // recursion: List> S = HenselMultUtil. liftDiophant(Ap, Bp, cm, Vp, d, k); //System.out.println("S = " + S); if (!ckfac.coFac.equals(S.get(0).ring.coFac)) { throw new IllegalArgumentException("ckfac != pkfac: " + ckfac.coFac + " != " + S.get(0).ring.coFac); } if (pkfac.nvar == 2 && !HenselUtil. isDiophantLift(Ap, Bp, S.get(1), S.get(0), cm)) { //System.out.println("isDiophantLift: false"); throw new NoLiftingException("isDiophantLift: false"); } mon = mon.multiply(xv); // Power.> power(pkfac,xv,e); //System.out.println("mon = " + mon); List> Sp = new ArrayList>(S.size()); int i = 0; supi = new ArrayList>(su.size()); for (GenPolynomial dd : S) { //System.out.println("dd = " + dd); GenPolynomial de = dd.extend(pkfac, 0, 0L); GenPolynomial dm = de.multiply(mon); Sp.add(dm); de = sup.get(i).sum(dm); //System.out.println("dd = " + dd); sup.set(i++, de); GenPolynomial spi = PolyUtil.integerFromModularCoefficients(ifac, dm); supi.add(spi); } //System.out.println("Sp = " + Sp); //System.out.println("sup = " + sup); //System.out.println("supi = " + supi); // compute new error //E = E; // - sum_i s_i b_i E = E.subtract(Bi.multiply(supi.get(0))); E = E.subtract(Ai.multiply(supi.get(1))); //System.out.println("E = " + E); if (E.isZERO()) { logger.info("liftDiophant leaving on zero E"); return sup; } Ep = PolyUtil. fromIntegerCoefficients(pkfac, E); //System.out.println("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); logger.info("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); if (Ep.isZERO()) { logger.info("liftDiophant leaving on zero Ep mod p^k"); return sup; } } //System.out.println("*** done: " + pkfac.nvar); return sup; } /** * Modular diophantine equation solution and lifting algorithm. Let p = * A_i.ring.coFac.modul() and assume ggt(a,b) == 1 mod p, for a, b in A. * @param A list of modular GenPolynomials, mod p^k * @param C modular GenPolynomial, mod p^k * @param V list of substitution values, mod p^k * @param d desired approximation exponent (x_i-v_i)^d. * @param k desired approximation exponent p^k. * @return [s_1,..., s_n] with sum_i s_i A_i' = C mod p^k, with Ai' = * prod_{j!=i} A_j. */ public static & Modular> List> liftDiophant( List> A, GenPolynomial C, List V, long d, long k) throws NoLiftingException { GenPolynomialRing pkfac = C.ring; if (pkfac.nvar == 1) { // V, d ignored return HenselUtil. liftDiophant(A, C, k); } if (!pkfac.equals(A.get(0).ring)) { throw new IllegalArgumentException("A.ring != pkfac: " + A.get(0).ring + " != " + pkfac); } // co-products GenPolynomial As = pkfac.getONE(); for (GenPolynomial a : A) { As = As.multiply(a); } List> Bp = new ArrayList>(A.size()); for (GenPolynomial a : A) { GenPolynomial b = PolyUtil. basePseudoDivide(As, a); Bp.add(b); } // evaluate at v_n: List Vp = new ArrayList(V); MOD v = Vp.remove(Vp.size() - 1); // (x_n - v) GenPolynomial mon = pkfac.getONE(); GenPolynomial xv = pkfac.univariate(0, 1); xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); //System.out.println("xv = " + xv); // A(v), B(v), C(v) ModularRingFactory cf = (ModularRingFactory) pkfac.coFac; MOD vp = cf.fromInteger(v.getSymmetricInteger().getVal()); //System.out.println("v = " + v + ", vp = " + vp); GenPolynomialRing ckfac = pkfac.contract(1); List> Ap = new ArrayList>(A.size()); for (GenPolynomial a : A) { GenPolynomial ap = PolyUtil. evaluateMain(ckfac, a, vp); Ap.add(ap); } GenPolynomial Cp = PolyUtil. evaluateMain(ckfac, C, vp); //System.out.println("Ap = " + Ap); //System.out.println("Cp = " + Cp); // recursion: List> su = HenselMultUtil. liftDiophant(Ap, Cp, Vp, d, k); //System.out.println("su@p^" + k + " = " + su); //System.out.println("coFac = " + su.get(0).ring.coFac.toScript()); if (pkfac.nvar == 2 && !HenselUtil. isDiophantLift(Ap, su, Cp)) { //System.out.println("isDiophantLift: false"); throw new NoLiftingException("isDiophantLift: false"); } if (!ckfac.equals(su.get(0).ring)) { throw new IllegalArgumentException("qfac != ckfac: " + su.get(0).ring + " != " + ckfac); } GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pkfac); //GenPolynomialRing cifac = new GenPolynomialRing(new BigInteger(), ckfac); //System.out.println("ifac = " + ifac.toScript()); String[] mn = new String[] { pkfac.getVars()[pkfac.nvar - 1] }; GenPolynomialRing> qrfac = new GenPolynomialRing>(ckfac, 1, mn); //System.out.println("qrfac = " + qrfac); List> sup = new ArrayList>(su.size()); List> supi = new ArrayList>(su.size()); for (GenPolynomial s : su) { GenPolynomial sp = s.extend(pkfac, 0, 0L); sup.add(sp); GenPolynomial spi = PolyUtil.integerFromModularCoefficients(ifac, sp); supi.add(spi); } //System.out.println("sup = " + sup); //System.out.println("supi = " + supi); List> Ai = new ArrayList>(A.size()); for (GenPolynomial a : A) { GenPolynomial ai = PolyUtil.integerFromModularCoefficients(ifac, a); Ai.add(ai); } List> Bi = new ArrayList>(A.size()); for (GenPolynomial b : Bp) { GenPolynomial bi = PolyUtil.integerFromModularCoefficients(ifac, b); Bi.add(bi); } GenPolynomial Ci = PolyUtil.integerFromModularCoefficients(ifac, C); //System.out.println("Ai = " + Ai); //System.out.println("Ci = " + Ci); List> Aq = new ArrayList>(A.size()); for (GenPolynomial ai : Ai) { GenPolynomial aq = PolyUtil. fromIntegerCoefficients(pkfac, ai); Aq.add(aq); } //System.out.println("Aq = " + Aq); // compute error: GenPolynomial E = Ci; // - sum_i s_i b_i int i = 0; for (GenPolynomial bi : Bi) { E = E.subtract(bi.multiply(supi.get(i++))); } //System.out.println("E = " + E); if (E.isZERO()) { logger.info("liftDiophant leaving on zero E"); return sup; } GenPolynomial Ep = PolyUtil. fromIntegerCoefficients(pkfac, E); //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); logger.info("Ep(0," + pkfac.nvar + ") = " + Ep); if (Ep.isZERO()) { logger.info("liftDiophant leaving on zero Ep mod p^k"); return sup; } for (int e = 1; e <= d; e++) { //System.out.println("\ne = " + e + " -------------------------------------- " + pkfac.nvar); GenPolynomial> Epr = PolyUtil. recursive(qrfac, Ep); //System.out.println("Epr = " + Epr); UnivPowerSeriesRing> psfac = new UnivPowerSeriesRing>(qrfac); //System.out.println("psfac = " + psfac); TaylorFunction> F = new PolynomialTaylorFunction>(Epr); //System.out.println("F = " + F); List> Vs = new ArrayList>(1); GenPolynomial vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); Vs.add(vq); //System.out.println("Vs = " + Vs); UnivPowerSeries> Epst = psfac.seriesOfTaylor(F, vq); //System.out.println("Epst = " + Epst); GenPolynomial cm = Epst.coefficient(e); //System.out.println("cm = " + cm + ", cm.ring = " + cm.ring.toScript()); if (cm.isZERO()) { continue; } // recursion: List> S = HenselMultUtil. liftDiophant(Ap, cm, Vp, d, k); //System.out.println("S = " + S); if (!ckfac.coFac.equals(S.get(0).ring.coFac)) { throw new IllegalArgumentException("ckfac != pkfac: " + ckfac.coFac + " != " + S.get(0).ring.coFac); } if (pkfac.nvar == 2 && !HenselUtil. isDiophantLift(Ap, S, cm)) { //System.out.println("isDiophantLift: false"); throw new NoLiftingException("isDiophantLift: false"); } mon = mon.multiply(xv); // Power.> power(pkfac,xv,e); //System.out.println("mon = " + mon); List> Sp = new ArrayList>(S.size()); i = 0; supi = new ArrayList>(su.size()); for (GenPolynomial dd : S) { //System.out.println("dd = " + dd); GenPolynomial de = dd.extend(pkfac, 0, 0L); GenPolynomial dm = de.multiply(mon); Sp.add(dm); de = sup.get(i).sum(dm); //System.out.println("dd = " + dd); sup.set(i++, de); GenPolynomial spi = PolyUtil.integerFromModularCoefficients(ifac, dm); supi.add(spi); } //System.out.println("Sp = " + Sp); //System.out.println("sup = " + sup); //System.out.println("supi = " + supi); // compute new error //E = E; // - sum_i s_i b_i i = 0; for (GenPolynomial bi : Bi) { E = E.subtract(bi.multiply(supi.get(i++))); } //System.out.println("E = " + E); if (E.isZERO()) { logger.info("liftDiophant leaving on zero E"); return sup; } Ep = PolyUtil. fromIntegerCoefficients(pkfac, E); //System.out.println("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); logger.info("Ep(" + e + "," + pkfac.nvar + ") = " + Ep); if (Ep.isZERO()) { logger.info("liftDiophant leaving on zero Ep mod p^k"); return sup; } } //System.out.println("*** done: " + pkfac.nvar); return sup; } /** * Modular Hensel lifting algorithm on coefficients test. Let p = * f_i.ring.coFac.modul() and assume C == prod_{0,...,n-1} f_i mod p with * gcd(f_i,f_j) == 1 mod p for i != j * @param C integer polynomial * @param Cp GenPolynomial mod p^k * @param F = [f_0,...,f_{n-1}] list of monic modular polynomials. * @param k approximation exponent. * @param L = [g_0,...,g_{n-1}] list of lifted modular polynomials. * @return true if C = prod_{0,...,n-1} g_i mod p^k, else false. * @deprecated use isHenselLift() without parameter k */ @Deprecated public static & Modular> boolean isHenselLift(GenPolynomial C, GenPolynomial Cp, List> F, long k, List> L) { return isHenselLift(C,Cp,F,L); } /** * Modular Hensel lifting algorithm on coefficients test. Let p = * f_i.ring.coFac.modul() and assume C == prod_{0,...,n-1} f_i mod p with * gcd(f_i,f_j) == 1 mod p for i != j * @param C integer polynomial * @param Cp GenPolynomial mod p^k * @param F = [f_0,...,f_{n-1}] list of monic modular polynomials. * @param L = [g_0,...,g_{n-1}] list of lifted modular polynomials. * @return true if C = prod_{0,...,n-1} g_i mod p^k, else false. */ public static & Modular> boolean isHenselLift(GenPolynomial C, GenPolynomial Cp, List> F, List> L) { boolean t = true; GenPolynomialRing qfac = L.get(0).ring; GenPolynomial q = qfac.getONE(); for (GenPolynomial fi : L) { q = q.multiply(fi); } t = Cp.equals(q); if (!t) { System.out.println("Cp = " + Cp); System.out.println("q = " + q); System.out.println("Cp != q: " + Cp.subtract(q)); return t; } GenPolynomialRing dfac = C.ring; GenPolynomial Ci = PolyUtil.integerFromModularCoefficients(dfac, q); t = C.equals(Ci); if (!t) { System.out.println("C = " + C); System.out.println("Ci = " + Ci); System.out.println("C != Ci: " + C.subtract(Ci)); return t; } // test L mod id(V) == F return t; } /** * Modular Hensel lifting algorithm, monic case. Let p = * A_i.ring.coFac.modul() and assume ggt(a,b) == 1 mod p, for a, b in A. * @param C monic GenPolynomial with integer coefficients * @param Cp GenPolynomial mod p^k * @param F list of modular GenPolynomials, mod (I_v, p^k ) * @param V list of integer substitution values * @param k desired approximation exponent p^k. * @return [g'_1,..., g'_n] with prod_i g'_i = Cp mod p^k. */ public static & Modular> List> liftHenselMonic( GenPolynomial C, GenPolynomial Cp, List> F, List V, long k) throws NoLiftingException { GenPolynomialRing pkfac = Cp.ring; //if (pkfac.nvar == 1) { // V ignored // return HenselUtil. liftHenselMonic(C,F,k); //} long d = C.degree(); //System.out.println("d = " + d); // prepare stack of polynomial rings and polynomials List> Pfac = new ArrayList>(); List> Ap = new ArrayList>(); List Vb = new ArrayList(); MOD v = pkfac.coFac.fromInteger( V.get(0).getVal() ); Pfac.add(pkfac); Ap.add(Cp); Vb.add(v); GenPolynomialRing pf = pkfac; GenPolynomial ap = Cp; for (int j = pkfac.nvar; j > 2; j--) { pf = pf.contract(1); Pfac.add(0, pf); //MOD vp = pkfac.coFac.fromInteger(V.get(j - 2).getSymmetricInteger().getVal()); MOD vp = pkfac.coFac.fromInteger(V.get(j - 2).getVal()); //System.out.println("vp = " + vp); Vb.add(1, vp); ap = PolyUtil. evaluateMain(pf, ap, vp); Ap.add(0, ap); } //System.out.println("Pfac = " + Pfac); if (debug) { logger.debug("Pfac = " + Pfac); } //System.out.println("Ap = " + Ap); //System.out.println("V = " + V); //System.out.println("Vb = " + Vb); // setup bi-variate base case GenPolynomialRing pk1fac = F.get(0).ring; if (!pkfac.coFac.equals(pk1fac.coFac)) { throw new IllegalArgumentException("F.ring != pkfac: " + pk1fac + " != " + pkfac); } // TODO: adjust leading coefficients pkfac = Pfac.get(0); //Cp = Ap.get(0); //System.out.println("pkfac = " + pkfac.toScript()); //System.out.println("pk1fac = " + pk1fac.toScript()); GenPolynomialRing i1fac = new GenPolynomialRing(new BigInteger(), pk1fac); //System.out.println("i1fac = " + i1fac.toScript()); List> Bi = new ArrayList>(F.size()); for (GenPolynomial b : F) { GenPolynomial bi = PolyUtil.integerFromModularCoefficients(i1fac, b); Bi.add(bi); } //System.out.println("Bi = " + Bi); // evaluate Cp at v_n: //ModularRingFactory cf = (ModularRingFactory) pkfac.coFac; //MOD vp = cf.fromInteger(v.getSymmetricInteger().getVal()); //System.out.println("v = " + v + ", vp = " + vp); GenPolynomialRing ckfac; // = pkfac.contract(1); //GenPolynomial Cs = PolyUtil. evaluateMain(ckfac, Cp, vp); //System.out.println("Cp = " + Cp); //System.out.println("Cs = " + Cs); List> U = new ArrayList>(F.size()); for (GenPolynomial b : F) { GenPolynomial bi = b.extend(pkfac, 0, 0L); U.add(bi); } //System.out.println("U = " + U); List> U1 = F; //System.out.println("U1 = " + U1); GenPolynomial E = C.ring.getZERO(); List Vh = new ArrayList(); while (Pfac.size() > 0) { // loop through stack of polynomial rings pkfac = Pfac.remove(0); Cp = Ap.remove(0); v = Vb.remove(0); //Vh.add(0,v); //System.out.println("\npkfac = " + pkfac.toScript() + " ================================== " + Vh); // (x_n - v) GenPolynomial mon = pkfac.getONE(); GenPolynomial xv = pkfac.univariate(0, 1); xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); //System.out.println("xv = " + xv); long deg = Cp.degree(pkfac.nvar - 1); //System.out.println("deg = " + deg); GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pkfac); //System.out.println("ifac = " + ifac.toScript()); List> Bip = new ArrayList>(F.size()); for (GenPolynomial b : Bi) { GenPolynomial bi = b.extend(ifac, 0, 0L); Bip.add(bi); } Bi = Bip; //System.out.println("Bi = " + Bi); GenPolynomial Ci = PolyUtil.integerFromModularCoefficients(ifac, Cp); //System.out.println("Ci = " + Ci); // compute error: E = ifac.getONE(); for (GenPolynomial bi : Bi) { E = E.multiply(bi); } E = Ci.subtract(E); //System.out.println("E = " + E); GenPolynomial Ep = PolyUtil. fromIntegerCoefficients(pkfac, E); //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); logger.info("Ep(0," + deg + "," + pkfac.nvar + ") = " + Ep); String[] mn = new String[] { pkfac.getVars()[pkfac.nvar - 1] }; ckfac = pkfac.contract(1); GenPolynomialRing> pkrfac = new GenPolynomialRing>(ckfac, 1, mn); //System.out.println("pkrfac = " + pkrfac.toScript()); for (int e = 1; e <= deg && !Ep.isZERO(); e++) { //System.out.println("\ne = " + e + " -------------------------------------- " + pkfac.nvar); GenPolynomial> Epr = PolyUtil. recursive(pkrfac, Ep); //System.out.println("Epr = " + Epr); UnivPowerSeriesRing> psfac = new UnivPowerSeriesRing>( pkrfac); //System.out.println("psfac = " + psfac); TaylorFunction> T = new PolynomialTaylorFunction>(Epr); //System.out.println("T = " + T); List> Vs = new ArrayList>(1); GenPolynomial vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); Vs.add(vq); //System.out.println("Vs = " + Vs + ", Vh = " + Vh); UnivPowerSeries> Epst = psfac.seriesOfTaylor(T, vq); //System.out.println("Epst = " + Epst); logger.info("Epst(" + e + "," + deg + ", " + pkfac.nvar + ") = " + Epst); GenPolynomial cm = Epst.coefficient(e); //System.out.println("cm = " + cm); if (cm.isZERO()) { continue; } List> Ud = HenselMultUtil. liftDiophant(U1, cm, Vh, d, k); //System.out.println("Ud = " + Ud); mon = mon.multiply(xv); // Power.> power(pkfac,xv,e); //System.out.println("mon = " + mon); List> Sd = new ArrayList>(Ud.size()); int i = 0; List> Si = new ArrayList>(Ud.size()); for (GenPolynomial dd : Ud) { //System.out.println("dd = " + dd); GenPolynomial de = dd.extend(pkfac, 0, 0L); GenPolynomial dm = de.multiply(mon); Sd.add(dm); de = U.get(i).sum(dm); //System.out.println("de = " + de); U.set(i++, de); GenPolynomial si = PolyUtil.integerFromModularCoefficients(ifac, de); Si.add(si); } //System.out.println("Sd = " + Sd); //System.out.println("U = " + U); //System.out.println("Si = " + Si); // compute new error: E = ifac.getONE(); for (GenPolynomial bi : Si) { E = E.multiply(bi); } E = Ci.subtract(E); //System.out.println("E = " + E); Ep = PolyUtil. fromIntegerCoefficients(pkfac, E); //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); logger.info("Ep(" + e + "," + deg + "," + pkfac.nvar + ") = " + Ep); } Vh.add(v); U1 = U; if (Pfac.size() > 0) { List> U2 = new ArrayList>(U.size()); pkfac = Pfac.get(0); for (GenPolynomial b : U) { GenPolynomial bi = b.extend(pkfac, 0, 0L); U2.add(bi); } U = U2; //System.out.println("U = " + U); } } if (E.isZERO()) { logger.info("liftHensel leaving with zero E"); } return U; } /** * Modular Hensel lifting algorithm. Let p = A_i.ring.coFac.modul() and * assume ggt(a,b) == 1 mod p, for a, b in A. * @param C GenPolynomial with integer coefficients * @param Cp GenPolynomial C mod p^k * @param F list of modular GenPolynomials, mod (I_v, p^k ) * @param V list of integral substitution values * @param k desired approximation exponent p^k. * @param G list of leading coefficients of the factors of C. * @return [g'_1,..., g'_n] with prod_i g'_i = Cp mod p^k. */ public static & Modular> List> liftHensel( GenPolynomial C, GenPolynomial Cp, List> F, List V, long k, List> G) throws NoLiftingException { GenPolynomialRing pkfac = Cp.ring; long d = C.degree(); //System.out.println("C = " + C); //System.out.println("Cp = " + Cp); //System.out.println("G = " + G); //GenPolynomial cd = G.get(0); // 1 //System.out.println("cd = " + cd + ", ring = " + C.ring); //if ( cd.equals(C.ring.univariate(0)) ) { // System.out.println("cd == G[1]"); //} // G mod p^k, in all variables GenPolynomialRing pkfac1 = new GenPolynomialRing(pkfac.coFac, G.get(0).ring); List> Lp = new ArrayList>(G.size()); for (GenPolynomial cd1 : G) { GenPolynomial cdq = PolyUtil. fromIntegerCoefficients(pkfac1, cd1); cdq = cdq.extendLower(pkfac, 0, 0L); // reintroduce lower variable Lp.add(cdq); } logger.info("G modulo p^k: " + Lp); // + ", ring = " + pkfac1); // prepare stack of polynomial rings, polynomials and evaluated leading coefficients List> Pfac = new ArrayList>(); List> Ap = new ArrayList>(); List>> Gp = new ArrayList>>(); List Vb = new ArrayList(); //MOD v = V.get(0); // fromInteger Pfac.add(pkfac); Ap.add(Cp); Gp.add(Lp); GenPolynomialRing pf = pkfac; //GenPolynomialRing pf1 = pkfac1; GenPolynomial ap = Cp; List> Lpp = Lp; for (int j = pkfac.nvar; j > 2; j--) { pf = pf.contract(1); Pfac.add(0, pf); //MOD vp = pkfac.coFac.fromInteger(V.get(pkfac.nvar - j).getSymmetricInteger().getVal()); MOD vp = pkfac.coFac.fromInteger(V.get(pkfac.nvar - j).getVal()); //System.out.println("vp = " + vp); Vb.add(vp); ap = PolyUtil. evaluateMain(pf, ap, vp); Ap.add(0, ap); List> Lps = new ArrayList>(Lpp.size()); for (GenPolynomial qp : Lpp) { GenPolynomial qpe = PolyUtil. evaluateMain(pf, qp, vp); Lps.add(qpe); } //System.out.println("Lps = " + Lps); Lpp = Lps; Gp.add(0, Lpp); } Vb.add( pkfac.coFac.fromInteger( V.get(pkfac.nvar - 2).getVal() ) ); //System.out.println("Pfac = " + Pfac); if (debug) { logger.debug("Pfac = " + Pfac); } //System.out.println("Ap = " + Ap); //System.out.println("Gp = " + Gp); //System.out.println("Gp[0] = " + Gp.get(0) + ", Gp[0].ring = " + Gp.get(0).get(0).ring); //System.out.println("V = " + V); //System.out.println("Vb = " + Vb + ", V == Vb: " + V.equals(Vb)); // check bi-variate base case GenPolynomialRing pk1fac = F.get(0).ring; if (!pkfac.coFac.equals(pk1fac.coFac)) { throw new IllegalArgumentException("F.ring != pkfac: " + pk1fac + " != " + pkfac); } // init recursion List> U = F; //logger.info("to lift U = " + U); // + ", U1.ring = " + U1.get(0).ring); GenPolynomial E = C.ring.getZERO(); List Vh = new ArrayList(); List> Si; // = new ArrayList>(F.size()); MOD v = null; while (Pfac.size() > 0) { // loop through stack of polynomial rings pkfac = Pfac.remove(0); Cp = Ap.remove(0); Lpp = Gp.remove(0); v = Vb.remove(Vb.size() - 1); // last in stack //System.out.println("\npkfac = " + pkfac.toScript() + " ================================== " + v); logger.info("stack loop: pkfac = " + pkfac.toScript() + " v = " + v); List> U1 = U; logger.info("to lift U1 = " + U1); // + ", U1.ring = " + U1.get(0).ring); U = new ArrayList>(U1.size()); // update U, replace leading coefficient if required int j = 0; for (GenPolynomial b : U1) { //System.out.println("b = " + b + ", b.ring = " + b.ring); GenPolynomial bi = b.extend(pkfac, 0, 0L); GenPolynomial li = Lpp.get(j); if (!li.isONE()) { //System.out.println("li = " + li + ", li.ring = " + li.ring); //System.out.println("bi = " + bi); GenPolynomialRing> pkrfac = pkfac.recursive(pkfac.nvar - 1); //System.out.println("pkrfac = " + pkrfac); GenPolynomial> br = PolyUtil. recursive(pkrfac, bi); //System.out.println("br = " + br); GenPolynomial> bs = PolyUtil. switchVariables(br); //System.out.println("bs = " + bs + ", bs.ring = " + bs.ring); GenPolynomial> lr = PolyUtil. recursive(pkrfac, li); //System.out.println("lr = " + lr); GenPolynomial> ls = PolyUtil. switchVariables(lr); //System.out.println("ls = " + ls + ", ls.ring = " + ls.ring); if (!ls.isConstant() && !ls.isZERO()) { throw new RuntimeException("ls not constant " + ls + ", li = " + li); } bs.doPutToMap(bs.leadingExpVector(), ls.leadingBaseCoefficient()); //System.out.println("bs = " + bs + ", bs.ring = " + bs.ring); br = PolyUtil. switchVariables(bs); //System.out.println("br = " + br); bi = PolyUtil. distribute(pkfac, br); //System.out.println("bi = " + bi); } U.add(bi); j++; } logger.info("U with leading coefficient replaced = " + U); // + ", U.ring = " + U.get(0).ring); // (x_n - v) GenPolynomial mon = pkfac.getONE(); GenPolynomial xv = pkfac.univariate(0, 1); xv = xv.subtract(pkfac.fromInteger(v.getSymmetricInteger().getVal())); //System.out.println("xv = " + xv); long deg = Cp.degree(pkfac.nvar - 1); //System.out.println("deg = " + deg + ", degv = " + Cp.degreeVector()); // convert to integer polynomials GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pkfac); //System.out.println("ifac = " + ifac.toScript()); List> Bi = PolyUtil.integerFromModularCoefficients(ifac, U); //System.out.println("Bi = " + Bi); GenPolynomial Ci = PolyUtil.integerFromModularCoefficients(ifac, Cp); //System.out.println("Ci = " + Ci); // compute error: E = ifac.getONE(); for (GenPolynomial bi : Bi) { E = E.multiply(bi); } //System.out.println("E = " + E); E = Ci.subtract(E); //System.out.println("E = " + E); GenPolynomial Ep = PolyUtil. fromIntegerCoefficients(pkfac, E); logger.info("Ep(0," + deg + "," + pkfac.nvar + ") = " + Ep); GenPolynomialRing> pkrfac = pkfac.recursive(1); GenPolynomialRing ckfac = (GenPolynomialRing) pkrfac.coFac; //System.out.println("pkrfac = " + pkrfac.toScript()); for (int e = 1; e <= deg && !Ep.isZERO(); e++) { //System.out.println("\ne = " + e + " -------------------------------------- " + deg); logger.info("approximation loop: e = " + e + " of deg = " + deg); GenPolynomial> Epr = PolyUtil. recursive(pkrfac, Ep); //System.out.println("Epr = " + Epr); UnivPowerSeriesRing> psfac = new UnivPowerSeriesRing>( pkrfac); //System.out.println("psfac = " + psfac); TaylorFunction> T = new PolynomialTaylorFunction>(Epr); //System.out.println("T = " + T); GenPolynomial vq = ckfac.fromInteger(v.getSymmetricInteger().getVal()); //System.out.println("vq = " + vq + ", Vh = " + Vh); UnivPowerSeries> Epst = psfac.seriesOfTaylor(T, vq); //System.out.println("Epst = " + Epst); logger.info("Epst(" + e + "," + deg + "," + pkfac.nvar + ") = " + Epst); GenPolynomial cm = Epst.coefficient(e); if (cm.isZERO()) { //System.out.println("cm = " + cm); continue; } List> Ud = HenselMultUtil. liftDiophant(U1, cm, Vh, d, k); //System.out.println("Ud = " + Ud); mon = mon.multiply(xv); // Power.> power(pkfac,xv,e); //System.out.println("mon = " + mon); List> Sd = new ArrayList>(Ud.size()); int i = 0; Si = new ArrayList>(Ud.size()); for (GenPolynomial dd : Ud) { //System.out.println("dd = " + dd); GenPolynomial de = dd.extend(pkfac, 0, 0L); GenPolynomial dm = de.multiply(mon); Sd.add(dm); de = U.get(i).sum(dm); //System.out.println("de = " + de); U.set(i++, de); GenPolynomial si = PolyUtil.integerFromModularCoefficients(ifac, de); Si.add(si); } //System.out.println("Sd = " + Sd); //System.out.println("U = " + U + ", U.ring = " + U.get(0).ring); //System.out.println("Si = " + Si); // compute new error: E = ifac.getONE(); for (GenPolynomial bi : Si) { E = E.multiply(bi); } E = Ci.subtract(E); //System.out.println("E = " + E); Ep = PolyUtil. fromIntegerCoefficients(pkfac, E); //System.out.println("Ep(0," + pkfac.nvar + ") = " + Ep); logger.info("Ep(" + e + "," + deg + "," + pkfac.nvar + ") = " + Ep); } Vh.add(v); GenPolynomial Uf = U.get(0).ring.getONE(); for (GenPolynomial Upp : U) { Uf = Uf.multiply(Upp); } if (false && !Cp.leadingExpVector().equals(Uf.leadingExpVector())) { // not meanigfull test System.out.println("\nU = " + U); System.out.println("Cp = " + Cp); System.out.println("Uf = " + Uf); //System.out.println("Cp.ring = " + Cp.ring.toScript() + ", Uf.ring = " + Uf.ring.toScript() + "\n"); System.out.println(""); //throw new NoLiftingException("no factorization, Cp != Uf"); } } if (E.isZERO()) { logger.info("liftHensel leaving with zero E, Ep"); } if (false && debug) { // remove normalization required ?? GreatestCommonDivisorAbstract ufd = GCDFactory.getImplementation(new BigInteger()); List> Fii = new ArrayList>(U.size()); for (GenPolynomial bi : Si) { GenPolynomial ci = ufd.content(bi); //ufd.primitivePart(bi); // ?? if (!ci.isONE()) { System.out.println("bi = " + bi + ", cont(bi) = " + ci); } //Fii.add(ci); } //Si = Fii; //System.out.println("Si = " + Si); } logger.info("multivariate lift: U = " + U + ", of " + F); return U; } /** * Modular Hensel full lifting algorithm. Let p = A_i.ring.coFac.modul() and * assume ggt(a,b) == 1 mod p, for a, b in A. * @param C GenPolynomial with integer coefficients * @param F list of modular GenPolynomials, mod (I_v, p ) * @param V list of integer substitution values * @param k desired approximation exponent p^k. * @param G = [g_1,...,g_n] list of factors of leading coefficients. * @return [c_1,..., c_n] with prod_i c_i = C mod p^k. */ public static & Modular> List> liftHenselFull( GenPolynomial C, List> F, List V, long k, List> G) throws NoLiftingException { if (F == null || F.size() == 0) { return new ArrayList>(); } GenPolynomialRing pkfac = F.get(0).ring; //long d = C.degree(); // setup q = p^k RingFactory cfac = pkfac.coFac; ModularRingFactory pcfac = (ModularRingFactory) cfac; //System.out.println("pcfac = " + pcfac); BigInteger p = pcfac.getIntegerModul(); BigInteger q = Power.positivePower(p, k); ModularRingFactory mcfac; if (ModLongRing.MAX_LONG.compareTo(q.getVal()) > 0) { mcfac = (ModularRingFactory) new ModLongRing(q.getVal()); } else { mcfac = (ModularRingFactory) new ModIntegerRing(q.getVal()); } //System.out.println("mcfac = " + mcfac); // convert C from Z[...] to Z_q[...] GenPolynomialRing qcfac = new GenPolynomialRing(mcfac, C.ring); GenPolynomial Cq = PolyUtil. fromIntegerCoefficients(qcfac, C); //System.out.println("C = " + C); //System.out.println("Cq = " + Cq); // convert g_i from Z[...] to Z_q[...] GenPolynomialRing gcfac = new GenPolynomialRing(mcfac, G.get(0).ring); List> GQ = new ArrayList>(); boolean allOnes = true; for (GenPolynomial g : G) { if (!g.isONE()) { allOnes = false; } GenPolynomial gq = PolyUtil. fromIntegerCoefficients(gcfac, g); GQ.add(gq); } //System.out.println("G = " + G); //System.out.println("GQ = " + GQ); // evaluate C to Z_q[x] GenPolynomialRing pf = qcfac; GenPolynomial ap = Cq; for (int j = C.ring.nvar; j > 1; j--) { pf = pf.contract(1); //MOD vp = mcfac.fromInteger(V.get(C.ring.nvar - j).getSymmetricInteger().getVal()); MOD vp = mcfac.fromInteger(V.get(C.ring.nvar - j).getVal()); //System.out.println("vp = " + vp); ap = PolyUtil. evaluateMain(pf, ap, vp); //System.out.println("ap = " + ap); } GenPolynomial Cq1 = ap; //System.out.println("Cq1 = " + Cq1); if (Cq1.isZERO()) { throw new NoLiftingException("C mod (I, p^k) == 0: " + C); } GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), pf); GenPolynomial Ci = PolyUtil.integerFromModularCoefficients(ifac, Cq1); //System.out.println("Ci = " + Ci); GreatestCommonDivisorAbstract ufd = GCDFactory.getImplementation(new BigInteger()); Ci = Ci.abs(); BigInteger cCi = ufd.baseContent(Ci); Ci = Ci.divide(cCi); //System.out.println("cCi = " + cCi); //System.out.println("Ci = " + Ci); ////System.out.println("F.fac = " + F.get(0).ring); // evaluate G to Z_q List> GP = new ArrayList>(); for (GenPolynomial gq : GQ) { GenPolynomialRing gf = gcfac; GenPolynomial gp = gq; for (int j = gcfac.nvar; j > 1; j--) { gf = gf.contract(1); //MOD vp = mcfac.fromInteger(V.get(gcfac.nvar - j).getSymmetricInteger().getVal()); MOD vp = mcfac.fromInteger(V.get(gcfac.nvar - j).getVal()); //System.out.println("vp = " + vp); gp = PolyUtil. evaluateMain(gf, gp, vp); //System.out.println("gp = " + gp); } GP.add(gp); } //System.out.println("GP = " + GP); // + ", GP.ring = " + GP.get(0).ring); // leading coefficient for recursion base, for Cq1 and list GP BigInteger gi0 = Ci.leadingBaseCoefficient(); // gq0.getSymmetricInteger(); //System.out.println("gi0 = " + gi0); // lift F to Z_{p^k}[x] //System.out.println("Ci = " + Ci + ", F = " + F + ", k = " + k + ", p = " + F.get(0).ring + ", gi0 = " + gi0); List> U1 = null; if (gi0.isONE()) { U1 = HenselUtil. liftHenselMonic(Ci, F, k); } else { U1 = HenselUtil. liftHensel(Ci, F, k, gi0); // GI0 TODO ?? } logger.info("univariate lift: Ci = " + Ci + ", F = " + F + ", U1 = " + U1); //System.out.println("U1.fac = " + U1.get(0).ring); // adjust leading coefficients of U1 with F List> U1i = PolyUtil. integerFromModularCoefficients(Ci.ring, U1); //System.out.println("U1i = " + U1i); boolean t = HenselUtil.isHenselLift(Ci, q, p, U1i); //System.out.println("isLift(U1) = " + t); if (!t) { //System.out.println("NoLiftingException, Ci = " + Ci + ", U1i = " + U1i); throw new NoLiftingException("Ci = " + Ci + ", U1i = " + U1i); } MOD cC = mcfac.fromInteger(cCi.getVal()); List> U1f = PolyUtil. fromIntegerCoefficients(F.get(0).ring, U1i); //System.out.println("U1f = " + U1f); List> U1s = new ArrayList>(U1.size()); int j = 0; int s = 0; for (GenPolynomial u : U1) { GenPolynomial uf = U1f.get(j); GenPolynomial f = F.get(j); GenPolynomial ui = U1i.get(j); GenPolynomial gi = G.get(j); if (ui.signum() != gi.signum()) { //System.out.println("ui = " + ui + ", gi = " + gi); u = u.negate(); uf = uf.negate(); s++; } j++; if (uf.isConstant()) { //System.out.println("u = " + u); u = u.monic(); //System.out.println("u = " + u); u = u.multiply(cC); cC = cC.divide(cC); //System.out.println("u = " + u); } else { MOD x = f.leadingBaseCoefficient().divide(uf.leadingBaseCoefficient()); //System.out.println("x = " + x + ", xi = " + x.getSymmetricInteger()); if (!x.isONE()) { MOD xq = mcfac.fromInteger(x.getSymmetricInteger().getVal()); //System.out.println("xq = " + xq); u = u.multiply(xq); cC = cC.divide(xq); //System.out.println("cC = " + cC); } } U1s.add(u); } //if ( s % 2 != 0 || !cC.isONE()) { if (!cC.isONE()) { throw new NoLiftingException("s = " + s + ", Ci = " + Ci + ", U1i = " + U1i + ", cC = " + cC); } U1 = U1s; U1i = PolyUtil. integerFromModularCoefficients(Ci.ring, U1); //System.out.println("U1i = " + U1i); U1f = PolyUtil. fromIntegerCoefficients(F.get(0).ring, U1i); if (!F.equals(U1f)) { // evtl loop until reached System.out.println("F = " + F); System.out.println("U1f = " + U1f); throw new NoLiftingException("F = " + F + ", U1f = " + U1f); } logger.info("multivariate lift: U1 = " + U1); // lift U to Z_{p^k}[x,...] //System.out.println("C = " + C + ", U1 = " + U1 + ", V = " + V + ", k = " + k + ", q = " + U1.get(0).ring + ", G = " + G); List> U = null; if (allOnes) { U = HenselMultUtil. liftHenselMonic(C, Cq, U1, V, k); } else { U = HenselMultUtil. liftHensel(C, Cq, U1, V, k, G); } logger.info("multivariate lift: C = " + C + ", U1 = " + U1 + ", U = " + U); //System.out.println("U = " + U); //System.out.println("U.fac = " + U.get(0).ring); return U; } } jas-2.5/src/edu/jas/ufd/GCDFactory.java0000644000175000017500000002440311677665254020060 0ustar giovannigiovanni/* * $Id: GCDFactory.java 3852 2011-12-31 20:03:57Z kredel $ */ package edu.jas.ufd; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLong; import edu.jas.arith.ModLongRing; import edu.jas.kern.ComputerThreads; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Greatest common divisor algorithms factory. Select appropriate GCD engine * based on the coefficient types. * @todo Base decision also an degree vectors and number of variables of * polynomials. Incorporate also number of CPUs / threads available (done * with GCDProxy). * @author Heinz Kredel * @usage To create objects that implement the * GreatestCommonDivisor interface use the * GCDFactory. It will select an appropriate implementation * based on the types of polynomial coefficients C. There are two methods * to obtain an implementation: getProxy() and * getImplementation(). getImplementation() * returns an object of a class which implements the * GreatestCommonDivisor interface. getProxy() * returns a proxy object of a class which implements the * GreatestCommonDivisorr interface. The proxy will run two * implementations in parallel, return the first computed result and * cancel the second running task. On systems with one CPU the computing * time will be two times the time of the fastest algorithm * implmentation. On systems with more than two CPUs the computing time * will be the time of the fastest algorithm implmentation. * *
 * GreatestCommonDivisor<CT> engine;
 * engine = GCDFactory.<CT> getImplementation(cofac);
 * or engine = GCDFactory.<CT> getProxy(cofac);
 * c = engine.gcd(a, b);
 * 
* * For example, if the coefficient type is BigInteger, the usage looks * like * *
 * BigInteger cofac = new BigInteger();
 * GreatestCommonDivisor<BigInteger> engine;
 * engine = GCDFactory.getImplementation(cofac);
 * or engine = GCDFactory.getProxy(cofac);
 * c = engine.gcd(a, b);
 * 
* * @see edu.jas.ufd.GreatestCommonDivisor#gcd(edu.jas.poly.GenPolynomial P, * edu.jas.poly.GenPolynomial S) */ public class GCDFactory { private static final Logger logger = Logger.getLogger(GCDFactory.class); /** * Protected factory constructor. */ protected GCDFactory() { } /** * Determine suitable implementation of gcd algorithms, case ModLong. * @param fac ModLongRing. * @return gcd algorithm implementation. */ public static GreatestCommonDivisorAbstract getImplementation(ModLongRing fac) { GreatestCommonDivisorAbstract ufd; if (fac.isField()) { ufd = new GreatestCommonDivisorModEval(); return ufd; } ufd = new GreatestCommonDivisorSubres(); return ufd; } /** * Determine suitable proxy for gcd algorithms, case ModLong. * @param fac ModLongRing. * @return gcd algorithm implementation. */ public static GreatestCommonDivisorAbstract getProxy(ModLongRing fac) { GreatestCommonDivisorAbstract ufd1, ufd2; ufd1 = new GreatestCommonDivisorSubres(); if (fac.isField()) { ufd2 = new GreatestCommonDivisorModEval(); } else { ufd2 = new GreatestCommonDivisorSimple(); } return new GCDProxy(ufd1, ufd2); } /** * Determine suitable implementation of gcd algorithms, case ModInteger. * @param fac ModIntegerRing. * @return gcd algorithm implementation. */ public static GreatestCommonDivisorAbstract getImplementation(ModIntegerRing fac) { GreatestCommonDivisorAbstract ufd; if (fac.isField()) { ufd = new GreatestCommonDivisorModEval(); return ufd; } ufd = new GreatestCommonDivisorSubres(); return ufd; } /** * Determine suitable proxy for gcd algorithms, case ModInteger. * @param fac ModIntegerRing. * @return gcd algorithm implementation. */ public static GreatestCommonDivisorAbstract getProxy(ModIntegerRing fac) { GreatestCommonDivisorAbstract ufd1, ufd2; ufd1 = new GreatestCommonDivisorSubres(); if (fac.isField()) { ufd2 = new GreatestCommonDivisorModEval(); } else { ufd2 = new GreatestCommonDivisorSimple(); } return new GCDProxy(ufd1, ufd2); } /** * Determine suitable implementation of gcd algorithms, case BigInteger. * @param fac BigInteger. * @return gcd algorithm implementation. */ public static GreatestCommonDivisorAbstract getImplementation(BigInteger fac) { GreatestCommonDivisorAbstract ufd; if (true) { ufd = new GreatestCommonDivisorModular(); // dummy type } else { ufd = new GreatestCommonDivisorSubres(); } return ufd; } /** * Determine suitable procy for gcd algorithms, case BigInteger. * @param fac BigInteger. * @return gcd algorithm implementation. */ public static GreatestCommonDivisorAbstract getProxy(BigInteger fac) { GreatestCommonDivisorAbstract ufd1, ufd2; ufd1 = new GreatestCommonDivisorSubres(); ufd2 = new GreatestCommonDivisorModular(); // dummy type return new GCDProxy(ufd1, ufd2); } /** * Determine suitable implementation of gcd algorithms, case BigRational. * @param fac BigRational. * @return gcd algorithm implementation. */ public static GreatestCommonDivisorAbstract getImplementation(BigRational fac) { GreatestCommonDivisorAbstract ufd; ufd = new GreatestCommonDivisorPrimitive(); return ufd; } /** * Determine suitable proxy for gcd algorithms, case BigRational. * @param fac BigRational. * @return gcd algorithm implementation. */ public static GreatestCommonDivisorAbstract getProxy(BigRational fac) { GreatestCommonDivisorAbstract ufd1, ufd2; ufd1 = new GreatestCommonDivisorSubres(); ufd2 = new GreatestCommonDivisorSimple(); return new GCDProxy(ufd1, ufd2); } /** * Determine suitable implementation of gcd algorithms, other cases. * @param fac RingFactory<C>. * @return gcd algorithm implementation. */ @SuppressWarnings("unchecked") public static > GreatestCommonDivisorAbstract getImplementation( RingFactory fac) { GreatestCommonDivisorAbstract/*raw type*/ufd; logger.debug("fac = " + fac.getClass().getName()); Object ofac = fac; if (ofac instanceof BigInteger) { ufd = new GreatestCommonDivisorModular(); //ufd = new GreatestCommonDivisorSubres(); //ufd = new GreatestCommonDivisorModular(true); } else if (ofac instanceof ModIntegerRing) { ufd = new GreatestCommonDivisorModEval(); } else if (ofac instanceof ModLongRing) { ufd = new GreatestCommonDivisorModEval(); } else if (ofac instanceof BigRational) { ufd = new GreatestCommonDivisorSubres(); } else { if (fac.isField()) { ufd = new GreatestCommonDivisorSimple(); } else { ufd = new GreatestCommonDivisorSubres(); } } logger.debug("implementation = " + ufd); return ufd; } /** * Determine suitable proxy for gcd algorithms, other cases. * @param fac RingFactory<C>. * @return gcd algorithm implementation. Note: This method contains a * hack for Google app engine to not use threads. * @see edu.jas.kern.ComputerThreads#NO_THREADS */ @SuppressWarnings("unchecked") public static > GreatestCommonDivisorAbstract getProxy(RingFactory fac) { if (ComputerThreads.NO_THREADS) { // hack for Google app engine return GCDFactory. getImplementation(fac); } GreatestCommonDivisorAbstract/*raw type*/ufd; logger.debug("fac = " + fac.getClass().getName()); Object ofac = fac; if (ofac instanceof BigInteger) { ufd = new GCDProxy(new GreatestCommonDivisorSubres(), new GreatestCommonDivisorModular()); } else if (ofac instanceof ModIntegerRing) { ufd = new GCDProxy(new GreatestCommonDivisorSimple(), // Subres new GreatestCommonDivisorModEval()); } else if (ofac instanceof ModLongRing) { ufd = new GCDProxy(new GreatestCommonDivisorSimple(), // Subres new GreatestCommonDivisorModEval()); } else if (ofac instanceof BigRational) { ufd = new GCDProxy(new GreatestCommonDivisorSubres(), new GreatestCommonDivisorSimple()); } else { if (fac.isField()) { ufd = new GCDProxy(new GreatestCommonDivisorSimple(), new GreatestCommonDivisorSubres()); } else { ufd = new GCDProxy(new GreatestCommonDivisorSubres(), new GreatestCommonDivisorPrimitive()); // no resultant } } logger.debug("ufd = " + ufd); return ufd; } } jas-2.5/src/edu/jas/ufd/GreatestCommonDivisorPrimitive.java0000644000175000017500000001011312003300514024245 0ustar giovannigiovanni/* * $Id: GreatestCommonDivisorPrimitive.java 4026 2012-07-23 16:52:28Z kredel $ */ package edu.jas.ufd; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; /** * Greatest common divisor algorithms with primitive polynomial remainder * sequence. * @author Heinz Kredel */ public class GreatestCommonDivisorPrimitive> extends GreatestCommonDivisorAbstract { private static final Logger logger = Logger.getLogger(GreatestCommonDivisorPrimitive.class); private final boolean debug = logger.isDebugEnabled(); /** * Univariate GenPolynomial greatest comon divisor. Uses pseudoRemainder for * remainder. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial baseGcd(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } if (P.ring.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); } long e = P.degree(0); long f = S.degree(0); GenPolynomial q; GenPolynomial r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } r = r.abs(); q = q.abs(); C a = baseContent(r); C b = baseContent(q); C c = gcd(a, b); // indirection r = divide(r, a); // indirection q = divide(q, b); // indirection if (r.isONE()) { return r.multiply(c); } if (q.isONE()) { return q.multiply(c); } GenPolynomial x; while (!r.isZERO()) { x = PolyUtil. baseSparsePseudoRemainder(q, r); q = r; r = basePrimitivePart(x); } return (q.multiply(c)).abs(); } /** * Univariate GenPolynomial recursive greatest comon divisor. Uses * pseudoRemainder for remainder. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial> recursiveUnivariateGcd(GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } if (P.ring.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); } long e = P.degree(0); long f = S.degree(0); GenPolynomial> q; GenPolynomial> r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } r = r.abs(); q = q.abs(); GenPolynomial a = recursiveContent(r); GenPolynomial b = recursiveContent(q); GenPolynomial c = gcd(a, b); // go to recursion //System.out.println("rgcd c = " + c); r = PolyUtil. recursiveDivide(r, a); q = PolyUtil. recursiveDivide(q, b); if (r.isONE()) { return r.multiply(c); } if (q.isONE()) { return q.multiply(c); } GenPolynomial> x; while (!r.isZERO()) { x = PolyUtil. recursivePseudoRemainder(q, r); //System.out.println("rgcd x = " + x); q = r; r = recursivePrimitivePart(x); } return q.abs().multiply(c); //.abs(); } } jas-2.5/src/edu/jas/ufd/GreatestCommonDivisorHensel.java0000644000175000017500000007217612103467406023553 0ustar giovannigiovanni/* * $Id: GreatestCommonDivisorHensel.java 4365 2013-02-03 14:07:02Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLongRing; import edu.jas.arith.Modular; import edu.jas.arith.ModularRingFactory; import edu.jas.arith.PrimeList; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; import edu.jas.structure.NotInvertibleException; //import edu.jas.application.Ideal; /** * Greatest common divisor algorithms with subresultant polynomial remainder * sequence and univariate Hensel lifting. * @author Heinz Kredel */ public class GreatestCommonDivisorHensel & Modular> extends GreatestCommonDivisorAbstract { private static final Logger logger = Logger.getLogger(GreatestCommonDivisorHensel.class); private final boolean debug = logger.isDebugEnabled(); /** * Flag for linear or quadratic Hensel lift. */ public final boolean quadratic; /** * Fall back gcd algorithm. */ public final GreatestCommonDivisorAbstract iufd; /* * Internal dispatcher. */ private final GreatestCommonDivisorAbstract ufd; /** * Constructor. */ public GreatestCommonDivisorHensel() { this(true); } /** * Constructor. * @param quadratic use quadratic Hensel lift. */ public GreatestCommonDivisorHensel(boolean quadratic) { this.quadratic = quadratic; iufd = new GreatestCommonDivisorSubres(); ufd = this; //iufd; } /** * Univariate GenPolynomial greatest comon divisor. Uses univariate Hensel * lifting. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial baseGcd(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } if (P.ring.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); } GenPolynomialRing fac = P.ring; long e = P.degree(0); long f = S.degree(0); GenPolynomial q; GenPolynomial r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } r = r.abs(); q = q.abs(); // compute contents and primitive parts BigInteger a = baseContent(r); BigInteger b = baseContent(q); // gcd of coefficient contents BigInteger c = gcd(a, b); // indirection r = divide(r, a); // indirection q = divide(q, b); // indirection if (r.isONE()) { return r.multiply(c); } if (q.isONE()) { return q.multiply(c); } // compute normalization factor BigInteger ac = r.leadingBaseCoefficient(); BigInteger bc = q.leadingBaseCoefficient(); BigInteger cc = gcd(ac, bc); // indirection // compute degree vectors, only univeriate ExpVector rdegv = r.degreeVector(); ExpVector qdegv = q.degreeVector(); //initialize prime list and degree vector PrimeList primes = new PrimeList(PrimeList.Range.medium); int pn = 50; //primes.size(); ModularRingFactory cofac; GenPolynomial qm; GenPolynomial qmf; GenPolynomial rm; GenPolynomial rmf; GenPolynomial cmf; GenPolynomialRing mfac; GenPolynomial cm = null; GenPolynomial[] ecm = null; GenPolynomial sm = null; GenPolynomial tm = null; HenselApprox lift = null; if (debug) { logger.debug("c = " + c); logger.debug("cc = " + cc); logger.debug("primes = " + primes); } int i = 0; for (java.math.BigInteger p : primes) { //System.out.println("next run ++++++++++++++++++++++++++++++++++"); if (++i >= pn) { logger.error("prime list exhausted, pn = " + pn); //logger.info("primes = " + primes); return iufd.baseGcd(P, S); //throw new ArithmeticException("prime list exhausted"); } // initialize coefficient factory and map normalization factor //cofac = new ModIntegerRing(p, true); if (ModLongRing.MAX_LONG.compareTo(p) > 0) { cofac = (ModularRingFactory) new ModLongRing(p, true); } else { cofac = (ModularRingFactory) new ModIntegerRing(p, true); } MOD nf = cofac.fromInteger(cc.getVal()); if (nf.isZERO()) { continue; } nf = cofac.fromInteger(q.leadingBaseCoefficient().getVal()); if (nf.isZERO()) { continue; } nf = cofac.fromInteger(r.leadingBaseCoefficient().getVal()); if (nf.isZERO()) { continue; } // initialize polynomial factory and map polynomials mfac = new GenPolynomialRing(cofac, fac.nvar, fac.tord, fac.getVars()); qm = PolyUtil. fromIntegerCoefficients(mfac, q); if (!qm.degreeVector().equals(qdegv)) { continue; } rm = PolyUtil. fromIntegerCoefficients(mfac, r); if (!rm.degreeVector().equals(rdegv)) { continue; } if (debug) { logger.info("cofac = " + cofac.getIntegerModul()); } // compute univariate modular gcd cm = qm.gcd(rm); // test for constant g.c.d if (cm.isConstant()) { logger.debug("cm, constant = " + cm); return fac.getONE().multiply(c); } // compute factors and gcd with factor GenPolynomial crq; rmf = rm.divide(cm); // rm = cm * rmf ecm = cm.egcd(rmf); if (ecm[0].isONE()) { //logger.debug("gcd() first factor " + rmf); crq = r; cmf = rmf; sm = ecm[1]; tm = ecm[2]; } else { qmf = qm.divide(cm); // qm = cm * qmf ecm = cm.egcd(qmf); if (ecm[0].isONE()) { //logger.debug("gcd() second factor " + qmf); crq = q; cmf = qmf; sm = ecm[1]; tm = ecm[2]; } else { logger.info("both gcd != 1: Hensel not applicable"); return iufd.baseGcd(P, S); } } BigInteger cn = crq.maxNorm(); cn = cn.multiply(crq.leadingBaseCoefficient().abs()); cn = cn.multiply(cn.fromInteger(2)); if (debug) { System.out.println("crq = " + crq); System.out.println("cm = " + cm); System.out.println("cmf = " + cmf); System.out.println("sm = " + sm); System.out.println("tm = " + tm); System.out.println("cn = " + cn); } try { if (quadratic) { lift = HenselUtil.liftHenselQuadratic(crq, cn, cm, cmf, sm, tm); } else { lift = HenselUtil.liftHensel(crq, cn, cm, cmf, sm, tm); } } catch (NoLiftingException nle) { logger.info("giving up on Hensel gcd reverting to Subres gcd " + nle); return iufd.baseGcd(P, S); } q = lift.A; if (debug) { System.out.println("q = " + q); System.out.println("qf = " + lift.B); } q = basePrimitivePart(q); q = q.multiply(c).abs(); if (PolyUtil. baseSparsePseudoRemainder(P, q).isZERO() && PolyUtil. baseSparsePseudoRemainder(S, q).isZERO()) { break; } logger.info("final devision not successfull"); //System.out.println("P rem q = " + PolyUtil.basePseudoRemainder(P,q)); //System.out.println("S rem q = " + PolyUtil.basePseudoRemainder(S,q)); //break; } return q; } /** * Univariate GenPolynomial recursive greatest comon divisor. Uses * multivariate Hensel list. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial> recursiveUnivariateGcd( GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } if (P.ring.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); } long e = P.degree(0); long f = S.degree(0); GenPolynomial> q, r, s; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } r = r.abs(); q = q.abs(); //logger.info("r: " + r + ", q: " + q); GenPolynomial a = ufd.recursiveContent(r); GenPolynomial b = ufd.recursiveContent(q); GenPolynomial c = ufd.gcd(a, b); // go to recursion //System.out.println("rgcd c = " + c); r = PolyUtil. recursiveDivide(r, a); q = PolyUtil. recursiveDivide(q, b); a = PolyUtil. basePseudoDivide(a, c); b = PolyUtil. basePseudoDivide(b, c); if (r.isONE()) { return r.multiply(c); } if (q.isONE()) { return q.multiply(c); } // check constant ldcf, TODO general case GenPolynomial la, lb, lc, lh; la = r.leadingBaseCoefficient(); lb = q.leadingBaseCoefficient(); lc = ufd.gcd(la,lb); //logger.info("la = " + la + ", lb = " + lb + ", lc = " + lc); if ( !lc.isConstant() ) { //continue; // easy way out GenPolynomial> T = iufd.recursiveUnivariateGcd(r, q); T = T.abs().multiply(c); logger.info("non monic ldcf (" + lc + ") not implemented: " + T + "= gcd(" + r + "," + q + ") * " + c); return T; } // convert from Z[y1,...,yr][x] to Z[x][y1,...,yr] to Z[x,y1,...,yr] GenPolynomial> qs = PolyUtil. switchVariables(q); GenPolynomial> rs = PolyUtil. switchVariables(r); GenPolynomialRing> rfac = qs.ring; RingFactory> rrfac = rfac.coFac; GenPolynomialRing cfac = (GenPolynomialRing) rrfac; GenPolynomialRing dfac = cfac.extend(rfac.getVars()); //System.out.println("pfac = " + P.ring.toScript()); //System.out.println("rfac = " + rfac.toScript()); //System.out.println("dfac = " + dfac.toScript()); GenPolynomial qd = PolyUtil. distribute(dfac, qs); GenPolynomial rd = PolyUtil. distribute(dfac, rs); // compute normalization factor BigInteger ac = rd.leadingBaseCoefficient(); BigInteger bc = qd.leadingBaseCoefficient(); BigInteger cc = gcd(ac, bc); // indirection //initialize prime list PrimeList primes = new PrimeList(PrimeList.Range.medium); Iterator primeIter = primes.iterator(); int pn = 50; //primes.size(); // double check variables // need qe,re,qd,rd,a,b GenPolynomial qe0, re0, ce0 = null; for (int i = 0; i < 11; i++) { // meta loop //System.out.println("======== run " + dfac.nvar + ", " + i); java.math.BigInteger p = null; //new java.math.BigInteger("19"); //primes.next(); // 5 small, 4 medium and 2 large size primes if (i == 0) { // medium size primes = new PrimeList(PrimeList.Range.medium); primeIter = primes.iterator(); } if (i == 4) { // small size primes = new PrimeList(PrimeList.Range.small); primeIter = primes.iterator(); p = primeIter.next(); // 2 p = primeIter.next(); // 3 p = primeIter.next(); // 5 p = primeIter.next(); // 7 } if (i == 9) { // large size primes = new PrimeList(PrimeList.Range.large); primeIter = primes.iterator(); } ModularRingFactory cofac = null; int pi = 0; while (pi < pn && primeIter.hasNext()) { p = primeIter.next(); //p = new java.math.BigInteger("19"); logger.info("prime = " + p); // initialize coefficient factory and map normalization factor and polynomials ModularRingFactory cf = null; if (ModLongRing.MAX_LONG.compareTo(p) > 0) { cf = (ModularRingFactory) new ModLongRing(p, true); } else { cf = (ModularRingFactory) new ModIntegerRing(p, true); } MOD nf = cf.fromInteger(cc.getVal()); if (nf.isZERO()) { continue; } nf = cf.fromInteger(q.leadingBaseCoefficient().leadingBaseCoefficient().getVal()); if (nf.isZERO()) { continue; } nf = cf.fromInteger(r.leadingBaseCoefficient().leadingBaseCoefficient().getVal()); if (nf.isZERO()) { continue; } cofac = cf; break; } if (cofac == null) { // no lucky prime found GenPolynomial> T = iufd.recursiveUnivariateGcd(q, r); logger.info("no lucky prime, gave up on Hensel: " + T + "= gcd(" + r + "," + q + ")"); return T.abs().multiply(c); //.abs(); } //System.out.println("cofac = " + cofac); // search evaluation points and evaluate List V = new ArrayList(P.ring.nvar); GenPolynomialRing ckfac = dfac; GenPolynomial qe = qd; GenPolynomial re = rd; GenPolynomial qei; GenPolynomial rei; for (int j = dfac.nvar; j > 1; j--) { // evaluation to univariate case long degq = qe.degree(ckfac.nvar - 2); long degr = re.degree(ckfac.nvar - 2); ckfac = ckfac.contract(1); long vi = 1L; //(long)(dfac.nvar-j); // 1L; 0 not so good for small p if (p.longValue() > 1000L) { //vi = (long)j+1L; vi = 0L; } // search small evaluation point while (true) { MOD vp = cofac.fromInteger(vi++); //System.out.println("vp = " + vp); if (vp.isZERO() && vi != 1L) { // all elements of Z_p exhausted qe = null; re = null; break; } BigInteger vii = new BigInteger(vi-1); qei = PolyUtil. evaluateMain(ckfac, qe, vii); rei = PolyUtil. evaluateMain(ckfac, re, vii); //System.out.println("qei = " + qei); //System.out.println("rei = " + rei); // check lucky evaluation point if (degq != qei.degree(ckfac.nvar - 1)) { //System.out.println("degv(qe) = " + qe.degreeVector()); //System.out.println("deg(qe) = " + degq + ", deg(qe) = " + qei.degree(ckfac.nvar-1)); continue; } if (degr != rei.degree(ckfac.nvar - 1)) { //System.out.println("degv(re) = " + re.degreeVector()); //System.out.println("deg(re) = " + degr + ", deg(re) = " + rei.degree(ckfac.nvar-1)); continue; } V.add(vii); qe = qei; re = rei; break; } if (qe == null && re == null) { break; } } if (qe == null && re == null) { continue; } logger.info("evaluation points = " + V); // recursion base: GenPolynomial ce = ufd.baseGcd(qe, re); if (ce.isConstant()) { return P.ring.getONE().multiply(c); } logger.info("base gcd = " + ce); // double check // need qe,re,qd,rd,a,b if (i == 0) { qe0 = qe; re0 = re; ce0 = ce; continue; } long d0 = ce0.degree(0); long d1 = ce.degree(0); //System.out.println("d0, d1 = " + d0 + ", " + d1); if (d1 < d0) { qe0 = qe; re0 = re; ce0 = ce; continue; } else if (d1 > d0) { continue; } // d0 == d1 is ok long dx = r.degree(0); //System.out.println("d0, dx = " + d0 + ", " + dx); if (d0 == dx) { // gcd == r ? if (PolyUtil. recursivePseudoRemainder(q, r).isZERO()) { r = r.abs().multiply(c); //.abs(); logger.info("exit with r | q : " + r); return r; } continue; } // norm BigInteger mn = null; //mn = mn.multiply(cc).multiply(mn.fromInteger(2)); // prepare lifting, chose factor polynomials GenPolynomial re1 = PolyUtil. basePseudoDivide(re, ce); GenPolynomial qe1 = PolyUtil. basePseudoDivide(qe, ce); GenPolynomial ui, he, pe; GenPolynomial g, gi, lui; GenPolynomial gcr, gcq; gcr = ufd.baseGcd(re1, ce); gcq = ufd.baseGcd(qe1, ce); if (gcr.isONE() && gcq.isONE() ) { // both gcds == 1: chose smaller ldcf if ( la.totalDegree() > lb.totalDegree() ) { ui = qd; s = q; he = qe1; pe = qe; BigInteger bn = qd.maxNorm(); mn = bn.multiply(cc).multiply(new BigInteger(2L)); g = lb; logger.debug("select deg: ui = qd, g = b"); //, qe1 = " + qe1); // + ", qe = " + qe); } else { ui = rd; s = r; he = re1; pe = re; BigInteger an = rd.maxNorm(); mn = an.multiply(cc).multiply(new BigInteger(2L)); g = la; logger.debug("select deg: ui = rd, g = a"); //, re1 = " + re1); // + ", re = " + re); } } else if (gcr.isONE()) { ui = rd; s = r; he = re1; pe = re; BigInteger an = rd.maxNorm(); mn = an.multiply(cc).multiply(new BigInteger(2L)); g = la; logger.debug("select: ui = rd, g = a"); //, re1 = " + re1); // + ", re = " + re); } else if (gcq.isONE()) { ui = qd; s = q; he = qe1; pe = qe; BigInteger bn = qd.maxNorm(); mn = bn.multiply(cc).multiply(new BigInteger(2L)); g = lb; logger.debug("select: ui = qd, g = b"); //, qe1 = " + qe1); // + ", qe = " + qe); } else { // both gcds != 1: method not applicable logger.info("both gcds != 1: method not applicable"); break; } lui = lc; //s.leadingBaseCoefficient(); lh = PolyUtil. basePseudoDivide(g, lui); BigInteger ge = PolyUtil. evaluateAll(g.ring.coFac, lui, V); if ( ge.isZERO() ) { continue; } BigInteger geh = PolyUtil. evaluateAll(g.ring.coFac, lh, V); if ( geh.isZERO() ) { continue; } BigInteger gg = PolyUtil. evaluateAll(g.ring.coFac, g, V); if ( gg.isZERO() ) { continue; } //System.out.println("ge = " + ge + ", geh = " + geh + ", gg = " + gg + ", pe = " + pe); // //ce = ce.multiply(geh); //ge); // he = he.multiply(ge); //gg); //ge); //geh); // gi = lui.extendLower(dfac,0,0L); //lui. // g. // ui = ui.multiply(gi); // gi !.multiply(gi) //System.out.println("ui = " + ui + ", deg(ui) = " + ui.degreeVector()); //System.out.println("ce = " + ce + ", he = " + he + ", ge = " + ge); logger.info("gcd(ldcf): " + lui + ", ldcf cofactor: " + lh + ", base cofactor: " + he); long k = Power.logarithm(new BigInteger(p), mn); //System.out.println("mn = " + mn); //System.out.println("k = " + k); BigInteger qp = Power.positivePower(cofac.getIntegerModul(), k); // == p ModularRingFactory muqfac; if (ModLongRing.MAX_LONG.compareTo(qp.getVal()) > 0) { muqfac = (ModularRingFactory) new ModLongRing(qp.getVal(),true); // nearly a field } else { muqfac = (ModularRingFactory) new ModIntegerRing(qp.getVal(),true); // nearly a field } GenPolynomialRing mucpfac = new GenPolynomialRing(muqfac, ckfac); //System.out.println("mucpfac = " + mucpfac.toScript()); if ( muqfac.fromInteger(ge.getVal()).isZERO() ) { continue; } //GenPolynomial xxx = invertPoly(muqfac,lui,V); //System.out.println("inv(lui) = " + xxx + ", muqfac = " + muqfac + ", lui = " + lui); //ce = ce.multiply(xxx); //.leadingBaseCoefficient()); //xxx = invertPoly(muqfac,lh,V); //System.out.println("inv(lh) = " + xxx + ", muqfac = " + muqfac + ", lh = " + lh); //he = he.multiply(xxx); //.leadingBaseCoefficient()); GenPolynomial cm = PolyUtil. fromIntegerCoefficients(mucpfac, ce); GenPolynomial hm = PolyUtil. fromIntegerCoefficients(mucpfac, he); if ( cm.degree(0) != ce.degree(0) || hm.degree(0) != he.degree(0) ) { continue; } if ( cm.isZERO() || hm.isZERO() ) { continue; } logger.info("univariate modulo p^k: " + cm + ", " + hm); // convert C from Z[...] to Z_q[...] GenPolynomialRing qcfac = new GenPolynomialRing(muqfac, dfac); GenPolynomial uq = PolyUtil. fromIntegerCoefficients(qcfac, ui); if ( !ui.leadingExpVector().equals(uq.leadingExpVector()) ) { logger.info("ev(ui) = " + ui.leadingExpVector() + ", ev(uq) = " + uq.leadingExpVector() ); continue; } logger.info("multivariate modulo p^k: " + uq); List> F = new ArrayList>(2); F.add(cm); F.add(hm); List> G = new ArrayList>(2); G.add(lui.ring.getONE()); //lui: lui.ring.getONE()); // TODO G.add(lui.ring.getONE()); //lh: lui); List> lift; try { //lift = HenselMultUtil. liftHenselFull(ui, F, V, k, G); lift = HenselMultUtil. liftHensel(ui, uq, F, V, k, G); logger.info("lift = " + lift); } catch (NoLiftingException nle) { logger.info("NoLiftingException"); //System.out.println("exception : " + nle); continue; } catch (ArithmeticException ae) { logger.info("ArithmeticException"); //System.out.println("exception : " + ae); continue; } catch (NotInvertibleException ni) { logger.info("NotInvertibleException"); //System.out.println("exception : " + ni); continue; } if ( false && ! HenselMultUtil. isHenselLift(ui, uq, F, k, lift) ) { // not meaningfull test logger.info("isHenselLift: false"); //continue; } // convert Ci from Z_{p^k}[x,y1,...,yr] to Z[x,y1,...,yr] to Z[x][y1,...,yr] to Z[y1,...,yr][x] GenPolynomial ci = PolyUtil.integerFromModularCoefficients(dfac, lift.get(0)); ci = basePrimitivePart(ci); GenPolynomial> Cr = PolyUtil. recursive(rfac, ci); GenPolynomial> Cs = PolyUtil. switchVariables(Cr); if (!Cs.ring.equals(P.ring)) { System.out.println("Cs.ring = " + Cs.ring + ", P.ring = " + P.ring); } GenPolynomial> Q = ufd.recursivePrimitivePart(Cs); Q = ufd.baseRecursivePrimitivePart(Q); Q = Q.abs().multiply(c); //.abs(); GenPolynomial> Pq, Sq; Pq = PolyUtil. recursivePseudoRemainder(P, Q); Sq = PolyUtil. recursivePseudoRemainder(S, Q); if ( Pq.isZERO() && Sq.isZERO()) { logger.info("gcd normal exit: " + Q); return Q; } logger.info("bad Q = " + Q); // + ", Pq = " + Pq + ", Sq = " + Sq); } // end for meta loop // Hensel gcd failed GenPolynomial> T = iufd.recursiveUnivariateGcd(r,q); T = T.abs().multiply(c); logger.info("no lucky prime or evaluation points, gave up on Hensel: " + T + "= gcd(" + r + "," + q + ")"); return T; } GenPolynomial invertPoly(ModularRingFactory mfac, GenPolynomial li, List V) { if ( li == null || li.isZERO() ) { throw new RuntimeException("li not invertible: " + li); } if ( li.isONE() ) { return li; } //System.out.println("mfac = " + mfac + ", V = " + V +", li = " + li); GenPolynomialRing pfac = li.ring; GenPolynomialRing mpfac = new GenPolynomialRing(mfac,pfac); GenPolynomial lm = PolyUtil. fromIntegerCoefficients(mpfac, li); //System.out.println("pfac = " + pfac + ", lm = " + lm); List> lid = new ArrayList>(V.size()); int i = 0; for ( BigInteger bi : V ) { MOD m = mfac.fromInteger(bi.getVal()); GenPolynomial mp = mpfac.univariate(i); mp = mp.subtract(m); // X_i - v_i lid.add(mp); i++; } //System.out.println("lid = " + lid); //Ideal id = new Ideal(mpfac,lid,true); // is a GB //System.out.println("id = " + id); GenPolynomial mi = lm; //id.inverse(lm); //System.out.println("mi = " + mi); GenPolynomial inv = PolyUtil.integerFromModularCoefficients(pfac, mi); return inv; } } jas-2.5/src/edu/jas/ufd/FactorAlgebraic.java0000644000175000017500000001707112003566210021116 0ustar giovannigiovanni/* * $Id: FactorAlgebraic.java 4028 2012-07-24 18:42:16Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.TermOrder; import edu.jas.structure.GcdRingElem; /** * Algebraic number coefficients factorization algorithms. This class implements * factorization methods for polynomials over algebraic numbers over rational * numbers or over (prime) modular integers. * @author Heinz Kredel * @param coefficient type */ public class FactorAlgebraic> extends FactorAbsolute> { private static final Logger logger = Logger.getLogger(FactorAlgebraic.class); private final boolean debug = logger.isDebugEnabled(); /** * Factorization engine for base coefficients. */ public final FactorAbstract factorCoeff; /** * No argument constructor. Note: can't use this constructor. */ protected FactorAlgebraic() { throw new IllegalArgumentException("don't use this constructor"); } /** * Constructor. * @param fac algebraic number factory. */ public FactorAlgebraic(AlgebraicNumberRing fac) { this(fac, FactorFactory. getImplementation(fac.ring.coFac) ); } /** * Constructor. * @param fac algebraic number factory. * @param factorCoeff factorization engine for polynomials over base coefficients. */ public FactorAlgebraic(AlgebraicNumberRing fac, FactorAbstract factorCoeff) { super(fac); this.factorCoeff = factorCoeff; } /** * GenPolynomial base factorization of a squarefree polynomial. * @param P squarefree GenPolynomial<AlgebraicNumber<C>>. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ @Override public List>> baseFactorsSquarefree(GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List>> factors = new ArrayList>>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing> pfac = P.ring; // Q(alpha)[x] if (pfac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomials"); } AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac; AlgebraicNumber ldcf = P.leadingBaseCoefficient(); if (!ldcf.isONE()) { P = P.monic(); factors.add(pfac.getONE().multiply(ldcf)); } //System.out.println("\nP = " + P); if (debug) { Squarefree> sqengine = SquarefreeFactory.> getImplementation(afac); if ( !sqengine.isSquarefree(P) ) { throw new RuntimeException("P not squarefree: " + sqengine.squarefreeFactors(P)); } GenPolynomial modu = afac.modul; if ( !factorCoeff.isIrreducible(modu) ) { throw new RuntimeException("modul not irreducible: " + factorCoeff.factors(modu)); } System.out.println("P squarefree and modul irreducible"); //GreatestCommonDivisor> aengine //= GCDFactory.> getProxy(afac); // = new GreatestCommonDivisorSimple>( /*cfac.coFac*/ ); } // search squarefree norm long k = 0L; long ks = k; GenPolynomial res = null; boolean sqf = false; //int[] klist = new int[]{ 0, 1, 2, 3, -1, -2, -3 , 5, -5, 7, -7, 101, -101, 1001, -1001 }; //int[] klist = new int[]{ 0, 1, 2, 3, -1, -2, -3 , 5, -5, 7, -7, 23, -23, 167, -167 }; //int[] klist = new int[] { 0, -1, -2, 1, 2, -3, 3 }; int[] klist = new int[] { 0, -1, -2, 1, 2 }; int ki = 0; while (!sqf) { // k = 0,1,2,-1,-2 if (ki >= klist.length) { break; } k = klist[ki]; ki++; // compute norm with x -> ( y - k x ) ks = k; res = PolyUfdUtil. norm(P, ks); //System.out.println("res = " + res); if (res.isZERO() || res.isConstant()) { continue; } sqf = factorCoeff.isSquarefree(res); //System.out.println("sqf("+ks+") = " + res.degree()); //System.out.println("resfact = " + factorCoeff.baseFactors(res) + "\n"); } // if Res is now squarefree, else must take radical factorization List> nfacs; if (!sqf) { //System.out.println("\nres = " + res); System.out.println("sqf(" + ks + ") = " + res.degree()); //res = factorCoeff.squarefreePart(res); // better use obtained factors //res = factorCoeff.baseFactors(res).lastKey(); } //res = res.monic(); if (logger.isInfoEnabled()) { logger.info("res = " + res); //System.out.println("\nres = " + res); } nfacs = factorCoeff.baseFactorsRadical(res); if (logger.isInfoEnabled()) { logger.info("res facs = " + nfacs); // Q[X] //System.out.println("\nnfacs = " + nfacs); // Q[X] } if (nfacs.size() == 1) { factors.add(P); return factors; } // compute gcds of factors with polynomial in Q(alpha)[X] GenPolynomial> Pp = P; //System.out.println("Pp = " + Pp); GenPolynomial> Ni; for (GenPolynomial nfi : nfacs) { //System.out.println("nfi = " + nfi); Ni = PolyUfdUtil. substituteConvertToAlgebraicCoefficients(pfac, nfi, ks); if (logger.isInfoEnabled()) { logger.info("Ni = " + Ni); //System.out.println("Pp = " + Pp); //System.out.println("Ni = " + Ni); } // compute gcds of factors with polynomial GenPolynomial> pni = engine.gcd(Ni, Pp); if (!pni.leadingBaseCoefficient().isONE()) { //System.out.println("gcd(Ni,Pp) not monic " + pni); pni = pni.monic(); } if (logger.isInfoEnabled()) { logger.info("gcd(Ni,Pp) = " + pni); //System.out.println("gcd(Ni,Pp) = " + pni); } if (!pni.isONE()) { factors.add(pni); Pp = Pp.divide(pni); // } else { // GenPolynomial> qni = Pp.divide(Ni); // GenPolynomial> rni = Pp.remainder(Ni); // System.out.println("div qni = " + qni); // System.out.println("div rni = " + rni); // continue; // //throw new RuntimeException("gcd(Ni,Pp) == 1"); } } if (!Pp.isZERO() && !Pp.isONE()) { // irreducible rest factors.add(Pp); } //System.out.println("afactors = " + factors); return factors; } } jas-2.5/src/edu/jas/ufd/FactorAbstract.java0000644000175000017500000007024612103522336021015 0ustar giovannigiovanni/* * $Id: FactorAbstract.java 4366 2013-02-03 17:56:46Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import org.apache.log4j.Logger; import edu.jas.kern.TimeStatus; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.poly.OptimizedPolynomialList; import edu.jas.poly.TermOrderOptimization; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.util.KsubSet; /** * Abstract factorization algorithms class. This class contains implementations * of all methods of the Factorization interface, except the method * for factorization of a squarefree polynomial. The methods to obtain * squarefree polynomials delegate the computation to the * GreatestCommonDivisor classes and are included for convenience. * @param coefficient type * @author Heinz Kredel * @see edu.jas.ufd.FactorFactory */ public abstract class FactorAbstract> implements Factorization { private static final Logger logger = Logger.getLogger(FactorAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Gcd engine for base coefficients. */ protected final GreatestCommonDivisorAbstract engine; /** * Squarefree decompositon engine for base coefficients. */ protected final SquarefreeAbstract sengine; /** * No argument constructor. */ protected FactorAbstract() { throw new IllegalArgumentException("don't use this constructor"); } /** * Constructor. * @param cfac coefficient ring factory. */ public FactorAbstract(RingFactory cfac) { engine = GCDFactory. getProxy(cfac); //engine = GCDFactory. getImplementation(cfac); sengine = SquarefreeFactory. getImplementation(cfac); } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return getClass().getName(); } /** * GenPolynomial test if is irreducible. * @param P GenPolynomial. * @return true if P is irreducible, else false. */ public boolean isIrreducible(GenPolynomial P) { if (!isSquarefree(P)) { return false; } List> F = factorsSquarefree(P); if (F.size() == 1) { return true; } else if (F.size() > 2) { return false; } else { //F.size() == 2 boolean cnst = false; for (GenPolynomial p : F) { if (p.isConstant()) { cnst = true; } } return cnst; } } /** * GenPolynomial test if a non trivial factorization exsists. * @param P GenPolynomial. * @return true if P is reducible, else false. */ public boolean isReducible(GenPolynomial P) { return !isIrreducible(P); } /** * GenPolynomial test if is squarefree. * @param P GenPolynomial. * @return true if P is squarefree, else false. */ public boolean isSquarefree(GenPolynomial P) { return sengine.isSquarefree(P); } /** * GenPolynomial factorization of a multivariate squarefree polynomial, * using Kronecker substitution and variable order optimization. * @param P squarefree and primitive! (respectively monic) multivariate * GenPolynomial over the ring C. * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. */ public List> factorsSquarefreeOptimize(GenPolynomial P) { GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return baseFactorsSquarefree(P); } List> topt = new ArrayList>(1); topt.add(P); OptimizedPolynomialList opt = TermOrderOptimization. optimizeTermOrder(pfac,topt); P = opt.list.get(0); logger.info("optimized polynomial: " + P); List iperm = TermOrderOptimization.inversePermutation(opt.perm); logger.info("optimize perm: " + opt.perm + ", de-optimize perm: " + iperm); ExpVector degv = P.degreeVector(); int[] donv = degv.dependencyOnVariables(); List> facs = null; if (degv.length() == donv.length) { // all variables appear logger.info("do.full factorsSquarefreeKronecker: " + P); facs = factorsSquarefreeKronecker(P); } else { // not all variables appear, remove unused variables GenPolynomial pu = PolyUtil. removeUnusedUpperVariables(P); //GenPolynomial pl = PolyUtil. removeUnusedLowerVariables(pu); // not useful after optimize logger.info("do.sparse factorsSquarefreeKronecker: " + pu); facs = factorsSquarefreeKronecker(pu); // pl List> fs = new ArrayList>(facs.size()); GenPolynomialRing pf = P.ring; //GenPolynomialRing pfu = pu.ring; for (GenPolynomial p : facs) { //GenPolynomial pel = p.extendLower(pfu, 0, 0L); GenPolynomial pe = p.extend(pf, 0, 0L); // pel fs.add(pe); } //System.out.println("fs = " + fs); facs = fs; } List> iopt = TermOrderOptimization. permutation(iperm, pfac,facs); logger.info("de-optimized polynomials: " + iopt); facs = normalizeFactorization(iopt); return facs; } /** * GenPolynomial factorization of a squarefree polynomial, using Kronecker * substitution. * @param P squarefree and primitive! (respectively monic) GenPolynomial. * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. */ @Override public List> factorsSquarefree(GenPolynomial P) { return factorsSquarefreeKronecker(P); //return factorsSquarefreeOptimize(P); } /** * GenPolynomial factorization of a squarefree polynomial, using Kronecker * substitution. * @param P squarefree and primitive! (respectively monic) GenPolynomial. * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. */ public List> factorsSquarefreeKronecker(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } GenPolynomialRing pfac = P.ring; if (pfac.nvar == 1) { return baseFactorsSquarefree(P); } List> factors = new ArrayList>(); if (P.isZERO()) { return factors; } if (P.degreeVector().totalDeg() <= 1L) { factors.add(P); return factors; } long d = P.degree() + 1L; GenPolynomial kr = PolyUfdUtil. substituteKronecker(P, d); GenPolynomialRing ufac = kr.ring; ufac.setVars(ufac.newVars("zz")); // side effects logger.info("deg(subs(P,d=" + d + ")) = " + kr.degree(0) + ", original degrees: " + P.degreeVector()); if (debug) { logger.info("subs(P,d=" + d + ") = " + kr); //System.out.println("subs(P,d=" + d + ") = " + kr); } if (kr.degree(0) > 100) { logger.warn("Kronecker substitution has to high degree"); TimeStatus.checkTime("degree > 100"); } // factor Kronecker polynomial List> ulist = new ArrayList>(); // kr might not be squarefree so complete factor univariate SortedMap, Long> slist = baseFactors(kr); if (debug && !isFactorization(kr, slist)) { System.out.println("kr = " + kr); System.out.println("slist = " + slist); throw new ArithmeticException("no factorization"); } for (Map.Entry, Long> me : slist.entrySet()) { GenPolynomial g = me.getKey(); long e = me.getValue(); // slist.get(g); for (int i = 0; i < e; i++) { // is this really required? yes! ulist.add(g); } } //System.out.println("ulist = " + ulist); if (ulist.size() == 1 && ulist.get(0).degree() == P.degree()) { factors.add(P); return factors; } //wrong: List> klist = PolyUfdUtil. backSubstituteKronecker(pfac, ulist, d); //System.out.println("back(klist) = " + PolyUfdUtil. backSubstituteKronecker(pfac, ulist, d)); if (logger.isInfoEnabled()) { logger.info("ulist = " + ulist); //System.out.println("ulist = " + ulist); } // combine trial factors int dl = ulist.size() - 1; //(ulist.size() + 1) / 2; //System.out.println("dl = " + dl); int ti = 0; GenPolynomial u = P; long deg = (u.degree() + 1L) / 2L; // max deg ExpVector evl = u.leadingExpVector(); ExpVector evt = u.trailingExpVector(); //System.out.println("deg = " + deg); for (int j = 1; j <= dl; j++) { KsubSet> ps = new KsubSet>(ulist, j); for (List> flist : ps) { //System.out.println("flist = " + flist); GenPolynomial utrial = ufac.getONE(); for (int k = 0; k < flist.size(); k++) { utrial = utrial.multiply(flist.get(k)); } GenPolynomial trial = PolyUfdUtil. backSubstituteKronecker(pfac, utrial, d); ti++; if (ti % 2000 == 0) { System.out.print("ti(" + ti + ") "); TimeStatus.checkTime(ti + " % 2000 == 0"); } if (!evl.multipleOf(trial.leadingExpVector())) { continue; } if (!evt.multipleOf(trial.trailingExpVector())) { continue; } if (trial.degree() > deg || trial.isConstant()) { continue; } trial = trial.monic(); if (ti % 15000 == 0) { System.out.println("\ndl = " + dl + ", deg(u) = " + deg); System.out.println("ulist = " + ulist); System.out.println("kr = " + kr); System.out.println("u = " + u); System.out.println("trial = " + trial); } GenPolynomial rem = PolyUtil. baseSparsePseudoRemainder(u, trial); //System.out.println(" rem = " + rem); if (rem.isZERO()) { logger.info("trial = " + trial); //System.out.println("trial = " + trial); factors.add(trial); u = PolyUtil. basePseudoDivide(u, trial); //u = u.divide( trial ); evl = u.leadingExpVector(); evt = u.trailingExpVector(); if (u.isConstant()) { j = dl + 1; break; } //if (ulist.removeAll(flist)) { // wrong ulist = removeOnce(ulist, flist); //System.out.println("new ulist = " + ulist); dl = (ulist.size() + 1) / 2; j = 0; // since j++ break; } } } if (!u.isONE() && !u.equals(P)) { logger.info("rest u = " + u); //System.out.println("rest u = " + u); factors.add(u); } if (factors.size() == 0) { logger.info("irred u = " + u); //System.out.println("irred u = " + u); factors.add(P); } return normalizeFactorization(factors); } /** * Remove one occurrence of elements. * @param a list of objects. * @param b list of objects. * @return remove every element of b from a, but only one occurrence. * Note: not available in java.util. */ static List removeOnce(List a, List b) { List res = new ArrayList(); res.addAll(a); for (T e : b) { boolean t = res.remove(e); } return res; } /** * Univariate GenPolynomial factorization ignoring multiplicities. * @param P GenPolynomial in one variable. * @return [p_1, ..., p_k] with P = prod_{i=1,...,k} p_i**{e_i} for some * e_i. */ public List> baseFactorsRadical(GenPolynomial P) { return new ArrayList>(baseFactors(P).keySet()); } /** * Univariate GenPolynomial factorization. * @param P GenPolynomial in one variable. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i**e_i. */ public SortedMap, Long> baseFactors(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } GenPolynomialRing pfac = P.ring; SortedMap, Long> factors = new TreeMap, Long>(pfac.getComparator()); if (P.isZERO()) { return factors; } if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } if (P.isConstant()) { factors.put(P, 1L); return factors; } C c; if (pfac.coFac.isField()) { //pfac.characteristic().signum() > 0 c = P.leadingBaseCoefficient(); } else { c = engine.baseContent(P); // move sign to the content if (P.signum() < 0 && c.signum() > 0) { c = c.negate(); //P = P.negate(); } } if (!c.isONE()) { GenPolynomial pc = pfac.getONE().multiply(c); factors.put(pc, 1L); P = P.divide(c); // make primitive or monic } if (logger.isInfoEnabled()) { logger.info("base facs for P = " + P); } SortedMap, Long> facs = sengine.baseSquarefreeFactors(P); if (facs == null || facs.size() == 0) { facs = new TreeMap, Long>(); facs.put(P, 1L); } if (logger.isInfoEnabled() && (facs.size() > 1 || (facs.size() == 1 && facs.get(facs.firstKey()) > 1))) { logger.info("squarefree facs = " + facs); //System.out.println("sfacs = " + facs); //boolean tt = isFactorization(P,facs); //System.out.println("sfacs tt = " + tt); } for (Map.Entry, Long> me : facs.entrySet()) { GenPolynomial g = me.getKey(); Long k = me.getValue(); //facs.get(g); //System.out.println("g = " + g); if (pfac.coFac.isField() && !g.leadingBaseCoefficient().isONE()) { g = g.monic(); // how can this happen? logger.warn("squarefree facs mon = " + g); } if (g.degree(0) <= 1) { if (!g.isONE()) { factors.put(g, k); } } else { List> sfacs = baseFactorsSquarefree(g); if (debug) { logger.info("factors of squarefree = " + sfacs); //System.out.println("sfacs = " + sfacs); } for (GenPolynomial h : sfacs) { Long j = factors.get(h); // evtl. constants if (j != null) { k += j; } if (!h.isONE()) { factors.put(h, k); } } } } //System.out.println("factors = " + factors); return factors; } /** * Univariate GenPolynomial factorization of a squarefree polynomial. * @param P squarefree and primitive! GenPolynomial in one variable. * @return [p_1, ..., p_k] with P = prod_{i=1,...,k} p_i. */ public abstract List> baseFactorsSquarefree(GenPolynomial P); /** * GenPolynomial factorization ignoring multiplicities. * @param P GenPolynomial. * @return [p_1, ..., p_k] with P = prod_{i=1,...,k} p_i**{e_i} for some * e_i. */ public List> factorsRadical(GenPolynomial P) { return new ArrayList>(factors(P).keySet()); } /** * GenPolynomial list factorization ignoring multiplicities. * @param L list of GenPolynomials. * @return [p_1, ..., p_k] with p = prod_{i=1,...,k} p_i**{e_i} for some e_i * for all p in L. */ public List> factorsRadical(List> L) { SortedSet> facs = new TreeSet>(); for (GenPolynomial p : L) { List> fs = factorsRadical(p); facs.addAll(fs); } return new ArrayList>(facs); } /** * GenPolynomial factorization. * @param P GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i**e_i. */ public SortedMap, Long> factors(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } GenPolynomialRing pfac = P.ring; if (pfac.nvar == 1) { return baseFactors(P); } SortedMap, Long> factors = new TreeMap, Long>(pfac.getComparator()); if (P.isZERO()) { return factors; } if (P.isConstant()) { factors.put(P, 1L); return factors; } C c; if (pfac.coFac.isField()) { // pfac.characteristic().signum() > 0 c = P.leadingBaseCoefficient(); } else { c = engine.baseContent(P); // move sign to the content if (P.signum() < 0 && c.signum() > 0) { c = c.negate(); //P = P.negate(); } } if (!c.isONE()) { GenPolynomial pc = pfac.getONE().multiply(c); factors.put(pc, 1L); P = P.divide(c); // make base primitive or base monic } if (logger.isInfoEnabled()) { logger.info("squarefree mfacs P = " + P); } SortedMap, Long> facs = sengine.squarefreeFactors(P); if (facs == null || facs.size() == 0) { facs = new TreeMap, Long>(); facs.put(P, 1L); throw new RuntimeException("this should not happen, facs is empty: " + facs); } if (logger.isInfoEnabled()) { if (facs.size() > 1) { logger.info("squarefree mfacs = " + facs); } else if (facs.size() == 1 && facs.get(facs.firstKey()) > 1L) { logger.info("squarefree #mfacs 1-n = " + facs); } else { logger.info("squarefree #mfacs 1-1 = " + facs); } } for (Map.Entry, Long> me : facs.entrySet()) { GenPolynomial g = me.getKey(); if (g.isONE()) { // skip 1 continue; } Long d = me.getValue(); // facs.get(g); List> sfacs = factorsSquarefree(g); if (logger.isInfoEnabled()) { logger.info("factors of squarefree ^" + d + " = " + sfacs); //System.out.println("sfacs = " + sfacs); } for (GenPolynomial h : sfacs) { long dd = d; Long j = factors.get(h); // evtl. constants if (j != null) { dd += j; } factors.put(h, dd); } } //System.out.println("factors = " + factors); return factors; } /** * GenPolynomial greatest squarefree divisor. Delegates computation to a * GreatestCommonDivisor class. * @param P GenPolynomial. * @return squarefree(P). */ public GenPolynomial squarefreePart(GenPolynomial P) { return sengine.squarefreePart(P); } /** * GenPolynomial primitive part. Delegates computation to a * GreatestCommonDivisor class. * @param P GenPolynomial. * @return primitivePart(P). */ public GenPolynomial primitivePart(GenPolynomial P) { return engine.primitivePart(P); } /** * GenPolynomial base primitive part. Delegates computation to a * GreatestCommonDivisor class. * @param P GenPolynomial. * @return basePrimitivePart(P). */ public GenPolynomial basePrimitivePart(GenPolynomial P) { return engine.basePrimitivePart(P); } /** * GenPolynomial squarefree factorization. Delegates computation to a * GreatestCommonDivisor class. * @param P GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i**e_i. */ public SortedMap, Long> squarefreeFactors(GenPolynomial P) { return sengine.squarefreeFactors(P); } /** * GenPolynomial is factorization. * @param P GenPolynomial. * @param F = [p_1,...,p_k]. * @return true if P = prod_{i=1,...,r} p_i, else false. */ public boolean isFactorization(GenPolynomial P, List> F) { return sengine.isFactorization(P, F); // test irreducible } /** * GenPolynomial is factorization. * @param P GenPolynomial. * @param F = [p_1 -> e_1, ..., p_k -> e_k]. * @return true if P = prod_{i=1,...,k} p_i**e_i , else false. */ public boolean isFactorization(GenPolynomial P, SortedMap, Long> F) { return sengine.isFactorization(P, F); // test irreducible } /** * Degree of a factorization. * @param F a factors map [p_1 -> e_1, ..., p_k -> e_k]. * @return sum_{i=1,...,k} degree(p_i)*e_i. */ public long factorsDegree(SortedMap, Long> F) { long d = 0; for (Map.Entry, Long> me : F.entrySet()) { GenPolynomial p = me.getKey(); long e = me.getValue(); //F.get(p); d += p.degree() * e; } return d; } /** * GenPolynomial is factorization. * @param P GenPolynomial. * @param F = [p_1 -> e_1, ..., p_k -> e_k]. * @return true if P = prod_{i=1,...,k} p_i**e_i , else false. */ public boolean isRecursiveFactorization(GenPolynomial> P, SortedMap>, Long> F) { return sengine.isRecursiveFactorization(P, F); // test irreducible } /** * Recursive GenPolynomial factorization of a squarefree polynomial. * @param P squarefree recursive GenPolynomial. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ public List>> recursiveFactorsSquarefree(GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List>> factors = new ArrayList>>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing> pfac = P.ring; GenPolynomialRing qi = (GenPolynomialRing) pfac.coFac; GenPolynomialRing ifac = qi.extend(pfac.getVars()); GenPolynomial Pi = PolyUtil. distribute(ifac, P); //System.out.println("Pi = " + Pi); C ldcf = Pi.leadingBaseCoefficient(); if (!ldcf.isONE() && ldcf.isUnit()) { //System.out.println("ldcf = " + ldcf); Pi = Pi.monic(); } // factor in C[x_1,...,x_n,y_1,...,y_m] List> ifacts = factorsSquarefree(Pi); if (logger.isInfoEnabled()) { logger.info("ifacts = " + ifacts); } if (ifacts.size() <= 1) { factors.add(P); return factors; } if (!ldcf.isONE() && ldcf.isUnit()) { GenPolynomial r = ifacts.get(0); ifacts.remove(r); r = r.multiply(ldcf); ifacts.add(0, r); } List>> rfacts = PolyUtil. recursive(pfac, ifacts); //System.out.println("rfacts = " + rfacts); if (logger.isDebugEnabled()) { logger.info("recfacts = " + rfacts); } factors.addAll(rfacts); return factors; } /** * Recursive GenPolynomial factorization. * @param P recursive GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} * p_i**e_i. */ public SortedMap>, Long> recursiveFactors(GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } GenPolynomialRing> pfac = P.ring; SortedMap>, Long> factors = new TreeMap>, Long>( pfac.getComparator()); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.put(P, 1L); return factors; } GenPolynomialRing qi = (GenPolynomialRing) pfac.coFac; GenPolynomialRing ifac = qi.extend(pfac.getVars()); GenPolynomial Pi = PolyUtil. distribute(ifac, P); //System.out.println("Pi = " + Pi); C ldcf = Pi.leadingBaseCoefficient(); if (!ldcf.isONE() && ldcf.isUnit()) { //System.out.println("ldcf = " + ldcf); Pi = Pi.monic(); } // factor in C[x_1,...,x_n,y_1,...,y_m] SortedMap, Long> dfacts = factors(Pi); if (logger.isInfoEnabled()) { logger.info("dfacts = " + dfacts); } if (!ldcf.isONE() && ldcf.isUnit()) { GenPolynomial r = dfacts.firstKey(); Long E = dfacts.remove(r); r = r.multiply(ldcf); dfacts.put(r, E); } for (Map.Entry, Long> me : dfacts.entrySet()) { GenPolynomial f = me.getKey(); Long E = me.getValue(); //dfacts.get(f); GenPolynomial> rp = PolyUtil. recursive(pfac, f); factors.put(rp, E); } //System.out.println("rfacts = " + rfacts); if (logger.isInfoEnabled()) { logger.info("recursive factors = " + factors); } return factors; } /** * Normalize factorization. p'_i > 0 for i > 1 and p'_1 != 1 if k > * 1. * @param F = [p_1,...,p_k]. * @return F' = [p'_1,...,p'_k]. */ public List> normalizeFactorization(List> F) { if (F == null || F.size() <= 1) { return F; } List> Fp = new ArrayList>(F.size()); GenPolynomial f0 = F.get(0); for (int i = 1; i < F.size(); i++) { GenPolynomial fi = F.get(i); if (fi.signum() < 0) { fi = fi.negate(); f0 = f0.negate(); } Fp.add(fi); } if (!f0.isONE()) { Fp.add(0, f0); } return Fp; } } jas-2.5/src/edu/jas/ufd/HenselUtil.java0000644000175000017500000023477412070337224020202 0ustar giovannigiovanni/* * $Id: HenselUtil.java 4341 2012-12-31 16:34:28Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.ModInteger; import edu.jas.arith.ModIntegerRing; import edu.jas.arith.ModLongRing; import edu.jas.arith.Modular; import edu.jas.arith.ModularRingFactory; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.Monomial; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.Power; /** * Hensel utilities for ufd. * @author Heinz Kredel */ public class HenselUtil { private static final Logger logger = Logger.getLogger(HenselUtil.class); private static final boolean debug = logger.isDebugEnabled(); /** * Modular Hensel lifting algorithm on coefficients. Let p = * A.ring.coFac.modul() = B.ring.coFac.modul() and assume C == A*B mod p * with gcd(A,B) == 1 mod p and S A + T B == 1 mod p. See Algorithm 6.1. in * Geddes et.al.. Linear version, as it does not lift S A + T B == 1 mod * p^{e+1}. * @param C GenPolynomial * @param A GenPolynomial * @param B other GenPolynomial * @param S GenPolynomial * @param T GenPolynomial * @param M bound on the coefficients of A1 and B1 as factors of C. * @return [A1,B1,Am,Bm] = lift(C,A,B), with C = A1 * B1 mod p^e, Am = A1 * mod p^e, Bm = B1 mod p^e . */ @SuppressWarnings("unchecked") public static & Modular> HenselApprox liftHensel( GenPolynomial C, BigInteger M, GenPolynomial A, GenPolynomial B, GenPolynomial S, GenPolynomial T) throws NoLiftingException { if (C == null || C.isZERO()) { return new HenselApprox(C, C, A, B); } if (A == null || A.isZERO() || B == null || B.isZERO()) { throw new IllegalArgumentException("A and B must be nonzero"); } GenPolynomialRing fac = C.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } // setup factories GenPolynomialRing pfac = A.ring; RingFactory p = pfac.coFac; RingFactory q = p; ModularRingFactory P = (ModularRingFactory) p; ModularRingFactory Q = (ModularRingFactory) q; BigInteger Qi = Q.getIntegerModul(); BigInteger M2 = M.multiply(M.fromInteger(2)); BigInteger Mq = Qi; // normalize c and a, b factors, assert p is prime GenPolynomial Ai; GenPolynomial Bi; BigInteger c = C.leadingBaseCoefficient(); C = C.multiply(c); // sic MOD a = A.leadingBaseCoefficient(); if (!a.isONE()) { // A = A.monic(); A = A.divide(a); S = S.multiply(a); } MOD b = B.leadingBaseCoefficient(); if (!b.isONE()) { // B = B.monic(); B = B.divide(b); T = T.multiply(b); } MOD cm = P.fromInteger(c.getVal()); A = A.multiply(cm); B = B.multiply(cm); T = T.divide(cm); S = S.divide(cm); Ai = PolyUtil.integerFromModularCoefficients(fac, A); Bi = PolyUtil.integerFromModularCoefficients(fac, B); // replace leading base coefficients ExpVector ea = Ai.leadingExpVector(); ExpVector eb = Bi.leadingExpVector(); Ai.doPutToMap(ea, c); Bi.doPutToMap(eb, c); // polynomials mod p GenPolynomial Ap; GenPolynomial Bp; GenPolynomial A1p = A; GenPolynomial B1p = B; GenPolynomial Ep; // polynomials over the integers GenPolynomial E; GenPolynomial Ea; GenPolynomial Eb; GenPolynomial Ea1; GenPolynomial Eb1; while (Mq.compareTo(M2) < 0) { // compute E=(C-AB)/q over the integers E = C.subtract(Ai.multiply(Bi)); if (E.isZERO()) { logger.info("leaving on zero E"); break; } try { E = E.divide(Qi); } catch (RuntimeException e) { // useful in debuging //System.out.println("C = " + C ); //System.out.println("Ai = " + Ai ); //System.out.println("Bi = " + Bi ); //System.out.println("E = " + E ); //System.out.println("Qi = " + Qi ); throw e; } // E mod p Ep = PolyUtil. fromIntegerCoefficients(pfac, E); //logger.info("Ep = " + Ep); // construct approximation mod p Ap = S.multiply(Ep); // S,T ++ T,S Bp = T.multiply(Ep); GenPolynomial[] QR; QR = Ap.quotientRemainder(B); GenPolynomial Qp; GenPolynomial Rp; Qp = QR[0]; Rp = QR[1]; A1p = Rp; B1p = Bp.sum(A.multiply(Qp)); // construct q-adic approximation, convert to integer Ea = PolyUtil.integerFromModularCoefficients(fac, A1p); Eb = PolyUtil.integerFromModularCoefficients(fac, B1p); Ea1 = Ea.multiply(Qi); Eb1 = Eb.multiply(Qi); Ea = Ai.sum(Eb1); // Eb1 and Ea1 are required Eb = Bi.sum(Ea1); //-------------------------- assert (Ea.degree(0) + Eb.degree(0) <= C.degree(0)); //if ( Ea.degree(0)+Eb.degree(0) > C.degree(0) ) { // debug // throw new RuntimeException("deg(A)+deg(B) > deg(C)"); //} // prepare for next iteration Mq = Qi; Qi = Q.getIntegerModul().multiply(P.getIntegerModul()); // Q = new ModIntegerRing(Qi.getVal()); if (ModLongRing.MAX_LONG.compareTo(Qi.getVal()) > 0) { Q = (ModularRingFactory) new ModLongRing(Qi.getVal()); } else { Q = (ModularRingFactory) new ModIntegerRing(Qi.getVal()); } Ai = Ea; Bi = Eb; } GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); // remove normalization BigInteger ai = ufd.baseContent(Ai); Ai = Ai.divide(ai); BigInteger bi = null; try { bi = c.divide(ai); Bi = Bi.divide(bi); // divide( c/a ) } catch (RuntimeException e) { //System.out.println("C = " + C ); //System.out.println("Ai = " + Ai ); //System.out.println("Bi = " + Bi ); //System.out.println("c = " + c ); //System.out.println("ai = " + ai ); //System.out.println("bi = " + bi ); //System.out.println("no exact lifting possible " + e); throw new NoLiftingException("no exact lifting possible " + e); } return new HenselApprox(Ai, Bi, A1p, B1p); } /** * Modular Hensel lifting algorithm on coefficients. Let p = * A.ring.coFac.modul() = B.ring.coFac.modul() and assume C == A*B mod p * with gcd(A,B) == 1 mod p. See algorithm 6.1. in Geddes et.al. and * algorithms 3.5.{5,6} in Cohen. * @param C GenPolynomial * @param A GenPolynomial * @param B other GenPolynomial * @param M bound on the coefficients of A1 and B1 as factors of C. * @return [A1,B1] = lift(C,A,B), with C = A1 * B1. */ @SuppressWarnings("unchecked") public static & Modular> HenselApprox liftHensel( GenPolynomial C, BigInteger M, GenPolynomial A, GenPolynomial B) throws NoLiftingException { if (C == null || C.isZERO()) { return new HenselApprox(C, C, A, B); } if (A == null || A.isZERO() || B == null || B.isZERO()) { throw new IllegalArgumentException("A and B must be nonzero"); } GenPolynomialRing fac = C.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } // one Hensel step on part polynomials try { GenPolynomial[] gst = A.egcd(B); if (!gst[0].isONE()) { throw new NoLiftingException("A and B not coprime, gcd = " + gst[0] + ", A = " + A + ", B = " + B); } GenPolynomial s = gst[1]; GenPolynomial t = gst[2]; HenselApprox ab = HenselUtil. liftHensel(C, M, A, B, s, t); return ab; } catch (ArithmeticException e) { throw new NoLiftingException("coefficient error " + e); } } /** * Modular quadratic Hensel lifting algorithm on coefficients. Let p = * A.ring.coFac.modul() = B.ring.coFac.modul() and assume C == A*B mod p * with gcd(A,B) == 1 mod p and S A + T B == 1 mod p. See algorithm 6.1. in * Geddes et.al. and algorithms 3.5.{5,6} in Cohen. Quadratic version, as it * also lifts S A + T B == 1 mod p^{e+1}. * @param C GenPolynomial * @param A GenPolynomial * @param B other GenPolynomial * @param S GenPolynomial * @param T GenPolynomial * @param M bound on the coefficients of A1 and B1 as factors of C. * @return [A1,B1] = lift(C,A,B), with C = A1 * B1. */ @SuppressWarnings("unchecked") public static & Modular> HenselApprox liftHenselQuadratic( GenPolynomial C, BigInteger M, GenPolynomial A, GenPolynomial B, GenPolynomial S, GenPolynomial T) throws NoLiftingException { if (C == null || C.isZERO()) { return new HenselApprox(C, C, A, B); } if (A == null || A.isZERO() || B == null || B.isZERO()) { throw new IllegalArgumentException("A and B must be nonzero"); } GenPolynomialRing fac = C.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } // setup factories GenPolynomialRing pfac = A.ring; RingFactory p = pfac.coFac; RingFactory q = p; ModularRingFactory P = (ModularRingFactory) p; ModularRingFactory Q = (ModularRingFactory) q; BigInteger Qi = Q.getIntegerModul(); BigInteger M2 = M.multiply(M.fromInteger(2)); BigInteger Mq = Qi; GenPolynomialRing qfac; qfac = new GenPolynomialRing(Q, pfac); // normalize c and a, b factors, assert p is prime GenPolynomial Ai; GenPolynomial Bi; BigInteger c = C.leadingBaseCoefficient(); C = C.multiply(c); // sic MOD a = A.leadingBaseCoefficient(); if (!a.isONE()) { // A = A.monic(); A = A.divide(a); S = S.multiply(a); } MOD b = B.leadingBaseCoefficient(); if (!b.isONE()) { // B = B.monic(); B = B.divide(b); T = T.multiply(b); } MOD cm = P.fromInteger(c.getVal()); A = A.multiply(cm); B = B.multiply(cm); T = T.divide(cm); S = S.divide(cm); Ai = PolyUtil.integerFromModularCoefficients(fac, A); Bi = PolyUtil.integerFromModularCoefficients(fac, B); // replace leading base coefficients ExpVector ea = Ai.leadingExpVector(); ExpVector eb = Bi.leadingExpVector(); Ai.doPutToMap(ea, c); Bi.doPutToMap(eb, c); // polynomials mod p GenPolynomial Ap; GenPolynomial Bp; GenPolynomial A1p = A; GenPolynomial B1p = B; GenPolynomial Ep; GenPolynomial Sp = S; GenPolynomial Tp = T; // polynomials mod q GenPolynomial Aq; GenPolynomial Bq; GenPolynomial Eq; // polynomials over the integers GenPolynomial E; GenPolynomial Ea; GenPolynomial Eb; GenPolynomial Ea1; GenPolynomial Eb1; GenPolynomial Si; GenPolynomial Ti; Si = PolyUtil.integerFromModularCoefficients(fac, S); Ti = PolyUtil.integerFromModularCoefficients(fac, T); Aq = PolyUtil. fromIntegerCoefficients(qfac, Ai); Bq = PolyUtil. fromIntegerCoefficients(qfac, Bi); while (Mq.compareTo(M2) < 0) { // compute E=(C-AB)/q over the integers E = C.subtract(Ai.multiply(Bi)); if (E.isZERO()) { logger.info("leaving on zero E"); break; } E = E.divide(Qi); // E mod p Ep = PolyUtil. fromIntegerCoefficients(qfac, E); //logger.info("Ep = " + Ep + ", qfac = " + qfac); //if (Ep.isZERO()) { //System.out.println("leaving on zero error"); //??logger.info("leaving on zero Ep"); //??break; //} // construct approximation mod p Ap = Sp.multiply(Ep); // S,T ++ T,S Bp = Tp.multiply(Ep); GenPolynomial[] QR; //logger.info("Ap = " + Ap + ", Bp = " + Bp + ", fac(Ap) = " + Ap.ring); QR = Ap.quotientRemainder(Bq); GenPolynomial Qp; GenPolynomial Rp; Qp = QR[0]; Rp = QR[1]; //logger.info("Qp = " + Qp + ", Rp = " + Rp); A1p = Rp; B1p = Bp.sum(Aq.multiply(Qp)); // construct q-adic approximation, convert to integer Ea = PolyUtil.integerFromModularCoefficients(fac, A1p); Eb = PolyUtil.integerFromModularCoefficients(fac, B1p); Ea1 = Ea.multiply(Qi); Eb1 = Eb.multiply(Qi); Ea = Ai.sum(Eb1); // Eb1 and Ea1 are required Eb = Bi.sum(Ea1); //-------------------------- assert (Ea.degree(0) + Eb.degree(0) <= C.degree(0)); //if ( Ea.degree(0)+Eb.degree(0) > C.degree(0) ) { // debug // throw new RuntimeException("deg(A)+deg(B) > deg(C)"); //} Ai = Ea; Bi = Eb; // gcd representation factors error -------------------------------- // compute E=(1-SA-TB)/q over the integers E = fac.getONE(); E = E.subtract(Si.multiply(Ai)).subtract(Ti.multiply(Bi)); E = E.divide(Qi); // E mod q Ep = PolyUtil. fromIntegerCoefficients(qfac, E); //logger.info("Ep2 = " + Ep); // construct approximation mod q Ap = Sp.multiply(Ep); // S,T ++ T,S Bp = Tp.multiply(Ep); QR = Bp.quotientRemainder(Aq); // Ai == A mod p ? Qp = QR[0]; Rp = QR[1]; B1p = Rp; A1p = Ap.sum(Bq.multiply(Qp)); if (false && debug) { Eq = A1p.multiply(Aq).sum(B1p.multiply(Bq)).subtract(Ep); if (!Eq.isZERO()) { System.out.println("A*A1p+B*B1p-Ep2 != 0 " + Eq); throw new RuntimeException("A*A1p+B*B1p-Ep2 != 0 mod " + Q.getIntegerModul()); } } // construct q-adic approximation, convert to integer Ea = PolyUtil.integerFromModularCoefficients(fac, A1p); Eb = PolyUtil.integerFromModularCoefficients(fac, B1p); Ea1 = Ea.multiply(Qi); Eb1 = Eb.multiply(Qi); Ea = Si.sum(Ea1); // Eb1 and Ea1 are required Eb = Ti.sum(Eb1); //-------------------------- Si = Ea; Ti = Eb; // prepare for next iteration Mq = Qi; Qi = Q.getIntegerModul().multiply(Q.getIntegerModul()); if (ModLongRing.MAX_LONG.compareTo(Qi.getVal()) > 0) { Q = (ModularRingFactory) new ModLongRing(Qi.getVal()); } else { Q = (ModularRingFactory) new ModIntegerRing(Qi.getVal()); } //Q = new ModIntegerRing(Qi.getVal()); //System.out.println("Q = " + Q + ", from Q = " + Mq); qfac = new GenPolynomialRing(Q, pfac); Aq = PolyUtil. fromIntegerCoefficients(qfac, Ai); Bq = PolyUtil. fromIntegerCoefficients(qfac, Bi); Sp = PolyUtil. fromIntegerCoefficients(qfac, Si); Tp = PolyUtil. fromIntegerCoefficients(qfac, Ti); if (false && debug) { E = Ai.multiply(Si).sum(Bi.multiply(Ti)); Eq = PolyUtil. fromIntegerCoefficients(qfac, E); if (!Eq.isONE()) { System.out.println("Ai*Si+Bi*Ti=1 " + Eq); throw new RuntimeException("Ai*Si+Bi*Ti != 1 mod " + Q.getIntegerModul()); } } } GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); // remove normalization if possible BigInteger ai = ufd.baseContent(Ai); Ai = Ai.divide(ai); BigInteger bi = null; try { bi = c.divide(ai); Bi = Bi.divide(bi); // divide( c/a ) } catch (RuntimeException e) { //System.out.println("C = " + C ); //System.out.println("Ai = " + Ai ); //System.out.println("Bi = " + Bi ); //System.out.println("c = " + c ); //System.out.println("ai = " + ai ); //System.out.println("bi = " + bi ); //System.out.println("no exact lifting possible " + e); throw new NoLiftingException("no exact lifting possible " + e); } return new HenselApprox(Ai, Bi, A1p, B1p); } /** * Modular quadratic Hensel lifting algorithm on coefficients. Let p = * A.ring.coFac.modul() = B.ring.coFac.modul() and assume C == A*B mod p * with gcd(A,B) == 1 mod p. See algorithm 6.1. in Geddes et.al. and * algorithms 3.5.{5,6} in Cohen. Quadratic version. * @param C GenPolynomial * @param A GenPolynomial * @param B other GenPolynomial * @param M bound on the coefficients of A1 and B1 as factors of C. * @return [A1,B1] = lift(C,A,B), with C = A1 * B1. */ @SuppressWarnings("unchecked") public static & Modular> HenselApprox liftHenselQuadratic( GenPolynomial C, BigInteger M, GenPolynomial A, GenPolynomial B) throws NoLiftingException { if (C == null || C.isZERO()) { return new HenselApprox(C, C, A, B); } if (A == null || A.isZERO() || B == null || B.isZERO()) { throw new IllegalArgumentException("A and B must be nonzero"); } GenPolynomialRing fac = C.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } // one Hensel step on part polynomials try { GenPolynomial[] gst = A.egcd(B); if (!gst[0].isONE()) { throw new NoLiftingException("A and B not coprime, gcd = " + gst[0] + ", A = " + A + ", B = " + B); } GenPolynomial s = gst[1]; GenPolynomial t = gst[2]; HenselApprox ab = HenselUtil. liftHenselQuadratic(C, M, A, B, s, t); return ab; } catch (ArithmeticException e) { throw new NoLiftingException("coefficient error " + e); } } /** * Modular Hensel lifting algorithm on coefficients. Let p = * A.ring.coFac.modul() = B.ring.coFac.modul() and assume C == A*B mod p * with gcd(A,B) == 1 mod p. See algorithm 6.1. in Geddes et.al. and * algorithms 3.5.{5,6} in Cohen. Quadratic version. * @param C GenPolynomial * @param A GenPolynomial * @param B other GenPolynomial * @param M bound on the coefficients of A1 and B1 as factors of C. * @return [A1,B1] = lift(C,A,B), with C = A1 * B1. */ @SuppressWarnings("unchecked") public static & Modular> HenselApprox liftHenselQuadraticFac( GenPolynomial C, BigInteger M, GenPolynomial A, GenPolynomial B) throws NoLiftingException { if (C == null || C.isZERO()) { throw new IllegalArgumentException("C must be nonzero"); } if (A == null || A.isZERO() || B == null || B.isZERO()) { throw new IllegalArgumentException("A and B must be nonzero"); } GenPolynomialRing fac = C.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } // one Hensel step on part polynomials try { GenPolynomial[] gst = A.egcd(B); if (!gst[0].isONE()) { throw new NoLiftingException("A and B not coprime, gcd = " + gst[0] + ", A = " + A + ", B = " + B); } GenPolynomial s = gst[1]; GenPolynomial t = gst[2]; HenselApprox ab = HenselUtil. liftHenselQuadraticFac(C, M, A, B, s, t); return ab; } catch (ArithmeticException e) { throw new NoLiftingException("coefficient error " + e); } } /** * Modular Hensel lifting algorithm on coefficients. Let p = * A.ring.coFac.modul() = B.ring.coFac.modul() and assume C == A*B mod p * with gcd(A,B) == 1 mod p and S A + T B == 1 mod p. See algorithm 6.1. in * Geddes et.al. and algorithms 3.5.{5,6} in Cohen. Quadratic version, as it * also lifts S A + T B == 1 mod p^{e+1}. * @param C primitive GenPolynomial * @param A GenPolynomial * @param B other GenPolynomial * @param S GenPolynomial * @param T GenPolynomial * @param M bound on the coefficients of A1 and B1 as factors of C. * @return [A1,B1] = lift(C,A,B), with C = A1 * B1. */ @SuppressWarnings("unchecked") public static & Modular> HenselApprox liftHenselQuadraticFac( GenPolynomial C, BigInteger M, GenPolynomial A, GenPolynomial B, GenPolynomial S, GenPolynomial T) throws NoLiftingException { //System.out.println("*** version for factorization *** "); //GenPolynomial[] AB = new GenPolynomial[2]; if (C == null || C.isZERO()) { throw new IllegalArgumentException("C must be nonzero"); } if (A == null || A.isZERO() || B == null || B.isZERO()) { throw new IllegalArgumentException("A and B must be nonzero"); } GenPolynomialRing fac = C.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } // setup factories GenPolynomialRing pfac = A.ring; RingFactory p = pfac.coFac; RingFactory q = p; ModularRingFactory P = (ModularRingFactory) p; ModularRingFactory Q = (ModularRingFactory) q; BigInteger PP = Q.getIntegerModul(); BigInteger Qi = PP; BigInteger M2 = M.multiply(M.fromInteger(2)); if (debug) { //System.out.println("M2 = " + M2); logger.debug("M2 = " + M2); } BigInteger Mq = Qi; GenPolynomialRing qfac; qfac = new GenPolynomialRing(Q, pfac); // mod p GenPolynomialRing mfac; BigInteger Mi = Q.getIntegerModul().multiply(Q.getIntegerModul()); ModularRingFactory Qmm; // = new ModIntegerRing(Mi.getVal()); if (ModLongRing.MAX_LONG.compareTo(Mi.getVal()) > 0) { Qmm = (ModularRingFactory) new ModLongRing(Mi.getVal()); } else { Qmm = (ModularRingFactory) new ModIntegerRing(Mi.getVal()); } mfac = new GenPolynomialRing(Qmm, qfac); // mod p^e MOD Qm = Qmm.fromInteger(Qi.getVal()); // partly normalize c and a, b factors, assert p is prime GenPolynomial Ai; GenPolynomial Bi; BigInteger c = C.leadingBaseCoefficient(); C = C.multiply(c); // sic MOD a = A.leadingBaseCoefficient(); if (!a.isONE()) { // A = A.monic(); A = A.divide(a); S = S.multiply(a); } MOD b = B.leadingBaseCoefficient(); if (!b.isONE()) { // B = B.monic(); B = B.divide(b); T = T.multiply(b); } MOD cm = P.fromInteger(c.getVal()); if (cm.isZERO()) { System.out.println("c = " + c); System.out.println("P = " + P); throw new ArithmeticException("c mod p == 0 not meaningful"); } // mod p A = A.multiply(cm); S = S.divide(cm); B = B.multiply(cm); T = T.divide(cm); Ai = PolyUtil.integerFromModularCoefficients(fac, A); Bi = PolyUtil.integerFromModularCoefficients(fac, B); // replace leading base coefficients ExpVector ea = Ai.leadingExpVector(); ExpVector eb = Bi.leadingExpVector(); Ai.doPutToMap(ea, c); Bi.doPutToMap(eb, c); // polynomials mod p GenPolynomial Ap; GenPolynomial Bp; GenPolynomial A1p = A; GenPolynomial B1p = B; GenPolynomial Sp = S; GenPolynomial Tp = T; // polynomials mod q GenPolynomial Aq; GenPolynomial Bq; // polynomials mod p^e GenPolynomial Cm; GenPolynomial Am; GenPolynomial Bm; GenPolynomial Em; GenPolynomial Emp; GenPolynomial Sm; GenPolynomial Tm; GenPolynomial Ema; GenPolynomial Emb; GenPolynomial Ema1; GenPolynomial Emb1; // polynomials over the integers GenPolynomial Ei; GenPolynomial Si; GenPolynomial Ti; Si = PolyUtil.integerFromModularCoefficients(fac, S); Ti = PolyUtil.integerFromModularCoefficients(fac, T); Aq = PolyUtil. fromIntegerCoefficients(qfac, Ai); Bq = PolyUtil. fromIntegerCoefficients(qfac, Bi); // polynomials mod p^e Cm = PolyUtil. fromIntegerCoefficients(mfac, C); Am = PolyUtil. fromIntegerCoefficients(mfac, Ai); Bm = PolyUtil. fromIntegerCoefficients(mfac, Bi); Sm = PolyUtil. fromIntegerCoefficients(mfac, Si); Tm = PolyUtil. fromIntegerCoefficients(mfac, Ti); //System.out.println("Cm = " + Cm); //System.out.println("Am = " + Am); //System.out.println("Bm = " + Bm); //System.out.println("Ai = " + Ai); //System.out.println("Bi = " + Bi); //System.out.println("mfac = " + mfac); while (Mq.compareTo(M2) < 0) { // compute E=(C-AB)/p mod p^e if (debug) { //System.out.println("mfac = " + Cm.ring); logger.debug("mfac = " + Cm.ring); } Em = Cm.subtract(Am.multiply(Bm)); //System.out.println("Em = " + Em); if (Em.isZERO()) { if (C.subtract(Ai.multiply(Bi)).isZERO()) { logger.info("leaving on zero E"); break; } } // Em = Em.divide( Qm ); Ei = PolyUtil.integerFromModularCoefficients(fac, Em); Ei = Ei.divide(Qi); //System.out.println("Ei = " + Ei); // Ei mod p Emp = PolyUtil. fromIntegerCoefficients(qfac, Ei); // Emp = PolyUtil.fromIntegerCoefficients(qfac, // PolyUtil.integerFromModularCoefficients(fac,Em) ); //System.out.println("Emp = " + Emp); //logger.info("Emp = " + Emp); if (Emp.isZERO()) { if (C.subtract(Ai.multiply(Bi)).isZERO()) { logger.info("leaving on zero Emp"); break; } } // construct approximation mod p Ap = Sp.multiply(Emp); // S,T ++ T,S Bp = Tp.multiply(Emp); GenPolynomial[] QR = null; QR = Ap.quotientRemainder(Bq); // Bq ! GenPolynomial Qp = QR[0]; GenPolynomial Rp = QR[1]; A1p = Rp; B1p = Bp.sum(Aq.multiply(Qp)); // Aq ! //System.out.println("A1p = " + A1p); //System.out.println("B1p = " + B1p); // construct q-adic approximation Ema = PolyUtil. fromIntegerCoefficients(mfac, PolyUtil.integerFromModularCoefficients(fac, A1p)); Emb = PolyUtil. fromIntegerCoefficients(mfac, PolyUtil.integerFromModularCoefficients(fac, B1p)); //System.out.println("Ema = " + Ema); //System.out.println("Emb = " + Emb); Ema1 = Ema.multiply(Qm); Emb1 = Emb.multiply(Qm); Ema = Am.sum(Emb1); // Eb1 and Ea1 are required Emb = Bm.sum(Ema1); //-------------------------- assert (Ema.degree(0) + Emb.degree(0) <= Cm.degree(0)); //if ( Ema.degree(0)+Emb.degree(0) > Cm.degree(0) ) { // debug // throw new RuntimeException("deg(A)+deg(B) > deg(C)"); //} Am = Ema; Bm = Emb; Ai = PolyUtil.integerFromModularCoefficients(fac, Am); Bi = PolyUtil.integerFromModularCoefficients(fac, Bm); //System.out.println("Am = " + Am); //System.out.println("Bm = " + Bm); //System.out.println("Ai = " + Ai); //System.out.println("Bi = " + Bi + "\n"); // gcd representation factors error -------------------------------- // compute E=(1-SA-TB)/p mod p^e Em = mfac.getONE(); Em = Em.subtract(Sm.multiply(Am)).subtract(Tm.multiply(Bm)); //System.out.println("Em = " + Em); // Em = Em.divide( Pm ); Ei = PolyUtil.integerFromModularCoefficients(fac, Em); Ei = Ei.divide(Qi); //System.out.println("Ei = " + Ei); // Ei mod p Emp = PolyUtil. fromIntegerCoefficients(qfac, Ei); //Emp = PolyUtil.fromIntegerCoefficients(qfac, // PolyUtil.integerFromModularCoefficients(fac,Em) ); //System.out.println("Emp = " + Emp); // construct approximation mod p Ap = Sp.multiply(Emp); // S,T ++ T,S // Ep Eqp Bp = Tp.multiply(Emp); // Ep Eqp QR = Bp.quotientRemainder(Aq); // Ap Aq ! // Ai == A mod p ? Qp = QR[0]; Rp = QR[1]; B1p = Rp; A1p = Ap.sum(Bq.multiply(Qp)); //System.out.println("A1p = " + A1p); //System.out.println("B1p = " + B1p); // construct p^e-adic approximation Ema = PolyUtil. fromIntegerCoefficients(mfac, PolyUtil.integerFromModularCoefficients(fac, A1p)); Emb = PolyUtil. fromIntegerCoefficients(mfac, PolyUtil.integerFromModularCoefficients(fac, B1p)); Ema1 = Ema.multiply(Qm); Emb1 = Emb.multiply(Qm); Ema = Sm.sum(Ema1); // Emb1 and Ema1 are required Emb = Tm.sum(Emb1); //-------------------------- Sm = Ema; Tm = Emb; Si = PolyUtil.integerFromModularCoefficients(fac, Sm); Ti = PolyUtil.integerFromModularCoefficients(fac, Tm); //System.out.println("Sm = " + Sm); //System.out.println("Tm = " + Tm); //System.out.println("Si = " + Si); //System.out.println("Ti = " + Ti + "\n"); // prepare for next iteration Qi = Q.getIntegerModul().multiply(Q.getIntegerModul()); Mq = Qi; //lmfac = mfac; // Q = new ModIntegerRing(Qi.getVal()); if (ModLongRing.MAX_LONG.compareTo(Qi.getVal()) > 0) { Q = (ModularRingFactory) new ModLongRing(Qi.getVal()); } else { Q = (ModularRingFactory) new ModIntegerRing(Qi.getVal()); } qfac = new GenPolynomialRing(Q, pfac); BigInteger Qmmi = Qmm.getIntegerModul().multiply(Qmm.getIntegerModul()); //Qmm = new ModIntegerRing(Qmmi.getVal()); if (ModLongRing.MAX_LONG.compareTo(Qmmi.getVal()) > 0) { Qmm = (ModularRingFactory) new ModLongRing(Qmmi.getVal()); } else { Qmm = (ModularRingFactory) new ModIntegerRing(Qmmi.getVal()); } mfac = new GenPolynomialRing(Qmm, qfac); Qm = Qmm.fromInteger(Qi.getVal()); Cm = PolyUtil. fromIntegerCoefficients(mfac, C); Am = PolyUtil. fromIntegerCoefficients(mfac, Ai); Bm = PolyUtil. fromIntegerCoefficients(mfac, Bi); Sm = PolyUtil. fromIntegerCoefficients(mfac, Si); Tm = PolyUtil. fromIntegerCoefficients(mfac, Ti); assert (isHenselLift(C, Mi, PP, Ai, Bi)); Mi = Mi.fromInteger(Qmm.getIntegerModul().getVal()); Aq = PolyUtil. fromIntegerCoefficients(qfac, Ai); Bq = PolyUtil. fromIntegerCoefficients(qfac, Bi); Sp = PolyUtil. fromIntegerCoefficients(qfac, Si); Tp = PolyUtil. fromIntegerCoefficients(qfac, Ti); //System.out.println("Am = " + Am); //System.out.println("Bm = " + Bm); //System.out.println("Sm = " + Sm); //System.out.println("Tm = " + Tm); //System.out.println("mfac = " + mfac); //System.out.println("Qmm = " + Qmm + ", M2 = " + M2 + ", Mq = " + Mq + "\n"); } //System.out.println("*Ai = " + Ai); //System.out.println("*Bi = " + Bi); Em = Cm.subtract(Am.multiply(Bm)); if (!Em.isZERO()) { System.out.println("Em = " + Em); //throw new NoLiftingException("no exact lifting possible"); } // remove normalization not possible when not exact factorization GreatestCommonDivisorAbstract ufd = new GreatestCommonDivisorPrimitive(); // remove normalization if possible BigInteger ai = ufd.baseContent(Ai); Ai = Ai.divide(ai); // Ai=pp(Ai) BigInteger[] qr = c.quotientRemainder(ai); BigInteger bi = null; boolean exact = true; if (qr[1].isZERO()) { bi = qr[0]; try { Bi = Bi.divide(bi); // divide( c/a ) } catch (RuntimeException e) { System.out.println("*catch: no exact factorization: " + bi + ", e = " + e); exact = false; } } else { System.out.println("*remainder: no exact factorization: q = " + qr[0] + ", r = " + qr[1]); exact = false; } if (!exact) { System.out.println("*Ai = " + Ai); System.out.println("*ai = " + ai); System.out.println("*Bi = " + Bi); System.out.println("*bi = " + bi); System.out.println("*c = " + c); throw new NoLiftingException("no exact lifting possible"); } return new HenselApprox(Ai, Bi, Aq, Bq); } /** * Modular Hensel lifting test. Let p be a prime number and assume C == * prod_{0,...,n-1} g_i mod p with gcd(g_i,g_j) == 1 mod p for i != j. * @param C GenPolynomial * @param G = [g_0,...,g_{n-1}] list of GenPolynomial * @param M bound on the coefficients of g_i as factors of C. * @param p prime number. * @return true if C = prod_{0,...,n-1} g_i mod p^e, else false. */ public static// & Modular> boolean isHenselLift(GenPolynomial C, BigInteger M, BigInteger p, List> G) { if (C == null || C.isZERO()) { return false; } GenPolynomialRing pfac = C.ring; ModIntegerRing pm = new ModIntegerRing(p.getVal(), true); GenPolynomialRing mfac = new GenPolynomialRing(pm, pfac); // check mod p GenPolynomial cl = mfac.getONE(); GenPolynomial hlp; for (GenPolynomial hl : G) { //System.out.println("hl = " + hl); hlp = PolyUtil. fromIntegerCoefficients(mfac, hl); //System.out.println("hl mod p = " + hlp); cl = cl.multiply(hlp); } GenPolynomial cp = PolyUtil. fromIntegerCoefficients(mfac, C); if (!cp.equals(cl)) { System.out.println("Hensel precondition wrong!"); if (debug) { System.out.println("cl = " + cl); System.out.println("cp = " + cp); System.out.println("mon(cl) = " + cl.monic()); System.out.println("mon(cp) = " + cp.monic()); System.out.println("cp-cl = " + cp.subtract(cl)); System.out.println("M = " + M + ", p = " + p); } return false; } // check mod p^e BigInteger mip = p; while (mip.compareTo(M) < 0) { mip = mip.multiply(mip); // p } // mip = mip.multiply(p); pm = new ModIntegerRing(mip.getVal(), false); mfac = new GenPolynomialRing(pm, pfac); cl = mfac.getONE(); for (GenPolynomial hl : G) { //System.out.println("hl = " + hl); hlp = PolyUtil. fromIntegerCoefficients(mfac, hl); //System.out.println("hl mod p^e = " + hlp); cl = cl.multiply(hlp); } cp = PolyUtil. fromIntegerCoefficients(mfac, C); if (!cp.equals(cl)) { System.out.println("Hensel post condition wrong!"); System.out.println("cl = " + cl); System.out.println("cp = " + cp); System.out.println("cp-cl = " + cp.subtract(cl)); System.out.println("M = " + M + ", p = " + p + ", p^e = " + mip); return false; } return true; } /** * Modular Hensel lifting test. Let p be a prime number and assume C == A * * B mod p with gcd(A,B) == 1 mod p. * @param C GenPolynomial * @param A GenPolynomial * @param B GenPolynomial * @param M bound on the coefficients of A and B as factors of C. * @param p prime number. * @return true if C = A * B mod p**e, else false. */ public static// & Modular> boolean isHenselLift(GenPolynomial C, BigInteger M, BigInteger p, GenPolynomial A, GenPolynomial B) { List> G = new ArrayList>(2); G.add(A); G.add(B); return isHenselLift(C, M, p, G); } /** * Modular Hensel lifting test. Let p be a prime number and assume C == A * * B mod p with gcd(A,B) == 1 mod p. * @param C GenPolynomial * @param Ha Hensel approximation. * @param M bound on the coefficients of A and B as factors of C. * @param p prime number. * @return true if C = A * B mod p^e, else false. */ public static & Modular> boolean isHenselLift(GenPolynomial C, BigInteger M, BigInteger p, HenselApprox Ha) { List> G = new ArrayList>(2); G.add(Ha.A); G.add(Ha.B); return isHenselLift(C, M, p, G); } /** * Constructing and lifting algorithm for extended Euclidean relation. Let p * = A.ring.coFac.modul() and assume gcd(A,B) == 1 mod p. * @param A modular GenPolynomial * @param B modular GenPolynomial * @param k desired approximation exponent p^k. * @return [s,t] with s A + t B = 1 mod p^k. */ public static & Modular> GenPolynomial[] liftExtendedEuclidean( GenPolynomial A, GenPolynomial B, long k) throws NoLiftingException { if (A == null || A.isZERO() || B == null || B.isZERO()) { throw new IllegalArgumentException("A and B must be nonzero, A = " + A + ", B = " + B); } GenPolynomialRing fac = A.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } // start with extended Euclidean relation mod p GenPolynomial[] gst = null; try { gst = A.egcd(B); if (!gst[0].isONE()) { throw new NoLiftingException("A and B not coprime, gcd = " + gst[0] + ", A = " + A + ", B = " + B); } } catch (ArithmeticException e) { throw new NoLiftingException("coefficient error " + e); } GenPolynomial S = gst[1]; GenPolynomial T = gst[2]; //System.out.println("eeS = " + S + ": " + S.ring.coFac); //System.out.println("eeT = " + T + ": " + T.ring.coFac); // setup integer polynomial ring GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), fac); GenPolynomial one = ifac.getONE(); GenPolynomial Ai = PolyUtil.integerFromModularCoefficients(ifac, A); GenPolynomial Bi = PolyUtil.integerFromModularCoefficients(ifac, B); GenPolynomial Si = PolyUtil.integerFromModularCoefficients(ifac, S); GenPolynomial Ti = PolyUtil.integerFromModularCoefficients(ifac, T); //System.out.println("Ai = " + Ai); //System.out.println("Bi = " + Bi); //System.out.println("Si = " + Si); //System.out.println("Ti = " + Ti); // approximate mod p^i ModularRingFactory mcfac = (ModularRingFactory) fac.coFac; BigInteger p = mcfac.getIntegerModul(); BigInteger modul = p; GenPolynomialRing mfac; // = new GenPolynomialRing(mcfac, fac); for (int i = 1; i < k; i++) { // e = 1 - s a - t b in Z[x] GenPolynomial e = one.subtract(Si.multiply(Ai)).subtract(Ti.multiply(Bi)); //System.out.println("\ne = " + e); if (e.isZERO()) { logger.info("leaving on zero e in liftExtendedEuclidean"); break; } e = e.divide(modul); // move to Z_p[x] and compute next approximation GenPolynomial c = PolyUtil. fromIntegerCoefficients(fac, e); //System.out.println("c = " + c + ": " + c.ring.coFac); GenPolynomial s = S.multiply(c); GenPolynomial t = T.multiply(c); //System.out.println("s = " + s + ": " + s.ring.coFac); //System.out.println("t = " + t + ": " + t.ring.coFac); GenPolynomial[] QR = s.quotientRemainder(B); // watch for ordering GenPolynomial q = QR[0]; s = QR[1]; t = t.sum(q.multiply(A)); //System.out.println("s = " + s + ": " + s.ring.coFac); //System.out.println("t = " + t + ": " + t.ring.coFac); GenPolynomial si = PolyUtil.integerFromModularCoefficients(ifac, s); GenPolynomial ti = PolyUtil.integerFromModularCoefficients(ifac, t); //System.out.println("si = " + si); //System.out.println("ti = " + si); // add approximation to solution Si = Si.sum(si.multiply(modul)); Ti = Ti.sum(ti.multiply(modul)); //System.out.println("Si = " + Si); //System.out.println("Ti = " + Ti); modul = modul.multiply(p); //System.out.println("modul = " + modul + ", " + p + "^" + k + ", p^k = " + Power.power(new BigInteger(),p,k)); } //System.out.println("Si = " + Si + ", Ti = " + Ti); // setup ring mod p^i if (ModLongRing.MAX_LONG.compareTo(modul.getVal()) > 0) { mcfac = (ModularRingFactory) new ModLongRing(modul.getVal()); } else { mcfac = (ModularRingFactory) new ModIntegerRing(modul.getVal()); } //System.out.println("mcfac = " + mcfac); mfac = new GenPolynomialRing(mcfac, fac); S = PolyUtil. fromIntegerCoefficients(mfac, Si); T = PolyUtil. fromIntegerCoefficients(mfac, Ti); //System.out.println("S = " + S + ": " + S.ring.coFac); //System.out.println("T = " + T + ": " + T.ring.coFac); if ( true || debug ) { List> AP = new ArrayList>(); AP.add(B); AP.add(A); List> SP = new ArrayList>(); SP.add(S); SP.add(T); if ( !HenselUtil.isExtendedEuclideanLift(AP,SP) ) { System.out.println("isExtendedEuclideanLift: false"); } } GenPolynomial[] rel = (GenPolynomial[]) new GenPolynomial[2]; rel[0] = S; rel[1] = T; return rel; } /** * Constructing and lifting algorithm for extended Euclidean relation. Let p * = A_i.ring.coFac.modul() and assume gcd(A_i,A_j) == 1 mod p, i != j. * @param A list of modular GenPolynomials * @param k desired approximation exponent p^k. * @return [s_0,...,s_n-1] with sum_i s_i * B_i = 1 mod p^k, with B_i = * prod_{i!=j} A_j. */ public static & Modular> List> liftExtendedEuclidean( List> A, long k) throws NoLiftingException { if (A == null || A.size() == 0) { throw new IllegalArgumentException("A must be non null and non empty"); } GenPolynomialRing fac = A.get(0).ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } GenPolynomial zero = fac.getZERO(); int r = A.size(); List> Q = new ArrayList>(r); for (int i = 0; i < r; i++) { Q.add(zero); } //System.out.println("A = " + A); Q.set(r - 2, A.get(r - 1)); for (int j = r - 3; j >= 0; j--) { GenPolynomial q = A.get(j + 1).multiply(Q.get(j + 1)); Q.set(j, q); } //System.out.println("Q = " + Q); List> B = new ArrayList>(r + 1); List> lift = new ArrayList>(r); for (int i = 0; i < r; i++) { B.add(zero); lift.add(zero); } GenPolynomial one = fac.getONE(); GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), fac); B.add(0, one); //System.out.println("B(0) = " + B.get(0)); GenPolynomial b = one; for (int j = 0; j < r - 1; j++) { //System.out.println("Q("+(j)+") = " + Q.get(j)); //System.out.println("A("+(j)+") = " + A.get(j)); //System.out.println("B("+(j)+") = " + B.get(j)); List> S = liftDiophant(Q.get(j), A.get(j), B.get(j), k); //System.out.println("\nSb = " + S); b = S.get(0); GenPolynomial bb = PolyUtil. fromIntegerCoefficients(fac, PolyUtil .integerFromModularCoefficients(ifac, b)); B.set(j + 1, bb); lift.set(j, S.get(1)); //System.out.println("B("+(j+1)+") = " + B.get(j+1)); if (debug) { logger.info("lift(" + j + ") = " + lift.get(j)); } } //System.out.println("liftb = " + lift); lift.set(r - 1, b); if (debug) { logger.info("lift(" + (r - 1) + ") = " + b); } //System.out.println("B("+(r-1)+") = " + B.get(r-1) + " : " + B.get(r-1).ring.coFac + ", b = " + b + " : " + b.ring.coFac); //System.out.println("B = " + B); //System.out.println("liftb = " + lift); return lift; } /** * Modular diophantine equation solution and lifting algorithm. Let p = * A_i.ring.coFac.modul() and assume gcd(A,B) == 1 mod p. * @param A modular GenPolynomial, mod p^k * @param B modular GenPolynomial, mod p^k * @param C modular GenPolynomial, mod p^k * @param k desired approximation exponent p^k. * @return [s, t] with s A' + t B' = C mod p^k, with A' = B, B' = A. */ public static & Modular> List> liftDiophant( GenPolynomial A, GenPolynomial B, GenPolynomial C, long k) throws NoLiftingException { if (A == null || A.isZERO() || B == null || B.isZERO()) { throw new IllegalArgumentException("A and B must be nonzero, A = " + A + ", B = " + B + ", C = " + C); } List> sol = new ArrayList>(); GenPolynomialRing fac = C.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } //System.out.println("C = " + C); GenPolynomial zero = fac.getZERO(); for (int i = 0; i < 2; i++) { sol.add(zero); } GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(),fac); for (Monomial m : C) { //System.out.println("monomial = " + m); long e = m.e.getVal(0); List> S = liftDiophant(A, B, e, k); //System.out.println("Se = " + S); MOD a = m.c; //System.out.println("C.fac = " + fac.toScript()); a = fac.coFac.fromInteger(a.getSymmetricInteger().getVal()); int i = 0; for (GenPolynomial d : S) { //System.out.println("d = " + d); d = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, d)); d = d.multiply(a); d = sol.get(i).sum(d); //System.out.println("d = " + d); sol.set(i++, d); } //System.out.println("sol = " + sol + ", for " + m); } if (true || debug) { //GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), fac); A = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, A)); B = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, B)); C = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, C)); GenPolynomial y = B.multiply(sol.get(0)).sum(A.multiply(sol.get(1))); if (!y.equals(C)) { System.out.println("A = " + A + ", B = " + B); System.out.println("s1 = " + sol.get(0) + ", s2 = " + sol.get(1)); System.out.println("Error: A*r1 + B*r2 = " + y + " : " + fac.coFac); } } return sol; } /** * Modular diophantine equation solution and lifting algorithm. Let p = * A_i.ring.coFac.modul() and assume gcd(a,b) == 1 mod p, for a, b in A. * @param A list of modular GenPolynomials, mod p^k * @param C modular GenPolynomial, mod p^k * @param k desired approximation exponent p^k. * @return [s_1,..., s_n] with sum_i s_i A_i' = C mod p^k, with Ai' = prod_{j!=i} A_j. */ public static & Modular> List> liftDiophant( List> A, GenPolynomial C, long k) throws NoLiftingException { if ( false && A.size() <= 2 ) { return HenselUtil. liftDiophant(A.get(0),A.get(1),C,k); } List> sol = new ArrayList>(); GenPolynomialRing fac = C.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } //System.out.println("C = " + C); GenPolynomial zero = fac.getZERO(); for (int i = 0; i < A.size(); i++) { sol.add(zero); } GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(),fac); for (Monomial m : C) { //System.out.println("monomial = " + m); long e = m.e.getVal(0); List> S = liftDiophant(A, e, k); //System.out.println("Se = " + S); MOD a = m.c; //System.out.println("C.fac = " + fac.toScript()); a = fac.coFac.fromInteger(a.getSymmetricInteger().getVal()); int i = 0; for (GenPolynomial d : S) { //System.out.println("d = " + d); d = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, d)); d = d.multiply(a); d = sol.get(i).sum(d); //System.out.println("d = " + d); sol.set(i++, d); } //System.out.println("sol = " + sol + ", for " + m); } /* if (true || debug) { //GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), fac); A = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, A)); B = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, B)); C = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, C)); GenPolynomial y = B.multiply(sol.get(0)).sum(A.multiply(sol.get(1))); if (!y.equals(C)) { System.out.println("A = " + A + ", B = " + B); System.out.println("s1 = " + sol.get(0) + ", s2 = " + sol.get(1)); System.out.println("Error: A*r1 + B*r2 = " + y + " : " + fac.coFac); } } */ return sol; } /** * Modular diophantine equation solution and lifting algorithm. Let p = * A_i.ring.coFac.modul() and assume gcd(A,B) == 1 mod p. * @param A modular GenPolynomial * @param B modular GenPolynomial * @param e exponent for x^e * @param k desired approximation exponent p^k. * @return [s, t] with s A' + t B' = x^e mod p^k, with A' = B, B' = A. */ public static & Modular> List> liftDiophant( GenPolynomial A, GenPolynomial B, long e, long k) throws NoLiftingException { if (A == null || A.isZERO() || B == null || B.isZERO()) { throw new IllegalArgumentException("A and B must be nonzero, A = " + A + ", B = " + B); } List> sol = new ArrayList>(); GenPolynomialRing fac = A.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } // lift EE relation to p^k GenPolynomial[] lee = liftExtendedEuclidean(B,A, k); GenPolynomial s1 = lee[0]; GenPolynomial s2 = lee[1]; if ( e == 0L ) { sol.add(s1); sol.add(s2); //System.out.println("sol@0 = " + sol); return sol; } fac = s1.ring; GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), fac); A = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, A)); B = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, B)); // this is the wrong sequence: // GenPolynomial xe = fac.univariate(0,e); // GenPolynomial q = s1.multiply(xe); // GenPolynomial[] QR = q.quotientRemainder(B); // q = QR[0]; // GenPolynomial r1 = QR[1]; // GenPolynomial r2 = s2.multiply(xe).sum( q.multiply(A) ); GenPolynomial xe = fac.univariate(0, e); GenPolynomial q = s1.multiply(xe); GenPolynomial[] QR = q.quotientRemainder(A); q = QR[0]; //System.out.println("ee coeff qr = " + Arrays.toString(QR)); GenPolynomial r1 = QR[1]; GenPolynomial r2 = s2.multiply(xe).sum(q.multiply(B)); //System.out.println("r1 = " + r1 + ", r2 = " + r2); sol.add(r1); sol.add(r2); //System.out.println("sol@"+ e + " = " + sol); if (true || debug) { GenPolynomial y = B.multiply(r1).sum(A.multiply(r2)); if (!y.equals(xe)) { System.out.println("A = " + A + ", B = " + B); System.out.println("r1 = " + r1 + ", r2 = " + r2); System.out.println("Error: A*r1 + B*r2 = " + y); } } return sol; } /** * Modular diophantine equation solution and lifting algorithm. Let p = * A_i.ring.coFac.modul() and assume gcd(a,b) == 1 mod p, for a, b in A. * @param A list of modular GenPolynomials * @param e exponent for x^e * @param k desired approximation exponent p^k. * @return [s_1,..., s_n] with sum_i s_i A_i' = x^e mod p^k, with Ai' = prod_{j!=i} A_j. */ public static & Modular> List> liftDiophant( List> A, long e, long k) throws NoLiftingException { if ( false && A.size() <= 2 ) { return HenselUtil. liftDiophant(A.get(0),A.get(1),e,k); } List> sol = new ArrayList>(); GenPolynomialRing fac = A.get(0).ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } // lift EE relation to p^k List> lee = liftExtendedEuclidean(A, k); if ( e == 0L ) { //System.out.println("sol@0 = " + sol); return lee; } fac = lee.get(0).ring; GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), fac); List> S = new ArrayList>(lee.size()); for ( GenPolynomial a : lee ) { a = PolyUtil. fromIntegerCoefficients(fac, PolyUtil.integerFromModularCoefficients(ifac, a)); S.add(a); } GenPolynomial xe = fac.univariate(0, e); //List> Sr = new ArrayList>(lee.size()); int i = 0; for ( GenPolynomial s : S ) { GenPolynomial q = s.multiply(xe); GenPolynomial r = q.remainder(A.get(i++)); //System.out.println("r = " + r); sol.add(r); } //System.out.println("sol@"+ e + " = " + sol); /* if (true || debug) { GenPolynomial y = B.multiply(r1).sum(A.multiply(r2)); if (!y.equals(xe)) { System.out.println("A = " + A + ", B = " + B); System.out.println("r1 = " + r1 + ", r2 = " + r2); System.out.println("Error: A*r1 + B*r2 = " + y); } } */ return sol; } /** * Modular Diophant relation lifting test. * @param A modular GenPolynomial * @param B modular GenPolynomial * @param C modular GenPolynomial * @param S1 modular GenPolynomial * @param S2 modular GenPolynomial * @return true if A*S1 + B*S2 = C, else false. */ public static & Modular> boolean isDiophantLift( GenPolynomial A, GenPolynomial B, GenPolynomial S1, GenPolynomial S2, GenPolynomial C) { GenPolynomialRing fac = C.ring; GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(),fac); GenPolynomial a = PolyUtil. fromIntegerCoefficients(fac,PolyUtil.integerFromModularCoefficients(ifac,A)); GenPolynomial b = PolyUtil. fromIntegerCoefficients(fac,PolyUtil.integerFromModularCoefficients(ifac,B)); GenPolynomial s1 = PolyUtil. fromIntegerCoefficients(fac,PolyUtil.integerFromModularCoefficients(ifac,S1)); GenPolynomial s2 = PolyUtil. fromIntegerCoefficients(fac,PolyUtil.integerFromModularCoefficients(ifac,S2)); GenPolynomial t = a.multiply(s1).sum( b.multiply(s2) ); if ( t.equals(C) ) { return true; } if (debug) { System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("s1 = " + s1); System.out.println("s2 = " + s2); System.out.println("t = " + t); System.out.println("C = " + C); } return false; } /** * Modular extended Euclidean relation lifting test. * @param A list of GenPolynomials * @param S = [s_0,...,s_{n-1}] list of GenPolynomial * @return true if prod_{0,...,n-1} s_i * B_i = 1 mod p^e, with B_i = * prod_{i!=j} A_j, else false. */ public static & Modular> boolean isExtendedEuclideanLift( List> A, List> S) { GenPolynomialRing fac = A.get(0).ring; GenPolynomial C = fac.getONE(); return isDiophantLift(A,S,C); } /** * Modular Diophant relation lifting test. * @param A list of GenPolynomials * @param S = [s_0,...,s_{n-1}] list of GenPolynomials * @param C = GenPolynomial * @return true if prod_{0,...,n-1} s_i * B_i = C mod p^k, with B_i = * prod_{i!=j} A_j, else false. */ public static & Modular> boolean isDiophantLift( List> A, List> S, GenPolynomial C) { GenPolynomialRing fac = A.get(0).ring; GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(),fac); List> B = new ArrayList>(A.size()); int i = 0; for (GenPolynomial ai : A) { GenPolynomial b = fac.getONE(); int j = 0; for (GenPolynomial aj : A) { if (i != j /*!ai.equals(aj)*/) { b = b.multiply(aj); } j++; } //System.out.println("b = " + b); b = PolyUtil. fromIntegerCoefficients(fac,PolyUtil.integerFromModularCoefficients(ifac,b)); B.add(b); i++; } //System.out.println("B = " + B); // check mod p^e GenPolynomial t = fac.getZERO(); i = 0; for (GenPolynomial a : B) { GenPolynomial b = S.get(i++); b = PolyUtil. fromIntegerCoefficients(fac,PolyUtil.integerFromModularCoefficients(ifac,b)); GenPolynomial s = a.multiply(b); t = t.sum(s); } if (!t.equals(C)) { if (debug) { System.out.println("no diophant lift!"); System.out.println("A = " + A); System.out.println("B = " + B); System.out.println("S = " + S); System.out.println("C = " + C); System.out.println("t = " + t); } return false; } return true; } /** * Modular Hensel lifting algorithm on coefficients. Let p = * f_i.ring.coFac.modul() and assume C == prod_{0,...,n-1} f_i mod p with * gcd(f_i,f_j) == 1 mod p for i != j * @param C monic integer polynomial * @param F = [f_0,...,f_{n-1}] list of monic modular polynomials. * @param k approximation exponent. * @return [g_0,...,g_{n-1}] with C = prod_{0,...,n-1} g_i mod p^k. */ public static & Modular> List> liftHenselMonic(GenPolynomial C, List> F, long k) throws NoLiftingException { if (C == null || C.isZERO() || F == null || F.size() == 0) { throw new IllegalArgumentException("C must be nonzero and F must be nonempty"); } GenPolynomialRing fac = C.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } List> lift = new ArrayList>(F.size()); GenPolynomialRing pfac = F.get(0).ring; RingFactory pcfac = pfac.coFac; ModularRingFactory PF = (ModularRingFactory) pcfac; BigInteger P = PF.getIntegerModul(); int n = F.size(); if (n == 1) { // lift F_0, this case will probably never be used GenPolynomial f = F.get(0); ModularRingFactory mcfac; if (ModLongRing.MAX_LONG.compareTo(P.getVal()) > 0) { mcfac = (ModularRingFactory) new ModLongRing(P.getVal()); } else { mcfac = (ModularRingFactory) new ModIntegerRing(P.getVal()); } GenPolynomialRing mfac = new GenPolynomialRing(mcfac, fac); f = PolyUtil.fromIntegerCoefficients(mfac, PolyUtil.integerFromModularCoefficients(fac, f)); lift.add(f); return lift; } // if (n == 2) { // only one step // HenselApprox ab = HenselUtil. liftHenselQuadratic(C, M, F.get(0), F.get(1)); // lift.add(ab.Am); // lift.add(ab.Bm); // return lift; // } // setup integer polynomial ring GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), fac); List> Fi = PolyUtil.integerFromModularCoefficients(ifac, F); //System.out.println("Fi = " + Fi); List> S = liftExtendedEuclidean(F, k + 1); // lift works for any k, TODO: use this //System.out.println("Sext = " + S); if (true || debug) { logger.info("EE lift = " + S); // adjust coefficients List> Sx = PolyUtil.fromIntegerCoefficients(pfac, PolyUtil .integerFromModularCoefficients(ifac, S)); try { boolean il = HenselUtil. isExtendedEuclideanLift(F, Sx); //System.out.println("islift = " + il); } catch (RuntimeException e) { e.printStackTrace(); } } List> Si = PolyUtil.integerFromModularCoefficients(ifac, S); //System.out.println("Si = " + Si); //System.out.println("C = " + C); // approximate mod p^i ModularRingFactory mcfac = PF; BigInteger p = mcfac.getIntegerModul(); BigInteger modul = p; GenPolynomialRing mfac = new GenPolynomialRing(mcfac, fac); List> Sp = PolyUtil.fromIntegerCoefficients(mfac, Si); //System.out.println("Sp = " + Sp); for (int i = 1; i < k; i++) { //System.out.println("i = " + i); GenPolynomial e = fac.getONE(); for (GenPolynomial fi : Fi) { e = e.multiply(fi); } e = C.subtract(e); //System.out.println("\ne = " + e); if (e.isZERO()) { logger.info("leaving on zero e"); break; } try { e = e.divide(modul); } catch (RuntimeException ex) { ex.printStackTrace(); throw ex; } //System.out.println("e = " + e); // move to in Z_p[x] GenPolynomial c = PolyUtil. fromIntegerCoefficients(mfac, e); //System.out.println("c = " + c + ": " + c.ring.coFac); List> s = new ArrayList>(S.size()); int j = 0; for (GenPolynomial f : Sp) { f = f.multiply(c); //System.out.println("f = " + f + " : " + f.ring.coFac); //System.out.println("F,i = " + F.get(j) + " : " + F.get(j).ring.coFac); f = f.remainder(F.get(j++)); //System.out.println("f = " + f + " : " + f.ring.coFac); s.add(f); } //System.out.println("s = " + s); List> si = PolyUtil.integerFromModularCoefficients(ifac, s); //System.out.println("si = " + si); List> Fii = new ArrayList>(F.size()); j = 0; for (GenPolynomial f : Fi) { f = f.sum(si.get(j++).multiply(modul)); Fii.add(f); } //System.out.println("Fii = " + Fii); Fi = Fii; modul = modul.multiply(p); if (i >= k - 1) { logger.info("e != 0 for k = " + k); } } // setup ring mod p^k modul = Power.positivePower(p,k); if (ModLongRing.MAX_LONG.compareTo(modul.getVal()) > 0) { mcfac = (ModularRingFactory) new ModLongRing(modul.getVal()); } else { mcfac = (ModularRingFactory) new ModIntegerRing(modul.getVal()); } //System.out.println("mcfac = " + mcfac); mfac = new GenPolynomialRing(mcfac, fac); lift = PolyUtil. fromIntegerCoefficients(mfac, Fi); //System.out.println("lift = " + lift + ": " + lift.get(0).ring.coFac); return lift; } /** * Modular Hensel lifting algorithm on coefficients. Let p = * f_i.ring.coFac.modul() and assume C == prod_{0,...,n-1} f_i mod p with * gcd(f_i,f_j) == 1 mod p for i != j * @param C integer polynomial * @param F = [f_0,...,f_{n-1}] list of monic modular polynomials. * @param k approximation exponent. * @param g leading coefficient. * @return [g_0,...,g_{n-1}] with C = prod_{0,...,n-1} g_i mod p^k. */ public static & Modular> List> liftHensel(GenPolynomial C, List> F, long k, BigInteger g) throws NoLiftingException { if (C == null || C.isZERO() || F == null || F.size() == 0) { throw new IllegalArgumentException("C must be nonzero and F must be nonempty"); } GenPolynomialRing fac = C.ring; if (fac.nvar != 1) { // todo assert throw new IllegalArgumentException("polynomial ring not univariate"); } List> lift = new ArrayList>(F.size()); GenPolynomialRing pfac = F.get(0).ring; RingFactory pcfac = pfac.coFac; ModularRingFactory PF = (ModularRingFactory) pcfac; BigInteger P = PF.getIntegerModul(); int n = F.size(); if (n == 1) { // lift F_0, this case will probably never be used GenPolynomial f = F.get(0); ModularRingFactory mcfac; if (ModLongRing.MAX_LONG.compareTo(P.getVal()) > 0) { mcfac = (ModularRingFactory) new ModLongRing(P.getVal()); } else { mcfac = (ModularRingFactory) new ModIntegerRing(P.getVal()); } GenPolynomialRing mfac = new GenPolynomialRing(mcfac, fac); f = PolyUtil.fromIntegerCoefficients(mfac, PolyUtil.integerFromModularCoefficients(fac, f)); lift.add(f); return lift; } // if (n == 2) { // only one step // HenselApprox ab = HenselUtil. liftHenselQuadratic(C, M, F.get(0), F.get(1)); // lift.add(ab.Am); // lift.add(ab.Bm); // return lift; // } // normalize C and F_i factors BigInteger cc = g; //C.leadingBaseCoefficient(); // == g ?? for ( int i = 1; i < F.size(); i++ ) { // #F-1 C = C.multiply(cc); // sic } MOD cm = PF.fromInteger(cc.getVal()); List> Fp = new ArrayList>(F.size()); for ( GenPolynomial fm : F ) { GenPolynomial am = fm.monic(); am = am.multiply(cm); Fp.add(am); } F = Fp; // setup integer polynomial ring GenPolynomialRing ifac = new GenPolynomialRing(new BigInteger(), fac); List> Fi = PolyUtil.integerFromModularCoefficients(ifac, F); //System.out.println("Fi = " + Fi); // inplace modify polynomials, replace leading coefficient for ( GenPolynomial ai : Fi ) { if ( ai.isZERO() ) { continue; } ExpVector ea = ai.leadingExpVector(); ai.doPutToMap(ea, cc); } //System.out.println("Fi = " + Fi); List> S = liftExtendedEuclidean(F, k + 1); // lift works for any k, TODO: use this //System.out.println("Sext = " + S); if (true || debug) { logger.info("EE lift = " + S); // adjust coefficients List> Sx = PolyUtil.fromIntegerCoefficients(pfac, PolyUtil .integerFromModularCoefficients(ifac, S)); try { boolean il = HenselUtil. isExtendedEuclideanLift(F, Sx); //System.out.println("islift = " + il); } catch (RuntimeException e) { e.printStackTrace(); } } List> Si = PolyUtil.integerFromModularCoefficients(ifac, S); //System.out.println("Si = " + Si); //System.out.println("C = " + C); // approximate mod p^i ModularRingFactory mcfac = PF; BigInteger p = mcfac.getIntegerModul(); BigInteger modul = p; GenPolynomialRing mfac = new GenPolynomialRing(mcfac, fac); List> Sp = PolyUtil.fromIntegerCoefficients(mfac, Si); //System.out.println("Sp = " + Sp); for (int i = 1; i < k; i++) { //System.out.println("i = " + i); GenPolynomial e = fac.getONE(); for (GenPolynomial fi : Fi) { e = e.multiply(fi); } e = C.subtract(e); //System.out.println("\ne = " + e); if (e.isZERO()) { logger.info("leaving on zero e"); break; } try { e = e.divide(modul); } catch (RuntimeException ex) { ex.printStackTrace(); throw ex; } //System.out.println("e = " + e); // move to in Z_p[x] GenPolynomial c = PolyUtil. fromIntegerCoefficients(mfac, e); //System.out.println("c = " + c + ": " + c.ring.coFac); List> s = new ArrayList>(S.size()); int j = 0; for (GenPolynomial f : Sp) { f = f.multiply(c); //System.out.println("f = " + f + " : " + f.ring.coFac); //System.out.println("F,i = " + F.get(j) + " : " + F.get(j).ring.coFac); f = f.remainder(F.get(j++)); //System.out.println("f = " + f + " : " + f.ring.coFac); s.add(f); } //System.out.println("s = " + s); List> si = PolyUtil.integerFromModularCoefficients(ifac, s); //System.out.println("si = " + si); List> Fii = new ArrayList>(F.size()); j = 0; for (GenPolynomial f : Fi) { f = f.sum(si.get(j++).multiply(modul)); Fii.add(f); } //System.out.println("Fii = " + Fii); Fi = Fii; modul = modul.multiply(p); if (i >= k - 1) { logger.info("e != 0 for k = " + k); } } //System.out.println("Fi = " + Fi); // remove normalization GreatestCommonDivisorAbstract ufd = GCDFactory.getImplementation(cc); //BigInteger ai = ufd.baseContent(Fi.get(0)); //System.out.println("ai = " + ai + ", cc = " + cc); List> Fii = new ArrayList>(F.size()); //int j = 0; for ( GenPolynomial bi : Fi ) { GenPolynomial ci = null; //if ( j++ == 0 ) { // ci = bi.divide(ai); //} else { // BigInteger i = cc.divide(ai); // ci = bi.divide(i); //} ci = ufd.basePrimitivePart(bi); // ?? //System.out.println("bi = " + bi + ", ci = " + ci); Fii.add(ci); } Fi = Fii; // setup ring mod p^k modul = Power.positivePower(p,k); if (ModLongRing.MAX_LONG.compareTo(modul.getVal()) > 0) { mcfac = (ModularRingFactory) new ModLongRing(modul.getVal()); } else { mcfac = (ModularRingFactory) new ModIntegerRing(modul.getVal()); } //System.out.println("mcfac = " + mcfac); mfac = new GenPolynomialRing(mcfac, fac); lift = PolyUtil. fromIntegerCoefficients(mfac, Fi); //System.out.println("lift = " + lift + ": " + lift.get(0).ring.coFac); return lift; } } jas-2.5/src/edu/jas/ufd/GreatestCommonDivisorSubres.java0000644000175000017500000003302012003277306023556 0ustar giovannigiovanni/* * $Id: GreatestCommonDivisorSubres.java 4025 2012-07-23 16:41:43Z kredel $ */ package edu.jas.ufd; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; /** * Greatest common divisor algorithms with subresultant polynomial remainder * sequence. * @author Heinz Kredel */ public class GreatestCommonDivisorSubres> extends GreatestCommonDivisorAbstract { private static final Logger logger = Logger.getLogger(GreatestCommonDivisorSubres.class); private boolean debug = logger.isDebugEnabled(); /** * GenPolynomial pseudo remainder. For univariate polynomials. * @param P GenPolynomial. * @param S nonzero GenPolynomial. * @return remainder with ldcf(S)m P = quotient * S + remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). * @deprecated Use {@link * edu.jas.poly.PolyUtil#baseDensePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)} * instead */ @Deprecated public GenPolynomial basePseudoRemainder(GenPolynomial P, GenPolynomial S) { return PolyUtil. baseDensePseudoRemainder(P, S); } /** * GenPolynomial pseudo remainder. For recursive polynomials. * @param P recursive GenPolynomial. * @param S nonzero recursive GenPolynomial. * @return remainder with ldcf(S)m P = quotient * S + remainder. * @see edu.jas.poly.GenPolynomial#remainder(edu.jas.poly.GenPolynomial). * @deprecated Use {@link * edu.jas.poly.PolyUtil#recursiveDensePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial)} instead */ @Deprecated public GenPolynomial> recursivePseudoRemainder(GenPolynomial> P, GenPolynomial> S) { return PolyUtil. recursiveDensePseudoRemainder(P, S); } /** * Univariate GenPolynomial greatest comon divisor. Uses pseudoRemainder for * remainder. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial baseGcd(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } if (P.ring.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); } long e = P.degree(0); long f = S.degree(0); GenPolynomial q; GenPolynomial r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } r = r.abs(); q = q.abs(); C a = baseContent(r); C b = baseContent(q); C c = gcd(a, b); // indirection r = divide(r, a); // indirection q = divide(q, b); // indirection if (r.isONE()) { return r.multiply(c); } if (q.isONE()) { return q.multiply(c); } C g = r.ring.getONECoefficient(); C h = r.ring.getONECoefficient(); GenPolynomial x; C z; while (!r.isZERO()) { long delta = q.degree(0) - r.degree(0); //System.out.println("delta = " + delta); x = PolyUtil. baseDensePseudoRemainder(q, r); q = r; if (!x.isZERO()) { z = g.multiply(power(P.ring.coFac, h, delta)); //System.out.println("z = " + z); r = x.divide(z); g = q.leadingBaseCoefficient(); z = power(P.ring.coFac, g, delta); h = z.divide(power(P.ring.coFac, h, delta - 1)); //System.out.println("g = " + g); //System.out.println("h = " + h); } else { r = x; } } q = basePrimitivePart(q); return (q.multiply(c)).abs(); } /** * Univariate GenPolynomial recursive greatest comon divisor. Uses * pseudoRemainder for remainder. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial> recursiveUnivariateGcd(GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } if (P.ring.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); } long e = P.degree(0); long f = S.degree(0); GenPolynomial> q; GenPolynomial> r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } r = r.abs(); q = q.abs(); GenPolynomial a = recursiveContent(r); GenPolynomial b = recursiveContent(q); GenPolynomial c = gcd(a, b); // go to recursion //System.out.println("rgcd c = " + c); r = PolyUtil. recursiveDivide(r, a); q = PolyUtil. recursiveDivide(q, b); if (r.isONE()) { return r.multiply(c); } if (q.isONE()) { return q.multiply(c); } GenPolynomial g = r.ring.getONECoefficient(); GenPolynomial h = r.ring.getONECoefficient(); GenPolynomial> x; GenPolynomial z = null; while (!r.isZERO()) { long delta = q.degree(0) - r.degree(0); //System.out.println("rgcd delta = " + delta); x = PolyUtil. recursiveDensePseudoRemainder(q, r); q = r; if (!x.isZERO()) { z = g.multiply(power(P.ring.coFac, h, delta)); r = PolyUtil. recursiveDivide(x, z); g = q.leadingBaseCoefficient(); z = power(P.ring.coFac, g, delta); h = PolyUtil. basePseudoDivide(z, power(P.ring.coFac, h, delta - 1)); } else { r = x; } } q = recursivePrimitivePart(q); return q.abs().multiply(c); //.abs(); } /** * Univariate GenPolynomial resultant. Uses pseudoRemainder for remainder. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial baseResultant(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } if (P.ring.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); } long e = P.degree(0); long f = S.degree(0); GenPolynomial q; GenPolynomial r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } //r = r.abs(); //q = q.abs(); C a = baseContent(r); C b = baseContent(q); r = divide(r, a); // indirection q = divide(q, b); // indirection RingFactory cofac = P.ring.coFac; C g = cofac.getONE(); C h = cofac.getONE(); C t = power(cofac, a, e); t = t.multiply(power(cofac, b, f)); long s = 1; GenPolynomial x; C z; while (r.degree(0) > 0) { long delta = q.degree(0) - r.degree(0); //System.out.println("delta = " + delta); if ((q.degree(0) % 2 != 0) && (r.degree(0) % 2 != 0)) { s = -s; } x = PolyUtil. baseDensePseudoRemainder(q, r); //System.out.println("x = " + x); q = r; if (x.degree(0) > 0) { z = g.multiply(power(cofac, h, delta)); //System.out.println("z = " + z); r = x.divide(z); g = q.leadingBaseCoefficient(); z = power(cofac, g, delta); h = z.divide(power(cofac, h, delta - 1)); } else { r = x; } } z = power(cofac, r.leadingBaseCoefficient(), q.degree(0)); h = z.divide(power(cofac, h, q.degree(0) - 1)); z = h.multiply(t); if ( s < 0 ) { z = z.negate(); } x = P.ring.getONE().multiply(z); return x; } /** * Univariate GenPolynomial recursive resultant. Uses pseudoRemainder for * remainder. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial> recursiveUnivariateResultant(GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } if (P.ring.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); } long e = P.degree(0); long f = S.degree(0); GenPolynomial> q; GenPolynomial> r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } r = r.abs(); q = q.abs(); GenPolynomial a = recursiveContent(r); GenPolynomial b = recursiveContent(q); r = PolyUtil. recursiveDivide(r, a); q = PolyUtil. recursiveDivide(q, b); RingFactory> cofac = P.ring.coFac; GenPolynomial g = cofac.getONE(); GenPolynomial h = cofac.getONE(); GenPolynomial> x; GenPolynomial t; if (f == 0 && e == 0 && g.ring.nvar > 0) { // if coeffs are multivariate (and non constant) // otherwise it would be 1 t = resultant(a, b); x = P.ring.getONE().multiply(t); return x; } t = power(cofac, a, e); t = t.multiply(power(cofac, b, f)); long s = 1; GenPolynomial z; while (r.degree(0) > 0) { long delta = q.degree(0) - r.degree(0); //System.out.println("delta = " + delta); if ((q.degree(0) % 2 != 0) && (r.degree(0) % 2 != 0)) { s = -s; } x = PolyUtil. recursiveDensePseudoRemainder(q, r); //System.out.println("x = " + x); q = r; if (x.degree(0) > 0) { z = g.multiply(power(P.ring.coFac, h, delta)); r = PolyUtil. recursiveDivide(x, z); g = q.leadingBaseCoefficient(); z = power(cofac, g, delta); h = PolyUtil. basePseudoDivide(z, power(cofac, h, delta - 1)); } else { r = x; } } z = power(cofac, r.leadingBaseCoefficient(), q.degree(0)); h = PolyUtil. basePseudoDivide(z, power(cofac, h, q.degree(0) - 1)); z = h.multiply(t); if ( s < 0 ) { z = z.negate(); } x = P.ring.getONE().multiply(z); return x; } /** * GenPolynomial base coefficient discriminant. * @param P GenPolynomial. * @return discriminant(P). */ public GenPolynomial baseDiscriminant(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " P not univariate"); } C a = P.leadingBaseCoefficient(); a = a.inverse(); GenPolynomial Pp = PolyUtil. baseDeriviative(P); GenPolynomial res = baseResultant(P, Pp); GenPolynomial disc = res.multiply(a); long n = P.degree(0); n = n * (n - 1); n = n / 2; if (n % 2L != 0L) { disc = disc.negate(); } return disc; } /** * Coefficient power. * @param A coefficient * @param i exponent. * @return A^i. */ C power(RingFactory fac, C A, long i) { return Power. power(fac, A, i); } /** * Polynomial power. * @param A polynomial. * @param i exponent. * @return A^i. */ GenPolynomial power(RingFactory> fac, GenPolynomial A, long i) { return Power.> power(fac, A, i); } } jas-2.5/src/edu/jas/ufd/FactorRational.java0000644000175000017500000001260312004537436021023 0ustar giovannigiovanni/* * $Id: FactorRational.java 4067 2012-07-27 16:17:35Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.BigRational; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; /** * Rational number coefficients factorization algorithms. This class implements * factorization methods for polynomials over rational numbers. * @author Heinz Kredel */ public class FactorRational extends FactorAbsolute { private static final Logger logger = Logger.getLogger(FactorRational.class); private final boolean debug = logger.isInfoEnabled(); /** * Factorization engine for integer base coefficients. */ protected final FactorAbstract iengine; /** * No argument constructor. */ protected FactorRational() { super(BigRational.ONE); iengine = FactorFactory.getImplementation(BigInteger.ONE); } /** * GenPolynomial base factorization of a squarefree polynomial. * @param P squarefree GenPolynomial. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ @Override public List> baseFactorsSquarefree(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List> factors = new ArrayList>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } GenPolynomial Pr = P; BigRational ldcf = P.leadingBaseCoefficient(); if (!ldcf.isONE()) { //System.out.println("ldcf = " + ldcf); Pr = Pr.monic(); } BigInteger bi = BigInteger.ONE; GenPolynomialRing ifac = new GenPolynomialRing(bi, pfac); GenPolynomial Pi = PolyUtil.integerFromRationalCoefficients(ifac, Pr); if (debug) { logger.info("Pi = " + Pi); } List> ifacts = iengine.baseFactorsSquarefree(Pi); if (logger.isInfoEnabled()) { logger.info("ifacts = " + ifacts); } if (ifacts.size() <= 1) { factors.add(P); return factors; } List> rfacts = PolyUtil.fromIntegerCoefficients(pfac, ifacts); //System.out.println("rfacts = " + rfacts); rfacts = PolyUtil.monic(rfacts); //System.out.println("rfacts = " + rfacts); if (!ldcf.isONE()) { GenPolynomial r = rfacts.get(0); rfacts.remove(r); r = r.multiply(ldcf); rfacts.set(0, r); } if (logger.isInfoEnabled()) { logger.info("rfacts = " + rfacts); } factors.addAll(rfacts); return factors; } /** * GenPolynomial factorization of a squarefree polynomial. * @param P squarefree GenPolynomial. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ @Override public List> factorsSquarefree(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List> factors = new ArrayList>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing pfac = P.ring; if (pfac.nvar == 1) { return baseFactorsSquarefree(P); } GenPolynomial Pr = P; BigRational ldcf = P.leadingBaseCoefficient(); if (!ldcf.isONE()) { //System.out.println("ldcf = " + ldcf); Pr = Pr.monic(); } BigInteger bi = BigInteger.ONE; GenPolynomialRing ifac = new GenPolynomialRing(bi, pfac); GenPolynomial Pi = PolyUtil.integerFromRationalCoefficients(ifac, Pr); if (debug) { logger.info("Pi = " + Pi); } List> ifacts = iengine.factorsSquarefree(Pi); if (logger.isInfoEnabled()) { logger.info("ifacts = " + ifacts); } if (ifacts.size() <= 1) { factors.add(P); return factors; } List> rfacts = PolyUtil.fromIntegerCoefficients(pfac, ifacts); //System.out.println("rfacts = " + rfacts); rfacts = PolyUtil.monic(rfacts); //System.out.println("rfacts = " + rfacts); if (!ldcf.isONE()) { GenPolynomial r = rfacts.get(0); rfacts.remove(r); r = r.multiply(ldcf); rfacts.set(0, r); } if (logger.isInfoEnabled()) { logger.info("rfacts = " + rfacts); } factors.addAll(rfacts); return factors; } } jas-2.5/src/edu/jas/ufd/PolyUfdUtil.java0000644000175000017500000004706412014234362020335 0ustar giovannigiovanni/* * $Id: PolyUfdUtil.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.UnaryFunctor; import edu.jas.util.ListUtil; /** * Polynomial ufd utilities, like conversion between different representations * and Hensel lifting. * @author Heinz Kredel */ public class PolyUfdUtil { private static final Logger logger = Logger.getLogger(PolyUfdUtil.class); private static boolean debug = logger.isDebugEnabled(); /** * Integral polynomial from rational function coefficients. Represent as * polynomial with integral polynomial coefficients by multiplication with * the lcm of the numerators of the rational function coefficients. * @param fac result polynomial factory. * @param A polynomial with rational function coefficients to be converted. * @return polynomial with integral polynomial coefficients. */ public static > GenPolynomial> integralFromQuotientCoefficients( GenPolynomialRing> fac, GenPolynomial> A) { GenPolynomial> B = fac.getZERO().copy(); if (A == null || A.isZERO()) { return B; } GenPolynomial c = null; GenPolynomial d; GenPolynomial x; GreatestCommonDivisor ufd = new GreatestCommonDivisorSubres(); int s = 0; // lcm of denominators for (Quotient y : A.getMap().values()) { x = y.den; // c = lcm(c,x) if (c == null) { c = x; s = x.signum(); } else { d = ufd.gcd(c, x); c = c.multiply(x.divide(d)); } } if (s < 0) { c = c.negate(); } for (Map.Entry> y : A.getMap().entrySet()) { ExpVector e = y.getKey(); Quotient a = y.getValue(); // p = n*(c/d) GenPolynomial b = c.divide(a.den); GenPolynomial p = a.num.multiply(b); //B = B.sum( p, e ); // inefficient B.doPutToMap(e, p); } return B; } /** * Integral polynomial from rational function coefficients. Represent as * polynomial with integral polynomial coefficients by multiplication with * the lcm of the numerators of the rational function coefficients. * @param fac result polynomial factory. * @param L list of polynomial with rational function coefficients to be * converted. * @return list of polynomials with integral polynomial coefficients. */ public static > List>> integralFromQuotientCoefficients( GenPolynomialRing> fac, Collection>> L) { if (L == null) { return null; } List>> list = new ArrayList>>(L.size()); for (GenPolynomial> p : L) { list.add(integralFromQuotientCoefficients(fac, p)); } return list; } /** * Rational function from integral polynomial coefficients. Represent as * polynomial with type Quotient coefficients. * @param fac result polynomial factory. * @param A polynomial with integral polynomial coefficients to be * converted. * @return polynomial with type Quotient coefficients. */ public static > GenPolynomial> quotientFromIntegralCoefficients( GenPolynomialRing> fac, GenPolynomial> A) { GenPolynomial> B = fac.getZERO().copy(); if (A == null || A.isZERO()) { return B; } RingFactory> cfac = fac.coFac; QuotientRing qfac = (QuotientRing) cfac; for (Map.Entry> y : A.getMap().entrySet()) { ExpVector e = y.getKey(); GenPolynomial a = y.getValue(); Quotient p = new Quotient(qfac, a); // can not be zero if (!p.isZERO()) { //B = B.sum( p, e ); // inefficient B.doPutToMap(e, p); } } return B; } /** * Rational function from integral polynomial coefficients. Represent as * polynomial with type Quotient coefficients. * @param fac result polynomial factory. * @param L list of polynomials with integral polynomial coefficients to be * converted. * @return list of polynomials with type Quotient coefficients. */ public static > List>> quotientFromIntegralCoefficients( GenPolynomialRing> fac, Collection>> L) { if (L == null) { return null; } List>> list = new ArrayList>>(L.size()); for (GenPolynomial> p : L) { list.add(quotientFromIntegralCoefficients(fac, p)); } return list; } /** * From BigInteger coefficients. Represent as polynomial with type * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. * @param fac result polynomial factory. * @param A polynomial with GenPolynomial<BigInteger> coefficients to * be converted. * @return polynomial with type GenPolynomial<C> coefficients. */ public static > GenPolynomial> fromIntegerCoefficients( GenPolynomialRing> fac, GenPolynomial> A) { GenPolynomial> B = fac.getZERO().copy(); if (A == null || A.isZERO()) { return B; } RingFactory> cfac = fac.coFac; GenPolynomialRing rfac = (GenPolynomialRing) cfac; for (Map.Entry> y : A.getMap().entrySet()) { ExpVector e = y.getKey(); GenPolynomial a = y.getValue(); GenPolynomial p = PolyUtil. fromIntegerCoefficients(rfac, a); if (!p.isZERO()) { //B = B.sum( p, e ); // inefficient B.doPutToMap(e, p); } } return B; } /** * From BigInteger coefficients. Represent as polynomial with type * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. * @param fac result polynomial factory. * @param L polynomial list with GenPolynomial<BigInteger> * coefficients to be converted. * @return polynomial list with polynomials with type GenPolynomial<C> * coefficients. */ public static > List>> fromIntegerCoefficients( GenPolynomialRing> fac, List>> L) { List>> K = null; if (L == null) { return K; } K = new ArrayList>>(L.size()); if (L.size() == 0) { return K; } for (GenPolynomial> a : L) { GenPolynomial> b = fromIntegerCoefficients(fac, a); K.add(b); } return K; } /** * Introduce lower variable. Represent as polynomial with type * GenPolynomial<C> coefficients. * @param rfac result polynomial factory. * @param A polynomial to be extended. * @return polynomial with type GenPolynomial<C> coefficients. */ public static > GenPolynomial> introduceLowerVariable( GenPolynomialRing> rfac, GenPolynomial A) { if (A == null || rfac == null) { return null; } GenPolynomial> Pc = rfac.getONE().multiply(A); if (Pc.isZERO()) { return Pc; } Pc = PolyUtil. switchVariables(Pc); return Pc; } /** * From AlgebraicNumber coefficients. Represent as polynomial with type * GenPolynomial<C> coefficients, e.g. ModInteger or BigRational. * @param rfac result polynomial factory. * @param A polynomial with AlgebraicNumber coefficients to be converted. * @param k for (y-k x) substitution. * @return polynomial with type GenPolynomial<C> coefficients. */ public static > GenPolynomial> substituteFromAlgebraicCoefficients( GenPolynomialRing> rfac, GenPolynomial> A, long k) { if (A == null || rfac == null) { return null; } if (A.isZERO()) { return rfac.getZERO(); } // setup x - k alpha GenPolynomialRing> apfac = A.ring; GenPolynomial> x = apfac.univariate(0); AlgebraicNumberRing afac = (AlgebraicNumberRing) A.ring.coFac; AlgebraicNumber alpha = afac.getGenerator(); AlgebraicNumber ka = afac.fromInteger(k); GenPolynomial> s = x.subtract(ka.multiply(alpha)); // x - k alpha if (debug) { logger.info("x - k alpha: " + s); } // substitute, convert and switch GenPolynomial> B = PolyUtil.> substituteMain(A, s); GenPolynomial> Pc = PolyUtil. fromAlgebraicCoefficients(rfac, B); // Q[alpha][x] Pc = PolyUtil. switchVariables(Pc); // Q[x][alpha] return Pc; } /** * Convert to AlgebraicNumber coefficients. Represent as polynomial with * AlgebraicNumber coefficients, C is e.g. ModInteger or BigRational. * @param pfac result polynomial factory. * @param A polynomial with GenPolynomial<BigInteger> coefficients to * be converted. * @param k for (y-k x) substitution. * @return polynomial with AlgebraicNumber<C> coefficients. */ public static > GenPolynomial> substituteConvertToAlgebraicCoefficients( GenPolynomialRing> pfac, GenPolynomial A, long k) { if (A == null || pfac == null) { return null; } if (A.isZERO()) { return pfac.getZERO(); } // convert to Q(alpha)[x] GenPolynomial> B = PolyUtil. convertToAlgebraicCoefficients(pfac, A); // setup x .+. k alpha for back substitution GenPolynomial> x = pfac.univariate(0); AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac; AlgebraicNumber alpha = afac.getGenerator(); AlgebraicNumber ka = afac.fromInteger(k); GenPolynomial> s = x.sum(ka.multiply(alpha)); // x + k alpha // substitute GenPolynomial> N = PolyUtil.> substituteMain(B, s); return N; } /** * Norm of a polynomial with AlgebraicNumber coefficients. * @param A polynomial from GenPolynomial<AlgebraicNumber<C>>. * @param k for (y - k x) substitution. * @return norm(A) = res_x(A(x,y),m(x)) in GenPolynomialRing<C>. */ public static > GenPolynomial norm(GenPolynomial> A, long k) { if (A == null) { return null; } GenPolynomialRing> pfac = A.ring; // Q(alpha)[x] if (pfac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomials"); } AlgebraicNumberRing afac = (AlgebraicNumberRing) pfac.coFac; GenPolynomial agen = afac.modul; GenPolynomialRing cfac = afac.ring; if (A.isZERO()) { return cfac.getZERO(); } AlgebraicNumber ldcf = A.leadingBaseCoefficient(); if (!ldcf.isONE()) { A = A.monic(); } GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, pfac); // transform minimal polynomial to bi-variate polynomial GenPolynomial> Ac = PolyUfdUtil. introduceLowerVariable(rfac, agen); //System.out.println("Ac = " + Ac.toScript()); // transform to bi-variate polynomial, // switching varaible sequence from Q[alpha][x] to Q[X][alpha] GenPolynomial> Pc = PolyUfdUtil. substituteFromAlgebraicCoefficients(rfac, A, k); Pc = PolyUtil. monic(Pc); //System.out.println("Pc = " + Pc.toScript()); GreatestCommonDivisorSubres engine = new GreatestCommonDivisorSubres( /*cfac.coFac*/); // = (GreatestCommonDivisorAbstract)GCDFactory.getImplementation( cfac.coFac ); GenPolynomial> Rc = engine.recursiveUnivariateResultant(Pc, Ac); //System.out.println("Rc = " + Rc.toScript()); GenPolynomial res = Rc.leadingBaseCoefficient(); res = res.monic(); return res; } /** * Norm of a polynomial with AlgebraicNumber coefficients. * @param A polynomial from GenPolynomial<AlgebraicNumber<C>>. * @return norm(A) = resultant_x( A(x,y), m(x) ) in K[y]. */ public static > GenPolynomial norm(GenPolynomial> A) { return norm(A, 0L); } /** * Ensure that the field property is determined. Checks if modul is * irreducible and modifies the algebraic number ring. * @param afac algebraic number ring. */ public static > void ensureFieldProperty(AlgebraicNumberRing afac) { if (afac.getField() != -1) { return; } if (!afac.ring.coFac.isField()) { afac.setField(false); return; } Factorization mf = FactorFactory. getImplementation(afac.ring); if (mf.isIrreducible(afac.modul)) { afac.setField(true); } else { afac.setField(false); } } /** * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a * univariate polynomial. * @param A polynomial to be converted. * @return a univariate polynomial. */ public static > GenPolynomial substituteKronecker(GenPolynomial A) { if (A == null) { return A; } long d = A.degree() + 1L; return substituteKronecker(A, d); } /** * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a * univariate polynomial. * @param A polynomial to be converted. * @return a univariate polynomial. */ public static > GenPolynomial substituteKronecker(GenPolynomial A, long d) { if (A == null) { return A; } RingFactory cfac = A.ring.coFac; GenPolynomialRing ufac = new GenPolynomialRing(cfac, 1); GenPolynomial B = ufac.getZERO().copy(); if (A.isZERO()) { return B; } for (Map.Entry y : A.getMap().entrySet()) { ExpVector e = y.getKey(); C a = y.getValue(); long f = 0L; long h = 1L; for (int i = 0; i < e.length(); i++) { long j = e.getVal(i) * h; f += j; h *= d; } ExpVector g = ExpVector.create(1, 0, f); B.doPutToMap(g, a); } return B; } /** * Kronecker substitution. Substitute x_i by x**d**(i-1) to construct a * univariate polynomials. * @param A list of polynomials to be converted. * @return a list of univariate polynomials. */ public static > List> substituteKronecker( List> A, int d) { if (A == null || A.get(0) == null) { return null; } return ListUtil., GenPolynomial> map(A, new SubstKronecker(d)); } /** * Kronecker back substitution. Substitute x**d**(i-1) to x_i to construct a * multivariate polynomial. * @param A polynomial to be converted. * @param fac result polynomial factory. * @return a multivariate polynomial. */ public static > GenPolynomial backSubstituteKronecker( GenPolynomialRing fac, GenPolynomial A, long d) { if (A == null) { return A; } if (fac == null) { throw new IllegalArgumentException("null factory not allowed "); } int n = fac.nvar; GenPolynomial B = fac.getZERO().copy(); if (A.isZERO()) { return B; } for (Map.Entry y : A.getMap().entrySet()) { ExpVector e = y.getKey(); C a = y.getValue(); long f = e.getVal(0); ExpVector g = ExpVector.create(n); for (int i = 0; i < n; i++) { long j = f % d; f /= d; g = g.subst(i, j); } B.doPutToMap(g, a); } return B; } /** * Kronecker back substitution. Substitute x**d**(i-1) to x_i to construct a * multivariate polynomials. * @param A list of polynomials to be converted. * @param fac result polynomial factory. * @return a list of multivariate polynomials. */ public static > List> backSubstituteKronecker( GenPolynomialRing fac, List> A, long d) { return ListUtil., GenPolynomial> map(A, new BackSubstKronecker(fac, d)); } } /** * Kronecker substitutuion functor. */ class SubstKronecker> implements UnaryFunctor, GenPolynomial> { final long d; public SubstKronecker(long d) { this.d = d; } public GenPolynomial eval(GenPolynomial c) { if (c == null) { return null; } return PolyUfdUtil. substituteKronecker(c, d); } } /** * Kronecker back substitutuion functor. */ class BackSubstKronecker> implements UnaryFunctor, GenPolynomial> { final long d; final GenPolynomialRing fac; public BackSubstKronecker(GenPolynomialRing fac, long d) { this.d = d; this.fac = fac; } public GenPolynomial eval(GenPolynomial c) { if (c == null) { return null; } return PolyUfdUtil. backSubstituteKronecker(fac, c, d); } } jas-2.5/src/edu/jas/ufd/FactorAbsolute.java0000644000175000017500000012134512014234362021025 0ustar giovannigiovanni/* * $Id: FactorAbsolute.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Absolute factorization algorithms class. This class contains implementations * of methods for factorization over algebraically closed fields. The required * field extension is computed along with the factors. The methods have been * tested for prime fields of characteristic zero, that is for * BigRational. It might eventually also be used for prime * fields of non-zero characteristic, that is with ModInteger. * The field extension may yet not be minimal. * @author Heinz Kredel * @param coefficient type */ public abstract class FactorAbsolute> extends FactorAbstract { private static final Logger logger = Logger.getLogger(FactorAbsolute.class); private final boolean debug = logger.isDebugEnabled(); /* * Factorization engine for algebraic number coefficients. */ //not possible here because of recursion AN -> Int|Mod -> AN -> ... //public final FactorAbstract> aengine; /** * No argument constructor. Note: can't use this constructor. */ protected FactorAbsolute() { throw new IllegalArgumentException("don't use this constructor"); } /** * Constructor. * @param cfac coefficient ring factory. */ public FactorAbsolute(RingFactory cfac) { super(cfac); //GenPolynomialRing fac = new GenPolynomialRing(cfac,1); //GenPolynomial p = fac.univariate(0); //AlgebraicNumberRing afac = new AlgebraicNumberRing(p); //aengine = null; //FactorFactory.getImplementation(afac); // hack } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return getClass().getName(); } /** * GenPolynomial test if is absolute irreducible. * @param P GenPolynomial. * @return true if P is absolute irreducible, else false. */ public boolean isAbsoluteIrreducible(GenPolynomial P) { if (!isIrreducible(P)) { return false; } Factors F = factorsAbsoluteIrreducible(P); if (F.afac == null) { return true; } else if (F.afactors.size() > 2) { return false; } else { //F.size() == 2 boolean cnst = false; for (GenPolynomial> p : F.afactors) { if (p.isConstant()) { cnst = true; } } return cnst; } } /** * GenPolynomial absolute base factorization of a polynomial. * @param P univariate GenPolynomial. * @return factors map container: [p_1 -> e_1, ..., p_k -> e_k] with P = * prod_{i=1,...,k} p_i**e_i. Note: K(alpha) not yet * minimal. */ // @Override public FactorsMap baseFactorsAbsolute(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } SortedMap, Long> factors = new TreeMap, Long>(); if (P.isZERO()) { return new FactorsMap(P, factors); } //System.out.println("\nP_base = " + P); GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar > 1) { //System.out.println("\nfacs_base: univ"); throw new IllegalArgumentException("only for univariate polynomials"); } if (!pfac.coFac.isField()) { //System.out.println("\nfacs_base: field"); throw new IllegalArgumentException("only for field coefficients"); } if (P.degree(0) <= 1) { factors.put(P, 1L); return new FactorsMap(P, factors); } // factor over K (=C) SortedMap, Long> facs = baseFactors(P); if (debug && !isFactorization(P, facs)) { System.out.println("facs = " + facs); throw new ArithmeticException("isFactorization = false"); } if (logger.isInfoEnabled()) { logger.info("all K factors = " + facs); // Q[X] //System.out.println("\nall K factors = " + facs); // Q[X] } // factor over some K(alpha) SortedMap, Long> afactors = new TreeMap, Long>(); for ( Map.Entry,Long> me : facs.entrySet()) { GenPolynomial p = me.getKey(); Long e = me.getValue(); //facs.get(p); if (p.degree(0) <= 1) { factors.put(p, e); } else { Factors afacs = baseFactorsAbsoluteIrreducible(p); //System.out.println("afacs = " + afacs); afactors.put(afacs, e); } } //System.out.println("K(alpha) factors = " + factors); return new FactorsMap(P, factors, afactors); } /** * GenPolynomial absolute base factorization of a squarefree polynomial. * @param P squarefree and primitive univariate GenPolynomial. * @return factors list container: [p_1,...,p_k] with P = prod_{i=1, ..., k} * p_i. Note: K(alpha) not yet minimal. */ // @Override public FactorsList baseFactorsAbsoluteSquarefree(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List> factors = new ArrayList>(); if (P.isZERO()) { return new FactorsList(P, factors); } //System.out.println("\nP_base_sqf = " + P); GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar > 1) { //System.out.println("facs_base_sqf: univ"); throw new IllegalArgumentException("only for univariate polynomials"); } if (!pfac.coFac.isField()) { //System.out.println("facs_base_sqf: field"); throw new IllegalArgumentException("only for field coefficients"); } if (P.degree(0) <= 1) { factors.add(P); return new FactorsList(P, factors); } // factor over K (=C) List> facs = baseFactorsSquarefree(P); //System.out.println("facs_base_irred = " + facs); if (debug && !isFactorization(P, facs)) { throw new ArithmeticException("isFactorization = false"); } if (logger.isInfoEnabled()) { logger.info("all K factors = " + facs); // Q[X] //System.out.println("\nall K factors = " + facs); // Q[X] } // factor over K(alpha) List> afactors = new ArrayList>(); for (GenPolynomial p : facs) { //System.out.println("facs_base_sqf_p = " + p); if (p.degree(0) <= 1) { factors.add(p); } else { Factors afacs = baseFactorsAbsoluteIrreducible(p); //System.out.println("afacs_base_sqf = " + afacs); if (logger.isInfoEnabled()) { logger.info("K(alpha) factors = " + afacs); // K(alpha)[X] } afactors.add(afacs); } } //System.out.println("K(alpha) factors = " + factors); return new FactorsList(P, factors, afactors); } /** * GenPolynomial base absolute factorization of a irreducible polynomial. * @param P irreducible! univariate GenPolynomial. * @return factors container: [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i * in K(alpha)[x] for suitable alpha and p_i irreducible over L[x], * where K \subset K(alpha) \subset L is an algebraically closed * field over K. Note: K(alpha) not yet minimal. */ public Factors baseFactorsAbsoluteIrreducible(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } if (P.isZERO()) { return new Factors(P); } //System.out.println("\nP_base_irred = " + P); GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar > 1) { //System.out.println("facs_base_irred: univ"); throw new IllegalArgumentException("only for univariate polynomials"); } if (!pfac.coFac.isField()) { //System.out.println("facs_base_irred: field"); throw new IllegalArgumentException("only for field coefficients"); } if (P.degree(0) <= 1) { return new Factors(P); } // setup field extension K(alpha) where alpha = z_xx //String[] vars = new String[] { "z_" + Math.abs(P.hashCode() % 1000) }; String[] vars = pfac.newVars( "z_" ); pfac = pfac.copy(); vars = pfac.setVars(vars); GenPolynomial aP = pfac.copy(P); // hack to exchange the variables AlgebraicNumberRing afac = new AlgebraicNumberRing(aP, true); // since irreducible if (logger.isInfoEnabled()) { logger.info("K(alpha) = " + afac); logger.info("K(alpha) = " + afac.toScript()); //System.out.println("K(alpha) = " + afac); } GenPolynomialRing> pafac = new GenPolynomialRing>(afac, aP.ring.nvar, aP.ring.tord, /*old*/vars); // convert to K(alpha) GenPolynomial> Pa = PolyUtil. convertToAlgebraicCoefficients(pafac, P); if (logger.isInfoEnabled()) { logger.info("P over K(alpha) = " + Pa); //logger.info("P over K(alpha) = " + Pa.toScript()); //System.out.println("P in K(alpha) = " + Pa); } // factor over K(alpha) FactorAbstract> engine = FactorFactory. getImplementation(afac); //System.out.println("K(alpha) engine = " + engine); List>> factors = engine.baseFactorsSquarefree(Pa); //System.out.println("factors = " + factors); if (logger.isInfoEnabled()) { logger.info("factors over K(alpha) = " + factors); //System.out.println("factors over K(alpha) = " + factors); } List>> faca = new ArrayList>>( factors.size()); List>> facar = new ArrayList>>(); for (GenPolynomial> fi : factors) { if (fi.degree(0) <= 1) { faca.add(fi); } else { //System.out.println("fi.deg > 1 = " + fi); FactorAbsolute> aengine = (FactorAbsolute>) FactorFactory . getImplementation(afac); Factors> fif = aengine.baseFactorsAbsoluteIrreducible(fi); //System.out.println("fif = " + fif); facar.add(fif); } } if (facar.size() == 0) { facar = null; } // find minimal field extension K(beta) \subset K(alpha) return new Factors(P, afac, Pa, faca, facar); } /** * Univariate GenPolynomial algebraic partial fraction decomposition, * Absolute factorization or Rothstein-Trager algorithm. * @param A univariate GenPolynomial, deg(A) < deg(P). * @param P univariate squarefree GenPolynomial, gcd(A,P) == 1. * @return partial fraction container. */ public PartialFraction baseAlgebraicPartialFraction(GenPolynomial A, GenPolynomial P) { if (P == null || P.isZERO() ) { throw new IllegalArgumentException(" P == null or P == 0"); } if (A == null || A.isZERO() ) { throw new IllegalArgumentException(" A == null or A == 0"); // PartialFraction(A,P,al,pl,empty,empty) } //System.out.println("\nP_base_algeb_part = " + P); GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar > 1) { //System.out.println("facs_base_irred: univ"); throw new IllegalArgumentException("only for univariate polynomials"); } if (!pfac.coFac.isField()) { //System.out.println("facs_base_irred: field"); throw new IllegalArgumentException("only for field coefficients"); } List cfactors = new ArrayList(); List> cdenom = new ArrayList>(); List> afactors = new ArrayList>(); List>> adenom = new ArrayList>>(); // P linear if (P.degree(0) <= 1) { cfactors.add(A.leadingBaseCoefficient()); cdenom.add(P); return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom); } List> Pfac = baseFactorsSquarefree(P); //System.out.println("\nPfac = " + Pfac); List> Afac = engine.basePartialFraction(A,Pfac); GenPolynomial A0 = Afac.remove(0); if ( !A0.isZERO() ) { throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)"); } // algebraic and linear factors int i = 0; for ( GenPolynomial pi : Pfac ) { GenPolynomial ai = Afac.get(i++); if ( pi.degree(0) <= 1 ) { cfactors.add( ai.leadingBaseCoefficient() ); cdenom.add(pi); continue; } PartialFraction pf = baseAlgebraicPartialFractionIrreducibleAbsolute(ai,pi); //PartialFraction pf = baseAlgebraicPartialFractionIrreducible(ai,pi); cfactors.addAll( pf.cfactors ); cdenom.addAll( pf.cdenom ); afactors.addAll( pf.afactors ); adenom.addAll( pf.adenom ); } return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom); } /** * Univariate GenPolynomial algebraic partial fraction decomposition, * Rothstein-Trager algorithm. * @param A univariate GenPolynomial, deg(A) < deg(P). * @param P univariate squarefree GenPolynomial, gcd(A,P) == 1. * @return partial fraction container. */ @Deprecated public PartialFraction baseAlgebraicPartialFractionIrreducible(GenPolynomial A, GenPolynomial P) { if (P == null || P.isZERO() ) { throw new IllegalArgumentException(" P == null or P == 0"); } //System.out.println("\nP_base_algeb_part = " + P); GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar > 1) { //System.out.println("facs_base_irred: univ"); throw new IllegalArgumentException("only for univariate polynomials"); } if (!pfac.coFac.isField()) { //System.out.println("facs_base_irred: field"); throw new IllegalArgumentException("only for field coefficients"); } List cfactors = new ArrayList(); List> cdenom = new ArrayList>(); List> afactors = new ArrayList>(); List>> adenom = new ArrayList>>(); // P linear if (P.degree(0) <= 1) { cfactors.add(A.leadingBaseCoefficient()); cdenom.add(P); return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom); } // deriviative GenPolynomial Pp = PolyUtil. baseDeriviative(P); //no: Pp = Pp.monic(); //System.out.println("\nP = " + P); //System.out.println("Pp = " + Pp); // Q[t] String[] vars = new String[] { "t" }; GenPolynomialRing cfac = new GenPolynomialRing(pfac.coFac, 1, pfac.tord, vars); GenPolynomial t = cfac.univariate(0); //System.out.println("t = " + t); // Q[x][t] GenPolynomialRing> rfac = new GenPolynomialRing>(pfac, cfac); // sic //System.out.println("rfac = " + rfac.toScript()); // transform polynomials to bi-variate polynomial GenPolynomial> Ac = PolyUfdUtil. introduceLowerVariable(rfac, A); //System.out.println("Ac = " + Ac); GenPolynomial> Pc = PolyUfdUtil. introduceLowerVariable(rfac, P); //System.out.println("Pc = " + Pc); GenPolynomial> Pcp = PolyUfdUtil. introduceLowerVariable(rfac, Pp); //System.out.println("Pcp = " + Pcp); // Q[t][x] GenPolynomialRing> rfac1 = Pc.ring; //System.out.println("rfac1 = " + rfac1.toScript()); // A - t P' GenPolynomial> tc = rfac1.getONE().multiply(t); //System.out.println("tc = " + tc); GenPolynomial> At = Ac.subtract( tc.multiply(Pcp) ); //System.out.println("At = " + At); GreatestCommonDivisorSubres engine = new GreatestCommonDivisorSubres(); // = GCDFactory.getImplementation( cfac.coFac ); GreatestCommonDivisorAbstract> aengine = null; GenPolynomial> Rc = engine.recursiveUnivariateResultant(Pc, At); //System.out.println("Rc = " + Rc); GenPolynomial res = Rc.leadingBaseCoefficient(); //no: res = res.monic(); //System.out.println("\nres = " + res); SortedMap,Long> resfac = baseFactors(res); //System.out.println("resfac = " + resfac + "\n"); for ( GenPolynomial r : resfac.keySet() ) { //System.out.println("\nr(t) = " + r); if ( r.isConstant() ) { continue; } // if ( r.degree(0) <= 1L ) { // System.out.println("warning linear factor in resultant ignored"); // continue; // //throw new ArithmeticException("input not irreducible"); // } //vars = new String[] { "z_" + Math.abs(r.hashCode() % 1000) }; vars = pfac.newVars( "z_" ); pfac = pfac.copy(); String[] ovars = pfac.setVars(vars); r = pfac.copy(r); // hack to exchange the variables //System.out.println("r(z_) = " + r); AlgebraicNumberRing afac = new AlgebraicNumberRing(r, true); // since irreducible logger.debug("afac = " + afac.toScript()); AlgebraicNumber a = afac.getGenerator(); //no: a = a.negate(); //System.out.println("a = " + a); // K(alpha)[x] GenPolynomialRing> pafac = new GenPolynomialRing>(afac, Pc.ring); //System.out.println("pafac = " + pafac.toScript()); // convert to K(alpha)[x] GenPolynomial> Pa = PolyUtil. convertToAlgebraicCoefficients(pafac, P); //System.out.println("Pa = " + Pa); GenPolynomial> Pap = PolyUtil. convertToAlgebraicCoefficients(pafac, Pp); //System.out.println("Pap = " + Pap); GenPolynomial> Aa = PolyUtil. convertToAlgebraicCoefficients(pafac, A); //System.out.println("Aa = " + Aa); // A - a P' GenPolynomial> Ap = Aa.subtract( Pap.multiply(a) ); //System.out.println("Ap = " + Ap); if ( aengine == null ) { aengine = GCDFactory.>getImplementation( afac ); //System.out.println("aengine = " + aengine); } GenPolynomial> Ga = aengine.baseGcd(Pa,Ap); //System.out.println("Ga = " + Ga); if ( Ga.isConstant() ) { //System.out.println("warning constant gcd ignored"); continue; } afactors.add( a ); adenom.add( Ga ); // quadratic case if ( P.degree(0) == 2 && Ga.degree(0) == 1 ) { GenPolynomial>[] qra = PolyUtil.> basePseudoQuotientRemainder(Pa,Ga); GenPolynomial> Qa = qra[0]; if ( !qra[1].isZERO() ) { throw new ArithmeticException("remainder not zero"); } //System.out.println("Qa = " + Qa); afactors.add( a.negate() ); adenom.add( Qa ); } if ( false && P.degree(0) == 3 && Ga.degree(0) == 1 ) { GenPolynomial>[] qra = PolyUtil.> basePseudoQuotientRemainder(Pa,Ga); GenPolynomial> Qa = qra[0]; if ( !qra[1].isZERO() ) { throw new ArithmeticException("remainder not zero"); } System.out.println("Qa3 = " + Qa); //afactors.add( a.negate() ); //adenom.add( Qa ); } } return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom); } /** * Univariate GenPolynomial algebraic partial fraction decomposition, * via absolute factorization to linear factors. * @param A univariate GenPolynomial, deg(A) < deg(P). * @param P univariate squarefree GenPolynomial, gcd(A,P) == 1. * @return partial fraction container. */ public PartialFraction baseAlgebraicPartialFractionIrreducibleAbsolute(GenPolynomial A, GenPolynomial P) { if (P == null || P.isZERO() ) { throw new IllegalArgumentException(" P == null or P == 0"); } //System.out.println("\nP_base_algeb_part = " + P); GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar > 1) { //System.out.println("facs_base_irred: univ"); throw new IllegalArgumentException("only for univariate polynomials"); } if (!pfac.coFac.isField()) { //System.out.println("facs_base_irred: field"); throw new IllegalArgumentException("only for field coefficients"); } List cfactors = new ArrayList(); List> cdenom = new ArrayList>(); List> afactors = new ArrayList>(); List>> adenom = new ArrayList>>(); // P linear if (P.degree(0) <= 1) { cfactors.add(A.leadingBaseCoefficient()); cdenom.add(P); return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom); } // non linear case Factors afacs = factorsAbsoluteIrreducible(P); //System.out.println("linear algebraic factors = " + afacs); //System.out.println("afactors = " + afacs.afactors); //System.out.println("arfactors = " + afacs.arfactors); //System.out.println("arfactors pol = " + afacs.arfactors.get(0).poly); //System.out.println("arfactors2 = " + afacs.arfactors.get(0).afactors); List>> fact = afacs.getFactors(); //System.out.println("factors = " + fact); GenPolynomial> Pa = afacs.apoly; GenPolynomial> Aa = PolyUtil . convertToRecAlgebraicCoefficients(1, Pa.ring, A); GreatestCommonDivisorAbstract> aengine = GCDFactory.getProxy(afacs.afac); //System.out.println("denom = " + Pa); //System.out.println("numer = " + Aa); List>> numers = aengine.basePartialFraction(Aa,fact); //System.out.println("part frac = " + numers); GenPolynomial> A0 = numers.remove(0); if ( ! A0.isZERO() ) { throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)"); } int i = 0; for ( GenPolynomial> fa : fact ) { GenPolynomial> an = numers.get(i++); if ( fa.degree(0) <= 1 ) { afactors.add(an.leadingBaseCoefficient()); adenom.add( fa ); continue; } System.out.println("fa = " + fa); Factors> faf = afacs.getFactor(fa); System.out.println("faf = " + faf); List>>> fafact = faf.getFactors(); GenPolynomial>> Aaa = PolyUtil .> convertToRecAlgebraicCoefficients(1, faf.apoly.ring, an); GreatestCommonDivisorAbstract>> aaengine = GCDFactory.getImplementation(faf.afac); List>>> anumers = aaengine.basePartialFraction(Aaa,fafact); System.out.println("algeb part frac = " + anumers); GenPolynomial>> A0a = anumers.remove(0); if ( ! A0a.isZERO() ) { throw new ArithmeticException(" A0 != 0: deg(A)>= deg(P)"); } int k = 0; for ( GenPolynomial>> faa : fafact ) { GenPolynomial>> ana = anumers.get(k++); System.out.println("faa = " + faa); System.out.println("ana = " + ana); if ( faa.degree(0) > 1 ) { throw new ArithmeticException(" faa not linear"); } GenPolynomial> ana1 = (GenPolynomial>)(GenPolynomial)ana; GenPolynomial> faa1 = (GenPolynomial>)(GenPolynomial)faa; afactors.add(ana1.leadingBaseCoefficient()); adenom.add( faa1 ); } } return new PartialFraction(A,P,cfactors,cdenom,afactors,adenom); } /** * GenPolynomial absolute factorization of a polynomial. * @param P GenPolynomial. * @return factors map container: [p_1 -> e_1, ..., p_k -> e_k] with P = * prod_{i=1,...,k} p_i**e_i. Note: K(alpha) not yet * minimal. */ public FactorsMap factorsAbsolute(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } SortedMap, Long> factors = new TreeMap, Long>(); if (P.isZERO()) { return new FactorsMap(P, factors); } //System.out.println("\nP_mult = " + P); GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar <= 1) { return baseFactorsAbsolute(P); } if (!pfac.coFac.isField()) { throw new IllegalArgumentException("only for field coefficients"); } if (P.degree() <= 1) { factors.put(P, 1L); return new FactorsMap(P, factors); } // factor over K (=C) SortedMap, Long> facs = factors(P); if (debug && !isFactorization(P, facs)) { throw new ArithmeticException("isFactorization = false"); } if (logger.isInfoEnabled()) { logger.info("all K factors = " + facs); // Q[X] //System.out.println("\nall K factors = " + facs); // Q[X] } SortedMap, Long> afactors = new TreeMap, Long>(); // factor over K(alpha) for ( Map.Entry, Long> me : facs.entrySet()) { GenPolynomial p = me.getKey(); Long e = me.getValue(); //facs.get(p); if (p.degree() <= 1) { factors.put(p, e); } else { Factors afacs = factorsAbsoluteIrreducible(p); if (afacs.afac == null) { // absolute irreducible factors.put(p, e); } else { afactors.put(afacs, e); } } } //System.out.println("K(alpha) factors multi = " + factors); return new FactorsMap(P, factors, afactors); } /** * GenPolynomial absolute factorization of a squarefree polynomial. * @param P squarefree and primitive GenPolynomial. * @return factors list container: [p_1,...,p_k] with P = prod_{i=1, ..., k} * p_i. Note: K(alpha) not yet minimal. */ // @Override public FactorsList factorsAbsoluteSquarefree(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List> factors = new ArrayList>(); if (P.isZERO()) { return new FactorsList(P, factors); } //System.out.println("\nP = " + P); GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar <= 1) { return baseFactorsAbsoluteSquarefree(P); } if (!pfac.coFac.isField()) { throw new IllegalArgumentException("only for field coefficients"); } if (P.degree() <= 1) { factors.add(P); return new FactorsList(P, factors); } // factor over K (=C) List> facs = factorsSquarefree(P); if (debug && !isFactorization(P, facs)) { throw new ArithmeticException("isFactorization = false"); } if (logger.isInfoEnabled()) { logger.info("all K factors = " + facs); // Q[X] //System.out.println("\nall K factors = " + facs); // Q[X] } List> afactors = new ArrayList>(); // factor over K(alpha) for (GenPolynomial p : facs) { if (p.degree() <= 1) { factors.add(p); } else { Factors afacs = factorsAbsoluteIrreducible(p); if (debug) { logger.info("K(alpha) factors = " + afacs); // K(alpha)[X] } if (afacs.afac == null) { // absolute irreducible factors.add(p); } else { afactors.add(afacs); } } } //System.out.println("K(alpha) factors = " + factors); return new FactorsList(P, factors, afactors); } /** * GenPolynomial absolute factorization of a irreducible polynomial. * @param P irreducible! GenPolynomial. * @return factors container: [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i * in K(alpha)[x] for suitable alpha and p_i irreducible over L[x], * where K \subset K(alpha) \subset L is an algebraically closed * field over K. Note: K(alpha) not yet minimal. */ public Factors factorsAbsoluteIrreducible(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } if (P.isZERO()) { return new Factors(P); } GenPolynomialRing pfac = P.ring; // K[x] if (pfac.nvar <= 1) { return baseFactorsAbsoluteIrreducible(P); } if (!pfac.coFac.isField()) { throw new IllegalArgumentException("only for field coefficients"); } //List> factors = new ArrayList>(); if (P.degree() <= 1) { return new Factors(P); } // find field extension K(alpha) GenPolynomial up = P; RingFactory cf = pfac.coFac; long cr = cf.characteristic().longValue(); // char might be larger if (cr == 0L) { cr = Long.MAX_VALUE; } long rp = 0L; for (int i = 0; i < (pfac.nvar - 1); i++) { rp = 0L; GenPolynomialRing nfac = pfac.contract(1); String[] vn = new String[] { pfac.getVars()[pfac.nvar - 1] }; GenPolynomialRing> rfac = new GenPolynomialRing>(nfac, 1, pfac.tord, vn); GenPolynomial> upr = PolyUtil. recursive(rfac, up); //System.out.println("upr = " + upr); GenPolynomial ep; do { if (rp >= cr) { throw new ArithmeticException("elements of prime field exhausted: " + cr); } C r = cf.fromInteger(rp); //cf.random(rp); //System.out.println("r = " + r); ep = PolyUtil. evaluateMainRecursive(nfac, upr, r); //System.out.println("ep = " + ep); rp++; } while (!isSquarefree(ep) /*todo: || ep.degree() <= 1*/); // max deg up = ep; pfac = nfac; } up = up.monic(); if (debug) { logger.info("P(" + rp + ") = " + up); //System.out.println("up = " + up); } if (debug && !isSquarefree(up)) { throw new ArithmeticException("not irreducible up = " + up); } if (up.degree(0) <= 1) { return new Factors(P); } // find irreducible factor of up List> UF = baseFactorsSquarefree(up); //System.out.println("UF = " + UF); FactorsList aUF = baseFactorsAbsoluteSquarefree(up); //System.out.println("aUF = " + aUF); AlgebraicNumberRing arfac = aUF.findExtensionField(); //System.out.println("arfac = " + arfac); long e = up.degree(0); // search factor polynomial with smallest degree for (int i = 0; i < UF.size(); i++) { GenPolynomial upi = UF.get(i); long d = upi.degree(0); if (1 <= d && d <= e) { up = upi; e = up.degree(0); } } if (up.degree(0) <= 1) { return new Factors(P); } if (debug) { logger.info("field extension by " + up); } List>> afactors = new ArrayList>>(); // setup field extension K(alpha) //String[] vars = new String[] { "z_" + Math.abs(up.hashCode() % 1000) }; String[] vars = pfac.newVars( "z_" ); pfac = pfac.copy(); String[] ovars = pfac.setVars(vars); // side effects! GenPolynomial aup = pfac.copy(up); // hack to exchange the variables //AlgebraicNumberRing afac = new AlgebraicNumberRing(aup,true); // since irreducible AlgebraicNumberRing afac = arfac; int depth = afac.depth(); //System.out.println("afac = " + afac); GenPolynomialRing> pafac = new GenPolynomialRing>(afac, P.ring.nvar, P.ring.tord, P.ring.getVars()); //System.out.println("pafac = " + pafac); // convert to K(alpha) GenPolynomial> Pa = PolyUtil . convertToRecAlgebraicCoefficients(depth, pafac, P); //System.out.println("Pa = " + Pa); // factor over K(alpha) FactorAbstract> engine = FactorFactory. getImplementation(afac); afactors = engine.factorsSquarefree(Pa); if (debug) { logger.info("K(alpha) factors multi = " + afactors); //System.out.println("K(alpha) factors = " + afactors); } if (afactors.size() <= 1) { return new Factors(P); } // normalize first factor to monic GenPolynomial> p1 = afactors.get(0); AlgebraicNumber p1c = p1.leadingBaseCoefficient(); if (!p1c.isONE()) { GenPolynomial> p2 = afactors.get(1); afactors.remove(p1); afactors.remove(p2); p1 = p1.divide(p1c); p2 = p2.multiply(p1c); afactors.add(p1); afactors.add(p2); } // recursion for splitting field // find minimal field extension K(beta) \subset K(alpha) return new Factors(P, afac, Pa, afactors); } /** * GenPolynomial is absolute factorization. * @param facs factors container. * @return true if P = prod_{i=1,...,r} p_i, else false. */ public boolean isAbsoluteFactorization(Factors facs) { if (facs == null) { throw new IllegalArgumentException("facs may not be null"); } if (facs.afac == null) { return true; } GenPolynomial> fa = facs.apoly; GenPolynomialRing> pafac = fa.ring; GenPolynomial> t = pafac.getONE(); for (GenPolynomial> f : facs.afactors) { t = t.multiply(f); } //return fa.equals(t) || fa.equals(t.negate()); boolean b = fa.equals(t) || fa.equals(t.negate()); if ( b ) { return b; } if ( facs.arfactors == null ) { return false; } for (Factors> arp : facs.arfactors) { t = t.multiply(arp.poly); } b = fa.equals(t) || fa.equals(t.negate()); if (!b) { System.out.println("\nFactors: " + facs); System.out.println("fa = " + fa); System.out.println("t = " + t); } return b; } /** * GenPolynomial is absolute factorization. * @param facs factors list container. * @return true if P = prod_{i=1,...,r} p_i, else false. */ public boolean isAbsoluteFactorization(FactorsList facs) { if (facs == null) { throw new IllegalArgumentException("facs may not be null"); } GenPolynomial P = facs.poly; GenPolynomial t = P.ring.getONE(); for (GenPolynomial f : facs.factors) { t = t.multiply(f); } if (P.equals(t) || P.equals(t.negate())) { return true; } if (facs.afactors == null) { return false; } for (Factors fs : facs.afactors) { if (!isAbsoluteFactorization(fs)) { return false; } t = t.multiply(facs.poly); } //return P.equals(t) || P.equals(t.negate()); boolean b = P.equals(t) || P.equals(t.negate()); if (!b) { System.out.println("\nFactorsList: " + facs); System.out.println("P = " + P); System.out.println("t = " + t); } return b; } /** * GenPolynomial is absolute factorization. * @param facs factors map container. * @return true if P = prod_{i=1,...,k} p_i**e_i , else false. */ public boolean isAbsoluteFactorization(FactorsMap facs) { if (facs == null) { throw new IllegalArgumentException("facs may not be null"); } GenPolynomial P = facs.poly; GenPolynomial t = P.ring.getONE(); for ( Map.Entry,Long> me : facs.factors.entrySet()) { GenPolynomial f = me.getKey(); long e = me.getValue(); //facs.factors.get(f); GenPolynomial g = Power.> positivePower(f, e); t = t.multiply(g); } if (P.equals(t) || P.equals(t.negate())) { return true; } if (facs.afactors == null) { return false; } for ( Map.Entry,Long> me : facs.afactors.entrySet()) { Factors fs = me.getKey(); if (!isAbsoluteFactorization(fs)) { return false; } long e = me.getValue(); // facs.afactors.get(fs); GenPolynomial g = Power.> positivePower(fs.poly, e); t = t.multiply(g); } boolean b = P.equals(t) || P.equals(t.negate()); if (!b) { System.out.println("\nFactorsMap: " + facs); System.out.println("P = " + P); System.out.println("t = " + t); } return b; } } jas-2.5/src/edu/jas/ufd/GreatestCommonDivisor.java0000644000175000017500000000546311677052522022413 0ustar giovannigiovanni/* * $Id: GreatestCommonDivisor.java 3843 2011-12-29 11:56:02Z kredel $ */ package edu.jas.ufd; import java.util.List; import java.io.Serializable; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Greatest common divisor algorithm interface. * @param coefficient type * @author Heinz Kredel * @usage To create classes that implement this interface use the * GreatestCommonDivisorFactory. It will select an appropriate * implementation based on the types of polynomial coefficients CT. * *
 * GreatestCommonDivisor<CT> engine = GCDFactory.<CT> getImplementation(cofac);
 * c = engine.gcd(a, b);
 * 
* * For example, if the coefficient type is BigInteger, the usage looks * like * *
 * BigInteger cofac = new BigInteger();
 * GreatestCommonDivisor<BigInteger> engine = GCDFactory.getImplementation(cofac);
 * c = engine.gcd(a, b);
 * 
* * @see edu.jas.ufd.GCDFactory#getImplementation */ public interface GreatestCommonDivisor> extends Serializable { /** * GenPolynomial content. * @param P GenPolynomial. * @return cont(P). */ public GenPolynomial content(GenPolynomial P); /** * GenPolynomial primitive part. * @param P GenPolynomial. * @return pp(P). */ public GenPolynomial primitivePart(GenPolynomial P); /** * GenPolynomial greatest comon divisor. * @param P GenPolynomial. * @param S GenPolynomial. * @return gcd(P,S). */ public GenPolynomial gcd(GenPolynomial P, GenPolynomial S); /** * GenPolynomial least comon multiple. * @param P GenPolynomial. * @param S GenPolynomial. * @return lcm(P,S). */ public GenPolynomial lcm(GenPolynomial P, GenPolynomial S); /** * GenPolynomial resultant. * The input polynomials are considered as univariate polynomials in the main variable. * @param P GenPolynomial. * @param S GenPolynomial. * @return res(P,S). * @throws UnsupportedOperationException if there is no implementation in the sub-class. */ public GenPolynomial resultant(GenPolynomial P, GenPolynomial S); /** * GenPolynomial co-prime list. * @param A list of GenPolynomials. * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant * a in A there exists b in B with b|a. B does not contain zero or * constant polynomials. */ public List> coPrime(List> A); /** * GenPolynomial test for co-prime list. * @param A list of GenPolynomials. * @return true if gcd(b,c) = 1 for all b != c in B, else false. */ public boolean isCoPrime(List> A); } jas-2.5/src/edu/jas/ufd/FactorModular.java0000644000175000017500000002011112004537436020646 0ustar giovannigiovanni/* * $Id: FactorModular.java 4067 2012-07-27 16:17:35Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.arith.ModLongRing; import edu.jas.arith.Modular; import edu.jas.arith.ModularRingFactory; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Modular coefficients factorization algorithms. This class implements * factorization methods for polynomials over (prime) modular integers. * @author Heinz Kredel */ public class FactorModular & Modular> extends FactorAbsolute { private static final Logger logger = Logger.getLogger(FactorModular.class); private final boolean debug = logger.isDebugEnabled(); /** * No argument constructor, do not use. */ @SuppressWarnings("unused") private FactorModular() { this((RingFactory) (Object) new ModLongRing(13, true)); // hack, 13 unimportant } /** * Constructor. * @param cfac coefficient ring factory. */ public FactorModular(RingFactory cfac) { super(cfac); } /** * GenPolynomial base distinct degree factorization. * @param P squarefree and monic GenPolynomial. * @return [e_1 -> p_1, ..., e_k -> p_k] with P = prod_{i=1,...,k} p_i * and p_i has only irreducible factors of degree e_i. */ public SortedMap> baseDistinctDegreeFactors(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } SortedMap> facs = new TreeMap>(); if (P.isZERO()) { return facs; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } ModularRingFactory mr = (ModularRingFactory) pfac.coFac; java.math.BigInteger m = mr.getIntegerModul().getVal(); //if (m.longValue() == 2L) { // logger.warn(this.getClass().getName() + " case p = 2 not implemented"); //} GenPolynomial x = pfac.univariate(0); GenPolynomial h = x; GenPolynomial f = P; GenPolynomial g; Power> pow = new Power>(pfac); long d = 0; while (d + 1 <= f.degree(0) / 2) { d++; h = pow.modPower(h, m, f); g = engine.gcd(h.subtract(x), f); if (!g.isONE()) { facs.put(d, g); f = f.divide(g); } } if (!f.isONE()) { d = f.degree(0); facs.put(d, f); } return facs; } /** * GenPolynomial base equal degree factorization. * @param P squarefree and monic GenPolynomial. * @param deg such that P has only irreducible factors of degree deg. * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. */ public List> baseEqualDegreeFactors(GenPolynomial P, long deg) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } List> facs = new ArrayList>(); if (P.isZERO()) { return facs; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } if (P.degree(0) == deg) { facs.add(P); return facs; } ModularRingFactory mr = (ModularRingFactory) pfac.coFac; java.math.BigInteger m = mr.getIntegerModul().getVal(); //System.out.println("m = " + m); boolean p2 = false; if (m.equals(java.math.BigInteger.valueOf(2L))) { p2 = true; //throw new RuntimeException(this.getClass().getName() + " case p = 2 not implemented"); } GenPolynomial one = pfac.getONE(); GenPolynomial t = pfac.univariate(0, 1L); GenPolynomial r; GenPolynomial h; GenPolynomial f = P; //GreatestCommonDivisor engine = GCDFactory. getImplementation(pfac.coFac); Power> pow = new Power>(pfac); GenPolynomial g = null; int degi = (int) deg; //f.degree(0); //System.out.println("deg = " + deg); BigInteger di = Power. positivePower(new BigInteger(m), deg); //System.out.println("di = " + di); java.math.BigInteger d = di.getVal(); //.longValue()-1; //System.out.println("d = " + d); d = d.shiftRight(1); // divide by 2 do { if (p2) { h = t; for (int i = 1; i < degi; i++) { h = t.sum(h.multiply(h)); h = h.remainder(f); } t = t.multiply(pfac.univariate(0, 2L)); //System.out.println("h = " + h); } else { r = pfac.random(17, degi, 2 * degi, 1.0f); if (r.degree(0) >= f.degree(0)) { r = r.remainder(f); } r = r.monic(); //System.out.println("r = " + r); h = pow.modPower(r, d, f).subtract(one); degi++; } g = engine.gcd(h, f); //System.out.println("g = " + g); } while (g.degree(0) == 0 || g.degree(0) == f.degree(0)); f = f.divide(g); facs.addAll(baseEqualDegreeFactors(f, deg)); facs.addAll(baseEqualDegreeFactors(g, deg)); return facs; } /** * GenPolynomial base factorization of a squarefree polynomial. * @param P squarefree and monic! GenPolynomial. * @return [p_1,...,p_k] with P = prod_{i=1,...,r} p_i. */ @Override public List> baseFactorsSquarefree(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List> factors = new ArrayList>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } if (!P.leadingBaseCoefficient().isONE()) { throw new IllegalArgumentException("ldcf(P) != 1: " + P); } SortedMap> dfacs = baseDistinctDegreeFactors(P); if (debug) { logger.info("dfacs = " + dfacs); //System.out.println("dfacs = " + dfacs); } for (Map.Entry> me : dfacs.entrySet()) { Long e = me.getKey(); GenPolynomial f = me.getValue(); // dfacs.get(e); List> efacs = baseEqualDegreeFactors(f, e); if (debug) { logger.info("efacs " + e + " = " + efacs); //System.out.println("efacs " + e + " = " + efacs); } factors.addAll(efacs); } //System.out.println("factors = " + factors); factors = PolyUtil. monic(factors); SortedSet> ss = new TreeSet>(factors); //System.out.println("sorted = " + ss); factors.clear(); factors.addAll(ss); return factors; } } jas-2.5/src/edu/jas/ufd/Squarefree.java0000644000175000017500000000776312000264162020215 0ustar giovannigiovanni/* * $Id: Squarefree.java 3989 2012-07-14 12:39:14Z kredel $ */ package edu.jas.ufd; import java.io.Serializable; import java.util.List; import java.util.SortedMap; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Squarefree decomposition interface. * @param coefficient type * @author Heinz Kredel * @usage To create objects that implement the Squarefree * interface use the SquarefreeFactory. It will select an * appropriate implementation based on the types of polynomial * coefficients C. To obtain an implementation use * getImplementation(), it returns an object of a class * which extends the SquarefreeAbstract class which * implements the Squarefree interface. * *
 * Squarefree<CT> engine;
 * engine = SquarefreeFactory.<CT> getImplementation(cofac);
 * c = engine.squarefreeFactors(a);
 * 
* * For example, if the coefficient type is BigInteger, the usage looks like * *
 * BigInteger cofac = new BigInteger();
 * Squarefree<BigInteger> engine;
 * engine = SquarefreeFactory.getImplementation(cofac);
 * Sm = engine.sqaurefreeFactors(poly);
 * 
* * @see edu.jas.ufd.SquarefreeFactory#getImplementation */ public interface Squarefree> extends Serializable { /** * GenPolynomial greatest squarefree divisor. * @param P GenPolynomial. * @return squarefree(pp(P)). */ public GenPolynomial squarefreePart(GenPolynomial P); /** * GenPolynomial test if is squarefree. * @param P GenPolynomial. * @return true if P is squarefree, else false. */ public boolean isSquarefree(GenPolynomial P); /** * GenPolynomial list test if squarefree. * @param L list of GenPolynomial. * @return true if each P in L is squarefree, else false. */ public boolean isSquarefree(List> L); /** * GenPolynomial squarefree factorization. * @param P GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} * and p_i squarefree. */ public SortedMap, Long> squarefreeFactors(GenPolynomial P); /** * GenPolynomial is (squarefree) factorization. * @param P GenPolynomial. * @param F = [p_1,...,p_k]. * @return true if P = prod_{i=1,...,r} p_i, else false. */ public boolean isFactorization(GenPolynomial P, List> F); /** * GenPolynomial is (squarefree) factorization. * @param P GenPolynomial. * @param F = [p_1 -> e_1, ..., p_k -> e_k]. * @return true if P = prod_{i=1,...,k} p_i**e_i, else false. */ public boolean isFactorization(GenPolynomial P, SortedMap, Long> F); /** * GenPolynomial squarefree and co-prime list. * @param A list of GenPolynomials. * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant * a in A there exists b in B with b|a and each b in B is * squarefree. B does not contain zero or constant polynomials. */ public List> coPrimeSquarefree(List> A); /** * GenPolynomial squarefree and co-prime list. * @param a polynomial. * @param P squarefree co-prime list of GenPolynomials. * @return B with gcd(b,c) = 1 for all b != c in B and for non-constant a * there exists b in P with b|a. B does not contain zero or constant * polynomials. */ public List> coPrimeSquarefree(GenPolynomial a, List> P); /** * Test if list of GenPolynomials is squarefree and co-prime. * @param B list of GenPolynomials. * @return true, if for all b != c in B gcd(b,c) = 1 and * each b in B is squarefree, else false. */ public boolean isCoPrimeSquarefree(List> B); } jas-2.5/src/edu/jas/ufd/SquarefreeInfiniteFieldCharP.java0000644000175000017500000003017612014234362023563 0ustar giovannigiovanni/* * $Id: SquarefreeInfiniteFieldCharP.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.ufd; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.Monomial; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Squarefree decomposition for infinite coefficient fields of characteristic p. * @author Heinz Kredel */ public class SquarefreeInfiniteFieldCharP> extends SquarefreeFieldCharP> { private static final Logger logger = Logger.getLogger(SquarefreeInfiniteFieldCharP.class); //private final boolean debug = logger.isDebugEnabled(); /** * Squarefree engine for infinite ring of characteristic p base coefficients. */ protected final SquarefreeAbstract qengine; /** * Constructor. */ public SquarefreeInfiniteFieldCharP(RingFactory> fac) { super(fac); // isFinite() predicate now present if (fac.isFinite()) { throw new IllegalArgumentException("fac must be in-finite"); } QuotientRing qfac = (QuotientRing) fac; GenPolynomialRing rfac = qfac.ring; qengine = (SquarefreeAbstract) SquarefreeFactory. getImplementation(rfac); //qengine = new SquarefreeFiniteFieldCharP(rfac.coFac); //qengine = new SquarefreeInfiniteRingCharP( rfac.coFac ); } /* --------- quotient char-th roots --------------------- */ /** * Squarefree factors of a Quotient. * @param P Quotient. * @return [p_1 -> e_1,...,p_k - > e_k] with P = prod_{i=1, ..., k} * p_i**e_k. */ @Override public SortedMap, Long> squarefreeFactors(Quotient P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } SortedMap, Long> factors = new TreeMap, Long>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.put(P, 1L); return factors; } GenPolynomial num = P.num; GenPolynomial den = P.den; QuotientRing pfac = P.ring; GenPolynomial one = pfac.ring.getONE(); if (!num.isONE()) { SortedMap, Long> nfac = qengine.squarefreeFactors(num); //System.out.println("nfac = " + nfac); for (Map.Entry, Long> me : nfac.entrySet()) { GenPolynomial nfp = me.getKey(); Quotient nf = new Quotient(pfac, nfp); factors.put(nf, me.getValue()); //nfac.get(nfp)); } } if (den.isONE()) { if (factors.size() == 0) { factors.put(P, 1L); } return factors; } SortedMap, Long> dfac = qengine.squarefreeFactors(den); //System.out.println("dfac = " + dfac); for (Map.Entry, Long> me : dfac.entrySet()) { GenPolynomial dfp = me.getKey(); Quotient df = new Quotient(pfac, one, dfp); factors.put(df, me.getValue()); //dfac.get(dfp)); } if (factors.size() == 0) { factors.put(P, 1L); } return factors; } /** * Characteristics root of a Quotient. * @param P Quotient. * @return [p -> k] if exists k with e=charactristic(P)*k and P = p**e, * else null. */ public SortedMap, Long> rootCharacteristic(Quotient P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } java.math.BigInteger c = P.ring.characteristic(); if (c.signum() == 0) { return null; } SortedMap, Long> root = new TreeMap, Long>(); if (P.isZERO()) { return root; } if (P.isONE()) { root.put(P, 1L); return root; } SortedMap, Long> sf = squarefreeFactors(P); if (sf.size() == 0) { return null; } if (logger.isInfoEnabled()) { logger.info("sf,quot = " + sf); } // better: test if sf.size() == 2 // no, since num and den factors Long k = null; Long cl = c.longValue(); for (Map.Entry, Long> me : sf.entrySet()) { Quotient p = me.getKey(); //System.out.println("p = " + p); if (p.isConstant()) { // todo: check for non-constants in coefficients continue; } Long e = me.getValue(); //sf.get(p); long E = e.longValue(); long r = E % cl; if (r != 0) { //System.out.println("r = " + r); return null; } if (k == null) { k = e; } else if (k >= e) { k = e; } } if (k == null) { k = 1L; //return null; } // now c divides all exponents of non constant elements for (Map.Entry, Long> me : sf.entrySet()) { Quotient q = me.getKey(); Long e = me.getValue(); //sf.get(q); //System.out.println("q = " + q + ", e = " + e); if (e >= k) { e = e / cl; //q = Power.> positivePower(q, e); root.put(q, e); } else { // constant case root.put(q, e); } } //System.out.println("root = " + root); return root; } /** * GenPolynomial char-th root main variable. * @param P univariate GenPolynomial with Quotient coefficients. * @return char-th_rootOf(P), or null, if P is no char-th root. */ public GenPolynomial> rootCharacteristic(GenPolynomial> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { // go to recursion GenPolynomialRing> cfac = pfac.contract(1); GenPolynomialRing>> rfac = new GenPolynomialRing>>( cfac, 1); GenPolynomial>> Pr = PolyUtil.> recursive(rfac, P); GenPolynomial>> Prc = recursiveUnivariateRootCharacteristic(Pr); if (Prc == null) { return null; } GenPolynomial> D = PolyUtil.> distribute(pfac, Prc); return D; } RingFactory> rf = pfac.coFac; if (rf.characteristic().signum() != 1) { // basePthRoot not possible throw new IllegalArgumentException(P.getClass().getName() + " only for ModInteger polynomials " + rf); } long mp = rf.characteristic().longValue(); GenPolynomial> d = pfac.getZERO().copy(); for (Monomial> m : P) { ExpVector f = m.e; long fl = f.getVal(0); if (fl % mp != 0) { return null; } fl = fl / mp; SortedMap, Long> sm = rootCharacteristic(m.c); if (sm == null) { return null; } if (logger.isInfoEnabled()) { logger.info("sm,root = " + sm); } Quotient r = rf.getONE(); for (Map.Entry, Long> me : sm.entrySet()) { Quotient rp = me.getKey(); long gl = me.getValue(); // sm.get(rp); if (gl > 1) { rp = Power.> positivePower(rp, gl); } r = r.multiply(rp); } ExpVector e = ExpVector.create(1, 0, fl); d.doPutToMap(e, r); } logger.info("sm,root,d = " + d); return d; } /** * GenPolynomial char-th root univariate polynomial. * @param P GenPolynomial. * @return char-th_rootOf(P). */ @Override public GenPolynomial> baseRootCharacteristic(GenPolynomial> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { // basePthRoot not possible by return type throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); } RingFactory> rf = pfac.coFac; if (rf.characteristic().signum() != 1) { // basePthRoot not possible throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); } long mp = rf.characteristic().longValue(); GenPolynomial> d = pfac.getZERO().copy(); for (Monomial> m : P) { //System.out.println("m = " + m); ExpVector f = m.e; long fl = f.getVal(0); if (fl % mp != 0) { return null; } fl = fl / mp; SortedMap, Long> sm = rootCharacteristic(m.c); if (sm == null) { return null; } if (logger.isInfoEnabled()) { logger.info("sm,base,root = " + sm); } Quotient r = rf.getONE(); for (Map.Entry, Long> me : sm.entrySet()) { Quotient rp = me.getKey(); //System.out.println("rp = " + rp); long gl = me.getValue(); //sm.get(rp); //System.out.println("gl = " + gl); Quotient re = rp; if (gl > 1) { re = Power.> positivePower(rp, gl); } //System.out.println("re = " + re); r = r.multiply(re); } ExpVector e = ExpVector.create(1, 0, fl); d.doPutToMap(e, r); } if (logger.isInfoEnabled()) { logger.info("sm,base,d = " + d); } return d; } /** * GenPolynomial char-th root univariate polynomial with polynomial * coefficients. * @param P recursive univariate GenPolynomial. * @return char-th_rootOf(P), or null if P is no char-th root. */ @Override public GenPolynomial>> recursiveUnivariateRootCharacteristic( GenPolynomial>> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing>> pfac = P.ring; if (pfac.nvar > 1) { // basePthRoot not possible by return type throw new IllegalArgumentException(P.getClass().getName() + " only for univariate recursive polynomials"); } RingFactory>> rf = pfac.coFac; if (rf.characteristic().signum() != 1) { // basePthRoot not possible throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); } long mp = rf.characteristic().longValue(); GenPolynomial>> d = pfac.getZERO().copy(); for (Monomial>> m : P) { ExpVector f = m.e; long fl = f.getVal(0); if (fl % mp != 0) { return null; } fl = fl / mp; GenPolynomial> r = rootCharacteristic(m.c); if (r == null) { return null; } ExpVector e = ExpVector.create(1, 0, fl); d.doPutToMap(e, r); } return d; } } jas-2.5/src/edu/jas/ufd/SquarefreeRingChar0.java0000644000175000017500000003346512014156644021723 0ustar giovannigiovanni/* * $Id: SquarefreeRingChar0.java 4112 2012-08-19 12:35:48Z kredel $ */ package edu.jas.ufd; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Squarefree decomposition for coefficient rings of characteristic 0. * @author Heinz Kredel */ public class SquarefreeRingChar0> extends SquarefreeAbstract /*implements Squarefree*/{ private static final Logger logger = Logger.getLogger(SquarefreeRingChar0.class); //private final boolean debug = logger.isDebugEnabled(); /** * Factory for ring of characteristic 0 coefficients. */ protected final RingFactory coFac; /** * Constructor. */ public SquarefreeRingChar0(RingFactory fac) { super(GCDFactory. getProxy(fac)); if (fac.isField()) { throw new IllegalArgumentException("fac is a field: use SquarefreeFieldChar0"); } if (fac.characteristic().signum() != 0) { throw new IllegalArgumentException("characterisic(fac) must be zero"); } coFac = fac; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return getClass().getName() + " with " + engine + " over " + coFac; } /** * GenPolynomial polynomial greatest squarefree divisor. * @param P GenPolynomial. * @return squarefree(pp(P)). */ @Override public GenPolynomial baseSquarefreePart(GenPolynomial P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } GenPolynomial pp = engine.basePrimitivePart(P); if (pp.isConstant()) { return pp; } GenPolynomial d = PolyUtil. baseDeriviative(pp); d = engine.basePrimitivePart(d); GenPolynomial g = engine.baseGcd(pp, d); g = engine.basePrimitivePart(g); GenPolynomial q = PolyUtil. basePseudoDivide(pp, g); q = engine.basePrimitivePart(q); return q; } /** * GenPolynomial polynomial squarefree factorization. * @param A GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} * and p_i squarefree. */ @Override public SortedMap, Long> baseSquarefreeFactors(GenPolynomial A) { SortedMap, Long> sfactors = new TreeMap, Long>(); if (A == null || A.isZERO()) { return sfactors; } if (A.isConstant()) { sfactors.put(A, 1L); return sfactors; } GenPolynomialRing pfac = A.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } C ldbcf = A.leadingBaseCoefficient(); if (!ldbcf.isONE()) { C cc = engine.baseContent(A); A = A.divide(cc); GenPolynomial f1 = pfac.getONE().multiply(cc); //System.out.println("gcda sqf f1 = " + f1); sfactors.put(f1, 1L); } GenPolynomial T0 = A; GenPolynomial Tp; GenPolynomial T = null; GenPolynomial V = null; long k = 0L; boolean init = true; while (true) { if (init) { if (T0.isConstant() || T0.isZERO()) { break; } Tp = PolyUtil. baseDeriviative(T0); T = engine.baseGcd(T0, Tp); T = engine.basePrimitivePart(T); V = PolyUtil. basePseudoDivide(T0, T); //System.out.println("iT0 = " + T0); //System.out.println("iTp = " + Tp); //System.out.println("iT = " + T); //System.out.println("iV = " + V); k = 0L; init = false; } if (V.isConstant()) { break; } k++; GenPolynomial W = engine.baseGcd(T, V); W = engine.basePrimitivePart(W); GenPolynomial z = PolyUtil. basePseudoDivide(V, W); //System.out.println("W = " + W); //System.out.println("z = " + z); V = W; T = PolyUtil. basePseudoDivide(T, V); //System.out.println("V = " + V); //System.out.println("T = " + T); if (z.degree(0) > 0) { if (ldbcf.isONE() && !z.leadingBaseCoefficient().isONE()) { z = engine.basePrimitivePart(z); logger.info("z,pp = " + z); } sfactors.put(z, k); } } return normalizeFactorization(sfactors); } /** * GenPolynomial recursive univariate polynomial greatest squarefree * divisor. * @param P recursive univariate GenPolynomial. * @return squarefree(pp(P)). */ @Override public GenPolynomial> recursiveUnivariateSquarefreePart(GenPolynomial> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " only for multivariate polynomials"); } // squarefree content GenPolynomial> pp = P; GenPolynomial Pc = engine.recursiveContent(P); Pc = engine.basePrimitivePart(Pc); //System.out.println("Pc,bPP = " + Pc); if (!Pc.isONE()) { pp = PolyUtil. coefficientPseudoDivide(pp, Pc); //System.out.println("pp,sqp = " + pp); //GenPolynomial Pr = squarefreePart(Pc); //Pr = engine.basePrimitivePart(Pr); //System.out.println("Pr,bPP = " + Pr); } if (pp.leadingExpVector().getVal(0) < 1) { //System.out.println("pp = " + pp); //System.out.println("Pc = " + Pc); return pp.multiply(Pc); } GenPolynomial> d = PolyUtil. recursiveDeriviative(pp); //System.out.println("d = " + d); GenPolynomial> g = engine.recursiveUnivariateGcd(pp, d); //System.out.println("g,rec = " + g); g = engine.baseRecursivePrimitivePart(g); //System.out.println("g,bPP = " + g); GenPolynomial> q = PolyUtil. recursivePseudoDivide(pp, g); q = engine.baseRecursivePrimitivePart(q); //System.out.println("q,bPP = " + q); return q.multiply(Pc); } /** * GenPolynomial recursive univariate polynomial squarefree factorization. * @param P recursive univariate GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} * and p_i squarefree. */ @Override public SortedMap>, Long> recursiveUnivariateSquarefreeFactors( GenPolynomial> P) { SortedMap>, Long> sfactors = new TreeMap>, Long>(); if (P == null || P.isZERO()) { return sfactors; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { // recursiveContent not possible by return type throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials"); } // if base coefficient ring is a field, make monic GenPolynomialRing cfac = (GenPolynomialRing) pfac.coFac; C bcc = engine.baseRecursiveContent(P); if (!bcc.isONE()) { GenPolynomial lc = cfac.getONE().multiply(bcc); GenPolynomial> pl = pfac.getONE().multiply(lc); sfactors.put(pl, 1L); P = PolyUtil. baseRecursiveDivide(P, bcc); } // factors of content GenPolynomial Pc = engine.recursiveContent(P); if (logger.isInfoEnabled()) { logger.info("Pc = " + Pc); } Pc = engine.basePrimitivePart(Pc); //System.out.println("Pc,PP = " + Pc); if (!Pc.isONE()) { P = PolyUtil. coefficientPseudoDivide(P, Pc); } SortedMap, Long> rsf = squarefreeFactors(Pc); if (logger.isInfoEnabled()) { logger.info("rsf = " + rsf); } // add factors of content for (Map.Entry, Long> me : rsf.entrySet()) { GenPolynomial c = me.getKey(); if (!c.isONE()) { GenPolynomial> cr = pfac.getONE().multiply(c); Long rk = me.getValue(); //rsf.get(c); sfactors.put(cr, rk); } } // factors of recursive polynomial GenPolynomial> T0 = P; GenPolynomial> Tp; GenPolynomial> T = null; GenPolynomial> V = null; long k = 0L; boolean init = true; while (true) { if (init) { if (T0.isConstant() || T0.isZERO()) { break; } Tp = PolyUtil. recursiveDeriviative(T0); T = engine.recursiveUnivariateGcd(T0, Tp); T = engine.baseRecursivePrimitivePart(T); V = PolyUtil. recursivePseudoDivide(T0, T); //System.out.println("iT0 = " + T0); //System.out.println("iTp = " + Tp); //System.out.println("iT = " + T); //System.out.println("iV = " + V); k = 0L; init = false; } if (V.isConstant()) { break; } k++; GenPolynomial> W = engine.recursiveUnivariateGcd(T, V); W = engine.baseRecursivePrimitivePart(W); GenPolynomial> z = PolyUtil. recursivePseudoDivide(V, W); //System.out.println("W = " + W); //System.out.println("z = " + z); V = W; T = PolyUtil. recursivePseudoDivide(T, V); //System.out.println("V = " + V); //System.out.println("T = " + T); //was: if ( z.degree(0) > 0 ) { if (!z.isONE() && !z.isZERO()) { z = engine.baseRecursivePrimitivePart(z); sfactors.put(z, k); } } return sfactors; } /** * GenPolynomial greatest squarefree divisor. * @param P GenPolynomial. * @return squarefree(pp(P)). */ @Override public GenPolynomial squarefreePart(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return baseSquarefreePart(P); } GenPolynomialRing cfac = pfac.contract(1); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1); GenPolynomial> Pr = PolyUtil. recursive(rfac, P); GenPolynomial Pc = engine.recursiveContent(Pr); Pr = PolyUtil. coefficientPseudoDivide(Pr, Pc); GenPolynomial Ps = squarefreePart(Pc); GenPolynomial> PP = recursiveUnivariateSquarefreePart(Pr); GenPolynomial> PS = PP.multiply(Ps); GenPolynomial D = PolyUtil. distribute(pfac, PS); return D; } /** * GenPolynomial squarefree factorization. * @param P GenPolynomial. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} * and p_i squarefree. */ @Override public SortedMap, Long> squarefreeFactors(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return baseSquarefreeFactors(P); } SortedMap, Long> sfactors = new TreeMap, Long>(); if (P.isZERO()) { return sfactors; } GenPolynomialRing cfac = pfac.contract(1); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1); GenPolynomial> Pr = PolyUtil. recursive(rfac, P); SortedMap>, Long> PP = recursiveUnivariateSquarefreeFactors(Pr); for (Map.Entry>, Long> m : PP.entrySet()) { Long i = m.getValue(); GenPolynomial> Dr = m.getKey(); GenPolynomial D = PolyUtil. distribute(pfac, Dr); sfactors.put(D, i); } return normalizeFactorization(sfactors); } /** * Coefficients squarefree factorization. * @param P coefficient. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} * and p_i squarefree. */ @Override public SortedMap squarefreeFactors(C P) { throw new UnsupportedOperationException("method not implemented"); } } jas-2.5/src/edu/jas/ufd/QuotientRing.java0000644000175000017500000002536012137713752020553 0ustar giovannigiovanni/* * $Id: QuotientRing.java 4406 2013-04-30 10:07:39Z kredel $ */ package edu.jas.ufd; import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.apache.log4j.Logger; import edu.jas.kern.StringUtil; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Quotient ring factory based on GenPolynomial with RingElem interface. Objects * of this class are immutable. * @author Heinz Kredel */ public class QuotientRing> implements RingFactory> { private static final Logger logger = Logger.getLogger(QuotientRing.class); //private boolean debug = logger.isDebugEnabled(); /** * Polynomial ring of the factory. */ public final GenPolynomialRing ring; /** * GCD engine of the factory. */ public final GreatestCommonDivisor engine; /** * Use GCD of package edu.jas.ufd. */ public final boolean ufdGCD; /** * The constructor creates a QuotientRing object from a GenPolynomialRing. * @param r polynomial ring. */ public QuotientRing(GenPolynomialRing r) { this(r, true); } /** * The constructor creates a QuotientRing object from a GenPolynomialRing. * @param r polynomial ring. * @param ufdGCD flag, if syzygy or gcd based algorithm used for engine. */ public QuotientRing(GenPolynomialRing r, boolean ufdGCD) { ring = r; this.ufdGCD = ufdGCD; // if (!ufdGCD) { // engine = null; // return; // } engine = GCDFactory. getProxy(ring.coFac); logger.debug("quotient ring constructed"); } /** * Divide. * @param n first polynomial. * @param d second polynomial. * @return divide(n,d) */ protected GenPolynomial divide(GenPolynomial n, GenPolynomial d) { return PolyUtil. basePseudoDivide(n, d); } /** * Greatest common divisor. * @param n first polynomial. * @param d second polynomial. * @return gcd(n,d) */ protected GenPolynomial gcd(GenPolynomial n, GenPolynomial d) { if (ufdGCD) { return engine.gcd(n, d); } return engine.gcd(n, d); //return syzGcd(n, d); } /* * Least common multiple. Just for fun, is not efficient. * @param n first polynomial. * @param d second polynomial. * @return lcm(n,d) */ // protected GenPolynomial syzLcm(GenPolynomial n, GenPolynomial d) { // List> list = new ArrayList>(1); // list.add(n); // Ideal N = new Ideal(n.ring, list, true); // list = new ArrayList>(1); // list.add(d); // Ideal D = new Ideal(n.ring, list, true); // Ideal L = N.intersect(D); // if (L.getList().size() != 1) { // throw new RuntimeException("lcm not uniqe"); // } // GenPolynomial lcm = L.getList().get(0); // return lcm; // } /* * Greatest common divisor. Just for fun, is not efficient. * @param n first polynomial. * @param d second polynomial. * @return gcd(n,d) */ // protected GenPolynomial syzGcd(GenPolynomial n, GenPolynomial d) { // if (n.isZERO()) { // return d; // } // if (d.isZERO()) { // return n; // } // if (n.isONE()) { // return n; // } // if (d.isONE()) { // return d; // } // GenPolynomial p = n.multiply(d); // GenPolynomial lcm = syzLcm(n, d); // GenPolynomial gcd = divide(p, lcm); // return gcd; // } /** * Is this structure finite or infinite. * @return true if this structure is finite, else false. * @see edu.jas.structure.ElemFactory#isFinite() */ public boolean isFinite() { return false; } /** * Copy Quotient element c. * @param c * @return a copy of c. */ public Quotient copy(Quotient c) { return new Quotient(c.ring, c.num, c.den, true); } /** * Get the zero element. * @return 0 as Quotient. */ public Quotient getZERO() { return new Quotient(this, ring.getZERO()); } /** * Get the one element. * @return 1 as Quotient. */ public Quotient getONE() { return new Quotient(this, ring.getONE()); } /** * Get a list of the generating elements. * @return list of generators for the algebraic structure. * @see edu.jas.structure.ElemFactory#generators() */ public List> generators() { List> pgens = ring.generators(); List> gens = new ArrayList>(pgens.size()); for (GenPolynomial p : pgens) { Quotient q = new Quotient(this, p); gens.add(q); } return gens; } /** * Query if this ring is commutative. * @return true if this ring is commutative, else false. */ public boolean isCommutative() { return ring.isCommutative(); } /** * Query if this ring is associative. * @return true if this ring is associative, else false. */ public boolean isAssociative() { return ring.isAssociative(); } /** * Query if this ring is a field. * @return true. */ public boolean isField() { return true; } /** * Characteristic of this ring. * @return characteristic of this ring. */ public java.math.BigInteger characteristic() { return ring.characteristic(); } /** * Get a Quotient element from a BigInteger value. * @param a BigInteger. * @return a Quotient. */ public Quotient fromInteger(java.math.BigInteger a) { return new Quotient(this, ring.fromInteger(a)); } /** * Get a Quotient element from a long value. * @param a long. * @return a Quotient. */ public Quotient fromInteger(long a) { return new Quotient(this, ring.fromInteger(a)); } /** * Get the String representation as RingFactory. * @see java.lang.Object#toString() */ @Override public String toString() { String s = null; if (ring.coFac.characteristic().signum() == 0) { s = "RatFunc"; } else { s = "ModFunc"; } return s + "( " + ring.toString() + " )"; } /** * Get a scripting compatible string representation. * @return script compatible representation for this ElemFactory. * @see edu.jas.structure.ElemFactory#toScript() */ //JAVA6only: @Override public String toScript() { // Python case return "RF(" + ring.toScript() + ")"; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") // not jet working public boolean equals(Object b) { if (!(b instanceof QuotientRing)) { return false; } QuotientRing a = null; try { a = (QuotientRing) b; } catch (ClassCastException e) { } if (a == null) { return false; } return ring.equals(a.ring); } /** * Hash code for this quotient ring. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h; h = ring.hashCode(); return h; } /** * Quotient random. * @param n such that 0 ≤ v ≤ (2n-1). * @return a random residue element. */ public Quotient random(int n) { GenPolynomial r = ring.random(n).monic(); GenPolynomial s = ring.random(n).monic(); while (s.isZERO()) { s = ring.random(n).monic(); } return new Quotient(this, r, s, false); } /** * Generate a random quotient polynomial. * @param k bitsize of random coefficients. * @param l number of terms. * @param d maximal degree in each variable. * @param q density of nozero exponents. * @return a random quotient polynomial. */ public Quotient random(int k, int l, int d, float q) { GenPolynomial r = ring.random(k, l, d, q).monic(); GenPolynomial s = ring.random(k, l, d, q).monic(); while (s.isZERO()) { s = ring.random(k, l, d, q).monic(); } return new Quotient(this, r, s, false); } /** * Quotient random. * @param n such that 0 ≤ v ≤ (2n-1). * @param rnd is a source for random bits. * @return a random quotient element. */ public Quotient random(int n, Random rnd) { GenPolynomial r = ring.random(n, rnd).monic(); GenPolynomial s = ring.random(n, rnd).monic(); while (s.isZERO()) { s = ring.random(n, rnd).monic(); } return new Quotient(this, r, s, false); } /** * Parse Quotient from String. Syntax: "{ polynomial | polynomial }" or * "{ polynomial }" or " polynomial | polynomial " or " polynomial " * @param s String. * @return Quotient from s. */ public Quotient parse(String s) { int i = s.indexOf("{"); if (i >= 0) { s = s.substring(i + 1); } i = s.lastIndexOf("}"); if (i >= 0) { s = s.substring(0, i); } i = s.indexOf("|"); if (i < 0) { GenPolynomial n = ring.parse(s); return new Quotient(this, n); } String s1 = s.substring(0, i); String s2 = s.substring(i + 1); GenPolynomial n = ring.parse(s1); GenPolynomial d = ring.parse(s2); return new Quotient(this, n, d); } /** * Parse Quotient from Reader. * @param r Reader. * @return next Quotient from r. */ public Quotient parse(Reader r) { String s = StringUtil.nextPairedString(r, '{', '}'); return parse(s); } /** * Degree of extension field. * @return degree of this extension field, -1 for transcendental extension. */ public long extensionDegree() { long degree = -1L; if (ring.nvar <= 0) { degree = 0L; } return degree; } } jas-2.5/src/edu/jas/ufd/SquarefreeInfiniteAlgebraicFieldCharP.java0000644000175000017500000004320012014234362025345 0ustar giovannigiovanni/* * $Id: SquarefreeInfiniteAlgebraicFieldCharP.java 3290 2010-08-26 09:18:48Z * kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.gb.GroebnerBaseAbstract; import edu.jas.gb.GroebnerBaseSeq; import edu.jas.gb.Reduction; import edu.jas.gb.ReductionSeq; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.Monomial; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Squarefree decomposition for algebraic extensions of infinite coefficient * fields of characteristic p > 0. * @author Heinz Kredel */ public class SquarefreeInfiniteAlgebraicFieldCharP> extends SquarefreeFieldCharP> { private static final Logger logger = Logger.getLogger(SquarefreeInfiniteAlgebraicFieldCharP.class); //private final boolean debug = logger.isDebugEnabled(); /** * Squarefree engine for infinite ring of characteristic p base coefficients. */ protected final SquarefreeAbstract aengine; /** * Constructor. */ public SquarefreeInfiniteAlgebraicFieldCharP(RingFactory> fac) { super(fac); // isFinite() predicate now present if (fac.isFinite()) { throw new IllegalArgumentException("fac must be in-finite"); } AlgebraicNumberRing afac = (AlgebraicNumberRing) fac; GenPolynomialRing rfac = afac.ring; //System.out.println("rfac = " + rfac); //System.out.println("rfac = " + rfac.coFac); aengine = SquarefreeFactory. getImplementation(rfac); //System.out.println("aengine = " + aengine); } /* --------- algebraic number char-th roots --------------------- */ /** * Squarefree factors of a AlgebraicNumber. * @param P AlgebraicNumber. * @return [p_1 -> e_1,...,p_k - > e_k] with P = prod_{i=1, ..., k} * p_i**e_k. */ @Override public SortedMap, Long> squarefreeFactors(AlgebraicNumber P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } SortedMap, Long> factors = new TreeMap, Long>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.put(P, 1L); return factors; } GenPolynomial an = P.val; AlgebraicNumberRing pfac = P.ring; if (!an.isONE()) { //System.out.println("an = " + an); //System.out.println("aengine = " + aengine); SortedMap, Long> nfac = aengine.squarefreeFactors(an); //System.out.println("nfac = " + nfac); for (Map.Entry, Long> me : nfac.entrySet()) { GenPolynomial nfp = me.getKey(); AlgebraicNumber nf = new AlgebraicNumber(pfac, nfp); factors.put(nf, me.getValue()); //nfac.get(nfp)); } } if (factors.size() == 0) { factors.put(P, 1L); } return factors; } /** * Characteristics root of a AlgebraicNumber. * @param P AlgebraicNumber. * @return [p -> k] if exists k with e=charactristic(P)*k and P = p**e, * else null. */ public SortedMap, Long> rootCharacteristic(AlgebraicNumber P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } java.math.BigInteger c = P.ring.characteristic(); if (c.signum() == 0) { return null; } SortedMap, Long> root = new TreeMap, Long>(); if (P.isZERO()) { return root; } if (P.isONE()) { root.put(P, 1L); return root; } // generate system of equations AlgebraicNumberRing afac = P.ring; long deg = afac.modul.degree(0); int d = (int) deg; String[] vn = GenPolynomialRing.newVars("c", d); GenPolynomialRing> pfac = new GenPolynomialRing>(afac, d, vn); List>> uv = (List>>) pfac .univariateList(); GenPolynomial> cp = pfac.getZERO(); GenPolynomialRing apfac = afac.ring; long i = 0; for (GenPolynomial> pa : uv) { GenPolynomial ca = apfac.univariate(0, i++); GenPolynomial> pb = pa.multiply(new AlgebraicNumber(afac, ca)); cp = cp.sum(pb); } GenPolynomial> cpp = Power .>> positivePower(cp, c); if (logger.isInfoEnabled()) { logger.info("cp = " + cp); logger.info("cp^p = " + cpp); logger.info("P = " + P); } GenPolynomialRing ppfac = new GenPolynomialRing(apfac.coFac, pfac); List> gl = new ArrayList>(); if (deg == c.longValue() && afac.modul.length() == 2) { logger.info("deg(" + deg + ") == char_p(" + c.longValue() + ")"); for (Monomial> m : cpp) { ExpVector f = m.e; AlgebraicNumber a = m.c; //System.out.println("a = " + a + " : " + a.toScriptFactory()); GenPolynomial ap = a.val; for (Monomial ma : ap) { ExpVector e = ma.e; C cc = ma.c; C pc = P.val.coefficient(e); C cc1 = ((RingFactory) pc.factory()).getONE(); C pc1 = ((RingFactory) pc.factory()).getZERO(); //System.out.println("cc = " + cc + ", e = " + e); //System.out.println("pc = " + pc + " : " + cc.toScriptFactory()); if (cc instanceof AlgebraicNumber && pc instanceof AlgebraicNumber) { throw new UnsupportedOperationException( "case multiple algebraic extensions not implemented"); } else if (cc instanceof Quotient && pc instanceof Quotient) { Quotient ccp = (Quotient) (Object) cc; Quotient pcp = (Quotient) (Object) pc; if (pcp.isConstant()) { //logger.error("finite field not allowed here " + afac.toScript()); throw new ArithmeticException("finite field not allowed here " + afac.toScript()); } //C dc = cc.divide(pc); Quotient dcp = ccp.divide(pcp); if (dcp.isConstant()) { // not possible: dc.isConstant() //System.out.println("dcp = " + dcp + " : " + cc.toScriptFactory()); // + ", dc = " + dc); //if ( dcp.num.isConstant() ) cc1 = cc; pc1 = pc; } GenPolynomial r = new GenPolynomial(ppfac, cc1, f); r = r.subtract(pc1); //System.out.println("r = " + r); gl.add(r); } } } } else { for (Monomial> m : cpp) { ExpVector f = m.e; AlgebraicNumber a = m.c; //System.out.println("m = " + m); GenPolynomial ap = a.val; for (Monomial ma : ap) { ExpVector e = ma.e; C cc = ma.c; C pc = P.val.coefficient(e); GenPolynomial r = new GenPolynomial(ppfac, cc, f); r = r.subtract(pc); //System.out.println("r = " + r); gl.add(r); } } } if (logger.isInfoEnabled()) { logger.info("equations = " + gl); } // solve system of equations and construct result Reduction red = new ReductionSeq(); gl = red.irreducibleSet(gl); GroebnerBaseAbstract bb = new GroebnerBaseSeq(); //GBFactory.getImplementation(); int z = bb.commonZeroTest(gl); if (z < 0) { // no solution return null; } if (logger.isInfoEnabled()) { logger.info("solution = " + gl); } GenPolynomial car = apfac.getZERO(); for (GenPolynomial pl : gl) { if (pl.length() <= 1) { continue; } if (pl.length() > 2) { throw new IllegalArgumentException("dim > 0 not implemented " + pl); } //System.out.println("pl = " + pl); ExpVector e = pl.leadingExpVector(); int[] v = e.dependencyOnVariables(); if (v == null || v.length == 0) { continue; } int vi = v[0]; //System.out.println("vi = " + vi); GenPolynomial ca = apfac.univariate(0, deg - 1 - vi); //System.out.println("ca = " + ca); C tc = pl.trailingBaseCoefficient(); tc = tc.negate(); if (e.maxDeg() == c.longValue()) { // p-th root of tc ... //SortedMap br = aengine.rootCharacteristic(tc); SortedMap br = aengine.squarefreeFactors(tc); //System.out.println("br = " + br); if (br != null && br.size() > 0) { C cc = apfac.coFac.getONE(); for (Map.Entry me : br.entrySet()) { C bc = me.getKey(); long ll = me.getValue(); //br.get(bc); if (ll % c.longValue() == 0L) { long fl = ll / c.longValue(); cc = cc.multiply(Power. positivePower(bc, fl)); } else { // fail ? cc = cc.multiply(bc); } } //System.out.println("cc = " + cc); tc = cc; } } ca = ca.multiply(tc); car = car.sum(ca); } AlgebraicNumber rr = new AlgebraicNumber(afac, car); if (logger.isInfoEnabled()) { logger.info("solution AN = " + rr); //System.out.println("rr = " + rr); } root.put(rr, 1L); return root; } /** * GenPolynomial char-th root main variable. * @param P univariate GenPolynomial with AlgebraicNumber coefficients. * @return char-th_rootOf(P), or null, if P is no char-th root. */ public GenPolynomial> rootCharacteristic(GenPolynomial> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { // go to recursion GenPolynomialRing> cfac = pfac.contract(1); GenPolynomialRing>> rfac = new GenPolynomialRing>>( cfac, 1); GenPolynomial>> Pr = PolyUtil.> recursive( rfac, P); GenPolynomial>> Prc = recursiveUnivariateRootCharacteristic(Pr); if (Prc == null) { return null; } GenPolynomial> D = PolyUtil.> distribute(pfac, Prc); return D; } RingFactory> rf = pfac.coFac; if (rf.characteristic().signum() != 1) { // basePthRoot not possible throw new IllegalArgumentException(P.getClass().getName() + " only for ModInteger polynomials " + rf); } long mp = rf.characteristic().longValue(); GenPolynomial> d = pfac.getZERO().copy(); for (Monomial> m : P) { ExpVector f = m.e; long fl = f.getVal(0); if (fl % mp != 0) { return null; } fl = fl / mp; SortedMap, Long> sm = rootCharacteristic(m.c); if (sm == null) { return null; } if (logger.isInfoEnabled()) { logger.info("sm_alg,root = " + sm); } AlgebraicNumber r = rf.getONE(); for (Map.Entry, Long> me : sm.entrySet()) { AlgebraicNumber rp = me.getKey(); long gl = me.getValue(); //sm.get(rp); if (gl > 1) { rp = Power.> positivePower(rp, gl); } r = r.multiply(rp); } ExpVector e = ExpVector.create(1, 0, fl); d.doPutToMap(e, r); } logger.info("sm_alg,root,d = " + d); return d; } /** * GenPolynomial char-th root univariate polynomial. * @param P GenPolynomial. * @return char-th_rootOf(P). */ @Override public GenPolynomial> baseRootCharacteristic(GenPolynomial> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { // basePthRoot not possible by return type throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); } RingFactory> rf = pfac.coFac; if (rf.characteristic().signum() != 1) { // basePthRoot not possible throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); } long mp = rf.characteristic().longValue(); GenPolynomial> d = pfac.getZERO().copy(); for (Monomial> m : P) { //System.out.println("m = " + m); ExpVector f = m.e; long fl = f.getVal(0); if (fl % mp != 0) { return null; } fl = fl / mp; SortedMap, Long> sm = rootCharacteristic(m.c); if (sm == null) { return null; } if (logger.isInfoEnabled()) { logger.info("sm_alg,base,root = " + sm); } AlgebraicNumber r = rf.getONE(); for (Map.Entry, Long> me : sm.entrySet()) { AlgebraicNumber rp = me.getKey(); //System.out.println("rp = " + rp); long gl = me.getValue(); //sm.get(rp); //System.out.println("gl = " + gl); AlgebraicNumber re = rp; if (gl > 1) { re = Power.> positivePower(rp, gl); } //System.out.println("re = " + re); r = r.multiply(re); } ExpVector e = ExpVector.create(1, 0, fl); d.doPutToMap(e, r); } if (logger.isInfoEnabled()) { logger.info("sm_alg,base,d = " + d); } return d; } /** * GenPolynomial char-th root univariate polynomial with polynomial * coefficients. * @param P recursive univariate GenPolynomial. * @return char-th_rootOf(P), or null if P is no char-th root. */ @Override public GenPolynomial>> recursiveUnivariateRootCharacteristic( GenPolynomial>> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing>> pfac = P.ring; if (pfac.nvar > 1) { // basePthRoot not possible by return type throw new IllegalArgumentException(P.getClass().getName() + " only for univariate recursive polynomials"); } RingFactory>> rf = pfac.coFac; if (rf.characteristic().signum() != 1) { // basePthRoot not possible throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); } long mp = rf.characteristic().longValue(); GenPolynomial>> d = pfac.getZERO().copy(); for (Monomial>> m : P) { ExpVector f = m.e; long fl = f.getVal(0); if (fl % mp != 0) { return null; } fl = fl / mp; GenPolynomial> r = rootCharacteristic(m.c); if (r == null) { return null; } ExpVector e = ExpVector.create(1, 0, fl); d.doPutToMap(e, r); } return d; } } jas-2.5/src/edu/jas/ufd/GreatestCommonDivisorSimple.java0000644000175000017500000002432412003277306023553 0ustar giovannigiovanni/* * $Id: GreatestCommonDivisorSimple.java 4025 2012-07-23 16:41:43Z kredel $ */ package edu.jas.ufd; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; import edu.jas.structure.Power; /** * Greatest common divisor algorithms with monic polynomial remainder sequence. * If C is a field, then the monic PRS (on coefficients) is computed otherwise * no simplifications in the reduction are made. * @author Heinz Kredel */ public class GreatestCommonDivisorSimple> extends GreatestCommonDivisorAbstract { private static final Logger logger = Logger.getLogger(GreatestCommonDivisorSimple.class); private final boolean debug = logger.isDebugEnabled(); /** * Univariate GenPolynomial greatest comon divisor. Uses pseudoRemainder for * remainder. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial baseGcd(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } if (P.ring.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); } boolean field = P.ring.coFac.isField(); long e = P.degree(0); long f = S.degree(0); GenPolynomial q; GenPolynomial r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } C c; if (field) { r = r.monic(); q = q.monic(); c = P.ring.getONECoefficient(); } else { r = r.abs(); q = q.abs(); C a = baseContent(r); C b = baseContent(q); c = gcd(a, b); // indirection r = divide(r, a); // indirection q = divide(q, b); // indirection } if (r.isONE()) { return r.multiply(c); } if (q.isONE()) { return q.multiply(c); } GenPolynomial x; //System.out.println("q = " + q); //System.out.println("r = " + r); while (!r.isZERO()) { x = PolyUtil. baseSparsePseudoRemainder(q, r); q = r; if (field) { r = x.monic(); } else { r = x; } //System.out.println("q = " + q); //System.out.println("r = " + r); } q = basePrimitivePart(q); return (q.multiply(c)).abs(); } /** * Univariate GenPolynomial recursive greatest comon divisor. Uses * pseudoRemainder for remainder. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial> recursiveUnivariateGcd(GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } if (P.ring.nvar > 1) { throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); } boolean field = P.leadingBaseCoefficient().ring.coFac.isField(); long e = P.degree(0); long f = S.degree(0); GenPolynomial> q; GenPolynomial> r; if (f > e) { r = P; q = S; long g = f; f = e; e = g; } else { q = P; r = S; } if (debug) { logger.debug("degrees: e = " + e + ", f = " + f); } if (field) { r = PolyUtil. monic(r); q = PolyUtil. monic(q); } else { r = r.abs(); q = q.abs(); } GenPolynomial a = recursiveContent(r); GenPolynomial b = recursiveContent(q); GenPolynomial c = gcd(a, b); // go to recursion //System.out.println("rgcd c = " + c); r = PolyUtil. recursiveDivide(r, a); q = PolyUtil. recursiveDivide(q, b); if (r.isONE()) { return r.multiply(c); } if (q.isONE()) { return q.multiply(c); } GenPolynomial> x; while (!r.isZERO()) { x = PolyUtil. recursivePseudoRemainder(q, r); q = r; if (field) { r = PolyUtil. monic(x); } else { r = x; } } q = recursivePrimitivePart(q); q = q.abs().multiply(c); return q; } /** * Univariate GenPolynomial resultant. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial baseResultant(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } if (P.ring.nvar > 1 || P.ring.nvar == 0) { throw new IllegalArgumentException("no univariate polynomial"); } long e = P.degree(0); long f = S.degree(0); if (f == 0 && e == 0) { return P.ring.getONE(); } if ( e == 0 ) { return Power.> power(P.ring,P,f); } if ( f == 0 ) { return Power.> power(S.ring,S,e); } GenPolynomial q; GenPolynomial r; int s = 0; // sign is +, 1 for sign is - if (e < f) { r = P; q = S; long t = e; e = f; f = t; if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f) s = 1; } } else { q = P; r = S; } RingFactory cofac = P.ring.coFac; boolean field = cofac.isField(); C c = cofac.getONE(); GenPolynomial x; long g; do { if (field) { x = q.remainder(r); } else { x = PolyUtil.baseSparsePseudoRemainder(q,r); //System.out.println("x_s = " + x + ", lbcf(r) = " + r.leadingBaseCoefficient()); } if ( x.isZERO() ) { return x; } //System.out.println("x = " + x); e = q.degree(0); f = r.degree(0); if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f) s = 1 - s; } g = x.degree(0); C c2 = r.leadingBaseCoefficient(); for (int i = 0; i < (e-g); i++ ) { c = c.multiply(c2); } q = r; r = x; } while (g != 0); C c2 = r.leadingBaseCoefficient(); for (int i = 0; i < f; i++ ) { c = c.multiply(c2); } if ( s == 1 ) { c = c.negate(); } x = P.ring.getONE().multiply(c); return x; } /** * Univariate GenPolynomial recursive resultant. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial> recursiveUnivariateResultant(GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } if (P.ring.nvar > 1 || P.ring.nvar == 0) { throw new IllegalArgumentException("no recursive univariate polynomial"); } long e = P.degree(0); long f = S.degree(0); if ( f == 0 && e == 0 ) { // if coeffs are multivariate (and non constant) // otherwise it would be 1 GenPolynomial t = resultant(P.leadingBaseCoefficient(), S.leadingBaseCoefficient()); return P.ring.getONE().multiply(t); } if ( e == 0 ) { return Power.>> power(P.ring,P,f); } if ( f == 0 ) { return Power.>> power(S.ring,S,e); } GenPolynomial> q; GenPolynomial> r; int s = 0; // sign is +, 1 for sign is - if (f > e) { r = P; q = S; long g = f; f = e; e = g; if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f) s = 1; } } else { q = P; r = S; } GenPolynomial> x; RingFactory> cofac = P.ring.coFac; GenPolynomial c = cofac.getONE(); long g; do { x = PolyUtil.recursiveSparsePseudoRemainder(q,r); //x = PolyUtil.recursiveDensePseudoRemainder(q,r); if ( x.isZERO() ) { return x; } //no: x = recursivePrimitivePart(x); //System.out.println("x = " + x); e = q.degree(0); f = r.degree(0); if ((e % 2 != 0) && (f % 2 != 0)) { // odd(e) && odd(f) s = 1 - s; } g = x.degree(0); GenPolynomial c2 = r.leadingBaseCoefficient(); for (int i = 0; i < (e-g); i++ ) { c = c.multiply(c2); } q = r; r = x; } while (g != 0); GenPolynomial c2 = r.leadingBaseCoefficient(); for (int i = 0; i < f; i++ ) { c = c.multiply(c2); } if ( s == 1 ) { c = c.negate(); } x = P.ring.getONE().multiply(c); return x; } } jas-2.5/src/edu/jas/ufd/GreatestCommonDivisorAbstract.java0000644000175000017500000010556512020212506024062 0ustar giovannigiovanni/* * $Id: GreatestCommonDivisorAbstract.java 4148 2012-08-31 19:49:27Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Greatest common divisor algorithms. * @author Heinz Kredel */ public abstract class GreatestCommonDivisorAbstract> implements GreatestCommonDivisor { private static final Logger logger = Logger.getLogger(GreatestCommonDivisorAbstract.class); private final boolean debug = logger.isDebugEnabled(); /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { return getClass().getName(); } /** * GenPolynomial base coefficient content. * @param P GenPolynomial. * @return cont(P). */ public C baseContent(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P.ring.getZEROCoefficient(); } C d = null; for (C c : P.getMap().values()) { if (d == null) { d = c; } else { d = d.gcd(c); } if (d.isONE()) { return d; } } if (d.signum() < 0) { d = d.negate(); } return d; } /** * GenPolynomial base coefficient primitive part. * @param P GenPolynomial. * @return pp(P). */ public GenPolynomial basePrimitivePart(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P; } C d = baseContent(P); if (d.isONE()) { return P; } GenPolynomial pp = P.divide(d); if (debug) { GenPolynomial p = pp.multiply(d); if (!p.equals(P)) { throw new ArithmeticException("pp(p)*cont(p) != p: "); } } return pp; } /** * Univariate GenPolynomial greatest common divisor. Uses sparse * pseudoRemainder for remainder. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return gcd(P,S). */ public abstract GenPolynomial baseGcd(GenPolynomial P, GenPolynomial S); /** * GenPolynomial recursive content. * @param P recursive GenPolynomial. * @return cont(P). */ public GenPolynomial recursiveContent(GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P.ring.getZEROCoefficient(); } GenPolynomial d = null; for (GenPolynomial c : P.getMap().values()) { if (d == null) { d = c; } else { d = gcd(d, c); // go to recursion } if (d.isONE()) { return d; } } return d.abs(); } /** * GenPolynomial recursive primitive part. * @param P recursive GenPolynomial. * @return pp(P). */ public GenPolynomial> recursivePrimitivePart(GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P; } GenPolynomial d = recursiveContent(P); if (d.isONE()) { return P; } GenPolynomial> pp = PolyUtil. recursiveDivide(P, d); return pp; } /** * GenPolynomial base recursive content. * @param P recursive GenPolynomial. * @return baseCont(P). */ public C baseRecursiveContent(GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { GenPolynomialRing cf = (GenPolynomialRing) P.ring.coFac; return cf.coFac.getZERO(); } C d = null; for (GenPolynomial c : P.getMap().values()) { C cc = baseContent(c); if (d == null) { d = cc; } else { d = gcd(d, cc); } if (d.isONE()) { return d; } } if (d.signum() < 0) { d = d.negate(); } return d; } /** * GenPolynomial base recursive primitive part. * @param P recursive GenPolynomial. * @return basePP(P). */ public GenPolynomial> baseRecursivePrimitivePart(GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P; } C d = baseRecursiveContent(P); if (d.isONE()) { return P; } GenPolynomial> pp = PolyUtil. baseRecursiveDivide(P, d); return pp; } /** * GenPolynomial recursive greatest common divisor. Uses pseudoRemainder for * remainder. * @param P recursive GenPolynomial. * @param S recursive GenPolynomial. * @return gcd(P,S). */ public GenPolynomial> recursiveGcd(GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } if (P.ring.nvar <= 1) { return recursiveUnivariateGcd(P, S); } // distributed polynomials gcd GenPolynomialRing> rfac = P.ring; RingFactory> rrfac = rfac.coFac; GenPolynomialRing cfac = (GenPolynomialRing) rrfac; GenPolynomialRing dfac = cfac.extend(rfac.nvar); GenPolynomial Pd = PolyUtil. distribute(dfac, P); GenPolynomial Sd = PolyUtil. distribute(dfac, S); GenPolynomial Dd = gcd(Pd, Sd); // convert to recursive GenPolynomial> C = PolyUtil. recursive(rfac, Dd); return C; } /** * Univariate GenPolynomial recursive greatest common divisor. Uses * pseudoRemainder for remainder. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return gcd(P,S). */ public abstract GenPolynomial> recursiveUnivariateGcd(GenPolynomial> P, GenPolynomial> S); /** * GenPolynomial content. * @param P GenPolynomial. * @return cont(P). */ public GenPolynomial content(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { // baseContent not possible by return type throw new IllegalArgumentException(this.getClass().getName() + " use baseContent for univariate polynomials"); } GenPolynomialRing cfac = pfac.contract(1); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1); GenPolynomial> Pr = PolyUtil. recursive(rfac, P); GenPolynomial D = recursiveContent(Pr); return D; } /** * GenPolynomial primitive part. * @param P GenPolynomial. * @return pp(P). */ public GenPolynomial primitivePart(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return basePrimitivePart(P); } GenPolynomialRing cfac = pfac.contract(1); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1); GenPolynomial> Pr = PolyUtil. recursive(rfac, P); GenPolynomial> PP = recursivePrimitivePart(Pr); GenPolynomial D = PolyUtil. distribute(pfac, PP); return D; } /** * GenPolynomial division. Indirection to GenPolynomial method. * @param a GenPolynomial. * @param b coefficient. * @return a/b. */ public GenPolynomial divide(GenPolynomial a, C b) { if (b == null || b.isZERO()) { throw new IllegalArgumentException("division by zero"); } if (a == null || a.isZERO()) { return a; } return a.divide(b); } /** * Coefficient greatest common divisor. Indirection to coefficient method. * @param a coefficient. * @param b coefficient. * @return gcd(a,b). */ public C gcd(C a, C b) { if (b == null || b.isZERO()) { return a; } if (a == null || a.isZERO()) { return b; } return a.gcd(b); } /** * GenPolynomial greatest common divisor. * @param P GenPolynomial. * @param S GenPolynomial. * @return gcd(P,S). */ public GenPolynomial gcd(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { GenPolynomial T = baseGcd(P, S); return T; } GenPolynomialRing cfac = pfac.contract(1); GenPolynomialRing> rfac; if (pfac.getVars() != null && pfac.getVars().length > 0) { String[] v = new String[] { pfac.getVars()[pfac.nvar - 1] }; rfac = new GenPolynomialRing>(cfac, 1, v); } else { rfac = new GenPolynomialRing>(cfac, 1); } GenPolynomial> Pr = PolyUtil. recursive(rfac, P); GenPolynomial> Sr = PolyUtil. recursive(rfac, S); GenPolynomial> Dr = recursiveUnivariateGcd(Pr, Sr); GenPolynomial D = PolyUtil. distribute(pfac, Dr); return D; } /** * GenPolynomial least common multiple. * @param P GenPolynomial. * @param S GenPolynomial. * @return lcm(P,S). */ public GenPolynomial lcm(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } GenPolynomial C = gcd(P, S); GenPolynomial A = P.multiply(S); return PolyUtil. basePseudoDivide(A, C); } /** * List of GenPolynomials greatest common divisor. * @param A non empty list of GenPolynomials. * @return gcd(A_i). */ public GenPolynomial gcd(List> A) { if (A == null || A.isEmpty()) { throw new IllegalArgumentException("A may not be empty"); } GenPolynomial g = A.get(0); for (int i = 1; i < A.size(); i++) { GenPolynomial f = A.get(i); g = gcd(g, f); } return g; } /** * Univariate GenPolynomial resultant. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return res(P,S). * @throws UnsupportedOperationException if there is no implementation in * the sub-class. */ @SuppressWarnings("unused") public GenPolynomial baseResultant(GenPolynomial P, GenPolynomial S) { // can not be abstract throw new UnsupportedOperationException("not implmented"); } /** * Univariate GenPolynomial recursive resultant. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return res(P,S). * @throws UnsupportedOperationException if there is no implementation in * the sub-class. */ @SuppressWarnings("unused") public GenPolynomial> recursiveUnivariateResultant(GenPolynomial> P, GenPolynomial> S) { // can not be abstract throw new UnsupportedOperationException("not implmented"); } /** * GenPolynomial recursive resultant. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return res(P,S). * @throws UnsupportedOperationException if there is no implementation in * the sub-class. */ public GenPolynomial> recursiveResultant(GenPolynomial> P, GenPolynomial> S) { if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } GenPolynomialRing> rfac = P.ring; GenPolynomialRing cfac = (GenPolynomialRing) rfac.coFac; GenPolynomialRing dfac = cfac.extend(rfac.getVars()); GenPolynomial Pp = PolyUtil. distribute(dfac, P); GenPolynomial Sp = PolyUtil. distribute(dfac, S); GenPolynomial res = resultant(Pp, Sp); GenPolynomial> Rr = PolyUtil. recursive(rfac, res); return Rr; } /** * GenPolynomial resultant. The input polynomials are considered as * univariate polynomials in the main variable. * @param P GenPolynomial. * @param S GenPolynomial. * @return res(P,S). * @see edu.jas.ufd.GreatestCommonDivisorSubres#recursiveResultant * @throws UnsupportedOperationException if there is no implementation in * the sub-class. */ public GenPolynomial resultant(GenPolynomial P, GenPolynomial S) { if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } // no more hacked: GreatestCommonDivisorSubres ufd_sr = new GreatestCommonDivisorSubres(); GenPolynomialRing pfac = P.ring; if (pfac.nvar <= 1) { return baseResultant(P, S); } GenPolynomialRing cfac = pfac.contract(1); GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1); GenPolynomial> Pr = PolyUtil. recursive(rfac, P); GenPolynomial> Sr = PolyUtil. recursive(rfac, S); GenPolynomial> Dr = recursiveUnivariateResultant(Pr, Sr); GenPolynomial D = PolyUtil. distribute(pfac, Dr); return D; } /** * GenPolynomial co-prime list. * @param A list of GenPolynomials. * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant * a in A there exists b in B with b|a. B does not contain zero or * constant polynomials. */ public List> coPrime(List> A) { if (A == null || A.isEmpty()) { return A; } List> B = new ArrayList>(A.size()); // make a coprime to rest of list GenPolynomial a = A.get(0); //System.out.println("a = " + a); if (!a.isZERO() && !a.isConstant()) { for (int i = 1; i < A.size(); i++) { GenPolynomial b = A.get(i); GenPolynomial g = gcd(a, b).abs(); if (!g.isONE()) { a = PolyUtil. basePseudoDivide(a, g); b = PolyUtil. basePseudoDivide(b, g); GenPolynomial gp = gcd(a, g).abs(); while (!gp.isONE()) { a = PolyUtil. basePseudoDivide(a, gp); g = PolyUtil. basePseudoDivide(g, gp); B.add(g); // gcd(a,g) == 1 g = gp; gp = gcd(a, gp).abs(); } if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) { B.add(g); // gcd(a,g) == 1 } } if (!b.isZERO() && !b.isConstant()) { B.add(b); // gcd(a,b) == 1 } } } else { B.addAll(A.subList(1, A.size())); } // make rest coprime B = coPrime(B); //System.out.println("B = " + B); if (!a.isZERO() && !a.isConstant() /*&& !B.contains(a)*/) { a = a.abs(); B.add(a); } return B; } /** * GenPolynomial co-prime list. * @param A list of GenPolynomials. * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant * a in A there exists b in B with b|a. B does not contain zero or * constant polynomials. */ public List> coPrimeRec(List> A) { if (A == null || A.isEmpty()) { return A; } List> B = new ArrayList>(); // make a co-prime to rest of list for (GenPolynomial a : A) { //System.out.println("a = " + a); B = coPrime(a, B); //System.out.println("B = " + B); } return B; } /** * GenPolynomial co-prime list. * @param a GenPolynomial. * @param P co-prime list of GenPolynomials. * @return B with gcd(b,c) = 1 for all b != c in B and for non-constant a * there exists b in P with b|a. B does not contain zero or constant * polynomials. */ public List> coPrime(GenPolynomial a, List> P) { if (a == null || a.isZERO() || a.isConstant()) { return P; } List> B = new ArrayList>(P.size() + 1); // make a coprime to elements of the list P for (int i = 0; i < P.size(); i++) { GenPolynomial b = P.get(i); GenPolynomial g = gcd(a, b).abs(); if (!g.isONE()) { a = PolyUtil. basePseudoDivide(a, g); b = PolyUtil. basePseudoDivide(b, g); // make g co-prime to new a, g is co-prime to c != b in P, B GenPolynomial gp = gcd(a, g).abs(); while (!gp.isONE()) { a = PolyUtil. basePseudoDivide(a, gp); g = PolyUtil. basePseudoDivide(g, gp); if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) { B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B } g = gp; gp = gcd(a, gp).abs(); } // make new g co-prime to new b gp = gcd(b, g).abs(); while (!gp.isONE()) { b = PolyUtil. basePseudoDivide(b, gp); g = PolyUtil. basePseudoDivide(g, gp); if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) { B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B } g = gp; gp = gcd(b, gp).abs(); } if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) { B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B } } if (!b.isZERO() && !b.isConstant() /*&& !B.contains(b)*/) { B.add(b); // gcd(a,b) == 1 and gcd(b,c) == 1 for c != b in P, B } } if (!a.isZERO() && !a.isConstant() /*&& !B.contains(a)*/) { B.add(a); } return B; } /** * GenPolynomial test for co-prime list. * @param A list of GenPolynomials. * @return true if gcd(b,c) = 1 for all b != c in B, else false. */ public boolean isCoPrime(List> A) { if (A == null || A.isEmpty()) { return true; } if (A.size() == 1) { return true; } for (int i = 0; i < A.size(); i++) { GenPolynomial a = A.get(i); for (int j = i + 1; j < A.size(); j++) { GenPolynomial b = A.get(j); GenPolynomial g = gcd(a, b); if (!g.isONE()) { System.out.println("not co-prime, a: " + a); System.out.println("not co-prime, b: " + b); System.out.println("not co-prime, g: " + g); return false; } } } return true; } /** * GenPolynomial test for co-prime list of given list. * @param A list of GenPolynomials. * @param P list of co-prime GenPolynomials. * @return true if isCoPrime(P) and for all a in A exists p in P with p | a, * else false. */ public boolean isCoPrime(List> P, List> A) { if (!isCoPrime(P)) { return false; } if (A == null || A.isEmpty()) { return true; } for (GenPolynomial q : A) { if (q.isZERO() || q.isConstant()) { continue; } boolean divides = false; for (GenPolynomial p : P) { GenPolynomial a = PolyUtil. baseSparsePseudoRemainder(q, p); if (a.isZERO()) { // p divides q divides = true; break; } } if (!divides) { System.out.println("no divisor for: " + q); return false; } } return true; } /** * Univariate GenPolynomial extended greatest common divisor. Uses sparse * pseudoRemainder for remainder. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return [ gcd(P,S), a, b ] with a*P + b*S = gcd(P,S). */ public GenPolynomial[] baseExtendedGcd(GenPolynomial P, GenPolynomial S) { //return P.egcd(S); GenPolynomial[] hegcd = baseHalfExtendedGcd(P, S); GenPolynomial[] ret = (GenPolynomial[]) new GenPolynomial[3]; ret[0] = hegcd[0]; ret[1] = hegcd[1]; GenPolynomial x = hegcd[0].subtract(hegcd[1].multiply(P)); GenPolynomial[] qr = PolyUtil. basePseudoQuotientRemainder(x, S); // assert qr[1].isZERO() ret[2] = qr[0]; return ret; } /** * Univariate GenPolynomial half extended greatest comon divisor. Uses * sparse pseudoRemainder for remainder. * @param S GenPolynomial. * @return [ gcd(P,S), a ] with a*P + b*S = gcd(P,S). */ public GenPolynomial[] baseHalfExtendedGcd(GenPolynomial P, GenPolynomial S) { //if ( P == null ) { // throw new IllegalArgumentException("null P not allowed"); //} GenPolynomial[] ret = (GenPolynomial[]) new GenPolynomial[2]; ret[0] = null; ret[1] = null; if (S == null || S.isZERO()) { ret[0] = P; ret[1] = P.ring.getONE(); return ret; } if (P == null || P.isZERO()) { ret[0] = S; ret[1] = S.ring.getZERO(); return ret; } if (P.ring.nvar != 1) { throw new IllegalArgumentException(this.getClass().getName() + " not univariate polynomials " + P.ring); } GenPolynomial q = P; GenPolynomial r = S; GenPolynomial c1 = P.ring.getONE().copy(); GenPolynomial d1 = P.ring.getZERO().copy(); while (!r.isZERO()) { GenPolynomial[] qr = PolyUtil. basePseudoQuotientRemainder(q, r); //q.divideAndRemainder(r); q = qr[0]; GenPolynomial x = c1.subtract(q.multiply(d1)); c1 = d1; d1 = x; q = r; r = qr[1]; } // normalize ldcf(q) to 1, i.e. make monic C g = q.leadingBaseCoefficient(); if (g.isUnit()) { C h = g.inverse(); q = q.multiply(h); c1 = c1.multiply(h); } //assert ( ((c1.multiply(P)).remainder(S).equals(q) )); ret[0] = q; ret[1] = c1; return ret; } /** * Univariate GenPolynomial greatest common divisor diophantine version. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @param c univariate GenPolynomial. * @return [ a, b ] with a*P + b*S = c and deg(a) < deg(S). */ public GenPolynomial[] baseGcdDiophant(GenPolynomial P, GenPolynomial S, GenPolynomial c) { GenPolynomial[] egcd = baseExtendedGcd(P, S); GenPolynomial g = egcd[0]; GenPolynomial[] qr = PolyUtil. basePseudoQuotientRemainder(c, g); if (!qr[1].isZERO()) { throw new ArithmeticException("not solvable, r = " + qr[1] + ", c = " + c + ", g = " + g); } GenPolynomial q = qr[0]; GenPolynomial a = egcd[1].multiply(q); GenPolynomial b = egcd[2].multiply(q); if (!a.isZERO() && a.degree(0) >= S.degree(0)) { qr = PolyUtil. basePseudoQuotientRemainder(a, S); a = qr[1]; b = b.sum(P.multiply(qr[0])); } GenPolynomial[] ret = (GenPolynomial[]) new GenPolynomial[2]; ret[0] = a; ret[1] = b; if (debug) { GenPolynomial y = ret[0].multiply(P).sum(ret[1].multiply(S)); if (!y.equals(c)) { System.out.println("P = " + P); System.out.println("S = " + S); System.out.println("c = " + c); System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("y = " + y); throw new ArithmeticException("not diophant, x = " + y.subtract(c)); } } return ret; } /** * Univariate GenPolynomial partial fraction decomposition. * @param A univariate GenPolynomial. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return [ A0, Ap, As ] with A/(P*S) = A0 + Ap/P + As/S with deg(Ap) < * deg(P) and deg(As) < deg(S). */ public GenPolynomial[] basePartialFraction(GenPolynomial A, GenPolynomial P, GenPolynomial S) { GenPolynomial[] ret = (GenPolynomial[]) new GenPolynomial[3]; ret[0] = null; ret[1] = null; ret[2] = null; GenPolynomial ps = P.multiply(S); GenPolynomial[] qr = PolyUtil. basePseudoQuotientRemainder(A, ps); ret[0] = qr[0]; GenPolynomial r = qr[1]; GenPolynomial[] diop = baseGcdDiophant(S, P, r); // switch arguments // GenPolynomial x = diop[0].multiply(S).sum( diop[1].multiply(P) ); // if ( !x.equals(r) ) { // System.out.println("r = " + r); // System.out.println("x = " + x); // throw new RuntimeException("not partial fraction, x = " + x); // } ret[1] = diop[0]; ret[2] = diop[1]; if (ret[1].degree(0) >= P.degree(0)) { qr = PolyUtil. basePseudoQuotientRemainder(ret[1], P); ret[0] = ret[0].sum(qr[0]); ret[1] = qr[1]; } if (ret[2].degree(0) >= S.degree(0)) { qr = PolyUtil. basePseudoQuotientRemainder(ret[2], S); ret[0] = ret[0].sum(qr[0]); ret[2] = qr[1]; } return ret; } /** * Univariate GenPolynomial partial fraction decomposition. * @param A univariate GenPolynomial. * @param P univariate GenPolynomial. * @param e exponent for P. * @return [ F0, F1, ..., Fe ] with A/(P^e) = sum( Fi / P^i ) with deg(Fi) < * deg(P). */ public List> basePartialFraction(GenPolynomial A, GenPolynomial P, int e) { if (A == null || P == null || e == 0) { throw new IllegalArgumentException("null A, P or e = 0 not allowed"); } List> pf = new ArrayList>(e); if (A.isZERO()) { for (int i = 0; i < e; i++) { pf.add(A); } return pf; } if (e == 1) { GenPolynomial[] qr = PolyUtil. basePseudoQuotientRemainder(A, P); pf.add(qr[0]); pf.add(qr[1]); return pf; } GenPolynomial a = A; for (int j = e; j > 0; j--) { GenPolynomial[] qr = PolyUtil. basePseudoQuotientRemainder(a, P); a = qr[0]; pf.add(0, qr[1]); } pf.add(0, a); return pf; } /** * Univariate GenPolynomial partial fraction decomposition. * @param A univariate GenPolynomial. * @param D list of co-prime univariate GenPolynomials. * @return [ A0, A1,..., An ] with A/prod(D) = A0 + sum( Ai/Di ) with * deg(Ai) < deg(Di). */ public List> basePartialFraction(GenPolynomial A, List> D) { if (D == null || A == null) { throw new IllegalArgumentException("null A or D not allowed"); } List> pf = new ArrayList>(D.size() + 1); if (A.isZERO() || D.size() == 0) { pf.add(A); for (int i = 0; i < D.size(); i++) { pf.add(A); } return pf; } List> Dp = new ArrayList>(D.size() - 1); GenPolynomial P = A.ring.getONE(); GenPolynomial d1 = null; for (GenPolynomial d : D) { if (d1 == null) { d1 = d; } else { P = P.multiply(d); Dp.add(d); } } GenPolynomial[] qr = PolyUtil. basePseudoQuotientRemainder(A, P.multiply(d1)); GenPolynomial A0 = qr[0]; GenPolynomial r = qr[1]; if (D.size() == 1) { pf.add(A0); pf.add(r); return pf; } GenPolynomial[] diop = baseGcdDiophant(P, d1, r); // switch arguments GenPolynomial A1 = diop[0]; GenPolynomial S = diop[1]; List> Fr = basePartialFraction(S, Dp); A0 = A0.sum(Fr.remove(0)); pf.add(A0); pf.add(A1); pf.addAll(Fr); return pf; } /** * Test for Univariate GenPolynomial partial fraction decomposition. * @param A univariate GenPolynomial. * @param D list of (co-prime) univariate GenPolynomials. * @param F list of univariate GenPolynomials from a partial fraction * computation. * @return true if A/prod(D) = F0 + sum( Fi/Di ) with deg(Fi) < deg(Di), Fi * in F, else false. */ public boolean isBasePartialFraction(GenPolynomial A, List> D, List> F) { if (D == null || A == null || F == null) { throw new IllegalArgumentException("null A, F or D not allowed"); } if (D.size() != F.size() - 1) { return false; } // A0*prod(D) + sum( Ai * Dip ), Dip = prod(D,j!=i) GenPolynomial P = A.ring.getONE(); for (GenPolynomial d : D) { P = P.multiply(d); } List> Fp = new ArrayList>(F); GenPolynomial A0 = Fp.remove(0).multiply(P); //System.out.println("A0 = " + A0); int j = 0; for (GenPolynomial Fi : Fp) { P = A.ring.getONE(); int i = 0; for (GenPolynomial d : D) { if (i != j) { P = P.multiply(d); } i++; } //System.out.println("Fi = " + Fi); //System.out.println("P = " + P); A0 = A0.sum(Fi.multiply(P)); //System.out.println("A0 = " + A0); j++; } boolean t = A.equals(A0); if (!t) { System.out.println("not isPartFrac = " + A0); } return t; } /** * Test for Univariate GenPolynomial partial fraction decomposition. * @param A univariate GenPolynomial. * @param P univariate GenPolynomial. * @param e exponent for P. * @param F list of univariate GenPolynomials from a partial fraction * computation. * @return true if A/(P^e) = F0 + sum( Fi / P^i ) with deg(Fi) < deg(P), Fi * in F, else false. */ public boolean isBasePartialFraction(GenPolynomial A, GenPolynomial P, int e, List> F) { if (A == null || P == null || F == null || e == 0) { throw new IllegalArgumentException("null A, P, F or e = 0 not allowed"); } GenPolynomial A0 = basePartialFractionValue(P, e, F); // A.ring.getZERO(); // for ( GenPolynomial Fi : F ) { // A0 = A0.multiply(P); // A0 = A0.sum(Fi); // //System.out.println("A0 = " + A0); // } boolean t = A.equals(A0); if (!t) { System.out.println("not isPartFrac = " + A0); } return t; } /** * Test for Univariate GenPolynomial partial fraction decomposition. * @param P univariate GenPolynomial. * @param e exponent for P. * @param F list of univariate GenPolynomials from a partial fraction * computation. * @return (F0 + sum( Fi / P^i )) * P^e. */ public GenPolynomial basePartialFractionValue(GenPolynomial P, int e, List> F) { if (P == null || F == null || e == 0) { throw new IllegalArgumentException("null P, F or e = 0 not allowed"); } GenPolynomial A0 = P.ring.getZERO(); for (GenPolynomial Fi : F) { A0 = A0.multiply(P); A0 = A0.sum(Fi); //System.out.println("A0 = " + A0); } return A0; } } jas-2.5/src/edu/jas/ufd/FactorComplex.java0000644000175000017500000001073111713546722020665 0ustar giovannigiovanni/* * $Id: FactorComplex.java 3883 2012-02-05 18:43:31Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import edu.jas.poly.AlgebraicNumber; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.Complex; import edu.jas.poly.ComplexRing; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.TermOrder; import edu.jas.poly.PolyUtil; import edu.jas.structure.GcdRingElem; import edu.jas.structure.RingFactory; /** * Complex coefficients factorization algorithms. This class implements * factorization methods for polynomials over Complex numbers via the algebraic * number C(i) over rational numbers or over (prime) modular integers. Note: * Decomposition to linear factors is only via absolute factorization since * Complex are not the analytic complex numbers. * @author Heinz Kredel * @param coefficient type */ public class FactorComplex> extends FactorAbsolute> { private static final Logger logger = Logger.getLogger(FactorComplex.class); private final boolean debug = logger.isDebugEnabled(); /** * Factorization engine for algebraic coefficients. */ public final FactorAbstract> factorAlgeb; /** * Complex algebraic factory. */ public final AlgebraicNumberRing afac; /** * No argument constructor. Note: can't use this constructor. */ protected FactorComplex() { throw new IllegalArgumentException("don't use this constructor"); } /** * Constructor. * @param fac complex number factory. */ public FactorComplex(RingFactory> fac) { // why is this constructor required? this((ComplexRing) fac); } /** * Constructor. * @param fac complex number factory. */ public FactorComplex(ComplexRing fac) { super(fac); this.afac = fac.algebraicRing(); this.factorAlgeb = FactorFactory. getImplementation(afac); } /** * Constructor. * @param fac complex number factory. * @param factorAlgeb factorization engine for polynomials over algebraic coefficients. */ public FactorComplex(ComplexRing fac, FactorAbstract> factorAlgeb) { super(fac); this.afac = fac.algebraicRing(); this.factorAlgeb = factorAlgeb; } /** * GenPolynomial base factorization of a squarefree polynomial. * @param P squarefree GenPolynomial<AlgebraicNumber<C>>. * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i. */ @Override public List>> baseFactorsSquarefree(GenPolynomial> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } List>> factors = new ArrayList>>(); if (P.isZERO()) { return factors; } if (P.isONE()) { factors.add(P); return factors; } GenPolynomialRing> pfac = P.ring; // CC[x] if (pfac.nvar > 1) { throw new IllegalArgumentException("only for univariate polynomials"); } ComplexRing cfac = (ComplexRing) pfac.coFac; if (!afac.ring.coFac.equals(cfac.ring)) { throw new IllegalArgumentException("coefficient rings do not match"); } Complex ldcf = P.leadingBaseCoefficient(); if (!ldcf.isONE()) { P = P.monic(); factors.add(pfac.getONE().multiply(ldcf)); } //System.out.println("\nP = " + P); GenPolynomialRing> pafac = new GenPolynomialRing>(afac, pfac); GenPolynomial> A = PolyUtil. algebraicFromComplex(pafac, P); //System.out.println("A = " + A); List>> afactors = factorAlgeb.baseFactorsSquarefree(A); if (debug) { // System.out.println("complex afactors = " + afactors); logger.info("complex afactors = " + afactors); } for (GenPolynomial> pa : afactors) { GenPolynomial> pc = PolyUtil. complexFromAlgebraic(pfac, pa); factors.add(pc); } //System.out.println("cfactors = " + factors); return factors; } } jas-2.5/src/edu/jas/ufd/FactorsList.java0000644000175000017500000000756411227701102020347 0ustar giovannigiovanni/* * $Id: FactorsList.java 2754 2009-07-16 19:40:51Z kredel $ */ package edu.jas.ufd; import java.io.Serializable; import java.util.List; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Container for the factors of a squarefree factorization. * @author Heinz Kredel * @param coefficient type */ public class FactorsList> implements Serializable { /** * Original polynomial to be factored with coefficients from C. */ public final GenPolynomial poly; /** * List of factors with coefficients from C. */ public final List> factors; /** * List of factors with coefficients from AlgebraicNumberRings. */ public final List> afactors; /** * Constructor. * @param p given GenPolynomial over C. * @param list irreducible factors of p with coefficients from C. */ public FactorsList(GenPolynomial p, List> list) { this(p, list, null); } /** * Constructor. * @param p given GenPolynomial over C. * @param list irreducible factors of p with coefficients from C. * @param alist irreducible factors of p with coefficients from an algebraic * number field. */ public FactorsList(GenPolynomial p, List> list, List> alist) { poly = p; factors = list; afactors = alist; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); //sb.append(poly.toString()); //sb.append(" =\n"); boolean first = true; for (GenPolynomial p : factors) { if (first) { first = false; } else { sb.append(",\n "); } sb.append(p.toString()); } if (afactors == null) { return sb.toString(); } for (Factors f : afactors) { if (first) { first = false; } else { sb.append(",\n "); } sb.append(f.toString()); } return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this container. * @see edu.jas.structure.ElemFactory#toScript() */ public String toScript() { // Python case StringBuffer sb = new StringBuffer(); sb.append(poly.toScript()); sb.append(" =\n"); boolean first = true; for (GenPolynomial p : factors) { if (first) { first = false; } else { sb.append("\n * "); } sb.append(p.toScript()); } if (afactors == null) { return sb.toString(); } for (Factors f : afactors) { if (first) { first = false; } else { sb.append("\n * "); } sb.append(f.toScript()); } return sb.toString(); } /** * Find largest extension field. * @return largest extension field or null if no extension field */ public AlgebraicNumberRing findExtensionField() { if (afactors == null) { return null; } AlgebraicNumberRing ar = null; int depth = 0; for (Factors f : afactors) { AlgebraicNumberRing aring = f.findExtensionField(); if (aring == null) { continue; } int d = aring.depth(); if (d > depth) { depth = d; ar = aring; } } return ar; } } jas-2.5/src/edu/jas/ufd/HenselApprox.java0000644000175000017500000000677611460603360020534 0ustar giovannigiovanni/* * $Id: HenselApprox.java 3355 2010-10-23 16:01:52Z kredel $ */ package edu.jas.ufd; import java.io.Serializable; import edu.jas.arith.BigInteger; import edu.jas.arith.Modular; import edu.jas.arith.ModularRingFactory; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Container for the approximation result from a Hensel algorithm. * @author Heinz Kredel * @param coefficient type */ public class HenselApprox & Modular> implements Serializable { /** * Approximated polynomial with integer coefficients. */ public final GenPolynomial A; /** * Approximated polynomial with integer coefficients. */ public final GenPolynomial B; /** * Modular approximated polynomial with modular coefficients. */ public final GenPolynomial Am; /** * Modular approximated polynomial with modular coefficients. */ public final GenPolynomial Bm; /** * Constructor. * @param A approximated polynomial. * @param B approximated polynomial. * @param Am approximated modular polynomial. * @param Bm approximated modular polynomial. */ public HenselApprox(GenPolynomial A, GenPolynomial B, GenPolynomial Am, GenPolynomial Bm) { this.A = A; this.B = B; this.Am = Am; this.Bm = Bm; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append(A.toString()); sb.append(","); sb.append(B.toString()); sb.append(","); sb.append(Am.toString()); sb.append(","); sb.append(Bm.toString()); return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this container. * @see edu.jas.structure.ElemFactory#toScript() */ public String toScript() { // Python case StringBuffer sb = new StringBuffer(); sb.append(A.toScript()); sb.append(","); sb.append(B.toScript()); sb.append(","); sb.append(Am.toScript()); sb.append(","); sb.append(Bm.toScript()); return sb.toString(); } /** * Hash code for this Factors. * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = A.hashCode(); h = 37 * h + B.hashCode(); h = 37 * h + Am.hashCode(); h = 37 * h + Bm.hashCode(); return h; } /** * Comparison with any other object. * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object B) { if (!(B instanceof HenselApprox)) { return false; } HenselApprox a = null; try { a = (HenselApprox) B; } catch (ClassCastException ignored) { } if (a == null) { return false; } return A.equals(a.A) && B.equals(a.B) && Am.equals(a.Am) && Bm.equals(a.Bm); } /** * Get modul of modular polynomial. * @return coefficient modul of polynomial mpol. */ public BigInteger approximationSize() { ModularRingFactory fac = (ModularRingFactory) Am.ring.coFac; return fac.getIntegerModul(); } } jas-2.5/src/edu/jas/ufd/SquarefreeFiniteFieldCharP.java0000644000175000017500000002302012014234362023222 0ustar giovannigiovanni/* * $Id: SquarefreeFiniteFieldCharP.java 4125 2012-08-19 19:05:22Z kredel $ */ package edu.jas.ufd; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.log4j.Logger; import edu.jas.arith.BigInteger; import edu.jas.poly.ExpVector; import edu.jas.poly.GenPolynomial; import edu.jas.poly.GenPolynomialRing; import edu.jas.poly.Monomial; import edu.jas.structure.GcdRingElem; import edu.jas.structure.Power; import edu.jas.structure.RingFactory; /** * Squarefree decomposition for finite coefficient fields of characteristic p. * @author Heinz Kredel */ public class SquarefreeFiniteFieldCharP> extends SquarefreeFieldCharP { private static final Logger logger = Logger.getLogger(SquarefreeFiniteFieldCharP.class); //private final boolean debug = logger.isDebugEnabled(); /** * Constructor. */ public SquarefreeFiniteFieldCharP(RingFactory fac) { super(fac); // isFinite() predicate now present if (!fac.isFinite()) { throw new IllegalArgumentException("fac must be finite"); } } /* --------- char-th roots --------------------- */ /** * Characteristics root of a coefficient. Note: not needed at the * moment. * @param p coefficient. * @return [p -> k] if exists k with e=k*charactristic(c) and c = p**e, * else null. */ public SortedMap rootCharacteristic(C p) { if (p == null) { throw new IllegalArgumentException(this.getClass().getName() + " p == null"); } // already checked in constructor: //java.math.BigInteger c = p.factory().characteristic(); //if ( c.signum() == 0 ) { // return null; //} SortedMap root = new TreeMap(); if (p.isZERO()) { return root; } // true for finite fields: root.put(p, 1L); return root; } /** * Characteristics root of a coefficient. * @param c coefficient. * @return r with r**p == c, if such an r exists, else null. */ public C coeffRootCharacteristic(C c) { if (c == null || c.isZERO()) { return c; } C r = c; if (aCoFac == null && qCoFac == null) { // case ModInteger: c**p == c return r; } if (aCoFac != null) { // case AlgebraicNumber: r = c**(p**(d-1)), r**p == c long d = aCoFac.totalExtensionDegree(); //System.out.println("d = " + d); if (d <= 1) { return r; } BigInteger p = new BigInteger(aCoFac.characteristic()); BigInteger q = Power. positivePower(p, d - 1); //System.out.println("p**(d-1) = " + q); r = Power. positivePower(r, q.getVal()); //System.out.println("r**q = " + r); return r; } if (qCoFac != null) { throw new UnsupportedOperationException("case QuotientRing not yet implemented"); } return r; } /** * Characteristics root of a polynomial. Note: call only in * recursion. * @param P polynomial. * @return [p -> k] if exists k with e=k*charactristic(P) and P = p**e, * else null. */ public SortedMap, Long> rootCharacteristic(GenPolynomial P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P == null"); } java.math.BigInteger c = P.ring.characteristic(); if (c.signum() == 0) { return null; } SortedMap, Long> root = new TreeMap, Long>(); if (P.isZERO()) { return root; } if (P.isONE()) { root.put(P, 1L); return root; } SortedMap, Long> sf = squarefreeFactors(P); if (logger.isInfoEnabled()) { logger.info("sf = " + sf); } // better: test if sf.size() == 1 // not ok Long k = null; for (Map.Entry, Long> me : sf.entrySet()) { GenPolynomial p = me.getKey(); if (p.isConstant()) { //System.out.println("p,const = " + p); continue; } Long e = me.getValue(); //sf.get(p); java.math.BigInteger E = new java.math.BigInteger(e.toString()); java.math.BigInteger r = E.remainder(c); if (!r.equals(java.math.BigInteger.ZERO)) { //System.out.println("r = " + r); return null; } if (k == null) { k = e; } else if (k.compareTo(e) >= 0) { k = e; } } // now c divides all exponents Long cl = c.longValue(); GenPolynomial rp = P.ring.getONE(); for (Map.Entry, Long> me : sf.entrySet()) { GenPolynomial q = me.getKey(); Long e = me.getValue(); // sf.get(q); if (q.isConstant()) { // ensure p-th root C qc = q.leadingBaseCoefficient(); //System.out.println("qc,const = " + qc + ", e = " + e); if (e > 1L) { qc = Power. positivePower(qc, e); //e = 1L; } C qr = coeffRootCharacteristic(qc); //System.out.println("qr,const = " + qr); q = P.ring.getONE().multiply(qr); root.put(q, 1L); continue; } if (e > k) { long ep = e / cl; q = Power.> positivePower(q, ep); } rp = rp.multiply(q); } if (k != null) { k = k / cl; root.put(rp, k); } //System.out.println("sf,root = " + root); return root; } /** * GenPolynomial char-th root univariate polynomial. Base coefficient type * must be finite field, that is ModInteger or * AlgebraicNumber<ModInteger> etc. * @param P GenPolynomial. * @return char-th_rootOf(P), or null if no char-th root. */ @Override public GenPolynomial baseRootCharacteristic(GenPolynomial P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing pfac = P.ring; if (pfac.nvar > 1) { // basePthRoot not possible by return type throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); } RingFactory rf = pfac.coFac; if (rf.characteristic().signum() != 1) { // basePthRoot not possible throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); } long mp = rf.characteristic().longValue(); GenPolynomial d = pfac.getZERO().copy(); for (Monomial m : P) { ExpVector f = m.e; long fl = f.getVal(0); if (fl % mp != 0) { return null; } fl = fl / mp; ExpVector e = ExpVector.create(1, 0, fl); // for m.c exists a char-th root, since finite field C r = coeffRootCharacteristic(m.c); d.doPutToMap(e, r); } return d; } /** * GenPolynomial char-th root univariate polynomial with polynomial * coefficients. * @param P recursive univariate GenPolynomial. * @return char-th_rootOf(P), or null if P is no char-th root. */ @Override public GenPolynomial> recursiveUnivariateRootCharacteristic( GenPolynomial> P) { if (P == null || P.isZERO()) { return P; } GenPolynomialRing> pfac = P.ring; if (pfac.nvar > 1) { // basePthRoot not possible by return type throw new IllegalArgumentException(P.getClass().getName() + " only for univariate polynomials"); } RingFactory> rf = pfac.coFac; if (rf.characteristic().signum() != 1) { // basePthRoot not possible throw new IllegalArgumentException(P.getClass().getName() + " only for char p > 0 " + rf); } long mp = rf.characteristic().longValue(); GenPolynomial> d = pfac.getZERO().copy(); for (Monomial> m : P) { ExpVector f = m.e; long fl = f.getVal(0); if (fl % mp != 0) { return null; } fl = fl / mp; SortedMap, Long> sm = rootCharacteristic(m.c); if (sm == null) { return null; } if (logger.isInfoEnabled()) { logger.info("sm,rec = " + sm); } GenPolynomial r = rf.getONE(); for (Map.Entry, Long> me : sm.entrySet()) { GenPolynomial rp = me.getKey(); long gl = me.getValue(); //sm.get(rp); if (gl > 1) { rp = Power.> positivePower(rp, gl); } r = r.multiply(rp); } ExpVector e = ExpVector.create(1, 0, fl); //System.out.println("put-root r = " + r + ", e = " + e); d.doPutToMap(e, r); } return d; } } jas-2.5/src/edu/jas/ufd/FactorsMap.java0000644000175000017500000001152612000362542020143 0ustar giovannigiovanni/* * $Id: FactorsMap.java 3992 2012-07-14 21:32:18Z kredel $ */ package edu.jas.ufd; import java.io.Serializable; import java.util.SortedMap; import edu.jas.poly.AlgebraicNumberRing; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Container for the factors of a eventually non-squarefree factorization. * @author Heinz Kredel * @param coefficient type */ public class FactorsMap> implements Serializable { /** * Original polynomial to be factored with coefficients from C. */ public final GenPolynomial poly; /** * List of factors with coefficients from C. */ public final SortedMap, Long> factors; /** * List of factors with coefficients from AlgebraicNumberRings. */ public final SortedMap, Long> afactors; /** * Constructor. * @param p given GenPolynomial over C. * @param map irreducible factors of p with coefficients from C. */ public FactorsMap(GenPolynomial p, SortedMap, Long> map) { this(p, map, null); } /** * Constructor. * @param p given GenPolynomial over C. * @param map irreducible factors of p with coefficients from C. * @param amap irreducible factors of p with coefficients from an algebraic * number field. */ public FactorsMap(GenPolynomial p, SortedMap, Long> map, SortedMap, Long> amap) { poly = p; factors = map; afactors = amap; } /** * Get the String representation. * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append(poly.toString()); sb.append(" =\n"); boolean first = true; for (GenPolynomial p : factors.keySet()) { if (first) { first = false; } else { sb.append(",\n "); } sb.append(p.toString()); long e = factors.get(p); if (e > 1) { sb.append("**" + e); } } if (afactors == null) { return sb.toString(); } for (Factors f : afactors.keySet()) { if (first) { first = false; } else { sb.append(",\n "); } sb.append(f.toString()); Long e = afactors.get(f); if ( e == null ) { continue; } if (e > 1) { sb.append("**" + e); } } return sb.toString(); } /** * Get a scripting compatible string representation. * @return script compatible representation for this container. * @see edu.jas.structure.ElemFactory#toScript() */ public String toScript() { // Python case StringBuffer sb = new StringBuffer(); //sb.append(poly.toScript()); //sb.append(" =\n"); boolean first = true; for (GenPolynomial p : factors.keySet()) { if (first) { first = false; } else { sb.append("\n * "); } sb.append(p.toScript()); long e = factors.get(p); if (e > 1) { sb.append("**" + e); } } if (afactors == null) { return sb.toString(); } for (Factors f : afactors.keySet()) { if (first) { first = false; } else { sb.append("\n * "); } Long e = afactors.get(f); if ( e == null ) { // should not happen System.out.println("f = " + f); System.out.println("afactors = " + afactors); throw new RuntimeException("this should not happen"); } if (e == 1) { sb.append(f.toScript()); } else { sb.append("(\n"); sb.append(f.toScript()); sb.append("\n)**" + e); } } return sb.toString(); } /** * Find largest extension field. * @return largest extension field or null if no extension field */ public AlgebraicNumberRing findExtensionField() { if (afactors == null) { return null; } AlgebraicNumberRing ar = null; int depth = 0; for (Factors f : afactors.keySet()) { AlgebraicNumberRing aring = f.findExtensionField(); if (aring == null) { continue; } int d = aring.depth(); if (d > depth) { depth = d; ar = aring; } } return ar; } } jas-2.5/src/edu/jas/ufd/GCDProxy.java0000644000175000017500000005140012004021526017534 0ustar giovannigiovanni/* * $Id: GCDProxy.java 4045 2012-07-25 16:48:23Z kredel $ */ package edu.jas.ufd; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import org.apache.log4j.Logger; import edu.jas.kern.ComputerThreads; import edu.jas.kern.PreemptingException; import edu.jas.poly.GenPolynomial; import edu.jas.structure.GcdRingElem; /** * Greatest common divisor parallel proxy. * Executes methods from two implementations in parallel and * returns the result from the fastest run. * @author Heinz Kredel */ public class GCDProxy> extends GreatestCommonDivisorAbstract { // implements GreatestCommonDivisor { private static final Logger logger = Logger.getLogger(GCDProxy.class); private final boolean debug = logger.isDebugEnabled(); //logger.isInfoEnabled(); /** * GCD and resultant engines. */ public final GreatestCommonDivisorAbstract e1; public final GreatestCommonDivisorAbstract e2; /** * Thread pool. */ protected transient ExecutorService pool; /** * Proxy constructor. */ public GCDProxy(GreatestCommonDivisorAbstract e1, GreatestCommonDivisorAbstract e2) { this.e1 = e1; this.e2 = e2; pool = ComputerThreads.getPool(); //System.out.println("pool 2 = "+pool); } /** * Get the String representation with gcd engines. * @see java.lang.Object#toString() */ @Override public String toString() { return "GCDProxy[ " + e1.getClass().getName() + ", " + e2.getClass().getName() + " ]"; } /** * Univariate GenPolynomial greatest common divisor. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial baseGcd(final GenPolynomial P, final GenPolynomial S) { if ( debug ) { if ( ComputerThreads.NO_THREADS ) { throw new RuntimeException("this should not happen"); } } if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } // parallel case GenPolynomial g = null; //Callable> c0; //Callable> c1; List>> cs = new ArrayList>>(2); cs.add(new Callable>() { public GenPolynomial call() { try { //System.out.println("starting e1 " + e1.getClass().getName()); GenPolynomial g = e1.baseGcd(P, S); if (debug) { logger.info("GCDProxy done e1 " + e1.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e1 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e1 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e1 " + e); //return P.ring.getONE(); } } }); cs.add(new Callable>() { public GenPolynomial call() { try { //System.out.println("starting e2 " + e2.getClass().getName()); GenPolynomial g = e2.baseGcd(P, S); if (debug) { logger.info("GCDProxy done e2 " + e2.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e2 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e2 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e2 " + e); //return P.ring.getONE(); } } }); try { g = pool.invokeAny(cs); } catch (InterruptedException ignored) { logger.info("InterruptedException " + ignored); Thread.currentThread().interrupt(); } catch (ExecutionException e) { logger.info("ExecutionException " + e); Thread.currentThread().interrupt(); } return g; } /** * Univariate GenPolynomial recursive greatest common divisor. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial> recursiveUnivariateGcd(final GenPolynomial> P, final GenPolynomial> S) { if ( debug ) { if ( ComputerThreads.NO_THREADS ) { throw new RuntimeException("this should not happen"); } } if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } // parallel case GenPolynomial> g = null; //Callable>> c0; //Callable>> c1; List>>> cs = new ArrayList>>>( 2); cs.add(new Callable>>() { public GenPolynomial> call() { try { GenPolynomial> g = e1.recursiveUnivariateGcd(P, S); if (debug) { logger.info("GCDProxy done e1 " + e1.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e1 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e1 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e1 " + e); //return P.ring.getONE(); } } }); cs.add(new Callable>>() { public GenPolynomial> call() { try { GenPolynomial> g = e2.recursiveUnivariateGcd(P, S); if (debug) { logger.info("GCDProxy done e2 " + e2.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e2 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e2 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e2 " + e); //return P.ring.getONE(); } } }); try { g = pool.invokeAny(cs); } catch (InterruptedException ignored) { logger.info("InterruptedException " + ignored); Thread.currentThread().interrupt(); } catch (ExecutionException e) { logger.info("ExecutionException " + e); Thread.currentThread().interrupt(); } return g; } /** * GenPolynomial greatest common divisor. * @param P GenPolynomial. * @param S GenPolynomial. * @return gcd(P,S). */ @Override public GenPolynomial gcd(final GenPolynomial P, final GenPolynomial S) { if ( debug ) { if ( ComputerThreads.NO_THREADS ) { throw new RuntimeException("this should not happen"); } } if (S == null || S.isZERO()) { return P; } if (P == null || P.isZERO()) { return S; } // parallel case GenPolynomial g = null; //Callable> c0; //Callable> c1; List>> cs = new ArrayList>>(2); cs.add(new Callable>() { public GenPolynomial call() { try { //System.out.println("starting e1 " + e1.getClass().getName()); GenPolynomial g = e1.gcd(P, S); if (debug) { logger.info("GCDProxy done e1 " + e1.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e1 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e1 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e1 " + e); //return P.ring.getONE(); } } }); cs.add(new Callable>() { public GenPolynomial call() { try { //System.out.println("starting e2 " + e2.getClass().getName()); GenPolynomial g = e2.gcd(P, S); if (debug) { logger.info("GCDProxy done e2 " + e2.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e2 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e2 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e2 " + e); //return P.ring.getONE(); } } }); try { g = pool.invokeAny(cs); } catch (InterruptedException ignored) { logger.info("InterruptedException " + ignored); Thread.currentThread().interrupt(); } catch (ExecutionException e) { logger.info("ExecutionException " + e); Thread.currentThread().interrupt(); } return g; } /** * Univariate GenPolynomial resultant. * @param P univariate GenPolynomial. * @param S univariate GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial baseResultant(final GenPolynomial P, final GenPolynomial S) { if ( debug ) { if ( ComputerThreads.NO_THREADS ) { throw new RuntimeException("this should not happen"); } } if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } // parallel case GenPolynomial g = null; //Callable> c0; //Callable> c1; List>> cs = new ArrayList>>(2); cs.add(new Callable>() { public GenPolynomial call() { try { //System.out.println("starting e1 " + e1.getClass().getName()); GenPolynomial g = e1.baseResultant(P, S); if (debug) { logger.info("GCDProxy done e1 " + e1.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e1 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e1 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e1 " + e); //return P.ring.getONE(); } } }); cs.add(new Callable>() { public GenPolynomial call() { try { //System.out.println("starting e2 " + e2.getClass().getName()); GenPolynomial g = e2.baseResultant(P, S); if (debug) { logger.info("GCDProxy done e2 " + e2.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e2 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e2 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e2 " + e); //return P.ring.getONE(); } } }); try { g = pool.invokeAny(cs); } catch (InterruptedException ignored) { logger.info("InterruptedException " + ignored); Thread.currentThread().interrupt(); } catch (ExecutionException e) { logger.info("ExecutionException " + e); Thread.currentThread().interrupt(); } return g; } /** * Univariate GenPolynomial resultant. * @param P univariate recursive GenPolynomial. * @param S univariate recursive GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial> recursiveUnivariateResultant(final GenPolynomial> P, final GenPolynomial> S) { if ( debug ) { if ( ComputerThreads.NO_THREADS ) { throw new RuntimeException("this should not happen"); } } if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } // parallel case GenPolynomial> g = null; //Callable>> c0; //Callable>> c1; List>>> cs = new ArrayList>>>( 2); cs.add(new Callable>>() { public GenPolynomial> call() { try { GenPolynomial> g = e1.recursiveUnivariateResultant(P, S); if (debug) { logger.info("GCDProxy done e1 " + e1.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e1 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e1 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e1 " + e); //return P.ring.getONE(); } } }); cs.add(new Callable>>() { public GenPolynomial> call() { try { GenPolynomial> g = e2.recursiveUnivariateResultant(P, S); if (debug) { logger.info("GCDProxy done e2 " + e2.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e2 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e2 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e2 " + e); //return P.ring.getONE(); } } }); try { g = pool.invokeAny(cs); } catch (InterruptedException ignored) { logger.info("InterruptedException " + ignored); Thread.currentThread().interrupt(); } catch (ExecutionException e) { logger.info("ExecutionException " + e); Thread.currentThread().interrupt(); } return g; } /** * GenPolynomial resultant. Main entry driver method. * @param P GenPolynomial. * @param S GenPolynomial. * @return res(P,S). */ @Override public GenPolynomial resultant(final GenPolynomial P, final GenPolynomial S) { if ( debug ) { if ( ComputerThreads.NO_THREADS ) { throw new RuntimeException("this should not happen"); } } if (S == null || S.isZERO()) { return S; } if (P == null || P.isZERO()) { return P; } // parallel case GenPolynomial g = null; //Callable> c0; //Callable> c1; List>> cs = new ArrayList>>(2); cs.add(new Callable>() { public GenPolynomial call() { try { //System.out.println("starting e1 " + e1.getClass().getName()); GenPolynomial g = e1.resultant(P, S); if (debug) { logger.info("GCDProxy done e1 " + e1.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e1 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e1 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e1 " + e); //return P.ring.getONE(); } } }); cs.add(new Callable>() { public GenPolynomial call() { try { //System.out.println("starting e2 " + e2.getClass().getName()); GenPolynomial g = e2.resultant(P, S); if (debug) { logger.info("GCDProxy done e2 " + e2.getClass().getName()); } return g; } catch (PreemptingException e) { throw new RuntimeException("GCDProxy e2 pre " + e); //return P.ring.getONE(); } catch (Exception e) { //e.printStackTrace(); logger.info("GCDProxy e2 " + e); logger.info("GCDProxy P = " + P); logger.info("GCDProxy S = " + S); throw new RuntimeException("GCDProxy e2 " + e); //return P.ring.getONE(); } } }); try { g = pool.invokeAny(cs); } catch (InterruptedException ignored) { logger.info("InterruptedException " + ignored); Thread.currentThread().interrupt(); } catch (ExecutionException e) { logger.info("ExecutionException " + e); Thread.currentThread().interrupt(); } return g; } } jas-2.5/src/edu/mas/0000755000175000017500000000000012140140260014455 5ustar giovannigiovannijas-2.5/src/edu/mas/kern/0000755000175000017500000000000012140140260015414 5ustar giovannigiovannijas-2.5/src/edu/mas/kern/LIST.java0000644000175000017500000003033011540753212017043 0ustar giovannigiovanni/* * $Id: LIST.java 3571 2011-03-18 22:02:51Z kredel $ */ package edu.mas.kern; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * MAS and SAC2/Aldes LIST emulation and adaptor class. * @author Heinz Kredel */ public class LIST { public static final LIST SIL = null; // not usable /** * Internal data structure. */ protected LinkedList list = null; // List list not ok /** * Internal iterator. */ protected Iterator iter = null; /** * LIST constructor. */ public LIST() { this(new LinkedList()); } /** * internal LIST constructor. * @param l */ protected LIST(LinkedList l) { list = l; iter = null; } /** * LIST constructor. * @param l any Java List */ public LIST(List l) { this(new LinkedList(l)); } /** * Is null. Test if the list L is null. */ protected static boolean isNull(LIST L) { if (L == null || L.list == null) { return true; } return false; } /** * Is empty. Test if the list L is empty. */ public static boolean isEmpty(LIST L) { if (isNull(L) || L.list.isEmpty()) { return true; } if (L.iter != null) { return !L.iter.hasNext(); } return false; } /** * Length. L is a list. Returns length(L). */ public static int LENGTH(LIST L) { if (isNull(L)) { return 0; } return L.list.size(); } /** * First. L is a non-null list. a is the first element of L. */ public static C FIRST(LIST L) { if (isNull(L)) { return null; } if (L.iter != null) { if (L.iter.hasNext()) { return L.iter.next(); } L.iter = null; return null; } return L.list.getFirst(); } /** * Reductum. L is a non-null list. Returns the reductum of L. */ public static LIST RED(LIST L) { if (isNull(L)) { return L; } LIST LP = L; // ok: LP = new LIST( L.list.subList(1,L.list.size()) ); if (L.iter == null) { LP = new LIST(L.list); LP.iter = LP.list.iterator(); C x = LP.iter.next(); //System.out.println("x = " + x); } // else noop return LP; } /** * Set first. L is a non-null list. a is a list. The first element of L is * changed to a. */ public static void SFIRST(LIST L, C a) { if (!isNull(L)) { L.list.set(0, a); } } /** * Set reductum. L is a non-null list. LP is a list. The reductum of L is * changed to LP. */ public static void SRED(LIST L, LIST LP) { if (!isNull(L)) { L.list.subList(1, L.list.size()).clear(); if (!isEmpty(LP)) { L.list.addAll(LP.list); } } } /** * Composition. a is an object. L is a list. Returns the composition of a * and L. */ public static LIST COMP(C a, LIST L) { LIST LP = L; if (L == null) { LP = new LIST(); } LP.list.addFirst(a); return LP; } /** * To string. */ @Override public String toString() { if (isNull(this)) { return "[]"; } return list.toString(); } /** * Reductum. A is a list. i is a non-negative beta-integer not less than * LENGTH(A). B=A, if i=0. Otherwise, B is the i-th reductum of A. */ public static LIST REDUCT(LIST L, int i) { LIST LP = null; if (!isNull(L)) { LP = new LIST(L.list.subList(i, L.list.size())); } return LP; } /** * Reductum 2. L is a list of length 2 or more. LP=RED(RED(L)). */ public static LIST RED2(LIST L, int i) { LIST LP = null; if (!isNull(L)) { LP = new LIST(L.list.subList(2, L.list.size())); } return LP; } /** * Reductum 3. L is a list of length 3 or more. M is the third reductum of * L. */ public static LIST RED3(LIST L, int i) { LIST LP = null; if (!isNull(L)) { LP = new LIST(L.list.subList(3, L.list.size())); } return LP; } /** * Reductum 4. L is a list of length 4 or more. M is the fourth reductum of * L. */ public static LIST RED4(LIST L, int i) { LIST LP = null; if (!isNull(L)) { LP = new LIST(L.list.subList(42, L.list.size())); } return LP; } /** * Clock. Returns the current CPU clock reading in milliseconds. Intervalls * are system dependent. */ public static long CLOCK() { return java.lang.System.currentTimeMillis(); } /** * List element. A is a list. 1 le i le LENGTH(A). a is the i-th element of * A. */ public static C LELT(LIST L, int i) { C x = null; if (!isNull(L)) { x = L.list.get(i); } return x; } /** * Second. L is a list of length 2 or more. a is the second element of L. */ public static C SECOND(LIST L) { C x = null; if (!isNull(L)) { x = L.list.get(2); } return x; } /** * Third. L is a list of length 3 or more. a is the third element of L. */ public static C THIRD(LIST L) { C x = null; if (!isNull(L)) { x = L.list.get(3); } return x; } /** * Fourth. L is a list of length 4 or more. a is the fourth element of L. */ public static C FOURTH(LIST L) { C x = null; if (!isNull(L)) { x = L.list.get(4); } return x; } /** * Constructive concatenation. L1 and L2 are lists. L is the concatenation * of L1 and L2. The list L is constructed. */ public static LIST CCONC(LIST L1, LIST L2) { if (isNull(L1)) { return L2; } if (isNull(L2)) { return L1; } LinkedList list = new LinkedList(L1.list); list.addAll(L2.list); return new LIST(list); } /** * Constructive inverse. L is a list. M=INV(L). M is constructed using COMP. */ public static LIST CINV(LIST L) { if (isNull(L)) { return L; } LinkedList list = new LinkedList(L.list); Collections.reverse(list); return new LIST(list); } /** * Inverse. L is a list. The inverse of L is returned. The list L is * modified. */ public static LIST INV(LIST L) { if (isNull(L)) { return L; } Collections.reverse(L.list); return L; } /** * Composition 2. a and b are objects. L is a list. M=COMP(a,COMP(b,L)). */ public static LIST COMP2(C a, C b, LIST L) { LIST LP = L; if (L == null) { LP = new LIST(); } LP.list.addFirst(b); LP.list.addFirst(a); return LP; } /** * Composition 3. a1, a2 and a3 are objects. L is a list. * M=COMP(a1,COMP(a2,COMP(a3,L))). */ public static LIST COMP3(C a, C b, C c, LIST L) { LIST LP = L; if (L == null) { LP = new LIST(); } LP.list.addFirst(c); LP.list.addFirst(b); LP.list.addFirst(a); return LP; } /** * Composition 4. a1, a2, a3 and a4 are objects. L is a list. * M=COMP(a1,COMP(a2,COMP(a3,COMP(a4,l)))). */ public static LIST COMP3(C a, C b, C c, C d, LIST L) { LIST LP = L; if (L == null) { LP = new LIST(); } LP.list.addFirst(d); LP.list.addFirst(c); LP.list.addFirst(b); LP.list.addFirst(a); return LP; } /** * Concatenation. L1 and L2 are lists. L=CONC(L1,L2). The list L1 is * modified. */ public static LIST CONC(LIST L1, LIST L2) { if (isNull(L1)) { return L2; } if (isNull(L2)) { return L1; } L1.list.addAll(L2.list); return L1; } /** * Equal. a and b are objects. t=true if a and b are equal and otherwise * t=false. */ public static boolean EQUAL(LIST L1, LIST L2) { if (isNull(L1)) { return isNull(L2); } if (isNull(L2)) { return isNull(L1); } return L1.list.equals(L2.list); } /** * Extent. L is a list. n the number of cells of L. */ public static int EXTENT(LIST L) { if (isNull(L)) { return 0; } int n = 0; for (C a : L.list) { if (a instanceof LIST) { LIST LP = null; try { LP = (LIST) a; } catch (ClassCastException e) { } if (isNull(LP)) { n++; } else { n += EXTENT(LP); } } else { n++; } } return n; } /** * List, 1 element. a in an object. L is the list (a). */ public static LIST LIST1(C a) { LIST L = new LIST(); L.list.addFirst(a); return L; } /** * List, 10 elements. a1, a2, a3, a4, a5, a6, a7, a8, a9 and a10 are * objects. L is the list (a1,a2,a3,a4,a5,a6,a7,a8,a9,a10). */ public static LIST LIST10(C a1, C a2, C a3, C a4, C a5, C a6, C a7, C a8, C a9, C a10) { LIST L = new LIST(); L.list.addFirst(a10); L.list.addFirst(a9); L.list.addFirst(a8); L.list.addFirst(a7); L.list.addFirst(a6); L.list.addFirst(a5); L.list.addFirst(a4); L.list.addFirst(a3); L.list.addFirst(a2); L.list.addFirst(a1); return L; } /** * List, 2 elements. a and b are objects. L is the list (a,b). */ public static LIST LIST2(C a, C b) { LIST L = new LIST(); L.list.addFirst(b); L.list.addFirst(a); return L; } /** * List, 3 elements. a1, a2 and a3 are objects. L=(a1,a2,a3). */ public static LIST LIST3(C a, C b, C c) { LIST L = new LIST(); L.list.addFirst(c); L.list.addFirst(b); L.list.addFirst(a); return L; } /** * List, 4 elements. a1, a2, a3 and a4 are objects. L is the list * (a1,a2,a3,a4). */ public static LIST LIST4(C a, C b, C c, C d) { LIST L = new LIST(); L.list.addFirst(d); L.list.addFirst(c); L.list.addFirst(b); L.list.addFirst(a); return L; } /** * List, 5 elements. a1,a2,a3,a4 and a5 are objects. L is the list * (a1,a2,a3,a4,a5). */ public static LIST LIST5(C a, C b, C c, C d, C e) { LIST L = new LIST(); L.list.addFirst(e); L.list.addFirst(d); L.list.addFirst(c); L.list.addFirst(b); L.list.addFirst(a); return L; } /** * Order. L is a list. maximal depth of L. */ public static int ORDER(LIST L) { if (isNull(L)) { return 0; } int n = 0; for (C a : L.list) { if (a instanceof LIST) { LIST LP = null; try { LP = (LIST) a; } catch (ClassCastException e) { } if (!isNull(LP)) { int o = ORDER(LP); if (o > n) { // max n = o; } } } } return n + 1; } } jas-2.5/src/edu/mas/kern/package.html0000644000175000017500000000161011046672606017715 0ustar giovannigiovanni Adaptors to MAS classes

Adaptors to MAS classes.

This package contains classes with the MAS module and method names. Semantics may not be preserved but should work with some preprocessing code transformations. For example ADV(a,b,c) must be substituted by b=FIRST(a); c=RED(a).


Heinz Kredel

Last modified: Fri Aug 8 00:20:24 CEST 2008

$Id: package.html 2002 2008-08-07 22:21:58Z kredel $

jas-2.5/download.html0000644000175000017500000003743212140140260015037 0ustar giovannigiovanni JAS Download

Download, installation and unit tests

Download jar-files or clone repository

  • This is JAS version: jas-2.5, subversion revision: 4408 (export at 2013-05-01).

  • The JAS classes jar-file jas-2.5.4408-bin.jar can be used the same way as any other Java archive during compilation and execution of your Java programs. It is compiled using Java 7 from OpenJDK (IcedTea7).
    The source code is in jas-2.5.4408-src.zip current version should compile on Java 1.5, 1.6 and 1.7 (aka Java 5, 6 and 7). (right click on the link and chose "save link as")
    The Javadoc API documentation is in jas-2.5.4408-doc.zip for current version.

  • The JAS Git repository is available with

     git clone http://krum.rz.uni-mannheim.de/jas.git  jas
    
  • Required libraries:
    lib/log4j.jar (from Apache Log4j),
    lib/junit.jar (from Junit),
    In case you have the first two ones, just ensure they are in the correct location (e.g. ../lib/) or they are in the class path.

    In case you can not use Apache log4j for some reason, there is an adaptor package mylog.jar which delegates all logging calls to native Java logging. For Android there is the adaptor package droidlog.jar which delegates all logging calls to native Android logging.

  • Optional libraries and files:

     

  • For latest developments see JAS Weblog and the Subversion change log.

Installation

  • Add the JAS jar-file and the other required jar-files to the classpath. Start using it in your applications. For example

    javac -classpath log4j.jar:junit.jar:jas.jar:. -d . src/edu/jas/gb/Examples.java
    
    java  -classpath log4j.jar:junit.jar:jas.jar:.      edu.jas.gb.Examples
    
  • If you want to develop with JAS, then extract the jar-file in a new directory jar -xvf jas-[version]-src.jar

  • JAS is currently developed for Java 6 (Sun JDK 1.6 and OpenJDK 1.6). It will compile also under Java 5 (Sun JDK 1.5), but some (concurrency) classes may not work under the Java Virtual Machine (JVM) of JRE-1.5. It seems best to disable automatic parallel computation then (see edu.jas.kern.ComputerThreads.NO_THREADS).

  • Among the extracted files, there is an Ant build script build.xml and also a Gnu make file Makefile.
    To use Ant, you must edit the build.xml file and adjust the lib property to point to the directory where you downloaded the jar files. Also be sure to use the correct JDK version, e.g. via setting the JAVA_HOME environment variable.
    To use the Gnu make file, you must edit the Makefile and adjust the JDK and the LIBPATH variables.

  • Most useful Ant targets:
    ant compile changed Java files are compiled,
    ant recompile all Java files are compiled,
    ant test run all JUnit tests,
    ant clean remove backup files,
    ant distclean remove all class files,
    ant doc create the Javadocs.

  • Most useful make file targets:
    make "class" run the main() method of the class,
    e.g. make edu.jas.poly.Examples run the class Examples.

Unit tests with JUnit

  • Unit tests can be run with the "test" target for ant, e.g. ant test

  • The output of the unit tests is collected in the directory test for inspection.

  • The test units work mainly with generated random polynomials. The parameters are choosen such that the resulting Groebner bases are not to hard to compute. However some random polynomials may be to big and the running time may occasionally be several minutes (but not hours).
    On the other hand random polynomials may sometimes be zero or one. If such input does not make sense the test will fail. I.e. some tests will fail from time to time, but not for repeated execution of the test. So if a test fails rerun the test a few times.

Documentation

  • The JAS documentation is contained in the jar files jas-[version]-src.jar and jas-[version]-doc.jar. Extract the jar files and start exploring with any browser from the index.html file in the main directory.

  • The JAS javadoc API documents and the jython documents can also be browsed online: API javadocs and epydoc of jas.py.

  • README and licencing: COPYING.jas (GPL) or COPYING.lgpl.jas (LGPL)

Usage with the Eclipse IDE

The JAS source distribution can also be compiled and used from the Eclipse integrated development environment.

Instructions to install the JAS source:

  1. Download the JAS source jar and unpack to some directory
  2. Download the Log4j and the Junit jar files
  3. Start eclipse
  4. Create a new project from "existing source"
  5. Specify the plain source directory /src from 1.
  6. Add the jars from 2. to the project libraries as "external JARs"
  7. Create a new project or use your default project
  8. In the project properties add as "required project" the JAS project from 4.

Instructions to install the JAS binary:

  1. Download the JAS binary jar file
  2. Download the Log4j and the Junit jar files
  3. Start eclipse
  4. In your projects properties add the jar files from 1. and 2. to the project libraries as "external JARs"

Create and edit a sample java programm which uses the JAS API. E.g. the following sample computes the first ten Legendre polynomials.

import java.util.List;
import java.util.ArrayList;

import edu.jas.arith.BigRational;
import edu.jas.poly.GenPolynomial;
import edu.jas.poly.GenPolynomialRing;

public class mytests {

    public static void main(String[] args) {
         BigRational fac = new BigRational();
         String[] var = new String[]{ "x" };
         GenPolynomialRing<BigRational> ring
             = new GenPolynomialRing<BigRational>(fac,1,var);

         int n = 10;
         List<GenPolynomial<BigRational>> P 
             = new ArrayList<GenPolynomial<BigRational>>(n);
         GenPolynomial<BigRational> t, one, x, xc;
         BigRational n21, nn;

         one = ring.getONE();
         x   = ring.univariate(0);

         P.add( one );
         P.add( x );
         for ( int i = 2; i < n; i++ ) {
             n21 = new BigRational( 2*i-1 );
             xc = x.multiply( n21 );
             t = xc.multiply( P.get(i-1) );  // (2n-1) x P[n-1]
             nn = new BigRational( i-1 );
             xc = P.get(i-2).multiply( nn ); // (n-1) P[n-2]
             t = t.subtract( xc );
             nn = new BigRational(1,i);      
             t = t.multiply( nn );           // 1/n t
             P.add( t );
         }
         for ( int i = 0; i < n; i++ ) {
             System.out.println("P["+i+"] = " + P.get(i) );
         }
    }
}

Using the Jython interpreter

  • Be sure you have downloaded the above libraries log4j.jar, junit.jar and jas*-bin.jar. JAS-2.4 is using and has been tested with Jython 2.5.2.

  • The main file to interface to the JAS library is jas.py. It must be imported by other Python files. HTML documents of the interface can be found here.

  • Start using JAS, e.g.

    jython -J-cp "../lib/log4j.jar:../lib/junit.jar:." examples/trinks.py

    The examples/trinks.py contains an Groebner base example named after its proposer Mr. Trinks. The file runs a sequential, a parallel and a distributed version of the Groebner base algorithms.

  • For further discussion of the JAS jython interface see User guide.

Using the JRuby interpreter

  • Be sure you have downloaded the above libraries log4j.jar, junit.jar and jas*-bin.jar. JAS-2.4 is using and has been tested with JRuby 1.6.4 (Ruby 1.8.7 & 1.9.2 compatible)

  • The main file to interface to the JAS library is jas.rb. It must be required by other Ruby files. HTML documents of the interface can be found here.

  • Start using JAS, e.g.

    jruby -J-cp "../lib/log4j.jar:../lib/junit.jar:." examples/trinks.rb

    The examples/trinks.rb contains an Groebner base example named after its proposer Mr. Trinks. The file runs a sequential, a parallel and a distributed version of the Groebner base algorithms.

  • For further discussion of the JAS scripting interface see User guide.

Using the Ruboto-IRB-JAS Android application

  • Be sure you have installed the above Android application package ruboto-irb-jas-debug.apk. It contains all required libraries and scripts. JAS-2.4 has been tested with Android 2.3 and 4.1 and is using JRuby 1.6.4 (Ruby 1.8.7 & 1.9.2 compatible)

  • The JAS app uses the Ruby IRB Ruboto for Android. This is just a Ruby interpreter running on Android together with a text editor. So all JAS JRuby scripts can be run in this environment. The JAS Java programs are included in compiled and transformed Dalvik "dex" format. Up to now, no functional problems have been encountered, i.e. all JAS Java code runs. However, due to limitations in CPU speed and memory on mobile phones or tablets eventually not all examples and problems will execute. In 2012, comparison of a two year old Android tablet (1 GHz, 0.5 GB) and a three year old PC (3 GHz, 4 GB) show that the examples run about 5 times slower than on the PC.

  • The main Ruboto screen with the "trinks.rb" example and its output looks as follows. Also the arbitrary precision numbers arithmetic works on Android.

    screen shot   screen shot   screen shot

    The list of examples can be accessed via the "scripts" button.

    screen shot

  • For further discussion of the JAS scripting interface see User guide.


Heinz Kredel

Last modified: Tue Apr 30 10:35:51 CEST 2013

jas-2.5/navigate.html0000644000175000017500000000641511654605524015045 0ustar giovannigiovanni Navigation

J A S


Home


Documentation
Users guide
API guide
Javadoc
Epydoc
Rdoc
FAQ
Weblog
Credits
Related Projects


Download
COPYING
Google code
freecode (freshmeat)
Ohloh
Contact


Google this site:

www.nosoftwarepatents.com

no frames

jas-2.5/.gitignore0000644000175000017500000000032311401776466014345 0ustar giovannigiovanni/*.class /*.old /*.orig /*.jar /*.tar /*.gz /*.tgz /*.out /*.out* /*.jad /*.txt /*.log /edu /source /classes /DTD /application /arith /kern /module /poly /ring /structure /ufd /util /vector /test /ps /NOTES* *~