2 Player game is in PSPACE - time

So I have given a boolean formula Q with 2n variables.Denoted by Q(x1...xn,y1...yn) and it is mentioned that there exists a1....an belonging to{0,1} such that for every b1...bn belonging to {0,1} Q(a1...an,b1,....bn} evaluates to true now the question is to show that this is in PSPACE and U DTIME(2^kn) complexity class.
Now i believe this is just like a two player in which player A has a winning strategy.
and if i can write a program that takes exponential time and polynomial space i will solve it.
now that program should return true if a choice exists for player A ie after he chooses a value for ai from 0 and 1 no matter whatever bi player B chooses and whatever value 0,1 he gives the formula will always evaluate to true.
So i am thinking on the terms of
for ai=a1 to an
{
flag =true;
for j=0 to 1
{
set ai =j;
//check all possible combination of bi's and check the formula
//if formula evaluates to false ,set flag =false and break,
//try the next j for ai;
}
//if flag =false then ai is not a good selection ,select another ai
//if flag =true yes we have a good selection of ai ,
//player 1 will always win in this case
return true and break;
}
is this approach correct ,also can i check all the combination of bi's using the same approach
for bi=b1 to bn
{
for j=0 to 1
{
//evaluate formula here
//but the problem is i do not have all the values of ai's
// i have only one value of ai ,what will i substitute for the rest
}
}
Any suggestion and new approach to tackle this type of problem will be appreciated

It's in DTIME(2**2n). Brute force algorithm:
//requires n bits space, 2**n iterations of check() or 2**2n time total
loop over all possibilities to choose (a1,...,an):
if (check(Q, (a1,..., an))):
return (a1,...,an);
return null
check(Q, (a1,...,an)):
//requires n bits space, 2**n iterations
loop over all possibilities to choose (b1,...,bn):
if (! Q(a1, ..., an, b1, ..., bn)):
return false
return true

Related

Recurrence relation for variation of Nim Game

I am struggling to get the optimal subtructure to solve the problem i.e. the recurrence that has to be followed and upon which Dynamic Programming Solution can be build for optimizing the Time Complexity.
Suppose A and B have 2 kinds of Stones. There are A stones of the first type and B of the second
type. They decide to play a game according to rules such in each turn one of the following valid moves can be done:
Pick some Stones of first type
Pick some Stones of Second type
Pick equal number of Stone of both type
They have to pick atleast one Stone in each turn. Whoever makes the last move wins the game. Both play optimally. However while telling the rules of the competition, Alice cheated a bit to ensure that she wins the game by deciding who will take the first move.
Given the Stones, determine if Alice takes the first move or not.
You can work backwards from a winning position.
If all remaining stones are of either the first of the second type, or if there are an equal amount of stones from each type, the player whose turn it is wins - by picking all remaining stones.
In any other position, the player whose turn it is can reduce the number of stones of either the first or second type by one or more, or can reduce the number of both types of stones by one or more. If all of the resulting positions are winning, this position is losing. If at least one of the resulting positions is losing, the player can choose that one, so this position is winning.
More formally, for a game with A stones of the first type and B stones of the second type, create a table N[A+1, B+1] of booleans, where true means winning and false means losing.
Then just fill the table like this:
for (a = 0; a <= A; a++) {
for (b = 0; <= B; b++) {
if (a == 0 || b == 0 || a == b) {
// case 1, always winning
N[a, b] = true;
} else {
// case 2, winning if there is a losing position reachable
if (
there is an 1 <= i <= a, such that N[a-i, b] is false
OR there is an 1 <= i <= b, such that N[a, b-i] is false
OR there is an 1 <= i <= min(a, b), such that N[a-i, b-i] is false
) {
N[a, b] = true;
} else {
N[a, b] = false;
}
}
}
}
After filling the table, Alice should start if N[A, B] is true and let Bob start otherwise.
Posting this as a separate answer because it so different from the other. I'll leave that answer too because this technique is probably not very useful for similar problems.
By running an example with 10 stones of each type by hand, I found that the only losing positions are (1, 2), (3, 5), (4, 7), (6, 10). There is a search engine for integer sequences where one can search for known formulas given the start of the sequence, called OEIS
So there is sequence A072061, which matches this one. This teaches us two things:
This is a known problem and the game is more commonly known as Wythoff's game
All losing positions are given by the formula (a(2*k), a(2*k+1)) for some integer k and a(n) = n*(1+(-1)^n)/4+floor((2*n+1-(-1)^n)*(1+sqrt(5))/8)
So to determine if Alice should start, you can compute if (A, B) is a losing position using the given formula.

Check whether A and B exists for the given values AorB and APlusB

Problem Statement:
You are given two non-negative integers: the longs pairOr and pairSum.
Determine whether it is possible that for two non-negative integers A and B we have both:
A or B = pairOr
A + B = pairSum
Above, "or" denotes the bitwise-or operator.
Return True if we can find such A and B, and False if not.
My Algorithm goes like this:
I've taken the equation: A | B = X and A + B =Y,
Now after substituting A's value from 2nd Equation, (Y-B) | B= X.
I'm going to traverse from 0 till Y (in place of B) to check if the above equation is true.
Code Snippet:
boolean isPossible(long orAandB,long plusAandB) {
for(long i=0;i<=plusAandB;i++) {
if(((plusAandB-i)|i)==orAandB ){
return true;
}
}
return false;
It will give TLE if the value of plusAndB is of number 10^18. Could you please help me optimize?
You don't need the full iteration, giving O(N). There's a way to do it in O(logN).
But completely solving the problem for you takes away most of the fun... ;-), so here's the main clue:
Your equation (Y-B) | B= X is one great observation, and the second is to have a look at this equation bit by bit, starting from the right (so you don't have to worry about borrow-bits in the first place). Which last-bit combinations of Y, X, and B can make your equation true? And if you found a B bit, how do you continue recursively with the higher bits (don't forget that subtraction may need a borrow)? I hope you remember the rules for subtracting binary numbers.
And keeping in mind that the problem only asks for true or false, not for any specific A or B value, can save you exponential complexity.

Simulating fake coin using array

There are 70 coins and out of which there is one fake coin. Need to detect the fake coin in minimum number of weighing. You have only a weighing scale and you know that the fake coin is lighter.
I am not sure if the below simulation of the problem is right or wrong i.e. representing it in a array and doing the comparison as i have done in my code. I am trying to simulate it with a array with all one's except one zero which is considered as fake coin. Below is my code. Please let me know if i have got it wrong.
It would be really be helpful if someone can prove/explain why 3 way division is better in simple maths.
Pseudo code for the below code:
INPUT : integer n
if n = 1 then
the coin is fake
else
divide the coins into piles of A = ceiling(n/3), B = ceiling(n/3),
and C = n-2*ceiling(n/3)
weigh A and B
if the scale balances then
iterate with C
else
iterate with the lighter of A and B
Code:
import random
def getmin(data, start, end, total_items):
if total_items == 1:
#for sure we have a fake coin
return (0, start)
elif total_items == 2:
if data[start] > data[end]:
return (1, end)
elif data[start] < data[end]:
return (1, start)
else:
partition = total_items/3
a_weight = sum(data[start:start+partition])
b_weight = sum(data[start+partition:start+2*partition])
c_weight = sum(data[start+2*partition:end])
if a_weight == b_weight:
result = getmin(data, start+2*partition, end, end-(start+2*partition))
return (1+result[0], result[1])
else:
if a_weight > b_weight:
result = getmin(data, start+partition, start+2*partition, partition)
return (1+result[0], result[1])
else:
result = getmin(data, start, start+partition, partition)
return (1+result[0], result[1])
n = int(raw_input())
data = [1]*n
data[random.randint(0, n-1)] = 0
total_weighing, position = getmin(data, 0, len(data), len(data))
print(total_weighing, position)
The complexity of this algorithm is O(log3N) because you reduce your problem size to 1/3 in each iteration. Complexity-wise O(log3(n)) == O(log2(n)) == O(log10(n)) so it doen't matter if you divide your problem size by 3 or by 10. The only better complexity is O(1) and that means regardless of size of the problem you can find the fake coin in a fixed number of operations, which is quite unlikely.
Note that in this algorithm we assume that we can find the sum of a range of elements in O(1), Otherwise the algorithm's complexity is O(n).
You ask "why 3-way division is better in simple maths." Better than what? In this problem, it's the best solution because it achieves the answer in the fewest weighings. The properties of a trivial balance scale yield three basic results: left is heavier, right is heavier, and equal weights. That's a 3-way decision, so information theory yields that the best algorithm is to divide the objects in three (if you can practically achieve it) at each phase.
You need 4 weighings for 28-81 coins.
Fortunately, your problem allows for exhaustive testing.
The code above performs one trial of random testing. That's okay for starters, but with only 70 cases to check, I recommend that you try them all. Wrap your main program in a loop over range(70), something like this:
n = 70
for bad_coin in range(70):
data = [1]*n
data[bad_coin] = 0
total_weighing, position = getmin(data, 0, n, n)
print ("trial", bad_coin)
if total_weighing != 4:
print ("Wrong number of weighings:", total_weighing)
if position != bad_coin:
print ("Wrong ID:", position)
This will quickly show any error in your program for the assigned 70 coins.
BTW, replace the if statements with assert, if you're comfortable with that feature.

Find a math algorithm for an equation

I just post a mathematic question at math.stackexchange, but I'll ask people here for a programmatically recursive algorithm.
The problem: fill in the blank number from 1 to 9 (once and only once each blank) to finish the equation.
Additional conditions:
1. Mathematic priority DOES matter.
2. All numbers (include evaluation result) should be integers.
Which mean the divide should be divisible (E.g. 9 mod 3 = 0 is OK, 8 mod 3 != 0 is not OK).
3. For those who don't know (as one in the original question), the operations in the diagram are:
+ = plus; : = divide; X = multiple; - = minus.
There should be more than 1 answer. I'd like to have a recursive algorithm to find out all the solutions.
Original question
PS: I'd like to learn about the recursive algorithm, performance improval. I was trying to solve the problem using brute force. My PC freeze for quite a while.
You have to find the right permuations
9! = 362880
This is not a big number and you can do your calculations the following way:
isValid(elements)
//return true if and only if the permutation of elements yields the expected result
end isValid
isValid is the validator, which checks whether a given permutation is correct.
calculate(elements, depth)
//End sign
if (depth >= 9) then
//if valid, then store
if (isValid(elements)) then
store(elements)
end if
return
end if
//iterate elements
for element = 1 to 9
//exclude elements already in the set
if (not contains(elements, element)) then
calculate(union(elements, element), depth + 1)
end if
end for
end calculate
Call calculate as follows:
calculate(emptySet, 1)
Here's a solution using PARI/GP:
div(a,b)=if(b&&a%b==0,a/b,error())
f(v)=
{
iferr(
v[1]+div(13*v[2],v[3])+v[4]+12*v[5]-v[6]-11+div(v[7]*v[8],v[9])-10==66
, E, 0)
}
for(i=0,9!-1,if(f(t=numtoperm(9,i)),print(t)))
The function f defines the particular function here. I used a helper function div which throws an error if the division fails (producing a non-integer or dividing by 0).
The program could be made more efficient by splitting out the blocks which involve division and aborting early if they fail. But since this takes only milliseconds to run through all 9! permutations I didn't think it was worth it.

Algorithm to find matching pairs in a list

I will phrase the problem in the precise form that I want below:
Given:
Two floating point lists N and D of the same length k (k is multiple of 2).
It is known that for all i=0,...,k-1, there exists j != i such that D[j]*D[i] == N[i]*N[j]. (I'm using zero-based indexing)
Return:
A (length k/2) list of pairs (i,j) such that D[j]*D[i] == N[i]*N[j].
The pairs returned may not be unique (any valid list of pairs is okay)
The application for this algorithm is to find reciprocal pairs of eigenvalues of a generalized palindromic eigenvalue problem.
The equality condition is equivalent to N[i]/D[i] == D[j]/N[j], but also works when denominators are zero (which is a definite possibility). Degeneracies in the eigenvalue problem cause the pairs to be non-unique.
More generally, the algorithm is equivalent to:
Given:
A list X of length k (k is multiple of 2).
It is known that for all i=0,...,k-1, there exists j != i such that IsMatch(X[i],X[j]) returns true, where IsMatch is a boolean matching function which is guaranteed to return true for at least one j != i for all i.
Return:
A (length k/2) list of pairs (i,j) such that IsMatch(i,j) == true for all pairs in the list.
The pairs returned may not be unique (any valid list of pairs is okay)
Obviously, my first problem can be formulated in terms of the second with IsMatch(u,v) := { (u - 1/v) == 0 }. Now, due to limitations of floating point precision, there will never be exact equality, so I want the solution which minimizes the match error. In other words, assume that IsMatch(u,v) returns the value u - 1/v and I want the algorithm to return a list for which IsMatch returns the minimal set of errors. This is a combinatorial optimization problem. I was thinking I can first naively compute the match error between all possible pairs of indexes i and j, but then I would need to select the set of minimum errors, and I don't know how I would do that.
Clarification
The IsMatch function is reflexive (IsMatch(a,b) implies IsMatch(b,a)), but not transitive. It is, however, 3-transitive: IsMatch(a,b) && IsMatch(b,c) && IsMatch(c,d) implies IsMatch(a,d).
Addendum
This problem is apparently identically the minimum weight perfect matching problem in graph theory. However, in my case I know that there should be a "good" perfect matching, so the distribution of edge weights is not totally random. I feel that this information should be used somehow. The question now is if there is a good implementation to the min-weight-perfect-matching problem that uses my prior knowledge to arrive at a solution early in the search. I'm also open to pointers towards a simple implementation of any such algorithm.
I hope I got your problem.
Well, if IsMatch(i, j) and IsMatch(j, l) then IsMatch(i, l). More generally, the IsMatch relation is transitive, commutative and reflexive, ie. its an equivalence relation. The algorithm translates to which element appears the most times in the list (use IsMatch instead of =).
(If I understand the problem...)
Here is one way to match each pair of products in the two lists.
Multiply each pair N and save it to a structure with the product, and the subscripts of the elements making up the product.
Multiply each pair D and save it to a second instance of the structure with the product, and the subscripts of the elements making up the product.
Sort both structions on the product.
Make a merge-type pass through both sorted structure arrays. Each time you find a product from one array that is close enough to the other, you can record the two subscripts from each sorted list for a match.
You can also use one sorted list for an ismatch function, doing a binary search on the product.
well。。Multiply each pair D and save it to a second instance of the structure with the product, and the subscripts of the elements making up the product.
I just asked my CS friend, and he came up with the algorithm below. He doesn't have an account here (and apparently unwilling to create one), but I think his answer is worth sharing.
// We will find the best match in the minimax sense; we will minimize
// the maximum matching error among all pairs. Alpha maintains a
// lower bound on the maximum matching error. We will raise Alpha until
// we find a solution. We assume MatchError returns an L_1 error.
// This first part finds the set of all possible alphas (which are
// the pairwise errors between all elements larger than maxi-min
// error.
Alpha = 0
For all i:
min = Infinity
For all j > i:
AlphaSet.Insert(MatchError(i,j))
if MatchError(i,j) < min
min = MatchError(i,j)
If min > Alpha
Alpha = min
Remove all elements of AlphaSet smaller than Alpha
// This next part increases Alpha until we find a solution
While !AlphaSet.Empty()
Alpha = AlphaSet.RemoveSmallest()
sol = GetBoundedErrorSolution(Alpha)
If sol != nil
Return sol
// This is the definition of the helper function. It returns
// a solution with maximum matching error <= Alpha or nil if
// no such solution exists.
GetBoundedErrorSolution(Alpha) :=
MaxAssignments = 0
For all i:
ValidAssignments[i] = empty set;
For all j > i:
if MatchError <= Alpha
ValidAssignments[i].Insert(j)
ValidAssignments[j].Insert(i)
// ValidAssignments[i].Size() > 0 due to our choice of Alpha
// in the outer loop
If ValidAssignments[i].Size() > MaxAssignments
MaxAssignments = ValidAssignments[i].Size()
If MaxAssignments = 1
return ValidAssignments
Else
G = graph(ValidAssignments)
// G is an undirected graph whose vertices are all values of i
// and edges between vertices if they have match error less
// than or equal to Alpha
If G has a perfect matching
// Note that this part is NP-complete.
Return the matching
Else
Return nil
It relies on being able to compute a perfect matching of a graph, which is NP-complete, but at least it is reduced to a known problem. It is expected that the solution be NP-complete, but this is OK since in practice the size of the given lists are quite small. I'll wait around for a better answer for a few days, or for someone to expand on how to find the perfect matching in a reasonable way.
You want to find j such that D(i)*D(j) = N(i)*N(j) {I assumed * is ordinary real multiplication}
assuming all N(i) are nonzero, let
Z(i) = D(i)/N(i).
Problem: find j, such that Z(i) = 1/Z(j).
Split set into positives and negatives and process separately.
take logs for clarity. z(i) = log Z(i).
Sort indirectly. Then in the sorted view you should have something like -5 -3 -1 +1 +3 +5, for example. Read off +/- pairs and that should give you the original indices.
Am I missing something, or is the problem easy?
Okay, I ended up using this ported Fortran code, where I simply specify the dense upper triangular distance matrix using:
complex_t num = N[i]*N[j] - D[i]*D[j];
complex_t den1 = N[j]*D[i];
complex_t den2 = N[i]*D[j];
if(std::abs(den1) < std::abs(den2)){
costs[j*(j-1)/2+i] = std::abs(-num/den2);
}else if(std::abs(den1) == 0){
costs[j*(j-1)/2+i] = std::sqrt(std::numeric_limits<double>::max());
}else{
costs[j*(j-1)/2+i] = std::abs(num/den1);
}
This works great and is fast enough for my purposes.
You should be able to sort the (D[i],N[i]) pairs. You don't need to divide by zero -- you can just multiply out, as follows:
bool order(i,j) {
float ni= N[i]; float di= D[i];
if(di<0) { di*=-1; ni*=-1; }
float nj= N[j]; float dj= D[j];
if(dj<0) { dj*=-1; nj*=-1; }
return ni*dj < nj*di;
}
Then, scan the sorted list to find two separation points: (N == D) and (N == -D); you can start matching reciprocal pairs from there, using:
abs(D[i]*D[j]-N[i]*N[j])<epsilon
as a validity check. Leave the (N == 0) and (D == 0) points for last; it doesn't matter whether you consider them negative or positive, as they will all match with each other.
edit: alternately, you could just handle (N==0) and (D==0) cases separately, removing them from the list. Then, you can use (N[i]/D[i]) to sort the rest of the indices. You still might want to start at 1.0 and -1.0, to make sure you can match near-zero cases with exactly-zero cases.

Resources