diff --git a/src/Model.h b/src/Model.h index 6ffec15..3948fb1 100644 --- a/src/Model.h +++ b/src/Model.h @@ -20,7 +20,5 @@ struct Customer struct Cost { - Customer m_Customer; - Facility m_Facility; - int m_Cost; + double m_Cost; }; \ No newline at end of file diff --git a/src/Parser.cpp b/src/Parser.cpp index d2a11b0..3da46e0 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -49,16 +49,19 @@ FileData ParseFile(const std::string& a_FileName) { fileData.m_Customers.push_back(customer); } + fileData.m_Costs.resize(fileData.m_Customers.size()); + for (std::size_t i = 0; i < fileData.m_Customers.size(); i++) { + fileData.m_Costs[i].resize(fileData.m_Facilities.size()); + } + // costs while (getline(in, line)) { - Cost cost; + double cost; int facilityID, customerID; std::stringstream stream(line); - stream >> customerID >> facilityID >> cost.m_Cost; - cost.m_Customer = fileData.m_Customers[customerID - 1]; - cost.m_Facility = fileData.m_Facilities[facilityID - 1]; - fileData.m_Costs.push_back(cost); + stream >> customerID >> facilityID >> cost; + fileData.m_Costs[customerID - 1][facilityID - 1] = cost; } return fileData; diff --git a/src/Parser.h b/src/Parser.h index b0e2814..6937cbd 100644 --- a/src/Parser.h +++ b/src/Parser.h @@ -7,7 +7,7 @@ struct FileData { std::vector m_Facilities; std::vector m_Customers; - std::vector m_Costs; + std::vector> m_Costs; }; FileData ParseFile(const std::string& a_FileName); \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5ae63b4..25dcb17 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,56 +1,91 @@ #include "Parser.h" -#include #include -#include -using namespace kiwi; +#include +#include +#include +#include +#include +#include + +#include + +using namespace operations_research; int main(int argc, char** argv) { auto fileData = ParseFile("RhoneCities_100.flpb"); - std::vector y; - std::vector> x(fileData.m_Facilities.size()); + sat::CpModelBuilder cp_model; + + std::vector y; + std::vector> x(fileData.m_Customers.size()); std::cout << "Adding variables ...\n"; - Solver solver; for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) { - y.emplace_back(fmt::format("y_{}", j)); + y.push_back(cp_model.NewBoolVar()); for (std::size_t i = 0; i < fileData.m_Customers.size(); i++) { - x[i].emplace_back(fmt::format("x_{}{}", i, j)); + x[i].push_back(cp_model.NewBoolVar()); } } std::cout << "Adding constraints 1...\n"; for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) { - Expression sum; + sat::LinearExpr sum; - for (std::size_t i = 0; i < fileData.m_Customers.size(); i++) { - sum = sum + fileData.m_Customers[i].m_Demand * x[i][j]; + for (size_t i = 0; i < fileData.m_Customers.size(); i++) { + sum += fileData.m_Customers[i].m_Demand * x[i][j]; } - solver.addConstraint({sum <= fileData.m_Facilities[j].m_Capacity * y[j]}); + cp_model.AddLessOrEqual(sum, fileData.m_Facilities[j].m_Capacity * y[j]); } std::cout << "Adding constraints 2...\n"; for (std::size_t i = 0; i < fileData.m_Customers.size(); i++) { - Expression sum; + cp_model.AddEquality(sat::LinearExpr::Sum(x[i]), 1); + } - for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) { - sum = sum + x[i][j]; + sat::DoubleLinearExpr obj; + + for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) { + for (size_t i = 0; i < fileData.m_Customers.size(); i++) { + auto cost = fileData.m_Costs[i][j]; + obj += cost * sat::DoubleLinearExpr(x[i][j]); } - - solver.addConstraint({sum == 1}); } - std::cout << "Updating variables...\n"; - solver.updateVariables(); - - for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) - { - std::cout << y[j].name() << "=" << y[j].value() << "\n"; + for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) { + obj += fileData.m_Facilities[j].m_Cost * sat::DoubleLinearExpr(y[j]); } - + + cp_model.Minimize(obj); + + std::cout << "Solving...\n"; + + auto start = static_cast( + std::chrono::duration_cast(std::chrono::system_clock().now().time_since_epoch()).count()); + + auto solution = sat::Solve(cp_model.Build()); + + auto end = static_cast( + std::chrono::duration_cast(std::chrono::system_clock().now().time_since_epoch()).count()); + + std::cout << "Done in " << end - start << "ms !" << std::endl; + std::cout << "Status : " << solution.status() << std::endl; + std::cout << "Objective : " << solution.objective_value() << "€" << std::endl; + + int fac_number = 0; + + for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) { + bool make_fac = sat::SolutionBooleanValue(solution, y[j]); + std::cout << make_fac; + if (make_fac) + fac_number++; + } + + std::cout << std::endl; + + std::cout << "N=" << fac_number << std::endl; return 0; } diff --git a/xmake.lua b/xmake.lua index d2471da..30c22e7 100644 --- a/xmake.lua +++ b/xmake.lua @@ -1,12 +1,11 @@ add_rules("mode.debug", "mode.release") -add_requires("kiwisolver", "fmt") - --- https://github.com/Qix-/kiwi/blob/int-solver/kiwi/variable.h +add_requires("or-tools[highs=true,glpk=true]") target("RhoneCities") set_kind("binary") - add_packages("kiwisolver", "fmt") + add_defines("OR_PROTO_DLL=") + add_packages("or-tools") add_files("src/*.cpp") set_rundir(".")