All pastes #676560 Raw Edit

Anonymous

public text v1 · immutable
#676560 ·published 2007-08-31 05:22 UTC
rendered paste body
type expr = Var of int | Prod of expr * expr | LInv of expr | RInv of expr
let prod x y = Prod (x, y) (* prod is the group product *)

let rec string_of_expr expr =
    match expr with
        |LInv a -> "L(" ^ (string_of_expr a) ^ ")"
        |RInv a -> "R(" ^ (string_of_expr a) ^ ")"
        |Var a -> "g_" ^ (string_of_int a)
        |Prod (a, b) -> "(" ^ (string_of_expr a) ^
                        "*" ^ (string_of_expr b) ^ ")"

(* check to see if two expressions are identical *)
let rec equiv expr1 expr2 =
    match (expr1, expr2) with
        |(LInv a, LInv b) -> equiv a b
        |(RInv a, RInv b) -> equiv a b
        |(Var a, Var b) -> a = b
        |(Prod (a, b), Prod (c, d)) -> (equiv a c) && (equiv b d)
        |_ -> false


let rec test_all test lst ele =
    match lst with
        |[] -> false
        |x :: xs -> if (test x ele) then true else test_all test xs ele

let nub_by test lst =
    let rec nbr test listin listout =
        match listin with
            |[] -> listout
            |x :: xs ->
                if (test_all test listout x)
                    then nbr test xs listout
                    else nbr test xs (x :: listout) in
    nbr test lst []

let prod_id_l expr =
    prod (Var 0) expr

let prod_id_r expr =
    prod expr (Var 0)

let prod_red expr =
    match expr with
         Prod (a, Var 0)
        |Prod (Var 0, a) -> a
        |_ -> expr

let assoc_l expr =
    match expr with
        Prod (a, Prod (b, c)) -> Prod (Prod (a, b), c)
        |_ -> expr

let assoc_r expr =
    match expr with
        Prod (Prod (a, b), c) -> Prod (a, Prod (b, c))
        |_ -> expr

let inv_red expr =
    match expr with
        Prod (a, RInv b)
       |Prod (LInv a, b) -> if (equiv a b) then (Var 0) else expr
       |_ -> expr

let list_of_ids = [prod_id_l; prod_id_r; prod_red; assoc_l; assoc_r; inv_red]

let rec substitute expr_lst =
    let rec concat_lists lst acc =
        match lst with [] -> acc | x :: xs -> concat_lists xs (x @ acc) in
    let deal_with_this_one expr =
        (* first, try applying to this node *)
        let top_eval = List.map (fun f -> f expr) list_of_ids in
        (* now a bunch of recursion rules to propagate along products *)
        match expr with
            |Prod (expr1, expr2) ->
                let first_half  = List.map (fun expr -> prod expr expr2) (substitute [expr1]) in
                let second_half = List.map (fun expr -> prod expr1 expr) (substitute [expr2]) in
                first_half @ second_half @ top_eval
            |_ -> top_eval in
    let big_expr_lst = List.map deal_with_this_one expr_lst in
    nub_by equiv (concat_lists big_expr_lst [])

let prove_with_hint expr1 expr2 exprstart =
    let rec prv expr1 expr2 results =
        let new_results = substitute results in
        List.iter (fun n -> print_endline (string_of_expr n)) results;
        print_endline "---";
        if (test_all equiv results expr1) && (test_all equiv results expr2)
            then true
            else prv expr1 expr2 new_results in
    prv expr1 expr2 [exprstart]

let prove expr1 expr2 =
    prove_with_hint expr1 expr2 expr1