ravensat 0.2.1 → 0.3.1
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/.github/workflows/main.yml +18 -0
- data/README.md +108 -8
- data/exe/ravensat +7 -0
- data/lib/ravensat/ast/initial_node.rb +11 -0
- data/lib/ravensat/ast/node.rb +14 -6
- data/lib/ravensat/ast/var_node.rb +4 -0
- data/lib/ravensat/ast.rb +11 -0
- data/lib/ravensat/{dimacs_decoder.rb → dimacs/dimacs_decoder.rb} +0 -0
- data/lib/ravensat/{dimacs_encoder.rb → dimacs/dimacs_encoder.rb} +6 -7
- data/lib/ravensat/dimacs.rb +6 -0
- data/lib/ravensat/extension/domain.rb +24 -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 +0 -7
- data/lib/ravensat/version.rb +1 -1
- data/lib/ravensat.rb +4 -9
- metadata +17 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 47afc062227efddad35ed4643e28c4eea8957ecb32c8aa34d3c69a9ff52d3a88
|
4
|
+
data.tar.gz: a39c4f15fb17321ded803e79b702c55150197b3a613a340ca4a728e0a6a27402
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f29375d0971be0c3a721e9932fec0b69ad9db5b6df089e9d07fad557a82fac176faf7b71eea0ca73b8ee76ba60b413bfc799fd2de798c0b0fc513e39c8c0388d
|
7
|
+
data.tar.gz: a596fa29bfb55341a016ddde64b2e7d788a4877d4504cd5921cee81e486ee28207fd14027c81c0e113c8485edd0cc9bd5921beac75728da85e3390c1eab4d23f
|
@@ -0,0 +1,18 @@
|
|
1
|
+
name: Ruby
|
2
|
+
|
3
|
+
on: [push,pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
steps:
|
9
|
+
- uses: actions/checkout@v2
|
10
|
+
- name: Set up Ruby
|
11
|
+
uses: ruby/setup-ruby@v1
|
12
|
+
with:
|
13
|
+
ruby-version: 3.0.0
|
14
|
+
- name: Run the default task
|
15
|
+
run: |
|
16
|
+
gem install bundler -v 2.2.3
|
17
|
+
bundle install
|
18
|
+
bundle exec rake
|
data/README.md
CHANGED
@@ -1,8 +1,50 @@
|
|
1
1
|
# Ravensat
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
(
|
3
|
+
[](https://github.com/matsuda0528/ravensat/actions/workflows/main.yml)
|
4
|
+
[](https://badge.fury.io/rb/ravensat)
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
6
|
+
|
7
|
+
Ravensat is an interface to SAT solver in Ruby.
|
8
|
+
|
9
|
+
In order to use Ravensat, you need to install SAT solver.
|
10
|
+
If you do not install SAT solver, it will use the one bundled in the gem.
|
11
|
+
|
12
|
+
About [SAT](https://en.wikipedia.org/wiki/Boolean_satisfiability_problem), [SAT solver](https://en.wikipedia.org/wiki/SAT_solver)
|
13
|
+
|
14
|
+
## Description
|
15
|
+
To solve SAT, we usually use SAT solver.
|
16
|
+
Now, let's solve the following SAT with SAT solver.
|
17
|
+
<p align="center">
|
18
|
+
<img src="https://latex.codecogs.com/svg.image?\inline&space;\large&space;\bg{white}(1&space;\lor&space;\lnot&space;5&space;\lor&space;4)&space;\land&space;(\lnot&space;1&space;\lor&space;5&space;\lor&space;3&space;\lor&space;4)&space;\land&space;(\lnot&space;3&space;\lor&space;\lnot&space;4)" style="background-color:white;"/>
|
19
|
+
</p>
|
20
|
+
|
21
|
+
Most SAT solvers are input in [DIMACS Format](https://www.cs.utexas.edu/users/moore/acl2/manuals/current/manual/index-seo.php/SATLINK____DIMACS).
|
22
|
+
Converting the example SAT to DIMACS Format yields the following.
|
23
|
+
|
24
|
+
```DIMACS Format
|
25
|
+
p cnf 5 3
|
26
|
+
1 -5 4 0
|
27
|
+
-1 5 3 4 0
|
28
|
+
-3 -4 0
|
29
|
+
```
|
30
|
+
DIMACS Format is widely distributed as an I/O format for SAT solver.
|
31
|
+
However, when solving a large SAT, the following problems occur.
|
32
|
+
- Need to create a file with thousands of lines.
|
33
|
+
- Confusion arises because of the inability to name variables meaningfully.
|
34
|
+
|
35
|
+
To solve these problems, Ravensat can be used.
|
36
|
+
Using Ravensat, propositional variables can be defined as local variables in Ruby.
|
37
|
+
```ruby
|
38
|
+
fuji_is_the_highest_mountain_in_japan = Ravensat::VarNode.new
|
39
|
+
```
|
40
|
+
In addition, you can write logical expressions intuitively.
|
41
|
+
```ruby
|
42
|
+
x = Ravensat::VarNode.new
|
43
|
+
y = Ravensat::VarNode.new
|
44
|
+
|
45
|
+
# (x or y) and (not x or y)
|
46
|
+
(x | y) & (~x | y)
|
47
|
+
```
|
6
48
|
|
7
49
|
|
8
50
|
## Installation
|
@@ -22,23 +64,81 @@ Or install it yourself as:
|
|
22
64
|
$ gem install ravensat
|
23
65
|
|
24
66
|
## Usage
|
25
|
-
|
67
|
+
### Basic Usage
|
68
|
+
This is a basic usage example of the library.
|
26
69
|
```ruby
|
27
70
|
require 'ravensat'
|
28
71
|
|
72
|
+
# Define propositional variables
|
29
73
|
a = Ravensat::VarNode.new
|
30
74
|
b = Ravensat::VarNode.new
|
31
75
|
|
32
|
-
a.
|
33
|
-
b.
|
76
|
+
a.result #=> nil
|
77
|
+
b.result #=> nil
|
34
78
|
|
79
|
+
# Generate logical expressions as CNF
|
35
80
|
logic = (a | b) & (~a | b) & (a | ~b)
|
36
81
|
|
82
|
+
# Launch SAT solver
|
37
83
|
solver = Ravensat::Solver.new
|
38
84
|
solver.solve logic #=> true(SAT)
|
39
85
|
|
40
|
-
|
41
|
-
|
86
|
+
# Refer to the satisfiability
|
87
|
+
a.result #=> true
|
88
|
+
b.result #=> true
|
89
|
+
```
|
90
|
+
|
91
|
+
If you have SAT solver installed, you can write:
|
92
|
+
```ruby
|
93
|
+
# Launch SAT solver
|
94
|
+
solver = Ravensat::Solver.new("<solver_name>")
|
95
|
+
solver.solve logic
|
96
|
+
```
|
97
|
+
The available solvers are assumed to be those that can be I/O in the DIMACS Format.
|
98
|
+
At least, we have confirmed that it works properly with [MiniSat](https://github.com/niklasso/minisat).
|
99
|
+
|
100
|
+
If you do not use an external SAT solver, create a SAT solver object without any constructor arguments.
|
101
|
+
In that case, **Arcteryx**(the very simple SAT solver built into Ravensat) will launch.
|
102
|
+
|
103
|
+
### Extension Usage
|
104
|
+
In Ravensat::Extension, C-like variable definitions are available.
|
105
|
+
|
106
|
+
*Note: In Ravensat::Extension, all undefined variables and methods are caught by method_missing method.*
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
require 'ravensat'
|
110
|
+
|
111
|
+
module Ravensat
|
112
|
+
module Extension
|
113
|
+
bool a, b
|
114
|
+
logic = (a | b) & (~a | b) & (a | ~b)
|
115
|
+
|
116
|
+
solver = Ravensat::Solver.new
|
117
|
+
solver.solve logic #=> true
|
118
|
+
|
119
|
+
a.result #=> true
|
120
|
+
b.result #=> true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
```
|
124
|
+
|
125
|
+
### Extension Usage(CSP; Constraint Satisfaction Problem)
|
126
|
+
It is possible to define integer variables and to describe some integer constraints.
|
127
|
+
```ruby
|
128
|
+
require 'ravensat'
|
129
|
+
|
130
|
+
module Ravensat
|
131
|
+
module Extension
|
132
|
+
int a(1..10), b(1..10)
|
133
|
+
constraint = (a.only_one & b.only_one & (a != b))
|
134
|
+
|
135
|
+
solver = Ravensat::Solver.new
|
136
|
+
solver.solve constraint #=> true
|
137
|
+
|
138
|
+
a.result #=> 1
|
139
|
+
b.result #=> 2
|
140
|
+
end
|
141
|
+
end
|
42
142
|
```
|
43
143
|
|
44
144
|
## Development
|
data/exe/ravensat
ADDED
data/lib/ravensat/ast/node.rb
CHANGED
@@ -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
|
@@ -22,12 +36,6 @@ module Ravensat
|
|
22
36
|
OrNode.new(self, object)
|
23
37
|
end
|
24
38
|
|
25
|
-
# def tree_text
|
26
|
-
# self.each do |child|
|
27
|
-
# child.to_s
|
28
|
-
# end
|
29
|
-
# end
|
30
|
-
|
31
39
|
def to_s
|
32
40
|
self.class.name
|
33
41
|
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
|
File without changes
|
@@ -8,19 +8,18 @@ module Ravensat
|
|
8
8
|
def to_dimacs(formula)
|
9
9
|
return nil unless formula.cnf?
|
10
10
|
|
11
|
-
dimacs_header = "p cnf #{formula.vars_size} #{formula.clauses_size}"
|
11
|
+
dimacs_header = "p cnf #{formula.vars_size} #{formula.clauses_size}\n"
|
12
12
|
dimacs_body = ""
|
13
13
|
create_table(formula)
|
14
|
-
formula.
|
14
|
+
formula.each_with_clause do |node|
|
15
15
|
case node
|
16
|
-
when AndNode
|
17
|
-
when OrNode then dimacs_body << "
|
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.gsub!(/\n{2,}/, "\n").gsub!(/\n/, "0\n") << '0'
|
22
|
+
dimacs_body << " 0\n"
|
24
23
|
|
25
24
|
dimacs_header + dimacs_body
|
26
25
|
end
|
@@ -0,0 +1,24 @@
|
|
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::Extension::BooleanVariable.new(var.name, var.args)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(name, *args)
|
20
|
+
LOCAL_VARIABLE_TABLE[name] || UndefinedVariable.new(name, args)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
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
@@ -5,15 +5,8 @@ module Ravensat
|
|
5
5
|
attr_accessor :name
|
6
6
|
def initialize( default_solver_name = "arcteryx" )
|
7
7
|
@name = default_solver_name
|
8
|
-
# @cnf = Array.new
|
9
|
-
# @nr_vars
|
10
|
-
# @nr_clses
|
11
8
|
end
|
12
9
|
|
13
|
-
# def <<( clause )
|
14
|
-
# 'this is << method'
|
15
|
-
# end
|
16
|
-
|
17
10
|
def solve( cnf )
|
18
11
|
encoder = DimacsEncoder.new
|
19
12
|
@input_file = Tempfile.open(["ravensat",".cnf"])
|
data/lib/ravensat/version.rb
CHANGED
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,22 +1,24 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ravensat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
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-
|
11
|
+
date: 2022-05-24 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:
|
21
|
+
- ".github/workflows/main.yml"
|
20
22
|
- ".gitignore"
|
21
23
|
- ".rspec"
|
22
24
|
- ".ruby-version"
|
@@ -28,17 +30,27 @@ files:
|
|
28
30
|
- bin/console
|
29
31
|
- bin/setup
|
30
32
|
- example/magic_square_3x3.rb
|
33
|
+
- exe/ravensat
|
31
34
|
- lib/arcteryx/arcteryx.rb
|
32
35
|
- lib/arcteryx/cnf.rb
|
33
36
|
- lib/ravensat.rb
|
37
|
+
- lib/ravensat/ast.rb
|
34
38
|
- lib/ravensat/ast/and_node.rb
|
39
|
+
- lib/ravensat/ast/initial_node.rb
|
35
40
|
- lib/ravensat/ast/node.rb
|
36
41
|
- lib/ravensat/ast/not_node.rb
|
37
42
|
- lib/ravensat/ast/opr_node.rb
|
38
43
|
- lib/ravensat/ast/or_node.rb
|
39
44
|
- lib/ravensat/ast/var_node.rb
|
40
|
-
- lib/ravensat/
|
41
|
-
- lib/ravensat/
|
45
|
+
- lib/ravensat/dimacs.rb
|
46
|
+
- lib/ravensat/dimacs/dimacs_decoder.rb
|
47
|
+
- lib/ravensat/dimacs/dimacs_encoder.rb
|
48
|
+
- lib/ravensat/extension.rb
|
49
|
+
- lib/ravensat/extension/domain.rb
|
50
|
+
- lib/ravensat/extension/variable/boolean_variable.rb
|
51
|
+
- lib/ravensat/extension/variable/integer_variable.rb
|
52
|
+
- lib/ravensat/extension/variable/undefined_variable.rb
|
53
|
+
- lib/ravensat/extension/variable/variable.rb
|
42
54
|
- lib/ravensat/ravenclaw.rb
|
43
55
|
- lib/ravensat/solver.rb
|
44
56
|
- lib/ravensat/version.rb
|