(*
 * lablai - An ML Artificial Inteligence library
 * Copyright (C) 2006  Till Crueger
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *)


(* File $RCSfile$ *)
(* last edited by $Author: till_crueger $ *)
(* $Date: 2007-12-15 19:53:03 +0100 (Sa, 15 Dez 2007) $, $Revision: 29 $*)


type 'a coord = {x : 'a ; y : 'a};;
 
type attribute = Bool of bool | Other of string;;

type data = attribute array;;

type 'a example = {ex_category : 'a ; ex_data : data};;

let sort predicate examples  =
   (* loop over all data we have *)
   let rec loop examples akku =
      match examples with 
         [] -> 
            akku
      | examples -> 
            (* get the first category *)
            let category = predicate (List.hd examples) in
            (* get all data in this category *)
            let filter x = (predicate x) = category in
            let filtered = List.filter filter examples in
            (* get the rest *)
            let rest = List.filter (fun x -> not (filter x)) examples in
            (* continue with the rest *)
            loop rest (filtered :: akku) 
   in
   loop examples []
   ;;
   
let sort_by_cat examples =
   (* sort according to category *)
   let sorted = sort (fun x -> x.ex_category) examples in
   (* clean up by seperating data and categories *)
   (* since categories are the same in each list, we just have to look up the category of the list head *)
   (* then we descend into the real data using List.rev_map *)
   let simplyfied = List.rev_map (fun x -> ((List.hd x).ex_category,List.rev_map (fun y ->y.ex_data) x)) sorted in
   simplyfied;;
   
let count (data : data list) = 
   (* get an array where the nth entry equals the list split according to the nth attribute*)
   let sorter i x = x.(i) in
   let num_attribs = Array.length (List.hd data) in
   let sorted = Array.init num_attribs (fun i -> sort (sorter i) data) in
   (* replace the lists with tupels of their attribute and their lengths *)
   let flatten i dat  = List.map (fun x -> ((List.hd x).(i),List.length x)) dat in
   Array.mapi flatten sorted
   ;;
   
let print_attribute attr =
   match attr with
      Bool var -> if var then print_string "true" else print_string "false"
   |  Other var -> print_string var
   ;;

let create data = data;;

let copy data = Array.copy data;;

let set (data : data) attr value = data.(attr) <- value;;

let get_data data attr = data.(attr);;

(* 
 * $Log$
 * Revision 1.2  2007/12/15 18:52:58  till_crueger
 * - Updated documentation
 * - Moved Log-Tags to a better position in the sources
 *
 * Revision 1.1  2006/03/26 17:58:24  till_crueger
 * Major code cleanup and improvment of the documentation.
 *
 *)