4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
# File 'lib/opt/solvers/scs_solver.rb', line 4
def solve(sense:, col_lower:, col_upper:, obj:, row_lower:, row_upper:, constraints_by_var:, vars:, offset:, verbose:, time_limit:, **)
obj = obj.map { |v| -v } if sense == :maximize
a = []
b = []
vars.each_with_index do |var, i|
if col_lower[i] != -Float::INFINITY
constraints_by_var << [{var => 1}, :>=, col_lower[i]]
end
if col_upper[i] != Float::INFINITY
constraints_by_var << [{var => 1}, :<=, col_upper[i]]
end
end
c1, c2 = constraints_by_var.partition { |_, op, _| op == :== }
z = c1.size
l = c2.size
c1.each do |left, _, right|
a << vars.map { |v| left[v] || 0 }
b << right
end
c2.each do |left, op, right|
ai = vars.map { |v| left[v] || 0 }
bi = right
if op == :>=
ai.map! { |v| v * -1 }
bi *= -1
end
a << ai
b << bi
end
data = {a: a, b: b, c: obj}
cone = {z: z, l: l}
solver = SCS::Solver.new
res = solver.solve(data, cone, verbose: verbose, time_limit_secs: time_limit)
objective = res[:pobj]
objective *= -1 if sense == :maximize
objective += offset
status =
case res[:status]
when "solved"
:optimal
when "infeasible", "unbounded"
res[:status].to_sym
else
res[:status]
end
{
status: status,
objective: objective,
x: res[:x]
}
end
|