Fwd: [Haskell-beginners] combinatorial
patrick.leboutillier at gmail.com
Sun Nov 22 17:04:11 EST 2009
Forgot to forward my response to the list...
---------- Forwarded message ----------
From: Patrick LeBoutillier <patrick.leboutillier at gmail.com>
Date: Sun, Nov 22, 2009 at 5:03 PM
Subject: Re: [Haskell-beginners] combinatorial
To: "Michael P. Mossey" <mpm at alumni.caltech.edu>
Here's how I would go about this:
type MidiPitch = Int
range :: [MidiPitch]
range = [10..90]
-- Just a dummy eval function, allows up or down one unit
eval ps | length ps <= 1 = Just 1.0
eval ps | length ps > 1 =
let a = last ps
b = last . init $ ps in
if abs (a - b) == 1
then Just 1.0
coolFunc :: Int -> MidiPitch -> ([MidiPitch] -> Maybe Float) -> [[MidiPitch]]
coolFunc n p f = generate n f [[p]]
-- Generate MidiPitch lists up to a given length, making sure each step
-- satisfies the eval function
generate :: Int -> ([MidiPitch] -> Maybe Float) -> [[MidiPitch]] ->
generate n f cs | n == 1 = cs
generate n f cs = generate (n-1) f $ concat . map (\p -> try p cs) $ range
-- Tries to add a MidiPitch to each of the MidiPitch lists, keep
-- only the sequences that pass the eval.
try :: MidiPitch -> [[MidiPitch]] -> [[MidiPitch]]
try p = filter (not . null) . map (test p)
where test p ps =
let ps' = ps ++ [p] in
case eval ps' of
Nothing -> 
otherwise -> ps'
It's seems to work, although I'm sure many bits sould be made more elegant...
Note: After that another pass would be required over the result set to
find the sequences that have the highest scores.
On Sun, Nov 22, 2009 at 5:25 AM, Michael P. Mossey
<mpm at alumni.caltech.edu> wrote:
> I'm trying to write a combinatorial search algorithm with evaluation, and
> kind of stuck. Not sure how to do this.
> I'm constructing a musical phrase, which is a list of MidiPitch:
> I have an evaluation function that determines the fitness of any given
> eval :: [MidiPitch] -> Maybe Float
> This returns Nothing if the phrase is completely unacceptable.
> The idea is to build up a phrase one midi pitch at a time, choosing all
> possible next pitches (notes) from a range:
> next pitch comes from: [10..90]
> Most of the pitches will result in a phrase that evaluates to Nothing, so
> the combinatoral "explosion" will be limited.
> I'd like to write a function that constructs a phrase of length n, and in
> fact will have to return a list of all phrases that have equal scores of the
> -- <length of output phrase> -> <first pitch> -> <eval func> ->
> -- <all tied phrases of best score>
> coolFunc :: Int -> MidiPitch -> ([MidiPitch] -> Maybe Float) ->
> I am stuck on how to write this.
> Beginners mailing list
> Beginners at haskell.org
Rosemère, Québec, Canada
Rosemère, Québec, Canada
More information about the Beginners