Example #1
0
func (c *Connectivity) connectivityChange() {
	// reachability prune
	g := graph.ReachableGraph(c.id, func(node NodeID) []NodeID {
		return c.connProp.Get(node, []NodeID(nil)).([]NodeID)
	})

	// The graph g might not be symmetric, as we might hear that
	// one side of a link was dropped or established
	// before/without hearing about the other side.
	//
	// We can't simply make it symmetric by adding edges to make
	// an undirected graph, because that might result in an edge in
	// the spanning tree that doesn't correspond to a working
	// link.
	//
	// Alteratively, we can make an undirected graph by removing
	// edges that don't have a counterpart reverse edge.  This is
	// better, but introduces a bootstrapping problem: When we add
	// a link to another node, we don't know that it is linked to
	// us, and so the edge won't feature in the graph.  Which
	// would mean that we can never learn anything from other
	// nodes.
	//
	// So we use the intersected graph, but enhance it with the
	// local graph whcih reflects links from this node to
	// neighbouring nodes.
	local := graph.Graph{
		Nodes: graph.SortNodeIDs(append(c.linkNodeIDs(), c.id)),
		Edges: func(node NodeID) []NodeID {
			if node == c.id {
				return c.linkNodeIDs()
			} else {
				return nil
			}
		},
	}

	local = local.Union(local.Transpose())

	g = g.Intersect(g.Transpose()).Union(local)

	// XXX Prune the propagation according to g

	// recompute spanning tree
	pcn := graph.FindPseudoCentralNode(g, 10)
	t := graph.MakeBushySpanningTree(g, pcn, 4)

	for _, link := range c.links {
		link.pendingProps = nil
	}

	for _, b := range t.Undirected().Edges(c.id) {
		c.links[b].pendingProps = make(map[*Propagation]*Neighbor)
	}

	c.checkPending(c.connProp)
}
Example #2
0
func (c *Connectivity) linksChanged() {
	c.connProp.Set(c.id, graph.SortNodeIDs(c.linkNodeIDs()))
}