CYCLUS
Loading...
Searching...
No Matches
prog_translator.cc
Go to the documentation of this file.
1#include "prog_translator.h"
2
3#include <algorithm>
4
5#include "CoinPackedVector.hpp"
6#include "OsiSolverInterface.hpp"
7
8#include "cyc_limits.h"
9#include "error.h"
10#include "exchange_graph.h"
11#include "exchange_solver.h"
12#include "logger.h"
13
14namespace cyclus {
15
16ProgTranslator::ProgTranslator(ExchangeGraph* g, OsiSolverInterface* iface)
17 : g_(g),
18 iface_(iface),
19 excl_(false),
20 pseudo_cost_(std::numeric_limits<double>::max()) {
21 Init();
22}
23
24ProgTranslator::ProgTranslator(ExchangeGraph* g, OsiSolverInterface* iface,
25 bool exclusive)
26 : g_(g),
27 iface_(iface),
28 excl_(exclusive),
29 pseudo_cost_(std::numeric_limits<double>::max()) {
30 Init();
31}
32
33ProgTranslator::ProgTranslator(ExchangeGraph* g, OsiSolverInterface* iface,
34 double pseudo_cost)
35 : g_(g), iface_(iface), excl_(false), pseudo_cost_(pseudo_cost) {
36 Init();
37}
38
39ProgTranslator::ProgTranslator(ExchangeGraph* g, OsiSolverInterface* iface,
40 bool exclusive, double pseudo_cost)
41 : g_(g), iface_(iface), excl_(exclusive), pseudo_cost_(pseudo_cost) {
42 Init();
43}
44
45void ProgTranslator::Init() {
46 arc_offset_ = g_->arcs().size();
47 int n_cols = arc_offset_ + g_->request_groups().size();
48 ctx_.obj_coeffs.resize(n_cols);
49 ctx_.col_ubs.resize(n_cols);
50 ctx_.col_lbs.resize(n_cols);
51 ctx_.m = CoinPackedMatrix(false, 0, 0);
52}
53
54void ProgTranslator::CheckPref(double pref) {
55 if (pref <= 0) {
56 std::stringstream ss;
57 ss << "Preference value found to be nonpositive (" << pref
58 << "). Preferences must be positive when using an optimization solver."
59 << " If using Cyclus in simulation mode (e.g., from the command line),"
60 << " this error is likely a bug in Cyclus. Please report it to the "
61 "developer's "
62 << "list (https://groups.google.com/forum/#!forum/cyclus-dev).";
63 throw ValueError(ss.str());
64 }
65}
66
68 // number of variables = number of arcs + 1 faux arc per request group with
69 // arcs
70 int nfalse = 0;
71 std::vector<RequestGroup::Ptr>& rgs = g_->request_groups();
72 for (int i = 0; i != g_->request_groups().size(); ++i)
73 nfalse += rgs[i].get()->HasArcs() ? 1 : 0;
74 int n_cols = g_->arcs().size() + nfalse;
75 ctx_.m.setDimensions(0, n_cols);
76
77 bool request;
78 std::vector<ExchangeNodeGroup::Ptr>& sgs = g_->supply_groups();
79 for (int i = 0; i != sgs.size(); i++) {
80 request = false;
81 XlateGrp_(sgs[i].get(), request);
82 }
83
84 for (int i = 0; i != rgs.size(); i++) {
85 request = true;
86 XlateGrp_(rgs[i].get(), request);
87 }
88
89 // add each false arc
90 CLOG(LEV_DEBUG1) << "Adding " << arc_offset_ - g_->arcs().size()
91 << " false arcs.";
92 double inf = iface_->getInfinity();
93 for (int i = g_->arcs().size(); i != arc_offset_; i++) {
94 ctx_.obj_coeffs[i] = pseudo_cost_;
95 ctx_.col_lbs[i] = 0;
96 ctx_.col_ubs[i] = inf;
97 }
98}
99
101 iface_->setObjSense(1.0); // minimize
102
103 // load er up!
104 iface_->loadProblem(ctx_.m, &ctx_.col_lbs[0], &ctx_.col_ubs[0],
105 &ctx_.obj_coeffs[0], &ctx_.row_lbs[0], &ctx_.row_ubs[0]);
106
107 if (excl_) {
108 std::vector<Arc>& arcs = g_->arcs();
109 for (int i = 0; i != arcs.size(); i++) {
110 Arc& a = arcs[i];
111 if (a.exclusive()) {
112 iface_->setInteger(g_->arc_ids()[a]);
113 }
114 }
115 }
116}
117
119 Translate();
120 Populate();
121}
122
123void ProgTranslator::XlateGrp_(ExchangeNodeGroup* grp, bool request) {
124 double inf = iface_->getInfinity();
125 std::vector<double>& caps = grp->capacities();
126
127 if (request && !grp->HasArcs())
128 return; // no arcs, no reason to add variables/constraints
129
130 std::vector<CoinPackedVector> cap_rows;
131 std::vector<CoinPackedVector> excl_rows;
132 for (int i = 0; i != caps.size(); i++) {
133 cap_rows.push_back(CoinPackedVector());
134 }
135
136 std::vector<ExchangeNode::Ptr>& nodes = grp->nodes();
137 for (int i = 0; i != nodes.size(); i++) {
138 std::map<Arc, std::vector<double>>& ucap_map = nodes[i]->unit_capacities;
139 std::map<Arc, std::vector<double>>::iterator cap_it;
140
141 // add each arc
142 for (cap_it = ucap_map.begin(); cap_it != ucap_map.end(); ++cap_it) {
143 const Arc& a = cap_it->first;
144 std::vector<double>& ucaps = cap_it->second;
145 int arc_id = g_->arc_ids()[a];
146
147 // add each unit capacity coefficient
148 for (int j = 0; j != ucaps.size(); j++) {
149 double coeff = ucaps[j];
150 if (excl_ && a.exclusive()) {
151 coeff *= a.excl_val();
152 }
153
154 cap_rows[j].insert(arc_id, coeff);
155 }
156
157 if (request) {
158 CheckPref(a.pref());
159 ctx_.obj_coeffs[arc_id] = ExchangeSolver::Cost(a, excl_);
160 ctx_.col_lbs[arc_id] = 0;
161 ctx_.col_ubs[arc_id] =
162 (excl_ && a.exclusive()) ? 1 : std::min(nodes[i]->qty, inf);
163 }
164 }
165 }
166
167 int faux_id;
168 if (request) {
169 faux_id = arc_offset_++;
170 }
171
172 // add all capacity rows
173 for (int i = 0; i != cap_rows.size(); i++) {
174 if (request) {
175 cap_rows[i].insert(faux_id, 1.0); // faux arc
176 }
177
178 // 1e15 is the largest value that doesn't make the solver fall over
179 // (by emperical testing)
180 double rlb = std::min(caps[i], 1e15);
181 ctx_.row_lbs.push_back(request ? rlb : 0);
182 ctx_.row_ubs.push_back(request ? inf : caps[i]);
183 ctx_.m.appendRow(cap_rows[i]);
184 }
185
186 if (excl_) {
187 // add exclusive arcs
188 std::vector<std::vector<ExchangeNode::Ptr>>& exngs =
189 grp->excl_node_groups();
190 for (int i = 0; i != exngs.size(); i++) {
191 CoinPackedVector excl_row;
192 std::vector<ExchangeNode::Ptr>& nodes = exngs[i];
193 for (int j = 0; j != nodes.size(); j++) {
194 std::vector<Arc>& arcs = g_->node_arc_map()[nodes[j]];
195 for (int k = 0; k != arcs.size(); k++) {
196 excl_row.insert(g_->arc_ids()[arcs[k]], 1.0);
197 }
198 }
199 if (excl_row.getNumElements() > 0) {
200 excl_rows.push_back(excl_row);
201 }
202 }
203
204 // add all exclusive rows
205 for (int i = 0; i != excl_rows.size(); i++) {
206 ctx_.row_lbs.push_back(0.0);
207 ctx_.row_ubs.push_back(1.0);
208 ctx_.m.appendRow(excl_rows[i]);
209 }
210 }
211}
212
214 const double* sol = iface_->getColSolution();
215 std::vector<Arc>& arcs = g_->arcs();
216 double flow;
217 for (int i = 0; i < arcs.size(); i++) {
218 Arc& a = g_->arc_by_id().at(i);
219 flow = sol[i];
220 flow = (excl_ && a.exclusive()) ? flow * a.excl_val() : flow;
221 if (flow > cyclus::eps()) {
222 g_->AddMatch(a, flow);
223 }
224 }
225}
226
227} // namespace cyclus
An arc represents a possible connection between two nodes in the bipartite resource exchange graph.
double excl_val() const
bool exclusive() const
An ExchangeGraph is a resource-neutral representation of a ResourceExchange.
const std::vector< Arc > & arcs() const
const std::map< Arc, int > & arc_ids() const
const std::vector< RequestGroup::Ptr > & request_groups() const
A ExchangeNodeGroup is a collection of ExchangeNodes, and is the ExchangeGraph representation of a Bi...
const std::vector< double > & capacities() const
the flow capacities assocaited with this group
const std::vector< ExchangeNode::Ptr > & nodes() const
const std::vector< std::vector< ExchangeNode::Ptr > > & excl_node_groups() const
exclusive node groups represent nodes over whose combined arcs flow can only exist on one arc
static double Cost(const Arc &a, bool exclusive_orders=kDefaultExclusive)
return the cost of an arc
ProgTranslator(ExchangeGraph *g, OsiSolverInterface *iface)
constructor
void FromProg()
translates solution from iface back into graph matches
void Populate()
populates the solver interface with values from the translators Context
void ToProg()
translates graph into mathematic program via iface.
void Translate()
translates the graph, filling the translators Context
Code providing rudimentary logging capability for the Cyclus core.
#define CLOG(level)
Definition logger.h:40
taken directly from OsiSolverInterface.cpp on 2/17/14 from https://projects.coin-or....
Definition agent.cc:14
@ LEV_DEBUG1
debugging information - least verbose
Definition logger.h:70
double eps()
a generic epsilon value
Definition cyc_limits.h:12
std::vector< double > col_lbs
std::vector< double > col_ubs
std::vector< double > obj_coeffs