コード例 #1
0
SparseMatrix BSplineBasis1D::refineKnotsLocally(double x)
{
    if (!insideSupport(x))
        throw Exception("BSplineBasis1D::refineKnotsLocally: Cannot refine outside support!");

    if (getNumBasisFunctions() >= getNumBasisFunctionsTarget()
            || assertNear(knots.front(), knots.back()))
    {
        unsigned int n = getNumBasisFunctions();
        DenseMatrix A = DenseMatrix::Identity(n,n);
        return A.sparseView();
    }

    // Refined knot vector
    std::vector<double> refinedKnots = knots;

    auto upper = std::lower_bound(refinedKnots.begin(), refinedKnots.end(), x);

    // Check left boundary
    if (upper == refinedKnots.begin())
        std::advance(upper, degree+1);

    // Get previous iterator
    auto lower = std::prev(upper);

    // Do not insert if upper and lower bounding knot are close
    if (assertNear(*upper, *lower))
    {
        unsigned int n = getNumBasisFunctions();
        DenseMatrix A = DenseMatrix::Identity(n,n);
        return A.sparseView();
    }

    // Insert knot at x
    double insertVal = x;

    // Adjust x if it is on or close to a knot
    if (knotMultiplicity(x) > 0
            || assertNear(*upper, x, 1e-6, 1e-6)
            || assertNear(*lower, x, 1e-6, 1e-6))
    {
        insertVal = (*upper + *lower)/2.0;
    }

    // Insert new knot
    refinedKnots.insert(upper, insertVal);

    if (!isKnotVectorRegular(refinedKnots) || !isRefinement(refinedKnots))
        throw Exception("BSplineBasis1D::refineKnotsLocally: New knot vector is not a proper refinement!");

    // Build knot insertion matrix
    SparseMatrix A = buildKnotInsertionMatrix(refinedKnots);

    // Update knots
    knots = refinedKnots;

    return A;
}
コード例 #2
0
SparseVector BSplineBasis1D::evaluateDerivative(double x, int r) const
{
    // Evaluate rth derivative of basis functions at x
    // Returns vector [D^(r)B_(u-p,p)(x) ... D^(r)B_(u,p)(x)]
    // where u is the knot index and p is the degree
    int p = degree;

    // Continuity requirement
    //assert(p > r);
    if (p <= r)
    {
        // Return zero-gradient
        SparseVector DB(getNumBasisFunctions());
        return DB;
    }

    // Check for knot multiplicity here!

    supportHack(x);

    int knotIndex = indexHalfopenInterval(x);

    // Algorithm 3.18 from Lyche and Moerken (2011)
    SparseMatrix B(1,1);
    B.insert(0,0) = 1;

    for (int i = 1; i <= p-r; i++)
    {
        SparseMatrix R = buildBasisMatrix(x, knotIndex, i);
        B = B*R;
    }

    for (int i = p-r+1; i <= p; i++)
    {
        SparseMatrix DR = buildBasisMatrix(x, knotIndex, i, true);
        B = B*DR;
    }
    double factorial = std::tgamma(p+1)/std::tgamma(p-r+1);
    B = B*factorial;

    assert(B.cols() == p+1);

    // From row vector to extended column vector
    SparseVector DB(getNumBasisFunctions());
    DB.reserve(p+1);
    int i = knotIndex-p; // First insertion index
    for (int k = 0; k < B.outerSize(); ++k)
    for (SparseMatrix::InnerIterator it(B,k); it; ++it)
    {
        DB.insert(i+it.col()) = it.value();
    }

    return DB;
}
コード例 #3
0
ファイル: bsplinebasis.cpp プロジェクト: pmukherj/splinter
// Old implementation of Jacobian
DenseMatrix BSplineBasis::evalBasisJacobianOld(DenseVector &x) const
{
    // Jacobian basis matrix
    DenseMatrix J; J.setZero(getNumBasisFunctions(), numVariables);

    // Calculate partial derivatives
    for (unsigned int i = 0; i < numVariables; i++)
    {
        // One column in basis jacobian
        DenseVector bi; bi.setOnes(1);
        for (unsigned int j = 0; j < numVariables; j++)
        {
            DenseVector temp = bi;
            DenseVector xi;
            if (j == i)
            {
                // Differentiated basis
                xi = bases.at(j).evaluateFirstDerivative(x(j));
            }
            else
            {
                // Normal basis
                xi = bases.at(j).evaluate(x(j));
            }

            bi = kroneckerProduct(temp, xi);
        }

        // Fill out column
        J.block(0,i,bi.rows(),1) = bi.block(0,0,bi.rows(),1);
    }

    return J;
}
コード例 #4
0
SparseVector BSplineBasis1D::evaluate(double x) const
{
    SparseVector basisvalues(getNumBasisFunctions());

    supportHack(x);

    std::vector<int> indexSupported = indexSupportedBasisfunctions(x);

    basisvalues.reserve(indexSupported.size());

    // Iterate through the nonzero basisfunctions and store functionvalues
    for (auto it = indexSupported.begin(); it != indexSupported.end(); ++it)
    {
        basisvalues.insert(*it) = deBoorCox(x, *it, degree);
    }

    // Alternative evaluation using basis matrix
//    int knotIndex = indexHalfopenInterval(x); // knot index

//    SparseMatrix basisvalues2 = buildBsplineMatrix(x, knotIndex, 1);
//    for (int i = 2; i <= basisDegree; i++)
//    {
//        SparseMatrix Ri = buildBsplineMatrix(x, knotIndex, i);
//        basisvalues2 = basisvalues2*Ri;
//    }
//    basisvalues2.makeCompressed();

//    assert(basisvalues2.rows() == 1);
//    assert(basisvalues2.cols() == basisDegree + 1);

    return basisvalues;
}
コード例 #5
0
// Old implementation of first derivative of basis functions
SparseVector BSplineBasis1D::evaluateFirstDerivative(double x) const
{
    SparseVector values(getNumBasisFunctions());

    supportHack(x);

    std::vector<int> supportedBasisFunctions = indexSupportedBasisfunctions(x);

    for (int i : supportedBasisFunctions)
    {
        // Differentiate basis function
        // Equation 3.35 in Lyche & Moerken (2011)
        double b1 = deBoorCox(x, i, degree-1);
        double b2 = deBoorCox(x, i+1, degree-1);

        double t11 = knots.at(i);
        double t12 = knots.at(i+degree);
        double t21 = knots.at(i+1);
        double t22 = knots.at(i+degree+1);

        (t12 == t11) ? b1 = 0 : b1 = b1/(t12-t11);
        (t22 == t21) ? b2 = 0 : b2 = b2/(t22-t21);

        values.insert(i) = degree*(b1 - b2);
    }

    return values;
}
コード例 #6
0
ファイル: bspline.cpp プロジェクト: LStoleriu/splinter
void BSpline::setCoefficients(const DenseVector &coefficients)
{
    if (coefficients.size() != getNumBasisFunctions())
        throw Exception("BSpline::setControlPoints: Incompatible size of coefficient vector.");

    this->coefficients = coefficients;
    checkControlPoints();
}
コード例 #7
0
ファイル: bsplinebasis.cpp プロジェクト: pmukherj/splinter
// NOTE: does not pass tests
SparseMatrix BSplineBasis::evalBasisJacobian(DenseVector &x) const
{
    // Jacobian basis matrix
    SparseMatrix J(getNumBasisFunctions(), numVariables);
    //J.setZero(numBasisFunctions(), numInputs);

    // Calculate partial derivatives
    for (unsigned int i = 0; i < numVariables; ++i)
    {
        // One column in basis jacobian
        std::vector<SparseVector> values(numVariables);

        for (unsigned int j = 0; j < numVariables; ++j)
        {
            if (j == i)
            {
                // Differentiated basis
                values.at(j) = bases.at(j).evaluateDerivative(x(j),1);
            }
            else
            {
                // Normal basis
                values.at(j) = bases.at(j).evaluate(x(j));
            }
        }

        SparseVector Ji = kroneckerProductVectors(values);

        // Fill out column
        for (int k = 0; k < Ji.outerSize(); ++k)
        for (SparseMatrix::InnerIterator it(Ji,k); it; ++it)
        {
            if (it.value() != 0)
                J.insert(it.row(),i) = it.value();
        }
        //J.block(0,i,Ji.rows(),1) = bi.block(0,0,Ji.rows(),1);
    }

    J.makeCompressed();

    return J;
}
コード例 #8
0
ファイル: bsplinebasis.cpp プロジェクト: pmukherj/splinter
SparseMatrix BSplineBasis::evalBasisJacobian2(DenseVector &x) const
{
    // Jacobian basis matrix
    SparseMatrix J(getNumBasisFunctions(), numVariables);

    // Evaluate B-spline basis functions before looping
    std::vector<SparseVector> funcValues(numVariables);
    std::vector<SparseVector> gradValues(numVariables);

    for (unsigned int i = 0; i < numVariables; ++i)
    {
        funcValues[i] = bases.at(i).evaluate(x(i));
        gradValues[i] = bases.at(i).evaluateFirstDerivative(x(i));
    }

    // Calculate partial derivatives
    for (unsigned int i = 0; i < numVariables; i++)
    {
        std::vector<SparseVector> values(numVariables);

        for (unsigned int j = 0; j < numVariables; j++)
        {
            if (j == i)
                values.at(j) = gradValues.at(j); // Differentiated basis
            else
                values.at(j) = funcValues.at(j); // Normal basis
        }

        SparseVector Ji = kroneckerProductVectors(values);

        // Fill out column
        for (SparseVector::InnerIterator it(Ji); it; ++it)
            J.insert(it.row(),i) = it.value();
    }

    return J;
}
コード例 #9
0
ファイル: bsplinebasis.cpp プロジェクト: pmukherj/splinter
SparseMatrix BSplineBasis::evalBasisHessian(DenseVector &x) const
{
    // Hessian basis matrix
    /* Hij = B1 x ... x DBi x ... x DBj x ... x Bn
     * (Hii = B1 x ... x DDBi x ... x Bn)
     * Where B are basis functions evaluated at x,
     * DB are the derivative of the basis functions,
     * and x is the kronecker product.
     * Hij is in R^(numBasisFunctions x 1)
     * so that basis hessian H is in R^(numBasisFunctions*numInputs x numInputs)
     * The real B-spline Hessian is calculated as (c^T x 1^(numInputs x 1))*H
     */
    SparseMatrix H(getNumBasisFunctions()*numVariables, numVariables);
    //H.setZero(numBasisFunctions()*numInputs, numInputs);

    // Calculate partial derivatives
    // Utilizing that Hessian is symmetric
    // Filling out lower left triangular
    for (unsigned int i = 0; i < numVariables; i++) // row
    {
        for (unsigned int j = 0; j <= i; j++) // col
        {
            // One column in basis jacobian
            SparseMatrix Hi(1,1);
            Hi.insert(0,0) = 1;

            for (unsigned int k = 0; k < numVariables; k++)
            {
                SparseMatrix temp = Hi;
                SparseMatrix Bk;
                if (i == j && k == i)
                {
                    // Diagonal element
                    Bk = bases.at(k).evaluateDerivative(x(k),2);
                }
                else if (k == i || k == j)
                {
                    Bk = bases.at(k).evaluateDerivative(x(k),1);
                }
                else
                {
                    Bk = bases.at(k).evaluate(x(k));
                }
                Hi = kroneckerProduct(temp, Bk);
            }

            // Fill out column
            for (int k = 0; k < Hi.outerSize(); ++k)
            for (SparseMatrix::InnerIterator it(Hi,k); it; ++it)
            {
                if (it.value() != 0)
                {
                    int row = i*getNumBasisFunctions()+it.row();
                    int col = j;
                    H.insert(row,col) = it.value();
                }
            }
        }
    }

    H.makeCompressed();

    return H;
}