gifts2017

7.7.: Решаем систему линейных уравнений

Опубликовал Александр Рытов (Арчибальд) в раздел Программирование - Теория программирования

Метод Гаусса

     Вот здесь http://forum.infostart.ru/forum14/topic40487/  была попытка выяснить, кому и зачем может потребоваться решать в 1С систему линейных уравненний. Оказалось, что речь шла всего лишь об учебном задании.

     На самом деле, решать систему линейных уравнений приходится при расчете себестоимости услуг вспомогательных цехов ( см http://infostart.ru/public/61847/ ), когда эти цеха оказывают услуги, в том числе, друг другу.

Предлагается обработка, решающая методом Гаусса систему

     a1_1*x1+a1_2*x2+...+a1_N*xN = b1

             ........

     aN_1*x1+aN_2*x2+...+aN_N*xN = bN

     Сначала задаем размерность системы, затем в таблице выставляем коэффициенты (двойной клик по ячейке). Если интересно посмотреть процесс преобразования матрицы к верхнетреугольному виду по шагам - задаем паузу между шагами. Для сортировки строк используется "пузырьковый" метод от Д. Кнута.

     Если коэффициенты заданы как на первом скрине, по кнопке Решить получим второй скрин. Ответ округляется до второго знака (мы же с рублями работаем).

 

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Гаусс0.ert
.ert 40,00Kb
10.07.13
103
.ert 40,00Kb 103 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Александр Рытов (Арчибальд) 05.07.11 14:23
Решаем СЛАУ в 12 + 8 строк кода
2. Ийон Тихий (cool.vlad4) 05.07.11 14:28
(0) :D ну, блин - тока-тока набросал функцию приведения в треугольную матрицу...все блин, лучше пойду на обед нормально...Арчибальд кстати в качестве матрицы, что использовал? я ТЗ...
3. Ийон Тихий (cool.vlad4) 05.07.11 14:30
можно и нужно оптимизировать, но Арчибальд всю охоту отбил ;)
Для i=0 По N-1 Цикл

max = i;
Для j = i + 1 По N-1 Цикл
Если abs(ТЗ[j][i])>abs(ТЗ[max][i]) Тогда max=j КонецЕсли;
КонецЦикла;

Для k = i По N Цикл
temp = ТЗ[i][k];
ТЗ[i][k] = ТЗ[max][k];
ТЗ[max][k] = temp;
КонецЦикла;

Для j = i + 1 По N-1 Цикл
Для k = i По N Цикл
ТЗ[j][N+i-k] = ТЗ[j][N+i-k] - ТЗ[i][N+i-k]*ТЗ[j][i]/ТЗ[i][i];
КонецЦикла;
КонецЦикла;

КонецЦикла;

ну а дальше сделать обход снизу верх и найти корни
4. Александр Рытов (Арчибальд) 05.07.11 14:31
(2) Аналогично © Следствие ведут колобки.
У меня фукнции Гаусс и Пузырек были задействованы в конфе, стоявшей у нас до 2002 года. Я просто вытащил их оттуда...
5. Ийон Тихий (cool.vlad4) 05.07.11 14:34
(4) молодец! а у меня на delphi, просто переписал...давно думаю замутить ВК какую-нибудь, ибо вычисления нужны, а 1С-у мне кажется сложно они даются и потом округления...
6. Александр Рытов (Арчибальд) 05.07.11 14:34
(3) А не короче разве
Процедура Пузырек(Матр,Ж,Ю)
	ММ=Ю-1;
	НН=Ж;
	Пока ММ>=НН Цикл 
	 	Если Абс(Матр.ПолучитьЗначение(ММ+1,Ж))>Абс(Матр.ПолучитьЗначение(ММ,Ж)) Тогда
		    Матр.СдвинутьСтроку(-1,ММ+1);
		КонецЕсли;
	       ММ=ММ-1;
	КонецЦикла;
КонецПроцедуры //Пузырек
//__________________________________________________________­___________________
Процедура Гаусс(Матрица) 
	Состояние("Решение системы уравнений");
	Размер=Матрица.КоличествоСтрок(); 
	Для Ж=1 По Размер-1 Цикл
		Пузырек(Матрица,Ж,Размер);
		Для КК=Ж+1 ПО Размер Цикл
			Коэфф=Матрица.ПолучитьЗначение(КК,Ж)/Матрица.ПолучитьЗначение(Ж,Ж);
			Для ВВ=Ж По Размер+1 Цикл
				Матрица.УстановитьЗначение(КК,ВВ,Матрица.ПолучитьЗначение(КК,ВВ)-Коэфф*Матрица.ПолучитьЗначение(Ж,ВВ));
			КонецЦикла;
		КонецЦикла;
	КонецЦикла; 
КонецПроцедуры //Гаусс(Матрица)
...Показать Скрыть
7. Ийон Тихий (cool.vlad4) 05.07.11 14:37
(6) в общем-то короче :D я правда 8 пользуюсь...я знаю у меня лишние циклы, можно доделать,...но да ладно...
8. Ийон Тихий (cool.vlad4) 05.07.11 14:43
Кстати для многих языков программирования есть оптимизированные разные алгоритмы под этот язык...неплохо бы иметь такую подборку для 1С, заточенную под 1С....пригодится...
9. Александр Рытов (Арчибальд) 05.07.11 14:47
(8) Мне время от времени приходит в голову мысль перевести алгоритмы из пары томов Кнута на 1С. Но эта мысль никого не застает и уходит... :o
10. Игорь Исхаков (Ish_2) 05.07.11 15:22
За свежую струю на ИС +.
Но текст не стал даже смотреть. Слишком старо. Все циклы, циклы ...
Дождусь смельчака , реализующего решение на запросах.
Не то чтобы эффективней - просто интереснее.
11. Ийон Тихий (cool.vlad4) 05.07.11 15:29
(10) Как раз не решался задать вопрос реально ли это сделать на запросах...
12. Александр Рытов (Арчибальд) 05.07.11 15:37
(11) А запрос - к кому? В смысле, к каким данным?
13. Александр Рытов (Арчибальд) 05.07.11 15:39
(10)
- Василь Иваныч, ракеты привезли!
- А седла к ним?
14. Ийон Тихий (cool.vlad4) 05.07.11 15:49
(12) неважно, когда работаешь с 1С, запросомания это нормально ;) ...
ЗЫ да, теперь фраза -вот это у тебя запросы, - носит двусмысленный оттенок :D ....
15. Игорь Исхаков (Ish_2) 05.07.11 15:57
(12)Матрицу вполне можно описать справочником (таблицей) НомерСтроки,НомерСтолбца, Значение.
К этой таблице и запрос.
16. Александр Рытов (Арчибальд) 05.07.11 16:01
(14)
теперь фраза -вот это у тебя запросы, - носит двусмысленный оттенок
Касательно Ish_2 - односмысленный...
17. Александр Рытов (Арчибальд) 05.07.11 16:05
(15) Это уж изврат. Алгоритм Гаусса суть помесь сортировки с вычитанием. Ладно, вычитание, но уж сортировать справочник...
18. Ийон Тихий (cool.vlad4) 05.07.11 16:11
Необязательно справочник, можно и временную таблицу использовать, но все это, конечно, изврат, главное в практике не нужный...меня больше другое интересует...возможность сделать более точное решение...к примеру (1/3)*3 - даст 1 плюс малую дельту...помню в универе нам говорили, что в maple есть возможность аналитических решений, интересно будет подумать как реализовать аналитическое решение...
19. Александр Рытов (Арчибальд) 05.07.11 16:17
(18) Могу аналитическое на 1С :D
А оно надо?
20. Ийон Тихий (cool.vlad4) 05.07.11 16:19
(19) скажи только как, метод, чисто из любопытства
21. Игорь Исхаков (Ish_2) 05.07.11 16:20
(17) Что ты понимаешь в извращениях ? В извратах надо знать толк !
Ты рассматриваешь данные отвлеченно. Дескать, данные - они данные и есть . ТЗ и чего тут думать ?
Я же прежде всего рассматриваю данные как некоторую таблицу , хранящуюся на сервере.
Раз она хранится на сервере , то эффективнее всего, в общем случае , обрабатывать ее там же на сервере.
Не перегоняя её в ТЗ на стороне клиента. Т.е. использовать язык запросов.

В этом смысл изврата по реализации метода Гаусса языком запросов.
Пусть даже такая попытка будет неудачной - всё равно это интереснее чем повторять известные еще при царе Горохе реализации на языке 1с.
22. Ийон Тихий (cool.vlad4) 05.07.11 16:24
(21) если я правильно понял, тогда лучше использовать SQL язык запросов (если база файловая, то разницы не будет, циклы или нет), + хранимую процедуру, думаю это имеет смысл и сделать как мне кажется проще(в принципе можно на каком-нибудь языке написать и прикрутить к sql)
23. Игорь Исхаков (Ish_2) 05.07.11 16:30
24. Александр Рытов (Арчибальд) 05.07.11 16:34
(20) Работа с текстами и интерпретация текстовых выражений. Ну, типа
а_1_1, а_1_2, в_1;
а_2_1, а_2_2, в_2

Превращаем в
а_1_1, а_1_2, в_1;
*, а_2_2-(а_1_2*а_2_1/а_1_1), в_2-(в_1*а_2_1/а_1_1)

И так далее. Интерпретация нужна, чтобы на ноль не делить (вовремя остановиться).
25. Ийон Тихий (cool.vlad4) 05.07.11 16:38
(24) в принципе я так и думал, в 1С как-то нет желания с этим возится, смысла действительно нет
(23) ок, будет время попробую,
26. Александр Рытов (Арчибальд) 05.07.11 16:46
27. Александр Рытов (Арчибальд) 05.07.11 16:55
(21) Не думаю, что данные - это обязательно таблица. Не хранит же 1С двумерный массив как набор кортежей. (Хотя, от них можно и этого ожидать. Что-то вроде временной таблицы).
Другое дело, что в реальной задаче для заполнения массива я использовал (естественно) запрос.
28. Игорь Исхаков (Ish_2) 05.07.11 17:07
(27) Если ты реляционный Субд-шник , то данные - это всегда таблица , пусть даже с одной записью.
29. Александр Рытов (Арчибальд) 05.07.11 17:15
(28) Не реляционный, а восьмерочный - возможно. И все равно, не могу себе представить, что литеральное число или строка хранятся в виде таблицы.
30. Игорь Исхаков (Ish_2) 05.07.11 17:21
(29) Выражение "Не реляционный, а восьмерочный - возможно." - не имеет смысла.
Рассматриваем 8-ку только как приложение к реляционной СУБД : Oracle,MSSQL,DB2.
Все данные 8-ки хранятся только в БД.
Файловый вариант я не рассматриваю.
31. Владимир (hogik) 05.07.11 21:13
В (15) написано:
"Матрицу вполне можно описать справочником (таблицей) НомерСтроки,НомерСтолбца, Значение. К этой таблице и запрос."(с)
В (21) написано:
"Я же прежде всего рассматриваю данные как некоторую таблицу , хранящуюся на сервере.
Раз она хранится на сервере , то эффективнее всего, в общем случае , обрабатывать ее там же на сервере."(с)


Игорь.
Для получение "матрицы" придётся её сначала "собрать" по базе данных, схема которой описывает предметную область. А потом уже выполнять "К этой таблице и запрос"(с). Ведь, такая "матрица" (таблица) не может и не должна существовать постоянно в БД. Именно этим и будет загружен сервер БД - тупой работой по перелопачиванию данных нескольких таблиц в "матрицу". Т.е. сервер будет решать свои проблемы - преобразовывать данные под удобства их обработки запросным ЯМД. Но тогда проще и логичней собрать "матрицу", например, в таблицу значений и порешить задачу как это сделано в данной публикации. Кстати, распределить нагрузку сети, в целом, на мозги рабочей станции. Если встаёт вопрос (проблема) размеров такой "матрицы", то это решается простейшим алгоритмом поддержки "динамических массивов" рабочими файлами на стороне клиента (рабочей станции).

Ссылка для ознакомления: http://blogerator.ru/page/nosql-vvedenie-v-teoriju-bd
32. Игорь Исхаков (Ish_2) 05.07.11 23:59
В (21) речь шла об извращениях.
Когда извращение (реализация метода Гаусса на SQL) представяет итерес - для меня, конечно.
И когда извращение (обработка Арчибальда) не представляет интереса -для меня, конечно.

При решении реальной же задачи для вполне оределенной предметной области - подходы ,конечно, могут быть разными.
33. Владимир (hogik) 06.07.11 00:14
34. Ийон Тихий (cool.vlad4) 06.07.11 10:04
(31) ага, тоже так думаю, просто не стал вступать в дискуссию
ЗЫ насчет запросов и алгоритмов - плохая практика переносить задачи сервера приложений на сервер БД...
35. vkr (vkr) 06.07.11 10:06
(9) Лучше из 2 тома - нормальный генератор случайных чисел (если я правильно помню...) :)
А сортировка и поиск - да ну их... :)
36. Ийон Тихий (cool.vlad4) 06.07.11 10:09
(35) скорость вычислений в 1С сводит все на нет...лучше сделать это на ВК, а в других языках уже давно это сделано
37. Александр Рытов (Арчибальд) 06.07.11 10:24
(35)
Т.1. Основные алгоритмы (в т.ч. деревья, списки и т.д.)
Т.2. Получисленные алгоритмы (в т.ч. случайные числа)
Т.3. Сортировка и поиск.
OFF для тех, у кого нет Кнута - упражнение из введения.
Докажите, что если n - целое число, n > 2, то уравнение x**n + y**n = z**n не имеет решения в целых положительных числах x, y, z.
38. Игорь Исхаков (Ish_2) 06.07.11 10:29
39. Ийон Тихий (cool.vlad4) 06.07.11 10:33
(37) меня тоже повеселило упражнение в свое время, ....кстати кажется т.Ферма уже доказали....надо погуглить...
40. Александр Рытов (Арчибальд) 06.07.11 10:34
41. Игорь Исхаков (Ish_2) 06.07.11 11:36
(33) Спасибо , Владимир. Прочитал и вытер слезу.
Возможно ли решить систему линейных уравнений запросом?
Дано:
- таблица А с тремя полями: номер строки, номер столбца, коэффициент
- таблица Б с двумя полями: номер строки, свободный член
- все значения заполнены
- система имеет единственное решение
Требуется:
вывести набор данных из двух столбцов: номер переменной, значение.
Текст запроса не должен зависеть от количества переменных



Ответ - можно.
Найти нормальное псевдорешение А(m,n)x=b,где А(m,n)- некая рациональня матрица.
42. Ийон Тихий (cool.vlad4) 06.07.11 12:00
Честно говоря от мисты большего и не ждал...поток всяких мыслей и сознания...четко сформулированной задачи нет...если говорить про sql - то это уже не первая попытка http://www.bigresource.com/Tracker/Track-ms_sql-hdDNfwz0/
ЗЫ к сожалению я очень ленивый прагматик, потому как для меня смысла делать на запросах нет, то не буду
43. Владимир (hogik) 06.07.11 16:20
(41)
"Прочитал и вытер слезу."(с)
И это были слёзы счастья... :-)
P.S. Лучше читайте ссылку из (31) сообщения.
44. Ийон Тихий (cool.vlad4) 06.07.11 17:14
(43) еще вчера читал...баловался как couchdb, так и mongodb...а в статье одна вода...
45. Ийон Тихий (cool.vlad4) 06.07.11 17:15
по крайней мере - автор говорит, что какие-то глобалы круче, а чем и в каких случаях непонятно...
46. Владимир (hogik) 06.07.11 17:22
(44)
"баловался как couchdb, так и mongodb...а в статье одна вода..."(с)
Я проверил ссылку - работает и отсылает куда и планировалось.
Только эта публикация не про couchdb/mongodb... :-(
47. Ийон Тихий (cool.vlad4) 06.07.11 17:23
(46) а где в моем комменте написано, что эта статья про эти БД?
48. Ийон Тихий (cool.vlad4) 06.07.11 17:26
(46) В статья явный упор на то, что какие крутые БД GT.M и Cache, только вот практического применения там нет, ссылок на док почти нет, да и вообще доков на эти БД мало...может действительно эти БД хороши...пускай...
49. Ийон Тихий (cool.vlad4) 06.07.11 17:33
50. Ийон Тихий (cool.vlad4) 06.07.11 17:36
причем здесь правда 1С...непонятно...
51. Владимир (hogik) 06.07.11 17:43
(48)
Нет там никакого упора на "крутые БД". Там информация о "тупиковом" пути реляционной модели СУБД снабжённой "запросным" ЯМД. Ссылка дана в тему от Игоря "Мы пишем з...".
(50)
"причем здесь правда 1С...непонятно..."(с)
Печально, что непонятно. :-(
Цитата от Игоря из (30) сообщения: "Рассматриваем 8-ку только как приложение к реляционной СУБД : Oracle,MSSQL,DB2.".

P.S. Хотя, Вы правы - "...пускай..."(с)...
52. Ийон Тихий (cool.vlad4) 06.07.11 17:49
(51) просто для меня связь с сообщениями Игоря была не так очевидна, потому так и сказал.....о тупиковом не знаю, мне кажется в каждом случае по разному, nosql не панацея и nosql - "это не только sql", по теореме CAP у Nosql решений проблемки с согласованностью данных, в системах как 1С это в общем не очень хорошо...хотя плюсы есть...почему сказал балуюсь couchdb - там есть нативный restful интерфейс, что позволяет его соединить с 1С, плюс там клевая система notification...есть мысли по поводу реализации интернет решения с реальным(близким) временем взаимодействия с 1С...
53. Владимир (hogik) 06.07.11 17:58
(52)
Для меня "NoSQL" - имя нарицательное. ВажнО - "это не только sql"(с).
О чем и говорю - давно и занудно... :-( Уж, очень хочется ЭТО донести до Игоря. Но, думаю, МЫ всё пытаемся ЭТО нанизывать на модель "1С 8.х". Беда...
54. Ийон Тихий (cool.vlad4) 06.07.11 18:00
так, что мне кажется nosql решения подходят для разреженных данных - как например в вебе, в различных сервисах, кэширование, может быть даже в анализе данных(data mining),...а как использовать на практике в системах 1С(чисто теоретически), честно говоря не знаю...разве, что вспомогательные сервисы(чат,анализ метаданныхх)
55. Ийон Тихий (cool.vlad4) 06.07.11 18:01
(53) это не специально, я свою фамилию пишу с маленькой буквы :D
56. Игорь Исхаков (Ish_2) 06.07.11 18:04
(51),(52) Владимир ,как обычно, зятянул свою грустную песню :
1. реляционные БД -тупик в развитии
2. Запрос как средство обращения к БД - недоразумение.

Вот скоро придут альтернативные СУБД и увеличат свою долю на рынке с 0.1% до 0.2%.
Как жить дальше 1с-никам ... куды бечь ?
57. Ийон Тихий (cool.vlad4) 06.07.11 18:14
(56) на самом деле надо надо быть как китайцы, брать отовсюду только хорошее :D я лично считаю, что в 1С нужна другая система запросов...интегрированная в язык...чтоб отладка была, чтоб гибкость была...я понимаю это сложно, но делать язык запросов чем-то отдаленно напоминающий sql и не являтся при этом СУБД для меня странно...все наоборот уходят в объекты...
58. Игорь Исхаков (Ish_2) 06.07.11 18:25
(57) Кхы.. кхы... Воздержусь от комментариев.
59. Владимир (hogik) 06.07.11 18:25
(54)
Повторюсь еще N-раз. При наличии в СУБД различных "моделей" БД и ЯМД не требуется, например, "средний уровень" (т.н. сервер приложений).И решаются задачи от Игоря в теме "Мы пишем з..." - элементарно...
А реляционная модель и только "запросный" ЯМД - это ошибка в СУБД-строении, приводящая к порождению многоуровневых монстров типа "1С 8.х". Вроде, об этом уже столько сказано (и сделано), что агрессивно восторгаться SQL-ем (фраза для Игоря) уже и неприлично... ;-) А пытаться решать ВСЕ задачи, только запросами - глупо...
(56)
"Как жить дальше 1с-никам ... куды бечь ?"(с)
Игорь, "бечь" всегда есть куда... ;-)
60. Ийон Тихий (cool.vlad4) 06.07.11 18:29
(59)
А пытаться решать ВСЕ задачи, только запросами
о чем я и намекал

(58) все это не более кухонный разговор, не надо важничать, тем более, что в этом нет резона...linq о чем-нибудь говорит?
61. Игорь Исхаков (Ish_2) 06.07.11 18:32
(60) Поважничаю маленько, чего там : "А ты Гришку Мотовилова знаешь ?"
62. Александр Рытов (Арчибальд) 07.07.11 09:32
(32) Сорвали меня с места, выпал из обсуждения.
Итак, в извратах надо знать толк. Я толку в извратах не знаю, потому и не занимаюсь оными. Выложенная обработка - просто кусочек модуля формы реального документа из реальной конфигурации. Интересно, неинтересно - система уравнений должна быть решена. Тебе интересно было бы извратиться, мне интересно решить практическую задачу. Я занимаюсь созданием данных и записью их в базу.

Экстраполируя твой подход: что мы имеем при проведении многострочного документа? Вполне очевидную таблицу, а значит, надо ее обрабатывать запросом. Перебор строк в цикле - это так скучно!
Словом, подход потребителя информации. Юзера БД.
Ну, а я уж останусь создателем. В неизвращенной форме и без цинизма.
Прикрепленные файлы:
63. Игорь Исхаков (Ish_2) 07.07.11 09:37
(62) Ок. Я до сих пор не понимаю как соотносятся решение СЛАУ и расчет себестоимости.
Описать задачу сможешь ?
65. Ийон Тихий (cool.vlad4) 07.07.11 10:24
в принципе кому интересно добавлю, если есть потребность быстро что-то решить и не думать о алгоритмах, есть wolfram alpha (те кто делает matematica) - там все написано, restful, api, 2000 запрсов в месяц (можно создать несколько акков)
66. Ийон Тихий (cool.vlad4) 07.07.11 10:30
да кстати там есть binding под разные языки (собственно я под net пару раз использовал)...желающие могут прикрутить к 1С...я в 1С не силен, мне лениво
67. Игорь Исхаков (Ish_2) 07.07.11 11:01
(62) Из статьи следует , что бухгалтеры и программисты ,колдующие при закрытии счетов 20,23,25,26 - просто морочат голову. И как бы они не хитрили в этой процедуре ("морща лоб и щуря глаза") -
в любом случае они решают СЛАУ методом простой итерации,
Который, разумеется , предполагает существенную погрешность решения (при 1-2 итерациях).
Ты читал только статью ? А книгу читал ?
68. Александр Рытов (Арчибальд) 07.07.11 11:10
(67) Я делал закрытие в 2001 году. Статья появилась гораздо позже, и ничего нового я в ней для себя не нашел. Книга же и вовсе только в прошлом году вышла, и я пока думаю, стоит ли ее покупать.
Кстати, та самая погрешность у меня называется невязкой. На картинке - 4 копейки. Это максимум модуля остатков по субконто 23 счета после закрытия месяца. В течение 2002 года колебания по месяцам были от 2 до 5 копеек.
69. Ийон Тихий (cool.vlad4) 07.07.11 11:17
(68) а на практике, Арчибальд, всегда используешь метод Гаусса?
70. Ийон Тихий (cool.vlad4) 07.07.11 11:22
раз уж я говорил про интернет сервисы, вот еще один, тоже с rest-ом, что позволит легко использовать в 1С, (35) генератор случайных чисел http://www.random.org/clients/http/ ... как уверяют true random number....вот пример запроса http://www.random.org/integers/?num=10&min=1&max=6&col=1&base=10&format=plain&rnd=new
71. Игорь Исхаков (Ish_2) 07.07.11 11:24
(68) Что значит невязка= 0.04 ? Невязка - это скаляр ?
Ты уж растолкуй , что понимается под невязкой.
Вообще-то вектор невязки для системы Ах=b определяется как b-Ax.
72. Игорь Исхаков (Ish_2) 07.07.11 11:28
(68) Почему метод Гаусса ? Можно привести тысячу причин почему система может быть близкой к вырожденной (определитель матрицы А det(A)~ 0). И что тогда ?
73. Александр Рытов (Арчибальд) 07.07.11 11:48
(71) Да, невязка - вектор. У меня не "настояшая" невязка, а максимум модуля "координат" вектора.
(72) В контексте расчета вторичных затрат равенство нулю определителя означает, что в матрицу взаимных услуг включены подразделения, не участвующие в этом процессе (это в запросе к данным отсеивается)
(68) Ну, не считать же определители (я имею в виру решение СЛАУ вручную)
74. Игорь Исхаков (Ish_2) 07.07.11 11:58
(73)
1. У тебя "невязка" похоже - даже не евклидова норма ||b-Ax|| , а простая сумма координат вектора невязки.
2. Я тебе запросто подброшу примерчик 10х10 с неравным 0 определителем. И погрешность будет очень велика.
Впрочем , проблема плохой обусловленности системы - проблема не твоя , а общая.
75. Александр Рытов (Арчибальд) 07.07.11 11:59
Посмотрел, как решают СЛАУ в УПП :D
// Решает систему линейных уравнений методом простых итераций (метод Якоби)
//
Функция РешитьСЛУБезИспользованияВременныхТаблиц(ДатаНач, ДатаКон, РегламентныйДокумент, РегистрУчета, ВидОтраженияВУчете, МенеджерВременныхТаблиц,СтруктураПараметров,ОперацияРасчетаСебестоимостиВыпуска)
	
	Перем МассивСвободныхЧленов, МассивСвободныхЧленовСтоимостьНУ, МассивСвободныхЧленовПостояннаяРазница;
	
	// Стоимость товара на складе равна стоимости, полученной извне (например, при покупке товара) плюс начальный остаток
	// плюс стоимость товара перемещенного с других складов, умноженная на количество перемещенного товара
	//
	// Это можно представить в виде СЛУ
	// K(1) * X(1) = S(1) + K(2) * X(2) + K(3) * X(3) + ... + K(j) * X(j)
	// K(2) * X(2) = S(1) + K(1) * X(1) + K(3) * X(3) + ... + K(j) * X(j)
	// ...
	// K(i) * X(i) = S(i) + K(1) * X(1) + K(2) * X(2) + ... + K(j) * X(j)
	//
	// где
	//	K(i) - количество товара на складе i
	//	X(i) - стоимость товара на складе i
	//	K(j) - количество перемещенного товара со склада j на склад i
	//	X(j) - стоимость товара на складе j
	//	S(i) - стоимость товара, полученного извне плюс начальный остаток на складе i
	
	// При решении уравнения используются следующие данные
	//  S(i)/K(i) 	- берется средняя стоимость внешних поступлений из регистра УчетЗатрат 
	//					(перед расчетом помещается в регистр УзлыКорректировкиСтоимостиСписания)
	//  K(i) 		- берется общее количество поступления из регистра УчетЗатрат 
	//					(перед расчетом помещается в регистр УзлыКорректировкиСтоимостиСписания)
	//	K(j) 		- берутся движения "расход" из регистра УчетЗатрат
	//	X(j) 		- берется из решения предыдущей итерации (для первой итерации берется S(i)/K(i))
	
	
	Запрос = Новый Запрос;
	Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
	Запрос.УстановитьПараметр("Регистратор", РегламентныйДокумент);
	Запрос.УстановитьПараметр("ДатаНач",     ДатаНач);
	Запрос.УстановитьПараметр("ДатаКон",     ДатаКон);
	
	//Сформируем список состояний
	КоличествоУравненийСЛУ = СформироватьДвиженияПоРегиструУзлыКорректировкиСтоимостиСпис­ания(
		Запрос,
		РегистрУчета,
		ВидОтраженияВУчете,
		СтруктураПараметров,
		ОперацияРасчетаСебестоимостиВыпуска
	);
	
	Если КоличествоУравненийСЛУ = 0 Тогда
		Возврат Ложь;
	КонецЕсли;	
	
	МаксимальноеКоличествоИтераций = СтруктураПараметров.МаксимальноеКоличествоИтераций;
	ТребуемаяТочность = СтруктураПараметров.СреднееОтклонениеСЛУ; 
	
	// Получим S(i)/K(i)
	ЗаполнитьМассивыСвободныхЧленов(МассивСвободныхЧленов, МассивСвободныхЧленовСтоимостьНУ, МассивСвободныхЧленовПостояннаяРазница, ВидОтраженияВУчете, Запрос);
	КоличествоУравненийСЛУ = МассивСвободныхЧленов.Количество();
	
	// Выберем начальное приближение X(j)
	ТекущееРешение = СкопироватьМассив(МассивСвободныхЧленов);
	Если ВидОтраженияВУчете = Перечисления.ВидыОтраженияВУчете.ОтражатьВРегламентированномУчете Тогда
		ТекущееРешениеСтоимостьНУ       = СкопироватьМассив(МассивСвободныхЧленовСтоимостьНУ);
		ТекущееРешениеПостояннаяРазница = СкопироватьМассив(МассивСвободныхЧленовПостояннаяРазница);
	КонецЕсли; 
	
	// Получим K(j) для всех уравнений системы
	МассивСЛУ = ПолучитьСЛУ(ВидОтраженияВУчете, КоличествоУравненийСЛУ, Запрос);
	
	// По умолчанию примем за решение начальное приближение
	НовоеРешение = СкопироватьМассив(ТекущееРешение);
	Если ВидОтраженияВУчете = Перечисления.ВидыОтраженияВУчете.ОтражатьВРегламентированномУчете Тогда
		НовоеРешениеСтоимостьНУ       = СкопироватьМассив(ТекущееРешениеСтоимостьНУ);
		НовоеРешениеПостояннаяРазница = СкопироватьМассив(ТекущееРешениеПостояннаяРазница);
	КонецЕсли; 
	
	// Решим СЛУ методом простых итераций
	ТекущееОтклонение = КоличествоУравненийСЛУ;
	
	КоличествоИтераций = 0;
	
	Пока (ТекущееОтклонение/КоличествоУравненийСЛУ > ТребуемаяТочность)
		И (КоличествоИтераций < МаксимальноеКоличествоИтераций) Цикл
		
		ТекущееОтклонение   = 0;
		ТекущееОтклонениеПР = 0;
		ТекущееОтклонениеНУ = 0;
		
		Для НомерТекущегоУравнения = 0 По МассивСЛУ.Количество() - 1 Цикл
			
			Если МассивСЛУ[НомерТекущегоУравнения] = Неопределено Тогда
				// Для этой переменной считать ничего не нужно, первое приближение - это и есть точное решение
				Продолжить;
			КонецЕсли;				
			
			// Получим первое выражение уравнения: S(i)/K(i)
			НовоеРешение[НомерТекущегоУравнения] = МассивСвободныхЧленов[НомерТекущегоУравнения];
			Если ВидОтраженияВУчете = Перечисления.ВидыОтраженияВУчете.ОтражатьВРегламентированномУчете Тогда
				НовоеРешениеСтоимостьНУ[НомерТекущегоУравнения]       = МассивСвободныхЧленовСтоимостьНУ[НомерТекущегоУравнения];
				НовоеРешениеПостояннаяРазница[НомерТекущегоУравнения] = МассивСвободныхЧленовПостояннаяРазница[НомерТекущегоУравнения];
			КонецЕсли; 
			
			// Добавим к уравнению остальные выражения: (K(1) * X(1) + K(2) * X(2) + ... + K(j) * X(j)) / K(i)
			Для Каждого ТекущийКоэффициент Из МассивСЛУ[НомерТекущегоУравнения] Цикл
				КоличествоПеремещенногоТовара = ?(ТекущийКоэффициент.ЗначениеКоэффициента = 0, ТекущийКоэффициент.Стоимость, ТекущийКоэффициент.ЗначениеКоэффициента);
				
				НовоеРешение[НомерТекущегоУравнения] = ДобавитьСтоимостьТовараПеремещенногоСДругихСкладов(
															НовоеРешение[НомерТекущегоУравнения],
															КоличествоПеремещенногоТовара, // K(j)
															ТекущийКоэффициент.УзелКоличество, // K(i)
															ТекущееРешение[ТекущийКоэффициент.НомерПеременной]); // X(j)
				
				Если ВидОтраженияВУчете = Перечисления.ВидыОтраженияВУчете.ОтражатьВРегламентированномУчете Тогда
					КоличествоПеремещенногоТовара = ?(ТекущийКоэффициент.КоличествоНУ = 0, ТекущийКоэффициент.СтоимостьНУ + ТекущийКоэффициент.ПостояннаяРазница, ТекущийКоэффициент.КоличествоНУ);
					
					НовоеРешениеСтоимостьНУ[НомерТекущегоУравнения] = ДобавитьСтоимостьТовараПеремещенногоСДругихСкладов(
																			НовоеРешениеСтоимостьНУ[НомерТекущегоУравнения],
																			КоличествоПеремещенногоТовара, // K(j)
																			ТекущийКоэффициент.УзелКоличествоНУ, // K(i)
																			ТекущееРешениеСтоимостьНУ[ТекущийКоэффициент.НомерПеременной]); // X(j)
																			
					НовоеРешениеПостояннаяРазница[НомерТекущегоУравнения] = ДобавитьСтоимостьТовараПеремещенногоСДругихСкладов(
																				НовоеРешениеПостояннаяРазница[НомерТекущегоУравнения],
																				КоличествоПеремещенногоТовара, // K(j)
																				ТекущийКоэффициент.УзелКоличествоНУ, // K(i)
																				ТекущееРешениеПостояннаяРазница[ТекущийКоэффициент.НомерПеременной]); // X(j)
					
					
				КонецЕсли; 
			КонецЦикла;	
			
			АА = НовоеРешение[НомерТекущегоУравнения] - ТекущееРешение[НомерТекущегоУравнения];
			Если АА < 0 Тогда
				АА = -АА;
			КонецЕсли;
			ТекущееОтклонение = ТекущееОтклонение + АА;
			
			Если ВидОтраженияВУчете = Перечисления.ВидыОтраженияВУчете.ОтражатьВРегламентированномУчете Тогда
				АА = НовоеРешениеСтоимостьНУ[НомерТекущегоУравнения] - ТекущееРешениеСтоимостьНУ[НомерТекущегоУравнения];
				Если АА < 0 Тогда
					АА = -АА;
				КонецЕсли;
				ТекущееОтклонениеНУ = ТекущееОтклонениеНУ + АА;
			
				АА = НовоеРешениеПостояннаяРазница[НомерТекущегоУравнения] - ТекущееРешениеПостояннаяРазница[НомерТекущегоУравнения];
				Если АА < 0 Тогда
					АА = -АА;
				КонецЕсли;
				ТекущееОтклонениеПР = ТекущееОтклонениеПР + АА;
			КонецЕсли; 
			
		КонецЦикла;
		
		ТекущееОтклонение = Макс(ТекущееОтклонение, ТекущееОтклонениеПР, ТекущееОтклонениеНУ);
		
		// Запомним решение текущей итерации чтобы использовать его в следующей итерации
		ТекущееРешение = СкопироватьМассив(НовоеРешение);
		Если ВидОтраженияВУчете = Перечисления.ВидыОтраженияВУчете.ОтражатьВРегламентированномУчете Тогда
			ТекущееРешениеСтоимостьНУ       = СкопироватьМассив(НовоеРешениеСтоимостьНУ);
			ТекущееРешениеПостояннаяРазница = СкопироватьМассив(НовоеРешениеПостояннаяРазница);
		КонецЕсли; 
		
		КоличествоИтераций = КоличествоИтераций + 1;
			
	КонецЦикла;	
	
	ВременнаяТаблицаРешений = Новый ТаблицаЗначений;
	ВременнаяТаблицаРешений.Колонки.Добавить("НомерУзла", Новый ОписаниеТипов("Число"));
	ВременнаяТаблицаРешений.Колонки.Добавить("ПостояннаяРазница", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(23, 10)));
	ВременнаяТаблицаРешений.Колонки.Добавить("СтоимостьНУ", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(23, 10)));
	ВременнаяТаблицаРешений.Колонки.Добавить("Стоимость", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(23, 10)));
	
	НомерУзла = 1;
	Для каждого ЭлКоллекции Из ТекущееРешение Цикл
		НовоеРешение = ВременнаяТаблицаРешений.Добавить();
		НовоеРешение.НомерУзла = НомерУзла;
		НовоеРешение.Стоимость = ЭлКоллекции;
		Если ВидОтраженияВУчете = Перечисления.ВидыОтраженияВУчете.ОтражатьВРегламентированномУчете Тогда
			НовоеРешение.СтоимостьНУ       = ТекущееРешениеСтоимостьНУ[НомерУзла-1];
			НовоеРешение.ПостояннаяРазница = ТекущееРешениеПостояннаяРазница[НомерУзла-1];
		КонецЕсли;		
		
		НомерУзла = НомерУзла + 1;
	КонецЦикла; 
	
	Запрос.Текст = "
		|УНИЧТОЖИТЬ ТаблицаРешений
		|;
		|ВЫБРАТЬ * ПОМЕСТИТЬ ВременнаяТаблицаРешений ИЗ &ВременнаяТаблицаРешений КАК ВременнаяТаблицаРешений
		|;
		|ВЫБРАТЬ
		|	УзлыКорректировкиСтоимостиСписания.НомерУзла КАК НомерУзла,
		|	//ДляРеглУчета ЕСТЬNULL(ВременнаяТаблицаРешений.ПостояннаяРазница, 0) КАК ПостояннаяРазница,
		|	//ДляРеглУчета ЕСТЬNULL(ВременнаяТаблицаРешений.СтоимостьНУ, 0) КАК СтоимостьНУ,
		|	ЕСТЬNULL(ВременнаяТаблицаРешений.Стоимость, 0) КАК Стоимость
		|
		|ПОМЕСТИТЬ ТаблицаРешений
		|ИЗ
		|	РегистрСведений.УзлыКорректировкиСтоимостиСписания КАК УзлыКорректировкиСтоимостиСписания
		|
		|	ЛЕВОЕ СОЕДИНЕНИЕ 
		|		ВременнаяТаблицаРешений КАК ВременнаяТаблицаРешений
		|	ПО 
		|		ВременнаяТаблицаРешений.НомерУзла = УзлыКорректировкиСтоимостиСписания.НомерУзла
		|ГДЕ
		|	УзлыКорректировкиСтоимостиСписания.Регистратор = &Регистратор
		|
		|ИНДЕКСИРОВАТЬ ПО
		|	НомерУзла
		|;
		|УНИЧТОЖИТЬ ВременнаяТаблицаРешений";
		
	Запрос.УстановитьПараметр("ВременнаяТаблицаРешений", ВременнаяТаблицаРешений);
	
	Запрос.Текст = УправлениеЗатратами.ЗаменитьКомментарииВТекстеЗапроса(Запрос.Текст, ВидОтраженияВУчете);
	Запрос.Выполнить();
	
	ОбщегоНазначения.Сообщение("Выполненное количество итераций расчета стоимости: " + Строка(КоличествоИтераций));
	ОбщегоНазначения.Сообщение("Полученное среднее отклонение решений: " + Строка(Окр(ТекущееОтклонение/КоличествоУравненийСЛУ, 13)));
	
	Возврат Истина;
	
КонецФункции
 
...Показать Скрыть
76. Ийон Тихий (cool.vlad4) 07.07.11 12:03
(75) я видел этот ужас :D теперь понятно почему я в одной из веток шумел по поводу нечитабельности кода, в типовых почему-то все мешают в кучу, алгоритмы, логику и т.п.
(74) да, действительно можно найти такие условия, при которых обычные методы решения не прокатывают (недаром даже аппроксимационные методы есть) , но здесь другой вопрос - а на практике это встречается, при расчете себестоимости?
77. Игорь Исхаков (Ish_2) 07.07.11 12:12
(75) Тебе что-то не нравится в этом тексте ?
78. Ийон Тихий (cool.vlad4) 07.07.11 12:18
мне не нравится, имхо - смешивать обобщенный алгоритм и сугубо конкретную задачу в одну функцию, мне кажется не хорошо, взять код Арчибальда - его можно использовать везде, не только в этой задаче и без изменения конфы, а код из 75 - нигде больше использовать нельзя и ошибку труднее найти. Код, конечно, рабочий, я ничего против не имею, просто считаю не красивым. Но, возможно, так написано специально, сугубо под конкретную задачу (может в целях оптимизации, не знаю)
79. Александр Рытов (Арчибальд) 07.07.11 12:18
(74) Не сумма, а максимум.
Касательно плохой обусловленности. Именно в условиях плохой обусловленности системы я и решал свою пракическую задачу. Конкретно, себестоимость услуг одних подразделений на три-четыре порядка превосходила себестоимость услуг других, соответственно выглядела и матрица. Но проблема решается простым округлением: ищем решение (цены) "в рублях и копейках", маленькие коэффициенты при этом вырождаются в нулевые.
80. Игорь Исхаков (Ish_2) 07.07.11 12:31
(79) Ну-ну. Округлением запросто можно добиться не улучшения обусловенности , а ухудшения.
И ты , конечно же, проводил сравнение результата без округлений и результата с начальными округлениями коэффициентов ?
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа