ravensat 0.1.1 → 0.3.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 +1 -1
- data/README.md +44 -7
- data/example/magic_square_3x3.rb +48 -0
- data/exe/ravensat +11 -0
- data/lib/ravensat/ast/and_node.rb +4 -0
- data/lib/ravensat/ast/initial_node.rb +11 -0
- data/lib/ravensat/ast/node.rb +65 -0
- data/lib/ravensat/ast/not_node.rb +4 -0
- data/lib/ravensat/ast/opr_node.rb +7 -0
- data/lib/ravensat/ast/or_node.rb +8 -0
- data/lib/ravensat/ast/var_node.rb +17 -0
- data/lib/ravensat/ast.rb +11 -0
- data/lib/ravensat/dimacs/dimacs_decoder.rb +24 -0
- data/lib/ravensat/dimacs/dimacs_encoder.rb +31 -0
- data/lib/ravensat/dimacs.rb +6 -0
- data/lib/ravensat/extension/domain.rb +25 -0
- data/lib/ravensat/extension/variable/boolean_variable.rb +17 -0
- data/lib/ravensat/extension/variable/integer_variable.rb +63 -0
- data/lib/ravensat/extension/variable/undefined_variable.rb +9 -0
- data/lib/ravensat/extension/variable/variable.rb +16 -0
- data/lib/ravensat/extension.rb +13 -0
- data/lib/ravensat/ravenclaw.rb +11 -7
- data/lib/ravensat/solver.rb +4 -12
- data/lib/ravensat/version.rb +1 -1
- data/lib/ravensat.rb +5 -2
- metadata +23 -5
- data/lib/ravensat/prop_logic.rb +0 -92
- data/lib/ravensat/prop_var.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d0f5a2e88e6b17130dc2101a9c2e85d0e401fba9bcba081299cf14ded1c683b
|
4
|
+
data.tar.gz: ee09cdeb7da7fd0cd04a80a5017ae351b836cf9a6d63ab92fddaa9181f36dff2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d763bab0b969a710ef42cae2e1aed39161e4b49488c1d898f8665b14a4763df09a881508875576f6505fc25c75daed694b805cb82ca081c95ac61d31bb49c12d
|
7
|
+
data.tar.gz: d5ff19dd7503194401664bba22b12bbe16a7ce8b6f1ff8cb54d19d1fcfde0d8912ad25d9762549d19f50dcc0d9d82161f020fae1c1207bd015ce530178eb8b62
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# Ravensat
|
2
2
|
|
3
|
-
|
3
|
+
Ravensat is an interface to SAT Solver .
|
4
|
+
In order to use Ravensat, you need to install SAT Solver and specify the name of the Solver .
|
5
|
+
(If you do not specify SAT Solver, it will use the one bundled in the gem .)
|
4
6
|
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
6
7
|
|
7
|
-
## Installation
|
8
|
+
## Installation
|
8
9
|
|
9
10
|
Add this line to your application's Gemfile:
|
10
11
|
|
@@ -21,12 +22,12 @@ Or install it yourself as:
|
|
21
22
|
$ gem install ravensat
|
22
23
|
|
23
24
|
## Usage
|
24
|
-
|
25
|
+
### General Usage
|
25
26
|
```ruby
|
26
27
|
require 'ravensat'
|
27
28
|
|
28
|
-
a = Ravensat::
|
29
|
-
b = Ravensat::
|
29
|
+
a = Ravensat::VarNode.new
|
30
|
+
b = Ravensat::VarNode.new
|
30
31
|
|
31
32
|
a.value #=> nil
|
32
33
|
b.value #=> nil
|
@@ -40,7 +41,43 @@ a.value #=> true
|
|
40
41
|
b.value #=> true
|
41
42
|
```
|
42
43
|
|
43
|
-
|
44
|
+
### Extension Usage(SAT)
|
45
|
+
```ruby
|
46
|
+
require 'ravensat'
|
47
|
+
|
48
|
+
module Ravensat
|
49
|
+
module Extension
|
50
|
+
bool a, b
|
51
|
+
logic = (a | b) & (~a | b) & (a | ~b)
|
52
|
+
|
53
|
+
solver = Ravensat::Solver.new
|
54
|
+
solver.solve logic #=> true
|
55
|
+
|
56
|
+
a.value #=> true
|
57
|
+
b.value #=> true
|
58
|
+
end
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
### Extension Usage(CSP; Constraint Satisfaction Problem)
|
63
|
+
```ruby
|
64
|
+
require 'ravensat'
|
65
|
+
|
66
|
+
module Ravensat
|
67
|
+
module Extension
|
68
|
+
int a(1..10), b(1..10)
|
69
|
+
constraint = (a.only_one & b.only_one & (a != b))
|
70
|
+
|
71
|
+
solver = Ravensat::Solver.new
|
72
|
+
solver.solve constraint #=> true
|
73
|
+
|
74
|
+
a.result #=> 1
|
75
|
+
b.result #=> 2
|
76
|
+
end
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
## Development
|
44
81
|
|
45
82
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
46
83
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'ravensat'
|
3
|
+
require 'pry'
|
4
|
+
|
5
|
+
# | ---- | ---- | ---- |
|
6
|
+
# | X1 | X2 | X3 |
|
7
|
+
# | X4 | X5 | X6 |
|
8
|
+
# | X7 | X8 | X9 |
|
9
|
+
# | ---- | ---- | ---- |
|
10
|
+
|
11
|
+
x1 = Array.new(9){ Ravensat::VarNode.new }
|
12
|
+
x2 = Array.new(9){ Ravensat::VarNode.new }
|
13
|
+
x3 = Array.new(9){ Ravensat::VarNode.new }
|
14
|
+
x4 = Array.new(9){ Ravensat::VarNode.new }
|
15
|
+
x5 = Array.new(9){ Ravensat::VarNode.new }
|
16
|
+
x6 = Array.new(9){ Ravensat::VarNode.new }
|
17
|
+
x7 = Array.new(9){ Ravensat::VarNode.new }
|
18
|
+
x8 = Array.new(9){ Ravensat::VarNode.new }
|
19
|
+
x9 = Array.new(9){ Ravensat::VarNode.new }
|
20
|
+
x = [x1, x2, x3, x4, x5, x6, x7, x8, x9]
|
21
|
+
|
22
|
+
logic = x1[4]
|
23
|
+
|
24
|
+
# one square, one number
|
25
|
+
9.times do |i|
|
26
|
+
logic &= Ravensat::RavenClaw.alo [x[i][0], x[i][1], x[i][2], x[i][3], x[i][4], x[i][5], x[i][6], x[i][7], x[i][8]]
|
27
|
+
logic &= Ravensat::RavenClaw.amo [x[i][0], x[i][1], x[i][2], x[i][3], x[i][4], x[i][5], x[i][6], x[i][7], x[i][8]]
|
28
|
+
end
|
29
|
+
|
30
|
+
# x1 ~ x9 are all different numbers
|
31
|
+
9.times do |i|
|
32
|
+
logic &= Ravensat::RavenClaw.alo [x[0][i], x[1][i], x[2][i], x[3][i], x[4][i], x[5][i], x[6][i], x[7][i], x[8][i]]
|
33
|
+
logic &= Ravensat::RavenClaw.amo [x[0][i], x[1][i], x[2][i], x[3][i], x[4][i], x[5][i], x[6][i], x[7][i], x[8][i]]
|
34
|
+
end
|
35
|
+
|
36
|
+
# TODO: generate constraint that sum to 15 in a row
|
37
|
+
# sum to 15 in a row
|
38
|
+
|
39
|
+
solver = Ravensat::Solver.new
|
40
|
+
solver.solve logic
|
41
|
+
|
42
|
+
puts <<~"MAGIC_SQUARE"
|
43
|
+
| --- | --- | --- |
|
44
|
+
| #{x1.index{|x| x.value} + 1} | #{x2.index{|x| x.value} + 1} | #{x3.index{|x| x.value} + 1} |
|
45
|
+
| #{x4.index{|x| x.value} + 1} | #{x5.index{|x| x.value} + 1} | #{x6.index{|x| x.value} + 1} |
|
46
|
+
| #{x7.index{|x| x.value} + 1} | #{x8.index{|x| x.value} + 1} | #{x9.index{|x| x.value} + 1} |
|
47
|
+
| --- | --- | --- |
|
48
|
+
MAGIC_SQUARE
|
data/exe/ravensat
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Ravensat
|
2
|
+
class Node
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_reader :children
|
6
|
+
def initialize
|
7
|
+
@children = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def each
|
11
|
+
yield(self)
|
12
|
+
@children.each do |child|
|
13
|
+
child.each {|c| yield(c)}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def each_with_clause
|
18
|
+
case self
|
19
|
+
when AndNode, OrNode
|
20
|
+
@children.first.each_with_clause{|c| yield(c)}
|
21
|
+
yield(self)
|
22
|
+
@children.last.each_with_clause{|c| yield(c)}
|
23
|
+
when NotNode
|
24
|
+
yield(self)
|
25
|
+
@children.first.each_with_clause{|c| yield(c)}
|
26
|
+
when VarNode
|
27
|
+
yield(self)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def &(object)
|
32
|
+
AndNode.new(self, object)
|
33
|
+
end
|
34
|
+
|
35
|
+
def |(object)
|
36
|
+
OrNode.new(self, object)
|
37
|
+
end
|
38
|
+
|
39
|
+
# def tree_text
|
40
|
+
# self.each do |child|
|
41
|
+
# child.to_s
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
self.class.name
|
47
|
+
end
|
48
|
+
|
49
|
+
def cnf?
|
50
|
+
@children.map(&:cnf?).reduce(:&)
|
51
|
+
end
|
52
|
+
|
53
|
+
def vars
|
54
|
+
self.select{|node| node.is_a? VarNode}.uniq
|
55
|
+
end
|
56
|
+
|
57
|
+
def vars_size
|
58
|
+
self.vars.size
|
59
|
+
end
|
60
|
+
|
61
|
+
def clauses_size
|
62
|
+
self.count{|node| node.is_a? AndNode} + 1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/ravensat/ast.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module Ravensat
|
2
|
+
dir = File.dirname(__FILE__) + '/ast'
|
3
|
+
|
4
|
+
autoload :Node, dir + '/node.rb'
|
5
|
+
autoload :VarNode, dir + '/var_node.rb'
|
6
|
+
autoload :OprNode, dir + '/opr_node.rb'
|
7
|
+
autoload :AndNode, dir + '/and_node.rb'
|
8
|
+
autoload :OrNode, dir + '/or_node.rb'
|
9
|
+
autoload :NotNode, dir + '/not_node.rb'
|
10
|
+
autoload :InitialNode, dir + '/initial_node.rb'
|
11
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Ravensat
|
2
|
+
class DimacsDecoder
|
3
|
+
def decode(model, name_table)
|
4
|
+
inverted_name_table = name_table.invert
|
5
|
+
case model.first
|
6
|
+
when "SAT"
|
7
|
+
model.last.split.each do |e|
|
8
|
+
if e == '0'
|
9
|
+
next
|
10
|
+
elsif e[0] == "-"
|
11
|
+
index = e.slice(1..-1)
|
12
|
+
inverted_name_table[index].value = false
|
13
|
+
else
|
14
|
+
index = e
|
15
|
+
inverted_name_table[index].value = true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
true
|
19
|
+
when "UNSAT"
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Ravensat
|
2
|
+
class DimacsEncoder
|
3
|
+
attr_reader :name_table
|
4
|
+
def initialize
|
5
|
+
@name_table = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_dimacs(formula)
|
9
|
+
return nil unless formula.cnf?
|
10
|
+
|
11
|
+
dimacs_header = "p cnf #{formula.vars_size} #{formula.clauses_size}\n"
|
12
|
+
dimacs_body = ""
|
13
|
+
create_table(formula)
|
14
|
+
formula.each_with_clause do |node|
|
15
|
+
case node
|
16
|
+
when AndNode then dimacs_body << " 0\n"
|
17
|
+
when OrNode then dimacs_body << " "
|
18
|
+
when NotNode then dimacs_body << "-"
|
19
|
+
when VarNode then dimacs_body << @name_table[node]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
dimacs_body << " 0\n"
|
23
|
+
|
24
|
+
dimacs_header + dimacs_body
|
25
|
+
end
|
26
|
+
|
27
|
+
def create_table(formula)
|
28
|
+
@name_table = formula.vars.zip((1..formula.vars.size).map(&:to_s)).to_h
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Ravensat
|
2
|
+
module Extension
|
3
|
+
module Domain
|
4
|
+
LOCAL_VARIABLE_TABLE = {}
|
5
|
+
def int(*vars)
|
6
|
+
vars.each do |var|
|
7
|
+
next if var.is_defined?
|
8
|
+
LOCAL_VARIABLE_TABLE[var.name] = Ravensat::Extension::IntegerVariable.new(var.name, var.args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def bool(*vars)
|
13
|
+
vars.each do |var|
|
14
|
+
next if var.is_defined?
|
15
|
+
# LOCAL_VARIABLE_TABLE[var.name] = Ravensat::VarNode.new
|
16
|
+
LOCAL_VARIABLE_TABLE[var.name] = Ravensat::Extension::BooleanVariable.new(var.name, var.args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def method_missing(name, *args)
|
21
|
+
LOCAL_VARIABLE_TABLE[name] || UndefinedVariable.new(name, args)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Ravensat
|
4
|
+
module Extension
|
5
|
+
class BooleanVariable < Variable
|
6
|
+
extend Forwardable
|
7
|
+
delegate Node.public_instance_methods(false) => :@var_node
|
8
|
+
delegate OprNode.public_instance_methods(false) => :@var_node
|
9
|
+
delegate VarNode.public_instance_methods(false) => :@var_node
|
10
|
+
|
11
|
+
def initialize(name, args)
|
12
|
+
super
|
13
|
+
@var_node = VarNode.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Ravensat
|
2
|
+
module Extension
|
3
|
+
class IntegerVariable < Variable
|
4
|
+
|
5
|
+
attr_reader :var_nodes
|
6
|
+
def initialize(name, args)
|
7
|
+
super
|
8
|
+
return unless args.first.is_a? Range
|
9
|
+
@var_nodes = args.first.zip(Array.new(args.first.size){Ravensat::VarNode.new}).to_h
|
10
|
+
end
|
11
|
+
|
12
|
+
def ==(object)
|
13
|
+
case object
|
14
|
+
when Integer
|
15
|
+
return @var_nodes[object]
|
16
|
+
when IntegerVariable
|
17
|
+
result_formula = Ravensat::InitialNode.new
|
18
|
+
duplicated_keys = self.var_nodes.keys & object.var_nodes.keys
|
19
|
+
|
20
|
+
[self.var_nodes, object.var_nodes].repeated_permutation(duplicated_keys.size) do |var_nodes|
|
21
|
+
result_formula &= Ravensat::RavenClaw.alo(var_nodes.zip(duplicated_keys).map{|arr| arr.first[arr.last]})
|
22
|
+
end
|
23
|
+
return result_formula
|
24
|
+
else
|
25
|
+
raise ArgumentError
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def !=(object)
|
30
|
+
case object
|
31
|
+
when Integer
|
32
|
+
return ~(@var_nodes[object])
|
33
|
+
when IntegerVariable
|
34
|
+
result_formula = Ravensat::InitialNode.new
|
35
|
+
duplicated_keys = self.var_nodes.keys & object.var_nodes.keys
|
36
|
+
|
37
|
+
duplicated_keys.each do |index|
|
38
|
+
result_formula &= ~(self.var_nodes[index]) | ~(object.var_nodes[index])
|
39
|
+
end
|
40
|
+
return result_formula
|
41
|
+
else
|
42
|
+
raise ArgumentError
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def only_one
|
47
|
+
result_formula = Ravensat::InitialNode.new
|
48
|
+
result_formula &= Ravensat::RavenClaw.alo @var_nodes.values
|
49
|
+
result_formula &= Ravensat::RavenClaw.amo @var_nodes.values
|
50
|
+
result_formula
|
51
|
+
end
|
52
|
+
|
53
|
+
def result
|
54
|
+
result = @var_nodes.select{|key, var_node| var_node.value}.keys
|
55
|
+
if result.one?
|
56
|
+
result.first
|
57
|
+
else
|
58
|
+
result
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Ravensat
|
2
|
+
module Extension
|
3
|
+
dir = File.dirname(__FILE__) + '/extension'
|
4
|
+
|
5
|
+
autoload :Domain, dir + '/domain.rb'
|
6
|
+
autoload :Variable, dir + '/variable/variable.rb'
|
7
|
+
autoload :BooleanVariable, dir + '/variable/boolean_variable.rb'
|
8
|
+
autoload :IntegerVariable, dir + '/variable/integer_variable.rb'
|
9
|
+
autoload :UndefinedVariable, dir + '/variable/undefined_variable.rb'
|
10
|
+
|
11
|
+
extend Domain
|
12
|
+
end
|
13
|
+
end
|
data/lib/ravensat/ravenclaw.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
module Ravensat
|
2
|
-
|
3
|
-
def
|
4
|
-
|
5
|
-
def self.alo(prop_vars)
|
6
|
-
prop_vars.reduce(:|)
|
2
|
+
module RavenClaw
|
3
|
+
def self.alo(bool_vars)
|
4
|
+
bool_vars.reduce(:|)
|
7
5
|
end
|
8
6
|
|
9
|
-
def self.amo(
|
10
|
-
|
7
|
+
def self.amo(bool_vars)
|
8
|
+
bool_vars.combination(2).map do |e|
|
11
9
|
e.map(&:~@).reduce(:|)
|
12
10
|
end.reduce(:&)
|
13
11
|
end
|
12
|
+
|
13
|
+
def self.all_different(*int_vars)
|
14
|
+
int_vars.combination(2).map do |int_var|
|
15
|
+
int_var.reduce(:!=)
|
16
|
+
end.reduce(:&)
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
data/lib/ravensat/solver.rb
CHANGED
@@ -15,10 +15,11 @@ module Ravensat
|
|
15
15
|
# end
|
16
16
|
|
17
17
|
def solve( cnf )
|
18
|
+
encoder = DimacsEncoder.new
|
18
19
|
@input_file = Tempfile.open(["ravensat",".cnf"])
|
19
20
|
@output_file = Tempfile.open(["ravensat",".mdl"])
|
20
21
|
|
21
|
-
@input_file.write
|
22
|
+
@input_file.write encoder.to_dimacs(cnf)
|
22
23
|
@input_file.flush
|
23
24
|
|
24
25
|
case @name
|
@@ -28,18 +29,9 @@ module Ravensat
|
|
28
29
|
system("#{@name} #{@input_file.to_path} #{@output_file.to_path}")
|
29
30
|
end
|
30
31
|
|
32
|
+
decoder = DimacsDecoder.new
|
31
33
|
model = @output_file.read.split("\n")
|
32
|
-
|
33
|
-
case model.first
|
34
|
-
when "SAT"
|
35
|
-
model.last.split.each do |e|
|
36
|
-
next if e == '0'
|
37
|
-
cnf.name_table.find{|key,value| value == e.to_i.abs.to_s}.first.value = !e.start_with?('-')
|
38
|
-
end
|
39
|
-
Arcteryx::SAT
|
40
|
-
when "UNSAT"
|
41
|
-
Arcteryx::UNSAT
|
42
|
-
end
|
34
|
+
decoder.decode(model, encoder.name_table)
|
43
35
|
end
|
44
36
|
|
45
37
|
end
|
data/lib/ravensat/version.rb
CHANGED
data/lib/ravensat.rb
CHANGED
@@ -4,12 +4,15 @@ require_relative "ravensat/version"
|
|
4
4
|
|
5
5
|
module Ravensat
|
6
6
|
ravensat = File.dirname(__FILE__) + '/ravensat'
|
7
|
+
ast = File.dirname(__FILE__) + '/ravensat/ast'
|
7
8
|
arcteryx = File.dirname(__FILE__) + '/arcteryx'
|
8
9
|
|
10
|
+
require_relative ravensat + "/ast.rb"
|
11
|
+
require_relative ravensat + "/dimacs.rb"
|
12
|
+
|
9
13
|
autoload :Solver, ravensat + '/solver.rb'
|
10
|
-
autoload :PropVar, ravensat + '/prop_var.rb'
|
11
|
-
autoload :PropLogic, ravensat + '/prop_logic.rb'
|
12
14
|
autoload :RavenClaw, ravensat + '/ravenclaw.rb'
|
15
|
+
autoload :Extension, ravensat + '/extension.rb'
|
13
16
|
|
14
17
|
autoload :Arcteryx, arcteryx + '/arcteryx.rb'
|
15
18
|
end
|
metadata
CHANGED
@@ -1,19 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ravensat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- rikuto matsuda
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
15
15
|
- p99y92og@s.okayama-u.ac.jp
|
16
|
-
executables:
|
16
|
+
executables:
|
17
|
+
- ravensat
|
17
18
|
extensions: []
|
18
19
|
extra_rdoc_files: []
|
19
20
|
files:
|
@@ -27,11 +28,28 @@ files:
|
|
27
28
|
- Rakefile
|
28
29
|
- bin/console
|
29
30
|
- bin/setup
|
31
|
+
- example/magic_square_3x3.rb
|
32
|
+
- exe/ravensat
|
30
33
|
- lib/arcteryx/arcteryx.rb
|
31
34
|
- lib/arcteryx/cnf.rb
|
32
35
|
- lib/ravensat.rb
|
33
|
-
- lib/ravensat/
|
34
|
-
- lib/ravensat/
|
36
|
+
- lib/ravensat/ast.rb
|
37
|
+
- lib/ravensat/ast/and_node.rb
|
38
|
+
- lib/ravensat/ast/initial_node.rb
|
39
|
+
- lib/ravensat/ast/node.rb
|
40
|
+
- lib/ravensat/ast/not_node.rb
|
41
|
+
- lib/ravensat/ast/opr_node.rb
|
42
|
+
- lib/ravensat/ast/or_node.rb
|
43
|
+
- lib/ravensat/ast/var_node.rb
|
44
|
+
- lib/ravensat/dimacs.rb
|
45
|
+
- lib/ravensat/dimacs/dimacs_decoder.rb
|
46
|
+
- lib/ravensat/dimacs/dimacs_encoder.rb
|
47
|
+
- lib/ravensat/extension.rb
|
48
|
+
- lib/ravensat/extension/domain.rb
|
49
|
+
- lib/ravensat/extension/variable/boolean_variable.rb
|
50
|
+
- lib/ravensat/extension/variable/integer_variable.rb
|
51
|
+
- lib/ravensat/extension/variable/undefined_variable.rb
|
52
|
+
- lib/ravensat/extension/variable/variable.rb
|
35
53
|
- lib/ravensat/ravenclaw.rb
|
36
54
|
- lib/ravensat/solver.rb
|
37
55
|
- lib/ravensat/version.rb
|
data/lib/ravensat/prop_logic.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
module Ravensat
|
2
|
-
class PropLogic
|
3
|
-
attr_reader :formula
|
4
|
-
attr_reader :name_table
|
5
|
-
|
6
|
-
def initialize( init_formula )
|
7
|
-
@formula = init_formula
|
8
|
-
# (a | b) & (~a | b) & (a | ~b) & (~a | ~b)
|
9
|
-
|
10
|
-
# [:and,
|
11
|
-
# [:or, a, b],
|
12
|
-
# [:or, [:not, a], b],
|
13
|
-
# [:or, a, [:not, b]],
|
14
|
-
# [:or, [:not, a], [:not, b]]
|
15
|
-
# ]
|
16
|
-
end
|
17
|
-
|
18
|
-
def to_cnf
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
def to_dimacs
|
23
|
-
cnf_text = String.new
|
24
|
-
tmp_name_table = @formula.flatten.uniq.reject{|e| e.class == Symbol}
|
25
|
-
@name_table = tmp_name_table.zip((1..tmp_name_table.size).to_a.map{|e| e.to_s}).to_h
|
26
|
-
|
27
|
-
nr_vars = tmp_name_table.size
|
28
|
-
nr_clses = @formula.size - 1
|
29
|
-
cnf_header = 'p cnf ' << nr_vars.to_s << ' ' << nr_clses.to_s << "\n"
|
30
|
-
# @formula.is_cnf?
|
31
|
-
@formula.each do |clause|
|
32
|
-
# next if clause.first != :and
|
33
|
-
case clause
|
34
|
-
when Symbol
|
35
|
-
next
|
36
|
-
when Array
|
37
|
-
case clause.first
|
38
|
-
when :or
|
39
|
-
clause.each do |literal|
|
40
|
-
case literal
|
41
|
-
when Symbol
|
42
|
-
next
|
43
|
-
when Ravensat::PropVar
|
44
|
-
cnf_text << @name_table[literal] << ' '
|
45
|
-
when Array #&& literal.first == :not
|
46
|
-
cnf_text << '-' << @name_table[literal.last] << ' '
|
47
|
-
end
|
48
|
-
end
|
49
|
-
when :not
|
50
|
-
cnf_text << '-' << @name_table[clause.last] << ' '
|
51
|
-
end
|
52
|
-
when Ravensat::PropVar
|
53
|
-
cnf_text << @name_table[clause] << ' '
|
54
|
-
end
|
55
|
-
cnf_text << '0' << "\n"
|
56
|
-
end
|
57
|
-
cnf_header + cnf_text
|
58
|
-
end
|
59
|
-
|
60
|
-
def &( object )
|
61
|
-
if @formula.first == :and
|
62
|
-
@formula.append object.formula
|
63
|
-
else
|
64
|
-
@formula = [:and, @formula, object.formula]
|
65
|
-
end
|
66
|
-
self
|
67
|
-
# Ravensat::PropLogic.new [:and, @formula, object]
|
68
|
-
# formulaがcnfである前提の実装
|
69
|
-
# @formula & other_formula
|
70
|
-
end
|
71
|
-
|
72
|
-
def |( object )
|
73
|
-
if @formula.first == :or
|
74
|
-
@formula.append object.formula
|
75
|
-
else
|
76
|
-
@formula = [:or, @formula, object.formula]
|
77
|
-
end
|
78
|
-
self
|
79
|
-
# Ravensat::PropLogic.new [:or, @formula, object]
|
80
|
-
# 木構造に落とすのが難しそう,実装見送り
|
81
|
-
# @formula | other_formula
|
82
|
-
end
|
83
|
-
|
84
|
-
# def to_a
|
85
|
-
# @formula.each do |f|
|
86
|
-
# if f.class == PropLogic
|
87
|
-
# f = f.to_a
|
88
|
-
# end
|
89
|
-
# end
|
90
|
-
# end
|
91
|
-
end
|
92
|
-
end
|
data/lib/ravensat/prop_var.rb
DELETED
@@ -1,45 +0,0 @@
|
|
1
|
-
module Ravensat
|
2
|
-
class PropVar
|
3
|
-
attr_accessor :value
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
@value # => true | false | undef
|
7
|
-
end
|
8
|
-
|
9
|
-
# def +@
|
10
|
-
# # unuse?
|
11
|
-
# # return PropLogic object
|
12
|
-
# 'this is +@ method'
|
13
|
-
# end
|
14
|
-
|
15
|
-
# def -@
|
16
|
-
# # return PropLogic object
|
17
|
-
# 'this is -@ method'
|
18
|
-
# end
|
19
|
-
|
20
|
-
def ~@
|
21
|
-
Ravensat::PropLogic.new [:not, self]
|
22
|
-
# return PropLogic object
|
23
|
-
end
|
24
|
-
|
25
|
-
def &( object )
|
26
|
-
Ravensat::PropLogic.new [:and, self, object.formula]
|
27
|
-
# return PropLogic object
|
28
|
-
end
|
29
|
-
|
30
|
-
def |( object )
|
31
|
-
Ravensat::PropLogic.new [:or, self, object.formula]
|
32
|
-
# return PropLogic object
|
33
|
-
end
|
34
|
-
|
35
|
-
def formula
|
36
|
-
# $BIU$1>F?O%a%=%C%I(B
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
|
-
# def self
|
41
|
-
# 'this is self method'
|
42
|
-
# end
|
43
|
-
|
44
|
-
end
|
45
|
-
end
|