001/*
002 * $Id: RunGB.java 5861 2018-07-20 10:09:03Z 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        Reader polyreader = new CatReader(new StringReader("("), problem); // ( has gone
198        //Reader polyreader = problem; 
199        GenPolynomialTokenizer tok = new GenPolynomialTokenizer(pfac, polyreader);
200        PolynomialList S = null;
201        try {
202            S = new PolynomialList(pfac, tok.nextPolynomialList());
203        } catch (IOException e) {
204            e.printStackTrace();
205            return;
206        }
207        System.out.println("input S =\n" + S);
208
209        GroebnerBaseAbstract gb = null;
210        if (kind.startsWith("build")) {
211            gb = getGBalgo(args, kind, S.ring);
212            if (gb == null) {
213                System.out.println(usage);
214                return;
215            }
216        }
217
218        if (kind.startsWith("seq")) {
219            runSequential(S, plusextra);
220        } else if (kind.startsWith("par")) {
221            runParallel(S, threads, plusextra);
222        } else if (kind.startsWith("disthyb")) {
223            runMasterHyb(S, threads, threadsPerNode, mfile, port, plusextra);
224            //} else if (kind.startsWith("dist")) {
225            //runMaster(S, threads, mfile, port, plusextra);
226        } else if (kind.startsWith("build")) {
227            runGB(S, gb);
228        }
229        ComputerThreads.terminate();
230        //System.exit(0);
231    }
232
233
234    // no more used
235    @SuppressWarnings("unchecked")
236    static void runMaster(PolynomialList S, int threads, String mfile, int port, boolean plusextra) {
237        List L = S.list;
238        List G = null;
239        long t, t1;
240        GroebnerBaseDistributedEC gbd = null;
241        GroebnerBaseDistributedEC gbds = null;
242
243        System.out.println("\nGroebner base distributed (" + threads + ", " + mfile + ", " + port + ") ...");
244        t = System.currentTimeMillis();
245        if (plusextra) {
246            //gbds = new GroebnerBaseDistributedEC(threads,mfile, port);
247            gbds = new GroebnerBaseDistributedEC(mfile, threads, new OrderedSyzPairlist(), port);
248        } else {
249            gbd = new GroebnerBaseDistributedEC(mfile, threads, port);
250        }
251        t1 = System.currentTimeMillis();
252        if (plusextra) {
253            G = gbds.GB(L);
254        } else {
255            G = gbd.GB(L);
256        }
257        t1 = System.currentTimeMillis() - t1;
258        if (plusextra) {
259            gbds.terminate(); //false);
260        } else {
261            gbd.terminate(); //false);
262        }
263        S = new PolynomialList(S.ring, G);
264        System.out.println("G =\n" + S);
265        System.out.println("G.size() = " + G.size());
266        t = System.currentTimeMillis() - t;
267        if (plusextra) {
268            System.out.print("d+ ");
269        } else {
270            System.out.print("d ");
271        }
272        System.out.println("= " + threads + ", time = " + t1 + " milliseconds, " + (t - t1) + " start-up "
273                        + ", total = " + t);
274        checkGB(S);
275        System.out.println("");
276    }
277
278
279    @SuppressWarnings("unchecked")
280    static void runMasterHyb(PolynomialList S, int threads, int threadsPerNode, String mfile, int port,
281                    boolean plusextra) {
282        List L = S.list;
283        List G = null;
284        long t, t1;
285        GroebnerBaseDistributedHybridEC gbd = null;
286        GroebnerBaseDistributedHybridEC gbds = null;
287
288        System.out.println("\nGroebner base distributed hybrid (" + threads + "/" + threadsPerNode + ", "
289                        + mfile + ", " + port + ") ...");
290        t = System.currentTimeMillis();
291        if (plusextra) {
292            // gbds = new GroebnerBaseDistributedHybridEC(mfile, threads,port);
293            gbds = new GroebnerBaseDistributedHybridEC(mfile, threads, threadsPerNode,
294                            new OrderedSyzPairlist(), port);
295        } else {
296            gbd = new GroebnerBaseDistributedHybridEC(mfile, threads, threadsPerNode, port);
297        }
298        t1 = System.currentTimeMillis();
299        if (plusextra) {
300            G = gbds.GB(L);
301        } else {
302            G = gbd.GB(L);
303        }
304        t1 = System.currentTimeMillis() - t1;
305        if (plusextra) {
306            gbds.terminate(); // true
307        } else {
308            gbd.terminate(); // false plus eventually killed by script
309        }
310        t = System.currentTimeMillis() - t;
311        S = new PolynomialList(S.ring, G);
312        System.out.println("G =\n" + S);
313        System.out.println("G.size() = " + G.size());
314        if (plusextra) {
315            System.out.print("d+ ");
316        } else {
317            System.out.print("d ");
318        }
319        System.out.println("= " + threads + ", ppn = " + threadsPerNode + ", time = " + t1 + " milliseconds, "
320                        + (t - t1) + " start-up " + ", total = " + t);
321        checkGB(S);
322        System.out.println("");
323    }
324
325
326    static void runClient(int port) {
327        System.out.println("\nGroebner base distributed client (" + port + ") ...");
328        ExecutableServer es = new ExecutableServer(port);
329        es.init();
330        try {
331            es.join();
332        } catch (InterruptedException e) {
333            // ignored
334        }
335        System.out.println("runClient() done: " + es);
336    }
337
338
339    @SuppressWarnings("unchecked")
340    static void runParallel(PolynomialList S, int threads, boolean plusextra) {
341        List L = S.list;
342        List G;
343        long t;
344        GroebnerBaseAbstract bb = null;
345        GroebnerBaseAbstract bbs = null;
346        if (plusextra) {
347            //bbs = new GroebnerBaseSeqPairParallel(threads);
348            bbs = new GroebnerBaseParallel(threads, new ReductionPar(), new OrderedSyzPairlist());
349        } else {
350            if (S.ring.coFac.isField()) {
351                bb = new GroebnerBaseParallel(threads);
352            } else {
353                bb = new GroebnerBasePseudoParallel(threads, S.ring.coFac);
354            }
355        }
356        System.out.println("\nGroebner base parallel (" + threads + ") ...");
357        t = System.currentTimeMillis();
358        if (plusextra) {
359            G = bbs.GB(L);
360        } else {
361            G = bb.GB(L);
362        }
363        t = System.currentTimeMillis() - t;
364        S = new PolynomialList(S.ring, G);
365        System.out.println("G =\n" + S);
366        System.out.println("G.size() = " + G.size());
367
368        if (plusextra) {
369            System.out.print("p+ ");
370        } else {
371            System.out.print("p ");
372        }
373        System.out.println("= " + threads + ", time = " + t + " milliseconds");
374        if (plusextra) {
375            bbs.terminate();
376        } else {
377            bb.terminate();
378        }
379        checkGB(S);
380        System.out.println("");
381    }
382
383
384    @SuppressWarnings("unchecked")
385    static void runSequential(PolynomialList S, boolean plusextra) {
386        List L = S.list;
387        List G;
388        long t;
389        GroebnerBaseAbstract bb = null;
390        if (plusextra) {
391            //bb = new GroebnerBaseSeqPlusextra();
392            bb = new GroebnerBaseSeq(new ReductionSeq(), new OrderedSyzPairlist());
393        } else {
394            bb = GBFactory.getImplementation(S.ring.coFac); //new GroebnerBaseSeq();
395        }
396        System.out.println("\nGroebner base sequential ...");
397        t = System.currentTimeMillis();
398        G = bb.GB(L);
399        t = System.currentTimeMillis() - t;
400        S = new PolynomialList(S.ring, G);
401        System.out.println("G =\n" + S);
402        System.out.println("G.size() = " + G.size());
403        if (plusextra) {
404            System.out.print("seq+, ");
405        } else {
406            System.out.print("seq, ");
407        }
408        System.out.println("time = " + t + " milliseconds");
409        checkGB(S);
410        System.out.println("");
411    }
412
413
414    @SuppressWarnings("unchecked")
415    static void runGB(PolynomialList S, GroebnerBaseAbstract bb) {
416        List L = S.list;
417        List G;
418        long t;
419        if (bb == null) { // should not happen
420            bb = GBFactory.getImplementation(S.ring.coFac);
421        }
422        String bbs = bb.toString().replaceAll(" ", "");
423        System.out.println("\nGroebner base build=" + bbs + " ...");
424        t = System.currentTimeMillis();
425        G = bb.GB(L);
426        t = System.currentTimeMillis() - t;
427        S = new PolynomialList(S.ring, G);
428        bbs = bb.toString().replaceAll(" ", "");
429        System.out.println("G =\n" + S);
430        System.out.println("G.size() = " + G.size());
431        System.out.print("build=" + bbs + ", ");
432        System.out.println("time = " + t + " milliseconds");
433        checkGB(S);
434        bb.terminate();
435        System.out.println("");
436    }
437
438
439    @SuppressWarnings("unchecked")
440    static void checkGB(PolynomialList S) {
441        if (!doCheck) {
442            return;
443        }
444        GroebnerBaseAbstract bb = GBFactory.getImplementation(S.ring.coFac);
445        long t = System.currentTimeMillis();
446        boolean chk = bb.isGB(S.list, false);
447        t = System.currentTimeMillis() - t;
448        System.out.println("check isGB = " + chk + " in " + t + " milliseconds");
449    }
450
451
452    static int indexOf(String[] args, String s) {
453        for (int i = 0; i < args.length; i++) {
454            if (s.startsWith(args[i])) {
455                return i;
456            }
457        }
458        return -1;
459    }
460
461
462    static String join(String[] args, String d) {
463        StringBuffer sb = new StringBuffer();
464        for (int i = 0; i < args.length; i++) {
465            if (i > 0) {
466                sb.append(d);
467            }
468            sb.append(args[i]);
469        }
470        return sb.toString();
471    }
472
473
474    @SuppressWarnings("resource")
475    static Reader getReader(String filename) {
476        Reader problem = null;
477        Exception fnf = null;
478        try {
479            problem = new InputStreamReader(new FileInputStream(filename), Charset.forName("UTF8"));
480            problem = new BufferedReader(problem);
481        } catch (FileNotFoundException e) {
482            fnf = e;
483        }
484        if (problem != null) {
485            return problem;
486        }
487        String examples = "examples.jar";
488        try {
489            JarFile jf = new JarFile(examples);
490            JarEntry je = jf.getJarEntry(filename);
491            if (je == null) {
492                if (jf != null) {
493                    jf.close();
494                }
495                fnf.printStackTrace();
496                return problem;
497            }
498            problem = new InputStreamReader(jf.getInputStream(je), Charset.forName("UTF8"));
499            problem = new BufferedReader(problem);
500        } catch (FileNotFoundException e) {
501            fnf.printStackTrace();
502            e.printStackTrace();
503        } catch (IOException e) {
504            fnf.printStackTrace();
505            e.printStackTrace();
506            //} finally { not possible, problem must remain open
507            //jf.close();
508        }
509        return problem;
510    }
511
512    
513    @SuppressWarnings("unchecked")
514    static GroebnerBaseAbstract getGBalgo(String[] args, String bstr, GenPolynomialRing ring) {
515        GroebnerBaseAbstract gb = null;
516        int i = bstr.indexOf("=");
517        if (i < 0) {
518            System.out.println("args(build): " + Arrays.toString(args));
519            return gb;
520        }
521        i += 1;
522        String tb = bstr.substring(i);
523        //System.out.println("build=" + tb);
524        GBAlgorithmBuilder ab = GBAlgorithmBuilder.polynomialRing(ring);
525        //System.out.println("ab = " + ab);
526        while (!tb.isEmpty()) {
527            int ii = tb.indexOf(".");
528            String mth;
529            if (ii >= 0) {
530                mth = tb.substring(0, ii);
531                tb = tb.substring(ii + 1);
532            } else {
533                mth = tb;
534                tb = "";
535            }
536            if (mth.startsWith("build")) {
537                continue;
538            }
539            String parm = "";
540            int jj = mth.indexOf("()");
541            if (jj >= 0) {
542                mth = mth.substring(0, jj);
543            } else {
544                jj = mth.indexOf("(");
545                if (jj >= 0) {
546                    parm = mth.substring(jj + 1);
547                    mth = mth.substring(0, jj);
548                    jj = parm.indexOf(")");
549                    parm = parm.substring(0, jj);
550                }
551            }
552            //System.out.println("mth = " + mth + ", parm = " + parm);
553            try {
554                Method method;
555                if (parm.isEmpty()) {
556                    method = ab.getClass().getMethod(mth, (Class<?>[]) null);
557                    ab = (GBAlgorithmBuilder) method.invoke(ab, (Object[]) null);
558                } else {
559                    int tparm = Integer.parseInt(parm);
560                    method = ab.getClass().getMethod(mth, int.class);
561                    ab = (GBAlgorithmBuilder) method.invoke(ab, tparm);
562                }
563            } catch (NoSuchMethodException e) {
564                System.out.println("args(build,method): " + Arrays.toString(args));
565                return gb;
566            } catch (IllegalAccessException e) {
567                System.out.println("args(build,access): " + Arrays.toString(args));
568                return gb;
569            } catch (InvocationTargetException e) {
570                System.out.println("args(build,invocation): " + Arrays.toString(args));
571                return gb;
572            } catch (NumberFormatException e) {
573                System.out.println("args(build,number): " + Arrays.toString(args));
574                return gb;
575            }
576        }
577        gb = ab.build();
578        //System.out.println("gb = " + gb);
579        return gb;
580    }
581
582}