I have 2 vectors, one (vector1 of structs (Point)) is filled with X amount of points and another (vector2 of structs (PrimeTemplate)) is filled with Y amount of points. I want to find all values below a threshold and I feel like my code just doesn't do that. For now I'll just ignore if one point maps to more than 1 other. What am I missing? I only generate a few points and I know I should be getting more.
struct Template{
int tempX;
int tempY;
};
struct PrimeTemplate{
double tempX;
double tempY;
};
int matches = 0;
for (int outerLoop = 0; outerLoop < vector1 .size(); outerLoop++)
{
for (int innerLoop = 0; innerLoop < vector2.size(); innerLoop++)
{
double tempEuclidianX = std::pow(abs(vector1 [outerLoop].tempX - vector2[innerLoop].tempX), 2.0);
double tempEuclidianY = std::pow(abs(vector1 [outerLoop].tempY - vector2[innerLoop].tempY), 2.0);
double Euclidian = sqrt(tempEuclidianX + tempEuclidianY);
if (Euclidian <= 5) //less than threshold
{
matches++;
}
}
}
Sample input from a file would look like this (two different files, random numbers) (no worries about getting data, it's all there)
245 21
452 54
124 68
485 78
111 29
97 75
78 113
300 124
411 101
What is wrong with your code is that you use abs() before squaring.
It isn't necessary to take the absolute value at all before squaring, of course, but if you are going to then you want to use fabs, as just abs takes and returns an integer. This extra rounding off might be why are not getting the right answer.
This was the method I used for calculating the shortest distances between a pair. It loops through a text file and loads up the vectors you see. Turned out the issue with the points was in my implementation before this code which was some the normalization of Biometric points.
for (int outerLoop = 0; outerLoop < Tvector.size(); outerLoop++)
{
for (int innerLoop = 0; innerLoop < QPrimeVector.size(); innerLoop++)
{
double tempEuclidianX = std::pow((QPrimeVector[innerLoop].tempX - Tvector[outerLoop].tempX), 2.0);
double tempEuclidianY = std::pow((QPrimeVector[innerLoop].tempY - Tvector[outerLoop].tempY), 2.0);
double Euclidian = sqrt(tempEuclidianX + tempEuclidianY);
if (Euclidian <= THRESHOLD) //less than threshold and not taken already
{
if (Euclidian < minEuclidian)
{
minEuclidian = Euclidian;
if (!Tvector[outerLoop].marked)
{
matched = innerLoop;
}
}
}
if (matched != -1)
{
matches++;
}
matched = -1;
minEuclidian = 10;
}
if (matches > masterMatchCount)
{
masterMatchCount = matches;
deltaThetaMaster = deltaTheta;
deltaXMaster = deltaX;
deltaYMaster = deltaY;
}
}
for (int reset = 0; reset < Tvector.size(); reset++)
{
Tvector[reset].marked = false; //reset all the matches
}
QPrimeVector.clear();
}
Related
Just started using cLion as an ide for c++. Am attempting to run this block of code where it reads a csv file and stores the values in a 189 x 141 2d vector. It then iterates through 5 for loops. Everything was running smoothly until I included the 5 nested for loops; at this point I was seeing the "Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)" message upon executing. I have seen an answer to a similar question claiming that it is the result of a lack of memory on my computer. Would this be the case?
When the first 3 for loops have ib0, ib1, ib2 iterate from 0 to 100, it would of course mean that there are over 26 billion iterations in total. However, when I reduce this range to 0 to 1, I still receive the message.
For reproducibility, I just have the ROB vector be 189 x 141 random values.
EDIT: If anyone runs this code, let me know how long it takes?
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main() {
double innerarrayval;
vector<vector<double>> ROB;
vector<double> innerarray;
for(int x=0;x<189;x++) {
innerarray.clear();
for (int y = 0; y < 141; y++) {
innerarrayval = rand() % 1000;
innerarray.push_back(innerarrayval);
}
ROB.push_back(innerarray);
}
double b0,b1,b2;
int nnb;
double chisquared, amean, content, sumpart, sumpartsquared,chisquaredNDOF,chimin;
double b0mem, b1mem, b2mem;
chimin = 1000.0;
for(int ib0 = 0; ib0 < 101; ib0++)
{
b0 = 15.0 + 0.1 * (ib0 - 1);
for(int ib1 = 0; ib1 < 101; ib1++)
{
b1 = -0.002 * (ib1 - 1);
for(int ib2 = 0; ib2 < 101; ib2++)
{
b2 = 0.002 * (ib2 - 1);
nnb = 0;
chisquared = 0;
amean = 0;
for(int i = 0; i <= 189; i++)
{
for(int j = 0; j <= 141; j++)
{
if((i >= 50 and i <= 116) and (j >= 42 and j <= 112))
{
continue;
}
else
{
content = ROB[i][j];
if(content == 0)
{
content = 1;
}
amean = amean + content;
sumpart = (content - b0 - (b1 * i) - (b2 * j))/sqrt(content);
sumpartsquared = pow(sumpart, 2);
chisquared = chisquared + sumpartsquared;
nnb = nnb + 1;
}
}
}
chisquaredNDOF = chisquared/double(nnb);
amean = amean/double(nnb);
if(chisquaredNDOF < chimin)
{
chimin = chisquaredNDOF;
b0mem = b0;
b1mem = b1;
b2mem = b2;
}
}
}
}
cout<<"chi squared: "<<chimin<<"\n";
cout<<"b0: "<<b0mem<<"\n";
cout<<"b1: "<<b1mem<<"\n";
cout<<"b2: "<<b2mem<<"\n";
cout<<"mean: "<<amean<<"\n";
return 0;
}
for(int x=0;x<189;x++) {
innerarray.clear();
for (int y = 0; y < 141; y++) {
innerarrayval = rand() % 1000;
innerarray.push_back(innerarrayval);
}
ROB.push_back(innerarray);
}
This part of the initialization loops carefully, and gingerly, initialized the two-dimensional ROB vector. As noted by each for loop's limit, the valid indexes for the first dimension is 0-188, and the 2nd dimension is 0-140.
This is correct. In C++ array/vector indexes start with 0, so for your expected result of a "189 x 141 2d vector", the first index's values range 0-188, and the 2nd one's range is 0-140.
If you proceed further in your code, to the part that reads the two-dimensional matrix:
for(int i = 0; i <= 189; i++)
{
for(int j = 0; j <= 141; j++)
{
And because this uses <=, this will attempt to access values in ROB whose first dimension's index range is 0-189 and the 2nd dimension's index range is 0-141.
The out of bounds access results in undefined behavior, and your likely crash.
You should use this obvious bug as an excellent opportunity for you to learn how to use your debugger. If you used your debugger to run this program, the debugger would've stopped at the point of the crash. If you then used your debugger to inspect the values of all variables, I would expect that the out-of-range values for i or j would be very visible, making the bug clear.
I am trying to implement the Divide and Conquer Algorithm to solve the Traveling Salesman problem.
I divided the problem into smaller parts, but I have no idea what to do next.
Here is my code:
struct coordinate
{
float x;
float y;
};
vector<coordinate> coordinates; //Please assume it is filled with random coordinates
void DivideAndConquer(int divide)
{
vector<vector<coordinate>> routes;
vector<coordinate> empty;
int check = 0;
for (int i = 0; i < coordinates.size(); i++)
{
if (i == divide * check)
{
check++;
routes.push_back(empty);
}
routes[check - 1].push_back(coordinates[i]);
}
//What now?
}
I also implemented methods to calculate distance:
float Distance(coordinate first, coordinate second)
{
return sqrt(pow(second.x - first.x, 2) + pow(second.y - first.y, 2) * 1.0);
}
float RouteDistance(vector<coordinate> route, bool returnBack)
{
float totalDistance = 0;
for (int i = 1; i < route.size(); i++)
{
totalDistance += Distance(route[i-1], route[i]);
}
if (returnBack) totalDistance += Distance(route[0], route[route.size() - 1]);
return totalDistance;
}
I wrote Brute Force algorithm as well, which I believe can be used in divide and conquer.
It simply returns to most optimal route of given coordinate vector.
vector<coordinate> BruteForce(vector<coordinate> route)
{
vector<int> turn;
for (int i = 0; i < route.size(); i++) turn.push_back(i);
int currentBestDistance = RouteDistance(route, true);
vector<coordinate> currentBestRoute = route;
do
{
vector<coordinate> newRoute;
int newRouteDistance;
for (int e : turn)
{
newRoute.push_back(route[e]);
}
newRouteDistance = RouteDistance(newRoute, false);
if (newRouteDistance < currentBestDistance)
{
currentBestRoute = newRoute;
currentBestDistance = newRouteDistance;
}
} while (next_permutation(turn.begin(), turn.end()));
return currentBestRoute;
}
In DivideAndConquer it currently divides the coordinates vector into sub vectors size of the "divide" parameter we call the function with.
For example, let's assume this is our coordinates:
10 20
23 54
98 123
55 72
16 82
And we call "DivideAndConquer(2)"
result:
10 20
23 54
98 123
55 72
16 82
I am trying to find the minimal distance in the Manhattan metric (x,y). I am searching for information about this. But I haven't found anything.
#include<bits/stdc++.h>
using namespace std;
#define st first
#define nd second
pair<int, int> pointsA[1000001];
pair<int, int> pointsB[1000001];
int main() {
int n, t;
unsigned long long dist;
scanf("%d", &t);
while(t-->0) {
dist = 4000000000LL;
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d%d", &pointsA[i].st, &pointsA[i].nd);
}
for(int i = 0; i < n; i++) {
scanf("%d%d", &pointsB[i].st, &pointsB[i].nd);
}
for(int i = 0; i < n ;i++) {
for(int j = 0; j < n ; j++) {
if(abs(pointsA[i].st - pointsB[j].st) + abs(pointsA[i].nd - pointsB[j].nd) < dist) {
dist = abs(pointsA[i].st - pointsB[j].st) + abs(pointsA[i].nd - pointsB[j].nd);
}
}
printf("%lld\n", dist);
}
}
}
My code works in O(n^2) but is too slow. I do not know whether it will be useful but y in pointsA always be > 0 and y in pointsB always be < 0. My code compare actually distance to next and chose smallest.
for example:
input:
2
3
-2 2
1 3
3 1
0 -1
-1 -2
1 -2
1
1 1
-1 -1
Output:
5
4
My solution (note for simplicity I do not care about overflow in manhattan_dist and for that reason it does not work with unsigned long long):
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <vector>
#include <limits>
#include <algorithm>
typedef std::pair<int, int> Point;
typedef std::vector<std::pair<int, int> > PointsList;
static inline bool cmp_by_x(const Point &a, const Point &b)
{
if (a.first < b.first) {
return true;
} else if (a.first > b.first) {
return false;
} else {
return a.second < b.second;
}
}
static inline bool cmp_by_y(const Point &a, const Point &b)
{
if (a.second < b.second) {
return true;
} else if (a.second > b.second) {
return false;
} else {
return a.first < b.first;
}
}
static inline unsigned manhattan_dist(const Point &a, const Point &b)
{
return std::abs(a.first - b.first) +
std::abs(a.second - b.second);
}
int main()
{
unsigned int n_iter = 0;
if (scanf("%u", &n_iter) != 1) {
std::abort();
}
for (unsigned i = 0; i < n_iter; ++i) {
unsigned int N = 0;
if (scanf("%u", &N) != 1) {
std::abort();
}
if (N == 0) {
continue;
}
PointsList pointsA(N);
for (PointsList::iterator it = pointsA.begin(), endi = pointsA.end(); it != endi; ++it) {
if (scanf("%d%d", &it->first, &it->second) != 2) {
std::abort();
}
assert(it->second > 0);
}
PointsList pointsB(N);
for (PointsList::iterator it = pointsB.begin(), endi = pointsB.end(); it != endi; ++it) {
if (scanf("%d%d", &it->first, &it->second) != 2) {
std::abort();
}
assert(it->second < 0);
}
std::sort(pointsA.begin(), pointsA.end(), cmp_by_y);
std::sort(pointsB.begin(), pointsB.end(), cmp_by_y);
const PointsList::const_iterator min_a_by_y = pointsA.begin();
const PointsList::const_iterator max_b_by_y = (pointsB.rbegin() + 1).base();
assert(*max_b_by_y == pointsB.back());
unsigned dist = manhattan_dist(*min_a_by_y, *max_b_by_y);
const unsigned diff_x = std::abs(min_a_by_y->first - max_b_by_y->first);
const unsigned best_diff_y = dist - diff_x;
const int max_y_for_a = max_b_by_y->second + dist;
const int min_y_for_b = min_a_by_y->second - dist;
PointsList::iterator it;
for (it = pointsA.begin() + 1; it != pointsA.end() && it->second <= max_y_for_a; ++it) {
}
if (it != pointsA.end()) {
pointsA.erase(it, pointsA.end());
}
PointsList::reverse_iterator rit;
for (rit = pointsB.rbegin() + 1; rit != pointsB.rend() && rit->second >= min_y_for_b; ++rit) {
}
if (rit != pointsB.rend()) {
pointsB.erase(pointsB.begin(), (rit + 1).base());
}
std::sort(pointsA.begin(), pointsA.end(), cmp_by_x);
std::sort(pointsB.begin(), pointsB.end(), cmp_by_x);
for (size_t j = 0; diff_x > 0 && j < pointsA.size(); ++j) {
const Point &cur_a_point = pointsA[j];
assert(max_y_for_a >= cur_a_point.second);
const int diff_x = dist - best_diff_y;
const int min_x = cur_a_point.first - diff_x + 1;
const int max_x = cur_a_point.first + diff_x - 1;
const Point search_term = std::make_pair(max_x, std::numeric_limits<int>::min());
PointsList::const_iterator may_be_near_it = std::lower_bound(pointsB.begin(), pointsB.end(), search_term, cmp_by_x);
for (PointsList::const_reverse_iterator rit(may_be_near_it); rit != pointsB.rend() && rit->first >= min_x; ++rit) {
const unsigned cur_dist = manhattan_dist(cur_a_point, *rit);
if (cur_dist < dist) {
dist = cur_dist;
}
}
}
printf("%u\n", dist);
}
}
Benchmark on my machine (Linux + i7 2.70 GHz + gcc -Ofast -march=native):
$ make bench
time ./test1 < data.txt > test1_res
real 0m7.846s
user 0m7.820s
sys 0m0.000s
time ./test2 < data.txt > test2_res
real 0m0.605s
user 0m0.590s
sys 0m0.010s
test1 is your variant, and test2 is mine.
You'll need to learn how to write functions and how to use containers. With your current coding style, it's infeasible to get a better solution.
The problem is that the better solution is a recursive method. Sort the points by X coordinate. Now recursively split the set in half and determine the closest distance within each half as well as the closest distance between a pair of points from either half.
The last part is efficient because both halves are sorted by X. Comparing the last values from the left half with the first value of the right half gives a good upper bound on the distance.
So there's a really simple optimization you can make that can cut a ton of time off.
Since you state that all points in set A have y > 0, and all points in set B have y < 0, you can immediately discard all points in A whose y > mindist and all points in B whose y < -mindist so far. These points can never be closer than the current closest pair:
for(int i = 0; i < n ;i++) {
if (pointsA[i].nd > dist)
continue; // <- this is the big one
for(int j = 0; j < n ; j++) {
if (pointsB[j].nd < -dist)
continue; // <- helps although not as much
if(abs(pointsA[i].st - pointsB[j].st) + abs(pointsA[i].nd - pointsB[j].nd) < dist) {
dist = abs(pointsA[i].st - pointsB[j].st) + abs(pointsA[i].nd - pointsB[j].nd);
}
}
printf("%lld\n", dist);
}
For a test of 40000 points per set, on my machine with gcc and -O2 this reduces the time from 8.2 seconds down to roughly 0.01 seconds (and yields correct results)! (measured with QueryPerformanceCounter on Windows).
Not too shabby.
Fwiw, computing your distance twice isn't actually that big of a deal. First of all that "second" calculation doesn't actually happen all that often, it only happens when a closer distance is found.
And secondly, for reasons I can't explain, storing it in a variable and only calculating it once actually consistently seems to add about 20% to the total run time, raising it from an average of 8.2 sec to about 10.5 seconds for the above set.
I'd say discarding points based on your assumptions about the Y values is by far the biggest bang for your buck you can get without significantly changing your algorithm.
You may be able to take advantage of that further by pre-sorting A and B in order of increasing Y values for A, and decreasing Y values for B, before finding the distances, to maximize the chance of skipping over subsequent point sets.
Keep a list of candidates in group A and group B, initially containing the whole input. Take min y of A and max y B for the closest pair in y, calculate the Manhattan distance, and eliminate any with y greater than the upper bound from the candidate lists. This might slash the input or it might have essentially no effect, but it's O(N) and a cheap first step.
Now sort the remaining candidates in x and y. This gives you a separated list in y ,and a mixed list in x, and is O(N log N), where N has been cut down, hopefully but not necessarily, by step one.
For each point, now calculate its closest neighbour in y (trivial) and closest in x (a bit harder), then calculate its minimum possible Manhattan distance, assuming the closest in x is also the closest in y. Eliminate any points further than your bound from the candidate list. Now sort again, by minimum possible. That's another N log N operation.
Now start with your best candidate and find its genuine minimum distance, by trying the closest point in either direction in x or y, and terminating when either delta x or delta y goes above the best so far, or delta x or delta y goes above your maximum bound. If you have better candidate pair then the current candidate pair, purge the candidate list of everything with a worse minimum possible. If the best candidate point doesn't form half of a candidate pair, you just purge that one point.
When you've purged a certain number of candidates, recalculate the lists. I'm not sure what the best value to use would be, certainly if you get to the worst candidate you must do that and then start again at the best. Maybe use 50%.
Eventually you are left with only one candidate pair. I'm not quite sure what the analysis is - worst case I suppose you only eliminate a few candidates on each test. But for most inputs you should get the candidate list down to a small value pretty fast.
I have a bunch of maths manipulations that have thresholds, yet no matter what I change, the if statements always return true. No compile errors, can't get the debugger to work. This is a function, the X Y and Z arrays are all correct (I printed them to check earlier), the maths is right at least for the blade distance check, yet that always returns true. I ran the same code (rewritten obviously) through matlab and that returns true or false depending on my data, so clearly its something with the way I've written this that's wrong. Also is there any way to slimline this?
bool Device::_SafeD(char _Type, float _Data[20][3]) {
bool S;
double x[20], y[20], z[20];
for (int i=0; i<20; i++) {
x[i] = _Data[i][0];
y[i] = _Data[i][1];
z[i] = _Data[i][2];
}
// Check angles for needle
if (_Type == 'n') {
for (int i=0; i<20; i++) {
float dot, moda, modb, c, angle;
dot = ((x[i]*x[i+1]) + (y[i]*y[i+1]) + (z[i]*z[i+1]));
moda = sqrt(pow(x[i],2)+pow(y[i],2)+pow(z[i],2));
modb = sqrt(pow(x[i+1],2)+(y[i+1],2)+(z[i+1],2));
c = dot/(moda*modb);
angle = acos(c);
if (angle > 45){
S = 0;
} else {
S = 1;
}
}
}
// Check distance for blade
if (_Type == 'b'){
for (int i=0; i<19; i++) {
float distance = (x[i+1]-x[i]) + (y[i+1]-y[i]) + (z[i+1]-z[i]);
cout << "distance " << distance << endl;
if (distance > 5.0) {
S = 0;
} else {
S = 1;
}
}
}
if (S == 0) {
return 0;
}
if(S == 1) {
return 1;
}
}
Cheers
The most likely error is that you are comparing angle to an angle in degree while the return value of acos is in radians.
if (angle > 45){
Convert the angle to degrees before comparing to 45 and you should be OK.
if (radians_to_degrees(angle) > 45){
where
double radians_to_degrees(double in)
{
return (in*180/M_PI);
}
Another option is to compute the equivalent of 45 degrees in radians and compare it with angle.
double const radian_45 = M_PI*45.0/180;
and use
if (angle > radian_45){
The other error is spelled out clearly in a comment by #Bob__:
OP uses two loops to check the angle and the distance, inside those loops a flag (S) is set to 0 or 1, but it's done for every index in the array, so it's overwritten. The return value of the entire function (in the provided code) depends only by the last two elements in the array.
I am reading some coordinates from a file and trying to assign them cell values (0-2) by diving them into a 3x3 grid. For some values the code is assigning negative cell values like for x=268 or x=269. Where am I going wrong?
I have file output.txt as follows with :
76 62
77 62
78 62
79 62
81 62
83 62
86 62
etc
The code to assign cells:
int x_points[99];
int y_points[99];
int i=0;
int x,y;
int max_x, max_y;
int min_x, min_y;
while(out.good())
{
out>>x;
out>>y;
if(i==0)
{
max_x=x;
min_x=x;
min_y=y;
max_y=y;
}
else if (x>max_x)
{
max_x=x;
}
else
if(x < min_x)
{
min_x=x;
}
else if (y>max_y)
{
max_y=y;
}
else
if(y < min_y)
{
min_y=y;
}
x_points[i]=x;
y_points[i]=y;
i++;
}
for(i=0; i<99; i++)
cout<<x_points[i]<<","<<y_points[i]<<"\n";
int cells_x[99];
int cells_y[99];
float x_width;
float y_width;
int divide = 3;
//To find out the cells. Divide it by 20
x_width=(max_x-min_x)/divide;
y_width=(max_y-min_y)/divide;
cout<<"\nx_width:"<<x_width;
cout<<"y_width:"<<y_width<<"\n";
int x1;
int y1;
for(i=0; i<99; i++)
{
x1=x_points[i]-min_x;
y1=y_points[i]-min_y;
for(int j=0; j<divide; j++)
{
if(j*x_width<=x1 && x1<((j+1)*x_width))
cells_x[i]=j;
if(j*y_width<=y1 && y1<((j+1)*y_width))
cells_y[i]=j;
}
cout<<cells_x[i]<<" "<<i<<" "<<cells_y[i]<<"\n";
}
The first problem I see is where you try to find the maximum and minimum values of x and y:
if(i==0)
{
max_x=x;
min_x=x;
min_y=y;
max_y=y;
}
else if (x>max_x)
{
max_x=x;
}
else if(x < min_x)
{
min_x=x;
}
else if (y>max_y) /* <-- This should not have an else! */
{
max_y=y;
}
else if(y < min_y)
{
min_y=y;
}
As written, it prevents the analysis of y values when an x is a new max or min. This will cause issues with the rest of your program, since max_y and min_y don't actually contain the max and min.
Next up is calculating the x_width and y_width:
x_width=(max_x-min_x)/divide; // should be x_width=(max_x-min_x + 1)/divide;
y_width=(max_y-min_y)/divide; // y_width=(max_y-min_y + 1)/divide;
If max_x = 8, and min_x = 0, your code would result in x_width = 8/3, or about 2.6666666666666666666666666666667. But 0-8 can be split up into 3 groups of 3. Adding 1 corrects this by calculating the number of points, not the length of the line.
It also prevents you from having a width of 0, which would happen if max_x == min_x. A width of 0 causes trouble in the next section:
for(int j=0; j<divide; j++)
{
/* an x_width of 0 will cause this to never evaluate to true */
/* x1 cannot ever be >= to 0 AND < 0 */
if(j*x_width<=x1 && x1<((j+1)*x_width))
cells_x[i]=j;
if(j*y_width<=y1 && y1<((j+1)*y_width))
cells_y[i]=j;
}
if x_width is zero, then you will never assign a value to cells_x[i], meaning it will still be set to its initialization value, which could be a negative number.