/** * @file FactoryGraphManager.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_HPP #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 "Stock.hpp" #include namespace artis::factory { class FactoryGraphManager : public artis::pdevs::GraphManager { public: enum sub_models { GENERATOR, ROUTER, POOL_ROUTER, MACHINE = 10000, ITEM_STOCK = 20000, STOCK = 30000 }; FactoryGraphManager(Coordinator *coordinator, const artis::common::NoParameters ¶meters, const FactoryGraphManagerParameters &graph_parameters) : artis::pdevs::GraphManager( coordinator, parameters, graph_parameters) { unsigned int machine_index = 0; 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._po_number, graph_parameters.factory._generator._po_order}; _generator = new GeneratorSimulator("G", generator_parameters); _router = new RouterSimulator("R", {graph_parameters.factory._pools.size()}); 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(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 + 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 + 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), 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 &) (*m)); _sinks.push_back(new_sink); this->add_child(MACHINE + machine_index, new_sink); // 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 break; } case COMBINER : { // TODO break; } case CONVEYOR : { // TODO break; } default: { } } } } out({_generator, artis::factory::ProductionOrderGenerator::outputs::OUT}) >> in({_router, artis::factory::Router::inputs::IN}); } private: typedef artis::pdevs::Simulator GeneratorSimulator; typedef artis::pdevs::Simulator RouterSimulator; 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; }; } #endif //ARTIS_FACTORY_FACTORY_GRAPH_MANAGER_HPP