예제 #1
0
    def test_intersect1d(self):

        vv1 = np.array([1.1, 3.3])
        vv2 = np.array([4.4, 7.7])
        bvv = BlockVector(2)
        bvv.set_blocks([vv1, vv2])
        res = pn.intersect1d(self.bv, bvv)
        self.assertIsInstance(res, BlockVector)
        self.assertTrue(np.allclose(res.get_block(0), vv1))
        self.assertTrue(np.allclose(res.get_block(1), vv2))
        vv3 = np.array([1.1, 7.7])
        res = pn.intersect1d(self.bv, vv3)
        self.assertIsInstance(res, BlockVector)
        self.assertTrue(np.allclose(res.get_block(0), np.array([1.1])))
        self.assertTrue(np.allclose(res.get_block(1), np.array([7.7])))
        res = pn.intersect1d(vv3, self.bv)
        self.assertIsInstance(res, BlockVector)
        self.assertTrue(np.allclose(res.get_block(0), np.array([1.1])))
        self.assertTrue(np.allclose(res.get_block(1), np.array([7.7])))
예제 #2
0
    def test_model3(self):
        G = np.array([[6, 2, 1], [2, 5, 2], [1, 2, 4]])
        A = np.array([[1, 0, 1], [0, 1, 1]])
        b = np.array([3, 0])
        c = np.array([-8, -3, -3])

        model = create_model3(G, A, b, c)
        nlp = PyomoNLP(model)
        solver = CyIpoptSolver(CyIpoptNLP(nlp))
        x, info = solver.solve(tee=False)
        x_sol = np.array([2.0, -1.0, 1.0])
        y_sol = np.array([-3., 2.])
        self.assertTrue(np.allclose(x, x_sol, rtol=1e-4))
        nlp.set_primals(x)
        nlp.set_duals(y_sol)
        self.assertAlmostEqual(nlp.evaluate_objective(), -3.5, places=5)
        self.assertTrue(np.allclose(info['mult_g'], y_sol, rtol=1e-4))
 def evaluate_external_jacobian(self, x):
     dy0dx0 = -0.2 / (x[0]**2 * x[1])
     dy0dx1 = -0.2 / (x[0] * x[1]**2)
     dy1dx0 = -0.5 * x[1]**0.5 / x[0]**2
     dy1dx1 = 0.25 / (x[0] * x[1]**0.5)
     return np.array([[dy0dx0, dy0dx1], [dy1dx0, dy1dx1]])
 def evaluate_external_jacobian(self, x):
     dy0dx0 = -2.0 * x[1]
     dy0dx1 = -2.0 * x[0] - 2.0 * x[1]
     dy1dx0 = -dy0dx0 - x[1] - 2.0 * x[0]
     dy1dx1 = -dy0dx1 - x[0]
     return np.array([[dy0dx0, dy0dx1], [dy1dx0, dy1dx1]])
예제 #5
0
    def setUpClass(cls):
        # test problem 1

        row = np.array([0, 3, 1, 2, 3, 0])
        col = np.array([0, 0, 1, 2, 3, 3])
        data = np.array([2., 1, 3, 4, 5, 1])
        m = coo_matrix((data, (row, col)), shape=(4, 4))

        rank = comm.Get_rank()
        # create mpi matrix
        rank_ownership = [[0, -1], [-1, 1]]
        bm = MPIBlockMatrix(2, 2, rank_ownership, comm)
        if rank == 0:
            bm.set_block(0, 0, m)
        if rank == 1:
            bm.set_block(1, 1, m)

        # create serial matrix image
        serial_bm = BlockMatrix(2, 2)
        serial_bm.set_block(0, 0, m)
        serial_bm.set_block(1, 1, m)
        cls.square_serial_mat = serial_bm

        bm.broadcast_block_sizes()
        cls.square_mpi_mat = bm

        # create mpi matrix
        rank_ownership = [[0, -1], [-1, 1]]
        bm = MPIBlockMatrix(2, 2, rank_ownership, comm)
        if rank == 0:
            bm.set_block(0, 0, m)
        if rank == 1:
            bm.set_block(1, 1, m)

        cls.square_mpi_mat_no_broadcast = bm

        # create matrix with shared blocks
        rank_ownership = [[0, -1], [-1, 1]]
        bm = MPIBlockMatrix(2, 2, rank_ownership, comm)
        if rank == 0:
            bm.set_block(0, 0, m)
        if rank == 1:
            bm.set_block(1, 1, m)
        bm.set_block(0, 1, m)

        bm.broadcast_block_sizes()
        cls.square_mpi_mat2 = bm

        # create serial matrix image
        serial_bm = BlockMatrix(2, 2)
        serial_bm.set_block(0, 0, m)
        serial_bm.set_block(1, 1, m)
        serial_bm.set_block(0, 1, m)
        cls.square_serial_mat2 = serial_bm

        row = np.array([0, 1, 2, 3])
        col = np.array([0, 1, 0, 1])
        data = np.array([1., 1., 1., 1.])
        m2 = coo_matrix((data, (row, col)), shape=(4, 2))

        rank_ownership = [[0, -1, 0], [-1, 1, -1]]
        bm = MPIBlockMatrix(2, 3, rank_ownership, comm)
        if rank == 0:
            bm.set_block(0, 0, m)
            bm.set_block(0, 2, m2)
        if rank == 1:
            bm.set_block(1, 1, m)
        bm.broadcast_block_sizes()
        cls.rectangular_mpi_mat = bm

        bm = BlockMatrix(2, 3)
        bm.set_block(0, 0, m)
        bm.set_block(0, 2, m2)
        bm.set_block(1, 1, m)
        cls.rectangular_serial_mat = bm
예제 #6
0
    def test_grad_objective(self):

        w_estimates = np.array([5.0, 5.0])
        z_estimates = np.array([2.0, 2.0])
        rho = 2.0
        nlp = AdmmNLP(self.pyomo_nlp,
                      self.coupling_vars,
                      rho=rho,
                      w_estimates=w_estimates,
                      z_estimates=z_estimates)

        hessian_base = self.model.hessian_f
        c = self.model.grad_f
        A = np.array([[1, 0, 0], [0, 0, 1]], dtype=np.double)
        x = nlp.create_vector_x()
        x.fill(1.0)

        df = hessian_base.dot(x) + c
        df += A.transpose().dot(w_estimates)
        df += rho * (A.transpose().dot(A).dot(x) -
                     A.transpose().dot(z_estimates))

        self.assertTrue(np.allclose(df, nlp.grad_objective(x)))

        # second nlp
        w_estimates = np.array([1.0, 2.0, 3.0])
        z_estimates = np.array([3.0, 4.0, 5.0])
        nlp = AdmmNLP(self.pyomo_nlp2,
                      self.coupling_vars2,
                      rho=3.0,
                      w_estimates=w_estimates,
                      z_estimates=z_estimates)

        m = self.model2
        transform = AdmmModel()
        aug_model = transform.create_using(
            m,
            complicating_vars=[m.x[1], m.x[3], m.x[5]],
            z_estimates=z_estimates,
            w_estimates=w_estimates,
            rho=3.0)
        nl = PyomoNLP(aug_model)

        x = nlp.create_vector_x()
        self.assertTrue(
            np.allclose(nlp.grad_objective(x), nl.grad_objective(x)))

        # third nlp
        w_estimates = np.array([1.0])
        z_estimates = np.array([3.0])
        nlp = AdmmNLP(self.pyomo_nlp3,
                      self.coupling_vars3,
                      rho=8.0,
                      w_estimates=w_estimates,
                      z_estimates=z_estimates)

        m = self.model3
        transform = AdmmModel()
        aug_model = transform.create_using(m,
                                           complicating_vars=[m.x[1]],
                                           z_estimates=z_estimates,
                                           w_estimates=w_estimates,
                                           rho=8.0)
        nl = PyomoNLP(aug_model)

        x = nlp.create_vector_x()
        x.fill(1.0)
        self.assertTrue(
            np.allclose(nlp.grad_objective(x), nl.grad_objective(x)))
예제 #7
0
    def test_objective(self):

        w_estimates = np.array([5.0, 5.0])
        z_estimates = np.array([2.0, 2.0])
        rho = 2.0
        nlp = AdmmNLP(self.pyomo_nlp,
                      self.coupling_vars,
                      rho=rho,
                      w_estimates=w_estimates,
                      z_estimates=z_estimates)

        hessian_base = self.model.hessian_f
        c = self.model.grad_f
        A = np.array([[1, 0, 0], [0, 0, 1]], dtype=np.double)
        x = nlp.create_vector_x()
        x.fill(1.0)
        f = 0.5 * x.transpose().dot(hessian_base.dot(x)) + c.dot(x)
        difference = A.dot(x) - z_estimates
        f += w_estimates.dot(difference)
        f += 0.5 * rho * np.linalg.norm(difference)**2
        self.assertEqual(f, nlp.objective(x))

        # second nlp
        w_estimates = np.array([1.0, 2.0, 3.0])
        z_estimates = np.array([3.0, 4.0, 5.0])
        nlp = AdmmNLP(self.pyomo_nlp2,
                      self.coupling_vars2,
                      rho=5.0,
                      w_estimates=w_estimates,
                      z_estimates=z_estimates)

        m = self.model2
        transform = AdmmModel()
        aug_model = transform.create_using(
            m,
            complicating_vars=[m.x[1], m.x[3], m.x[5]],
            z_estimates=z_estimates,
            w_estimates=w_estimates,
            rho=5.0)
        nl = PyomoNLP(aug_model)

        x = nlp.create_vector_x()
        self.assertAlmostEqual(nlp.objective(x), nl.objective((x)))

        # third nlp
        w_estimates = np.array([1.0])
        z_estimates = np.array([3.0])
        nlp = AdmmNLP(self.pyomo_nlp3,
                      self.coupling_vars3,
                      rho=7.0,
                      w_estimates=w_estimates,
                      z_estimates=z_estimates)

        m = self.model3
        transform = AdmmModel()
        aug_model = transform.create_using(m,
                                           complicating_vars=[m.x[1]],
                                           z_estimates=z_estimates,
                                           w_estimates=w_estimates,
                                           rho=7.0)
        nl = PyomoNLP(aug_model)

        x = nlp.create_vector_x()
        self.assertAlmostEqual(nlp.objective(x), nl.objective((x)))
예제 #8
0
    def test_hessian_lag(self):

        hessian_base = self.model.hessian_f
        ata = np.array([[1, 0, 0], [0, 0, 0], [0, 0, 1]], dtype=np.double)
        rho = self.nlp.rho
        admm_hessian = hessian_base + ata * rho
        x = self.nlp.create_vector_x()
        y = self.nlp.create_vector_y()
        hess_lag = self.nlp.hessian_lag(x, y)
        dense_hess_lag = hess_lag.todense()
        self.assertTrue(np.allclose(dense_hess_lag, admm_hessian))

        # second nlp
        w_estimates = np.array([1.0, 2.0, 3.0])
        z_estimates = np.array([3.0, 4.0, 5.0])
        nlp = AdmmNLP(self.pyomo_nlp2,
                      self.coupling_vars2,
                      rho=7.0,
                      w_estimates=w_estimates,
                      z_estimates=z_estimates)

        m = self.model2
        transform = AdmmModel()
        aug_model = transform.create_using(
            m,
            complicating_vars=[m.x[1], m.x[3], m.x[5]],
            z_estimates=z_estimates,
            w_estimates=w_estimates,
            rho=7.0)
        nl = PyomoNLP(aug_model)

        x = nlp.create_vector_x()
        y = nlp.create_vector_y()
        hess_lag = nlp.hessian_lag(x, y)
        dense_hess_lag = hess_lag.todense()
        hess_lagp = nl.hessian_lag(x, y)
        dense_hess_lagp = hess_lagp.todense()
        self.assertTrue(np.allclose(dense_hess_lag, dense_hess_lagp))

        # third nlp
        w_estimates = np.array([1.0])
        z_estimates = np.array([3.0])
        nlp = AdmmNLP(self.pyomo_nlp3,
                      self.coupling_vars3,
                      rho=1.0,
                      w_estimates=w_estimates,
                      z_estimates=z_estimates)

        m = self.model3
        transform = AdmmModel()
        aug_model = transform.create_using(m,
                                           complicating_vars=[m.x[1]],
                                           z_estimates=z_estimates,
                                           w_estimates=w_estimates,
                                           rho=1.0)
        nl = PyomoNLP(aug_model)
        x = nlp.create_vector_x()
        y = nlp.create_vector_y()
        hess_lag = nlp.hessian_lag(x, y)
        dense_hess_lag = hess_lag.todense()
        hess_lagp = nl.hessian_lag(x, y)
        dense_hess_lagp = hess_lagp.todense()

        self.assertTrue(np.allclose(dense_hess_lag, dense_hess_lagp))
예제 #9
0
 def test_xu(self):
     xu = [np.inf, 100.0, np.inf]
     self.assertTrue(np.allclose(xu, self.nlp3.xu()))
     xu = np.array([100.0])
     self.assertTrue(np.allclose(xu, self.nlp3.xu(condensed=True)))
예제 #10
0
 def test_xl(self):
     xl = np.array([-np.inf, 0, 0])
     self.assertTrue(np.allclose(xl, self.nlp3.xl()))
     xl = np.zeros(2)
     self.assertTrue(np.allclose(xl, self.nlp3.xl(condensed=True)))
예제 #11
0
 def test_c_maps(self):
     c_mask = np.array([True, True, False, False, False], dtype=bool)
     self.assertTrue(np.allclose(self.nlp3._c_mask, c_mask))
     c_map = np.array([0, 1])
     self.assertTrue(np.allclose(self.nlp3._c_map, c_map))
예제 #12
0
 def test_parallel_vector_ops(self):
     z1_local, z2, z3 = parallel_vector_ops.main()
     z1_correct = np.array([6, 6, 6, 2, 2, 2, 4, 4, 4, 2, 4, 6])
     self.assertTrue(np.allclose(z1_local, z1_correct))
     self.assertAlmostEqual(z2, 56)
     self.assertAlmostEqual(z3, 3)
예제 #13
0
    def test_hessian_2(self):
        # Test with duals different than vector of ones
        m = pyo.ConcreteModel()
        m.ex_block = ExternalGreyBoxBlock(concrete=True)
        block = m.ex_block

        m_ex = _make_external_model()
        input_vars = [m_ex.a, m_ex.b, m_ex.r, m_ex.x_out, m_ex.y_out]
        external_vars = [m_ex.x, m_ex.y]
        residual_cons = [m_ex.c_out_1, m_ex.c_out_2]
        external_cons = [m_ex.c_ex_1, m_ex.c_ex_2]
        ex_model = ExternalPyomoModel(
            input_vars,
            external_vars,
            residual_cons,
            external_cons,
        )
        block.set_external_model(ex_model)

        a = m.ex_block.inputs["input_0"]
        b = m.ex_block.inputs["input_1"]
        r = m.ex_block.inputs["input_2"]
        x = m.ex_block.inputs["input_3"]
        y = m.ex_block.inputs["input_4"]
        m.obj = pyo.Objective(expr=(x - 2.0)**2 + (y - 2.0)**2 + (a - 2.0)**2 +
                              (b - 2.0)**2 + (r - 2.0)**2)

        _add_nonlinear_linking_constraints(m)

        nlp = PyomoNLPWithGreyBoxBlocks(m)
        primals = np.array([0, 1, 2, 3, 4, 5, 6, 7])
        duals = np.array([4.4, -3.3, 2.2, -1.1, 0.0])
        nlp.set_primals(primals)
        nlp.set_duals(duals)
        hess = nlp.evaluate_hessian_lag()

        # Variable order (verified by a previous test):
        # [
        #     "a",
        #     "b",
        #     "ex_block.inputs[input_0]",
        #     "ex_block.inputs[input_1]",
        #     "ex_block.inputs[input_2]",
        #     "ex_block.inputs[input_3]",
        #     "ex_block.inputs[input_4]",
        #     "r",
        # ]
        row = [0, 1, 7]
        col = [0, 1, 7]
        # Data entries are influenced by multiplier values.
        data = [4.4 * 2.0, -3.3 * 2.0, 2.2 * 2.0]
        # ^ These variables only appear in linking constraints
        rcd_dict = dict(((i, j), val) for i, j, val in zip(row, col, data))

        # These are the coordinates of the Hessian corresponding to
        # external variables with true nonzeros. The coordinates have
        # terms due to objective, linking constraints, and external
        # constraints. Values were extracted from the external model
        # while writing this test, which is just meant to verify
        # that the different Hessians combined properly.
        ex_block_nonzeros = {
            (2, 2): 2.0 + 4.4 * (-1.0) + -1.1 * (-0.10967928),
            (2, 3): -1.1 * (-0.10684633),
            (3, 2): -1.1 * (-0.10684633),
            (2, 4): -1.1 * (0.19329898),
            (4, 2): -1.1 * (0.19329898),
            (3, 3): 2.0 + (-3.3) * (-1.0) + -1.1 * (-1.31592135),
            (3, 4): -1.1 * (1.13920361),
            (4, 3): -1.1 * (1.13920361),
            (4, 4): 2.0 + 2.2 * (-1.0) + -1.1 * (-1.0891866),
            (5, 5): 2.0,
            (6, 6): 2.0,
        }
        rcd_dict.update(ex_block_nonzeros)

        # Because "external Hessians" are computed by factorizing matrices,
        # we have dense blocks in the Hessian for now.
        ex_block_coords = [2, 3, 4, 5, 6]
        for i, j in itertools.product(ex_block_coords, ex_block_coords):
            row.append(i)
            col.append(j)
            if (i, j) not in rcd_dict:
                rcd_dict[i, j] = 0.0

        self.assertEqual(len(row), len(hess.row))
        for i, j, val in zip(hess.row, hess.col, hess.data):
            self.assertIn((i, j), rcd_dict)
            self.assertAlmostEqual(rcd_dict[i, j], val, delta=1e-8)
예제 #14
0
    def test_jacobian(self):
        m = pyo.ConcreteModel()
        m.ex_block = ExternalGreyBoxBlock(concrete=True)
        block = m.ex_block

        m_ex = _make_external_model()
        input_vars = [m_ex.a, m_ex.b, m_ex.r, m_ex.x_out, m_ex.y_out]
        external_vars = [m_ex.x, m_ex.y]
        residual_cons = [m_ex.c_out_1, m_ex.c_out_2]
        external_cons = [m_ex.c_ex_1, m_ex.c_ex_2]
        ex_model = ExternalPyomoModel(
            input_vars,
            external_vars,
            residual_cons,
            external_cons,
        )
        block.set_external_model(ex_model)

        a = m.ex_block.inputs["input_0"]
        b = m.ex_block.inputs["input_1"]
        r = m.ex_block.inputs["input_2"]
        x = m.ex_block.inputs["input_3"]
        y = m.ex_block.inputs["input_4"]
        m.obj = pyo.Objective(expr=(x - 2.0)**2 + (y - 2.0)**2 + (a - 2.0)**2 +
                              (b - 2.0)**2 + (r - 2.0)**2)

        _add_linking_constraints(m)

        nlp = PyomoNLPWithGreyBoxBlocks(m)
        primals = np.array([0, 1, 2, 3, 4, 5, 6, 7])
        nlp.set_primals(primals)
        jac = nlp.evaluate_jacobian()

        # Variable and constraint orders (verified by previous test):
        # Rows:
        # [
        #     "linking_constraint[0]",
        #     "linking_constraint[1]",
        #     "linking_constraint[2]",
        #     "ex_block.residual_0",
        #     "ex_block.residual_1",
        # ]
        # Cols:
        # [
        #     "a",
        #     "b",
        #     "ex_block.inputs[input_0]",
        #     "ex_block.inputs[input_1]",
        #     "ex_block.inputs[input_2]",
        #     "ex_block.inputs[input_3]",
        #     "ex_block.inputs[input_4]",
        #     "r",
        # ]
        row = [
            0,
            0,
            1,
            1,
            2,
            2,
            3,
            3,
            3,
            3,
            3,
            4,
            4,
            4,
            4,
            4,
        ]
        col = [
            0,
            2,
            1,
            3,
            7,
            4,
            2,
            3,
            4,
            5,
            6,
            2,
            3,
            4,
            5,
            6,
        ]
        data = [
            1,
            -1,
            1,
            -1,
            1,
            -1,
            -0.16747094,
            -1.00068434,
            1.72383729,
            1,
            0,
            -0.30708535,
            -0.28546127,
            -0.25235924,
            0,
            1,
        ]
        self.assertEqual(len(row), len(jac.row))
        rcd_dict = dict(((i, j), val) for i, j, val in zip(row, col, data))
        for i, j, val in zip(jac.row, jac.col, jac.data):
            self.assertIn((i, j), rcd_dict)
            self.assertAlmostEqual(rcd_dict[i, j], val, delta=1e-8)
예제 #15
0
    def test_set_and_evaluate(self):
        m = pyo.ConcreteModel()
        m.ex_block = ExternalGreyBoxBlock(concrete=True)
        block = m.ex_block

        m_ex = _make_external_model()
        input_vars = [m_ex.a, m_ex.b, m_ex.r, m_ex.x_out, m_ex.y_out]
        external_vars = [m_ex.x, m_ex.y]
        residual_cons = [m_ex.c_out_1, m_ex.c_out_2]
        external_cons = [m_ex.c_ex_1, m_ex.c_ex_2]
        ex_model = ExternalPyomoModel(
            input_vars,
            external_vars,
            residual_cons,
            external_cons,
        )
        block.set_external_model(ex_model)

        a = m.ex_block.inputs["input_0"]
        b = m.ex_block.inputs["input_1"]
        r = m.ex_block.inputs["input_2"]
        x = m.ex_block.inputs["input_3"]
        y = m.ex_block.inputs["input_4"]
        m.obj = pyo.Objective(expr=(x - 2.0)**2 + (y - 2.0)**2 + (a - 2.0)**2 +
                              (b - 2.0)**2 + (r - 2.0)**2)

        _add_linking_constraints(m)

        nlp = PyomoNLPWithGreyBoxBlocks(m)

        # Set primals in model, get primals in nlp
        # set/get duals
        # evaluate constraints
        # evaluate Jacobian
        # evaluate Hessian
        self.assertEqual(nlp.n_primals(), 8)

        # PyomoNLPWithGreyBoxBlocks sorts variables by name
        primals_names = [
            "a",
            "b",
            "ex_block.inputs[input_0]",
            "ex_block.inputs[input_1]",
            "ex_block.inputs[input_2]",
            "ex_block.inputs[input_3]",
            "ex_block.inputs[input_4]",
            "r",
        ]
        self.assertEqual(nlp.primals_names(), primals_names)
        np.testing.assert_equal(np.zeros(8), nlp.get_primals())

        primals = np.array([0, 1, 2, 3, 4, 5, 6, 7])
        nlp.set_primals(primals)
        np.testing.assert_equal(primals, nlp.get_primals())
        nlp.load_state_into_pyomo()

        for name, val in zip(primals_names, primals):
            var = m.find_component(name)
            self.assertEqual(var.value, val)

        constraint_names = [
            "linking_constraint[0]",
            "linking_constraint[1]",
            "linking_constraint[2]",
            "ex_block.residual_0",
            "ex_block.residual_1",
        ]
        self.assertEqual(constraint_names, nlp.constraint_names())
        residuals = np.array([
            -2.0,
            -2.0,
            3.0,
            # These values were obtained by solving the same system
            # with Ipopt in another script. It may be better to do
            # the solve in this test in case the system changes.
            5.0 - (-3.03051522),
            6.0 - 3.583839997,
        ])
        np.testing.assert_allclose(residuals,
                                   nlp.evaluate_constraints(),
                                   rtol=1e-8)

        duals = np.array([1, 2, 3, 4, 5])
        nlp.set_duals(duals)

        self.assertEqual(ex_model.residual_con_multipliers, [4, 5])
        np.testing.assert_equal(nlp.get_duals(), duals)