satre 0.1.0 → 1.0.0
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/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
|