Commit cd9c75f8 authored by Jonas Seidel's avatar Jonas Seidel

adding dualization support

parent f5f5f876
......@@ -10,32 +10,31 @@ Linear_Program::Linear_Program(Linear_Program&& lp){
Linear_Program::Linear_Program(bool maximum) : _maximum(maximum) {}
Linear_Program::Linear_Program(bool maximum, size_t direction_start, std::vector<double> direction, Polyeder& polyeder)
: _maximum(maximum), _direction_start(direction_start), _direction(direction), _polyeder(polyeder) {}
Linear_Program::Linear_Program(bool maximum, std::map<Variable*, double> direction, Polyeder polyeder)
: _maximum(std::move(maximum)), _direction(std::move(direction)), _polyeder(std::move(polyeder)) {}
bool Linear_Program::is_maximum(){
return this->_maximum;
}
double Linear_Program::direction_coefficient(size_t index){
if(index < this->direction_start() || index > this->direction_end()) return 0;
return this->_direction[index - this->direction_start()];
std::map<Variable*, double> Linear_Program::direction(){
return this->_direction;
}
Polyeder& Linear_Program::polyeder(){
return this->_polyeder;
void Linear_Program::add_direction_coefficient(std::pair<Variable*, double> summand){
this->_direction.insert(summand);
}
size_t& Linear_Program::direction_start(){
return this->_direction_start;
double Linear_Program::direction_coefficient(Variable* var){
auto search_result = this->_direction.find(var);
if(search_result == this->_direction.end()) return 0;
return search_result->second;
}
size_t Linear_Program::direction_end(){
return this->direction_start() + this->_direction.size();
Polyeder& Linear_Program::polyeder(){
return this->_polyeder;
}
std::vector<double>& Linear_Program::direction(){
return this->_direction;
void Linear_Program::solve(){
std::stringstream path;
path << "./.data/.cache/" << this << ".lp";
......@@ -49,18 +48,105 @@ void Linear_Program::solve(){
void Linear_Program::operator=(Linear_Program& lp){
this->_maximum = lp._maximum;
this->_direction_start = lp._direction_start;
this->_direction = lp._direction;
this->_polyeder = lp._polyeder;
}
void Linear_Program::operator=(Linear_Program&& lp){
this->_maximum = lp._maximum;
this->_direction_start = lp._direction_start;
this->_direction = std::move(lp._direction);
this->_polyeder = std::move(lp._polyeder);
}
Linear_Program Linear_Program::relaxation_dual(){
std::vector<Constraint> constraints;
constraints.reserve(this->polyeder().vs_dim());
class bimap_counter{
boost::bimap<Variable*, size_t> _bimap;
size_t _counter;
public:
bimap_counter() : _counter(0) {}
void insert(Variable* var){
_bimap.insert({var, _counter});
_counter++;
}
boost::bimap<Variable*, size_t>& unwrap(){
return _bimap;
}
} variables;
std::map<Variable*, double> direction;
for(size_t index = 0; index < this->polyeder().number_of_constraints(); ++index){
std::stringstream name;
name << "dual_" << this->polyeder().constraint(index).description();
if(this->polyeder().constraint(index).is_equality()){
variables.insert({new Variable(name.str(), Continuous)});
}else{
variables.insert(new Variable(name.str(), Continuous, {true, 0}));
}
}
// we introduce one constraint per primal variable
for(auto curr_variable : this->polyeder().variables()){
// gather lhs_coefficient
std::map<Variable*, double> lhs;
for(size_t index = 0; index < this->polyeder().number_of_constraints(); ++index){
lhs.insert({variables.unwrap().right.find(index)->second, -this->polyeder().constraint(index).lhs_coefficient(curr_variable.left)});
}
// name of new constraint
std::stringstream name;
name << "dual_" << curr_variable.left->description();
// generate contraint where inequality / equality property is based in existance of 0 <= x_curr_var bound
{
// if upper bound ex. generate new var and add to lhs
if(curr_variable.left->upper_bound().first == true){
std::stringstream ub_name;
ub_name << "upper_bound_" << curr_variable.left->description();
Variable* upper_bound_var = new Variable(ub_name.str(), Continuous, {true, 0});
variables.insert(upper_bound_var);
lhs.insert({upper_bound_var, -1});
direction.insert({upper_bound_var, curr_variable.left->upper_bound().second});
}
}
{
if(curr_variable.left->lower_bound().first == true){
if(curr_variable.left->lower_bound().second == 0){
constraints.push_back(Constraint(name.str(), Inequality, lhs, -this->direction_coefficient(curr_variable.left)));
}else{
std::stringstream lb_name;
lb_name << "lower_bound_" << curr_variable.left->description();
Variable* lower_bound_var = new Variable(lb_name.str(), Continuous, {true, 0});
variables.insert(lower_bound_var);
lhs.insert({lower_bound_var, 1});
constraints.push_back(Constraint(name.str(), Equality, lhs, -this->direction_coefficient(curr_variable.left)));
direction.insert({lower_bound_var, -1});
}
}else{
constraints.push_back(Constraint(name.str(), Equality, lhs, -this->direction_coefficient(curr_variable.left)));
}
}
}
Polyeder polyeder (constraints, variables.unwrap());
for(size_t index = 0; index < this->polyeder().number_of_constraints(); ++index){
direction.insert({variables.unwrap().right.find(index)->second, this->polyeder().constraint(index).rhs()});
}
return Linear_Program(!this->is_maximum(), direction, polyeder);
}
std::ostream& operator<<(std::ostream& os, Linear_Program& linear_program){
if(linear_program.is_maximum()){
os << "Maximize\n";
......@@ -71,19 +157,19 @@ std::ostream& operator<<(std::ostream& os, Linear_Program& linear_program){
bool empty = true;
if(linear_program.direction().size() > 0){
bool add_plus = false;
for(size_t index = linear_program.direction_start(); index < linear_program.direction_end(); index++){
if(std::abs(linear_program.direction_coefficient(index)) > 1e-100){
for(auto direction_summand : linear_program.direction()){
if(std::abs(direction_summand.second) > 1e-100){
empty = false;
if(linear_program.direction_coefficient(index) < 0){
if(direction_summand.second < 0){
os << " - ";
}else if(add_plus){
os << " + ";
}
add_plus = true;
if(std::abs(std::abs(linear_program.direction_coefficient(index)) - 1) > 1e-100){
os << std::abs(linear_program.direction_coefficient(index)) << " ";
if(std::abs(std::abs(direction_summand.second) - 1) > 1e-100){
os << std::abs(direction_summand.second) << " ";
}
os << linear_program.polyeder().variable_identifier(index);
os << direction_summand.first->description();
}
}
}
......
......@@ -2,36 +2,42 @@
#define LINEAR_PROGRAM_H
#include <cstddef>
#include <map>
#include <vector>
#include <cmath>
#include <sstream>
#include <fstream>
#include <iostream>
#include <cstdlib>
#include <boost/bimap.hpp>
#include "Polyeder.h"
#include "../Common/integrality.h"
class Linear_Program{
bool _maximum;
size_t _direction_start;
std::vector<double> _direction;
std::map<Variable*, double> _direction;
Polyeder _polyeder;
public:
Linear_Program(Linear_Program& lp);
Linear_Program(Linear_Program&& lp);
Linear_Program(bool maximum);
Linear_Program(bool maximum, size_t direction_start, std::vector<double> direction, Polyeder& polyeder);
Linear_Program(bool maximum, std::map<Variable*, double> direction, Polyeder polyeder);
bool is_maximum();
double direction_coefficient(size_t index);
std::map<Variable*, double> direction();
void add_direction_coefficient(std::pair<Variable*, double> summand);
double direction_coefficient(Variable* index);
Polyeder& polyeder();
size_t& direction_start();
size_t direction_end();
std::vector<double>& direction();
void solve();
void operator=(Linear_Program& lp);
void operator=(Linear_Program&& lp);
Linear_Program dual();
Linear_Program relaxation_dual();
};
std::ostream& operator<<(std::ostream& os, Linear_Program& linear_program);
#endif
......@@ -64,6 +64,12 @@ void Polyeder::add_constraint(Constraint constraint){
this->_constraints.push_back(constraint);
}
Polyeder::~Polyeder(){
// for(auto var : this->_variables){
// delete var.left;
// }
}
void Polyeder::operator=(const Polyeder& p){
this->_constraints = p._constraints;
this->_variables = p._variables;
......
......@@ -36,6 +36,8 @@ public:
void operator=(const Polyeder& p);
void operator=(Polyeder&& p);
~Polyeder();
};
std::ostream& operator<<(std::ostream& os, Polyeder& polyeder);
......
......@@ -7,7 +7,7 @@ Variable::Variable(const Variable& var) : _description(var._description), _integ
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) {}
//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) {}
Variable::Variable(std::string description, integrality integrality, std::pair<bool, double> lower_bound, std::pair<bool, double> upper_bound, double value) : _description(description), _integrality(integrality), _lower_bound(lower_bound), _upper_bound(upper_bound), _value(value) {}
......
......@@ -2,6 +2,7 @@
#define VARIABLE_H
#include <string>
#include <iostream>
#include "../Common/integrality.h"
......@@ -15,7 +16,7 @@ class Variable{
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(integrality integrality, std::pair<bool, double> lower_bound = {false, 0}, std::pair<bool, double> upper_bound = {false, 0}, double value = 0); // string needs to be intialized
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);
std::string description();
......
......@@ -80,7 +80,7 @@ Maintenance_Problem::Maintenance_Problem(CircSelectNetwork& g, CircSelectNode* s
/*
value bounded by flow
*/
auto target_var = this->polyeder().add_variable(Variable("target_variable", Continuous));
std::pair<Variable*, size_t> target_var = this->polyeder().add_variable(Variable("target_variable", Continuous));
for(size_t epoch = 0; epoch < intervals; ++epoch){
auto lookup_during_epoch = lookup[epoch];
......@@ -102,8 +102,7 @@ Maintenance_Problem::Maintenance_Problem(CircSelectNetwork& g, CircSelectNode* s
);
}
this->direction() = {1};
this->direction_start() = this->polyeder().vs_dim()-1;
this->add_direction_coefficient({target_var.first, 1});
}
void Maintenance_Problem::operator=(Maintenance_Problem& mp){
......
#include "./Linear_Programming/Linear_Program.h"
#include <iostream>
int main(){
auto var1 = new Variable("x1", Continuous, {true, 0});
auto var2 = new Variable("x2", Continuous, {true, 0});
auto var3 = new Variable("x3", Continuous, {false,0}, {true, 6});
std::vector<boost::bimap<Variable*, size_t>::value_type> v = {{var1, 0}, {var2, 1}, {var3, 2}};
Linear_Program lp (true, {{var1, 1}, {var2, -2}}, Polyeder({Constraint("1", Equality, {{var1, 1}, {var3, -1}}, 0), Constraint("2", Inequality, {{var1, 1}, {var2, 1}, {var3, 1}}, 1), Constraint("3", Inequality, {{var1, -1}, {var3, -1}}, 5)}, {v.begin(), v.end()}));
std::cout << lp << std::endl;
lp.solve();
auto dual = lp.relaxation_dual();
std::cout << dual << std::endl;
dual.solve();
}
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