Algorithms for Containment/Avoidance

For bounding extremal functions ex(n, P) of forbidden 0-1 matrices P, it can be useful to calculate exact values of the extremal function for small values of n. One way to do this is to check whether any of the n x n matrices with k ones avoid P for increasing values of k.

## Naive algorithm

Suppose

A

{\displaystyle A}

 is a

h
A

×

w
A

{\displaystyle h\_A\times w\_A}

 0-1 matrix and

B

{\displaystyle B}

 is a

h
B

×

w
B

{\displaystyle h\_B\times w\_B}

 0-1 matrix. Then one naive algorithm takes

O
(

(

h
A

h
B

)

(

w
A

w
B

)

B

)

{\displaystyle O({h\_A \choose h\_B}{w\_A \choose w\_B}|B|)}

 time to decide whether

A

{\displaystyle A}

 contains

B

{\displaystyle B}

, where

B

{\displaystyle |B|}

 is the number of ones in matrix

B

{\displaystyle B}

.

## Faster algorithms for specific patterns

For many specific patterns

P

{\displaystyle P}

, it is possible to determine whether a

h
A

×

w
A

{\displaystyle h\_A\times w\_A}

 0-1 matrix contains

P

{\displaystyle P}

 in

O
(

w
A

×

h
A

)

{\displaystyle O(w\_A\times h\_A)}

 time.

k
×
1

{\displaystyle k \times 1 }

## matrix with all ones

One of the easiest cases is a

k
×
1

{\displaystyle k \times 1 }

 matrix with all ones. If

B

{\displaystyle B}

 is

k
×
1

{\displaystyle k \times 1 }

 with all ones, then an

O
(

w
A

×

h
A

)

{\displaystyle O(w\_A\times h\_A)}

 algorithm scans

A

{\displaystyle A}

 column by column, and whenever it finds any column of

A

{\displaystyle A}

 with at least

k

{\displaystyle k}

 ones, it stops and determines

A

{\displaystyle A}

 contains

B

{\displaystyle B}

. Otherwise

A

{\displaystyle A}

 doesn't contain

B

{\displaystyle B}

 after the algorithm scans through all columns.

k
×
k

{\displaystyle k \times k}

## identity matrix

If

B

{\displaystyle B}

 is a

k
×
k

{\displaystyle k \times k}

 identity matrix. The following algorithm takes

O
(

w
A

×

h
A

)

{\displaystyle O(w\_A\times h\_A)}

 time.

It maintains an array

D
[

h
A

]
[

w
A

]

{\displaystyle D[h\_A][w\_A]}

. For

1
≤
r
≤

h
A

{\displaystyle 1\leq r\leq h\_A}

,

D
[
r
]
[
c
]

{\displaystyle D[r][c]}

 is the
maximum number of ones from column

c

{\displaystyle c}

 to the last column of

A

{\displaystyle A}

 such that (1) all these ones are in rows between

r

{\displaystyle r}

 and

h
A

{\displaystyle h\_A}

, inclusive. (2) all these ones form a

D
[
r
]
[
c
]
×
D
[
r
]
[
c
]

{\displaystyle D[r][c]\times D[r][c]}

 identity matrix when we remove all columns and rows not containing these ones.

Initially

D
[
r
]
[
c
]

{\displaystyle D[r][c]}

 is 0 for all

r

{\displaystyle r}

. The algorithm updates

D

{\displaystyle D}

 as follows.

```
 For

 c
 =

 w
 A

 {\displaystyle c = w\_A}

 to

 1

 {\displaystyle 1}

   For

 r
 =

 h
 A

 {\displaystyle r = h\_A}

 to

 1

 {\displaystyle 1}

 D
 [
 r
 ]
 [
 c
 ]
 =
 max
 (
 D
 [
 r
 1
 ]
 [
 c
 ]
 ,
 D
 [
 r
 ]
 [
 c
 1
 ]
 )

 {\displaystyle D[r][c]=\max(D[r+1][c],D[r][c+1])}

     if

 A
 (
 r
 ,
 c
 )
 =
 1

 {\displaystyle A(r,c) = 1}

 D
 [
 r
 ]
 [
 c
 ]
 =
 max
 (
 D
 [
 r
 ]
 [
 c
 ]
 ,
 1
 D
 [
 r
 1
 ]
 [
 c
 1
 ]
 )

 {\displaystyle D[r][c]=\max(D[r][c], 1 + D[r+1][c+1])}

```

The algorithm reports

A

{\displaystyle A}

 contains

B

{\displaystyle B}

 whenever some

D
[
r
]
[
c
]

{\displaystyle D[r][c]}

 hits

k

{\displaystyle k}

. Replace any

D

{\displaystyle D}

 above with index out of bound by value 0.

## Tensor of k x k identity matrix with j x 1 matrix of all 1's

For matrix B obtained by replacing each one of an identity matrix with a matrix with all ones -- let's denote it by j-column-identity matrix, here is an algorithm to determine whether A contains B in time O(h\_A w\_A):

D[r][c] now indicates the maximum width of j-column-identity matrix contained by the submatrix of A within row r to h\_A and column c to w\_A. The algorithm reports true if any D[r][c] reaches k.

The algorithm proceeds as before, but for each column c and each row r, it needs to know a number r+j <= H(r,c) <= h\_A first. H(r,c) is as small as possible such that in column c the number of 1s between row r and H(r,c)-1, inclusive, is at least j. If in column c there are less than j 1s from row r through the bottom we can set H(r,c)= infinity. Since the outer loop of the algorithm scans each column and the inner loop scans each row, simple technique ensures the overhead of computing H(r,c) is O(h\_A) per column, and hence doesn't impact overall asymptotic complexity.

So the recurrence becomes

D[r][c] = max(D[r+1][c],D[r][c+1])

If A[r][c]=1

..D[r][c] = max(D[r][c],1+D[H(r,c)][c+1])

## k x d matrix of all ones

An algorithm in time O(w2h) and memory O(w2) can decide whether a given matrix A contains P if P is k x 2. It goes by keeping {w \choose 2} counters and scanning row by row of A. In each row i if both A\_{i,a} and A\_{i,b} are 1 then counter (a,b) is incremented by 1. The algorithm reports true if any counter hits k. Generalizing to k x 3 and k x 4 patterns, the time complexity goes to O(w3h) and O(w4h), respectively.

## L-shaped patterns

For patterns P\_{m x n}=L(m,n), defined as L-shaped 1s with P\_{i,j}=1 iff j=1 or i=m, we know ex(n,P)=O(n). And the O(hw) algorithm to determine if A contains P is this: Keep w counters. Scan A row by row from bottom to top. If in current row there are k >= n ones, mark the left k-n+1 columns with ones. Also if there's an one in a column i marked in any of previous rows, increment counter i by 1. Whenever a counter hits m-1, A contains P.

## Cross-patterns

Let P\_{a x b} denote a cross pattern, with P(i,j)=1 iff i=c or j=d where c and d are constants such that 1 <= c <= a and 1 <= d <= b.

It turns out to also depend on the format the list of ones are given in this particular example. An O(x) algorithm exists if the ones are in the following format. Each one is associated with a distinct node, which has at most 4 links (pointers) to other nodes.

One link to the next one to the right in the same row, or if it doesn't exist, the left most one in the next row below. One to the next one to the left in the same row, or if it doesn't exist, the right most one in the next row below...and something similar for vertical links.

Each node may have special marks indicating it's the top/bottom/right most/left most one of that column/row.

Following these 4 links and marks, we can compute and store R(node), the number of ones to its right in the same row, and similary L(node),U(node),D(node), in 4 linear traversals, i.e. O(x) time. Finally, in one extra traversal the algorithm reports true if a node's L, R, D, and U values are all above respective thresholds.

The assumed input data structure and the needed algorithm could be generalized to d-dimensional case. Each node has 2d pointers pointing to its 2d neighbors (actually d pointers work too, just need extra O(x) backtrack time and O(x) memory for backtracking), and 2d counters storing the number of ones beyond itself in each direction. The overall 2d+1 O(x) time traversal could be reduced to 2d, because in the last traversal when the last counter is populated, we can check if all counters are above the thresholds.

The requirement that the pointer has to point to (for example) the top ones in the next column if the current node is the bottom one in its column can be avoided. The only reason for this requirement was to enable a smooth traversal. To get rid of it, in each dimension and each direction we can require the node be presented as a list of linked lists, one for each row or column in the 2-D case. And the traversal for all ones in each dimension and direction is then accomplished by traversing each linked list in the list. Therefore, the final data structure is a list of lists of linked lists. Each element in the highest level list corresponds to a dimension and a direction, each element in the second level list is a linked list corresponding to, for example, a column in the 2-D case.

## Relation to ex(n, P)

If the exact value of ex(n,P)=O(n) is known and h=w: To find out if A contains P, we can first count 1s in A. If it exceeds ex(h,P), then A contains P. Otherwise, we're left with O(h) ones. Now if we have an O(x2) algorithm that decides if the given x ones contain P, then we do have an O(h2) algorithm for the original problem.

If A is n x n, then any algorithm has to check at least n2-ex(n,P) entries to declare A avoids P, because if it skips ex(n,P)+1 elements, then in the worst case these skipped elements are all 1 and contains P. Since ex(n,P)=o(n2) then the proportion of elements that must be checked before saying A avoids P is close to 1.

## Open Problems

What is the fastest running time for an algorithm to determine whether a 0-1 matrix A contains a 0-1 matrix B with all ones?

More specifically, what is the fastest running time for an algorithm to determine whether a 0-1 matrix A contains a k x d matrix B with all ones?

Given a 0-1 matrix A as a list e\_{1}, ..., e\_{x} of all entries where A has ones, can we determine whether A contains P with an O(x2) algorithm?

Given a 0-1 matrix A as a list e\_{1}, ..., e\_{x} of all entries where A has ones, can we determine whether A contains P with an O(x) algorithm?

Thread: http://www.artofproblemsolving.com/polymath/mitprimes2016/f/c195578h1246307\_creating\_a\_research\_game