or-tools 0.6.1 → 0.7.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: '018061d137668676a2aca20c0ea0b1bbf01cfb19e02e0f7a532e9e4d800fb735'
4
- data.tar.gz: 05e1f19947935d6ccf13c551cbf24cccd4fe3aa989d9bbbb31612c15837eb837
3
+ metadata.gz: 03544e925041f7337e6e6ba1b00b6d6c4d97353bcd7ee3785a46959a952bf09c
4
+ data.tar.gz: eddbab6814900afc7ddda651da92a53aa06b0db857659ab2ccd1c1adb9770fe0
5
5
  SHA512:
6
- metadata.gz: 4c32d4c6171f9c67011c4be7ec730583b1ea81cff00ab4ef865185b42fc5b0b7f843305e8bad31bcf22ad054fc0f7813e4d2ef84d0416bf42612c91800df699d
7
- data.tar.gz: e13cb7b42a02d010f733e7f1b12d36fc79abf1718c3a8064b5d2d97d63b93f6e80c73f54743d6a290856d014c5f6a1141328e671c78fc9679a543fcc178ee2d5
6
+ metadata.gz: '041939b99da310567a099f7654658697b93e36436abf06779336ca51e0d02be94473c0474d238041285975f293734cde65c37e5db565b8f30b49f856fe519100'
7
+ data.tar.gz: '09f6a2f0701acb005f356555df0d0e19befe36090d4de1b2188e7944a55836c80022eed5d4e185dc3b3b016c9c73fa3d5957e8c3cf8adf83bf4773b1090e5f0a'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## 0.7.0 (2022-03-23)
2
+
3
+ - Updated OR-Tools to 9.3
4
+ - Removed `add_lin_min_equality` (use `add_min_equality` instead)
5
+ - Removed `add_lin_max_equality` (use `add_max_equality` instead)
6
+ - Dropped support for Debian 10
7
+
8
+ ## 0.6.3 (2022-03-13)
9
+
10
+ - Reduced gem size
11
+
12
+ ## 0.6.2 (2022-02-09)
13
+
14
+ - Fixed segfaults with `Solver`
15
+
1
16
  ## 0.6.1 (2022-01-22)
2
17
 
3
18
  - 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).
@@ -57,11 +57,11 @@ namespace Rice::detail
57
57
  auto coeff = From_Ruby<int64_t>().convert(cvar[1].value());
58
58
 
59
59
  if (var.is_a(rb_cBoolVar)) {
60
- expr.AddTerm(From_Ruby<BoolVar>().convert(var.value()), coeff);
60
+ expr += From_Ruby<BoolVar>().convert(var.value()) * coeff;
61
61
  } else if (var.is_a(rb_cInteger)) {
62
- expr.AddConstant(From_Ruby<int64_t>().convert(var.value()) * coeff);
62
+ expr += From_Ruby<int64_t>().convert(var.value()) * coeff;
63
63
  } else {
64
- expr.AddTerm(From_Ruby<IntVar>().convert(var.value()), coeff);
64
+ expr += From_Ruby<IntVar>().convert(var.value()) * coeff;
65
65
  }
66
66
  }
67
67
  } else {
@@ -253,42 +253,32 @@ void init_constraint(Rice::Module& m) {
253
253
  })
254
254
  .define_method(
255
255
  "add_min_equality",
256
- [](CpModelBuilder& self, IntVar target, std::vector<IntVar> vars) {
256
+ [](CpModelBuilder& self, LinearExpr target, std::vector<LinearExpr> vars) {
257
257
  return self.AddMinEquality(target, vars);
258
258
  })
259
- .define_method(
260
- "add_lin_min_equality",
261
- [](CpModelBuilder& self, LinearExpr target, std::vector<LinearExpr> exprs) {
262
- return self.AddLinMinEquality(target, exprs);
263
- })
264
259
  .define_method(
265
260
  "add_max_equality",
266
- [](CpModelBuilder& self, IntVar target, std::vector<IntVar> vars) {
261
+ [](CpModelBuilder& self, LinearExpr target, std::vector<LinearExpr> vars) {
267
262
  return self.AddMaxEquality(target, vars);
268
263
  })
269
- .define_method(
270
- "add_lin_max_equality",
271
- [](CpModelBuilder& self, LinearExpr target, std::vector<LinearExpr> exprs) {
272
- return self.AddLinMaxEquality(target, exprs);
273
- })
274
264
  .define_method(
275
265
  "add_division_equality",
276
- [](CpModelBuilder& self, IntVar target, IntVar numerator, IntVar denominator) {
266
+ [](CpModelBuilder& self, LinearExpr target, LinearExpr numerator, LinearExpr denominator) {
277
267
  return self.AddDivisionEquality(target, numerator, denominator);
278
268
  })
279
269
  .define_method(
280
270
  "add_abs_equality",
281
- [](CpModelBuilder& self, IntVar target, IntVar var) {
271
+ [](CpModelBuilder& self, LinearExpr target, LinearExpr var) {
282
272
  return self.AddAbsEquality(target, var);
283
273
  })
284
274
  .define_method(
285
275
  "add_modulo_equality",
286
- [](CpModelBuilder& self, IntVar target, IntVar var, IntVar mod) {
276
+ [](CpModelBuilder& self, LinearExpr target, LinearExpr var, LinearExpr mod) {
287
277
  return self.AddModuloEquality(target, var, mod);
288
278
  })
289
279
  .define_method(
290
280
  "add_multiplication_equality",
291
- [](CpModelBuilder& self, IntVar target, std::vector<IntVar> vars) {
281
+ [](CpModelBuilder& self, LinearExpr target, std::vector<LinearExpr> vars) {
292
282
  return self.AddMultiplicationEquality(target, vars);
293
283
  })
294
284
  .define_method(
@@ -25,12 +25,7 @@ end
25
25
 
26
26
  $INCFLAGS << " -I#{inc}"
27
27
 
28
- $LDFLAGS << " -Wl,-rpath,#{rpath}"
29
- $LDFLAGS << " -L#{lib}"
28
+ $LDFLAGS.prepend("-Wl,-rpath,#{rpath} -L#{lib} ")
30
29
  raise "OR-Tools not found" unless have_library("ortools")
31
30
 
32
- Dir["#{lib}/libabsl_*.a"].each do |lib|
33
- $LDFLAGS << " #{lib}"
34
- end
35
-
36
31
  create_makefile("or_tools/ext")
@@ -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) {
@@ -4,7 +4,7 @@ require "fileutils"
4
4
  require "net/http"
5
5
  require "tmpdir"
6
6
 
7
- version = "9.2.9972"
7
+ version = "9.3.10497"
8
8
 
9
9
  if RbConfig::CONFIG["host_os"] =~ /darwin/i
10
10
  if RbConfig::CONFIG["host_cpu"] =~ /arm|aarch64/i
@@ -17,8 +17,8 @@ if RbConfig::CONFIG["host_os"] =~ /darwin/i
17
17
 
18
18
  MSG
19
19
  else
20
- filename = "or-tools_MacOsX-12.0.1_v#{version}.tar.gz"
21
- checksum = "796791a8ef84507d62e193e647cccb1c7725dae4f1474476e1777fe4a44ee3e0"
20
+ filename = "or-tools_MacOsX-12.2.1_v#{version}.tar.gz"
21
+ checksum = "33941702c59983897935eef06d91aca6c89ed9a8f5f4de3a9dfe489e97d7ca8c"
22
22
  end
23
23
  else
24
24
  # try /etc/os-release with fallback to /usr/lib/os-release
@@ -32,23 +32,21 @@ else
32
32
  os_version = os_info["VERSION_ID"]
33
33
 
34
34
  if os == "ubuntu" && os_version == "20.04"
35
- filename = "or-tools_amd64_ubuntu-20.04_v#{version}.tar.gz"
36
- checksum = "985e3036eaecacfc8a0258ec2ebef429240491577d4e0896d68fc076e65451ec"
35
+ # TODO remove sub in v9.4
36
+ filename = "or-tools_amd64_ubuntu-20.04_v#{version.sub(".10497", ".10502")}.tar.gz"
37
+ checksum = "3d1979967a2c9358b5bc956f2e6b608b00e89e13c71d48d075475ce4138b6d1c"
37
38
  elsif os == "ubuntu" && os_version == "18.04"
38
39
  filename = "or-tools_amd64_ubuntu-18.04_v#{version}.tar.gz"
39
- checksum = "e36406c4fe8c111e1ace0ede9d0787ff0e98f11afd7db9cc074adfd0f55628a6"
40
+ checksum = "6ba5cc153417267e8f8e15f8b6390b17f22de07bacc61f3740a4172ccd56c274"
40
41
  elsif os == "debian" && os_version == "11"
41
42
  filename = "or-tools_amd64_debian-11_v#{version}.tar.gz"
42
- checksum = "bd49ee916213b2140ab255414d35a28f19dff7caf87632309753d3fc553f85dd"
43
- elsif os == "debian" && os_version == "10"
44
- filename = "or-tools_amd64_debian-10_v#{version}.tar.gz"
45
- checksum = "b152fee584f0c8228fe2ff21b74c789870ff9b7064e42ca26305c6b5653f0064"
43
+ checksum = "db0636bab909eabf06a7004f7572dca6fa152f3823c1365b0b7428405bf250e6"
46
44
  elsif os == "centos" && os_version == "8"
47
45
  filename = "or-tools_amd64_centos-8_v#{version}.tar.gz"
48
- checksum = "66ed4bb800acf92c672f7e68acdf4ea27bbfdb17bbddc02f8326cd55a97305f6"
46
+ checksum = "e5649069fd7a3e8228cc18b91e265a90562c5d03a0c962b0346911aada0aedc9"
49
47
  elsif os == "centos" && os_version == "7"
50
48
  filename = "or-tools_amd64_centos-7_v#{version}.tar.gz"
51
- checksum = "4a5c1b1639a2828cd7e1ba82a574ef37876557b59e8aab8b81811bb750d53035"
49
+ checksum = "3bffdec8c09fc1345dcbd6a553437e2894014093fafb53e50adc7d4d776bb08b"
52
50
  else
53
51
  platform =
54
52
  if Gem.win_platform?
@@ -121,12 +119,37 @@ end
121
119
  download_checksum = Digest::SHA256.file(download_path).hexdigest
122
120
  raise "Bad checksum: #{download_checksum}" if download_checksum != checksum
123
121
 
124
- # extract - can't use Gem::Package#extract_tar_gz from RubyGems
125
- # since it limits filenames to 100 characters (doesn't support UStar format)
126
122
  path = File.expand_path("../../tmp/or-tools", __dir__)
127
123
  FileUtils.mkdir_p(path)
128
- tar_args = Gem.win_platform? ? ["--force-local"] : []
129
- system "tar", "zxf", download_path, "-C", path, "--strip-components=1", *tar_args
124
+
125
+ # extract - can't use Gem::Package#extract_tar_gz from RubyGems
126
+ # since it limits filenames to 100 characters (doesn't support UStar format)
127
+ # for space, only keep licenses, include, and shared library
128
+ Dir.mktmpdir do |extract_path|
129
+ tar_args = Gem.win_platform? ? ["--force-local"] : []
130
+ system "tar", "zxf", download_path, "-C", extract_path, "--strip-components=1", *tar_args
131
+
132
+ # licenses
133
+ license_files = Dir.glob("**/*{LICENSE,LICENCE,NOTICE,COPYING,license,licence,notice,copying}*", base: extract_path)
134
+ raise "License not found" unless license_files.any?
135
+ license_files.each do |file|
136
+ FileUtils.mkdir_p(File.join(path, File.dirname(file)))
137
+ FileUtils.cp(File.join(extract_path, file), File.join(path, file))
138
+ end
139
+
140
+ # include
141
+ FileUtils.cp_r(File.join(extract_path, "include"), File.join(path, "include"))
142
+
143
+ # shared library
144
+ FileUtils.mkdir(File.join(path, "lib"))
145
+ Dir.glob("lib/libortools.{dylib,so.9}", base: extract_path) do |file|
146
+ FileUtils.cp(File.join(extract_path, file), File.join(path, file))
147
+ end
148
+ so_path = File.join(path, "lib/libortools.so.9")
149
+ if File.exist?(so_path)
150
+ File.symlink(so_path, File.join(path, "lib/libortools.so"))
151
+ end
152
+ end
130
153
 
131
154
  # export
132
155
  $vendor_path = path
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.7.0"
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.7.0
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-03-23 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
@@ -87,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
92
  - !ruby/object:Gem::Version
88
93
  version: '0'
89
94
  requirements: []
90
- rubygems_version: 3.3.3
95
+ rubygems_version: 3.3.7
91
96
  signing_key:
92
97
  specification_version: 4
93
98
  summary: Operations research tools for Ruby