Killer heuristic

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Killer heuristic

Post by bob »

Martin Brown wrote:
bob wrote:
Martin Brown wrote:This seems like a good time to ask why there isn't some advantage to storing any killer move (including captures) and trying out the killer with a slightly more complex test for legality before move generation at that ply.

I presume that in general this approach must be slower and that sorted favourable captures are so effective in their own right as to be not worth storing. Although in the toy program I have written it seems to be faster when the killer is tried before full move generation. My move generator is old and slow, but it is terminal node evaluations that dominate runtime.

Thanks for any enlightenment.
I don't quite follow. Here's my move ordering and an explanation of why this is:

(1) hash move (always). This move was proved best in a previous search, it should be tried first here. I do this without generating any moves at all.

(2) captures with SEE >= 0. I only generate captures here and try the ones that appear to not be bad.

(3) killer moves (2). I do this before generating any additional moves (I have already generated captures, I still have to generate non-captures).

(4) The rest of the moves. Here I have to generate the non-captures and search them in the order generated.

So back to the original question. Killers should not be captures, because we will try the good captures _before_ we try any killers at all. We would not want to search the same capture again (we should get an instant hash fail low if we did) which would simply waste that killer.
I expect the problem here is my lack of understanding of the right way to do things. Thanks for your patience if this is a really dumb question. I am not sure what you mean here by hash move (lookup into the hash table of previous results for the position or PV from a shallower search?).
At each node in the tree, you should be doing a probe into your hash (transposition/refutation) table. Sometimes the draft of that position is sufficient, and the bound is usable, so that you can terminate the search immediately. At other times, the draft is insufficient, or the stored bound doesn't help you, but you may well have a "best move" stored in that entry (you would normally have a best move if you search a node and either return a real score (score > alpha && score < beta) or a lower bound (score >= beta). In either of those cases, you have a best move you can store in the table. This is what I call a "hash move". Since it was best in a previous search from this same position, you should try it first in this position as well...
The code I am resurrecting dates from the 1980's. The way it was done then was very crude:

Generate all moves
Try killer(s) {any move allowed as a killer}
Try sorted list of moves {excluding killers}

I changed it to apply the killers with a test for legality before move generation. So it is now

Test killer legal - try killer
Generate all moves
Try list of sorted moves excluding killers.

I can see that allowing captures as killers pollutes the killer line with responses to daft opponent moves that leave pieces en prise. But isn't that issue taken care of by having two killers and a usage heuristic?

And if a superficially bad capture that is tried after all other moves causes a beta cutoff why should it not enter the killer line ?

I am sure your way is better since that is how everybody seems to do it now, but I am curious to better understand why... Thanks again.
Good captures first. Why? Most moves in a full width search hang something, and the quickest way to refute a move that hangs material is to capture the thing instantly. If that doesn't work, then you try moves that were good in previous searches (killer moves). Of course the hash move still comes first and it _may_ be a capture, it is simply whatever was best the last time this exact position was searched.
adieguez

Re: Killer heuristic

Post by adieguez »

Hi,

in my program I use several killers. If I change anything my program get more weaker. Thinking in the reason for that, perhaps my move ordering is worse than average for the moves which are not killers. But I have wasted much time tunning that too to be so bad (in the case it is so bad) well..

another thing I use killers from ply+2 and ply+4, using from ply-2 have never worked for me, neither the current best in ply-2 nothing.
cms271828 wrote:Hi, I'm looking at killer moves again, and trying to figure out what I want to do.

To make it simple, suppose we just store 1 killer move, so this will be a non-capture that causes a cutoff (not sure why captures aren't included).

I presume we have a killer move for each ply of the search, so if we are in some branch at some ply p, and we get a cutoff, would we overwrite the killermove at ply p in the killer array? Or, would we store the score with the killer move, and overwrite if this new move has a greater or equal score?

Also, wouldn't it be wise to try killers from previous plies too, instead of just from the ply we are in? I'm thinking we could do all even/odd ply, as half the entries in killer array will be for other side.

Thanks
User avatar
cms271828
Posts: 316
Joined: Wed Apr 12, 2006 10:47 pm

Re: Killer heuristic

Post by cms271828 »

So currently, I can't really implement killers till I split my captures to good and bad. I was thinking of just knocking something simple up with my MVVLVA method, but now that I think about it, I might as well try and implement SEE instead.

I've read a little about on mediocre chess web page http://mediocrechess.blogspot.com/2007/ ... n-see.html
And its quite good, but not totally clear. I guess we ultimately want the material difference after all captures have taken place on that square with weaker pieces capturing first.

But it seems awquard when pieces are queuing up in a file/rank/diagonal.
For example Rook, Queen on a Rank, and Queen,Bishop on diagonal.

Would you start the sequence with

Rook(Rank), Queen(Rank) or
Rook(Rank), Queen(Diag) or
Queen(Diag), Bishop(Diag) or
Queen(Diag), Rook(Rank) ?

Thanks, also how do I show FEN strings graphically, I can't remember.
Colin
Martin Brown
Posts: 46
Joined: Sun Oct 18, 2009 12:07 pm

Re: Killer heuristic

Post by Martin Brown »

bob wrote:
Martin Brown wrote: And if a superficially bad capture that is tried after all other moves causes a beta cutoff why should it not enter the killer line ?

I am sure your way is better since that is how everybody seems to do it now, but I am curious to better understand why... Thanks again.
Good captures first. Why? Most moves in a full width search hang something, and the quickest way to refute a move that hangs material is to capture the thing instantly. If that doesn't work, then you try moves that were good in previous searches (killer moves). Of course the hash move still comes first and it _may_ be a capture, it is simply whatever was best the last time this exact position was searched.
Thank you for a very clear explanation. I will give that a try.
Martin Brown
adieguez

Re: Killer heuristic

Post by adieguez »

I got a slighty improvement, nothing dramatic. Using the size of the subtree of the killers, so I save from, to, tree size, etc. This will change a bit my implementation.
adieguez wrote:Hi,

in my program I use several killers. If I change anything my program get more weaker. Thinking in the reason for that, perhaps my move ordering is worse than average for the moves which are not killers. But I have wasted much time tunning that too to be so bad (in the case it is so bad) well..

another thing I use killers from ply+2 and ply+4, using from ply-2 have never worked for me, neither the current best in ply-2 nothing.
cms271828 wrote:Hi, I'm looking at killer moves again, and trying to figure out what I want to do.

To make it simple, suppose we just store 1 killer move, so this will be a non-capture that causes a cutoff (not sure why captures aren't included).

I presume we have a killer move for each ply of the search, so if we are in some branch at some ply p, and we get a cutoff, would we overwrite the killermove at ply p in the killer array? Or, would we store the score with the killer move, and overwrite if this new move has a greater or equal score?

Also, wouldn't it be wise to try killers from previous plies too, instead of just from the ply we are in? I'm thinking we could do all even/odd ply, as half the entries in killer array will be for other side.

Thanks
wgarvin
Posts: 838
Joined: Thu Jul 05, 2007 5:03 pm
Location: British Columbia, Canada

Re: Killer heuristic

Post by wgarvin »

Martin Brown wrote:
bob wrote:
Martin Brown wrote: And if a superficially bad capture that is tried after all other moves causes a beta cutoff why should it not enter the killer line ?

I am sure your way is better since that is how everybody seems to do it now, but I am curious to better understand why... Thanks again.
Good captures first. Why? Most moves in a full width search hang something, and the quickest way to refute a move that hangs material is to capture the thing instantly. If that doesn't work, then you try moves that were good in previous searches (killer moves). Of course the hash move still comes first and it _may_ be a capture, it is simply whatever was best the last time this exact position was searched.
Thank you for a very clear explanation. I will give that a try.
There's something on Ed's page about REBEL, saying that it will order a killer move before any captures (i.e. right after the hash move) if the killer move has produced a mate score in the tree (see "Mate-Killer-Move"). He says it works very well in positions where mate threats are an issue. I wonder if others have tried this?