theory HSV_tasks_2022 imports Complex_Main begin section "Task 1: Full adders" fun halfadder :: "bool * bool \ bool * bool" where "halfadder (a,b) = ( let cout = (a \ b) in let s = (a \ b) \ \(a \ b) in (cout, s))" fun fulladder :: "bool * bool * bool \ bool * bool" where "fulladder (a,b,cin) = ( let (tmp1, tmp2) = halfadder(a,b) in let (tmp3, s) = halfadder(cin,tmp2) in let cout = tmp1 | tmp3 in (cout, s))" fun b2i :: "bool \ int" where "b2i (b) = (if (b) then 1 else 0)" theorem "\a b.(co,s) = halfadder(a,b) \ (2*b2i(co)+b2i(s)) = (b2i(a)+b2i(b))" by auto theorem "\a b ci.(co,s) = fulladder(a,b,ci) \ (2*b2i(co)+b2i(s)) = (b2i(a)+b2i(b)+b2i(ci))" by auto section "Task 2: Fifth powers" theorem "(n::nat)^5 mod 10 = n mod 10" proof (induct n) case 0 thus ?case by simp next case (Suc n) have d2:"((n::nat)^4 + n) mod 2 = 0" by simp hence d10:"(5*((n::nat)^4 + n)) mod 10 = 0" by (metis mult_0_right mult_2_right mult_mod_right numeral_Bit0) assume IH:"n ^ 5 mod 10 = n mod 10" have "(Suc n)^5 = (n + 1)^5" by simp have "... = n^5 + 5*(n^4 + n) + 10*n^3 + 10*n^2 + 1" by algebra have "... mod 10 = (n^5 + 5*(n^4 + n) + 1) mod 10" by (smt (verit, ccfv_SIG) mod_add_cong mod_mult_self2) have "... = (n^5 + 1) mod 10" using d10 by auto thus ?case by (metis Suc Suc_eq_plus1 \(n + 1) ^ 5 = n ^ 5 + 5 * (n ^ 4 + n) + 10 * n ^ 3 + 10 * n\<^sup>2 + 1\ \(n ^ 5 + 5 * (n ^ 4 + n) + 10 * n ^ 3 + 10 * n\<^sup>2 + 1) mod 10 = (n ^ 5 + 5 * (n ^ 4 + n) + 1) mod 10\ mod_Suc_eq) qed theorem "\n::nat.(n^6 mod 10 \ n mod 10)" by (rule exI[where x = 2], simp) section "Task 3: Logic optimisation" (* Datatype for representing simple circuits. *) datatype "circuit" = NOT "circuit" | AND "circuit" "circuit" | OR "circuit" "circuit" | TRUE | FALSE | INPUT "int" (* Simulates a circuit given a valuation for each input wire. *) fun simulate where "simulate (AND c1 c2) \ = ((simulate c1 \) \ (simulate c2 \))" | "simulate (OR c1 c2) \ = ((simulate c1 \) \ (simulate c2 \))" | "simulate (NOT c) \ = (\ (simulate c \))" | "simulate TRUE \ = True" | "simulate FALSE \ = False" | "simulate (INPUT i) \ = \ i" (* Equivalence between circuits. *) fun circuits_equiv (infix "\" 50) (* the "50" indicates the operator precedence *) where "c1 \ c2 = (\\. simulate c1 \ = simulate c2 \)" (* An optimisation that exploits the following Boolean identities: `a | a = a` `a & a = a` *) fun opt_ident where "opt_ident (NOT c) = NOT (opt_ident c)" | "opt_ident (AND c1 c2) = ( let c1' = opt_ident c1 in let c2' = opt_ident c2 in if c1' = c2' then c1' else AND c1' c2')" | "opt_ident (OR c1 c2) = ( let c1' = opt_ident c1 in let c2' = opt_ident c2 in if c1' = c2' then c1' else OR c1' c2')" | "opt_ident TRUE = TRUE" | "opt_ident FALSE = FALSE" | "opt_ident (INPUT i) = INPUT i" lemma (* test case *) "opt_ident (AND (INPUT 1) (OR (INPUT 1) (INPUT 1))) = INPUT 1" by eval theorem opt_ident_is_sound: "opt_ident c \ c" oops fun area :: "circuit \ nat" where "area (NOT c) = 1 + area c" | "area (AND c1 c2) = 1 + area c1 + area c2" | "area (OR c1 c2) = 1 + area c1 + area c2" | "area _ = 0" section "Task 4: More logic optimisation" lemma (* test case *) "opt_redundancy (AND (INPUT 1) (OR (INPUT 1) (INPUT 2))) = INPUT 1" (* by eval *) oops lemma (* test case *) "opt_redundancy (AND (AND (INPUT 1) (OR (INPUT 1) (INPUT 2))) (OR (AND (INPUT 1) (OR (INPUT 1) (INPUT 2))) (INPUT 2))) = INPUT 1" (* by eval *) oops lemma (* test case *) "opt_redundancy (AND (AND (INPUT 1) (OR (INPUT 1) (INPUT 2))) (OR (INPUT 2) (AND (INPUT 1) (OR (INPUT 1) (INPUT 2))))) = INPUT 1" (* by eval *) oops lemma (* test case *) "opt_redundancy (AND (AND (AND (INPUT 1) (OR (INPUT 1) (INPUT 2))) (OR (INPUT 2) (AND (INPUT 1) (OR (INPUT 1) (INPUT 2))))) (OR (INPUT 1) (INPUT 2))) = INPUT 1" (* by eval *) oops end