Two ways to spend the same education budget: a uniform random sample (spray and pray) vs the highest-degree hubs, ties broken stably towards lower node numbers so the pick is deterministic. The origin is never educated; they post the fake. rng.Shuffle does a seeded Fisher-Yates, so the random pick is reproducible too. min() is a builtin since Go 1.21.
52 lines
1.6 KiB
Go
52 lines
1.6 KiB
Go
package engine
|
|
|
|
import (
|
|
"math/rand/v2"
|
|
"slices"
|
|
)
|
|
|
|
// Education strategies pick which students the program educates. The origin
|
|
// is never educated (they post the fake in the first place). Returned
|
|
// slices are sorted by node number for readable, stable output; the order
|
|
// carries no meaning.
|
|
|
|
// EducateRandom educates count students drawn uniformly from everyone but
|
|
// the origin. This is the "spray and pray" baseline.
|
|
func EducateRandom(graph *Graph, origin, count int, rng *rand.Rand) []int {
|
|
if count <= 0 {
|
|
return nil
|
|
}
|
|
candidates := make([]int, 0, graph.NumNodes()-1)
|
|
for student := range graph.NumNodes() {
|
|
if student != origin {
|
|
candidates = append(candidates, student)
|
|
}
|
|
}
|
|
rng.Shuffle(len(candidates), func(i, j int) {
|
|
candidates[i], candidates[j] = candidates[j], candidates[i]
|
|
})
|
|
educated := candidates[:min(count, len(candidates))]
|
|
slices.Sort(educated)
|
|
return educated
|
|
}
|
|
|
|
// EducateMostConnected educates the count students with the highest degree:
|
|
// the hubs whose forwarding keeps the network connected. Ties break towards
|
|
// the lower node number (stable sort) so the choice is deterministic.
|
|
func EducateMostConnected(graph *Graph, origin, count int) []int {
|
|
if count <= 0 {
|
|
return nil
|
|
}
|
|
candidates := make([]int, 0, graph.NumNodes()-1)
|
|
for student := range graph.NumNodes() {
|
|
if student != origin {
|
|
candidates = append(candidates, student)
|
|
}
|
|
}
|
|
slices.SortStableFunc(candidates, func(first, second int) int {
|
|
return graph.Degree(second) - graph.Degree(first) // descending by degree
|
|
})
|
|
educated := candidates[:min(count, len(candidates))]
|
|
slices.Sort(educated)
|
|
return educated
|
|
}
|