Dynamic Programming Solution for TSP in C++ - c++

I have been trying to implement Dynamic Programming solution for TSP (Travelling Salesperson Problem) in C++. My code compiles but when I try to run the object file the program stops working and I am forced to close it.
Here is the code:
int tsp(std::vector<std::vector<int>> matrix) {
int n = matrix[0].size();
std::vector<std::vector<int>> A; // Vertex, Set-Size
std::set<int> S;
for(int i = 0; i < n; ++i) {
S.insert(i);
}
for(int i = 0; i < n; i++) {
if(S.size() == 2) {
A[i][2] = matrix[1][i];
}
else if(S.size() > 2) {
std::set<int>::iterator it;
for(it = S.begin(); it != S.end(); ++it) {
int s = S.size();
S.erase(i);
int sd = S.size();
int k = *it;
if((k != i) && (k != 1) && (A[i][s] > (matrix[k][i] + A[k][sd]))) {
A[i][s] = matrix[k][i] + A[k][sd];
}
}
}
}
return A[1][n];
}
Can someone please point out what mistake I am making.

You need to fill or resize a std::vector before calling operator[int] on it. A vector is basically an array that holds its size. So any out of bound access will cause a segmentation fault in runtime (if you are lucky) or will corrupt your memory.
You have a vector of vectors here, so you will need to iterate over two ranges and fill (or resize) vectors properly:
std::vector<std::vector<int>> A; // Vertex, Set-Size
for(int i=size; i>0; --i)
A.push_back(std::vector<int>);
for(int i=size; i>0; --i)
for(int j=size; j>0; --j)
A[i][j] = 0;
Even better:
A.resize(size);
for(auto& v : a) // (since you already have c++11)
v.resize(size, val); // fill with val

Related

2 Dimensional array initializer list exception

[Exeption]
Hello guys,
I'm trying to make an initializer_list constructor for 2D array.
Any Help, please?
.......................
Matrix(int row,int col,const std::initializer_list<double>& list)
{
rows = row;
cols = col;
std::initializer_list<double>::iterator it;
arr = new double* [rows];
/*double* ptr = arr[k];*/
int n = 0;
for (it = list.begin(); it != list.end(); ++it)
{
int k = 0;
if (n == cols)
{
k++;
n = 0;
}
n++;
arr[k][n] = *it;
}
}
You did not allocate enough memory. Also note that you probably do not want to reset k in every iteration and there are ranged-based loops if you want to do something on the entire container:
//correct allocation
int n = 0;
int k = 0;
for (auto const& number : list) {
arr[k][n] = number;
n++;
if (n == col) {
n = 0;
++k;
}
}
There is also no need to declare variables before you need them. With iterators use for(auto it = list.begin(); it != list.end(); ++it).
Also there is no need for temporary variables when they are function parameters and row and col do not have a type.

Searching in vectors of pairs

I have a 2d vector of pairs and I would like get in which row is a given pair.
I tried to iterate through all the elements but I didn't succeed.
Here is the adjacency matrix of an undirected, weighted graph:
vector<pair<int,int >> adj[20];
for (int i = 1; i <= nodes; i++){
f >> x >> y >> weight;
adj[x].push_back(make_pair(weight, y));
adj[y].push_back(make_pair(weight, x));
}
And it looks like something like this:
(4,2),(5,3)
(4,1),(6,3)
(5,1),(6,2)
I am trying to find in which row is the pair (6,2)
typedef pair<int, int>p;
p pair= make_pair(6, 2);
cout << which_row(adj, pair);
Here is what I tried first:
int which_row(vector<p>adj[20], p pair) {
vector <pair<int, int>> ::iterator it;
for (int i = 0; i < adj->size(); i++) {
for (int j = 0; j < adj[i].size(); i++)
if (pair.first == adj[i][j].first && pair.second == adj[i][j].second)
return i;
}
return -1;
}
but it does not step in the for loop.
Second:
int which_row(vector<p>adj[20], p pair) {
vector <pair<int, int>> ::iterator it;
for (int i = 0; i <= adj->size(); i++) {
for (it = adj[i].begin(); it != adj[i].end(); it++)
if (pair.first == it->first && pair.second == it->second)
return i;
}
}
But it does not step in the second for loop.
What can I do?
Since we can infer your x and y inputs from the pairs you gave us, you never push anything into adj[0]. adj->size() is the same as adj[0].size(). You never pushed anything into this so it will be 0. It seems you want to go over every row? Each row contains a vector? Each vector contains some pairs? Make adj a vector<vector<pair<int, int>>> so you can access adj.size(). That's likely what you want. Or iterate from i = 0; i < 20; i++ to go over each row.
Change your iteration to:
int which_row(vector<p>adj[20], p pair) {
for (int i = 0; i < 20; i++) { // <-- changed to < 20 (not <= 20)
for (auto it = adj[i].begin(); it != adj[i].end(); it++)
if (pair == *it) // <-- pairs compare as you'd expect, no need to compare each element
return i;
}
return -1; // need to return something if not found
}
Or we can take advantage of std::find in the <algorithm> library:
#include <algorithm>
int which_row(vector<p>adj[20], p pair) {
for (int i = 0; i < 20; i++) { // <-- changed to < 20 (not <= 20)
if (std::find(adj[i].begin(), adj[i].end(), pair) != adj[i].end())
return i;
}
return -1; // need to return something if not found
}
If you change your adj initialization to std::vector<std::vector<p>> adj(20); you can change your which_row to:
// in main or whatever:
// makes a vector of 20 default-initialized (empty) vector<p>
std::vector<std::vector<p>> adj(20);
// elsewhere:
int which_row(vector<vector<p>> adj, p pair) {
for (auto i = 0; i < adj.size(); i++) { // <-- adj is a vector now
if (std::find(adj[i].begin(), adj[i].end(), pair) != adj[i].end())
return i;
}
}
return -1; // need to return something if not found
}

Unable to understand error

I have written a mergesort algo as follows but on compiling it I get the following ,which states
Expression: vector subscript out of range
I dont understand why I am getting this error, plz point out the mistakes,I have coded this algo based on my understanding of the mergesort algorithm
As per my understanding I have coded a recursive function(mergesort), in which each time the array in question is divided in two parts left and right namely and then the left and right arrays are subdivided further till the point where there is only 1 element present in the subarrays once this stage arrives the merge function is called to sort the partitioned arrays and merge it to the original array from which the arrays were partitioned and the recursion goes a step backward in the recursion tree
Here is the source code
#include<iostream>
#include<vector>
using namespace std;
class Soham
{
vector<int> v;
public:
Soham();
void merge(vector<int> &, vector<int> & ,vector<int> &);
void mergesort(vector<int> &);
};
Soham::Soham()
{
int no;
for (int i = 0; i < 5; i++)
{
cin >> no;
v.push_back(no);
}
mergesort(v);
cout << "result" << endl;
for (auto it = v.begin(); it != v.end(); it++)
cout << *it << " ";
}
void Soham::mergesort(vector<int> &v)
{
if (v.size() < 2)
return;
else
{
vector<int>left, right;
if (v.size() % 2 == 0)//if input size is even
{
auto it = v.begin() + (v.size() / 2);
left.assign(v.begin(),it);
right.assign(it, v.end());
}
else// if input size is odd
{
auto it = v.begin() + (v.size() / 2);
left.assign(v.begin(),next(it));
right.assign(next(it), v.end());
}
mergesort(left);
mergesort(right);
merge(left, right,v);
}
}
void Soham::merge(vector<int> &temp_left, vector<int> &temp_right,vector<int> &temp_main)
{
int i = 0, j = 0, k = 0;
while (i<= temp_left.size() && j <= temp_right.size())
{
if (temp_left[i] <= temp_right[j])
{
temp_main[k] = temp_left[i];
i++;
k++;
}
else
{
temp_main[k]=temp_right[j];
j++;
k++;
}
}
while (i <= temp_left.size())
{
temp_main[k]=temp_left[i];
i++;
k++;
}
while (j <= temp_right.size())
{
temp_main[k]=temp_right[j];
j++;
k++;
}
}
int main()
{
Soham a;
system("pause");
return 0;
}
Thanks For Help
while (i <= temp_left.size())
When you access vector at index size() you will get your out-of-bounds access

Segmentation fault 11 when using vectors in C++ concordance program

For starters, total C++ and coding noob here, apologies in advance. I've been working on a program that creates a concordance of a text file with the number of times a word occurs and on what lines the word occurs on. Brief example of the intended output:
A occurs 9 time(s) on lines 1 3 5
AND occurs 3 time(s) on lines 2 4
I first wrote the program using only arrays, which I've got running successfully. I'm now trying to rewrite it using vectors instead of arrays, and basically I have no idea what I'm doing past declaring the vectors. I've got my vector version to compile and link without errors, but when I run it I get a "segmentation fault 11" error. From what I understand, the reason this error is occurring because I'm trying to access memory that hasn't been allocated yet. I'm pasting my entire code that I've written so far below. If someone can help me out, or point me in the right director of what I need to do to make this happen, that'd be so awesome. I know I'll need to push the push_back method, but I just have no idea where. I realize this probably rudimentary to most of you, but I'm just trying to wrap my head around all of this. Again, thanks so much -
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
void copy(vector<int> fromarr, vector< vector<int> > toarr, int index)
{
for (int i = 0; i <= fromarr[0]; i++)
{
toarr[index][i] = fromarr[i];
}
}
void copy(vector< vector<int> > fromarr, vector<int> toarr, int index)
{
for (int i = 0; i <= fromarr[index][0]; i++)
{
toarr[i] = fromarr[index][i];
}
}
int search(vector<string> array, int len, string target)
{
for(int i = 0; i < len; i++)
{
if(array[i] == target) return i;
}
return -1;
}
void sort(vector<string> wordarray, vector<int> linecount, vector< vector<int> > linenumbersarray, int length)
{
int minpos = 0;
for(int i = 0; i < length; i++)
{
minpos = i;
for (int j = 0; j < length; j++)
{
if(wordarray[j] > wordarray[minpos]) minpos = j;
string tempword = wordarray[i];
int tempcount = linecount[i];
vector<int> tempnums;
copy(linenumbersarray, tempnums, i);
wordarray[i] = wordarray[minpos];
linecount[i] = linecount[minpos];
copy(linenumbersarray[minpos], linenumbersarray, i);
wordarray[minpos] = tempword;
linecount[minpos] = tempcount;
copy(tempnums, linenumbersarray, minpos);
}
}
}
int main(int argc, char* argv[])
{
vector<string> wordarray;
vector<int> linecount;
vector< vector<int> > linenumbersarray;
int arrayposition = 0;
int linenumber = 1;
int wordlength = 0;
ifstream infile;
infile.open(argv[1]);
string aline;
while (getline(infile, aline))
{
istringstream theline(aline);
string aword;
while (theline >> aword)
{
int isupdated = search(wordarray, wordlength, aword);
if (isupdated == -1)
{
wordarray[wordlength] = aword;
linecount[wordlength] = 1;
linenumbersarray[wordlength][0] = 1;
linenumbersarray[wordlength][1] = linenumber;
wordlength = wordlength + 1;
}
else
{
linecount[isupdated] = linecount[isupdated] + 1;
if (linenumbersarray[isupdated][linenumbersarray[isupdated][0]] != linenumber)
(linenumbersarray[isupdated][++linenumbersarray[isupdated][0]] = linenumber);
}
}
linenumber = linenumber + 1;
}
sort(wordarray, linecount, linenumbersarray, wordlength);
for (int i = 0; i < wordlength; i++)
{
ostringstream out;
for (int j = 1; j <= linenumbersarray[i][0]; j++)
{
out << linenumbersarray[i][j];
j != linenumbersarray[i][0] ? out << " " : out << ".";
}
cout << wordarray[i] << " occurs " << linecount[i] << " time(s) on lines " << out.str() << endl;
out.flush();
}
}
How do you populate your vectors? Use push_back function to fill them in.
vector<int> v; // an empty container
v.push_back(10); // now it has one element - an integer 10
Use size() function to access a vector size, do not pass length parameter as you do in few functions (sort, search).
Another way to iterate through an stl container (vector is a container) is to use iterators.
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{ int a = *it; /*gives you an element of the container*/ }
Using size or iterators will prevent you from accessing unallocated memory - this is your problem.
Do not use operator [] without checking vector boundary.
if (i < v.size()) {v[i]; //an element}
Here are two variants of your search function
int search(vector<string> const &array, string const &target)
{
for(int i = 0; i < array.size(); i++)
{
if(array[i] == target) return i;
}
return -1;
}
vector<string>::const_iterator search(vector<string> const &array, string const &target)
{
for(vector<string>::const_iterator it = array.begin(); it != array.end(); ++it)
{
if(*it == target) return it;
}
return array.end();
}
A better way of searching is to use std::find function, but you may leave that for later when you are more comfortable with STL. std::find does the same as second variant of search above.
vector<string>::iterator it;
it = find (myvector.begin(), myvector.end(), target);
if (it != myvector.end())
std::cout << "Element found in myvector: " << *it << '\n';
else
std::cout << "Element not found in myvector\n";

another vector vs dynamically allocated array

One often reads that there is little performance difference between dynamically allocated array and std::vector.
Here are two versions of the problem 10 of project Euler test with two versions:
with std::vector:
const __int64 sum_of_primes_below_vectorversion(int max)
{
auto primes = new_primes_vector(max);
__int64 sum = 0;
for (auto p : primes) {
sum += p;
}
return sum;
}
const std::vector<int> new_primes_vector(__int32 max_prime)
{
std::vector<bool> is_prime(max_prime, true);
is_prime[0] = is_prime[1] = false;
for (auto i = 2; i < max_prime; i++) {
is_prime[i] = true;
}
for (auto i = 1; i < max_prime; i++) {
if (is_prime[i]) {
auto max_j = max_prime / i;
for (auto j = i; j < max_j; j++) {
is_prime[j * i] = false;
}
}
}
auto primes_count = 0;
for (auto i = 0; i < max_prime; i++) {
if (is_prime[i]) {
primes_count++;
}
}
std::vector<int> primes(primes_count, 0);
for (auto i = 0; i < max_prime; i++) {
if (is_prime[i]) {
primes.push_back(i);
}
}
return primes;
}
Note that I also tested the version version with the call to the default constructor of std::vector and without the precomputation of its final size.
Here is the array version:
const __int64 sum_of_primes_below_carrayversion(int max)
{
auto p_length = (int*)malloc(sizeof(int));
auto primes = new_primes_array(max, p_length);
auto last_index = *p_length - 1;
__int64 sum = 0;
for (int i = 0; i < last_index; i++) {
sum += primes[i];
}
free((__int32*)(primes));
free(p_length);
return sum;
}
const __int32* new_primes_array(__int32 max_prime, int* p_primes_count)
{
auto is_prime = (bool*)malloc(max_prime * sizeof(bool));
is_prime[0] = false;
is_prime[1] = false;
for (auto i = 2; i < max_prime; i++) {
is_prime[i] = true;
}
for (auto i = 1; i < max_prime; i++) {
if (is_prime[i]) {
auto max_j = max_prime / i;
for (auto j = i; j < max_j; j++) {
is_prime[j * i] = false;
}
}
}
auto primes_count = 0;
for (auto i = 0; i < max_prime; i++) {
if (is_prime[i]) {
primes_count++;
}
}
*p_primes_count = primes_count;
int* primes = (int*)malloc(*p_primes_count * sizeof(__int32));
int index_primes = 0;
for (auto i = 0; i < max_prime; i++) {
if (is_prime[i]) {
primes[index_primes] = i;
index_primes++;
}
}
free(is_prime);
return primes;
}
This is compiled with the MVS2013 compiler, with optimization flags O2.
I don't really see what should be the big difference, because of the move semantics (allowing returning the big vector by value without copy).
Here are the results, with an input of 2E6:
C array version
avg= 0.0438
std= 0.00928224
vector version
avg= 0.0625
std= 0.0005
vector version (no realloc)
avg= 0.0687
std= 0.00781089
The statistics are on 10 trials.
I think there are quite some differences here. Is it because something in my code to be improved?
edit: after correction of my code (and another improvement), here are my new results:
C array version
avg= 0.0344
std= 0.00631189
vector version
avg= 0.0343
std= 0.00611637
vector version (no realloc)
avg= 0.0469
std= 0.00997447
which confirms that there is no penalty of std::vector compare to C arrays (and that one should avoid reallocating).
There shouldn't be a performance difference between vector and a dynamic array, since a vector is a dynamic array.
The performance difference in your code comes from the fact that you are actually doing different things between the vector and array version. For instance:
std::vector<int> primes(primes_count, 0);
for (auto i = 0; i < max_prime; i++) {
if (is_prime[i]) {
primes.push_back(i);
}
}
return primes;
This creates a vector of size primes_count, all initialized to 0, and then pushes back a bunch of primes onto it. But it still starts with primes_count 0s! So that's wasted memory from both an initialization perspective and an iteration perspective. What you want to do is:
std::vector<int> primes;
primes.reserve(primes_count);
// same push_back loop
return primes;
Along the same lines, this block;
std::vector<int> is_prime(max_prime, true);
is_prime[0] = is_prime[1] = false;
for (auto i = 2; i < max_prime; i++) {
is_prime[i] = true;
}
You construct a vector of max_prime ints initialized to true... and then assign most of them to true again. You're doing the initialization twice here, whereas in the array implementation you only do it once. You should just remove this for loop.
I bet if you fix these two issues - which would make the two algorithms comparable - you'd get the same performance.