Commit 724237f3 authored by jonasseidel's avatar jonasseidel

more const correctness

parent 16b3fcfb
#include "Maintenance_Problem.h"
// computational
#include "computational_types/semiassignment_hdlr.h"
#include "computational_types/semiassignment_branch.h"
#include "computational_types/generate_nmp_bendersdecomp.h"
#include "stock_computational_benders_types/nmp_benders_generation.h"
Maintenance_Problem::Maintenance_Problem() : Linear_Program(true), _number_of_epochs(0), _g({{"Flow", Attribute(max, 0)},{"Upper", Attribute(fix, 1)}, {"Selected", Attribute(fix, 0)}}), _source(nullptr), _target(nullptr) {
Maintenance_Problem::Maintenance_Problem() : Linear_Program("maintenance_problem_ip", true), _number_of_epochs(0), _g({{"Flow", Attribute(max, 0)},{"Upper", Attribute(fix, 1)}, {"Selected", Attribute(fix, 0)}}), _source(nullptr), _target(nullptr) {
}
Maintenance_Problem::Maintenance_Problem(Maintenance_Problem& mp) : Linear_Program(true) {
Maintenance_Problem::Maintenance_Problem(Maintenance_Problem& mp) : Linear_Program("maintenance_problem_ip", true) {
*this = mp;
}
Maintenance_Problem::Maintenance_Problem(Maintenance_Problem&& mp) : Linear_Program(true){
Maintenance_Problem::Maintenance_Problem(Maintenance_Problem&& mp) : Linear_Program("maintenance_problem_ip", true) {
*this = std::move(mp);
}
Maintenance_Problem::Maintenance_Problem(
Graph& g, Node* source,
Node* target,
const Graph& g, const Node* source,
const Node* target,
size_t epochs
)
: Linear_Program(true), _number_of_epochs(epochs)
: Linear_Program("maintenance_problem_ip", true), _number_of_epochs(epochs)
{
// copy graph and transform source and target variables to ptrs in the copy
assert(g.nodes().find(source) != g.nodes().end());
......@@ -35,7 +39,7 @@ Maintenance_Problem::Maintenance_Problem(
this->_target = target_lookup->second;
// create lp
std::set<Edge*> critical = g.gather_edges({"Selected"});
std::set<const Edge*> critical = g.gather_edges({"Selected"});
for(std::string attr : std::vector({"Selected", "Upper", "Flow"})){
if(!this->_g.edge_template(attr).first) {
......@@ -48,11 +52,11 @@ Maintenance_Problem::Maintenance_Problem(
std::vector<
std::pair<
std::map<
std::pair<Node*,std::string>,
std::pair<const Node*,std::string>,
std::pair<Variable*, size_t>
>,
std::map<
std::pair<Edge*,std::string>,
std::pair<const Edge*,std::string>,
std::pair<Variable*, size_t>
>
>
......@@ -67,7 +71,7 @@ Maintenance_Problem::Maintenance_Problem(
lookup.push_back(lp_generator::grow_from_graph(
*this,
g,
[&critical, epoch](Edge* edge) -> std::vector<constraint_data> {
[&critical, epoch](const Edge* edge) -> std::vector<constraint_data> {
std::stringstream capacity_name;
capacity_name << "edge_" << edge->description() << "_capacity_epoch_" << epoch;
std::stringstream non_critical_fix;
......@@ -82,7 +86,7 @@ Maintenance_Problem::Maintenance_Problem(
}
return constraints;
},
[source, target, &critical, epoch](Node* node) -> std::vector<constraint_data> {
[source, target, &critical, epoch](const Node* node) -> std::vector<constraint_data> {
if(node == source || node == target) return {};
std::stringstream name;
name << "node_" << node->description() << "_flow_conservation_epoch_" << epoch;
......@@ -101,7 +105,7 @@ Maintenance_Problem::Maintenance_Problem(
/*
critical edges processed
*/
for(Edge* e : critical){
for(const Edge* e : critical){
std::unordered_map<Variable*, Coefficient> lhs;
for(auto lookup_during_epoch : lookup){
lhs.insert({lookup_during_epoch.second.find({e, "Selected"})->second.first, {1}});
......@@ -146,25 +150,30 @@ Maintenance_Problem::Maintenance_Problem(
this->add_direction_coefficient({target_var.first, 1});
}
Graph& Maintenance_Problem::network(){
const Graph& Maintenance_Problem::network() const {
return this->_g;
}
Node* Maintenance_Problem::source(){
const Node* Maintenance_Problem::source() const {
return this->_source;
}
Node* Maintenance_Problem::target(){
const Node* Maintenance_Problem::target() const {
return this->_target;
}
size_t Maintenance_Problem::number_of_epochs(){
size_t Maintenance_Problem::number_of_epochs() const {
return this->_number_of_epochs;
}
std::vector<SCIP*> Maintenance_Problem::all_computational_models(){
// basic model:
SCIP* scip_basic = Linear_Program::computational_model().first;
SCIPsolve(scip_basic);
auto [scip_basic, lookup] = Linear_Program::computational_model();
// release all vars
for(auto& [variable, computational_var] : lookup){
SCIP_CALL_ABORT( SCIPreleaseVar(scip_basic, &computational_var));
}
//SCIPsolve(scip_basic);
/*
// semiassignment_branching
SCIP* scip_semiassign = Linear_Program::computational_model().first;
......@@ -182,10 +191,14 @@ std::vector<SCIP*> Maintenance_Problem::all_computational_models(){
SCIPincludeBranchruleSemiassign(scip_semiassign, process_cons.size(), process_cons_array);
*/
// benders
SCIP* scip_benders = generate_nmp_bendersdecomp(*this, scip_basic, SCIPgetBestSol(scip_basic));
//SCIP* benders_native = nmp_generate_benders(*this);
//SCIP* scip_benders = generate_nmp_bendersdecomp(*this, benders_native, SCIPgetBestSol(benders_native));
// return all models
return {scip_basic, /*scip_semiassign,*/ scip_benders};
return {scip_basic/*, scip_semiassign/*, scip_benders/*, benders_native*/};
}
void Maintenance_Problem::operator=(Maintenance_Problem& mp){
......@@ -210,7 +223,40 @@ void Maintenance_Problem::operator=(Maintenance_Problem&& mp){
this->_target = mp._target;
}
std::ostream& operator<<(std::ostream& os, Maintenance_Problem& mp){
os << static_cast<Linear_Program&>(mp) << std::endl;
Maintenance_Problem::Maintenance_Problem(std::istream& is) : Linear_Program("maintenance_problem_ip", true) {
std::string curr;
is >> curr;
assert(curr == "Maintenance_Problem");
is >> curr;
assert(curr == "{");
is >> curr;
size_t number_of_epochs = std::stoi(curr);
auto pos = is.tellg();
is >> curr;
assert(curr == "Graph");
is.seekg(pos);
Graph g = Graph(is);
std::set<Node*> sources = g.gather_nodes({"Source"});
assert(sources.size() == 1);
Node* source = *sources.begin();
std::set<Node*> targets = g.gather_nodes({"Target"});
assert(targets.size() == 1);
Node* target = *targets.begin();
is >> curr;
assert(curr == "}");
*this = Maintenance_Problem(g, source, target, number_of_epochs);
}
std::ostream& operator<<(std::ostream& os, const Maintenance_Problem& mp){
os << "Maintenance_Problem {\n"
<< mp.number_of_epochs() << "\n"
<< mp.network() << "\n"
<< "}";
return os;
}
std::istream& operator>>(std::istream& is, Maintenance_Problem& mp){
mp = std::move(Maintenance_Problem(is));
return is;
}
......@@ -9,9 +9,6 @@
#include "../../../Linear_Programming/Linear_Program.h"
#include "../../../Linear_Programming/lp_generator.h"
// computational
#include "computational_types/semiassignment_hdlr.h"
#include "computational_types/semiassignment_branch.h"
#include <scip/scip.h>
#include <scip/scipdefplugins.h>
......@@ -25,21 +22,25 @@ public:
Maintenance_Problem();
Maintenance_Problem(Maintenance_Problem& mp);
Maintenance_Problem(Maintenance_Problem&& mp);
Maintenance_Problem(Graph& g, Node* source, Node* target, size_t intervals);
Maintenance_Problem(const Graph& g, const Node* source, const Node* target, size_t intervals);
Graph& network(); // this better be const so that source and target may be set appropriately
Node* source();
Node* target();
size_t number_of_epochs();
const Graph& network() const ;
const Node* source() const ;
const Node* target() const ;
size_t number_of_epochs() const;
std::vector<SCIP*> all_computational_models();
void operator=(Maintenance_Problem& mp);
void operator=(Maintenance_Problem&& mp);
friend std::ostream& operator<<(std::ostream& os, Maintenance_Problem& mp);
Maintenance_Problem(std::istream& is);
friend std::ostream& operator<<(std::ostream& os, const Maintenance_Problem& mp);
friend std::istream& operator>>(std::istream& os, Maintenance_Problem& mp);
};
std::ostream& operator<<(std::ostream& os, Maintenance_Problem& mp);
std::ostream& operator<<(std::ostream& os, const Maintenance_Problem& mp);
std::istream& operator>>(std::istream& iis, Maintenance_Problem& mp);
#endif
......@@ -5,6 +5,7 @@
#include <scip/prob.h>
#include <scip/struct_var.h>
struct SCIP_VarData_Master{
SCIP* subproblem_lpsol;
SCIP_VAR* edgepot_of_subproblem_lpsol;
......@@ -58,16 +59,16 @@ std::pair<
Linear_Program,
std::pair<
std::map<
std::pair<Node*,std::string>,
std::pair<const Node*,std::string>,
std::pair<Variable*, size_t>
>,
std::map<
std::pair<Edge*,std::string>,
std::pair<const Edge*,std::string>,
std::pair<Variable*, size_t>
>
>
> generate_dual_flow_problem(Graph& graph, Node* source, Node* target){
Linear_Program lp(false);
> generate_dual_flow_problem(const Graph& graph, const Node* source, const Node* target){
Linear_Program lp("min_cut_lp", false);
assert(graph.nodes().find(source) != graph.nodes().end());
assert(graph.nodes().find(target) != graph.nodes().end());
......@@ -82,11 +83,11 @@ std::pair<
std::pair<
std::map<
std::pair<Node*,std::string>,
std::pair<const Node*,std::string>,
std::pair<Variable*, size_t>
>,
std::map<
std::pair<Edge*,std::string>,
std::pair<const Edge*,std::string>,
std::pair<Variable*, size_t>
>
> lookup;
......@@ -97,27 +98,27 @@ std::pair<
lookup = lp_generator::grow_from_graph(
lp,
graph,
[](Edge* edge) -> std::vector<constraint_data> {
[](const Edge* edge) -> std::vector<constraint_data> {
std::stringstream capacity_name;
capacity_name << "edge_" << edge->description();
std::vector<constraint_data> constraints;
constraints.push_back({capacity_name.str(), Inequality, {{{{edge->from(), "Nodepotential"}, -1}, {{edge->to(), "Nodepotential"}, 1}}, {{{edge, "Edgepotential"}, -1}}}, 0});
constraints.push_back({capacity_name.str(), Inequality, {{{{edge->from(), "Nodepotential"}, 1}, {{edge->to(), "Nodepotential"}, -1}}, {{{edge, "Edgepotential"}, -1}}}, 0});
return constraints;
},
[source, target](Node* node) -> std::vector<constraint_data> {
[source, target](const Node* node) -> std::vector<constraint_data> {
std::vector<constraint_data> constraints;
if(node == source){
constraints.push_back({"set_source_potential", Equality, {{{{source, "Nodepotential"}, 1}}, {} }, -1});
constraints.push_back({"set_source_potential", Equality, {{{{source, "Nodepotential"}, 1}}, {} }, 1});
}else if(node == target){
constraints.push_back({"set_target_potential", Equality, {{{{target, "Nodepotential"}, 1}}, {} }, 0});
}
return constraints;
},
{{"Edgepotential", {Continuous, {true, 0}, {false, 1}}}},
{{"Nodepotential", {Continuous, {false, 0}, {false, 0}}}},
{{"Nodepotential", {Continuous, {false, 0}, {false, 1}}}},
""
);
......@@ -129,19 +130,19 @@ std::pair<
std::vector<
std::pair<
std::map<
std::pair<Node*,std::string>,
std::pair<const Node*,std::string>,
std::pair<Variable*, size_t>
>,
std::map<
std::pair<Edge*,std::string>,
std::pair<const Edge*,std::string>,
std::pair<Variable*, size_t>
>
>
>
> generate_master(Maintenance_Problem& nmp, Graph& graph, Node* source, Node* target){
Linear_Program lp(true);
> generate_master(Maintenance_Problem& nmp, const Graph& graph, const Node* source, const Node* target){
Linear_Program lp("maintenance_problem_master_ip", true);
std::set<Edge*> critical = graph.gather_edges({"Selected"});
std::set<const Edge*> critical = graph.gather_edges({"Selected"});
for(std::string attr : std::vector({"Selected", "Upper", "Flow"})){
if(!graph.edge_template(attr).first) {
......@@ -154,11 +155,11 @@ std::pair<
std::vector<
std::pair<
std::map<
std::pair<Node*,std::string>,
std::pair<const Node*,std::string>,
std::pair<Variable*, size_t>
>,
std::map<
std::pair<Edge*,std::string>,
std::pair<const Edge*,std::string>,
std::pair<Variable*, size_t>
>
>
......@@ -171,7 +172,7 @@ std::pair<
lookup.push_back(lp_generator::grow_from_graph(
lp,
graph,
[&critical, epoch](Edge* edge) -> std::vector<constraint_data> {
[&critical, epoch](const Edge* edge) -> std::vector<constraint_data> {
std::stringstream non_critical_fix;
non_critical_fix << "edge_" << edge->description() << "_non_critical_epoch_" << epoch;
......@@ -180,7 +181,7 @@ std::pair<
}
return {};
},
[](Node* node) -> std::vector<constraint_data> {
[](const Node* node) -> std::vector<constraint_data> {
return {};
},
{{"Selected", {Integral, {true, 0}, {true, 1}}}},
......@@ -192,7 +193,7 @@ std::pair<
/*
critical edges processed
*/
for(Edge* e : critical){
for(const Edge* e : critical){
std::unordered_map<Variable*, Coefficient> lhs;
for(auto lookup_during_epoch : lookup){
lhs.insert({lookup_during_epoch.second.find({e, "Selected"})->second.first, {1}});
......@@ -215,55 +216,23 @@ std::pair<
return {lp, lookup};
}
SCIP* generate_nmp_bendersdecomp(Maintenance_Problem& nmp, SCIP* basic_scip, SCIP_SOL* opt){
container* c = new container;
*c = container{
basic_scip,
opt,
std::map<SCIP_VAR*, SCIP_VAR*>(),
nullptr
};
SCIP* generate_nmp_bendersdecomp(Maintenance_Problem& nmp, SCIP* scip_basic, SCIP_SOL* opt){
// generating programs:
std::cout << "generating master program" << std::endl;
auto master_and_lookup = generate_master(nmp, nmp.network(), nmp.source(), nmp.target());
auto computational_master_and_lookup = master_and_lookup.first.computational_model();
SCIP_SOL* sol;
SCIPcreateSol(computational_master_and_lookup.first, &sol, NULL);
SCIP_VAR** vars = SCIPgetOrigVars(computational_master_and_lookup.first);
int nvars = SCIPgetNOrigVars(computational_master_and_lookup.first);
for(int index = 0; index < nvars; index++){
SCIP_VAR* remote = SCIPfindVar(c->basic_scip, SCIPvarGetName(vars[index]));
c->trans.insert({vars[index], remote});
SCIPsetSolVal(computational_master_and_lookup.first, sol, vars[index], SCIPgetSolVal(c->basic_scip, c->opt, remote));
c->transopt = sol;
assert(SCIPgetSolVal(computational_master_and_lookup.first, c->transopt, vars[index]) == SCIPgetSolVal(c->basic_scip, c->opt, remote));
}
std::cout << "generating subproblems: ";
std::vector<
std::pair<
Linear_Program,
std::pair<
std::map<
std::pair<Node*,std::string>,
std::pair<const Node*,std::string>,
std::pair<Variable*, size_t>
>,
std::map<
std::pair<Edge*,std::string>,
std::pair<const Edge*,std::string>,
std::pair<Variable*, size_t>
>
>
......@@ -282,11 +251,11 @@ SCIP* generate_nmp_bendersdecomp(Maintenance_Problem& nmp, SCIP* basic_scip, SCI
Linear_Program,
std::pair<
std::map<
std::pair<Node*,std::string>,
std::pair<const Node*,std::string>,
std::pair<Variable*, size_t>
>,
std::map<
std::pair<Edge*,std::string>,
std::pair<const Edge*,std::string>,
std::pair<Variable*, size_t>
>
>
......@@ -323,7 +292,7 @@ SCIP* generate_nmp_bendersdecomp(Maintenance_Problem& nmp, SCIP* basic_scip, SCI
We link these in their respective vardata for quick access.
(This is in contrast to benders_default.c where this translation is achieved with hashmaps)
*/
for(Edge* e : nmp.network().edges()){
for(const Edge* e : nmp.network().edges()){
Variable* master_var = master_and_lookup.second[epoch].second.find({e, "Selected"})->second.first;
SCIP_VAR* computational_master_var = computational_master_and_lookup.second.find(master_var)->second;
......@@ -367,9 +336,22 @@ SCIP* generate_nmp_bendersdecomp(Maintenance_Problem& nmp, SCIP* basic_scip, SCI
SCIPvarSetData(computational_subproblem_var_heursol, (SCIP_VARDATA*) subproblem_vardata_heursol);
SCIPvarSetDelorigData(computational_subproblem_var_heursol, del_vardata_subproblem);
}
/* (this does not seem to be necessary)
// forcing vardata of the other variables to NULL in order to reliably differentiate between them
for(Node* n : nmp.network().nodes()){
Variable* subproblem_var_lpsol = subproblems_with_lookups_lpsols[epoch].second.first.find({n, "Nodepotential"})->second.first;
SCIP_VAR* computational_subproblem_var_lpsol = computational_subproblems_with_lookups_lpsols[epoch].second.find(subproblem_var_lpsol)->second;
Variable* subproblem_var_heursol = subproblems_with_lookups_heursols[epoch].second.first.find({n, "Nodepotential"})->second.first;
SCIP_VAR* computational_subproblem_var_heursol = computational_subproblems_with_lookups_heursols[epoch].second.find(subproblem_var_heursol)->second;
SCIPvarSetData(computational_subproblem_var_lpsol, NULL);
SCIPvarSetData(computational_subproblem_var_heursol, NULL);
}*/
}
std::cout << "\n";
// copying subproblem ptrs into continuous array (also setting reopt flag and probdata)
std::cout << "Initializing Benders Conshdlr" << std::endl;
SCIP** benders_separators_lpsols;
......@@ -382,9 +364,9 @@ SCIP* generate_nmp_bendersdecomp(Maintenance_Problem& nmp, SCIP* basic_scip, SCI
SCIP_Probdata_Subproblem* probdata_lpsol;
SCIP_CALL_ABORT( SCIPallocBlockMemory(benders_separators_lpsols[epoch], &probdata_lpsol));
*probdata_lpsol = SCIP_Probdata_Subproblem{
epoch,
nmp.number_of_epochs(),
nmp.network().edges().size(),
(int) epoch,
(int) nmp.number_of_epochs(),
(int) nmp.network().edges().size(),
0
};
SCIP_CALL_ABORT( SCIPsetProbData(benders_separators_lpsols[epoch], (SCIP_PROBDATA*) probdata_lpsol));
......@@ -395,9 +377,9 @@ SCIP* generate_nmp_bendersdecomp(Maintenance_Problem& nmp, SCIP* basic_scip, SCI
SCIP_Probdata_Subproblem* probdata_heursol;
SCIP_CALL_ABORT( SCIPallocBlockMemory(benders_separators_heursols[epoch], &probdata_heursol));
*probdata_heursol = SCIP_Probdata_Subproblem{
epoch,
nmp.number_of_epochs(),
nmp.network().edges().size(),
(int) epoch,
(int) nmp.number_of_epochs(),
(int) nmp.network().edges().size(),
0
};
SCIP_CALL_ABORT( SCIPsetProbData(benders_separators_heursols[epoch], (SCIP_PROBDATA*) probdata_heursol));
......@@ -409,84 +391,24 @@ SCIP* generate_nmp_bendersdecomp(Maintenance_Problem& nmp, SCIP* basic_scip, SCI
SCIP_CALL_ABORT( SCIPsetBoolParam(computational_master_and_lookup.first, "constraints/benders/active", TRUE) );
SCIP_CALL_ABORT( SCIPsetPresolving(computational_master_and_lookup.first, SCIP_PARAMSETTING_OFF, TRUE) );
SCIP_CALL_ABORT( SCIPsetIntParam(computational_master_and_lookup.first, "propagating/maxrounds", 0) );
SCIP_CALL_ABORT( SCIPsetIntParam(computational_master_and_lookup.first, "propagating/maxroundsroot", 0) );
SCIP_CALL_ABORT( SCIPsetIntParam(computational_master_and_lookup.first, "heuristics/trysol/freq", 1) );
SCIP_CALL_ABORT( SCIPsetIntParam(computational_master_and_lookup.first, "presolving/maxrestarts", 0) );
SCIP_CALL_ABORT( SCIPsetIntParam(computational_master_and_lookup.first, "constraints/benders/maxprerounds", 0) );
SCIP_CALL_ABORT( SCIPsetIntParam(computational_master_and_lookup.first, "presolving/maxrounds", 0) );
SCIP_CALL_ABORT( SCIPincludeConshdlrNMPBenders( computational_master_and_lookup.first, benders_separators_lpsols, benders_separators_heursols, nmp.number_of_epochs(), c));
SCIPprintOrigProblem(computational_master_and_lookup.first, fopen("lp", "w"), "lp", FALSE);
SCIP_Bool feasible = false;
SCIPcheckSolOrig(c->basic_scip, c->opt, &feasible, FALSE, TRUE);
assert(feasible);
SCIPprintSol(c->basic_scip, c->opt, NULL, TRUE);
SCIPprintSol(computational_master_and_lookup.first, c->transopt, NULL, TRUE);
SCIP_CONS** conss = SCIPgetOrigConss(computational_master_and_lookup.first);
int nconss = SCIPgetNOrigConss(computational_master_and_lookup.first);
for(int index = 0; index < nconss; index++){
SCIP_VAR* vars[1000];
SCIP_Bool success;
SCIPgetConsVars(computational_master_and_lookup.first, conss[index], vars, 1000, &success);
assert(success);
int nvars;
SCIPgetConsNVars(computational_master_and_lookup.first, conss[index], &nvars, &success);
assert(success);
SCIP_Real coeffs[1000];
SCIPgetConsVals(computational_master_and_lookup.first, conss[index], coeffs, 1000, &success);
SCIP_Real lhs = SCIPconsGetLhs(computational_master_and_lookup.first, conss[index], &success);
assert(success);
SCIP_Real rhs = SCIPconsGetRhs(computational_master_and_lookup.first, conss[index], &success);
assert(success);
std::cout << lhs << " <= ";
double center = 0;
for(int var_index = 0; var_index < nvars; var_index++){
std::cout << " + " << coeffs[var_index] << " " << SCIPvarGetName(vars[var_index]);
double test = coeffs[var_index] * SCIPgetSolVal(c->basic_scip, c->opt, c->trans.find(vars[var_index])->second);
assert(coeffs[var_index] == 1);
std::cout << " (" << center << " + " << test;
center = center + test;
std::cout << " = " << center << ") ";
}
std::cout << " <= " << rhs << std::endl;
std::cout << lhs << " <= " << center << " <= " << rhs << std::endl;
if(SCIPisGT(c->basic_scip, lhs, center) || SCIPisGT(c->basic_scip, center, rhs)){
for(int var_index = 0; var_index < nvars; var_index++){
std::cout << "name of benders var " << SCIPvarGetName(vars[var_index]) << std::endl;
std::cout << "name of basic_scip var " << SCIPvarGetName(c->trans.find(vars[var_index])->second) << std::endl;
std::cout << "status in benders " << SCIPvarGetStatus(vars[var_index]) << std::endl;
std::cout << "status in benders " << SCIPvarGetStatus(c->trans.find(vars[var_index])->second) << std::endl;