This commit is contained in:
2026-02-08 14:50:55 +01:00
parent 5f7e9c2073
commit fa9f8d3c9c
5 changed files with 72 additions and 37 deletions

View File

@@ -20,7 +20,5 @@ struct Customer
struct Cost struct Cost
{ {
Customer m_Customer; double m_Cost;
Facility m_Facility;
int m_Cost;
}; };

View File

@@ -49,16 +49,19 @@ FileData ParseFile(const std::string& a_FileName) {
fileData.m_Customers.push_back(customer); 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 // costs
while (getline(in, line)) while (getline(in, line))
{ {
Cost cost; double cost;
int facilityID, customerID; int facilityID, customerID;
std::stringstream stream(line); std::stringstream stream(line);
stream >> customerID >> facilityID >> cost.m_Cost; stream >> customerID >> facilityID >> cost;
cost.m_Customer = fileData.m_Customers[customerID - 1]; fileData.m_Costs[customerID - 1][facilityID - 1] = cost;
cost.m_Facility = fileData.m_Facilities[facilityID - 1];
fileData.m_Costs.push_back(cost);
} }
return fileData; return fileData;

View File

@@ -7,7 +7,7 @@ struct FileData
{ {
std::vector<Facility> m_Facilities; std::vector<Facility> m_Facilities;
std::vector<Customer> m_Customers; std::vector<Customer> m_Customers;
std::vector<Cost> m_Costs; std::vector<std::vector<double>> m_Costs;
}; };
FileData ParseFile(const std::string& a_FileName); FileData ParseFile(const std::string& a_FileName);

View File

@@ -1,56 +1,91 @@
#include "Parser.h" #include "Parser.h"
#include <fmt/format.h>
#include <iostream> #include <iostream>
#include <kiwi/kiwi.h>
using namespace kiwi; #include <absl/base/log_severity.h>
#include <absl/log/globals.h>
#include <absl/log/log.h>
#include <ortools/base/init_google.h>
#include <ortools/sat/cp_model.h>
#include <ortools/sat/cp_model_solver.h>
#include <chrono>
using namespace operations_research;
int main(int argc, char** argv) { int main(int argc, char** argv) {
auto fileData = ParseFile("RhoneCities_100.flpb"); auto fileData = ParseFile("RhoneCities_100.flpb");
std::vector<Variable> y; sat::CpModelBuilder cp_model;
std::vector<std::vector<Variable>> x(fileData.m_Facilities.size());
std::vector<sat::BoolVar> y;
std::vector<std::vector<sat::BoolVar>> x(fileData.m_Customers.size());
std::cout << "Adding variables ...\n"; std::cout << "Adding variables ...\n";
Solver solver;
for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) { 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++) { 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"; std::cout << "Adding constraints 1...\n";
for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) { 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++) { for (size_t i = 0; i < fileData.m_Customers.size(); i++) {
sum = sum + fileData.m_Customers[i].m_Demand * x[i][j]; 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"; std::cout << "Adding constraints 2...\n";
for (std::size_t i = 0; i < fileData.m_Customers.size(); i++) { 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++) { sat::DoubleLinearExpr obj;
sum = sum + x[i][j];
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"; for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) {
solver.updateVariables(); obj += fileData.m_Facilities[j].m_Cost * sat::DoubleLinearExpr(y[j]);
for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++)
{
std::cout << y[j].name() << "=" << y[j].value() << "\n";
} }
cp_model.Minimize(obj);
std::cout << "Solving...\n";
auto start = static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock().now().time_since_epoch()).count());
auto solution = sat::Solve(cp_model.Build());
auto end = static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(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; return 0;
} }

View File

@@ -1,12 +1,11 @@
add_rules("mode.debug", "mode.release") add_rules("mode.debug", "mode.release")
add_requires("kiwisolver", "fmt") add_requires("or-tools[highs=true,glpk=true]")
-- https://github.com/Qix-/kiwi/blob/int-solver/kiwi/variable.h
target("RhoneCities") target("RhoneCities")
set_kind("binary") set_kind("binary")
add_packages("kiwisolver", "fmt") add_defines("OR_PROTO_DLL=")
add_packages("or-tools")
add_files("src/*.cpp") add_files("src/*.cpp")
set_rundir(".") set_rundir(".")