or-tools 0.6.1 → 0.6.2

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