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