Commit f8146a2c authored by Gauthier Quesnel's avatar Gauthier Quesnel
Browse files

core: split initializing

Use must initialize the default_* variables in model. These variable must be
copied into real model's variables. The default_* variables are used to
initialize and re-initialize models.
parent 312f07fc
Pipeline #10206 passed with stage
in 1 minute and 8 seconds
......@@ -32,13 +32,18 @@ run_simulation(simulation& sim,
simulation_status& st,
std::vector<float>& obs_a,
std::vector<float>& obs_b,
int& obs_id,
double* a,
double* b) noexcept
double* b,
const bool& stop) noexcept
{
double last = begin;
double last{ begin };
size_t obs_id{ 0 };
current = begin;
obs_id = 0;
if (irt::is_bad(sim.initialize(current))) {
st = simulation_status::internal_error;
return;
}
do {
if (!is_success(sim.run(current))) {
......@@ -46,13 +51,15 @@ run_simulation(simulation& sim,
return;
}
if (current - last > obs_freq) {
while (current - last > obs_freq &&
obs_a.size() > (size_t)obs_id &&
!stop) {
obs_a[obs_id] = static_cast<float>(*a);
obs_b[obs_id] = static_cast<float>(*b);
last = current;
last += obs_freq;
obs_id++;
}
} while (current < end);
} while (current < end && !stop);
st = simulation_status::success;
}
......@@ -71,7 +78,7 @@ struct editor
simulation_status st = simulation_status::uninitialized;
bool show_simulation_box = true;
double *value_a = nullptr, *value_b = nullptr;
int obs_id = 0;
bool stop = false;
std::vector<float> obs_a;
std::vector<float> obs_b;
......@@ -100,26 +107,26 @@ struct editor
auto& quantifier_a = sim.quantifier_models.alloc();
auto& quantifier_b = sim.quantifier_models.alloc();
integrator_a.current_value = 18.0;
integrator_a.default_current_value = 18.0;
quantifier_a.m_adapt_state = irt::quantifier::adapt_state::possible;
quantifier_a.m_zero_init_offset = true;
quantifier_a.m_step_size = 0.01;
quantifier_a.m_past_length = 3;
quantifier_a.default_adapt_state = irt::quantifier::adapt_state::possible;
quantifier_a.default_zero_init_offset = true;
quantifier_a.default_step_size = 0.01;
quantifier_a.default_past_length = 3;
integrator_b.current_value = 7.0;
integrator_b.default_current_value = 7.0;
quantifier_b.m_adapt_state = irt::quantifier::adapt_state::possible;
quantifier_b.m_zero_init_offset = true;
quantifier_b.m_step_size = 0.01;
quantifier_b.m_past_length = 3;
quantifier_b.default_adapt_state = irt::quantifier::adapt_state::possible;
quantifier_b.default_zero_init_offset = true;
quantifier_b.default_step_size = 0.01;
quantifier_b.default_past_length = 3;
product.input_coeffs[0] = 1.0;
product.input_coeffs[1] = 1.0;
sum_a.input_coeffs[0] = 2.0;
sum_a.input_coeffs[1] = -0.4;
sum_b.input_coeffs[0] = -1.0;
sum_b.input_coeffs[1] = 0.1;
product.default_input_coeffs[0] = 1.0;
product.default_input_coeffs[1] = 1.0;
sum_a.default_input_coeffs[0] = 2.0;
sum_a.default_input_coeffs[1] = -0.4;
sum_b.default_input_coeffs[0] = -1.0;
sum_b.default_input_coeffs[1] = 0.1;
irt_return_if_bad(
sim.alloc(sum_a, sim.adder_2_models.get_id(sum_a), "sum_a"));
......@@ -253,21 +260,25 @@ show_model_dynamics(simulation& sim, model& mdl)
break;
case dynamics_type::integrator: {
auto& dyn = sim.integrator_models.get(mdl.id);
imnodes::BeginOutputAttribute(get_out(dyn.y[0]));
ImGui::TextUnformatted("x_dot");
imnodes::EndAttribute();
imnodes::BeginInputAttribute(get_in(dyn.x[0]));
ImGui::TextUnformatted("quanta");
imnodes::EndAttribute();
imnodes::BeginInputAttribute(get_in(dyn.x[1]));
ImGui::TextUnformatted("x_dot");
imnodes::EndAttribute();
imnodes::BeginInputAttribute(get_in(dyn.x[2]));
ImGui::TextUnformatted("reset");
imnodes::EndAttribute();
ImGui::PushItemWidth(120.0f);
ImGui::InputDouble("value", &dyn.current_value);
ImGui::InputDouble("value", &dyn.default_current_value);
ImGui::InputDouble("reset", &dyn.default_reset_value);
ImGui::PopItemWidth();
imnodes::BeginInputAttribute(get_in(dyn.x[1]));
const float text_width = ImGui::CalcTextSize("prod").x;
ImGui::Indent(120.f + ImGui::CalcTextSize("coeff-0").x - text_width);
ImGui::TextUnformatted("x_dot");
imnodes::BeginOutputAttribute(get_out(dyn.y[0]));
const float text_width = ImGui::CalcTextSize("x").x;
ImGui::Indent(120.f + ImGui::CalcTextSize("quanta").x - text_width);
ImGui::TextUnformatted("x");
imnodes::EndAttribute();
} break;
case dynamics_type::quantifier: {
......@@ -277,8 +288,8 @@ show_model_dynamics(simulation& sim, model& mdl)
imnodes::EndAttribute();
ImGui::PushItemWidth(120.0f);
ImGui::InputDouble("quantum", &dyn.m_step_size);
ImGui::SliderInt("archive length", &dyn.m_past_length, 3, 100);
ImGui::InputDouble("quantum", &dyn.default_step_size);
ImGui::SliderInt("archive length", &dyn.default_past_length, 3, 100);
ImGui::PopItemWidth();
imnodes::BeginOutputAttribute(get_out(dyn.y[0]));
......@@ -295,8 +306,8 @@ show_model_dynamics(simulation& sim, model& mdl)
imnodes::EndAttribute();
ImGui::PushItemWidth(120.0f);
ImGui::InputDouble("coeff-0", &dyn.input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.input_coeffs[1]);
ImGui::InputDouble("coeff-0", &dyn.default_input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.default_input_coeffs[1]);
ImGui::PopItemWidth();
imnodes::BeginOutputAttribute(get_out(dyn.y[0]));
......@@ -318,9 +329,9 @@ show_model_dynamics(simulation& sim, model& mdl)
imnodes::EndAttribute();
ImGui::PushItemWidth(120.0f);
ImGui::InputDouble("coeff-0", &dyn.input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.input_coeffs[1]);
ImGui::InputDouble("coeff-2", &dyn.input_coeffs[2]);
ImGui::InputDouble("coeff-0", &dyn.default_input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.default_input_coeffs[1]);
ImGui::InputDouble("coeff-2", &dyn.default_input_coeffs[2]);
ImGui::PopItemWidth();
imnodes::BeginOutputAttribute(get_out(dyn.y[0]));
......@@ -345,10 +356,10 @@ show_model_dynamics(simulation& sim, model& mdl)
imnodes::EndAttribute();
ImGui::PushItemWidth(120.0f);
ImGui::InputDouble("coeff-0", &dyn.input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.input_coeffs[1]);
ImGui::InputDouble("coeff-2", &dyn.input_coeffs[2]);
ImGui::InputDouble("coeff-2", &dyn.input_coeffs[3]);
ImGui::InputDouble("coeff-0", &dyn.default_input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.default_input_coeffs[1]);
ImGui::InputDouble("coeff-2", &dyn.default_input_coeffs[2]);
ImGui::InputDouble("coeff-2", &dyn.default_input_coeffs[3]);
ImGui::PopItemWidth();
imnodes::BeginOutputAttribute(get_out(dyn.y[0]));
......@@ -367,8 +378,8 @@ show_model_dynamics(simulation& sim, model& mdl)
imnodes::EndAttribute();
ImGui::PushItemWidth(120.0f);
ImGui::InputDouble("coeff-0", &dyn.input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.input_coeffs[1]);
ImGui::InputDouble("coeff-0", &dyn.default_input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.default_input_coeffs[1]);
ImGui::PopItemWidth();
imnodes::BeginOutputAttribute(get_out(dyn.y[0]));
......@@ -390,9 +401,9 @@ show_model_dynamics(simulation& sim, model& mdl)
imnodes::EndAttribute();
ImGui::PushItemWidth(120.0f);
ImGui::InputDouble("coeff-0", &dyn.input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.input_coeffs[1]);
ImGui::InputDouble("coeff-2", &dyn.input_coeffs[2]);
ImGui::InputDouble("coeff-0", &dyn.default_input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.default_input_coeffs[1]);
ImGui::InputDouble("coeff-2", &dyn.default_input_coeffs[2]);
ImGui::PopItemWidth();
imnodes::BeginOutputAttribute(get_out(dyn.y[0]));
......@@ -417,10 +428,10 @@ show_model_dynamics(simulation& sim, model& mdl)
imnodes::EndAttribute();
ImGui::PushItemWidth(120.0f);
ImGui::InputDouble("coeff-0", &dyn.input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.input_coeffs[1]);
ImGui::InputDouble("coeff-2", &dyn.input_coeffs[2]);
ImGui::InputDouble("coeff-3", &dyn.input_coeffs[3]);
ImGui::InputDouble("coeff-0", &dyn.default_input_coeffs[0]);
ImGui::InputDouble("coeff-1", &dyn.default_input_coeffs[1]);
ImGui::InputDouble("coeff-2", &dyn.default_input_coeffs[2]);
ImGui::InputDouble("coeff-3", &dyn.default_input_coeffs[3]);
ImGui::PopItemWidth();
imnodes::BeginOutputAttribute(get_out(dyn.y[0]));
......@@ -445,7 +456,7 @@ show_model_dynamics(simulation& sim, model& mdl)
auto& dyn = sim.constant_models.get(mdl.id);
ImGui::PushItemWidth(120.0f);
ImGui::InputDouble("value", &dyn.value);
ImGui::InputDouble("value", &dyn.default_value);
ImGui::PopItemWidth();
imnodes::BeginOutputAttribute(get_out(dyn.y[0]));
......@@ -520,22 +531,22 @@ show_editor(const char* editor_name, editor& ed)
if (!ImGui::Begin("Simulation box", &ed.show_simulation_box)) {
ImGui::End();
} else {
ImGui::InputDouble("Begin", &ed.simulation_begin);
ImGui::InputDouble("End", &ed.simulation_end);
ImGui::SliderInt(
"Observations", &ed.simulation_observation_number, 1, 10000);
if (ed.st != simulation_status::running) {
if (ed.simulation_thread.joinable()) {
ed.simulation_thread.join();
ed.st = simulation_status::success;
}
ImGui::InputDouble("Begin", &ed.simulation_begin);
ImGui::InputDouble("End", &ed.simulation_end);
ImGui::SliderInt(
"Observations", &ed.simulation_observation_number, 1, 10000);
if (ImGui::Button("Start")) {
ed.st = simulation_status::running;
ed.obs_a.resize(ed.simulation_observation_number, 0.0);
ed.obs_b.resize(ed.simulation_observation_number, 0.0);
ed.obs_id = 0;
ed.stop = false;
ed.simulation_thread = std::thread(
&run_simulation,
......@@ -548,23 +559,24 @@ show_editor(const char* editor_name, editor& ed)
std::ref(ed.st),
std::ref(ed.obs_a),
std::ref(ed.obs_b),
std::ref(ed.obs_id),
ed.value_a,
ed.value_b);
ed.value_b,
std::cref(ed.stop));
}
}
if (ed.st == simulation_status::success ||
ed.st == simulation_status::running) {
ImGui::Text("Begin: %g", ed.simulation_begin);
ImGui::Text("End: %g", ed.simulation_end);
ImGui::Text("Current: %g", ed.simulation_current);
ImGui::Text("Observations: %d", ed.simulation_observation_number);
if (ImGui::Button("Stop"))
ed.stop = true;
const double duration = ed.simulation_end - ed.simulation_begin;
const double elapsed = ed.simulation_current - ed.simulation_begin;
const double fraction = elapsed / duration;
ImGui::ProgressBar(static_cast<float>(fraction));
ImGui::PlotLines("A",
ed.obs_a.data(),
ed.simulation_observation_number,
......@@ -573,6 +585,7 @@ show_editor(const char* editor_name, editor& ed)
-5.0,
+30.0,
ImVec2(0, 50));
ImGui::PlotLines("B",
ed.obs_b.data(),
ed.simulation_observation_number,
......
......@@ -2267,6 +2267,13 @@ public:
return status::success;
}
void clear()
{
m_size = 0;
max_size = 0;
root = nullptr;
}
handle insert(time tn, model_id id) noexcept
{
node* new_node = &nodes[max_size++];
......@@ -2576,17 +2583,33 @@ struct adder
model_id id;
input_port_id x[PortNumber];
output_port_id y[1];
double input_coeffs[PortNumber] = { 0 };
double values[PortNumber] = { 0 };
time sigma;
status initialize(data_array<message, message_id>& init_messages) noexcept
double default_values[PortNumber];
double default_input_coeffs[PortNumber];
double values[PortNumber];
double input_coeffs[PortNumber];
adder() noexcept
{
std::fill_n(std::begin(values),
std::fill_n(std::begin(default_values),
PortNumber,
1.0 / static_cast<double>(PortNumber));
std::fill_n(std::begin(default_input_coeffs),
PortNumber,
0.0);
}
status initialize(data_array<message, message_id>& init_messages) noexcept
{
std::copy_n(std::begin(default_values), PortNumber, std::begin(values));
std::copy_n(std::begin(default_input_coeffs),
PortNumber,
std::begin(input_coeffs));
sigma = time_domain<time>::infinity;
return status::success;
......@@ -2646,14 +2669,28 @@ struct mult
model_id id;
input_port_id x[PortNumber];
output_port_id y[1];
time sigma;
double default_values[PortNumber];
double default_input_coeffs[PortNumber];
double input_coeffs[PortNumber] = { 0 };
double values[PortNumber];
time sigma;
double input_coeffs[PortNumber];
mult() noexcept
{
std::fill_n(std::begin(default_values), PortNumber, 1.0);
std::fill_n(std::begin(default_input_coeffs), PortNumber, 0.0);
}
status initialize(data_array<message, message_id>& init_messages) noexcept
{
std::fill_n(std::begin(values), PortNumber, 1.0);
std::copy_n(
std::begin(default_values), PortNumber, std::begin(values));
std::copy_n(std::begin(default_input_coeffs),
PortNumber,
std::begin(input_coeffs));
sigma = time_domain<time>::infinity;
......@@ -2716,8 +2753,8 @@ struct counter
{
model_id id;
input_port_id x[1];
long unsigned number;
time sigma;
long unsigned number;
status initialize(
data_array<message, message_id>& /*init_messages*/) noexcept
......@@ -2758,7 +2795,7 @@ struct generator
status initialize(
data_array<message, message_id>& /*init_messages*/) noexcept
{
sigma = 1;
sigma = 1.0;
return status::success;
}
......@@ -2778,12 +2815,17 @@ struct constant
model_id id;
output_port_id y[1];
time sigma;
double default_value = 0.0;
double value = 0.0;
status initialize(data_array<message, message_id>& init_messages) noexcept
{
sigma = time_domain<time>::zero;
value = default_value;
return status::success;
}
......@@ -2813,10 +2855,15 @@ struct time_func
model_id id;
output_port_id y[1];
time sigma;
double(*default_f)(double);
double value;
double (*f)(double);
double (*f)(double) = nullptr;
status initialize(data_array<message, message_id>& init_messages) noexcept
{
f = default_f;
sigma = 1.0;
value = sigma;
return status::success;
......@@ -2843,16 +2890,20 @@ struct time_func
return status::success;
}
};
struct cross
{
model_id id;
input_port_id x[3];
output_port_id y[1];
time sigma;
double default_threshold = 0.0;
double threshold;
double value = threshold - 1.0;
double if_value = 0.0;
double else_value = 0.0;
double value;
double if_value;
double else_value;
enum port_name
{
......@@ -2863,13 +2914,16 @@ struct cross
status initialize(data_array<message, message_id>& init_messages) noexcept
{
threshold = default_threshold;
value = threshold - 1.0;
if_value = 0.0;
else_value = 0.0;
sigma = time_domain<time>::zero;
return status::success;
}
status transition(data_array<input_port, input_port_id>& input_ports,
time /*t*/,
time /*e*/,
......@@ -2948,9 +3002,9 @@ struct none
struct integrator
{
model_id id;
time sigma = time_domain<time>::zero;
input_port_id x[3];
output_port_id y[1];
time sigma = time_domain<time>::zero;
enum port_name
{
......@@ -2968,21 +3022,33 @@ struct integrator
running
};
double default_current_value = 0.0;
double default_reset_value = 0.0;
flat_double_list<record> archive;
double current_value = 0.0;
double reset_value = 0.0;
double up_threshold = 0.0;
double down_threshold = 0.0;
double last_output_value = 0.0;
double current_value = 0.0;
double expected_value = 0.0;
bool reset = false;
double reset_value;
flat_double_list<record> archive;
state st = state::init;
status initialize(data_array<message, message_id>& /*init*/) noexcept
{
sigma = time_domain<time>::zero;
current_value = default_current_value;
reset_value = default_reset_value;
up_threshold = 0.0;
down_threshold = 0.0;
last_output_value = 0.0;
expected_value = 0.0;
reset = false;
archive.clear();
st = state::init;
sigma = time_domain<time>::zero;
return status::success;
}
......@@ -3099,7 +3165,6 @@ struct integrator
return status::success;
}
private:
status ta() noexcept
{
if (st == state::running) {
......@@ -3170,9 +3235,9 @@ private:
struct quantifier
{
model_id id;
time sigma = time_domain<time>::infinity;
input_port_id x[1];
output_port_id y[1];
time sigma = time_domain<time>::infinity;
enum class state
{
......@@ -3188,38 +3253,40 @@ struct quantifier
done
};
enum class direction
{
up,
down
};
double default_step_size = 0.0;
int default_past_length = 3;
adapt_state default_adapt_state = adapt_state::possible;
bool default_zero_init_offset = false;
flat_double_list<record> archive;
double m_upthreshold = 0.0;
double m_downthreshold = 0.0;
double m_offset = 0.0;
double m_step_size = 0.0;
int m_step_number = 0;
int m_past_length = 0;
flat_double_list<record> archive;
bool m_zero_init_offset = false;
state m_state = state::init;
adapt_state m_adapt_state = adapt_state::possible;
enum init_port_name
{
i_allow_offsets,
i_zero_init_offset,
i_quantum,
i_archive_length
};
status initialize(data_array<message, message_id>& init_messages) noexcept
{
m_step_size = default_step_size;
m_past_length = default_past_length;
m_zero_init_offset = default_zero_init_offset;
m_adapt_state = default_adapt_state;
m_upthreshold = 0.0;
m_downthreshold = 0.0;
m_offset = 0.0;
m_step_number = 0;
archive.clear();
m_state = state::init;
irt_return_if_fail(m_step_size > 0, status::model_quantifier_bad_quantum_parameter);
......@@ -3497,6 +3564,12 @@ public:
return status::success;
}
void clear()
{
m_heap.clear();
m_list.clear();
}
/**
* @brief Insert a newly model into the scheduller.
*/
......@@ -3696,27 +3769,6 @@ struct simulation
else
mdl.type = dynamics_type::time_func;
if constexpr (is_detected_v<initialize_function_t, Dynamics>) {
//if constexpr (is_detected_v<has_init_port_t, Dynamics>) {
// /* Combine all init_message from the init_messages
// structure where the model equals mdl_id. */
// init_message* msg = nullptr;
// while (init_messages.next(msg)) {
// auto it = std::find_if(std::begin(msg->models),
// std::end(msg->models),
// [mdl_id](const auto& pair) {
// return pair.first == mdl_id;
// });
// if (it != std::end(msg->models))
// dynamics.init[it->second] = msg->msg;