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 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