nysol-zdd 3.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ext/zdd_so/BDD.cc +495 -0
- data/ext/zdd_so/BDD.h +356 -0
- data/ext/zdd_so/BDDDG.cc +1818 -0
- data/ext/zdd_so/BDDDG.h +107 -0
- data/ext/zdd_so/BDDHASH.cc +91 -0
- data/ext/zdd_so/BtoI.cc +503 -0
- data/ext/zdd_so/BtoI.h +144 -0
- data/ext/zdd_so/CtoI.cc +1072 -0
- data/ext/zdd_so/CtoI.h +186 -0
- data/ext/zdd_so/MLZBDDV.cc +153 -0
- data/ext/zdd_so/MLZBDDV.h +42 -0
- data/ext/zdd_so/SOP.cc +608 -0
- data/ext/zdd_so/SOP.h +199 -0
- data/ext/zdd_so/ZBDD.cc +1035 -0
- data/ext/zdd_so/ZBDD.h +243 -0
- data/ext/zdd_so/ZBDDDG.cc +1834 -0
- data/ext/zdd_so/ZBDDDG.h +105 -0
- data/ext/zdd_so/ZBDDHASH.cc +91 -0
- data/ext/zdd_so/bddc.c +2816 -0
- data/ext/zdd_so/bddc.h +132 -0
- data/ext/zdd_so/extconf.rb +25 -0
- data/ext/zdd_so/include/aheap.c +211 -0
- data/ext/zdd_so/include/aheap.h +111 -0
- data/ext/zdd_so/include/base.c +93 -0
- data/ext/zdd_so/include/base.h +60 -0
- data/ext/zdd_so/include/itemset.c +473 -0
- data/ext/zdd_so/include/itemset.h +153 -0
- data/ext/zdd_so/include/problem.c +371 -0
- data/ext/zdd_so/include/problem.h +160 -0
- data/ext/zdd_so/include/queue.c +518 -0
- data/ext/zdd_so/include/queue.h +177 -0
- data/ext/zdd_so/include/sgraph.c +331 -0
- data/ext/zdd_so/include/sgraph.h +170 -0
- data/ext/zdd_so/include/stdlib2.c +832 -0
- data/ext/zdd_so/include/stdlib2.h +746 -0
- data/ext/zdd_so/include/trsact.c +723 -0
- data/ext/zdd_so/include/trsact.h +167 -0
- data/ext/zdd_so/include/vec.c +583 -0
- data/ext/zdd_so/include/vec.h +159 -0
- data/ext/zdd_so/lcm-vsop.cc +596 -0
- data/ext/zdd_so/print.cc +683 -0
- data/ext/zdd_so/table.cc +330 -0
- data/ext/zdd_so/vsop.h +88 -0
- data/ext/zdd_so/zdd_so.cpp +3277 -0
- data/lib/nysol/zdd.rb +31 -0
- 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
|