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