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
|
||||
// node.
|
||||
//
|
||||
// The scores will be in the range [0, M], where 0 indicates no
|
||||
// improvement in connectivity if a channel is opened to this node,
|
||||
// while M is the maximum possible improvement in connectivity. The
|
||||
// size of M is up to the implementation of this interface, so scores
|
||||
// must be normalized if compared against other implementations.
|
||||
// The returned scores will be in the range [0, 1.0], where 0 indicates
|
||||
// no improvement in connectivity if a channel is opened to this node,
|
||||
// while 1.0 is the maximum possible improvement in connectivity. The
|
||||
// implementation of this interface must return scores in this range to
|
||||
// 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
|
||||
// score of 0.
|
||||
|
@ -43,9 +43,10 @@ func NewNodeID(pub *btcec.PublicKey) NodeID {
|
||||
return n
|
||||
}
|
||||
|
||||
// NodeScores is a method that given the current channel graph and
|
||||
// current set of local channels, scores the given nodes according to
|
||||
// the preference of opening a channel of the given size with them.
|
||||
// NodeScores is a method that given the current channel graph and current set
|
||||
// of local channels, scores the given nodes according to the preference of
|
||||
// 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
|
||||
// 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{}) (
|
||||
map[NodeID]*NodeScore, error) {
|
||||
|
||||
// Count the number of channels in the graph. We'll also count the
|
||||
// number of channels as we go for the nodes we are interested in.
|
||||
var graphChans int
|
||||
// Count the number of channels for each particular node in the graph.
|
||||
var maxChans int
|
||||
nodeChanNum := make(map[NodeID]int)
|
||||
if err := g.ForEachNode(func(n Node) error {
|
||||
var nodeChans int
|
||||
err := n.ForEachChannel(func(_ ChannelEdge) error {
|
||||
nodeChans++
|
||||
graphChans++
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
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
|
||||
// early.
|
||||
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
|
||||
// preferences, so we return, indicating all candidates get a score of
|
||||
// zero.
|
||||
if graphChans == 0 {
|
||||
if maxChans == 0 {
|
||||
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
|
||||
// channels in the graph.
|
||||
score := float64(nodeChans) / float64(graphChans)
|
||||
// channels in the graph, scaled such that the highest-degree
|
||||
// node will be given a score of 1.0.
|
||||
score := float64(nodeChans) / float64(maxChans)
|
||||
candidates[nID] = &NodeScore{
|
||||
NodeID: nID,
|
||||
Score: score,
|
||||
|
@ -249,8 +249,8 @@ func TestPrefAttachmentSelectTwoVertexes(t *testing.T) {
|
||||
|
||||
// Since each of the nodes has 1 channel, out
|
||||
// of only one channel in the graph, we expect
|
||||
// their score to be 0.5.
|
||||
expScore := float64(0.5)
|
||||
// their score to be 1.0.
|
||||
expScore := float64(1.0)
|
||||
if candidate.Score != expScore {
|
||||
t1.Fatalf("expected candidate score "+
|
||||
"to be %v, instead was %v",
|
||||
|
Loading…
Reference in New Issue
Block a user