rename gg.HalfEdge to gg.OpenEdge

This commit is contained in:
Brian Picciano 2017-11-05 09:11:05 -07:00
parent 11328fa76c
commit cae3116424
2 changed files with 71 additions and 73 deletions

View File

@ -8,8 +8,6 @@ import (
"hash" "hash"
) )
// TODO rename half-edge to open-edge
// Identifier is implemented by any value which can return a unique string for // Identifier is implemented by any value which can return a unique string for
// itself via an Identify method // itself via an Identify method
type Identifier interface { type Identifier interface {
@ -53,9 +51,9 @@ type Vertex struct {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// HalfEdge is an un-realized Edge which can't be used for anything except // OpenEdge is an un-realized Edge which can't be used for anything except
// constructing graphs. It has no meaning on its own. // constructing graphs. It has no meaning on its own.
type HalfEdge struct { type OpenEdge struct {
// fromV will be the source vertex as-if the vertex (and any sub-vertices of // fromV will be the source vertex as-if the vertex (and any sub-vertices of
// it) doesn't already exist in the graph. If it or it's sub-vertices does // it) doesn't already exist in the graph. If it or it's sub-vertices does
// already that will need to be taken into account when persisting into the // already that will need to be taken into account when persisting into the
@ -65,19 +63,19 @@ type HalfEdge struct {
} }
// Identify implements the Identifier interface // Identify implements the Identifier interface
func (he HalfEdge) Identify(h hash.Hash) { func (oe OpenEdge) Identify(h hash.Hash) {
fmt.Fprintln(h, "halfEdge") fmt.Fprintln(h, "openEdge")
he.fromV.Identify(h) oe.fromV.Identify(h)
he.val.Identify(h) oe.val.Identify(h)
} }
// vertex is a representation of a vertex in the graph. Each Graph contains a // vertex is a representation of a vertex in the graph. Each Graph contains a
// set of all the Value vertex instances it knows about. Each of these contains // set of all the Value vertex instances it knows about. Each of these contains
// all the input HalfEdges which are known for it. So you can think of these // all the input OpenEdges which are known for it. So you can think of these
// "top-level" Value vertex instances as root nodes in a tree, and each HalfEdge // "top-level" Value vertex instances as root nodes in a tree, and each OpenEdge
// as a branch. // as a branch.
// //
// If a HalfEdge contains a fromV which is a Value that vertex won't have its in // If a OpenEdge contains a fromV which is a Value that vertex won't have its in
// slice populated no matter what. If fromV is a Junction it will be populated, // slice populated no matter what. If fromV is a Junction it will be populated,
// with any sub-Value's not being populated and so-on recursively // with any sub-Value's not being populated and so-on recursively
// //
@ -86,7 +84,7 @@ func (he HalfEdge) Identify(h hash.Hash) {
type vertex struct { type vertex struct {
VertexType VertexType
val Identifier val Identifier
in []HalfEdge in []OpenEdge
} }
// A Value vertex is unique by the value it contains // A Value vertex is unique by the value it contains
@ -108,25 +106,25 @@ func (v vertex) Identify(h hash.Hash) {
func (v vertex) cp() vertex { func (v vertex) cp() vertex {
cp := v cp := v
cp.in = make([]HalfEdge, len(v.in)) cp.in = make([]OpenEdge, len(v.in))
copy(cp.in, v.in) copy(cp.in, v.in)
return cp return cp
} }
func (v vertex) hasHalfEdge(he HalfEdge) bool { func (v vertex) hasOpenEdge(oe OpenEdge) bool {
heID := identify(he) oeID := identify(oe)
for _, in := range v.in { for _, in := range v.in {
if identify(in) == heID { if identify(in) == oeID {
return true return true
} }
} }
return false return false
} }
func (v vertex) cpAndDelHalfEdge(he HalfEdge) (vertex, bool) { func (v vertex) cpAndDelOpenEdge(oe OpenEdge) (vertex, bool) {
heID := identify(he) oeID := identify(oe)
for i, in := range v.in { for i, in := range v.in {
if identify(in) == heID { if identify(in) == oeID {
v = v.cp() v = v.cp()
v.in = append(v.in[:i], v.in[i+1:]...) v.in = append(v.in[:i], v.in[i+1:]...)
return v, true return v, true
@ -162,15 +160,15 @@ func (g *Graph) cp() *Graph {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Graph creation // Graph creation
// ValueOut creates a HalfEdge which, when used to construct a Graph, represents // ValueOut creates a OpenEdge which, when used to construct a Graph, represents
// an edge (with edgeVal attached to it) leaving the Value Vertex containing // an edge (with edgeVal attached to it) leaving the Value Vertex containing
// val. // val.
// //
// When constructing Graphs Value vertices are de-duplicated on their value. So // When constructing Graphs Value vertices are de-duplicated on their value. So
// multiple ValueOut HalfEdges constructed with the same val will be leaving the // multiple ValueOut OpenEdges constructed with the same val will be leaving the
// same Vertex instance in the constructed Graph. // same Vertex instance in the constructed Graph.
func ValueOut(val, edgeVal Identifier) HalfEdge { func ValueOut(val, edgeVal Identifier) OpenEdge {
return HalfEdge{ return OpenEdge{
fromV: vertex{ fromV: vertex{
VertexType: Value, VertexType: Value,
val: val, val: val,
@ -179,15 +177,15 @@ func ValueOut(val, edgeVal Identifier) HalfEdge {
} }
} }
// JunctionOut creates a HalfEdge which, when used to construct a Graph, // JunctionOut creates a OpenEdge which, when used to construct a Graph,
// represents an edge (with edgeVal attached to it) leaving the Junction Vertex // represents an edge (with edgeVal attached to it) leaving the Junction Vertex
// comprised of the given ordered-set of input edges. // comprised of the given ordered-set of input edges.
// //
// When constructing Graphs Junction vertices are de-duplicated on their input // When constructing Graphs Junction vertices are de-duplicated on their input
// edges. So multiple Junction HalfEdges constructed with the same set of input // edges. So multiple Junction OpenEdges constructed with the same set of input
// edges will be leaving the same Junction instance in the constructed Graph. // edges will be leaving the same Junction instance in the constructed Graph.
func JunctionOut(in []HalfEdge, edgeVal Identifier) HalfEdge { func JunctionOut(in []OpenEdge, edgeVal Identifier) OpenEdge {
return HalfEdge{ return OpenEdge{
fromV: vertex{ fromV: vertex{
VertexType: Junction, VertexType: Junction,
in: in, in: in,
@ -196,11 +194,11 @@ func JunctionOut(in []HalfEdge, edgeVal Identifier) HalfEdge {
} }
} }
// AddValueIn takes a HalfEdge and connects it to the Value Vertex containing // AddValueIn takes a OpenEdge and connects it to the Value Vertex containing
// val, returning the new Graph which reflects that connection. Any Vertices // val, returning the new Graph which reflects that connection. Any Vertices
// referenced within the HalfEdge which do not yet exist in the Graph will also // referenced within toe OpenEdge which do not yet exist in the Graph will also
// be created in this step. // be created in this step.
func (g *Graph) AddValueIn(he HalfEdge, val Identifier) *Graph { func (g *Graph) AddValueIn(oe OpenEdge, val Identifier) *Graph {
to := vertex{ to := vertex{
VertexType: Value, VertexType: Value,
val: val, val: val,
@ -214,12 +212,12 @@ func (g *Graph) AddValueIn(he HalfEdge, val Identifier) *Graph {
} }
// if the incoming edge already exists in to then there's nothing to do // if the incoming edge already exists in to then there's nothing to do
if to.hasHalfEdge(he) { if to.hasOpenEdge(oe) {
return g return g
} }
to = to.cp() to = to.cp()
to.in = append(to.in, he) to.in = append(to.in, oe)
g = g.cp() g = g.cp()
// starting with to (which we always overwrite) go through vM and // starting with to (which we always overwrite) go through vM and
@ -246,12 +244,12 @@ func (g *Graph) AddValueIn(he HalfEdge, val Identifier) *Graph {
return g return g
} }
// DelValueIn takes a HalfEdge and disconnects it from the Value Vertex // DelValueIn takes a OpenEdge and disconnects it from the Value Vertex
// containing val, returning the new Graph which reflects the disconnection. If // containing val, returning the new Graph which reflects the disconnection. If
// the Value Vertex doesn't exist within the graph, or it doesn't have the given // the Value Vertex doesn't exist within the graph, or it doesn't have the given
// HalfEdge, no changes are made. Any vertices referenced by the HalfEdge for // OpenEdge, no changes are made. Any vertices referenced by toe OpenEdge for
// which that edge is their only outgoing edge will be removed from the Graph. // which that edge is their only outgoing edge will be removed from the Graph.
func (g *Graph) DelValueIn(he HalfEdge, val Identifier) *Graph { func (g *Graph) DelValueIn(oe OpenEdge, val Identifier) *Graph {
to := vertex{ to := vertex{
VertexType: Value, VertexType: Value,
val: val, val: val,
@ -266,7 +264,7 @@ func (g *Graph) DelValueIn(he HalfEdge, val Identifier) *Graph {
// get new copy of to without the half-edge, or return if the half-edge // get new copy of to without the half-edge, or return if the half-edge
// wasn't even in to // wasn't even in to
to, ok = to.cpAndDelHalfEdge(he) to, ok = to.cpAndDelOpenEdge(oe)
if !ok { if !ok {
return g return g
} }
@ -309,19 +307,19 @@ func (g *Graph) DelValueIn(he HalfEdge, val Identifier) *Graph {
delete(g.vM, toID) delete(g.vM, toID)
} }
// rmOrphaned descends down the given HalfEdge and removes any Value // rmOrphaned descends down the given OpenEdge and removes any Value
// Vertices referenced in it which are now orphaned // Vertices referenced in it which are now orphaned
var rmOrphaned func(HalfEdge) var rmOrphaned func(OpenEdge)
rmOrphaned = func(he HalfEdge) { rmOrphaned = func(oe OpenEdge) {
if he.fromV.VertexType == Value && isOrphaned(he.fromV) { if oe.fromV.VertexType == Value && isOrphaned(oe.fromV) {
delete(g.vM, identify(he.fromV)) delete(g.vM, identify(oe.fromV))
} else if he.fromV.VertexType == Junction { } else if oe.fromV.VertexType == Junction {
for _, juncHe := range he.fromV.in { for _, juncHe := range oe.fromV.in {
rmOrphaned(juncHe) rmOrphaned(juncHe)
} }
} }
} }
rmOrphaned(he) rmOrphaned(oe)
return g return g
} }
@ -337,7 +335,7 @@ func (g *Graph) Union(g2 *Graph) *Graph {
v = v2 v = v2
} else { } else {
for _, v2e := range v2.in { for _, v2e := range v2.in {
if !v.hasHalfEdge(v2e) { if !v.hasOpenEdge(v2e) {
v.in = append(v.in, v2e) v.in = append(v.in, v2e)
} }
} }
@ -432,7 +430,7 @@ func Equal(g1, g2 *Graph) bool {
return false return false
} }
for _, in := range v1.in { for _, in := range v1.in {
if !v2.hasHalfEdge(in) { if !v2.hasOpenEdge(in) {
return false return false
} }
} }

View File

@ -156,7 +156,7 @@ func TestGraph(t *T) {
func() *Graph { func() *Graph {
e0 := ValueOut(id("v0"), id("e0")) e0 := ValueOut(id("v0"), id("e0"))
e1 := ValueOut(id("v1"), id("e1")) e1 := ValueOut(id("v1"), id("e1"))
ej0 := JunctionOut([]HalfEdge{e0, e1}, id("ej0")) ej0 := JunctionOut([]OpenEdge{e0, e1}, id("ej0"))
return Null.AddValueIn(ej0, id("v2")) return Null.AddValueIn(ej0, id("v2"))
}, },
value("v0"), value("v1"), value("v0"), value("v1"),
@ -171,11 +171,11 @@ func TestGraph(t *T) {
func() *Graph { func() *Graph {
e00 := ValueOut(id("v0"), id("e00")) e00 := ValueOut(id("v0"), id("e00"))
e10 := ValueOut(id("v1"), id("e10")) e10 := ValueOut(id("v1"), id("e10"))
ej0 := JunctionOut([]HalfEdge{e00, e10}, id("ej0")) ej0 := JunctionOut([]OpenEdge{e00, e10}, id("ej0"))
e01 := ValueOut(id("v0"), id("e01")) e01 := ValueOut(id("v0"), id("e01"))
e11 := ValueOut(id("v1"), id("e11")) e11 := ValueOut(id("v1"), id("e11"))
ej1 := JunctionOut([]HalfEdge{e01, e11}, id("ej1")) ej1 := JunctionOut([]OpenEdge{e01, e11}, id("ej1"))
ej2 := JunctionOut([]HalfEdge{ej0, ej1}, id("ej2")) ej2 := JunctionOut([]OpenEdge{ej0, ej1}, id("ej2"))
return Null.AddValueIn(ej2, id("v2")) return Null.AddValueIn(ej2, id("v2"))
}, },
value("v0"), value("v1"), value("v0"), value("v1"),
@ -196,7 +196,7 @@ func TestGraph(t *T) {
func() *Graph { func() *Graph {
e0 := ValueOut(id("v0"), id("e0")) e0 := ValueOut(id("v0"), id("e0"))
e1 := ValueOut(id("v1"), id("e1")) e1 := ValueOut(id("v1"), id("e1"))
ej0 := JunctionOut([]HalfEdge{e0, e1}, id("ej0")) ej0 := JunctionOut([]OpenEdge{e0, e1}, id("ej0"))
g0 := Null.AddValueIn(ej0, id("v2")) g0 := Null.AddValueIn(ej0, id("v2"))
e20 := ValueOut(id("v2"), id("e20")) e20 := ValueOut(id("v2"), id("e20"))
g1 := g0.AddValueIn(e20, id("v0")) g1 := g0.AddValueIn(e20, id("v0"))
@ -275,27 +275,27 @@ func TestGraphDelValueIn(t *T) {
} }
{ // removing only edge { // removing only edge
he := ValueOut(id("v0"), id("e0")) oe := ValueOut(id("v0"), id("e0"))
g0 := Null.AddValueIn(he, id("v1")) g0 := Null.AddValueIn(oe, id("v1"))
g1 := g0.DelValueIn(he, id("v1")) g1 := g0.DelValueIn(oe, id("v1"))
assert.True(t, Equal(Null, g1)) assert.True(t, Equal(Null, g1))
} }
{ // removing only edge (junction) { // removing only edge (junction)
he := JunctionOut([]HalfEdge{ oe := JunctionOut([]OpenEdge{
ValueOut(id("v0"), id("e0")), ValueOut(id("v0"), id("e0")),
ValueOut(id("v1"), id("e1")), ValueOut(id("v1"), id("e1")),
}, id("ej0")) }, id("ej0"))
g0 := Null.AddValueIn(he, id("v2")) g0 := Null.AddValueIn(oe, id("v2"))
g1 := g0.DelValueIn(he, id("v2")) g1 := g0.DelValueIn(oe, id("v2"))
assert.True(t, Equal(Null, g1)) assert.True(t, Equal(Null, g1))
} }
{ // removing one of two edges { // removing one of two edges
he := ValueOut(id("v1"), id("e0")) oe := ValueOut(id("v1"), id("e0"))
g0 := Null.AddValueIn(ValueOut(id("v0"), id("e0")), id("v2")) g0 := Null.AddValueIn(ValueOut(id("v0"), id("e0")), id("v2"))
g1 := g0.AddValueIn(he, id("v2")) g1 := g0.AddValueIn(oe, id("v2"))
g2 := g1.DelValueIn(he, id("v2")) g2 := g1.DelValueIn(oe, id("v2"))
assert.True(t, Equal(g0, g2)) assert.True(t, Equal(g0, g2))
assert.NotNil(t, g2.Value(id("v0"))) assert.NotNil(t, g2.Value(id("v0")))
assert.Nil(t, g2.Value(id("v1"))) assert.Nil(t, g2.Value(id("v1")))
@ -306,11 +306,11 @@ func TestGraphDelValueIn(t *T) {
e0 := ValueOut(id("v0"), id("e0")) e0 := ValueOut(id("v0"), id("e0"))
e1 := ValueOut(id("v1"), id("e1")) e1 := ValueOut(id("v1"), id("e1"))
e2 := ValueOut(id("v2"), id("e2")) e2 := ValueOut(id("v2"), id("e2"))
heA := JunctionOut([]HalfEdge{e0, e1}, id("heA")) oeA := JunctionOut([]OpenEdge{e0, e1}, id("oeA"))
heB := JunctionOut([]HalfEdge{e1, e2}, id("heB")) oeB := JunctionOut([]OpenEdge{e1, e2}, id("oeB"))
g0a := Null.AddValueIn(heA, id("v3")) g0a := Null.AddValueIn(oeA, id("v3"))
g0b := Null.AddValueIn(heB, id("v3")) g0b := Null.AddValueIn(oeB, id("v3"))
g1 := g0a.Union(g0b).DelValueIn(heA, id("v3")) g1 := g0a.Union(g0b).DelValueIn(oeA, id("v3"))
assert.True(t, Equal(g1, g0b)) assert.True(t, Equal(g1, g0b))
assert.Nil(t, g1.Value(id("v0"))) assert.Nil(t, g1.Value(id("v0")))
assert.NotNil(t, g1.Value(id("v1"))) assert.NotNil(t, g1.Value(id("v1")))
@ -329,7 +329,7 @@ func TestGraphDelValueIn(t *T) {
} }
{ // removing to's only edge, sub-nodes have edge to each other { // removing to's only edge, sub-nodes have edge to each other
ej := JunctionOut([]HalfEdge{ ej := JunctionOut([]OpenEdge{
ValueOut(id("v0"), id("ej0")), ValueOut(id("v0"), id("ej0")),
ValueOut(id("v1"), id("ej0")), ValueOut(id("v1"), id("ej0")),
}, id("ej")) }, id("ej"))
@ -370,11 +370,11 @@ func TestGraphUnion(t *T) {
} }
{ // Two disparate graphs with junctions { // Two disparate graphs with junctions
ga := Null.AddValueIn(JunctionOut([]HalfEdge{ ga := Null.AddValueIn(JunctionOut([]OpenEdge{
ValueOut(id("va0"), id("ea0")), ValueOut(id("va0"), id("ea0")),
ValueOut(id("va1"), id("ea1")), ValueOut(id("va1"), id("ea1")),
}, id("eaj")), id("va2")) }, id("eaj")), id("va2"))
gb := Null.AddValueIn(JunctionOut([]HalfEdge{ gb := Null.AddValueIn(JunctionOut([]OpenEdge{
ValueOut(id("vb0"), id("eb0")), ValueOut(id("vb0"), id("eb0")),
ValueOut(id("vb1"), id("eb1")), ValueOut(id("vb1"), id("eb1")),
}, id("ebj")), id("vb2")) }, id("ebj")), id("vb2"))
@ -413,11 +413,11 @@ func TestGraphUnion(t *T) {
} }
{ // two partially overlapping graphs with junctions { // two partially overlapping graphs with junctions
g0 := Null.AddValueIn(JunctionOut([]HalfEdge{ g0 := Null.AddValueIn(JunctionOut([]OpenEdge{
ValueOut(id("v0"), id("e0")), ValueOut(id("v0"), id("e0")),
ValueOut(id("v1"), id("e1")), ValueOut(id("v1"), id("e1")),
}, id("ej0")), id("v2")) }, id("ej0")), id("v2"))
g1 := Null.AddValueIn(JunctionOut([]HalfEdge{ g1 := Null.AddValueIn(JunctionOut([]OpenEdge{
ValueOut(id("v0"), id("e0")), ValueOut(id("v0"), id("e0")),
ValueOut(id("v1"), id("e1")), ValueOut(id("v1"), id("e1")),
}, id("ej1")), id("v2")) }, id("ej1")), id("v2"))
@ -444,7 +444,7 @@ func TestGraphUnion(t *T) {
} }
{ // Two equal graphs with junctions { // Two equal graphs with junctions
g0 := Null.AddValueIn(JunctionOut([]HalfEdge{ g0 := Null.AddValueIn(JunctionOut([]OpenEdge{
ValueOut(id("v0"), id("e0")), ValueOut(id("v0"), id("e0")),
ValueOut(id("v1"), id("e1")), ValueOut(id("v1"), id("e1")),
}, id("ej0")), id("v2")) }, id("ej0")), id("v2"))
@ -500,8 +500,8 @@ func TestGraphEqual(t *T) {
{ // junction basic test { // junction basic test
e0 := ValueOut(id("v0"), id("e0")) e0 := ValueOut(id("v0"), id("e0"))
e1 := ValueOut(id("v1"), id("e1")) e1 := ValueOut(id("v1"), id("e1"))
ga := Null.AddValueIn(JunctionOut([]HalfEdge{e0, e1}, id("ej")), id("v2")) ga := Null.AddValueIn(JunctionOut([]OpenEdge{e0, e1}, id("ej")), id("v2"))
gb := Null.AddValueIn(JunctionOut([]HalfEdge{e1, e0}, id("ej")), id("v2")) gb := Null.AddValueIn(JunctionOut([]OpenEdge{e1, e0}, id("ej")), id("v2"))
assertEqual(ga, ga) assertEqual(ga, ga)
assertNotEqual(ga, gb) assertNotEqual(ga, gb)
} }