225 lines
4.1 KiB
C++
225 lines
4.1 KiB
C++
// Alexander Huddleston
|
|
// 10/2/17
|
|
// hw1pr2.cpp
|
|
// Read a file of points, compute interative best-first of a closed path between points.
|
|
|
|
#include<stdio.h>
|
|
#include<iostream>
|
|
#include<fstream>
|
|
#include<cmath>
|
|
#include<future>
|
|
#include<chrono>
|
|
#include<vector>
|
|
#include<climits>
|
|
#include<unordered_set>
|
|
|
|
using namespace std;
|
|
|
|
// Double vector used to store list of squared distances between points.
|
|
vector<vector<long int>> dmat;
|
|
|
|
vector<tuple<int, int>> points;
|
|
|
|
unordered_set<long int> relaxed_edges;
|
|
|
|
void store_points(ifstream *input, string filename)
|
|
{
|
|
input->open(filename);
|
|
|
|
string line = "";
|
|
|
|
string token = "";
|
|
|
|
tuple<int, int> temp_point;
|
|
get<0>(temp_point) = 0.0;
|
|
get<1>(temp_point) = 0.0;
|
|
|
|
while(getline(*input, line))
|
|
{
|
|
for(char c : line)
|
|
{
|
|
if(c == ' ')
|
|
{
|
|
get<0>(temp_point) = stof(token);
|
|
token = "";
|
|
}
|
|
else
|
|
{
|
|
token = token + c;
|
|
}
|
|
}
|
|
|
|
get<1>(temp_point) = stof(token);
|
|
|
|
token = "";
|
|
|
|
points.push_back(temp_point);
|
|
}
|
|
|
|
input->close();
|
|
}
|
|
|
|
void store_distances()
|
|
{
|
|
long int d1 = 0.0;
|
|
long int d2 = 0.0;
|
|
|
|
tuple< int, int> x;
|
|
tuple< int, int> y;
|
|
get<0>(x) = 0.0;
|
|
get<1>(x) = 0.0;
|
|
get<0>(y) = 0.0;
|
|
get<1>(y) = 0.0;
|
|
|
|
vector<long int> tempvec;
|
|
|
|
for(int r = points.size() - 1; r >= 0; --r)
|
|
{
|
|
for(int c = 0; c < points.size() - (points.size() - r); ++c)
|
|
{
|
|
x = points.at(r);
|
|
y = points.at(c);
|
|
|
|
d1 = (get<0>(x) - get<0>(y));
|
|
d2 = (get<1>(x) - get<1>(y));
|
|
|
|
tempvec.push_back(d1*d1 + d2*d2);
|
|
}
|
|
|
|
dmat.push_back(tempvec);
|
|
tempvec.clear();
|
|
}
|
|
}
|
|
|
|
bool is_visited(vector<int> relaxed_edges, int index)
|
|
{
|
|
for(int x : relaxed_edges)
|
|
{
|
|
if(x == index)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
long double best_first(ifstream *input, string filename)
|
|
{
|
|
// First, store the points from the file into global vector.
|
|
store_points(input, filename);
|
|
|
|
// Small optomization so we don't have to call points.size() so much.
|
|
long int n = points.size();
|
|
|
|
// Store squared distances into dmat.
|
|
// Ignore duplicate distances, 0 vectors.
|
|
store_distances();
|
|
|
|
// Find best-first shortest path.
|
|
|
|
// Keep edges we've already visited.
|
|
|
|
// Store distance up to this point.
|
|
long double current_distance = 0;
|
|
|
|
// Using this to keep track of selected node.
|
|
long int current_node = 0;
|
|
|
|
long int selected_node = 0;
|
|
|
|
// Using this to keep track of min distance.
|
|
long int min_distance = 0;
|
|
|
|
while(relaxed_edges.size() < (n - 1))
|
|
{
|
|
min_distance = INT_MAX;
|
|
for(int i = 0; i < (n - 1); ++i)
|
|
{
|
|
while(relaxed_edges.find(i) != relaxed_edges.end())
|
|
{
|
|
++i;
|
|
if(i == current_node)
|
|
{
|
|
++i;
|
|
}
|
|
}
|
|
if(i > (n - 1))
|
|
{
|
|
break;
|
|
}
|
|
|
|
if(i < current_node)
|
|
{
|
|
if(min_distance > dmat.at(i).at((n - 1) - current_node))
|
|
{
|
|
selected_node = ((n - 1) - i);
|
|
min_distance = dmat.at(i).at((n - 1) - current_node);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(i == current_node)
|
|
{
|
|
++i;
|
|
if(i > (n - 1))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(min_distance > dmat.at(current_node).at((n - 1) - i))
|
|
{
|
|
selected_node = ((n - 1) - i);
|
|
min_distance = dmat.at(current_node).at((n - 1) - i);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
relaxed_edges.insert((n - 1) - current_node);
|
|
current_node = selected_node;
|
|
current_distance += sqrt(min_distance);
|
|
}
|
|
|
|
current_distance += sqrt(dmat.at(current_node).at(0));
|
|
return current_distance;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
ifstream input;
|
|
|
|
string filename = "hw1pr_data.txt";
|
|
|
|
future<long double> fut = async(best_first, &input, filename);
|
|
|
|
chrono::milliseconds span(60000);
|
|
|
|
while((fut.wait_for(span)==future_status::timeout) || input.is_open())
|
|
{
|
|
}
|
|
|
|
if(input.is_open())
|
|
{
|
|
input.close();
|
|
}
|
|
|
|
long double total = fut.get();
|
|
|
|
tuple<int, int> tempx;
|
|
tuple<int, int> tempy;
|
|
|
|
long int temp;
|
|
|
|
for(long int i : relaxed_edges)
|
|
{
|
|
tempx = points.at(temp);
|
|
tempy = points.at(i);
|
|
cout << get<0>(tempx) << "\t" << get<1>(tempx) << "\t" << get<0>(tempy) << "\t" << get<1>(tempy) << endl;
|
|
temp = i;
|
|
}
|
|
|
|
cout << total << endl;
|
|
|
|
return 0;
|
|
}
|