1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
package build
// EdgeSet describes a set of edges; an edge (v, w), v ≠ w, belongs to the set
// if Keep(v, w) is true and (v, w) belongs to either From × To or To × From.
// The zero value of an edge set is the universe, the set containing all edges.
type EdgeSet struct {
From, To VertexSet
Keep FilterFunc
Cost CostFunc
}
// AllEdges returns the universe, the set containing all edges.
// The edge cost is zero.
func AllEdges() EdgeSet {
return EdgeSet{}
}
// NoEdges returns a set that includes no edges.
func NoEdges() EdgeSet {
return EdgeSet{
From: Range(0, 0),
To: Range(0, 0),
Keep: neverEdge,
}
}
// Edge returns a set consisting of a single edge {v, w}, v ≠ w, of zero cost.
func Edge(v, w int) EdgeSet {
if v < 0 || w < 0 || v == w {
return NoEdges()
}
return EdgeSet{
From: Vertex(v),
To: Vertex(w),
}
}
// Contains tells if the set contains the edge {v, w}.
func (e EdgeSet) Contains(v, w int) bool {
switch {
case e.Keep != nil && !e.Keep(v, w):
return false
case e.From.Contains(v) && e.To.Contains(w):
return true
case e.To.Contains(v) && e.From.Contains(w):
return true
default:
return false
}
}
// Add returns a graph containing all edges in g plus all edges in e.
// Any edges belonging to both g and e will retain their cost from g.
func (g *Virtual) Add(e EdgeSet) *Virtual {
return g.union(newEdges(g.Order(), e), true)
}
// Delete returns a graph containing all edges in g except those also found in e.
func (g *Virtual) Delete(e EdgeSet) *Virtual {
return g.Keep(func(v, w int) bool {
return !e.Contains(v, w)
})
}
// newEdges returns a virtual graph with n vertices and all edges
// belonging to the edge set.
func newEdges(n int, e EdgeSet) *Virtual {
switch {
case n < 0:
return nil
case n == 0:
return null
case n == 1:
return singleton()
}
var noCost bool
if e.Cost == nil {
noCost = true
e.Cost = zero
}
var noFilter bool
if e.Keep == nil {
noFilter = true
e.Keep = alwaysEdge
}
from := e.From.And(Range(0, n))
to := e.To.And(Range(0, n))
if from.size() == 0 || to.size() == 0 {
return Empty(n)
}
res := generic(n, e.Cost, func(v, w int) (edge bool) {
return e.Contains(v, w)
})
intersect := from.And(to)
union := from.Or(to)
if noFilter {
res.degree = func(v int) (deg int) {
switch {
case intersect.Contains(v):
return union.size() - 1
case from.Contains(v):
return to.size()
case to.Contains(v):
return from.size()
default:
return
}
}
}
visit := func(v int, a int, do func(w int, c int64) bool) (aborted bool) {
switch {
case intersect.Contains(v):
for _, in := range union.And(Range(a, n)).set {
for w := in.a; w < in.b; w++ {
if v != w && e.Keep(v, w) && do(w, e.Cost(v, w)) {
return true
}
}
}
return
case from.Contains(v):
for _, in := range to.And(Range(a, n)).set {
for w := in.a; w < in.b; w++ {
if e.Keep(v, w) && do(w, e.Cost(v, w)) {
return true
}
}
}
return
case to.Contains(v):
for _, in := range from.And(Range(a, n)).set {
for w := in.a; w < in.b; w++ {
if e.Keep(v, w) && do(w, e.Cost(v, w)) {
return true
}
}
}
return
default:
return
}
}
visit0 := func(v int, a int, do func(w int, c int64) bool) (aborted bool) {
switch {
case intersect.Contains(v):
for _, in := range union.And(Range(a, n)).set {
for w := in.a; w < in.b; w++ {
if v != w && e.Keep(v, w) && do(w, 0) {
return true
}
}
}
return
case from.Contains(v):
for _, in := range to.And(Range(a, n)).set {
for w := in.a; w < in.b; w++ {
if e.Keep(v, w) && do(w, 0) {
return true
}
}
}
return
case to.Contains(v):
for _, in := range from.And(Range(a, n)).set {
for w := in.a; w < in.b; w++ {
if e.Keep(v, w) && do(w, 0) {
return true
}
}
}
return
default:
return
}
}
if noCost {
res.visit = visit0
} else {
res.visit = visit
}
return res
}
|