views:

200

answers:

8

Is there any way in C/C++ to stop a backtracking algorithm after finding the first solution without exiting the program.

I want my function to immediately exit the function,not to quit every level of recurrsion one by one stating return.

A: 

It actually depends on your implementation, but you could set some special param and use it as a flag like "Did we get a solution? If yes, then abort your current routine and get only that solution to the output".

Kotti
how do you abort the routine,If you state 'return' it will only exit the current recursive level
John Retallack
Adding something like `if (flag == exit_flag) return` would recursively exit from every recusion level if the flag is set to exit flag. Just find an approach to your algorithm implementation.
Kotti
yes ,but that would exit one level at a time till I reach the first level.Im interested in exiting the recursion immediately after I find a solution not exiting every level until I am the first.
John Retallack
Then the approach with exception would be the best, but I'm pretty sure that you can build your application the way that "If we've found the first solution, then we exit every recursion level by only one `return`. This would be (I think so) optimized by the compliler and will have even better performance, than the `exception` method (exception handling invokes stack unwinding and therefore, should never be used in terms of non-exception-handling, because it's SLOW)
Kotti
yes I can exit using return,but if you are at a big depth wouldn't exiting immediately make some differences in terms of performance.
John Retallack
Forgive me if I'm wrong, since I never used C/C++ extensively, but didn't returning from a stack of function calls also involves stack unwinding?
Lie Ryan
Have you in fact measured the performance and know its a problem? Best practice is to avoid optimizing until a profile has pointed out there is a problem. If there is in fact a problem, you should consider an alternative approach (such as finite state machine)
Chris Hafey
I'm pretty sure that you will never reach `that big depth`, that you'll feel the difference. Turning on optimizations will generally collapse those `return - return - return ...` blocks and everything will be fine. If you don't trust me, you could simply profile flag approach and exception / longjmp approach.
Kotti
A: 

A quick and dirty way is to throw an Exception and catch it at the base level (around right now a lot of people will scream to only use Exceptions for Errors, I argue, founding a solution is an exceptional event since not finding one is the norm)

Lie Ryan
+1  A: 

if you have a flag that is set when you are done and then which is checked in your functions you could solve this. e.g.

void foo(..)
{
   if (g_done) return;
...
}
Anders K.
A: 

You could use setjmp()/longjmp() in both C and C++ for a crude but effective way of bypassing the need to pass a flag all the way back.

Richard Pennington
I thought `setjmp` and `longjmp` should be never used in C++
Kotti
It should be used *very* carefully, longjmp bypasses destructor calls. Can't beat the speed though.
Hans Passant
They should probably never be used (hence the crude but effective comment), but they are there and can be used (carefully!) in both C and C++.
Richard Pennington
+4  A: 

Without knowing exactly what you need, I would look at implementing your own stack, and avoid recursion completely. That way it becomes trivial to exit the backtracking tree (a single "return"), and it is also possible to resume the search to find the next solution by calling the function again, presuming the state of the user-defined stack is preserved (in static variables). Of course, there is a bit of programming overhead to convert a simple recursive program to a loop, but it's pretty straightforward to do.

Nathan
Managing your own stack is error-prone, unless you need to squeeze the last bit of performance, there is little benefit in obfuscating a naturally recursive algorithm into iterative algorithm.
Lie Ryan
assuming that there is no need for reusing the stack, I don't think that allocating/deallocating a stack would be more efficient from recursion and *returning*.
Nick D
Using your own stack, you can preallocate to maximum depth avoiding running into stack overflow, avoid storing return adresses, avoid storing locals that don't need to be preserved across the recursive call, avoid method prologue / epilogue, make it easier for the optimizer, can store a snapshot and continue later, and - as said above - can stop any time, at any depth. ---- It is usually more code but easier to analyze for readers not understanding recursion, allows better debug + diagnostics, and it's a common code transformation that sometimes becomes necessary.
peterchen
+1  A: 

Why do you want the function to immediately exit? Not backtracking through the stack is dangerous as you could have objects on it that need to be destroyed. Throwing an exception might due the trick for you, and it will cleanup the stack. Provide more information about what you are trying to do and we might be able to provide other approaches.

Chris Hafey
A: 

If your backtracking algorithm is actually recursing deep enough for this to matter, you shouldn't use recursion because you'll be in danger of blowing the stack. Rather than committing some atrocity involving longjmp, you should consider rewriting your algorithm to an iterative approach with your own heap-allocated stack which stores a POD object representing the state. When you find your solution the state container can be destroyed in one efficient step and the answer can be returned.

See http://stackoverflow.com/questions/159590/way-to-go-from-recursion-to-iteration

Alan
A: 

First, note that you can not do it for any recursive function. Consider the following code:

int SumNum(int nMax)
{
    if (0 == nMax)
        return 0;
    else
        return nMax + SumNum(nMax-1);
}

The actual value is calculated during the backtracking.

However, you can rewrite the code in the following way:

int SumNum(int nMax, int nSum)
{
    if (0 == nMax)
        return nSum;
    else
        return SumNum(nMax-1, nSum+nMax);
}

Now, you can do the following trick:

    int SumNum(int nMax, int nSum)
    {
        if (0 == nMax)
            throw nSum;
        else
            return SumNum(nMax-1, nSum+nMax);
    }


f()
{
        int nSum;

        try
        {
            SumNum(100, 0);
        }
        catch (int _nSum)
        {
            nSum= _nSum;
        }
}
Lior Kogan