github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/topo/clique_graph.go (about)

     1  // Copyright ©2017 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package topo
     6  
     7  import (
     8  	"sort"
     9  
    10  	"github.com/jingcheng-WU/gonum/graph"
    11  	"github.com/jingcheng-WU/gonum/graph/internal/ordered"
    12  	"github.com/jingcheng-WU/gonum/graph/internal/set"
    13  )
    14  
    15  // Builder is a pure topological graph construction type.
    16  type Builder interface {
    17  	AddNode(graph.Node)
    18  	SetEdge(graph.Edge)
    19  }
    20  
    21  // CliqueGraph builds the clique graph of g in dst using Clique and CliqueGraphEdge
    22  // nodes and edges. The nodes returned by calls to Nodes on the nodes and edges of
    23  // the constructed graph are the cliques and the common nodes between cliques
    24  // respectively. The dst graph is not cleared.
    25  func CliqueGraph(dst Builder, g graph.Undirected) {
    26  	cliques := BronKerbosch(g)
    27  
    28  	// Construct a consistent view of cliques in g. Sorting costs
    29  	// us a little, but not as much as the cliques themselves.
    30  	for _, c := range cliques {
    31  		sort.Sort(ordered.ByID(c))
    32  	}
    33  	sort.Sort(ordered.BySliceIDs(cliques))
    34  
    35  	cliqueNodes := make(cliqueNodeSets, len(cliques))
    36  	for id, c := range cliques {
    37  		s := set.NewNodesSize(len(c))
    38  		for _, n := range c {
    39  			s.Add(n)
    40  		}
    41  		ns := &nodeSet{Clique: Clique{id: int64(id), nodes: c}, nodes: s}
    42  		dst.AddNode(ns.Clique)
    43  		for _, n := range c {
    44  			nid := n.ID()
    45  			cliqueNodes[nid] = append(cliqueNodes[nid], ns)
    46  		}
    47  	}
    48  
    49  	for _, cliques := range cliqueNodes {
    50  		for i, uc := range cliques {
    51  			for _, vc := range cliques[i+1:] {
    52  				// Retain the nodes that contribute to the
    53  				// edge between the cliques.
    54  				var edgeNodes []graph.Node
    55  				switch 1 {
    56  				case len(uc.Clique.nodes):
    57  					edgeNodes = []graph.Node{uc.Clique.nodes[0]}
    58  				case len(vc.Clique.nodes):
    59  					edgeNodes = []graph.Node{vc.Clique.nodes[0]}
    60  				default:
    61  					for _, n := range set.IntersectionOfNodes(uc.nodes, vc.nodes) {
    62  						edgeNodes = append(edgeNodes, n)
    63  					}
    64  					sort.Sort(ordered.ByID(edgeNodes))
    65  				}
    66  
    67  				dst.SetEdge(CliqueGraphEdge{from: uc.Clique, to: vc.Clique, nodes: edgeNodes})
    68  			}
    69  		}
    70  	}
    71  }
    72  
    73  type cliqueNodeSets map[int64][]*nodeSet
    74  
    75  type nodeSet struct {
    76  	Clique
    77  	nodes set.Nodes
    78  }
    79  
    80  // Clique is a node in a clique graph.
    81  type Clique struct {
    82  	id    int64
    83  	nodes []graph.Node
    84  }
    85  
    86  // ID returns the node ID.
    87  func (n Clique) ID() int64 { return n.id }
    88  
    89  // Nodes returns the nodes in the clique.
    90  func (n Clique) Nodes() []graph.Node { return n.nodes }
    91  
    92  // CliqueGraphEdge is an edge in a clique graph.
    93  type CliqueGraphEdge struct {
    94  	from, to Clique
    95  	nodes    []graph.Node
    96  }
    97  
    98  // From returns the from node of the edge.
    99  func (e CliqueGraphEdge) From() graph.Node { return e.from }
   100  
   101  // To returns the to node of the edge.
   102  func (e CliqueGraphEdge) To() graph.Node { return e.to }
   103  
   104  // ReversedEdge returns a new CliqueGraphEdge with
   105  // the edge end points swapped. The nodes of the
   106  // new edge are shared with the receiver.
   107  func (e CliqueGraphEdge) ReversedEdge() graph.Edge { e.from, e.to = e.to, e.from; return e }
   108  
   109  // Nodes returns the common nodes in the cliques of the underlying graph
   110  // corresponding to the from and to nodes in the clique graph.
   111  func (e CliqueGraphEdge) Nodes() []graph.Node { return e.nodes }