At a glance... |
Syllabus |
Models |
Code |
Lecturer
NOTE TO STUDENTS: if this homework seems too complex, then reflect a little more on Code4 and Code5. This code generalizes Code45 to the point where we can quickly write many models and many optimizers. So it actually simplifies the optimization process.... at the cost of some extra architecture.
After doing all the following, you should
be able to write one source files into hw/code/6
along with
screen snaps of your work (if relevant).
Using some URL shortener (e.g. goo.gl), shorten the URL to hw/code/6
and paste into the submission page.
From the following, show the output of running sa, mws on Schaffer, Osyczka2, Kursawe.
Rewrite your SA and MWS code such that you can run the following loop:
for model in [Schaffer, Osyczka2, Kursawe]:
for optimizer in [sa, mws]:
optimizer(model())
This is the generic experiment loop that allows for rapid extension to handle more models and more optimizers.
The above loops requires the Kursawe model.
The above code assumes that mws, sa are functions that accept one argument: a description of the model they are processing.
For the above loop to work, each model (e.g. Schaffer) has to be class that produces an instance via model(). That model defines:
- the number of decisions;
- the number of objectives;
- the name of each decision/objective;
- the min/max range of each decision/objective;
- the any function that scores a candidate
- the ok function that checks if a particular candidate is valid (for Schaffer and Kursawe, this returns True while for Osyczka2, this does some checking).
- the eval function that computes the objective scores for each candidate
While the models are all different, the form of the candidates can be the same. Using the o class, you could define a candidate in a generic way:
def candidate(): return o(decs=[],objs=[], scores=[],energy = None)
then use a model to fill in the generic candidate; e.g.
class Model:
def eval(i,c):
if not c.scores:
c.scores = [obj(c) for obj in i.objectives()]
if c.energy == None
c.energy = i.energy(c.scores)
return c
Note that Schaffer, Kursawe, Osyczka2 (and all other models) could subclass Model and use the same eval method.
Also, i.objectives is some Model property that lists a set of methods to call to evaluate a score. E.g. for Schaffer
class Schaffer(Models):
def f1(i,c):
x=c.decs[0]
return x**2
def f2(i,c):
x=c.decs[0]
return (x-2)**2
def objectives(i):
return [i.f1,i.f2]
All your models will have to know about the name and range of values for each attribute. This can be stored in yet another class, which I call Has.
Here, in all its complex glory, is my Has class.
- If i.touch is True then I am allowed to mutate it (by default, I can mutate anything)
- If goal is not Nil, then this is an objective
- If non-nil, goal can be one of lt or gt indicating what direction is better.
Note that you won't need (yet) a class this complex. But something (simpler) that this should be used inside Model in a method that defines the decisions and objectives.
import random
r = random.random
def within(lo,hi): return lo + (hi - lo)*r()
def lt(x,t): return x < y # less than
def bt(x,y_: return x > y # better than
class Has(object):
def __init__(i,name='',lo=0,hi=1e32,init=0,
goal=None,touch=True):
i.name,i.lo,i.hi = name,lo,hi
i.init,i.goal,i.touch = init,goal,touch
def restrain(i,x):
if x < i.lo: return i.lo
elif x > i.hi: return i.hi
else:
return x
def any(i):
return within(i.lo,i.hi)
def ok(i,x):
return i.lo <= x <= i.hi
def __repr__(i):
return '%s=%s' % (i.name, o(name=i.name,lo=i.lo,hi=i.hi,init=i.init,goal=i.goal,touch=i.touch))
Copyright © 2015 Tim Menzies.
This is free and unencumbered software released into the public domain.
For more details, see the license.