#!/usr/bin/python
# -*- coding: utf-8 -*-

# Posets des partitions semi-pointées de type B

# on commence par générer la partition la plus fine
def genPartFine(n,k):
    """
  exple :  genPartFine(2,1)
[[{0}, 0], [{1}, 1], [{2}, 0]]
    """
    L=[]
    L=L+[[Set([0]),0]]
    for x in range(n):
            if k == 0:
                L=L+[[Set([x+1]),0]]
            else:
                L=L+[[Set([x+1]),x+1]]
                k=k-1
    return L

def op(S):
    """
étant donné un ensemble, renvoie le même opposé

exple : op(Set([1,2,3,4]))
{-4, -1, -2, -3}
    """
    return Set([-a for a in S])


def PosSet(S):
    """
renvoie la valeur absolue de l'ensemble

exple : PosSet(Set([1,-3,4,-5,-1,8,-10,-11]))
{1, 3, 4, 5, 8, 10, 11}
    """
    return Set([abs(a) for a in S])


def PlusPetit(p):
    """
    renvoie la liste des partitions plus fines que p, une partition semi-pointée de type B
    A noter que l'on considère que l'arête avec 0 est toujours première

exple : PlusPetit([[{0, 1}, 1], [{2}, 2], [{3}, 0]])
[[[{0, 1, 2}, 2], [{3}, 0]], [[{0, 1, 2}, -2], [{3}, 0]], [[{0, 1, 2}, 1], [{3}, 0]], [[{0, 1, 3}, 0], [{2}, 2]], [[{0, 1, 3}, 1], [{2}, 2]], [[{0, 1}, 1], [{2, 3}, 2]], [[{0, 1}, 1], [{2, 3}, 0]], [[{0, 1}, 1], [{2, -3}, 2]], [[{0, 1}, 1], [{2, -3}, 0]]]
    """
    L=[]
    np=[] 
    for k in range(len(p)-1):
        np=[]
        for a in range(len(p)-1):
            if a!=k:
                np=np+[p[a+1]]
        np1=[[p[0][0].union(PosSet(p[k+1][0])),p[k+1][1]]]+np
        L=L+[np1]
        if p[k+1][1]!=0:
            np1=[[p[0][0].union(PosSet(p[k+1][0])),-p[k+1][1]]]+np
            L=L+[np1]
        if (p[0][1]!=0) or (len(p[0][0])!=1):
            np1=[[p[0][0].union(PosSet(p[k+1][0])),p[0][1]]]+np
            L=L+[np1]
              
    for k in range(len(p)-1):    
        for l in range (len(p)-k-2):
            np=[]
            if min(PosSet(p[k+1][0]))>min(PosSet(p[l+k+2][0])):
                ensptt=p[l+k+2][0]
                ensgrd=p[k+1][0]
                pptt=p[l+k+2][1]
                pgrd=p[k+1][1]
            else:
                ensgrd=p[l+k+2][0]
                ensptt=p[k+1][0]
                pgrd=p[l+k+2][1]
                pptt=p[k+1][1]
            for a in range(len(p)):
                if a != k+1:
                    if a != l+k+2:
                        np=np+[p[a]]
            np1=np+[[ensptt.union(ensgrd),pptt]]
            L=L+[np1]
            if pptt != pgrd:
                np2=np+[[ensptt.union(ensgrd),pgrd]]
                L=L+[np2]
            np1=np+[[ensptt.union(op(ensgrd)),pptt]]
            L=L+[np1]
            if pptt != pgrd:
                np2=np+[[ensptt.union(op(ensgrd)),-pgrd]]
                L=L+[np2]
    return L


