Algorithm Design-extremely small search

Source: Internet
Author: User

Extremely small search strategies are generally used in NLP games:

 

In this way, the deep search policy is used in essence, so it can be implemented using recursive methods. In the search process, the maximum value should be obtained for the search point advantageous to the local party, and the minimum value should be obtained for the search point unfavorable to the local party.

The minimum and maximum values are relative.

 

In the search process, you need to properly control the search depth. The deeper the search depth, the lower the efficiency. But in general, the better the search method.

 

Extremely small searches can be written separately or written together.

 

The main algorithm steps are as follows:

 

Input: search depth

Output: the optimal route of the node and its corresponding optimal Valuation

Function Format: int minmaxsearch (INT depth) Here you can also add the int side parameter to indicate who is playing the game currently

 

If it is red

Initialize the optimal value best = negative infinity // very big point. Here we think that the Red Square goes first.

Otherwise

Initialize the optimal value best = positive infinity // minimum

 

If depth <= 0

Call evaluation function value

 

Otherwise

Generate all reasonable current steps

Step by step

Execution steps

Call minmaxsearch (depth-1) and assign the value to value

Withdrawal steps

 

If it is red

If value> Best

Best = Value

If depth = max_depth

Bestmove = mv

Otherwise

If value <best

Best = Value

If depth = max_depth

Bestmove = mv

 

Back to best

 

In the situation evaluation function, the difference between the advantages of both parties is generally returned as the evaluation value.

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~

 

Here we will summarize the negative maximum search policy:

In a situation, X is the advantage of the red party, and-X is the advantage of the black party. In a situation, X is the advantage of the red party, and X is the advantage of the black party. In the negative maximum search algorithm, there is no minimum point, but only a very large point. It should be noted that when the advantages of one party are converted to those of the other, a negative sign is required. The estimated range is a symmetric range of 0 points:

[-Maxvalue, maxvalue]. it should be noted that, in order to make the negative maximum search algorithm get a correct evaluation, the return value of the situation evaluation function must be modified. The original result in the extremely small search algorithm always returns the advantage of the Red Square, now we want to change it to the advantages of the current player.

 

Negative maximum search algorithm:

 

Input: search depth

Output: the optimal route of the node and the corresponding optimal Valuation

Function Format: int negamaxsearch (INT depth)

 

Initialize the optimal value best = negative infinity // All are very big points

If depth is less than or equal to 0

Call the evaluation function and assign the result to the value

Return Value

 

Otherwise

Generate all valid steps

Steps for each step

Execution steps

Value =-negamaxsearch (depth-1) // note that there is a negative number before the Function

Withdrawal steps

If value> Best

Best = Value

If depth = max_depth

Bestmove = mv

Return best // return the optimal evaluation value of a search Branch

 

 

Algorithm for evaluating functions:

 

Input: Game Board

Output: Advantages of the situation on the current party

 

Rvalue: Sum of advantages of the Red Square

Bvalue: Total strengths of the black party

 

Evaluate the problem and design the problem separately to obtain the values of rvalue and bvalue.

 

If the current situation is a game player

Return rvalue-bvalue;

Otherwise

Return bvalue-rvalue;

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~

 

Improvements to extremely small search strategies and negative maximum search strategies -- alpha-beta pruning search strategies

 

In general, in order to cause pruning during the search process, two parameters must be passed down in the recursive process. The first parameter is Alpha, which indicates the best value found by one of the current search nodes. Any value smaller than it makes no sense. The 2nd values are beta, indicating the current disadvantage of the opponent. This is the best result that the opponent can bear, and the values greater than it will be discarded.

Because it is a negative maximum value search, the larger the beta value, the more obvious the opponent's disadvantage, the smaller the beta value, the smaller the disadvantage.

 

For the alpha-beta search pruning algorithm, you can use-maxvalue ~ because there is no alpha-beta value in the initial state ~ Maxvalue.

 

The alpha-beta search pruning algorithm is as follows:

 

Input: search depth, alpha, beta

Output: the optimal route of the node and the corresponding optimal Valuation

Function Format: int alphabetasearch (INT depth, int Alpha, int beta)

 

If depth is less than or equal to 0

Call the evaluation function and assign the result to the value

Return Value

Otherwise

Generate all reasonable current steps

For every walk

Execution steps

Value =-alphabetasearch (depth-1,-Beta,-alpha );

// Note that there is a negative value before the function, and the alpha and beta parameters take negative values and exchange them.

Withdrawal steps

If value> = beta // you can search for a method first, because the search efficiency depends largely on the pruning effect.

Return to Beta

If value> alpha

Alpha = Value

If depth = max_depth

Bestmove = mv

Returns Alpha.

 

Call method: alphabetasearch (maxdepth,-maxvalue, maxvalue)

Traditionally, the interval that is passed to the alpha and beta values of a node to be searched is called a search window.

The narrower the search window, the higher the possibility of pruning, and the higher the search efficiency.

Will the Alpha value passed to a node to be searched be greater than the beta value? (Absolutely not. It is impossible to even wait ).

 

 

The following is the question of poj3317 stake your claim, which uses the negative maximum value search and alpha-beta pruning optimization code. From this experiment, we found that alpha-beta pruning is very helpful for improving efficiency.

 

The following is a defined situation evaluation class:

 

# Include <iostream> <br/> # include <cstring> <br/> using namespace STD; <br/>/* <br/> * class for situation evaluation <br/> */<br/> class Evaluater {</P> <p> public: </P> <p> Evaluater (char map [] [8], int S): size (s) {</P> <p> // memcpy (square, map, sizeof (MAP); <br/> for (INT I = 0; I <8; I ++) <br/> for (Int J = 0; j <8; j ++) <br/> Square [I] [J] = map [I] [J]; </P> <p >}</P> <p>/* <br/> * situation evaluation function <br/> */<br/> int getvaluated (int side) {</P> <p> int p0v Alue = 0, p1value = 0; <br/> for (INT I = 0; I <size; I ++) {</P> <p> for (Int J = 0; j <size; j ++) {</P> <p> If ('0' = square [I] [J]) {</P> <p> getmostsquares ('0', I, j); <br/> If (count> p0value) <br/> p0value = count; <br/> COUNT = 1; <br/>}</P> <p> If ('1' = square [I] [J]) {</P> <p> getmostsquares ('1', I, j); <br/> If (count> p1value) <br/> p1value = count; <br/> COUNT = 1; <br/>}</P> <p> if (1 = side) <br/> return p0va Lue-p1value; <br/> else <br/> return p1value-p0value; </P> <p >}</P> <p> PRIVATE: </P> <p>/* <br/> * search for the number of chess pieces in the largest region <br/> */<br/> void getmostsquares (char flag, int X, int y) {</P> <p> static int dir [4] [2] = {0,-1 }, {1, 0 };</P> <p> int I, j; </P> <p> Square [x] [Y] = 'X '; // space marked as 'X' </P> <p> for (int K = 0; k <4; k ++) {</P> <p> I = x + dir [k] [0]; <br/> J = Y + dir [k] [1]; </P> <p> If (I <0 | I> = size | j <0 | J> = size | square [I] [J]! = Flag) <br/> continue; </P> <p> else {</P> <p> count ++; <br/> getmostsquares (flag, I, j); <br/>}</P> <p> Enum tablesize {max_size = 8 }; // maximum size of the Board <br/> int size; // actual size of the Board <br/> char square [max_size] [max_size]; // chessboard <br/> static int count; <br/>}; </P> <p> int Evaluater: Count = 1; // static variables must be initialized outside the class </P> <p>

 

Below is the implementation of the negative maximum value search: At first, when using extremely large and small values, the results are always not correct, and then directly use the negative maximum value search policy. Note that, the evaluation function corresponding to the negative maximum search needs to return the evaluation value for different current players. In addition, in the search function, all vertices are the maximum vertices, therefore, the value of best can be directly assigned int_min. when returning a recursive function, you do not need to judge side.

 

/* <Br/> * poj 3317 stake your claim <br/> * this is a game question <br/> * search strategy: extremely small <br/> */<br/> # include <iostream> <br/> # include <fstream> <br/> # include <ctime> <br/> # DEFINE _ debug 0 <br/> # include "mapevaluate. H "<br/> using namespace STD; </P> <p> # define Max 8 </P> <p> char map [Max] [Max]; <br/> int num; // actual size of the Board <br/> // 1: player0,-1: player1 <br/> int currside; <br/> // maximum search depth <br/> int max_depth; </P> <p> typedef struct Mo Ve {</P> <p> int X; <br/> int y; <br/> move () {}< br/> move (INT X1, int Y1): X (X1), y (Y1) {}< br/> friend ostream & operator <(ostream & out, const Move & M) {</P> <p> return out <"(" <m. x <"," <m. Y <")"; <br/>}< br/>} Move; </P> <p> move bestmove; // The best movement </P> <p> void print () {</P> <p> for (INT I = 0; I <num; I ++) {<br/> for (Int J = 0; j <num; j ++) {</P> <p> cout <map [I] [J] <""; </P> <p >}</P> <p> cout <Endl; <br/>}</P> <p>/* <B R/> * generate all possible mobile solutions <br/> */<br/> int genallmove (move * array) {</P> <p> int COUNT = 0; <br/> for (INT I = 0; I <num; I ++) <br/> for (Int J = 0; j <num; j ++) {</P> <p> If ('. '= map [I] [J]) {</P> <p> array [count] = move (I, j); <br/> count ++; <br/>}</P> <p> return count; </P> <p >}</P> <p>/* <br/> * Go <br/> */<br/> inline void makemove (move mV, int side) {</P> <p> map [mV. x] [mV. y] = (1 = side )? '0': '1 '; <br/>}</P> <p>/* <br/> * restore the chessboard <br/> */<br/> inline void unmakemove (move mV) {</P> <p> map [mV. x] [mV. y] = '. '; <br/>}</P> <p>/* <br/> * Core algorithms of extremely small search functions <br/> */<br/> int negmaxsearch (int depth, int side) {</P> <p> int best, value; <br/> move movearray [12]; // a maximum of 1 ~ 10 spaces <br/> move tmpmv; </P> <p> // when using the negative maximum value for search, the best value is always int_min <br/> Best = int_min; </P> <p> If (0 = depth) {</P> <p> Evaluater V (MAP, num); <br/> return v. getvaluated (side); <br/>}</P> <p> int num = genallmove (movearray); </P> <p> for (INT I = 0; I <num; I ++) {</P> <p> tmpmv = movearray [I]; <br/> makemove (tmpmv, side ); </P> <p> If (_ Debug) {<br/> Print (); <br/> cout <Endl ;} </P> <p> // note "~ Side ", otherwise the side value is always true <br/> // After side is returned recursively, side restores the original value because "! Side "the original value of side is not changed <br/> // value = minmaxsearch (depth-1 ,! Side); // each time the game moves, <br/> value =-minmaxsearch (depth-1,-1 * side); </P> <p> unmakemove (tmpmv ); </P> <p> If (_ Debug) {<br/> Print (); <br/> cout <Endl ;} </P> <p> // negative maximum value search <br/> If (value> Best) {</P> <p> Best = value; <br/> If (depth = max_depth) <br/> bestmove = tmpmv; <br/>}</P> <p >}< br/> // returns the optimal extreme value <br/> If (depth = max_depth) <br/> cout <bestmove; <br/> return best; </P> <p >}</P> <p> int main () {</P> <p> ifstream in ("test. TXT "); <br/> int count0, count1; </P> <p> while (1) {</P> <p> in> num; <br/> If (0 = num) <br/> break; </P> <p> // initialization starts at the beginning of each round. <br/> count1 = 0; <br/> count0 = 0; </P> <p> for (INT I = 0; I <num; I ++) {</P> <p> for (Int J = 0; j <num; j ++) {</P> <p> in> map [I] [J]; <br/> If ('1' = map [I] [J]) {</P> <p> count1 ++; <br/>}< br/> If ('0' = map [I] [J]) {</P> <p> count0 ++; <br/>}</P> <p> currside = (count0> count1 )? -1: 1; <br/> // search all the vacant spaces <br/> max_depth = num * num-count1-count0; <br/> If (_ Debug) {<br/> cout <currside <Endl; <br/> cout <max_depth <Endl; <br/>}</P> <p> clock_t time = clock (); <br/> cout <"" <negmaxsearch (max_depth, currside) <Endl; <br/> cout <"computing time:" <clock ()-time <"Ms" <Endl; </P> <p >}< br/>

 

The code after Alpha-beta pruning is added. Note that the pruning method is as follows:

 

/* <Br/> * poj 3317 stake your claim <br/> * this is a game question <br/> * search strategy: extremely small <br/> */<br/> # include <iostream> <br/> # include <fstream> <br/> # include <ctime> <br/> # DEFINE _ debug 0 <br/> # include "mapevaluate. H "<br/> using namespace STD; </P> <p> # define Max 8 </P> <p> char map [Max] [Max]; <br/> int num; // actual size of the Board <br/> // 1: player0,-1: player1 <br/> int currside; <br/> // maximum search depth <br/> int max_depth; </P> <p> typedef struct Mo Ve {</P> <p> int X; <br/> int y; <br/> move () {}< br/> move (INT X1, int Y1): X (X1), y (Y1) {}< br/> friend ostream & operator <(ostream & out, const Move & M) {</P> <p> return out <"(" <m. x <"," <m. Y <")"; <br/>}< br/>} Move; </P> <p> move bestmove; // The best movement </P> <p> void print () {</P> <p> for (INT I = 0; I <num; I ++) {<br/> for (Int J = 0; j <num; j ++) {</P> <p> cout <map [I] [J] <""; </P> <p >}</P> <p> cout <Endl; <br/>}</P> <p>/* <B R/> * generate all possible mobile solutions <br/> */<br/> int genallmove (move * array) {</P> <p> int COUNT = 0; <br/> for (INT I = 0; I <num; I ++) <br/> for (Int J = 0; j <num; j ++) {</P> <p> If ('. '= map [I] [J]) {</P> <p> array [count] = move (I, j); <br/> count ++; <br/>}</P> <p> return count; </P> <p >}</P> <p>/* <br/> * Go <br/> */<br/> inline void makemove (move mV, int side) {</P> <p> map [mV. x] [mV. y] = (1 = side )? '0': '1 '; <br/>}</P> <p>/* <br/> * restore the chessboard <br/> */<br/> inline void unmakemove (move mV) {</P> <p> map [mV. x] [mV. y] = '. '; <br/>}</P> <p>/* <br/> * Core algorithms of extremely small search functions <br/> */<br/> int alphabetasearch (int depth, int side, int Alpha, int beta) {</P> <p> int best, value; <br/> move movearray [12]; // a maximum of 1 ~ 10 spaces <br/> move tmpmv; </P> <p> If (0 = depth) {</P> <p> Evaluater V (MAP, num ); <br/> return v. getvaluated (side); <br/>}</P> <p> int num = genallmove (movearray); </P> <p> for (INT I = 0; I <num; I ++) {</P> <p> tmpmv = movearray [I]; <br/> makemove (tmpmv, side ); </P> <p> If (_ Debug) {<br/> Print (); <br/> cout <Endl ;} </P> <p> // note "~ Side ", otherwise the side value is always true <br/> // After side is returned recursively, side restores the original value because "! Side "the original value of side is not changed <br/> // value = minmaxsearch (depth-1 ,! Side); // change the player Every time <br/> value =-minmaxsearch (depth-1,-1 * side,-Beta,-alpha ); </P> <p> unmakemove (tmpmv); </P> <p> If (_ Debug) {<br/> Print (); <br/> cout <Endl ;}</P> <p> // alpha-beta pruning search <br/> If (value> = beta) <br/> return Beta; <br/> If (value> alpha) {</P> <p> alpha = value; <br/> If (depth = max_depth) <br/> bestmove = tmpmv; <br/>}</P> <p >}< br/> // returns the optimal extreme value <br/> If (depth = max_depth) <br/> cout <bestmo Ve; <br/> return Alpha; </P> <p >}</P> <p> int main () {</P> <p> ifstream in ("test.txt"); <br/> int count0, count1; </P> <p> while (1) {</P> <p> in> num; <br/> If (0 = num) <br/> break; </P> <p> // initialization starts from each bureau. <br/> count1 = 0; <br/> count0 = 0; </P> <p> for (INT I = 0; I <num; I ++) {</P> <p> for (Int J = 0; j <num; j ++) {</P> <p> in> map [I] [J]; <br/> If ('1' = map [I] [J]) {</P> <p> count1 ++; <br/>}< br/> If ('0' = map [I] [J]) {</P> <p> count0 ++; <BR/>}< br/>}</P> <p> currside = (count0> count1 )? -1: 1; <br/> // search all the vacant spaces <br/> max_depth = num * num-count1-count0; <br/> If (_ Debug) {<br/> cout <currside <Endl; <br/> cout <max_depth <Endl; <br/>}</P> <p> clock_t time = clock (); <br/> cout <"" <alphabetasearch (max_depth, currside,-100,100) <Endl; <br/> cout <"computing time:" <clock ()-time <"Ms" <Endl; </P> <p >}< br/>

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.