opl 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/opl.rb +33 -14
- metadata +2 -2
data/lib/opl.rb
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
require "rglpk"
|
2
2
|
|
3
3
|
#TODO
|
4
|
+
#unbounded or conflicting bounds messages
|
5
|
+
# e.g.
|
6
|
+
# lp = maximize(
|
7
|
+
# "x",
|
8
|
+
# subject_to([
|
9
|
+
# "x >= 0"
|
10
|
+
# ]))
|
11
|
+
|
12
|
+
#put a warning about branch and cut in the github description
|
13
|
+
|
4
14
|
#1.1
|
5
15
|
#setting variable values in constraints
|
6
16
|
#and then using that variable value in further constraints
|
7
|
-
|
17
|
+
|
8
18
|
#1.2
|
9
19
|
#summing of variables
|
10
20
|
#e.g. x1 + x1 <= 3
|
@@ -89,7 +99,7 @@ class OPL
|
|
89
99
|
variable = text.scan(/[a-z]\[/)[0].gsub("[","")
|
90
100
|
#will need to make this multiple variables??
|
91
101
|
#or is this even used at all????
|
92
|
-
value_combinations =
|
102
|
+
value_combinations = self.mass_product(values)
|
93
103
|
value_combinations.each_index do |vc_index|
|
94
104
|
value_combination = value_combinations[vc_index]
|
95
105
|
value_combination = [value_combination] unless value_combination.is_a?(Array)
|
@@ -263,7 +273,7 @@ class OPL
|
|
263
273
|
end
|
264
274
|
|
265
275
|
def self.coefficients(text)#parameter is one side of the equation
|
266
|
-
equation =
|
276
|
+
equation = self.add_ones(text)
|
267
277
|
if equation[0]=="-"
|
268
278
|
equation.scan(/[+-][\d\.]+/)
|
269
279
|
else
|
@@ -272,7 +282,7 @@ class OPL
|
|
272
282
|
end
|
273
283
|
|
274
284
|
def self.variables(text)#parameter is one side of the equation
|
275
|
-
equation =
|
285
|
+
equation = self.add_ones(text)
|
276
286
|
equation.scan(/[a-z]+[\[\]\d]*/)
|
277
287
|
end
|
278
288
|
|
@@ -312,8 +322,8 @@ class OPL
|
|
312
322
|
#in: "-8 + x + y + 3 <= 100"
|
313
323
|
#out: "x + y <= 100 + 5"
|
314
324
|
text = text.gsub(" ","")
|
315
|
-
s =
|
316
|
-
constants_results =
|
325
|
+
s = self.sides(text)
|
326
|
+
constants_results = self.get_constants(s[:lhs])
|
317
327
|
constants = []
|
318
328
|
constants_results[:formatted].each_index do |i|
|
319
329
|
formatted_constant = constants_results[:formatted][i]
|
@@ -356,7 +366,7 @@ class OPL
|
|
356
366
|
end
|
357
367
|
|
358
368
|
def self.sub_rhs_with_summed_constants(constraint)
|
359
|
-
rhs =
|
369
|
+
rhs = self.sides(constraint)[:rhs]
|
360
370
|
constraint.gsub(rhs, self.sum_constants(rhs))
|
361
371
|
end
|
362
372
|
|
@@ -382,7 +392,7 @@ class OPL
|
|
382
392
|
#in: "x + y - x[3] <= 3z + 2x[2] - 10"
|
383
393
|
#out: "x + y - x[3] - 3z - 2x[2] <= -10"
|
384
394
|
text = text.gsub(" ", "")
|
385
|
-
s =
|
395
|
+
s = self.sides(text)
|
386
396
|
oper = self.operator(text)
|
387
397
|
rhs = s[:rhs]
|
388
398
|
lhs = s[:lhs]
|
@@ -471,6 +481,9 @@ class OPL
|
|
471
481
|
attr_accessor :formatted_constraints
|
472
482
|
attr_accessor :rglpk_object
|
473
483
|
attr_accessor :solver
|
484
|
+
attr_accessor :matrix
|
485
|
+
attr_accessor :simplex_message
|
486
|
+
attr_accessor :mip_message
|
474
487
|
|
475
488
|
def initialize(objective, constraints)
|
476
489
|
@objective = objective
|
@@ -629,8 +642,9 @@ def optimize(optimization, objective, rows_c)
|
|
629
642
|
rows_c.each_index do |i|
|
630
643
|
row = rows_c[i]
|
631
644
|
rows[i].name = row.name
|
632
|
-
rows[i].set_bounds(Rglpk::GLP_UP,
|
633
|
-
rows[i].set_bounds(Rglpk::GLP_LO,
|
645
|
+
rows[i].set_bounds(Rglpk::GLP_UP, nil, row.upper_bound) unless row.upper_bound.nil?
|
646
|
+
rows[i].set_bounds(Rglpk::GLP_LO, nil, row.lower_bound) unless row.lower_bound.nil?
|
647
|
+
#rows[i].set_bounds(Rglpk::GLP_FR, row.lower_bound, row.upper_bound)
|
634
648
|
end
|
635
649
|
vars = rows_c.first.variable_coefficient_pairs
|
636
650
|
cols = p.add_cols(vars.size)
|
@@ -638,12 +652,15 @@ def optimize(optimization, objective, rows_c)
|
|
638
652
|
vars.each_index do |i|
|
639
653
|
column_name = vars[i].variable
|
640
654
|
cols[i].name = column_name
|
641
|
-
cols[i].set_bounds(Rglpk::GLP_LO, 0.0, 0.0)
|
642
655
|
cols[i].kind = vars[i].variable_type#boolean, integer, etc.
|
656
|
+
if [1,2].include? cols[i].kind
|
657
|
+
cols[i].set_bounds(Rglpk::GLP_FR, nil, nil)
|
658
|
+
end
|
643
659
|
if vars[i].variable_type != 1
|
644
660
|
solver = "mip"
|
645
661
|
end
|
646
662
|
end
|
663
|
+
lp.solver = solver
|
647
664
|
all_vars = rows_c.first.variable_coefficient_pairs.map{|vcp|vcp.variable}
|
648
665
|
obj_coefficients = OPL::Helper.coefficients(objective.gsub(" ","")).map{|c|c.to_f}
|
649
666
|
obj_vars = OPL::Helper.variables(objective.gsub(" ",""))
|
@@ -654,16 +671,18 @@ def optimize(optimization, objective, rows_c)
|
|
654
671
|
all_obj_coefficients << coef
|
655
672
|
end
|
656
673
|
p.obj.coefs = all_obj_coefficients
|
657
|
-
|
674
|
+
matrix = rows_c.map{|row|row.variable_coefficient_pairs.map{|vcp|vcp.coefficient.to_f}}.flatten
|
675
|
+
lp.matrix = matrix
|
676
|
+
p.set_matrix(matrix)
|
658
677
|
answer = Hash.new()
|
659
|
-
p.simplex
|
678
|
+
lp.simplex_message = p.simplex
|
660
679
|
if solver == "simplex"
|
661
680
|
lp.objective.optimized_value = p.obj.get + objective_addition.to_f
|
662
681
|
cols.each do |c|
|
663
682
|
answer[c.name] = c.get_prim.to_s
|
664
683
|
end
|
665
684
|
elsif solver == "mip"
|
666
|
-
p.mip
|
685
|
+
lp.mip_message = p.mip
|
667
686
|
lp.objective.optimized_value = p.obj.mip + objective_addition.to_f
|
668
687
|
cols.each do |c|
|
669
688
|
answer[c.name] = c.mip_val.to_s
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-09-
|
12
|
+
date: 2013-09-24 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: Built on top of the glpk gem for linear programming. The syntax is copied
|
15
15
|
from OPL Studio, which remains my favorite linear programming software, but the
|