How to convert type of a variable when using JuMP - type-conversion

I am using Julia/JuMP to implement an algorithm. In one part, I define a model with continues variables and solve the linear model. I do some other calculations based on which I add a couple constraints to the model, and then I want to solve the same problem but with integer variables. I could not use convert() function as it does not take variables.
I tried to define the variable again as integer, but the model did not seem to consider it! I provide a sample code here:
m = Model()
#defVar(m, 0 <= x <= 5)
#setObjective(m, Max, x)
#addConstraint(m, con, x <= 3.1)
solve(m)
println(getValue(x))
#defVar(m, 0 <= x <= 1, Bin)
solve(m)
println(getValue(x))
Would you please help me do this conversion?

The problem is that the second #variable(m, 0 <= x <= 1, Bin) actually creates a new variable in the model, but with the same name in Julia.
To change a variable from a continuous to a binary, you can do
setcategory(x, :Bin)
to change the variable bounds and class before calling solve again.

In newer versions of JuMP, you need to use a different function than setcategory. The methods you are looking for are:
set_binary Add binary constraint to variable.
unset_binary Remove binary constraint from variable.
set_integer Add integer constraint to variable.
unset_integer Remove integer constraint from variable.
The documentation on this can be found here.

Related

Division by zero depending on parameter

I am using the FixedRotation component and get a division by zero error. This happens in a translated expression of the form
var = nominator/fixedRotation.R_rel_inv.T[1,3]
because T[1,3] is 0 for the chosen parameters:
n={0,1,0}
angle=180 deg.
It seems that Openmodelica keeps the symbolic variable and tries to be generic but in this case this leads to division by zero because it chooses to put T[1,3] in the denominator.
What are the modifications in order to tell the compiler that the evaluated values T[1,3] for the compilation shall be considered as if the values were hard coded? R_rel is internally in fixedRotation not defined with Evaluate=true...
Should I use custom version of this block? (when I copy paste the source code to a new model and set the parameters R_rel and R_rel_inv to Evalute=true then the simulation works without division by zero)...
BUT is there a modifier to tell from outside that a parameter shall be Evaluate=true without the need to make a new model?
Any other way to prevent division by zero?
Try propagating the parameter at a higher level and setting annotation(Evaluate=true) on this.
For example:
model A
parameter Real a=1;
end A;
model B
parameter Real aPropagated = 2 annotation(Evaluate=true);
A Ainstance(a=aPropagated);
end B;
I don't understand how the Evaluate annotation should help here. The denominator is obviously zero and this is what shall be in fact treated.
To solve division by zero, there are various possibilities (e.g. to set a particular value for that case or to define a small offset to denominator, you can find examples in the Modelica Standard Library). You can also consider the physical meaning of the equation and handle this accordingly.
Since the denominator depends on a parameter, you can also set an assert() to warn the user there is wrong parameter value.
Btw. R_rel_inv is protected and shall, thus, not be used. Use R_rel instead. Also, to deal with rotation matrices, usage of functions from Modelica.Mechanics.MultiBody.Frames is a preferrable way.
And: to use custom version or own implementation depends on your preferences. Custom version is maintained by the comunity, own version is in your hands.

Inequality indexing using optimization variables in MATLAB

Let the variables A and B be n x 1 doubles and c be a scalar. My goal is to sum the values in A corresponding to indices for which the optimization variable x is greater than B. I have written this up below:
x = optimvar('x',n); % Creates optimization variable
objfun = sum(x); % Creates objective function
constraint = sum(A(x>=B))>=c; % Constraint based on logical indexing
The third line in the code above returns an error message because optimization variables are not compatible with inequality indexing. Specifically, x>=B cannot be input as indexes into A. Is there a way around this? Or am I thinking about this the wrong way?
Thank you!
You need to use function handles for both, the objective function as well as the constraint-function:
objfun = #(var) sum(var);
constraint = #(var) sum(A(var>=B)) >= c;
In fact, for the objective function objfun, you may also use objfun = #sum. This is a function handle. You can think of it as a pointer or reference to a certain function. Function, which work with one input can be used directly (with #). The optimizer calls the function and uses the optimization variable as input.
Now, if you have multiple inputs, you need to create a function, where you define all inputs but one. For this, you create an anonymous function handle, where you tell the handle what variables are placed where: #(var) sum(A(var>=B)) >= c. The variable var is the changing input and the other variables A, B, and c are taken from the workspace at the point of definition (i.e. the function handle is unaffected if you change the variables later or even delete them).

not equal constraint for an array of var float decision variables in minizinc

I have a model that needs to constrain each element of a var float array to be alldifferent
I tried to use the global alldifferent global constraint but I get the following error:
MiniZinc: type error: no function or predicate with this signature found: `alldifferent(array[int] of var float)'
So I replaced the alldifferent constraint with the following comprehension:
constraint forall (i,j in 1..nVERTICIES where i<j) (X[i] != X[j]);
but now I get the following error when I use the Geocode solver:
Error: Registry: Constraint float_lin_ne not found
and the following error when I use the G12 MIP solver:
flatzinc: error: the built-in operation `float_lin_ne/3' is not supported by the MIP solver backend.
Is there a different way I can encode this constraint?
For your first problem: acording to the official documentation, MiniZinc does not support alldifferent float. Only ints are supported.
For your second problem and third problem: Your solvers does not seam to support floats. Maybe you are not using the letest solvers and/or latest MiniZinc?
Another better solution is to convert your float problem into a integer problem. Just map your floating point range to a integer range instead.
As some of the other responses have mentioned there's not (to my knowledge) an alldifferent for floats.
Your expression of this global constraint as a series of binary inequalities is a valid approach however the issue you are encountering is a reflection of the difficulty of determining whether two floats are different (which is a broader issue that isn't just limited to CP modelling).
One solution you could do is to compare the absolute difference between your variables and enforce that this must be greater than some configurable value.
int: nVERTICES = 10;
float: epsilon = 0.001; % the minimum floats need to be apart to be considered not equal.
array[1..nVERTICES] of var -10.0..10.0: X;
constraint forall (i, j in 1..nVERTICES where i < j) (abs(X[i] - X[j]) >= epsilon);
solve satisfy;
output [ show(X) ];
Notice also that I've set a domain on X rather than just declaring it as a float. I was experiencing as an Gecode: Float::linear: Number out of limits until I switched to specifying the domain explicitly.

Linear programming constraints: multiplication of optimization variables

Given an optimization problem with two optimization variables (x_in(t), x_out(t)). For any time-step, when x_in is non-zero, x_out must be zero (and vice versa). Written as a constraint:
x_in(t)*x_out(t)=0
How can such a constraint be included in Matlab's linprog function?
Since the problem is not entirely linear, I do not believe you can solve it as-is using the linprog function. However, you should be able to reformulate the problem as a mixed integer linear programming problem. Then you would be able to use for example this extension from Matlab Central to solve the problem.
Assuming that x_in(t) and x_out(t) are non-negative variables with upper bounds x_in_max and x_out_max, respectively, then you can add the variables y_in(t) and y_out(t) to your optimization problem and include the following constraints:
(1) y_in(t) and y_out(t) are binary, i.e. 0 or 1
(2) x_in(t) <= x_in_max * y_in(t)
(3) x_out(t) <= x_out_max * y_out(t)
(4) y_in(t) + y_out(t) = 1
Given that y_in and y_out are binary variables, constraints (2) and (3) relate the x_ and y_ variables with each other and ensure that the x_ variables remain within bounds (fix bounds on the x_ variables can thus and should be removed from the problem formulation). Constraint (4) ensures that either the _in or the _out event occurs, but not both at the same time.

Can you explain this Embedded MATLAB Function error?

I'm having a problem sending a value from a GUI to an Embedded MATLAB Function (EMF) in a Simulink model. I get this value from a slider in my GUI and send it to an EMF block in my model. I can confirm that the value is being transferred correctly from my GUI to my Simulink block, since I can display the value with a display block in my model and see the value change when I change the slider position in my GUI. However I keep getting this error when I run my model:
Could not determine the size of this expression.
Function 'Kastl' (#18.282.283), line 14, column 1:
"f"
This is part of my EMF block code:
function y = input_par(u,fstart)
...
f_end = 1000;
f = fstart:f_end;
...
I believe MikeT is correct: you can't redefine the size of a variable in an embedded function. If you look at this Embedded MATLAB Function documentation page under the subsection Defining Local Variables, it says:
Once you define a variable, you cannot
redefine it to any other type or size
in the function body.
You will have to rework your embedded function such that the variables you declare are not changing size. Since I don't know what you are subsequently doing with the variable f, there's not much more specific help I can give you.
In general, if you absolutely need to use data that changes size, one solution is to pad the data with "garbage" values in order to maintain a constant size. For example:
MAX_ELEMS = 1000; % Define the maximum number of elements in the vector
f = [fstart:MAX_ELEMS nan(1,fstart-1)]; % Create vector and pad with NaNs
In the above example, the variable f will always have 1000 elements (assuming the value of fstart is an integer value less than or equal to 1000). The value NaN is used to pad the vector to the appropriate constant size. Any subsequent code would have to be able to recognize that a value of NaN should be ignored. Depending on what calculations are subsequently done in the embedded function, different pad values might be needed in place of NaN (such as 0, negative values, etc.).
I believe the issue you are running into is that you can't change a parameter during simulation that will cause the dimension of a signal to change. In your example, the code,
f = fstart:f_end;
changes size whenever fstart changes. I think this is what EMF block is complaining about. I don't have any easy workaround for this particular issue, but maybe there's an equivalent way of doing what you want that avoids this issue.