Partition std::vector of 2D points - c++

Suppose I have a std::vector<Point> where Point is struct Point { double x; double y;}
I'd like to partition such a vector into groups (buckets), where all Points in same bucket have same Euclidean norm between each other (e.g dist(PointA,PointB) == X, where X is constant). I've decided to use std::map for such task with custom sorting operator:
struct ClosePoints
{
bool operator()(Point const& A, Point const& B) const
{
bool same = dist(A,B) < x;
//If not close enough use lexical sort
return same ? false : std::tie(A.x, A.y) < std::tie(B.x,);
}
}
Partitioning code:
std::map<Point, std::list<Point>, ClosePoints> map;
for(const auto& p : pointsVector)
map[p].push_back(p);
After some testing and printing the buckets I've noticed that some points that do obey given Euclidean norm limit X ended in different buckets.
I can't figure out why is it so ?

The issue is that comparison operator that you defined does not provide equivalence relationship. For instance, you can have a point B that close to A and C but points A and C could be far from each other. Thus, if you compare B with A and C, you will put them in the same basket as B. However, if you compere A and C first, results will be unpredictable.

Related

removing duplicate elemnts from a vector of non-primitive type

I read a very large number of point coordinates x, y and z and store them in a vector of Point structures to do further processing.
struct Point{
double x,y,z;
Point (double x0, double y0, double z0): x(x0), y(y0), z(z0) {}
}
vector<Point> pv;
pv.push_back (Point(x,y,z));
I also have a hash function that maps all the points with the same coordinates together with their vector index to an unordered_multimap for some other processing.
the problem is there are many duplicate points that I read from the file and I have to get rid of those elements. I have seen solutions on how to remove duplicate elements from a vector of primitive types but that does not apply to my case. In addition many of the proposed methods, requires sorting that is not applicable to a Point structure.
Define the less operator and then apply the same method as for primitive type
How to define the operator is:
struct Point{
(...)
const bool operator < ( const Point &r ) const{
return (x<r.x) || (x==r.x && y<r.y) || (x==r.x && y==r.y && z<r.z);
}
};
You can use the so-called erase-remove "idiom":
#include <algorithm>
...
pv.erase(std::remove(pv.begin(), pv.end(), pointToRemove), pv.end());
where operator== has been defined for Point:
bool operator==(Point a, Point b) {
return a.x == b.x && a.y == b.y && a.z == b.z;
}

c++ std set insert not "working"

I'm having some problems with std set. I know that it does not allows you to insert repeated elements and (I think that) my code is not trying to insert repeated elements. But it seems like the set is not inserting both elements. What is the problem? Is the collection considering both elements equal? Why?
#include <bits/stdc++.h>
using namespace std;
struct sam{
double a,b, tam;
sam(){
}
sam(double a1, double b1){
a = a1;
b = b1;
tam = b - a;
}
bool operator<(const sam &p) const{
return tam > p.tam;
}
};
set<sam> ssw;
int main(void){
ssw.insert(sam(0,2));
ssw.insert(sam(4,6));
cout<<ssw.size()<<"\n"; // prints "1"
return 0;
}
For both objects, the value of tam is 2.0. Since the operator< function works with that value, the two objects are considered to be equal.
BTW, using a floating point number to compare two objects is not a good idea. You can get unexpected results due to the imprecise nature of how floating points are represented.
In std::set
In imprecise terms, two objects a and b are considered equivalent (not
unique) if neither compares less than the other: !comp(a, b) &&
!comp(b, a)
In your case bool operator< not satisfy the above condition hence set treats them not unique.
Currently your comparator returns same values for both the inserts. Hence, only one item is successfully inserted. The other is just a duplicate, and is hence, ignored.
Maybe you meant this:
bool operator<(const sam &p) const{
return ( (a > p.a) || (b > p.b) || (tam > p.tam) );
}

How do I sort a vector with respect to another vector?

I have few vectors with same data type as.
v < int > = {5,4,1,2}
v2 < int > = {2,4,3,5,1,6,8,7}
v3 < int > = {1,4,2,3}
There is any way to sort vector v2 , v3 ... with respect to vector v using STL of C++(algorithm) so that
after sorting v2 would be {5,4,1,2,3,6,7,8} when it's sorted with respect to v and v3 would be {4,1,2,3} when it's sorted with respect to v .
Edit:
It may be unclear for some people.
let me explain ..
sorted vector has two parts , one is A and another one is B .
A contains element of vector v i.e. A is subset of v ,it follows same order as it's in v
B contains remaining element{v_i - A} of given vector(v_i) and it's sorted .
so for vector v2 after sorting it would be
v2 = A union B
A = {5,4,1,2}
B = {3,6,7,8}
class StrangeComparison {
public:
StrangeComparison(const vector<int>& ordering) : ordering_(ordering) {}
bool operator()(int a, int b) const {
auto index_a = find(ordering_.begin(), ordering_.end(), a);
auto index_b = find(ordering_.begin(), ordering_.end(), b);
return make_pair(index_a, a) < make_pair(index_b, b);
}
private:
const vector<int>& ordering_;
};
sort(v2.begin(), v2.end(), StrangeComparison(v));
Working example. Improving efficiency is left as an exercise for the reader (hint: look at std::find calls).
You only need to augment your comparison function with the following rules:
if the first value exists in the vector to sort with respect to, but the second value does not exist in it, then first < second
if the second value exists but the first does not, then second < first
if both values exist, compare their index values within that vector
If none of those conditions are true, the existing comparison logic would run.

dot product of vector < vector < int > > over the first dimension

I have
vector < vector < int > > data_mat ( 3, vector < int > (4) );
vector < int > data_vec ( 3 );
where data_mat can be thought of as a matrix and data_vec as a column vector, and I'm looking for a way to compute the inner product of every column of data_mat with data_vec, and store it in another vector < int > data_out (4).
The example http://liveworkspace.org/code/2bW3X5%241 using for_each and transform, can be used to compute column sums of a matrix:
sum=vector<int> (data_mat[0].size());
for_each(data_mat.begin(), data_mat.end(),
[&](const std::vector<int>& c) {
std::transform(c.begin(), c.end(), sum.begin(), sum.begin(),
[](int d1, double d2)
{ return d1 + d2; }
);
}
);
Is it possible, in a similar way (or in a slightly different way that uses STL functions), to compute column dot products of matrix columns with a vector?
The problem is that the 'd2 = d1 + d2' trick does not work here in the column inner product case -- if there is a way to include a d3 as well that would solve it ( d3 = d3 + d1 * d2 ) but ternary functions do not seem to exist in transform.
In fact you can use your existing column sum approach nearly one to one. You don't need a ternary std::transform as inner loop because the factor you scale the matrix rows with before summing them up is constant for each row, since it is the row value from the column vector and that iterates together with the matrix rows and thus the outer std::for_each.
So what we need to do is iterate over the rows of the matrix and multiply each complete row by the corresponding value in the column vector and add that scaled row to the sum vector. But unfortunately for this we would need a std::for_each function that simultaneously iterates over two ranges, the rows of the matrix and the rows of the column vector. To achieve this, we could use the usual unary std::for_each and just do the iteration over the column vector manually, using an additional iterator:
std::vector<int> sum(data_mat[0].size());
auto vec_iter = data_vec.begin();
std::for_each(data_mat.begin(), data_mat.end(),
[&](const std::vector<int>& row) {
int vec_value = *vec_iter++; //manually advance vector row
std::transform(row.begin(), row.end(), sum.begin(), sum.begin(),
[=](int a, int b) { return a*vec_value + b; });
});
The additional manual iteration inside the std::for_each isn't really that idiomatic use of the standard library algorithms, but unfortunately there is no binary std::for_each we could use.
Another option would be to use std::transform as outer loop (which can iterate over two ranges), but we don't really compute a single value in each outer iteration to return, so we would have to just return some dummy value from the outer lambda and throw it away by using some kind of dummy output iterator. That wouldn't be the cleanest solution either:
//output iterator that just discards any output
struct discard_iterator : std::iterator<std::output_iterator_tag,
void, void, void, void>
{
discard_iterator& operator*() { return *this; }
discard_iterator& operator++() { return *this; }
discard_iterator& operator++(int) { return *this; }
template<typename T> discard_iterator& operator=(T&&) { return *this; }
};
//iterate over rows of matrix and vector, misusing transform as binary for_each
std::vector<int> sum(data_mat[0].size());
std::transform(data_mat.begin(), data_mat.end(),
data_vec.begin(), discard_iterator(),
[&](const std::vector<int>& row, int vec_value) {
return std::transform(row.begin(), row.end(),
sum.begin(), sum.begin(),
[=](int a, int b) {
return a*vec_value + b;
});
});
EDIT: Although this has already been discussed in comments and I understand (and appreciate) the theoretic nature of the question, I will still include the suggestion that in practice a dynamic array of dynamic arrays is an awfull way to represent such a structurally well-defined 2D array like a matrix. A proper matrix data structure (which stores its contents contigously) with the appropriate operators is nearly always a better choice. But nevertheless due to their genericity you can still use the standard library algorithms for working with such a custom datastructure (maybe even by letting the matrix type provide its own iterators).

function inside functor definition

I have the following functor for redefining the less operator of the sort method for the vector type:
typedef vector< vector<int> > MxInt2d;
typedef vector< vector<double> > MxDouble2d;
class QSweep{
public:
....
static MxDouble2d myPoints_;
MxDouble2d myEdges_;
class order{
public:
bool operator() (const vector<int>& edge1, const vector<int>& edge2){
//std::cout<<"inside sort"<<endl;
//3 sort criteria
return (myPoints_[edge1[0]][0]<myPoints_[edge2[0]][0])||
(myPoints_[edge1[0]][0]==myPoints_[edge2[0]][0]&&
myPoints_[edge1[0]][1]<myPoints_[edge2[0]][1])
||
(myPoints_[edge1[0]][0]==myPoints_[edge2[0]][0]&&
myPoints_[edge1[0]][1]==myPoints_[edge2[0]][1]&&
getSlope(myPoints_[edge1[0]][0],myPoints_[edge1[0][1],
myPoints_[edge1[1]][0],myPoints_[edge1[1]][0])
<
getSlope(myPoints_[edge2[0][0],myPoints_[edge2[0][1],
myPoints_[edge2[1]][0],myPoints_[edge2[1]][0]));
}
};
static double getSlope(double a, double b, double c, double d);
};
where getSlope is a function defined in the following way:
double QSweep::getSlope(double a, double b, double c, double d){
double slope=0.0;
//std::cout<<"slope criteria"<<endl;
double denum=c-a;
if (denum==0){
std::cout<<"zero denominator"<<endl;
}
else{
slope=(d-b)/denum;
}
return slope;
}
Each point is given by an index, an x, and a y coordinate; Each edge is given by source-edge[0] and destination-edge[1],where edge[0],edge[1] are indexes of the points).
I want to arrange the edge:
- by the x coordinate of their edge[0] coordinate (iff the x's of 2 edges are different)
- by the y coordinate of their edge[0] coordinate (iff the x's of 2 edges are equal)
- by their corresponding slopes (iff the x's of edges and the y's of edges are equal).
I declared the getSLope function static, but when I sort the edges with
sort(myEdges_.begin(),myEdges_.end(),order());
the last condition is not fullfilled.
if I have two edges with the same x's and y's for edgep[0] but with different slopes, e.g. slope(edge1)=1 ,slope(edge2)=1/2 than I would want to get
[edge2, edge1]; instead I get [edge1,edge2].
So my getSlope criteria is not computed.
is it because I declared getSlope static? what should I change so that the criteria is fulfilled?
thank you in advance for your suggestions,
madalina
crikey! It looks quite complex, firstly have you tried with a less complex set of values to compute - ie I see you have cout statements, I trust that they work correctly when you run it?
If so, can iut be that your inputs to getSlope are wrong - shouldn't
getSlope(myPoints_[edge2[0][0],myPoints_[edge2[0][1],
myPoints_[edge2[1]][0],myPoints_[edge2[1]][0])
be
getSlope(myPoints_[edge2[0][0],myPoints_[edge2[0][1],
myPoints_[edge2[1]][0],myPoints_[edge2[1]][1])
Maybe it happened because expression result could be calculated without it.
E.g.:
false && someFunction(); - function will not be called
true || someFunction(); - function will not be called
This is nice rule, it allow us write next:
if ( ptr && ptr->someMethod() )
// call method will not be called for NULL pointers