001/*
002 * $Id: GBSigBased.java 5809 2018-04-23 19:54:18Z kredel $
003 */
004
005package edu.jas.gb;
006
007
008import java.util.ArrayList;
009import java.util.List;
010
011import javax.script.ScriptEngine;
012import javax.script.ScriptEngineManager;
013import javax.script.ScriptException;
014
015import org.apache.log4j.Logger;
016
017import edu.jas.poly.GenPolynomial;
018import edu.jas.structure.GcdRingElem;
019
020
021/**
022 * Groebner bases via signatur based GBs using jython script. TODO: Computing
023 * via the ScriptEngine is way slower than the direct execution in the jython
024 * interpreter. Check if a different engine is in the path or if it must be
025 * configured in some special way.
026 * @author Heinz Kredel
027 */
028
029public class GBSigBased<C extends GcdRingElem<C>> extends GroebnerBaseAbstract<C> {
030
031
032    private static final Logger logger = Logger.getLogger(GBSigBased.class);
033
034
035    private static final boolean debug = logger.isDebugEnabled(); //logger.isInfoEnabled();
036
037
038    /**
039     * GB algorithm indicators:
040     * sbgb = sigbased_gb(), arri = arris_algorithm(), 
041     * ggv = ggv(), ggv1 = ggv_first_implementation(), f5 = f5(), ff5 = f5z().
042     */
043    public static enum GBAlgo {
044        sbgb, arri, ggv, ggv1, f5, ff5
045    }
046
047
048    /**
049     * Scripting engine.
050     */
051    public final ScriptEngine engine;
052
053
054    /**
055     * Selected GB algorithm.
056     */
057    public final GBAlgo algo;
058
059
060    /**
061     * GBSigBased constructor.
062     */
063    public GBSigBased() {
064        this(GBAlgo.ggv1);
065    }
066
067
068    /**
069     * GBSigBased constructor.
070     * @param a GB algorithm indicator.
071     */
072    public GBSigBased(GBAlgo a) {
073        algo = a;
074        ScriptEngineManager manager = new ScriptEngineManager();
075        //System.out.println("manager = " + manager);
076        //System.out.println("factories = " + manager.getEngineFactories());
077        engine = manager.getEngineByExtension("py");
078        if (engine == null) {
079            logger.error("no script engine found");
080            throw new RuntimeException("no script engine found");
081        }
082        StringBuffer sb = new StringBuffer();
083        sb.append("from jas import PolyRing, ZZ, QQ, arraylist2pylist, pylist2arraylist;\n");
084        sb.append("from basic_sigbased_gb import sigbased_gb, arris_algorithm, ggv, ggv_first_implementation, f5, f5z;\n");
085        sb.append("sbgb = sigbased_gb();\n");
086        sb.append("arri = arris_algorithm();\n");
087        sb.append("ggv = ggv();\n");
088        sb.append("ggv1 = ggv_first_implementation();\n");
089        sb.append("f5 = f5();\n");
090        sb.append("ff5 = f5z();\n");
091        String ex = sb.toString();
092        if (debug) {
093            logger.info("input for evaluation:\n" + ex);
094        }
095        try {
096            Object ans = engine.eval(ex);
097            if (ans != null) {
098                logger.info("constructor answer: " + ans);
099            }
100        } catch (ScriptException e) {
101            e.printStackTrace();
102            throw new RuntimeException(e);
103        }
104        logger.info(toString());
105    }
106
107
108    /**
109     * Get the String representation with GB engine.
110     * @see java.lang.Object#toString()
111     */
112    @Override
113    public String toString() {
114        return "GBSigBased[ " + engine.getClass().getName() + ", GBAlgo = " + algo + " ]";
115    }
116
117
118    /**
119     * Cleanup and terminate ThreadPool.
120     */
121    @Override
122    public void terminate() {
123    }
124
125
126    /**
127     * Cancel ThreadPool.
128     */
129    @Override
130    public int cancel() {
131        return 0;
132    }
133
134
135    /**
136     * Groebner base.
137     * @param modv module variable number.
138     * @param F polynomial list.
139     * @return GB(F) a Groebner base of F.
140     */
141    @Override
142    @SuppressWarnings("unchecked")
143    public List<GenPolynomial<C>> GB(int modv, List<GenPolynomial<C>> F) {
144        if (F == null || F.isEmpty()) {
145            return F;
146        }
147        if (modv != 0) {
148            throw new UnsupportedOperationException("implemented only for modv = 0, not " + modv);
149        }
150        //GenPolynomialRing<C> pfac = F.get(0).ring;
151        List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>();
152        long millis = System.currentTimeMillis();
153        try {
154            engine.put("F", F);
155            StringBuffer sb = new StringBuffer();
156            //sb.append("r = " + pfac.toScript() + ";\n");
157            //sb.append("print str(r);\n");
158            //sb.append("print \"F = \" + str(F);\n");
159            sb.append("Fp = arraylist2pylist(F);\n");
160
161            //sb.append("Gp = sbgb.basis_sig(Fp);\n");
162            //sb.append("Gp = ff5.basis_sig(Fp);\n");
163            //sb.append("Gp = arri.basis_sig(Fp);\n");
164            //sb.append("Gp = ggv1.basis_sig(Fp);\n");
165            sb.append("Gp = " + algo + ".basis_sig(Fp);\n");
166            sb.append("G = pylist2arraylist(Gp);\n");
167
168            String ex = sb.toString();
169            if (debug) {
170                logger.info("input for evaluation:\n" + ex);
171            }
172            Object ans = engine.eval(ex);
173            if (ans != null) {
174                logger.info("answer: " + ans);
175            }
176            G = (List<GenPolynomial<C>>) engine.get("G");
177        } catch (ScriptException e) {
178            e.printStackTrace();
179        } catch (Exception e) {
180            e.printStackTrace();
181        }
182        millis = System.currentTimeMillis() - millis;
183        System.out.println("evaluation took " + millis);
184        if (debug) {
185            logger.info("polynomials G: " + G);
186        }
187        return G;
188    }
189
190}