dither 0.0.10 → 0.0.11

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: e6aeec317ee301c987fa9f850ae1d131ae2e5fc6
4
- data.tar.gz: 5258de5745ae92ca80c7040911e7cf0d9a8156ff
3
+ metadata.gz: d7fbd5b281ba90ffd541192320abf17d31c8e345
4
+ data.tar.gz: 08e49deed38f7d4e239f080c28341c023317d195
5
5
  SHA512:
6
- metadata.gz: 771652b00d5078fcc02585ac67caa0c891081f6dd4ad75747cd08491242f8fd019030a07b4a2cfbc5154723c6dba8b54f8ab614bd043f6268b35d358a5b0068f
7
- data.tar.gz: 08ab024560ddd9a7cde11f8ca7ae6ae77e69267e4478b7c6dad079ede63b626ed9b7a52d3ef0a0ab5053dc05ba6aaaa9b871c27542f804572a4482abca5ff9eb
6
+ metadata.gz: a4f14b7801a1914321ea7dd02dd803dab97cc7c9ad1a0fc44658093ded0deec3defba34eae97fb4b0984f9c99eef4a94ad828e88e6f4d010ce67c9d31a139726
7
+ data.tar.gz: fd023b9f6fd8d00ce0d776546ad807515f211283a5f8b62bf0cdc1b088ae2764d7f69773d2a6b96a5711164db3a92889bcd1eb89f9c7dc7c270e0ac88c8c4112
data/README.md CHANGED
@@ -3,6 +3,7 @@ Collection of combinatorial test generation strategies.
3
3
 
4
4
  # Usage
5
5
 
6
+ ## Pairwise Testing
6
7
  ```ruby
7
8
  require 'dither'
8
9
 
@@ -31,6 +32,49 @@ Dither.ipog([[true, false],
31
32
 
32
33
  ```
33
34
 
35
+ ## Graph Models (Experimental)
36
+ ```ruby
37
+ raw_graph = {
38
+ :origin => 0,
39
+ :edges => [
40
+ {
41
+ :name => :a,
42
+ :src_vertex => 0,
43
+ :dst_vertex => 1,
44
+ },
45
+ {
46
+ :name => :b,
47
+ :src_vertex => 0,
48
+ :dst_vertex => 2,
49
+ },
50
+ {
51
+ :name => :c,
52
+ :src_vertex => 1,
53
+ :dst_vertex => 2,
54
+ },
55
+ {
56
+ :name => :d,
57
+ :src_vertex => 1,
58
+ :dst_vertex => 3,
59
+ },
60
+ {
61
+ :name => :e,
62
+ :src_vertex => 2,
63
+ :dst_vertex => 3,
64
+ },
65
+ {
66
+ :name => :f,
67
+ :src_vertex => 3,
68
+ :dst_vertex => 0,
69
+ }
70
+ ]
71
+ }
72
+
73
+ # shortest path to cover all edges at least once
74
+ Dither.all_edges(raw_graph)
75
+ ```
76
+
77
+
34
78
  # Note on Patches/Pull Requests
35
79
 
36
80
  * Fork the project.
@@ -0,0 +1,220 @@
1
+
2
+ # implement thimbleby's solution to the chinese @postman problem
3
+ # http://www.cs.swansea.ac.uk/~csharold/cv/files/cpp.pdf
4
+
5
+ module Dither
6
+ module Cpp
7
+ class Graph
8
+
9
+ attr_accessor :n, :neg, :pos, :degree, :path, :edges, :cheapest_edge, :f, :defined, :label, :c, :initialized, :origin
10
+
11
+ Edge = Struct.new(:name, :src_vertex, :dst_vertex)
12
+
13
+ def initialize(n)
14
+
15
+ @n = n
16
+ @degree = Array.new(n).fill(0)
17
+ @defined = Array.new(n).fill { |_| Array.new(n).fill(false) }
18
+ @label = Array.new(n).fill { |_| Array.new(n).fill { |_| [] } }
19
+ @c = Array.new(n).fill { |_| Array.new(n).fill(0.0) }
20
+ @f = Array.new(n).fill { |_| Array.new(n).fill(0) }
21
+ @edges = Array.new(n).fill { |_| Array.new(n).fill(0) }
22
+ @cheapest_edge = Array.new(n).fill { |_| Array.new(n).fill(0) }
23
+ @path = Array.new(n).fill { |_| Array.new(n).fill(0) }
24
+ @initialized = true
25
+ end
26
+
27
+
28
+ def cpp
29
+ initialized?
30
+ least_cost_paths
31
+ check_valid
32
+ find_feasible
33
+ while improvments do
34
+ end
35
+ print(origin)
36
+ end
37
+
38
+ def self.create(raw_graph)
39
+ vertices = [].to_set
40
+ raw_graph[:edges].each do |edge|
41
+ vertices << edge[:src_vertex]
42
+ vertices << edge[:dst_vertex]
43
+ end
44
+
45
+ graph = Graph.new(vertices.length)
46
+
47
+ raw_graph[:edges].each do |edge|
48
+ graph.add_edge(edge[:name], edge[:src_vertex], edge[:dst_vertex], 1)
49
+ end
50
+ graph.origin = raw_graph[:origin]
51
+ graph
52
+ end
53
+
54
+ def add_edge(lab, u, v, cost)
55
+ @label[u][v] = [] unless defined[u][v]
56
+ @label[u][v] << lab
57
+ if !defined[u][v] || c[u][v] > cost
58
+ @c[u][v] = cost
59
+ @cheapest_edge[u][v] = edges[u][v]
60
+ @defined[u][v] = true
61
+ @path[u][v] = v
62
+ end
63
+ @edges[u][v] += 1
64
+ @degree[u] += 1
65
+ @degree[v] -= 1
66
+ self
67
+ end
68
+
69
+ def check_valid
70
+ (0...n).each do |i|
71
+ raise Dither::Error, 'negative cycle' if c[i][i] < 0
72
+ (0...n).each do |j|
73
+ raise Dither::Error, 'not strongly connected' unless defined[i][j]
74
+ end
75
+ end
76
+ end
77
+
78
+ def least_cost_paths
79
+ (0...n).each do |k|
80
+ (0...n).each do |i|
81
+ if defined[i][k]
82
+ (0...n).each do |j|
83
+ if defined[k][j] && (!defined[i][j] || c[i][j] > c[i][k]+c[k][j])
84
+ @defined[i][j] = true
85
+ @path[i][j] = path[i][k]
86
+ @c[i][j] = c[i][k] + c[k][j]
87
+ # negative cycle
88
+ return if i == j && c[i][j] < 0
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ def find_feasible
97
+ nn, np = 0, 0
98
+ (0...n).each do |i|
99
+ if degree[i] < 0
100
+ nn += 1
101
+ elsif degree[i] > 0
102
+ np += 1
103
+ end
104
+ end
105
+
106
+ @neg = Array.new(nn)
107
+ @pos = Array.new(np)
108
+ nn, np = 0, 0
109
+ (0...n).each do |i|
110
+ if degree[i] < 0
111
+ @neg[nn] = i
112
+ nn += 1
113
+ elsif degree[i] > 0
114
+ @pos[np] = i
115
+ np += 1
116
+ end
117
+ end
118
+
119
+ (0...nn).each do |u|
120
+ i = neg[u]
121
+ (0...np).each do |v|
122
+ j = pos[v]
123
+ @f[i][j] = -degree[i] < degree[j] ? -degree[i] : degree[j]
124
+ @degree[i] += f[i][j]
125
+ @degree[j] -= f[i][j]
126
+ end
127
+ end
128
+ end
129
+
130
+ def improvments
131
+ r = Graph.new(n)
132
+ (0...neg.length).each do |u|
133
+ i = neg[u]
134
+ (0...pos.length).each do |v|
135
+ j = pos[v]
136
+ if edges[i][j] > 0
137
+ r.add_edge(nil, i, j, c[i][j])
138
+ end
139
+ if f[i][j] != 0
140
+ r.add_edge(nil, j, i, -c[i][j])
141
+ end
142
+ end
143
+ end
144
+
145
+ r.least_cost_paths
146
+ (0...n).each do |i|
147
+ if r.c[i][i] < 0
148
+ k = 0
149
+ kunset = true
150
+ u = i
151
+ begin
152
+ v = r.path[u][i]
153
+ if r.c[u][v] < 0 && (kunset || k > f[v][u])
154
+ k = f[v][u]
155
+ kunset = false
156
+ end
157
+ u = v
158
+ end while u != i
159
+ u = i
160
+ begin
161
+ v = r.path[u][i]
162
+ if r.c[u][v] < 0
163
+ @f[v][u] -= k
164
+ else
165
+ @f[u][v] += k
166
+ end
167
+ u = v
168
+ end while u != i
169
+ return true
170
+ end
171
+ end
172
+ false
173
+ end
174
+
175
+ def print(start)
176
+ result = []
177
+ v = start
178
+ loop do
179
+ skip = false
180
+ u = v
181
+ (0...n).each do |i|
182
+ if f[u][i] > 0
183
+ v = i
184
+ @f[u][v] -= 1
185
+ while u != v
186
+ p = path[u][v]
187
+ result << Edge.new(label[u][p][cheapest_edge[u][p]], u, p)
188
+ u = p
189
+ end
190
+ skip = true
191
+ end
192
+ end
193
+
194
+ next if skip
195
+
196
+ v = -1
197
+ (0...n).each do |i|
198
+ if edges[u][i] > 0
199
+ v = i if v == -1 || i != path[u][start]
200
+ end
201
+ end
202
+ return result if v == -1
203
+ result << Edge.new(label[u][v][edges[u][v] - 1], u, v)
204
+ @edges[u][v] -= 1
205
+ end
206
+ result
207
+ end
208
+
209
+ def initialized?
210
+ raise Dither::Error, 'graph not initialized' unless initialized
211
+ raise Dither::Error, 'origin not set' unless origin
212
+ @initialized = false
213
+ end
214
+ end # Graph
215
+ end # Cpp
216
+
217
+ def self.all_edges(raw_graph)
218
+ Dither::Cpp::Graph.create(raw_graph).cpp
219
+ end
220
+ end # Dither
@@ -1,4 +1,4 @@
1
1
 
2
2
  module Dither
3
- VERSION = '0.0.10'
3
+ VERSION = '0.0.11'
4
4
  end
data/lib/dither.rb CHANGED
@@ -33,6 +33,7 @@ require 'dither/test_case'
33
33
  require 'dither/ipog_helper'
34
34
  require 'dither/ipog'
35
35
  require 'dither/mipog'
36
+ require 'dither/chinese_postman_problem'
36
37
 
37
38
  if RUBY_PLATFORM =~ /java/
38
39
  require 'java'
@@ -0,0 +1,77 @@
1
+ require File.expand_path('../../spec_helper.rb', __FILE__)
2
+
3
+ describe Dither::Cpp::Graph do
4
+ let(:raw_graph) do
5
+ {
6
+ :origin => 0,
7
+ :edges => [
8
+ {
9
+ :name => :a,
10
+ :src_vertex => 0,
11
+ :dst_vertex => 1,
12
+ },
13
+ {
14
+ :name => :b,
15
+ :src_vertex => 0,
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 => 0,
37
+ }
38
+ ]
39
+ }
40
+ end
41
+
42
+ it 'can compute chinese postman problem' do
43
+ expected = [
44
+ [:b, 0, 2],
45
+ [:e, 2, 3],
46
+ [:f, 3, 0],
47
+ [:a, 0, 1],
48
+ [:c, 1, 2],
49
+ [:e, 2, 3],
50
+ [:f, 3, 0],
51
+ [:a, 0, 1],
52
+ [:d, 1, 3],
53
+ [:f, 3, 0]].map { |a| Dither::Cpp::Graph::Edge.new(*a) }
54
+ expect(Dither.all_edges(raw_graph)).to eq(expected)
55
+ end
56
+
57
+ it 'verify origin is set' do
58
+ raw_graph.delete(:origin)
59
+ expect { Dither.all_edges(raw_graph) }.to raise_error
60
+ end
61
+
62
+ it 'raise error when calling cpp twice' do
63
+ graph = Dither::Cpp::Graph.create(raw_graph)
64
+ graph.cpp
65
+ expect { graph.cpp }.to raise_error
66
+ end
67
+
68
+ it 'raise error when graph is not strongly connected' do
69
+ raw_graph[:edges] << {
70
+ :name => :w,
71
+ :src_vertex => 23,
72
+ :dst_vertex => 78
73
+ }
74
+
75
+ expect { Dither.all_edges(raw_graph) }.to raise_error
76
+ end
77
+ 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.0.10
4
+ version: 0.0.11
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-06-11 00:00:00.000000000 Z
11
+ date: 2015-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -69,6 +69,7 @@ files:
69
69
  - Rakefile
70
70
  - dither.gemspec
71
71
  - lib/dither.rb
72
+ - lib/dither/chinese_postman_problem.rb
72
73
  - lib/dither/ipog.rb
73
74
  - lib/dither/ipog_helper.rb
74
75
  - lib/dither/java_ext/dither.rb
@@ -77,6 +78,7 @@ files:
77
78
  - lib/dither/test_case.rb
78
79
  - lib/dither/unbound_param.rb
79
80
  - lib/dither/version.rb
81
+ - spec/dither/chinese_postman_problem_spec.rb
80
82
  - spec/dither/dither_spec.rb
81
83
  - spec/spec_helper.rb
82
84
  homepage: https://github.com/jesg/dither
@@ -104,5 +106,6 @@ signing_key:
104
106
  specification_version: 4
105
107
  summary: Collection of test generation strategies
106
108
  test_files:
109
+ - spec/dither/chinese_postman_problem_spec.rb
107
110
  - spec/dither/dither_spec.rb
108
111
  - spec/spec_helper.rb