-1

I am looking for Python code to find maximal elements in a partial order.

There are two other posts, which address the problem,

but they only have vague descriptions and no code. Also some years have passed, since these were asked.

edit: To be more specific, both of them suggest building a DAG. My own idea is with some loops, and adding to and deleting from lists. However, I would like to know whether there is some short "pythonic" way, of coding this.

More precisely, I have a list of arrays with entries 0,1; all of the same length. These arrays are the image space of some matrix over GF(2), the field with just 0 and 1.

Let x and y be two arrays. I say x <= y, if this inequality holds piecewise.

edit: More precisely, my inequality is given by the function

def leq(x,y):
  return all([x[i] <= y[i] for i in range(len(x))])

Example

Input:

[1 1 0]
[1 0 0]
[1 0 1]

Output:

[1 1 0]
[1 0 1]

edit I have written down my idea

import numpy as np

l = [np.array([1, 1, 0]), np.array([1, 0, 0]), np.array([0, 1, 1])]
l.sort(reverse=True, key=np.sum)
maximal = [l[0]]
for e in l:
    i = 0
    replaced = False
    while i < len(maximal):
        if (maximal[i] <= e).all():
            if replaced:
                maximal.remove(maximal[i])
            else:
                maximal[i] = e.copy()
                replaced = True
        if (e <= maximal[i]).all():
            break
        i += 1
    if i == len(maximal) and not replaced:
        maximal.append(e.copy())

How can I compute this nicely (shorter code/faster runtime) in Python?

Hennich
  • 682
  • 3
  • 18

1 Answers1

0

After some more testing, I ended up with the following code. The above code from the question still had some bugs.

import numpy as np

def maximal_elements(input_list):
  """Given a list of np.array, compute the maximal elements.

  Call:
    maximal = maximal_elements(input_list)
  Input:
    input_list: list of np.array, all need to have the same length.
  Output:
    maximal: list of np.array, which contains the maximal elements of input_list,
      the order used is elementwise "<="      
  """
  l = input_list.copy()
  l.sort(reverse=True, key=np.sum)
  maximal = [l[0]]
  for e in l[1:]:
    i = 0
    replaced = False
    while i < len(maximal):
      if (maximal[i] <= e).all():
        if replaced:
          maximal.pop(i)
          i -= 1
        else:
          maximal[i] = e.copy()
          replaced = True
      if (e <= maximal[i]).all():
        if not (e == maximal[i]).all():
          break
      i += 1
    if i == len(maximal) and not replaced:
      maximal.append(e.copy())
  return maximal

import itertools
import random
random.seed(2)
l = [np.array(e) for e in random.sample(list(itertools.product([0,1], repeat=5)), 9)]
maximal_elements(l)

returns [array([1, 1, 1, 1, 0]), array([1, 0, 1, 1, 1]), array([0, 1, 0, 1, 1])]

Hennich
  • 682
  • 3
  • 18