diff --git a/artis-factory.layout b/artis-factory.layout
index 570d6d1..576ad0c 100644
--- a/artis-factory.layout
+++ b/artis-factory.layout
@@ -2,14 +2,29 @@
-
+
-
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
@@ -24,7 +39,7 @@
-
+
@@ -32,19 +47,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/FactoryGraphManager.hpp b/src/FactoryGraphManager.hpp
index 0551528..bfd915c 100644
--- a/src/FactoryGraphManager.hpp
+++ b/src/FactoryGraphManager.hpp
@@ -28,24 +28,22 @@
#define ARTIS_FACTORY_FACTORY_GRAPH_MANAGER_HPP
#include "Base.hpp"
+#include "FactoryGraphManagerParameters.hpp"
+#include "ItemStock.hpp"
#include "JsonReader.hpp"
#include "PoolRouter.hpp"
#include "Router.hpp"
-#include "Sink.hpp"
+#include "Stock.hpp"
#include
namespace artis::factory {
-struct FactoryGraphManagerParameters {
- Factory factory;
-};
-
class FactoryGraphManager
: public artis::pdevs::GraphManager {
public:
enum sub_models {
- GENERATOR, ROUTER, POOL_ROUTER, MACHINE = 10000
+ GENERATOR, ROUTER, POOL_ROUTER, MACHINE = 10000, ITEM_STOCK = 20000, STOCK = 30000
};
FactoryGraphManager(Coordinator *coordinator, const artis::common::NoParameters ¶meters,
@@ -53,27 +51,13 @@ public:
artis::pdevs::GraphManager(
coordinator, parameters, graph_parameters) {
unsigned int machine_index = 0;
- std::map programs;
- for (const auto &product: graph_parameters.factory._products) {
- unsigned int product_id = product.first;
- Program program;
-
- for (const auto &pool_job: product.second._pool_jobs) {
- std::vector machines;
-
- for (const auto &machine_job: pool_job._machine_jobs) {
- machines.push_back(machine_job._machine_id);
- }
- program.emplace_back((uint8_t) pool_job._pool_id, machines);
- }
- programs[product_id] = program;
- }
-
- ProductionOrderGeneratorParameters generator_parameters{programs,
+ ProductionOrderGeneratorParameters generator_parameters{graph_parameters.get_programs(),
graph_parameters.factory._generator._random_seed,
graph_parameters.factory._generator._min_send_speed_rate,
- graph_parameters.factory._generator._max_send_speed_rate};
+ graph_parameters.factory._generator._max_send_speed_rate,
+ graph_parameters.factory._generator._po_number,
+ graph_parameters.factory._generator._po_order};
_generator = new GeneratorSimulator("G", generator_parameters);
_router = new RouterSimulator("R", {graph_parameters.factory._pools.size()});
@@ -81,45 +65,131 @@ public:
this->add_child(ROUTER, _router);
this->add_child(GENERATOR, _generator);
+ // item stocks
+ for (const auto &p: graph_parameters.factory._stocks) {
+ _item_stocks.push_back(
+ new ItemStockSimulator("I_S_" + std::to_string(p._id),
+ ItemStockParameters{graph_parameters.get_item_stock(p._id),
+ graph_parameters.get_machines_to_item_stock(p._id)}));
+ this->add_child(ITEM_STOCK + p._id, _item_stocks.back());
+ }
+
+ // intermediate stocks
for (const auto &p: graph_parameters.factory._pools) {
+ unsigned int pool_id = std::get<0>(p);
+ for (const auto &s: std::get<3>(p)) {
+ _stocks[std::make_pair(pool_id, s._id)] = new StockSimulator(
+ "S_" + std::to_string(pool_id) + "_" + std::to_string(s._id),
+ StockParameters{graph_parameters.get_machines_to_in_stock(pool_id, s._id),
+ graph_parameters.get_machines_to_out_stock(pool_id, s._id),
+ s._capacity});
+ this->add_child(STOCK + pool_id * 100 + s._id, _stocks[std::make_pair(pool_id, s._id)]);
+ }
+ }
+
+ // pool + machines
+ for (const auto &p: graph_parameters.factory._pools) {
+ unsigned int pool_id = std::get<0>(p);
+ std::map capacities;
+
+ for (const auto &m: std::get<2>(p)) {
+ capacities[m->machine_id] = m->capacity;
+ }
_pool_routers.push_back(
- new PoolRouterSimulator("P_R_" + std::to_string(std::get<0>(p)),
- PoolRouterParameters{std::get<1>(p), std::get<2>(p).size()}));
+ new PoolRouterSimulator("P_R_" + std::to_string(pool_id), PoolRouterParameters{std::get<1>(p), capacities}));
this->add_child(POOL_ROUTER + std::get<0>(p), _pool_routers.back());
- out({_router, artis::factory::Router::outputs::OUT_P + std::get<0>(p)})
+ out({_router, artis::factory::Router::outputs::OUT_P + pool_id})
>> in({_pool_routers.back(), artis::factory::PoolRouter::inputs::IN});
out({_pool_routers.back(), artis::factory::PoolRouter::outputs::OUT})
- >> in({_router, artis::factory::Router::inputs::IN_P + std::get<0>(p)});
+ >> in({_router, artis::factory::Router::inputs::IN_P + pool_id});
+
+ // machines
for (const auto &m: std::get<2>(p)) {
switch (m->machine_type) {
case PROCESSOR: {
+ auto &processor_parameters = (ProcessorParameters &) (*m);
auto new_processor = new ProcessorSimulator(
- "M_" + std::to_string(m->pool_id) + "_" + std::to_string(m->machine_id), (ProcessorParameters &) (*m));
+ "M_" + std::to_string(m->pool_id) + "_" + std::to_string(m->machine_id), processor_parameters);
_processors.push_back(new_processor);
this->add_child(MACHINE + machine_index, new_processor);
+
+ // connection processor <-> pool router
out({_pool_routers.back(), artis::factory::PoolRouter::outputs::OUT_M + m->machine_id})
>> in({new_processor, artis::factory::Processor::inputs::IN});
out({new_processor, artis::factory::Processor::outputs::OUT})
>> in({_pool_routers.back(), artis::factory::PoolRouter::inputs::IN_M + m->machine_id});
+
+ // connection processor <-> item stock
+ std::vector item_stocks;
+
+ for (const auto &q: processor_parameters.in_out) {
+ for (const auto &r: q.second._ins) {
+ if (r._source._pool_id == -1) {
+ item_stocks.push_back(r._source._stock_id);
+ }
+ }
+ }
+ for (const auto &q: item_stocks) {
+ out({new_processor, artis::factory::Processor::outputs::OUT_ITEM_DEMAND + q})
+ >> in({_item_stocks.back(), artis::factory::ItemStock::inputs::IN + m->machine_id});
+ out({_item_stocks.back(), artis::factory::ItemStock::outputs::OUT + m->machine_id})
+ >> in({new_processor, artis::factory::Processor::inputs::IN_ITEM});
+ }
+ // connection processor <-> intermediate stock
+ std::vector> stocks;
+
+ for (const auto &q: processor_parameters.in_out) {
+ for (const auto &r: q.second._outs) {
+ auto u = std::make_pair((unsigned int) r._destination._pool_id, r._destination._stock_id);
+
+ if (r._destination._pool_id != -1 and std::find(stocks.cbegin(), stocks.cend(), u) == stocks.cend()) {
+ stocks.push_back(u);
+ }
+ }
+ }
+ for (const auto &q: stocks) {
+ out({new_processor, artis::factory::Processor::outputs::OUT_STOCK + (q.first * 100 + q.second)})
+ >> in({_stocks[q], artis::factory::Stock::inputs::IN});
+ out({new_processor, artis::factory::Processor::outputs::OUT_STOCK_AVAILABLE + (q.first * 100 + q.second)})
+ >> in({_stocks[q], artis::factory::Stock::inputs::IN_STOCK_AVAILABLE + m->machine_id});
+ out({_stocks[q], artis::factory::Stock::outputs::OUT_STOCK_AVAILABLE + m->machine_id})
+ >> in(
+ {new_processor, artis::factory::Processor::inputs::IN_STOCK_AVAILABLE + (q.first * 100 + q.second)});
+ }
+ stocks.clear();
+ for (const auto &q: processor_parameters.in_out) {
+ for (const auto &r: q.second._ins) {
+ auto u = std::make_pair((unsigned int) r._source._pool_id, r._source._stock_id);
+
+ if (r._source._pool_id != -1 and std::find(stocks.cbegin(), stocks.cend(), u) == stocks.cend()) {
+ stocks.push_back(u);
+ }
+ }
+ }
+ for (const auto &q: stocks) {
+ out({new_processor, artis::factory::Processor::outputs::OUT_STOCK_DEMAND + (q.first * 100 + q.second)})
+ >> in({_stocks[q], artis::factory::Stock::inputs::IN_DEMAND + m->machine_id});
+ out({_stocks[q], artis::factory::Stock::outputs::OUT + m->machine_id})
+ >> in({new_processor, artis::factory::Processor::inputs::IN_STOCK});
+ }
++machine_index;
break;
}
case SINK: {
- auto new_sink = new SinkSimulator(
- "M_" + std::to_string(m->pool_id) + "_" + std::to_string(m->machine_id),
- SinkParameters{}
- );
+ auto new_sink = new SinkSimulator(
+ "M_" + std::to_string(m->pool_id) + "_" + std::to_string(m->machine_id), (SinkParameters &) (*m));
- _sinks.push_back(new_sink);
- this->add_child(MACHINE + machine_index, new_sink);
+ _sinks.push_back(new_sink);
+ this->add_child(MACHINE + machine_index, new_sink);
- // PoolRouter -> Sink
- out({_pool_routers.back(), artis::factory::PoolRouter::outputs::OUT_M + m->machine_id})
- >> in({_sinks.back(), artis::factory::Sink::inputs::IN});
-
- ++machine_index;
- break;
+ // connection sink <-> pool router
+ out({_pool_routers.back(), artis::factory::PoolRouter::outputs::OUT_M + m->machine_id})
+ >> in({new_sink, artis::factory::Sink::inputs::IN});
+ out({new_sink, artis::factory::Sink::outputs::OUT})
+ >> in({_pool_routers.back(), artis::factory::PoolRouter::inputs::FINISH});
+ ++machine_index;
+ break;
}
case SEPARATOR: {
// TODO
@@ -129,11 +199,12 @@ public:
// TODO
break;
}
- case CONVEYOR :{
+ case CONVEYOR : {
// TODO
break;
}
- default: {}
+ default: {
+ }
}
}
}
@@ -147,12 +218,16 @@ private:
typedef artis::pdevs::Simulator PoolRouterSimulator;
typedef artis::pdevs::Simulator ProcessorSimulator;
typedef artis::pdevs::Simulator SinkSimulator;
+ typedef artis::pdevs::Simulator ItemStockSimulator;
+ typedef artis::pdevs::Simulator StockSimulator;
GeneratorSimulator *_generator;
RouterSimulator *_router;
std::vector _pool_routers;
std::vector _processors;
std::vector _sinks;
+ std::vector _item_stocks;
+ std::map, StockSimulator *> _stocks;
};
}
diff --git a/src/FactoryGraphManagerParameters.hpp b/src/FactoryGraphManagerParameters.hpp
new file mode 100644
index 0000000..691cdec
--- /dev/null
+++ b/src/FactoryGraphManagerParameters.hpp
@@ -0,0 +1,128 @@
+/**
+ * @file FactoryGraphManagerParameters.hpp
+ * @author The ARTIS Development Team
+ * See the AUTHORS or Authors.txt file
+ */
+
+/*
+ * ARTIS - the multimodeling and simulation environment
+ * This file is a part of the ARTIS environment
+ *
+ * Copyright (C) 2013-2023 ULCO http://www.univ-littoral.fr
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef ARTIS_FACTORY_FACTORY_GRAPH_MANAGER_PARAMETERS_HPP
+#define ARTIS_FACTORY_FACTORY_GRAPH_MANAGER_PARAMETERS_HPP
+
+#include "JsonReader.hpp"
+
+namespace artis::factory {
+
+struct FactoryGraphManagerParameters {
+ Factory factory;
+
+ std::map get_item_stock(unsigned int id) const {
+ std::map items;
+
+ auto it = std::find_if(factory._stocks.cbegin(), factory._stocks.cend(),
+ [id](const auto &e) { return e._id == id; });
+ if (it != factory._stocks.cend()) {
+ for (const auto &e: it->_items) {
+ items[e._id] = e._quantity;
+ }
+ }
+ return items;
+ }
+
+ std::vector get_machines_to_item_stock(unsigned int id) const {
+ std::vector machines;
+
+ for (const auto &p: factory._products) {
+ for (const auto &q: p.second._pool_jobs) {
+ for (const auto &r: q._machine_jobs) {
+ for (const auto &s: r._ins) {
+ if (s._source._stock_id == id and
+ std::find(machines.cbegin(), machines.cend(), r._machine_id) == machines.cend()) {
+ machines.push_back(r._machine_id);
+ }
+ }
+ }
+ }
+ }
+ return machines;
+ }
+
+ std::vector get_machines_to_in_stock(unsigned int pool_id, unsigned int stock_id) const {
+ std::vector machines;
+
+ for (const auto &p: factory._products) {
+ for (const auto &q: p.second._pool_jobs) {
+ for (const auto &r: q._machine_jobs) {
+ for (const auto &s: r._ins) {
+ if (s._source._pool_id == (int) pool_id and s._source._stock_id == stock_id and
+ std::find(machines.cbegin(), machines.cend(), r._machine_id) == machines.cend()) {
+ machines.push_back(r._machine_id);
+ }
+ }
+ }
+ }
+ }
+ return machines;
+ }
+
+ std::vector get_machines_to_out_stock(unsigned int pool_id, unsigned int stock_id) const {
+ std::vector machines;
+
+ for (const auto &p: factory._products) {
+ for (const auto &q: p.second._pool_jobs) {
+ for (const auto &r: q._machine_jobs) {
+ for (const auto &s: r._outs) {
+ if (s._destination._pool_id == (int) pool_id and s._destination._stock_id == stock_id and
+ std::find(machines.cbegin(), machines.cend(), r._machine_id) == machines.cend()) {
+ machines.push_back(r._machine_id);
+ }
+ }
+ }
+ }
+ }
+ return machines;
+ }
+
+ std::map get_programs() const {
+ std::map programs;
+
+ for (const auto &product: factory._products) {
+ unsigned int product_id = product.first;
+ Program program;
+
+ for (const auto &pool_job: product.second._pool_jobs) {
+ std::vector machines;
+
+ for (const auto &machine_job: pool_job._machine_jobs) {
+ machines.push_back(machine_job._machine_id);
+ }
+ program.emplace_back((uint8_t) pool_job._pool_id, machines);
+ }
+ programs[product_id] = program;
+ }
+ return programs;
+ }
+
+};
+
+}
+
+#endif //ARTIS_FACTORY_FACTORY_GRAPH_MANAGER_PARAMETERS_HPP
diff --git a/src/Item.hpp b/src/Item.hpp
index bfaaad3..7973995 100644
--- a/src/Item.hpp
+++ b/src/Item.hpp
@@ -1,5 +1,5 @@
/**
- * @file Item.hpp
+* @file Item.hpp
* @author The ARTIS Development Team
* See the AUTHORS or Authors.txt file
*/
@@ -29,13 +29,13 @@
namespace artis::factory {
-struct BaseItem {
- unsigned int _id;
-};
+ struct BaseItem {
+ unsigned int _id;
+ };
-struct Item {
- unsigned int _po_id;
-};
+ struct Item {
+ unsigned int _po_id;
+ };
}
diff --git a/src/ItemStock.cpp b/src/ItemStock.cpp
index 79cb840..555285c 100644
--- a/src/ItemStock.cpp
+++ b/src/ItemStock.cpp
@@ -29,28 +29,58 @@
namespace artis::factory {
void ItemStock::dint(const Time & /* t */) {
- // TODO
+ switch (_phase) {
+ case Phase::SEND: {
+ _demands.clear();
+ _phase = Phase::WAIT;
+ break;
+ }
+ case Phase::WAIT: {
+ assert(false);
+ }
+ }
}
void ItemStock::dext(const Time & /* t */, const Time & /* e */, const Bag &bag) {
- std::for_each(bag.begin(), bag.end(), [](const ExternalEvent & /* event */) {
- // TODO
+ std::for_each(bag.begin(), bag.end(), [this](const ExternalEvent &event) {
+ ItemDemand demand;
+
+ event.data()(demand);
+ if (_items[demand.item_id] == -1 or _items[demand.item_id] >= (int) demand.quantity) {
+ _demands.push_back(std::make_pair(event.port_index() - inputs::IN, demand));
+ if (_items[demand.item_id] != -1) {
+ _items[demand.item_id] -= (int) demand.quantity;
+ }
+ _phase = Phase::SEND;
+ } else {
+ _unsatisfied_demands.push_back(std::make_pair(event.port_index() - inputs::IN, demand));
+ }
});
}
void ItemStock::start(const Time & /* t */) {
- // TODO
+ _phase = Phase::WAIT;
+ _items = _parameters._items;
}
Time ItemStock::ta(const Time & /* t */) const {
- // TODO
+ switch (_phase) {
+ case Phase::WAIT:
+ return artis::common::DoubleTime::infinity;
+ case Phase::SEND:
+ return 0;
+ }
return artis::common::DoubleTime::infinity;
}
Bag ItemStock::lambda(const Time & /* t */) const {
Bag bag;
- // TODO
+ if (_phase == Phase::SEND) {
+ for (const auto &e: _demands) {
+ bag.push_back(ExternalEvent(outputs::OUT + e.first, ItemResponse(e.second.item_id, e.second.po_id)));
+ }
+ }
return bag;
}
diff --git a/src/ItemStock.hpp b/src/ItemStock.hpp
index 58f280e..918e48b 100644
--- a/src/ItemStock.hpp
+++ b/src/ItemStock.hpp
@@ -32,7 +32,42 @@
namespace artis::factory {
+struct ItemDemand {
+ int item_id;
+ int po_id;
+ unsigned int quantity;
+
+ ItemDemand(int item_id = -1, int po_id = -1, unsigned int quantity = 0) : item_id(item_id), po_id(po_id),
+ quantity(quantity) {}
+
+ bool operator==(const ItemDemand &other) const {
+ return item_id == other.item_id and po_id == other.po_id and quantity == other.quantity;
+ }
+
+ std::string to_string() const {
+ return "Demand < " + std::to_string(item_id) + " | " + std::to_string(po_id) + " | " + std::to_string(quantity) +
+ " >";
+ }
+};
+
+struct ItemResponse {
+ int item_id;
+ int po_id;
+
+ ItemResponse(int item_id = -1, int po_id = -1) : item_id(item_id), po_id(po_id) {}
+
+ bool operator==(const ItemResponse &other) const {
+ return item_id == other.item_id and po_id == other.po_id;
+ }
+
+ std::string to_string() const {
+ return "Response < " + std::to_string(item_id) + " | " + std::to_string(po_id) + " >";
+ }
+};
+
struct ItemStockParameters {
+ std::map _items;
+ std::vector _machines;
};
class ItemStock : public Dynamics {
@@ -55,9 +90,11 @@ public:
};
ItemStock(const std::string &name, const Context &context)
- : Dynamics(name, context) {
- input_port({inputs::IN, "in"});
- output_port({outputs::OUT, "out"});
+ : Dynamics(name, context), _parameters(context.parameters()) {
+ for (const auto &m: _parameters._machines) {
+ input_port({inputs::IN + m, "in_" + std::to_string(m)});
+ output_port({outputs::OUT + m, "out_" + std::to_string(m)});
+ }
}
~ItemStock() override = default;
@@ -75,7 +112,29 @@ public:
artis::common::event::Value observe(const Time &t, unsigned int index) const override;
private:
- // TODO (state)
+ struct Phase {
+ enum values {
+ WAIT,
+ SEND
+ };
+
+ static std::string to_string(const values &value) {
+ switch (value) {
+ case WAIT:
+ return "WAIT";
+ case SEND:
+ return "SEND";
+ }
+ return "";
+ }
+ };
+
+ ItemStockParameters _parameters;
+
+ Phase::values _phase;
+ std::map _items;
+ std::vector> _demands;
+ std::vector> _unsatisfied_demands;
};
} // namespace artis::factory
diff --git a/src/JsonReader.hpp b/src/JsonReader.hpp
index 0889edb..2d02537 100644
--- a/src/JsonReader.hpp
+++ b/src/JsonReader.hpp
@@ -39,27 +39,11 @@
namespace artis::factory {
-struct Location {
- int _pool_id;
- unsigned int _stock_id;
-};
-
-struct In {
- int _id; // -1 if global
- Location _source;
- unsigned int _quantity;
-};
-
-struct Out {
- int _id; // -1 if global
- Location _destination;
- unsigned int _quantity;
-};
-
struct MachineJob {
unsigned int _machine_id;
std::vector _ins;
std::vector _outs;
+ std::shared_ptr _durations;
};
struct PoolJob {
@@ -69,16 +53,20 @@ struct PoolJob {
struct Product {
unsigned int _id;
+ std::vector> _components;
std::vector _pool_jobs;
+ bool final;
};
struct Generator {
uint _random_seed;
uint _min_send_speed_rate;
uint _max_send_speed_rate;
+ int _po_number;
+ std::vector _po_order;
};
-struct Stock {
+struct IntermediateStock {
unsigned int _id;
int _capacity; // if -1 then infinity
};
@@ -88,16 +76,16 @@ struct Item {
int _quantity; // if -1 then infinity
};
-struct ItemStock {
+struct GlobalStock {
unsigned int _id;
std::vector- _items;
};
struct Factory {
Generator _generator;
- std::vector>, std::vector >> _pools;
+ std::vector>, std::vector >> _pools;
std::map _products;
- std::vector _stocks;
+ std::vector _stocks;
};
class JsonReader {
@@ -114,6 +102,7 @@ public:
parse_products(data["products"]);
parse_generator(data["generator"]);
parse_pools(data["pools"]);
+ parse_product_job_durations(data["products"]);
if (data.contains("stocks")) {
parse_item_stocks(data["stocks"]);
}
@@ -123,7 +112,8 @@ private:
void parse_generator(const nlohmann::json &data) {
_factory._generator = Generator{data["random_seed"].get(),
data["min_send_speed_rate"].get(),
- data["max_send_speed_rate"].get()};
+ data["max_send_speed_rate"].get(),
+ -1, {}};
}
std::vector parse_ins(const nlohmann::json &data) {
@@ -144,8 +134,22 @@ private:
std::vector> machines;
for (const nlohmann::json &machine: data) {
+ unsigned int machine_id = machine["id"].get();
unsigned int machine_type = machine["type"].get();
+ unsigned int capacity = machine.contains("capacity") ? machine["capacity"].get() : 1;
+ std::map in_out;
+ for (const auto &product: _factory._products) {
+ for (const auto &pool_job: product.second._pool_jobs) {
+ if (pool_job._pool_id == pool_id) {
+ for (const auto &machine_job: pool_job._machine_jobs) {
+ if (machine_job._machine_id == machine_id) {
+ in_out[product.first] = InOut{machine_job._ins, machine_job._outs};
+ }
+ }
+ }
+ }
+ }
switch (machine_type) {
case PROCESSOR: {
unsigned int load_time = machine.contains("load_time") ? machine["load_time"].get() : 0;
@@ -154,32 +158,32 @@ private:
unsigned int unload_time = machine.contains("unload_time") ? machine["unload_time"].get() : 0;
machines.push_back(
- std::make_shared(ProcessorParameters{{machine["id"].get(), machine_type,
- pool_id}, load_time, processing_time,
- unload_time}));
+ std::make_shared(ProcessorParameters{{machine_id, machine_type, pool_id, capacity},
+ ProcessorDurations{{}, load_time, processing_time,
+ unload_time}, in_out, {}}));
break;
}
case SINK: {
- machines.push_back(std::make_shared(
- SinkParameters{{machine["id"].get(), machine_type, pool_id}}));
+ machines.push_back(
+ std::make_shared(SinkParameters{{machine_id, machine_type, pool_id, capacity}}));
break;
}
case SEPARATOR: {
// TODO
- machines.push_back(std::make_shared(
- SeparatorParameters{{machine["id"].get(), machine_type, pool_id}}));
+ machines.push_back(
+ std::make_shared(SeparatorParameters{{machine_id, machine_type, pool_id, capacity}}));
break;
}
case COMBINER : {
// TODO
- machines.push_back(std::make_shared(
- CombinerParameters{{machine["id"].get(), machine_type, pool_id}}));
+ machines.push_back(
+ std::make_shared(CombinerParameters{{machine_id, machine_type, pool_id, capacity}}));
break;
}
case CONVEYOR : {
// TODO
- machines.push_back(std::make_shared(
- ConveyorParameters{{machine["id"].get(), machine_type, pool_id}}));
+ machines.push_back(
+ std::make_shared(ConveyorParameters{{machine_id, machine_type, pool_id, capacity}}));
break;
}
default: {
@@ -207,7 +211,7 @@ private:
for (const nlohmann::json &pool: data) {
unsigned int pool_id = pool["id"].get();
unsigned int pool_type = pool["type"].get();
- std::vector stocks;
+ std::vector stocks;
if (pool.contains("stocks")) {
for (const nlohmann::json &stock: pool["stocks"]) {
@@ -224,8 +228,54 @@ private:
void parse_products(const nlohmann::json &data) {
for (const nlohmann::json &product: data) {
unsigned int product_id = product["id"].get();
+ bool final = product.contains("final") ? product["final"].get() : true;
+ std::vector> components;
- _factory._products[product_id] = Product{product_id, parse_program(product["program"])};
+ if (product.contains("components")) {
+ for (const nlohmann::json &component: product["components"]) {
+ components.emplace_back(component["id"].get(), component["number"].get());
+ }
+ }
+ _factory._products[product_id] = Product{product_id, components, parse_program(product["program"]), final};
+ }
+ }
+
+ void parse_product_job_durations(const nlohmann::json &data) {
+ for (const nlohmann::json &product: data) {
+ unsigned int product_id = product["id"].get();
+ unsigned int pool_index = 0;
+
+ for (const nlohmann::json &pool_machine: product["program"]) {
+ unsigned int pool_id = pool_machine["poolID"].get();
+ const auto &pool = *std::find_if(_factory._pools.cbegin(), _factory._pools.cend(),
+ [pool_id](const auto &e) { return std::get<0>(e) == pool_id; });
+ const auto &machines = std::get<2>(pool);
+ unsigned int sequence_index = 0;
+
+ for (const nlohmann::json &machine: pool_machine["sequence"]) {
+ if (machine.is_object()) {
+ unsigned int machine_id = machine["machineID"].get();
+ const auto &m = *std::find_if(machines.cbegin(), machines.cend(),
+ [machine_id](const auto &e) { return e->machine_id == machine_id; });
+
+ if (m->machine_type == PROCESSOR) {
+ auto &M = (ProcessorParameters &) (*m);
+ auto d = std::make_shared(
+ ProcessorDurations{{},
+ machine.contains("load_time") ? machine["load_time"].get() : 0,
+ machine.contains("processing_time")
+ ? machine["processing_time"].get() : 0,
+ machine.contains("unload_time") ? machine["unload_time"].get() : 0
+ });
+
+ _factory._products[product_id]._pool_jobs[pool_index]._machine_jobs[sequence_index]._durations = d;
+ M.product_durations[product_id] = d;
+ }
+ }
+ ++sequence_index;
+ }
+ ++pool_index;
+ }
}
}
@@ -254,9 +304,9 @@ private:
if (machine.contains("outs")) {
outs = parse_outs(machine["outs"]);
}
- sequence.push_back(MachineJob{machine["machineID"].get(), ins, outs});
+ sequence.push_back(MachineJob{machine["machineID"].get(), ins, outs, {}});
} else {
- sequence.push_back(MachineJob{machine.get(), {}, {}});
+ sequence.push_back(MachineJob{machine.get(), {}, {}, {}});
}
}
return sequence;
diff --git a/src/Machine.hpp b/src/Machine.hpp
index 7dc9f99..3d3e6f3 100644
--- a/src/Machine.hpp
+++ b/src/Machine.hpp
@@ -1,5 +1,5 @@
/**
- * @file Machine.hpp
+* @file Machine.hpp
* @author The ARTIS Development Team
* See the AUTHORS or Authors.txt file
*/
@@ -32,11 +32,15 @@
namespace artis::factory {
-struct MachineParameters {
- uint machine_id;
- uint machine_type;
- uint pool_id;
-};
+ struct MachineParameters {
+ uint machine_id;
+ uint machine_type;
+ uint pool_id;
+ uint capacity;
+ };
+
+ struct Durations {
+ };
} // namespace artis::factory
diff --git a/src/PoolRouter.cpp b/src/PoolRouter.cpp
index 737585d..79fcb42 100644
--- a/src/PoolRouter.cpp
+++ b/src/PoolRouter.cpp
@@ -25,7 +25,6 @@
*/
#include "PoolRouter.hpp"
-#include "Sink.hpp"
namespace artis::factory {
@@ -43,25 +42,13 @@ void PoolRouter::dint(const Time & /* t */) {
assert(it != _pending_po.cend());
- if ((*it)->is_finish()) {
- _available_machines[(*it)->last_operation()->get_loc_index()] = true;
- } else if ((*it)->current_operation().get_type() == CHANGE_POOL_TYPE) {
- _available_machines[(*it)->previous_operation()->get_loc_index()] = true;
- } else {
- //_available_machines[(*it)->current_operation().get_loc_index()] = false;
- auto idx = (*it)->current_operation().get_loc_index();
-
- // Modifié pour gérer le Sink
- if (idx == _available_machines.size()-1) {// Par simplicité, je considère que la dernière machine connectée est le Sink
- _available_machines[idx] = true;// Et si idx est le dernier index, alors cette "machine" reste disponible
- } else {
- _available_machines[idx] = false;
- }
+ if (not (*it)->is_finish() and (*it)->current_operation().get_type() != CHANGE_POOL_TYPE) {
+ _available_machines[(*it)->current_operation().get_loc_index()]--;
}
_pending_po.erase(it);
if (std::find_if(_pending_po.cbegin(), _pending_po.cend(), [this](const auto &e) {
return e->is_finish() or e->current_operation().get_type() == CHANGE_POOL_TYPE or
- _available_machines[e->current_operation().get_loc_index()];
+ _available_machines[e->current_operation().get_loc_index()] > 0;
}) != _pending_po.cend()) {
_phase = Phase::SEND;
} else {
@@ -80,19 +67,24 @@ void PoolRouter::dext(const Time &t, const Time & /* e */, const Bag &bag) {
event.data()(data);
_pending_po.push_back(std::make_unique(data, event.data().size()));
_pending_po.back()->next();
+ } else if (event.port_index() == inputs::FINISH) {
+ unsigned int index;
+
+ event.data()(index);
+ _available_machines[index]++;
} else if (event.port_index() >= inputs::IN_M) {
uint8_t *data = nullptr;
event.data()(data);
_pending_po.push_back(std::make_unique(data, event.data().size()));
- _available_machines[event.port_index() - inputs::IN_M] = true;
+ _available_machines[event.port_index() - inputs::IN_M]++;
_pending_po.back()->next();
}
}
);
if (std::find_if(_pending_po.cbegin(), _pending_po.cend(), [this](const auto &e) {
return e->is_finish() or e->current_operation().get_type() == CHANGE_POOL_TYPE or
- _available_machines[e->current_operation().get_loc_index()];
+ _available_machines[e->current_operation().get_loc_index()] > 0;
}) != _pending_po.cend()) {
_phase = Phase::SEND;
} else {
@@ -102,6 +94,9 @@ void PoolRouter::dext(const Time &t, const Time & /* e */, const Bag &bag) {
void PoolRouter::start(const Time & /* t */) {
_phase = Phase::INIT;
+ for (const auto &e: _parameters.capacities) {
+ _available_machines[e.first] = e.second;
+ }
}
Time PoolRouter::ta(const Time & /* t */) const {
@@ -155,8 +150,8 @@ PoolRouter::ProductionOrders::const_iterator PoolRouter::next_po() const {
return it;
} else {
return std::find_if(_pending_po.cbegin(), _pending_po.cend(),
- [this](const auto &e) { return _available_machines[e->current_operation().get_loc_index()]; });
+ [this](const auto &e) { return _available_machines.at(e->current_operation().get_loc_index()) > 0; });
}
}
-} // namespace artis::factory
+} // namespace artis::factory
\ No newline at end of file
diff --git a/src/PoolRouter.hpp b/src/PoolRouter.hpp
index 94fe489..a9563b3 100644
--- a/src/PoolRouter.hpp
+++ b/src/PoolRouter.hpp
@@ -36,14 +36,14 @@ namespace artis::factory {
struct PoolRouterParameters {
uint type;
- std::size_t machine_number;
+ std::map capacities;
};
class PoolRouter : public Dynamics {
public:
struct inputs {
enum values {
- IN, IN_M = 1000
+ IN, FINISH, IN_M = 1000
};
};
@@ -60,14 +60,13 @@ public:
};
PoolRouter(const std::string &name, const Context &context)
- : Dynamics(name, context),
- _parameters(context.parameters()), _available_machines(context.parameters().machine_number) {
- input_port({inputs::IN, "in"});
+ : Dynamics(name, context), _parameters(context.parameters()) {
+ input_ports({{inputs::IN, "in"},
+ {inputs::FINISH, "finish"}});
output_port({outputs::OUT, "out"});
- for (unsigned int i = 0; i < context.parameters().machine_number; ++i) {
- output_port({outputs::OUT_M + i, "out_m" + std::to_string(i)});
- input_port({inputs::IN_M + i, "in_m" + std::to_string(i)});
- _available_machines[i] = true;
+ for (const auto &e: context.parameters().capacities) {
+ output_port({outputs::OUT_M + e.first, "out_m_" + std::to_string(e.first)});
+ input_port({inputs::IN_M + e.first, "in_m_" + std::to_string(e.first)});
}
observables({{vars::WAITING_PO_NUMBER, "waiting_po_number"}});
}
@@ -115,7 +114,7 @@ private:
// state
Phase::values _phase;
ProductionOrders _pending_po;
- std::vector _available_machines;
+ std::map _available_machines;
};
} // namespace artis::factory
diff --git a/src/Processor.cpp b/src/Processor.cpp
index 4e4581a..cbd041c 100644
--- a/src/Processor.cpp
+++ b/src/Processor.cpp
@@ -24,63 +24,97 @@
* along with this program. If not, see .
*/
+#include "ItemStock.hpp"
#include "Processor.hpp"
+#include "Stock.hpp"
namespace artis::factory {
- void Processor::dint(const Time & t) {
- switch (_phase) {
- case Phase::INIT: {
- _phase = Phase::WAIT;
- break;
- }
- case Phase::READY:
- _po.reset(nullptr);
- _phase = Phase::WAIT;
- break;
- case Phase::WAIT:
- assert(false);
- break;
- case Phase::LOADING: {
- _phase = Phase::PROCESSING;
- break;
- }
- case Phase::PROCESSING: {
- _phase = Phase::UNLOADING;
- break;
- }
- case Phase::UNLOADING: {
- _phase = Phase::READY;
-
-#ifdef WITH_TRACE
- Trace::trace()
- << TraceElement(get_name(), t,
- artis::common::FormalismType::PDEVS,
- artis::common::FunctionType::DELTA_INT,
- artis::common::LevelType::USER)
- << "FINISH po = " << _po->to_string();
- Trace::trace().flush();
-#endif
-
- break;
- }
- default:
- assert(false);
+void Processor::dint(const Time &t) {
+ for (auto it = _jobs.cbegin(); it != _jobs.cend();) {
+ if (it->second._next_time == t and it->second._phase == Phase::READY) {
+ it = _jobs.erase(it);
+ } else {
+ ++it;
}
}
+ for (auto &j: _jobs) {
+ auto &job = j.second;
+ if (job._next_time == t) {
+ switch (job._phase) {
+ case Phase::DEMAND_SUPPLY:
+ job._phase = Phase::WAIT_SUPPLY;
+ job._next_time = artis::common::DoubleTime::infinity;
+ break;
+ case Phase::WAIT_SUPPLY:
+ case Phase::WAIT:
+ assert(false);
+ break;
+ case Phase::LOADING: {
+ job._phase = Phase::PROCESSING;
+ job._next_time = t + durations(job._po->get_productID()).processing_time;
+ break;
+ }
+ case Phase::PROCESSING: {
+ job._phase = Phase::UNLOADING;
+ job._next_time = t + durations(job._po->get_productID()).unload_time;
+ break;
+ }
+ case Phase::UNLOADING: {
+ auto it = _parameters.in_out.find(job._po->get_productID());
- void Processor::dext(const Time &t, const Time & /* e */, const Bag &bag) {
+ if (it != _parameters.in_out.cend() and not it->second._outs.empty()) {
+ job._phase = Phase::SEND_STOCK_AVAILABLE;
+ job._next_time = t;
+ } else {
+ job._phase = Phase::READY;
+ job._next_time = t;
+ }
+
+#ifdef WITH_TRACE
+ Trace::trace()
+ << TraceElement(get_name(), t,
+ artis::common::FormalismType::PDEVS,
+ artis::common::FunctionType::DELTA_INT,
+ artis::common::LevelType::USER)
+ << "FINISH po = " << job._po->to_string();
+ Trace::trace().flush();
+#endif
+
+ break;
+ }
+ case Phase::SEND_STOCK_AVAILABLE: {
+ job._phase = Phase::WAIT_STOCK_AVAILABLE;
+ job._next_time = artis::common::DoubleTime::infinity;
+ break;
+ }
+ default:
+ assert(false);
+ }
+ }
+ }
+}
+
+void Processor::dext(const Time &t, const Time & /* e */, const Bag &bag) {
std::for_each(bag.begin(), bag.end(), [this, t](const ExternalEvent &event) {
- if (event.port_index() == inputs::IN) {
+ if (event.on_port(inputs::IN)) {
uint8_t *data = nullptr;
- // TODO
- assert(_po == nullptr);
+ assert(_jobs.size() < _parameters.capacity);
event.data()(data);
- _po = std::make_unique(data, event.data().size());
- _phase = Phase::LOADING;
+
+ auto po = std::make_unique(data, event.data().size());
+ auto po_id = po->getID();
+ auto product_id = po->get_productID();
+ auto it = _parameters.in_out.find(po->get_productID());
+
+ if (it == _parameters.in_out.end() or it->second._ins.empty()) {
+ _jobs[po_id] = Job{Phase::LOADING, std::move(po), 0, t + durations(product_id).load_time};
+ } else {
+ _jobs[po_id] = Job{Phase::DEMAND_SUPPLY, std::move(po), (unsigned int) it->second._ins.size(), t};
+ }
#ifdef WITH_TRACE
Trace::trace()
@@ -88,43 +122,125 @@ namespace artis::factory {
artis::common::FormalismType::PDEVS,
artis::common::FunctionType::DELTA_EXT,
artis::common::LevelType::USER)
- << "START po = " << _po->to_string();
+ << "START po = " << _jobs[po_id]._po->to_string();
Trace::trace().flush();
#endif
+ } else if (event.on_port(inputs::IN_ITEM)) {
+ ItemResponse response;
+
+ event.data()(response);
+
+ assert(_jobs.find(response.po_id) != _jobs.end());
+
+ auto &job = _jobs[response.po_id];
+ job._demand_number--;
+ if (job._demand_number == 0) {
+ job._phase = Phase::LOADING;
+ job._next_time = t + durations(job._po->get_productID()).load_time;
+ }
+ } else if (event.on_port(inputs::IN_STOCK)) {
+ ProductResponse response;
+
+ event.data()(response);
+
+ assert(_jobs.find(response.po_id) != _jobs.end());
+
+ auto &job = _jobs[response.po_id];
+
+ job._demand_number--;
+ if (job._demand_number == 0) {
+ job._phase = Phase::LOADING;
+ job._next_time = t + durations(job._po->get_productID()).load_time;
+ }
+ } else if (event.port_index() >= inputs::IN_STOCK_AVAILABLE) {
+ StockAvailableResponse response;
+
+ event.data()(response);
+
+ assert(_jobs.find(response.po_id) != _jobs.end());
+
+ auto &job = _jobs[response.po_id];
+
+ switch (response.response) {
+ case StockAvailableResponse::AVAILABLE: {
+ job._phase = Phase::READY;
+ job._next_time = t;
+ break;
+ }
+ case StockAvailableResponse::NOT_AVAILABLE: {
+ job._phase = Phase::WAIT_STOCK_AVAILABLE;
+ job._next_time = artis::common::DoubleTime::infinity;
+ break;
+ }
+ case StockAvailableResponse::NEW_AVAILABLE: {
+ job._phase = Phase::SEND_STOCK_AVAILABLE;
+ job._next_time = t;
+ break;
+ }
+ }
}
});
}
void Processor::start(const Time & /* t */) {
- // TODO
- _phase = Phase::INIT;
}
-Time Processor::ta(const Time & /* t */) const {
- // TODO
- switch (_phase) {
- case Phase::INIT:
- case Phase::READY:
- return 0;
- case Phase::WAIT:
- return artis::common::DoubleTime::infinity;
- case Phase::LOADING:
- return _parameters.load_time;
- case Phase::PROCESSING:
- return _parameters.processing_time;
- case Phase::UNLOADING:
- return _parameters.unload_time;
+Time Processor::ta(const Time &t) const {
+ if (not _jobs.empty()) {
+ return std::min_element(_jobs.cbegin(), _jobs.cend(), [](const auto &lhs, const auto &rhs) {
+ return (lhs.second._next_time != artis::common::DoubleTime::infinity and
+ lhs.second._next_time < rhs.second._next_time) or
+ rhs.second._next_time == artis::common::DoubleTime::infinity;
+ })->second._next_time - t;
}
return artis::common::DoubleTime::infinity;
}
-Bag Processor::lambda(const Time & /* t */) const {
+Bag Processor::lambda(const Time &t) const {
Bag bag;
- // TODO
- if (_phase == Phase::READY) {
- bag.push_back(ExternalEvent(outputs::OUT, common::event::Value(_po->_buffer, _po->_size)));
+ for (const auto &e: _jobs) {
+ const auto &job = e.second;
+
+ if (job._next_time == t) {
+ if (job._phase == Phase::READY) {
+ bag.push_back(ExternalEvent(outputs::OUT, common::event::Value(job._po->_buffer, job._po->_size)));
+
+ auto it = _parameters.in_out.find(job._po->get_productID());
+
+ if (it != _parameters.in_out.cend() and not it->second._outs.empty()) {
+ const auto &p = it->second._outs.front()._destination;
+
+ bag.push_back(ExternalEvent(outputs::OUT_STOCK + int(p._pool_id * 100 + p._stock_id),
+ StockEntry(e.first, job._po->operation_index(),
+ job._po->get_productID(), 1)));
+ }
+ } else if (job._phase == Phase::DEMAND_SUPPLY) {
+ auto it = _parameters.in_out.find(job._po->get_productID());
+
+ for (const auto &item: it->second._ins) {
+ if (item._source._pool_id == -1) {
+ bag.push_back(ExternalEvent(outputs::OUT_ITEM_DEMAND + (int) item._source._stock_id,
+ ItemDemand(item._id, e.first, item._quantity)));
+ } else {
+ bag.push_back(
+ ExternalEvent(outputs::OUT_STOCK_DEMAND + (int) (item._source._pool_id * 100 + item._source._stock_id),
+ ProductDemand(e.first, job._po->operation_index() - (job._po->get_operation(
+ job._po->operation_index() - 1)->get_type() == CHANGE_POOL_TYPE ? 2 : 1),
+ job._po->get_productID(), 1)));
+ }
+ }
+ } else if (job._phase == Phase::SEND_STOCK_AVAILABLE) {
+ auto it = _parameters.in_out.find(job._po->get_productID());
+
+ if (it != _parameters.in_out.cend() and not it->second._outs.empty()) {
+ const auto &p = it->second._outs.front()._destination;
+
+ bag.push_back(ExternalEvent(outputs::OUT_STOCK_AVAILABLE + int(p._pool_id * 100 + p._stock_id), e.first));
+ }
+ }
+ }
}
return bag;
}
@@ -133,4 +249,4 @@ artis::common::event::Value Processor::observe(const Time & /* t */, unsigned in
return {};
}
-} // namespace artis::factory
+} // namespace artis::factory
\ No newline at end of file
diff --git a/src/Processor.hpp b/src/Processor.hpp
index ecfc3fc..4bb86cb 100644
--- a/src/Processor.hpp
+++ b/src/Processor.hpp
@@ -33,23 +33,51 @@
namespace artis::factory {
-struct ProcessorParameters : MachineParameters {
+struct Location {
+ int _pool_id; // -1 if global
+ unsigned int _stock_id;
+};
+
+struct In {
+ int _id; // -1 if current product
+ Location _source;
+ unsigned int _quantity;
+};
+
+struct Out {
+ int _id; // -1 if current product
+ Location _destination;
+ unsigned int _quantity;
+};
+
+struct InOut {
+ std::vector _ins;
+ std::vector _outs;
+};
+
+struct ProcessorDurations : Durations {
uint load_time;
uint processing_time;
uint unload_time;
};
+struct ProcessorParameters : MachineParameters {
+ ProcessorDurations durations;
+ std::map in_out;
+ std::map> product_durations;
+};
+
class Processor : public Dynamics {
public:
struct inputs {
enum values {
- IN
+ IN, IN_ITEM, IN_STOCK, IN_STOCK_AVAILABLE = 4000
};
};
struct outputs {
enum values {
- OUT
+ OUT, OUT_ITEM_DEMAND = 1000, OUT_STOCK = 2000, OUT_STOCK_DEMAND = 3000, OUT_STOCK_AVAILABLE = 4000
};
};
@@ -60,8 +88,66 @@ public:
Processor(const std::string &name, const Context &context)
: Dynamics(name, context), _parameters(context.parameters()) {
- input_port({inputs::IN, "in"});
+ input_ports({{inputs::IN, "in"},
+ {inputs::IN_ITEM, "in_supply"},
+ {inputs::IN_STOCK, "in_stock"}});
output_port({outputs::OUT, "out"});
+
+ // demand: processor -> item stocks
+ std::vector item_stocks;
+
+ for (const auto &p: _parameters.in_out) {
+ for (const auto &q: p.second._ins) {
+ if (q._source._pool_id == -1 and
+ std::find(item_stocks.cbegin(), item_stocks.cend(), q._source._stock_id) == item_stocks.cend()) {
+ item_stocks.push_back(q._source._stock_id);
+ }
+ }
+ }
+ for (const auto &p: item_stocks) {
+ output_port({outputs::OUT_ITEM_DEMAND + p, "out_demand_supply_" + std::to_string(p)});
+ }
+
+ // processor -> intermediate stocks
+ std::vector> stocks;
+
+ for (const auto &p: _parameters.in_out) {
+ for (const auto &q: p.second._outs) {
+ auto r = std::make_pair((unsigned int) q._destination._pool_id, q._destination._stock_id);
+
+ if (q._destination._pool_id != -1 and std::find(stocks.cbegin(), stocks.cend(), r) == stocks.cend()) {
+ stocks.push_back(r);
+ }
+ }
+ }
+ for (const auto &p: stocks) {
+ output_port(
+ {outputs::OUT_STOCK + (p.first * 100 + p.second),
+ "out_stock_" + std::to_string(p.first) + "_" + std::to_string(p.second)});
+ output_port(
+ {outputs::OUT_STOCK_AVAILABLE + (p.first * 100 + p.second),
+ "out_stock_available_" + std::to_string(p.first) + "_" + std::to_string(p.second)});
+ input_port(
+ {inputs::IN_STOCK_AVAILABLE + (p.first * 100 + p.second),
+ "in_stock_available_" + std::to_string(p.first) + "_" + std::to_string(p.second)});
+ }
+
+ // demand: processor -> intermediate stocks
+ stocks.clear();
+ for (const auto &p: _parameters.in_out) {
+ for (const auto &q: p.second._ins) {
+ auto r = std::make_pair((unsigned int) q._source._pool_id, q._source._stock_id);
+
+ if (q._source._pool_id != -1 and std::find(stocks.cbegin(), stocks.cend(), r) == stocks.cend()) {
+ stocks.push_back(r);
+ }
+ }
+ }
+ for (const auto &p: stocks) {
+ output_port(
+ {outputs::OUT_STOCK_DEMAND + (p.first * 100 + p.second),
+ "out_stock_demand_" + std::to_string(p.first) + "_" + std::to_string(p.second)});
+ }
}
~Processor() override = default;
@@ -79,21 +165,29 @@ public:
artis::common::event::Value observe(const Time &t, unsigned int index) const override;
private:
+ const ProcessorDurations &durations(unsigned int product_id) const {
+ if (_parameters.product_durations.find(product_id) == _parameters.product_durations.cend()) {
+ return _parameters.durations;
+ } else {
+ return *_parameters.product_durations.at(product_id);
+ }
+ }
struct Phase {
enum values {
- INIT,
READY,
WAIT,
LOADING,
PROCESSING,
- UNLOADING
+ UNLOADING,
+ DEMAND_SUPPLY,
+ WAIT_SUPPLY,
+ SEND_STOCK_AVAILABLE,
+ WAIT_STOCK_AVAILABLE
};
static std::string to_string(const values &value) {
switch (value) {
- case INIT:
- return "INIT";
case READY:
return "READY";
case WAIT:
@@ -104,19 +198,33 @@ private:
return "PROCESSING";
case UNLOADING:
return "UNLOADING";
+ case DEMAND_SUPPLY:
+ return "DEMAND SUPPLY";
+ case WAIT_SUPPLY:
+ return "WAIT SUPPLY";
+ case SEND_STOCK_AVAILABLE:
+ return "SEND STOCK AVAILABLE";
+ case WAIT_STOCK_AVAILABLE:
+ return "WAIT STOCK AVAILABLE";
}
return "";
}
};
- // parameters
+ struct Job {
+ Phase::values _phase;
+ std::unique_ptr _po;
+ unsigned int _demand_number;
+ Time _next_time;
+ };
+
+// parameters
ProcessorParameters _parameters;
- // state
- Phase::values _phase;
- std::unique_ptr _po;
+// state
+ std::map _jobs; // key = po_id
};
} // namespace artis::factory
-#endif
+#endif
\ No newline at end of file
diff --git a/src/ProductionOrder.cpp b/src/ProductionOrder.cpp
index 3ae3f02..535714e 100644
--- a/src/ProductionOrder.cpp
+++ b/src/ProductionOrder.cpp
@@ -84,7 +84,8 @@ ProductionOrder::ProductionOrder(uint8_t *buffer, std::size_t size)
_is_finish = _buffer[INDEX_POSITION] + 1 >= _buffer[OPERATION_NUMBER_POSITION];
}
-ProductionOrder::ProductionOrder(uint16_t ID, uint16_t product_ID, const Program &program) : _is_finish(false) {
+ProductionOrder::ProductionOrder(uint16_t ID, uint16_t parent_ID, uint32_t due_date, uint16_t product_ID,
+ const Program &program) : _is_finish(false) {
Reference reference{0, 0};
std::size_t operation_number = 0;
@@ -108,6 +109,16 @@ ProductionOrder::ProductionOrder(uint16_t ID, uint16_t product_ID, const Program
_buffer[reference._byte_index++] = (uint8_t) (ID >> 8);
_buffer[reference._byte_index++] = (uint8_t) (ID & 0xFF);
+ // parent ID
+ _buffer[reference._byte_index++] = (uint8_t) (parent_ID >> 8);
+ _buffer[reference._byte_index++] = (uint8_t) (parent_ID & 0xFF);
+
+ // due date
+ _buffer[reference._byte_index++] = (uint8_t) (due_date >> 24);
+ _buffer[reference._byte_index++] = (uint8_t) ((due_date >> 16) & 0xFF);
+ _buffer[reference._byte_index++] = (uint8_t) ((due_date >> 8) & 0xFF);
+ _buffer[reference._byte_index++] = (uint8_t) (due_date & 0xFF);
+
// product ID
_buffer[reference._byte_index++] = (uint8_t) (product_ID >> 8);
_buffer[reference._byte_index++] = (uint8_t) (product_ID & 0xFF);
@@ -199,8 +210,14 @@ std::unique_ptr ProductionOrder::previous_operation() const {
std::string ProductionOrder::to_string() const {
std::string str = "[ ";
uint16_t ID = (_buffer[ID_POSITION] << 8) + _buffer[ID_POSITION + 1];
+ uint16_t parentID = (_buffer[PARENT_ID_POSITION] << 8) + _buffer[PARENT_ID_POSITION + 1];
- str += std::to_string(ID) + " ][ ";
+ str += std::to_string(ID);
+ if (ID != parentID) {
+ str += + "/" + std::to_string(parentID) +" ][ ";
+
+ }
+ str += " ][ ";
for (uint8_t i = 0; i < _buffer[OPERATION_NUMBER_POSITION]; ++i) {
if (_buffer[INDEX_POSITION] == i) {
str += "<";
diff --git a/src/ProductionOrder.hpp b/src/ProductionOrder.hpp
index 1dfef61..dd46409 100644
--- a/src/ProductionOrder.hpp
+++ b/src/ProductionOrder.hpp
@@ -34,15 +34,17 @@
namespace artis::factory {
-// HEADER = [bit number (16 bits)][ID (16 bits)][Product ID (16 bits)][index (8 bits)][operation number (8 bits)]
-const std::size_t POOL_SIZE = 7; // bit number
-const std::size_t MACHINE_SIZE = 4; // bit number
-const std::size_t TYPE_SIZE = 2; // bit number
-const std::size_t HEADER_SIZE = 8; // byte number
+// HEADER = [bit number (16 bits)][ID (16 bits)][parent ID (16 bits)][Due date (32 bits)][Product ID (16 bits)][index (8 bits)][operation number (8 bits)]
+const std::size_t POOL_SIZE = 7; // bit number
+const std::size_t MACHINE_SIZE = 4; // bit number
+const std::size_t TYPE_SIZE = 2; // bitModifier le générateur de PO afin de générer tous les PO number
+const std::size_t HEADER_SIZE = 14; // byte number
const std::size_t BIT_NUMBER_POSITION = 0;
const std::size_t ID_POSITION = BIT_NUMBER_POSITION + 2;
-const std::size_t PRODUCT_ID_POSITION = ID_POSITION + 2;
+const std::size_t PARENT_ID_POSITION = ID_POSITION + 2;
+const std::size_t DUE_DATE_POSITION = PARENT_ID_POSITION + 2;
+const std::size_t PRODUCT_ID_POSITION = DUE_DATE_POSITION + 4;
const std::size_t INDEX_POSITION = PRODUCT_ID_POSITION + 2;
const std::size_t OPERATION_NUMBER_POSITION = INDEX_POSITION + 1;
@@ -139,7 +141,7 @@ struct ProductionOrder {
~ProductionOrder() { delete[] _buffer; }
- ProductionOrder(uint16_t ID, uint16_t product_ID, const Program &program);
+ ProductionOrder(uint16_t ID, uint16_t parent_ID, uint32_t due_date, uint16_t product_ID, const Program &program);
const Operation ¤t_operation() const { return *_current_operation; }
@@ -147,8 +149,17 @@ struct ProductionOrder {
return (_buffer[ID_POSITION] << 8) + _buffer[ID_POSITION + 1];
}
+ uint32_t get_due_date() const {
+ return (_buffer[DUE_DATE_POSITION] << 24) + (_buffer[DUE_DATE_POSITION] << 16) + (_buffer[DUE_DATE_POSITION] << 8) +
+ _buffer[DUE_DATE_POSITION + 1];
+ }
+
std::unique_ptr get_operation(uint8_t index) const;
+ uint16_t get_parentID() const {
+ return (_buffer[PARENT_ID_POSITION] << 8) + _buffer[PARENT_ID_POSITION + 1];
+ }
+
uint16_t get_productID() const {
return (_buffer[PRODUCT_ID_POSITION] << 8) + _buffer[PRODUCT_ID_POSITION + 1];
}
diff --git a/src/ProductionOrderGenerator.cpp b/src/ProductionOrderGenerator.cpp
index 3bc3294..18fa932 100644
--- a/src/ProductionOrderGenerator.cpp
+++ b/src/ProductionOrderGenerator.cpp
@@ -28,20 +28,30 @@
namespace artis::factory {
-void ProductionOrderGenerator::dint(const Time & /* &t */) {
+void ProductionOrderGenerator::dint(const Time &t) {
switch (_phase) {
case Phase::INIT:
_phase = Phase::SEND;
break;
case Phase::SEND: {
- _current_id++;
- _po_counter++;
- _productID = _productIDs[_distrib_product(_rng)];
- _po = std::make_unique(_current_id, _productID, _parameters.programs[_productID]);
- _send_speed = _distrib_send_speed(_rng);
- _phase = Phase::SEND;
+ if (_parameters.po_number == -1) {
+ generate_production_orders(t);
+ _sigma = _distrib_send_speed(_rng);
+ _phase = Phase::SEND;
+ } else {
+ if (_po_index < (unsigned int) _parameters.po_number - 1) {
+ _po_index++;
+ if (not _parameters.po_order.empty()) {
+ _sigma = 0;
+ }
+ } else {
+ _phase = Phase::FINISH;
+ }
+ }
break;
}
+ case Phase::FINISH:
+ assert(false);
}
}
@@ -51,14 +61,18 @@ void ProductionOrderGenerator::dext(const Time & /* t */, const Time & /* e */,
});
}
-void ProductionOrderGenerator::start(const Time & /* t */) {
+void ProductionOrderGenerator::start(const Time &t) {
_phase = Phase::INIT;
- _po = nullptr;
_current_id = 0;
- _productID = _productIDs[_distrib_product(_rng)];
- _po = std::make_unique(_current_id, _productID, _parameters.programs[_productID]);
- _po_counter = 0;
- _send_speed = 0; // _distrib_send_speed(_rng);
+ _po_index = 0;
+ if (_parameters.po_number == -1) {
+ generate_production_orders(t);
+ } else {
+ for (unsigned int i = 0; i < (unsigned int) _parameters.po_number; ++i) {
+ generate_production_orders(t);
+ }
+ }
+ _sigma = 0;
}
Time ProductionOrderGenerator::ta(const Time & /* t */) const {
@@ -66,7 +80,9 @@ Time ProductionOrderGenerator::ta(const Time & /* t */) const {
case Phase::INIT:
return 0;
case Phase::SEND:
- return _send_speed;
+ return _sigma;
+ case Phase::FINISH:
+ return artis::common::DoubleTime::infinity;
}
return artis::common::DoubleTime::infinity;
}
@@ -75,8 +91,12 @@ Bag ProductionOrderGenerator::lambda(const Time & /* t */) const {
Bag bag;
if (_phase == Phase::SEND) {
- if (_po) {
- bag.push_back(ExternalEvent(outputs::OUT, common::event::Value(_po->_buffer, _po->_size)));
+ if (_parameters.po_order.empty()) {
+ bag.push_back(ExternalEvent(outputs::OUT, common::event::Value(_pos[_po_index]->_buffer, _pos[_po_index]->_size)));
+ } else {
+ const auto &po = _pos[_parameters.po_order[_po_index]];
+
+ bag.push_back(ExternalEvent(outputs::OUT, common::event::Value(po->_buffer, po->_size)));
}
}
return bag;
@@ -85,9 +105,16 @@ Bag ProductionOrderGenerator::lambda(const Time & /* t */) const {
artis::common::event::Value ProductionOrderGenerator::observe(const Time & /* t */, unsigned int index) const {
switch (index) {
case vars::TOTAL_PO_NUMBER:
- return (unsigned int) _po_counter;
+ return (unsigned int) _po_index;
}
return {};
}
+void ProductionOrderGenerator::generate_production_orders(const Time &t) {
+ _productID = _productIDs[_distrib_product(_rng)];
+ _pos.push_back(std::make_unique(_current_id, _current_id, t + 8 * 60 * 60, _productID,
+ _parameters.programs[_productID]));
+ _current_id++;
+}
+
} // namespace artis::factory
diff --git a/src/ProductionOrderGenerator.hpp b/src/ProductionOrderGenerator.hpp
index eb17013..a0ff848 100644
--- a/src/ProductionOrderGenerator.hpp
+++ b/src/ProductionOrderGenerator.hpp
@@ -42,6 +42,8 @@ struct ProductionOrderGeneratorParameters {
uint random_seed;
uint min_send_speed_rate;
uint max_send_speed_rate;
+ int po_number{-1};
+ std::vector po_order{};
};
class ProductionOrderGenerator
@@ -89,9 +91,11 @@ public:
artis::common::event::Value observe(const Time &t, unsigned int index) const override;
private:
+ void generate_production_orders(const Time & t);
+
struct Phase {
enum values {
- INIT, SEND
+ INIT, SEND, FINISH
};
static std::string to_string(const values &value) {
@@ -100,6 +104,8 @@ private:
return "INIT";
case SEND:
return "SEND";
+ case FINISH:
+ return "FINISH";
}
return "";
}
@@ -119,11 +125,11 @@ private:
std::vector _productIDs;
unsigned int _productID;
- std::unique_ptr _po;
+ std::vector> _pos;
unsigned int _current_id;
- std::size_t _po_counter;
- unsigned int _send_speed;
+ std::size_t _po_index;
+ unsigned int _sigma;
};
} // namespace artis::factory
diff --git a/src/Sink.cpp b/src/Sink.cpp
index aa44550..5c5eca8 100644
--- a/src/Sink.cpp
+++ b/src/Sink.cpp
@@ -28,52 +28,51 @@
namespace artis::factory {
-void Sink::dint(const Time &/*t*/) {
- // TODO
- // Inutile si l'on consiède que cet élément ce fait que recevoir des POs. Il ne fait rien par lui-même, et ne varie que en fonction de son environnement.
+void Sink::dint(const Time & /* t */) {
+ switch (_phase) {
+ case Phase::WAIT: {
+ assert(false);
+ }
+ case Phase::SEND: {
+ _phase = Phase::WAIT;
+ }
+ }
}
void Sink::dext(const Time &t, const Time & /* e */, const Bag &bag) {
- std::for_each(bag.begin(), bag.end(), [this, t](const ExternalEvent &event) {
-
+ std::for_each(bag.begin(), bag.end(), [t, this](const ExternalEvent &event) {
if (event.port_index() == inputs::IN) {
uint8_t *data = nullptr;
event.data()(data);
- std::unique_ptr po = std::make_unique(data, event.data().size());
- #ifdef WITH_TRACE
- Trace::trace()
- << TraceElement(get_name(), t,
- artis::common::FormalismType::PDEVS,
- artis::common::FunctionType::DELTA_EXT,
- artis::common::LevelType::USER)
- << "Sink received po = " << po->to_string();
- Trace::trace().flush();
- #endif
- _pos.push_back(std::move(po));//Je ne peux pas dupliquer ce pointer unique dans la liste, je dois explicitement le déplacer.
- _phase = Phase::LOADED;
+ _finished_po.push_back(std::make_unique(data, event.data().size()));
+ _phase = Phase::SEND;
+#ifdef WITH_TRACE
+ Trace::trace()
+ << TraceElement(get_name(), t,
+ artis::common::FormalismType::PDEVS,
+ artis::common::FunctionType::DELTA_EXT,
+ artis::common::LevelType::USER)
+ << "FINISH po = " << _finished_po.back()->to_string();
+ Trace::trace().flush();
+#endif
}
});
}
void Sink::start(const Time & /* t */) {
- _phase = Phase::INIT;
- // Préparation du modèle, j'imagine que ce n'est pas utile donc passage immédiat en READY
- _phase = Phase::READY;
- // Le modèle est prêt, on attend des PO
_phase = Phase::WAIT;
}
Time Sink::ta(const Time & /* t */) const {
switch (_phase) {
- case Phase::INIT:// Phase transitoire, je n'y reste pas, le modèle ne fait qu'y passer
- case Phase::READY:// Idem
- //case Phase::UNLOADING:// Déchargement des PO dans la sortie, ce n'est que transitoire
- return 0;
- case Phase::WAIT:// J'attends un premier PO, potentiellement infini
- case Phase::LOADED:// J'ai un PO en stock, j'attends d'en faire quelque chose,ce qui est potentiellement infini
+ case Phase::WAIT: {
return artis::common::DoubleTime::infinity;
+ }
+ case Phase::SEND: {
+ return 0;
+ }
}
return artis::common::DoubleTime::infinity;
}
@@ -81,13 +80,18 @@ Time Sink::ta(const Time & /* t */) const {
Bag Sink::lambda(const Time & /* t */) const {
Bag bag;
- // TODO
- // Pour le moment, Sink ne laisse pas sortir les POs arrivés dedans. Inutile de définir ceci.
+ if (_phase == Phase::SEND) {
+ bag.push_back(ExternalEvent(outputs::OUT, (unsigned int) _parameters.machine_id));
+ }
return bag;
}
-artis::common::event::Value Sink::observe(const Time & /* t */, unsigned int /* index */) const {
+artis::common::event::Value Sink::observe(const Time & /* t */, unsigned int index) const {
+ switch (index) {
+ case vars::FINISHED_PO_NUMBER:
+ return (unsigned int) _finished_po.size();
+ }
return {};
}
-} // namespace artis::factory
+} // namespace artis::factory
\ No newline at end of file
diff --git a/src/Sink.hpp b/src/Sink.hpp
index cd11f6c..91453e8 100644
--- a/src/Sink.hpp
+++ b/src/Sink.hpp
@@ -34,7 +34,6 @@
namespace artis::factory {
struct SinkParameters : MachineParameters {
-
};
class Sink : public Dynamics {
@@ -53,13 +52,15 @@ public:
struct vars {
enum values {
+ FINISHED_PO_NUMBER
};
};
Sink(const std::string &name, const Context &context)
- : Dynamics(name, context) {
+ : Dynamics(name, context), _parameters(context.parameters()) {
input_port({inputs::IN, "in"});
output_port({outputs::OUT, "out"});
+ observables({{vars::FINISHED_PO_NUMBER, "finished_po_number"}});
}
~Sink() override = default;
@@ -77,38 +78,30 @@ public:
artis::common::event::Value observe(const Time &t, unsigned int index) const override;
private:
- struct Phase {
- enum values {
- INIT,
- READY,
- WAIT,
- LOADED,
- //UNLOADING
- };
-
- static std::string to_string(const values &value) {
- switch (value) {
- case INIT:
- return "INIT";
- case READY:
- return "READY";
- case WAIT:
- return "WAIT";
- case LOADED:
- return "LOADED";
- /*case UNLOADING:
- return "UNLOADING";*/
- }
- return "";
- }
+ struct Phase {
+ enum values {
+ WAIT, SEND
};
+ static std::string to_string(const values &value) {
+ switch (value) {
+ case WAIT:
+ return "WAIT";
+ case SEND:
+ return "SEND";
+ }
+ return "";
+ }
+ };
+ typedef std::deque> ProductionOrders;
- Phase::values _phase;
- std::vector> _pos;
-}; // class Sink
+ SinkParameters _parameters;
+
+ Phase::values _phase;
+ ProductionOrders _finished_po;
+};
} // namespace artis::factory
-#endif // ARTIS_FACTORY_SINK_HPP
+#endif
\ No newline at end of file
diff --git a/src/Stock.cpp b/src/Stock.cpp
index 8469936..3d62cae 100644
--- a/src/Stock.cpp
+++ b/src/Stock.cpp
@@ -29,32 +29,119 @@
namespace artis::factory {
void Stock::dint(const Time & /* t */) {
- // TODO
+ switch (_phase) {
+ case Phase::SEND_AVAILABLE: {
+ _available_demands.clear();
+ _phase = Phase::WAIT;
+ break;
+ }
+ case Phase::SEND: {
+ _demands.clear();
+ _phase = Phase::WAIT;
+ break;
+ }
+ case Phase::WAIT: {
+ assert(false);
+ }
+ }
}
-void Stock::dext(const Time & /* t */, const Time & /* e */, const Bag &bag) {
- std::for_each(bag.begin(), bag.end(), [](const ExternalEvent & /* event */) {
- // TODO
+void Stock::dext(const Time &t, const Time & /* e */, const Bag &bag) {
+ std::for_each(bag.begin(), bag.end(), [t, this](const ExternalEvent &event) {
+ if (event.on_port(inputs::IN)) {
+ StockEntry entry;
+
+ event.data()(entry);
+ if (_parameters._capacity == -1 or (int) _entries.size() < _parameters._capacity) {
+ _entries.push_back({t, entry.po_id, entry.po_index, entry.product_id, entry.quantity});
+ } else {
+ assert(false);
+ }
+ } else if (event.port_index() >= inputs::IN_DEMAND and event.port_index() < inputs::IN_STOCK_AVAILABLE) {
+ ProductDemand demand;
+
+ event.data()(demand);
+ auto it = std::find_if(_entries.begin(), _entries.end(), [demand](const auto &e) {
+ return e._po_id == demand.po_id and e._po_index == demand.po_index and e._product_id == demand.product_id
+ and e._quantity >= demand.quantity;
+ });
+
+ if (it != _entries.end()) {
+ if (it->_quantity == demand.quantity) {
+ _entries.erase(it);
+ } else {
+ it->_quantity -= demand.quantity;
+ }
+ _demands.push_back(std::make_pair(event.port_index() - inputs::IN_DEMAND, demand));
+ _phase = Phase::SEND;
+ }
+ } else if (event.port_index() >= inputs::IN_STOCK_AVAILABLE) {
+ unsigned int machine_id = event.port_index() - inputs::IN_STOCK_AVAILABLE;
+ unsigned int po_id;
+
+ event.data()(po_id);
+ _available_demands.push_back(AvailableDemand{machine_id, po_id, false});
+ if (_parameters._capacity == -1 or (int) _entries.size() < _parameters._capacity) {
+ auto it = std::find_if(_waiting_machine_ids.begin(), _waiting_machine_ids.end(),
+ [machine_id, po_id](const auto &e) {
+ return machine_id == e.first and po_id == e.second;
+ });
+
+ if (it != _waiting_machine_ids.end()) {
+ _waiting_machine_ids.erase(it);
+ }
+ _available_demands.back()._available = true;
+ _phase = Phase::SEND_AVAILABLE;
+ } else {
+ _waiting_machine_ids.push_back(std::make_pair(machine_id, po_id));
+ _phase = Phase::SEND_AVAILABLE;
+ }
+ }
});
}
void Stock::start(const Time & /* t */) {
- // TODO
+ _phase = Phase::WAIT;
}
Time Stock::ta(const Time & /* t */) const {
- // TODO
+ switch (_phase) {
+ case Phase::WAIT:
+ return artis::common::DoubleTime::infinity;
+ case Phase::SEND:
+ case Phase::SEND_AVAILABLE:
+ return 0;
+ }
return artis::common::DoubleTime::infinity;
}
Bag Stock::lambda(const Time & /* t */) const {
Bag bag;
- // TODO
+ if (_phase == Phase::SEND) {
+ for (const auto &e: _waiting_machine_ids) {
+ bag.push_back(ExternalEvent(outputs::OUT_STOCK_AVAILABLE + e.first,
+ StockAvailableResponse(e.second, StockAvailableResponse::NEW_AVAILABLE)));
+ }
+ for (const auto &e: _demands) {
+ bag.push_back(ExternalEvent(outputs::OUT + e.first, ProductResponse(e.second.product_id, e.second.po_id)));
+ }
+ } else if (_phase == Phase::SEND_AVAILABLE) {
+ for (const auto &demand: _available_demands) {
+ bag.push_back(ExternalEvent(outputs::OUT_STOCK_AVAILABLE + demand._machine_id,
+ StockAvailableResponse(demand._po_id,
+ demand._available ? StockAvailableResponse::AVAILABLE
+ : StockAvailableResponse::NOT_AVAILABLE)));
+ }
+ }
return bag;
}
-artis::common::event::Value Stock::observe(const Time & /* t */, unsigned int /* index */) const {
+artis::common::event::Value Stock::observe(const Time & /* t */, unsigned int index) const {
+ switch (index) {
+ case vars::ENTRY_NUMBER:
+ return (unsigned int) _entries.size();
+ }
return {};
}
diff --git a/src/Stock.hpp b/src/Stock.hpp
index 779dcde..274b85c 100644
--- a/src/Stock.hpp
+++ b/src/Stock.hpp
@@ -1,5 +1,5 @@
/**
- * @file Stock.hpp
+ * @file IntermediateStock.hpp
* @author The ARTIS Development Team
* See the AUTHORS or Authors.txt file
*/
@@ -32,32 +32,120 @@
namespace artis::factory {
+struct StockEntry {
+ unsigned int po_id;
+ unsigned int po_index;
+ unsigned int product_id;
+ unsigned int quantity;
+
+ StockEntry(unsigned int po_id = 0, unsigned int po_index = 0, unsigned int product_id = 0, unsigned int quantity = 0)
+ : po_id(po_id), po_index(po_index), product_id(product_id), quantity(quantity) {}
+
+ bool operator==(const StockEntry &other) const {
+ return po_id == other.po_id and po_index == other.po_index and product_id == other.product_id and
+ quantity == other.quantity;
+ }
+
+ std::string to_string() const {
+ return "StockEntry < " + std::to_string(po_id) + " | " + std::to_string(po_index) + " | " +
+ std::to_string(product_id) + " | " + std::to_string(quantity) + " >";
+ }
+};
+
+struct ProductDemand {
+ unsigned int po_id;
+ unsigned int po_index;
+ unsigned int product_id;
+ unsigned int quantity;
+
+ ProductDemand(unsigned int po_id = 0, unsigned int po_index = 0, unsigned int product_id = 0,
+ unsigned int quantity = 0)
+ : po_id(po_id), po_index(po_index), product_id(product_id), quantity(quantity) {}
+
+ bool operator==(const ProductDemand &other) const {
+ return po_id == other.po_id and po_index == other.po_index and product_id == other.product_id and
+ quantity == other.quantity;
+ }
+
+ std::string to_string() const {
+ return "ProductDemand < " + std::to_string(po_id) + " | " + std::to_string(po_index) + " | " +
+ std::to_string(product_id) + " | " + std::to_string(quantity) + " >";
+ }
+};
+
+struct StockAvailableResponse {
+ int po_id;
+
+ enum values {
+ AVAILABLE, NOT_AVAILABLE, NEW_AVAILABLE
+ } response;
+
+ StockAvailableResponse(unsigned int po_id = 0, values response = NOT_AVAILABLE)
+ : po_id(po_id), response(response) {}
+
+ bool operator==(const StockAvailableResponse &other) const {
+ return po_id == other.po_id and response == other.response;
+ }
+
+ std::string to_string() const {
+ return "StockAvailableResponse < " + std::to_string(po_id) + " | " +
+ (response == AVAILABLE ? "AVAILABLE" : (response == NOT_AVAILABLE ? "NOT AVAILABLE" : "NEW AVAILABLE")) + " >";
+ }
+};
+
+struct ProductResponse {
+ int product_id;
+ int po_id;
+
+ ProductResponse(int product_id = -1, int po_id = -1) : product_id(product_id), po_id(po_id) {}
+
+ bool operator==(const ProductResponse &other) const {
+ return product_id == other.product_id and po_id == other.po_id;
+ }
+
+ std::string to_string() const {
+ return "Response < " + std::to_string(product_id) + " | " + std::to_string(po_id) + " >";
+ }
+};
+
struct StockParameters {
+ std::vector _in_machines;
+ std::vector _out_machines;
+ int _capacity; // if -1 then infinity
};
class Stock : public Dynamics {
public:
struct inputs {
enum values {
- IN
+ IN, IN_DEMAND = 1000, IN_STOCK_AVAILABLE = 2000
};
};
struct outputs {
enum values {
- OUT
+ OUT = 1000, OUT_STOCK_AVAILABLE = 2000
};
};
struct vars {
enum values {
+ ENTRY_NUMBER
};
};
Stock(const std::string &name, const Context &context)
- : Dynamics(name, context) {
+ : Dynamics(name, context), _parameters(context.parameters()) {
input_port({inputs::IN, "in"});
- output_port({outputs::OUT, "out"});
+ for (const auto &m: _parameters._in_machines) {
+ output_port({outputs::OUT + m, "out_" + std::to_string(m)});
+ input_port({inputs::IN_DEMAND + m, "in_demand_" + std::to_string(m)});
+ }
+ for (const auto &m: _parameters._out_machines) {
+ output_port({outputs::OUT_STOCK_AVAILABLE + m, "out_stock_available_" + std::to_string(m)});
+ input_port({inputs::IN_STOCK_AVAILABLE + m, "in_stock_available_" + std::to_string(m)});
+ }
+ observables({{vars::ENTRY_NUMBER, "entry number"}});
}
~Stock() override = default;
@@ -75,7 +163,47 @@ public:
artis::common::event::Value observe(const Time &t, unsigned int index) const override;
private:
- // TODO (state)
+ struct Phase {
+ enum values {
+ WAIT,
+ SEND,
+ SEND_AVAILABLE
+ };
+
+ static std::string to_string(const values &value) {
+ switch (value) {
+ case WAIT:
+ return "WAIT";
+ case SEND:
+ return "SEND";
+ case SEND_AVAILABLE:
+ return "SEND AVAILABLE";
+ }
+ return "";
+ }
+ };
+
+ struct Entry {
+ Time _t;
+ unsigned int _po_id;
+ unsigned int _po_index;
+ unsigned int _product_id;
+ unsigned int _quantity;
+ };
+
+ struct AvailableDemand {
+ unsigned int _machine_id;
+ unsigned int _po_id;
+ bool _available;
+ };
+
+ StockParameters _parameters;
+
+ Phase::values _phase;
+ std::vector _entries;
+ std::vector> _demands;
+ std::vector _available_demands;
+ std::deque> _waiting_machine_ids; // pair(machine_id,po_id)
};
} // namespace artis::factory
diff --git a/test/test_json.cpp b/test/test_json.cpp
index ffcc17a..745e5bf 100644
--- a/test/test_json.cpp
+++ b/test/test_json.cpp
@@ -34,7 +34,8 @@ public:
BOOST_AUTO_TEST_CASE(TestCase_JSONPool)
{
- std::ifstream input("../data/factory.json"); // Fix : j'ai retiré un ../ pour que le test passe sous Codeblocks
+ //std::ifstream input("../../data/factory_with_sinks.json");
+ std::ifstream input("../../data/factory_with_sinks.json");
if (input) {
std::string str((std::istreambuf_iterator(input)), std::istreambuf_iterator());
@@ -66,12 +67,11 @@ BOOST_AUTO_TEST_CASE(TestCase_JSONPool)
output(context.begin(), context.end(), {context.begin(), 1});
- std::cout << artis::factory::Trace::trace().elements().filter_level_type(artis::common::LevelType::USER).to_string()
+ std::cout << artis::factory::Trace::trace().elements().filter_level_type(artis::common::LevelType::USER).filter_model_name("M_3_0").to_string()
<< std::endl;
BOOST_CHECK(true);
} else {
- std::cout << "ERREUR : FICHIER JSON NON TROUVé" << std::endl;
BOOST_CHECK(false);
}
-}
+}
\ No newline at end of file
diff --git a/test/test_optim.cpp b/test/test_optim.cpp
new file mode 100644
index 0000000..a727f36
--- /dev/null
+++ b/test/test_optim.cpp
@@ -0,0 +1,229 @@
+#include
+#include
+#include
+#include
+
+#include "FactoryGraphManager.hpp"
+#include "Machine.hpp"
+
+using namespace artis::factory;
+
+constexpr unsigned int product_number = 10;
+constexpr unsigned int machine_number = 5;
+constexpr unsigned int po_number = 100;
+constexpr unsigned int iteration_number = 1000;
+
+unsigned int processing_times[product_number][machine_number] = {
+ {2, 7, 12, 17, 22},
+ {3, 8, 13, 18, 23},
+ {1, 9, 12, 19, 6},
+ {5, 10, 15, 20, 25},
+ {6, 11, 16, 21, 26},
+ {27, 28, 29, 30, 2},
+ {3, 4, 15, 10, 7},
+ {8, 9, 10, 11, 12},
+ {13, 3, 15, 7, 17},
+ {18, 19, 20, 21, 22}
+};
+
+struct Solution {
+ std::vector po_order;
+ std::vector capacities;
+};
+
+class MyView : public View {
+public:
+ MyView() {
+ for (int i = 0; i < (int) machine_number - 1; ++i) {
+ selector("Stock_" + std::to_string(i) + ":entry_number",
+ {FactoryGraphManager::STOCK + i, Stock::vars::ENTRY_NUMBER});
+ }
+ selector("Sink:finished_po_number",
+ {FactoryGraphManager::MACHINE + machine_number, Sink::vars::FINISHED_PO_NUMBER});
+ }
+};
+
+std::vector make_po_order() {
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ std::vector order;
+ std::vector allNumbers;
+
+ for (unsigned int i = 0; i < po_number; ++i) {
+ allNumbers.push_back(i);
+ }
+ while (order.size() < po_number) {
+ std::uniform_int_distribution dist(0, allNumbers.size() - 1);
+ unsigned int index = dist(gen);
+
+ order.push_back(allNumbers[index]);
+ allNumbers.erase(allNumbers.begin() + index);
+ }
+ return order;
+}
+
+std::vector make_capacities() {
+ std::vector capacities(machine_number - 1, -1);
+
+ return capacities;
+}
+
+class Evaluator {
+public:
+ Evaluator() {
+ make_flow_shop();
+ }
+
+ std::vector evaluate(const Solution &solution) {
+ apply(solution);
+
+ FactoryGraphManagerParameters graph_parameters{factory};
+ artis::common::context::Context context(0, 7200);
+ artis::common::RootCoordinator<
+ artis::common::DoubleTime, artis::pdevs::Coordinator<
+ artis::common::DoubleTime, FactoryGraphManager, artis::common::NoParameters, FactoryGraphManagerParameters>
+ > rc(context, "root", artis::common::NoParameters(), graph_parameters);
+
+ rc.attachView("V", new MyView);
+ rc.switch_to_timed_observer(1);
+
+ rc.run(context);
+
+ auto sink_values = rc.observer().view("V").get("Sink:finished_po_number");
+ double t = -1;
+
+ for (const auto &v: sink_values) {
+ unsigned int n;
+
+ v.second.operator()(n);
+ if (n == po_number) {
+ t = v.first;
+ break;
+ }
+ }
+
+ double sum = 0;
+ for (unsigned int i = 0; i < machine_number - 1; ++i) {
+ auto stock_values = rc.observer().view("V").get("Stock_" + std::to_string(i) + ":entry_number");
+
+ for (const auto &v: stock_values) {
+ unsigned int n;
+
+ v.second.operator()(n);
+ if (v.first > t) {
+ break;
+ }
+ sum += n;
+ }
+ }
+ return {t, sum / (machine_number - 1) / t};
+ }
+
+private:
+ void apply(const Solution &solution) {
+ factory._generator._po_order = solution.po_order;
+ for (unsigned int i = 0; i < machine_number - 1; ++i) {
+ std::get<3>(factory._pools[0])[i]._capacity = (int)solution.capacities[i];
+ }
+ }
+
+ void fix_durations() {
+ for (const auto &product: factory._products) {
+ unsigned int product_id = product.first;
+ unsigned int pool_index = 0;
+
+ for (const auto &pool_machine: product.second._pool_jobs) {
+ unsigned int pool_id = pool_machine._pool_id;
+ const auto &pool = *std::find_if(factory._pools.cbegin(), factory._pools.cend(),
+ [pool_id](const auto &e) { return std::get<0>(e) == pool_id; });
+ const auto &machines = std::get<2>(pool);
+ unsigned int sequence_index = 0;
+
+ for (const auto &machine: pool_machine._machine_jobs) {
+ unsigned int machine_id = machine._machine_id;
+ const auto &m = *std::find_if(machines.cbegin(), machines.cend(),
+ [machine_id](const auto &e) { return e->machine_id == machine_id; });
+
+ if (m->machine_type == PROCESSOR) {
+ auto &M = (ProcessorParameters &) (*m);
+
+ M.product_durations[product_id] = std::static_pointer_cast(machine._durations);
+ }
+ ++sequence_index;
+ }
+ ++pool_index;
+ }
+ }
+ }
+
+ void make_flow_shop() {
+ // generator
+ factory._generator._min_send_speed_rate = 0;
+ factory._generator._max_send_speed_rate = 0;
+ factory._generator._random_seed = 62642;
+ factory._generator._po_number = po_number;
+ // products
+ for (unsigned int i = 0; i < product_number; ++i) {
+ Product product{i, {}, {PoolJob{0, {}}}, true};
+
+ for (unsigned int j = 0; j < machine_number; ++j) {
+ std::vector ins;
+ std::vector outs;
+
+ if (j > 0) {
+ ins.push_back({-1, {0, j - 1}, 1});
+ }
+ if (j < machine_number - 1) {
+ outs.push_back({-1, {0, j}, 1});
+ }
+ product._pool_jobs[0]._machine_jobs.push_back(
+ MachineJob{j, ins, outs,
+ std::make_shared(ProcessorDurations{{}, 1, processing_times[i][j], 1})});
+ }
+
+ product._pool_jobs[0]._machine_jobs.push_back(MachineJob{machine_number, {}, {}, {}});
+ factory._products[i] = product;
+ }
+ // pools
+ factory._pools.push_back({0, 0, {}, {}});
+ for (unsigned int i = 0; i < machine_number; ++i) {
+ std::map in_out;
+
+ for (const auto &product: factory._products) {
+ for (const auto &pool_job: product.second._pool_jobs) {
+ if (pool_job._pool_id == 0) {
+ for (const auto &machine_job: pool_job._machine_jobs) {
+ if (machine_job._machine_id == i) {
+ in_out[product.first] = InOut{machine_job._ins, machine_job._outs};
+ }
+ }
+ }
+ }
+ }
+ std::get<2>(factory._pools[0]).push_back(std::make_shared(ProcessorParameters{{i, 0, 0, 1},
+ {{}, 1, 3, 1},
+ in_out,
+ {}}));
+ }
+ std::get<2>(factory._pools[0]).push_back(
+ std::make_shared(SinkParameters{{machine_number, 1, 0, 1}}));
+ // intermediate stocks
+ for (unsigned int i = 0; i < machine_number - 1; ++i) {
+ std::get<3>(factory._pools[0]).push_back({i, -1});
+ }
+
+ fix_durations();
+ }
+
+ Factory factory;
+};
+
+int main() {
+ Evaluator evaluator;
+
+ for (unsigned int i = 0; i < iteration_number; ++i) {
+ Solution solution{make_po_order(), make_capacities()};
+
+ std::cout << evaluator.evaluate(solution)[0] << " " << evaluator.evaluate(solution)[1] << std::endl;
+ }
+}
\ No newline at end of file
diff --git a/test/test_simple.cpp b/test/test_simple.cpp
index 97dfb56..a727f36 100644
--- a/test/test_simple.cpp
+++ b/test/test_simple.cpp
@@ -1,140 +1,229 @@
#include
#include
#include
-
-#include
#include
-#define BOOST_TEST_MODULE Factory_Simple_Tests
+#include "FactoryGraphManager.hpp"
+#include "Machine.hpp"
-#include
-#include
+using namespace artis::factory;
-#include "Processor.hpp"
-#include "PoolRouter.hpp"
-#include "ProductionOrderGenerator.hpp"
-#include "Router.hpp"
-#include "Sink.hpp"
+constexpr unsigned int product_number = 10;
+constexpr unsigned int machine_number = 5;
+constexpr unsigned int po_number = 100;
+constexpr unsigned int iteration_number = 1000;
-using namespace std::chrono;
+unsigned int processing_times[product_number][machine_number] = {
+ {2, 7, 12, 17, 22},
+ {3, 8, 13, 18, 23},
+ {1, 9, 12, 19, 6},
+ {5, 10, 15, 20, 25},
+ {6, 11, 16, 21, 26},
+ {27, 28, 29, 30, 2},
+ {3, 4, 15, 10, 7},
+ {8, 9, 10, 11, 12},
+ {13, 3, 15, 7, 17},
+ {18, 19, 20, 21, 22}
+};
-class OnlyOnePoolGraphManager
- : public artis::pdevs::GraphManager {
+struct Solution {
+ std::vector po_order;
+ std::vector capacities;
+};
+
+class MyView : public View {
public:
- enum sub_models {
- PROCESSOR_1, PROCESSOR_2, PROCESSOR_3, POOL_ROUTER, ROUTER, GENERATOR, SINK
- };
+ MyView() {
+ for (int i = 0; i < (int) machine_number - 1; ++i) {
+ selector("Stock_" + std::to_string(i) + ":entry_number",
+ {FactoryGraphManager::STOCK + i, Stock::vars::ENTRY_NUMBER});
+ }
+ selector("Sink:finished_po_number",
+ {FactoryGraphManager::MACHINE + machine_number, Sink::vars::FINISHED_PO_NUMBER});
+ }
+};
- OnlyOnePoolGraphManager(artis::common::Coordinator *coordinator,
- const artis::common::NoParameters ¶meters,
- const artis::common::NoParameters &graph_parameters
- ) : artis::pdevs::GraphManager(
- coordinator, parameters, graph_parameters),
- _generator("G",
- {
- {
- {0, {artis::factory::PoolMachineSequence(0, {0, 1, 2, 3})}},
- {1, {artis::factory::PoolMachineSequence(0, {1, 2, 0, 3})}},
- {2, {artis::factory::PoolMachineSequence(0, {2, 0, 1, 3})}}
- },
- 62642, 15, 30
- }),
- _router("R", {1}),
- _pool_router("P_R", {0, 4}),
- _processor_1("M1", {{0, 0, 0}, 1, 10, 1}),
- _processor_2("M2", {{1, 0, 0}, 1, 8, 1}),
- _processor_3("M3", {{2, 0, 0}, 1, 15, 1}),
- _sink("S", {3, 0}) {
- this->add_child(SINK, &_sink);
- this->add_child(PROCESSOR_1, &_processor_1);
- this->add_child(PROCESSOR_2, &_processor_2);
- this->add_child(PROCESSOR_3, &_processor_3);
- this->add_child(ROUTER, &_router);
- this->add_child(POOL_ROUTER, &_pool_router);
- this->add_child(GENERATOR, &_generator);
+std::vector make_po_order() {
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ std::vector order;
+ std::vector allNumbers;
- out({&_generator, artis::factory::ProductionOrderGenerator::outputs::OUT})
- >> in({&_router, artis::factory::Router::inputs::IN});
+ for (unsigned int i = 0; i < po_number; ++i) {
+ allNumbers.push_back(i);
+ }
+ while (order.size() < po_number) {
+ std::uniform_int_distribution dist(0, allNumbers.size() - 1);
+ unsigned int index = dist(gen);
- out({&_router, artis::factory::Router::outputs::OUT_P + 0})
- >> in({&_pool_router, artis::factory::PoolRouter::inputs::IN});
+ order.push_back(allNumbers[index]);
+ allNumbers.erase(allNumbers.begin() + index);
+ }
+ return order;
+}
- out({&_pool_router, artis::factory::PoolRouter::outputs::OUT})
- >> in({&_router, artis::factory::Router::inputs::IN_P + 0});
+std::vector make_capacities() {
+ std::vector capacities(machine_number - 1, -1);
- out({&_pool_router, artis::factory::PoolRouter::outputs::OUT_M + 0})
- >> in({&_processor_1, artis::factory::Processor::inputs::IN});
+ return capacities;
+}
- out({&_pool_router, artis::factory::PoolRouter::outputs::OUT_M + 1})
- >> in({&_processor_2, artis::factory::Processor::inputs::IN});
-
- out({&_pool_router, artis::factory::PoolRouter::outputs::OUT_M + 2})
- >> in({&_processor_3, artis::factory::Processor::inputs::IN});
-
- out({&_processor_1, artis::factory::Processor::outputs::OUT})
- >> in({&_pool_router, artis::factory::PoolRouter::inputs::IN_M + 0});
-
- out({&_processor_2, artis::factory::Processor::outputs::OUT})
- >> in({&_pool_router, artis::factory::PoolRouter::inputs::IN_M + 1});
-
- out({&_processor_3, artis::factory::Processor::outputs::OUT})
- >> in({&_pool_router, artis::factory::PoolRouter::inputs::IN_M + 2});
-
- out({&_router, artis::factory::Router::outputs::OUT/*_M+3*/}) // Sink
- >> in({&_sink, artis::factory::Sink::inputs::IN});
+class Evaluator {
+public:
+ Evaluator() {
+ make_flow_shop();
}
- ~OnlyOnePoolGraphManager() override = default;
+ std::vector evaluate(const Solution &solution) {
+ apply(solution);
+
+ FactoryGraphManagerParameters graph_parameters{factory};
+ artis::common::context::Context context(0, 7200);
+ artis::common::RootCoordinator<
+ artis::common::DoubleTime, artis::pdevs::Coordinator<
+ artis::common::DoubleTime, FactoryGraphManager, artis::common::NoParameters, FactoryGraphManagerParameters>
+ > rc(context, "root", artis::common::NoParameters(), graph_parameters);
+
+ rc.attachView("V", new MyView);
+ rc.switch_to_timed_observer(1);
+
+ rc.run(context);
+
+ auto sink_values = rc.observer().view("V").get("Sink:finished_po_number");
+ double t = -1;
+
+ for (const auto &v: sink_values) {
+ unsigned int n;
+
+ v.second.operator()(n);
+ if (n == po_number) {
+ t = v.first;
+ break;
+ }
+ }
+
+ double sum = 0;
+ for (unsigned int i = 0; i < machine_number - 1; ++i) {
+ auto stock_values = rc.observer().view("V").get("Stock_" + std::to_string(i) + ":entry_number");
+
+ for (const auto &v: stock_values) {
+ unsigned int n;
+
+ v.second.operator()(n);
+ if (v.first > t) {
+ break;
+ }
+ sum += n;
+ }
+ }
+ return {t, sum / (machine_number - 1) / t};
+ }
private:
- artis::pdevs::Simulator _generator;
- artis::pdevs::Simulator _router;
- artis::pdevs::Simulator _pool_router;
- artis::pdevs::Simulator _processor_1;
- artis::pdevs::Simulator _processor_2;
- artis::pdevs::Simulator _processor_3;
- artis::pdevs::Simulator _sink;
-};
-
-class PoolRouterView : public artis::factory::View {
-public:
- PoolRouterView() {
- selector("PoolRouter:waiting_po_number",
- {OnlyOnePoolGraphManager::POOL_ROUTER, artis::factory::PoolRouter::vars::WAITING_PO_NUMBER});
- selector("Generator:total_po_number",
- {OnlyOnePoolGraphManager::GENERATOR, artis::factory::ProductionOrderGenerator::vars::TOTAL_PO_NUMBER});
+ void apply(const Solution &solution) {
+ factory._generator._po_order = solution.po_order;
+ for (unsigned int i = 0; i < machine_number - 1; ++i) {
+ std::get<3>(factory._pools[0])[i]._capacity = (int)solution.capacities[i];
+ }
}
+
+ void fix_durations() {
+ for (const auto &product: factory._products) {
+ unsigned int product_id = product.first;
+ unsigned int pool_index = 0;
+
+ for (const auto &pool_machine: product.second._pool_jobs) {
+ unsigned int pool_id = pool_machine._pool_id;
+ const auto &pool = *std::find_if(factory._pools.cbegin(), factory._pools.cend(),
+ [pool_id](const auto &e) { return std::get<0>(e) == pool_id; });
+ const auto &machines = std::get<2>(pool);
+ unsigned int sequence_index = 0;
+
+ for (const auto &machine: pool_machine._machine_jobs) {
+ unsigned int machine_id = machine._machine_id;
+ const auto &m = *std::find_if(machines.cbegin(), machines.cend(),
+ [machine_id](const auto &e) { return e->machine_id == machine_id; });
+
+ if (m->machine_type == PROCESSOR) {
+ auto &M = (ProcessorParameters &) (*m);
+
+ M.product_durations[product_id] = std::static_pointer_cast(machine._durations);
+ }
+ ++sequence_index;
+ }
+ ++pool_index;
+ }
+ }
+ }
+
+ void make_flow_shop() {
+ // generator
+ factory._generator._min_send_speed_rate = 0;
+ factory._generator._max_send_speed_rate = 0;
+ factory._generator._random_seed = 62642;
+ factory._generator._po_number = po_number;
+ // products
+ for (unsigned int i = 0; i < product_number; ++i) {
+ Product product{i, {}, {PoolJob{0, {}}}, true};
+
+ for (unsigned int j = 0; j < machine_number; ++j) {
+ std::vector ins;
+ std::vector outs;
+
+ if (j > 0) {
+ ins.push_back({-1, {0, j - 1}, 1});
+ }
+ if (j < machine_number - 1) {
+ outs.push_back({-1, {0, j}, 1});
+ }
+ product._pool_jobs[0]._machine_jobs.push_back(
+ MachineJob{j, ins, outs,
+ std::make_shared(ProcessorDurations{{}, 1, processing_times[i][j], 1})});
+ }
+
+ product._pool_jobs[0]._machine_jobs.push_back(MachineJob{machine_number, {}, {}, {}});
+ factory._products[i] = product;
+ }
+ // pools
+ factory._pools.push_back({0, 0, {}, {}});
+ for (unsigned int i = 0; i < machine_number; ++i) {
+ std::map in_out;
+
+ for (const auto &product: factory._products) {
+ for (const auto &pool_job: product.second._pool_jobs) {
+ if (pool_job._pool_id == 0) {
+ for (const auto &machine_job: pool_job._machine_jobs) {
+ if (machine_job._machine_id == i) {
+ in_out[product.first] = InOut{machine_job._ins, machine_job._outs};
+ }
+ }
+ }
+ }
+ }
+ std::get<2>(factory._pools[0]).push_back(std::make_shared(ProcessorParameters{{i, 0, 0, 1},
+ {{}, 1, 3, 1},
+ in_out,
+ {}}));
+ }
+ std::get<2>(factory._pools[0]).push_back(
+ std::make_shared(SinkParameters{{machine_number, 1, 0, 1}}));
+ // intermediate stocks
+ for (unsigned int i = 0; i < machine_number - 1; ++i) {
+ std::get<3>(factory._pools[0]).push_back({i, -1});
+ }
+
+ fix_durations();
+ }
+
+ Factory factory;
};
-BOOST_AUTO_TEST_CASE(TestCase_OnePool)
-{
- artis::common::context::Context context(0, 8 * 3600); // 8h
- artis::common::RootCoordinator<
- artis::common::DoubleTime, artis::pdevs::Coordinator<
- artis::common::DoubleTime, OnlyOnePoolGraphManager, artis::common::NoParameters>
- > rc(context, "root", artis::common::NoParameters(), artis::common::NoParameters());
+int main() {
+ Evaluator evaluator;
- rc.attachView("PoolRouter", new PoolRouterView());
- rc.switch_to_timed_observer(1);
+ for (unsigned int i = 0; i < iteration_number; ++i) {
+ Solution solution{make_po_order(), make_capacities()};
- steady_clock::time_point t1 = steady_clock::now();
-
- std::cout << "OK" << std::endl;
- rc.run(context);
- std::cout << "OK" << std::endl;
-
- steady_clock::time_point t2 = steady_clock::now();
-
- duration time_span = duration_cast >(t2 - t1);
-
- std::cout << "Duration: " << time_span.count() << std::endl;
-
- artis::factory::Output output(rc.observer());
-
- output(context.begin(), context.end(), {context.begin(), 1});
-
- std::cout << artis::factory::Trace::trace().elements().filter_level_type(artis::common::LevelType::USER).to_string()
- << std::endl;
-
- BOOST_CHECK(true);
-}
+ std::cout << evaluator.evaluate(solution)[0] << " " << evaluator.evaluate(solution)[1] << std::endl;
+ }
+}
\ No newline at end of file