# YPetri `YPetri` is a domain model and a simulator of _functional_ _Petri_ _nets_, a family of Petri nets, whose transitions have functions attached to them. ## Usage `YPetri` provides a _domain_ _specific_ _language_ (DSL), that can be loaded by: ```ruby require 'y_petri' include YPetri ``` Now, one can create places: ```ruby A = Place() B = Place() places.names # you can shorten this to #pn #=> [:A, :B] # Setting their marking: A.marking = 2 B.marking = 5 ``` And transitions: ```ruby A2B = Transition stoichiometry: { A: -1, B: 1 } #=> # A2B.stoichiometry #=> [-1, 1] A2B.s #=> {:A=>-1, :B=>1} A2B.arcs.names #=> [:A, :B] A2B.timeless? #=> true A2B.enabled? #=> true ``` Explanation of the keywords: _arcs_, _enabled_ are standard Petri net terms, _stoichiometry_ means arcs with the amount of tokens to add / take from the connected places when the transition fires, _timeless_ means that firing of the transition is not defined in time. We can now play the _token_ _game_: ```ruby places.map &:marking #=> [2, 5] A2B.fire! places.map &:marking #=> [1, 6] A2B.fire! places.map &:marking #=> [0, 7] ``` ## Advanced usage A Petri net is mostly used as a wiring diagram of some real-world system. Such Petri net can then be used to generate its simulation -- represented by `YPetri::Simulation` class. A Petri net consisting of only _timed_ transitions can be used to generate (implicitly or explicitly) a system of ordinary differential equations (ODE). A simulation generated from such Petri net can then be used to solve (eg.) the initial value problem by numeric methods: ```ruby # Start a fresh irb session! require 'y_petri' include YPetri A = Place default_marking: 0.5 B = Place default_marking: 0.5 A_pump = Transition s: { A: -1 }, rate: proc { 0.005 } B_decay = Transition s: { B: -1 }, rate: 0.05 net #=> # run! ``` Simulation can now be accessed through `simulation` DSL method: ```ruby simulation #=> # simulation.settings #=> {:method=>:pseudo_euler, :guarded=>false, :step=>0.1, :sampling=>5, :time=>0..60} print_recording ``` If you have `gnuplot` gem installed properly, you can view plots: ```ruby plot_state plot_flux ``` So much for the demo for now! Thanks for trying YPetri! ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Added some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request core_ext/array/