musa-dsl 0.30.2 → 0.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -1
  3. data/.version +6 -0
  4. data/.yardopts +7 -0
  5. data/Gemfile +0 -1
  6. data/README.md +227 -6
  7. data/docs/README.md +83 -0
  8. data/docs/api-reference.md +86 -0
  9. data/docs/getting-started/quick-start.md +93 -0
  10. data/docs/getting-started/tutorial.md +58 -0
  11. data/docs/subsystems/core-extensions.md +316 -0
  12. data/docs/subsystems/datasets.md +465 -0
  13. data/docs/subsystems/generative.md +290 -0
  14. data/docs/subsystems/matrix.md +63 -0
  15. data/docs/subsystems/midi.md +123 -0
  16. data/docs/subsystems/music.md +544 -0
  17. data/docs/subsystems/musicxml-builder.md +264 -0
  18. data/docs/subsystems/neumas.md +71 -0
  19. data/docs/subsystems/repl.md +135 -0
  20. data/docs/subsystems/sequencer.md +98 -0
  21. data/docs/subsystems/series.md +302 -0
  22. data/docs/subsystems/transcription.md +152 -0
  23. data/docs/subsystems/transport.md +177 -0
  24. data/lib/musa-dsl/core-ext/array-explode-ranges.rb +68 -0
  25. data/lib/musa-dsl/core-ext/arrayfy.rb +110 -0
  26. data/lib/musa-dsl/core-ext/attribute-builder.rb +91 -30
  27. data/lib/musa-dsl/core-ext/deep-copy.rb +125 -2
  28. data/lib/musa-dsl/core-ext/dynamic-proxy.rb +78 -0
  29. data/lib/musa-dsl/core-ext/extension.rb +53 -0
  30. data/lib/musa-dsl/core-ext/hashify.rb +162 -1
  31. data/lib/musa-dsl/core-ext/inspect-nice.rb +154 -0
  32. data/lib/musa-dsl/core-ext/smart-proc-binder.rb +117 -0
  33. data/lib/musa-dsl/core-ext/with.rb +114 -0
  34. data/lib/musa-dsl/datasets/dataset.rb +109 -0
  35. data/lib/musa-dsl/datasets/delta-d.rb +78 -0
  36. data/lib/musa-dsl/datasets/e.rb +186 -2
  37. data/lib/musa-dsl/datasets/gdv.rb +279 -2
  38. data/lib/musa-dsl/datasets/gdvd.rb +201 -0
  39. data/lib/musa-dsl/datasets/helper.rb +75 -0
  40. data/lib/musa-dsl/datasets/p.rb +177 -2
  41. data/lib/musa-dsl/datasets/packed-v.rb +91 -0
  42. data/lib/musa-dsl/datasets/pdv.rb +136 -1
  43. data/lib/musa-dsl/datasets/ps.rb +134 -4
  44. data/lib/musa-dsl/datasets/score/queriable.rb +143 -1
  45. data/lib/musa-dsl/datasets/score/render.rb +105 -1
  46. data/lib/musa-dsl/datasets/score/to-mxml/process-pdv.rb +138 -1
  47. data/lib/musa-dsl/datasets/score/to-mxml/process-ps.rb +111 -0
  48. data/lib/musa-dsl/datasets/score/to-mxml/process-time.rb +200 -1
  49. data/lib/musa-dsl/datasets/score/to-mxml/to-mxml.rb +145 -1
  50. data/lib/musa-dsl/datasets/score.rb +279 -0
  51. data/lib/musa-dsl/datasets/v.rb +88 -0
  52. data/lib/musa-dsl/generative/darwin.rb +215 -1
  53. data/lib/musa-dsl/generative/generative-grammar.rb +387 -0
  54. data/lib/musa-dsl/generative/markov.rb +135 -3
  55. data/lib/musa-dsl/generative/rules.rb +312 -4
  56. data/lib/musa-dsl/generative/variatio.rb +286 -2
  57. data/lib/musa-dsl/logger/logger.rb +267 -2
  58. data/lib/musa-dsl/matrix/matrix.rb +256 -10
  59. data/lib/musa-dsl/midi/midi-recorder.rb +113 -2
  60. data/lib/musa-dsl/midi/midi-voices.rb +275 -4
  61. data/lib/musa-dsl/music/chord-definition.rb +233 -1
  62. data/lib/musa-dsl/music/chord-definitions.rb +33 -6
  63. data/lib/musa-dsl/music/chords.rb +353 -2
  64. data/lib/musa-dsl/music/equally-tempered-12-tone-scale-system.rb +70 -206
  65. data/lib/musa-dsl/music/scale_kinds/bebop/bebop_dominant_scale_kind.rb +110 -0
  66. data/lib/musa-dsl/music/scale_kinds/bebop/bebop_major_scale_kind.rb +110 -0
  67. data/lib/musa-dsl/music/scale_kinds/bebop/bebop_minor_scale_kind.rb +110 -0
  68. data/lib/musa-dsl/music/scale_kinds/blues/blues_major_scale_kind.rb +100 -0
  69. data/lib/musa-dsl/music/scale_kinds/blues/blues_scale_kind.rb +99 -0
  70. data/lib/musa-dsl/music/scale_kinds/chromatic_scale_kind.rb +79 -0
  71. data/lib/musa-dsl/music/scale_kinds/ethnic/double_harmonic_scale_kind.rb +102 -0
  72. data/lib/musa-dsl/music/scale_kinds/ethnic/hungarian_minor_scale_kind.rb +102 -0
  73. data/lib/musa-dsl/music/scale_kinds/ethnic/neapolitan_major_scale_kind.rb +102 -0
  74. data/lib/musa-dsl/music/scale_kinds/ethnic/neapolitan_minor_scale_kind.rb +101 -0
  75. data/lib/musa-dsl/music/scale_kinds/ethnic/phrygian_dominant_scale_kind.rb +103 -0
  76. data/lib/musa-dsl/music/scale_kinds/harmonic_major/harmonic_major_scale_kind.rb +104 -0
  77. data/lib/musa-dsl/music/scale_kinds/major_scale_kind.rb +110 -0
  78. data/lib/musa-dsl/music/scale_kinds/melodic_minor/altered_scale_kind.rb +106 -0
  79. data/lib/musa-dsl/music/scale_kinds/melodic_minor/dorian_b2_scale_kind.rb +104 -0
  80. data/lib/musa-dsl/music/scale_kinds/melodic_minor/locrian_sharp2_scale_kind.rb +103 -0
  81. data/lib/musa-dsl/music/scale_kinds/melodic_minor/lydian_augmented_scale_kind.rb +103 -0
  82. data/lib/musa-dsl/music/scale_kinds/melodic_minor/lydian_dominant_scale_kind.rb +106 -0
  83. data/lib/musa-dsl/music/scale_kinds/melodic_minor/melodic_minor_scale_kind.rb +104 -0
  84. data/lib/musa-dsl/music/scale_kinds/melodic_minor/mixolydian_b6_scale_kind.rb +103 -0
  85. data/lib/musa-dsl/music/scale_kinds/minor_harmonic_scale_kind.rb +125 -0
  86. data/lib/musa-dsl/music/scale_kinds/minor_natural_scale_kind.rb +123 -0
  87. data/lib/musa-dsl/music/scale_kinds/modes/dorian_scale_kind.rb +111 -0
  88. data/lib/musa-dsl/music/scale_kinds/modes/locrian_scale_kind.rb +114 -0
  89. data/lib/musa-dsl/music/scale_kinds/modes/lydian_scale_kind.rb +111 -0
  90. data/lib/musa-dsl/music/scale_kinds/modes/mixolydian_scale_kind.rb +111 -0
  91. data/lib/musa-dsl/music/scale_kinds/modes/phrygian_scale_kind.rb +111 -0
  92. data/lib/musa-dsl/music/scale_kinds/pentatonic/pentatonic_major_scale_kind.rb +93 -0
  93. data/lib/musa-dsl/music/scale_kinds/pentatonic/pentatonic_minor_scale_kind.rb +99 -0
  94. data/lib/musa-dsl/music/scale_kinds/symmetric/diminished_hw_scale_kind.rb +110 -0
  95. data/lib/musa-dsl/music/scale_kinds/symmetric/diminished_wh_scale_kind.rb +110 -0
  96. data/lib/musa-dsl/music/scale_kinds/symmetric/whole_tone_scale_kind.rb +99 -0
  97. data/lib/musa-dsl/music/scale_systems/equally_tempered_12_tone_scale_system.rb +80 -0
  98. data/lib/musa-dsl/music/scale_systems/twelve_semitones_scale_system.rb +60 -0
  99. data/lib/musa-dsl/music/scales.rb +1384 -40
  100. data/lib/musa-dsl/musicxml/builder/attributes.rb +483 -3
  101. data/lib/musa-dsl/musicxml/builder/backup-forward.rb +166 -1
  102. data/lib/musa-dsl/musicxml/builder/direction.rb +243 -0
  103. data/lib/musa-dsl/musicxml/builder/helper.rb +240 -0
  104. data/lib/musa-dsl/musicxml/builder/measure.rb +284 -0
  105. data/lib/musa-dsl/musicxml/builder/note-complexities.rb +324 -8
  106. data/lib/musa-dsl/musicxml/builder/note.rb +285 -0
  107. data/lib/musa-dsl/musicxml/builder/part-group.rb +108 -1
  108. data/lib/musa-dsl/musicxml/builder/part.rb +139 -0
  109. data/lib/musa-dsl/musicxml/builder/pitched-note.rb +124 -0
  110. data/lib/musa-dsl/musicxml/builder/rest.rb +93 -0
  111. data/lib/musa-dsl/musicxml/builder/score-partwise.rb +276 -0
  112. data/lib/musa-dsl/musicxml/builder/typed-text.rb +62 -1
  113. data/lib/musa-dsl/musicxml/builder/unpitched-note.rb +83 -0
  114. data/lib/musa-dsl/neumalang/neumalang.rb +675 -0
  115. data/lib/musa-dsl/neumas/array-to-neumas.rb +149 -0
  116. data/lib/musa-dsl/neumas/neuma-decoder.rb +253 -0
  117. data/lib/musa-dsl/neumas/neuma-gdv-decoder.rb +142 -2
  118. data/lib/musa-dsl/neumas/neuma-gdvd-decoder.rb +82 -0
  119. data/lib/musa-dsl/neumas/neumas.rb +67 -0
  120. data/lib/musa-dsl/neumas/string-to-neumas.rb +233 -1
  121. data/lib/musa-dsl/repl/repl.rb +550 -0
  122. data/lib/musa-dsl/sequencer/base-sequencer-implementation-every.rb +118 -2
  123. data/lib/musa-dsl/sequencer/base-sequencer-implementation-move.rb +149 -2
  124. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-helper.rb +296 -0
  125. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play-timed.rb +88 -2
  126. data/lib/musa-dsl/sequencer/base-sequencer-implementation-play.rb +161 -0
  127. data/lib/musa-dsl/sequencer/base-sequencer-implementation.rb +263 -0
  128. data/lib/musa-dsl/sequencer/base-sequencer-tick-based.rb +173 -1
  129. data/lib/musa-dsl/sequencer/base-sequencer-tickless-based.rb +177 -0
  130. data/lib/musa-dsl/sequencer/base-sequencer.rb +710 -10
  131. data/lib/musa-dsl/sequencer/sequencer-dsl.rb +210 -0
  132. data/lib/musa-dsl/sequencer/timeslots.rb +79 -0
  133. data/lib/musa-dsl/series/array-to-serie.rb +37 -1
  134. data/lib/musa-dsl/series/base-series.rb +843 -5
  135. data/lib/musa-dsl/series/buffer-serie.rb +54 -0
  136. data/lib/musa-dsl/series/hash-or-array-serie-splitter.rb +64 -0
  137. data/lib/musa-dsl/series/main-serie-constructors.rb +398 -2
  138. data/lib/musa-dsl/series/main-serie-operations.rb +538 -16
  139. data/lib/musa-dsl/series/proxy-serie.rb +67 -0
  140. data/lib/musa-dsl/series/quantizer-serie.rb +57 -7
  141. data/lib/musa-dsl/series/queue-serie.rb +78 -0
  142. data/lib/musa-dsl/series/series-composer.rb +701 -0
  143. data/lib/musa-dsl/series/timed-serie.rb +473 -28
  144. data/lib/musa-dsl/transcription/from-gdv-to-midi.rb +404 -1
  145. data/lib/musa-dsl/transcription/from-gdv-to-musicxml.rb +118 -0
  146. data/lib/musa-dsl/transcription/from-gdv.rb +84 -1
  147. data/lib/musa-dsl/transcription/transcription.rb +265 -0
  148. data/lib/musa-dsl/transport/clock.rb +125 -0
  149. data/lib/musa-dsl/transport/dummy-clock.rb +89 -2
  150. data/lib/musa-dsl/transport/external-tick-clock.rb +91 -0
  151. data/lib/musa-dsl/transport/input-midi-clock.rb +133 -1
  152. data/lib/musa-dsl/transport/timer-clock.rb +183 -1
  153. data/lib/musa-dsl/transport/timer.rb +83 -0
  154. data/lib/musa-dsl/transport/transport.rb +318 -0
  155. data/lib/musa-dsl/version.rb +2 -1
  156. data/lib/musa-dsl.rb +132 -25
  157. data/musa-dsl.gemspec +25 -18
  158. metadata +158 -16
@@ -1,8 +1,111 @@
1
1
  require_relative '../core-ext/with'
2
2
 
3
3
  module Musa
4
+ # Evolutionary selection algorithm based on fitness evaluation.
5
+ #
6
+ # Darwin implements a selection algorithm inspired by natural selection,
7
+ # evaluating and ranking a population of objects based on defined measures
8
+ # (features and dimensions) and weights. Objects are measured, scored, and
9
+ # sorted by fitness for evolutionary algorithms or optimization.
10
+ #
11
+ # ## Core Concepts
12
+ #
13
+ # - **Population**: Collection of objects to evaluate
14
+ # - **Measures**: Evaluation criteria for each object
15
+ # - **Features**: Boolean flags (present/absent)
16
+ # - **Dimensions**: Numeric values (continuous)
17
+ # - **Die**: Mark object as non-viable (eliminated)
18
+ # - **Weights**: Importance multipliers for features/dimensions
19
+ # - **Fitness**: Calculated score from normalized dimensions and features
20
+ # - **Selection**: Population sorted by fitness (highest first)
21
+ #
22
+ # ## Evaluation Process
23
+ #
24
+ # 1. **Measure**: Evaluate each object with measures block
25
+ # 2. **Normalize**: Scale dimension values to 0-1 range
26
+ # 3. **Weight**: Apply weights to dimensions and features
27
+ # 4. **Score**: Calculate total fitness for each object
28
+ # 5. **Sort**: Order population by fitness (descending)
29
+ #
30
+ # ## Musical Applications
31
+ #
32
+ # - Select best harmonic progressions from generated candidates
33
+ # - Rank melodic variations by aesthetic criteria
34
+ # - Optimize rhythmic patterns for complexity/simplicity
35
+ # - Evolve musical structures through iterative selection
36
+ #
37
+ # @example Basic selection with features and dimensions
38
+ # darwin = Musa::Darwin::Darwin.new do
39
+ # measures do |object|
40
+ # # Kill objects with unwanted property
41
+ # die if object[:bad_property]
42
+ #
43
+ # # Binary features
44
+ # feature :has_alpha if object[:type] == :alpha
45
+ # feature :has_beta if object[:type] == :beta
46
+ #
47
+ # # Numeric dimension (negative to prefer lower values)
48
+ # dimension :complexity, -object[:complexity].to_f
49
+ # end
50
+ #
51
+ # # Weight contributions to fitness
52
+ # weight complexity: 2.0, has_alpha: 1.0, has_beta: -0.5
53
+ # end
54
+ #
55
+ # population = generate_candidates()
56
+ # selected = darwin.select(population)
57
+ # # Returns population sorted by fitness (best first)
58
+ #
59
+ # @example Musical chord progression selection
60
+ # darwin = Musa::Darwin::Darwin.new do
61
+ # measures do |progression|
62
+ # # Eliminate progressions with parallel fifths
63
+ # die if has_parallel_fifths?(progression)
64
+ #
65
+ # # Prefer smooth voice leading
66
+ # dimension :voice_leading, -total_voice_leading_distance(progression)
67
+ #
68
+ # # Prefer certain cadences
69
+ # feature :authentic_cadence if ends_with_V_I?(progression)
70
+ # feature :plagal_cadence if ends_with_IV_I?(progression)
71
+ #
72
+ # # Penalize excessive chromaticism
73
+ # dimension :chromaticism, -count_chromatic_notes(progression)
74
+ # end
75
+ #
76
+ # weight voice_leading: 3.0,
77
+ # authentic_cadence: 2.0,
78
+ # plagal_cadence: 1.0,
79
+ # chromaticism: 1.5
80
+ # end
81
+ #
82
+ # candidates = generate_progressions()
83
+ # best = darwin.select(candidates).first(10) # Top 10 progressions
84
+ #
85
+ # @see Darwin Main evolutionary selector class
86
+ # @see Musa::Extension::With DSL context management for evaluation blocks
87
+ # @see https://en.wikipedia.org/wiki/Evolutionary_algorithm Evolutionary algorithm (Wikipedia)
88
+ # @see https://en.wikipedia.org/wiki/Fitness_function Fitness function (Wikipedia)
4
89
  module Darwin
90
+ # Evolutionary selector for population-based optimization.
91
+ #
92
+ # Evaluates population using measures and weights, returning sorted
93
+ # population by fitness score.
5
94
  class Darwin
95
+ # Creates Darwin selector with evaluation rules.
96
+ #
97
+ # @yield evaluation DSL block
98
+ # @yieldreturn [void]
99
+ #
100
+ # @raise [ArgumentError] if no block given
101
+ #
102
+ # @example
103
+ # darwin = Darwin.new do
104
+ # measures { |obj| dimension :value, obj[:score] }
105
+ # weight value: 1.0
106
+ # end
107
+ #
108
+ # @return [void]
6
109
  def initialize(&block)
7
110
  raise ArgumentError, 'block is needed' unless block
8
111
 
@@ -12,6 +115,22 @@ module Musa
12
115
  @weights = main_context._weights
13
116
  end
14
117
 
118
+ # Selects and ranks population by fitness.
119
+ #
120
+ # Evaluates each object with measures, normalizes dimensions across
121
+ # population, applies weights, and returns population sorted by fitness
122
+ # (highest first). Objects marked as died are excluded.
123
+ #
124
+ # @param population [Array] objects to evaluate
125
+ #
126
+ # @return [Array] population sorted by fitness (descending)
127
+ #
128
+ # @example
129
+ # candidates = [obj1, obj2, obj3, ...]
130
+ # ranked = darwin.select(candidates)
131
+ # best = ranked.first # Highest fitness
132
+ # worst = ranked.last # Lowest fitness
133
+ # top10 = ranked.first(10) # Top 10
15
134
  def select(population)
16
135
  measured_objects = []
17
136
 
@@ -46,7 +165,8 @@ module Musa
46
165
 
47
166
  measure.dimensions.each do |dimension_name, value|
48
167
  limit = limits[dimension_name]
49
- measure.normalized_dimensions[dimension_name] = (value - limit[:min]) / limit[:range]
168
+ measure.normalized_dimensions[dimension_name] =
169
+ limit[:range].zero? ? 0.5 : (value - limit[:min]) / limit[:range]
50
170
  end
51
171
 
52
172
  # warn "Darwin.select: #{measured_object[:object]} #{measured_object[:measure]} weight=#{measured_object[:measure].evaluate_weight(@weights).round(2)}"
@@ -57,24 +177,53 @@ module Musa
57
177
  measured_objects.collect { |measured_object| measured_object[:object] }
58
178
  end
59
179
 
180
+ # Compares two measures by their weighted fitness.
181
+ #
182
+ # @param measure_a [Measure] first measure to compare
183
+ # @param measure_b [Measure] second measure to compare
184
+ #
185
+ # @return [Integer] comparison result (-1, 0, 1)
186
+ #
187
+ # @api private
60
188
  def evaluate_weights(measure_a, measure_b)
61
189
  measure_b.evaluate_weight(@weights) <=> measure_a.evaluate_weight(@weights)
62
190
  end
63
191
 
192
+ # DSL context for Darwin configuration.
193
+ #
194
+ # @api private
64
195
  class MainContext
65
196
  include Musa::Extension::With
66
197
 
198
+ # @return [Proc] measures evaluation block
199
+ # @return [Hash] weight assignments
67
200
  attr_reader :_measures, :_weights
68
201
 
202
+ # @return [void]
203
+ # @api private
69
204
  def initialize(&block)
70
205
  @_weights = {}
71
206
  with &block
72
207
  end
73
208
 
209
+ # Defines measures evaluation block.
210
+ #
211
+ # @yield [object] measures DSL block
212
+ #
213
+ # @return [Proc] the measures block
214
+ #
215
+ # @api private
74
216
  def measures(&block)
75
217
  @_measures = block
76
218
  end
77
219
 
220
+ # Assigns weights to features/dimensions.
221
+ #
222
+ # @param feature_or_dimension_weights [Hash{Symbol => Numeric}] name => weight pairs
223
+ #
224
+ # @return [void]
225
+ #
226
+ # @api private
78
227
  def weight(**feature_or_dimension_weights)
79
228
  feature_or_dimension_weights.each do |name, value|
80
229
  @_weights[name] = value
@@ -82,39 +231,88 @@ module Musa
82
231
  end
83
232
  end
84
233
 
234
+ # DSL context for object measurement.
235
+ #
236
+ # @api private
85
237
  class MeasuresEvalContext
86
238
  include Musa::Extension::With
87
239
 
240
+ # @return [void]
241
+ # @api private
88
242
  def initialize
89
243
  @_features = {}
90
244
  @_dimensions = {}
91
245
  @_died = false
92
246
  end
93
247
 
248
+ # Returns measure result.
249
+ #
250
+ # @return [Measure] measurement
251
+ # @api private
94
252
  def _measure
95
253
  Measure.new @_features, @_dimensions, @_died
96
254
  end
97
255
 
256
+ # Marks object as having a feature.
257
+ #
258
+ # @param feature_name [Symbol] feature identifier
259
+ #
260
+ # @return [void]
261
+ #
262
+ # @api private
98
263
  def feature(feature_name)
99
264
  @_features[feature_name] = true
100
265
  end
101
266
 
267
+ # Records dimensional measurement.
268
+ #
269
+ # @param dimension_name [Symbol] dimension identifier
270
+ # @param value [Numeric] measured value
271
+ #
272
+ # @return [void]
273
+ #
274
+ # @api private
102
275
  def dimension(dimension_name, value)
103
276
  @_dimensions[dimension_name] = value
104
277
  end
105
278
 
279
+ # Marks object as non-viable (to be excluded).
280
+ #
281
+ # @return [void]
282
+ #
283
+ # @api private
106
284
  def die
107
285
  @_died = true
108
286
  end
109
287
 
288
+ # Checks if object marked as died.
289
+ #
290
+ # @return [Boolean]
291
+ # @api private
110
292
  def died?
111
293
  @_died
112
294
  end
113
295
  end
114
296
 
297
+ # Measurement result for an object.
298
+ #
299
+ # Contains features, dimensions, and viability status.
300
+ #
301
+ # @attr_reader features [Hash{Symbol => Boolean}] feature flags
302
+ # @attr_reader dimensions [Hash{Symbol => Numeric}] raw dimension values
303
+ # @attr_reader normalized_dimensions [Hash{Symbol => Float}] normalized (0-1) dimensions
304
+ #
305
+ # @api private
115
306
  class Measure
116
307
  attr_reader :features, :dimensions, :normalized_dimensions
117
308
 
309
+ # @param features [Hash{Symbol => Boolean}] feature flags
310
+ # @param dimensions [Hash{Symbol => Numeric}] dimension values
311
+ # @param died [Boolean] viability status
312
+ #
313
+ # @return [void]
314
+ #
315
+ # @api private
118
316
  def initialize(features, dimensions, died)
119
317
  @features = features
120
318
  @dimensions = dimensions
@@ -123,10 +321,23 @@ module Musa
123
321
  @normalized_dimensions = {}
124
322
  end
125
323
 
324
+ # Checks if object is non-viable.
325
+ #
326
+ # @return [Boolean]
327
+ # @api private
126
328
  def died?
127
329
  @died
128
330
  end
129
331
 
332
+ # Calculates weighted fitness score.
333
+ #
334
+ # Sums weighted normalized dimensions and features.
335
+ #
336
+ # @param weights [Hash{Symbol => Numeric}] weight assignments
337
+ #
338
+ # @return [Float] total fitness score
339
+ #
340
+ # @api private
130
341
  def evaluate_weight(weights)
131
342
  total = 0.0
132
343
 
@@ -140,6 +351,9 @@ module Musa
140
351
  total
141
352
  end
142
353
 
354
+ # Returns string representation of measure.
355
+ #
356
+ # @return [String] formatted measure description
143
357
  def inspect
144
358
  "Measure features=#{@features.collect { |k, _v| k }} dimensions=#{@normalized_dimensions.collect { |k, v| [k, [@dimensions[k].round(5), v.round(2)]] }.to_h}"
145
359
  end