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 values. 10 * 11 * <p>DoubleChromosome is ideal for continuous optimization problems where solutions can be encoded as 12 * real-valued vectors. This chromosome type provides high precision for numerical optimization tasks 13 * and is commonly used in function optimization, neural network weight evolution, and parameter tuning. 14 * 15 * <p>This chromosome type is particularly suitable for: 16 * <ul> 17 * <li><strong>Continuous optimization</strong>: Function minimization/maximization with real-valued parameters</li> 18 * <li><strong>Neural network evolution</strong>: Evolving connection weights and biases</li> 19 * <li><strong>Engineering optimization</strong>: Design parameters with continuous constraints</li> 20 * <li><strong>Scientific computing</strong>: Model parameter estimation and calibration</li> 21 * <li><strong>Financial modeling</strong>: Portfolio optimization and risk parameter tuning</li> 22 * <li><strong>Machine learning</strong>: Hyperparameter optimization for continuous parameters</li> 23 * </ul> 24 * 25 * <p>Key characteristics: 26 * <ul> 27 * <li><strong>High precision</strong>: 64-bit floating-point representation for accurate computations</li> 28 * <li><strong>Bounded values</strong>: All doubles 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>The chromosome maintains bounds information which is used by genetic operators such as: 35 * <ul> 36 * <li><strong>Arithmetic crossover</strong>: Weighted averaging of parent values</li> 37 * <li><strong>Gaussian mutation</strong>: Adding normally distributed noise</li> 38 * <li><strong>Uniform mutation</strong>: Random replacement within bounds</li> 39 * <li><strong>Creep mutation</strong>: Small incremental changes</li> 40 * </ul> 41 * 42 * <p>Special considerations for floating-point chromosomes: 43 * <ul> 44 * <li><strong>Precision handling</strong>: Be aware of floating-point precision limits</li> 45 * <li><strong>Boundary conditions</strong>: Handle edge cases at min/max values</li> 46 * <li><strong>Convergence</strong>: May require epsilon-based convergence criteria</li> 47 * <li><strong>Scaling</strong>: Consider normalizing parameters for better performance</li> 48 * </ul> 49 * 50 * @see Chromosome 51 * @see net.bmahe.genetics4j.core.spec.chromosome.DoubleChromosomeSpec 52 * @see net.bmahe.genetics4j.core.chromosomes.factory.DoubleChromosomeFactory 53 * @see FloatChromosome 54 */ 55 public class DoubleChromosome implements Chromosome { 56 57 private final int size; 58 private final double minValue; 59 private final double maxValue; 60 private final double[] values; 61 62 /** 63 * Creates a new double chromosome with the specified parameters and values. 64 * 65 * @param _size the number of double values in this chromosome 66 * @param _minValue the minimum allowed value for any double in this chromosome 67 * @param _maxValue the maximum allowed value for any double in this chromosome 68 * @param _values the array of double values for this chromosome 69 * @throws IllegalArgumentException if size is not positive, if minValue > maxValue, 70 * if values array is null, or if the array length 71 * 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 134 * affect this chromosome. 135 * 136 * @return a copy of the double values array 137 */ 138 public double[] getValues() { 139 return values; 140 } 141 142 @Override 143 public int hashCode() { 144 final int prime = 31; 145 int result = 1; 146 result = prime * result + Arrays.hashCode(values); 147 result = prime * result + Objects.hash(maxValue, minValue, size); 148 return result; 149 } 150 151 @Override 152 public boolean equals(Object obj) { 153 if (this == obj) 154 return true; 155 if (obj == null) 156 return false; 157 if (getClass() != obj.getClass()) 158 return false; 159 DoubleChromosome other = (DoubleChromosome) obj; 160 return Double.doubleToLongBits(maxValue) == Double.doubleToLongBits(other.maxValue) 161 && Double.doubleToLongBits(minValue) == Double.doubleToLongBits(other.minValue) && size == other.size 162 && Arrays.equals(values, other.values); 163 } 164 165 @Override 166 public String toString() { 167 return "DoubleChromosome [size=" + size + ", minValue=" + minValue + ", maxValue=" + maxValue + ", values=" 168 + Arrays.toString(values) + "]"; 169 } 170 }