0 / 0 / 0
Регистрация: 04.09.2016
Сообщений: 3
1

Итерационное вычисление частных производных

04.09.2016, 22:06. Показов 5479. Ответов 9
Метки нет (Все метки)

доброго времени суток

в задачах по численным методам столкнулся с необходимостью вычисления частных производных
сами вычисления "в лоб" вопросов не вызывают, работаем строго по определению:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
double e=0.000001;  //точность
 
double f(double x1,double x2,double x3){ // сама функция 
return x1+3*x2+2*x3*x3;
}
 
double df1(double x01,double x02,double x03){  //частная производная по х1    
    return (f(x01+e,x02,x03)-f(x01,x02,x03))/e;
}
 
double df11(double x01,double x02,double x03){ //частная производная по х1 частной производной х1    
    return (df1(x01+e,x02,x03)-df1(x01,x02,x03))/e;
}


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

я пытался искать что-то вроде передачи указателя на функцию в функцию, нашел простые примеры
ну, да, эти работают, если я вызываю новый df1 с параметром f:
Кликните здесь для просмотра всего текста
C++
1
2
3
double (*f)(double,double,double);
double df1(double,double,double,
           double (*func)(double,double,double));


но если я хочу вызвать производную от самой себя компилятор ругается на несоответствие параметров (т.е. нужно добавить в определение func внутри df1 параметр функции:
Кликните здесь для просмотра всего текста
C++
1
2
double df1(double,double,double,
           double (*func)(double,double,double,double (*func)(double,double,double)));
)
но это ведет к тому, что я не могу подать как параметр более простую функцию, и чем больше производных я хочу посчитать итерационно - тем больше мне приходится нагромождать определение изначальных функций.

можно ли вообще это как-то сделать с помощью вызова производными самих себя? или есть более простой способ?
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.09.2016, 22:06
Ответы с готовыми решениями:

Метод Дихотомии (итерационное вычисление нуля функции)
Считает сумму, но с ответом не сходится До какого момента нужно считать? #include...

Метод Конечных Разностей для уравнения в частных производных
Здравствуйте, требуется ваша помощь в нахождении ошибки в программе. Вычисляю по явной схеме....

Ищу источники информации по численному решению ДУ в частных производных
Знает ли кто-нибудь хорошую книгу или сайт по численному решению ДУЧП? Например, просто по...

Вычисление непрерывных дробей и выражений. Вычисление полиномов и их производных.
1. Чему равна знакочередующаяся сумма цифр числа n. 2. Даны натуральное число n и...

9
4814 / 2275 / 287
Регистрация: 01.03.2013
Сообщений: 5,933
Записей в блоге: 26
04.09.2016, 22:46 2
Подозреваю, что способов масса. Но мне то ФВП сразу вспоминаются
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
double e=0.001;  //точность
 
int main() {
    auto f = [](double x1,double x2,double x3) {return x1*x1*x1*x1*x1*x1 + 3*x2 + 2*x3*x3;};
    auto d1 = [](auto f) {
        return [&f](double x1,double x2,double x3) {return (f(x1+e,x2,x3)-f(x1,x2,x3))/e;};};
    auto d2 = [](auto f) {
        return [&f](double x1,double x2,double x3) {return (f(x1,x2+e,x3)-f(x1,x2,x3))/e;};};
    auto d3 = [](auto f) {
        return [&f](double x1,double x2,double x3) {return (f(x1,x2,x3+e)-f(x1,x2,x3))/e;};};
 
    std::cout << d1(f)(1,1,1) << "\n";
    std::cout << d1(d1(f))(1,1,1) << "\n";
    std::cout << d1(d1(d1(f)))(1,1,1) << "\n";
    std::cout << d1(d1(d1(d1(f))))(1,1,1) << "\n";
    std::cout << d3(f)(1,1,1) << "\n";
    std::cout << d3(d3(f))(1,1,1) << "\n";
}
ЗЫ метод первых разностей для оценки производных высших порядков весьма убог.
1
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
04.09.2016, 23:06 3
Лучший ответ Сообщение было отмечено cArmius как решение

Решение

Должно работать, особо не тестил:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
namespace detail {
 
constexpr double e = 0.000001;
 
constexpr double f(double x1, double x2, double x3) {
    return x1 + 3*x2 + 2*x3*x3;
}
 
} // end namespace detail
 
template <int N>
constexpr double calc(double x01, double x02, double x03)
{
    using detail::e;
    return (calc<N-1>(x01+e, x02, x03) - calc<N-1>(x01, x02, x03)) / e;
}
 
template <>
constexpr double calc<0>(double x1, double x2, double x3)
{
    return detail::f(x1, x2, x3);
}
 
///////////////////////////////////////////////////////////////////////////////
// for test:
 
using namespace detail;
 
constexpr double df1(double x01, double x02, double x03) {
    return (f(x01+e, x02, x03) - f(x01, x02, x03)) / e;
}
 
constexpr double df11(double x01, double x02 ,double x03) {
    return (df1(x01+e ,x02, x03) - df1(x01, x02, x03)) / e;
}
 
int main()
{
    std::cout << calc<2>(1.1, 2.22, 3.33) << "\n";
    std::cout << df11(1.1, 2.22, 3.33) << "\n";
 
    std::cout << calc<1>(1.1, 2.22, 3.33) << "\n";
    std::cout << df1(1.1, 2.22, 3.33) << "\n";
 
    std::cout << calc<0>(1.1, 2.22, 3.33) << "\n";
    std::cout << f(1.1, 2.22, 3.33) << "\n";
}
1
1386 / 1016 / 323
Регистрация: 28.07.2012
Сообщений: 2,804
04.09.2016, 23:39 4
cArmius, _Ivana, а мне вот такой товарищ в голову пришел...
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <functional>
#include <tuple>
 
using namespace std;
 
double e = 0.000001;  //точность
 
double f(double x1, double x2, double x3) {
    return x1 + 3 * x2 + 2 * x3*x3;
}
 
template<size_t L, typename Functor, typename... Args>
double df1(Functor func, Args ... args) { 
    std::tuple<Args &...> t(args...);
    double r = func(args...);
    get<L>(t) = get<L>(t) + e;
    return (func(args...) - r) / e;
}
 
int main() {
    cout << df1<2>(f, 0., 0., 0.5) << endl;
    auto next = [](double x1, double x2, double x3) {return df1<2>(f, x1, x2, x3); };
    cout << df1<2>(next, 0., 0., 0.5) << endl;
    return 0;
}
Как-то можно наверно избавиться от лямбды, но голова уже не варит.

Добавлено через 31 минуту
UPD:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <functional>
#include <tuple>
 
using namespace std;
 
double e = 0.00001;  //точность
 
double f(double x1, double x2, double x3) {
    return x1 + 3 * x2 + 2 * x3*x3;
}
 
template<typename Functor, typename... Args>
double df1(Functor func, Args ... args) {
    return func(args...);
}
 
template<size_t L, size_t... Ln, typename Functor, typename... Args>
double df1(Functor func, Args ... args) { 
 
    auto lm = [&](Args... args) {
        std::tuple<Args &...> t(args...);
        double r = func(args...);
        get<L>(t) = get<L>(t) + e;
        return (func(args...) - r) / e;
    };
    return df1<Ln...>(lm, args...);
 
}
 
int main() {
    cout << df1<2, 2>(f, 0., 0., 0.5) << endl;
    return 0;
}
Оно даже что-то считает... но я боюсь это отлаживать...
1
2756 / 1910 / 569
Регистрация: 05.06.2014
Сообщений: 5,560
05.09.2016, 00:48 5
Цитата Сообщение от cArmius Посмотреть сообщение
однако, я задумался о том, возможно ли считать производную от производной не так долго - для нахождения всех частных производных третьего порядка мне нужно написать уже не 9 а 27 функций. пусть это решается простым копипастом, но должен же существовать более простой метод?
1) Представляете функцию в форме любого понравившегося интерполяционного многочлена.
2) Взятие производной любой степени от многочлена, остается вам в качестве самостоятельного задания по школьному курсу алгебры.
0
0 / 0 / 0
Регистрация: 04.09.2016
Сообщений: 3
05.09.2016, 23:39  [ТС] 6
Цитата Сообщение от _Ivana Посмотреть сообщение
Подозреваю, что способов масса. Но мне то ФВП сразу вспоминаются

ЗЫ метод первых разностей для оценки производных высших порядков весьма убог.
выглядит совсем незнакомо, можно полное название метода, чтобы хоть погуглить? ну или просто пояснения к форме задания функций
был бы очень благодарен )

ну и так то да, я уже осознал что хотя бы из-за точности выходит беда ) эффективнее задать-таки формулами
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
double d2f(int n1, int n2, double x01,double x02,double x03){
double el=0.0001;   
  if(n1==1)if(n2==1)return (f(x01+el,x02,x03)-2*f(x01,x02,x03)+f(x01-el,x02,x03))/(el*el);
  if(n1==1)if(n2==2)return (f(x01+el,x02+el,x03)-f(x01-el,x02+el,x03)-f(x01+el,x02-el,x03)+f(x01-el,x02-el,x03))/(el*el);
  if(n1==1)if(n2==3)return (f(x01+el,x02,x03+el)-f(x01-el,x02,x03+el)-f(x01+el,x02,x03-el)+f(x01-el,x02,x03-el))/(el*el);
  if(n1==2)if(n2==1)return (f(x01+el,x02+el,x03)-f(x01-el,x02+el,x03)-f(x01+el,x02-el,x03)+f(x01-el,x02-el,x03))/(el*el);
  if(n1==2)if(n2==2)return (f(x01,x02+el,x03)-2*f(x01,x02,x03)+f(x01,x02-el,x03))/(el*el);
  if(n1==2)if(n2==3)return (f(x01,x02+el,x03+el)-f(x01,x02-el,x03+el)-f(x01,x02+el,x03-el)+f(x01,x02-el,x03-el))/(el*el);
  if(n1==3)if(n2==1)return (f(x01+el,x02,x03+el)-f(x01-el,x02,x03+el)-f(x01+el,x02,x03-el)+f(x01-el,x02,x03-el))/(el*el);
  if(n1==3)if(n2==2)return (f(x01,x02+el,x03+el)-f(x01,x02-el,x03+el)-f(x01,x02+el,x03-el)+f(x01,x02-el,x03-el))/(el*el);
  if(n1==3)if(n2==3)return (f(x01,x02,x03+el)-2*f(x01,x02,x03)+f(x01,x02,x03-el))/(el*el);
}


Добавлено через 3 минуты
Цитата Сообщение от notAll Посмотреть сообщение
Должно работать, особо не тестил:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
namespace detail {
 
constexpr double e = 0.000001;
 
constexpr double f(double x1, double x2, double x3) {
    return x1 + 3*x2 + 2*x3*x3;
}
 
} // end namespace detail
 
template <int N>
constexpr double calc(double x01, double x02, double x03)
{
    using detail::e;
    return (calc<N-1>(x01+e, x02, x03) - calc<N-1>(x01, x02, x03)) / e;
}
 
template <>
constexpr double calc<0>(double x1, double x2, double x3)
{
    return detail::f(x1, x2, x3);
}
 
///////////////////////////////////////////////////////////////////////////////
// for test:
 
using namespace detail;
 
constexpr double df1(double x01, double x02, double x03) {
    return (f(x01+e, x02, x03) - f(x01, x02, x03)) / e;
}
 
constexpr double df11(double x01, double x02 ,double x03) {
    return (df1(x01+e ,x02, x03) - df1(x01, x02, x03)) / e;
}
 
int main()
{
    std::cout << calc<2>(1.1, 2.22, 3.33) << "\n";
    std::cout << df11(1.1, 2.22, 3.33) << "\n";
 
    std::cout << calc<1>(1.1, 2.22, 3.33) << "\n";
    std::cout << df1(1.1, 2.22, 3.33) << "\n";
 
    std::cout << calc<0>(1.1, 2.22, 3.33) << "\n";
    std::cout << f(1.1, 2.22, 3.33) << "\n";
}

замечательно, это как раз то, что я пытался построить, огромное спасибо )

Добавлено через 1 минуту
Цитата Сообщение от nonedark2008 Посмотреть сообщение
cArmius, _Ivana, а мне вот такой товарищ в голову пришел...
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <functional>
#include <tuple>
 
using namespace std;
 
double e = 0.000001;  //точность
 
double f(double x1, double x2, double x3) {
    return x1 + 3 * x2 + 2 * x3*x3;
}
 
template<size_t L, typename Functor, typename... Args>
double df1(Functor func, Args ... args) { 
    std::tuple<Args &...> t(args...);
    double r = func(args...);
    get<L>(t) = get<L>(t) + e;
    return (func(args...) - r) / e;
}
 
int main() {
    cout << df1<2>(f, 0., 0., 0.5) << endl;
    auto next = [](double x1, double x2, double x3) {return df1<2>(f, x1, x2, x3); };
    cout << df1<2>(next, 0., 0., 0.5) << endl;
    return 0;
}
Как-то можно наверно избавиться от лямбды, но голова уже не варит.

Добавлено через 31 минуту
UPD:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <functional>
#include <tuple>
 
using namespace std;
 
double e = 0.00001;  //точность
 
double f(double x1, double x2, double x3) {
    return x1 + 3 * x2 + 2 * x3*x3;
}
 
template<typename Functor, typename... Args>
double df1(Functor func, Args ... args) {
    return func(args...);
}
 
template<size_t L, size_t... Ln, typename Functor, typename... Args>
double df1(Functor func, Args ... args) { 
 
    auto lm = [&](Args... args) {
        std::tuple<Args &...> t(args...);
        double r = func(args...);
        get<L>(t) = get<L>(t) + e;
        return (func(args...) - r) / e;
    };
    return df1<Ln...>(lm, args...);
 
}
 
int main() {
    cout << df1<2, 2>(f, 0., 0., 0.5) << endl;
    return 0;
}

Оно даже что-то считает... но я боюсь это отлаживать...
ух. я правильно понимаю, что для того чтобы понять как это работает мне нужно искать функции с неопределенным количеством переменных?
P.S. на самом деле, если не смотреть на название темы - это самый близкий ответ на вопрос, который я пытался задать, о комбинации функций от функций

Добавлено через 9 минут
Цитата Сообщение от Renji Посмотреть сообщение
1) Представляете функцию в форме любого понравившегося интерполяционного многочлена.
2) Взятие производной любой степени от многочлена, остается вам в качестве самостоятельного задания по школьному курсу алгебры.
в примере с производными - пожалуй
но вообще я пытался понять можно ли аккуратно построить комбинацию функций, не обязательно производных
0
1386 / 1016 / 323
Регистрация: 28.07.2012
Сообщений: 2,804
06.09.2016, 00:48 7
Цитата Сообщение от cArmius Посмотреть сообщение
ух. я правильно понимаю, что для того чтобы понять как это работает мне нужно искать функции с неопределенным количеством переменных?
Там все довольно безхитростно. В функцию df1 передается в шаблоне набор чисел - порядок взятия частных производных. Каждое число - номер аргумента функции. Вычисляем функцию в точке f(args), далее зворачиваем ссылки на эти аргументы в tuple, что бы просто взять L-тый из них и увеличить его на "e". И вот это все дело заворачиваем в лямбда-функцию и рекурсивно вызываем df1 уже с лямбдой для расчета следующей производной.
0
4814 / 2275 / 287
Регистрация: 01.03.2013
Сообщений: 5,933
Записей в блоге: 26
06.09.2016, 01:19 8
Цитата Сообщение от cArmius Посмотреть сообщение
но вообще я пытался понять можно ли аккуратно построить комбинацию функций, не обязательно производных
Производная - функциональный оператор. То есть, его аргумент - функция, и результат - функция. То, что вы называете "комбинацию функций". Возьмем для примера обычный косинус. Это функция из числа в число, поэтому можно сколько угодно раз композировать cos(cos(cos(.... x))), и вычислять это в цикле, потому что числовые значения являются в С++ гражданами первого класса - помимо всего прочего, они могут возвращаться из функций. Такой же подход с функциями сработает только, если в языке функция может быть таким же гражданином первого класса. В функциональных языках это с рождения так, а в остальных пытаются приклеить абстракции разной степени похожести.
0
0 / 0 / 0
Регистрация: 04.09.2016
Сообщений: 3
11.09.2016, 11:18  [ТС] 9
Цитата Сообщение от _Ivana Посмотреть сообщение
Производная - функциональный оператор. То есть, его аргумент - функция, и результат - функция. То, что вы называете "комбинацию функций". Возьмем для примера обычный косинус. Это функция из числа в число, поэтому можно сколько угодно раз композировать cos(cos(cos(.... x))), и вычислять это в цикле, потому что числовые значения являются в С++ гражданами первого класса - помимо всего прочего, они могут возвращаться из функций. Такой же подход с функциями сработает только, если в языке функция может быть таким же гражданином первого класса. В функциональных языках это с рождения так, а в остальных пытаются приклеить абстракции разной степени похожести.
то есть, в принципе, я могу создать класс, допустим, векторный V(3х1), и мастерить функции f:V->V
а если у меня есть функция вида f(g(х1,х2),x1,x2) где внутри функции f где-то используется g, то я могу вставлять её в f указателями на функцию

и, наверное, если я задам достаточно указателей на функции, я могу их переобозначать перед вызовом функции, где использую их, и использовать именно их внутри функции
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
double (*f1)(double,double);
...
double (*fn)(double,double);
 
double func(...){
abrakadabra=f1(f2(),...)+...;
}
 
int main(){
f1=g(x1,x2);
...
 
}
0
4814 / 2275 / 287
Регистрация: 01.03.2013
Сообщений: 5,933
Записей в блоге: 26
11.09.2016, 20:01 10
cArmius, если я правильно понимаю то, что вы написали - то нифига подобного Пока функция - не объект первого класса языка, у вас в принципе могут быть только лишь те функции, которые вы написали в коде и которые известны на этапе компиляции. Вы не можете создавать в рантайме новые функции, только вызывать скомпилированные с разными параметрами.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.09.2016, 20:01
Помогаю со студенческими работами здесь

Итерационное преобразование числа
На вход программе подается целое положительное число n. Если оно четное, делим на 2, если нечетное,...

Итерационное время стремится к нолю
Итерационное время в программе сортировки данных стремится к нолю. Это нормально или требуются...

Вычисление частных производных
помогите, проверьте укажите ошибки F(x1,x2) = c0+c1x1+c2x2+c12x1x2+c11x1^2+c22x2^2 мой вариант...

Уравнение в частных производных
Уважаемые коллеги! Не считает уравнение в частных производных (теплопроводность). В чем может...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru