001 // Licensed to the Apache Software Foundation (ASF) under one 002 // or more contributor license agreements. See the NOTICE file 003 // distributed with this work for additional information 004 // regarding copyright ownership. The ASF licenses this file 005 // to you under the Apache License, Version 2.0 (the 006 // "License"); you may not use this file except in compliance 007 // with 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, 012 // software distributed under the License is distributed on an 013 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 014 // KIND, either express or implied. See the License for the 015 // specific language governing permissions and limitations 016 // under the License. 017 018 package org.apache.commons.math.optimization.fitting; 019 020 import static org.junit.Assert.assertEquals; 021 import static org.junit.Assert.assertTrue; 022 023 import java.util.Random; 024 025 import org.apache.commons.math.optimization.OptimizationException; 026 import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer; 027 import org.apache.commons.math.util.MathUtils; 028 import org.junit.Test; 029 030 public class HarmonicFitterTest { 031 032 @Test 033 public void testNoError() throws OptimizationException { 034 HarmonicFunction f = new HarmonicFunction(0.2, 3.4, 4.1); 035 036 HarmonicFitter fitter = 037 new HarmonicFitter(new LevenbergMarquardtOptimizer()); 038 for (double x = 0.0; x < 1.3; x += 0.01) { 039 fitter.addObservedPoint(1.0, x, f.value(x)); 040 } 041 042 HarmonicFunction fitted = fitter.fit(); 043 assertEquals(f.getAmplitude(), fitted.getAmplitude(), 1.0e-13); 044 assertEquals(f.getPulsation(), fitted.getPulsation(), 1.0e-13); 045 assertEquals(f.getPhase(), MathUtils.normalizeAngle(fitted.getPhase(), f.getPhase()), 1.0e-13); 046 047 for (double x = -1.0; x < 1.0; x += 0.01) { 048 assertTrue(Math.abs(f.value(x) - fitted.value(x)) < 1.0e-13); 049 } 050 051 } 052 053 @Test 054 public void test1PercentError() throws OptimizationException { 055 Random randomizer = new Random(64925784252l); 056 HarmonicFunction f = new HarmonicFunction(0.2, 3.4, 4.1); 057 058 HarmonicFitter fitter = 059 new HarmonicFitter(new LevenbergMarquardtOptimizer()); 060 for (double x = 0.0; x < 10.0; x += 0.1) { 061 fitter.addObservedPoint(1.0, x, 062 f.value(x) + 0.01 * randomizer.nextGaussian()); 063 } 064 065 HarmonicFunction fitted = fitter.fit(); 066 assertEquals(f.getAmplitude(), fitted.getAmplitude(), 7.6e-4); 067 assertEquals(f.getPulsation(), fitted.getPulsation(), 2.7e-3); 068 assertEquals(f.getPhase(), MathUtils.normalizeAngle(fitted.getPhase(), f.getPhase()), 1.3e-2); 069 070 } 071 072 @Test 073 public void testInitialGuess() throws OptimizationException { 074 Random randomizer = new Random(45314242l); 075 HarmonicFunction f = new HarmonicFunction(0.2, 3.4, 4.1); 076 077 HarmonicFitter fitter = 078 new HarmonicFitter(new LevenbergMarquardtOptimizer(), new double[] { 0.15, 3.6, 4.5 }); 079 for (double x = 0.0; x < 10.0; x += 0.1) { 080 fitter.addObservedPoint(1.0, x, 081 f.value(x) + 0.01 * randomizer.nextGaussian()); 082 } 083 084 HarmonicFunction fitted = fitter.fit(); 085 assertEquals(f.getAmplitude(), fitted.getAmplitude(), 1.2e-3); 086 assertEquals(f.getPulsation(), fitted.getPulsation(), 3.3e-3); 087 assertEquals(f.getPhase(), MathUtils.normalizeAngle(fitted.getPhase(), f.getPhase()), 1.7e-2); 088 089 } 090 091 @Test 092 public void testUnsorted() throws OptimizationException { 093 Random randomizer = new Random(64925784252l); 094 HarmonicFunction f = new HarmonicFunction(0.2, 3.4, 4.1); 095 096 HarmonicFitter fitter = 097 new HarmonicFitter(new LevenbergMarquardtOptimizer()); 098 099 // build a regularly spaced array of measurements 100 int size = 100; 101 double[] xTab = new double[size]; 102 double[] yTab = new double[size]; 103 for (int i = 0; i < size; ++i) { 104 xTab[i] = 0.1 * i; 105 yTab[i] = f.value(xTab[i]) + 0.01 * randomizer.nextGaussian(); 106 } 107 108 // shake it 109 for (int i = 0; i < size; ++i) { 110 int i1 = randomizer.nextInt(size); 111 int i2 = randomizer.nextInt(size); 112 double xTmp = xTab[i1]; 113 double yTmp = yTab[i1]; 114 xTab[i1] = xTab[i2]; 115 yTab[i1] = yTab[i2]; 116 xTab[i2] = xTmp; 117 yTab[i2] = yTmp; 118 } 119 120 // pass it to the fitter 121 for (int i = 0; i < size; ++i) { 122 fitter.addObservedPoint(1.0, xTab[i], yTab[i]); 123 } 124 125 HarmonicFunction fitted = fitter.fit(); 126 assertEquals(f.getAmplitude(), fitted.getAmplitude(), 7.6e-4); 127 assertEquals(f.getPulsation(), fitted.getPulsation(), 3.5e-3); 128 assertEquals(f.getPhase(), MathUtils.normalizeAngle(fitted.getPhase(), f.getPhase()), 1.5e-2); 129 130 } 131 132 }