Полученная ошибка - «Число выходит за пределы» на языке моделирования Minizinc - PullRequest
0 голосов
/ 09 января 2019

Я пытаюсь создать модель в Minizinc, но получаю следующую ошибку:

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

Я использую версию Minizinc "2.2.3" и решатель "Geocode 6.1.0".

Может кто-нибудь объяснить, почему я получаю эту ошибку? В модели или в решателе есть ошибка?

Этот код пытается оптимизировать батарею, максимизируя полученный доход.

Ограничения описывают, сколько аккумулятор может разрядить / зарядить за определенный период времени и сколько энергии

Вот код:

%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;

Я использую следующий входной файл:

% 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];

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Если это опция, вы можете изменить тип всех параметров float на int. Тип переменных battery_activity и battery_state также изменяется на int, и домены корректируются путем умножения границ на коэффициент F. В разделе вывода переменные преобразованы обратно.

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" ]

Кажется, хорошо работает с OsiCBC для данных.

0 голосов
/ 10 января 2019

Это ошибка из решателя Gecode. Gecode имеет ограниченную поддержку только для переменных Float, выдается ошибка, указывающая, что один из доменов переменных с плавающей запятой находится вне диапазона, который может поддерживать Gecode.

Как показывают комментарии, решатели программирования с ограничениями обычно не являются лучшими решателями, когда ваша модель содержит переменные с плавающей запятой. Вместо этого вы можете попробовать решатель, который основан на смешанном целочисленном программировании. В комплект MiniZinc входит OsiCBC и поддержка Gurobi и CPLEX, эти решатели, скорее всего, будут лучше при решении вашей модели.

...