Version: 1.0
connectivity_graph.cpp
Go to the documentation of this file.
1 #include "connectivity_graph.h"
2 
3 #include <set>
4 //#include <unordered_set>
5 #include <iterator>
6 #include <bitset>
7 
8 // This function creates and initializes an adjacencies graph with name and values starting from a pixel_set
10  graph g(ps.size());
11 
12  for (size_t i = 0; i < g.size(); ++i)
13  g.set_name(i, ps[i].name_);
14 
15  for (size_t i = 0; i < g.size(); ++i) {
16  for (size_t j = i; j < g.size(); ++j) {
17  g[i][j] = g[j][i] = ChebyshevDistance(ps[i], ps[j]) <= 1;
18  }
19  }
20 
21  return g;
22 }
23 
24 static void MakeConnectivitiesRec(size_t i, size_t j, graph& g, const graph& ag, std::set<size_t>& visited) {
25  for (size_t k = 0; k < g.size(); ++k) {
26  if (visited.find(k) == visited.end() && ag[j][k]) {
27  g[i][k] = 1;
28  visited.insert(k);
29  if (g.nodes_[k] != "x")
30  MakeConnectivitiesRec(i, k, g, ag, visited);
31  }
32  }
33 }
35  graph g(ag.size());
36  g.nodes_ = ag.nodes_;
37  g.rnodes_ = ag.rnodes_;
38 
39  for (size_t i = 0; i < g.size(); ++i) {
40  if (ag[i][i]) {
41  std::set<size_t> visited;
42  MakeConnectivitiesRec(i, i, g, ag, visited);
43  }
44  }
45 
46  return g;
47 }
48 
49 static void MakeConnectivitiesRecSpecial(size_t i, size_t j, graph& g, const graph& ag, std::set<size_t>& visited, const std::vector<std::string>& pixel_list) {
50  for (size_t k = 0; k < g.size(); ++k) {
51  if (visited.find(k) == visited.end() && ag[j][k]) {
52  g[i][k] = 1;
53  visited.insert(k);
54  if (std::count(pixel_list.begin(), pixel_list.end(), g.nodes_[k]) == 0)
55  MakeConnectivitiesRecSpecial(i, k, g, ag, visited, pixel_list);
56  }
57  }
58 }
59 graph MakeConnectivitiesSpecial(const graph& ag, const std::vector<std::string>& pixel_list) {
60  graph g(ag.size());
61  g.nodes_ = ag.nodes_;
62  g.rnodes_ = ag.rnodes_;
63 
64  for (size_t i = 0; i < g.size(); ++i) {
65  if (ag[i][i]) {
66  std::set<size_t> visited;
67  MakeConnectivitiesRecSpecial(i, i, g, ag, visited, pixel_list);
68  }
69  }
70 
71  return g;
72 }
73 
74 std::ostream& operator<<(std::ostream& os, const graph& g) {
75  using std::copy; using std::begin; using std::end; using std::string;
76  os << " ";
77  copy(begin(g.nodes_), end(g.nodes_), std::ostream_iterator<string>(os, " "));
78  os << "\n";
79 
80  for (size_t i = 0; i < g.arcs_.size(); ++i) {
81  os << g.nodes_[i] << " ";
82  copy(begin(g.arcs_[i]), end(g.arcs_[i]), std::ostream_iterator<int>(os, " "));
83  os << "\n";
84  }
85 
86  return os;
87 }
88 
89 bool graph::Write(const std::string& filename)
90 {
91  std::ofstream os(filename);
92  if (os) {
93  os << *this;
94  return true;
95  }
96  else {
97  return false;
98  }
99 }
100 
101 // Less operator for bitset
102 template<size_t N>
103 struct less {
104  bool operator()(const std::bitset<N>& lhs, const std::bitset<N>& rhs) const {
105  return lhs.to_string() < rhs.to_string();
106  }
107 };
108 
109 // This function generates all possible actions, avoiding useless ones such as merges between adjacent pixels
110 std::vector<std::string> GenerateAllPossibleLabelingActions(const graph& ag)
111 {
112  auto nconds = ag.size();
113  auto nrules = 1u << nconds;
114  std::set<std::bitset<128>, less<128>> actions_set; // Set of actions described as list of pixels to be merged
115  std::vector<std::string> actions = { "nothing" };
116 
117  auto posx = ag.rnodes_.at("x");
118  for (size_t rule = 0; rule < nrules; ++rule) {
119  if ((rule >> posx) & 1) {
120  std::bitset<128> cur_action = 0;
121  std::vector<size_t> cur_conds;
122  for (size_t j = 0; j < nconds; ++j) {
123  if (j != posx && ((rule >> j) & 1) == 1) {
124  bool adj = false;
125  for (size_t k = 0; k < cur_conds.size(); ++k) {
126  if (ag[j][cur_conds[k]] == 1) {
127  adj = true;
128  break;
129  }
130  }
131  cur_conds.push_back(j);
132  if (!adj) {
133  cur_action.set(j);
134  }
135  }
136  }
137  actions_set.insert(cur_action);
138  }
139  }
140 
141  for (const auto& a : actions_set) {
142  std::string action = "x<-";
143  for (size_t j = 0; j < nconds; ++j) {
144  if (a[j]) {
145  action += ag.nodes_[j] + "+";
146  }
147  }
148  if (action == "x<-")
149  action += "newlabel";
150  else
151  action.resize(action.size() - 1); // remove last + sign
152 
153  actions.push_back(action);
154  }
155 
156  return actions;
157 }
158 
159 // This function generates all possible actions, avoiding useless ones such as merges between adjacent pixels. This version allows
160 // to consider reference pixel with a name different from x
161 std::vector<std::string> GenerateAllPossibleLabelingActions(const graph& ag, const std::string& ref_pixel_name)
162 {
163  auto nconds = ag.size();
164  auto nrules = 1u << nconds;
165  std::set<std::bitset<128>, less<128>> actions_set; // Set of actions described as list of pixels to be merged
166  std::vector<std::string> actions = { "nothing" };
167 
168  auto posx = ag.rnodes_.at(ref_pixel_name);
169  for (size_t rule = 0; rule < nrules; ++rule) {
170  if ((rule >> posx) & 1) {
171  std::bitset<128> cur_action = 0;
172  std::vector<size_t> cur_conds;
173  for (size_t j = 0; j < nconds; ++j) {
174  if (j != posx && ((rule >> j) & 1) == 1) {
175  bool adj = false;
176  for (size_t k = 0; k < cur_conds.size(); ++k) {
177  if (ag[j][cur_conds[k]] == 1) {
178  adj = true;
179  break;
180  }
181  }
182  cur_conds.push_back(j);
183  if (!adj) {
184  cur_action.set(j);
185  }
186  }
187  }
188  actions_set.insert(cur_action);
189  }
190  }
191 
192  for (const auto& a : actions_set) {
193  std::string action = ref_pixel_name + "<-";
194  for (size_t j = 0; j < nconds; ++j) {
195  if (a[j]) {
196  action += ag.nodes_[j] + "+";
197  }
198  }
199  if (action == ref_pixel_name + "<-")
200  action += "newlabel";
201  else
202  action.resize(action.size() - 1); // remove last + sign
203 
204  actions.push_back(action);
205  }
206 
207  return actions;
208 }
209 
210 void PrintActionsSet(std::set<std::bitset<128>, less<128>>& to_print, std::ostream& os) {
211  for (const auto& x : to_print) {
212  os << x.to_string().substr(119) << "\n";
213  }
214 }
215 
218 //std::vector<std::string> GenerateAllPossibleLabelingActionsGivenTheSetOfPixelToBeLabeled(const graph& ag, const std::vector<std::string>& to_be_labeled_pixels)
219 //{
220 // auto nconds = ag.size();
221 // auto nrules = 1u << nconds;
222 //
223 // // Vector of set of actions described as pixels to be merged (bitmapped). The vector contains as many sets as the number of
224 // // pixels to be labeled
225 // std::vector<std::set<std::bitset<128>, less<128>>> actions_set(to_be_labeled_pixels.size());
226 // std::vector<std::vector<std::string>> actions(to_be_labeled_pixels.size());
227 //
228 // //auto posx = ag.rnodes_.at("x");
229 // std::vector<size_t> posp(to_be_labeled_pixels.size());
230 // for (size_t i = 0; i < to_be_labeled_pixels.size(); ++i) {
231 // posp[i] = ag.rnodes_.at(to_be_labeled_pixels[i]);
232 // }
233 //
234 // for (size_t i = 0; i < to_be_labeled_pixels.size(); ++i) {
235 // auto posx = posp[i];
236 // for (size_t rule = 0; rule < nrules; ++rule) {
237 // if ((rule >> posx) & 1) {
238 // std::bitset<128> cur_action = 0;
239 // std::vector<int> cur_conds;
240 // for (size_t j = 0; j < nconds; ++j) {
241 //
242 // bool is_in_the_labe_set = false;
243 // for (size_t lss = 0 + i; lss < to_be_labeled_pixels.size(); ++lss) {
244 // if (j == posp[lss]) {
245 // is_in_the_labe_set = true;
246 // break;
247 // }
248 // }
249 //
250 // if (!is_in_the_labe_set && ((rule >> j) & 1) == 1) {
251 // bool adj = false;
252 // for (size_t k = 0; k < cur_conds.size(); ++k) {
253 // if (ag[j][cur_conds[k]] == 1) {
254 // adj = true;
255 // break;
256 // }
257 // }
258 // cur_conds.push_back(j);
259 // if (!adj) {
260 // cur_action.set(j);
261 // }
262 // }
263 // }
264 // actions_set[i].insert(cur_action);
265 // }
266 // }
267 // }
268 //
269 //
270 // {
271 // std::ofstream os("actions_set.txt");
272 // for (int i = ag.nodes_.size() - 1; i >= 0; --i) {
273 // os << ag.nodes_[i];
274 // }
275 // os << "\n";
276 // PrintActionsSet(actions_set[0], os);
277 // os << "\n";
278 // PrintActionsSet(actions_set[1], os);
279 // os << "\n";
280 // PrintActionsSet(actions_set[2], os);
281 //
282 // }
283 //
284 // for (size_t i = 0; i < actions_set.size(); ++i) {
285 // std::vector<std::string> cur_actions = { "nothing" };
286 // auto cur_actions_set = actions_set[i];
287 // for (const auto& a : cur_actions_set) {
288 // std::string action = to_be_labeled_pixels[i] + "<-";
289 // for (size_t j = 0; j < nconds; ++j) {
290 // if (a[j]) {
291 // action += ag.nodes_[j] + "+";
292 // }
293 // }
294 // if (action == to_be_labeled_pixels[i] + "<-")
295 // action += "newlabel";
296 // else
297 // action.resize(action.size() - 1); // remove last + sign
298 //
299 // cur_actions.push_back(action);
300 // }
301 // actions[i] = cur_actions;
302 // }
303 //
304 // //std::set<std::string> final_actions;
305 // std::vector<std::string> final_actions;
306 //
307 // for (size_t e = 0; e < actions[0].size(); ++e) {
308 // for (size_t g = 0; g < actions[1].size(); ++g) {
309 // for (size_t i = 0; i < actions[2].size(); ++i) {
310 // std::string es = actions[0][e], gs = actions[1][g], is = actions[2][i];
311 // /*if (es.substr(3) == gs.substr(3) && es != "nothing") {
312 // gs = "g<-e";
313 // }
314 //
315 // if (es.substr(3) == is.substr(3) && es != "nothing") {
316 // is = "i<-e";
317 // }
318 //
319 // if (gs.substr(3) == is.substr(3) && gs != "nothing") {
320 // is = "i<-g";
321 // }*/
322 //
323 // //final_actions.insert(es + "," + gs + "," + is);
324 // final_actions.push_back(es + "," + gs + "," + is);
325 // }
326 // }
327 // }
328 //
329 // /*std::vector<std::string> return_val(final_actions.size());
330 // std::copy(final_actions.begin(), final_actions.end(), return_val.begin());
331 //
332 // return return_val;*/
333 // return final_actions;
334 //}
336 
337 #include "merge_set.h"
338 // This function generates all possible actions, avoiding useless ones such as merges between adjacent pixels and considering multiple pixels inside the mask
339 std::vector<std::string> GenerateAllPossibleLabelingActionsGivenTheSetOfPixelToBeLabeled(const graph& ag, const std::vector<std::string>& to_be_labeled_pixels, rule_set& rs)
340 {
341  std::set<std::string> actions;
342 
343  auto nconds = ag.size();
344  auto nrules = 1u << nconds;
345 
346  for (int i = 0; i < static_cast<int>(nrules); ++i) {
347  rule_wrapper r(rs, i);
348 
349  auto lag = ag;
350  for (size_t j = 0; j < lag.size(); ++j) {
351  if (((i >> j) & 1) == 0)
352  lag.DetachNode(j);
353  }
354 
355  std::vector<std::string> e_actions;
356  if (r["e"]) {
357  graph cg = MakeConnectivitiesSpecial(lag, std::vector<std::string>{"e", "g", "i"});
359  con.data_ = cg.arcs_;
360 
361  MultiMergeSet mse(con, std::vector<std::string>({ "e", "g", "i" }), std::string("e"));
362  mse.BuildMergeSet();
363  for (const auto& s : mse.mergesets_) {
364  std::string action = "e<-";
365  if (s.empty())
366  action += "newlabel";
367  else {
368  action += s[0];
369  for (size_t i = 1; i < s.size(); ++i)
370  action += "+" + s[i];
371  }
372  e_actions.push_back(action);
373  }
374  }
375  else {
376  e_actions.push_back("nothing");
377  }
378 
379  std::vector<std::string> g_actions;
380  if (r["g"]) {
381  graph cg = MakeConnectivitiesSpecial(lag, std::vector<std::string>{"g", "i"});
383  con.data_ = cg.arcs_;
384  MultiMergeSet msg(con, std::vector<std::string>({ "g", "i" }), std::string("g"));
385  msg.BuildMergeSet();
386 
387  for (const auto& s : msg.mergesets_) {
388  std::string action = "g<-";
389  if (s.empty())
390  action += "newlabel";
391  else {
392  action += s[0];
393  for (size_t i = 1; i < s.size(); ++i)
394  action += "+" + s[i];
395  }
396  g_actions.push_back(action);
397  }
398  }
399  else {
400  g_actions.push_back("nothing");
401  }
402 
403  std::vector<std::string> i_actions;
404  if (r["i"]) {
405  graph cg = MakeConnectivitiesSpecial(lag, std::vector<std::string>{"i"});
407  con.data_ = cg.arcs_;
408  MultiMergeSet msi(con, std::vector<std::string>({ "i" }), std::string("i"));
409  msi.BuildMergeSet();
410 
411  for (const auto& s : msi.mergesets_) {
412  std::string action = "i<-";
413  if (s.empty())
414  action += "newlabel";
415  else {
416  action += s[0];
417  for (size_t i = 1; i < s.size(); ++i)
418  action += "+" + s[i];
419  }
420  i_actions.push_back(action);
421  }
422  }
423  else {
424  i_actions.push_back("nothing");
425  }
426 
427  for (const auto& ae : e_actions) {
428  for (const auto& ag : g_actions) {
429  for (const auto& ai : i_actions) {
430  std::string es = ae, gs = ag, is = ai;
431  size_t found = es.find(gs.substr(3));
432  if (found != std::string::npos && es != "nothing" && es != "e<-newlabel") {
433  gs = "g<-e";
434  }
435  found = es.find(is.substr(3));
436  if (found != std::string::npos && es != "nothing" && es != "e<-newlabel") {
437  is = "i<-e";
438  }
439  found = gs.find(is.substr(3));
440  if (found != std::string::npos && gs != "nothing" && gs != "g<-newlabel") {
441  is = "i<-g";
442  }
443  actions.insert(es + "," + gs + "," + is);
444  }
445  }
446  }
447  }
448 
449  std::vector<std::string> return_val(actions.size());
450  std::copy(actions.begin(), actions.end(), return_val.begin());
451 
452  return return_val;
453 
454  //return actions;
455 }
graph MakeConnectivitiesSpecial(const graph &ag, const std::vector< std::string > &pixel_list)
std::ostream & operator<<(std::ostream &os, const graph &g)
std::vector< std::string > GenerateAllPossibleLabelingActionsGivenTheSetOfPixelToBeLabeled(const graph &ag, const std::vector< std::string > &to_be_labeled_pixels, rule_set &rs)
VERSION WITH MANY MORE ACTIONS THAN NECESSARY / This function generates all possible actions,...
std::vector< std::string > GenerateAllPossibleLabelingActions(const graph &ag)
graph MakeAdjacencies(const pixel_set &ps)
graph MakeConnectivities(const graph &ag)
void PrintActionsSet(std::set< std::bitset< 128 >, less< 128 >> &to_print, std::ostream &os)
void BuildMergeSet()
Definition: merge_set.h:119
std::set< std::vector< std::string > > mergesets_
Definition: merge_set.h:69
std::vector< std::vector< int > > arcs_
void set_name(size_t i, const std::string &name)
std::vector< std::string > nodes_
std::map< std::string, size_t > rnodes_
bool Write(const std::string &filename)
auto size() const
void DetachNode(size_t i)
bool operator()(const std::bitset< N > &lhs, const std::bitset< N > &rhs) const
auto size() const
Definition: pixel_set.h:126
std::vector< std::string > conditions
Definition: rule_set.h:48
Definition: rule_set.h:41