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 org.apache.commons.math.random.RandomGenerator;
019    
020    /**
021     * An {@link Optimizer} tries to optimize a given population of individuals to
022     * improve their fitness. The concrete optimization technique depends on the
023     * subclasses implementation.
024     * <p>
025     * Subclasses need to implement this optimization technique inside
026     * {@link #optimize()} and should override {@link #getConfiguration()} to cast
027     * the result to the appropriate {@link OptimizerConfiguration}'s subtype.
028     * 
029     * <p>
030     * The implementations are generally considered to be <b>not thread-safe</b> and
031     * <b>not reusable</b>. Every instance should only be used for one optimization.
032     * And if the subclass' instance can be reused, external synchronization should
033     * be used to ensure that only one optimization runs on a given instance.
034     * 
035     * @param <I>
036     *            the individuals' type
037     * 
038     * @author <a href="http://kumpe.de/christian/java">Christian Kumpe</a>
039     */
040    public abstract class Optimizer<I> {
041            private final OptimizerConfiguration<I> configuration;
042            private final RandomGenerator randomGenerator;
043    
044            /**
045             * Creates a new {@link Optimizer} object with the given
046             * {@link OptimizerConfiguration}.
047             * <p>
048             * The configuration will be {@link OptimizerConfiguration#clone() cloned}
049             * and {@link OptimizerConfiguration#validate() validated}.
050             * 
051             * @param configuration
052             *            the new optimizer's configuration
053             * 
054             * 
055             * @throws NullPointerException
056             *             if {@code configuration} is <code>null</code>
057             * @throws IllegalStateException
058             *             if the given configuration is not valid
059             */
060            public Optimizer(final OptimizerConfiguration<I> configuration) {
061                    this.configuration = configuration.clone();
062                    this.configuration.validate();
063                    this.randomGenerator = this.configuration.getRandomGeneratorFactory()
064                                    .createRandomGenerator(System.currentTimeMillis());
065            }
066    
067            /**
068             * Returns the optimizer's configuration. This configuration should not be
069             * modified once the optimizer has been created.
070             * <p>
071             * This method can be overridden to cast the {@link OptimizerConfiguration}
072             * to the appropriate subtype for the concrete optimizer implementation.
073             * 
074             * @return the optimizer's configuration
075             */
076            protected OptimizerConfiguration<I> getConfiguration() {
077                    return configuration;
078            }
079    
080            protected RandomGenerator getRandomGenerator() {
081                    return randomGenerator;
082            }
083    
084            /**
085             * Starts the optimization.
086             * <p>
087             * Subclasses need to implement this method with a concrete optimization
088             * technique.
089             * 
090             * @throws OptimizerException
091             *             if a checked exception occurs inside the optimization
092             */
093            public abstract void optimize();
094    }