github.com/igggame/nebulas-go@v2.1.0+incompatible/common/dag/dag.go (about) 1 // This file is part of the go-nebulas library. 2 // 3 // the go-nebulas library is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // (at your option) any later version. 7 // 8 // the go-nebulas library is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with the go-nebulas library. If not, see <http://www.gnu.org/licenses/>. 15 // 16 17 package dag 18 19 import ( 20 "encoding/json" 21 "errors" 22 23 "github.com/gogo/protobuf/proto" 24 "github.com/nebulasio/go-nebulas/common/dag/pb" 25 ) 26 27 // Node struct 28 type Node struct { 29 key interface{} 30 index int 31 children []*Node 32 parentCounter int 33 } 34 35 // Errors 36 var ( 37 ErrKeyNotFound = errors.New("not found") 38 ErrKeyIsExisted = errors.New("already existed") 39 ErrInvalidProtoToDag = errors.New("Protobuf message cannot be converted into Dag") 40 ErrInvalidDagToProto = errors.New("Dag cannot be converted into Protobuf message") 41 ) 42 43 // NewNode new node 44 func NewNode(key interface{}, index int) *Node { 45 return &Node{ 46 key: key, 47 index: index, 48 parentCounter: 0, 49 children: make([]*Node, 0), 50 } 51 } 52 53 // Index return node index 54 func (n *Node) Index() int { 55 return n.index 56 } 57 58 // Dag struct 59 type Dag struct { 60 nodes map[interface{}]*Node 61 index int 62 indexs map[int]interface{} 63 } 64 65 // ToProto converts domain Dag into proto Dag 66 func (dag *Dag) ToProto() (proto.Message, error) { 67 68 nodes := make([]*dagpb.Node, len(dag.nodes)) 69 70 for idx, key := range dag.indexs { 71 v, ok := dag.nodes[key] 72 if !ok { 73 return nil, ErrInvalidDagToProto 74 } 75 76 node := new(dagpb.Node) 77 node.Index = int32(v.index) 78 //node.Key = v.Key.(string) 79 node.Children = make([]int32, len(v.children)) 80 for i, child := range v.children { 81 node.Children[i] = int32(child.index) 82 } 83 84 nodes[idx] = node 85 } 86 87 return &dagpb.Dag{ 88 Nodes: nodes, 89 }, nil 90 } 91 92 // FromProto converts proto Dag to domain Dag 93 func (dag *Dag) FromProto(msg proto.Message) error { 94 if msg, ok := msg.(*dagpb.Dag); ok { 95 if msg != nil { 96 for _, v := range msg.Nodes { 97 dag.addNodeWithIndex(int(v.Index), int(v.Index)) 98 } 99 100 for _, v := range msg.Nodes { 101 for _, child := range v.Children { 102 dag.AddEdge(int(v.Index), int(child)) 103 } 104 } 105 return nil 106 } 107 return ErrInvalidProtoToDag 108 } 109 return ErrInvalidProtoToDag 110 } 111 112 // String 113 func (dag *Dag) String() string { 114 msg, err := dag.ToProto() 115 if err != nil { 116 return string("") 117 } 118 j, _ := json.Marshal(msg) 119 return string(j) 120 } 121 122 // NewDag new dag 123 func NewDag() *Dag { 124 return &Dag{ 125 nodes: make(map[interface{}]*Node, 0), 126 index: 0, 127 indexs: make(map[int]interface{}, 0), 128 } 129 } 130 131 // Len Dag len 132 func (dag *Dag) Len() int { 133 return len(dag.nodes) 134 } 135 136 // GetNode get node by key 137 func (dag *Dag) GetNode(key interface{}) *Node { 138 if v, ok := dag.nodes[key]; ok { 139 return v 140 } 141 return nil 142 } 143 144 // GetChildrenNodes get children nodes with key 145 func (dag *Dag) GetChildrenNodes(key interface{}) []*Node { 146 if v, ok := dag.nodes[key]; ok { 147 return v.children 148 } 149 150 return nil 151 } 152 153 // GetRootNodes get root nodes 154 func (dag *Dag) GetRootNodes() []*Node { 155 nodes := make([]*Node, 0) 156 for _, node := range dag.nodes { 157 if node.parentCounter == 0 { 158 nodes = append(nodes, node) 159 } 160 } 161 return nodes 162 } 163 164 // GetNodes get all nodes 165 func (dag *Dag) GetNodes() []*Node { 166 nodes := make([]*Node, 0) 167 for _, node := range dag.nodes { 168 nodes = append(nodes, node) 169 } 170 return nodes 171 } 172 173 // AddNode add node 174 func (dag *Dag) AddNode(key interface{}) error { 175 if _, ok := dag.nodes[key]; ok { 176 return ErrKeyIsExisted 177 } 178 179 dag.nodes[key] = NewNode(key, dag.index) 180 dag.indexs[dag.index] = key 181 dag.index++ 182 return nil 183 } 184 185 // addNodeWithIndex add node 186 func (dag *Dag) addNodeWithIndex(key interface{}, index int) error { 187 if _, ok := dag.nodes[key]; ok { 188 return ErrKeyIsExisted 189 } 190 191 dag.nodes[key] = NewNode(key, index) 192 dag.indexs[index] = key 193 dag.index = index 194 return nil 195 } 196 197 // AddEdge add edge fromKey toKey 198 func (dag *Dag) AddEdge(fromKey, toKey interface{}) error { 199 var from, to *Node 200 var ok bool 201 202 if from, ok = dag.nodes[fromKey]; !ok { 203 return ErrKeyNotFound 204 } 205 206 if to, ok = dag.nodes[toKey]; !ok { 207 return ErrKeyNotFound 208 } 209 210 for _, childNode := range from.children { 211 if childNode == to { 212 return ErrKeyIsExisted 213 } 214 } 215 216 dag.nodes[toKey].parentCounter++ 217 dag.nodes[fromKey].children = append(from.children, to) 218 219 return nil 220 } 221 222 //IsCirclular a->b-c->a 223 func (dag *Dag) IsCirclular() bool { 224 225 visited := make(map[interface{}]int, len(dag.nodes)) 226 rootNodes := make(map[interface{}]*Node) 227 for key, node := range dag.nodes { 228 visited[key] = 0 229 rootNodes[key] = node 230 } 231 232 for _, node := range rootNodes { 233 if dag.hasCirclularDep(node, visited) { 234 return true 235 } 236 } 237 238 for _, count := range visited { 239 if count == 0 { 240 return true 241 } 242 } 243 return false 244 } 245 246 func (dag *Dag) hasCirclularDep(current *Node, visited map[interface{}]int) bool { 247 248 visited[current.key] = 1 249 for _, child := range current.children { 250 if visited[child.key] == 1 { 251 return true 252 } 253 254 if dag.hasCirclularDep(child, visited) { 255 return true 256 } 257 } 258 visited[current.key] = 2 259 return false 260 }