When should an evaluation function for the minimax algorithm return negative values? - minimax

I have an evaluation function for a connect four type game. I don't understand when the evaluation function is suppose to give negative values. My evaluation function basically assigns a value for each move psuedocode might be easier to show
if player has 4 in a row
return 5000;
if player has 3 in a row
return 4000;
if opponent has 3 in a row or 3 in a column
return 4000;
if opponent a disjoint 3 in a row or column //ie xx x
return 4000;
if opponent has in row with spaces on both sides// ie ' 'OO' '
return 100;
if opponent has two in arrow w/o spaces on both sides // ie XOO
return 95;
This is the basic idea, however since there are no negative values, the min function always returns 0;
What am I missing here?

First off, your evaluation function does not have to ever give negative values. That is only a convention for simplicity that moves good for player one are positive, good for player two are negative, and equally good are zero. That should not cause your min function to return zero. If you post your min function, perhaps we can help you. My suspicion from personal experience (I made a connect four engine too) is that the min function sets the default value to zero. That will only work for the max function. The min funcion default must be set to a very high number (in the case of your evaluation numbers 5000). Otherwise, all moves it looks at will never beat zero. Just a guess

Related

How to calculate expected number of turns using DP in O(n)?

A single-player board game. The board is made up of a row of n cells numbered 1 to n from left to
right. Cell ‘j' contains a positive integer cj.
The rules are like this:
You start on the leftmost cell.
On each turn, you roll a fair 6-sided die with A as the outcome number. You
move forward A × cj cells, where j is the index of the cell that you are standing
on.
You win once you exit the board i.e., you win when your index j > n.
For instance, consider the board of size n=10
To begin with, you are at the first cell having the value c1 = 2. In the first turn, you roll a dice
and obtain a value 1, so you move forward 2 cells. Then on the next roll you roll a 5 on cell 3
(with c3 = 4), so you move forward 20 cells makes you exit the board. You win!! You took 2
turns to win.
How to calculate the expected number of turns needed to win using dynamic programming algorithm that runs in time (n) for the above game?
The recurrence relation you're looking for is:
E[j] = 0 (if j > n)
E[j] = 1 + 1/6 * sum_k(E[j + k * c_j]) (otherwise, for k \in 1..6)
For each cell, calculate how many turns to win on average.
For cell[k] with k>=n, this is 0.
For other cells with k<n, it 1 plus the average of turns to win at cell[1..6*c_k].
Cache results and don't recalculate them.
Return turns to win from cell 0.
Yes, this is seemingly nothing non-obvious. Dynamic programming is seeming to do nothing non-obvious, with an appropriately bounded cache in the middle of the naive algorithm.
The trick is arranging the problem to have a cache with good bounds that makes a naive algorithm collapse into not doing much work.

Random selection of a number from a list of numbers that is biased toward the lowest number

At every moment t, I have a different set of positive integers. I need to randomly select one of them, satisfying the criteria that the probability of a particular number to be selected from the set must be proportionally higher, the lower is the value of the number. At moment t+1, we have another set of positive integers, and again we need to select one of them satisfying the same criteria. So on, so forth. How to do this in c++?
One way would be to assign ranges to each number, randomize a value, and pick the number which has the range in which the randomized value is included.
Example
Input:
1 2 3
Ranges:
[0,300) [300, 450) [450, 550)
Probability for each number:
~55% ~27% ~18%
With random value between 0 and 550, ex. 135 the selected number would be 1 since 0 <= 135 < 300.
As to how you do this in C++, try it for yourself first.
What you're talking about is basically the Geometric distribution, or at least a chopped and normalized variant of it.
C++11 includes a geometric distribution generator, and you can use that directly if you like, but to keep things simple, you can also do something like this:
int genRandom(int count)
{
while(true)
{
int x = 0;
while(x < count-1)
{
if(rand() < RAND_MAX/2) // with probability 0.5...
{
return x;
}
x++;
}
}
}
Note that here I'm using rejection sampling to ensure that a value gets picked, rather than return count-1 if I run past it (which would give the last two items equal probability).

Calculating the mean of the data

/***************************************************************************
Description : Calculates the trimmed mean of the data.
Comments : trim defaults to 0. Trim = 0.5 now gives the median.
***************************************************************************/
Real StatData::mean(Real trim) const
{
check_trim(trim);
if (size() < 1)
err << "StatData::mean: no data" << fatal_error;
Real result = 0;
const_cast<StatData&>(*this).items.sort();
int low = (int)(size()*trim); // starting at 0
int high = size() - low;
if (low == high) {
low--; high++;
}
for(int k = low; k < high; k++)
result += items[k];
ASSERT(2*low < size()); // Make sure we're not dividing by zero.
return result / (size() - 2*low);
}
I have three questions to ask:
1) Is *this referring to StatData?
2) Why is ASSERT(2*low < size()) checking for not dividing by zero?
3) The mean value usually means the total sum divided by the total size. but why are we doing size()-2*low?
Before we start, let's take a little bit of time to explain what the parameter trim is.
trim denotes how much fraction of data you want to cut off from both ends of the data before you want to compute what you need, assuming this is in sorted order. By doing trim = 0.5, you are cutting everything off except for considering the middle, which is the median. By doing trim = 0.1 for example, the first 10% and the last 10% of the data are discarded, and you only compute the mean within the remaining 80% of the data. Note that this is a normalized fraction between [0,1]. This fraction is then multiplied by size() to determine which index in your data we need to start from when computing the mean - denoted by low, and also which index to stop at - denoted by high. high is simply computed by size() - low, as the amount of data to cut off on both sides needs to be symmetric. This is actually sometimes called the alpha trimmed mean, or more commonly known as the truncated mean. The reason why it is also called alpha trimmed mean is because alpha defines how much of a fraction you want to cut off from the beginning and end of your sorted data. Equivalently in our case, alpha = trim.
Now onto your questions.
Question #1
The *this is referring to an instance of the current class which is of type StatData, and is ultimately trying to access items, which seems to be a container that contains some numbers of type Real. However, as Neil Kirk explained in his comment, and with what Hi I'm Dan has said, this is a very unsafe way of using const_cast so that you're able to access items so that you can sort these items. This is very bad.
Question #2
This is basically to ensure that when you're calculating the mean, you aren't dividing by zero. This condition will never be > 2*low because the size of your data will never get higher than this point. They check to see if size() < 2*low to ensure that you are going to divide the summation of your data by a number > 0, which is what we expect from the arithmetic mean. Should this condition fail, this means that computing the mean is not possible, and it should output an error.
Question #3
You are dividing by size() - 2*low because you are using trim to discard the proportion of data from the beginning and from the end of your data you don't need. This exactly corresponds to low on the one side and low on the other side. Take note that high computes where we need to stop accumulating at the upper end, and the proportion of data that exists after this point is low. As such, the combination of these proportions that are eliminated is 2*low, which is why you need to subtract this away from size() as you aren't using that data anymore.
The function is marked const, so the developer used a rather ugly const_cast to cast the const away in order to call sort.
ASSERT appears to be a macro (due to it being in capital letters) that most likely calls assert, which terminates the program if the expression evaluates to zero.
For a summary of what trimmed mean means, refer to this page.
The 10% trimmed mean is the mean computed by excluding the 10% largest
and 10% smallest values from the sample and taking the arithmetic mean
of the remaining 80% of the sample ...

How to calc percentage of coverage in an array of 1-100 using C++?

This is for an assignment so I would appreciate no direct answers; rather, any logic help with my algorithms (or pointing out any logic flaws) would be incredibly helpful and appreciated!
I have a program that receives "n" number of elements from the user to put into a single-dimensional array.
The array uses random generated numbers.
IE: If the user inputs 88, a list of 88 random numbers (each between 1 to 100) is generated).
"n" has a max of 100.
I must write 2 functions.
Function #1:
Determine the percentage of numbers that appear in the array of "n" elements.
So any duplicates would decrease the percentage.
And any missing numbers would decrease the percentage.
Thus if n = 75, then you have a maximum possible %age of 0.75
(this max %age decreases if there are duplicates)
This function basically calls upon function #2.
FUNCTION HEADER(GIVEN) = "double coverage (int array[], int n)"
Function #2:
Using a linear search, search for the key (key being the current # in the list of 1 to 100, which should be from the loop in function #1), in the array.
Return the position if that key is found in the array
(IE: if this is the loops 40th run, it will be at the variable "39",
and will go through every instance of an element in the array
and if any element is equal to 39, all of those positions will be returned?
I believe that is what our prof is asking)
Return -1 if the key is not found.
Given notes = "Only function #1 calls function #2,
and does so to find out if a certain value (key) is found among the first n elements of the array."
FUNCTION HEADER(GIVEN) = "int search (int array[], int n, int key)"
What I really need help with is the logic for the algorithm.
I would appreciate any help with this as I would approach this problem completely differently than our professor wants us.
My first thoughts would be to loop through function #1 for all variable keys of 1 through 100.
And in that loop, go to the search function (function #2), in which a loop would go through every number in the array and add to a counter if a number was (1)a duplicate or (2) non-existent in the array. Then I would subtract that counter from 100. Thus if all numbers were included in the array except for the #40 and #41, and then #77 was a duplicate , the total percentage of coverage would be 100 - 3 = 97%.
Although as I type this I think that may in of itself be flawed? ^ Because with a max of 100 elements in the array, if the only number missing was 99, then you would subtract 1 for having that number missing, and then if there was a duplicate you would subtract another 1, and thus your percentage of coverage would be (100-2) = 98, when clearly it ought to be 99.
And this ^ is exactly why I would REALLY appreciate any logic help. :)
I know I am having some problems approaching this logically.
I think I can figure out the coding with a relative amount of ease; what I am struggling witht he most is the steps to take. So any pseudocode ideas would be amazing!
(I can post my entire program code so far if necessary for anyone, just ask, but it is rather long as of now as I have many other functions performing other tasks in the program)
I may be mistaken, but as I read it all you need to do is:
write a function that loops through the array of n elements to find a given number in it. It would return the index of first occurence, or a negative value in case the number cannot be found in the array.
write a loop to call the function for all numbers 1 to 100 and count the finds. Then divide the result by 100.
I'm not sure if I understand this whole thing right, but 1 function you can do it, if you don't care about speed, it's better to put array into a vector, loop through 1..100 and use boost find function http://www.boost.org/doc/libs/1_41_0/doc/html/boost/algorithm/find_nth.html. There you can compare current value with the second entry value in the vector, if it contains you decrease, not not decrease, if you want to find if the unique number is in array, use http://www.cplusplus.com/reference/algorithm/find/. I don't understand, how the percentage decreases, so it's on your own and I don't rly understand second function, but if its linear search use again find.
P.S. Vector description http://www.cplusplus.com/reference/vector/vector/begin/.
You want to know how many numbers in the range [1, 100] appear in your given array. You can search for each number in turn:
size_t count_unique(int array[], size_t n)
{
size_t result = 0;
for (int i = 1; i <= 100; ++i)
{
if (contains(array, n, i))
{
++result;
}
}
return result;
}
All you still need is an implementation of the containment check contains(array, n, i), and to transform the unique count into a percentage (by using division).

C++ minimax function

I have searched Google and Stackoverflow for this question, but I still don't understand how a minimax function works.
I found the wikipedia entry has a pseudocode version of the function:
function integer minimax(node, depth)
if node is a terminal node or depth <= 0:
return the heuristic value of node
α = -∞
for child in node: # evaluation is identical for both players
α = max(α, -minimax(child, depth-1))
return α
Several other minimax functions I found with Google are basically the same thing; I'm trying to implement this in C++, and this is what I have come up with so far:
double miniMax(Board eval, int iterations)
{
//I evaluate the board from both players' point of view and subtract the difference
if(iterations == 0)
return boardEval(eval, playerNumber) - boardEval(eval, opponentSide());
/*Here, playerTurn tells the findPossibleMoves function whose turn it is;
I mean, how do you generate a list of possible moves if you don't even know
whose turn it's supposed to be? But the problem is, I don't see where I can
get playerTurn from, as there are only 2 parameters in all the examples of
minimax I've seen*/
vector<int> moves = eval.findPossibleMoves(playerTurn);
//I'm assuming -∞ in the wikipedia article means a very low number?
int result = -999999999;
//Now I run this loop to evaluate each possible move
/*Also, the Lua example in the wiki article has
alpha = node.player==1 and math.max(alpha,score) or math.min(alpha,score)
Is alpha a boolean there?!*/
for(int i = 0; i * 2 < moves.size(); i++)
{
//I make a copy of the board...
Board temp = eval;
/*and make the next possible move... once again playerTurn crops up, and I
don't know where I can get that variable from*/
temp.putPiece(moves[i * 2], moves[i * 2 + 1], playerTurn);
/*So do I create a function max that returns the bigger of two doubles?*/
result = max(result, -miniMax(temp, iterations - 1));
}
return result;
/*So now I've returned the maximum score from all possible moves within a certain
# of moves; so how do I know which move to make? I have the score; how do I know
which sequence of moves that score belongs to?*/
}
As you can see, I'm pretty confused about this minimax function. Please at the very least give me some hints to help me with this.
Thanks! :)
That sample from Wikipedia is doing NegaMax with Alpha/Beta pruning.
You may be helped by getting the naming straight:
The basis is MiniMax, a literal implementation would involve 2 methods that take turns (mutually recursive), 1 for each side.
Lazy programmers turn this into NegaMax, one method with a strategically placed - operator.
Alpha/Beta pruning is keeping track of a Window of best moves (over multiple depths) to detect dead branches.
Your playerTurn is used to determine whose turn it is . In NegaMax you can derive this from the depth (iterations) being odd or even. But it would be easier to use 2 parameters (myColor, otherColor) and switch them at each level.
Your miniMax() function should remember the best move it found so far. So instead of this code:
/*So do I create a function max that returns the bigger of two doubles?*/
result = max(result, -miniMax(temp, iterations - 1));
You should do something like this:
/*So do I create a function max that returns the bigger of two doubles?*/
double score = -miniMax(temp, iterations - 1);
if (score > result)
{
result = score;
bestMove = i;
}
Of course, you need a variable "bestMove" and a way to return the best move found to the caller.
Add the playerTurn variable as an argument to miniMax, and call miniMax which the current player's move initially and recursively.
Also, opponentSide needs to be a function of playerTurn.
A good place to start with game tree searching is the chess programming wiki. For your question about the move: I think it is most common to have two max-functions. The difference between the two max functions is that one returns only the score and the other returns the score and the best move. A recursive call order would be like following:
maxWithBestMoveReturn(...) --> min(...) --> max(...) --> min(...)
There are some good papers with pseudocode for the Alpha Beta algorithm:
TA Marsland - Computer Chess and Search
J Schaeffer - The games Computers (and People) Play
To your question in the comment: and math.max(alpha,score) or math.min(alpha,score) Is alpha a boolean there?!
No alpha is a window bound in a alpha beta algorithm. The alpha value gets updated with a new value. Because alpha and beta are swapped with the recursive call of the negamax-Function the alpha variable refers to the beta variable in the next recursive call.
One note to the playerTurn variable: The minimax or alpha-beta algorithm doesn't need this information. So i would give the information -- who's next --, into the Board-Structure. The functions findPossibleMoves and boardEval get all information they need from the Board-Structure.
One note to the recursive break condition: If i understand your code right, then you only have the one with iterations == o. I think this means the algorithm has reached the desired depth. But what if there are no possible moves left befor the algorithm reaches this depth. Maybe you should write following:
vector<int> moves = findPossibleMoves(...);
if (!moves.size())
return boardEval(...);
In your pseudocode, the node variable has to contain all the information about the current board position (or whatever). This information would include whose turn it is to move.