Wideband autonomous SDR analysis engine forked from sdr-visual-suite
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

208 líneas
5.8KB

  1. package pipeline
  2. import "strings"
  3. type BudgetQueue struct {
  4. Max int `json:"max"`
  5. IntentBias float64 `json:"intent_bias,omitempty"`
  6. Preference float64 `json:"preference,omitempty"`
  7. EffectiveMax float64 `json:"effective_max,omitempty"`
  8. RebalancedMax int `json:"rebalanced_max,omitempty"`
  9. RebalanceDelta int `json:"rebalance_delta,omitempty"`
  10. Source string `json:"source,omitempty"`
  11. }
  12. type BudgetPreference struct {
  13. Refinement float64 `json:"refinement"`
  14. Record float64 `json:"record"`
  15. Decode float64 `json:"decode"`
  16. Reasons []string `json:"reasons,omitempty"`
  17. }
  18. type BudgetModel struct {
  19. Refinement BudgetQueue `json:"refinement"`
  20. Record BudgetQueue `json:"record"`
  21. Decode BudgetQueue `json:"decode"`
  22. HoldMs int `json:"hold_ms"`
  23. Intent string `json:"intent,omitempty"`
  24. Profile string `json:"profile,omitempty"`
  25. Strategy string `json:"strategy,omitempty"`
  26. Preference BudgetPreference `json:"preference,omitempty"`
  27. Rebalance BudgetRebalance `json:"rebalance,omitempty"`
  28. }
  29. func BudgetModelFromPolicy(policy Policy) BudgetModel {
  30. recordBias, decodeBias := budgetIntentBias(policy.Intent)
  31. refBudget, refSource := refinementBudgetFromPolicy(policy)
  32. preference := BudgetPreferenceFromPolicy(policy)
  33. refEffective := effectiveBudget(refBudget, preference.Refinement)
  34. recordEffective := effectiveBudget(policy.MaxRecordingStreams, preference.Record)
  35. decodeEffective := effectiveBudget(policy.MaxDecodeJobs, preference.Decode)
  36. return BudgetModel{
  37. Refinement: BudgetQueue{
  38. Max: refBudget,
  39. Preference: preference.Refinement,
  40. EffectiveMax: refEffective,
  41. Source: refSource,
  42. },
  43. Record: BudgetQueue{
  44. Max: policy.MaxRecordingStreams,
  45. IntentBias: recordBias,
  46. Preference: preference.Record,
  47. EffectiveMax: recordEffective,
  48. Source: "resources.max_recording_streams",
  49. },
  50. Decode: BudgetQueue{
  51. Max: policy.MaxDecodeJobs,
  52. IntentBias: decodeBias,
  53. Preference: preference.Decode,
  54. EffectiveMax: decodeEffective,
  55. Source: "resources.max_decode_jobs",
  56. },
  57. HoldMs: policy.DecisionHoldMs,
  58. Intent: policy.Intent,
  59. Profile: policy.Profile,
  60. Strategy: policy.RefinementStrategy,
  61. Preference: preference,
  62. }
  63. }
  64. func BudgetModelFromPolicyWithRebalance(policy Policy, pressure BudgetPressureSummary) BudgetModel {
  65. base := BudgetModelFromPolicy(policy)
  66. return ApplyBudgetRebalance(policy, base, pressure)
  67. }
  68. func refinementBudgetFromPolicy(policy Policy) (int, string) {
  69. budget := policy.MaxRefinementJobs
  70. source := "resources.max_refinement_jobs"
  71. if policy.RefinementMaxConcurrent > 0 && (budget <= 0 || policy.RefinementMaxConcurrent < budget) {
  72. budget = policy.RefinementMaxConcurrent
  73. source = "refinement.max_concurrent"
  74. }
  75. return budget, source
  76. }
  77. func budgetIntentBias(intent string) (float64, float64) {
  78. if intent == "" {
  79. return 0, 0
  80. }
  81. recordBias := 0.0
  82. decodeBias := 0.0
  83. intent = strings.ToLower(intent)
  84. if strings.Contains(intent, "archive") || strings.Contains(intent, "record") {
  85. recordBias += 1.5
  86. }
  87. if strings.Contains(intent, "triage") {
  88. recordBias += 0.5
  89. decodeBias += 0.5
  90. }
  91. if strings.Contains(intent, "decode") || strings.Contains(intent, "analysis") {
  92. decodeBias += 1.0
  93. }
  94. if strings.Contains(intent, "digital") {
  95. decodeBias += 0.5
  96. }
  97. return recordBias, decodeBias
  98. }
  99. func BudgetPreferenceFromPolicy(policy Policy) BudgetPreference {
  100. pref := BudgetPreference{Refinement: 1.0, Record: 1.0, Decode: 1.0}
  101. reasons := make([]string, 0, 6)
  102. addReason := func(tag string) {
  103. if tag == "" {
  104. return
  105. }
  106. for _, r := range reasons {
  107. if r == tag {
  108. return
  109. }
  110. }
  111. reasons = append(reasons, tag)
  112. }
  113. profile := strings.ToLower(strings.TrimSpace(policy.Profile))
  114. intent := strings.ToLower(strings.TrimSpace(policy.Intent))
  115. strategy := strings.ToLower(strings.TrimSpace(policy.RefinementStrategy))
  116. if strings.Contains(profile, "archive") {
  117. pref.Record += 0.6
  118. pref.Decode += 0.2
  119. pref.Refinement += 0.15
  120. addReason("profile:archive")
  121. }
  122. if strings.Contains(profile, "digital") {
  123. pref.Decode += 0.6
  124. pref.Record += 0.1
  125. pref.Refinement += 0.15
  126. addReason("profile:digital")
  127. }
  128. if strings.Contains(profile, "aggressive") {
  129. pref.Refinement += 0.35
  130. addReason("profile:aggressive")
  131. }
  132. if strings.Contains(intent, "archive") || strings.Contains(intent, "record") {
  133. pref.Record += 0.5
  134. addReason("intent:record")
  135. }
  136. if strings.Contains(intent, "decode") || strings.Contains(intent, "analysis") || strings.Contains(intent, "classif") {
  137. pref.Decode += 0.5
  138. addReason("intent:decode")
  139. }
  140. if strings.Contains(intent, "digital") || strings.Contains(intent, "hunt") {
  141. pref.Decode += 0.25
  142. addReason("intent:digital")
  143. }
  144. if strings.Contains(intent, "wideband") || strings.Contains(intent, "surveillance") {
  145. pref.Refinement += 0.25
  146. addReason("intent:wideband")
  147. }
  148. if strings.Contains(strategy, "archive") {
  149. pref.Record += 0.2
  150. pref.Refinement += 0.1
  151. addReason("strategy:archive")
  152. }
  153. if strings.Contains(strategy, "digital") {
  154. pref.Decode += 0.2
  155. addReason("strategy:digital")
  156. }
  157. if strings.Contains(strategy, "multi") {
  158. pref.Refinement += 0.2
  159. addReason("strategy:multi-resolution")
  160. }
  161. pref.Refinement = clampPreference(pref.Refinement)
  162. pref.Record = clampPreference(pref.Record)
  163. pref.Decode = clampPreference(pref.Decode)
  164. pref.Reasons = reasons
  165. return pref
  166. }
  167. func clampPreference(value float64) float64 {
  168. if value < 0.35 {
  169. return 0.35
  170. }
  171. return value
  172. }
  173. func effectiveBudget(max int, preference float64) float64 {
  174. if max <= 0 {
  175. return 0
  176. }
  177. if preference <= 0 {
  178. preference = 1.0
  179. }
  180. return float64(max) * preference
  181. }
  182. func budgetQueueLimit(queue BudgetQueue) int {
  183. if queue.RebalanceDelta != 0 {
  184. return queue.RebalancedMax
  185. }
  186. if queue.RebalancedMax != 0 {
  187. return queue.RebalancedMax
  188. }
  189. return queue.Max
  190. }