diff --git a/src/algos/base_algo.cpp b/src/algos/base_algo.cpp index f4675e8..3663a58 100644 --- a/src/algos/base_algo.cpp +++ b/src/algos/base_algo.cpp @@ -138,7 +138,22 @@ Bin* BaseAlgo::createNewBin() bool BaseAlgo::checkItemToBin(Item* item, Bin* bin) const { - return (bin->doesItemFit(item->getSizes())); + if (!instance.getWithConflicts()) + return bin->doesItemFit(item->getSizes()); + else + return (bin->doesItemFit(item->getSizes()) + && !doesItemConflict(item, bin->getAllocList())); +} + +bool BaseAlgo::doesItemConflict(Item* item, const AllocList& allocated_items) const +{ + const auto& conflicts = instance.getAdjacencyList().at(item->getId()); + + for (int conflict_id : conflicts) + if (std::find(allocated_items.begin(), allocated_items.end(), conflict_id) != allocated_items.end()) + return true; + + return false; } void BaseAlgo::addItemToBin(Item* item, Bin* bin) diff --git a/src/algos/base_algo.hpp b/src/algos/base_algo.hpp index a191006..a44f2af 100644 --- a/src/algos/base_algo.hpp +++ b/src/algos/base_algo.hpp @@ -34,6 +34,7 @@ class BaseAlgo protected: virtual Bin* createNewBin(); // Open a new empty bin virtual bool checkItemToBin(Item* item, Bin* bin) const; + virtual bool doesItemConflict(Item* item, const AllocList& allocated_items) const; virtual void addItemToBin(Item* item, Bin* bin); protected: diff --git a/src/lib/instance.cpp b/src/lib/instance.cpp index 669347d..6c030cf 100644 --- a/src/lib/instance.cpp +++ b/src/lib/instance.cpp @@ -13,9 +13,11 @@ auto RANDOM_SEED = 23; // For deterministic shuffles Instance::Instance(const std::string instance_name, const std::string& filename, - const bool shuffle_items): + const bool shuffle_items, + bool with_conflicts): name(instance_name), - items_shuffled(shuffle_items) + items_shuffled(shuffle_items), + with_conflicts(with_conflicts) { ifstream ifile(filename.c_str()); if(!ifile.is_open()) @@ -46,6 +48,12 @@ Instance::Instance(const std::string instance_name, // Retrieve the item list item_list.reserve(this->nb_items); + + // Resize the adjacency vector + if (with_conflicts) + { + adjacency_list.resize(nb_items); + } // For each row create one Item for(int internal_id = 0; internal_id < this->nb_items; internal_id++) @@ -53,7 +61,7 @@ Instance::Instance(const std::string instance_name, getline(ifile, line); SizeList sizes; FloatList norm_sizes; - retrieveSizeLists(line, this->capacity_list, sizes, norm_sizes); + retrieveSizeLists(this, line, sizes, norm_sizes, internal_id, with_conflicts); if (sizes.size() != this->dimensions) { @@ -120,6 +128,15 @@ const bool Instance::getItemsShuffled() const return items_shuffled; } +const bool Instance::getWithConflicts() const +{ + return with_conflicts; +} + +const std::vector>& Instance::getAdjacencyList() const +{ + return adjacency_list; +} SizeList vectorpack::retrieveCapacityList(std::string resource_str) { @@ -136,23 +153,37 @@ SizeList vectorpack::retrieveCapacityList(std::string resource_str) return vect; } -void vectorpack::retrieveSizeLists(std::string resource_str, SizeList& capacity_list, - SizeList& sizes, FloatList& norm_sizes) +void vectorpack::retrieveSizeLists(Instance* instance, std::string resource_str, + SizeList& sizes, FloatList& norm_sizes, int item_id, bool with_conflicts) { int val; std::string str_val; std::istringstream splitStream(resource_str); - int d = (int)capacity_list.size(); + int d = (int)instance->capacity_list.size(); sizes.reserve(d); norm_sizes.reserve(d); - int i = 0; - while(std::getline(splitStream, str_val, ' ') && (i < d)) + int value; + // Read sizes + for (int i = 0; (i < d) and (splitStream.good()); i++) { + splitStream >> value; + + sizes.push_back(value); + norm_sizes.push_back((float)value / (float)instance->capacity_list[i]); + } + + // Omit b_i value (the multiplicity value for CSP problems) + splitStream >> value; + + // Read list of conflicts if with_conflicts is true + if (with_conflicts) { - val = std::stoi(str_val); - sizes.push_back(val); - norm_sizes.push_back((float)val / (float)capacity_list[i]); - i++; + int conflict_id; + while (splitStream >> conflict_id) + { + instance->adjacency_list.at(item_id).push_back(conflict_id); + instance->adjacency_list.at(conflict_id).push_back(item_id); // For conflicts symmetry + } } } diff --git a/src/lib/instance.hpp b/src/lib/instance.hpp index b5212b9..a7b1220 100644 --- a/src/lib/instance.hpp +++ b/src/lib/instance.hpp @@ -11,7 +11,8 @@ class Instance public: Instance(const std::string instance_name, const std::string& filename, - const bool shuffle_items = true); + const bool shuffle_items = true, + bool with_conflicts = false); virtual ~Instance(); @@ -21,19 +22,26 @@ class Instance const SizeList& getBinCapacities() const; const ItemList& getItems() const; const bool getItemsShuffled() const; + const bool getWithConflicts() const; + const std::vector>& getAdjacencyList() const; + friend void retrieveSizeLists(Instance* instance, std::string resource_str, + SizeList& sizes, FloatList& norm_sizes, int item_id, bool with_conflicts); + private: const std::string name; // The instance name const bool items_shuffled; // Whether the items were shuffled int nb_items; // The number of items int dimensions; // The number of dimensions + bool with_conflicts; + std::vector> adjacency_list; // Adjacency lists for explicit conflicts of BPPC instances SizeList capacity_list;// The list of bin capacities ItemList item_list; // The list of Items of this instance }; SizeList retrieveCapacityList(std::string resource_str); -void retrieveSizeLists(std::string resource_str, SizeList& capacity_list, - SizeList& sizes, FloatList& norm_sizes); +void retrieveSizeLists(Instance* instance, std::string resource_str, + SizeList& sizes, FloatList& norm_sizes, int item_id, bool with_conflicts); } // namespace vectorpack #endif // VECTORPACK_INSTANCE_HPP diff --git a/src/main_vectorpack.cpp b/src/main_vectorpack.cpp index 90cbb55..a102e78 100644 --- a/src/main_vectorpack.cpp +++ b/src/main_vectorpack.cpp @@ -36,6 +36,8 @@ void show_usage(std::string prog_name) << "\t--order-bins-output: Outputs bins in their order of creation\n" << "\t--offset-item-ids: Makes item identifiers start at 1 instead of 0 in the output\n" << "\t--no-shuffle: Disables shuffling of items during loading of the instance\n" + << "\t--with-conflicts: Takes into account explicit conflicts between items (for BPPC instances)\n" + << "\t-h, --help: Shows this help message\n" << std::endl; } @@ -57,6 +59,8 @@ int main(int argc, char** argv) bool offset_item_ids = false; bool shuffle_items = true; + bool with_conflicts = false; + // Parsing options from CLI greatly inspired by // https://cplusplus.com/articles/DEN36Up4/ for (int i = 3; i < argc; ++i) @@ -93,15 +97,19 @@ int main(int argc, char** argv) { shuffle_items = false; } + else if (arg == "--with-conflicts") + { + with_conflicts = true; + } else { - std::cerr << "Unknow option: " << arg << std::endl; + std::cerr << "Unknown option: " << arg << std::endl; return 1; } } // End of parsing options - Instance inst(instance_name, instance_file, shuffle_items); + Instance inst(instance_name, instance_file, shuffle_items, with_conflicts); //time_point start; //time_point stop;