Add a new dumper
[libfirm] / ir / adt / bipartite.c
1
2 #include <stdio.h>
3 #include <assert.h>
4
5 #include "bitset.h"
6 #include "bipartite.h"
7 #include "xmalloc.h"
8
9 struct _bipartite_t {
10         int n_left, n_right;
11         bitset_t *adj[1];
12 };
13
14 bipartite_t *bipartite_new(int n_left, int n_right)
15 {
16         int i, size;
17         bipartite_t *gr;
18
19         size = n_left > 0 ? n_left - 1 : 0;
20         gr = xmalloc(sizeof(*gr) + size * sizeof(void *));
21         memset(gr, 0, sizeof(*gr));
22
23         gr->n_left = n_left;
24         gr->n_right = n_right;
25
26         for(i = 0; i < n_left; ++i)
27                 gr->adj[i] = bitset_malloc(n_right);
28
29         return gr;
30 }
31
32 void bipartite_free(bipartite_t *gr)
33 {
34         int i;
35         for(i = 0; i < gr->n_left; ++i)
36                 bitset_free(gr->adj[i]);
37         free(gr);
38 }
39
40 void bipartite_add(bipartite_t *gr, int i, int j)
41 {
42         assert(i < gr->n_left && j < gr->n_right);
43         bitset_set(gr->adj[i], j);
44 }
45
46 void bipartite_remv(bipartite_t *gr, int i, int j)
47 {
48         assert(i < gr->n_left && j < gr->n_right);
49         bitset_clear(gr->adj[i], j);
50 }
51
52 int bipartite_adj(const bipartite_t *gr, int i, int j)
53 {
54         assert(i < gr->n_left && j < gr->n_right);
55         return bitset_is_set(gr->adj[i], j);
56 }
57
58 static int apply_alternating_path(const bipartite_t *gr, int *matching,
59                 bitset_t *matched_left, bitset_t *matched_right)
60 {
61         int left, right;
62         int done_something = 0;
63         bitset_t *tmp = bitset_alloca(gr->n_right);
64
65         for(left = 0; left < gr->n_left; ++left) {
66                 bitset_t *left_adj = gr->adj[left];
67                 int i;
68
69                 bitset_copy(tmp, left_adj);
70
71                 if(matching[left] >= 0) {
72                         int old_right = matching[left];
73
74                         /* Check of all neighbors of the left node are already matched.
75                          * We cannot improve this edge then. */
76                         if(bitset_contains(left_adj, matched_right))
77                                 continue;
78
79                         bitset_andnot(tmp, matched_right);
80                         right = bitset_next_set(tmp, 0);
81
82                         assert(right != -1);
83
84                         /*
85                                 We have to find another left node which has the old right one as a neighbor.
86                                 This node must not be part of a matching
87                         */
88                         for(i = 0; i < gr->n_left; ++i)
89                                 if(i != left && bitset_is_set(gr->adj[i], old_right) && !bitset_is_set(matched_left, i))
90                                         break;
91
92                         /* If no such node can be found, exit. */
93                         if(i >= gr->n_left)
94                                 continue;
95
96                         /* Else, we can improve this edge. */
97                         matching[left] = right;
98                         matching[i] = old_right;
99                         bitset_set(matched_left, i);
100                         bitset_set(matched_right, right);
101                         done_something = 1;
102                 }
103
104
105                 /* We have to create a new single edge */
106                 else {
107                         assert(!bitset_is_set(matched_left, left));
108
109                         bitset_andnot(tmp, matched_right);
110                         if(bitset_popcnt(tmp) == 0)
111                                 continue;
112
113                         right = bitset_min(tmp);
114                         assert(!bitset_is_set(matched_right, right));
115                         matching[left] = right;
116                         bitset_set(matched_left, left);
117                         bitset_set(matched_right, right);
118                         done_something = 1;
119                 }
120         }
121
122         return done_something;
123 }
124
125 void bipartite_matching(const bipartite_t *gr, int *matching)
126 {
127         bitset_t *matched_left = bitset_alloca(gr->n_left);
128         bitset_t *matched_right = bitset_alloca(gr->n_right);
129
130         memset(matching, -1, gr->n_left * sizeof(int));
131         while(apply_alternating_path(gr, matching, matched_left, matched_right));
132 }
133
134 void bipartite_dump_f(FILE *f, const bipartite_t *gr)
135 {
136         int i;
137
138         for(i = 0; i < gr->n_left; ++i) {
139                 bitset_fprint(f, gr->adj[i]);
140                 fprintf(f, "\n");
141         }
142 }
143
144 void bipartite_dump(const char *name, const bipartite_t *gr) {
145         FILE *f = fopen(name, "w");
146
147         if (f) {
148                 bipartite_dump_f(f, gr);
149                 fclose(f);
150         }
151 }