opt-rb 0.1.0 → 0.1.1

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