(Оффтоп)
Если бы я был ежом - я бы начал с выяснения вопроса, не вкусный ли это червячок? Нет? Ну хоть что-то съедобное? Тоже нет? Тема бесперспективная и абсолютно недиссертабельная.
Увы, концептуальная парадигма ежей несколько прагматична...
Давненько я не брал в руки Turbo Pascal. Хотя не так давно, как могло быть. В обозримом прошлом пришлось корректировать софт к одному старому прибору, где разработчик кое-что наврал. Любезное предоставленные им исходники компилировались только на TP, более того, исключительно на TP 5.5 (что-то он там на ассемблере вставлял хитрое). Но даже на TP, помнится, были фокусы, позволявшие брать из "кучи" более 64Кб одним куском, и даже брать из extended memory, до 4 Мб (не уверен, но возможно, его ASM-вставки как раз для этого и были, хотя, может, для фокусов с видеопамятью). Впрочем, более осмысленно идти по стопам Древних Титанов, храня такие, не влезающие в ОП, данные, во внешней памяти и подгружая по надобности (Великие Древние ухитрялись обращать матрицу размерности тысяча на тысяча при 4096 словах памяти...). И даже если хранить исходные данные в single (а они, подозреваю, снимаются с АЦП, где разрядность 12 или 14, может, 16, и можно хранить, как целочисленные отсчёты по 2 байта), то вычислять лучше всё же в double. Обращая матрицу, в частности. Маленькие ошибки могут там изрядно вывернуть обратную матрицу.
Возвращаясь к Левенбергу-Марквардту. Прежде всего - это приближение к методу Ньютона. Но упрощённое. Не требующее вычисления вторых производных от приближающей функции. Матрица вторых производных от квадратичной целевой функции (суммы квадратов невязок) включает первые производные от приближающей функции и вторые производные от неё. Упрощение в Л-М состоит в том, что вторые производные мы волевым решением приравниваем к нулю, избавляясь от
![$n^2$ $n^2$](https://dxdy-01.korotkov.co.uk/f/0/2/1/021273d50c6ff03efebda428e9e42d7782.png)
вычислений вторых производных на каждой итерации и такого же количества выписываний аналитических выражений для них. Обращаемая матрица при этом может быть вырождена или близка к вырожденной, и мы ещё более загрубляем, прибавляя к её диагонали положительные числа (одинаковые или пропорциональные диагональным элементам).
То есть нам надо уметь считать
![$n$ $n$](https://dxdy-02.korotkov.co.uk/f/5/5/a/55a049b8f161ae7cfeb0197d75aff96782.png)
производных по параметрам.
Если функция имеет вид
![$y=e^{-at}(I_0\sin\omega t+I_1\cos\omega t)$ $y=e^{-at}(I_0\sin\omega t+I_1\cos\omega t)$](https://dxdy-04.korotkov.co.uk/f/7/2/4/7240a55d17585656ae3a33297ebd04a882.png)
(я настаиваю на необходимости учёта фазового сдвига - даже если Вы уверены, что при
![$t=0$ $t=0$](https://dxdy-02.korotkov.co.uk/f/1/c/8/1c899e1c767eb4eac89facb5d1f2cb0d82.png)
непременно
![$y=0$ $y=0$](https://dxdy-03.korotkov.co.uk/f/a/4/2/a42b1c71ca6ab3bfc0e416ac9b58799382.png)
, ничто не гарантирует, что Ваш первый отсчёт, снятый с АЦП, будет соответствовать
![$t=0$ $t=0$](https://dxdy-02.korotkov.co.uk/f/1/c/8/1c899e1c767eb4eac89facb5d1f2cb0d82.png)
; кроме того, использование представления в виде суммы синуса и косинуса, синфазной и квадратурной составляющей, несколько упрощает работу сравнительно с
![$\sin(\omega t+\varphi)$ $\sin(\omega t+\varphi)$](https://dxdy-03.korotkov.co.uk/f/2/4/9/249afb55d9f03f09b9c57ab084c291a382.png)
)
то производные будут
![$\frac{\partial y}{\partial a}=-t e^{-at}(I_0\sin\omega t+I_1\cos\omega t)$ $\frac{\partial y}{\partial a}=-t e^{-at}(I_0\sin\omega t+I_1\cos\omega t)$](https://dxdy-03.korotkov.co.uk/f/2/6/f/26f4b2a3b9dd16b5aa241fc4e8114f4282.png)
![$\frac{\partial y}{\partial \omega}=e^{-at}(I_0 t \cos\omega t-I_1 t \sin\omega t)$ $\frac{\partial y}{\partial \omega}=e^{-at}(I_0 t \cos\omega t-I_1 t \sin\omega t)$](https://dxdy-01.korotkov.co.uk/f/0/c/a/0cab580d6efe5e5b95b0e0896a6c8f9982.png)
![$\frac{\partial y}{\partial I_0}= e^{-at}\sin\omega t$ $\frac{\partial y}{\partial I_0}= e^{-at}\sin\omega t$](https://dxdy-02.korotkov.co.uk/f/d/8/7/d87034be1e3ab5b5ec049bd762aae25e82.png)
![$\frac{\partial y}{\partial I_1}= e^{-at}\cos\omega t$ $\frac{\partial y}{\partial I_1}= e^{-at}\cos\omega t$](https://dxdy-04.korotkov.co.uk/f/b/9/f/b9f427f2766126af5fcc6b5b685cbecc82.png)
Имея какие-то начальные приближения для параметров (лично я бы в Вашем случае частоту оценил бы через число максимумов, минимумов или пересечений ноля, а декремент затухания - проведя линейную регрессию через логарифмы максимумов и/или абсолютных величин минимумов, наклон даст Вам параметр
![$a$ $a$](https://dxdy-01.korotkov.co.uk/f/4/4/b/44bc9d542a92714cac84e01cbbb7fd6182.png)
, а свободный член будет логарифмом
![$I$ $I$](https://dxdy-03.korotkov.co.uk/f/2/1/f/21fd4e8eecd6bdf1a4d3d6bd1fb8d73382.png)
), вычисляем значения функции в точках при этих параметрах и их отклонения от наблюдаемых, составляющие вектор
![$u$ $u$](https://dxdy-03.korotkov.co.uk/f/6/d/b/6dbb78540bd76da3f1625782d42d6d1682.png)
, а значения производных в этих точках - матрицу Z (сержант-вычислитель Равненько из батареи к-на Очевидность подсказывает, что в программе их хранить необязательно, особенно если у Вас дефицит памяти, о векторе и матрице речь идёт лишь для удобства изложения, на практике лучше держать только матрицу
![$R=Z^TZ$ $R=Z^TZ$](https://dxdy-03.korotkov.co.uk/f/6/e/9/6e945bb3b6469af990e7d42b186d42d182.png)
и вектор
![$w=Z^Tu$ $w=Z^Tu$](https://dxdy-02.korotkov.co.uk/f/1/8/4/1840d6a6b318b2ab3eabb10ad0ec3f3a82.png)
, существенно меньшей размерности, накапливая в них значения, двигаясь по
![$t$ $t$](https://dxdy-01.korotkov.co.uk/f/4/f/4/4f4f4e395762a3af4575de74c019ebb582.png)
)
Тогда поправка к значениям параметров получается, как
![$\Delta=(Z^TZ)^{-1}Z^Tu=R^{-1}w$ $\Delta=(Z^TZ)^{-1}Z^Tu=R^{-1}w$](https://dxdy-02.korotkov.co.uk/f/1/3/a/13a114b2759e4d4f2dd130e4590a9ea782.png)
, но тут может быть вычислительная проблема, если матрица
![$R$ $R$](https://dxdy-02.korotkov.co.uk/f/1/e/4/1e438235ef9ec72fc51ac5025516017c82.png)
будет близка к вырожденной, поэтому пользуются более устойчивой вычислительно поправкой
![$\Delta=(Z^TZ+D)^{-1}Z^Tu=(R+D)^{-1}w$ $\Delta=(Z^TZ+D)^{-1}Z^Tu=(R+D)^{-1}w$](https://dxdy-04.korotkov.co.uk/f/7/2/a/72a4d29d71c6e0e7737f51e22eecc3b982.png)
, где
![$D$ $D$](https://dxdy-04.korotkov.co.uk/f/7/8/e/78ec2b7008296ce0561cf83393cb746d82.png)
- диагональная матрица, элементы которой либо равные малые числа, либо умноженные на малое число диагональные элементы матрицы
(насколько малые - ну, вот я увеличивал диагональные на один процент и сверх того прибавлял одну миллионную).
Скорректировав значения параметров - повторяем расчёт, следя за сходимостью.