or-tools 0.6.1 → 0.6.2

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: '018061d137668676a2aca20c0ea0b1bbf01cfb19e02e0f7a532e9e4d800fb735'
4
- data.tar.gz: 05e1f19947935d6ccf13c551cbf24cccd4fe3aa989d9bbbb31612c15837eb837
3
+ metadata.gz: c0e0f455741da72e3a215287df4ef1858893fb31d0b4be40db6ef9ab025e339c
4
+ data.tar.gz: 9291933eee08f800f48f3d83ca4f2d0fc71efb0a328134ba9667ca2ac8efb185
5
5
  SHA512:
6
- metadata.gz: 4c32d4c6171f9c67011c4be7ec730583b1ea81cff00ab4ef865185b42fc5b0b7f843305e8bad31bcf22ad054fc0f7813e4d2ef84d0416bf42612c91800df699d
7
- data.tar.gz: e13cb7b42a02d010f733e7f1b12d36fc79abf1718c3a8064b5d2d97d63b93f6e80c73f54743d6a290856d014c5f6a1141328e671c78fc9679a543fcc178ee2d5
6
+ metadata.gz: 61ccc7c5f3a6c3cdf1e3dffb1ee6572d0b8cde09d4684d50353efd6f2efcb93ca4ba940343f994a3bf65992e518331bd62a02ef74ecc52f2427e12350ea7a430
7
+ data.tar.gz: 589423f5b52c872b453569400ff1fd60bb1fcd3b0035e70aadbb47eedefec9b7f4187a5442893e50608529f836d2009bd77333aae3f64ce1b9d700df6fe020e7
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.6.2 (2022-02-09)
2
+
3
+ - Fixed segfaults with `Solver`
4
+
1
5
  ## 0.6.1 (2022-01-22)
2
6
 
3
7
  - Added installation instructions for Mac ARM
data/NOTICE.txt CHANGED
@@ -1,5 +1,5 @@
1
- Copyright 2010-2018 Google LLC
2
- Copyright 2020-2021 Andrew Kane
1
+ Copyright 2010-2021 Google LLC
2
+ Copyright 2020-2022 Andrew Kane
3
3
 
4
4
  Licensed under the Apache License, Version 2.0 (the "License");
5
5
  you may not use this file except in compliance with the License.
data/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  Add this line to your application’s Gemfile:
10
10
 
11
11
  ```ruby
12
- gem 'or-tools'
12
+ gem "or-tools"
13
13
  ```
14
14
 
15
15
  Installation can take a few minutes as OR-Tools downloads and builds. For Mac ARM, also follow [these instructions](#additional-instructions).
@@ -46,86 +46,14 @@ namespace Rice::detail
46
46
 
47
47
  void init_linear(Rice::Module& m) {
48
48
  Rice::define_class_under<LinearRange>(m, "LinearRange");
49
+
50
+ // TODO remove in 0.7.0
49
51
  auto rb_cLinearExpr = Rice::define_class_under<LinearExpr>(m, "LinearExpr");
52
+ rb_cLinearExpr.define_constructor(Rice::Constructor<LinearExpr>());
50
53
 
51
- Rice::define_class_under<MPVariable>(m, "MPVariable")
54
+ Rice::define_class_under<MPVariable, LinearExpr>(m, "MPVariable")
52
55
  .define_method("name", &MPVariable::name)
53
- .define_method("solution_value", &MPVariable::solution_value)
54
- .define_method(
55
- "+",
56
- [](MPVariable& self, LinearExpr& other) {
57
- LinearExpr s(&self);
58
- return s + other;
59
- })
60
- .define_method(
61
- "-",
62
- [](MPVariable& self, LinearExpr& other) {
63
- LinearExpr s(&self);
64
- return s - other;
65
- })
66
- .define_method(
67
- "*",
68
- [](MPVariable& self, double other) {
69
- LinearExpr s(&self);
70
- return s * other;
71
- })
72
- .define_method(
73
- "inspect",
74
- [](MPVariable& self) {
75
- return "#<ORTools::MPVariable @name=\"" + self.name() + "\">";
76
- });
77
-
78
- rb_cLinearExpr
79
- .define_constructor(Rice::Constructor<LinearExpr>())
80
- .define_method(
81
- "_add_linear_expr",
82
- [](LinearExpr& self, LinearExpr& other) {
83
- return self + other;
84
- })
85
- .define_method(
86
- "_add_mp_variable",
87
- [](LinearExpr& self, MPVariable &other) {
88
- LinearExpr o(&other);
89
- return self + o;
90
- })
91
- .define_method(
92
- "_gte_double",
93
- [](LinearExpr& self, double other) {
94
- LinearExpr o(other);
95
- return self >= o;
96
- })
97
- .define_method(
98
- "_gte_linear_expr",
99
- [](LinearExpr& self, LinearExpr& other) {
100
- return self >= other;
101
- })
102
- .define_method(
103
- "_lte_double",
104
- [](LinearExpr& self, double other) {
105
- LinearExpr o(other);
106
- return self <= o;
107
- })
108
- .define_method(
109
- "_lte_linear_expr",
110
- [](LinearExpr& self, LinearExpr& other) {
111
- return self <= other;
112
- })
113
- .define_method(
114
- "==",
115
- [](LinearExpr& self, double other) {
116
- LinearExpr o(other);
117
- return self == o;
118
- })
119
- .define_method(
120
- "to_s",
121
- [](LinearExpr& self) {
122
- return self.ToString();
123
- })
124
- .define_method(
125
- "inspect",
126
- [](LinearExpr& self) {
127
- return "#<ORTools::LinearExpr \"" + self.ToString() + "\">";
128
- });
56
+ .define_method("solution_value", &MPVariable::solution_value);
129
57
 
130
58
  Rice::define_class_under<MPConstraint>(m, "MPConstraint")
131
59
  .define_method("set_coefficient", &MPConstraint::SetCoefficient);
@@ -133,7 +61,8 @@ void init_linear(Rice::Module& m) {
133
61
  Rice::define_class_under<MPObjective>(m, "MPObjective")
134
62
  .define_method("value", &MPObjective::Value)
135
63
  .define_method("set_coefficient", &MPObjective::SetCoefficient)
136
- .define_method("set_maximization", &MPObjective::SetMaximization);
64
+ .define_method("set_maximization", &MPObjective::SetMaximization)
65
+ .define_method("set_minimization", &MPObjective::SetMinimization);
137
66
 
138
67
  Rice::define_class_under<MPSolver>(m, "Solver")
139
68
  .define_constructor(Rice::Constructor<MPSolver, std::string, MPSolver::OptimizationProblemType>())
@@ -155,21 +84,6 @@ void init_linear(Rice::Module& m) {
155
84
  .define_method("iterations", &MPSolver::iterations)
156
85
  .define_method("nodes", &MPSolver::nodes)
157
86
  .define_method("objective", &MPSolver::MutableObjective)
158
- .define_method(
159
- "maximize",
160
- [](MPSolver& self, LinearExpr& expr) {
161
- return self.MutableObjective()->MaximizeLinearExpr(expr);
162
- })
163
- .define_method(
164
- "minimize",
165
- [](MPSolver& self, LinearExpr& expr) {
166
- return self.MutableObjective()->MinimizeLinearExpr(expr);
167
- })
168
- .define_method(
169
- "add",
170
- [](MPSolver& self, const LinearRange& range) {
171
- return self.MakeRowConstraint(range);
172
- })
173
87
  .define_method(
174
88
  "constraint",
175
89
  [](MPSolver& self, double lb, double ub) {
data/lib/or-tools.rb CHANGED
@@ -5,17 +5,22 @@ require "or_tools/ext"
5
5
  require "or_tools/comparison"
6
6
  require "or_tools/comparison_operators"
7
7
  require "or_tools/bool_var"
8
+ require "or_tools/constant"
8
9
  require "or_tools/cp_model"
9
10
  require "or_tools/cp_solver"
10
11
  require "or_tools/cp_solver_solution_callback"
11
12
  require "or_tools/int_var"
12
13
  require "or_tools/knapsack_solver"
14
+ require "or_tools/linear_constraint"
13
15
  require "or_tools/linear_expr"
16
+ require "or_tools/mp_variable"
17
+ require "or_tools/product_cst"
14
18
  require "or_tools/routing_index_manager"
15
19
  require "or_tools/routing_model"
16
20
  require "or_tools/sat_linear_expr"
17
21
  require "or_tools/sat_int_var"
18
22
  require "or_tools/solver"
23
+ require "or_tools/sum_array"
19
24
  require "or_tools/version"
20
25
 
21
26
  # solution printers
@@ -8,8 +8,13 @@ module ORTools
8
8
  @right = right
9
9
  end
10
10
 
11
- def inspect
11
+ def to_s
12
12
  "#{left.inspect} #{operator} #{right.inspect}"
13
13
  end
14
+
15
+ # TODO add class
16
+ def inspect
17
+ to_s
18
+ end
14
19
  end
15
20
  end
@@ -0,0 +1,23 @@
1
+ module ORTools
2
+ class Constant < LinearExpr
3
+ def initialize(val)
4
+ @val = val
5
+ end
6
+
7
+ def to_s
8
+ @val.to_s
9
+ end
10
+
11
+ def add_self_to_coeff_map_or_stack(coeffs, multiplier, stack)
12
+ coeffs[OFFSET_KEY] += @val * multiplier
13
+ end
14
+ end
15
+
16
+ class FakeMPVariableRepresentingTheConstantOffset
17
+ def solution_value
18
+ 1
19
+ end
20
+ end
21
+
22
+ OFFSET_KEY = FakeMPVariableRepresentingTheConstantOffset.new
23
+ end
@@ -0,0 +1,50 @@
1
+ module ORTools
2
+ class LinearConstraint
3
+ attr_reader :expr, :lb, :ub
4
+
5
+ def initialize(expr, lb, ub)
6
+ @expr = expr
7
+ @lb = lb
8
+ @ub = ub
9
+ end
10
+
11
+ def to_s
12
+ if @lb > -Float::INFINITY && @ub < Float::INFINITY
13
+ if @lb == @ub
14
+ "#{@expr} == #{@lb}"
15
+ else
16
+ "#{@lb} <= #{@expr} <= #{@ub}"
17
+ end
18
+ elsif @lb > -Float::INFINITY
19
+ "#{@expr} >= #{@lb}"
20
+ elsif @ub < Float::INFINITY
21
+ "#{@expr} <= #{@ub}"
22
+ else
23
+ "Trivial inequality (always true)"
24
+ end
25
+ end
26
+
27
+ def inspect
28
+ "#<#{self.class.name} #{to_s}>"
29
+ end
30
+
31
+ def extract(solver)
32
+ coeffs = @expr.coeffs
33
+ constant = coeffs.delete(OFFSET_KEY) || 0.0
34
+ lb = -solver.infinity
35
+ ub = solver.infinity
36
+ if @lb > -Float::INFINITY
37
+ lb = @lb - constant
38
+ end
39
+ if @ub < Float::INFINITY
40
+ ub = @ub - constant
41
+ end
42
+
43
+ constraint = solver.constraint(lb, ub)
44
+ coeffs.each do |v, c|
45
+ constraint.set_coefficient(v, c.to_f)
46
+ end
47
+ constraint
48
+ end
49
+ end
50
+ end
@@ -1,27 +1,73 @@
1
1
  module ORTools
2
2
  class LinearExpr
3
- def +(other)
4
- if other.is_a?(LinearExpr)
5
- _add_linear_expr(other)
3
+ def solution_value
4
+ coeffs.sum { |var, coeff| var.solution_value * coeff }
5
+ end
6
+
7
+ def coeffs
8
+ coeffs = Hash.new(0.0)
9
+ stack = [[1.0, self]]
10
+ while stack.any?
11
+ current_multiplier, current_expression = stack.pop
12
+
13
+ # skip empty LinearExpr for backwards compatibility
14
+ next if current_expression.instance_of?(LinearExpr)
15
+
16
+ current_expression.add_self_to_coeff_map_or_stack(coeffs, current_multiplier, stack)
17
+ end
18
+ coeffs
19
+ end
20
+
21
+ def +(expr)
22
+ SumArray.new([self, expr])
23
+ end
24
+
25
+ def -(expr)
26
+ SumArray.new([self, -expr])
27
+ end
28
+
29
+ def *(other)
30
+ ProductCst.new(self, other)
31
+ end
32
+
33
+ def /(cst)
34
+ ProductCst.new(self, 1.0 / other)
35
+ end
36
+
37
+ def -@
38
+ ProductCst.new(self, -1)
39
+ end
40
+
41
+ def ==(arg)
42
+ if arg.is_a?(Numeric)
43
+ LinearConstraint.new(self, arg, arg)
6
44
  else
7
- _add_mp_variable(other)
45
+ LinearConstraint.new(self - arg, 0.0, 0.0)
8
46
  end
9
47
  end
10
48
 
11
- def >=(other)
12
- if other.is_a?(LinearExpr)
13
- _gte_linear_expr(other)
49
+ def >=(arg)
50
+ if arg.is_a?(Numeric)
51
+ LinearConstraint.new(self, arg, Float::INFINITY)
14
52
  else
15
- _gte_double(other)
53
+ LinearConstraint.new(self - arg, 0.0, Float::INFINITY)
16
54
  end
17
55
  end
18
56
 
19
- def <=(other)
20
- if other.is_a?(LinearExpr)
21
- _lte_linear_expr(other)
57
+ def <=(arg)
58
+ if arg.is_a?(Numeric)
59
+ LinearConstraint.new(self, -Float::INFINITY, arg)
22
60
  else
23
- _lte_double(other)
61
+ LinearConstraint.new(self - arg, -Float::INFINITY, 0.0)
24
62
  end
25
63
  end
64
+
65
+ def to_s
66
+ "(empty)"
67
+ end
68
+
69
+ def inspect
70
+ "#<#{self.class.name} #{to_s}>"
71
+ end
26
72
  end
27
73
  end
@@ -0,0 +1,12 @@
1
+ module ORTools
2
+ # TODO change to VariableExpr in 0.7.0
3
+ class MPVariable < LinearExpr
4
+ def add_self_to_coeff_map_or_stack(coeffs, multiplier, stack)
5
+ coeffs[self] += multiplier
6
+ end
7
+
8
+ def to_s
9
+ name
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,31 @@
1
+ module ORTools
2
+ class ProductCst < LinearExpr
3
+ attr_reader :expr, :coef
4
+
5
+ def initialize(expr, coef)
6
+ @expr = cast_to_lin_exp(expr)
7
+ # TODO improve message
8
+ raise TypeError, "expected numeric" unless coef.is_a?(Numeric)
9
+ @coef = coef
10
+ end
11
+
12
+ def to_s
13
+ if @coef == -1
14
+ "-#{@expr}"
15
+ else
16
+ "(#{@coef} * #{@expr})"
17
+ end
18
+ end
19
+
20
+ def add_self_to_coeff_map_or_stack(coeffs, multiplier, stack)
21
+ current_multiplier = multiplier * @coef
22
+ if current_multiplier
23
+ stack << [current_multiplier, @expr]
24
+ end
25
+ end
26
+
27
+ def cast_to_lin_exp(v)
28
+ v.is_a?(Numeric) ? Constant.new(v) : v
29
+ end
30
+ end
31
+ end
@@ -18,9 +18,13 @@ module ORTools
18
18
  SatLinearExpr.new([[self, -1]])
19
19
  end
20
20
 
21
- # for now
22
- def inspect
21
+ def to_s
23
22
  name
24
23
  end
24
+
25
+ # TODO add class
26
+ def inspect
27
+ to_s
28
+ end
25
29
  end
26
30
  end
@@ -24,7 +24,7 @@ module ORTools
24
24
  end
25
25
  end
26
26
 
27
- def inspect
27
+ def to_s
28
28
  vars.map do |v|
29
29
  k = v[0]
30
30
  k = k.respond_to?(:name) ? k.name : k.inspect
@@ -36,6 +36,11 @@ module ORTools
36
36
  end.join(" + ").sub(" + -", " - ")
37
37
  end
38
38
 
39
+ # TODO add class
40
+ def inspect
41
+ to_s
42
+ end
43
+
39
44
  private
40
45
 
41
46
  def add(other, sign)
@@ -1,7 +1,25 @@
1
1
  module ORTools
2
2
  class Solver
3
3
  def sum(arr)
4
- arr.sum(LinearExpr.new)
4
+ SumArray.new(arr)
5
+ end
6
+
7
+ def add(expr)
8
+ expr.extract(self)
9
+ end
10
+
11
+ def maximize(expr)
12
+ expr.coeffs.each do |v, c|
13
+ objective.set_coefficient(v, c)
14
+ end
15
+ objective.set_maximization
16
+ end
17
+
18
+ def minimize(expr)
19
+ expr.coeffs.each do |v, c|
20
+ objective.set_coefficient(v, c)
21
+ end
22
+ objective.set_minimization
5
23
  end
6
24
  end
7
25
  end
@@ -0,0 +1,23 @@
1
+ module ORTools
2
+ class SumArray < LinearExpr
3
+ attr_reader :array
4
+
5
+ def initialize(array)
6
+ @array = array.map { |v| cast_to_lin_exp(v) }
7
+ end
8
+
9
+ def add_self_to_coeff_map_or_stack(coeffs, multiplier, stack)
10
+ @array.reverse.each do |arg|
11
+ stack << [multiplier, arg]
12
+ end
13
+ end
14
+
15
+ def cast_to_lin_exp(v)
16
+ v.is_a?(Numeric) ? Constant.new(v) : v
17
+ end
18
+
19
+ def to_s
20
+ "(#{@array.map(&:to_s).join(" + ")})"
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module ORTools
2
- VERSION = "0.6.1"
2
+ VERSION = "0.6.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: or-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-22 00:00:00.000000000 Z
11
+ date: 2022-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rice
@@ -50,13 +50,17 @@ files:
50
50
  - lib/or_tools/bool_var.rb
51
51
  - lib/or_tools/comparison.rb
52
52
  - lib/or_tools/comparison_operators.rb
53
+ - lib/or_tools/constant.rb
53
54
  - lib/or_tools/cp_model.rb
54
55
  - lib/or_tools/cp_solver.rb
55
56
  - lib/or_tools/cp_solver_solution_callback.rb
56
57
  - lib/or_tools/int_var.rb
57
58
  - lib/or_tools/knapsack_solver.rb
59
+ - lib/or_tools/linear_constraint.rb
58
60
  - lib/or_tools/linear_expr.rb
61
+ - lib/or_tools/mp_variable.rb
59
62
  - lib/or_tools/objective_solution_printer.rb
63
+ - lib/or_tools/product_cst.rb
60
64
  - lib/or_tools/routing_index_manager.rb
61
65
  - lib/or_tools/routing_model.rb
62
66
  - lib/or_tools/sat_int_var.rb
@@ -64,6 +68,7 @@ files:
64
68
  - lib/or_tools/seating.rb
65
69
  - lib/or_tools/solver.rb
66
70
  - lib/or_tools/sudoku.rb
71
+ - lib/or_tools/sum_array.rb
67
72
  - lib/or_tools/tsp.rb
68
73
  - lib/or_tools/var_array_and_objective_solution_printer.rb
69
74
  - lib/or_tools/var_array_solution_printer.rb