dither 0.1.3-java → 0.1.4-java
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/README.md +46 -0
- data/lib/dither.rb +1 -0
- data/lib/dither/graph.rb +102 -0
- data/lib/dither/version.rb +1 -1
- data/spec/dither/graph_spec.rb +124 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3af620c3811276969244eb515443a6f89bce71c8
|
4
|
+
data.tar.gz: f40ebd686325b3d402f3e752cb9db9fcaca4074f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36ef90323fdb4264d5f183fd203adc0a7ed7d12e7cf5bc561b38cef6878ec4e6af2b75f342011f2925df0b1abc34d7ac602e53da4a1d79550a8426efe73db1da
|
7
|
+
data.tar.gz: 26e28e273e9d7cf80773a990c94b7866059fead5a22b4b949a59a4839544b1be5860973a792b2ac40422b7c31d6db53e06223a4dd500efe840bd6a17b2c9afd9
|
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
|
|
data/lib/dither.rb
CHANGED
data/lib/dither/graph.rb
ADDED
@@ -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
|
data/lib/dither/version.rb
CHANGED
@@ -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.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Jason Gowan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-10-
|
11
|
+
date: 2015-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -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
|
- lib/dither-0.1.2.jar
|
87
89
|
- lib/choco-solver-3.3.1-with-dependencies.jar
|
@@ -112,4 +114,5 @@ summary: Collection of test generation strategies
|
|
112
114
|
test_files:
|
113
115
|
- spec/dither/chinese_postman_problem_spec.rb
|
114
116
|
- spec/dither/dither_spec.rb
|
117
|
+
- spec/dither/graph_spec.rb
|
115
118
|
- spec/spec_helper.rb
|