// Alexander Huddleston 223000555 // CSCE420 // Due: October 2, 2017 (changed to 4) // hw1pr2.cpp // Purpose: Read a file of points, compute interative best-first of a closed path between points. #include #include #include #include #include #include #include #include #include #include using namespace std; // Double vector used to store list of squared distances between points. vector> dmat; // Used to store the points from file. vector> points; // Used to store the paths each iteration has traveled. vector> relaxed_edges; // Used to store the distance values of the respective paths. vector shortest_paths; void store_points(ifstream *input, string filename) { input->open(filename); string line = ""; string token = ""; tuple 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 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 tuple_sort(tuple t1, tuple t2) { return (get<1>(t1) < get<1>(t2)); } tuple, long double> iterate_path(int p) { // Find best-first shortest path for this iteration. // Small optomization so we don't have to call points.size() so much. long int n = points.size(); // In this variation, I want to keep track of the 4 closest points to root. vector closest; vector> first; long int temp_counter = n - 1; if(dmat.at(p).size() > 0) { for(long int b : dmat.at(p)) { tuple t (temp_counter, b); first.push_back(t); --temp_counter; } } for(int a = 0; a < (temp_counter); ++a) { tuple t ((temp_counter - a), (dmat.at(a).at((n - 1) - p))); first.push_back(t); } sort(first.begin(), first.end(), tuple_sort); temp_counter = 0; for(tuple te : first) { if(temp_counter > 3) { break; } closest.push_back(get<0>(te)); ++temp_counter; } // 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.at(p).size() < (n - 1)) { min_distance = INT_MAX; for(int i = 0; i < (n - 1); ++i) { while(relaxed_edges.at(p).find(i) != relaxed_edges.at(p).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.at(p).insert((n - 1) - current_node); current_node = selected_node; current_distance += sqrt(min_distance); } current_distance += sqrt(dmat.at(current_node).at(0)); tuple, long double> output; get<0>(output) = closest; get<1>(output) = current_distance; return output; } long double best_first(ifstream *input, string filename) { // First, store the points from the file into global vector. store_points(input, filename); // Store squared distances into dmat. // Ignore duplicate distances, 0 vectors. store_distances(); // This is how we know depth. long int depth = 1; // Which node iteration are we on? int n = 0; unordered_set empty; relaxed_edges.push_back(empty); while(depth < points.size() - 1) { // Find shortest path with given path. tuple, long double> ip = iterate_path(n); shortest_paths.push_back(get<1>(ip)); vector closest = get<0>(ip); unordered_set one; unordered_set two; unordered_set three; unordered_set four; long int temp = 0; for(long int i : relaxed_edges.at(n)) { ++temp; one.insert(i); two.insert(i); three.insert(i); four.insert(i); if(temp == depth) { if(closest.size() > 0) { one.insert(closest.at(0)); } if(closest.size() > 1) { two.insert(closest.at(1)); } if(closest.size() > 2) { three.insert(closest.at(2)); } if(closest.size() > 3) { four.insert(closest.at(3)); } break; } } relaxed_edges.push_back(one); relaxed_edges.push_back(two); relaxed_edges.push_back(three); relaxed_edges.push_back(four); if(n <= 1) { depth = 2; } else { depth = 2 + ((int)(log(n + 1)/log(4))); } ++n; } return shortest_paths.at(0); } int main() { ifstream input; string filename = "hw1pr2_data.txt"; future 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 tempx; tuple tempy; long int temp = 0; // Change 0 to shortest path. for(long int i : relaxed_edges.at(0)) { 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; }