Commit fd879008 authored by Jonas Seidel's avatar Jonas Seidel

Constraint representation rehash & verbose variable names

parent d9c57a2d
#include "Constraint.h"
Constraint::Constraint(std::string description, relation relation_type, std::vector<double> lhs, double rhs, size_t starting_variable)
: _description(description), _relation(relation_type), _starting_variable(starting_variable), _lhs(lhs), _rhs(rhs){}
Constraint::Constraint(std::string description, relation relation_type, std::map<Variable*, double> lhs, double rhs)
: _description(description), _relation(relation_type), _lhs(lhs), _rhs(rhs){}
Constraint::Constraint(relation relation_type, std::vector<double> lhs, double rhs, size_t starting_variable)
: _relation(relation_type), _starting_variable(starting_variable), _lhs(lhs), _rhs(rhs){}
Constraint::Constraint(relation relation_type, std::map<Variable*, double> lhs, double rhs)
: _relation(relation_type), _lhs(lhs), _rhs(rhs){}
std::string Constraint::description(){
return this->_description;
......@@ -14,21 +14,16 @@ relation Constraint::is_equality(){
return this->_relation;
}
size_t Constraint::lhs_first_variable(){
return this->_starting_variable;
}
size_t Constraint::lhs_end(){
return this->_starting_variable + this->_lhs.size();
}
std::vector<double> Constraint::lhs(){
std::map<Variable*, double> Constraint::lhs(){
return this->_lhs;
}
double Constraint::lhs_coefficient(size_t index){
if(index >= this->lhs_end() || index < this->lhs_first_variable()) return 0;
return this->_lhs[index - this->lhs_first_variable()];
double Constraint::lhs_coefficient(Variable* var){
auto tmp = this->_lhs.find(var);
if(tmp == this->_lhs.end()){
return 0;
}
return tmp->second;
}
double Constraint::rhs(){
......@@ -38,22 +33,21 @@ double Constraint::rhs(){
std::ostream& operator<<(std::ostream& os, Constraint& constraint){
os << constraint.description() << ": ";
bool empty = true;
if(constraint.lhs_end() > 0){
bool add_plus = false;
for(size_t index = constraint.lhs_first_variable(); index < constraint.lhs_end(); index++){
if(std::abs(constraint.lhs_coefficient(index)) > 1e-100){
empty = false;
if(constraint.lhs_coefficient(index) < 0){
os << " - ";
}else if(add_plus){
os << " + ";
}
add_plus = true;
if(std::abs(std::abs(constraint.lhs_coefficient(index)) - 1) > 1e-100){
os << std::abs(constraint.lhs_coefficient(index)) << " ";
}
os << "x" << index;
bool add_plus = false;
for(auto summand : constraint.lhs()){
if(std::abs(summand.second) > 1e-100){
empty = false;
if(summand.second < 0){
os << " - ";
}else if(add_plus){
os << " + ";
}
add_plus = true;
if(std::abs(std::abs(summand.second) - 1) > 1e-100){
os << std::abs(summand.second) << " ";
}
os << summand.first->description();
}
}
if(empty){
......
......@@ -3,28 +3,27 @@
#include <cstddef>
#include <string>
#include <vector>
#include <map>
#include <iostream>
#include <cmath>
#include "Variable.h"
enum relation : bool {Inequality = false, Equality = true};
class Constraint{
std::string _description;
relation _relation;
size_t _starting_variable;
std::vector<double> _lhs;
std::map<Variable*, double> _lhs;
double _rhs;
public:
Constraint(std::string description, relation relation_type, std::vector<double> lhs, double rhs, size_t starting_variable = 0);
Constraint(relation relation_type, std::vector<double> lhs, double rhs, size_t starting_variable = 0);
Constraint(std::string description, relation relation_type, std::map<Variable*, double> lhs, double rhs);
Constraint(relation relation_type, std::map<Variable*, double> lhs, double rhs);
std::string description();
relation is_equality();
size_t lhs_first_variable();
size_t lhs_end();
std::vector<double> lhs();
double lhs_coefficient(size_t index);
std::map<Variable*, double> lhs();
double lhs_coefficient(Variable* var);
double rhs();
};
......
......@@ -74,7 +74,7 @@ std::ostream& operator<<(std::ostream& os, Linear_Program& linear_program){
if(std::abs(std::abs(linear_program.direction_coefficient(index)) - 1) > 1e-100){
os << std::abs(linear_program.direction_coefficient(index)) << " ";
}
os << "x" << index;
os << linear_program.polyeder().variable_identifier(index);
}
}
}
......
......@@ -27,6 +27,8 @@ public:
void operator=(Linear_Program& lp);
void operator=(Linear_Program&& lp);
Linear_Program dual();
};
std::ostream& operator<<(std::ostream& os, Linear_Program& linear_program);
......
......@@ -6,13 +6,11 @@ Polyeder::Polyeder(const Polyeder& p){
*this = p;
}
Polyeder::Polyeder(std::vector<Constraint> constraints, std::vector<Variable> variables) : _constraints(constraints), _variables(variables) {
for(Constraint c : this->_constraints){
assert(c.lhs_end() == variables.size());
}
Polyeder::Polyeder(std::vector<Constraint> constraints, boost::bimap<Variable*, size_t> variables) : _constraints(constraints), _variables(variables) {
// TODO: check that variables used in constraints are registered in variables?
}
std::vector<Variable> Polyeder::variables(){
boost::bimap<Variable*, size_t> Polyeder::variables(){
return this->_variables;
}
......@@ -21,19 +19,28 @@ size_t Polyeder::vs_dim(){
}
Variable& Polyeder::variable(size_t index){
assert(index < this->vs_dim());
return this->_variables[index];
auto search_result = this->_variables.right.find(index);
if(search_result == this->_variables.right.end()) throw std::range_error("no such variable!");
return *search_result->second;
}
size_t Polyeder::variable(Variable& var){
auto search_result = this->_variables.left.find(&var);
if(search_result == this->_variables.left.end()) throw std::range_error("no such variable!");
return search_result->second;
}
size_t Polyeder::add_variable(Variable var){
this->_variables.push_back(var);
return this->vs_dim()-1;
std::pair<Variable*, size_t> Polyeder::add_variable(Variable var){
Variable* new_var = new Variable(var);
size_t position = this->_variables.size();
this->_variables.insert({new_var, position});
return {new_var, position};
}
std::string Polyeder::variable_identifier(size_t index){
std::stringstream name;
if(Variable::VERBOSE_IDENT){
name << this->variable(index).description() << "_x" << index;
name << this->variable(index).description();
}else{
name << "x" << index;
}
......@@ -53,7 +60,7 @@ Constraint& Polyeder::constraint(size_t index){
}
void Polyeder::add_constraint(Constraint constraint){
if(this->vs_dim() < constraint.lhs_end()) throw std::range_error("undeclared variables used!");
// TODO: check that variables used in constraint are registered in polyeder?
this->_constraints.push_back(constraint);
}
......@@ -69,8 +76,8 @@ void Polyeder::operator=(Polyeder&& p){
std::ostream& operator<<(std::ostream& os, Polyeder& polyeder){
os << "Subject to\n";
for(size_t index = 0; index < polyeder.number_of_constraints(); ++index) {
os << polyeder.constraint(index) << "\n";
for(auto constraint : polyeder.constraints()) {
os << constraint << "\n";
}
os << "Bounds\n";
for(size_t index = 0; index < polyeder.variables().size(); ++index){
......@@ -88,7 +95,7 @@ std::ostream& operator<<(std::ostream& os, Polyeder& polyeder){
os << "General\n";
for(size_t index = 0; index < polyeder.vs_dim(); ++index){
if(polyeder.variable(index).is_integral() == Integral){
os << "x" << index << " ";
os << polyeder.variable_identifier(index) << " ";
}
}
return os;
......
......@@ -5,30 +5,35 @@
#include <vector>
#include <sstream>
#include <cassert>
#include <stdexcept>
#include <boost/bimap.hpp>
#include "Variable.h"
#include "Constraint.h"
class Polyeder{
std::vector<Constraint> _constraints;
std::vector<Variable> _variables;
boost::bimap<Variable*, size_t> _variables;
public:
Polyeder();
Polyeder(const Polyeder& p);
Polyeder(std::vector<Constraint> constraints, std::vector<Variable> variables);
Polyeder(std::vector<Constraint> constraints, boost::bimap<Variable*, size_t> variables);
std::vector<Variable> variables();
boost::bimap<Variable*, size_t> variables();
size_t vs_dim();
Variable& variable(size_t index);
size_t add_variable(Variable var);
std::string variable_identifier(size_t index);
size_t variable(Variable& var);
std::pair<Variable*, size_t> add_variable(Variable var);
std::vector<Constraint> constraints();
size_t number_of_constraints();
Constraint& constraint(size_t index);
void add_constraint(Constraint constraint);
std::string variable_identifier(size_t index);
void operator=(const Polyeder& p);
void operator=(Polyeder&& p);
};
......
#include "Variable.h"
bool Variable::VERBOSE_IDENT = false;
bool Variable::VERBOSE_IDENT = true;
Variable::Variable(const Variable& var) : _description(var._description), _integrality(var._integrality), _lower_bound(var._lower_bound), _upper_bound(var._upper_bound), _value(var._value) {}
Variable::Variable(Variable&& var) : _description(std::move(var._description)), _integrality(std::move(var._integrality)), _lower_bound(std::move(var._lower_bound)), _upper_bound(std::move(var._upper_bound)), _value(std::move(var._value)) {}
Variable::Variable(integrality integrality, std::pair<bool, double> lower_bound, std::pair<bool, double> upper_bound, double value) : _integrality(integrality), _lower_bound(lower_bound), _upper_bound(upper_bound), _value(value) {}
......
......@@ -13,6 +13,8 @@ class Variable{
std::pair<bool, double> _upper_bound;
double _value;
public:
Variable(const Variable& var);
Variable(Variable&& var);
Variable(integrality integrality, std::pair<bool, double> lower_bound = {false, 0}, std::pair<bool, double> upper_bound = {false, 0}, double value = 0);
Variable(std::string description, integrality integrality, std::pair<bool, double> lower_bound = {false, 0}, std::pair<bool, double> upper_bound = {false, 0}, double value = 0);
......
......@@ -23,10 +23,20 @@ using edge_constraint_data_generator = std::function<std::vector<constraint_data
class lp_generator{
template <typename N, typename E>
static std::vector<double> lhs_from_data(size_t start_index, size_t length, lhs_constraint_data<N,E>& data, std::map<std::pair<Edge<N,E>*,E>, size_t>& edge_variable_lookup, std::map<std::pair<Node<N,E>*,N>, size_t>& node_variable_lookup);
static std::map<Variable*, double> lhs_from_data(
size_t start_index, size_t length,
lhs_constraint_data<N,E>& data,
std::map<std::pair<Edge<N,E>*,E>, std::pair<Variable*, size_t>>& edge_variable_lookup,
std::map<std::pair<Node<N,E>*,N>, std::pair<Variable*, size_t>>& node_variable_lookup
);
public:
template <typename N, typename E>
static std::pair<std::map<std::pair<Node<N,E>*,N>, size_t>, std::map<std::pair<Edge<N,E>*,E>, size_t>> grow_from_graph(Linear_Program& lp, Graph<N,E>& g, edge_constraint_data_generator<N,E> edge_generator, node_constraint_data_generator<N,E> node_generator, std::vector<std::pair<E,std::tuple<integrality, std::pair<bool, double>, std::pair<bool, double>>> > edge_var_data, std::vector<std::pair<N,std::tuple<integrality, std::pair<bool, double>, std::pair<bool, double>>> > node_var_data);
static std::pair<std::map<std::pair<Node<N,E>*,N>, std::pair<Variable*, size_t>>, std::map<std::pair<Edge<N,E>*,E>, std::pair<Variable*, size_t>>> grow_from_graph(
Linear_Program& lp, Graph<N,E>& g,
edge_constraint_data_generator<N,E> edge_generator, node_constraint_data_generator<N,E> node_generator,
std::vector<std::pair<E, std::tuple<integrality, std::pair<bool, double>, std::pair<bool, double>>> > edge_var_data,
std::vector<std::pair<N, std::tuple<integrality, std::pair<bool, double>, std::pair<bool, double>>> > node_var_data
);
};
#include "lp_generator.ipp"
......
template <typename N, typename E>
std::vector<double> lp_generator::lhs_from_data(size_t start_index, size_t length, lhs_constraint_data<N,E>& data, std::map<std::pair<Edge<N,E>*,E>, size_t>& edge_variable_lookup, std::map<std::pair<Node<N,E>*,N>, size_t>& node_variable_lookup){
std::vector<double> lhs (length);
std::map<Variable*, double> lp_generator::lhs_from_data(size_t start_index, size_t length, lhs_constraint_data<N,E>& data, std::map<std::pair<Edge<N,E>*,E>, std::pair<Variable*, size_t>>& edge_variable_lookup, std::map<std::pair<Node<N,E>*,N>, std::pair<Variable*, size_t>>& node_variable_lookup){
std::map<Variable*, double> lhs;
for(std::pair<std::pair<Node<N,E>*,N>, double> w : data.first){
lhs[node_variable_lookup.find(w.first)->second - start_index] = w.second;
auto search_result = node_variable_lookup.find(w.first);
if(search_result == node_variable_lookup.end()) throw std::range_error("lp_generator::lhs_from_data use of undeclared variable in constraint generation! (node)");
lhs.insert({search_result->second.first, w.second});
}
for(std::pair<std::pair<Edge<N,E>*,E>, double> w : data.second){
lhs[edge_variable_lookup.find(w.first)->second - start_index] = w.second;
auto search_result = edge_variable_lookup.find(w.first);
if(search_result == edge_variable_lookup.end()) throw std::range_error("lp_generator::lhs_from_data use of undeclared variable in constraint generation! (edge)");
lhs.insert({search_result->second.first, w.second});
}
return lhs;
}
template <typename N, typename E>
std::pair<std::map<std::pair<Node<N,E>*,N>, size_t>, std::map<std::pair<Edge<N,E>*,E>, size_t>> lp_generator::grow_from_graph(
std::pair<std::map<std::pair<Node<N,E>*,N>, std::pair<Variable*, size_t>>, std::map<std::pair<Edge<N,E>*,E>, std::pair<Variable*, size_t>>> lp_generator::grow_from_graph(
Linear_Program& lp, Graph<N,E>& g, edge_constraint_data_generator<N,E> edge_generator, node_constraint_data_generator<N,E> node_generator,
std::vector<std::pair<E, std::tuple<integrality, std::pair<bool, double>, std::pair<bool, double>>> > edge_var_data, std::vector<std::pair<N, std::tuple<integrality, std::pair<bool, double>, std::pair<bool, double>>> > node_var_data)
{
Polyeder& p = lp.polyeder();
std::map<std::pair<Node<N,E>*,N>, size_t> node_lookup;
std::map<std::pair<Edge<N,E>*,E>, size_t> edge_lookup;
std::map<std::pair<Node<N,E>*,N>, std::pair<Variable*, size_t>> node_lookup;
std::map<std::pair<Edge<N,E>*,E>, std::pair<Variable*, size_t>> edge_lookup;
size_t start_index = p.vs_dim();
......@@ -43,6 +47,7 @@ std::pair<std::map<std::pair<Node<N,E>*,N>, size_t>, std::map<std::pair<Edge<N,E
edge_function,
node_function
);
size_t length = p.vs_dim()-start_index;
for(Node<N,E>* n : g.nodes()){
for(auto data : node_generator(n)){
......@@ -51,8 +56,7 @@ std::pair<std::map<std::pair<Node<N,E>*,N>, size_t>, std::map<std::pair<Edge<N,E
std::get<0>(data),
std::get<1>(data),
lp_generator::lhs_from_data(start_index, length, std::get<2>(data), edge_lookup, node_lookup),
std::get<3>(data),
start_index
std::get<3>(data)
)
);
}
......@@ -65,8 +69,7 @@ std::pair<std::map<std::pair<Node<N,E>*,N>, size_t>, std::map<std::pair<Edge<N,E
std::get<0>(data),
std::get<1>(data),
lp_generator::lhs_from_data(start_index, length, std::get<2>(data), edge_lookup, node_lookup),
std::get<3>(data),
start_index
std::get<3>(data)
)
);
}
......
......@@ -15,7 +15,7 @@ Maintenance_Problem::Maintenance_Problem(Maintenance_Problem&& mp) : Linear_Prog
Maintenance_Problem::Maintenance_Problem(CircSelectNetwork& g, CircSelectNode* source, CircSelectNode* target, std::set<CircSelectEdge*> critical, size_t intervals)
: Linear_Program(true)//, _g(g)
{
std::vector<std::pair< std::map<std::pair<CircSelectNode*,CircSelectNodeFields>, size_t>, std::map<std::pair<CircSelectEdge*,CircSelectEdgeFields>, size_t> >> lookup;
std::vector<std::pair< std::map<std::pair<CircSelectNode*,CircSelectNodeFields>, std::pair<Variable*, size_t>>, std::map<std::pair<CircSelectEdge*,CircSelectEdgeFields>, std::pair<Variable*, size_t>> >> lookup;
/*
flow conservation constraints for all epochs
......@@ -58,10 +58,9 @@ Maintenance_Problem::Maintenance_Problem(CircSelectNetwork& g, CircSelectNode* s
critical edges processed
*/
for(CircSelectEdge* e : critical){
std::vector<double> lhs (this->polyeder().vs_dim());
std::vector<std::pair<std::pair<CircSelectEdge*,CircSelectEdgeFields>,double>> critical_processed;
std::map<Variable*, double> lhs;
for(auto lookup_during_epoch : lookup){
lhs[lookup_during_epoch.second.find({e, Critical})->second] = 1;
lhs.insert({lookup_during_epoch.second.find({e, Critical})->second.first, 1});
}
std::stringstream name;
name << "critical_edge_" << e << "_processed";
......@@ -78,15 +77,15 @@ Maintenance_Problem::Maintenance_Problem(CircSelectNetwork& g, CircSelectNode* s
/*
value bounded by flow
*/
this->polyeder().add_variable(Variable("target_variable", Continuous));
auto target_var = this->polyeder().add_variable(Variable("target_variable", Continuous));
for(size_t epoch = 0; epoch < intervals; ++epoch){
auto lookup_during_epoch = lookup[epoch];
std::vector<double> lhs (this->polyeder().vs_dim());
std::map<Variable*, double> lhs;
for(CircSelectEdge* e : source->incident()){
lhs[lookup_during_epoch.second.find({e, Flow})->second] = -1;
lhs.insert({lookup_during_epoch.second.find({e, Flow})->second.first, -1});
}
lhs[this->polyeder().vs_dim()-1] = 1;
lhs.insert({target_var.first, 1});
std::stringstream name;
name << "target_variable_bounds_epoch_" << epoch;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment