///[W, F, errors, times, iters] = NMFSparseKL(V, W0, F0, maxIter, tolerence)
void mexFunction(int nlhs, mxArray *outs[], int nrhs, const mxArray *inps[])
{
    srand (9999);
    int nz, m, n, k, d1, d2;
    unsigned long *x, *ind;
    double *values, **W, **F, **Wr, **Fr;
    get(inps[0], nz, n, m, x, ind, values);
    //mexPrintf(" m = %d, n = %d\n", m, n);
    vector<map<int, double>> V, VT;
    vector<vector<pair<int, double> > > VV, VVT;
    
    convert(nz, m, n, x, ind, values, V);
    transpose(nz, m, n, x, ind, values, VT);
    map_vector(V, VV);
    map_vector(VT, VVT);
    
    getArray(inps[1], m, k, W);
    getArray(inps[2], n, k, F);
    int maxIter = (int) getDouble(inps[3]);
    double tolerance = getDouble(inps[4]);
    int maxThread = (int) getDouble(inps[5]);
    double **params;
    getArray(inps[6], d1, d2, params);
    vector<double> errors, times, iters;
    printfFnc(" m = %d, n = %d, k = %d\n", m, n, k);
    printfFnc(" %f %f %f %f\n", (*params)[0], (*params)[1], (*params)[2], (*params)[3]);
    
    /// Output arguments
	outs[0] = mxCreateDoubleMatrix(m, k, mxREAL);
    outs[1] = mxCreateDoubleMatrix(n, k, mxREAL);
    outs[2] = mxCreateDoubleMatrix(1, maxIter, mxREAL);
    double* derrors =  mxGetPr(outs[2]);
    outs[3] = mxCreateDoubleMatrix(1, maxIter, mxREAL);
    double* dtimes =  mxGetPr(outs[3]);
    outs[4] = mxCreateDoubleMatrix(1, maxIter, mxREAL);
    double* diters =  mxGetPr(outs[4]);
   
    getArray(outs[0], m, k, Wr);
    getArray(outs[1], n, k, Fr);
    
    MultipleIterativeAlgorithmPar(VV, VVT, W, F, Wr, Fr, m, n, k, maxIter, 
            tolerance, errors, times, iters, maxThread, *params);
    
    For(i, maxIter)
        derrors[i] = errors[i], dtimes[i] = times[i], diters[i] = iters[i];
}
void CRationalApproximationCGMJob::compute()
{
    SG_DEBUG("Entering\n");

    REQUIRE(m_aggregator, "Job result aggregator is not set!\n");
    REQUIRE(m_operator, "Operator is not set!\n");
    REQUIRE(m_vector.vector, "Vector is not set!\n");
    REQUIRE(m_shifts.vector, "Shifts are not set!\n");
    REQUIRE(m_weights.vector, "Weights are not set!\n");
    REQUIRE(m_operator->get_dimension()==m_vector.vlen,
            "Dimension mismatch! %d vs %d\n", m_operator->get_dimension(), m_vector.vlen);
    REQUIRE(m_shifts.vlen==m_weights.vlen,
            "Number of shifts and weights are not equal!\n");

    // solve the linear system with the sample vector
    SGVector<complex128_t> vec=m_linear_solver->solve_shifted_weighted(
                                   m_operator, m_vector, m_shifts, m_weights);

    // Take negative (see CRationalApproximation for the formula)
    Map<VectorXcd> v(vec.vector, vec.vlen);
    v=-v;

    // take out the imaginary part of the result before
    // applying linear operator
    SGVector<float64_t> agg=m_operator->apply(vec.get_imag());

    // perform dot product
    Map<VectorXd> map_agg(agg.vector, agg.vlen);
    Map<VectorXd> map_vector(m_vector.vector, m_vector.vlen);
    float64_t result=map_vector.dot(map_agg);

    result*=m_const_multiplier;

    // form the final result into a scalar result and submit to the aggregator
    CScalarResult<float64_t>* final_result=new CScalarResult<float64_t>(result);
    SG_REF(final_result);

    m_aggregator->submit_result(final_result);

    SG_UNREF(final_result);

    SG_DEBUG("Leaving\n");
}
Beispiel #3
0
void pclbo::LBOEstimation<PointT, NormalT>::compute() {

    typename pcl::KdTreeFLANN<PointT>::Ptr kdt(new pcl::KdTreeFLANN<PointT>());
    kdt->setInputCloud(_cloud);

    const double avg_dist = pclbo::avg_distance<PointT>(10, _cloud, kdt);
    const double h = 5 * avg_dist;

    std::cout << "Average distance between points: " << avg_dist << std::endl;

    int points_with_mass = 0;
    double avg_mass = 0.0;
    B.resize(_cloud->size());

    std::cout << "Computing the Mass matrix..." << std::flush;

    // Compute the mass matrix diagonal B
    for (int i = 0; i < _cloud->size(); i++) {
        const auto& point = _cloud->at(i);
        const auto& normal = _normals->at(i);

        const auto& normal_vector = normal.getNormalVector3fMap().template cast<double>();

        if (!pcl::isFinite(point)) continue;

        std::vector<int> indices;
        std::vector<float> distances;
        kdt->radiusSearch(point, h, indices, distances);

        if (indices.size() < 4) {
            B[i] = 0.0;
            continue;
        }

        // Project the neighbor points in the tangent plane at p_i with normal n_i
        std::vector<Eigen::Vector3d> projected_points;
        for (const auto& neighbor_index : indices) {
            if (neighbor_index != i) {
                const auto& neighbor_point = _cloud->at(neighbor_index);
                projected_points.push_back(project(point, normal, neighbor_point));
            }
        }

        assert(projected_points.size() >= 3);

        // Use the first vector to create a 2D basis
        Eigen::Vector3d u = projected_points[0];
        u.normalize();
        Eigen::Vector3d v = (u.cross(normal_vector));
        v.normalize();

        // Add the points to a 2D plane
        std::vector<Eigen::Vector2d> plane;

        // Add the point at the center
        plane.push_back(Eigen::Vector2d::Zero());

        // Add the rest of the points
        for (const auto& projected : projected_points) {

            double x = projected.dot(u);
            double y = projected.dot(v);

            // Add the 2D point to the vector
            plane.push_back(Eigen::Vector2d(x, y));
        }

        assert(plane.size() >= 4);

        // Compute the voronoi cell area of the point
        double area = VoronoiDiagram::area(plane);
        B[i] = area;
        avg_mass += area;
        points_with_mass++;
    }

    // Average mass
    if (points_with_mass > 0) {
        avg_mass /= static_cast<double>(points_with_mass);
    }

    // Set border points to have average mass
    for (auto& b : B) {
        if (b == 0.0) {
            b = avg_mass; 
        } 
    }

    std::cout << "done" << std::endl;
    std::cout << "Computing the stiffness matrix..." << std::flush;

    std::vector<double> diag(_cloud->size(), 0.0);

    // Compute the stiffness matrix Q
    for (int i = 0; i < _cloud->size(); i++) {
        const auto& point = _cloud->at(i);

        if (!pcl::isFinite(point)) continue;

        std::vector<int> indices;
        std::vector<float> distances;
        kdt->radiusSearch(point, h, indices, distances);

        for (const auto& j : indices) {
            if (j != i) {
                const auto& neighbor = _cloud->at(j);

                double d = (neighbor.getVector3fMap() - point.getVector3fMap()).norm();
                double w = B[i] * B[j] * (1.0 / (4.0 * M_PI * h * h)) * exp(-(d * d) / (4.0 * h));

                I.push_back(i);
                J.push_back(j);
                S.push_back(w);

                diag[i] += w;
            }
        }
    }

    // Fill the diagonal as the negative sum of the rows
    for (int i = 0; i < diag.size(); i++) {
        I.push_back(i);
        J.push_back(i);
        S.push_back(-diag[i]);
    }

    // Compute the B^{-1}Q matrix
    Eigen::MatrixXd Q = Eigen::MatrixXd::Zero(_cloud->size(), _cloud->size());
    for (int i = 0; i < I.size(); i++) {
        const int row = I[i];
        const int col = J[i];
        Q(row, col) = S[i];
    }

    std::cout << "done" << std::endl;
    std::cout << "Computing eigenvectors" << std::endl;

    Eigen::Map<Eigen::VectorXd> B_vec(B.data(), B.size());

    Eigen::GeneralizedSelfAdjointEigenSolver<Eigen::MatrixXd> ges;
    ges.compute(Q, B_vec.asDiagonal());

    eigenvalues = ges.eigenvalues();
    eigenfunctions = ges.eigenvectors();

    // Sort the eigenvalues by magnitude
    std::vector<std::pair<double, int> > map_vector(eigenvalues.size());

    for (auto i = 0; i < eigenvalues.size(); i++) {
        map_vector[i].first = std::abs(eigenvalues(i));
        map_vector[i].second = i;
    }

    std::sort(map_vector.begin(), map_vector.end());

    // truncate the first 100 eigenfunctions
    Eigen::MatrixXd eigenvectors(eigenfunctions.rows(), eigenfunctions.cols());
    Eigen::VectorXd eigenvals(eigenfunctions.cols());

    eigenvalues.resize(map_vector.size());
    for (auto i = 0; i < map_vector.size(); i++) {
        const auto& pair = map_vector[i];
        eigenvectors.col(i) = eigenfunctions.col(pair.second); 
        eigenvals(i) = pair.first;
    }

    eigenfunctions = eigenvectors;
    eigenvalues = eigenvals;
}