Commit 7ca13859 authored by Jonas Seidel's avatar Jonas Seidel
Browse files

LP generator using dfs

parent 8099e287
#ifndef LP_GENERATOR_H
#define LP_GENERATOR_H
#include <tuple>
#include <vector>
#include <map>
#include <functional>
#include "../Linear_Programming/Linear_Program.h"
#include "../Graphtheory/Graph.h"
template <typename N, typename E>
using lhs_constraint_data = std::pair<std::vector<std::pair<Node<N,E>*,double>>, std::vector<std::pair<Edge<N,E>*,double>> >;
template <typename N, typename E>
using constraint_data = std::tuple<relation, lhs_constraint_data<N,E>, double>;
template <typename N,typename E>
using node_constraint_data_generator = std::function<constraint_data<N,E>(Edge<N,E>*)>;
template <typename N,typename E>
using edge_constraint_data_generator = std::function<constraint_data<N,E>(Node<N,E>*)>;
class LP_Generator{
template <typename N, typename E>
static std::vector<double> constraint_from_data(size_t length, lhs_constraint_data<N,E>& data, std::map<Edge<N,E>*, size_t>& edge_variable_lookup, std::map<Node<N,E>*, size_t>& node_variable_lookup);
public:
template <typename N, typename E>
static void grow_from_graph(Linear_Program& lp, Graph<N,E>& g, edge_constraint_data_generator<N,E> edge, node_constraint_data_generator<N,E> node, integrality edge_integrality, integrality node_integrality);
};
#include "LP_Generator.ipp"
#endif
#include "LP_Generator.h"
template <typename N, typename E>
std::vector<double> LP_Generator::constraint_from_data(size_t length, lhs_constraint_data<N,E>& data, std::map<Edge<N,E>*, size_t>& edge_variable_lookup, std::map<Node<N,E>*, size_t>& node_variable_lookup){
std::vector<double> lhs;
lhs.reserve(length);
for(std::pair<Node<N,E>*, double> w : data.fist){
lhs[edge_variable_lookup.find(w.first)->second] = w.second;
}
for(std::pair<Edge<N,E>*, double> w : data.second){
lhs[edge_variable_lookup.find(w.first)->second] = w.second;
}
return lhs;
}
template <typename N, typename E>
void LP_Generator::grow_from_graph(Linear_Program& lp, Graph<N,E>& g, edge_constraint_data_generator<N,E> edge, node_constraint_data_generator<N,E> node, integrality edge_integrality, integrality node_integrality){
Polyeder& p = lp.polyeder();
std::map<Node<N,E>*, size_t> node_lookup;
std::map<Edge<N,E>*, size_t> edge_lookup;
size_t start_index = p.vs_dim();
{
std::vector<Node<N,E>*> nodes = g.nodes();
for(int index = 0; index < nodes.size(); index++){
node_lookup.insert({nodes[index], p.add_variable(Variable(node_integrality))-start_index});
}
}
{
std::vector<Edge<N,E>*> edges = g.edges();
for(int index = 0; index < edges.size(); index++){
node_lookup.insert({edges[index], p.add_variable(Variable(edge_integrality))-start_index});
}
}
size_t length = p.vs_dim()-start_index;
for(Node<N,E>* n : g.nodes()){
auto data = node_constraint_data_generator<N,E>(n);
p.add_constraint(
Constraint(
std::get<0>(data),
LP_Generator::constraint_from_data(length, std::get<1>(data), edge_lookup, node_lookup),
std::get<2>(data),
start_index
)
);
}
for(Edge<N,E>* e : g.edges()){
auto data = edge_constraint_data_generator<N,E>(e);
p.add_constraint(
Constraint(
std::get<0>(data),
LP_Generator::constraint_from_data(length, std::get<1>(data), edge_lookup, node_lookup),
std::get<2>(data),
start_index
)
);
}
}
#ifndef LP_GENERATOR_H
#define LP_GENERATOR_H
#include <string>
#include <sstream>
#include <tuple>
#include <vector>
#include <map>
#include <functional>
#include "../Linear_Programming/Linear_Program.h"
#include "../Graphtheory/Graph.h"
template <typename N, typename E>
using lhs_constraint_data = std::pair<std::vector<std::pair<std::pair<Node<N,E>*,N>,double>>, std::vector<std::pair<std::pair<Edge<N,E>*,E>,double>> >;
template <typename N, typename E>
using constraint_data = std::tuple<std::string, relation, lhs_constraint_data<N,E>, double>;
template <typename N,typename E>
using node_constraint_data_generator = std::function<std::vector<constraint_data<N,E>>(Node<N,E>*)>;
template <typename N,typename E>
using edge_constraint_data_generator = std::function<std::vector<constraint_data<N,E>>(Edge<N,E>*)>;
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);
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);
};
#include "lp_generator.ipp"
#endif
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);
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;
}
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;
}
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(
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;
size_t start_index = p.vs_dim();
// put inside conditional_bfs_all_components call as parameters;
std::function<void(Node<N,E>* from, Edge<N,E>* via, bool used_in_traversal)> edge_function = [&p, &edge_lookup, &edge_var_data, start_index](Node<N,E>* from, Edge<N,E>* via, bool used_in_traversal) -> void {
for(std::pair<E, std::tuple<integrality, std::pair<bool, double>, std::pair<bool, double>>> edge_prop : edge_var_data){
std::stringstream name;
name << "edge" << via->from() << "_" << via->to() << "_" << static_cast<char>(edge_prop.first);
edge_lookup.insert({{via, edge_prop.first}, p.add_variable(Variable(name.str(), std::get<0>(edge_prop.second), std::get<1>(edge_prop.second), std::get<2>(edge_prop.second)))});
}
};
std::function<void(Node<N,E>*)> node_function = [&p, &node_lookup, &node_var_data, start_index](Node<N,E>* n) -> void {
for(std::pair<N, std::tuple<integrality, std::pair<bool, double>, std::pair<bool, double>>> node_prop : node_var_data){
std::stringstream name;
name << "node" << n << "_" << static_cast<char>(node_prop.first);
node_lookup.insert({{n,node_prop.first}, p.add_variable(Variable(name.str(), std::get<0>(node_prop.second), std::get<1>(node_prop.second), std::get<2>(node_prop.second)))});
}
};
g.conditional_bfs_all_components(
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)){
p.add_constraint(
Constraint(
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
)
);
}
}
for(Edge<N,E>* e : g.edges()){
for(auto data : edge_generator(e)){
p.add_constraint(
Constraint(
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
)
);
}
}
return {node_lookup, edge_lookup};
}
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