Esempio n. 1
0
    def __init__(self, nlp, intermediate_callback=None):
        """This class provides a CyIpoptProblemInterface for use
        with the CyIpoptSolver class that can take in an NLP
        as long as it provides vectors as numpy ndarrays and
        matrices as scipy.sparse.coo_matrix objects. This class
        provides the interface between AmplNLP or PyomoNLP objects
        and the CyIpoptSolver
        """
        self._nlp = nlp
        self._intermediate_callback = intermediate_callback

        x = nlp.init_primals()
        y = nlp.init_duals()
        if np.any(np.isnan(y)):
            # did not get initial values for y, use this default
            y.fill(1.0)

        self._cached_x = x.copy()
        self._cached_y = y.copy()
        self._cached_obj_factor = 1.0

        nlp.set_primals(self._cached_x)
        nlp.set_duals(self._cached_y)

        # get jacobian and hessian structures
        self._jac_g = nlp.evaluate_jacobian()
        try:
            self._hess_lag = nlp.evaluate_hessian_lag()
            self._hess_lower_mask = self._hess_lag.row >= self._hess_lag.col
            self._hessian_available = True
        except (AttributeError, NotImplementedError):
            self._hessian_available = False
            self._hess_lag = None
            self._hess_lower_mask = None
Esempio n. 2
0
 def __call__(self, exception=True):
     """Compute the value of the body of this constraint"""
     if self.x is None:
         raise ValueError("No variable order has been assigned")
     values = numpy.array([v.value for v in self.x], dtype=float)
     if numpy.isnan(values).any():
         if exception:
             raise ValueError("One or more variables "
                              "do not have a value")
         return None
     return self._A.dot(values)
Esempio n. 3
0
 def test_pow2(self):
     xl = np.linspace(-2, 2, 9)
     xu = np.linspace(-2, 2, 9)
     yl = np.linspace(-2, 2, 9)
     yu = np.linspace(-2, 2, 9)
     for _xl in xl:
         for _xu in xu:
             if _xl > _xu:
                 continue
             for _yl in yl:
                 for _yu in yu:
                     if _yl > _yu:
                         continue
                     if _xl == 0 and _xu == 0 and _yu < 0:
                         lb, ub = interval.power(_xl,
                                                 _xu,
                                                 _yl,
                                                 _yu,
                                                 feasibility_tol=1e-8)
                         self.assertEqual(lb, -interval.inf)
                         self.assertEqual(ub, interval.inf)
                     elif _yl == _yu and _yl != round(_yl) and (
                             _xu < 0 or (_xu < 0 and _yu < 0)):
                         with self.assertRaises(
                             (InfeasibleConstraintException,
                              interval.IntervalException)):
                             lb, ub = interval.power(_xl,
                                                     _xu,
                                                     _yl,
                                                     _yu,
                                                     feasibility_tol=1e-8)
                     else:
                         lb, ub = interval.power(_xl,
                                                 _xu,
                                                 _yl,
                                                 _yu,
                                                 feasibility_tol=1e-8)
                         if isfinite(lb) and isfinite(ub):
                             nan_fill = 0.5 * (lb + ub)
                         elif isfinite(lb):
                             nan_fill = lb + 1
                         elif isfinite(ub):
                             nan_fill = ub - 1
                         else:
                             nan_fill = 0
                         x = np.linspace(_xl, _xu, 30)
                         y = np.linspace(_yl, _yu, 30)
                         z = x**np.split(y, len(y))
                         z[np.isnan(z)] = nan_fill
                         all_values = z
                         estimated_lb = all_values.min()
                         estimated_ub = all_values.max()
                         self.assertTrue(lb - 1e-8 <= estimated_lb)
                         self.assertTrue(ub + 1e-8 >= estimated_ub)
Esempio n. 4
0
    def compute_err(self, svals, dvals, tol_type):
        """Compute the diff between svals and dvals for the given tol_type"""
        if tol_type not in ("abs", "rel"):
            raise ValueError("Invalid tol_type '%s'" % (tol_type, ))

        diff = svals - dvals
        if tol_type == "abs":
            err = diff
        else:
            # relative: divide by current value of svals
            old_settings = numpy.seterr(divide='ignore', invalid='ignore')
            err = diff / svals
            numpy.seterr(**old_settings)
            # isnan means 0/0 so diff is 0
            err[numpy.isnan(err)] = 0
            # isinf means diff/0, so just use the diff
            if any(numpy.isinf(err)):
                for i in range(len(err)):
                    if numpy.isinf(err[i]):
                        err[i] = diff[i]

        return err
Esempio n. 5
0
    def solve_tear_wegstein(self, G, order, function, tears, outEdges, iterLim,
                            tol, tol_type, report_diffs, accel_min, accel_max):
        """
        Use Wegstein to solve tears. If multiple tears are given
        they are solved simultaneously.

        Arguments
        ---------
            order
                List of lists of order in which to calculate nodes
            tears
                List of tear edge indexes
            iterLim
                Limit on the number of iterations to run
            tol
                Tolerance at which iteration can be stopped
            accel_min
                Minimum value for Wegstein acceleration factor
            accel_max
                Maximum value for Wegstein acceleration factor
            tol_type
                Type of tolerance value, either "abs" (absolute) or
                "rel" (relative to current value)

        Returns
        -------
            list
                List of lists of diff history, differences between input and
                output values at each iteration
        """
        hist = []  # diff at each iteration in every variable

        if not len(tears):
            # no need to iterate just run the calculations
            self.run_order(G, order, function, tears)
            return hist

        logger.info("Starting Wegstein tear convergence")

        itercount = 0
        ignore = tears + outEdges

        gofx = self.generate_gofx(G, tears)
        x = self.generate_first_x(G, tears)

        err = self.compute_err(gofx, x, tol_type)
        hist.append(err)

        if report_diffs:
            print("Diff matrix:\n%s" % err)

        # check if it's already solved
        if numpy.max(numpy.abs(err)) < tol:
            logger.info("Wegstein converged in %s iterations" % itercount)
            return hist

        # if not solved yet do one direct step
        x_prev = x
        gofx_prev = gofx
        x = gofx
        self.pass_tear_wegstein(G, tears, gofx)

        while True:
            itercount += 1

            logger.info("Running Wegstein iteration %s" % itercount)
            self.run_order(G, order, function, ignore)

            gofx = self.generate_gofx(G, tears)

            err = self.compute_err(gofx, x, tol_type)
            hist.append(err)

            if report_diffs:
                print("Diff matrix:\n%s" % err)

            if numpy.max(numpy.abs(err)) < tol:
                break

            if itercount > iterLim:
                logger.warning("Wegstein failed to converge in %s iterations" %
                               iterLim)
                return hist

            denom = x - x_prev
            # this will divide by 0 at some points but we handle that below,
            # so ignore division warnings
            old_settings = numpy.seterr(divide='ignore', invalid='ignore')
            slope = numpy.divide((gofx - gofx_prev), denom)
            numpy.seterr(**old_settings)
            # if isnan or isinf then x and x_prev were the same,
            # so just do direct sub for those elements
            slope[numpy.isnan(slope)] = 0
            slope[numpy.isinf(slope)] = 0
            accel = slope / (slope - 1)
            accel[accel < accel_min] = accel_min
            accel[accel > accel_max] = accel_max
            x_prev = x
            gofx_prev = gofx
            x = accel * x_prev + (1 - accel) * gofx_prev
            self.pass_tear_wegstein(G, tears, x)

        self.pass_edges(G, outEdges)

        logger.info("Wegstein converged in %s iterations" % itercount)

        return hist