Wideband autonomous SDR analysis engine forked from sdr-visual-suite
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

71 строка
2.1KB

  1. package pipeline
  2. import "sort"
  3. type ScheduledCandidate struct {
  4. Candidate Candidate `json:"candidate"`
  5. Priority float64 `json:"priority"`
  6. }
  7. // BuildRefinementPlan scores and budgets candidates for costly local refinement.
  8. // Current heuristic is intentionally simple and deterministic; later phases can add
  9. // richer scoring (novelty, persistence, profile-aware band priorities, decoder value).
  10. func BuildRefinementPlan(candidates []Candidate, policy Policy) RefinementPlan {
  11. budget := policy.MaxRefinementJobs
  12. if policy.RefinementMaxConcurrent > 0 && (budget <= 0 || policy.RefinementMaxConcurrent < budget) {
  13. budget = policy.RefinementMaxConcurrent
  14. }
  15. plan := RefinementPlan{
  16. TotalCandidates: len(candidates),
  17. MinCandidateSNRDb: policy.MinCandidateSNRDb,
  18. Budget: budget,
  19. }
  20. if len(candidates) == 0 {
  21. return plan
  22. }
  23. snrWeight, bwWeight, peakWeight := refinementIntentWeights(policy.Intent)
  24. scored := make([]ScheduledCandidate, 0, len(candidates))
  25. for _, c := range candidates {
  26. if !candidateInMonitor(policy, c) {
  27. plan.DroppedByMonitor++
  28. continue
  29. }
  30. if c.SNRDb < policy.MinCandidateSNRDb {
  31. plan.DroppedBySNR++
  32. continue
  33. }
  34. priority := c.SNRDb*snrWeight + CandidatePriorityBoost(policy, c.Hint)
  35. if c.BandwidthHz > 0 {
  36. priority += minFloat64(c.BandwidthHz/25000.0, 6) * bwWeight
  37. }
  38. if c.PeakDb > 0 {
  39. priority += (c.PeakDb / 20.0) * peakWeight
  40. }
  41. scored = append(scored, ScheduledCandidate{Candidate: c, Priority: priority})
  42. }
  43. sort.Slice(scored, func(i, j int) bool {
  44. if scored[i].Priority == scored[j].Priority {
  45. return scored[i].Candidate.CenterHz < scored[j].Candidate.CenterHz
  46. }
  47. return scored[i].Priority > scored[j].Priority
  48. })
  49. limit := plan.Budget
  50. if limit <= 0 || limit > len(scored) {
  51. limit = len(scored)
  52. }
  53. plan.Selected = scored[:limit]
  54. plan.DroppedByBudget = len(scored) - len(plan.Selected)
  55. return plan
  56. }
  57. func ScheduleCandidates(candidates []Candidate, policy Policy) []ScheduledCandidate {
  58. return BuildRefinementPlan(candidates, policy).Selected
  59. }
  60. func minFloat64(a, b float64) float64 {
  61. if a < b {
  62. return a
  63. }
  64. return b
  65. }