Вложенный выходной цикл Minizinc

Я пытаюсь написать оператор вывода с вложенными циклами и нетривиальным выводом на внешних уровнях. Если бы в Minizinc была команда верхнего уровня for, я бы сделал что-то вроде

for (f in Foo) (
  output(["Foo: ", f])
  for (b in Bar) (
    for (q in Quz) (
      output([myArray[f,b,q], " "]);
    )
    output(["\n"]);
  )
  output(["\n"]);
)

так что если

myArray = [[[1,2], [3,4]], [[5,6], [7,8]]];

это будет выводить

Foo: 1
1 2
3 4

Foo: 2
5 6
7 8

Думаю, я могу сделать это с помощью чего-то вроде

output(if (b = 1 /\ q = 1) then "Foo: " ++ show(f) else "" endif ++
       show(myArray[f,b,q] ++ " " ++
       if (<maximum q>) <newline> ++
       if (<maximum q and maximum b>) <newline>
       | f in Foo, b in Bar, q in Quz);

но это кажется неудобным (и моя первая попытка не увенчалась успехом).

Я видел Minizinc, вложенный для цикла, который отличается, потому что весь вывод находится внутри внутреннего самая петля. Мне также нужен вывод во внешних циклах.

Я думаю, что более четкая версия принятого ответа была бы

output [
  "Foo: \(f)\n"
  ++ concat(
       concat([show(myArray[f,b,q]) ++ " " | q in Quz])
         ++ "\n"
       | b in Bar])
  ++ "\n"
| f in Foo];

Это позволяет избежать конструкции if / then / else и дает понять, что мы добавляем дополнительный вывод до / после каждого внутреннего цикла.


person Troy Daniels    schedule 22.11.2017    source источник


Ответы (1)


Как вы уже сказали: выходные данные MiniZinc могут быть немного неудобными. Оператор вывода состоит из ключевого слова output, за которым следует массив строк. Во многих случаях мы хотели бы использовать цикл for, но в декларативном языке, таком как MiniZinc, такая структура потока управления недоступна.

Однако вы уже предложили решение: понимание массива! Кажется, вы почти у цели, но ваш синтаксис был немного неправильным, и вы могли не понимать, как они на самом деле работают. Понимание массива похоже на цикл for в том, что он выполняет итерацию по всем значениям в наборе. Однако он отличается тем, что он не просто выполняет операторы в цикле, но и оценивает их, и все результаты должны быть одного типа, в данном случае - строки.

Записываемый вами оператор вывода может быть записан следующим образом:

output [
  "Foo: \(f)\n"
  ++ concat(["\(myArray[f,b,q])"
    ++ if q == max(Quz
      then "\n"
      else " "
    endif
  |b in Bar, q in Quz])
  ++ "\n"
| f in Foo];
person Dekker1    schedule 22.11.2017
comment
Ах! Мне не удалось понять, что вы можете использовать concat для вложения понятий. - person Troy Daniels; 23.11.2017
comment
concat значительно упрощает работу, мы можем делать то же самое и без нее, но это значительно упрощает работу. - person Dekker1; 23.11.2017
comment
concat тоже спас мне день - person Panos Kal.; 25.11.2017