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