nysol-zdd 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/ext/zdd_so/BDD.cc +495 -0
  3. data/ext/zdd_so/BDD.h +356 -0
  4. data/ext/zdd_so/BDDDG.cc +1818 -0
  5. data/ext/zdd_so/BDDDG.h +107 -0
  6. data/ext/zdd_so/BDDHASH.cc +91 -0
  7. data/ext/zdd_so/BtoI.cc +503 -0
  8. data/ext/zdd_so/BtoI.h +144 -0
  9. data/ext/zdd_so/CtoI.cc +1072 -0
  10. data/ext/zdd_so/CtoI.h +186 -0
  11. data/ext/zdd_so/MLZBDDV.cc +153 -0
  12. data/ext/zdd_so/MLZBDDV.h +42 -0
  13. data/ext/zdd_so/SOP.cc +608 -0
  14. data/ext/zdd_so/SOP.h +199 -0
  15. data/ext/zdd_so/ZBDD.cc +1035 -0
  16. data/ext/zdd_so/ZBDD.h +243 -0
  17. data/ext/zdd_so/ZBDDDG.cc +1834 -0
  18. data/ext/zdd_so/ZBDDDG.h +105 -0
  19. data/ext/zdd_so/ZBDDHASH.cc +91 -0
  20. data/ext/zdd_so/bddc.c +2816 -0
  21. data/ext/zdd_so/bddc.h +132 -0
  22. data/ext/zdd_so/extconf.rb +25 -0
  23. data/ext/zdd_so/include/aheap.c +211 -0
  24. data/ext/zdd_so/include/aheap.h +111 -0
  25. data/ext/zdd_so/include/base.c +93 -0
  26. data/ext/zdd_so/include/base.h +60 -0
  27. data/ext/zdd_so/include/itemset.c +473 -0
  28. data/ext/zdd_so/include/itemset.h +153 -0
  29. data/ext/zdd_so/include/problem.c +371 -0
  30. data/ext/zdd_so/include/problem.h +160 -0
  31. data/ext/zdd_so/include/queue.c +518 -0
  32. data/ext/zdd_so/include/queue.h +177 -0
  33. data/ext/zdd_so/include/sgraph.c +331 -0
  34. data/ext/zdd_so/include/sgraph.h +170 -0
  35. data/ext/zdd_so/include/stdlib2.c +832 -0
  36. data/ext/zdd_so/include/stdlib2.h +746 -0
  37. data/ext/zdd_so/include/trsact.c +723 -0
  38. data/ext/zdd_so/include/trsact.h +167 -0
  39. data/ext/zdd_so/include/vec.c +583 -0
  40. data/ext/zdd_so/include/vec.h +159 -0
  41. data/ext/zdd_so/lcm-vsop.cc +596 -0
  42. data/ext/zdd_so/print.cc +683 -0
  43. data/ext/zdd_so/table.cc +330 -0
  44. data/ext/zdd_so/vsop.h +88 -0
  45. data/ext/zdd_so/zdd_so.cpp +3277 -0
  46. data/lib/nysol/zdd.rb +31 -0
  47. metadata +131 -0
@@ -0,0 +1,177 @@
1
+ /* Library of queue: spped priority implementation
2
+ 12/Apr/2001 by Takeaki Uno e-mail:uno@nii.jp,
3
+ homepage: http://research.nii.ac.jp/~uno/index.html */
4
+ /* This program is available for only academic use, basically.
5
+ Anyone can modify this program, but he/she has to write down
6
+ the change of the modification on the top of the source code.
7
+ Neither contact nor appointment to Takeaki Uno is needed.
8
+ If one wants to re-distribute this code, do not forget to
9
+ refer the newest code, and show the link to homepage of
10
+ Takeaki Uno, to notify the news about the codes for the users.
11
+ For the commercial use, please make a contact to Takeaki Uno. */
12
+
13
+ #ifndef _queue_h_
14
+ #define _queue_h_
15
+
16
+ #include"stdlib2.h"
17
+
18
+ #ifndef QUEUE_INT
19
+ #ifdef QUEUE_INT_LONG
20
+ #define QUEUE_INT LONG // define the type before if change is needed
21
+ #define QUEUE_INTHUGE LONGHUGE // comment out if QUEUE_INT is "short"
22
+ #define QUEUE_INTF "%lld"
23
+ #else
24
+ #define QUEUE_INT int // define the type before if change is needed
25
+ #define QUEUE_INTHUGE INTHUGE // comment out if QUEUE_INT is "short"
26
+ #define QUEUE_INTF "%d"
27
+ #endif
28
+ #endif
29
+
30
+ #ifndef QUEUE_ID
31
+ #ifdef QUEUE_ID_LONG
32
+ #define QUEUE_ID LONG // define the type before if change is needed
33
+ #define QUEUE_IDHUGE LONGHUGE // comment out if QUEUE_INT is "short"
34
+ #define QUEUE_IDF "%lld"
35
+ #else
36
+ #define QUEUE_ID int // define the type before if change is needed
37
+ #define QUEUE_IDHUGE INTHUGE // comment out if QUEUE_INT is "short"
38
+ #define QUEUE_IDF "%d"
39
+ #endif
40
+ #endif
41
+ #define SWAP_QUEUE_INT(a,b) (common_QUEUE_INT=a,a=b,b=common_QUEUE_INT)
42
+ #define SWAP_QUEUE_ID(a,b) (common_QUEUE_ID=a,a=b,b=common_QUEUE_ID)
43
+
44
+ typedef struct {
45
+ unsigned char type; // type of the structure
46
+ QUEUE_INT *v; // pointer to the array
47
+ QUEUE_ID end; // the length of the array
48
+ QUEUE_ID t; // end position+1
49
+ QUEUE_ID s; // start position
50
+ } QUEUE;
51
+
52
+ /* QUEUE stores at most end-1 elements. Overflow occurs after inserting end-1 elements */
53
+
54
+ #define QUEUE_INCREMENT(Q,i) ((i)=((i)>=(Q).end-1)?0:(i)+1)
55
+ #define QUEUE_DECREMENT(Q,i) ((i)=(i)==0?(Q).end-1:(i)-1)
56
+ #define QUEUE_LENGTH(Q) (((Q).t-(Q).s+(Q).end)%(Q).end)
57
+ #define QUEUE_LENGTH_(Q) ((Q).t-(Q).s)
58
+
59
+ /* macro for loop w.r.t., QUEUE */
60
+ #define QUEUE_F_LOOP(Q,i) for((i)=(Q).s;(i)!=(Q).t;((i)=((i)>=(Q).end-1)?0:(i)+1))
61
+ #define QUEUE_F_LOOP_(Q,i) for((i)=(Q).s;(i)<(Q).t;(i)++)
62
+ #define QUEUE_FE_LOOP(Q,i,x) for((i)=(Q).s,x=(Q).v[i];(i)!=(Q).t;((i)=((i)>=(Q).end-1)?0:(i)+1),x=(Q).v[i])
63
+ #define QUEUE_FE_LOOP_(Q,i,x) for((i)=(Q).s,x=(Q).v[i];(i)<(Q).t;(i)++,x=(Q).v[i])
64
+ #define QUEUE_B_LOOP(Q,i) for((i)=(Q).t==0?(Q).end-1:(Q).t-1;(i)!=(Q).s;(i)=(i)==0?(Q).end-1:(i)-1)
65
+ #define QUEUE_B_LOOP_(Q,i) for((i)=(Q).t-1;(i)>=(Q).s;(i)--)
66
+ #define QUEUE_BE_LOOP(Q,i,x) for((i)=(Q).t==0?(Q).end-1:(Q).t-1,x=(Q).v[i];(i)!=(Q).s;(i)=(i)==0?(Q).end-1:(i)-1,x=(Q).v[i])
67
+ #define QUEUE_BE_LOOP_(Q,i,x) for((i)=(Q).t-1;((i)>=(Q).s)?((x=(Q).v[i])||1):0;(i)--)
68
+
69
+ #define QUEUE_RMALL(Q) ((Q).t=(Q).s)
70
+ #define QUEUE_RMALL_(Q) ((Q).t=0)
71
+ #define QUEUE_HEAD(Q) ((Q).v[(Q).s])
72
+ #define QUEUE_TAIL_(Q) ((Q).v[(Q).t-1])
73
+
74
+ extern QUEUE INIT_QUEUE;
75
+ extern QUEUE_INT common_QUEUE_INT, *common_QUEUE_INTp;
76
+ QSORT_TYPE_HEADER(QUEUE_INT, QUEUE_INT)
77
+ QSORT_TYPE_HEADER(QUEUE_ID, QUEUE_ID)
78
+
79
+
80
+ /* initialization, not fill the memory by 0 */
81
+ void QUEUE_alloc (QUEUE *Q, QUEUE_ID siz);
82
+
83
+ /* termination processing */
84
+ void QUEUE_end (QUEUE *Q);
85
+
86
+ /* delivery: transpose that matrinx (transaction database) Q. Each row of the
87
+ transposed matrix is called occurrence.
88
+
89
+ variables to be set.
90
+ OQ:array for occurrences, c: for counting frequency, jump: list of items with non-empty OQ
91
+ if c!=NULL, count the frequency and set to c, and set occurrences to OQ, otherwise.
92
+ if jump==NULL, then the list of non-empty item will not be generated
93
+ Q:matrix, of an array of QUEUE, occ: list of rows of Q to be scaned, t; maximum ID of the
94
+ row to be scaned; if occ==NULL, occ will be ignored, otherwise t will be ignored.
95
+ M: end mark of each QUEUE. */
96
+ void QUEUE_delivery(QUEUE *OQ, VEC_ID *c, QUEUE *jump, QUEUE *Q, QUEUE *occ, VEC_ID t, QUEUE_INT M);
97
+ /* sort a QUEUE with WEIGHT, with already allocated memory (size have to no less than the size of QUEUE) */
98
+ void QUEUE_perm_WEIGHT (QUEUE *Q, WEIGHT *w, PERM *invperm, int flag);
99
+
100
+ /* remove (or unify) the consecutive same ID's in a QUEUE (duplication delete, if sorted) */
101
+ void QUEUE_rm_dup_WEIGHT (QUEUE *Q, WEIGHT *w);
102
+
103
+ /***********************************************************************/
104
+ /* duplicate occ's in jump, ( copy occ's to allocated QUEUE array) */
105
+ /* Q[i].end := original item, clear each original occ */
106
+ /* buffer size is multiplied by u */
107
+ /*******************************************************/
108
+
109
+
110
+ void QUEUE_occ_dup (QUEUE *jump, QUEUE **QQ, QUEUE *Q, WEIGHT **ww, WEIGHT *w, WEIGHT **ppw, WEIGHT *pw, int u);
111
+
112
+ /* return the position of the first element having value e. return -1 if no such element exists */
113
+ LONG QUEUE_ele (QUEUE *Q, QUEUE_INT e);
114
+
115
+ /* insert an element to the tail/head */
116
+ void QUEUE_ins_ (QUEUE *Q, QUEUE_INT e);
117
+ void QUEUE_ins (QUEUE *Q, QUEUE_INT e);
118
+ void QUEUE_ins_head_ (QUEUE *Q, QUEUE_INT e);
119
+ void QUEUE_ins_head (QUEUE *Q, QUEUE_INT e);
120
+
121
+ /* extract an element from the head/tail, without checking the underflow */
122
+ QUEUE_INT QUEUE_ext_ (QUEUE *Q);
123
+ QUEUE_INT QUEUE_ext (QUEUE *Q);
124
+ QUEUE_INT QUEUE_ext_tail_ (QUEUE *Q);
125
+ QUEUE_INT QUEUE_ext_tail (QUEUE *Q);
126
+
127
+ /* remove the j-th element and replace it by the tail/head or shift */
128
+ void QUEUE_rm_ (QUEUE *Q, QUEUE_ID j);
129
+ void QUEUE_rm (QUEUE *Q, QUEUE_ID j);
130
+ void QUEUE_rm_head_ (QUEUE *Q, QUEUE_ID j);
131
+ void QUEUE_rm_head (QUEUE *Q, QUEUE_ID j);
132
+ int QUEUE_rm_ele_ (QUEUE *Q, QUEUE_INT e);
133
+
134
+ /* Append Q2 to the tail of Q1. Q2 will (not) be deleted */
135
+ void QUEUE_append_ (QUEUE *Q1, QUEUE *Q2);
136
+ void QUEUE_append (QUEUE *Q1, QUEUE *Q2);
137
+ void QUEUE_concat_ (QUEUE *Q1, QUEUE *Q2);
138
+ void QUEUE_concat (QUEUE *Q1, QUEUE *Q2);
139
+
140
+ /* Append from j to jj th elements to the tail of Q1. Q2 will not be deleted */
141
+ void QUEUE_subconcat_ (QUEUE *Q1, QUEUE *Q2, QUEUE_ID j, QUEUE_ID jj);
142
+ void QUEUE_subconcat (QUEUE *Q1, QUEUE *Q2, QUEUE_ID j, QUEUE_ID jj);
143
+
144
+ /* initialize Q1 by length of Q2, and copy Q2 to Q1 */
145
+ void QUEUE_store_ (QUEUE *Q1, QUEUE *Q2);
146
+ void QUEUE_store (QUEUE *Q1, QUEUE *Q2);
147
+ /* copy Q2 to Q1 and delete Q2 */
148
+ void QUEUE_restore_ (QUEUE *Q1, QUEUE *Q2);
149
+ void QUEUE_restore (QUEUE *Q1, QUEUE *Q2);
150
+
151
+ /* copy Q2 to Q1 */
152
+ void QUEUE_cpy_ (QUEUE *Q1, QUEUE *Q2);
153
+ void QUEUE_cpy (QUEUE *Q1, QUEUE *Q2);
154
+ QUEUE QUEUE_dup_ (QUEUE *Q);
155
+ /* copy l elements of Q2 starting from s2 to the s1th position of Q1.
156
+ size of Q1 is not increasing */
157
+ void QUEUE_subcpy_ (QUEUE *Q1, QUEUE_ID s1, QUEUE *Q2, QUEUE_ID s2, QUEUE_ID l);
158
+ void QUEUE_subcpy (QUEUE *Q1, QUEUE_ID s1, QUEUE *Q2, QUEUE_ID s2, QUEUE_ID l);
159
+
160
+ /* merge/minum/intersection of Q1 and Q2, and set Q1 to it.
161
+ Both Q1 and Q2 have to be sorted in increasing order */
162
+ void QUEUE_merge_ (QUEUE *Q1, QUEUE *Q2);
163
+ void QUEUE_merge (QUEUE *Q1, QUEUE *Q2);
164
+ void QUEUE_minus_ (QUEUE *Q1, QUEUE *Q2);
165
+ void QUEUE_minus (QUEUE *Q1, QUEUE *Q2);
166
+ void QUEUE_and_ (QUEUE *Q1, QUEUE *Q2);
167
+ void QUEUE_and (QUEUE *Q1, QUEUE *Q2);
168
+
169
+ /* insertion sort */
170
+ void QUEUE_sort (QUEUE *Q);
171
+
172
+ /* print */
173
+ void QUEUE_print (QUEUE *Q);
174
+ void QUEUE_print_ (QUEUE *Q);
175
+
176
+
177
+ #endif
@@ -0,0 +1,331 @@
1
+ /* graph library by array list
2
+ 12/Feb/2002 by Takeaki Uno
3
+ homepage: http://research.nii.ac.jp/~uno/index.html */
4
+ /* This program is available for only academic use, basically.
5
+ Anyone can modify this program, but he/she has to write down
6
+ the change of the modification on the top of the source code.
7
+ Neither contact nor appointment to Takeaki Uno is needed.
8
+ If one wants to re-distribute this code, do not forget to
9
+ refer the newest code, and show the link to homepage of
10
+ Takeaki Uno, to notify the news about the codes for the users.
11
+ For the commercial use, please make a contact to Takeaki Uno. */
12
+
13
+ #ifndef _sgraph_c_
14
+ #define _sgraph_c_
15
+
16
+ #include"sgraph.h"
17
+ #include"vec.c"
18
+
19
+ SGRAPH INIT_SGRAPH = {TYPE_SGRAPH,INIT_SETFAMILY_,INIT_SETFAMILY_,INIT_SETFAMILY_,0,0,NULL,NULL};
20
+
21
+ /* initialization */
22
+ void SGRAPH_alloc (SGRAPH *G, QUEUE_ID nodes, size_t edge_num, size_t arc_num){
23
+ if ( edge_num > 0 ){
24
+ SETFAMILY_alloc (&G->edge, nodes, NULL, nodes, edge_num);
25
+ if ( G->flag&LOAD_EDGEW && (!ERROR_MES) ) SETFAMILY_alloc_weight (&G->edge);
26
+ }
27
+ if ( arc_num > 0 ){
28
+ SETFAMILY_alloc (&G->in, nodes, NULL, nodes, arc_num);
29
+ SETFAMILY_alloc (&G->out, nodes, NULL, nodes, arc_num);
30
+ if ( G->flag&LOAD_EDGEW && (!ERROR_MES) ){
31
+ SETFAMILY_alloc_weight (&G->in);
32
+ SETFAMILY_alloc_weight (&G->out);
33
+ }
34
+ }
35
+ if (G->flag&LOAD_NODEW) calloc2 (G->node_w, nodes, "SGRAPH_alloc: node_w", G->node_w=0);
36
+ if ( ERROR_MES ){ SGRAPH_end (G); EXIT; }
37
+ }
38
+
39
+ /* copy graph G to graph G2. Underconstruction */
40
+ //void SGRAPH_cpy (SGRAPH *G2, SGRAPH *G){}
41
+
42
+ /* free graph object */
43
+ void SGRAPH_end (SGRAPH *G){
44
+ SETFAMILY_end (&G->edge);
45
+ SETFAMILY_end (&G->in);
46
+ SETFAMILY_end (&G->out);
47
+ mfree (G->wbuf, G->perm);
48
+ *G = INIT_SGRAPH;
49
+ }
50
+
51
+
52
+ /* make an edge between u and v.
53
+ If they are already connected, it will be a multiple edge */
54
+ void SGRAPH_edge_mk (SGRAPH *G, QUEUE_INT u, QUEUE_INT v, WEIGHT w){
55
+ if ( G->edge.w ){
56
+ G->edge.w[u][G->edge.v[u].t] = w;
57
+ G->edge.w[v][G->edge.v[v].t] = w;
58
+ }
59
+ ARY_INS (G->edge.v[u], v);
60
+ ARY_INS (G->edge.v[v], u);
61
+ G->edge.eles += 2;
62
+ }
63
+
64
+ /* make an arc between u and v.
65
+ If they are already connected, it will be a multiple arc */
66
+ void SGRAPH_arc_mk (SGRAPH *G, QUEUE_INT u, QUEUE_INT v, WEIGHT w){
67
+ if ( G->out.w ) G->out.w[u][G->out.v[u].t] = w;
68
+ if ( G->in.w ) G->in.w[v][G->in.v[v].t] = w;
69
+ ARY_INS (G->out.v[u], v);
70
+ ARY_INS (G->in.v[v], u);
71
+ G->in.eles++;
72
+ G->out.eles++;
73
+ }
74
+
75
+ /* Delete the edge connecting u and v. If edge (u,v) does not exist, nothing will occur. */
76
+ void SGRAPH_edge_rm_iter (SETFAMILY *M, QUEUE_INT u, QUEUE_INT v){
77
+ QUEUE_INT i;
78
+ if ( (i = (QUEUE_INT)QUEUE_ele (&M->v[u], v)) >= 0 ){
79
+ QUEUE_rm (&M->v[u], i);
80
+ if ( M->w ) M->w[u][i] = M->w[u][M->v[u].t];
81
+ M->eles--;
82
+ }
83
+ }
84
+
85
+ /* Delete the edge connecting u and v. If edge (u,v) does not exist, nothing will occur. */
86
+ void SGRAPH_edge_rm (SGRAPH *G, QUEUE_INT u, QUEUE_INT v){
87
+ SGRAPH_edge_rm_iter (&G->edge, u, v);
88
+ SGRAPH_edge_rm_iter (&G->edge, v, u);
89
+ }
90
+
91
+ /* Delete the arc connecting u and v. If arc (u,v) does not exist, nothing will occur. */
92
+ void SGRAPH_arc_rm (SGRAPH *G, QUEUE_INT u, QUEUE_INT v){
93
+ SGRAPH_edge_rm_iter (&G->out, u, v);
94
+ SGRAPH_edge_rm_iter (&G->in, v, u);
95
+ }
96
+
97
+ /* print graph by numbers */
98
+ void SGRAPH_print (SGRAPH *G){
99
+ VEC_ID i;
100
+ QUEUE_ID j;
101
+ QUEUE_INT e;
102
+
103
+ printf ("#node "VEC_IDF" ,#edge %zd ,#arc %zd\n", SGRAPH_NODE_NUM(*G), G->edge.eles, G->in.eles);
104
+ FLOOP (i, 0, SGRAPH_NODE_NUM(*G)){
105
+ printf ("NODE "VEC_IDF" ", i);
106
+ if ( G->node_w ){ putchar ('('); print_WEIGHT (G->node_w[i]); putchar (')'); }
107
+ printf (" >>\n");
108
+ if ( G->edge.v && G->edge.v[i].t ){
109
+ printf (" edge : ");
110
+ ARY_FLOOP (G->edge.v[i], j, e){
111
+ printf (VEC_IDF, e);
112
+ if ( G->edge.w ){ putchar ('('); print_WEIGHT (G->edge.w[i][j]); putchar (')'); }
113
+ putchar (',');
114
+ }
115
+ putchar ('\n');
116
+ }
117
+ if ( G->in.w ){
118
+ if ( G->in.v[i].t ){
119
+ printf (" in-arc : ");
120
+ ARY_FLOOP (G->in.v[i], j, e){
121
+ printf (VEC_IDF, e);
122
+ if ( G->in.w ){ putchar ('('); print_WEIGHT (G->in.w[i][j]); putchar (')'); }
123
+ putchar (',');
124
+ }
125
+ putchar ('\n');
126
+ }
127
+ }
128
+ if ( G->out.w ){
129
+ if ( G->out.v[i].t ){
130
+ printf (" out-arc : ");
131
+ ARY_FLOOP (G->out.v[i], j, e){
132
+ printf (VEC_IDF, e);
133
+ if ( G->out.w ){ putchar ('('); print_WEIGHT (G->out.w[i][j]); putchar (')');}
134
+ putchar (',');
135
+ }
136
+ putchar ('\n');
137
+ }
138
+ }
139
+ }
140
+ }
141
+
142
+ /* Output a graph to file
143
+ Vertices, edges, arcs less than node_num, edge_num, arc_num are written to the file. Input parameters are
144
+ (graph) (file name) (flag)
145
+ SGRAPH_READ_NODEW 512 // read node weight
146
+ SGRAPH_READ_EDGEW 1024 // read edge weight
147
+ */
148
+ /*
149
+ format of file:(including notifications to make input file)
150
+
151
+ the ith row corresponds to node i-1, and
152
+ ID list of nodes adjacent to i, and having ID > i, for undirected graph
153
+ ID list of nodes adjacent to i by out-going arc of i, for directed graph
154
+ Separator is ",", but graph load routine accepts any letter for
155
+ separator but not a number.
156
+ If the graph has both edges and arcs, write them in two lines separately,
157
+ so a node then uses two lines, and #nodes = #lines/2.
158
+
159
+ == Notifications to make input file ==
160
+ Notice that if 0th line has node 2, and the 2nd line has 0, then there
161
+ will be multiple edge (0,2) and (2,0).
162
+ The read routine does not make error with multiple edges, it is allowed.
163
+
164
+ The ID of nodes begin from 0. After reading graph, node_num is set to
165
+ node_end.
166
+
167
+ Input file example, without weights, E={(0,1),(0,2),(1,1),(1,3),(2,3)}
168
+ ===========
169
+ 1,2
170
+ 1 3
171
+ 3
172
+
173
+ [EOF]
174
+ =========
175
+ Nodes are 0,1, and 2, both edges and arcs exist, with node/edge/arc weights)
176
+ 5000,1,30
177
+ 0,50,1,20,
178
+ 100,1,3
179
+ 2,20
180
+ 200
181
+
182
+ [EOF]
183
+ =======
184
+ where node weights are 5000, 100, 200, and edges and their weights are
185
+ (0,1),30, (1,1),3
186
+ arcs and their weights are (0,0),50, (0,1), 20, (1,2), 20
187
+
188
+ In the case of bipartite graph, write the adjacent-node lists only for
189
+ the node in node set one.
190
+
191
+
192
+ */
193
+
194
+ /* graph load routine. Allocate memory as much as the size of input file.
195
+ parameters are,
196
+ (graph) (file name)
197
+ LOAD_EDGE // read undirected edge from file
198
+ LOAD_ARC // read directed arc from file
199
+ LOAD_BIPARTITE // load bipartite graph
200
+ LOAD_NODEW // read node weight
201
+ LOAD_EDGEW // read edge weight
202
+ */
203
+ /* In the bipartite case, even if the IDs of node set 2 begin from 0, i.e.,
204
+ overlaps with node 1, the routine automatically correct them. */
205
+ /* Directed bipartite graph, all arcs are considered to be from node set 1
206
+ to node set 2. If both directions exist, read as a general graph, and set
207
+ node1_num later in some way. */
208
+ /* The routine compares the maximum node index and #lines, and set #node
209
+ to the larger one. However, if node weight exists, weights will be included
210
+ in the candidates of maximum index, thus in this case we fix #node := #lines.
211
+ In the case of bipartite graph, the routine compares, but the weights of
212
+ non-existing lines will be -1. */
213
+
214
+ /* make the opposite direction edge, for each edge; buffers have to be already doubly allocated */
215
+ void SGRAPH_load_delivery (SGRAPH *G, SETFAMILY *OO, SETFAMILY *MM, QUEUE_ID *c){
216
+ VEC_ID i;
217
+ QUEUE_ID j;
218
+ QUEUE_INT e;
219
+ FLOOP (i, 0, MM->t) c[i] = MM->v[i].t;
220
+ FLOOP (i, 0, MM->t){
221
+ FLOOP (j, 0, c[i]){
222
+ e = MM->v[i].v[j];
223
+ if ( OO->w ) OO->w[e][OO->v[e].t] = MM->w[i][j];
224
+ ARY_INS (OO->v[e], i);
225
+ }
226
+ }
227
+ }
228
+
229
+ /* make the opposite direction edge, for each edge; buffers have to be already doubly allocated */
230
+ void SGRAPH_mk_opposite_edge (SGRAPH *G, QUEUE_ID *c){
231
+ VEC_ID i;
232
+ size_t j, jj;
233
+ j = G->edge.eles; // shift the arrays to insert edges of opposite directions
234
+ BLOOP (i, G->edge.t, 0){
235
+ j -= G->edge.v[i].t+c[i];
236
+ jj = G->edge.v[i].t+1;
237
+ do {
238
+ jj--;
239
+ G->edge.buf[j+i+jj] = G->edge.v[i].v[jj];
240
+ } while ( jj>0 );
241
+ G->edge.v[i].end += c[i];
242
+ G->edge.v[i].v = &G->edge.buf[j+i];
243
+ if ( G->edge.w ){
244
+ memcpy ( &G->edge.buf[j], G->edge.w[i], sizeof(WEIGHT)*G->edge.v[i].t );
245
+ G->edge.w[i] = &G->edge.wbuf[j];
246
+ }
247
+ }
248
+ }
249
+
250
+ /* load edges/arcs (determined by G->flag) from file */
251
+ void SGRAPH_load (SGRAPH *G, char *fname, char *wfname){
252
+ VEC_ID i;
253
+ QUEUE_ID *c;
254
+ SETFAMILY *F1, *F2;
255
+
256
+ if ( G->flag&LOAD_EDGE ){ F1 = F2 = &G->edge; G->edge.flag |= LOAD_DBLBUF; }
257
+ else { F1 = &G->in; F2 = &G->out; }
258
+ SETFAMILY_load (F1, fname, wfname);
259
+ // adjact so that #rows and #colums are the same
260
+ if ( !(G->flag&LOAD_BIPARTITE)){
261
+ if ( F1->clms < F1->t ){
262
+ F1->clms = F1->t;
263
+ FLOOP (i, 0, F1->t) F1->v[i].v[F1->v[i].t] = F1->t; // re-set endmark
264
+ } else if ( F1->clms > F1->t ){
265
+ reallocx_ (F1->v, F1->t, F1->clms, INIT_QUEUE, "SGRAPH_load: v", EXIT);
266
+ FLOOP (i, F1->t, F1->clms){
267
+ F1->v[i].v = F1->v[F1->t -1].v +F1->v[F1->t -1].t +1 +(i -(F1->t-1));
268
+ F1->v[i].v[0] = F1->clms;
269
+ } // re-set endmark
270
+ F1->t = F1->clms;
271
+ }
272
+ }
273
+
274
+ calloc2 (c, F1->t, "SGRAPH_load: c", EXIT);
275
+ QUEUE_delivery (NULL, c, NULL, F1->v, NULL, F1->t, F1->t);
276
+ // SETFAMILY_print (stdout, F1);
277
+
278
+ if ( F1 != F2 ) SETFAMILY_alloc (F2, F1->t, c, F1->t, 0);
279
+ else {
280
+ G->edge.eles *= 2; G->edge.ele_end *= 2;
281
+ SGRAPH_mk_opposite_edge (G, c); // shift the arrays to insert edges of opposite directions
282
+ }
283
+
284
+ SGRAPH_load_delivery (G, F2, F1, c);
285
+ free (c);
286
+ F2->clms = F2->t; FLOOP (i, 0, F2->t) F2->v[i].v[F2->v[i].t] = F2->t; // re-set endmark
287
+
288
+ F1->flag |= G->flag; SETFAMILY_sort (F1);
289
+ if ( F1 != F2 ){ F2->flag |= G->flag; SETFAMILY_sort (F2); }
290
+ }
291
+
292
+ /* replace node i by perm[i] */
293
+ void SGRAPH_replace_index (SGRAPH *G, PERM *perm, PERM *invperm){
294
+ QUEUE_INT *x;
295
+ VEC_ID i;
296
+ QUEUE Q;
297
+ WEIGHT *w, ww;
298
+
299
+ FLOOP (i, 0, G->edge.t)
300
+ if ( G->edge.v ){
301
+ MQUE_FLOOP (G->edge.v[i], x) *x = perm[*x];
302
+ ARY_INVPERMUTE (G->edge.v, invperm, Q, G->edge.t, "SGRAPH_repl_ind:", EXIT);
303
+ }
304
+ if ( G->in.v ){
305
+ MQUE_FLOOP (G->in.v[i], x) *x = perm[*x];
306
+ ARY_INVPERMUTE (G->in.v, invperm, Q, G->edge.t, "SGRAPH_repl_ind:", EXIT);
307
+ }
308
+ if ( G->out.v ){
309
+ MQUE_FLOOP (G->out.v[i], x) *x = perm[*x];
310
+ ARY_INVPERMUTE (G->out.v, invperm, Q, G->edge.t, "SGRAPH_repl_ind:", EXIT);
311
+ }
312
+ if ( G->edge.w ) ARY_INVPERMUTE (G->edge.w, invperm, w, G->edge.t, "SGRAPH_repl_ind:", EXIT);
313
+ if ( G->in.w ) ARY_INVPERMUTE (G->in.w, invperm, w, G->edge.t, "SGRAPH_repl_ind:", EXIT);
314
+ if ( G->out.w ) ARY_INVPERMUTE (G->out.w, invperm, w, G->edge.t, "SGRAPH_repl_ind:", EXIT);
315
+ if ( G->node_w ) ARY_INVPERMUTE (G->node_w, invperm, ww, G->edge.t, "SGRAPH_repl_ind:", EXIT);
316
+ G->perm = perm;
317
+ }
318
+
319
+ /* sort the nodes by Q->t, increasing if flag=1, decreasing if flag=-1 */
320
+ void SGRAPH_perm_node (SGRAPH *G, PERM *tmp){
321
+ VEC_ID c1=0, c2=G->node1_num, i;
322
+ PERM *perm;
323
+ malloc2 (perm, G->edge.t, "SGRAPH_perm_node", {free(tmp);EXIT;});
324
+ FLOOP (i, 0, G->edge.t)
325
+ if ( tmp[i]<G->node1_num ) perm[tmp[i]] = c1++; else perm[tmp[i]] = c2++;
326
+ ARY_INV_PERM_ (tmp, perm, G->edge.t);
327
+ SGRAPH_replace_index (G, perm, tmp);
328
+ free2 (tmp);
329
+ }
330
+
331
+ #endif