satre 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -1
- data/README.md +9 -7
- data/bin/exercise +64 -8
- data/lib/satre.rb +1 -3
- data/lib/satre/errors.rb +3 -0
- data/lib/satre/errors/argument_error.rb +2 -0
- data/lib/satre/errors/expression_error.rb +2 -0
- data/lib/satre/errors/parser_error.rb +2 -0
- data/lib/satre/formula.rb +3 -9
- data/lib/satre/formula/first_order_logic.rb +4 -0
- data/lib/satre/formula/first_order_logic/exists.rb +32 -0
- data/lib/satre/formula/first_order_logic/fol_formula.rb +35 -0
- data/lib/satre/formula/first_order_logic/forall.rb +32 -0
- data/lib/satre/formula/first_order_logic/relation.rb +38 -0
- data/lib/satre/formula/formula.rb +1 -13
- data/lib/satre/formula/propositional_logic.rb +9 -0
- data/lib/satre/formula/propositional_logic/and.rb +37 -0
- data/lib/satre/formula/propositional_logic/atom.rb +44 -0
- data/lib/satre/formula/propositional_logic/entails.rb +42 -0
- data/lib/satre/formula/{false.rb → propositional_logic/false.rb} +9 -2
- data/lib/satre/formula/propositional_logic/iff.rb +38 -0
- data/lib/satre/formula/propositional_logic/imp.rb +38 -0
- data/lib/satre/formula/propositional_logic/not.rb +34 -0
- data/lib/satre/formula/propositional_logic/or.rb +37 -0
- data/lib/satre/formula/{true.rb → propositional_logic/true.rb} +11 -2
- data/lib/satre/formula/term.rb +3 -0
- data/lib/satre/formula/term/function.rb +33 -0
- data/lib/satre/formula/term/term.rb +6 -0
- data/lib/satre/formula/term/variable.rb +24 -0
- data/lib/satre/parser.rb +4 -15
- data/lib/satre/parser/formula_parser.rb +74 -0
- data/lib/satre/parser/lexer.rb +55 -0
- data/lib/satre/parser/parser.rb +80 -0
- data/lib/satre/parser/term_parser.rb +85 -0
- data/lib/satre/version.rb +1 -1
- data/satre.gemspec +1 -0
- metadata +43 -20
- data/lib/satre/expression.rb +0 -6
- data/lib/satre/expression/add.rb +0 -26
- data/lib/satre/expression/const.rb +0 -23
- data/lib/satre/expression/expression.rb +0 -22
- data/lib/satre/expression/expression_parser.rb +0 -56
- data/lib/satre/expression/mul.rb +0 -30
- data/lib/satre/expression/var.rb +0 -14
- data/lib/satre/formula/and.rb +0 -26
- data/lib/satre/formula/atom.rb +0 -28
- data/lib/satre/formula/entails.rb +0 -29
- data/lib/satre/formula/iff.rb +0 -27
- data/lib/satre/formula/imp.rb +0 -25
- data/lib/satre/formula/not.rb +0 -22
- data/lib/satre/formula/or.rb +0 -25
- data/lib/satre/formula_parser.rb +0 -92
- data/lib/satre/lexer.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7bb9d290e43ab1740a0ae02f2fd3114cd97a5551
|
4
|
+
data.tar.gz: 9d0f9212637e9305900abb80d0b173eef4cbdaf8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9dfa67b219f98a724c0e1bb145ba540f185e711510f650be7d3f43b10262ff928b67813547bd73ba99e66b0cca35b93461f1f3f8db98eea5ff704c76431b57f9
|
7
|
+
data.tar.gz: d652a9ad06ede5fb9ca5bda81b6ab3a0d5aa1d77b489958ef64156d81b0111c8acb27bc270cdb84e0977167615849288b468e49610b8ba81397542f5910afba3
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
satre (
|
4
|
+
satre (1.0.0)
|
5
5
|
terminal-table
|
6
6
|
|
7
7
|
GEM
|
@@ -10,6 +10,8 @@ GEM
|
|
10
10
|
ast (2.1.0)
|
11
11
|
astrolabe (1.3.1)
|
12
12
|
parser (~> 2.2)
|
13
|
+
codeclimate-test-reporter (0.4.8)
|
14
|
+
simplecov (>= 0.7.1, < 1.0.0)
|
13
15
|
coderay (1.1.0)
|
14
16
|
diff-lcs (1.2.5)
|
15
17
|
docile (1.1.5)
|
@@ -95,6 +97,7 @@ PLATFORMS
|
|
95
97
|
|
96
98
|
DEPENDENCIES
|
97
99
|
bundler (~> 1.10)
|
100
|
+
codeclimate-test-reporter
|
98
101
|
guard-bundler
|
99
102
|
guard-minitest
|
100
103
|
guard-rubocop
|
data/README.md
CHANGED
@@ -36,30 +36,32 @@ The see the results of the exercise run `./bin/exercise` from the root directory
|
|
36
36
|
To embed proportional logic solving in your project one can use `String#to_formula`, on a well formed proportional logic string.
|
37
37
|
Possible operations are
|
38
38
|
|
39
|
-
* True value `"
|
40
|
-
* False value `"
|
39
|
+
* True value `"true"`
|
40
|
+
* False value `"false"`
|
41
41
|
* Atomic logical variable `"A"` (or any other alphanumeric combination)
|
42
42
|
* logical negation `"~A"`
|
43
43
|
* logical and `"A /\\ B"`
|
44
44
|
* logical or `"A \\/ B"`
|
45
45
|
* Implies `"A <=> B"`
|
46
|
-
* If and only if `"A
|
46
|
+
* If and only if `"A ==> B"`
|
47
47
|
* Entails `"A |= B"`
|
48
|
+
* Forall `"forall x. y"`
|
49
|
+
* Exists `"exists x. y"`
|
48
50
|
|
49
51
|
An example
|
50
52
|
|
51
53
|
```ruby
|
52
|
-
formula = '(Fire
|
54
|
+
formula = '(Fire ==> Smoke) /\\ Fire /\\ ~Smoke'.to_formula
|
53
55
|
```
|
54
56
|
|
55
57
|
To evaluate a formula use `Satre::Formula#eval`
|
56
58
|
|
57
59
|
```ruby
|
58
|
-
formula = '(Fire
|
59
|
-
formula.eval
|
60
|
+
formula = '(Fire ==> Smoke) /\\ Fire /\\ ~Smoke'.to_formula
|
61
|
+
formula.eval Fire: true, Smoke: true
|
60
62
|
```
|
61
63
|
|
62
|
-
Further are provided `Satre::Formula#tauntolgy?`,`Satre::Formula#satisfiable?`,`Satre::Formula#unsatisfiable?`
|
64
|
+
Further are provided `Satre::Formula#tauntolgy?`,`Satre::Formula#satisfiable?`,`Satre::Formula#unsatisfiable?`, `Satre::Formula#holds?`,`Satre::Formula#wellformed?`
|
63
65
|
|
64
66
|
For further information see the doc.
|
65
67
|
|
data/bin/exercise
CHANGED
@@ -6,16 +6,17 @@ require 'terminal-table'
|
|
6
6
|
|
7
7
|
include Satre
|
8
8
|
|
9
|
-
problem_4_1_1 = '
|
10
|
-
problem_4_1_2 = '
|
9
|
+
problem_4_1_1 = 'false |= true'.to_formula
|
10
|
+
problem_4_1_2 = 'true |= false'.to_formula
|
11
11
|
problem_4_1_3 = '(A /\\ B) |= (A <=> B)'.to_formula
|
12
12
|
problem_4_1_4 = '(A <=> B) |= A \\/ B'.to_formula
|
13
13
|
problem_4_1_5 = '(A <=> B) |= ~A \\/ B'.to_formula
|
14
14
|
|
15
|
-
problem_4_2_1 = 'Smoke
|
16
|
-
problem_4_2_2 = '(Smoke
|
15
|
+
problem_4_2_1 = 'Smoke ==> Smoke'.to_formula
|
16
|
+
problem_4_2_2 = '(Smoke ==> Fire) ==> (~Smoke ==> ~Fire)'.to_formula
|
17
17
|
problem_4_2_3 = 'Smoke \\/ Fire \\/ ~Fire'.to_formula
|
18
|
-
problem_4_2_4 = '(Fire
|
18
|
+
problem_4_2_4 = '(Fire ==> Smoke) /\\ Fire /\\ ~Smoke'.to_formula
|
19
|
+
|
19
20
|
|
20
21
|
bsays = 'b <=> (a <=> ~a)'.to_formula
|
21
22
|
csays = 'c <=> ~b'.to_formula
|
@@ -29,6 +30,33 @@ b_is_knave = Entails.new(kb,'~b'.to_formula)
|
|
29
30
|
c_is_knight = Entails.new(kb,'c'.to_formula)
|
30
31
|
c_is_knave = Entails.new(kb,'~c'.to_formula)
|
31
32
|
|
33
|
+
problem_5_1_1_1 = 'g(d,d)'.to_term
|
34
|
+
problem_5_1_1_2 = 'f(x,g(y,z),d)'.to_term
|
35
|
+
problem_5_1_1_3 = 'g(x,f(y,z),d)'.to_term
|
36
|
+
problem_5_1_1_4 = 'f(x,h(x,z),d)'.to_term
|
37
|
+
sig_5_1_1 = {d: 0, f: 2, g: 3}
|
38
|
+
|
39
|
+
problem_5_1_2_1 = 'S(m, x)'.to_formula
|
40
|
+
p problem_5_1_2_1
|
41
|
+
problem_5_1_2_2 = 'B(m, f(m))'.to_formula
|
42
|
+
problem_5_1_2_3 = 'B(B(m,x),y)'.to_formula
|
43
|
+
problem_5_1_2_4 = 'B(x,y) ==> (exists z. S(z,y))'.to_formula
|
44
|
+
problem_5_1_2_5 = 'S(x,y) ==> S(y,f(f(x)))'.to_formula
|
45
|
+
sig_5_1_2 = {m: 0, f: 1, S: 2, B: 2}
|
46
|
+
|
47
|
+
axiom_1 = "forall x. x = x".to_formula
|
48
|
+
axiom_2 = "forall x y. (x = y ==> y = x)".to_formula
|
49
|
+
axiom_3 = "forall x y z. (x = y /\\ y = x ==> x = z)".to_formula
|
50
|
+
|
51
|
+
domain = (0..23).to_a
|
52
|
+
valudation = {}
|
53
|
+
func = ->(f, args) {}
|
54
|
+
empty = ->(p, args) { if p == '=' then false else fail "undefined predicate #{p}" end }
|
55
|
+
universal = ->(p, args) { if p == '=' then true else fail "undefined predicate #{p}" end }
|
56
|
+
equality = ->(p, args) { if p == '=' then args.inject(:==) else fail "undefined predicate #{p}" end }
|
57
|
+
even_sum = ->(p, args) { if p == '=' then args.inject(:+).even? else fail "undefined predicate #{p}" end }
|
58
|
+
modular_aritmetic = ->(p, args) { if p == '=' then args[0] == (args[1] % 16) else fail "undefined predicate #{p}" end }
|
59
|
+
|
32
60
|
problem_4_1 = Terminal::Table.new do |t|
|
33
61
|
t.title = 'Problem 4.1'
|
34
62
|
t.headings = ['', 'Formula', 'Result' ]
|
@@ -39,7 +67,6 @@ problem_4_1 = Terminal::Table.new do |t|
|
|
39
67
|
t << ['5.', problem_4_1_5, problem_4_1_5.eval ]
|
40
68
|
end
|
41
69
|
|
42
|
-
|
43
70
|
problem_4_2 = Terminal::Table.new do |t|
|
44
71
|
t.title = 'Problem 4.2'
|
45
72
|
t.headings = ['', 'Formula', 'tauntolgy?', 'satifiable?', 'unsatifiable?']
|
@@ -56,15 +83,44 @@ problem_4_3 = Terminal::Table.new do |t|
|
|
56
83
|
t << ['is knave?', a_is_knave.eval , b_is_knave.eval , c_is_knave.eval ]
|
57
84
|
end
|
58
85
|
|
86
|
+
problem_5_1_1 = Terminal::Table.new do |t|
|
87
|
+
t.title = 'Problem 5.1.1'
|
88
|
+
t.headings = ['', 'Term', 'Signature', 'wellformed?']
|
89
|
+
t << ['1.', problem_5_1_1_1, sig_5_1_1.to_s, problem_5_1_1_1.wellformed?(sig_5_1_1) ]
|
90
|
+
t << ['2.', problem_5_1_1_2, sig_5_1_1.to_s, problem_5_1_1_2.wellformed?(sig_5_1_1) ]
|
91
|
+
t << ['3.', problem_5_1_1_3, sig_5_1_1.to_s, problem_5_1_1_3.wellformed?(sig_5_1_1) ]
|
92
|
+
t << ['4.', problem_5_1_1_4, sig_5_1_1.to_s, problem_5_1_1_4.wellformed?(sig_5_1_1) ]
|
93
|
+
end
|
94
|
+
|
95
|
+
problem_5_1_2 = Terminal::Table.new do |t|
|
96
|
+
t.title = 'Problem 5.1.2'
|
97
|
+
t.headings = ['', 'Formula', 'Signature', 'wellformed?']
|
98
|
+
t << ['1.', problem_5_1_2_1, sig_5_1_2.to_s, problem_5_1_2_1.wellformed?(sig_5_1_2) ]
|
99
|
+
t << ['2.', problem_5_1_2_2, sig_5_1_2.to_s, problem_5_1_2_2.wellformed?(sig_5_1_2) ]
|
100
|
+
t << ['3.', problem_5_1_2_3, sig_5_1_2.to_s, problem_5_1_2_3.wellformed?(sig_5_1_2) ]
|
101
|
+
t << ['4.', problem_5_1_2_4, sig_5_1_2.to_s, problem_5_1_2_4.wellformed?(sig_5_1_2) ]
|
102
|
+
t << ['5.', problem_5_1_2_5, sig_5_1_2.to_s, problem_5_1_2_5.wellformed?(sig_5_1_2) ]
|
103
|
+
end
|
104
|
+
|
105
|
+
problem_5_2 = Terminal::Table.new do |t|
|
106
|
+
t.title = 'Problem 5.2'
|
107
|
+
t.headings = ['relation', "#{axiom_1}.holds?", "#{axiom_2}.holds?", "#{axiom_3}.holds?"]
|
108
|
+
t << ['empty', axiom_1.holds?(domain, func, empty, valudation), axiom_2.holds?(domain, func, empty, valudation), axiom_3.holds?(domain, func, empty, valudation)]
|
109
|
+
t << ['universal', axiom_1.holds?(domain, func, universal, valudation), axiom_2.holds?(domain, func, universal, valudation), axiom_3.holds?(domain, func, universal, valudation)]
|
110
|
+
t << ['equality', axiom_1.holds?(domain, func, equality, valudation), axiom_2.holds?(domain, func, equality, valudation), axiom_3.holds?(domain, func, equality, valudation)]
|
111
|
+
t << ['even sum', axiom_1.holds?(domain, func, even_sum, valudation), axiom_2.holds?(domain, func, even_sum, valudation), axiom_3.holds?(domain, func, even_sum, valudation)]
|
112
|
+
t << ['modular aritmetic', axiom_1.holds?(domain, func, modular_aritmetic, valudation), axiom_2.holds?(domain, func, modular_aritmetic, valudation), axiom_3.holds?(domain, func, modular_aritmetic, valudation)]
|
113
|
+
end
|
59
114
|
|
60
115
|
puts problem_4_1
|
61
116
|
puts """I used a similar approach in my pencil-and-paper derivations
|
62
117
|
first subtitude the entails a |= b with a /\\ ~b and then check this statement
|
63
118
|
on unsatisfiability.
|
64
119
|
"""
|
65
|
-
|
66
120
|
puts problem_4_2
|
67
121
|
puts problem_4_3
|
68
|
-
|
69
122
|
puts """This approach uses the entails functions to solve the puzzle,
|
70
123
|
while in the exercise we substituded with the rules until clear statements were made."""
|
124
|
+
puts problem_5_1_1
|
125
|
+
puts problem_5_1_2
|
126
|
+
puts problem_5_2
|
data/lib/satre.rb
CHANGED
data/lib/satre/errors.rb
ADDED
data/lib/satre/formula.rb
CHANGED
@@ -1,10 +1,4 @@
|
|
1
1
|
require 'satre/formula/formula'
|
2
|
-
require 'satre/formula/
|
3
|
-
require 'satre/formula/
|
4
|
-
require 'satre/formula/
|
5
|
-
require 'satre/formula/false'
|
6
|
-
require 'satre/formula/iff'
|
7
|
-
require 'satre/formula/imp'
|
8
|
-
require 'satre/formula/not'
|
9
|
-
require 'satre/formula/or'
|
10
|
-
require 'satre/formula/true'
|
2
|
+
require 'satre/formula/term'
|
3
|
+
require 'satre/formula/propositional_logic'
|
4
|
+
require 'satre/formula/first_order_logic'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'satre/formula/first_order_logic/fol_formula'
|
2
|
+
|
3
|
+
module Satre
|
4
|
+
class Exists < Fol_Formula
|
5
|
+
attr_reader :variable
|
6
|
+
attr_reader :term
|
7
|
+
|
8
|
+
def initialize(variable, term)
|
9
|
+
#fail(ArgumentError, '...') unless variable.is_a?(Formula)
|
10
|
+
#fail(ArgumentError, '...') unless term.is_a?(Formula)
|
11
|
+
@variable = variable.dup.freeze
|
12
|
+
@term = term.dup.freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
# exists x. p is well-formed if p is well-formed
|
16
|
+
def wellformed?(sig)
|
17
|
+
term.wellformed?(sig)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Exists(x,p) -> exists (fun a -> holds m ((x |-> a) v) p) domain;;
|
21
|
+
def holds?(domain, func, pred, valudation)
|
22
|
+
domain.any? do |a|
|
23
|
+
valudation[variable.to_s.to_sym] = a
|
24
|
+
term.holds?(domain, func, pred, valudation )
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
"∃ #{variable}. #{term}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'satre/formula/formula'
|
2
|
+
|
3
|
+
module Satre
|
4
|
+
class Fol_Formula < Formula
|
5
|
+
|
6
|
+
# let rec holds (domain, func, pred as m) v fm =
|
7
|
+
# match fm with
|
8
|
+
# False -> false
|
9
|
+
# | True -> true
|
10
|
+
# | Atom(R(r,args)) -> pred r (map (termval m v) args)
|
11
|
+
# | Not(p) -> not(holds m v p)
|
12
|
+
# | And(p,q) -> (holds m v p) & (holds m v q)
|
13
|
+
# | Or(p,q) -> (holds m v p) or (holds m v q)
|
14
|
+
# | Imp(p,q) -> not(holds m v p) or (holds m v q)
|
15
|
+
# | Iff(p,q) -> (holds m v p = holds m v q)
|
16
|
+
# | Forall(x,p) -> forall (fun a -> holds m ((x |-> a) v) p) domain
|
17
|
+
# | Exists(x,p) -> exists (fun a -> holds m ((x |-> a) v) p) domani;;
|
18
|
+
def holds?(domain, func, predicate, valudation)
|
19
|
+
fail 'abstract method'
|
20
|
+
end
|
21
|
+
|
22
|
+
# 1. Constant True and False are wellformed
|
23
|
+
# 2. Predicate $p(x_1, \dots, x_n)$ is well-formed if
|
24
|
+
# (a) Each term is $x_1, \dots, x_n$ is well formed
|
25
|
+
# (b) There is a pair (q, m) in signature sig q = p and n = m
|
26
|
+
# 3. p //\ q is wellformed if p and q are wellformed
|
27
|
+
# 4. p \// q is wellformed if p and q are wellformed
|
28
|
+
# 5. p ==> q is wellformed if p and q are wellformed
|
29
|
+
# 6. p <=> q is wellformed if p and q are wellformed
|
30
|
+
# 7. forall x. p and exists x. p are wellformed if p is wellformed
|
31
|
+
def wellformed?(signature)
|
32
|
+
fail 'abstract method'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'satre/formula/first_order_logic/fol_formula'
|
2
|
+
|
3
|
+
module Satre
|
4
|
+
class Forall < Fol_Formula
|
5
|
+
attr_reader :variable
|
6
|
+
attr_reader :term
|
7
|
+
|
8
|
+
def initialize(variable, term)
|
9
|
+
#fail(ArgumentError, "Variable was #{variable.class}") unless variable.is_a?(Formula)
|
10
|
+
#fail(ArgumentError, "Term was #{term.class}") unless term.is_a?(Formula)
|
11
|
+
@variable = variable.dup.freeze
|
12
|
+
@term = term.dup.freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
# forall x. p is well-formed if p is well-formed
|
16
|
+
def wellformed?(sig)
|
17
|
+
term.wellformed?(sig)
|
18
|
+
end
|
19
|
+
|
20
|
+
# | Forall(x,p) -> forall (fun a -> holds m ((x |-> a) v) p) domain
|
21
|
+
def holds?(domain, func, pred, valudation)
|
22
|
+
domain.all? do |a|
|
23
|
+
valudation[variable.to_s.to_sym] = a
|
24
|
+
term.holds?(domain, func, pred, valudation)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_s
|
29
|
+
"∀ #{variable}. #{term}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'satre/formula/first_order_logic/fol_formula'
|
2
|
+
|
3
|
+
module Satre
|
4
|
+
# A first-order-logig relation between terms
|
5
|
+
#
|
6
|
+
# Typical relations are
|
7
|
+
# p > q - term p is greater than term p
|
8
|
+
# p < q - term p is less than term p
|
9
|
+
# p = q - term p is equvivalent to term p
|
10
|
+
# p >= q - term p is greter or equvivalent to term q
|
11
|
+
# p <= q - term p is less or equvivalent to term q
|
12
|
+
# p != q - term p is not equvivalent to term q
|
13
|
+
class Relation < Fol_Formula
|
14
|
+
attr_reader :relation
|
15
|
+
attr_reader :term_list
|
16
|
+
|
17
|
+
def initialize(relation, term_list)
|
18
|
+
@relation = relation.dup.freeze
|
19
|
+
@term_list = term_list.dup.freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
def holds?(domain, func, predicate, valudation)
|
23
|
+
predicate.call(relation, term_list.map { |t| t.validate(func, predicate, valudation) })
|
24
|
+
end
|
25
|
+
# A predicate p(x_1,...,x_n) is well-formed if
|
26
|
+
# (a) each term x_1,...,x_n is well-formed
|
27
|
+
# (b) there is a pair (q, m) in signature sig where q = p and n = m
|
28
|
+
def wellformed?(sig)
|
29
|
+
term_list.all? { |x| x.wellformed?(sig) } && sig[relation.to_sym] == term_list.length
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
return term_list.map(&:to_s).join(relation.to_s) if ['>','<','=','<=','>=','!='].include?(relation)
|
34
|
+
s = term_list.map(&:to_s).join(',')
|
35
|
+
"#{relation}#{"("+s+")" unless s.to_s == ''}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -3,18 +3,7 @@ module Satre
|
|
3
3
|
include Comparable
|
4
4
|
|
5
5
|
def <=>(other)
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
|
-
attr_reader :base
|
10
|
-
|
11
|
-
def initialize(base)
|
12
|
-
fail(ArgumentError, 'Argument must be a String') unless base.is_a?(String)
|
13
|
-
@base = base.dup.freeze
|
14
|
-
end
|
15
|
-
|
16
|
-
def to_s
|
17
|
-
base
|
6
|
+
self.to_s <=> other.to_s
|
18
7
|
end
|
19
8
|
|
20
9
|
def atoms
|
@@ -53,7 +42,6 @@ module Satre
|
|
53
42
|
end
|
54
43
|
|
55
44
|
def entails?(other)
|
56
|
-
#Imp.new(self, other).tautology?
|
57
45
|
And.new(self, Not.new(other)).unsatifiable?
|
58
46
|
end
|
59
47
|
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'satre/formula/propositional_logic/and'
|
2
|
+
require 'satre/formula/propositional_logic/atom'
|
3
|
+
require 'satre/formula/propositional_logic/entails'
|
4
|
+
require 'satre/formula/propositional_logic/false'
|
5
|
+
require 'satre/formula/propositional_logic/iff'
|
6
|
+
require 'satre/formula/propositional_logic/imp'
|
7
|
+
require 'satre/formula/propositional_logic/not'
|
8
|
+
require 'satre/formula/propositional_logic/or'
|
9
|
+
require 'satre/formula/propositional_logic/true'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'satre/formula'
|
2
|
+
|
3
|
+
module Satre
|
4
|
+
class And < Formula
|
5
|
+
attr_reader :left_conjunct
|
6
|
+
attr_reader :right_conjunct
|
7
|
+
|
8
|
+
def initialize(left_conjunct, right_conjunct)
|
9
|
+
fail(ArgumentError, 'Argument must be a Formula') unless left_conjunct.is_a?(Formula)
|
10
|
+
fail(ArgumentError, 'Argument must be a Formula') unless right_conjunct.is_a?(Formula)
|
11
|
+
@left_conjunct = left_conjunct.dup.freeze
|
12
|
+
@right_conjunct = right_conjunct.dup.freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"(#{left_conjunct} ∧ #{right_conjunct})"
|
17
|
+
end
|
18
|
+
|
19
|
+
def holds?(domain, func, pred, valudation)
|
20
|
+
left_conjunct.holds?(domain, func, pred, valudation) && right_conjunct.holds?(domain, func, pred, valudation)
|
21
|
+
end
|
22
|
+
|
23
|
+
# p /\\ q is well-formed if p and q are well-formed
|
24
|
+
def wellformed?(sig)
|
25
|
+
left_conjunct.wellformed?(sig) && right_conjunct.wellformed(sig)
|
26
|
+
end
|
27
|
+
|
28
|
+
def eval(valudation)
|
29
|
+
left_conjunct.eval(valudation) && right_conjunct.eval(valudation)
|
30
|
+
end
|
31
|
+
|
32
|
+
def atoms
|
33
|
+
atoms = left_conjunct.atoms + right_conjunct.atoms
|
34
|
+
atoms.uniq || []
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|