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

# Générer les partitions les plus fines sur n sommets avec k avec pointages et les autres sans pointage

def genPartFine(n,k):
    L=[]
    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
        

# Générer les partitions moins fines qu'une donnée

def PlusPetit(p):
    """
        renvoie la liste des partitions plus fines que p, une partition
        """
    L=[]
    np=[] 
    for k in range(len(p)):
        for l in range (len(p)-k-1):
            np=[]
            np=np+[[p[k][0].union(p[l+k+1][0]),p[k][1]]]
            for a in range(len(p)):
                if a != k:
                    if a != l+k+1:
                        np=np+[p[a]]
            L=L+[np]                
            if p[k][1]!=p[l+k+1][1]:
                np=[]
                np=np+[[p[k][0].union(p[l+k+1][0]),p[l+k+1][1]]]
                for a in range(len(p)):
                    if a != k:
                        if a != k+l+1:
                            np=np+[p[a]]
                L=L+[np]

    return L
        
#Affiche joliement la partition

def BPrint(lp):
    L=[]
    jp=[]
    for k in range(len(lp)):
        p=lp[k]
        jp=[]
        pointed=[]
        for l in range(len(p)):
            jp=jp+[p[l][0]]
            pointed=pointed+[p[l][1]]           
        L=L+[[jp, Set(pointed)]]
    return L

#Générer les partitions

def part(n,k): 
    """
    Renvoie l'ensemble des partitions de n avec k parts pointées dans la plus fine
    L[h] contiendra la liste des hyperarbres de hauteurs h
    """
    L=[[genPartFine(n,k)]]
    Lfin=[genPartFine(n,k)]
    Lh=[]
    for h in range(n-1):
        Lh=[]
        for i in range(len(L[h])):
            for parto in PlusPetit(L[h][i]):
                newp=true
                for j in range(len(Lh)):
                    if Lh[j]==parto:
                        newp=false
                if newp:
                    Lh=Lh+[parto]
        L=L+[Lh]
        Lfin=Lfin+Lh
    return Lfin

def stx(p):
    """
    Renvoie une partition en ensemble
    """
    return Set([Set(p[i]) for i in range(len(p))])

def homol(n,k):
    """
    Renvoie l'homologie du poset
    """
    Part = part(n,k)
    P = Poset({stx(Part[i+1]): [stx(PlusPetit(Part[i+1])[j]) for j in range(len(PlusPetit(Part[i+1])))] for i in range(len(Part)-1)})
    return P.order_complex().homology()


# Générer les partitions les plus fines sur n sommets avec 0 avec pointages et les autres sans pointage

def genPartnp(n):
    L=[]
    for x in range(n):
                L=L+[Set([x+1])]
    return L
        

# Générer les partitions moins fines qu'une donnée

def PlusPetitnp(p):
    """
        renvoie la liste des partitions plus fines que p, une partition
        """
    L=[]
    np=[] 
    for k in range(len(p)):
        for l in range (len(p)-k-1):
            np=[]
            np=np+[p[k].union(p[l+k+1])]
            for a in range(len(p)):
                if a != k:
                    if a != l+k+1:
                        np=np+[p[a]]
            L=L+[np]                
    return L


#Générer les partitions

def partnp(n): 
    """
    Renvoie l'ensemble des partitions de n avec k parts pointées dans la plus fine
    L[h] contiendra la liste des hyperarbres de hauteurs h
    """
    L=[[genPartnp(n)]]
    Lfin=[]
    Lh=[]
    for h in range(n-1):
        Lh=[]
        for i in range(len(L[h])):
            if len(PlusPetitnp(L[h])) !=1:
                for parto in PlusPetitnp(L[h]):
                    newp=true
                    for j in range(len(Lh)):
                        if Lh[j]==parto:
                            newp=false
                    if newp:
                        Lh=Lh+[parto]
        L=L+[Lh]
        Lfin=Lfin+Lh
    return Lfin
    
def stx(p):
    """
    Renvoie une partition en ensemble
    """
    return Set([Set(p[i]) for i in range(len(p))])

def homol(n,k):
    """
    Renvoie l'homologie du poset
    """
    Part = part(n,k)
    P = Poset({stx(Part[i+1]): [stx(PlusPetit(Part[i+1])[j]) for j in range(len(PlusPetit(Part[i+1])))] for i in range(len(Part)-1)})
    return P.order_complex().homology()


