I'm looking for efficient memory allocation when dealing with recursive function. As far as I understand, variables I use in the function will remain allocated in memory until recursion is finished. Is there a way to avoid this as I believe this causes slow run of my code below where state variable is copied every time the function is called (correct me if I'm wrong as I'm new to C++).
#include <fstream>
#include <vector>
using namespace std;
int N = 30;
double MIN_COST = 1000000;
vector<int> MIN_CUT = {};
void minCut(vector<int> state, int index, int nodeValue) {
double currentCost;
if (index >= 0) {
currentCost = getCurrentCost(state); // some magic evaluating state cost
state.push_back(nodeValue);
if (currentCost >= MIN_COST) { // kill branch if incomplete solution is already worse than best achieved solution
return;
}
}
if (index == N - 1) { // check if leaf node
if (currentCost < MIN_COST) {
MIN_COST = currentCost;
MIN_CUT = state;
}
return;
}
minCut(state, index + 1, 1); // left subtree - adding 1 to vector
minCut(state, index + 1, 0); // right subtree - adding 0 to vector
return;
}
int main() {
vector<int> state = {};
minCut(state, -1, NULL);
cout << MIN_COST << "\n";
return 0;
}
Your algorithm is effectively building a tree of paths, but you're using a vector to hold the nodes for each path.
A
/ \
/ \
B C
/ \ / \
D E F G
This is the tree you're traversing.
But you're creating new vectors at every node, which contain the whole path up to that node. So as you're visiting node G, in your stack you have 3 vectors:
vector { A, C, G }
vector { A, C }
vector { A }
It should be clear how this is less efficient as you have noticed, but maybe seeing it this way hints at the correct efficient implementation.
The call stack itself holds the path to the root node. The stack when visiting G would be something like
minCut < visiting G >
minCut < visiting C >
minCut < visiting A >
In order to efficiently exploit this fact, make minCut pass the minimum amount of information. In this case we're talking about something linked-list like.
You have then two options that jump out:
Use vector, but:
Pass it by reference.
And you must then maintain it across calls, pushing and popping nodes to keep synchronized with the actual state.
Use an actual linked list. It should be easy to construct the vector by traversing pointers-to-parent-nodes.
Yes, there is a more efficient way to pass state through each function call. This is called passing by reference and can be achieved like so:
void minCut(vector<int>& state, int index, int nodeValue) { ...
This will result in the original state being referenced instead of copied each time the function is called.
For this to work correctly in the code you posted you will have to make some modifications, this is just the general concept.
Related
I am using an implementation of the IDDFS graph algorithm in a project and I noticed that for each node, the function takes around 8 - 10 seconds to compute. And, with a very large dataset with over 7000 nodes, it is proving to be the most cumbersome. So, I am trying to optimize my code so that it will run faster but all I have found so far is to change my function call by value parameters to being called by reference which has made a decent difference.
Are there any other ways I could fasten my code? I am compiling using c++11.
// Utility DFS function -- returns DFS Path if it exists, -1 if not exists
vector<int> dfs_util(vector<int> path, int target, vector<vector<int>> &adj_list, int depth)
{
int curr_node = path.back();
if (curr_node == target)
return path;
if (depth <= 0)
{
vector<int> tmp;
tmp.push_back(CUST_NULL);
return tmp;
}
for (auto child : adj_list[curr_node])
{
vector<int> new_path = path;
new_path.push_back(child);
vector<int> result = dfs_util(new_path, target, adj_list, depth - 1);
if (result.back() != CUST_NULL)
{
return result;
}
}
vector<int> tmp;
tmp.push_back(CUST_NULL);
return tmp;
}
// IDDFS Function -- returns IDDFS Path if it exists, -1 if not
vector<int> iddfs(vector<vector<int>> &adj_list, int src, int target, int max_depth = 2)
{
vector<int> result;
max_depth++;
for (int depth = 0; depth < max_depth; depth++)
{
vector<int> path;
path.push_back(src);
result = dfs_util(path, target, adj_list, depth);
if (result.back() == CUST_NULL || result.size() == 0)
continue;
int final_index = 0;
int idx_count = 0;
for (auto item : result)
{
if (item == src)
final_index = max(final_index, idx_count);
idx_count++;
}
result = vector<int>(result.begin() + final_index, result.end());
}
return result;
}
Here are few points to optimize your code:
The parameter vector<int> path is copied for no apparent reasons. You can pass it by reference.
vector<int> new_path = path; create a new copy of path. This is not needed: you can mutate path (passed by reference) so to add an element before the recursive call and remove it after. You can also reserve some space initially so to avoid re-allocations.
Returning a vector<int> in a recursive function is generally not a good idea in term of performance. This is especially true here since the function sometime ruen a vector of size 1 with CUST_NULL inside so to return a special code. This is very inefficient since std::vector will allocate some memory for that and memory allocations are expensive. You can instead return it by reference or play with std::optional so to return a special code without having to create a new non-empty vector. Note that the mutation-based solution is probably faster.
Be aware that push_back do some check to reallocate the target vector if needed. While this is simple and flexible, this is not actually needed for path since its maximum size is known not to be bigger than a threshold (depth +/- 1). You can fix its size to this threshold and fill it based on an index provided in the recursive function.
Using vector<vector<int>> is not efficient since each item of this data structure (of type vector<int>) are likely stored non-contiguously (they may with some luck due to the way low-level allocator works and depending on how your code fill them). It is more efficient to use a big flat vector<int> virtually split in some parts. The starting location of each part can be put in another vector<size_t> (with n+1 items). This makes the code a bit more complex though.
You can unroll/inline the function code when depth is 1 so to avoid many function calls in that case (and copies in your current code). This strategy is not guaranteed to be faster (though it often is) if the compiled function assembly code becomes huge or if this case never happen in practice (eg. to fit in CPU instruction cache).
So I was asked to write a function that changes array's values in a way that:
All of the values that are the smallest aren't changed
if, let's assume, the smallest number is 2 and there is no 3's and 4's then all 5's are changed for 3's etc.
for example, for an array = [2, 5, 7, 5] we would get [2, 3, 4, 3], which generalizes to getting a minimal value of an array which remains unchanged, and every other minimum (not including the first one) is changed depending on which minimum it is. On our example - 5 is the first minimum (besides 2), so it is 2 (first minimum) + 1 = 3, 7 is 2nd smallest after 2, so it is 2+2(as it is 2nd smallest).
I've come up with something like this:
int fillGaps(int arr[], size_t sz){
int min = *min_element(arr, arr+sz);
int w = 1;
for (int i = 0; i<sz; i++){
if (arr[i] == min) {continue;}
else{
int mini = *min_element(arr+i, arr+sz);
for (int j = 0; j<sz; j++){
if (arr[j] == mini){arr[j] = min+w;}
}
w++;}
}
return arr[sz-1];
}
However it works fine only for the 0th and 1st value, it doesnt affect any further items. Could anyone please help me with that?
I don't quite follow the logic of your function, so can't quite comment on that.
Here's how I interpret what needs to be done. Note that my example implementation is written to be as understandable as possible. There might be ways to make it faster.
Note that I'm also using an std::vector, to make things more readable and C++-like. You really shouldn't be passing raw pointers and sizes, that's super error prone. At the very least bundle them in a struct.
#include <algorithm>
#include <set>
#include <unordered_map>
#include <vector>
int fillGaps (std::vector<int> & data) {
// Make sure we don't have to worry about edge cases in the code below.
if (data.empty()) { return 0; }
/* The minimum number of times we need to loop over the data is two.
* First to check which values are in there, which lets us decide
* what each original value should be replaced with. Second to do the
* actual replacing.
*
* So let's trade some memory for speed and start by creating a lookup table.
* Each entry will map an existing value to its new value. Let's use the
* "define lambda and immediately invoke it" to make the scope of variables
* used to calculate all this as small as possible.
*/
auto const valueMapping = [&data] {
// Use an std::set so we get all unique values in sorted order.
std::set<int> values;
for (int e : data) { values.insert(e); }
std::unordered_map<int, int> result;
result.reserve(values.size());
// Map minimum value to itself, and increase replacement value by one for
// each subsequent value present in the data vector.
int replacement = *values.begin();
for (auto e : values) { result.emplace(e, replacement++); }
return result;
}();
// Now the actual algorithm is trivial: loop over the data and replace each
// element with its replacement value.
for (auto & e : data) { e = valueMapping.at(e); }
return data.back();
}
I am having two main issues implementing the algorithm described in this article in C++: properly terminating the algorithm and freeing up dynamically allocated memory without running into a seg fault.
Here is the pseudocode provided in the article:
RBFS (node: N, value: V, bound: B)
IF f(N)>B, return f(N)
IF N is a goal, EXIT algorithm
IF N has no children, RETURN infinity
FOR each child Ni of N,
IF f(N) < V AND f(Ni) < V THEN F[i] := V
ELSE F[i] := f(Ni)
sort Ni and F[i] in increasing order of F[i]
IF only one child, F[2] := infinity
WHILE (F[1] <= B)
F[1] := RBFS(N1, F[1], MIN(B, F[2]))
insert N1 and F[1] in sorted order
return F[1]
Here, f(Ni) refers to the "computed" function value, whereas F[i] refers to the currently stored value of f(Ni).
Here is my C++ implementation, in which I had to use a global variable to keep track of whether the goal had been reached or not (note, I am trying to maximize my f(n) value as opposed to minimizing, so I reversed inequalities, orders, min/max values, etc.):
bool goal_found = false;
bool state_cmp(FlowState *lhs, FlowState *rhs)
{
return (lhs->value > rhs->value);
}
int _rbfs(FlowState *state, int value, int bound)
{
if (state->value < bound) // Returning if the state value is less than bound
{
int value = state->value;
delete state;
return value;
}
if (state->is_goal()) // Check if the goal has been reached
{
cout << "Solved the puzzle!" << endl;
goal_found = true; // Modify the global variable to exit the recursion
return state->value;
}
vector<FlowState*> children = state->children();
if (children.empty())
{
//delete state; // Deleting this state seems to result in a corrupted state elsewhere
return INT_MIN;
}
int n = 0; // Count the number of children
for (const auto& child: children)
{
if (state->value < value && child->value < value)
child->value = value;
else
child->update_value(); // Equivalent of setting stored value to static value (F[i] := f(Ni))
++n;
}
sort(children.begin(), children.end(), state_cmp);
while (children.front()->value >= bound && !goal_found)
{// Loop depends on the global goal_found variable since this is where the recursive calls happen
if (children.size() < 2)
children.front()->set_value(_rbfs(children.front(), children.front()->value, bound));
else
children.front()->set_value(_rbfs(children.front(), children.front()->value, max(children[1]->value, bound)));
}
// Free children except the front
int i;
for (i = 1; i < n; ++i)
delete children[i];
state->child = children.front(); // Records the path
return state->child->value;
}
void rbfs(FlowState* initial_state)
{
// This is the actual function I invoke to call the algorithm
_rbfs(initial_state, initial_state->get_value(), INT_MIN);
print_path(initial_state);
}
My main questions are:
Is there a way to terminate this function than having to use a global variable (bool goal_reached) without a complete re-implementation? Recursive algorithms usually have some kind of base-case to terminate the function, but I am not seeing an obvious way of doing that.
I can't seem to delete the dead-end state (when the state has no children) without running into a segmentation fault, but not deleting it results in unfreed memory (each state object was dynamically allocated). How can I modify this code to ensure that I've freed all of the states that pass through it?
I ran the program with gdb to see what was going on, and it appears that after deleting the dead-end state, the next state that is recursively called is not actually NULL, but appears to be corrupted. It has an address, but the data it contains is all junk. Not deleting that node lets the program terminate just fine, but then many states aren't getting freed. In addition, I had originally used the classical, iterative best-first search (but it takes up far too much memory for my case, and is much slower), and in that case, all dynamically allocated states were properly freed so the issue is in this code somewhere (and yes, I am freeing each of the states on the path in main() after calling rbfs).
In your code, you have
children.front()->set_value(_rbfs(children.front(), ...
where state inside of _rbfs is thus children.front().
And in _rbfs, you sometimes delete state. So children.front() can be deleted and then called with ->set_value. There's your problem.
Is there any reason why you calling delete at all?
Working on below problem as an algorithm puzzle. Referred a few similar solutions (and post one of them below), tried and they worked. The question is, for the line "swap(num[i], num[k]);", how do we ensure we could always swap to a number which never tried before (e.g. suppose we swap 1 with 2 in current iteration of the for loop, then it is possible later we swap 2 back with 1 in next iterations of the same for loop of the same level/layer of recursive call)? I have the confusion since we pass num by reference, and it is very possible later (lower level/layer) recursive calls modify content of num, which cause numbers we already evaluated swap back. However, I tried and it works for all of my test cases. Wondering if below solution is 100% correct, or happened to pass my test cases? :)
Here are detailed problem statement and code I am debugging,
Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2] have the following unique permutations:
[1,1,2], [1,2,1], and [2,1,1]
class Solution {
public:
void recursion(vector<int> num, int i, int j, vector<vector<int> > &res) {
if (i == j-1) {
res.push_back(num);
return;
}
for (int k = i; k < j; k++) {
if (i != k && num[i] == num[k]) continue;
swap(num[i], num[k]);
recursion(num, i+1, j, res);
}
}
vector<vector<int> > permuteUnique(vector<int> &num) {
sort(num.begin(), num.end());
vector<vector<int> >res;
recursion(num, 0, num.size(), res);
return res;
}
};
thanks in advance,
Lin
As #notmyfriend said in the comments, num is actually copied each function call.
So now it boils down to:
Of all array values, select one to be the first one and place it there.
That in a loop for each value one time, and then recursively:
Of all values after the first one, select one to be the first and place it there...
...and so on, combined with a check to filter out swaps where nothing changes, ie. filter out duplicates.
If num were a real reference, it won't work anymore (at least not without additional steps).
Eg. 1 1 2 is an easy conterexample, it would give the results:
112, 121, 211, 112, 121
ie. there are duplicates despite the check (and probably there
are examples where some permutations are not generated at all, too).
About the comment:
Per default, every normal function parameter in C++ is copied
(normal = without explicit reference symbol '&' etc.).
Maybe you're thinking of C-style arrays: Essentially, what is passed there is a pointer (to the first value). The pointer is copied, but both original and copied pointer point to the same memory location.
While the purpose of std::vector is (too) to contain an array, the vector itself is a single class object (which contains a pointer to the values somewhere). A class can define itself how it should be copied (with a copy constructor).
Technically, the vector class could implement copying as pointer copying, then it would have the same effect as passing the whole vector as reference; but the C++ creators wanted to keep the copy semantics, ie. that copying a container class should make a real copy with all values duplicated.
For non-copying, there are references already...
Below you can find a solution written in Java. Sorry for not providing a solution in C++, I'm not using it for a long time. But the syntax would be similar.
Solution is using Backtracking (https://en.wikipedia.org/wiki/Backtracking)
Also I'm using hashset to check uniqueness, may be there is a solution which does not use any hashset type data structure, becase my solution is using extra memory in order to provide unique solutions.
Sample input and output;
input : [1, 1, 2]
output : [1, 1, 2]
[1, 2, 1]
[2, 1, 1]
And the solution is;
public class permutation {
public static void main(String[] args) {
permutation p = new permutation();
p.permute(new int[] { 1, 1, 2 });
}
HashSet<String> set = new HashSet<String>();
private void permute(int[] arr) {
set.clear();
this.permute(arr, 0, arr.length - 1);
}
private void permute(int[] arr, int l, int r) {
if (l == r) {
String key = Arrays.toString(arr);
if (set.contains(key))
return;
set.add(key);
System.out.println(key);
} else {
for (int i = l; i <= r; i++) {
swap(arr, l, i);
permute(arr, l + 1, r);
swap(arr, i, l);
}
}
}
private void swap(int[] arr, int l, int r) {
int tmp = arr[l];
arr[l] = arr[r];
arr[r] = tmp;
}
}
I've developed a method called "rotate" to my stack object class. What I did was that if the stack contains elements: {0,2,3,4,5,6,7} I would needed to rotate the elements forwards and backwards.
Where if i need to rotate forwards by 2 elements, then we would have, {3,4,5,6,7,0,2} in the array. And if I need to rotate backwards, or -3 elements, then, looking at the original array it would be, {5,6,7,0,2,3,4}
So the method that I have developed works fine. Its just terribly ineffecient IMO. I was wondering if I could wrap the array around by using the mod operator? Or if their is useless code hangin' around that I havent realized yet, and so on.
I guess my question is, How can i simplify this method? e.g. using less code. :-)
void stack::rotate(int r)
{
int i = 0;
while ( r > 0 ) // rotate postively.
{
front.n = items[top+1].n;
for ( int j = 0; j < bottom; j++ )
{
items[j] = items[j+1];
}
items[count-1].n = front.n;
r--;
}
while ( r < 0 ) // rotate negatively.
{
if ( i == top+1 )
{
front.n = items[top+1].n;
items[top+1].n = items[count-1].n; // switch last with first
}
back.n = items[++i].n; // second element is the new back
items[i].n = front.n;
if ( i == bottom )
{
items[count-1].n = front.n; // last is first
i = 0;
r++;
continue;
}
else
{
front.n = items[++i].n;
items[i].n = back.n;
if ( i == bottom )
{
i = 0;
r++;
continue;
}
}
}
}
Instead of moving all the items in your stack, you could change the definition of 'beginning'. Have an index that represents the first item in the stack, 0 at the start, which you add to and subtract from using modular arithmetic whenever you want to rotate your stack.
Note that if you take this approach you shouldn't give users of your class access to the underlying array (not that you really should anyway...).
Well, as this is an abstraction around an array, you can store the "zero" index as a member of the abstraction, and index into the array based on this abstract notion of the first element. Roughly...
class WrappedArray
{
int length;
int first;
T *array;
T get(int index)
{
return array[(first + index) % length];
}
int rotateForwards()
{
first++;
if (first == length)
first = 0;
}
}
You've gotten a couple of reasonable answers, already, but perhaps one more won't hurt. My first reaction would be to make your stack a wrapper around an std::deque, in which case moving an element from one end to the other is cheap (O(1)).
What you are after here is a circular list.
If you insist on storing items in an array just use top offset and size for access. This approach makes inserting elements after you reached allocated size expensive though (re-allocation, copying). This can be solved by using doubly-linked list (ala std::list) and an iterator, but arbitrary access into the stack will be O(n).
The function rotate below is based on reminders (do you mean this under the 'mod' operation?)
It is also quite efficient.
// Helper function.
// Finds GCD.
// See http://en.wikipedia.org/wiki/Euclidean_algorithm#Implementations
int gcd(int a, int b) {return b == 0 ? a : gcd(b, a % b);}
// Number of assignments of elements in algo is
// equal to (items.size() + gcd(items.size(),r)).
void rotate(std::vector<int>& items, int r) {
int size = (int)items.size();
if (size <= 1) return; // nothing to do
r = (r % size + size) % size; // fits r into [0..size)
int num_cycles = gcd(size, r);
for (int first_index = 0; first_index < num_cycles; ++first_index) {
int mem = items[first_index]; // assignment of items elements
int index = (first_index + r) % size, index_prev = first_index;
while (index != first_index) {
items[index_prev] = items[index]; // assignment of items elements
index_prev = index;
index = (index + r) % size;
};
items[index_prev] = mem; // assignment of items elements
}
}
Of course if it is appropriate for you to change data structure as described in other answers, you can obtain more efficient solution.
And now, the usual "it's already in Boost" answer: There is a Boost.CircularBuffer
If for some reason you'd prefer to perform actual physical rotation of array elements, you might find several alternative solutions in "Programming Pearls" by Jon Bentley (Column 2, 2.3 The Power of Primitives). Actually a Web search for Rotating Algorithms 'Programming Pearls' will tell you everything. The literal approach you are using now has very little practical value.
If you'd prefer to try to solve it yourself, it might help to try looking at the problem differently. You see, "rotating an array" is really the same thing as "swapping two unequal parts of an array". Thinking about this problem in the latter terms might lead you to new solutions :)
For example,
Reversal Approach. Reverse the order of the elements in the entire array. Then reverse the two parts independently. You are done.
For example, let's say we want to rotate abcdefg right by 2
abcdefg -> reverse the whole -> gfedcba -> reverse the two parts -> fgabcde
P.S. Slides for that chapter of "Programming Pearls". Note that in Bentley's experiments the above algorithm proves to be quite efficient (among the three tested).
I don't understand what the variables front and back mean, and why you need .n. Anyway, this is the shortest code I know to rotate the elements of an array, which can also be found in Bentley's book.
#include <algorithm>
std::reverse(array , array + r );
std::reverse(array + r, array + size);
std::reverse(array , array + size);