#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; } }