ravensat 0.2.2 → 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: 2206c8010f299d713c19b74682a2c46470d0c4cc7e27ade7e429ee0de09622de
4
- data.tar.gz: 14b05657764ab053b091da8f0ddb339201ea2cd469d2828eccc04fd0b3c4e49e
3
+ metadata.gz: 9d0f5a2e88e6b17130dc2101a9c2e85d0e401fba9bcba081299cf14ded1c683b
4
+ data.tar.gz: ee09cdeb7da7fd0cd04a80a5017ae351b836cf9a6d63ab92fddaa9181f36dff2
5
5
  SHA512:
6
- metadata.gz: ba52ce15498089d710d8e7ded3b8f35da11364a74a6f72241482ceb794cec83164423142e5b3d3feb90b0a444d8ec62327d7be830cac6d4390844fb9ce10cb6e
7
- data.tar.gz: 83509b606c6693373ce2918fe4ae9feda5aafbd241bca5510ed795cc52aae6dc0120cfc0e0294dd76a53004dbb825c1a9b0aa27664c47ff04a5e311ebf7bb167
6
+ metadata.gz: d763bab0b969a710ef42cae2e1aed39161e4b49488c1d898f8665b14a4763df09a881508875576f6505fc25c75daed694b805cb82ca081c95ac61d31bb49c12d
7
+ data.tar.gz: d5ff19dd7503194401664bba22b12bbe16a7ce8b6f1ff8cb54d19d1fcfde0d8912ad25d9762549d19f50dcc0d9d82161f020fae1c1207bd015ce530178eb8b62
data/README.md CHANGED
@@ -22,7 +22,7 @@ Or install it yourself as:
22
22
  $ gem install ravensat
23
23
 
24
24
  ## Usage
25
-
25
+ ### General Usage
26
26
  ```ruby
27
27
  require 'ravensat'
28
28
 
@@ -41,6 +41,42 @@ a.value #=> true
41
41
  b.value #=> true
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
+
44
80
  ## Development
45
81
 
46
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.
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,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
@@ -14,6 +14,20 @@ module Ravensat
14
14
  end
15
15
  end
16
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
+
17
31
  def &(object)
18
32
  AndNode.new(self, object)
19
33
  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
@@ -11,18 +11,15 @@ module Ravensat
11
11
  dimacs_header = "p cnf #{formula.vars_size} #{formula.clauses_size}\n"
12
12
  dimacs_body = ""
13
13
  create_table(formula)
14
- formula.each do |node|
14
+ formula.each_with_clause do |node|
15
15
  case node
16
- when AndNode
17
- when OrNode then dimacs_body << "\n"
16
+ when AndNode then dimacs_body << " 0\n"
17
+ when OrNode then dimacs_body << " "
18
18
  when NotNode then dimacs_body << "-"
19
- when VarNode then dimacs_body << @name_table[node] << " "
19
+ when VarNode then dimacs_body << @name_table[node]
20
20
  end
21
21
  end
22
-
23
- # dimacs_body formatting
24
- dimacs_body.strip! << ' '
25
- dimacs_body.gsub!(/\n{2,}/, "\n").gsub!(/\n/, "0\n") << '0'
22
+ dimacs_body << " 0\n"
26
23
 
27
24
  dimacs_header + dimacs_body
28
25
  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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ravensat
4
- VERSION = "0.2.2"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/ravensat.rb CHANGED
@@ -7,17 +7,12 @@ module Ravensat
7
7
  ast = File.dirname(__FILE__) + '/ravensat/ast'
8
8
  arcteryx = File.dirname(__FILE__) + '/arcteryx'
9
9
 
10
+ require_relative ravensat + "/ast.rb"
11
+ require_relative ravensat + "/dimacs.rb"
12
+
10
13
  autoload :Solver, ravensat + '/solver.rb'
11
- autoload :DimacsEncoder, ravensat + '/dimacs_encoder.rb'
12
- autoload :DimacsDecoder, ravensat + '/dimacs_decoder.rb'
13
14
  autoload :RavenClaw, ravensat + '/ravenclaw.rb'
14
-
15
- autoload :Node, ast + '/node.rb'
16
- autoload :VarNode, ast + '/var_node.rb'
17
- autoload :OprNode, ast + '/opr_node.rb'
18
- autoload :AndNode, ast + '/and_node.rb'
19
- autoload :OrNode, ast + '/or_node.rb'
20
- autoload :NotNode, ast + '/not_node.rb'
15
+ autoload :Extension, ravensat + '/extension.rb'
21
16
 
22
17
  autoload :Arcteryx, arcteryx + '/arcteryx.rb'
23
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.2.2
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: 2022-05-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:
@@ -28,17 +29,27 @@ files:
28
29
  - bin/console
29
30
  - bin/setup
30
31
  - example/magic_square_3x3.rb
32
+ - exe/ravensat
31
33
  - lib/arcteryx/arcteryx.rb
32
34
  - lib/arcteryx/cnf.rb
33
35
  - lib/ravensat.rb
36
+ - lib/ravensat/ast.rb
34
37
  - lib/ravensat/ast/and_node.rb
38
+ - lib/ravensat/ast/initial_node.rb
35
39
  - lib/ravensat/ast/node.rb
36
40
  - lib/ravensat/ast/not_node.rb
37
41
  - lib/ravensat/ast/opr_node.rb
38
42
  - lib/ravensat/ast/or_node.rb
39
43
  - lib/ravensat/ast/var_node.rb
40
- - lib/ravensat/dimacs_decoder.rb
41
- - lib/ravensat/dimacs_encoder.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
42
53
  - lib/ravensat/ravenclaw.rb
43
54
  - lib/ravensat/solver.rb
44
55
  - lib/ravensat/version.rb