prop_logic 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/CHANGELOG.md +5 -1
- data/lib/prop_logic/and_term.rb +7 -7
- data/lib/prop_logic/constants.rb +7 -7
- data/lib/prop_logic/functions.rb +6 -6
- data/lib/prop_logic/not_term.rb +9 -9
- data/lib/prop_logic/or_term.rb +9 -9
- data/lib/prop_logic/sat_solver.rb +15 -10
- data/lib/prop_logic/term.rb +31 -31
- data/lib/prop_logic/then_term.rb +4 -4
- data/lib/prop_logic/variable.rb +9 -9
- data/lib/prop_logic/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ed096886dc984eabcd875c578b78a074b5c8b90
|
4
|
+
data.tar.gz: e449635063d3c36226d7efae7db50d0aaddc26be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8635b171e757d2e5bde2f2e16cf37baae110780dedaec0d76b703ae5c5c7189ca3095e45d8d4f31db3d4feb957c6bb990c38a782ad633544623b7f2e4e8067f6
|
7
|
+
data.tar.gz: 66febccd6887ec890e1e56aca6d6929c13381843d2953fc32b30233f0ac528ac9940482cb7eb08dfba5108c01016963d8198fb42a340de31476c40f31ccefa94
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
# Ver. 0.1.3 (2016/03/11)
|
2
|
+
- Code cleanup
|
3
|
+
- save `PropLogic.sat_solver` to module instance variable (no interface change)
|
4
|
+
|
1
5
|
# Ver. 0.1.2 (2016/03/07)
|
2
6
|
- Cache @variables (avoid recursive search)
|
3
7
|
|
4
8
|
# Ver. 0.1.1 (2016/01/28)
|
5
9
|
- `PropLogic.all_and`/`PropLogic.all_or` with less than one argument(s) behaviors fixed
|
6
|
-
- And/or terms with duplicated subterms are no longer regarded as reduced
|
10
|
+
- And/or terms with duplicated subterms are no longer regarded as reduced
|
7
11
|
|
8
12
|
# Ver. 0.1.0 (2016/01/27)
|
9
13
|
Initial version
|
data/lib/prop_logic/and_term.rb
CHANGED
@@ -26,12 +26,12 @@ module PropLogic
|
|
26
26
|
negated_variales = not_terms.map{|t| t.terms[0]}
|
27
27
|
@is_reduced = false unless (negated_variales & @terms).empty?
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def to_s(in_term = false)
|
31
31
|
str = @terms.map(&:to_s_in_term).join(' & ')
|
32
32
|
in_term ? "( #{str} )" : str
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def nnf?
|
36
36
|
@is_nnf
|
37
37
|
end
|
@@ -39,7 +39,7 @@ module PropLogic
|
|
39
39
|
def reduced?
|
40
40
|
@is_reduced
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
def reduce
|
44
44
|
return self if reduced?
|
45
45
|
reduced_terms = @terms.map(&:reduce).uniq
|
@@ -57,12 +57,12 @@ module PropLogic
|
|
57
57
|
Term.get self.class, *reduced_terms
|
58
58
|
end
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
def cnf?
|
62
62
|
return false unless reduced?
|
63
63
|
@terms.all?(&:cnf?)
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
def to_cnf
|
67
67
|
return super unless reduced?
|
68
68
|
return self if cnf?
|
@@ -70,13 +70,13 @@ module PropLogic
|
|
70
70
|
without_pools = all_and(*@terms.map{|t| t.tseitin(pool)})
|
71
71
|
all_and(without_pools, *pool)
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
def tseitin(pool)
|
75
75
|
val = Variable.new
|
76
76
|
terms = @terms.map{|t| t.cnf? ? t : t.tseitin(pool)}
|
77
77
|
pool.concat terms.map{|t| ~val | t }
|
78
78
|
val
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
end
|
82
82
|
end
|
data/lib/prop_logic/constants.rb
CHANGED
@@ -5,28 +5,28 @@ module PropLogic
|
|
5
5
|
def variables
|
6
6
|
[]
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
def to_cnf
|
10
10
|
self
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
class TrueConstant < Constant
|
16
16
|
include Singleton
|
17
17
|
def to_s(*)
|
18
18
|
'true'
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def assign(trues, falses, variables = nil)
|
22
22
|
if falses.include?(self)
|
23
23
|
raise ArgumentError, 'Contradicted assignment'
|
24
24
|
end
|
25
25
|
self
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
class FalseConstant < Constant
|
31
31
|
include Singleton
|
32
32
|
def to_s(*)
|
@@ -39,7 +39,7 @@ module PropLogic
|
|
39
39
|
self
|
40
40
|
end
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
True = TrueConstant.instance.freeze
|
44
44
|
False = FalseConstant.instance.freeze
|
45
45
|
end
|
data/lib/prop_logic/functions.rb
CHANGED
@@ -4,26 +4,26 @@ module PropLogic
|
|
4
4
|
def all_or(*args)
|
5
5
|
Term.get OrTerm, *args
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def all_and(*args)
|
9
9
|
Term.get AndTerm, *args
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def new_variable(*args)
|
13
13
|
Variable.new *args
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
extend Functions
|
18
18
|
include Functions
|
19
19
|
public_class_method(*Functions.private_instance_methods(false))
|
20
|
-
|
20
|
+
|
21
21
|
def all_combination(arr)
|
22
22
|
0.upto(arr.length) do |num|
|
23
23
|
arr.combination(num){|c| yield c}
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
module_function :all_combination
|
28
|
-
|
28
|
+
|
29
29
|
end
|
data/lib/prop_logic/not_term.rb
CHANGED
@@ -3,15 +3,15 @@ module PropLogic
|
|
3
3
|
def initialize(term)
|
4
4
|
@terms = [term].freeze
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def to_s(*)
|
8
8
|
"~" + @terms[0].to_s(true)
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
def nnf?
|
12
12
|
@terms[0].is_a?(Variable)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def to_nnf
|
16
16
|
term = @terms[0]
|
17
17
|
case term
|
@@ -27,11 +27,11 @@ module PropLogic
|
|
27
27
|
all_and(*term.terms.map{|t| (~t).to_nnf})
|
28
28
|
end
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def reduced?
|
32
32
|
nnf? && ! (@terms[0].is_a?(Constant))
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def reduce
|
36
36
|
return self if reduced?
|
37
37
|
reduced_term = @terms[0].reduce
|
@@ -44,7 +44,7 @@ module PropLogic
|
|
44
44
|
(~reduced_term).to_nnf
|
45
45
|
end
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
def to_cnf
|
49
49
|
if reduced?
|
50
50
|
self
|
@@ -52,7 +52,7 @@ module PropLogic
|
|
52
52
|
super
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
def tseitin(pool)
|
57
57
|
if nnf?
|
58
58
|
self
|
@@ -62,7 +62,7 @@ module PropLogic
|
|
62
62
|
raise 'Non-NNF terms cannot be converted to Tseitin form.' + self.to_s
|
63
63
|
end
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
alias_method :cnf?, :reduced?
|
67
67
|
end
|
68
|
-
end
|
68
|
+
end
|
data/lib/prop_logic/or_term.rb
CHANGED
@@ -2,7 +2,7 @@ module PropLogic
|
|
2
2
|
class OrTerm < Term
|
3
3
|
def initialize(*terms)
|
4
4
|
@terms = terms.map{|t| t.is_a?(OrTerm) ? t.terms : t}.flatten.freeze
|
5
|
-
@is_nnf = @terms.all?(&:nnf?)
|
5
|
+
@is_nnf = @terms.all?(&:nnf?)
|
6
6
|
@is_reduced = @is_nnf && @terms.all? do |term|
|
7
7
|
if term.is_a?(Constant) || !(term.reduced?)
|
8
8
|
false
|
@@ -25,20 +25,20 @@ module PropLogic
|
|
25
25
|
negated_variales = not_terms.map{|t| t.terms[0]}
|
26
26
|
@is_reduced = false unless (negated_variales & @terms).empty?
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def to_s(in_term = false)
|
30
30
|
str = @terms.map(&:to_s_in_term).join(' | ')
|
31
31
|
in_term ? "( #{str} )" : str
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def nnf?
|
35
35
|
@is_nnf
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
def reduced?
|
39
39
|
@is_reduced
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def reduce
|
43
43
|
return self if reduced?
|
44
44
|
reduced_terms = @terms.map(&:reduce).uniq
|
@@ -55,12 +55,12 @@ module PropLogic
|
|
55
55
|
Term.get self.class, *reduced_terms
|
56
56
|
end
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def cnf?
|
60
60
|
return false unless reduced?
|
61
61
|
! @terms.any?{ |term| term.is_a?(AndTerm) }
|
62
62
|
end
|
63
|
-
|
63
|
+
|
64
64
|
def to_cnf
|
65
65
|
return super unless reduced?
|
66
66
|
return self if cnf?
|
@@ -68,12 +68,12 @@ module PropLogic
|
|
68
68
|
without_pools = tseitin(pool)
|
69
69
|
all_and(without_pools, *pool)
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
def tseitin(pool)
|
73
73
|
val = Variable.new
|
74
74
|
terms = @terms.map{|t| t.tseitin(pool)}
|
75
75
|
pool << (~val | all_or(*terms))
|
76
|
-
val
|
76
|
+
val
|
77
77
|
end
|
78
78
|
|
79
79
|
end
|
@@ -1,13 +1,18 @@
|
|
1
|
+
# :nodoc:
|
1
2
|
module PropLogic
|
2
|
-
#default
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
3
|
+
# default SAT solver.
|
4
|
+
# only intended for test use.
|
5
|
+
@sat_solver = PropLogic::BruteForceSatSolver
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# @return [Object] current SAT solver
|
9
|
+
attr_reader :sat_solver
|
10
|
+
|
11
|
+
# @param [Object] new SAT solver.
|
12
|
+
# It must have #call(term) method
|
13
|
+
def sat_solver=(engine)
|
14
|
+
raise TypeError unless engine.respond_to?(:call)
|
15
|
+
@sat_solver = engine
|
16
|
+
end
|
12
17
|
end
|
13
18
|
end
|
data/lib/prop_logic/term.rb
CHANGED
@@ -4,52 +4,52 @@ require 'prop_logic/functions'
|
|
4
4
|
module PropLogic
|
5
5
|
class Term
|
6
6
|
include Functions
|
7
|
-
|
7
|
+
|
8
8
|
def initialize
|
9
9
|
raise NotImplementedError, 'Term cannot be initialized'
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def initialize_copy(*)
|
13
13
|
raise TypeError, 'Term cannot be duplicated (immutable, not necessary)'
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
class << self
|
17
17
|
protected :new
|
18
18
|
end
|
19
19
|
|
20
20
|
attr_reader :terms
|
21
|
-
|
21
|
+
|
22
22
|
def and(*others)
|
23
23
|
others.unshift self
|
24
24
|
Term.get AndTerm, *others
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
alias_method :&, :and
|
28
|
-
|
28
|
+
|
29
29
|
def or(*others)
|
30
30
|
others.unshift self
|
31
31
|
Term.get OrTerm, *others
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
alias_method :|, :or
|
35
|
-
|
35
|
+
|
36
36
|
def not
|
37
37
|
Term.get NotTerm, self
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
alias_method :~, :not
|
41
41
|
alias_method :-@, :not
|
42
|
-
|
42
|
+
|
43
43
|
def then(other)
|
44
44
|
Term.get ThenTerm, self, other
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
alias_method :>>, :then
|
48
|
-
|
48
|
+
|
49
49
|
def to_s_in_term
|
50
50
|
to_s true
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
def to_nnf
|
54
54
|
if nnf?
|
55
55
|
self
|
@@ -57,11 +57,11 @@ module PropLogic
|
|
57
57
|
Term.get self.class, *@terms.map(&:to_nnf)
|
58
58
|
end
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
def nnf?
|
62
62
|
false
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
def reduce
|
66
66
|
if reduced?
|
67
67
|
self
|
@@ -69,15 +69,15 @@ module PropLogic
|
|
69
69
|
Term.get self.class, *@terms.map(&:reduce)
|
70
70
|
end
|
71
71
|
end
|
72
|
-
|
72
|
+
|
73
73
|
def reduced?
|
74
74
|
false
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
def to_cnf
|
78
78
|
reduce.to_cnf
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
def self.validate_terms(*terms)
|
82
82
|
raise ArgumentError, 'no terms given' if terms.empty?
|
83
83
|
terms.map do |term|
|
@@ -93,16 +93,16 @@ module PropLogic
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
private_class_method :validate_terms
|
98
|
-
|
98
|
+
|
99
99
|
def self.get(klass, *terms)
|
100
100
|
@table ||= Ref::WeakValueMap.new
|
101
101
|
terms = validate_terms(*terms)
|
102
102
|
if klass == AndTerm || klass == OrTerm
|
103
103
|
terms = terms.map{|t| t.is_a?(klass) ? t.terms : t}.flatten
|
104
104
|
return terms[0] if terms.length == 1
|
105
|
-
end
|
105
|
+
end
|
106
106
|
key = klass.name + terms.map(&:object_id).join(',')
|
107
107
|
return @table[key] if @table[key]
|
108
108
|
ret = klass.__send__ :new, *terms
|
@@ -111,15 +111,15 @@ module PropLogic
|
|
111
111
|
ret.variables
|
112
112
|
ret.freeze
|
113
113
|
end
|
114
|
-
|
114
|
+
|
115
115
|
def cnf?
|
116
116
|
false
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
def variables
|
120
120
|
@variables ||= @terms.map(&:variables).flatten.uniq
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
def assign(trues, falses, variables = nil)
|
124
124
|
# contradicted assignment
|
125
125
|
raise ArgumentError, 'Contradicted assignment' unless (trues & falses).empty?
|
@@ -133,26 +133,26 @@ module PropLogic
|
|
133
133
|
end
|
134
134
|
Term.get self.class, *assigned_terms
|
135
135
|
end
|
136
|
-
|
136
|
+
|
137
137
|
def assign_true(*variables)
|
138
138
|
assign variables, []
|
139
139
|
end
|
140
|
-
|
140
|
+
|
141
141
|
def assign_false(*variables)
|
142
142
|
assign [], variables
|
143
143
|
end
|
144
|
-
|
144
|
+
|
145
145
|
def sat?
|
146
146
|
PropLogic.sat_solver.call(self)
|
147
147
|
end
|
148
|
-
|
148
|
+
|
149
149
|
def unsat?
|
150
150
|
sat? == false
|
151
151
|
end
|
152
|
-
|
152
|
+
|
153
153
|
def equiv?(other)
|
154
|
-
((self | other) & (~self | ~other)).unsat?
|
154
|
+
((self | other) & (~self | ~other)).unsat?
|
155
155
|
end
|
156
|
-
|
156
|
+
|
157
157
|
end
|
158
158
|
end
|
data/lib/prop_logic/then_term.rb
CHANGED
@@ -3,20 +3,20 @@ module PropLogic
|
|
3
3
|
def initialize(term1, term2)
|
4
4
|
@terms = [term1, term2].freeze
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def to_s(in_term = false)
|
8
8
|
str = "#{@terms[0].to_s(true)} => #{@terms[1].to_s(true)}"
|
9
9
|
in_term ? "( #{str} )" : str
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def nnf?
|
13
13
|
false
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def to_nnf
|
17
17
|
(~@terms[0]).to_nnf | @terms[1].to_nnf
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def reduce
|
21
21
|
to_nnf.reduce
|
22
22
|
end
|
data/lib/prop_logic/variable.rb
CHANGED
@@ -5,37 +5,37 @@ module PropLogic
|
|
5
5
|
@terms = [].freeze
|
6
6
|
freeze
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
public_class_method :new
|
10
|
-
|
10
|
+
|
11
11
|
def to_s(*)
|
12
12
|
@name
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
def nnf?
|
16
16
|
true
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def reduced?
|
20
20
|
true
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def to_cnf
|
24
24
|
self
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
def tseitin(pool)
|
28
28
|
self
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def cnf?
|
32
32
|
true
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def variables
|
36
36
|
[self]
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
def assign(trues, falses, variables = nil)
|
40
40
|
if trues.include? self
|
41
41
|
True
|
data/lib/prop_logic/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prop_logic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jkr2255
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
11
|
+
date: 2016-03-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ref
|
@@ -116,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
116
|
version: '0'
|
117
117
|
requirements: []
|
118
118
|
rubyforge_project:
|
119
|
-
rubygems_version: 2.4.
|
119
|
+
rubygems_version: 2.4.5.1
|
120
120
|
signing_key:
|
121
121
|
specification_version: 4
|
122
122
|
summary: Propositional logic for Ruby
|