View Javadoc
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 }