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 }