(*
* 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 $ *)
let dfsearch ~start ~childgen ~goaltest ~combinator =
let rec search start akku =
(* see if we have reached a goal*)
if goaltest start then
combinator start true akku
else
(
(* produce all children and descend their paths *)
let childs = childgen start in
let path = combinator start false akku in
let rec loop childs =
match childs with
child :: childs ->
let res = search child path in
(* Was this path successfull?*)
if res = None then
loop childs
else
res
| [] -> None
in
loop childs
)
in
search start None
;;
let boundeddfsearch ~start ~childgen ~goaltest ~combinator ~depth =
let rec search start depth akku =
(*check if we already have reached a goal*)
if goaltest start then
combinator start true akku
else
(* maybe we have reached the maximun depth*)
if depth = 0 then
None
else
(
(* generate all the childs and loop over them*)
let childs = childgen start in
let path = combinator start false akku in
let rec loop childs =
match childs with
child :: childs ->
(* recursive call until we find a goal, or exceed the depth *)
let res = search child (depth-1) path in
if res = None then
loop childs
else
res
| [] -> None
in
loop childs
)
in
search start depth None
;;
let iterativedfs ~start ~childgen ~goaltest ~combinator =
(* repeatedly call boundeddfsearch with increasing depth, until we find a solution*)
let rec loop iter =
let res = boundeddfsearch ~start ~childgen ~goaltest ~combinator ~depth:iter in
if res = None then
loop (iter+1)
else
res
in
loop 1
;;
let bfsearch ~start ~childgen ~goaltest ~combinator =
(*create a queue to store all the unexpanded nodes*)
let queue = Queue.create () in
let rec search start akku () =
(* test if we have reached a goal *)
if goaltest start then
combinator start true akku
else
(* generate all the childs and the path leading up to them *)
let childs = childgen start in
let path = combinator start false akku in
(* Add the partialy evaluated functions to the end of the queue *)
let rec loop childs =
match childs with
child :: childs ->
Queue.push (Lazy.lazy_from_fun (search child path)) queue;
loop childs
| [] -> ()
in
loop childs;
(* get the first function from the queue and evaluate it *)
if Queue.is_empty queue then None else Lazy.force_val (Queue.pop queue)
in
search start None ()
;;
let res_comb node found _ =
(* only return something when we have reached a goal *)
if found then Some node else None
;;
let path_comb node found hist =
(* add the current node to the list *)
let res =
match hist with
None -> node :: []
| Some hist -> node :: hist
in
(* when we have reached a goal, it is save to reverse the list
(no further search at this point)*)
if found then Some (List.rev res) else Some res
;;
let exhaustive_search ~start ~childgen ~goaltest ~combinator =
let res = ref [] in
let rec search start akku =
(* see if we have reached a goal*)
if goaltest start then
(*add the current solution to the list of results*)
match (combinator start true akku) with
Some solution -> res := solution :: !res
| None -> ()
else ();
(* produce all children and descend their paths *)
let childs = childgen start in
let path = combinator start false akku in
let rec loop childs =
match childs with
child :: childs ->
(* descend *)
search child path;
(* look at sibblings *)
loop childs
| [] -> ()
in
loop childs
in
search start None;
!res
;;
(*
* $Log$
* Revision 1.6 2007/12/15 18:52:58 till_crueger
* - Updated documentation
* - Moved Log-Tags to a better position in the sources
*
* Revision 1.5 2006/03/26 17:58:25 till_crueger
* Major code cleanup and improvment of the documentation.
*
* Revision 1.4 2006/02/20 20:21:46 till
* Added LGPL to all files
* Added LGPL to package
*
* Revision 1.3 2006/02/20 17:36:01 till
* Improved Makefile
*
* Fixed some minor problems so they won't cause warnings
*
* Revision 1.2 2006/02/11 11:11:12 till
* Added CVS Tags
*
*)