Bläddra i källkod

added HOmod topo

Snej69420 5 månader sedan
förälder
incheckning
f2a2b9f138
3 ändrade filer med 156 tillägg och 63 borttagningar
  1. 1 1
      benchmarks/Agents/Manifest.toml
  2. 147 55
      benchmarks/Agents/Topologies.jl
  3. 8 7
      benchmarks/Agents/main.jl

+ 1 - 1
benchmarks/Agents/Manifest.toml

@@ -200,7 +200,7 @@ version = "4.1.1"
 
 [[deps.DEVS2Agents]]
 deps = ["Agents", "ArgParse", "DataStructures", "Test"]
-git-tree-sha1 = "448a1c05c22a2073ddb079af04ea5166f68e45a9"
+git-tree-sha1 = "9b45c843073814888b867d3995fd9fc1f571bbdd"
 repo-rev = "main"
 repo-url = "git@github.com:Snej69420/DEVS2Agents.git"
 uuid = "073a0784-fe80-4c04-b3c3-fb0686668e26"

+ 147 - 55
benchmarks/Agents/Topologies.jl

@@ -1,53 +1,45 @@
+@enum Structure LI HI HO HOmod
 
-@enum Structure LI HI HO
-
-function build_devstone(type::Structure, name::String, depth::Int, width::Int, int_delay::Float64, ext_delay::Float64, stats::Bool=false)
-    if depth < 1 || width < 1
-        error("Invalid depth or width")
-    end
-
-    top_model = CoupledDEVS(name)
-    has_out_port = type == HI || type == HO
+# Port Config
+function setup_ports!(top_model::CoupledDEVS, type::Structure)
+    has_out_port = type in (HI, HO, HOmod)
 
     add_in_port!(top_model, :i_in)
     if has_out_port
         add_out_port!(top_model, :o_out)
     end
-    if type == HO
+    if type in (HO, HOmod)
         add_in_port!(top_model, :i_in2)
+    end
+    if type == HO
         add_out_port!(top_model, :o_out2)
     end
 
-    # Leaf
-    if depth == 1
-        p_time = round(rand() + 1.0, digits=3)
-        atom = add_submodel!(top_model, "Atomic_0_0", DelayedAtomic;
-            inbox=(; i_in=Union{Generate, A2A}[]),
-            out_ports=has_out_port ? Set([:o_out]) : Set{Symbol}(),
-            int_delay=int_delay, ext_delay=ext_delay, prep_time=p_time,
-            has_out_port, stats=stats)
-
-        connect!(top_model, self.i_in, atom.i_in)
-        if has_out_port
-            connect!(top_model, atom.o_out, self.o_out)
-        end
+    return has_out_port
+end
 
-        return top_model
-    end
-
-    child_name = "Coupled_$(depth - 1)"
-    child_coupled = build_devstone(type, child_name, depth - 1, width, int_delay, ext_delay, stats)
-    child = add_submodel!(top_model, child_name, child_coupled)
+# Depth 1
+function build_leaf_node(name::String, type::Structure, int_delay::Float64, ext_delay::Float64, stats::Bool)
+    top_model = CoupledDEVS(name)
+    has_out_port = setup_ports!(top_model, type)
 
-    connect!(top_model, self.i_in, child.i_in)
-    if type == HO
-        connect!(top_model, self.i_in, child.i_in2)
-    end
+    p_time = round(rand() + 1.0, digits=3)
+    atom = add_submodel!(top_model, "Atomic_0_0", DelayedAtomic;
+        inbox=(; i_in=Union{Generate, A2A}[]),
+        out_ports=has_out_port ? Set([:o_out]) : Set{Symbol}(),
+        int_delay=int_delay, ext_delay=ext_delay, prep_time=p_time,
+        has_out_port=has_out_port, stats=stats)
 
+    connect!(top_model, self.i_in, atom.i_in)
     if has_out_port
-        connect!(top_model, child.o_out, self.o_out)
+        connect!(top_model, atom.o_out, self.o_out)
     end
 
+    return top_model
+end
+
+# Create Atomics (LI, HI, HO)
+function build_atomics!(top_model::CoupledDEVS, depth::Int, width::Int, int_delay::Float64, ext_delay::Float64, has_out_port::Bool, stats::Bool)
     width_models = ModelRef[]
     for idx in 0:(width - 2)
         p_time = 1.0 - round(rand() * (0.5 / width) + (idx / width), digits=3)
@@ -61,36 +53,136 @@ function build_devstone(type::Structure, name::String, depth::Int, width::Int, i
 
         push!(width_models, atom)
     end
+    return width_models
+end
 
-    if type == LI
-        for atom in width_models
-            connect!(top_model, self.i_in, atom.i_in)
-        end
+# Routing
+function route_LI!(top_model::CoupledDEVS, width_models::Vector{ModelRef})
+    for atom in width_models
+        connect!(top_model, self.i_in, atom.i_in)
+    end
+end
+
+function route_HI!(top_model::CoupledDEVS, width_models::Vector{ModelRef})
+    for atom in width_models
+        connect!(top_model, self.i_in, atom.i_in)
+    end
+    for i in 1:(length(width_models) - 1)
+        connect!(top_model, width_models[i].o_out, width_models[i + 1].i_in)
+    end
+end
+
+function route_HO!(top_model::CoupledDEVS, width_models::Vector{ModelRef})
+    for i in 1:(length(width_models) - 1)
+        curr_atom = width_models[i]
+        next_atom = width_models[i + 1]
+
+        connect!(top_model, curr_atom.o_out, next_atom.i_in)
+        connect!(top_model, self.i_in2, curr_atom.i_in)
+        connect!(top_model, curr_atom.o_out, self.o_out2)
+    end
 
-    elseif type == HI
-        for atom in width_models
-            connect!(top_model, self.i_in, atom.i_in)
+    if !isempty(width_models)
+        last_atom = width_models[end]
+        connect!(top_model, self.i_in2, last_atom.i_in)
+        connect!(top_model, last_atom.o_out, self.o_out2)
+    end
+end
+
+# Create HOmod Structure---
+function build_HOmod!(top_model::CoupledDEVS, child::ModelRef, depth::Int, width::Int, int_delay::Float64, ext_delay::Float64, stats::Bool)
+    if width < 2
+        return
+    end
+
+    atomics = Dict{Int, Vector{ModelRef}}()
+
+    # create grid
+    for i in 0:(width - 1)
+        atomics[i] = ModelRef[]
+        min_row_idx = i < 2 ? 0 : i - 1
+
+        for j in min_row_idx:(width - 2)
+            atomic_name = "A$(i)_$(j)"
+
+            atom = add_submodel!(top_model, atomic_name, DelayedAtomic;
+                inbox=(; i_in=Union{Generate, A2A}[]),
+                out_ports=Set([:o_out]),
+                int_delay=int_delay, ext_delay=ext_delay, prep_time=1.0,
+                has_out_port=true, stats=stats)
+
+            push!(atomics[i], atom)
         end
+    end
 
-        # Chain atomics
-        for i in 1:(length(width_models) - 1)
-            connect!(top_model, width_models[i].o_out, width_models[i + 1].i_in)
+    for atom in atomics[0]
+        connect!(top_model, self.i_in2, atom.i_in)
+    end
+    for i in 1:(width - 1)
+        if !isempty(atomics[i])
+            connect!(top_model, self.i_in2, atomics[i][1].i_in)
         end
+    end
+
+    for atom in atomics[0]
+        connect!(top_model, atom.o_out, child.i_in2)
+    end
 
-    elseif type == HO
-        for i in 1:(length(width_models) - 1)
-            curr_atom = width_models[i]
-            next_atom = width_models[i + 1]
+    if haskey(atomics, 1) && haskey(atomics, 0)
+        for atom1 in atomics[1]
+            for atom0 in atomics[0]
+                connect!(top_model, atom1.o_out, atom0.i_in)
+            end
+        end
+    end
 
-            connect!(top_model, curr_atom.o_out, next_atom.i_in)
-            connect!(top_model, self.i_in2, curr_atom.i_in)
-            connect!(top_model, curr_atom.o_out, self.o_out2)
+    for i in 2:(width - 1)
+        for j in 1:length(atomics[i])
+            connect!(top_model, atomics[i][j].o_out, atomics[i-1][j+1].i_in)
         end
+    end
+end
+
+
+function build_devstone(type::Structure, name::String, depth::Int, width::Int, int_delay::Float64, ext_delay::Float64, stats::Bool=false)
+    if depth < 1 || width < 1
+        error("Invalid depth or width")
+    end
+
+    # Base Case
+    if depth == 1
+        return build_leaf_node(name, type, int_delay, ext_delay, stats)
+    end
+
+    # Recursive
+    top_model = CoupledDEVS(name)
+    has_out_port = setup_ports!(top_model, type)
+
+    child_name = "Coupled_$(depth - 1)"
+    child_coupled = build_devstone(type, child_name, depth - 1, width, int_delay, ext_delay, stats)
+    child = add_submodel!(top_model, child_name, child_coupled)
+
+    # Connect Parent to Child
+    connect!(top_model, self.i_in, child.i_in)
+    if type == HO
+        connect!(top_model, self.i_in, child.i_in2)
+    end
+    if has_out_port
+        connect!(top_model, child.o_out, self.o_out)
+    end
 
-        if length(width_models) > 0
-            last_atom = width_models[end]
-            connect!(top_model, self.i_in2, last_atom.i_in)
-            connect!(top_model, last_atom.o_out, self.o_out2)
+    # Sub-topology Generation & Routing
+    if type == HOmod
+        build_HOmod!(top_model, child, depth, width, int_delay, ext_delay, stats)
+    else
+        width_models = build_atomics!(top_model, depth, width, int_delay, ext_delay, has_out_port, stats)
+
+        if type == LI
+            route_LI!(top_model, width_models)
+        elseif type == HI
+            route_HI!(top_model, width_models)
+        elseif type == HO
+            route_HO!(top_model, width_models)
         end
     end
 

+ 8 - 7
benchmarks/Agents/main.jl

@@ -8,15 +8,15 @@ include("DelayedAtomic.jl")
 include("Generator.jl")
 include("Topologies.jl")
 
-function build_environment(type::Structure, devstone_model::CoupledDEVS, gen_period::Float64, num_outputs::Int)
+function build_environment(type::Structure, devstone_model::CoupledDEVS, gen_period::Float64, output::Int)
     env = CoupledDEVS("DEVStoneEnvironment")
     add_submodel!(env, :generator, Generator;
         out_ports=Set([:o_out]),
-        num_outputs = num_outputs, period = gen_period, cycles = 1)
+        output = output, period = gen_period, cycles = 1)
     add_submodel!(env, :devstone, devstone_model)
 
     connect!(env, ModelRef(:generator).o_out, ModelRef(:devstone).i_in)
-    if type == HO
+    if type == HO || type == HOmod
         connect!(env, ModelRef(:generator).o_out, ModelRef(:devstone).i_in2)
     end
     return env
@@ -68,9 +68,9 @@ function parse_commandline()
             help = "Enables and print model traces to the console"
             action = :store_true
         "--model-structure", "--ms"
-            help = "List of structures to run (e.g., LI HI HO)"
+            help = "List of structures to run (e.g., LI HI HO HOmod)"
             nargs = '*'
-            default = ["LI", "HI", "HO"]
+            default = ["LI", "HI", "HO", "HOmod"]
     end
 
     return parse_args(s)
@@ -90,7 +90,8 @@ function run_single_simulation(topology_type::Structure, type_str::String, depth
 
     # Setup
     AgentUnion = Union{DelayedAtomic, Generator}
-    model = compile_devs(env, (UniversalEvent, ); logging=false)
+    model = compile_devs(env; logging)
+#     println("Number of Atomic: $(nagents(model))")
     engine_setup_time = time()
 
     if profile
@@ -132,7 +133,7 @@ function main()
     mkpath(time_dir)
 
     # Convert string inputs to Enum
-    struct_map = Dict("LI" => LI, "HI" => HI, "HO" => HO)
+    struct_map = Dict("LI" => LI, "HI" => HI, "HO" => HO, "HOmod" => HOmod)
 
     for model_str in args["model-structure"]
         if !haskey(struct_map, model_str)