CYCLUS
request_portfolio.h
Go to the documentation of this file.
1 #ifndef CYCLUS_SRC_REQUEST_PORTFOLIO_H_
2 #define CYCLUS_SRC_REQUEST_PORTFOLIO_H_
3 
4 #include <functional>
5 #include <numeric>
6 #include <set>
7 #include <string>
8 #include <vector>
9 
10 #include <boost/enable_shared_from_this.hpp>
11 #include <boost/shared_ptr.hpp>
12 
13 #include "capacity_constraint.h"
14 #include "error.h"
15 #include "logger.h"
16 #include "request.h"
17 
18 namespace cyclus {
19 
20 class Trader;
21 
22 /// @brief accumulator sum for request quantities
23 template <class T> inline double SumQty(double total, Request<T>* r) {
24  return total += r->target()->quantity();
25 }
26 
27 /// @brief provide coefficients for default mass constraints
28 ///
29 /// Coefficients are determiend by the request portfolio and are provided to the
30 /// converter. The arc and exchange context are used in order to reference the
31 /// original request so that the request's coefficient can be applied.
32 template <class T> struct QtyCoeffConverter : public Converter<T> {
33  QtyCoeffConverter(const std::map<Request<T>*, double>& coeffs)
34  : coeffs(coeffs) {}
35 
36  inline virtual double convert(
37  boost::shared_ptr<T> offer,
38  Arc const* a,
39  ExchangeTranslationContext<T> const* ctx) const {
40  return offer->quantity() * coeffs.at(ctx->node_to_request.at(a->unode()));
41  }
42 
43  virtual bool operator==(Converter<T>& other) const {
44  QtyCoeffConverter<T>* cast = dynamic_cast<QtyCoeffConverter<T>*>(&other);
45  return cast != NULL && coeffs == cast->coeffs;
46  }
47 
48  std::map<Request<T>*, double> coeffs;
49 };
50 
51 /// @class RequestPortfolio
52 ///
53 /// @brief A RequestPortfolio is a group of (possibly constrainted) requests for
54 /// resources
55 ///
56 /// The portfolio contains a grouping of resource requests that may be mutually
57 /// met by suppliers. These requests may share a common set of
58 /// constraints. Take, for instance, a facility that needs fuel, of which there
59 /// are
60 /// two commodity types, fuelA and fuelB. If some combination of the two suffice
61 /// the facility's needs, then requests for both would be added to the portfolio
62 /// along with a capacity constraint.
63 ///
64 /// The ExchangeTranslator will automatically add a mass-based constraint, that
65 /// accounts for mutual requests, if the portfolio has them. , e.g.,
66 /// @code
67 ///
68 /// RequestPortfolio<SomeResource>::Ptr rp(new
69 /// RequestPortfolio<SomeResource>());
70 /// // add some requests
71 /// rp->AddRequest(/* args */);
72 /// // declare some of them as multicommodity requsts (i.e., any one will
73 /// // satisfy this demand).
74 /// rp->AddMutualReqs(/* args */);
75 ///
76 /// @endcode
77 ///
78 /// A default constraint will add unity for normal requests in the portfolio,
79 /// but will add a weighted coefficient for requests that meet the same mutual
80 /// demand. For example, if 10 kg of MOX and 9 kg of UOX meet the same demand
81 /// for fuel, coefficients are added such that a full order of either will
82 /// determine the demand as "met". In this case, the total demand is 9.5, the
83 /// MOX order is given a coefficient of 9.5 / 10, and the UOX order is given a
84 /// coefficient of 9.5 / 9.
85 template <class T>
86 class RequestPortfolio
87  : public boost::enable_shared_from_this<RequestPortfolio<T>> {
88  public:
89  typedef boost::shared_ptr<RequestPortfolio<T>> Ptr;
90  typedef std::function<double(boost::shared_ptr<T>)> cost_function_t;
91 
92  RequestPortfolio() : requester_(NULL), qty_(0) {}
93 
94  /// deletes all requests associated with it
96  typename std::vector<Request<T>*>::iterator it;
97  for (it = requests_.begin(); it != requests_.end(); ++it) {
98  delete *it;
99  }
100  }
101 
102  /// @brief add a request to the portfolio
103  /// @param target the target resource associated with this request
104  /// @param requester the requester
105  /// @param commodity the commodity associated with this request
106  /// @param preference the preference associated with this request (relative to
107  /// others in the portfolio)
108  /// @param exclusive a flag denoting that this request must be met
109  /// exclusively,
110  /// i.e., in its entirety by a single offer
111  /// @param cost_function The cost function that the requester sets so that the
112  /// bidder may evaluate many potential resources.
113  /// @throws KeyError if a request is added from a different requester than the
114  /// original or if the request quantity is different than the original
115  Request<T>* AddRequest(boost::shared_ptr<T> target, Trader* requester,
116  std::string commodity, double preference,
117  bool exclusive, cost_function_t cost_function) {
118  Request<T>* r =
119  Request<T>::Create(target, requester, this->shared_from_this(),
120  commodity, preference, exclusive, cost_function);
121  VerifyRequester_(r);
122  requests_.push_back(r);
123  mass_coeffs_[r] = 1;
124  qty_ += target->quantity();
125  return r;
126  }
127  /// @brief add a request to the portfolio
128  /// @param target the target resource associated with this request
129  /// @param requester the requester
130  /// @param commodity the commodity associated with this request
131  /// @param preference the preference associated with this request (relative to
132  /// others in the portfolio)
133  /// @param exclusive a flag denoting that this request must be met
134  /// exclusively,
135  /// i.e., in its entirety by a single offer
136  /// @throws KeyError if a request is added from a different requester than the
137  /// original or if the request quantity is different than the original
138  Request<T>* AddRequest(boost::shared_ptr<T> target, Trader* requester,
139  std::string commodity = "",
140  double preference = kDefaultPref,
141  bool exclusive = false) {
142  return AddRequest(target, requester, commodity, preference, exclusive,
143  NULL);
144  }
145 
146  /// @brief adds a collection of requests (already having been registered with
147  /// this portfolio) as multicommodity requests
148  /// @param rs the collection of requests to add
149  inline void AddMutualReqs(const std::vector<Request<T>*>& rs) {
150  double avg_qty =
151  std::accumulate(rs.begin(), rs.end(), 0.0, SumQty<T>) / rs.size();
152  double qty;
153  Request<T>* r;
154  for (int i = 0; i < rs.size(); i++) {
155  r = rs[i];
156  qty = r->target()->quantity();
157  mass_coeffs_[r] = r->target()->quantity() / avg_qty;
158  qty_ -= qty;
159  }
160  qty_ += avg_qty;
161  }
162 
163  /// @brief add a capacity constraint associated with the portfolio, if it
164  /// doesn't already exist
165  /// @param c the constraint to add
166  inline void AddConstraint(const CapacityConstraint<T>& c) {
167  constraints_.insert(c);
168  }
169 
170  /// @return the agent associated with the portfolio. if no reqeusts have
171  /// been added, the requester is NULL.
172  inline Trader* requester() const { return requester_; }
173 
174  /// @return the request quantity associated with the portfolio.
175  ///
176  /// @brief, all requests in a portfolio must have the same quantity, which is
177  /// checked during AddRequest()
178  inline double qty() const { return qty_; }
179 
180  /// @return const access to the unconstrained requests
181  inline const std::vector<Request<T>*>& requests() const { return requests_; }
182 
183  /// @return const access to the request constraints
184  inline const std::set<CapacityConstraint<T>>& constraints() const {
185  return constraints_;
186  }
187 
188  /// returns a capacity converter for this portfolios request quantities
189  inline typename Converter<T>::Ptr qty_converter() {
190  return typename Converter<T>::Ptr(new QtyCoeffConverter<T>(mass_coeffs_));
191  }
192 
193  private:
194  /// @brief copy constructor is private to prevent copying and preserve
195  /// explicit single-ownership of requests
196  RequestPortfolio(const RequestPortfolio& rhs) {
197  requester_ = rhs.requester_;
198  requests_ = rhs.requests_;
199  constraints_ = rhs.constraints_;
200  qty_ = rhs.qty_;
201  typename std::vector<Request<T>*>::iterator it;
202  for (it = requests_.begin(); it != requests_.end(); ++it) {
203  it->get()->set_portfolio(this->shared_from_this());
204  }
205  }
206 
207  /// @brief if the requester has not been determined yet, it is set. otherwise
208  /// VerifyRequester() verifies the the request is associated with the
209  /// portfolio's
210  /// requester
211  /// @throws KeyError if a request is added from a different requester than the
212  /// original
213  void VerifyRequester_(const Request<T>* r) {
214  if (requester_ == NULL) {
215  requester_ = r->requester();
216  } else if (requester_ != r->requester()) {
217  std::string msg = "Insertion error: requesters do not match.";
218  throw KeyError(msg);
219  }
220  }
221 
222  /// requests_ is a vector because many requests may be identical, i.e., a set
223  /// is not appropriate
224  std::vector<Request<T>*> requests_;
225 
226  /// coefficients for the default mass constraint for known resources
227  std::map<Request<T>*, double> mass_coeffs_;
228 
229  /// constraints_ is a set because constraints are assumed to be unique
230  std::set<CapacityConstraint<T>> constraints_;
231 
232  /// the total quantity of resources assocaited with the portfolio
233  double qty_;
234  Trader* requester_;
235 };
236 
237 } // namespace cyclus
238 
239 #endif // CYCLUS_SRC_REQUEST_PORTFOLIO_H_
a simple interface for converting resource objects to unit capacities
An arc represents a possible connection between two nodes in the bipartite resource exchange graph...
static const double kDefaultPref
Default preference values are unity.
Definition: request.h:18
boost::shared_ptr< T > target() const
Definition: request.h:97
void AddConstraint(const CapacityConstraint< T > &c)
add a capacity constraint associated with the portfolio, if it doesn&#39;t already exist ...
boost::shared_ptr< RequestPortfolio< T > > Ptr
static Request< T > * Create(boost::shared_ptr< T > target, Trader *requester, typename RequestPortfolio< T >::Ptr portfolio, std::string commodity, double preference, bool exclusive, cost_function_t cost_function)
a factory method for a request
Definition: request.h:45
boost::shared_ptr< ExchangeNode > unode() const
A CapacityConstraint provides an ability to determine an agent&#39;s constraints on resource allocation g...
A simple API for agents that wish to exchange resources in the simulation.
Definition: trader.h:24
const std::set< CapacityConstraint< T > > & constraints() const
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
const std::vector< Request< T > * > & requests() const
Request< T > * AddRequest(boost::shared_ptr< T > target, Trader *requester, std::string commodity="", double preference=kDefaultPref, bool exclusive=false)
add a request to the portfolio
~RequestPortfolio()
deletes all requests associated with it
void AddRequest(ExchangeTranslationContext< T > &translation_ctx, Request< T > *r, ExchangeNode::Ptr n)
Adds a request-node mapping.
virtual bool operator==(Converter< T > &other) const
operator== is available for subclassing, see cyclus::TrivialConverter for an example ...
Converter< T >::Ptr qty_converter()
returns a capacity converter for this portfolios request quantities
std::map< Request< T > *, double > coeffs
virtual double convert(boost::shared_ptr< T > offer, Arc const *a, ExchangeTranslationContext< T > const *ctx) const
convert a capacitated quantity for an offer in its exchange context
void AddMutualReqs(const std::vector< Request< T > *> &rs)
adds a collection of requests (already having been registered with this portfolio) as multicommodity ...
Trader * requester() const
Definition: request.h:100
An ExchangeTranslationContext is a simple holder class for any information needed to translate a Reso...
boost::shared_ptr< Converter< T > > Ptr
provide coefficients for default mass constraints
Code providing rudimentary logging capability for the Cyclus core.
taken directly from OsiSolverInterface.cpp on 2/17/14 from https://projects.coin-or.org/Osi/browser/trunk.
Definition: agent.cc:14
double SumQty(double total, Request< T > *r)
accumulator sum for request quantities
QtyCoeffConverter(const std::map< Request< T > *, double > &coeffs)
std::function< double(boost::shared_ptr< T >)> cost_function_t
double qty() const
, all requests in a portfolio must have the same quantity, which is checked during AddRequest() ...
std::map< ExchangeNode::Ptr, Request< T > * > node_to_request
For failed retrieval/insertion of key-based data into/from data structures.
Definition: error.h:47
A Request encapsulates all the information required to communicate the needs of an agent in the Dynam...
Definition: request.h:29
A RequestPortfolio is a group of (possibly constrainted) requests for resources.
Definition: request.h:21