001/*
002 * $Id: RunGB.java 5788 2018-01-04 21:07:10Z kredel $
003 */
004
005package edu.jas.application;
006
007
008import java.io.BufferedReader;
009import java.io.FileInputStream;
010import java.io.FileNotFoundException;
011import java.io.IOException;
012import java.io.InputStreamReader;
013import java.io.Reader;
014import java.io.StringReader;
015import java.lang.reflect.InvocationTargetException;
016import java.lang.reflect.Method;
017import java.nio.charset.Charset;
018import java.util.Arrays;
019import java.util.List;
020import java.util.jar.JarEntry;
021import java.util.jar.JarFile;
022
023import org.apache.log4j.BasicConfigurator;
024
025import edu.jas.gb.GroebnerBaseAbstract;
026import edu.jas.gb.GroebnerBaseDistributedEC;
027import edu.jas.gb.GroebnerBaseDistributedHybridEC;
028import edu.jas.gb.GroebnerBaseParallel;
029import edu.jas.gb.GroebnerBaseSeq;
030import edu.jas.gb.OrderedSyzPairlist;
031import edu.jas.gb.ReductionPar;
032import edu.jas.gb.ReductionSeq;
033import edu.jas.gbufd.GBFactory;
034import edu.jas.gbufd.GroebnerBasePseudoParallel;
035import edu.jas.kern.ComputerThreads;
036import edu.jas.poly.GenPolynomialRing;
037import edu.jas.poly.GenPolynomialTokenizer;
038import edu.jas.poly.PolynomialList;
039import edu.jas.util.CatReader;
040import edu.jas.util.ExecutableServer;
041
042
043/**
044 * Simple setup to run a GB example. <br>
045 * Usage: RunGB [seq(+)|par(+)|build=string|disthyb|cli] &lt;file&gt;
046 * #procs/#threadsPerNode [machinefile] &lt;check&gt; &lt;nolog&gt; <br>
047 * Build string can be any combination of method calls from GBAlgorithmBuilder.
048 * Method polynomialRing() is called based on declaration from "file". Method
049 * build() is called automatically. For example <br>
050 * build=syzygyPairlist.iterated.graded.parallel(3)
051 * @see edu.jas.application.GBAlgorithmBuilder
052 * @author Heinz Kredel
053 */
054public class RunGB {
055
056
057    /**
058     * Check result GB if it is a GB.
059     */
060    static boolean doCheck = false;
061
062
063    /**
064     * Enable logging.
065     */
066    static boolean doLog = true;
067
068
069    /**
070     * main method to be called from commandline <br>
071     * Usage: RunGB [seq|par(+)|build=string|disthyb(+)|cli] &lt;file&gt;
072     * #procs/#threadsPerNode [machinefile] &lt;check&gt; &lt;nolog&gt;
073     */
074    @SuppressWarnings("unchecked")
075    public static void main(String[] args) {
076
077        String[] allkinds = new String[] { "seq", "seq+", "par", "par+", "build=", "disthyb", "disthyb+",
078                "cli" }; // must be last
079
080        String usage = "Usage: RunGB [ " + join(allkinds, " | ") + "[port] ] " + "<file> "
081                        + "#procs/#threadsPerNode " + "[machinefile] " + "[check] [nolog]";
082
083        if (args.length < 1) {
084            System.out.println("args: " + Arrays.toString(args));
085            System.out.println(usage);
086            return;
087        }
088
089        boolean plusextra = false;
090        String kind = args[0];
091        boolean sup = false;
092        int k = -1;
093        for (int i = 0; i < args.length; i++) {
094            int j = indexOf(allkinds, args[i]);
095            if (j < 0) {
096                continue;
097            }
098            sup = true;
099            k = i;
100            kind = args[k];
101            break;
102        }
103        if (!sup) {
104            System.out.println("args(sup): " + Arrays.toString(args));
105            System.out.println(usage);
106            return;
107        }
108        if (kind.indexOf("+") >= 0) {
109            plusextra = true;
110        }
111        System.out.println("kind: " + kind + ", k = " + k);
112
113        final int GB_SERVER_PORT = 7114;
114        int port = GB_SERVER_PORT;
115
116        if (kind.equals("cli")) {
117            if (args.length - k >= 2) {
118                try {
119                    port = Integer.parseInt(args[k + 1]);
120                } catch (NumberFormatException e) {
121                    e.printStackTrace();
122                    System.out.println("args(port): " + Arrays.toString(args));
123                    System.out.println(usage);
124                    return;
125                }
126            }
127            runClient(port);
128            return;
129        }
130
131        String filename = null;
132        if (!kind.equals("cli")) {
133            if (args.length - k < 2) {
134                System.out.println("args(file): " + Arrays.toString(args));
135                System.out.println(usage);
136                return;
137            }
138            filename = args[k + 1];
139        }
140
141        int j = indexOf(args, "check");
142        if (j >= 0) {
143            doCheck = true;
144        }
145        j = indexOf(args, "nolog");
146        if (j >= 0) {
147            doLog = false;
148        }
149
150        int threads = 0;
151        int threadsPerNode = 1;
152        if (kind.startsWith("par") || kind.startsWith("dist")) {
153            if (args.length - k < 3) {
154                System.out.println("args(par|dist): " + Arrays.toString(args));
155                System.out.println(usage);
156                return;
157            }
158            String tup = args[k + 2];
159            String t = tup;
160            int i = tup.indexOf("/");
161            if (i >= 0) {
162                t = tup.substring(0, i).trim();
163                tup = tup.substring(i + 1).trim();
164                try {
165                    threadsPerNode = Integer.parseInt(tup);
166                } catch (NumberFormatException e) {
167                    e.printStackTrace();
168                    System.out.println("args(threadsPerNode): " + Arrays.toString(args));
169                    System.out.println(usage);
170                    return;
171                }
172            }
173            try {
174                threads = Integer.parseInt(t);
175            } catch (NumberFormatException e) {
176                e.printStackTrace();
177                System.out.println("args(threads): " + Arrays.toString(args));
178                System.out.println(usage);
179                return;
180            }
181        }
182
183        String mfile = null;
184        if (kind.startsWith("dist")) {
185            if (args.length - k >= 4) {
186                mfile = args[k + 3];
187            } else {
188                mfile = "machines";
189            }
190        }
191
192        Reader problem = getReader(filename);
193        if (problem == null) {
194            System.out.println("args(file): " + filename);
195            System.out.println("args(file): examples.jar(" + filename + ")");
196            System.out.println("args(file): " + Arrays.toString(args));
197            System.out.println(usage);
198            return;
199        }
200        RingFactoryTokenizer rftok = new RingFactoryTokenizer(problem);
201        GenPolynomialRing pfac = null;
202        try {
203            pfac = rftok.nextPolynomialRing();
204            rftok = null;
205        } catch (IOException e) {
206            e.printStackTrace();
207            return;
208        }
209        Reader polyreader = new CatReader(new StringReader("("), problem); // ( has gone
210        //Reader polyreader = problem; 
211        GenPolynomialTokenizer tok = new GenPolynomialTokenizer(pfac, polyreader);
212        PolynomialList S = null;
213        try {
214            S = new PolynomialList(pfac, tok.nextPolynomialList());
215        } catch (IOException e) {
216            e.printStackTrace();
217            return;
218        }
219        System.out.println("input S =\n" + S);
220
221        GroebnerBaseAbstract gb = null;
222        if (kind.startsWith("build")) {
223            gb = getGBalgo(args, kind, S.ring);
224            if (gb == null) {
225                System.out.println(usage);
226                return;
227            }
228        }
229
230        if (doLog) {
231            BasicConfigurator.configure();
232        }
233
234        if (kind.startsWith("seq")) {
235            runSequential(S, plusextra);
236        } else if (kind.startsWith("par")) {
237            runParallel(S, threads, plusextra);
238        } else if (kind.startsWith("disthyb")) {
239            runMasterHyb(S, threads, threadsPerNode, mfile, port, plusextra);
240            //} else if (kind.startsWith("dist")) {
241            //runMaster(S, threads, mfile, port, plusextra);
242        } else if (kind.startsWith("build")) {
243            runGB(S, gb);
244        }
245        ComputerThreads.terminate();
246        //System.exit(0);
247    }
248
249
250    // no more used
251    @SuppressWarnings("unchecked")
252    static void runMaster(PolynomialList S, int threads, String mfile, int port, boolean plusextra) {
253        List L = S.list;
254        List G = null;
255        long t, t1;
256        GroebnerBaseDistributedEC gbd = null;
257        GroebnerBaseDistributedEC gbds = null;
258
259        System.out.println("\nGroebner base distributed (" + threads + ", " + mfile + ", " + port + ") ...");
260        t = System.currentTimeMillis();
261        if (plusextra) {
262            //gbds = new GroebnerBaseDistributedEC(threads,mfile, port);
263            gbds = new GroebnerBaseDistributedEC(mfile, threads, new OrderedSyzPairlist(), port);
264        } else {
265            gbd = new GroebnerBaseDistributedEC(mfile, threads, port);
266        }
267        t1 = System.currentTimeMillis();
268        if (plusextra) {
269            G = gbds.GB(L);
270        } else {
271            G = gbd.GB(L);
272        }
273        t1 = System.currentTimeMillis() - t1;
274        if (plusextra) {
275            gbds.terminate(); //false);
276        } else {
277            gbd.terminate(); //false);
278        }
279        S = new PolynomialList(S.ring, G);
280        System.out.println("G =\n" + S);
281        System.out.println("G.size() = " + G.size());
282        t = System.currentTimeMillis() - t;
283        if (plusextra) {
284            System.out.print("d+ ");
285        } else {
286            System.out.print("d ");
287        }
288        System.out.println("= " + threads + ", time = " + t1 + " milliseconds, " + (t - t1) + " start-up "
289                        + ", total = " + t);
290        checkGB(S);
291        System.out.println("");
292    }
293
294
295    @SuppressWarnings("unchecked")
296    static void runMasterHyb(PolynomialList S, int threads, int threadsPerNode, String mfile, int port,
297                    boolean plusextra) {
298        List L = S.list;
299        List G = null;
300        long t, t1;
301        GroebnerBaseDistributedHybridEC gbd = null;
302        GroebnerBaseDistributedHybridEC gbds = null;
303
304        System.out.println("\nGroebner base distributed hybrid (" + threads + "/" + threadsPerNode + ", "
305                        + mfile + ", " + port + ") ...");
306        t = System.currentTimeMillis();
307        if (plusextra) {
308            // gbds = new GroebnerBaseDistributedHybridEC(mfile, threads,port);
309            gbds = new GroebnerBaseDistributedHybridEC(mfile, threads, threadsPerNode,
310                            new OrderedSyzPairlist(), port);
311        } else {
312            gbd = new GroebnerBaseDistributedHybridEC(mfile, threads, threadsPerNode, port);
313        }
314        t1 = System.currentTimeMillis();
315        if (plusextra) {
316            G = gbds.GB(L);
317        } else {
318            G = gbd.GB(L);
319        }
320        t1 = System.currentTimeMillis() - t1;
321        if (plusextra) {
322            gbds.terminate(); // true
323        } else {
324            gbd.terminate(); // false plus eventually killed by script
325        }
326        t = System.currentTimeMillis() - t;
327        S = new PolynomialList(S.ring, G);
328        System.out.println("G =\n" + S);
329        System.out.println("G.size() = " + G.size());
330        if (plusextra) {
331            System.out.print("d+ ");
332        } else {
333            System.out.print("d ");
334        }
335        System.out.println("= " + threads + ", ppn = " + threadsPerNode + ", time = " + t1 + " milliseconds, "
336                        + (t - t1) + " start-up " + ", total = " + t);
337        checkGB(S);
338        System.out.println("");
339    }
340
341
342    static void runClient(int port) {
343        System.out.println("\nGroebner base distributed client (" + port + ") ...");
344        ExecutableServer es = new ExecutableServer(port);
345        es.init();
346        try {
347            es.join();
348        } catch (InterruptedException e) {
349            // ignored
350        }
351        System.out.println("runClient() done: " + es);
352    }
353
354
355    @SuppressWarnings("unchecked")
356    static void runParallel(PolynomialList S, int threads, boolean plusextra) {
357        List L = S.list;
358        List G;
359        long t;
360        GroebnerBaseAbstract bb = null;
361        GroebnerBaseAbstract bbs = null;
362        if (plusextra) {
363            //bbs = new GroebnerBaseSeqPairParallel(threads);
364            bbs = new GroebnerBaseParallel(threads, new ReductionPar(), new OrderedSyzPairlist());
365        } else {
366            if (S.ring.coFac.isField()) {
367                bb = new GroebnerBaseParallel(threads);
368            } else {
369                bb = new GroebnerBasePseudoParallel(threads, S.ring.coFac);
370            }
371        }
372        System.out.println("\nGroebner base parallel (" + threads + ") ...");
373        t = System.currentTimeMillis();
374        if (plusextra) {
375            G = bbs.GB(L);
376        } else {
377            G = bb.GB(L);
378        }
379        t = System.currentTimeMillis() - t;
380        S = new PolynomialList(S.ring, G);
381        System.out.println("G =\n" + S);
382        System.out.println("G.size() = " + G.size());
383
384        if (plusextra) {
385            System.out.print("p+ ");
386        } else {
387            System.out.print("p ");
388        }
389        System.out.println("= " + threads + ", time = " + t + " milliseconds");
390        if (plusextra) {
391            bbs.terminate();
392        } else {
393            bb.terminate();
394        }
395        checkGB(S);
396        System.out.println("");
397    }
398
399
400    @SuppressWarnings("unchecked")
401    static void runSequential(PolynomialList S, boolean plusextra) {
402        List L = S.list;
403        List G;
404        long t;
405        GroebnerBaseAbstract bb = null;
406        if (plusextra) {
407            //bb = new GroebnerBaseSeqPlusextra();
408            bb = new GroebnerBaseSeq(new ReductionSeq(), new OrderedSyzPairlist());
409        } else {
410            bb = GBFactory.getImplementation(S.ring.coFac); //new GroebnerBaseSeq();
411        }
412        System.out.println("\nGroebner base sequential ...");
413        t = System.currentTimeMillis();
414        G = bb.GB(L);
415        t = System.currentTimeMillis() - t;
416        S = new PolynomialList(S.ring, G);
417        System.out.println("G =\n" + S);
418        System.out.println("G.size() = " + G.size());
419        if (plusextra) {
420            System.out.print("seq+, ");
421        } else {
422            System.out.print("seq, ");
423        }
424        System.out.println("time = " + t + " milliseconds");
425        checkGB(S);
426        System.out.println("");
427    }
428
429
430    @SuppressWarnings("unchecked")
431    static void runGB(PolynomialList S, GroebnerBaseAbstract bb) {
432        List L = S.list;
433        List G;
434        long t;
435        if (bb == null) { // should not happen
436            bb = GBFactory.getImplementation(S.ring.coFac);
437        }
438        String bbs = bb.toString().replaceAll(" ", "");
439        System.out.println("\nGroebner base build=" + bbs + " ...");
440        t = System.currentTimeMillis();
441        G = bb.GB(L);
442        t = System.currentTimeMillis() - t;
443        S = new PolynomialList(S.ring, G);
444        bbs = bb.toString().replaceAll(" ", "");
445        System.out.println("G =\n" + S);
446        System.out.println("G.size() = " + G.size());
447        System.out.print("build=" + bbs + ", ");
448        System.out.println("time = " + t + " milliseconds");
449        checkGB(S);
450        bb.terminate();
451        System.out.println("");
452    }
453
454
455    @SuppressWarnings("unchecked")
456    static void checkGB(PolynomialList S) {
457        if (!doCheck) {
458            return;
459        }
460        GroebnerBaseAbstract bb = GBFactory.getImplementation(S.ring.coFac);
461        long t = System.currentTimeMillis();
462        boolean chk = bb.isGB(S.list, false);
463        t = System.currentTimeMillis() - t;
464        System.out.println("check isGB = " + chk + " in " + t + " milliseconds");
465    }
466
467
468    static int indexOf(String[] args, String s) {
469        for (int i = 0; i < args.length; i++) {
470            if (s.startsWith(args[i])) {
471                return i;
472            }
473        }
474        return -1;
475    }
476
477
478    static String join(String[] args, String d) {
479        StringBuffer sb = new StringBuffer();
480        for (int i = 0; i < args.length; i++) {
481            if (i > 0) {
482                sb.append(d);
483            }
484            sb.append(args[i]);
485        }
486        return sb.toString();
487    }
488
489
490    @SuppressWarnings("resource")
491    static Reader getReader(String filename) {
492        Reader problem = null;
493        Exception fnf = null;
494        try {
495            problem = new InputStreamReader(new FileInputStream(filename), Charset.forName("UTF8"));
496            problem = new BufferedReader(problem);
497        } catch (FileNotFoundException e) {
498            fnf = e;
499        }
500        if (problem != null) {
501            return problem;
502        }
503        String examples = "examples.jar";
504        try {
505            JarFile jf = new JarFile(examples);
506            JarEntry je = jf.getJarEntry(filename);
507            if (je == null) {
508                if (jf != null) {
509                    jf.close();
510                }
511                fnf.printStackTrace();
512                return problem;
513            }
514            problem = new InputStreamReader(jf.getInputStream(je), Charset.forName("UTF8"));
515            problem = new BufferedReader(problem);
516        } catch (FileNotFoundException e) {
517            fnf.printStackTrace();
518            e.printStackTrace();
519        } catch (IOException e) {
520            fnf.printStackTrace();
521            e.printStackTrace();
522            //} finally { not possible, problem must remain open
523            //jf.close();
524        }
525        return problem;
526    }
527
528
529    static GroebnerBaseAbstract getGBalgo(String[] args, String bstr, GenPolynomialRing ring) {
530        GroebnerBaseAbstract gb = null;
531        int i = bstr.indexOf("=");
532        if (i < 0) {
533            System.out.println("args(build): " + Arrays.toString(args));
534            return gb;
535        }
536        i += 1;
537        String tb = bstr.substring(i);
538        //System.out.println("build=" + tb);
539        GBAlgorithmBuilder ab = GBAlgorithmBuilder.polynomialRing(ring);
540        //System.out.println("ab = " + ab);
541        while (!tb.isEmpty()) {
542            int ii = tb.indexOf(".");
543            String mth;
544            if (ii >= 0) {
545                mth = tb.substring(0, ii);
546                tb = tb.substring(ii + 1);
547            } else {
548                mth = tb;
549                tb = "";
550            }
551            if (mth.startsWith("build")) {
552                continue;
553            }
554            String parm = "";
555            int jj = mth.indexOf("()");
556            if (jj >= 0) {
557                mth = mth.substring(0, jj);
558            } else {
559                jj = mth.indexOf("(");
560                if (jj >= 0) {
561                    parm = mth.substring(jj + 1);
562                    mth = mth.substring(0, jj);
563                    jj = parm.indexOf(")");
564                    parm = parm.substring(0, jj);
565                }
566            }
567            //System.out.println("mth = " + mth + ", parm = " + parm);
568            try {
569                Method method;
570                if (parm.isEmpty()) {
571                    method = ab.getClass().getMethod(mth, (Class<?>[]) null);
572                    ab = (GBAlgorithmBuilder) method.invoke(ab, (Object[]) null);
573                } else {
574                    int tparm = Integer.parseInt(parm);
575                    method = ab.getClass().getMethod(mth, int.class);
576                    ab = (GBAlgorithmBuilder) method.invoke(ab, tparm);
577                }
578            } catch (NoSuchMethodException e) {
579                System.out.println("args(build,method): " + Arrays.toString(args));
580                return gb;
581            } catch (IllegalAccessException e) {
582                System.out.println("args(build,access): " + Arrays.toString(args));
583                return gb;
584            } catch (InvocationTargetException e) {
585                System.out.println("args(build,invocation): " + Arrays.toString(args));
586                return gb;
587            } catch (NumberFormatException e) {
588                System.out.println("args(build,number): " + Arrays.toString(args));
589                return gb;
590            }
591        }
592        gb = ab.build();
593        //System.out.println("gb = " + gb);
594        return gb;
595    }
596
597}