Skip to content

Commit

Permalink
initial scaffolding for transport units
Browse files Browse the repository at this point in the history
  • Loading branch information
nuclearkatie committed May 30, 2024
1 parent eaa0cd1 commit 0f6743b
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 1 deletion.
36 changes: 35 additions & 1 deletion src/context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,40 @@ Package::Ptr Context::GetPackage(std::string name) {
return packages_[name];
}

Package::Ptr Context::GetPackageById(int id) {
if (id == Package::unpackaged_id()) {
return Package::unpackaged();
}
if (id < 0) {
throw ValueError("Invalid package id " + std::to_string(id));
}
// iterate through the list of packages to get the one package with the correct id
std::map<std::string, Package::Ptr>::iterator it;
for (it = packages_.begin(); it != packages_.end(); ++it) {
if (it->second->id() == id) {
return it->second;
}
}
throw ValueError("Invalid package id " + std::to_string(id));
}

void AddTransportUnit(std::string name, int fill_min, int fill_max,
std::string strategy) {
transport_units_[name] = TransportUnit::Create(name, fill_min, fill_max, strategy);
NewDatum("TransportUnit")
->AddVal("TransportUnit", name)
->AddVal("FillMin", fill_min)
->AddVal("FillMax", fill_max)
->AddVal("Strategy", strategy)
->AddVal("Id", transport_units_[name]->id())
->Record();
}

/// Retrieve a registered transport unit
TransportUnit::Ptr GetTransportUnitByName(std::string name);

TransportUnit::Ptr GetTransportUnitById(int id);

void Context::InitSim(SimInfo si) {
NewDatum("Info")
->AddVal("Handle", si.handle)
Expand Down Expand Up @@ -277,7 +311,7 @@ void Context::InitSim(SimInfo si) {
int Context::time() {
return ti_->time();
}

LoadPacka
int Context::random() {
return rng_->random();
}
Expand Down
1 change: 1 addition & 0 deletions src/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,7 @@ class Context {
std::map<std::string, Agent*> protos_;
std::map<std::string, Composition::Ptr> recipes_;
std::map<std::string, Package::Ptr> packages_;
std::map<std::string, TransportUnit::Ptr> transport_units_;
std::set<Agent*> agent_list_;
std::set<Trader*> traders_;
std::map<std::string, int> n_prototypes_;
Expand Down
61 changes: 61 additions & 0 deletions src/package.cc
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,65 @@ Package::Package(std::string name, double fill_min, double fill_max,
}
}

// unrestricted id is 1, so start the user-declared transport id at 2
int TransportUnit::next_package_id_ = 2;
TransportUnit::Ptr TransportUnit::unrestricted_ = NULL;

TransportUnit::Ptr TransportUnit::Create(std::string name, int fill_min, int fill_max, std::string strategy) {
if (fill_min < 0 || fill_max < 0) {
throw ValueError("fill_min and fill_max must be non-negative");
}
else if (fill_min > fill_max) {
throw ValueError("fill_min must be less than or equal to fill_max");
}
Ptr p(new TransportUnit(name, fill_min, fill_max, strategy));
return p;
}

// singleton pattern:
// if the static member is not yet set, create a new object
// otherwise return the object that already exists
TransportUnit::Ptr& TransportUnit::unrestricted() {

if (!unrestricted) {
unrestricted_ = Ptr(new TransportUnit(unrestricted_name_));
}
return unrestricted_;
}

int TransportUnit::GetFillMass(double qty) {
if (qty < fill_min_) {
// less than one pkg of material available
return 0;
}

int fill_mass;
if (strategy_ == "first") {
fill_mass = fill_max_;
} else if (strategy_ == "equal") {
int num_min_fill = std::floor(qty / fill_min_);
int num_max_fill = std::ceil(qty / fill_max_);
if (num_min_fill >= num_max_fill) {
// all material can fit in a package
int fill_mass = qty / num_max_fill;
} else {
// some material will remain unrestricted, fill up as many max packages as possible
fill_mass = fill_max_;
}
}
return fill_mass;
}

TransportUnit::TransportUnit(std::string name, int fill_min, int fill_max, std::string strategy) :
name_(name), fill_min_(fill_min), fill_max_(fill_max), strategy_(strategy) {
if (name == unrestricted_name_) {
if (unrestricted_) {
throw ValueError("can't create a new transport unit with name 'unrestricted'");
}
id_ = unrestricted_id_;
} else {
id_ = next_transport_unit_id_++;
}
}

} // namespace cyclus
66 changes: 66 additions & 0 deletions src/package.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,72 @@ class Package {
std::string strategy_;
};

class TransportUnit {
public:
typedef boost::shared_ptr<TransportUnit> Ptr;

// create a new package type. Should be called by the context only
// (see Context::AddPackage), unless you want an untracked package
// type (which you probably don't)
static Ptr Create(std::string name, int fill_min = 0,
int fill_max = std::numeric_limits<int>::max(),
std::string strategy = "first");

/// Returns optimal fill mass for a resource to be packaged. Can be used
/// to determine how to respond to requests for material, and to actually
/// package and send off trades.
/// Packaging strategy "first" simply fills the packages one by one to the
/// maximum fill. Therefore, it should always try to max fill.
/// Packaging strategy "equal" tries to fill all packages to the same mass.
/// This tries to find the optimal number and fill mass of packages given
/// the packaging limitations. It does this by calculating bounding fills,
/// floor(quantity/fill_min) and ceiling(quantity/fill_max).
/// There might be a scenario where there is no solution, i.e. an integer
/// number of packages cannot be filled with no remainder. In this case,
/// the most effective fill strategy is to fill to the max. Numeric example:
/// quantity = 5, fill_min = 3, fill_max = 4. num_min_fill = floor(5/3) = 1,
/// num_max_fill = ceil(5/4) = 2. num_min_fill < num_max_fill, so fill to
/// the max.
int GetShippableTransportUnits(int qty);

// returns package id
int id() const { return id_; }
// returns package name
std::string name() const { return name_; }
// returns package fill min
int fill_min() const { return fill_min_; }
// returns package fill max
int fill_max() const { return fill_max_; }
// returns package strategy
std::string strategy() const { return strategy_; }

// returns the unrestricted id (1)
static int unrestricted_id() { return unrestricted_id_; }

// returns the unrestricted transport unit name
static std::string unrestricted_name() { return unrestricted_name_; }

// returns the unrestricted singleton object
static Ptr& unrestricted();

private:
Package(std::string name,
int fill_min = 0,
int fill_max = std::numeric_limits<int>::max(),
std::string strategy = "first");

static const int unrestricted_id_ = 1;
static constexpr char unrestricted_name_[11] = "unrestricted";
static Ptr unrestricted_;
static int next_tranport_unit_id_;

std::string name_;
int id_;
int fill_min_;
int fill_max_;
std::string strategy_;
};

} // namespace cyclus

#endif // CYCLUS_SRC_PACKAGE_H_
19 changes: 19 additions & 0 deletions src/xml_file_loader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ void XMLFileLoader::LoadSim() {
LoadSolver();
LoadRecipes();
LoadPackages();
LoadTransportUnits();
LoadSpecs();
LoadInitialAgents(); // must be last
SimInit::Snapshot(ctx_);
Expand Down Expand Up @@ -348,6 +349,24 @@ void XMLFileLoader::LoadPackages() {
}
}

void XMLFileLoader::LoadTransportUnits() {
InfileTree xqe(*parser_);

std::string query = "/*/transportunit";
int num_transport_units = xqe.NMatches(query);
for (int i = 0; i < num_transport_units; i++) {
InfileTree* qe = xqe.SubTree(query, i);
std::string name = cyclus::OptionalQuery<std::string>(qe, "name", "default");
CLOG(LEV_DEBUG3) << "loading transport unit: " << name;

double fill_min = cyclus::OptionalQuery<double>(qe, "fill_min", eps());
double fill_max = cyclus::OptionalQuery<double>(qe, "fill_max", std::numeric_limits<double>::max());

std::string strategy = cyclus::OptionalQuery<std::string>(qe, "strategy", "first");

ctx_->AddTransportUnit(name, fill_min, fill_max, strategy);
}

void XMLFileLoader::LoadSpecs() {
std::vector<AgentSpec> specs = ParseSpecs(file_, format_);
for (int i = 0; i < specs.size(); ++i) {
Expand Down
3 changes: 3 additions & 0 deletions src/xml_file_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ class XMLFileLoader {
/// Loads packages
void LoadPackages();

/// Loads Transport Units
void LoadTransportUnits();

/// Creates all initial agent instances from the input file.
virtual void LoadInitialAgents();

Expand Down

0 comments on commit 0f6743b

Please sign in to comment.