GLPSOL Problem within the Operation Research field - glpk

For a couple of months now, I am trying to solve an operational research model with glpk on a mac. The thing is that I have searched throughout the internet and also I have tried to find help in universities based in Athens Greece but it seems that noone has a clue regarding the specific program. So, my MODEL is the following:
#PARAMETERS
#
param P;
param D;
param S;
param R;
param B;
param LS;
param CLNGs;
param Tp;
param H;
param Frest;
param MA;
param f;
param Cvr {1..B};
param Cvf {1..B};
param Vv {1..B};
param Qv {1..B};
param Demand {1..R};
param d {1..P, 1..D};
# VARIABLES
#
var z{1..B} >=0, integer;
var x{1..P,1..R,1..B,1..S,1..D} >=0, continuous;
var y{1..P,1..B,1..R,1..S,1..D} >=0, integer;
# OBJECTIVE FUNCTION
#
minimize F {p<>m}: sum {p in 1..P} sum {m in 1..D}
sum {v in 1..B}Cf[v]*d[p,m]*y[p,m,v] + H* sum {v in 1..B} Cr[v]*z[v] +
sum {s in 1..S} sum {r in 1..R} sum {v in 1..B} CLNG[s]*Q[v]*x[s,r,v];
# CONSTRAINTS
#
s.t. constr1 {r in 1..R, r<>p, r<>m }: sum {p in 1..P}
sum {v in 1..B}Q[v]*x[p,r,v] - sum{m in 1..D}
sum{v in 1..B}Q[v]*x[r,m,v] >=Demand[r];
s.t. constr2 {p in 1..P, r in 1..R, v in 1..B}: y[p,r,v] >= x[p,r,v];
s.t. constr3 { r in 1..R, v in 1..B}:
sum {p in 1..P} x[p,r,v] >= sum {m in 1..D} x[r,m,v];
s.t. constr4 { p in 1..P, v in 1..B, p<>m}:
sum {m in 1..D} y[m,p,v] = sum {m in 1..D} y[p,m,v];
s.t. constr5 {v in 1..B, p<>m}: H*z[v] >= 1/V[v] *sum{p in 1..P}
sum{m in 1..D} d[p,m]*y[p,m,v] +
sum{p in 1..P}*(T[p]*sum{m in 1..D}y[p,m,v]);
s.t. constr6 {p in 1..P, r in 1..R, v in 1..B}:
Q[v]*y[p,r,v] <= Frest*y[p,r,v];
s.t. constr7 {v in 1..LS, i<>j}: sum {i in 1..R}
sum {j in 1..R} x[i,j,v] = 0;
s.t. constr8 {s in 1..S}: sum {r in 1..R}
sum {v in 1..V} Q[v]*x[s,r,v] <= MA[s];
s.t. constr9 {s in 1..S, r in 1..R}: x[s,r,v] >= f*y[s,r,v];
end;
And my DATA:
#test comments
param P := 7;
param D := 7;
param S := 3;
param R := 4;
param B := 4;
param LS := 2;
param CLNGs := 200;
param Tp := 24;
param H := 30;
param Frest := 1000000000
param MA := 10000000000
param f :=0.8
param Cvr : 1 :=
1 510000
2 600000
3 700000
4 900000
;
param Cvf : 1 :=
1 22
2 26
3 32
4 42
;
param Vv : 1 :=
1 24
2 26
3 28
4 30
;
param Qv : 1 :=
1 5000
2 7500
3 10000
4 15000
;
param Demand : 1 :=
1 2595.9
2 3781.2
3 1668
4 372.9
;
param d: 1 2 3 4 5 6 7:=
1 0 1663 996 306 291 333 372
2 1663 0 2413 1867 1905 1856 2050
3 996 2413 0 924 938 761 1103
4 306 1867 924 0 107 202 110
5 291 1905 938 107 0 122 184
6 333 1856 761 202 122 0 302
7 372 1050 1103 110 184 302 0
;
end;
When I am trying to run this i get always the following error:
thesis.mod:29: syntax error in variable statement
Context: ..... P , 1 .. R , 1 .. B , 1 .. S , 1 .. D } >= 0 ,continuous
MathProg model processing error
Do you have any ideas on how to solve this?

There is no 'continuous' attribute defined in the var statement of the GMPL language. Variables are by default continuous.
Please, read doc/gmpl.pdf that comes with GLPK.

Related

Fibonacci sequence less than 1000 in R

I'm trying to print the Fibonacci Sequence less than 1000 using while loop in R.
So far,
fib <- c(1,1)
counter <-3
while (fib[counter-1]<1000){
fib[counter]<- fib[counter-2]+fib[counter-1]
counter = counter+1
}
fib
I have this code. Only the first two numbers are given: 1,1. This is printing:
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
How do I fix my code to print only less than 1000?
Instead of checking the value of the last element wrt 1000, for the expected output you should be checking the sum of the last two elements as so.
fib <- c(1,1)
counter <-3
while (fib[counter-2]+fib[counter - 1]<1000){
fib[counter]<- fib[counter-2]+fib[counter-1]
counter = counter+1
}
fib
The issue with your approach is when the condition (fib[counter-1]<1000) in while loop is FALSE you have already added the number in fib which is greater than 1000.
You could return fib[-length(fib)] to remove the last number or check the number before inserting the number in fib.
fib <- c(1,1)
counter <-3
while (TRUE){
temp <- fib[counter-2] + fib[counter-1]
if(temp < 1000)
fib[counter] <- temp
else
break
counter = counter+1
}
fib
#[1] 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
You could change the while condition to sum the last 2 answers instead of just the last one:
fib <- c(1,1)
counter <-3
while (sum(fib[counter - 1:2]) < 1000){
fib[counter]<- fib[counter-2]+fib[counter-1]
counter = counter+1
}
fib
#> [1] 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
Or just get rid of counter completely:
fib <- c(1,1)
while (sum(fib[length(fib) - 0:1]) < 1000) fib <- c(fib, sum(fib[length(fib) - 0:1]))
fib
#> [1] 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

How to switch between radians and degrees in SAS

just looking for an easy way to run trig functions in SAS without having to manually correct in each calculation. Below is what I am working with.
I am running this in SAS 9 probably, the SAS Studio Student Module but this is a general SAS question.
I have manually created a variable, 'rad' in the 'calc' data step to deal with this but it adds a step of complexity that I would like to avoid.
I am asking whether there is a system setting, alternate trig function or ... ? that would change the calculation from:
bh_x = cos(rad*bh_a)*bh_l ;
to:
bh_x = cos(bh_a)*bh_l ;
so I don't have to manually convert my angle in degrees to radians for the trig function to work.
Thanks to anyone reading this and putting any mental effort to the solution!
Tim
data spec ;
length
b2h_a 8
b2h_l 8
b2h_l_e 8
bike $ 8
name $ 16
;
input
bike $
name $
bh_a
bh_l
ht_a
spcr
st_h
st_a
st_l
hb_r
hb_a
;
datalines ;
srcn (0,0) 0 0 67 0 0 0 0 0 0
srcn c 41 658 71.5 27 40 25 120 100 13
srcn ne_27_n13 41 658 71.5 27 40 27 127 100 13
srcn ne_15_0 41 658 71.5 15 40 27 127 100 0
srcn ne_5_0 41 658 71.5 5 40 27 127 100 0
srcn ne_2_n9 41 658 71.5 2 40 27 127 100 9
srcn ne_5_10 41 658 71.5 5 40 27 127 100 -10
srcn ne_10_rf10 41 658 71.5 10 40 27 127 20 -10
srcn max 41 658 90 250 0 0 250 0 0
;
run ;
data calc ;
set spec ;
pi=constant('pi') ;
rad=pi/180 ;
bh_x = cos(rad*bh_a)*bh_l ;
bh_y = sin(rad*bh_a)*bh_l ;
sr_x = (cos(rad*ht_a)*(spcr+st_h/2))*-1 ;
sr_y = sin(rad*ht_a)*(spcr+st_h/2);
st_x = cos(rad*(90-ht_a+st_a))*st_l ;
st_y = sin(rad*(90-ht_a+st_a))*st_l ;
hb_x = cos(rad*(90-hb_a))*hb_r*-1 ;
hb_y = sin(rad*(90-hb_a))*hb_r ;
hd_x = bh_x + sr_x + st_x + hb_x ;
hd_y = bh_y + sr_y + st_y + hb_y ;
if hd_x=0 then do ;
b2h_a=0 ;
b2h_l=0 ;
end ;
else do ;
b2h_a = atan(hd_y/hd_x)/rad ;
b2h_l = hd_y/sin(b2h_a*rad) ;
end ;
b2h_l_e = b2h_l/25.4 ;
drop pi rad ;
format
b2h_a 5.
b2h_l 5.
b2h_l_e 5.
bh_a 5.
bh_l 5.
ht_a 5.
spcr 5.
st_h 5.
st_a 5.
st_l 5.
hb_r 5.
hb_a 5.
bh_x 5.
bh_y 5.
sr_x 5.
sr_y 5.
st_x 5.
st_y 5.
hb_x 5.
hb_y 5.
hd_x 5.
hd_y 5.
b2h_a 5.
b2h_l 5.
b2h_l_e 5.1
;
run ;
There are no trig functions in SAS that accept DEGREE or GRADIAN arguments. You always need to convert from your data's angular measurement system to RADIAN.
You can write a macro to perform the conversion. Example:
%macro cosD(theta);
%* theta is angle in degrees;
%* emit data step source code that performs conversion from degrees to radians;
cos(&theta*constant('PI')/180)
%mend;
In use:
data calc ;
set spec ;
bh_x = %cosD(bh_a) * bh_l ;
You could convert the angular data to radians during the step where input occurs and then not have to worry about it again.

Rolling queue size

I want to calculate number of items waiting or queued over. Let's say, I have fixed capacity of 102 item/hour and different incoming items for 9 hours.
as data table:
dt<-data.table(hour = c(1,2,3,4,5,6,7,8,9),
incoming = c(78,102,115,117,105,99,91,80,71),
capacity = rep(102,9))
I want to calculate queued items in each period.
In 1 and 2 capacity is enough and queue is 0.
In 3, 13 items are queued
In 4, 15+13 backlogged items are queued.
In 6, there were 31 backlogged items and 3 items are deducted so 28 were queued.
I have tried several options but could not figure out how to calculate.
Result should be:
Explicit looping in R won't get you far, and I don't see a vectorized solution for this, but this is trivial to solve using Rcpp:
library(Rcpp)
cppFunction("NumericVector queue(NumericVector x) {
NumericVector res(x.size());
res[0] = std::max<double>(0, x[0]);
for (int i = 1, size = x.size(); i < size; ++i) {
res[i] = std::max<double>(0, res[i-1] + x[i]);
}
return res;
}")
dt[, queued := queue(incoming - capacity)][]
# hour incoming capacity queued
#1: 1 78 102 0
#2: 2 102 102 0
#3: 3 115 102 13
#4: 4 117 102 28
#5: 5 105 102 31
#6: 6 99 102 28
#7: 7 91 102 17
#8: 8 80 102 0
#9: 9 71 102 0
I'd create a separate function to get queued number like #sebastian-c did, but with #R.S. 's logic. Like this
get_queue <- function(x){
n <- length(x)
y <- c(max(0, x[[1]]), rep(0, n - 1))
for(i in 2:n){
y[i] <- max(0, y[i - 1] + x[i])
}
y
}
And then
dt[,incoming_capacity := incoming - capacity]
dt[,queued := get_queue(incoming_capacity)]
Another alternative:
require(data.table)
dt<-data.table(hour = c(1,2,3,4,5,6,7,8,9),
incoming = c(78,102,115,117,105,99,91,80,71),
capacity = rep(102,9))
dt$incoming_capactity<- dt$incoming-dt$capacity
dt$carriedover<- 0
dt$carriedover[1]<- max(0,dt$incoming_capactity[1]) #added
for( i in 2:length(dt$carriedover)) {
dt$carriedover[i]<- max(0,dt$incoming_capactity[i] + dt$carriedover[i-1])
}
dt

IF "OR" multiple conditions

I have a standard 2x2 table
Yes No
Yes a b
No c d
I want to create a condition whereby IF(a or b or c or d = 0) then 0.5 is added on to each of the cells a,b,c,d.
I have tried this:
if(a && b && c && d == 0){
a=a+0.5, b=b+0.5, c=c+0.5, d=d+0.5
}
But I am getting an error saying
Error: unexpected ',' in:
"if(a && b && c && d== 0){
a=a+0.5,"
i.e. I don't think it is letting me put multiple things to execute.
Also I don't think that the && is right between each of the letters as I believe that means IF(a and b and ...)
UPDATE TO QUESTION:
I have another related question.
If I have say a set of say n tables, all in the format:
Yes No
Yes a b
No c d
and if one of the a,b,c or d in any of the n tables is equal to zero then 0.5 is added on to each of the a,b,c,d for all of the n tables. How would I do that?
My list looks like the following:
n11 n12 n21 n22
1 188 1157 173 1168
2 2 201 1 101
3 369 2280 354 2289
4 1 61 0 61
5 1306 16870 1333 16773
6 4 81 3 79
7 6 117 5 118
8 19 334 15 318
9 1 49 0 48
10 0 36 1 33
11 2 114 3 113
12 13 433 37 696
13 1 64 0 65
14 4 157 1 160
15 1 42 0 43
16 1 150 5 146
17 7 1124 10 1117
18 2 78 2 77
and what I am trying to say is that if any of the aspects of the cells of the table are 0, then I want 0.5 to be added on to every cell.
In R you can't use , to separate line, but you can use ;.
Also, the way you are doing considers a,b and c are boolean (TRUE/FALSE), which is not the case as they are numbers. Your condition should be :
if (a == 0 || b == 0 || c == 0 || d == 0)
Note that your code will run nevertheless, even if a,b and c are not boolean since they are numbers and there is an equivalence between FALSE and a == 0. This means you could also write your condition as :
if (!a || !b || !c || !d)
For the UPDATE, I consider matList is the list of matrices :
for (ii in 1:length(matList())) {
if (any(matList[[ii]] == 0)) {
matList = lapply(matList, function(X){X+0.5})
break # Exit the for loop
}
}
lapply applies mat + 0.5 (i.e + 0.5 to each element of the matrix thanks to R sugar) to every element (here matrices) of the list matList and returns the resulting list.
The problem is with the commas that separate your variables. R syntax does not allow you to do it. Write it this way:
if (a && b && c && d == 0){
a=a+0.5
b=b+0.5
c=c+0.5
d=d+0.5
}
Another problem is that the behaviour you described does not match with your code. If you write && it means and, not or. If you want to check if each element is equal to 0, you should write the following:
Modified based on Rodrigo's comment, the correct code would be:
if (0 %in% c(a,b,c,d)){
a=a+0.5
b=b+0.5
c=c+0.5
d=d+0.5
}

Normalizing the values in a data table using the values stored in another data table

I am trying to normalize the values in a data table (dt) using the baseline values stored in another data table (dt.base). Next you have a sample contents of these tables and the code to generate that example:
> dt
Bench Config Part Power
1: A 10 P 171
2: A 10 Q 125
3: A 100 P 139
4: A 100 Q 109
5: B 10 P 196
6: B 10 Q 101
7: B 100 P 157
8: B 100 Q 176
> dt.base
Bench Config Part Power
1: A Base P 187
2: A Base Q 104
3: B Base P 166
4: B Base Q 188
Example generation code:
set.seed(13)
dt <- data.table(
Bench = c(rep('A', 4), rep('B', 4)),
Config = rep(c(10, 10, 100, 100), 2),
Part = rep(c('P', 'Q'), 4),
Power = round(runif(8, 100, 200)))
dt.base <- data.table(
Bench = c(rep('A', 2), rep('B', 2)),
Config = c('Base', 'Base', 'Base', 'Base'),
Part = rep(c('P', 'Q'), 2),
Power = round(runif(4, 100, 200)))
The idea would be to divide all the values in dt by their corresponding values in dt.base. Therefore, the table would become:
Bench Config Part Power
1: A 10 P 171 / 187
2: A 10 Q 125 / 104
3: A 100 P 139 / 187
4: A 100 Q 109 / 104
5: B 10 P 196 / 166
6: B 10 Q 101 / 188
7: B 100 P 157 / 166
8: B 100 Q 176 / 188
I thought the solution for this was quite straightforward, but I am running into some issues. This is my current attempt:
normalize.power <- function(pwr, base.pwr) {
pwr / base.pwr
}
dt.norm <- dt[,
Power <- normalize.power(
.SD, dt.base[Bench == Bench & Config == 'Base' & Part == Part,
'Power', with = F]
), by = list(Bench, Config, Part)]
The problem is that normalize.pwr is not receiving a single value in its second parameter (base.pwr), but rather a vector containing all the power values in dt.base. However, when I directly execute from the command line
dt.base[Bench == 'A' & Config == 'Base' & Part == 'P', 'Power', with = F]
then I obtain a single power value, as expected.
I would appreciate any help that solves my problem or leads me to the solution.
You can try something like this
setkey(dt, Bench, Part)
setkey(dt.base, Bench, Part)
dt[dt.base, Power := Power / i.Power]
dt
## Bench Config Part Power
## 1: A 10 P 0.91444
## 2: A 100 P 0.74332
## 3: A 10 Q 1.20192
## 4: A 100 Q 1.04808
## 5: B 10 P 1.18072
## 6: B 100 P 0.94578
## 7: B 10 Q 0.53723
## 8: B 100 Q 0.93617
Thanks #Arun for the useful i.Power syntax

Resources