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