I am writing minimax as part of a project, but its awfully hard to check that it is working correctly. If I could print a tree of what it does, it would be extremely useful.
Is there an easy way to print a tree of recursive calls, selecting whatever variables are important to the situation?
Keep track of recursion depth by means of a parameter (in minimax, you'd do that anyway). Then print depth * a small number of spaces, followed by the interesting variables in each call to obtain
player=1, move=...
player=2, move=...
player=1, move=...
...
player=2, move=...
You might also want to print the return value of each recursive call.
If you desperately want a pretty picture of a tree, post-process the output of the above and feed it to a tree-drawing package.
Related
I'm trying to get breadth first enumeration working with Gremlin, however I'm having trouble finding a way to output all the steps observed during the enumeration. I can only print out the result of the last iteration.
My question would be, given a starting node like this, how can I follow all paths (without knowing the overall depth) using Gremlin and print out everything I find along the way?
study=g.v('myId')
I have tried the scatter approach, looping approach (although both seem to require knowledge about the actual length of the path beforehand if I understand correctly)
Many thanks!
You don't provide any significant code that shows how you are using loop, but I think with the right arguments you can get it to do what you want:
gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.v(1).as('x').out.gather.scatter.loop('x'){true}{true}
==>v[2]
==>v[4]
==>v[3]
==>v[5]
==>v[3]
I'm assuming that you understand the code through gather/scatter and the first part of the loop that points back to x. So, with that assumption in mind, I'll focus on the two closures passed to loop.
The first closure passed to loop tells Gremlin when to break out of the loop. By simply returning true, you're saying to exhaust the loop. Depending on the structure of your graph, that may not be advisable as you could be waiting for a very long time for a result to come back. At a minimum you should consider setting it to something impossibly high so that if you do hit some cycle in the graph, your traversal breaks.
The second closure is known as the "emit closure". You can read more about it here, but basically it determines if intermediate objects in the pipe (not just the ones at the end of the loop) should be returned or not. In this case, you can see I simply set that value to true so that it would emit all objects at all steps of the loop.
So I was reading about Recursive searching in a binary search algorithm and I saw a line that says, that with every computation where you don't find the result, you cut the array you are looking through in half and create a new array. Is it really necessary to make a new array with every computation instead of adjusting the start and end index of the array you started with?
sure you can just adjust the start and end index. This is the implementation. What you are reading is an easy description of the algorithm, the implementation can differ if it still does the work.
I have been looking at the current problem on Coding Bat:
"We have triangle made of blocks. The topmost row has 1 block, the next row down has 2 blocks, the next row has 3 blocks, and so on. Compute recursively (no loops or multiplication) the total number of blocks in such a triangle with the given number of rows."
I understand what the problem is asking for, and I understand how recursion works. For example, if I am given a recursion function I can work it out by hand and show what the output will be.
The problem is actually creating the recursion function from a given problem, such as this one. I'm not sure how to actually set this up and do it recursively. Are there some sort of rules to follow when actually setting up a recursion problem? I can only find examples that show you how recursion works, not showing you how to actually solve a recursion problem. Any help understanding how to get ready to write the actually recursion algorithm would be appreciated.
Roughly:
Always look at the problem and try to find out if it can be divided
into subproblems of the same type. That's a first hint that you can
possibly use a recursion. Essentially you are looking for a smaller
instances/versions of an actual problem.
Recursion takes therefore a top down approach(from the more complex to simpler problem cases).
When you can find such cases then you should find out what is the
relation between the "bigger" case and the "smaller" case and you
have your recursion step.
The final thing is to find out the terminating condition or what
is the smallest or last case where you want to stop.
You probably know about this but if not it might help you.
For a recursion algorithm,
first design the base case, for which the function should start the unwinding of the stack or to return the base value.
Then design the algorithm to be actually done, for each of the non-base cases
if(rows == 1) return 1; is useless here.
For the recursion global issue, you must disassemble your problem and find:
An exit rule (can be an initial value like in your example, or some exit condition on one of the inputs)
A stepping process (what do you have to do with the previous input to get the next one)
And assemble them in a function that calls itself.
Try this code:
#include <iostream>
using namespace std;
int sumf(int row,int sum){
if(row==0) //basecase which ends the recursion.
return sum;
else
{sum=row+sum;
return sumf(--row,sum); // repeating the process.
}}
int main() {
cout<<"sum is: "<<sumf(5,0)<<endl;
system("pause");
return 0;
}
This is the video which make you understand about recursion.(forget about language just focus on concept.)
http://www.youtube.com/watch?v=sNJQrtGD1Nc
I've got a lot of true/false results saved as bits in long[] arrays. I do have a huge number of these (millions and millions of longs).
For example, say I have only five results, I'd have:
+----- condition 5 is true
|
|+---- condition 4 is false
||
||+--- condition 3 is true
|||
|||+-- condition 2 is true
||||
||||+- condition 1 is false
10110
I also do have a few trees representing statements like:
condition1 AND (condition2 OR (condition3 AND condition 4))
The trees are very simple but very long. They basically look like this (it's an oversimplification below, just to show what I've got):
class Node {
int operator();
List<Node> nodes;
int conditionNumber();
}
Basically either the Node is a leaf and then has a condition number (matching one of the bit in the long[] arrays) or the Node is not a leaf and hence refers several subnodes.
They're simple yet they allow to express complicated boolean expressions. It works great.
So far so good, everything is working great. However I do have a problem: I need to evaluate a LOT of expressions, determining if they're true or false. Basically I need to do some brute-force computation for a problem for which there's no know better solution than brute-forcing.
So I need to walk the tree and answer either true or false depending on the content of the tree and the content of the long[].
The method I need to optimize looks like this:
boolean solve( Node node, long[] trueorfalse ) {
...
}
where on the first call the node is the root node and then, obviously, subnodes (being recursive, that solve method calls itself).
Knowing that I'll only have a few trees (maybe up to a hundred or so) but millions and millions of long[] to check, what steps can I take to optimize this?
The obvious recursive solution passes parameters (the (sub)tree and the long[], I could get rid of the long[] by not passing it as a parameter) and is quite slow with all the recursive calls etc. I need to check which operator is used (AND or OR or NOT etc.) and there's quite a lot of if/else or switch statements involved.
I'm not looking for another algorithm (there aren't) so I'm not looking for going from O(x) to O(y) where y would be smaller than x.
What I'm looking for is "times x" speedup: if I can write code performing 5x faster, then I'll have a 5x speedup and that's it and I'd be very happy with it.
The only enhancement I see as of now --and I think it would be a huge "times x" speedup compared to what I have now-- would be to generate bytecode for every tree and have the logic for every tree hardcoded into a class. It should work well because I'll only ever have a hundred or so trees (but the trees aren't fixed: I cannot know in advance how the trees are going to look like, otherwise it would be trivial to simply hardcode manually every tree).
Any idea besides generating bytecode for every tree?
Now if I want to try the bytecode generation route, how should I go about it?
In order to maximize the opportunities for shortcut evaluation, you need to do your own branch prediction.
You might want to profile it, tallying
which AND branches evaluate into false
which OR branches result into true
You can then reorder the tree relative to the weights that you found in the profiling step. If you want/need to be particularly nifty, you can devise a mechanism that detects the weighting for a certain dataset during runtime, so you can reorder the branches on the fly.
Note that in the latter case, it might be advisable to not reorder the actual tree (with respect to storage efficiency and correctness of result while still executing), but rather devise a tree-node visitor (traversal algorithm) that is able to locally sort the branches according to the 'live' weights.
I hope all of this makes sense, because I realize the prose version is dense. However, like Fermat said, the code example is too big to fit into this margin :)
There is a simple and fast way to evaluate boolean operations like this in C. Assuming you want to evaluate z=(x op y) you can do this:
z = result[op+x+(y<<1)];
So op will be a multiple of 4 to select your operation AND, OR, XOR, etc. you create a lookup table for all possible answers. If this table is small enough, you can encode it into a single value and use right shift and a mask to select the output bit:
z = (MAGIC_NUMBER >> (op+x+(y<<1))) & 1;
That would be the fastest way to evaluate large numbers of these. Of course you'll have to split operations with multiple inputs into trees where each node has only 2 inputs. There is no easy way to short circuit this however. You can convert the tree into a list where each item contains the operation number and pointers to the 2 inputs and output. Once in list form, you can use a single loop to blow through that one line a million times very quickly.
For small trees, this is a win. For larger trees with short circuiting it's probably not a win because the average number of branches that need to be evaluated goes from 2 to 1.5 which is a huge win for large trees. YMMV.
EDIT:
On second thought, you can use something like a skip-list to implement short circuiting. Each operation (node) would include a compare value and a skip-count. if the result matched the compare value, you can bypass the next skip-count values. So the list would be created from a depth-first traversal of the tree, and the first child would include a skip count equal to the size of the other child. This takes a bit more complexity to each node evaluation but allows short circuiting. Careful implementation could do it without any condition checking (think 1 or 0 times the skip-count).
I think your byte-coding idea is the right direction.
What I would do, regardless of language, is write a precompiler.
It would walk each tree, and use print statements to translate it into source code, such as.
((word&1) && ((word&2) || ((word&4) && (word&8))))
That can be compiled on the fly whenever the trees change, and the resulting byte code / dll loaded, all of which takes under a second.
The thing is, at present you are interpreting the contents of the trees.
Turning them into compiled code should make them run 10-100 times faster.
ADDED in response to your comments on not having the JDK. Then, if you can't generate Java byte code, I would try to write my own byte-code interpreter than would run as fast as possible. It could look something like this:
while(iop < nop){
switch(code[iop++]){
case BIT1: // check the 1 bit and stack a boolean
stack[nstack++] = ((word & 1) != 0);
break;
case BIT2: // check the 2 bit and stack a boolean
stack[nstack++] = ((word & 2) != 0);
break;
case BIT4: // check the 4 bit and stack a boolean
stack[nstack++] = ((word & 4) != 0);
break;
// etc. etc.
case AND: // pop 2 booleans and push their AND
nstack--;
stack[nstack-1] = (stack[nstack-1] && stack[nstack]);
break;
case OR: // pop 2 booleans and push their OR
nstack--;
stack[nstack-1] = (stack[nstack-1] || stack[nstack]);
break;
}
}
The idea is to cause the compiler to turn the switch into a jump table, so it performs each operation with the smallest number of cycles.
To generate the opcodes, you can just do a postfix walk of the tree.
On top of that, you might be able to simplify it by some manipulation of De Morgan's laws, so you could check more than one bit at a time.
Is there any algorithm to reduce sat problem.
Satisfiability is the problem of determining if the variables of a given Boolean formula can be assigned in such a way as to make the formula evaluate to TRUE. Equally important is to determine whether no such assignments exist, which would imply that the function expressed by the formula is identically FALSE for all possible variable assignments. In this latter case, we would say that the function is unsatisfiable; otherwise it is satisfiable. To emphasize the binary nature of this problem, it is frequently referred to as Boolean or propositional satisfiability. The shorthand "SAT" is also commonly used to denote it, with the implicit understanding that the function and its variables are all binary-valued.
I have used genetic algorithms to solve this, but it would be easier if is reduced first?.
Take a look at Reduced Order Binary Decision Diagrams (ROBDD). It provides a way of compressing boolean expressions to a reduced canonical form. There's plenty of software around for performing the BDD reduction, the wikipedia link above for ROBDD contains a nice list of external links to other relevant packages at the bottom of the article.
You could probably do a depth-first path-tree search on the formula to identify "paths" - Ie, for (ICanEat && (IHaveSandwich || IHaveBanana)), if "ICanEat" is false, the values in brackets don't matter and can be ignored. So, right there you can discard some edges and nodes.
And, if while you're generating this depth-first search, the current Node resolves to True, you've found your solution.
What do you mean by "reduced", exactly? I'm going to assume you mean some sort of preprocessing beforehand, to maybe eliminate or simplify some variables or clauses first.
It all depends on how much work you want to do. Certainly you should do unit propagation until it completes. There are other, more expensive things you can do. See the pre-processing section of the march_dl page for some examples.