fastest implementation to cut n×n board into n connected n-minos - complexity-theory

I am attempting to create a puzzle to let players piece together an n×n grid using n connected n-minos (definition: connected piece of n 1×1 blocks, e.g. each of the Tetris pieces is a 4-mino). However, generating a way to cut the grid first proves to be a challenge despite seemingly easy enough for a human.
example board
For human, generating such a solution is a relative easy task by recursively following the following logic/pseudo-code:
:start_of_recursion:
Start with a random "least connected" piece (end, corner, edge pieces that has the fewest member connecting to it) to be the starting mino block
:start_of_recursion:
Make a "grow" in a random available direction from a random piece in the current mino
If "grow" results in a "separated" remaining board(, if the separated region isn't a multiple of n), try some other location and direction
if all location and direction has been attempted, revert to previous board configuration (shouldn't really occur?)
If size-n has been reached, exit recursion
:end_of_recursion:
if board has been filled, exit recursion
:end_of_recursion:
Performing this routine seem to generate an O(n^2) method of solution generation, however the condition checks prove to be really expensive for computers. In order to determine whether the board to be connected, a human simply checks for any "gap" inside the remaining region, and is processed in almost O(1) fashion for a simple non-overlapping graph, whereas my code implementation need to "spread" from a point on the graph into its neighboring territories and check after the spreading is complete to check whether if any points lies outside of reach (O(n) at best). Since this check is to be performed every time in the innermost iteration, it degenerates the complexity into an O(n^(3+)) problem and becomes really inefficient.
Is there a method to check for "gap" in a manner similar to that of human cognition? Or can the problem be fundamentally thought of and simplified into a problem easier for computer to solve?

Your problem sounds like a variant of bin packing problem. I would approach this by constraint satisfaction method. Below I'll use Minizinc pseudo-code.
A board consists of cells, each cell could be colored into one color from several. We can represent it as follows:
int: rows;
int: cols;
int: colors_num;
array [1...colors_num] of int: colors;
array [1..rows,1..cols] of var colors: board;
Next, we add constraints. For example, if a cell has color A then atleast 1 adjacent cell must have the same color A:
constraint forall (c in colors) (
if board[i, j] == c then
at_least (1, [board[i-1, j], board[i+1, j], board[i, j-1], board[i,j+1]], c)
else
true
endif
You can describe all allowed/prohibited shapes as constraints or use some other smart approach introducing possible cuts.
Constraint satisfaction should be much more efficient than your recursive approach. However, it's not very scalable - if you'll try to generate a game for a gigantic board (hundreds or thousands of cells/colors), it will take quite some time and memory to generate minos.

Related

Chess programming: minimax, detecting repeats, transposition tables

I'm building a database of chess evaluations (essentially a map from a chess position to an evaluation), and I want to use this to come up with a good move for given positions. The idea is to do a kind of "static" minimax, i.e.: for each position, use the stored evaluation if evaluations for child nodes (positions after next ply) are not available, otherwise use max (white to move)/min (black to move) evaluations of child nodes (which are determined in the same way).
The problem are, of course, loops in the graph, i.e. repeating positions. I can't fathom how to deal with this without making this infinitely less efficient.
The ideas I have explored so far are:
assume an evaluation of 0 for any position that can be reached in a game with less moves than are currently evaluated. This is an invalid assumption, because - for example - if White plays A, it might not be desirable for Black to follow up with x, but if White plays B, then y -> A -> x -> -B -> -y might be best line, resulting in the same position as A -> x, without any repetitions (-m denoting the inverse move to m here, lower case: Black moves, upper case: White moves).
having one instance for each possible way a position can be reached solves the loop problem, but this yields a bazillion of instances in some positions and is therefore not practical
the fact that there is a loop from a position back to that position doesn't mean that it's a draw by repetition, because playing the repeating line may not be best choice
I've tried iterating through the loops a few times to see if the overall evaluation would become stable. It doesn't, because in some cases, assuming the repeat is the best line means it isn't any longer - and then it goes back to the draw being the back line etc.
I know that chess engines use transposition tables to detect positions already reached before, but I believe this doesn't address my problem, and I actually wonder if there isn't an issue with them: a position may be reachable through two paths in the search tree - one of them going through the same position before, so it's a repeat, and the other path not doing that. Then the evaluation for path 1 would have to be 0, but the one for path 2 wouldn't necessarily be (path 1 may not be the best line), so whichever evaluation the transposition table holds may be wrong, right?
I feel sure this problem must have a "standard / best practice" solution, but google failed me. Any pointers / ideas would be very welcome!
I don't understand what the problem is. A minimax evaluation, unless we've added randomness to it, will have the exact same result for any given board position combined with who's turn it is and other key info. If we have the space available to store common board_position+who's_turn+castling+en passant+draw_related tuples (or hash thereof), go right ahead. When reaching that tuple in any other evaluation, just return the stored value or rely on its more detailed record for more complex evaluations (if the search yielding that record was not exhaustive, we can have different interpretations for it in any one evaluation). If the program also plays chess with time limits on the game, an additional time dimension (maybe a few broad blocks) would probably be needed in the memoisation as well.
(I assume you've read common public info about transposition tables.)

Markov chains and Random walks on top of biological data

I'm coming from biology's field and thus I have some difficulties in understanding (intuitively?) some of the ideas of that paper. I really tried my best to decipher it step by step by using a lot of google and youtube, but now I feel, it's the time to refer to the professionals in that field.
Before filling out the whole universe with (unordered) questions, let me put the whole thing down and try to introduce you to the subject while at the same time explain to you what I got so far from my research on that.
Microarrays
For those that do not have any idea of what this is, you can imagine, that it is literally an array (matrix) where each cell of it contains a probe for a specific gene. Making the long story short, by the end of the microarray experiment, you have a matrix (in computational terms) with each column representing a sample, each line a different gene while the contents of the matrix represent the expression values of the genes for each sample.
Pathways
In biology pathway / gene-set they call a set of genes that interact with each other forming a small network responsible for a specific function.These pathways are not isolated but they talk/interact with each other too. What that paper does on the first hand, is to expand the initial pathway (let us call it target pathway), by including some other genes from other pathways that might interact with that.
Procedure
1.
Let's assume now that we have a matrix G x S. Where G for genes and S for Samples. We construct a gene co-expression network (G x G) using as weights the Pearson's correlation coefficients between genes' pairs (a). This could also be represented as an undirected weighted graph. .
2.
For each gene (row OR column) we calculate the weighted degree (d) which is nothing more than the sum of all correlation coefficients of that gene.
3.
From the two previous matrices, they construct the transition matrix producing the probabilities (P) to transit from one gene to another by using the
formula
Q1. Why do they call this transition probability? Is there any intuitive way to see this as a probability in the biological context?
4.
Since we have the whole transition matrix, we can define a subnetwork of the initial one, that we want to expand it and it consisted out of let's say 15 genes. In that step, they used formula number 3 (on the paper) which transforms the values of the initial transition matrix as it says. They set the probability of 1 on the nodes that are part of the selected subnetwork because they define them as absorbing states.
Q2. In that same formula (3), I cannot understand what the second condition does. When should the probability be 0? Intuitively, in my opinion, all nodes that didn't exist in subnetwork, should have the P_ij value as a probability.
5.
After that, the newly constructed transition matrix is showed at formula (4) in the paper and I managed to understand it using this excellent article.
6.
Here is where everything is getting more blur for me and where I need the most of the help. What I imagine at that step, is that the algorithm starts randomly from one node and keep walking around the network. In order to construct a relevance function (What that exactly means?), they firstly calculate a probability called joint probability of visiting one node/edge E(i,j) and noted as :
From the other hand they seem to calculate another probability called probability of a walk of length L starting in x and denoted as :
7.
In the next step, they divide the previously calculated probabilities and calculate the number of times a random walk starts in x using the transition from i to j that I don't really understand what this means.
After that step, I lost their reasoning at all :-P.
I'm not expecting an expert to come open my mind and give me understand that procedure. What I'm expecting is some guidelines, hints, ideas, useful resources or more intuitive approaches to understanding the whole procedure. Then when I fully understand it I will try to implement it on R or python.
So any idea / critics is welcome.
Thanks.

A good randomizer for puzzle-15

I have implemented a puzzle 15 for people to compete online. My current randomizer works by starting from the good configuration and moving tiles around for 100 moves (arbitrary number)
Everything is fine, however, once in a little while the tiles are shuffled too easy and it takes only a few moves to solve the puzzle, therefore the game is really unfair for some people reaching better scores in a much higher speed.
What would be a good way to randomize the initial configuration so it is not "too easy"?
You can generate a completely random configuration (that is solvable) and then use some solver to determine the optimal sequence of moves. If the sequence is long enough for you, good, otherwise generate a new configuration and repeat.
Update & details
There is an article on Wikipedia about the 15-puzzle and when it is (and isn't) solvable. In short, if the empty square is in the lower-right corner, then the puzzle is solvable if and only if the number of inversions (an inversion is a swap of two elements in the sequence, not necessarily adjacent elements) with respect to the goal permutation is even.
You can then easily generate a solvable start state by doing an even number of inversions, which may lead to a not-so-easy-to-solve state far quicker than by doing regular moves, and it is guaranteed that it will remain solvable.
In fact, you don't need to use a search algorithm as I mentioned above, but an admissible heuristic. Such one always underestimates never overestimates the number of moves needed to solve the puzzle, i.e. you are guaranteed that it will not take less moves that the heuristic tells you.
A good heuristic is the sum of manhattan distances of each number to its goal position.
Summary
In short, a possible (very simple) algorithm for generating starting positions might look like this:
1: current_state <- goal_state
2: swap two arbitrary (randomly selected) pieces
3: swap two arbitrary (randomly selected) pieces again (to ensure solvability)
4: h <- heuristic(current_state)
5: if h > desired threshold
6: return current_state
7: else
8: go to 2.
To be absolutely certain about how difficult a state is, you need to find the optimal solution using some solver. Heuristics will give you only an estimate.
I would do this
start from solution (just like you did)
make valid turn in random direction
so you must keep track where the gap is and generate random direction (N,E,S,W) and do the move. I think this part you have done too.
compute the randomness of your placements
So compute some coefficient dependent on the order of the array. So ordered (solved) solutions will have low values and random will have high values. The equation for the coefficiet however is a matter of trial and error. Here some ideas what to use:
correlation coefficient
sum of average difference of value and its neighbors
1 2 4
3 6 5
9 8 7
coeff(6)= (|6-3|+|6-5|+|6-2|+|6-8|)/4
coeff=coeff(1)+coeff(2)+...coeff(15)
abs distance from ordered array
You can combine more approaches together. You can divide this to separated rows and columns and then combine the sub coefficients together.
loop #2 unit coefficient from #3 is high enough (treshold)
The treshold can be used also to change the difficulty.

Mutually Overlapping Subset of Activites

I am prepping for a final and this was a practice problem. It is not a homework problem.
How do I go about attacking this? Also, more generally, how do I know when to use Greedy vs. Dynamic programming? Intuitively, I think this is a good place to use greedy. I'm also thinking that if I could somehow create an orthogonal line and "sweep" it, checking the #of intersections at each point and updating a global max, then I could just return the max at the end of the sweep. I'm not sure how to plane sweep algorithmically though.
a. We are given a set of activities I1 ... In: each activity Ii is represented by its left-point Li and its right-point Ri. Design a very efficient algorithm that finds the maximum number of mutually overlapping subset of activities (write your solution in English, bullet by bullet).
b. Analyze the time complexity of your algorithm.
Proposed solution:
Ex set: {(0,2) (3,7) (4,6) (7,8) (1,5)}
Max is 3 from interval 4-5
1) Split start and end points into two separate arrays and sort them in non-decreasing order
Start points: [0,1,3,4,7] (SP)
End points: [2,5,6,7,8] (EP)
I know that I can use two pointers to sort of simulate the plane sweep, but I'm not exactly sure how. I'm stuck here.
I'd say your idea of a sweep is good.
You don't need to worry about planar sweeping, just use the start/end points. Put the elements in a queue. In every step take the smaller element from the queue front. If it's a start point, increment current tasks count, otherwise decrement it.
Since you don't need to point which tasks are overlapping - just the count of them - you don't need to worry about specific tasks duration.
Regarding your greedy vs DP question, in my non-professional opinion greedy may not always provide valid answer, whereas DP only works for problem that can be divided into smaller subproblems well. In this case, I wouldn't call your sweep-solution either.

How do I use MATLAB to solve this PDE

I have the following question on a practice exam:
I need to use MATLAB to solve it. The problem is, I have not seen a problem like this before and I'm struggling to get started.
I have my 1x1 grid, split into 10x10. I know I can calculate the whole bottom row besides the corners using 1/10 * x*2. I also know I can calculate the entire right row using (1/10)(1+t)^2. However, I cannot figure out how to get enough points to be able to fill in the values for the entire grid. I know it must have something to do with the partial derivatives given in the problem, but I'm not quite sure where they come into play (especially the u_x equation). Can someone help me get a start here?
I don't need the whole solution. Once I have enough points I can easily write a matlab program to solve the rest. Really, I think I just need the x=0 axis solved, then I just fill in the middle of the grid.
I have calculated the bottom row, minus the two corners, to be 0.001, 0.004, 0.009, 0.016, 0.025, 0.036, 0.049, 0.064, 0.081. And similarly, the entire right row is trival to calculate using the given boundry condition. I just can't piece together where to go from there.
Edit: the third boundry condition equation was mistyped. it should read:
u_x(0,t) = 1/5t, NOT u(0,t) = 1/5t
First realise that the equation you have to solve is the linear wave equation, and the numerical scheme you are given can be rewritten as
( u^(n+1)_m - 2u^n_m + u^(n-1)_m )/k^2 = ( u^n_(m-1) - 2u^n_m + u^n_(m+1) )/h^2
where k is the time step and h is the delta x in space.
The reformulated numerical scheme makes clear that the left- and right-hand sides are the second order centred finite difference approximations of u_tt and u_xx respectively.
To solve the problem numerically, however, you need to use the form given to you because it is the explicit update formula that you need to implement numerically: it gives you the solution at time n+1 as a function of the previous two times n and n-1. You need to start from the initial condition and march the solution in time.
Observe that the solution is assigned on the boundaries of the domain (x=0 and x=1), so the values of the discretized solution u^(n)_0 and u^(n)_10 are known for any n (t=n*k). At the nth time step your unknown is the vector [u^(n+1)_1, u^(n+1)_2, ..., u^(n+1)_9].
Observe also that to use the update formula to find the solution at the n+1 step, requires the knowledge of the solution at two previous steps. So, how do you start from n=0 if you need information from two previous times? This is where the initial conditions come into play.
You have the solution at n=0 (t=0), but you also have u_t at t=0. These two pieces of information combined can give you both u^0 and u^1 and get you started.
I would use the following start-up scheme:
u^0_m = u(h*m,0) // initial condition on u
(u^2_m - u^0_m)/(2k) = u_t(h*m,0) // initial condition on u_t
that combined with the numerical scheme used with n=1 gives you everything you need to define a linear system for both u^1_m and u^2_m for m=1,...,9.
To summarize:
--use the start-up scheme to find solution at n=1 and n=2 simultaneously.
--from there on march in time using the numerical scheme you are given.
If you are completely lost check out things like: finite difference schemes, finite difference schemes for advection equations, finite difference schemes for hyperbolic equations, time marching.
EDITING:
For the boundary condition on u_x you typically use the ghost cell method:
Introduce a ghost cell at m=-1, i.e. a fictitious (or auxiliary) grid point that is used to deal with boundary condition, but that is not part of the solution.
The first node m=0 is back into your unknown vector, i.e. you are now working with [u_0 u_1 ... u_9].
Use the left side boundary condition to close the system.
Specifically, by writing down the centered approx of the boundary condition
u^n_(1) - u^n_(-1) = 2*h*u_x(0,k*n)
The above equation allows you to express the solution on the ghost node in terms on the solution on an internal, real node. Therefore you can apply the time-marching numerical scheme (the one you are given) to the m=0 node. (The numerical scheme applied to m=0 would contain contributions from the m=-1 ghost node, but now you have that expressed in terms of the m=1 node.)

Resources