opl 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/opl.rb +25 -14
- metadata +1 -1
data/lib/opl.rb
CHANGED
@@ -2,24 +2,29 @@ require "rglpk"
|
|
2
2
|
|
3
3
|
#TODO
|
4
4
|
#1.0
|
5
|
+
#object structure
|
5
6
|
|
6
|
-
#2.
|
7
|
-
#data arrays
|
7
|
+
#2.1
|
8
8
|
#setting variable values in constraints
|
9
9
|
#and then using that variable value in further constraints
|
10
|
-
#
|
11
|
-
|
10
|
+
#Look into fixed variables in the glp documentation
|
11
|
+
#2.2
|
12
12
|
#summing of variables
|
13
13
|
#e.g. x1 + x1 <= 3
|
14
|
-
#
|
14
|
+
#2.3
|
15
|
+
#allow a POSITIVE: x option or NEGATIVE: x
|
15
16
|
|
16
17
|
#3.0
|
17
|
-
#
|
18
|
+
#a matrix representation of the solution if using
|
19
|
+
#sub notation
|
20
|
+
#data arrays
|
21
|
+
|
22
|
+
#4.0
|
18
23
|
#make sure extreme cases of foralls and sums
|
19
24
|
#are handled
|
20
25
|
#multiple level sub notation e.g. x[1][[3]]
|
21
26
|
|
22
|
-
#
|
27
|
+
#5.0
|
23
28
|
#absolute value: abs()
|
24
29
|
#if --> then statements
|
25
30
|
#or statements
|
@@ -27,6 +32,8 @@ require "rglpk"
|
|
27
32
|
|
28
33
|
#write as module
|
29
34
|
|
35
|
+
$default_epsilon = 0.01
|
36
|
+
|
30
37
|
def sides(equation)
|
31
38
|
if equation.include?("<=")
|
32
39
|
char = "<="
|
@@ -284,12 +291,14 @@ class Row
|
|
284
291
|
attr_accessor :lower_bound
|
285
292
|
attr_accessor :upper_bound
|
286
293
|
attr_accessor :variable_coefficient_pairs
|
294
|
+
attr_accessor :epsilon
|
287
295
|
|
288
|
-
def initialize(name, lower_bound, upper_bound)
|
296
|
+
def initialize(name, lower_bound, upper_bound, epsilon)
|
289
297
|
@name = name
|
290
298
|
@lower_bound = lower_bound
|
291
299
|
@upper_bound = upper_bound
|
292
300
|
@variable_coefficient_pairs = []
|
301
|
+
@epsilon = epsilon
|
293
302
|
end
|
294
303
|
end
|
295
304
|
|
@@ -475,9 +484,9 @@ def produce_variable_type_hash(variable_types, all_variables)
|
|
475
484
|
variable_type_hash = {}
|
476
485
|
variable_types.each do |vt|
|
477
486
|
type = vt.gsub(" ","").split(":")[0]
|
478
|
-
if type == "
|
487
|
+
if type.downcase == "boolean"
|
479
488
|
type_number = 3
|
480
|
-
elsif type == "
|
489
|
+
elsif type.downcase == "integer"
|
481
490
|
type_number = 2
|
482
491
|
end
|
483
492
|
variables = vt.split(":")[1].gsub(" ","").split(",")
|
@@ -491,7 +500,9 @@ def produce_variable_type_hash(variable_types, all_variables)
|
|
491
500
|
variable_type_hash
|
492
501
|
end
|
493
502
|
|
494
|
-
def subject_to(constraints,
|
503
|
+
def subject_to(constraints, options=[])
|
504
|
+
variable_types = options.find_all{|option|option.downcase.include?("boolean") || option.downcase.include?("integer")} || []
|
505
|
+
epsilon = options.find_all{|option|option.downcase.include?("epsilon")}.first.gsub(" ","").split(":")[1].to_f rescue $default_epsilon
|
495
506
|
constraints = constraints.flatten
|
496
507
|
constraints = split_equals_a(constraints)
|
497
508
|
constraints = constraints.map do |constraint|
|
@@ -531,10 +542,10 @@ def subject_to(constraints, variable_types=[])
|
|
531
542
|
bound = value.split(">=")[1].to_f
|
532
543
|
upper_bound = (bound*-1).to_s
|
533
544
|
elsif value.include?("<")
|
534
|
-
upper_bound = (value.split("<")[1]).to_f -
|
545
|
+
upper_bound = (value.split("<")[1]).to_f - epsilon
|
535
546
|
elsif value.include?(">")
|
536
547
|
negate = true
|
537
|
-
bound = (value.split(">")[1]).to_f +
|
548
|
+
bound = (value.split(">")[1]).to_f + epsilon
|
538
549
|
upper_bound = (bound*-1).to_s
|
539
550
|
end
|
540
551
|
coefs = coefficients(sides(value)[:lhs])
|
@@ -549,7 +560,7 @@ def subject_to(constraints, variable_types=[])
|
|
549
560
|
end
|
550
561
|
vars = variables(sides(value)[:lhs])
|
551
562
|
zero_coef_vars = all_vars - vars
|
552
|
-
row = Row.new(name, lower_bound, upper_bound)
|
563
|
+
row = Row.new(name, lower_bound, upper_bound, epsilon)
|
553
564
|
row.constraint = constraint
|
554
565
|
coefs = coefs + zero_coef_vars.map{|z|0}
|
555
566
|
vars = vars + zero_coef_vars
|