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