Example #1
0
def setupImplicitFunction(operAlpha, An, geom):

    #setup function to obtain B and RHS for the Fourier series calc
    def getBandRHS(alphaiLoc):
        alphaLoc = geom.alphaGeometric(operAlpha) - alphaiLoc
        clLoc = geom.clLoc(alphaLoc)
        RHS = clLoc*geom.chordLoc
        B = numpy.sin(numpy.outer(geom.thetaLoc, geom.sumN))*(4.0*geom.bref)
        return (B,RHS)

    alphaiLoc = []
    for i in range(geom.n):
        alphaiLoc.append(
            C.inner_prod(geom.sumN*numpy.sin(geom.sumN*geom.thetaLoc[i])/numpy.sin(geom.thetaLoc[i]), An))
    alphaiLoc = C.veccat(alphaiLoc)

    (B,RHS) = getBandRHS(alphaiLoc)
    makeMeZero = RHS - C.mul(B, An)

    CL  = An[0]*numpy.pi*geom.AR
    CDi = 0.0
    for i in range(geom.n):
        k = geom.sumN[i]
        CDi += k * An[i]**2 / An[0]**2
    CDi *= numpy.pi*geom.AR*An[0]**2

    return (makeMeZero, alphaiLoc, CL, CDi)
Example #2
0
File: ad.py Project: ml-lab/casadi
    def test_MX(self):

        x = MX.sym("x", 2)
        y = MX.sym("y", 2, 2)

        f1 = MXFunction("f1", [x, y], [x + y[0, 0], mul(y, x)])

        f2 = MXFunction("f2", [x, y], [mul(MX.zeros(0, 2), x)])

        f3 = MXFunction("f3", [x, y], [MX.zeros(0, 0), mul(y, x)])

        f4 = MXFunction("f4", [x, y], [MX.zeros(0, 2), mul(y, x)])

        ndir = 2

        in1 = [x, y]
        v1 = [DMatrix([1.1, 1.3]), DMatrix([[0.7, 1.5], [2.1, 0.9]])]

        w = x[:]
        w[1] *= 2

        w2 = x[:]
        w2[1] *= x[0]

        ww = x[:]
        ww[[0, 1]] *= x

        wwf = x[:]
        wwf[[1, 0]] *= x

        wwr = x[:]
        wwr[[0, 0, 1, 1]] *= 2

        yy = y[:, :]

        yy[:, 0] = x

        yy2 = y[:, :]

        yy2[:, 0] = x**2

        yyy = y[:, :]

        yyy[[1, 0], 0] = x

        yyy2 = y[:, :]

        yyy2[[1, 0], 0] = x**2

        def remove_first(x):
            ret = DMatrix(x)
            if ret.numel() > 0:
                ret[0, 0] = DMatrix(1, 1)
                return ret
            else:
                return ret

        def remove_last(x):
            ret = DMatrix(x)
            if ret.nnz() > 0:
                ret[ret.sparsity().row()[-1],
                    ret.sparsity().getCol()[-1]] = DMatrix(1, 1)
                return ret
            else:
                return x

        spmods = [lambda x: x, remove_first, remove_last]

        # TODO: sparse seeding

        for inputs, values, out, jac in [
            (in1, v1, x, DMatrix.eye(2)),
            (in1, v1, x.T, DMatrix.eye(2)),
            (in1, v1, x**2, 2 * c.diag(x)),
            (in1, v1, (x**2).attachAssert(True), 2 * c.diag(x)),
            (in1, v1, (x**2).T, 2 * c.diag(x)),
            (in1, v1, c.reshape(x, (1, 2)), DMatrix.eye(2)),
            (in1, v1, c.reshape(x**2, (1, 2)), 2 * c.diag(x)),
            (in1, v1, x + y.nz[0], DMatrix.eye(2)),
            (in1, v1, x + y[0, 0], DMatrix.eye(2)),
            (in1, v1, x + x, 2 * DMatrix.eye(2)),
            (in1, v1, x**2 + x, 2 * c.diag(x) + DMatrix.eye(2)),
            (in1, v1, x * x, 2 * c.diag(x)),
            (in1, v1, x * y.nz[0], DMatrix.eye(2) * y.nz[0]),
            (in1, v1, x * y[0, 0], DMatrix.eye(2) * y[0, 0]),
            (in1, v1, x[0], DMatrix.eye(2)[0, :]),
            (in1, v1, (x**2)[0], horzcat([2 * x[0], MX(1, 1)])),
            (in1, v1, x[0] + x[1], DMatrix.ones(1, 2)),
            (in1, v1, sin(repmat(x**2, 1, 3)),
             repmat(cos(c.diag(x**2)) * 2 * c.diag(x), 3, 1)),
            (in1, v1, sin(repsum((x**2).T, 1,
                                 2)), cos(x[0]**2 + x[1]**2) * 2 * x.T),
            (in1, v1, vertcat([x[1], x[0]]), sparsify(DMatrix([[0, 1], [1,
                                                                        0]]))),
            (in1, v1, vertsplit(x, [0, 1, 2])[1], sparsify(DMatrix([[0, 1]]))),
            (in1, v1, vertcat([x[1]**2, x[0]**2]),
             blockcat([[MX(1, 1), 2 * x[1]], [2 * x[0], MX(1, 1)]])),
            (in1, v1, vertsplit(x**2,
                                [0, 1, 2])[1], blockcat([[MX(1, 1),
                                                          2 * x[1]]])),
            (in1, v1, vertsplit(x**2, [0, 1, 2])[1]**3,
             blockcat([[MX(1, 1), 6 * x[1]**5]])),
            (in1, v1, horzcat([x[1],
                               x[0]]).T, sparsify(DMatrix([[0, 1], [1, 0]]))),
            (in1, v1, horzcat([x[1]**2, x[0]**2]).T,
             blockcat([[MX(1, 1), 2 * x[1]], [2 * x[0], MX(1, 1)]])),
            (in1, v1, diagcat([x[1]**2, y, x[0]**2]),
             blockcat([[MX(1, 1), 2 * x[1]]] + ([[MX(1, 1), MX(1, 1)]] * 14) +
                      [[2 * x[0], MX(1, 1)]])),
            (in1, v1, horzcat([x[1]**2, x[0]**2]).T,
             blockcat([[MX(1, 1), 2 * x[1]], [2 * x[0], MX(1, 1)]])),
            (in1, v1, x[[0, 1]], sparsify(DMatrix([[1, 0], [0, 1]]))),
            (in1, v1, (x**2)[[0, 1]], 2 * c.diag(x)),
            (in1, v1, x[[0, 0, 1, 1]],
             sparsify(DMatrix([[1, 0], [1, 0], [0, 1], [0, 1]]))),
            (in1, v1, (x**2)[[0, 0, 1, 1]],
             blockcat([[2 * x[0], MX(1, 1)], [2 * x[0], MX(1, 1)],
                       [MX(1, 1), 2 * x[1]], [MX(1, 1), 2 * x[1]]])),
            (in1, v1, wwr, sparsify(DMatrix([[2, 0], [0, 2]]))),
            (in1, v1, x[[1, 0]], sparsify(DMatrix([[0, 1], [1, 0]]))),
            (in1, v1, x[[1, 0], 0], sparsify(DMatrix([[0, 1], [1, 0]]))),
            (in1, v1, w, sparsify(DMatrix([[1, 0], [0, 2]]))),
            (in1, v1, w2, blockcat([[1, MX(1, 1)], [x[1], x[0]]])),
            (in1, v1, ww, 2 * c.diag(x)),
            (in1, v1, wwf, vertcat([x[[1, 0]].T, x[[1, 0]].T])),
            (in1, v1, yy[:, 0], DMatrix.eye(2)),
            (in1, v1, yy2[:, 0], 2 * c.diag(x)),
            (in1, v1, yyy[:, 0], sparsify(DMatrix([[0, 1], [1, 0]]))),
            (in1, v1, mul(y, x), y),
            (in1, v1, mul(x.T, y.T), y),
            (in1, v1, mac(y, x, DMatrix.zeros(Sparsity.triplet(2, 1, [1],
                                                               [0]))),
             y[Sparsity.triplet(2, 2, [1, 1], [0, 1])]),
            (in1, v1,
             mac(x.T, y.T, DMatrix.zeros(Sparsity.triplet(2, 1, [1], [0]).T)),
             y[Sparsity.triplet(2, 2, [1, 1], [0, 1])]),
            (in1, v1, mul(y[Sparsity.triplet(2, 2, [0, 1, 1], [0, 0, 1])],
                          x), y[Sparsity.triplet(2, 2, [0, 1, 1], [0, 0, 1])]),
            (in1, v1,
             mul(x.T, y[Sparsity.triplet(2, 2, [0, 1, 1], [0, 0, 1])].T),
             y[Sparsity.triplet(2, 2, [0, 1, 1], [0, 0, 1])]),
            (in1, v1, mul(y, x**2), y * 2 * vertcat([x.T, x.T])),
            (in1, v1, sin(x), c.diag(cos(x))),
            (in1, v1, sin(x**2), c.diag(cos(x**2) * 2 * x)),
            (in1, v1, x * y[:, 0], c.diag(y[:, 0])),
            (in1, v1, x * y.nz[[0, 1]], c.diag(y.nz[[0, 1]])),
            (in1, v1, x * y.nz[[1, 0]], c.diag(y.nz[[1, 0]])),
            (in1, v1, x * y[[0, 1], 0], c.diag(y[[0, 1], 0])),
            (in1, v1, x * y[[1, 0], 0], c.diag(y[[1, 0], 0])),
            (in1, v1, inner_prod(x, x), (2 * x).T),
            (in1, v1, inner_prod(x**2, x), (3 * x**2).T),
                #(in1,v1,c.det(horzcat([x,DMatrix([1,2])])),DMatrix([-1,2])), not implemented
            (in1, v1, f1.call(in1)[1], y),
            (in1, v1, f1.call([x**2, y])[1], y * 2 * vertcat([x.T, x.T])),
            (in1, v1, f2.call(in1)[0], DMatrix.zeros(0, 2)),
            (in1, v1, f2.call([x**2, y])[0], DMatrix.zeros(0, 2)),
            (in1, v1, f3.call(in1)[0], DMatrix.zeros(0, 2)),
            (in1, v1, f3.call([x**2, y])[0], DMatrix.zeros(0, 2)),
            (in1, v1, f4.call(in1)[0], DMatrix.zeros(0, 2)),
            (in1, v1, f4.call([x**2, y])[0], DMatrix.zeros(0, 2)),
                #(in1,v1,f1.call([x**2,[]])[1],DMatrix.zeros(2,2)),
                #(in1,v1,f1.call([[],y])[1],DMatrix.zeros(2,2)),
            (in1, v1, vertcat([x, DMatrix(0, 1)]), DMatrix.eye(2)),
            (in1, v1, (x**2).project(sparsify(DMatrix([0, 1])).sparsity()),
             blockcat([[MX(1, 1), MX(1, 1)], [MX(1, 1), 2 * x[1]]])),
            (in1, v1, c.inner_prod(x, y[:, 0]), y[:, 0].T),
            (in1, v1, x.nz[IMatrix([[1, 0]])].T * y.nz[IMatrix([[0, 2]])],
             blockcat([[MX(1, 1), y.nz[0]], [y.nz[2], MX(1, 1)]])),
            (in1, v1, x.nz[c.diag([1, 0])] * y.nz[c.diag([0, 2])],
             blockcat([[MX(1, 1), y.nz[0]], [MX(1, 1), MX(1, 1)],
                       [MX(1, 1), MX(1, 1)], [y.nz[2], MX(1, 1)]])),
        ]:
            print out
            fun = MXFunction("fun", inputs, [out, jac])
            funsx = fun.expand()
            funsx.init()

            for i, v in enumerate(values):
                fun.setInput(v, i)
                funsx.setInput(v, i)

            fun.evaluate()
            funsx.evaluate()
            self.checkarray(fun.getOutput(0), funsx.getOutput(0))
            self.checkarray(fun.getOutput(1), funsx.getOutput(1))

            self.check_codegen(fun)

            J_ = fun.getOutput(1)

            def vec(l):
                ret = []
                for i in l:
                    ret.extend(i)
                return ret

            storage2 = {}
            storage = {}

            vf_mx = None

            for f in [fun, fun.expand()]:
                f.init()
                d1 = f.derForward(ndir)
                d1.init()
                d2 = f.derReverse(ndir)
                d2.init()

                num_in = f.nIn()
                num_out = f.nOut()
                """# Fwd and Adjoint AD
        for i,v in enumerate(values):
          f.setInput(v,i)
          d.setInput(v,i)
        
        for d in range(ndir):
          f.setInput(DMatrix(inputs[0].sparsity(),random.random(inputs[0].nnz())),num_in+d*num_in + d)
          f.setAdjSeed(DMatrix(out.sparsity(),random.random(out.nnz())),num_in+d*num_in + 0)
          f.setFwdSeed(0,1,d)
          f.setAdjSeed(0,1,d)
          
        f.evaluate()
        for d in range(ndir):
          seed = array(f.getFwdSeed(0,d)).ravel()
          sens = array(f.getFwdSens(0,d)).ravel()
          self.checkarray(sens,mul(J_,seed),"Fwd %d %s" % (d,str(type(f))))

          seed = array(f.getAdjSeed(0,d)).ravel()
          sens = array(f.getAdjSens(0,d)).ravel()
          self.checkarray(sens,mul(J_.T,seed),"Adj %d" %d)
        """

                # evalThings
                for sym, Function in [(MX.sym, MXFunction),
                                      (SX.sym, SXFunction)]:
                    if isinstance(f, MXFunction) and Function is SXFunction:
                        continue
                    if isinstance(f, SXFunction) and Function is MXFunction:
                        continue

                    # dense
                    for spmod, spmod2 in itertools.product(spmods, repeat=2):
                        fseeds = [[
                            sym("f",
                                spmod(f.getInput(i)).sparsity())
                            for i in range(f.nIn())
                        ] for d in range(ndir)]
                        aseeds = [[
                            sym("a",
                                spmod2(f.getOutput(i)).sparsity())
                            for i in range(f.nOut())
                        ] for d in range(ndir)]
                        inputss = [
                            sym("i",
                                f.getInput(i).sparsity())
                            for i in range(f.nIn())
                        ]

                        with internalAPI():
                            res = f.call(inputss, True)
                            fwdsens = f.callForward(inputss, res, fseeds, True)
                            adjsens = f.callReverse(inputss, res, aseeds, True)

                        fseed = [
                            DMatrix(fseeds[d][0].sparsity(),
                                    random.random(fseeds[d][0].nnz()))
                            for d in range(ndir)
                        ]
                        aseed = [
                            DMatrix(aseeds[d][0].sparsity(),
                                    random.random(aseeds[d][0].nnz()))
                            for d in range(ndir)
                        ]
                        vf = Function(
                            "vf", inputss +
                            vec([fseeds[i] + aseeds[i] for i in range(ndir)]),
                            list(res) + vec([
                                list(fwdsens[i]) + list(adjsens[i])
                                for i in range(ndir)
                            ]))

                        for i, v in enumerate(values):
                            vf.setInput(v, i)
                        offset = len(inputss)

                        for d in range(ndir):
                            vf.setInput(fseed[d], offset + 0)
                            for i in range(len(values) - 1):
                                vf.setInput(0, offset + i + 1)

                            offset += len(inputss)

                            vf.setInput(aseed[d], offset + 0)
                            vf.setInput(0, offset + 1)
                            offset += 2

                        assert (offset == vf.nIn())

                        vf.evaluate()
                        self.check_codegen(vf)

                        offset = len(res)
                        for d in range(ndir):
                            seed = array(fseed[d].T).ravel()
                            sens = array(vf.getOutput(offset + 0).T).ravel()
                            offset += len(inputss)
                            self.checkarray(
                                sens, mul(J_, seed), "eval Fwd %d %s" %
                                (d, str(type(f)) + str(sym)))

                            seed = array(aseed[d].T).ravel()
                            sens = array(vf.getOutput(offset + 0).T).ravel()
                            offset += len(inputss)

                            self.checkarray(
                                sens, mul(J_.T, seed), "eval Adj %d %s" %
                                (d,
                                 str([
                                     vf.getOutput(i) for i in range(vf.nOut())
                                 ])))

                        assert (offset == vf.nOut())

                        # Complete random seeding
                        random.seed(1)
                        for i in range(vf.nIn()):
                            vf.setInput(
                                DMatrix(
                                    vf.getInput(i).sparsity(),
                                    random.random(vf.getInput(i).nnz())), i)

                        vf.evaluate()
                        self.check_codegen(vf)
                        storagekey = (spmod, spmod2)
                        if not (storagekey in storage):
                            storage[storagekey] = []
                        storage[storagekey].append(
                            [vf.getOutput(i) for i in range(vf.nOut())])

                        # Added to make sure that the same seeds are used for SX and MX
                        if Function is MXFunction:
                            vf_mx = vf

                    # Second order sensitivities
                    for sym2, Function2 in [(MX.sym, MXFunction),
                                            (SX.sym, SXFunction)]:

                        if isinstance(vf,
                                      MXFunction) and Function2 is SXFunction:
                            continue
                        if isinstance(vf,
                                      SXFunction) and Function2 is MXFunction:
                            continue

                        for spmod_2, spmod2_2 in itertools.product(spmods,
                                                                   repeat=2):
                            fseeds2 = [[
                                sym2("f",
                                     vf_mx.getInput(i).sparsity())
                                for i in range(vf.nIn())
                            ] for d in range(ndir)]
                            aseeds2 = [[
                                sym2("a",
                                     vf_mx.getOutput(i).sparsity())
                                for i in range(vf.nOut())
                            ] for d in range(ndir)]
                            inputss2 = [
                                sym2("i",
                                     vf_mx.getInput(i).sparsity())
                                for i in range(vf.nIn())
                            ]

                            with internalAPI():
                                res2 = vf.call(inputss2, True)
                                fwdsens2 = vf.callForward(
                                    inputss2, res2, fseeds2, True)
                                adjsens2 = vf.callReverse(
                                    inputss2, res2, aseeds2, True)

                            vf2 = Function2(
                                "vf2", inputss2 + vec([
                                    fseeds2[i] + aseeds2[i]
                                    for i in range(ndir)
                                ]),
                                list(res2) + vec([
                                    list(fwdsens2[i]) + list(adjsens2[i])
                                    for i in range(ndir)
                                ]))

                            random.seed(1)
                            for i in range(vf2.nIn()):
                                vf2.setInput(
                                    DMatrix(
                                        vf2.getInput(i).sparsity(),
                                        random.random(vf2.getInput(i).nnz())),
                                    i)

                            vf2.evaluate()
                            self.check_codegen(vf2)
                            storagekey = (spmod, spmod2)
                            if not (storagekey in storage2):
                                storage2[storagekey] = []
                            storage2[storagekey].append(
                                [vf2.getOutput(i) for i in range(vf2.nOut())])

            # Remainder of eval testing
            for store, order in [(storage, "first-order"),
                                 (storage2, "second-order")]:
                for stk, st in store.items():
                    for i in range(len(st) - 1):
                        for k, (a, b) in enumerate(zip(st[0], st[i + 1])):
                            if b.numel() == 0 and sparsify(a).nnz() == 0:
                                continue
                            if a.numel() == 0 and sparsify(b).nnz() == 0:
                                continue
                            self.checkarray(sparsify(a), sparsify(b),
                                            ("%s, output(%d)" % (order, k)) +
                                            str(vf2.getInput(0)))

            for f in [fun.expand(), fun]:
                #  jacobian()
                for mode in ["forward", "reverse"]:
                    f.setOption("ad_weight", 0 if mode == 'forward' else 1)
                    f.setOption("ad_weight_sp", 0 if mode == 'forward' else 1)
                    f.init()
                    Jf = f.jacobian(0, 0)
                    Jf.init()
                    for i, v in enumerate(values):
                        Jf.setInput(v, i)
                    Jf.evaluate()

                    self.check_codegen(Jf)
                    self.checkarray(Jf.getOutput(), J_)
                    self.checkarray(DMatrix.ones(Jf.getOutput().sparsity()),
                                    DMatrix.ones(J_.sparsity()),
                                    str(out) + str(mode))
                    self.checkarray(DMatrix.ones(f.jacSparsity()),
                                    DMatrix.ones(J_.sparsity()))

            # Scalarized
            if out.isempty(): continue
            s_i = out.sparsity().row()[0]
            s_j = out.sparsity().getCol()[0]
            s_k = s_i * out.size2() + s_j
            fun = MXFunction("fun", inputs, [out[s_i, s_j], jac[s_k, :].T])

            for i, v in enumerate(values):
                fun.setInput(v, i)

            fun.evaluate()
            J_ = fun.getOutput(1)

            for f in [fun, fun.expand()]:
                #  gradient()
                for mode in ["forward", "reverse"]:
                    f.setOption("ad_weight", 0 if mode == 'forward' else 1)
                    f.setOption("ad_weight_sp", 0 if mode == 'forward' else 1)
                    f.init()
                    Gf = f.gradient(0, 0)
                    Gf.init()
                    for i, v in enumerate(values):
                        Gf.setInput(v, i)
                    Gf.evaluate()
                    self.check_codegen(Gf)
                    self.checkarray(Gf.getOutput(),
                                    J_,
                                    failmessage=("mode: %s" % mode))
                    #self.checkarray(DMatrix(Gf.getOutput().sparsity(),1),DMatrix(J_.sparsity(),1),str(mode)+str(out)+str(type(fun)))

            H_ = None

            for f in [fun, fun.expand()]:
                #  hessian()
                for mode in ["forward", "reverse"]:
                    f.setOption("ad_weight", 0 if mode == 'forward' else 1)
                    f.setOption("ad_weight_sp", 0 if mode == 'forward' else 1)
                    f.init()
                    Hf = f.hessian(0, 0)
                    Hf.init()
                    for i, v in enumerate(values):
                        Hf.setInput(v, i)
                    Hf.evaluate()
                    self.check_codegen(Hf)
                    if H_ is None:
                        H_ = Hf.getOutput()
                    self.checkarray(Hf.getOutput(),
                                    H_,
                                    failmessage=("mode: %s" % mode))
Example #3
0
  def test_MX(self):

    x = MX.sym("x",2)
    y = MX.sym("y",2,2)
    
    f1 = MXFunction([x,y],[x+y[0,0],mul(y,x)])
    f1.init()
    
    f2 = MXFunction([x,y],[mul(MX.zeros(0,2),x)])
    f2.init()

    f3 = MXFunction([x,y],[MX.zeros(0,0),mul(y,x)])
    f3.init()
    
    f4 = MXFunction([x,y],[MX.zeros(0,2),mul(y,x)])
    f4.init()
    
    ndir = 2
    
    in1 = [x,y]
    v1 = [DMatrix([1.1,1.3]),DMatrix([[0.7,1.5],[2.1,0.9]])]
    
    w=x[:]
    w[1]*=2

    w2=x[:]
    w2[1]*=x[0]
    
    ww=x[:]
    ww[[0,1]]*=x

    wwf=x[:]
    wwf[[1,0]]*=x
    
    wwr=x[:]
    wwr[[0,0,1,1]]*=2
    
    yy=y[:,:]
    
    yy[:,0] = x

    yy2=y[:,:]
    
    yy2[:,0] = x**2
    
    yyy=y[:,:]
    
    yyy[[1,0],0] = x

    yyy2=y[:,:]
    
    yyy2[[1,0],0] = x**2
    

    def remove_first(x):
      ret = DMatrix(x)
      if ret.numel()>0:
        ret[0,0] = DMatrix.sparse(1,1)
        return ret
      else:
        return ret

    def remove_last(x):
      ret = DMatrix(x)
      if ret.size()>0:
        ret[ret.sparsity().row()[-1],ret.sparsity().getCol()[-1]] = DMatrix.sparse(1,1)
        return ret
      else:
        return x
      
    spmods = [lambda x: x , remove_first, remove_last]
    
    # TODO: sparse seeding
    
    for inputs,values,out, jac in [
          (in1,v1,x,DMatrix.eye(2)),
          (in1,v1,x.T,DMatrix.eye(2)),
          (in1,v1,x**2,2*c.diag(x)),
          (in1,v1,(x**2).attachAssert(True),2*c.diag(x)),
          (in1,v1,(x**2).T,2*c.diag(x)),
          (in1,v1,c.reshape(x,(1,2)),DMatrix.eye(2)),
          (in1,v1,c.reshape(x**2,(1,2)),2*c.diag(x)),
          (in1,v1,x+y.nz[0],DMatrix.eye(2)),
          (in1,v1,x+y[0,0],DMatrix.eye(2)),
          (in1,v1,x+x,2*DMatrix.eye(2)),
          (in1,v1,x**2+x,2*c.diag(x)+DMatrix.eye(2)),
          (in1,v1,x*x,2*c.diag(x)),
          (in1,v1,x*y.nz[0],DMatrix.eye(2)*y.nz[0]),
          (in1,v1,x*y[0,0],DMatrix.eye(2)*y[0,0]),
          (in1,v1,x[0],DMatrix.eye(2)[0,:]),
          (in1,v1,(x**2)[0],horzcat([2*x[0],MX.sparse(1,1)])),
          (in1,v1,x[0]+x[1],DMatrix.ones(1,2)),
          (in1,v1,vertcat([x[1],x[0]]),sparse(DMatrix([[0,1],[1,0]]))),
          (in1,v1,vertsplit(x,[0,1,2])[1],sparse(DMatrix([[0,1]]))),
          (in1,v1,vertcat([x[1]**2,x[0]**2]),blockcat([[MX.sparse(1,1),2*x[1]],[2*x[0],MX.sparse(1,1)]])),
          (in1,v1,vertsplit(x**2,[0,1,2])[1],blockcat([[MX.sparse(1,1),2*x[1]]])),
          (in1,v1,vertsplit(x**2,[0,1,2])[1]**3,blockcat([[MX.sparse(1,1),6*x[1]**5]])),
          (in1,v1,horzcat([x[1],x[0]]).T,sparse(DMatrix([[0,1],[1,0]]))),
          (in1,v1,horzcat([x[1]**2,x[0]**2]).T,blockcat([[MX.sparse(1,1),2*x[1]],[2*x[0],MX.sparse(1,1)]])),
          (in1,v1,diagcat([x[1]**2,y,x[0]**2]),
            blockcat(  [[MX.sparse(1,1),2*x[1]]] + ([[MX.sparse(1,1),MX.sparse(1,1)]]*14)  + [[2*x[0],MX.sparse(1,1)]] )
          ),
          (in1,v1,horzcat([x[1]**2,x[0]**2]).T,blockcat([[MX.sparse(1,1),2*x[1]],[2*x[0],MX.sparse(1,1)]])),
          (in1,v1,x[[0,1]],sparse(DMatrix([[1,0],[0,1]]))),
          (in1,v1,(x**2)[[0,1]],2*c.diag(x)),
          (in1,v1,x[[0,0,1,1]],sparse(DMatrix([[1,0],[1,0],[0,1],[0,1]]))),
          (in1,v1,(x**2)[[0,0,1,1]],blockcat([[2*x[0],MX.sparse(1,1)],[2*x[0],MX.sparse(1,1)],[MX.sparse(1,1),2*x[1]],[MX.sparse(1,1),2*x[1]]])),
          (in1,v1,wwr,sparse(DMatrix([[2,0],[0,2]]))),
          (in1,v1,x[[1,0]],sparse(DMatrix([[0,1],[1,0]]))), 
          (in1,v1,x[[1,0],0],sparse(DMatrix([[0,1],[1,0]]))),
          (in1,v1,w,sparse(DMatrix([[1,0],[0,2]]))),
          (in1,v1,w2,blockcat([[1,MX.sparse(1,1)],[x[1],x[0]]])),
          (in1,v1,ww,2*c.diag(x)),
          (in1,v1,wwf,vertcat([x[[1,0]].T,x[[1,0]].T])),
          (in1,v1,yy[:,0],DMatrix.eye(2)),
          (in1,v1,yy2[:,0],2*c.diag(x)),
          (in1,v1,yyy[:,0],sparse(DMatrix([[0,1],[1,0]]))),
          (in1,v1,mul(y,x),y),
          (in1,v1,mul(x.T,y.T),y),
          (in1,v1,mul(y,x,DMatrix.zeros(Sparsity.triplet(2,1,[1],[0]))),y[Sparsity.triplet(2,2,[1,1],[0,1])]),
          (in1,v1,mul(x.T,y.T,DMatrix.zeros(Sparsity.triplet(2,1,[1],[0]).T)),y[Sparsity.triplet(2,2,[1,1],[0,1])]),
          (in1,v1,mul(y[Sparsity.triplet(2,2,[0,1,1],[0,0,1])],x),y[Sparsity.triplet(2,2,[0,1,1],[0,0,1])]),
          (in1,v1,mul(x.T,y[Sparsity.triplet(2,2,[0,1,1],[0,0,1])].T),y[Sparsity.triplet(2,2,[0,1,1],[0,0,1])]),
          (in1,v1,mul(y,x**2),y*2*vertcat([x.T,x.T])),
          (in1,v1,sin(x),c.diag(cos(x))),
          (in1,v1,sin(x**2),c.diag(cos(x**2)*2*x)),
          (in1,v1,x*y[:,0],c.diag(y[:,0])),
          (in1,v1,x*y.nz[[0,1]],c.diag(y.nz[[0,1]])),
          (in1,v1,x*y.nz[[1,0]],c.diag(y.nz[[1,0]])),
          (in1,v1,x*y[[0,1],0],c.diag(y[[0,1],0])),
          (in1,v1,x*y[[1,0],0],c.diag(y[[1,0],0])),
          (in1,v1,inner_prod(x,x),(2*x).T),
          (in1,v1,inner_prod(x**2,x),(3*x**2).T),
          #(in1,v1,c.det(horzcat([x,DMatrix([1,2])])),DMatrix([-1,2])), not implemented
          (in1,v1,f1.call(in1)[1],y),
          (in1,v1,f1.call([x**2,y])[1],y*2*vertcat([x.T,x.T])),
          (in1,v1,f2.call(in1)[0],DMatrix.zeros(0,2)),
          (in1,v1,f2.call([x**2,y])[0],DMatrix.zeros(0,2)),
          (in1,v1,f3.call(in1)[0],DMatrix.zeros(0,2)),
          (in1,v1,f3.call([x**2,y])[0],DMatrix.zeros(0,2)),
          (in1,v1,f4.call(in1)[0],DMatrix.zeros(0,2)),
          (in1,v1,f4.call([x**2,y])[0],DMatrix.zeros(0,2)),
          #(in1,v1,f1.call([x**2,[]])[1],DMatrix.zeros(2,2)),
          #(in1,v1,f1.call([[],y])[1],DMatrix.zeros(2,2)),
          (in1,v1,vertcat([x,DMatrix.sparse(0,1)]),DMatrix.eye(2)),
          (in1,v1,(x**2).setSparse(sparse(DMatrix([0,1])).sparsity()),blockcat([[MX.sparse(1,1),MX.sparse(1,1)],[MX.sparse(1,1),2*x[1]]])),
          (in1,v1,c.inner_prod(x,y[:,0]),y[:,0].T),
          (in1,v1,x.nz[IMatrix([[1,0]])]*y.nz[IMatrix([[0,2]])],blockcat([[MX.sparse(1,1),y.nz[0]],[y.nz[2],MX.sparse(1,1)]])),
          (in1,v1,x.nz[c.diag([1,0])]*y.nz[c.diag([0,2])],blockcat([[MX.sparse(1,1),y.nz[0]],[MX.sparse(1,1),MX.sparse(1,1)],[MX.sparse(1,1),MX.sparse(1,1)],[y.nz[2],MX.sparse(1,1)]])),
     ]:
      print out
      fun = MXFunction(inputs,[out,jac])
      fun.init()
      
      funsx = fun.expand()
      funsx.init()
      
      for i,v in enumerate(values):
        fun.setInput(v,i)
        funsx.setInput(v,i)
        
      fun.evaluate()
      funsx.evaluate()
      self.checkarray(fun.getOutput(0),funsx.getOutput(0))
      self.checkarray(fun.getOutput(1),funsx.getOutput(1))
      
      J_ = fun.getOutput(1)
      
      def vec(l):
        ret = []
        for i in l:
          ret.extend(i)
        return ret

      storage2 = {}
      storage = {}
      
      vf_mx = None
              
      for f in [fun,fun.expand()]:
        f.init()
        d = f.derivative(ndir,ndir)
        d.init()
        
        num_in = f.getNumInputs()
        num_out = f.getNumOutputs()

        """# Fwd and Adjoint AD
        for i,v in enumerate(values):
          f.setInput(v,i)
          d.setInput(v,i)
        
        for d in range(ndir):
          f.setInput(DMatrix(inputs[0].sparsity(),random.random(inputs[0].size())),num_in+d*num_in + d)
          f.setAdjSeed(DMatrix(out.sparsity(),random.random(out.size())),num_in+d*num_in + 0)
          f.setFwdSeed(0,1,d)
          f.setAdjSeed(0,1,d)
          
        f.evaluate()
        for d in range(ndir):
          seed = array(f.getFwdSeed(0,d)).ravel()
          sens = array(f.getFwdSens(0,d)).ravel()
          self.checkarray(sens,mul(J_,seed),"Fwd %d %s" % (d,str(type(f))))

          seed = array(f.getAdjSeed(0,d)).ravel()
          sens = array(f.getAdjSens(0,d)).ravel()
          self.checkarray(sens,mul(J_.T,seed),"Adj %d" %d)
        """
        
        # evalThings
        for sym, Function in [(MX.sym,MXFunction),(SX.sym,SXFunction)]:
          if isinstance(f, MXFunction) and Function is SXFunction: continue
          if isinstance(f, SXFunction) and Function is MXFunction: continue
          
          

          # dense
          for spmod,spmod2 in itertools.product(spmods,repeat=2):
            fseeds = [[sym("f",spmod(f.getInput(i)).sparsity()) for i in range(f.getNumInputs())]  for d in range(ndir)]
            aseeds = [[sym("a",spmod2(f.getOutput(i)).sparsity())  for i in range(f.getNumOutputs())] for d in range(ndir)]
            inputss = [sym("i",f.input(i).sparsity()) for i in range(f.getNumInputs())]
        
            with internalAPI():
              res,fwdsens,adjsens = f.callDerivative(inputss,fseeds,aseeds,True)
            
            fseed = [DMatrix(fseeds[d][0].sparsity(),random.random(fseeds[d][0].size())) for d in range(ndir) ]
            aseed = [DMatrix(aseeds[d][0].sparsity(),random.random(aseeds[d][0].size())) for d in range(ndir) ]
            vf = Function(inputss+vec([fseeds[i]+aseeds[i] for i in range(ndir)]),list(res) + vec([list(fwdsens[i])+list(adjsens[i]) for i in range(ndir)]))
            
            vf.init()
            
            for i,v in enumerate(values):
              vf.setInput(v,i)
            offset = len(inputss)
              
            for d in range(ndir):
              vf.setInput(fseed[d],offset+0)
              for i in range(len(values)-1):
                vf.setInput(0,offset+i+1)
                
              offset += len(inputss)

              vf.setInput(aseed[d],offset+0)
              vf.setInput(0,offset+1)
              offset+=2
              
            assert(offset==vf.getNumInputs())
            
            vf.evaluate()
              
            offset = len(res)
            for d in range(ndir):
              seed = array(fseed[d]).ravel()
              sens = array(vf.getOutput(offset+0)).ravel()
              offset+=len(inputss)
              self.checkarray(sens,mul(J_,seed),"eval Fwd %d %s" % (d,str(type(f))+str(sym)))

              seed = array(aseed[d]).ravel()
              sens = array(vf.getOutput(offset+0)).ravel()
              offset+=len(inputss)
              
              self.checkarray(sens,mul(J_.T,seed),"eval Adj %d %s" % (d,str([vf.getOutput(i) for i in range(vf.getNumOutputs())])))
          
          
            assert(offset==vf.getNumOutputs())
          
            # Complete random seeding
            random.seed(1)
            for i in range(vf.getNumInputs()):
              vf.setInput(DMatrix(vf.input(i).sparsity(),random.random(vf.input(i).size())),i)
            
            vf.evaluate()
            storagekey = (spmod,spmod2)
            if not(storagekey in storage):
              storage[storagekey] = []
            storage[storagekey].append([vf.getOutput(i) for i in range(vf.getNumOutputs())])
            
            # Added to make sure that the same seeds are used for SX and MX
            if Function is MXFunction:
              vf_mx = vf

          # Second order sensitivities
          for sym2, Function2 in [(MX.sym,MXFunction),(SX.sym,SXFunction)]:
          
            if isinstance(vf, MXFunction) and Function2 is SXFunction: continue
            if isinstance(vf, SXFunction) and Function2 is MXFunction: continue
            

            for spmod_2,spmod2_2 in itertools.product(spmods,repeat=2):
              fseeds2 = [[sym2("f",vf_mx.input(i).sparsity()) for i in range(vf.getNumInputs())] for d in range(ndir)]
              aseeds2 = [[sym2("a",vf_mx.output(i).sparsity())  for i in range(vf.getNumOutputs()) ] for d in range(ndir)]
              inputss2 = [sym2("i",vf_mx.input(i).sparsity()) for i in range(vf.getNumInputs())]
           
              with internalAPI():
                res2,fwdsens2,adjsens2 = vf.callDerivative(inputss2,fseeds2,aseeds2,True)

              vf2 = Function2(inputss2+vec([fseeds2[i]+aseeds2[i] for i in range(ndir)]),list(res2) + vec([list(fwdsens2[i])+list(adjsens2[i]) for i in range(ndir)]))
              vf2.init()
                
              random.seed(1)
              for i in range(vf2.getNumInputs()):
                vf2.setInput(DMatrix(vf2.input(i).sparsity(),random.random(vf2.input(i).size())),i)
              
              vf2.evaluate()
              storagekey = (spmod,spmod2)
              if not(storagekey in storage2):
                storage2[storagekey] = []
              storage2[storagekey].append([vf2.getOutput(i) for i in range(vf2.getNumOutputs())])

      # Remainder of eval testing
      for store,order in [(storage,"first-order"),(storage2,"second-order")]:
        for stk,st in store.items():
          for i in range(len(st)-1):
            for k,(a,b) in enumerate(zip(st[0],st[i+1])):
              if b.numel()==0 and sparse(a).size()==0: continue
              if a.numel()==0 and sparse(b).size()==0: continue
              self.checkarray(sparse(a),sparse(b),("%s, output(%d)" % (order,k))+str(vf2.getInput(0)))
              
      for f in [fun.expand(),fun]:
        #  jacobian()
        for mode in ["forward","reverse"]:
          f.setOption("ad_mode",mode)
          f.init()
          Jf=f.jacobian(0,0)
          Jf.init()
          for i,v in enumerate(values):
            Jf.setInput(v,i)
          Jf.evaluate()
          self.checkarray(Jf.getOutput(),J_)
          self.checkarray(DMatrix(Jf.output().sparsity(),1),DMatrix(J_.sparsity(),1),str(out)+str(mode))
          self.checkarray(DMatrix(f.jacSparsity(),1),DMatrix(J_.sparsity(),1))
                
      # Scalarized
      if out.isEmpty(): continue
      s_i  = out.sparsity().row()[0]
      s_j  = out.sparsity().getCol()[0]
      s_k = s_i*out.size2()+s_j
      fun = MXFunction(inputs,[out[s_i,s_j],jac[s_k,:].T])
      fun.init()
        
      for i,v in enumerate(values):
        fun.setInput(v,i)
        
        
      fun.evaluate()
      J_ = fun.getOutput(1)
      
      for f in [fun,fun.expand()]:
        #  gradient()
        for mode in ["forward","reverse"]:
          f.setOption("ad_mode",mode)
          f.init()
          Gf=f.gradient(0,0)
          Gf.init()
          for i,v in enumerate(values):
            Gf.setInput(v,i)
          Gf.evaluate()
          self.checkarray(Gf.getOutput(),J_,failmessage=("mode: %s" % mode))
          #self.checkarray(DMatrix(Gf.output().sparsity(),1),DMatrix(J_.sparsity(),1),str(mode)+str(out)+str(type(fun)))

      H_ = None
      
      for f in [fun,fun.expand()]:
        #  hessian()
        for mode in ["forward","reverse"]:
          f.setOption("ad_mode",mode)
          f.init()
          Hf=f.hessian(0,0)
          Hf.init()
          for i,v in enumerate(values):
            Hf.setInput(v,i)
          Hf.evaluate()
          if H_ is None:
            H_ = Hf.getOutput()
          self.checkarray(Hf.getOutput(),H_,failmessage=("mode: %s" % mode))