Variable in lower/upper bound error AMPL - ampl

I have a problem when I try to make a sum with variable limits, when i execute
in AMPL, it returns the error "Variable in Lower Bound" and "Variable in Upper Bound" in the final line, but I really don't get it, thats the exact idea of using min and max! WTF
thanks a lot
var Y{i in Dias,j in Bloques} binary;
var B{i in Dias,j in Bloques}= Y[i,j]*j;
var L{i in Dias}=min{n in Bloques}if B[i,n]>0 then B[i,n];
var M{i in Dias}=max{n in Bloques}if B[i,n]>0 then B[i,n];
#this line gives error
var V{i in Dias}= sum{z in (L[i]..M[i])}1-Y[i,z];

You can't use decision variables to specify the range bounds a and b in a..b (L[i]..M[i] in your code). If the range bounds are known in advance rather than as an outcome of an optimization process, then you should use parameters instead of variables.
param L{i in Dias} = ...
param M{i in Dias} = ...
Otherwise you'll have to reformulate your model.

Related

Pyomo: Unbounded objective function though bounded

I am currently implementing an optimization problem with pyomo and since now some hours I get the message that my problem is unbounded. After searching for the issue, I came along one term which seems to be unbounded. I excluded this term from the objective function and it shows that it takes a very high negative value, which supports the assumption that it is unbounded to -Inf.
But I have checked the problem further and it is impossible that the term is unbounded, as following code and results show:
model.nominal_cap_storage = Var(model.STORAGE, bounds=(0,None)) #lower bound is 0
#I assumed very high CAPEX for each storage (see print)
dict_capex_storage = {'battery': capex_battery_storage,
'co2': capex_co2_storage,
'hydrogen': capex_hydrogen_storage,
'heat': capex_heat_storage,
'syncrude': capex_syncrude_storage}
print(dict_capex_storage)
>>> {'battery': 100000000000000000, 'co2': 100000000000000000,
'hydrogen': 1000000000000000000, 'heat': 1000000000000000, 'syncrude': 10000000000000000000}
From these assumptions I already assume that it is impossible that the one term can be unbounded towards -Inf as the capacity has the lower bound of 0 and the CAPEX is a positive fixed value. But now it gets crazy. The following term is has the issue of being unbounded:
model.total_investment_storage = Var()
def total_investment_storage_rule(model):
return model.total_investment_storage == sum(model.nominal_cap_storage[storage] * dict_capex_storage[storage] \
for storage in model.STORAGE)
model.total_investment_storage_con = Constraint(rule=total_investment_storage_rule)
If I exclude the term from the objective function, I get following value after the optimization. It seems, that it can take high negative values.
>>>>
Variable total_investment_storage
-1004724108.3426505
So I checked the term regarding the component model.nominal_cap_storage to see the value of the capacity:
model.total_cap_storage = Var()
def total_cap_storage_rule(model):
return model.total_cap_storage == sum(model.nominal_cap_storage[storage] for storage in model.STORAGE)
model.total_cap_storage_con = Constraint(rule=total_cap_storage_rule)
>>>>
Variable total_cap_storage
0.0
I did the same for the dictionary, but made a mistake: I forgot to delete the model.nominal_cap_storage. But the result is confusing:
model.total_capex_storage = Var()
def total_capex_storage_rule(model):
return model.total_capex_storage == sum(model.nominal_cap_storage[storage] * dict_capex_storage[storage] \
for storage in model.STORAGE)
model.total_capex_storage_con = Constraint(rule=total_capex_storage_rule)
>>>>
Variable total_capex_storage
0.0
So my question is why is the term unbounded and how is it possible that model.total_investment_storage and model.total_capex_storage have different solutions though both are calculated equally? Any help is highly appreciated.
I think you are misinterpreting "unbounded." When the solver says the problem is unbounded, that means the objective function value is unbounded based on the variables and constraints in the problem. It has nothing to do with bounds on variables, unless one of those variable bounds prevents the objective from being unbound.
If you want help on above problem, you need to edit and post the full problem, with the objective function, and (if possible) the error. What you have now is a collection of different snippets of different variations of a problem, which isn't really informative on the overall issue.
I solved the problem by setting a lower bound to the term, which takes a negative value:
model.total_investment_storage = Var(bounds=(0, None)
I am still not sure why this term can take negative values but this solved at least my problem

Assign a Seq(Seq) into arrays

What is it the correct syntax to assign a Seq(Seq) into multiple typed arrays without assign the Seq to an scalar first? Has the Seq to be flattened somehow? This fails:
class A { has Int $.r }
my A (#ra1, #ra2);
#create two arrays with 5 random numbers below a certain limit
#Fails: Type check failed in assignment to #ra1; expected A but got Seq($((A.new(r => 3), A.n...)
(#ra1, #ra2) =
<10 20>.map( -> $up_limit {
(^5).map({A.new( r => (^$up_limit).pick ) })
});
TL;DR Binding is faster than assignment, so perhaps this is the best practice solution to your problem:
:(#ra1, #ra2) := <10 20>.map(...);
While uglier than the solution in the accepted answer, this is algorithmically faster because binding is O(1) in contrast to assignment's O(N) in the length of the list(s) being bound.
Assigning / copying
Simplifying, your non-working code is:
(#listvar1, #listvar2) = list1, list2;
In Raku infix = means assignment / copying from the right of the = into one or more of the container variables on the left of the =.
If a variable on the left is bound to a Scalar container, then it will assign one of the values on the right. Then the assignment process starts over with the next container variable on the left and the next value on the right.
If a variable on the left is bound to an Array container, then it uses up all remaining values on the right. So your first array variable receives both list1 and list2. This is not what you want.
Simplifying, here's Christoph's answer:
#listvar1, #listvar2 Z= list1, list2;
Putting the = aside for a moment, Z is an infix version of the zip routine. It's like (a physical zip pairing up consecutive arguments on its left and right. When used with an operator it applies that operator to the pair. So you can read the above Z= as:
#listvar1 = list1;
#listvar2 = list2;
Job done?
Assignment into Array containers entails:
Individually copying as many individual items as there are in each list into the containers. (In the code in your example list1 and list2 contain 5 elements each, so there would be 10 copying operations in total.)
Forcing the containers to resize as necessary to accommodate the items.
Doubling up the memory used by the items (the original list elements and the duplicates copied into the Array elements).
Checking that the type of each item matches the element type constraint.
Assignment is in general much slower and more memory intensive than binding...
Binding
:(#listvar1, #listvar2) := list1, list2;
The := operator binds whatever's on its left to the arguments on its right.
If there's a single variable on the left then things are especially simple. After binding, the variable now refers precisely to what's on the right. (This is especially simple and fast -- a quick type check and it's done.)
But that's not so in our case.
Binding also accepts a standalone signature literal on its left. The :(...) in my answer is a standalone Signature literal.
(Signatures are typically attached to a routine without the colon prefix. For example, in sub foo (#var1, #var2) {} the (#var1, #var2) part is a signature attached to the routine foo. But as you can see, one can write a signature separately and let Raku know it's a signature by prefixing a pair of parens with a colon. A key difference is that any variables listed in the signature must have already been declared.)
When there's a signature literal on the left then binding happens according to the same logic as binding arguments in routine calls to a receiving routine's signature.
So the net result is that the variables get the values they'd have inside this sub:
sub foo (#listvar1, #listvar2) { }
foo list1, list2;
which is to say the effect is the same as:
#listvar1 := list1;
#listvar2 := list2;
Again, as with Christoph's answer, job done.
But this way we'll have avoided assignment overhead.
Not entirely sure if it's by design, but what seems to happen is that both of your sequences are getting stored into #ra1, while #ra2 remains empty. This violates the type constraint.
What does work is
#ra1, #ra2 Z= <10 20>.map(...);

Summation iterated over a variable length

I have written an optimization problem in pyomo and need a constraint, which contains a summation that has a variable length:
u_i_t[i, t]*T_min_run - sum (tnewnew in (t-T_min_run+1)..t-1) u_i_t[i,tnewnew] <= sum (tnew in t..(t+T_min_run-1)) u_i_t[i,tnew]
T is my actual timeline and N my machines
usually I iterate over t, but I need to guarantee the machines are turned on for certain amount of time.
def HP_on_rule(model, i, t):
return model.u_i_t[i, t]*T_min_run - sum(model.u_i_t[i, tnewnew] for tnewnew in range((t-T_min_run+1), (t-1))) <= sum(model.u_i_t[i, tnew] for tnew in range(t, (t+T_min_run-1)))
model.HP_on_rule = Constraint(N, rule=HP_on_rule)
I hope you can provide me with the correct formulation in pyomo/python.
The problem is that t is a running variable and I do not know how to implement this in Python. tnew is only a help variable. E.g. t=6 (variable), T_min_run=3 (constant) and u_i_t is binary [00001111100000...] then I get:
1*3 - 1 <= 3
As I said, I do not know how to implement this in my code and the current version is not running.
TypeError: HP_on_rule() missing 1 required positional argument: 't'
It seems like you didn't provide all your arguments to the function rule.
Since t is a parameter of your function, I assume that it corresponds to an element of set T (your timeline).
Then, your last line of your code example should include not only the set N, but also the set T. Try this:
model.HP_on_rule = Constraint(N, T, rule=HP_on_rule)
Please note: Building a Constraint with a "for each" part, you must provide the Pyomo Sets that you want to iterate over at the begining of the call for Constraint construction. As a rule of thumb, your constraint rule function should have 1 more argument than the number of Pyomo Sets specified in the Constraint initilization line.

Gnuplot summation issue

I am trying to make a plot of a simple mutation accumulation process on a binary tree...
My technical problem in gnuplot, is that is that I want to plot the possibility of getting 2 mutations on a specific lineage on the graph, here is the equation which determines it:
P_{2 mutation} = sum[k=0:n] (m/(2**(k+1)/(1-(1/2)**k)))(1-exp(-muk))
(dont bother with the formula im not sure that this is the correct one yet :))
where n is the number of levels of the binary tree, mu is the mutation rate, and m is the number of previously randomly thrown mutations onto the graphs edges...
I want to make a plot which is this possibility depending on the levels of the binary tree...
Therefore I wrote a script which is something like this:
set term pngcairo size 800,600
set title "Két mutáció megjelenésének valószínűsége, egy n szintű bináris fa egyik sejtvonalában"
set xlabel"szintek száma (n)"
set ylabel"Két mutáció megjelenésének valószínűsége (P_{2^{lin})"
set xrange[1:10]
set yrange[0:1]
set output '2mutvalsz.png'
set multiplot
do for[i=1:10]{
mu = 0.1+(i*0.1)
m = 4
f(x)=(x/((2**(x+1))*(1-(0.5)**x)))
if(m<floor(f(x)))
{
p(x)=sum [k=0:floor(x)](m*(1/((2**(x+1))*(1-(0.5)**x))))*(1-exp(-mu*k))
}
else
{
p(x)=1
}
plot p(x) lt i lw 1
}
unset multiplot
set output
So my problem is, that I dont know if it is correct to do what I do in the
if statement...
What I want is to behold the statement m< f(x) where f(x) is the number of edges in respect of n, which is an integer value therefore I use floor(f(x)), and sum through the x values (which are the number of levels what has to be an integer too... so floor(x), like a heavyside function to make the x axis discrete) in the sum...
And also I get an error message:
gnuplot> load '2mutvalsz.plt'
line 27: undefined variable: x
where line 27 is the end of the do for loop...
So my question is that is it a correct way to make a summation integer the x values and of course why I get the error message...
Thank you, and I hope everything is clear...
The error message is produced because the if statement in your script is interpreted when Gnuplot loads the script - it tries to evaluate the condition of the if statement and since the variable x is not defined, it produces the mentioned message.
You could put everything together using the ternary operator as:
p(x)=( m<floor(f(x)) )?( sum [k=0:floor(x)](m*(1/((2**(x+1))*(1-(0.5)**x))))*(1-exp(-mu*k)) ):1;
However, since the function f(x) is on the imposed x-range of [0,1] less than 1, the condition m<floor(f(x)) will be always false.

Error due to variable size data in Simulink Matlab function block

I'm working with the Simulink block MATLAB FUNCTION and I'm having problems with the bounds of the variables that I define in there.
This is the part of the code where I’m getting troubles
function P_S1_100= fcn(SOC_S1_100,S1_AGENTS_10,time_CAP_100)
assert(time_CAP_100(1)<100)
tcharging_a1_1=[0:0.05:time_CAP_100(1)]
tcharging_a1_2=[time_CAP_100(1):0.05:time_CAP_100(1)*2]
tcharging_a1=[0:0.05:time_CAP_100(1)]
(Where time_CAP_100 is a vector [1x6])
And this is the error that I'm getting:
Computed maximum size of the output of function 'colon' is not bounded.
Static memory allocation requires all sizes to be bounded.
The computed size is [1 x :?].
Function 'Subsystem1/Slow Charge/S1/MATLAB Function5' (#265.262.302), line 8, column 16:
"[time_CAP_100(1):0.05:time_CAP_100(1)*2]"
Could anyone give me an idea of how to solve this error?
Thanks in advance.
For each of your variable-size data inputs/outputs, you need to define what the upper bound is. See http://www.mathworks.co.uk/help/simulink/ug/declare-variable-size-inputs-and-outputs.html for more details.
Only work around I can think of is to manually write a loop with fixed loop bounds to expand [time_CAP_100(1):0.05:time_CAP_100(1)*2]. That expression is what is causing the problem. You need to know the bounds of this vector. Then you can write a loop something like
% max_size is the maximum length possible for tcharging_a1_2
tcharging_a1_2 = zeros(1,max_size);
tcharging_a1_2(1) = time_CAP_100(1);
for ii=2:max_size
if tcharging_a1_2(ii) < time_CAP_100(1)*2
tcharging_a1_2(ii) = tcharging_a1_2(ii) + .05;
end
end