1 Star 0 Fork 0

妥協 / fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
perm.go 4.13 KB
一键复制 编辑 原始数据 按行查看 历史
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package graph
import (
"math/rand"
"time"
)
func init() {
rand.Seed(time.Now().UnixNano())
}
// treePermutations represents possible permutations
// of a tree
type treePermutations struct {
combinationUpperBound int // The upper bound of combinations of direct descendants.
originalRoot *TreeVertex // The root vertex of all sub-trees
permutations []*TreeVertex // The accumulated permutations
descendantPermutations map[*TreeVertex][][]*TreeVertex // Defines the combinations of sub-trees based on the threshold of the current vertex
}
// newTreePermutation creates a new treePermutations object with a given root vertex
func newTreePermutation(root *TreeVertex, combinationUpperBound int) *treePermutations {
return &treePermutations{
combinationUpperBound: combinationUpperBound,
descendantPermutations: make(map[*TreeVertex][][]*TreeVertex),
originalRoot: root,
permutations: []*TreeVertex{root},
}
}
// permute returns Trees that their vertices and edges all exist in the original tree who's vertex
// is the 'originalRoot' field of the treePermutations
func (tp *treePermutations) permute() []*Tree {
tp.computeDescendantPermutations()
it := newBFSIterator(tp.originalRoot)
for {
v := it.Next()
if v == nil {
break
}
if len(v.Descendants) == 0 {
continue
}
// Iterate over all permutations where v exists
// and separate them to 2 sets: a indiceSet where it exists and a indiceSet where it doesn't
var permutationsWhereVexists []*TreeVertex
var permutationsWhereVdoesntExist []*TreeVertex
for _, perm := range tp.permutations {
if perm.Exists(v.Id) {
permutationsWhereVexists = append(permutationsWhereVexists, perm)
} else {
permutationsWhereVdoesntExist = append(permutationsWhereVdoesntExist, perm)
}
}
// Remove the permutations where v exists from the permutations
tp.permutations = permutationsWhereVdoesntExist
// Next, we replace each occurrence of a permutation where v exists,
// with multiple occurrences of its descendants permutations
for _, perm := range permutationsWhereVexists {
// For each permutation of v's descendants, clone the graph
// and create a new graph with v replaced with the permutated graph
// of v connected to the descendant permutation
for _, permutation := range tp.descendantPermutations[v] {
subGraph := &TreeVertex{
Id: v.Id,
Data: v.Data,
Descendants: permutation,
}
newTree := perm.Clone()
newTree.replace(v.Id, subGraph)
// Add the new option to the permutations
tp.permutations = append(tp.permutations, newTree)
}
}
}
res := make([]*Tree, len(tp.permutations))
for i, perm := range tp.permutations {
res[i] = perm.ToTree()
}
return res
}
// computeDescendantPermutations computes all possible combinations of sub-trees
// for all vertices, based on the thresholds.
func (tp *treePermutations) computeDescendantPermutations() {
it := newBFSIterator(tp.originalRoot)
for {
v := it.Next()
if v == nil {
return
}
// Skip leaves
if len(v.Descendants) == 0 {
continue
}
// Ensure we don't have too much combinations of descendants
for CombinationsExceed(len(v.Descendants), v.Threshold, tp.combinationUpperBound) {
// Randomly pick a descendant, and remove it
victim := rand.Intn(len(v.Descendants))
v.Descendants = append(v.Descendants[:victim], v.Descendants[victim+1:]...)
}
// Iterate over all options of selecting the threshold out of the descendants
for _, el := range chooseKoutOfN(len(v.Descendants), v.Threshold) {
// And for each such option, append it to the current TreeVertex
tp.descendantPermutations[v] = append(tp.descendantPermutations[v], v.selectDescendants(el.indices))
}
}
}
// selectDescendants returns a subset of descendants according to given indices
func (v *TreeVertex) selectDescendants(indices []int) []*TreeVertex {
r := make([]*TreeVertex, len(indices))
i := 0
for _, index := range indices {
r[i] = v.Descendants[index]
i++
}
return r
}
1
https://gitee.com/liurenhao/fabric.git
git@gitee.com:liurenhao/fabric.git
liurenhao
fabric
fabric
v2.1.1

搜索帮助