Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Помогите с задачей / 7 сообщений из 7, страница 1 из 1
09.07.2009, 04:43:17
    #36080927
студентик
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с задачей
Задача взята из книги А. Шеня "Программирование теоремы и задачи". Решения задачи в книге не приводится. Если кто знает принцип, поясните его хотя бы в общих словах, или приведите ссылку
на источник, буду благодарен. Просто долго мучаюсь с задачей и не могу найти правильного решения.

Задача. Дана программа вычисления значения некоторого многочлена Р(х 1 , х 2 , ..., x n ), содержащая только комады присваивания. Их правые части - выражения, содержащие сложение, умножение, константы, переменные х 1 , х 2 , ..., x n и ранее встречавшиеся(в левой части) переменные. Доказать, что существует программа того же типа, вычисляющая все n частных производных, причем общее число арифмитических операций не более чем в С раз превосходит число арифметических операцийв исходной программе. Константа С не зависит от n.
[Указание: Можно считать что каждая комманда - сложение двух чисел, умножение двух чисел или умножение на константу. Использовать индукцию по числу команд, применяя индуктивное предположение к программе, получающейся отбрасывание первой команды.]
...
Рейтинг: 0 / 0
10.07.2009, 01:45:15
    #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
11.07.2009, 00:55:44
    #36085308
студентик
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с задачей
rmull, Спасибо.
...
Рейтинг: 0 / 0
11.07.2009, 04:44:38
    #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
11.07.2009, 05:55:15
    #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
11.07.2009, 17:52:45
    #36085550
студентик
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите с задачей
rmull, Большое спасибо, теперь стало намного понятнее.
...
Рейтинг: 0 / 0
11.07.2009, 23:38:57
    #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]