opt-rb 0.1.0 → 0.1.1

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: 300747a1f97ca67851cda0264f649d1e7e0a4f126609c658efb4f3fc509f14f7
4
- data.tar.gz: 87fdcba2ec49277f3491f9a61b04ae74107b1df77d13c81392f63cf58989194f
3
+ metadata.gz: 8fbd52b19c465db0b32b7ef39a80c581904de6cfd257ca20f28c04fb0ac50b31
4
+ data.tar.gz: 1dea622c2248537c91c9d66ec80b749a60485195acbc25383a6377b53f4c7086
5
5
  SHA512:
6
- metadata.gz: 1c850b8f467bb5b0b9f1fc7a960db0232a2cddd26a129fa8db072b7701e4ccd6ddb0fa828042f16bb4d6263e05c2ea856796648ad7f2619971bca559afc97749
7
- data.tar.gz: 99e1b9798bb609fe56b844f21df02578e44984885076a631590569c47fc979c51113098c57f667ffccfbc4f86d91784bdd98eec7fc23ee9e5c38a9cc65ccabf3
6
+ metadata.gz: 405e7e4a8109885cb1c97e0fc9380e346ae9876439376635fa1d3cd0f1cdf293ca005e6bc31b7af49913c2a52ade0972690b6b155e13db07f4919eda12125625
7
+ data.tar.gz: 6d3b768fefe6388cf3b21dcb499e1c80e7d2eb4c5f61febd2ce72ec1f4ea7cae790267620a452ca805684d4434fa35bcada98d9ad89865cac2f099d063fe8255
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.1.1 (2023-04-16)
2
+
3
+ - Added support for semi-continuous and semi-integer variables
4
+
1
5
  ## 0.1.0 (2023-01-25)
2
6
 
3
7
  - First release
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  :fire: Convex optimization for Ruby
4
4
 
5
- Supports [Cbc](https://github.com/ankane/cbc-ruby), [Clp](https://github.com/ankane/clp-ruby), [GLOP](https://github.com/ankane/or-tools-ruby), [GLPK](https://github.com/ankane/glpk-ruby), [HiGHS](https://github.com/ankane/highs-ruby), [OSQP](https://github.com/ankane/osqp-ruby), and [SCS](https://github.com/ankane/scs-ruby)
5
+ Supports Cbc, Clp, GLOP, GLPK, HiGHS, OSQP, and SCS
6
6
 
7
7
  [![Build Status](https://github.com/ankane/opt/workflows/build/badge.svg?branch=master)](https://github.com/ankane/opt/actions)
8
8
 
@@ -14,15 +14,19 @@ Add this line to your application’s Gemfile:
14
14
  gem "opt-rb"
15
15
  ```
16
16
 
17
- And install a solver:
17
+ And install one or more solvers based on your problem types:
18
18
 
19
- - [Cbc](https://github.com/ankane/cbc-ruby#installation)
20
- - [Clp](https://github.com/ankane/clp-ruby#installation)
21
- - [GLOP](https://github.com/ankane/or-tools-ruby#installation)
22
- - [GLPK](https://github.com/ankane/glpk-ruby#installation)
23
- - [HiGHS](https://github.com/ankane/highs-ruby#installation)
24
- - [OSQP](https://github.com/ankane/osqp-ruby#installation)
25
- - [SCS](https://github.com/ankane/scs-ruby#installation)
19
+ Solver | LP | QP | MIP | License
20
+ --- | --- | --- | --- | ---
21
+ [Cbc](https://github.com/ankane/cbc-ruby) | ✓ | | ✓ | EPL-2.0
22
+ [Clp](https://github.com/ankane/clp-ruby) | ✓ | | | EPL-2.0
23
+ [GLOP](https://github.com/ankane/or-tools-ruby) | ✓ | | | Apache-2.0
24
+ [GLPK](https://github.com/ankane/glpk-ruby) | ✓ | | ✓ | GPL-3.0-or-later
25
+ [HiGHS](https://github.com/ankane/highs-ruby) | ✓ | ✓ | ✓ | MIT
26
+ [OSQP](https://github.com/ankane/osqp-ruby) | ✓ | ✓ | | Apache-2.0
27
+ [SCS](https://github.com/ankane/scs-ruby) | ✓ | * | | MIT
28
+
29
+ \* supports, but not implemented yet
26
30
 
27
31
  ## Getting Started
28
32
 
@@ -46,29 +50,34 @@ Get the value of a variable
46
50
  x1.value
47
51
  ```
48
52
 
53
+ QP
54
+
55
+ ```ruby
56
+ prob.minimize(x1 * x1)
57
+ ```
58
+
49
59
  MIP
50
60
 
51
61
  ```ruby
52
62
  x1 = Opt::Integer.new(0.., "x1")
53
- x1 = Opt::Binary.new("x1")
63
+ x2 = Opt::Binary.new("x2")
54
64
  ```
55
65
 
56
- ## Problem Types
57
-
58
- Solver | LP | QP | MIP | License
59
- --- | --- | --- | --- | ---
60
- Cbc | ✓ | | ✓ | EPL-2.0
61
- Clp | ✓ | | | EPL-2.0
62
- GLOP | ✓ | | | Apache-2.0
63
- GLPK | ✓ | | ✓ | GPL-3.0-or-later
64
- HiGHS | ✓ | ✓ | ✓ | MIT
65
- OSQP | ✓ | ✓ | | Apache-2.0
66
- SCS | ✓ | * | | MIT
66
+ MIP with semi-continuous variables - *HiGHS only at the moment* [unreleased]
67
67
 
68
- \* supports, but not implemented yet
68
+ ```ruby
69
+ x1 = Opt::SemiContinuous.new(2.., "x1")
70
+ x2 = Opt::SemiInteger.new(2.., "x2")
71
+ ```
69
72
 
70
73
  ## Reference
71
74
 
75
+ Specify the solver
76
+
77
+ ```ruby
78
+ prob.solve(solver: :cbc)
79
+ ```
80
+
72
81
  Enable verbose logging
73
82
 
74
83
  ```ruby
data/lib/opt/problem.rb CHANGED
@@ -27,7 +27,10 @@ module Opt
27
27
 
28
28
  vars = self.vars
29
29
  raise Error, "No variables" if vars.empty?
30
- type = vars.any? { |v| v.is_a?(Integer) } ? :mip : :lp
30
+ has_semi_continuous_var = vars.any? { |v| v.is_a?(SemiContinuous) }
31
+ has_semi_integer_var = vars.any? { |v| v.is_a?(SemiInteger) }
32
+ has_integer_var = vars.any? { |v| v.is_a?(Integer) }
33
+ type = has_semi_continuous_var || has_semi_integer_var || has_integer_var ? :mip : :lp
31
34
  quadratic = @indexed_objective.any? { |k, _| k.is_a?(Array) }
32
35
 
33
36
  if quadratic
@@ -44,6 +47,9 @@ module Opt
44
47
  solver_cls = Opt.solvers.fetch(solver)
45
48
  raise Error, "Solver does not support #{type}" unless solver_cls.supports_type?(type)
46
49
 
50
+ raise Error, "Solver does not support semi-continuous variables" if has_semi_continuous_var && !solver_cls.supports_semi_continuous_variables?
51
+ raise Error, "Solver does not support semi-integer variables" if has_semi_integer_var && !solver_cls.supports_semi_integer_variables?
52
+
47
53
  col_lower = []
48
54
  col_upper = []
49
55
  obj = []
@@ -54,7 +60,8 @@ module Opt
54
60
  col_lower << (var.bounds.begin || -Float::INFINITY)
55
61
  upper = var.bounds.end
56
62
  if upper && var.bounds.exclude_end?
57
- if var.is_a?(Integer)
63
+ case var
64
+ when Integer, SemiInteger
58
65
  upper -= 1
59
66
  else
60
67
  upper -= Float::EPSILON
@@ -117,7 +124,7 @@ module Opt
117
124
  case a
118
125
  when Binary
119
126
  b.round != 0
120
- when Integer
127
+ when Integer, SemiInteger
121
128
  b.round
122
129
  else
123
130
  b
@@ -149,6 +156,9 @@ module Opt
149
156
  else
150
157
  "#{var.name} #{end_op} #{bounds.end}"
151
158
  end
159
+ if var.is_a?(SemiContinuous) || var.is_a?(SemiInteger)
160
+ var_str = "#{var_str} or #{var.name} = 0"
161
+ end
152
162
  str << " #{var_str}\n"
153
163
  end
154
164
  str
@@ -0,0 +1,4 @@
1
+ module Opt
2
+ class SemiContinuous < Variable
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Opt
2
+ class SemiInteger < Variable
3
+ end
4
+ end
@@ -4,6 +4,14 @@ module Opt
4
4
  def self.supports_type?(type)
5
5
  supported_types.include?(type)
6
6
  end
7
+
8
+ def self.supports_semi_continuous_variables?
9
+ false
10
+ end
11
+
12
+ def self.supports_semi_integer_variables?
13
+ false
14
+ end
7
15
  end
8
16
  end
9
17
  end
@@ -19,7 +19,7 @@ module Opt
19
19
  a_index: index,
20
20
  a_value: value,
21
21
  offset: offset,
22
- integrality: vars.map { |v| v.is_a?(Integer) ? 1 : 0 }
22
+ integrality: vars.map { |var| integrality(var) }
23
23
  )
24
24
  when :qp
25
25
  q_start = []
@@ -80,6 +80,17 @@ module Opt
80
80
  }
81
81
  end
82
82
 
83
+ private
84
+
85
+ def integrality(var)
86
+ case var
87
+ when SemiInteger then 3
88
+ when SemiContinuous then 2
89
+ when Integer then 1
90
+ else 0
91
+ end
92
+ end
93
+
83
94
  def self.available?
84
95
  defined?(Highs)
85
96
  end
@@ -87,6 +98,14 @@ module Opt
87
98
  def self.supported_types
88
99
  [:lp, :qp, :mip]
89
100
  end
101
+
102
+ def self.supports_semi_continuous_variables?
103
+ true
104
+ end
105
+
106
+ def self.supports_semi_integer_variables?
107
+ true
108
+ end
90
109
  end
91
110
  end
92
111
  end
data/lib/opt/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Opt
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
data/lib/opt.rb CHANGED
@@ -5,6 +5,8 @@ require_relative "opt/constant"
5
5
  require_relative "opt/variable"
6
6
  require_relative "opt/integer"
7
7
  require_relative "opt/binary"
8
+ require_relative "opt/semi_continuous"
9
+ require_relative "opt/semi_integer"
8
10
  require_relative "opt/problem"
9
11
  require_relative "opt/product"
10
12
  require_relative "opt/version"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opt-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-26 00:00:00.000000000 Z
11
+ date: 2023-04-17 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: andrew@ankane.org
@@ -28,6 +28,8 @@ files:
28
28
  - lib/opt/integer.rb
29
29
  - lib/opt/problem.rb
30
30
  - lib/opt/product.rb
31
+ - lib/opt/semi_continuous.rb
32
+ - lib/opt/semi_integer.rb
31
33
  - lib/opt/solvers/abstract_solver.rb
32
34
  - lib/opt/solvers/cbc_solver.rb
33
35
  - lib/opt/solvers/clp_solver.rb
@@ -57,7 +59,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
59
  - !ruby/object:Gem::Version
58
60
  version: '0'
59
61
  requirements: []
60
- rubygems_version: 3.4.1
62
+ rubygems_version: 3.4.10
61
63
  signing_key:
62
64
  specification_version: 4
63
65
  summary: Convex optimization for Ruby