How to sort a multidimensional vector of floats? - c++

So, I have a set of points in 3D, and I would like to store them in a 3 dimensional vector. Then I need sort that vector, giving priority first to the X dimention, then Y, then Z. So, for example, if I have this set of points:
P1 = (5, 10 ,9)
P2 = (1, 11, 4)
P3 = (8, 5, 2)
P4 = (5, 10, 3)
P5 = (5, 4, 0)
I would like to get a vector sorted like this:
[1, 11, 4]
[5, 4, 0]
[5, 10, 3]
[5, 10, 9]
[8, 5, 2]
So, how can a sort a multidimentional vector taking all rows into account?
Should I use std::priority_queue instead? If so, how show I use it?
Thanks

You could use an std::tuple<double, double, double> to represent a point. The comparison for std::tuple works lexicographically, the way you want it to. Alternatively, you could provide a custom sort function to your vector of points. Something like this:
sort(pointVector.begin(), pointVector.end(), [](const Point& lhs, const Point& rhs){//Implement your required comparison predicate here});
Also, as this question shows, you can achieve some sort of a named-tuple-with-lexicographic-sorting by using std::tuples lexicographic sort and std::tie.

...giving priority first to the X dimention, then Y, then Z
Use std::sort with std::tie, something like following
#include <algorithm>
#include <tuple>
//....
struct Points // Your 3D Point
{
float x,y,z;
} ;
std::vector<Points> v; // Vector of 3D points
std::sort( v.begin(), v.end(),
[]( const Points& lhs, const Points& rhs )
{
return std::tie(lhs.x,lhs.y,lhs.z)
< std::tie(rhs.x,rhs.y,rhs.z) ;
}
) ;
DEMO

You can use the std::sort() to easily sort according to your specific conditions by making your own comparator function.
Assuming you have stored a single 3D point in a struct point, and the points in a std::vector<points> (A std::tuple might be more useful.), try out this code.
Example:
#include <vector>
#include <algorithm>
using namespace std;
struct point
{
float x, y, z;
}
bool mySort(const point& a, const point& b)
{
//A naive comparison to help you understand better.
//You could always use std::tie for lexicographical comparison.
if (a.x == b.x)
{
if (a.y == b.y)
return a.z < b.z;
else
return a.y < b.y;
}
else
return a.x < b.x;
}
int main()
{
vector<point> graph;
//push_back() all your points into the graph.
//mySort() is a custom comparator function.
sort(graph.begin(),graph.end(),mySort);
}

Related

How can implement pdist of matlab using eigen with C++?

In Matlab, the D = pdist(X, Y) function computes pairwise distances between the two sets of observations X and Y. E.g. Given X = randu(3, 2), Y = randu(3, 2), where each row stores an observation (x, y). Then pdist returns a [3 x 3] D matrix in which the (i, j) entry represents the distance between the i-th observation in X and the j-th observation in Y.
I want to imitate this behavior using Eigen with C++.
I naively use a for-loop to iterate every observation in X and compute the pairwise distances between the current observation in X and every observation in Y. The result is a [1 x Y.rows] row vector which is then populated into the i-th row of the D matrix.
I think this implementation is somewhat slow as two iterations of the for-loop are independent, and a vectorization technique may be helpful.
Can some shed me some info to make the implementation faster?
I tried using Eigen's binaryExpr but the result was not expected.
I have implemented this function according to your explanation (I assume you want number of observations to be dynamic and this should work for any number of observations N1,N2):
#include <Eigen/Dense>
#include <iostream>
const int oDims = 2;
typedef Eigen::Matrix<double, Eigen::Dynamic, oDims, Eigen::RowMajor> ObservationMatrix;
auto pdist(const ObservationMatrix& X, const ObservationMatrix& Y)
{
return (X.replicate(1, Y.rows()) - Y.reshaped<Eigen::RowMajor>(1, Y.rows() * oDims).replicate(X.rows(), 1))
.reshaped<Eigen::RowMajor>(X.rows() * Y.rows(), oDims)
.rowwise().norm()
.reshaped<Eigen::RowMajor>(X.rows(), Y.rows());
}
int main() {
ObservationMatrix X(3, oDims), Y(4, oDims);
X << 3, 2,
4, 1,
0, 5;
Y << 10, 14,
12, 17,
16, 11,
13, 18;
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> result = pdist(X, Y);
std::cout << result << std::endl;
return 0;
}
I'm not sure if this implementation is faster but if you can share your implementation using for-loops we can check the timings. I have tried to verify it's functionality with MATLAB's pdist function. However, I couldn't find a template of pdist that accepts two matrices X, Y like you have described (https://www.mathworks.com/help/stats/pdist.html). Am I missing something?

How to find adjacent points in a 3D space in c++

I have a couple of points in a 3D space, and I want to write a condition to determine whether two points are adjacent: are they only a single unit apart in the integer lattice?
I have a struct named Point that holds x,y and z coordinates. Then in the main function, I set the values for points a,b,c,d,e and push them into a vector. Then in the for loop I want to check if two points are adjacent or not. Currently I'm just checking if they are on the same axis, but I do not know how to proceed.
struct Point {
int x;
int y;
int z;
};
bool adjacent(Point a, Point b) { ??? }
int main() {
struct Point a = {0, 0, 0};
struct Point b = {0, 0, -1};
struct Point c = {1, 0, -1};
struct Point d = {1, -1, -1};
struct Point e = {2, -1, -1};
assert(adjacent(a, b));
assert(adjacent(b, c));
assert(adjacent(c, d));
assert(adjacent(d, e));
assert(!adjacent(a, c));
}
By adjacent I mean something like in this photo:
Very briefly:
for each pair of points:
if two of the three coordinates are equal AND
the other coordinate differs by 1:
then mark the pair as adjacent.
Iterating through point pairs is simple enough: the first point a walks through indices 0-(n-2); the second point b walks through indices from a's position through the end, n-1.
Checking adjacency is also easy, given integer coordinates.
diff = abs(a.x - b.x) +
abs(a.y - b.y) +
abs(a.z - b.z)
diff = 1 iff the points are adjacent.

Trying to write a setdiff() function using RcppArmadillo gives compilation error

I'm trying to write a sort of analogue of R's setdiff() function in C++ using RcppArmadillo. My rather crude approach:
// [[Rcpp::export]]
arma::uvec my_setdiff(arma::uvec x, arma::uvec y){
// Coefficientes of unsigned integer vector y form a subset of the coefficients of unsigned integer vector x.
// Returns set difference between the coefficients of x and those of y
int n2 = y.n_elem;
uword q1;
for (int j=0 ; j<n2 ; j++){
q1 = find(x==y[j]);
x.shed_row(q1);
}
return x;
}
fails at compilation time. The error reads:
fnsauxarma.cpp:622:29: error: no matching function for call to ‘arma::Col<double>::shed_row(const arma::mtOp<unsigned int, arma::mtOp<unsigned int, arma::Col<double>, arma::op_rel_eq>, arma::op_find>)’
I really have no idea what's going on, any help or comments would be greatly appreciated.
The problem is that arma::find returns a uvec, and doesn't know how to make the implicit conversion to arma::uword, as pointed out by #mtall. You can help the compiler out by using the templated arma::conv_to<T>::from() function. Also, I included another version of my_setdiff that returns an Rcpp::NumericVector because although the first version returns the correct values, it's technically a matrix (i.e. it has dimensions), and I assume you would want this to be as compatible with R's setdiff as possible. This is accomplished by setting the dim attribute of the return vector to NULL, using R_NilValue and the Rcpp::attr member function.
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::uvec my_setdiff(arma::uvec& x, const arma::uvec& y){
for (size_t j = 0; j < y.n_elem; j++) {
arma::uword q1 = arma::conv_to<arma::uword>::from(arma::find(x == y[j]));
x.shed_row(q1);
}
return x;
}
// [[Rcpp::export]]
Rcpp::NumericVector my_setdiff2(arma::uvec& x, const arma::uvec& y){
for (size_t j = 0; j < y.n_elem; j++) {
arma::uword q1 = arma::conv_to<arma::uword>::from(arma::find(x == y[j]));
x.shed_row(q1);
}
Rcpp::NumericVector x2 = Rcpp::wrap(x);
x2.attr("dim") = R_NilValue;
return x2;
}
/*** R
x <- 1:8
y <- 2:6
R> all.equal(setdiff(x,y), my_setdiff(x,y))
#[1] "Attributes: < target is NULL, current is list >" "target is numeric, current is matrix"
R> all.equal(setdiff(x,y), my_setdiff2(x,y))
#[1] TRUE
R> setdiff(x,y)
#[1] 1 7 8
R> my_setdiff(x,y)
# [,1]
# [1,] 1
# [2,] 7
# [3,] 8
R> my_setdiff2(x,y)
#[1] 1 7 8
*/
Edit:
For the sake of completeness, here is a more robust version of setdiff than the two implementations presented above:
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
// [[Rcpp::export]]
Rcpp::NumericVector arma_setdiff(arma::uvec& x, arma::uvec& y){
x = arma::unique(x);
y = arma::unique(y);
for (size_t j = 0; j < y.n_elem; j++) {
arma::uvec q1 = arma::find(x == y[j]);
if (!q1.empty()) {
x.shed_row(q1(0));
}
}
Rcpp::NumericVector x2 = Rcpp::wrap(x);
x2.attr("dim") = R_NilValue;
return x2;
}
/*** R
x <- 1:10
y <- 2:8
R> all.equal(setdiff(x,y), arma_setdiff(x,y))
#[1] TRUE
X <- 1:6
Y <- c(2,2,3)
R> all.equal(setdiff(X,Y), arma_setdiff(X,Y))
#[1] TRUE
*/
The previous versions would throw an error if you passed them vectors with non-unique elements, e.g.
R> my_setdiff2(X,Y)
error: conv_to(): given object doesn't have exactly one element
To solve the problem and more closely mirror R's setdiff, we just make x and y unique. Additionally, I switched out the arma::conv_to<>::from with q1(0) (where q1 is now a uvec instead of a uword), because uvec's are just a vector of uwords, and the explicit cast seemed a little inelegant.
I've used std::set_difference from the STL instead, converting back and forth from arma::uvec.
#include <RcppArmadillo.h>
#include <algorithm>
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::uvec std_setdiff(arma::uvec& x, arma::uvec& y) {
std::vector<int> a = arma::conv_to< std::vector<int> >::from(arma::sort(x));
std::vector<int> b = arma::conv_to< std::vector<int> >::from(arma::sort(y));
std::vector<int> out;
std::set_difference(a.begin(), a.end(), b.begin(), b.end(),
std::inserter(out, out.end()));
return arma::conv_to<arma::uvec>::from(out);
}
Edit: I thought a performance comparison might be in order. The difference becomes smaller when the relative sizes of the sets are in the opposite order.
a <- sample.int(350)
b <- sample.int(150)
microbenchmark::microbenchmark(std_setdiff(a, b), arma_setdiff(a, b))
> Unit: microseconds
> expr min lq mean median uq max neval cld
> std_setdiff(a, b) 11.548 14.7545 17.29930 17.107 19.245 36.779 100 a
> arma_setdiff(a, b) 60.727 65.0040 71.77804 66.714 72.702 138.133 100 b
The Questioner might have already got the answer. However, the following template version may be more general. This is equivalent to setdiff function in Matlab
If P and Q are two sets, then their difference is given by P - Q or Q - P. If P = {1, 2, 3, 4} and Q = {4, 5, 6}, P - Q means elements of P which are not in Q. i.e., in the above example P - Q = {1, 2, 3}.
/* setdiff(t1, t2) is similar to setdiff() function in MATLAB. It removes the common elements and
gives the uncommon elements in the vectors t1 and t2. */
template <typename T>
T setdiff(T t1, T t2)
{
int size_of_t1 = size(t1);
int size_of_t2 = size(t2);
T Intersection_Elements;
uvec iA, iB;
intersect(Intersection_Elements, iA, iB, t1, t2);
for (int i = 0; i < size(iA); i++)
{
t1(iA(i)) = 0;
}
for (int i = 0; i < size(iB); i++)
{
t2(iB(i)) = 0;
}
T t1_t2_vec(size_of_t1 + size_of_t2);
t1_t2_vec = join_vert(t1, t2);
T DiffVec = nonzeros(t1_t2_vec);
return DiffVec;
}
Any suggestions for improving the performance of the algorithm are welcome.

Subtracting two vector<point2f> directly

I have to subtract two vectors of type Point2f (both are of same size). I know it can be done by extracting the values at each index and then subtracting them in a loop but is there a direct method to it? Something like
Vector<Point2f> A[3];
A[2] = A[1] - A[0];
just for sports ;)
std::vector<Point2f> A,B;
A.push_back(Point2f(1,2));
A.push_back(Point2f(3,4));
A.push_back(Point2f(5,6));
B.push_back(Point2f(5,2));
B.push_back(Point2f(4,4));
B.push_back(Point2f(3,6));
// Mat C; subtract(A,B,C);
Mat C = Mat(A) - Mat(B);
cout<< A << endl << B << endl <<C<<endl;
[1, 2; 3, 4; 5, 6]
[5, 2; 4, 4; 3, 6]
[-4, 0; -1, 0; 2, 0]
As per the documentation link that you provided, subtraction of two points is supported. So the following should work:
std::transform (A[1].begin(), A[1].end(), A[0].begin(), A[2].begin(), std::minus<Point2f>());
Note that this assumes that A[2] is big enough to store the result.
Alternative, you could write your own overloaded operator-() for vector subtraction:
const vector<Point2f> operator-(const vector<Point2f>& lhs, const vector<Point2f>& rhs)
{ ... }
You would need to optimize the above function to avoid a copy of the vector when the function returns. This does not preclude the need to write the looping code that you want to avoid. But it will give you a cleaner syntax for vector subtractions.

hashmap for 2d(3d) coordinates (i.e. vector of doubles)?

I wonder if there is a general all-around solution for a hash map for coordinates (in 2d or 3d, i.e. a vector of doubles)?
An example here demonstrates how to create a custom hash-map for pair<int,int>,
but it does not seem to be trivial to come-up with an unique map from pair<double,double> (which could represent a 2d coordinate) to size_t.
I know that i can use ordered maps by providing comparator object, but for my application there is no need to order them and hash-maps seems to be faster anyway.
However since i'm a newcomer to all this hash stuff, i am kind of lost on how to proceed.
p/s/ i use c++11.
To avoid extra dependencies, you can use std::hash. Here's an example using the code from the link you posted, and updated to use a std::pair<double,double>:
#include <unordered_map>
#include <cassert>
using namespace std;
class TPoint3D{
public:
TPoint3D(double x, double y, double z) : x(x), y(y), z(z){};
double x, y, z;
};
struct hashFunc{
size_t operator()(const TPoint3D &k) const{
size_t h1 = std::hash<double>()(k.x);
size_t h2 = std::hash<double>()(k.y);
size_t h3 = std::hash<double>()(k.z);
return (h1 ^ (h2 << 1)) ^ h3;
}
};
struct equalsFunc{
bool operator()( const TPoint3D& lhs, const TPoint3D& rhs ) const{
return (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z);
}
};
typedef unordered_map<TPoint3D, int, hashFunc, equalsFunc> TPoint3DMap;
int main(){
TPoint3DMap myMap;
// test equalsFunc
myMap[TPoint3D(10.0, 20.0, 30.0)] = 100;
myMap[TPoint3D(10.0, 20.0, 30.0)] = 200;
assert(myMap[TPoint3D(10.0, 20.0, 30.0)] == 200);
// test if hashFunc handles well repeated values inside TPoint3D
myMap[TPoint3D(10.0, 10.0, 10.0)] = 1;
myMap[TPoint3D(10.0, 20.0, 10.0)] = 2;
myMap[TPoint3D(10.0, 10.0, 20.0)] = 3;
myMap[TPoint3D(20.0, 10.0, 10.0)] = 4;
assert(myMap[TPoint3D(10.0, 10.0, 10.0)] == 1);
assert(myMap[TPoint3D(10.0, 20.0, 10.0)] == 2);
assert(myMap[TPoint3D(10.0, 10.0, 20.0)] == 3);
assert(myMap[TPoint3D(20.0, 10.0, 10.0)] == 4);
return 0;
}
As I said before, if you wish to use another structure you have to adapt both the pairHash class and pairEquals struct operator() to appropriately hash and compare the new keys, respectively.
Cheers
EDIT :
Modified code to use custom TPPoint3D class and uniform functor classes definitions (both using struct).
Added simple tests to validate the hash and equals functors.
I cannot comment on Andre's answer because I do not have enough reputation yet, but anyone trying to create a hash function using ^ (XOR) should note that XOR is associative. In other words a ^ (b ^ c) == (a ^ b) ^ c. This means that
(h1 ^ (h2 << 1)) ^ h3
which is the return value of Andre's answer, is the same as:
h1 ^ ((h2 << 1) ^ h3)
which itself is, due to the commutative nature of XOR (a ^ b == b ^ a), equivalent to:
(h3 ^ (h2 << 1)) ^ h1
What all of this means is that the hash method I am referring to will, for distinct a, b, and c, return the same hash for (a,b,c) as it will for (c,b,a). In other words the x and z coordinates are order independent / insensitive.
Depending on how you are using this hash method this might not be a problem. However, if for example the points you were hashing were aligned to a grid you would receive an inordinate number of hash collisions.
I would replace the expression in the return statement in Andre's answer with the one below. This should be order dependent / sensitive.
(h1 ^ (h2 << 1)) ^ (h3 << 2)
In the 3D case,std::unordered_map<std::tuple<double, double, double>, your_value_type> should work fine for you, assuming you are doing exact lookups. std::tuple<...> defines equality and hash functions for you, based on the equality and hash functions of the types it is aggregating.
The 2D case is of course the same, but using a std::tuple<double, double>.
Edit: Sorry for misinformation. There actually is not a default hash defined for std::tuple. To use this approach, you would have to define a hash_tuple templated functor class and then use that in the std::unordered_map. Other answers show how to do that part.
What about using hash_combine from Boost?
http://www.boost.org/doc/libs/1_53_0/doc/html/hash/combine.html