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