or-tools 0.14.0 → 0.14.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 +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +7 -7
- data/ext/or-tools/bin_packing.cpp +3 -4
- data/ext/or-tools/constraint.cpp +4 -4
- data/ext/or-tools/extconf.rb +1 -1
- data/ext/or-tools/linear.cpp +111 -7
- data/ext/or-tools/math_opt.cpp +4 -4
- data/ext/or-tools/routing.cpp +7 -8
- data/lib/or_tools/solver.rb +5 -0
- data/lib/or_tools/version.rb +1 -1
- metadata +5 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2974585825c8e1f3d50aabc494131861eef79c80468a889537f58b2dd3926be
|
|
4
|
+
data.tar.gz: 5f9b8fe4574a30ebea1fba0b53a91475683e68fe5e535ba99047a6f2b3a16173
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 48fc84cebe3a922044a98909dd8b06d61712ea1bdf06014b99a0a92dd4406766facd99cd3f2c99425257642ef08ad5a489d9ee87f354cf7f5d16a3d7ff306d5e
|
|
7
|
+
data.tar.gz: 6edc981eb8b47f716f607be3e7c28a59c49076810a7fcbda7077fcc3a1abcf420fe58c17d372a40447f435e7abfd68879fc471b0c8c86afdd4d1610786b0489e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
## 0.14.2 (2025-02-10)
|
|
2
|
+
|
|
3
|
+
- Fixed error with Rice 4.5
|
|
4
|
+
|
|
5
|
+
## 0.14.1 (2024-12-04)
|
|
6
|
+
|
|
7
|
+
- Added support for parameters to `Solver`
|
|
8
|
+
- Fixed error with `inspect` for `MathOpt` variables
|
|
9
|
+
|
|
1
10
|
## 0.14.0 (2024-10-22)
|
|
2
11
|
|
|
3
12
|
- Added experimental support for `MathOpt`
|
data/README.md
CHANGED
|
@@ -93,15 +93,15 @@ Specify people and their availabililty
|
|
|
93
93
|
people = [
|
|
94
94
|
{
|
|
95
95
|
availability: [
|
|
96
|
-
{starts_at: Time.parse("
|
|
97
|
-
{starts_at: Time.parse("
|
|
96
|
+
{starts_at: Time.parse("2025-01-01 08:00:00"), ends_at: Time.parse("2025-01-01 16:00:00")},
|
|
97
|
+
{starts_at: Time.parse("2025-01-02 08:00:00"), ends_at: Time.parse("2025-01-02 16:00:00")}
|
|
98
98
|
],
|
|
99
99
|
max_hours: 40 # optional, applies to entire scheduling period
|
|
100
100
|
},
|
|
101
101
|
{
|
|
102
102
|
availability: [
|
|
103
|
-
{starts_at: Time.parse("
|
|
104
|
-
{starts_at: Time.parse("
|
|
103
|
+
{starts_at: Time.parse("2025-01-01 08:00:00"), ends_at: Time.parse("2025-01-01 16:00:00")},
|
|
104
|
+
{starts_at: Time.parse("2025-01-03 08:00:00"), ends_at: Time.parse("2025-01-03 16:00:00")}
|
|
105
105
|
],
|
|
106
106
|
max_hours: 20
|
|
107
107
|
}
|
|
@@ -112,9 +112,9 @@ Specify shifts
|
|
|
112
112
|
|
|
113
113
|
```ruby
|
|
114
114
|
shifts = [
|
|
115
|
-
{starts_at: Time.parse("
|
|
116
|
-
{starts_at: Time.parse("
|
|
117
|
-
{starts_at: Time.parse("
|
|
115
|
+
{starts_at: Time.parse("2025-01-01 08:00:00"), ends_at: Time.parse("2025-01-01 16:00:00")},
|
|
116
|
+
{starts_at: Time.parse("2025-01-02 08:00:00"), ends_at: Time.parse("2025-01-02 16:00:00")},
|
|
117
|
+
{starts_at: Time.parse("2025-01-03 08:00:00"), ends_at: Time.parse("2025-01-03 16:00:00")}
|
|
118
118
|
]
|
|
119
119
|
```
|
|
120
120
|
|
|
@@ -13,16 +13,15 @@ namespace Rice::detail
|
|
|
13
13
|
template<>
|
|
14
14
|
struct Type<KnapsackSolver::SolverType>
|
|
15
15
|
{
|
|
16
|
-
static bool verify()
|
|
17
|
-
{
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
16
|
+
static bool verify() { return true; }
|
|
20
17
|
};
|
|
21
18
|
|
|
22
19
|
template<>
|
|
23
20
|
class From_Ruby<KnapsackSolver::SolverType>
|
|
24
21
|
{
|
|
25
22
|
public:
|
|
23
|
+
Convertible is_convertible(VALUE value) { return Convertible::Cast; }
|
|
24
|
+
|
|
26
25
|
KnapsackSolver::SolverType convert(VALUE x)
|
|
27
26
|
{
|
|
28
27
|
auto s = Symbol(x).str();
|
data/ext/or-tools/constraint.cpp
CHANGED
|
@@ -32,16 +32,15 @@ namespace Rice::detail
|
|
|
32
32
|
template<>
|
|
33
33
|
struct Type<LinearExpr>
|
|
34
34
|
{
|
|
35
|
-
static bool verify()
|
|
36
|
-
{
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
35
|
+
static bool verify() { return true; }
|
|
39
36
|
};
|
|
40
37
|
|
|
41
38
|
template<>
|
|
42
39
|
class From_Ruby<LinearExpr>
|
|
43
40
|
{
|
|
44
41
|
public:
|
|
42
|
+
Convertible is_convertible(VALUE value) { return Convertible::Cast; }
|
|
43
|
+
|
|
45
44
|
LinearExpr convert(VALUE v)
|
|
46
45
|
{
|
|
47
46
|
LinearExpr expr;
|
|
@@ -70,6 +69,7 @@ namespace Rice::detail
|
|
|
70
69
|
void init_constraint(Rice::Module& m) {
|
|
71
70
|
Rice::define_class_under<Domain>(m, "Domain")
|
|
72
71
|
.define_constructor(Rice::Constructor<Domain, int64_t, int64_t>())
|
|
72
|
+
.define_singleton_function("from_values", &Domain::FromValues)
|
|
73
73
|
.define_method("min", &Domain::Min)
|
|
74
74
|
.define_method("max", &Domain::Max);
|
|
75
75
|
|
data/ext/or-tools/extconf.rb
CHANGED
|
@@ -9,7 +9,7 @@ $CXXFLAGS << " -Wall -Wextra"
|
|
|
9
9
|
$CXXFLAGS << " -Wno-sign-compare -Wno-ignored-qualifiers -Wno-unused-parameter -Wno-missing-field-initializers"
|
|
10
10
|
|
|
11
11
|
# hide Rice warnings
|
|
12
|
-
$CXXFLAGS << " -Wno-implicit-fallthrough"
|
|
12
|
+
$CXXFLAGS << " -Wno-unused-private-field -Wno-implicit-fallthrough"
|
|
13
13
|
|
|
14
14
|
inc, lib = dir_config("or-tools")
|
|
15
15
|
if inc || lib
|
data/ext/or-tools/linear.cpp
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
using operations_research::MPConstraint;
|
|
6
6
|
using operations_research::MPObjective;
|
|
7
|
+
using operations_research::MPSolverParameters;
|
|
7
8
|
using operations_research::MPSolver;
|
|
8
9
|
using operations_research::MPVariable;
|
|
9
10
|
|
|
@@ -19,15 +20,14 @@ namespace Rice::detail
|
|
|
19
20
|
template<>
|
|
20
21
|
struct Type<MPSolver::OptimizationProblemType>
|
|
21
22
|
{
|
|
22
|
-
static bool verify()
|
|
23
|
-
{
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
23
|
+
static bool verify() { return true; }
|
|
26
24
|
};
|
|
27
25
|
|
|
28
26
|
template<>
|
|
29
27
|
struct From_Ruby<MPSolver::OptimizationProblemType>
|
|
30
28
|
{
|
|
29
|
+
Convertible is_convertible(VALUE value) { return Convertible::Cast; }
|
|
30
|
+
|
|
31
31
|
static MPSolver::OptimizationProblemType convert(VALUE x)
|
|
32
32
|
{
|
|
33
33
|
auto s = Symbol(x).str();
|
|
@@ -56,8 +56,112 @@ void init_linear(Rice::Module& m) {
|
|
|
56
56
|
.define_method("set_coefficient", &MPObjective::SetCoefficient)
|
|
57
57
|
.define_method("set_offset", &MPObjective::SetOffset)
|
|
58
58
|
.define_method("set_maximization", &MPObjective::SetMaximization)
|
|
59
|
+
.define_method("best_bound", &MPObjective::BestBound)
|
|
59
60
|
.define_method("set_minimization", &MPObjective::SetMinimization);
|
|
60
61
|
|
|
62
|
+
Rice::define_class_under<MPSolverParameters>(m, "MPSolverParameters")
|
|
63
|
+
.define_constructor(Rice::Constructor<MPSolverParameters>())
|
|
64
|
+
.define_method("reset", &MPSolverParameters::Reset)
|
|
65
|
+
.define_method(
|
|
66
|
+
"relative_mip_gap=",
|
|
67
|
+
[](MPSolverParameters& self, double relative_mip_gap) {
|
|
68
|
+
self.SetDoubleParam(MPSolverParameters::DoubleParam::RELATIVE_MIP_GAP, relative_mip_gap);
|
|
69
|
+
})
|
|
70
|
+
.define_method(
|
|
71
|
+
"relative_mip_gap",
|
|
72
|
+
[](MPSolverParameters& self) {
|
|
73
|
+
return self.GetDoubleParam(MPSolverParameters::DoubleParam::RELATIVE_MIP_GAP);
|
|
74
|
+
})
|
|
75
|
+
.define_method(
|
|
76
|
+
"primal_tolerance=",
|
|
77
|
+
[](MPSolverParameters& self, double primal_tolerance) {
|
|
78
|
+
self.SetDoubleParam(MPSolverParameters::DoubleParam::PRIMAL_TOLERANCE, primal_tolerance);
|
|
79
|
+
})
|
|
80
|
+
.define_method(
|
|
81
|
+
"primal_tolerance",
|
|
82
|
+
[](MPSolverParameters& self) {
|
|
83
|
+
return self.GetDoubleParam(MPSolverParameters::DoubleParam::PRIMAL_TOLERANCE);
|
|
84
|
+
})
|
|
85
|
+
.define_method(
|
|
86
|
+
"dual_tolerance=",
|
|
87
|
+
[](MPSolverParameters& self, double dual_tolerance) {
|
|
88
|
+
self.SetDoubleParam(MPSolverParameters::DoubleParam::DUAL_TOLERANCE, dual_tolerance);
|
|
89
|
+
})
|
|
90
|
+
.define_method(
|
|
91
|
+
"dual_tolerance",
|
|
92
|
+
[](MPSolverParameters& self) {
|
|
93
|
+
return self.GetDoubleParam(MPSolverParameters::DoubleParam::DUAL_TOLERANCE);
|
|
94
|
+
})
|
|
95
|
+
.define_method(
|
|
96
|
+
"presolve=",
|
|
97
|
+
[](MPSolverParameters& self, bool value) {
|
|
98
|
+
int presolve;
|
|
99
|
+
if (value) {
|
|
100
|
+
presolve = MPSolverParameters::PresolveValues::PRESOLVE_ON;
|
|
101
|
+
} else {
|
|
102
|
+
presolve = MPSolverParameters::PresolveValues::PRESOLVE_OFF;
|
|
103
|
+
}
|
|
104
|
+
self.SetIntegerParam(MPSolverParameters::IntegerParam::PRESOLVE, presolve);
|
|
105
|
+
})
|
|
106
|
+
.define_method(
|
|
107
|
+
"presolve",
|
|
108
|
+
[](MPSolverParameters& self) {
|
|
109
|
+
int presolve = self.GetIntegerParam(MPSolverParameters::IntegerParam::PRESOLVE);
|
|
110
|
+
if (presolve == MPSolverParameters::PresolveValues::PRESOLVE_ON) {
|
|
111
|
+
return Rice::True;
|
|
112
|
+
} else if (presolve == MPSolverParameters::PresolveValues::PRESOLVE_OFF) {
|
|
113
|
+
return Rice::False;
|
|
114
|
+
} else {
|
|
115
|
+
return Rice::Nil;
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
.define_method(
|
|
119
|
+
"incrementality=",
|
|
120
|
+
[](MPSolverParameters& self, bool value) {
|
|
121
|
+
int incrementality;
|
|
122
|
+
if (value) {
|
|
123
|
+
incrementality = MPSolverParameters::IncrementalityValues::INCREMENTALITY_ON;
|
|
124
|
+
} else {
|
|
125
|
+
incrementality = MPSolverParameters::IncrementalityValues::INCREMENTALITY_OFF;
|
|
126
|
+
}
|
|
127
|
+
self.SetIntegerParam(MPSolverParameters::IntegerParam::INCREMENTALITY, incrementality);
|
|
128
|
+
})
|
|
129
|
+
.define_method(
|
|
130
|
+
"incrementality",
|
|
131
|
+
[](MPSolverParameters& self) {
|
|
132
|
+
int incrementality = self.GetIntegerParam(MPSolverParameters::IntegerParam::INCREMENTALITY);
|
|
133
|
+
if (incrementality == MPSolverParameters::IncrementalityValues::INCREMENTALITY_ON) {
|
|
134
|
+
return Rice::True;
|
|
135
|
+
} else if (incrementality == MPSolverParameters::IncrementalityValues::INCREMENTALITY_OFF) {
|
|
136
|
+
return Rice::False;
|
|
137
|
+
} else {
|
|
138
|
+
return Rice::Nil;
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
.define_method(
|
|
142
|
+
"scaling=",
|
|
143
|
+
[](MPSolverParameters& self, bool value) {
|
|
144
|
+
int scaling;
|
|
145
|
+
if (value) {
|
|
146
|
+
scaling = MPSolverParameters::ScalingValues::SCALING_ON;
|
|
147
|
+
} else {
|
|
148
|
+
scaling = MPSolverParameters::ScalingValues::SCALING_OFF;
|
|
149
|
+
}
|
|
150
|
+
self.SetIntegerParam(MPSolverParameters::IntegerParam::SCALING, scaling);
|
|
151
|
+
})
|
|
152
|
+
.define_method(
|
|
153
|
+
"scaling",
|
|
154
|
+
[](MPSolverParameters& self) {
|
|
155
|
+
int scaling = self.GetIntegerParam(MPSolverParameters::IntegerParam::SCALING);
|
|
156
|
+
if (scaling == MPSolverParameters::ScalingValues::SCALING_ON) {
|
|
157
|
+
return Rice::True;
|
|
158
|
+
} else if (scaling == MPSolverParameters::ScalingValues::SCALING_OFF) {
|
|
159
|
+
return Rice::False;
|
|
160
|
+
} else {
|
|
161
|
+
return Rice::Nil;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
|
|
61
165
|
Rice::define_class_under<MPSolver>(m, "Solver")
|
|
62
166
|
.define_singleton_function(
|
|
63
167
|
"_new",
|
|
@@ -109,9 +213,9 @@ void init_linear(Rice::Module& m) {
|
|
|
109
213
|
return self.MakeRowConstraint(lb, ub);
|
|
110
214
|
})
|
|
111
215
|
.define_method(
|
|
112
|
-
"
|
|
113
|
-
[](MPSolver& self) {
|
|
114
|
-
auto status = self.Solve();
|
|
216
|
+
"_solve",
|
|
217
|
+
[](MPSolver& self, MPSolverParameters& params) {
|
|
218
|
+
auto status = self.Solve(params);
|
|
115
219
|
|
|
116
220
|
if (status == MPSolver::ResultStatus::OPTIMAL) {
|
|
117
221
|
return Symbol("optimal");
|
data/ext/or-tools/math_opt.cpp
CHANGED
|
@@ -20,15 +20,14 @@ namespace Rice::detail
|
|
|
20
20
|
template<>
|
|
21
21
|
struct Type<SolverType>
|
|
22
22
|
{
|
|
23
|
-
static bool verify()
|
|
24
|
-
{
|
|
25
|
-
return true;
|
|
26
|
-
}
|
|
23
|
+
static bool verify() { return true; }
|
|
27
24
|
};
|
|
28
25
|
|
|
29
26
|
template<>
|
|
30
27
|
struct From_Ruby<SolverType>
|
|
31
28
|
{
|
|
29
|
+
Convertible is_convertible(VALUE value) { return Convertible::Cast; }
|
|
30
|
+
|
|
32
31
|
static SolverType convert(VALUE x)
|
|
33
32
|
{
|
|
34
33
|
auto s = Symbol(x).str();
|
|
@@ -64,6 +63,7 @@ void init_math_opt(Rice::Module& m) {
|
|
|
64
63
|
|
|
65
64
|
Rice::define_class_under<Variable>(mathopt, "Variable")
|
|
66
65
|
.define_method("id", &Variable::id)
|
|
66
|
+
.define_method("name", &Variable::name)
|
|
67
67
|
.define_method(
|
|
68
68
|
"_eql?",
|
|
69
69
|
[](Variable& self, Variable &other) {
|
data/ext/or-tools/routing.cpp
CHANGED
|
@@ -28,16 +28,15 @@ namespace Rice::detail
|
|
|
28
28
|
template<>
|
|
29
29
|
struct Type<RoutingNodeIndex>
|
|
30
30
|
{
|
|
31
|
-
static bool verify()
|
|
32
|
-
{
|
|
33
|
-
return true;
|
|
34
|
-
}
|
|
31
|
+
static bool verify() { return true; }
|
|
35
32
|
};
|
|
36
33
|
|
|
37
34
|
template<>
|
|
38
35
|
class From_Ruby<RoutingNodeIndex>
|
|
39
36
|
{
|
|
40
37
|
public:
|
|
38
|
+
Convertible is_convertible(VALUE value) { return Convertible::Cast; }
|
|
39
|
+
|
|
41
40
|
RoutingNodeIndex convert(VALUE x)
|
|
42
41
|
{
|
|
43
42
|
const RoutingNodeIndex index{From_Ruby<int>().convert(x)};
|
|
@@ -285,7 +284,7 @@ void init_routing(Rice::Module& m) {
|
|
|
285
284
|
Rice::define_class_under<RoutingModel::ResourceGroup>(m, "ResourceGroup");
|
|
286
285
|
|
|
287
286
|
Rice::define_class_under<RoutingModel>(m, "RoutingModel")
|
|
288
|
-
.define_constructor(Rice::Constructor<RoutingModel, RoutingIndexManager, RoutingModelParameters>(), Rice::Arg("
|
|
287
|
+
.define_constructor(Rice::Constructor<RoutingModel, RoutingIndexManager, RoutingModelParameters>(), Rice::Arg("_index_manager"), Rice::Arg("_parameters") = operations_research::DefaultRoutingModelParameters())
|
|
289
288
|
.define_method("register_unary_transit_vector", &RoutingModel::RegisterUnaryTransitVector)
|
|
290
289
|
.define_method(
|
|
291
290
|
"register_unary_transit_callback",
|
|
@@ -300,7 +299,7 @@ void init_routing(Rice::Module& m) {
|
|
|
300
299
|
return Rice::detail::From_Ruby<int64_t>().convert(callback.call("call", from_index));
|
|
301
300
|
}
|
|
302
301
|
);
|
|
303
|
-
}, Rice::Arg("
|
|
302
|
+
}, Rice::Arg("_callback").keepAlive())
|
|
304
303
|
.define_method("register_transit_matrix", &RoutingModel::RegisterTransitMatrix)
|
|
305
304
|
.define_method(
|
|
306
305
|
"register_transit_callback",
|
|
@@ -315,7 +314,7 @@ void init_routing(Rice::Module& m) {
|
|
|
315
314
|
return Rice::detail::From_Ruby<int64_t>().convert(callback.call("call", from_index, to_index));
|
|
316
315
|
}
|
|
317
316
|
);
|
|
318
|
-
}, Rice::Arg("
|
|
317
|
+
}, Rice::Arg("_callback").keepAlive())
|
|
319
318
|
.define_method("add_dimension", &RoutingModel::AddDimension)
|
|
320
319
|
.define_method("add_dimension_with_vehicle_transits", &RoutingModel::AddDimensionWithVehicleTransits)
|
|
321
320
|
.define_method("add_dimension_with_vehicle_capacity", &RoutingModel::AddDimensionWithVehicleCapacity)
|
|
@@ -332,7 +331,7 @@ void init_routing(Rice::Module& m) {
|
|
|
332
331
|
.define_method("add_resource_group", &RoutingModel::AddResourceGroup)
|
|
333
332
|
.define_method("dimension_resource_group_indices", &RoutingModel::GetDimensionResourceGroupIndices)
|
|
334
333
|
.define_method("dimension_resource_group_index", &RoutingModel::GetDimensionResourceGroupIndex)
|
|
335
|
-
.define_method("add_disjunction", &RoutingModel::AddDisjunction, Rice::Arg("
|
|
334
|
+
.define_method("add_disjunction", &RoutingModel::AddDisjunction, Rice::Arg("_indices"), Rice::Arg("_penalty"), Rice::Arg("_max_cardinality") = (int64_t)1)
|
|
336
335
|
.define_method("disjunction_indices", &RoutingModel::GetDisjunctionIndices)
|
|
337
336
|
.define_method("disjunction_penalty", &RoutingModel::GetDisjunctionPenalty)
|
|
338
337
|
.define_method("disjunction_max_cardinality", &RoutingModel::GetDisjunctionMaxCardinality)
|
data/lib/or_tools/solver.rb
CHANGED
data/lib/or_tools/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: or-tools
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.14.
|
|
4
|
+
version: 0.14.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Kane
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2025-02-10 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rice
|
|
@@ -16,15 +15,14 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: 4.
|
|
18
|
+
version: '4.5'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: 4.
|
|
27
|
-
description:
|
|
25
|
+
version: '4.5'
|
|
28
26
|
email: andrew@ankane.org
|
|
29
27
|
executables: []
|
|
30
28
|
extensions:
|
|
@@ -74,7 +72,6 @@ homepage: https://github.com/ankane/or-tools-ruby
|
|
|
74
72
|
licenses:
|
|
75
73
|
- Apache-2.0
|
|
76
74
|
metadata: {}
|
|
77
|
-
post_install_message:
|
|
78
75
|
rdoc_options: []
|
|
79
76
|
require_paths:
|
|
80
77
|
- lib
|
|
@@ -89,8 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
89
86
|
- !ruby/object:Gem::Version
|
|
90
87
|
version: '0'
|
|
91
88
|
requirements: []
|
|
92
|
-
rubygems_version: 3.
|
|
93
|
-
signing_key:
|
|
89
|
+
rubygems_version: 3.6.2
|
|
94
90
|
specification_version: 4
|
|
95
91
|
summary: Operations research tools for Ruby
|
|
96
92
|
test_files: []
|