Patch correctif TP2

This commit is contained in:
2025-10-20 14:07:37 +02:00
parent e2d1a2da34
commit 06b1f2df82
23 changed files with 1610 additions and 455 deletions

View File

@@ -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<char>(input)), std::istreambuf_iterator<char>());
@@ -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);
}
}
}

229
test/test_optim.cpp Normal file
View File

@@ -0,0 +1,229 @@
#include <artis-star/common/RootCoordinator.hpp>
#include <artis-star/kernel/pdevs/Coordinator.hpp>
#include <artis-star/kernel/pdevs/GraphManager.hpp>
#include <iostream>
#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<unsigned int> po_order;
std::vector<unsigned int> 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<unsigned int> make_po_order() {
std::random_device rd;
std::mt19937 gen(rd());
std::vector<unsigned int> order;
std::vector<unsigned int> allNumbers;
for (unsigned int i = 0; i < po_number; ++i) {
allNumbers.push_back(i);
}
while (order.size() < po_number) {
std::uniform_int_distribution<unsigned int> dist(0, allNumbers.size() - 1);
unsigned int index = dist(gen);
order.push_back(allNumbers[index]);
allNumbers.erase(allNumbers.begin() + index);
}
return order;
}
std::vector<unsigned int> make_capacities() {
std::vector<unsigned int> capacities(machine_number - 1, -1);
return capacities;
}
class Evaluator {
public:
Evaluator() {
make_flow_shop();
}
std::vector<double> evaluate(const Solution &solution) {
apply(solution);
FactoryGraphManagerParameters graph_parameters{factory};
artis::common::context::Context<artis::common::DoubleTime> 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<ProcessorDurations>(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<In> ins;
std::vector<Out> 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>(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<unsigned int, InOut> 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>(ProcessorParameters{{i, 0, 0, 1},
{{}, 1, 3, 1},
in_out,
{}}));
}
std::get<2>(factory._pools[0]).push_back(
std::make_shared<SinkParameters>(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;
}
}

View File

@@ -1,140 +1,229 @@
#include <artis-star/common/RootCoordinator.hpp>
#include <artis-star/kernel/pdevs/Coordinator.hpp>
#include <artis-star/kernel/pdevs/GraphManager.hpp>
#include <chrono>
#include <iostream>
#define BOOST_TEST_MODULE Factory_Simple_Tests
#include "FactoryGraphManager.hpp"
#include "Machine.hpp"
#include <boost/test/unit_test.hpp>
#include <artis-star/kernel/pdevs/Simulator.hpp>
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<artis::common::DoubleTime, artis::common::NoParameters, artis::common::NoParameters> {
struct Solution {
std::vector<unsigned int> po_order;
std::vector<unsigned int> 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<artis::common::DoubleTime> *coordinator,
const artis::common::NoParameters &parameters,
const artis::common::NoParameters &graph_parameters
) : artis::pdevs::GraphManager<artis::common::DoubleTime, artis::common::NoParameters, artis::common::NoParameters>(
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<unsigned int> make_po_order() {
std::random_device rd;
std::mt19937 gen(rd());
std::vector<unsigned int> order;
std::vector<unsigned int> 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<unsigned int> 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<unsigned int> make_capacities() {
std::vector<unsigned int> 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<double> evaluate(const Solution &solution) {
apply(solution);
FactoryGraphManagerParameters graph_parameters{factory};
artis::common::context::Context<artis::common::DoubleTime> 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<artis::common::DoubleTime, artis::factory::ProductionOrderGenerator, artis::factory::ProductionOrderGeneratorParameters> _generator;
artis::pdevs::Simulator<artis::common::DoubleTime, artis::factory::Router, artis::factory::RouterParameters> _router;
artis::pdevs::Simulator<artis::common::DoubleTime, artis::factory::PoolRouter, artis::factory::PoolRouterParameters> _pool_router;
artis::pdevs::Simulator<artis::common::DoubleTime, artis::factory::Processor, artis::factory::ProcessorParameters> _processor_1;
artis::pdevs::Simulator<artis::common::DoubleTime, artis::factory::Processor, artis::factory::ProcessorParameters> _processor_2;
artis::pdevs::Simulator<artis::common::DoubleTime, artis::factory::Processor, artis::factory::ProcessorParameters> _processor_3;
artis::pdevs::Simulator<artis::common::DoubleTime, artis::factory::Sink, artis::factory::SinkParameters> _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<ProcessorDurations>(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<In> ins;
std::vector<Out> 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>(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<unsigned int, InOut> 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>(ProcessorParameters{{i, 0, 0, 1},
{{}, 1, 3, 1},
in_out,
{}}));
}
std::get<2>(factory._pools[0]).push_back(
std::make_shared<SinkParameters>(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<artis::common::DoubleTime> 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<double> time_span = duration_cast<duration<double> >(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;
}
}