задача определителя точности Matlab

У меня есть следующая программа

format compact; format short g; clear; clc;  
L = 140; J = 77; Jm = 10540; G = 0.8*10^8; d = L/3;  
for i=1:500000  
omegan=1.+0.0001*i;

a(1,1) = ((omegan^2)*(Jm/(G*J))*d^2)-2; a(1,2) = 2; a(1,3) = 0; a(1,4) = 0;
a(2,1) = 1; a(2,2) = ((omegan^2)*(Jm/(G*J))*d^2)-2; a(2,3) = 1; a(2,4) = 0;
a(3,1) = 0; a(3,2) = 1; a(3,3) = ((omegan^2)*(Jm/(G*J))*d^2)-2; a(3,4) = 1;
a(4,1) = 0; a(4,2) = 0; a(4,3) = 2; a(4,4) = ((omegan^2)*(Jm/(G*J))*d^2)-2;

if(abs(det(a))<1E-10) sprintf('omegan= %8.3f det= %8.3f',omegan,det(a))
end          
end

Аналитическое решение приведенной выше системы, и та же программа, написанная на фортране, выдает значения омеган равно 16,3818 и 32,7636 (значения на Фортране; аналитические немного отличаются, но где-то есть).

Итак, теперь я задаюсь вопросом ... где я ошибаюсь в этом? Почему Matlab не дает ожидаемых результатов?

(возможно, это что-то ужасно простое, но у меня от этого голова болит)


person Rook    schedule 07.05.2010    source источник
comment
Интересный. Для меня это тоже никогда не прекращается. Значения, которые я получаю для det(a), равны -4E-5 и -3E-4 с вашим омеганом (если я не ошибся). Просто для проверки на ошибки: вы получили список значений для det (a) из программы на фортране и сравнили их со значениями из Matlab?   -  person Jonas    schedule 07.05.2010
comment
@Jonas - Нет, я думал, что это излишне. В конце концов, я просто скопировал (сделав необходимые модификации) программу на фортране в матлаб, а так как матлаб по умолчанию работает в режиме dp, я полагал, что он решит эту проблему без проблем. Как я сказал в комментарии к gnovice, это был только пример - меня не столько интересуют результаты, сколько расхождения между фортраном и матлабом (я все еще проверяю, может ли матлаб справиться с такими проблемами ).   -  person Rook    schedule 07.05.2010
comment
@Idigas: Я понимаю, что вас не особо интересует эта конкретная проблема. Но если это действительно проблема точности, разве вы не хотели бы знать, при каких условиях это происходит? Кроме того, как отмечали другие: Matlab действительно находит решения, просто отсечка может быть другой.   -  person Jonas    schedule 07.05.2010
comment
@ Джонас - прошу прощения. Я не хотел, чтобы выяснилось, что мне это неинтересно. Наоборот. Это именно то, что меня интересует. Но поскольку я не вижу алгоритма матлаба для вычисления дет. матрицы, я не вижу, как сравнение значений может помочь. Пожалуйста, прокомментируйте, если у вас есть идея или две, в общем, как это сделать.   -  person Rook    schedule 07.05.2010
comment
Хотя я всегда был пользователем фортрана, матлаб в последнее время стал мне интересен, потому что в нем большая коллекция готовых функций, а значит, мне очень легко экспериментировать, и легко прототипировать модели, прежде чем я их перепишу на фортране (если возникнет необходимость). Но теперь я понимаю, что иногда закрытые функции не являются необходимым преимуществом.   -  person Rook    schedule 07.05.2010
comment
@Idigas: Добро пожаловать в числовые вычисления. У нас были проблемы с запуском программ, использующих один и тот же код оптимизации в разных операционных системах. То, что вы могли бы получить от сравнения значений, было бы знанием того, откуда берутся ошибки точности. Например, det(a) может быть почти таким же, пока оно выше, скажем, 1E-3, и что Fortran систематически возвращает значения ближе к нулю для определителя, если он становится маленьким. Это может дать вам представление о том, как вам нужно адаптировать допуски при переносе из одной программы в другую.   -  person Jonas    schedule 07.05.2010
comment
@ Джонас - Верно; идея, которую стоит попробовать. Я ухожу пробовать. Что касается запуска программ, использующих один и тот же код на разных платформах, я не знаю о Matlab, но fortran предлагает очень хорошие функции в этом сегменте с использованием спецификатора KIND. Это позволяет вам указать необходимую точность и диапазон типов, что исключает зависимость вашей программы от платформы (REAL * 4 зависит от платформы, в зависимости от того, что означает * 4 на каком процессоре / платформе / компиляторе. Это вошло в стандарт в fortran95 я считаю, и это одна из бесценных возможностей   -  person Rook    schedule 07.05.2010
comment
язык с точки зрения переносимости. Хотя и не очень известно, так как большинство людей до сих пор живут в мышлении на фортране77 (к сожалению :(.   -  person Rook    schedule 07.05.2010


Ответы (3)


Вы ищете слишком маленькие значения определителя, потому что Matlab использует другую функцию определителя (или по какой-то другой причине, например, что-то связанное с точностью с плавающей запятой, используемой в двух разных методах). Я покажу вам, что Matlab, по сути, дает вам правильные значения и лучший способ подойти к этой проблеме в целом.

Во-первых, давайте возьмем ваш код и немного его изменим.

format compact; format short g; clear; clc;
L = 140; J = 77; Jm = 10540; G = 0.8*10^8; d = L/3;
vals = zeros(1,500000);
for i=1:500000
    omegan=1.+0.0001*i;

    a(1,1) = ((omegan^2)*(Jm/(G*J))*d^2)-2; a(1,2) = 2; a(1,3) = 0; a(1,4) = 0;
    a(2,1) = 1; a(2,2) = ((omegan^2)*(Jm/(G*J))*d^2)-2; a(2,3) = 1; a(2,4) = 0;
    a(3,1) = 0; a(3,2) = 1; a(3,3) = ((omegan^2)*(Jm/(G*J))*d^2)-2; a(3,4) = 1;
    a(4,1) = 0; a(4,2) = 0; a(4,3) = 2; a(4,4) = ((omegan^2)*(Jm/(G*J))*d^2)-2;
    vals(i) = abs(det(a));
    if(vals(i)<1E-10)
        sprintf('omegan= %8.3f det= %8.3f',omegan,det(a))
    end
end
plot(1.+0.0001*(1:500000),log(vals))

На самом деле все, что я сделал, это записал значения определителя для всех значений омегана и построил логарифм этих значений определителя как функцию омегана. Вот сюжет:

альтернативный текст

Вы заметили три основных провала на графике. Два совпадают с вашими результатами 16,3818 и 32,7636, но есть и дополнительный, который вы пропустили (вероятно, потому, что ваше условие детерминанта меньше 1e-10 было слишком низким даже для вашего кода Fortran, чтобы подобрать его). Следовательно, Matlab также сообщает вам, что это значения омегана, которые вы искали, но из-за того, что определитель был определен в Matlab по-другому, значения не были одинаковыми, что неудивительно при работе с плохо обусловленными матрицами. . Кроме того, это, вероятно, связано с тем, что Фортран использует поплавки одинарной точности, как сказал кто-то другой. Я не собираюсь разбираться, почему это не так, потому что не хочу тратить на это время. Вместо этого давайте посмотрим, что вы пытаетесь сделать, и попробуем другой подход.

Вы, как я уверен, в курсе, пытаетесь найти собственные значения матрицы

a = [[-2 2 0 0]; [1 -2 1 0]; [0 1 -2 1]; [0 0 2 -2]];

, установите их равными

-omegan^2*(Jm/(G*J)*d^2)

и решить для омеган. Вот как я это сделал:

format compact; format short g; clear; clc;
L = 140; J = 77; Jm = 10540; G = 0.8*10^8; d = L/3;
C1 = (Jm/(G*J)*d^2);
a = [[-2 2 0 0]; [1 -2 1 0]; [0 1 -2 1]; [0,0,2,-2]];
myeigs = eig(a);
myeigs(abs(myeigs) < eps) = 0.0;
for i=1:4
    sprintf('omegan= %8.3f', sqrt(-myeigs(i)/C1))
end

Это дает вам все четыре решения, а не только два, которые вы нашли с помощью своего кода на Фортране (хотя одно из них, нулевое, находилось за пределами вашего диапазона тестирования для омеган). Если вы хотите решить эту проблему, проверив определитель в Matlab, как вы пытались это сделать, вам придется поиграть со значением, которое вы проверяете, чтобы абсолютное значение определителя было меньше. Я заставил его работать для значения 1e-4 (это дало 3 решения: 16,382, 28,374 и 32,764).

Извините за такое длинное решение, но, надеюсь, оно поможет.

Обновление:

В моем первом блоке кода выше я заменил

vals(i) = abs(det(a));

с

[L,U] = lu(a);
s = det(L);
vals(i) = abs(s*prod(diag(U)));

это алгоритм, который det предположительно использует в соответствии с документами Matlab. Теперь я могу использовать 1E-10 в качестве условия, и это работает. Так что, может быть, Matlab не вычисляет определитель точно так, как говорят документы? Это немного беспокоит.

person Justin Peel    schedule 07.05.2010
comment
Это может быть проблемой (matlab использует другую функцию определителя). Вы знаете, где можно узнать, какой алгоритм использует для этого Matlab? Кстати, я ценю усилия, которые вы приложили для решения этой системы, но, к сожалению, я не могу использовать ее в своей работе. Матрицы коэффициентов, которые я использую, собираются с использованием уже написанных функций и всегда сложнее (и больше), чем эта (которая была для простой балки, разделенной на 3 элемента/4 узла). - person Rook; 07.05.2010
comment
Третьего (или второго, как посмотреть) омегана я не пропустил. Программа на Фортране дала и это. Просто это не было одним из решений, хотя оно было численно правильным. Частоты. должны быть в определенных рационах друг к другу. Прошу прощения, если я вызвал у вас некоторую путаницу; Я должен был упомянуть об этом в вопросе. - person Rook; 07.05.2010
comment
Я нахожу это ужасно раздражающим, кстати. Я ожидал, что если Matlab работает с двойной точностью, и если я пишу свои программы на Фортране с такой точностью; Я мог бы получить те же результаты без особой перезаписи (в основном операторы ** для ^ :). Я не ожидал, что функции Matlab вызовут проблемы. - person Rook; 07.05.2010
comment
@Jonas - аналитические решения одинаковы (на моем калькуляторе и с использованием dp в фортране, до седьмого или восьмого знака после запятой. Одинарная точность не отличается от этих значений, так что это говорит мне, что нет никаких ошибок округления / добавления , что имеет существенное значение). - person Rook; 07.05.2010
comment
Matlab использует разложение LU для вычисления определителя, как описано в разделе справки по алгоритму. - person Justin Peel; 07.05.2010
comment
@ldigas: Настоящая проблема заключается в том, что вы пытаетесь использовать характеристический полином для поиска собственных значений, что численно проблематично; кроме того, вы используете очень неэффективный поиск корней. Нахождение собственных значений — сложная задача с числовой точки зрения; Я бы настоятельно рекомендовал вам использовать существующую подпрограмму, такую ​​как подпрограмма MATLAB eig(). Вы говорите, что не можете использовать этот подход для ваших существующих матриц, но почему? - person Martin B; 07.05.2010
comment
@Justin: Да, это несколько тревожно. Я думаю, мы можем позвонить в службу поддержки TMW по этому поводу. - person Jonas; 07.05.2010
comment
@Martin B - ну, честно говоря, я не уверен, для чего я действительно могу использовать Matlab. Я всегда был пользователем Фортрана, но в последнее время я все больше и больше начал использовать Matlab для прототипирования и простого анализа менее совершенных моделей. Мне это нравится, потому что это очень просто разработать. Затем я повторно уточняю сетку в 200 раз и добавляю ее в свои решатели на Фортране. Тем не менее, у меня все еще есть проблемы с адаптацией к причудам Matlab в некоторых представлениях; поэтому этот (и, возможно, последуют другие) вопросы. - person Rook; 08.05.2010
comment
@Justin - это немного страшно! - person Rook; 08.05.2010

Новый ответ:

Вы можете исследовать эту проблему, используя символьные уравнения, которые дают мне правильные ответы:

>> clear all             %# Clear all existing variables
>> format long           %# Display more digits of precision
>> syms Jm d omegan G J  %# Your symbolic variables
>> a = ((Jm*(d*omegan)^2)/(G*J)-2).*eye(4)+...  %# Create the matrix a
       diag([2 1 1],1)+...
       diag([1 1 2],-1);
>> solns = solve(det(a),'omegan')  %# Solve for where the determinant is 0

solns =

                                0
                                0
            (G*J*Jm)^(1/2)/(Jm*d)
           -(G*J*Jm)^(1/2)/(Jm*d)
       -(2*(G*J*Jm)^(1/2))/(Jm*d)
        (2*(G*J*Jm)^(1/2))/(Jm*d)
  (3^(1/2)*(G*J*Jm)^(1/2))/(Jm*d)
 -(3^(1/2)*(G*J*Jm)^(1/2))/(Jm*d)

>> solns = subs(solns,{G,J,Jm,d},{8e7,77,10540,140/3})  %# Substitute values

solns =

                   0
                   0
  16.381862247021893
 -16.381862247021893
 -32.763724494043785
  32.763724494043785
  28.374217734436371
 -28.374217734436371

Я думаю, что вы либо просто не выбирали значения в своем цикле достаточно близко к решениям для omegan, либо ваш порог того, насколько близок определитель к нулю, слишком строг. Когда я подставляю данные значения к a вместе с omegan = 16.3819 (что является ближайшим значением к одному решению, которое выдает ваш цикл), я получаю следующее:

>> det(subs(a,{omegan,G,J,Jm,d},{16.3819,8e7,77,10540,140/3}))

ans =

    2.765476845475786e-005

Что еще больше по абсолютной амплитуде, чем 1e-10.

person gnovice    schedule 07.05.2010
comment
Здравствуйте, gnovice, я надеялся, что вы зайдете :) Нет, знак "меньше" там в порядке (если только я не упустил что-то, на что вы пытаетесь намекнуть). Это проблема собственных значений в колебаниях ... Мне нужно найти все омеганы (собственные частоты), для которых определитель равен нулю. Их бесконечное количество, но я ищу только первые несколько (две или три). Однако я не могу понять, почему моя программа на Фортране проглатывает это без проблем, а функция det() - нет. Кажется, это не одинарное/двойное - person Rook; 07.05.2010
comment
проблема с точностью - программа на фортране делает это с одинарной точностью, а в матлабе по умолчанию все с двойной точностью. Таким образом, у Matlab должно быть преимущество с самого начала. - person Rook; 07.05.2010
comment
На самом деле sprintf лишний, он здесь только для того, чтобы людям, которые попытаются понять это, не пришлось добавлять его самим. Как я уже сказал, я уже знаю результаты в этом случае. Меня больше интересует причина этой ошибки, так как теперь я не знаю, могу ли я полагаться на механизм Matlab при решении более крупной проблемы (результат которой я не знаю). - person Rook; 07.05.2010
comment
@Idigas: я дал совершенно новый ответ. Надеюсь, поможет. - person gnovice; 07.05.2010
comment
@gnovice - спасибо! Я пока не пробовал символический набор инструментов, так как для сборки матрицы коэффициентов процедуры уже сделаны. Кроме того, я, вероятно, не смогу его использовать, так как эта матрица обычно немного сложнее, чем эта (это был просто простой луч, разделенный на 3 элемента). Но, как я только что написал Джонасу в комментариях к вопросу, я не понимаю. У меня такой же шаг для омегана, у меня такие же критерии остановки. Почему Matlab, работающий с двойной точностью, не дает соответствующих результатов? - person Rook; 07.05.2010
comment
@Idigas: Я предполагаю, что есть расхождения, возникающие из-за порядка операций в вашем коде или в функции det. Если порядок арифметических операций для выполнения определенных вычислений различается между двумя реализациями, могут возникнуть небольшие различия в точности. - person gnovice; 07.05.2010

Я поставил это как ответ, потому что не могу вставить это в комментарий: вот как Matlab вычисляет детерминант. Я предполагаю, что ошибки округления возникают из-за вычисления произведения нескольких диагональных элементов в U.

Алгоритм

Определитель вычисляется из треугольных множителей, полученных методом исключения Гаусса.

[L,U] = lu(A) s =  det(L)        
%# This is always +1 or -1  
det(A) = s*prod(diag(U))
person Jonas    schedule 07.05.2010