Doptima
Doptima

Reputation: 191

Received Error - "Number out of limits" on Minizinc modelling language

I am trying to create a model in Minizinc but get the following error:

Error: Gecode: Float::linear: Number out of limits

I am using Minizinc version "2.2.3" and solver "Geocode 6.1.0".

Can anyone explain why I get this error? Is there an error in the model or the solver?

This code is trying to optimize a battery, maximizing the revenue generated.

The constraints describe how much the battery can discharge/charge in a time period and how much energy

Here is the code:

%enumerators
enum ACTION = {charging, discharging, no_action};

%paramters
int: Num_intervals;
float: start_battery_state;
float: battery_max_charge;
float: battery_max_discharge;
float: battery_max_storage;
float: battery_min_storage;
array[int] of float: charge_prices;
array[int] of float: discharge_prices;

%sets
set of int: TIME = 1..Num_intervals;
set of int: TIME2 = 2..Num_intervals;

%variables
array[TIME] of var -4.0..4.0: battery_activity;
array[TIME] of var float: battery_state;
array[TIME] of var ACTION: choice;
array[TIME] of var float: revenue_generated;
var float: total_revenue = sum(t in TIME)(revenue_generated[t]);

%constraints - determining battery state - cannot go below min or above max
constraint battery_state[1] = start_battery_state;
constraint forall(t in TIME2)(battery_state[t] = battery_state[t-1] + battery_activity[t]);
constraint forall(t in TIME2)(battery_state[t] >= battery_min_storage);
constraint forall(t in TIME2)(battery_state[t] <= battery_max_storage);

%constraints - if charging, calculate revenue/cost using charge_prices
%if discharging, calculate revenue/cost using discharge prices

constraint forall(t in TIME)(if choice[t] = charging then revenue_generated[t] = -battery_activity[t] * charge_prices[t] 
                                elseif choice[t] = discharging then revenue_generated[t] = battery_activity[t] * discharge_prices[t]
                                else revenue_generated[t] = 0 endif);


%setting the the choice variable (charging, discharging, no-action)         
%depending on battery activity
constraint forall(t in TIME)(if battery_activity[t] > 0 then choice[t] = charging  
                             elseif battery_activity[t] < 0 then choice[t] = discharging 
                             else choice[t] = no_action endif);



solve maximize total_revenue;

I am using the following input file:

% number of time intervals
Num_intervals = 5;

start_battery_state = 8.0;

battery_max_charge = 4.0;

battery_max_discharge = -4.0;

battery_min_storage = 0.0;

battery_max_storage = 7.0;

%charge_efficiency = 0.85;

%discharge_efficiency = 1.0;

charge_prices = [35.0,20.0,60.0,-5.0,20.0];

discharge_prices = [35.0,20.0,60.0,-5.0,20.0];

Upvotes: 2

Views: 1477

Answers (2)

Magnus &#197;hlander
Magnus &#197;hlander

Reputation: 1446

If that is an option, you could modify the type of all the float parameters to int. The type of the variables battery_activity and battery_state is also changed to int and the domains are adjusted by multiplying the bounds by a factor F. In the output section the variables are transformed back.

int: F = 100;

%variables
array[TIME] of var -F*4..F*4: battery_activity;
array[TIME] of var F*min([battery_min_storage, start_battery_state])..F*max([battery_max_storage, start_battery_state]): battery_state;
array[TIME] of var ACTION: choice;
array[TIME] of var int: revenue_generated;
var int: total_revenue = sum(t in TIME2)(revenue_generated[t]);

%constraints - determining battery state - cannot go below min or above max
constraint battery_state[1] = F * start_battery_state;

constraint forall(t in TIME2)(battery_state[t] = battery_state[t-1] + battery_activity[t]);
constraint forall(t in TIME2)(battery_state[t] >= F * battery_min_storage);
constraint forall(t in TIME2)(battery_state[t] <= F * battery_max_storage);

%constraints - if charging, calculate revenue/cost using charge_prices
%if discharging, calculate revenue/cost using discharge prices

constraint forall(t in TIME2)(
    revenue_generated[t] = 
        (battery_activity[t] > 0) * (-battery_activity[t] * charge_prices[t]) +
        (battery_activity[t] < 0) * (battery_activity[t] * discharge_prices[t]));

solve
maximize total_revenue;

output ["total_revenue = ", show(total_revenue / F), ";\n" ] ++
["revenue_generated = ", show([revenue_generated[t] / F | t in TIME2]), ";\n" ] ++
["battery_state = ", show([battery_state[t] / F | t in TIME]), ";\n" ] ++
["battery_activity = ", show([battery_activity[t] / F | t in TIME2]), ";\n" ] ++
["choice = ", show([if battery_activity[t] > 0 then charging elseif battery_activity[t] < 0 then discharging else no_action endif| t in TIME2]), ";\n" ]

Seems to work well with OsiCBC for the given data.

Upvotes: 0

Dekker1
Dekker1

Reputation: 5786

This is an error from the Gecode solver. Gecode only has limited support for the Float variables, the error is thrown to indicate that one of the domains of the floating point variables is out of the range that Gecode can support.

As the comments indicate, constraint programming solvers are generally not the best solvers when your model contains floating point variables. Instead you might want to try a solver that is based on Mixed Integer Programming. The MiniZinc bundle includes OsiCBC and has support for Gurobi and CPLEX, these solver would most likely be better at solving your model.

Upvotes: 1

Related Questions