Method¶
Melody methods determine how the search/optimisation space is going to be traversed. In the first instance melody is being used to search the optimisation space rather than optimise over it.
Methods¶
Melody currently only supports a single method called BruteForce
.
BruteForce¶
The BruteForce method iterates over all possible combinations specified in the inputs irrespective of the return values. Thus it is a parameter search method rather than an optimisation method. It has proven useful to investigate relatively small optimisation-space landscapes if they are not known. For example, the performance of a code for a set of input parameters.
For example, if we specify three input objects, the associated function will be called for all combinations of their values.
>>> from melody.inputs import Fixed, Switch, IntRange
>>> inputs = [Fixed(name="opt1", value="grey"),
Switch(name="opt2", off="dark", on="light"),
IntRange("opt3", low=1, high=3, step=1)]
>>> def function(input):
print "function {0}".format(str(input))
return True, {"value": 10}
>>> from melody.search import BruteForce
>>> from melody.main import Melody
>>> melody = Melody(inputs=inputs, function=function,
method=BruteForce)
>>> melody.search()
function [{'opt1': 'grey'}, {'opt2': 'dark'}, {'opt3': 1}]
[{'opt1': 'grey'}, {'opt2': 'dark'}, {'opt3': 1}] True {'value': 10}
function [{'opt1': 'grey'}, {'opt2': 'dark'}, {'opt3': 2}]
[{'opt1': 'grey'}, {'opt2': 'dark'}, {'opt3': 2}] True {'value': 10}
function [{'opt1': 'grey'}, {'opt2': 'light'}, {'opt3': 1}]
[{'opt1': 'grey'}, {'opt2': 'light'}, {'opt3': 1}] True {'value': 10}
function [{'opt1': 'grey'}, {'opt2': 'light'}, {'opt3': 2}]
[{'opt1': 'grey'}, {'opt2': 'light'}, {'opt3': 2}] True {'value': 10}
In the above example, the first input object has 1 option, the second 2 options and the third 2 options. Therefore for a brute force combination one would expect to have 1*2*2 combinations in total equaling 4. As you can see, 4 options are output.
Extending¶
The user can create new Melody methods if they so wish. All methods
should inherit from the SearchMethod
base class.
Note
Please ignore the state argument and method in the SearchMethod
class. These are not used at the moment and are placeholders for
future developments.
The user can subclass the SearchMethod
base class. The run
method must be implemented as this is called by the Melody
class
(see the Melody section). The run
method should take all of
the supplied inputs
and call the function appropriately.
In the example below an illustrative PrintInputs
class is created
which simply prints out the input objects supplied (it does not call
the function)
>>> from melody.inputs import Fixed, Switch, IntRange
>>> inputs = [Fixed(name="option1", value="grey"),
Switch(name="option2", off="dark", on="light"),
IntRange("option3", low=1, high=3, step=1)]
>>> def function(input):
return True, {"value": 10}
>>> from melody.search import SearchMethod
>>> class PrintInputs(SearchMethod):
''' example searchmethod subclass '''
def __init__(self, inputs, function, state=None):
SearchMethod.__init__(self, inputs, function, state)
def run(self):
''' example run method '''
for input in inputs:
print input
>>> from melody.main import Melody
>>> melody = Melody(inputs=inputs, function=function,
method=PrintInputs)
>>> melody.search()
<melody.inputs.Fixed object at 0x7f7c1136a490>
<melody.inputs.Switch object at 0x7f7c1136a650>
<melody.inputs.IntRange object at 0x7f7c1136a990>