class ParetoFilterBase(Component): """ Base functionality for a pareto filter. Not to be instantiated directly. Should be subclassed. """ def _is_dominated(self, y1, y2): """Tests to see if the point y1 is dominated by the point y2. True if y1 is dominated by y2, False otherwise. """ if y1 == y2: return False for a, b in zip(y1, y2): if a < b: return False return True def execute(self): """Finds and removes pareto optimal points in the given case set. Returns a list of pareto optimal points. Smaller is better for all criteria. """ #convert stuff to caseSets if they are not case_sets = [] for ci in self.case_sets: if not isinstance(ci, CaseSet): case_sets.append(caseiter_to_caseset(ci)) else: case_sets.append(ci) y_list = [] if len(case_sets) > 1: case_set = case_sets[0].union(*case_sets[1:]) else: case_set = case_sets[0] criteria_count = len(self.criteria) try: # need to transpose the list of outputs y_list = zip(*[case_set[crit] for crit in self.criteria]) except KeyError: self.raise_exception('no cases provided had all of the outputs ' 'matching the provided criteria, %s' % self.criteria, ValueError) y_temp = list(y_list) self.dominated_set = CaseSet() self.pareto_set = CaseSet() # TODO: need a way to copy casesets for point1, case in zip(y_list, iter(case_set)): dominated = False for point2 in y_temp: if self._is_dominated(point1, point2): self.dominated_set.record(case) y_temp.remove(point1) dominated = True break if not dominated: self.pareto_set.record(case)
def test_from_case(self): cs = CaseSet(self.case1) self.assertEqual(1, len(cs)) self.assertEqual(cs[0]._inputs, self.case1_dup._inputs) self.assertEqual(cs[0]._outputs, self.case1_dup._outputs) cs.record(self.case2) cs.record(self.case1_dup) self.assertEqual(2, len(cs))
def test_iteration(self): cs = CaseSet() cs.record(self.case1) cs.record(self.case2) cs.record(self.case1_dup) expected = [self.case1, self.case2, self.case1_dup] for i,case in enumerate(cs): self.assertEqual(case._inputs, expected[i]._inputs) self.assertEqual(case._outputs, expected[i]._outputs)
def test_start_empty(self): cs = CaseSet() cs.record(self.case1) cs.record(self.case2) cs.record(self.case1_dup) self.assertEqual(2, len(cs)) self.assertEqual(cs[0]._inputs, self.case1_dup._inputs) self.assertEqual(cs[0]._outputs, self.case1_dup._outputs) self.assertEqual(cs[1]._inputs, self.case2._inputs) self.assertEqual(cs[1]._outputs, self.case2._outputs)
def test_ei_2obj(self): ei = MultiObjExpectedImprovement() bests = CaseSet() list_of_cases = [Case(outputs=[("y1", 1), ("y2", 10)]), Case(outputs=[("y1", 1), ("y2", -10)])] for case in list_of_cases: bests.record(case) ei.best_cases = bests ei.criteria = ["y1", "y2"] ei.predicted_values = [NormalDistribution(mu=1, sigma=1), NormalDistribution(mu=0, sigma=1)] ei.calc_switch = "EI" ei.execute() self.assertAlmostEqual([5.0], ei.EI, 1) self.assertEqual(0.5, ei.PI, 6)
def test_start_empty_subset(self): names = ["comp1.a", "comp2.c+comp2.d", "comp1.b"] ins = [names[0], names[2]] outs = [names[1]] cs = CaseSet(names=names) cs.record(self.case1) cs.record(self.case2) cs.record(self.case1_dup) self.assertEqual(2, len(cs)) self.assertEqual(3, len(cs[0].items())) self.assertEqual(2, len(cs[0].items("in"))) self.assertEqual(1, len(cs[0].items("out"))) self.assertEqual(set(names), set(cs[0].keys())) self.assertEqual(set(ins), set(cs[0].keys("in"))) self.assertEqual(set(outs), set(cs[0].keys("out")))
def test_start_empty_subset(self): names=['comp1.a','comp2.c+comp2.d','comp1.b'] ins = [names[0], names[2]] outs = [names[1]] cs = CaseSet(names=names) cs.record(self.case1) cs.record(self.case2) cs.record(self.case1_dup) self.assertEqual(2, len(cs)) self.assertEqual(3, len(cs[0].items())) self.assertEqual(2, len(cs[0].items('in'))) self.assertEqual(1, len(cs[0].items('out'))) self.assertEqual(set(names), set(cs[0].keys())) self.assertEqual(set(ins), set(cs[0].keys('in'))) self.assertEqual(set(outs), set(cs[0].keys('out')))
def test_ei_zero_division(self): ei = ExpectedImprovement() ei.best_case = CaseSet(Case(outputs=[("y", 1)])) ei.criteria = "y" ei.predicted_value = NormalDistribution(mu=1, sigma=0) ei.execute() self.assertEqual(0, ei.EI) self.assertEqual(0, ei.PI)
def test_ei(self): ei = ExpectedImprovement() ei.best_case = CaseSet(Case(outputs=[("y", 1)])) ei.criteria = "y" ei.predicted_value = NormalDistribution(mu=1, sigma=1) ei.execute() self.assertAlmostEqual([0.91], ei.EI, 2) self.assertAlmostEqual(0.5, ei.PI, 6)
def execute(self): """Finds and removes pareto optimal points in the given case set. Returns a list of pareto optimal points. Smaller is better for all criteria. """ #convert stuff to caseSets if they are not case_sets = [] for ci in self.case_sets: if not isinstance(ci, CaseSet): case_sets.append(caseiter_to_caseset(ci)) else: case_sets.append(ci) y_list = [] if len(case_sets) > 1: case_set = case_sets[0].union(*case_sets[1:]) else: case_set = case_sets[0] criteria_count = len(self.criteria) try: # need to transpose the list of outputs y_list = zip(*[case_set[crit] for crit in self.criteria]) except KeyError: self.raise_exception( 'no cases provided had all of the outputs ' 'matching the provided criteria, %s' % self.criteria, ValueError) y_temp = list(y_list) self.dominated_set = CaseSet() self.pareto_set = CaseSet() #TODO: need a way to copy casesets for point1, case in zip(y_list, iter(case_set)): dominated = False for point2 in y_temp: if self._is_dominated(point1, point2): self.dominated_set.record(case) y_temp.remove(point1) dominated = True break if not dominated: self.pareto_set.record(case)
def test_copy(self): cs = CaseSet() cs.record(self.case1) cs.record(self.case2) cs.record(self.case1_dup) cscopy = cs.copy() for c1, c2 in zip(cs, cscopy): self.assertEqual(c1, c2)
def execute(self): """Finds and removes pareto optimal points in the given case set. Returns a list of pareto optimal points. Smaller is better for all criteria. """ #convert stuff to caseSets if they are not case_sets = [] for ci in self.case_sets: if not isinstance(ci,CaseSet): case_sets.append(caseiter_to_caseset(ci)) else: case_sets.append(ci) y_list = [] if len(case_sets) > 1: case_set = case_sets[0].union(*case_sets[1:]) else: case_set = case_sets[0] criteria_count = len(self.criteria) try: # need to transpose the list of outputs y_list = zip(*[case_set[crit] for crit in self.criteria]) except KeyError: self.raise_exception('no cases provided had all of the outputs ' 'matching the provided criteria, %s'%self.criteria, ValueError) y_temp = list(y_list) self.dominated_set = CaseSet() self.pareto_set = CaseSet() #TODO: need a way to copy casesets for point1, case in zip(y_list, iter(case_set)): dominated = False for point2 in y_temp: if self._is_dominated(point1, point2): self.dominated_set.record(case) y_temp.remove(point1) dominated = True break if not dominated: self.pareto_set.record(case)
def test_ei_bad_criteria(self): ei = ExpectedImprovement() ei.best_case = CaseSet(Case(outputs=[("y", 1)])) ei.criteria = "x" ei.predicted_value = NormalDistribution(mu=1, sigma=1) try: ei.execute() except ValueError, err: self.assertEqual( str(err), ": best_case did not have an output which " "matched the criteria, 'x'")
def test_reset_y_star_event(self): ei = MultiObjExpectedImprovement(3) bests = CaseSet() list_of_cases = [Case(outputs=[("y1",1),("y2",1),("y3",1)])] for case in list_of_cases: bests.record(case) ei.best_cases = bests ei.criteria = ['y1','y2','y3'] ei.predicted_values = [NormalDistribution(mu=1,sigma=1), NormalDistribution(mu=1,sigma=1), NormalDistribution(mu=1,sigma=1)] ei.execute() bests = CaseSet() list_of_cases = [Case(outputs=[("y1",2),("y2",2),("y3",2)])] for case in list_of_cases: bests.record(case) ei.best_cases = bests ei.reset_y_star = True ei.execute() self.assertEqual(ei.y_star.all(),array([2,2,2]).all())
def test_update_empty(self): c1 = Case(inputs=[('x', 10)], outputs=[('y', 10)]) c2 = Case(inputs=[('x', 1)], outputs=[('y', 1)]) cs1 = CaseSet() cs1.record_case(c1) cs1.record_case(c2) cs2 = CaseSet() cs2.update(cs1) for c1, c2 in zip(cs1, cs2): self.assertEqual(c1, c2)
def test_close(self): c1 = Case(inputs=[ ('x', 10), ], outputs=[('y', 10)]) cs1 = CaseSet() cs1.record(c1) cs1.close()
def test_ei_nobj(self): ei = MultiObjExpectedImprovement(3) bests = CaseSet() list_of_cases = [Case(outputs=[("y1",1),("y2",1),("y3",1)])] for case in list_of_cases: bests.record(case) ei.best_cases = bests ei.criteria = ['y1','y2','y3'] ei.predicted_values = [NormalDistribution(mu=1,sigma=1), NormalDistribution(mu=1,sigma=1), NormalDistribution(mu=1,sigma=1)] ei.execute() self.assertAlmostEqual(0.875,ei.PI,1)
def test_subset_from_dict(self): dct = { 'comp1.a': [2, 4, 6], 'comp1.b': [4, 8, 12], 'comp2.b': [1, 2, 3], } cs = CaseSet(dct, names=['comp1.a', 'comp2.b']) self.assertEqual(3, len(cs)) self.assertEqual(set(['comp1.a', 'comp2.b']), set(cs._names)) self.assertEqual(cs['comp1.a'], [2, 4, 6]) case = cs[1] expected = Case(inputs=[('comp1.a', 4), ('comp2.b', 2)]) self.assertEqual(case._inputs, expected._inputs)
def test_ei_2obj(self): ei = MultiObjExpectedImprovement() bests = CaseSet() list_of_cases = [Case(outputs=[("y1",1),("y2",10)]),Case(outputs=[("y1",1),("y2",-10)])] for case in list_of_cases: bests.record(case) ei.best_cases = bests ei.criteria = ["y1","y2"] ei.predicted_values = [NormalDistribution(mu=1,sigma=1),NormalDistribution(mu=0,sigma=1)] ei.calc_switch = "EI" ei.execute() self.assertAlmostEqual([5.0],ei.EI,1) self.assertEqual(0.5,ei.PI,6)
def test_iteration(self): cs = CaseSet() cs.record(self.case1) cs.record(self.case2) cs.record(self.case1_dup) expected = [self.case1, self.case2, self.case1_dup] for i, case in enumerate(cs): self.assertEqual(case._inputs, expected[i]._inputs) self.assertEqual(case._outputs, expected[i]._outputs)
def test_bad_criteria(self): ei = MultiObjExpectedImprovement(2) bests = CaseSet() list_of_cases = [Case(outputs=[("y1",1),("y2",1)])] for case in list_of_cases: bests.record(case) ei.best_cases = bests ei.criteria = ['y1','y3'] ei.predicted_values = [NormalDistribution(mu=1,sigma=1), NormalDistribution(mu=1,sigma=1)] try: ei.execute() except ValueError,err: self.assertEqual(str(err),": no cases in the provided case_set" " had output matching the provided criteria, ['y1' 'y3']")
def test_ei_calc_switch(self): ei = MultiObjExpectedImprovement(3) bests = CaseSet() list_of_cases = [Case(outputs=[("y1",1),("y2",1),("y3",1)])] for case in list_of_cases: bests.record(case) ei.best_cases = bests ei.criteria = ['y1','y2','y3'] ei.predicted_values = [NormalDistribution(mu=1,sigma=1), NormalDistribution(mu=1,sigma=1), NormalDistribution(mu=1,sigma=1)] ei.calc_switch = 'EI' try: ei.execute() except ValueError,err: self.assertEqual(str(err),': EI calculations not supported' ' for more than 2 objectives')
def test_update_empty(self): c1 = Case(inputs=[('x',10),], outputs=[('y',10)]) c2 = Case(inputs=[('x',1),], outputs=[('y',1)]) cs1 = CaseSet() cs1.record(c1) cs1.record(c2) cs2 = CaseSet() cs2.update(cs1) for c1,c2 in zip(cs1, cs2): self.assertEqual(c1, c2)
def test_start_empty_subset(self): names = ['comp1.a', 'comp2.c+comp2.d', 'comp1.b'] ins = [names[0], names[2]] outs = [names[1]] cs = CaseSet(names=names) cs.record(self.case1) cs.record(self.case2) cs.record(self.case1_dup) self.assertEqual(2, len(cs)) self.assertEqual(3, len(cs[0].items())) self.assertEqual(2, len(cs[0].items('in'))) self.assertEqual(1, len(cs[0].items('out'))) self.assertEqual(set(names), set(cs[0].keys())) self.assertEqual(set(ins), set(cs[0].keys('in'))) self.assertEqual(set(outs), set(cs[0].keys('out')))
# pylint: disable-msg=C0103, E1101 from matplotlib import pyplot as py from mpl_toolkits.mplot3d import Axes3D from numpy import random random.seed(10) from openmdao.main.case import Case pf = ParetoFilter() # 2D PARETO FILTERING EXAMPLE n = 1000 x = random.uniform(-1, 0, n) y = -(1 - x**2)**0.5 * random.random(n) cases = CaseSet() for x_0, y_0 in zip(x, y): cases.record(Case(inputs=[("x", x_0), ("y", y_0)])) pf.case_sets = [cases] pf.criteria = ['x', 'y'] pf.execute() x_p, y_p = pf.pareto_set['x'], pf.pareto_set['y'] x_dom, y_dom = pf.dominated_set['x'], pf.dominated_set['y'] py.figure() py.scatter(x, y, s=5) py.scatter(x_dom, y_dom, c='', edgecolor='b', s=80) py.scatter(x_p, y_p, c='', edgecolors='r', s=80)
def test_set_ops(self): cs = CaseSet() cs2 = CaseSet() for case in self.caselist: cs.record(case) cs2.record(case) self.assertEqual(len(cs), len(self.caselist) - 2) self.assertTrue(cs == cs2) case = cs2.pop(1) self.assertFalse(cs == cs2) self.assertTrue(cs2 < cs) self.assertFalse(cs < cs) self.assertTrue(cs <= cs) self.assertTrue(cs >= cs) self.assertFalse(cs2 > cs) self.assertFalse(cs2 > cs2) self.assertTrue(case in cs) self.assertFalse(case in cs2) self.assertTrue(case not in cs2) self.assertFalse(case not in cs) diffset = cs - cs2 self.assertEqual(len(diffset), 1) self.assertTrue(case in diffset) cs3 = CaseSet() cs4 = CaseSet() cs3.record(self.case1) cs3.record(self.case2) try: self.assertTrue(cs3.isdisjoint(cs4)) except ValueError, err: self.assertEqual( str(err), "case containers have different sets of variables")
def test_set_ops(self): cs = CaseSet() cs2 = CaseSet() for case in self.caselist: cs.record(case) cs2.record(case) self.assertEqual(len(cs), len(self.caselist)-2) self.assertTrue(cs == cs2) case = cs2.pop(1) self.assertFalse(cs == cs2) self.assertTrue(cs2 < cs) self.assertFalse(cs < cs) self.assertTrue(cs <= cs) self.assertTrue(cs >= cs) self.assertFalse(cs2 > cs) self.assertFalse(cs2 > cs2) self.assertTrue(case in cs) self.assertFalse(case in cs2) self.assertTrue(case not in cs2) self.assertFalse(case not in cs) diffset = cs - cs2 self.assertEqual(len(diffset), 1) self.assertTrue(case in diffset) cs3 = CaseSet() cs4 = CaseSet() cs3.record(self.case1) cs3.record(self.case2) try: self.assertTrue(cs3.isdisjoint(cs4)) except ValueError, err: self.assertEqual(str(err), "case containers have different sets of variables")
def test_contains(self): cs = CaseSet() cs.record(self.case1) self.assertTrue(self.case1_dup in cs) self.assertFalse(self.case2 in cs) self.assertFalse(None in cs)
def test_close(self): c1 = Case(inputs=[("x", 10)], outputs=[("y", 10)]) cs1 = CaseSet() cs1.record(c1) cs1.close()
def test_close(self): c1 = Case(inputs=[('x', 10)], outputs=[('y', 10)]) cs1 = CaseSet() cs1.record_case(c1) cs1.close()
# pylint: disable-msg=C0103, E1101 from matplotlib import pyplot as py from mpl_toolkits.mplot3d import Axes3D from numpy import random random.seed(10) from openmdao.main.case import Case pf = ParetoFilter() # 2D PARETO FILTERING EXAMPLE n = 1000 x = random.uniform(-1, 0, n) y = -(1-x**2)**0.5*random.random(n) cases = CaseSet() for x_0, y_0 in zip(x, y): cases.record(Case(inputs=[("x", x_0), ("y", y_0)])) pf.case_sets = [cases] pf.criteria = ['x', 'y'] pf.execute() x_p, y_p = pf.pareto_set['x'],pf.pareto_set['y'] x_dom, y_dom = pf.dominated_set['x'],pf.dominated_set['y'] py.figure() py.scatter(x, y, s=5) py.scatter(x_dom, y_dom, c='', edgecolor='b', s=80) py.scatter(x_p, y_p, c='', edgecolors='r', s=80)
class ParetoFilter(Component): """Takes a set of cases and filters out the subset of cases which are pareto optimal. Assumes that smaller values for model responses are better, so all problems must be posed as minimization problems. """ # pylint: disable-msg=E1101 criteria = ListStr([], iotype="in", desc="List of outputs from the case to consider for " "filtering. Note that only case outputs are allowed as " "criteria.") #case_set = Slot(ICaseIterator, iotype="in", # desc="CaseIterator with the cases to be filtered to " # "Find the pareto optimal subset.") case_sets = List(Slot(ICaseIterator), value=[], iotype="in", desc="CaseSet with the cases to be filtered to " "Find the pareto optimal subset.") pareto_set = Slot(CaseSet, iotype="out", desc="Resulting collection of pareto optimal cases.",copy="shallow") dominated_set = Slot(CaseSet, iotype="out", desc="Resulting collection of dominated cases.",copy="shallow") def _is_dominated(self, y1, y2): """Tests to see if the point y1 is dominated by the point y2. True if y1 is dominated by y2, False otherwise. """ if y1 == y2: return False for a,b in zip(y1, y2): if a<b: return False return True def execute(self): """Finds and removes pareto optimal points in the given case set. Returns a list of pareto optimal points. Smaller is better for all criteria. """ #convert stuff to caseSets if they are not case_sets = [] for ci in self.case_sets: if not isinstance(ci,CaseSet): case_sets.append(caseiter_to_caseset(ci)) else: case_sets.append(ci) y_list = [] if len(case_sets) > 1: case_set = case_sets[0].union(*case_sets[1:]) else: case_set = case_sets[0] criteria_count = len(self.criteria) try: # need to transpose the list of outputs y_list = zip(*[case_set[crit] for crit in self.criteria]) except KeyError: self.raise_exception('no cases provided had all of the outputs ' 'matching the provided criteria, %s'%self.criteria, ValueError) y_temp = list(y_list) self.dominated_set = CaseSet() self.pareto_set = CaseSet() #TODO: need a way to copy casesets for point1, case in zip(y_list, iter(case_set)): dominated = False for point2 in y_temp: if self._is_dominated(point1, point2): self.dominated_set.record(case) y_temp.remove(point1) dominated = True break if not dominated: self.pareto_set.record(case)