| 2107 | |
| 2108 | def spanning_trees_count(self, root_vertex=None): |
| 2109 | """ |
| 2110 | Returns the number of spanning trees in a graph. In the case of a |
| 2111 | digraph, couts the number of spanning out-trees rooted in |
| 2112 | ``root_vertex``. |
| 2113 | Default is to set first vertex as root. |
| 2114 | |
| 2115 | This computation uses Kirchhoff's Matrix Tree Theorem [1] to calculate |
| 2116 | the number of spanning trees. For complete graphs on `n` vertices the |
| 2117 | result can also be reached using Cayley's formula: the number of |
| 2118 | spanning trees are `n^(n-2)`. |
| 2119 | |
| 2120 | For digraphs, the augmented Kirchhoff Matrix as defined in [2] is |
| 2121 | used for calculations. Here the result is the number of out-trees |
| 2122 | rooted at a specific vertex. |
| 2123 | |
| 2124 | INPUT: |
| 2125 | |
| 2126 | - ``root_vertex`` -- integer (default: the first vertex) This is the vertex |
| 2127 | that will be used as root for all spanning out-trees if the graph |
| 2128 | is a directed graph. |
| 2129 | This argument is ignored if the graph is not a digraph. |
| 2130 | |
| 2131 | REFERENCES: |
| 2132 | |
| 2133 | - [1] http://mathworld.wolfram.com/MatrixTreeTheorem.html |
| 2134 | |
| 2135 | - [2] Lih-Hsing Hsu, Cheng-Kuan Lin, "Graph Theory and Interconnection |
| 2136 | Networks" |
| 2137 | |
| 2138 | AUTHORS: |
| 2139 | |
| 2140 | - Anders Jonsson (2009-10-10) |
| 2141 | |
| 2142 | EXAMPLES:: |
| 2143 | |
| 2144 | sage: G = graphs.PetersenGraph() |
| 2145 | sage: G.spanning_trees_count() |
| 2146 | 2000 |
| 2147 | |
| 2148 | :: |
| 2149 | |
| 2150 | sage: n = 11 |
| 2151 | sage: G = graphs.CompleteGraph(n) |
| 2152 | sage: ST = G.spanning_trees_count() |
| 2153 | sage: ST == n^(n-2) |
| 2154 | True |
| 2155 | |
| 2156 | :: |
| 2157 | |
| 2158 | sage: M=matrix(3,3,[0,1,0,0,0,1,1,1,0]) |
| 2159 | sage: D=DiGraph(M) |
| 2160 | sage: D.spanning_trees_count() |
| 2161 | 1 |
| 2162 | sage: D.spanning_trees_count(0) |
| 2163 | 1 |
| 2164 | sage: D.spanning_trees_count(2) |
| 2165 | 2 |
| 2166 | |
| 2167 | """ |
| 2168 | if self.is_directed() == False: |
| 2169 | M=self.kirchhoff_matrix() |
| 2170 | M.subdivide(1,1) |
| 2171 | M2 = M.subdivision(1,1) |
| 2172 | return abs(M2.determinant()) |
| 2173 | else: |
| 2174 | G=self.copy() |
| 2175 | if (type(G.vertices()[G.order()-1]) is str): |
| 2176 | n = G.vertices()[G.order()-1] + "a" |
| 2177 | else: |
| 2178 | n = G.vertices()[G.order()-1] + 1 |
| 2179 | if root_vertex == None: |
| 2180 | root_vertex=G.vertex_iterator().next() |
| 2181 | if root_vertex not in G.vertices(): |
| 2182 | raise ValueError, ("Vertex (%s) not in the graph."%root_vertex) |
| 2183 | |
| 2184 | G.add_vertex(n) |
| 2185 | G.add_edge(n,root_vertex) |
| 2186 | M=G.kirchhoff_matrix() |
| 2187 | j=0 |
| 2188 | for i in G.vertices(): |
| 2189 | M[j,j]=G.in_degree(i) |
| 2190 | j= j + 1 |
| 2191 | M.subdivide(G.order()-1,G.order()-1) |
| 2192 | M2=M.subdivision(0,0) |
| 2193 | return abs(M2.determinant()) |