001    /*
002     * Copyright 2011 Christian Kumpe http://kumpe.de/christian/java
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package de.kumpe.hadooptimizer;
017    
018    import java.io.Serializable;
019    
020    /**
021     * A special type of an immutable individual for evolution strategies.
022     * <p>
023     * The actual individual is a vector of real numbers (<code>double[]</code>). It
024     * is combined with an increment (the standard deviation during the mutation of
025     * the vector), which is mutated by itself.
026     * <p>
027     * <i>Note: a instance is considered immutable, so you <b>should not modify</b>
028     * the contained individual. See {@link #getIndividual()} for additional
029     * hints.</i>
030     * 
031     * @author <a href="http://kumpe.de/christian/java">Christian Kumpe</a>
032     */
033    public final class EsIndividual implements Serializable {
034            private static final long serialVersionUID = 1L;
035    
036            private final double[] individual;
037            private final double increment;
038    
039            /**
040             * Creates a new {@link EsIndividual} with the given single
041             * {@code individual}, which is converted to one-dimensional vector, and an
042             * increment of 1.
043             */
044            public EsIndividual(final double individual) {
045                    this(new double[] { individual });
046            }
047    
048            /**
049             * Creates a new {@link EsIndividual} with the given {@code individual} and
050             * an increment of 1.
051             * 
052             * @throws NullPointerException
053             *             if {@code individual} is <code>null</code>
054             * @throws IllegalArgumentException
055             *             if {@code individual} is an empty array
056             */
057            public EsIndividual(final double[] individual) {
058                    this(individual, 1d);
059            }
060    
061            /**
062             * Creates a new {@link EsIndividual} with the given single
063             * {@code individual}, which is converted to one-dimensional vector, and the
064             * given {@code increment}.
065             */
066            public EsIndividual(final double individual, final double increment) {
067                    this(new double[] { individual }, increment);
068            }
069    
070            /**
071             * Creates a new {@link EsIndividual} with the given {@code individual} and
072             * {@code increment}.
073             * 
074             * @throws NullPointerException
075             *             if {@code individual} is <code>null</code>
076             * @throws IllegalArgumentException
077             *             if {@code individual} is an empty array
078             */
079            public EsIndividual(final double[] individual, final double increment) {
080                    if (null == individual) {
081                            throw new NullPointerException("individual may not be null");
082                    }
083                    if (0 == individual.length) {
084                            throw new IllegalArgumentException(
085                                            "individual may not be an empty array");
086                    }
087    
088                    this.individual = individual;
089                    this.increment = increment;
090            }
091    
092            /**
093             * Return the contained actual individual.
094             * <p>
095             * <i>Note: An instance of {@link EsIndividual} is considered to be
096             * immutable, but for performance reasons the contained array is not copied.
097             * So <b>don't modify</b> the returned array.</i>
098             * 
099             * @return the contained actual individual; cannot be <code>null</code>
100             */
101            public double[] getIndividual() {
102                    assert null != individual;
103    
104                    return individual;
105            }
106    
107            /**
108             * Returns the current increment.
109             * 
110             * @return the current increment
111             */
112            public double getIncrement() {
113                    return increment;
114            }
115    
116            @Override
117            public int hashCode() {
118                    assert null != individual;
119    
120                    final int prime = 31;
121                    int result = 1;
122                    long temp;
123                    temp = Double.doubleToLongBits(increment);
124                    result = prime * result + (int) (temp ^ temp >>> 32);
125                    result = prime * result + individual.hashCode();
126                    return result;
127            }
128    
129            @Override
130            public boolean equals(final Object obj) {
131                    assert null != individual;
132    
133                    if (this == obj) {
134                            return true;
135                    }
136                    if (obj == null) {
137                            return false;
138                    }
139                    if (!(obj instanceof EsIndividual)) {
140                            return false;
141                    }
142                    final EsIndividual other = (EsIndividual) obj;
143                    if (Double.doubleToLongBits(increment) != Double
144                                    .doubleToLongBits(other.increment)) {
145                            return false;
146                    }
147    
148                    return individual.equals(other.individual);
149            }
150    
151            @Override
152            public String toString() {
153                    return "EsIndividual [increment=" + increment + ", individual="
154                                    + individual + "]";
155            }
156    }