def snakes_find_the_head(g):
    # We'll want a type that represents a cell in the grid. We use a datatype because we can make it a sum type -
    # that is, its 0-arity constructors represent a closed enumeration of distinct objects.
    Cell = Datatype("Cell")

    for x, y in g.coords():
        if g.snake(x, y) is not None:
            Cell.declare("cell_{}_{}".format(x, y))
    Cell = Cell.create()

    # We'll have two functions that we explicitly declare. One is the short-distance "connected" relationship.
    # The other is a convenience function for turning the coordinates of a cell into the datatype member that
    # represents that position.
    Connected = Function("Connected", Cell, Cell, BoolSort())
    XYToCell = Function("XYToCell", IntSort(), IntSort(), Cell)

    cell = {}
    for x, y in g.coords():
        if g.snake(x, y) is not None:
            cell[x, y] = getattr(Cell, "cell_{}_{}".format(x, y))
            g.add(XYToCell(x, y) == cell[x, y])

    # Two cells are connected *if and only* if they are adjacent and both hold snakes
    # We need to be really clear about the "and only if" part; a naive implementation here will let the
    # solver fill in other arbitrary values for `Connected` in order to make the desired outcome true.
    # We do this by ensuring there's a value declared for our Connected relationship between every pair
    # of potential arguments.

    for x1, y1 in g.coords():
        c1 = g.snake(x1, y1)
        if c1 is None:
            continue
        # If there's a snake here, the cell is connected to itself
        g.add(Connected(cell[x1, y1], cell[x1, y1]) == c1)
        for x2, y2 in g.coords():
            c2 = g.snake(x2, y2)
            if c2 is None or (x1, y1) == (x2, y2):
                continue
            if manh(x1, y1, x2, y2) == 1:
                g.add(Connected(cell[x1, y1], cell[x2, y2]) == And(c1, c2))
            else:
                # Without this, our function declaration is only partial. The solver can fill in missing values
                # in order to scupper our good intentions.
                g.add(Not(Connected(cell[x1, y1], cell[x2, y2])))

    # The transitive closure of Connectedness is Reaches
    Reaches = TransitiveClosure(Connected)

    # For every cell in the grid, if it's a snake then we can connect it to the head position
    hx, hy = g.head()
    for x, y in g.coords():
        c = g.snake(x, y)
        if c is None:
            continue

        g.add(Implies(c, Reaches(cell[x, y], XYToCell(hx, hy))))
Exemple #2
0
    def __init__(self, max_segs=None):
        self.corners_x = Function(f'seg_belt{self._IDX}_x', IntSort(), IntSort())
        self.corners_y = Function(f'seg_belt{self._IDX}_y', IntSort(), IntSort())
        self.num_segs = Const(f'seg_belt{self._IDX}_num_segs', IntSort())
        SOL.add(self.num_segs > 0)
        if max_segs:
            SOL.add(self.num_segs <= max_segs)

        i,j = Consts("i j", IntSort())
        SOL.add(ForAll([i], Implies(And(0 <= i, i < self.num_segs),
                                    Or(self.segment(i).horizontal(), self.segment(i).vertical()))))

        self.__class__._IDX += 1
Exemple #3
0
    def __init__(self):
        self.belt_x = Function(f'belt{self._IDX}_x', IntSort(), IntSort())
        self.belt_y = Function(f'belt{self._IDX}_y', IntSort(), IntSort())
        self.belt_len = Const(f'belt{self._IDX}_len', IntSort())
        SOL.add(self.belt_len > 0)

        i,j = Consts("i j", IntSort())
        # neighbor condition
        SOL.add(ForAll([i], Implies(And(i < self.belt_len - 1, i >= 0),
                                    neighs(self[i], self[i+1]))))

        # no intersections
        SOL.add(ForAll([i, j], Implies(And(i >= 0, i < j, j < self.belt_len),
                                       Not(self[i] == self[j]))))
        self.__class__._IDX += 1
Exemple #4
0
    def function(self, name, return_sort: z3.SortRef) -> z3.ExprRef:
        """Return a new function that receives all environment variables as arguments."""
        params = self._z3_sorts if self.forall_mode != ForallMode.FORALL_GLOBALS else []
        func = Function(name, params + [return_sort])

        # Registering types for faster apply.
        if str(return_sort) == "Real":
            Ref = RatNumRef
        elif str(return_sort) == "Int":
            Ref = IntNumRef
        else:
            assert str(return_sort) == "Bool"
            Ref = BoolRef
        self._function_types[func.get_id()] = Ref

        return func
Exemple #5
0
 def declare_predicate(self, elem_predicate: Predicate):
     arg_types = [
         x.get_engine_obj(self._name)
         for x in elem_predicate.get_arg_types()
     ]
     arg_types += [BoolSort()]
     rel = Function(elem_predicate.get_name(), *arg_types)
     self._solver.register_relation(rel)
     elem_predicate.add_engine_object(rel)
    def add_observation_constraints(self, s, planner, ground_actions, length,
                                    observations):
        obsSort = DeclareSort('Obs')
        orderObs = Function('orderObs', obsSort, IntSort())
        orderExec = Function('orderExec', obsSort, IntSort())
        obsConsts = []
        for i in range(0, len(observations)):
            o = Const(str(observations[i]), obsSort)
            obsConsts.append(o)
            s.add(orderObs(o) == i)

        for t in range(0, length):
            # forced_obs = []
            for action in ground_actions:
                index = observations.index_of(action.signature())
                if index > -1:
                    obsC = obsConsts[index]
                    # forced_obs.append(planner.action_prop_at(action, t))
                    s.add(
                        Implies(planner.action_prop_at(action, t),
                                orderExec(obsC) == t))
            # s.add(Or(*forced_obs))

        x = Const('x', obsSort)
        y = Const('y', obsSort)
        # orderSync = Function('order-sync', BoolSort())
        s.add(
            ForAll([x, y],
                   Implies(
                       orderObs(x) < orderObs(y),
                       orderExec(x) < orderExec(y))))
        s.add(
            ForAll([x, y],
                   Implies(
                       orderObs(x) == orderObs(y),
                       orderExec(x) == orderExec(y))))
        s.add(
            ForAll([x, y],
                   Implies(
                       orderObs(x) > orderObs(y),
                       orderExec(x) > orderExec(y))))
Exemple #7
0
## Qui a tué le chat?

from z3 import Function, EnumSort, BoolSort, ForAll, Solver, Implies, Const, Consts, Exists, Not, And, Or

# type et ses constantes
Entity, (jack, luna, curiosity) = EnumSort('Entity',
                                           ('jack', 'luna', 'curiosity'))

Animal = Function('Animal', Entity, BoolSort())
Aimer = Function('Aimer', Entity, Entity, BoolSort())
Tuer = Function('Tuer', Entity, Entity, BoolSort())

s = Solver()
x, y, z = Consts('x y z', Entity)
# Tous ceux qui aiment tous les animaux sont aimés par qqun
s.add(
    ForAll(
        x,
        Implies(ForAll(y, Implies(Animal(y), Aimer(x, y))),
                Exists(z, Aimer(z, x)))))

# Quiconque tue un animal n’est aimé par personne
s.add(
    ForAll(
        x,
        Implies(Exists(y, And(Animal(y), Tuer(x, y))),
                ForAll(z, Not(Exists(z, Aimer(z, x)))))))
# Jack aime tous les animaux
s.add(ForAll(x, Implies(Animal(x), Aimer(jack, x))))
# C’est soit Jack soit Curiosité qui a tué le chat appelé Luna
s.add(Or(Tuer(jack, luna), Tuer(curiosity, luna)))
Exemple #8
0
# functions - on these domains.
# So, first we declare two enum 'sorts'. In Z3 a 'sort' is like a type.
# EnumSort thus is a sort of enumerable many values. In this case, Knight,
# Knave, and Spy.

# The first is the name (Role) followed by a tuple of all values.
Role, (Knight, Knave, Spy) = EnumSort('Role', ('Knight', 'Knave', 'Spy'))

# Same for Person. Values A, B, C.
Person, (A,B,C) = EnumSort('Person', ('A', 'B', 'C'))

# Now, what we want to do is reconstruct who is who based on puzzle
# statements as predicates.
# Let's declare a function R which gives the role of a person.
# This is a function which maps from Person to Role:
R = Function('R', Person, Role)

# As you can see we have just declared a function - there's no 
# 'implementation' or code. This because if we know how to encode
# this function, the problem would be solved! (We would know who was
# who.) In fact, the function R is the unknown quantity, this is what
# our solver will reconstruct. So it is an unknown!

# But, as it is a z3 function, we can go ahead and write predicates
# using it. For example, R(A) != R(B)  would encode that the role of A cannot be
# the same as the role of B.

# In fact, the first general constraint of the game - that there is always one
# person of each sort - could be encoded in this manner:
# Saying "The role of A is not the same as the role of B, is not the same as role of C."
# Or in code as `And([R(A) != R(B), R(B) != R(C), R(C) != R(A)])`
Exemple #9
0
def new_interpretation():
    return Function('interpretation', Variable, Node)
Exemple #10
0
import sys

from z3 import Const, DeclareSort, Function, Solver

print("""
S = DeclareSort('S')       # Declare an uninterpreted sort S
f = Function('f', S, S)    # Declare function f : S -> S
x = Const('x', S)          # Declare constant x : S
""")
sys.stdin.readline()

S = DeclareSort('S')
f = Function('f', S, S)
x = Const('x', S)

print("""
s = Solver()               # Create a solver context
s.add(x == f(f(x)))        # Assert fact 1
s.add(x == f(f(f(x))))     # Assert fact 2
""")
sys.stdin.readline()

s = Solver()
s.add(x == f(f(x)))
s.add(x == f(f(f(x))))

print("""
print s                   # Print solver's state
""")
sys.stdin.readline()
print(">>", s)
Exemple #11
0
## Les dragons chinois

from z3 import Function, EnumSort, BoolSort, ForAll, Solver, Implies, Const, Consts, Exists, Not, And, Or

animal, (dragon) = EnumSort('animal', ('dragon'))
humain, (touriste) = EnumSort('humain', ('touriste'))

est_fort = Function('est_fort', animal, BoolSort())
souffler_feu = Function('souffler_feu', animal, BoolSort())

# Formaliser les phrases suivantes :

# Aucun dragon fort ne peut ne pas souffler le feu.

# Un dragon rusé a toujours des cornes.

# Aucun dragon faible n’a des cornes.

# Les touristes ne chassent que les dragons ne soufflant pas le feu.

# On veut répondre à la question suivante :
# Un dragon rusé doit-il craindre les touristes ? (autrement dit : est-il chassé ?)
"""
# Corrigé
from z3 import *
Dragon, (drago,) = EnumSort('Dragon', ('drago',))
fort = Function('fort',Dragon,BoolSort())
feu = Function('feu',Dragon,BoolSort())
ruse = Function('ruse',Dragon,BoolSort())
cornes = Function('cornes',Dragon,BoolSort())
chasse = Function('chasse',Dragon,BoolSort())
from z3 import Not, And, ForAll, Implies, IntSort, BoolSort, Solver, Function, Int

__counter = 100
__agents = {}


def new_noun(name):
    global __counter
    global __agents
    if name not in __agents:
        __agents[name] = __counter
        __counter += 1
    return Int(__agents[name])


IsKinase = Function("is_kinase", IntSort(), BoolSort())
IsActiveWhenPhosphorylated = Function("is_active_when_phosphorylated",
                                      IntSort(), BoolSort())

Phosphorylates = Function("phosphorylates", IntSort(), IntSort(), BoolSort())
Activates = Function("activates", IntSort(), IntSort(), BoolSort())

ActivityIncreasesActivity = Function("activity_increases_activity", IntSort(),
                                     IntSort(), BoolSort())

solver = Solver()

MEK1 = new_noun("MEK1")
ERK1 = new_noun("ERK1")
RAF = new_noun("RAF")
HRAS = new_noun("HRAS")
Exemple #13
0
def function(name, *sort):
    return Function(id_name(name), sort)
Exemple #14
0
    def __init__(self, name: str, max_num_vars: int):

        self.name = name
        self.input_range = randint(1, min(max_num_vars, 5))
        z3_input = [RealSort()] * self.input_range
        self.z3 = Function(name, *z3_input, RealSort())
Exemple #15
0
#!/usr/bin/env python

# from TU Graz presentation by Vedad Hadzic

from z3 import Solver, Int, IntSort, BoolSort, Function
from z3 import ForAll, And, Or, Not, Implies, sat as SAT

# create an integer and a function
x = Int("x")
f = Function("f", IntSort(), IntSort(), BoolSort())

solver = Solver()

solver.add(ForAll([x], Implies(And(x > 0, x < 4), f(x, x))))
solver.add(ForAll([x], Implies(Or(x <= 0, x >= 4), Not(f(x, x)))))

if solver.check() != SAT:
    exit(1)

m = solver.model()

print(f'f(0,0)={m.eval(f(0,0))}')
print(f'f(1,2)={m.eval(f(1,2))}')
print(f'f(2,3)={m.eval(f(2,3))}')
print(f'f(3,3)={m.eval(f(3,3))}')

for i in range(0, 5):
    # assert ∀ x in (0,4). f(x,x) = 1 # check if satisfiable
    # get the solution
    # print the relation table
    vs = [int(bool(m.eval(f(i, j)))) for j in range(0, 5)]
Exemple #16
0

# This represents a set of possible <graph, action> pairs -- a single Kappa
# chemical system or model.
Model = Datatype('Model')
Model.declare('model', ('pregraph', Graph), ('action', Action),
              ('postgraph', Graph))
Model = Model.create()

import collections
Submodel = collections.namedtuple('Submodel',
                                  ['pregraph', 'action', 'postgraph'])

# This represents a set of sets of <graph, action> pairs -- many possible
# chemical systems that an L statement could represent.
ModelSet = Function('possible_system', Model, BoolSort())

Variable = Datatype('Variable')
Variable.declare('variable', ('get_name', IntSort()))
Variable = Variable.create()


def new_thing_function(datatype, default_name):
    def new_thing(nickname=default_name):
        return Const(_collision_free_string(nickname), datatype)

    return new_thing


new_variable = new_thing_function(Variable, 'var')
new_graph = new_thing_function(Graph, 'graph')
Exemple #17
0
from z3 import EnumSort, Solver, Function, Const, sat
import itertools

R, values = EnumSort('R', ('alpha', 'beta', 'gamma'))

plus = Function('plus', R, R, R)
multiply = Function('multiply', R, R, R)

neutral_plus = Const('neutral_plus', R)
neutral_multiply = Const('neutral_multiply', R)

solver = Solver()

for a, b, c in itertools.product(values, repeat=3):
    # (R, +) is a commutative monoid with identity element 0:
    #     (a + b) + c = a + (b + c)
    #     0 + a = a + 0 = a
    #     a + b = b + a
    solver.add(plus(plus(a, b), c) == plus(a, plus(b, c)))
    solver.add(plus(neutral_plus, a) == a)
    solver.add(plus(a, neutral_plus) == a)
    solver.add(plus(a, b) == plus(b, a))

    # (R, ⋅) is a monoid with identity element 1:
    #     (a⋅b)⋅c = a⋅(b⋅c)
    #     1⋅a = a⋅1 = a
    solver.add(multiply(multiply(a, b), c) == multiply(a, multiply(b, c)))
    solver.add(multiply(neutral_multiply, a) == a)
    solver.add(multiply(a, neutral_multiply) == a)

    # Multiplication left and right distributes over addition:
Exemple #18
0
def new_modelset(nickname='modelset'):
    return Function(_collision_free_string(nickname), Model, BoolSort())
Exemple #19
0
}
dna_to_z3_enum_codon = {
    str_codon: z3_codon
    for str_codon, z3_codon in zip(triplet_dna_codons, z3_enum_codons)
}
dna_to_z3_enum_nuc = {
    str_nuc: z3nuc
    for str_nuc, z3nuc in zip(dNTPs, z3_enum_nucleotides)
}
rna_to_z3_enum_codon = {
    str_codon: z3_codon
    for str_codon, z3_codon in zip(triplet_rna_codons, z3_enum_codons)
}
amino_to_z3_enum_amino = {
    str_amino: z3_amino
    for str_amino, z3_amino in zip(aminoacids, z3_enum_aminos)
}
amino_to_z3_bv_amino = {
    str_amino: z3_bitvec_amino
    for str_amino, z3_bitvec_amino in zip(aminoacids, z3_bitvec_aminos)
}

# z3 Functions
f_nuc_to_codon = Function("nucleotides -> codons", NucleotideBitVecSort,
                          NucleotideBitVecSort, NucleotideBitVecSort,
                          CodonEnumSort)
f_codon_to_amino = Function("codons -> aminos", CodonEnumSort, AminoBitVecSort)
f_nuc_to_amino = Function("nucleotides -> aminos", NucleotideBitVecSort,
                          NucleotideBitVecSort, NucleotideBitVecSort,
                          AminoBitVecSort)
print(problem)

# declare finite data type mansion
MansionDT = Datatype("Mansion")
MansionDT.declare("Agatha")
MansionDT.declare("Butler")
MansionDT.declare("Charles")

# create finite sort Mansion
Mansion = MansionDT.create()

# constants for ease of reference
a, b, c = Mansion.Agatha, Mansion.Butler, Mansion.Charles

# declare predicates
killed = Function("killed", Mansion, Mansion, BoolSort())
hates = Function("hates", Mansion, Mansion, BoolSort())
richer = Function("richer", Mansion, Mansion, BoolSort())

# quantified variables
x = Const("x", Mansion)
y = Const("y", Mansion)

e1 = Exists([x], killed(x, a))
e2a = ForAll([x, y], Implies(killed(x, y), hates(x, y)))
e2b = ForAll([x, y], Implies(killed(x, y), Not(richer(x, y))))
e3 = ForAll([x], Implies(hates(a, x), Not(hates(c, x))))
e4a = hates(a, a)
e4b = hates(a, c)
e5 = ForAll([x], Implies(Not(richer(x, a)), hates(b, x)))
e6 = ForAll([x], Implies(hates(a, x), hates(b, x)))