Skip to content

Commit

Permalink
Timed event graph: remove places when a transition is removed #14
Browse files Browse the repository at this point in the history
  • Loading branch information
Lecrapouille committed May 18, 2024
1 parent 18820a4 commit c683945
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 73 deletions.
26 changes: 26 additions & 0 deletions include/TimedPetriNetEditor/PetriNet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,32 @@ class Net
//--------------------------------------------------------------------------
bool sanityArc(Node const& from, Node const& to, bool const strict) const;

//--------------------------------------------------------------------------
//! \brief Helper method removing a transition. This function does not care
//! of upstream/downstream arcs: they shall be removed.
//! For fastest deletion, we simply swap the undesired node with the
//! latest node in the container. To do that, we have to iterate from the end
//! of the container.
//--------------------------------------------------------------------------
void helperRemoveTransition(Node& node);

//--------------------------------------------------------------------------
//! \brief Helper method removing a place. This function does not care
//! of upstream/downstream arcs: they shall be removed.
//! For fastest deletion, we simply swap the undesired node with the
//! latest node in the container. To do that, we have to iterate from the end
//! of the container.
//--------------------------------------------------------------------------
void helperRemovePlace(Node& node);

//--------------------------------------------------------------------------
//! \brief Helper method removing all arcs linked to the given node.
//! Note: For fastest deletion, we simply swap the undesired arc with the
//! latest arc in the container. To do that, we have to iterate from the end
//! of the container.
//--------------------------------------------------------------------------
void helperRemoveArcFromNode(Node& node);

private:

//! \brief Type of net GRAFCET, Petri, Timed Petri ...
Expand Down
1 change: 0 additions & 1 deletion src/Editor/DearImGui/Editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1560,7 +1560,6 @@ void Editor::PetriView::onHandleInput()
auto action = std::make_unique<NetModifaction>(m_editor);
action->before(m_editor.m_net);
m_editor.m_net.removeNode(*node);
// FIXME: TimedEventGraph: supprimer aussi les places
action->after(m_editor.m_net);
m_editor.m_history.add(std::move(action));
}
Expand Down
192 changes: 120 additions & 72 deletions src/Net/PetriNet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,8 @@ bool Net::removeArc(Arc const& a)
//------------------------------------------------------------------------------
bool Net::removeArc(Node const& from, Node const& to)
{
// Supprimer les arcs qui touchent la place supprimee

size_t i = m_arcs.size();
while (i--)
{
Expand All @@ -568,105 +570,151 @@ bool Net::removeArc(Node const& from, Node const& to)
}

//------------------------------------------------------------------------------
void Net::removeNode(Node& node)
void Net::helperRemovePlace(Node& node)
{
size_t i = m_places.size();
while (i--)
{
// Found the undesired node: make the latest element take its
// location in the container. But before doing this we have to
// restore references on impacted arcs.
if (m_places[i].id == node.id)
{
// Swap element but keep the ID of the removed element
Place& pi = m_places[i];
Place& pe = m_places[m_places.size() - 1u];
if (pe.caption == pe.key)
{
m_places[i] = Place(pi.id, pi.key, pe.x, pe.y, pe.tokens);
}
else
{
m_places[i] = Place(pi.id, pe.caption, pe.x, pe.y, pe.tokens);
}
assert(m_next_place_id >= 1u);
m_next_place_id -= 1u;

// Update the references to nodes of the arc
for (auto& a: m_arcs) // TODO optim: use in/out arcs but they may not be generated
{
if (a.to.key == pe.key)
a = Arc(a.from, m_places[i], a.duration);
if (a.from.key == pe.key)
a = Arc(m_places[i], a.to, a.duration);
}

m_places.pop_back();
}
}
}

//------------------------------------------------------------------------------
void Net::helperRemoveTransition(Node& node)
{
size_t i = m_transitions.size();
while (i--)
{
// Found the undesired node: make the latest element take its
// location in the container. But before doing this we have to
// restore references on impacted arcs.
if (m_transitions[i].id == node.id)
{
Transition& ti = m_transitions[i];
Transition& te = m_transitions[m_transitions.size() - 1u];
if (te.caption == te.key)
{
m_transitions[i] = Transition(ti.id, ti.key, te.x, te.y, te.angle,
(m_type == TypeOfNet::TimedPetriNet)
? true : false);
}
else
{
m_transitions[i] = Transition(ti.id, te.caption, te.x, te.y, te.angle,
(m_type == TypeOfNet::TimedPetriNet)
? true : false);
}
assert(m_next_transition_id >= 1u);
m_next_transition_id -= 1u;

// Update the references to nodes of the arc
for (auto& a: m_arcs) // TODO optim: use in/out arcs but they may not be generated
{
if (a.to.key == te.key)
a = Arc(a.from, m_transitions[i], a.duration);
if (a.from.key == te.key)
a = Arc(m_transitions[i], a.to, a.duration);
}

m_transitions.pop_back();
}
}
}

//------------------------------------------------------------------------------
void Net::helperRemoveArcFromNode(Node& node)
{
// Remove all arcs linked to this node.
// Note: For fastest deletion, we simply swap the undesired arc with the
// latest arc in the container. To do that, we have to iterate from the end
// of the container.
size_t s = m_arcs.size();
size_t i = s;
while (i--)
{
if ((m_arcs[i].to.key == node.key) || (m_arcs[i].from.key == node.key))
{
// Found the undesired arc: make the latest element take its
// location in the container.
m_arcs[i] = m_arcs[m_arcs.size() - 1u];
m_arcs.pop_back();
}
}
}

//------------------------------------------------------------------------------
void Net::removeNode(Node& node)
{
std::vector<Node*> nodes_to_remove;
if (m_type != TypeOfNet::TimedEventGraph)
{
helperRemoveArcFromNode(node);
}
else
{
for (auto& a: m_transitions[node.id].arcsIn)
{
nodes_to_remove.push_back(&a->from);
}
for (auto& a: m_transitions[node.id].arcsOut)
{
nodes_to_remove.push_back(&a->to);
}

// Since we swap nodes inside the array before removing
// then, we have to start from greater id to lowest id.
std::sort(nodes_to_remove.begin(), nodes_to_remove.end(),
[](Node* a, Node* b) { return a->id > b-> id; });

for (auto it: nodes_to_remove)
{
helperRemoveArcFromNode(*it);
}
}

// Search and remove the node.
// Note: For fastest deletion, we simply swap the undesired node with the
// latest node in the container. To do that, we have to iterate from the end
// of the container.
if (node.type == Node::Type::Place)
{
i = m_places.size();
while (i--)
{
// Found the undesired node: make the latest element take its
// location in the container. But before doing this we have to
// restore references on impacted arcs.
if (m_places[i].id == node.id)
{
// Swap element but keep the ID of the removed element
Place& pi = m_places[i];
Place& pe = m_places[m_places.size() - 1u];
if (pe.caption == pe.key)
{
m_places[i] = Place(pi.id, pi.key, pe.x, pe.y, pe.tokens);
}
else
{
m_places[i] = Place(pi.id, pe.caption, pe.x, pe.y, pe.tokens);
}
assert(m_next_place_id >= 1u);
m_next_place_id -= 1u;

// Update the references to nodes of the arc
for (auto& a: m_arcs) // TODO optim: use in/out arcs but they may not be generated
{
if (a.to.key == pe.key)
a = Arc(a.from, m_places[i], a.duration);
if (a.from.key == pe.key)
a = Arc(m_places[i], a.to, a.duration);
}

m_places.pop_back();
}
}
helperRemovePlace(node);
}
else
{
i = m_transitions.size();
while (i--)
helperRemoveTransition(node);
for (auto it: nodes_to_remove)
{
if (m_transitions[i].id == node.id)
{
Transition& ti = m_transitions[i];
Transition& te = m_transitions[m_transitions.size() - 1u];
if (te.caption == te.key)
{
m_transitions[i] = Transition(ti.id, ti.key, te.x, te.y, te.angle,
(m_type == TypeOfNet::TimedPetriNet)
? true : false);
}
else
{
m_transitions[i] = Transition(ti.id, te.caption, te.x, te.y, te.angle,
(m_type == TypeOfNet::TimedPetriNet)
? true : false);
}
assert(m_next_transition_id >= 1u);
m_next_transition_id -= 1u;

for (auto& a: m_arcs) // TODO idem
{
if (a.to.key == te.key)
a = Arc(a.from, m_transitions[i], a.duration);
if (a.from.key == te.key)
a = Arc(m_transitions[i], a.to, a.duration);
}

m_transitions.pop_back();
}
helperRemovePlace(*it);
}
}

// Restore in arcs and out arcs for each node
generateArcsInArcsOut();
modified = true;
}

//------------------------------------------------------------------------------
Expand Down

0 comments on commit c683945

Please sign in to comment.