Z3 parte 1 – o Básico

Z3 É um Solver SMT escrito pela Microsoft: https://github.com/Z3Prover/z3

Pessoalmente, tive que usar o Z3 em vários desafios diferentes. Quando você precisa encontrar uma senha para um nome de usuário e a lógica é matemática, Z3 o ajudará a encontrar a senha

Abaixo está um vídeo que demonstra como realizar o processo:

Solver É uma espécie de extensão para-SAT Solver (satisfiability), SAT Solver Obtém um conjunto de condições e verifica se elas retornam True ou False. Se todas as condições retornarem True, um sinal de que temos uma solução para as condições obtidas.

SAT Funciona apenas com condições booleanas, o SMT faz o mesmo para todos os tipos de condições para que possamos escrever um exercício matemático padrão ou inserir nele algum problema que desejamos resolver para nós.

por exemplo:

(x > 1 OR y < 5) AND (x = 2 OR x = 3 and x = y) AND (y > 0 OR x>y)

Nosso software verificará todas as condições e chegará a uma solução, pegara na primeira linha a x > 1 Então, na segunda linha o

x = 3 and x = y E na terceira linha o y > 0 Tudo funciona, então a resposta é True.

Mas no caso de recebermos algo assim:

( x > 2*x, x > 0 )

Ficamos com unsat porque o exercício não pode ser resolvido, então quando trabalharmos com z3, primeiro verificaremos se o exercício pode ser resolvido usando o comando check() E só então vamos resolver-lo usando ()model O que parece assim.:

If solv.check() == sat:    solv.model()

Para instalar o z3, usaremos o seguinte comando:

pip install z3-solver

No Z3 primeiro temos que definir nossas variáveis usando INT, BitVec, Bool ou qualquer outra coisa dependendo do exercício, por exemplo, se quisermos resolver o próximo exercício facilmente sem realizar um teste:

x = Int('x') y = Int('y') solve(x > 2, y < 10, x + 2*y == 7)

É assim que realmente definimos x e y, que são números que correspondem ao exercício matemático que é colocado no solve e o resultado é:

[y = 0, x = 7]

Também é possível simplificar um exercício matemático atravez do comando simplify assim:

x = Int('x') y = Int('y') print simplify(x + y + 2*x + 4)

O resultado será uma simplificação do exercício matemático:

4 + 3*x + y

Ao definir um exercício matemático ele pode ser mantido em uma variável e então será possível trabalhar com ele da seguinte maneira:

x = Int('x') y = Int('y') n = x + y >= 3 print n print "num args: ", n.num_args() print "children: ", n.children() print "1st child:", n.arg(0) print "2nd child:", n.arg(1) print "operator: ", n.decl() print "op name: ", n.decl().name()

O resultado ficará assim:

Se quisermos que o resultado seja em números reais (números quebrados), Usaremos-Real:

x = Real('x') y = Real('y') solve(x**2 + y**2 == 3, x**3 == 2) set_option(precision=30) print "Solving, and displaying result with 30 decimal places" solve(x**2 + y**2 == 3, x**3 == 2)

O resultado:

Usamos aqui o comando.:

set_option(precision=30)

Então, basicamente definimos quantos dígitos queremos após o ponto, a ideia por trás de set_option é basicamente uma definição do ambiente do z3.
Se houver uma variável True ou False iremos defini-la dessa forma:

p = Bool('p') q = Bool('q') r = Bool('r') solve(r == Not(q), Or(Not(p), r))

E o resultado será assim.:

[q = True, p = False, r = False]

Se fizermos algum exercício matemático como você viu no vídeo e tentarmos resolvê-lo:

No total teremos que definir todas as nossas variáveis e as condições do exercício da seguinte maneira, primeiro vamos definir todas as nossas variáveis:

`from z3 import *

x1 = Int(“x1”)
x2 = Int(“x2”)
x3 = Int(“x3”)
x4 = Int(“x4”)
x5 = Int(“x5”)
x6 = Int(“x6”)
x7 = Int(“x7”)
x8 = Int(“x8”)
x9 = Int(“x9”)
`

Em seguida, definiremos um solver para que possamos colocar nossas regras nele e examiná-lo:

solv = Solver() solv.add(x1+13*x2/x3+x4+12*x5-x6-11+x7*x8/x9-10 == 66) solv.add(x1 > 0, x2 >0 ,x3 >0 ,x4 > 0,x5 >0 ,x6>0,x7>0,x8>8,x9>0)

Finalmente, verificaremos se o exercício pode ser resolvido usando o SAT Solver e pediremos ao z3 para resolver o exercício usandomodel-:

`if solv.check() == sat:
     print solv.model()
else:
     print “failed to solve”

`

O resultado ficará assim:

No próximo artigo, vou mostrar como você pode resolver o sudoku usando o z3 e até mesmo resolver um exercício de engenharia reversa que exige que deciframos qual é a senha usando z3, vale a pena esperar!

Compartilhe este post

Outros artigos que você pode ter interesse: