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 double-precision floating-point 10 * values. 11 * 12 * <p>DoubleChromosome is ideal for continuous optimization problems where solutions can be encoded as real-valued 13 * vectors. This chromosome type provides high precision for numerical optimization tasks and is commonly used in 14 * function optimization, neural network weight evolution, and parameter tuning. 15 * 16 * <p>This chromosome type is particularly suitable for: 17 * <ul> 18 * <li><strong>Continuous optimization</strong>: Function minimization/maximization with real-valued parameters</li> 19 * <li><strong>Neural network evolution</strong>: Evolving connection weights and biases</li> 20 * <li><strong>Engineering optimization</strong>: Design parameters with continuous constraints</li> 21 * <li><strong>Scientific computing</strong>: Model parameter estimation and calibration</li> 22 * <li><strong>Financial modeling</strong>: Portfolio optimization and risk parameter tuning</li> 23 * <li><strong>Machine learning</strong>: Hyperparameter optimization for continuous parameters</li> 24 * </ul> 25 * 26 * <p>Key characteristics: 27 * <ul> 28 * <li><strong>High precision</strong>: 64-bit floating-point representation for accurate computations</li> 29 * <li><strong>Bounded values</strong>: All doubles are constrained to [minValue, maxValue]</li> 30 * <li><strong>Fixed length</strong>: Chromosome size is determined at creation time</li> 31 * <li><strong>Immutable</strong>: Values cannot be changed after construction</li> 32 * <li><strong>IEEE 754 compliant</strong>: Standard floating-point arithmetic and comparisons</li> 33 * </ul> 34 * 35 * <p>The chromosome maintains bounds information which is used by genetic operators such as: 36 * <ul> 37 * <li><strong>Arithmetic crossover</strong>: Weighted averaging of parent values</li> 38 * <li><strong>Gaussian mutation</strong>: Adding normally distributed noise</li> 39 * <li><strong>Uniform mutation</strong>: Random replacement within bounds</li> 40 * <li><strong>Creep mutation</strong>: Small incremental changes</li> 41 * </ul> 42 * 43 * <p>Special considerations for floating-point chromosomes: 44 * <ul> 45 * <li><strong>Precision handling</strong>: Be aware of floating-point precision limits</li> 46 * <li><strong>Boundary conditions</strong>: Handle edge cases at min/max values</li> 47 * <li><strong>Convergence</strong>: May require epsilon-based convergence criteria</li> 48 * <li><strong>Scaling</strong>: Consider normalizing parameters for better performance</li> 49 * </ul> 50 * 51 * @see Chromosome 52 * @see net.bmahe.genetics4j.core.spec.chromosome.DoubleChromosomeSpec 53 * @see net.bmahe.genetics4j.core.chromosomes.factory.DoubleChromosomeFactory 54 * @see FloatChromosome 55 */ 56 public class DoubleChromosome implements Chromosome { 57 58 private final int size; 59 private final double minValue; 60 private final double maxValue; 61 private final double[] values; 62 63 /** 64 * Creates a new double chromosome with the specified parameters and values. 65 * 66 * @param _size the number of double values in this chromosome 67 * @param _minValue the minimum allowed value for any double in this chromosome 68 * @param _maxValue the maximum allowed value for any double in this chromosome 69 * @param _values the array of double values for this chromosome 70 * @throws IllegalArgumentException if size is not positive, if minValue > maxValue, if values array is null, or if 71 * the array length doesn't match the specified size 72 */ 73 public DoubleChromosome(final int _size, final double _minValue, final double _maxValue, final double[] _values) { 74 Validate.isTrue(_size > 0); 75 Validate.isTrue(_minValue <= _maxValue); 76 Validate.notNull(_values); 77 Validate.isTrue(_size == _values.length, "Provided size does not match the size of the content"); 78 79 this.size = _size; 80 this.minValue = _minValue; 81 this.maxValue = _maxValue; 82 this.values = Arrays.copyOf(_values, _size); 83 } 84 85 @Override 86 public int getNumAlleles() { 87 return size; 88 } 89 90 /** 91 * Returns the double value at the specified index. 92 * 93 * @param index the index of the allele to retrieve (0-based) 94 * @return the double value at the specified position 95 * @throws IllegalArgumentException if index is negative or greater than or equal to the chromosome size 96 */ 97 public double getAllele(final int index) { 98 Validate.inclusiveBetween(0, size - 1, index); 99 100 return values[index]; 101 } 102 103 /** 104 * Returns the number of double values in this chromosome. 105 * 106 * @return the chromosome size 107 */ 108 public int getSize() { 109 return size; 110 } 111 112 /** 113 * Returns the minimum allowed value for doubles in this chromosome. 114 * 115 * @return the minimum value constraint 116 */ 117 public double getMinValue() { 118 return minValue; 119 } 120 121 /** 122 * Returns the maximum allowed value for doubles in this chromosome. 123 * 124 * @return the maximum value constraint 125 */ 126 public double getMaxValue() { 127 return maxValue; 128 } 129 130 /** 131 * Returns a copy of the double values in this chromosome. 132 * 133 * <p>The returned array is a defensive copy; modifications to it will not affect this chromosome. 134 * 135 * @return a copy of the double values array 136 */ 137 public double[] getValues() { 138 return values; 139 } 140 141 @Override 142 public int hashCode() { 143 final int prime = 31; 144 int result = 1; 145 result = prime * result + Arrays.hashCode(values); 146 result = prime * result + Objects.hash(maxValue, minValue, size); 147 return result; 148 } 149 150 @Override 151 public boolean equals(Object obj) { 152 if (this == obj) 153 return true; 154 if (obj == null) 155 return false; 156 if (getClass() != obj.getClass()) 157 return false; 158 DoubleChromosome other = (DoubleChromosome) obj; 159 return Double.doubleToLongBits(maxValue) == Double.doubleToLongBits(other.maxValue) 160 && Double.doubleToLongBits(minValue) == Double.doubleToLongBits(other.minValue) && size == other.size 161 && Arrays.equals(values, other.values); 162 } 163 164 @Override 165 public String toString() { 166 return "DoubleChromosome [size=" + size + ", minValue=" + minValue + ", maxValue=" + maxValue + ", values=" 167 + Arrays.toString(values) + "]"; 168 } 169 }