Есть ли способ использовать range с Z3ints в z3py?

#z3py

#z3py

Вопрос:

Я относительно новичок в Z3 и экспериментирую с ним в python. Я закодировал программу, которая возвращает порядок, в котором выполняются различные действия, представленные числом. Z3 возвращает целое число, представляющее секунду начала действия.

Теперь я хочу взглянуть на модель и посмотреть, есть ли момент времени, когда ничего не происходит. Для этого я создал список, содержащий только 0, и я хочу изменить индекс во время выполнения каждого действия на 1. Например, если действие начинается на 5-й секунде и занимает 8 секунд для выполнения, индекс от 5 до 12 будет установлен равным 1. Выполнение этого со всеми действиями, а затем поиск 0 в списке, надеюсь, даст мне случаи, когда ничего не происходит.

Проблема в том, что я хотел бы написать что-то подобное для кодирования проблемы

 list_for_check = [0]*total_time
m = s.model()
for action in actions: 
    for index in range(m.evaluate(action.number) , m.evaluate(action.number)   action.time_it_takes):
        list_for_check[index] = 1
  

Но я получаю сообщение об ошибке:

 'IntNumRef' object cannot be interpreted as an integer
  

Я понял, что Z3 не возвращает обычные целые числа или bools в своих моделях, но пишет

 if m.evaluate(action.boolean):
  

работает, поэтому я предполагаю, что if каким-то образом перезаписан, но, похоже, это не относится к range. Итак, мой вопрос: есть ли способ использовать range с Z3 ints? Или есть другой способ сделать это?

Проблема также может заключаться в том, что action.time_it_takes является целым числом, и добавление Z3int с «обычным» int не работает. (Сделано во второй части диапазона).

Я также пробовал использовать int(m.evaluate(action.number)), но это не работает.

Заранее спасибо 🙂

Ответ №1:

При вызове evaluate он возвращает IntNumRef , которое является внутренним z3 представлением целого числа внутри z3. Вам нужно вызвать as_long() его метод, чтобы преобразовать его в число Python. Вот пример:

 from z3 import *

s = Solver()
a = Int('a')

s.add(a > 4);
s.add(a < 7);

if s.check() == sat:
    m = s.model()
    print("a is %s" % m.evaluate(a))
    print("Iterating from a to a 5:")
    av = m.evaluate(a).as_long()
    for index in range(av, av   5):
        print(index)
  

Когда я запускаю это, я получаю:

 a is 5
Iterating from a to a 5:
5
6
7
8
9
  

это именно то, чего вы пытаетесь достичь.

Метод as_long() определен здесь. Обратите внимание, что существуют аналогичные функции преобразования из битовых векторов и рациональных чисел. Вы можете выполнить поиск в API z3py, используя интерфейс по адресу: https://z3prover.github.io/api/html/namespacez3py.html

Комментарии:

1. Спасибо! Именно то, что мне было нужно!