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; 018 019 import org.apache.commons.math3.exception.DimensionMismatchException; 020 import org.apache.commons.math3.exception.NumberIsTooSmallException; 021 import org.apache.commons.math3.exception.NumberIsTooLargeException; 022 023 /** 024 * Base class for implementing optimizers for multivariate functions. 025 * It contains the boiler-plate code for initial guess and bounds 026 * specifications. 027 * <em>It is not a "user" class.</em> 028 * 029 * @param <PAIR> Type of the point/value pair returned by the optimization 030 * algorithm. 031 * 032 * @version $Id$ 033 * @since 3.1 034 */ 035 public abstract class BaseMultivariateOptimizer<PAIR> 036 extends BaseOptimizer<PAIR> { 037 /** Initial guess. */ 038 private double[] start; 039 /** Lower bounds. */ 040 private double[] lowerBound; 041 /** Upper bounds. */ 042 private double[] upperBound; 043 044 /** 045 * @param checker Convergence checker. 046 */ 047 protected BaseMultivariateOptimizer(ConvergenceChecker<PAIR> checker) { 048 super(checker); 049 } 050 051 /** 052 * {@inheritDoc} 053 * 054 * @param optData Optimization data. 055 * The following data will be looked for: 056 * <ul> 057 * <li>{@link MaxEval}</li> 058 * <li>{@link InitialGuess}</li> 059 * <li>{@link SimpleBounds}</li> 060 * </ul> 061 * @return {@inheritDoc} 062 */ 063 @Override 064 public PAIR optimize(OptimizationData... optData) { 065 // Retrieve settings. 066 parseOptimizationData(optData); 067 // Check input consistency. 068 checkParameters(); 069 // Perform optimization. 070 return super.optimize(optData); 071 } 072 073 /** 074 * Scans the list of (required and optional) optimization data that 075 * characterize the problem. 076 * 077 * @param optData Optimization data. The following data will be looked for: 078 * <ul> 079 * <li>{@link InitialGuess}</li> 080 * <li>{@link SimpleBounds}</li> 081 * </ul> 082 */ 083 private void parseOptimizationData(OptimizationData... optData) { 084 // The existing values (as set by the previous call) are reused if 085 // not provided in the argument list. 086 for (OptimizationData data : optData) { 087 if (data instanceof InitialGuess) { 088 start = ((InitialGuess) data).getInitialGuess(); 089 continue; 090 } 091 if (data instanceof SimpleBounds) { 092 final SimpleBounds bounds = (SimpleBounds) data; 093 lowerBound = bounds.getLower(); 094 upperBound = bounds.getUpper(); 095 continue; 096 } 097 } 098 } 099 100 /** 101 * Gets the initial guess. 102 * 103 * @return the initial guess, or {@code null} if not set. 104 */ 105 public double[] getStartPoint() { 106 return start == null ? null : start.clone(); 107 } 108 /** 109 * @return the lower bounds, or {@code null} if not set. 110 */ 111 public double[] getLowerBound() { 112 return lowerBound == null ? null : lowerBound.clone(); 113 } 114 /** 115 * @return the upper bounds, or {@code null} if not set. 116 */ 117 public double[] getUpperBound() { 118 return upperBound == null ? null : upperBound.clone(); 119 } 120 121 /** 122 * Check parameters consistency. 123 */ 124 private void checkParameters() { 125 if (start != null) { 126 final int dim = start.length; 127 if (lowerBound != null) { 128 if (lowerBound.length != dim) { 129 throw new DimensionMismatchException(lowerBound.length, dim); 130 } 131 for (int i = 0; i < dim; i++) { 132 final double v = start[i]; 133 final double lo = lowerBound[i]; 134 if (v < lo) { 135 throw new NumberIsTooSmallException(v, lo, true); 136 } 137 } 138 } 139 if (upperBound != null) { 140 if (upperBound.length != dim) { 141 throw new DimensionMismatchException(upperBound.length, dim); 142 } 143 for (int i = 0; i < dim; i++) { 144 final double v = start[i]; 145 final double hi = upperBound[i]; 146 if (v > hi) { 147 throw new NumberIsTooLargeException(v, hi, true); 148 } 149 } 150 } 151 } 152 } 153 }