caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Type inference inside exceptions ?
@ 2006-10-06 18:16 Diego Olivier FERNANDEZ PONS
  2006-10-06 20:20 ` [Caml-list] " ketty .
  2006-10-11 22:50 ` Stéphane Glondu
  0 siblings, 2 replies; 11+ messages in thread
From: Diego Olivier FERNANDEZ PONS @ 2006-10-06 18:16 UTC (permalink / raw)
  To: caml-list

     Bonjour,

I would like the type-checker to infer the type inside exceptions (or  
at least to help me in the "guess a type and test" loop).

More specifically, here is my problem:

I have a program that computes the optimal solution of the minimal  
cardinality subset-sum problem with multiplicities. In simple words it  
gives the minimum number of coins you need to reach a given amount of  
money.

val smc : int -> int list -> int list list * int = <fun>
# smc 226 [198; 122; 90; 75; 64; 54; 53; 10; 5; 1];;
- : int list list * int =
([[75; 75; 75; 1]; [122; 64; 10; 10; 10; 10]; [198; 10; 10; 5; 1; 1; 1]],
  198105)

The programs gives all the solutions it found, the last one being the  
optimal (with the total number of backtracks). The best solution is  
kept by side-effects on a global variable.

type environment = {
     mutable solutions : int list list;
     mutable backtracks : int;
     mutable card : int
   }

exception Fail

let rec min_card env = fun to_reach chosen candidates ->
   if (to_reach = 0) then
     match compare env.card (List.length chosen) with
       | n when n <= 0 ->
	  env.backtracks <- env.backtracks + 1;
	  raise Fail
       | _ ->
	  env.solutions <- chosen :: env.solutions;
	  env.card <- List.length chosen;
	  raise Fail
   else
     match candidates with
       | [] ->
	  env.backtracks <- env.backtracks + 1;
	  raise Fail
       | x :: tail when x > to_reach -> min_card env to_reach chosen tail
       | x :: tail ->
	  try
	    min_card env (to_reach - x) (x :: chosen) candidates
	  with Fail ->
	    min_card env to_reach chosen tail

let rec smc = fun to_reach list ->
   let env = { solutions = []; backtracks = 0; card = max_int } in
     try
       min_card env to_reach [] (List.sort (fun x y -> compare y x) list)
   with Fail -> (List.map List.rev env.solutions, env.backtracks)

Now I want the program not to return all the solutions but only the  
first solution it found and a list of continuations that I can launch  
again if a better solution is required.

Therefore I add a second exception
type continuation = ...
exception Solution of int * continuation list

And I collect the continuations from the try ... catch when the left  
tree happens to contain a solution

try
    explore left subtree
with
   | Fail -> explore right subtree
   | Solution (s, cont) ->
     let c = function () -> explore right subtree in
       raise Solution (s, c :: cont)

Not knowing the type of the continuation, I just tried unit -> int

Here is the detailed code

type continuation = unit -> int
exception Solution of int * continuation list

let rec min_card env = fun to_reach chosen candidates ->
   if (to_reach = 0) then
     match compare env.card (List.length chosen) with
       | n when n <= 0 ->
	  env.backtracks <- env.backtracks + 1;
	  raise Fail
       | _ ->
	  env.solutions <- chosen :: env.solutions;
	  env.card <- List.length chosen;
	  raise (Solution (List.length chosen, []))
   else
     match candidates with
       | [] ->
	  env.backtracks <- env.backtracks + 1;
	  raise Fail
       | x :: tail when x > to_reach -> min_card env to_reach chosen tail
       | x :: tail ->
	  try
	    min_card env (to_reach - x) (x :: chosen) candidates
	  with
	    | Fail -> min_card env to_reach chosen tail
	    | Solution (s, continuation) ->
		let c = fun () -> min_card env to_reach chosen tail in
		  raise (Solution (s, (c :: continuation)))

I first wrap without catching the exceptions and test

let smc = fun to_reach list ->
   let env = { solutions = []; backtracks = 0; card = max_int } in
       min_card env to_reach [] list

# val smc : int -> int list -> int = <fun>
# smc 226 [198; 122; 90; 75; 64; 54; 53; 10; 5; 1];;
Exception: Solution (7, [<fun>; <fun>; <fun>; <fun>; <fun>; <fun>; <fun>]

Seems correct.

Now I try to extract the integer

let smc = fun to_reach list ->
   try
     let env = { solutions = []; backtracks = 0; card = max_int } in
       min_card env to_reach [] list
   with Solution (c, l) -> c

# val smc : int -> int list -> int = <fun>
# smc 226 [198; 122; 90; 75; 64; 54; 53; 10; 5; 1];;
- : int = 7

Correct.

Now I try to extract the continuation list

let smc = fun to_reach list ->
   let env = { solutions = []; backtracks = 0; card = max_int } in
     try
       min_card env to_reach [] list
     with Solution (c, l) -> l

This expression has type continuation list but is here used with type int

Ok. I have to correct the type of continuation by hand

lets try [type continuation = unit -> (unit -> int)]

This expression has type continuation list but is here used with type
   unit -> int

lets try [type continuation = Cont of (unit -> continuation)]
and [let c = Cont (fun () -> ... ) in raise Solution (s, c :: cont)]

This expression has type continuation list but is here used with type
   continuation

lets try [type continuation = Cont of (unit -> continuation list)]

# val smc : int -> int list -> continuation list = <fun>
# smc 226 [198; 122; 90; 75; 64; 54; 53; 10; 5; 1];;
- : continuation list =
[Cont <fun>; Cont <fun>; Cont <fun>; Cont <fun>; Cont <fun>; Cont <fun>;
  Cont <fun>]

Great ! Now I want the solution, its cardinality and the continuation list

lets try ...

          Diego Olivier


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Type inference inside exceptions ?
  2006-10-06 18:16 Type inference inside exceptions ? Diego Olivier FERNANDEZ PONS
@ 2006-10-06 20:20 ` ketty .
  2006-10-10 10:28   ` Diego Olivier FERNANDEZ PONS
  2006-10-11 22:50 ` Stéphane Glondu
  1 sibling, 1 reply; 11+ messages in thread
From: ketty . @ 2006-10-06 20:20 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 278 bytes --]

On 10/6/06, Diego Olivier FERNANDEZ PONS <diego.fernandez_pons@etu.upmc.fr>
wrote:

> I would like the type-checker to infer the type inside exceptions (or
> at least to help me in the "guess a type and test" loop).



I'd like it to infer the types of record-fields as well :)

[-- Attachment #2: Type: text/html, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Type inference inside exceptions ?
  2006-10-06 20:20 ` [Caml-list] " ketty .
@ 2006-10-10 10:28   ` Diego Olivier FERNANDEZ PONS
  0 siblings, 0 replies; 11+ messages in thread
From: Diego Olivier FERNANDEZ PONS @ 2006-10-10 10:28 UTC (permalink / raw)
  To: ketty .; +Cc: caml-list

Quoting "ketty ." <kattlachan@gmail.com>:

>> I would like the type-checker to infer the type inside exceptions (or
>> at least to help me in the "guess a type and test" loop).
>
> I'd like it to infer the types of record-fields as well :)

WISH GRANTED.

type ('a, 'b, 'c) environment = {
     mutable solutions : 'a;
     mutable backtracks : 'b;
     mutable objective : 'c
}

let min_card = fun env ... -> ...

# val min_card :
   (int list list, int, int) environment ->
   int -> int list -> int list -> int list * int list continuation list =
   <fun>

The typechecker inferred the type of your record-fields.

Polymorphic exceptions are forbidden because they could break the type  
system, leading to a ['a -> 'b] type. That is why I asked for "type  
inference" or any kind of useful help and not for "polymorphic  
exceptions". I would accept the compiler to deny the use of the  
exception if it is not monomorphic.

         Diego Olivier


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Type inference inside exceptions ?
  2006-10-06 18:16 Type inference inside exceptions ? Diego Olivier FERNANDEZ PONS
  2006-10-06 20:20 ` [Caml-list] " ketty .
@ 2006-10-11 22:50 ` Stéphane Glondu
  2006-10-13 12:23   ` Diego Olivier FERNANDEZ PONS
  1 sibling, 1 reply; 11+ messages in thread
From: Stéphane Glondu @ 2006-10-11 22:50 UTC (permalink / raw)
  To: Diego Olivier FERNANDEZ PONS; +Cc: caml-list

Diego Olivier FERNANDEZ PONS a écrit :
> Now I want the program not to return all the solutions but only the
> first solution it found and a list of continuations that I can launch
> again if a better solution is required.

I don't really understand what you are doing: why do you generate a list
of continuations instead of a single one? Don't you want a kind of lazy
list?

> Here is the detailed code
> [...]
> Great ! Now I want the solution, its cardinality and the continuation list

Does this code really do what you expect? Did you take into
consideration multiple executions of your continuations? I am rather
unconfident with your single mutable variable...

> lets try ...

Is this the end of your mail?

-- 
Stephane Glondu



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Type inference inside exceptions ?
  2006-10-11 22:50 ` Stéphane Glondu
@ 2006-10-13 12:23   ` Diego Olivier FERNANDEZ PONS
  2006-10-13 12:42     ` Pietro Abate
  0 siblings, 1 reply; 11+ messages in thread
From: Diego Olivier FERNANDEZ PONS @ 2006-10-13 12:23 UTC (permalink / raw)
  To: Stéphane Glondu; +Cc: caml-list

     Bonjour,

Quoting Stéphane Glondu <steph@glondu.net>:
> I don't really understand what you are doing: why do you generate a list
> of continuations instead of a single one?

Reordering the continuations to continue the computation in an other  
branch than the deepest try ... fail is a classical technique in  
combinatorial optimization. The way you order your continuations  
defines a "node ordering strategy", most usual being :
- stack -> depth first search
- queue -> limited discrepancy search
- priority queue -> best first search

> Don't you want a kind of lazy list?

I first wrote a code that solves the problem completely.
Then I modified the code to handle continuations of the form (unit ->  
somthing)
Then I replaced (unit -> something) with a lazy list
Finally I kept the list of continuations but send it back by function  
return instead of an exception [And type inference DOES work in that  
case !]

I am "complaining" because the compile DOES infer types within  
exceptions but does not allow you to let him fix the type the way he  
needs. It only says "It is not what I was expecting, so your function  
won't compile, sorry".

As far as I understand the reason is to avoid polymorphic exceptions  
but this could have been done just forbidding the final result to be  
polymorphic or typechecking and not compiling, or giving me a way to  
just typecheck without creating the value.

> Does this code really do what you expect?

Reasonably

>> lets try ...
>
> Is this the end of your mail?

Unless you want a complete log of everything I tried when developping  
that code...

         Diego Olivier


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Type inference inside exceptions ?
  2006-10-13 12:23   ` Diego Olivier FERNANDEZ PONS
@ 2006-10-13 12:42     ` Pietro Abate
  2006-10-14 19:56       ` Reordering continuations (was :Type inference inside exceptions ?) Diego Olivier FERNANDEZ PONS
  0 siblings, 1 reply; 11+ messages in thread
From: Pietro Abate @ 2006-10-13 12:42 UTC (permalink / raw)
  To: caml-list, caml-list

On Fri, Oct 13, 2006 at 02:23:17PM +0200, Diego Olivier FERNANDEZ PONS wrote:
> Quoting St??phane Glondu <steph@glondu.net>:
> >I don't really understand what you are doing: why do you generate a list
> >of continuations instead of a single one?
> Reordering the continuations to continue the computation in an other  
> branch than the deepest try ... fail is a classical technique in  
> combinatorial optimization. The way you order your continuations  
> defines a "node ordering strategy", most usual being :
> - stack -> depth first search
> - queue -> limited discrepancy search
> - priority queue -> best first search

Can you give some pointer about this technique ... I guess I've already
seen/used it, but maybe in disguise... is this related with delimited
continuations and some kind of lookahead technique to detect failures
and backtrack ?

thanks!
:)
p

-- 
++ Blog: http://blog.rsise.anu.edu.au/?q=pietro
++ 
++ "All great truths begin as blasphemies." -George Bernard Shaw
++ Please avoid sending me Word or PowerPoint attachments.
   See http://www.fsf.org/philosophy/no-word-attachments.html


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Reordering continuations (was :Type inference inside exceptions ?)
  2006-10-13 12:42     ` Pietro Abate
@ 2006-10-14 19:56       ` Diego Olivier FERNANDEZ PONS
  2006-10-16  9:25         ` [Caml-list] " Diego Olivier FERNANDEZ PONS
  0 siblings, 1 reply; 11+ messages in thread
From: Diego Olivier FERNANDEZ PONS @ 2006-10-14 19:56 UTC (permalink / raw)
  To: Pietro Abate; +Cc: caml-list

Quoting Pietro Abate <Pietro.Abate@anu.edu.au>:

>> Reordering the continuations to continue the computation in an other
>> branch than the deepest try ... fail is a classical technique in
>> combinatorial optimization. The way you order your continuations
>> defines a "node ordering strategy", most usual being :
>> - stack -> depth first search
>> - queue -> limited discrepancy search
>> - priority queue -> best first search
>
> Can you give some pointer about this technique ... I guess I've already
> seen/used it, but maybe in disguise... is this related with delimited
> continuations and some kind of lookahead technique to detect failures
> and backtrack ?

This topic is shared by a lot of domains including combinatorial
optimization [linear (integer) programming, constraint programming,
dedicated algorithms], automatic theorem proving [SAT and related],
incremental computation [self-adjusting algorithms], functional
programming, data structures, etc.

I will divide my answer in several parts :
1. Relation with (limited) continuations
2. Reordering continuations
3. Implementing reversibility : copying vs trailing


1. Relation with (limited) continuations

Basically, you did a computation (e.g. computed some shortest path),
where you used the fact that x = 2 and you want to go back to a previous
state where x != 2 because :
- not knowing the value of x, you did the hypothesis x = 2 and now
want to try its negation [implicit enumeration algorithms]
- the data of you program changed and now x = 3 [self adjusting
algorithms]
- any other reason (e.g. debugging)

In combinatorial optimization, we call this REVERSIBILITY (talk about  
its links with persistence later).

Unlike (delimited) continuations, you don't need to go back to any
possible previous state but only to specific points. These points are
named CHOICE POINTS and can only be placed on some "events" which is
the minimum granularity of your backtracking algorithm.

This is similar to the Caml debugger (events and jumps).

Programming languages for combinatorial optimization integrate some
facilities to declare choice points (in other words continuation
"holes") and provide a set of possible events on
DECISION VARIABLES (typically when the domain of the variable changes).
All this is then translated by the underlying algorithm to a low-level
implementation that can use several techniques (call/cc, exceptions,
persistence, reified continuations, etc.)

Example: OPL (The Optimization Programming Language, Pascal van Hentenryck
MIT Press 1996) introduces two constructions [dvar] and [try] that
allows you to write (simplified syntax)

dvar x [0..3]  // possible events
dvar y [0..3]  // possible events

subject to

     x + y == 2

search

     forall v in x, try (x == v) // continuation holes

Compare this with a much more complex continuation framework
integrated to a general purpose language like

R. Kent Dybvig, Simon Peyton Jones, and Amr Sabry:
A Monadic Framework for Delimited Continuations

I can now answer to the first question

> is this related with delimited continuations

Yes but I would say that we use these techniques (continuations,
persistent data structures, backtracking monads, exceptions) more
than contribute to their study.

2. Reordering continuations

In an implicit enumeration algorithm, all the possible continuations
have to be visited (that is the "enumeration" part of the name) but
some orders may be better than others because one accumulates
information while visiting the continuations and this allow the
algorithm to prove that visiting some continuations is useless (that
is the "implicit" part of the name).

Usually you have for an optimization problem:
- a global lower and upper bound (that improves while the algorithm
runs)
- local lower and upper bounds (that depend on your position in the
tree, in other words the sequence of decision that have been take to
arrive to that point e.g. x1 == 0, x2 == 3, y3 == 0, all other
unknown).

If you are minimizing, and the local lower bound is already higher
than the global upper bound, you can prune all the branch. All those
continuations won't be visited.

There are tons of search strategies according to the type of problem
you are solving. They all combine
- a variable ordering (this gives the shape to the tree)
- a node ordering (this says how the nodes are visited)

As I said before, the most usual node orderings are depth first,
limited discrepancy and best-first. You will find a good entering
point with the original LDS paper (on the web)

William D. Harvey, Matthew L. Ginsberg
Limited Discrepancy Search (IJCAI 1995)

> Is this related to [...] some kind of lookahead technique to detect  
> failures and backtrack ?

I would not call that lookahead but rather using statistical  
correlation between the data and the position in the tree of the  
optimal solution to find it soon.

3. Implementing reversibility

There are two classical ways to implement reversibility in
combinatorial optimization engines : copy and trailing

A copy engine just maintains a copy of the decision variables for all
opened nodes. When you jump from a node to another, you just have to
select the correct version.

In functional languages, the simplest implementation is combining
recursive calls (and exceptions) with persistent data structures.

Example : Alain Frish's sudoku solver

But some engines written in imperative languages also work that way

Example : Gecode in C++ (Alice is its SML frontend).

In the trailing technique, there is a single state (current state)
that has to be synchronized every time the "focus" is moved in the
search tree. Usually this leads to stamped version arrays data
structures, that save all the local differences in a TRAIL.

Within trailing engines, the state your program would have in another node is
distributed in the central memory. To jump to another node you have to
"replay" the paths in the search tree: you physically undo the
modifications until the lowest common ancestor between the current
node and the desired node and you do again all the "forward" decisions
needed to reach the node.

An example of trailing engine in a functional language is FaCiLe
(Pascal Brisset et Nicolas Barnier, Caml).

An example of trailing for self-adjusting algorithms is given by

Umut A. Acar, Guy E. Blelloch, Matthias Blume, Kanat Tangwongsan.
An Experimental Analysis of Self-Adjusting Computation (PLDI 2006)

The original LDS paper is written supposing that the underlying engine
uses trailing to implement reversibility.

There is also something named "semantic backtracking". To keep it
short, instead of physically restoring the state, you restore it
logically, in other words you change your current state in order to be
semantically equivalent to the state you want to reach.
Imagine a fixed-size queue implemented by an array with a first and
last pointer. Then any "translated" array is semantically equivalent,
so instead of physically restoring the queue you had, you can put the
elements back in a "forward" way.

Pascal Van Hentenryck and Viswanath Ramachandran
Backtracking without trailing in CLP (R) (TOPLAS 1995)

         Diego Olivier


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Reordering continuations (was :Type inference inside exceptions ?)
  2006-10-14 19:56       ` Reordering continuations (was :Type inference inside exceptions ?) Diego Olivier FERNANDEZ PONS
@ 2006-10-16  9:25         ` Diego Olivier FERNANDEZ PONS
  2006-10-17 12:33           ` Diego Olivier FERNANDEZ PONS
  0 siblings, 1 reply; 11+ messages in thread
From: Diego Olivier FERNANDEZ PONS @ 2006-10-16  9:25 UTC (permalink / raw)
  To: Pietro Abate; +Cc: caml-list

     Bonjour,

Here is some code that shows the effect of reordering continuations in  
a combinatorial problem. The first one is the minimum cardinality  
subset-sum problem, the second returns the order in which the leaves  
of the search tree are visited.

Each time a solution is found, the number of failures is printed. This  
gives an idea of how much time was spent to find the solution.

(* subsetsum in depth first search *)
# let p = smc 47 [39;32;20;19;16;9;1] in solve p (new stack);;
0 fails : 39 1 1 1 1 1 1 1 1
8 fails : 32 9 1 1 1 1 1 1
47 fails : 20 16 9 1 1
61 fails : 20 9 9 9
118 fails : 19 19 9
- : int list list * int =
([[39; 1; 1; 1; 1; 1; 1; 1; 1]; [32; 9; 1; 1; 1; 1; 1; 1]; [20; 16; 9; 1; 1];
   [20; 9; 9; 9]; [19; 19; 9]],
  457)

(* subset sum in limited discrepancy search *)
# let p = smc 47 [39;32;20;19;16;9;1] in solve p (new queue);;
0 fails : 39 1 1 1 1 1 1 1 1
0 fails : 32 9 1 1 1 1 1 1
16 fails : 19 19 9
- : int list list * int =
([[39; 1; 1; 1; 1; 1; 1; 1; 1]; [32; 9; 1; 1; 1; 1; 1; 1]; [19; 19; 9]], 459

The second example builds a tree which leaves are labelled from 0 to  
2^n - 1 from left to right. The order in which the leaves are visited  
is returned.

# let p = label 4 in solve p (new stack);;
- : int list * int =
([0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15], 0)

# let p = label 4 in solve p (new queue);;
- : int list * int =
([0; 8; 4; 2; 1; 12; 10; 9; 6; 5; 3; 14; 13; 11; 7; 15], 0)

Here is the complete code

class type ['a] continuationQueue =
   object
     method push : 'a -> unit
     method pop : 'a
     method is_empty : bool
     method length : int
   end

class ['a] queue =
   (object
     val contents = (Queue.create () : 'a Queue.t)
     method push = fun x -> Queue.push x contents
     method pop = Queue.pop contents
     method is_empty = Queue.is_empty contents
     method length = Queue.length contents
   end : ['a] continuationQueue)

class ['a] stack =
   (object
     val contents = (Stack.create () : 'a Stack.t)
     method push = fun x -> Stack.push x contents
     method pop = Stack.pop contents
     method is_empty = Stack.is_empty contents
     method length = Stack.length contents
   end : ['a] continuationQueue)

type 'a environment = {
     mutable backtracks : int;
     mutable objective : int;
     mutable queue : 'a queue
  }

exception Fail

type 'a continuation = Cont of (unit -> 'a)

let rec print_list = function
   | [] -> print_newline()
   | x :: tail -> print_int x; print_string " "; print_list tail

let rec min_card env = fun to_reach chosen candidates ->
   if (to_reach = 0) then
     match compare env.objective (List.length chosen) with
     | n when n <= 0 ->
	env.backtracks <- env.backtracks + 1;
	raise Fail
     | _ ->
	env.objective <- List.length chosen;
	print_int env.backtracks;
	print_string " fails : ";
	print_list (List.rev chosen);
	(List.rev chosen)
   else
     match candidates with
     | [] ->
	env.backtracks <- env.backtracks + 1;
	raise Fail
     | x :: tail when x > to_reach -> min_card env to_reach chosen tail
     | x :: tail ->
	let c = Cont (fun () -> min_card env to_reach chosen tail) in
	env.queue#push c;
	min_card env (to_reach - x) (x :: chosen) candidates

let smc = fun to_reach list ->
   function env ->
     let c = Cont (function () -> min_card env to_reach [] list) in
     env.queue#push c; env

let rec label_nodes env = fun count remaining_depth ->
   match remaining_depth with
     | 0 -> count
     | n ->
	let c = Cont (fun () -> label_nodes env (2 * count + 1) (n - 1)) in
	  env.queue#push c;
	  label_nodes env (2 * count) (n - 1)

let label = function depth ->
   function env ->
     let c = Cont (fun () -> label_nodes env 0 depth) in
       env.queue#push c; env

let rec solve_rec = function env ->
   if env.queue#is_empty then []
   else
     let Cont c = env.queue#pop in
     try
       let s = c () in
       s :: solve_rec env
     with Fail -> solve_rec env

let solve = fun f queue ->
   let env = { backtracks = 0; objective = max_int; queue = queue } in
   let solutions = solve_rec (f env) in
   (solutions, env.backtracks)

         Diego Olivier


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Reordering continuations (was :Type inference inside exceptions ?)
  2006-10-16  9:25         ` [Caml-list] " Diego Olivier FERNANDEZ PONS
@ 2006-10-17 12:33           ` Diego Olivier FERNANDEZ PONS
  2006-10-19  7:32             ` Looking for references to usage of ocaml in data mining, knowleadge discovery, etc  Dr. Axel Poigné 
  0 siblings, 1 reply; 11+ messages in thread
From: Diego Olivier FERNANDEZ PONS @ 2006-10-17 12:33 UTC (permalink / raw)
  To: Francisco José Valverde Albacete; +Cc: caml-list

     Bonjour,

I am not sure I understood all of your comments but I can at least answer
to a few of them

[Francisco Valverde a écrit]
> It is also the technique to find alternative recognition hypotheses  
> in most speech recognizers (hypothesis graph search with dynamical  
> reordering & pruning of nodes & backtrack, in a nutshell).

Parsers and combinatorial optimization engines are equivalent in the
sense that for every combinatorial problem you can find a grammar and
a string which solutions are the solutions of the combinatorial
problem (think of Prolog) and reciprocally under some reasonable
hypothesis. This is true for anything that gets close to NP-completeness
but in this case both problems are really closely related.

Parsing Techniques explain how to compile a non-deterministic stack automaton
(e.g. an LR grammar with conflicts, an ambiguous grammar) to an
exception based implicit enumeration algorithm (i.e. a recursive  
ascent parser implemented with a set of recursive functions).

Parsing Techniques - A Practical Guide
Dick Grune and Ceriel J.H. Jacobs (1990) on the web

A few years ago I put on my web page a few toy LR parser written in
that way and an Early parser (in which continuations reified to lists
are executed in a breath-first-search way and is some sense memoized).

There are working parsers that use this technique, including

- Frown, an LALR(k) parser generator for Haskell
Ralf Hinze, Ross Paterson

- The Essence parser generator for Scheme
Mike Sperber (uses partial evaluation instead of code generation)

Both come with interesting papers.

The general idea is that the definition of the search space
(construction of a stack automaton) and its exploration (optimistic -> depth
first search = LR, pessimistic -> breath first search = Earley) are
two orthogonal things.

The Tomita parsers are a bit more difficult since they are equivalent to
a form of memoization inside an implicit enumeration algorithm (or
conversely a form of duplication at ambiguous points inside a
deterministic algorithm).

Speech recognition is a more complicated because of uncertainty but it  
is the same idea.

> Explicit management of the continuation queue/stack/whatever is a
> boon I didn't expect, though! If you come up with a library or  
> modular solution please let me know.

It is rather specific to constraint programming but there is a paper that
describes a system that allows you to specify in a declarative way the
order in which the continuations will be executed. The trick is to
lift the combinatorial engine to the search tree: the execution order
of the continuations is itself a combinatorial program (I believe they
do not bootstrap the solver however but use an ad-hoc mini-solver instead).

ToOLS: A Library for Partial and Hybrid Search Methods (2003)
Simon de Givry, Laurent Jeannin
Proceedings CPAIOR '03 (on Citeseer)

It is only applicable when the continuations are restricted enough to
carry a clear semantics. If you are looking for more low-level things
you should have a look to Oleg's work, and related papers.

Native delimited continuations in (byte-code) OCaml
http://okmij.org/ftp/Computation/Continuations.html#caml-shift

> I'm looking forward to hearing more about your research, as always.

Well I can at least explain what I have been trying to do ultimately
with continuations and memoization.

Pisinger introduced a very fast class of algorithms for knapsack
problems which are an hybridisation of implicit enumeration (branch and
bound) and dynamic programming.

Knapsack Problems
Hans Kellerer, Ulrich Pferschy, David Pisinger
Springer 2004

[Good overview : New trends in exact algorithms for the 0-1 knapsack
problem. EJOR 123 (2000), on the web]

I want to automatically derive similar algorithms from any implicit
enumeration algorithms thanks to memoization.

There is an additional problem related to combinatorial optimization:
computing an average solution (50% of the optimum) takes 1s,
a good solution (90%) 1 minute, an excellent solution (99%) 1 hour,
the optimal solution 1 day, and the optimality proof 1 week.
But you usually don't need the optimal solution to a subproblem, only
a good enough "lower bound" that enables you either to cut the branch
or to decide to dive in it.

- From the memoization point of view, one has to generalize the
   value table to a improving pair of bounds + continuation stack

   instead of memo : (int -> int) -> int -> int

   you need memo : (int -> int * continuation queue) -> (int, int) ref *
   continuation queue

   if you want the confidence interval [lower bound..upper bound] of a
   subproblem to be refined, you just execute a few more continuations.

- From the implicit enumeration point of view, one has to order the
   continuations in a "structured stack" where the continuations are
   indexed by the sub-problems they are solving, and add a cache.

   You also need to use the relations between the subproblems: the
   optimal solution of a more constrained problem is an upper bound of
   the optimal solution of a less contrained problem.

   For instance:
   min cardinality subsetsum 15 [17;13;7;5;2] == 2
   min cardinality subsetsum 15 [17;15;13;12;11;7;5;2;1] == 1

This gives you upper and lower bounds form the keys of the table and
the cached partial results.

I had the idea when reading papers on adaptive functional programming,
specially those of U. Acar (http://ttic.uchicago.edu/~umut/papers/index.html)

Umut A. Acar, Guy E. Blelloch, Matthias Blume, Kanat Tangwongsan.
An Experimental Analysis of Self-Adjusting Computation (PLDI 2006)

         Diego Olivier


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Looking for references to usage of ocaml in data mining, knowleadge discovery, etc
  2006-10-17 12:33           ` Diego Olivier FERNANDEZ PONS
@ 2006-10-19  7:32             `  Dr. Axel Poigné 
  2006-10-19 14:06               ` [Caml-list] " Markus Mottl
  0 siblings, 1 reply; 11+ messages in thread
From:  Dr. Axel Poigné  @ 2006-10-19  7:32 UTC (permalink / raw)
  To: caml-list

Hello

I look for references to usage of ocaml in Data Mining, Knowleadge  
Discovery. Inductive Logic Programming, Vector support Machines and  
related topics. I have browsed the net but entries are sparse.

I would like to try using Ocaml in these areas and want to avoid  
double work.

Axel


------------------------------------------------------------------------ 
-------------------------
Dr.rer.nat. Dipl.Ing.Axel Poigné

Fraunhofer Institut Intelligente Analyse- und Informationssysteme - IAIS
Department Knowledge Discovery
Schloss Birlinghoven
D-53754 Sankt Augustin

Tel.: +49 (0) 2241 14 - 2440
Fax: +49 (0) 2241 14 - 42440
e-Mail: axel.poigne@ais.fraunhofer.de
web:  http://www.ais.fraunhofer.de/~ap
------------------------------------------------------------------------ 
------------------------



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Caml-list] Looking for references to usage of ocaml in data mining, knowleadge discovery, etc
  2006-10-19  7:32             ` Looking for references to usage of ocaml in data mining, knowleadge discovery, etc  Dr. Axel Poigné 
@ 2006-10-19 14:06               ` Markus Mottl
  0 siblings, 0 replies; 11+ messages in thread
From: Markus Mottl @ 2006-10-19 14:06 UTC (permalink / raw)
  To: Dr. Axel Poigné; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 1303 bytes --]

On 10/19/06, Dr. Axel Poigné <axel.poigne@iais.fraunhofer.de> wrote:
>
> I look for references to usage of ocaml in Data Mining, Knowleadge
> Discovery. Inductive Logic Programming, Vector support Machines and
> related topics. I have browsed the net but entries are sparse.
>
> I would like to try using Ocaml in these areas and want to avoid
> double work.
>

You may have already found AIFAD (Automated Induction of Functions over
Algebraic Datatypes), a symbolic machine learning program, which generalizes
induction of decision trees to structured values, and is pretty efficient
even on large amounts of data.  You can find the sources and documentation
here:

  http://www.ocaml.info/aifad

It's also available as a Godi-package, which makes it easier to install,
because it depends on other libraries.

We use Lacaml, a fairly complete and convenient binding to BLAS/LAPACK, here
at Jane Street Capital for implementing numeric algorithms to analyse very
substantial amounts of financial data.  I unfortunately cannot give you
details about this work.  You can get Lacaml through Godi or download it
here:

  http://www.ocaml.info/home/ocaml_sources.html#LACAML

Best regards,
Markus

-- 
Markus Mottl        http://www.ocaml.info        markus.mottl@gmail.com

[-- Attachment #2: Type: text/html, Size: 1909 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2006-10-19 14:06 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-10-06 18:16 Type inference inside exceptions ? Diego Olivier FERNANDEZ PONS
2006-10-06 20:20 ` [Caml-list] " ketty .
2006-10-10 10:28   ` Diego Olivier FERNANDEZ PONS
2006-10-11 22:50 ` Stéphane Glondu
2006-10-13 12:23   ` Diego Olivier FERNANDEZ PONS
2006-10-13 12:42     ` Pietro Abate
2006-10-14 19:56       ` Reordering continuations (was :Type inference inside exceptions ?) Diego Olivier FERNANDEZ PONS
2006-10-16  9:25         ` [Caml-list] " Diego Olivier FERNANDEZ PONS
2006-10-17 12:33           ` Diego Olivier FERNANDEZ PONS
2006-10-19  7:32             ` Looking for references to usage of ocaml in data mining, knowleadge discovery, etc  Dr. Axel Poigné 
2006-10-19 14:06               ` [Caml-list] " Markus Mottl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).