CMR  1.3.0
signing.hpp
Go to the documentation of this file.
1 #pragma once
2 
4 
5 #include <set>
6 
7 #include <boost/type_traits/is_const.hpp>
8 
9 #include "matrix_transposed.hpp"
10 #include "matrix_permuted.hpp"
11 #include "matrix_reorder.hpp"
12 #include "matrix.hpp"
13 #include "bipartite_graph_bfs.hpp"
14 
15 namespace tu
16 {
17 
30  template <typename MatrixType>
31  bool find_nonzero_column(MatrixType& matrix, size_t column_first, size_t column_beyond, size_t row_first, size_t row_beyond, size_t target_column)
32  {
33  for (size_t column = column_first; column < column_beyond; ++column)
34  {
35  for (size_t row = row_first; row < row_beyond; ++row)
36  {
37  if (matrix(row, column) != 0)
38  {
39  matrix_permute2(matrix, target_column, column);
40  return true;
41  }
42 
43  }
44  }
45  return false;
46  }
47 
60  template <typename MatrixType>
61  void check_sign(const MatrixType& matrix, const std::vector <bipartite_graph_bfs_node>& spanning_tree, const bipartite_graph_dimensions& dim,
62  const std::set <size_t>& nodes, size_t current_index, size_t column, std::map <size_t, bool>& changes)
63  {
65  if (spanning_tree[current_index].predecessor == current_index)
66  {
67  changes[dim.index_to_row(current_index)] = false;
68  return;
69  }
70 
72  int value = matrix(dim.index_to_row(current_index), column);
73  size_t last, index = current_index;
74  do
75  {
76  last = index;
77  index = spanning_tree[index].predecessor;
78  std::pair <size_t, size_t> coords = dim.indexes_to_coordinates(index, last);
79  value += matrix(coords.first, coords.second);
80  }
81  while (nodes.find(index) == nodes.end());
82 
84  if (changes.find(dim.index_to_row(index)) == changes.end())
85  {
86  check_sign(matrix, spanning_tree, dim, nodes, index, column, changes);
87  }
88 
89  value += matrix(dim.index_to_row(index), column);
90  if (changes[dim.index_to_row(index)])
91  {
92  value += 2;
93  }
94 
95  value = (value >= 0 ? value : -value) % 4;
97  changes[dim.index_to_row(current_index)] = (value == 2);
98 
99  if (value != 0 && value != 2)
100  {
101  throw std::logic_error("Signing procedure: modulo-sum of cycle was neither 0, nor 2!");
102  }
103  }
104 
109  template <typename T>
110  struct abs_greater
111  {
120  bool operator()(const T& first, const T& second)
121  {
122  T abs_first = first >= 0 ? first : -first;
123  T abs_second = second >= 0 ? second : -second;
124  return abs_first > abs_second;
125  }
126  };
127 
137  template <typename M>
138  bool sign_matrix(M& matrix, submatrix_indices* violator)
139  {
140  bool result = true;
141  matrix_permuted <M> permuted(matrix);
142  size_t handled_rows = 0;
143 
145  for (size_t handled_columns = 0; handled_columns < permuted.size2(); ++handled_columns)
146  {
147  if (find_nonzero_column(permuted, handled_columns, permuted.size2(), 0, handled_rows, handled_columns))
148  {
150 
151  std::set <size_t> start_nodes;
152  std::set <size_t> end_nodes;
153  std::set <size_t> all_nodes;
154 
155  bipartite_graph_dimensions dim(handled_rows, handled_columns);
156  for (size_t row = 0; row < handled_rows; ++row)
157  {
158  if (permuted(row, handled_columns) != 0)
159  {
160  size_t index = dim.row_to_index(row);
161  if (start_nodes.empty())
162  start_nodes.insert(index);
163  else
164  end_nodes.insert(index);
165  all_nodes.insert(index);
166  }
167  }
168 
170 
171  std::vector <bipartite_graph_bfs_node> bfs_result;
172  if (!bipartite_graph_bfs(permuted, dim, start_nodes, end_nodes, true, bfs_result))
173  throw std::logic_error("Signing procedure: Did not reach all nodes via bfs!");
174 
176  std::map <size_t, bool> changes;
177  for (typename std::set <size_t>::const_iterator iter = end_nodes.begin(); iter != end_nodes.end(); ++iter)
178  {
179  check_sign(permuted, bfs_result, dim, all_nodes, *iter, handled_columns, changes);
180  }
181 
183  for (std::map <size_t, bool>::iterator iter = changes.begin(); iter != changes.end(); ++iter)
184  {
185  if (!iter->second)
186  continue;
187 
188  if (boost::is_const <M>::value)
189  {
190  if (violator)
191  {
193  std::set <size_t> violator_rows, violator_columns;
194 
195  size_t index = iter->first;
196  do
197  {
198  if (dim.is_row(index))
199  violator_rows.insert(permuted.perm1()(dim.index_to_row(index)));
200  else
201  violator_columns.insert(permuted.perm2()(dim.index_to_column(index)));
202 
203  index = bfs_result[index].predecessor;
204  }
205  while (all_nodes.find(index) == all_nodes.end());
206  violator_rows.insert(permuted.perm1()(dim.index_to_row(index)));
207  violator_columns.insert(permuted.perm2()(handled_columns));
208 
210  violator->rows = submatrix_indices::indirect_array_type(violator_rows.size());
211  violator->columns = submatrix_indices::indirect_array_type(violator_columns.size());
212  size_t i = 0;
213  for (std::set <size_t>::const_iterator iter = violator_rows.begin(); iter != violator_rows.end(); ++iter)
214  violator->rows[i++] = *iter;
215  i = 0;
216  for (std::set <size_t>::const_iterator iter = violator_columns.begin(); iter != violator_columns.end(); ++iter)
217  violator->columns[i++] = *iter;
218  }
219  return false;
220  }
221  else
222  {
224  size_t real_row = permuted.perm1()(dim.index_to_row(iter->first));
225  size_t real_column = permuted.perm2()(handled_columns);
226  matrix_set_value(matrix, real_row, real_column, -matrix(real_row, real_column));
227 
228  result = false;
229  }
230  }
231 
232  matrix_reorder_rows(permuted, handled_rows, permuted.size1(), handled_columns, permuted.size2(), abs_greater <int> ());
233 
235  while (handled_rows < permuted.size1())
236  {
237  if (permuted(handled_rows, handled_columns) == 0)
238  break;
239  else
240  ++handled_rows;
241  }
242  }
243  else
244  {
246  for (size_t column = handled_columns; column < permuted.size2(); ++column)
247  {
248  size_t count = 0;
249  for (size_t row = handled_rows; row < permuted.size1(); ++row)
250  {
251  if (permuted(row, column) != 0)
252  ++count;
253  }
254 
256  if (count > 0)
257  {
259  matrix_reorder_rows(permuted, handled_rows, permuted.size1(), handled_columns, permuted.size2(), abs_greater <int> ());
260  while (handled_rows < permuted.size1())
261  {
262  if (permuted(handled_rows, handled_columns) == 0)
263  break;
264  else
265  ++handled_rows;
266  }
267 
268  break;
269  }
270  }
271  }
272  }
273 
274  return result;
275  }
276 
277 } /* namespace tu */
Definition: matrix_permuted.hpp:17
const permutation_type & perm2() const
Definition: matrix_permuted.hpp:92
const permutation_type & perm1() const
Definition: matrix_permuted.hpp:74
size_type size2() const
Definition: matrix_permuted.hpp:65
size_type size1() const
Definition: matrix_permuted.hpp:56
Definition: algorithm.hpp:14
bool bipartite_graph_bfs(const MatrixType &matrix, const bipartite_graph_dimensions &dimensions, const StartNodesContainerType &start_nodes, const EndNodesContainerType &end_nodes, bool reach_all, std::vector< bipartite_graph_bfs_node > &result)
Definition: bipartite_graph_bfs.hpp:182
void check_sign(const MatrixType &matrix, const std::vector< bipartite_graph_bfs_node > &spanning_tree, const bipartite_graph_dimensions &dim, const std::set< size_t > &nodes, size_t current_index, size_t column, std::map< size_t, bool > &changes)
Definition: signing.hpp:61
void matrix_reorder_rows(const MatrixType &matrix, size_t row_first, size_t row_beyond, size_t column_first, size_t column_beyond, ElementLess element_less, permutation &result_permutation)
Definition: matrix_reorder.hpp:110
void matrix_set_value(matrix_permuted< MatrixType > &matrix, size_t row, size_t column, typename MatrixType::value_type value)
Definition: matrix_permuted.hpp:168
bool sign_matrix(M &matrix, submatrix_indices *violator)
Definition: signing.hpp:138
bool find_nonzero_column(MatrixType &matrix, size_t column_first, size_t column_beyond, size_t row_first, size_t row_beyond, size_t target_column)
Definition: signing.hpp:31
void matrix_permute2(MatrixType &matrix, size_t index1, size_t index2)
Definition: matrix.hpp:1740
Definition: signing.hpp:111
bool operator()(const T &first, const T &second)
Definition: signing.hpp:120
Definition: bipartite_graph_bfs.hpp:39
bool is_row(index_type index) const
Definition: bipartite_graph_bfs.hpp:88
std::pair< size_t, size_t > indexes_to_coordinates(index_type first, index_type second) const
Definition: bipartite_graph_bfs.hpp:155
size_t index_to_column(index_type index) const
Definition: bipartite_graph_bfs.hpp:119
index_type row_to_index(size_t row) const
Definition: bipartite_graph_bfs.hpp:130
size_t index_to_row(index_type index) const
Definition: bipartite_graph_bfs.hpp:108
Definition: common.hpp:15
indirect_array_type columns
Definition: common.hpp:20
boost::numeric::ublas::indirect_array< vector_type > indirect_array_type
Definition: common.hpp:17
indirect_array_type rows
Definition: common.hpp:19