Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://github.com/uberparagon/mgn
22 June 2021, 16:13:34 UTC
  • Code
  • Branches (5)
  • Releases (0)
  • Visits
    • Branches
    • Releases
    • HEAD
    • refs/heads/master
    • refs/tags/1.1.2
    • refs/tags/v1.0.4
    • refs/tags/v1.0.5
    • refs/tags/v1.0.9
    No releases to show
  • 97085ea
  • /
  • strataalgebra
  • /
  • intersect.py
Raw File Download
Take a new snapshot of a software origin

If the archived software origin currently browsed is not synchronized with its upstream version (for instance when new commits have been issued), you can explicitly request Software Heritage to take a new snapshot of it.

Use the form below to proceed. Once a request has been submitted and accepted, it will be processed as soon as possible. You can then check its processing state by visiting this dedicated page.
swh spinner

Processing "take a new snapshot" request ...

Permalinks

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
  • revision
  • snapshot
origin badgecontent badge Iframe embedding
swh:1:cnt:1e7e604c1012ca259d3338358931473e8ffd3bb4
origin badgedirectory badge Iframe embedding
swh:1:dir:81284197a7d7278adc1fe2d2fbd5c72cd401c538
origin badgerevision badge
swh:1:rev:87eacb93177c9d41edb525bb71ae03ae45f18d14
origin badgesnapshot badge
swh:1:snp:6e9d4128140ea9fc091a9d1ff362de9d8be50de2
Citations

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
  • revision
  • snapshot
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Tip revision: 87eacb93177c9d41edb525bb71ae03ae45f18d14 authored by Drew Johnson on 20 March 2020, 16:48:33 UTC
added a ps and ps_ member to strataalgebra
Tip revision: 87eacb9
intersect.py
from __future__ import absolute_import
#load("tautrel.sage")
#load("AllStrata.sage")
from sage.all import Graph, Integer, OrderedSetPartitions, Permutations, flatten
from .stratagraph import StrataGraph
import itertools
   
            
class StrataWithSageGraph(object):
    def __init__(self, strataG):
        self.strataG = strataG
        self.sageG = Graph([list(range(1,strataG.num_vertices()+1)),[]], multiedges=True, loops = True)
        self.edge_label_to_edge = dict()
        self.vertex_to_marks = {v:[] for v in range(1, self.strataG.num_vertices()+1)}
        self._has_marks = False
        
        for e in range(1, strataG.num_edges()+1):
            edge_done = False
            if self.strataG.M[0,e] != 0: #it is a half edge
                for v in range(1, strataG.num_vertices()+1):
                    if self.strataG.M[v,e][0] == 1:
                        self.vertex_to_marks[v].append((e,self.strataG.M[0,e]))
                        edge_done = True
                        self._has_marks = True
                        break
            else: #it is a whole edge           
                   
                vert_touching_e = []
            
                for v in range(1, strataG.num_vertices()+1):
                    if strataG.M[v,e][0] == 2:
                        #add a loop
                        self.sageG.add_edge( (v,v,e) )
                        self.edge_label_to_edge[e] = (v,v,e)
                        edge_done = True
                        break
                    if strataG.M[v,e][0] == 1:
                        vert_touching_e.append(v)
                        if len(vert_touching_e) == 2:
                            break
                            
            if edge_done:
                continue
            if len(vert_touching_e) == 2:
                self.sageG.add_edge( (vert_touching_e[0], vert_touching_e[1],e) )
                self.edge_label_to_edge[e] = (vert_touching_e[0], vert_touching_e[1],e)
            else:
                raise Exception("Unexpected here!")
    
    def has_marks(self):
        return self._has_marks
        
    def marks_on_v(self,v):
        return self.vertex_to_marks[v]
                 
    def edges_incident(self,v):
        for v1,v2,e in self.sageG.edges_incident(v):
            yield e
            
    def edges_labels_between_vertex_sets(self,vs1,vs2):
        #problem here when overlap........
        result = []
        for v1,v2, e in self.sageG.edges():
            if v1 in vs1 and v2 in vs2:
                result.append(e)
            elif v1 in vs2 and v2 in vs1:
                result.append(e)
        return result
        
        #some probably garbage...
        #v1sedges = set()
        #v2sedges = set()
        #for v1 in vs1:
        #    for e in self.edges_incident(v1):
        #        v1sedges.add(e)
        #for v2 in vs2:
        #    for e in self.edges_incident(v2):
        #        v2sedges.add(e)
                
        #return v1sedges.intersection(v2sedges)
        
    def edges(self):
        """
        Returns a list of triples!
        """
        return self.sageG.edges()
        
    def vertices(self):
        return self.sageG.vertices()
        
    def num_vertices(self):
        return self.strataG.num_vertices()
        
    def v_genus(self,v):
        """
        Returns the genus of the vertex v.
        """
        return self.strataG.M[v,0][0]
        
    def subgraph(self,vertices, edge_labels): 
        #print self.edge_label_to_edge
        #print self.sageG.edges()
        return self.sageG.subgraph(vertices, [self.edge_label_to_edge[l] for l in edge_labels])
        
    def edge_is_incident(self,e,v):
        #print "is_inc", e,v
        #print self.strataG
        #print
        return self.strataG.M[v,e][0] > 0
        
    def is_loop(self, e):
        v1,v2, ep = self.edge_label_to_edge[e]
        return v1==v2
                
                

class GStructOnA(object):
    
    def __init__(self,G, A,alpha_inv, beta, gamma_inv):
        self.G = G
        self.A = A
        self.alpha_inv = alpha_inv
        self.beta = beta
        self.gamma_inv = gamma_inv
        
    def __str__(self):
        return """
        ****
        alpha_inv:     {0}
        beta:      {1}
        gamma_inv: {2}
        ****
        """.format(self.alpha_inv, self.beta, self.gamma_inv)
    
    #@cache_method    
    def beta_ray(self,eG,vG):
        """
            vG is a vertex of G.
            eG is an edge of G.
            
            Returns an pair vA,eA
        """
        raise Exception("Depreciated")
        eA = self.beta[eG]
        vA = max((vAi for vAi in self.alpha_inv[vG] if self.A.edge_is_incident(eA,vAi) ))
        return eA, vA
    
    #@cache_method
    def beta_ray2(self,eG,vG):
        raise Exception("Depreciated")
        eA = self.beta[eG]        
        vA = min((vAi for vAi in self.alpha_inv[vG] if self.A.edge_is_incident(eA,vAi) ))
        return eA, vA
        
    def psi_no_loop(self, eG,vG, ex, psi):
        """
        Returns a 
        """
        eA = self.beta[eG]
        vis = [vAi for vAi in self.alpha_inv[vG] if self.A.edge_is_incident(eA,vAi)]
        if len(vis) > 1:
            raise Exception("Unexpected!!!")
        return psi[(eA,vis[0])]**ex
        
    def psi_loop(self, eG, vG, ex1,ex2, psi1,psi2):
        #print self.G.strataG
        #print self.A.strataG
        #print eG
        #print vG
        #print psi1
        #print psi2
        #print "alpha_inv", self.alpha_inv
        #print "beta", self.beta
        eA = self.beta[eG]
        vis = [vAi for vAi in self.alpha_inv[vG] if self.A.edge_is_incident(eA,vAi)]
        #print vis
        #print eA
        #print
        
        if len(vis) == 1:
            return  (psi1[(eA,vis[0])]**ex1 * psi2[(eA,vis[0])]**ex2 + psi1[(eA,vis[0])]**ex2 * psi2[(eA,vis[0])]**ex1)
        if len(vis) == 2:
            return (psi1[(eA,vis[0])]**ex1 * psi1[(eA,vis[1])]**ex2 + psi1[(eA,vis[1])]**ex1 * psi1[(eA,vis[0])]**ex2)
        raise Exception("Unexpected!!!!")
        
    def count_loop_to_loops(self):
        count = 0
        for  vG1, vG2, eG in self.G.edges():
            if vG1 == vG2 and self.A.is_loop(self.beta[eG]):
                count +=1
        return count

# Can't do this until we implement canonical labeling!
#class GStructsOnAMetaclass(type):
#    def __init__(self, *args, **kwargs):
#        super(GStructsOnAMetaclass, self).__init__(*args, **kwargs)
#        self.dict = dict()
#        
#    def __call__(self, *args, **kwargs):
#        G = args[0]
#        A= args[1]
#        
#        value = self.dict.get((G,A),None)
#        if value == None:
#            sp = super(GStructsOnAMetaclass,self).__call__(G,A)
#            self.dict[(G,A)] = sp
#            return sp
#        else:
#            print ".",
#            return value
            
class GStructsOnA(object):
#    __metaclass__ = GStructsOnAMetaclass
    
    def __init__(self,strataG,strataA):
        """
        The inputs should be StrataGraph objects.
        """
        self.G = StrataWithSageGraph(strataG)
        self.A = StrataWithSageGraph(strataA)
        #self._structs = None
        #print "G:"
        #print strataG
        #print self.G.vertex_to_marks
        #print "A:"
        #print strataA
        #print self.A.vertex_to_marks
        
    def __iter__(self):
        for alpha_inv_s in OrderedSetPartitions(self.A.num_vertices(), self.G.num_vertices()):
            
            
            
            beta_marks_list = list(self.get_beta_marks(alpha_inv_s))       
            if len(beta_marks_list) == 0:
                continue
            
            if not self.genus_v_ok(alpha_inv_s):
                continue
                
            #also, we should check the marked points somewhere about here.
            
            #do we need this??
            alpha = dict()    
            for vG,  alpha_inv_vG in zip(self.G.vertices(), alpha_inv_s):
                for vA in alpha_inv_vG:
                    alpha[vA] = vG
                    
            #print "alpha", alpha_inv_s, alpha        
            #print "about to do cp on ",
            #print [list(self.A.edges_labels_between_vertex_sets(alpha_inv_s[v1-1], alpha_inv_s[v2-1]))  for v1,v2,e in self.G.edges() ]
            #print self.G.edges()
                
            
            for beta_s in itertools.product(*[ list(self.A.edges_labels_between_vertex_sets(alpha_inv_s[v1-1],alpha_inv_s[v2-1]))  for v1,v2,e in self.G.edges() ]):
                gamma_inv = {vG:[] for vG in self.G.vertices()}
                #print "beta_s", beta_s
                bad = False
                for vA1, vA2, eA in self.A.edges(): 
                    if not eA in beta_s:
                        if alpha[vA1] != alpha[vA2]:
                            bad = True
                            break
                        else:
                            gamma_inv[alpha[vA1]].append(eA)
                if bad:
                    continue
                        
                        
                        
                            

            
                if not self.genus_ok(alpha_inv_s,gamma_inv):
                    continue
                
                if not self.connected_ok(alpha_inv_s,gamma_inv):
                    continue
                
                #print "about to yield alpha_inv_s" ,alpha_inv_s
                #print "beta_s", beta_s
                alpha_inv = {i+1:alpha_inv_s[i] for i in range(len(alpha_inv_s))}
                beta_no_marks = {eG[2] : eA for eG,eA in zip(self.G.edges(), beta_s)}
                for beta_marks in beta_marks_list:
                    beta = dict(beta_no_marks)
                    beta.update(beta_marks)
                    yield GStructOnA(self.G, self.A, alpha_inv, beta, gamma_inv)
                
    def genus_v_ok(self, alpha_inv_s):
        """
        Checks whether the map of vertices already has too large of genus in the fibers.
        """
        for vG,  alpha_inv_vG in zip(self.G.vertices(), alpha_inv_s):
            if sum(( self.A.v_genus(vA) for vA in alpha_inv_vG)) > self.G.v_genus(vG):
                return False
        return True
        
    def get_beta_marks(self, alpha_inv_s):
        if not self.G.has_marks():
            #print "G has no marks!"
            yield dict()
            return
    
        inv_marks_perms_list = []
        Gmarks = []
        for vG,  alpha_inv_vG in zip(self.G.vertices(), alpha_inv_s):
            inv_marks = []
            for vA in alpha_inv_vG:
                inv_marks += self.A.marks_on_v(vA)
            
            vGmarks = self.G.marks_on_v(vG)    
            Gmarks += vGmarks
            if len(inv_marks) != len(vGmarks):
                return 
            if len(vGmarks) == 0:
                continue
            
            inv_marks_perms = []
            #print "inv_marks", inv_marks
            for p in Permutations(inv_marks):
                bad = False
                for i,j in zip(vGmarks,p):
                    if i[1] != j[1]:
                        bad = True
                        break
                if not bad:
                    inv_marks_perms.append(list(p))
                    #print "inv_marks_perm", inv_marks_perms
            
            if len(inv_marks_perms) > 0:
                inv_marks_perms_list.append(inv_marks_perms)
            else:
                return       
                
        #print "made this",Gmarks, inv_marks_perms_list

                
        for p in itertools.product(*inv_marks_perms_list):
            pf = flatten(p,max_level=1)
            yield {i[0]:j[0] for i,j in zip(Gmarks, pf)}
            
                          
    def genus_ok(self, alpha_inv_s, gamma_inv):
        """
        Checks whether the proposed G-struct on A has the correct genus in the fibers.
        """
        #print alpha_inv_s, gamma_inv
        for v in self.G.vertices():
            inv_genus = sum(( self.A.v_genus(vA) for vA in alpha_inv_s[v-1])) + len(gamma_inv[v]) - len(alpha_inv_s[v-1]) +1
            if inv_genus != self.G.v_genus(v):
                return False
        return True            
        
    def connected_ok(self, alpha_inv_s, gamma_inv):
        """
        Checks whether the fibers of the proposed G-struct on A are connected.
        """
        for v in self.G.vertices():
            invG = self.A.subgraph(alpha_inv_s[v-1], gamma_inv[v])
            if not invG.is_connected():
                return False
        return True

def is_generic(Gs,Hs):
    for v1,v2,e in Gs.A.edges():
        if not (e in Gs.beta.values() or e in Hs.beta.values()):
            return False
    return True
                
def genericGHstructures(G,H,A):
    for Gs in GStructsOnA(G,A):
        for Hs in GStructsOnA(H,A):
            if is_generic(Gs,Hs):
                yield Gs,Hs
                
                

                                
def decorate_with_monomial(PsiKappaRing,A,m):
    """
    A should be a StrataGraph.
    Returns a new StrataGraph decorated according to the monomial m, which is actualy a tuple of exponents for generators of the PsiKappaRing
    """
    #print "entering decorate"
    #print A
    #print m
    X = StrataGraph.Xvar
    Anew = StrataGraph(A.M)
    for gen, e in zip(PsiKappaRing.gens(),m):
        if e == 0:
            continue
        var_str = str(gen)
        if var_str[0] == "k":
            stav = var_str[5:].split("_")
            a= Integer(stav[0])
            v= Integer(stav[1])
            Anew.M[v,0] += e*X**a
        elif var_str[0] == "p":
            stev = var_str[3:].split("_")
            edge = Integer(stev[0])
            v = Integer(stev[1])
            if len(stev) == 2:
                Anew.M[v,edge] += e*X
            if len(stev) == 3:
                if Anew.M[v,edge][1] > 0:
                    if Anew.M[v,edge][1] >= e: #if it already has a psi
                        Anew.M[v,edge] += e*X**2
                    else:
                        Anew.M[v,edge] = Anew.M[v,edge][1]*X**2 + e*X + Anew.M[v,edge][0]
                else: #the psi2 is the only one psi
                    Anew.M[v,edge] += e*X
                        
                
        else:
            raise Exception("You passed the wrong ring!?")
            
    #Anew.compute_invariant()
    #print "returning"
    #print Anew
    return Anew
    
def count_automorphisms_bad(A):
    Ag = StrataWithSageGraph(A)
    return Ag.sageG.automorphism_group().order()
    
def shared_edges(Gs,Hs):
    #print "shared edges for", Gs.beta.values(), Hs.beta.values()
    full_edges = [e for v1,v2,e in Gs.A.edges()]
    edges = set(Gs.beta.values()).intersection(Hs.beta.values()).intersection(full_edges)
    
    for e in edges:
        yield Gs.A.edge_label_to_edge[e]
    
        
#for testing
#Gtest = StrataGraph(Matrix(R,[[-1,0,0,0],[1,2,1,0],[1,0,1,2]]))
#GGtest = StrataWithSageGraph(Gtest)

#for gs in GStructsOnA(Gtest,Gtest):
#    print gs
    
#yG = get_single_stratum(32,4,3,())
#yA = get_single_stratum(855,4,5,())
#yH = get_single_stratum(2185,4,6,())

#results = list(GStructsOnA(yG,yA))

#for r in results:
#    print r

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Contact— JavaScript license information— Web API

back to top