Skip to content

Commit bf9d701

Browse files
committed
Proper menu critical circuit
1 parent 897d479 commit bf9d701

3 files changed

Lines changed: 106 additions & 42 deletions

File tree

src/Editor/Editor.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ class Editor: public Application
119119

120120
private: // Show results from Petri algorithms
121121

122-
void showCriticalCycles();// const;
122+
void showCriticalCircuit();// const;
123123
void showDynamicLinearSystem() const;
124124
void showCounterOrDaterEquation() const;
125125
void showAdjacencyMatrices() const;
@@ -239,7 +239,7 @@ class Editor: public Application
239239

240240
//! \brief Algorithm analysis dialogs
241241
bool do_counter_or_dater = false;
242-
bool do_find_critical_cycle = false;
242+
bool do_find_critical_circuit = false;
243243
bool do_syslin = false;
244244
bool do_adjency = false;
245245

src/Editor/EditorDialogs.cpp

Lines changed: 102 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,23 @@
2424
#include "PetriNet/Algorithms.hpp"
2525
#include "PetriNet/SparseMatrix.hpp"
2626
#include "imgui/imgui.h"
27+
#include <iomanip>
28+
#include <set>
2729
#include <sstream>
2830

2931
namespace tpne {
3032

33+
namespace {
34+
35+
std::string formatTimeUnits(double const value)
36+
{
37+
std::ostringstream os;
38+
os << std::fixed << std::setprecision(2) << value;
39+
return os.str();
40+
}
41+
42+
} // namespace
43+
3144
//------------------------------------------------------------------------------
3245
void Editor::showStyleSelector()
3346
{
@@ -228,12 +241,13 @@ void Editor::showDynamicLinearSystem() const
228241
}
229242

230243
//------------------------------------------------------------------------------
231-
void Editor::showCriticalCycles()
244+
void Editor::showCriticalCircuit()
232245
{
233-
ImGui::OpenPopup("Critical Cycle");
246+
ImGui::OpenPopup("Critical circuit analysis");
234247
ImGui::SetNextWindowPos(m_states.viewport_center, ImGuiCond_Appearing,
235248
ImVec2(0.5f, 0.5f));
236-
if (ImGui::BeginPopupModal("Critical Cycle", NULL, ImGuiWindowFlags_AlwaysAutoResize))
249+
if (ImGui::BeginPopupModal("Critical circuit analysis", NULL,
250+
ImGuiWindowFlags_AlwaysAutoResize))
237251
{
238252
static CriticalCycleResult cached;
239253
static bool cached_valid = false;
@@ -250,59 +264,109 @@ void Editor::showCriticalCycles()
250264
}
251265
else
252266
{
253-
ImGui::Text("Found %zu connected components of the optimal policy", res.cycles);
267+
ImGui::TextWrapped(
268+
"Howard policy for this timed event graph. "
269+
"Highlighted arcs on the canvas form the critical circuit(s).");
270+
ImGui::Spacing();
271+
ImGui::Text("Strongly connected components: %zu", res.cycles);
272+
273+
std::set<double> const lambdas(res.durations.begin(), res.durations.end());
274+
if (!lambdas.empty())
275+
{
276+
if (lambdas.size() == 1u)
277+
{
278+
ImGui::Text("Cycle time λ: %s time units.",
279+
formatTimeUnits(*lambdas.begin()).c_str());
280+
}
281+
else
282+
{
283+
std::ostringstream os;
284+
auto it = lambdas.begin();
285+
os << formatTimeUnits(*it++);
286+
for (; it != lambdas.end(); ++it)
287+
os << ", " << formatTimeUnits(*it);
288+
ImGui::Text("Cycle times λ: %s time units.", os.str().c_str());
289+
}
290+
}
254291

255292
m_marked_arcs = res.arcs;
256293
ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
257294
if (ImGui::BeginTabBar("CriticalCycleResult", tab_bar_flags))
258295
{
259-
if (ImGui::BeginTabItem("Critical cycle"))
296+
if (ImGui::BeginTabItem("Circuit arcs"))
260297
{
261-
std::stringstream txt;
262-
if (net().type() == TypeOfNet::TimedEventGraph)
298+
ImGuiTableFlags const flags =
299+
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
300+
ImGuiTableFlags_SizingFixedFit;
301+
if (ImGui::BeginTable("CriticalCircuitArcs", 3, flags))
263302
{
303+
ImGui::TableSetupColumn("From");
304+
ImGui::TableSetupColumn("Place");
305+
ImGui::TableSetupColumn("To");
306+
ImGui::TableHeadersRow();
264307
for (size_t it = 0u; it < res.arcs.size(); it += 2u)
265308
{
266-
txt << res.arcs[it]->from.key << " -> "
267-
<< res.arcs[it + 1u]->to.key
268-
<< std::endl;
309+
ImGui::TableNextRow();
310+
ImGui::TableNextColumn();
311+
ImGui::TextUnformatted(res.arcs[it]->from.key.c_str());
312+
ImGui::TableNextColumn();
313+
ImGui::TextUnformatted(res.arcs[it]->to.key.c_str());
314+
ImGui::TableNextColumn();
315+
ImGui::TextUnformatted(res.arcs[it + 1u]->to.key.c_str());
269316
}
317+
ImGui::EndTable();
270318
}
271-
else
272-
{
273-
for (size_t it = 0u; it < res.arcs.size(); it += 2u)
274-
{
275-
txt << res.arcs[it]->from.key << " -> "
276-
<< res.arcs[it]->to.key << " -> "
277-
<< res.arcs[it + 1u]->to.key
278-
<< std::endl;
279-
}
280-
}
281-
ImGui::Text("%s", txt.str().c_str());
282319
ImGui::EndTabItem();
283320
}
284-
if (ImGui::BeginTabItem("Cycle durations"))
321+
if (ImGui::BeginTabItem("Bias"))
285322
{
286-
const auto& tr = net().transitions();
287-
std::stringstream txt;
288-
for (size_t i = 0u; i < res.durations.size(); ++i)
323+
auto const& transitions = net().transitions();
324+
ImGuiTableFlags const flags =
325+
ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
326+
ImGuiTableFlags_SizingFixedFit;
327+
if (ImGui::BeginTable("CriticalCircuitBias", 2, flags))
289328
{
290-
txt << "From " << tr[i].key << ": "
291-
<< res.durations[i]
292-
<< " units of time"
293-
<< std::endl;
329+
ImGui::TableSetupColumn("Transition");
330+
ImGui::TableSetupColumn("Bias [time units]");
331+
ImGui::TableHeadersRow();
332+
size_t const n = std::min(transitions.size(),
333+
res.eigenvector.size());
334+
for (size_t i = 0; i < n; ++i)
335+
{
336+
ImGui::TableNextRow();
337+
ImGui::TableNextColumn();
338+
ImGui::TextUnformatted(transitions[i].key.c_str());
339+
ImGui::TableNextColumn();
340+
ImGui::TextUnformatted(
341+
formatTimeUnits(res.eigenvector[i]).c_str());
342+
}
343+
ImGui::EndTable();
294344
}
295-
ImGui::Text("%s", txt.str().c_str());
296345
ImGui::EndTabItem();
297346
}
298-
if (ImGui::BeginTabItem("Eigenvector"))
347+
if (ImGui::BeginTabItem("Help"))
299348
{
300-
std::stringstream txt;
301-
for (auto const& it : res.eigenvector)
302-
{
303-
txt << it << std::endl;
304-
}
305-
ImGui::Text("%s", txt.str().c_str());
349+
float const help_wrap = ImGui::GetCursorPos().x + 420.0f;
350+
ImGui::PushTextWrapPos(help_wrap);
351+
ImGui::TextDisabled("Cycle time λ");
352+
ImGui::TextWrapped(
353+
"Max-plus eigenvalue of the timed event graph (same time "
354+
"units as arc durations). Average duration of one turn around "
355+
"a circuit in the optimal (Howard) policy—the bottleneck of "
356+
"the steady periodic regime.");
357+
ImGui::Spacing();
358+
ImGui::TextDisabled("Critical circuit");
359+
ImGui::TextWrapped(
360+
"Arcs of the optimal policy that lie on a cycle and set λ. "
361+
"They are highlighted on the canvas (listed in the "
362+
"Circuit arcs tab).");
363+
ImGui::Spacing();
364+
ImGui::TextDisabled("Bias");
365+
ImGui::TextWrapped(
366+
"Initial time offset of each transition in the optimal "
367+
"policy, in the same time units. Transitions on the same "
368+
"circuit share the same λ but may have different biases.");
369+
ImGui::PopTextWrapPos();
306370
ImGui::EndTabItem();
307371
}
308372
ImGui::EndTabBar();
@@ -313,7 +377,7 @@ void Editor::showCriticalCycles()
313377
if (ImGui::Button("OK", ImVec2(120, 0)))
314378
{
315379
ImGui::CloseCurrentPopup();
316-
m_states.do_find_critical_cycle = false;
380+
m_states.do_find_critical_circuit = false;
317381
cached_valid = false;
318382
}
319383
ImGui::EndPopup();

src/Editor/EditorMenu.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ void Editor::menuGraphEvents()
404404

405405
if (ImGui::MenuItem("Show Critical Circuit", nullptr, false))
406406
{
407-
m_states.do_find_critical_cycle = true;
407+
m_states.do_find_critical_circuit = true;
408408
}
409409
if (ImGui::MenuItem("Show (max, +) Dynamic Linear System", nullptr, false))
410410
{
@@ -479,7 +479,7 @@ void Editor::handleMenuActions()
479479
if (m_states.do_adjency) { showAdjacencyMatrices(); }
480480
if (m_states.do_counter_or_dater) { showCounterOrDaterEquation(); }
481481
if (m_states.do_syslin) { showDynamicLinearSystem(); }
482-
if (m_states.do_find_critical_cycle) { showCriticalCycles(); }
482+
if (m_states.do_find_critical_circuit) { showCriticalCircuit(); }
483483

484484
// Quit request handling
485485
if (m_states.request_quitting)

0 commit comments

Comments
 (0)