Skip to content

Commit

Permalink
add example on ccg
Browse files Browse the repository at this point in the history
  • Loading branch information
hlefebvr committed Feb 20, 2025
1 parent 69973c8 commit 7a80bb7
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 102 deletions.
1 change: 1 addition & 0 deletions docs/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,5 @@ Robust Optimization

robust-determistic
robust-adr
robust-ccg

10 changes: 10 additions & 0 deletions docs/examples/robust-ccg.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.. _example_robust_flp_ccg:

Using column-and-constraint generation to solve a two-stage facility location problem with facility disruption
==============================================================================================================

Implementation
--------------

.. literalinclude:: ../../examples/robust/ccg-discrete-uncertainty.example.cpp
:language: cpp
49 changes: 0 additions & 49 deletions docs/examples/two-stage-robust-facility-location-problem.rst

This file was deleted.

115 changes: 64 additions & 51 deletions examples/robust/ccg-discrete-uncertainty.example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,57 @@
// Created by henri on 05.02.25.
//
#include <iostream>
#include <OsiCpxSolverInterface.hpp>
#include <OsiClpSolverInterface.hpp>
#include <OsiSymSolverInterface.hpp>
#include "idol/modeling.h"
#include "idol/mixed-integer/problems/facility-location-problem/FLP_Instance.h"
#include "idol/mixed-integer/optimizers/branch-and-bound/BranchAndBound.h"
#include "idol/mixed-integer/optimizers/branch-and-bound/branching-rules/factories/PseudoCost.h"
#include "idol/mixed-integer/optimizers/branch-and-bound/node-selection-rules/factories/BestEstimate.h"
#include "idol/mixed-integer/optimizers/wrappers/HiGHS/HiGHS.h"
#include "idol/mixed-integer/optimizers/wrappers/GLPK/GLPK.h"
#include "idol/mixed-integer/optimizers/wrappers/Gurobi/Gurobi.h"
#include "idol/mixed-integer/optimizers/branch-and-bound/node-selection-rules/factories/BestBound.h"
#include "idol/mixed-integer/optimizers/branch-and-bound/branching-rules/factories/MostInfeasible.h"
#include "idol/mixed-integer/optimizers/callbacks/ReducedCostFixing.h"
#include "idol/robust/modeling/Description.h"
#include "idol/robust/optimizers/deterministic/Deterministic.h"
#include "idol/robust/optimizers/affine-decision-rule/AffineDecisionRule.h"
#include "idol/bilevel/modeling/Description.h"
#include "idol/robust/optimizers/column-and-constraint-generation/ColumnAndConstraintGeneration.h"
#include "idol/bilevel/optimizers/wrappers/MibS/MibS.h"
#include "idol/bilevel/optimizers/KKT/KKT.h"
#include "idol/mixed-integer/optimizers/padm/SubProblem.h"
#include "idol/mixed-integer/optimizers/padm/PenaltyUpdates.h"
#include "idol/bilevel/optimizers/StrongDuality/StrongDuality.h"
#include "idol/mixed-integer/optimizers/padm/PADM.h"
#include "idol/bilevel/optimizers/PessimisticAsOptimistic/PessimisticAsOptimistic.h"
#include "idol/mixed-integer/optimizers/wrappers/Gurobi/Gurobi.h"

using namespace idol;

int main(int t_argc, const char** t_argv) {

Env env;

//const auto instance = Problems::FLP::generate_instance_1991_Cornuejols_et_al(5, 10, 2);
//std::ofstream file("ccg-discrete-uncertainty.data.txt");
//file << instance;
//file.close();
/*****************/
/* Read Instance */
/*****************/

// Read instance
const auto instance = Problems::FLP::read_instance_1991_Cornuejols_et_al("ccg-discrete-uncertainty.data.txt");
const unsigned int n_customers = instance.n_customers();
const unsigned int n_facilities = instance.n_facilities();

// Uncertainty set
Model uncertainty_set(env);
const double Gamma = 2;
const auto xi = uncertainty_set.add_vars(Dim<2>(n_facilities, n_customers), 0., 1., Binary, 0., "xi");
uncertainty_set.add_ctr(idol_Sum(i, Range(n_facilities), idol_Sum(j, Range(n_customers), xi[i][j])) <= Gamma);
/****************************/
/* Make Deterministic Model */
/****************************/

// Make model
Model model(env);
Robust::Description robust_description(uncertainty_set);
Bilevel::Description bilevel_description(env);

auto x = model.add_vars(Dim<1>(n_facilities), 0., 1., Binary, 0., "x");
auto y = model.add_vars(Dim<2>(n_facilities, n_customers), 0., 1., Binary, 0., "y");
const auto x = model.add_vars(Dim<1>(n_facilities), 0., 1., Binary, 0., "x");
const auto y = model.add_vars(Dim<2>(n_facilities, n_customers), 0., 1., Binary, 0., "y");
std::list<Ctr> second_stage_constraints;

for (unsigned int i = 0 ; i < n_facilities ; ++i) {
const auto c = model.add_ctr(
idol_Sum(j, Range(n_customers), instance.demand(j) * y[i][j]) <= instance.capacity(i)
);
bilevel_description.make_lower_level(c);
const auto c = model.add_ctr(idol_Sum(j, Range(n_customers), instance.demand(j) * y[i][j]) <= instance.capacity(i));
second_stage_constraints.emplace_back(c);
}

for (unsigned int j = 0 ; j < n_customers ; ++j) {
const auto c = model.add_ctr(idol_Sum(i, Range(n_facilities), y[i][j]) >= 1);
bilevel_description.make_lower_level(c);
second_stage_constraints.emplace_back(c);
}

for (unsigned int i = 0 ; i < n_facilities ; ++i) {
for (unsigned int j = 0 ; j < n_customers ; ++j) {
const auto c = model.add_ctr(y[i][j] <= x[i]);
bilevel_description.make_lower_level(c);
}
}

for (unsigned int i = 0 ; i < n_facilities ; ++i) {
for (unsigned int j = 0; j < n_customers; ++j) {
bilevel_description.make_lower_level(y[i][j]);
second_stage_constraints.emplace_back(c);
}
}

Expand All @@ -94,6 +66,33 @@ int main(int t_argc, const char** t_argv) {
)
);

/************************/
/* Declare Second Stage */
/************************/

Bilevel::Description bilevel_description(env);
for (const auto& y_ij : flatten<Var, 2>(y)) {
bilevel_description.make_lower_level(y_ij);
}
for (const auto& ctr : second_stage_constraints) {
bilevel_description.make_lower_level(ctr);
}

/**************************/
/* Create Uncertainty Set */
/**************************/

Model uncertainty_set(env);
const double Gamma = 2;
const auto xi = uncertainty_set.add_vars(Dim<2>(n_facilities, n_customers), 0., 1., Binary, 0., "xi");
uncertainty_set.add_ctr(idol_Sum(i, Range(n_facilities), idol_Sum(j, Range(n_customers), xi[i][j])) <= Gamma);

/***********************/
/* Declare Uncertainty */
/***********************/

Robust::Description robust_description(uncertainty_set);

for (unsigned int i = 0 ; i < n_facilities ; ++i) {
for (unsigned int j = 0; j < n_customers; ++j) {
const auto c = model.add_ctr(y[i][j] <= 1);
Expand All @@ -102,16 +101,18 @@ int main(int t_argc, const char** t_argv) {
}
}

/***********************************************************************************************/
/* Creating a heuristic for the adversarial solver: PADM based on strong duality reformulation */
/***********************************************************************************************/

Annotation<double> initial_penalties(env, "initial_penalties", 1e1);
Annotation<unsigned int> decomposition(env, "sub_problem", 0);
for (unsigned int i = 0 ; i < n_facilities ; ++i) {
for (unsigned int j = 0; j < n_customers; ++j) {
xi[i][j].set(decomposition, 1);
}
}

Annotation<double> initial_penalties(env, "initial_penalties", 1e1);

/*
const auto padm = Bilevel::StrongDuality()
.with_single_level_optimizer(
PADM(decomposition, initial_penalties)
Expand All @@ -123,14 +124,20 @@ int main(int t_argc, const char** t_argv) {
.with_logs(false)
)
;
*/

/**************************************************************/
/* Creating an exact solver for the adversarial problem: MibS */
/**************************************************************/

const auto mibs = Bilevel::MibS()
.with_cplex_for_feasibility(true)
.with_file_interface(false)
.with_logs(false)
.with_logs(true)
;

/************************************************/
/* Creating the column-and-constraint optimizer */
/************************************************/

model.use(
Robust::ColumnAndConstraintGeneration(robust_description, bilevel_description)

Expand All @@ -139,13 +146,19 @@ int main(int t_argc, const char** t_argv) {

.with_master_optimizer(Gurobi())

//.add_feasibility_separation_optimizer(padm)
.add_feasibility_separation_optimizer(padm)
.add_feasibility_separation_optimizer(mibs)

//.add_optimality_separation_optimizer(padm)
.add_optimality_separation_optimizer(Bilevel::PessimisticAsOptimistic() + mibs)
.add_optimality_separation_optimizer(padm)
.add_optimality_separation_optimizer(mibs)
.with_logs(true)
);


/***********/
/* Solving */
/***********/

model.optimize();

std::cout << "Status: " << model.get_status() << std::endl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ void idol::CCG::Formulation::add_scenario_to_master(const idol::Point<idol::Var>
m_master.add_ctr(*m_second_stage_epigraph >= std::move(objective));

if (!m_bilevel_description.lower_level_obj().is_zero(Tolerance::Feasibility)) {
throw Exception("Newly created lower-levels do not have an objective function. This has to be "
"implemented. Though they have the right annotation.");
std::cerr << "Newly created lower-levels do not have an objective function. This has to be "
"implemented. Though they have the right annotation." << std::endl;
}

++m_n_added_scenario;
Expand Down

0 comments on commit 7a80bb7

Please sign in to comment.