Class: YPetri::Net

Inherits:
Object
  • Object
show all
Defined in:
lib/y_petri/net.rb,
lib/y_petri/net/timed.rb

Overview

Represents a _Petri net_: A collection of places and transitions. The connector arrows – called arcs in classical Petri net terminology – can be considered a property of transitions. Therefore in YPetri::Net, you won't find arcs as first-class citizens, but only as a synonym denoting nearest neighbors of nodes (places or transitions).

Defined Under Namespace

Modules: NodeAccess, OwnState, Timed, Visualization Classes: DataSet, State

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(places: [], transitions: []) ⇒ Net

Takes 2 arguments (:places and :transitions) and builds a net from them.


38
39
40
41
42
43
44
45
# File 'lib/y_petri/net.rb', line 38

def initialize( places: [], transitions: [] )
  param_class!( { State: State,
                  Simulation: YPetri::Simulation },
                with: { net: self } )
  @places, @transitions = [], []
  places.each &method( :include_place )
  transitions.each &method( :include_transition )
end

Class Method Details

.of(nodes) ⇒ Object

Constructs a net containing a particular set of nodes.


28
29
30
# File 'lib/y_petri/net.rb', line 28

def of nodes
  new.tap { |inst| nodes.each { |node| inst << node } }
end

Instance Method Details

#+(other) ⇒ Object

Creates a new net that contains all the places and transitions of both operands.


135
136
137
138
139
140
# File 'lib/y_petri/net.rb', line 135

def + other
  self.class.send( :new ).tap do |net|
    net.merge! self
    net.merge! other
  end
end

#-(other) ⇒ Object

Returns a new net that is the result of subtraction of the net given as argument from this net.


145
146
147
148
149
150
# File 'lib/y_petri/net.rb', line 145

def - other
  self.class.send( :new ).tap do |net|
    net.include_net self
    net.exclude_net other
  end
end

#<<(node) ⇒ Object

Includes a node (place or transition) in the receiver net.


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/y_petri/net.rb', line 112

def << node
  begin
    type = :place
    place = self.class.place node
  rescue NameError, TypeError
    begin
      type = :transition
      transition = self.class.transition node
    rescue NameError, TypeError => err
      raise TypeError, "Current world contains no place or " +
        "transition #{node}! (#{err})"
    end
  end
  case type # Factored out to minimize the code inside the rescue clause.
  when :place then include_place( place )
  when :transition then include_transition( transition )
  else fail "Implementation error!" end
  return self # important to enable chaining, eg. foo_net << p1 << p2 << t1
end

#==(other) ⇒ Object

Networks are equal when their places and transitions are equal.


173
174
175
176
# File 'lib/y_petri/net.rb', line 173

def == other
  return false unless other.class_complies? self.class
  places == other.places && transitions == other.transitions
end

#exclude_net(id) ⇒ Object

Excludes another net from the receiver net. Returns true if successful (ie. if there was any change to the receiver net), false if the receiver net contained no node of the argument net.


103
104
105
106
107
108
# File 'lib/y_petri/net.rb', line 103

def exclude_net id
  net = Net().instance( id ) rescue YPetri::Net.instance( net )
  t_rslt = net.tt.map { |t| exclude_transition t }.reduce :|
  p_rslt = net.pp.map { |p| exclude_place p }.reduce :|
  p_rslt || t_rslt
end

#exclude_place(place) ⇒ Object

Excludes a place from the receiver. Returns true if successful, false if the place was not found in the receiver net. A place may not be excluded from the receiver so long as any transitions therein connect to it.


72
73
74
75
76
77
# File 'lib/y_petri/net.rb', line 72

def exclude_place place
  place = Place().instance( place )
  fail "Unable to exclude #{place} from #{self}: Transitions depend on it!" if
    transitions.any? { |transition| transition.arcs.include? place }
  false.tap { return true if @places.delete( place ) }
end

#exclude_transition(transition) ⇒ Object

Excludes a transition from the receiver. Returns true if successful, false if the transition was not found in the receiver net.


82
83
84
85
# File 'lib/y_petri/net.rb', line 82

def exclude_transition transition
  transition = Transition().instance( transition )
  false.tap { return true if @transitions.delete( transition ) }
end

#functional?Boolean

Is the net functional?

Returns:

  • (Boolean)

154
155
156
# File 'lib/y_petri/net.rb', line 154

def functional?
  transitions.any? &:functional?
end

#include_net(net) ⇒ Object Also known as: merge!

Includes another net in the receiver net. Returns true if successful (ie. if there was any change to the receiver net), false if the receiver net already includes the argument net.


91
92
93
94
95
96
# File 'lib/y_petri/net.rb', line 91

def include_net net
  net = Net().instance( net ) rescue YPetri::Net.instance( net )
  p_results = net.pp.map &method( :include_place )
  t_results = net.tt.map &method( :include_transition )
  ( p_results + t_results ).reduce :|
end

#include_place(place) ⇒ Object

Includes a place in the receiver. Returns true if successful, false if the place is already included in the receiver net.


50
51
52
53
54
# File 'lib/y_petri/net.rb', line 50

def include_place place
  place = Place().instance( place )
  return false if include_place? place
  true.tap { @places << place }
end

#include_transition(transition) ⇒ Object

Includes a transition in the receiver. Returns true if successful, false if the transition is already included in the net. The arcs of the transition being included may only connect to the places already in the receiver net.


60
61
62
63
64
65
66
# File 'lib/y_petri/net.rb', line 60

def include_transition transition
  transition = Transition().instance( transition )
  return false if include_transition? transition
  fail "Transition #{transition} has arcs to places outside #{self}!" unless
    transition.arcs.all? { |place| include_place? place }
  true.tap { @transitions << transition }
end

#inspectObject

Inspect string of the instance.


189
190
191
# File 'lib/y_petri/net.rb', line 189

def inspect
  to_s
end

#simulation(**settings) ⇒ Object Also known as: new_simulation

Creates a new simulation from the net.


166
167
168
# File 'lib/y_petri/net.rb', line 166

def simulation( **settings )
  Simulation().__new__ **settings
end

#timed?Boolean

Is the net timed?

Returns:

  • (Boolean)

160
161
162
# File 'lib/y_petri/net.rb', line 160

def timed?
  transitions.any? &:timed?
end

#to_sObject

Returns a string briefly describing the net.


180
181
182
183
184
185
# File 'lib/y_petri/net.rb', line 180

def to_s
  form = "#<Net: %s>"
  content = ( name.nil? ? "%s" : "name: #{name}, %s" ) %
    "#{pp.size rescue ''} places, #{tt.size rescue ''} transitions"
  form % content
end