gifts2017

Еще один взгляд на проблему "жизнь без последовательностей"

Опубликовал Сергей (ildarovich) в раздел Управление - Теория учета

Предлагаю свой взгляд на решение проблемы "документы без последовательности". Решение навеяно обсуждениями http://infostart.ru/public/62785/ и http://infostart.ru/forum/forum11/topic28666/. Даже попытался описать его там (152). Теперь думаю, что оно может быть опубликовано и самостоятельно. Я считаю это решение теоретически исчерпывающим и готовым к практическому воплощению, а что скажете Вы?

Для краткости и ясности используем язык математики.

Обозначим номенклатуру i, приход j, расход k. 

Функция X(i,j,k) определяет структуру списания, сложившуюся в интересующий нас момент t. 

То есть отвечает на вопрос - сколько номенклатуры i из прихода j было списано при расходе k. 

Функцию можно представить в виде куба со сторонами: Номенклатура, Приход, Расход. 

Исправление задним числом можно представить как функцию dX(i,j,k). Так что Xt+1(i,j,k)=Xt(i,j,k)+dX(i,j,k). 

То есть корректировка документа не должна быть перепроведением, а должна рассчитывать дельту структуры списания. 

 

Предложение объединить два измерения (номенклатуру и приход) ничего не меняет. 

В этом случае используется структура Y(l,k), где l=i*N+j. N - количество номенклатуры. 

А уравнение превращается в Yt+1(l,k)=Yt(l,k)+dY(l,k).

 

Как решается задача определения dX? 

 

Куб X делится на слои номенклатуры i: Z=X(i=i,j,k). В каждом слое применяется изменение d (уменьшается или увеличивается приход или расход или изменяется их порядок). 

Затем решается частный случай ТРАНСПОРТНОЙ ЗАДАЧИ (это разновидность задач линейного программирования) с ограничениями: 

 

Σj Zjk = Rk

 

(общий расход из всех приходов равен количеству Rk в расходной накладной k)

 

Σk Zjk <= Sj

 

 

(общий приход из всех расходов ограничен количеством Sj прихода j)

 

и целевой функцией:

 

Σjk Zjk * Cjk -> min

 

При этом для метода ФИФО, например,  коэффициенты Сjk будут определяться правилом

 

Cjk = 1/(T(k) - T(j)), если T(k) > T(j) и  Cjk = ∞, если T(k) <= T(j),

где T(j), T(k) - время прихода и расхода соответственно.

 

В качестве опорного решения берется текущее значение Z. 

Правда, так мы фактически вычисляем не dX, а непосредственно Xt+1.

 

Почему же тогда 1С использует перепроведение и последовательность? 

Потому что в этом случае не нужен отдельный алгоритм расчета dX и структуры данных под него. 

dX определяется последовательным повторением элементарных проведений одного документа, 

начиная с момента нарушения последовательности. 

Такие алгоритмы называются решением методом "грубой силы". 

Можно предложить различные частичные усовершенствования. Например, "softpoint", в котором восстановление последовательности проводится отдельно по каждому слою номенклатуры.

Можно оптимизировать хранение структуры списания. 

Хотя сам собой напрашивается регистр сведений с измерениями: Номенклатура, Приход, Расход и ресурсом Количество. 

Так раньше и хранили разреженные матрицы.

Можно поставить задачу найти самый быстрый алгоритм расчета dX. 

Сам алгоритм решения ТРАНСПОРТНОЙ ЗАДАЧИ (метод потенциалов, симплекс-метод) хорошо исследован, 

новое можно попробовать поискать в ускорении для данного частного случая задания целевой функции и опорного решения. 

Или уже учесть особенности реализации: самый быстрый с использованием промежуточных записей в БД, самый быстрый в оперативной памяти, 

самый быстрый при использовании структур данных 77 и т.п. 

 

Только сначала нужно определиться: зачем? 

 

Дело в том, что генезис платформ 1С - от бухгалтерии, от учетных задач, нацеливает решения не на отражение настоящего, а на рисование прошлого. 

Бухгалтер раскладывает на столе первичку и решает: в какой момент произвести списание? 

Когда товар был подороже или подешевле? Показывать или нет авансы? 

Ну и пусть попробует один вариант, восстановит последовательность (пересчитает себестоимость), подождет. 

Вам хочется, чтобы это делалось максимально быстро? Стоит ли овчинка выделки? Раз в месяц, раз в квартал - компьютер не перетрудится! 

В общем, к управлению, к отражению настоящего, эта задача "рисования прошлого" не относится, а значит, ИМХО не требует высокой скорости расчетов.

См. также

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

Комментарии

1. Александр Рытов (Арчибальд) 21.12.09 09:22
По-моему, в данном случае математическая модель не проясняет, а маскирует ситуацию. Поскольку никому не нужно складывать булки с отвертками, мы всегда находимся ровно в одном "слое", так что задача линейного программирования (ЗЛП) не более чем двумерна. А с учетом того, что Приход = -Расход, размерность и вовсе единична. Далее, ограничение "приход раньше расхода" на практике несущественно, ибо физически невозможна отгрузка несуществующего товара. Вот документально, даже юридически, она вполне возможна - хоть "задним числом" это назови, хоть "фьючерсным контрактом". И наконец, никакой целевой функции нет, так что это вообще не ЗЛП.
zexpress; Ёпрст; +2 Ответить 1
2. Kayen (kayen) 21.12.09 15:06
Интересная модель но к сожалению неприменима к жизни. Как например быть с себестоимостью в рамках конкретного периода?
3. Сергей (ildarovich) 21.12.09 15:26
(1)Хорошо! Без маскировки. Вы думаете о проблеме: как вести учет, забыв о последовательностях.
Я Вам говорю, что Ваше желание сбудется, если у Вас будет таблица "структура списания", в которой для каждой номенклатуры, прихода и расхода будет отмечаться: сколько товара по этой цепочке прошло. Таблица - это регистр остатков с измерениями: номенклатура, документ прихода, документ расхода и ресурсом: количество. НадеюсЬ, Вы не будете спорить, что таблица должна быть заполнена "правильно". Эта правильность - учет ограничений: сумма количества одной номенклатуры из одного прихода во всех строках таблицы не должно быть больше исходного количества прихода; сумма количества для одного расхода в разных строках таблицы должно совпадать с количеством этой номенклатуры в этой расходной накладной; количества в строчках таблицы должно быть положительным.
Попытавшись составить это "судоку", Вы поймете, что это можно сделать гуголом различных способов. Потому, что ограничений - столько, сколько приходов + расходов, а переменных - столько, сколько приходов х расходов. Я Вам говорю, что среди этого гугола есть Ваш, единственный и наилучший способ. И говорю как его определить. Нужно минимизировать случаи, когда списывается товар с ближайшего по времени прихода, сделав это невыгодным. Штраф рассчитаем (для ФИФО) обратно пропорционально близости времени расхода и прихода, а если расход был раньше прихода сделаем штраф вообще запредельным! То есть нам будет выгоднее списывать более ранние партии для конкретного расхода. И вот этот Ваш заветный наилучший способ Вы и найдете, решив ЗЛП (точнее, ее частный случай - транспортную задачу). В процессе поиска решения сначала найдете опорное решение методом "северо-западного угла". Можете удивляться или нет, но программируя списание партий, Вы действуете точно таким же способом.
Итак, у нас есть "структура списания", полученная всего-лишь по-другому названным способом. Затраты времени на это оказались примерно теми-же. В чем же выигрыш? А вот в чем.
Кладовщик развернул рыбу - это оказалась накладная! И дата - 13-е, пятница, прошлого месяца!
Что делать? - Пересчитывать таблицу "структура списания". Как??? Да по тому же алгоритму поиска оптимального решения распределения по партиям! Всего-то и делов - одно ограничение добавилось. Метод "потенциалов" решения нового судоку работает так, что выполняет минимум итераций, если опорное решение близко к оптимуму. На выходе имеем новую "правильную" таблицу списания партий. С учетом новой накладной. И не важно - приход, расход. Если рыба в накладной была в холодильнике - мы даже не поморщились! Аналогично рассматриваются случаи изменения количества в накладных, добавления новых позиций, исключения старых. При этом контролируются остатки на любой момент! То есть ограничения не допускают никаких, хотя бы секундных "косяков". Метод просто отвергнет очередное изменение, не найдя решения!
Еще раз - мы имеем дело со всем массивом документов одновременно. Неважно, в какой последовательности изменяются документы массива - мы каждый раз перестраиваем "структуру списания". Это все равно, что при каждом нарушении последовательности востанавливать ее перепроведением. Только вместо расчета "от печки" мы быстро, за минимум итераций(отцы доказали!), переходим по граням выпуклого многоугольника ограничений симплекс-метода.
Теперь понятно?
4. Михаил Ражиков (tango) 21.12.09 15:30
(3) "Таблица - это регистр остатков с измерениями: номенклатура, документ прихода, документ расхода и ресурсом: количество."

Таблица - это регистр сведений ... без количества, поскольку вводим запись на каждую минимальную единицу учета, т.е. кол == 1

**
В измерения кроме Номенклатуры впихнем еще ЗначенияНабораХарактеристикНоменклатуры

**
В набор характеристик можно добавить число ЦенаПоступления
5. Сергей (ildarovich) 21.12.09 15:40
(2) Имея актуальную "структуру списания", то есть зная: что, когда и по какому документу приходило, в каком количестве, когда и по какому документу списывалось Вы дальше можете рассчитать что угодно.
Не хотелось усложнять, но, наверное понятно, что ЛИФО будет отличаться видом целевой функции (разность времен в числителе), при среднем в таблице будет одна строка, при среднемесячном - столько, сколько месяцев и так далее.
6. Александр Рытов (Арчибальд) 21.12.09 15:53
(3) Повеселил :D
Вы думаете о проблеме: как вести учет, забыв о последовательностях
Ничего подобного я не думаю. Я это знаю и делаю. Нет у меня никаких последовательностей, и я прекрасно себя чувствую.
нам будет выгоднее списывать более ранние партии для конкретного расхода. И вот этот Ваш заветный наилучший способ Вы и найдете, решив ЗЛП

Не факт, что списание самых ранних партий всегда лучше. Но даже если и так, то после возврата части древней партии "трехмерная" оптимизация рассыплется - все последующие списания придется корректировать.
То есть ограничения не допускают никаких, хотя бы секундных "косяков". Метод просто отвергнет очередное изменение, не найдя решения
Тогда как бухгалтер/менеджер решение легко найдут...
Можете удивляться или нет
Меня удивить вряд ли получится :D
http://infostart.ru/profile/46936/blog/843/
7. Сергей (Che) Коцюра (CheBurator) 21.12.09 17:20
прочитал бегло... так что не взыщите...
> То есть нам будет выгоднее списывать более ранние партии для конкретного расхода. И вот этот Ваш заветный наилучший способ ...
- бяка (частная). при списывании с ранних партий - при необходимости впихнуть задним числом новый расход натыкаемся на нехватку товара - так как товар с ранних партий уже списан. А вот если списывать с ближайших партий - такого не будет...
.. но это все пока написал "на бегу".. в порядке дежурного бреда...
8. Сергей (ildarovich) 21.12.09 18:14
(7) Слово "выгоднее" я употребил для объяснения значения параметров целевой функции. Имелось ввиду, что это требование заставит считать лучшим решение распределения партий "как при списании по ФИФО". Не имелась ввиду динамика наших действий - целевая функция определяет требование к результату, который может быть получен хоть алгоритмом случайного поиска. Про алгоритм "метод потенциала" и его реализацию я вообще не упоминал, считая, что он и так известен. Этот алгоритм довольно мудреный и, если тут еще и его описывать, вообще запутаемся. Просто считаем, что он применяется и таким образом мы переходим от одного разрешенного состояния к другому в направлении оптимума (правильно распределенных партий). Не применяя абстракции от используемого алгоритма поиска оптимального решения, нам потребуется рассматривать отдельно уменьшение прихода, увеличение прихода, уменьшение расхода, увеличение расхода, перестановку приходов, перестановку расходов. А затем просматривать "волну изменений" в "таблице списания". Этого не нужно, если на данном этапе представить алгоритм "метод потенциала" как черный ящик, дающий оптимальное решение. Возьмите хотя бы Эксель и решение транспортной задачи через подбор параметра. Там Вы не видите процесса решения - видите результат.
Математика тут применяется для того, чтобы описать, что мы хотим получить в итоге. И каким требованиям должно удовлетворять решение. Существует ли оно вообще. Это и выводит нас на общий метод решения таких задач. Дальше остаются подробности реализации. И хотя "дьявол кроется в деталях", математическая обоснованность сходимости и скорости сходимости методов ЛП, дает уверенность в получении результата.
9. Александр Шишкин (Шёпот теней) 21.12.09 18:53
... не согласен с :

"Обозначим номенклатуру i, приход j, расход k. Функция X(i,j,k) "

почему:

1. эта функция истинна в случае номенклатура = приходу ...
2. если номенклатура = НЕприход тогда это множество без сортировки ...
3. если мы к п.2. добавляем партии, то номенклатура превращается в двойное множество ...
4. если мы берём лифо-фифо то функции усложняется ещё и сортировкой внутри п.3 ...
5. в связи с усложнённостью функции учитывающей пп. 2,3,4 мы имеем систему охреНительной сложность ... а если ещё добавить сложность перекрёстных ссылок (влияние документов друг на друга) - то будет полная амба - типа 1С ....

... ВОТтакоеМНЕНИЕесть ...

...
10. Валерий (vuzurp) 22.12.09 08:46
Что-то мне непонятно в этой прикладной математике! :D

В реальном учете (не виртуальном, не теоретическом!) у "изменения документа задним числом" одна единственная задача - привести все последующие показатели к требуемым величинам. Т.е. переделать движения всех последующих документов!

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

Механизмы для решения обеих задач существуют. Что нового предлагает обсуждаемая медота?
11. Сергей (ildarovich) 22.12.09 11:32
(10)
В реальном учете (не виртуальном, не теоретическом!) у "изменения документа задним числом" одна единственная задача - привести все последующие показатели к требуемым величинам. Т.е. переделать движения всех последующих документов!

Когда Вы говорите "переделать движения всех последующих документов", Вы как-будто подразумеваете, что последующий документ делает движения по регистру партий и что, не перепроводя его, ничего не сделать, поскольку нельзя (или сложно) изменить движения без перепроведения. То есть связываете себя конкретной реализацией партионного учета.
Я же смотрю на проблему в целом. Что есть регистр партий? - Всего лишь структура для определения того, из какого документа прихода взят конкретный расход (X(i,j,k)). Функция X(i,j,k) может быть реализована как угодно. И рассчитываться не обязательно последовательным проведением документов. В моем предложении - небольшими или большими (если изменение в массиве документов существенное) точечными корректировками dX(i,j,k).

Другими словами, НЕ переделать ДВИЖЕНИЯ ВСЕХ ПОСЛЕДУЮЩИХ документов, а пересчитать только измененные связи документов, возникшие из-за исходного изменения.
Механизмы для решения обеих задач существуют. Что нового предлагает обсуждаемая медота?

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

Кроме того, предлагаемое решение не использует понятие "последовательность".

Также мне показалось ценным то, что в классе возможных алгоритмов решения определено место стандартного алгоритма 1С, а следовательно - его достоинства и недостатки относительно других методов. В итоге, я и предлагаю осознанно искать лучшие методы, зная, что мы можем выиграть и нужно ли это вообще!
12. cdr (phsin) 23.12.09 12:47
кажется, для 7.7 это не применимо, т.к. движения можно делать только в модуле документа. а здесь получается придется изменять движения по регистрам обработкой...
поправьте меня, если я не прав, автор предлагает восстанавливать последовательность только по тем товарам, которые изменились при проведении задним числом каким-то хитрым способом с привлечением (потусторонних сил) транспортной логистики..
хотя с теорией я увы на ВЫ, поэтому так и хочется крикнуть "Пример в студию!" ;)
13. Сергей (ildarovich) 23.12.09 13:12
(12) Понимаю Ваши сомнения. Намеренно хотел уйти от технических подробностей реализации, чтобы взглянуть на корень проблемы.
Вижу, без примера не все понятно. Пример подготовлю. Нужно какое-то время.
14. cdr (phsin) 23.12.09 13:15
15. Сергей (ildarovich) 23.12.09 13:18
(12)
поправьте меня, если я не прав

Вы не совсем правы. Хитрым способом я предлагаю не восстанавливать последовательность, а корректировать структуру списания X(i,j,k), которая ее заменяет. Привлекается не транспортная логистика, а математически схожая с распределением по партиям задача линейного программирования.
16. bulpi bulpi (bulpi) 23.12.09 21:27
Уважаемый автор! Я поставил плюс за новый, свежий взгляд на известные вещи. Но должен Вас предупредить : те самые "готовые хорошо исследованные алгоритмы решения" неприятно удивят Вас своей сходимостью для случая большого количества переменных. Сам пробовал, удивлялся. Теоретически вроде все ОК, а практически до числа довести - фиг!
17. Сергей (ildarovich) 23.12.09 22:48
(16) Большое спасибо. Вы уловили суть дела. Но все же хочу попробовать. В данном случае критерием истины будут результаты практического исследования на задачах реальной размерности. Обнадеживает легко просматриваемое сходство с приемами ускоренного проведения по партиям.
18. Владимир (hogik) 24.12.09 02:10
(0)
В данной статье меня заинтересовал текст после слов: "...зачем?". Я согласен с каждым утверждением этой части статьи. И попробую дополнить этот текст некоторыми деталями своего понимания задачи.
1) "...1С ...нацеливает решения не на отражение настоящего, а на рисование прошлого."
- А изменение прошлого не должно влиять на текущий процесс торговли. Как в изменении основных итоговых показателей - реальные остатки на полках и взаиморасчеты с клиентами. Так и не должны нарушать вычислительный процесс регламентными работами в сетевой (многопользовательской) среде.
2) "Бухгалтер раскладывает на столе первичку и решает: в какой момент произвести списание? Когда товар был подороже или подешевле? Показывать или нет авансы?"
- Для этого можно не раскладывать документы на столе. А дать бухгалтеру программные средства раскладки документов в компьютерной базе данных в соответствии с его пожеланиями (правилами).
3) "Ну и пусть попробует один вариант, восстановит последовательность (пересчитает себестоимость), подождет."
- Т.к. данные этого расчета (например, себестоимости) никак не влияют на "отражение настоящего", то не имеет смысла хранить эти расчеты в базе данных в момент "восстановления последовательности" прошлого периода. И, тем более не имеет смысла, нагружать систему лишней работой в момент отражения настоящего (проведение документов текущего периода). Т.е. "себестоимость" надо не пересчитывать, а считать всегда заново после перестановки документов (см. пункт #5).
4) "Вам хочется, чтобы это делалось максимально быстро? ... Раз в месяц, раз в квартал - компьютер не перетрудится!"
- Для "настоящего" требуется доступность вычислительных средств всегда. И перерыв в работе торговли, даже один раз в месяц (квартал), не допустим. Это означает, что "восстановление последовательностей" прошлого периода (для бухгалтерских нужд) должен выполняться в многопользовательской среде и не мешать реальной торговле.
5) "... эта задача "рисования прошлого" ... не требует высокой скорости расчетов."
- Сам расчет существует всегда. А быстро он выполняется, если в процессе расчета не делается перепроведение документов. Т.е. документы расставлены в соответствии с пунктом #2, а окончательные цифирьки рассчитываются и выводятся отчетом. И не хранятся в базе данных!
19. Сергей Гуров (hansel) 25.12.09 22:45
(0) Как говорят англоязычные коллеги: if you are so clever, show me your money.
Переводя с "ихнего", и адаптируя к сути Вашей статьи: если Вы такой умный, нам код работающий покажите.

Сразу PS: Не сочтите реплику за неуважение. Будет практический результат Ваших идей - обсудим, а так - мутно всё это.
20. Сергей (ildarovich) 25.12.09 23:38
21. Евгений Стоянов (quick) 03.03.10 14:55
Интересная идея по поводу того что можно проверять приход за весь период с сравнивать его с предполагаемым расходом. А если без дельта и т.д. напрямую?
Приход = ПолучитьПриходЗаВесьПериод();
РасчетныйРасход = ПолучитьРасходЗаВесьПериод + КолвоСписать;
Если Приход - РасчетныйРасход < 0 Тогда
Сообщить("Списание в минус");
Подумать только как бы общий расход приход хранить для быстрого расчета.
22. Сергей (ildarovich) 19.08.10 09:41
(12)(16)(19) В статье http://infostart.ru/public/74343/ описывается практическая реализация данного метода, приводятся: тестовая конфигурация, программный код, оценки быстродействия.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа