ravensat 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a47d909acb01362653613bd0a4df6da1d426303a5e0919987b587fe3adcb77fd
4
- data.tar.gz: 46f323addbd8e5f183eeb8bd81c28ffd0994553bc63a2e99689b991a43d1e508
3
+ metadata.gz: 9d0f5a2e88e6b17130dc2101a9c2e85d0e401fba9bcba081299cf14ded1c683b
4
+ data.tar.gz: ee09cdeb7da7fd0cd04a80a5017ae351b836cf9a6d63ab92fddaa9181f36dff2
5
5
  SHA512:
6
- metadata.gz: 31ebd03521bce3df1d2447d9bddba7eef23deced640285f9bbfb79cf790bdc2a4af45b6c299e4ed5c6aa8000a43e4114b4d7045f1e963305175de85728a01cee
7
- data.tar.gz: '097189b8c4d177f9cd8658fa4ff16481616dfb9ca72c65fbe80fbcbb63eaa453db55067312ff152c4fff01e613f4f82c745e7594b6a00861ee2b266c7ea740d1'
6
+ metadata.gz: d763bab0b969a710ef42cae2e1aed39161e4b49488c1d898f8665b14a4763df09a881508875576f6505fc25c75daed694b805cb82ca081c95ac61d31bb49c12d
7
+ data.tar.gz: d5ff19dd7503194401664bba22b12bbe16a7ce8b6f1ff8cb54d19d1fcfde0d8912ad25d9762549d19f50dcc0d9d82161f020fae1c1207bd015ce530178eb8b62
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ravensat (0.1.0)
4
+ ravensat (0.1.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,10 +1,11 @@
1
1
  # Ravensat
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/ravensat`. To experiment with that code, run `bin/console` for an interactive prompt.
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(Not implemented)
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::PropVar.new
29
- b = Ravensat::PropVar.new
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
- ## Development(Not implemented)
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,11 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ require 'ravensat'
5
+ require 'pry'
6
+
7
+ module Ravensat
8
+ module Extension
9
+ binding.pry
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ module Ravensat
2
+ class AndNode < OprNode
3
+ end
4
+ end
@@ -0,0 +1,11 @@
1
+ module Ravensat
2
+ class InitialNode < Node
3
+ def &(object)
4
+ object
5
+ end
6
+
7
+ def |(object)
8
+ object
9
+ end
10
+ end
11
+ end
@@ -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
@@ -0,0 +1,4 @@
1
+ module Ravensat
2
+ class NotNode < OprNode
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module Ravensat
2
+ class OprNode < Node
3
+ def initialize(*nodes)
4
+ @children = nodes
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Ravensat
2
+ class OrNode < OprNode
3
+ def cnf?
4
+ return false if @children.any?{|node| node.is_a? AndNode}
5
+ @children.map(&:cnf?).reduce(:&)
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ module Ravensat
2
+ class VarNode < Node
3
+ attr_accessor :value
4
+ def initialize
5
+ @value
6
+ @children = []
7
+ end
8
+
9
+ def ~@
10
+ NotNode.new(self)
11
+ end
12
+
13
+ def cnf?
14
+ true
15
+ end
16
+ end
17
+ end
@@ -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,6 @@
1
+ module Ravensat
2
+ dir = File.dirname(__FILE__) + '/dimacs'
3
+
4
+ autoload :DimacsEncoder, dir + '/dimacs_encoder.rb'
5
+ autoload :DimacsDecoder, dir + '/dimacs_decoder.rb'
6
+ 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,9 @@
1
+ module Ravensat
2
+ module Extension
3
+ class UndefinedVariable < Variable
4
+ def is_defined?
5
+ false
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ module Ravensat
2
+ module Extension
3
+ class Variable
4
+
5
+ attr_reader :name, :args
6
+ def initialize(name, args)
7
+ @name = name
8
+ @args = args
9
+ end
10
+
11
+ def is_defined?
12
+ true
13
+ end
14
+ end
15
+ end
16
+ 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
@@ -1,15 +1,19 @@
1
1
  module Ravensat
2
- class RavenClaw
3
- def initialize; end
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(prop_vars)
10
- prop_vars.combination(2).map do |e|
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
@@ -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 cnf.to_dimacs
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ravensat
4
- VERSION = "0.1.1"
4
+ VERSION = "0.3.0"
5
5
  end
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.1.1
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: 2021-12-16 00:00:00.000000000 Z
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/prop_logic.rb
34
- - lib/ravensat/prop_var.rb
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
@@ -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
@@ -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