What is happening with vector array here? - c++

I'm solving the Traveling Salesman Problem via an ACO implementation in C++. However, I found out that the program I've built so far gives a segmentation fault.
(Note: I've limited the algorithm to only do one iteration of the colony for debugging purposes).
First off, I have a total of 52 cities taken from a file, and I distribute the ants so that every city has the same number of ants starting from it.
To store the distances between every pair of cities, I'm using a vector of vectors of doubles called Map (a square matrix). However, half-way during the execution it looks like these vectors are deleted. In this instance, it happens when calculating the path for the ant number 55. I've added a section of code just to highlight exactly where it crashes:
//DEBUGGING SECTION
cout << "Size Roulette: " << Roulette.size() << endl;
cout << "Size Remain: " << RemainingCities.size() << endl;
cout << "Size Map: " << Map.size() << " x " << Map[0].size() << endl;
int k = 0;
cout << "Test: Map access: " << endl;
for(int i = 0; i < Map.size(); ++i) // HERE IT CRASHES AT ANT NUMBER 55
cout << Map[0][i] << " ";
cout << endl;
cout << "Test: Operation: " << Map[Colony[ant_i][city_i-1]][RemainingCities[k]] << endl;
Roulette[k] = pow((MAX_DIST - Map[Colony[ant_i][city_i-1]][RemainingCities[k]]), heur_coef) + pow((pheromones[Colony[ant_i][city_i-1]][RemainingCities[k]]), pher_coef);
//END OF DEBUGGING SECTION
There, the function Map[0].size() normally returns 52 (just like Map.size(), as it's supposed to be a square matrix), but at the crashing iteration it returns what looks like a memory address, and the moment I try to access any element, a segmentation fault occurs.
I have checked that the memory access is always correct, and I can access any other variable without issue except Map until that 55th ant.
I've tried different seeds for the roulette method, but it always crashes at the same place.
I have also varied the number of ants of the colony. If it's just one ant per city, the program executes without issue, but for any higher amount the program always crashes at the 55th ant.
You can download the full cpp file and the reading .tsp file from github:
https://github.com/yitosmash/ACO
In any case, I'll leave the full function here:
void ACO(const vector<City>& cities, const vector<vector<double>>& Map, int max_it, int num_ants, double decay, double heur_coef, double pher_coef, double pher_coef_elit)
{
srand(30);
//Initialise colony of ants (each ant is a vector of city indices)
vector<vector<int>> Colony(num_ants, vector<int>(cities.size(), 0));
//Initialise pheromone matrix
vector<vector<double>> pheromones(cities.size(), vector<double>(cities.size(), 0));
//Initialise costs vector(for etilist expansion)
vector<double> costs(cities.size(), 0);
//Auxiliar vector of indices
vector<int> cityIndices(cities.size());
for (int i = 0; i < cities.size(); ++i)
cityIndices[i] = i;
//Longest distance from Map, used for heuristic values.
vector<double> longests(cities.size(), 0);
for(int i = 0; i < cities.size(); ++i)
longests[i] = *(max_element(Map[i].begin(), Map[i].end()));
const double MAX_DIST = *(max_element(longests.begin(), longests.end()));
longests.clear();
int i=0;
while(i<max_it)
{
for(int ant_i = 0; ant_i < num_ants; ++ant_i)
{
cout << "Ant: " << ant_i << endl;
//City for ant_i to start at; each ant is assigned a determined starting city
int starting_city = (int) ((float)ant_i/num_ants*cities.size());
//cout << starting_city << endl;
Colony[ant_i][0] = starting_city;
//Get a vector with the cities left to visit
vector<int> RemainingCities = cityIndices;
//Remove starting city from remaining cities
RemainingCities.erase(RemainingCities.begin() + starting_city);
//Create path for ant_i
for(int city_i = 1; city_i < Colony[ant_i].size(); ++city_i)
{
cout << "Calculating city number: " << city_i << endl;
//Create roulette for next city selection
vector<double> Roulette(RemainingCities.size(), 0);
double total = 0;
//DEBUGGING SECTION
cout << "Size Roulette: " << Roulette.size() << endl;
cout << "Size Remain: " << RemainingCities.size() << endl;
cout << "Size Map: " << Map.size() << " x " << Map[0].size() << endl;
int k = 0;
cout << "Test: Map access: " << endl;
for(int i = 0; i < Map.size(); ++i) // HERE IT CRASHES AT ANT NUMBER 55
cout << Map[0][i] << " ";
cout << endl;
cout << "Test: Operation: " << Map[Colony[ant_i][city_i-1]][RemainingCities[k]] << endl;
Roulette[k] = pow((MAX_DIST - Map[Colony[ant_i][city_i-1]][RemainingCities[k]]), heur_coef) + pow((pheromones[Colony[ant_i][city_i-1]][RemainingCities[k]]), pher_coef);
//END OF DEBUGGING SECTION
for(int j = 0; j < RemainingCities.size(); ++j)
{
//Heuristic value is MAX_DIST - current edge.
Roulette[j] = pow((MAX_DIST - Map[Colony[ant_i][city_i-1]][RemainingCities[j]]), heur_coef) + pow((pheromones[Colony[ant_i][city_i-1]][RemainingCities[j]]), pher_coef);
total += Roulette[j];
}
cout << endl;
//Transform roulette into stacked probabilities
Roulette[0] = Roulette[0]/total;
for(int j = 1; j < Roulette.size(); ++j)
Roulette[j] = Roulette[j-1] + Roulette[j] / total;
//Select a city from Roulette
int chosen = 0;
double r = (double) rand()/RAND_MAX;
while(Roulette[chosen] < r)
chosen++;
//Add chosen city to
Colony[ant_i][city_i] = RemainingCities[chosen];
RemainingCities.erase(RemainingCities.begin() + chosen);
}
cout << endl;
//Save cost of ant_i, for elitist expansion
costs[ant_i] = pathCost(Colony[ant_i], Map);
}
i++;
}
}

That part is very suspicious :
for(int i = 0; i < Map.size(); ++i) // HERE IT CRASHES AT ANT NUMBER 55
cout << Map[0][i] << " ";
because i is the size of the map but you use it as an index in a probable string / vector, so you probably go out of the string/vector with an undefined behavior
probably you want
for(int i = 0; i < Map.size(); ++i)
cout << Map[i] << " ";
or
for(int i = 0; i < Map[0].size(); ++i)
cout << Map[0][i] << " ";
As I said in a remark at a moment RemainingCities[0] values -163172699 first in
cout << "Test: Operation: " << Map.at(Colony.at(ant_i).at(city_i-1)).at(RemainingCities.at(k)) << endl;
so is not a valid index in Map, but there is visible reason to have that looking at the code, so the reason is a probable write out of a vector destructing your memory elements.
To detect where I replaced all the [...] by .at(...) and the first error I have is in ACO at the line
costs.at(ant_i) = pathCost(Colony.at(ant_i), Map);
where ant_i values 52 while costs has 52 entries and Colony 260, so the error concerns costs
note that ant_i is set by the loop
for(int ant_i = 0; ant_i < num_ants; ++ant_i)
and in that case num_ants value 260 so much more than the size of costs which is defined as
vector<double> costs(cities.size(), 0);
but cost is just allocated and set but never read, so its goal is just to destruct the memory.
If I remove the two lines concerning it I do not have anymore an error and the program ends normally, there is no exception in a .at(...) and valgrind detect no error too.

Related

How can I print 2D arrays with four columns

I am struggling with printing an array with 4 rows and 4 columns, when I initialized the array and entered all the values. Then, I used for loop to get all the values together so I can print them. But I get is an array that companied all the values in one row.
I have attached the output when I run the code.
Here is a portion of my code, it is long code but I am struggling in specific part:
#include <iostream>
using namespace std;
int main()
{
cout << "The martix before I flipped it: " << endl;
cout << endl;
int array[4][4] = { 16,3,2,13,5,10,11,8,9,6,7,12,4,5,14,1 };
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
cout << array[i][j] << " ";
}
}
return 0;
The standard output utility std::cout is a stream from the stl and, as such, its << operator does not usually automagically append a linebreak.
Which is quite practical since, otherwise, you would not be able to print multiple numbers on a single line.
That being, said, you'll need to add the linebreak manually, like so :
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
std::cout << array[i][j] << " ";
}
std::cout << std::endl;
}
Alternatively, you can consider printing lines 4 at a time since your matrix is of constant size :
for (int i = 0; i < 4; i++) {
std::cout << array[i][0] << " "
<< array[i][1] << " "
<< array[i][2] << " "
<< array[i][3] << " " << std::endl;
}
Have a great day,

Two arrays, int and string, how do I display strings with corresponding ints?

#include <iostream>
#include <cmath>
using namespace std;
int main()
{
string iceCream[5] = {"vanilla", "butter pecan", "superman", "chocolate fudge", "strawberry"};
int iceCreamscoops[5];
int totalScoops = 0;
cout << "enter the total amount of scoops for each icecream flavor\n";
for (int i = 0; i < 5; ++i)
{
cin >> iceCreamscoops[i];
cout << "\n";
}
for (int i = 0; i < 5; ++i)
{
cout << iceCream[i] << " = " << iceCreamscoops[i] << " have been sold"
<< "\n";
totalScoops = totalScoops + iceCreamscoops[i];
}
cout << totalScoops << " total icecream scoops sold";
for (int i = 0; i < 5; ++i)
{
// Change < to > if you want to find the smallest element
if (iceCreamscoops[0] < iceCreamscoops[i])
iceCreamscoops[0] = iceCreamscoops[i];
}
cout << "\nMost popular flavor/flavors and scoops sold = " << iceCreamscoops[0];
for (int i = 0; i < 5; ++i)
{
if (iceCreamscoops[0] > iceCreamscoops[i])
iceCreamscoops[0] = iceCreamscoops[i];
}
cout << "\nLeast popular flavor/flavors and scoops sold = " << iceCreamscoops[0];
}
In the code above I need to display the ice cream that sold the most and least alongside its flavor. How do I display the string alongside the inputted value? I tried to compare the code by taking the found value and comparing it to the string array.
(You don't need to include cmath for what you're doing.)
It might be helpful to keep track of the greatest and least number of scoops as well as the index of each, instead of overwrite iceCreamScoops[0]. For example, we could create variables mostScoops + indexOfMostScoops and leastScoops + indexOfLeastScoops, as in the following:
#include <iostream>
using namespace std;
int main()
{
string iceCream[5] = {"vanilla", "butter pecan", "superman", "chocolate fudge", "strawberry "};
int iceCreamScoops[5];
int totalScoops = 0;
int mostScoops = -1, leastScoops = 1E6;
int indexOfMostScoops = -1, indexOfLeastScoops = -1;
cout << "Enter the total amount of scoops for each icecream flavor.\n";
for (int i = 0; i < 5; ++i)
{
cout << iceCream[i] << ": ";
cin >> iceCreamScoops[i];
totalScoops += iceCreamScoops[i];
if (iceCreamScoops[i] > mostScoops)
{
mostScoops = iceCreamScoops[i];
indexOfMostScoops = i;
}
if (iceCreamScoops[i] < leastScoops)
{
leastScoops = iceCreamScoops[i];
indexOfLeastScoops = i;
}
}
cout << "\nThe total number of scoops is " << totalScoops << ".\n";
cout << "The most popular flavor is " << iceCream[indexOfMostScoops] << " with " << mostScoops << " scoops.\n";
cout << "The least popular flavor is " << iceCream[indexOfLeastScoops] << " with " << leastScoops << " scoops.\n";
}
(Of course, you might want to add checks to make sure the user only inputs non negative integers as number of scoops.)
Edit:
If you want to identify all flavors with a specific number of scoops (e.g. the largest number of scoops), you don't even need to keep track of the indices. For example, you could just do something like:
cout << "\nThe greatest number of scoops is " << mostScoops << ".\n"
<< "The following flavors had this number of scoops:\n";
for (int i = 0; i < 5; i++)
{
if (iceCreamScoops[i] == mostScoops)
{
cout << " " << iceCream[i] << endl;
}
}
The basic idea to find a maximum value is to start off with a value that is smaller than any value expected (such as -1 scoops), and then update this maximum value each time we come across a value greater than the current maximum value.
Similarly, to find a minimum value, we can start off with a value that is greater than any expected value (such as 1E6 scoops), and then update this minimum value whenever we come across a smaller value.

C++ Hashing search function stuck in endless "else" and "while" loop

If the generated random number to look for does not exist in hashtable array, then programm gets stuck in endless loop in function void hashSearch(),
whereas it should just get out of the loop and output that search item is not found. The exact place in code is where these to outputs are:
cout << "stuck in else loop \n"; and cout << "stuck in while loop end \n";.
I've googled around, but can't find similar examples.
#include <iostream>
#include <stdlib.h> /* srand, rand */
#include <time.h> /* time */
#include <chrono>
using namespace std;
int arr [1000];
int arr2 [1000];
int randArrayInt, n, randSearchItem, searchInt, address, size2;
void printZeroArr();
void linearSentinelSearch();
void printHashArray();
void hashSearch();
int main ()
{
srand (time(nullptr)); //initialize random seed:
n = rand() % 900 + 100; //random integer number from 100 - 1000, length of the array
//n = rand() % 10; // random number in the range 1-10 for sanity tests, length of the array
//randSearchItem = rand() % 10 + 1;
randSearchItem = rand() % 900 + 100; //this is the number to search for
cout << "Array length is " << n << endl;
cout << "[";
for (int i = 0; i <= n; i++)
{
randArrayInt = rand() % 900 + 100;
//randArrayInt = rand() % 10 + 1; // generate random 1-10 number for for sanity tests
arr[i] = randArrayInt; // insert into array position the generated random number
cout<< " " << arr[i]; // print out array element at current loop position
}
cout << " ]\n" << endl;
printZeroArr();
}
void printZeroArr()
{
size2 = n + 1; //length of hashed array
cout << "This is the random key to search for in array: " << randSearchItem << endl;
cout << "This is the size2 length " << size2 << endl;
cout << "This is the hasharray with zeros" << endl;
cout << "[";
for (int i = 0; i <= size2; i++)
{
arr2[i] = 0; // insert into hasharray number 0
cout<< " " << arr2[i]; // print out hasharray element at current loop position
}
cout << " ]\n" << endl;
linearSentinelSearch();
}
void linearSentinelSearch()
{
auto start = std::chrono::high_resolution_clock::now();
arr[n + 1] = randSearchItem;
//cout << "testing arr[n + 1] is " << arr[n + 1] << endl;
int i = 0;
while (arr[i] != randSearchItem) i++;
if (i == n + 1)
cout << "Sentinel search did not found the searchitem in random array" << "\n" << endl;
else
cout << "Searchitem found in array with linearsearch at position " << i << "\n" << endl;
auto finish = std::chrono::high_resolution_clock::now();
chrono::duration<double> elapsed = finish - start;
cout << "Elapsed time: " << elapsed.count() << " s\n";
printHashArray();
}
void printHashArray()
{
//cout << "printing out 'address' value, or the modulo result: " << endl;
//cout << "[";
for (int i = 0; i <= n; i++)
{
address = arr[i] % size2;
//cout << " " << address;
while (arr2[address] != 0)
{
if (address == size2 - 1)
{
address = 0;
} else
{
address++;
}
}
arr2[address] = arr[i];
}
//cout << " ]\n" << endl;
cout << "This is the hasharray with hashitems" << endl;
cout << "[";
for (int i = 0; i <= size2; i++)
{
cout << " " << arr2[i];
}
cout << " ]\n" << endl; hashSearch();
}
void hashSearch()
{
auto start = std::chrono::high_resolution_clock::now();
int searchInt = randSearchItem % size2;
while ((arr2[searchInt] != 0) && (arr2[searchInt] != randSearchItem))
{
if (searchInt == size2 - 1)
{
searchInt = 0;
cout << "if loop \n";
}
else
{
searchInt++;
cout << " stuck in else loop \n";
}
cout << " stuck in while loop end \n";
}
if (searchInt == 0) {
cout << "Search item not found using hashSearch" << endl;
} else {
cout << "Search item " << randSearchItem << " found using hashSearch at position " << searchInt << " in arr2." << endl;
}
auto finish = std::chrono::high_resolution_clock::now();
chrono::duration<double> elapsed = finish - start;
cout << "Elapsed time: " << elapsed.count() << " s\n";
}
Whereas it should just get out of the loop and output that search item is not found.
Search for cout << " stuck in else loop \n"; and cout << " stuck in while loop end \n";.
You want to stop your loop when you hit the end of the array: To that effect, you set the item to search for to zero:
if (searchInt == size2 - 1)
{
searchInt = 0;
cout << "if loop \n";
}
But in the loop control, you don't test that. You only test the array element at the current index for zero (not found) or the item to search (found):
while ((arr2[searchInt] != 0) && (arr2[searchInt] != randSearchItem)) ...
You need an additional test:
while ((searchInt != 0) && ...) ...
It took me a while to see that you want to code an open-address hastable where a zero marks unused slots. The hash value is just the number itself. Using zero as indicator for an empty slot is not ideal: You cannot store numbers whose hash code modulo the table size is zero.
I'd also code this with a non-void function where the return value is the index or some unambiguous value meaning "not found", perhaps -1. (Alternatively, you can return a pointer to the found item or NULL if the item isn't found -- after all, the index in the hash array is part of the hash table's internals and non concern to the caller.)
Then you can use early returns:
int hashSearch(const int *arr2, int size2, int item)
{
int i = item % size2;
for (; i < size2; i++) {
if (arr2[i] == -1) break; // -1 indicated unused space
if (arr2[i] == item) return i; // return index of item
}
return -1; // not found!
}
But what do you do if there is no room for a further element when you have a hash code close to the array size? You will need to add extra space at the end or you'll need to wrap around. Perhaps that is what you wanted to achieve by setting the index back to zero. In your case, ther array is full, so there are no zeros that could serve as loop-breaking criterion. You will have to find another criterion. You could ensure that there are zeros by making the hash table 30% or so bigger than the number of entries. Or you could try to detect whether the index has come full circle to the original index.
As already pointed out to you in comments: Try to use function arguments and local variables rather than puttin everything into global space. Also, the chaining of function calls, where the last thing in a function is to call the next one is strange. It's probably better to put all sequential calls into main.

Memory leak when printing 2D array

I have memory leak when i print my 2D array, i looped in data from a vector into a vector called grid
Some indexes in Grid is null for example grid[8][8] is null, but grid[1][1] has a value of 3.
When i display indexes of grid with null value gives me a memory leak.
Below are my code, Any recommendations will be appreciated!
void populateAppendixB(vector<string> cityLocation, int **grid, int col, int row) {
vector<int> data = appendixB_data(cityLocation);
vector<string> appendixB_coordinates = getCoordinates(cityLocation);
vector<int> x_value = returncolValue(appendixB_coordinates);
vector<int> y_value = returnrowValue(appendixB_coordinates);
//loop data into grid[][]
for (int i = 0; i < x_value.size(); i++) {
grid[x_value[i]][y_value[i]] = data[i];
}
cout << " ";
//Top outer Grid
for (int i = 0; i < col + 2; i++) {
cout << " # ";
}
cout << " # ";
cout << endl;
//end
//y-axis
for (int j = row; j >= 0; --j) {
cout << " " << j << " # ";
for (int i = 0; i <= col; ++i) {
//displaying data
if(grid[i][j] == 0) {
cout << " ";
}
else {
cout << grid[i][j] << " ";
}
}
//Right outer Grid
cout << "#";
cout << endl;
}
//Last row of #
cout << " ";
for (int i = 0; i < col + 2; i++) {
cout << " # ";
}
cout << " # ";
cout << endl;
cout << " ";
//x-Axis
for (int i = 0; i <= col; i++) {
cout << i << " ";
}
cout << endl;
}
You use grid[x_value[i]][y_value[i]] = data[i];, but will not fill all of the grid since you only fill in one value of each column of grid (you only do this loop: for (int i = 0; i < x_value.size(); i++) {). Unless the grid passed in is pre-filled in with 0's properly (impossible to tell given your submitted code), then this is probably undefined behavior.
Even if it is a pre-filled in 2d array, when you print the elements of grid, you iterate from [0, cols] and [0, rows], which is likely not what you want (that iterates cols+1 columns and rows+1 rows. So, at least that last value will be accessing memory that is probably not valid.
As previous comments mention, it's a better idea to just use std::vector (e.g. std::vector<std::vector<int>> while using .at(i).at(j) to access elements which make use of C++ exceptions rather than accessing bad memory) or even std::array which are better at preventing and catching many issues cleanly. If you're worried about speed, it's probably not a huge deal and you can avoid copies by e.g. passing by reference, wrapping things in smart pointers if applicable, move semantics, etc.
I solved my problem by setting all my 2D array values to { }, then populate the grid array with the values that i want specifically.
It solves the memory leak problem but i am not sure if it is a good practice.

How can I get the array to show the previous list of array content before the next input?

I need the user input to be saved into my array and then output the array before the user inputs the next time. I have been moving things around different ways but cannot seem to get them to perform properly. I tried to cut down the code to the two functions I am having issues with.
void PlayGame()
{
const int HighestNum = 50;
const int LowestNum = 1;
int RandomNumber = LowestNum + rand() % HighestNum; //set for better random results
cout << "Guess the random number between " << LowestNum << " and " << HighestNum << "!\n\n";
const int attempts = 15;// limits the attempts to guess the random number to 15
int Guess [attempts] = {};
cout << "Enter your guess " << endl;
for (int count = 0; count < attempts; count++)
{
cin >> Guess[count];
int z = RandomNumber, y = Guess[count], r;
r = reviewGuess (z,y);//calling the function that determines the results
switch (r)//switch statement for function results, letting the user know if they matched the number, if the number is higher, or lower
{
case 0:
cout << "You Win!!" << endl;
cout << "\n";
cin.get();
return;
case 1:
cout << "The number is higher than your guess" << endl;
break;
case -1:
cout << "The number is lower than your guess" <<endl;
break;
}
if (count == 15)
{
cout << "Sorry, no guesses remain. The random number was... " << RandomNumber << "!";//so the user can see the random number at the end of their attempts
cout << "\n";
cin.get();
Again();
}
}
return;
}
int DisplayGuess(int member[])
{
for(int i = 0; i < 15; ++i)
cout << "\nGuess " << i + 1 << ": " << member[i];
cout << endl;
return;
}
Try this inside your loop
if(count > 0)
{
for (int j= 0; j < count; j++)
{
cout<<Guess[j];
}
}
Call DisplayGuess() in the first line of the for loop. Since the first you time you call it your array is empty, it shouldn't output anything.
So,
for (int count = 0; count < attempts; count++)
{
DisplayGuess(Guess[count]);
cin >> Guess[count];
int z = RandomNumber, y = Guess[count], r;
r = reviewGuess (z,y);//calling the function that determines the
results
. . . . . .