dither 0.1.3 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c63e06dd14ae60b7f896ba8b994342685a5a118f
4
- data.tar.gz: 2301ba688f8160c579591c15c8230ee27ec5e803
3
+ metadata.gz: ddb46b01324c8b26f43cfecca3e4685eb49108d4
4
+ data.tar.gz: 08c81cf35fbf9eaf3633462e024f9c9f6852803d
5
5
  SHA512:
6
- metadata.gz: 991fd2981ad978594df9116deb0cc51ade974a2f34c5b62d2a470688e82bf7f3eae8697a3e877d24b248bc0aabf40e41207f69be41b74609a8b734210ed668e1
7
- data.tar.gz: d599badafa4375dd11f9fe120c720a44d4d997abec9f8e1ecdea352d6db557e2bf819eed1a06ffe6ea1301aad86c64b39eff3ee8e0aec9b0b5362aa16cce74fb
6
+ metadata.gz: 14585282cf173b2f0a7e6fefe2beedfef2c45dedfb927d0241b1dcb24dc7f8d6db9d72fd9d4dbc23dd9cb96e78fe565f741fd49086231da6a575d06e08f3bb9f
7
+ data.tar.gz: 0d5dd1636473a8cf8bdd0381ebdf7823322e58eac0b2cca21640ac0f432965fa9d2d56e40b828d34135830639b7529b2b00af323dbdb021d103b24ce4070bed0
data/README.md CHANGED
@@ -98,6 +98,52 @@ raw_graph = {
98
98
  Dither.all_edges(raw_graph)
99
99
  ```
100
100
 
101
+ Random walk on a graph. Each edge has equal weight.
102
+ ```ruby
103
+ raw_graph = {
104
+ :origin => 0,
105
+ :edges => [
106
+ {
107
+ :name => :a,
108
+ :src_vertex => 0,
109
+ :dst_vertex => 1,
110
+ },
111
+ {
112
+ :name => :b,
113
+ :src_vertex => 0,
114
+ :dst_vertex => 2,
115
+ },
116
+ {
117
+ :name => :c,
118
+ :src_vertex => 1,
119
+ :dst_vertex => 2,
120
+ },
121
+ {
122
+ :name => :d,
123
+ :src_vertex => 1,
124
+ :dst_vertex => 3,
125
+ },
126
+ {
127
+ :name => :e,
128
+ :src_vertex => 2,
129
+ :dst_vertex => 3,
130
+ },
131
+ {
132
+ :name => :f,
133
+ :src_vertex => 3,
134
+ :dst_vertex => 0,
135
+ }
136
+ ]
137
+ }
138
+
139
+ graph = Dither::Graph.create(raw_graph)
140
+
141
+ # infinite sequence of random walks
142
+ graph.each do |path|
143
+ puts path.map(&:name).to_s
144
+ end
145
+ ```
146
+
101
147
 
102
148
  # Note on Patches/Pull Requests
103
149
 
@@ -0,0 +1,102 @@
1
+
2
+ module Dither
3
+ class Graph
4
+ include Enumerable
5
+
6
+ attr_accessor :rand, :max_depth, :origin_name
7
+ attr_reader :vertices, :edges, :stop_conditions, :skip_conditions
8
+ Edge = Struct.new(:name, :src_vertex, :dst_vertex, :count)
9
+ Vertex = Struct.new(:name, :edges, :count)
10
+
11
+ def initialize
12
+ @vertices = {}
13
+ @edges = []
14
+ @stop_conditions = []
15
+ @skip_conditions = []
16
+ @rand = Random.new
17
+ @max_depth = 10
18
+ @origin_name = :origin
19
+ end
20
+
21
+ def self.create(hash)
22
+ edges = hash[:edges]
23
+ graph = Graph.new
24
+ graph.origin_name = hash[:origin] if hash.has_key?(:origin)
25
+
26
+ edges.each do |edge|
27
+ graph.add_edge(edge[:name], edge[:src_vertex], edge[:dst_vertex])
28
+ end
29
+ graph
30
+ end
31
+
32
+ def add_edge(name, src_vertex_name, dst_vertex_name)
33
+ # check & create vertexes if they do not exist
34
+ vertices[src_vertex_name] ||= Vertex.new(src_vertex_name, [], 0)
35
+ vertices[dst_vertex_name] ||= Vertex.new(dst_vertex_name, [], 0)
36
+
37
+ # add edge to src_vertex
38
+ src_vertex = vertices[src_vertex_name]
39
+ dst_vertex = vertices[dst_vertex_name]
40
+ edge = Edge.new(name, src_vertex, dst_vertex, 0)
41
+ src_vertex.edges << edge
42
+ edges << edge
43
+
44
+ self
45
+ end
46
+
47
+ def add_skip_condition(cond)
48
+ raise Dither::Error, "#{cond} does not respond to skip?" unless cond.respond_to? :skip?
49
+ skip_conditions << cond
50
+ end
51
+
52
+ def add_stop_condition(cond)
53
+ raise Dither::Error, "#{cond} does not respond to stop?" unless cond.respond_to? :stop?
54
+ stop_conditions << cond
55
+ end
56
+
57
+ def origin
58
+ vertices[origin_name]
59
+ end
60
+
61
+ def random_walk
62
+ current_edge = origin.edges.sample(:random => rand)
63
+ current_max_depth = max_depth - 1
64
+ loop do
65
+ current_edge.src_vertex.count += 1
66
+ current_edge.count += 1
67
+ yield current_edge
68
+ current_edge = current_edge.dst_vertex.edges.sample(:random => rand)
69
+ current_max_depth -= 1
70
+ break if current_max_depth < 0 || current_edge.src_vertex.name == origin_name
71
+ end
72
+ end
73
+
74
+ def each
75
+ loop do
76
+ break if stop?
77
+ path = []
78
+ random_walk { |a| path << a }
79
+ next if skip?
80
+ yield path
81
+ end
82
+ end
83
+
84
+ def stop?
85
+ stop_conditions.any? { |cond| cond.stop?(self) }
86
+ end
87
+
88
+ def skip?
89
+ skip_conditions.any? { |cond| cond.skip?(self) }
90
+ end
91
+
92
+ def vertices_covered
93
+ b = vertices.count { |a| a.count > 0 }
94
+ b/vertices.length.to_f
95
+ end
96
+
97
+ def edges_covered
98
+ b = edges.count { |a| a.count > 0 }
99
+ b/edges.length.to_f
100
+ end
101
+ end
102
+ end
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Dither
3
- VERSION = '0.1.3'
3
+ VERSION = '0.1.4'
4
4
  end
data/lib/dither.rb CHANGED
@@ -43,6 +43,7 @@ require 'dither/mipog'
43
43
  require 'dither/chinese_postman_problem'
44
44
  require 'dither/aetg'
45
45
  require 'dither/aetg_pairwise'
46
+ require 'dither/graph'
46
47
 
47
48
  if RUBY_PLATFORM =~ /java/
48
49
  require 'java'
@@ -0,0 +1,124 @@
1
+
2
+ require File.expand_path('../../spec_helper.rb', __FILE__)
3
+
4
+ describe Dither::Graph do
5
+ let(:raw_graph) do
6
+ {
7
+ :edges => [
8
+ {
9
+ :name => :a,
10
+ :src_vertex => :origin,
11
+ :dst_vertex => 1,
12
+ },
13
+ {
14
+ :name => :b,
15
+ :src_vertex => :origin,
16
+ :dst_vertex => 2,
17
+ },
18
+ {
19
+ :name => :c,
20
+ :src_vertex => 1,
21
+ :dst_vertex => 2,
22
+ },
23
+ {
24
+ :name => :d,
25
+ :src_vertex => 1,
26
+ :dst_vertex => 3,
27
+ },
28
+ {
29
+ :name => :e,
30
+ :src_vertex => 2,
31
+ :dst_vertex => 3,
32
+ },
33
+ {
34
+ :name => :f,
35
+ :src_vertex => 3,
36
+ :dst_vertex => :origin,
37
+ }
38
+ ]
39
+ }
40
+ end
41
+
42
+
43
+ let(:raw_graph_infinite_cycle) do
44
+ {
45
+ :origin => 0,
46
+ :edges => [
47
+ {
48
+ :name => :a,
49
+ :src_vertex => 0,
50
+ :dst_vertex => 1,
51
+ },
52
+ {
53
+ :name => :b,
54
+ :src_vertex => 1,
55
+ :dst_vertex => 2,
56
+ },
57
+ {
58
+ :name => :c,
59
+ :src_vertex => 2,
60
+ :dst_vertex => 1,
61
+ },
62
+ ]
63
+ }
64
+ end
65
+
66
+ it 'can run random walk' do
67
+ graph = Dither::Graph.create(raw_graph)
68
+ graph.rand = Random.new 0
69
+ graph.each do |path|
70
+ first = path.map(&:name)
71
+ expect(first).to eql([:a, :d, :f])
72
+ break
73
+ end
74
+ end
75
+
76
+ it 'can skip at skip condition' do
77
+ graph = Dither::Graph.create(raw_graph_infinite_cycle)
78
+ stop_cond = 'stop_cond'
79
+ def stop_cond.stop?(graph)
80
+ @count ||= 0
81
+ @count += 1
82
+ @count > 2
83
+ end
84
+ skip_cond = double("skip_cond", :skip? => true)
85
+ graph.add_skip_condition(skip_cond)
86
+ graph.add_stop_condition(stop_cond)
87
+ count = 0
88
+ graph.each do |a|
89
+ count += 1
90
+ end
91
+
92
+ expect(count).to eql(0)
93
+ end
94
+
95
+ it 'can stop at stop condition' do
96
+ graph = Dither::Graph.create(raw_graph_infinite_cycle)
97
+ cond = double("stop_cond", :stop? => true)
98
+ graph.add_stop_condition(cond)
99
+ count = 0
100
+ graph.each { |a| count += 1 }
101
+
102
+ expect(count).to eql(0)
103
+ end
104
+
105
+ it 'infinite cycle terminates at max_depth' do
106
+ graph = Dither::Graph.create(raw_graph_infinite_cycle)
107
+ graph.random_walk { |a| }
108
+
109
+ edge_count = graph.edges.map(&:count).reduce(&:+)
110
+ expect(edge_count).to eql(graph.max_depth)
111
+ end
112
+
113
+ it 'raise error when invalid stop condition' do
114
+ graph = Dither::Graph.new
115
+
116
+ expect { graph.add_stop_condition("hi") }.to raise_error
117
+ end
118
+
119
+ it 'raise error when invalid skip condition' do
120
+ graph = Dither::Graph.new
121
+
122
+ expect { graph.add_skip_condition("hi") }.to raise_error
123
+ end
124
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dither
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Gowan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-16 00:00:00.000000000 Z
11
+ date: 2015-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -72,6 +72,7 @@ files:
72
72
  - lib/dither/aetg.rb
73
73
  - lib/dither/aetg_pairwise.rb
74
74
  - lib/dither/chinese_postman_problem.rb
75
+ - lib/dither/graph.rb
75
76
  - lib/dither/ipog.rb
76
77
  - lib/dither/ipog_helper.rb
77
78
  - lib/dither/java_ext/dither.rb
@@ -82,6 +83,7 @@ files:
82
83
  - lib/dither/version.rb
83
84
  - spec/dither/chinese_postman_problem_spec.rb
84
85
  - spec/dither/dither_spec.rb
86
+ - spec/dither/graph_spec.rb
85
87
  - spec/spec_helper.rb
86
88
  homepage: https://github.com/jesg/dither
87
89
  licenses:
@@ -110,4 +112,5 @@ summary: Collection of test generation strategies
110
112
  test_files:
111
113
  - spec/dither/chinese_postman_problem_spec.rb
112
114
  - spec/dither/dither_spec.rb
115
+ - spec/dither/graph_spec.rb
113
116
  - spec/spec_helper.rb