let update_intruder_knowledge (() : unit) : unit =
        let rec find_match e l =
                match l with [] -> false
                        |(x::ls) ->         if (match_message "(Intruder_, 0)" ""  x "(Intruder_, 0)" "" e)
                                        then true
                                        else find_match e ls
        in
          let deduce_knowledge initial_knowledge =
                let build_knowledge e y =
                        let decomp_y = decompose y in
                        let know_public_key_of_private_key e = 
                                let decomp = decompose e in
                                if(decomp=[]) then false
                                else if((car decomp)="inv" && (find_match (cadr decomp) initial_knowledge)) then true
                                else false
                        in
                        let know_private_key_of_public_key e = ("public_key"=(get_type e)) && (find_match e initial_knowledge) in
                          if(decomp_y<>[])then(
                            (*                                if((car decomp_y)=" && (cadr decomp_y)=e) then [(caddr decomp_y)] *)
                            if((car decomp_y)="scrypt" && 
                                              (* Check that the cypher key unifies with e *)
                                              (match_message "(Intruder_, 0)" "" (cadr decomp_y) "(Intruder_, 0)"  "" e ))
                            then [(caddr decomp_y)]
                            else if((car decomp_y)="xor" && 
                                                   (* Check that the xor right member unifies with e *)
                                                   (match_message "" "" (cadr decomp_y) ""  "" e ))
                            then [(caddr decomp_y)]
                            else if((car decomp_y)="xor" && 
                                                   (* Check that the xor left member unifies with e *)
                                                   (match_message "" "" (caddr decomp_y) ""  "" e ))
                            then [(cadr decomp_y)]
                            else if((car decomp_y)="crypt" && (know_private_key_of_public_key e)) 
                            then [(caddr decomp_y)]
                            else if((car decomp_y)="crypt" && (know_public_key_of_private_key e)) 
                            then [(caddr decomp_y)]
                            else if((car decomp_y)="pair"then (cdr decomp_y)
                            else []
                          )
                          else []
                in
                let rec aux2 elt l res =
                  match l with [] -> res
                                |x::ls ->         let k1 = List.map (fun e -> if(List.mem e initial_knowledge) then "" else e) (build_knowledge x elt) in
                                                let k2 = List.map (fun e -> if(List.mem e initial_knowledge) then "" else e) (build_knowledge elt x) in
                                                aux2 elt ls (k1@k2@res)
                in
                let rec aux l res =
                        match l with [] -> remove_double (remove "" (List.flatten res))
                                |x::ls -> aux ls ((aux2 x ls [])::res)
                in
                aux initial_knowledge []
        in
        let replay =         let set_ref = (get_value_of_var "(Intruder_, 0)" "Set_knowledge"in
                        if(is_a_set set_ref) then (
                                let decomp = decompose(get_value_of_var "x" set_ref) in
                                if(decomp=[]) 
                                then []
                                else (
                                        let knowledge_to_add = 
                                                let rec aux k =
                                                        let tmp = deduce_knowledge k in
                                                        if(tmp<>[]) then aux (tmp@k) 
                                                        else k
                                                in aux (cdr decomp)
                                        in
                                        List.iter (fun k -> add_in_set "(Intruder_, 0)" k "(Intruder_, 0)" "Set_knowledge") knowledge_to_add;
                                        knowledge_to_add
                                )
                        )
                        else []

        in
        let rec add_transition l k new_state new_actions = 
                match l with [] -> (("Intruder_,0,Set_knowledge,Listen_i",ref false)::new_state,(("Intruder_,0,Set_knowledge,Listen_i","Listen_i"), (([],[]), ([],["cons(Listen_i,Set_knowledge)"])), ("Intruder_,0,Set_knowledge,Listen_i",""))::new_actions)
                        |(x::ls) ->         let action_tmp = ( ("Intruder_,"^(string_of_int k)^",Set_knowledge,Listen_i",""), (([],[]), ([],[])), ("Intruder_,"^(string_of_int (- k))^",Set_knowledge,Listen_i", x) ) in
                                        let state_tmp = ("Intruder_,"^(string_of_int (- k))^",Set_knowledge,Listen_i", ref truein
                                        if(List.mem action_tmp  new_actions)
                                        then add_transition ls k new_state new_actions
                                        else add_transition ls (k+1) (state_tmp::new_state) (action_tmp::new_actions)
        in
        automate:=(
        List.map
        (fun (name,id,state,actionsL) ->
                if(name="Intruder_" && id=0) 
                then (
                        let (new_states,new_actions) = add_transition replay 1 [] [] in
                        state:=new_states;
                        (name,id,state,new_actions)
                )
                else (name,id,state,actionsL)
        )
        !automate
        )