petri_net 0.8.0 → 0.9.4
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/.travis.yml +3 -2
- data/Gemfile +3 -0
- data/lib/petri_net/graph/edge.rb +2 -1
- data/lib/petri_net/graph/graph.rb +152 -4
- data/lib/petri_net/graph/node.rb +4 -0
- data/lib/petri_net/net.rb +67 -3
- data/lib/petri_net/version.rb +1 -1
- data/petri_net.gemspec +1 -1
- data/test/reachability_graph/tc_graph.rb +22 -5
- data/test/tc_petri_net.rb +5 -0
- metadata +2 -16
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 785d6ed616e72a8f4229c584b3625bd182dcc354
         | 
| 4 | 
            +
              data.tar.gz: 7ae508f907786e328f3148ab86c5653bdc6e03c2
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 71ec4878553ee6f33000bf9901d2ba1b9707ad3ddb0e793812ec19bbc027ce2ea1a77ee2669f1f625210f82f13744ecd304614379c2348d76fa33288d4600ff0
         | 
| 7 | 
            +
              data.tar.gz: 2eba62b83d60d28a62d14a67d07bb1981a2026a3f693b959f264bd7bd0c9e7f24fe6f556a7415c4db82edb9fd675aff38b8e5d28dee7a8e5634445d8691b4afa
         | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/Gemfile
    CHANGED
    
    
    
        data/lib/petri_net/graph/edge.rb
    CHANGED
    
    | @@ -31,6 +31,7 @@ class PetriNet::Graph::Edge < PetriNet::Base | |
| 31 31 |  | 
| 32 32 | 
             
                # Validates the data holded by this edge, this will be used while adding the edge to the graph
         | 
| 33 33 | 
             
                def validate
         | 
| 34 | 
            +
                    return false unless ( @graph.nodes.has_key? @source.name and @graph.nodes.has_key? @destination.name )
         | 
| 34 35 | 
             
                    true
         | 
| 35 36 | 
             
                end
         | 
| 36 37 |  | 
| @@ -43,7 +44,7 @@ class PetriNet::Graph::Edge < PetriNet::Base | |
| 43 44 | 
             
                    (@source == object.yource && @destination == oject.destination)
         | 
| 44 45 | 
             
                end
         | 
| 45 46 | 
             
                def to_s
         | 
| 46 | 
            -
                    "#{@id}: #{@name} #{@source | 
| 47 | 
            +
                    "#{@id}: #{@name} #{@source} -> #{@destination} )"
         | 
| 47 48 | 
             
                end
         | 
| 48 49 |  | 
| 49 50 | 
             
                private
         | 
| @@ -1,5 +1,7 @@ | |
| 1 1 | 
             
            require 'graphviz'
         | 
| 2 | 
            -
             | 
| 2 | 
            +
            require 'graphviz/theory'
         | 
| 3 | 
            +
            require 'rgl/adjacency'
         | 
| 4 | 
            +
            require 'rgl/dijkstra'
         | 
| 3 5 | 
             
            class PetriNet::InfiniteReachabilityGraphError < RuntimeError
         | 
| 4 6 | 
             
            end
         | 
| 5 7 |  | 
| @@ -7,6 +9,10 @@ class PetriNet::Graph < PetriNet::Base | |
| 7 9 |  | 
| 8 10 | 
             
                # The PetriNet this graph belongs to
         | 
| 9 11 | 
             
                attr_reader :net
         | 
| 12 | 
            +
                # all nodes from this graph
         | 
| 13 | 
            +
                attr_reader :nodes
         | 
| 14 | 
            +
                # all edges of this graph
         | 
| 15 | 
            +
                attr_reader :edges
         | 
| 10 16 |  | 
| 11 17 | 
             
                def initialize(net, options = Hash.new)
         | 
| 12 18 | 
             
                    @net = net
         | 
| @@ -29,6 +35,10 @@ class PetriNet::Graph < PetriNet::Base | |
| 29 35 | 
             
                        node.graph = self
         | 
| 30 36 | 
             
                        return node.id
         | 
| 31 37 | 
             
                    end
         | 
| 38 | 
            +
                    if @objects.include? node
         | 
| 39 | 
            +
                        res = (@objects.index node) * -1
         | 
| 40 | 
            +
                        return res 
         | 
| 41 | 
            +
                    end
         | 
| 32 42 | 
             
                    return false
         | 
| 33 43 | 
             
                end
         | 
| 34 44 | 
             
                alias_method :add_node!, :add_node
         | 
| @@ -38,12 +48,24 @@ class PetriNet::Graph < PetriNet::Base | |
| 38 48 | 
             
                        @objects[edge.id] = edge
         | 
| 39 49 | 
             
                        @edges[edge.name] = edge.id
         | 
| 40 50 | 
             
                        edge.graph = self
         | 
| 51 | 
            +
                        edge.source.outputs << edge.id
         | 
| 52 | 
            +
                        edge.destination.inputs << edge.id
         | 
| 41 53 | 
             
                        return edge.id
         | 
| 42 54 | 
             
                    end
         | 
| 43 55 | 
             
                    return false
         | 
| 44 56 | 
             
                end
         | 
| 45 57 |  | 
| 46 | 
            -
                 | 
| 58 | 
            +
                def get_edge(source, dest)
         | 
| 59 | 
            +
                    res = nil
         | 
| 60 | 
            +
                    @edges.each_value do |edge|
         | 
| 61 | 
            +
                        if @objects[edge].source == source && @objects[edge].destination == dest
         | 
| 62 | 
            +
                            res = @objects[edge]
         | 
| 63 | 
            +
                        end
         | 
| 64 | 
            +
                    end
         | 
| 65 | 
            +
                    res
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                # Add an object to the Graph.
         | 
| 47 69 | 
             
                def <<(object)
         | 
| 48 70 | 
             
                    case object.class.to_s
         | 
| 49 71 | 
             
                    when "Array"
         | 
| @@ -59,7 +81,16 @@ class PetriNet::Graph < PetriNet::Base | |
| 59 81 | 
             
                end
         | 
| 60 82 | 
             
                alias_method :add_object, :<<
         | 
| 61 83 |  | 
| 62 | 
            -
                def get_node( | 
| 84 | 
            +
                def get_node(node)
         | 
| 85 | 
            +
                    if node.class.to_s == "Fixnum"
         | 
| 86 | 
            +
                        return @objects[node]
         | 
| 87 | 
            +
                    end
         | 
| 88 | 
            +
                    if node.class.to_s == "Array"
         | 
| 89 | 
            +
                        return @objects.select{|o| o.class.to_s == "PetriNet::ReachabilityGraph::Node" && o.markings == node}.first
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def get_object(id)
         | 
| 63 94 | 
             
                    @objects[id]
         | 
| 64 95 | 
             
                end
         | 
| 65 96 |  | 
| @@ -71,6 +102,13 @@ class PetriNet::Graph < PetriNet::Base | |
| 71 102 | 
             
                    res
         | 
| 72 103 | 
             
                end
         | 
| 73 104 |  | 
| 105 | 
            +
                def infinite?
         | 
| 106 | 
            +
                    @nodes.each_value do |node|
         | 
| 107 | 
            +
                        return true if @objects[node].infinite?
         | 
| 108 | 
            +
                    end
         | 
| 109 | 
            +
                    false
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
             | 
| 74 112 | 
             
                def to_gv(output = 'png', filename = '')
         | 
| 75 113 | 
             
                    g = generate_gv
         | 
| 76 114 | 
             
                    if filename.empty?
         | 
| @@ -95,7 +133,18 @@ class PetriNet::Graph < PetriNet::Base | |
| 95 133 | 
             
                            e.label = @objects[edge].transition
         | 
| 96 134 | 
             
                        end
         | 
| 97 135 | 
             
                    end
         | 
| 98 | 
            -
                    g
         | 
| 136 | 
            +
                    @gv = g
         | 
| 137 | 
            +
                end
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                def generate_rgl
         | 
| 140 | 
            +
                    g = RGL::DirectedAdjacencyGraph.new 
         | 
| 141 | 
            +
                    @nodes.each_value do |node|
         | 
| 142 | 
            +
                        g.add_vertex @objects[node].markings.to_s
         | 
| 143 | 
            +
                    end
         | 
| 144 | 
            +
                    @edges.each_value do |edge|
         | 
| 145 | 
            +
                        g.add_edge @objects[edge].source.markings.to_s, @objects[edge].destination.markings.to_s
         | 
| 146 | 
            +
                    end
         | 
| 147 | 
            +
                    @rgl = g
         | 
| 99 148 | 
             
                end
         | 
| 100 149 |  | 
| 101 150 | 
             
                def to_s
         | 
| @@ -118,4 +167,103 @@ class PetriNet::Graph < PetriNet::Base | |
| 118 167 | 
             
                    return str
         | 
| 119 168 | 
             
                end
         | 
| 120 169 |  | 
| 170 | 
            +
                def get_rgl
         | 
| 171 | 
            +
                    if @rgl.nil?
         | 
| 172 | 
            +
                        generate_rgl
         | 
| 173 | 
            +
                    end
         | 
| 174 | 
            +
                    @rgl
         | 
| 175 | 
            +
                end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                def cycles
         | 
| 178 | 
            +
                    get_rgl.cycles
         | 
| 179 | 
            +
                end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                def shortest_path(start, destination)
         | 
| 182 | 
            +
                    g = get_rgl
         | 
| 183 | 
            +
                    weights = lambda { |edge| 1 }
         | 
| 184 | 
            +
                    g.dijkstra_shortest_path(weights, start.to_s, destination.to_s)
         | 
| 185 | 
            +
                end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
             | 
| 188 | 
            +
                def path_probability(path)
         | 
| 189 | 
            +
                    sanitize_probabilities
         | 
| 190 | 
            +
                    prob = 1
         | 
| 191 | 
            +
                    counter = 0
         | 
| 192 | 
            +
                    path.each do |node|
         | 
| 193 | 
            +
                        edge = get_edge(path[counter+1], node)
         | 
| 194 | 
            +
                        prob = prob * edge.probability unless edge.nil? # last node has no pre-edge
         | 
| 195 | 
            +
                        counter = counter += 1
         | 
| 196 | 
            +
                    end
         | 
| 197 | 
            +
                    prob
         | 
| 198 | 
            +
                end
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                def node_probability(start, node)
         | 
| 201 | 
            +
                    paths = get_paths_without_loops(start, node)
         | 
| 202 | 
            +
                    prob = 0
         | 
| 203 | 
            +
                    paths.each do |path|
         | 
| 204 | 
            +
                        prob = prob + (path_probability path)
         | 
| 205 | 
            +
                    end
         | 
| 206 | 
            +
                    prob
         | 
| 207 | 
            +
                end
         | 
| 208 | 
            +
             | 
| 209 | 
            +
                def best_path(start, node)
         | 
| 210 | 
            +
                    paths = get_paths_without_loops(start, node)
         | 
| 211 | 
            +
                    prob = 0
         | 
| 212 | 
            +
                    res_path = nil
         | 
| 213 | 
            +
                    paths.each do |path|
         | 
| 214 | 
            +
                        if (path_probability path) >= prob
         | 
| 215 | 
            +
                            prob = (path_probability path)
         | 
| 216 | 
            +
                            res_path = path
         | 
| 217 | 
            +
                        end
         | 
| 218 | 
            +
                    end
         | 
| 219 | 
            +
                    [res_path,prob]
         | 
| 220 | 
            +
                end
         | 
| 221 | 
            +
             | 
| 222 | 
            +
                def worst_path(start, node)
         | 
| 223 | 
            +
                    paths = get_paths_without_loops(start, node)
         | 
| 224 | 
            +
                    prob = 1
         | 
| 225 | 
            +
                    res_path = nil
         | 
| 226 | 
            +
                    paths.each do |path|
         | 
| 227 | 
            +
                        if (path_probability path) <= prob
         | 
| 228 | 
            +
                            prob = (path_probability path)
         | 
| 229 | 
            +
                            res_path = path
         | 
| 230 | 
            +
                        end
         | 
| 231 | 
            +
                    end
         | 
| 232 | 
            +
                    [res_path,prob]
         | 
| 233 | 
            +
                end
         | 
| 234 | 
            +
             | 
| 235 | 
            +
                def get_paths_without_loops(start, goal)
         | 
| 236 | 
            +
                    get_paths_without_loops_helper(get_node(start), get_node(goal)) 
         | 
| 237 | 
            +
                end
         | 
| 238 | 
            +
             | 
| 239 | 
            +
                def sanitize_probabilities
         | 
| 240 | 
            +
                    @nodes.each_value do |node|
         | 
| 241 | 
            +
                        prob = 1.0
         | 
| 242 | 
            +
                        @objects[node].outputs.each do |edge|
         | 
| 243 | 
            +
                            prob = prob + @objects[edge].probability unless @objects[edge].probability.nil?
         | 
| 244 | 
            +
                        end
         | 
| 245 | 
            +
                        @objects[node].outputs.each do |edge|
         | 
| 246 | 
            +
                            @objects[edge].probability = prob/@objects[node].outputs.size if @objects[edge].probability.nil?
         | 
| 247 | 
            +
                        end
         | 
| 248 | 
            +
                    end
         | 
| 249 | 
            +
                end
         | 
| 250 | 
            +
             | 
| 251 | 
            +
             | 
| 252 | 
            +
            private
         | 
| 253 | 
            +
                def get_paths_without_loops_helper(start, goal, reverse_paths = Array.new, reverse_path = Array.new)
         | 
| 254 | 
            +
                    if goal == start
         | 
| 255 | 
            +
                        reverse_path << goal
         | 
| 256 | 
            +
                        reverse_paths << reverse_path
         | 
| 257 | 
            +
                        return nil 
         | 
| 258 | 
            +
                    end
         | 
| 259 | 
            +
                    if reverse_path.include? goal
         | 
| 260 | 
            +
                        return nil
         | 
| 261 | 
            +
                    end
         | 
| 262 | 
            +
                    path = Array.new
         | 
| 263 | 
            +
                    goal.inputs.each do |input|
         | 
| 264 | 
            +
                        get_paths_without_loops_helper(start, @objects[input].source, reverse_paths, reverse_path.clone << goal)
         | 
| 265 | 
            +
                    end
         | 
| 266 | 
            +
                    reverse_paths 
         | 
| 267 | 
            +
                end
         | 
| 268 | 
            +
             | 
| 121 269 | 
             
            end
         | 
    
        data/lib/petri_net/graph/node.rb
    CHANGED
    
    
    
        data/lib/petri_net/net.rb
    CHANGED
    
    | @@ -1,6 +1,10 @@ | |
| 1 1 | 
             
            require 'yaml'
         | 
| 2 | 
            +
            require 'graphviz'
         | 
| 3 | 
            +
            require 'matrix'
         | 
| 4 | 
            +
            require 'bigdecimal/ludcmp'
         | 
| 2 5 |  | 
| 3 6 | 
             
            class PetriNet::Net < PetriNet::Base
         | 
| 7 | 
            +
                include LUSolve
         | 
| 4 8 | 
             
                # Human readable name
         | 
| 5 9 | 
             
                attr_accessor :name
         | 
| 6 10 | 
             
                # Storage filename
         | 
| @@ -240,6 +244,9 @@ Arcs | |
| 240 244 | 
             
                end
         | 
| 241 245 |  | 
| 242 246 | 
             
                def reachability_graph
         | 
| 247 | 
            +
                    if !@up_to_date
         | 
| 248 | 
            +
                        update
         | 
| 249 | 
            +
                    end
         | 
| 243 250 | 
             
                    generate_reachability_graph unless (@graph && @up_to_date)
         | 
| 244 251 | 
             
                    @graph
         | 
| 245 252 | 
             
                end
         | 
| @@ -300,6 +307,18 @@ Arcs | |
| 300 307 | 
             
                    @places.map{|key,pid| @objects[pid].markings.size}
         | 
| 301 308 | 
             
                end
         | 
| 302 309 |  | 
| 310 | 
            +
                def get_marking(places)
         | 
| 311 | 
            +
                    unless places.class.to_s == "Array"
         | 
| 312 | 
            +
                        places = [places]
         | 
| 313 | 
            +
                    end
         | 
| 314 | 
            +
                    if places.first.class.to_s == "Fixnum"
         | 
| 315 | 
            +
                        places.map!{|p| get_place p}
         | 
| 316 | 
            +
                    end
         | 
| 317 | 
            +
                    res = Array.new
         | 
| 318 | 
            +
                    get_place_list.map{|place| if places.include? place.name then res << 1 else res << 0 end}
         | 
| 319 | 
            +
                    res
         | 
| 320 | 
            +
                end
         | 
| 321 | 
            +
             | 
| 303 322 | 
             
                def set_markings(markings)
         | 
| 304 323 | 
             
                    i = 0
         | 
| 305 324 | 
             
                    @places.each_value do |pid| 
         | 
| @@ -313,6 +332,11 @@ Arcs | |
| 313 332 | 
             
                    @places.map{|key,pid| @objects[pid]}
         | 
| 314 333 | 
             
                end
         | 
| 315 334 |  | 
| 335 | 
            +
                def get_place_from_marking(marking)
         | 
| 336 | 
            +
                    return marking if marking.count(1) != 1
         | 
| 337 | 
            +
                    get_place_list[marking.index(1)].name
         | 
| 338 | 
            +
                end
         | 
| 339 | 
            +
             | 
| 316 340 |  | 
| 317 341 | 
             
                def objects_size
         | 
| 318 342 | 
             
                    @objects.count{|o| !o.nil?}
         | 
| @@ -346,8 +370,46 @@ Arcs | |
| 346 370 | 
             
                    get_transition(transition).fire
         | 
| 347 371 | 
             
                end
         | 
| 348 372 |  | 
| 373 | 
            +
                def delta
         | 
| 374 | 
            +
                    if @delta.nil?
         | 
| 375 | 
            +
                        generate_delta
         | 
| 376 | 
            +
                    end
         | 
| 377 | 
            +
                    @delta
         | 
| 378 | 
            +
                end
         | 
| 379 | 
            +
             | 
| 380 | 
            +
                def t_invariants
         | 
| 381 | 
            +
                    delta = self.delta
         | 
| 382 | 
            +
                    zero_vector = Array.new
         | 
| 383 | 
            +
                    delta.row_count.times { zero_vector << 0 }
         | 
| 384 | 
            +
                    zero = BigDecimal("0.0")
         | 
| 385 | 
            +
                    one  = BigDecimal("1.0")
         | 
| 386 | 
            +
             | 
| 387 | 
            +
                    ps = ludecomp(delta.t.to_a.flatten.map{|i|BigDecimal(i,16)},delta.row_count, zero, one)
         | 
| 388 | 
            +
                    x = lusolve(delta.t.to_a.flatten.map{|i|BigDecimal(i,16)},zero_vector.map{|i|BigDecimal(i,16)},ps, zero)
         | 
| 389 | 
            +
             | 
| 390 | 
            +
                    x
         | 
| 391 | 
            +
                end
         | 
| 392 | 
            +
             | 
| 393 | 
            +
                def s_invariant
         | 
| 394 | 
            +
                    raise "Not jet implemented"
         | 
| 395 | 
            +
                end
         | 
| 396 | 
            +
             | 
| 349 397 | 
             
                private
         | 
| 350 398 |  | 
| 399 | 
            +
                def generate_delta
         | 
| 400 | 
            +
                    d = Array.new(@places.size){Array.new(@transitions.size)}
         | 
| 401 | 
            +
                    i = 0
         | 
| 402 | 
            +
                    @places.each do |p_key,p_value|
         | 
| 403 | 
            +
                        j = 0
         | 
| 404 | 
            +
                        @transitions.each do |t_key,t_value|
         | 
| 405 | 
            +
                            d[i][j] = w0(t_value, p_value) - w0(p_value,t_value)
         | 
| 406 | 
            +
                            j += 1
         | 
| 407 | 
            +
                        end
         | 
| 408 | 
            +
                        i += 1
         | 
| 409 | 
            +
                    end
         | 
| 410 | 
            +
                    @delta = Matrix[d]
         | 
| 411 | 
            +
                end
         | 
| 412 | 
            +
             | 
| 351 413 | 
             
                def changed_structure
         | 
| 352 414 | 
             
                    @w_up_to_date = false
         | 
| 353 415 | 
             
                    @up_to_date = false
         | 
| @@ -356,7 +418,6 @@ Arcs | |
| 356 418 | 
             
                def changed_state
         | 
| 357 419 | 
             
                    @up_to_date = false
         | 
| 358 420 | 
             
                end
         | 
| 359 | 
            -
             | 
| 360 421 | 
             
                def reachability_helper(markings, source)
         | 
| 361 422 | 
             
                    @transitions.each_value do |tid|
         | 
| 362 423 | 
             
                        raise PetriNet::ReachabilityGraph::InfinityGraphError if @objects[tid].inputs.empty? && !@objects[tid].outputs.empty?
         | 
| @@ -373,8 +434,11 @@ Arcs | |
| 373 434 | 
             
                                @graph.add_edge PetriNet::ReachabilityGraph::Edge.new(@graph, source: current_node, destination: infinity_node)
         | 
| 374 435 | 
             
                                next 
         | 
| 375 436 | 
             
                            end
         | 
| 376 | 
            -
                             | 
| 377 | 
            -
             | 
| 437 | 
            +
                            if node_id < 0
         | 
| 438 | 
            +
                                current_node = @graph.get_node node_id.abs
         | 
| 439 | 
            +
                            end
         | 
| 440 | 
            +
                            @graph.add_edge PetriNet::ReachabilityGraph::Edge.new(@graph, source: source, destination: current_node, probability: @objects[tid].probability)# if node_id
         | 
| 441 | 
            +
                            reachability_helper get_markings, current_node if node_id >= 0
         | 
| 378 442 | 
             
                        end
         | 
| 379 443 | 
             
                        set_markings markings
         | 
| 380 444 | 
             
                    end
         | 
    
        data/lib/petri_net/version.rb
    CHANGED
    
    
    
        data/petri_net.gemspec
    CHANGED
    
    
| @@ -71,7 +71,7 @@ Edges | |
| 71 71 | 
             
                    @net << PetriNet::Arc.new(source:@net.get_transition('T'), destination:@net.get_place('B'))
         | 
| 72 72 | 
             
                    @net.get_place('A').add_marking
         | 
| 73 73 | 
             
                    rn = @net.generate_reachability_graph
         | 
| 74 | 
            -
                    assert_equal "Reachability Graph [SimpleNet1]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n6: Node6 ([1, 0])\n7: Node7 ([0, 1])\n\nEdges\n----------------------------\n8: Edge8 6 -> 7: Node7 ([0, 1]) )\n\n", rn.to_s
         | 
| 74 | 
            +
                    assert_equal "Reachability Graph [SimpleNet1]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n6: Node6 ([1, 0])\n7: Node7 ([0, 1])\n\nEdges\n----------------------------\n8: Edge8 6: Node6 ([1, 0]) -> 7: Node7 ([0, 1]) )\n\n", rn.to_s
         | 
| 75 75 |  | 
| 76 76 | 
             
                end
         | 
| 77 77 |  | 
| @@ -88,7 +88,7 @@ Edges | |
| 88 88 | 
             
                    @net << PetriNet::Arc.new(source:@net.get_transition('T2'), destination:@net.get_place('C'))
         | 
| 89 89 | 
             
                    @net.get_place('A').add_marking
         | 
| 90 90 | 
             
                    rn = @net.generate_reachability_graph
         | 
| 91 | 
            -
                    assert_equal "Reachability Graph [SimpleNet2]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n10: Node10 ([1, 0, 0])\n11: Node11 ([0, 1, 0])\n13: Node13 ([0, 0, 1])\n\nEdges\n----------------------------\n12: Edge12 10 -> 11: Node11 ([0, 1, 0]) )\n14: Edge14 10 -> 13: Node13 ([0, 0, 1]) )\n\n", rn.to_s
         | 
| 91 | 
            +
                    assert_equal "Reachability Graph [SimpleNet2]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n10: Node10 ([1, 0, 0])\n11: Node11 ([0, 1, 0])\n13: Node13 ([0, 0, 1])\n\nEdges\n----------------------------\n12: Edge12 10: Node10 ([1, 0, 0]) -> 11: Node11 ([0, 1, 0]) )\n14: Edge14 10: Node10 ([1, 0, 0]) -> 13: Node13 ([0, 0, 1]) )\n\n", rn.to_s
         | 
| 92 92 |  | 
| 93 93 | 
             
                end
         | 
| 94 94 |  | 
| @@ -102,7 +102,7 @@ Edges | |
| 102 102 | 
             
                    @net << PetriNet::Arc.new(source:@net.get_transition('T'), destination:@net.get_place('A'))
         | 
| 103 103 | 
             
                    @net.get_place('A').add_marking
         | 
| 104 104 | 
             
                    rn = @net.generate_reachability_graph
         | 
| 105 | 
            -
                    assert_equal "Reachability Graph [SimpleNet3]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n7: Node7 ([1, 0])\n8: Node8 ([1, 1])\n10: Node10 ([Infinity])\n\nEdges\n----------------------------\n9: Edge9 7 -> 8: Node8 ([1, 1]) )\n11: Edge11 8 -> 10: Node10 ([Infinity]) )\n\n", rn.to_s
         | 
| 105 | 
            +
                    assert_equal "Reachability Graph [SimpleNet3]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n7: Node7 ([1, 0])\n8: Node8 ([1, 1])\n10: Node10 ([Infinity])\n\nEdges\n----------------------------\n9: Edge9 7: Node7 ([1, 0]) -> 8: Node8 ([1, 1]) )\n11: Edge11 8: Node8 ([1, 1]) -> 10: Node10 ([Infinity]) )\n\n", rn.to_s
         | 
| 106 106 |  | 
| 107 107 | 
             
                end
         | 
| 108 108 |  | 
| @@ -119,7 +119,7 @@ Edges | |
| 119 119 | 
             
                    @net << PetriNet::Arc.new(source:@net.get_transition('T2'), destination:@net.get_place('A'))
         | 
| 120 120 | 
             
                    @net.get_place('A').add_marking
         | 
| 121 121 | 
             
                    rn = @net.generate_reachability_graph
         | 
| 122 | 
            -
                    assert_equal "Reachability Graph [SimpleNet4]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n10: Node10 ([1, 0])\n11: Node11 ([1, 1])\n13: Node13 ([Infinity])\n15: Node15 ([2, 0])\n17: Node17 ([Infinity])\n\nEdges\n----------------------------\n12: Edge12 10 -> 11: Node11 ([1, 1]) )\n14: Edge14 11 -> 13: Node13 ([Infinity]) )\n16: Edge16 10 -> 15: Node15 ([2, 0]) )\n18: Edge18 15 -> 17: Node17 ([Infinity]) )\n\n", rn.to_s
         | 
| 122 | 
            +
                    assert_equal "Reachability Graph [SimpleNet4]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n10: Node10 ([1, 0])\n11: Node11 ([1, 1])\n13: Node13 ([Infinity])\n15: Node15 ([2, 0])\n17: Node17 ([Infinity])\n\nEdges\n----------------------------\n12: Edge12 10: Node10 ([1, 0]) -> 11: Node11 ([1, 1]) )\n14: Edge14 11: Node11 ([1, 1]) -> 13: Node13 ([Infinity]) )\n16: Edge16 10: Node10 ([1, 0]) -> 15: Node15 ([2, 0]) )\n18: Edge18 15: Node15 ([2, 0]) -> 17: Node17 ([Infinity]) )\n\n", rn.to_s
         | 
| 123 123 |  | 
| 124 124 | 
             
                end
         | 
| 125 125 |  | 
| @@ -136,7 +136,7 @@ Edges | |
| 136 136 | 
             
                    @net.get_place('A').add_marking
         | 
| 137 137 | 
             
                    @net.to_gv_new
         | 
| 138 138 | 
             
                    rn = @net.generate_reachability_graph
         | 
| 139 | 
            -
                    assert_equal "Reachability Graph [SimpleNet5]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n9: Node9 ([1, 0])\n10: Node10 ([0, 1])\n\nEdges\n----------------------------\n11: Edge11 9 -> 10: Node10 ([0, 1]) )\n\n", rn.to_s
         | 
| 139 | 
            +
                    assert_equal "Reachability Graph [SimpleNet5]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n9: Node9 ([1, 0])\n10: Node10 ([0, 1])\n\nEdges\n----------------------------\n11: Edge11 9: Node9 ([1, 0]) -> 10: Node10 ([0, 1]) )\n13: Edge13 10: Node10 ([0, 1]) -> 9: Node9 ([1, 0]) )\n\n", rn.to_s
         | 
| 140 140 |  | 
| 141 141 | 
             
                    rn.to_gv
         | 
| 142 142 | 
             
                end
         | 
| @@ -182,4 +182,21 @@ Edges | |
| 182 182 | 
             
                    @net << PetriNet::Transition.new(name:'T1')
         | 
| 183 183 | 
             
                    @net.generate_reachability_graph # Don't know what to test here, bit this crashed with an Error before...
         | 
| 184 184 | 
             
                end
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                def test_looped_net1
         | 
| 187 | 
            +
                    @net = PetriNet::Net.new(:name => 'LoopedNet1', :description => 'Should be looped')
         | 
| 188 | 
            +
                    @net << PetriNet::Place.new(name: 'A')
         | 
| 189 | 
            +
                    @net << PetriNet::Place.new(name: 'B')
         | 
| 190 | 
            +
                    @net << PetriNet::Transition.new(name:'T1')
         | 
| 191 | 
            +
                    @net << PetriNet::Transition.new(name:'T2')
         | 
| 192 | 
            +
                    @net << PetriNet::Arc.new(source:@net.get_place('A'), destination:@net.get_transition('T1'))
         | 
| 193 | 
            +
                    @net << PetriNet::Arc.new(source:@net.get_place('B'), destination:@net.get_transition('T2'))
         | 
| 194 | 
            +
                    @net << PetriNet::Arc.new(source:@net.get_transition('T1'), destination:@net.get_place('B'))
         | 
| 195 | 
            +
                    @net << PetriNet::Arc.new(source:@net.get_transition('T2'), destination:@net.get_place('A'))
         | 
| 196 | 
            +
                    @net.get_place('A').add_marking
         | 
| 197 | 
            +
                    @net.to_gv_new
         | 
| 198 | 
            +
                    rg = @net.generate_reachability_graph 
         | 
| 199 | 
            +
                    rg.to_gv
         | 
| 200 | 
            +
                    assert_equal "Reachability Graph [LoopedNet1]\n----------------------------\nDescription: \nFilename: \n\nNodes\n----------------------------\n9: Node9 ([1, 0])\n10: Node10 ([0, 1])\n\nEdges\n----------------------------\n11: Edge11 9: Node9 ([1, 0]) -> 10: Node10 ([0, 1]) )\n13: Edge13 10: Node10 ([0, 1]) -> 9: Node9 ([1, 0]) )\n\n", rg.to_s
         | 
| 201 | 
            +
                end
         | 
| 185 202 | 
             
            end
         | 
    
        data/test/tc_petri_net.rb
    CHANGED
    
    | @@ -279,6 +279,11 @@ Edges | |
| 279 279 | 
             
                    assert_equal weight, @net.generate_weight_function
         | 
| 280 280 | 
             
                end
         | 
| 281 281 |  | 
| 282 | 
            +
                def test_t_invariants
         | 
| 283 | 
            +
                    fill_net
         | 
| 284 | 
            +
                    assert BigDecimal("0.0") == @net.t_invariants.first
         | 
| 285 | 
            +
                end
         | 
| 286 | 
            +
             | 
| 282 287 | 
             
                def test_get_markings
         | 
| 283 288 | 
             
                    fill_net
         | 
| 284 289 | 
             
                    @net << PetriNet::Place.new(name: 'place2')
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: petri_net
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.9.4
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - cclausen
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2014- | 
| 11 | 
            +
            date: 2014-05-16 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: ruby-graphviz
         | 
| @@ -24,20 +24,6 @@ dependencies: | |
| 24 24 | 
             
                - - '>='
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 26 | 
             
                    version: '0'
         | 
| 27 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            -
              name: graphviz
         | 
| 29 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            -
                requirements:
         | 
| 31 | 
            -
                - - '>='
         | 
| 32 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            -
                    version: '0'
         | 
| 34 | 
            -
              type: :runtime
         | 
| 35 | 
            -
              prerelease: false
         | 
| 36 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            -
                requirements:
         | 
| 38 | 
            -
                - - '>='
         | 
| 39 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            -
                    version: '0'
         | 
| 41 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 42 28 | 
             
              name: net-sftp
         | 
| 43 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         |