opt-rb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,76 @@
1
+ module Opt
2
+ module Solvers
3
+ class ScsSolver < AbstractSolver
4
+ def solve(sense:, col_lower:, col_upper:, obj:, row_lower:, row_upper:, constraints_by_var:, vars:, offset:, verbose:, time_limit:, **)
5
+ obj = obj.map { |v| -v } if sense == :maximize
6
+
7
+ a = []
8
+ b = []
9
+
10
+ # add variables to constraints
11
+ vars.each_with_index do |var, i|
12
+ if col_lower[i] != -Float::INFINITY
13
+ constraints_by_var << [{var => 1}, :>=, col_lower[i]]
14
+ end
15
+ if col_upper[i] != Float::INFINITY
16
+ constraints_by_var << [{var => 1}, :<=, col_upper[i]]
17
+ end
18
+ end
19
+
20
+ c1, c2 = constraints_by_var.partition { |_, op, _| op == :== }
21
+ z = c1.size
22
+ l = c2.size
23
+
24
+ c1.each do |left, _, right|
25
+ a << vars.map { |v| left[v] || 0 }
26
+ b << right
27
+ end
28
+
29
+ c2.each do |left, op, right|
30
+ ai = vars.map { |v| left[v] || 0 }
31
+ bi = right
32
+
33
+ if op == :>=
34
+ ai.map! { |v| v * -1 }
35
+ bi *= -1
36
+ end
37
+
38
+ a << ai
39
+ b << bi
40
+ end
41
+
42
+ data = {a: a, b: b, c: obj}
43
+ cone = {z: z, l: l}
44
+ solver = SCS::Solver.new
45
+ res = solver.solve(data, cone, verbose: verbose, time_limit_secs: time_limit)
46
+ objective = res[:pobj]
47
+ objective *= -1 if sense == :maximize
48
+ objective += offset
49
+
50
+ status =
51
+ case res[:status]
52
+ when "solved"
53
+ :optimal
54
+ when "infeasible", "unbounded"
55
+ res[:status].to_sym
56
+ else
57
+ res[:status]
58
+ end
59
+
60
+ {
61
+ status: status,
62
+ objective: objective,
63
+ x: res[:x]
64
+ }
65
+ end
66
+
67
+ def self.available?
68
+ defined?(SCS)
69
+ end
70
+
71
+ def self.supported_types
72
+ [:lp]
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,19 @@
1
+ module Opt
2
+ class Variable < Expression
3
+ attr_reader :bounds, :name
4
+ attr_accessor :value
5
+
6
+ def initialize(bounds, name = nil)
7
+ @bounds = bounds
8
+ @name = name || "x#{object_id}"
9
+ end
10
+
11
+ def inspect
12
+ @name
13
+ end
14
+
15
+ def vars
16
+ @vars ||= [self]
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module Opt
2
+ VERSION = "0.1.0"
3
+ end
data/lib/opt-rb.rb ADDED
@@ -0,0 +1 @@
1
+ require_relative "opt"
data/lib/opt.rb ADDED
@@ -0,0 +1,46 @@
1
+ # modules
2
+ require_relative "opt/expression"
3
+ require_relative "opt/comparison"
4
+ require_relative "opt/constant"
5
+ require_relative "opt/variable"
6
+ require_relative "opt/integer"
7
+ require_relative "opt/binary"
8
+ require_relative "opt/problem"
9
+ require_relative "opt/product"
10
+ require_relative "opt/version"
11
+
12
+ # solvers
13
+ require_relative "opt/solvers/abstract_solver"
14
+ require_relative "opt/solvers/cbc_solver"
15
+ require_relative "opt/solvers/clp_solver"
16
+ require_relative "opt/solvers/glop_solver"
17
+ require_relative "opt/solvers/glpk_solver"
18
+ require_relative "opt/solvers/highs_solver"
19
+ require_relative "opt/solvers/osqp_solver"
20
+ require_relative "opt/solvers/scs_solver"
21
+
22
+ module Opt
23
+ class Error < StandardError; end
24
+
25
+ class << self
26
+ attr_accessor :solvers, :default_solvers
27
+ end
28
+ self.solvers = {}
29
+ self.default_solvers = {}
30
+
31
+ def self.register_solver(key, cls)
32
+ solvers[key] = cls
33
+ end
34
+
35
+ def self.available_solvers
36
+ solvers.select { |k, v| v.available? }.map(&:first)
37
+ end
38
+ end
39
+
40
+ Opt.register_solver :cbc, Opt::Solvers::CbcSolver
41
+ Opt.register_solver :clp, Opt::Solvers::ClpSolver
42
+ Opt.register_solver :glop, Opt::Solvers::GlopSolver
43
+ Opt.register_solver :glpk, Opt::Solvers::GlpkSolver
44
+ Opt.register_solver :highs, Opt::Solvers::HighsSolver
45
+ Opt.register_solver :osqp, Opt::Solvers::OsqpSolver
46
+ Opt.register_solver :scs, Opt::Solvers::ScsSolver
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: opt-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Kane
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-26 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email: andrew@ankane.org
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - CHANGELOG.md
20
+ - LICENSE.txt
21
+ - README.md
22
+ - lib/opt-rb.rb
23
+ - lib/opt.rb
24
+ - lib/opt/binary.rb
25
+ - lib/opt/comparison.rb
26
+ - lib/opt/constant.rb
27
+ - lib/opt/expression.rb
28
+ - lib/opt/integer.rb
29
+ - lib/opt/problem.rb
30
+ - lib/opt/product.rb
31
+ - lib/opt/solvers/abstract_solver.rb
32
+ - lib/opt/solvers/cbc_solver.rb
33
+ - lib/opt/solvers/clp_solver.rb
34
+ - lib/opt/solvers/glop_solver.rb
35
+ - lib/opt/solvers/glpk_solver.rb
36
+ - lib/opt/solvers/highs_solver.rb
37
+ - lib/opt/solvers/osqp_solver.rb
38
+ - lib/opt/solvers/scs_solver.rb
39
+ - lib/opt/variable.rb
40
+ - lib/opt/version.rb
41
+ homepage: https://github.com/ankane/opt
42
+ licenses:
43
+ - Apache-2.0
44
+ metadata: {}
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '2.7'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubygems_version: 3.4.1
61
+ signing_key:
62
+ specification_version: 4
63
+ summary: Convex optimization for Ruby
64
+ test_files: []