InteractionGraph::InteractionGraph(MILPP* problem) : graph_t(problem->get_num_cols()) { int ri; /* row index */ int ci; /* col index */ int ni; /* neighbor index */ PackedVector* row; problem_ = problem; /* Start forming variable neighbourhoods by using constraints */ for (ri = 0; ri < problem->get_num_rows(); ri++) { row = problem->get_row(ri); for (ci = 0; ci < row->get_num_elements(); ci++) for (ni = 0; ni < row->get_num_elements(); ni++) { if ((ci == ni) || /* Skip variables with the same index */ edge(row->get_index_by_pos(ci), row->get_index_by_pos(ni), *this).second) continue; /* Add variable with index n as a neighbor for a variable with index c*/ add_edge(row->get_index_by_pos(ci), row->get_index_by_pos(ni), *this); } } }
inline void PackedDeque::append_front(const uint64_t& value) { if (filled == vec.size()) { size_t new_capacity = size_t(factor * vec.size()) + 1; PackedVector new_vec; new_vec.resize(new_capacity); new_vec.set(0, value); for (size_t i = 0; i < filled; i++) { new_vec.set(i + 1, get(i)); } vec = std::move(new_vec); begin_idx = 0; } else { if (begin_idx == 0) { begin_idx = vec.size() - 1; } else { begin_idx--; } vec.set(begin_idx, value); } filled++; }
TEST_F(FidoVectorTest, makeSparse){ EXPECT_EQ(3,pv.size()); EXPECT_EQ(3,pv.numberEntries()); PackedVector sparse = pv.makeSparse(); EXPECT_EQ(6,sparse.size()); EXPECT_EQ(6,sparse.numberEntries()); }
inline void PagedVector::set(const size_t& i, const uint64_t& value) { assert(i < filled); uint64_t anchor = anchors.get(i / page_size); if (anchor == 0) { // this page does not have a non-zero anchor yet, use this one anchors.set(i / page_size, value); anchor = value; } pages[i / page_size].set(i % page_size, to_diff(value, anchor)); }
inline void PackedDeque::append_back(const uint64_t& value) { // expand capacity if necessary if (filled == vec.size()) { size_t new_capacity = size_t(factor * vec.size()) + 1; reserve(new_capacity); } // update the pointer to the back filled++; // set the value vec.set(internal_index(filled - 1), value); }
void MILPP::set_cons_matrix(const PackedMatrix* matrix) { cons_matrix_ = *matrix; for (int i = 0; i < get_num_rows(); i++) { PackedVector* row = get_row(i); for (int j = 0; j < row->get_num_elements(); j++) { col_to_row_mapping_[ row->get_index_by_pos(j) ]->insert(i); row_to_col_mapping_[i]->insert( row->get_index_by_pos(j) ); } } }
inline void PagedVector::pop() { filled--; while (filled + page_size <= pages.size() * page_size) { // the final page is unused now, remove it pages.pop_back(); // TODO: this won't resize since it's an STL vector anchors.pop(); } }
inline void PackedDeque::pop_front() { begin_idx++; if (begin_idx == vec.size()) { begin_idx = 0; } filled--; contract(); }
inline void PagedVector::pop() { filled--; if (filled % page_size == 0) { // we've emptied a page, remove it pages.pop_back(); anchors.pop(); } }
inline void PagedVector::reserve(const size_t& future_size) { if (future_size > pages.size() * page_size) { // how many pages does this require? size_t num_pages = (future_size - 1) / page_size + 1; // note: we don't need to worry about underflow b/c previous condition // implies future_size > 0 // expand anchor and pages vectors out to the capacity of the number of pages anchors.reserve(num_pages); pages.reserve(num_pages); // add the anchors and fixed-width pages in this anchors.resize(num_pages); while (num_pages > pages.size()) { pages.emplace_back(); pages.back().resize(page_size); } } }
inline void PackedDeque::append_back(const uint64_t& value) { if (filled == vec.size()) { size_t new_capacity = size_t(factor * vec.size()) + 1; PackedVector new_vec; new_vec.resize(new_capacity); for (size_t i = 0; i < filled; i++) { new_vec.set(i, get(i)); } new_vec.set(filled, value); vec = std::move(new_vec); begin_idx = 0; filled++; } else { filled++; vec.set(internal_index(filled - 1), value); } }
inline void PackedDeque::append_front(const uint64_t& value) { // expand capacity if necessary if (filled == vec.size()) { size_t new_capacity = size_t(factor * vec.size()) + 1; reserve(new_capacity); } // update the pointer to the front if (begin_idx == 0) { begin_idx = vec.size() - 1; } else { begin_idx--; } // update the pointer to the back filled++; // set the value vec.set(internal_index(0), value); }
inline void PackedDeque::reserve(const size_t& future_size) { if (future_size > vec.size()) { PackedVector new_vec; new_vec.resize(future_size); for (size_t i = 0; i < filled; i++) { new_vec.set(i, get(i)); } vec = std::move(new_vec); begin_idx = 0; } }
inline void PackedDeque::pop_front() { // update the pointer to the beginning begin_idx++; if (begin_idx == vec.size()) { begin_idx = 0; } // update the pointer to the end filled--; // shrink if necessary contract(); }
inline void PagedVector::append(const uint64_t& value) { if (filled % page_size == 0) { // init a new page and a new anchor pages.emplace_back(); pages.back().resize(page_size); anchors.append(0); } // use the logic in set to choose anchor and diff filled++; set(filled - 1, value); }
TEST_F(FidoVectorTest, packedAdd){ const PackedVector pv_const = pv; const PackedVector pv2_const = pv2; PackedVector diff = pv_const.packedAdd(pv2_const); EXPECT_EQ(10,diff[diff.find(1)]); EXPECT_EQ(5,diff[diff.find(2)]); EXPECT_EQ(20,diff[diff.find(3)]); EXPECT_EQ(60,diff[diff.find(5)]); EXPECT_EQ(-10,diff[diff.find(9)]); }
inline void PackedDeque::contract() { size_t shrink_capacity = vec.size() / (factor * factor); if (filled <= shrink_capacity) { PackedVector new_vec; new_vec.resize(filled); for (size_t i = 0; i < filled; i++) { new_vec.set(i, get(i)); } vec = std::move(new_vec); begin_idx = 0; } }
inline void PagedVector::resize(const size_t& new_size) { if (new_size < filled) { // shrink down to the number of pages we would need size_t num_pages = new_size == 0 ? 0 : (new_size - 1) / page_size + 1; anchors.resize(num_pages); pages.resize(num_pages); } else if (new_size > filled) { // make sure we capacity for this many elements reserve(new_size); } filled = new_size; }
inline void PagedVector::resize(size_t new_size) { // how many pages does this require? size_t num_pages = new_size > 0 ? (new_size - 1) / page_size + 1 : 0; anchors.resize(num_pages); // add pages if necessary while (num_pages > pages.size()) { pages.emplace_back(); pages.back().resize(page_size); } // remove pages if necessary pages.resize(num_pages); filled = new_size; }
TEST_F(FidoVectorTest, packedSubtract){ const PackedVector pv_const = pv; const PackedVector pv2_const = pv2; PackedVector diff = pv_const.packedSubtract(pv2_const); EXPECT_EQ(10,diff[diff.find(1)]); EXPECT_EQ(-5,diff[diff.find(2)]); EXPECT_EQ(20,diff[diff.find(3)]); EXPECT_EQ(10,diff[diff.find(9)]); EXPECT_EQ(4,diff.numberEntries()); }
void MILPP::print() { int i; int j; int offset; /* Print objective function sense and its coefficients */ for (int i = 0; i < get_num_cols(); ++i) { if (i) printf(" + "); printf("%.1fx%d", get_obj_coef(i), i); } printf(" -> %s\n", obj_sense_to_string()); /* Print constraints represented by rows */ printf("subject to\n"); for (i = 0; i < cons_matrix_.get_num_rows(); i++) { int t = 0; /* start from col zero */ PackedVector* row = cons_matrix_.get_vector(i); printf("(%d) ", i); for (j = 0; j < row->get_num_elements(); j++) { if (j > 0) printf(" + "); //printf("[%d|%d]", row->get_index_by_pos(j), t); if ((offset = row->get_index_by_pos(j) - t) >= 1) { if (j > 0) offset -= 1; //printf("(%d)", offset); offset *= 5 + 3; for (int s = 0; s < offset; s++) printf(" "); } t = row->get_index_by_pos(j); printf("%.1fx%d", row->get_element_by_pos(j), row->get_index_by_pos(j)); } /* Print row sense */ printf(" <= "); /* Print row upper bound */ printf("%.1f", get_row_upper_bound(i)); printf("\n"); } }
inline void PackedSplayTree::set_left(size_t x, size_t y) { tree.set((x - 1) * NODE_SIZE + LEFT_CHILD_OFFSET, y); }
inline uint64_t PackedDeque::get(const size_t& i) const { return vec.get(internal_index(i)); }
inline void PagedVector::clear() { pages.clear(); anchors.clear(); filled = 0; }
inline void PackedSplayTree::set_right(size_t x, size_t y) { tree.set((x - 1) * NODE_SIZE + RIGHT_CHILD_OFFSET, y); }
inline void PackedSplayTree::set_parent(size_t x, size_t y) { tree.set((x - 1) * NODE_SIZE + PARENT_OFFSET, y); }
inline size_t PackedDeque::internal_index(const size_t& i) const { assert(i < filled); return i < vec.size() - begin_idx ? begin_idx + i : i - (vec.size() - begin_idx); }
inline void PackedDeque::set(const size_t& i, const uint64_t& value) { return vec.set(internal_index(i), value); }
inline uint64_t PagedVector::get(const size_t& i) const { assert(i < filled); return from_diff(pages[i / page_size].get(i % page_size), anchors.get(i / page_size)); }
inline void PackedDeque::clear() { vec.clear(); filled = 0; begin_idx = 0; }