dither 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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