I see there is an option in the Alloy Analyzer to allow recursion up to a certain depth (1-3).
But what happens when a counterexample cannot be found because of the limited recursion depth?
Will there be an error or a warning, or are such counterexamples silently ignored?
Alloy basically does not support recursion. When it encounters recursion, it unrolls the code the max number of times. Therefore, if it cannot found a solution, it just, well, cannot find a solution. If it could only generate an error if it knew there was a potential solution, which would solve the original problem.
This is, imho, one of the weakest spots in Alloy. Recursion is extremely important in almost all specifications.
Related
When applying the wrong tactic or the wrong deduction rule, the error message is usually too general:
Failed to apply initial proof method⌂
I am using Isabelle to teach natural deduction. When Isabelle complains, some students change the rule/tactic arbitrary without reflecting on the possible causes of the error. A more detailed error message could be part of the learning process of Isabelle, I think.
How to make those error messages student friendly? Does that require editing the source code or can it be managed by defining more expressive tactics of natural deduction?
Tactics in Isabelle can be thought of as chainable non-deterministic transformations of the goal state. That means that the question of what specifically caused a tactic to fail is difficult to answer in general, and there is no mechanism to track such information in Isabelle's tactic system. However, one could relatively easily modify existing tactics such that they can optionally output some tracing information.
However, I have no idea what this information should be. There are simple tactics such as rule where the reason why applying it fails is always that the rule that it is given cannot be unified with the goal (and possibly chained facts), and there are similarly simple tactics like intro, drule, frule, erule, and elim. Such unification-related problems can be debugged quite well sometimes using declare [[unify_trace_failure]], which prints some tracing information every time a unification fails.
With simp and auto, the situation is much less clear because of how many different things these methods can do. Essentially, when the proof method could not be applied at all, it means that ‘none of the things that simp and auto can do worked for this goal’. For simp, this includes simplification, splitting, linear arithmetic, and probably a lot more things that I forgot. For auto, it additionally includes classical reasoning with a certain search depth. One cannot really say easily what specific thing went wrong when these methods fail.
Some specialised tactics do print more specific error messages if something goes wrong, e.g. sat and smt sometimes print a special error message when they have found a counterexample to the goal, but I cannot even imagine what more helpful output for something like simp or auto would look like. If you have an idea, please do tell me.
I think this problem cannot really be solved with error messages; one must simply get to know the system and the tactics one uses better and understand what they do and when they fail. Perhaps it would be good to have a kind of catalogue of commonly-used tactics that mentions these things.
I am learning data structure and algorithms. I found it especially difficult to understand recursions.
So I have the following questions. But they are not related to any specific code.
When I implement methods, when/where should I consider recursion?
In general coding convention, should I prefer recursion over simple iteration if they are both feasible?
How to actually comprehend most possible forms of recursion so I can think of them when I need? What is the best way to learn it? (Any related book or website?) Is there any pattern?
I know the question may sounds unconstructive if you find recursion simple and natural.
But for me it doesn't align with my intuition well. I do appreciate any help.
1
Very often recursive solutions to problems are smaller when data can be seen as similar. Eg. If you have a binary tree and you want to get the sum of all the leaf nodes you define sum-tree as If it's a leaf node, it's sum is it's value, if it's not a leaf node it the addition of the sum of both sub-trees.
Here's a Scheme implementation of my text
(define (sum-tree tree)
(if (leaf? tree)
(node-value tree)
(+ (sum-tree (node-left tree))
(sum-tree (node-right tree)))))
Or the same in Java, defined as a method in the Node class.
public int sum()
{
if ( isLeaf() )
return value;
else
return left.sum() + right.sum();
}
An iterative solution to this would be longer and harder to read. In this case you should prefer recursion.
2
It depends. If you are programming in Python or Java you should not since they donæt have tail recursion. With Scheme however, it's the only way to go. If your language supports tail recursion you should pick recursion when it makes clearer code.
3
Learn by doing. You need to write some algorithms that uses recursion as a tool. Use paper to follow the flow of the stack if you are unsure of the flow. Learning some Scheme or a similar functional language might help you a lot.
Recursion can be used when you are repeating the same thing over and over. For example, you are traversing a tree, you can use a recursion method to go to the left or right child.
I would go for the one that is easier to read. Generally, simple iteration will be faster as it does not have any overhead (recursion has some overhead, and can cause stack overflow if the levels are to deep, while simple iteration won't). But for some case, writing a recursive function is a lot easier than writing the equivalent in the simple iteration.
I would rather see the problem first and then decide whether I need recursion to solve it, not vice versa. Any algorithm book should be good enough. Perhaps you can start over reading http://en.wikipedia.org/wiki/Recursion to begin with. There is a simple example there about recursion, which I think you will be able to implement too using simple iteration.
At first, wrapping my head around recursion was hard as well. When I was learning recursion it was during school with Java. I found it more often I would use recursion over iterators as they were annoying to write in Java. However, I learned Ruby and I found myself writing recursive methods less and less. Then, I learned Elixir and Erlang and found myself writing a lot of recursive functions. My point? Some tools will give themselves for writing with certain style.
Now to answer your questions, since you're just starting to learn recursion, I would suggest diving deep into them and trying to get comfortable with them writing them as much as you can.
Certain tasks are much better off with recursion (e.g. Fibonacci sequence, traversing trees, etc..). Some other's you're better off writing a simple loop. However, note that you can write any recursive method with a loop. It might get tricky on certain occasions though.
All in all, recursion is actually a pretty cool concept once you get the hang of it.
Take a look at this question that relates to recursion: Erlang exercise, creating lists
I'd go for a study of some well known recursive algorithms. For instance, you could try to implement a factorial computation, or to get all the paths lengths in a tree.
By doing that you'll (hopefully) see how the recursive approach helps to simplify the code, and why it is a good approach in these particular cases. This could give you some ideas for future applications :)
I'm learning Data Structures & Algorithms now.
My lecture notes have an implementation of a binary search tree which is implemented using a recursive method. That is an elegant way, but my question is in real life code, should I implement a binary search tree recursively, will it generate a lot of calling stack if the tree has large height/depth number.
I understand that recursion is a key concept to understand lots of data structure concepts, but would you choose to use recursion in real life code?
A tree is recursive by nature. Each node of a tree represents a subtree, and each child of each note represents a subtree of that subtree, so recursion is the best bet, especially in practice where other people people might have to edit and maintain your code.
Now, IF depth becomes a problem for your call stack, than I'm afraid that there are deeper problems with your data structure (either it's monstrously huge, or it's very unbalanced)
"I understand that recursive is a key concept to understand lots of
data structure, but will you choose to use recursive in real life
code?"
After first learning about recursion I felt the same way. However, having been working in the Software industry for over a year now, I can say that I have used the concept of recursion to solve several problems. There are often times that recursion is cleaner, easier to understand/read, and just downright better. And to emphasize a point in the previous answer, a tree is a recursive data structure. IMO, there is no other way to traverse a BST :)
Many times, the compiler can optimize your code, to avoid creating a new stack frame for each recursive call (look up tail recursion, for example). Of course, it all depends on the algorithm and on your data structure. If the tree is reasonably balanced, I don't think a recursive algorithm should cause any problems.
its true that recursion is intutive and elegent and it produces code that is clear and concise. its also correct that some methods such as quick sort, DFS etc. are really hard to implement iterativelly.
but in practice recursive implementations are almost always going to be slow when compared to iterative counterparts because of all the function calls (To really understand the performance hit I suggest you learn how much book keeping stuff assembler has to do for a single function call).
the optimizations that we talk about are not applicable to every recursive method in general and manny compilers and interpreters dont even support them.
so in summary if you are writing something which is performance critical such as a data strucute then stay away from recursion (or use it if you are sure that your compiler/interpreter got you covered)
PS: CLRS (introduction to algorithms, page 290, last line) suggests that iterative search procedure for a BST is faster compared to recursive one.
I am currently working in PHP, so this example will be in PHP, but the question applies to multiple languages.
I am working on this project with a fiend of mine, and as always we were held up by a big problem. Now we both went home, couldn't solve the problem. That night we both found the solution, only I used a loop to tackle the problem, and he used recursion.
Now I wanted to tell him the difference between the loop and recursion, but I couldn't come up with a solution where you need recursion over a normal loop.
I am going to make a simplified version of both, I hope someone can explain how one is different from the other.
Please forgive me for any coding errors
The loop:
printnumbers(1,10);
public function printnumbers($start,$stop)
{
for($i=$start;$i<=$stop;$i++)
{
echo $i;
}
}
Now the code above just simply prints out the numbers.
Now let's do this with recursion:
printnumbers(1,10);
public function printnumbers($start,$stop)
{
$i = $start;
if($i <= $stop)
{
echo $i;
printnumbers($start+1,$stop);
}
}
This method above will do the exact same thing as the loop, but then only with recursion.
Can anyone explain to me what there is different about using one of these methods.
Loops and recursions are in many ways equivalent. There are no programs the need one or the other, in principle you can always translate from loops to recursion or vice versa.
Recursions is more powerful in the sense that to translating recursion to a loop might need a stack that you have to manipulate yourself. (Try traversing a binary tree using a loop and you will feel the pain.)
On the other hand, many languages (and implementations), e.g., Java, don't implement tail recursion properly. Tail recursion is when the last thing you do in a function is to call yourself (like in your example). This kind of recursion does not have to consume any stack, but in many languages they do, which means you can't always use recursion.
Often, a problem is easier expressed using recursion. This is especially true when you talk about tree-like data structures (e.g. directories, decision trees...).
These data structures are finite in nature, so most of the time processing them is clearer with recursion.
When stack-depth is often limited, and every function call requires a piece of stack, and when talking about a possibly infinite data structure you will have to abandon recursion and translate it into iteration.
Especially functional languages are good at handling 'infinite' recursion. Imperative languages are focused on iteration-like loops.
In general, a recursive function will consume more stack space (since it's really a large set of function calls), while an iterative solution won't. This also means that an iterative solution, in general, will be faster because.
I am not sure if this applies to an interpreted language like PHP though, it is possible that the interpreter can handle this better.
A loop will be faster because there's always overhead in executing an extra function call.
A problem with learning about recursion is a lot of the examples given (say, factorials) are bad examples of using recursion.
Where possible, stick with a loop unless you need to do something different. A good example of using recursion is looping over each node in a Tree with multiple levels of child nodes.
Recursion is a bit slower (because function calls are slower than setting a variable), and uses more space on most languages' call stacks. If you tried to printnumbers(1, 1000000000), the recursive version would likely throw a PHP fatal error or even a 500 error.
There are some cases where recursion makes sense, like doing something to every part of a tree (getting all files in a directory and its subdirectories, or maybe messing with an XML document), but it has its price -- in speed, stack footprint, and the time spent to make sure it doesn't get stuck calling itself over and over til it crashes. If a loop makes more sense, it's definitely the way to go.
Well, I don't know about PHP but most languages generate a function call (at the machine level) for every recursion. So they have the potential to use a lot of stack space, unless the compiler produces tail-call optimizations (if your code allows it).
Loops are more 'efficient' in that sense because they don't grow the stack. Recursion has the advantage of being able to express some tasks more naturally though.
In this specific case, from a conceptual (rather than implementative) point of view, the two solutions are totally equivalent.
Compared to loops, a function call has its own overhead like allocating stack etc. And in most cases, loops are more understandable than their recursive counterparts.
Also, you will end up using more memory and can even run out of stack space if the difference between start and stop is high and there are too many instances of this code running simultaneously (which can happen as you get more traffic).
You don't really need recursion for a flat structure like that. The first code I ever used recursion in involved managing physical containers. Each container might contain stuff (a list of them, each with weights) and/or more containers, which have a weight. I needed the total weight of a container and all it held. (I was using it to predict the weight of large backpacks full of camping equipment without packing and weighing them.) This was easy to do with recursion and would have been a lot harder with loops. But many kinds of problems that naturally suit themselves to one approach can also be tackled with the other.
Stack overflow.
And no, I don't mean a website or something. I MEAN a "stack overflow".
I am trying to do work with examples on Trees as given here: http://cslibrary.stanford.edu/110/BinaryTrees.html
These examples all solve problems via recursion, I wonder if we can provide a iterative solution for each one of them, meaning, can we always be sure that a problem which can be solved by recursion will also have a iterative solution, in general. If not, what example can we give to show a problem which can be solved only by recursion/Iteration?
--
The only difference between iteration and recursion on a computer is whether you use the built-in stack or a user-defined stack. So they are equivalent.
In my experience, most recursive solution can indeed be solved iteratively.
It is also a good technique to have, as recursive solutions may have too large an overhead in memory and CPU consumptions.
Since recursion uses an implicit stack on which it stores information about each call, you can always implement that stack yourself and avoid the recursive calls. So yes, every recursive solution can be transformed into an iterative one.
Read this question for a proof.
Recursion and iteration are two tools that, at a very fundamental level, do the same thing: execute a repeated operation over a defined set of values. They are interchangeable in that there is no problem that cannot, in some way, be solved by only one of them. That does not mean, however, that one cannot be more suited than the other.
Recursion has the advantage where it will continue without a known end. A perfect example of this is a tuned and threaded Quick Sort.
You can't spawn additional loops, but you can spawn new threads via recursion.
As an "old guy," I fall back to my memory of learning that recursive descent parsers are easier to write, but that stack-based, iterative parsers perform better. Here's an article that seems to support that idea with metrics:
http://www.texttoolkit.com/index.php?option=com_content&view=article&catid=35%3Atechnology&id=60%3Abeyond-recursive-descent&Itemid=55
One thing to note is the author's mention of overrunning the call stack with recursive descent. An iterative, stack-based implementation can be much more efficient of resources.