Speaking for myself, I have _lots_ of small functions/procedures. By intent and design, as I subscribe to the "linux approach" of keeping functions as small as possible to make them easier to read and understand...CThinker wrote:These are "call graphs". Each node is a function, and each lines (edge) is a function call (from one function to another).Uri Blass wrote:I can only say that I do not understand what these graphs mean and how you generate them,CThinker wrote:It is all about simplicity. It may not be expensive as far as run-time is concerned, but it is still extra ugly code. To me, at least, it looks like that.bob wrote: My only question is this: Why would you not collect the PV on the fly by backing it up along with the score? A PV harvested from the trans/ref table is inaccurate, and (IMHO) makes it harder to debug things. I often look at a PV and score from Crafty, then run down the PV and repeatedly use the score command to tweak things to bring the score closer to what seems reasonable. A hash PV is almost guaranteed to not lead you to the actual position that was scored, which makes debugging much more complicated...
And backing up the PV is not expensive.
Even within Thinker, the implementation of search is hidden from the shell. The tree search is just one form of search. The book search is another. Both have completely different behavior. So, the shell does not care how they find the best move. The shell just knows that they will return one.
To the shell, the book search and the tree search are just "strategies" (in design pattern speak). So, even if I implement a PV collection in the tree search, would I want to expose that? That means the book search would have to return a PV also? That means that any "search strategy" always include a PV. I could design it that way, but that would be a very bad design. That may not be a big deal to others, but it is to me.
Just to give an idea of the simplicity that I am talking about, below is a comparison of the call graphs of Fruit 2.3.1, Crafty 22.9 and Thinker 5.4C.
Cheers...
http://www.winboardengines.de/thinker/C ... -2-3-1.bmp
http://www.winboardengines.de/thinker/C ... y-22-9.bmp
http://www.winboardengines.de/thinker/C ... ker54C.bmp
When you talk about elegence then I do not understand what is the exact meaning of ut.
I do not know if there is some mathematical way to measure it.
Uri
I found this example of a fully labeled one:
http://multimedia.cx/eggs/images/dcng-w ... lgraph.png
I don't think they are an indicator of elegance.
It can however give you an indication of the complexity of the program. The number of functions is a simple indicator, but not very accurate. But if your functions are bunched together and layered, and there are just few lines between those bunched-up (or layered) functions, then it indicates that program is modularized. That is, a group of functions (or a layer) perform a specific task, and there is a well defined small set of interfaces to them.
The Fruit and Crafty code definitely has a lot of functions, and so, you can't see each one of them anymore (they should show-up as rectangles, like in Thinker graph). This explains why the Fruit binary is 10 times the Thinker binary.
Now, I can't accurately comment on modularity of Fruit and Crafty because the individual lines are no longer visible. I just have a feeling that there are a lot of crisscrossing of lines there.
I don't think a program with one large block of code is more elegant at all, although the call graph would be quite simple...