CYCLUS
Loading...
Searching...
No Matches
matl_buy_policy.cc
Go to the documentation of this file.
1#include "matl_buy_policy.h"
2
3#include <sstream>
4
5#include "error.h"
6
7#define LG(X) LOG(LEV_##X, "buypol")
8#define LGH(X) \
9 LOG(LEV_##X, "buypol") << "policy " << name_ << " (agent " \
10 << Trader::manager()->prototype() << "-" \
11 << Trader::manager()->id() << "): "
12
13namespace cyclus {
14namespace toolkit {
15
17 : Trader(NULL),
18 name_(""),
19 throughput_(std::numeric_limits<double>::max()),
20 quantize_(-1),
21 fill_to_(std::numeric_limits<double>::max()),
22 req_at_(std::numeric_limits<double>::max()),
23 cumulative_cap_(-1),
24 cycle_total_inv_(0),
25 active_dist_(NULL),
26 dormant_dist_(NULL),
27 size_dist_(NULL) {
29 "MatlBuyPolicy is experimental and its API may be subject to change");
30}
31
35
37 throughput_ = std::numeric_limits<double>::max();
38 quantize_ = -1;
39 fill_to_ = std::numeric_limits<double>::max();
40 req_at_ = std::numeric_limits<double>::max();
41 cumulative_cap_ = -1;
42 cycle_total_inv_ = 0;
43 active_dist_ = NULL;
44 dormant_dist_ = NULL;
45 size_dist_ = NULL;
46 return *this;
47}
48
49void MatlBuyPolicy::set_manager(Agent* m) {
50 if (m != NULL) {
52 } else {
53 std::stringstream ss;
54 ss << "No manager set on Buy Policy " << name_;
55 throw ValueError(ss.str());
56 }
57}
58
59void MatlBuyPolicy::set_total_inv_tracker(TotalInvTracker* t) {
60 if (t == NULL) {
61 std::vector<ResBuf<Material>*> bufs = {buf_};
62 buf_tracker_->Init(bufs, buf_->capacity());
63 } else if (!t->buf_in_tracker(buf_)) {
64 std::stringstream ss;
65 ss << "TotalInvTracker does not contain ResBuf used in buy policy";
66 throw ValueError(ss.str());
67 } else {
68 buf_tracker_ = t;
69 }
70}
71
72void MatlBuyPolicy::set_inv_policy(std::string inv_policy, double fill,
73 double req_at) {
74 set_req_at(req_at);
75 std::transform(inv_policy.begin(), inv_policy.end(), inv_policy.begin(),
76 ::tolower);
77 if ((inv_policy == "ss")) {
78 set_fill_to(fill);
79 } else if ((inv_policy == "rq") || (inv_policy == "qr")) {
80 set_quantize(fill);
81 // maximum amount that an RQ policy could achieve is req_at + fill
82 set_fill_to(req_at + fill);
83 } else {
84 throw ValueError("Invalid inventory policy");
85 }
86}
87
88void MatlBuyPolicy::set_fill_to(double x) {
89 assert(x > 0);
90 fill_to_ = std::min(x, buf_->capacity());
91}
92
93void MatlBuyPolicy::set_req_at(double x) {
94 assert(x >= 0);
95 req_at_ = std::min(x, buf_->capacity());
96}
97
98void MatlBuyPolicy::set_cumulative_cap(double x) {
99 assert(x > 0);
100 cumulative_cap_ = std::min(x, buf_->capacity());
101}
102
103void MatlBuyPolicy::set_quantize(double x) {
104 assert(x != 0);
105 quantize_ = x;
106}
107
108void MatlBuyPolicy::set_throughput(double x) {
109 assert(x >= 0);
110 throughput_ = x;
111}
112
113void MatlBuyPolicy::init_active_dormant() {
114 if (active_dist_ == NULL) {
115 active_dist_ = boost::shared_ptr<FixedIntDist>(new FixedIntDist(1));
116 }
117 if (dormant_dist_ == NULL) {
118 dormant_dist_ = boost::shared_ptr<FixedIntDist>(new FixedIntDist(-1));
119 }
120 if (size_dist_ == NULL) {
121 size_dist_ = boost::shared_ptr<FixedDoubleDist>(new FixedDoubleDist(1.0));
122 }
123
124 if (size_dist_->max() > 1) {
125 throw ValueError("Size distribution cannot have a max greater than 1.");
126 }
127
129 LGH(INFO4) << "first active time end: " << next_active_end_ << std::endl;
130
131 if (dormant_dist_->sample() < 0) {
132 next_dormant_end_ = -1;
133 LGH(INFO4) << "dormant length -1, always active" << std::endl;
134 } else if (use_cumulative_capacity()) {
135 next_dormant_end_ = -1;
136 LGH(INFO4) << "dormant length set at -1 for first active period of "
137 "cumulative capacity cycle"
138 << std::endl;
139 } else {
141 LGH(INFO4) << "first dormant time end: " << next_dormant_end_ << std::endl;
142 }
143}
144
146 std::string name,
147 TotalInvTracker* buf_tracker) {
148 set_manager(manager);
149 buf_ = buf;
150 name_ = name;
151 set_total_inv_tracker(buf_tracker);
152 init_active_dormant();
153 return *this;
154}
155
157 Agent* manager, ResBuf<Material>* buf, std::string name,
158 TotalInvTracker* buf_tracker, double throughput,
159 boost::shared_ptr<IntDistribution> active_dist,
160 boost::shared_ptr<IntDistribution> dormant_dist,
161 boost::shared_ptr<DoubleDistribution> size_dist) {
162 set_manager(manager);
163 buf_ = buf;
164 name_ = name;
165 set_total_inv_tracker(buf_tracker);
166 set_throughput(throughput);
167 active_dist_ = active_dist;
168 dormant_dist_ = dormant_dist;
169 size_dist_ = size_dist;
170 init_active_dormant();
171 return *this;
172}
173
175 std::string name,
176 TotalInvTracker* buf_tracker,
177 double throughput, double quantize) {
178 set_manager(manager);
179 buf_ = buf;
180 name_ = name;
181 set_total_inv_tracker(buf_tracker);
182 set_throughput(throughput);
183 set_quantize(quantize);
184 init_active_dormant();
185 return *this;
186}
187
189 std::string name,
190 TotalInvTracker* buf_tracker,
191 double throughput, std::string inv_policy,
192 double fill_behav, double req_at) {
193 set_manager(manager);
194 buf_ = buf;
195 name_ = name;
196 set_total_inv_tracker(buf_tracker);
197 set_inv_policy(inv_policy, fill_behav, req_at);
198 set_throughput(throughput);
199 init_active_dormant();
200 return *this;
201}
202
204 std::string name,
205 TotalInvTracker* buf_tracker,
206 std::string inv_policy, double fill_behav,
207 double req_at) {
208 set_manager(manager);
209 buf_ = buf;
210 name_ = name;
211 set_total_inv_tracker(buf_tracker);
212 set_inv_policy(inv_policy, fill_behav, req_at);
213 init_active_dormant();
214 return *this;
215}
216
218 Agent* manager, ResBuf<Material>* buf, std::string name,
219 TotalInvTracker* buf_tracker, double throughput, double cumulative_cap,
220 boost::shared_ptr<IntDistribution> dormant_dist) {
221 set_manager(manager);
222 buf_ = buf;
223 name_ = name;
224 set_total_inv_tracker(buf_tracker);
225 set_throughput(throughput);
226 set_cumulative_cap(cumulative_cap);
227 dormant_dist_ = dormant_dist;
228 init_active_dormant();
229 return *this;
230}
231
232MatlBuyPolicy& MatlBuyPolicy::Set(std::string commod) {
233 CompMap c;
234 c[10010000] = 1e-100;
235 return Set(commod, Composition::CreateFromMass(c), 1.0);
236}
237
239 return Set(commod, c, 1.0);
240}
241
243 double pref) {
244 CommodDetail d;
245 d.comp = c;
246 d.pref = pref;
247 commod_details_[commod] = d;
248 return *this;
249}
250
252 commod_details_.erase(commod);
253 return *this;
254}
255
257 if (manager() == NULL) {
258 std::stringstream ss;
259 ss << "No manager set on Buy Policy " << name_;
260 throw ValueError(ss.str());
261 }
262 manager()->context()->RegisterTrader(this);
263}
264
266 if (manager() == NULL) {
267 std::stringstream ss;
268 ss << "No manager set on Buy Policy " << name_;
269 throw ValueError(ss.str());
270 }
271 manager()->context()->UnregisterTrader(this);
272}
273
274std::set<RequestPortfolio<Material>::Ptr> MatlBuyPolicy::GetMatlRequests() {
275 rsrc_commods_.clear();
276 std::set<RequestPortfolio<Material>::Ptr> ports;
277
278 double amt = 0;
279
280 int current_time_ = manager()->context()->time();
281
282 double max_request_amt = use_cumulative_capacity()
283 ? cumulative_cap_ - cycle_total_inv_
284 : std::numeric_limits<double>::max();
285
286 if (MakeReq() && !dormant(current_time_)) {
287 amt = std::min(TotalAvailable() * SampleRequestSize(), max_request_amt);
288 } else {
289 LGH(INFO3) << "in dormant period, no request" << std::endl;
290 }
291
293
294 if (amt < eps()) return ports;
295
296 bool excl = Excl();
297 double req_amt = ReqQty(amt);
298 int n_req = NReq(amt);
299 LGH(INFO3) << "requesting " << amt << " kg via " << n_req << " request(s)"
300 << std::endl;
301
302 // one portfolio for each request
303 for (int i = 0; i != n_req; i++) {
305 std::vector<Request<Material>*> mreqs;
306 std::map<std::string, CommodDetail>::iterator it;
307 for (it = commod_details_.begin(); it != commod_details_.end(); ++it) {
308 std::string commod = it->first;
309 CommodDetail d = it->second;
310 LG(INFO3) << " - one " << amt << " kg request of " << commod;
311 Material::Ptr m = Material::CreateUntracked(req_amt, d.comp);
312 Request<Material>* r = port->AddRequest(m, this, commod, d.pref, excl);
313 mreqs.push_back(r);
314 }
315 port->AddMutualReqs(mreqs);
316 ports.insert(port);
317 }
318
319 return ports;
320}
321
323 const std::vector<std::pair<Trade<Material>, Material::Ptr>>& resps) {
324 std::vector<std::pair<Trade<Material>, Material::Ptr>>::const_iterator it;
325 rsrc_commods_.clear();
326 for (it = resps.begin(); it != resps.end(); ++it) {
327 rsrc_commods_[it->second] = it->first.request->commodity();
328 LGH(INFO3) << "got " << it->second->quantity() << " kg of "
329 << it->first.request->commodity() << std::endl;
330 buf_->Push(it->second);
331 // cumulative capacity handling
333 cycle_total_inv_ += it->second->quantity();
334 }
335 }
336 // check if cumulative cap has been reached. If yes, then sample for dormant
337 // length and reset cycle_total_inv
339 ((cumulative_cap_ - cycle_total_inv_) < eps_rsrc())) {
341 LGH(INFO3) << "cycle cumulative inventory has been reached. Dormant period "
342 "will end at "
343 << next_dormant_end_ << std::endl;
344 cycle_total_inv_ = 0;
345 }
346}
347
349 int active_length = active_dist_->sample();
350 next_active_end_ = active_length + manager()->context()->time();
351 if (manager() != NULL) {
353 RecordActiveDormantTime(manager()->context()->time(), "CumulativeCap",
354 active_length);
355 } else {
356 RecordActiveDormantTime(manager()->context()->time(), "Active",
357 active_length);
358 }
359 }
360 return;
361};
362
364 int dormant_length;
365 int dormant_start;
367 // cumulative_cap dormant portion is updated only after the active cycle
368 // ends, because it's based on actual material recieved and not a dist
369 // that can be sampled at any time. Therefore, need the +1 when
370 // because next_active_end_ is not useful
371 dormant_length = dormant_dist_->sample();
372 dormant_start = manager()->context()->time() + 1;
373 } else if (next_dormant_end_ >= 0) {
374 // dormant dist is used, and so is active dist. Just need to sample for
375 // length and add to active cycle
376 dormant_length = dormant_dist_->sample();
377 dormant_start = std::max(next_active_end_, 1);
378 } else { // next_active_end_ < 0 used to indicate always active. Do not enter
379 // dormant
380 return;
381 }
382 next_dormant_end_ = dormant_length + dormant_start;
383 if (manager() != NULL) {
384 RecordActiveDormantTime(dormant_start, "Dormant", dormant_length);
385 }
386 return;
387}
388
390 return size_dist_->sample();
391}
392
394 if (manager()->context()->time() == next_dormant_end_) {
396 next_dormant_end_ = -1;
397 } else {
399
401 LGH(INFO4) << "end of dormant period, next active time end: "
402 << next_active_end_
403 << ", and next dormant time end: " << next_dormant_end_
404 << std::endl;
405 }
406 }
407 return;
408}
409
410void MatlBuyPolicy::RecordActiveDormantTime(int time, std::string type,
411 int length) {
412 manager()
413 ->context()
414 ->NewDatum("BuyPolActiveDormant")
415 ->AddVal("Agent", manager()->id())
416 ->AddVal("Time", time)
417 ->AddVal("Type", type)
418 ->AddVal("Length", length)
419 ->Record();
420 return;
421}
422
423} // namespace toolkit
424} // namespace cyclus
The abstract base class used by all types of agents that live and interact in a simulation.
Definition agent.h:50
Context * context() const
Returns this agent's simulation context.
Definition agent.h:364
static Ptr CreateFromMass(CompMap v)
Creates a new composition from v with its components having appropriate mass-based ratios.
boost::shared_ptr< Composition > Ptr
Definition composition.h:43
void UnregisterTrader(Trader *e)
Unregisters an agent as a participant in resource exchanges.
Definition context.h:181
Datum * NewDatum(std::string title)
See Recorder::NewDatum documentation.
Definition context.cc:351
void RegisterTrader(Trader *e)
Registers an agent as a participant in resource exchanges.
Definition context.h:178
virtual int time()
Returns the current simulation timestep.
Definition context.cc:314
Datum * AddVal(const char *field, boost::spirit::hold_any val, std::vector< int > *shape=NULL)
Add an arbitrary field-value pair to the datum.
Definition datum.cc:21
void Record()
Record this datum to its Recorder.
Definition datum.cc:34
static Ptr CreateUntracked(double quantity, Composition::Ptr c, double unit_value=kUnsetUnitValue)
Creates a new material resource that does not actually exist as part of the simulation and is untrack...
Definition material.cc:26
boost::shared_ptr< Material > Ptr
Definition material.h:75
A RequestPortfolio is a group of (possibly constrained) requests for resources.
void AddMutualReqs(const std::vector< Request< T > * > &rs)
adds a collection of requests (already having been registered with this portfolio) as multicommodity ...
Request< T > * AddRequest(boost::shared_ptr< T > target, Trader *requester, std::string commodity, double preference, bool exclusive, cost_function_t cost_function)
add a request to the portfolio
boost::shared_ptr< RequestPortfolio< T > > Ptr
A Request encapsulates all the information required to communicate the needs of an agent in the Dynam...
Definition request.h:29
Trader(Agent *manager)
Definition trader.h:26
Agent * manager_
Definition trader.h:82
virtual Agent * manager()
Definition trader.h:28
For values that are too big, too small, etc.
Definition error.h:37
MatlBuyPolicy performs semi-automatic inventory management of a material buffer by making requests an...
void Stop()
Unregisters this policy as a trader in the current simulation.
int NReq(double amt) const
the number of requests made per each commodity
MatlBuyPolicy & Set(std::string commod)
Instructs the policy to fill its buffer with requests on the given commodity of composition c and the...
virtual std::set< RequestPortfolio< Material >::Ptr > GetMatlRequests()
Trader Methods.
void Start()
Registers this policy as a trader in the current simulation.
virtual void AcceptMatlTrades(const std::vector< std::pair< Trade< Material >, Material::Ptr > > &resps)
default implementation for material trade acceptance
bool Excl() const
whether trades will be denoted as exclusive or not
MatlBuyPolicy & Init(Agent *manager, ResBuf< Material > *buf, std::string name, TotalInvTracker *buf_tracker)
Configures the policy to keep buf filled to a certain fraction of its capacity every time step.
MatlBuyPolicy & Unset(std::string commod)
Instructs the policy to stop requesting a speific commodity.
MatlBuyPolicy & ResetBehavior()
Reset a material buy policy parameters that govern its behavior to the default state.
double TotalAvailable() const
the total amount available to request
bool MakeReq() const
whether a request can be made
void RecordActiveDormantTime(int time, std::string type, int length)
MatlBuyPolicy()
Creates an uninitialized policy.
double ReqQty(double amt) const
the amount requested per each request
ResBuf is a helper class that provides semi-automated management of a collection of resources (e....
Definition res_buf.h:61
#define LG(X)
#define LGH(X)
double cumulative_cap
cyclus::IntDistribution::Ptr dormant_dist_
cyclus::IntDistribution::Ptr active_dist_
cyclus::DoubleDistribution::Ptr size_dist_
taken directly from OsiSolverInterface.cpp on 2/17/14 from https://projects.coin-or....
Definition agent.cc:14
double eps_rsrc()
an epsilon value to be used by resources
Definition cyc_limits.h:19
std::map< Nuc, double > CompMap
a raw definition of nuclides and corresponding (dimensionless quantities).
Definition composition.h:17
double eps()
a generic epsilon value
Definition cyc_limits.h:12
void Warn(const std::string &msg)
Issue a warning with the approriate message, accoring to the current warning settings.
Definition error.h:108
A Trade is a simple container that associates a request for a resource with a bid for that resource.
Definition trade.h:15