Search code examples
pythonpython-3.xnetwork-programming

Finding block list from allowed list using python


We will pass a policy list to the function. Policy list contains a list of entities.We need to return list of entities that cannot talk to each other. Eg. policy1 = [['A'], ['B', 'C'], ['D']] This policy1 means that B-C traffic allowed rest all is denied. We need to return list of entities that cannot talk to each other. block_list = [('A', 'C', 'D'), ('A', 'B', 'D')]

Similarly for policy2 = [['A', 'B'], ['B', 'C'], ['D']] where B can communicate directly with A,C but A and C cannot communicate with each other and cannot communicate D. D cannot communicate with each other(A,B,C). block_list = [('A', 'C', 'D'), ('B', 'D')]

Similarly for policy3 = [['A'], ['B', 'C'], ['D', 'E']]; A cannot communicate with any other entity. B and C can communicate with each other but not with others(A,D,E), block_list = [('A', 'C', 'D'), ('A', 'B', 'D'), ('A', 'C', 'E'), ('A', 'B', 'E')]

Similary for policy4 = [['A'], ['B', 'C'], ['D', 'E'], ['F'], ['G']] ; block_list =[('A', 'B', 'E', 'F', 'G'), ('A', 'C', 'D', 'F', 'G'), ('A', 'C', 'E', 'F', 'G'), ('A', 'B', 'D', 'F', 'G')]

I wrote code

from itertools import product

def generate_block_list(policy):
    block_set = set()

    # Generate block list for each entity in the policy
    for entity in policy:
        other_entities = [e for e in policy if e != entity]

        # Generate all possible combinations of the current entity with other entities
        combinations = list(product(entity, *other_entities))
        unique_combinations = [tuple(sorted(set(combination))) for combination in combinations]

        # Add combinations to the block list
        block_set.update(unique_combinations)

    block_list = list(block_set)
    return block_list

# Example usage:
policy1 = [['A'], ['B', 'C'], ['D']]
block_list1 = generate_block_list(policy1)
print("\nPolicy:", policy1)
print("Block List:", block_list1)

policy2 = [['A', 'B'], ['B', 'C'], ['D']]
block_list2 = generate_block_list(policy2)
print("\nPolicy:", policy2)
print("Block List:", block_list2)

policy3 = [['A'], ['B', 'C'], ['D', 'E']]
block_list3 = generate_block_list(policy3)
print("\nPolicy:", policy3)
print("Block List:", block_list3)

policy4 = [['A'], ['B', 'C'], ['D', 'E'], ['F'], ['G']]
block_list4 = generate_block_list(policy4)
print("\nPolicy:", policy4)
print("Block List:", block_list4)

I got output :

Policy: [['A'], ['B', 'C'], ['D']] Block List: [('A', 'C', 'D'), ('A', 'B', 'D')]

Policy: [['A', 'B'], ['B', 'C'], ['D']] Block List: [('A', 'C', 'D'), ('A', 'B', 'D'), ('B', 'D'), ('B', 'C', 'D')]

Policy: [['A'], ['B', 'C'], ['D', 'E']] Block List: [('A', 'C', 'D'), ('A', 'B', 'D'), ('A', 'C', 'E'), ('A', 'B', 'E')]

Policy: [['A'], ['B', 'C'], ['D', 'E'], ['F'], ['G']] Block List: [('A', 'B', 'E', 'F', 'G'), ('A', 'C', 'D', 'F', 'G'), ('A', 'C', 'E', 'F', 'G'), ('A', 'B', 'D', 'F', 'G')]

It is failing for policy2 where entities are common. Help me fix. Or suggest a better way to do. Block List: [('A', 'C', 'D'), ('A', 'B', 'D'), ('B', 'D'), ('B', 'C', 'D')] is wrong it should be Block List: [('A', 'C', 'D'), ('B', 'D')]


Solution

  • I'm not sure why you're not using the built-in combination method and only calculating certain combinations and not others, but something like this should work:

    from itertools import combinations
    
    def all_combinations(lst):
        for i in range(2,len(lst)+1):
            for combination in combinations(lst,i):
                yield set(combination)
    
    def is_allowed(combination,allowed_connections):
        for connection in allowed_connections:
            if connection == combination:
                return True
        return False
                
    policy = [['A'], ['B', 'C'], ['D']]
    all_nodes = [item for group in policy for item in group]
    allowed_connections = [set(group) for group in policy if len(group)>1]
    block_list = [combination for combination in all_combinations(all_nodes) if not is_allowed(combination,allowed_connections)]
    print(block_list)
    

    this will block everything that is not explicitly allowed.