在 minizinc 中使用 forall() 谓词作为没有“约束”的赋值语句

Max*_*wer 3 optimization scheduler mathematical-optimization minizinc

我有一个 Minizinc 程序,用于为并网电池生成最佳充电/放电时间表,给定一组时间间隔价格。

我的程序有效(有点;有一些注意事项),但我的问题是关于两个“约束”语句,它们实际上只是赋值语句:

constraint forall(t in 2..T)(MW_SETPOINT[t-1] - SALE[t] = MW_SETPOINT[t]);
constraint forall(t in 1..T)(PROFIT[t] = SALE[t] * PRICE[t]);
Run Code Online (Sandbox Code Playgroud)

这些只是平均能量SALES是在三角洲MW_SETPOINTt-11,并且PROFITSALE*PRICE每个间隔。因此,将它们声明为“约束”对我来说似乎违反直觉。但是我一直无法在不抛出语法错误的情况下将它们表述为赋值语句。

题:

  • 有没有更惯用的方法来为作为其他参数/​​变量的函数的数组声明这样的赋值语句?或者是在constraints 中为数组赋值是在 Minizinc 中推荐的/惯用的方法吗?

上下文的完整程序:

% PARAMS
int: MW_CAPACITY = 10;
array[int] of float: PRICE; 

% DERIVED PARAMS
int: STARTING_MW = MW_CAPACITY div 2;  % integer division
int: T = length(PRICE);

% DECISION VARIABLE - MW SETPOINT EACH INTERVAL
array[1..T] of var 0..MW_CAPACITY: MW_SETPOINT;

% DERIVED/INTERMEDIATE VARIABLES
array[1..T] of var -1*MW_CAPACITY..MW_CAPACITY: SALE;  
array[1..T] of var float: PROFIT;
var float: NET_PROFIT = sum(PROFIT);

% CONSTRAINTS
%% If start at 5MW, and sell 5 first interval, setpoint for first interval is 0 
constraint MW_SETPOINT[1] = STARTING_MW - SALE[1];  

%% End where you started; opt schedule from arbitrage means no net MW over time
constraint MW_SETPOINT[T] = STARTING_MW;            

%% these are really justassignment statements for SALE & PROFIT
constraint forall(t in 2..T)(MW_SETPOINT[t-1] - SALE[t] = MW_SETPOINT[t]);
constraint forall(t in 1..T)(PROFIT[t] = SALE[t] * PRICE[t]);

% OBJECTIVE: MAXIMIZE REVENUE
solve maximize NET_PROFIT;

output["DAILY_PROFIT: " ++ show(NET_PROFIT) ++ 
      "\nMW SETPOINTS: " ++ show(MW_SETPOINT) ++ 
      "\nMW SALES: " ++ show(SALE) ++
      "\n$/MW PRICES: " ++ show(PRICE)++
      "\nPROFITS: " ++ show(PROFIT)
      ]; 
Run Code Online (Sandbox Code Playgroud)

它可以运行

minizinc opt_sched_hindsight.mzn --solver org.minizinc.mip.coin-bc -D "PRICE = [29.835, 29.310470000000002, 28.575059999999997, 28.02416, 28.800690000000003, 32.41052, 34.38542, 29.512390000000003, 25.66587, 25.0499, 26.555529999999997, 28.149440000000002, 30.216509999999996, 32.32415, 31.406609999999997, 36.77642, 41.94735, 51.235209999999995, 50.68137, 64.54481, 48.235170000000004, 40.27663, 34.93675, 31.10404];"```
Run Code Online (Sandbox Code Playgroud)

Pat*_*tin 6

您可以使用Array Comprehensions :(引自文档)

数组推导式具有以下语法:

<array-comp> ::= "[" <expr> "|" <comp-tail> "]"
Run Code Online (Sandbox Code Playgroud)

例如(右侧的文字等价物):

[2*i | i in 1..5]       % [2, 4, 6, 8, 10]
Run Code Online (Sandbox Code Playgroud)

数组推导式比集合推导式具有更灵活的类型和 inst 要求(请参阅集合推导式)。

在有限类型的变量集上允许数组推导,结果是一个可选类型的数组,长度等于变量集上界的基数。例如:

var set of 1..5: x;
array[int] of var opt int: y = [ i * i | i in x ];
Run Code Online (Sandbox Code Playgroud)

数组的长度将为 5。

当 where-expression 为 a 时,允许使用数组推导式var bool。同样,结果数组是可选类型,长度等于生成器表达式给出的长度。例如:

var int x;
array[int] of var opt int: y = [ i | i in 1..10 where i != x ];
Run Code Online (Sandbox Code Playgroud)

数组的长度将为 10。

已评估的简单数组推导式的索引是隐式的1..n,其中n是已评估推导式的长度。

例子:

<array-comp> ::= "[" <expr> "|" <comp-tail> "]"
Run Code Online (Sandbox Code Playgroud)

输出:

[2*i | i in 1..5]       % [2, 4, 6, 8, 10]
Run Code Online (Sandbox Code Playgroud)

请注意,index_set(PRICE)不是别的,而是1..Tmin(index_set(PRICE))不是别的,但是1,这样一个可以写上述阵列内涵也为

var set of 1..5: x;
array[int] of var opt int: y = [ i * i | i in x ];
Run Code Online (Sandbox Code Playgroud)

  • @MaxPower 它们还可以通过将 1.D 数组转换为所需的 ND 维度来用于高阶数组。处理复杂数组生成器时,“if ... then ... else ... endif”和“let {} in ...”都可以在表达式内部使用。 (2认同)