Bläddra i källkod

disabled termination condition, improved dynamic generation for dLI and dHI

Snej69420 15 timmar sedan
förälder
incheckning
6d8bf18486

+ 6 - 0
devstone/Results-PyPDEVS/LI_Paper

@@ -0,0 +1,6 @@
+model_type,depth,width,run,creation_time,setup_time,simulation_time
+LI,200,200,0,0.07788777351379395,0.19076967239379883,2.227574586868286
+LI,200,200,1,0.07655572891235352,0.18913054466247559,2.252530097961426
+LI,200,200,2,0.07787609100341797,0.19379425048828125,2.2242274284362793
+LI,200,200,3,0.07746052742004395,0.1930854320526123,2.2729926109313965
+LI,200,200,4,0.0774681568145752,0.1895005702972412,2.240265369415283

+ 16 - 0
devstone/Results-PyPDEVS/_Paper/HI_Paper-Minimal.csv

@@ -0,0 +1,16 @@
+model_type,depth,width,run,creation_time,setup_time,simulation_time
+HI,200,200,0,0.0725862979888916,0.06826567649841309,3.4317548274993896
+HI,200,200,1,0.07343697547912598,0.07040238380432129,3.421359062194824
+HI,200,200,2,0.07334446907043457,0.07012653350830078,3.509392023086548
+HI,200,200,3,0.07277894020080566,0.07003641128540039,3.4331741333007812
+HI,200,200,4,0.07248234748840332,0.06951761245727539,3.4231278896331787
+HI,200,40,0,0.027466297149658203,0.016195058822631836,0.15006303787231445
+HI,200,40,1,0.026807785034179688,0.01626753807067871,0.14705824851989746
+HI,200,40,2,0.027379751205444336,0.016247987747192383,0.15302729606628418
+HI,200,40,3,0.027170658111572266,0.015934467315673828,0.14744806289672852
+HI,200,40,4,0.027163982391357422,0.01612997055053711,0.1498417854309082
+HI,40,200,0,0.022704124450683594,0.01564335823059082,0.5452539920806885
+HI,40,200,1,0.022482633590698242,0.015565156936645508,0.5466611385345459
+HI,40,200,2,0.022641897201538086,0.01603984832763672,0.5467772483825684
+HI,40,200,3,0.02221965789794922,0.01574397087097168,0.5582840442657471
+HI,40,200,4,0.022856712341308594,0.01574110984802246,0.5498270988464355

+ 16 - 0
devstone/Results-PyPDEVS/_Paper/HI_Paper.csv

@@ -0,0 +1,16 @@
+model_type,depth,width,run,creation_time,setup_time,simulation_time
+HI,200,200,0,0.13329815864562988,0.23231887817382812,11.053540468215942
+HI,200,200,1,0.1351783275604248,0.22269272804260254,10.990642309188843
+HI,200,200,2,0.13295340538024902,0.22066807746887207,11.538768291473389
+HI,200,200,3,0.13465094566345215,0.2151343822479248,10.95034646987915
+HI,200,200,4,0.1372361183166504,0.21716761589050293,11.279894351959229
+HI,200,40,0,0.04456591606140137,0.044670820236206055,0.7869377136230469
+HI,200,40,1,0.043260812759399414,0.04155778884887695,0.803992748260498
+HI,200,40,2,0.043242454528808594,0.04130959510803223,0.7623703479766846
+HI,200,40,3,0.04193425178527832,0.03959226608276367,0.8794400691986084
+HI,200,40,4,0.043242692947387695,0.04169106483459473,0.8316826820373535
+HI,40,200,0,0.036783695220947266,0.016538381576538086,2.0196523666381836
+HI,40,200,1,0.036581993103027344,0.016563892364501953,1.9879934787750244
+HI,40,200,2,0.03595113754272461,0.016231298446655273,2.000950574874878
+HI,40,200,3,0.03543686866760254,0.016526222229003906,1.961158275604248
+HI,40,200,4,0.03586077690124512,0.016132354736328125,1.964233160018921

+ 16 - 0
devstone/Results-PyPDEVS/_Paper/LI_Paper-Minimal.csv

@@ -0,0 +1,16 @@
+model_type,depth,width,run,creation_time,setup_time,simulation_time
+LI,200,200,0,0.04097247123718262,0.0420842170715332,0.0839996337890625
+LI,200,200,1,0.04095292091369629,0.04137611389160156,0.08546662330627441
+LI,200,200,2,0.04017925262451172,0.04166889190673828,0.08567261695861816
+LI,200,200,3,0.039157867431640625,0.04170966148376465,0.08265280723571777
+LI,200,200,4,0.03914451599121094,0.04064750671386719,0.08250212669372559
+LI,200,40,0,0.01925182342529297,0.01087188720703125,0.021505355834960938
+LI,200,40,1,0.019538402557373047,0.011331796646118164,0.021213293075561523
+LI,200,40,2,0.018903732299804688,0.010725021362304688,0.02150249481201172
+LI,200,40,3,0.0183560848236084,0.011188268661499023,0.022145986557006836
+LI,200,40,4,0.019310474395751953,0.011333703994750977,0.021699905395507812
+LI,40,200,0,0.016556739807128906,0.00893855094909668,0.02158951759338379
+LI,40,200,1,0.016380786895751953,0.008169412612915039,0.02101302146911621
+LI,40,200,2,0.01652050018310547,0.008060455322265625,0.02170395851135254
+LI,40,200,3,0.01611924171447754,0.008328914642333984,0.021507978439331055
+LI,40,200,4,0.017661094665527344,0.008860588073730469,0.02190709114074707

+ 16 - 0
devstone/Results-PyPDEVS/_Paper/LI_Paper.csv

@@ -0,0 +1,16 @@
+model_type,depth,width,run,creation_time,setup_time,simulation_time
+LI,200,200,0,0.07983231544494629,0.18855643272399902,2.1902711391448975
+LI,200,200,1,0.07810616493225098,0.18871259689331055,2.2272324562072754
+LI,200,200,2,0.07976770401000977,0.19611144065856934,2.2235727310180664
+LI,200,200,3,0.07812666893005371,0.19191694259643555,2.1959493160247803
+LI,200,200,4,0.0777435302734375,0.18906378746032715,2.1890485286712646
+LI,200,40,0,0.02758169174194336,0.03517889976501465,0.3223590850830078
+LI,200,40,1,0.028234004974365234,0.03490042686462402,0.3238966464996338
+LI,200,40,2,0.0276339054107666,0.03506040573120117,0.3313453197479248
+LI,200,40,3,0.028155088424682617,0.03495597839355469,0.32274484634399414
+LI,200,40,4,0.030199766159057617,0.036293745040893555,0.32237815856933594
+LI,40,200,0,0.022413969039916992,0.016003131866455078,0.309891939163208
+LI,40,200,1,0.02237725257873535,0.01562356948852539,0.31186699867248535
+LI,40,200,2,0.022500991821289062,0.01607680320739746,0.30567145347595215
+LI,40,200,3,0.022100448608398438,0.015973567962646484,0.30257511138916016
+LI,40,200,4,0.022861719131469727,0.016422510147094727,0.3106989860534668

+ 9 - 10
devstone/pythonpdevs/devstone.py

@@ -404,9 +404,15 @@ class DynamicGenerator(AtomicDEVS):
         # increment counter and request modelTransition (return True)
         if self._counter >= self.repeat:
             return False
-        self._counter += 1
+        remaining = self.repeat - self._counter
+
+        num2create = self.number
+        if remaining < self.number:
+            num2create = remaining
+
+        self._counter += num2create
         state["generate"] = True
-        state["create"] = self.number
+        state["create"] = num2create
         state["created"] = 0
         return True
 
@@ -416,18 +422,12 @@ class DynamicDEVStoneWrapper(DEVStoneWrapper, ABC):
         if number <= 0:
             raise ValueError("number of models to be generated must be greater than zero")
 
-        # makes it easier to reason about width should be divisible by the number provided
-        # but the width provided also includes a coupled model so the actual width to be generated
-        # would be width - 1, this mitigates that
-        if number > 1 and root:
-            width += 1
-
         self.root = root
         self.mode = mode
         self.created = 0 # keeps track of how many atomic models have been created
         self.current_width = 1
         self.number = number
-        self.max_gen = (width - 1) // self.number # dynamically generate atomic components until width is reached excludes the coupled model
+        self.max_gen = width - 1 # dynamically generate atomic components until width is reached excludes the coupled model
 
         super().__init__(name, depth, width, int_delay, ext_delay, add_atomic_out_ports, prep_time=prep_time,
                          stats=stats, mode=mode, dynamic=True)
@@ -506,7 +506,6 @@ class dHI(DynamicDEVStoneWrapper):
     """
     def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, /, prep_time=0, stats=False, root=True, number: int = 1, gen_mode: str = "uniform"):
         super().__init__(name, depth, width, int_delay, ext_delay, True, prep_time, stats, mode="HI-Dynamic", root=root, number=number, gen_mode=gen_mode)
-
         if len(self.models) > 1:
             assert isinstance(self.component_set[-1], AtomicDEVS)
             self.connectPorts(self.i_in, self.component_set[-1].i_in)

+ 5 - 3
devstone/pythonpdevs/main.py

@@ -49,7 +49,7 @@ def parse_args():
 
     parser.add_argument('-C', '--classic', action="store_true", default=False, help='Use classic DEVS simulator')
     parser.add_argument('-D', '--dynamic', action="store_true", default=False, help='Enables Dynamic Structure DEVS')
-    parser.add_argument('-n', '--number', required=True, default=1, type=int, help='Number of models to be generated within a cycle in a single coupled model')
+    parser.add_argument('-n', '--number', required=False, default=1, type=int, help='Number of models to be generated within a cycle in a single coupled model')
     parser.add_argument("-g", "--gen-mode", choices=GEN_METHODS, help="Determines the spread of model creation.")
     args = parser.parse_args()
 
@@ -99,10 +99,12 @@ if __name__ == '__main__':
     if args.dynamic:
         sim.setDSDEVS(True)
         term = partial(terminate, timeLimit=args.width + 0.5)
-    sim.setTerminationCondition(term)
+    # adds massive overhead
+    # sim.setTerminationCondition(term)
     # sim.setVerbose(None)
     # sim.setTerminationTime(10.0)
     # sim.setStateSaving("custom")
+
     engine_setup_time = time.time()
     # pr = cProfile.Profile()
     # pr.enable()
@@ -114,7 +116,7 @@ if __name__ == '__main__':
     # sortby = pstats.SortKey.CUMULATIVE
     # ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
     # ps.print_stats()
-    # print(s.getvalue()[:2500])
+    # print(s.getvalue())
 
     # devstone_model.dot(f"{args.model_type}-after")
 

+ 22 - 13
devstone/testPyPDEVS.py

@@ -1,4 +1,5 @@
 #!/usr/bin/env python3
+import os
 import subprocess
 import csv
 import re
@@ -33,7 +34,7 @@ def run_devstone(model_type, depth, width, mode="parallel", out=False, *, classi
         SCRIPT_PATH = MinimalPyPDEVS
 
     cmd = [
-        "python3", SCRIPT_PATH,
+        "uv", "run", SCRIPT_PATH,
         "-m", model_type,
         "-d", str(depth),
         "-w", str(width),
@@ -126,13 +127,14 @@ def parse_args():
     parser = ArgumentParser()
     parser.add_argument("-p", "--path", type=str, default="./Results-PyPDEVS/", help="Path to the results directory")
     parser.add_argument("-f", '--filename', type=str, default="", help="Name of the output file")
+    parser.add_argument("-a", "--append", action="store_true", help="Append to the output file instead of overwriting.")
 
     parser.add_argument("-md", "--max-depth", default=8, type=int, help="Max depth for the generated models")
-    parser.add_argument("-ds", "--depth-stepsize", default=1, type=int,
+    parser.add_argument("-ds", "--depth-stepsize", type=int,
                         help="Determines for which depths a model is generated.")
 
     parser.add_argument("-mw", "--max-width", default=8, type=int, help="Max width for the generated models")
-    parser.add_argument("-ws", "--width-stepsize", default=1, type=int,
+    parser.add_argument("-ws", "--width-stepsize", type=int,
                         help="Determines for which depths a model is generated.")
 
     parser.add_argument("-r", "--repetitions", default=1, type=int, help="The number of times a simulation is repeated")
@@ -145,6 +147,11 @@ def parse_args():
     Dynamic(subparsers)
 
     args = parser.parse_args()
+    if args.depth_stepsize is None:
+        args.depth_stepsize = args.max_depth
+    if args.width_stepsize is None:
+        args.width_stepsize = args.max_width
+
     return args
 
 if __name__ == "__main__":
@@ -163,26 +170,28 @@ if __name__ == "__main__":
     if args.mode == "dynamic":
         fieldnames += ["number", "generator_mode"]
 
+    extra = {
+        "classic": False if not hasattr(args, "classic") else args.classic,
+        "gen_mode": "uniform" if not hasattr(args, "gen_mode") else args.gen_mode,
+        "number": 1 if not hasattr(args, "number") else args.number,
+    }
 
     for model_type in args.model_structure:
         model_filename = f"{args.path}{model_type}"
         if args.filename:
             model_filename += f"_{args.filename}"
-        else:
-            model_filename += ".csv"
-        with open(model_filename, "w", newline="") as csvfile:
+        model_filename += ".csv"
+
+        file_mode = "a" if args.append else "w"
+        write_header = not args.append or not os.path.exists(model_filename)
+        with open(model_filename, file_mode, newline="") as csvfile:
             writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
-            writer.writeheader()
+            if write_header:
+                writer.writeheader()
 
             for depth in range(d[1], d[0] + 1, d[1]):
                 for width in range(w[1], w[0] + 1, w[1]):
                     for run in range(args.repetitions):
-                        extra = {}
-                        if args.mode == "dynamic":
-                            extra["classic"] = args.classic
-                            extra["gen_mode"] = args.gen_mode
-                            extra["number"] = args.number
-
                         creation, setup, sim, output = run_devstone(
                             model_type, depth, width,
                             args.mode, args.output,

+ 11 - 0
uv.lock

@@ -102,6 +102,7 @@ name = "devstone-comparative"
 version = "0.1.0"
 source = { virtual = "." }
 dependencies = [
+    { name = "graphviz" },
     { name = "matplotlib" },
     { name = "pandas" },
     { name = "seaborn" },
@@ -109,6 +110,7 @@ dependencies = [
 
 [package.metadata]
 requires-dist = [
+    { name = "graphviz", specifier = ">=0.21" },
     { name = "matplotlib", specifier = ">=3.10.7" },
     { name = "pandas", specifier = ">=2.3.3" },
     { name = "seaborn", specifier = ">=0.13.2" },
@@ -163,6 +165,15 @@ wheels = [
     { url = "https://files.pythonhosted.org/packages/c7/93/0dd45cd283c32dea1545151d8c3637b4b8c53cdb3a625aeb2885b184d74d/fonttools-4.60.1-py3-none-any.whl", hash = "sha256:906306ac7afe2156fcf0042173d6ebbb05416af70f6b370967b47f8f00103bbb", size = 1143175, upload-time = "2025-09-29T21:13:24.134Z" },
 ]
 
+[[package]]
+name = "graphviz"
+version = "0.21"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f8/b3/3ac91e9be6b761a4b30d66ff165e54439dcd48b83f4e20d644867215f6ca/graphviz-0.21.tar.gz", hash = "sha256:20743e7183be82aaaa8ad6c93f8893c923bd6658a04c32ee115edb3c8a835f78", size = 200434, upload-time = "2025-06-15T09:35:05.824Z" }
+wheels = [
+    { url = "https://files.pythonhosted.org/packages/91/4c/e0ce1ef95d4000ebc1c11801f9b944fa5910ecc15b5e351865763d8657f8/graphviz-0.21-py3-none-any.whl", hash = "sha256:54f33de9f4f911d7e84e4191749cac8cc5653f815b06738c54db9a15ab8b1e42", size = 47300, upload-time = "2025-06-15T09:35:04.433Z" },
+]
+
 [[package]]
 name = "kiwisolver"
 version = "1.4.9"