00001 #include<iostream>
00002 #include<scil/scil.h>
00003 #include<scil/constraints/spantree.h>
00004 #include<scil/core/monomial.h>
00005 #include <boost/foreach.hpp>
00006 #include <boost/graph/adjacency_list.hpp>
00007 #include <boost/graph/graph_traits.hpp>
00008 #include <boost/graph/iteration_macros.hpp>
00009 #include <boost/graph/kruskal_min_spanning_tree.hpp>
00010
00011 using namespace SCIL;
00012 using namespace std;
00013 using namespace boost;
00014
00015 typedef adjacency_list<vecS, vecS, undirectedS> Graph;
00016 typedef boost::graph_traits<Graph> GraphTraits;
00017 typedef GraphTraits::vertex_descriptor vertex_descriptor;
00018 typedef GraphTraits::edge_descriptor edge_descriptor;
00019
00020 class qmst_heuristic : public primal_heuristic {
00021 private:
00022 Graph& G;
00023 var_map<edge_descriptor>& VM;
00024
00025 public:
00026 qmst_heuristic(Graph& G_, var_map<edge_descriptor>& VM_)
00027 : G(G_), VM(VM_)
00028 { }
00029
00030 int heuristic(subproblem& S, solution& newSol) {
00031 edge_descriptor e;
00032 map<edge_descriptor, int> tc;
00033 BGL_FORALL_EDGES(e, G, Graph) {
00034 tc[e] = int(10. * (1. - (S.value(VM[e]))));
00035 }
00036
00037 list<edge_descriptor> tree;
00038
00039 typedef map<edge_descriptor, int> weight_map_t;
00040 typedef map<vertex_descriptor, size_t> vertex_index_t;
00041
00042 vertex_index_t vertex_index_map;
00043 int i = 0;
00044 BGL_FORALL_VERTICES(v, G, Graph)
00045 vertex_index_map[v] = i++;
00046
00047 associative_property_map<weight_map_t> pm_weight(tc);
00048 associative_property_map<vertex_index_t> pm_vertex_index(vertex_index_map);
00049
00050 kruskal_minimum_spanning_tree(G, back_inserter(tree), boost::weight_map(pm_weight).vertex_index_map(pm_vertex_index));
00051
00052 BGL_FORALL_EDGES(e, G, Graph) {
00053 newSol.set_value(VM[e], 0.);
00054 }
00055 BOOST_FOREACH(e, tree) {
00056 newSol.set_value(VM[e], 1.);
00057 }
00058 S.GM.extendSolution(newSol);
00059
00060 return 1;
00061 }
00062
00063 };
00064
00065 void read_inst(const char* file_name, Graph& G, var_map<edge_descriptor>& VM, ILP_Problem& IP) {
00066
00067 ifstream file;
00068 file.open(file_name);
00069
00070 int m, n, h1, h2, t1, t2, w;
00071 file >> n >> m;
00072 vector<vertex_descriptor> nm(n+1);
00073 edge_descriptor* em = new edge_descriptor[n*n];
00074
00075
00076 for( int i = 1; i <= n; i++ )
00077 nm[i] = add_vertex(G);
00078
00079
00080 for( int i = 0; i < m; i++ ) {
00081 file >> t1 >> h1 >> w;
00082 em[(t1-1)*n+(h1-1)] = add_edge(nm[t1], nm[h1], G).first;
00083 VM[em[(t1-1)*n+(h1-1)]] = IP.add_binary_variable(w);
00084 }
00085
00086
00087 for( int i = 0; i < m*(m-1); i++ ) {
00088 file >> t1 >> h1 >> t2 >> h2 >> w;
00089 IP.add_polynomial(VM[em[(t1-1)*n+(h1-1)]] * VM[em[(t2-1)*n+(h2-1)]] * w);
00090 }
00091
00092 file.close();
00093 return;
00094 }
00095
00096 int main(int argc, char** argv)
00097 {
00098 ILP_Problem IP(Optsense_Min);
00099
00100 Graph G;
00101 var_map<edge_descriptor> VM;
00102 read_inst(argv[1], G, VM, IP);
00103
00104
00105 IP.add_sym_constraint(new SpanTree<Graph>(G, VM));
00106
00107 IP.set_primal_heuristic(new qmst_heuristic(G, VM));
00108
00109 IP.optimize();
00110
00111 cout<<"optimal solution: "<<IP.get_optimum()<<endl;
00112
00113 cout<<"spanning tree: "<<endl;
00114 BGL_FORALL_EDGES(e, G, Graph)
00115 if(IP.get_solution(VM[e]))
00116 cout<<e<<endl;
00117
00118 return 0;
00119 }
00120