Ejemplo n.º 1
0
    def test_coefficient_vector(self):
        mesh = (np.arange(3), np.arange(10, 12))
        G = Grid.Grid(mesh, initializer=lambda *x: 0.0)
        # print G
        F = FD.FiniteDifferenceEngineADI(G,
                                         coefficients={
                                             (0, 1): lambda t, *x: 1
                                         })

        op = self.F.operators[(0, 1)]
        op.D.data[op.D.data != 0] = op.D.data[op.D.data != 0]**0
        op.D = todia(op.D)
        # diamat = op.D
        # densemat = diamat.todense()

        # f0 = lambda t, *x: x[0]
        # f1 = lambda t, *x: x[1]
        f = lambda t, *x: x

        vec = F.coefficient_vector(f, 0, 0)
        ref = np.tile(mesh[0], G.shape[1]), np.repeat(mesh[1], G.shape[0])
        npt.assert_array_equal(ref, vec, "Failed when focused on dim: %i", 0)

        vec = F.coefficient_vector(f, 0, 1)
        ref = np.repeat(mesh[0], G.shape[1]), np.tile(mesh[1], G.shape[0])
        npt.assert_array_equal(ref, vec, "Failed when focused on dim: %i", 1)
Ejemplo n.º 2
0
    def setUp(self):
        # print "Setting up Params for CPP tests"
        shape = (5,4)
        self.v1 = np.arange(shape[0]*shape[1], dtype=float)**2
        self.v2 = self.v1.copy()
        self.v2.resize(shape)

        coeffs = {(0,) : lambda t, *x: x[0]*x[1],
                  (0,0): lambda t, *x: x[0]*x[1],
                  (1,) : lambda t, *x: x[0]*x[1],
                  (1,1): lambda t, *x: x[0]*x[1],
                  (0,1): lambda t, *x: x[0]*x[1],
                  }
        bounds = {
                (0,)  : ((0,    lambda *args: 0),    (1,    lambda *args: 1)),
                (0,0) : ((0,    lambda *args: 0),    (None, lambda *args: 1)),
                (1,)  : ((None, lambda *args: None), (None, lambda *args: None)),
                (1,1) : ((1,    lambda *args: 0.0),  (None, lambda *args: None)),
                }

        schemes = {}

        self.G = Grid.Grid([np.arange(shape[0], dtype=float)**3, np.arange(shape[1], dtype=float)**3], lambda x, y: (x*shape[1]+y)**2)
        self.F = FD.FiniteDifferenceEngineADI(self.G, coefficients=coeffs,
                boundaries=bounds, schemes=schemes, force_bandwidth=None)
        # print "Setting up FDE for CPP tests"
        self.F.init()
        self.F.operators[0].R = np.arange(self.G.size, dtype=float)
        self.F.operators[1].R = np.arange(self.G.size, dtype=float)
Ejemplo n.º 3
0
    def setUp(self):
        loops = 200
        blocks = 2
        decimals = 12

        self.loops = loops
        self.blocks = blocks
        self.decimals = decimals

        mat = np.matrix("""
                        -1.5 0.5 2 0 0;
                        -1   2  -1 0 0;
                        0   -1   2 -1 0;
                        0   0    -1 2 -1;
                        0   0   -1.5 0.5 2""").A
        diamat = todia(scipy.sparse.dia_matrix(mat))

        x = foldMatFor(diamat, 1).todense().A
        topx = x.copy()
        bottomx = x.copy()
        topx[-1,-2] = 0
        bottomx[0,1] = 0
        x, topx, bottomx = map(todia, [x, topx, bottomx])


        topblockx = scipy.sparse.block_diag([topx]*blocks)
        bottomblockx = scipy.sparse.block_diag([bottomx]*blocks)
        blockx = todia(scipy.sparse.block_diag([x]*blocks))
        self.blockxI = blockx.todense().I.A
        self.topblockxI = topblockx.todense().I.A
        self.bottomblockxI = bottomblockx.todense().I.A

        npt.assert_array_equal(todia(topblockx.dot(bottomblockx)).data, blockx.data)

        blockdiamat = todia(scipy.sparse.block_diag([diamat]*blocks))

        blocktridiamat = todia(blockx.dot(blockdiamat))
        topblocktridiamat = todia(topblockx.dot(blockdiamat))
        bottomblocktridiamat = todia(bottomblockx.dot(blockdiamat))

        self.blockdiamat = blockdiamat

        self.blockx = blockx
        self.topblockx = topblockx
        self.bottomblockx = bottomblockx

        self.blocktridiamat = blocktridiamat
        self.topblocktridiamat = topblocktridiamat
        self.bottomblocktridiamat = bottomblocktridiamat

        self.vec = np.random.random(mat.shape[1]*blocks)

        self.B = FD.BandedOperator((blockdiamat.data, (2, 1, 0, -1, -2)), inplace=False)
        self.B.blocks = blocks
Ejemplo n.º 4
0
def build_FDE_2D(bounds=bounds):
    def init(x, y):
        mesh = np.sqrt(x[:, np.newaxis]**2 + y**2)
        return heat_kernel_nD(2, 0, mesh, dt)

    G = Grid(mesh=(np.linspace(-1, 1, 21), np.linspace(-1, 1, 21)),
             initializer=init)

    # vis.surface(G.domain[-1], *G.mesh)

    F = FD.FiniteDifferenceEngineADI(G, coefficients=coeffs, boundaries=bounds)
    return F
Ejemplo n.º 5
0
def build_FDE_1D(bounds=bounds):
    def init(x):
        return x**2
        # mesh = x
        # return heat_kernel_nD(2, 0, mesh, start)

    G = Grid(mesh=(np.linspace(xmin, xmax, nx), ), initializer=init)

    # vis.lineplot(G.domain[-1], *G.mesh)

    F = FD.FiniteDifferenceEngineADI(G, coefficients=coeffs, boundaries=bounds)
    return F
Ejemplo n.º 6
0
    def setUp(self):
        k = 3.0
        nspots = 7
        spot_max = 1500.0
        spotdensity = 7.0  # infinity is linear?
        vec = utils.sinh_space(k, spot_max, spotdensity, nspots)
        self.vec = vec

        def coeff(high,low=None):
            if low is not None:
                high, low = low, high
            return np.linspace(0, 1, len(vec))[low:high]
        def fcoeff(i):
            return np.linspace(0, 1, len(vec))[i]
        def f0(x): return x*0.0
        def fx(x): return x+2.0

        data = np.ones((5,len(vec)))
        data[0][:2] = 0
        data[1][0] = 0
        data[3][-1] = 0
        data[4][-2:] = 0
        offsets = [2,1,0,-1,-2]
        res = np.ones_like(vec)
        oldB = FD.BandedOperator((data, offsets), res)
        self.oldB = oldB

        manualB = oldB.copy()
        # newB = oldB.copy()
        # vecB = oldB.copy()
        manualB.D.data[0][2:] *= coeff(len(vec)-2)
        manualB.D.data[1][1:] *= coeff(len(vec)-1)
        manualB.D.data[2] *= coeff(len(vec))
        manualB.D.data[3][:-1] *= coeff(1, len(vec))
        manualB.D.data[4][:-2] *= coeff(2, len(vec))
        manualB.R *= coeff(len(vec))

        self.manualB = manualB

        self.coeff = coeff
        self.fcoeff = fcoeff
        self.f0 = f0
        self.fx = fx
Ejemplo n.º 7
0
    def test_scale_no_dirichlet(self):
        no_nan = np.nan_to_num
        vec = self.vec
        def f0(x): return 0
        def fx(x): return x
        data = np.ones((5,len(vec)), dtype=float)
        data[0][:2] = 0
        data[1][0] = 0
        data[3][-1] = 0
        data[4][-2:] = 0
        offsets = [2,1,0,-1,-2]
        res = np.ones_like(vec)
        oldB = FD.BandedOperator((data, offsets), res)

        newB = oldB.copy()
        newB.scale(f0)
        # fp(newB.D.data)
        npt.assert_array_equal(0, no_nan(newB.D.data))

        manualB = oldB.copy()
        newB = oldB.copy()
        manualB.D.data[0][2:] *= np.arange(len(vec)-2)
        manualB.D.data[1][1:] *= np.arange(len(vec)-1)
        manualB.D.data[2] *= np.arange(len(vec))
        manualB.D.data[3][:-1] *= np.arange(1, len(vec))
        manualB.D.data[4][:-2] *= np.arange(2, len(vec))
        manualB.R *= np.arange(len(vec))
        newB.scale(fx)
        # print "manual"
        # fp(manualB.data)
        # print
        # print "new"
        # fp(newB.data)
        # print
        # print "manualR"
        # print manualB.R
        # print
        # print "newR"
        # print newB.R
        npt.assert_array_equal(manualB, newB)
Ejemplo n.º 8
0
    def test_scale_dirichlet(self):
        # no_nan = np.nan_to_num
        vec = self.vec
        flag = int(1)
        data = np.ones((5,len(vec)), dtype=int)*flag
        data[0][:2] = 0
        data[1][0] = 0
        data[3][-1] = 0
        data[4][-2:] = 0
        offsets = [2,1,0,-1,-2]
        res = np.ones_like(vec)

        for dchlet in itertools.product([1., None], repeat=2):
            oldB = FD.BandedOperator((data.copy(), offsets), res.copy())
            oldB.dirichlet = dchlet
            zeroB = oldB.copy()
            zeroB.scale(self.f0)

            manualzeroB = np.zeros_like(zeroB.D.data)
            if zeroB.dirichlet[0] is not None:
                manualzeroB[0, 2] = flag
                manualzeroB[1, 1] = flag
                manualzeroB[2, 0] = flag
            if zeroB.dirichlet[1] is not None:
                manualzeroB[2, -1] = flag
                manualzeroB[3, -2] = flag
                manualzeroB[4, -3] = flag

            # print "Dirichlet", dchlet
            # print
            # print "zeroB"
            # fp(zeroB.D.data)
            # fp(zeroB.R)
            # print
            # print "manualzeroB"
            # fp(manualzeroB)
            # fp(manualzeroB.R)
            # print

            manualB = oldB.copy()
            newB = oldB.copy()
            bottom = 0
            top = manualB.shape[0]
            if dchlet[0]:
                bottom += 1
            if dchlet[1]:
                top -= 1
            manualB.D.data[0][bottom+2:] *= np.arange(bottom, manualB.shape[0]-2)+2
            manualB.D.data[1][bottom+1:] *= np.arange(bottom, manualB.shape[0]-1)+2
            manualB.D.data[2][bottom:top] *= np.arange(bottom, top)+2
            manualB.D.data[3][:top-1] *= np.arange(1, top)+2
            manualB.D.data[4][:top-2] *= np.arange(2, top)+2
            manualB.R[bottom:top] *= np.arange(bottom, top)+2
            newB.scale(self.fx)
            # print "manual"
            # fp(manualB.D.data)
            # print
            # print "new"
            # fp(newB.D.data)
            # print
            # print "manualR"
            # print manualB.R
            # print
            # print "newR"
            # print newB.R
            npt.assert_array_equal(manualzeroB, zeroB.D.data)
            assert manualB == newB
Ejemplo n.º 9
0
    def test_block_vectorizedscale(self):
        no_nan = np.nan_to_num
        vec = self.vec
        oldB = self.oldB
        manualB = self.manualB
        flag = int(1)
        data = np.ones((5,len(vec)), dtype=float)*flag
        data[0][:2] = 0
        data[1][0] = 0
        data[3][-1] = 0
        data[4][-2:] = 0
        offsets = [2,1,0,-1,-2]
        res = np.ones_like(vec)

        blocks = 3

        blockvec = np.tile(vec, blocks)

        newB = oldB.copy()
        newB.scale(self.f0)
        vecB = oldB.copy()
        vecB.vectorized_scale(self.f0(vec))


        npt.assert_array_equal(0, no_nan(newB.D.data))
        npt.assert_array_equal(0, no_nan(vecB.D.data))

        for dchlet in itertools.product([1., None], repeat=2):
            oldB = FD.BandedOperator((data.copy(), offsets), res.copy())
            oldB.dirichlet = dchlet

            veczeroB = block_repeat(oldB, blocks)
            veczeroB.vectorized_scale(self.f0(blockvec))
            manualzeroB = np.zeros_like(oldB.D.data)
            if veczeroB.dirichlet[0] is not None:
                manualzeroB[0, 2] = flag
                manualzeroB[1, 1] = flag
                manualzeroB[2, 0] = flag
            if veczeroB.dirichlet[1] is not None:
                manualzeroB[2, -1] = flag
                manualzeroB[3, -2] = flag
                manualzeroB[4, -3] = flag
            manualzeroB = np.tile(manualzeroB, blocks)

            # print dchlet
            # print
            # print "veczeroB"
            # fp(veczeroB.D.data)
            # print
            # print "manualzeroB"
            # fp(manualzeroB)
            # print

            manualB = oldB.copy()
            bottom = 0
            top = last = manualB.shape[0]
            if dchlet[0]:
                bottom += 1
            if dchlet[1]:
                top -= 1
            manualB.D.data[0][bottom+2:]  *= vec[bottom : last-2]+2
            manualB.D.data[1][bottom+1:]  *= vec[bottom : last-1]+2
            manualB.D.data[2][bottom:top] *= vec[bottom : top]+2
            manualB.D.data[3][:top-1]     *= vec[1      : top]+2
            manualB.D.data[4][:top-2]     *= vec[2      : top]+2
            manualB.R[bottom:top]       *= vec[bottom:top]+2
            manualB = block_repeat(manualB, blocks)

            vecB = block_repeat(oldB, blocks)
            vecB.vectorized_scale(self.fx(blockvec))

            newB = block_repeat(oldB, blocks)
            newB.scale(lambda i: blockvec[i]+2)
            # print "vec"
            # fp(vec)
            # print
            # print "manual"
            # fp(manualB.D.data)
            # print
            # print "newB"
            # fp(newB.D.data)
            # print
            # print "vecB"
            # fp(vecB.D.data)
            # print
            # print "manualR"
            # print manualB.R
            # print
            # print "vecR"
            # print vecB.R
            # print
            # print "newR"
            # print newB.R
            # print
            # print "manual"
            # fp(manualB.D)
            # print
            # print "newB"
            # fp(newB.D)
            npt.assert_array_equal(manualzeroB, veczeroB.D.data)
            npt.assert_(newB == vecB)
            npt.assert_array_equal(manualB, newB)
            npt.assert_array_equal(manualB, vecB)

        newB = oldB.copy()
        newB.scale(self.fcoeff)
        vecB = oldB.copy()
        vecB.vectorized_scale(self.coeff(len(vec)))
        # print "new"
        # fp(newB.data)
        # print
        # print "vec"
        # fp(vecB.data)
        # print
        # print "newR"
        # print newB.R
        assert newB == vecB
Ejemplo n.º 10
0
    def setUp(self):
        s1_enable = 1
        s2_enable = 1
        v1_enable = 1
        v2_enable = 1
        r_enable = 1
        dirichlet_s = 1
        dirichlet_v = 1
        kappa = 1
        r = 0.06
        theta = 0.04
        sigma = 0.4
        rho = 0.6
        spot_max = 1500.0
        var_max = 13.0
        nspots = 5
        nvols = 5
        spotdensity = 7.0  # infinity is linear?
        varexp = 5

        up_or_down_spot = 'up'
        up_or_down_var = 'down'
        flip_idx_spot = nspots // 2
        flip_idx_var = nvols // 2
        k = spot_max / 4.0
        # spots = np.linspace(0, spot_max, nspots)
        # vars = np.linspace(0, var_max, nvols)
        spots = utils.sinh_space(k, spot_max, spotdensity, nspots)
        vars = utils.exponential_space(0.00, 0.04, var_max, varexp, nvols)

        def mu_s(t, *dim):
            return r * dim[0] * s1_enable

        def gamma2_s(t, *dim):
            return 0.5 * dim[1] * dim[0]**2 * s2_enable

        def mu_v(t, *dim):
            return kappa * (theta - dim[1]) * v1_enable

        def gamma2_v(t, *dim):
            return 0.5 * sigma**2 * dim[1] * v2_enable

        coeffs = {
            (): lambda t: -r * r_enable,
            (0, ): mu_s,
            (0, 0): gamma2_s,
            (1, ): mu_v,
            (1, 1): gamma2_v,
            (0, 1): lambda t, *dim: dim[0] * dim[1] * rho * sigma
        }
        coeffs = {k: lambda *x: 1 for k in coeffs}
        bounds = {
            (0, ): ((0, lambda *args: 0), (1, lambda *args: 1)),
            (0, 0): ((0, lambda *args: 0), (None, lambda *args: 1)),
            (1, ): ((None, lambda *args: None), (None, lambda *args: None)),
            (1, 1): ((1, lambda *args: 0.0), (None, lambda *args: None)),
        }

        schemes = {}
        # G = Grid.Grid((spots, vars), initializer=lambda x0,x1: np.maximum(x0-k,0))
        self.G = Grid.Grid((spots, vars), initializer=lambda x0, x1: x0 * x1)
        # print G

        self.F = FD.FiniteDifferenceEngineADI(self.G,
                                              coefficients=coeffs,
                                              boundaries=bounds,
                                              schemes=schemes,
                                              force_bandwidth=None)
        self.F.init()
        # self.F.operators[1].diagonalize()
        self.FG = FDG.FiniteDifferenceEngineADI()
        self.FG.from_host_FiniteDifferenceEngine(self.F)
Ejemplo n.º 11
0
    def test_dirichlet_boundary(self):
        spots = np.arange(5.)
        vars = np.arange(4.)

        def rndgrid(x0, x1):
            return np.random.random((x0.shape[0], x1.shape[1]))

        G = Grid.Grid((spots, vars), initializer=rndgrid)
        npt.assert_array_equal(G.shape, tuple(map(len, G.mesh)))
        coeffs = bounds = {}
        coeffs = {
            (0, ): lambda t, *dim: 1,
            # (0,0): lambda t, *dim: 0,
            (
                1, ): lambda t, *dim: 0,
            # (1,1): lambda t, *dim: 0,
            # (0,1): lambda t, *dim: 0
        }
        bounds = {
            (0, ): ((0, lambda t, *x: 1), (0, lambda t, *x: 1)),
            # (0,0): ((None, lambda *x: 1), (0, lambda *x: 1)),
            (
                1, ): ((0, lambda *x: 1), (0, lambda *x: 1)),
            # (1,1): ((0, lambda *x: 1), (0, lambda *x: 1)),
        }
        F = FD.FiniteDifferenceEngineADI(G,
                                         coefficients=coeffs,
                                         boundaries=bounds,
                                         force_bandwidth=None)
        F.init()

        for d, o in F.simple_operators.items():
            l = [[1] * F.grid.shape[(o.axis + 1) % 2]] * 2
            npt.assert_array_equal(
                o.dirichlet,
                l,
                err_msg="Dim: %s, dirichlet: %s, expected: %s" %
                (d, o.dirichlet, l))
        for d, o in F.simple_operators.items():
            l = [[1] * F.grid.shape[(o.axis + 1) % 2]] * 2
            npt.assert_array_equal(
                o.dirichlet,
                l,
                err_msg="Dim: %s, dirichlet: %s, expected: %s" %
                (d, o.dirichlet, l))

        for d in bounds.keys():
            B = F.simple_operators[d]
            # print "Derivative", d, "Dirichlets", B.dirichlet
            g = (B + 1).solve(F.grid.domain[-1])
            if B.axis == 1:
                g = g.T
            if B.dirichlet[0] is not None:
                npt.assert_array_equal(g[0, :], 1)
            if B.dirichlet[1] is not None:
                npt.assert_array_equal(g[-1, :], 1)

        for d in bounds.keys():
            B = F.simple_operators[d]
            # print "Derivative", d, "Dirichlets", B.dirichlet
            # print B.dirichlet
            g = B.apply(F.grid.domain[-1])
            if B.axis == 1:
                g = g.T
            if B.dirichlet[0] is not None:
                npt.assert_array_equal(g[0, :], 1)
            if B.dirichlet[1] is not None:
                npt.assert_array_equal(g[-1, :], 1)

        for d in bounds.keys():
            B = F.simple_operators[d]
            # print "Derivative", d, "Dirichlets", B.dirichlet
            # fp(B.data)
            g = (B + 1).solve(F.grid.domain[-1])
            # fp(g)
            if B.axis == 1:
                g = g.T
            if B.dirichlet[0] is not None:
                npt.assert_array_equal(g[0, :], 1)
            if B.dirichlet[1] is not None:
                npt.assert_array_equal(g[-1, :], 1)
Ejemplo n.º 12
0
    def test_numpy_vs_operators(self):
        spots = np.linspace(0, 1, 4)
        vars = np.linspace(0, 10, 4)
        # spots = self.G.mesh[0]
        # vars = self.G.mesh[1]
        G = Grid.Grid((spots, vars), initializer=lambda x0, x1: x1 * 1)
        coeffs = {
            (): lambda t: 0,
            (0, ): lambda t, *dim: dim[0],
            (0, 0): lambda t, *dim: dim[0],
            (1, ): lambda t, *dim: 0 * dim[1],
            (1, 1): lambda t, *dim: dim[1],
            (0, 1): lambda t, *dim: dim[0] * dim[1]
        }
        bounds = {
            (0, ): ((None, lambda *x: None), (None, lambda *x: 3)),
            (0, 0): ((None, lambda *x: None), (None, lambda *x: 3)),
            (1, ): ((None, lambda *x: None), (None, lambda *x: 1)),
            (1, 1): ((None, lambda *x: None), (None, lambda *x: 1)),
        }
        F = FD.FiniteDifferenceEngineADI(G,
                                         coefficients=coeffs,
                                         boundaries=bounds,
                                         force_bandwidth=None)
        F.init()

        cb = utils.clear_boundary
        g = F.grid.domain[-1]

        op_ = {'delta': {}, 'grid_delta': {}, 'derivative': {}}
        np_ = {'delta': {}, 'grid_delta': {}, 'derivative': {}}

        dims = coeffs.keys()
        dims.remove(())

        for dim in dims:
            op_['grid_delta'][dim] = F.simple_operators[dim].copy()
            op_['grid_delta'][dim].R = None

        op_['delta'][(0, )] = op_['grid_delta'][(0, )].deltas[:, np.newaxis]
        op_['delta'][(1, )] = op_['grid_delta'][(1, )].deltas

        x = F.grid.mesh[0]
        y = F.grid.mesh[1]
        np_['delta'][(0, )] = np.gradient(x)[:, np.newaxis]
        np_['delta'][(1, )] = np.gradient(y)
        np_['delta'][(0, )][0, 0] = np.nan
        np_['delta'][(1, )][0] = np.nan

        for f in (op_, np_):
            f['delta'][(0, 0)] = f['delta'][(0, )]**2
            f['delta'][(1, 1)] = f['delta'][(1, )]**2
            f['delta'][(0, 1)] = f['delta'][(1, )] * f['delta'][(0, )]
            f['delta'][(1, 0)] = f['delta'][(1, )] * f['delta'][(0, )]

        np_['grid_delta'][(0, )], np_['grid_delta'][(1, )] = np.gradient(g)
        for fst in [0, 1]:
            np_['grid_delta'][(fst,
                               0)], np_['grid_delta'][(fst, 1)] = np.gradient(
                                   np_['grid_delta'][(fst, )])

        Y, X = np.meshgrid(y, x)
        for dim in dims:
            op_['derivative'][dim] = cb(op_['grid_delta'][dim].apply(g),
                                        inplace=True)
            npt.assert_(op_['derivative'][dim].shape == g.shape)
            np_['derivative'][dim] = cb(np_['grid_delta'][dim] /
                                        np_['delta'][dim],
                                        inplace=True)
            np_['derivative'][dim] *= F.coefficients[dim](0, X, Y)
            op_['derivative'][dim] *= F.coefficients[dim](0, X, Y)

        np_['derivative'][(1, 0)] = cb(np_['grid_delta'][(1, 0)] /
                                       np_['delta'][(1, 0)],
                                       inplace=True)
        np_['derivative'][(1, 0)] *= F.coefficients[(0, 1)](0, X, Y)

        for dim in dims:
            for x in ('delta', 'derivative'):
                msg = "Comparing %s in dimension %s" % (x, dim)
                try:
                    npt.assert_array_almost_equal(op_[x][dim],
                                                  np_[x][dim],
                                                  decimal=7,
                                                  err_msg=msg)
                except AssertionError:
                    print msg, op_['grid_delta'][dim].axis
                    fp((op_['grid_delta'][dim]).D.data)
                    fp((op_[x][dim]), fmt='f')
                    fp((np_[x][dim]), fmt='f')
                    fp((op_[x][dim] - np_[x][dim]), fmt='f')
                # npt.assert_allclose(op_[x][dim], np_[x][dim], err_msg=msg)
                npt.assert_array_almost_equal(op_[x][dim],
                                              np_[x][dim],
                                              decimal=7,
                                              err_msg=msg)

        npt.assert_array_almost_equal(np_['derivative'][(0, 1)],
                                      np_['derivative'][(1, 0)],
                                      err_msg=msg)
Ejemplo n.º 13
0
    def setUp(self):
        s1_enable = 1
        s2_enable = 1
        v1_enable = 1
        v2_enable = 1
        r_enable = 1
        dirichlet_s = 1
        dirichlet_v = 1
        kappa = 1
        r = 0.06
        theta = 0.04
        sigma = 0.4
        rho = 0.6
        spot_max = 1500.0
        var_max = 13.0
        nspots = 5
        nvols = 5
        spotdensity = 7.0  # infinity is linear?
        varexp = 5

        # TODO:!!!!XXX TODO XXX
        # var_max = nvols-1
        # spot_max = nspots-1

        up_or_down_spot = 'up'
        up_or_down_var = 'down'
        flip_idx_spot = nspots // 2
        flip_idx_var = nvols // 2
        k = spot_max / 4.0
        # spots = np.linspace(0, spot_max, nspots)
        # vars = np.linspace(0, var_max, nvols)
        spots = utils.sinh_space(k, spot_max, spotdensity, nspots)
        vars = utils.exponential_space(0.00, 0.04, var_max, varexp, nvols)

        def mu_s(t, *dim):
            return r * dim[0] * s1_enable

        def gamma2_s(t, *dim):
            return 0.5 * dim[1] * dim[0]**2 * s2_enable

        def mu_v(t, *dim):
            return kappa * (theta - dim[1]) * v1_enable

        def gamma2_v(t, *dim):
            return 0.5 * sigma**2 * dim[1] * v2_enable

        coeffs = {
            (): lambda t: -r * r_enable,
            (0, ): mu_s,
            (0, 0): gamma2_s,
            (1, ): mu_v,
            (1, 1): gamma2_v,
            (0, 1): lambda t, *dim: dim[0] * dim[1] * rho * sigma
        }
        bounds = {
            # D: U = 0              VN: dU/dS = 1
            (
                0, ): ((0 if dirichlet_s else 1, lambda *args: 0.0),
                       (1, lambda *args: 1.0)),
            # D: U = 0              Free boundary
            (0, 0): ((0 if dirichlet_s else 1, lambda *args: 0.0),
                     (None, lambda *x: 1.0)),
            # Free boundary at low variance
            (
                1, ): (
                (None, lambda *x: None),
                # (0.0, lambda t, *dim: 0),
                # D intrinsic value at high variance
                # (None, lambda *x: None)
                (0 if dirichlet_v else 1,
                 lambda t, *dim: np.maximum(0.0, dim[0] - k))),
            # # Free boundary
            (1, 1): (
                (1, lambda *x: 0),
                # D intrinsic value at high variance
                # (None, lambda *x: None)
                (0 if dirichlet_v else 1,
                 lambda t, *dim: np.maximum(0.0, dim[0] - k)))
        }

        schemes = {}
        schemes[(0, )] = ({
            "scheme": "center"
        }, {
            "scheme": up_or_down_spot,
            "from": flip_idx_spot
        })
        schemes[(1, )] = ({
            "scheme": "center"
        }, {
            "scheme": up_or_down_var,
            "from": flip_idx_var
        })

        dss = np.hstack((np.nan, np.diff(spots)))
        dvs = np.hstack((np.nan, np.diff(vars)))
        As_ = utils.nonuniform_complete_coefficients(
            dss, up_or_down=up_or_down_spot, flip_idx=flip_idx_spot)[0]
        Ass_ = utils.nonuniform_complete_coefficients(dss)[1]
        L1_ = []
        R1_ = []
        # As_, Ass_ = utils.nonuniform_forward_coefficients(dss)
        assert (not np.isnan(As_.data).any())
        assert (not np.isnan(Ass_.data).any())
        for j, v in enumerate(vars):
            # Be careful not to overwrite operators
            As, Ass = As_.copy(), Ass_.copy()
            m = 2

            mu_s = r * spots * s1_enable
            gamma2_s = 0.5 * v * spots**2 * s2_enable
            for i, z in enumerate(mu_s):
                # print z, coeffs[0,](0, spots[i])
                assert z == coeffs[0, ](0, spots[i])
            for i, z in enumerate(gamma2_s):
                # print z, coeffs[0,0](0, spots[i], v)
                assert z == coeffs[0, 0](0, spots[i], v)

            Rs = np.zeros(nspots)
            Rs[-1] = 1

            As.data[m - 2, 2:] *= mu_s[:-2]
            As.data[m - 1, 1:] *= mu_s[:-1]
            As.data[m, :] *= mu_s
            As.data[m + 1, :-1] *= mu_s[1:]
            As.data[m + 2, :-2] *= mu_s[2:]

            Rs *= mu_s

            Rss = np.zeros(nspots)
            Rss[-1] = 2 * dss[-1] / dss[-1]**2

            Ass.data[m + 1, -2] = 2 / dss[-1]**2
            Ass.data[m, -1] = -2 / dss[-1]**2

            Ass.data[m - 2, 2:] *= gamma2_s[:-2]
            Ass.data[m - 1, 1:] *= gamma2_s[:-1]
            Ass.data[m, :] *= gamma2_s
            Ass.data[m + 1, :-1] *= gamma2_s[1:]
            Ass.data[m + 2, :-2] *= gamma2_s[2:]

            Rss *= gamma2_s

            L1_.append(As.copy())
            L1_[j].data += Ass.data
            L1_[j].data[m, :] -= 0.5 * r * r_enable
            L1_[j].data[m, 0] = 1 * dirichlet_s

            R1_.append((Rs + Rss).copy())
            R1_[j][0] = 0

        L2_ = []
        R2_ = []
        Av_ = utils.nonuniform_complete_coefficients(dvs,
                                                     up_or_down=up_or_down_var,
                                                     flip_idx=flip_idx_var)[0]
        Avv_ = utils.nonuniform_complete_coefficients(dvs)[1]
        assert (not np.isnan(Av_.data).any())
        assert (not np.isnan(Avv_.data).any())
        for i, s in enumerate(spots):
            mu_v = kappa * (theta - vars) * v1_enable
            gamma2_v = 0.5 * sigma**2 * vars * v2_enable
            # for j, z in enumerate(mu_v):
            # assert z == coeffs[1,](0, 0, vars[j])
            # for j, z in enumerate(gamma2_v):
            # assert z == coeffs[1,1](0, 0, vars[j])

            # Be careful not to overwrite our operators
            Av, Avv = Av_.copy(), Avv_.copy()

            m = 2

            Av.data[m - 2, 2] = -dvs[1] / (dvs[2] * (dvs[1] + dvs[2]))
            Av.data[m - 1, 1] = (dvs[1] + dvs[2]) / (dvs[1] * dvs[2])
            Av.data[m,
                    0] = (-2 * dvs[1] - dvs[2]) / (dvs[1] * (dvs[1] + dvs[2]))

            Av.data[m - 2, 2:] *= mu_v[:-2]
            Av.data[m - 1, 1:] *= mu_v[:-1]
            Av.data[m, :] *= mu_v
            Av.data[m + 1, :-1] *= mu_v[1:]
            Av.data[m + 2, :-2] *= mu_v[2:]

            Rv = np.zeros(nvols)
            Rv *= mu_v

            Avv.data[m - 1, 1] = 2 / dvs[1]**2
            Avv.data[m, 0] = -2 / dvs[1]**2

            Avv.data[m - 2, 2:] *= gamma2_v[:-2]
            Avv.data[m - 1, 1:] *= gamma2_v[:-1]
            Avv.data[m, :] *= gamma2_v
            Avv.data[m + 1, :-1] *= gamma2_v[1:]
            Avv.data[m + 2, :-2] *= gamma2_v[2:]

            Rvv = np.zeros(nvols)
            Rvv[0] = 2 * dvs[1] / dvs[1]**2
            Rvv *= gamma2_v

            L2_.append(Av.copy())
            L2_[i].data += Avv.data
            L2_[i].data[m, :] -= 0.5 * r * r_enable
            L2_[i].data[
                m,
                -1] = 1 * dirichlet_v  # This is to cancel out the previous value so we can
            # set the dirichlet boundary condition using R.
            # Then we have U_i + -U_i + R

            R2_.append(Rv + Rvv)
            R2_[i][-1] = 0  # np.maximum(0, s - k)

        def flatten_tensor(mats):
            diags = np.hstack([x.data for x in mats])
            flatmat = scipy.sparse.dia_matrix(
                (diags, mats[0].offsets),
                shape=(diags.shape[1], diags.shape[1]))
            return flatmat

        L1 = flatten_tensor(L1_)
        L2 = flatten_tensor(L2_)
        R1 = np.array(R1_).T
        R2 = np.array(R2_)

        self.As_ = As_
        self.Ass_ = Ass_
        self.L1_ = L1
        self.R1_ = R1
        self.L2_ = L2
        self.R2_ = R2
        # G = Grid.Grid((spots, vars), initializer=lambda x0,x1: np.maximum(x0-k,0))
        self.G = Grid.Grid((spots, vars), initializer=lambda x0, x1: x0 * x1)
        # print G

        self.F = FD.FiniteDifferenceEngineADI(self.G,
                                              coefficients=coeffs,
                                              boundaries=bounds,
                                              schemes=schemes,
                                              force_bandwidth=None)
        self.F.init()