[Haskell-cafe] All possible expressions [was All possible trees]

Andrew Coppin andrewcoppin at btinternet.com
Fri Jun 15 16:44:43 EDT 2007

Andrew Coppin wrote:
> The size of the deepest possible *balanced* tree with N leaves is log2 
> N. The deepest possible *unbalanced* tree has N nodes!

My God... even when I correct myself I make mistakes! >_<

Anyway, I eventually got my program to work. But it's absurdly slow. So 
I'm looking at ways to make it faster.

You'll recall I wanted to construct all possible expressions from a set 
of numbers. The trouble is, the set of ALL possible expressions turns 
out to be vast - 33.6 million, roughly. It takes forever to check them 
all. Part of the problem is that the computer considers x + y and y + x 
to be two seperate expressions, when in fact they are completely 
equivilent. On the other hand, x - y and y - x are most certainly NOT 
equivilent. I am currently sitting down and trying to write some code 
that does the construction correctly, based on some basic algebraic 
properties of the four functions of arithmetic. I'm hoping that if I can 
get it so that fewer expressions are generated, I will have a smaller 
search space to test.

(Of course, one way would be to generate all possible trees and then 
throw away "equivilent" ones - but that would be orders of magnitude 
slower still!)

In the code I'm currently working on, I've come up with this:

type Pick  x = (x,[x])
type Picks x = ([x],[x])

pick :: [x] -> [Pick x]
pick = pick_from []

pick_from :: [x] -> [x] -> [Pick x]
pick_from ks [] = []
pick_from ks (x:xs) = (x, ks ++ xs) : pick_from (ks ++ [x]) xs

picks :: [x] -> [Picks x]
picks [] = []
picks [x] = [([],[x]), ([x],[])]
picks (x:xs) = do
  (as,bs) <- picks xs
  [(as,x:bs), (x:as,bs)]

I think these functions are quite interesting, and I don't recall ever 
seeing them in any library. Have I discovered something new here, or am 
I reinventing the wheel?

Anyway, I'm really loving the way the whole "list is a monad" concept 
allows you to write code like every variable is a superposition of all 
possible values...

all_sums :: [Term] -> [Pick Term]
all_sums ts = do
  (as,bs) <- picks ts
  if length as < 2
    then fail "trivial sum"
    else return (Sum as, bs)

all_negates :: [Term] -> [[Term]]
all_negates [] = [[]]
all_negates (t:ts) = do
  ts' <- all_negates ts
  [(t : ts'), (Negate t : ts')]

Neat, eh?

More information about the Haskell-Cafe mailing list