CYCLUS
Loading...
Searching...
No Matches
package.cc
Go to the documentation of this file.
1#include "package.h"
2#include "error.h"
3#include "cyc_limits.h"
4
5namespace cyclus {
6
7Package::Ptr Package::unpackaged_ = NULL;
8
9Package::Ptr Package::Create(std::string name, double fill_min, double fill_max,
10 std::string strategy) {
11 if (fill_min < 0 || fill_max < 0) {
12 throw ValueError("fill_min and fill_max must be non-negative");
13 } else if (fill_min > fill_max) {
14 throw ValueError("fill_min must be less than or equal to fill_max");
15 }
16 Ptr p(new Package(name, fill_min, fill_max, strategy));
17 return p;
18}
19
20// singleton pattern:
21// if the static member is not yet set, create a new object
22// otherwise return the object that already exists
24 if (!unpackaged_) {
25 unpackaged_ = Ptr(new Package(unpackaged_name_));
26 }
27
28 return unpackaged_;
29}
30
32 if (strategy_ == "uniform") {
33 dist_ = UniformDoubleDist::Ptr(new UniformDoubleDist(fill_min_, fill_max_));
34 } else if (strategy_ == "normal") {
35 dist_ =
36 NormalDoubleDist::Ptr(new NormalDoubleDist((fill_min_ + fill_max_) / 2,
37 (fill_max_ - fill_min_) / 6,
38 fill_min_,
39 fill_max_));
40 }
41}
42
43std::vector<double> Package::GetFillMass(double qty) {
44 std::vector<double> packages;
45 if ((qty - fill_min_) < -eps_rsrc()) {
46 // less than one pkg of material available
47 return packages;
48 }
49
50 // simple check for whether vector limits *might* be exceeded
51 ExceedsSplitLimits(qty / fill_max_);
52
53 double fill_mass;
54 int num_at_fill_mass;
55
56 if (strategy_ == "first") {
57 fill_mass = fill_max_;
58 } else if (strategy_ == "equal") {
59 int num_min_fill = std::floor(qty / fill_min_);
60 int num_max_fill = std::ceil(qty / fill_max_);
61 if (num_min_fill >= num_max_fill) {
62 // all material can fit in package(s)
63 fill_mass = qty / num_max_fill;
64 } else {
65 // some material will remain unpackaged, fill up as many max packages as
66 // possible
67 fill_mass = fill_max_;
68 }
69 }
70
71 if (strategy_ == "first" || strategy_ == "equal") {
72 fill_mass = std::min(qty, fill_mass);
73 num_at_fill_mass = static_cast<int>(std::floor(qty / fill_mass));
74 ExceedsSplitLimits(num_at_fill_mass);
75 packages.assign(num_at_fill_mass, fill_mass);
76
77 qty -= num_at_fill_mass * fill_mass;
78 }
79
80 if (strategy_ == "uniform" || strategy_ == "normal") {
81 // only use random if a full package amount is available. if less than one
82 // full amount is available, below will fill a partial package (no random).
83 while (qty >= std::max(eps_rsrc(), fill_max_)) {
84 fill_mass = dist_->sample();
85 packages.push_back(fill_mass);
86 qty -= fill_mass;
87 }
88 }
89
90 if (qty >= std::max(eps_rsrc(), fill_min_)) {
91 // leftover material is enough to fill one more partial package.
92 packages.push_back(qty);
93 }
94
95 Package::ExceedsSplitLimits(packages.size());
96
97 return packages;
98}
99
100Package::Package(std::string name, double fill_min, double fill_max,
101 std::string strategy)
102 : name_(name),
103 fill_min_(fill_min),
104 fill_max_(fill_max),
105 strategy_(strategy) {
106 if (name == unpackaged_name_) {
107 if (unpackaged_) {
108 throw ValueError("can't create a new package with name 'unpackaged'");
109 }
110 }
111 if (!IsValidStrategy(strategy_)) {
112 throw ValueError("Invalid strategy for package: " + strategy_);
113 }
115}
116
117TransportUnit::Ptr TransportUnit::unrestricted_ = NULL;
118
120 int fill_max, std::string strategy) {
121 if (fill_min < 0 || fill_max < 0) {
122 throw ValueError("fill_min and fill_max must be non-negative");
123 } else if (fill_min > fill_max) {
124 throw ValueError("fill_min must be less than or equal to fill_max");
125 }
126 Ptr t(new TransportUnit(name, fill_min, fill_max, strategy));
127 return t;
128}
129
130// singleton pattern:
131// if the static member is not yet set, create a new object
132// otherwise return the object that already exists
134 if (!unrestricted_) {
135 unrestricted_ = Ptr(new TransportUnit(unrestricted_name_));
136 }
137 return unrestricted_;
138}
139
141 if (qty < fill_min_) {
142 // less than one TransportUnit of material available
143 return 0;
144 }
145
146 if (strategy_ == "first") {
147 return fill_max_;
148 } else if (strategy_ == "equal" || strategy_ == "hybrid") {
149 // int division automatically rounds down. don't need floor in min, and
150 // get ceil by hand instead
151 int num_at_min_fill = qty / fill_min_;
152 int num_at_max_fill = (qty + fill_max_ - 1) / fill_max_;
153
154 if (num_at_min_fill >= num_at_max_fill) {
155 // all material *might* fit transport units. However, this is more
156 // challenging than packages because transport units are discrete.
157 double dbl_fill_mass = (double)qty / (double)num_at_max_fill;
158 return std::floor(dbl_fill_mass);
159 }
160 // some material will remain unrestricted, fill up as many transport
161 // units as possible. Or, perfect fill is possible but not with integer
162 // fill (see above).
163 }
164 return fill_max_;
165}
166
168 int TU_fill;
169 int shippable = 0;
170
171 if (pkgs == 0 || pkgs < fill_min_) {
172 return 0;
173
174 } else if (name_ == unrestricted_name_) {
175 return pkgs;
176
177 } else if (strategy_ == "first" || strategy_ == "equal") {
178 TU_fill = GetTransportUnitFill(pkgs);
179 if (TU_fill == 0) {
180 return 0;
181 }
182 shippable = std::min(pkgs, (pkgs / TU_fill) * TU_fill);
183 return shippable;
184
185 } else if (strategy_ == "hybrid") {
186 while ((pkgs > 0) && (pkgs >= fill_min_)) {
187 TU_fill = GetTransportUnitFill(pkgs);
188 shippable += TU_fill;
189 pkgs -= TU_fill;
190 }
191 return shippable;
192 }
193 return 0;
194}
195
196TransportUnit::TransportUnit(std::string name, int fill_min, int fill_max,
197 std::string strategy)
198 : name_(name),
199 fill_min_(fill_min),
200 fill_max_(fill_max),
201 strategy_(strategy) {
202 if (name == unrestricted_name_) {
203 if (unrestricted_) {
204 throw ValueError(
205 "can't create a new transport unit with name 'unrestricted'");
206 }
207 }
208 if (strategy != "first" && strategy != "equal" && strategy != "hybrid") {
209 throw ValueError("Invalid strategy for transport unit: " + strategy_);
210 }
211}
212
213} // namespace cyclus
boost::shared_ptr< NormalDoubleDist > Ptr
static void ExceedsSplitLimits(int pkgs, std::string ss_extra="")
Definition package.h:73
static Ptr Create(std::string name, double fill_min=0, double fill_max=std::numeric_limits< double >::max(), std::string strategy="first")
Definition package.cc:9
static Ptr & unpackaged()
Definition package.cc:23
boost::shared_ptr< Package > Ptr
Definition package.h:21
std::string name() const
Definition package.h:59
std::vector< double > GetFillMass(double qty)
Returns optimal fill mass for a resource to be packaged, and number of packages that can be crated at...
Definition package.cc:43
void SetDistribution()
Definition package.cc:31
double fill_min() const
Definition package.h:61
double fill_max() const
Definition package.h:63
std::string strategy() const
Definition package.h:65
bool IsValidStrategy(std::string strategy)
Definition package.h:95
std::string strategy() const
Definition package.h:155
int fill_max() const
Definition package.h:153
int fill_min() const
Definition package.h:151
int GetTransportUnitFill(int qty)
Returns number of packages for each transport unit.
Definition package.cc:140
boost::shared_ptr< TransportUnit > Ptr
Definition package.h:131
int MaxShippablePackages(int pkgs)
Returns the max number of transport units that can be shipped from the available quantity.
Definition package.cc:167
static Ptr Create(std::string name, int fill_min=0, int fill_max=std::numeric_limits< int >::max(), std::string strategy="first")
create a new transport unit type.
Definition package.cc:119
static Ptr & unrestricted()
Definition package.cc:133
std::string name() const
Definition package.h:149
boost::shared_ptr< UniformDoubleDist > Ptr
For values that are too big, too small, etc.
Definition error.h:37
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