C++ vector initialise a vector of agents for a genetic algorithm - c++

I have the following C++ code, but I get some errors in mainly stuff like the following (after the block of code) the Agent is just a class that I created in a seperate file
vector<Agent> population;
for (vector<int>::iterator i = population.begin(); i != population.end(); ++i) {
population.push_back(new Agent(generateDna(targetString.size())));
}
I get the following errors
no suitable user-defined conversion from "__gnu_cxx::__normal_iterator>>" to "__gnu_cxx::__normal_iterator>>" exists
2.no operator "!=" matches these operands -- operand types are: __gnu_cxx::__normal_iterator>> != __gnu_cxx::__normal_iterator>>
3.no instance of overloaded function "std::vector<_Tp, _Alloc>::push_back [with _Tp=Agent, _Alloc=std::allocator]" matches the argument list -- argument types are: (Agent *) -- object type is: std::vector>
and I'm new to c++ so these things might be self explanatory, but I don't know what they mean.

The main problem is that you are iterating over collection in which you append during the cycle and even through iterator which is defined as int instead of Agent. Create new vector and push your generated values into this new vector.
Also be aware of using new keyword. You must dealocate that memory later.
Solution:
vector<Agent> population;
vector<Agent> newPopulation;
for (vector<Agent>::iterator i = population.begin(); i != population.end(); ++i) {
newPopulation.push_back(Agent(generateDna(targetString.size())));
}

Your current compilation issue is that you're trying to store a std::vector<Agent>::iterator into a std::vector<int>::iterator. These are two completely different types.
Then there's your runtime issue (after you actually add elements to your container because right now you have none), your iterators might be invalidated after a push_back and you'll have UB because you're modifying the container while you're looping over it.
Then there's the issue where you're trying to store an Agent* into a vector of Agent's.
All in all:
std::vector<Agent> population;
//fill your vector.. otherwise loop is useless because size is 0..
auto size = population.size();
for (unsigned int i = 0; i < size; ++i) {
population.push_back(Agent(generateDna(targetString.size())));
}

Related

How to copy a set of object to an array of object?

I have to copy the first size element from a set of Solution (a class) named population to an array of solution named parents. I have some problems with iterators because i should do an hybrid solution between a normal for loop
and a for with iterators. The idea is this: when I'm at the ith iteration of the for I declare a new iterator that's pointing the beginning
of population, then I advance this iterator to the ith position, I take this solution element and I copy into parents[i]
Solution* parents; //it is filled somewhere else
std::set<Solution> population; //it is filled somewhere else
for (int i = 0; i < size; i++) {
auto it = population.begin();
advance(it, i);
parents[i] = *it;
}
Two error messages popup with this sentence: 'Expression: cannot dereference end map/set iterator'
and 'Expression: cannot advance end map/set iterator'
Any idea on how to this trick? I know it's kinda bad mixing array and set, i should use vector instead of array?
You use std::copy_n.
#include <algorithm>
extern Solution* parents; //it is filled somewhere else
extern std::set<Solution> population; //it is filled somewhere else
std::copy_n(population.begin(), size, parents);
It seems like size may be incorrectly set. To ensure that your code behaves as expected, you should just use the collection's size directly:
auto it = population.begin();
for (int i = 0; i < population.size(); i++) {
parents[i] = *it;
++it;
}
This can also be solved with a much simpler expression:
std::copy(population.begin(), population.end(), parents);
I have to copy the first size element from a set [..] to an array
You can use std::copy_n.
for (int i = 0; i < size; i++) {
auto it = population.begin();
advance(it, i);
The problem with this is that you're iterating over the linked list in every iteration. This turns the copy operation from normally linear complexity to quadratic.
Expression: cannot dereference end map/set iterator'
The problem here appears to be that your set doesn't contain at least size number of elements. You cannot copy size number of elements if there aren't that many. I suggest that you would copy less elements when the set is smaller.
i should use vector instead of array?
Probably. Is the array very large? Is the size of the vector not known at compile time? If so, use a vector.

Segmentation fault: 11 c++ when using vector

i am trying to write a program for my university project the program is supposed to do first come first serve scheduling i have thought a lot about this function but i don't know how to make it work, i always get Segmentation fault: 11, i also tried to use temp.at(j) but it gave me Segmentation fault: 6, and i tried to minimise the vector so it would be in-bound by declaring the vectors outside the function, then use temp.size() instead of Processes but it also did't work.
void FCFS(Process ProcessDetails[], int Processes)
{
vector<int> temp;
vector<int> temp1;
int first = 0; //first value to compare with.
for(int j = 0; j < Processes; j++){ // to make sure that it passes through all elements.
for(int i = 0; i < Processes; i++){ // pass each PID and Burst time to vector temp and temp1.
if(ProcessDetails[i].ArrivalTime == first){
temp.operator[](j) = ProcessDetails[i].PID;
temp1.operator[](j) = ProcessDetails[i].BurstTime;
}
}
first++;// increase first value to declare the round is finished and start a new one.
}
for(int i = 0; i < Processes; i++){ // pass the sorted vector values back to the arrays.
ProcessDetails[i].PID = temp.operator[](i);
ProcessDetails[i].BurstTime = temp1.operator[](i);
}
}
the program works fine until it reaches this function, please help.
The behaviour of a vector's operator[]() is undefined if it is used to access elements that do not exist.
Since you have used default-constructed vectors, their size is zero - so they have no elements to access.
If you use the .at() member function, it will check the index and throw an exception (of type std::out_of_range, which is declared in the standard header <stdexcept>) when indices are invalid. You can confirm that by wrapping the code in an appropriate try/catch block.
To eliminate the problem, you need to reize the vector (e.g. add elements to it using push_back(), resize it using resize(), etc) before using operator[](). And ensure the index is valid, since operator[]() does not resize a std::vector.
Also, temp[j] is equivalent to temp.operator[](j). For types that supply an operator[]() function, the compiler handles turning expressions like temp[j] into a call of temp.operator[](j).
Your vectors have no elements.
Using the vector operator[] will therefore fail.
Use push_back, emplace, resize, or some other function to add elements to the vectors.
you will have to change your vector assignment to
if(ProcessDetails[i].ArrivalTime == first){
temp.push_back(ProcessDetails[i].PID);
temp1.push_back(ProcessDetails[i].BurstTime);
}

Adding elements to a vector from an array of pointers in C++

I've been trying to use an array of pointers to point to vectors, which I have so far been able to implement, however, in trying to add an element to one of the sub-vectors, I repeatedly get an unknown error on run-time.
I have previously defined my array as so:
std::vector<std::string> *frequency_table[10000];
I then try to add an element to a specific one of the vectors. This is the line that causes the run-time error.
frequency_table[index]->push_back(value);
Any ideas?
At first glance the problem looks like you haven't allocated any memory for the pointer so it has nowhere to push the value to. Though i can't be sure without the error message.
If that is the case however you would need to use new to allocate the memory
Your approach involves mixing vectors (and vectors are a good thing) and C-style arrays of pointers to objects (which betrays a mix-up since there are already vectors in your code).
If you want 10000 vectors of vectors of string, then just write
std::vector<std::vector<std::string> > frequency_table(10000);
. . .
frequency_table[index].push_back(value);
The first line declares a vector, each element of which is a vector<string>, allocates 10000 elements to it and initializes each element.
Using the input from you guys, I realized that my problem was the vectors were not being initialized, so I added this loop before the loop in which I populate the vectors, and it works now:
for(int i = 0; i < 5000; ++i)
{
frequency_table[i] = new std::vector<std::string>;
}
The final code looks like this:
for(int i = 0; i < 5000; ++i)
{
frequency_table[i] = new std::vector<std::string>;
}
for(auto itr = frequency_map.begin(); itr != frequency_map.end(); ++itr)
{
std::string key = itr->first;
double value = itr->second;
frequency_table[(int)value]->push_back(key);
}
Thanks all!
ps I halved the 10000 for testing purposes

How can I make my dynamic array or vector operate at a similar speed to a standard array? C++

I'm still quite inexperienced in C++ and i'm trying to write sum code to add numbers precisely. This is a dll plugin for some finite difference software and the code is called several million times during a run. I want to write a function where any number of arguments can be passed in and the sum will be returned. My code looks like:
#include <cstdarg>
double SumFunction(int numArgs, ...){ // this allows me to pass any number
// of arguments to my function.
va_list args;
va_start(args,numArgs); //necessary prerequisites for using cstdarg
double myarray[10];
for (int i = 0; i < numArgs; i++) {
myarray[i] = va_arg(args,double);
} // I imagine this is sloppy code; however i cannot create
// myarray{numArgs] because numArgs is not a const int.
sum(myarray); // The actual method of addition is not relevant here, but
//for more complicated methods, I need to put the summation
// terms in a list.
vector<double> vec(numArgs); // instead, place all values in a vector
for (int i = 0; i < numArgs; i++) {
vec.at(i) = va_arg(args,double);
}
sum(vec); //This would be passed by reference, of course. The function sum
// doesn't actually exist, it would all be contained within the
// current function. This is method is twice as slow as placing
//all the values in the static array.
double *vec;
vec = new double[numArgs];
for (int i = 0; i < (numArgs); i++) {
vec[i] = va_arg(args,double);
}
sum(vec); // Again half of the speed of using a standard array and
// increasing in magnitude for every extra dynamic array!
delete[] vec;
va_end(args);
}
So the problem I have is that using an oversized static array is sloppy programming, but using either a vector or a dynamic array slows the program down considerably. So I really don't know what to do. Can anyone help, please?
One way to speed the code up (at the cost of making it more complicated) is to reuse a dynamic array or vector between calls, then you will avoid incurring the overhead of memory allocation and deallocation each time you call the function.
For example declare these variables outside your function either as global variables or as member variables inside some class. I'll just make them globals for ease of explanation:
double* sumArray = NULL;
int sumArraySize = 0;
In your SumFunction, check if the array exists and if not allocate it, and resize if necessary:
double SumFunction(int numArgs, ...){ // this allows me to pass any number
// of arguments to my function.
va_list args;
va_start(args,numArgs); //necessary prerequisites for using cstdarg
// if the array has already been allocated, check if it is large enough and delete if not:
if((sumArray != NULL) && (numArgs > sumArraySize))
{
delete[] sumArray;
sumArray = NULL;
}
// allocate the array, but only if necessary:
if(sumArray == NULL)
{
sumArray = new double[numArgs];
sumArraySize = numArgs;
}
double *vec = sumArray; // set to your array, reusable between calls
for (int i = 0; i < (numArgs); i++) {
vec[i] = va_arg(args,double);
}
sum(vec, numArgs); // you will need to pass the array size
va_end(args);
// note no array deallocation
}
The catch is that you need to remember to deallocate the array at some point by calling a function similar to this (like I said, you pay for speed with extra complexity):
void freeSumArray()
{
if(sumArray != NULL)
{
delete[] sumArray;
sumArray = NULL;
sumArraySize = 0;
}
}
You can take a similar (and simpler/cleaner) approach with a vector, allocate it the first time if it doesn't already exist, or call resize() on it with numArgs if it does.
When using a std::vector the optimizer must consider that relocation is possible and this introduces an extra indirection.
In other words the code for
v[index] += value;
where v is for example a std::vector<int> is expanded to
int *p = v._begin + index;
*p += value;
i.e. from vector you need first to get the field _begin (that contains where the content starts in memory), then apply the index, and then dereference to get the value and mutate it.
If the code performing the computation on the elements of the vector in a loop calls any unknown non-inlined code, the optimizer is forced to assume that unknown code may mutate the _begin field of the vector and this will require doing the two-steps indirection for each element.
(NOTE: that the vector is passed with a cost std::vector<T>& reference is totally irrelevant: a const reference doesn't mean that the vector is const but simply puts a limitation on what operations are permitted using that reference; external code could have a non-const reference to access the vector and constness can also be legally casted away... constness of references is basically ignored by the optimizer).
One way to remove this extra lookup (if you know that the vector is not being resized during the computation) is to cache this address in a local and use that instead of the vector operator [] to access the element:
int *p = &v[0];
for (int i=0,n=v.size(); i<n; i++) {
/// use p[i] instead of v[i]
}
This will generate code that is almost as efficient as a static array because, given that the address of p is not published, nothing in the body of the loop can change it and the value p can be assumed constant (something that cannot be done for v._begin as the optimizer cannot know if someone else knows the address of _begin).
I'm saying "almost" because a static array only requires indexing, while using a dynamically allocated area requires "base + indexing" access; most CPUs however provide this kind of memory access at no extra cost. Moreover if you're processing elements in sequence the indexing addressing becomes just a sequential memory access but only if you can assume the start address constant (i.e. not in the case of std::vector<T>::operator[]).
Assuming that the "max storage ever needed" is in the order of 10-50, I'd say using a local array is perfectly fine.
Using vector<T> will use 3 * sizeof(*T) (at least) to track the contents of the vector. So if we compare that to an array of double arr[10];, then that's 7 elements more on the stack of equal size (or 8.5 in 32-bit build). But you also need a call to new, which takes a size argument. So that takes up AT LEAST one, more likely 2-3 elements of stackspace, and the implementation of new is quite possibly not straightforward, so further calls are needed, which take up further stack-space.
If you "don't know" the number of elements, and need to cope with quite large numbers of elements, then using a hybrid solution, where you have a small stack-based local array, and if numargs > small_size use vector, and then pass vec.data() to the function sum.

Dereferencing iterator (c++)

I have problem with dereferencing result of operation that returns non-pointer value.
In this map i have pointers to matrixes
map<string, GeneralMatrix*> matrixes;
and this is how operations with matrixes look like
GeneralMatrix & add(const GeneralMatrix & m2) {
//Check for compatible matrixes
if (height != m2.height || width != m2.width) {
cout << "Matrix sizes must match!" << endl;
return *this;
}
//Create new empty matrix
GeneralMatrix &m3 = createNew(width, m2.height);
//Set every number to sum of this and given matrix
for (int i = 0; i < height; i++) {
for (int j = 0; j < m2.width; j++) {
double val = m2.get(i, j);
if (val != 0) {
val += get(i, j);
m3.set(i, j, val);
}
}
}
return m3;
}
As you can see, add method returns non-pointer matrix that i want to insert into my map.
This is what I tried:
map<string, GeneralMatrix *>::iterator itop1 , itop2;
//now seting iterators to their position
//there is the problem
matrixes.insert(pair<string, GeneralMatrix *>(result, (*itop1->second->add(*itop2->second))));
Problem is that i cant find out how to insert second parameter of pair. It alway ends with error because of different types.
Attempt n1:
itop1->second->add(itop2->second)
Add method needs pointer
Attempt n2:
itop1->second->add(*itop2->second)
Result is non-pointer, needs to be pointer
Attemp n3:
(*itop1->second->add(*itop2->second))
main.cpp:611:68: error: no match for ‘operator*’ (operand type is ‘GeneralMatrix’)
How to derefence result then ?
Ideally you would change matrixes to type map<string, GeneralMatrix>.
Alternatively you could keep an std::list<GeneralMatrix> that stores the matrices and you give a pointer to the matrix inside the list.
It is considered bad style to have naked pointers. Pointers should instead tell the ownership status they have over the item, such as unique_ptr, shared_ptr or weak_ptr. That would also take care of memory management.
If your class is well behaved and the map holds owning pointers you could do something like this:
matrixes.insert(std::make_pair(std::string("name"), new GeneralMatrix(std::move(m)));
Where m is the matrix you are trying to move into the map.
If the pointers in the map do not own the pointers you can just insert the address of the map with &m, but that requires you to store the matrix somewhere persistent such as the list shown above.
Edit:
Your specific problem with the iterator can be solved like this:
matrixes.insert(pair<string, GeneralMatrix *>(result, &(*itop1)));
A quick solution to your problem is:
GeneralMatrix& m3= add(m2);
matrixes["string"] = &m3;
matrixes.insert(std::make_pair(std::string("name"), (&m3)));
matrixes.insert(std::make_pair<std::string, GeneralMatrix*>("name", &m3));
They are basically both equivalent in this case, however operator[] will always insert a value in the map, even if the right hand operator is null.
For example:
matrixes["s"];
will insert an empty pointer
Your code however has several problems:
first, why do you need to return a reference from the method createNew?
Just return a value to a new matrix. You don't gain anything doing this.
GeneralMatrix createNew(width, m2.height);
As suggested in another answer, have a map of string to unique_pointers instead of using raw pointers and/or leverage move semantics.
In your case, since an "add" operation will always result in creating a new matrix, I wouldn't even bother dealing with pointers, as they give you no real advantage
Here you can find some stripped down code that will fit your needs:
std::map<std::string, GeneralMatrix> matrixes;
GeneralMatrix add(const GeneralMatrix& m2)
{
//Create new empty matrix
auto m3 = createNew(width, m2.height);
return m3;
}
Note also that this code will be optimized by your compiled, using something called NRVO (named return valueoptimization), and it will likely be faster that your previous one that dealt with dynamic allocation in the createNew method).
Now, if General matrix implements correctly the rvalue copy constructor you can move it to your map
map.insert(std::string("string"), std::move<m3>);
or you can just emplace it (not yet implemented by all compilers)
map.emplace(std::make_pair(std::string("string"), createNew(m2)));
If you need polymorphism, just use a factory method that returns a base std::unique_ptr.
std::unique_ptr<GeneralMatrix> createNew(width, m2.height);