Strano comportamento durante il controllo del sabato Z3
Domanda
Qualcuno può vedere cosa sto facendo sbagliato .... Sto usando il quantificatore per creare questa due linee:
(assert(forall((t Task)) (not (mustPrecede t t))))
(assert(forall((t1 Task)(t2 Task)(t3 Task)) (implies (and (mustPrecede t1 t2)(mustPrecede t2 t3)) (mustPrecede t1 t3))))
.
Questo è il codice ..
Sort User = ctx.mkUninterpretedSort("User");
Sort Task = ctx.mkUninterpretedSort("Task");
//function declaration
FuncDecl assignUser = ctx.mkFuncDecl("assignUser", Task, User);
FuncDecl TaskUser = ctx.mkFuncDecl("TaskUser", new Sort[] { Task, User }, ctx.mkBoolSort());
FuncDecl mustPrecede = ctx.mkFuncDecl("mustPrecede", new Sort[]{Task,Task}, ctx.mkBoolSort());
//task for using in quatifiers
Expr task = ctx.mkConst("t",Task);
Expr user = ctx.mkConst("u",User);
// creating (assert(forall((t Task)) (not (mustPrecede t t))))
//just one task is needed
Sort[] Tasks = new Sort[1];
Tasks[0] = Task;
//setting the name for the task
Symbol[] namess = new Symbol[1];
namess[0] = ctx.mkSymbol("t");
//Creating a map between mustPrecede and its two parameters
Expr mtt = ctx.mkApp(mustPrecede, task,task);
//acreating not
Expr body = ctx.mkNot((BoolExpr)mtt);
Expr mustPrecedett = ctx.mkForall(Tasks, namess, body, 1, null, null,
ctx.mkSymbol("Q1"), ctx.mkSymbol("skid1"));
System.out.println("Quantifier mustPrecedett: " + mustPrecedett.toString());
//creating (assert(forall((t1 Task)(t2 Task)(t3 Task)) (implies (and (mustPrecede t1 t2)(mustPrecede t2 t3)) (mustPrecede t1 t3))))
//tree taks will be neede
Sort[] tTask = new Sort[3];
tTask[0] =Task;
tTask[1] =Task;
tTask[2] =Task;
//setting the names for the tasks
Symbol[] Tnames = new Symbol[3];
Tnames[0] = ctx.mkSymbol("t1");
Tnames[1] = ctx.mkSymbol("t2");
Tnames[2] = ctx.mkSymbol("t3");
//creating tree diferent tasks for the relations
Expr t1 = ctx.mkConst("t1",Task);
Expr t2 = ctx.mkConst("t2",Task);
Expr t3 = ctx.mkConst("t3",Task);
//creating mappins
Expr mt1t2 = ctx.mkApp(mustPrecede, t1,t2);
Expr mt2t3 = ctx.mkApp(mustPrecede, t2,t3);
Expr mt1t3 = ctx.mkApp(mustPrecede, t1,t3);
//Creating the relation between them
Expr tbody2= ctx.mkImplies(ctx.mkAnd((BoolExpr)mt1t2,(BoolExpr) mt2t3), (BoolExpr) mt1t3);
//building quatifier
Expr tra = ctx.mkForall(tTask, Tnames, tbody2, 1, null, null,ctx.mkSymbol("Q1"), ctx.mkSymbol("skid1"));
.
Allora sto aggiungendo sia al risolutore come segue:
// creating (assert(forall((t Task)) (not (mustPrecede t t))))
solver.add(ctx.mkForall(Tasks, namess, body, 1, null, null,ctx.mkSymbol("Q1"), ctx.mkSymbol("skid1")));
//creating (assert(forall((t1 Task)(t2 Task)(t3 Task)) (implies (and (mustPrecede t1 t2)(mustPrecede t2 t3)) (mustPrecede t1 t3))))
solver.add(ctx.mkForall(tTask, Tnames, tbody2, 1, null, null,ctx.mkSymbol("Q1"), ctx.mkSymbol("skid1")));
.
Ma quando si assisterà
//T2 ; T4 ;(; T12 ; T13 ;AND ; T14 ; T15;) ; T10; T11
Expr T2 = ctx.mkConst("t2", Task);
Expr T3 = ctx.mkConst("t3", Task);
Expr mt = ctx.mkApp(mustPrecede, T2,T3);
Expr mts = ctx.mkApp(mustPrecede, T3,T2);
solver.add(ctx.mkAnd((BoolExpr)mt,(BoolExpr)mts));
.
Il risolutore SAT sta segnalando seduto .. Ma questo Si non è possibile dal momento che il musteprecede è irrilevante in base alle mie precedenti definizioni con quantificatori .. Qualcuno può vedere cosa mi manca o perché il risolutore sab non considera i "vincoli" che ho aggiunto i "vincoli"con le fori ??
Soluzione
Esistono due modi per costruire espressioni quantificate in Z3, uno è utilizzando costanti chiamate, l'altra è di variabili indicizzate di De-Brujin. Il codice pubblicato qui mescola questi due e quindi crea espressioni che look a destra, quando non sono.
Le seguenti parti:
Sort[] tTask = ...
Symbol[] Tnames = ...
...
Expr t1 = ctx.mkConst("t1",Task);
...
Expr mt1t2 = ctx.mkApp(mustPrecede, t1,t2);
...
Expr tra = ctx.mkForall(tTask, Tnames, ...
.
Costruisci il corpo del quantificatore da costanti ("T1" ecc.), Ma la chiamata a ctx.mkForall
richiede variabili indicizzate de-brujin (gli indici sono impliciti e tTask
e tnames
assegna loro nomi e ordinarli). Per funzionare, il corpo deve essere costruito utilizzando variabili indicizzate, che vengono generate da chiamate a ctx.mkBound(...)
.
Viceversa, se le espressioni costante sono preferite, il quantificatore potrebbe essere costruito da una chiamata a ctx.mkForall(Expr[] boundConstants, ...
in cui il primo argomento è una serie di espressioni costanti come new Expr[] { t1, t2, t3 }
.
Il modo migliore per vedere perché il codice non funziona è quando i simboli in Tnames
vengono assegnati nomi diversi. È quindi chiaro da vedere dall'uscita che c'è una disallineamento tra quelle variabili. Ad esempio, modifica del codice su
....
Expr t1 = ctx.mkConst("x",Task);
Expr t2 = ctx.mkConst("y",Task);
Expr t3 = ctx.mkConst("z",Task);
....
.
Modifica il primo quantificatore a
(forall ((x Task) (y Task) (z Task)) (not (mustPrecede t t)))
.