[Puzzle] How to do parameter variation?

Discussion in 'Ruby' started by Gary Boone, Dec 7, 2006.

  1. Gary Boone

    Gary Boone Guest

    Suppose you want to do several runs of a program or function, varying
    the parameters each time. You start with a hash of parameter lists:

    params = { speed=>[1,2,3], beta=>[0.1, 0.002, 0.4], x=>['a', 'b'] }

    Given this set, you'll call the test function 18 times:

    test_function( {speed=>1, beta=>0.1, x=>'a'} )
    test_function( {speed=>1, beta=>0.1, x=>'b'} )
    test_function( {speed=>1, beta=>0.002, x=>'a'} )
    ... etc

    So the puzzle is how to take the original params list and generate a
    list of all the combinations of the parameters? The resulting parameter
    sets will be passed one at a time to the function as shown above.

    Notes:
    - I used hashes and lists to explain the problem. Maybe there's a better
    way.
    - You don't know how many parameters will be given.
    - The number of values for each parameter is unknown in advance.
    - The parameters have different types, as shown above. Each parameter's
    values are all the same type, though.

    --
    Posted via http://www.ruby-forum.com/.
    Gary Boone, Dec 7, 2006
    #1
    1. Advertising

  2. On Thu, Dec 07, 2006 at 04:25:43PM +0900, Gary Boone wrote:
    }
    } Suppose you want to do several runs of a program or function, varying
    } the parameters each time. You start with a hash of parameter lists:
    }
    } params = { speed=>[1,2,3], beta=>[0.1, 0.002, 0.4], x=>['a', 'b'] }
    }
    } Given this set, you'll call the test function 18 times:
    }
    } test_function( {speed=>1, beta=>0.1, x=>'a'} )
    } test_function( {speed=>1, beta=>0.1, x=>'b'} )
    } test_function( {speed=>1, beta=>0.002, x=>'a'} )
    } ... etc
    }
    } So the puzzle is how to take the original params list and generate a
    } list of all the combinations of the parameters? The resulting parameter
    } sets will be passed one at a time to the function as shown above.
    }
    } Notes:
    } - I used hashes and lists to explain the problem. Maybe there's a better
    } way.
    } - You don't know how many parameters will be given.
    } - The number of values for each parameter is unknown in advance.
    } - The parameters have different types, as shown above. Each parameter's
    } values are all the same type, though.

    params = { :speed => [1,2,3], :beta => [0.1, 0.002, 0.4], :x => ['a', 'b'] }

    all = params.inject([{}]) do |perms,(k,list)|
    perms.inject([]) do |expanded,base|
    list.each do |v|
    expanded << base.merge(k => v)
    end
    expanded
    end
    end

    require 'yaml'
    puts all.size
    puts all.to_yaml

    --Greg
    Gregory Seidman, Dec 7, 2006
    #2
    1. Advertising

  3. On Dec 7, 2006, at 1:25 AM, Gary Boone wrote:

    >
    > Suppose you want to do several runs of a program or function, varying
    > the parameters each time. You start with a hash of parameter lists:
    >
    > params = { speed=>[1,2,3], beta=>[0.1, 0.002, 0.4], x=>['a',
    > 'b'] }
    >
    > Given this set, you'll call the test function 18 times:
    >
    > test_function( {speed=>1, beta=>0.1, x=>'a'} )
    > test_function( {speed=>1, beta=>0.1, x=>'b'} )
    > test_function( {speed=>1, beta=>0.002, x=>'a'} )
    > ... etc


    See if this gives you some ideas:

    #!/usr/bin/env ruby -w

    def call_with(meth, params, selected = Hash.new)
    params = params.dup
    key = params.keys.sort_by { |k| k.to_s }.first
    choices = params.delete(key)

    choices.each do |choice|
    selected = selected.merge(key => choice)
    if params.empty?
    send(meth, selected)
    else
    call_with(meth, params, selected)
    end
    end
    end

    def print_args(args)
    p args
    end

    call_with :print_args, :speed => [1, 2, 3],
    :beta => [0.1, 0.002, 0.4],
    :x => ["a", "b"]
    # >> {:speed=>1, :beta=>0.1, :x=>"a"}
    # >> {:speed=>1, :beta=>0.1, :x=>"b"}
    # >> {:speed=>2, :beta=>0.1, :x=>"a"}
    # >> {:speed=>2, :beta=>0.1, :x=>"b"}
    # >> {:speed=>3, :beta=>0.1, :x=>"a"}
    # >> {:speed=>3, :beta=>0.1, :x=>"b"}
    # >> {:speed=>1, :beta=>0.002, :x=>"a"}
    # >> {:speed=>1, :beta=>0.002, :x=>"b"}
    # >> {:speed=>2, :beta=>0.002, :x=>"a"}
    # >> {:speed=>2, :beta=>0.002, :x=>"b"}
    # >> {:speed=>3, :beta=>0.002, :x=>"a"}
    # >> {:speed=>3, :beta=>0.002, :x=>"b"}
    # >> {:speed=>1, :beta=>0.4, :x=>"a"}
    # >> {:speed=>1, :beta=>0.4, :x=>"b"}
    # >> {:speed=>2, :beta=>0.4, :x=>"a"}
    # >> {:speed=>2, :beta=>0.4, :x=>"b"}
    # >> {:speed=>3, :beta=>0.4, :x=>"a"}
    # >> {:speed=>3, :beta=>0.4, :x=>"b"}

    James Edward Gray II
    James Edward Gray II, Dec 7, 2006
    #3
  4. Gary Boone

    Gary Boone Guest

    Cool. While I study the others, here's my solution. Looks like it's
    similar to Greg's.

    --Gary


    # expand_hash_lists
    #
    # note that accumulating lists must be passed in as the first argument
    #
    def expand_hash_lists(a1, a2)
    a1.inject([]){|acc,f| a2.inject(acc){|a,b| a << +
    (f.is_a?(Hash)?[f]:f)}}
    end

    if __FILE__ == $0

    # tests of expand_hash_lists
    ah=[{'a'=>1}, {'a'=>2}, {'a'=>3}]
    bh=[{'b'=>21}, {'b'=>22}, {'b'=>23}]
    ch=[{'c'=>31}, {'c'=>32}, {'c'=>33}]
    dh=[{'d'=>41}, {'d'=>42}, {'d'=>43}]

    abh = expand_hash_lists(ah, bh)
    abch = expand_hash_lists(abh, ch)
    p expand_hash_lists(abch, dh).inspect

    # Additional tests
    p "----"
    p [[{'a'=>1}], [{'b'=>2}]].inject{|acc, vl| expand_hash_lists(acc,
    vl)}.inspect
    p "----"
    p [[{'a'=>1}, {'a'=>3}], [{'b'=>2}]].inject{|acc, vl|
    expand_hash_lists(acc, vl)}.inspect
    p "----"
    p [[{'a'=>1}, {'a'=>3}], [{'b'=>2}, {'b'=>4}]].inject{|acc, vl|
    expand_hash_lists(acc, vl)}.inspect
    end

    --
    Posted via http://www.ruby-forum.com/.
    Gary Boone, Dec 8, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alison Bowes
    Replies:
    0
    Views:
    467
    Alison Bowes
    Feb 18, 2005
  2. Erlend Andreas Garberg

    Travelling salesman variation in python

    Erlend Andreas Garberg, Apr 1, 2004, in forum: Python
    Replies:
    20
    Views:
    4,166
    G√ľnter Jantzen
    Apr 2, 2004
  3. j0mbolar

    opinions on logical OR variation

    j0mbolar, Sep 28, 2004, in forum: C Programming
    Replies:
    3
    Views:
    305
    Tim Rentsch
    Sep 29, 2004
  4. yanyo

    standard variation

    yanyo, Oct 6, 2005, in forum: C Programming
    Replies:
    1
    Views:
    952
    Alexei A. Frounze
    Oct 6, 2005
  5. Replies:
    0
    Views:
    1,246
Loading...

Share This Page