    001    /*
    002     * Licensed to the Apache Software Foundation (ASF) under one or more
    003     * contributor license agreements.  See the NOTICE file distributed with
    004     * this work for additional information regarding copyright ownership.
    005     * The ASF licenses this file to You under the Apache License, Version 2.0
    006     * (the "License"); you may not use this file except in compliance with
    007     * the License.  You may obtain a copy of the License at
    008     *
    009     *      http://www.apache.org/licenses/LICENSE-2.0
    010     *
    011     * Unless required by applicable law or agreed to in writing, software
    012     * distributed under the License is distributed on an "AS IS" BASIS,
    013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014     * See the License for the specific language governing permissions and
    015     * limitations under the License.
    016     */
    017    package org.apache.commons.math3.optim.nonlinear.scalar;
    018
    019    import java.util.Collections;
    020    import java.util.List;
    021    import java.util.ArrayList;
    022    import java.util.Comparator;
    023    import org.apache.commons.math3.exception.NotStrictlyPositiveException;
    024    import org.apache.commons.math3.exception.NullArgumentException;
    025    import org.apache.commons.math3.random.RandomVectorGenerator;
    026    import org.apache.commons.math3.optim.BaseMultiStartMultivariateOptimizer;
    027    import org.apache.commons.math3.optim.PointValuePair;
    028
    029    /**
    030     * Multi-start optimizer.
    031     *
    032     * This class wraps an optimizer in order to use it several times in
    033     * turn with different starting points (trying to avoid being trapped
    034     * in a local extremum when looking for a global one).
    035     *
    036     * @version $Id$
    037     * @since 3.0
    038     */
    039    public class MultiStartMultivariateOptimizer
    040        extends BaseMultiStartMultivariateOptimizer<PointValuePair> {
    041        /** Underlying optimizer. */
    042        private final MultivariateOptimizer optimizer;
    043        /** Found optima. */
    044        private final List<PointValuePair> optima = new ArrayList<PointValuePair>();
    045
    046        /**
    047         * Create a multi-start optimizer from a single-start optimizer.
    048         *
    049         * @param optimizer Single-start optimizer to wrap.
    050         * @param starts Number of starts to perform.
    051         * If {@code starts == 1}, the result will be same as if {@code optimizer}
    052         * is called directly.
    053         * @param generator Random vector generator to use for restarts.
    054         * @throws NullArgumentException if {@code optimizer} or {@code generator}
    055         * is {@code null}.
    056         * @throws NotStrictlyPositiveException if {@code starts < 1}.
    057         */
    058        public MultiStartMultivariateOptimizer(final MultivariateOptimizer optimizer,
    059                                               final int starts,
    060                                               final RandomVectorGenerator generator)
    061            throws NullArgumentException,
    062            NotStrictlyPositiveException {
    063            super(optimizer, starts, generator);
    064            this.optimizer = optimizer;
    065        }
    066
    067        /**
    068         * {@inheritDoc}
    069         */
    070        @Override
    071        public PointValuePair[] getOptima() {
    072            Collections.sort(optima, getPairComparator());
    073            return optima.toArray(new PointValuePair[0]);
    074        }
    075
    076        /**
    077         * {@inheritDoc}
    078         */
    079        @Override
    080        protected void store(PointValuePair optimum) {
    081            optima.add(optimum);
    082        }
    083
    084        /**
    085         * {@inheritDoc}
    086         */
    087        @Override
    088        protected void clear() {
    089            optima.clear();
    090        }
    091
    092        /**
    093         * @return a comparator for sorting the optima.
    094         */
    095        private Comparator<PointValuePair> getPairComparator() {
    096            return new Comparator<PointValuePair>() {
    097                public int compare(final PointValuePair o1,
    098                                   final PointValuePair o2) {
    099                    if (o1 == null) {
    100                        return (o2 == null) ? 0 : 1;
    101                    } else if (o2 == null) {
    102                        return -1;
    103                    }
    104                    final double v1 = o1.getValue();
    105                    final double v2 = o2.getValue();
    106                    return (optimizer.getGoalType() == GoalType.MINIMIZE) ?
    107                        Double.compare(v1, v2) : Double.compare(v2, v1);
    108                }
    109            };
    110        }
    111    }