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