Аллокация расходов

dava

Подскажите плз, как лучше реализовать аллокацию расходов.
Скажем, есть правило: расходы статьи А1 распределять в пропорциях: 0.6*А2 и 0.4*А3.
А2 может распределяться другим правилом на 0.3*А4 + 0.3*А5+ 0.4*А6.
Теоретически, могут быть циклы.
Правил таких могут быть сотни.
Данные хранятся в Oracle DBMS.
На ум приходит сделать матрицу M, в которой Mij = Коэффициент перед Aj в правиле для распределения Ai, и возвести её в большую степень, затем переделать опять в правила, проиндексировать и применить джойном. Но так как размерность матрицы будет большой, то это вроде как будет дико неоптимально. Наверно как-то можно к блочному виду привести или что-нибудь в этом роде, но ЧМы давно были, уже не помню best practices...
Подскажите плз, как наиболее оптимально реализовать?

6yrop

мне напомнило пример с название Revenue Recognition из книжки Martin Fowler, Patterns of Enterprise Application Architecture. Может и не то :)

dava

пасиба, поищу на просторах инета

okis

это ж задача линейного программирования в чистом виде, не?

danilov

Я, наверное, не понял, что требуется, но разве недостаточно
найти (M - E)^(-1)?
Что вообще на выходе-то должно получиться?

mbolik1

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

dava

Я, наверное, не понял, что требуется, но разве недостаточно
найти (M - E)^(-1)?
Что вообще на выходе-то должно получиться?
Может быть, я чесгря не помню, что даёт эта формула.
По идее, задача применять правила аллокации расходов к этим самым расходам вплоть до момента, пока применение этих правил не перестанет менять суммы более, чем на одну копейку.
Ну то есть, если построить матрицу из коэффициентов аллокации и возводить её в степень, устремляющуюся к бесконечности, то получится как раз нужный результат. Идемпотентная матрица такая, кажись.

dava

То что у тебя последующие правила правят данные на статье которую уже разносили может быть вполне осознанным действием с точки зрения разнесения расходов.
Ну да, и как тогда такие правила отсортировать? Я вижу выход только предел степени матрицы брать, но наверно он как-то вычисляется попроще, чем тупо возведением в степень много раз. В интернетах вот предлагают возводить матрицу в квадрат, потом полученную - также возводить в квадрат, потом ещё разок - уже соответствует 2^3 итераций применения правил, вроде как... ну и так далее. Другие говорят, мол, жорданову форму надо найти, а потом множить между собой блоки.

yroslavasako

это ж задача линейного программирования в чистом виде, не?
всё ещё проще. Это в чистом виде система линейных уравнений. Возможно, поверх разреженной матрицы.

mbolik1

Ну да, и как тогда такие правила отсортировать?
Так, как правильно с точки зрения методологии. Этот вопрос технически вообще не решается.
Я вижу выход только предел степени матрицы брать, но наверно он как-то вычисляется попроще, чем тупо возведением в степень много раз.

Так как аллокации расходов всегда допускают какую-то погрешность, зачастую довольно большую (до 5%). То и особо усердствовать вычисляя абсолютно точные формы не нужно. Там где это действительно нужно (вы договорились об этом с бизнесом) можно просто цикл раза 3 прогнать.

sgalexandra

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

danilov

Тогда как-то так:
B = M - E
Если |B| != 0, тогда тебе не повезло и итерации либо никогда не сойдутся, либо сойдутся к 0.
Если всё же |B| = 0, тогда ищем ядро B (kerB)
Тогда для любого a из kerB Ma = a.
Через ortB (хз, как оно пишется) обозначим ортогональное дополнение к kerB.
для a из kerB и b из ortB выполнено
(Mb, a) = (b, Ma) = (b, a) = 0, то есть
M(ortB) = ortB.
таким образом, для всякого вектора c существует единственное разложение
c = a + b, такое что a лежит в kerB, b - в ortB
и если M сжимающее на ortB, то итерации будут сходиться к a, иначе расходиться.
Таким образом, тебе надо найти kerB, а ответом будет проекция исходного вектора на kerB.
Предварительно посчитать надо будет много, зато по каждому исходному вектору результат будет получаться просто перемножением на матрицу замены.
Кажется, так.

danilov

Не, такое разложение на пространства работает только для самосопряжённых матриц.
В общем случае не помню, как представить, но должно быть тоже не сложно.
upd.
Точно, ортогональное дополнение нужно искать для транспонированной матрицы. Тогда в результате будет не проекция, а таки честное разложение,
Но всё равно строится матрица замены.
Оставить комментарий
Имя или ник:
Комментарий: