y_petri 2.0.15 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/y_petri/{manipulator → agent}/hash_key_pointer.rb +2 -2
- data/lib/y_petri/agent/petri_net_related.rb +115 -0
- data/lib/y_petri/{manipulator → agent}/selection.rb +2 -1
- data/lib/y_petri/{manipulator/simulation_related_methods.rb → agent/simulation_related.rb} +93 -110
- data/lib/y_petri/agent.rb +22 -0
- data/lib/y_petri/core/timed/euler.rb +20 -0
- data/lib/y_petri/core/timed/pseudo_euler.rb +31 -0
- data/lib/y_petri/core/timed/quasi_euler.rb +23 -0
- data/lib/y_petri/core/timed.rb +70 -0
- data/lib/y_petri/core/timeless/pseudo_euler.rb +20 -0
- data/lib/y_petri/core/timeless.rb +12 -0
- data/lib/y_petri/core.rb +100 -0
- data/lib/y_petri/dsl.rb +66 -0
- data/lib/y_petri/fixed_assets.rb +7 -0
- data/lib/y_petri/net/element_access.rb +239 -0
- data/lib/y_petri/net/state/feature/delta.rb +88 -0
- data/lib/y_petri/net/state/feature/firing.rb +57 -0
- data/lib/y_petri/net/state/feature/flux.rb +58 -0
- data/lib/y_petri/net/state/feature/gradient.rb +75 -0
- data/lib/y_petri/net/state/feature/marking.rb +62 -0
- data/lib/y_petri/net/state/feature.rb +79 -0
- data/lib/y_petri/net/state/features/dataset.rb +135 -0
- data/lib/y_petri/net/state/features/record.rb +50 -0
- data/lib/y_petri/net/state/features.rb +126 -0
- data/lib/y_petri/net/state.rb +121 -0
- data/lib/y_petri/net/timed.rb +8 -0
- data/lib/y_petri/net/visualization.rb +3 -3
- data/lib/y_petri/net.rb +73 -77
- data/lib/y_petri/place.rb +8 -3
- data/lib/y_petri/simulation/dependency.rb +107 -0
- data/lib/y_petri/simulation/element_representation.rb +20 -0
- data/lib/y_petri/simulation/elements/access.rb +57 -0
- data/lib/y_petri/simulation/elements.rb +45 -0
- data/lib/y_petri/simulation/feature_set.rb +21 -0
- data/lib/y_petri/simulation/initial_marking/access.rb +55 -0
- data/lib/y_petri/simulation/initial_marking.rb +15 -0
- data/lib/y_petri/simulation/marking_clamps/access.rb +34 -0
- data/lib/y_petri/simulation/marking_clamps.rb +18 -0
- data/lib/y_petri/simulation/marking_vector/access.rb +106 -0
- data/lib/y_petri/simulation/marking_vector.rb +156 -0
- data/lib/y_petri/simulation/matrix.rb +64 -0
- data/lib/y_petri/simulation/place_mapping.rb +62 -0
- data/lib/y_petri/simulation/place_representation.rb +74 -0
- data/lib/y_petri/simulation/places/access.rb +121 -0
- data/lib/y_petri/simulation/places/clamped.rb +8 -0
- data/lib/y_petri/simulation/places/free.rb +8 -0
- data/lib/y_petri/simulation/places/types.rb +25 -0
- data/lib/y_petri/simulation/places.rb +41 -0
- data/lib/y_petri/simulation/recorder.rb +54 -0
- data/lib/y_petri/simulation/timed/recorder.rb +53 -0
- data/lib/y_petri/simulation/timed.rb +161 -261
- data/lib/y_petri/simulation/timeless/recorder.rb +25 -0
- data/lib/y_petri/simulation/timeless.rb +35 -0
- data/lib/y_petri/simulation/transition_representation/A.rb +58 -0
- data/lib/y_petri/simulation/transition_representation/S.rb +45 -0
- data/lib/y_petri/simulation/transition_representation/T.rb +80 -0
- data/lib/y_petri/simulation/transition_representation/TS.rb +46 -0
- data/lib/y_petri/simulation/transition_representation/Ts.rb +32 -0
- data/lib/y_petri/simulation/transition_representation/a.rb +30 -0
- data/lib/y_petri/simulation/transition_representation/s.rb +29 -0
- data/lib/y_petri/simulation/transition_representation/t.rb +37 -0
- data/lib/y_petri/simulation/transition_representation/tS.rb +38 -0
- data/lib/y_petri/simulation/transition_representation/ts.rb +32 -0
- data/lib/y_petri/simulation/transition_representation/types.rb +62 -0
- data/lib/y_petri/simulation/transition_representation.rb +79 -0
- data/lib/y_petri/simulation/transitions/A.rb +40 -0
- data/lib/y_petri/simulation/transitions/S.rb +24 -0
- data/lib/y_petri/simulation/transitions/T.rb +34 -0
- data/lib/y_petri/simulation/transitions/TS.rb +57 -0
- data/lib/y_petri/simulation/transitions/Ts.rb +60 -0
- data/lib/y_petri/simulation/transitions/a.rb +8 -0
- data/lib/y_petri/simulation/transitions/access.rb +186 -0
- data/lib/y_petri/simulation/transitions/s.rb +9 -0
- data/lib/y_petri/simulation/transitions/t.rb +22 -0
- data/lib/y_petri/simulation/transitions/tS.rb +55 -0
- data/lib/y_petri/simulation/transitions/ts.rb +58 -0
- data/lib/y_petri/simulation/transitions/types.rb +98 -0
- data/lib/y_petri/simulation/transitions.rb +21 -0
- data/lib/y_petri/simulation.rb +176 -781
- data/lib/y_petri/transition/assignment.rb +7 -5
- data/lib/y_petri/transition/construction.rb +119 -187
- data/lib/y_petri/transition/init.rb +311 -0
- data/lib/y_petri/transition/ordinary_timeless.rb +8 -6
- data/lib/y_petri/transition/timed.rb +11 -18
- data/lib/y_petri/transition.rb +104 -132
- data/lib/y_petri/version.rb +1 -1
- data/lib/y_petri/world/dependency.rb +40 -0
- data/lib/y_petri/world/petri_net_related.rb +61 -0
- data/lib/y_petri/{workspace/simulation_related_methods.rb → world/simulation_related.rb} +42 -49
- data/lib/y_petri/world.rb +27 -0
- data/lib/y_petri.rb +47 -99
- data/test/{manipulator_test.rb → agent_test.rb} +19 -17
- data/{lib/y_petri → test/examples}/demonstrator.rb +0 -0
- data/{lib/y_petri → test/examples}/demonstrator_2.rb +1 -0
- data/{lib/y_petri → test/examples}/demonstrator_3.rb +0 -0
- data/{lib/y_petri → test/examples}/demonstrator_4.rb +0 -0
- data/test/examples/example_2.rb +16 -0
- data/test/{manual_examples.rb → examples/manual_examples.rb} +0 -0
- data/test/net_test.rb +126 -121
- data/test/place_test.rb +1 -1
- data/test/sim_test +565 -0
- data/test/simulation_test.rb +338 -264
- data/test/transition_test.rb +77 -174
- data/test/world_mock.rb +12 -0
- data/test/{workspace_test.rb → world_test.rb} +19 -20
- data/test/y_petri_test.rb +4 -5
- metadata +101 -26
- data/lib/y_petri/dependency_injection.rb +0 -45
- data/lib/y_petri/manipulator/petri_net_related_methods.rb +0 -74
- data/lib/y_petri/manipulator.rb +0 -20
- data/lib/y_petri/net/selections.rb +0 -209
- data/lib/y_petri/simulation/collections.rb +0 -460
- data/lib/y_petri/workspace/parametrized_subclassing.rb +0 -22
- data/lib/y_petri/workspace/petri_net_related_methods.rb +0 -88
- data/lib/y_petri/workspace.rb +0 -16
- data/test/timed_simulation_test.rb +0 -153
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 2b031424367891fe4ff8af4b6c61afb984f5d341
         | 
| 4 | 
            +
              data.tar.gz: adb9f8df5d999a60beff42aa1f69fa9aed7f0a7a
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ed934ecfc8a78e32d65b8174fee3eedab5ee969ae857b847698581ca3b33e002a4ead151e361caa2d14593efaf44d3d8b04b49f4c286f2a72173bd36c1314a25
         | 
| 7 | 
            +
              data.tar.gz: c4fabc8dcf91e509e249dab7e0af4afb97ec2dc8d2b93b5bd18936e408915913e96ef45eb53756b34767257dff0d842194af6a992354e68f183facbad3b05f15
         | 
| @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            # Represents a pointer to a key of a specific hash associated with the pointer
         | 
| 2 | 
            -
            # instance. Used to implement pointers of the  | 
| 2 | 
            +
            # instance. Used to implement pointers of the Agent class.
         | 
| 3 3 | 
             
            # 
         | 
| 4 | 
            -
            class YPetri:: | 
| 4 | 
            +
            class YPetri::Agent::HashKeyPointer
         | 
| 5 5 | 
             
              # Key at which the pointer points.
         | 
| 6 6 | 
             
              # 
         | 
| 7 7 | 
             
              attr_reader :key
         | 
| @@ -0,0 +1,115 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Public command interface of YPetri.
         | 
| 4 | 
            +
            # 
         | 
| 5 | 
            +
            module YPetri::Agent::PetriNetRelated
         | 
| 6 | 
            +
              # Net selection class.
         | 
| 7 | 
            +
              # 
         | 
| 8 | 
            +
              NetSelection = Class.new YPetri::Agent::Selection
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              # Net point
         | 
| 11 | 
            +
              # 
         | 
| 12 | 
            +
              attr_reader :net_point
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              # Net selection.
         | 
| 15 | 
            +
              # 
         | 
| 16 | 
            +
              attr_reader :net_selection
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              def initialize
         | 
| 19 | 
            +
                net_point_reset
         | 
| 20 | 
            +
                @net_selection = NetSelection.new
         | 
| 21 | 
            +
                super
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              # Elements and selections:
         | 
| 25 | 
            +
              # 
         | 
| 26 | 
            +
              delegate :place, :transition, :element, 
         | 
| 27 | 
            +
                       :nets, :places, :transitions,
         | 
| 28 | 
            +
                       to: :world
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              # Place name.
         | 
| 31 | 
            +
              # 
         | 
| 32 | 
            +
              def pl( place_id )
         | 
| 33 | 
            +
                place( place_id ).name
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              # Transition name.
         | 
| 37 | 
            +
              # 
         | 
| 38 | 
            +
              def tr( transition_id )
         | 
| 39 | 
            +
                transition( transition_id ).name
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              # Place names.
         | 
| 43 | 
            +
              # 
         | 
| 44 | 
            +
              def pn
         | 
| 45 | 
            +
                places.names
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              # Transition names.
         | 
| 49 | 
            +
              # 
         | 
| 50 | 
            +
              def tn
         | 
| 51 | 
            +
                transitions.names
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              # Net names.
         | 
| 55 | 
            +
              # 
         | 
| 56 | 
            +
              def nn
         | 
| 57 | 
            +
                nets.names
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              # Place constructor: Creates a new place in the current world.
         | 
| 61 | 
            +
              # 
         | 
| 62 | 
            +
              def Place( *ordered_args, **named_args, &block )
         | 
| 63 | 
            +
                fail ArgumentError, "If block is given, :guard named argument " +
         | 
| 64 | 
            +
                  "must not be given!" if named_args.has? :guard if block
         | 
| 65 | 
            +
                named_args.update( guard: block ) if block # use block as a guard
         | 
| 66 | 
            +
                named_args.may_have :default_marking, syn!: :m!
         | 
| 67 | 
            +
                named_args.may_have :marking, syn!: :m
         | 
| 68 | 
            +
                world.Place.new *ordered_args, **named_args
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              # Transition constructor: Creates a new transition in the current world.
         | 
| 72 | 
            +
              # 
         | 
| 73 | 
            +
              def Transition( *ordered, **named, &block )
         | 
| 74 | 
            +
                world.Transition.new *ordered, **named, &block
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              # Timed transition constructor: Creates a new timed transition in the current
         | 
| 78 | 
            +
              # world. Rate closure has to be supplied as a block.
         | 
| 79 | 
            +
              # 
         | 
| 80 | 
            +
              def T( *ordered, **named, &block )
         | 
| 81 | 
            +
                world.Transition.new *ordered, **named.update( rate: block )
         | 
| 82 | 
            +
              end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              # Assignment transition constructor: Creates a new assignment transition in
         | 
| 85 | 
            +
              # the current world. Assignment closure has to be supplied as a block.
         | 
| 86 | 
            +
              # 
         | 
| 87 | 
            +
              def A( *ordered, **named, &block )
         | 
| 88 | 
            +
                world.Transition.new *ordered,
         | 
| 89 | 
            +
                                     **named.update( assignment: true, action: block )
         | 
| 90 | 
            +
              end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
              # Net constructor: Creates a new Net instance in the current world.
         | 
| 93 | 
            +
              # 
         | 
| 94 | 
            +
              def Net *ordered, **named, &block
         | 
| 95 | 
            +
                world.Net.new *ordered, **named, &block
         | 
| 96 | 
            +
              end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
              # Returns the net identified, or the net at point (if no argument given).
         | 
| 99 | 
            +
              # 
         | 
| 100 | 
            +
              def net id=nil
         | 
| 101 | 
            +
                id.nil? ? @net_point : world.net( id )
         | 
| 102 | 
            +
              end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
              # Sets the net point to a given net, or to world.Net::Top if none given.
         | 
| 105 | 
            +
              # 
         | 
| 106 | 
            +
              def net_point_reset id=world.Net::Top
         | 
| 107 | 
            +
                @net_point = world.net( id )
         | 
| 108 | 
            +
              end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
              # Sets net point to a given net.
         | 
| 111 | 
            +
              # 
         | 
| 112 | 
            +
              def net_point= id
         | 
| 113 | 
            +
                net_point_reset id
         | 
| 114 | 
            +
              end
         | 
| 115 | 
            +
            end # module YPetri::Agent::PetriNetRelated
         | 
| @@ -1,32 +1,34 @@ | |
| 1 | 
            -
            #  | 
| 2 | 
            -
             | 
| 3 | 
            -
            #  | 
| 4 | 
            -
            # of simulations...)
         | 
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Agent instance methods related to simulation (initial marking collections,
         | 
| 4 | 
            +
            # clamp collections, initial marking collections, management of simulations...)
         | 
| 5 5 | 
             
            # 
         | 
| 6 | 
            -
            module YPetri:: | 
| 6 | 
            +
            module YPetri::Agent::SimulationRelated
         | 
| 7 7 | 
             
              require_relative 'hash_key_pointer'
         | 
| 8 8 | 
             
              require_relative 'selection'
         | 
| 9 9 |  | 
| 10 10 | 
             
              # Simulation selection class.
         | 
| 11 11 | 
             
              # 
         | 
| 12 | 
            -
              SimulationSelection =  | 
| 12 | 
            +
              SimulationSelection = YPetri::Agent::Selection.parametrize agent: self
         | 
| 13 13 |  | 
| 14 14 | 
             
              # Simulation settings collection selection class.
         | 
| 15 15 | 
             
              # 
         | 
| 16 | 
            -
              SscSelection =  | 
| 16 | 
            +
              SscSelection = YPetri::Agent::Selection.parametrize agent: self
         | 
| 17 17 |  | 
| 18 18 | 
             
              # Clamp collection selection class.
         | 
| 19 19 | 
             
              # 
         | 
| 20 | 
            -
              CcSelection =  | 
| 20 | 
            +
              CcSelection = YPetri::Agent::Selection.parametrize agent: self
         | 
| 21 21 |  | 
| 22 22 | 
             
              # Initial marking collection selection class.
         | 
| 23 23 | 
             
              # 
         | 
| 24 | 
            -
              ImcSelection =  | 
| 24 | 
            +
              ImcSelection = YPetri::Agent::Selection.parametrize agent: self
         | 
| 25 25 |  | 
| 26 | 
            -
              class SimulationPoint < YPetri:: | 
| 26 | 
            +
              class SimulationPoint < YPetri::Agent::HashKeyPointer
         | 
| 27 27 | 
             
                # Reset to the first simulation, or nil if that is absent.
         | 
| 28 28 | 
             
                # 
         | 
| 29 | 
            -
                def reset | 
| 29 | 
            +
                def reset
         | 
| 30 | 
            +
                  @key = @hash.empty? ? nil : set( @hash.first[0] )
         | 
| 31 | 
            +
                end
         | 
| 30 32 |  | 
| 31 33 | 
             
                # A simulation is identified either by its name (if named), or by its
         | 
| 32 34 | 
             
                # parameters and settings (:net, :cc, :imc, :ssc).
         | 
| @@ -47,19 +49,24 @@ module YPetri::Manipulator::SimulationRelatedMethods | |
| 47 49 |  | 
| 48 50 | 
             
              # Pointer to a collection of simulation settings.
         | 
| 49 51 | 
             
              # 
         | 
| 50 | 
            -
              SscPoint =  | 
| 52 | 
            +
              SscPoint = YPetri::Agent::HashKeyPointer.parametrize agent: self
         | 
| 51 53 |  | 
| 52 54 | 
             
              # Pointer to a clamp collection.
         | 
| 53 55 | 
             
              # 
         | 
| 54 | 
            -
              CcPoint =  | 
| 56 | 
            +
              CcPoint = YPetri::Agent::HashKeyPointer.parametrize agent: self
         | 
| 55 57 |  | 
| 56 58 | 
             
              # Pointer to a collection of initial markings.
         | 
| 57 59 | 
             
              # 
         | 
| 58 | 
            -
              ImcPoint =  | 
| 60 | 
            +
              ImcPoint = YPetri::Agent::HashKeyPointer.parametrize agent: self
         | 
| 59 61 |  | 
| 60 | 
            -
              attr_reader :simulation_point, | 
| 61 | 
            -
                          : | 
| 62 | 
            -
                          : | 
| 62 | 
            +
              attr_reader :simulation_point,
         | 
| 63 | 
            +
                          :ssc_point,
         | 
| 64 | 
            +
                          :cc_point,
         | 
| 65 | 
            +
                          :imc_point,
         | 
| 66 | 
            +
                          :simulation_selection,
         | 
| 67 | 
            +
                          :ssc_selection,
         | 
| 68 | 
            +
                          :cc_selection,
         | 
| 69 | 
            +
                          :imc_selection
         | 
| 63 70 |  | 
| 64 71 | 
             
              def initialize
         | 
| 65 72 | 
             
                # set up this manipulator's pointers
         | 
| @@ -83,20 +90,20 @@ module YPetri::Manipulator::SimulationRelatedMethods | |
| 83 90 | 
             
                super
         | 
| 84 91 | 
             
              end
         | 
| 85 92 |  | 
| 86 | 
            -
              # Simulation-related methods delegated to the  | 
| 93 | 
            +
              # Simulation-related methods delegated to the world.
         | 
| 87 94 | 
             
              delegate :simulations,
         | 
| 88 95 | 
             
                       :clamp_collections,
         | 
| 89 96 | 
             
                       :initial_marking_collections,
         | 
| 90 97 | 
             
                       :simulation_settings_collections,
         | 
| 91 | 
            -
                       :clamp_collection_names, : | 
| 92 | 
            -
                       :initial_marking_collection_names, : | 
| 93 | 
            -
                       :simulation_settings_collection_names, : | 
| 94 | 
            -
                       :set_clamp_collection, : | 
| 95 | 
            -
                       :set_initial_marking_collection, : | 
| 98 | 
            +
                       :clamp_collection_names, :ncc,
         | 
| 99 | 
            +
                       :initial_marking_collection_names, :nimc,
         | 
| 100 | 
            +
                       :simulation_settings_collection_names, :nssc,
         | 
| 101 | 
            +
                       :set_clamp_collection, :ncc,
         | 
| 102 | 
            +
                       :set_initial_marking_collection, :nimc,
         | 
| 96 103 | 
             
                       :set_simulation_settings_collection, :set_ssc,
         | 
| 97 | 
            -
                       : | 
| 104 | 
            +
                       :new_simulation,
         | 
| 98 105 | 
             
                       :clamp_cc, :initial_marking_cc, :simulation_settings_cc,
         | 
| 99 | 
            -
                       to: : | 
| 106 | 
            +
                       to: :world
         | 
| 100 107 |  | 
| 101 108 | 
             
              # Returns the simulation identified by the argument, or one at simulation
         | 
| 102 109 | 
             
              # point, if no argument given. The simulation is identified in the same way
         | 
| @@ -107,10 +114,6 @@ module YPetri::Manipulator::SimulationRelatedMethods | |
| 107 114 | 
             
                SimulationPoint.new( hash: simulations, hash_value_is: "simulation" ).get
         | 
| 108 115 | 
             
              end
         | 
| 109 116 |  | 
| 110 | 
            -
              # # TEMPORARY KLUGE - FIXME
         | 
| 111 | 
            -
              # # 
         | 
| 112 | 
            -
              # def simulation; @workspace.simulations.values[-1] end
         | 
| 113 | 
            -
             | 
| 114 117 | 
             
              # Returns identified clamp collection, or (if no argument given) one
         | 
| 115 118 | 
             
              # corresponding to cc_point.
         | 
| 116 119 | 
             
              # 
         | 
| @@ -143,7 +146,7 @@ module YPetri::Manipulator::SimulationRelatedMethods | |
| 143 146 |  | 
| 144 147 | 
             
              def clamp clamp_hash
         | 
| 145 148 | 
             
                clamp_hash.each_pair do |place, clamp|
         | 
| 146 | 
            -
                  clamp_collection.merge!  | 
| 149 | 
            +
                  clamp_collection.merge! world.place( place ) => clamp
         | 
| 147 150 | 
             
                end
         | 
| 148 151 | 
             
              end
         | 
| 149 152 |  | 
| @@ -151,7 +154,7 @@ module YPetri::Manipulator::SimulationRelatedMethods | |
| 151 154 | 
             
              # field:
         | 
| 152 155 | 
             
              # * No arguments: returns current imc
         | 
| 153 156 | 
             
              # * Exactly one ordered argument: it is assumed to identify a place whose
         | 
| 154 | 
            -
              #   im in  | 
| 157 | 
            +
              #   im in the current imc will be returned.
         | 
| 155 158 | 
             
              # * A hash: Assumed to be { place_id => im }, current imc is updated with it.
         | 
| 156 159 | 
             
              # * One ordered argument, and a hash: The imc identified by the ordered
         | 
| 157 160 | 
             
              #   ordered arg is updated with the hash.
         | 
| @@ -222,8 +225,8 @@ module YPetri::Manipulator::SimulationRelatedMethods | |
| 222 225 | 
             
              # Create a new timed simulation and make it available in the simulations
         | 
| 223 226 | 
             
              # table.
         | 
| 224 227 | 
             
              # 
         | 
| 225 | 
            -
              def  | 
| 226 | 
            -
                instance =  | 
| 228 | 
            +
              def new_simulation *args, &block
         | 
| 229 | 
            +
                instance = world.new_simulation( *args, &block )
         | 
| 227 230 | 
             
                # Set the point to it
         | 
| 228 231 | 
             
                simulation_point.set( simulations.rassoc( instance )[0] )
         | 
| 229 232 | 
             
                return instance
         | 
| @@ -232,43 +235,37 @@ module YPetri::Manipulator::SimulationRelatedMethods | |
| 232 235 | 
             
              # Create a new timed simulation and run it.
         | 
| 233 236 | 
             
              # 
         | 
| 234 237 | 
             
              def run!
         | 
| 235 | 
            -
                 | 
| 238 | 
            +
                new_simulation.run!
         | 
| 236 239 | 
             
              end
         | 
| 237 240 |  | 
| 238 241 | 
             
              # Write the recorded samples in a file (csv).
         | 
| 239 242 | 
             
              # 
         | 
| 240 | 
            -
              def print_recording( filename | 
| 243 | 
            +
              def print_recording( filename=nil )
         | 
| 241 244 | 
             
                if filename.nil? then
         | 
| 242 | 
            -
                  puts simulation. | 
| 245 | 
            +
                  puts simulation.recording.to_csv
         | 
| 243 246 | 
             
                else
         | 
| 244 247 | 
             
                  File.open( filename, "w" ) do |f|
         | 
| 245 | 
            -
                    f << simulation. | 
| 248 | 
            +
                    f << simulation.recording.to_csv
         | 
| 246 249 | 
             
                  end
         | 
| 247 250 | 
             
                end
         | 
| 248 251 | 
             
              end
         | 
| 249 252 |  | 
| 250 253 | 
             
              # Plot the recorded samples.
         | 
| 251 254 | 
             
              # 
         | 
| 252 | 
            -
              def plot  | 
| 253 | 
            -
                 | 
| 254 | 
            -
                 | 
| 255 | 
            -
                 | 
| 256 | 
            -
                 | 
| 257 | 
            -
             | 
| 258 | 
            -
                  case plot_what
         | 
| 259 | 
            -
                  when :state then plot_recording oo
         | 
| 260 | 
            -
                  when :flux then plot_flux oo
         | 
| 261 | 
            -
                  when :all then plot_all oo
         | 
| 262 | 
            -
                  else plot_selected *args end
         | 
| 263 | 
            -
                else raise "Too many ordered arguments!" end
         | 
| 264 | 
            -
              end
         | 
| 255 | 
            +
              def plot **features
         | 
| 256 | 
            +
                # --> state feature ids
         | 
| 257 | 
            +
                # --> gradient feature ids
         | 
| 258 | 
            +
                # --> delta feature ids
         | 
| 259 | 
            +
                # --> flux feature ids
         | 
| 260 | 
            +
                # --> firing feature ids
         | 
| 265 261 |  | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 268 | 
            -
             | 
| 269 | 
            -
             | 
| 270 | 
            -
                 | 
| 271 | 
            -
             | 
| 262 | 
            +
                # take these features together
         | 
| 263 | 
            +
             | 
| 264 | 
            +
                # construct the labels and the time series for each
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                # plot them
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                return nil unless sim = world.simulations.values[-1] # sim@point
         | 
| 272 269 | 
             
                # Decide abnout the features
         | 
| 273 270 | 
             
                features = sim.places.dup.map { |p|
         | 
| 274 271 | 
             
                  collection.include?( p ) ? p : nil
         | 
| @@ -285,82 +282,68 @@ module YPetri::Manipulator::SimulationRelatedMethods | |
| 285 282 | 
             
                gnuplot( ᴛ, features.compact.map( &:name ), time_series.compact,
         | 
| 286 283 | 
             
                         title: "Selected features plot", ylabel: "Marking" )
         | 
| 287 284 | 
             
              end
         | 
| 288 | 
            -
                
         | 
| 289 285 |  | 
| 290 286 | 
             
              # Plot the recorded samples (system state history).
         | 
| 291 287 | 
             
              # 
         | 
| 292 | 
            -
              def plot_state(  | 
| 293 | 
            -
                 | 
| 294 | 
            -
                 | 
| 295 | 
            -
                 | 
| 296 | 
            -
             | 
| 297 | 
            -
                features = excluded.each_with_object sim.places.dup do |x, α|
         | 
| 298 | 
            -
                  i = α.index x
         | 
| 299 | 
            -
                  α[i] = nil if i
         | 
| 300 | 
            -
                end
         | 
| 301 | 
            -
                # Get recording
         | 
| 302 | 
            -
                rec = sim.recording
         | 
| 303 | 
            -
                # Select a time series for each feature.
         | 
| 304 | 
            -
                time_series = features.map.with_index do |feature, i|
         | 
| 305 | 
            -
                  feature and rec.map { |key, val| [ key, val[i] ] }.transpose
         | 
| 306 | 
            -
                end
         | 
| 307 | 
            -
                # Time axis
         | 
| 308 | 
            -
                ᴛ = sim.target_time
         | 
| 309 | 
            -
                # Gnuplot call
         | 
| 310 | 
            -
                gnuplot( ᴛ, features.compact.map( &:name ), time_series.compact,
         | 
| 311 | 
            -
                         title: "State plot", ylabel: "Marking" )
         | 
| 288 | 
            +
              def plot_state( place_ids=nil, except: [] )
         | 
| 289 | 
            +
                sim = simulation or return nil
         | 
| 290 | 
            +
                feat = sim.pp( place_ids || sim.pp ) - sim.pp( Array except )
         | 
| 291 | 
            +
                gnuplot sim.record.marking( feat ), time: sim.target_time,
         | 
| 292 | 
            +
                        title: "State plot", ylabel: "Marking"
         | 
| 312 293 | 
             
              end
         | 
| 294 | 
            +
              alias plot_marking plot_state
         | 
| 313 295 |  | 
| 314 296 | 
             
              # Plot the recorded flux (computed flux history at the sampling points).
         | 
| 315 297 | 
             
              # 
         | 
| 316 | 
            -
              def plot_flux(  | 
| 317 | 
            -
                 | 
| 318 | 
            -
                 | 
| 319 | 
            -
                 | 
| 320 | 
            -
                 | 
| 321 | 
            -
                 | 
| 322 | 
            -
             | 
| 323 | 
            -
             | 
| 324 | 
            -
                  if i then α[i] = nil end
         | 
| 298 | 
            +
              def plot_flux( transition_ids=nil, **options )
         | 
| 299 | 
            +
                sim = world.simulations.values[-1] or return nil # sim@point
         | 
| 300 | 
            +
                tt = sim.TS_transitions( transition_ids ).sources
         | 
| 301 | 
            +
                excluded = sim.transitions( Array options[:except] ).sources
         | 
| 302 | 
            +
                tt -= excluded
         | 
| 303 | 
            +
                flux = sim.recording.modify do |time, record|
         | 
| 304 | 
            +
                  [ time,
         | 
| 305 | 
            +
                    sim.at( time: time, marking: record ).TS_transitions( tt ).flux_vector ]
         | 
| 325 306 | 
             
                end
         | 
| 326 | 
            -
                # Get recording.
         | 
| 327 | 
            -
                rec = sim.recording
         | 
| 328 | 
            -
                # Get flux recording.
         | 
| 329 | 
            -
                flux = rec.modify { |ᴛ, ᴍ| [ ᴛ, sim.at( t: ᴛ, m: ᴍ ).flux_for( *all ) ] }
         | 
| 330 307 | 
             
                # Select a time series for each feature.
         | 
| 331 | 
            -
                time_series =  | 
| 332 | 
            -
                   | 
| 308 | 
            +
                time_series = tt.map.with_index do |tr, i|
         | 
| 309 | 
            +
                  tr and flux.map { |time, flux| [ time, flux[i] ] }.transpose
         | 
| 333 310 | 
             
                end
         | 
| 334 311 | 
             
                # Time axis
         | 
| 335 | 
            -
                 | 
| 312 | 
            +
                time = sim.target_time
         | 
| 336 313 | 
             
                # Gnuplot call
         | 
| 337 | 
            -
                gnuplot(  | 
| 314 | 
            +
                gnuplot( time, tt.compact.names, time_series.compact,
         | 
| 338 315 | 
             
                         title: "Flux plot", ylabel: "Flux [µMⁿ.s⁻¹]" )
         | 
| 339 316 | 
             
              end
         | 
| 340 317 |  | 
| 341 318 | 
             
              private
         | 
| 342 319 |  | 
| 343 | 
            -
              # Gnuplots  | 
| 320 | 
            +
              # Gnuplots a recording. Target time or time range can be supplied as :time
         | 
| 321 | 
            +
              # named argument.
         | 
| 344 322 | 
             
              # 
         | 
| 345 | 
            -
              def gnuplot(  | 
| 346 | 
            -
                 | 
| 347 | 
            -
                 | 
| 348 | 
            -
                 | 
| 323 | 
            +
              def gnuplot( dataset, time: nil, **nn )
         | 
| 324 | 
            +
                event_vector = dataset.events
         | 
| 325 | 
            +
                data_vectors = dataset.values.transpose
         | 
| 326 | 
            +
                x_range = if time.is_a? Range then
         | 
| 327 | 
            +
                            "[#{time.begin}:#{time.end}]"
         | 
| 328 | 
            +
                          else
         | 
| 329 | 
            +
                            "[-0:#{SY::Time.magnitude( time ).amount rescue time}]"
         | 
| 330 | 
            +
                          end
         | 
| 331 | 
            +
                labels = recording.features.labels
         | 
| 349 332 |  | 
| 350 333 | 
             
                Gnuplot.open do |gp|
         | 
| 351 334 | 
             
                  Gnuplot::Plot.new( gp ) do |plot|
         | 
| 352 | 
            -
                    plot.xrange  | 
| 353 | 
            -
                    plot.title  | 
| 354 | 
            -
                    plot.ylabel  | 
| 355 | 
            -
                    plot.xlabel  | 
| 356 | 
            -
             | 
| 357 | 
            -
                    labels.zip(  | 
| 358 | 
            -
                      plot.data << Gnuplot::DataSet.new(  | 
| 359 | 
            -
                         | 
| 360 | 
            -
                         | 
| 361 | 
            -
                       | 
| 335 | 
            +
                    plot.xrange x_range
         | 
| 336 | 
            +
                    plot.title nn[:title] || "Simulation plot"
         | 
| 337 | 
            +
                    plot.ylabel nn[:ylabel] || "Values"
         | 
| 338 | 
            +
                    plot.xlabel nn[:xlabel] || "Time [s]"
         | 
| 339 | 
            +
             | 
| 340 | 
            +
                    labels.zip( data_vectors ).each { |label, data_vector|
         | 
| 341 | 
            +
                      plot.data << Gnuplot::DataSet.new( [event_vector, data_vector] ) { |ds|
         | 
| 342 | 
            +
                        ds.with = "linespoints"
         | 
| 343 | 
            +
                        ds.title = lbl
         | 
| 344 | 
            +
                      }
         | 
| 362 345 | 
             
                    }
         | 
| 363 346 | 
             
                  end
         | 
| 364 347 | 
             
                end
         | 
| 365 348 | 
             
              end
         | 
| 366 | 
            -
            end # module YPetri:: | 
| 349 | 
            +
            end # module YPetri::Agent::SimulationRelated
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            #encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Public command interface of YPetri.
         | 
| 4 | 
            +
            # 
         | 
| 5 | 
            +
            module YPetri
         | 
| 6 | 
            +
              class Agent
         | 
| 7 | 
            +
                attr_reader :world
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def initialize
         | 
| 10 | 
            +
                  @world = YPetri::World.new
         | 
| 11 | 
            +
                  super
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                require_relative 'agent/selection'
         | 
| 15 | 
            +
                require_relative 'agent/hash_key_pointer'
         | 
| 16 | 
            +
                require_relative 'agent/petri_net_related'
         | 
| 17 | 
            +
                require_relative 'agent/simulation_related'
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                include self::PetriNetRelated
         | 
| 20 | 
            +
                include self::SimulationRelated
         | 
| 21 | 
            +
              end # class Agent
         | 
| 22 | 
            +
            end # module YPetri
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Euler method.
         | 
| 4 | 
            +
            # 
         | 
| 5 | 
            +
            class YPetri::Core::Timed
         | 
| 6 | 
            +
              module Euler
         | 
| 7 | 
            +
                # Name of this method.
         | 
| 8 | 
            +
                # 
         | 
| 9 | 
            +
                def simulation_method
         | 
| 10 | 
            +
                  :euler
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                # Computes Δ for the period of Δt.
         | 
| 14 | 
            +
                # 
         | 
| 15 | 
            +
                def delta Δt
         | 
| 16 | 
            +
                  gradient * Δt
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
                alias Δ delta
         | 
| 19 | 
            +
              end # Euler
         | 
| 20 | 
            +
            end # YPetri::Core::Timed
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Euler method with timeless transitions firing after each step.
         | 
| 4 | 
            +
            # 
         | 
| 5 | 
            +
            class YPetri::Core::Timed
         | 
| 6 | 
            +
              module PseudoEuler
         | 
| 7 | 
            +
                include Euler
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                # Name of this method.
         | 
| 10 | 
            +
                # 
         | 
| 11 | 
            +
                def simulation_method
         | 
| 12 | 
            +
                  :pseudo_euler
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                # Computes Δ for the period of Δt.
         | 
| 16 | 
            +
                # 
         | 
| 17 | 
            +
                def delta Δt
         | 
| 18 | 
            +
                  super + delta_timeless
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
                alias Δ delta
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                # Makes a single step by Δt.
         | 
| 23 | 
            +
                # 
         | 
| 24 | 
            +
                def step! Δt=simulation.step
         | 
| 25 | 
            +
                  increment_marking_vector Δ( Δt )
         | 
| 26 | 
            +
                  assignment_transitions_all_fire!
         | 
| 27 | 
            +
                  simulation.increment_time! Δt
         | 
| 28 | 
            +
                  alert
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end # PseudoEuler
         | 
| 31 | 
            +
            end # YPetri::Core::Timed
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Euler method with timeless transitions firing every time tick.
         | 
| 4 | 
            +
            # 
         | 
| 5 | 
            +
            class YPetri::Core::Timed
         | 
| 6 | 
            +
              module QuasiEuler
         | 
| 7 | 
            +
                include Euler
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                # Name of this method.
         | 
| 10 | 
            +
                # 
         | 
| 11 | 
            +
                def simulation_method
         | 
| 12 | 
            +
                  :quasi_euler
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                # Makes a single step by Δt.
         | 
| 16 | 
            +
                # 
         | 
| 17 | 
            +
                def step! Δt=simulation.step_size
         | 
| 18 | 
            +
                  fail NotImplementedError
         | 
| 19 | 
            +
                  # Now one would have to compare whichever comes first, time tick or the
         | 
| 20 | 
            +
                  # end of Δt, and then again and again, until Δt is fired...
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end # QuasiEuler
         | 
| 23 | 
            +
            end # YPetri::Core::Timed
         | 
| @@ -0,0 +1,70 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Timed simulation core.
         | 
| 4 | 
            +
            # 
         | 
| 5 | 
            +
            class YPetri::Core
         | 
| 6 | 
            +
              class Timed < YPetri::Core
         | 
| 7 | 
            +
                require_relative 'timed/euler.rb'
         | 
| 8 | 
            +
                require_relative 'timed/pseudo_euler.rb' # timeless fire after each step
         | 
| 9 | 
            +
                require_relative 'timed/quasi_euler.rb'  # timeless fire each time tick
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                # Makes a single step by Δt.
         | 
| 12 | 
            +
                # 
         | 
| 13 | 
            +
                def step! Δt=simulation.step
         | 
| 14 | 
            +
                  increment_marking_vector Δ( Δt )
         | 
| 15 | 
            +
                  increment_time! Δt
         | 
| 16 | 
            +
                  note_state_change
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                # Gradient for free places.
         | 
| 20 | 
            +
                # 
         | 
| 21 | 
            +
                def gradient
         | 
| 22 | 
            +
                  gradient_Ts + gradient_TS
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
                alias ∇ gradient
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                # Gradient contribution by Ts transitions.
         | 
| 27 | 
            +
                # 
         | 
| 28 | 
            +
                def gradient_Ts
         | 
| 29 | 
            +
                  simulation.Ts_gradient_closure.call
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                # Gradient contribution by TS transitions.
         | 
| 33 | 
            +
                # 
         | 
| 34 | 
            +
                def gradient_TS
         | 
| 35 | 
            +
                  ( simulation.TS_stoichiometry_matrix * flux_vector_TS )
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                # Flux vector. The caller asserts that all the timed transitions are
         | 
| 39 | 
            +
                # stoichiometric, or error.
         | 
| 40 | 
            +
                # 
         | 
| 41 | 
            +
                def flux_vector
         | 
| 42 | 
            +
                  msg = "#flux_vector method only applies to the timed simulations with " +
         | 
| 43 | 
            +
                    "no Ts transitions. Try #flux_vector_TS instead!"
         | 
| 44 | 
            +
                  fail msg unless Ts_transitions().empty?
         | 
| 45 | 
            +
                  simulation.TS_rate_closure.call
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                # Flux vector of TS transitions.
         | 
| 49 | 
            +
                # 
         | 
| 50 | 
            +
                def flux_vector_TS
         | 
| 51 | 
            +
                  simulation.TS_rate_closure.call
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
              end # class Timed
         | 
| 54 | 
            +
            end # class YPetri::Core
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            # In general, it is not required that all net elements are simulated with the
         | 
| 57 | 
            +
            # same method. Practically, ODE systems have many good simulation methods
         | 
| 58 | 
            +
            # available.
         | 
| 59 | 
            +
            #
         | 
| 60 | 
            +
            # (1) ᴍ(t) = ϝ f(ᴍ, t).dt, where f(ᴍ, t) is a known function.
         | 
| 61 | 
            +
            #
         | 
| 62 | 
            +
            # Many of these methods depend on the Jacobian, but that may not be available
         | 
| 63 | 
            +
            # for some places. Therefore, the places, whose marking defines the system
         | 
| 64 | 
            +
            # state, are divided into two categories: "A" (accelerated), for which as
         | 
| 65 | 
            +
            # common Jacobian can be found, and "E" places, where "E" can stand either for
         | 
| 66 | 
            +
            # "External" or "Euler".
         | 
| 67 | 
            +
            #
         | 
| 68 | 
            +
            # If we apply the definition of "causal orientation" on A and E places, then it
         | 
| 69 | 
            +
            # can be said, that only the transitions causally oriented towards "A" places
         | 
| 70 | 
            +
            # are allowed for compliance with the equation (1).
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Implicit Euler for timeless nets. Simply, timeless transitions
         | 
| 4 | 
            +
            # fire simultaneously, after which A transitions (if any) fire.
         | 
| 5 | 
            +
            #
         | 
| 6 | 
            +
            class YPetri::Core::Timeless
         | 
| 7 | 
            +
              module PseudoEuler
         | 
| 8 | 
            +
                # Name of this method.
         | 
| 9 | 
            +
                # 
         | 
| 10 | 
            +
                def simulation_method
         | 
| 11 | 
            +
                  :pseudo_euler
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def step!
         | 
| 15 | 
            +
                  increment_marking_vector Δ
         | 
| 16 | 
            +
                  assignment_transitions_all_fire!
         | 
| 17 | 
            +
                  alert
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end # module PseudoEuler
         | 
| 20 | 
            +
            end # class YPetri::Core::Timeless
         |