source: git/Singular/LIB/polybori.lib @ 526587

spielwiese
Last change on this file since 526587 was 526587, checked in by Hans Schoenemann <hannes@…>, 8 years ago
fix: URL (requires @texinfo)
  • Property mode set to 100644
File size: 36.1 KB
Line 
1////////////////////////////////////////////////////////////////
2version="version polybori.lib 4.0.0.0 Jun_2013 "; // $Id$
3category="Miscellaneous";
4
5// summary description of the library
6
7info="
8LIBRARY:   polybori.lib A Singular Library Interface for PolyBoRi
9AUTHORS:   Maximilian Kammermeier: Max0791@gmx.de
10           Susanne Scherer: sscherer90@yahoo.de
11
12SEE ALSO:  Libraries, pyobject, User defined types
13
14
15@*
16
17OVERVIEW:  A library for using @code{PolyBoRi} in the SINGULAR interface, with
18procedures that convert structures (polynomials, rings, ideals) in both
19directions. Therefore, it is possible to compute boolean groebner basis
20via @ref{boolean_std}. Polynomials can be converted to zero-supressed decision
21diagrams (zdd) and vice versa.
22
23For usability it defines the @code{PolyBoRi} types @code{bideal}, @code{bpoly},
24and @code{bring} which are equivalent to Singular's @code{ideal}, @code{poly},
25and @code{ring}, as well as @code{bset} which corresponds to the type @code{zdd}
26introduced here. In addition @code{bvar(i)} constructs the Boolean variable corresponding
27to @code{var(i)} from current @code{ring};
28
29For convenience, the corresponding types can be converted explictely or implicitely
30while assigning.
31Also several SINGULAR operators were overloaded: @code{bring} comes with @code{nvars},
32@code{bpoly} implements @code{lead}, @code{leadmonom} and @code{leadcoef}.
33Objects of this type  may be added and multiplied, too.
34Finally, @code{bideal} yields @code{std} and @code{size} as well as addition and element access.
35
36
37Hence, by using these types @code{PolyBoRi} functionality
38can be carried out seamlessly in SINGULAR:
39
40@code{> LIB \"polybori.lib\";} @*
41@code{> ring r0=2,x(1..4),lp;} @*
42@code{> def x=bvar; // enforce Boolean variables} @*
43
44@code{> bpoly f1=x(1)+x(4);} @*
45@code{> bpoly f2=x(1)+x(3)*x(1);} @*
46@code{> bideal bI=list(f1,f2);} @*
47
48@code{> std(bI);} @*
49@code{_[1] = x(1) + x(4)} @*
50@code{_[2] = x(3)*x(4) + x(4)} @*
51
52
53NOTE:
54@texinfo
55 For using this library SINGULAR's @code{python} interface must be available
56 on your system.
57 Please @code{./configure --with-python} when building SINGULAR for this purpose.
58
59 There are prebuilt binary packages for @code{PolyBoRi} available
60 from @uref{http://polybori.sf.net/}.
61
62 For building your own @code{PolyBoRi} please ensure that you have @code{scons} and a
63 development version of the boost libaries installed on you system.
64 Then you may execute the following commands in a @code{bash}-style shell
65 to build @code{PolyBoRi} available to @code{python}:
66
67@code{PBDIR=/path/to/custom/polybori} @*
68@code{wget http://downloads.sf.net/project/polybori/polybori/\\}@*
69@code{0.8.2/polybori-0.8.2.tar.gz} @*
70@code{tar -xvzf polybori-0.8.2.tar.gz} @*
71@code{cd polybori-0.8.2} @*
72@code{scons install PREFIX=$PBDIR PYINSTALLPREFIX=$PBDIR/python} @*
73@code{export PYTHONPATH=$PBDIR/python:$PYTHONPATH} @*
74@end texinfo
75
76REFERENCES:
77@texinfo
78See @uref{http://polybori.sf.net} for details about @code{PolyBoRi}.
79@end texinfo
80
81PROCEDURES:
82  boolean_std(bideal);                            Singular ideal of boolean groebner basis of I
83
84  boolean_poly_ring(ring);                       convert ring
85  boolean_constant(int[, bring]);                convert constant
86  boolean_poly(poly[, int, bring])               convert polynomial
87  direct_boolean_poly(poly[, bring]);            convert polynomial direct
88  recursive_boolean_poly(poly[, bring]);         convert polynomial recursively
89  boolean_ideal(ideal[, bring]);                 convert ideal
90  boolean_set(zdd[, bring]);                     convert zdd
91
92
93  from_boolean_constant(bpoly);                  convert boolean constant
94  from_boolean_poly(bpoly[, int]);               convert boolean polynomial
95  direct_from_boolean_poly(bpoly);               convert boolean polynomial direct
96  recursive_from_boolean_poly(bpoly);            convert boolean polynomial recursively
97  from_boolean_ideal(bpoly);                     convert to ideal
98  from_boolean_set(bset);                        convert to zdd
99
100
101  bvar(i);                                       return i-th Boolean variable
102  poly2zdd(poly);                                return zdd of a given polynomial
103  zdd2poly(zdd);                                 return polynomial representation of a given zdd
104  disp_zdd(zdd);                                 return string with a visualization of a given
105
106KEYWORDS: library, polybori.lib; polybori; polybori.lib; library; pyobject; newstruct; zdd
107
108";
109
110///////////////////////////////////////////////////////////////////////
111// initialization of datatypes and constant structures
112
113static proc mod_init()
114"USAGE: mod_init()
115RETURN: none
116NOTE: load PolyBoRi and introduce the structures zdd and bpoly
117SEE ALSO: boolean_ideal, boolean_std
118KEYWORDS: PolyBoRi, Boolean Groebner Basis
119"
120{
121  if (typeof(Pyobject)!="package")
122  {
123    LIB("pyobject.so");
124  }
125  if (typeof(zdd_one)=="?unknown type?")
126  {
127    python_import("polybori");
128
129 // install new types
130
131    newstruct("zdd","int idx,def thenBranch,def elseBranch");
132    newstruct("bpoly","pyobject boolpoly");
133    newstruct("bideal","pyobject pylist");
134    newstruct("bring", "pyobject pyring");
135    newstruct("bset", "pyobject pyset");
136
137 // install type operations
138
139    system("install", "zdd",      "==",      zdd_check,2);
140    system("install", "bpoly",    "==",      bpoly_check,2);
141    system("install", "bpoly",    "*",       bpoly_mult,2);
142    system("install", "bpoly",    "+",       bpoly_add,2);
143    system("install", "zdd",      "print",   print_zdd, 1);
144    system("install", "bpoly",    "print",   print_bpoly,1);
145    system("install", "bideal",   "print",   print_bideal,1);
146    system("install", "bideal",   "size",    size_bideal,1);
147    system("install", "bpoly",    "lead",     lead_bpoly, 1);
148    system("install", "bpoly",    "leadmonom",lead_monom_bpoly, 1);
149    system("install", "bpoly",    "leadcoef", lead_coef_bpoly, 1);
150    system("install", "bideal",   "[",        op_getitem, 2);
151    system("install", "bideal",   "+",        bideal_add, 2);
152    system("install", "bideal",   "std",      boolean_std, 4);
153
154 // install type conversions
155
156//    implemented typecasts (both directions)
157//    SINGULAR             BOOLEAN OBJECTS
158//    ring                 bring
159//    poly                 bpoly
160//    zdd                  bset
161//    ideal                bideal
162//
163// furthermore, it is possible to switch between poly <-> zdd and bpoly <-> bset
164
165    system("install", "bring",    "=",        ring2bring, 1);
166    system("install", "bring",    "nvars",    nvars_bring, 1);
167
168    system("install", "pyobject", "poly",     from_boolean_poly, 1);
169    system("install", "pyobject", "size",     size_pyobject, 1);
170
171    system("install", "pyobject", "bideal",   pyobject2bideal,1);
172    system("install", "bideal",   "pyobject", bideal2pyobject,1);
173
174    system("install", "bideal",   "ideal",    bideal2ideal, 4);
175    system("install", "bideal",   "=",        type2bideal, 1);
176
177
178
179    system("install", "zdd",      "poly",     zdd2poly, 1);
180    system("install", "zdd",      "=",        poly2zdd, 1);
181
182    system("install", "zdd",      "pyobject", boolean_set, 1);
183    system("install", "pyobject", "zdd",      from_boolean_set, 1);
184
185    system("install", "bset",     "zdd",      bset2zdd, 1);
186    system("install", "zdd",      "bset",     zdd2bset, 1);
187
188    system("install", "bpoly",    "bset",     bpoly2bset, 1);
189    system("install", "bset",     "bpoly",    bset2bpoly, 1);
190
191    system("install", "pyobject", "bpoly",    pyobject2bpoly,1);
192    system("install", "bpoly",    "pyobject", bpoly2pyobject,1);
193
194    system("install", "bpoly",     "poly",    bpoly2poly,1);
195    system("install", "bpoly",     "bideal",  bpoly2bideal,1);
196    system("install", "bpoly",     "=",       poly2bpoly,1);
197
198
199
200 // initialize constant zdds
201
202    zdd zdd_one;
203    zdd_one.idx=0;
204    zdd_one.thenBranch=int(1);
205    zdd_one.elseBranch=int(0);
206    zdd zdd_zero;
207    zdd_zero.idx=0;
208    zdd_zero.thenBranch=int(0);
209    zdd_zero.elseBranch=int(0);
210    export(zdd_one);
211    export(zdd_zero);
212
213    python_run("def if_then_else_idx(idx,b,c): return b.set().change(idx).union(c)");
214    python_run("_SINGULAR_RINGS = dict()");
215    python_run("_SINGULAR_RINGS_ACCESSED = 0");
216    python_run("def _SINGULAR_DECACHE_RING(arg): val = arg(); return 0 if val is None else val");
217  }
218}
219
220///////////////////////////////////////////////////////////////////////
221// computes the leading term of a bpoly
222
223proc lead_bpoly(bpoly pp)
224{
225  pyobject zero=0;
226  bpoly zero2;
227  zero2.boolpoly=zero;
228  if (pp==zero2)
229  {
230    return(0);
231  }
232  else
233  {
234    pyobject ppb=pp.boolpoly."lead"();
235    return(ppb);
236  }
237}
238
239///////////////////////////////////////////////////////////////////////
240// computes the leading monomial of a bpoly
241
242proc lead_monom_bpoly(bpoly pp)
243{
244  if (pp.boolpoly == 0) {  return(0); }
245
246  pyobject ppb=pp.boolpoly."lead"();
247  return(ppb);
248}
249
250///////////////////////////////////////////////////////////////////////
251// computes the leading coefficient of a bpoly
252
253proc lead_coef_bpoly(bpoly pp)
254{
255  if (int(pp.is_zero())) {  return(0); }
256  return(1);
257}
258
259///////////////////////////////////////////////////////////////////////
260// converts a Singular ring into a Boolean ring
261
262proc ring2bring(def r)
263{
264  bring rb;
265  rb.pyring = boolean_poly_ring(r);
266  return(rb);
267}
268///////////////////////////////////////////////////////////////////////
269// Generate an ideal from one constructor
270proc bpoly2bideal(bpoly bp)
271{
272  pyobject obj = list(bp);
273  bideal bI = obj;
274  return (bI);
275}
276
277///////////////////////////////////////////////////////////////////////
278// get number of variables of a Boolean ring
279
280proc nvars_bring(bring rb)
281{
282  return (int(rb.pyring.n_variables()));
283}
284
285///////////////////////////////////////////////////////////////////////
286// get variable of Boolean ring corresponding to current basering
287
288proc bvar(int i)
289"USAGE: bvar(i); int i
290RETURN: i-th variable of Boolean ring corresponding to current basering
291SEE ALSO: boolean_poly_ring, var
292KEYWORDS: PolyBoRi, Boolean Groebner Basis
293EXAMPLE: example bvar; shows an example"
294{
295  bpoly re = var(i);
296  return (re);
297}
298example
299{ "EXAMPLE:"; echo=2;
300  ring r = 2,(x,y,z),Dp;
301  bvar(1); // -> x
302}
303
304///////////////////////////////////////////////////////////////////////
305// Internal functions for caching converted ring
306///////////////////////////////////////////////////////////////////////
307
308
309// Mark cache as accessed and clear garbage every 100 accesses
310static proc bring_mark_cache(list #)
311{
312  if (int(python_eval("_SINGULAR_RINGS_ACCESSED >= 100"))) {
313    python_run("_SINGULAR_RINGS_ACCESSED = 0");
314    def erased = python_eval("[_k for (_k,_v) in _SINGULAR_RINGS.items() if _v() is None]");
315    erased = python_eval("(lambda _keys: [_SINGULAR_RINGS.pop(_k) for _k in _keys])")(erased);
316  }
317  python_run("_SINGULAR_RINGS_ACCESSED += 1");
318}
319
320// look up whether we cached this conversion before
321static proc bring_from_cache(def r)
322{
323  bring_mark_cache();
324  def result1 = python_eval("_SINGULAR_RINGS.get('" + string(r) + "', (lambda: None))");
325  def result = python_eval("_SINGULAR_DECACHE_RING")(result1);
326  return (result);
327}
328
329// insert computed result into cache
330static proc bring_to_cache(def r, pyobject newring)
331{
332  def value = WeakRingRef(newring);
333  python_eval("_SINGULAR_RINGS")."__setitem__"(string(r), value);
334}
335
336///////////////////////////////////////////////////////////////////////
337// converts a Singular ring into a python ring
338
339proc boolean_poly_ring(def r)
340{
341  def cached = bring_from_cache(r);
342  if (int(cached != int(0))) { return (cached); }
343
344  def rl = ringlist(r);
345  list blocks;
346  string ordering;
347  pyobject orders = python_eval("dict(lp=OrderCode.lp)");
348  if (size(rl[3]) >2)
349  {
350    orders.update(python_eval("dict(Dp=OrderCode.block_dlex)"));
351  }
352  else
353  {
354    orders.update(python_eval("dict(Dp=OrderCode.dlex)"));
355  }
356
357  int i;
358  int counter=0;
359  for (i=1; i<=size(ringlist(r)[3]); i++)
360  {
361    if (rl[3][i][1]<>"C")
362    {
363      ordering=rl[3][i][1];
364      if (counter) { blocks = blocks + list(counter) };
365      counter = counter + size(rl[3][i][2]);
366    }
367  }
368  if(int(orders.has_key(ordering)==0))
369  {
370     "// Warning: Unsupported ordering, using 'lp`!";
371  }
372
373  def result = Ring(nvars(r), orders.get(ordering, 0), rl[2], blocks);
374  bring_to_cache(r, result);
375  return (result);
376}
377
378///////////////////////////////////////////////////////////////////////
379// returns ith entry of a bideal
380
381proc op_getitem(bideal arg, def idx)
382{
383  if (typeof(idx) == "int") { return (arg.pylist[idx-1]); }
384
385  bideal re = (python_eval("lambda ll, idx: [ll[i] for i in idx]")(arg.pylist, idx-1));
386  return (re);
387}
388
389///////////////////////////////////////////////////////////////////////
390// concatenate generators of bideals
391
392proc bideal_add(bideal arg1, bideal arg2)
393{
394  pyobject tmp = python_eval("lambda x, y: list(sorted(set(x).union(set(y))))");
395  bideal re = tmp(arg1.pylist,arg2.pylist);
396  return (re);
397}
398
399///////////////////////////////////////////////////////////////////////
400// checks the equality of two bpolys
401
402proc bpoly_check(bpoly pb1,bpoly pb2)
403{
404  return(pb1.boolpoly==pb2.boolpoly);
405}
406
407///////////////////////////////////////////////////////////////////////
408// computes the multiplication of two bpolys
409
410proc bpoly_mult(bpoly pb1,bpoly pb2)
411{
412  bpoly bpol;
413  bpol.boolpoly=pb1.boolpoly*pb2.boolpoly;
414  return(bpol);
415}
416
417///////////////////////////////////////////////////////////////////////
418// computes the addition of two bpolys
419
420proc bpoly_add(bpoly pb1, bpoly pb2)
421{
422  bpoly bpol;
423  bpol.boolpoly=pb1.boolpoly+pb2.boolpoly;
424  return(bpol);
425}
426
427///////////////////////////////////////////////////////////////////////
428// convert bpoly to pyobject
429
430proc bpoly2pyobject(bpoly pb)
431{
432  return(pb.boolpoly);
433}
434
435///////////////////////////////////////////////////////////////////////
436// convert bideal to pyobject
437
438proc bideal2pyobject(bideal Ib)
439{
440  return(Ib.pylist);
441}
442
443///////////////////////////////////////////////////////////////////////
444// convert poly to bpoly
445
446proc poly2bpoly(poly p)
447{
448  bpoly bpol;
449  bpol.boolpoly=boolean_poly(p);
450  return(bpol);
451}
452
453///////////////////////////////////////////////////////////////////////
454// convert zdd to bset
455
456proc zdd2bset(zdd ss)
457{
458  bset bs;
459  bs.pyset=boolean_set(ss);
460  return(bs);
461}
462
463///////////////////////////////////////////////////////////////////////
464// convert bpoly to bset
465
466proc bpoly2bset(bpoly ss)
467{
468  bset bs;
469  bs.pyset=ss.boolpoly.set();
470  return(bs);
471}
472
473///////////////////////////////////////////////////////////////////////
474// convert bset to zdd
475
476proc bset2zdd(bset ss)
477{
478  zdd bs;
479  bs=from_boolean_set(ss.pyset);
480  return(bs);
481}
482
483///////////////////////////////////////////////////////////////////////
484// convert bset to bpoly
485
486proc bset2bpoly(bset ss)
487{
488  bpoly pb;
489  pb.boolpoly=python_eval("Polynomial")(ss.pyset);
490  return(pb);
491}
492
493///////////////////////////////////////////////////////////////////////
494// convert type (ideal or list) to bideal
495
496proc type2bideal(def I)
497{
498  if (typeof(I) == "ideal") { return (boolean_ideal(I)); }
499
500  bideal bid;
501  pyobject pylist;
502
503  if (typeof(I) == "list")
504  {
505    pylist = python_eval("list()");
506    int i; int nlen=size(I); bpoly elt;
507    for (i=1; i <= nlen; i++) {
508      elt = I[i];
509      pylist.append(pyobject(elt));
510    }
511  }
512  else { pylist = I; }
513  bid.pylist = pylist;
514  return (bid);
515}
516
517///////////////////////////////////////////////////////////////////////
518// convert bpoly to poly
519
520proc bpoly2poly(bpoly pb)
521{
522  poly h=poly(pb.boolpoly);
523  return(h);
524}
525
526
527///////////////////////////////////////////////////////////////////////
528// convert bideal to ideal
529
530proc bideal2ideal(bideal Ib)
531{
532  ideal I;
533  I=from_boolean_ideal(Ib);
534  return(I);
535}
536
537///////////////////////////////////////////////////////////////////////
538// convert pyobject to bpoly
539
540proc pyobject2bpoly(pyobject pb)
541{
542  bpoly bpol;
543  bpol.boolpoly=pb;
544  return(bpol);
545}
546
547///////////////////////////////////////////////////////////////////////
548// convert pyobject to bideal
549
550proc pyobject2bideal(pyobject Ib)
551{
552  bideal bid;
553  bid.pylist=Ib;
554  return(bid);
555}
556
557///////////////////////////////////////////////////////////////////////
558// print bpoly
559
560proc print_bpoly(bpoly pb)
561{
562  pb.boolpoly;
563}
564
565///////////////////////////////////////////////////////////////////////
566// print bideal
567
568proc print_bideal(bideal Ib)
569{
570  int nlen = size(Ib);
571  for (int i = 1; i <= nlen; i++)
572  {
573    "_[" + string(i)+"] = " + string(Ib[i]);
574  }
575}
576
577///////////////////////////////////////////////////////////////////////
578// get size of pyobject
579
580proc size_pyobject(pyobject obj)
581{
582  return (int(python_eval("len")(obj)));
583}
584
585///////////////////////////////////////////////////////////////////////
586// get size of bideal
587
588proc size_bideal(bideal Ib)
589{
590  return (size(Ib.pylist));
591}
592
593
594///////////////////////////////////////////////////////////////////////
595// print zdd
596
597proc print_zdd(zdd ss)
598{
599  "zdd: ";
600  disp_zdd(ss);
601}
602
603///////////////////////////////////////////////////////////////////////
604// check equality
605
606proc zdd_check(zdd zdd1,zdd zdd2)
607"USAGE: zdd_check(zdd1,zdd2); zdd zdd1, zdd zdd2
608RETURN: 0 or 1 "
609{
610  if (zdd1.idx != zdd2.idx) { return (int(0)); }
611
612  if (zdd1.idx == 0) {  return (int(zdd1.thenBranch == zdd2.thenBranch)); }
613
614  return (zdd_check(zdd1.thenBranch,zdd2.thenBranch)*zdd_check(zdd1.elseBranch,zdd2.elseBranch));
615}
616
617///////////////////////////////////////////////////////////////////////
618
619proc boolean_set(zdd ss,list #)
620"USAGE: boolean_set(ss[, rb]); ss zdd, rb boolean ring
621RETURN: default: boolean set ss in the representation of a Polybori boolean set
622in the ring rb==boolean_poly_ring(basering); optional input: boolean ring rb
623SEE ALSO: boolean_ideal, boolean_std
624KEYWORDS: PolyBoRi, Boolean Groebner Basis
625EXAMPLE: example boolean_set; shows an example"
626{
627  pyobject rb;
628  rb=check_additional_ring(#);
629  pyobject newthen,newelse,unbek,outp;
630  if (ss.idx==0)
631  {
632    if (zdd_check(ss,zdd_one)==1) { return (boolean_constant(1,rb)); }
633    return (boolean_constant(0,rb));
634  }
635  newthen=(boolean_set(ss.thenBranch,rb));
636  newelse=(boolean_set(ss.elseBranch,rb));
637  outp=if_then_else_idx(ss.idx-1,newthen,newelse);
638  return (outp);
639}
640
641example
642{ "EXAMPLE:"; echo=2;
643  ring rs=0,(x,y,z),Dp;
644  poly ps=(x+1)*(y+1)*(z+1);
645  zdd fz=ps;
646  boolean_set(fz);
647
648  poly g=x*y*z+1;
649  zdd gz=g;
650  boolean_set(gz);
651
652  ring R=0,(x(1..4)),Dp;
653  def Rb=boolean_poly_ring(R);
654  poly h=(x(1)+1)*(x(2)+1)*(x(3)+1)*(x(4)+1);
655  zdd hz=h;
656  boolean_set(hz);
657}
658
659///////////////////////////////////////////////////////////////////////
660
661proc from_boolean_set(def s)
662"USAGE: from_boolean_set(sb); sb boolean set
663RETURN: Boolean set sb in the representation of a zdd
664SEE ALSO: boolean_ideal, boolean_std
665KEYWORDS: PolyBoRi, Boolean Groebner Basis
666EXAMPLE: example from_boolean_set; shows an example"
667{
668  bpoly bp = s;
669  pyobject sb = bp;
670  def rb=boolean_poly_ring(basering);
671  zdd result;
672  def nav=sb.navigation();
673  int ind=int(nav.value());
674  def navout_then=nav.then_branch();
675  def navout_else=nav.else_branch();
676  def pb=Polynomial(sb);
677
678  if (int(nav.constant()))
679  {
680    if (pb==1) { return(zdd_one); }
681    return(zdd_zero);
682  }
683
684  result.idx=ind+1;
685  pyobject one=1;
686  def substpoly=one*rb.variable(ind);
687
688  if (int(navout_then.constant()))
689  {
690      result.thenBranch=zdd_one;
691  }
692  else
693  {
694    result.thenBranch=from_boolean_set(BooleSet(navout_then,rb));
695  }
696  if (int(navout_else.constant()))
697  {
698    if (subst(from_boolean_poly(pb),from_boolean_poly(substpoly),0)==1)
699    {
700      result.elseBranch=zdd_one;
701    }
702    else
703    {
704      result.elseBranch=zdd_zero;
705    }
706  }
707  else
708  {
709    result.elseBranch=from_boolean_set(BooleSet(navout_else,rb));
710  }
711  return(result);
712}
713
714example
715{ "EXAMPLE:"; echo=2;
716  ring r=0,(x,y,z),Dp;
717  poly f=(x+1)*(y+1)*(z+1);
718  bpoly fb=f;
719  bset fs=fb;
720  from_boolean_set(fs);
721
722  poly g=x*y*z+1;
723  bpoly gb=g;
724  bset gs=gb;
725  from_boolean_set(gs);
726
727  ring R=0,(x(1..4)),Dp;
728  poly h=(x(1)+1)*(x(2)+1)*(x(3)+1)*(x(4)+1);
729  pyobject hb=boolean_poly(h);
730  def hs=hb.set();
731  from_boolean_set(hs);
732}
733
734//////////////////////////////////////////////////////////////////////
735
736proc direct_from_boolean_poly(def p)
737"USAGE:   from_boolean_poly(pb); pb boolean polynomial
738RETURN:   polynomial in Singular
739SEE ALSO: from_boolean_ideal, boolean_ideal, boolean_poly, boolean_poly_ring,
740boolean_std
741KEYWORDS: PolyBoRi, Boolean Groebner Basis
742EXAMPLE:  example from_boolean_poly; shows an example"
743{
744  pyobject pb = p;
745  poly result = 0;
746  def terms = python_eval("list")(pb.terms());
747  int nlen = size(terms);
748  for (int i = 0; i < nlen; i++)
749  {
750    result=from_boolean_poly_update(result,terms[i]);
751  }
752  return (result);
753}
754
755example
756{ "EXAMPLE:"; echo=2;
757  ring r=0,(x,y,z),Dp;
758  pyobject rb=boolean_poly_ring(r);
759  poly f=x^2+2*y^3+3*z^3;
760  bpoly pp=f;
761  direct_from_boolean_poly(pp);
762
763  poly g=0;
764  bpoly pp=g;
765  direct_from_boolean_poly(pp);
766}
767
768///////////////////////////////////////////////////////////////////////
769// one iteration in direct_from_boolean_poly
770
771static proc from_boolean_poly_update(poly ps, pyobject pb)
772"USAGE: from_boolean_poly_update(ps,pb); ps polynomial, pb boolean polynomial,
773RETURN: update of the Singular polynomial in from_boolean_poly in one iteration
774SEE ALSO: from_boolean_poly
775{
776  pyobject current = pb."variables"();
777  pyobject vars = python_eval("list")(current);
778  int j, index;
779  poly term = 1;
780  pyobject currentvar;
781  int tlen = size(vars);
782  for (j = 0; j < tlen; j++)
783  {
784    currentvar = vars[j];
785    index = int(currentvar.index());
786    term = term * var(index+1);
787  }
788  return(ps + term);
789}
790
791///////////////////////////////////////////////////////////////////////
792// return 1, iff int is 1 modulo 2 and 0 else
793
794static proc coeff_check(int const)
795"USAGE: coeff_check(const); const int
796RETURN: 1 iff the coefficient equals 1 modulo 2 and 0 else
797NOTE: helps to handle leading coefficients of rings in arbitrary characteristic
798SEE ALSO: recursive_boolean_poly, boolean_poly
799KEYWORDS: PolyBoRi, Boolean Groebner Basis
800EXAMPLE: example coeff_check; shows an example"
801{
802  if (char(basering)==2) { return (const); }
803
804  return ((const%2)*(const%2));
805}
806example
807{ "EXAMPLE:"; echo = 2;
808  ring R1=5,x(1..4),lp;
809  poly f=3*x(1)+x(2)^2;
810  coeff_check(int(leadcoef(f)));
811}
812
813///////////////////////////////////////////////////////////////////////
814
815static proc check_additional_ring(list #)
816"USAGE: check_additional_ring(#);
817NOTE: Help function to check whether an additional ring exists and if it is a
818bring or a ring in python."
819{
820  pyobject rb;
821  bring rbhelp;
822  if (size(#)==0)
823  {
824    rb=boolean_poly_ring(basering);
825  }
826  else
827  {
828    if (typeof(#[1])=="bring")
829    {
830      rbhelp=#[1];
831      rb=rbhelp.pyring;
832    }
833    else
834    {
835      rb=#[1];
836    }
837  }
838  return(rb);
839}
840///////////////////////////////////////////////////////////////////////
841
842proc boolean_constant(int const, list #)
843"USAGE: boolean_constant(const[, rb]); const constant and rb boolean ring
844RETURN: default: constant const in the representation of the boolean ring
845rb==boolean_poly_ring(basering); optional input: rb=boolean ring rb
846SEE ALSO: boolean_ideal, boolean_std
847KEYWORDS: PolyBoRi, Boolean Groebner Basis
848EXAMPLE: example boolean_constant; shows an example"
849{
850  pyobject rb = check_additional_ring(#);
851  if (coeff_check(const)==0) { return (rb.zero()); }
852
853  return (rb.one());
854}
855
856example
857{ "EXAMPLE:"; echo = 2;
858  ring r=7,(x,y),Dp;
859  pyobject rb=boolean_poly_ring(r);
860  boolean_constant(int(3));
861  typeof(boolean_constant(int(3)));
862  boolean_constant(int(0));
863  typeof(boolean_constant(int(0)));
864}
865
866///////////////////////////////////////////////////////////////////////
867
868proc boolean_poly(poly ps, list #)
869"USAGE: boolean_poly(ps[, dir, rb]); ps polynomial, dir integer zero or one, rb
870boolean ring
871RETURN: default: polynomial ps in the representation of the boolean ring
872rb==boolean_poly_ring(basering); optional input: boolean ring rb
873NOTE: via the optional input dir, one can choose the computation method (either
874direct[dir==0] or recursive[dir==1]). default: recursive
875SEE ALSO: boolean_ideal, boolean_std
876KEYWORDS: PolyBoRi, Boolean Groebner Basis
877EXAMPLE: example boolean_poly; shows an example"
878{
879  if (size(#)==0)
880  {
881    return(recursive_boolean_poly(ps));
882  }
883  if (size(#)==1)
884  {
885    if (typeof(#[1])=="int")
886    {
887      if (#[1]==0) { return(direct_boolean_poly(ps)); }
888
889      return(recursive_boolean_poly(ps));
890    }
891    return(direct_boolean_poly(ps,#[1]));
892  }
893  if (#[1]==0) { return(direct_boolean_poly(ps,#[2])); }
894
895  return(recursive_boolean_poly(ps,#[2]));
896}
897example
898{ "EXAMPLE:"; echo = 2;
899  ring r=0,x(1..5),Dp;
900  poly f=x(2)*(x(3)-x(1))+x(4)*x(5);
901  bring rb=r;
902  boolean_poly(f);
903  boolean_poly(f,0);
904  boolean_poly(f,0,boolean_poly_ring(r));
905  boolean_poly(f,0,rb);
906
907
908  poly g=0;
909  boolean_poly(g);
910
911  poly g=1;
912  boolean_poly(g);
913}
914
915///////////////////////////////////////////////////////////////////////
916
917proc from_boolean_poly(def p, list #)
918"USAGE: from_boolean_poly(ps[, dir]); ps polynomial, dir integer zero or one
919RETURN: default: polynomial ps in the representation of the boolean ring
920NOTE: via the optional input dir, one can choose the computation method (either
921direct[dir==0] or recursive[dir==1]). default: direct
922SEE ALSO: boolean_ideal, boolean_std
923KEYWORDS: PolyBoRi, Boolean Groebner Basis
924EXAMPLE: example from_boolean_poly; shows an example"
925{
926  pyobject pb = pyobject(p);
927
928  if (size(#)==0) { return(direct_from_boolean_poly(pb)); }
929  if (#[1]==0) { return(direct_from_boolean_poly(pb)); }
930
931  return(recursive_from_boolean_poly(pb));
932}
933
934example
935{ "EXAMPLE:"; echo = 2;
936  ring r=0,(x,y,z),Dp;
937  def rb=boolean_poly_ring(r);
938  poly f=x^2+2*y+5*z^4;
939  bpoly pp=f;
940  from_boolean_poly(pp);
941  from_boolean_poly(pp,1);
942
943  ring r2=5,(x,y,z),Dp;
944  def rb2=boolean_poly_ring(r2);
945  poly f2=x+y+z;
946  bpoly pp2=f2;
947  from_boolean_poly(pp);
948  from_boolean_poly(pp,1);
949}
950
951///////////////////////////////////////////////////////////////////////
952
953proc direct_boolean_poly(poly ps, list #)
954"USAGE: boolean_poly(ps[, rb]); ps polynomial, rb boolean ring
955RETURN: default: polynomial ps in the representation of the boolean ring
956rb==boolean_poly_ring(basering); optional input: boolean ring rb
957SEE ALSO: boolean_ideal, boolean_std
958KEYWORDS: PolyBoRi, Boolean Groebner Basis
959EXAMPLE: example boolean_poly; shows an example"
960{
961  pyobject resultbool,rb;
962  rb=check_additional_ring(#);
963
964  int nmax= size(ps);
965  resultbool = Polynomial(rb.zero());
966  for (int i = 1; i <= nmax; i++)
967  {
968    if ( coeff_check(int(leadcoef(ps[i]))) == 1 )
969    {
970      resultbool=boolean_poly_update(resultbool,ps[i],rb);
971    }
972  }
973  return (resultbool);
974}
975
976example
977{ "EXAMPLE:"; echo = 2;
978  ring r0=2,x(1..4),lp;
979  bring rb=r0;
980  poly f=x(1)^2+2*x(2)*(x(3))-x(4)^3;
981  direct_boolean_poly(f);
982  direct_boolean_poly(f,rb);
983
984  ring r1=0,x,Dp;
985  poly f=x3+2x+1;
986  direct_boolean_poly(f);
987
988  ring r2=32003,(x,y,z),Dp;
989  poly f=xyz+20*x^2*y-3*xz+15;
990  direct_boolean_poly(f);
991}
992
993///////////////////////////////////////////////////////////////////////
994// one iteration in direct_boolean_poly
995
996static proc boolean_poly_update(def pb, poly ps, pyobject rb)
997"USAGE: boolean_poly_update(pb,ps,rb); pb boolean polynomial, ps polynomial,
998rb boolean ring
999RETURN: update of the boolean polynomial in boolean_poly in one iteration
1000SEE ALSO: boolean_poly
1001{
1002  intvec current = leadexp(ps);
1003  int j;
1004  pyobject term, var_rb;
1005  term = python_eval("Monomial")(rb);
1006  for (j = 1; j <= size(current); j=j+1)
1007  {
1008    var_rb = rb.variable(j-1);
1009    if (current[j] > 0) { term = term * var_rb; }
1010  }
1011  return (pb + term);
1012}
1013
1014///////////////////////////////////////////////////////////////////////
1015
1016proc recursive_boolean_poly(poly ps, list #)
1017"USAGE: boolean_poly(ps[, rb]); ps polynomial, rb boolean ring
1018RETURN: default: polynomial ps in the representation of the boolean ring
1019rb==boolean_poly_ring(basering); optional input: rb boolean ring
1020SEE ALSO: boolean_ideal, boolean_std
1021KEYWORDS: PolyBoRi, Boolean Groebner Basis
1022EXAMPLE: example recursive_boolean_poly; shows an example"
1023{
1024  pyobject rb;
1025  if (size(#)==0)
1026  {
1027    #[1]=boolean_poly_ring(basering);
1028    #[2]=0;
1029  }
1030  if (size(#)==1)
1031  {
1032    #[2]=0;
1033  }
1034  rb=check_additional_ring(#[1]);
1035  if (#[2]==int(rb.n_variables()))
1036  {
1037    return (boolean_constant(int(leadcoef(ps)),rb));
1038  }
1039  else
1040  {
1041    def xsu=var(#[2]+1);
1042    poly p0=subst(ps,xsu,0);
1043    poly p1=subst(ps-p0,xsu,1);
1044    def ahelp=recursive_boolean_poly(p1,rb,#[2]+1);
1045    def bhelp=recursive_boolean_poly(p0,rb,#[2]+1);
1046    return (rb.variable(#[2])*ahelp+bhelp);
1047  }
1048}
1049
1050example
1051{ "EXAMPLE:"; echo = 2;
1052  ring r0=2,x(1..4),lp;
1053  poly f=x(1)^2+2*x(2)*(x(3))-x(4)^3;
1054  recursive_boolean_poly(f);
1055
1056  ring r1=0,x,Dp;
1057  poly f=x3+2x+1;
1058  recursive_boolean_poly(f);
1059
1060  ring r2=32003,(x,y,z),Dp;
1061  def br2=boolean_poly_ring(r2);
1062  bring bbr2=r2;
1063  poly f=xyz+20*x^2*y-3*xz+15;
1064  recursive_boolean_poly(f,br2);
1065  recursive_boolean_poly(f,bbr2);
1066}
1067
1068///////////////////////////////////////////////////////////////////////
1069
1070proc boolean_ideal(ideal Is, list #)
1071"USAGE: boolean_ideal(Is[, rb]); Is Ideal, rb boolean ring
1072RETURN: default: ideal Is in the representation of the boolean ring
1073rb==boolean_poly_ring(basering); optional input: rb boolean ring
1074SEE ALSO: boolean_std
1075KEYWORDS: PolyBoRi, Boolean Groebner Basis
1076EXAMPLE: example boolean_ideal; shows an example"
1077{
1078  pyobject rb;
1079  rb=check_additional_ring(#);
1080  int len=size(Is);
1081  pyobject Ib = python_eval("list()");
1082  for (int i=1; i<=len; i++)
1083  {
1084    Ib.append(boolean_poly(Is[i],rb));
1085  }
1086  bideal re;
1087  re.pylist = Ib;
1088
1089  return(re);
1090}
1091
1092example
1093{ "EXAMPLE:"; echo = 2;
1094  ring r0=2,x(1..4),lp;
1095  poly f1=x(1)^2+2*x(2)*(x(3))-x(4)^3;
1096  poly f2=x(1)^2-x(3)*x(1);
1097  poly f3=x(2)+5-2*x(1);
1098  poly f4=x(1)*x(2)-x(3);
1099  ideal I=f1,f2,f3,f4;
1100  boolean_ideal(I);
1101
1102  ring r1=0,x,Dp;
1103  poly f1=x3+2*x+1;
1104  poly f2=x10-x5+2x;
1105  poly f3=19;
1106  ideal I=f1,f2,f3;
1107  boolean_ideal(I);
1108
1109  ring r2=32003,(x,y,z),Dp;
1110  bring bbr2=r2;
1111  poly f1=xyz+20*x^2*y-3*xz+15;
1112  poly f2=32002*xy+z2;
1113  poly f3=19;
1114  ideal I=f1,f2,f3;
1115  boolean_ideal(I);
1116  boolean_ideal(I,bbr2);
1117}
1118
1119////////////////////////////////////////////////////////////////
1120
1121proc from_boolean_ideal(bideal I)
1122"USAGE: from_boolean_ideal(I); I boolean ideal
1123RETURN: ideal in Singular
1124SEE ALSO: from_boolean_poly, boolean_ideal, boolean_poly, boolean_std,
1125boolean_poly_ring
1126KEYWORDS: PolyBoRi, Boolean Groebner Basis
1127EXAMPLE: example from_boolean_ideal; shows an example"
1128{
1129  ideal re;
1130  int i;
1131  int nlen = size(I);
1132  for (i = 1; i <= nlen; i++)
1133  {
1134    re[i] = from_boolean_poly(I[i]);
1135  }
1136  return (re);
1137}
1138
1139example
1140{ "EXAMPLE:"; echo=2;
1141  ring rs=0,(x,y,z),Dp;
1142  def rb3=boolean_poly_ring(rs);
1143  poly f1=x+y;
1144  poly f2=x+z;
1145  bpoly pp =f1;
1146  bpoly p = f2;
1147  bideal Ib;
1148  list K=(p,pp);
1149  Ib=K;
1150  from_boolean_ideal(Ib);
1151
1152  ring rs2=5,(x,y,z),Dp;
1153  def rb4=boolean_poly_ring(rs2);
1154  poly p1=x+y;
1155  poly p2=x+z;
1156  poly p3=y+z;
1157  bpoly p = p1;
1158  bpoly pp = p2;
1159  bpoly ppp = p3;
1160  bideal Ib;
1161  list K=(p,pp,ppp);
1162  Ib=K;
1163  from_boolean_ideal(Ib);
1164}
1165
1166///////////////////////////////////////////////////////////////////////
1167
1168proc boolean_std(bideal Is)
1169"USAGE: boolean_std(Is); Is ideal
1170RETURN: Singular ideal of the boolean groebner basis of Is
1171SEE ALSO: from_boolean_poly, boolean_ideal, boolean_poly, from_boolean_ideal,
1172boolean_poly_ring
1173KEYWORDS: PolyBoRi, Boolean Groebner Basis
1174EXAMPLE: example boolean_std; shows an example"
1175{
1176  pyobject Ib = Is;
1177
1178  def redIb=groebner_basis(Ib);
1179  bideal result = redIb;
1180  return(result);
1181}
1182
1183example
1184{ "EXAMPLE:"; echo = 2;
1185  ring r0=2,x(1..4),lp;
1186  poly f1=x(1)^2+2*x(2)*(x(3))-x(4)^3;
1187  poly f2=x(1)^2-x(3)*x(1);
1188  poly f3=x(2)+5-2*x(1);
1189  poly f4=x(1)*x(2)-x(3);
1190  ideal I=f1,f2,f3,f4;
1191
1192  boolean_std(I);        // implicitely add x(i)^2-x(i)
1193
1194  bideal bI=I;           // alternative syntax
1195  bideal re = std(bI);  // Continue PolyBoRi computations
1196  std(re[1..2]);
1197
1198  ring r1=0,x,Dp;
1199  poly f1=x3+2*x+1;
1200  poly f2=x10-x5+2x;
1201  poly f3=19;
1202  ideal I=f1,f2,f3;
1203  boolean_std(I);
1204
1205  ring r2=32003,(x,y,z),Dp;
1206  poly f1=xz+y+20*x^2*y;
1207  poly f2=32002*xy+xz2+y;
1208  ideal I=f1,f2;
1209  boolean_std(I);
1210
1211  ring r2=32003,(x,y,z),Dp;
1212  poly f1=xyz+20*x^2*y-3*xz+15;
1213  poly f2=32002*xy+z2;
1214  poly f3=19*x5y;
1215  ideal I=f1,f2,f3;
1216  boolean_std(I);
1217}
1218
1219/////////////////////////////////////////////////////////////////////////
1220
1221proc from_boolean_constant(def p)
1222"USAGE: from_boolean_constant(pb); pb pyobject
1223RETURN: constant polynomial
1224SEE ALSO: boolean_ideal, boolean_std
1225KEYWORDS: PolyBoRi, Boolean Groebner Basis
1226EXAMPLE: example from_boolean_constant; shows an example"
1227{
1228  pyobject pb = p;
1229  if (pb==0) { return (poly(0)); }
1230
1231  return (poly(1));
1232}
1233
1234example
1235{ "EXAMPLE:"; echo = 2;
1236  ring rs=0,(x,y,z),Dp;
1237  def rsb=boolean_poly_ring(rs);
1238  poly f=(x+y)*x+z;
1239  bpoly pp=f;
1240  from_boolean_constant(0);
1241  from_boolean_constant(1);
1242  from_boolean_constant(pp);
1243}
1244
1245///////////////////////////////////////////////////////////////////////
1246
1247proc recursive_from_boolean_poly(def p)
1248"USAGE: recursive_from_boolean_poly(pb); pb boolean polynomial
1249RETURN: polynomial in Singular
1250SEE ALSO: from_boolean_poly, boolean_ideal, boolean_poly, from_boolean_ideal,
1251boolean_poly_ring
1252KEYWORDS: PolyBoRi, Boolean Groebner Basis
1253EXAMPLE: example recursive_from_boolean_poly; shows an example"
1254{
1255  pyobject pb = p;
1256
1257  if (pb==0) { return(0); }
1258  if (pb==1) { return(1); }
1259
1260  int idx = int(pb.navigation().value());
1261  def p0=Polynomial(pb.set().subset0(idx));
1262  def p1 = Polynomial(pb.set().subset1(idx));
1263
1264  return (var(idx+1)*recursive_from_boolean_poly(p1)+recursive_from_boolean_poly(p0));
1265}
1266
1267example
1268{ "EXAMPLE:"; echo = 2;
1269  ring rs=0,(x,y,z),Dp;
1270  def rsb=boolean_poly_ring(rs);
1271  poly f=(x+y)*x+z;
1272  bpoly pp=f;
1273  recursive_from_boolean_poly(pp);
1274
1275  ring rs2=2,(x,y,z),Dp;
1276  def rsb2=boolean_poly_ring(rs2);
1277  poly f2=(x+y)*x+x;
1278  bpoly pp2=f2;
1279  recursive_from_boolean_poly(pp);
1280}
1281
1282/////////////////////////////////////////////////////////////////////////
1283
1284proc poly2zdd(poly ps)
1285"USAGE: poly2zdd(poly ps); polynomial ps
1286RETURN: polynomial ps in zdd representation
1287SEE ALSO: boolean_poly, from_boolean_set
1288KEYWORDS: PolyBoRi, zero-supressed decision diagram
1289EXAMPLE: example poly2zdd; shows an example"
1290{
1291  pyobject pp=boolean_poly(ps);
1292  pyobject pset = pp.set();
1293  zdd result = from_boolean_set(pset);
1294  return(result);
1295}
1296
1297example
1298{ "EXAMPLE:"; echo = 2;
1299  ring r=0,x(1..5),Dp;
1300  poly f=(x(1)+1)*(x(2)+1)*(x(3)+1)*x(4)*x(5);
1301  poly2zdd(f);
1302
1303  poly g=x(3);
1304  poly2zdd(g);
1305}
1306
1307/////////////////////////////////////////////////////////////////////////
1308
1309proc zdd2poly(zdd ss)
1310"USAGE: zdd2poly(ss); zero-supressed decision diagram ss
1311RETURN: zdd ss in polynomial representation
1312SEE ALSO:from_boolean_poly, boolean_set
1313KEYWORDS: PolyBoRi, Boolean Groebner Basis
1314EXAMPLE: example poly2zdd; shows an example"
1315{
1316  def ps=boolean_set(ss);
1317  return(from_boolean_poly(Polynomial(ps)));
1318}
1319
1320example
1321{ "EXAMPLE:"; echo = 2;
1322  ring r=0,x(1..5),Dp;
1323  poly f=(x(1)+1)*(x(2)+1)*(x(3)+1)*x(4)*x(5);
1324  zdd2poly(poly2zdd(f));
1325
1326  poly g=x(3);
1327  zdd2poly(poly2zdd(g));
1328
1329  poly g=0;
1330  zdd2poly(poly2zdd(0));
1331
1332  poly g=1;
1333  zdd2poly(poly2zdd(01));
1334}
1335
1336/////////////////////////////////////////////////////////////////////////
1337
1338proc disp_zdd(zdd ss, list #)
1339"USAGE: disp_zdd(ss); zero-supressed decision diagram ss
1340RETURN: string containing visualization of ss
1341NOTE: the resulting string is the visualization of the polynomial that corresponds
1342to ss, but with a additional structure that comes from the zdd. Every reached else-
1343Branch induces a new line in the string.
1344SEE ALSO:zdd2poly, poly2zdd
1345KEYWORDS: Polybori, Boolean Groebner Basis
1346EXAMPLE: example disp_zdd; shows an example"
1347{
1348  int dist,i;
1349  string str,space;
1350  if (size(#)==0)
1351  {
1352    dist=1;
1353    str=" ";
1354  }
1355  else
1356  {
1357    dist=#[1];
1358    str=#[2];
1359  }
1360  for (i=1;i<=dist+3;i++)
1361  {
1362    space=space+" ";
1363  }
1364  if (ss.idx==0)
1365  {
1366    if (size(space)>5)
1367    {
1368      return(str);
1369    }
1370    else
1371    {
1372      if (ss==zdd_one)
1373      {
1374        return (1);
1375      }
1376      else
1377      {
1378      return (0);
1379      }
1380    }
1381  }
1382  else
1383  {
1384    str=str,"x",string(ss.idx);
1385    if (ss.thenBranch.idx!=0)
1386    {
1387      str=str,"(";
1388      str=disp_zdd(ss.thenBranch,dist+3,str);
1389      str=str,")";
1390    }
1391    if ((ss.elseBranch.idx!=0)||(ss.elseBranch==zdd_one))
1392    {
1393      if (ss.elseBranch==zdd_one)
1394      {
1395        str=str+"+1";
1396      }
1397      else
1398      {
1399        str=str,"+"+newline+space;
1400        str=disp_zdd(ss.elseBranch,dist+3,str);
1401      }
1402    }
1403    return(str);
1404  }
1405}
1406
1407example
1408{ "EXAMPLE:"; echo = 2;
1409  ring r1=0,(x,y,z),Dp;
1410  poly f1=xyz+xy+xz+yz+y+z+x+1;
1411  zdd s1=f1;
1412  disp_zdd(s1);
1413
1414  ring r2=0,x(1..6),Dp;
1415  poly f2=x(1)+x(2)+x(3)+x(5)^2+x(6);
1416  zdd s2=f2;
1417  disp_zdd(s2);
1418
1419  ring r4=0,x(1..6),Dp;
1420  poly f2=x(1)+1;
1421  zdd s2=f2;
1422  disp_zdd(s2);
1423
1424  ring r2=0,x(1..6),Dp;
1425  poly f2=x(1)*x(2)*(x(3)-x(5)^2*x(6))+3*x(4)*x(5)-3;
1426  zdd s2=f2;
1427  disp_zdd(s2);
1428
1429  poly f4=0;
1430  zdd s4=f4;
1431  disp_zdd(s4);
1432
1433  poly f5=1;
1434  zdd s5=f5;
1435  disp_zdd(s5);
1436}
Note: See TracBrowser for help on using the repository browser.