powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Помогите с задачей
7 сообщений из 7, страница 1 из 1
Помогите с задачей
    #36080927
студентик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Задача взята из книги А. Шеня "Программирование теоремы и задачи". Решения задачи в книге не приводится. Если кто знает принцип, поясните его хотя бы в общих словах, или приведите ссылку
на источник, буду благодарен. Просто долго мучаюсь с задачей и не могу найти правильного решения.

Задача. Дана программа вычисления значения некоторого многочлена Р(х 1 , х 2 , ..., x n ), содержащая только комады присваивания. Их правые части - выражения, содержащие сложение, умножение, константы, переменные х 1 , х 2 , ..., x n и ранее встречавшиеся(в левой части) переменные. Доказать, что существует программа того же типа, вычисляющая все n частных производных, причем общее число арифмитических операций не более чем в С раз превосходит число арифметических операцийв исходной программе. Константа С не зависит от n.
[Указание: Можно считать что каждая комманда - сложение двух чисел, умножение двух чисел или умножение на константу. Использовать индукцию по числу команд, применяя индуктивное предположение к программе, получающейся отбрасывание первой команды.]
...
Рейтинг: 0 / 0
Помогите с задачей
    #36083366
rmull
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я решал без индукции.

Сначала преобразуем команды как сказано в подсказке, т.е. чтобы каждая состояла из одного сложения или одного умножения. Пусть их число равно K.

Теперь построим графовую модель задачи. Граф будет DAG-ом, с помеченными дугами, из каждой вершины выходит от 0 до 2 дуг. n вершин будут соответствовать неизвестным x 1 , ..., x n . Рядом с ними можно подписать их векторы частных производных, каждый содержит все нули, кроме одной единицы. Ещё у нас будет K вершин, соответствующие командам, вернее, производным переменных, стоящих в левых частях команд.

Для команд вида
A = B + C
производная равна
A' = B' + C'
поэтому из вершины, соответствующей A', рисуем дуги в вершины B' и C' с метками = 1.

Для команд вида
A = B * C
производная равна
A' = B' * C + B * C'
из вершины A' рисуем дугу в B', помеченную C, и дугу в C', помеченную B.

Структура графа известна до выполнения алгоритма, а метки на дугах станут известны в ходе вычислений. Если мы найдём метки на дугах и будем вычислять для каждой вершины соответствующий вектор из n частных производных, то сложность получится O(N*(N+K)).

Но, если немного подумать, то можно заметить, что производную по x i можно найти так: если мы рассмотрим все пути, ведущие из корня в вершину x i , и для каждого перемножим метки на нём, и просуммируем всё, то получится искомая величина. И мы можем найти для каждой вершины такую сумму по всем путям из корня в данную вершину в сумме за O(N+K).

Понятно, что граф в явном виде в программе строить не обязательно. Он нужен просто для упрощения понимая сути алгоритма.
...
Рейтинг: 0 / 0
Помогите с задачей
    #36085308
студентик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rmull, Спасибо.
...
Рейтинг: 0 / 0
Помогите с задачей
    #36085362
студентик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rmullЯ решал без индукции.

Сначала преобразуем команды как сказано в подсказке, т.е. чтобы каждая состояла из одного сложения или одного умножения. Пусть их число равно K.

Теперь построим графовую модель задачи. Граф будет DAG-ом, с помеченными дугами, из каждой вершины выходит от 0 до 2 дуг. n вершин будут соответствовать неизвестным x 1 , ..., x n . Рядом с ними можно подписать их векторы частных производных, каждый содержит все нули, кроме одной единицы. Ещё у нас будет K вершин, соответствующие командам, вернее, производным переменных, стоящих в левых частях команд.

Для команд вида
A = B + C
производная равна
A' = B' + C'
поэтому из вершины, соответствующей A', рисуем дуги в вершины B' и C' с метками = 1.

Для команд вида
A = B * C
производная равна
A' = B' * C + B * C'
из вершины A' рисуем дугу в B', помеченную C, и дугу в C', помеченную B.

Структура графа известна до выполнения алгоритма, а метки на дугах станут известны в ходе вычислений. Если мы найдём метки на дугах и будем вычислять для каждой вершины соответствующий вектор из n частных производных, то сложность получится O(N*(N+K)).

Но, если немного подумать, то можно заметить, что производную по x i можно найти так: если мы рассмотрим все пути, ведущие из корня в вершину x i , и для каждого перемножим метки на нём, и просуммируем всё, то получится искомая величина. И мы можем найти для каждой вершины такую сумму по всем путям из корня в данную вершину в сумме за O(N+K).

Понятно, что граф в явном виде в программе строить не обязательно. Он нужен просто для упрощения понимая сути алгоритма.

А не могли бы вы, если вас, конечно, не затруднит, написать небольшой простой пример к приведенной выше теории. Просто у меня были некоторые практические наработки, хотелось бы узнать есть ли что схожее с приведенной идеей, а разобраться полностью с теорией, которую вы написали, еще не сумел.
...
Рейтинг: 0 / 0
Помогите с задачей
    #36085366
rmull
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
студентик
А не могли бы вы, если вас, конечно, не затруднит, написать небольшой простой пример к приведенной выше теории. Просто у меня были некоторые практические наработки, хотелось бы узнать есть ли что схожее с приведенной идеей, а разобраться полностью с теорией, которую вы написали, еще не сумел.

Пусть у нас есть такая функция, считающая полином от трёх переменных:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
double f(double x1, double x2, double x3) {
	double a = x1*x2;
	double b = x2+x3;
	double c = a*b;
	double d =  2 *b;
	double e = c+d;
	return e;

	// c = (x1*x2)*(x2+x3) = x1*x2*x2+x1*x2*x3
	// d =  2 *(x2+x3) =  2 *x2+ 2 *x3
	// e = x1*x2*x2+x1*x2*x3+ 2 *x2+ 2 *x3
}

Построим граф. Вершины обозначим x1p, x2p, x3p, ap, bp, cp, dp, ep.
Дуги:
ap -> x1p (вес = x2)
ap -> x2p (вес = x1)
bp -> x2p (вес = 1)
bp -> x3p (вес = 1)
cp -> ap (вес = b)
cp -> bp (вес = a)
dp -> bp (вес = 2)
ep -> cp (вес = 1)
ep -> dp (вес = 1)

Функция, считающая производные:
Код: plaintext
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.
double fp(double x1, double x2, double x3, double& x1p, double& x2p, double& x3p) {
	double a = x1*x2;
	double b = x2+x3;
	double c = a*b;
	double d =  2 *b;
	double e = c+d;

	// добавим переменные, соответствующие вершинам графа
	x1p = x2p = x3p =  0 ;
	double ap =  0 , bp =  0 , cp =  0 , dp =  0 , ep =  0 ;

	// теперь для каждой вершины находим 
	// сумму по всем дугам, ведущим в неё, произведений веса дуги на величину вершины, 
	// из которой идёт дуга
	ep =  1 ;
	dp +=  1 *ep;
	cp +=  1 *ep;
	bp +=  2 *dp;
	bp += a*cp;
	ap += b*cp;
	x3p +=  1 *bp;
	x2p +=  1 *bp;
	x2p += x1*ap;
	x1p += x2*ap;
	
	// производные теперь в x1p, x2p, x3p

	return e;
}

Можете вручную посчитать производные и сравнить найденные значения для различных x1, x2, x3.
Для каждой команды из первоначальной функции добавляется новая переменная и не более двух команд +=. Следовательно, объём нового кода линейно зависит от объёма старого.
...
Рейтинг: 0 / 0
Помогите с задачей
    #36085550
студентик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rmull, Большое спасибо, теперь стало намного понятнее.
...
Рейтинг: 0 / 0
Помогите с задачей
    #36085653
студентик
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
rmullстудентик
А не могли бы вы, если вас, конечно, не затруднит, написать небольшой простой пример к приведенной выше теории. Просто у меня были некоторые практические наработки, хотелось бы узнать есть ли что схожее с приведенной идеей, а разобраться полностью с теорией, которую вы написали, еще не сумел.

Пусть у нас есть такая функция, считающая полином от трёх переменных:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
double f(double x1, double x2, double x3) {
	double a = x1*x2;
	double b = x2+x3;
	double c = a*b;
	double d =  2 *b;
	double e = c+d;
	return e;

	// c = (x1*x2)*(x2+x3) = x1*x2*x2+x1*x2*x3
	// d =  2 *(x2+x3) =  2 *x2+ 2 *x3
	// e = x1*x2*x2+x1*x2*x3+ 2 *x2+ 2 *x3
}

Построим граф. Вершины обозначим x1p, x2p, x3p, ap, bp, cp, dp, ep.
Дуги:
ap -> x1p (вес = x2)
ap -> x2p (вес = x1)
bp -> x2p (вес = 1)
bp -> x3p (вес = 1)
cp -> ap (вес = b)
cp -> bp (вес = a)
dp -> bp (вес = 2)
ep -> cp (вес = 1)
ep -> dp (вес = 1)

Функция, считающая производные:
Код: plaintext
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.
double fp(double x1, double x2, double x3, double& x1p, double& x2p, double& x3p) {
	double a = x1*x2;
	double b = x2+x3;
	double c = a*b;
	double d =  2 *b;
	double e = c+d;

	// добавим переменные, соответствующие вершинам графа
	x1p = x2p = x3p =  0 ;
	double ap =  0 , bp =  0 , cp =  0 , dp =  0 , ep =  0 ;

	// теперь для каждой вершины находим 
	// сумму по всем дугам, ведущим в неё, произведений веса дуги на величину вершины, 
	// из которой идёт дуга
	ep =  1 ;
	dp +=  1 *ep;
	cp +=  1 *ep;
	bp +=  2 *dp;
	bp += a*cp;
	ap += b*cp;
	x3p +=  1 *bp;
	x2p +=  1 *bp;
	x2p += x1*ap;
	x1p += x2*ap;
	
	// производные теперь в x1p, x2p, x3p

	return e;
}

Можете вручную посчитать производные и сравнить найденные значения для различных x1, x2, x3.
Для каждой команды из первоначальной функции добавляется новая переменная и не более двух команд +=. Следовательно, объём нового кода линейно зависит от объёма старого.

Что-то подобное приходило в голову, только смущало количество переменных на команду, хотя по идее некие промежуточные результаты в ходе вычислений можно и не сохранять в отдельной переменной, если в ходе вычислений они не используются.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Помогите с задачей
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]