working
This commit is contained in:
@@ -20,7 +20,5 @@ struct Customer
|
||||
|
||||
struct Cost
|
||||
{
|
||||
Customer m_Customer;
|
||||
Facility m_Facility;
|
||||
int m_Cost;
|
||||
double m_Cost;
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -7,7 +7,7 @@ struct FileData
|
||||
{
|
||||
std::vector<Facility> m_Facilities;
|
||||
std::vector<Customer> m_Customers;
|
||||
std::vector<Cost> m_Costs;
|
||||
std::vector<std::vector<double>> m_Costs;
|
||||
};
|
||||
|
||||
FileData ParseFile(const std::string& a_FileName);
|
||||
75
src/main.cpp
75
src/main.cpp
@@ -1,56 +1,91 @@
|
||||
#include "Parser.h"
|
||||
#include <fmt/format.h>
|
||||
#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) {
|
||||
auto fileData = ParseFile("RhoneCities_100.flpb");
|
||||
|
||||
std::vector<Variable> y;
|
||||
std::vector<std::vector<Variable>> x(fileData.m_Facilities.size());
|
||||
sat::CpModelBuilder cp_model;
|
||||
|
||||
std::vector<sat::BoolVar> y;
|
||||
std::vector<std::vector<sat::BoolVar>> 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);
|
||||
}
|
||||
|
||||
sat::DoubleLinearExpr obj;
|
||||
|
||||
for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) {
|
||||
sum = sum + x[i][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});
|
||||
for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++) {
|
||||
obj += fileData.m_Facilities[j].m_Cost * sat::DoubleLinearExpr(y[j]);
|
||||
}
|
||||
|
||||
std::cout << "Updating variables...\n";
|
||||
solver.updateVariables();
|
||||
cp_model.Minimize(obj);
|
||||
|
||||
for (std::size_t j = 0; j < fileData.m_Facilities.size(); j++)
|
||||
{
|
||||
std::cout << y[j].name() << "=" << y[j].value() << "\n";
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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(".")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user