OSDN Git Service

7aa349a0ada038979bd24fa001a4767aa9ea9902
[nysol/mining.git] / zdd / lib / zdd_so_cxx_org
1 //lcmのruby拡張
2 #include <ruby.h>
3 #include <fstream>
4 #include <memory>
5 //Vsop_Rubyクラス
6 #include"CtoI.h"
7
8 extern int CtoI_Lcm1_ub(char *, char *, int, int, int); // by ham
9
10 // ruby 1.8.5以下対応
11 #ifndef RSTRING_PTR
12         #define RSTRING_PTR(s) (RSTRING(s)->ptr)
13 #endif
14 #ifndef RARRAY_PTR
15         #define RARRAY_PTR(s) (RARRAY(s)->ptr)
16 #endif
17
18
19
20
21 CtoI* string2ctoi(char *str);
22 CtoI* int2ctoi(int val);
23 CtoI *value2ctoi(VALUE v);
24 //------------------------------------------------------------------------------
25 // 配列型に拡張したauto_ptr
26 //------------------------------------------------------------------------------
27 template<class T>
28 class kgAutoPtr2 {
29   T* _ptr;
30
31 public:
32   kgAutoPtr2(T* ptr=0) : _ptr(ptr) {};
33   virtual ~kgAutoPtr2(void) { if(_ptr != NULL) delete[] _ptr; }
34   T* get(void) const throw() { return _ptr; }
35   void set(T* ptr) throw() { if(_ptr!=NULL) delete[] _ptr; _ptr=ptr; }
36   void clear(void) { if(_ptr!=NULL) delete[] _ptr; _ptr=0;}
37 };
38
39
40 class Vsop_Ruby{
41 public:
42         CtoI *cmod;     
43         ~Vsop_Ruby(void){
44                 if(cmod!=0) delete cmod;
45         }       
46 };
47 void free_rmod(Vsop_Ruby* rmod){
48         if(rmod!=0){
49                 delete rmod;
50         }
51 }
52 //初期化カウント
53 int init_cnt=0;
54 //ノード数
55 #define DEF_ENV_NMAX 400000000
56 int env_nmax=0;
57 bool env_warning = false;
58
59 #include "setfunc.cpp"
60
61
62 #define MAX_LEN 409600
63
64 extern "C"{
65         void Init_zdd_so();
66 }
67 #define HASH_MAX 409600
68 int     yylineno=1;
69 static int hashcnt;
70 static int Depth;
71 static int* S_Var;
72 static int PFflag;
73
74 static int Depth_e;
75 static int* S_Var_e;
76
77 static int Depth_item;
78 static int* S_Var_item;
79
80 static int* S_Var_ary;
81
82
83 static int PutNum(CtoI a, int base,ofstream &fs)
84 {
85         if(a.TopItem() > 0) a = a.MaxVal();
86         int d = a.TopDigit() / 3 + 14;
87         kgAutoPtr2<char> a_ptr;
88         char *s;
89         try{
90                 a_ptr.set(new char[d]);
91                 s = a_ptr.get();
92         }catch(...){
93                 rb_raise(rb_eRuntimeError,"memory allocation error");
94         }
95         int err;
96         if(base == 16) err = a.StrNum16(s);
97         else err = a.StrNum10(s);
98         if(err == 1)            return 1;
99         fs << s<< ",";
100
101         return 0;
102 }
103
104 static int PF(CtoI a, int base,ofstream &fs)
105 {
106         if(a.IsConst())
107         {
108                 if(PFflag == 1){fs << endl;}
109                 if(a.TopDigit() & 1) {fs << "-" ; a = -a; }
110                 
111                 PFflag = 1;
112                 int c1 = (a != 1);
113                 if(c1 || Depth == 0)
114                 {
115                         if(PutNum(a, base,fs) == 1) return 1;
116                 }
117                 else if(!c1){
118                         fs <<  "1,";
119                 }
120                 for(int i=0; i<Depth; i++)
121                 {
122                         if(i==0){fs << VTable.GetName(S_Var[i]);}
123                         else{fs << " " << VTable.GetName(S_Var[i]);}
124                 }
125                 return 0;
126         }
127         int v = a.TopItem();
128         CtoI b = a.Factor1(v);
129         if(b == CtoI_Null()) return 1;
130         S_Var[Depth] = v;
131         Depth++;
132         if(PF(b, base,fs) == 1) return 1;
133         Depth--;
134         b = a.Factor0(v);
135         if(b == 0) return 0;
136         if(b == CtoI_Null()) return 1;
137         return PF(b, base,fs);
138 }
139
140 int CsvoutCtoI(CtoI a,ofstream &fs)
141 {
142         if(a == CtoI_Null()) return 1;
143         if(a == 0) return 0;
144         else
145         {
146                 int lev = BDD_LevOfVar(a.TopItem());
147                 Depth = 0;
148                 kgAutoPtr2<int> a_ptr;
149                 try{
150                         a_ptr.set(new int[lev]);
151                         S_Var = a_ptr.get();
152                 }catch(...){
153                         rb_raise(rb_eRuntimeError,"memory allocation error");
154                 }
155                 PFflag = 0;
156                 int err = PF(a, 10,fs);
157                 if(err == 1){ 
158                         rb_raise(rb_eRuntimeError,"memory over flow");
159                         return 1; 
160                 }
161         }
162         fs << endl;
163         return 0;
164 }
165 /*
166  * call-seq:
167  * zdd.csvout(fileName)  -> self : CSV出力
168  *
169  *  zdd      : ZDD Object
170  *  fileName : Ruby String
171  * 
172  * === 説明
173  * zddオブジェクトの内容をfileNameで指定したファイル名にCSV形式で出力する。
174  * 項目は、重みとアイテム集合がこの順番で出力される。
175  * ただし項目名は出力されない。
176  * 空のアイテム集合はnull値として出力される。
177  * 返り値はself(自分自身)。
178  *
179  * === 例
180  *  > a.show # -> a b + 2 b c + 3 d + 4
181  *  > a.csvout("output.csv")
182  *
183  *  $ more output.csv
184  *  1,a b
185  *  2,b c
186  *  3,d
187  *  4,
188  *
189  * === 関連
190  *  hashout
191  */
192 VALUE vsop_csvout(int argc, VALUE *argv, VALUE self) {
193         Vsop_Ruby* rmod;
194         VALUE v;
195         Data_Get_Struct(self,Vsop_Ruby,rmod);
196         rb_scan_args(argc, argv,"10",&v);
197         char *str = RSTRING_PTR(v);
198         ofstream fs;
199         fs.open(str);
200         CsvoutCtoI(*rmod->cmod,fs);
201         fs.close();
202         return self;
203 }
204
205 static int PF_hash(CtoI a, int base,VALUE& hash)
206 {
207         if(a.IsConst())
208         {
209                 char valstr[MAX_LEN];
210                 if(a.TopDigit() & 1) {strcpy(valstr,"-") ; a = -a; }
211                 else{ strcpy(valstr,"");}
212
213                 PFflag = 1;
214                 int c1 = (a != 1);
215
216                 char *valrtn;
217                 kgAutoPtr2<char> a_ptr;
218                 if(c1 || Depth == 0)
219                 {
220                         if(a.TopItem() > 0) a = a.MaxVal();
221                         int d = a.TopDigit() / 3 + 14;
222                         try{
223                                 a_ptr.set(new char[d]);
224                                 valrtn = a_ptr.get();
225                         }catch(...){
226                                 rb_raise(rb_eRuntimeError,"memory allocation error");
227                         }
228                         int err;
229                         if(base == 16) err = a.StrNum16(valrtn);
230                         else err = a.StrNum10(valrtn);
231                         if(err == 1)
232                         {
233                                 rb_raise(rb_eRuntimeError,"memory over flow");
234                                 return 1;
235                         }
236                         strcat(valstr,valrtn);
237                 }
238                 else if(!c1){
239                         strcat(valstr,"1");
240                 }
241
242                 char keystr[MAX_LEN];
243                 *keystr = 0;
244                 for(int i=0; i<Depth; i++)
245                 {
246                         int size = strlen(keystr)+strlen(VTable.GetName(S_Var[i]))+2;
247                         if(size>MAX_LEN){
248                                 rb_raise(rb_eRuntimeError,"string size over flow");                             
249                         }
250                         if(i==0){
251                                 strcpy(keystr,VTable.GetName(S_Var[i]));
252                         }
253                         else{
254                                 strcat(keystr," ");
255                                 strcat(keystr,VTable.GetName(S_Var[i]));
256                         }
257                 }
258
259                 VALUE key = rb_str_new2(keystr);
260                 VALUE val = INT2NUM(atoi(valstr));
261                 rb_hash_aset(hash, key, val);
262                 hashcnt++;
263                 if(hashcnt> HASH_MAX){return 2;}
264                 return 0;
265         }
266         int v = a.TopItem();
267         printf("HPF_2 %d\n",v);
268         CtoI b = a.Factor1(v);
269         if(b == CtoI_Null()) return 1;
270         S_Var[Depth] = v;
271         Depth++;
272         int chk=PF_hash(b, base,hash);
273         if(chk > 0) return chk;
274         Depth--;
275         b = a.Factor0(v);
276         if(b == 0) return 0;
277         if(b == CtoI_Null()) return 1;
278
279         return PF_hash(b, base,hash);
280 }
281
282
283 static void num_check(char *str){
284         //数値チェック(アイテムが数値なら警告)
285         char *p=str;
286         if(*p=='-' || *p=='+' ) p++;
287                 while(*p){
288                 if( ( *p>='0' && *p<='9' ) || *p == '.' ){
289                                 fprintf(stderr,"chech %c\n",*p);
290                                 fprintf(stderr,"use numbers for symbol Variable\n");
291                                 break;
292                 }
293                 p++;
294         }
295 }
296
297
298
299 VALUE HashoutCtoI(CtoI a,int *rtn)
300 {
301         hashcnt=0;
302         VALUE hash = rb_hash_new();
303         if(a == CtoI_Null()) return 1;
304         if(a == 0) return 0;
305         else
306         {
307                 int lev = BDD_LevOfVar(a.TopItem());
308                 Depth = 0;
309                 kgAutoPtr2<int> a_ptr;
310                 try{
311                         a_ptr.set(new int[lev]);
312                         S_Var = a_ptr.get();
313                 }catch(...){
314                         rb_raise(rb_eRuntimeError,"memory allocation error");
315                 }
316                 PFflag = 0;
317                 int err = PF_hash(a, 10,hash);
318                 *rtn = err;
319                 if(err == 1){
320                         rb_raise(rb_eRuntimeError,"memory over flow");
321                         return rb_hash_new();
322                 }
323         }
324         return hash;
325 }
326
327
328
329
330 /*
331  * call-seq:
332  * zdd.hashout -> hash : Hash出力
333  *
334  *  zdd  : ZDD Object
335  *  hash : Ruby Hash
336  * 
337  * === 説明
338  * zddの内容をrubyのHashオブジェクトに変換し、そのオブジェクトを返す。
339  * ハッシュキーはアイテム集合、対応する値は重み。
340  *
341  * === 例
342  *  > a.show
343  *   a b + 2 b c + 3 d + 4
344  *
345  *  > h=a.hashout
346  *  > p h #
347  *   {""=>4, "a b"=>1, "d"=>3, "b c"=>2}
348  *
349  * === 関連
350  *  csvout
351  */
352 VALUE vsop_hashout(VALUE self){
353         int rtnflg=0;
354         Vsop_Ruby* rmod;
355         Data_Get_Struct(self,Vsop_Ruby,rmod);
356         VALUE hash = HashoutCtoI(*rmod->cmod,&rtnflg);
357         if(rtnflg==2){
358                 rb_iv_set(self,"@partly", Qtrue );
359         }
360         else{
361                 rb_iv_set(self,"@partly", Qfalse);
362         }
363         return hash;
364 }
365
366
367
368 ///////////  each用
369 static int PF_array_each(CtoI a, VALUE& self)
370 {
371         int sign=1;
372         if(a.IsConst())
373         {
374                 char valstr[MAX_LEN];
375                 if(a.TopDigit() & 1) {sign= -1 ; a = -a; }
376                 CtoI rtn;
377                 int c1 = (a != 1);
378                 char *valrtn;
379                 kgAutoPtr2<char> a_ptr;
380                 if(c1 || Depth_e == 0)
381                 {
382                         if(a.TopItem() > 0) a = a.MaxVal();
383                         int d = a.TopDigit() / 3 + 14;
384                         try{
385                                 a_ptr.set(new char[d]);
386                                 valrtn = a_ptr.get();
387                         }catch(...){
388                                 rb_raise(rb_eRuntimeError,"memory allocation error");
389                         }
390                         int  err = a.StrNum10(valrtn);
391                         if(err == 1){
392                                 rb_raise(rb_eRuntimeError,"memory over flow");
393                                 return 1;
394                         }
395                         rtn = CtoI(CtoI_atoi(valrtn));
396                 }
397                 else if(!c1){
398                         rtn = CtoI(CtoI_atoi("1"));;
399                 }
400
401                 for(int i=0; i<Depth_e; i++)
402                 {
403                         char *str = VTable.GetName(S_Var_e[i]);
404                         int ckck = VTable.GetID(str);
405                         rtn =Product(rtn, CtoI(1).AffixVar( ckck));
406                 }
407                 
408                 Vsop_Ruby* rmod=new Vsop_Ruby;
409                 rmod->cmod = new CtoI (rtn) ;
410                         rb_yield_values(1,Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod));
411                 return 0;
412         }
413                         
414         int v = a.TopItem();
415         CtoI b = a.Factor1(v);
416         if(b == CtoI_Null()) return 1;
417         S_Var_e[Depth_e] = v;
418         Depth_e++;
419         int chk=PF_array_each(b, self);
420         if(chk > 0) return chk;
421         Depth_e--;
422         b = a.Factor0(v);
423         if(b == 0) return 0;
424         if(b == CtoI_Null()) return 1;
425         return PF_array_each(b,self);
426 }
427
428 //////////////////////////////////////////////
429 void CtoI2Array_each(CtoI a,VALUE &self)
430 {
431         if(a == CtoI_Null()) return ;
432         if(a == 0) return ;
433         else
434         {
435                 int lev = BDD_LevOfVar(a.TopItem());
436                 Depth_e = 0;
437                 kgAutoPtr2<int> a_ptr;
438                 try{
439                         a_ptr.set(new int[lev]);
440                         S_Var_e = a_ptr.get();
441                 }catch(...){
442                         rb_raise(rb_eRuntimeError,"memory allocation error");
443                 }
444                 PF_array_each(a, self);
445         }
446 }
447 /*
448  * call-seq:
449  * zdd.each{|x|} -> Qtrue
450  *
451  *  ZDDからアイテムセットを1つずつ読み込み,指定されたブロックを実行する.
452  *
453  * === 例
454  *  > x.show
455  *   2 a + 2 b + 4 a c
456  *  # x,yが上記の通り定義されていたとする。
457  *
458  *  > x.each{|x|
459  *  >   x.show
460  *  > }
461  *  4 a c
462  *  2 a
463  *  2 b
464 */
465 VALUE vsop_each(VALUE self){
466         Vsop_Ruby* rmod;
467         Data_Get_Struct(self,Vsop_Ruby,rmod);
468         CtoI2Array_each(*rmod->cmod,self);
469         return Qtrue;   
470 }
471
472
473
474
475
476
477 // array用
478 static int PF_array(CtoI a,VALUE& array)
479 {
480         if(a.IsConst())
481         {
482                 char valstr[MAX_LEN];
483                 if(a.TopDigit() & 1) {strcpy(valstr,"-") ; a = -a; }
484                 else{ strcpy(valstr,"");}
485
486                 PFflag = 1;
487                 int c1 = (a != 1);
488
489                 char *valrtn;
490                 kgAutoPtr2<char> a_ptr;
491                 if(c1 || Depth == 0)
492                 {
493                         if(a.TopItem() > 0) a = a.MaxVal();
494                         int d = a.TopDigit() / 3 + 14;
495                         try{
496                                 a_ptr.set(new char[d]);
497                                 valrtn = a_ptr.get();
498                         }catch(...){
499                                 rb_raise(rb_eRuntimeError,"memory allocation error");
500                         }
501                         int err;
502                         err = a.StrNum10(valrtn);
503                         if(err == 1)
504                         {
505                                 rb_raise(rb_eRuntimeError,"memory over flow");
506                                 return 1;
507                         }
508                         strcat(valstr,valrtn);
509                 }
510
511                 char keystr[MAX_LEN];
512                 *keystr = 0;
513                 for(int i=0; i<Depth; i++)
514                 {
515                         int size = strlen(keystr)+strlen(VTable.GetName(S_Var_ary[i]))+2;
516                         if(size>MAX_LEN){
517                                 rb_raise(rb_eRuntimeError,"string size over flow");                             
518                         }
519                         if(i==0){
520                                 strcpy(keystr,VTable.GetName(S_Var_ary[i]));
521                         }
522                         else{
523                                 strcat(keystr," ");
524                                 strcat(keystr,VTable.GetName(S_Var_ary[i]));
525                         }
526                 }
527                 if(*valstr&& *keystr){ 
528                         strcat(valstr," ");
529                         strcat(valstr,keystr); 
530                 }
531                 else{strcat(valstr,keystr); }
532
533                 VALUE val = rb_str_new2(valstr);
534                 rb_ary_push(array,val);
535                 return 0;
536         }
537         int v = a.TopItem();
538         CtoI b = a.Factor1(v);
539         if(b == CtoI_Null()) return 1;
540         S_Var_ary[Depth] = v;
541         Depth++;
542         int chk=PF_array(b, array);
543         if(chk > 0) return chk;
544         Depth--;
545         b = a.Factor0(v);
546         if(b == 0) return 0;
547         if(b == CtoI_Null()) return 1;
548
549         return PF_array(b, array);
550 }
551
552
553 VALUE CtoI2Array(CtoI a)
554 {
555         VALUE array = rb_ary_new();
556         if(a == CtoI_Null()) return array;
557         if(a == 0) return array;
558         else
559         {
560                 int lev = BDD_LevOfVar(a.TopItem());
561                 Depth = 0;
562                 kgAutoPtr2<int> a_ptr;
563                 try{
564                         a_ptr.set(new int[lev]);
565                         S_Var_ary = a_ptr.get();
566                 }catch(...){
567                         rb_raise(rb_eRuntimeError,"memory allocation error");
568                 }
569                 int err = PF_array(a, array);
570                 if(err == 1){ 
571                         rb_raise(rb_eRuntimeError,"memory over flow");
572                         return array; 
573                 }
574         }
575         return array;
576 }
577 /*
578  * call-seq:
579  * zdd.to_a -> Array
580  *
581  *  ZDDからアイテムセット文字列の配列を返す.
582  *
583  * === 例
584  *  > x.show
585  *   2 a + 2 b + 4 a c
586  *  # x,yが上記の通り定義されていたとする。
587  *
588  *  > array = x.to_a
589  * [ "4 a c","2 a","2 b"]
590 */
591 VALUE vsop_to_a(VALUE self){
592         Vsop_Ruby* rmod;
593         Data_Get_Struct(self,Vsop_Ruby,rmod);
594         VALUE array = CtoI2Array(*rmod->cmod);
595
596         return array;
597 }
598
599
600
601
602
603 //str用
604 static int PutNum_str(CtoI a, int base,VALUE &str)
605 {
606         if(a.TopItem() > 0) a = a.MaxVal();
607         int d = a.TopDigit() / 3 + 14;
608         kgAutoPtr2<char> a_ptr;
609         char *s;
610         try{
611                 a_ptr.set(new char[d]);
612                 s = a_ptr.get();
613         }catch(...){
614                 rb_raise(rb_eRuntimeError,"memory allocation error");
615         }
616         int err;
617         if(base == 16) err = a.StrNum16(s);
618         else err = a.StrNum10(s);
619         if(err == 1)            return 1;
620         rb_str_cat(str,s,strlen(s));
621
622         return 0;
623 }
624
625 static int PF_str(CtoI a,VALUE str)
626 {
627         if(a.IsConst())
628         {
629                 if(PFflag == 1){rb_str_cat(str," + ",strlen(" + "));}
630                 if(a.TopDigit() & 1) {rb_str_cat(str," - ",strlen(" - ")); a = -a; }
631                 
632                 PFflag = 1;
633                 int c1 = (a != 1);
634                 if(c1 || Depth == 0)
635                 {
636                         if(PutNum_str(a, 10,str) == 1) return 1;
637                         rb_str_cat(str," ",strlen(" "));
638                 }
639
640                 for(int i=0; i<Depth; i++)
641                 {
642                         char *p = VTable.GetName(S_Var[i]);
643                         rb_str_cat(str,p,strlen(p));
644                         if( i<Depth-1) rb_str_cat(str," ",strlen(" "));
645                 }
646                 return 0;
647         }
648         int v = a.TopItem();
649         CtoI b = a.Factor1(v);
650         if(b == CtoI_Null()) return 1;
651         S_Var[Depth] = v;
652         Depth++;
653         if(PF_str(b, str) == 1) return 1;
654         Depth--;
655         b = a.Factor0(v);
656         if(b == 0) return 0;
657         if(b == CtoI_Null()) return 1;
658         return PF_str(b,str);
659 }
660
661 VALUE CtoI2String(CtoI a)
662 {
663         VALUE str = rb_str_new2("");
664
665         if(a == CtoI_Null()) return str;
666         if(a == 0) return str;
667         else
668         {
669                 int lev = BDD_LevOfVar(a.TopItem());
670                 Depth = 0;
671                 kgAutoPtr2<int> a_ptr;
672                 try{
673                         a_ptr.set(new int[lev]);
674                         S_Var = a_ptr.get();
675                 }catch(...){
676                         rb_raise(rb_eRuntimeError,"memory allocation error");
677                 }
678                 PFflag = 0;
679                 int err = PF_str(a, str);
680                 if(err == 1){ 
681                         rb_raise(rb_eRuntimeError,"memory over flow");
682                         return str; 
683                 }
684         }
685         return str;
686 }
687
688 /*
689  * call-seq:
690  * zdd.to_a -> String
691  *
692  *  ZDDからアイテムセット文字列を返す.
693  *
694  * === 例
695  *  > x.show
696  *   2 a + 2 b + 4 a c
697  *  # x,yが上記の通り定義されていたとする。
698  *
699  *  > array = x.to_s
700  * "4 a c + 2 a + 2 b"
701 */
702 VALUE vsop_to_s(VALUE self){
703         Vsop_Ruby* rmod;
704         Data_Get_Struct(self,Vsop_Ruby,rmod);
705         VALUE str = CtoI2String(*rmod->cmod);
706         return str;
707 }
708
709
710
711 ///////////  each_item用
712 static int PF_itemarray(CtoI a, VALUE& self)
713 {
714         int sign=1;
715         if(a.IsConst())
716         {
717                 char valstr[MAX_LEN];
718                 if(a.TopDigit() & 1) {sign= -1 ; a = -a; }
719                 int c1 = (a != 1);
720                 VALUE weight;
721                 char *valrtn;
722                 kgAutoPtr2<char> a_ptr;
723                 if(c1 || Depth_item == 0)
724                 {
725                         if(a.TopItem() > 0) a = a.MaxVal();
726                         int d = a.TopDigit() / 3 + 14;
727                         try{
728                                 a_ptr.set(new char[d]);
729                                 valrtn = a_ptr.get();
730                         }catch(...){
731                                 rb_raise(rb_eRuntimeError,"memory allocation error");
732                         }
733                         int  err = a.StrNum10(valrtn);
734                         if(err == 1){
735                                 rb_raise(rb_eRuntimeError,"memory over flow");
736                                 return 1;
737                         }
738                         weight = INT2NUM(atoi(valrtn));
739                 }
740                 else if(!c1){
741                         weight = INT2NUM(1);
742                 }
743
744                 VALUE top=Qtrue;
745                 VALUE bottom=Qfalse;
746                 for(int i=0; i<Depth_item; i++){
747                         char *str = VTable.GetName(S_Var_item[i]);
748                         int ckck = VTable.GetID(str);
749                         Vsop_Ruby* rmod=new Vsop_Ruby;
750                         rmod->cmod = new CtoI (CtoI(1).AffixVar( ckck)) ;
751                         if( i>0 ) top=Qfalse;
752                         if( i+1==Depth_item ) bottom=Qtrue; 
753                         rb_yield_values(4,weight,Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod) ,top,bottom);
754                 }
755                 return 0;
756         }       
757         int v = a.TopItem();
758         CtoI b = a.Factor1(v);
759         if(b == CtoI_Null()) return 1;
760         S_Var_item[Depth_item] = v;
761         Depth_item++;
762         int chk=PF_itemarray(b, self);
763         if(chk > 0) return chk;
764         Depth_item--;
765         b = a.Factor0(v);
766         if(b == 0) return 0;
767         if(b == CtoI_Null()) return 1;
768         return PF_itemarray(b,self);
769 }
770
771 //////////////////////////////////////////////
772 void CtoI2ItemArray(CtoI a,VALUE &self)
773 {
774         VALUE ary = rb_ary_new();
775         if(a == CtoI_Null()) return;
776         if(a == 0) return;
777         else
778         {
779                 int lev = BDD_LevOfVar(a.TopItem());
780                 Depth_item = 0;
781                 kgAutoPtr2<int> a_ptr;
782                 try{
783                         a_ptr.set(new int[lev]);
784                         S_Var_item = a_ptr.get();
785                 }catch(...){
786                         rb_raise(rb_eRuntimeError,"memory allocation error");
787                 }
788                 PF_itemarray(a, self);
789         }
790 }
791
792
793
794 /*
795  * call-seq:
796  * zdd.each_item{|val ,item,top,botom |} -> Qtrue
797  *
798  *  ZDDをアイテムセットのアイテムを1つずつ読み込み,指定されたブロックを実行する.
799  *
800  * === ブロック引数
801  * zddeach {|weight,item,top,bottom|}
802  * weight :: アイテムセットの重み
803  * item :: アイテムzdd
804  * top :: アイテムセットの最初のアイテムであればture、それ以外はfalse
805  * bottom :: アイテムセットの最後のアイテムであればture、それ以外はfalse.
806  * 
807  * === 例
808  *  > x.show
809  *   2 a + 2 b + 4 a c
810  *  # x,yが上記の通り定義されていたとする。
811  *
812  *  > f.each_item{|val,x,t,b|
813  *  >   p val
814  *  >   x.show
815  *  >   p t
816  *  >   p b
817  *  > p "----------"
818  *  >}
819  *   4
820  *   a
821  *   true
822  *   false
823  *   "----------"
824  *   4
825  *   c
826  *   false
827  *   true
828  *   "----------"
829  *   2
830  *   a
831  *   true
832  *   true
833  *   "----------"
834  *   2
835  *   b
836  *   true
837  *   true
838  *   "----------"
839 */
840 VALUE vsop_each_item(VALUE self){
841         Vsop_Ruby* rmod;
842         Data_Get_Struct(self,Vsop_Ruby,rmod);
843         CtoI2ItemArray(*rmod->cmod,self);
844         return Qtrue;   
845 }
846
847
848 //この値はBDDライブラリとかぶらないよう注意すること
849 // キャッシュがおかしくなる
850 static const char BC_CtoI_DELTA =  50;
851
852 CtoI CtoI_Delta(CtoI a, CtoI b)
853 {
854   if(a == CtoI_Null())  return a;
855   if(b == CtoI_Null()) return b;
856   if(a == 0) return 0;
857   if(b == 0) return 0;
858   if(a == 1 && b==1) return 1;
859
860
861   int atop = a.Top();
862   int btop = b.Top();
863   if(BDD_LevOfVar(atop) < BDD_LevOfVar(btop)) return CtoI_Delta(b, a);
864
865   bddword ax = a.GetZBDD().GetID();
866   bddword bx = b.GetZBDD().GetID();
867   if(atop == btop && ax < bx) return CtoI_Delta(b, a);
868
869   ZBDD z = BDD_CacheZBDD(BC_CtoI_DELTA, ax, bx);
870   if(z != -1) return CtoI(z);
871
872   CtoI a0 = a.Factor0(atop);
873   CtoI a1 = a.Factor1(atop);
874   CtoI c;
875   if(atop != btop)
876   {
877                 if(a.IsBool()) c =  CtoI_Union( CtoI_Delta(a0, b), CtoI_Delta(a1, b).AffixVar(atop) );
878     else c = CtoI_Delta(a0, b) + CtoI_Delta(a1, b).TimesSysVar(atop);
879   }
880   else
881   {
882     CtoI b0 = b.Factor0(atop);
883     CtoI b1 = b.Factor1(atop);
884     if(a.IsBool())
885       c = CtoI_Union( CtoI_Delta(a0, b0) + CtoI_Delta(a1, b1),
886              (CtoI_Delta(a1, b0)+ CtoI_Delta(a0, b1)).AffixVar(atop) ) ;
887                 else if(atop > 1)
888       c = CtoI_Delta(a0, b0)
889         + (CtoI_Delta(a1, b0) + CtoI_Delta(a0, b1)).TimesSysVar(atop)
890         + CtoI_Delta(a1, b1).TimesSysVar(atop-1);
891     else BDDerr("CtoI_Delta(): SysVar overflow.");
892   }
893   BDD_CacheEnt(BC_CtoI_DELTA, ax, bx, c.GetZBDD().GetID());
894   return c;
895 }
896
897 /*
898  * call-seq:
899  * zdd1.delta(zdd2) -> ZDD Object : delta演算
900  *
901  *  zdd1,zdd2 : ZDD Object
902  *
903  * === 説明
904  *  zdd1に含まれるアイテム集合αとzdd2に含まれるアイテム集合βのα ⊕βを求める。
905  *  例えば、アイテム集合abc と bcd の排他的論理和は以下の通り。
906  *   abc.delta(bcd) = abc ⊕ bcd = ad
907  *  複数のアイテム集合間の演算では全組合せについて排他的論理和を求める。
908  *  (abc + a).delta(bcd + b) = abc ⊕ bcd + abc ⊕ b + a ⊕ bcd + a ⊕ b
909  *                          = ad        + ac       + abcd       + ab
910  *  重みについては、同じアイテム集合を複数に展開して計算すればよい。
911  *  (2abc).delta(bcd) = (abc+abc).delta(bcd) = ad + ad = 2ad
912  *
913  * === 例
914  *  > a=VSOP.itemset("a")
915  *  > b=VSOP.itemset("b")
916  *  > f=a+2*a*b+3*b
917  *  
918  *  # a + 2ab + 3b の各アイテム集合と引き数で指定されたアイテム集合 a との排他的論理和を求めると、
919  *  # 3 a b + 2 b + 1 となる。
920  *  > f.delta(a).show
921  *  3 a b + 2 b + 1
922  *
923  *  # アイテム集合bとの排他的論理和を求めると a b + 2 a + 3 となる。
924  *  > f.delta(b).show
925  *  a b + 2 a + 3
926  *
927  *  # アイテム集合 ab との排他的論理和を求めると 3 a + b + 2 となる。
928  *  > f.delta(a*b).show
929  *  3 a + b + 2 
930  *
931  *  # 定数1は空のアイテム集合なので、それとの排他的論理和を求めると元の集合のままとなる。
932  *  > f.meet(1).show
933  *  2 a b + a + 3 b
934  *  > exit
935  *
936  *  > a=VSOP.itemset("a")
937  *  > b=VSOP.itemset("b")
938  *  > c=VSOP.itemset("c")
939  *  >
940  *  > f=((a*b*c)+2*(a*b)+(b*c)+1)
941  *  > f.show
942  *   a b c + 2 a b + b c + 1
943  *
944  *  > g=2*a*b + a
945  *  > g.show
946  *   a b + a
947  *  # abc + 2ab + bc + 1 の各アイテム集合と引き数で指定された 2ab + a の各アイテム集合との排他的論理和を求めると、
948  *  # 以下の通りとなる(アイテム間のスペースは省略)。
949  *  # abc ⊕ 2ab = 2c
950  *  # 2ab ⊕ 2ab = 4
951  *  # bc  ⊕ 2ab = 2ac
952  *  # 1   ⊕ 2ab = 2ab
953  *  # abc ⊕ a   = bc
954  *  # 2ab ⊕ a   = 2b
955  *  # bc  ⊕ a   = abc
956  *  # 1   ⊕ a   = a
957  *  # 結果をまとめると a b c + 2 a b + 2 a c + a + b c + 2 b + 2 c + 4  となる。
958  *  #
959  *  > f.delta(g).show
960  *   a b c + 2 a b + 2 a c + a + b c + 2 b + 2 c + 4
961  * ----
962  * ====== 上記の例において出力結果を示したコメントでは、アイテムをアルファベット小文字1文字で表し、項における重みとアイテム間のスペースおよびアイテム間のスペースを省略して表記している。
963  */
964
965 VALUE vsop_delta(int argc, VALUE *argv,VALUE self){
966         Vsop_Ruby* rmod;
967         VALUE v;
968         Data_Get_Struct(self,Vsop_Ruby,rmod);
969         rb_scan_args(argc, argv,"10",&v);
970         CtoI *ctoi_moda =new CtoI(*rmod->cmod);
971         CtoI *ctoi_modc = value2ctoi(v);
972         CtoI *ctoi_fin; 
973         *ctoi_moda = CtoI_Delta(*ctoi_moda, *ctoi_modc);
974   ctoi_fin = ctoi_moda;
975   delete ctoi_modc;
976         Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
977         rmod_rtn->cmod = ctoi_fin;
978         return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
979 }
980
981 CtoI* string2ctoi(char *str){
982         //初回呼び出し時のみBDDの初期化
983 /*
984         v = rb_cv_get(self,"@@init_cnt");
985         int init_cnt_v =  NUM2INT(v);
986         if(init_cnt_v==0){ BDDV_Init(256, env_nmax);}
987         init_cnt_v++;
988         rb_cv_set(self,"@@init_cnt",INT2NUM(init_cnt_v));
989 */
990
991         if(init_cnt==0){ BDDV_Init(256, env_nmax);}
992         init_cnt++;
993         int sep_cnt=0;
994         for(char *p=str;*p;p++){
995                 if(*p==' '){ 
996                         sep_cnt++;
997                 }
998         }
999         sep_cnt++;
1000         kgAutoPtr2<CtoI> a_ptr;
1001         CtoI * ctoitmp;
1002         try{
1003                 a_ptr.set(new CtoI[sep_cnt]);
1004                 ctoitmp = a_ptr.get();
1005         }catch(...){
1006                 rb_raise(rb_eRuntimeError,"memory allocation error");
1007         }
1008         int i=0;
1009         char *p,*q;
1010         p=str;
1011         q=str;
1012         while(1){
1013                 if(*p==' '){//区切り文字
1014                         *p='\0';
1015                         int var = VTable.GetID(q);     
1016                         if(var == 0){
1017                                 if(env_warning){ num_check(q); }
1018                                 VTable.SetB(q, power16/2);
1019                                 var  = VTable.GetID(q);
1020                         }
1021                         ctoitmp[i] = CtoI(1).AffixVar(var);
1022                         q=p+1;
1023                         i++;
1024                 }
1025                 else if(*p=='\0'){//終了時文字
1026                         int var = VTable.GetID(q);     
1027                         if(var == 0){
1028                                 if(env_warning){ num_check(q); }
1029                                 VTable.SetB(q, power16/2);
1030                                 var  = VTable.GetID(q);
1031                         }
1032                         ctoitmp[i] = CtoI(1).AffixVar(var);
1033                         break;
1034                 }
1035                 p++;
1036         }
1037         CtoI ctmp = ctoitmp[0];
1038         for(int i=1;i<sep_cnt;i++){
1039                 ctmp = Product(ctmp,ctoitmp[i]);
1040         }
1041         CtoI *rtnctoi = new CtoI(ctmp);
1042         return rtnctoi;
1043 }
1044
1045 //VALUEを受け取り、CtoI*を返す
1046 CtoI *value2ctoi(VALUE v){
1047  CtoI *rtnctoi;
1048         Vsop_Ruby* argrmod;
1049         if(TYPE(v)==T_STRING){
1050                 rtnctoi=string2ctoi(RSTRING_PTR(v));
1051         }
1052         else if(TYPE(v)==T_FIXNUM){
1053                 rtnctoi=int2ctoi(FIX2INT(v));
1054         }
1055         else if(TYPE(v)==T_BIGNUM){
1056                 rtnctoi=int2ctoi(NUM2INT(v));
1057         }
1058         else{
1059                 Data_Get_Struct(v,Vsop_Ruby,argrmod);
1060                 rtnctoi =new CtoI(*argrmod->cmod);
1061         }
1062         return rtnctoi; 
1063 }
1064
1065 /*
1066  * call-seq:
1067  * 書式1) ZDD.symbol(itemName, value, to) -> Qture : シンボル変数の宣言
1068  * 書式2) ZDD.symbol -> itemList : シンボル変数の一覧
1069  *
1070  *  itemName : Ruby String
1071  *  value    : Ruby Float
1072  *  to         : Ruby String
1073  *  itemList : Ruby String
1074  *
1075  * === 説明
1076  *  書式1)
1077  *  itemNameで指定した文字列のZDDアイテム名を宣言する。
1078  *  アイテム名として利用できる文字種に特に制限はない。また文字列長についても特に制限はない(メモリ容量制限のみ)。
1079  *  valueは、そのアイテムに与える値で、valueやmaxcoverなどのメソッドで利用される。詳しくは、valueメソッドを参照のこと。
1080  *  省略時には0.5が設定される。
1081  *  toは宣言したアイテムの追加する方向を指定する(top | bottom)。
1082  *  省略時にはbottomが設定される。
1083  *  書式2)
1084  *  引数なしでこのメソッドを呼び出すと、シンボル変数の一覧がスペース区切りの文字列として返される。
1085  *
1086  * === 例
1087  *  > ZDD.symbol("a",1.0)
1088  *  > ZDD.symbol("b",0.5)
1089  *  > ZDD.symbol("c",2.0,"top")
1090  *  > ZDD.symbol("d")
1091  *  > ZDD.symbol
1092  *  c a  b  d
1093  *
1094  *  > (1..10).each{|i|
1095  *  >   ZDD.symbol("s_#{i}",i)
1096  *  > }
1097  *  > puts  ZDD.symbol
1098  *  c a b d s_1 s_2 s_3 s_4 s_5 s_6 s_7 s_8 s_9 s_10 
1099  *
1100  * === 関連
1101  *  itemset, value
1102  */
1103 VALUE vsop_symbol(int argc, VALUE *argv, VALUE self) {
1104         //引数読み込み
1105         VALUE rtn;
1106         //初回呼び出し時のみBDDの初期化    
1107         if(init_cnt==0){ BDDV_Init(256, env_nmax);}
1108         init_cnt++;
1109
1110         if(argc>=1){
1111                 int val=power16/2;
1112                 char *to ="bottom";
1113                 char *str;
1114                 VALUE v1,v2,v3;
1115                 rb_scan_args(argc, argv,"12",&v1,&v2,&v3);
1116                 switch(argc){
1117                         case 3:
1118                                 if(TYPE(v3)!=T_STRING){
1119                                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
1120                                 }
1121                                 to = RSTRING_PTR(v3);                           
1122                         case 2:
1123                                 if(TYPE(v2)==T_FLOAT){
1124                                         val = (int)( NUM2DBL(v2)*power16);
1125                                 }
1126                                 else if(TYPE(v2)==T_FIXNUM){
1127                                         val =  NUM2INT(v2)*power16;
1128                                 }
1129                                 else if(TYPE(v2)==T_NIL){
1130                                 }                               
1131                                 else{
1132                                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be FLOAT or INT or NIL)");
1133                                 }                               
1134                         case 1:
1135                                 if(TYPE(v1)!=T_STRING){
1136                                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
1137                                 }
1138                                 str = RSTRING_PTR(v1);
1139                                 //数値チェック(アイテムが数値なら警告)
1140                                 if(env_warning){ num_check(str); }
1141                                 break;
1142                         default:
1143                                 rb_raise(rb_eRuntimeError,"argument type error");
1144                                 break;
1145                 }
1146                 if(*str!='\0'){
1147                         int var = VTable.GetID(str);
1148                         if(var == 0){
1149                                 if(!strcmp(to,"top"))   { VTable.SetT(str, val);}
1150                                 else                                    { VTable.SetB(str, val);}
1151                         }
1152                 }
1153                 rtn = Qtrue;
1154         }
1155         else{
1156                 int n = VTable.Used();
1157                 string str ;
1158                 for(int i=n; i>0; i--)
1159                 {
1160                         int var = BDD_VarOfLev(i);
1161                         str += VTable.GetName(var);
1162                         str += " ";
1163                 }
1164                 rtn = rb_str_new2(str.c_str());
1165         }
1166         return rtn;
1167 }
1168 /*
1169  * call-seq:
1170  * ZDD.itemset(itemSets) -> zdd : アイテム集合のzddオブジェクトの作成
1171  *
1172  *  itemSets : Ruby String
1173  *  zdd      : ZDD Object
1174  *
1175  * === 説明
1176  *  itemSetsで指定されたアイテム集合のzddオブジェクトを生成する。
1177  *  複数のアイテムは半角スペースで区切る。
1178  *  空文字("")が指定された場合は空のアイテム集合と扱われ、積和表現の定数項1として設定される(zdd.constant(1)と同様)。
1179  *  symbolメソッドで宣言されていないアイテムは現在のアイテム順の最後に追加される。
1180  *  またアイテムに設定される値はデフォルトの0.5となる。
1181  *
1182  * === 例
1183  *  > a=ZDD.itemset("a b")
1184  *  > a.show
1185  *   a b
1186  *
1187  *  > b=ZDD.itemset("b")
1188  *  > b.show
1189  *   b
1190  *
1191  *  > c=ZDD.itemset("")
1192  *  > c.show
1193  *   1
1194  *
1195  *  # 数字をアイテム名として利用することも可能
1196  *  > x0=ZDD.itemset("2")
1197  *  > x0.show
1198  *   2
1199  *
1200  *  # ただし、表示上重みと区別がつかなくなるので注意が必要。
1201  *  > (2*x0).show
1202  *   2 2
1203  *
1204  *  # こんな記号ばかりのアイテム名もOK。
1205  *  > x1=ZDD.itemset("!#%&'()=~|@[;:]")
1206  *  > x1.show
1207  *   !#%&'()=~|@[;:]
1208  *
1209  *  # ただし、rubyで特殊な意味を持つ記号はエスケープする必要がある。
1210  *  > x2=ZDD.itemset("\\\$\"")
1211  *  > x2.show
1212  *   \$"
1213  *
1214  *  # もちろん日本語も利用可。
1215  *  > x3=ZDD.itemset("りんご ばなな")
1216  *  > x3.show
1217  *   りんご ばなな
1218  *
1219  * === 関連
1220  *  symbol, constant, value
1221  */
1222 VALUE vsop_itemset(int argc, VALUE *argv, VALUE self) {
1223
1224         Vsop_Ruby* rmod=new Vsop_Ruby;
1225         VALUE v;
1226
1227         //引数読み込み
1228         rb_scan_args(argc, argv,"10",&v);
1229         if(TYPE(v)!=T_STRING){
1230                 rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
1231         }
1232         
1233         char *str = RSTRING_PTR(v);
1234         if (*str =='\0'){
1235                 rmod->cmod = int2ctoi(1);
1236         }
1237         else{
1238                 rmod->cmod = string2ctoi(str);
1239         }
1240
1241         return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod);
1242 }
1243
1244 CtoI * int2ctoi(int val){
1245         //初回呼び出し時のみBDDの初期化
1246         if(init_cnt==0){ BDDV_Init(256, env_nmax);}
1247         init_cnt++;
1248         char wrkval[64];
1249         sprintf(wrkval,"%d",val);
1250         CtoI *rtnctoi = new CtoI(CtoI_atoi(wrkval));
1251         return rtnctoi;
1252 }
1253
1254 /*
1255  * call-seq:
1256  * ZDD.constant(weight) -> zdd : ZDD重みオブジェクトの生成
1257  *
1258  *  weight : Ruby Integer
1259  *  zdd    : ZDD Object
1260  *
1261  * === 説明
1262  *  weightで指定した整数をZDDの重みオブジェクト(空のアイテム集合の重み)に変換する。
1263  *
1264  * === 例
1265  *  > c=ZDD.constant(10)
1266  *  > c.show
1267  *   10
1268  *
1269  *  > c*"a"   -> 10 a  # ZDD重みオブジェクトとruby文字列との演算では、ruby文字列はアイテム集合と見なされ自動でZDDオブジェクトにキャストされる。
1270  *  > 0*c     -> 0     # ZDD重みオブジェクトとruby整数との演算では、ruby整数はZDD重みオブジェクトと見なされる。
1271  *  > puts c.to_i*10   # ZDD重みオブジェクトをruby整数に変換し、ruby整数として演算する。
1272  *   100
1273  *
1274  *  # 以下のように、0の重みを定義しておくと、そのオブジェクトとの演算においては、RubyStringを自動的にキャストしてくれるので便利である。
1275  *  > a=ZDD.constant(0)
1276  *  > a+="x"
1277  *  > a+="x z"
1278  *  > a+="z"
1279  *  > a.show
1280  *   x z + x + z
1281  *
1282  * === 関連
1283  *  to_i
1284  */
1285 VALUE vsop_constant(int argc, VALUE *argv, VALUE self) {
1286         Vsop_Ruby* rmod=new Vsop_Ruby;
1287         VALUE v;
1288
1289         //引数読み込み
1290         rb_scan_args(argc, argv,"10",&v);
1291
1292         CtoI ctoitmp;
1293         //定数FIXNUM
1294         if(TYPE(v)==T_FIXNUM){
1295                 rmod->cmod = int2ctoi(FIX2INT(v));
1296         }
1297         //定数BIGNUM
1298         else if(TYPE(v)==T_BIGNUM){
1299                 rmod->cmod = int2ctoi(NUM2INT(v));
1300         }
1301         else{
1302                 rb_raise(rb_eRuntimeError,"argument type error (arguments must be FIXNUM or BIGNUM)");
1303         }
1304         VALUE rtn = Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod);
1305         return rtn;
1306 }
1307
1308 /* call-seq:
1309  *  ZDD.lcm(transaction, type,fixnum [,order]) -> zdd : lcm over zdd(最大サポート指定可能)
1310  *
1311  *  transaction : RubyString
1312  *  type        : RubyString
1313  *  minSupport  : RubyInteger
1314  *  order       : RubyString
1315  *  zdd         : ZDD Object
1316  *
1317  * === 説明
1318  *  transactionで指定されたファイルから、LCM over zdd アルゴリズムを利用し頻出パターンを列挙しそのZDDオブジェクトを返す。
1319  *  列挙する頻出パターンの種別はtypeで与える("F":頻出集合, "M":極大集合, "C":飽和集合)。
1320  *
1321  *  orderファイルによりアイテムの宣言順序を制御できる。
1322  *  同じtransactionデータに対して異なる最小サポートで実行すると、本メソッドにおける内部的なアイテム宣言方法 (得られる全パターンにのみ含まれるアイテムについて、頻度の高い順に宣言される)が原因して宣言順序にずれが生じる可能性がある。
1323  *  それを回避するために、頻度1以上の全アイテムを頻度の高い順に登録したorderファイルを用意し、本メソッドに与える。
1324  *  orderファイルの作成についてはlcm-ruby拡張パッケージのメソッドを利用することで得ることができる。
1325  *
1326  *  transactionのデータ値は数字に変換しておく必要がある。
1327  *
1328  * <b>説明</b> 
1329  * ==== sring3がない場合
1330  * generates frequent patterns using LCM algorithm from the FIMI format database file "string2" with minimum support = "fixnum".
1331  * ===== "string1" specifies LCM parameter as:
1332  * * F  all patterns,
1333  * * C  clesed patterns,
1334  * * M  maximal patterns,
1335  * * FQ  all patterns with frequencies,
1336  * * CQ  clesed patterns with frequencies,
1337  * * MQ  maximal patterns with frequencies.
1338  * ==== sring3がある場合
1339  * generates frequent patterns using LCM algorithm from the FIMI format database file "string1" with minimum support = "fixnum" and variable order file "string3".
1340  * ===== "string1" specifies LCM parameter as:
1341  * * F  all patterns,
1342  * * C  clesed patterns,
1343  * * M  maximal patterns,
1344  * * FQ  all patterns with frequencies,
1345  * * CQ  clesed patterns with frequencies,
1346  * * MQ  maximal patterns with frequencies.
1347  *
1348 */
1349 VALUE vsop_lcm(int argc, VALUE *argv, VALUE self){
1350         VALUE rtnval;
1351         if(argc==4){
1352                 rtnval = vsop_lcm_order(argc,argv,self);
1353         }
1354         else{
1355                 rtnval = vsop_lcm_nomal(argc,argv,self);
1356         }
1357         return rtnval;
1358 }
1359
1360
1361
1362 // ------------------------------ パターン長制約を入れたlcm over zdd
1363
1364 VALUE vsop_lcm_nomal_ub(int argc, VALUE *argv, VALUE self){
1365 /*
1366         VALUE vz = rb_cv_get(self,"@@init_cnt");
1367         int init_cnt_v =  NUM2INT(vz);
1368         if(init_cnt_v==0){ BDDV_Init(256, env_nmax);}
1369         init_cnt_v++;
1370         rb_cv_set(self,"@@init_cnt",INT2NUM(init_cnt_v));
1371 */
1372         if(init_cnt==0){ BDDV_Init(256, env_nmax);}
1373         init_cnt++;
1374
1375         VALUE v1,v2,v3,v4;
1376         CtoI *ctoi_fin; 
1377         rb_scan_args(argc, argv,"40",&v1,&v2,&v3,&v4);
1378         if(TYPE(v1)!=T_STRING){
1379                 rb_raise(rb_eRuntimeError,"argument type error (1st argument must be STRING)");
1380         }
1381         if(TYPE(v2)!=T_STRING){
1382                 rb_raise(rb_eRuntimeError,"argument type error (1st argument must be STRING)");
1383         }
1384         if(TYPE(v3)!=T_FIXNUM){
1385                 rb_raise(rb_eRuntimeError,"argument type error (3rd argument must be FIXNUM)");
1386         }
1387         if(TYPE(v4)!=T_FIXNUM){
1388                 rb_raise(rb_eRuntimeError,"argument type error (4th argument must be FIXNUM)");
1389         }
1390         char *arg1 = RSTRING_PTR(v1);
1391         char *arg2 = RSTRING_PTR(v2);
1392         int arg3_fix = FIX2INT(v3);
1393         int len_ub = FIX2INT(v4);
1394
1395         int len;
1396
1397         len = strlen(arg1);
1398         char *str_c = new char[len+3];
1399         sprintf(str_c,"\"%s\"",arg1);
1400         int len_c = len+2;
1401
1402         len = strlen(arg2);
1403         char *str_d = new char[len+3];
1404         sprintf(str_d,"\"%s\"",arg2);
1405         int len_d = len+2;
1406
1407         char *str_e = new char[64];
1408         sprintf(str_e,"%d",arg3_fix);
1409               str_c[len_c - 1] = 0;
1410       str_d[len_d - 1] = 0;
1411       int th = atoi(str_e);
1412            if(strcmp(str_c+1, "F" ) == 0) CtoI_Lcm1_ub(str_d+1, 0, th,  0, len_ub);
1413       else if(strcmp(str_c+1, "C" ) == 0) CtoI_Lcm1_ub(str_d+1, 0, th,  1, len_ub);
1414       else if(strcmp(str_c+1, "M" ) == 0) CtoI_Lcm1_ub(str_d+1, 0, th,  2, len_ub);
1415       else if(strcmp(str_c+1, "FQ") == 0) CtoI_Lcm1_ub(str_d+1, 0, th, 10, len_ub);
1416       else if(strcmp(str_c+1, "CQ") == 0) CtoI_Lcm1_ub(str_d+1, 0, th, 11, len_ub);
1417       else if(strcmp(str_c+1, "MQ") == 0) CtoI_Lcm1_ub(str_d+1, 0, th, 12, len_ub); //11 -> 12 by ham
1418       for(int i=VTable.Used(); i<CtoI_LcmItems(); i++)
1419       {
1420         int t = 1;
1421         char s[32];
1422         int x = CtoI_LcmPerm(i);
1423         sprintf(s, "x%d", x);
1424         while(VTable.GetID(s) != 0)
1425         {
1426           t++;
1427           sprintf(s, "x%d_%d", x, t);
1428         }
1429         VTable.SetT(s, power16/2);
1430       }
1431       CtoI a = CtoI_Lcm2();
1432       ctoi_fin = new CtoI(a);
1433       delete[] str_c;
1434       delete[] str_d;
1435       delete[] str_e;
1436
1437         Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
1438         rmod_rtn->cmod = ctoi_fin;
1439         return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
1440 }
1441
1442
1443 VALUE vsop_lcm_order_ub(int argc, VALUE *argv, VALUE self){
1444         if(init_cnt==0){ BDDV_Init(256, env_nmax);}
1445         init_cnt++;
1446
1447         VALUE v1,v2,v3,v4,v5;
1448         CtoI *ctoi_fin; 
1449         rb_scan_args(argc, argv,"50",&v1,&v2,&v3,&v4,&v5);
1450         if(TYPE(v1)!=T_STRING){
1451                 rb_raise(rb_eRuntimeError,"argument type error (1st argument must be STRING)");
1452         }
1453         if(TYPE(v2)!=T_STRING){
1454                 rb_raise(rb_eRuntimeError,"argument type error (1st argument must be STRING)");
1455         }
1456         if(TYPE(v3)!=T_FIXNUM){
1457                 rb_raise(rb_eRuntimeError,"argument type error (3rd argument must be FIXNUM)");
1458         }
1459         if(TYPE(v4)!=T_STRING){
1460                 rb_raise(rb_eRuntimeError,"argument type error (4th argument must be STRING)");
1461         }
1462         if(TYPE(v5)!=T_FIXNUM){
1463                 rb_raise(rb_eRuntimeError,"argument type error (5th argument must be FIXNUM)");
1464         }
1465         char *arg1 = RSTRING_PTR(v1);
1466         char *arg2 = RSTRING_PTR(v2);
1467         int arg3_fix = FIX2INT(v3);
1468         char *arg4 = RSTRING_PTR(v4);
1469
1470         int len_ub = FIX2INT(v5);
1471
1472         int len;
1473
1474         len = strlen(arg1);
1475         char *str_c = new char[len+3];
1476         sprintf(str_c,"\"%s\"",arg1);
1477         int len_c = len+2;
1478
1479         len = strlen(arg2);
1480         char *str_d = new char[len+3];
1481         sprintf(str_d,"\"%s\"",arg2);
1482         int len_d = len+2;
1483
1484         char *str_e = new char[64];
1485         sprintf(str_e,"%d",arg3_fix);
1486
1487         len = strlen(arg4);
1488         char *str_f = new char[len+3];
1489         sprintf(str_f,"\"%s\"",arg4);
1490         int len_f = len+2;
1491
1492               str_c[len_c - 1] = 0;
1493       str_d[len_d - 1] = 0;
1494       int th = atoi(str_e);
1495       str_f[len_f - 1] = 0;
1496            if(strcmp(str_c+1, "F" ) == 0) CtoI_Lcm1_ub(str_d+1, str_f+1, th,  0, len_ub);
1497       else if(strcmp(str_c+1, "C" ) == 0) CtoI_Lcm1_ub(str_d+1, str_f+1, th,  1, len_ub);
1498       else if(strcmp(str_c+1, "M" ) == 0) CtoI_Lcm1_ub(str_d+1, str_f+1, th,  2, len_ub);
1499       else if(strcmp(str_c+1, "FQ") == 0) CtoI_Lcm1_ub(str_d+1, str_f+1, th, 10, len_ub);
1500       else if(strcmp(str_c+1, "CQ") == 0) CtoI_Lcm1_ub(str_d+1, str_f+1, th, 11, len_ub);
1501       else if(strcmp(str_c+1, "MQ") == 0) CtoI_Lcm1_ub(str_d+1, str_f+1, th, 12, len_ub);
1502       for(int i=VTable.Used(); i<CtoI_LcmItems(); i++)
1503       {
1504         int t = 1;
1505         char s[32];
1506         int x = CtoI_LcmPerm(i);
1507         sprintf(s, "x%d", x);
1508         while(VTable.GetID(s) != 0)
1509         {
1510           t++;
1511           sprintf(s, "x%d_%d", x, t);
1512         }
1513         VTable.SetT(s, power16/2);
1514       }
1515       CtoI a = CtoI_Lcm2();
1516       ctoi_fin = new CtoI(a);
1517       delete[] str_c;
1518       delete[] str_d;
1519       delete[] str_e;
1520       delete[] str_f;
1521
1522
1523         Vsop_Ruby *rmod_rtn = new Vsop_Ruby;
1524         rmod_rtn->cmod = ctoi_fin;
1525         return Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod_rtn);
1526 }
1527
1528
1529
1530 /*
1531  * call-seq:
1532  *  ZDD.lcm_ub() -> zdd : lcm over zdd(最大サポート指定可能)
1533  *
1534  * === 説明
1535  *
1536  * === 関連
1537  *  show        
1538  */
1539 VALUE vsop_lcm_ub(int argc, VALUE *argv, VALUE self){
1540         VALUE rtnval;
1541         if(argc==5){
1542                 rtnval = vsop_lcm_order_ub(argc,argv,self);
1543         }
1544         else{
1545                 rtnval = vsop_lcm_nomal_ub(argc,argv,self);
1546         }
1547         return rtnval;
1548 }
1549
1550 // ------------------------------ パターン長制約を入れたlcm over zdd ここまで 2010/02/28
1551 // print関係
1552
1553 /*
1554  * call-seq:
1555  *  zdd.map -> self : カルノー図の表示
1556  *
1557  *  zdd    : ZDD Object
1558  *
1559  * === 説明
1560  *  zddのカルノー図を標準出力に表示する。
1561  *  アイテム数は6個まで表示できる。
1562  *
1563  * === 例
1564  *  > a=2*ZDD.itemset("a b")+3*ZDD.itemset("b")+4
1565  *  > a.show
1566  *  2 a b + 3 b + 4
1567  *
1568  *  > a.map
1569  *  a : b
1570  *      |     0     1
1571  *    0 |     4     3
1572  *    1 |     0     2
1573  *
1574  *  # アイテムaが1列目のビット列に、アイテムbが1行目のビット列に対応してアイテム集合が表現されている。
1575  *  # セルの値は重みを表す。左上のセルはaが0、bが0、すなわち定数項が4であることが示されている。
1576  *
1577  *  # 4アイテムでは以下の通り。
1578  *  > a=ZDD.itemset("a b")+2*ZDD.itemset("b c")+3*ZDD.itemset("d")+4
1579  *  > a.show
1580  *  a b + 2 b c + 3 d + 4
1581  *
1582  *  > a.map
1583  *  a b : c d
1584  *      |    00    01    11    10
1585  *   00 |     4     3     0     0
1586  *   01 |     0     0     0     2
1587  *   11 |     1     0     0     0
1588  *   10 |     0     0     0     0
1589  *
1590  * === 関連
1591  *  rmap
1592  */
1593 VALUE vsop_print_map(int argc, VALUE *argv, VALUE self){
1594         Vsop_Ruby* rmod;
1595         Data_Get_Struct(self,Vsop_Ruby,rmod);
1596         //引数読み込み
1597         VALUE *v;
1598         rb_scan_args(argc, argv,"01",&v);
1599         if(argc!=0){
1600                 if(TYPE(v)==T_STRING){
1601                         char *str = RSTRING_PTR(v);
1602                         bout.Set(str);
1603                 }
1604                 else{
1605                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
1606                 }
1607         }
1608
1609         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
1610         CtoI *ctoitmp = auto_p.get();
1611         if(MapAll(*ctoitmp) == 1){
1612                 rb_raise(rb_eRuntimeError,"01Memory overflow");
1613         }
1614
1615         bout.Unset();
1616
1617         return self;
1618 }
1619
1620 /*
1621  * call-seq:
1622  *  zdd.rmap -> self : 冗長性を排除したカルノー図の表示
1623  *
1624  *  zdd    : ZDD Object
1625  *
1626  * === 説明
1627  *  zddのカルノー図を標準出力に表示する。ただし、使われていないアイテムは省いて表示される。
1628  *
1629  * === 例
1630  *  # 4つのアイテムa,b,c,dを宣言
1631  *  > ZDD.symbol("a")
1632  *  > ZDD.symbol("b")
1633  *  > ZDD.symbol("c")
1634  *  > ZDD.symbol("d")
1635  *  # a,b,cのみ利用したZDD
1636  *  > a=ZDD.itemset("a b")+2*ZDD.itemset("b c")+4
1637  *  > a.show
1638  *  a b + 2 b c + 4
1639  *
1640  *  # mapで表示させると以下の通り。
1641  *  > a.map
1642  *  a b : c d
1643  *      |    00    01    11    10
1644  *   00 |     4     0     0     0
1645  *   01 |     0     0     0     2
1646  *   11 |     1     0     0     0
1647  *   10 |     0     0     0     0
1648  * 
1649  *  # rmapで表示させるとdが省かれて表示される。
1650  *  > a.rmap
1651  *  a : b c
1652  *      |    00    01    11    10
1653  *    0 |     4     0     2     0
1654  *    1 |     0     0     0     1
1655  * === 関連
1656  *  map
1657  */
1658 VALUE vsop_print_rmap(int argc, VALUE *argv, VALUE self){
1659         Vsop_Ruby* rmod;
1660         Data_Get_Struct(self,Vsop_Ruby,rmod);
1661         //引数読み込み
1662         VALUE *v;
1663         rb_scan_args(argc, argv,"01",&v);
1664         if(argc!=0){
1665                 if(TYPE(v)==T_STRING){
1666                         char *str = RSTRING_PTR(v);
1667                         bout.Set(str);
1668                 }
1669                 else{
1670                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
1671                 }
1672         }
1673
1674         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
1675         CtoI *ctoitmp = auto_p.get();
1676         if(MapSel(*ctoitmp) == 1){
1677                 rb_raise(rb_eRuntimeError,"02Memory overflow");
1678         }
1679
1680         bout.Unset();
1681         return self;
1682 }        
1683
1684 /*
1685  * call-seq:
1686  *  zdd.hex -> self : 16進数表現積和表示
1687  *
1688  *  zdd    : ZDD Object
1689  *
1690  * === 説明
1691  *  係数を16進数で表現し積和形で標準出力に出力する。
1692  *
1693  * === 例
1694  *  > a=ZDD.itemset("a b")+11*ZDD.itemset("b c")+30*ZDD.itemset("d")+4
1695  *  > a.show
1696  *  a b + 11 b c + 30 d + 4
1697  *  > a.hex
1698  *  a b + B b c + 1E d + 4
1699  *
1700  * === 関連
1701  *  show
1702  */
1703 VALUE vsop_print_hex(int argc, VALUE *argv, VALUE self){
1704         Vsop_Ruby* rmod;
1705         Data_Get_Struct(self,Vsop_Ruby,rmod);
1706         //引数読み込み
1707         VALUE *v;
1708         rb_scan_args(argc, argv,"01",&v);
1709         if(argc!=0){
1710                 if(TYPE(v)==T_STRING){
1711                         char *str = RSTRING_PTR(v);
1712                         bout.Set(str);
1713                 }
1714                 else{
1715                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
1716                 }
1717         }
1718         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
1719         CtoI *ctoitmp = auto_p.get();
1720         if(PrintCtoI_16(*ctoitmp) == 1){
1721                 rb_raise(rb_eRuntimeError,"03Memory overflow");
1722         }
1723         bout.Unset();
1724         return self;
1725 }      
1726
1727 /*
1728  * call-seq:
1729  * zdd.bit -> self : 重みの(-2)進数の各桁別アイテム集合の表示
1730  *
1731  *  zdd    : ZDD Object
1732  *
1733  * === 説明
1734  *  ZDDでは重みをマイナス2進数で表現し、各桁ごとにZDDを生成している。
1735  *  このメソッドにより各桁別に、そのZDDに登録されているアイテム集合を標準出力に出力できる。
1736  *
1737  * === 例
1738  *  > a=5*ZDD.itemset("a b c")+3*ZDD.itemset("a b")+2*ZDD.itemset("b c")+1*ZDD.it
1739  *  > a.show
1740  *  5 a b c - 3 a b + 2 b c + c
1741  *
1742  *  > a.bit
1743  *  3: a b
1744  *  2: a b c + a b + b c
1745  *  1: b c
1746  *  0: a b c + a b + c
1747  *
1748  *  # "a b c"の重み5の(-2)進数は101となる。
1749  *  # 1*(-2)^2+0*(-2)^1+1*(-2)^0 = 5
1750  *  # よって0桁目と2桁目にアイテム集合"a b c"が表示されている。
1751  *  # "a b"の重み-3の(-2)進数は1101となる。
1752  *  # 1*(-2)^3+1*(-2)^2+0*(-2)^1+1*(-2)^0 = -3
1753  *  # よって0,2,3桁目にアイテム集合"a b"が表示されている。
1754  */
1755 VALUE vsop_print_bit(int argc, VALUE *argv, VALUE self){
1756         Vsop_Ruby* rmod;
1757         Data_Get_Struct(self,Vsop_Ruby,rmod);
1758         //引数読み込み
1759         VALUE *v;
1760         rb_scan_args(argc, argv,"01",&v);
1761         if(argc!=0){
1762                 if(TYPE(v)==T_STRING){
1763                         char *str = RSTRING_PTR(v);
1764                         bout.Set(str);
1765                 }
1766                 else{
1767                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
1768                 }
1769         }
1770         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
1771         CtoI *ctoitmp = auto_p.get();
1772         if(PrintDigital(*ctoitmp) == 1){
1773                 rb_raise(rb_eRuntimeError,"04Memory overflow");
1774         }
1775         bout.Unset();
1776         return self;
1777 }        
1778
1779 /*
1780  * call-seq:
1781  * zdd.case -> self : 重み別アイテム集合の表示
1782  *
1783  *  zdd    : ZDD Object
1784  *
1785  * === 説明
1786  *  重みの値別にアイテム集合を標準出力に出力する。
1787  *    
1788  * === 例
1789  *  > a=5*ZDD.itemset("a b c")+3*ZDD.itemset("a b")+2*ZDD.itemset("b c")+1*ZDD.it
1790  *  > a.show
1791  *  5 a b c - 3 a b + 2 b c + c
1792  *
1793  *  > a.case
1794  *  5:  a b c
1795  *  2:  b c
1796  *  1:  c
1797  *  -3:  a b
1798  *
1799  * === 関連
1800  *  show        
1801  */
1802 VALUE vsop_print_case(int argc, VALUE *argv, VALUE self){
1803         Vsop_Ruby* rmod;
1804         Data_Get_Struct(self,Vsop_Ruby,rmod);
1805         //引数読み込み
1806         VALUE *v;
1807         rb_scan_args(argc, argv,"01",&v);
1808         if(argc!=0){
1809                 if(TYPE(v)==T_STRING){
1810                         char *str = RSTRING_PTR(v);
1811                         bout.Set(str);
1812                 }
1813                 else{
1814                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
1815                 }
1816         }
1817
1818         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
1819         CtoI *ctoitmp = auto_p.get();
1820         if(PrintCase(*ctoitmp) == 1){
1821                 rb_raise(rb_eRuntimeError,"05Memory overflow");
1822         }
1823
1824         bout.Unset();
1825         return self;
1826 }        
1827
1828
1829 /*
1830  * call-seq:
1831  * zdd1.same?(zdd2) -> bool : 等価比較
1832  * zdd1 ===    (zdd2) -> bool : 等価比較
1833  *
1834  *  bool   : Qtrue or Qfalse
1835  *  zdd1,zdd2 : ZDD Object
1836  *
1837  * === 説明
1838  * zdd1とzdd2を比較し、同じならtrue、異なるならfalseを返す
1839  *  
1840  * === 関連
1841  *  diff? 
1842  */
1843  VALUE vsop_same(int argc, VALUE *argv,VALUE self){
1844         Vsop_Ruby* rmod;
1845         VALUE v;
1846         Data_Get_Struct(self,Vsop_Ruby,rmod);
1847         rb_scan_args(argc, argv,"10",&v);
1848         
1849         CtoI *ctoi_modc = value2ctoi(v);
1850         if ( *rmod->cmod == *ctoi_modc){
1851                 return Qtrue;
1852         } 
1853         else{
1854                 return  Qfalse;
1855         }
1856 }
1857
1858 /*
1859  * call-seq:
1860  * zdd1.diff?(zdd2) -> bool :  不等価比較
1861  *
1862  *  bool   : Qtrue or Qfalse
1863  *  zdd1,zdd2 : ZDD Object
1864  *
1865  * === 説明
1866  * zdd1とzdd2を比較し、同じならfalse、異なるならtrueを返す
1867  * 
1868  * === 関連
1869  *  same? ,=== 
1870  */
1871 VALUE vsop_diff(int argc, VALUE *argv,VALUE self){
1872         Vsop_Ruby* rmod;
1873         VALUE v;
1874         Data_Get_Struct(self,Vsop_Ruby,rmod);
1875         rb_scan_args(argc, argv,"10",&v);
1876         
1877         CtoI *ctoi_modc = value2ctoi(v);
1878         if ( *rmod->cmod != *ctoi_modc){
1879                 return Qtrue;
1880         } 
1881         else{
1882                 return  Qfalse;
1883         }
1884 }
1885
1886
1887 /*
1888  * call-seq:
1889  * zdd.size -> nodeSize : ZDD節点数
1890  *
1891  *  zdd      : ZDD Object
1892  *  nodeSize : Ruby Integer
1893  *
1894  * === 説明
1895  * zddの節点数を返す。
1896  *
1897  * === 例
1898  *  > a=5*ZDD.ƒ("a b c")-3*ZDD.itemset("a b")+2*ZDD.itemset("b c")+1*ZDD.itemset("c")
1899  *  > a.show
1900  *  5 a b c - 3 a b + 2 b c + c
1901  *
1902  *  > puts a.size
1903  *  10
1904  *
1905  * === 関連 
1906  *  totalsize
1907  */
1908 VALUE vsop_print_size( VALUE self){
1909         Vsop_Ruby* rmod;
1910         Data_Get_Struct(self,Vsop_Ruby,rmod);
1911         int val = rmod->cmod->Size();
1912         return INT2NUM(val);
1913 }        
1914
1915 /*
1916  * call-seq:
1917  * ZDD.totalsize -> nodeSize : 処理系全体のZDD節点数
1918  *
1919  *  nodeSize : Ruby Integer
1920  *
1921  * === 説明
1922  *  動作中のrubyインタープリタ上で構築された全ZDDオブジェクトの節点数を返す。
1923  *
1924  * === 例
1925  *  > a=5*ZDD.itemset("a b c")-3*ZDD.itemset("a b")+2*ZDD.itemset("b c")+1*ZDD.itemset("c")
1926  *  > a.show
1927  *  5 a b c - 3 a b + 2 b c + c
1928  *  > puts a.size
1929  *  10
1930  *  > puts ZDD.totalsize
1931  *  10
1932  *
1933  *  > b=-3*ZDD.itemset("a c")
1934  *  > b.show
1935  *  - 3 a c
1936  *  > puts b.size
1937  *  5
1938  *  > puts ZDD.nodesize
1939  *  14
1940  *
1941  * === 関連 
1942  *  size
1943  */
1944 VALUE vsop_print_totalsize(VALUE self){
1945         rb_gc();
1946         BDD_GC();
1947         VALUE rtn = INT2NUM(BDD_Used());
1948
1949         return rtn;
1950 }        
1951
1952 /*
1953  * call-seq:
1954  * zdd.count -> numItemsets : 項数計算
1955  *
1956  *  numItemsets : Ruby Integer
1957  *
1958  * === 説明
1959  *  zddに格納された項の数(アイテム集合の数)を返す。
1960  * 
1961  * === 例
1962  *  > A=ZDD.itemset("a")
1963  *  > B=ZDD.itemset("b")
1964  *  > F=A+B+A*B
1965  *  > F.show
1966  *  a b + a + b
1967  *  > puts F.count
1968  *  3
1969  *
1970  *  > G=A+B+A*B+1
1971  *  > G.show
1972  *  a b + a + b + 1
1973  *  > puts G.count
1974  *  4
1975  *
1976  *  > c=ZDD.constant(0)
1977  *  > puts c.count
1978  *  0
1979  *
1980  *  > d=ZDD.constant(1)
1981  *  > puts d.count
1982  *  1
1983  */
1984
1985 VALUE vsop_print_count( VALUE self){
1986         Vsop_Ruby* rmod;
1987         Data_Get_Struct(self,Vsop_Ruby,rmod);
1988         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
1989         CtoI *ctoitmp = auto_p.get();
1990         *ctoitmp = ctoitmp -> CountTerms();
1991         if(*ctoitmp == CtoI_Null())
1992         {
1993                 *ctoitmp = 0;
1994                 rb_raise(rb_eRuntimeError,"06Memory overflow");
1995         }
1996         int slen = ctoitmp->TopDigit() / 3 + 14;
1997         kgAutoPtr2<char> a_ptr;
1998         char *s;
1999         try{
2000                 a_ptr.set(new char[slen]);
2001                 s = a_ptr.get();
2002         }catch(...){
2003                 rb_raise(rb_eRuntimeError,"memory allocation error");
2004         }
2005         ctoitmp -> StrNum10(s);
2006 //      VALUE rtn = LL2NUM(atoll(s));    
2007         VALUE rtn = rb_cstr_to_inum(s, 10, Qfalse);
2008         return rtn;
2009 }        
2010
2011 /*
2012  * call-seq:
2013  * zdd.density -> dens : ZDDの濃度計算
2014  *
2015  *  dens : Ruby Float
2016  *
2017  * === 説明
2018  *  濃度とは、登録されている全アイテムから構成可能なアイテム集合の総数に対するzddに格納されたアイテム集合の数の割合と定義される。
2019  *
2020  * === 例
2021  *  > a=ZDD.itemset("a")
2022  *  > b=ZDD.itemset("b")
2023  *  > c=ZDD.itemset("c")
2024  *
2025  *  # a,b,cの3アイテムを使った全組合せ数は8通り。
2026  *  # 以下で、Fにはそのすべての組合せが格納されているので濃度は1.0となる。
2027  *  > F=(a+1)*(b+1)*(c+1)
2028  *  > F.show
2029  *   a b c + a b + a c + a + b c + b + c + 1
2030  *  > puts F.density
2031  *  1.0
2032  *
2033  *  # 以下で、Fには1通りの組合せ(a b)が格納されているので濃度は1/8=0.125となる。
2034  *  > F=a*b
2035  *  > F.show
2036  *   a b
2037  *  > puts F.density
2038  *  0.125
2039  *
2040  *  # 以下で、Fには3通りの組合せ(a b,a,b)が格納されているので濃度は3/8=0.375となる。
2041  *  > F+=a
2042  *  > F+=b
2043  *  > F.show
2044  *   a b + a + b
2045  *  > puts F.density
2046  *  0.375
2047  */
2048
2049 VALUE vsop_print_density( VALUE self){
2050         Vsop_Ruby* rmod;
2051         Data_Get_Struct(self,Vsop_Ruby,rmod);
2052         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
2053         CtoI *ctoitmp = auto_p.get();
2054
2055         *ctoitmp = ctoitmp -> NonZero();
2056         if(*ctoitmp == CtoI_Null())
2057         {
2058                 *ctoitmp = 0;
2059                 rb_raise(rb_eRuntimeError,"07Memory overflow");
2060         }
2061         int d = Density(ctoitmp -> GetZBDD(), VTable.Used());
2062         if(d == 0 && *ctoitmp != 0){
2063                 rb_raise(rb_eRuntimeError,"Bit underflow occurred");
2064         }
2065         VALUE rtn = rb_float_new((float)d / power30);
2066         return rtn;
2067 }
2068
2069 /*
2070  * call-seq:
2071  * zdd.value -> cost : アイテムの値による式の評価
2072  *
2073  *  cost : Ruby Float
2074  *
2075  * === 説明
2076  *  アイテムに設定された値(symbolメソッドを参照のこと)をzddの各アイテムに代入したときの式の値を返す(この値をコストと呼ぶ)。
2077  *
2078  * === 例
2079  *  # シンボルa, b, cに値1.0, 0.5, 1.8をそれぞれ与える。
2080  *  > ZDD.symbol("a",1.0)
2081  *  > ZDD.symbol("b",0.5)
2082  *  > ZDD.symbol("c",2.0)
2083  *
2084  *  > a=ZDD.itemset("a")
2085  *  > b=ZDD.itemset("b")
2086  *  > c=ZDD.itemset("c")
2087  *
2088  *  # 式は1つのシンボルaから構成されa=1.0
2089  *  > puts a.value
2090  *   a
2091  *  > puts f.value
2092  *  1.5
2093  *
2094  *  # 式"a b"にa=1.0,b=0.5を代入すると1.0*0.5=0.5
2095  *  > f*=b
2096  *  > f.show
2097  *   a b
2098  *  > puts f.value
2099  *  0.5
2100  *
2101  *  # 式"a b + 2 a + c + 3"にa=1.0,b=0.5,c=2.0を代入すると 1.0*0.5+2*1.0+2.0+3=7.5
2102  *  > f+=2*a + c + 3
2103  *  > f.show
2104  *   a b + 2 a + c + 3
2105  *  > puts f.value
2106  *   7.5
2107  *
2108  * === 関連 
2109  *  itemset,maxcover,maxcost,mincover,mincost
2110  */
2111
2112 VALUE vsop_print_value( VALUE self){
2113         Vsop_Ruby* rmod;
2114         Data_Get_Struct(self,Vsop_Ruby,rmod);
2115         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
2116         CtoI *ctoitmp = auto_p.get();
2117         
2118         if(OVF.Check()!= 0){
2119                 rb_raise(rb_eRuntimeError,"Bit overflow occurred");
2120         }
2121         VALUE rtn = rb_float_new((float)Value(*ctoitmp)/power16);
2122         return rtn;
2123 }        
2124
2125 /*
2126  * call-seq:
2127  * zdd.maxcover -> self : コスト最大のアイテム集合の表示
2128  *
2129  *  zdd  : ZDD Object
2130  *
2131  * === 説明
2132  *  zddに含まれるアイテム集合の中で、コストが最大となるアイテム集合を表示する。
2133  *  そのコストの値を表示するにはzdd.maxcostを用いる。
2134  *
2135  * === 例
2136  *  > ZDD.symbol("a",1.0)
2137  *  > ZDD.symbol("b",0.5)
2138  *  > ZDD.symbol("c",2.0)
2139  *
2140  *  > a=ZDD.itemset("a")
2141  *  > b=ZDD.itemset("b")
2142  *  > c=ZDD.itemset("c")
2143  *
2144  *  > f=a*b + b*c + c*a
2145  *  > f.show
2146  *  # a b のコスト=1.0+0.5=1.5
2147  *  # b c のコスト=0.5+2.0=2.5
2148  *  # c a のコスト=2.0+1.0=3.0
2149  *  > puts f.maxcover
2150  *  a c
2151  *  > puts f.maxcost
2152  *  3.0
2153  *  > puts f.mincover
2154  *  a b
2155  *  > puts f.mincost
2156  *  1.5
2157  *
2158  * === 関連 
2159  *  symbol
2160  *  value
2161  *  maxcost
2162  *  mincover
2163  *  mincost
2164  */
2165 VALUE vsop_print_maxcover(int argc, VALUE *argv, VALUE self){
2166         Vsop_Ruby* rmod;
2167         Data_Get_Struct(self,Vsop_Ruby,rmod);
2168         //引数読み込み
2169         VALUE *v;
2170         rb_scan_args(argc, argv,"01",&v);
2171         if(argc!=0){
2172                 if(TYPE(v)==T_STRING){
2173                         char *str = RSTRING_PTR(v);
2174                         bout.Set(str);
2175                 }
2176                 else{
2177                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
2178                 }
2179         }
2180
2181         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
2182         CtoI *ctoitmp = auto_p.get();
2183         
2184         *ctoitmp = ctoitmp -> NonZero();
2185         if(*ctoitmp == CtoI_Null())
2186         {
2187                 *ctoitmp = 0;
2188                 rb_raise(rb_eRuntimeError,"08Memory overflow");
2189         }
2190         if(*ctoitmp == 0){
2191                 bout << "  0";
2192         }
2193         else
2194         {
2195                 ZBDD f = ctoitmp -> GetZBDD();
2196                 if(MaxCost(f)==0){
2197                         bout << "  1";
2198                 }
2199                 else
2200                 {
2201 //                      bout << "<Items>: ";
2202                         while(1)
2203                         {
2204                                 int var = f.Top();
2205                                 if(var == 0) break;
2206                                 ZBDD f0 = f.OffSet(var);
2207                                 ZBDD f1 = f.OnSet0(var);
2208                                 int c1 = MaxCost(f1) + VTable.GetValue(var);
2209                                 if(MaxCost(f0) < c1)
2210                                 {
2211                                         bout << VTable.GetName(var);
2212                                         bout.Delimit();
2213                                         f = f1;
2214                                 }
2215                                 else f = f0;
2216                         }
2217                 }
2218         }
2219         bout.Return();
2220         bout.Unset();
2221
2222         return self;
2223 }        
2224
2225 /*
2226  * call-seq:
2227  * zdd.maxcost -> cost : コスト最大のアイテム集合のコスト値を返す
2228  *
2229  *  zdd  : ZDD Object
2230  *  cost : Ruby Float
2231  *
2232  * ===  説明,例
2233  *  maxcoverメソッドを参照のこと。
2234  *
2235  * === 関連 
2236  *  symbol
2237  *  value
2238  *  maxcover
2239  *  mincover
2240  *  mincost
2241  */
2242 VALUE vsop_print_maxcost( VALUE self){
2243         Vsop_Ruby* rmod;
2244         Data_Get_Struct(self,Vsop_Ruby,rmod);
2245         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
2246         CtoI *ctoitmp = auto_p.get();
2247
2248         *ctoitmp = ctoitmp -> NonZero();
2249         if(*ctoitmp == CtoI_Null())
2250         {
2251                 *ctoitmp = 0;
2252                 rb_raise(rb_eRuntimeError,"09Memory overflow");
2253         }
2254         VALUE rtn;
2255         if(*ctoitmp == 0){
2256                 rtn =   Qnil;
2257         }
2258         else
2259         {
2260                 int c = MaxCost(ctoitmp -> GetZBDD());
2261                 rtn = rb_float_new((float)c/power16);
2262         }
2263         return rtn;
2264 }        
2265
2266 /*
2267  * call-seq:
2268  * zdd.mincover -> self : コスト最小のアイテム集合の表示
2269  *
2270  *  zdd  : ZDD Object
2271  *
2272  * ===  説明,例
2273  *  maxcoverメソッドを参照のこと。
2274  *
2275  * === 関連 
2276  *  symbol
2277  *  value
2278  *  maxcover
2279  *  maxcost
2280  *  mincost
2281  */
2282 VALUE vsop_print_mincover(int argc, VALUE *argv, VALUE self){
2283         Vsop_Ruby* rmod;
2284         Data_Get_Struct(self,Vsop_Ruby,rmod);
2285         VALUE *v;
2286         rb_scan_args(argc, argv,"01",&v);
2287         if(argc!=0){
2288                 if(TYPE(v)==T_STRING){
2289                         char *str = RSTRING_PTR(v);
2290                         bout.Set(str);
2291                 }
2292                 else{
2293                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
2294                 }
2295         }
2296
2297         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
2298         CtoI *ctoitmp = auto_p.get();
2299         
2300         *ctoitmp = ctoitmp -> NonZero();
2301         if(*ctoitmp == CtoI_Null())
2302         {
2303                 *ctoitmp = 0;
2304                 rb_raise(rb_eRuntimeError,"10Memory overflow");
2305         }
2306         if(*ctoitmp == 0){
2307                 bout << "  0";
2308         }
2309         else
2310         {
2311                 ZBDD f = ctoitmp -> GetZBDD();
2312                 if(MinCost(f)==0){
2313                         bout << "  1";
2314                 }
2315                 else
2316                 {
2317 //                      bout << "<Items>: ";
2318                         while(1)
2319                         {
2320                                 int var = f.Top();
2321                                 if(var == 0) break;
2322                                 ZBDD f0 = f.OffSet(var);
2323                                 ZBDD f1 = f.OnSet0(var);
2324                                 int c1 = MinCost(f1) + VTable.GetValue(var);
2325                                 if(MinCost(f0) > c1)
2326                                 {
2327                                         bout << VTable.GetName(var);
2328                                         bout.Delimit();
2329                                         f = f1;
2330                                 }
2331                                 else f = f0;
2332                         }
2333                 }
2334         }
2335         bout.Return();
2336         bout.Unset();
2337         return self;
2338 }        
2339
2340 /*
2341  * call-seq:
2342  * zdd.mincost -> cost : コスト最小のアイテム集合のコストを返す
2343  *
2344  *  zdd  : ZDD Object
2345  *  cost : Ruby Float
2346  *
2347  * ===  説明,例
2348  *  maxcoverメソッドを参照のこと。
2349  *
2350  * === 関連 
2351  *  symbol
2352  *  value
2353  *  maxcover
2354  *  maxcost
2355  *  mincover
2356  */
2357 VALUE vsop_print_mincost( VALUE self){
2358         Vsop_Ruby* rmod;
2359         Data_Get_Struct(self,Vsop_Ruby,rmod);
2360         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
2361         CtoI *ctoitmp = auto_p.get();
2362         
2363         *ctoitmp = ctoitmp -> NonZero();
2364         if(*ctoitmp == CtoI_Null())
2365         {
2366                 *ctoitmp = 0;
2367                 rb_raise(rb_eRuntimeError,"11Memory overflow");
2368         }
2369         VALUE rtn;
2370         if(*ctoitmp == 0){
2371                 rtn = Qnil;
2372         }
2373         else
2374         {
2375                 int c = MinCost(ctoitmp -> GetZBDD());
2376                 rtn = rb_float_new((float)c/power16);
2377         }
2378         return rtn;
2379 }        
2380
2381 /*
2382  * call-seq:
2383  * zdd.decomp([fileName]) -> self : 単純直交分解形式での出力
2384  *
2385  *  zdd      : ZDD Object
2386  *  fileName : Ruby String
2387  *
2388  * === 説明
2389  *  zddを単純直交分解(simple disjoint decomposition)形式で出力する。
2390  *  fileNameの指定があれば、そのファイルに出力する。
2391  *  省略すれば標準出力に出力する。
2392  *
2393  * === 例
2394  *  > a=ZDD.itemset("a")
2395  *  > b=ZDD.itemset("b")
2396  *  > c=ZDD.itemset("c")
2397  *
2398  *  > f1=(a*b*c)
2399  *  > f1.show
2400  *   a b c
2401  *  > f1.decomp
2402  *  AND( a b c )
2403  * # a,b,cのANDということでa*b*c=a b c
2404  *
2405  *  > f2=((a*b*c)+(a*b))
2406  *  > f2.show
2407  *   a b c + a b
2408  *  > f2.decomp
2409  *  AND( a b OR( c 1 ) )
2410  *  # c,1のORにて(c+1)、それとa bとのANDで(a b)*(c+1)=a b c + a b
2411  *
2412  *  > f3=((a*b*c)+(a*b)+(b*c))
2413  *  > f3.show
2414  *   a b c + a b + b c
2415  *  > f3.decomp
2416  *  AND( [ a c ] b )
2417  *  # [ a c ]はaとcによる全組合せ集合、すなわち(a c + a + c)。
2418  *  # それとbとのANDで b*(a c + a + c) = a b c + a b + b c
2419  *
2420  *  > f4=((a*b*c)+(a*b)+(b*c)+(c*a))
2421  *  > f4.show
2422  *   a b c + a b + a c + b c
2423  *  > f4.decomp
2424  *  [ a b c ]
2425  *  # [ a b c ]はa,b,cによる全組合せ集合、すなわち(a b c + a b + b c + c a)
2426  */
2427
2428 VALUE vsop_print_decomp(int argc, VALUE *argv, VALUE self){
2429         Vsop_Ruby* rmod;
2430         Data_Get_Struct(self,Vsop_Ruby,rmod);
2431         VALUE *v;
2432         rb_scan_args(argc, argv,"01",&v);
2433         if(argc!=0){
2434                 if(TYPE(v)==T_STRING){
2435                         char *str = RSTRING_PTR(v);
2436                         bout.Set(str);
2437                 }
2438                 else{
2439                         rb_raise(rb_eRuntimeError,"argument type error (arguments must be STRING)");
2440                 }
2441         }
2442
2443         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
2444         CtoI *ctoitmp = auto_p.get();
2445
2446         if(PrintDecomp(*ctoitmp) == 1)
2447         {
2448                 rb_raise(rb_eRuntimeError,"12Memory overflow");
2449         }
2450         bout.Unset();
2451         return self;
2452 }        
2453
2454 /*
2455  * call-seq:
2456  * zdd.export([fileName]) : ZDDのエキスポート
2457  *
2458  *  zdd      : ZDD Object
2459  *  fileName : Ruby String
2460  *
2461  * === 説明
2462  *  zddオブジェクトのZDD内部構造をテキストで出力する。
2463  *  fileNameを指定すれば、そのファイルに出力する。
2464  *  省略すれば標準出力に出力する。
2465  *
2466  * === 例
2467  *  > a=ZDD.itemset("a")
2468  *  > b=ZDD.itemset("b")
2469  *  > c=ZDD.itemset("c")
2470  *  > f=5*a*b*c+3*a*b++2*b*c+c
2471  *  > f.show
2472  *   5 a b c + 3 a b + 2 b c + c
2473  *
2474  *  > f.export
2475  *   _i 3
2476  *   _o 3
2477  *   _n 7
2478  *   4 1 F T
2479  *   248 2 F 5
2480  *   276 3 4 248
2481  *   232 2 F 4
2482  *   2 2 F T
2483  *   272 3 232 2
2484  *   268 3 232 248
2485  *   276
2486  *   272
2487  *   268
2488  */
2489 VALUE vsop_print_export(int argc, VALUE *argv, VALUE self){
2490         Vsop_Ruby* rmod;
2491         Data_Get_Struct(self,Vsop_Ruby,rmod);
2492         auto_ptr<CtoI> auto_p(new CtoI(*rmod->cmod));
2493         CtoI *ctoitmp = auto_p.get();
2494         FILE *fp=NULL;
2495         if(argc==1){
2496                 VALUE v1;
2497                 rb_scan_args(argc, argv,"0*",&v1);
2498                 if(TYPE(RARRAY_PTR(v1)[0])==T_STRING){
2499                                 char *str = RSTRING_PTR(RARRAY_PTR(v1)[0]);
2500                                 fp = fopen(str, "w");
2501                                 if(fp == NULL){
2502                                         rb_raise(rb_eRuntimeError,"Can't open the file");               
2503                                 }
2504                 }
2505                 else{
2506                         rb_raise(rb_eRuntimeError,"argument type error (1st argument must be STRING)");
2507                 }
2508         }
2509         else if(argc!=0){
2510                 rb_raise(rb_eRuntimeError,"number of argument is 0 or 1 ");             
2511         }
2512
2513         int d = ctoitmp -> TopDigit();
2514         ZBDDV v = ZBDDV();
2515         for(int i=0; i<=d; i++){
2516                 v += ZBDDV(ctoitmp -> Digit(i).GetZBDD(), i);
2517         }
2518
2519         if(fp){
2520                 v.Export(fp);
2521                 fclose(fp);
2522         }else{
2523                 v.Export();
2524         }
2525         return self;
2526 }        
2527
2528 /*
2529  * call-seq:
2530  * zdd.show([switch] [,fileName]) : 出力及び表示用メソッド
2531  *
2532  *  zdd    : ZDD Object
2533  *  switch : Ruby String
2534  *
2535  * === 説明
2536  * string1でスイッチを指定し出力形式を決定する。exportを指定した場合のみstring2を指定可能(ファイル名)
2537  *
2538  *    switchの内容  : 機能
2539  * * (スイッチ無し)       : 式のカッコを展開した積和形での表示
2540  * *  /bit                                      : 重みの(-2)進数の各桁別アイテム集合の表示(bitメソッドに同じ) 
2541  * *  /hex                                      : 整数値を 16 進数で表現する積和形表示(hexメソッドに同じ)
2542  * *  /map                                      : カルノー図で表示。アイテム変数6個まで表示できる(mapメソッドに同じ)
2543  * *  /rmap                               : カルノー図で表示。冗長なアイテム変数は省いて表示(rmapメソッドに同じ)
2544  * *  /case                               : 整数値ごとに場合分けして積和形表示(caseメソッドに同じ)
2545  * *  /size                               : 計算結果のBDD節点数(および処理系全体の節点数)を表示(sizeメソッドに同じ)
2546  * *  /count                            : 式に現れる(0 以外の値を持つ)組合せの個数を表示(countメソッドに同じ)
2547  * *  /density            : 集合の濃度(0 以外の値を持つ組合せの比率)を表示(densityメソッドに同じ)
2548  * *  /value                            : シンボル変数にすべて数値を代入したときの式の値を表示(valueメソッドに同じ)
2549  * *  /maxcover           : 式に含まれる(0 以外の値を持つ)コスト最大の組合せを1つ表示(maxcoverメソッドに同じ)
2550  * *  /maxcost            : コスト最大組合せのコスト値を表示(maxcostメソッドに同じ)
2551  * *  /mincover           : 式に含まれる(0 以外の値を持つ)コスト最小の組合せを1つ表示(mincoverメソッドに同じ)
2552  * *  /mincost            : コスト最小組合せのコスト値を表示(mincostメソッドに同じ)
2553  * *  /plot                               : BDDの形を図示する。(使用不可)
2554  * *  /decomp                     : 単純直交分解形式での出力
2555  * *  /export                     : BDDの形を図示する(否定枝不使用)。string2に指定があれば、指定されたファイルに出力(exportメソッドに同じ)
2556  *
2557  * === 関連
2558  *  bit hex map rmap case size count density value maxcover mincover mincost decomp export
2559  */
2560 VALUE vsop_show(int argc, VALUE *argv, VALUE self){
2561         VALUE rtnval;
2562         if(argc == 0){
2563                 rtnval = vsop_print(self);
2564         }
2565         else if(argc == 1)      {
2566                 VALUE v;
2567                 rb_scan_args(argc, argv,"10",&v);
2568                 if(TYPE(v)!=T_STRING){
2569                         rb_raise(rb_eRuntimeError,"argument type error (1st argument must be STRING)");
2570                 }
2571                 char *argtmp = RSTRING_PTR(v);
2572                 int len = strlen(argtmp);
2573                 char *str_c;
2574                 if(*argtmp=='/'){
2575                         str_c = new char[len];
2576                         strcpy(str_c,argtmp+1);
2577                 }
2578                 else{
2579                         str_c = new char[len+1];
2580                         strcpy(str_c,argtmp);           
2581                 }
2582                 rtnval = vsop_print_arg1(self,str_c);
2583
2584         }
2585         else    if(argc == 2)
2586         {
2587                 rtnval = vsop_print_arg2(argc,argv,self);
2588         }
2589         else{
2590                 rb_raise(rb_eRuntimeError,"number of argument is 0 or 1 or 2");
2591         }
2592         return rtnval;
2593 }
2594
2595 /*
2596  * call-seq:
2597  * ZDD.partly -> bool : 部分hash出力フラグ
2598  *
2599  *  bool   : Qtrue or Qfalse
2600  *
2601  * === 説明
2602  *  hashoutメソッドにて全データをセット出来なかった場合、このメソッドはtrueを返す。
2603  *
2604  * === 関連
2605  *  hashout
2606  */
2607 VALUE vsop_partly(VALUE self){
2608         return rb_iv_get(self,"@partly");
2609 }
2610
2611 //強制変換用
2612 VALUE vsop_coerce(int argc, VALUE *argv, VALUE self){
2613         VALUE v;
2614         Vsop_Ruby* rmod=new Vsop_Ruby;
2615         rb_scan_args(argc, argv,"10",&v);
2616         rmod->cmod =value2ctoi(v);
2617         VALUE rtn_v = Data_Wrap_Struct(rb_class_of(self),0,free_rmod,rmod);
2618         return rb_ary_new3(2,rtn_v,self);
2619 }
2620
2621 /*
2622  * call-seq:
2623  *  zdd.to_i -> int : ZDDの重みをRuby整数に変換
2624  *
2625  *  int : Ruby Integer
2626  *
2627  * === 説明
2628  * ZDD重みオブジェクト(空のアイテム集合の重み)をruby整数に変換する。重みオブジェクトでないZDDオブジェクトに適用した場合はnilを返す。
2629  *
2630  * === 例
2631  *  > c=ZDD.constant(10)
2632  *  > c.show            # ZDD重みオブジェクト
2633  *   10
2634  *  > puts c.to_i       # ruby整数
2635  *   10
2636  *  a=ZDD.itemset("a") # ZDDアイテム集合オブジェクトに対して適用するとnil
2637  *  a.to_i
2638  *   nil
2639  *
2640  * === 関連
2641  *  constant
2642  */
2643
2644 VALUE vsop_const_to_i(VALUE self){
2645         Vsop_Ruby* rmod;
2646         Data_Get_Struct(self,Vsop_Ruby,rmod);
2647
2648         if(rmod->cmod->IsConst()){
2649                 int val = rmod->cmod->GetInt();
2650                 return INT2NUM(val);
2651         }else{
2652                 return Qnil;
2653         }
2654 }
2655
2656
2657 void Init_zdd_so() {
2658 /*
2659  * Document-class: ZDD
2660  * = ZDDを動作させるモジュール
2661  * (version: ##version##.##revision##)
2662  *
2663  * === 0.概要
2664  *  ZDD(Zero-suppressed Binary Decision Diagrams: ゼロサプレス型二分決定グラフ)を利用し、
2665  *  重み付きのアイテムの組み合わせ集合をコンパクトに格納することを可能とするZDD
2666  *  (Valued-Sum-Of-Products calculator)をruby拡張ライブラリとして実装したもの。
2667  *  ZDDオブジェクトに対する演算子(`+',`-',`=='など)の多くは、ZDD演算としてオーバーロードしており、
2668  *  ZDDの各種機能とrubyの制御などの各種機能をシームレスに組み合わせて利用することを可能としている。
2669  *
2670  *  本マニュアルはRDocとしても提供されているので、コマンドライン上からも閲覧可能である。
2671  *  ----
2672  *  $ ri ZDD # ZDDモジュール全体のマニュアルの閲覧
2673  *  $ ri ZDD.symbol # symbolメソッドの閲覧
2674  *  ----
2675  *
2676  *  注: 本モジュールは開発途上であり、本文書の仕様は予告なしに変更することがある。
2677  *
2678  *  科学技術振興機構 ERATO湊離散構造系プロジェクト 関西サテライトラボ
2679  *
2680  * === 1.はじめよう!(チュートリアル)
2681  *  以下では、4つのアイテムの全組合せ集合を列挙する方法を示す。
2682  *  rubyスクリプトを記述して実行してもよいし、irbで一行ずつ実行してもよい。
2683  *  ZDD ruby拡張ライブラリが既に正しくインストールされており、またrubyについての基本的な知識があることを前提としている。
2684  *
2685  * 注:本マニュアルでの例で使われている記号の意味は以下の通り。
2686  *  ">" : rubyのメソッド入力を表す。
2687  *  "$" : シェルのコマンドライン入力を表す。
2688  *  "#" : コメントを表す。
2689  *  記号なし : 実行結果を表す。
2690  *
2691  * ==== 1-1. ZDD ruby拡張ライブラリのrequire
2692  *  vsop ruby拡張ライブラリはrubygemsを使ってパッケージングされているので、以下の通りrubygemsをrequireした後にvsopをrequireする。
2693  * 
2694  *  ----
2695  *  > require 'rubygems'
2696  *  > require 'zdd'
2697  *  ----
2698  *
2699  * ==== 1-2. 利用するアイテムの宣言
2700  *  利用するアイテム名を宣言するためにZDD.symbolメソッドを利用する。一つのメソッドで一つのアイテムが宣言できる。
2701  *  アイテム宣言の順序は重要で、その順序がZDDの木構造における根からのレベルに対応する。宣言の順序により異なる構造のZDDが作成され、よってそのサイズに大幅に影響を与えることがある。
2702  *  以下では、"a","b","c","d"という名前の4つのアイテムを宣言している。
2703  *
2704  *  ----
2705  *  > ZDD.symbol("a")
2706  *  > ZDD.symbol("b")
2707  *  > ZDD.symbol("c")
2708  *  > ZDD.symbol("d")
2709  *  ----
2710  *
2711  * ==== 1-3. アイテムの定義
2712  *  symbolでは単に利用するアイテムを宣言しただけなので、次に、それらのアイテムから構成されるアイテム集合の定義、すなわちZDDオブジェクトを作成していく。
2713  *  以下では、1つのアイテムから構成されるアイテム集合を作る。次のステップで、それらのアイテム集合に対して様々な演算を加えることで全組合せを列挙する。
2714  *
2715  *  ----
2716  *  > a=ZDD.itemset("a")
2717  *  > b=ZDD.itemset("b")
2718  *  > c=ZDD.itemset("c")
2719  *  > d=ZDD.itemset("d")
2720  *  ----
2721  *
2722  *  最初の行は、"a"というアイテムから構成されるアイテム集合のZDDオブジェクトがruby変数aに格納される。以下同様にb,c,dの変数にもZDDオブジェクトが格納される。
2723  *
2724  * ==== 1-4. 演算
2725  *  ZDDで定義されている様々な演算を利用してアイテム集合を変換していく。
2726  *  以下のような式を入力すると、4つのアイテムa,b,c,dの全組合せが列挙されることになる。
2727  *  式の展開方法は、以下のケースにおいては、一般的な多項式の展開方法と同様に考えれば良い。
2728  *  右辺の演算結果として構築されたZDDオブジェクトがruby変数fに代入されている。
2729  *  そしてZDDオブジェクトの内容を表示するshowメソッドにより表示する。
2730  *  showはZDDオブジェクトの内容を重み付き積和形で表示するメソッドである。
2731  *  最後の項の"1"は空集合の係数である。
2732  *
2733  *  ----
2734  *  > f=(a+1)*(b+1)*(c+1)*(d+1)
2735  *  > f.show
2736  *  a b c d + a b c + a b d + a b + a c d + a c + a d + a + b c d + b c +
2737  *    b d + b + c d + c + d + 1
2738  *  ----
2739  *
2740  *  他にも、2つほど異なる演算結果を示す。なぜこのような結果になるかは本マニュアルの"*"演算子(乗算)を参照のこと。
2741  *
2742  *  ----
2743  *  > g=(a+b)*(b+c)*(c+d)*(d+a)
2744  *  > g.show
2745  *  2 a b c d + 3 a b c + 3 a b d + 3 a c d + a c + 3 b c d + b d
2746  *
2747  *  > h=(a+1)*(a+1)*(a+1)*(a+1)
2748  *  > h.show
2749  *  15 a + 1
2750  *  ----
2751  *
2752  * === 2. 様々な用法
2753  * 以下では、よく利用するメソッドを中心にして、vsopライブラリの様々な用法について学ぶ。
2754  *
2755  * ==== 2-1. symbolメソッドによる宣言なしにitemsetメソッドを使う
2756  *  ZDD.symbolメソッドは利用するアイテムの宣言に利用するが、これは省くことができる。省略した場合は、itemsetメソッドで定義されたアイテムの登場順にsymbolで宣言することに等しい。
2757  *
2758  *  ----
2759  *  > a=ZDD.itemset("a")
2760  *  > b=ZDD.itemset("b")
2761  *  > c=ZDD.itemset("c")
2762  *  > ZDD.itemset # itemsetメソッドを引き数なしで呼び出すと、宣言されたアイテムがその順番で表示される。
2763  *  a b c
2764  *
2765  *  > a=ZDD.itemset("a")
2766  *  > c=ZDD.itemset("c")
2767  *  > b=ZDD.itemset("b")
2768  *  > ZDD.itemset
2769  *  a c b
2770  *  ----
2771  *
2772  * ==== 2-2. アイテム集合のZDDオブジェクトを一行で生成する方法
2773  *  ZDD.itemsetメソッドにアイテム名をスペース区切りで列挙することでアイテム集合のZDDオブジェクトを作成することができる。
2774  *
2775  *  ----
2776  *  # 3つのアイテム`a',`b',`c'で構成されるアイテム集合{a,b,c}を表すZDDオブジェクトをrubyの変数`a'にセットする。
2777  *  > a=ZDD.itemset("a b c")
2778  *  > a.show
2779  *   a b c
2780  *  ----
2781  *
2782  * ==== 2-3. 重みの定義
2783  *  重みを表す整数値定数項(空のアイテム集合の重み)はconstantメソッドを利用する。
2784  *
2785  *  ----
2786  *  > a=ZDD.itemset("a b c")
2787  *  > q=ZDD.constant(4) # 重み4の空のアイテム集合ZDDオブジェクトが作成されruby変数qに格納される。
2788  *  > (q*a).show
2789  *   4 a b c
2790  *  ----
2791  *
2792  * ==== 2-4. ZDDオブジェクトに対する演算
2793  *  ZDDオブジェクトを一つでも引数に持つ演算子はオーバーロードされたZDD演算子となる。
2794  *
2795  *  ----
2796  *  > a=ZDD.itemset("a b c") # rubyの変数`a'はZDDオブジェクト
2797  *  > (4*a).show              # よって`*'はZDD演算子として機能し、ruby整数`4'は自動的にZDDオブジェクトに型変換される。
2798  *   4 a b c                  # 内部的には、(ZDD.constant(4)*a).show を実行している。
2799  *  > (a+"a b").show          # ruby文字列"a b"は自動的にZDDオブジェクトに変換される。
2800  *   a b c + a b              # 内部的には、(a+ZDD.itemset("a b")).show を実行している。
2801  *  > a="a b"+"c d"           #これは演算子の引数が二つともrubyのStringオブジェクトであるため、単なる文字列の結合となってしまう。
2802  *  ----
2803  *
2804  * ==== 2-5. 制御文との組合せ
2805  *  制御文と組み合わせると以下のような書き方も可能である
2806  *
2807  *  ----
2808  *  > z=ZDD.constant(0)
2809  *  > ["a","b","c"].each{|item|
2810  *  >    z += item  # `z'はZDDオブジェクトなので、それに対する`+'演算はZDD演算子となる。
2811  *  > }
2812  *  > z.show
2813  *   a + b + c
2814  *
2815  *  > z=ZDD.constant(0)
2816  *  > (1..5).each{|i|
2817  *  >   z += "item_#{i}"
2818  *  > }
2819  *  > z.show
2820  *   item_1 + item_2 + item_3 + item_4 + item_5
2821  *  ----
2822  *
2823  * === 3.環境変数
2824  *  以下の環境変数を設定することでデフォルトの動作を変更することができる
2825  *  ZDDLimitNode 
2826  *     最大節点数 デフォルト値:1000000
2827  *  ZDDWarning
2828  *     警告メッセージ出力 設定すると数値文字をアイテムに使用使用とした場合に警告メッセージが出力される
2829  * 
2830  */
2831         //環境変数取得
2832         char *envStr;
2833         envStr=getenv("ZDDLimitNode");
2834         if(envStr!=NULL){
2835                 env_nmax=atoi(envStr);
2836         }else{
2837                 env_nmax=DEF_ENV_NMAX ;
2838         }
2839         envStr=getenv("ZDDWarning");
2840         if(envStr!=NULL){
2841                 env_warning=true;
2842         }else{
2843                 env_warning=false;
2844         }
2845         
2846
2847         VALUE vsop_main=rb_define_module("ZDD");
2848         //モジュール変数設定
2849         rb_define_module_function(vsop_main,   "itemset", RUBY_METHOD_FUNC(vsop_itemset), -1);
2850         rb_define_module_function(vsop_main,  "constant", RUBY_METHOD_FUNC(vsop_constant), -1);
2851         rb_define_module_function(vsop_main,    "symbol", RUBY_METHOD_FUNC(vsop_symbol), -1);
2852         rb_define_module_function(vsop_main,      "each", RUBY_METHOD_FUNC(vsop_each), 0);
2853         rb_define_module_function(vsop_main, "each_item", RUBY_METHOD_FUNC(vsop_each_item), 0);
2854
2855         rb_define_module_function(vsop_main,      "show", RUBY_METHOD_FUNC(vsop_show), -1);
2856         rb_define_module_function(vsop_main,       "lcm", RUBY_METHOD_FUNC(vsop_lcm), -1);
2857         rb_define_module_function(vsop_main,    "lcm_ub", RUBY_METHOD_FUNC(vsop_lcm_ub), -1);
2858         rb_define_module_function(vsop_main,    "permit", RUBY_METHOD_FUNC(vsop_permit), -1);
2859         rb_define_module_function(vsop_main, "permitsym", RUBY_METHOD_FUNC(vsop_permitsym), -1);
2860         rb_define_module_function(vsop_main,  "restrict", RUBY_METHOD_FUNC(vsop_restrict), -1);
2861         rb_define_module_function(vsop_main,  "freqpatC", RUBY_METHOD_FUNC(vsop_freqpatC), -1);
2862         rb_define_module_function(vsop_main,  "freqpatM", RUBY_METHOD_FUNC(vsop_freqpatM), -1);
2863         rb_define_module_function(vsop_main,  "freqpatA", RUBY_METHOD_FUNC(vsop_freqpatA), -1);
2864         rb_define_module_function(vsop_main,   "termsLE", RUBY_METHOD_FUNC(vsop_termsLE), -1);
2865         rb_define_module_function(vsop_main,   "termsLT", RUBY_METHOD_FUNC(vsop_termsLT), -1);
2866         rb_define_module_function(vsop_main,   "termsGE", RUBY_METHOD_FUNC(vsop_termsGE), -1);
2867         rb_define_module_function(vsop_main,   "termsGT", RUBY_METHOD_FUNC(vsop_termsGT), -1);
2868         rb_define_module_function(vsop_main,   "termsNE", RUBY_METHOD_FUNC(vsop_termsNE), -1);
2869         rb_define_module_function(vsop_main,   "termsEQ", RUBY_METHOD_FUNC(vsop_termsEQ), -1);
2870
2871         rb_define_module_function(vsop_main,        "<=", RUBY_METHOD_FUNC(vsop_le), -1);
2872         rb_define_module_function(vsop_main,         "<", RUBY_METHOD_FUNC(vsop_lt), -1);
2873         rb_define_module_function(vsop_main,        ">=", RUBY_METHOD_FUNC(vsop_ge), -1);
2874         rb_define_module_function(vsop_main,         ">", RUBY_METHOD_FUNC(vsop_gt), -1);
2875         rb_define_module_function(vsop_main,       "ne?", RUBY_METHOD_FUNC(vsop_ne), -1);
2876         rb_define_module_function(vsop_main,        "==", RUBY_METHOD_FUNC(vsop_eq), -1);
2877         rb_define_module_function(vsop_main,       "iif", RUBY_METHOD_FUNC(vsop_iif), -1);
2878         //rb_define_module_function(vsop_main,      "meet", RUBY_METHOD_FUNC(vsop_meet), -1);
2879         rb_define_module_function(vsop_main,     "same?", RUBY_METHOD_FUNC(vsop_same), -1);
2880         rb_define_module_function(vsop_main,       "===", RUBY_METHOD_FUNC(vsop_same), -1);     
2881         rb_define_module_function(vsop_main,     "diff?", RUBY_METHOD_FUNC(vsop_diff), -1);
2882         rb_define_module_function(vsop_main,     "delta", RUBY_METHOD_FUNC(vsop_delta), -1);
2883
2884         rb_define_module_function(vsop_main,         "+", RUBY_METHOD_FUNC(vsop_plus), -1);
2885         rb_define_module_function(vsop_main,         "-", RUBY_METHOD_FUNC(vsop_minus), -1);
2886         rb_define_module_function(vsop_main,        "+@", RUBY_METHOD_FUNC(vsop_plus_op), 0);
2887         rb_define_module_function(vsop_main,        "-@", RUBY_METHOD_FUNC(vsop_minus_op), 0);
2888         rb_define_module_function(vsop_main,         "*", RUBY_METHOD_FUNC(vsop_multiply), -1);
2889         rb_define_module_function(vsop_main,         "/", RUBY_METHOD_FUNC(vsop_quotiment), -1);
2890         rb_define_module_function(vsop_main,         "%", RUBY_METHOD_FUNC(vsop_remainder), -1);
2891         rb_define_module_function(vsop_main,    "csvout", RUBY_METHOD_FUNC(vsop_csvout), -1);
2892         rb_define_module_function(vsop_main,    "import", RUBY_METHOD_FUNC(vsop_import), -1);
2893         rb_define_module_function(vsop_main,   "hashout", RUBY_METHOD_FUNC(vsop_hashout), 0);
2894         rb_define_module_function(vsop_main,    "maxval", RUBY_METHOD_FUNC(vsop_maxval), 0);
2895         rb_define_module_function(vsop_main,    "minval", RUBY_METHOD_FUNC(vsop_minval), 0);
2896         rb_define_module_function(vsop_main,  "totalval", RUBY_METHOD_FUNC(vsop_totalval), 0);
2897         rb_define_module_function(vsop_main,     "items", RUBY_METHOD_FUNC(vsop_items), 0);
2898         rb_define_module_function(vsop_main,    "symgrp", RUBY_METHOD_FUNC(vsop_symgrp), 0);
2899
2900         rb_define_module_function(vsop_main,       "map", RUBY_METHOD_FUNC(vsop_print_map), -1);
2901         rb_define_module_function(vsop_main,      "rmap", RUBY_METHOD_FUNC(vsop_print_rmap), -1);
2902         rb_define_module_function(vsop_main,       "hex", RUBY_METHOD_FUNC(vsop_print_hex), -1);
2903         rb_define_module_function(vsop_main,       "bit", RUBY_METHOD_FUNC(vsop_print_bit), -1);
2904         rb_define_module_function(vsop_main,      "case", RUBY_METHOD_FUNC(vsop_print_case), -1);
2905         rb_define_module_function(vsop_main,      "size", RUBY_METHOD_FUNC(vsop_print_size), 0);
2906         rb_define_module_function(vsop_main, "totalsize", RUBY_METHOD_FUNC(vsop_print_totalsize), 0);
2907         rb_define_module_function(vsop_main,     "count", RUBY_METHOD_FUNC(vsop_print_count), 0);
2908         rb_define_module_function(vsop_main,   "density", RUBY_METHOD_FUNC(vsop_print_density), 0);
2909         rb_define_module_function(vsop_main,     "value", RUBY_METHOD_FUNC(vsop_print_value), 0);
2910         rb_define_module_function(vsop_main,  "maxcover", RUBY_METHOD_FUNC(vsop_print_maxcover), -1);
2911         rb_define_module_function(vsop_main,   "maxcost", RUBY_METHOD_FUNC(vsop_print_maxcost), 0);
2912         rb_define_module_function(vsop_main,  "mincover", RUBY_METHOD_FUNC(vsop_print_mincover), -1);
2913         rb_define_module_function(vsop_main,   "mincost", RUBY_METHOD_FUNC(vsop_print_mincost), 0);
2914         rb_define_module_function(vsop_main,    "decomp", RUBY_METHOD_FUNC(vsop_print_decomp), -1);
2915         rb_define_module_function(vsop_main,    "export", RUBY_METHOD_FUNC(vsop_print_export), -1);
2916         rb_define_module_function(vsop_main,    "partly", RUBY_METHOD_FUNC(vsop_partly), 0);
2917         rb_define_module_function(vsop_main,    "coerce", RUBY_METHOD_FUNC(vsop_coerce), -1);
2918         rb_define_module_function(vsop_main,      "to_i", RUBY_METHOD_FUNC(vsop_const_to_i), 0);
2919         rb_define_module_function(vsop_main,      "to_a", RUBY_METHOD_FUNC(vsop_to_a), 0);
2920         rb_define_module_function(vsop_main,      "to_s", RUBY_METHOD_FUNC(vsop_to_s), 0);
2921         rb_define_module_function(vsop_main,   "inspect", RUBY_METHOD_FUNC(vsop_to_s), 0);
2922
2923 }