Когда вы кодируете проблему, подобную этой, в SBV, производительность может влиять на два момента:
- SBV может потребоваться много времени для создания самого запроса
- SBV отправляет запрос солирующему штрафу, но решателю требуется много времени, чтобы ответить
Судя по вашему описанию, он кажется последним; но вы можете убедиться в этом, вызвав optimize
следующим образом:
optimizeWith z3{verbose=True} ...
Что это будет сделать, это напечатать взаимодействие SBV с бэкэнд-решателем. В какой-то момент вы увидите:
[SEND] (check-sat)
Это означает, что SBV выполнил свою работу и теперь ждет, когда решатель вернется с ответом. Запустите вашу программу еще раз с этой опцией. Если SBV не торопится, то вы не увидите вышеупомянутую строку [SEND] (check-sat)
, и об этом следует сообщить здесь как о проблеме SBV: https://github.com/LeventErkok/sbv/issues
Скорее всего, SBV отправляет штраф check-sat
, но решатель требует гораздо больше времени, чтобы ответить, когда вы используете SInt32
, а не SInteger
.
Если предположить, что это так, то Вероятно, это связано с тем, что решить проблему гораздо сложнее, если базовый тип - SInt32
. Вы делаете много арифметических действий c и просите, чтобы решатель максимизировал и минимизировал две отдельные цели. Вы можете себе представить, что если у вас есть неограниченные значения Integer
, с максимальным сложением чисел может быть легко справиться: с увеличением аргументов будет увеличиваться и их сумма. Но это не так для SInt32
: как только значения начнут переполняться, сумма будет намного ниже, чем аргументы из-за переноса. Таким образом, с модульной арифметикой c пространство поиска становится намного интереснее и намного больше по сравнению со случаем SInteger
. Суть в том, что, хотя SInt32
имеет конечное представление, проблема оптимизации по SInt32 x SInt32 x SInt32
(у вас есть три переменные) может быть намного сложнее из-за того, как работает арифметика c по сравнению с SInteger x SInteger x SInteger
. В частности, решение для SInt32
будет , а не обязательно будет таким же, как SInteger
, опять же из-за модульной арифметики c.
Конечно, что происходит за дверями внутри z3 скорее черный ящик, и, возможно, они неоправданно медленные. Если вы считаете, что это так, вы можете сообщить об этом людям z3. SBV может сгенерировать стенограмму, которую вы можете отправить им, когда используется следующим образом:
optimizeWith z3{transcript = Just "longRun.smt2"} ...
Это создаст файл longRun.smt2
в нотации SMTLib, который может быть передан в решатель вне Haskell экосистема. Вы можете отправить такую ошибку по адресу: https://github.com/Z3Prover/z3/issues, но имейте в виду, что файлы SMTLib, сгенерированные SBV, могут быть длинными и многословными: если вы можете уменьшить размер проблемы, все равно демонстрируя проблему, это будет полезно.