Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   Converting recursive algorithm to an iterative version (http://www.velocityreviews.com/forums/t806705-converting-recursive-algorithm-to-an-iterative-version.html)

Ania 12-07-2011 11:48 PM

Converting recursive algorithm to an iterative version
 
Hi,

Here is my problem:
I implemented recurive algorithm in c++ for a problem given below:

I have a list of items (only positive integers are allowed) and fixed
number of bins of identical capacity. I need to pack items (if
possible) so that elements in each bin sum up to given capacity.

I try to convert my recursive algorithm to an one. However, my
implementation with explicit stack doesn't work as I expected. I can't
pinpoint the place where I have made a mistake.

//items are sorted in decreasing order

Recursive:
bool backtrack(vector<int>& items, vector<Bin>& bins, unsigned
index,unsigned bin_capacity)
{
if (bin_capacity - items.front() < 0) return false;

if (index < items.size())
{
//try to put an item into all opened bins
for(unsigned i = 0; i < bins.size(); ++i)
{
if (bins[i].sum() + items[index] + items.back() <=
bin_capacity || bin_capacity - bins[i].sum() == items[index])
{
bins[i].add(items[index]);
return backtrack(items, bins, index + 1,
bin_capacity);

}
}
//put an item without exceeding maximum number of bins
if (bins.size() < BINS)
{
Bin new_bin = Bin();
bins.push_back(new_bin);
bins.back().add(items[index]);

return backtrack(items, bins, index + 1, bin_capacity);

}
}
else
{
//check if solution has been found
if (bins.size() == BINS )
{
for (unsigned i = 0; i <bins.size(); ++i)
{
packed_items.push_back(bins[i]);
}

return true;
}
}
return false;

}

Iterative( not working properly)
bool backtrack(vector<int>& items, vector<Bin>& bins, unsigned index,
unsigned bin_capacity)
{
stack<Node> stack;
Node node, child_node;
Bin new_bin;
//init the stack
node.bins.add(new_bin);
node.bins.back().add(items[item_index]);
stack.push(node);
item_index++;

while(!stack.empty())
{
node = stack.top();
stack.pop();

if (item_index < items.size())
{
if (node.bins.size() < BINS)
{
child_node = node;
Bin empty;
child_node.bins.add(empty);
child_node.bins.back().add(items[item_index]);
stack.push(child_node);
}

int last_index = node.bins.size() - 1;
for (unsigned i = 0; i <= last_index; i++)
{
if (node.bins[last_index - i]->get_sum()
+items[item_index]+ items.back( <=bin_capacity || bin_capacity -
node.bins[last_index - i]->get_sum() ==items[item_index])
{
child_node = node;
child_node.bins[last_index - i]-
>push_back(items[item_index]);


stack.push(child_node);
}
}
item_index++;
}
else
{
if (node.bins() == BINS)
{
//copy solution
bins = node.bins;
return true;
}
}
}
return false;

}

Any help would be highly appreciated.

Victor Bazarov 12-08-2011 01:59 PM

Re: Converting recursive algorithm to an iterative version
 
On 12/7/2011 6:48 PM, Ania wrote:
> Here is my problem:
> I implemented recurive algorithm in c++ for a problem given below:
>
> I have a list of items (only positive integers are allowed) and fixed
> number of bins of identical capacity. I need to pack items (if
> possible) so that elements in each bin sum up to given capacity.
>
> I try to convert my recursive algorithm to an one. However, my
> implementation with explicit stack doesn't work as I expected.


What does that mean? What did you expect? What does it do? Do you
think we should be guessing or dusting off our crystal ball?

> I can't
> pinpoint the place where I have made a mistake.


Have you tried using a "debugger" and step through your code? Do you
have a test case? Do you know what values of your objects need to be on
every step of your algorithm? If you do, just fire off that debugger
(whichever you got, all pretty much work when you know what you're
doing) and execute your test program step by step, and verify that the
values of the objects as they need to be. If they aren't make changes
to the code.

If you don't have a test case, get yourself one. If you don't know what
values of your objects should be at every point in your program... did
you actually write your program yourself? If you did, you should. Do
you know how to use a debugger? If you don't, it looks like it's time
to learn.

Bite the bullet and fix your own program. Otherwise, find a different
field to develop your skills.

V
--
I do not respond to top-posted replies, please don't ask

Nick Keighley 12-08-2011 02:30 PM

Re: Converting recursive algorithm to an iterative version
 
On Dec 7, 11:48*pm, Ania <anka.step...@gmail.com> wrote:
> Hi,
>
> Here is my problem:
> I implemented recurive algorithm in c++ for a problem given below:
>
> I have a list of items (only positive integers are allowed) and fixed
> number of bins of identical capacity. I need to pack items (if
> possible) so that elements in each bin sum up to given capacity.
>
> I try to convert my recursive algorithm to an one. However, my
> implementation with explicit stack doesn't work as I expected. I can't
> pinpoint the place where I have made a mistake.
>
> //items are sorted in decreasing order
>
> Recursive:
> bool backtrack(vector<int>& items, vector<Bin>& bins, unsigned
> index,unsigned bin_capacity)
> {
> * * if (bin_capacity - items.front() < 0) return false;
>
> * * if (index < items.size())
> * * {
> * * * * //try to put an item into all opened bins
> * * * * for(unsigned i = 0; i < bins.size(); ++i)
> * * * * {
> * * * * * * if (bins[i].sum() + items[index] + items.back() <=
> bin_capacity || bin_capacity - bins[i].sum() == items[index])
> * * * * * * {
> * * * * * * * * bins[i].add(items[index]);
> * * * * * * * * return backtrack(items, bins, index + 1,
> bin_capacity);
>
> * * * * * * }
> * * * * }
> * * * * //put an item without exceeding maximum number of bins
> * * * * if (bins.size() < BINS)
> * * * * {
> * * * * * * Bin new_bin = Bin();
> * * * * * * bins.push_back(new_bin);
> * * * * * * bins.back().add(items[index]);
>
> * * * * * * return backtrack(items, bins, index + 1, bin_capacity);
>
> * * * * }
> * * }
> * * else
> * * {
> * * * * //check if solution has been found
> * * * * if *(bins.size() == BINS )
> * * * * {
> * * * * * * for (unsigned i = 0; i <bins.size(); ++i)
> * * * * * * {
> * * * * * * * * packed_items.push_back(bins[i]);
> * * * * * * }
>
> * * * * * * return true;
> * * * * }
> * * }
> * * return false;
>
> }
>
> Iterative( not working properly)
> bool backtrack(vector<int>& items, vector<Bin>& bins, unsigned index,
> unsigned bin_capacity)
> {
> * * * stack<Node> stack;
> * * * Node node, child_node;
> * * * Bin new_bin;
> * * * //init the stack
> * * * node.bins.add(new_bin);
> * * * node.bins.back().add(items[item_index]);
> * * * stack.push(node);
> * * * item_index++;
>
> * * * while(!stack.empty())
> * * * {
> * * * * node = stack.top();
> * * * * stack.pop();
>
> * * * * if (item_index < items.size())
> * * * * {
> * * * * * * if (node.bins.size() < BINS)
> * * * * * * {
> * * * * * * * *child_node = node;
> * * * * * * * *Bin empty;
> * * * * * * * *child_node.bins.add(empty);
> * * * * * * * *child_node.bins.back().add(items[item_index]);
> * * * * * * * *stack.push(child_node);
> * * * * * * }
>
> * * * * * * int last_index = node.bins.size() - 1;
> * * * * * * for (unsigned i = 0; i <= last_index; i++)
> * * * * * * {
> * * * * * * * * if (node.bins[last_index - i]->get_sum()
> +items[item_index]+ items.back( <=bin_capacity || bin_capacity -
> node.bins[last_index - i]->get_sum() ==items[item_index])
> * * * * * * * *{
> * * * * * * * * * *child_node = node;
> * * * * * * * * * *child_node.bins[last_index - i]-
>
> >push_back(items[item_index]);

>
> * * * * * * * * * *stack.push(child_node);
> * * * * * * * * }
> * * * * * * }
> * * * * * * item_index++;
> * * * * * * }
> * * * * else
> * * * * {
> * * * * * *if (node.bins() == BINS)
> * * * * * *{
> * * * * * * * *//copy solution
> * * * * * * * *bins = node.bins;
> * * * * * * * *return true;
> * * * * * *}
> * * * *}
> * *}
> * * return false;
>
> }
>
> Any help would be highly appreciated.


build in some sort of trace facility. By seeing what gets called with
what parameters should enable you to compare the recursive with the
iterative and fix one or the other.

Why are you doing this?


Ania 12-08-2011 04:25 PM

Re: Converting recursive algorithm to an iterative version
 
@Nick Keighley I'm trying to implement an iterative version just
because of stack overflows for large datasets in recursive approach,

Thanks for your suggestions, I'll try to use debugger.


Larry Evans 12-08-2011 05:58 PM

Re: Converting recursive algorithm to an iterative version
 
On 12/07/11 17:48, Ania wrote:
[snip]
> I try to convert my recursive algorithm to an one. However, my
> implementation with explicit stack doesn't work as I expected. I can't
> pinpoint the place where I have made a mistake.

[snip]

In the iterative code, there's:

> int last_index = node.bins.size() - 1;
> for (unsigned i = 0; i <= last_index; i++)
> {
> if (node.bins[last_index - i]->get_sum()
> +items[item_index]+ items.back( <=bin_capacity || bin_capacity -
> node.bins[last_index - i]->get_sum() ==items[item_index])

This looks suspicious to me:

( <=bin_capacity

Are you sure you've posted code that compiles?

-regards,
Larry

Ania 12-08-2011 07:41 PM

Re: Converting recursive algorithm to an iterative version
 
On 8 Gru, 18:58, Larry Evans <cppljev...@suddenlink.net> wrote:
> On 12/07/11 17:48, Ania wrote:
> [snip]> I try to convert my recursive algorithm to an one. However, my
> > implementation with explicit stack doesn't work as I expected. I can't
> > pinpoint the place where I have made a mistake.

>
> [snip]
>
> In the iterative code, there's:
>
> > * * * * * * int last_index = node.bins.size() - 1;
> > * * * * * * for (unsigned i = 0; i <= last_index; i++)
> > * * * * * * {
> > * * * * * * * * if (node.bins[last_index - i]->get_sum()
> > +items[item_index]+ items.back( <=bin_capacity || bin_capacity -
> > node.bins[last_index - i]->get_sum() ==items[item_index])

>
> This looks suspicious to me:
>
> * ( <=bin_capacity
>
> Are you sure you've posted code that compiles?
>
> -regards,
> Larry


Finally, I found a place where I made a mistake. I messed with
pointers(shallow copies) and that was the main problem. Now it works
great.

Thanks for inspiring me.

I'm sorry but the code posted was not ready to compile, it was high
level pseudocode.
Here is code ready to compile (I don't use pointers here, just to make
it simpler).

class Bin
{
public:
Bin() { _sum = 0;}
int get_sum(){ return _sum; }
int size() {return bin.size(); }
bool isFull() { return _sum == bin.size(); }
void add(int item)
{
bin.push_back(item);
_sum += item;
}
//for testing output
void print(){
for(unsigned i = 0; i < bin.size(); ++i)
{
cout<< bin[i]<<endl;
}
}
private:
vector<unsigned> bin;
unsigned _sum;
};

struct Node
{
vector<Bin> bins;
};

BINS = 3; //just example value

bool backtrack(vector<unsigned>& items, vector<Bin>& bins, unsigned
index,unsigned bin_capacity)
{
if (bin_capacity - items.front() < 0) return false;

if (index < items.size())
{
//try to put an item into all opened bins
for(unsigned i = 0; i < bins.size(); ++i)
{
if (bins[i].get_sum() + items[index] + items.back() <=
bin_capacity || bin_capacity - bins[i].get_sum() == items[index])
{
bins[i].add(items[index]);
return backtrack(items, bins, index + 1,
bin_capacity);

}
}
//put an item without exceeding maximum number of bins
if (bins.size() < BINS)
{
Bin new_bin = Bin();
bins.push_back(new_bin);
bins.back().add(items[index]);

return backtrack(items, bins, index + 1, bin_capacity);

}
}
else
{
if (bins.size() == BINS )
{
return true;
}
}
return false;

}


bool backtrack2(vector<unsigned>& items, vector<Bin>& bins, unsigned
item_index, unsigned bin_capacity)
{
stack<Node> stack;
Node node, child_node;
Bin new_bin;
//init the stack
node.bins.push_back(new_bin);
node.bins.back().add(items[item_index]);
stack.push(node);
item_index++;

while(!stack.empty())
{
node = stack.top();
stack.pop();

if (item_index < items.size())
{
if (node.bins.size() < BINS)
{
child_node = node;
Bin empty;
child_node.bins.push_back(empty);
child_node.bins.back().add(items[item_index]);
stack.push(child_node);
}

int last_index = node.bins.size() - 1;
for (unsigned i = 0; i <= last_index; i++)
{
if (node.bins[last_index - i].get_sum()
+items[item_index]+ items.back() <=bin_capacity || bin_capacity -
node.bins[last_index - i].get_sum() ==items[item_index])
{
child_node = node;
child_node.bins[last_index -
i].add(items[item_index]);

stack.push(child_node);
}
}
item_index++;
}
else
{
if (node.bins.size() == BINS)
{
//copy solution
bins = node.bins;
return true;
}
}
}
return false;

}

Juha Nieminen 12-09-2011 06:41 AM

Re: Converting recursive algorithm to an iterative version
 
Ania <anka.stepien@gmail.com> wrote:
> I try to convert my recursive algorithm to an [iterative] one.


May I ask why?

I think that unless there's a good reason for that, this is a true case
of premature optimization (in the most negative sense). It is often the
case that if an algorithm is recursive in nature, trying to implement it
iteratively (especially if you need an explicit stack) only produces
significantly longer and more complicated code. If the amount of recursion
in the original algorithm is less-than-linear (eg. O(log n) recursions),
then any possible overhead caused by the recursive calls is insignificant.

Thus, in such a case, the iterative version will be longer, more
complicated and with little to no speed benefit. (Hence why it's true
premature optimization.)

88888 Dihedral 12-09-2011 08:51 PM

Re: Converting recursive algorithm to an iterative version
 
On Friday, December 9, 2011 2:41:12 PM UTC+8, Juha Nieminen wrote:
> Ania <anka.s...@gmail.com> wrote:
> > I try to convert my recursive algorithm to an [iterative] one.

>
> May I ask why?
>
> I think that unless there's a good reason for that, this is a true case
> of premature optimization (in the most negative sense). It is often the
> case that if an algorithm is recursive in nature, trying to implement it
> iteratively (especially if you need an explicit stack) only produces
> significantly longer and more complicated code. If the amount of recursion
> in the original algorithm is less-than-linear (eg. O(log n) recursions),
> then any possible overhead caused by the recursive calls is insignificant.
>
> Thus, in such a case, the iterative version will be longer, more
> complicated and with little to no speed benefit. (Hence why it's true
> premature optimization.)


If you are writing programs to be run infrequently for trivial jobs,
I have to say that in this kind of trivial cases there is no need for any optimization or improvement for this kind of programming.

But in my experience, codes fine-tued for speed requirements are not low paid
programmers' jobs in the industry.












Juha Nieminen 12-10-2011 09:54 AM

Re: Converting recursive algorithm to an iterative version
 
88888 Dihedral <dihedral88888@googlemail.com> wrote:
> If you are writing programs to be run infrequently for trivial jobs,
> I have to say that in this kind of trivial cases there is no need for any optimization or improvement for this kind of programming.


And my point is that *regardless* of where the code might be used,
converting a naturally recursive algorithm into an iterative form that
avoids the recursive function call is usually premature optimization of
the bad kind (makes the code significantly more complicated for little
to no benefit).

88888 Dihedral 12-10-2011 10:14 AM

Re: Converting recursive algorithm to an iterative version
 
On Saturday, December 10, 2011 5:54:32 PM UTC+8, Juha Nieminen wrote:
> 88888 Dihedral <dihedr...@googlemail.com> wrote:
> > If you are writing programs to be run infrequently for trivial jobs,
> > I have to say that in this kind of trivial cases there is no need for any optimization or improvement for this kind of programming.

>
> And my point is that *regardless* of where the code might be used,
> converting a naturally recursive algorithm into an iterative form that
> avoids the recursive function call is usually premature optimization of
> the bad kind (makes the code significantly more complicated for little
> to no benefit).


There are very limited cases for recursive functions to be used in C.
The quick sort in the c lib is notorious to be choked quite often.
Tree visiting of 30K nodes or less in C is too simple to be modified for speeds.



All times are GMT. The time now is 07:36 AM.

Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57