let iter ?on_environment ?on_function ?on_behavior ?on_goal () =
  begin
    match on_environment with
    | None -> ()
    | Some phi ->
      Imap.iter
        (fun m k ->
          for i = 1 to k do
            phi (env_name m i)
          done)
        system.environments
  end ;
  if on_function <> None || on_behavior <> None || on_goal <> None
  then
    let sorted_index =
      List.sort
        (fun (k1,_) (k2,_) ->
          if Kernel_function.equal k1 k2 then 0 else
            if Kernel_function.get_name k1 <= Kernel_function.get_name k2
            then -1 else 1)
        (Kfmap.fold (fun k v a -> (k,v)::a) system.index [])
    in
    List.iter
      (fun (kf,bmap) ->
        if (on_behavior <> None || on_goal <> None&&
          not (Imap.is_empty bmap)
        then
          begin
            ( match on_function with
            | None -> ()
            | Some phi -> phi kf ) ;
            let sorted_behaviors =
              List.sort
                (fun (k1,_) (k2,_) -> String.compare k1 k2)
                (Imap.fold (fun k v a -> (k,v)::a) bmap [])
            in
            List.iter
              (fun (b,pset) ->
                if not (WPOset.is_empty pset) then
                  begin
                    ( match on_behavior with
                    | None -> ()
                    | Some phi ->
                      phi kf (if b="" then None else Some b) ) ;
                    match on_goal with
                    | None -> ()
                    | Some f -> WPOset.iter f pset
                  end)
              sorted_behaviors
          end)
      sorted_index