ravensat 1.0.0 → 1.0.3

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: bd6bb73a8f6668c36675461d24272ae8e02632c5b2d3f768b5a81347ad29956a
4
- data.tar.gz: 48e4f44fa76bd1716b32ed98ddaa82d198cb83064e944269ecfd57ab21645860
3
+ metadata.gz: 430c194a8bc6d59ba234e117839a244c0ee4bb61b507615b1a12b1d52609013c
4
+ data.tar.gz: e2090935ff06835501061059e47156889e13bc9afe7c3a57746958afe6c4abb0
5
5
  SHA512:
6
- metadata.gz: 5365bfdf37eeb55b5a7ccab53f0ecca8cf8c73ecdfcac2eb9c92ce843aa6fa2e77f711f14a9b00f37cb9a37bfade19c65ea38cbd3f7478398b0d1ef8a5cf416a
7
- data.tar.gz: abf648c3097425241ae106e7ed42876f9c9a33e55bf4615cefc16c77943aedf62b0bd99fc6b9c2062147dbaf6c9b690b13f5a28204771e03934e4c59bdf98a9e
6
+ metadata.gz: 5500d691a90e8153d994db9c9fb0f5e4c0729232820fb41b7b6ddf1726a95090a783cf09c272e9459d139b2693effccb1c3e7e55625d15e269fc0595b5235327
7
+ data.tar.gz: 2e9f44f44ef99640f370eb2329059438670b84e743729e8d4eaa19d585cc02bab17d506c45324971b2034cba7a41af890081f03803ebb7155fafced6d5c5725f
data/README.md CHANGED
@@ -1,24 +1,26 @@
1
- # Ravensat
2
-
3
1
  [![GitHub Actions](https://github.com/matsuda0528/ravensat/actions/workflows/main.yml/badge.svg)](https://github.com/matsuda0528/ravensat/actions/workflows/main.yml)
4
2
  [![Gem Version](https://badge.fury.io/rb/ravensat.svg)](https://badge.fury.io/rb/ravensat)
5
3
  [![LICENSE](https://img.shields.io/github/license/matsuda0528/ravensat)](https://opensource.org/licenses/MIT)
6
4
 
7
- [![GitHub Pages](https://img.shields.io/badge/GitHub%20Pages--brightgreen.svg?logo=github&style=social)](https://matsuda0528.github.io/ravensat/)
5
+ <!-- [![GitHub Pages](https://img.shields.io/badge/GitHub%20Pages--brightgreen.svg?logo=github&style=social)](https://matsuda0528.github.io/ravensat/) -->
8
6
 
9
- Ravensat is an interface to SAT solver in Ruby.
7
+ # Ravensat
10
8
 
9
+ Ravensat provides an intuitive interface for working with SAT solver.
10
+ SAT solver is a useful tool for solving various problems, but it is not user-friendly.
11
+ Ravensat wraps the SAT solver and makes it easier to use.
11
12
  In order to use Ravensat, you need to install SAT solver.
12
13
  If you do not install SAT solver, it will use the one bundled in the gem.
13
14
 
14
15
  About [SAT](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem), [SAT solver](https://en.wikipedia.org/wiki/SAT_solver)
15
16
 
16
17
  ## Description
17
- To solve SAT, we usually use SAT solver.
18
+ To solve SAT(Boolean Satisfiability Problem), we usually use SAT solver.
18
19
  Now, let's solve the following SAT with SAT solver.
19
20
 
20
21
  $$(p_{1} \lor \lnot p_{5} \lor p_{4}) \land (\lnot p_{1} \lor p_{5} \lor p_{3} \lor p_{4}) \land (\lnot p_{3} \lor \lnot p_{4})$$
21
22
 
23
+ To solve the above SAT, give it to the SAT solver.
22
24
  Most SAT solvers are input in [DIMACS Format](https://www.cs.utexas.edu/users/moore/acl2/manuals/current/manual/index-seo.php/SATLINK____DIMACS).
23
25
  Converting the example SAT to DIMACS Format yields the following.
24
26
 
@@ -34,22 +36,31 @@ However, when solving a large SAT, the following problems occur.
34
36
  - Need to create a file with thousands of lines.
35
37
  - Confusion arises because of the inability to name variables meaningfully.
36
38
 
37
- To solve these problems, Ravensat can be used.
39
+ Therefore, we need an interface that can flexibly determine the names of variables and imperatively write loginal expressions.
40
+ To achieve these requirements, we are developing Ravensat.
38
41
  Using Ravensat, propositional variables can be defined as local variables in Ruby.
39
42
 
40
43
  ```ruby
41
- fuji_is_the_highest_mountain_in_japan = Ravensat::VarNode.new
44
+ John_is_a_male = Ravensat::VarNode.new
42
45
  ```
43
46
 
44
- In addition, you can write logical expressions intuitively.
47
+ In addition, you can write logical expressions intuitively and imperatively.
45
48
 
46
49
  ```ruby
47
50
  x = Ravensat::VarNode.new
48
51
  y = Ravensat::VarNode.new
49
52
 
50
- (x | y) & (~x | y) # (x or y) and (not x or y)
53
+ (x | y) & (~x | y)
51
54
  ```
52
55
 
56
+ ```ruby
57
+ x = Ravensat::VarNode.new
58
+ y = Ravensat::VarNode.new
59
+ z = Ravensat::VarNode.new
60
+
61
+ # (~x | ~y) & (~x | ~z) & (~y | ~z)
62
+ Ravensat::Claw.pairwise_amo [x,y,z]
63
+ ```
53
64
 
54
65
  ## Installation
55
66
 
@@ -102,7 +113,7 @@ At least, we have confirmed that it works properly with [MiniSat](https://github
102
113
  If you do not use an external SAT solver, create a SAT solver object without any constructor arguments.
103
114
  In that case, **Arcteryx**(the very simple SAT solver built into Ravensat) will launch.
104
115
 
105
- ### Extension Usage
116
+ ### Extension Usage(prototype)
106
117
  In Ravensat::Extension, C-like variable definitions are available.
107
118
 
108
119
  *Note: In Ravensat::Extension, all undefined variables and methods are caught by method_missing method.*
@@ -124,7 +135,6 @@ module Ravensat
124
135
  end
125
136
  ```
126
137
 
127
- ### Extension Usage(CSP; Constraint Satisfaction Problem)
128
138
  It is possible to define integer variables and to describe some integer constraints.
129
139
 
130
140
  ```ruby
@@ -7,39 +7,14 @@ module Ravensat
7
7
  @children = []
8
8
  end
9
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
18
- # case self
19
- # when AndNode, OrNode
20
- # @children.first.each{|c| yield(c)}
21
- # yield(self)
22
- # @children.last.each{|c| yield(c)}
23
- # when NotNode
24
- # yield(self)
25
- # @children.first.each{|c| yield(c)}
26
- # when VarNode
27
- # yield(self)
28
- # end
29
- # end
30
-
31
- def each_DP
10
+ def each_by_descriptive
32
11
  node_stack = [[self, self.children.clone]] #[[parent, children], ...]
33
12
 
34
13
  until node_stack.empty?
35
14
  current_parent, current_children = node_stack.pop
36
15
  current_node = current_children.shift
37
16
 
38
- # puts 'loop'
39
- # puts "node_stack.size:#{node_stack.size}"
40
- # puts "current_parent:#{current_parent.class}"
41
- # puts "current_children.size:#{current_children.size}"
42
- # puts "current_node:#{current_node.class}"
17
+ and_node_obj = AndNode.new
43
18
 
44
19
  case current_node
45
20
  when AndNode
@@ -53,7 +28,7 @@ module Ravensat
53
28
  yield(current_node.children.first)
54
29
 
55
30
  if current_children.empty?
56
- yield(node_stack.last.first)
31
+ yield(and_node_obj)
57
32
  else
58
33
  yield(current_parent)
59
34
  node_stack.push [current_parent, current_children.clone]
@@ -62,13 +37,12 @@ module Ravensat
62
37
  yield(current_node)
63
38
 
64
39
  if current_children.empty?
65
- yield(node_stack.last.first)
40
+ yield(and_node_obj)
66
41
  else
67
42
  yield(current_parent)
68
43
  node_stack.push [current_parent, current_children.clone]
69
44
  end
70
45
  end
71
-
72
46
  end
73
47
  end
74
48
 
@@ -88,13 +62,6 @@ module Ravensat
88
62
  self if block_given?
89
63
  end
90
64
 
91
- def each_naive
92
- yield(self)
93
- @children.each do |child|
94
- child.each {|c| yield(c)}
95
- end
96
- end
97
-
98
65
  def &(object)
99
66
  AndNode.new(self, object)
100
67
  end
@@ -123,7 +90,12 @@ module Ravensat
123
90
  end
124
91
 
125
92
  def clauses_size
126
- self.count{|node| node.is_a? AndNode} + 1
93
+ cnt = 0
94
+ self.each_by_descriptive do |node|
95
+ cnt+=1 if node.is_a? AndNode
96
+ end
97
+ cnt
98
+ # self.count{|node| node.is_a? AndNode} + 1
127
99
  end
128
100
  end
129
101
  end
data/lib/ravensat/claw.rb CHANGED
@@ -10,6 +10,7 @@ module Ravensat
10
10
  end.reduce(:&)
11
11
  end
12
12
 
13
+ # NOTE: Klieber, W. and Kwon, G.: Efficient CNF Encoding for Selecting 1 from N Objects (2007).
13
14
  def self.commander_amo(bool_vars)
14
15
  m = bool_vars.size / 2
15
16
  commander_variables = []
@@ -1,22 +1,13 @@
1
1
  module Ravensat
2
2
  class DimacsDecoder
3
3
  def decode(model, cnf)
4
- # inverted_name_table = name_table.invert
5
4
  prop_vars = cnf.vars
6
5
  case model.first
7
6
  when "SAT"
8
- model.last.split.each do |e|
9
- if e == '0'
10
- next
11
- elsif e[0] == "-"
12
- dimacs_name = e.slice(1..-1)
13
- var = prop_vars.find{|i| i.dimacs_name == dimacs_name}
14
- var.value = false
15
- else
16
- dimacs_name = e
17
- var = prop_vars.find{|i| i.dimacs_name == dimacs_name}
18
- var.value = true
19
- end
7
+ model.last.split.each_with_index do |e,i|
8
+ break if e == '0'
9
+ var = prop_vars[i]
10
+ var.value = !(e[0] == '-')
20
11
  end
21
12
  true
22
13
  when "UNSAT"
@@ -12,7 +12,7 @@ module Ravensat
12
12
 
13
13
  set_dimacs_name(formula)
14
14
 
15
- formula.each_DP do |node|
15
+ formula.each_by_descriptive do |node|
16
16
  dimacs_body << node.to_dimacs
17
17
  end
18
18
 
@@ -1,4 +1,5 @@
1
1
  require 'tempfile'
2
+ require 'open3'
2
3
 
3
4
  module Ravensat
4
5
  class Solver
@@ -7,7 +8,7 @@ module Ravensat
7
8
  @name = default_solver_name
8
9
  end
9
10
 
10
- def solve( cnf )
11
+ def solve( cnf , solver_log: false)
11
12
  encoder = DimacsEncoder.new
12
13
  @input_file = Tempfile.open(["ravensat",".cnf"])
13
14
  @output_file = Tempfile.open(["ravensat",".mdl"])
@@ -19,7 +20,8 @@ module Ravensat
19
20
  when "arcteryx"
20
21
  Arcteryx.solve(@input_file.to_path, @output_file.to_path)
21
22
  else
22
- system("#{@name} #{@input_file.to_path} #{@output_file.to_path}")
23
+ result, err, status = Open3.capture3("#{@name} #{@input_file.to_path} #{@output_file.to_path}")
24
+ puts result if solver_log
23
25
  end
24
26
 
25
27
  decoder = DimacsDecoder.new
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ravensat
4
- VERSION = "1.0.0"
4
+ VERSION = "1.0.3"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ravensat
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.3
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-07-11 00:00:00.000000000 Z
11
+ date: 2022-08-18 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -23,7 +23,6 @@ files:
23
23
  - ".rspec"
24
24
  - ".ruby-version"
25
25
  - Gemfile
26
- - Gemfile.lock
27
26
  - LICENSE.txt
28
27
  - README.md
29
28
  - Rakefile
data/Gemfile.lock DELETED
@@ -1,45 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- ravensat (0.1.1)
5
-
6
- GEM
7
- remote: https://rubygems.org/
8
- specs:
9
- byebug (11.1.3)
10
- coderay (1.1.3)
11
- diff-lcs (1.4.4)
12
- method_source (1.0.0)
13
- pry (0.14.0)
14
- coderay (~> 1.1)
15
- method_source (~> 1.0)
16
- pry-byebug (3.8.0)
17
- byebug (~> 11.0)
18
- pry (~> 0.10)
19
- rake (13.0.3)
20
- rspec (3.10.0)
21
- rspec-core (~> 3.10.0)
22
- rspec-expectations (~> 3.10.0)
23
- rspec-mocks (~> 3.10.0)
24
- rspec-core (3.10.1)
25
- rspec-support (~> 3.10.0)
26
- rspec-expectations (3.10.1)
27
- diff-lcs (>= 1.2.0, < 2.0)
28
- rspec-support (~> 3.10.0)
29
- rspec-mocks (3.10.2)
30
- diff-lcs (>= 1.2.0, < 2.0)
31
- rspec-support (~> 3.10.0)
32
- rspec-support (3.10.2)
33
-
34
- PLATFORMS
35
- x86_64-linux
36
-
37
- DEPENDENCIES
38
- pry
39
- pry-byebug
40
- rake (~> 13.0)
41
- ravensat!
42
- rspec (~> 3.0)
43
-
44
- BUNDLED WITH
45
- 2.2.24