Stange behaviour using nanoflann - c++

Using the nanoflann-library for k-nearest-neighbor searches based on KDTrees I encountered a very strange behavior. My Code is a simple set of queries:
#include <vector>
#include <iostream>
#include <nanoflann.hpp>
#include <eigen3/Eigen/Dense>
using Eigen::MatrixX3d;
using Eigen::Vector3d;
using nanoflann::KNNResultSet;
using nanoflann::SearchParams;
using kdt = nanoflann::KDTreeEigenMatrixAdaptor<MatrixX3d, 3, nanoflann::metric_L2>;
int main()
{
// Create simple matrix
MatrixX3d matrix(10, 3);
for(unsigned int i = 0; i < 10; i++)
{
double f_i = static_cast<double>(i);
matrix.row(i) = Vector3d(f_i, 0, 0);
}
// Create test points
std::vector<Vector3d> test_vecs;
for(unsigned int i = 0; i < 10; i++)
{
double f_i = static_cast<double>(i);
test_vecs.push_back(Vector3d(f_i, f_i, f_i));
}
// Result buffer
double distance;
size_t index;
KNNResultSet<double> result_set(1);
result_set.init(&index, &distance);
SearchParams sp;
// KDTree
kdt matrix_index(3, std::ref(matrix), 10);
matrix_index.index->buildIndex();
//Query points backwards
for(int i = 9; i >= 0; i--)
{
Vector3d curr_vec = test_vecs.at(i);
matrix_index.index->findNeighbors(result_set, &curr_vec[0], sp);
std::cout << i << std::endl;
std::cout << index << " " << distance << std::endl << std::endl;
}
// Query points forwards
for(unsigned int i = 0; i < 10; i++)
{
Vector3d curr_vec = test_vecs.at(i);
matrix_index.index->findNeighbors(result_set, &curr_vec[0], sp);
std::cout << i << std::endl;
std::cout << index << " " << distance << std::endl << std::endl;
}
}
The backward query (BQ) returns the expected results. However the forward query (FQ) only yields zeros (both index and distance). FQ also seems to break the KDTree altogether. If you change the order of the two queries (the last two for loops), so that FQ is performed before BQ both will now only yield zeros.
Why does that behavior occur and how to circumvent it?

The result set appears to be stateful - it's always showing you the nearest overall neighbor of all the points. For instance, if you loop from 5 to 10 you get 5 50 for each iteration
Reinitialize the result set each iteration and you'll get your desired behavior:
result_set.init(&index, &distance);
matrix_index.index->findNeighbors(result_set, &curr_vec[0], sp);
Demo: https://godbolt.org/z/s5f1jq

Related

Confusion on push_back interaction with pair<float,int>

I have no error message instead I only have unexpected behavior.
double get_optimal_value(int capacity, vector<int> weights, vector<int> values) {
int n = weights.size();
vector<pair<double, int>> valuePerWeight(n);
pair<double,int> x;
for(int i = 0; i < n; i++){
double v = values[i]/weights[i];
x = make_pair(values[i]/weights[i], weights[i]);
valuePerWeight.push_back(x);
}
for(int i = 0; i < n && capacity > 0; i++){
int amount = min(capacity, valuePerWeight[i].second);
value += valuePerWeight[i].first * amount;
capacity -= amount;
}
double value = 0.0;
return value;
}
I am creating a vector with values of type pair<double,int>. I create the pair using make_pair(some_double, some_int), then I call push_back with the pair.
Later in the function I index into the vector and do stuff using the pairs.
However an issue arises, when I index into my valuePerWeight vector and retrieve the attributes of the different pairs. They all end up being zero regardless of index and regardless of .first or .second.
Through printing a bunch of variables I have asserted the created pair is not {0,0} but as soon as I push_back into the vector and index the pair and look at it's .first and .second attributes both are equal to 0.
I can't seem to understand why this is, originally I was using push_back seen as below
valuePerWeight.push_back(make_pair(values[i]/weights[i], weights[i]));
instead of creating into a temporary variable x . However the same issue still stands.
Any help in the right direction would be greatly appreciated.
If there is any further clarification that I can give please ask me.
If you'd like to see for some values below is a snippet which can be compiled
I use input
3 50
60 20
100 50
120 30
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
double get_optimal_value(int capacity, vector<int> weights, vector<int> values) {
double value = 0.0;
int n = weights.size();
vector<pair<double, int>> valuePerWeight(n);
pair<double,int> x;
for(int i = 0; i < n; i++){
double v = values[i]/weights[i];
cout << v << ' '<< weights[i] << '\n';
x = make_pair(values[i]/weights[i], weights[i]);
cout << x.first << ' ' << x.second << '\n';
valuePerWeight.push_back(x);
cout << valuePerWeight[i].first << ' ' << valuePerWeight[i].second << '\n';
}
for(int i = 0; i < n; i++){
cout << valuePerWeight[i].first;
cout << valuePerWeight[i].second;
cout << '\n';
}
sort(valuePerWeight.begin(), valuePerWeight.end());
for(int i = 0; i < n && capacity > 0; i++){
int amount = min(capacity, valuePerWeight[i].second);
value += valuePerWeight[i].first * amount;
capacity -= amount;
}
// for(auto vp: valuePerWeight){
// cout << vp.first << vp.second;
// cout << '\n';
// }
return value;
}
int main() {
int n;
int capacity;
std::cin >> n >> capacity;
vector<int> values(n);
vector<int> weights(n);
for (int i = 0; i < n; i++) {
std::cin >> values[i] >> weights[i];
}
double optimal_value = get_optimal_value(capacity, weights, values);
std::cout.precision(10);
std::cout << optimal_value << std::endl;
return 0;
}
The confusion here is due to the behavior of the constructor you use
vector<pair<double, int>> valuePerWeight(n);
This actually fills the vector with n default constructed pairs, which as you may surmise, are (0, 0). When you push_back, you push to the end of these, so you a totally get 2n pairs.
.reserve does something close to what you expected, not actually filling the vector, but is likely not needed for something not bottle-necking on vector resizing.
Short story, omit the (n) to just construct an empty vector.
Three more suggestions: accept the vectors as const& to save a copy, and look at emplace_back instead of making a pair yourself and pushing it. That's what it's meant for. Also, note the comment by churill - dividing two integers will result in integer division regardless of where you are assigning the result. Static cast one of them to a float or double (or multiply by 1.0 at the start) to ensure floating point division.

How to fill a sparse matrix efficiently?

I use the eigen library to perform the sparse matrix operations, particularly, to fill a sparse matirx. But the rows and cols are very large in our case, which results in a long time for filling the sparse matrix. Is there any efficient way to do this (maybe by the other libraries)?
Below is the my code:
SparseMatrix mat(rows,cols);
mat.reserve(VectorXi::Constant(cols,6));
for each i,j such that v_ij != 0
mat.insert(i,j) = v_ij;
mat.makeCompressed();
The order in which a SparseMatrix is filled can make an enormous difference in computation time. To fill a SparseMatrix matrix quickly, the elements should be addressed in a sequence that corresponds to the storage order of the SparseMatrix. By default, the storage order in Eigen's SparseMatrix is column major, but it is easy to change this.
The following code demonstrates the time difference between a rowwise filling of two sparse matrices with different storage order. The square sparse matrices are relatively small and nominally identical. While the RowMajor matrix is almost instantly filled, it takes a much longer time (about 30 seconds on my desktop computer) in the case of ColMajor storage format.
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/SparseCore>
#include <random>
using namespace Eigen;
typedef SparseMatrix<double, RowMajor> SpMat_RM;
typedef SparseMatrix<double, ColMajor> SpMat_CM;
// compile with -std=c++11 -O3
int main() {
const int n = 1e4;
const int nnzpr = 50;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> randInt(0, n-1);
SpMat_RM m_RM(n,n);
m_RM.reserve(n);
SpMat_CM m_CM(n,n);
m_CM.reserve(n);
std::cout << "Row-wise filling of [" << n << " x " << n << "] sparse matrix (RowMajor) ..." << std::flush;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < nnzpr; ++j) {
int col = randInt(gen);
double val = 1. ; // v_ij
m_RM.coeffRef(i,col) = val ;
}
}
m_RM.makeCompressed();
std::cout << "done." << std::endl;
std::cout << "Row-wise filling of [" << n << " x " << n << "] sparse matrix (ColMajor) ..." << std::flush;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < nnzpr; ++j) {
int col = randInt(gen);
double val = 1.; // v_ij
m_CM.coeffRef(i,col) = val ;
}
}
m_CM.makeCompressed();
std::cout << "done." << std::endl;
}

Getting sequential pointers for the coordinates of a vtkPoint data

I wrote the following function to store the (x, y, z) of a vtkPoint in an array of type double and size of 3*N, where N is the number of vertices (or points).
double* myClass::getMyPoints(void)
{
double* vertices = new double[this->m_numberOfVertices * 3];
for (vtkIdType ivert = 0; ivert < this->m_numberOfVertices; ivert++)
for (auto i = 0; i < 3; ++i)
this->m_points->GetPoint(ivert, &vertices[3 * ivert]);
return vertices;
}
where m_points is a member of myClass and is of type vtkSmartPointer<vtkPoints>.
This function does what I want and works just fine. I was wondering if there is an elegant way of getting the sequential pointers. I tried GetVoidPointer(), which looks like an elegant one-line code, to avoid the for loop but it does not get the coordinates correctly after the function returns vertices.
(double*)(m_points->GetData()->GetVoidPointer(0));
Could someone help me with this?
vtkPoints internally stores it's data as a float array instead of a double array. So you may need to modify your function to work with float* instead of double*. If we want to use double array for vtkPoints then we should call SetDataTypeToDouble() on the vtkPoints object.
#include <stdio.h>
#include <stdlib.h>
#include <vtkPoints.h>
#include <vtkSmartPointer.h>
int main(){
// Create data
auto N = 5;
vtkNew<vtkPoints> pts;
pts->SetDataTypeToDouble();
for(auto i=0; i < N; ++i)
pts->InsertNextPoint(rand()%100,rand()%100,rand()%100);
// Read using for loop
std::cout<< "Using for loop ... " << std::endl;
for( auto j=0; j < N; ++j ){
double p[3];
pts->GetPoint( j, p );
std::cout<< p[0] << "," << p[1] << "," << p[2] << std::endl;
}
// Read using GetVoidPointer()
std::cout<< "Using GetVoidPointer() ... " << std::endl;
auto data_ptr = (double*) pts->GetData()->GetVoidPointer(0);
for( auto k = 0; k < N; ++k )
std::cout<< *(data_ptr + 3*k) << ","
<< *(data_ptr + 3*k + 1) << ","
<< *(data_ptr + 3*k + 2) << std::endl;
return 0;
}
This gives result as follows:
Test that there are N = 5 tuples.
Using for loop ...
83,86,77
15,93,35
86,92,49
21,62,27
90,59,63
Using GetVoidPointer() ...
83,86,77
15,93,35
86,92,49
21,62,27
90,59,63

Program stuck in infinite lop during single for loop calculation

I am new to c++ programming and am taking a computational physics class where we are analyzing the problem of percolation on a square lattice using a single-cluster algorithm. My professor has given us some base code, and asked us to modify it as well as write some additional code and scripts within and without this specific program. I have written the majority of the code and scripts necessary to solve and plot this problem, but I am having an issue with my main data output program, specifically that of an infinite loop when I set an input parameter to any value other than 0.
Three main function comprise this program, namely LATTICE::LATTICE, CLUSTER::grow, and CUSTER::print, and also uses a standard Mersenne Twister header file. The heavily modified, commented, and toyed with c++ program is as follows:
#include <fstream>
#include <iostream>
#include <math.h>
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
#include <cstdlib>
#include "MersenneTwister.h"
using namespace std;
class PARAMS
{
public:
int Nlin; // linear size of lattice
double pr; // probability for a site
double Nclust; // number of clusters in a bin
double Nbin; // number of bins of data to output
int SEED; // seed for mersenne twister
string latt_; // which lattice
PARAMS();//constructor
};
class LATTICE
{
public:
LATTICE(const PARAMS&);//constructor
int Nsite;// number of lattice sites
int Lx,Ly;
vector<vector<int> > nrnbrs;
void print ();
};
class CLUSTER
{
public:
CLUSTER(const PARAMS&, const LATTICE&);//constructor
void grow(const PARAMS&, const LATTICE&, MTRand&);
void meas_clear(const LATTICE&);
void meas(const LATTICE&);
void binwrite(const PARAMS&, const LATTICE&);
//void print(const LATTICE& latt, int index);
void print(const PARAMS& p, const LATTICE& latt);
~CLUSTER();// destructor
//private:
int size;
vector <int> conf;
vector <int> stack;
double pr;
//int stck_pnt,stck_end;
double avg_size;
ofstream dfout;
vector <int> stck_pnt;
vector <int> stck_end;
int z, pnt, prob, val, row, column;
vector< vector< vector <int> > > imax;
};
int main(void)
{
PARAMS p;
LATTICE latt(p);
CLUSTER cluster(p,latt);
MTRand ran(p.SEED);
latt.print();
/*for (int bin=0;bin<p.Nbin;bin++)
{
cluster.meas_clear(latt);
for(int clust=0;clust<p.Nclust;clust++)
{
cluster.grow(p,latt,ran);
cluster.meas(latt);
}
cluster.binwrite(p,latt);
}
*/
cluster.grow(p, latt, ran);
cluster.print(p,latt);
}
PARAMS::PARAMS(){
//initializes commonly used parameters from a file
ifstream pfin;
pfin.open("param.dat");
if (pfin.is_open()) {
pfin >> Nlin;
pfin >> pr;
pfin >> Nclust;
pfin >> Nbin;
pfin >> SEED;
pfin >> latt_;
}
else
{cout << "No input file to read ... exiting!"<<endl;exit(1);}
pfin.close();
// print out all parameters for record
cout << "--- Parameters at input for percolation problem ---"<<endl;
cout <<"Nlin = "<<Nlin<<"; prob. of site = "<<pr<<endl;
cout <<"Number of clusters in a bin = "<<Nclust<<"; Number of bins = "<<Nbin<<endl;
cout <<"RNG will be given SEED of = "<<SEED<<endl;
cout <<"Percolation problem on lattice --> "<<latt_<<endl;
};//constructor
LATTICE::LATTICE (const PARAMS& p)
{
string latt_=p.latt_;
if(p.latt_=="sqlatt_PBC")
{
Lx=p.Nlin;Ly=p.Nlin;
Nsite=Lx*Ly;
int i;
nrnbrs = vector<vector<int> >(Nsite, vector<int>(4));
for (i=0; i<Nsite; i++){
if((i+1) % p.Nlin != 0) nrnbrs[i][0] = i+1;
else nrnbrs[i][0] = i - p.Nlin + 1 ;
if(i + p.Nlin < Nsite ) nrnbrs[i][1] = i+p.Nlin;
else nrnbrs[i][1] = i - (Nsite-p.Nlin);
if(i % p.Nlin > 0) nrnbrs[i][2] = i-1;
else nrnbrs[i][2] = i-1+p.Nlin;
if(i - p.Nlin >= 0) nrnbrs[i][3] = i-p.Nlin;
else nrnbrs[i][3] = i + (Nsite-p.Nlin);
}
}
else if(p.latt_=="sqlatt_OBC")
{
Lx=p.Nlin;Ly=p.Nlin;
Nsite=Lx*Ly;
nrnbrs = vector<vector<int> >(Nsite, vector<int>(0));
for (int i=0; i<Nsite; i++){
if((i+1) % p.Nlin != 0){
nrnbrs[i].push_back(i+1);
}
if(i + p.Nlin < Nsite ){
nrnbrs[i].push_back(i+p.Nlin);
}
if(i % p.Nlin > 0){
nrnbrs[i].push_back(i-1);
}
if(i - p.Nlin >= 0){
nrnbrs[i].push_back(i-p.Nlin);
}
}
}
else
{cout <<"Dont know your option for lattice in param.dat .. exiting"<<endl;exit(1);}
}
void LATTICE::print()
{
//THIS FUNCTIONS MAY BE CALLED DURING DEBUGGING TO MAKE SURE LATTICE HAS BEEN DEFINED CORRECTLY
cout <<"---printing out properties of lattice ---"<<endl;
cout<<"size is "<<Lx<<"x"<<Ly<<endl;
cout <<"neighbors are"<<endl;
for (int site=0;site<Nsite;site++)
{
cout <<site<<" : ";
for (size_t nn=0;nn<nrnbrs.at(site).size();nn++)
cout<<nrnbrs.at(site).at(nn)<<" ";
cout <<endl;
}
cout << endl;
}
CLUSTER::CLUSTER(const PARAMS& p, const LATTICE& latt)
{
conf.resize(latt.Nsite);
stack.resize(latt.Nsite);
pr=p.pr;// store prob in a private member of cluster
dfout.open("data.out");
}
CLUSTER::~CLUSTER()
{
dfout.close();
}
void CLUSTER::grow(const PARAMS& p, const LATTICE& latt, MTRand& ran)
{
conf.resize(latt.Nsite); // Initalize Nsite elements of lattice to 0 in conf
// 0 = Not Asked; 1 = Asked, Joined; 2 = Asked, Refused
for (int i = 0; i < p.Nclust; ++i) { // Iterate for Nclust values
z = ran.randInt(latt.Nsite - 1); // Random integer between 0 and Nsite; Selects first lattice element in the cluster algorithm per Nclus
stck_pnt.resize(0); // Set stck_pnt and stck_end vectors to size 0; Will be filled when iterating through each Nclust
stck_end.resize(0); //-----------------------------------------------------------------------------------------------
//while (conf[z] != 0) { z = ran.randInt(latt.Nsite - 1); } // Iterate through lattice elements until we select one that has not been asked to join
conf[z] = 1; // Set element z in conf to have been asked to join and accepted
stck_pnt.push_back(z); // Add z to both stck_pnt and stck_end
stck_end.push_back(z);
for (int j = 0; j = 3; ++j) { // Add z's nearest neighbors to stck_end; Ignore if already been asked
if (conf[latt.nrnbrs[z][j] == 0]) {
stck_end.push_back(latt.nrnbrs[z][j]);
}
}
pnt = 1; // Initialize pnt for trasnferral of stack_end values to stck_pnt
while (stck_pnt.size() < stck_end.size()) {
stck_pnt.push_back(stck_end[pnt]); // Add pnt element of stck_end to stck_pnt
double prob = ran.rand(); // Get probability value for testing if cluster grows
if (prob <= pr) {
conf[stck_pnt[pnt]] = 1; // Set the current stck_pnt element to joined in conf
for (int j = 0; j = 3; ++j) { // Add z's nearest neighbors to stck_end; Ignore if already been asked
if (find(stck_end.begin(), stck_end.end(), latt.nrnbrs[stck_pnt[pnt]][j]) != stck_end.end()) {
// The given value already exists in stck_end, don't add it again
}
else { // The given value is not contained in stck_end, add it to stck_end
stck_end.push_back(latt.nrnbrs[z][j]);
}
}
}
else {
conf[stck_pnt[pnt]] = 2; // Set the given value to haven been asked and refused in conf
}
++pnt; // Increment pnt; ++p is more efficient then p++ due to lack of copying value
}
}
}
/*
void CLUSTER::print(const LATTICE& latt, int index)
{
stringstream ss;
string file_name;
ss << index << ".clust";
file_name = ss.str();
ofstream clout;
clout.open(file_name.c_str());
clout << "#" << latt.Lx << " x " << latt.Ly << endl;
for (int y = 0; y < latt.Ly; y++)
{
for (int x = 0; x < latt.Lx; x++)
clout << conf[x + y*latt.Lx] << " ";
clout << endl;
}
clout.close();
}
*/
void CLUSTER::print(const PARAMS& p, const LATTICE& latt)
{
//vector< vector< vector<int> > > imax(latt.Lx, vector< vector<int>>(latt.Ly, vector<int>(1)));
// Resize and allocate memeory for imax
//-------------- Row = y-position = i/Lx --------------- Column = x-position = i%Lx ---------------- val = conf[i]
ofstream myFile;
myFile.open("imax.out");
cout << "THe following output was calculated for the input parameters; Recorded to 'imax.out'" << endl;
cout <<"[index]" << "\t" << "[x-position]" << "\t" << "[y-position]" << "\t" << "[conf val]" << endl << endl;
for (int i = 0; i < latt.Nsite; ++i) {
val = conf[i]; // Find color value
row = i / latt.Lx; // Find row number
column = i%latt.Lx; // Find column number
cout << i << "\t" << column << "\t" << row << "\t" << val << endl;
myFile << i << "\t" << column << "\t" << row << "\t" << val << endl;
}
myFile.close();
double size = 0.0; // Initialize size
for (int i = 0; i < latt.Nsite; ++i) {
if (conf[i] == 1) {
size += 1;
}
}
double avg_size = size / p.Nclust; // Find avg_size
}
void CLUSTER::meas(const LATTICE& latt)
{
avg_size+=(double)size;
}
void CLUSTER::meas_clear(const LATTICE& latt)
{
avg_size=0.;
}
void CLUSTER::binwrite(const PARAMS& p, const LATTICE& latt)
{
dfout << avg_size/((double)p.Nclust)<<endl;
}
When I set Nclust=0 in the input file, the code runs as expected and gives the proper output in the file and console. However, when I set Nclust equal to any other value, I get the proper lattice console output but the program hangs for the cluster algorithm. I at first assumed that my computer and algorithm were slow and inefficient and that the program was working in some non-linear time. However, after leaving the program running for around 30 minutes for a 4x4 lattice (only 16 elements in the conf[] vector), no progress had been made and I assumed that the program was stuck in a loop.
After spending several hours going over the CLUSTER::grow() method line-by-line and experimenting with changing various bits of code, I have been unable to resolve where this loop error originates from. I would assume it is somewhere in the while loop that compares the size of stck_pnt and stck_end, but I cannot figure out why or where this is. Any help with this would be very greatly appreciated.
Tl;dr: For Nclust !=0, CLUSTER:grow gets stuck in an infinite loop
You have infinite loop here:
stck_end.push_back(z);
for (int j = 0; j = 3; ++j) { // <======== HERE
and here:
conf[stck_pnt[pnt]] = 1; // Set the current stck_pnt element to joined in conf
for (int j = 0; j = 3; ++j) { // <======== HERE

How do you print a full array of values in C++

I'm trying to figure out print a full array in C++.
For example, I want the output to be x = [1,2,3,4,5....n]
How would I go about doing this? I already know how to print each element of the array using a simple for loop. For example in python, you could simply say x = [], make a for loop to append elements to the array, and print x.
So let's say I have this code.
int n = 10;
int m = 10;
double x[n];
// Generate vector of random values for x
for (int i = 0; i<n; ++i)
{
x[i] = (double)rand()/(double)RAND_MAX;
// Print each array element
// std::cout << x[i] << std::endl;
}
std::cout << x[n-1] << std::endl;
This obviously only spits out x[10] in this case. Where as I want x = [1...n] etc.
What is the simplest way of achieving this?
I'm using Eclipse on OSX. I use the g++ compiler that the Xcode developer tools has for the command line
You're looking for a range based for loop:
double x[] = { .0, .1, .2, .3, .4 };
// Iterate through all elements
for (auto d : x)
{
std::cout << d << std::endl;
}
Note that the above takes a copy of each element, so if you wanted to modify an element you'd need to use
for (auto& d : x)
instead.
Alternatively you could just use a normal for loop like you did originally:
for (int i = 0; i<n; ++i)
{
std::cout << x[i] << std::endl;
}
The range based for loop is the easiest though.
if you know something about STL , you can try to use iterator
code:
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
int arr[5] = {1,2,3,4,5};
copy(arr, arr + sizeof(arr)/sizeof(int),ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}