y_petri 2.1.18 → 2.1.20
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/README.md +83 -16
- data/lib/y_petri/net/data_set.rb +8 -0
- data/lib/y_petri/simulation.rb +1 -1
- data/lib/y_petri/version.rb +1 -1
- data/test/simulation_test.rb +4 -3
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 925fd4bc4059984743c3a79a05161f8318bb664b
|
4
|
+
data.tar.gz: 9df7ce42d2a6d90d196b9b0325ce9f547892b228
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d6e49798a1982ffee6b72a5fe210cce73cb30a2dfa32b745cad5d5be27160600cecb6449a786bcff335dfa3b49d3132655c35fb88094716df430c3b66e43c0b9
|
7
|
+
data.tar.gz: 56705a76926aa07e3116038dd216427d4bc07dfc512422d9fc354087b8103e6e67a3722f5b80cbec7075a7d194c77bc1dde1ae57e8005f40f03c5a78cc7c6c4a
|
data/README.md
CHANGED
@@ -1,26 +1,93 @@
|
|
1
1
|
# YPetri
|
2
2
|
|
3
|
-
|
3
|
+
`YPetri` is a domain model and a simulator of _functional_ _Petri_ _nets_,
|
4
|
+
a family of Petri nets, whose transitions have functions attached to them.
|
4
5
|
|
5
|
-
##
|
6
|
-
|
7
|
-
Add this line to your application's Gemfile:
|
8
|
-
|
9
|
-
gem 'y_petri'
|
10
|
-
|
11
|
-
And then execute:
|
12
|
-
|
13
|
-
$ bundle
|
6
|
+
## Usage
|
14
7
|
|
15
|
-
|
8
|
+
`YPetri` provides a _domain_ _specific_ _language_ (DSL), that can be loaded by:
|
9
|
+
```ruby
|
10
|
+
require 'y_petri'
|
11
|
+
include YPetri
|
12
|
+
```
|
13
|
+
Now, one can create places:
|
14
|
+
```ruby
|
15
|
+
A = Place()
|
16
|
+
B = Place()
|
17
|
+
places.names # you can shorten this to #pn
|
18
|
+
#=> [:A, :B]
|
19
|
+
# Setting their marking:
|
20
|
+
A.marking = 2
|
21
|
+
B.marking = 5
|
22
|
+
```
|
23
|
+
And transitions:
|
24
|
+
```ruby
|
25
|
+
A2B = Transition stoichiometry: { A: -1, B: 1 }
|
26
|
+
#=> #<Transition: A2B (tS) >
|
27
|
+
A2B.stoichiometry
|
28
|
+
#=> [-1, 1]
|
29
|
+
A2B.s
|
30
|
+
#=> {:A=>-1, :B=>1}
|
31
|
+
A2B.arcs.names
|
32
|
+
#=> [:A, :B]
|
33
|
+
A2B.timeless?
|
34
|
+
#=> true
|
35
|
+
A2B.enabled?
|
36
|
+
#=> true
|
37
|
+
```
|
38
|
+
Explanation of the keywords: _arcs_, _enabled_ are standard Petri net terms,
|
39
|
+
_stoichiometry_ means arcs with the amount of tokens to add / take from the
|
40
|
+
connected places when the transition fires, _timeless_ means that firing of
|
41
|
+
the transition is not defined in time.
|
16
42
|
|
17
|
-
|
43
|
+
We can now play the _token_ _game_:
|
44
|
+
```ruby
|
45
|
+
places.map &:marking
|
46
|
+
#=> [2, 5]
|
47
|
+
A2B.fire!
|
48
|
+
places.map &:marking
|
49
|
+
#=> [1, 6]
|
50
|
+
A2B.fire!
|
51
|
+
places.map &:marking
|
52
|
+
#=> [0, 7]
|
53
|
+
```
|
18
54
|
|
19
|
-
##
|
55
|
+
## Advanced usage
|
20
56
|
|
21
|
-
|
22
|
-
|
23
|
-
|
57
|
+
A Petri net is mostly used as a wiring diagram of some real-world system. Such
|
58
|
+
Petri net can then be used to generate (implicitly or explicitly) a more specific
|
59
|
+
simulation of that real-world system. This is represented by `YPetri::Simulation`
|
60
|
+
class. If a Petri net with only _timed_ transitions is considered, it can then
|
61
|
+
be used to generate (implicitly or explicitly) a system of ordinary differential
|
62
|
+
equations (ODE). A Simulation class instance generated from such Petri net can
|
63
|
+
then be used to eg. solve the initial value problem by numeric integration of the
|
64
|
+
ODE system using one of the available numerical methods:
|
65
|
+
```ruby
|
66
|
+
# Start a fresh irb session!
|
67
|
+
require 'y_petri'
|
68
|
+
include YPetri
|
69
|
+
A = Place default_marking: 0.5
|
70
|
+
B = Place default_marking: 0.5
|
71
|
+
A_pump = Transition s: { A: -1 }, rate: proc { 0.005 }
|
72
|
+
B_decay = Transition s: { B: -1 }, rate: 0.05
|
73
|
+
net
|
74
|
+
#=> #<Net: name: Top, 2pp, 2tt >
|
75
|
+
run!
|
76
|
+
```
|
77
|
+
Simulation can now be accessed through `simulation` DSL method:
|
78
|
+
```ruby
|
79
|
+
simulation
|
80
|
+
#=> #<Simulation: time: 60, pp: 2, tt: 2, oid: -XXXXXXXXX>
|
81
|
+
simulation.settings
|
82
|
+
#=> {:method=>:pseudo_euler, :guarded=>false, :step=>0.1, :sampling=>5, :time=>0..60}
|
83
|
+
print_recording
|
84
|
+
```
|
85
|
+
If you have `gnuplot` gem installed properly, you can view plots:
|
86
|
+
```ruby
|
87
|
+
plot_state
|
88
|
+
plot_flux
|
89
|
+
```
|
90
|
+
So much for the demo for now! Thanks for trying YPetri!
|
24
91
|
|
25
92
|
## Contributing
|
26
93
|
|
data/lib/y_petri/net/data_set.rb
CHANGED
@@ -252,4 +252,12 @@ class YPetri::Net::DataSet < Hash
|
|
252
252
|
def inspect
|
253
253
|
to_s
|
254
254
|
end
|
255
|
+
|
256
|
+
# Pretty print the dataset.
|
257
|
+
#
|
258
|
+
def print precision: 4, distance: precision + 4
|
259
|
+
features.labels.print_as_line precision: precision, distance: distance
|
260
|
+
puts '-' * features.size * distance
|
261
|
+
records.each.print_as_line precision: precision, distance: distance
|
262
|
+
end
|
255
263
|
end # YPetri::Net::Dataset
|
data/lib/y_petri/simulation.rb
CHANGED
data/lib/y_petri/version.rb
CHANGED
data/test/simulation_test.rb
CHANGED
@@ -119,7 +119,7 @@ describe YPetri::Simulation do
|
|
119
119
|
@sim.ts_tt.first.domain.names.must_equal []
|
120
120
|
@sim.timed?.must_equal false
|
121
121
|
@sim.m.must_equal [1, 2]
|
122
|
-
@sim.
|
122
|
+
@sim.p_m.must_equal( { A: 1, B: 2 } )
|
123
123
|
@sim.recording.must_equal( { 0 => [1, 2]} )
|
124
124
|
@sim.simulation_method.must_equal :pseudo_euler
|
125
125
|
@sim.core.must_be_kind_of YPetri::Core
|
@@ -133,7 +133,7 @@ describe YPetri::Simulation do
|
|
133
133
|
cl = @sim.send( :transitions ).ts.delta_closure
|
134
134
|
cl.call.must_equal Matrix[ [1], [0] ]
|
135
135
|
@sim.step!
|
136
|
-
@sim.
|
136
|
+
@sim.p_m.must_equal( { A: 2, B: 2 } ) # marking of A goes up by 1
|
137
137
|
@sim.recording.must_equal( { 0 => [1, 2], 1 => [2, 2] } )
|
138
138
|
end
|
139
139
|
end
|
@@ -277,7 +277,8 @@ describe "timeless simulation" do
|
|
277
277
|
.must_equal [2.5, 4.5]
|
278
278
|
-> { ds.interpolate( 1.5 ) }.must_raise TypeError
|
279
279
|
ds.reconstruct( event: 2 )
|
280
|
-
.
|
280
|
+
.p_m.must_equal( { U: 2.5, V: 4.5 } )
|
281
|
+
ds.reconstruct( event: 2 ).must_respond_to( :pm )
|
281
282
|
ds.marking.slice( 2..4 ).series
|
282
283
|
.must_equal [[2.5, 2.5, 2.5], [4.5, 5.5, 6.5]]
|
283
284
|
ds.marking.slice( 2..4 )
|