├── .gitignore ├── README.md ├── code-examples ├── README.md ├── dune-project ├── dune-workspace ├── ocaml │ ├── dune │ ├── ex1.ml │ ├── ex2.ml │ ├── ex3.ml │ ├── ex4.ml │ ├── ex5.ml │ └── ex6.ml ├── sign-analysis │ ├── dune │ └── signAnalysis.ml └── z3 │ ├── _tags │ ├── dune │ ├── ex1.ml │ ├── ex2.ml │ ├── ex3.ml │ ├── run.sh │ └── util.ml ├── exams └── 2024-mid.pdf ├── homework └── hw1 │ ├── benchmark │ ├── safe1 │ ├── safe2 │ ├── unsafe1 │ └── unsafe2 │ ├── code │ ├── _tags │ ├── build │ ├── formula.ml │ ├── formula.mli │ ├── lexer.mll │ ├── main.ml │ ├── options.ml │ ├── parser.mly │ ├── pgm.ml │ ├── pgm.mli │ ├── solver.ml │ ├── solver.mli │ ├── trace.ml │ ├── trace.mli │ ├── verify.ml │ ├── verify.mli │ ├── verify_utils.ml │ └── verify_utils.mli │ └── hw1.pdf ├── setup ├── _tags ├── ex.py ├── install_ocaml_mac.sh ├── install_ocaml_ubuntu.sh ├── install_z3.sh ├── main.ml ├── test_ocaml.sh ├── wsl-install-guideline.pdf └── wsl_install.ps1 └── slides ├── lec-halting.pdf ├── lec-ocaml.pdf ├── lec0.pdf ├── lec1.pdf ├── lec10.pdf ├── lec11.pdf ├── lec12.pdf ├── lec13.pdf ├── lec14.pdf ├── lec15.pdf ├── lec16.pdf ├── lec17.pdf ├── lec18.pdf ├── lec2.pdf ├── lec3.pdf ├── lec4.pdf ├── lec5.pdf ├── lec6.pdf ├── lec7.pdf ├── lec8.pdf └── lec9.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | *.native 2 | *.swp 3 | _build 4 | main.native 5 | 6 | # build file by dune 7 | *.exe 8 | *.opam 9 | 10 | # for MacOS users 11 | .DS_Store 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EC4219: Software Engineering (소프트웨어공학) 2 | - Instructor: [Sunbeom So](https://gist-pal.github.io) 3 | - Location: EECS B201 4 | - Time: Mon/Wed 16:00-17:30 5 | 6 | ## About The Course 7 | Software Engineering is an engineering discipline that is concerned with all aspects of SW production process. 8 | In particular, SW validation is highly important in the SW process due to the prevalence of SW errors, comprising more than half of the SW development cost. 9 | Our focus in this course is to study program analysis methods, which are fundamental and modern technologies that can effectively help the SW validation process. 10 | 11 | ## Configuring the Programming Environment 12 | We will use [OCaml](https://ocaml.org/install) programming language for our programming exercises. This instruction assumes that you are using the Linux command line interface. 13 | 14 | ### macOS 15 | To install OCaml, simply copy and run the following commands in the terminal. 16 | ``` 17 | $ chmod +x setup/install_ocaml_mac.sh; ./setup/install_ocaml_mac.sh; eval $(opam env) 18 | ``` 19 | 20 | ### Ubuntu 21 | To install OCaml, simply copy and run the following commands in the terminal. I checked that the following commands successfully work for the clean docker image ``python:3.9.19-slim``. 22 | ``` 23 | $ chmod +x setup/install_ocaml_ubuntu.sh; ./setup/install_ocaml_ubuntu.sh; eval $(opam env) 24 | ``` 25 | 26 | ### Windows 27 | For Windows users, I recommend using [WSL](https://learn.microsoft.com/en-us/windows/wsl/install). 28 | * [WSL setup](setup/wsl-install-guideline.pdf): We provide a PDF guideline that explains how to install WSL and how to share files between the host OS and the guest OS. 29 | * [script](setup/wsl_install.ps1): For running this installation script, please refer to p.02 of the above PDF guideline. 30 | 31 | After setting up WSL, simply copy and run the following commands in the terminal to install OCaml. 32 | ``` 33 | $ chmod +x setup/install_ocaml_ubuntu.sh; ./setup/install_ocaml_ubuntu.sh; eval $(opam env) 34 | ``` 35 | 36 | ### Installing Z3 37 | To install Z3, simply copy and run the following commands in the terminal. 38 | ``` 39 | $ chmod +x setup/install_z3.sh; ./setup/install_z3.sh 40 | ``` 41 | 42 | ### Installation Verification 43 | ``` 44 | $ ocaml --version 45 | The OCaml toplevel, version 5.1.1 46 | $ z3 --version 47 | Z3 version 4.13.0 - 64 bit 48 | ``` 49 | 50 | 51 | ## Textbook 52 | * [The Calculus of Computation](https://link.springer.com/book/10.1007/978-3-540-74113-8) (COC) 53 | * [Semantics with Applications: An Appetizer](https://link.springer.com/book/10.1007/978-1-84628-692-6) (SAA) 54 | 55 | ## Schedule 56 | |#|Date|Topics|Recommended Reading| 57 | |-|-|------|------| 58 | |0|3/5|[Course Overview](slides/lec0.pdf)|| 59 | |1|3/10|[Propositional Logic (1)](slides/lec1.pdf)| COC Ch.1.1-1.5| 60 | |2|3/17, 3/19|[Propositional Logic (1)](slides/lec2.pdf)| COC Ch.1.6-1.7| 61 | |3|3/24, 3/27, 3/31|[First-Order Logic](slides/lec3.pdf)| COC Ch.2| 62 | |4|4/2, 4/7|[First-Order Theories](slides/lec4.pdf)| COC Ch.3| 63 | |-|4/7|[Undecidability, Halting Problem](slides/lec-halting.pdf)| | 64 | |5|4/9|[Problem Solving using SMT Solvers](slides/lec5.pdf)| | 65 | |-|4/14|[Reviewing Past Exam Questions]| | 66 | |-|4/21|[Mid-term Exam]| | 67 | |-|4/28|[Functional Programming in OCaml](slides/lec-ocaml.pdf)|| 68 | |6|4/30, 5/7|[Program Verification (1): Specification](slides/lec6.pdf)|COC Ch.5.1| 69 | |7|5/7, 5/12, 5/14|[Program Verification (2): Inductive Assertion Method](slides/lec7.pdf)|COC Ch.5.2| 70 | |8|5/19|[Program Verification (3): Inductive Assertion Method](slides/lec8.pdf)|| 71 | |9|5/21|[Program Verification (4): Invariant Inference](slides/lec9.pdf)|[Houdini Paper](https://users.soe.ucsc.edu/~cormac/papers/fme01.pdf)| 72 | |10|5/26, 5/28|[Symbolic Execution](slides/lec10.pdf)|[A Survey of Symbolic Execution Techniques](https://dl.acm.org/doi/10.1145/3182657)| 73 | |11|6/2|[Program Verification (5): Termination Proof](slides/lec11.pdf)|COC Ch.5.3| 74 | |12|6/4|[Type System (1): Introduction](slides/lec12.pdf)|| 75 | 76 | 77 | ## Academic Integrity 78 | By registering for this course, I will assume you agree with the policy below. 79 | * All assignments (i.e., writing code) must be your own work. No discussions are allowed. 80 | * You should not share/show your code. 81 | * You should not post your code on public websites. 82 | * You should not modify other students’ code. 83 | * I will have a one-on-one meeting with each student under suspicion. 84 | If you fail to prove your integrity in the meeting (e.g., failing to answer my questions about the details of your submissions), I will consider that you committed academic misconduct, even if you do not admit to your cheating. 85 | * Cheating on assignments will result in an F. 86 | 87 | 88 | ## References & Acknowledgements 89 | My lecture slides are based on those from the following courses. 90 | I sincerely appreciate their authors for providing materials that have greatly enhanced the quality of this course. 91 | 92 | * [AAA615:Formal Methods](https://prl.korea.ac.kr/courses/aaa615/2017) course taught by Prof. Hakjoo Oh at Korea University 93 | * [CS398L:Automated Logical Reasoning](https://www.cs.utexas.edu/~isil/cs389L/) course taught by Prof. Isil Dillig at UT Austin 94 | * [CIS547:Software Analysis](https://software-analysis-class.org) course taught by Prof. Mayur Naik at UPenn 95 | -------------------------------------------------------------------------------- /code-examples/README.md: -------------------------------------------------------------------------------- 1 | ## How to test your code on the OCaml toplevel 2 | 3 | 1. Install `utop`, the alternative OCaml Toplevel program. 4 | 5 | ```bash 6 | opam install utop 7 | ``` 8 | 9 | [Here](https://opam.ocaml.org/blog/about-utop/) is the brief explanation about `utop`. You may find `utop` be more convenient than the basic OCaml Toplevel since it has a much improved interface. For example, 10 | 11 | * it automatically shows all valid names in the namespace 12 | * and supports auto-completion (Use `Tab` key) 13 | 14 | 2. On the project root directory (i.e. the directory that has the `dune-project` file of that project, in our case, `ec4219-software-engineering/code-examples`), type 15 | 16 | ```bash 17 | dune utop 18 | ``` 19 | 20 | This command runs `utop`, with loading all your libraries. For more information, type `dune utop --help`. 21 | 22 | You can access to each elements of examples in this directory by `Ocaml_example.Ex[1-6].`, `Z3_example.Ex[1-3].` and `SignAnalysis.`. 23 | 24 | Example: 25 | 26 | ```bash 27 | utop > Ocaml_example.Ex2.reverse [1; 2; 3] ;; 28 | - : int list = [3; 2; 1] 29 | ``` 30 | 31 | ```bash 32 | utop > Z3_example.Util.check_sat_print Z3_example.Ex2.final ;; 33 | SAT 34 | (define-fun y () Int 35 | 0) 36 | (define-fun x () Int 37 | 7) 38 | - : unit = () 39 | ``` -------------------------------------------------------------------------------- /code-examples/dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 3.17) 2 | 3 | (name Examples) 4 | 5 | (generate_opam_files true) 6 | 7 | (source 8 | (github username/reponame)) 9 | 10 | (authors "Author Name ") 11 | 12 | (maintainers "Maintainer Name ") 13 | 14 | (license LICENSE) 15 | 16 | (documentation https://url/to/documentation) 17 | 18 | (package 19 | (name Examples) 20 | (synopsis "A short synopsis") 21 | (description "A longer description") 22 | (depends ocaml) 23 | (tags 24 | ("add topics" "to describe" your project))) 25 | 26 | ; See the complete stanza docs at https://dune.readthedocs.io/en/stable/reference/dune-project/index.html 27 | -------------------------------------------------------------------------------- /code-examples/dune-workspace: -------------------------------------------------------------------------------- 1 | (lang dune 3.17) 2 | 3 | (env 4 | (dev 5 | (flags :standard -warn-error -27-32-33-39))) 6 | 7 | ; to fully ignore warnings: flags :standard -w -27 -------------------------------------------------------------------------------- /code-examples/ocaml/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (public_name Examples.ocaml_example) 3 | (name ocaml_example)) 4 | -------------------------------------------------------------------------------- /code-examples/ocaml/ex1.ml: -------------------------------------------------------------------------------- 1 | let rec append l1 l2 = 2 | match l1 with 3 | | [] -> l2 4 | | h::t -> h::(append t l2) 5 | -------------------------------------------------------------------------------- /code-examples/ocaml/ex2.ml: -------------------------------------------------------------------------------- 1 | let rec reverse l = 2 | match l with 3 | | [] -> [] 4 | | h::t -> (reverse t) @ [h] 5 | -------------------------------------------------------------------------------- /code-examples/ocaml/ex3.ml: -------------------------------------------------------------------------------- 1 | let rec nth l n = 2 | match l with 3 | | [] -> raise (Failure "list is too short") 4 | | hd::tl -> if n = 0 then hd else nth tl (n-1) 5 | 6 | let tc1 = (([1;2;3], 2), 3) 7 | 8 | let run f ((l,n),out) = (f l n = out) 9 | 10 | let _ = print_endline (string_of_bool (run nth tc1)) 11 | let _ = print_endline (string_of_bool (run nth tc1)) 12 | -------------------------------------------------------------------------------- /code-examples/ocaml/ex4.ml: -------------------------------------------------------------------------------- 1 | let rec remove_first a l = 2 | match l with 3 | | [] -> [] 4 | | hd::tl -> 5 | if a=hd then tl 6 | else hd::(remove_first a tl) 7 | -------------------------------------------------------------------------------- /code-examples/ocaml/ex5.ml: -------------------------------------------------------------------------------- 1 | let rec insert a l = (* assume increasing order *) 2 | match l with 3 | | [] -> [a] 4 | | hd::tl -> 5 | if a <= hd then a::hd::tl 6 | else hd::(insert a tl) 7 | -------------------------------------------------------------------------------- /code-examples/ocaml/ex6.ml: -------------------------------------------------------------------------------- 1 | (* Do not change the template *) 2 | (* For example, do not change the definition of the variants, the type of the function, etc. *) 3 | 4 | type exp = 5 | | Int of int 6 | | Minus of exp * exp 7 | | Plus of exp * exp 8 | | Mult of exp * exp 9 | | Div of exp * exp 10 | 11 | let rec eval : exp -> int 12 | = fun exp -> (* TODO *) failwith "NotImplemented" 13 | -------------------------------------------------------------------------------- /code-examples/sign-analysis/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (public_name Examples.signAnalysis) 3 | (name signAnalysis)) 4 | -------------------------------------------------------------------------------- /code-examples/sign-analysis/signAnalysis.ml: -------------------------------------------------------------------------------- 1 | exception NotImplemented 2 | 3 | (********************) 4 | (***** Language *****) 5 | (********************) 6 | 7 | type aexp = 8 | | Int of int 9 | | Var of var 10 | | Plus of aexp * aexp 11 | | Mul of aexp * aexp 12 | | Sub of aexp * aexp 13 | 14 | and var = string 15 | 16 | type bexp = 17 | | True | False 18 | | Eq of aexp * aexp 19 | | Leq of aexp * aexp 20 | | Not of bexp 21 | | And of bexp * bexp 22 | 23 | type cmd = 24 | | Assign of var * aexp 25 | | Skip 26 | | Seq of cmd * cmd 27 | | If of bexp * cmd * cmd 28 | | While of bexp * cmd 29 | 30 | (***************************) 31 | (***** Abstract Domain *****) 32 | (***************************) 33 | 34 | module AbsBool = struct 35 | type t = Top | Bot | True | False 36 | 37 | let porder : t -> t -> bool 38 | = fun b1 b2 -> 39 | if b1 = b2 then true 40 | else 41 | match b1,b2 with 42 | | Bot,_ -> true 43 | | _,Top -> true 44 | | _ -> false 45 | 46 | let to_string : t -> string 47 | = fun t -> 48 | match t with 49 | | Bot -> "bot" 50 | | False -> "false" 51 | | True -> "true" 52 | | Top -> "top" 53 | 54 | let not : t -> t 55 | = fun b -> 56 | match b with 57 | | Bot -> Bot 58 | | True -> False 59 | | False -> True 60 | | Top -> Top 61 | 62 | let band : t -> t -> t 63 | = fun b1 b2 -> 64 | match b1,b2 with 65 | | Bot,_ 66 | | _,Bot -> Bot 67 | | True,True -> True 68 | | False,_ 69 | | _,False -> False 70 | | _ -> Top 71 | end 72 | 73 | module Sign = struct 74 | type t = Top | Bot | Pos | Neg | Zero | NonPos | NonNeg | NonZero 75 | 76 | let porder : t -> t -> bool 77 | = fun s1 s2 -> 78 | match s1,s2 with 79 | | _ when s1 = s2 -> true 80 | | Bot,_ -> true 81 | | _,Top -> true 82 | | Neg,NonPos -> true 83 | | Neg,NonZero -> true 84 | | Zero,NonPos -> true 85 | | Zero,NonNeg -> true 86 | | Pos,NonZero -> true 87 | | Pos,NonNeg -> true 88 | | _ -> false 89 | 90 | let to_string : t -> string 91 | = fun t -> 92 | match t with 93 | | Top -> "top" 94 | | Bot -> "bot" 95 | | Pos -> "pos" 96 | | Neg -> "neg" 97 | | Zero -> "zero" 98 | | NonPos -> "nonpos" 99 | | NonNeg -> "nonneg" 100 | | NonZero -> "nonzero" 101 | 102 | 103 | let alpha' : int -> t 104 | = fun n -> 105 | if n>0 then Pos 106 | else if n=0 then Zero 107 | else Neg 108 | 109 | let join : t -> t -> t 110 | = fun s1 s2 -> 111 | if porder s1 s2 then s2 112 | else if porder s2 s1 then s1 113 | else 114 | match s1,s2 with 115 | | Neg,Pos 116 | | Pos,Neg -> NonZero 117 | | Neg,Zero 118 | | Zero,Neg -> NonPos 119 | | Zero,Pos 120 | | Pos,Zero -> NonNeg 121 | | _ -> Top 122 | 123 | let add : t -> t -> t 124 | = fun s1 s2 -> 125 | match s1,s2 with 126 | | Bot,_ 127 | | _,Bot -> Bot 128 | | Top,_ 129 | | _,Top -> Top 130 | | Neg,Neg -> Neg 131 | | Neg,Zero -> Neg 132 | | Neg,NonPos -> Neg 133 | | Neg,_ -> Top 134 | | Zero,_ -> s2 135 | | Pos,Zero 136 | | Pos,Pos 137 | | Pos,NonNeg -> Pos 138 | | Pos,_ -> Top 139 | | NonPos,Neg -> Neg 140 | | NonPos,Zero -> NonPos 141 | | NonPos,NonPos -> NonPos 142 | | NonPos,_ -> Top 143 | | NonZero,Zero -> NonZero 144 | | NonZero,_ -> Top 145 | | NonNeg,Zero -> NonNeg 146 | | NonNeg,Pos -> Pos 147 | | NonNeg,NonNeg -> NonNeg 148 | | NonNeg,_ -> Top 149 | 150 | let sub s1 s2 = raise NotImplemented (* TODO: exercise *) 151 | let mul s1 s2 = raise NotImplemented (* TODO: exercise *) 152 | 153 | let leq : t -> t -> AbsBool.t 154 | = fun s1 s2 -> 155 | match s1,s2 with 156 | | Bot,_ -> AbsBool.Bot 157 | | _,Bot -> AbsBool.Bot 158 | | Neg,_ when List.mem s2 [Zero;Pos;NonNeg] -> AbsBool.True 159 | | Zero,_ when List.mem s2 [Zero;Pos;NonNeg] -> AbsBool.True 160 | | Pos,_ -> AbsBool.Top 161 | | NonPos,_ when List.mem s2 [Pos] -> AbsBool.True 162 | | NonZero,_ -> AbsBool.Top 163 | | NonNeg,_ -> AbsBool.Top 164 | | _ -> AbsBool.Top 165 | 166 | let eq : t -> t -> AbsBool.t 167 | = fun s1 s2 -> 168 | match s1,s2 with 169 | | Bot,_ -> AbsBool.Bot 170 | | _,Bot -> AbsBool.Bot 171 | | Zero,_ when List.mem s2 [Neg;Pos;NonZero] -> AbsBool.False 172 | | Zero,Zero -> AbsBool.True 173 | | Pos,_ when List.mem s2 [Neg;Zero;NonPos] -> AbsBool.False 174 | | NonPos,Pos -> AbsBool.False 175 | | NonZero,Zero -> AbsBool.False 176 | | NonNeg,Neg -> AbsBool.False 177 | | _ -> AbsBool.Top 178 | end 179 | 180 | module AbsMem = struct 181 | (* reference : https://ocaml.org/manual/5.2/api/Map.Make.html *) 182 | module Map = Map.Make(String) (* key domain: variable *) 183 | type t = Sign.t Map.t (* map domain: string(var) -> Sign.t *) 184 | 185 | let empty = Map.empty 186 | let add = Map.add 187 | let find x m = try Map.find x m with _ -> Sign.Bot 188 | 189 | let join m1 m2 = 190 | let f k v1 v2 = 191 | match v1,v2 with 192 | | None,None -> None 193 | | Some v,None -> Some v 194 | | None,Some v -> Some v 195 | | Some v1,Some v2 -> Some (Sign.join v1 v2) 196 | in 197 | Map.merge f m1 m2 198 | 199 | let porder : t -> t -> bool 200 | = fun m1 m2 -> 201 | Map.for_all (fun x v -> Sign.porder v (find x m2)) m1 202 | 203 | let print : t -> unit 204 | = fun m -> 205 | if Map.is_empty m then print_endline "empty" 206 | else 207 | Map.iter (fun x v -> print_endline (x ^ " |-> " ^ Sign.to_string v)) m 208 | end 209 | 210 | (******************************) 211 | (***** Abstract Semantics *****) 212 | (******************************) 213 | 214 | let rec eval_a : aexp -> AbsMem.t -> Sign.t 215 | = fun a m -> 216 | match a with 217 | | Int n -> Sign.alpha' n 218 | | Var x -> AbsMem.find x m 219 | | Plus (a1, a2) -> Sign.add (eval_a a1 m) (eval_a a2 m) 220 | | Mul (a1, a2) -> Sign.mul (eval_a a1 m) (eval_a a2 m) 221 | | Sub (a1, a2) -> Sign.sub (eval_a a1 m) (eval_a a2 m) 222 | 223 | let rec eval_b : bexp -> AbsMem.t -> AbsBool.t 224 | = fun b m -> 225 | match b with 226 | | True -> AbsBool.True 227 | | False -> AbsBool.False 228 | | Eq (a1, a2) -> Sign.eq (eval_a a1 m) (eval_a a2 m) 229 | | Leq (a1, a2) -> Sign.leq (eval_a a1 m) (eval_a a2 m) 230 | | Not b -> AbsBool.not (eval_b b m) 231 | | And (b1, b2) -> AbsBool.band (eval_b b1 m) (eval_b b2 m) 232 | 233 | let rec eval_c : cmd -> AbsMem.t -> AbsMem.t 234 | = fun c m -> 235 | match c with 236 | | Assign (x,a) -> AbsMem.add x (eval_a a m) m 237 | | Skip -> m 238 | | Seq (c1,c2) -> eval_c c2 (eval_c c1 m) 239 | | If (b, c1, c2) -> cond (eval_b b, eval_c c1, eval_c c2) m 240 | | While (b, c) -> 241 | let filter p x = if AbsBool.porder AbsBool.True (eval_b p x) then x else AbsMem.empty in 242 | let onestep x = AbsMem.join m (eval_c c (filter b x)) in 243 | let rec fix f x i = 244 | let x' = f x in 245 | let _ = print_endline ("=== iteration " ^ string_of_int i ^ " ===") in 246 | let _ = print_endline "- input memory" in 247 | let _ = AbsMem.print x in 248 | let _ = print_endline "- output memory" in 249 | let _ = AbsMem.print x' in 250 | let _ = print_endline "" in 251 | if AbsMem.porder x' x then x 252 | else fix f x' (i+1) 253 | in 254 | filter (Not b) (fix onestep m 1) 255 | 256 | and cond (f,g,h) m = 257 | match f m with 258 | | AbsBool.Bot -> AbsMem.empty 259 | | AbsBool.True -> g m 260 | | AbsBool.False -> h m 261 | | AbsBool.Top -> AbsMem.join (g m) (h m) 262 | 263 | (****************) 264 | (***** Test *****) 265 | (****************) 266 | 267 | let pgm = 268 | let l1 = Assign ("x", Int 0) in 269 | let l2 = Assign ("y", Int 0) in 270 | let l5 = Assign ("x", Plus (Var "x", Int 1)) in 271 | let l8 = Assign ("x", Plus (Var "x", Var "y")) in 272 | let l10 = Assign ("y", Plus (Var "y", Int 1)) in 273 | let loop = 274 | While (Leq (Var "y", Var "n"), 275 | Seq (If (Eq (Var "z", Int 0), l5, l8), l10) 276 | ) 277 | in 278 | Seq (l1, Seq (l2, loop)) 279 | 280 | let mem = (AbsMem.add "z" Sign.Top (AbsMem.add "n" Sign.Top AbsMem.empty)) 281 | let _ = 282 | let mem' = eval_c pgm mem in 283 | print_endline "=== final memory ==="; 284 | AbsMem.print mem' 285 | -------------------------------------------------------------------------------- /code-examples/z3/_tags: -------------------------------------------------------------------------------- 1 | true: package(Z3) 2 | -------------------------------------------------------------------------------- /code-examples/z3/dune: -------------------------------------------------------------------------------- 1 | (library 2 | (public_name Examples.z3_example) 3 | (name z3_example) 4 | (libraries z3)) 5 | -------------------------------------------------------------------------------- /code-examples/z3/ex1.ml: -------------------------------------------------------------------------------- 1 | open Util 2 | 3 | let p = PVar "p" 4 | let q = PVar "q" 5 | let r = PVar "r" 6 | 7 | let f1 = Imply (p,q) 8 | let f2 = Iff (r, Not q) 9 | let f3 = Or (Not p, r) 10 | 11 | let final = And (f1,And (f2,f3)) 12 | 13 | let _ = check_sat_print final 14 | -------------------------------------------------------------------------------- /code-examples/z3/ex2.ml: -------------------------------------------------------------------------------- 1 | open Util 2 | 3 | let x = Var ("x", EType Int) 4 | let y = Var ("y", EType Int) 5 | 6 | let mk_add x y = BinOp (Add, x, y, EType Int) 7 | let mk_mul x y = BinOp (Mul, x, y, EType Int) 8 | 9 | let f1 = BinRel(Gt, x, Int 2) 10 | let f2 = BinRel(Lt, y, Int 10) 11 | let f3 = BinRel(Eq, mk_add x (mk_mul (Int 2) y), Int 7) 12 | 13 | let final = And (f1,And (f2,f3)) 14 | 15 | let _ = check_sat_print final 16 | -------------------------------------------------------------------------------- /code-examples/z3/ex3.ml: -------------------------------------------------------------------------------- 1 | open Util 2 | 3 | let mk_read (t1,t2) = Read (t1,t2) 4 | let mk_write (t1,t2,t3) = Write (t1,t2,t3) 5 | 6 | let i = Var ("i", EType Int) 7 | let e = Var ("e", EType Int) 8 | 9 | let a = Var ("a", Array Int) 10 | 11 | let pre = BinRel (Eq, mk_read (a, i), e) 12 | let con = 13 | let j = Var ("@j", EType Int) in 14 | Forall ([("@j", EType Int)], BinRel (Eq, mk_read (mk_write (a,i,e), j),mk_read (a,j))) 15 | 16 | let final = Imply (pre, con) 17 | 18 | let _ = check_sat_print (Not final) 19 | -------------------------------------------------------------------------------- /code-examples/z3/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf "$1".native 4 | ocamlbuild ./"$1".native -use-ocamlfind -tag thread -Is . 5 | ./"$1".native 6 | -------------------------------------------------------------------------------- /code-examples/z3/util.ml: -------------------------------------------------------------------------------- 1 | open Z3 2 | open Z3.Solver 3 | 4 | let ctx = Z3.mk_context [("timeout", "30000")] 5 | 6 | (*****************) 7 | (**** Formula ****) 8 | (*****************) 9 | 10 | type formula = 11 | | True | False 12 | | Not of formula 13 | | And of formula * formula 14 | | Or of formula * formula 15 | | PVar of name 16 | | BinRel of brel * term * term 17 | | Imply of formula * formula 18 | | Iff of formula * formula 19 | | Forall of var list * formula 20 | | Exists of var list * formula 21 | 22 | and term = 23 | | Int of int 24 | | Var of var 25 | | Read of term * term (* A[i] *) 26 | | Write of term * term * term (* A[i] := v, return the modified A *) 27 | | BinOp of bop * term * term * typ 28 | 29 | and var = (name * typ) 30 | and name = string 31 | 32 | and brel = Geq | Gt | Leq | Lt | Eq 33 | and bop = Add | Sub | Mul 34 | 35 | and typ = 36 | | EType of etyp 37 | | Array of etyp 38 | 39 | and etyp = (* elementary type *) 40 | | Int 41 | | Bool 42 | 43 | let rec typ_to_sort : typ -> Z3.Sort.sort 44 | = fun typ -> 45 | match typ with 46 | | EType et -> etyp_to_sort et 47 | | Array et -> 48 | Z3.Z3Array.mk_sort ctx (Z3.Arithmetic.Integer.mk_sort ctx) (etyp_to_sort et) 49 | 50 | and etyp_to_sort : etyp -> Z3.Sort.sort 51 | = fun etyp -> 52 | match etyp with 53 | | Int -> Z3.Arithmetic.Integer.mk_sort ctx 54 | | Bool -> Z3.Boolean.mk_sort ctx 55 | 56 | let rec trans_f : formula -> Z3.Expr.expr 57 | = fun f -> 58 | match f with 59 | | True -> Z3.Boolean.mk_true ctx 60 | | False -> Z3.Boolean.mk_false ctx 61 | | PVar x -> Z3.Boolean.mk_const_s ctx x 62 | | Not f -> Z3.Boolean.mk_not ctx (trans_f f) 63 | | And (f1,f2) -> Z3.Boolean.mk_and ctx [trans_f f1; trans_f f2] 64 | | Or (f1,f2) -> Z3.Boolean.mk_or ctx [trans_f f1; trans_f f2] 65 | | BinRel (brel,t1,t2) -> 66 | let z3exp1 = trans_t t1 in 67 | let z3exp2 = trans_t t2 in 68 | (match brel with 69 | | Geq -> Z3.Arithmetic.mk_ge ctx z3exp1 z3exp2 70 | | Gt -> Z3.Arithmetic.mk_gt ctx z3exp1 z3exp2 71 | | Leq -> Z3.Arithmetic.mk_le ctx z3exp1 z3exp2 72 | | Lt -> Z3.Arithmetic.mk_lt ctx z3exp1 z3exp2 73 | | Eq -> Z3.Boolean.mk_eq ctx z3exp1 z3exp2) 74 | | Imply (f1,f2) -> Z3.Boolean.mk_implies ctx (trans_f f1) (trans_f f2) 75 | | Iff (f1,f2) -> Z3.Boolean.mk_iff ctx (trans_f f1) (trans_f f2) 76 | | Forall (vars,f) -> 77 | let bvars = List.map (fun (x,t) -> trans_t (Var (x,t))) vars in 78 | let z3f = trans_f f in 79 | Z3.Quantifier.expr_of_quantifier (Z3.Quantifier.mk_forall_const ctx bvars z3f None [] [] None None) 80 | | Exists (vars,f) -> 81 | let bvars = List.map (fun (x,t) -> trans_t (Var (x,t))) vars in 82 | let z3f = trans_f f in 83 | Z3.Quantifier.expr_of_quantifier (Z3.Quantifier.mk_exists_const ctx bvars z3f None [] [] None None) 84 | 85 | and trans_t : term -> Z3.Expr.expr 86 | = fun t -> 87 | match t with 88 | | Int n -> Z3.Arithmetic.Integer.mk_numeral_i ctx n 89 | | Var (x,typ) -> Z3.Expr.mk_const_s ctx x (typ_to_sort typ) 90 | | Read (t1,t2) -> 91 | let z3exp1 = trans_t t1 in 92 | let z3exp2 = trans_t t2 in 93 | Z3.Z3Array.mk_select ctx z3exp1 z3exp2 94 | | Write (t1,t2,t3) -> 95 | let z3exp1 = trans_t t1 in 96 | let z3exp2 = trans_t t2 in 97 | let z3exp3 = trans_t t3 in 98 | Z3.Z3Array.mk_store ctx z3exp1 z3exp2 z3exp3 99 | | BinOp (bop,t1,t2,typ) -> 100 | let _ = assert (typ = EType Int) in 101 | let z3exp1 = trans_t t1 in 102 | let z3exp2 = trans_t t2 in 103 | (match bop with 104 | | Add -> Z3.Arithmetic.mk_add ctx [z3exp1; z3exp2] 105 | | Sub -> Z3.Arithmetic.mk_sub ctx [z3exp1; z3exp2] 106 | | Mul -> Z3.Arithmetic.mk_mul ctx [z3exp1; z3exp2]) 107 | 108 | (*********************) 109 | (**** Z3 wrappers ****) 110 | (*********************) 111 | 112 | let mk_solver : unit -> Z3.Solver.solver 113 | = fun () -> Z3.Solver.mk_solver ctx None 114 | 115 | type status = 116 | | SAT 117 | | UNSAT 118 | | UNK 119 | 120 | let check_sat : formula -> (status * Z3.Model.model option) 121 | = fun f -> 122 | let solver = mk_solver () in 123 | let _ = Z3.Solver.add solver [trans_f f] in 124 | (match Z3.Solver.check solver [] with 125 | | UNSATISFIABLE -> (UNSAT, None) 126 | | UNKNOWN -> (UNK, None) 127 | | SATISFIABLE -> 128 | (match Z3.Solver.get_model solver with 129 | | Some m -> (SAT, Some m) 130 | | None -> assert false)) 131 | 132 | let check_validity : formula -> bool 133 | = fun f -> 134 | match check_sat (Not f) with 135 | | UNSAT,_ -> true 136 | | _ -> false 137 | 138 | let string_of_model : Z3.Model.model -> string 139 | = fun m -> Z3.Model.to_string m 140 | 141 | let check_sat_print : formula -> unit 142 | = fun f -> 143 | match check_sat f with 144 | | SAT, Some m -> 145 | (print_endline "SAT"; 146 | print_endline (string_of_model m)) 147 | | SAT,None -> assert false 148 | | UNSAT,_ -> print_endline "UNSAT" 149 | | UNK,_ -> print_endline "UNKNOWN" 150 | -------------------------------------------------------------------------------- /exams/2024-mid.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/exams/2024-mid.pdf -------------------------------------------------------------------------------- /homework/hw1/benchmark/safe1: -------------------------------------------------------------------------------- 1 | --- Thread_A --- 2 | (0, maygoto 1) 3 | (1, a=true and goto 2) 4 | (2, if b then goto 2 else goto 3) 5 | (3, critical and goto 4) 6 | (4, a=false and goto 0) 7 | 8 | --- Thread_B --- 9 | (0, maygoto 1) 10 | (1, b=true and goto 2) 11 | (2, if a then goto 2 else goto 3) 12 | (3, critical and goto 4) 13 | (4, b=false and goto 0) 14 | -------------------------------------------------------------------------------- /homework/hw1/benchmark/safe2: -------------------------------------------------------------------------------- 1 | --- Thread_A --- 2 | (0, maygoto 1) 3 | (1, a=true and goto 2) 4 | (2, p=false and goto 3) 5 | (3, if b then goto 4 else goto 5) 6 | (4, if p then goto 5 else goto 3) 7 | (5, critical and goto 6) 8 | (6, a=false and goto 0) 9 | 10 | --- Thread_B --- 11 | (0, maygoto 1) 12 | (1, b=true and goto 2) 13 | (2, p=true and goto 3) 14 | (3, if a then goto 4 else goto 5) 15 | (4, if p then goto 3 else goto 5) 16 | (5, critical and goto 6) 17 | (6, b=false and goto 0) 18 | -------------------------------------------------------------------------------- /homework/hw1/benchmark/unsafe1: -------------------------------------------------------------------------------- 1 | --- Thread_A --- 2 | (0, maygoto 1) 3 | (1, if p then goto 1 else goto 2) 4 | (2, p=true and goto 3) 5 | (3, critical and goto 4) 6 | (4, p=false and goto 0) 7 | 8 | --- Thread_B --- 9 | (0, maygoto 1) 10 | (1, if p then goto 1 else goto 2) 11 | (2, p=true and goto 3) 12 | (3, critical and goto 4) 13 | (4, p=false and goto 0) 14 | -------------------------------------------------------------------------------- /homework/hw1/benchmark/unsafe2: -------------------------------------------------------------------------------- 1 | --- Thread_A --- 2 | (0, maygoto 1) 3 | (1, if b then goto 1 else goto 2) 4 | (2, a=true and goto 3) 5 | (3, critical and goto 4) 6 | (4, a=false and goto 0) 7 | 8 | --- Thread_B --- 9 | (0, maygoto 1) 10 | (1, if a then goto 1 else goto 2) 11 | (2, b=true and goto 3) 12 | (3, critical and goto 4) 13 | (4, b=false and goto 0) 14 | -------------------------------------------------------------------------------- /homework/hw1/code/_tags: -------------------------------------------------------------------------------- 1 | true: package(batteries), package(str), package(Z3) 2 | -------------------------------------------------------------------------------- /homework/hw1/code/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TARGET=main.native 4 | INCLUDE_DIRS=lib 5 | 6 | function clean 7 | { 8 | ocamlbuild -clean 9 | exit 0 10 | } 11 | 12 | while [ $# -ne 0 ] && [ ! -z $1 ]; do 13 | case $1 in 14 | debug|clean|rebuild) "$1" ;; 15 | *) echo "build: invalid argument $1" && exit 1 ;; 16 | esac 17 | shift 18 | done 19 | 20 | 21 | time ocamlbuild $TARGET -use-ocamlfind -Is $INCLUDE_DIRS -tag thread 22 | -------------------------------------------------------------------------------- /homework/hw1/code/formula.ml: -------------------------------------------------------------------------------- 1 | type t = 2 | | True | False 3 | | Var of id 4 | | Not of t 5 | | And of t * t 6 | | Or of t * t 7 | | Imply of t * t 8 | | Iff of t * t 9 | 10 | and formula = t 11 | and id = string 12 | 13 | let rec to_string : t -> string 14 | = fun f -> 15 | match f with 16 | | True -> "true" 17 | | False -> "false" 18 | | Var x -> x 19 | | Not f -> "!(" ^ to_string f ^ ")" 20 | | And (f1,f2) -> "(" ^ to_string f1 ^ " /\\ " ^ to_string f2 ^ ")" 21 | | Or (f1,f2) -> "(" ^ to_string f1 ^ " \\/ " ^ to_string f2 ^ ")" 22 | | Imply (f1,f2) -> "(" ^ to_string f1 ^ " -> " ^ to_string f2 ^ ")" 23 | | Iff (f1,f2) -> "(" ^ to_string f1 ^ " <-> " ^ to_string f2 ^ ")" 24 | -------------------------------------------------------------------------------- /homework/hw1/code/formula.mli: -------------------------------------------------------------------------------- 1 | type t = 2 | | True | False 3 | | Var of id 4 | | Not of t 5 | | And of t * t 6 | | Or of t * t 7 | | Imply of t * t 8 | | Iff of t * t 9 | 10 | and formula = t 11 | and id = string 12 | 13 | val to_string : t -> string 14 | -------------------------------------------------------------------------------- /homework/hw1/code/lexer.mll: -------------------------------------------------------------------------------- 1 | { 2 | open Parser 3 | exception Eof 4 | exception LexicalError 5 | let comment_depth = ref 0 6 | } 7 | 8 | let blank = [' ' '\n' '\t' '\r']+ 9 | let id = ['a'-'z' 'A'-'Z']['a'-'z' 'A'-'Z' '\'' '0'-'9' '_']* 10 | let number = ['0'-'9']+ 11 | 12 | rule start = parse 13 | | blank { start lexbuf } 14 | | "(*" { comment_depth :=1; 15 | comment lexbuf; 16 | start lexbuf } 17 | | "(" {LPAREN} | ")" {RPAREN} | "---" {MINUS} 18 | | "and" {AND} | "if" {IF} | "then" {THEN} 19 | | "goto" {GOTO} | "else" {ELSE} | "=" {EQ} 20 | | "," {COMMA} | "maygoto" {MAY} 21 | | "critical" {CRITICAL} 22 | | "Thread_A" {THREAD_A} | "Thread_B" {THREAD_B} 23 | | "true" {BOOL true} | "false" {BOOL false} 24 | | number {NUM (int_of_string (Lexing.lexeme lexbuf))} 25 | | id {ID (Lexing.lexeme lexbuf)} 26 | | eof {EOF} 27 | | _ { print_endline (Lexing.lexeme lexbuf); raise LexicalError } 28 | 29 | and comment = parse 30 | | "(*" {comment_depth := !comment_depth+1; comment lexbuf} 31 | | "*)" {comment_depth := !comment_depth-1; 32 | if !comment_depth > 0 then comment lexbuf } 33 | | eof {raise Eof} 34 | | _ {comment lexbuf} 35 | -------------------------------------------------------------------------------- /homework/hw1/code/main.ml: -------------------------------------------------------------------------------- 1 | open Pgm 2 | open Options 3 | 4 | let main () = 5 | let usageMsg = "./main.native -input filename" in 6 | let _ = Arg.parse options (fun s->()) usageMsg in 7 | let file_channel = open_in !inputfile in 8 | let lexbuf = Lexing.from_channel file_channel in 9 | let pgm = Parser.program Lexer.start lexbuf in 10 | 11 | let t0 = Sys.time () in 12 | let res = Verify.run pgm in 13 | let t1 = Sys.time () in 14 | 15 | begin 16 | print_endline "===== Verification Result ======"; 17 | match res with 18 | | None -> print_endline "Safe" 19 | | Some (bound,model) -> ( 20 | Printf.printf "Unsafe at bound %d\n" bound; 21 | let error_trace = Trace.gen pgm bound model in 22 | print_endline ("Error trace: " ^ Trace.to_string error_trace) 23 | ) 24 | end; 25 | Printf.eprintf "Time: %.3f seconds\n%!" (t1 -. t0) 26 | 27 | let _ = main () 28 | -------------------------------------------------------------------------------- /homework/hw1/code/options.ml: -------------------------------------------------------------------------------- 1 | let inputfile = ref "" 2 | let max_bound = ref 30 3 | 4 | let options = 5 | [ 6 | ("-input", Arg.String (fun s -> inputfile := s), "inputfile containing your examples"); 7 | ("-max_bound", Arg.Int (fun n -> max_bound := n), "maximum verification bound (default : 30)") 8 | ] 9 | -------------------------------------------------------------------------------- /homework/hw1/code/parser.mly: -------------------------------------------------------------------------------- 1 | %{ 2 | open Pgm 3 | %} 4 | 5 | %token NUM 6 | %token ID 7 | %token BOOL 8 | %token TRUE FALSE 9 | %token LPAREN RPAREN MINUS 10 | %token AND IF THEN GOTO ELSE EQ 11 | %token MAY COMMA 12 | %token CRITICAL 13 | %token THREAD_A THREAD_B 14 | %token EOF 15 | 16 | %start program 17 | %type program 18 | 19 | %% 20 | 21 | program: 22 | MINUS THREAD_A MINUS thread 23 | MINUS THREAD_B MINUS thread EOF 24 | {(("A",$4),("B",$8))} 25 | 26 | thread: lcmd_lst { $1 } 27 | 28 | lcmd_lst: 29 | | lcmd lcmd_lst {$1::$2} 30 | | { [] } 31 | 32 | lcmd: LPAREN NUM COMMA cmd RPAREN { ($2,$4)} 33 | 34 | cmd: 35 | | MAY NUM {MayGoto $2} 36 | | IF ID THEN GOTO NUM ELSE GOTO NUM { If ($2,$5,$8) } 37 | | ID EQ BOOL AND GOTO NUM { Set ($1,$3,$6) } 38 | | CRITICAL AND GOTO NUM { Critical $4 } 39 | 40 | %% 41 | -------------------------------------------------------------------------------- /homework/hw1/code/pgm.ml: -------------------------------------------------------------------------------- 1 | type t = thread * thread 2 | 3 | and pgm = t 4 | and thread = tid * lcmd list 5 | and lcmd = label * cmd 6 | and label = int 7 | and tid = string 8 | and var = string 9 | 10 | and cmd = 11 | | MayGoto of label 12 | | If of var * label * label 13 | | Set of var * bool * label 14 | | Critical of label 15 | 16 | let get_tid (tid,lcmds) = tid 17 | let get_lcmds (tid,lcmds) = lcmds 18 | 19 | let get_last_state thread = 20 | List.length (get_lcmds thread) - 1 21 | 22 | let collect_vars : pgm -> var BatSet.t 23 | = fun (a,b) -> 24 | let collect' thread : var BatSet.t = 25 | List.fold_left (fun acc (_,cmd) -> 26 | match cmd with 27 | | MayGoto _ | Critical _ -> acc 28 | | If (x,_,_) | Set (x,_,_) -> BatSet.add x acc 29 | ) BatSet.empty (get_lcmds thread) 30 | in 31 | BatSet.union (collect' a) (collect' b) 32 | -------------------------------------------------------------------------------- /homework/hw1/code/pgm.mli: -------------------------------------------------------------------------------- 1 | type t = thread * thread 2 | 3 | and pgm = t 4 | and thread = tid * lcmd list 5 | and lcmd = label * cmd 6 | and label = int 7 | and tid = string 8 | and var = string 9 | 10 | and cmd = 11 | | MayGoto of label 12 | | If of var * label * label 13 | | Set of var * bool * label 14 | | Critical of label 15 | 16 | val get_tid : thread -> tid 17 | val get_lcmds : thread -> lcmd list 18 | val get_last_state : thread -> label 19 | 20 | (* collect all shared variables in a program *) 21 | val collect_vars : pgm -> var BatSet.t 22 | -------------------------------------------------------------------------------- /homework/hw1/code/solver.ml: -------------------------------------------------------------------------------- 1 | open Z3 2 | open Z3.Solver 3 | open Formula 4 | 5 | let ctx = Z3.mk_context [("timeout", "30000")] 6 | 7 | let rec trans : formula -> Z3.Expr.expr 8 | = fun f -> 9 | match f with 10 | | True -> Z3.Boolean.mk_true ctx 11 | | False -> Z3.Boolean.mk_false ctx 12 | | Var x -> Z3.Boolean.mk_const_s ctx x 13 | | Not f -> Z3.Boolean.mk_not ctx (trans f) 14 | | And (f1,f2) -> Z3.Boolean.mk_and ctx [trans f1; trans f2] 15 | | Or (f1,f2) -> Z3.Boolean.mk_or ctx [trans f1; trans f2] 16 | | Imply (f1,f2) -> Z3.Boolean.mk_implies ctx (trans f1) (trans f2) 17 | | Iff (f1,f2) -> Z3.Boolean.mk_iff ctx (trans f1) (trans f2) 18 | 19 | (*********************) 20 | (**** Z3 wrappers ****) 21 | (*********************) 22 | 23 | let mk_solver : unit -> Z3.Solver.solver 24 | = fun () -> Z3.Solver.mk_solver ctx None 25 | 26 | type status = SAT | UNSAT | UNK 27 | 28 | let check_sat : formula -> (status * Z3.Model.model option) 29 | = fun f -> 30 | let solver = mk_solver () in 31 | let _ = Z3.Solver.add solver [trans f] in 32 | (match Z3.Solver.check solver [] with 33 | | UNSATISFIABLE -> (UNSAT, None) 34 | | UNKNOWN -> (UNK, None) 35 | | SATISFIABLE -> 36 | (match Z3.Solver.get_model solver with 37 | | Some m -> (SAT, Some m) 38 | | None -> assert false)) 39 | 40 | let check_validity : formula -> bool 41 | = fun f -> 42 | match check_sat (Not f) with 43 | | UNSAT,_ -> true 44 | | _ -> false 45 | 46 | let string_of_model : Z3.Model.model -> string 47 | = fun m -> Z3.Model.to_string m 48 | 49 | let is_true: Z3.Model.model -> formula -> bool 50 | = fun model f -> 51 | match Z3.Model.eval model (trans f) false with 52 | | Some z3exp -> Z3.Boolean.is_true z3exp 53 | | None -> assert false 54 | -------------------------------------------------------------------------------- /homework/hw1/code/solver.mli: -------------------------------------------------------------------------------- 1 | open Formula 2 | 3 | type status = SAT | UNSAT | UNK 4 | 5 | val check_sat : formula -> (status * Z3.Model.model option) 6 | val string_of_model : Z3.Model.model -> string 7 | 8 | (* return true if the formula is true under the given model *) 9 | val is_true: Z3.Model.model -> formula -> bool 10 | -------------------------------------------------------------------------------- /homework/hw1/code/trace.ml: -------------------------------------------------------------------------------- 1 | open Solver 2 | open Pgm 3 | open Verify_utils 4 | 5 | type t = (label * label) list 6 | and trace = t 7 | 8 | (* generate error trace *) 9 | let gen : pgm -> label -> Z3.Model.model -> trace 10 | = fun (a,b) last_t model -> 11 | 12 | (* find a state of tid at time t *) 13 | let find_state (tid,t) last_l : int = 14 | let rec find l = 15 | if l > last_l then assert false 16 | else if Solver.is_true model (v3 (tid,l,t)) then l 17 | else find (l+1) 18 | in 19 | find 0 20 | in 21 | 22 | (* the last label of each state *) 23 | let a_last, b_last = (get_last_state a, get_last_state b) in 24 | 25 | (* generate a state pair for each time t *) 26 | let rec loop t acc : (label * label) list = 27 | if t > last_t then List.rev acc 28 | else 29 | let a_l = find_state (get_tid a, t) a_last in 30 | let b_l = find_state (get_tid b, t) b_last in 31 | loop (t+1) ((a_l,b_l)::acc) 32 | in 33 | 34 | loop 0 [] 35 | 36 | let to_string : trace -> string 37 | = fun trace -> 38 | trace 39 | |> List.map (fun (l_a,l_b) -> "(" ^ string_of_int l_a ^ "," ^ string_of_int l_b ^ ")") 40 | |> String.concat " -> " 41 | -------------------------------------------------------------------------------- /homework/hw1/code/trace.mli: -------------------------------------------------------------------------------- 1 | type trace 2 | type t = trace 3 | 4 | (* generate error trace *) 5 | val gen : Pgm.pgm -> int -> Z3.Model.model -> trace 6 | 7 | val to_string : trace -> string 8 | -------------------------------------------------------------------------------- /homework/hw1/code/verify.ml: -------------------------------------------------------------------------------- 1 | open Pgm 2 | open Formula 3 | open Solver 4 | open Verify_utils 5 | 6 | exception NotImplemented 7 | 8 | let gen_vc : pgm -> int -> formula 9 | = fun pgm cur_bound -> raise NotImplemented (* TODO *) 10 | 11 | 12 | type res = int * Z3.Model.model 13 | 14 | let run : pgm -> res option 15 | = fun pgm -> 16 | let rec loop (cur_bound:int) : res option = 17 | if cur_bound > !Options.max_bound then None 18 | else begin 19 | Printf.eprintf "[INFO] current bound: %d\n%!" cur_bound; 20 | assert (0 < cur_bound && cur_bound <= !Options.max_bound); 21 | 22 | let vc = gen_vc pgm cur_bound in 23 | match Solver.check_sat vc with 24 | | SAT,Some model -> Some (cur_bound,model) 25 | | UNSAT,None -> loop (cur_bound + 1) 26 | | UNK,None -> failwith "unknown results" 27 | | _ -> assert false 28 | end 29 | in 30 | loop 1 31 | -------------------------------------------------------------------------------- /homework/hw1/code/verify.mli: -------------------------------------------------------------------------------- 1 | type res = int * Z3.Model.model 2 | 3 | val run : Pgm.pgm -> res option 4 | -------------------------------------------------------------------------------- /homework/hw1/code/verify_utils.ml: -------------------------------------------------------------------------------- 1 | open Formula 2 | open Pgm 3 | 4 | (* X_t : a shared variable X at time t *) 5 | let v2 (id,t) = 6 | Var (id ^ "_" ^ string_of_int t) 7 | 8 | (* H_lt : thread H is in state l at time t *) 9 | let v3 (tid,l,t) = 10 | Var (tid ^ "_" ^ string_of_int l ^ string_of_int t) 11 | 12 | (* A_lt : thread A is in state l at time t *) 13 | let a (l,t) = v3 ("A",l,t) 14 | 15 | (* B_lt : thread B is in state l at time t *) 16 | let b (l,t) = v3 ("B",l,t) 17 | -------------------------------------------------------------------------------- /homework/hw1/code/verify_utils.mli: -------------------------------------------------------------------------------- 1 | (* create a variable X_t for representing a shared variable X at time t *) 2 | val v2 : Formula.id * int -> Formula.formula 3 | 4 | (* create a variable H_t for representing a thread H is in state l at time t *) 5 | val v3 : Pgm.tid * int * int -> Formula.formula 6 | 7 | (* create a variable A_lt for representing a thread A is in state l at time t *) 8 | val a : int * int -> Formula.formula 9 | 10 | (* create a variable B_lt for representing a thread B is in state l at time t *) 11 | val b : int * int -> Formula.formula 12 | -------------------------------------------------------------------------------- /homework/hw1/hw1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/homework/hw1/hw1.pdf -------------------------------------------------------------------------------- /setup/_tags: -------------------------------------------------------------------------------- 1 | true: package(Z3) 2 | -------------------------------------------------------------------------------- /setup/ex.py: -------------------------------------------------------------------------------- 1 | from z3 import * 2 | 3 | x = Bool('x') 4 | y = Bool('y') 5 | 6 | f = And (x, y) 7 | 8 | solve (f) 9 | -------------------------------------------------------------------------------- /setup/install_ocaml_mac.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo rm -rf ~/.opam 4 | sudo rm -rf $(which opam) 5 | sudo rm -rf $(which ocaml) 6 | 7 | sudo yes '' | bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)" 8 | opam init -y 9 | eval $(opam env --switch=default) 10 | opam switch create 5.1.1 11 | eval $(opam env --switch=5.1.1) 12 | brew reinstall gmp pkg-config 13 | opam install -y conf-m4.1 ocamlfind ocamlbuild zarith batteries 14 | eval $(opam env) 15 | -------------------------------------------------------------------------------- /setup/install_ocaml_ubuntu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # check if sudo is installed 4 | if ! command -v sudo &> /dev/null; then 5 | apt-get update && apt-get upgrade -y 6 | apt-get install -y --no-install-recommends sudo 7 | fi 8 | 9 | sudo rm -rf ~/.opam && sudo rm -rf $(which opam) && sudo rm -rf $(which ocaml) 10 | 11 | sudo apt-get install -y --no-install-recommends wget gcc build-essential curl unzip bubblewrap ocaml-findlib vim libgmp-dev m4 pkg-config 12 | yes '' | bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)" 13 | opam init -y 14 | eval $(opam env --switch=default) 15 | opam switch create 5.1.1 16 | eval $(opam env --switch=5.1.1) 17 | opam install -y conf-m4.1 ocamlfind ocamlbuild zarith batteries 18 | eval $(opam env) 19 | -------------------------------------------------------------------------------- /setup/install_z3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | wget https://github.com/Z3Prover/z3/archive/refs/tags/z3-4.13.0.tar.gz 4 | tar -xvzf z3-4.13.0.tar.gz 5 | cd z3-z3-4.13.0 6 | 7 | # OCaml binding 8 | python3 scripts/mk_make.py --ml 9 | cd build; make -j 4 10 | sudo make install 11 | 12 | # Python binding 13 | cd ..; mkdir $home/mylib 14 | python3 scripts/mk_make.py --python --prefix=$home --pypkgdir=$home/mylib 15 | export PYTHONPATH=$home/mylib:$PYTHONPATH 16 | cd build; make -j 4 17 | sudo make install 18 | -------------------------------------------------------------------------------- /setup/main.ml: -------------------------------------------------------------------------------- 1 | open Z3 2 | 3 | let () = 4 | let ctx = Z3.mk_context [] in 5 | let a = Boolean.mk_const_s ctx "a" in 6 | let b = Boolean.mk_const_s ctx "b" in 7 | let f = Boolean.mk_and ctx [a; b] in 8 | let solver = Solver.mk_solver ctx None in 9 | match (Solver.check solver [f]) with 10 | | SATISFIABLE -> 11 | (print_endline "SAT"; 12 | match Solver.get_model solver with 13 | | Some m -> print_endline (Model.to_string m) 14 | | None -> assert false) 15 | | UNSATISFIABLE -> print_endline "UNSAT" 16 | | UNKNOWN -> print_endline "UNKNOWN" 17 | -------------------------------------------------------------------------------- /setup/test_ocaml.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ocamlbuild ./main.native -use-ocamlfind -tag thread -Is . 4 | ./main.native 5 | -------------------------------------------------------------------------------- /setup/wsl-install-guideline.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/setup/wsl-install-guideline.pdf -------------------------------------------------------------------------------- /setup/wsl_install.ps1: -------------------------------------------------------------------------------- 1 | function Main { 2 | try { 3 | # Windows 버전 및 빌드 번호 확인 4 | $osInfo = Get-WmiObject -Class Win32_OperatingSystem 5 | $windowsVersion = [System.Version]$osInfo.Version 6 | $windowsBuild = $osInfo.BuildNumber 7 | 8 | if ($windowsVersion.Major -ge 10 -and $windowsVersion.Minor -ge 0 -and $windowsBuild -ge 19041) { 9 | Write-Host "Compatible Windows version detected (Windows 10 version 2004 or later, or Windows 11)." 10 | Write-Host "Activating WSL and Virtual Machine Platform features..." 11 | dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart 12 | dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart 13 | 14 | Write-Host "Installing WSL with Ubuntu..." 15 | wsl --install 16 | 17 | Write-Host "WSL and default Ubuntu distribution have been successfully installed." 18 | Write-Host "A system restart is required to complete the installation." 19 | 20 | $restart = Read-Host "Do you want to restart now? (Y/N)" 21 | if ($restart -eq 'Y' -or $restart -eq 'y') { 22 | Restart-Computer 23 | } 24 | } else { 25 | # 호환되지 않는 버전인 경우 26 | Write-Host "Incompatible Windows version detected. Proceeding with WSL installation and kernel update." 27 | 28 | Write-Host "Activating WSL and Virtual Machine Platform features..." 29 | dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart 30 | dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart 31 | 32 | Write-Host "WSL is already installed. Proceeding with WSL2 kernel update..." 33 | 34 | # WSL2 커널 업데이트 35 | Write-Host "Downloading and installing WSL2 Linux kernel update package..." 36 | $url = "https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi" 37 | if ($env:PROCESSOR_ARCHITECTURE -like "*ARM*") { 38 | $url = "https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_arm64.msi" 39 | } 40 | 41 | $outPath = "$env:TEMP\wsl_update.msi" 42 | try { 43 | Invoke-WebRequest -Uri $url -OutFile $outPath -ErrorAction Stop 44 | Write-Host "WSL2 Linux kernel update package downloaded successfully." 45 | } catch { 46 | Write-Warning "Failed to download WSL2 Linux kernel update package: $_" 47 | Write-Host "Please download and install the WSL2 Linux kernel update package manually from: $url" 48 | return 49 | } 50 | 51 | try { 52 | $installProcess = Start-Process msiexec.exe -Wait -ArgumentList "/I `$outPath /quiet" -PassThru -Verb RunAs 53 | if ($installProcess.ExitCode -eq 0) { 54 | Write-Host "WSL2 Linux kernel update package installed successfully." 55 | } else { 56 | Write-Warning "WSL2 Linux kernel update package installation might have failed. Exit code: $($installProcess.ExitCode)" 57 | } 58 | } catch { 59 | Write-Warning "An error occurred during WSL2 Linux kernel update package installation: $_" 60 | } 61 | 62 | # Ubuntu 설치 여부 확인 및 설치 63 | if (-not (wsl --list --online | Select-String -Pattern "Ubuntu")) { 64 | try { 65 | Write-Host "Attempting to install Ubuntu 22.04.3 LTS..." 66 | $installProcess = Start-Process -FilePath "winget" -ArgumentList "install --id 9PN20MSR04DW --source msstore --accept-package-agreements --accept-source-agreements" -NoNewWindow -PassThru -Wait 67 | 68 | if ($installProcess.ExitCode -eq 0) { 69 | Write-Host "Ubuntu 22.04.3 LTS has been successfully installed." 70 | } else { 71 | Write-Warning "Installation might have failed. Exit code: $($installProcess.ExitCode)" 72 | Write-Host "If the installation failed, please try to install Ubuntu 22.04.3 LTS manually from the Microsoft Store." 73 | } 74 | } catch { 75 | Write-Warning "An error occurred during installation: $_" 76 | Write-Host "Please try to install Ubuntu 22.04.3 LTS manually from the Microsoft Store." 77 | } 78 | } else { 79 | Write-Host "Ubuntu is already installed." 80 | } 81 | 82 | Write-Host "To run Ubuntu, search for 'Ubuntu' in the Start menu." 83 | 84 | # 재시작 요청 85 | $restart = Read-Host "A system restart is recommended to complete the update. Do you want to restart now? (Y/N)" 86 | if ($restart -eq 'Y' -or $restart -eq 'y') { 87 | Restart-Computer 88 | } 89 | } 90 | } catch { 91 | Write-Host "An error occurred: $_" 92 | Write-Host "Please check the error and try again." 93 | } 94 | } 95 | 96 | # 스크립트 실행 97 | Main 98 | -------------------------------------------------------------------------------- /slides/lec-halting.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec-halting.pdf -------------------------------------------------------------------------------- /slides/lec-ocaml.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec-ocaml.pdf -------------------------------------------------------------------------------- /slides/lec0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec0.pdf -------------------------------------------------------------------------------- /slides/lec1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec1.pdf -------------------------------------------------------------------------------- /slides/lec10.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec10.pdf -------------------------------------------------------------------------------- /slides/lec11.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec11.pdf -------------------------------------------------------------------------------- /slides/lec12.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec12.pdf -------------------------------------------------------------------------------- /slides/lec13.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec13.pdf -------------------------------------------------------------------------------- /slides/lec14.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec14.pdf -------------------------------------------------------------------------------- /slides/lec15.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec15.pdf -------------------------------------------------------------------------------- /slides/lec16.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec16.pdf -------------------------------------------------------------------------------- /slides/lec17.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec17.pdf -------------------------------------------------------------------------------- /slides/lec18.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec18.pdf -------------------------------------------------------------------------------- /slides/lec2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec2.pdf -------------------------------------------------------------------------------- /slides/lec3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec3.pdf -------------------------------------------------------------------------------- /slides/lec4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec4.pdf -------------------------------------------------------------------------------- /slides/lec5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec5.pdf -------------------------------------------------------------------------------- /slides/lec6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec6.pdf -------------------------------------------------------------------------------- /slides/lec7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec7.pdf -------------------------------------------------------------------------------- /slides/lec8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec8.pdf -------------------------------------------------------------------------------- /slides/lec9.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gist-pal/ec4219-software-engineering/6e9f4f1be219d769dd1fd866d0ad30f1950fa5ce/slides/lec9.pdf --------------------------------------------------------------------------------