Моделирование логической головоломки

1

Я пытаюсь смоделировать логическую головоломку из "Перемешать пересмешника". Я изо всех сил пытаюсь перевести это на SMT-LIB. Головоломка выглядит примерно так:

Есть сад, в котором все цветы красного, желтого или синего цветов, и все цвета представлены. Для любых трех цветов, которые вы выберете, по крайней мере, один будет красным, а другой - желтым. Третий цветок всегда будет синим?

Я попытался смоделировать сад как Array Int Flower, но это не сработало, я думаю, потому что домен массива фиксирован, чтобы охватывать все целые числа. Z3 услужливо говорит мне, что это неудовлетворительно, CVC4 сразу возвращает неизвестное.

Единственное решение головоломки - это сад с ровно одним цветком каждого цвета, но как мне заставить решателя сказать мне это?

Это моя неудачная попытка:

(declare-datatypes () ((Flower R Y B)))
(declare-const garden (Array Int Flower))
(assert (forall ((a Int) (b Int) (c Int))
                (and (or (= (select garden a) R)
                         (= (select garden b) R)
                         (= (select garden c) R))
                     (or (= (select garden a) Y)
                         (= (select garden b) Y)
                         (= (select garden c) Y)))))
(check-sat)
Теги:
z3
z3py
smt
cvc4

1 ответ

2
Лучший ответ

Я думаю, что существует неявное предположение, что цветы всех трех цветов представлены в саду. Имея это в виду, вот как я мог бы написать кодирование с использованием интерфейсов Python и Haskell для Z3; потому что код на этих языках проще, чем непосредственно в SMTLib.

питон

from z3 import *

# Color enumeration
Color, (R, Y, B) = EnumSort('Color', ('R', 'Y', 'B'))

# An uninterpreted function for color assignment
col = Function('col', IntSort(), Color)

# Number of flowers
N = Int('N')

# Helper function to specify distinct valid choices:
def validPick (i1, i2, i3):
    return And( Distinct(i1, i2, i3)
              , 1 <= i1, 1 <= i2, 1 <= i3
              , i1 <= N, i2 <= N, i3 <= N
              )

# Helper function to count a given color
def count(pickedColor, flowers):
    return Sum([If(col(f) == pickedColor, 1, 0) for f in flowers])

# Get a solver and variables for our assertions:
s = Solver()
f1, f2, f3 = Ints('f1 f2 f3')

# There at least one flower of each color
s.add(Exists([f1, f2, f3], And(validPick(f1, f2, f3), col(f1) == R, col(f2) == Y, col(f3) == B)))

# You pick three, and at least one of them is red
s.add(ForAll([f1, f2, f3], Implies(validPick(f1, f2, f3), count(R, [f1, f2, f3]) >= 1)))

# You pick three, and at least one of them is yellow
s.add(ForAll([f1, f2, f3], Implies(validPick(f1, f2, f3), count(Y, [f1, f2, f3]) >= 1)))

# For every three flowers you pick, one of them has to be blue
s.add(ForAll([f1, f2, f3], Implies(validPick(f1, f2, f3), count(B, [f1, f2, f3]) == 1)))

# Find a satisfying value of N
print s.check()
print s.model()[N]

# See if there any other value by outlawing the choice
nVal = s.model()[N]
s.add(N != nVal)
print s.check()

При запуске это печатает:

sat
3
unsat

Способ чтения этого вывода состоит в том, что данные условия действительно выполняются, когда N=3; как вы пытались выяснить. Кроме того, если вы также утверждаете, что N не равно 3, то удовлетворяющая модель отсутствует, т.е. Выбор 3 навязывается заданными условиями. Я считаю, что это то, что вы хотели установить.

Я надеюсь, что код ясен, но не стесняйтесь просить разъяснений. Если вам это нужно в SMT-Lib, вы всегда можете вставить:

print s.sexpr()

перед вызовами s.check() и вы можете увидеть сгенерированный SMTLib.

Haskell

Также можно кодировать то же самое в Haskell/SBV. Посмотрите эту суть почти для буквального кодирования того же самого: https://gist.github.com/LeventErkok/66594d8e94dc0ab2ebffffe4fdabccc9 Обратите внимание, что решение Haskell может использовать преимущества конструкции allSat SBV (которая возвращает все удовлетворяющие предположения), и более просто показать, что N=3 является единственным решением.

  • 0
    Для второго теста, т. Е. Чтобы доказать гипотезу, не могли бы вы вместо этого проверить, является ли совокупность посылок и отрицание последнего утверждения неудовлетворительной? То есть s.add(Exists([f1, f2, f3], And(validPick(f1, f2, f3), count(B, [f1, f2, f3]) == 0)))
  • 1
    @DmitriChubarov Это просто произвело бы unsat для всех значений N поскольку это противоречило бы самой первой аксиоме, что есть цветок любого цвета. Конечно, это было бы правдой, но на самом деле это не имело бы смысла, и из этого нельзя сделать какой-либо вывод.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню