Exemplo n.º 1
0
def base_and_dirs2utpm(x, V):
    """
    x_utpm = base_and_dirs2utpm(x,V)
    where x_utpm is an instance of UTPM
    V.shape = x.shape + (P,D)
    then x_utpm.data.shape = (D+1,P) = x.shape
    """
    x = numpy.asarray(x)
    V = numpy.asarray(V)

    xshp = x.shape
    Vshp = V.shape
    P, D = Vshp[-2:]
    Nxshp = len(xshp)
    NVshp = len(Vshp)
    numpy.testing.assert_array_equal(xshp,
                                     Vshp[:-2],
                                     err_msg='x.shape does not match V.shape')

    tc = numpy.zeros((D + 1, P) + xshp)
    for p in range(P):
        tc[0, p, ...] = x[...]

    axes_ids = tuple(numpy.arange(NVshp))
    tc[1:, ...] = V.transpose((axes_ids[-1], axes_ids[-2]) + axes_ids[:-2])

    return algopy.UTPM(tc)
Exemplo n.º 2
0
    def vec_jac(self, w, x):
        """ computes the Jacobian-vector product w^T*J of a function
        F:R^N --> R^M in the reverse mode

        wJ = self.vec_jac(w, x)

        Parameters
        ----------
        x: array_like
            x.ndim = 1

        w: array_like
            w.ndim = 1

        Returns
        -------
        wJ: array_like
            the vector-Jacobian product
        """

        x = numpy.asarray(x)
        w = numpy.asarray(w)

        if x.ndim != 1:
            raise ValueError("x.ndim must be 1 but provided %d"%x.ndim)

        if w.ndim != 1:
            raise ValueError("w.ndim must be 1 but provided %d"%w.ndim)

        M = self.dependentFunctionList[0].size

        tmp = numpy.zeros((1,1) + numpy.shape(x))
        tmp[0,...] = x
        utpm_x_list = [algopy.UTPM(tmp)]

        self.pushforward(utpm_x_list)

        ybar =  algopy.UTPM(numpy.zeros((1,1,M)))
        ybar.data[0,0,:] = w
        self.pullback([ybar])

        return self.independentFunctionList[0].xbar.data[0,0,...]
Exemplo n.º 3
0
    def vec_hess_vec(self, w, x, v):
        """ computes  d^2(w F) v, where  F:R^N ---> R^M

        lHv = self.vec_hess_mat(w, x, v)

        Parameters
        ----------
        lagra: array_like
            "Lagrange multipliers"

        x: array_like
            x.ndim = 1, base point

        v: array_like
            v.ndim = 1
            input directions

        Returns
        -------
        lHv: array
            two-dimensional array containing the result

        """


        x = numpy.asarray(x)
        v = numpy.asarray(v)
        w = numpy.asarray(w)

        if x.ndim != 1:
            raise ValueError("x.ndim must be 1 but provided %d"%x.ndim)

        if v.ndim != 1:
            raise ValueError("v.ndim must be 1 but provided %d"%v.ndim)

        if w.ndim != 1:
            raise ValueError("w.ndim must be 1 but provided %d"%w.ndim)

        if x.shape != v.shape or x.shape != w.shape:
            raise ValueError("x.shape must be the same as v.shape or v.shape, but provided x.shape=%s, v.shape=%s and w.shape=%s"%(x.shape, v.shape, w.shape))

        # raise NotImplementedError('this function does not work correctly yet')

        xtmp = numpy.zeros((2,1) + x.shape)
        xtmp[0,:] = x; xtmp[1,...] = v
        xtmp = algopy.UTPM(xtmp)

        self.pushforward([xtmp])
        ybar =  self.dependentFunctionList[0].x.zeros_like()
        ybar.data[0,0,...] = w
        self.pullback([ybar])

        return self.independentFunctionList[0].xbar.data[1,0,:]
Exemplo n.º 4
0
    def hess_vec(self, x, v):
        """ computes the Hessian vector product  dot(H,v)

        Hv = self.hess_vec(x, v)

        Parameters
        ----------
        x: array_like
            x.ndim == 1

        v: array_like
            x.ndim == 1

        Returns
        -------
        Hv: array
            one-dimensional array containing the Hessian vector product

        """

        x = numpy.asarray(x)
        v = numpy.asarray(v)

        if x.ndim != 1:
            raise ValueError("x.ndim must be 1 but provided %d"%x.ndim)

        if v.ndim != 1:
            raise ValueError("v.ndim must be 1 but provided %d"%v.ndim)

        if x.shape != v.shape:
            raise ValueError("x.shape must be the same as v.shape, but provided x.shape=%s and v.shape=%s"%(x.shape, v.shape))

        xtmp = numpy.zeros((2,1) + numpy.shape(x))
        xtmp[0,0] = x; xtmp[1,0] = v
        xtmp = algopy.UTPM(xtmp)

        self.pushforward([xtmp])
        ybar =  self.dependentFunctionList[0].x.zeros_like()
        ybar.data[0,:] = 1.
        self.pullback([ybar])

        return self.independentFunctionList[0].xbar.data[1,0]
Exemplo n.º 5
0
    def jac_vec(self, x, v):
        """ computes the Jacobian-vector product J*v of a function
        F:R^N --> R^M in the forward mode

        Jv = self.jac_vec(x, v)

        Parameters
        ----------
        x: array_like
            x.ndim = 1

        v: array_like
            w.ndim = 1

        Returns
        -------
        Jv: array_like
            the Jacobian-vector product
        """

        x = numpy.asarray(x)
        v = numpy.asarray(v)

        if x.ndim != 1:
            raise ValueError("x.ndim must be 1 but provided %d"%x.ndim)

        if v.ndim != 1:
            raise ValueError("v.ndim must be 1 but provided %d"%v.ndim)

        if x.shape != v.shape:
            raise ValueError("x.shape must be the same as v.shape but provided x.shape=%s, v.shape=%s "%(x.shape, v.shape))


        N = self.independentFunctionList[0].size

        tmp = numpy.zeros((2,1) + numpy.shape(x))
        tmp[0,...] = x
        tmp[1,0,...] = v
        utpm_x_list = [algopy.UTPM(tmp)]

        self.pushforward(utpm_x_list)
        return  self.dependentFunctionList[0].x.data[1,0,...]
Exemplo n.º 6
0
def f_fcn(x):
    A = algopy.zeros((2, 2), dtype=x)
    A[0, 0] = x[0]
    A[1, 0] = x[1] * x[0]
    A[0, 1] = x[1]
    Q, R = algopy.qr(A)
    return R[0, 0]


# Method 1: Complex-step derivative approximation (CSDA)
h = 10**-20
x0 = numpy.array([3, 2], dtype=float)
x1 = numpy.array([1, 0])
yc = numpy.imag(f_fcn(x0 + 1j * h * x1) - f_fcn(x0 - 1j * h * x1)) / (2 * h)

# Method 2: univariate Taylor polynomial arithmetic (UTP)
ax = algopy.UTPM(numpy.zeros((2, 1, 2)))
ax.data[0, 0] = x0
ax.data[1, 0] = x1
ay = f_fcn(ax)

# Method 3: finite differences
h = 10**-8
yf = (f_fcn(x0 + h * x1) - f_fcn(x0)) / h

# Print results
print('CSDA result =', yc)
print('UTP result  =', ay.data[1, 0])
print('FD  result  =', yf)
Exemplo n.º 7
0
        dirs[count + 1] += Id[n1]
        dirs[count + 1] -= Id[n2]

        count += 2

print('dirs =')
print(dirs)

# STEP 2: use these directions to initialize the UTPM instance
xdata = numpy.zeros((D, 2 * N * N, N))
xdata[0] = [1, 2, 3]
xdata[1] = dirs

# STEP 3: compute function F in UTP arithmetic
x = algopy.UTPM(xdata)
y = eval_F(x)

# STEP 4: use polarization identity to build univariate Taylor polynomial
#         of the Jacobian J
Jdata = numpy.zeros((D - 1, N, N, N))
count, count2 = 0, 0

# build J_0
for n in range(N):
    Jdata[0, :, :, n] = y.data[1, 2 * n * (N + 1), :] / 2.

# build J_1
count = 0
for n1 in range(N):
    for n2 in range(N):
Exemplo n.º 8
0
    def jacobian(self, x):
        """ computes the Jacobian of a function F:R^N --> R^M in the reverse mode

        J = self.jacobian(x)

        If x is a UTPM instance, the Taylor series of the entries of the Jacobian
        are computed.

        Parameters
        ----------

        x: array_like or UTPM instance
            x.ndim = 1

        Returns
        -------
        J: array_like or UTPM instance
            the Jacobian evaluated at x
            J.ndim = 2 when M>1 and J.ndim = 1 when M == 1


        Example
        -------

        import algopy

        def f(x):
            return x**2

        cg = algopy.CGraph()
        x = algopy.Function(numpy.array([3.,7.]))
        y = f(x)
        cg.trace_off()
        cg.independentFunctionList = [x]
        cg.dependentFunctionList = [y]
        print cg.jacobian(numpy.array([1.,2.]))

        """

        if len(self.independentFunctionList) != 1:
            err_str = 'len(self.independentFunctionList) must be 1 but provided %d' % \
                       len(self.independentFunctionList) 
            raise ValueError(err_str)

        if len(self.dependentFunctionList) != 1:
            err_str = 'len(self.dependentFunctionList) must be 1 but provided %d' % \
                       len(self.dependentFunctionList)
            raise ValueError(err_str)

        if isinstance(x, algopy.UTPM):

            if x.ndim != 1:
                raise ValueError("x.ndim must be 1 but provided %d"%x.ndim)
                
            M = self.dependentFunctionList[0].size

            D,P = x.data.shape[:2]
            shp = x.shape

            # if P != 1:
            #     raise ValueError("x.data.shape[1] must be 1, but provided %d" % x.data.shape[1])

            tmp = numpy.zeros((D,M*P) + x.shape)

            for p in range(P):
                tmp[:, p*M:(p+1)*M, ...] = x.data[:, p:p+1, ...]

            utpm_x_list = [algopy.UTPM(tmp)]

            self.pushforward(utpm_x_list)

            ybar = algopy.UTPM(numpy.zeros((D, P*M, M)))

            for p in range(P):
                ybar.data[0, p*M:(p+1)*M, :] = numpy.eye(M)

            self.pullback([ybar])

            return algopy.UTPM(self.independentFunctionList[0].xbar.data.reshape((D, P, M) + shp))


        else:
            x = numpy.asarray(x)

            if x.ndim != 1:
                raise ValueError("x.ndim must be 1 but provided %d"%x.ndim)

            M = self.dependentFunctionList[0].size

            tmp = numpy.zeros((1,M) + numpy.shape(x))
            tmp[0,...] = x
            utpm_x_list = [algopy.UTPM(tmp)]

            self.pushforward(utpm_x_list)

            ybar =  algopy.UTPM(numpy.zeros((1,M,M)))
            ybar.data[0,:,:] = numpy.eye(M)
            self.pullback([ybar])

            return self.independentFunctionList[0].xbar.data[0,:]
Exemplo n.º 9
0
    def gradient(self, x):
        """ computes the gradient of a function f: R^N --> R

        g = gradient(self, x_list)

        Parameters
        ----------

        x: array_like or list of array_like


        Example 1
        ---------

        import algopy

        def f(x):
            return x**2

        cg = algopy.CGraph()
        x = algopy.Function(3.)
        y = f(x)
        cg.trace_off()
        cg.independentFunctionList = [x]
        cg.dependentFunctionList = [y]
        print(cg.gradient(7.))


        Example 2
        ---------

        import algopy

        def f(x):
            return x[0]*x[1]

        cg = algopy.CGraph()
        x = algopy.Function([3., 7.])
        y = f(x)
        cg.trace_off()
        cg.independentFunctionList = [x]
        cg.dependentFunctionList = [y]
        print(cg.gradient([1.,2.]))
        """

        if self.dependentFunctionList[0].ndim != 0:
            raise Exception('you are trying to compute the gradient of a non-scalar valued function')

        if isinstance(x, list):
            if isinstance(x[0], numpy.ndarray) or isinstance(x[0], list):
                x_list = x
            else:
                x_list = [numpy.asarray(x)]
        else:
            x_list = [x]

        utpm_x_list = []
        for xi in x_list:
            element = numpy.asarray(xi).reshape((1,1) + numpy.shape(xi))
            utpm_x_list.append(algopy.UTPM(element))

        self.pushforward(utpm_x_list)

        ybar =  self.dependentFunctionList[0].x.zeros_like()
        ybar.data[0,:] = 1.
        self.pullback([ybar])

        if isinstance(x, list):
            return [x.xbar.data[0,0] for x in self.independentFunctionList]
        else:
            return self.independentFunctionList[0].xbar.data[0,0]
Exemplo n.º 10
0
# "defect_QR_minus_A": (algopy.dot(Q,R) - A).data,
# "defect_QTQ_minus_Id": (algopy.dot(Q.T,Q) - numpy.eye(M)).data
# })


import mpmath
mpmath.mp.prec = 200 # increase lenght of mantissa
print(mpmath.mp)

print('QR decomposition based on Householder')
D,P,M,N = 50,1,3,2

# in float64 arithmetic
data = numpy.random.random((D,P,M,N))
data = numpy.asarray(data, dtype=numpy.float64)
A = algopy.UTPM(data)
Q,R = qr_house(A.copy())

# in multiprecision arithmetic
data2 = numpy.asarray(data)*mpmath.mpf(1)
A2 = algopy.UTPM(data2)
Q2,R2 = qr_house(A2.copy())

print('-'*20)
print(A.data[-1])
print('-'*20)
print((Q.data[-1] - Q2.data[-1])/Q2.data[-1])
print('-'*20)
print(algopy.dot(Q, R).data[-1] - A.data[-1])
print('-'*20)
print(algopy.dot(Q2, R2).data[-1] - A2.data[-1])
Exemplo n.º 11
0
import numpy, algopy
from IPython.core.debugger import set_trace

x = algopy.UTPM(numpy.ones((2, 1)))
y = algopy.UTPM(2 * numpy.ones((2, 1)))

# right
z = algopy.zeros(2, dtype=x)
z[0] = x
z[1] = y

set_trace()