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.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/lib/y_petri/{manipulator → agent}/hash_key_pointer.rb +2 -2
  3. data/lib/y_petri/agent/petri_net_related.rb +115 -0
  4. data/lib/y_petri/{manipulator → agent}/selection.rb +2 -1
  5. data/lib/y_petri/{manipulator/simulation_related_methods.rb → agent/simulation_related.rb} +93 -110
  6. data/lib/y_petri/agent.rb +22 -0
  7. data/lib/y_petri/core/timed/euler.rb +20 -0
  8. data/lib/y_petri/core/timed/pseudo_euler.rb +31 -0
  9. data/lib/y_petri/core/timed/quasi_euler.rb +23 -0
  10. data/lib/y_petri/core/timed.rb +70 -0
  11. data/lib/y_petri/core/timeless/pseudo_euler.rb +20 -0
  12. data/lib/y_petri/core/timeless.rb +12 -0
  13. data/lib/y_petri/core.rb +100 -0
  14. data/lib/y_petri/dsl.rb +66 -0
  15. data/lib/y_petri/fixed_assets.rb +7 -0
  16. data/lib/y_petri/net/element_access.rb +239 -0
  17. data/lib/y_petri/net/state/feature/delta.rb +88 -0
  18. data/lib/y_petri/net/state/feature/firing.rb +57 -0
  19. data/lib/y_petri/net/state/feature/flux.rb +58 -0
  20. data/lib/y_petri/net/state/feature/gradient.rb +75 -0
  21. data/lib/y_petri/net/state/feature/marking.rb +62 -0
  22. data/lib/y_petri/net/state/feature.rb +79 -0
  23. data/lib/y_petri/net/state/features/dataset.rb +135 -0
  24. data/lib/y_petri/net/state/features/record.rb +50 -0
  25. data/lib/y_petri/net/state/features.rb +126 -0
  26. data/lib/y_petri/net/state.rb +121 -0
  27. data/lib/y_petri/net/timed.rb +8 -0
  28. data/lib/y_petri/net/visualization.rb +3 -3
  29. data/lib/y_petri/net.rb +73 -77
  30. data/lib/y_petri/place.rb +8 -3
  31. data/lib/y_petri/simulation/dependency.rb +107 -0
  32. data/lib/y_petri/simulation/element_representation.rb +20 -0
  33. data/lib/y_petri/simulation/elements/access.rb +57 -0
  34. data/lib/y_petri/simulation/elements.rb +45 -0
  35. data/lib/y_petri/simulation/feature_set.rb +21 -0
  36. data/lib/y_petri/simulation/initial_marking/access.rb +55 -0
  37. data/lib/y_petri/simulation/initial_marking.rb +15 -0
  38. data/lib/y_petri/simulation/marking_clamps/access.rb +34 -0
  39. data/lib/y_petri/simulation/marking_clamps.rb +18 -0
  40. data/lib/y_petri/simulation/marking_vector/access.rb +106 -0
  41. data/lib/y_petri/simulation/marking_vector.rb +156 -0
  42. data/lib/y_petri/simulation/matrix.rb +64 -0
  43. data/lib/y_petri/simulation/place_mapping.rb +62 -0
  44. data/lib/y_petri/simulation/place_representation.rb +74 -0
  45. data/lib/y_petri/simulation/places/access.rb +121 -0
  46. data/lib/y_petri/simulation/places/clamped.rb +8 -0
  47. data/lib/y_petri/simulation/places/free.rb +8 -0
  48. data/lib/y_petri/simulation/places/types.rb +25 -0
  49. data/lib/y_petri/simulation/places.rb +41 -0
  50. data/lib/y_petri/simulation/recorder.rb +54 -0
  51. data/lib/y_petri/simulation/timed/recorder.rb +53 -0
  52. data/lib/y_petri/simulation/timed.rb +161 -261
  53. data/lib/y_petri/simulation/timeless/recorder.rb +25 -0
  54. data/lib/y_petri/simulation/timeless.rb +35 -0
  55. data/lib/y_petri/simulation/transition_representation/A.rb +58 -0
  56. data/lib/y_petri/simulation/transition_representation/S.rb +45 -0
  57. data/lib/y_petri/simulation/transition_representation/T.rb +80 -0
  58. data/lib/y_petri/simulation/transition_representation/TS.rb +46 -0
  59. data/lib/y_petri/simulation/transition_representation/Ts.rb +32 -0
  60. data/lib/y_petri/simulation/transition_representation/a.rb +30 -0
  61. data/lib/y_petri/simulation/transition_representation/s.rb +29 -0
  62. data/lib/y_petri/simulation/transition_representation/t.rb +37 -0
  63. data/lib/y_petri/simulation/transition_representation/tS.rb +38 -0
  64. data/lib/y_petri/simulation/transition_representation/ts.rb +32 -0
  65. data/lib/y_petri/simulation/transition_representation/types.rb +62 -0
  66. data/lib/y_petri/simulation/transition_representation.rb +79 -0
  67. data/lib/y_petri/simulation/transitions/A.rb +40 -0
  68. data/lib/y_petri/simulation/transitions/S.rb +24 -0
  69. data/lib/y_petri/simulation/transitions/T.rb +34 -0
  70. data/lib/y_petri/simulation/transitions/TS.rb +57 -0
  71. data/lib/y_petri/simulation/transitions/Ts.rb +60 -0
  72. data/lib/y_petri/simulation/transitions/a.rb +8 -0
  73. data/lib/y_petri/simulation/transitions/access.rb +186 -0
  74. data/lib/y_petri/simulation/transitions/s.rb +9 -0
  75. data/lib/y_petri/simulation/transitions/t.rb +22 -0
  76. data/lib/y_petri/simulation/transitions/tS.rb +55 -0
  77. data/lib/y_petri/simulation/transitions/ts.rb +58 -0
  78. data/lib/y_petri/simulation/transitions/types.rb +98 -0
  79. data/lib/y_petri/simulation/transitions.rb +21 -0
  80. data/lib/y_petri/simulation.rb +176 -781
  81. data/lib/y_petri/transition/assignment.rb +7 -5
  82. data/lib/y_petri/transition/construction.rb +119 -187
  83. data/lib/y_petri/transition/init.rb +311 -0
  84. data/lib/y_petri/transition/ordinary_timeless.rb +8 -6
  85. data/lib/y_petri/transition/timed.rb +11 -18
  86. data/lib/y_petri/transition.rb +104 -132
  87. data/lib/y_petri/version.rb +1 -1
  88. data/lib/y_petri/world/dependency.rb +40 -0
  89. data/lib/y_petri/world/petri_net_related.rb +61 -0
  90. data/lib/y_petri/{workspace/simulation_related_methods.rb → world/simulation_related.rb} +42 -49
  91. data/lib/y_petri/world.rb +27 -0
  92. data/lib/y_petri.rb +47 -99
  93. data/test/{manipulator_test.rb → agent_test.rb} +19 -17
  94. data/{lib/y_petri → test/examples}/demonstrator.rb +0 -0
  95. data/{lib/y_petri → test/examples}/demonstrator_2.rb +1 -0
  96. data/{lib/y_petri → test/examples}/demonstrator_3.rb +0 -0
  97. data/{lib/y_petri → test/examples}/demonstrator_4.rb +0 -0
  98. data/test/examples/example_2.rb +16 -0
  99. data/test/{manual_examples.rb → examples/manual_examples.rb} +0 -0
  100. data/test/net_test.rb +126 -121
  101. data/test/place_test.rb +1 -1
  102. data/test/sim_test +565 -0
  103. data/test/simulation_test.rb +338 -264
  104. data/test/transition_test.rb +77 -174
  105. data/test/world_mock.rb +12 -0
  106. data/test/{workspace_test.rb → world_test.rb} +19 -20
  107. data/test/y_petri_test.rb +4 -5
  108. metadata +101 -26
  109. data/lib/y_petri/dependency_injection.rb +0 -45
  110. data/lib/y_petri/manipulator/petri_net_related_methods.rb +0 -74
  111. data/lib/y_petri/manipulator.rb +0 -20
  112. data/lib/y_petri/net/selections.rb +0 -209
  113. data/lib/y_petri/simulation/collections.rb +0 -460
  114. data/lib/y_petri/workspace/parametrized_subclassing.rb +0 -22
  115. data/lib/y_petri/workspace/petri_net_related_methods.rb +0 -88
  116. data/lib/y_petri/workspace.rb +0 -16
  117. data/test/timed_simulation_test.rb +0 -153
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+
3
+ class YPetri::Net::State
4
+ class Feature
5
+ # Marking of a Petri net place.
6
+ #
7
+ class Marking < Feature
8
+ attr_reader :place
9
+
10
+ class << self
11
+ def parametrize *args
12
+ Class.instance_method( :parametrize ).bind( self ).( *args ).tap do |ç|
13
+ ç.instance_variable_set( :@instances,
14
+ Hash.new do |hsh, id|
15
+ case id
16
+ when Marking then
17
+ hsh[ id.place ]
18
+ when ç.net.Place then
19
+ hsh[ id ] = ç.__new__( id )
20
+ else
21
+ hsh[ ç.net.place( id ) ]
22
+ end
23
+ end )
24
+ end
25
+ end
26
+
27
+ attr_reader :instances
28
+
29
+ alias __new__ new
30
+
31
+ def new id
32
+ instances[ id ]
33
+ end
34
+
35
+ def of id
36
+ new id
37
+ end
38
+ end
39
+
40
+ def initialize place
41
+ @place = net.place( place )
42
+ end
43
+
44
+ def extract_from arg, **nn
45
+ case arg
46
+ when YPetri::Simulation then
47
+ arg.m( [ place ] ).first
48
+ else
49
+ fail TypeError, "Argument type not supported!"
50
+ end
51
+ end
52
+
53
+ def to_s
54
+ place.name
55
+ end
56
+
57
+ def label
58
+ ":#{place.name}"
59
+ end
60
+ end # class Marking
61
+ end # class Feature
62
+ end # YPetri::Net::State
@@ -0,0 +1,79 @@
1
+ # encoding: utf-8
2
+
3
+ class YPetri::Net::State
4
+ # A feature of a Petri net.
5
+ #
6
+ class Feature
7
+ require_relative 'feature/marking'
8
+ require_relative 'feature/firing'
9
+ require_relative 'feature/gradient'
10
+ require_relative 'feature/flux'
11
+ require_relative 'feature/delta'
12
+
13
+ class << self
14
+ def parametrize parameters
15
+ Class.new( self ).tap do |ç|
16
+ parameters.each_pair { |symbol, value|
17
+ ç.define_singleton_method symbol do value end
18
+ }
19
+ sç = ç.State
20
+ ç.instance_variable_set :@Marking, Marking.parametrize( State: sç )
21
+ ç.instance_variable_set :@Firing, Firing.parametrize( State: sç )
22
+ ç.instance_variable_set :@Gradient, Gradient.parametrize( State: sç )
23
+ ç.instance_variable_set :@Flux, Flux.parametrize( State: sç )
24
+ ç.instance_variable_set :@Delta, Delta.parametrize( State: sç )
25
+ end
26
+ end
27
+
28
+ delegate :net,
29
+ to: "State()"
30
+
31
+ def Marking id=L!
32
+ return @Marking if id.local_object?
33
+ case id
34
+ when Marking() then id
35
+ when Marking then Marking().of( id.place )
36
+ else Marking().of( id ) end # assume it's a place
37
+ end
38
+
39
+ def Firing id=L!
40
+ return @Firing if id.local_object?
41
+ case id
42
+ when Firing() then id
43
+ when Firing then Firing().of( id.transition )
44
+ else Firing().of( id ) end # assume it's a place
45
+ end
46
+
47
+ def Gradient id=L!, transitions: net.T_tt
48
+ return @Gradient if id.local_object?
49
+ case id
50
+ when Gradient() then id
51
+ when Gradient then
52
+ Gradient().of( id.place, transitions: id.transitions )
53
+ else Gradient().of( id, transitions: transitions ) end # assume it's a place
54
+ end
55
+
56
+ def Flux id=L!
57
+ return @Flux if id.local_object?
58
+ case id
59
+ when Flux() then id
60
+ when Flux then Flux().of( id.transition )
61
+ else Flux().of( id ) end # assume it's a place
62
+ end
63
+
64
+ def Delta id=L!, transitions: net.tt
65
+ return @Delta if id.local_object?
66
+ case id
67
+ when Delta() then id
68
+ when Delta then
69
+ Delta().of( id.place, transitions: id.transitions )
70
+ else Delta().of( id, transitions: transitions ) end # assume it's a place
71
+ end
72
+ end # class << self
73
+
74
+ delegate :net,
75
+ :State,
76
+ :Marking, :Firing, :Gradient, :Flux, :Delta,
77
+ to: "self.class"
78
+ end # class Feature
79
+ end # YPetri::Net::State
@@ -0,0 +1,135 @@
1
+ # encoding: utf-8
2
+
3
+ class YPetri::Net::State
4
+ class Features
5
+ # Dataset is a collection of labeled state records.
6
+ #
7
+ class Dataset < Hash
8
+ class << self
9
+ alias __new__ new
10
+
11
+ def new
12
+ __new__ do |hsh, missing|
13
+ case missing
14
+ when Float then nil
15
+ else hsh[ missing.to_f ] end
16
+ end
17
+ end
18
+ end
19
+
20
+ alias events keys
21
+ alias records values
22
+
23
+ delegate :features, to: "self.class"
24
+ delegate :net, to: :features
25
+ delegate :State, to: :net
26
+
27
+ # Revives records from values.
28
+ #
29
+ def records
30
+ values.map { |value| features.Record.new( value ) }
31
+ end
32
+
33
+ # Recreates the simulation at a given event label.
34
+ #
35
+ def reconstruct event: event, **settings # settings include marking clampls
36
+ interpolate( event ).reconstruct **settings
37
+ end
38
+
39
+ # Interpolates the recording an the given point (event).
40
+ #
41
+ def interpolate( event )
42
+ # TODO: This whole interpolation thing is unfinished.
43
+ begin
44
+ record( event )
45
+ rescue KeyError => msg
46
+ timed? or raise TypeError, "Event #{event} does not have a record!"
47
+ f_time, floor = floor( event ) # timed datasets support floor, ceiling
48
+ c_time, ceiling = ceiling( time )
49
+ floor + ( ceiling - floor ) / ( c_time - f_time ) * ( time - f_time )
50
+ end
51
+ end
52
+
53
+ # Returns the data series for the specified features.
54
+ #
55
+ def series arg=nil
56
+ return records.transpose if arg.nil?
57
+ reduce_features( State().features( arg ) ).series
58
+ end
59
+
60
+ # Expects a hash of features (:marking (alias :state) of places, :firing
61
+ # of tS transitions, :delta of places and/or transitions) and returns the
62
+ # corresponding mapping of the recording.
63
+ #
64
+ def reduce_features features
65
+ rf = net.State.features( features )
66
+ rr_class = rf.Record
67
+ rf.new_dataset.tap do |ds|
68
+ ( events >> records ).each_pair { |event, record|
69
+ ds.update event => rr_class.load( rf.map { |f| record.fetch f } )
70
+ }
71
+ end
72
+ end
73
+
74
+ def marking *args
75
+ return reduce_features features.select { |f| f.is_a? YPetri::Net::State::Feature::Marking } if args.empty?
76
+ reduce_features marking: args.first
77
+ end
78
+
79
+ def firing *args
80
+ return reduce_features features.select { |f| f.is_a? YPetri::Net::State::Feature::Firing } if args.empty?
81
+ reduce_features firing: args.first
82
+ end
83
+
84
+ def flux *args
85
+ return reduce_features features.select { |f| f.is_a? YPetri::Net::State::Feature::Flux } if args.empty?
86
+ reduce_features flux: args.first
87
+ end
88
+
89
+ def gradient *args
90
+ return reduce_features features.select { |f| f.is_a? YPetri::Net::State::Feature::Gradient } if args.empty?
91
+ reduce_features gradient: args
92
+ end
93
+
94
+ def delta *args
95
+ return reduce_features features.select { |f| f.is_a? YPetri::Net::State::Feature::Delta } if args.empty?
96
+ reduce_features delta: args
97
+ end
98
+
99
+ # Outputs the current recording in CSV format.
100
+ #
101
+ def to_csv
102
+ map { |lbl, rec| [ lbl, *rec ].join ',' }.join "\n"
103
+ end
104
+
105
+ # Plots the dataset.
106
+ #
107
+ def plot time: nil, **nn
108
+ events = events()
109
+ data_ss = series
110
+ x_range = if time.is_a? Range then
111
+ "[#{time.begin}:#{time.end}]"
112
+ else
113
+ "[-0:#{SY::Time.magnitude( time ).amount rescue time}]"
114
+ end
115
+
116
+ Gnuplot.open do |gp|
117
+ Gnuplot::Plot.new gp do |plot|
118
+ plot.xrange x_range
119
+ plot.title nn[:title] || "#{net} plot"
120
+ plot.ylabel nn[:ylabel] || "Values"
121
+ plot.xlabel nn[:xlabel] || "Time [s]"
122
+
123
+ features.labels.zip( data_ss )
124
+ .each { |label, data_array|
125
+ plot.data << Gnuplot::DataSet.new( [ events, data_array ] ) { |ds|
126
+ ds.with = "linespoints"
127
+ ds.title = label
128
+ }
129
+ }
130
+ end
131
+ end
132
+ end
133
+ end # class Dataset
134
+ end # class Features
135
+ end # YPetri::Simulation::State
@@ -0,0 +1,50 @@
1
+ class YPetri::Net::State
2
+ class Features
3
+ # A collection of values for a given set of state features.
4
+ #
5
+ class Record < Array
6
+ class << self
7
+ delegate :State,
8
+ :net,
9
+ to: "Features()"
10
+
11
+ # Construcs a new Record object from a given collection of values.
12
+ #
13
+ def load values
14
+ new( values.dup )
15
+ end
16
+ end
17
+
18
+ delegate :Features,
19
+ :State,
20
+ :net,
21
+ :features,
22
+ to: "self.class"
23
+
24
+ # Outputs the record as a plain array.
25
+ #
26
+ def dump precision: nil
27
+ features.map { |f| fetch( f ).round( precision ) }
28
+ end
29
+
30
+ # Returns an identified feature, or fails.
31
+ #
32
+ def fetch feature
33
+ super begin
34
+ Integer( feature )
35
+ rescue TypeError
36
+ features.index State().feature( feature )
37
+ end
38
+ end
39
+
40
+ # Returns the state instance implied by the receiver record, and a set of
41
+ # complementary marking clamps supplied as the argument.
42
+ #
43
+ def state marking_clamps: {}
44
+ State.new self, marking_clamps: marking_clamps
45
+ end
46
+
47
+ delegate :reconstruct, to: :state
48
+ end # class Record
49
+ end # class Features
50
+ end # YPetri::Net::State
@@ -0,0 +1,126 @@
1
+ # encoding: utf-8
2
+
3
+ class YPetri::Net::State
4
+ # A set of state features.
5
+ #
6
+ class Features < Array
7
+ require_relative 'features/record'
8
+ require_relative 'features/dataset'
9
+
10
+ class << self
11
+ # Customization of the parametrize method for the Features class: Its
12
+ # dependents Record and Dataset are also parametrized.
13
+ #
14
+ def parametrize parameters
15
+ Class.new( self ).tap do |subclass|
16
+ parameters.each_pair { |symbol, value|
17
+ subclass.define_singleton_method symbol do value end
18
+ }
19
+ subclass.param_class( { Record: Record, Dataset: Dataset },
20
+ with: { Features: subclass } )
21
+ end
22
+ end
23
+
24
+ delegate :net,
25
+ :Feature,
26
+ :feature,
27
+ to: "State()"
28
+
29
+ delegate :Marking,
30
+ :Firing,
31
+ :Gradient,
32
+ :Flux,
33
+ :Delta,
34
+ to: "Feature()"
35
+
36
+ delegate :load, to: :Record
37
+
38
+ alias __new__ new
39
+
40
+ def new features
41
+ ff = features.map &method( :feature )
42
+ __new__( ff ).tap do |inst|
43
+ # Parametrize them <em>one more time</em> with Features instance.
44
+ # Banged version of #param_class! ensures that #Record, #Dataset
45
+ # methods are shadowed.
46
+ inst.param_class!( { Record: Record(), Dataset: Dataset() },
47
+ with: { features: inst } )
48
+ end
49
+ end
50
+
51
+ def marking places=net.pp
52
+ new net.pp( places ).map { |p| Marking( p ) }
53
+ end
54
+
55
+ def firing transitions=net.tS_tt
56
+ new net.tS_tt( transitions ).map { |t| Firing( t ) }
57
+ end
58
+
59
+ def gradient places=net.pp, transitions: net.T_tt
60
+ tt = net.T_tt( transitions )
61
+ new net.pp( places ).map { |p|
62
+ Gradient( p, transitions: tt )
63
+ }
64
+ end
65
+
66
+ def flux transitions=net.TS_tt
67
+ new net.TS_tt( transitions ).map { |t| Flux( t ) }
68
+ end
69
+
70
+ def delta places=net.pp, transitions: net.tt
71
+ transitions = net.tt( transitions )
72
+ new net.pp( places ).map { |p|
73
+ Delta( p, transitions: transitions )
74
+ }
75
+ end
76
+ end
77
+
78
+ delegate :State,
79
+ :net,
80
+ :Feature,
81
+ :feature,
82
+ :Marking,
83
+ :Firing,
84
+ :Gradient,
85
+ :Flux,
86
+ :Delta,
87
+ :load,
88
+ to: "self.class"
89
+
90
+ # Extracts the features from a given target
91
+ #
92
+ def extract_from target, **nn
93
+ Record().new( map { |feature| feature.extract_from( target, **nn ) } )
94
+ end
95
+
96
+ # Constructs a new dataset from these features.
97
+ #
98
+ def new_dataset
99
+ Dataset().new
100
+ end
101
+
102
+ # Feature summation -- of feature class.
103
+ #
104
+ def + other
105
+ self.class.new( super )
106
+ end
107
+
108
+ # Feature summation -- of feature class.
109
+ #
110
+ def - other
111
+ self.class.new( super )
112
+ end
113
+
114
+ # Feature summation -- of feature class.
115
+ #
116
+ def * other
117
+ self.class.new( super )
118
+ end
119
+
120
+ # Feature labels.
121
+ #
122
+ def labels
123
+ map &:label
124
+ end
125
+ end # class Features
126
+ end # YPetri::Net::State
@@ -0,0 +1,121 @@
1
+ # encoding: utf-8
2
+
3
+ class YPetri::Net
4
+ # Petri net state (marking of all its places).
5
+ #
6
+ class State < Array
7
+ require_relative 'state/feature'
8
+ require_relative 'state/features'
9
+
10
+ class << self
11
+ # Customization of the parametrize method for the State class: Its
12
+ # dependents Feature and Features (ie. feature set) are also parametrized.
13
+ #
14
+ def parametrize net: (fail ArgumentError, "No owning net!")
15
+ Class.new( self ).tap do |subclass|
16
+ subclass.define_singleton_method :net do net end
17
+ subclass.param_class( { Feature: Feature,
18
+ Features: Features },
19
+ with: { State: subclass } )
20
+ end
21
+ end
22
+
23
+ delegate :Marking,
24
+ :Firing,
25
+ :Gradient,
26
+ :Flux,
27
+ :Delta,
28
+ to: "Feature()"
29
+
30
+ alias __new__ new
31
+
32
+ # Revives a state from a record and a given set of marking clamps.
33
+ #
34
+ def new record, marking_clamps: {}
35
+ cc = marking_clamps.with_keys { |k| net.place k }.with_values! do |v|
36
+ case v
37
+ when YPetri::Place then v.marking
38
+ when ~:call then v.call
39
+ else v end
40
+ end
41
+
42
+ record = features( marking: net.pp - cc.keys ).load( record )
43
+
44
+ __new__ net.pp.map do |p|
45
+ begin; cc.fetch p; rescue IndexError
46
+ record.fetch Marking().of( p )
47
+ end
48
+ end
49
+ end
50
+
51
+ # Returns the feature identified by the argument.
52
+ #
53
+ def feature id
54
+ case id
55
+ when Feature() then id
56
+ when Feature then id.class.new( id )
57
+ else
58
+ features( id ).tap do |ff|
59
+ ff.size == 1 or fail ArgumentError, "Argument #{id} must identify " +
60
+ "exactly 1 feature!"
61
+ end.first
62
+ end
63
+ end
64
+
65
+ # If the argument is an array of features, or another Features instance,
66
+ # a feature set based on this array is returned. But the real purpose of
67
+ # this method is to allow hash-type argument, with keys +:marking+,
68
+ # +:firing+, +:gradient+, +:flux+ and +:delta+, specifying the respective
69
+ # features. For +:marking+, an array of places (or Marking features) is
70
+ # expected. For +:firing+ and +:flux+, an array of transitions (or Firing
71
+ # / Flux features) is expected. For +:gradient+ and +:delta+, a hash value
72
+ # is expected, containing keys +:places+ and +:transitions+, specifying
73
+ # for which place set / transition set should gradient / delta features
74
+ # be constructed. More in detail, values supplied under keys +:marking+,
75
+ # +:firing+, +:gradient+, +:flux+ and +:delta+ are delegated to
76
+ # +Features.marking+, +Features.firing+, +Features.gradient+ and
77
+ # +Features.flux+ methods, and their results are joined into a single
78
+ # feature set.
79
+ #
80
+ def features arg
81
+ case arg
82
+ when Features(), Array then Features().new( arg )
83
+ else # the real job of the method
84
+ marking = arg[:marking] || []
85
+ firing = arg[:firing] || [] # array of tS transitions
86
+ gradient = arg[:gradient] || [ [], transitions: [] ]
87
+ flux = arg[:flux] || [] # array of TS transitions
88
+ delta = arg[:delta] || [ [], transitions: [] ]
89
+ [ Features().marking( marking ),
90
+ Features().firing( firing ),
91
+ Features().gradient( *gradient ),
92
+ Features().flux( flux ),
93
+ Features().delta( *delta ) ].reduce :+
94
+ end
95
+ end
96
+
97
+ delegate :marking, :firing, :gradient, :flux, :delta, to: "Features()"
98
+ end
99
+
100
+ # For non-parametrized vesion of the class, the class instance variables
101
+ # hold the non-parametrized dependent classes.
102
+ #
103
+ @Feature, @Features = Feature, Features
104
+
105
+ delegate :net,
106
+ :Feature,
107
+ :Features,
108
+ :features,
109
+ :marking, :firing, :gradient, :flux, :delta,
110
+ to: "self.class"
111
+
112
+ # Reconstructs a simulation from the current state instance, given marking
113
+ # clamps and other simulation settings.
114
+ #
115
+ def reconstruct marking_clamps: {}, **settings
116
+ net.simulation marking: to_hash,
117
+ marking_clamps: marking_clamps,
118
+ **settings
119
+ end
120
+ end # class State
121
+ end # YPetri::Net
@@ -0,0 +1,8 @@
1
+ # encoding: utf-8
2
+
3
+ class YPetri::Net
4
+ # A mixin for timed nets, used by +#extend+ call during init.
5
+ #
6
+ module Timed
7
+ end # module Timed
8
+ end # class YPetri::Net
@@ -19,10 +19,10 @@ class YPetri::Net
19
19
  ꜧ[tr] = γ.add_nodes tr.name.to_s,
20
20
  shape: 'box',
21
21
  fillcolor: if tr.assignment? then 'yellow'
22
- elsif tr.basic_type == :SR then 'lightcyan'
22
+ elsif tr.type == :TS then 'lightcyan'
23
23
  else 'ghostwhite' end,
24
24
  color: if tr.assignment? then 'goldenrod'
25
- elsif tr.basic_type == :SR then 'cyan'
25
+ elsif tr.type == :TS then 'cyan'
26
26
  else 'grey' end,
27
27
  style: 'filled'
28
28
  end
@@ -35,7 +35,7 @@ class YPetri::Net
35
35
  ( tr.domain - tr.codomain ).each { |pl|
36
36
  γ.add_edges tr_node, place_nodes[pl], color: 'grey', arrowhead: 'none'
37
37
  }
38
- elsif tr.basic_type == :SR then
38
+ elsif tr.type == :TS then
39
39
  tr.codomain.each { |pl|
40
40
  if tr.stoichio[pl] > 0 then # producing arc
41
41
  γ.add_edges tr_node, place_nodes[pl], color: 'cyan'