def test_2_nested_drivers_same_assembly(self):
        print "*** test_2_nested_drivers_same_assembly ***"
        #
        # Solve (x-3)^2 + xy + (y+4)^2 = 3
        # using two optimizers nested. The inner loop optimizes y
        # the outer loop takes care of x
        #
        # Optimal solution: x = 6.6667; y = -7.3333
        top = set_as_top(Assembly())
        # create the outer driver
        outer_driver = top.add('driver', CONMINdriver())

        # create the inner driver
        inner_driver = top.add('driver1', CONMINdriver())

        top.add('comp1', ExprComp(expr='x-3'))
        top.add('comp2', ExprComp(expr='-3'))
        top.add('comp3', ExprComp2(expr='x*x + (x+3)*y + (y+4)**2'))
        top.add('comp4', ExprComp2(expr='x+y'))
        top.comp1.x = 50
        top.comp3.y = -50

        # Hook stuff up
        top.connect('comp1.f_x', 'comp3.x')
        top.connect('comp3.f_xy', 'comp4.y')
        top.connect('comp2.f_x', 'comp4.x')

        # Driver process definition
        outer_driver.workflow.add('driver1')
        inner_driver.workflow.add(['comp1','comp2','comp3','comp4'])

        inner_driver.itmax = 30
        inner_driver.fdch = .000001
        inner_driver.fdchm = .000001
        inner_driver.add_objective('comp3.f_xy')
        inner_driver.add_parameter('comp3.y', low=-50, high=50)

        outer_driver.itmax = 30
        outer_driver.fdch = .000001
        outer_driver.fdchm = .000001
        outer_driver.add_objective('comp4.f_xy')
        outer_driver.add_parameter('comp1.x', low=-50, high=50)

        top.run()
        # Notes: CONMIN does not quite reach the anlytical minimum
        # In fact, it only gets to about 2 places of accuracy.
        # This is also the case for a single 2-var problem.
        self.assertAlmostEqual(top.comp1.x, 6.66667, places=4)
        self.assertAlmostEqual(top.comp3.y, -7.33333, places=4)

        # test dumping of iteration tree
        stream = StringIO()
        dump_iteration_tree(top, full=False, f=stream, tabsize=3)
        s = stream.getvalue()
        s = s.replace('comp2', 'comp2or3')
        s = s.replace('comp3', 'comp2or3')
        self.assertEqual(s,
            '\n   driver\n      driver1\n         comp1\n         comp2or3\n'
            '         comp2or3\n         comp4\n')
    def test_2_nested_drivers_same_assembly(self):
        print "*** test_2_nested_drivers_same_assembly ***"
        #
        # Solve (x-3)^2 + xy + (y+4)^2 = 3
        # using two optimizers nested. The inner loop optimizes y
        # the outer loop takes care of x
        #
        # Optimal solution: x = 6.6667; y = -7.3333
        top = set_as_top(Assembly())
        # create the outer driver
        outer_driver = top.add("driver", CONMINdriver())

        # create the inner driver
        inner_driver = top.add("driver1", CONMINdriver())

        top.add("comp1", ExprComp(expr="x-3"))
        top.add("comp2", ExprComp(expr="-3"))
        top.add("comp3", ExprComp2(expr="x*x + (x+3)*y + (y+4)**2"))
        top.add("comp4", ExprComp2(expr="x+y"))
        top.comp1.x = 50
        top.comp3.y = -50

        # Hook stuff up
        top.connect("comp1.f_x", "comp3.x")
        top.connect("comp3.f_xy", "comp4.y")
        top.connect("comp2.f_x", "comp4.x")

        # Driver process definition
        outer_driver.workflow.add("driver1")
        inner_driver.workflow.add(["comp1", "comp2", "comp3", "comp4"])

        inner_driver.itmax = 30
        inner_driver.fdch = 0.000001
        inner_driver.fdchm = 0.000001
        inner_driver.add_objective("comp3.f_xy")
        inner_driver.add_parameter("comp3.y", low=-50, high=50)

        outer_driver.itmax = 30
        outer_driver.fdch = 0.000001
        outer_driver.fdchm = 0.000001
        outer_driver.add_objective("comp4.f_xy")
        outer_driver.add_parameter("comp1.x", low=-50, high=50)

        top.run()
        # Notes: CONMIN does not quite reach the anlytical minimum
        # In fact, it only gets to about 2 places of accuracy.
        # This is also the case for a single 2-var problem.
        self.assertAlmostEqual(top.comp1.x, 6.66667, places=4)
        self.assertAlmostEqual(top.comp3.y, -7.33333, places=4)

        # test dumping of iteration tree
        s = dump_iteration_tree(top)
        s = s.replace("comp2", "comp2or3")
        s = s.replace("comp3", "comp2or3")
        self.assertEqual(
            s, "\n   driver\n      driver1\n         comp1\n         comp2or3\n" "         comp2or3\n         comp4\n"
        )
    def test_2_nested_assemblies(self):
        print "*** test_2_nested_assemblies ***"
        #
        # Solve (x-3)^2 + xy + (y+4)^2 = 3
        # using two optimizers nested. The inner loop optimizes y
        # the outer loop takes care of x
        # Enough components created to assure that the optimizers don't "touch"
        #
        # Optimal solution: x = 6.6667; y = -7.3333
        self.top = set_as_top(Assembly())
        # create the outer driver
        outer_driver = self.top.add("driver", CONMINdriver())
        nested = self.top.add("nested", Assembly())
        # create the inner driver
        inner_driver = nested.add("driver", CONMINdriver())
        # inner_driver = nested.driver

        nested.add("comp1", ExprComp(expr="x-3"))
        nested.add("comp2", ExprComp(expr="-3"))
        nested.add("comp3", ExprComp2(expr="x*x + (x+3)*y + (y+4)**2"))
        nested.add("comp4", ExprComp2(expr="x+y"))
        nested.comp1.x = 50
        nested.comp3.y = -50

        # Hook stuff up
        nested.connect("comp1.f_x", "comp3.x")
        nested.connect("comp3.f_xy", "comp4.y")
        nested.connect("comp2.f_x", "comp4.x")

        nested.create_passthrough("comp1.x")
        nested.create_passthrough("comp4.f_xy")

        outer_driver.workflow.add("nested")
        inner_driver.workflow.add(["comp1", "comp2", "comp3", "comp4"])

        inner_driver.itmax = 30
        inner_driver.fdch = 0.000001
        inner_driver.fdchm = 0.000001
        # inner_driver.conmin_diff = True
        inner_driver.add_objective("comp3.f_xy")
        inner_driver.add_parameter("comp3.y", low=-50, high=50)

        outer_driver.itmax = 30
        outer_driver.fdch = 0.000001
        outer_driver.fdchm = 0.000001
        outer_driver.conmin_diff = True
        outer_driver.add_objective("nested.f_xy")  # comp4.f_xy passthrough
        outer_driver.add_parameter("nested.x", low=-50, high=50)  # comp1.x passthrough

        self.top.run()

        # Notes: CONMIN does not quite reach the analytical minimum
        # In fact, it only gets to about 2 places of accuracy.
        # This is also the case for a single 2-var problem.
        self.assertAlmostEqual(nested.x, 6.66667, places=4)
        self.assertAlmostEqual(nested.comp3.y, -7.33333, places=4)

        # test dumping of iteration tree
        s = dump_iteration_tree(self.top)

        # Comp2 and Comp3 are ambiguous in the sort
        s = s.replace("comp2", "comp2or3")
        s = s.replace("comp3", "comp2or3")
        self.assertEqual(
            s,
            "\n   driver\n      nested\n         nested.driver\n            "
            "nested.comp1\n            nested.comp2or3\n            nested.comp2or3\n"
            "            nested.comp4\n",
        )
    def test_2_nested_assemblies(self):
        print "*** test_2_nested_assemblies ***"
        #
        # Solve (x-3)^2 + xy + (y+4)^2 = 3
        # using two optimizers nested. The inner loop optimizes y
        # the outer loop takes care of x
        # Enough components created to assure that the optimizers don't "touch"
        #
        # Optimal solution: x = 6.6667; y = -7.3333
        self.top = set_as_top(Assembly())
        # create the outer driver
        outer_driver = self.top.add('driver', CONMINdriver())
        nested = self.top.add('nested', Assembly())
        # create the inner driver
        inner_driver = nested.add('driver', CONMINdriver())
        #inner_driver = nested.driver

        nested.add('comp1', ExprComp(expr='x-3'))
        nested.add('comp2', ExprComp(expr='-3'))
        nested.add('comp3', ExprComp2(expr='x*x + (x+3)*y + (y+4)**2'))
        nested.add('comp4', ExprComp2(expr='x+y'))
        nested.comp1.x = 50
        nested.comp3.y = -50

        # Hook stuff up
        nested.connect('comp1.f_x', 'comp3.x')
        nested.connect('comp3.f_xy', 'comp4.y')
        nested.connect('comp2.f_x', 'comp4.x')

        nested.create_passthrough('comp1.x')
        nested.create_passthrough('comp4.f_xy')

        outer_driver.workflow.add('nested')
        inner_driver.workflow.add(['comp1', 'comp2', 'comp3', 'comp4'])

        inner_driver.itmax = 30
        inner_driver.fdch = .000001
        inner_driver.fdchm = .000001
        #inner_driver.conmin_diff = True
        inner_driver.add_objective('comp3.f_xy')
        inner_driver.add_parameter('comp3.y', low=-50, high=50)

        outer_driver.itmax = 30
        outer_driver.fdch = .000001
        outer_driver.fdchm = .000001
        outer_driver.conmin_diff = True
        outer_driver.add_objective('nested.f_xy')  # comp4.f_xy passthrough
        outer_driver.add_parameter('nested.x', low=-50,
                                   high=50)  # comp1.x passthrough

        self.top.run()

        # Notes: CONMIN does not quite reach the analytical minimum
        # In fact, it only gets to about 2 places of accuracy.
        # This is also the case for a single 2-var problem.
        self.assertAlmostEqual(nested.x, 6.66667, places=4)
        self.assertAlmostEqual(nested.comp3.y, -7.33333, places=4)

        # test dumping of iteration tree
        stream = StringIO()
        dump_iteration_tree(self.top, full=False, f=stream, tabsize=3)
        s = stream.getvalue()

        # Comp2 and Comp3 are ambiguous in the sort
        s = s.replace('comp2', 'comp2or3')
        s = s.replace('comp3', 'comp2or3')
        self.assertEqual(
            s, '\n   driver\n      nested\n         driver\n            '
            'comp1\n            comp2or3\n            comp2or3\n'
            '            comp4\n')
    def test_2_nested_drivers_same_assembly_extra_comp(self):
        print "*** test_2_nested_drivers_same_assembly ***"
        #
        # Same as above, but one extra trailing component in outer
        # workflow.
        #
        # Optimal solution: x = 6.6667; y = -7.3333
        self.top = set_as_top(Assembly())
        top = self.top
        # create the outer driver
        outer_driver = top.add("driver", CONMINdriver())

        # create the inner driver
        inner_driver = top.add("driver1", CONMINdriver())

        top.add("comp1", ExprComp(expr="x-3"))
        top.add("comp2", ExprComp(expr="-3"))
        top.add("comp3", ExprComp2(expr="x*x + (x+3)*y + (y+4)**2"))
        top.add("comp4", ExprComp2(expr="x+y"))
        top.add("comp5", ExprComp(expr="x"))
        top.comp1.x = 50
        top.comp3.y = -50

        # Hook stuff up
        top.connect("comp1.f_x", "comp3.x")
        top.connect("comp3.f_xy", "comp4.y")
        top.connect("comp2.f_x", "comp4.x")
        top.connect("comp4.f_xy", "comp5.x")

        # Driver process definition
        outer_driver.workflow.add(["driver1", "comp5"])
        inner_driver.workflow.add(["comp1", "comp2", "comp3", "comp4"])

        inner_driver.itmax = 30
        inner_driver.fdch = 0.000001
        inner_driver.fdchm = 0.000001
        inner_driver.add_objective("comp3.f_xy")
        inner_driver.add_parameter("comp3.y", low=-50, high=50)

        outer_driver.itmax = 30
        outer_driver.fdch = 0.000001
        outer_driver.fdchm = 0.000001
        outer_driver.add_objective("comp5.f_x")
        outer_driver.add_parameter("comp1.x", low=-50, high=50)

        self.top.run()

        # Notes: CONMIN does not quite reach the anlytical minimum
        # In fact, it only gets to about 2 places of accuracy.
        # This is also the case for a single 2-var problem.
        self.assertAlmostEqual(top.comp1.x, 6.66667, places=4)
        self.assertAlmostEqual(top.comp3.y, -7.33333, places=4)

        # test dumping of iteration tree
        stream = StringIO()
        dump_iteration_tree(self.top, full=False, f=stream, tabsize=3)
        s = stream.getvalue()
        s = s.replace("comp2", "comp2or3")
        s = s.replace("comp3", "comp2or3")
        self.assertEqual(
            s,
            "\n   driver\n      driver1\n         comp1\n         comp2or3\n"
            "         comp2or3\n         comp4\n      comp5\n",
        )
    def test_2_nested_assemblies(self):
        print "*** test_2_nested_assemblies ***"
        #
        # Solve (x-3)^2 + xy + (y+4)^2 = 3
        # using two optimizers nested. The inner loop optimizes y
        # the outer loop takes care of x
        # Enough components created to assure that the optimizers don't "touch"
        # 
        # Optimal solution: x = 6.6667; y = -7.3333
        self.top = set_as_top(Assembly())
        # create the outer driver
        outer_driver = self.top.add('driver', CONMINdriver())
        nested = self.top.add('nested', Assembly())
        # create the inner driver
        inner_driver = nested.add('driver', CONMINdriver())
        
        nested.add('comp1', ExprComp(expr='x-3'))
        nested.add('comp2', ExprComp(expr='-3'))
        nested.add('comp3', ExprComp2(expr='x*x + (x+3)*y + (y+4)**2'))
        nested.add('comp4', ExprComp2(expr='x+y'))
        nested.comp1.x = 50
        nested.comp3.y = -50
        
        # Hook stuff up
        nested.connect('comp1.f_x', 'comp3.x')
        nested.connect('comp3.f_xy', 'comp4.y')
        nested.connect('comp2.f_x', 'comp4.x')
        
        nested.create_passthrough('comp1.x')
        nested.create_passthrough('comp4.f_xy')
        
        outer_driver.workflow.add('nested')
        inner_driver.workflow.add(['comp1','comp2','comp3','comp4'])

        ## create one driver for testing
        #inner_driver = self.top.add('driver1', CONMINdriver())
        #inner_driver.itmax = 30
        #inner_driver.iprint = 1001
        #inner_driver.fdch = .000001
        #inner_driver.fdchm = .000001
        #inner_driver.add_objective('comp4.f_xy')
        #inner_driver.add_parameter('comp1.x',-50,50)
        #inner_driver.add_parameter('comp3.y',-50,50)
        ##inner_driver.constraints = ['comp1.x**2 + comp3.y**2']
            
        inner_driver.itmax = 30
        inner_driver.fdch = .000001
        inner_driver.fdchm = .000001
        inner_driver.add_objective('comp3.f_xy')
        inner_driver.add_parameter('comp3.y', low=-50, high=50)
        
        outer_driver.itmax = 30
        outer_driver.fdch = .000001
        outer_driver.fdchm = .000001
        outer_driver.add_objective('nested.f_xy')   # comp4.f_xy passthrough
        outer_driver.add_parameter('nested.x', low=-50, high=50)  # comp1.x passthrough
        
        self.top.run()

        # Notes: CONMIN does not quite reach the anlytical minimum
        # In fact, it only gets to about 2 places of accuracy.
        # This is also the case for a single 2-var problem.
        self.assertAlmostEqual(nested.x, 6.66667, places=4)
        self.assertAlmostEqual(nested.comp3.y, -7.33333, places=4)

        # test dumping of iteration tree
        s = dump_iteration_tree(self.top)
        self.assertEqual(s, 
            '\n   driver\n      nested\n         nested.driver\n            '
            'nested.comp1\n            nested.comp3\n            nested.comp2\n'
            '            nested.comp4\n')