prop_logic 0.1.2 → 0.1.3
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/.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
|