autopilot/interface+prefattach: scale node scores to range [0.0, 1.0]
To prepare for combinning scores from multiple heuristics, we require the scores returned from the NodeSores API to be in the range [0.0, 1.0]. The prefAttach heuristic is altered to scale the returned scores such that the most connected node in the grpah is given a score of 1.0.
This commit is contained in:
parent
4537c63dbd
commit
592ce92c72
@ -125,11 +125,12 @@ type AttachmentHeuristic interface {
|
|||||||
// returned channel candidates maps the NodeID to a NodeScore for the
|
// returned channel candidates maps the NodeID to a NodeScore for the
|
||||||
// node.
|
// node.
|
||||||
//
|
//
|
||||||
// The scores will be in the range [0, M], where 0 indicates no
|
// The returned scores will be in the range [0, 1.0], where 0 indicates
|
||||||
// improvement in connectivity if a channel is opened to this node,
|
// no improvement in connectivity if a channel is opened to this node,
|
||||||
// while M is the maximum possible improvement in connectivity. The
|
// while 1.0 is the maximum possible improvement in connectivity. The
|
||||||
// size of M is up to the implementation of this interface, so scores
|
// implementation of this interface must return scores in this range to
|
||||||
// must be normalized if compared against other implementations.
|
// properly allow the autopilot agent to make a reasonable choice based
|
||||||
|
// on the score from multiple heuristics.
|
||||||
//
|
//
|
||||||
// NOTE: A NodeID not found in the returned map is implicitly given a
|
// NOTE: A NodeID not found in the returned map is implicitly given a
|
||||||
// score of 0.
|
// score of 0.
|
||||||
|
@ -43,9 +43,10 @@ func NewNodeID(pub *btcec.PublicKey) NodeID {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeScores is a method that given the current channel graph and
|
// NodeScores is a method that given the current channel graph and current set
|
||||||
// current set of local channels, scores the given nodes according to
|
// of local channels, scores the given nodes according to the preference of
|
||||||
// the preference of opening a channel of the given size with them.
|
// opening a channel of the given size with them. The returned channel
|
||||||
|
// candidates maps the NodeID to a NodeScore for the node.
|
||||||
//
|
//
|
||||||
// The heuristic employed by this method is one that attempts to promote a
|
// The heuristic employed by this method is one that attempts to promote a
|
||||||
// scale-free network globally, via local attachment preferences for new nodes
|
// scale-free network globally, via local attachment preferences for new nodes
|
||||||
@ -64,21 +65,25 @@ func (p *PrefAttachment) NodeScores(g ChannelGraph, chans []Channel,
|
|||||||
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
|
chanSize btcutil.Amount, nodes map[NodeID]struct{}) (
|
||||||
map[NodeID]*NodeScore, error) {
|
map[NodeID]*NodeScore, error) {
|
||||||
|
|
||||||
// Count the number of channels in the graph. We'll also count the
|
// Count the number of channels for each particular node in the graph.
|
||||||
// number of channels as we go for the nodes we are interested in.
|
var maxChans int
|
||||||
var graphChans int
|
|
||||||
nodeChanNum := make(map[NodeID]int)
|
nodeChanNum := make(map[NodeID]int)
|
||||||
if err := g.ForEachNode(func(n Node) error {
|
if err := g.ForEachNode(func(n Node) error {
|
||||||
var nodeChans int
|
var nodeChans int
|
||||||
err := n.ForEachChannel(func(_ ChannelEdge) error {
|
err := n.ForEachChannel(func(_ ChannelEdge) error {
|
||||||
nodeChans++
|
nodeChans++
|
||||||
graphChans++
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We keep track of the highest-degree node we've seen, as this
|
||||||
|
// will be given the max score.
|
||||||
|
if nodeChans > maxChans {
|
||||||
|
maxChans = nodeChans
|
||||||
|
}
|
||||||
|
|
||||||
// If this node is not among our nodes to score, we can return
|
// If this node is not among our nodes to score, we can return
|
||||||
// early.
|
// early.
|
||||||
nID := NodeID(n.PubKey())
|
nID := NodeID(n.PubKey())
|
||||||
@ -97,7 +102,7 @@ func (p *PrefAttachment) NodeScores(g ChannelGraph, chans []Channel,
|
|||||||
// If there are no channels in the graph we cannot determine any
|
// If there are no channels in the graph we cannot determine any
|
||||||
// preferences, so we return, indicating all candidates get a score of
|
// preferences, so we return, indicating all candidates get a score of
|
||||||
// zero.
|
// zero.
|
||||||
if graphChans == 0 {
|
if maxChans == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,8 +132,9 @@ func (p *PrefAttachment) NodeScores(g ChannelGraph, chans []Channel,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we score the node according to its fraction of
|
// Otherwise we score the node according to its fraction of
|
||||||
// channels in the graph.
|
// channels in the graph, scaled such that the highest-degree
|
||||||
score := float64(nodeChans) / float64(graphChans)
|
// node will be given a score of 1.0.
|
||||||
|
score := float64(nodeChans) / float64(maxChans)
|
||||||
candidates[nID] = &NodeScore{
|
candidates[nID] = &NodeScore{
|
||||||
NodeID: nID,
|
NodeID: nID,
|
||||||
Score: score,
|
Score: score,
|
||||||
|
@ -249,8 +249,8 @@ func TestPrefAttachmentSelectTwoVertexes(t *testing.T) {
|
|||||||
|
|
||||||
// Since each of the nodes has 1 channel, out
|
// Since each of the nodes has 1 channel, out
|
||||||
// of only one channel in the graph, we expect
|
// of only one channel in the graph, we expect
|
||||||
// their score to be 0.5.
|
// their score to be 1.0.
|
||||||
expScore := float64(0.5)
|
expScore := float64(1.0)
|
||||||
if candidate.Score != expScore {
|
if candidate.Score != expScore {
|
||||||
t1.Fatalf("expected candidate score "+
|
t1.Fatalf("expected candidate score "+
|
||||||
"to be %v, instead was %v",
|
"to be %v, instead was %v",
|
||||||
|
Loading…
Reference in New Issue
Block a user