diff --git a/lib/predicate.rb b/lib/predicate.rb index 8a7b54a..ad03435 100644 --- a/lib/predicate.rb +++ b/lib/predicate.rb @@ -88,6 +88,7 @@ def constants def &(other) return self if other.tautology? or other==self return other if tautology? + Predicate.new(expr & other.expr) end diff --git a/lib/predicate/nodes/and.rb b/lib/predicate/nodes/and.rb index dfc26a9..81c8337 100644 --- a/lib/predicate/nodes/and.rb +++ b/lib/predicate/nodes/and.rb @@ -7,6 +7,8 @@ def operator_symbol end def &(other) + return contradiction if in_contradiction?(self, other) + case other when Tautology then self when Contradiction then other diff --git a/lib/predicate/nodes/eq.rb b/lib/predicate/nodes/eq.rb index cf9a13f..659f0bd 100644 --- a/lib/predicate/nodes/eq.rb +++ b/lib/predicate/nodes/eq.rb @@ -7,12 +7,9 @@ def operator_symbol end def &(other) - return super unless free_variables == other.free_variables case other - when Eq - return self if constants == other.constants - return contradiction when In + return super unless free_variables == other.free_variables return super unless var_against_literal_value? && other.var_against_literal_value? mine, hers = self.right.value, other.right.value return self if hers.include?(mine) diff --git a/lib/predicate/nodes/expr.rb b/lib/predicate/nodes/expr.rb index 1d24d24..83eb46d 100644 --- a/lib/predicate/nodes/expr.rb +++ b/lib/predicate/nodes/expr.rb @@ -31,6 +31,12 @@ def identifier? sexpr_type == :identifier end + def in_contradiction?(me, other) + mine = me.constants + yours = other.constants + (mine.keys & yours.keys).any?{|k| mine[k] != yours[k] } + end + def ! sexpr([:not, self]) end @@ -41,6 +47,8 @@ def &(other) return other if other.contradiction? return self if other.tautology? return other & self if other.dyadic_priority > self.dyadic_priority + return contradiction if in_contradiction?(self, other) + sexpr([:and, self, other]) end diff --git a/spec/nodes/and/test_and.rb b/spec/nodes/and/test_and.rb index 51664a1..9ae41ce 100644 --- a/spec/nodes/and/test_and.rb +++ b/spec/nodes/and/test_and.rb @@ -30,5 +30,15 @@ class Predicate end end + context 'with an eq yielding a contradiction' do + let(:right) { + Factory.eq(:x, 5) + } + + it 'returns a contradiction' do + expect(subject).to be_a(Contradiction) + end + end + end -end \ No newline at end of file +end diff --git a/spec/nodes/eq/test_and.rb b/spec/nodes/eq/test_and.rb index 9820b44..f0f4994 100644 --- a/spec/nodes/eq/test_and.rb +++ b/spec/nodes/eq/test_and.rb @@ -14,6 +14,12 @@ class Predicate it{ should be_a(Contradiction) } end + context 'with an and leading to a contradiction' do + let(:right){ Factory.eq(:y, 4) & Factory.eq(:x, 3) } + + it{ should be_a(Contradiction) } + end + context 'with an IN on same variable and literal' do let(:right){ Factory.in(:x, [2,4]) }