From 33319d9b443ec35ae59e19282b77efc7e101f02c Mon Sep 17 00:00:00 2001
From: Mahmoud Bentriou <mahmoud.bentriou@centralesupelec.fr>
Date: Sun, 29 Nov 2020 19:10:57 +0100
Subject: [PATCH] Small improvment perf for next_state! of LHA

---
 core/lha.jl   | 90 ++++++++++++++++++++++++++++-----------------------
 core/model.jl |  4 +--
 2 files changed, 51 insertions(+), 43 deletions(-)

diff --git a/core/lha.jl b/core/lha.jl
index e6f6680..3d670e3 100644
--- a/core/lha.jl
+++ b/core/lha.jl
@@ -33,9 +33,44 @@ function init_state(A::LHA, x0::Vector{Int}, t0::Float64)
     return S0
 end
 
+function _find_edge_candidates!(edge_candidates::Vector{Edge}, current_loc::Location, 
+                                A::LHA, Snplus1::StateLHA)
+     
+    for loc in A.l_loc
+        tuple_edges = (current_loc, loc)
+        if haskey(A.map_edges, tuple_edges)
+            for edge in A.map_edges[tuple_edges]
+                if edge.check_constraints(A, Snplus1)
+                    push!(edge_candidates, edge)
+                end
+            end
+        end
+    end
+end
+
+function _get_edge_index(edge_candidates::Vector{Edge}, first_round::Bool, 
+                         detected_event::Bool, tr_nplus1::Transition)
+    ind_edge = 0
+    bool_event = detected_event
+    for i in eachindex(edge_candidates)
+        edge = edge_candidates[i]
+        if edge.transitions[1] == nothing
+            return (i, bool_event)
+        end
+        if first_round || !detected_event
+            if (length(edge.transitions) == 1 && tr_nplus1 != nothing && edge.transitions[1] == "ALL") || 
+                (tr_nplus1 in edge.transitions)
+                ind_edge = i
+                bool_event = true
+            end
+        end
+    end
+    return (ind_edge, bool_event)
+end
+
 function next_state!(Snplus1::StateLHA, A::LHA, 
                     xnplus1::Vector{Int}, tnplus1::Float64, tr_nplus1::Transition, 
-                    Sn::StateLHA; verbose = false)
+                    Sn::StateLHA; verbose::Bool = false)
     for i in eachindex(Snplus1.l_var)
         Snplus1.l_var[i] += (A.l_flow[Sn.loc])[i]*(tnplus1 - Sn.time) 
     end
@@ -43,61 +78,34 @@ function next_state!(Snplus1::StateLHA, A::LHA,
 
     # En fait d'apres observation de Cosmos, après qu'on ait lu la transition on devrait stop.
     edge_candidates = Edge[]
-    tuple_candidates = Tuple{Location, Location}[]
-    first_round = true
-    detected_event = (tr_nplus1 == nothing) ? true : false
+    first_round::Bool = true
+    detected_event::Bool = (tr_nplus1 == nothing) ? true : false
     turns = 1
     while first_round || !detected_event || length(edge_candidates) > 0
-        edge_candidates = Edge[]
-        tuple_candidates = Tuple{Location,Location}[]
+        edge_candidates = empty!(edge_candidates)
         current_loc = Snplus1.loc
-        if verbose
-            @show turns
-        end
+        if verbose @show turns end
         # Save all edges that satisfies transition predicate (synchronous or autonomous)
-        for loc in A.l_loc
-            tuple_edges = (current_loc, loc)
-            if haskey(A.map_edges, tuple_edges)
-                for edge in A.map_edges[tuple_edges]
-                    if edge.check_constraints(A, Snplus1)
-                        push!(edge_candidates, edge)
-                        push!(tuple_candidates, tuple_edges)
-                    end
-                end
-            end
-        end
+        _find_edge_candidates!(edge_candidates, current_loc, A, Snplus1)
         # Search the one we must chose
-        ind_edge = 0
-        for (i, edge) in enumerate(edge_candidates)
-            if edge.transitions[1] == nothing
-                ind_edge = i
-                break
-            end
-            if first_round || !detected_event
-                if (length(edge.transitions) == 1 && tr_nplus1 != nothing && edge.transitions[1] == "ALL") || 
-                    (tr_nplus1 in edge.transitions)
-                    detected_event = true
-                    ind_edge = i
-                end
-            end
-        end
+        ind_edge, detected_event = _get_edge_index(edge_candidates, first_round, detected_event, tr_nplus1)
         # Update the state with the chosen one (if it exists)
         if ind_edge > 0
             edge_candidates[ind_edge].update_state!(A, Snplus1, xnplus1)
             # Should add something like if edges_candidates[ind_edge].transition != nohting break end ??
         end
+        if ind_edge == 0 break end
         if verbose
-            @show first_round, detected_event
-            @show tnplus1, tr_nplus1, xnplus1
+            @show first_round detected_event
+            @show tnplus1 tr_nplus1 xnplus1
             @show ind_edge
             @show edge_candidates
             @show tuple_candidates
             @show Snplus1
         end
-        if ind_edge == 0 break end
         # For debug
-        if turns > 10
-            println("Turns, Bad behavior of region2 automaton")
+        if turns > 100
+            println("Number of turns in next_state! is suspicious")
             @show first_round, detected_event
             @show length(edge_candidates)
             @show tnplus1, tr_nplus1, xnplus1
@@ -105,14 +113,14 @@ function next_state!(Snplus1::StateLHA, A::LHA,
             for edge in edge_candidates
                 @show edge.check_constraints(A, Snplus1)
             end
-            error("Unpredicted behavior automaton F v2")
+            error("Unpredicted behavior automaton")
         end
         turns += 1
         first_round = false
     end
 end
 
-# For debug purposes
+# For tests purposes
 function read_trajectory(A::LHA, σ::Trajectory; verbose = false)
     A_new = LHA(A, (σ.m)._map_obs_var_idx)
     l_t = times(σ)
diff --git a/core/model.jl b/core/model.jl
index c1e39b1..eb95321 100644
--- a/core/model.jl
+++ b/core/model.jl
@@ -46,7 +46,7 @@ function simulate(m::ContinuousTimeModel; p::Union{Nothing,AbstractVector{Float6
     transitions[1] = nothing
     # Values at time n
     n = 1
-    xn = m.x0 # View for type stability
+    xn = m.x0 
     tn = m.t0 
     # at time n+1
     isabsorbing::Bool = m.isabsorbing(p_sim,xn)
@@ -144,7 +144,7 @@ function simulate(product::SynchronizedModel; p::Union{Nothing,AbstractVector{Fl
     S0 = init_state(A, m.x0, m.t0)
     # Values at time n
     n = 1
-    xn = m.x0 # View for type stability
+    xn = m.x0 
     tn = m.t0 
     Sn = copy(S0)
     isabsorbing::Bool = m.isabsorbing(p_sim,xn)
-- 
GitLab