github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/core/dag/dag.go (about)

     1  // Copyright 2020 The go-simplechain Authors
     2  // This file is part of the go-simplechain library.
     3  //
     4  // The go-simplechain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-simplechain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-simplechain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package dag
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/gob"
    22  	"fmt"
    23  )
    24  
    25  type Vertex struct {
    26  	InDegree int
    27  	OutEdges []int
    28  	InEdges  []int
    29  }
    30  
    31  func NewVertex() *Vertex {
    32  	vertex := &Vertex{
    33  		InDegree: 0,
    34  		OutEdges: make([]int, 0),
    35  		InEdges:  make([]int, 0),
    36  	}
    37  	return vertex
    38  }
    39  
    40  type Dag struct {
    41  	V          int
    42  	Consumed   int
    43  	VertexList []*Vertex
    44  	NextList   []int
    45  }
    46  
    47  func NewDag(v int) *Dag {
    48  	dag := &Dag{
    49  		V: v,
    50  	}
    51  	for i := 0; i < v; i++ {
    52  		dag.VertexList = append(dag.VertexList, NewVertex())
    53  	}
    54  	return dag
    55  }
    56  
    57  func (dag *Dag) AddEdge(from, to int) {
    58  	dag.VertexList[from].OutEdges = append(dag.VertexList[from].OutEdges, to)
    59  	dag.VertexList[to].InDegree++
    60  	dag.VertexList[to].InEdges = append(dag.VertexList[to].InEdges, from)
    61  }
    62  
    63  func (dag *Dag) GetOutEdges(from int) []int {
    64  	return dag.VertexList[from].OutEdges
    65  }
    66  
    67  func (dag *Dag) GetInEdges(to int) []int {
    68  	return dag.VertexList[to].InEdges
    69  }
    70  
    71  func (dag *Dag) HasNext() bool {
    72  	return dag.Consumed < dag.V
    73  }
    74  
    75  func (dag *Dag) Next() []int {
    76  	if len(dag.NextList) == 0 {
    77  		for i := 0; i < dag.V; i++ {
    78  			if dag.VertexList[i].InDegree == 0 {
    79  				dag.NextList = append(dag.NextList, i)
    80  			}
    81  		}
    82  	} else {
    83  		//need copy?
    84  		preList := dag.NextList
    85  		dag.NextList = []int{}
    86  		for _, vtxIdx := range preList {
    87  			for _, outVtxIdx := range dag.VertexList[vtxIdx].OutEdges {
    88  				dag.VertexList[outVtxIdx].InDegree--
    89  				if dag.VertexList[outVtxIdx].InDegree == 0 {
    90  					dag.NextList = append(dag.NextList, outVtxIdx)
    91  				}
    92  			}
    93  		}
    94  	}
    95  	dag.Consumed = dag.Consumed + len(dag.NextList)
    96  	return dag.NextList
    97  }
    98  
    99  func (dag *Dag) InDegree(i int) int {
   100  	return dag.VertexList[i].InDegree
   101  }
   102  
   103  func (dag *Dag) OutDegree(i int) int {
   104  	return len(dag.VertexList[i].OutEdges)
   105  }
   106  
   107  func (dag *Dag) Print() (bytes.Buffer, error) {
   108  	var buffer bytes.Buffer
   109  
   110  	var dagCpy = &Dag{}
   111  	if err := clone(dag, dagCpy); err != nil {
   112  		return buffer, err
   113  	}
   114  	var level = 0
   115  	for dagCpy.HasNext() {
   116  		buffer.WriteString(fmt.Sprintf("level:%d \n    ", level))
   117  		idxs := dagCpy.Next()
   118  		for _, idx := range idxs {
   119  			if level == 0 {
   120  				buffer.WriteString(fmt.Sprintf("idx:%d ", idx))
   121  			} else {
   122  				buffer.WriteString(fmt.Sprintf("idx:%d%+v ", idx, dagCpy.VertexList[idx].InEdges))
   123  			}
   124  		}
   125  		buffer.WriteString("\n")
   126  		level++
   127  	}
   128  	return buffer, nil
   129  }
   130  
   131  func clone(src, dest interface{}) error {
   132  	buff := new(bytes.Buffer)
   133  	enc := gob.NewEncoder(buff)
   134  	dec := gob.NewDecoder(buff)
   135  	if err := enc.Encode(src); err != nil {
   136  		return err
   137  	}
   138  	if err := dec.Decode(dest); err != nil {
   139  		return err
   140  	}
   141  	return nil
   142  }