Procházet zdrojové kódy

removed all simulators except for pythonpdevs as well as their model implementations. \n Updated the generator to follow the DEVS formalism and added a getter for the transitions

Snej69420 před 8 měsíci
rodič
revize
e19568bc94
94 změnil soubory, kde provedl 4641 přidání a 7823 odebrání
  1. binární
      benchmarks/Plots/HI/HI-Classic-Compared_width_100.png
  2. binární
      benchmarks/Plots/HI/HI-Compared_width_100.png
  3. binární
      benchmarks/Plots/HI/HI-Dynamic-Compared_width_100.png
  4. binární
      benchmarks/Plots/LI/LI-Classic-Compared_width_100.png
  5. binární
      benchmarks/Plots/LI/LI-Compared_width_100.png
  6. binární
      benchmarks/Plots/LI/LI-Dynamic-Compared_width_100.png
  7. 0 0
      benchmarks/__init__.py
  8. 100 0
      benchmarks/compare.py
  9. 96 0
      benchmarks/compareDEVS.py
  10. 16 0
      benchmarks/dhry/Makefile
  11. 453 0
      benchmarks/dhry/dhry.h
  12. 440 0
      benchmarks/dhry/dhry_1.c
  13. 209 0
      benchmarks/dhry/dhry_2.c
  14. 99 0
      benchmarks/model_properties.py
  15. 265 0
      benchmarks/plotNumberOfDCP.py
  16. 84 0
      benchmarks/plot_time-models.py
  17. 0 0
      benchmarks/pythonpdevs-minimal/__init__.py
  18. 267 0
      benchmarks/pythonpdevs-minimal/devstone.py
  19. 36 0
      benchmarks/pythonpdevs-minimal/generator.py
  20. 75 0
      benchmarks/pythonpdevs-minimal/main.py
  21. 277 0
      benchmarks/pythonpdevs-minimal/pystone.py
  22. 347 0
      benchmarks/pythonpdevs-minimal/test_devstone.py
  23. 0 0
      benchmarks/pythonpdevs/__init__.py
  24. 668 0
      benchmarks/pythonpdevs/devstone.py
  25. 44 0
      benchmarks/pythonpdevs/generator.py
  26. 146 0
      benchmarks/pythonpdevs/main.py
  27. 277 0
      benchmarks/pythonpdevs/pystone.py
  28. 347 0
      benchmarks/pythonpdevs/test_devstone.py
  29. 286 0
      benchmarks/testPyPDEVS.py
  30. 109 0
      benchmarks/w-d-plot.py
  31. 0 0
      devstone/__init__.py
  32. 0 27
      devstone/adevs/CMakeLists.txt
  33. 0 53
      devstone/adevs/src/devstone.cpp
  34. 0 47
      devstone/adevs/src/devstone.hpp
  35. 0 61
      devstone/adevs/src/devstone_atomic.hpp
  36. 0 98
      devstone/adevs/src/devstone_coupled.hpp
  37. 0 33
      devstone/adevs/src/hi.hpp
  38. 0 41
      devstone/adevs/src/ho.hpp
  39. 0 64
      devstone/adevs/src/homod.hpp
  40. 0 26
      devstone/adevs/src/li.hpp
  41. 0 43
      devstone/adevs/src/seeder.hpp
  42. 0 8
      devstone/adevs/src/utils.hpp
  43. 0 156
      devstone/adevs/test/test_devstone.cpp
  44. 0 21
      devstone/cadmium/CMakeLists.txt
  45. 0 100
      devstone/cadmium/events.txt
  46. 0 1
      devstone/cadmium/events_devstone.txt
  47. 0 118
      devstone/cadmium/src/cadmium-devstone-atomic.hpp
  48. 0 128
      devstone/cadmium/src/cadmium-dynamic-devstone.cpp
  49. 0 145
      devstone/cadmium/src/cadmium-event-reader.hpp
  50. 0 159
      devstone/cadmium/src/dynamic/HI_generator.cpp
  51. 0 168
      devstone/cadmium/src/dynamic/HO_generator.cpp
  52. 0 179
      devstone/cadmium/src/dynamic/HOmod_generator.cpp
  53. 0 151
      devstone/cadmium/src/dynamic/LI_generator.cpp
  54. 0 21
      devstone/cdboost/CMakeLists.txt
  55. 0 1
      devstone/cdboost/events_devstone.txt
  56. 0 108
      devstone/cdboost/src/cdboost-devstone-atomic-pair.hpp
  57. 0 108
      devstone/cdboost/src/cdboost-devstone-atomic.hpp
  58. 0 110
      devstone/cdboost/src/cdboost-devstone-filter.hpp
  59. 0 108
      devstone/cdboost/src/cdboost-devstone-input-stream-pair.hpp
  60. 0 306
      devstone/cdboost/src/cdboost-devstone.cpp
  61. 0 0
      devstone/pythonpdevs/__init__.py
  62. 0 81
      simulators/adevs-3.3/README
  63. 0 30
      simulators/adevs-3.3/copyright.txt
  64. 0 51
      simulators/adevs-3.3/include/adevs.h
  65. 0 119
      simulators/adevs-3.3/include/adevs_abstract_simulator.h
  66. 0 193
      simulators/adevs-3.3/include/adevs_bag.h
  67. 0 216
      simulators/adevs-3.3/include/adevs_cellspace.h
  68. 0 143
      simulators/adevs-3.3/include/adevs_corrected_euler.h
  69. 0 212
      simulators/adevs-3.3/include/adevs_digraph.h
  70. 0 74
      simulators/adevs-3.3/include/adevs_event_listener.h
  71. 0 233
      simulators/adevs-3.3/include/adevs_event_locators.h
  72. 0 98
      simulators/adevs-3.3/include/adevs_exception.h
  73. 0 592
      simulators/adevs-3.3/include/adevs_fmi.h
  74. 0 617
      simulators/adevs-3.3/include/adevs_hybrid.h
  75. 0 311
      simulators/adevs-3.3/include/adevs_models.h
  76. 0 95
      simulators/adevs-3.3/include/adevs_poly.h
  77. 0 233
      simulators/adevs-3.3/include/adevs_rand.h
  78. 0 171
      simulators/adevs-3.3/include/adevs_rk_45.h
  79. 0 240
      simulators/adevs-3.3/include/adevs_sched.h
  80. 0 59
      simulators/adevs-3.3/include/adevs_set.h
  81. 0 133
      simulators/adevs-3.3/include/adevs_simpledigraph.h
  82. 0 718
      simulators/adevs-3.3/include/adevs_simulator.h
  83. 0 321
      simulators/adevs-3.3/include/adevs_time.h
  84. 0 207
      simulators/adevs-3.3/include/adevs_wrapper.h
  85. 0 78
      simulators/adevs-3.3/include/object_pool.h
  86. 0 1
      simulators/cadmium
  87. 0 1
      simulators/cadmium_v2
  88. 0 1
      simulators/pythonpdevs
  89. 0 1
      simulators/xdevs.c
  90. 0 1
      simulators/xdevs.cpp
  91. 0 1
      simulators/xdevs.java
  92. 0 1
      simulators/xdevs.py
  93. 0 1
      simulators/xdevs.rs
  94. 0 1
      simulators/xdevs.rs-new

binární
benchmarks/Plots/HI/HI-Classic-Compared_width_100.png


binární
benchmarks/Plots/HI/HI-Compared_width_100.png


binární
benchmarks/Plots/HI/HI-Dynamic-Compared_width_100.png


binární
benchmarks/Plots/LI/LI-Classic-Compared_width_100.png


binární
benchmarks/Plots/LI/LI-Compared_width_100.png


binární
benchmarks/Plots/LI/LI-Dynamic-Compared_width_100.png


+ 0 - 0
benchmarks/__init__.py


+ 100 - 0
benchmarks/compare.py

@@ -0,0 +1,100 @@
+#!/usr/bin/env python3
+import os
+import argparse
+import pandas as pd
+import matplotlib.pyplot as plt
+from pathlib import Path
+
+def clean_data(df):
+    df["total_time"] = (
+        df["simulation_time"]
+        + df["creation_time"]
+        + df["setup_time"]
+    )
+
+    possible_group_cols = ["depth", "width", "number", "total_time"]
+    grouping_cols = [c for c in possible_group_cols if c in df.columns]
+
+    def clean(group):
+        Q1 = group["total_time"].quantile(0.25)
+        Q3 = group["total_time"].quantile(0.75)
+        IQR = Q3 - Q1
+        lower = Q1 - 1.5 * IQR
+        upper = Q3 + 1.5 * IQR
+        return group[(group["total_time"] >= lower) & (group["total_time"] <= upper)]
+
+    cleaned = (
+        df.groupby(grouping_cols, group_keys=False)[grouping_cols]
+          .apply(clean)
+    )
+
+    return cleaned
+
+def plot_time_vs_param(csv_files, param, fixed_param=None, fixed_value=None, max_value=0, name="DEVS"):
+    results = {}
+    for path in csv_files:
+        df = pd.read_csv(path)
+        df = clean_data(df)
+        if fixed_param and fixed_value is not None:
+            df = df[df[fixed_param] == fixed_value]
+        if max_value > 0:
+            df = df[df[param] <= max_value]
+
+        grouped = df.groupby(param, as_index=False)["total_time"].mean()
+        results[path.stem] = grouped
+
+    plt.figure(figsize=(8,6))
+    for label, df in results.items():
+        plt.plot(df[param], df["total_time"], marker='o', label=label)
+
+    title = f"Average Simulation Time vs {param.capitalize()}"
+    if fixed_param:
+        title += f" (fixed {fixed_param}={fixed_value})"
+    plt.title(title)
+    plt.xlabel(param.capitalize())
+    plt.ylabel("Average Simulation Time (s)")
+    plt.legend()
+    plt.grid(True)
+
+    output_dir = Path("./Plots")
+    output_dir.mkdir(parents=True, exist_ok=True)
+    output_file = output_dir / f"{name}_{param}.png"
+    plt.tight_layout()
+    plt.savefig(output_file, dpi=300)
+    print(f"Saved plot as {output_file}")
+
+def main():
+    parser = argparse.ArgumentParser(description="Compare simulation results from multiple CSV files.")
+    subparsers = parser.add_subparsers(dest="command", required=True)
+
+    # Subcommand: time-vs-depth/width
+    parser_tvparam = subparsers.add_parser("param", help="Plot total time vs depth or width")
+    parser_tvparam.add_argument("csv_files", nargs="+", type=Path, help="CSV files to process")
+    parser_tvparam.add_argument("-n", "--name", default="DEVS", type=str, help="Name of output file")
+    group = parser_tvparam.add_mutually_exclusive_group(required=True)
+    group.add_argument("-w", "--width", type=int, help="Fixed width value")
+    group.add_argument("-d", "--depth", type=int, help="Fixed depth value")
+    parser_tvparam.add_argument('-m', '--max', type=int, default=0, help="Maximum value of varying parameter")
+
+    # Subcommand: time-vs-number
+    parser_tvn = subparsers.add_parser("number", help="Plot total time vs number")
+    parser_tvn.add_argument("csv_files", nargs="+", type=Path, help="CSV files to process")
+    parser_tvn.add_argument("-n", "--name", default="DEVS", type=str, help="Name of output file")
+
+    args = parser.parse_args()
+
+    if args.command == "param":
+        if args.width is not None:
+            fixed_param, fixed_value = "width", args.width
+            varying_param = "depth"
+        else:
+            fixed_param, fixed_value = "depth", args.depth
+            varying_param = "width"
+        plot_time_vs_param(args.csv_files, param=varying_param,
+                           fixed_param=fixed_param, fixed_value=fixed_value,
+                           max_value=args.max, name=args.name)
+    elif args.command == "number":
+        plot_time_vs_param(args.csv_files, param="number", name=args.name)
+
+if __name__ == "__main__":
+    main()

+ 96 - 0
benchmarks/compareDEVS.py

@@ -0,0 +1,96 @@
+#!/usr/bin/env python3
+"""
+Compares DEVStone benchmark results from multiple DEVS variants
+(Classic, Parallel, Dynamic Structure, etc.).
+
+Each CSV must contain:
+  model_type, depth, width, run, creation_time, setup_time, simulation_time
+
+Produces:
+  - Plots of scalability (depth/width)
+  - Overhead composition
+  - Speedup ratios
+  - A summary CSV table with average speedups
+"""
+
+import pandas as pd
+import matplotlib.pyplot as plt
+import seaborn as sns
+from pathlib import Path
+
+# === CONFIGURATION ===
+FILES = {
+    # "Classic": "./Results-PyPDEVS/DEVSTONE-classic.csv",
+    "Parallel": "./Results-PyPDEVS/DEVSTONE.csv",
+    # "Minimal": "./Results-PyPDEVS/DEVSTONE-minimal.csv",
+    "Dynamic Structure": "./Results-PyPDEVS/DEVSTONE-dynamic.csv",
+    # "DS-C": "./Results-PyPDEVS/DEVSTONE-classic-dynamic.csv",
+
+}
+OUTPUT_DIR = Path("./Results-PyPDEVS")
+OUTPUT_DIR.mkdir(exist_ok=True)
+
+# === LOAD & MERGE ===
+dfs = []
+for variant, path in FILES.items():
+    df = pd.read_csv(path)
+    df["variant"] = variant
+    dfs.append(df)
+data = pd.concat(dfs, ignore_index=True)
+
+# === PROCESSING ===
+data["total_time"] = data["creation_time"] + data["setup_time"] + data["simulation_time"]
+agg = (
+    data.groupby(["variant", "model_type", "depth", "width"], as_index=False)
+    .agg({
+        "creation_time": ["mean", "std"],
+        "setup_time": ["mean", "std"],
+        "simulation_time": ["mean", "std"],
+        "total_time": ["mean", "std"]
+    })
+)
+# Flatten multi-level columns
+agg.columns = ["_".join(col).rstrip("_") for col in agg.columns.values]
+
+sns.set_theme(style="whitegrid", font_scale=1.2)
+
+# === Scalability with Width ===
+for model in agg["model_type"].unique():
+    subset = agg[agg["model_type"] == model]
+    plt.figure(figsize=(7, 5))
+    sns.lineplot(data=subset, x="width", y="simulation_time_mean", hue="variant", marker="o")
+    plt.title(f"Scalability with Width – {model}")
+    plt.xlabel("Width (# submodels per level)")
+    plt.ylabel("Simulation time (s)")
+    plt.tight_layout()
+    plt.savefig(OUTPUT_DIR / f"scalability_width_{model}.png")
+    plt.close()
+
+# === Scalability with Depth ===
+for model in agg["model_type"].unique():
+    subset = agg[agg["model_type"] == model]
+    plt.figure(figsize=(7, 5))
+    sns.lineplot(data=subset, x="depth", y="simulation_time_mean", hue="variant", marker="o")
+    plt.title(f"Scalability with Depth – {model}")
+    plt.xlabel("Depth (levels)")
+    plt.ylabel("Simulation time (s)")
+    plt.tight_layout()
+    plt.savefig(OUTPUT_DIR / f"scalability_depth_{model}.png")
+    plt.close()
+
+# === Overhead Composition ===
+comp = data.melt(
+    id_vars=["variant", "model_type", "depth", "width"],
+    value_vars=["creation_time", "setup_time", "simulation_time"],
+    var_name="phase",
+    value_name="time"
+)
+plt.figure(figsize=(9, 6))
+sns.barplot(data=comp, x="variant", y="time", hue="phase", estimator="mean", errorbar="sd")
+plt.title("Average Overhead Composition by Variant")
+plt.ylabel("Mean time (s)")
+plt.tight_layout()
+plt.savefig(OUTPUT_DIR / "overhead_composition.png")
+plt.close()
+
+print(f"\nAnalysis complete. Plots and summary saved in: {OUTPUT_DIR}/")

+ 16 - 0
benchmarks/dhry/Makefile

@@ -0,0 +1,16 @@
+CC=clang
+CXX=clang++
+
+CFLAGS= -c -O0 -fPIC
+LDFLAGS+= -L/usr/local/lib
+
+DHRYSTONE=dhry_1.c dhry_2.c
+
+DHRYSTONE_OBJECTS=$(DHRYSTONE:.c=.o)
+
+all: dhrystone
+
+dhrystone: $(DHRYSTONE_OBJECTS)
+
+clean:
+	rm *.o

+ 453 - 0
benchmarks/dhry/dhry.h

@@ -0,0 +1,453 @@
+#ifndef DHRY_H
+#define DHRY_H
+/*
+ ****************************************************************************
+ *
+ *                   "DHRYSTONE" Benchmark Program
+ *                   -----------------------------
+ *                                                                            
+ *  Version:    C, Version 2.1
+ *                                                                            
+ *  File:       dhry.h (part 1 of 3)
+ *
+ *  Date:       May 25, 1988
+ *
+ *  Author:     Reinhold P. Weicker
+ *                      Siemens AG, AUT E 51
+ *                      Postfach 3220
+ *                      8520 Erlangen
+ *                      Germany (West)
+ *                              Phone:  [+49]-9131-7-20330
+ *                                      (8-17 Central European Time)
+ *                              Usenet: ..!mcsun!unido!estevax!weicker
+ *
+ *              converted to ANSI C by Jeremy Johnson.  1/20/00
+ *
+ *              Original Version (in Ada) published in
+ *              "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
+ *              pp. 1013 - 1030, together with the statistics
+ *              on which the distribution of statements etc. is based.
+ *
+ *              In this C version, the following C library functions are used:
+ *              - strcpy, strcmp (inside the measurement loop)
+ *              - printf, scanf (outside the measurement loop)
+ *              In addition, Berkeley UNIX system calls "times ()" or "time ()"
+ *              are used for execution time measurement. For measurements
+ *              on other systems, these calls have to be changed.
+ *
+ *  Collection of Results:
+ *              Reinhold Weicker (address see above) and
+ *              
+ *              Rick Richardson
+ *              PC Research. Inc.
+ *              94 Apple Orchard Drive
+ *              Tinton Falls, NJ 07724
+ *                      Phone:  (201) 389-8963 (9-17 EST)               
+ *                      Usenet: ...!uunet!pcrat!rick
+ *
+ *      Please send results to Rick Richardson and/or Reinhold Weicker.
+ *      Complete information should be given on hardware and software used.
+ *      Hardware information includes: Machine type, CPU, type and size
+ *      of caches; for microprocessors: clock frequency, memory speed
+ *      (number of wait states).
+ *      Software information includes: Compiler (and runtime library)
+ *      manufacturer and version, compilation switches, OS version.
+ *      The Operating System version may give an indication about the
+ *      compiler; Dhrystone itself performs no OS calls in the measurement loop.
+ *
+ *      The complete output generated by the program should be mailed
+ *      such that at least some checks for correctness can be made.
+ *
+ ***************************************************************************
+ *
+ *  History:    This version C/2.1 has been made for two reasons:
+ *
+ *              1) There is an obvious need for a common C version of
+ *              Dhrystone, since C is at present the most popular system
+ *              programming language for the class of processors
+ *              (microcomputers, minicomputers) where Dhrystone is used most.
+ *              There should be, as far as possible, only one C version of
+ *              Dhrystone such that results can be compared without
+ *              restrictions. In the past, the C versions distributed
+ *              by Rick Richardson (Version 1.1) and by Reinhold Weicker
+ *              had small (though not significant) differences.
+ *
+ *              2) As far as it is possible without changes to the Dhrystone
+ *              statistics, optimizing compilers should be prevented from
+ *              removing significant statements.
+ *
+ *              This C version has been developed in cooperation with
+ *              Rick Richardson (Tinton Falls, NJ), it incorporates many
+ *              ideas from the "Version 1.1" distributed previously by
+ *              him over the UNIX network Usenet.
+ *              I also thank Chaim Benedelac (National Semiconductor),
+ *              David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
+ *              Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
+ *              for their help with comments on earlier versions of the
+ *              benchmark.
+ *
+ *  Changes:    In the initialization part, this version follows mostly
+ *              Rick Richardson's version distributed via Usenet, not the
+ *              version distributed earlier via floppy disk by Reinhold Weicker.
+ *              As a concession to older compilers, names have been made
+ *              unique within the first 8 characters.
+ *              Inside the measurement loop, this version follows the
+ *              version previously distributed by Reinhold Weicker.
+ *
+ *              At several places in the benchmark, code has been added,
+ *              but within the measurement loop only in branches that 
+ *              are not executed. The intention is that optimizing compilers
+ *              should be prevented from moving code out of the measurement
+ *              loop, or from removing code altogether. Since the statements
+ *              that are executed within the measurement loop have NOT been
+ *              changed, the numbers defining the "Dhrystone distribution"
+ *              (distribution of statements, operand types and locality)
+ *              still hold. Except for sophisticated optimizing compilers,
+ *              execution times for this version should be the same as
+ *              for previous versions.
+ *              
+ *              Since it has proven difficult to subtract the time for the
+ *              measurement loop overhead in a correct way, the loop check
+ *              has been made a part of the benchmark. This does have
+ *              an impact - though a very minor one - on the distribution
+ *              statistics which have been updated for this version.
+ *
+ *              All changes within the measurement loop are described
+ *              and discussed in the companion paper "Rationale for
+ *              Dhrystone version 2".
+ *
+ *              Because of the self-imposed limitation that the order and
+ *              distribution of the executed statements should not be
+ *              changed, there are still cases where optimizing compilers
+ *              may not generate code for some statements. To a certain
+ *              degree, this is unavoidable for small synthetic benchmarks.
+ *              Users of the benchmark are advised to check code listings
+ *              whether code is generated for all statements of Dhrystone.
+ *
+ *              Version 2.1 is identical to version 2.0 distributed via
+ *              the UNIX network Usenet in March 1988 except that it corrects
+ *              some minor deficiencies that were found by users of version 2.0.
+ *              The only change within the measurement loop is that a
+ *              non-executed "else" part was added to the "if" statement in
+ *              Func_3, and a non-executed "else" part removed from Proc_3.
+ *
+ ***************************************************************************
+ *
+ * Defines:     The following "Defines" are possible:
+ *              -DREG=register          (default: Not defined)
+ *                      As an approximation to what an average C programmer
+ *                      might do, the "register" storage class is applied
+ *                      (if enabled by -DREG=register)
+ *                      - for local variables, if they are used (dynamically)
+ *                        five or more times
+ *                      - for parameters if they are used (dynamically)
+ *                        six or more times
+ *                      Note that an optimal "register" strategy is
+ *                      compiler-dependent, and that "register" declarations
+ *                      do not necessarily lead to faster execution.
+ *              -DNOSTRUCTASSIGN        (default: Not defined)
+ *                      Define if the C compiler does not support
+ *                      assignment of structures.
+ *              -DNOENUMS               (default: Not defined)
+ *                      Define if the C compiler does not support
+ *                      enumeration types.
+ *              -DTIMES                 (default)
+ *              -DTIME
+ *                      The "times" function of UNIX (returning process times)
+ *                      or the "time" function (returning wallclock time)
+ *                      is used for measurement. 
+ *                      For single user machines, "time ()" is adequate. For
+ *                      multi-user machines where you cannot get single-user
+ *                      access, use the "times ()" function. If you have
+ *                      neither, use a stopwatch in the dead of night.
+ *                      "printf"s are provided marking the points "Start Timer"
+ *                      and "Stop Timer". DO NOT use the UNIX "time(1)"
+ *                      command, as this will measure the total time to
+ *                      run this program, which will (erroneously) include
+ *                      the time to allocate storage (malloc) and to perform
+ *                      the initialization.
+ *              -DHZ=nnn
+ *                      In Berkeley UNIX, the function "times" returns process
+ *                      time in 1/HZ seconds, with HZ = 60 for most systems.
+ *                      CHECK YOUR SYSTEM DESCRIPTION BEFORE YOU JUST APPLY
+ *                      A VALUE.
+ *
+ ***************************************************************************
+ *
+ *  Compilation model and measurement (IMPORTANT):
+ *
+ *  This C version of Dhrystone consists of three files:
+ *  - dhry.h (this file, containing global definitions and comments)
+ *  - dhry_1.c (containing the code corresponding to Ada package Pack_1)
+ *  - dhry_2.c (containing the code corresponding to Ada package Pack_2)
+ *
+ *  The following "ground rules" apply for measurements:
+ *  - Separate compilation
+ *  - No procedure merging
+ *  - Otherwise, compiler optimizations are allowed but should be indicated
+ *  - Default results are those without register declarations
+ *  See the companion paper "Rationale for Dhrystone Version 2" for a more
+ *  detailed discussion of these ground rules.
+ *
+ *  For 16-Bit processors (e.g. 80186, 80286), times for all compilation
+ *  models ("small", "medium", "large" etc.) should be given if possible,
+ *  together with a definition of these models for the compiler system used.
+ *
+ **************************************************************************
+ *
+ *  Dhrystone (C version) statistics:
+ *
+ *  [Comment from the first distribution, updated for version 2.
+ *   Note that because of language differences, the numbers are slightly
+ *   different from the Ada version.]
+ *
+ *  The following program contains statements of a high level programming
+ *  language (here: C) in a distribution considered representative:           
+ *
+ *    assignments                  52 (51.0 %)
+ *    control statements           33 (32.4 %)
+ *    procedure, function calls    17 (16.7 %)
+ *
+ *  103 statements are dynamically executed. The program is balanced with
+ *  respect to the three aspects:                                             
+ *
+ *    - statement type
+ *    - operand type
+ *    - operand locality
+ *         operand global, local, parameter, or constant.                     
+ *
+ *  The combination of these three aspects is balanced only approximately.    
+ *
+ *  1. Statement Type:                                                        
+ *  -----------------             number
+ *
+ *     V1 = V2                     9
+ *       (incl. V1 = F(..)
+ *     V = Constant               12
+ *     Assignment,                 7
+ *       with array element
+ *     Assignment,                 6
+ *       with record component
+ *                                --
+ *                                34       34
+ *
+ *     X = Y +|-|"&&"|"|" Z        5
+ *     X = Y +|-|"==" Constant     6
+ *     X = X +|- 1                 3
+ *     X = Y *|/ Z                 2
+ *     X = Expression,             1
+ *           two operators
+ *     X = Expression,             1
+ *           three operators
+ *                                --
+ *                                18       18
+ *
+ *     if ....                    14
+ *       with "else"      7
+ *       without "else"   7
+ *           executed        3
+ *           not executed    4
+ *     for ...                     7  |  counted every time
+ *     while ...                   4  |  the loop condition
+ *     do ... while                1  |  is evaluated
+ *     switch ...                  1
+ *     break                       1
+ *     declaration with            1
+ *       initialization
+ *                                --
+ *                                34       34
+ *
+ *     P (...)  procedure call    11
+ *       user procedure      10
+ *       library procedure    1
+ *     X = F (...)
+ *             function  call      6
+ *       user function        5                                         
+ *       library function     1                                               
+ *                                --                                          
+ *                                17       17
+ *                                        ---
+ *                                        103
+ *
+ *    The average number of parameters in procedure or function calls
+ *    is 1.82 (not counting the function values as implicit parameters).
+ *
+ *
+ *  2. Operators
+ *  ------------
+ *                          number    approximate
+ *                                    percentage
+ *
+ *    Arithmetic             32          50.8                                 
+ *
+ *       +                     21          33.3                              
+ *       -                      7          11.1                              
+ *       *                      3           4.8
+ *       / (int div)            1           1.6
+ *
+ *    Comparison             27           42.8
+ *
+ *       ==                     9           14.3
+ *       /=                     4            6.3
+ *       >                      1            1.6
+ *       <                      3            4.8
+ *       >=                     1            1.6
+ *       <=                     9           14.3
+ *
+ *    Logic                   4            6.3
+ *
+ *       && (AND-THEN)          1            1.6
+ *       |  (OR)                1            1.6
+ *       !  (NOT)               2            3.2
+ * 
+ *                           --          -----
+ *                           63          100.1
+ *
+ *
+ *  3. Operand Type (counted once per operand reference):
+ *  ---------------
+ *                          number    approximate
+ *                                    percentage
+ *
+ *     Integer               175        72.3 %
+ *     Character              45        18.6 %
+ *     Pointer                12         5.0 %
+ *     String30                6         2.5 %
+ *     Array                   2         0.8 %
+ *     Record                  2         0.8 %
+ *                           ---       -------
+ *                           242       100.0 %
+ *
+ *  When there is an access path leading to the final operand (e.g. a record
+ *  component), only the final data type on the access path is counted.       
+ *
+ *
+ *  4. Operand Locality:                                                      
+ *  -------------------
+ *                                number    approximate
+ *                                          percentage
+ *
+ *     local variable              114        47.1 %
+ *     global variable              22         9.1 %
+ *     parameter                    45        18.6 %
+ *        value                        23         9.5 %
+ *        reference                    22         9.1 %
+ *     function result               6         2.5 %
+ *     constant                     55        22.7 %
+ *                                 ---       -------
+ *                                 242       100.0 %
+ *
+ *
+ *  The program does not compute anything meaningful, but it is syntactically
+ *  and semantically correct. All variables have a value assigned to them
+ *  before they are used as a source operand.
+ *
+ *  There has been no explicit effort to account for the effects of a
+ *  cache, or to balance the use of long or short displacements for code or
+ *  data.
+ *
+ ***************************************************************************
+ */
+
+/* Compiler and system dependent definitions: */
+
+#define CLOCK
+
+#ifdef CLOCK
+#include <time.h>
+#endif
+/*
+#ifndef TIME
+#define TIMES
+#endif
+*/
+                /* Use times(2) time function unless    */
+                /* explicitly defined otherwise         */
+
+#ifdef TIMES
+#include <sys/types.h>
+#include <sys/times.h>
+#endif	        /* for "times" */
+
+#define Mic_secs_Per_Second     1000000.0
+                /* Berkeley UNIX C returns process times in seconds/HZ */
+
+#ifdef  NOSTRUCTASSIGN
+#define structassign(d, s)      memcpy(&(d), &(s), sizeof(d))
+#else
+#define structassign(d, s)      d = s
+#endif
+
+#ifdef  NOENUM
+#define Ident_1 0
+#define Ident_2 1
+#define Ident_3 2
+#define Ident_4 3
+#define Ident_5 4
+  typedef int   Enumeration;
+#else
+  typedef enum  {Ident_1, Ident_2, Ident_3, Ident_4, Ident_5}
+  				Enumeration;
+#endif
+        /* for boolean and enumeration types in Ada, Pascal */
+
+/* General definitions: */
+
+#include <stdio.h>
+/* Added by JRJ. for strcpy and strcmp. */
+#include <string.h>
+/* Added by JRJ for malloc. */
+#include <stdlib.h>
+//#include <cmalloc.h>
+
+#define Null 0 
+                /* Value of a Null pointer */
+#define true  1
+#define false 0
+
+typedef int     One_Thirty;
+typedef int     One_Fifty;
+typedef char    Capital_Letter;
+typedef int     Boolean;
+typedef char    Str_30 [31];
+typedef int     Arr_1_Dim [50];
+typedef int     Arr_2_Dim [50] [50];
+
+typedef struct record 
+    {
+    struct record *Ptr_Comp;
+    Enumeration    Discr;
+    union {
+          struct {
+                  Enumeration Enum_Comp;
+                  int         Int_Comp;
+                  char        Str_Comp [31];
+                  } var_1;
+          struct {
+                  Enumeration E_Comp_2;
+                  char        Str_2_Comp [31];
+                  } var_2;
+          struct {
+                  char        Ch_1_Comp;
+                  char        Ch_2_Comp;
+                  } var_3;
+          } variant;
+      } Rec_Type, *Rec_Pointer;
+
+
+extern void Proc_1 (Rec_Pointer Ptr_Val_Par);
+extern void Proc_2 (One_Fifty *Int_Par_Ref);
+extern void Proc_3 (Rec_Pointer *Ptr_Ref_Par);
+extern void Proc_4 (void);
+extern void Proc_5 (void);
+extern void Proc_6 (Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par);
+extern void Proc_7 (One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref);
+extern void Proc_8 (Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val);
+
+extern Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
+extern Boolean Func_2 (Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref);
+extern Boolean Func_3 (Enumeration Enum_Par_Val);
+
+int dhrystoneRun (int Number_Of_Runs);
+
+#endif // DHRY_H

+ 440 - 0
benchmarks/dhry/dhry_1.c

@@ -0,0 +1,440 @@
+/*
+
+ ****************************************************************************
+ *
+ *                   "DHRYSTONE" Benchmark Program
+ *                   -----------------------------
+ *                                                                            
+ *  Version:    C, Version 2.1
+ *                                                                            
+ *  File:       dhry_1.c (part 2 of 3)
+ *
+ *  Date:       May 25, 1988
+ *
+ *  Author:     Reinhold P. Weicker
+ *              converted to ANSI C by Jeremy Johnson.  1/20/00
+ *
+ ****************************************************************************
+ */
+#ifndef DHRY1_C
+#define DHRY1_C
+
+
+#include "dhry.h"
+#include "dhry_2.c"
+
+/* Global Variables: */
+int             Int_Glob;
+char            Ch_1_Glob;
+
+
+class DhryStone {
+
+    public:
+        Rec_Pointer     Ptr_Glob,
+                        Next_Ptr_Glob;
+        Boolean         Bool_Glob;
+        char            Ch_2_Glob;
+        int             Arr_1_Glob [50];
+        int             Arr_2_Glob [50] [50];
+        long            Begin_Time,
+                        End_Time,
+                        User_Time;
+        float           Microseconds,
+                        Dhrystones_Per_Second;
+
+        /* Added to dhry.h.  JRJ. */
+        /* extern char     *malloc (); */
+
+        /* Enumeration     Func_1 (); */
+        /* forward declaration necessary since Enumeration may not simply be int */
+
+        #ifndef REG
+            Boolean Reg = false;
+        #define REG
+                /* REG becomes defined as empty */
+                /* i.e. no register variables   */
+        #else
+        //        Boolean Reg = true;
+        #endif
+
+        /* variables for time measurement: */
+
+        #ifdef TIMES
+            struct tms      time_info;
+        extern  int     times ();
+                        /* see library function "times" */
+        //#define Too_Small_Time 120
+        #define Too_Small_Time 1
+                        /* RTDEVS MODIFICATIONS -
+                        Before : Measurements should last at least about 2 seconds
+                        Now    : It can last as little as I want */
+        #endif
+        #ifdef TIME
+            extern long     time();
+                        /* see library function "time"  */
+
+        //#define Too_Small_Time 120
+        #define Too_Small_Time 1
+                        /* RTDEVS MODIFICATIONS -
+                        Before : Measurements should last at least about 2 seconds
+                        Now    : It can last as little as I want */
+        #endif
+
+        #ifdef CLOCK
+        // #define Too_Small_Time 2 * CLOCKS_PER_SEC
+        #define Too_Small_Time 1
+            /* RTDEVS MODIFICATIONS -
+            Before : Measurements should last at least about 2 seconds
+            Now    : It can last as little as I want */
+        #endif
+
+
+        int dhrystoneRun (int parameterNofRuns)
+    /*****/
+
+        /* main program, corresponds to procedures        */
+        /* Main and Proc_0 in the Ada version             */
+        {
+          One_Fifty       Int_1_Loc;
+          REG   One_Fifty       Int_2_Loc=0;
+          One_Fifty       Int_3_Loc;
+          REG   char            Ch_Index;
+          Enumeration     Enum_Loc;
+          Str_30          Str_1_Loc;
+          Str_30          Str_2_Loc;
+          REG   int             Run_Index;
+          REG   int             Number_Of_Runs;
+
+          /* Initializations */
+
+          Next_Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
+          Ptr_Glob = (Rec_Pointer) malloc (sizeof (Rec_Type));
+
+          Ptr_Glob->Ptr_Comp                    = Next_Ptr_Glob;
+          Ptr_Glob->Discr                       = Ident_1;
+          Ptr_Glob->variant.var_1.Enum_Comp     = Ident_3;
+          Ptr_Glob->variant.var_1.Int_Comp      = 40;
+          strcpy (Ptr_Glob->variant.var_1.Str_Comp,
+                  "DHRYSTONE PROGRAM, SOME STRING");
+          strcpy (Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
+
+          Arr_2_Glob [8][7] = 10;
+          /* Was missing in published program. Without this statement,    */
+          /* Arr_2_Glob [8][7] would have an undefined value.             */
+          /* Warning: With 16-Bit processors and Number_Of_Runs > 32000,  */
+          /* overflow may occur for this array element.                   */
+
+    /*  printf ("\n");
+      printf ("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
+      printf ("\n");
+    */
+          if (true)
+          {
+    /*    printf ("Program compiled with 'register' attribute\n");
+        printf ("\n");
+    */
+          }
+          else
+          {
+    /*    printf ("Program compiled without 'register' attribute\n");
+        printf ("\n");
+    */
+          }
+    //  printf ("Please give the number of runs through the benchmark: ");
+          {
+            int n;
+    //    scanf ("%d", &n);
+    //    Number_Of_Runs = n;
+            Number_Of_Runs = parameterNofRuns;
+          }
+    /*  printf ("\n");
+
+      printf ("Execution starts, %d runs through Dhrystone\n", Number_Of_Runs);
+    */
+          /***************/
+          /* Start timer */
+          /***************/
+
+    #ifdef TIMES
+          times (&time_info);
+      Begin_Time = (long) time_info.tms_utime;
+    #endif
+    #ifdef TIME
+          Begin_Time = time ( (long *) 0);
+    #endif
+
+    #ifdef CLOCK
+          Begin_Time = (long) clock();
+    #endif
+
+          for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
+          {
+
+            Proc_5();
+            Proc_4();
+            /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
+            Int_1_Loc = 2;
+            Int_2_Loc = 3;
+            strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
+            Enum_Loc = Ident_2;
+            Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
+            /* Bool_Glob == 1 */
+            while (Int_1_Loc < Int_2_Loc)  /* loop body executed once */
+            {
+              Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
+              /* Int_3_Loc == 7 */
+              Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
+              /* Int_3_Loc == 7 */
+              Int_1_Loc += 1;
+            } /* while */
+            /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
+            Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
+            /* Int_Glob == 5 */
+            Proc_1 (Ptr_Glob);
+            for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
+              /* loop body executed twice */
+            {
+              if (Enum_Loc == Func_1 (Ch_Index, 'C'))
+                /* then, not executed */
+              {
+                Proc_6 (Ident_1, &Enum_Loc);
+                strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
+                Int_2_Loc = Run_Index;
+                Int_Glob = Run_Index;
+              }
+            }
+            /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
+            Int_2_Loc = Int_2_Loc * Int_1_Loc;
+            Int_1_Loc = Int_2_Loc / Int_3_Loc;
+            Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
+            /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
+            Proc_2 (&Int_1_Loc);
+            /* Int_1_Loc == 5 */
+
+          } /* loop "for Run_Index" */
+
+          /**************/
+          /* Stop timer */
+          /**************/
+
+    #ifdef TIMES
+          times (&time_info);
+      End_Time = (long) time_info.tms_utime;
+    #endif
+    #ifdef TIME
+          End_Time = time ( (long *) 0);
+    #endif
+
+    #ifdef CLOCK
+          End_Time = (long) clock();
+    #endif
+
+    /*
+      printf ("Execution ends\n");
+      printf ("\n");
+      printf ("Final values of the variables used in the benchmark:\n");
+      printf ("\n");
+      printf ("Int_Glob:            %d\n", Int_Glob);
+      printf ("        should be:   %d\n", 5);
+      printf ("Bool_Glob:           %d\n", Bool_Glob);
+      printf ("        should be:   %d\n", 1);
+      printf ("Ch_1_Glob:           %c\n", Ch_1_Glob);
+      printf ("        should be:   %c\n", 'A');
+      printf ("Ch_2_Glob:           %c\n", Ch_2_Glob);
+      printf ("        should be:   %c\n", 'B');
+      printf ("Arr_1_Glob[8]:       %d\n", Arr_1_Glob[8]);
+      printf ("        should be:   %d\n", 7);
+      printf ("Arr_2_Glob[8][7]:    %d\n", Arr_2_Glob[8][7]);
+      printf ("        should be:   Number_Of_Runs + 10\n");
+      printf ("Ptr_Glob->\n");
+      printf ("  Ptr_Comp:          %d\n", (int) Ptr_Glob->Ptr_Comp);
+      printf ("        should be:   (implementation-dependent)\n");
+      printf ("  Discr:             %d\n", Ptr_Glob->Discr);
+      printf ("        should be:   %d\n", 0);
+      printf ("  Enum_Comp:         %d\n", Ptr_Glob->variant.var_1.Enum_Comp);
+      printf ("        should be:   %d\n", 2);
+      printf ("  Int_Comp:          %d\n", Ptr_Glob->variant.var_1.Int_Comp);
+      printf ("        should be:   %d\n", 17);
+      printf ("  Str_Comp:          %s\n", Ptr_Glob->variant.var_1.Str_Comp);
+      printf ("        should be:   DHRYSTONE PROGRAM, SOME STRING\n");
+      printf ("Next_Ptr_Glob->\n");
+      printf ("  Ptr_Comp:          %d\n", (int) Next_Ptr_Glob->Ptr_Comp);
+      printf ("        should be:   (implementation-dependent), same as above\n");
+      printf ("  Discr:             %d\n", Next_Ptr_Glob->Discr);
+      printf ("        should be:   %d\n", 0);
+      printf ("  Enum_Comp:         %d\n", Next_Ptr_Glob->variant.var_1.Enum_Comp);
+      printf ("        should be:   %d\n", 1);
+      printf ("  Int_Comp:          %d\n", Next_Ptr_Glob->variant.var_1.Int_Comp);
+      printf ("        should be:   %d\n", 18);
+      printf ("  Str_Comp:          %s\n",
+                                    Next_Ptr_Glob->variant.var_1.Str_Comp);
+      printf ("        should be:   DHRYSTONE PROGRAM, SOME STRING\n");
+      printf ("Int_1_Loc:           %d\n", Int_1_Loc);
+      printf ("        should be:   %d\n", 5);
+      printf ("Int_2_Loc:           %d\n", Int_2_Loc);
+      printf ("        should be:   %d\n", 13);
+      printf ("Int_3_Loc:           %d\n", Int_3_Loc);
+      printf ("        should be:   %d\n", 7);
+      printf ("Enum_Loc:            %d\n", Enum_Loc);
+      printf ("        should be:   %d\n", 1);
+      printf ("Str_1_Loc:           %s\n", Str_1_Loc);
+      printf ("        should be:   DHRYSTONE PROGRAM, 1'ST STRING\n");
+      printf ("Str_2_Loc:           %s\n", Str_2_Loc);
+      printf ("        should be:   DHRYSTONE PROGRAM, 2'ND STRING\n");
+      printf ("\n");
+    */
+          User_Time = End_Time - Begin_Time;
+
+          if (User_Time < Too_Small_Time)
+          {
+    /*    printf ("Measured time too small to obtain meaningful results\n");
+        printf ("Please increase number of runs\n");
+        printf ("\n");
+    */
+          }
+          else
+          {
+    #ifdef TIME
+            Microseconds = (float) User_Time * Mic_secs_Per_Second
+                            / (float) Number_Of_Runs;
+        Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time;
+    #endif
+    #ifdef TIMES
+            Microseconds = (float) User_Time * Mic_secs_Per_Second
+                            / ((float) HZ * ((float) Number_Of_Runs));
+        Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs)
+                            / (float) User_Time;
+    #endif
+    #ifdef CLOCK
+            Microseconds =
+                    ((float) User_Time)/((float) CLOCKS_PER_SEC) * Mic_secs_Per_Second
+                    / (float) Number_Of_Runs;
+            Dhrystones_Per_Second =
+                    (float) Number_Of_Runs / (((float) User_Time)/((float) CLOCKS_PER_SEC));
+    #endif
+
+    /*    printf ("Microseconds for one run through Dhrystone: ");
+        printf ("%6.1f \n", Microseconds);
+        printf ("Dhrystones per Second:                      ");
+        printf ("%6.1f \n", Dhrystones_Per_Second);
+        printf ("\n");
+    */
+          }
+          return 0;
+        }
+
+
+        void Proc_1 (Rec_Pointer Ptr_Val_Par)
+    /* Converted to ANSI style declaration. JRJ */
+    /******************/
+
+    /* REG Rec_Pointer Ptr_Val_Par;  */
+        /* executed once */
+        {
+          REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
+          /* == Ptr_Glob_Next */
+          /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp,    */
+          /* corresponds to "rename" in Ada, "with" in Pascal           */
+
+          structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob);
+          Ptr_Val_Par->variant.var_1.Int_Comp = 5;
+          Next_Record->variant.var_1.Int_Comp
+                  = Ptr_Val_Par->variant.var_1.Int_Comp;
+          Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
+          Proc_3 (&Next_Record->Ptr_Comp);
+          /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp
+                              == Ptr_Glob->Ptr_Comp */
+          if (Next_Record->Discr == Ident_1)
+            /* then, executed */
+          {
+            Next_Record->variant.var_1.Int_Comp = 6;
+            Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp,
+                    &Next_Record->variant.var_1.Enum_Comp);
+            Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
+            Proc_7 (Next_Record->variant.var_1.Int_Comp, 10,
+                    &Next_Record->variant.var_1.Int_Comp);
+          }
+          else /* not executed */
+            structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
+        } /* Proc_1 */
+
+
+        void Proc_2 (One_Fifty *Int_Par_Ref)
+    /* Converted to ANSI style declaration. JRJ */
+    /******************/
+        /* executed once */
+        /* *Int_Par_Ref == 1, becomes 4 */
+
+    /* One_Fifty   *Int_Par_Ref; */
+        {
+          One_Fifty  Int_Loc;
+          Enumeration   Enum_Loc = Ident_1;
+
+          Int_Loc = *Int_Par_Ref + 10;
+          do /* executed once */
+            if (Ch_1_Glob == 'A')
+              /* then, executed */
+            {
+              Int_Loc -= 1;
+              *Int_Par_Ref = Int_Loc - Int_Glob;
+              Enum_Loc = Ident_1;
+            } /* if */
+          while (Enum_Loc != Ident_1); /* true */
+        } /* Proc_2 */
+
+
+        void Proc_3 (Rec_Pointer *Ptr_Ref_Par)
+    /* Converted to ANSI style declaration. JRJ */
+    /******************/
+        /* executed once */
+        /* Ptr_Ref_Par becomes Ptr_Glob */
+
+    /* Rec_Pointer *Ptr_Ref_Par; */
+
+        {
+          if (Ptr_Glob != Null)
+            /* then, executed */
+            *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
+          Proc_7 (10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
+        } /* Proc_3 */
+
+
+        void Proc_4 (void) /* without parameters */
+    /* Converted to ANSI style declaration. JRJ */
+    /*******/
+        /* executed once */
+        {
+          Boolean Bool_Loc;
+
+          Bool_Loc = Ch_1_Glob == 'A';
+          Bool_Glob = Bool_Loc | Bool_Glob;
+          Ch_2_Glob = 'B';
+        } /* Proc_4 */
+
+
+        void Proc_5 (void)
+    /* Converted to ANSI style declaration. JRJ */
+    /*******/
+        /* executed once */
+        {
+          Ch_1_Glob = 'A';
+          Bool_Glob = false;
+        } /* Proc_5 */
+
+
+        /* Procedure for the assignment of structures,          */
+        /* if the C compiler doesn't support this feature       */
+    #ifdef  NOSTRUCTASSIGN
+        memcpy (d, s, l)
+    register char   *d;
+    register char   *s;
+    register int    l;
+    {
+            while (l--) *d++ = *s++;
+    }
+    #endif
+};
+
+
+#endif

+ 209 - 0
benchmarks/dhry/dhry_2.c

@@ -0,0 +1,209 @@
+/*
+ ****************************************************************************
+ *
+ *                   "DHRYSTONE" Benchmark Program
+ *                   -----------------------------
+ *                                                                            
+ *  Version:    C, Version 2.1
+ *                                                                            
+ *  File:       dhry_2.c (part 3 of 3)
+ *
+ *  Date:       May 25, 1988
+ *
+ *  Author:     Reinhold P. Weicker
+ *              converted to ANSI C by Jeremy Johnson.  1/20/00
+ *
+ ****************************************************************************
+ */
+
+#include "dhry.h"
+
+#ifndef REG
+#define REG
+        /* REG becomes defined as empty */
+        /* i.e. no register variables   */
+#endif
+
+extern  int     Int_Glob;
+extern  char    Ch_1_Glob;
+
+
+void Proc_6 (Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par)
+/* Converted to ANSI style declaration. JRJ */
+/*********************************/
+    /* executed once */
+    /* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
+
+/*
+Enumeration  Enum_Val_Par;
+Enumeration *Enum_Ref_Par;
+*/
+{
+  *Enum_Ref_Par = Enum_Val_Par;
+  if (! Func_3 (Enum_Val_Par))
+    /* then, not executed */
+    *Enum_Ref_Par = Ident_4;
+  switch (Enum_Val_Par)
+  {
+    case Ident_1: 
+      *Enum_Ref_Par = Ident_1;
+      break;
+    case Ident_2: 
+      if (Int_Glob > 100)
+        /* then */
+      *Enum_Ref_Par = Ident_1;
+      else *Enum_Ref_Par = Ident_4;
+      break;
+    case Ident_3: /* executed */
+      *Enum_Ref_Par = Ident_2;
+      break;
+    case Ident_4: break;
+    case Ident_5: 
+      *Enum_Ref_Par = Ident_3;
+      break;
+  } /* switch */
+} /* Proc_6 */
+
+
+void Proc_7 (One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref)
+/* Converted to ANSI style declaration. JRJ */
+/**********************************************/
+    /* executed three times                                      */ 
+    /* first call:      Int_1_Par_Val == 2, Int_2_Par_Val == 3,  */
+    /*                  Int_Par_Ref becomes 7                    */
+    /* second call:     Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
+    /*                  Int_Par_Ref becomes 17                   */
+    /* third call:      Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
+    /*                  Int_Par_Ref becomes 18                   */
+/*
+One_Fifty       Int_1_Par_Val;
+One_Fifty       Int_2_Par_Val;
+One_Fifty      *Int_Par_Ref;
+*/
+{
+  One_Fifty Int_Loc;
+
+  Int_Loc = Int_1_Par_Val + 2;
+  *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
+} /* Proc_7 */
+
+
+void Proc_8 (Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val)
+/* Converted to ANSI style declaration. JRJ */
+/*********************************************************************/
+    /* executed once      */
+    /* Int_Par_Val_1 == 3 */
+    /* Int_Par_Val_2 == 7 */
+/*
+Arr_1_Dim       Arr_1_Par_Ref;
+Arr_2_Dim       Arr_2_Par_Ref;
+int             Int_1_Par_Val;
+int             Int_2_Par_Val;
+*/
+{
+  REG One_Fifty Int_Index;
+  REG One_Fifty Int_Loc;
+
+  Int_Loc = Int_1_Par_Val + 5;
+  Arr_1_Par_Ref [Int_Loc] = Int_2_Par_Val;
+  Arr_1_Par_Ref [Int_Loc+1] = Arr_1_Par_Ref [Int_Loc];
+  Arr_1_Par_Ref [Int_Loc+30] = Int_Loc;
+  for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
+    Arr_2_Par_Ref [Int_Loc] [Int_Index] = Int_Loc;
+  Arr_2_Par_Ref [Int_Loc] [Int_Loc-1] += 1;
+  Arr_2_Par_Ref [Int_Loc+20] [Int_Loc] = Arr_1_Par_Ref [Int_Loc];
+  Int_Glob = 5;
+} /* Proc_8 */
+
+
+Enumeration Func_1 (Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
+/* Converted to ANSI style declaration. JRJ */
+/*************************************************/
+    /* executed three times                                         */
+    /* first call:      Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R'    */
+    /* second call:     Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C'    */
+    /* third call:      Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C'    */
+
+/*
+Capital_Letter   Ch_1_Par_Val;
+Capital_Letter   Ch_2_Par_Val;
+*/
+{
+  Capital_Letter        Ch_1_Loc;
+  Capital_Letter        Ch_2_Loc;
+
+  Ch_1_Loc = Ch_1_Par_Val;
+  Ch_2_Loc = Ch_1_Loc;
+  if (Ch_2_Loc != Ch_2_Par_Val)
+    /* then, executed */
+    return (Ident_1);
+  else  /* not executed */
+  {
+    Ch_1_Glob = Ch_1_Loc;
+    return (Ident_2);
+   }
+} /* Func_1 */
+
+
+Boolean Func_2 (Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref)
+/* Converted to ANSI style declaration. JRJ */
+/*************************************************/
+    /* executed once */
+    /* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
+    /* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
+
+/*
+Str_30  Str_1_Par_Ref;
+Str_30  Str_2_Par_Ref;
+*/
+{
+  REG One_Thirty        Int_Loc;
+      Capital_Letter    Ch_Loc;
+
+  Int_Loc = 2;
+  while (Int_Loc <= 2) /* loop body executed once */
+    if (Func_1 (Str_1_Par_Ref[Int_Loc],
+                Str_2_Par_Ref[Int_Loc+1]) == Ident_1)
+      /* then, executed */
+    {
+      Ch_Loc = 'A';
+      Int_Loc += 1;
+    } /* if, while */
+  if (Ch_Loc >= 'W' && Ch_Loc < 'Z')
+    /* then, not executed */
+    Int_Loc = 7;
+  if (Ch_Loc == 'R')
+    /* then, not executed */
+    return (true);
+  else /* executed */
+  {
+    if (strcmp (Str_1_Par_Ref, Str_2_Par_Ref) > 0)
+      /* then, not executed */
+    {
+      Int_Loc += 7;
+      Int_Glob = Int_Loc;
+      return (true);
+    }
+    else /* executed */
+      return (false);
+  } /* if Ch_Loc */
+} /* Func_2 */
+
+
+Boolean Func_3 (Enumeration Enum_Par_Val)
+/* Converted to ANSI style declaration. JRJ */
+/***************************/
+    /* executed once        */
+    /* Enum_Par_Val == Ident_3 */
+/* Enumeration Enum_Par_Val; */
+{
+  Enumeration Enum_Loc;
+
+  Enum_Loc = Enum_Par_Val;
+  if (Enum_Loc == Ident_3)
+    /* then, executed */
+    return (true);
+  else /* not executed */
+    return (false);
+} /* Func_3 */
+

+ 99 - 0
benchmarks/model_properties.py

@@ -0,0 +1,99 @@
+def LI(width: int, depth: int) -> dict:
+    properties = {}
+    properties["Atomic Models"] = (width - 1) * (depth - 1) + 1
+    properties["External Incoming Connections"] = width * (depth - 1) + 1
+    properties["External Outgoing Connections"] = depth
+    properties["Internal Connections"] = 0
+    properties["Events"] = (width - 1) * (depth - 1) + 1
+    return properties
+
+def HI(width: int, depth: int) -> dict:
+    properties = {}
+    properties["Atomic Models"] = (width - 1) * (depth - 1) + 1
+    properties["External Incoming Connections"] = width * (depth - 1) + 1
+    properties["External Outgoing Connections"] = depth
+    properties["Internal Connections"] = (width - 2) * (depth - 1) if width > 2 else 0
+    properties["Events"] = 1 + (depth - 1) * ((width - 1) * width) / 2
+    return properties
+
+def HO(width: int, depth: int) -> dict:
+    properties = {}
+    properties["Atomic Models"] = (width - 1) * (depth - 1) + 1
+    properties["External Incoming Connections"] = (width + 1) * (depth - 1) + 1
+    properties["External Outgoing Connections"] = width * (depth - 1) + 1
+    properties["Internal Connections"] = (width - 2) * (depth - 1) if width > 2 else 0
+    properties["Events"] = 1 + (depth - 1) * ((width - 1) * width) / 2
+    return properties
+
+def HOmod(width: int, depth: int) -> dict:
+    properties = {}
+    properties["Atomic Models"] = (width - 1 + ((width - 1) * width) / 2) * (depth - 1) + 1
+    properties["External Incoming Connections"] = (2 * (width - 1) + 1) * (depth - 1) + 1
+    properties["External Outgoing Connections"] = depth
+    properties["Internal Connections"] = ((width - 1) ** 2 + ((width - 1) * width) / 2) * (depth - 1)
+    properties["Events"] = 1
+    for i in range(1, depth - 1):
+        e = (1 + (i - 1) * (width - 1)) * ((width - 1) * width) / 2 + (width - 1) * (width + (i - 1) * (width - 1))
+        properties["Events"] += e
+    return properties
+
+def dLI(width: int, depth: int) -> dict:
+    properties = LI(width, depth)
+    properties["Created"] = (width - 1) * (depth - 1)
+    properties["Connected"] = (width - 1) * (depth - 1)
+    return properties
+
+def mdLI(width: int, depth: int) -> dict:
+    properties = dLI(width, depth)
+    properties["Atomic Models"] += depth
+    return properties
+
+def dHI(width: int, depth: int) -> dict:
+    properties = HI(width, depth)
+    properties["Created"] = (width - 1) * (depth - 1)
+    properties["Connected"] = 2 * (width - 1) * (depth - 1)
+    return properties
+
+def mdHI(width: int, depth: int) -> dict:
+    properties = dHI(width, depth)
+    properties["Atomic Models"] += depth
+    return properties
+
+def model_properties(model: str, width: int, depth: int) -> dict:
+    match model:
+        case "LI":
+            return LI(width, depth)
+        case "HI":
+            return HI(width, depth)
+        case "HO":
+            return HO(width, depth)
+        case "HOmod":
+            return HOmod(width, depth)
+        case "HI2LI":
+            return {}
+        case "LI2HI":
+            return {}
+        case "dLI":
+            return dLI(width, depth)
+        case "mdLI":
+            return mdLI(width, depth)
+        case "dHI":
+            return dHI(width, depth)
+        case "mdHI":
+            return mdHI(width, depth)
+        case _:
+            return {}
+
+def display_model_properties(model: str, width: int, depth: int):
+    properties = model_properties(model, width, depth)
+    print(f"Model: {model}")
+    for key, value in properties.items():
+        print(f"Number of {key}: {value:,}")
+    print("="*50)
+
+
+if __name__ == "__main__":
+    # display_model_properties("LI", 100, 100)
+    display_model_properties("HI", 100, 100)
+    # display_model_properties("HO", 100, 100)
+    # display_model_properties("HOmod", 30, 30)

+ 265 - 0
benchmarks/plotNumberOfDCP.py

@@ -0,0 +1,265 @@
+import argparse
+import pandas as pd
+import numpy as np
+import matplotlib.pyplot as plt
+from model_properties import model_properties
+
+# ==========================================
+#               Model Formulas
+# ==========================================
+
+def model_dLI(width, depth, n):
+    """
+    dLI Model Formula:
+    DCP = ((n + 1)(d - 1) + 1) * floor((w - 1) / n) + remaining
+    remaining = (n_2 + 1)(d - 1) + 1  if n_2 > 0 else 0
+    where n_2 = (w - 1) % n
+    """
+    w = np.atleast_1d(width)
+    d = np.atleast_1d(depth)
+    n_val = np.atleast_1d(n)
+
+    # Broadcast scalar n if w/d are arrays
+    if len(n_val) == 1 and len(w) > 1:
+        n_val = np.full_like(w, n_val[0])
+
+    # Ensure n >= 1
+    n_val = np.maximum(n_val, 1)
+
+    # Main Term
+    floor_term = np.floor((w - 1) / n_val)
+    term_main = ((n_val + 1) * (d - 1) + 1) * floor_term
+
+    # Remaining Term
+    n_2 = (w - 1) % n_val
+    term_rem = (n_2 + 1) * (d - 1) + 1
+    term_rem = np.where(n_2 > 0, term_rem, 0)
+
+    return term_main + term_rem
+
+def model_dHI(width, depth, n):
+    """
+    dHI Model Formula:
+    DCP = c1 + ci * floor((w - n - 1) / n) + remaining
+    c1 = (2n + 1)(d - 1) + 1
+    ci = (2n + 2)(d - 1) + 1
+    remaining = (2n_2 + 1)(d - 1) + 1  if n_2 > 0 else 0
+    where n_2 = (w - n - 1) % n
+    """
+    w = np.atleast_1d(width)
+    d = np.atleast_1d(depth)
+    n_val = np.atleast_1d(n)
+
+    if len(n_val) == 1 and len(w) > 1:
+        n_val = np.full_like(w, n_val[0])
+
+    # Safety: clamp n to width-1 to preserve physical meaning (chunk size cannot exceed width)
+    # This prevents negative floor values when w < n+1
+    n_eff = np.where(w > 1, np.minimum(n_val, w - 1), 1)
+
+    # First term (c1)
+    term_c1 = (2 * n_eff + 1) * (d - 1) + 1
+
+    # Intermediate term (ci)
+    val_for_floor = w - n_eff - 1
+    floor_term = np.floor(val_for_floor / n_eff)
+    term_ci = ((2 * n_eff + 2) * (d - 1) + 1) * floor_term
+
+    # Remaining term
+    n_2 = val_for_floor % n_eff
+    term_rem = (2 * n_2 + 1) * (d - 1) + 1
+    term_rem = np.where(n_2 > 0, term_rem, 0)
+
+    return term_c1 + term_ci + term_rem
+
+
+MODELS = {
+    'dLI': model_dLI,
+    'dHI': model_dHI,
+}
+
+
+def get_model_func(model_name):
+    return MODELS.get(model_name)
+
+
+# ==========================================
+#               Execution Modes
+# ==========================================
+
+def run_vary_n(args):
+    """Mode 1: Fix W/D, Vary n"""
+    print(f"Running 'Vary N' | Model: {args.model}, Width: {args.width}, Depth: {args.depth}")
+
+    func = get_model_func(args.model)
+    if not func:
+        print(f"Error: Model '{args.model}' not found.")
+        return
+
+    n_vals = np.arange(1, args.limit + 1)
+    Y = func(args.width, args.depth, n_vals)
+
+    plt.figure(figsize=(10, 6))
+    plt.plot(n_vals, Y, marker='o', label=f'{args.model}: W={args.width}, D={args.depth}')
+    plt.yscale('log')
+    plt.xlabel('n (Models per cycle)')
+    plt.ylabel('Number of DCP calls')
+    plt.title(f'#DCP Calls vs n for {args.model}')
+    plt.legend()
+    plt.grid(True, which="both", ls="--")
+    plt.tight_layout()
+    plt.show()
+
+
+def run_vary_dim(args):
+    """Mode 2: Fix n, Vary Width/Depth (The 'Old Code' adaptation)"""
+    print(f"Running 'Vary Dimensions' | Model: {args.model}, n: {args.n}")
+
+    func = get_model_func(args.model)
+    if not func:
+        print(f"Error: Model '{args.model}' not found.")
+        return
+
+    # Generate grid of W and D
+    w_vals = np.arange(2, args.limit + 1)
+    d_vals = np.arange(2, args.limit + 1)
+    width, depth = np.meshgrid(w_vals, d_vals)
+
+    # Calculate X axis (Total Atomic Models)
+    X = (width - 1) * (depth - 1) + 1
+
+    # Calculate Y axis (DCP Calls)
+    Y = func(width, depth, args.n)
+
+    plt.figure(figsize=(10, 6))
+    plt.scatter(X.flatten(), Y.flatten(), s=5, alpha=0.5, label=f'{args.model}, n={args.n}')
+    plt.yscale('log')
+    # plt.xscale('log') # Optional: log scale for X if desired
+    plt.xlabel('Number of atomic models')
+    plt.ylabel('Number of DCP calls')
+    plt.title(f'#DCP Calls vs Atomic Models for {args.model}')
+    plt.legend()
+    plt.grid(True, which="both", ls="--")
+    plt.tight_layout()
+    plt.show()
+
+def clean_data(df):
+    df["total_time"] = (
+        df["simulation_time"]
+        + df["creation_time"]
+        + df["setup_time"]
+    )
+
+    possible_group_cols = ["model_type", "depth", "width", "number", "total_time"]
+    grouping_cols = [c for c in possible_group_cols if c in df.columns]
+
+    def clean(group):
+        Q1 = group["total_time"].quantile(0.25)
+        Q3 = group["total_time"].quantile(0.75)
+        IQR = Q3 - Q1
+        lower = Q1 - 1.5 * IQR
+        upper = Q3 + 1.5 * IQR
+        return group[(group["total_time"] >= lower) & (group["total_time"] <= upper)]
+
+    cleaned = (
+        df.groupby(grouping_cols, group_keys=False)[grouping_cols]
+          .apply(clean)
+    )
+
+    return cleaned
+
+def run_csv_mode(args):
+    """Mode 3: Read CSV, calculate theoretical DCP, plot vs Runtime"""
+    print(f"Running 'CSV Mode' | File: {args.file}")
+
+    try:
+        df = pd.read_csv(args.file)
+    except FileNotFoundError:
+        print(f"Error: File {args.file} not found.")
+        return
+    df = clean_data(df)
+
+    # Create 'dcp_calls' column
+    df['dcp_calls'] = 0.0
+
+    # Determine model per row or globally
+    if 'model_type' not in df.columns:
+        df['model_type'] = args.model
+
+    # Check for unknown models in CSV
+    unique_models = df['model_type'].unique()
+    if len(unique_models) > 1:
+        print(f"Error: More than one model type found. Found: {unique_models}")
+        return
+
+    model = unique_models[0]
+    if model not in MODELS:
+        print(f"Error: CSV contains unknown model '{model}'.")
+        return
+
+    df['atomic_models'] = (df['width'] - 1) * (df['depth'] - 1) + 1
+
+    # Calculate DCP calls by group (efficient for different models)
+    for m_name, group in df.groupby('model_type'):
+        func = get_model_func(m_name)
+        # Fallback to default if model not found in dictionary
+        if not func:
+            func = get_model_func(args.model)
+
+        # Use 'n' from CSV if available, otherwise CLI default
+        n_vals = group['number'].values if 'number' in group.columns else args.n
+
+        df.loc[group.index, 'dcp_calls'] = func(group['width'].values, group['depth'].values, n_vals)
+
+    plt.figure(figsize=(10, 6))
+    scatter = plt.scatter(df['dcp_calls'], df['total_time'],
+                          c=df['atomic_models'], cmap='viridis', alpha=0.7, edgecolors='k', s=50)
+
+    plt.colorbar(scatter, label='# Atomic Models')
+    plt.xlabel('Theoretical DCP Calls')
+    plt.ylabel('Total Simulation Time (s)')
+    plt.title(f'Run Time vs DCP Calls for {model}')
+    plt.grid(True, linestyle='--', alpha=0.6)
+    plt.tight_layout()
+    plt.show()
+
+
+# ==========================================
+#               CLI
+# ==========================================
+
+def main():
+    parser = argparse.ArgumentParser(description="DCP Calculation Tool")
+    subparsers = parser.add_subparsers(dest='mode', required=True, help='Operation Mode')
+
+    # Common arguments
+    parent_parser = argparse.ArgumentParser(add_help=False)
+    parent_parser.add_argument('--model', '-m', type=str, choices=MODELS.keys(), help='Model formula to use')
+
+    # 1. Vary N
+    parser_n = subparsers.add_parser('created', parents=[parent_parser], help='Fix Width and Depth, Vary number of models created per cycle')
+    parser_n.add_argument('--width', '-w', type=int, default=100)
+    parser_n.add_argument('--depth', '-d', type=int, default=100)
+    parser_n.add_argument('--limit', '-l', type=int, default=100, help='Max n')
+
+    # 2. Vary Dimensions
+    parser_dim = subparsers.add_parser('dimensions', parents=[parent_parser], help='Fix n, Vary W/D')
+    parser_dim.add_argument('--n', type=int, default=2)
+    parser_dim.add_argument('--limit', '-l', type=int, default=100, help='Max width/depth')
+
+    # 3. CSV
+    parser_csv = subparsers.add_parser('time', parents=[parent_parser], help='Read CSV and plot DCP calls against simulation time')
+    parser_csv.add_argument('--file', '-f', type=str)
+    parser_csv.add_argument('--n', type=int, default=1, help='Default n if not in CSV')
+
+    args = parser.parse_args()
+
+    if args.mode == 'created':
+        run_vary_n(args)
+    elif args.mode == 'dimensions':
+        run_vary_dim(args)
+    elif args.mode == 'time':
+        run_csv_mode(args)
+
+if __name__ == "__main__":
+    main()

+ 84 - 0
benchmarks/plot_time-models.py

@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+import argparse
+from pathlib import Path
+import pandas as pd
+import matplotlib.pyplot as plt
+from copy import copy
+
+def remove_outliers_iqr(df):
+    groups = ["model_type", "width", "depth"]
+
+    q1 = df.groupby(groups)["simulation_time"].quantile(0.25)
+    q3 = df.groupby(groups)["simulation_time"].quantile(0.75)
+
+    iqr = q3 - q1
+    lower = q1 - 1.5 * iqr
+    upper = q3 + 1.5 * iqr
+
+    # Join bounds back to original rows
+    bounds = pd.concat([lower, upper], axis=1)
+    bounds.columns = ["lower", "upper"]
+
+    df = df.join(bounds, on=groups)
+
+    return df[(df["simulation_time"] >= df["lower"]) &
+              (df["simulation_time"] <= df["upper"])].drop(columns=["lower", "upper"])
+
+
+def process_file(path, max: int = 0):
+    """Load file, remove outliers, compute atomic models, average per atomic count."""
+    df = pd.read_csv(path).copy()
+    if max > 0:
+        df = df[df["width"] <= max].copy()
+        df = df[df["depth"] <= max].copy()
+
+    df = remove_outliers_iqr(df)
+    df["atomic_models"] = (df["width"] - 1) * (df["depth"] - 1) + 1
+    grouped = df.groupby("atomic_models", as_index=False)["simulation_time"].mean()
+
+    label = path.parent.name + "-" + path.stem
+    return label, grouped
+
+
+def plot_results(results_dict, name):
+    plt.figure(figsize=(16, 9))
+
+    for label, df in results_dict.items():
+        plt.plot(
+            df["atomic_models"],
+            df["simulation_time"],
+            marker="o",
+            linestyle="-",
+            label=label
+        )
+
+    plt.title("Mean Simulation Time vs Atomic Model Count")
+    plt.xlabel("# Atomic Models")
+    plt.ylabel("Mean Simulation Time (s)")
+    plt.grid(True)
+    plt.legend()
+    plt.tight_layout()
+
+    output_path = f"../Plots/{name}_NA.png"
+    plt.savefig(output_path, dpi=300)
+    print(f"Saved plot: {output_path}")
+
+
+def main():
+    parser = argparse.ArgumentParser(description="Compare multiple model results by atomic-model count.")
+    parser.add_argument("csv_files", nargs="+", type=Path, help="Input CSV files")
+    parser.add_argument("-n", "--name", type=str, default="comparison", help="Output file name")
+    parser.add_argument('-m', '--max', type=int, default=0, help='Maximum value of the varying parameter')
+
+    args = parser.parse_args()
+
+    results = {}
+    for file in args.csv_files:
+        label, grouped = process_file(file, args.max)
+        results[label] = grouped
+
+    plot_results(results, args.name)
+
+
+if __name__ == "__main__":
+    main()

+ 0 - 0
benchmarks/pythonpdevs-minimal/__init__.py


+ 267 - 0
benchmarks/pythonpdevs-minimal/devstone.py

@@ -0,0 +1,267 @@
+from abc import ABC, abstractmethod
+from collections import defaultdict
+
+from pystone import pystones
+from pypdevs.minimal import AtomicDEVS, CoupledDEVS
+from pypdevs.infinity import INFINITY
+from pypdevs.simulator import Simulator
+
+
+class DelayedAtomic(AtomicDEVS):
+    def __init__(self, name: str, int_delay: float, ext_delay: float, add_out_port: bool = False, prep_time=0):
+        super().__init__(name)
+
+        self.int_delay = int_delay
+        self.ext_delay = ext_delay
+        self.prep_time = prep_time
+
+        self.i_in = self.addInPort("i_in")
+
+        if add_out_port:
+            self.o_out = self.addOutPort("o_out")
+
+    def intTransition(self):
+        if self.int_delay:
+            pystones(self.int_delay)
+
+        return "passive"
+
+    def timeAdvance(self):
+        if self.state == "active":
+            return self.prep_time
+        else:
+            return INFINITY
+
+    def outputFnc(self):
+        if hasattr(self, "o_out"):
+            return {self.o_out: [0]}
+        return {}
+
+    def extTransition(self, inputs):
+        if self.ext_delay:
+            pystones(self.ext_delay)
+
+        return "active"
+
+
+class DelayedAtomicStats(DelayedAtomic):
+    def __init__(self, name: str, int_delay: float, ext_delay: float, add_out_port: bool = False, prep_time=0):
+        super().__init__(name, int_delay, ext_delay, add_out_port, prep_time)
+
+        self.int_count = 0
+        self.ext_count = 0
+
+    def intTransition(self):
+        self.int_count += 1
+        return super().intTransition()
+
+    def extTransition(self, inputs):
+        self.ext_count += 1
+        return super().extTransition(inputs)
+
+
+class DEVStoneWrapper(CoupledDEVS, ABC):
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float,
+                 add_atomic_out_ports: bool = False, prep_time=0, stats=False):
+        super().__init__(name)
+
+        self.depth = depth
+        self.width = width
+        self.int_delay = int_delay
+        self.ext_delay = ext_delay
+        self.prep_time = prep_time
+        self.stats = stats
+        self.add_atomic_out_ports = add_atomic_out_ports
+
+        self.i_in = self.addInPort("i_in")
+        self.o_out = self.addOutPort("o_out")
+
+        if depth < 1:
+            raise ValueError("Invalid depth")
+        if width < 1:
+            raise ValueError("Invalid width")
+        if int_delay < 0:
+            raise ValueError("Invalid int_delay")
+        if ext_delay < 0:
+            raise ValueError("Invalid ext_delay")
+
+        if depth == 1:
+            if self.stats:
+                atomic = DelayedAtomicStats("Atomic_0_0", int_delay, ext_delay, add_out_port=True, prep_time=prep_time)
+            else:
+                atomic = DelayedAtomic("Atomic_0_0", int_delay, ext_delay, add_out_port=True, prep_time=prep_time)
+
+            self.addSubModel(atomic)
+
+            self.connectPorts(self.i_in, atomic.i_in)
+            self.connectPorts(atomic.o_out, self.o_out)
+        else:
+            coupled = self.gen_coupled()
+            self.addSubModel(coupled)
+            self.connectPorts(self.i_in, coupled.i_in)
+            self.connectPorts(coupled.o_out, self.o_out)
+
+            for idx in range(width - 1):
+                if self.stats:
+                    atomic = DelayedAtomicStats("Atomic_%d_%d" % (depth - 1, idx), int_delay, ext_delay,
+                                                add_out_port=add_atomic_out_ports, prep_time=prep_time)
+                else:
+                    atomic = DelayedAtomic("Atomic_%d_%d" % (depth - 1, idx), int_delay, ext_delay,
+                                           add_out_port=add_atomic_out_ports, prep_time=prep_time)
+                self.addSubModel(atomic)
+
+    @abstractmethod
+    def gen_coupled(self):
+        """ :return a coupled method with i_in and o_out ports"""
+        pass
+
+
+class LI(DEVStoneWrapper):
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False):
+        super().__init__(name, depth, width, int_delay, ext_delay, add_atomic_out_ports=False, prep_time=prep_time,
+                         stats=stats)
+
+        for idx in range(1, len(self.component_set)):
+            assert isinstance(self.component_set[idx], AtomicDEVS)
+            self.connectPorts(self.i_in, self.component_set[idx].i_in)
+
+    def gen_coupled(self):
+        return LI("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                  prep_time=self.prep_time, stats=self.stats)
+
+
+class HI(DEVStoneWrapper):
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False):
+        super().__init__(name, depth, width, int_delay, ext_delay, add_atomic_out_ports=True, prep_time=prep_time,
+                         stats=stats)
+
+        if len(self.component_set) > 1:
+            assert isinstance(self.component_set[-1], AtomicDEVS)
+            self.connectPorts(self.i_in, self.component_set[-1].i_in)
+
+        for idx in range(1, len(self.component_set) - 1):
+            assert isinstance(self.component_set[idx], AtomicDEVS)
+            self.connectPorts(self.component_set[idx].o_out, self.component_set[idx + 1].i_in)
+            self.connectPorts(self.i_in, self.component_set[idx].i_in)
+
+    def gen_coupled(self):
+        return HI("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                  prep_time=self.prep_time, stats=self.stats)
+
+
+class HO(DEVStoneWrapper):
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False):
+        super().__init__(name, depth, width, int_delay, ext_delay, add_atomic_out_ports=True, prep_time=prep_time,
+                         stats=stats)
+
+        self.i_in2 = self.addInPort("i_in2")
+        self.o_out2 = self.addOutPort("o_out2")
+
+        assert len(self.component_set) > 0
+        if isinstance(self.component_set[0], CoupledDEVS):
+            self.connectPorts(self.i_in, self.component_set[0].i_in2)
+
+        if len(self.component_set) > 1:
+            assert isinstance(self.component_set[-1], AtomicDEVS)
+            self.connectPorts(self.i_in2, self.component_set[-1].i_in)
+            self.connectPorts(self.component_set[-1].o_out, self.o_out2)
+
+        for idx in range(1, len(self.component_set) - 1):
+            assert isinstance(self.component_set[idx], AtomicDEVS)
+            self.connectPorts(self.component_set[idx].o_out, self.component_set[idx + 1].i_in)
+            self.connectPorts(self.i_in2, self.component_set[idx].i_in)
+            self.connectPorts(self.component_set[idx].o_out, self.o_out2)
+
+    def gen_coupled(self):
+        return HO("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                  prep_time=self.prep_time, stats=self.stats)
+
+
+class HOmod(CoupledDEVS):
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False):
+        super().__init__(name)
+
+        self.depth = depth
+        self.width = width
+        self.int_delay = int_delay
+        self.ext_delay = ext_delay
+        self.prep_time = prep_time
+        self.stats = stats
+
+        self.i_in = self.addInPort("i_in")
+        self.i_in2 = self.addInPort("i_in2")
+        self.o_out = self.addOutPort("o_out")
+
+        if depth < 1:
+            raise ValueError("Invalid depth")
+        if width < 1:
+            raise ValueError("Invalid width")
+        if int_delay < 0:
+            raise ValueError("Invalid int_delay")
+        if ext_delay < 0:
+            raise ValueError("Invalid ext_delay")
+
+        if depth == 1:
+            if self.stats:
+                atomic = DelayedAtomicStats("Atomic_0_0", int_delay, ext_delay, add_out_port=True, prep_time=prep_time)
+            else:
+                atomic = DelayedAtomic("Atomic_0_0", int_delay, ext_delay, add_out_port=True, prep_time=prep_time)
+            self.addSubModel(atomic)
+
+            self.connectPorts(self.i_in, atomic.i_in)
+            self.connectPorts(atomic.o_out, self.o_out)
+        else:
+            coupled = HOmod("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay, prep_time=prep_time, stats=stats)
+            self.addSubModel(coupled)
+            self.connectPorts(self.i_in, coupled.i_in)
+            self.connectPorts(coupled.o_out, self.o_out)
+
+            if width >= 2:
+                atomics = defaultdict(list)
+
+                # Generate atomic components
+                for i in range(width):
+                    min_row_idx = 0 if i < 2 else i - 1
+                    for j in range(min_row_idx, width - 1):
+                        if self.stats:
+                            atomic = DelayedAtomicStats("Atomic_%d_%d_%d" % (depth - 1, i, j), int_delay, ext_delay,
+                                                   add_out_port=True, prep_time=prep_time)
+                        else:
+                            atomic = DelayedAtomic("Atomic_%d_%d_%d" % (depth - 1, i, j), int_delay, ext_delay,
+                                                   add_out_port=True, prep_time=prep_time)
+                        self.addSubModel(atomic)
+                        atomics[i].append(atomic)
+
+                # Connect EIC
+                for atomic in atomics[0]:
+                    self.connectPorts(self.i_in2, atomic.i_in)
+                for i in range(1, width):
+                    atomic_set = atomics[i]
+                    self.connectPorts(self.i_in2, atomic_set[0].i_in)
+
+                # Connect IC
+                for atomic in atomics[0]:  # First row to coupled component
+                    self.connectPorts(atomic.o_out, coupled.i_in2)
+                for i in range(len(atomics[1])):  # Second to first rows
+                    for j in range(len(atomics[0])):
+                        self.connectPorts(atomics[1][i].o_out, atomics[0][j].i_in)
+                for i in range(2, width):  # Rest of rows
+                    for j in range(len(atomics[i])):
+                        self.connectPorts(atomics[i][j].o_out, atomics[i - 1][j + 1].i_in)
+
+
+if __name__ == '__main__':
+    import sys
+
+    sys.setrecursionlimit(10000)
+    root = HOmod("Root", 4, 3, 0, 0)
+    sim = Simulator(root)
+    sim.setVerbose(None)
+    # sim.setTerminationTime(10.0)
+    sim.setStateSaving("custom")
+    sim.simulate()

+ 36 - 0
benchmarks/pythonpdevs-minimal/generator.py

@@ -0,0 +1,36 @@
+from typing import Any
+
+from pypdevs.minimal import AtomicDEVS
+from pypdevs.infinity import INFINITY
+
+
+class Generator(AtomicDEVS):
+
+    def __init__(self, name, num_outputs=1, period=None):
+        super(Generator, self).__init__(name=name)
+        self.num_outputs = num_outputs
+        self.period = period
+        self.state = "active"
+        self.o_out = self.addOutPort("o_out")
+
+    def intTransition(self):
+        if self.state == "active" and self.period is not None:
+            self.state = "waiting"
+        elif self.state == "waiting":
+            self.state = "active"
+        else:
+            self.state = "passive"
+
+    def timeAdvance(self):
+        if self.state == "active":
+            return 0
+        elif self.state == "waiting":
+            return self.period
+        else:
+            return INFINITY
+
+    def outputFnc(self):
+        return {self.o_out: list(range(self.num_outputs))}
+
+    def extTransition(self, inputs):
+        pass

+ 75 - 0
benchmarks/pythonpdevs-minimal/main.py

@@ -0,0 +1,75 @@
+import argparse
+import sys
+import time
+from pypdevs.minimal import CoupledDEVS
+from pypdevs.minimal import Simulator
+
+from devstone import LI, HI, HO, HOmod
+from generator import Generator
+
+sys.setrecursionlimit(10000)
+
+
+class DEVStoneEnvironment(CoupledDEVS):
+
+    def __init__(self, name, devstone_model, num_gen_outputs=1, gen_period=None):
+        super(DEVStoneEnvironment, self).__init__(name=name)
+        generator = Generator("generator", num_gen_outputs, gen_period)
+        self.addSubModel(generator)
+        self.addSubModel(devstone_model)
+
+        self.connectPorts(generator.o_out, devstone_model.i_in)
+
+        if isinstance(devstone_model, HO) or isinstance(devstone_model, HOmod):
+            self.connectPorts(generator.o_out, devstone_model.i_in2)
+
+
+MODEL_TYPES = ("LI", "HI", "HO", "HOmod")
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(description='Script to compare DEVStone implementations with different engines')
+
+    parser.add_argument('-m', '--model-type', required=True, help='DEVStone model type (LI, HI, HO, HOmod)')
+    parser.add_argument('-d', '--depth', type=int, required=True, help='Number of recursive levels of the model.')
+    parser.add_argument('-w', '--width', type=int, required=True, help='Width of each coupled model.')
+    parser.add_argument('-i', '--int-cycles', type=int, default=0, help='Dhrystone cycles executed in internal transitions')
+    parser.add_argument('-e', '--ext-cycles', type=int, default=0, help='Dhrystone cycles executed in external transitions')
+    parser.add_argument('-f', '--flatten', action="store_true", help='Activate flattening on model')
+    parser.add_argument('-c', '--chained', action="store_true", help='Use chained coordinator')
+    args = parser.parse_args()
+
+    if args.model_type not in MODEL_TYPES:
+        raise RuntimeError("Unrecognized model type.")
+
+    return args
+
+if __name__ == '__main__':
+    args = parse_args()
+
+    devstone_model = None
+    start_time = time.time()
+    if args.model_type == "LI":
+        devstone_model = LI("LI_root", args.depth, args.width, args.int_cycles, args.ext_cycles, prep_time=1)
+    elif args.model_type == "HI":
+        devstone_model = HI("HI_root", args.depth, args.width, args.int_cycles, args.ext_cycles, prep_time=1)
+    elif args.model_type == "HO":
+        devstone_model = HO("HO_root", args.depth, args.width, args.int_cycles, args.ext_cycles, prep_time=1)
+    elif args.model_type == "HOmod":
+        devstone_model = HOmod("HOmod_root", args.depth, args.width, args.int_cycles, args.ext_cycles, prep_time=1)
+
+    env = DEVStoneEnvironment("DEVStoneEnvironment", devstone_model)
+    model_created_time = time.time()
+
+    sim = Simulator(env)
+    # sim.setTerminationTime(10.0)
+    # sim.setStateSaving("custom")
+    engine_setup_time = time.time()
+
+    sim.simulate()
+    sim_time = time.time()
+
+    print("Model creation time: {}".format(model_created_time - start_time))
+    print("Engine setup time: {}".format(engine_setup_time - model_created_time))
+    print("Simulation time: {}".format(sim_time - engine_setup_time))
+

+ 277 - 0
benchmarks/pythonpdevs-minimal/pystone.py

@@ -0,0 +1,277 @@
+#! /usr/bin/python3.6
+
+"""
+"PYSTONE" Benchmark Program
+
+Version:        Python/1.2 (corresponds to C/1.1 plus 3 Pystone fixes)
+
+Author:         Reinhold P. Weicker,  CACM Vol 27, No 10, 10/84 pg. 1013.
+
+                Translated from ADA to C by Rick Richardson.
+                Every method to preserve ADA-likeness has been used,
+                at the expense of C-ness.
+
+                Translated from C to Python by Guido van Rossum.
+
+Version History:
+
+                Version 1.1 corrects two bugs in version 1.0:
+
+                First, it leaked memory: in Proc1(), NextRecord ends
+                up having a pointer to itself.  I have corrected this
+                by zapping NextRecord.PtrComp at the end of Proc1().
+
+                Second, Proc3() used the operator != to compare a
+                record to None.  This is rather inefficient and not
+                true to the intention of the original benchmark (where
+                a pointer comparison to None is intended; the !=
+                operator attempts to find a method __cmp__ to do value
+                comparison of the record).  Version 1.1 runs 5-10
+                percent faster than version 1.0, so benchmark figures
+                of different versions can't be compared directly.
+
+                Version 1.2 changes the division to floor division.
+
+                Under Python 3 version 1.1 would use the normal division
+                operator, resulting in some of the operations mistakenly
+                yielding floats. Version 1.2 instead uses floor division
+                making the benchmark an integer benchmark again.
+
+"""
+
+LOOPS = 50000
+
+from time import time
+
+__version__ = "1.2"
+
+[Ident1, Ident2, Ident3, Ident4, Ident5] = range(1, 6)
+
+class Record:
+
+    def __init__(self, PtrComp = None, Discr = 0, EnumComp = 0,
+                       IntComp = 0, StringComp = 0):
+        self.PtrComp = PtrComp
+        self.Discr = Discr
+        self.EnumComp = EnumComp
+        self.IntComp = IntComp
+        self.StringComp = StringComp
+
+    def copy(self):
+        return Record(self.PtrComp, self.Discr, self.EnumComp,
+                      self.IntComp, self.StringComp)
+
+TRUE = 1
+FALSE = 0
+
+def main(loops=LOOPS):
+    benchtime, stones = pystones(loops)
+    print("Pystone(%s) time for %d passes = %g" % \
+          (__version__, loops, benchtime))
+    print("This machine benchmarks at %g pystones/second" % stones)
+
+
+def pystones(loops=LOOPS):
+    return Proc0(loops)
+
+IntGlob = 0
+BoolGlob = FALSE
+Char1Glob = '\0'
+Char2Glob = '\0'
+Array1Glob = [0]*51
+Array2Glob = [x[:] for x in [Array1Glob]*51]
+PtrGlb = None
+PtrGlbNext = None
+
+def Proc0(loops=LOOPS):
+    global IntGlob
+    global BoolGlob
+    global Char1Glob
+    global Char2Glob
+    global Array1Glob
+    global Array2Glob
+    global PtrGlb
+    global PtrGlbNext
+
+    starttime = time()
+    for i in range(loops):
+        pass
+    nulltime = time() - starttime
+
+    PtrGlbNext = Record()
+    PtrGlb = Record()
+    PtrGlb.PtrComp = PtrGlbNext
+    PtrGlb.Discr = Ident1
+    PtrGlb.EnumComp = Ident3
+    PtrGlb.IntComp = 40
+    PtrGlb.StringComp = "DHRYSTONE PROGRAM, SOME STRING"
+    String1Loc = "DHRYSTONE PROGRAM, 1'ST STRING"
+    Array2Glob[8][7] = 10
+
+    starttime = time()
+
+    for i in range(loops):
+        Proc5()
+        Proc4()
+        IntLoc1 = 2
+        IntLoc2 = 3
+        String2Loc = "DHRYSTONE PROGRAM, 2'ND STRING"
+        EnumLoc = Ident2
+        BoolGlob = not Func2(String1Loc, String2Loc)
+        while IntLoc1 < IntLoc2:
+            IntLoc3 = 5 * IntLoc1 - IntLoc2
+            IntLoc3 = Proc7(IntLoc1, IntLoc2)
+            IntLoc1 = IntLoc1 + 1
+        Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3)
+        PtrGlb = Proc1(PtrGlb)
+        CharIndex = 'A'
+        while CharIndex <= Char2Glob:
+            if EnumLoc == Func1(CharIndex, 'C'):
+                EnumLoc = Proc6(Ident1)
+            CharIndex = chr(ord(CharIndex)+1)
+        IntLoc3 = IntLoc2 * IntLoc1
+        IntLoc2 = IntLoc3 // IntLoc1
+        IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1
+        IntLoc1 = Proc2(IntLoc1)
+
+    benchtime = time() - starttime - nulltime
+    if benchtime == 0.0:
+        loopsPerBenchtime = 0.0
+    else:
+        loopsPerBenchtime = (loops / benchtime)
+    return benchtime, loopsPerBenchtime
+
+def Proc1(PtrParIn):
+    PtrParIn.PtrComp = NextRecord = PtrGlb.copy()
+    PtrParIn.IntComp = 5
+    NextRecord.IntComp = PtrParIn.IntComp
+    NextRecord.PtrComp = PtrParIn.PtrComp
+    NextRecord.PtrComp = Proc3(NextRecord.PtrComp)
+    if NextRecord.Discr == Ident1:
+        NextRecord.IntComp = 6
+        NextRecord.EnumComp = Proc6(PtrParIn.EnumComp)
+        NextRecord.PtrComp = PtrGlb.PtrComp
+        NextRecord.IntComp = Proc7(NextRecord.IntComp, 10)
+    else:
+        PtrParIn = NextRecord.copy()
+    NextRecord.PtrComp = None
+    return PtrParIn
+
+def Proc2(IntParIO):
+    IntLoc = IntParIO + 10
+    while 1:
+        if Char1Glob == 'A':
+            IntLoc = IntLoc - 1
+            IntParIO = IntLoc - IntGlob
+            EnumLoc = Ident1
+        if EnumLoc == Ident1:
+            break
+    return IntParIO
+
+def Proc3(PtrParOut):
+    global IntGlob
+
+    if PtrGlb is not None:
+        PtrParOut = PtrGlb.PtrComp
+    else:
+        IntGlob = 100
+    PtrGlb.IntComp = Proc7(10, IntGlob)
+    return PtrParOut
+
+def Proc4():
+    global Char2Glob
+
+    BoolLoc = Char1Glob == 'A'
+    BoolLoc = BoolLoc or BoolGlob
+    Char2Glob = 'B'
+
+def Proc5():
+    global Char1Glob
+    global BoolGlob
+
+    Char1Glob = 'A'
+    BoolGlob = FALSE
+
+def Proc6(EnumParIn):
+    EnumParOut = EnumParIn
+    if not Func3(EnumParIn):
+        EnumParOut = Ident4
+    if EnumParIn == Ident1:
+        EnumParOut = Ident1
+    elif EnumParIn == Ident2:
+        if IntGlob > 100:
+            EnumParOut = Ident1
+        else:
+            EnumParOut = Ident4
+    elif EnumParIn == Ident3:
+        EnumParOut = Ident2
+    elif EnumParIn == Ident4:
+        pass
+    elif EnumParIn == Ident5:
+        EnumParOut = Ident3
+    return EnumParOut
+
+def Proc7(IntParI1, IntParI2):
+    IntLoc = IntParI1 + 2
+    IntParOut = IntParI2 + IntLoc
+    return IntParOut
+
+def Proc8(Array1Par, Array2Par, IntParI1, IntParI2):
+    global IntGlob
+
+    IntLoc = IntParI1 + 5
+    Array1Par[IntLoc] = IntParI2
+    Array1Par[IntLoc+1] = Array1Par[IntLoc]
+    Array1Par[IntLoc+30] = IntLoc
+    for IntIndex in range(IntLoc, IntLoc+2):
+        Array2Par[IntLoc][IntIndex] = IntLoc
+    Array2Par[IntLoc][IntLoc-1] = Array2Par[IntLoc][IntLoc-1] + 1
+    Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc]
+    IntGlob = 5
+
+def Func1(CharPar1, CharPar2):
+    CharLoc1 = CharPar1
+    CharLoc2 = CharLoc1
+    if CharLoc2 != CharPar2:
+        return Ident1
+    else:
+        return Ident2
+
+def Func2(StrParI1, StrParI2):
+    IntLoc = 1
+    while IntLoc <= 1:
+        if Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1:
+            CharLoc = 'A'
+            IntLoc = IntLoc + 1
+    if CharLoc >= 'W' and CharLoc <= 'Z':
+        IntLoc = 7
+    if CharLoc == 'X':
+        return TRUE
+    else:
+        if StrParI1 > StrParI2:
+            IntLoc = IntLoc + 7
+            return TRUE
+        else:
+            return FALSE
+
+def Func3(EnumParIn):
+    EnumLoc = EnumParIn
+    if EnumLoc == Ident3: return TRUE
+    return FALSE
+
+if __name__ == '__main__':
+    import sys
+    def error(msg):
+        print(msg, end=' ', file=sys.stderr)
+        print("usage: %s [number_of_loops]" % sys.argv[0], file=sys.stderr)
+        sys.exit(100)
+    nargs = len(sys.argv) - 1
+    if nargs > 1:
+        error("%d arguments are too many;" % nargs)
+    elif nargs == 1:
+        try: loops = int(sys.argv[1])
+        except ValueError:
+            error("Invalid argument %r;" % sys.argv[1])
+    else:
+        loops = LOOPS
+    main(loops)

+ 347 - 0
benchmarks/pythonpdevs-minimal/test_devstone.py

@@ -0,0 +1,347 @@
+from abc import abstractmethod
+from unittest import TestCase
+import random
+
+from pypdevs.minimal import AtomicDEVS, CoupledDEVS
+from pypdevs.simulator import Simulator
+
+from devstone import LI, DelayedAtomic, DelayedAtomicStats, HI, HO, HOmod
+from generator import Generator
+from main import DEVStoneEnvironment
+
+
+class Utils:
+
+    @staticmethod
+    def count_atomics(coupled):
+        """
+        :return: Number of atomic components in a coupled model
+        """
+        atomic_count = 0
+        for comp in coupled.component_set:
+            if isinstance(comp, AtomicDEVS):
+                atomic_count += 1
+            elif isinstance(comp, CoupledDEVS):
+                atomic_count += Utils.count_atomics(comp)
+            else:
+                raise RuntimeError("Unrecognized type of component")
+
+        return atomic_count
+
+    @staticmethod
+    def count_ic(coupled):
+        """
+        :return: Number of ic couplings in a coupled model
+        """
+        ic_count = 0
+        for comp in coupled.component_set:
+            for src_port in comp.OPorts:
+                for dst_port in src_port.outline:
+                    if dst_port.host_DEVS != coupled:
+                        ic_count += 1
+
+        for comp in coupled.component_set:
+            if isinstance(comp, CoupledDEVS):
+                ic_count += Utils.count_ic(comp)
+            elif not isinstance(comp, AtomicDEVS):
+                raise RuntimeError("Unrecognized type of component")
+
+        return ic_count
+
+    @staticmethod
+    def count_eic(coupled):
+        """
+        :return: Number of eic couplings in a coupled model
+        """
+        eic_count = sum([len(port.outline) for port in coupled.IPorts])
+        for comp in coupled.component_set:
+            if isinstance(comp, CoupledDEVS):
+                eic_count += Utils.count_eic(comp)
+            elif not isinstance(comp, AtomicDEVS):
+                raise RuntimeError("Unrecognized type of component")
+
+        return eic_count
+
+    @staticmethod
+    def count_eoc(coupled):
+        """
+        :return: Number of eoc couplings in a coupled model
+        """
+        eoc_count = sum([len(port.inline) for port in coupled.OPorts])
+        for comp in coupled.component_set:
+            if isinstance(comp, CoupledDEVS):
+                eoc_count += Utils.count_eoc(comp)
+            elif not isinstance(comp, AtomicDEVS):
+                raise RuntimeError("Unrecognized type of component")
+
+        return eoc_count
+
+    @staticmethod
+    def count_transitions(coupled):
+        """
+        :return: Number of atomic components in a coupled model
+        """
+        int_count = 0
+        ext_count = 0
+        for comp in coupled.component_set:
+            if isinstance(comp, DelayedAtomicStats):
+                int_count += comp.int_count
+                ext_count += comp.ext_count
+            elif isinstance(comp, CoupledDEVS):
+                pic, pec = Utils.count_transitions(comp)
+                int_count += pic
+                ext_count += pec
+            elif not isinstance(comp, Generator):
+                raise RuntimeError("Unexpected type of component: %s" % comp.__class__.__name__)
+
+        return int_count, ext_count
+
+
+class DevstoneUtilsTestCase(TestCase):
+
+    def __init__(self, name, num_valid_params_sets: int = 10):
+        super().__init__(name)
+        self.valid_high_params = []
+        self.valid_low_params = []
+
+        for _ in range(int(num_valid_params_sets)):
+            self.valid_high_params.append([random.randint(1, 100), random.randint(1, 200),
+                                           random.randint(1, 1000), random.randint(1, 1000)])
+
+        for _ in range(int(num_valid_params_sets)):
+            self.valid_low_params.append([random.randint(1, 20), random.randint(1, 30),
+                                      random.randint(0, 10), random.randint(0, 10)])
+
+    def check_invalid_inputs(self, base_class):
+        self.assertRaises(ValueError, base_class, "root", 0, 1, 1, 1)
+        self.assertRaises(ValueError, base_class, "root", 1, 0, 1, 1)
+        self.assertRaises(ValueError, base_class, "root", 1, 1, -1, 0)
+        self.assertRaises(ValueError, base_class, "root", 1, 1, 0, -1)
+        self.assertRaises(ValueError, base_class, "root", 0, 1, -1, -1)
+        self.assertRaises(ValueError, base_class, "root", 0, 0, -1, -1)
+
+    def test_behavior_sequential(self):
+        self._test_behavior(Simulator)
+
+    #def test_behavior_parallel(self):
+    #    self._test_behavior(ParallelThreadCoordinator)
+
+    @abstractmethod
+    def _test_behavior(self, Coordinator):
+        pass
+
+
+class TestLI(DevstoneUtilsTestCase):
+
+    def test_structure(self):
+        """
+        Check structure params: atomic modules, ic's, eic's and eoc's.
+        """
+        for params_tuple in self.valid_high_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                self._check_structure(**params)
+
+    def test_structure_corner_cases(self):
+        params = {"depth": 10, "width": 1, "int_delay": 1, "ext_delay": 1}
+        self._check_structure(**params)
+        params["depth"] = 1
+        self._check_structure(**params)
+
+    def _check_structure(self, **params):
+        li_root = LI("LI_root", **params)
+        self.assertEqual(Utils.count_atomics(li_root), (params["width"] - 1) * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eic(li_root), params["width"] * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eoc(li_root), params["depth"])
+        self.assertEqual(Utils.count_ic(li_root), 0)
+
+    def _test_behavior(self, coord_type):
+        """
+        Check behaviour params: number of int and ext transitions.
+        """
+        for params_tuple in self.valid_low_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                li_root = LI("LI_root", stats=True, **params)
+                li_env = DEVStoneEnvironment("LI_env", li_root)
+                sim = Simulator(li_env)
+                sim.setVerbose(None)
+                # sim.setTerminationTime(10.0)
+                # sim.setStateSaving("custom")
+                sim.simulate()
+
+                int_count, ext_count = Utils.count_transitions(li_root)
+                self.assertEqual(int_count, (params["width"] - 1) * (params["depth"] - 1) + 1)
+                self.assertEqual(ext_count, (params["width"] - 1) * (params["depth"] - 1) + 1)
+
+    def test_invalid_inputs(self):
+        super().check_invalid_inputs(LI)
+
+
+class TestHI(DevstoneUtilsTestCase):
+
+    def test_structure(self):
+        """
+        Check structure params: atomic modules, ic's, eic's and eoc's.
+        """
+        for params_tuple in self.valid_high_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                self._check_structure(**params)
+
+    def test_structure_corner_cases(self):
+        params = {"depth": 10, "width": 1, "int_delay": 1, "ext_delay": 1}
+        self._check_structure(**params)
+        params["depth"] = 1
+        self._check_structure(**params)
+
+    def _check_structure(self, **params):
+        hi_root = HI("HI_root", **params)
+        self.assertEqual(Utils.count_atomics(hi_root), (params["width"] - 1) * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eic(hi_root), params["width"] * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eoc(hi_root), params["depth"])
+        self.assertEqual(Utils.count_ic(hi_root),
+                         (params["width"] - 2) * (params["depth"] - 1) if params["width"] > 2 else 0)
+
+    def _test_behavior(self, coord_type):
+        """
+        Check behaviour params: number of int and ext transitions.
+        """
+        for params_tuple in self.valid_low_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                hi_root = HI("HI_root", stats=True, **params)
+                hi_env = DEVStoneEnvironment("HI_env", hi_root)
+                sim = Simulator(hi_env)
+                sim.setVerbose(None)
+                # sim.setTerminationTime(10.0)
+                # sim.setStateSaving("custom")
+                sim.simulate()
+
+                int_count, ext_count = Utils.count_transitions(hi_root)
+                self.assertEqual(int_count, (((params["width"] - 1) * params["width"]) / 2) * (params["depth"] - 1) + 1)
+                self.assertEqual(ext_count, (((params["width"] - 1) * params["width"]) / 2) * (params["depth"] - 1) + 1)
+
+    def test_invalid_inputs(self):
+        super().check_invalid_inputs(HI)
+
+
+class TestHO(DevstoneUtilsTestCase):
+
+    def test_structure(self):
+        """
+        Check structure params: atomic modules, ic's, eic's and eoc's.
+        """
+        for params_tuple in self.valid_high_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                self._check_structure(**params)
+
+    def test_structure_corner_cases(self):
+        params = {"depth": 10, "width": 1, "int_delay": 1, "ext_delay": 1}
+        self._check_structure(**params)
+        params["depth"] = 1
+        self._check_structure(**params)
+
+    def _check_structure(self, **params):
+        ho_root = HO("HO_root", **params)
+        self.assertEqual(Utils.count_atomics(ho_root), (params["width"] - 1) * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eic(ho_root), (params["width"] + 1) * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eoc(ho_root), params["width"] * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_ic(ho_root),
+                         (params["width"] - 2) * (params["depth"] - 1) if params["width"] > 2 else 0)
+
+    def _test_behavior(self, coord_type):
+        """
+        Check behaviour params: number of int and ext transitions.
+        """
+        for params_tuple in self.valid_low_params[0]:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                ho_root = HO("HO_root", stats=True, **params)
+                ho_env = DEVStoneEnvironment("HO_env", ho_root)
+                sim = Simulator(ho_env)
+                sim.setVerbose(None)
+                # sim.setTerminationTime(10.0)
+                # sim.setStateSaving("custom")
+                sim.simulate()
+
+                int_count, ext_count = Utils.count_transitions(ho_env)
+                self.assertEqual(int_count, (((params["width"] - 1) * params["width"]) / 2) * (params["depth"] - 1) + 1)
+                self.assertEqual(ext_count, (((params["width"] - 1) * params["width"]) / 2) * (params["depth"] - 1) + 1)
+
+    def test_invalid_inputs(self):
+        super().check_invalid_inputs(HO)
+
+
+class TestHOmod(DevstoneUtilsTestCase):
+
+    def test_structure(self):
+        """
+        Check structure params: atomic modules, ic's, eic's and eoc's.
+        """
+        for params_tuple in self.valid_high_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                self._check_structure(**params)
+
+    def test_structure_corner_cases(self):
+        params = {"depth": 10, "width": 1, "int_delay": 1, "ext_delay": 1}
+        self._check_structure(**params)
+        params["depth"] = 1
+        self._check_structure(**params)
+
+    def _check_structure(self, **params):
+        homod_root = HOmod("HOmod_root", **params)
+        self.assertEqual(Utils.count_atomics(homod_root),
+                         ((params["width"] - 1) + ((params["width"] - 1) * params["width"]) / 2) * (
+                                     params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eic(homod_root), (2 * (params["width"] - 1) + 1) * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eoc(homod_root), params["depth"])
+        # ICs relative to the "triangular" section
+        exp_ic = (((params["width"] - 2) * (params["width"] - 1)) / 2) if params["width"] > 1 else 0
+        # Plus the ones relative to the connection from the 2nd to 1st row...
+        exp_ic += (params["width"] - 1) ** 2
+        # ...and from the 1st to the couple component
+        exp_ic += params["width"] - 1
+        # Multiplied by the number of layers (except the deepest one, that doesn't have ICs)
+        exp_ic *= (params["depth"] - 1)
+        self.assertEqual(Utils.count_ic(homod_root), exp_ic)
+
+    def _test_behavior(self, coord_type):
+        """
+        Check behaviour params: number of int and ext transitions.
+        """
+        for params_tuple in self.valid_low_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                homod_root = HOmod("HOmod_root", stats=True, **params)
+                homod_env = DEVStoneEnvironment("HOmod_env", homod_root)
+                sim = Simulator(homod_env)
+                sim.setVerbose(None)
+                # sim.setTerminationTime(10.0)
+                # sim.setStateSaving("custom")
+                sim.simulate()
+
+                calc_in = lambda x, w: 1 + (x - 1) * (w - 1)
+                exp_trans = 1
+                tr_atomics = sum(range(1, params["width"]))
+                for i in range(1, params["depth"]):
+                    num_inputs = calc_in(i, params["width"])
+                    trans_first_row = (params["width"] - 1) * (num_inputs + params["width"] - 1)
+                    exp_trans += num_inputs * tr_atomics + trans_first_row
+
+                int_count, ext_count = Utils.count_transitions(homod_env)
+                self.assertEqual(int_count, exp_trans)
+                self.assertEqual(ext_count, exp_trans)
+
+    def test_invalid_inputs(self):
+        super().check_invalid_inputs(HOmod)

+ 0 - 0
benchmarks/pythonpdevs/__init__.py


+ 668 - 0
benchmarks/pythonpdevs/devstone.py

@@ -0,0 +1,668 @@
+from abc import ABC, abstractmethod
+from collections import defaultdict
+
+from pystone import pystones
+from pypdevs.DEVS import AtomicDEVS, CoupledDEVS
+from pypdevs.infinity import INFINITY
+from pypdevs.simulator import Simulator
+
+from graphviz import Source
+import time
+
+import random
+random.seed(42)
+
+
+class DelayedAtomic(AtomicDEVS):
+    def __init__(self, name: str, int_delay: float, ext_delay: float, add_out_port: bool = False, prep_time=0.0, mode: str = ""):
+        super().__init__(name)
+        self.state = "passive"
+        self.int_delay = int_delay
+        self.ext_delay = ext_delay
+        self.prep_time = prep_time
+
+        self.i_in = self.addInPort("i_in")
+        if add_out_port: # for HI and HO models
+            self.o_out = self.addOutPort("o_out")
+
+        # Dynamic Structure extras
+        self.mode = mode
+        self.out_ports = [] # used for dynamic structure model LI2HI
+
+    def intTransition(self):
+        if self.int_delay:
+            pystones(self.int_delay)
+        return "passive"
+
+    def timeAdvance(self):
+        if self.state == "active":
+            return self.prep_time
+        else:
+            return INFINITY
+
+    def outputFnc(self):
+        if hasattr(self, "o_out") and self.o_out is not None:
+            return {self.o_out: [0]}
+
+        # for DSDEVS LI2HI
+        if len(self.out_ports) == 1 and self.out_ports[0].outline != []:
+            return {self.out_ports[0]: [0]}
+        return {}
+
+    def extTransition(self, inputs):
+        if self.ext_delay:
+            pystones(self.ext_delay)
+
+        return "active"
+
+    def modelTransition(self, state):
+        result = False
+        if self.mode == "LI2HI":
+            result = self.LI2HI(state)
+        elif self.mode == "HI2LI":
+            result = self.HI2LI(state)
+        return result
+
+    def LI2HI(self, state):
+        if len(self.out_ports) == 0 and not hasattr(self, "o_out"):
+            # every automic dev gets the extra out port
+            # even though the last atomic could miss it see fig
+            # except the atomic model in the coupled model at max depth
+            # which has a output port by default
+            state["LI2HI"] = True
+            state["name"] = self.name
+            self.out_ports.append(self.addOutPort("o_HI")) # standard LI model doesn't have by default
+            # print(f"{self.name}: should be first call!!")
+            return True # send to the parent to connect ports
+        return False
+
+    def HI2LI(self, state):
+        if hasattr(self, "o_out") and self.o_out is not None:
+            state["HI2LI"] = True
+            state["name"] = self.name
+            self.removePort(self.o_out)
+            self.o_out = None
+        return False
+
+
+class DelayedAtomicStats(DelayedAtomic):
+    def __init__(self, name: str, int_delay: float, ext_delay: float, add_out_port: bool = False, prep_time=0, mode:str = ""):
+        super().__init__(name, int_delay, ext_delay, add_out_port, prep_time, mode)
+
+        self.int_count = 0
+        self.ext_count = 0
+
+    def intTransition(self):
+        self.int_count += 1
+        return super().intTransition()
+
+    def extTransition(self, inputs):
+        self.ext_count += 1
+        return super().extTransition(inputs)
+
+
+class DEVStoneWrapper(CoupledDEVS, ABC):
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float,
+                 add_atomic_out_ports: bool = False, prep_time=0, stats=False, mode: str = "", dynamic: bool = False):
+        super().__init__(name)
+
+        self.depth = depth
+        self.width = width
+        self.int_delay = int_delay
+        self.ext_delay = ext_delay
+        self.prep_time = prep_time
+        self.stats = stats
+        self.add_atomic_out_ports = add_atomic_out_ports
+
+        self.i_in = self.addInPort("i_in")
+        self.o_out = self.addOutPort("o_out")
+
+        self.models = [] # stores all models part of the coupled model
+        # added to deal with DS DEVS which don't keep it all in the component_set
+
+        if depth < 1:
+            raise ValueError("Invalid depth")
+        if width < 1:
+            raise ValueError("Invalid width")
+        if int_delay < 0:
+            raise ValueError("Invalid int_delay")
+        if ext_delay < 0:
+            raise ValueError("Invalid ext_delay")
+
+        if depth == 1:
+            p_time = random.uniform(1.0, 2.0)
+            if self.stats:
+                atomic = DelayedAtomicStats("Atomic_0_0", int_delay, ext_delay, add_out_port=True, prep_time=p_time, mode=mode)
+            else:
+                atomic = DelayedAtomic("Atomic_0_0", int_delay, ext_delay, add_out_port=True, prep_time=p_time, mode=mode)
+
+            self.models.append(self.addSubModel(atomic))
+
+            self.connectPorts(self.i_in, atomic.i_in)
+            self.connectPorts(atomic.o_out, self.o_out)
+        else:
+            coupled = self.gen_coupled()
+            self.addSubModel(coupled)
+            self.connectPorts(self.i_in, coupled.i_in)
+            self.connectPorts(coupled.o_out, self.o_out)
+
+            if dynamic:
+                return # width will be dynamically generated
+
+            # + (idx * 1e-6) to address too many transitions at the same time
+            # => problem for Classic DEVS only it seems
+            for idx in range(width - 1):
+                p_time = 1 - random.uniform(idx/self.width, (idx + 0.5)/self.width)
+                if self.stats:
+                    atomic = DelayedAtomicStats("Atomic_%d_%d" % (depth - 1, idx), int_delay, ext_delay,
+                                                add_out_port=add_atomic_out_ports, prep_time=p_time, mode=mode)
+                else:
+                    atomic = DelayedAtomic("Atomic_%d_%d" % (depth - 1, idx), int_delay, ext_delay,
+                                           add_out_port=add_atomic_out_ports, prep_time=p_time, mode=mode)
+                self.models.append(self.addSubModel(atomic))
+
+    def dot(self, name) -> None:
+        result = ("\n\ndigraph {\n\tlayout=dot;"
+                  "\n\tnodesep=0.25;"
+                  "\n\tranksep=0.2;"
+                  "\n\trankdir=LR;"
+                  "\n\tsplines=ortho;\n")
+        result += f"\tCoupled_{self.depth}[shape=box, label=\"C_{self.depth}\"];\n"
+        coupled = self.component_set[0]
+        result += f"\t{coupled.name}[shape=box, label=\"{'C_' + '_'.join(coupled.name.split('_')[1:3])}\"];\n"
+        for model in self.models:
+            result += f"\t{model.name}[shape=ellipse, label=\"{'A_' + '_'.join(model.name.split('_')[1:3])}\"];\n"
+
+        for connections in self.i_in.outline:
+            result += f"\tCoupled_{self.depth}:i_in -> {str(connections).split('.')[-2]}:{connections.name};\n"
+
+        for model in self.models:
+            if not hasattr(model, "o_out"):
+                continue
+            for connections in model.o_out.outline:
+                result += f"\t{model.name}:o_out -> {str(connections).split('.')[2]}:{connections.name};\n"
+        result += "}\n"
+
+        src = Source(result)
+        src.view(filename=f'{name}_{self.depth}')
+
+    def getStats(self, display=True):
+        total_i = 0
+        total_e = 0
+        if isinstance(self.component_set[0], CoupledDEVS):
+            i, e = self.component_set[0].getStats(False)
+            total_i += i
+            total_e += e
+
+        for m in self.models:
+            if not (hasattr(m, "int_count") and hasattr(m, "ext_count")):
+                continue
+            total_i += m.int_count
+            total_e += m.ext_count
+        if display:
+            print(f"Total internal transitions during simulation: {total_i}")
+            print(f"Total external transitions during simulation: {total_e}")
+            print(f"Total Number of Events: {total_i + total_e}")
+        return total_i, total_e
+
+    @abstractmethod
+    def gen_coupled(self):
+        """ :return a coupled method with i_in and o_out ports"""
+        pass
+
+
+class LI(DEVStoneWrapper):
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False):
+        super().__init__(name, depth, width, int_delay, ext_delay, add_atomic_out_ports=False, prep_time=prep_time,
+                         stats=stats)
+
+        for idx in range(1, len(self.component_set)):
+            assert isinstance(self.component_set[idx], AtomicDEVS)
+            self.connectPorts(self.i_in, self.component_set[idx].i_in)
+
+    def gen_coupled(self):
+        return LI("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                  prep_time=self.prep_time, stats=self.stats)
+
+
+class HI(DEVStoneWrapper):
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False):
+        super().__init__(name, depth, width, int_delay, ext_delay, add_atomic_out_ports=True, prep_time=prep_time,
+                         stats=stats)
+
+        if len(self.component_set) > 1:
+            assert isinstance(self.component_set[-1], AtomicDEVS)
+            self.connectPorts(self.i_in, self.component_set[-1].i_in)
+
+        for idx in range(1, len(self.component_set) - 1):
+            assert isinstance(self.component_set[idx], AtomicDEVS)
+            self.connectPorts(self.component_set[idx].o_out, self.component_set[idx + 1].i_in)
+            self.connectPorts(self.i_in, self.component_set[idx].i_in)
+
+    def gen_coupled(self):
+        return HI("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                  prep_time=self.prep_time, stats=self.stats)
+
+
+class HO(DEVStoneWrapper):
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False):
+        super().__init__(name, depth, width, int_delay, ext_delay, add_atomic_out_ports=True, prep_time=prep_time,
+                         stats=stats)
+
+        self.i_in2 = self.addInPort("i_in2")
+        self.o_out2 = self.addOutPort("o_out2")
+
+        assert len(self.component_set) > 0
+        if isinstance(self.component_set[0], CoupledDEVS):
+            self.connectPorts(self.i_in, self.component_set[0].i_in2) # seems wrong i_in -> i_in and i_in2 -> i_in2 not criss-crossed??
+
+        if len(self.component_set) > 1:
+            assert isinstance(self.component_set[-1], AtomicDEVS)
+            self.connectPorts(self.i_in2, self.component_set[-1].i_in)
+            self.connectPorts(self.component_set[-1].o_out, self.o_out2)
+
+        for idx in range(1, len(self.component_set) - 1):
+            assert isinstance(self.component_set[idx], AtomicDEVS)
+            self.connectPorts(self.component_set[idx].o_out, self.component_set[idx + 1].i_in)
+            self.connectPorts(self.i_in2, self.component_set[idx].i_in)
+            self.connectPorts(self.component_set[idx].o_out, self.o_out2)
+
+    def gen_coupled(self):
+        return HO("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                  prep_time=self.prep_time, stats=self.stats)
+
+
+class HOmod(CoupledDEVS):
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False):
+        super().__init__(name)
+
+        self.depth = depth
+        self.width = width
+        self.int_delay = int_delay
+        self.ext_delay = ext_delay
+        self.prep_time = prep_time
+        self.stats = stats
+
+        self.i_in = self.addInPort("i_in")
+        self.i_in2 = self.addInPort("i_in2")
+        self.o_out = self.addOutPort("o_out")
+
+        if depth < 1:
+            raise ValueError("Invalid depth")
+        if width < 1:
+            raise ValueError("Invalid width")
+        if int_delay < 0:
+            raise ValueError("Invalid int_delay")
+        if ext_delay < 0:
+            raise ValueError("Invalid ext_delay")
+
+        if depth == 1:
+            if self.stats:
+                atomic = DelayedAtomicStats("Atomic_0_0", int_delay, ext_delay, add_out_port=True, prep_time=prep_time)
+            else:
+                atomic = DelayedAtomic("Atomic_0_0", int_delay, ext_delay, add_out_port=True, prep_time=prep_time)
+            self.addSubModel(atomic)
+
+            self.connectPorts(self.i_in, atomic.i_in)
+            self.connectPorts(atomic.o_out, self.o_out)
+        else:
+            coupled = HOmod("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay, prep_time=prep_time, stats=stats)
+            self.addSubModel(coupled)
+            self.connectPorts(self.i_in, coupled.i_in)
+            self.connectPorts(coupled.o_out, self.o_out)
+
+            if width >= 2:
+                atomics = defaultdict(list)
+
+                # Generate atomic components
+                for i in range(width):
+                    min_row_idx = 0 if i < 2 else i - 1
+                    for j in range(min_row_idx, width - 1):
+                        if self.stats:
+                            atomic = DelayedAtomicStats("Atomic_%d_%d_%d" % (depth - 1, i, j), int_delay, ext_delay,
+                                                   add_out_port=True, prep_time=prep_time)
+                        else:
+                            atomic = DelayedAtomic("Atomic_%d_%d_%d" % (depth - 1, i, j), int_delay, ext_delay,
+                                                   add_out_port=True, prep_time=prep_time)
+                        self.addSubModel(atomic)
+                        atomics[i].append(atomic)
+
+                # Connect EIC
+                for atomic in atomics[0]:
+                    self.connectPorts(self.i_in2, atomic.i_in)
+                for i in range(1, width):
+                    atomic_set = atomics[i]
+                    self.connectPorts(self.i_in2, atomic_set[0].i_in)
+
+                # Connect IC
+                for atomic in atomics[0]:  # First row to coupled component
+                    self.connectPorts(atomic.o_out, coupled.i_in2)
+                for i in range(len(atomics[1])):  # Second to first rows
+                    for j in range(len(atomics[0])):
+                        self.connectPorts(atomics[1][i].o_out, atomics[0][j].i_in)
+                for i in range(2, width):  # Rest of rows
+                    for j in range(len(atomics[i])):
+                        self.connectPorts(atomics[i][j].o_out, atomics[i - 1][j + 1].i_in)
+
+
+class LI2HI(DEVStoneWrapper):
+    """
+    Dynamic DEVStone variant that starts as an LI
+    and (gradually??) transforms into an HI model
+    """
+
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False):
+        super().__init__(name, depth, width, int_delay, ext_delay, add_atomic_out_ports=False, prep_time=prep_time,
+                         stats=stats, mode="LI2HI")
+
+        for idx in range(1, len(self.component_set)):
+            assert isinstance(self.component_set[idx], AtomicDEVS)
+            self.connectPorts(self.i_in, self.component_set[idx].i_in)
+
+    def gen_coupled(self):
+        return LI2HI("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                  prep_time=self.prep_time, stats=self.stats)
+
+    def modelTransition(self, state):
+        if state.get("LI2HI", True):
+            for i in range(len(self.component_set) - 1): # -1 because the last model can't be connected
+                # basically checks if it is an atomic model and if it got the extra output port
+                if hasattr(self.component_set[i], "out_ports") and len(self.component_set[i].out_ports) == 1:
+                    # print(f"Connect {self.component_set[i].name} to {self.component_set[i+1].name}")
+                    self.connectPorts(self.component_set[i].out_ports[0], self.component_set[i + 1].i_in)
+            return False
+        return False
+
+
+class HI2LI(DEVStoneWrapper):
+    """
+    Dynamic DEVStone variant that starts as an HI
+    and (gradually??) transforms into an LI model
+    """
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False):
+        super().__init__(name, depth, width, int_delay, ext_delay, add_atomic_out_ports=True, prep_time=prep_time,
+                         stats=stats, mode="HI2LI")
+
+        if len(self.component_set) > 1:
+            assert isinstance(self.component_set[-1], AtomicDEVS)
+            self.connectPorts(self.i_in, self.component_set[-1].i_in)
+
+        for idx in range(1, len(self.component_set) - 1):
+            assert isinstance(self.component_set[idx], AtomicDEVS)
+            self.connectPorts(self.component_set[idx].o_out, self.component_set[idx + 1].i_in)
+            self.connectPorts(self.i_in, self.component_set[idx].i_in)
+
+    def gen_coupled(self):
+        return HI2LI("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                  prep_time=self.prep_time, stats=self.stats)
+
+
+class DynamicGenerator(AtomicDEVS):
+    def __init__(self, name: str, period: float = 1, repeat: int = 1, num: int = 1):
+        super().__init__(name)
+        self.period = period
+        self.repeat = repeat
+        self.number = num # how many models need to be generated per cycle
+
+        self._counter = 0
+
+    def intTransition(self):
+        return "passive" # state is unimportant
+
+    def timeAdvance(self):
+        if self._counter >= self.repeat:
+            return INFINITY
+        return self.period
+
+    def outputFnc(self):
+        return {}
+
+    def modelTransition(self, state):
+        # every time TA elapses, this will be called on the atomic:
+        # set a flag the parent coupled can read
+        # increment counter and request modelTransition (return True)
+        if self._counter >= self.repeat:
+            return False
+        remaining = self.repeat - self._counter
+
+        num2create = self.number
+        if remaining < self.number:
+            num2create = remaining
+
+        self._counter += num2create
+        state["generate"] = True
+        state["create"] = num2create
+        state["created"] = 0
+        return True
+
+
+class DynamicDEVStoneWrapper(DEVStoneWrapper, ABC):
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float,
+                 add_atomic_out_ports: bool = False, /, prep_time=0, stats=False, root=False, mode: str = "", number: int = 1, gen_mode: str="uniform"):
+        if number <= 0:
+            raise ValueError("number of models to be generated must be greater than zero")
+
+        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 # 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)
+
+        self.connector = self.i_in
+        if self.depth == 1:
+            self.generator = self.addSubModel(DynamicGenerator(self.name + "_gen", repeat=self.max_gen, num=self.number))
+
+    def createAtomic(self, name: str = "", outport: bool = False):
+        """
+        params are there for 'manual' use of method
+        """
+        add_outport = self.add_atomic_out_ports or outport
+        if name == "":
+            name = f"Atomic_0_{self.current_width}"
+            if self.depth > 1:
+                name = f"Atomic_{self.depth-1}_{self.current_width}"
+
+        if self.stats:
+            atomic = DelayedAtomicStats(name, self.int_delay, self.ext_delay,
+                                          add_out_port=add_outport, prep_time=self.prep_time,
+                                          mode=self.mode)
+        else:
+            atomic = DelayedAtomic(name, self.int_delay, self.ext_delay,
+                                     add_out_port=add_outport, prep_time=self.prep_time,
+                                     mode=self.mode)
+
+        self.models.append(self.addSubModel(atomic))
+        return atomic
+
+    def modelTransition(self, state):
+        if state.get("generate", True) and self.depth == 1:
+            return True
+
+        if state.get("generate", True) and self.depth > 1:
+            number = state.get("create")
+            for _ in range(number):
+                atom = self.createAtomic()
+                self.connectPorts(self.connector, atom.i_in)
+
+                if len(self.models) > 1:
+                    prev = self.models[-2] # new model was already added so the previous one isn't the last in the list anymore
+                    if isinstance(prev, AtomicDEVS) and hasattr(prev, "o_out"):
+                        self.connectPorts(prev.o_out, atom.i_in)
+                    if hasattr(self, "o_out2"):
+                        self.connectPorts(atom.o_out, self.o_out2)
+
+                self.current_width += 1
+
+                if self.current_width > self.width:
+                    raise RuntimeError(f"The width has grown beyond what was specified!"
+                                   f"\n current width: {self.current_width}"
+                                   f"\n specified width: {self.width}")
+
+            # enables visualisation of each level (coupled model)
+                # if self.current_width == self.width:
+                #     self.dot(f"dLI_{self.depth}")
+
+            if not self.root:
+                state["created"] += number
+                return True
+            self.created += state["created"] + number
+            return False
+        return False
+
+
+class dLI(DynamicDEVStoneWrapper):
+    """
+    A LI model which grows in width
+    """
+    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, False, prep_time, stats, mode="LI-Dynamic", root=root, number=number, gen_mode=gen_mode)
+
+    def gen_coupled(self):
+        return dLI("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                   prep_time=self.prep_time, stats=self.stats, root=False, number=self.number)
+
+
+class mdLI(DynamicDEVStoneWrapper):
+    """
+    A LI model which grows in width
+    """
+    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, False, prep_time, stats, mode="LI-Dynamic", root=root, number=number, gen_mode=gen_mode)
+
+        intermediate = self.createAtomic("intermediate", outport=True)
+        self.connectPorts(self.i_in, intermediate.i_in)
+        self.connector = intermediate.o_out
+
+
+    def gen_coupled(self):
+        return mdLI("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                   prep_time=self.prep_time, stats=self.stats, root=False, number=self.number)
+
+
+class dHI(DynamicDEVStoneWrapper):
+    """
+    A HI model which grows in width
+    """
+    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)
+
+    def gen_coupled(self):
+        return dHI("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                   prep_time=self.prep_time, stats=self.stats, root=False, number=self.number)
+
+
+class mdHI(DynamicDEVStoneWrapper):
+    """
+    A HI model which grows in width
+    """
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, /, prep_time=0, stats=False, root: bool = True, number: int = 1, gen_mode: str = "uniform"):
+        super().__init__(name, depth, width, int_delay, ext_delay, True, prep_time=prep_time, stats=stats, mode="HI-Dynamic", root=root, number=number, gen_mode=gen_mode)
+        intermediate = self.createAtomic("intermediate", outport=True)
+        self.connectPorts(self.i_in, intermediate.i_in)
+        self.connector = intermediate.o_out
+
+    def gen_coupled(self):
+        return mdHI("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay,
+                   prep_time=self.prep_time, stats=self.stats, root=False, number=self.number)
+
+
+class dHO(DynamicDEVStoneWrapper):
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False, root: bool = True, number: int = 1, gen_mode: str = "uniform"):
+        super().__init__(name, depth, width, int_delay, ext_delay, True, prep_time=prep_time, stats=stats, mode="HO-dynamic", root=root, number=number, gen_mode=gen_mode)
+
+        self.i_in2 = self.addInPort("i_in2")
+        self.o_out2 = self.addOutPort("o_out2")
+
+        assert len(self.component_set) > 0
+        if isinstance(self.component_set[0], CoupledDEVS):
+            self.connectPorts(self.i_in, self.component_set[0].i_in2)
+        self.connector = self.i_in2
+
+    def gen_coupled(self):
+        return dHO("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay, self.prep_time, self.stats, root=False, number=self.number)
+
+
+class mdHO(DynamicDEVStoneWrapper):
+    def __init__(self, name: str, depth: int, width: int, int_delay: float, ext_delay: float, prep_time=0, stats=False, root: bool = True, number: int = 1, gen_mode: str = "uniform"):
+        super().__init__(name, depth, width, int_delay, ext_delay, True, prep_time=prep_time, stats=stats, mode="HO-dynamic", root=root, number=number, gen_mode=gen_mode)
+
+        self.i_in2 = self.addInPort("i_in2")
+        self.o_out2 = self.addOutPort("o_out2")
+
+        assert len(self.component_set) > 0
+        if isinstance(self.component_set[0], CoupledDEVS):
+            self.connectPorts(self.i_in, self.component_set[0].i_in2) # seems wrong i_in -> i_in and i_in2 -> i_in2 not criss-crossed??
+
+        intermediate = self.createAtomic("intermediate", outport=True)
+        self.connectPorts(self.i_in2, intermediate.i_in)
+        self.connector = intermediate.o_out
+
+    def gen_coupled(self):
+        return mdHO("Coupled_%d" % (self.depth - 1), self.depth - 1, self.width, self.int_delay, self.ext_delay, self.prep_time, self.stats, root=False, number=self.number)
+
+
+class dynamicTest(CoupledDEVS):
+    def __init__(self):
+        super().__init__("TEST")
+        self.i_in = self.addInPort("i_in")
+        self.o_out = self.addOutPort("o_out")
+
+        self.coupled = self.addSubModel(dynamicTest2())
+        self.model1 = self.addSubModel(DelayedAtomic("root",0, 0, True, 0.1))
+        self.model2 = self.addSubModel(DelayedAtomic("model1", 0, 0, True, 0.1))
+        self.model3 = self.addSubModel(DelayedAtomic("model2", 0, 0, True, 0.1))
+        # self.model4 = self.addSubModel(DelayedAtomic("model3", 0, 0, True, 0.1))
+
+        self.connectPorts(self.i_in, self.coupled.i_in)
+        self.connectPorts(self.coupled.o_out, self.o_out)
+        self.connectPorts(self.i_in, self.model1.i_in)
+        self.connectPorts(self.model1.o_out, self.model2.i_in)
+        # self.connectPorts(self.model1.o_out, self.model3.i_in)
+
+        # r - m1 - m2
+        #       \_ m3
+
+        # self.generator = self.addSubModel(DynamicGenerator("test"))
+
+    def modelTransition(self, state):
+        if state.get("generate", True):
+            model3 = self.addSubModel(DelayedAtomic("model3", 0, 0, True, 0.1))
+            self.connectPorts(self.model1.o_out, model3.i_in)
+            # model4 = self.addSubModel(DelayedAtomic("model4", 0, 0, True, 0.1))
+            # self.connectPorts(self.model3.o_out, model4.i_in)
+
+
+class dynamicTest2(CoupledDEVS):
+    def __init__(self):
+        super().__init__("TEST")
+        self.i_in = self.addInPort("i_in")
+        self.o_out = self.addOutPort("o_out")
+
+        self.generator = self.addSubModel(DynamicGenerator("test"))
+
+    def modelTransition(self, state):
+        if state.get("generate", True):
+            model1 = self.addSubModel(DelayedAtomic("model3", 0, 0, True, 0.1))
+            self.connectPorts(self.i_in, model1.i_in)
+            model2 = self.addSubModel(DelayedAtomic("model2", 0, 0, True, 0.1))
+
+
+if __name__ == '__main__':
+    import sys
+
+    sys.setrecursionlimit(10000)
+    root = HOmod("Root", 4, 3, 0, 0)
+    sim = Simulator(root)
+    sim.setVerbose(None)
+    # sim.setTerminationTime(10.0)
+    sim.setStateSaving("custom")
+    sim.simulate()

+ 44 - 0
benchmarks/pythonpdevs/generator.py

@@ -0,0 +1,44 @@
+from typing import Any
+
+from pypdevs.DEVS import AtomicDEVS
+from pypdevs.infinity import INFINITY
+
+
+class Generator(AtomicDEVS):
+
+    def __init__(self, name, num_outputs=1, period=None, cycles=1):
+        super(Generator, self).__init__(name=name)
+        self.num_outputs = num_outputs
+        self.period = period
+        self.cycles = cycles
+        self.state = "waiting", 0
+        self.o_out = self.addOutPort("o_out")
+
+    def intTransition(self):
+        state, cycle = self.state
+        if cycle >= self.cycles:
+            return "passive", cycle
+        elif state == "active" and self.period is not None:
+            return "waiting", cycle + 1
+        elif state == "waiting":
+            return "active", cycle
+        else:
+            return "passive", cycle
+
+    def timeAdvance(self):
+        state, cycle = self.state
+        if state == "active":
+            return 0
+        elif state == "waiting":
+            return self.period
+        else:
+            return INFINITY
+
+    def outputFnc(self):
+        state, cycle = self.state
+        if state == "active":
+            return {self.o_out: list(range(self.num_outputs))}
+        return {}
+
+    def extTransition(self, inputs):
+        pass

+ 146 - 0
benchmarks/pythonpdevs/main.py

@@ -0,0 +1,146 @@
+import argparse
+import sys
+import time
+from functools import partial
+
+from pypdevs.DEVS import CoupledDEVS
+from pypdevs.simulator import Simulator
+
+from devstone import LI, HI, HO, HOmod, LI2HI, HI2LI, dLI, mdLI, dHI, mdHI, dHO, mdHO, dynamicTest
+from generator import Generator
+from devstone.model_properties import model_properties
+
+sys.setrecursionlimit(10000)
+
+def terminate(clock, model, timeLimit):
+    # print(clock[0])
+    if clock[0] > timeLimit:
+        return True
+    return False
+
+
+class DEVStoneEnvironment(CoupledDEVS):
+
+    def __init__(self, name, devstone_model, num_gen_outputs=1, gen_period=1):
+        super(DEVStoneEnvironment, self).__init__(name=name)
+        generator = Generator("generator", num_gen_outputs, gen_period)
+        self.addSubModel(generator)
+        self.addSubModel(devstone_model)
+
+        self.connectPorts(generator.o_out, devstone_model.i_in)
+
+        if isinstance(devstone_model, HO) or isinstance(devstone_model, HOmod):
+            self.connectPorts(generator.o_out, devstone_model.i_in2)
+
+
+MODEL_TYPES = ("LI", "HI", "HO", "HOmod", "LI2HI", "HI2LI", "dLI", "mdLI", "dHI", "mdHI", "dHO", "mdHO", "test")
+GEN_METHODS = ("start", "uniform", "end")
+
+
+def parse_args():
+    parser = argparse.ArgumentParser(description='Script to compare DEVStone implementations with different engines')
+
+    parser.add_argument('-m', '--model-type', required=True, help='DEVStone model type (LI, HI, HO, HOmod, LI2HI, HI2LI)')
+    parser.add_argument('-d', '--depth', type=int, required=True, help='Number of recursive levels of the model.')
+    parser.add_argument('-w', '--width', type=int, required=True, help='Width of each coupled model.')
+    parser.add_argument('-i', '--int-cycles', type=int, default=0, help='Dhrystone cycles executed in internal transitions')
+    parser.add_argument('-e', '--ext-cycles', type=int, default=0, help='Dhrystone cycles executed in external transitions')
+    parser.add_argument('-f', '--flatten', action="store_true", help='Activate flattening on model')
+    parser.add_argument('-c', '--chained', action="store_true", help='Use chained coordinator')
+    parser.add_argument("--stats", "-s", action="store_true", help="Enable Event Tracking")
+
+    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=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()
+
+    if args.model_type not in MODEL_TYPES:
+        raise RuntimeError("Unrecognized model type.")
+
+    return args
+
+def create_model(args):
+    match args.model_type:
+        case "LI":
+            return LI("LI_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats)
+        case "HI":
+            return HI("HI_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats)
+        case "HO":
+            return HO("HO_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats)
+        case "HOmod":
+            return HOmod("HOmod_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats)
+        case "LI2HI":
+            return LI2HI("LI2HI_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats)
+        case "HI2LI":
+            return HI2LI("HI2LI_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats)
+        case "dLI":
+            return dLI("dLI_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats, number=args.number, gen_mode=args.gen_mode)
+        case "mdLI":
+            return mdLI("mdLI_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats, number=args.number, gen_mode=args.gen_mode)
+        case "dHI":
+            return dHI("dHI_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats, number=args.number, gen_mode=args.gen_mode)
+        case "mdHI":
+            return mdHI("mdHI_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats, number=args.number, gen_mode=args.gen_mode)
+        case "dHO":
+            return dHO("dHO_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats, number=args.number, gen_mode=args.gen_mode)
+        case "mdHO":
+            return mdHO("mdHO_root", args.depth, args.width, args.int_cycles, args.ext_cycles, 1, args.stats, number=args.number, gen_mode=args.gen_mode)
+        case "test":
+            return dynamicTest()
+        case _:
+            raise Exception("Unknown model type.")
+
+
+if __name__ == '__main__':
+    args = parse_args()
+
+    start_time = time.time()
+    devstone_model = create_model(args)
+
+    env = DEVStoneEnvironment("DEVStoneEnvironment", devstone_model)
+    model_created_time = time.time()
+
+    # devstone_model.dot(f"{args.model_type}-before")
+
+    import cProfile
+    import pstats
+    import io
+
+    sim = Simulator(env)
+    if args.classic:
+        sim.setClassicDEVS(True)
+
+    # term = partial(terminate, timeLimit=1.5)
+    if args.dynamic:
+        sim.setDSDEVS(True)
+        # term = partial(terminate, timeLimit=args.width + 0.5)
+    # 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()
+    sim.simulate()
+    # pr.disable()
+    sim_time = time.time()
+
+    # s = io.StringIO()
+    # sortby = pstats.SortKey.CUMULATIVE
+    # ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
+    # ps.print_stats()
+    # print(s.getvalue())
+
+    # devstone_model.dot(f"{args.model_type}-after")
+
+    print("Model creation time: {}".format(model_created_time - start_time))
+    print("Engine setup time: {}".format(engine_setup_time - model_created_time))
+    print("Simulation time: {}".format(sim_time - engine_setup_time))
+    if args.stats:
+        devstone_model.getStats()
+        print(f"Theoretical Events: {model_properties(args.model_type, args.width, args.depth)}")
+
+

+ 277 - 0
benchmarks/pythonpdevs/pystone.py

@@ -0,0 +1,277 @@
+#! /usr/bin/python3.6
+
+"""
+"PYSTONE" Benchmark Program
+
+Version:        Python/1.2 (corresponds to C/1.1 plus 3 Pystone fixes)
+
+Author:         Reinhold P. Weicker,  CACM Vol 27, No 10, 10/84 pg. 1013.
+
+                Translated from ADA to C by Rick Richardson.
+                Every method to preserve ADA-likeness has been used,
+                at the expense of C-ness.
+
+                Translated from C to Python by Guido van Rossum.
+
+Version History:
+
+                Version 1.1 corrects two bugs in version 1.0:
+
+                First, it leaked memory: in Proc1(), NextRecord ends
+                up having a pointer to itself.  I have corrected this
+                by zapping NextRecord.PtrComp at the end of Proc1().
+
+                Second, Proc3() used the operator != to compare a
+                record to None.  This is rather inefficient and not
+                true to the intention of the original benchmark (where
+                a pointer comparison to None is intended; the !=
+                operator attempts to find a method __cmp__ to do value
+                comparison of the record).  Version 1.1 runs 5-10
+                percent faster than version 1.0, so benchmark figures
+                of different versions can't be compared directly.
+
+                Version 1.2 changes the division to floor division.
+
+                Under Python 3 version 1.1 would use the normal division
+                operator, resulting in some of the operations mistakenly
+                yielding floats. Version 1.2 instead uses floor division
+                making the benchmark an integer benchmark again.
+
+"""
+
+LOOPS = 50000
+
+from time import time
+
+__version__ = "1.2"
+
+[Ident1, Ident2, Ident3, Ident4, Ident5] = range(1, 6)
+
+class Record:
+
+    def __init__(self, PtrComp = None, Discr = 0, EnumComp = 0,
+                       IntComp = 0, StringComp = 0):
+        self.PtrComp = PtrComp
+        self.Discr = Discr
+        self.EnumComp = EnumComp
+        self.IntComp = IntComp
+        self.StringComp = StringComp
+
+    def copy(self):
+        return Record(self.PtrComp, self.Discr, self.EnumComp,
+                      self.IntComp, self.StringComp)
+
+TRUE = 1
+FALSE = 0
+
+def main(loops=LOOPS):
+    benchtime, stones = pystones(loops)
+    print("Pystone(%s) time for %d passes = %g" % \
+          (__version__, loops, benchtime))
+    print("This machine benchmarks at %g pystones/second" % stones)
+
+
+def pystones(loops=LOOPS):
+    return Proc0(loops)
+
+IntGlob = 0
+BoolGlob = FALSE
+Char1Glob = '\0'
+Char2Glob = '\0'
+Array1Glob = [0]*51
+Array2Glob = [x[:] for x in [Array1Glob]*51]
+PtrGlb = None
+PtrGlbNext = None
+
+def Proc0(loops=LOOPS):
+    global IntGlob
+    global BoolGlob
+    global Char1Glob
+    global Char2Glob
+    global Array1Glob
+    global Array2Glob
+    global PtrGlb
+    global PtrGlbNext
+
+    starttime = time()
+    for i in range(loops):
+        pass
+    nulltime = time() - starttime
+
+    PtrGlbNext = Record()
+    PtrGlb = Record()
+    PtrGlb.PtrComp = PtrGlbNext
+    PtrGlb.Discr = Ident1
+    PtrGlb.EnumComp = Ident3
+    PtrGlb.IntComp = 40
+    PtrGlb.StringComp = "DHRYSTONE PROGRAM, SOME STRING"
+    String1Loc = "DHRYSTONE PROGRAM, 1'ST STRING"
+    Array2Glob[8][7] = 10
+
+    starttime = time()
+
+    for i in range(loops):
+        Proc5()
+        Proc4()
+        IntLoc1 = 2
+        IntLoc2 = 3
+        String2Loc = "DHRYSTONE PROGRAM, 2'ND STRING"
+        EnumLoc = Ident2
+        BoolGlob = not Func2(String1Loc, String2Loc)
+        while IntLoc1 < IntLoc2:
+            IntLoc3 = 5 * IntLoc1 - IntLoc2
+            IntLoc3 = Proc7(IntLoc1, IntLoc2)
+            IntLoc1 = IntLoc1 + 1
+        Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3)
+        PtrGlb = Proc1(PtrGlb)
+        CharIndex = 'A'
+        while CharIndex <= Char2Glob:
+            if EnumLoc == Func1(CharIndex, 'C'):
+                EnumLoc = Proc6(Ident1)
+            CharIndex = chr(ord(CharIndex)+1)
+        IntLoc3 = IntLoc2 * IntLoc1
+        IntLoc2 = IntLoc3 // IntLoc1
+        IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1
+        IntLoc1 = Proc2(IntLoc1)
+
+    benchtime = time() - starttime - nulltime
+    if benchtime == 0.0:
+        loopsPerBenchtime = 0.0
+    else:
+        loopsPerBenchtime = (loops / benchtime)
+    return benchtime, loopsPerBenchtime
+
+def Proc1(PtrParIn):
+    PtrParIn.PtrComp = NextRecord = PtrGlb.copy()
+    PtrParIn.IntComp = 5
+    NextRecord.IntComp = PtrParIn.IntComp
+    NextRecord.PtrComp = PtrParIn.PtrComp
+    NextRecord.PtrComp = Proc3(NextRecord.PtrComp)
+    if NextRecord.Discr == Ident1:
+        NextRecord.IntComp = 6
+        NextRecord.EnumComp = Proc6(PtrParIn.EnumComp)
+        NextRecord.PtrComp = PtrGlb.PtrComp
+        NextRecord.IntComp = Proc7(NextRecord.IntComp, 10)
+    else:
+        PtrParIn = NextRecord.copy()
+    NextRecord.PtrComp = None
+    return PtrParIn
+
+def Proc2(IntParIO):
+    IntLoc = IntParIO + 10
+    while 1:
+        if Char1Glob == 'A':
+            IntLoc = IntLoc - 1
+            IntParIO = IntLoc - IntGlob
+            EnumLoc = Ident1
+        if EnumLoc == Ident1:
+            break
+    return IntParIO
+
+def Proc3(PtrParOut):
+    global IntGlob
+
+    if PtrGlb is not None:
+        PtrParOut = PtrGlb.PtrComp
+    else:
+        IntGlob = 100
+    PtrGlb.IntComp = Proc7(10, IntGlob)
+    return PtrParOut
+
+def Proc4():
+    global Char2Glob
+
+    BoolLoc = Char1Glob == 'A'
+    BoolLoc = BoolLoc or BoolGlob
+    Char2Glob = 'B'
+
+def Proc5():
+    global Char1Glob
+    global BoolGlob
+
+    Char1Glob = 'A'
+    BoolGlob = FALSE
+
+def Proc6(EnumParIn):
+    EnumParOut = EnumParIn
+    if not Func3(EnumParIn):
+        EnumParOut = Ident4
+    if EnumParIn == Ident1:
+        EnumParOut = Ident1
+    elif EnumParIn == Ident2:
+        if IntGlob > 100:
+            EnumParOut = Ident1
+        else:
+            EnumParOut = Ident4
+    elif EnumParIn == Ident3:
+        EnumParOut = Ident2
+    elif EnumParIn == Ident4:
+        pass
+    elif EnumParIn == Ident5:
+        EnumParOut = Ident3
+    return EnumParOut
+
+def Proc7(IntParI1, IntParI2):
+    IntLoc = IntParI1 + 2
+    IntParOut = IntParI2 + IntLoc
+    return IntParOut
+
+def Proc8(Array1Par, Array2Par, IntParI1, IntParI2):
+    global IntGlob
+
+    IntLoc = IntParI1 + 5
+    Array1Par[IntLoc] = IntParI2
+    Array1Par[IntLoc+1] = Array1Par[IntLoc]
+    Array1Par[IntLoc+30] = IntLoc
+    for IntIndex in range(IntLoc, IntLoc+2):
+        Array2Par[IntLoc][IntIndex] = IntLoc
+    Array2Par[IntLoc][IntLoc-1] = Array2Par[IntLoc][IntLoc-1] + 1
+    Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc]
+    IntGlob = 5
+
+def Func1(CharPar1, CharPar2):
+    CharLoc1 = CharPar1
+    CharLoc2 = CharLoc1
+    if CharLoc2 != CharPar2:
+        return Ident1
+    else:
+        return Ident2
+
+def Func2(StrParI1, StrParI2):
+    IntLoc = 1
+    while IntLoc <= 1:
+        if Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1:
+            CharLoc = 'A'
+            IntLoc = IntLoc + 1
+    if CharLoc >= 'W' and CharLoc <= 'Z':
+        IntLoc = 7
+    if CharLoc == 'X':
+        return TRUE
+    else:
+        if StrParI1 > StrParI2:
+            IntLoc = IntLoc + 7
+            return TRUE
+        else:
+            return FALSE
+
+def Func3(EnumParIn):
+    EnumLoc = EnumParIn
+    if EnumLoc == Ident3: return TRUE
+    return FALSE
+
+if __name__ == '__main__':
+    import sys
+    def error(msg):
+        print(msg, end=' ', file=sys.stderr)
+        print("usage: %s [number_of_loops]" % sys.argv[0], file=sys.stderr)
+        sys.exit(100)
+    nargs = len(sys.argv) - 1
+    if nargs > 1:
+        error("%d arguments are too many;" % nargs)
+    elif nargs == 1:
+        try: loops = int(sys.argv[1])
+        except ValueError:
+            error("Invalid argument %r;" % sys.argv[1])
+    else:
+        loops = LOOPS
+    main(loops)

+ 347 - 0
benchmarks/pythonpdevs/test_devstone.py

@@ -0,0 +1,347 @@
+from abc import abstractmethod
+from unittest import TestCase
+import random
+
+from pypdevs.DEVS import AtomicDEVS, CoupledDEVS
+from pypdevs.simulator import Simulator
+
+from devstone import LI, DelayedAtomic, DelayedAtomicStats, HI, HO, HOmod
+from generator import Generator
+from main import DEVStoneEnvironment
+
+
+class Utils:
+
+    @staticmethod
+    def count_atomics(coupled):
+        """
+        :return: Number of atomic components in a coupled model
+        """
+        atomic_count = 0
+        for comp in coupled.component_set:
+            if isinstance(comp, AtomicDEVS):
+                atomic_count += 1
+            elif isinstance(comp, CoupledDEVS):
+                atomic_count += Utils.count_atomics(comp)
+            else:
+                raise RuntimeError("Unrecognized type of component")
+
+        return atomic_count
+
+    @staticmethod
+    def count_ic(coupled):
+        """
+        :return: Number of ic couplings in a coupled model
+        """
+        ic_count = 0
+        for comp in coupled.component_set:
+            for src_port in comp.OPorts:
+                for dst_port in src_port.outline:
+                    if dst_port.host_DEVS != coupled:
+                        ic_count += 1
+
+        for comp in coupled.component_set:
+            if isinstance(comp, CoupledDEVS):
+                ic_count += Utils.count_ic(comp)
+            elif not isinstance(comp, AtomicDEVS):
+                raise RuntimeError("Unrecognized type of component")
+
+        return ic_count
+
+    @staticmethod
+    def count_eic(coupled):
+        """
+        :return: Number of eic couplings in a coupled model
+        """
+        eic_count = sum([len(port.outline) for port in coupled.IPorts])
+        for comp in coupled.component_set:
+            if isinstance(comp, CoupledDEVS):
+                eic_count += Utils.count_eic(comp)
+            elif not isinstance(comp, AtomicDEVS):
+                raise RuntimeError("Unrecognized type of component")
+
+        return eic_count
+
+    @staticmethod
+    def count_eoc(coupled):
+        """
+        :return: Number of eoc couplings in a coupled model
+        """
+        eoc_count = sum([len(port.inline) for port in coupled.OPorts])
+        for comp in coupled.component_set:
+            if isinstance(comp, CoupledDEVS):
+                eoc_count += Utils.count_eoc(comp)
+            elif not isinstance(comp, AtomicDEVS):
+                raise RuntimeError("Unrecognized type of component")
+
+        return eoc_count
+
+    @staticmethod
+    def count_transitions(coupled):
+        """
+        :return: Number of atomic components in a coupled model
+        """
+        int_count = 0
+        ext_count = 0
+        for comp in coupled.component_set:
+            if isinstance(comp, DelayedAtomicStats):
+                int_count += comp.int_count
+                ext_count += comp.ext_count
+            elif isinstance(comp, CoupledDEVS):
+                pic, pec = Utils.count_transitions(comp)
+                int_count += pic
+                ext_count += pec
+            elif not isinstance(comp, Generator):
+                raise RuntimeError("Unexpected type of component: %s" % comp.__class__.__name__)
+
+        return int_count, ext_count
+
+
+class DevstoneUtilsTestCase(TestCase):
+
+    def __init__(self, name, num_valid_params_sets: int = 10):
+        super().__init__(name)
+        self.valid_high_params = []
+        self.valid_low_params = []
+
+        for _ in range(int(num_valid_params_sets)):
+            self.valid_high_params.append([random.randint(1, 100), random.randint(1, 200),
+                                           random.randint(1, 1000), random.randint(1, 1000)])
+
+        for _ in range(int(num_valid_params_sets)):
+            self.valid_low_params.append([random.randint(1, 20), random.randint(1, 30),
+                                      random.randint(0, 10), random.randint(0, 10)])
+
+    def check_invalid_inputs(self, base_class):
+        self.assertRaises(ValueError, base_class, "root", 0, 1, 1, 1)
+        self.assertRaises(ValueError, base_class, "root", 1, 0, 1, 1)
+        self.assertRaises(ValueError, base_class, "root", 1, 1, -1, 0)
+        self.assertRaises(ValueError, base_class, "root", 1, 1, 0, -1)
+        self.assertRaises(ValueError, base_class, "root", 0, 1, -1, -1)
+        self.assertRaises(ValueError, base_class, "root", 0, 0, -1, -1)
+
+    def test_behavior_sequential(self):
+        self._test_behavior(Simulator)
+
+    #def test_behavior_parallel(self):
+    #    self._test_behavior(ParallelThreadCoordinator)
+
+    @abstractmethod
+    def _test_behavior(self, Coordinator):
+        pass
+
+
+class TestLI(DevstoneUtilsTestCase):
+
+    def test_structure(self):
+        """
+        Check structure params: atomic modules, ic's, eic's and eoc's.
+        """
+        for params_tuple in self.valid_high_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                self._check_structure(**params)
+
+    def test_structure_corner_cases(self):
+        params = {"depth": 10, "width": 1, "int_delay": 1, "ext_delay": 1}
+        self._check_structure(**params)
+        params["depth"] = 1
+        self._check_structure(**params)
+
+    def _check_structure(self, **params):
+        li_root = LI("LI_root", **params)
+        self.assertEqual(Utils.count_atomics(li_root), (params["width"] - 1) * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eic(li_root), params["width"] * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eoc(li_root), params["depth"])
+        self.assertEqual(Utils.count_ic(li_root), 0)
+
+    def _test_behavior(self, coord_type):
+        """
+        Check behaviour params: number of int and ext transitions.
+        """
+        for params_tuple in self.valid_low_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                li_root = LI("LI_root", stats=True, **params)
+                li_env = DEVStoneEnvironment("LI_env", li_root)
+                sim = Simulator(li_env)
+                sim.setVerbose(None)
+                # sim.setTerminationTime(10.0)
+                # sim.setStateSaving("custom")
+                sim.simulate()
+
+                int_count, ext_count = Utils.count_transitions(li_root)
+                self.assertEqual(int_count, (params["width"] - 1) * (params["depth"] - 1) + 1)
+                self.assertEqual(ext_count, (params["width"] - 1) * (params["depth"] - 1) + 1)
+
+    def test_invalid_inputs(self):
+        super().check_invalid_inputs(LI)
+
+
+class TestHI(DevstoneUtilsTestCase):
+
+    def test_structure(self):
+        """
+        Check structure params: atomic modules, ic's, eic's and eoc's.
+        """
+        for params_tuple in self.valid_high_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                self._check_structure(**params)
+
+    def test_structure_corner_cases(self):
+        params = {"depth": 10, "width": 1, "int_delay": 1, "ext_delay": 1}
+        self._check_structure(**params)
+        params["depth"] = 1
+        self._check_structure(**params)
+
+    def _check_structure(self, **params):
+        hi_root = HI("HI_root", **params)
+        self.assertEqual(Utils.count_atomics(hi_root), (params["width"] - 1) * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eic(hi_root), params["width"] * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eoc(hi_root), params["depth"])
+        self.assertEqual(Utils.count_ic(hi_root),
+                         (params["width"] - 2) * (params["depth"] - 1) if params["width"] > 2 else 0)
+
+    def _test_behavior(self, coord_type):
+        """
+        Check behaviour params: number of int and ext transitions.
+        """
+        for params_tuple in self.valid_low_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                hi_root = HI("HI_root", stats=True, **params)
+                hi_env = DEVStoneEnvironment("HI_env", hi_root)
+                sim = Simulator(hi_env)
+                sim.setVerbose(None)
+                # sim.setTerminationTime(10.0)
+                # sim.setStateSaving("custom")
+                sim.simulate()
+
+                int_count, ext_count = Utils.count_transitions(hi_root)
+                self.assertEqual(int_count, (((params["width"] - 1) * params["width"]) / 2) * (params["depth"] - 1) + 1)
+                self.assertEqual(ext_count, (((params["width"] - 1) * params["width"]) / 2) * (params["depth"] - 1) + 1)
+
+    def test_invalid_inputs(self):
+        super().check_invalid_inputs(HI)
+
+
+class TestHO(DevstoneUtilsTestCase):
+
+    def test_structure(self):
+        """
+        Check structure params: atomic modules, ic's, eic's and eoc's.
+        """
+        for params_tuple in self.valid_high_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                self._check_structure(**params)
+
+    def test_structure_corner_cases(self):
+        params = {"depth": 10, "width": 1, "int_delay": 1, "ext_delay": 1}
+        self._check_structure(**params)
+        params["depth"] = 1
+        self._check_structure(**params)
+
+    def _check_structure(self, **params):
+        ho_root = HO("HO_root", **params)
+        self.assertEqual(Utils.count_atomics(ho_root), (params["width"] - 1) * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eic(ho_root), (params["width"] + 1) * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eoc(ho_root), params["width"] * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_ic(ho_root),
+                         (params["width"] - 2) * (params["depth"] - 1) if params["width"] > 2 else 0)
+
+    def _test_behavior(self, coord_type):
+        """
+        Check behaviour params: number of int and ext transitions.
+        """
+        for params_tuple in self.valid_low_params[0]:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                ho_root = HO("HO_root", stats=True, **params)
+                ho_env = DEVStoneEnvironment("HO_env", ho_root)
+                sim = Simulator(ho_env)
+                sim.setVerbose(None)
+                # sim.setTerminationTime(10.0)
+                # sim.setStateSaving("custom")
+                sim.simulate()
+
+                int_count, ext_count = Utils.count_transitions(ho_env)
+                self.assertEqual(int_count, (((params["width"] - 1) * params["width"]) / 2) * (params["depth"] - 1) + 1)
+                self.assertEqual(ext_count, (((params["width"] - 1) * params["width"]) / 2) * (params["depth"] - 1) + 1)
+
+    def test_invalid_inputs(self):
+        super().check_invalid_inputs(HO)
+
+
+class TestHOmod(DevstoneUtilsTestCase):
+
+    def test_structure(self):
+        """
+        Check structure params: atomic modules, ic's, eic's and eoc's.
+        """
+        for params_tuple in self.valid_high_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                self._check_structure(**params)
+
+    def test_structure_corner_cases(self):
+        params = {"depth": 10, "width": 1, "int_delay": 1, "ext_delay": 1}
+        self._check_structure(**params)
+        params["depth"] = 1
+        self._check_structure(**params)
+
+    def _check_structure(self, **params):
+        homod_root = HOmod("HOmod_root", **params)
+        self.assertEqual(Utils.count_atomics(homod_root),
+                         ((params["width"] - 1) + ((params["width"] - 1) * params["width"]) / 2) * (
+                                     params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eic(homod_root), (2 * (params["width"] - 1) + 1) * (params["depth"] - 1) + 1)
+        self.assertEqual(Utils.count_eoc(homod_root), params["depth"])
+        # ICs relative to the "triangular" section
+        exp_ic = (((params["width"] - 2) * (params["width"] - 1)) / 2) if params["width"] > 1 else 0
+        # Plus the ones relative to the connection from the 2nd to 1st row...
+        exp_ic += (params["width"] - 1) ** 2
+        # ...and from the 1st to the couple component
+        exp_ic += params["width"] - 1
+        # Multiplied by the number of layers (except the deepest one, that doesn't have ICs)
+        exp_ic *= (params["depth"] - 1)
+        self.assertEqual(Utils.count_ic(homod_root), exp_ic)
+
+    def _test_behavior(self, coord_type):
+        """
+        Check behaviour params: number of int and ext transitions.
+        """
+        for params_tuple in self.valid_low_params:
+            params = dict(zip(("depth", "width", "int_delay", "ext_delay"), params_tuple))
+
+            with self.subTest(**params):
+                homod_root = HOmod("HOmod_root", stats=True, **params)
+                homod_env = DEVStoneEnvironment("HOmod_env", homod_root)
+                sim = Simulator(homod_env)
+                sim.setVerbose(None)
+                # sim.setTerminationTime(10.0)
+                # sim.setStateSaving("custom")
+                sim.simulate()
+
+                calc_in = lambda x, w: 1 + (x - 1) * (w - 1)
+                exp_trans = 1
+                tr_atomics = sum(range(1, params["width"]))
+                for i in range(1, params["depth"]):
+                    num_inputs = calc_in(i, params["width"])
+                    trans_first_row = (params["width"] - 1) * (num_inputs + params["width"] - 1)
+                    exp_trans += num_inputs * tr_atomics + trans_first_row
+
+                int_count, ext_count = Utils.count_transitions(homod_env)
+                self.assertEqual(int_count, exp_trans)
+                self.assertEqual(ext_count, exp_trans)
+
+    def test_invalid_inputs(self):
+        super().check_invalid_inputs(HOmod)

+ 286 - 0
benchmarks/testPyPDEVS.py

@@ -0,0 +1,286 @@
+#!/usr/bin/env python3
+import os
+import subprocess
+import csv
+import re
+from argparse import ArgumentParser, Action
+from pathlib import Path
+from model_properties import model_properties
+
+MODEL_TYPES = ("LI", "HI", "HO", "HOmod")
+DS_MODEL_TYPES = ("LI2HI", "HI2LI", "LI-HI", "dLI", "mdLI", "dHI", "mdHI", "dHO", "mdHO", "test")
+GEN_METHODS = ("start", "uniform", "end")
+
+INT_CYCLES = 0
+EXT_CYCLES = 0
+
+PyPDEVS = "./pythonpdevs/main.py"
+MinimalPyPDEVS = "./pythonpdevs-minimal/main.py"
+
+# Regex to capture times from script output
+TIME_PATTERN = re.compile(
+    r"Model creation time: ([\d.eE+-]+).*"
+    r"Engine setup time: ([\d.eE+-]+).*"
+    r"Simulation time: ([\d.eE+-]+)",
+    re.S
+)
+
+
+def create_graph(file, title=None):
+    # Base command
+    cmd = f"procpath plot -d {file} -f {file.with_suffix('.svg')} -q rss --relative-time"
+
+    # Add title if provided
+    if title:
+        cmd += f" --title '{title}'"
+
+    subprocess.run(cmd, shell=True)
+
+def run_devstone(model_type, depth, width, mode, out, memory, stats, *, classic=False, number=1, gen_mode="uniform"):
+    """Runs the devstone_driver.py script and returns timing results as floats."""
+    SCRIPT_PATH = PyPDEVS
+    if mode == "minimal":
+        SCRIPT_PATH = MinimalPyPDEVS
+
+    cmd = [
+        "uv", "run", SCRIPT_PATH,
+        "-m", model_type,
+        "-d", str(depth),
+        "-w", str(width),
+        "-i", str(INT_CYCLES),
+        "-e", str(EXT_CYCLES),
+    ]
+    if stats:
+        cmd.extend(["-s"])
+
+    if mode == "dynamic":
+        cmd.extend(["-D"])
+        if classic:
+            cmd.extend(["-C"])
+        cmd.extend(["-n", str(number)])
+        cmd.extend(["-g", gen_mode])
+    if mode == "classic":
+        cmd.extend(["-C"])
+    full_cmd = " ".join(cmd)
+
+    if memory:
+        full_cmd = (
+            f"{full_cmd} & "
+            f"PID=$!; "
+            f"python -m procpath record -i {memory['interval']} -f stat -d {memory['file']} "
+            f"--stop-without-result \"$..children[?(@.stat.pid == $PID)]\""
+        )
+
+    result = subprocess.run(full_cmd, shell=True, capture_output=True, text=True)
+    cout = result.stdout.strip()
+    if out:
+        print(cout)
+    if memory:
+        props = model_properties(model_type, width, depth)
+        n_atomic = props.get("Atomic Models", "0")
+        graph_title = f"{model_type} ({n_atomic} atomic models)"
+        create_graph(memory["file"], graph_title)
+
+    cerr = result.stderr.strip()
+    match = TIME_PATTERN.search(cout)
+
+    if match:
+        creation, setup, sim = map(float, match.groups())
+        return creation, setup, sim
+
+    print("Failed to run: ", " ".join(cmd))
+    print(cout)
+    print(cerr)
+    return None, None, None
+
+def defaultArguments(parser):
+    parser.add_argument("-p", "--path", type=Path, default=Path("./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", 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", 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")
+    parser.add_argument("-O", "--output", action="store_true", help="Print Simulation Outputs")
+    parser.add_argument("-M", "--memory", action="store_true", help="Measures the memory usage of a simulation.")
+    parser.add_argument("-i", "--interval", default=1.0, type=float, help="The interval at which measurements are taken.")
+    parser.add_argument("--stats", "-s", action="store_true", help="Enable Event Tracking")
+
+def Minimal(subparsers):
+    minimal = subparsers.add_parser("minimal", help="Minimal DEVS kernel")
+    minimal.set_defaults(mode="minimal")
+    defaultArguments(minimal)
+    minimal.add_argument(
+        "-ms", "--model-structure",
+        nargs="+",
+        choices=MODEL_TYPES,
+        default=MODEL_TYPES
+    )
+
+def Classic(subparsers):
+    classic = subparsers.add_parser("classic", help="Classic DEVS Simulator")
+    classic.set_defaults(mode="classic")
+    defaultArguments(classic)
+    classic.add_argument(
+        "-ms", "--model-structure",
+        nargs="+",
+        choices=MODEL_TYPES,
+        default=MODEL_TYPES
+    )
+
+def Parallel(subparsers):
+    parallel = subparsers.add_parser("parallel", help="Parallel DEVS")
+    parallel.set_defaults(mode="parallel")
+    defaultArguments(parallel)
+    parallel.add_argument(
+        "-ms", "--model-structure",
+        nargs="+",
+        choices=MODEL_TYPES,
+        default=MODEL_TYPES
+    )
+
+def Dynamic(subparsers):
+    dynamic = subparsers.add_parser("dynamic", help="Dynamic Structure DEVS")
+    dynamic.set_defaults(mode="dynamic")
+    defaultArguments(dynamic)
+    dynamic.add_argument(
+        "-ms", "--model-structure",
+        nargs="+",
+        choices=MODEL_TYPES + DS_MODEL_TYPES,
+        default=MODEL_TYPES + DS_MODEL_TYPES
+    )
+    dynamic.add_argument(
+        "-C", "--classic",
+        action="store_true",
+        default=False,
+        help="Selects the Classic DEVS Simulator"
+    )
+    dynamic.add_argument(
+        "-n", "--number",
+        default=1,
+        type=int,
+        help="Number of models to be generated in a cycle per coupled model")
+    dynamic.add_argument(
+        "-g", "--gen-mode",
+        choices=GEN_METHODS,
+        default="uniform"
+    )
+
+def parse_args():
+    parser = ArgumentParser()
+    subparsers = parser.add_subparsers(dest="mode")
+    Minimal(subparsers)
+    Parallel(subparsers)
+    Classic(subparsers)
+    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
+
+    if args.memory or args.stats:
+        args.output = True
+
+    return args
+
+def run(writer, csvfile, model_type, d, w, args, mem_cmd, extra):
+    """Orchestrates the repeated simulation runs."""
+    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):
+                creation, setup, sim = run_devstone(
+                    model_type, depth, width,
+                    args.mode, args.output,
+                    mem_cmd, args.stats,
+                    **extra
+                )
+
+                # Only write to CSV if a writer was provided
+                if writer and creation is not None:
+                    row = {
+                        "model_type": model_type, "depth": depth, "width": width, "run": run,
+                        "creation_time": creation, "setup_time": setup, "simulation_time": sim,
+                    }
+                    if args.mode == "dynamic":
+                        row["number"] = args.number
+                        row["generator_mode"] = args.gen_mode
+                    writer.writerow(row)
+                    csvfile.flush()
+
+
+if __name__ == "__main__":
+    args = parse_args()
+    print(args)
+
+    d = (args.max_depth, args.depth_stepsize)
+    w = (args.max_width, args.width_stepsize)
+    if d[0] % d[1] != 0:
+        raise RuntimeError("Invalid depth stepsize.")
+    if w[0] % w[1] != 0:
+        raise RuntimeError("Invalid width stepsize.")
+
+    fieldnames = ["model_type", "depth", "width", "run",
+                  "creation_time", "setup_time", "simulation_time"]
+    mode = args.mode
+    if mode == "dynamic":
+        if args.classic:
+            mode += "-classic"
+        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,
+    }
+    time_dir = args.path / "Time"
+    time_dir.mkdir(parents=True, exist_ok=True)
+    mem_dir = args.path / "Memory"
+    mem_dir.mkdir(parents=True, exist_ok=True)
+    for model_type in args.model_structure:
+        time_mode = time_dir / mode
+        time_mode.mkdir(parents=True, exist_ok=True)
+        mem_mode = mem_dir / mode
+        mem_mode.mkdir(parents=True, exist_ok=True)
+
+        time_file = (time_mode / model_type).with_suffix(".csv")
+        memory_file = (mem_mode / model_type).with_suffix(".sqlite")
+
+        if args.number is not None and args.number > 1:
+            time_file = time_file.with_stem(time_file.stem + "-" + str(args.number))
+            memory_file = memory_file.with_stem(memory_file.stem + "-" + str(args.number))
+
+        if args.filename:
+            suffix = f"_{args.filename}"
+            time_file = time_file.with_stem(time_file.stem + suffix)
+            memory_file = memory_file.with_stem(memory_file.stem + suffix)
+
+
+
+
+        mem_cmd = {"interval": args.interval, "file": memory_file} if args.memory else {}
+
+        if not args.memory:
+            file_mode = "a" if args.append else "w"
+            write_header = not args.append or not os.path.exists(time_file)
+
+            with open(time_file, file_mode, newline="") as csvfile:
+                writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
+                if write_header:
+                    writer.writeheader()
+
+                run(writer, csvfile, model_type, d, w, args, mem_cmd, extra)
+            print(f"✅ Saved timing results to {time_file}")
+        else:
+            if os.path.exists(memory_file) and not args.append:
+                os.remove(memory_file)
+
+            print("📊 Measuring memory (Timing results will not be saved)...")
+            run(None, None, model_type, d, w, args, mem_cmd, extra)
+            print(f"✅ Saved memory database to {memory_file}")
+

+ 109 - 0
benchmarks/w-d-plot.py

@@ -0,0 +1,109 @@
+#!/usr/bin/env python3
+import numpy as np
+import matplotlib.pyplot as plt
+from mpl_toolkits.mplot3d import Axes3D
+import matplotlib.cm as cm
+import matplotlib.colors as colors
+import argparse
+import sys
+
+from model_properties import model_properties
+
+
+def calculate_metric(model_type, metric, W, D):
+    """
+    Calculates the Z-axis data (metric) for the given model type over the meshgrid W, D.
+    Uses the logic defined in model_properties.py.
+    """
+
+    # Create a vectorized wrapper around the model_properties function
+    def get_value(w, d):
+        props = model_properties(model_type, int(w), int(d))
+        if metric == "models":
+            return props.get("Atomic Models", 0)
+        elif metric == "events":
+            return props.get("Events", 0)
+        return 0
+
+    # Vectorize allows the function to operate on the numpy meshgrids W and D efficiently
+    vec_calc = np.vectorize(get_value)
+    return vec_calc(W, D)
+
+
+def plot_data(model_type, metric, max_val):
+    w_vals = np.arange(1, max_val + 1)
+    d_vals = np.arange(1, max_val + 1)
+    W, D = np.meshgrid(w_vals, d_vals)
+
+    print(f"Calculating '{metric}' for model '{model_type}'...")
+    Z_data = calculate_metric(model_type, metric, W, D)
+
+    x = W.ravel()
+    y = D.ravel()
+    z = np.zeros_like(x)
+    dx = dy = 0.6
+    dz = Z_data.ravel()
+
+    norm = colors.Normalize(vmin=dz.min(), vmax=dz.max())
+    colors_map = cm.viridis(norm(dz))
+
+    fig = plt.figure(figsize=(12, 8))
+    ax = fig.add_subplot(111, projection='3d')
+
+    ax.bar3d(x - dx / 2, y - dy / 2, z, dx, dy, dz, shade=True, color=colors_map, zsort='average')
+
+    metric_label = "# Atomic Models" if metric == "models" else "# Events"
+
+    ax.set_xlabel('Width')
+    ax.set_ylabel('Depth')
+    ax.set_zlabel(metric_label)
+
+    tick_step = max(1, max_val // 10)
+    ax.set_xticks(w_vals[::tick_step])
+    ax.set_yticks(d_vals[::tick_step])
+
+    ax.set_title(f"{metric_label} for {model_type} Model")
+    ax.view_init(elev=30, azim=-135)
+
+    mappable = cm.ScalarMappable(norm=norm, cmap=cm.viridis)
+    mappable.set_array(dz)
+    cbar = fig.colorbar(mappable, ax=ax, shrink=0.6, pad=0.1)
+    cbar.set_label('Count')
+
+    plt.tight_layout()
+    print("Displaying plot...")
+    plt.show()
+
+
+def main():
+    parser = argparse.ArgumentParser(description="Plot 3D bar chart for DEVS Model metrics.")
+
+    parser.add_argument(
+        "-m", "--model",
+        type=str,
+        choices=["LI", "HI", "HO", "HOmod"],
+        default="LI",
+        help="The model type to analyze (default: LI)"
+    )
+
+    parser.add_argument(
+        "-z", "--z-axis",
+        type=str,
+        choices=["models", "events"],
+        default="models",
+        help="The metric to plot on the Z-axis: 'models' or 'events' (default: models)"
+    )
+
+    parser.add_argument(
+        "-l", "--limit",
+        type=int,
+        default=25,
+        help="Maximum value for Width and Depth ranges (default: 25)"
+    )
+
+    args = parser.parse_args()
+    plot_data(args.model, args.z_axis, args.limit)
+
+
+if __name__ == "__main__":
+    main()

+ 0 - 0
devstone/__init__.py


+ 0 - 27
devstone/adevs/CMakeLists.txt

@@ -1,27 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-project(devstone-adevs)
-set (CMAKE_CXX_STANDARD 17)
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
-
-if(NOT CMAKE_BUILD_TYPE)
-  set(CMAKE_BUILD_TYPE Release)
-endif()
-set(CMAKE_CXX_FLAGS_DEBUG "-g")
-set(CMAKE_CXX_FLAGS_RELEASE "-O3")
-
-include_directories(SYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/../../simulators/adevs-3.3/include)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-
-add_executable(devstone src/devstone.cpp)
-
-# Testing stuff
-find_package(Boost COMPONENTS system filesystem unit_test_framework)
-if (Boost_FOUND)
-  add_definitions(-DBOOST_TEST_DYN_LINK)
-  enable_testing()
-  add_executable(test_devstone test/test_devstone.cpp)
-  target_link_libraries(test_devstone ${Boost_FILESYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
-  add_test(NAME test_devstone COMMAND test_devstone)
-else()
-  message(STATUS "Boost not found. You won't be able to run tests for adevs.")
-endif()

+ 0 - 53
devstone/adevs/src/devstone.cpp

@@ -1,53 +0,0 @@
-#include <chrono>
-#include <iostream>
-#include <string>
-#include "devstone.hpp"
-using namespace std;
-using hclock=chrono::high_resolution_clock;
-
-int main(int argc, char* argv[]) {
-    // First, we parse the arguments
-    if (argc < 4) {
-        std::cerr << "ERROR: not enough arguments" << std::endl;
-        std::cerr << "    Usage:" << std::endl;
-        std::cerr << "    > devstone MODEL_TYPE WIDTH DEPTH INTDELAY EXTDELAY" << std::endl;
-        std::cerr << "        (MODEL_TYPE must be either LI, HI, HO, or HOmod)" << std::endl;
-        std::cerr << "        (WIDTH and DEPTH must be greater than or equal to 1)" << std::endl;
-        std::cerr << "        (INTDELAY and EXTDELAY must be greater than or equal to 0 ms)" << std::endl;
-        std::cerr << "    Alternative usages:" << std::endl;
-        std::cerr << "    > main_devstone MODEL_TYPE WIDTH DEPTH DELAY" << std::endl;
-        std::cerr << "        (INTDELAY and EXTDELAY are set to DELAY ms)" << std::endl;
-        std::cerr << "    > main_devstone MODEL_TYPE WIDTH DEPTH" << std::endl;
-        std::cerr << "        (INTDELAY and EXTDELAY are set to 0 ms)" << std::endl;
-        return -1;
-    }
-    std::string type = argv[1];
-    int width = std::stoi(argv[2]);
-    int depth = std::stoi(argv[3]);
-    int intDelay = 0;
-    int extDelay = 0;
-    if (argc > 4) {
-        intDelay = std::stoi(argv[4]);
-        extDelay = (argc == 5) ? intDelay : std::stoi(argv[5]);
-    }
-    auto processed_parameters = hclock::now();
-
-    auto *devstone = new DEVStone(type, width, depth, intDelay, extDelay);
-
-    auto model_built = hclock::now();
-
-    cout << endl;
-    cout << "Model creation time: " << chrono::duration_cast<chrono::duration<double, ratio<1>>>( model_built - processed_parameters).count() << " seconds" << endl;
-    adevs::Simulator<IO_Type> sim(devstone);
-
-    auto model_init = hclock::now();
-
-    cout << "Engine setup time: " << chrono::duration_cast<chrono::duration<double, ratio<1>>>( model_init - model_built).count() << " seconds" << endl;
-    while (sim.nextEventTime() < DBL_MAX) {
-        sim.execNextEvent();
-    }
-    /// Done!
-    auto finished_simulation = hclock::now();
-    cout << "Simulation time: " << chrono::duration_cast<chrono::duration<double, ratio<1>>>( finished_simulation - model_init).count() << " seconds" << endl;
-    return 0;
-}

+ 0 - 47
devstone/adevs/src/devstone.hpp

@@ -1,47 +0,0 @@
-#ifndef DEVSTONE_ADEVS_DEVSTONE_HPP
-#define DEVSTONE_ADEVS_DEVSTONE_HPP
-
-#include "utils.hpp"
-#include "li.hpp"
-#include "hi.hpp"
-#include "ho.hpp"
-#include "homod.hpp"
-#include "seeder.hpp"
-
-class DEVStone: public adevs::Digraph<int*> {
-public:
-    [[maybe_unused]] DEVStoneCoupled *model;
-    DEVStone(const string& type, int width, int depth, int intDelay, int extDelay): adevs::Digraph<int*>() {
-        auto *seeder = new Seeder();
-        add(seeder);
-
-        //adevs::Digraph<int*> devstone;
-        if (type == "LI") {
-            auto *li = new LI(width, depth, intDelay, extDelay);
-            add(li);
-            couple(seeder, Seeder::out, li, LI::in);
-            model = li;
-        } else if (type == "HI") {
-            auto *hi = new HI(width, depth, intDelay, extDelay);
-            add(hi);
-            couple(seeder, Seeder::out, hi, HI::in);
-            model = hi;
-        } else if (type == "HO") {
-            auto *ho = new HO(width, depth, intDelay, extDelay);
-            add(ho);
-            couple(seeder, Seeder::out, ho, HO::in);
-            couple(seeder, Seeder::out, ho, HOmod::in2);
-            model = ho;
-        } else if (type == "HOmod") {
-            auto *homod = new HOmod(width, depth, intDelay, extDelay);
-            add(homod);
-            couple(seeder, Seeder::out, homod, HOmod::in);
-            couple(seeder, Seeder::out, homod, HOmod::in2);
-            model = homod;
-        } else {
-            throw runtime_error("Unable to determine DEVStone model type");
-        }
-    }
-};
-
-#endif //DEVSTONE_ADEVS_DEVSTONE_HPP

+ 0 - 61
devstone/adevs/src/devstone_atomic.hpp

@@ -1,61 +0,0 @@
-#ifndef DEVSTONE_ADEVS_DEVSTONEATOMIC_HPP
-#define DEVSTONE_ADEVS_DEVSTONEATOMIC_HPP
-
-#include <adevs.h>
-#include <list>
-#include "utils.hpp"
-
-class DEVStoneAtomic: public adevs::Atomic<IO_Type> {
-    private:
-        /// Model state variables
-        __attribute__ ((unused)) int intDelay, extDelay;  // TODO include Dhrystone stuff
-        double sigma;
-    public:
-        /// Model input port
-        static const int in = 0;
-        /// Model output port
-        static const int out = 1;
-        /// To count the number of events etc.
-        unsigned int nInternals, nExternals, nEvents;
-
-        /// Constructor
-        DEVStoneAtomic(int intDelay, int extDelay): adevs::Atomic<IO_Type>(), intDelay(intDelay), extDelay(extDelay), sigma(DBL_MAX) {
-            nInternals = 0;
-            nExternals = 0;
-            nEvents = 0;
-        }
-
-        /// External transition function
-        void delta_ext(__attribute__ ((unused)) double e, const adevs::Bag<IO_Type>& x) override {
-            // DhryStone().dhrystoneRun(extDelay); // TODO
-            nExternals += 1;
-            nEvents += x.size();
-            sigma = 0;
-        }
-
-        /// Internal transition function
-        void delta_int() override {
-            // DhryStone().dhrystoneRun(intDelay); // TODO
-            nInternals += 1;
-            sigma = DBL_MAX;
-        }
-
-        /// Confluent transition function.
-        void delta_conf(const adevs::Bag<IO_Type>& x) override {
-            delta_int();
-            delta_ext(0.0, x);
-        }
-        /// Output function.
-        void output_func(adevs::Bag<IO_Type>& y) override {
-            y.insert(IO_Type(out, 0));
-        }
-
-        /// Time advance function.
-        double ta() override {
-            return sigma;
-        }
-        /// Garbage collection.
-        void gc_output(adevs::Bag<IO_Type>&) override {}
-};
-
-#endif //DEVSTONE_ADEVS_DEVSTONEATOMIC_HPP

+ 0 - 98
devstone/adevs/src/devstone_coupled.hpp

@@ -1,98 +0,0 @@
-#ifndef DEVSTONE_ADEVS_DEVSTONECOUPLED_HPP
-#define DEVSTONE_ADEVS_DEVSTONECOUPLED_HPP
-
-#include "utils.hpp"
-#include "devstone_atomic.hpp"
-#include <vector>
-
-class DEVStoneCoupled: public adevs::Digraph<int*> {
-protected:
-    DEVStoneCoupled* childCoupled;
-    std::vector<DEVStoneAtomic*> atomics;
-    int intDelay, extDelay;
-    std::size_t nEIC, nIC, nEOC;
-
-public:
-    /// Model input port
-    static const int in = 0;
-    /// Model output port
-    static const int out = 1;
-    /// Constructor
-    DEVStoneCoupled(int width, int depth, int intDelay, int extDelay): adevs::Digraph<int*>(), childCoupled(), atomics(), intDelay(intDelay), extDelay(extDelay), nEIC(), nIC(), nEOC() {
-        if (depth < 1 || width < 1) {
-            throw std::bad_exception();
-        }
-        if (depth == 1) {
-            auto *a = addAtomic();
-            couple(this, DEVStoneCoupled::in, a, DEVStoneAtomic::in);
-            nEIC += 1;
-            couple(a, DEVStoneAtomic::out, this, DEVStoneCoupled::out);
-            nEOC += 1;
-        }
-    }
-
-    DEVStoneAtomic* addAtomic() {
-        auto *a = new DEVStoneAtomic(intDelay, extDelay);
-        add(a);
-        atomics.push_back(a);
-        return a;
-    }
-
-    [[nodiscard]] unsigned long nEICs() const {
-        auto res = nEIC;
-        if (childCoupled != nullptr) {
-            res += childCoupled->nEICs();
-        }
-        return res;
-    }
-
-    [[nodiscard]] unsigned long nICs() const {
-        auto res = nIC;
-        if (childCoupled != nullptr) {
-            res += childCoupled->nICs();
-        }
-        return res;
-    }
-
-    [[nodiscard]] unsigned long nEOCs() const {
-        auto res = nEOC;
-        if (childCoupled != nullptr) {
-            res += childCoupled->nEOCs();
-        }
-        return res;
-    }
-
-    [[nodiscard]] unsigned long nAtomics() const {
-        auto res = atomics.size();
-        if (childCoupled != nullptr) {
-            res += childCoupled->nAtomics();
-        }
-        return res;
-    }
-
-    [[nodiscard]] unsigned long nInternals() const {
-        auto res = (childCoupled != nullptr) ? childCoupled->nInternals() : 0;
-        for (const auto& atomic: atomics) {
-            res += atomic->nInternals;
-        }
-        return res;
-    }
-
-    [[nodiscard]] unsigned long nExternals() const {
-        auto res = (childCoupled != nullptr) ? childCoupled->nExternals() : 0;
-        for (const auto& atomic: atomics) {
-            res += atomic->nExternals;
-        }
-        return res;
-    }
-
-    [[nodiscard]] unsigned long nEvents() const {
-        auto res = (childCoupled != nullptr) ? childCoupled->nEvents() : 0;
-        for (const auto& atomic: atomics) {
-            res += atomic->nEvents;
-        }
-        return res;
-    }
-};
-
-#endif //DEVSTONE_ADEVS_DEVSTONECOUPLED_HPP

+ 0 - 33
devstone/adevs/src/hi.hpp

@@ -1,33 +0,0 @@
-#ifndef DEVSTONE_ADEVS_HI_HPP
-#define DEVSTONE_ADEVS_HI_HPP
-
-#include "utils.hpp"
-#include "devstone_coupled.hpp"
-
-class HI: public DEVStoneCoupled {
-public:
-    HI(int width, int depth, int intDelay, int extDelay): DEVStoneCoupled(width, depth, intDelay, extDelay) {
-        if (depth > 1) {
-            childCoupled = new HI(width, depth - 1, intDelay, extDelay);
-            add(childCoupled);
-            couple(this, HI::in, childCoupled, HI::in);
-            nEIC += 1;
-            couple(childCoupled, HI::out, this, HI::out);
-            nEOC += 1;
-            DEVStoneAtomic* prevAtomic = nullptr;
-            for (auto i = 1; i < width; ++i) {
-                auto atomic = addAtomic();
-                couple(this, HI::in, atomic, DEVStoneAtomic::in);
-                nEIC += 1;
-                if (prevAtomic != nullptr) {
-                    couple(prevAtomic, DEVStoneAtomic::out, atomic, DEVStoneAtomic::in);
-                    nIC += 1;
-                }
-                prevAtomic = atomic;
-            }
-        }
-    }
-};
-
-
-#endif //DEVSTONE_ADEVS_HI_HPP

+ 0 - 41
devstone/adevs/src/ho.hpp

@@ -1,41 +0,0 @@
-#ifndef DEVSTONE_ADEVS_HO_HPP
-#define DEVSTONE_ADEVS_HO_HPP
-
-#include <adevs.h>
-#include "devstone.hpp"
-#include "devstone_coupled.hpp"
-
-class HO: public DEVStoneCoupled {
-public:
-    /// Additional model input port
-    static const int in2 = 2;
-    /// Additional model output port
-    static const int out2 = 3;
-    HO(int width, int depth, int intDelay, int extDelay): DEVStoneCoupled(width, depth, intDelay, extDelay) {
-        if (depth > 1) {
-            childCoupled = new HO(width, depth - 1, intDelay, extDelay);
-            add(childCoupled);
-            couple(this, HO::in, childCoupled, HO::in);
-            nEIC += 1;
-            couple(this, HO::in2, childCoupled, HO::in2);
-            nEIC += 1;
-            couple(childCoupled, HO::out, this, HO::out);
-            nEOC += 1;
-            DEVStoneAtomic* prevAtomic = nullptr;
-            for (auto i = 1; i < width; ++i) {
-                auto atomic = addAtomic();
-                couple(this, HO::in2, atomic, DEVStoneAtomic::in);
-                nEIC += 1;
-                if (prevAtomic != nullptr) {
-                    couple(prevAtomic, DEVStoneAtomic::out, atomic, DEVStoneAtomic::in);
-                    nIC += 1;
-                }
-                couple(atomic, DEVStoneAtomic::out, this, HO::out2);
-                nEOC += 1;
-                prevAtomic = atomic;
-            }
-        }
-    }
-};
-
-#endif //DEVSTONE_ADEVS_HO_HPP

+ 0 - 64
devstone/adevs/src/homod.hpp

@@ -1,64 +0,0 @@
-#ifndef DEVSTONE_ADEVS_HOMOD_HPP
-#define DEVSTONE_ADEVS_HOMOD_HPP
-
-#include "utils.hpp"
-#include "devstone_coupled.hpp"
-
-class HOmod: public DEVStoneCoupled {
- public:
-    /// Additional model input port
-    static const int in2 = 2;
-    HOmod(int width, int depth, int intDelay, int extDelay): DEVStoneCoupled(width, depth, intDelay, extDelay) {
-        if (depth > 1) {
-            childCoupled = new HOmod(width, depth - 1, intDelay, extDelay);
-            add(childCoupled);
-            couple(this, HOmod::in, childCoupled, HOmod::in);
-            nEIC += 1;
-            couple(childCoupled, HOmod::out, this, HOmod::out);
-            nEOC += 1;
-
-            std::vector<DEVStoneAtomic*> prevLayer, currentLayer;
-            // First layer of atomic models:
-            for (int i = 1; i < width; ++i) {
-                auto atomic = addAtomic();
-                couple(this, HOmod::in2, atomic, DEVStoneAtomic::in);
-                nEIC += 1;
-                couple(atomic, DEVStoneAtomic::out, childCoupled, HOmod::in2);
-                nIC += 1;
-                prevLayer.push_back(atomic);
-            }
-            // Second layer of atomic models:
-            for (int i = 1; i < width; ++i) {
-                auto atomic = addAtomic();
-                if (i == 1) {
-                    couple(this, HOmod::in2, atomic, DEVStoneAtomic::in);
-                    nEIC += 1;
-                }
-                for (const auto& prevAtomic: prevLayer) {
-                    couple(atomic, DEVStoneAtomic::out, prevAtomic, DEVStoneAtomic::in);
-                    nIC += 1;
-                }
-                currentLayer.push_back(atomic);
-            }
-            // Rest of the tree
-            prevLayer = currentLayer;
-            currentLayer = std::vector<DEVStoneAtomic*>();
-            for (int layer = 3; layer <= width; ++layer) {
-                for (unsigned long i = 1; i < prevLayer.size(); ++i) {
-                    auto atomic = addAtomic();
-                    if (i == 1) {
-                        couple(this, HOmod::in2, atomic, DEVStoneAtomic::in);
-                        nEIC += 1;
-                    }
-                    couple(atomic, DEVStoneAtomic::out, prevLayer.at(i), DEVStoneAtomic::in);
-                    nIC += 1;
-                    currentLayer.push_back(atomic);
-                }
-                prevLayer = currentLayer;
-                currentLayer = std::vector<DEVStoneAtomic*>();
-            }
-        }
-    }
-};
-
-#endif //DEVSTONE_ADEVS_HOMOD_HPP

+ 0 - 26
devstone/adevs/src/li.hpp

@@ -1,26 +0,0 @@
-#ifndef DEVSTONE_ADEVS_LI_HPP
-#define DEVSTONE_ADEVS_LI_HPP
-
-#include "utils.hpp"
-#include "devstone_coupled.hpp"
-
-class LI: public DEVStoneCoupled {
-  public:
-    LI(int width, int depth, int intDelay, int extDelay): DEVStoneCoupled(width, depth, intDelay, extDelay) {
-        if (depth > 1) {
-            childCoupled = new LI(width, depth - 1, intDelay, extDelay);
-            add(childCoupled);
-            couple(this, LI::in, childCoupled, LI::in);
-            nEIC += 1;
-            couple(childCoupled, LI::out, this, LI::out);
-            nEOC += 1;
-            for (auto i = 1; i < width; ++i) {
-                auto atomic = addAtomic();
-                couple(this, LI::in, atomic, DEVStoneAtomic::in);
-                nEIC += 1;
-            }
-        }
-    }
-};
-
-#endif //DEVSTONE_ADEVS_LI_HPP

+ 0 - 43
devstone/adevs/src/seeder.hpp

@@ -1,43 +0,0 @@
-#ifndef DEVSTONE_ADEVS_SEEDER_HPP
-#define DEVSTONE_ADEVS_SEEDER_HPP
-
-#include <adevs.h>
-#include <list>
-#include "utils.hpp"
-
-class Seeder: public adevs::Atomic<IO_Type> {
-private:
-    /// Model state variables
-    double sigma;
-public:
-    /// Model output port
-    static const int out = 0;
-
-    /// Constructor.
-    explicit Seeder(): adevs::Atomic<IO_Type>(), sigma() {}
-
-    /// External transition function (does not apply)
-    void delta_ext(__attribute__ ((unused)) double e, __attribute__ ((unused)) const adevs::Bag<IO_Type>& x) override {}
-
-    /// Internal transition function (just passivates)
-    void delta_int() override {
-            sigma = std::numeric_limits<double>::infinity();
-    }
-    /// Confluent transition function (standard one)
-    void delta_conf(const adevs::Bag<IO_Type>& x) override {
-        delta_int();
-        delta_ext(0.0, x);
-    }
-    /// Output function (sends a single message via the single port).
-    void output_func(adevs::Bag<IO_Type>& y) override {
-        y.insert(IO_Type(out, 0));
-    }
-    /// Time advance function (just returns sigma)
-    double ta() override {
-        return sigma;
-    }
-    /// Garbage collection.
-    void gc_output(adevs::Bag<IO_Type>&) override {}
-};
-
-#endif //DEVSTONE_ADEVS_SEEDER_HPP

+ 0 - 8
devstone/adevs/src/utils.hpp

@@ -1,8 +0,0 @@
-#ifndef DEVSTONE_ADEVS_UTILS_HPP
-#define DEVSTONE_ADEVS_UTILS_HPP
-
-#include <adevs.h>
-
-typedef adevs::PortValue<int*> IO_Type;  // Define the type of the messages to be sent
-
-#endif //DEVSTONE_ADEVS_UTILS_HPP

+ 0 - 156
devstone/adevs/test/test_devstone.cpp

@@ -1,156 +0,0 @@
-#define BOOST_TEST_MODULE DEVStoneTests
-#include <boost/test/unit_test.hpp>
-#include <string>
-#include "../src/devstone.hpp"
-
-#define STEP 5
-#define MAX_WIDTH 50
-#define MAX_DEPTH 50
-
-int expectedAtomics(const std::string& type, int width, int depth) {
-    auto wFactor = width - 1;
-    if (type == "HOmod") {
-        wFactor += (width - 1) * width / 2;
-    }
-    return wFactor * (depth - 1) + 1;
-}
-
-int expectedEICs(const std::string& type, int width, int depth) {
-    auto wFactor = width;
-    if (type == "HO") {
-        wFactor = width + 1;
-    } else if (type == "HOmod") {
-        wFactor = 2 * (width - 1) + 1;
-    }
-    return wFactor * (depth - 1) + 1;
-}
-
-int expectedICs(const std::string& type, int width, int depth) {
-    auto wFactor = 0;
-    if (width > 2 && (type == "HI" || type == "HO")) {
-        wFactor = (width - 2);
-    } else if (type == "HOmod") {
-        wFactor = (width - 1) * (width - 1) + (width - 1) * width / 2;
-    }
-    return wFactor * (depth - 1);
-}
-
-int expectedEOCs(const std::string& type, int width, int depth) {
-    return (type == "HO")? width * (depth - 1) + 1 : depth;
-}
-
-int expectedInternals(const std::string& type, int width, int depth) {
-    if (type == "LI") {
-        return (width - 1) * (depth - 1) + 1;
-    } else if (type == "HI" || type == "HO") {
-        return (width - 1) * width / 2 * (depth - 1) + 1;
-    }
-    auto n = 1;
-    for (int d = 1; d < depth; ++d) {
-        n += (1 + (d - 1) * (width - 1)) * (width - 1) * width / 2 + (width - 1) * (width + (d - 1) * (width - 1));
-    }
-    return n;
-}
-
-int expectedExternals(const std::string& type, int width, int depth) {
-    return expectedInternals(type, width, depth);
-}
-
-int expectedEvents(const std::string& type, int width, int depth) {
-    if (type != "HOmod") {
-        return expectedInternals(type, width, depth);
-    }
-    auto n = 1;
-    if (width > 1 && depth > 1) {
-        n += 2 * (width - 1);
-        auto aux = 0;
-        for (int i = 2; i < depth; ++i) {
-            aux += 1 + (i - 1) * (width - 1);
-        }
-        n += aux * 2 * (width - 1) * (width - 1);
-        n += (aux + 1) * ((width - 1) * (width - 1) + (width - 2) * (width - 1) / 2);
-    }
-    return n;
-}
-
-adevs::Simulator<IO_Type> createEngine(DEVStone* devstone) {
-    return {devstone};
-}
-
-[[maybe_unused]] void runSimulation(adevs::Simulator<IO_Type>& sim) {
-    while (sim.nextEventTime() < DBL_MAX) {
-        sim.execNextEvent();
-    }
-}
-
-BOOST_AUTO_TEST_CASE(DEVStoneLI)
-{
-    for (int w = 1; w <= MAX_WIDTH; w += STEP) {
-        for (int d = 1; d <= MAX_DEPTH; d += STEP) {
-            auto coupled = new DEVStone("LI", w, d, 0, 0);
-            BOOST_CHECK_EQUAL(coupled->model->nAtomics(), expectedAtomics("LI", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEICs(), expectedEICs("LI", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nICs(), expectedICs("LI", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEOCs(), expectedEOCs("LI", w, d));
-            auto coordinator = createEngine(coupled);
-            runSimulation(coordinator);
-            BOOST_CHECK_EQUAL(coupled->model->nInternals(), expectedInternals("LI", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nExternals(), expectedExternals("LI", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEvents(), expectedEvents("LI", w, d));
-        }
-    }
-}
-
-BOOST_AUTO_TEST_CASE(DEVStoneHI)
-{
-    for (int w = 1; w <= MAX_WIDTH; w += STEP) {
-        for (int d = 1; d <= MAX_DEPTH; d += STEP) {
-            auto coupled = new DEVStone("HI", w, d, 0, 0);
-            BOOST_CHECK_EQUAL(coupled->model->nAtomics(), expectedAtomics("HI", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEICs(), expectedEICs("HI", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nICs(), expectedICs("HI", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEOCs(), expectedEOCs("HI", w, d));
-            auto coordinator = createEngine(coupled);
-            runSimulation(coordinator);
-            BOOST_CHECK_EQUAL(coupled->model->nInternals(), expectedInternals("HI", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nExternals(), expectedExternals("HI", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEvents(), expectedEvents("HI", w, d));
-        }
-    }
-}
-
-BOOST_AUTO_TEST_CASE(DEVStoneHO)
-{
-    for (int w = 1; w <= MAX_WIDTH; w += STEP) {
-        for (int d = 1; d <= MAX_DEPTH; d += STEP) {
-            auto coupled = new DEVStone("HO", w, d, 0, 0);
-            BOOST_CHECK_EQUAL(coupled->model->nAtomics(), expectedAtomics("HO", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEICs(), expectedEICs("HO", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nICs(), expectedICs("HO", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEOCs(), expectedEOCs("HO", w, d));
-            auto coordinator = createEngine(coupled);
-            runSimulation(coordinator);
-            BOOST_CHECK_EQUAL(coupled->model->nInternals(), expectedInternals("HO", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nExternals(), expectedExternals("HO", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEvents(), expectedEvents("HO", w, d));
-        }
-    }
-}
-
-BOOST_AUTO_TEST_CASE(DEVStoneHOmod)
-{
-    for (int w = 1; w <= MAX_WIDTH / 5; w += STEP / 5) {
-        for (int d = 1; d <= MAX_DEPTH / 5; d += STEP / 5) {
-            auto coupled = new DEVStone("HOmod", w, d, 0, 0);
-            BOOST_CHECK_EQUAL(coupled->model->nAtomics(), expectedAtomics("HOmod", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEICs(), expectedEICs("HOmod", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nICs(), expectedICs("HOmod", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEOCs(), expectedEOCs("HOmod", w, d));
-            auto coordinator = createEngine(coupled);
-            runSimulation(coordinator);
-            BOOST_CHECK_EQUAL(coupled->model->nInternals(), expectedInternals("HOmod", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nExternals(), expectedExternals("HOmod", w, d));
-            BOOST_CHECK_EQUAL(coupled->model->nEvents(), expectedEvents("HOmod", w, d));
-        }
-    }
-}

+ 0 - 21
devstone/cadmium/CMakeLists.txt

@@ -1,21 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-project(devstone-cadmium)
-
-set (CMAKE_CXX_STANDARD 17)
-set (CMAKE_CXX_COMPILER "g++")
-add_compile_options(-O3)
-
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../simulators/cadmium/include)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
-
-set(Boost_USE_STATIC_LIBS ON)
-
-find_package(Boost COMPONENTS program_options unit_test_framework REQUIRED)
-
-include_directories(${Boost_INCLUDE_DIRS})
-
-## Cadmium dynamic
-add_executable(cadmium-dynamic-devstone src/cadmium-dynamic-devstone.cpp
-        events_devstone.txt)
-target_link_libraries(cadmium-dynamic-devstone
-    ${Boost_PROGRAM_OPTIONS_LIBRARY} ${UTILOBJS})

+ 0 - 100
devstone/cadmium/events.txt

@@ -1,100 +0,0 @@
-1 1
-2 2
-3 3
-4 4
-5 5
-6 6
-7 7
-8 8
-9 9
-10 10
-11 11
-12 12
-13 13
-14 14
-15 15
-16 16
-17 17
-18 18
-19 19
-20 20
-21 21
-22 22
-23 23
-24 24
-25 25
-26 26
-27 27
-28 28
-29 29
-30 30
-31 31
-32 32
-33 33
-34 34
-35 35
-36 36
-37 37
-38 38
-39 39
-40 40
-41 41
-42 42
-43 43
-44 44
-45 45
-46 46
-47 47
-48 48
-49 49
-50 50
-51 51
-52 52
-53 53
-54 54
-55 55
-56 56
-57 57
-58 58
-59 59
-60 60
-61 61
-62 62
-63 63
-64 64
-65 65
-66 66
-67 67
-68 68
-69 69
-70 70
-71 71
-72 72
-73 73
-74 74
-75 75
-76 76
-77 77
-78 78
-79 79
-80 80
-81 81
-82 82
-83 83
-84 84
-85 85
-86 86
-87 87
-88 88
-89 89
-90 90
-91 91
-92 92
-93 93
-94 94
-95 95
-96 96
-97 97
-98 98
-99 99
-100 100

+ 0 - 1
devstone/cadmium/events_devstone.txt

@@ -1 +0,0 @@
-0 0

+ 0 - 118
devstone/cadmium/src/cadmium-devstone-atomic.hpp

@@ -1,118 +0,0 @@
-/**
- * Copyright (c) 2017, Damian Vicino
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CADMIUM_DEVSTONE_ATOMIC_HPP
-#define CADMIUM_DEVSTONE_ATOMIC_HPP
-
-#include<cadmium/modeling/ports.hpp>
-#include<cadmium/modeling/message_bag.hpp>
-#include<limits>
-
-#include "../../dhry/dhry_1.c"
-
-
-/**
- * @brief PDEVStone Atomic Model.
- *
- * PDEVStone (InternalTime, ExternalTime, Period):
- * This model executes:
- * - a Dhrystone for InternalCycles on each Internal transition,
- * - a Dhrystone for ExternalCycles on each External transition,
- * - the time advance after each external transition is Period.
-*/
-
-//  an integer input and output port for the model
-struct devstone_atomic_defs{
-    //custom ports
-    struct in : public cadmium::in_port<int> {};
-    struct out : public cadmium::out_port<int> {};
-};
-
-
-template<typename TIME>
-class devstone_atomic {
-    using defs=devstone_atomic_defs;
-public:
-    // default constructor
-    constexpr devstone_atomic() noexcept {
-        //preparing the output bag, since we return always same message
-        cadmium::get_messages<typename defs::out>(outbag).emplace_back(1);
-    }
-
-    constexpr devstone_atomic(int ext_cycles, int int_cycles, TIME time_advance) noexcept
-        : period(time_advance), external_cycles(ext_cycles), internal_cycles(int_cycles){
-        //preparing the output bag, since we return always same message
-        cadmium::get_messages<typename defs::out>(outbag).emplace_back(1);
-    }
-
-    // state definition
-    using queued_processes=int; //for readability
-    using state_type=queued_processes;
-    state_type state = 0;
-
-    // ports definition
-    using input_ports=std::tuple<typename defs::in>;
-    using output_ports=std::tuple<typename defs::out>;
-
-protected:
-    /*
-     * This model executes:
-     * - a Dhrystone for InternalCycles on each Internal transition,
-     * - a Dhrystone for ExternalCycles on each External transition,
-     * - the time advance after each external transition is Period.
-     * The following 3 variables need to be overriden by the inheriting model constructor.
-     */
-    TIME period=std::numeric_limits<float>::infinity();
-    int external_cycles=-1;
-    int internal_cycles=-1;
-    using outbag_t=typename cadmium::make_message_bags<output_ports>::type;
-    outbag_t outbag;
-
-public:
-    void internal_transition() {
-        DhryStone().dhrystoneRun(internal_cycles);
-        state--;
-    }
-
-    void external_transition(TIME e, typename cadmium::make_message_bags<input_ports>::type mbs) {
-        DhryStone().dhrystoneRun(external_cycles);
-        state+= cadmium::get_messages<typename defs::in>(mbs).size();
-    }
-
-    void confluence_transition(TIME e, typename cadmium::make_message_bags<input_ports>::type mbs) {
-        internal_transition();
-        external_transition(e, mbs);
-    }
-
-    outbag_t output() const {
-        return outbag;
-    }
-
-    TIME time_advance() const {
-        return (state!=0?period:std::numeric_limits<TIME>::infinity());
-    }
-};
-
-#endif // CADMIUM_DEVSTONE_ATOMIC_HPP

+ 0 - 128
devstone/cadmium/src/cadmium-dynamic-devstone.cpp

@@ -1,128 +0,0 @@
-/**
- * Copyright (c) 2019, Juan Lanuza
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <iostream>
-#include <chrono>
-#include <algorithm>
-#include <fstream>
-
-#include <boost/program_options.hpp>
-
-#include <cadmium/engine/pdevs_dynamic_runner.hpp>
-
-#include "dynamic/LI_generator.cpp"
-#include "dynamic/HI_generator.cpp"
-#include "dynamic/HO_generator.cpp"
-#include "dynamic/HOmod_generator.cpp"
-
-namespace po=boost::program_options;
-using hclock=std::chrono::high_resolution_clock;
-using Time=float;
-
-int main(int argc, char* argv[]){
-
-    // Declare the supported options.
-    po::options_description desc("Allowed options");
-    desc.add_options()
-            ("help", "produce help message")
-            ("kind", po::value<std::string>()->required(), "set kind of devstone: LI, HI, HO or HOmod")
-            ("width", po::value<int>()->required(), "set width of the DEVStone: integer value")
-            ("depth", po::value<int>()->required(), "set depth of the DEVStone: integer value")
-            ("int-cycles", po::value<int>()->required(), "set the Dhrystone cycles to expend in internal transtions: integer value")
-            ("ext-cycles", po::value<int>()->required(), "set the Dhrystone cycles to expend in external transtions: integer value")
-            ("time-advance", po::value<int>()->default_value(0), "set the time expend in external transtions by the Dhrystone in miliseconds: integer value")
-            #ifdef CADMIUM_EXECUTE_CONCURRENT
-            ("threads", po::value<int>()->required(), "amount of threads to use")
-            #endif //CADMIUM_EXECUTE_CONCURRENT
-            ;
-
-    po::variables_map vm;
-    try {
-        po::store(po::parse_command_line(argc, argv, desc), vm);
-        po::notify(vm);
-    } catch ( boost::program_options::required_option be ){
-        if (vm.count("help")) {
-            std::cout << desc << "\n";
-            return 0;
-        } else {
-            std::cout << be.what() << std::endl;
-            std::cout << std::endl;
-            std::cout << "for mode information run: " << argv[0] << " --help" << std::endl;
-            return 1;
-        }
-    }
-    std::string kind = vm["kind"].as<std::string>();
-    if (kind.compare("LI") != 0  && kind.compare("HI") != 0 &&
-        kind.compare("HO") != 0 && kind.compare("HOmod") != 0) {
-        std::cout << "The kind needs to be LI, HI, HO or HOmod and received value was: " << kind << std::endl;
-        std::cout << "for mode information run: " << argv[0] << " --help" << std::endl;
-        return 1;
-    }
-
-    int width = vm["width"].as<int>();
-    int depth = vm["depth"].as<int>();
-    int int_cycles = vm["int-cycles"].as<int>();
-    int ext_cycles = vm["ext-cycles"].as<int>();
-    int time_advance = vm["time-advance"].as<int>();
-    #ifdef CADMIUM_EXECUTE_CONCURRENT
-    int threads = vm["threads"].as<int>();
-    #endif //CADMIUM_EXECUTE_CONCURRENT
-    //finished processing input
-
-    auto processed_parameters = hclock::now();
-
-    std::shared_ptr<cadmium::dynamic::modeling::coupled<Time>> TOP_coupled;
-    if (kind.compare("LI") == 0){
-        TOP_coupled = create_LI_model(width,depth, ext_cycles, int_cycles, time_advance);
-    } else if (kind.compare("HI") == 0) {
-        TOP_coupled = create_HI_model(width, depth, ext_cycles, int_cycles, time_advance);
-    } else if (kind.compare("HO") == 0) {
-        TOP_coupled = create_HO_model(width,depth, ext_cycles, int_cycles, time_advance);
-    } else if (kind.compare("HOmod") == 0) {
-        TOP_coupled = create_HOmod_model(width,depth, ext_cycles, int_cycles, time_advance);
-    } else {
-        abort();
-    }
-
-    auto model_init = hclock::now();
-
-    std::cout << "Model creation time: " << std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>( model_init - processed_parameters).count() << " seconds" << std::endl;
-
-    #ifdef CADMIUM_EXECUTE_CONCURRENT
-        cadmium::dynamic::engine::runner<Time, cadmium::logger::not_logger> r(TOP_coupled, 0.0, threads);
-    #else
-        cadmium::dynamic::engine::runner<TIME, cadmium::logger::not_logger> r(TOP_coupled, 0.0);
-    #endif //CADMIUM_EXECUTE_CONCURRENT
-
-    auto runner_init = hclock::now();
-
-    std::cout << "Engine setup time: " << std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(runner_init - model_init).count() << " seconds" << std::endl;
-
-    r.run_until(1000000);
-
-    auto finished_simulation = hclock::now();
-
-    std::cout << "Simulation time: " << std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(finished_simulation - runner_init).count() << " seconds" << std::endl;
-}

+ 0 - 145
devstone/cadmium/src/cadmium-event-reader.hpp

@@ -1,145 +0,0 @@
-/**
- * Copyright (c) 2017, Damian Vicino
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-#ifndef CADMIUM_EVENT_READER_HPP
-#define CADMIUM_EVENT_READER_HPP
-
-#include<cadmium/modeling/ports.hpp>
-#include<cadmium/modeling/message_bag.hpp>
-#include<limits>
-#include<fstream>
-#include <cassert>
-
-/**
- * Events are read from "events.txt", first column is absolute time the event has to be sent,
- * the second column tells the integer to sent in the "out" port
- */
-
-//  an integer output port for the model
-struct devstone_event_reader_defs{
-    //custom ports
-    struct in : public cadmium::in_port<int> {};
-    struct out : public cadmium::out_port<int> {};
-};
-
-
-template<typename TIME>
-class devstone_event_reader {
-public:
-    using defs=devstone_event_reader_defs;
-
-    // state definition is ignored, the state is hold out of the system
-    using state_type=int;
-    state_type state = 0;
-    
-    // ports definition
-    using input_ports=std::tuple<>;
-    using output_ports=std::tuple<typename defs::out>;
-    using outbag_t=typename cadmium::make_message_bags<output_ports>::type;
-    outbag_t outbag;
-
-    std::ifstream is; //the stream
-    TIME last;
-    TIME next;
-    float prefetched_time;
-    
-    // default constructor opens the stream and sets initial time
-    constexpr devstone_event_reader() {
-        last = 0;
-        is.open("events_devstone.txt");
-        if (!is.good()) throw std::runtime_error("failed to open events file");
-        is >> prefetched_time;
-        if (is.eof()){
-             next = std::numeric_limits<float>::infinity();
-        } else {
-            next = prefetched_time;
-            fetchUntilTimeAdvances();
-        }
-    }
-    
-    void internal_transition() {
-        last = next;
-        next = prefetched_time;
-        cadmium::get_messages<typename defs::out>(outbag).clear();
-        if(next < std::numeric_limits<float>::infinity()) {
-            fetchUntilTimeAdvances();
-        }
-    }
-    
-    void external_transition(TIME e, typename cadmium::make_message_bags<input_ports>::type mbs) {
-        assert(false && "Non external input is expected in this model");
-    }
-    
-    void confluence_transition(TIME e, typename cadmium::make_message_bags<input_ports>::type mbs) {
-        assert(false && "Non external input is expected in this model");
-    }
-    
-    outbag_t output() const {
-        return outbag;
-    }
-    
-    TIME time_advance() const {
-        return (next < std::numeric_limits<float>::infinity()?next-last:next);
-    }
-    
-    
-private:
-    //helper function
-    void fetchUntilTimeAdvances() {
-        //making use of the prefetched values
-        //cadmium::get_messages<typename defs::out>(outbag) = {prefetched_time};
-        TIME t;
-        int m;
-        //fetching next messages
-        t = prefetched_time;
-        /*if (is.eof()){
-            prefetched_time = std::numeric_limits<float>::infinity();
-            return;
-        }*/
-        while (!is.eof() && t == next){
-            is >> m;
-            cadmium::get_messages<typename defs::out>(outbag).push_back(m);
-            is >> t;
-        }
-        if (is.eof()){
-            prefetched_time = std::numeric_limits<float>::infinity();
-            return;
-        } else {
-            if (next < t) {
-                prefetched_time = t;
-                //cache the last message fetched
-                //is >> prefetched_message;
-            } else {
-                throw std::runtime_error("next is before than now");
-            }
-        }
-    }
-
-};
-
-
-
-#endif // CADMIUM_EVENT_READER_HPP

+ 0 - 159
devstone/cadmium/src/dynamic/HI_generator.cpp

@@ -1,159 +0,0 @@
-/**
- * Copyright (c) 2019, Juan Lanuza
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <chrono>
-#include <boost/format.hpp>
-
-#include "../cadmium-devstone-atomic.hpp"
-#include "../cadmium-event-reader.hpp"
-
-//#include <cadmium/modeling/coupled_model.hpp>
-#include <cadmium/modeling/ports.hpp>
-#include <cadmium/modeling/dynamic_model_translator.hpp>
-#include <cadmium/concept/coupled_model_assert.hpp>
-#include <cadmium/modeling/dynamic_coupled.hpp>
-#include <cadmium/modeling/dynamic_atomic.hpp>
-#include <cadmium/engine/pdevs_dynamic_runner.hpp>
-#include <cadmium/logger/tuple_to_ostream.hpp>
-#include <cadmium/logger/common_loggers.hpp>
-
-using TIME = float;
-
-// Ports for coupled models, we use the same in every level
-struct coupledHI_in_port : public cadmium::in_port<int>{};
-struct coupledHI_out_port : public cadmium::out_port<int>{};
-
-std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> create_HI_model(
-        uint width, uint depth, int ext_cycles, int int_cycles, TIME time_advance) {
-    // Creates the HI model with the passed parameters
-    // Returns a shared_ptr to the TOP model
-
-    auto make_atomic_devstone = [&ext_cycles, &int_cycles, &time_advance](std::string model_id) -> std::shared_ptr<cadmium::dynamic::modeling::model> {
-        return cadmium::dynamic::translate::make_dynamic_atomic_model<devstone_atomic, TIME>(model_id, ext_cycles, int_cycles, time_advance);
-    };
-    //Level 0 has always a single model
-    std::shared_ptr<cadmium::dynamic::modeling::model> devstone_atomic_L0_0 = make_atomic_devstone("devstone_atomic_L0_0");
-
-    std::unordered_map<int, cadmium::dynamic::modeling::Models> atomics_by_level;
-    std::unordered_map<int, std::shared_ptr<cadmium::dynamic::modeling::model>> coupleds_by_level;
-
-    cadmium::dynamic::modeling::Ports coupled_in_ports = {typeid(coupledHI_in_port)};
-    cadmium::dynamic::modeling::Ports coupled_out_ports = {typeid(coupledHI_out_port)};
-
-    for (int level=1; level <= depth; level++) {
-
-        //atomics
-        std::vector<std::shared_ptr<cadmium::dynamic::modeling::model>> atomics_current_level;
-        if (level < depth) {
-            //Last level does not have atomics
-            for(int idx_atomic=0; idx_atomic < width-1; idx_atomic++) {
-                std::string atomic_name = "devstone_atomic_L" + std::to_string(level) + "_" + std::to_string(idx_atomic);
-                atomics_current_level.push_back(make_atomic_devstone(atomic_name));
-            }
-        }
-        atomics_by_level[level] = atomics_current_level;
-
-        //coupled
-        cadmium::dynamic::modeling::Models Lcoupled_submodels;
-        cadmium::dynamic::modeling::EICs Lcoupled_eics;
-        cadmium::dynamic::modeling::EOCs Lcoupled_eocs;
-        cadmium::dynamic::modeling::ICs Lcoupled_ics = {};
-
-        if (level == 1) {
-            Lcoupled_submodels= {devstone_atomic_L0_0};
-            Lcoupled_eics = {
-                cadmium::dynamic::translate::make_EIC<coupledHI_in_port, devstone_atomic_defs::in>("devstone_atomic_L0_0")
-            };
-            Lcoupled_eocs = {
-              cadmium::dynamic::translate::make_EOC<devstone_atomic_defs::out,coupledHI_out_port>("devstone_atomic_L0_0")
-            };
-        } else {
-            std::shared_ptr<cadmium::dynamic::modeling::model> coupled_prev_level = coupleds_by_level[level - 1];
-
-            Lcoupled_submodels = { coupled_prev_level };
-
-            Lcoupled_eics = {
-                cadmium::dynamic::translate::make_EIC<coupledHI_in_port, coupledHI_in_port>(
-                    coupled_prev_level.get()->get_id()
-                )
-            };
-
-            Lcoupled_eocs = {
-                cadmium::dynamic::translate::make_EOC<coupledHI_out_port, coupledHI_out_port>(
-                    coupled_prev_level.get()->get_id()
-                )
-            };
-            for (int i=0; i < atomics_by_level[level - 1].size(); i++) {
-                auto atomic = atomics_by_level[level - 1][i];
-                Lcoupled_submodels.push_back(atomic);
-                Lcoupled_eics.push_back(
-                    cadmium::dynamic::translate::make_EIC<coupledHI_in_port, devstone_atomic_defs::in>(atomic.get()->get_id())
-                );
-                if(i < atomics_by_level[level - 1].size()- 1 ) { // skip last iteration
-                    auto next_atomic = atomics_by_level[level - 1][i+1];
-                    Lcoupled_ics.push_back(
-                        cadmium::dynamic::translate::make_IC<devstone_atomic_defs::out, devstone_atomic_defs::in>(atomic.get()->get_id(), next_atomic.get()->get_id())
-                    );
-                }
-            }
-        }
-        std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> L_coupled = std::make_shared<cadmium::dynamic::modeling::coupled<TIME>>(
-             "L" + std::to_string(level) + "_coupled",
-             Lcoupled_submodels,
-             coupled_in_ports,
-             coupled_out_ports,
-             Lcoupled_eics,
-             Lcoupled_eocs,
-             Lcoupled_ics
-        );
-        coupleds_by_level[level] = L_coupled;
-    }
-
-    //Create instance of devstone_event_reader
-    std::shared_ptr<cadmium::dynamic::modeling::model> devstone_event_reader1 = cadmium::dynamic::translate::make_dynamic_atomic_model<devstone_event_reader, TIME>("devstone_event_reader1");
-
-    std::shared_ptr<cadmium::dynamic::modeling::model> last_level_coupled = coupleds_by_level[depth];
-
-    //TOP model conecting a generator of events to the input
-    cadmium::dynamic::modeling::Ports TOP_coupled_in_ports = {};
-    cadmium::dynamic::modeling::Ports TOP_coupled_out_ports = {};
-    cadmium::dynamic::modeling::Models TOP_submodels = {devstone_event_reader1, last_level_coupled};
-    cadmium::dynamic::modeling::EICs TOP_eics = {};
-    cadmium::dynamic::modeling::EOCs TOP_eocs = {};
-    cadmium::dynamic::modeling::ICs TOP_ics = {
-        cadmium::dynamic::translate::make_IC<devstone_event_reader_defs::out,coupledHI_in_port>("devstone_event_reader1",last_level_coupled.get()->get_id())
-    };
-    std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> TOP_coupled = std::make_shared<cadmium::dynamic::modeling::coupled<TIME>>(
-     "TOP_coupled",
-     TOP_submodels,
-     TOP_coupled_in_ports,
-     TOP_coupled_out_ports,
-     TOP_eics,
-     TOP_eocs,
-     TOP_ics
-    );
-
-    return TOP_coupled;
-}

+ 0 - 168
devstone/cadmium/src/dynamic/HO_generator.cpp

@@ -1,168 +0,0 @@
-/**
- * Copyright (c) 2019, Juan Lanuza
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <chrono>
-#include <boost/format.hpp>
-
-#include "../cadmium-devstone-atomic.hpp"
-#include "../cadmium-event-reader.hpp"
-
-//#include <cadmium/modeling/coupled_model.hpp>
-#include <cadmium/modeling/ports.hpp>
-#include <cadmium/modeling/dynamic_model_translator.hpp>
-#include <cadmium/concept/coupled_model_assert.hpp>
-#include <cadmium/modeling/dynamic_coupled.hpp>
-#include <cadmium/modeling/dynamic_atomic.hpp>
-#include <cadmium/engine/pdevs_dynamic_runner.hpp>
-#include <cadmium/logger/tuple_to_ostream.hpp>
-#include <cadmium/logger/common_loggers.hpp>
-
-using TIME = float;
-
-// Ports for coupled models, we use the same in every level
-struct coupledHO_in_port1 : public cadmium::in_port<int>{};
-struct coupledHO_in_port2 : public cadmium::in_port<int>{};
-struct coupledHO_out_port1 : public cadmium::out_port<int>{};
-struct coupledHO_out_port2 : public cadmium::out_port<int>{};
-
-std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> create_HO_model(
-        uint width, uint depth, int ext_cycles, int int_cycles, TIME time_advance) {
-    // Creates the HO model with the passed parameters
-    // Returns a shared_ptr to the TOP model
-
-    auto make_atomic_devstone = [&ext_cycles, &int_cycles, &time_advance](std::string model_id) -> std::shared_ptr<cadmium::dynamic::modeling::model> {
-        return cadmium::dynamic::translate::make_dynamic_atomic_model<devstone_atomic, TIME>(model_id, ext_cycles, int_cycles, time_advance);
-    };
-    //Level 0 has always a single model
-    std::shared_ptr<cadmium::dynamic::modeling::model> devstone_atomic_L0_0 = make_atomic_devstone("devstone_atomic_L0_0");
-
-    std::unordered_map<int, cadmium::dynamic::modeling::Models> atomics_by_level;
-    std::unordered_map<int, std::shared_ptr<cadmium::dynamic::modeling::model>> coupleds_by_level;
-
-    cadmium::dynamic::modeling::Ports coupled_in_ports = {typeid(coupledHO_in_port1), typeid(coupledHO_in_port2)};
-    cadmium::dynamic::modeling::Ports coupled_out_ports = {typeid(coupledHO_out_port1), typeid(coupledHO_out_port2)};
-
-    for (int level=1; level <= depth; level++) {
-
-        //atomics
-        std::vector<std::shared_ptr<cadmium::dynamic::modeling::model>> atomics_current_level;
-        if (level < depth) {
-            //Last level does not have atomics
-            for(int idx_atomic=0; idx_atomic < width-1; idx_atomic++) {
-                std::string atomic_name = "devstone_atomic_L" + std::to_string(level) + "_" + std::to_string(idx_atomic);
-                atomics_current_level.push_back(make_atomic_devstone(atomic_name));
-            }
-        }
-        atomics_by_level[level] = atomics_current_level;
-
-        //coupled
-        cadmium::dynamic::modeling::Models Lcoupled_submodels;
-        cadmium::dynamic::modeling::EICs Lcoupled_eics;
-        cadmium::dynamic::modeling::EOCs Lcoupled_eocs;
-        cadmium::dynamic::modeling::ICs Lcoupled_ics = {};
-
-        if (level == 1) {
-            Lcoupled_submodels= {devstone_atomic_L0_0};
-            Lcoupled_eics = {
-                cadmium::dynamic::translate::make_EIC<coupledHO_in_port1, devstone_atomic_defs::in>("devstone_atomic_L0_0")
-            };
-            Lcoupled_eocs = {
-              cadmium::dynamic::translate::make_EOC<devstone_atomic_defs::out,coupledHO_out_port1>("devstone_atomic_L0_0")
-            };
-        } else {
-            std::shared_ptr<cadmium::dynamic::modeling::model> coupled_prev_level = coupleds_by_level[level - 1];
-
-            Lcoupled_submodels = { coupled_prev_level };
-
-            Lcoupled_eics = {
-                cadmium::dynamic::translate::make_EIC<coupledHO_in_port1, coupledHO_in_port1>(
-                    coupled_prev_level.get()->get_id()
-                ),
-                cadmium::dynamic::translate::make_EIC<coupledHO_in_port1, coupledHO_in_port2>(
-                    coupled_prev_level.get()->get_id()
-                )
-            };
-
-            Lcoupled_eocs = {
-                cadmium::dynamic::translate::make_EOC<coupledHO_out_port1, coupledHO_out_port1>(
-                    coupled_prev_level.get()->get_id()
-                )
-            };
-            for (int i=0; i < atomics_by_level[level - 1].size(); i++) {
-                auto atomic = atomics_by_level[level - 1][i];
-                Lcoupled_submodels.push_back(atomic);
-                Lcoupled_eics.push_back(
-                    cadmium::dynamic::translate::make_EIC<coupledHO_in_port2, devstone_atomic_defs::in>(atomic.get()->get_id())
-                );
-                Lcoupled_eocs.push_back(
-                    cadmium::dynamic::translate::make_EOC<devstone_atomic_defs::out, coupledHO_out_port2>(atomic.get()->get_id())
-                );
-                if(i < atomics_by_level[level - 1].size()- 1 ) { // skip last iteration
-                    auto next_atomic = atomics_by_level[level - 1][i+1];
-                    Lcoupled_ics.push_back(
-                        cadmium::dynamic::translate::make_IC<devstone_atomic_defs::out, devstone_atomic_defs::in>(atomic.get()->get_id(), next_atomic.get()->get_id())
-                    );
-                }
-            }
-        }
-        std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> L_coupled = std::make_shared<cadmium::dynamic::modeling::coupled<TIME>>(
-             "L" + std::to_string(level) + "_coupled",
-             Lcoupled_submodels,
-             coupled_in_ports,
-             coupled_out_ports,
-             Lcoupled_eics,
-             Lcoupled_eocs,
-             Lcoupled_ics
-        );
-        coupleds_by_level[level] = L_coupled;
-    }
-
-    //Create instance of devstone_event_reader
-    std::shared_ptr<cadmium::dynamic::modeling::model> devstone_event_reader1 = cadmium::dynamic::translate::make_dynamic_atomic_model<devstone_event_reader, TIME>("devstone_event_reader1");
-
-    std::shared_ptr<cadmium::dynamic::modeling::model> last_level_coupled = coupleds_by_level[depth];
-
-    //TOP model conecting a generator of events to the input
-    cadmium::dynamic::modeling::Ports TOP_coupled_in_ports = {};
-    cadmium::dynamic::modeling::Ports TOP_coupled_out_ports = {};
-    cadmium::dynamic::modeling::Models TOP_submodels = {devstone_event_reader1, last_level_coupled};
-    cadmium::dynamic::modeling::EICs TOP_eics = {};
-    cadmium::dynamic::modeling::EOCs TOP_eocs = {};
-    cadmium::dynamic::modeling::ICs TOP_ics = {
-        cadmium::dynamic::translate::make_IC<devstone_event_reader_defs::out,coupledHO_in_port1>("devstone_event_reader1",last_level_coupled.get()->get_id()),
-        cadmium::dynamic::translate::make_IC<devstone_event_reader_defs::out,coupledHO_in_port2>("devstone_event_reader1",last_level_coupled.get()->get_id())
-    };
-    std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> TOP_coupled = std::make_shared<cadmium::dynamic::modeling::coupled<TIME>>(
-     "TOP_coupled",
-     TOP_submodels,
-     TOP_coupled_in_ports,
-     TOP_coupled_out_ports,
-     TOP_eics,
-     TOP_eocs,
-     TOP_ics
-    );
-
-    return TOP_coupled;
-}

+ 0 - 179
devstone/cadmium/src/dynamic/HOmod_generator.cpp

@@ -1,179 +0,0 @@
-/**
- * Copyright (c) 2019, Juan Lanuza
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <chrono>
-#include <boost/format.hpp>
-
-#include "../cadmium-devstone-atomic.hpp"
-#include "../cadmium-event-reader.hpp"
-
-//#include <cadmium/modeling/coupled_model.hpp>
-#include <cadmium/modeling/ports.hpp>
-#include <cadmium/modeling/dynamic_model_translator.hpp>
-#include <cadmium/concept/coupled_model_assert.hpp>
-#include <cadmium/modeling/dynamic_coupled.hpp>
-#include <cadmium/modeling/dynamic_atomic.hpp>
-#include <cadmium/engine/pdevs_dynamic_runner.hpp>
-#include <cadmium/logger/tuple_to_ostream.hpp>
-#include <cadmium/logger/common_loggers.hpp>
-
-using TIME = float;
-
-// Ports for coupled models, we use the same in every level
-struct coupledHOmod_in_port1 : public cadmium::in_port<int>{};
-struct coupledHOmod_in_port2 : public cadmium::in_port<int>{};
-struct coupledHOmod_out_port : public cadmium::out_port<int>{};
-
-using ModelMatrix = std::vector<std::vector<std::shared_ptr<cadmium::dynamic::modeling::model>>>;
-
-std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> create_HOmod_model(
-        uint width, uint depth, int ext_cycles, int int_cycles, TIME time_advance) {
-    // Creates the HOmod model with the passed parameters
-    // Returns a shared_ptr to the TOP model
-
-    auto make_atomic_devstone = [&ext_cycles, &int_cycles, &time_advance](std::string model_id) -> std::shared_ptr<cadmium::dynamic::modeling::model> {
-        return cadmium::dynamic::translate::make_dynamic_atomic_model<devstone_atomic, TIME>(model_id, ext_cycles, int_cycles, time_advance);
-    };
-    //Level 0 has always a single model
-    std::shared_ptr<cadmium::dynamic::modeling::model> devstone_atomic_L0_0 = make_atomic_devstone("devstone_atomic_L0_0");
-    std::unordered_map<int, ModelMatrix> atomics_by_level;
-    std::unordered_map<int, std::shared_ptr<cadmium::dynamic::modeling::model>> coupleds_by_level;
-
-    cadmium::dynamic::modeling::Ports coupled_in_ports = {typeid(coupledHOmod_in_port1), typeid(coupledHOmod_in_port2)};
-    cadmium::dynamic::modeling::Ports coupled_out_ports = {typeid(coupledHOmod_out_port)};
-
-    for (int level=1; level <= depth; level++) {
-
-        //atomics
-        ModelMatrix atomics_current_level;
-        if (level < depth) {
-            //Last level does not have atomics
-            for(int idx_column=0; idx_column < width-1; idx_column++) {
-                cadmium::dynamic::modeling::Models models_col;
-                for(int idx_row=0; idx_row < idx_column + 2; idx_row++) {
-                    std::string atomic_name = "devstone_atomic_L" + std::to_string(level) + "_" + std::to_string(idx_column) + ";" + std::to_string(idx_row);
-                    models_col.push_back(make_atomic_devstone(atomic_name));
-                }
-                atomics_current_level.push_back(models_col);
-            }
-        }
-        atomics_by_level[level] = atomics_current_level;
-
-        //coupled
-        cadmium::dynamic::modeling::Models Lcoupled_submodels;
-        cadmium::dynamic::modeling::EICs Lcoupled_eics;
-        cadmium::dynamic::modeling::EOCs Lcoupled_eocs;
-        cadmium::dynamic::modeling::ICs Lcoupled_ics = {};
-
-        if (level == 1) {
-            Lcoupled_submodels= {devstone_atomic_L0_0};
-            Lcoupled_eics = {
-                cadmium::dynamic::translate::make_EIC<coupledHOmod_in_port1, devstone_atomic_defs::in>("devstone_atomic_L0_0")
-            };
-            Lcoupled_eocs = {
-              cadmium::dynamic::translate::make_EOC<devstone_atomic_defs::out,coupledHOmod_out_port>("devstone_atomic_L0_0")
-            };
-        } else {
-            std::shared_ptr<cadmium::dynamic::modeling::model> coupled_prev_level = coupleds_by_level[level - 1];
-
-            Lcoupled_submodels = { coupled_prev_level };
-
-            Lcoupled_eics = {
-                cadmium::dynamic::translate::make_EIC<coupledHOmod_in_port1, coupledHOmod_in_port1>(
-                    coupled_prev_level.get()->get_id()
-                )
-            };
-
-            Lcoupled_eocs = {
-                cadmium::dynamic::translate::make_EOC<coupledHOmod_out_port, coupledHOmod_out_port>(
-                    coupled_prev_level.get()->get_id()
-                )
-            };
-
-            ModelMatrix atomics_prev_level = atomics_by_level[level-1];
-            for(int idx_column=0; idx_column < width-1; idx_column++) {
-                cadmium::dynamic::modeling::Models models_col;
-                for(int idx_row=0; idx_row < idx_column + 2; idx_row++) {
-                    auto atomic = atomics_prev_level[idx_column][idx_row];
-                    Lcoupled_submodels.push_back(atomic);
-
-                    if(idx_row == 0 || idx_row == idx_column + 1) { //only first and last row
-                        Lcoupled_eics.push_back(
-                                cadmium::dynamic::translate::make_EIC<coupledHOmod_in_port2, devstone_atomic_defs::in>(atomic.get()->get_id())
-                        );
-                    }
-
-                    if(idx_row == 0) {
-                        Lcoupled_ics.push_back(
-                                cadmium::dynamic::translate::make_IC<devstone_atomic_defs::out, coupledHOmod_in_port2>(atomic.get()->get_id(), coupled_prev_level->get_id())
-                        );
-                    } else {
-                        auto prev_atomic = atomics_prev_level[idx_column][idx_row-1];
-                        Lcoupled_ics.push_back(
-                                cadmium::dynamic::translate::make_IC<devstone_atomic_defs::out, devstone_atomic_defs::in>(atomic.get()->get_id(), prev_atomic.get()->get_id())
-                        );
-                    }
-                }
-            }
-        }
-        std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> L_coupled = std::make_shared<cadmium::dynamic::modeling::coupled<TIME>>(
-             "L" + std::to_string(level) + "_coupled",
-             Lcoupled_submodels,
-             coupled_in_ports,
-             coupled_out_ports,
-             Lcoupled_eics,
-             Lcoupled_eocs,
-             Lcoupled_ics
-        );
-        coupleds_by_level[level] = L_coupled;
-    }
-
-    //Create instance of devstone_event_reader
-    std::shared_ptr<cadmium::dynamic::modeling::model> devstone_event_reader1 = cadmium::dynamic::translate::make_dynamic_atomic_model<devstone_event_reader, TIME>("devstone_event_reader1");
-
-    std::shared_ptr<cadmium::dynamic::modeling::model> last_level_coupled = coupleds_by_level[depth];
-
-    //TOP model conecting a generator of events to the input
-    cadmium::dynamic::modeling::Ports TOP_coupled_in_ports = {};
-    cadmium::dynamic::modeling::Ports TOP_coupled_out_ports = {};
-    cadmium::dynamic::modeling::Models TOP_submodels = {devstone_event_reader1, last_level_coupled};
-    cadmium::dynamic::modeling::EICs TOP_eics = {};
-    cadmium::dynamic::modeling::EOCs TOP_eocs = {};
-    cadmium::dynamic::modeling::ICs TOP_ics = {
-        cadmium::dynamic::translate::make_IC<devstone_event_reader_defs::out,coupledHOmod_in_port1>("devstone_event_reader1",last_level_coupled.get()->get_id()),
-        cadmium::dynamic::translate::make_IC<devstone_event_reader_defs::out,coupledHOmod_in_port2>("devstone_event_reader1",last_level_coupled.get()->get_id())
-    };
-    std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> TOP_coupled = std::make_shared<cadmium::dynamic::modeling::coupled<TIME>>(
-     "TOP_coupled",
-     TOP_submodels,
-     TOP_coupled_in_ports,
-     TOP_coupled_out_ports,
-     TOP_eics,
-     TOP_eocs,
-     TOP_ics
-    );
-
-    return TOP_coupled;
-}

+ 0 - 151
devstone/cadmium/src/dynamic/LI_generator.cpp

@@ -1,151 +0,0 @@
-/**
- * Copyright (c) 2019, Juan Lanuza
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <chrono>
-#include <unordered_map>
-#include <boost/format.hpp>
-
-#include "../cadmium-devstone-atomic.hpp"
-#include "../cadmium-event-reader.hpp"
-
-//#include <cadmium/modeling/coupled_model.hpp>
-#include <cadmium/modeling/ports.hpp>
-#include <cadmium/modeling/dynamic_model_translator.hpp>
-#include <cadmium/concept/coupled_model_assert.hpp>
-#include <cadmium/modeling/dynamic_coupled.hpp>
-#include <cadmium/modeling/dynamic_atomic.hpp>
-#include <cadmium/engine/pdevs_dynamic_runner.hpp>
-#include <cadmium/logger/tuple_to_ostream.hpp>
-#include <cadmium/logger/common_loggers.hpp>
-
-using TIME = float;
-
-// Ports for coupled models, we use the same in every level
-struct coupledLI_in_port : public cadmium::in_port<int>{};
-struct coupledLI_out_port : public cadmium::out_port<int>{};
-
-std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> create_LI_model(
-        uint width, uint depth, int ext_cycles, int int_cycles, TIME time_advance) {
-    // Creates the LI model with the passed parameters
-    // Returns a shared_ptr to the TOP model
-    auto make_atomic_devstone = [&ext_cycles, &int_cycles, &time_advance](std::string model_id) -> std::shared_ptr<cadmium::dynamic::modeling::model> {
-        return cadmium::dynamic::translate::make_dynamic_atomic_model<devstone_atomic, TIME>(model_id, ext_cycles, int_cycles, time_advance);
-    };
-    //Level 0 has always a single model
-    std::shared_ptr<cadmium::dynamic::modeling::model> devstone_atomic_L0_0 = make_atomic_devstone("devstone_atomic_L0_0");
-
-    std::unordered_map<int, cadmium::dynamic::modeling::Models> atomics_by_level;
-    std::unordered_map<int, std::shared_ptr<cadmium::dynamic::modeling::model>> coupleds_by_level;
-
-    cadmium::dynamic::modeling::Ports coupled_in_ports = {typeid(coupledLI_in_port)};
-    cadmium::dynamic::modeling::Ports coupled_out_ports = {typeid(coupledLI_out_port)};
-    cadmium::dynamic::modeling::ICs ics = {}; //LI models have no Internal coupling
-
-    for (int level=1; level <= depth; level++) {
-
-        //atomics
-        std::vector<std::shared_ptr<cadmium::dynamic::modeling::model>> atomics_current_level;
-        if (level < depth) {
-            //Last level does not have atomics
-            for(int idx_atomic=0; idx_atomic < width-1; idx_atomic++) {
-                std::string atomic_name = "devstone_atomic_L" + std::to_string(level) + "_" + std::to_string(idx_atomic);
-                atomics_current_level.push_back(make_atomic_devstone(atomic_name));
-            }
-        }
-        atomics_by_level[level] = atomics_current_level;
-
-        //coupled
-        cadmium::dynamic::modeling::Models Lcoupled_submodels;
-        cadmium::dynamic::modeling::EICs Lcoupled_eics;
-        cadmium::dynamic::modeling::EOCs Lcoupled_eocs;
-        if (level == 1) {
-            Lcoupled_submodels= {devstone_atomic_L0_0};
-            Lcoupled_eics = {
-                cadmium::dynamic::translate::make_EIC<coupledLI_in_port, devstone_atomic_defs::in>("devstone_atomic_L0_0")
-            };
-            Lcoupled_eocs = {
-              cadmium::dynamic::translate::make_EOC<devstone_atomic_defs::out,coupledLI_out_port>("devstone_atomic_L0_0")
-            };
-        } else {
-            std::shared_ptr<cadmium::dynamic::modeling::model> coupled_prev_level = coupleds_by_level[level - 1];
-
-            Lcoupled_submodels = { coupled_prev_level };
-
-            Lcoupled_eics = {
-                cadmium::dynamic::translate::make_EIC<coupledLI_in_port, coupledLI_in_port>(
-                    coupled_prev_level.get()->get_id()
-                )
-            };
-
-            Lcoupled_eocs = {
-                cadmium::dynamic::translate::make_EOC<coupledLI_out_port, coupledLI_out_port>(
-                    coupled_prev_level.get()->get_id()
-                )
-            };
-            for (auto atomic : atomics_by_level[level - 1]) {
-                Lcoupled_submodels.push_back(atomic);
-                Lcoupled_eics.push_back(
-                    cadmium::dynamic::translate::make_EIC<coupledLI_in_port, devstone_atomic_defs::in>(atomic.get()->get_id())
-                );
-            }
-        }
-        std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> L_coupled = std::make_shared<cadmium::dynamic::modeling::coupled<TIME>>(
-             "L" + std::to_string(level) + "_coupled",
-             Lcoupled_submodels,
-             coupled_in_ports,
-             coupled_out_ports,
-             Lcoupled_eics,
-             Lcoupled_eocs,
-             ics
-        );
-        coupleds_by_level[level] = L_coupled;
-    }
-
-    //Create instance of devstone_event_reader
-    std::shared_ptr<cadmium::dynamic::modeling::model> devstone_event_reader1 = cadmium::dynamic::translate::make_dynamic_atomic_model<devstone_event_reader, TIME>("devstone_event_reader1");
-
-    std::shared_ptr<cadmium::dynamic::modeling::model> last_level_coupled = coupleds_by_level[depth];
-
-    //TOP model conecting a generator of events to the input
-    cadmium::dynamic::modeling::Ports TOP_coupled_in_ports = {};
-    cadmium::dynamic::modeling::Ports TOP_coupled_out_ports = {};
-    cadmium::dynamic::modeling::Models TOP_submodels = {devstone_event_reader1, last_level_coupled};
-    cadmium::dynamic::modeling::EICs TOP_eics = {};
-    cadmium::dynamic::modeling::EOCs TOP_eocs = {};
-    cadmium::dynamic::modeling::ICs TOP_ics = {
-        cadmium::dynamic::translate::make_IC<devstone_event_reader_defs::out,coupledLI_in_port>("devstone_event_reader1",last_level_coupled.get()->get_id())
-    };
-    std::shared_ptr<cadmium::dynamic::modeling::coupled<TIME>> TOP_coupled = std::make_shared<cadmium::dynamic::modeling::coupled<TIME>>(
-     "TOP_coupled",
-     TOP_submodels,
-     TOP_coupled_in_ports,
-     TOP_coupled_out_ports,
-     TOP_eics,
-     TOP_eocs,
-     TOP_ics
-    );
-
-    return TOP_coupled;
-}

+ 0 - 21
devstone/cdboost/CMakeLists.txt

@@ -1,21 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-project(devstone-cdboost)
-
-set (CMAKE_CXX_STANDARD 17)
-set (CMAKE_CXX_COMPILER "g++")
-
-set(Boost_USE_STATIC_LIBS        ON)
-set(Boost_USE_MULTITHREADED     OFF)
-
-
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../simulators/cdboost/include)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
-
-find_package(Boost COMPONENTS program_options thread unit_test_framework REQUIRED)
-
-include_directories(${Boost_INCLUDE_DIRS})
-
-## CDBoost
-add_executable(cdboost-devstone src/cdboost-devstone.cpp events_devstone.txt)
-target_include_directories(cdboost-devstone PUBLIC ${PROJECT_SOURCE_DIR}/simulators/cdboost/include)
-target_link_libraries(cdboost-devstone ${Boost_PROGRAM_OPTIONS_LIBRARY})

+ 0 - 1
devstone/cdboost/events_devstone.txt

@@ -1 +0,0 @@
-0 0

+ 0 - 108
devstone/cdboost/src/cdboost-devstone-atomic-pair.hpp

@@ -1,108 +0,0 @@
-/**
- * Copyright (c) 2013-2014, Carleton University, Universite de Nice-Sophia Antipolis
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef P_DEVSTONE_ATOMIC_PAIR_H
-#define P_DEVSTONE_ATOMIC_PAIR_H
-
-#include <boost/simulation/pdevs/atomic.hpp>
-#include "../../dhry/dhry_1.c"
-
-namespace cdpp {
-/**
- * @brief PDEVStone Atomic Model.
- *
- * PDEVStone (InternalTime, ExternalTime, Period):
- * This model executes:
- * - a Dhrystone for InternalCycles on each Internal transition,
- * - a Dhrystone for ExternalCycles on each External transition,
- * - the time advance after each external transition is Period.
-*/
-template<class TIME, class MSG>
-class PDEVStoneAtomicPair : public boost::simulation::pdevs::atomic<TIME, MSG>
-{
-    std::vector<MSG> _out;
-    int _internal_cycles;
-    int _external_cycles;
-    TIME _period;
-    int _queued_processes;
-public:
-    /**
-     * @brief DEVStoneAtomic constructor.
-     *
-     * @param internal_cycles the cycles dhrystone will be run in internal transitions.
-     * @param external_cycles the cycles dhrystone will be run in external transitions.
-     * @param period the time used for all time_advances.
-     */
-    explicit PDEVStoneAtomicPair(int internal_cycles, int external_cycles,  TIME period)
-        : _internal_cycles(internal_cycles), _external_cycles(external_cycles), _period(period), _queued_processes(0)
-    {
-        _out.push_back(std::make_pair(1, 1));
-    }
-    /**
-     * @brief internal function.
-     */
-    void internal() noexcept {
-        DhryStone().dhrystoneRun(_internal_cycles);
-        _queued_processes--;
-    }
-    /**
-     * @brief advance function.
-     * @return Time until next internal event.
-     */
-    TIME advance() const noexcept {
-        return (_queued_processes?_period: boost::simulation::pdevs::atomic<TIME, MSG>::infinity);
-    }
-    /**
-     * @brief out function.
-     * @return Message defined in contruction.
-     */
-    std::vector<MSG> out() const noexcept{
-        return _out;
-    }
-    /**
-     * @brief external function domain is empty, so it throws.
-     * @param msg external input message.
-     * @param t time the external input is received.
-     */
-    void external(const std::vector<MSG>& msg, const TIME& t) noexcept {
-        DhryStone().dhrystoneRun(_external_cycles);
-        _queued_processes+=msg.size();
-    }
-    /**
-     * @brief confluence function as defined in PDEVS
-     * Message interpretation (with cdpp::message_cast) is confluence function responsability.
-     * @param mb is a bag of messages coming from outside
-     * @param t is the time the message is received
-     */
-    void confluence(const std::vector<MSG>& mb, const TIME& t) noexcept{
-        internal();
-        external(mb, TIME(0));
-    }
-
-};
-
-}
-
-#endif // P_DEVSTONE_ATOMIC_PAIR_H

+ 0 - 108
devstone/cdboost/src/cdboost-devstone-atomic.hpp

@@ -1,108 +0,0 @@
-/**
- * Copyright (c) 2013-2014, Carleton University, Universite de Nice-Sophia Antipolis
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef P_DEVSTONE_ATOMIC_H
-#define P_DEVSTONE_ATOMIC_H
-
-#include <boost/simulation/pdevs/atomic.hpp>
-#include "../../dhry/dhry_1.c"
-
-namespace cdpp {
-/**
- * @brief PDEVStone Atomic Model.
- *
- * PDEVStone (InternalTime, ExternalTime, Period):
- * This model executes:
- * - a Dhrystone for InternalCycles on each Internal transition,
- * - a Dhrystone for ExternalCycles on each External transition,
- * - the time advance after each external transition is Period.
-*/
-template<class TIME, class MSG>
-class PDEVStoneAtomic : public boost::simulation::pdevs::atomic<TIME, MSG>
-{
-    std::vector<MSG> _out;
-    int _internal_cycles;
-    int _external_cycles;
-    TIME _period;
-    int _queued_processes;
-public:
-    /**
-     * @brief DEVStoneAtomic constructor.
-     *
-     * @param internal_cycles the cycles dhrystone will be run in internal transitions.
-     * @param external_cycles the cycles dhrystone will be run in external transitions.
-     * @param period the time used for all time_advances.
-     */
-    explicit PDEVStoneAtomic(int internal_cycles, int external_cycles,  TIME period)
-        : _internal_cycles(internal_cycles), _external_cycles(external_cycles), _period(period), _queued_processes(0)
-    {
-        _out.push_back(1);
-    }
-    /**
-     * @brief internal function.
-     */
-    void internal() noexcept {
-        DhryStone().dhrystoneRun(_internal_cycles);
-        _queued_processes--;
-    }
-    /**
-     * @brief advance function.
-     * @return Time until next internal event.
-     */
-    TIME advance() const noexcept {
-        return (_queued_processes?_period: boost::simulation::pdevs::atomic<TIME, MSG>::infinity);
-    }
-    /**
-     * @brief out function.
-     * @return Message defined in contruction.
-     */
-    std::vector<MSG> out() const noexcept{
-        return _out;
-    }
-    /**
-     * @brief external function domain is empty, so it throws.
-     * @param msg external input message.
-     * @param t time the external input is received.
-     */
-    void external(const std::vector<MSG>& msg, const TIME& t) noexcept {
-        DhryStone().dhrystoneRun(_external_cycles);
-        _queued_processes+=msg.size();
-    }
-    /**
-     * @brief confluence function as defined in PDEVS
-     * Message interpretation (with cdpp::message_cast) is confluence function responsability.
-     * @param mb is a bag of messages coming from outside
-     * @param t is the time the message is received
-     */
-    void confluence(const std::vector<MSG>& mb, const TIME& t) noexcept{
-        internal();
-        external(mb, TIME(0));
-    }
-
-};
-
-}
-
-#endif // P_DEVSTONE_ATOMIC_H

+ 0 - 110
devstone/cdboost/src/cdboost-devstone-filter.hpp

@@ -1,110 +0,0 @@
-/**
- * Copyright (c) 2013-2014, Carleton University, Universite de Nice-Sophia Antipolis
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef P_DEVSTONE_FILTER_H
-#define P_DEVSTONE_FILTER_H
-
-#include <boost/simulation/pdevs/atomic.hpp>
-
-namespace cdpp {
-/**
- * @brief PDEVStone Atomic Model.
- *
- * PDEVStone (InternalTime, ExternalTime, Period):
- * This model executes:
- * - a Dhrystone for InternalCycles on each Internal transition,
- * - a Dhrystone for ExternalCycles on each External transition,
- * - the time advance after each external transition is Period.
-*/
-template<class TIME, class MSG>
-class PDEVStoneFilter : public boost::simulation::pdevs::atomic<TIME, MSG>
-{
-    std::vector<MSG> _out;
-    TIME _period;
-    int _reference;
-    int _state;  // 0 passive, 1 active
-public:
-    /**
-     * @brief DEVStoneAtomic constructor.
-     *
-     * @param internal_cycles the cycles dhrystone will be run in internal transitions.
-     * @param external_cycles the cycles dhrystone will be run in external transitions.
-     * @param period the time used for all time_advances.
-     */
-    explicit PDEVStoneFilter(int reference,  TIME period)
-        : _period(period), _reference(reference)
-    {
-        _state = 0;
-    }
-    /**
-     * @brief internal function.
-     */
-    void internal() noexcept {
-        _state = 0;
-    }
-    /**
-     * @brief advance function.
-     * @return Time until next internal event.
-     */
-    TIME advance() const noexcept {
-        return ((_state==1)? 0 : boost::simulation::pdevs::atomic<TIME, MSG>::infinity);
-    }
-    /**
-     * @brief out function.
-     * @return Message defined in contruction.
-     */
-    std::vector<MSG> out() const noexcept{
-        return _out;
-    }
-    /**
-     * @brief external function domain is empty, so it throws.
-     * @param msg external input message.
-     * @param t time the external input is received.
-     */
-    void external(const std::vector<MSG>& msg, const TIME& t) noexcept {
-        for(std::pair<int, int> m: msg) {
-            if(m.first == _reference) {
-                _out.push_back(m);
-            }
-        }
-
-        if(_out.size() != 0) _state = 1;
-    }
-    /**
-     * @brief confluence function as defined in PDEVS
-     * Message interpretation (with cdpp::message_cast) is confluence function responsability.
-     * @param mb is a bag of messages coming from outside
-     * @param t is the time the message is received
-     */
-    void confluence(const std::vector<MSG>& mb, const TIME& t) noexcept{
-        internal();
-        external(mb, TIME(0));
-    }
-
-};
-
-}
-
-#endif // P_DEVSTONE_FILTER_H

+ 0 - 108
devstone/cdboost/src/cdboost-devstone-input-stream-pair.hpp

@@ -1,108 +0,0 @@
-/**
- * Copyright (c) 2013-2014, Carleton University, Universite de Nice-Sophia Antipolis
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef P_DEVSTONE_INPUT_STREAM_PAIR_H
-#define P_DEVSTONE_INPUT_STREAM_PAIR_H
-
-#include <istream>
-#include <sstream>
-#include <boost/simulation/pdevs/atomic.hpp>
-
-using namespace boost::simulation::pdevs;
-
-namespace cdpp {
-/**
- * @brief input_stream PDEVS Model.
- *
- * istream PDEVS Model plays a history of events received by an input stream.
- * The list of events allows to be used as a connector to external tools.
- * The input format is "time output and a custom parser can be defined."
- *
-*/
-template<class TIME, class MSG>
-class devstone_input_stream_pair : public boost::simulation::pdevs::atomic<TIME, MSG>
-{
-    std::vector<MSG> _out;
-    TIME _period;
-    int _state;  // 0 passive, 1 active
-public:
-    /**
-     * @brief DEVStoneAtomic constructor.
-     *
-     * @param internal_cycles the cycles dhrystone will be run in internal transitions.
-     * @param external_cycles the cycles dhrystone will be run in external transitions.
-     * @param period the time used for all time_advances.
-     */
-    explicit devstone_input_stream_pair(TIME period)
-            : _period(period)
-    {
-        _state = 1;
-        _out.push_back(std::make_pair(0, 0));
-        _out.push_back(std::make_pair(1, 0));
-    }
-    /**
-     * @brief internal function.
-     */
-    void internal() noexcept {
-        _state = 0;
-    }
-    /**
-     * @brief advance function.
-     * @return Time until next internal event.
-     */
-    TIME advance() const noexcept {
-        return ((_state==1)? 0 : boost::simulation::pdevs::atomic<TIME, MSG>::infinity);
-    }
-    /**
-     * @brief out function.
-     * @return Message defined in contruction.
-     */
-    std::vector<MSG> out() const noexcept{
-        return _out;
-    }
-    /**
-     * @brief external function domain is empty, so it throws.
-     * @param msg external input message.
-     * @param t time the external input is received.
-     */
-    void external(const std::vector<MSG>& msg, const TIME& t) noexcept {
-
-    }
-    /**
-     * @brief confluence function as defined in PDEVS
-     * Message interpretation (with cdpp::message_cast) is confluence function responsability.
-     * @param mb is a bag of messages coming from outside
-     * @param t is the time the message is received
-     */
-    void confluence(const std::vector<MSG>& mb, const TIME& t) noexcept{
-        internal();
-        external(mb, TIME(0));
-    }
-
-};
-
-}
-
-#endif // P_DEVSTONE_INPUT_STREAM_PAIR_H

+ 0 - 306
devstone/cdboost/src/cdboost-devstone.cpp

@@ -1,306 +0,0 @@
-/**
- * Copyright (c) 2013-2014, Carleton University, Universite de Nice-Sophia Antipolis
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <iostream>
-#include <chrono>
-#include <algorithm>
-#include <fstream>
-#include <boost/program_options.hpp>
-#include <boost/simulation.hpp>
-#include "cdboost-devstone-atomic.hpp"
-#include "cdboost-devstone-atomic-pair.hpp"
-#include "cdboost-devstone-filter.hpp"
-#include "cdboost-devstone-input-stream-pair.hpp"
-
-using namespace std;
-using namespace cdpp;
-namespace po=boost::program_options;
-using hclock=chrono::high_resolution_clock;
-using Time=double;
-//const float infinity = std::numeric_limits<double>::infinity();
-inline bool is_infinity(double& f ){ return isinf(f); }
-using msg_type_int=int;
-using msg_type_pair=std::pair<int, int>;
-
-shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_int>> LI_coupling(int& counted_atomic_models, int& counted_coupled_models,
-                           int width, int depth, string event_list, int ext_cycles, int int_cycles, int time_advance)
-{
-    shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_int>> cm;
-    auto first_pdevstone = boost::simulation::make_atomic_ptr<PDEVStoneAtomic<Time, msg_type_int>, int, int, Time>(int_cycles, ext_cycles, Time(time_advance));
-    counted_atomic_models++;
-    cm.reset(new boost::simulation::pdevs::coupled<Time, msg_type_int>{{first_pdevstone}, {first_pdevstone}, {}, {first_pdevstone}});
-    counted_coupled_models++;
-
-    //connect higher level models
-
-    for (int i=1; i < depth; i++){
-        vector<std::shared_ptr<boost::simulation::model<Time>>> vpdt;
-        vector<std::shared_ptr<boost::simulation::model<Time>>> eoc_cm;
-        vector<std::shared_ptr<boost::simulation::model<Time>>> eic_cm;
-        vpdt.clear();
-        eoc_cm.clear();
-        eic_cm.clear();
-        eoc_cm.push_back(cm);
-        for (int j=0; j < width-1; j++){
-            auto current = (std::shared_ptr<boost::simulation::model<Time>>) std::make_shared<cdpp::PDEVStoneAtomic<Time, msg_type_int>>(int_cycles, ext_cycles, Time(time_advance));
-            vpdt.push_back(current);
-            counted_atomic_models++;
-            eic_cm.push_back(current);
-        }
-        vpdt.push_back(cm);
-        eic_cm.push_back(cm);
-
-        shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_int>> cm_int ( new boost::simulation::pdevs::coupled<Time, msg_type_int>{vpdt, eic_cm, {}, eoc_cm});
-        counted_coupled_models++;
-        cm=cm_int;
-    }
-
-    //Plug the input events
-    shared_ptr<istream> piss{ new ifstream{event_list} };
-    auto pf = boost::simulation::make_atomic_ptr<boost::simulation::pdevs::basic_models::input_stream<Time, msg_type_int, int, int>, shared_ptr<istream>, Time>(piss, Time{0});
-    counted_atomic_models++;
-
-    auto root = std::make_shared<boost::simulation::pdevs::coupled<Time, msg_type_int>>(boost::simulation::pdevs::coupled<Time, msg_type_int>({pf, cm}, {}, {{pf, cm}}, {cm}));
-    counted_coupled_models++;
-    return root;
-}
-
-shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_int>> HI_coupling(int& counted_atomic_models, int& counted_coupled_models,
-                           int width, int depth, string event_list, int ext_cycles, int int_cycles, int time_advance)
-{
-    shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_int>> cm;
-    auto first_pdevstone = boost::simulation::make_atomic_ptr<PDEVStoneAtomic<Time, msg_type_int>, int, int, Time>(int_cycles, ext_cycles, Time(time_advance));
-    counted_atomic_models++;
-    cm.reset(new boost::simulation::pdevs::coupled<Time, msg_type_int>{{first_pdevstone}, {first_pdevstone}, {}, {first_pdevstone}});
-    counted_coupled_models++;
-
-    //connect higher level models
-
-    for (int i=1; i < depth; i++){
-        vector<std::shared_ptr<boost::simulation::model<Time>>> vpdt;
-        vector<std::shared_ptr<boost::simulation::model<Time>>> eoc_cm;
-        vector<std::shared_ptr<boost::simulation::model<Time>>> eic_cm;
-        vector<pair<std::shared_ptr<boost::simulation::model<Time>>, std::shared_ptr<boost::simulation::model<Time>>>> ic_cm;
-        vpdt.clear();
-        eoc_cm.clear();
-        eic_cm.clear();
-        ic_cm.clear();
-        eoc_cm.push_back(cm);
-        for (int j=0; j < width-1; j++){
-            std::shared_ptr<boost::simulation::model<Time>> current = std::shared_ptr<boost::simulation::model<Time>>(make_shared<PDEVStoneAtomic<Time, msg_type_int>>(int_cycles, ext_cycles, Time(time_advance)));
-            if (j > 0) ic_cm.push_back({vpdt.back(), current});
-            vpdt.push_back(current);
-            counted_atomic_models++;
-            eic_cm.push_back(current);
-        }
-        vpdt.push_back(cm);
-        eic_cm.push_back(cm);
-
-        shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_int>> cm_int ( new boost::simulation::pdevs::coupled<Time, msg_type_int>{vpdt, eic_cm, ic_cm, eoc_cm});
-        counted_coupled_models++;
-        cm=cm_int;
-    }
-
-    //Plug the input events
-    shared_ptr<istream> piss{ new ifstream{event_list} };
-    auto pf = boost::simulation::make_atomic_ptr<boost::simulation::pdevs::basic_models::input_stream<Time, msg_type_int, int, int>, shared_ptr<istream>, Time>(piss, Time{0});
-
-    counted_atomic_models++;
-
-    auto root = std::make_shared<boost::simulation::pdevs::coupled<Time, msg_type_int>>(boost::simulation::pdevs::coupled<Time, msg_type_int>({pf, cm}, {}, {{pf, cm}}, {cm}));
-    counted_coupled_models++;
-    return root;
-}
-
-
-shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_pair>> HO_coupling(int& counted_atomic_models, int& counted_coupled_models,
-                                                                          int width, int depth, string event_list, int ext_cycles, int int_cycles, int time_advance)
-{
-    shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_pair>> cm;
-    auto first_pdevstone = boost::simulation::make_atomic_ptr<PDEVStoneAtomicPair<Time, msg_type_pair>, int, int, Time>(int_cycles, ext_cycles, Time(time_advance));
-    counted_atomic_models++;
-    cm.reset(new boost::simulation::pdevs::coupled<Time, msg_type_pair>{{first_pdevstone}, {first_pdevstone}, {}, {first_pdevstone}});
-    counted_coupled_models++;
-
-    //connect higher level models
-
-    for (int i=1; i < depth; i++){
-        auto filter0 = boost::simulation::make_atomic_ptr<PDEVStoneFilter<Time, msg_type_pair>, int, Time>(0, Time(time_advance));   // in
-        auto filter1 = boost::simulation::make_atomic_ptr<PDEVStoneFilter<Time, msg_type_pair>, int, Time>(1, Time(time_advance));   // in2
-        counted_atomic_models+=2;
-        vector<std::shared_ptr<boost::simulation::model<Time>>> vpdt;
-        vector<std::shared_ptr<boost::simulation::model<Time>>> eoc_cm;
-        vector<std::shared_ptr<boost::simulation::model<Time>>> eic_cm;
-        vector<pair<std::shared_ptr<boost::simulation::model<Time>>, std::shared_ptr<boost::simulation::model<Time>>>> ic_cm;
-        vpdt.clear();
-        eoc_cm.clear();
-        eic_cm.clear();
-        ic_cm.clear();
-        eoc_cm.push_back(cm);
-        eic_cm.push_back(filter0);
-        eic_cm.push_back(filter1);
-        for (int j=0; j < width-1; j++){
-            std::shared_ptr<boost::simulation::model<Time>> current = std::shared_ptr<boost::simulation::model<Time>>(make_shared<PDEVStoneAtomicPair<Time, msg_type_pair>>(int_cycles, ext_cycles, Time(time_advance)));
-            if (j > 0) ic_cm.push_back({vpdt.back(), current});
-            vpdt.push_back(current);
-            counted_atomic_models++;
-            //eic_cm.push_back(current);
-            ic_cm.push_back({filter1, current});
-            eoc_cm.push_back(current);
-        }
-        vpdt.push_back(cm);
-        vpdt.push_back(filter0);
-        vpdt.push_back(filter1);
-        //eic_cm.push_back(cm);
-        ic_cm.push_back({filter0, cm});
-
-        shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_pair>> cm_int ( new boost::simulation::pdevs::coupled<Time, msg_type_pair>{vpdt, eic_cm, ic_cm, eoc_cm});
-        counted_coupled_models++;
-        cm=cm_int;
-    }
-
-    //Plug the input events
-    auto gen = boost::simulation::make_atomic_ptr<devstone_input_stream_pair<Time, msg_type_pair>, Time>(Time(time_advance));
-    counted_atomic_models++;
-
-    auto root = std::make_shared<boost::simulation::pdevs::coupled<Time, msg_type_pair>>(boost::simulation::pdevs::coupled<Time, msg_type_pair>({gen, cm}, {}, {{gen, cm}}, {cm}));
-    counted_coupled_models++;
-    return root;
-}
-
-
-
-
-int main(int argc, char* argv[]){
-    auto start = hclock::now();
-
-    // Declare the supported options.
-    po::options_description desc("Allowed options");
-    desc.add_options()
-            ("help", "produce help message")
-            ("kind", po::value<string>()->required(), "set kind of devstone: LI, HI or HO")
-            ("width", po::value<int>()->required(), "set width of the DEVStone: integer value")
-            ("depth", po::value<int>()->required(), "set depth of the DEVStone: integer value")
-            ("int-cycles", po::value<int>()->required(), "set the Dhrystone cycles to expend in internal transtions: integer value")
-            ("ext-cycles", po::value<int>()->required(), "set the Dhrystone cycles to expend in external transtions: integer value")
-            ("event-list", po::value<string>()->required(), "set the file to read the events. The format is 2 ints per line meaning time->msg")
-            ("time-advance", po::value<int>()->default_value(1), "set the time expend in external transtions by the Dhrystone in miliseconds: integer value")
-            ;
-
-    po::variables_map vm;
-    try {
-        po::store(po::parse_command_line(argc, argv, desc), vm);
-        po::notify(vm);
-    } catch ( boost::program_options::required_option be ){
-        if (vm.count("help")) {
-            cout << desc << "\n";
-            return 0;
-        } else {
-            cout << be.what() << endl;
-            cout << endl;
-            cout << "for mode information run: " << argv[0] << " --help" << endl;
-            return 1;
-        }
-    }
-    string kind = vm["kind"].as<string>();
-    if (kind.compare("LI") != 0  && kind.compare("HI") != 0 && kind.compare("HO") != 0) {
-        cout << "The kind needs to be LI, HI or HO and received value was: " << kind;
-        cout << endl;
-        cout << "for mode information run: " << argv[0] << " --help" << endl;
-        return 1;
-    }
-
-    {
-        std::ifstream f(vm["event-list"].as<string>().c_str());
-        if(!f.is_open()){
-            cout << "File for events: " << vm["event-list"].as<string>() << " is not accesible." << endl;
-            cout << endl;
-            cout << "for mode information run: " << argv[0] << " --help" << endl;
-            return 1;
-        }
-    }
-
-    int width = vm["width"].as<int>();
-    int depth = vm["depth"].as<int>();
-    int int_cycles = vm["int-cycles"].as<int>();
-    int ext_cycles = vm["ext-cycles"].as<int>();
-    int time_advance = vm["time-advance"].as<int>();
-    string event_list = vm["event-list"].as<string>();
-    //finished processing input
-
-    //create models for LI kind
-    int models_quantity = (width - 1) * (depth - 1) + 1;
-    int counted_atomic_models=0;
-    int counted_coupled_models=0;
-
-    auto processed_parameters = hclock::now();
-
-    shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_int>> root_int;
-    shared_ptr<boost::simulation::pdevs::coupled<Time, msg_type_pair>> root_pair;
-    if (kind.compare("LI") == 0){
-        root_int = LI_coupling(counted_atomic_models, counted_coupled_models, width, depth, event_list, ext_cycles, int_cycles, time_advance);
-    } else if (kind.compare("HI") == 0){
-        root_int = HI_coupling(counted_atomic_models, counted_coupled_models, width, depth, event_list, ext_cycles, int_cycles, time_advance);
-    } else if (kind.compare("HO") == 0){
-        root_pair = HO_coupling(counted_atomic_models, counted_coupled_models, width, depth, event_list, ext_cycles, int_cycles, time_advance);
-    } else {
-        abort();
-    }
-
-    auto model_built = hclock::now();
-    std::chrono::_V2::system_clock::time_point model_init;
-    //run the model
-    if (kind.compare("LI") == 0 || kind.compare("HI") == 0) {
-        boost::simulation::pdevs::runner<Time, msg_type_int> r(root_int, Time{0});
-        model_init = hclock::now();
-        r.runUntilPassivate();
-    } else {  // HO or HOmod
-        boost::simulation::pdevs::runner<Time, msg_type_pair> r(root_pair, Time{0});
-        model_init = hclock::now();
-        r.runUntilPassivate();
-    }
-
-    auto finished_simulation = hclock::now();
-
-    cout << "Simulation with params: ";
-
-    for (const auto& it : vm) {
-        cout << it.first.c_str() << ": ";
-        auto& value = it.second.value();
-        if (auto v = boost::any_cast<int>(&value))
-            std::cout << *v;
-        else if (auto v = boost::any_cast<std::string>(&value))
-            std::cout << *v;
-        else
-            std::cout << "error";
-        cout << " ";
-    }
-
-
-    cout << endl;
-    cout << "Model creation time: " << chrono::duration_cast<chrono::duration<double, ratio<1>>>( model_built - processed_parameters).count() << endl;
-    cout << "Engine setup time: " << chrono::duration_cast<chrono::duration<double, ratio<1>>>( model_init - model_built).count() << endl;
-    cout << "Simulation time: " << chrono::duration_cast<chrono::duration<double, ratio<1>>>( finished_simulation - model_init).count() << endl;
-}

+ 0 - 0
devstone/pythonpdevs/__init__.py


+ 0 - 81
simulators/adevs-3.3/README

@@ -1,81 +0,0 @@
-This file contains instructions for building the C++ library and
-the Java bindings. Development versions of this library are available 
-from SourceForge and github.
-
----- C++ -----
-Adevs is implemented primarily as a set of C++ header files,
-and for many applications these are sufficient. The rest of
-the simulation engine is in the static library file 'libadevs.a'.
-To build this library file this, go to the directory called 'src'
-and run 'make'. The default options for the compiler should
-work if you are using the GNU g++ compiler. For other compilers,
-you make set options, build commands, etc. by editing the Makefile.
-
-If you are using Visual Studio and Windows, then to build the
-static library do the following: 1) open a command shell, 2) go the
-'src' directory, and 3) run the batch file 'build.bat'. This 
-creates a static library to link with your simulation applications.
-
----- Java -----
-To build the java bindings for Linux, go the the 'src' directory and  
-edit the Makefile so that JAVA_HOME points to your jdk installation.
-Then run 'make java_adevs'. This builds the shared library libjava_adevs.so
-and the jar-file adevs.jar. To use these put the shared library into 
-your LD_LIBRARY_PATH and the jar file into your CLASSPATH.
-
-To build the java bindings For Windows, first make sure that 1) your
-JAVA_HOME environment variable points to your jdk installation and
-2) that the java compiler is in your executable PATH. Then execute
-the batch file src/adevs_jni/build.bat. This creates the jar-file
-adevs.jar and DLL-file java_adevs.dll. You can use these by putting
-the former into your CLASSPATH and latter into your PATH.
-
----- FMI ----
-Adevs supports importing models that use the FMI standard for Model
-Exchange. Information about this standard can be found at
-http://www.fmi-standard.org. This feature is particularly useful
-for importing continuous system models built with the Modelica
-language into your discrete event simulation. The examples and
-test cases shipped with adevs assume that you have the 
-OpenModelica compiler installed. You can get this compiler from
-http://www.openmodelica.org. The bash script build-omc.sh for building
-the OpenModelica compiler from source code is located in the util
-directory. The fmi test cases are located in test/fmi, and you can
-execute these by going to that directory and running 'make all'.
-
----- Useful scripts ----
-
-xml2cpp.py
-This script will convert an FMI model description file to a C++ class
-that imports the FMI described into an adevs simulation by using the
-adevs::FMI class. Executing the script will display rudimentary information
-about command line arguments.
-
-build-omc.sh
-This bash shell script will download and build the OpenModelica compiler,
-which can be used to translate Modelica models into FMI modules. These FMI
-modules can then be loaded into your adevs simulation.
-
----- Testing -----
-There are four sets of test cases that can be run from the
-directory 'test'. The first set are for the C++ library without
-and these tests are run with 'make check_cpp'.
-The java bindings can be tested by
-executing 'make check_java'. The fmi import support can be
-tested by executing 'make check_fmi'. Executing 'make check'
-runs all of the test cases.
-
-The make.common file contains platform specific settings for
-the test scripts. It is setup by default for a GNU/Linux type of
-environment. Change as needed for your environment, but if you are
-using a more or less typical Linux distribution then the defaults
-should work fine.
-
-When testing the Java bindings, be sure your PATH, LD_LIBRARY_PATH,
-and CLASSPATH are setup properly before running the Java test
-cases. These need to include your DLL (for Windows) and Java binaries,
-shared object file (for Linux), and jar file and the '.' directory
-respectively.
-
-For the FMI test cases, you will need to have the OpenModelica compiler
-installed.

+ 0 - 30
simulators/adevs-3.3/copyright.txt

@@ -1,30 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */

+ 0 - 51
simulators/adevs-3.3/include/adevs.h

@@ -1,51 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-/**
- * \mainpage
- * Links to the user manual, tutorials on DEVS, and other such
- * stuff are <a href="../index.html">here</a>.
- */
-/**
- * Include everything needed to compile user models.
- */
-#include "adevs_exception.h"
-#include "adevs_models.h"
-#include "adevs_simulator.h"
-#include "adevs_digraph.h"
-#include "adevs_simpledigraph.h"
-#include "adevs_cellspace.h"
-#include "adevs_rand.h"
-#include "adevs_hybrid.h"
-#include "adevs_corrected_euler.h"
-#include "adevs_event_locators.h"
-#include "adevs_rk_45.h"
-#include "adevs_poly.h"
-#include "adevs_wrapper.h"

+ 0 - 119
simulators/adevs-3.3/include/adevs_abstract_simulator.h

@@ -1,119 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_abstract_simulator_h_
-#define __adevs_abstract_simulator_h_
-#include "adevs_models.h"
-#include "adevs_event_listener.h"
-#include "adevs_bag.h"
-
-namespace adevs
-{
-
-/**
- * This is the base class for all simulators. It defines an interface that is
- * supported by all derived classes and provides some basic helper routines
- * for those derived classes.
- */
-template <class X, class T = double> class AbstractSimulator 
-{
-	public:
-		/// Constructor
-		AbstractSimulator(){}
-		/**
-		 * Add an event listener that will be notified of output events 
-		 * produced by all components within the model.
-		 * @param l The listener to be notified
-		 */
-		void addEventListener(EventListener<X,T>* l)
-		{
-			listeners.insert(l);
-		}
-		/**
-		 * Remove an event listener that was previously added.
-		 * @param l The listener to be removed
-		 */
-		void removeEventListener(EventListener<X,T>* l)
-		{
-			listeners.erase(l);
-		}
-		/// Get the model's next event time
-		virtual T nextEventTime() = 0;
-		/// Execute the simulator until the next event time is greater than tend
-		virtual T execUntil(T tend) = 0;
-		/// Destructor leaves the model intact.
-		virtual ~AbstractSimulator(){}
-		/// Notify listeners of an output event.
-		void notify_output_listeners(Devs<X,T>* model, const X& value, T t);
-		/// Notify listeners of an input event.
-		void notify_input_listeners(Devs<X,T>* model, const X& value, T t);
-		/// Notify listeners of a state change.
-		void notify_state_listeners(Atomic<X,T>* model, T t);
-	private:
-		/// Eternal event listeners
-		Bag<EventListener<X,T>*> listeners;
-
-};
-
-template <class X, class T>
-void AbstractSimulator<X,T>::notify_output_listeners(Devs<X,T>* model, const X& value, T t)
-{
-	Event<X,T> event(model,value);
-	typename Bag<EventListener<X,T>*>::iterator iter;
-	for (iter = listeners.begin(); iter != listeners.end(); iter++)
-	{
-		(*iter)->outputEvent(event,t);
-	}
-}
-
-template <class X, class T>
-void AbstractSimulator<X,T>::notify_input_listeners(Devs<X,T>* model, const X& value, T t)
-{
-	Event<X,T> event(model,value);
-	typename Bag<EventListener<X,T>*>::iterator iter;
-	for (iter = listeners.begin(); iter != listeners.end(); iter++)
-	{
-		(*iter)->inputEvent(event,t);
-	}
-}
-
-template <class X, class T>
-void AbstractSimulator<X,T>::notify_state_listeners(Atomic<X,T>* model, T t)
-{
-	typename Bag<EventListener<X,T>*>::iterator iter;
-	for (iter = listeners.begin(); iter != listeners.end(); iter++)
-	{
-		(*iter)->stateChange(model,t);
-	}
-}
-
-} // end of namespace
-
-#endif

+ 0 - 193
simulators/adevs-3.3/include/adevs_bag.h

@@ -1,193 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef _adevs_bag_h
-#define _adevs_bag_h
-#include <cstdlib>
-
-namespace adevs
-{
-
-/**
- * The Bag is (almost) a model of a STL Multiple Associative Container.
- * This implementation is optimized for the simulation engine, and it 
- * does not satisfy the STL complexity requirements. Neither does it implement
- * the full set of required methods, but those methods that are implemented
- * conform to the standard (except for the time complexity requirement).
- */
-template <class T> class Bag
-{
-	public:
-		/// A bidirectional iterator for the Bag
-		class iterator
-		{
-			public:
-				/// Default constructor
-				iterator(){}
-				/// Copy constructor
-				iterator(const iterator& src):i(src.i),b(src.b){}
-				/// Copy by assignment
-				const iterator& operator=(const iterator& src) 
-				{ 
-					i = src.i; 
-					b = src.b;
-					return *this;
-				}
-				/// True if two iterators point at the same position in the bag
-				bool operator==(const iterator& src) const { return i==src.i; }
-				/// True if two iterators point at different positions in the bag
-				bool operator!=(const iterator& src) const { return i!=src.i; }
-				/// Get the element at the current position
-				T& operator*() { return b[i]; }
-				/// Get the element at the current position
-				const T& operator*() const { return b[i]; }
-				/// Move to the next position and get the element there
-				iterator& operator++() { i++; return *this; }
-				/// Move to the next position and get the element there
-				iterator& operator++(int) { ++i; return *this; }
-				/// Move to the previous position and get the element there
-				iterator& operator--() { i--; return *this; }
-				/// Move to the previous position and get the element there
-				iterator& operator--(int) { --i; return *this; }
-			private:
-				friend class Bag<T>;	
-				unsigned int i;
-				T* b;
-				iterator(unsigned int start, T* b):i(start),b(b){}
-		};
-		/// A bidirection iterator for the Bag that should not change its contents 
-		typedef iterator const_iterator;
-		/// Create an empty bag with an initial capacity
-		Bag(unsigned int cap = 8):
-		cap_(cap),size_(0),b(new T[cap]){}
-		/// Copy constructor uses the = operator of T
-		Bag(const Bag<T>& src):
-		cap_(src.cap_),
-		size_(src.size_)
-		{
-			b = new T[src.cap_];
-			for (unsigned int i = 0; i < size_; i++) 
-				b[i] = src.b[i];
-		}
-		/// Assignment operator uses the = operator of T
-		const Bag<T>& operator=(const Bag<T>& src)
-		{
-			cap_ = src.cap_;
-			size_ = src.size_;
-			delete [] b;
-			b = new T[src.cap_];
-			for (unsigned int i = 0; i < size_; i++) 
-				b[i] = src.b[i];
-			return *this;
-		}
-		/// Swaps contents of this bag with the contents of the supplied bag. Returns this bag.
-		Bag<T>& swap(Bag<T>& src)
-		{
-			unsigned tmp_cap_, tmp_size_;
-			T* tmp_b;
-			tmp_cap_ = src.cap_;
-			tmp_size_ = src.size_;
-			tmp_b = src.b;
-			src.cap_ = cap_;
-			src.size_ = size_;
-			src.b = b;
-			cap_ = tmp_cap_;
-			size_ = tmp_size_;
-			b = tmp_b;
-			return *this;
-		}
-		/// Count the instances of a stored in the bag
-		unsigned count(const T& a) const
-		{
-			unsigned result = 0;
-			for (unsigned i = 0; i < size_; i++)
-				if (b[i] == a) result++;
-			return result;
-		}
-		/// Get the number of elements in the bag
-		unsigned size() const { return size_; }
-		/// Same as size()==0
-		bool empty() const { return size_ == 0; }
-		/// Get an iterator pointing to the first element in the bag
-		iterator begin() const { return iterator(0,b); }
-		/// Get an iterator to the end of the bag (i.e., just after the last element)
-		iterator end() const { return iterator(size_,b); }
-		/// Erase the first instance of k
-		void erase(const T& k) 
-		{
-			iterator p = find(k);
-			if (p != end()) erase(p);
-		}
-		/// Erase the element pointed to by p
-		void erase(iterator p)
-		{
-			size_--;
-			b[p.i] = b[size_];
-		}
-		/// Remove all of the elements from the bag
-		void clear() { size_ = 0; }
-		/// Find the first instance of k, or end() if no instance is found. Uses == for comparing T.
-		iterator find(const T& k) const
-		{
-			for (unsigned i = 0; i < size_; i++)
-				if (b[i] == k) return iterator(i,b);
-			return end();
-		}
-		/// Put t into the bag
-		void insert(const T& t)
-		{
-			if (cap_ == size_) enlarge(2*cap_);
-			b[size_] = t;
-			size_++;
-		}
-		/// Access the element at position k
-		const T& operator[](unsigned k) const { return b[k]; }
-		/// Access the element at position k
-		T& operator[](unsigned k) { return b[k]; }
-		/// Delete the bag 
-		~Bag() { delete [] b; }
-	private:	
-		unsigned cap_, size_;
-		T* b;
-		/// Adds the specified capacity to the bag.
-		void enlarge(unsigned adjustment)
-		{
-			cap_ = cap_ + adjustment;
-			T* rb = new T[cap_];
-			for (unsigned i = 0; i < size_; i++) 
-				rb[i] = b[i];
-			delete [] b;
-			b = rb;
-		}
-	};
-
-} // end of namespace
-
-#endif

+ 0 - 216
simulators/adevs-3.3/include/adevs_cellspace.h

@@ -1,216 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_cellspace_h_
-#define __adevs_cellspace_h_
-#include "adevs.h"
-#include <cstdlib>
-
-namespace adevs
-{
-
-/**
- * Input and output events produced by components of a CellSpace must
- * be of the type CellEvent.  A CellEvent has an event value (i.e., the actual
- * input/output value) and a target cell for the event.
- */
-template <class X> class CellEvent
-{
-	public:
-		/// Default constructor. Sets x = y = z = 0.
-		CellEvent():value() { x = y = z = 0; }
-		/// Copy constructor
-		CellEvent(const CellEvent<X>& src):
-		x(src.x),y(src.y),z(src.z),value(src.value){}
-		/// Assignment operator
-		const CellEvent& operator=(const CellEvent<X>& src)
-		{
-			x = src.x; y = src.y; z = src.z; value = src.value;
-			return *this;
-		}
-		/// The x coordinate of the event target
-		long int x;
-		/// The y coordinate of the event target
-		long int y;
-		/// The z coordinate of the event target
-		long int z;
-		/// The event value
-		X value;
-};
-
-/**
- * This class describes a 3D cell space whose components accept and produce CellEvent objects.
- * This class is meant to be useful for solving PDEs, simulating
- * next event cell spaces, and for building other types of models represented as a space of 
- * discrete, interacting points. Output events produced by component models must be of type CellEvent, and
- * the CellEvent (x,y,z) coordinate indicates the
- * target cell for the event. The corresponding input event will have the same (x,y,z) value as
- * the output event. Targets that are outside of the CellSpace will become external output
- * events for the CellSpace model.  Similarly, CellEvent objects that are injected into the
- * CellSpace (i.e., external input events) will be delivered to the targeted cell.
- */
-template <class X, class T = double> class CellSpace: public Network<CellEvent<X>,T>
-{
-	public:
-		/// A component model in the CellSpace
-		typedef Devs<CellEvent<X>,T> Cell;
-		/// Create an Width x Height x Depth CellSpace with NULL entries in the cell locations.
-		CellSpace(long int width, long int height = 1, long int depth = 1);
-		/// Insert a model at the x,y,z position.
-		void add(Cell* model, long int x, long int y = 0, long int z = 0) 
-		{
-			space[x][y][z] = model;
-			model->setParent(this);
-		}
-		/// Get the model at location x,y,z.
-		const Cell* getModel(long int x, long int y = 0, long int z = 0) const
-		{
-			return space[x][y][z];
-		}
-		/// Get a mutable version of the model at x,y,z.
-		Cell* getModel(long int x, long int y = 0, long int z = 0)
-		{
-			return space[x][y][z];
-		}
-		/// Get the width of the CellSpace.
-		long int getWidth() const { return w; }
-		/// Get the height of the CellSpace.
-		long int getHeight() const { return h; }
-		/// Get the depth of the CellSpace.
-		long int getDepth() const { return d; }
-		/// Get the model's set of components
-		void getComponents(Set<Cell*>& c);
-		/// Route events within the Cellspace
-		void route(const CellEvent<X>& event, Cell* model, 
-		Bag<Event<CellEvent<X>,T> >& r);
-		/// Destructor; this destroys the components as well.
-		~CellSpace();
-	private:	
-		long int w, h, d;
-		Cell**** space;
-};
-
-// Implementation of constructor
-template <class X, class T>
-CellSpace<X,T>::CellSpace(long int width, long int height, long int depth):
-Network<CellEvent<X>,T>()
-{
-	w = width;
-	h = height;
-	d = depth;
-	// Allocate space for the cells and set the entries to NULL
-	space = new Cell***[w];
-	for (long int x = 0; x < w; x++)
-	{
-		space[x] = new Cell**[h];
-		for (long int y = 0; y < h; y++)
-		{
-			space[x][y] = new Cell*[h];
-			for (long int z = 0; z < d; z++)
-			{
-				space[x][y][z] = NULL;
-			}
-		}
-	}
-}
-
-// Implementation of destructor
-template <class X, class T>
-CellSpace<X,T>::~CellSpace()
-{
-	for (long int x = 0; x < w; x++)
-	{
-		for (long int y = 0; y < h; y++)
-		{
-			for (long int z = 0; z < d; z++)
-			{
-				if (space[x][y][z] != NULL)
-				{
-					delete space[x][y][z];
-				}
-			}
-			delete [] space[x][y];
-		}
-		delete [] space[x];
-	}
-	delete [] space;
-}
-
-// Implementation of the getComponents() method
-template <class X, class T>
-void CellSpace<X,T>::getComponents(Set<Cell*>& c)
-{
-	// Add all non-null entries to the set c
-	for (long int x = 0; x < w; x++)
-	{
-		for (long int y = 0; y < h; y++)
-		{
-			for (long int z = 0; z < d; z++)
-			{
-				if (space[x][y][z] != NULL)
-				{
-					c.insert(space[x][y][z]);
-				}
-			}
-		}
-	}
-}
-
-// Event routing function for the net_exec
-template <class X, class T>
-void CellSpace<X,T>::route(
-const CellEvent<X>& event, Cell* model, Bag<Event<CellEvent<X>,T> >& r)
-{
-	Cell* target = NULL;
-	// If the target cell is inside of the cellspace
-	if (event.x >= 0 && event.x < w &&  // check x dimension
-	event.y >= 0 && event.y < h && // check y dimension
-	event.z >= 0 && event.z < d) // check z dimension
-	{
-		// Get the interior target
-		target = space[event.x][event.y][event.z];
-	}
-	else
-	{
-		// Otherwise, the event becomes an external output from the cellspace
-		target = this;
-	}
-	// If the target exists
-	if (target != NULL)
-	{
-		// Add an appropriate event to the receiver bag
-		Event<CellEvent<X>,T> io(target,event);
-		r.insert(io);
-	}
-}
-
-} // end of namespace
-
-#endif

+ 0 - 143
simulators/adevs-3.3/include/adevs_corrected_euler.h

@@ -1,143 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef _adevs_corrected_euler_h_
-#define _adevs_corrected_euler_h_
-#include <cmath>
-#include <algorithm>
-#include "adevs_hybrid.h"
-
-namespace adevs
-{
-
-/**
- * This is the second order accurate RK2 method with adaptive step sizing for
- * error control.
- */
-template <typename X> class corrected_euler:
-	public ode_solver<X>
-{
-	public:
-		/**
-		 * Create an integrator that will use the specified per step error
-		 * tolerance and maximum step size.
-		 */
-		corrected_euler(ode_system<X>* sys, double err_tol, double h_max);
-		/// Destructor
-		~corrected_euler();
-		double integrate(double* q, double h_lim);
-		void advance(double* q, double h);
-	private:
-		double *dq, // derivative
-			   *qq, // trial solution
-			   *t,  // temporary variable for computing k2
-			   *k[2]; // k1 and k2
-		const double err_tol; // Error tolerance
-		const double h_max; // Maximum time step
-		double h_cur; // Previous time step that satisfied error constraint
-		// Compute a step of size h, put it in qq, and return the error
-		double trial_step(double h);
-};
-
-template <typename X>
-corrected_euler<X>::corrected_euler(ode_system<X>* sys, double err_tol,
-		double h_max):
-	ode_solver<X>(sys),err_tol(err_tol),h_max(h_max),h_cur(h_max)
-{
-	for (int i = 0; i < 2; i++) k[i] = new double[sys->numVars()];
-	dq = new double[sys->numVars()];
-	qq = new double[sys->numVars()];
-	t = new double[sys->numVars()];
-}
-
-template <typename X>
-corrected_euler<X>::~corrected_euler()
-{
-	delete [] t; delete [] qq; delete [] dq;
-	for (int i = 0; i < 2; i++) delete [] k[i];
-}
-
-template <typename X>
-void corrected_euler<X>::advance(double* q, double h)
-{
-	double dt;
-	while ((dt = integrate(q,h)) < h) h -= dt;
-}
-
-template <typename X>
-double corrected_euler<X>::integrate(double* q, double h_lim)
-{
-	// Initial error estimate and step size
-	double err = DBL_MAX,
-		   h = std::min<double>(h_cur*1.1,std::min<double>(h_max,h_lim));
-	for (;;) {
-		// Copy q to the trial vector
-		for (int i = 0; i < this->sys->numVars(); i++) qq[i] = q[i];
-		// Make the trial step which will be stored in qq
-		err = trial_step(h);
-		// If the error is ok, then we have found the proper step size
-		if (err <= err_tol) { // Keep h if shrunk to control the error
-			if (h_lim >= h_cur) h_cur = h; 
-			break;
-		}
-		// Otherwise shrink the step size and try again
-		else {
-			double h_guess = 0.8*err_tol*h/fabs(err);
-			if (h < h_guess) h *= 0.8;
-			else h = h_guess;
-		}
-	}
-	// Put the trial solution in q and return the selected step size
-	for (int i = 0; i < this->sys->numVars(); i++) q[i] = qq[i];
-	return h;
-}
-
-template <typename X>
-double corrected_euler<X>::trial_step(double step)
-{
-	int j;
-	// Compute k1
-	this->sys->der_func(qq,dq); 
-	for (j = 0; j < this->sys->numVars(); j++) k[0][j] = step*dq[j];
-	// Compute k2
-	for (j = 0; j < this->sys->numVars(); j++) t[j] = qq[j] + 0.5*k[0][j];
-	this->sys->der_func(t,dq);
-	for (j = 0; j < this->sys->numVars(); j++) k[1][j] = step*dq[j];
-	// Compute next state and approximate error
-	double err = 0.0;
-	for (j = 0; j < this->sys->numVars(); j++) {
-		qq[j] += k[1][j]; // Next state
-		err = std::max<double>(err,fabs(k[0][j]-k[1][j])); // Maximum error
-	}
-	return err; // Return the error
-}
-
-} // end of namespace
-#endif

+ 0 - 212
simulators/adevs-3.3/include/adevs_digraph.h

@@ -1,212 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_digraph_h_
-#define __adevs_digraph_h_
-#include "adevs.h"
-#include <cassert>
-#include <map>
-#include <set>
-#include <cstdlib>
-
-namespace adevs
-{
-
-/**
- * The components of a digraph model must use PortValue objects
- * as their basic I/O type: the port and value types are template
- * arguments. The default port type is an integer.
- */
-template <class VALUE, class PORT=int> class PortValue
-{
-	public:
-		/// Constructor
-		PortValue():
-		port(),
-		value()
-		{
-		}
-		/// Copy constructor
-		PortValue(const PortValue& src):
-		port(src.port),
-		value(src.value)
-		{
-		}
-		/// Create an object with the specified port and value
-		PortValue(PORT port, const VALUE& value):
-		port(port),
-		value(value)
-		{
-		}
-		/// Assignment operator
-		const PortValue<VALUE,PORT>& operator=(const PortValue<VALUE,PORT>& src)
-		{
-			port = src.port;
-			value = src.value;
-			return *this;
-		}
-		/// Destructor
-		~PortValue()
-		{
-		}
-		/// The port on which the value appears
-		PORT port;
-		/// The value appearing on the port
-		VALUE value;
-};
-
-/**
- * The digraph model is used to build block-diagrams from network and atomic components.
- * Its components must have PortValue objects as their input/output type.
- */
-template <class VALUE, class PORT=int, class T = double> class Digraph: 
-public Network<PortValue<VALUE,PORT>,T>
-{
-	public:
-		/// An input or output to a component model
-		typedef PortValue<VALUE,PORT> IO_Type;
-		/// A component of the Digraph model
-		typedef Devs<IO_Type,T> Component;
-
-		/// Construct a network with no components.
-		Digraph():
-		Network<IO_Type,T>()
-		{
-		}
-		/// Add a model to the network.
-		void add(Component* model);
-		/// Couple the source model to the destination model.  
-		void couple(Component* src, PORT srcPort, 
-		Component* dst, PORT dstPort);
-		/// Puts the network's components into to c
-		void getComponents(Set<Component*>& c);
-		/// Route an event based on the coupling information.
-		void route(const IO_Type& x, Component* model, 
-		Bag<Event<IO_Type,T> >& r);
-		/// Destructor.  Destroys all of the component models.
-		~Digraph();
-
-	private:	
-		// A node in the coupling graph
-		struct node
-		{
-			node():
-			model(NULL),
-			port()
-			{
-			}
-			node(Component* model, PORT port):
-			model(model),
-			port(port)
-			{
-			}
-			const node& operator=(const node& src)
-			{
-				model = src.model;
-				port = src.port;
-				return *this;
-			}
-			Component* model;
-			PORT port;
-		
-			// Comparison for STL map
-			bool operator<(const node& other) const
-			{
-				if (model == other.model) return port < other.port;
-				return model < other.model;
-			}
-		};
-		// Component model set
-		Set<Component*> models;
-		// Coupling information
-		std::map<node,Bag<node> > graph;
-};
-
-template <class VALUE, class PORT, class T>
-void Digraph<VALUE,PORT,T>::add(Component* model)
-{
-	assert(model != this);
-	models.insert(model);
-	model->setParent(this);
-}
-
-template <class VALUE, class PORT, class T>
-void Digraph<VALUE,PORT,T>::couple(Component* src, PORT srcPort, 
-Component* dst, PORT dstPort)
-{
-	if (src != this) add(src);
-	if (dst != this) add(dst);
-	node src_node(src,srcPort);
-	node dst_node(dst,dstPort);
-	graph[src_node].insert(dst_node);
-}
-
-template <class VALUE, class PORT, class T>
-void Digraph<VALUE,PORT,T>::getComponents(Set<Component*>& c)
-{
-	c = models;
-}
-
-template <class VALUE, class PORT, class T>
-void Digraph<VALUE,PORT,T>::
-route(const IO_Type& x, Component* model, 
-Bag<Event<IO_Type,T> >& r)
-{
-	// Find the list of target models and ports
-	node src_node(model,x.port);
-	typename std::map<node,Bag<node> >::iterator graph_iter;
-	graph_iter = graph.find(src_node);
-	// If no target, just return
-	if (graph_iter == graph.end()) return;
-	// Otherwise, add the targets to the event bag
-	Event<IO_Type,T> event;
-	typename Bag<node>::iterator node_iter;
-	for (node_iter = (*graph_iter).second.begin();
-	node_iter != (*graph_iter).second.end(); node_iter++)
-	{
-		event.model = (*node_iter).model;
-		event.value.port = (*node_iter).port;
-		event.value.value = x.value;
-		r.insert(event);
-	}
-}
-template <class VALUE, class PORT, class T>
-Digraph<VALUE,PORT,T>::~Digraph()
-{ 
-	typename Set<Component*>::iterator i;
-	for (i = models.begin(); i != models.end(); i++)
-	{
-		delete *i;
-	}
-}
-
-} // end of namespace 
-
-#endif

+ 0 - 74
simulators/adevs-3.3/include/adevs_event_listener.h

@@ -1,74 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_event_listener_h_
-#define __adevs_event_listener_h_
-#include "adevs_models.h"
-#include "adevs_bag.h"
-
-namespace adevs
-{
-
-/**
- * The EventListener interface is used to receive output events produced
- * by model and to be notified of state changes at Atomic models.
- */
-template <class X, class T = double> class EventListener
-{
-	public:
-		/**
-		 * This callback is invoked when a model, network or atomic,
-		 * produces an output. The default implementation is empty.
-		 * @param x The model that produced the output and the output's value
-		 * @param t The absolute time at which the output occurred
-		 */
-		virtual void outputEvent(Event<X,T> x, T t){}
-		/**
-		 * This callback is invoked when a model, network or atomic,
-		 * recieves an input. The default implementation is empty.
-		 * @param x The model and input value
-		 * @param t The absolute time at which the output occurred
-		 */
-		virtual void inputEvent(Event<X,T> x, T t){}
-		/**
-		 * This callback is invoked by the simulator after an Atomic
-		 * model changes its state. This method has an empty default
-		 * implementation.
-		 * @param model The model that changed state
-		 * @param t The absolute time at which the state change occurred
-		 */
-		virtual void stateChange(Atomic<X,T>* model, T t){}
-		/// Destructor
-		virtual ~EventListener(){}
-};
-
-} // end of namespace
-
-#endif

+ 0 - 233
simulators/adevs-3.3/include/adevs_event_locators.h

@@ -1,233 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef _adevs_event_locators_h_
-#define _adevs_event_locators_h_
-#include "adevs_hybrid.h"
-#include <cmath>
-#include <iostream>
-
-namespace adevs
-{
-
-/**
- * This is a state event locator that uses either bisection or
- * linear interpolation to pinpoints events in time.
- */
-template <typename X> class event_locator_impl:
-	public event_locator<X>
-{
-	public:
-		/**
-		 * The locator will attempt to pinpoint events within err_tol of
-		 * zero for each state event function; i.e., an event occurs
-		 * at the first instant t' >= t where z(t)*z(t') <= 0 and
-		 * |z(t')| < err_tol.
-		 */
-		enum Mode { INTERPOLATE, BISECTION, DISCONTINUOUS };
-		/**
-		 * Create an event locator that will act on the supplied ode system.
-		 * @param sys The system of equations to solve
-		 * @param err_tol Threshold for the zero crossing function that will
-		 * trigger an event detect.
-		 * @param mode The event localization method to be used
-		 */
-		event_locator_impl(ode_system<X>* sys, double err_tol, Mode mode);
-		/// Destructor leaves the ode_system object intact
-		~event_locator_impl();
-		/**
-		 * Location discrete events between now and now + h.
-		 * @param events This array contains one entry for each zero crossing
-		 * function. An entry is true of that function is within err_tol of
-		 * zero and false otherwise.
-		 * @param qstart The continuous variable state vector now.
-		 * @param qend The continuous value state vector when the event
-		 * is detected or at now+h if no event is detected.
-		 * @param solver The ode solver to use when computing continuous
-		 * state vector values.
-		 * @param h The interval of time over which to look for events.
-		 * @return true if at least one event was found and false otherwise.
-		 */
-		bool find_events(bool* events, const double* qstart, double* qend,
-				ode_solver<X>* solver, double& h);
-	private:
-		double *z[2]; // State events at the start and end of [0,h]
-		const double err_tol; // Error tolerance
-		Mode mode;
-
-		int sign(double x) const
-		{
-			if (x < 0.0) return -1;
-			else if (x > 0.0) return 1;
-			else return 0;
-		}
-};
-
-template <typename X>
-event_locator_impl<X>::event_locator_impl(ode_system<X>* sys,
-		double err_tol, Mode mode):
-	event_locator<X>(sys),
-	err_tol(err_tol),
-	mode(mode)
-{
-	z[0] = new double[sys->numEvents()];
-	z[1] = new double[sys->numEvents()];
-}
-
-template <typename X>
-event_locator_impl<X>::~event_locator_impl()
-{
-	delete [] z[0]; delete [] z[1];
-}
-
-template <typename X>
-bool event_locator_impl<X>::find_events(bool* events,
-	const double* qstart, double* qend, ode_solver<X>* solver, double& h)
-{
-	// Calculate the state event functions at the start 
-	// of the interval
-	this->sys->state_event_func(qstart,z[0]);
-	// Look for the first event inside of the interval [0,h]
-	while (this->sys->numEvents() > 0)
-	{
-		double tguess = h;
-		bool event_in_interval = false, found_event = false;
-		this->sys->state_event_func(qend,z[1]);
-		// Do any of the z functions change sign? Have we found an event?
-		for (int i = 0; i < this->sys->numEvents(); i++)
-		{
-			events[i] = false;
-			if (sign(z[1][i]) != sign(z[0][i]))
-			{
-				// Event at h > 0
-				if (
-						// End condition when z is continuous
-						((mode != DISCONTINUOUS) && (fabs(z[1][i]) <= err_tol)) ||
-						// End condition when z is discontinuous
-						((mode == DISCONTINUOUS) && (h <= err_tol))
-					)
-				{
-					events[i] = found_event = true; 
-				}
-				// There is an event in (0,h)
-				else 
-				{
-					if (mode == INTERPOLATE)
-					{
-						double tcandidate = z[0][i]*h/(z[0][i]-z[1][i]);
-						// Don't let the step size go to zero
-						if (tcandidate < h/4.0) tcandidate = h/4.0;
-						if (tcandidate < tguess) tguess = tcandidate;
-					}
-					event_in_interval = true;
-				}
-			}
-		}
-		// Guess at a new h and calculate qend for that time
-		if (event_in_interval)
-		{
-			if (mode == BISECTION || mode == DISCONTINUOUS) h /= 2.0;
-			else h = tguess;
-			for (int i = 0; i < this->sys->numVars(); i++)
-				qend[i] = qstart[i];
-			solver->advance(qend,h);
-		}
-		else return found_event;
-	}
-	// Will never reach this line
-	return false;
-}
-
-/**
- * Locate events using the bisection method. Your z functions must be
- * continuous for this to work.
- */
-template <typename X>
-class bisection_event_locator:
-	public event_locator_impl<X>
-{
-	public:
-		/// Create an event locator that implements the bisection search mode
-		bisection_event_locator(ode_system<X>* sys, double err_tol):
-			event_locator_impl<X>(
-					sys,err_tol,event_locator_impl<X>::BISECTION){}
-};
-
-/**
- * Locate events using linear interpolation. Your z functions must be
- * continuous for this to work.
- */
-template <typename X>
-class linear_event_locator:
-	public event_locator_impl<X>
-{
-	public:
-		/// Create an event locator that implements the linear interpolation search mode
-		linear_event_locator(ode_system<X>* sys, double err_tol):
-			event_locator_impl<X>(
-					sys,err_tol,event_locator_impl<X>::INTERPOLATE){}
-};
-
-/**
- * Locate events using bisection assuming discontinuous z functions.
- */
-template <typename X>
-class discontinuous_event_locator:
-	public event_locator_impl<X>
-{
-	public:
-		/**
-		 * Create an event locator that implements a bisection search while
-		 * assuming the z functions are not continuous.
-		 */
-		discontinuous_event_locator(ode_system<X>* sys, double err_tol):
-			event_locator_impl<X>(
-					sys,err_tol,event_locator_impl<X>::DISCONTINUOUS){}
-};
-
-/**
- * This event locator is for models that have no state events. Its find_events
- * method simply returns false.
- */
-template <typename X> class null_event_locator:
-	public event_locator<X>
-{
-	public:
-		null_event_locator():event_locator<X>(NULL){}
-		~null_event_locator(){}
-		bool find_events(bool*, const double*, double*, ode_solver<X>*, double&)
-		{
-			return false;
-		}
-};
-
-} // end of namespace 
-
-#endif

+ 0 - 98
simulators/adevs-3.3/include/adevs_exception.h

@@ -1,98 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef _adevs_exception_h_
-#define _adevs_exception_h_
-#include <string>
-#include <exception>
-
-namespace adevs
-{
-
-/**
- * The adevs::exception class is derived from the standard template
- * library exception class.
- */
-class exception: public std::exception
-{
-	public:
-		/**
-		 * Create an exception with an error message and, if appropriate,
-		 * a pointer to the model that created the error.  To avoid
-		 * templated exceptions, the model pointer is just a void*.
-		 */
-		exception(const char* msg, void* model = NULL):
-		std::exception(),
-		msg(msg),
-		model(model) 
-		{}
-		/// Copy constructor.
-		exception(const adevs::exception& src):
-		std::exception(src),
-		msg(src.msg),
-		model(src.model)
-		{}
-		/// Get the error message.
-		const char* what() const throw()
-		{
-			return msg.c_str();
-		}
-		/// Get a pointer to the model that created the error.
-		void* who() const { return model; }
-		/// Destructor.
-		~exception() throw(){}
-	private:
-		std::string msg;
-		void* model;
-};
-
-/**
- * The unsupported method exception is raised if an optional virtual method
- * is not supported by a model.
- */
-class method_not_supported_exception:
-	public exception
-{
-	public:
-		/**
-		 * Constructor should be supplied with the model throwing
-		 * the exception and the name of the method that is not supported.
-		 */
-		method_not_supported_exception(const char* method, void* model):
-			exception((std::string("Unsupported method: ")+std::string(method)).c_str(),
-					model)
-		{
-		}
-};
-
-} // end of namespace
-
-#endif
-

+ 0 - 592
simulators/adevs-3.3/include/adevs_fmi.h

@@ -1,592 +0,0 @@
-/**
- * Copyright (c) 2014, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef _adevs_fmi_h_
-#define _adevs_fmi_h_
-#include <algorithm>
-#include <cmath>
-#include <iostream>
-#include <cstdlib>
-#include <cstdio>
-#include <cassert>
-#include "adevs_hybrid.h"
-#include "fmi2Functions.h"
-#include "fmi2FunctionTypes.h"
-#include "fmi2TypesPlatform.h"
-
-// Functions for loading DLL and so files
-#ifdef _WIN32
-#include <windows.h>
-#define OPEN_LIB(name) LoadLibrary(name)
-#define GET_FUNC(hndl,name) GetProcAddress(hndl,name)
-#define CLOSE_LIB(hndl) FreeLibrary(hndl)
-#else
-#include <dlfcn.h>
-#define OPEN_LIB(name) dlopen(name,RTLD_LAZY)
-#define GET_FUNC(hndl,name) dlsym(hndl,name)
-#define CLOSE_LIB(hndl) dlclose(hndl)
-#endif
-
-namespace adevs
-{
-
-/**
- * Load an FMI wrapped continuous system model for use in a
- * discrete event simulation. The FMI can then be attached
- * to any of the ODE solvers and event detectors in adevs
- * for simulation with the Hybrid class. This FMI loader 
- * does not automatically extract model information from the
- * description XML, and so that information must be provided
- * explicitly by the end-user, but you probably need to know
- * this information regardless if you are using the FMI inside
- * of a larger discrete event simulation.
- */
-template <typename X> class FMI:
-	public ode_system<X>
-{
-	public:
-		/**
-		 * This constructs a wrapper around an FMI. The constructor
-		 * must be provided with the FMI's GUID, the number of state variables,
-		 * number of event indicators, and the path to the .so file
-		 * that contains the FMI functions for this model.
-		 */
-		FMI(const char* modelname,
-			const char* guid,
-			const char* resource_location,
-			int num_state_variables,
-			int num_event_indicators,
-			const char* shared_lib_name,
-			const double tolerance = 1E-8,
-			int num_extra_event_indicators = 0,
-			double start_time = 0.0);
-		/// Copy the initial state of the model to q
-		virtual void init(double* q);
-		/// Compute the derivative for state q and put it in dq
-		virtual void der_func(const double* q, double* dq);
-		/// Compute the state event functions for state q and put them in z
-		virtual void state_event_func(const double* q, double* z);
-		/// Compute the time event function using state q
-		virtual double time_event_func(const double* q);
-		/**
-		 * This method is invoked immediately following an update of the
-		 * continuous state variables and signal to the FMI the end
-		 * of an integration state.
-		 */
-		virtual void postStep(double* q);
-		/**
-		 * Like the postStep() method, but this is called at the end
-		 * of a trial step made by the numerical integrator. Trial steps
-		 * are used to locate state events and to estimate numerical
-		 * errors. The state vector q passed to this method may not be
-		 * the final vector assigned to the model at the end of
-		 * the current integration step. The get that value use
-		 * the postStep() method.
-		 */
-		virtual void postTrialStep(double* q);
-		/**
-		 * The internal transition function. This function will process all events
-		 * required by the FMI. Any derived class should call this method for the
-		 * parent class, then set or get any variables as appropriate, and then
-		 * call the base class method again to account for these changes. 
-		 */
-		virtual void internal_event(double* q,
-				const bool* state_event);
-		/**
-		 * The external transition See the notes on the internal_event function for
-		 * derived classes.
-		 */
-		virtual void external_event(double* q, double e,
-				const Bag<X>& xb);
-		/**
-		 * The confluent transition function. See the notes on the internal_event function for
-		 * derived classes.
-		 */
-		virtual void confluent_event(double *q, const bool* state_event,
-				const Bag<X>& xb);
-		/**
-		 * The output function. This can read variables for the FMI, but should
-		 * not make any modifications to those variables.
-		 */
-		virtual void output_func(const double *q, const bool* state_event,
-				Bag<X>& yb);
-		/**
-		 * Garbage collection function. This works just like the Atomic gc_output method.
-		 * The default implementation does nothing.
-		 */
-		virtual void gc_output(Bag<X>& gb);
-		/// Destructor
-		virtual ~FMI();
-		/// Get the current time
-		double get_time() const { return t_now; }
-		/// Get the value of a real variable
-		double get_real(int k);
-		/// Set the value of a real variable
-		void set_real(int k, double val);
-		/// Get the value of an integer variable
-		int get_int(int k);
-		/// Set the value of an integer variable
-		void set_int(int k, int val);
-		/// Get the value of a boolean variable
-		bool get_bool(int k);
-		/// Set the value of a boolean variable
-		void set_bool(int k, bool val);
-		/// Get the value of a string variable
-		std::string get_string(int k);
-		/// Set the value of a string variable
-		void set_string(int k, std::string& val);
-	private:
-		// Reference to the FMI
-		fmi2Component c;
-		// Pointer to the FMI interface
-		fmi2Component (*_fmi2Instantiate)(fmi2String, fmi2Type,
-				fmi2String, fmi2String, const fmi2CallbackFunctions*,
-				fmi2Boolean, fmi2Boolean);
-		void (*_fmi2FreeInstance)(fmi2Component);
-		fmi2Status (*_fmi2SetupExperiment)(fmi2Component, fmi2Boolean,
-				fmi2Real, fmi2Real, fmi2Boolean, fmi2Real);
-		fmi2Status (*_fmi2EnterInitializationMode)(fmi2Component);
-		fmi2Status (*_fmi2ExitInitializationMode)(fmi2Component);
-		fmi2Status (*_fmi2GetReal)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Real*);
-		fmi2Status (*_fmi2GetInteger)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Integer*);
-		fmi2Status (*_fmi2GetBoolean)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Boolean*);
-		fmi2Status (*_fmi2GetString)(fmi2Component, const fmi2ValueReference*, size_t, fmi2String*);
-		fmi2Status (*_fmi2SetReal)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Real*);
-		fmi2Status (*_fmi2SetInteger)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Integer*);
-		fmi2Status (*_fmi2SetBoolean)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Boolean*);
-		fmi2Status (*_fmi2SetString)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2String*);
-		fmi2Status (*_fmi2EnterEventMode)(fmi2Component);
-		fmi2Status (*_fmi2NewDiscreteStates)(fmi2Component,fmi2EventInfo*);
-		fmi2Status (*_fmi2EnterContinuousTimeMode)(fmi2Component);
-		fmi2Status (*_fmi2CompletedIntegratorStep)(fmi2Component, fmi2Boolean, fmi2Boolean*, fmi2Boolean*);
-		fmi2Status (*_fmi2SetTime)(fmi2Component, fmi2Real);
-		fmi2Status (*_fmi2SetContinuousStates)(fmi2Component, const fmi2Real*, size_t);
-		fmi2Status (*_fmi2GetDerivatives)(fmi2Component, fmi2Real*, size_t);
-		fmi2Status (*_fmi2GetEventIndicators)(fmi2Component, fmi2Real*, size_t);
-		fmi2Status (*_fmi2GetContinuousStates)(fmi2Component, fmi2Real*, size_t);	
-		
-		// Instant of the next time event
-		double next_time_event;
-		// Current time
-		double t_now;
-		// so library handle
-		#ifdef _WIN32
-		HINSTANCE so_hndl;
-		#else
-		void* so_hndl;
-		#endif
-		// Are we in continuous time mode?
-		bool cont_time_mode;
-		// Number of event indicators that are not governed by the FMI
-		int num_extra_event_indicators;
-		// Start time of the simulation
-		double start_time;
-
-		static void fmilogger(
-			fmi2ComponentEnvironment componentEnvironment,
-			fmi2String instanceName,
-			fmi2Status status,
-			fmi2String category,
-			fmi2String message,...)
-		{
-			if (message != NULL){			
-		
-				fprintf(stderr, message,"\n");
-			}
-		}
-
-		fmi2CallbackFunctions* callbackFuncs;
-
-		void iterate_events();
-};
-
-template <typename X>
-FMI<X>::FMI(const char* modelname,
-			const char* guid,
-			const char* resource_location,
-			int num_state_variables,
-			int num_event_indicators,
-			const char* so_file_name,
-			const double tolerance,
-			int num_extra_event_indicators,
-			double start_time):
-	// One extra variable at the end for time
-	ode_system<X>(num_state_variables+1,num_event_indicators+num_extra_event_indicators),
-	next_time_event(adevs_inf<double>()),
-	t_now(start_time),
-	so_hndl(NULL),
-	cont_time_mode(false),
-	num_extra_event_indicators(num_extra_event_indicators)	
-{
-	fmi2CallbackFunctions tmp = {adevs::FMI<X>::fmilogger,calloc,free,NULL,NULL};
-	callbackFuncs = new fmi2CallbackFunctions(tmp);
-	so_hndl = OPEN_LIB(so_file_name);
-	if (so_hndl == NULL)
-	{
-		throw adevs::exception("Could not load so file",this);
-    }
-	// This only works with a POSIX compliant compiler/system
-	_fmi2Instantiate = (fmi2Component (*)(fmi2String, fmi2Type,
-		fmi2String, fmi2String, const fmi2CallbackFunctions*,
-		fmi2Boolean, fmi2Boolean))GET_FUNC(so_hndl,"fmi2Instantiate");
-	assert(_fmi2Instantiate != NULL);
-	_fmi2FreeInstance = (void (*)(fmi2Component))GET_FUNC(so_hndl,"fmi2FreeInstance");
-	assert(_fmi2FreeInstance != NULL);
-	_fmi2SetupExperiment = (fmi2Status (*)(fmi2Component, fmi2Boolean,
-		fmi2Real, fmi2Real, fmi2Boolean, fmi2Real))GET_FUNC(so_hndl,"fmi2SetupExperiment");
-	assert(_fmi2SetupExperiment != NULL);
-	_fmi2EnterInitializationMode = (fmi2Status (*)(fmi2Component))GET_FUNC(so_hndl,"fmi2EnterInitializationMode");
-	assert(_fmi2EnterInitializationMode != NULL);
-	_fmi2ExitInitializationMode = (fmi2Status (*)(fmi2Component))GET_FUNC(so_hndl,"fmi2ExitInitializationMode");
-	assert(_fmi2ExitInitializationMode != NULL);
-	_fmi2GetReal = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Real*))
-		GET_FUNC(so_hndl,"fmi2GetReal");
-	assert(_fmi2GetReal != NULL);
-	_fmi2GetInteger = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Integer*)) 
-		GET_FUNC(so_hndl,"fmi2GetInteger");
-	assert(_fmi2GetInteger != NULL);
-	_fmi2GetBoolean = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, fmi2Boolean*))
-		GET_FUNC(so_hndl,"fmi2GetBoolean");
-	assert(_fmi2GetBoolean != NULL);
-	_fmi2GetString = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, fmi2String*))
-		GET_FUNC(so_hndl,"fmi2GetString");
-	assert(_fmi2GetString != NULL);
-	_fmi2SetReal = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Real*))
-		GET_FUNC(so_hndl,"fmi2SetReal");
-	assert(_fmi2SetReal != NULL);
-	_fmi2SetInteger = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Integer*))
-		GET_FUNC(so_hndl,"fmi2SetInteger");
-	assert(_fmi2SetInteger != NULL);
-	_fmi2SetBoolean = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2Boolean*))
-		GET_FUNC(so_hndl,"fmi2SetBoolean");
-	assert(_fmi2SetBoolean != NULL);
-	_fmi2SetString = (fmi2Status (*)(fmi2Component, const fmi2ValueReference*, size_t, const fmi2String*))
-		GET_FUNC(so_hndl,"fmi2SetString");
-	assert(_fmi2SetString != NULL);
-	_fmi2EnterEventMode = (fmi2Status (*)(fmi2Component))GET_FUNC(so_hndl,"fmi2EnterEventMode");
-	assert(_fmi2EnterEventMode != NULL);
-	_fmi2NewDiscreteStates = (fmi2Status (*)(fmi2Component,fmi2EventInfo*))GET_FUNC(so_hndl,"fmi2NewDiscreteStates");
-	assert(_fmi2NewDiscreteStates != NULL);
-	_fmi2EnterContinuousTimeMode = (fmi2Status (*)(fmi2Component))GET_FUNC(so_hndl,"fmi2EnterContinuousTimeMode");
-	assert(_fmi2EnterContinuousTimeMode != NULL);
-	_fmi2CompletedIntegratorStep = (fmi2Status (*)(fmi2Component, fmi2Boolean, fmi2Boolean*, fmi2Boolean*))
-		GET_FUNC(so_hndl,"fmi2CompletedIntegratorStep");
-	assert(_fmi2CompletedIntegratorStep != NULL);
-	_fmi2SetTime = (fmi2Status (*)(fmi2Component, fmi2Real))GET_FUNC(so_hndl,"fmi2SetTime");
-	assert(_fmi2SetTime != NULL);
-	_fmi2SetContinuousStates = (fmi2Status (*)(fmi2Component, const fmi2Real*, size_t))
-		GET_FUNC(so_hndl,"fmi2SetContinuousStates");
-	assert(_fmi2SetContinuousStates != NULL);
-	_fmi2GetDerivatives = (fmi2Status (*)(fmi2Component, fmi2Real*, size_t))GET_FUNC(so_hndl,"fmi2GetDerivatives");
-	assert(_fmi2GetDerivatives != NULL);
-	_fmi2GetEventIndicators = (fmi2Status (*)(fmi2Component, fmi2Real*, size_t))GET_FUNC(so_hndl,"fmi2GetEventIndicators");
-	assert(_fmi2GetEventIndicators != NULL);
-	_fmi2GetContinuousStates = (fmi2Status (*)(fmi2Component, fmi2Real*, size_t))GET_FUNC(so_hndl,"fmi2GetContinuousStates");
-	assert(_fmi2GetContinuousStates != NULL);
-	// Create the FMI component
-	c = _fmi2Instantiate(modelname,fmi2ModelExchange,guid,resource_location,callbackFuncs,fmi2False,fmi2False);
-	assert(c != NULL);
-	_fmi2SetupExperiment(c,fmi2True,tolerance,-1.0,fmi2False,-1.0);
-}
-
-template <typename X>
-void FMI<X>::iterate_events()
-{
-	fmi2Status status;
-	// Put into consistent initial state
-	fmi2EventInfo eventInfo;
-	do
-	{
-		status = _fmi2NewDiscreteStates(c,&eventInfo);
-		assert(status == fmi2OK);
-	}
-	while (eventInfo.newDiscreteStatesNeeded == fmi2True);
-	if (eventInfo.nextEventTimeDefined == fmi2True)
-		next_time_event = eventInfo.nextEventTime;
-	else
-		next_time_event = adevs_inf<double>();
-	assert(status == fmi2OK);
-}
-
-template <typename X>
-void FMI<X>::init(double* q)
-{
-	fmi2Status status;
-	// Initialize all variables
-	status = _fmi2EnterInitializationMode(c);
-	assert(status == fmi2OK);
-	// Done with initialization
-	status = _fmi2ExitInitializationMode(c);
-	assert(status == fmi2OK);
-	// Put into consistent initial state
-	iterate_events();
-	// Enter continuous time mode to start integration
-	status = _fmi2EnterContinuousTimeMode(c);
-	assert(status == fmi2OK);
-	// Set initial value for time
-	status = _fmi2SetTime(c,t_now);
-	assert(status == fmi2OK);
-	// Get starting state variable values
-	status = _fmi2GetContinuousStates(c,q,this->numVars()-1);
-	assert(status == fmi2OK);
-	q[this->numVars()-1] = t_now;
-	cont_time_mode = true;
-}
-
-template <typename X>
-void FMI<X>::der_func(const double* q, double* dq)
-{
-	fmi2Status status;
-	if (!cont_time_mode)
-	{
-		status = _fmi2EnterContinuousTimeMode(c);
-		assert(status == fmi2OK);
-		cont_time_mode = true;
-	}
-	status =_fmi2SetTime(c,q[this->numVars()-1]);
-	assert(status == fmi2OK);
-	status = _fmi2SetContinuousStates(c,q,this->numVars()-1);
-	assert(status == fmi2OK);
-	status = _fmi2GetDerivatives(c,dq,this->numVars()-1);
-	assert(status == fmi2OK);
-	dq[this->numVars()-1] = 1.0;
-}
-
-template <typename X>
-void FMI<X>::state_event_func(const double* q, double* z)
-{
-	fmi2Status status;
-	if (!cont_time_mode)
-	{
-		status = _fmi2EnterContinuousTimeMode(c);
-		assert(status == fmi2OK);
-		cont_time_mode = true;
-	}
-	status = _fmi2SetTime(c,q[this->numVars()-1]);
-	assert(status == fmi2OK);
-	status = _fmi2SetContinuousStates(c,q,this->numVars()-1);
-	assert(status == fmi2OK);
-	status = _fmi2GetEventIndicators(c,z,this->numEvents()-num_extra_event_indicators);
-	assert(status == fmi2OK);
-}
-
-template <typename X>
-double FMI<X>::time_event_func(const double* q)
-{
-	return next_time_event-q[this->numVars()-1];
-}
-
-template <typename X>
-void FMI<X>::postStep(double* q)
-{
-	assert(cont_time_mode);
-	// Don't advance the FMI state by zero units of time
-	// when in continuous mode
-	if (q[this->numVars()-1] <= t_now)
-		return;
-	// Try to complete the integration step
-	fmi2Status status;
-	fmi2Boolean enterEventMode;
-	fmi2Boolean terminateSimulation;
-	t_now = q[this->numVars()-1];
-	status = _fmi2SetTime(c,t_now);
-	assert(status == fmi2OK);
-	status = _fmi2SetContinuousStates(c,q,this->numVars()-1);
-	assert(status == fmi2OK);
-	status = _fmi2CompletedIntegratorStep(c,fmi2True,&enterEventMode,&terminateSimulation);
-	assert(status == fmi2OK);
-	// Force an event if one is indicated
-	if (enterEventMode == fmi2True)
-		next_time_event = t_now;
-}
-
-template <typename X>
-void FMI<X>::postTrialStep(double* q)
-{
-	assert(cont_time_mode);
-	// Restore values changed by der_func and state_event_func
-	fmi2Status status;
-	status = _fmi2SetTime(c,q[this->numVars()-1]);
-	assert(status == fmi2OK);
-	status = _fmi2SetContinuousStates(c,q,this->numVars()-1);
-	assert(status == fmi2OK);
-}
-
-template <typename X>
-void FMI<X>::internal_event(double* q, const bool* state_event)
-{
-	fmi2Status status;
-	// postStep will have updated the continuous variables, so 
-	// we just process discrete events here.
-	if (cont_time_mode)
-	{
-		status = _fmi2EnterEventMode(c);
-		assert(status == fmi2OK);
-		cont_time_mode = false;
-	}
-	// Process events
-	iterate_events();
-	// Update the state variable array
-	status = _fmi2GetContinuousStates(c,q,this->numVars()-1);
-	assert(status == fmi2OK);
-}
-				
-template <typename X>
-void FMI<X>::external_event(double* q, double e, const Bag<X>& xb)
-{
-	fmi2Status status;
-	// Go to event mode if we have not yet done so
-	if (cont_time_mode)
-	{
-		status = _fmi2EnterEventMode(c);
-		assert(status == fmi2OK);
-		cont_time_mode = false;
-	}
-	// process any events that need processing
-	iterate_events();
-	status = _fmi2GetContinuousStates(c,q,this->numVars()-1);
-	assert(status == fmi2OK);
-}
-				
-template <typename X>
-void FMI<X>::confluent_event(double *q, const bool* state_event, const Bag<X>& xb)
-{
-	fmi2Status status;
-	// postStep will have updated the continuous variables, so 
-	// we just process discrete events here.
-	if (cont_time_mode)
-	{
-		status = _fmi2EnterEventMode(c);
-		assert(status == fmi2OK);
-		cont_time_mode = false;
-	}
-	iterate_events();
-	status = _fmi2GetContinuousStates(c,q,this->numVars()-1);
-	assert(status == fmi2OK);
-}
-				
-template <typename X>
-void FMI<X>::output_func(const double *q, const bool* state_event, Bag<X>& yb)
-{
-}
-
-template <typename X>
-void FMI<X>::gc_output(Bag<X>& gb)
-{
-}
-
-template <typename X>
-FMI<X>::~FMI()
-{
-	_fmi2FreeInstance(c);
-	delete callbackFuncs;
-	CLOSE_LIB(so_hndl);
-}
-
-template <typename X>
-double FMI<X>::get_real(int k)
-{
-	const fmi2ValueReference ref = k;
-	fmi2Real val;
-	fmi2Status status = _fmi2GetReal(c,&ref,1,&val);
-	assert(status == fmi2OK);
-	return val;
-}
-
-template <typename X>
-void FMI<X>::set_real(int k, double val)
-{
-	const fmi2ValueReference ref = k;
-	fmi2Real fmi_val = val;
-	fmi2Status status = _fmi2SetReal(c,&ref,1,&fmi_val);
-	assert(status == fmi2OK);
-}
-
-template <typename X>
-int FMI<X>::get_int(int k)
-{
-	const fmi2ValueReference ref = k;
-	fmi2Integer val;
-	fmi2Status status = _fmi2GetInteger(c,&ref,1,&val);
-	assert(status == fmi2OK);
-	return val;
-}
-
-template <typename X>
-void FMI<X>::set_int(int k, int val)
-{
-	const fmi2ValueReference ref = k;
-	fmi2Integer fmi_val = val;
-	fmi2Status status = _fmi2SetInteger(c,&ref,1,&fmi_val);
-	assert(status == fmi2OK);
-}
-
-template <typename X>
-bool FMI<X>::get_bool(int k)
-{
-	const fmi2ValueReference ref = k;
-	fmi2Boolean val;
-	fmi2Status status = _fmi2GetBoolean(c,&ref,1,&val);
-	assert(status == fmi2OK);
-	return (val == fmi2True);
-}
-
-template <typename X>
-void FMI<X>::set_bool(int k, bool val)
-{
-	const fmi2ValueReference ref = k;
-	fmi2Boolean fmi_val = fmi2False;
-	if (val) fmi_val = fmi2True;
-	fmi2Status status = _fmi2SetBoolean(c,&ref,1,&fmi_val);
-	assert(status == fmi2OK);
-}
-
-template <typename X>
-std::string FMI<X>::get_string(int k)
-{
-	const fmi2ValueReference ref = k;
-	fmi2String val;
-	fmi2Status status = _fmi2GetString(c,&ref,1,&val);
-	assert(status == fmi2OK);
-	return val;
-}
-
-template <typename X>
-void FMI<X>::set_string(int k, std::string& val)
-{
-	const fmi2ValueReference ref = k;
-	fmi2String fmi_val = fmi2False;
-	fmi2Status status = _fmi2SetString(c,&ref,1,&fmi_val);
-	assert(status == fmi2OK);
-}
-
-} // end of namespace
-
-#endif

+ 0 - 617
simulators/adevs-3.3/include/adevs_hybrid.h

@@ -1,617 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef _adevs_hybrid_h_
-#define _adevs_hybrid_h_
-#include <algorithm>
-#include <cmath>
-#include "adevs_models.h"
-
-namespace adevs
-{
-
-/**
- * This is the base class for all hybrid systems. The init and der_func methods
- * are used to implement the model's continuous dynamics. The other functions
- * are for discrete event dynamics.
- */
-template <typename X> class ode_system
-{
-	public:
-		/// Make a system with N state variables and M state event functions
-		ode_system(int N_vars, int M_event_funcs):
-			N(N_vars),M(M_event_funcs){}
-		/// Get the number of state variables
-		int numVars() const { return N; }
-		/// Get the number of state events
-		int numEvents() const { return M; }
-		/// Copy the initial state of the model to q
-		virtual void init(double* q) = 0;
-		/// Compute the derivative for state q and put it in dq
-		virtual void der_func(const double* q, double* dq) = 0;
-		/// Compute the state event functions for state q and put them in z
-		virtual void state_event_func(const double* q, double* z) = 0;
-		/// Compute the time event function using state q
-		virtual double time_event_func(const double* q) = 0;
-		/**
-		 * This method is invoked immediately following an update of the
-		 * continuous state variables. The main use of this callback is to
-		 * update algberaic variables. The default implementation does nothing.
-		 */
-		virtual void postStep(double* q){};
-		/**
-		 * This is called after a trial step. It can be used to restore the values
-		 * of any variables that might have been changed by der_func or state_event_func
-		 * while calculating the trial step. By default this method does nothing.
-		 */
-		virtual void postTrialStep(double* q){};
-		/// The internal transition function
-		virtual void internal_event(double* q,
-				const bool* state_event) = 0;
-		/// The external transition function
-		virtual void external_event(double* q, double e,
-				const Bag<X>& xb) = 0;
-		/// The confluent transition function
-		virtual void confluent_event(double *q, const bool* state_event,
-				const Bag<X>& xb) = 0;
-		/// The output function
-		virtual void output_func(const double *q, const bool* state_event,
-				Bag<X>& yb) = 0;
-		/// Garbage collection function. This works just like the Atomic gc_output method.
-		virtual void gc_output(Bag<X>& gb) = 0;
-		/// Destructor
-		virtual ~ode_system(){}
-	private:
-		const int N, M;
-};
-
-/**
- * <p>This extension of the ode_system provides for modeling some semi-explicit
- * DAEs of index 1, specifically those in the form dx/dt = f(x,y), y = g(x,y).
- * The solution to y=g(x,y) is found by iteration on y.
- * See "The Numerical Solution of Differential-Algebraic Systems by Runge-Kutta
- * Methods" by Ernst Hairer, Michel Roche and Christian Lubich, published
- * by Springer as Lecture Notes in Mathematics, Volum 1409, c. 1989.
- * The section on Half-explicit methods (starting pg. 20 of my copy)
- * describes the procedure.</p>
- * <p>Only the methods that include the algebraic variables should be overriden.
- * Any explicit, single step ODE solver can be used to generate trajectories for
- * this object (e.g., the Runge-Kutta methods included with adevs will work).</p>
- */
-template <typename X> class dae_se1_system:
-	public ode_system<X>
-{
-	public:
-		/**
-		 * Make a system with N state variables, M state event functions
-		 * and A algebraic variables. The error tolerance determines
-		 * the acceptable accuracy for the algebraic solution to y=g(x,y).
-		 * The max_iters argument determines how many iterations will
-		 * be used to try and generate a solution.
-		 */
-		dae_se1_system(int N_vars, int M_event_funcs, int A_alg_vars,
-				double err_tol = 1E-10, int max_iters = 30, double alpha = -1.0):
-			ode_system<X>(N_vars,M_event_funcs),
-			A(A_alg_vars),
-			max_iters(max_iters),
-			err_tol(err_tol),
-			alpha(alpha)
-			{
-				failed = 0;
-				max_err = 0.0;
-				a = new double[A];
-				atmp = new double[A];
-				d = new double[A];
-				f[1] = new double[A];
-				f[0] = new double[A];
-			}
-		/// Get the number of algebraic variables
-		int numAlgVars() const { return A; }
-		/// Get the algebraic variables
-		double getAlgVar(int i) const { return a[i]; }
-		/**
-		 * Write an intial solution for the state variables q
-		 * and algebraic variables a.
-		 */
-		virtual void init(double* q, double* a) = 0;
-		/**
-		 * Calculate the algebraic function for the state vector
-		 * q and algebraic variables a and store the result to af.
-		 * A solution to alg_func(a,q) = a will be found by 
-		 * iteration on this function.
-		 */
-		virtual void alg_func(const double* q, const double* a, double* af) = 0;
-		/**
-		 * Calculate the derivative of the state variables and store
-		 * the result in dq.
-		 */
-		virtual void der_func(const double* q, const double* a, double* dq) = 0;
-		/**
-		 * Calculate the state event functions and store the result in z.
-		 */
-		virtual void state_event_func(const double* q, const double* a, double* z) = 0;
-		/// Compute the time event function using state q and algebraic variables a
-		virtual double time_event_func(const double* q, const double* a) = 0;
-		/**
-		 * Update any variables that need updating at then end of a simulation step.
-		 * This is called both when postStep(q) would be called and also immediately
-		 * after the execution a discrete state transition.
-		 */
-		virtual void postStep(double* q, double* a) = 0;
-		/**
-		 * Default implementation calls postTrialStep(q)
-		 */
-		virtual void postTrialStep(double *q, double* a) { ode_system<X>::postTrialStep(q); }
-		/// The internal transition function
-		virtual void internal_event(double* q, double* a,
-				const bool* state_event) = 0;
-		/// The external transition function
-		virtual void external_event(double* q, double* a,
-				double e, const Bag<X>& xb) = 0;
-		/// The confluent transition function
-		virtual void confluent_event(double *q, double* a, 
-				const bool* state_event, const Bag<X>& xb) = 0;
-		/// The output function
-		virtual void output_func(const double *q, const double* a,
-				const bool* state_event, Bag<X>& yb) = 0;
-		/// Destructor
-		virtual ~dae_se1_system()
-		{
-			delete [] d;
-			delete [] a;
-			delete [] atmp;
-			delete [] f[1];
-			delete [] f[0];
-		}
-		/**
-		 * Get the number of times that the error tolerance was not satisfied
-		 * before the iteration limit was reached.
-		 */
-		int getIterFailCount() const { return failed; }
-		/**
-		 * Get the worst error in a case where the algebraic solver did
-		 * not satisfy the error tolerance. This will be zero if
-		 * there were no failures of the algebraic solver.
-		 */
-		double getWorseError() const { return max_err; }
-		/// Do not override
-		void init(double* q)
-		{
-			init(q,a);
-		}
-		/// Do not override
-		void der_func(const double* q, double* dq)
-		{
-			solve(q);
-			der_func(q,a,dq);
-		}
-		/// Override only if you have no state event functions.
-		void state_event_func(const double* q, double* z)
-		{
-			solve(q);
-			state_event_func(q,a,z);
-		}
-		/// Override only if you have no time events.
-		double time_event_func(const double* q)
-		{
-			solve(q);
-			return time_event_func(q,a);
-		}
-		/// Do not override
-		void postStep(double* q)
-		{
-			solve(q);
-			postStep(q,a);
-		}
-		/// Do not override
-		void internal_event(double* q, const bool* state_event)
-		{
-			// The variable a was solved for in the post step
-			internal_event(q,a,state_event);
-			// Make sure the algebraic variables are consistent with q
-			solve(q);
-			postStep(q,a);
-		}
-		/// Do not override
-		void external_event(double* q, double e, const Bag<X>& xb)
-		{
-			// The variable a was solved for in the post step
-			external_event(q,a,e,xb);
-			// Make sure the algebraic variables are consistent with q
-			solve(q);
-			postStep(q,a);
-		}
-		/// Do not override
-		void confluent_event(double *q, const bool* state_event, const Bag<X>& xb)
-		{
-			// The variable a was solved for in the post step
-			confluent_event(q,a,state_event,xb);
-			// Make sure the algebraic variables are consistent with q
-			solve(q);
-			postStep(q,a);
-		}
-		/// Do not override
-		void output_func(const double *q, const bool* state_event, Bag<X>& yb)
-		{
-			// The variable a was solved for in the post step
-			output_func(q,a,state_event,yb);
-		}
-	protected:
-		/**
-		 * Solve the algebraic equations. This should
-		 * not usually need to be called by the derived class. An exception might
-		 * be where updated values for the algebraic variables are needed from
-		 * within an event function due to some discrete change in q or the
-		 * structure of the systems.
-		 */
-		void solve(const double* q);
-	private:
-		const int A, max_iters;
-		const double err_tol, alpha;
-		// Guess at the algebraic solution
-		double *a, *atmp;
-		// Guesses at g(y)-y
-		double* f[2];
-		// Direction
-		double* d;
-		// Maximum error in the wake of a failure
-		double max_err;
-		// Number of failures
-		int failed;
-};
-
-template <typename X>
-void dae_se1_system<X>::solve(const double* q)
-{
-	int iter_count = 0, alt, good;
-	double prev_err, err = 0.0, ee, beta, g2, alpha_tmp = alpha;
-	/**
-	 * Solve y=g(x,y) by the conjugate gradient method.
-	 * Method iterates on f(x,y)=g(x,y)-y to find
-	 * f(x,y)=0.
-	 */
-	_adevs_dae_se_1_system_solve_try_it_again:
-	alt = 0;
-	good = 1;
-	prev_err = DBL_MAX;
-	// First step by steepest descent
-	alg_func(q,a,f[alt]);
-	for (int i = 0; i < A; i++)
-	{
-		// Calculate f(x,y)
-		f[alt][i] -= a[i];
-		// First direction
-		d[i] = -f[alt][i];
-		// Make the move
-		atmp[i] = a[i];
-		a[i] += alpha_tmp*d[i];
-	}
-	// Otherwise, first guess by steepest descent
-	// Finish search by conjugate gradiant
-	while (iter_count < max_iters)
-	{
-		iter_count++;
-		err = 0.0;
-		// Calculate y = g(x,y) 
-		alg_func(q,a,f[good]);
-		// Check the quality of the solution
-		for (int i = 0; i < A; i++)
-		{
-			// Calculate f(x,y) 
-			f[good][i] -= a[i];
-			// Get the largest error 
-			ee = fabs(f[good][i]);
-			if (ee > err) err = ee;
-		}
-		// If the solution is good enough then return
-		if (err < err_tol) return;
-		// If the solution is not converging...
-		if (err > prev_err)
-		{
-			// Restore previous solution
-			for (int i = 0; i < A; i++)
-				a[i] = atmp[i];
-			// Restart with a new value for alpha
-			if (alpha_tmp < 0.0) alpha_tmp = -alpha_tmp;
-			else alpha_tmp *= -0.5;
-			goto _adevs_dae_se_1_system_solve_try_it_again;
-		}
-		prev_err = err;
-		// Calculate beta. See Strang's "Intro. to Applied Mathematics",
-		// pg. 379.
-		beta = g2 = 0.0;
-		for (int i = 0; i < A; i++)
-			g2 += f[alt][i]*f[alt][i];
-		for (int i = 0; i < A; i++)
-			beta += f[good][i]*(f[good][i]-f[alt][i]);
-		beta /= g2;
-		// Calculate a new guess at the solution
-		for (int i = 0; i < A; i++)
-		{
-			d[i] = beta*d[i]-f[good][i];
-			atmp[i] = a[i];
-			a[i] += alpha_tmp*d[i];
-		}
-		// Swap buffers
-		good = alt;
-		alt = (good+1)%2;
-	}
-	// Increment the failed count and worse case error if an 
-	// acceptible solution was not found.
-	failed++;
-	if (err > max_err)
-		max_err = err;
-}
-
-/**
- * This is the interface for numerical integrators that are to be used with the
- * Hybrid class.
- */
-template <typename X> class ode_solver
-{
-	public:
-		/**
-		 * Create and ode_solver that will integrate the der_func method of the
-		 * supplied ode_system.
-		 */
-		ode_solver(ode_system<X>* sys):sys(sys){}
-		/**
-		 * Take an integration step from state q of at most size h_lim and
-		 * return the step size that was actually used. Copy the result of
-		 * the integration step to q.
-		 */
-		virtual double integrate(double* q, double h_lim) = 0;
-		/**
-		 * Advance the system through exactly h units of time.
-		 */
-		virtual void advance(double* q, double h) = 0;
-		/// Destructor
-		virtual ~ode_solver(){}
-	protected:
-		/// The system of odes to be acted upon by the solver
-		ode_system<X>* sys;
-};
-
-/**
- * This is the interface for algorithms that detect state events in the trajectory
- * of an ode_system. The ode_solver provided to this class is used to compute
- * intermediate states during the detection process.
- */
-template <typename X> class event_locator
-{
-	public:
-		/**
-		 * The locator will use the der_func and state_event_func of the supplied
-		 * ode_system object.
-		 */
-		event_locator(ode_system<X>* sys):sys(sys){}
-		/**
-		 * Find the first state event in the interval [0,h] starting from
-		 * state qstart. The method returns true if an event is found,
-		 * setting the events flags to true if the corresponding z entry in
-		 * the state_event_func above triggered the event. The value of
-		 * h is overwritten with the event time, and the state of the model
-		 * at that time is copied to qend. The event finding method should
-		 * select an instant of time when the zero crossing function is zero or
-		 * has changed sign to trigger an event.
-		 */
-		virtual bool find_events(bool* events, const double *qstart, 
-				double* qend, ode_solver<X>* solver, double& h) = 0;
-		/// Destructor
-		virtual ~event_locator(){}
-	protected:
-		/// The system of odes to be acted upon by the event locator
-		ode_system<X>* sys;
-};
-
-/**
- * This Atomic model encapsulates an ode_system and numerical solvers for it.
- * Output from the Hybrid model is produced by the output_func method of the
- * ode_system whenever a state event or time event occurs. Internal, external,
- * and confluent events for the Hybrid model are computed with the corresponding
- * methods of the ode_system. The time advance of the Hybrid class ensures that
- * its internal events coincide with state and time events in the ode_system.
- */
-template <typename X, class T = double> class Hybrid:
-	public Atomic<X,T>
-{
-	public:
-		/**
-		 * Create and initialize a simulator for the system. All objects 
-		 * are adopted by the Hybrid object and are deleted when it is.
-		 */
-		Hybrid(ode_system<X>* sys, ode_solver<X>* solver,
-				event_locator<X>* event_finder):
-			sys(sys),solver(solver),event_finder(event_finder),
-			e_accum(0.0)
-		{
-			q = new double[sys->numVars()];
-			q_trial = new double[sys->numVars()];
-			event = new bool[sys->numEvents()+1];
-			event_exists = false;
-			sys->init(q_trial); // Get the initial state of the model
-			for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
-			tentative_step(); // Take the first tentative step
-		}
-		/// Get the value of the kth continuous state variable
-		double getState(int k) const { return q[k]; }
-		/// Get the array of state variables
-		const double* getState() const { return q; }
-		/// Get the system that this solver is operating on
-		ode_system<X>* getSystem() { return sys; }
-		/// Did a discrete event occur at the last state transition?
-		bool eventHappened() const { return event_happened; }
-		/**
-		 * Do not override this method. It performs numerical integration and
-		 * invokes the ode_system method for internal events as needed.
-		 */
-		void delta_int()
-		{
-			if (!missedOutput.empty())
-			{
-				missedOutput.clear();
-				return;
-			}
-			e_accum += ta();
-			// Execute any discrete events
-			event_happened = event_exists;
-			if (event_exists) // Execute the internal event
-			{
-				sys->internal_event(q_trial,event); 
-				e_accum = 0.0;
-			}
-			// Copy the new state vector to q
-			for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
-			tentative_step(); // Take a tentative step
-		}
-		/**
-		 * Do not override this method. It performs numerical integration and
-		 * invokes the ode_system for external events as needed.
-		 */
-		void delta_ext(T e, const Bag<X>& xb)
-		{
-			bool state_event_exists = false;
-			event_happened = true;
-			// Check that we have not missed a state event
-			if (event_exists)
-			{
-				for (int i = 0; i < sys->numVars(); i++)
-					q_trial[i] = q[i];
-				solver->advance(q_trial,e);
-				state_event_exists =
-					event_finder->find_events(event,q,q_trial,solver,e);
-				// We missed an event
-				if (state_event_exists)
-				{
-					output_func(missedOutput);
-					sys->confluent_event(q_trial,event,xb); 
-					for (int i = 0; i < sys->numVars(); i++)
-						q[i] = q_trial[i];
-				}
-			}
-			if (!state_event_exists)// We didn't miss an event
-			{
-				solver->advance(q,e); // Advance the state q by e
-				// Let the model adjust algebraic variables, etc. for the new state
-				sys->postStep(q);
-				// Process the discrete input
-				sys->external_event(q,e+e_accum,xb);
-			}
-			e_accum = 0.0;
-			// Copy the new state to the trial solution 
-			for (int i = 0; i < sys->numVars(); i++) q_trial[i] = q[i];
-			tentative_step(); // Take a tentative step
-		}
-		/**
-		 * Do not override. This method invokes the ode_system method
-		 * for confluent events as needed.
-		 */
-		void delta_conf(const Bag<X>& xb)
-		{
-			if (!missedOutput.empty())
-			{
-				missedOutput.clear();
-				if (sigma > 0.0) event_exists = false;
-			}
-			// Execute any discrete events
-			event_happened = true;
-			if (event_exists) 
-				sys->confluent_event(q_trial,event,xb); 
-			else sys->external_event(q_trial,e_accum+ta(),xb);
-			e_accum = 0.0;
-			// Copy the new state vector to q
-			for (int i = 0; i < sys->numVars(); i++) q[i] = q_trial[i];
-			tentative_step(); // Take a tentative step 
-		}
-		/// Do not override.
-		T ta()
-		{
-			if (missedOutput.empty()) return sigma;
-			else return 0.0;
-		}
-		/// Do not override. Invokes the ode_system output function as needed.
-		void output_func(Bag<X>& yb)
-		{
-			if (!missedOutput.empty())
-			{
-				typename Bag<X>::iterator iter = missedOutput.begin();
-				for (; iter != missedOutput.end(); iter++)
-					yb.insert(*iter);
-				if (sigma == 0.0) // Confluent event
-					sys->output_func(q_trial,event,yb);
-			}
-			else
-			{
-				// Let the model adjust algebraic variables, etc. for the new state
-				sys->postStep(q_trial);
-				if (event_exists)
-					sys->output_func(q_trial,event,yb);
-			}
-		}
-		/// Do not override. Invokes the ode_system gc_output method as needed.
-		void gc_output(Bag<X>& gb) { sys->gc_output(gb); }
-		/// Destructor deletes everything.
-		virtual ~Hybrid()
-		{
-			delete [] q; delete [] q_trial; delete [] event;
-			delete event_finder; delete solver; delete sys;
-		}
-	private:
-		ode_system<X>* sys; // The ODE system
-		ode_solver<X>* solver; // Integrator for the ode set
-		event_locator<X>* event_finder; // Event locator
-		double sigma; // Time to the next internal event
-		double *q, *q_trial; // Current and tentative states
-		bool* event; // Flags indicating the encountered event surfaces
-		bool event_exists; // True if there is at least one event
-		bool event_happened; // True if a discrete event in the ode_system took place
-		double e_accum; // Accumlated time between discrete events
-		Bag<X> missedOutput; // Output missed at an external event
-		// Execute a tentative step and calculate the time advance function
-		void tentative_step()
-		{
-			// Check for a time event
-			double time_event = sys->time_event_func(q);
-			// Integrate up to that time at most
-			double step_size = solver->integrate(q_trial,time_event);
-			// Look for state events inside of the interval [0,step_size]
-			bool state_event_exists =
-				event_finder->find_events(event,q,q_trial,solver,step_size);
-			// Find the time advance and set the time event flag
-			sigma = std::min<double>(step_size,time_event);
-			event[sys->numEvents()] = time_event <= sigma;
-			event_exists = event[sys->numEvents()] || state_event_exists;
-			sys->postTrialStep(q);
-		}
-};
-
-} // end of namespace
-
-#endif

+ 0 - 311
simulators/adevs-3.3/include/adevs_models.h

@@ -1,311 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_models_h_
-#define __adevs_models_h_
-#include "adevs_time.h"
-#include "adevs_bag.h"
-#include "adevs_set.h"
-#include "adevs_exception.h"
-#include <cstdlib>
-
-namespace adevs
-{
-
-/*
- * Declare network and atomic model so types can be used as the type of
- * parent in the basic Devs model and for type ID functions.  
- */
-template <typename X, typename T> class Network;
-template <typename X, typename T> class Atomic;
-template <typename X, typename T> class MealyAtomic;
-template <typename X, typename T> class Schedule;
-template <typename X, typename T> class Simulator;
-
-/**
- * The Devs class provides basic operations for all devs models.
- * The model I/O type is set by the template argument X. The 
- * type to be used for time is set with the template argument
- * T. The default type for time is double.
- */
-template <typename X, typename T = double> class Devs
-{
-	public:
-		/// Default constructor.
-		Devs():
-		parent(NULL)
-		{
-		}
-		/// Destructor.
-		virtual ~Devs()
-		{
-		}
-		/**
-		 * Returns NULL if this is not a network model; returns a pointer to
-		 * itself otherwise. This method is used to avoid a relatively expensive
-		 * dynamic cast.
-		 */
-		virtual Network<X,T>* typeIsNetwork() { return NULL; }
-		/// Returns NULL if this is not an atomic model; returns itself otherwise.
-		virtual Atomic<X,T>* typeIsAtomic() { return NULL; }
-		/// Returns NULL if this is not a mealy atomic model; returns itself otherwise.
-		virtual MealyAtomic<X,T>* typeIsMealyAtomic() { return NULL; }
-		/**
-		 * Get the model that contains this model as a component.  Returns
-		 * NULL if this model is at the top of the hierarchy.
-		 */
-		const Network<X,T>* getParent() const { return parent; }
-		/// Get the model that contains this model as a component.
-		Network<X,T>* getParent() { return parent; }
-		/**
-		 * Assign a new parent to this model. Network model's should always
-		 * call this method to make themselves the parent of their components.
-		 * If the parent is not set correctly, then the event routing algorithm
-		 * in the simulator will fail.
-		 */
-		void setParent(Network<X,T>* parent) { this->parent = parent; }
-		/**
-		 * This is the structure transition function, which is evaluated following
-		 * every change of the model's state. It should return true
-		 * if a structure change is to occur, and false otherwise. False is the
-		 * default return value.
-		 * This method is used by the simulator to limit the execution
-		 * of potentially expensive structure changes. 
-		 * If the return value is true, then the parent's model_transition()
-		 * will also be evaluated. For network models, the model_transition() function is
-		 * preceded and anteceded by a call to getComponents(). The difference
-		 * of these two sets is used to determine if any models were added or removed
-		 * as part of the model transition.
-		 */
-		virtual bool model_transition() { return false; }
-	private:
-		Network<X,T>* parent;
-};
-
-/**
- * Event objects are used for routing within a network model,
- * for notifying event listeners of output events, and for injecting
- * input into a running simulation.
- */
-template <typename X, typename T = double> class Event
-{
-	public:
-		/// Constructor.  Sets the model to NULL.
-		Event():
-		model(NULL),
-		value()
-		{
-		}
-		/**
-		 * Constructor sets the model and value. The input into a
-		 * Simulator and in a network's routing method,
-		 * the model is the target of the input value.
-		 * In a callback to an event listener, the model is the
-		 * source of the output value. 
-		 */
-		Event(Devs<X,T>* model, const X& value):
-		model(model),
-		value(value)
-		{
-		}
-		/// Copy constructor.
-		Event(const Event<X,T>& src):
-		model(src.model),
-		value(src.value)
-		{
-		}
-		/// Assignment operator.
-		const Event<X,T>& operator=(const Event<X,T>& src)
-		{
-			model = src.model;
-			value = src.value;
-			return *this;
-		}
-		/// The model associated with the event.
-		Devs<X,T>* model;
-		/// The value associated with the event.
-		X value;
-		/// Destructor
-		~Event()
-		{
-		}
-};
-
-/**
- * Base type for all atomic DEVS models.
- */
-template <typename X, typename T = double> class Atomic: public Devs<X,T>
-{
-	public:
-		/// The constructor should place the model into its initial state.
-		Atomic():
-			Devs<X,T>(),
-			tL(adevs_zero<T>()),
-			q_index(0), // The Schedule requires this to be zero
-			proc(-1),
-			x(NULL),
-			y(NULL)
-		{
-		}
-		/// Internal transition function.
-		virtual void delta_int() = 0;
-		/**
-		 * External transition function.
-		 * @param e Time elapsed since the last change of state
-		 * @param xb Input for the model.
-		 */  
-		virtual void delta_ext(T e, const Bag<X>& xb) = 0;
-		/**
-		 * Confluent transition function.
-		 * @param xb Input for the model.
-		 */
-		virtual void delta_conf(const Bag<X>& xb) = 0;
-		/**
-		 * Output function.  Output values should be added to the bag yb.
-		 * @param yb Empty bag to be filled with the model's output
-		 */
-		virtual void output_func(Bag<X>& yb) = 0;
-		/**
-		 * Time advance function. adevs_inf<T>() is used for infinity.
-		 * @return The time to the next internal event
-		 */
-		virtual T ta() = 0;
-		/**
-		 * Garbage collection function.  The objects in g are
-		 * no longer in use by the simulation engine and should be disposed of. 
-`		 * Note that the elements in g are only those objects produced as
-		 * output by this model.
-		 */
-		virtual void gc_output(Bag<X>& g) = 0;
-		/// Destructor.
-		virtual ~Atomic(){}
-		/// Returns a pointer to this model.
-		Atomic<X,T>* typeIsAtomic() { return this; }
-	protected:
-		/**
-		 * Get the last event time for this model. This is 
-		 * provided primarily for use with the backwards compatibility
-		 * module and should not be relied on. It is likely to be
-		 * removed in later versions of the code.
-		 */
-		T getLastEventTime() const { return tL; }
-
-	private:
-
-		friend class Simulator<X,T>;
-		friend class Schedule<X,T>;
-
-		// Time of last event
-		T tL;
-		// Index in the priority queue
-		unsigned int q_index;
-		// Thread assigned to this model
-		int proc;
-		// Input and output event bags
-		Bag<X> *x, *y;
-};
-
-/**
- * This is a Mealy type atomic model where its output
- * may depend on its input. Mealy machines cannot be
- * connected to other Mealy machines. An exception
- * will be generated by the Simulator if you attempt
- * to do so.
- */
-
-template <typename X, typename T = double> class MealyAtomic:
-	public Atomic<X,T>
-{
-	public:
-		MealyAtomic<X,T>():Atomic<X,T>(),imm(false){}
-		MealyAtomic<X,T>* typeIsMealyAtomic() { return this; }
-		/**
-		 * Produce output at e < ta(q) in response to xb.
-		 * This is output preceding an external event.
-		 */
-		virtual void output_func(T e, const Bag<X>& xb, Bag<X>& yb) = 0;
-		/**
-		 * Produce output at e = ta(q) in response to xb.
-		 * This is output preceding a confluent event.
-		 */
-		virtual void output_func(const Bag<X>& xb, Bag<X>& yb) = 0;
-		virtual ~MealyAtomic(){}
-
-	private:
-
-		friend class Simulator<X,T>;
-
-		bool imm;
-};
-
-/**
- * Base class for DEVS network models.
- */
-template <typename X, typename T = double> class Network: public Devs<X,T>
-{
-	public:
-		/// Constructor.
-		Network():
-		Devs<X,T>()
-		{
-		}
-		/**
-		 * This method should fill the
-		 * set c with all the Network's components, excluding the 
-		 * Network model itself.
-		 * @param c An empty set to the filled with the Network's components.
-		 */
-		virtual void getComponents(Set<Devs<X,T>*>& c) = 0;
-		/**
-		 * This method is called by the Simulator to route an output value
-		 * produced by a model. This method should fill the bag r
-		 * with Events that point to the target model and carry the value
-		 * to be delivered to the target. The target may be a component 
-		 * of the Network or the Network itself, the latter causing the
-		 * Network to produce an output.
-		 * @param model The model that produced the output value
-		 * @param value The output value produced by the model
-		 * @param r A bag to be filled with (target,value) pairs
-		 */
-		virtual void route(const X& value, Devs<X,T>* model, Bag<Event<X,T> >& r) = 0;
-		/**
-		 * Destructor.  This destructor does not delete any component models.
-		 * Any necessary cleanup should be done by the derived class.
-		 */
-		virtual ~Network()
-		{
-		}
-		/// Returns a pointer to this model.
-		Network<X,T>* typeIsNetwork() { return this; }
-};
-
-} // end of namespace
-
-#endif

+ 0 - 95
simulators/adevs-3.3/include/adevs_poly.h

@@ -1,95 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef _adevs_poly_h_
-#define _adevs_poly_h_
-#include <cstdlib>
-
-namespace adevs
-{
-    /**
-     * This class implements Lagrange interpolating
-     * polynomials of arbitrary order for functions of
-     * a single variable. This can be 
-     * useful in many discrete event simulations where
-     * tabular values, possible produced by discrete time
-     * calculations, need to be interpolated for use
-     * in a discrete event system. GDEVS is one particular
-     * example of this.
-     */
-    class InterPoly
-    {
-	public:
-	    /**
-	     * Construct a polynomial to interpolate
-	     * a function u(t). The u- values
-	     * are the dependent variable and t- the independent
-	     * variables.
-	     */
-	    InterPoly(const double* u, const double* t, unsigned int n);
-		/**
-		 * Construct a polynomial to interpolate u(t) with data points
-		 * that are regularly spaced in time from an offset t0
-		 */
-		InterPoly(const double* u, double dt, unsigned int n, double t0 = 0.0);
-		/**
-		 * Assign new values to the data set. If t is NULL, then
-		 * only new u values will be assigned and the old t data is
-		 * kept.
-		 */
-		void setData(const double* u, const double* t = NULL);
-	    /**
-	     * Get the interpolated value at t
-	     */
-	    double interpolate(double t) const;
-	    /**
-	     * Overloaded operator for the interpolate method
-	     */
-	    double operator()(double t) const;
-	    /**
-	     * Approximate the function derivative at t
-	     */
-	    double derivative(double t) const;
-	    /**
-	     * Destructor
-	     */
-	    ~InterPoly();
-	private:
-	    InterPoly(){}
-	    InterPoly(const InterPoly&){}
-	    void operator=(const InterPoly&){}
-
-	    double* tdat;
-	    double* udat;
-	    unsigned int n;
-    };
-}
-
-#endif

+ 0 - 233
simulators/adevs-3.3/include/adevs_rand.h

@@ -1,233 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_rand_h_
-#define __adevs_rand_h_
-#include "adevs.h"
-#include <cstdlib>
-
-namespace adevs
-{
-
-/**
- * The random_seq class is an abstract interface to a random sequence
- * generator.
- */
-class random_seq 
-{
-	public:
-		/// Set the seed for the random number generator
-		virtual void set_seed(unsigned long seed) = 0;
-		/// Get the next double uniformly distributed in [0, 1]
-		virtual double next_dbl() = 0;
-		/// Copy the random number generator
-		virtual random_seq* copy() const = 0;
-		/// Get the next unsigned long
-		virtual unsigned long next_long() = 0;
-		/// Destructor
-		virtual ~random_seq(){}
-};
-
-/**
- * The crand class provides random number sequences using the standard
- * C rand_r() function. Each instance of crand generates its own random
- * number sequence, and the clone method saves the state of the random
- * number generator. This class can be used in parallel simulations. 
- */
-class crand: public random_seq 
-{
-	public:
-		/// Create a generator with the default seed
-		crand():seedp(0){}
-		/// Copy constructor
-		crand(const crand& src):seedp(src.seedp){}
-		/// Create a generator with the given seed
-		crand(unsigned long seed):seedp((unsigned int)seed){}
-		/// Set the seed for the random number generator
-		void set_seed(unsigned long seed) { seedp = (unsigned int)seed; }
-		/// Get the next double uniformly distributed in [0, 1]
-		double next_dbl()
-		{
-			#ifdef _WIN32
-			return ((double)next_long()/(double)UINT_MAX);
-			#else
-			return ((double)next_long()/(double)RAND_MAX);
-			#endif
-		}
-		/// Get the next unsigned long
-		unsigned long next_long();
-		/// Copy the random number generator
-		random_seq* copy() const { return new crand(*this); }
-		/// Destructor
-		~crand(){}
-	private:
-		unsigned int seedp;
-};
-
-/**
- * <p>The rv class provides a random variable based on a selectable
- * implementation.  By default, this implementation is crand.
- * I recommend that you find a modern random variate generator,
- * such as the ones included in the new C++ standards,
- * rather than use the one here.</p>
- * <p>The assortment of random variable types was contributed by
- * Alex Cave (who, at the time, was with the Intelligent 
- * Systems Automation Group in the School of Engineering at
- * Deakin University).</p>
- */
-class rv 
-{
-	public:
-		/// Create a random variable with the default implementation.
-		rv (unsigned long seed = 1);
-		/**
-		 * Create a random variable with the desired implementation.  The
-		 * implementation class is adopted by the rv.
-		 */
-		rv(random_seq* rand);
-		/// Copy constructor relies on copy method of underlying stream.
-		rv(const rv& src);
-		/// Assignment operator relies on copy method of underlying stream.
-		const rv& operator=(const rv& src);
-		/// See the random number generator implementation
-		void set_seed(unsigned long seed);
-		/// Get a raw value from the underlying random number generator
-		unsigned long next_long();
-		/// Sample a triangular distribution with minimum a, maximum b,
-		/// and mode c.
-		double triangular(double a, double b, double c);
-		/// Sample a uniform distribution in the range [a, b]
-		double uniform(double a, double b);
-		/**
-		 * Sample a normally distributed random variable with mean m and 
-		 * standard deviation s.
-		 */
-		double normal(double m, double s);
-		/**
-		 * return a negative exponentially distributed random number with
-		 * the mean as parameter
-		 */
-		double exponential(double a);
-		/**
-		 * return a hyperexponentially distributed random number with
-		 * the means as parameters to two exponentially distributed variates,
-		 * the first with a chance of p of being generated, the second with a
-		 * chance of 1-p.
-		 */
-		double hyperexponential(double p,double a,double b);
-		/// Return a laplace number with the given parameter
-		double laplace(double a);
-		/// Sample a chisquare random variable with n degrees of freedom
-		double chisquare(unsigned int n);
-		/// Sample a student-t random variable
-		double student(unsigned int n);
-		/// Sample a lognormal random variable
-		double lognormal(double a,double b);
-		/// Sample an erlang distribution
-		double erlang(unsigned int n,double a);
-		/// Sample a gamma random variable
-		double gamma(double a,double b);
-		/// Sample a beta random variable
-		double beta(double a,double b);
-		/// Sample a F-distributed random variable
-		double fdistribution(unsigned int n,unsigned int m);
-		/// Sample a Poisson random variable
-		double poisson(double a);
-		/// Sample a geometric random variable with event probability p
-		double geometric(double p);
-		/**
-		 * return a variate from the hypergeometric distribution with m the
-		 * population, p the chance on success and n the number of items drawn
-		 */
-		double hypergeometric(unsigned int m,unsigned int n,double p);
-		/// Sample a weibull random variable
-		double weibull(double a,double b);
-		/**
-		 *  An event count for a binomial distribution with event
-		 *  probability p and n the number of trials
-		 */ 
-		double binomial(double p,unsigned int n);
-		/**
-		 * return a random variable with probabilty of success equal to p
-		 * and n as the number of successes
-		 */
-		double negativebinomial(double p,unsigned int n);
-		/// Sample a triangular random variable
-		double triangular(double a);
-		/// return TRUE with probability p and FALSE with probability 1-p
-		bool probability(double p);
-		/// Sample a lognormal gamma random variable
-		double lngamma(double xx);
-		/// Destructor
-		~rv();
-	private:	
-		random_seq* _impl;
-		typedef enum 
-		{
-			NDURATION,
-			NCOUNT,
-			EMPTY,
-			NDELAY,
-			ADDTOQ,
-			EMPTYQ,
-			HNCLMS,
-			HMODE,
-			PROBVAL,
-			ERRUNIFORM,
-			ERRNORMAL,
-			ERRLOGNORM,
-			ERRTRIANG,
-			ERRGAMMA,
-			ERRBETA,
-			ERREXPONENT,
-			ERRERLANG,
-			ERRHYPGEO,
-			NULLEV,
-			NOHISTO,
-			INITERR,
-			AMODE,
-			HFORM,
-			ERRFILE,
-			SAMPLE,
-			FRACTION,
-			LEVEL,
-			SCAN,
-			SUPPRESS,
-			SEED
-		} errorType;
-
-		void err(errorType n);
-};
-
-} // end of namespace
-
-#endif
-
-

+ 0 - 171
simulators/adevs-3.3/include/adevs_rk_45.h

@@ -1,171 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef _adevs_rk_45_h_
-#define _adevs_rk_45_h_
-#include "adevs_hybrid.h"
-#include <cmath>
-
-namespace adevs
-{
-
-/**
- * This ode_solver implements a 4th/5th order integrator that adjust
- * its step size to control error.
- */
-template <typename X> class rk_45:
-	public ode_solver<X>
-{
-	public:
-		/**
-		 * The integrator will adjust its step size to maintain a per
-		 * step error less than err_tol, and will use a step size
-		 * strictly less than h_max.
-		 */
-		rk_45(ode_system<X>* sys, double err_tol, double h_max);
-		/// Destructor
-		~rk_45();
-		double integrate(double* q, double h_lim);
-		void advance(double* q, double h);
-	private:
-		double *dq, // derivative
-			   *qq, // trial solution
-			   *t,  // temporary variables for computing stages
-			   *k[6]; // the six RK stages
-		const double err_tol; // Error tolerance
-		const double h_max; // Maximum time step
-		double h_cur; // Previous successful step size
-		// Compute a trial step of size h, store the result in qq, and return the error
-		double trial_step(double h);
-};
-
-template <typename X>
-rk_45<X>::rk_45(ode_system<X>* sys, double err_tol, double h_max):
-	ode_solver<X>(sys),err_tol(err_tol),h_max(h_max),h_cur(h_max)
-{
-	for (int i = 0; i < 6; i++)
-		k[i] = new double[sys->numVars()];
-	dq = new double[sys->numVars()];
-	qq = new double[sys->numVars()];
-	t = new double[sys->numVars()];
-}
-
-template <typename X>
-rk_45<X>::~rk_45()
-{
-	delete [] dq;
-	delete [] t;
-	for (int i = 0; i < 6; i++)
-		delete [] k[i];
-}
-
-template <typename X>
-void rk_45<X>::advance(double* q, double h)
-{
-	double dt;
-	while ((dt = integrate(q,h)) < h) h -= dt;
-}
-
-template <typename X>
-double rk_45<X>::integrate(double* q, double h_lim)
-{
-	// Initial error estimate and step size
-	double err = DBL_MAX,
-		   h = std::min<double>(h_cur*1.1,std::min<double>(h_max,h_lim));
-	for (;;) {
-		// Copy q to the trial vector
-		for (int i = 0; i < this->sys->numVars(); i++) qq[i] = q[i];
-		// Make the trial step which will be stored in qq
-		err = trial_step(h);
-		// If the error is ok, then we have found the proper step size
-		if (err <= err_tol) {
-			if (h_cur <= h_lim) h_cur = h;
-			break;
-		}
-		// Otherwise shrink the step size and try again
-		else {
-			double h_guess = 0.8*pow(err_tol*pow(h,4.0)/fabs(err),0.25);
-			if (h < h_guess) h *= 0.8;
-			else h = h_guess;
-		}
-	}
-	// Copy the trial solution to q and return the step size that was selected
-	for (int i = 0; i < this->sys->numVars(); i++) q[i] = qq[i];
-	return h;
-}
-
-template <typename X>
-double rk_45<X>::trial_step(double step)
-{
-	// Compute k1
-	this->sys->der_func(qq,dq); 
-	for (int j = 0; j < this->sys->numVars(); j++) k[0][j] = step*dq[j];
-	// Compute k2
-	for (int j = 0; j < this->sys->numVars(); j++) t[j] = qq[j] + 0.5*k[0][j];
-	this->sys->der_func(t,dq);
-	for (int j = 0; j < this->sys->numVars(); j++) k[1][j] = step*dq[j];
-	// Compute k3
-	for (int j = 0; j < this->sys->numVars(); j++) t[j] = qq[j] + 0.25*(k[0][j]+k[1][j]);
-	this->sys->der_func(t,dq);
-	for (int j = 0; j < this->sys->numVars(); j++) k[2][j] = step*dq[j];
-	// Compute k4
-	for (int j = 0; j < this->sys->numVars(); j++) t[j] = qq[j] - k[1][j] + 2.0*k[2][j];
-	this->sys->der_func(t,dq);
-	for (int j = 0; j < this->sys->numVars(); j++) k[3][j] = step*dq[j];
-	// Compute k5
-	for (int j = 0; j < this->sys->numVars(); j++)
-		t[j] = qq[j] + (7.0/27.0)*k[0][j] + (10.0/27.0)*k[1][j] + (1.0/27.0)*k[3][j];
-	this->sys->der_func(t,dq);
-	for (int j = 0; j < this->sys->numVars(); j++) k[4][j] = step*dq[j];
-	// Compute k6
-	for (int j = 0; j < this->sys->numVars(); j++)
-		t[j] = qq[j] + (28.0/625.0)*k[0][j] - 0.2*k[1][j] + (546.0/625.0)*k[2][j]
-			+ (54.0/625.0)*k[3][j] - (378.0/625.0)*k[4][j];
-	this->sys->der_func(t,dq);
-	for (int j = 0 ; j < this->sys->numVars(); j++) k[5][j] = step*dq[j];
-	// Compute next state and the approximate error
-	double err = 0.0;
-	for (int j = 0; j < this->sys->numVars(); j++)
-	{
-		// Next state
-		qq[j] += (1.0/24.0)*k[0][j] + (5.0/48.0)*k[3][j] + 
-			(27.0/56.0)*k[4][j] + (125.0/336.0)*k[5][j];
-		// Componennt wise maximum of the approximate error
-		err = std::max(err,
-				fabs(k[0][j]/8.0+2.0*k[2][j]/3.0+k[3][j]/16.0-27.0*k[4][j]/56.0
-					-125.0*k[5][j]/336.0));
-	}
-	// Return the error
-	return err;
-}
-
-} // end of namespace
-#endif
-

+ 0 - 240
simulators/adevs-3.3/include/adevs_sched.h

@@ -1,240 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_schedule_h_
-#define __adevs_schedule_h_
-#include "adevs_time.h"
-#include "adevs_models.h"
-#include <cfloat>
-#include <cstdlib>
-#include <list>
-
-using namespace std;
-
-namespace adevs
-{
-
-/**
- * This is a binary heap for scheduling Atomic models. The Schedule uses 
- * the q_index attribute of the Atomic model to keep track of the object's
- * position in the heap. Therefore, a model can be put into only one Schedule.
- * Please observe that the q_index value for a model must be initialized
- * to zero before it is placed into the heap for the first time.
- */
-template <class X, class T = double> class Schedule
-{
-	public:
-		/**
-		 * An interface for objects that want to visit the imminent models
-		 * in the schedule.
-		 */
-		class ImminentVisitor
-		{
-			public:
-				virtual void visit(Atomic<X,T>* model) = 0;
-				virtual ~ImminentVisitor(){}
-		};
-		/// Creates a scheduler with the default or specified initial capacity.
-		Schedule(unsigned int capacity = 100):
-		capacity(capacity),size(0),heap(new heap_element[capacity])
-		{
-			heap[0].priority = adevs_sentinel<T>(); // This is a sentinel value
-		}
-		/// Get the model at the front of the queue.
-		Atomic<X,T>* getMinimum() const { return heap[1].item; }
-		/// Get the time of the next event.
-		T minPriority() const { return heap[1].priority; }
-		/// Visit the imminent models.
-		void visitImminent(ImminentVisitor* visitor) const {
-			visitImminent(visitor,1);
-		}
-		/// Remove the model at the front of the queue.
-		void removeMinimum();
-		/// Add, remove, or move a model as required by its priority.
-		void schedule(Atomic<X,T>* model, T priority);
-		/// Returns true if the queue is empty, and false otherwise.
-		bool empty() const { return size == 0; }
-		/// Get the number of elements in the heap.
-		unsigned int getSize() const { return size; }
-		/// Destructor.
-		~Schedule() { delete [] heap; }
-	private:
-		// Definition of an element in the heap.
-		struct heap_element 
-		{
-			Atomic<X,T>* item;
-			T priority;
-			// Constructor initializes the item and priority
-			heap_element():
-				item(NULL),priority(adevs_inf<T>()){}
-		};
-		unsigned int capacity, size;
-		heap_element* heap;
-		/// Double the schedule capacity
-		void enlarge();
-		/// Move the item at index down and return its new position
-		unsigned int percolate_down(unsigned int index, T priority);
-		/// Move the item at index up and return its new position
-		unsigned int percolate_up(unsigned int index, T priority);
-		/// Visit the imminent set recursively
-		void visitImminent(ImminentVisitor* visitor, unsigned int root) const;
-};
-
-template <class X, class T>
-void Schedule<X,T>::visitImminent(typename Schedule<X,T>::ImminentVisitor* visitor,
-		unsigned int root) const
-{
-	// Stop if the bottom is reached or the next priority is not equal to the minimum
-	if (root > size || heap[1].priority < heap[root].priority)
-		return;
-	visitor->visit(heap[root].item);
-	// Look for more imminent models in the left sub-tree
-	visitImminent(visitor,root*2);
-	// Look in the right sub-tree
-	visitImminent(visitor,root*2+1);
-}
-
-template <class X, class T>
-void Schedule<X,T>::removeMinimum()
-{
-	// Don't do anything if the heap is empty
-	if (size == 0) return;
-	size--;
-	// Set index to 0 to show that this model is not in the schedule
-	heap[1].item->q_index = 0;
-	// If the schedule is empty, set the priority of the last element to adevs_inf
-	if (size == 0)
-	{
-		heap[1].priority = adevs_inf<T>();
-		heap[1].item = NULL;
-	}
-	// Otherwise fill the hole left by the deleted model
-	else
-	{
-		unsigned int i = percolate_down(1,heap[size+1].priority);
-		heap[i] = heap[size+1];
-		heap[i].item->q_index = i;
-		heap[size+1].item = NULL;
-	}
-}
-
-template <class X, class T>
-void Schedule<X,T>::schedule(Atomic<X,T>* model, T priority)
-{
-	// If the model is in the schedule
-	if (model->q_index != 0)
-	{
-		// Remove the model if the next event time is infinite
-		if (!(priority < adevs_inf<T>())) 
-		{
-			// Move the item to the top of the heap
-			T min_priority = minPriority();
-			model->q_index = percolate_up(model->q_index,min_priority);
-			heap[model->q_index].priority = min_priority;
-			heap[model->q_index].item = model;
-			// Remove it and return
-			removeMinimum();
-			return;
-		}
-		// Decrease the time to next event
-		else if (priority < heap[model->q_index].priority)
-			model->q_index = percolate_up(model->q_index,priority);
-		// Increase the time to next event
-		else if (heap[model->q_index].priority < priority)
-			model->q_index = percolate_down(model->q_index,priority);
-		// Don't do anything if the priority is unchanged
-		else return;
-		heap[model->q_index].priority = priority;
-		heap[model->q_index].item = model;
-	}
-	// If it is not in the schedule and the next event time is
-	// not at infinity, then add it to the schedule
-	else if (priority < adevs_inf<T>())
-	{
-		// Enlarge the heap to hold the new model
-		size++;
-		if (size == capacity) enlarge();
-		// Find a slot and put the item into it
-		model->q_index = percolate_up(size,priority);
-		heap[model->q_index].priority = priority;
-		heap[model->q_index].item = model;
-	}
-	// Otherwise, the model is not enqueued and has no next event
-}
-
-template <class X, class T>
-unsigned int Schedule<X,T>::percolate_down(unsigned int index, T priority)
-{
-	unsigned int child;
-	for (; index*2 <= size; index = child) 
-	{
-		child = index*2;
-		if (child != size && heap[child+1].priority < heap[child].priority) 
-		{
-			child++;
-		}
-		if (heap[child].priority < priority) 
-		{
-			heap[index] = heap[child];
-			heap[index].item->q_index = index;
-		}
-		else break;
-	}
-	return index;
-}
-
-template <class X, class T>
-unsigned int Schedule<X,T>::percolate_up(unsigned int index, T priority)
-{
-	// Position 0 has priority -1 and this method is always called
-	// with priority >= 0 and index > 0. 
-	while (priority <= heap[index/2].priority) 
-	{
-		heap[index] = heap[index/2];
-		heap[index].item->q_index = index;
-		index /= 2;
-	}
-	return index;
-}
-
-template <class X, class T>
-void Schedule<X,T>::enlarge()
-{
-	heap_element* rheap = new heap_element[capacity*2];
-	for (unsigned int i = 0; i < capacity; i++)
-		rheap[i] = heap[i];
-	capacity *= 2;
-	delete [] heap;
-	heap = rheap;
-}
-
-} // end of namespace
-
-#endif

+ 0 - 59
simulators/adevs-3.3/include/adevs_set.h

@@ -1,59 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef _adevs_set_h
-#define _adevs_set_h
-#include <set>
-#include <algorithm>
-
-namespace adevs
-{
-
-/**
- * This Set is just an STL set. 
- */
-template <class T> class Set: public std::set<T>
-{
-};
-
-/// Set difference operator. Returns the set A-B.
-template <class T> 
-void set_assign_diff(Bag<T>& result, const Set<T>& A, const Set<T>& B)
-{
-	typename Set<T>::const_iterator iter = A.begin();
-	for (; iter != A.end(); iter++)
-	{
-		if (B.find(*iter) == B.end()) result.insert(*iter);
-	}
-}
-
-} // end of namespace
-
-#endif

+ 0 - 133
simulators/adevs-3.3/include/adevs_simpledigraph.h

@@ -1,133 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_simpledigraph_h_
-#define __adevs_simpledigraph_h_
-#include "adevs.h"
-#include <map>
-#include <set>
-#include <cstdlib>
-
-namespace adevs
-{
-
-/**
- * This is a very simple digraph model for connecting single input/single
- * output systems. Output generated by a component model is sent to all
- * components connected to it.
- */
-template <class VALUE, class T = double> class SimpleDigraph: 
-public Network<VALUE,T>
-{
-	public:
-		/// A component of the SimpleDigraph model
-		typedef Devs<VALUE,T> Component;
-
-		/// Construct a network without components.
-		SimpleDigraph():
-		Network<VALUE,T>()
-		{
-		}
-		/// Add a model to the network.
-		void add(Component* model);
-		/// Couple the source model to the destination model.  
-		void couple(Component* src, Component* dst);
-		/// Puts the network's set of components into c
-		void getComponents(Set<Component*>& c);
-		/// Route an event according to the network's couplings
-		void route(const VALUE& x, Component* model, 
-		Bag<Event<VALUE,T> >& r);
-		/// Destructor.  Destroys all of the component models.
-		~SimpleDigraph();
-
-	private:	
-		// The set of components
-		Set<Component*> models;
-		// Coupling information
-		std::map<Component*,Bag<Component*> > graph;
-};
-
-template <class VALUE, class T>
-void SimpleDigraph<VALUE,T>::add(Component* model)
-{
-	assert(model != this);
-	models.insert(model);
-	model->setParent(this);
-}
-
-template <class VALUE, class T>
-void SimpleDigraph<VALUE,T>::couple(Component* src, Component* dst) 
-{
-	if (src != this) add(src);
-	if (dst != this) add(dst);
-	graph[src].insert(dst);
-}
-
-template <class VALUE, class T>
-void SimpleDigraph<VALUE,T>::getComponents(Set<Component*>& c)
-{
-	c = models;
-}
-
-template <class VALUE, class T>
-void SimpleDigraph<VALUE,T>::
-route(const VALUE& x, Component* model, 
-Bag<Event<VALUE,T> >& r)
-{
-	// Find the list of target models and ports
-	typename std::map<Component*,Bag<Component*> >::iterator graph_iter;
-	graph_iter = graph.find(model);
-	// If no target, just return
-	if (graph_iter == graph.end()) return;
-	// Otherwise, add the targets to the event bag
-	Event<VALUE,T> event;
-	typename Bag<Component*>::iterator node_iter;
-	for (node_iter = (*graph_iter).second.begin();
-	node_iter != (*graph_iter).second.end(); node_iter++)
-	{
-		event.model = *node_iter;
-		event.value = x;
-		r.insert(event);
-	}
-}
-
-template <class VALUE, class T>
-SimpleDigraph<VALUE,T>::~SimpleDigraph()
-{ 
-	typename Set<Component*>::iterator i;
-	for (i = models.begin(); i != models.end(); i++)
-	{
-		delete *i;
-	}
-}
-
-} // end of namespace 
-
-#endif

+ 0 - 718
simulators/adevs-3.3/include/adevs_simulator.h

@@ -1,718 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_simulator_h_
-#define __adevs_simulator_h_
-#include "adevs_abstract_simulator.h"
-#include "adevs_models.h"
-#include "adevs_event_listener.h"
-#include "adevs_sched.h"
-#include "adevs_bag.h"
-#include "adevs_set.h"
-#include "object_pool.h"
-#include <cassert>
-#include <cstdlib>
-#include <iostream>
-#include <vector>
-
-namespace adevs
-{
-
-/**
- * This Simulator class implements the DEVS simulation algorithm.
- * Its methods throw adevs::exception objects if any of the DEVS model
- * constraints are violated (i.e., a negative time advance, a model
- * attempting to send an input directly to itself, or coupled Mealy
- * type systems).
- */
-template <class X, class T = double> class Simulator:
-	public AbstractSimulator<X,T>,
-	private Schedule<X,T>::ImminentVisitor
-{
-	public:
-		/**
-		 * Create a simulator for a model. The simulator
-		 * constructor will fail and throw an adevs::exception if the
-		 * time advance of any component atomic model is less than zero.
-		 * @param model The model to simulate
-		 */
-		Simulator(Devs<X,T>* model):
-			AbstractSimulator<X,T>(),
-			Schedule<X,T>::ImminentVisitor(),
-			io_up_to_date(false)
-		{
-			schedule(model,adevs_zero<T>());
-		}
-		/**
-		 * Get the model's next event time
-		 * @return The absolute time of the next event
-		 */
-		T nextEventTime()
-		{
-			return sched.minPriority();
-		}
-		/**
-		 * Execute the simulation cycle at time nextEventTime()
-		 * @return The updated simulation time
-		 */
-		T execNextEvent()
-		{
-			return computeNextState();
-		}
-		/**
-		 * Execute until nextEventTime() > tend.
-		 * @return The updated simulation time
-		 */
-		T execUntil(T tend)
-		{
-			T t = tend+adevs_epsilon<T>();
-			while (nextEventTime() <= tend 
-                   && nextEventTime() < adevs_inf<T>()) {
-				t = execNextEvent();
-            }
-			return t;
-		}
-		/**
-		 * Compute the output values of the imminent component models 
-		 * if these values have not already been computed.  This will
-		 * notify registered EventListeners as the outputs are produced. 
-		 */
-		void computeNextOutput();
-		/**
-		 * Compute the output value of the model in response to an input
-		 * at some time in lastEventTime() <= t <= nextEventTime().
-		 * This will notify registered EventListeners as the outputs
-		 * are produced. If this is the first call since the prior
-		 * state change with the given t, then the new output is computed.
-		 * Subsequent calls for the same time t simply
-		 * append to the input already supplied at time t.
-		 * @param input A bag of (input target,value) pairs
-		 * @param t The time at which the input takes effect
-		 */
-		void computeNextOutput(Bag<Event<X,T> >& input, T t);
-		/**
-		 * Apply the bag of inputs at time t and then compute the next model
-		 * states. Requires that lastEventTime() <= t <= nextEventTime().
-		 * This, in effect, implements the state transition function of 
-		 * the resultant model. If the output has already been computed
-		 * at time t, then the new input at t is simply appended to the
-		 * prior input. Otherwise, the old results are discarded and input
-		 * is calculated at the given time.
-		 * @param input A bag of (input target,value) pairs
-		 * @param t The time at which the input takes effect
-		 * @return The new, current simulation time
-		 */
-		T computeNextState(Bag<Event<X,T> >& input, T t);
-		/**
-		 * Compute the next state at the time at the time t and with
-		 * input supplied at the prior call to computeNextOutput
-		 * assuming no computeNextState has intervened. Assumes
-		 * t = nextEventTime() and input an empty bag if there was
-		 * no prior call to computeNextOutput.
-		 * @return The new, current simulation time
-		 */
-		T computeNextState();
-		/**
-		 * Deletes the simulator, but leaves the model intact. The model must
-		 * exist when the simulator is deleted.  Delete the model only after
-		 * the Simulator is deleted.
-		 */
-		~Simulator();
-		/**
-		 * Assign a model to the simulator. This has the same effect as passing
-		 * the model to the constructor.
-		 */
-		void addModel(Atomic<X,T>* model) 
-		{
-			schedule(model,adevs_zero<T>());
-		}
-	private:
-		// Bogus input bag for execNextEvent() method
-		Bag<Event<X,T> > bogus_input;
-		// The event schedule
-		Schedule<X,T> sched;
-		// List of models that are imminent or activated by input
-		Bag<Atomic<X,T>*> activated;
-		// Mealy systems that we need to process
-		bool allow_mealy_input, io_up_to_date;
-		T io_time;
-		Bag<MealyAtomic<X,T>*> mealy;
-		// Pools of preallocated, commonly used objects
-		object_pool<Bag<X> > io_pool;
-		object_pool<Bag<Event<X,T> > > recv_pool;
-		// Sets for computing structure changes.
-		Bag<Devs<X,T>*> added;
-		Bag<Devs<X,T>*> removed;
-		Set<Devs<X,T>*> next;
-		Set<Devs<X,T>*> prev;
-		// Model transition functions are evaluated from the bottom up!
-		struct bottom_to_top_depth_compare
-		{
-			bool operator()(const Network<X,T>* m1, const Network<X,T>* m2) const
-			{
-				unsigned long int d1 = 0, d2 = 0;
-				// Compute depth of m1
-				const Network<X,T>* m = m1->getParent();
-				while (m != NULL) 
-				{
-					d1++;
-					m = m->getParent();
-				}
-				// Compute depth of m2
-				m = m2->getParent();
-				while (m != NULL)
-				{
-					d2++;
-					m = m->getParent();
-				}
-				// Models at the same depth are sorted by name
-				if (d1 == d2) return m1 < m2;
-				// Otherwise, sort by depth
-				return d1 > d2;
-			}
-		};
-		struct top_to_bottom_depth_compare
-		{
-			bool operator()(const Devs<X,T>* m1, const Devs<X,T>* m2) const
-			{
-				unsigned long int d1 = 0, d2 = 0;
-				// Compute depth of m1
-				const Network<X,T>* m = m1->getParent();
-				while (m != NULL) 
-				{
-					d1++;
-					m = m->getParent();
-				}
-				// Compute depth of m2
-				m = m2->getParent();
-				while (m != NULL)
-				{
-					d2++;
-					m = m->getParent();
-				}
-				// Models at the same depth are sorted by name
-				if (d1 == d2) return m1 < m2;
-				// Otherwise, sort by depth
-				return d1 < d2;
-			}
-		};
-		std::set<Network<X,T>*,bottom_to_top_depth_compare> model_func_eval_set;
-		std::set<Devs<X,T>*,top_to_bottom_depth_compare> sorted_removed;
-		/**
-		 * Recursively add the model and its elements to the schedule 
-		 * using t as the time of last event.
-		 */
-		void schedule(Devs<X,T>* model, T t);
-		/// Route an event generated by the source model contained in the parent model.
-		void route(Network<X,T>* parent, Devs<X,T>* src, X& x);
-		/**	
-		 * Add an input to the input bag of an an atomic model. If the 
-		 * model is not already active , then this method adds the model to
-		 * the activated bag.
-		 */
-		void inject_event(Atomic<X,T>* model, X& value);
-		/**
-		 * Recursively remove a model and its components from the schedule 
-		 * and the imminent/activated bags
-		 */
-		void unschedule_model(Devs<X,T>* model);
-		/**
-		 * Delete any thing in the output bag, and return the input
-		 * and output bags to the pools.
-		 * Recursively clean up network model components.
-		 */
-		void clean_up(Devs<X,T>* model);
-		/**
-		 * Construct the complete descendant set of a network model and store it in s.
-		 */
-		void getAllChildren(Network<X,T>* model, Set<Devs<X,T>*>& s);
-		/**
-		 * Visit method inhereted from ImminentVisitor
-		 */
-		void visit(Atomic<X,T>* model);
-};
-
-template <class X, class T>
-void Simulator<X,T>::visit(Atomic<X,T>* model)
-{
-	assert(model->y == NULL);
-	// Mealy models are processed after the Moore models
-	if (model->typeIsMealyAtomic() != NULL)
-	{
-		model->typeIsMealyAtomic()->imm = true;
-		assert(model->y == NULL);
-		// May be in the mealy list because of a route call
-		if (model->x == NULL)
-			mealy.insert(model->typeIsMealyAtomic());
-		return;
-	}
-	model->y = io_pool.make_obj();
-	// Put it in the active list if it is not already there
-	if (model->x == NULL)
-		activated.insert(model);
-	// Compute output functions and route the events. The bags of output
-	// are held for garbage collection at a later time.
-	model->output_func(*(model->y));
-	// Route each event in y
-	for (typename Bag<X>::iterator y_iter = model->y->begin(); 
-		y_iter != model->y->end(); y_iter++)
-	{
-		route(model->getParent(),model,*y_iter);
-	}
-}
-
-template <class X, class T>
-void Simulator<X,T>::computeNextOutput(Bag<Event<X,T> >& input, T t)
-{
-	// Undo any prior output calculation at another time
-	if (io_up_to_date && !(io_time == t))
-	{
-		typename Bag<Atomic<X,T>*>::iterator iter;
-		for (iter = activated.begin(); iter != activated.end(); iter++)
-		{
-			clean_up(*iter);
-		}
-		activated.clear();
-	}
-	// Input and output happen at the current time.
-	io_time = t;
-	// Get the imminent Moore models from the schedule if we have not
-	// already done so.
-	allow_mealy_input = true;
-	if (t == sched.minPriority() && !io_up_to_date)
-		sched.visitImminent(this);
-	// Apply the injected inputs. 
-	for (typename Bag<Event<X,T> >::iterator iter = input.begin(); 
-		iter != input.end(); iter++)
-	{
-		Atomic<X,T>* amodel = (*iter).model->typeIsAtomic();
-		if (amodel != NULL)
-		{
-			inject_event(amodel,(*iter).value);
-		}
-		else
-		{
-			route((*iter).model->typeIsNetwork(),(*iter).model,(*iter).value);
-		}
-	}
-	// Only Moore models can influence Mealy models. 
-	allow_mealy_input = false;
-	// Iterate over activated Mealy models to calculate their output
-	for (typename Bag<MealyAtomic<X,T>*>::iterator m_iter = mealy.begin();
-		m_iter != mealy.end(); m_iter++)
-	{
-		MealyAtomic<X,T> *model = *m_iter;
-		assert(model->y == NULL);
-		model->y = io_pool.make_obj();
-		// Put it in the active set if it is not already there
-		if (model->x == NULL)
-			activated.insert(model);
-		// Compute output functions and route the events. The bags of output
-		// are held for garbage collection at a later time.
-		if (model->imm) // These are the imminent Mealy models
-		{
-			if (model->x == NULL)
-				model->typeIsAtomic()->output_func(*(model->y));
-			else
-				model->output_func(*(model->x),*(model->y));
-		}
-		else
-		{
-			assert(model->x != NULL);
-			// These are the Mealy models activated by input
-			model->output_func(sched.minPriority()-model->tL,*(model->x),*(model->y));
-		}
-	}
-	// Translate Mealy output to inputs for Moore models. The route method
-	// will throw an exception if an event is sent to a Mealy model.
-	for (typename Bag<MealyAtomic<X,T>*>::iterator m_iter = mealy.begin();
-		m_iter != mealy.end(); m_iter++)
-	{
-		MealyAtomic<X,T> *model = *m_iter;
-		// Route each event in y
-		for (typename Bag<X>::iterator y_iter = model->y->begin(); 
-			y_iter != model->y->end(); y_iter++)
-		{
-			route(model->getParent(),model,*y_iter);
-		}
-	}
-	mealy.clear();
-	io_up_to_date = true;
-}
-
-template<class X, class T>
-void Simulator<X,T>::computeNextOutput()
-{
-	computeNextOutput(bogus_input,sched.minPriority());
-}
-
-template <class X, class T>
-T Simulator<X,T>::computeNextState(Bag<Event<X,T> >& input, T t)
-{
-	computeNextOutput(input,t);
-	assert(io_time == t && io_up_to_date);
-	return computeNextState();
-}
-
-template <class X, class T>
-T Simulator<X,T>::computeNextState()
-{
-	if (!io_up_to_date)
-		computeNextOutput();
-	io_up_to_date = false;
-	T t = io_time, tQ = io_time + adevs_epsilon<T>();
-	/*
-	 * Compute the states of atomic models.  Store Network models that 
-	 * need to have their model transition function evaluated in a
-	 * special container that will be used when the structure changes are
-	 * computed.
-	 */
-	for (unsigned i = 0; i < activated.size(); i++)
-	{
-		Atomic<X,T>* model = activated[i];
-		// Internal event if no input
-		if (model->x == NULL)
-			model->delta_int();
-		// Confluent event if model is imminent and has input
-		else if (
-				(model->typeIsMealyAtomic() == NULL && model->y != NULL)
-				|| (model->typeIsMealyAtomic() != NULL && model->typeIsMealyAtomic()->imm)
-			)
-			model->delta_conf(*(model->x));
-		// External event if model is not imminent and has input
-		else
-			model->delta_ext(t-model->tL,*(model->x));
-		// Notify listeners 
-		this->notify_state_listeners(model,tQ);
-		// Check for a model transition
-		if (model->model_transition() && model->getParent() != NULL)
-		{
-			model_func_eval_set.insert(model->getParent());
-		}
-		// Adjust position in the schedule
-		schedule(model,tQ);
-	}
-	/**
-	 * The new states are in effect at t + eps so advance t
-	 */
-	t = tQ;
-	/**
-	 * Compute model transitions and build up the prev (pre-transition)
-	 * and next (post-transition) component sets. These sets are built
-	 * up from only the models that have the model_transition function
-	 * evaluated.
-	 */
-	if (model_func_eval_set.empty() == false)
-	{
-		while (!model_func_eval_set.empty())
-		{
-			Network<X,T>* network_model = *(model_func_eval_set.begin());
-			model_func_eval_set.erase(model_func_eval_set.begin());
-			getAllChildren(network_model,prev);
-			if (network_model->model_transition() &&
-					network_model->getParent() != NULL)
-			{
-				model_func_eval_set.insert(network_model->getParent());
-			}
-			getAllChildren(network_model,next);
-		}
-		// Find the set of models that were added.
-		set_assign_diff(added,next,prev);
-		// Find the set of models that were removed
-		set_assign_diff(removed,prev,next);
-		// Intersection of added and removed is always empty, so no need to look
-		// for models in both (an earlier version of the code did this).
-		next.clear();
-		prev.clear();
-		/** 
-		 * The model adds are processed first.  This is done so that, if any
-		 * of the added models are components something that was removed at
-		 * a higher level, then the models will not have been deleted when
-		 * trying to schedule them.
-		 */
-		for (typename Bag<Devs<X,T>*>::iterator iter = added.begin(); 
-			iter != added.end(); iter++)
-		{
-			schedule(*iter,t);
-		}
-		// Done with the additions
-		added.clear();
-		// Remove the models that are in the removed set.
-		for (typename Bag<Devs<X,T>*>::iterator iter = removed.begin(); 
-			iter != removed.end(); iter++)
-		{
-			clean_up(*iter);
-			unschedule_model(*iter);
-			// Add to a sorted remove set for deletion
-			sorted_removed.insert(*iter); 
-		}
-		// Done with the unsorted remove set
-		removed.clear();
-		// Delete the sorted removed models
-		while (!sorted_removed.empty())
-		{
-			// Get the model to erase
-			Devs<X,T>* model_to_remove = *(sorted_removed.begin());
-			// Remove the model
-			sorted_removed.erase(sorted_removed.begin());
-			/**
-			 * If this model has children, then remove them from the 
-			 * deletion set. This will avoid double delete problems.
-			 */
-			if (model_to_remove->typeIsNetwork() != NULL)
-			{
-				getAllChildren(model_to_remove->typeIsNetwork(),prev);
-				typename Set<Devs<X,T>*>::iterator iter = prev.begin();
-				for (; iter != prev.end(); iter++)
-					sorted_removed.erase(*iter);
-				prev.clear();
-			}
-			// Delete the model and its children
-			delete model_to_remove;
-		}
-		// Removed sets should be empty now
-		assert(prev.empty());
-		assert(sorted_removed.empty());
-	} // End of the structure change
-	// Cleanup and reschedule models that changed state in this iteration
-	// and survived the structure change phase.
-	for (typename Bag<Atomic<X,T>*>::iterator iter = activated.begin(); 
-		iter != activated.end(); iter++)
-	{
-		clean_up(*iter);
-	}
-	// Empty the bags
-	activated.clear();
-	// Return the current simulation time
-	return t;
-}
-
-template <class X, class T>
-void Simulator<X,T>::clean_up(Devs<X,T>* model)
-{
-	Atomic<X,T>* amodel = model->typeIsAtomic();
-	if (amodel != NULL)
-	{
-		if (amodel->x != NULL)
-		{
-			amodel->x->clear();
-			io_pool.destroy_obj(amodel->x);
-			amodel->x = NULL;
-		}
-		if (amodel->y != NULL)
-		{
-			amodel->gc_output(*(amodel->y));
-			amodel->y->clear();
-			io_pool.destroy_obj(amodel->y);
-			amodel->y = NULL;
-		}
-		if (amodel->typeIsMealyAtomic() != NULL)
-		{
-			amodel->typeIsMealyAtomic()->imm = false;
-		}
-	}
-	else
-	{
-		Set<Devs<X,T>*> components;
-		model->typeIsNetwork()->getComponents(components);
-		for (typename Set<Devs<X,T>*>::iterator iter = components.begin();
-		iter != components.end(); iter++)
-		{
-			clean_up(*iter);
-		}
-	}
-}
-
-template <class X, class T>
-void Simulator<X,T>::unschedule_model(Devs<X,T>* model)
-{
-	if (model->typeIsAtomic() != NULL)
-	{
-		sched.schedule(model->typeIsAtomic(),adevs_inf<T>());
-		activated.erase(model->typeIsAtomic());
-	}
-	else
-	{
-		Set<Devs<X,T>*> components;
-		model->typeIsNetwork()->getComponents(components);
-		for (typename Set<Devs<X,T>*>::iterator iter = components.begin();
-		iter != components.end(); iter++)
-		{
-			unschedule_model(*iter);
-		}
-	}
-}
-
-template <class X, class T>
-void Simulator<X,T>::schedule(Devs<X,T>* model, T t)
-{
-	Atomic<X,T>* a = model->typeIsAtomic();
-	if (a != NULL)
-	{
-		a->tL = t;
-		T dt = a->ta();
-		if (dt == adevs_inf<T>())
-		{
-			sched.schedule(a,adevs_inf<T>());
-		}
-		else
-		{
-			T tNext = a->tL+dt;
-			if (tNext < a->tL)
-			{
-				exception err("Negative time advance",a);
-				throw err;
-			}
-			sched.schedule(a,tNext);
-		}
-	}
-	else
-	{
-		Set<Devs<X,T>*> components;
-		model->typeIsNetwork()->getComponents(components);
-		typename Set<Devs<X,T>*>::iterator iter = components.begin();
-		for (; iter != components.end(); iter++)
-		{
-			schedule(*iter,t);
-		}
-	}
-}
-
-template <class X, class T>
-void Simulator<X,T>::inject_event(Atomic<X,T>* model, X& value)
-{
-	if (io_time < model->tL)
-	{
-		exception err("Attempt to apply input in the past",model);
-		throw err;
-	}
-	// If this is a Mealy model, add it to the list of models that
-	// will need their input calculated
-	if (model->typeIsMealyAtomic())
-	{
-		if (allow_mealy_input)
-		{
-			assert(model->y == NULL);
-			// Add it to the list of its not already there
-			if (model->x == NULL && !model->typeIsMealyAtomic()->imm)
-				mealy.insert(model->typeIsMealyAtomic());
-		}
-		else
-		{
-			exception err("Mealy model coupled to a Mealy model",model);
-			throw err;
-		}
-	}
-	// Add the output to the model's bag of output to be processed
-	if (model->x == NULL)
-	{
-		if (model->y == NULL)
-			activated.insert(model);
-		model->x = io_pool.make_obj();
-	}
-	this->notify_input_listeners(model,value,io_time);
-	model->x->insert(value);
-}
-
-template <class X, class T>
-void Simulator<X,T>::route(Network<X,T>* parent, Devs<X,T>* src, X& x)
-{
-	// Notify event listeners if this is an output event
-	if (parent != src)
-		this->notify_output_listeners(src,x,io_time);
-	// No one to do the routing, so return
-	if (parent == NULL) return;
-	// Compute the set of receivers for this value
-	Bag<Event<X,T> >* recvs = recv_pool.make_obj();
-	parent->route(x,src,*recvs);
-	// Deliver the event to each of its targets
-	Atomic<X,T>* amodel = NULL;
-	typename Bag<Event<X,T> >::iterator recv_iter = recvs->begin();
-	for (; recv_iter != recvs->end(); recv_iter++)
-	{
-		/**
-		 * If the destination is an atomic model, add the event to the IO bag
-		 * for that model and add model to the list of activated models
-		 */
-		amodel = (*recv_iter).model->typeIsAtomic();
-		if (amodel != NULL)
-		{
-			inject_event(amodel,(*recv_iter).value);
-		}
-		// if this is an external output from the parent model
-		else if ((*recv_iter).model == parent)
-		{
-			route(parent->getParent(),parent,(*recv_iter).value);
-		}
-		// otherwise it is an input to a coupled model
-		else
-		{
-			this->notify_input_listeners((*recv_iter).model,(*recv_iter).value,io_time);
-			route((*recv_iter).model->typeIsNetwork(),
-			(*recv_iter).model,(*recv_iter).value);
-		}
-	}
-	recvs->clear();
-	recv_pool.destroy_obj(recvs);
-}
-
-template <class X, class T>
-void Simulator<X,T>::getAllChildren(Network<X,T>* model, Set<Devs<X,T>*>& s)
-{
-	Set<Devs<X,T>*> tmp;
-	// Get the component set
-	model->getComponents(tmp);
-	// Add all of the local level elements to s
-	s.insert(tmp.begin(),tmp.end());
-	// Find the components of type network and update s recursively
-	typename Set<Devs<X,T>*>::iterator iter;
-	for (iter = tmp.begin(); iter != tmp.end(); iter++)
-	{
-		if ((*iter)->typeIsNetwork() != NULL)
-		{
-			getAllChildren((*iter)->typeIsNetwork(),s);
-		}
-	}
-}
-
-template <class X, class T>
-Simulator<X,T>::~Simulator()
-{
-	// Clean up the models with stale IO
-	typename Bag<Atomic<X,T>*>::iterator iter;
-	for (iter = activated.begin(); iter != activated.end(); iter++)
-	{
-		clean_up(*iter);
-	}
-}
-
-} // End of namespace
-
-#endif

+ 0 - 321
simulators/adevs-3.3/include/adevs_time.h

@@ -1,321 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_time_h_
-#define __adevs_time_h_
-#include <cfloat>
-#include <iostream>
-#include <cmath>
-#include <limits>
-
-/// Returns the maximum value for a time type
-template <class T> inline T adevs_inf();
-/// Returns the zero value for a time type
-template <class T> inline T adevs_zero(); 
-/// Returns a value less than adevs_zero()
-template <class T> inline T adevs_sentinel(); 
-/// Returns the interval to the next instant of time
-template <class T> inline T adevs_epsilon(); 
-
-namespace adevs
-{
-
-/**
- * This time type allows models to evolve on R x Z.
- */
-template <typename T=double>
-class sd_time
-{
-	public:
-		/// Creates the identify (0,0)
-		sd_time():t(0),k(0){}
-		/// Create a time (t,k)
-		sd_time(T t, int k):t(t),k(k){}
-		/// Copy constructor
-		sd_time(const sd_time& other):t(other.t),k(other.k){}
-		/// Get the real part of time
-		T real() const { return t; }
-		/// Get the logical part of time
-		double integer() const { return k; }
-		/// Assignment operator
-		const sd_time& operator=(const sd_time& other)
-		{
-			t = other.t;
-			k = other.k;
-			return *this;
-		}
-		/// Equivalence
-		bool operator==(const sd_time& t2) const
-		{
-			return (t == t2.t && k == t2.k);
-		}
-		/// Not equal
-		bool operator!=(const sd_time& t2) const
-		{
-			return !(*this == t2);
-		}
-		/// Order by t then by c
-		bool operator<(const sd_time& t2) const
-		{
-			return (t < t2.t || (t == t2.t && k < t2.k));
-		}
-		/// Less than or equal
-		bool operator<=(const sd_time& t2) const
-		{
-			return (*this == t2 || *this < t2);
-		}
-		/// Greater than
-		bool operator>(const sd_time& t2) const
-		{
-			return !(*this <= t2);
-		}
-		/// Greater than or equal
-		bool operator>=(const sd_time& t2) const
-		{
-			return !(*this < t2);
-		}
-		/// Advance this value by a step size t2
-		sd_time operator+(const sd_time& t2) const
-		{
-			sd_time result(*this);
-			result += t2;
-			return result;
-		}
-		/// Advance this value by a step size t2
-		const sd_time& operator+=(const sd_time& t2) 
-		{
-			if (t2.t == 0) k += t2.k;
-			else { t += t2.t; k = t2.k; }
-			return *this;
-		}
-		/// Length of the interval from now to t2
-		sd_time operator-(const sd_time& t2) const
-		{
-			sd_time result(*this);
-			result -= t2;
-			return result;
-		}
-		/// Length of the interval from now to t2
-		const sd_time& operator-=(const sd_time& t2) 
-		{
-			if (t == t2.t) { t = 0; k -= t2.k; }
-			else t -= t2.t; 
-			return *this;
-		}
-		/// Print a time to the output stream
-		friend std::ostream& operator<<(std::ostream& out, const sd_time& t)
-		{
-			out << "(" << t.t << "," << t.k << ")";
-			return out;
-		}
-		/// Read a time from the input stream
-		friend std::istream& operator>>(std::istream& in, sd_time& t)
-		{
-			char junk;
-			in >> junk >> t.t >> junk >> t.k >> junk;
-			return in;
-		}
-	private:
-		T t; int k;
-};
-
-/**
- * <p>The fcmp() inline function is taken from fcmp.c, which is
- * Copyright (c) 1998-2000 Theodore C. Belding,
- * University of Michigan Center for the Study of Complex Systems,
- * <mailto:Ted.Belding@umich.edu>,
- * <http://www-personal.umich.edu/~streak/>,
- * </p>
- *
- * <p>This code is part of the fcmp distribution. fcmp is free software;
- * you can redistribute and modify it under the terms of the GNU Library
- * General Public License (LGPL), version 2 or later.  This software
- * comes with absolutely no warranty.</p>
- */ 
-inline int fcmp(double x1, double x2, double epsilon) 
-{
-    int exponent;
-    double delta;
-    double difference;
-
-    /* Get exponent(max(fabs(x1), fabs(x2))) and store it in exponent. */
-
-    /* If neither x1 nor x2 is 0, */
-    /* this is equivalent to max(exponent(x1), exponent(x2)). */
-
-    /* If either x1 or x2 is 0, its exponent returned by frexp would be 0, */
-    /* which is much larger than the exponents of numbers close to 0 in */
-    /* magnitude. But the exponent of 0 should be less than any number */
-    /* whose magnitude is greater than 0. */
-
-    /* So we only want to set exponent to 0 if both x1 and */
-    /* x2 are 0. Hence, the following works for all x1 and x2. */
-
-    frexp(fabs(x1) > fabs(x2) ? x1 : x2, &exponent);
-
-    /* Do the comparison. */
-
-    /* delta = epsilon * pow(2, exponent) */
-
-    /* Form a neighborhood around x2 of size delta in either direction. */
-    /* If x1 is within this delta neighborhood of x2, x1 == x2. */
-    /* Otherwise x1 > x2 or x1 < x2, depending on which side of */
-    /* the neighborhood x1 is on. */
-
-    delta = ldexp(epsilon, exponent); 
-
-    difference = x1 - x2;
-
-    if (difference > delta)
-        return 1; /* x1 > x2 */
-    else if (difference < -delta)
-        return -1;  /* x1 < x2 */
-    else /* -delta <= difference <= delta */
-        return 0;  /* x1 == x2 */
-}
-
-/**
- * This is an alternative double that may be used for the simulation clock
- * (i.e., as the template parameter T for models and simulators). It
- * uses the fcmp function to check for equality instead of the 
- * default equality operator. Information on the fcmp function
- * may be found at http://fcmp.sourceforge.net/
- */
-class double_fcmp {
-
-private:
-	double d;
-
-public:
-    /**
-	 * The user must instantiate this static variable
-	 * and initialize as required by the fcmp function.
-	 */
-    static double epsilon;
-
-    double_fcmp(double rhs = 0) 
-        : d(rhs) { }
-
-    const double_fcmp& operator=(const double_fcmp& rhs)
-    {
-        d = rhs.d;
-        return *this;
-    }
-    const double_fcmp& operator=(double rhs)
-    {
-        d = rhs;
-        return *this;
-    }
-    operator double()
-    {
-        return d;
-    }
-    bool operator<(double rhs) const
-    {
-        return (fcmp(d, rhs, epsilon) < 0);
-    }
-    bool operator<(const double_fcmp& rhs) const
-    {
-        return (fcmp(d, rhs.d, epsilon) < 0);
-    }
-    bool operator<=(const double_fcmp& rhs) const
-    {
-        return (fcmp(d, rhs.d, epsilon) <= 0);
-    }
-    bool operator>(const double_fcmp& rhs) const
-    {
-        return (fcmp(d, rhs.d, epsilon) > 0);
-    }
-    bool operator>=(const double_fcmp& rhs) const
-    {
-        return (fcmp(d, rhs.d, epsilon) >= 0);
-    }
-    bool operator==(double rhs) const
-    {
-        return (fcmp(d, rhs, epsilon) == 0);
-    }
-    bool operator==(const double_fcmp& rhs) const
-    {
-        return (fcmp(d, rhs.d, epsilon) == 0);
-    }
-};
-
-} // end namespace
-
-template <> inline float adevs_inf() {
-	return std::numeric_limits<float>::max(); }
-template <> inline long double adevs_inf() {
-	return std::numeric_limits<long double>::max(); }
-template <> inline double adevs_inf() {
-	return std::numeric_limits<double>::max(); }
-template <> inline int adevs_inf() {
-	return std::numeric_limits<int>::max(); }
-template <> inline long adevs_inf() {
-	return std::numeric_limits<long>::max(); }
-template <> inline adevs::double_fcmp adevs_inf() {
-	return std::numeric_limits<double>::max(); }
-template <> inline adevs::sd_time<double> adevs_inf() {
-	return adevs::sd_time<double>(std::numeric_limits<double>::max(),std::numeric_limits<int>::max()); }
-template <> inline adevs::sd_time<long> adevs_inf() {
-	return adevs::sd_time<long>(std::numeric_limits<long>::max(),std::numeric_limits<int>::max()); }
-template <> inline adevs::sd_time<int> adevs_inf() {
-	return adevs::sd_time<int>(std::numeric_limits<int>::max(),std::numeric_limits<int>::max()); }
-
-template <> inline float adevs_zero() { return 0.0f; }
-template <> inline long double adevs_zero() { return 0.0L; }
-template <> inline double adevs_zero() { return 0.0; }
-template <> inline int adevs_zero() { return 0; }
-template <> inline long adevs_zero() { return 0; }
-template <> inline adevs::double_fcmp adevs_zero() { return 0.0; }
-template <> inline adevs::sd_time<double> adevs_zero() { return adevs::sd_time<double>(0.0,0); }
-template <> inline adevs::sd_time<long> adevs_zero() { return adevs::sd_time<long>(0,0); }
-template <> inline adevs::sd_time<int> adevs_zero() { return adevs::sd_time<int>(0,0); }
-
-template <> inline float adevs_sentinel() { return -1.0f; }
-template <> inline long double adevs_sentinel() { return -1.0L; }
-template <> inline double adevs_sentinel() { return -1.0; }
-template <> inline int adevs_sentinel() { return -1; }
-template <> inline long adevs_sentinel() { return -1; }
-template <> inline adevs::double_fcmp adevs_sentinel() { return -1.0; }
-template <> inline adevs::sd_time<double> adevs_sentinel() { return adevs::sd_time<double>(-1.0,0); }
-template <> inline adevs::sd_time<long> adevs_sentinel() { return adevs::sd_time<long>(-1,0); }
-template <> inline adevs::sd_time<int> adevs_sentinel() { return adevs::sd_time<int>(-1,0); }
-
-template <> inline float adevs_epsilon() { return 0.0f; }
-template <> inline long double adevs_epsilon() { return 0.0L; }
-template <> inline double adevs_epsilon() { return 0.0; }
-template <> inline int adevs_epsilon() { return 0; }
-template <> inline long adevs_epsilon() { return 0; }
-template <> inline adevs::double_fcmp adevs_epsilon() { return 0.0; }
-template <> inline adevs::sd_time<double> adevs_epsilon() { return adevs::sd_time<double>(0.0,1); }
-template <> inline adevs::sd_time<long> adevs_epsilon() { return adevs::sd_time<long>(0,1); }
-template <> inline adevs::sd_time<int> adevs_epsilon() { return adevs::sd_time<int>(0,1); }
-
-#endif

+ 0 - 207
simulators/adevs-3.3/include/adevs_wrapper.h

@@ -1,207 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_wrapper_h_
-#define __adevs_wrapper_h_
-#include "adevs_models.h"
-
-namespace adevs
-{
-	/**
-	 * <p>This class wraps a Network or Atomic model with interface type InternalType in an
-	 * Atomic model with interface type ExternalType. Input to the ModelWrapper is passed
-	 * through a user provided input translation method before being handed off
-	 * to the wrapped model for processing. Output from the wrapped model is
-	 * passed through a user provided output translation method before emerging
-	 * as output from the ModelWrapper. If the wrapped model is a Network, the input
-	 * translation method can create inputs for any of its components. Similarly
-	 * the output translation method is provided with every output produced by
-	 * every component in the Network. If the wrapped model is Atomic then there
-	 * is, of course, only one possible destination for incoming events and only
-	 * one source of outgoing events.
-	 * <p>You will need to implement the usual gc_output event for outputs
-	 * produced by the ModelWrapper. You will also need to implement
-	 * gcInputEvents method to clean up events that are created during
-	 * the input translation process.
-	 */
-	template <typename ExternalType, typename InternalType, class T = double> class ModelWrapper:
-		public Atomic<ExternalType,T>,
-		public EventListener<InternalType,T>
-	{
-		public:
-			/**
-			 * Create a wrapper for the specified model. The ModelWrapper takes
-			 * ownership of the supplied model and will delete it when the
-			 * ModelWrapper is deleted.
-			 */
-			ModelWrapper(Devs<InternalType,T>* model);
-			/**
-			 * This method is used to translate incoming input objects into
-			 * input objects that the wrapped model can process. The supplied
-			 * internal_input bag should be filled with Events that contain the targeted
-			 * internal models and the values to supply to them. The external_input
-			 * bag contains the input values supplied to the wrapper's external or
-			 * confluent transition function.
-			 */
-			virtual void translateInput(const Bag<ExternalType>& external_input,
-					Bag<Event<InternalType,T> >& internal_input) = 0;
-			/**
-			 * This method is used to translate outgoing output objects
-			 * into objects that the ModelWrapper can produce. The 
-			 * internal_output bag contains all of the output events that the
-			 * were produced by the wrapped model. The external_output bag
-			 * should be filled with objects of type ExternalType that
-			 * will be produced as output by the ModelWrapper.
-			 */
-			virtual void translateOutput(const Bag<Event<InternalType,T> >& internal_output,
-					Bag<ExternalType>& external_output) = 0;
-			/**
-			 * This is the garbage collection method for internal input events.
-			 * It will be called when the wrapper is done with a set of events
-			 * that you created with the translateInput method. The supplied bag
-			 * is the same one that you filled out in the translateInput method.
-			 */
-			virtual void gc_input(Bag<Event<InternalType,T> >& g) = 0;
-			/// Get the model that is wrapped by this object
-			Devs<InternalType,T>* getWrappedModel() { return model; }
-			/// Atomic internal transition function
-			void delta_int();
-			/// Atomic external transition function
-			void delta_ext(T e, const Bag<ExternalType>& xb);
-			/// Atomic confluent transition function
-			void delta_conf(const Bag<ExternalType>& xb);
-			/// Atomic output function
-			void output_func(Bag<ExternalType>& yb);
-			/// Atomic time advance function
-			T ta();
-			/// EventListener outputEvent method
-			void outputEvent(Event<InternalType,T> y, T t);
-			/// Destructor. This destroys the wrapped model too.
-			~ModelWrapper();
-		private:
-			ModelWrapper(){}
-			ModelWrapper(const ModelWrapper&){}
-			void operator=(const ModelWrapper&){}
-			// Bag of events created by the input translation method 
-			Bag<Event<InternalType,T> > input;
-			// Output from the wrapped model
-			Bag<Event<InternalType,T> > output;
-			// The wrapped model
-			Devs<InternalType,T>* model;
-			// Simulator for driving the wrapped model
-			Simulator<InternalType,T>* sim;
-			// Last event time
-			T tL;
-	};
-
-template <typename ExternalType, typename InternalType, class T> 
-ModelWrapper<ExternalType,InternalType,T>::ModelWrapper(Devs<InternalType,T>* model):
-	Atomic<ExternalType,T>(),
-	EventListener<InternalType,T>(),
-	model(model),
-	tL(adevs_zero<T>())
-{
-	sim = new Simulator<InternalType,T>(model);
-	sim->addEventListener(this);
-}
-
-template <typename ExternalType, typename InternalType, class T> 
-void ModelWrapper<ExternalType,InternalType,T>::delta_int()
-{
-	// Update the internal clock
-	tL = sim->nextEventTime();
-	// Execute the next autonomous event for the wrapped model
-	sim->execNextEvent();
-}
-
-template <typename ExternalType, typename InternalType, class T> 
-void ModelWrapper<ExternalType,InternalType,T>::delta_ext(T e, const Bag<ExternalType>& xb)
-{
-	// Update the internal clock
-	tL += e;
-	// Convert the external inputs to internal inputs
-	translateInput(xb,input);
-	// Apply the input
-	sim->computeNextState(input,tL);
-	// Clean up 
-	gc_input(input);
-	input.clear();
-}
-
-template <typename ExternalType, typename InternalType, class T> 
-void ModelWrapper<ExternalType,InternalType,T>::delta_conf(const Bag<ExternalType>& xb)
-{
-	// Update the internal clock
-	tL = sim->nextEventTime();
-	// Convert the external inputs to internal inputs
-	translateInput(xb,input);
-	// Apply the input
-	sim->computeNextState(input,tL);
-	// Clean up 
-	gc_input(input);
-	input.clear();
-}
-
-template <typename ExternalType, typename InternalType, class T> 
-T ModelWrapper<ExternalType,InternalType,T>::ta()
-{
-	if (sim->nextEventTime() < adevs_inf<T>()) return sim->nextEventTime()-tL;
-	else return adevs_inf<T>();
-}
-
-template <typename ExternalType, typename InternalType, class T> 
-void ModelWrapper<ExternalType,InternalType,T>::output_func(Bag<ExternalType>& yb)
-{
-	// Compute the model's output events; this causes the outputEvent method to be called
-	sim->computeNextOutput();
-	// Translate the output events to external output events
-	translateOutput(output,yb);
-	// Clean up; the contents of the output bag are deleted by the wrapped model's 
-	// gc_output method
-	output.clear();
-}
-
-template <typename ExternalType, typename InternalType, class T> 
-void ModelWrapper<ExternalType,InternalType,T>::outputEvent(Event<InternalType,T> y, T t)
-{
-	// Just save the events for processing by the output_func
-	output.insert(y);
-}
-
-template <typename ExternalType, typename InternalType, class T> 
-ModelWrapper<ExternalType,InternalType,T>::~ModelWrapper()
-{
-	delete sim;
-	delete model;
-}
-
-} // end of namespace
-
-#endif

+ 0 - 78
simulators/adevs-3.3/include/object_pool.h

@@ -1,78 +0,0 @@
-/**
- * Copyright (c) 2013, James Nutaro
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met: 
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- *    list of conditions and the following disclaimer. 
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- *    this list of conditions and the following disclaimer in the documentation
- *    and/or other materials provided with the distribution. 
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies, 
- * either expressed or implied, of the FreeBSD Project.
- *
- * Bugs, comments, and questions can be sent to nutaro@gmail.com
- */
-#ifndef __adevs_object_pool_h_
-#define __adevs_object_pool_h_
-#include "adevs_bag.h"
-
-namespace adevs
-{
-
-/**
- * A utility class for managing pools of objects that are stored on the heap.
- * Uses the new and delete operators to create and destroy objects.
- */
-template <class T> class object_pool
-{
-	public:
-		/// Construct a pool with a specific initial population
-		object_pool(unsigned int pop = 0):
-		pool()
-		{
-			for (unsigned int i = 0; i < pop; i++)
-				pool.insert(new T());
-		}
-		/// Create an object 
-		T* make_obj()
-		{
-			T* obj;
-			if (pool.empty()) obj = new T;
-			else
-			{
-				obj = *((pool.end())--);
-				pool.erase(pool.end()--);
-			}
-			return obj;
-		}
-		/// Return an object to the pool
-		void destroy_obj(T* obj) { pool.insert(obj); }
-		// Delete all objects in the pool
-		~object_pool()
-		{
-			typename Bag<T*>::iterator iter = pool.begin();
-			for (; iter != pool.end(); iter++) delete *iter;
-		}
-	private:
-		Bag<T*> pool;
-};
-
-} // end of namespace
-
-#endif

+ 0 - 1
simulators/cadmium

@@ -1 +0,0 @@
-Subproject commit b6636f791d3fbff41b6b72e1d9e34ce18152065d

+ 0 - 1
simulators/cadmium_v2

@@ -1 +0,0 @@
-Subproject commit 145a7c68caece68b6bb298a50deb5ab4eaffd0ba

+ 0 - 1
simulators/pythonpdevs

@@ -1 +0,0 @@
-Subproject commit 50164a92c68f2b74905d2aecdb783b1ff5efd110

+ 0 - 1
simulators/xdevs.c

@@ -1 +0,0 @@
-Subproject commit 9c2a54ddd671a790528f6ba4d5a71c2732a431dd

+ 0 - 1
simulators/xdevs.cpp

@@ -1 +0,0 @@
-Subproject commit 4a5b9cf7b6498e88e760dfba177a761240999955

+ 0 - 1
simulators/xdevs.java

@@ -1 +0,0 @@
-Subproject commit 94b7d15ab3e79220e8145f9576e69948db4b4fb6

+ 0 - 1
simulators/xdevs.py

@@ -1 +0,0 @@
-Subproject commit b53a6f170350af8296af43d1b2334e173e95990c

+ 0 - 1
simulators/xdevs.rs

@@ -1 +0,0 @@
-Subproject commit 9105a2ebbfb176c7333e3765ac2c79d52a2cc03b

+ 0 - 1
simulators/xdevs.rs-new

@@ -1 +0,0 @@
-Subproject commit 64670afaeabfbf2bf1d34edd64cbc06bdfaad51d