Thực thi tự động trong JPF sử dụng đầu và là Java byte code, từ Java byte code, việc kết hợp giữa thực thi tự động với JPF lõi (core) sẽ sinh ra các đối tượng PC. Các PC này sẽ chứa ràng buộc. Một ràng buộc là một lớp bao gồm biểu thức phía trái, biểu thức phía phải, phép so sánh và chính nó:
public abstract class Constraint {
JPF Wrapper Z3
Java class ( byte code) Thực thi Tượng trưng Các ràng buộc định dạng JPF Định dạng SMT - Lib
34
private final Expression left; private final Comparator comp; private final Expression right; Constraint and;
}
Ví dụ: x + 1 > y +z
Khi đó biểu thức bên trái là x + 1, bên phải là y + z và phép so sánh là phép lớn hơn: > .
Một biểu thức cũng sẽ được định nghĩa bao gồm biểu thức bên trái, phép toán và biểu thức bên phải. Bên dưới là lớp định nghĩa biểu thức cho số thực:
class BinaryRealExpression extends RealExpression {
RealExpression left; Operator op;
RealExpression right;
BinaryRealExpression (RealExpression l, Operator o, RealExpression r) {
left = l; op = o; right = r; }
public double solution() { double l = left.solution(); double r = right.solution(); switch(op){
case PLUS: return l + r; case MINUS: return l - r; case MUL: return l * r; case DIV: assert(r!=0); return l/r;
default: throw new RuntimeException("## Error: BinaryRealSolution solution: l " + l + " op " + op + " r " + r);
} }
public void getVarsVals(Map<String,Object> varsVals) { left.getVarsVals(varsVals);
right.getVarsVals(varsVals); }
35
JPF đưa ra một lớp chuẩn để chuyển từ những định dạng của JPF sang một công cụ tìm lời giải nào đó. Đó là lớp trừu tượng ProblemGenenal, lớp này sẽ chứa các phương thức để chuyển các biểu thức nguyên tử hoặc ràng buộc nguyên tử sang định dạng của công cụ tìm lời giải, các lớp cụ thể sẽ được mở rộng từ những lớp này. Trong mở rộng này đã có 3 cài đặt là ProblemChoco, ProblemIAsolver, ProblemCVC3, tương ứng với việc sử dụng: Choco, IAsolver, CVC3. Ví dụ để chuyển đổi sang định dạng của ràng buộc phép lớn hơn của IAsolver sẽ như sau:
Object gt(Object exp1, Object exp2){
return (String)exp1 + " > " + (String)exp2 + "; "; }
Việc mở rộng với Z3 cũng nên tuân thủ mô hình tích hợp với các công cụ tìm lời giải khác của JPF. Bây giờ ta phải tổ chức để sao cho chuyển ràng buộc từ JPF sang SMT-LIB. Một SMT-LIB sẽ có dạng như sau:
(benchmark:// Tên
:logic // kiểu cua logic - ví dụ số học tuyến tính là: QF_LIA :extrafuns: // Khai báo biến
:formula :// Phần định nghĩa biểu thức )
Trong đó formula chính là biểu thức cần phải chuyển ràng buộc của JPF sang, ví dụ về một biểu thức được định nghĩa bằng SMT LIB như sau.
(benchmark example :status sat
:logic QF_LIA
:extrafuns ((x1 Int) (x2 Int) (x3 Int)) :formula (and (>= (- x1 x2) 1)
(<= (- x1 x2) 3)
(= x1 (+ (* 2 x3) 4)) )
Ta thiết kế một lớp ProblemZ3 (tương tự như cách JPF tích hợp với các công cụ tìm lời giải: Choco, IASolver, CVC3) có nhiệm vụ chuyển ràng buộc sang dạng biểu thức ở trên..
Ví dụ chuyển đổi phép cho ràng buộc lớn hơn hoặc bằng >= sẽ như sau: Object geq(int value, Object exp){
return "(>= " + value + " " + (String)exp + ")"; }
Object geq(Object exp, int value){
return "(>= " + (String)exp + " " + value + ")"; }
36
return "(>= " + (String)exp1 + " " + (String)exp2 + ")"; }
Object geq(double value, Object exp){
Return "(>= " + String.format(format,value) + " " + (String)exp + ")";
}
Object geq(Object exp, double value){
return "(>= " + (String)exp + " )" +
String.format(format,value) + ")"; }
Sau đó ta sẽ thực hiện việc lưu định dạng trên ra file theo đúng như cấu trúc của ngôn ngữ SMT-LIB và gọi Z3 thông qua dòng lệnh. Kết quả trả về sẽ được lưu trong đối tượng Result. Đối tượng này sẽ gồm một thuộc tính Boolean và một vector. Biến Boolean sẽ là true nếu câu trả lời là thỏa mãn, và false nếu câu trả lời là không thỏa mãn. Biến vector sẽ lưu trữ những cặp (biến, giá trị) nếu nhận được câu trả lời là true.
public class Result {
public Boolean result; public Vector vresult; public Result() {
super();
vresult= new Vector(); }
public Vector getVresult() { return vresult;
}
public void setVresult(Vector vresult) { this.vresult = vresult;
}
public Boolean getResult() { return result;
}
public void setResult(Boolean result) { this.result = result;
37