Индексирование массива с помощью логического массива - PullRequest
1 голос
/ 15 мая 2019

Учитывая реальный массив (например, myArray) и логический массив (например, myMask), я хотел бы иметь:

  • если myMask[i] == true, то myArray[i] = myValueTrue
  • если myMask[i] == false, то myArray[i] = myValueFalse

Это работает

model BooleanIndexing
  parameter Boolean myMask[3] = {false, true, true};
  parameter Boolean myMask_negated[3] = {true, false, false};
  Real myArray[3];
  parameter Real myValueTrue = 3.0;
  parameter Real myValueFalse = 5.0;
equation
  myArray[Modelica.Math.BooleanVectors.index(myMask)] = fill(myValueTrue, Modelica.Math.BooleanVectors.countTrue(myMask));
  myArray[Modelica.Math.BooleanVectors.index(myMask_negated)] = fill(myValueFalse, Modelica.Math.BooleanVectors.countTrue(myMask_negated));
end BooleanIndexing;

но это не

model BooleanIndexing
  parameter Boolean myMask[3] = {false, true, true};
  parameter Boolean myMask_negated[3] = not myMask;
  Real myArray[3];
  parameter Real myValueTrue = 3.0;
  parameter Real myValueFalse = 5.0;
equation
  myArray[Modelica.Math.BooleanVectors.index(myMask)] = fill(myValueTrue, Modelica.Math.BooleanVectors.countTrue(myMask));
  myArray[Modelica.Math.BooleanVectors.index(myMask_negated)] = fill(myValueFalse, Modelica.Math.BooleanVectors.countTrue(myMask_negated));
end BooleanIndexing;

Единственная разница в том, как я инициализировал myMask_negated.

Ошибки в OpenModelica:

[BooleanIndexing: 9:3-9:139]: Illegal subscript Modelica.Math.BooleanVectors.index({myMask_negated[1], myMask_negated[2], myMask_negated[3]}) for dimensions 3 in component myArray[Modelica.Math.BooleanVectors.index(myMask_negated)].

[BooleanIndexing: 9:3-9:139]: Variable myArray[Modelica.Math.BooleanVectors.index(myMask_negated)] not found in scope BooleanIndexing.

Error occurred while flattening model BooleanIndexing

и в Дымола2018

Translation of BooleanIndexing:

Failed to expand myArray[Modelica.Math.BooleanVectors.index(myMask)].

Errors or failure to expand the equation:
myArray[Modelica.Math.BooleanVectors.index(myMask)] = fill(myValueTrue, Modelica.Math.BooleanVectors.countTrue(myMask));
Found in class BooleanIndexing, C:/workspace/modelica_vehicle/modelica_test/BooleanIndexing.mo at line 8.

Errors or failure to expand vector or matrix expressions.

Translation aborted.

Прямое логическое индексирование myArray[myMask], похоже, не является решением здесь. Я не могу понять, почему они терпят неудачу и есть ли более элегантные решения.

1 Ответ

2 голосов
/ 16 мая 2019

Обе ваши версии не гарантируют, что генерируется правильное количество уравнений. myValueTrue и myValueTrue_negated оба являются параметрами, поэтому пользователь может изменить значения векторов на нечто, не являющееся комплементарным.

Следовательно, я бы рекомендовал установить

final parameter Boolean myMask_negated[3] = not myMask;

но это также не работает, ни в Open Modelica, ни в Dymola.

Поэтому вместо этого я рекомендую удалить myMask_negated и использовать вместо него циклы. Либо с двумя отдельными:

model BooleanIndexing
  parameter Boolean myMask[3] = {false, true, true};
  Real myArray[3];
  parameter Real myValueTrue = 3.0;
  parameter Real myValueFalse = 5.0;
equation 
  for i in Modelica.Math.BooleanVectors.index(myMask) loop
    myArray[i] = myValueTrue;
  end for;

  for i in Modelica.Math.BooleanVectors.index(not myMask) loop
    myArray[i] = myValueFalse;
  end for;

end BooleanIndexing;

или с одним циклом for, использующим конструктор массива, как показано здесь:

model BooleanIndexing2
  parameter Boolean myMask[3] = {false, true, true};
  Real myArray[3];
  parameter Real myValueTrue = 3.0;
  parameter Real myValueFalse = 5.0;
equation 

  myArray = {if value then myValueTrue else myValueFalse for value in myMask};

end BooleanIndexing2;
...