1 package net.bmahe.genetics4j.core.chromosomes;
2
3 import java.util.Arrays;
4 import java.util.Objects;
5
6 import org.apache.commons.lang3.Validate;
7
8 /**
9 * A chromosome implementation that represents genetic information as an array of single-precision floating-point
10 * values.
11 *
12 * <p>FloatChromosome provides a memory-efficient alternative to DoubleChromosome for continuous optimization problems
13 * where single precision (32-bit) is sufficient. This chromosome type offers good performance for real-valued
14 * optimization while using approximately half the memory of double-precision alternatives.
15 *
16 * <p>This chromosome type is particularly suitable for:
17 * <ul>
18 * <li><strong>Large-scale optimization</strong>: Problems with thousands of parameters where memory efficiency
19 * matters</li>
20 * <li><strong>Neural network evolution</strong>: Evolving weights when single precision is adequate</li>
21 * <li><strong>Graphics and gaming</strong>: Position, rotation, and scaling parameters</li>
22 * <li><strong>Signal processing</strong>: Audio and image processing parameter optimization</li>
23 * <li><strong>Embedded systems</strong>: Resource-constrained environments with limited memory</li>
24 * <li><strong>Real-time applications</strong>: Where performance is more critical than precision</li>
25 * </ul>
26 *
27 * <p>Key characteristics:
28 * <ul>
29 * <li><strong>Memory efficient</strong>: 32-bit floating-point representation reduces memory usage</li>
30 * <li><strong>Bounded values</strong>: All floats are constrained to [minValue, maxValue]</li>
31 * <li><strong>Fixed length</strong>: Chromosome size is determined at creation time</li>
32 * <li><strong>Immutable</strong>: Values cannot be changed after construction</li>
33 * <li><strong>IEEE 754 compliant</strong>: Standard floating-point arithmetic and comparisons</li>
34 * </ul>
35 *
36 * <p>Performance considerations:
37 * <ul>
38 * <li><strong>Memory usage</strong>: Approximately 50% less memory than DoubleChromosome</li>
39 * <li><strong>Cache efficiency</strong>: Better cache utilization due to smaller data size</li>
40 * <li><strong>Precision trade-off</strong>: ~7 decimal digits vs ~15 for double precision</li>
41 * <li><strong>Range limitations</strong>: Smaller representable range than double precision</li>
42 * </ul>
43 *
44 * <p>The chromosome maintains bounds information which is used by genetic operators such as:
45 * <ul>
46 * <li><strong>Arithmetic crossover</strong>: Weighted averaging of parent values</li>
47 * <li><strong>Gaussian mutation</strong>: Adding normally distributed noise</li>
48 * <li><strong>Uniform mutation</strong>: Random replacement within bounds</li>
49 * <li><strong>Creep mutation</strong>: Small incremental changes</li>
50 * </ul>
51 *
52 * <p>When to choose FloatChromosome vs DoubleChromosome:
53 * <ul>
54 * <li><strong>Use FloatChromosome</strong>: Large populations, memory constraints, adequate precision</li>
55 * <li><strong>Use DoubleChromosome</strong>: High precision requirements, scientific computing</li>
56 * </ul>
57 *
58 * @see Chromosome
59 * @see net.bmahe.genetics4j.core.spec.chromosome.FloatChromosomeSpec
60 * @see net.bmahe.genetics4j.core.chromosomes.factory.FloatChromosomeFactory
61 * @see DoubleChromosome
62 */
63 public class FloatChromosome implements Chromosome {
64
65 private final int size;
66 private final float minValue;
67 private final float maxValue;
68 private final float[] values;
69
70 /**
71 * Creates a new float chromosome with the specified parameters and values.
72 *
73 * @param _size the number of float values in this chromosome
74 * @param _minValue the minimum allowed value for any float in this chromosome
75 * @param _maxValue the maximum allowed value for any float in this chromosome
76 * @param _values the array of float values for this chromosome
77 * @throws IllegalArgumentException if size is not positive, if minValue > maxValue, if values array is null, or if
78 * the array length doesn't match the specified size
79 */
80 public FloatChromosome(final int _size, final float _minValue, final float _maxValue, final float[] _values) {
81 Validate.isTrue(_size > 0);
82 Validate.isTrue(_minValue <= _maxValue);
83 Validate.notNull(_values);
84 Validate.isTrue(_size == _values.length, "Provided size does not match the size of the content");
85
86 this.size = _size;
87 this.minValue = _minValue;
88 this.maxValue = _maxValue;
89 this.values = Arrays.copyOf(_values, _size);
90 }
91
92 @Override
93 public int getNumAlleles() {
94 return size;
95 }
96
97 /**
98 * Returns the float value at the specified index.
99 *
100 * @param index the index of the allele to retrieve (0-based)
101 * @return the float value at the specified position
102 * @throws IllegalArgumentException if index is negative or greater than or equal to the chromosome size
103 */
104 public float getAllele(final int index) {
105 Validate.inclusiveBetween(0, size - 1, index);
106
107 return values[index];
108 }
109
110 /**
111 * Returns the number of float values in this chromosome.
112 *
113 * @return the chromosome size
114 */
115 public int getSize() {
116 return size;
117 }
118
119 /**
120 * Returns the minimum allowed value for floats in this chromosome.
121 *
122 * @return the minimum value constraint
123 */
124 public float getMinValue() {
125 return minValue;
126 }
127
128 /**
129 * Returns the maximum allowed value for floats in this chromosome.
130 *
131 * @return the maximum value constraint
132 */
133 public float getMaxValue() {
134 return maxValue;
135 }
136
137 /**
138 * Returns a copy of the float values in this chromosome.
139 *
140 * <p>The returned array is a defensive copy; modifications to it will not affect this chromosome.
141 *
142 * @return a copy of the float values array
143 */
144 public float[] getValues() {
145 return values;
146 }
147
148 @Override
149 public int hashCode() {
150 final int prime = 31;
151 int result = 1;
152 result = prime * result + Arrays.hashCode(values);
153 result = prime * result + Objects.hash(maxValue, minValue, size);
154 return result;
155 }
156
157 @Override
158 public boolean equals(Object obj) {
159 if (this == obj)
160 return true;
161 if (obj == null)
162 return false;
163 if (getClass() != obj.getClass())
164 return false;
165 FloatChromosome other = (FloatChromosome) obj;
166 return Float.floatToIntBits(maxValue) == Float.floatToIntBits(other.maxValue)
167 && Float.floatToIntBits(minValue) == Float.floatToIntBits(other.minValue) && size == other.size
168 && Arrays.equals(values, other.values);
169 }
170
171 @Override
172 public String toString() {
173 return "FloatChromosome [size=" + size + ", minValue=" + minValue + ", maxValue=" + maxValue + ", values="
174 + Arrays.toString(values) + "]";
175 }
176 }