predicate 1.2.0 → 1.3.0

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: 710a45c31d1350beeded48ea522d3e868925e600
4
- data.tar.gz: 8e9acddd67b337218c749aa6744940b26ca8568e
3
+ metadata.gz: 61fec1238a5307709753d2214ed0bf4b07af3790
4
+ data.tar.gz: 8ca0232c14c907971c4bc39b10ddbe3629f2f529
5
5
  SHA512:
6
- metadata.gz: e3d92a4dfa7227cbac8dc6b9dc9e4856861983103e2840ad041721269a66ecce74980750293178b3c3cdc9f34c06aa2d5a396880634f47e84a0b03aaac3a202d
7
- data.tar.gz: ff1eee7dcc029585926d897eb5f3da17b68dd6f392f6e2c73bb50208ae00d22aedf0422feccea4cf747d869555b37dfa720407aa73746dd74935cfd52384f8de
6
+ metadata.gz: a66b05a35406d025a78fa0bc44c1508c3c74906eff4ef2270b8fcc4177aeaf88b9f54ff11d259eaa17aa30bb8b728d00ca08a038efcb98b4e735fecde2ad844e
7
+ data.tar.gz: 88029e029b342093b92a7925ef0ca7edd618e440fc33d99eaf2f128b4cbf0e344639e62aa2768621507582e24f007faff03727bde874b6b0c729e0519d1638c8
@@ -6,6 +6,15 @@ class Predicate
6
6
  :'&&'
7
7
  end
8
8
 
9
+ def &(other)
10
+ case other
11
+ when Tautology then self
12
+ when Contradiction then other
13
+ when And then sexpr(dup + other[1..-1])
14
+ else dup << other
15
+ end
16
+ end
17
+
9
18
  def and_split(attr_list)
10
19
  # Say we are X = X1 & X2 & X3
11
20
  # We will split each term: X = (X1 & Y1) & (X2 & Y2) & (X3 & Y3)
@@ -34,5 +43,15 @@ class Predicate
34
43
  end
35
44
  end
36
45
 
46
+ def constants
47
+ sexpr_body.each_with_object({}) do |op, cs|
48
+ cs.merge!(op.constants){|k,v1,v2| v1 }
49
+ end
50
+ end
51
+
52
+ def evaluate(tuple)
53
+ sexpr_body.all?{|operand| operand.evaluate(tuple) }
54
+ end
55
+
37
56
  end
38
57
  end
@@ -18,6 +18,10 @@ class Predicate
18
18
  other
19
19
  end
20
20
 
21
+ def dyadic_priority
22
+ 1000
23
+ end
24
+
21
25
  def priority
22
26
  100
23
27
  end
@@ -30,5 +34,9 @@ class Predicate
30
34
  { nil => self }
31
35
  end
32
36
 
37
+ def evaluate(tuple)
38
+ false
39
+ end
40
+
33
41
  end
34
42
  end
@@ -6,10 +6,46 @@ class Predicate
6
6
  :==
7
7
  end
8
8
 
9
+ def &(other)
10
+ case other
11
+ when Eq
12
+ if free_variables == other.free_variables
13
+ return self if constants == other.constants
14
+ contradiction
15
+ else
16
+ super
17
+ end
18
+ when In
19
+ return self if free_variables == other.free_variables
20
+ super
21
+ else
22
+ super
23
+ end
24
+ end
25
+
9
26
  def constant_variables
10
27
  fv = free_variables
11
28
  fv.size == 1 ? fv : []
12
29
  end
13
30
 
31
+ def constants
32
+ left, right = sexpr(self.left), sexpr(self.right)
33
+ if left.identifier? && right.literal?
34
+ { left.name => right.value }
35
+ elsif right.identifier? && left.literal?
36
+ { right.name => left.value }
37
+ else
38
+ {}
39
+ end
40
+ end
41
+
42
+ def dyadic_priority
43
+ 900
44
+ end
45
+
46
+ def evaluate(tuple)
47
+ left.evaluate(tuple) == right.evaluate(tuple)
48
+ end
49
+
14
50
  end
15
51
  end
@@ -19,13 +19,26 @@ class Predicate
19
19
  false
20
20
  end
21
21
 
22
+ def literal?
23
+ sexpr_type == :literal
24
+ end
25
+
26
+ def identifier?
27
+ sexpr_type == :identifier
28
+ end
29
+
22
30
  def !
23
31
  sexpr([:not, self])
24
32
  end
25
33
 
34
+ def dyadic_priority
35
+ 0
36
+ end
37
+
26
38
  def &(other)
27
39
  return other if other.contradiction?
28
40
  return self if other.tautology?
41
+ return other & self if other.dyadic_priority > self.dyadic_priority
29
42
  sexpr([:and, self, other])
30
43
  end
31
44
 
@@ -64,6 +77,10 @@ class Predicate
64
77
  []
65
78
  end
66
79
 
80
+ def constants
81
+ {}
82
+ end
83
+
67
84
  def to_ruby_code(scope = 't')
68
85
  code = ToRubyCode.call(self, scope: scope)
69
86
  "->(t){ #{code} }"
@@ -6,5 +6,9 @@ class Predicate
6
6
  :>
7
7
  end
8
8
 
9
+ def evaluate(tuple)
10
+ left.evaluate(tuple) > right.evaluate(tuple)
11
+ end
12
+
9
13
  end
10
14
  end
@@ -6,5 +6,9 @@ class Predicate
6
6
  :>=
7
7
  end
8
8
 
9
+ def evaluate(tuple)
10
+ left.evaluate(tuple) >= right.evaluate(tuple)
11
+ end
12
+
9
13
  end
10
14
  end
@@ -14,5 +14,9 @@ class Predicate
14
14
  @free_variables ||= [ name ]
15
15
  end
16
16
 
17
+ def evaluate(tuple)
18
+ tuple[name]
19
+ end
20
+
17
21
  end
18
22
  end
@@ -14,6 +14,27 @@ class Predicate
14
14
  self[2]
15
15
  end
16
16
 
17
+ def &(other)
18
+ case other
19
+ when In
20
+ fv = free_variables
21
+ if fv.size == 1 && fv == other.free_variables
22
+ intersection = values & other.values
23
+ if intersection.empty?
24
+ Factory.contradiction
25
+ elsif intersection.size == 1
26
+ Factory.eq(fv.first, [:literal, intersection.first])
27
+ else
28
+ Factory.in(fv.first, intersection)
29
+ end
30
+ else
31
+ super
32
+ end
33
+ else
34
+ super
35
+ end
36
+ end
37
+
17
38
  def free_variables
18
39
  @free_variables ||= identifier.free_variables
19
40
  end
@@ -22,5 +43,17 @@ class Predicate
22
43
  values.size == 1 ? free_variables : []
23
44
  end
24
45
 
46
+ def constants
47
+ values.size == 1 ? { identifier.name => values.first } : {}
48
+ end
49
+
50
+ def dyadic_priority
51
+ 800
52
+ end
53
+
54
+ def evaluate(tuple)
55
+ values.include?(left.evaluate(tuple))
56
+ end
57
+
25
58
  end
26
59
  end
@@ -22,5 +22,10 @@ class Predicate
22
22
  values.size == 1 ? free_variables : []
23
23
  end
24
24
 
25
+ def evaluate(tuple)
26
+ t_x = left.evaluate(tuple)
27
+ t_x && !(tx & right.evaluate(tuple)).empty?
28
+ end
29
+
25
30
  end
26
31
  end
@@ -14,5 +14,9 @@ class Predicate
14
14
  last
15
15
  end
16
16
 
17
+ def evaluate(tuple)
18
+ value
19
+ end
20
+
17
21
  end
18
22
  end
@@ -6,5 +6,9 @@ class Predicate
6
6
  :<
7
7
  end
8
8
 
9
+ def evaluate(tuple)
10
+ left.evaluate(tuple) < right.evaluate(tuple)
11
+ end
12
+
9
13
  end
10
14
  end
@@ -6,5 +6,9 @@ class Predicate
6
6
  :<=
7
7
  end
8
8
 
9
+ def evaluate(tuple)
10
+ left.evaluate(tuple) <= right.evaluate(tuple)
11
+ end
12
+
9
13
  end
10
14
  end
@@ -36,6 +36,10 @@ class Predicate
36
36
  proc
37
37
  end
38
38
 
39
+ def evaluate(tuple)
40
+ proc.call(tuple)
41
+ end
42
+
39
43
  def free_variables
40
44
  raise NotSupportedError
41
45
  end
@@ -6,5 +6,9 @@ class Predicate
6
6
  :'!='
7
7
  end
8
8
 
9
+ def evaluate(tuple)
10
+ left.evaluate(tuple) != right.evaluate(tuple)
11
+ end
12
+
9
13
  end
10
14
  end
@@ -18,5 +18,9 @@ class Predicate
18
18
  @free_variables ||= last.free_variables
19
19
  end
20
20
 
21
+ def evaluate(tuple)
22
+ !last.evaluate(tuple)
23
+ end
24
+
21
25
  end
22
26
  end
@@ -6,5 +6,9 @@ class Predicate
6
6
  :'||'
7
7
  end
8
8
 
9
+ def evaluate(tuple)
10
+ sexpr_body.any?{|op| op.evaluate(tuple) }
11
+ end
12
+
9
13
  end
10
14
  end
@@ -18,5 +18,9 @@ class Predicate
18
18
  @free_variables ||= [ name ]
19
19
  end
20
20
 
21
+ def evaluate(tuple)
22
+ tuple[name]
23
+ end
24
+
21
25
  end
22
26
  end
@@ -18,6 +18,10 @@ class Predicate
18
18
  self
19
19
  end
20
20
 
21
+ def dyadic_priority
22
+ 1000
23
+ end
24
+
21
25
  def priority
22
26
  100
23
27
  end
@@ -30,5 +34,9 @@ class Predicate
30
34
  {}
31
35
  end
32
36
 
37
+ def evaluate(tuple)
38
+ true
39
+ end
40
+
33
41
  end
34
42
  end
@@ -50,7 +50,8 @@ class Predicate
50
50
  end
51
51
 
52
52
  def on_intersect(sexpr)
53
- "!(#{apply(sexpr.identifier)} & #{to_ruby_literal(sexpr.values)}).empty?"
53
+ t_x = apply(sexpr.identifier)
54
+ "!#{t_x}.nil? && !(#{t_x} & #{to_ruby_literal(sexpr.values)}).empty?"
54
55
  end
55
56
 
56
57
  def on_literal(sexpr)
@@ -1,7 +1,7 @@
1
1
  class Predicate
2
2
  module Version
3
3
  MAJOR = 1
4
- MINOR = 2
4
+ MINOR = 3
5
5
  TINY = 0
6
6
  end
7
7
  VERSION = "#{Version::MAJOR}.#{Version::MINOR}.#{Version::TINY}"
data/lib/predicate.rb CHANGED
@@ -60,6 +60,10 @@ class Predicate
60
60
  expr.constant_variables
61
61
  end
62
62
 
63
+ def constants
64
+ expr.constants
65
+ end
66
+
63
67
  def &(other)
64
68
  return self if other.tautology? or other==self
65
69
  return other if tautology?
@@ -85,7 +89,7 @@ class Predicate
85
89
  end
86
90
 
87
91
  def evaluate(tuple)
88
- to_proc.call(tuple)
92
+ expr.evaluate(tuple)
89
93
  end
90
94
 
91
95
  # Splits this predicate, say P, as too predicates P1 & P2
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+ class Predicate
3
+ describe And, "&" do
4
+
5
+ let(:left){
6
+ Factory.eq(:x, 2) & Factory.eq(:y, 3)
7
+ }
8
+
9
+ subject{ left & right }
10
+
11
+ context 'with another predicate' do
12
+ let(:right) {
13
+ Factory.eq(:z, 4)
14
+ }
15
+
16
+ it 'collects it' do
17
+ expect(subject).to be_a(And)
18
+ expect(subject.size).to eql(4)
19
+ end
20
+
21
+ it 'is as expected' do
22
+ expect(subject.to_ruby_code).to eql("->(t){ (t[:x] == 2) && (t[:y] == 3) && (t[:z] == 4) }")
23
+ end
24
+ end
25
+
26
+ context 'with another and' do
27
+ let(:right) {
28
+ Factory.eq(:w, 5) & Factory.eq(:z, 4)
29
+ }
30
+
31
+ it 'collects it' do
32
+ expect(subject).to be_a(And)
33
+ expect(subject.size).to eql(5)
34
+ end
35
+
36
+ it 'is as expected' do
37
+ expect(subject.to_ruby_code).to eql("->(t){ (t[:x] == 2) && (t[:y] == 3) && (t[:w] == 5) && (t[:z] == 4) }")
38
+ end
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ class Predicate
3
+ describe Eq, "&" do
4
+
5
+ let(:left){
6
+ Factory.eq(:x, 2)
7
+ }
8
+
9
+ subject{ left & right }
10
+
11
+ context 'with an eq leading to a contradiction' do
12
+ let(:right){ Factory.eq(:x, 3) }
13
+
14
+ it{ should be_a(Contradiction) }
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ class Predicate
3
+ describe In, "&" do
4
+
5
+ let(:left){
6
+ Factory.in(:x, [2, 4, 8])
7
+ }
8
+
9
+ subject{ left & right }
10
+
11
+ context 'with an eq on same variable' do
12
+ let(:right){ Factory.eq(:x, 3) }
13
+
14
+ it{ should be(right) }
15
+ end
16
+
17
+ context 'with an in on same variable' do
18
+ let(:right){ Factory.in(:x, [2, 4, 5]) }
19
+
20
+ it{ should eql(Factory.in(:x, [2, 4])) }
21
+ end
22
+
23
+ context 'with an in on same variable, leading to a singleton' do
24
+ let(:right){ Factory.in(:x, [2, 5]) }
25
+
26
+ it{ should eql(Factory.eq(:x, 2)) }
27
+ end
28
+
29
+ context 'with an in on same variable, leading to a empty set' do
30
+ let(:right){ Factory.in(:x, [5]) }
31
+
32
+ it{ should eql(Factory.contradiction) }
33
+ end
34
+
35
+ end
36
+ end
@@ -30,5 +30,21 @@ class Predicate
30
30
  end
31
31
  end
32
32
 
33
+ context 'with tautology' do
34
+ let(:right){ Predicate.tautology }
35
+
36
+ it 'returns self' do
37
+ expect(subject).to eql(left)
38
+ end
39
+ end
40
+
41
+ context 'with contradiction' do
42
+ let(:right){ Predicate.contradiction }
43
+
44
+ it 'returns contradiction' do
45
+ expect(subject).to eql(right)
46
+ end
47
+ end
48
+
33
49
  end
34
50
  end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+ class Predicate
3
+ describe Predicate, "constants" do
4
+
5
+ let(:p){ Predicate }
6
+ subject{ pred.constants }
7
+
8
+ context "on tautology" do
9
+ let(:pred){ p.tautology }
10
+
11
+ it{ should eq({}) }
12
+ end
13
+
14
+ context "on contradiction" do
15
+ let(:pred){ p.contradiction }
16
+
17
+ it{ should eq({}) }
18
+ end
19
+
20
+ context "on eq(identifier,value)" do
21
+ let(:pred){ p.eq(:x, 2) }
22
+
23
+ it{ should eq({x: 2}) }
24
+ end
25
+
26
+ context "on eq(value,identifier)" do
27
+ let(:pred){ p.eq(2, :x) }
28
+
29
+ it{ should eq({x: 2}) }
30
+ end
31
+
32
+ context "on eq(identifier,identifier)" do
33
+ let(:pred){ p.eq(:x, :y) }
34
+
35
+ it{ should eq({}) }
36
+ end
37
+
38
+ context "on not" do
39
+ let(:pred){ !p.eq(:x, 2) }
40
+
41
+ it{ should eq({}) }
42
+ end
43
+
44
+ context "on neq" do
45
+ let(:pred){ p.neq(:x, 2) }
46
+
47
+ it{ should eq({}) }
48
+ end
49
+
50
+ context "on gt" do
51
+ let(:pred){ p.gt(:x, 2) }
52
+
53
+ it{ should eq({}) }
54
+ end
55
+
56
+ context "on in (singleton)" do
57
+ let(:pred){ p.in(:x, [2]) }
58
+
59
+ it{ should eq({x: 2}) }
60
+ end
61
+
62
+ context "on in (multiples)" do
63
+ let(:pred){ p.in(:x, [2, 3]) }
64
+
65
+ it{ should eq({}) }
66
+ end
67
+
68
+ context "on and (two eqs)" do
69
+ let(:pred){ p.eq(:x, 2) & p.eq(:y, 4) }
70
+
71
+ it{ should eq({x: 2, y: 4}) }
72
+ end
73
+
74
+ context "on and (one eq)" do
75
+ let(:pred){ p.eq(:x, 2) & p.in(:y, [4,8]) }
76
+
77
+ it{ should eq({x: 2}) }
78
+ end
79
+
80
+ context "on and (one eq, one in, same variable)" do
81
+ let(:pred){ p.in(:x, [4,8]) & p.eq(:x, 2) }
82
+
83
+ it{ should eq({x: 2}) }
84
+ end
85
+
86
+ context "on and (contradiction)" do
87
+ let(:pred){ p.eq(:x, 2) & p.eq(:x, 4) }
88
+
89
+ it{ should eq({}) }
90
+ end
91
+
92
+ context "on intersect" do
93
+ let(:pred){ p.intersect(:x, [4,8]) }
94
+
95
+ it{ should eq({}) }
96
+ end
97
+
98
+ context "on or (two eqs)" do
99
+ let(:pred){ p.eq(:x, 2) | p.eq(:y, 4) }
100
+
101
+ it{ should eq({}) }
102
+ end
103
+
104
+ context "on native" do
105
+ let(:pred){ p.native(->(t){}) }
106
+
107
+ it{ should eq({}) }
108
+ end
109
+
110
+ end
111
+ end
@@ -76,7 +76,7 @@ class Predicate
76
76
  context 'intersect' do
77
77
  subject{ Predicate.intersect(:x, [7,8]) }
78
78
 
79
- specify{ subject.to_ruby_code.should eq("->(t){ !(t[:x] & [7, 8]).empty? }") }
79
+ specify{ subject.to_ruby_code.should eq("->(t){ !t[:x].nil? && !(t[:x] & [7, 8]).empty? }") }
80
80
  end
81
81
 
82
82
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: predicate
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bernard Lambeau
@@ -148,12 +148,15 @@ files:
148
148
  - spec/factory/test_tautology.rb
149
149
  - spec/grammar/test_match.rb
150
150
  - spec/grammar/test_sexpr.rb
151
+ - spec/nodes/and/test_and.rb
151
152
  - spec/nodes/and/test_and_split.rb
152
153
  - spec/nodes/and/test_attr_split.rb
153
154
  - spec/nodes/dyadic_comp/test_and_split.rb
155
+ - spec/nodes/eq/test_and.rb
154
156
  - spec/nodes/identifier/test_and_split.rb
155
157
  - spec/nodes/identifier/test_free_variables.rb
156
158
  - spec/nodes/identifier/test_name.rb
159
+ - spec/nodes/in/test_and.rb
157
160
  - spec/nodes/nadic_bool/test_free_variables.rb
158
161
  - spec/nodes/or/test_and_split.rb
159
162
  - spec/nodes/qualified_identifier/test_and_split.rb
@@ -167,6 +170,7 @@ files:
167
170
  - spec/predicate/test_bool_or.rb
168
171
  - spec/predicate/test_coerce.rb
169
172
  - spec/predicate/test_constant_variables.rb
173
+ - spec/predicate/test_constants.rb
170
174
  - spec/predicate/test_contradiction.rb
171
175
  - spec/predicate/test_evaluate.rb
172
176
  - spec/predicate/test_factory_methods.rb