//template <typename T> std::vector< int64_t > rand_permute(const int64_t& N, std::default_random_engine& rand_gen) { std::vector< int64_t > permuted(N, 0); std::vector< float64_t > permuted_probs(N, 0); std::uniform_real_distribution<float64_t> dist(0.0, 1.0); //Does NOT include B, i.e. [0, 1) for(size_t a=0; a<N; ++a) { permuted[a] = a; permuted_probs[a] = dist(rand_gen); } //sort it sorter<float64_t> bob( &permuted_probs[0] , permuted_probs.size() ); bob.add_l( &permuted[0] ); //lol must be int, what if we make size_T? Need to mod sorter algo? bob.runsort(); //and now we check ordering of index values if we want...? return permuted; }
bool sign_matrix(M& matrix, submatrix_indices* violator) { bool result = true; matrix_permuted <M> permuted(matrix); size_t handled_rows = 0; /// Go trough column by column. for (size_t handled_columns = 0; handled_columns < permuted.size2(); ++handled_columns) { if (find_nonzero_column(permuted, handled_columns, permuted.size2(), 0, handled_rows, handled_columns)) { /// There is a non-zero column right of the already-handled submatrix. std::set <size_t> start_nodes; std::set <size_t> end_nodes; std::set <size_t> all_nodes; bipartite_graph_dimensions dim(handled_rows, handled_columns); for (size_t row = 0; row < handled_rows; ++row) { if (permuted(row, handled_columns) != 0) { size_t index = dim.row_to_index(row); if (start_nodes.empty()) start_nodes.insert(index); else end_nodes.insert(index); all_nodes.insert(index); } } /// Start a BFS on bipartite graph of the submatrix and look for shortest paths from first 1 to all others std::vector <bipartite_graph_bfs_node> bfs_result; if (!bipartite_graph_bfs(permuted, dim, start_nodes, end_nodes, true, bfs_result)) throw std::logic_error("Signing procedure: Did not reach all nodes via bfs!"); /// Evaluate matrix-entries on the shortest paths std::map <size_t, bool> changes; for (typename std::set <size_t>::const_iterator iter = end_nodes.begin(); iter != end_nodes.end(); ++iter) { check_sign(permuted, bfs_result, dim, all_nodes, *iter, handled_columns, changes); } /// Checking changes for (std::map <size_t, bool>::iterator iter = changes.begin(); iter != changes.end(); ++iter) { if (!iter->second) continue; if (boost::is_const <M>::value) { if (violator) { /// Find the violator, going along the path std::set <size_t> violator_rows, violator_columns; size_t index = iter->first; do { if (dim.is_row(index)) violator_rows.insert(permuted.perm1()(dim.index_to_row(index))); else violator_columns.insert(permuted.perm2()(dim.index_to_column(index))); index = bfs_result[index].predecessor; } while (all_nodes.find(index) == all_nodes.end()); violator_rows.insert(permuted.perm1()(dim.index_to_row(index))); violator_columns.insert(permuted.perm2()(handled_columns)); /// Fill violator data violator->rows = submatrix_indices::indirect_array_type(violator_rows.size()); violator->columns = submatrix_indices::indirect_array_type(violator_columns.size()); size_t i = 0; for (std::set <size_t>::const_iterator iter = violator_rows.begin(); iter != violator_rows.end(); ++iter) violator->rows[i++] = *iter; i = 0; for (std::set <size_t>::const_iterator iter = violator_columns.begin(); iter != violator_columns.end(); ++iter) violator->columns[i++] = *iter; } return false; } else { /// We are not just testing, so swap the sign on a one. size_t real_row = permuted.perm1()(dim.index_to_row(iter->first)); size_t real_column = permuted.perm2()(handled_columns); matrix_set_value(matrix, real_row, real_column, -matrix(real_row, real_column)); result = false; } } matrix_reorder_rows(permuted, handled_rows, permuted.size1(), handled_columns, permuted.size2(), abs_greater <int> ()); /// Augment submatrix by rows with 1 in the new column. while (handled_rows < permuted.size1()) { if (permuted(handled_rows, handled_columns) == 0) break; else ++handled_rows; } } else { /// Handled upper-left submatrix and lower-right submatrix are disconnected for (size_t column = handled_columns; column < permuted.size2(); ++column) { size_t count = 0; for (size_t row = handled_rows; row < permuted.size1(); ++row) { if (permuted(row, column) != 0) ++count; } /// A zero column can be skipped, as it is handled by definition. if (count > 0) { /// Found a nonzero column and swap ones to the top. matrix_reorder_rows(permuted, handled_rows, permuted.size1(), handled_columns, permuted.size2(), abs_greater <int> ()); while (handled_rows < permuted.size1()) { if (permuted(handled_rows, handled_columns) == 0) break; else ++handled_rows; } break; } } } } return result; }