From c17e4e7fc9e2e6b76751393b668fd46a5667fcac Mon Sep 17 00:00:00 2001 From: gsv Date: Thu, 6 Nov 2025 17:05:00 +0300 Subject: [PATCH 01/22] Draft of the demo description. --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/README.md b/README.md index 1b503b6..bf08a1d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,53 @@ # PageRankBenchmark Stand for PageRank algorithm benchmark + +# Минимальный пример + +Цель примера --- показать, как в рамках GraphBLAS можно работать со сложными атрибутами вершин и рёбер графа. + +В качестве примера возьмём следующую задачу. +Пусть есть граф с двумя типами вершин: пользователи и карты. +Три типа ориентированных рёбер: +* "Перевод": соединяет две карты (откуда и куда перевод) +* "Звонок": соединяет двух пользователей (кто кому звонил) +* "Владеет": соединяет пользователя и карту (от владельца карты к карте) + +Каждый тип вершины имеет свой набор атрибутов. +* "Пользователь": пол, ФИО, год рождения +* "Карта": тип, год выпуска + +Каждый тип рёбер также имеет свой набор атрибутов. +* "Перевод": общая сумма, "количество транзакций" +* "Звонок": суммарная продолжительность в секундах +* "Владеет": не имеет атрибутов + +Хотим выбрать по некоторому критерию пользователей их карты и для анализа переводов хотим посчитать PageRank на подграфе, заданном переводами между отобранными картами. +Выбрать хотим все карты системы "МИР", которыми владеют пользователи мужского пола старше заданного года рождения. + +Картинка графа. + +Атрибуты --- структуры. + +Граф представлен как набор матриц и векторов. По одной матрице на каждый тип рёбер и по одному вектору на каждый тип вершин. +Считаем при этом, что все вершины, вне зависимости от типа, занумерованы с 0 подряд. + +Картинка с тем, как хранится наш граф. + +Первым делов фильтруем пользователей. Select. Пример кода, полукольцо и т.д. + +Далее, создаём диагональную матрицу из отобранных вершин и фильтруем рёбра через умножение полученной матрицы на марицу, хранящую соответствующий тип рёбер. + +Пример кода. + +Далее редукция полученной матрицы, чтобы получить карты и снова диагональная матрица и умножение, чтобы получить переводы только между нужными нам картами. + +Пример кода. + +Конструируем матрицу, по которой будем считать PageRank. +В качестве исходного веса ребра берём 1 - (средняя сумма перевода). + +Пример кода. + +Запускаем PageRank. + +Пример кода. From 2c90fd5df18fa253d11000b8dfb9dd82af92bb84 Mon Sep 17 00:00:00 2001 From: Semyon Date: Fri, 7 Nov 2025 08:55:46 +0300 Subject: [PATCH 02/22] =?UTF-8?q?=D0=9E=D0=BF=D0=B5=D1=87=D0=B0=D1=82?= =?UTF-8?q?=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rodion Suvorov <107667059+suvorovrain@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bf08a1d..5e19201 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Stand for PageRank algorithm benchmark Первым делов фильтруем пользователей. Select. Пример кода, полукольцо и т.д. -Далее, создаём диагональную матрицу из отобранных вершин и фильтруем рёбра через умножение полученной матрицы на марицу, хранящую соответствующий тип рёбер. +Далее, создаём диагональную матрицу из отобранных вершин и фильтруем рёбра через умножение полученной матрицы на матрицу, хранящую соответствующий тип рёбер. Пример кода. From ff8a46854a93a4b96f70c98b4dc7122b81b33854 Mon Sep 17 00:00:00 2001 From: gsv Date: Fri, 7 Nov 2025 10:11:04 +0300 Subject: [PATCH 03/22] =?UTF-8?q?=D0=A7=D0=B5=D1=80=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D0=BA=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D1=8F?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5=D1=81=D1=81=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=80=D0=BE=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BC?= =?UTF-8?q?=D0=B0=D1=82=D1=80=D0=B8=D1=86=D1=8B=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=B2=D1=8B=D1=87=D0=B8=D1=81=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?PageRank.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 5e19201..2e724c0 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,21 @@ Stand for PageRank algorithm benchmark Конструируем матрицу, по которой будем считать PageRank. В качестве исходного веса ребра берём 1 - (средняя сумма перевода). +Для построения распределения будем использовать идею функции Softmax, которая задаётся следующим образом. + +$$ +{\displaystyle \sigma (\overrightarrow{z})_{i}={\frac {e^{z_{i}}}{\displaystyle \sum _{k\mathop {=} 1}^{K}e^{z_{k}}}}} +$$ + +В нашем случае подобная функция должна быть применена к каждой строке матрицы, задающей переводы. При этом должна быть задана некая функция $f$, получающая вес ребра по его атрибутам. +То есть итоговая формула выглядит следующим образом. + +$$ +{\displaystyle \sigma (\overrightarrow{z})_{i}={\frac {e^{f(z_{i})}}{\displaystyle \sum _{k\mathop {=} 1}^{K}e^{f(z_{k})}}}} +$$ + +Вычислять будем следующим образом. Сперва выполним редукцию по колонкам. Таким образом получим знаменатель дроби. +После этого тензорно умножим полученный вектор на вектор из единиц, использую исходную матрицу в качестве маски. Таким образом получим матрицу, в которой знаменатель стоит на необходимых местах. После чего поэлементно поделим две матрицы. Пример кода. From 46a277792a16faa9ff17392f877590d3308ec65e Mon Sep 17 00:00:00 2001 From: gsv Date: Tue, 11 Nov 2025 10:18:35 +0300 Subject: [PATCH 04/22] An attempt to insert svg to readme. --- Figures/Graph.svg | 1034 +++++++++++++++++++++++++++++++++++++++++++++ README.md | 2 +- 2 files changed, 1035 insertions(+), 1 deletion(-) create mode 100644 Figures/Graph.svg diff --git a/Figures/Graph.svg b/Figures/Graph.svg new file mode 100644 index 0000000..4412eff --- /dev/null +++ b/Figures/Graph.svg @@ -0,0 +1,1034 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id: 4 + Gender: FAdge: 52 + + + + + id: 2 + Gender: FAdge: 52 + + + + id: 3 + Gender: FAdge: 52 + + + + id: 10 + Gender: FAdge: 52 + + + + id: 1 + Gender: FAdge: 52 + + + + id: 11 + System: MIRLimit: 60 000 + + + + id: 12 + System: MIRLimit: 60 000 + + + + id: 6 + System: MIRLimit: 60 000 + + + + id: 7 + System: MIRLimit: 60 000 + + + + id: 8 + System: MIRLimit: 60 000 + + + + + + id: 9 + System: MIRLimit: 60 000 + + + + id: 5 + System: MIRLimit: 60 000 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/README.md b/README.md index 2e724c0..3b64f81 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Stand for PageRank algorithm benchmark Хотим выбрать по некоторому критерию пользователей их карты и для анализа переводов хотим посчитать PageRank на подграфе, заданном переводами между отобранными картами. Выбрать хотим все карты системы "МИР", которыми владеют пользователи мужского пола старше заданного года рождения. -Картинка графа. +![Пример графа](./Figures/Graph.svg) Атрибуты --- структуры. From a5b15cab033f4dbd75a6f8be4ef27383f83990a7 Mon Sep 17 00:00:00 2001 From: gsv Date: Tue, 11 Nov 2025 11:13:49 +0300 Subject: [PATCH 05/22] Example of the input graph. --- Figures/Graph.svg | 625 ++++++++++++++++++++++++++++++---------------- 1 file changed, 404 insertions(+), 221 deletions(-) diff --git a/Figures/Graph.svg b/Figures/Graph.svg index 4412eff..dbf7368 100644 --- a/Figures/Graph.svg +++ b/Figures/Graph.svg @@ -2,9 +2,9 @@ - - - - - - + transform="matrix(0.5,0,0,0.5,22.42737,31.99714)"> Gender: FGender: MAdge: 52 + id="tspan3">Adge: 42 + transform="matrix(0.5,0,0,0.5,111.27613,136.13843)"> Adge: 52 + id="tspan3-2">Adge: 25 + transform="matrix(0.5,0,0,0.5,88.384476,31.99714)"> Adge: 52 + id="tspan3-7">Adge: 40 + transform="matrix(0.5,0,0,0.5,198.79177,31.99714)"> Gender: FGender: MAdge: 52 + id="tspan3-6">Adge: 35 + transform="matrix(0.5,0,0,0.5,30.257477,136.13843)"> Adge: 52 + id="g10" + transform="translate(27.516678,-28.575001)"> + width="31.19491" + height="15.238575" + x="120.32306" + y="103.45654" /> id: 11 + style="stroke-width:0.132291" + x="121.16551" + y="106.72439">id: 11 System: MIRSystem: MIRLimit: 60 000 + style="stroke-width:0.132291" + x="121.16551" + y="115.25858" + id="tspan6">Limit: 99 000 000 + id="g9" + transform="translate(28.575012,12.170831)"> + width="30.993973" + height="15.239405" + x="174.66626" + y="103.45613" /> id: 12 + style="stroke-width:0.132291" + x="175.50911" + y="106.72439">id: 12 System: MIRSystem: MIRLimit: 60 000 + style="stroke-width:0.132291" + x="175.50911" + y="115.25858" + id="tspan6-5">Limit: 99 000 000 + transform="matrix(0.5,0,0,0.5,60.383093,38.772372)"> Limit: 60 000 + id="tspan6-4">Limit: 70 000 + transform="matrix(0.5,0,0,0.5,112.93599,80.394972)"> System: MIRSystem: VISALimit: 60 000 + id="tspan6-6">Limit: 80 000 + id="g11" + transform="translate(20.10834,-13.758331)"> + width="36.62112" + height="15.217095" + x="64.059044" + y="145.0899" /> id: 8 + style="stroke-width:0.132291" + x="64.890747" + y="148.347">id: 8 System: MIRSystem: MASTERCARDLimit: 60 000 + style="stroke-width:0.132291" + x="64.890747" + y="156.8812" + id="tspan6-61">Limit: 90 000 - - - - id: 9 - System: MIRLimit: 60 000 + id="g7" + transform="matrix(0.60459582,0,0,0.49924759,-2.9448202,80.460772)"> + + id: 9 + System: VISALimit: 10 000 000 + transform="matrix(0.5,0,0,0.5,6.0394815,38.772372)"> Limit: 60 000 + style="fill:none;stroke:#0000ca;stroke-width:0.3325;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#ConcaveTriangle-5)" + d="M 53.88534,90.980786 53.84652,114.9536" + id="path8" + sodipodi:nodetypes="cc" /> - - + Sum: 23412Count: 6 + Sum: 13214.1Count: 5 + Sum: 19999.1Count: 6 + Sum: 69999.1Count: 16 + Sum: 8999.1Count: 7 + Sum: 59999.1Count: 12 + Sum: 99999.1Count: 5 + Sum: 79999.1Count: 15 + Sum: 999999.1Count: 9 + Sum: 49999.1Count: 12 + Sum: 92223Count: 9 + Sum: 81312Count: 7 + Sum: 16325.99Count: 5 + Sum: 62412Count: 9 + From 2de046cdd4d7ee9f7861868072f5b87254df6f99 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 11:54:39 +0300 Subject: [PATCH 06/22] =?UTF-8?q?=D0=92=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5,=20=D0=B8=D0=B7=D0=BE=D0=B1=D1=80=D0=B0=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5,=20=D1=82=D0=B8=D0=BF=D1=8B=20=D0=BC?= =?UTF-8?q?=D0=B5=D1=82=D0=BE=D0=BA.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 75 ++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 61 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 3b64f81..77087a0 100644 --- a/README.md +++ b/README.md @@ -7,31 +7,78 @@ Stand for PageRank algorithm benchmark В качестве примера возьмём следующую задачу. Пусть есть граф с двумя типами вершин: пользователи и карты. -Три типа ориентированных рёбер: +Также есть два типа ориентированных рёбер: * "Перевод": соединяет две карты (откуда и куда перевод) -* "Звонок": соединяет двух пользователей (кто кому звонил) * "Владеет": соединяет пользователя и карту (от владельца карты к карте) Каждый тип вершины имеет свой набор атрибутов. -* "Пользователь": пол, ФИО, год рождения -* "Карта": тип, год выпуска +* "Пользователь": пол, возраст +* "Карта": тип, лимит средств + +Пусть будут следующие типы карт: МИР, VISA, MASTERCARD. Каждый тип рёбер также имеет свой набор атрибутов. * "Перевод": общая сумма, "количество транзакций" -* "Звонок": суммарная продолжительность в секундах * "Владеет": не имеет атрибутов -Хотим выбрать по некоторому критерию пользователей их карты и для анализа переводов хотим посчитать PageRank на подграфе, заданном переводами между отобранными картами. -Выбрать хотим все карты системы "МИР", которыми владеют пользователи мужского пола старше заданного года рождения. - +Для примера возьмём следующий граф. ![Пример графа](./Figures/Graph.svg) +У каждой вершины есть уникальный идентификатор, синие рёбра отображают переводы, красные --- отношение владения, розовые вершины --- пользователи, синие --- карты. + +Хотим выбрать по некоторому критерию пользователей и их карты, а затем для анализа переводов хотим посчитать PageRank на подграфе, заданном переводами между отобранными картами. +Выбрать хотим все карты системы "МИР", которыми владеют пользователи мужского пола старше заданного года рождения. Покажем, как это можно сделать, используя матрично-векторные операции, в частности [GraphBLAS](https://github.com/GraphBLAS). +Полный код разбираемого примера мрожно увидеть в файле [!!!!](!!!!). + +GraphBLAS позволяет в качестве атрибутов использовать пользовательские типы (фиксированных размеров), потому объявим необходимый нам набор типов. +```c +// Тип карты +typedef enum +{ + VISA, + MIR, + MASTERCARD, +} System; + +// Пол +typedef enum +{ + MALE, + FEMALE, +} Gender; + +// Данные о пользователе +typedef struct +{ + Gender gender; + uint8_t age; +} User; + +// Данные о карте +typedef struct +{ + System system; + double limit; +} Card; + +// Данные о переводах +typedef struct +{ + double sum; + uint32_t count; +} EdgeTX; +``` + +Граф представлен как набор матриц и векторов: по одной матрице на каждый тип рёбер и по одному вектору на каждый тип вершин. +Считаем при этом, что все вершины, вне зависимости от типа, занумерованы с 0 подряд (id вершин на рисунке). +Таким образом, нам понядобятся две матрицы!!! -Атрибуты --- структуры. - -Граф представлен как набор матриц и векторов. По одной матрице на каждый тип рёбер и по одному вектору на каждый тип вершин. -Считаем при этом, что все вершины, вне зависимости от типа, занумерованы с 0 подряд. - -Картинка с тем, как хранится наш граф. +$$ +\texttt{TX-Edges}= +\begin{pmatrix} +\{Sum:104353; Count: 4 \} & . \\ +. & b +\end{pmatrix} +$$ Первым делов фильтруем пользователей. Select. Пример кода, полукольцо и т.д. From f1a1407733fa8a54f8ea4adda51323228188a5c5 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 12:50:52 +0300 Subject: [PATCH 07/22] =?UTF-8?q?=D0=9F=D1=80=D0=B5=D0=B4=D1=81=D1=82?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D1=84=D0=B0=20=D0=B2=20=D0=B2=D0=B8=D0=B4=D0=B5=20=D0=BC=D0=B0?= =?UTF-8?q?=D1=82=D1=80=D0=B8=D1=86=20=D1=81=D0=BC=D0=B5=D0=B6=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B8.=20=D0=9F=D0=BE=D0=BA=D0=B0=20=D0=B1=D0=B5?= =?UTF-8?q?=D0=B7=20=D0=B2=D0=B5=D0=BA=D1=82=D0=BE=D1=80=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=BF=D0=BE=D0=B4=20=D0=B2=D0=B5=D1=80=D1=88=D0=B8=D0=BD=D1=8B?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 77087a0..4e04f0e 100644 --- a/README.md +++ b/README.md @@ -70,16 +70,45 @@ typedef struct Граф представлен как набор матриц и векторов: по одной матрице на каждый тип рёбер и по одному вектору на каждый тип вершин. Считаем при этом, что все вершины, вне зависимости от типа, занумерованы с 0 подряд (id вершин на рисунке). -Таким образом, нам понядобятся две матрицы!!! +Таким образом, нам понядобятся две матрицы!!! $$ \texttt{TX-Edges}= \begin{pmatrix} -\{Sum:104353; Count: 4 \} & . \\ -. & b +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & \\{23412; 6\\} & . & . & \\{13214.1; 5\\} & . & \\{99999.1; 5\\} & . \\ +. & . & . & . & \\{13214.1; 5\\} & . & \\{81312; 7\\} & . & \\{92223; 9\\} & . & \\{19999.1; 6\\} & . \\ +. & . & . & . & . & . & . & . & . & . & . & \\{8999.1; 7\\} \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & \\{16325.99; 5\\} & . & . & . & . & . & . & \\{49999.1; 12\\} \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & \\{79999.1; 15\\} & \\{69999.1; 16\\} & . & . & . & . & . & . \\ +. & . & . & . & . & . & \\{59999.1; 12\\} & . & \\{999999.1; 9\\} & . & . & . \\ \end{pmatrix} $$ +$$ +\texttt{Owns-Edges}= +\begin{pmatrix} +. & . & . & . & . & . & . & 1 & . & . & . & . \\ +. & . & . & . & . & . & 1 & 1 & . & . & . & . \\ +. & . & . & . & . & 1 & . & . & . & . & . & . \\ +. & . & . & . & 1 & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & 1 & 1 \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +\end{pmatrix} +$$ + + Первым делов фильтруем пользователей. Select. Пример кода, полукольцо и т.д. Далее, создаём диагональную матрицу из отобранных вершин и фильтруем рёбра через умножение полученной матрицы на матрицу, хранящую соответствующий тип рёбер. From bf598ed6c19988adf9ecae7c1c517142d921d617 Mon Sep 17 00:00:00 2001 From: gsv Date: Tue, 11 Nov 2025 12:52:01 +0300 Subject: [PATCH 08/22] =?UTF-8?q?=D0=92=D0=B5=D1=80=D1=88=D0=B8=D0=BD?= =?UTF-8?q?=D1=8B=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BD=D1=83=D0=BC=D0=B5=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D1=8B=20=D1=81=200.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Figures/Graph.svg | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Figures/Graph.svg b/Figures/Graph.svg index dbf7368..2c5706f 100644 --- a/Figures/Graph.svg +++ b/Figures/Graph.svg @@ -23,13 +23,13 @@ inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" - inkscape:zoom="1.3113356" - inkscape:cx="369.08935" - inkscape:cy="406.07455" - inkscape:window-width="1920" - inkscape:window-height="1131" - inkscape:window-x="0" - inkscape:window-y="32" + inkscape:zoom="1.8545086" + inkscape:cx="395.52258" + inkscape:cy="379.34578" + inkscape:window-width="2560" + inkscape:window-height="1403" + inkscape:window-x="1920" + inkscape:window-y="0" inkscape:window-maximized="1" inkscape:current-layer="layer1" /> id: 4 + y="36.808945">id: 3 id: 2 + y="36.808945">id: 1 id: 3 + y="36.808945">id: 2 id: 10 + y="36.808945">id: 9 id: 1 + y="36.808945">id: 0 id: 11 + y="106.72439">id: 10 id: 12 + y="106.72439">id: 11 id: 6 + y="78.754021">id: 5 id: 7 + y="78.754021">id: 6 id: 8 + y="148.347">id: 7 id: 9 + y="119.77202">id: 8 id: 5 + y="78.754021">id: 4 Date: Tue, 11 Nov 2025 13:05:55 +0300 Subject: [PATCH 09/22] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0=20=D0=BF=D0=BE=D0=B4=20=D0=B2=D0=B5=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 4e04f0e..b4c6f40 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ typedef struct Граф представлен как набор матриц и векторов: по одной матрице на каждый тип рёбер и по одному вектору на каждый тип вершин. Считаем при этом, что все вершины, вне зависимости от типа, занумерованы с 0 подряд (id вершин на рисунке). -Таким образом, нам понядобятся две матрицы!!! +Таким образом, нам понядобятся две матрицы: $$ \texttt{TX-Edges}= @@ -79,14 +79,14 @@ $$ . & . & . & . & . & . & . & . & . & . & . & . \\ . & . & . & . & . & . & . & . & . & . & . & . \\ . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & \\{23412; 6\\} & . & . & \\{13214.1; 5\\} & . & \\{99999.1; 5\\} & . \\ -. & . & . & . & \\{13214.1; 5\\} & . & \\{81312; 7\\} & . & \\{92223; 9\\} & . & \\{19999.1; 6\\} & . \\ -. & . & . & . & . & . & . & . & . & . & . & \\{8999.1; 7\\} \\ +. & . & . & . & . & \\{23 \ 412; 6\\} & . & . & \\{13 214.1; 5\\} & . & \\{99 999.1; 5\\} & . \\ +. & . & . & . & \\{13 214.1; 5\\} & . & \\{81 312; 7\\} & . & \\{92 223; 9\\} & . & \\{19 999.1; 6\\} & . \\ +. & . & . & . & . & . & . & . & . & . & . & \\{8 999.1; 7\\} \\ . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & \\{16325.99; 5\\} & . & . & . & . & . & . & \\{49999.1; 12\\} \\ +. & . & . & . & \\{16 325.99; 5\\} & . & . & . & . & . & . & \\{49 999.1; 12\\} \\ . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & \\{79999.1; 15\\} & \\{69999.1; 16\\} & . & . & . & . & . & . \\ -. & . & . & . & . & . & \\{59999.1; 12\\} & . & \\{999999.1; 9\\} & . & . & . \\ +. & . & . & . & \\{79 999.1; 15\\} & \\{69 999.1; 16\\} & . & . & . & . & . & . \\ +. & . & . & . & . & . & \\{59 999.1; 12\\} & . & \\{999 999.1; 9\\} & . & . & . \\ \end{pmatrix} $$ @@ -108,6 +108,17 @@ $$ \end{pmatrix} $$ +И два вектора: + +$$ +\texttt{Users} = +\begin{pmatrix} +\\{F; 52\\} & \\{F; 25\\} & \\{F; 40\\} & \\{M; 42\\} & . & . & . & . & . & \\{M; 35\\} & . & . +\end{pmatrix} +$$ +$$ +\texttt{Cards} = [. ; . ; . ; . ; \\{\text{MIR}; 60 000\\} ; \\{MIR; 70 000\\} ; \\{VISA; 80 000\\} ; \\{MASTERCARD; 90 000\\} ; \\{VISA; 10 000 000\\} ; . ; \\{MIR; 99 000 000\\} ; \\{MIR; 99 000 000\\} ] +$$ Первым делов фильтруем пользователей. Select. Пример кода, полукольцо и т.д. From f9c7fadbd1b769d462927b91f3ce0174605a8abc Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 14:19:37 +0300 Subject: [PATCH 10/22] =?UTF-8?q?=D0=A4=D0=B8=D0=BB=D1=8C=D1=82=D1=80?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D0=B5=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 97 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index b4c6f40..8488026 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ typedef struct ``` Граф представлен как набор матриц и векторов: по одной матрице на каждый тип рёбер и по одному вектору на каждый тип вершин. +Матрицы и вектора в большинстве случаев будут разреженными и мы будем использовать символ '$.$' для обозначения отсутсвующего элемента. Считаем при этом, что все вершины, вне зависимости от типа, занумерованы с 0 подряд (id вершин на рисунке). Таким образом, нам понядобятся две матрицы: @@ -79,21 +80,21 @@ $$ . & . & . & . & . & . & . & . & . & . & . & . \\ . & . & . & . & . & . & . & . & . & . & . & . \\ . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & \\{23 \ 412; 6\\} & . & . & \\{13 214.1; 5\\} & . & \\{99 999.1; 5\\} & . \\ -. & . & . & . & \\{13 214.1; 5\\} & . & \\{81 312; 7\\} & . & \\{92 223; 9\\} & . & \\{19 999.1; 6\\} & . \\ -. & . & . & . & . & . & . & . & . & . & . & \\{8 999.1; 7\\} \\ +. & . & . & . & . & \\{23 \ 412; 6\\} & . & . & \\{13 \ 214.1; 5\\} & . & \\{99 \ 999.1; 5\\} & . \\ +. & . & . & . & \\{13 \ 214.1; 5\\} & . & \\{81 \ 312; 7\\} & . & \\{92 \ 223; 9\\} & . & \\{19 \ 999.1; 6\\} & . \\ +. & . & . & . & . & . & . & . & . & . & . & \\{8 \ 999.1; 7\\} \\ . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & \\{16 325.99; 5\\} & . & . & . & . & . & . & \\{49 999.1; 12\\} \\ +. & . & . & . & \\{16 \ 325.99; 5\\} & . & . & . & . & . & . & \\{49 \ 999.1; 12\\} \\ . & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & \\{79 999.1; 15\\} & \\{69 999.1; 16\\} & . & . & . & . & . & . \\ -. & . & . & . & . & . & \\{59 999.1; 12\\} & . & \\{999 999.1; 9\\} & . & . & . \\ +. & . & . & . & \\{79 \ 999.1; 15\\} & \\{69 \ 999.1; 16\\} & . & . & . & . & . & . \\ +. & . & . & . & . & . & \\{59 \ 999.1; 12\\} & . & \\{999 \ 999.1; 9\\} & . & . & . \\ \end{pmatrix} $$ $$ \texttt{Owns-Edges}= \begin{pmatrix} -. & . & . & . & . & . & . & 1 & . & . & . & . \\ +. & . & . & . & . & . & . & . & 1 & . & . & . \\ . & . & . & . & . & . & 1 & 1 & . & . & . & . \\ . & . & . & . & . & 1 & . & . & . & . & . & . \\ . & . & . & . & 1 & . & . & . & . & . & . & . \\ @@ -112,23 +113,87 @@ $$ $$ \texttt{Users} = -\begin{pmatrix} -\\{F; 52\\} & \\{F; 25\\} & \\{F; 40\\} & \\{M; 42\\} & . & . & . & . & . & \\{M; 35\\} & . & . -\end{pmatrix} +[\\{F; 52\\} \ ; \ \\{F; 25\\} \ ; \ \\{F; 40\\} \ ; \ \\{M; 42\\} \ ; \ . \ ; \ . \ ; \ . \ ; \ . \ ; \ . \ ; \ \\{M; 35\\} \ ; \ . \ ; \ . ] $$ + $$ -\texttt{Cards} = [. ; . ; . ; . ; \\{\text{MIR}; 60 000\\} ; \\{MIR; 70 000\\} ; \\{VISA; 80 000\\} ; \\{MASTERCARD; 90 000\\} ; \\{VISA; 10 000 000\\} ; . ; \\{MIR; 99 000 000\\} ; \\{MIR; 99 000 000\\} ] +\texttt{Cards} = +[. \ ; \ . \ ; \ . \ ; \ . \ ; \ \\{\text{MIR}; 60 \ 000\\} \ ; \ \\{\text{MIR}; 70 \ 000\\} \ ; \ \\{\text{VISA}; 80 \ 000\\} \ ; \ \\{\text{MASTERCARD}; 90 \ 000\\} \ ; \ \\{\text{VISA}; 10 \ 000 \ 000\\} \ ; \ . \ ; \ \\{\text{MIR}; 99 \ 000 \ 000\\} \ ; \ \\{\text{MIR}; 99 \ 000 \ 000\\} ] $$ -Первым делов фильтруем пользователей. Select. Пример кода, полукольцо и т.д. +Первым делом фильтруем пользователей по возрасту. +Скажем, нас будут интересовать пользователи старше 30 лет. +Для этого в GraphBLAS есть функция ```Select```, которая фильтрует коллекции, используя функцию-предикат принимаемую в качестве аргумента. -Далее, создаём диагональную матрицу из отобранных вершин и фильтруем рёбра через умножение полученной матрицы на матрицу, хранящую соответствующий тип рёбер. +Так как нам предстоит работать с пользовательскими типами, то предётся написать собственный предикат. -Пример кода. +```c +void check_user_age(bool *z, const User *x, GrB_Index _i, GrB_Index _j, const uint8_t *y) +{ + *z = (x->age > *y); +} +``` + +Два дополнительных параметра типа ```GrB_Index``` позволяют, при необходимости, использовать в фильтре координаты рассматриваемого элемента. + +Для того, чтобы выбрать карты, принадлежащие выбранным пользователям, нам необходимо получить "концы" рёбер типа Owns, исходящие из выбранных пользователей. +Чтобы сделать это, воспользуемся тем фактом, что выбор исходящих рёбер, инцидентных заданному множеству вершин --- это умножение матрицы смежности на диагональную матрицу, в которой ненулевые элементы на местах интересующих ас вершин, слева. +То есть нам необходимо вычислить следующее произведение. + +$$ +\texttt{Filtered-Owns} = +\begin{pmatrix} +\\{M; 42\\} & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & \\{F; 40\\} & . & . & . & . & . & . & . & . & . \\ +. & . & . & \\{M; 42\\} & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & \\{F; 35\\} & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +\end{pmatrix} +\otimes +\begin{pmatrix} +. & . & . & . & . & . & . & . & 1 & . & . & . \\ +. & . & . & . & . & . & 1 & 1 & . & . & . & . \\ +. & . & . & . & . & 1 & . & . & . & . & . & . \\ +. & . & . & . & 1 & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & 1 & 1 \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +\end{pmatrix} = +\begin{pmatrix} +. & . & . & . & . & . & . & . & 1 & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & 1 & . & . & . & . & . & . \\ +. & . & . & . & 1 & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & 1 & 1 \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +\end{pmatrix} +$$ + +Здесь операция $\otimes$ требует задания специфичных поэлементных операций $+$ и $*$ (в терминах GraphBLAS необходимо мконструировать пользовательское полукольцо). + +Для получения карт редуцируем матрицу $\texttt{Filtered-Owns}$ построчно. +Чтобы получить переводы только между отобранными картами применим уже известную технику с диагональной матрицей. +Но в данном случае нам необходимо умножить на неё и слева, и справа (нам важно, чтобы все рёбра шли **только** между отобранными картами). -Далее редукция полученной матрицы, чтобы получить карты и снова диагональная матрица и умножение, чтобы получить переводы только между нужными нам картами. -Пример кода. Конструируем матрицу, по которой будем считать PageRank. В качестве исходного веса ребра берём 1 - (средняя сумма перевода). From 85a783934ceaba1b0892f244eebe250e812d98e1 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 15:11:57 +0300 Subject: [PATCH 11/22] =?UTF-8?q?=D0=9F=D0=BE=D0=B4=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D1=84=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20PageRank=20=D0=B3=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8488026..f20d277 100644 --- a/README.md +++ b/README.md @@ -189,11 +189,84 @@ $$ Здесь операция $\otimes$ требует задания специфичных поэлементных операций $+$ и $*$ (в терминах GraphBLAS необходимо мконструировать пользовательское полукольцо). +$$ +\+ : \textit{bool} \times \textit{bool} \to \textit{bool} +$$ +$$ +\* : \textit{User} \times \textit{bool} \to \textit{bool} +$$ + +В качестве конкрьеных реализаций для $+$ можно взять логическое "и", а в качестве $*$ операцию $\textit{second}$ (вернуть второй элемент из пары). + Для получения карт редуцируем матрицу $\texttt{Filtered-Owns}$ построчно. Чтобы получить переводы только между отобранными картами применим уже известную технику с диагональной матрицей. -Но в данном случае нам необходимо умножить на неё и слева, и справа (нам важно, чтобы все рёбра шли **только** между отобранными картами). +Но в данном случае нам необходимо умножить на неё и слева, и справа (нам важно, чтобы все рёбра шли **только между** отобранными картами). +$$ +\texttt{Filtered-Transactions} = +\begin{pmatrix} +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & 1 & . & . & . & . & . & . & . \\ +. & . & . & . & . & 1 & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & 1 & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & 1 & . \\ +. & . & . & . & . & . & . & . & . & . & . & 1 \\ +\end{pmatrix} +\otimes_1 +\begin{pmatrix} +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & \\{23 \ 412; 6\\} & . & . & \\{13 \ 214.1; 5\\} & . & \\{99 \ 999.1; 5\\} & . \\ +. & . & . & . & \\{13 \ 214.1; 5\\} & . & \\{81 \ 312; 7\\} & . & \\{92 \ 223; 9\\} & . & \\{19 \ 999.1; 6\\} & . \\ +. & . & . & . & . & . & . & . & . & . & . & \\{8 \ 999.1; 7\\} \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & \\{16 \ 325.99; 5\\} & . & . & . & . & . & . & \\{49 \ 999.1; 12\\} \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & \\{79 \ 999.1; 15\\} & \\{69 \ 999.1; 16\\} & . & . & . & . & . & . \\ +. & . & . & . & . & . & \\{59 \ 999.1; 12\\} & . & \\{999 \ 999.1; 9\\} & . & . & . \\ +\end{pmatrix} +\otimes_2 +\begin{pmatrix} +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & 1 & . & . & . & . & . & . & . \\ +. & . & . & . & . & 1 & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & 1 & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & 1 & . \\ +. & . & . & . & . & . & . & . & . & . & . & 1 \\ +\end{pmatrix} = +\begin{pmatrix} +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & \\{23 \ 412; 6\\} & . & . & \\{13 \ 214.1; 5\\} & . & \\{99 \ 999.1; 5\\} & . \\ +. & . & . & . & \\{13 \ 214.1; 5\\} & . & . & . & \\{92 \ 223; 9\\} & . & \\{19 \ 999.1; 6\\} & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & \\{16 \ 325.99; 5\\} & . & . & . & . & . & . & \\{49 \ 999.1; 12\\} \\ +. & . & . & . & . & . & . & . & . & . & . & . \\ +. & . & . & . & \\{79 \ 999.1; 15\\} & \\{69 \ 999.1; 16\\} & . & . & . & . & . & . \\ +. & . & . & . & . & . & . & . & \\{999 \ 999.1; 9\\} & . & . & . \\ +\end{pmatrix} +$$ +Здесь операции $\otimes_1$ и $\otimes_2$ также требуют задания пользовательских полуколец, как и в предыдущем случае. +Конструироваться они будут по аналогии. +Необходимо только проследить за тем, в какие моменты надо брать первый элемент из пары, а в какие вотрой, чтобы в результате получилась матрица с элементами типа $\texttt{EdgeTX}$ Конструируем матрицу, по которой будем считать PageRank. В качестве исходного веса ребра берём 1 - (средняя сумма перевода). From c9839f9b3835cde3d3e75800c9d8774126a88a22 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 15:28:23 +0300 Subject: [PATCH 12/22] =?UTF-8?q?=D0=9F=D0=BE=D0=B4=D0=B3=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D0=B2=D0=BA=D0=B0=20=D0=BA=20PageRank?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f20d277..1bb3993 100644 --- a/README.md +++ b/README.md @@ -268,15 +268,18 @@ $$ Конструироваться они будут по аналогии. Необходимо только проследить за тем, в какие моменты надо брать первый элемент из пары, а в какие вотрой, чтобы в результате получилась матрица с элементами типа $\texttt{EdgeTX}$ -Конструируем матрицу, по которой будем считать PageRank. -В качестве исходного веса ребра берём 1 - (средняя сумма перевода). -Для построения распределения будем использовать идею функции Softmax, которая задаётся следующим образом. +Подграф готов. +Теперь неорбходимо сконструировать матрицу, по которой непосредственно будем считать PageRank. +Сейчас метки рёбер --- структуры, хранящие информацию о переврдах, а мы хотим получить одно число. +При этом важно, чтобы сумма весов всех исходящих рёбер была равна единице. +Для примера действовать будем следующим образом: возьмём "средний размер транзакции" (вычислим как $\frac{\textit{Sum}}{\textit{Count}}$), поделим на 1000 (на всякий случай, чтобы избежать слишком больших знчений) и затем построчно примерним Softmax. +Иными словами, будем использовать идею функции Softmax, которая задаётся следующим образом. $$ {\displaystyle \sigma (\overrightarrow{z})_{i}={\frac {e^{z_{i}}}{\displaystyle \sum _{k\mathop {=} 1}^{K}e^{z_{k}}}}} $$ -В нашем случае подобная функция должна быть применена к каждой строке матрицы, задающей переводы. При этом должна быть задана некая функция $f$, получающая вес ребра по его атрибутам. +В нашем случае подобная функция должна быть применена к каждой строке матрицы, задающей переводы. При этом должна быть определена функция $f$, которая получает вес ребра по его атрибутам (вычисляет $\frac{\textit{Sum}}{\textit{Count} * 1000}$). То есть итоговая формула выглядит следующим образом. $$ From daefbbce21f202b7bbf2b811f68aac974ea45e79 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 16:57:23 +0300 Subject: [PATCH 13/22] =?UTF-8?q?=D0=9F=D0=B0=D1=80=D0=B0=20=D1=81=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=BF=D1=80=D0=BE=20PageRank.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Осталост синхронищировать с кодом * Ссылки * Шаг обхода в ширину вместо диагонали и редукции. --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 1bb3993..2a51a02 100644 --- a/README.md +++ b/README.md @@ -286,11 +286,11 @@ $$ {\displaystyle \sigma (\overrightarrow{z})_{i}={\frac {e^{f(z_{i})}}{\displaystyle \sum _{k\mathop {=} 1}^{K}e^{f(z_{k})}}}} $$ -Вычислять будем следующим образом. Сперва выполним редукцию по колонкам. Таким образом получим знаменатель дроби. -После этого тензорно умножим полученный вектор на вектор из единиц, использую исходную матрицу в качестве маски. Таким образом получим матрицу, в которой знаменатель стоит на необходимых местах. После чего поэлементно поделим две матрицы. - -Пример кода. - -Запускаем PageRank. - -Пример кода. +Вычисления построим следующим образом. Сперва выполним редукцию по колонкам с использованием функции $f$: таким образом получим знаменатель дроби. +После этого сконструируем две квадратные матрицы: в одной нулевой столбец --- это получанный вектор, а остальные нули, в другой --- нулевая строка --- единицы, остальное --- нули. +Перемножим эти две матрицы, использую исходную матрицу $\texttt{Filtered-Transactions}$ в качестве маски. +Таким образом получим матрицу, в которой знаменатель стоит на необходимых местах. +Также нам нужна будет матрица, содержащая числители дробей (получается поэлементным примерением соответствующей функции к $\texttt{Filtered-Transactions}$) +После чего поэлементно поделим эти две матрицы. + +Далее на полученной матрице запускаем [классический алгоритм PageRank](!!!) (правда, без "телепортации" в несвязанные вершины), который в терминах линейной алгебры реалищуется по определению: итеративное умножение исходной матрицы на вектор. From 560eb426d317ec37c589a0d1cb7229a3887b4a97 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 17:31:48 +0300 Subject: [PATCH 14/22] =?UTF-8?q?=D0=9E=D0=BF=D0=B5=D1=87=D0=B0=D1=82?= =?UTF-8?q?=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rodion Suvorov <107667059+suvorovrain@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a51a02..8e758c6 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ void check_user_age(bool *z, const User *x, GrB_Index _i, GrB_Index _j, const ui Два дополнительных параметра типа ```GrB_Index``` позволяют, при необходимости, использовать в фильтре координаты рассматриваемого элемента. Для того, чтобы выбрать карты, принадлежащие выбранным пользователям, нам необходимо получить "концы" рёбер типа Owns, исходящие из выбранных пользователей. -Чтобы сделать это, воспользуемся тем фактом, что выбор исходящих рёбер, инцидентных заданному множеству вершин --- это умножение матрицы смежности на диагональную матрицу, в которой ненулевые элементы на местах интересующих ас вершин, слева. +Чтобы сделать это, воспользуемся тем фактом, что выбор исходящих рёбер, инцидентных заданному множеству вершин --- это умножение матрицы смежности на диагональную матрицу, в которой ненулевые элементы на местах интересующих нас вершин, слева. То есть нам необходимо вычислить следующее произведение. $$ From dfa90d4ff55feae4732818b33e2f5c472e70eb98 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 17:32:07 +0300 Subject: [PATCH 15/22] =?UTF-8?q?=D0=9E=D0=BF=D0=B5=D1=87=D0=B0=D1=82?= =?UTF-8?q?=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rodion Suvorov <107667059+suvorovrain@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8e758c6..b0a1e85 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,7 @@ $$ \end{pmatrix} $$ -Здесь операция $\otimes$ требует задания специфичных поэлементных операций $+$ и $*$ (в терминах GraphBLAS необходимо мконструировать пользовательское полукольцо). +Здесь операция $\otimes$ требует задания специфичных поэлементных операций $+$ и $*$ (в терминах GraphBLAS необходимо сконструировать пользовательское полукольцо). $$ \+ : \textit{bool} \times \textit{bool} \to \textit{bool} From 116b9d215d81fe6bd99ef0eec0e06a90f6bfea49 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 17:34:27 +0300 Subject: [PATCH 16/22] =?UTF-8?q?=D0=9E=D0=BF=D0=B5=D1=87=D0=B0=D1=82?= =?UTF-8?q?=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rodion Suvorov <107667059+suvorovrain@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b0a1e85..90b4306 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ $$ \* : \textit{User} \times \textit{bool} \to \textit{bool} $$ -В качестве конкрьеных реализаций для $+$ можно взять логическое "и", а в качестве $*$ операцию $\textit{second}$ (вернуть второй элемент из пары). +В качестве конкретных реализаций для $+$ можно взять логическое "И", а в качестве $*$ операцию $\textit{second}$ (вернуть второй элемент из пары). Для получения карт редуцируем матрицу $\texttt{Filtered-Owns}$ построчно. Чтобы получить переводы только между отобранными картами применим уже известную технику с диагональной матрицей. From f43554bcf9d80c07c02b9eae57e09af7ea756b61 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 17:34:49 +0300 Subject: [PATCH 17/22] =?UTF-8?q?=D0=9E=D0=BF=D0=B5=D1=87=D0=B0=D1=82?= =?UTF-8?q?=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rodion Suvorov <107667059+suvorovrain@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 90b4306..69edd9d 100644 --- a/README.md +++ b/README.md @@ -270,7 +270,7 @@ $$ Подграф готов. Теперь неорбходимо сконструировать матрицу, по которой непосредственно будем считать PageRank. -Сейчас метки рёбер --- структуры, хранящие информацию о переврдах, а мы хотим получить одно число. +Сейчас метки рёбер --- структуры, хранящие информацию о переводах, а мы хотим получить одно число. При этом важно, чтобы сумма весов всех исходящих рёбер была равна единице. Для примера действовать будем следующим образом: возьмём "средний размер транзакции" (вычислим как $\frac{\textit{Sum}}{\textit{Count}}$), поделим на 1000 (на всякий случай, чтобы избежать слишком больших знчений) и затем построчно примерним Softmax. Иными словами, будем использовать идею функции Softmax, которая задаётся следующим образом. From 53baef38a1a629331f1a77659927a733d854a3f3 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 18:08:09 +0300 Subject: [PATCH 18/22] =?UTF-8?q?=D0=97=D0=B0=D0=BC=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80=D0=B0=D1=86=D0=B8?= =?UTF-8?q?=D1=8E=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20=D1=83=D0=BC=D0=BD?= =?UTF-8?q?=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B0=20=D0=B4?= =?UTF-8?q?=D0=B8=D0=B0=D0=B3=D0=BE=D0=BD=D0=B0=D0=BB=D1=8C=20=D0=BD=D0=B0?= =?UTF-8?q?=20=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=20=D0=B2=20=D1=88=D0=B8=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 76 +++++++++++++++++++++++-------------------------------- 1 file changed, 31 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 69edd9d..495f3d0 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Stand for PageRank algorithm benchmark У каждой вершины есть уникальный идентификатор, синие рёбра отображают переводы, красные --- отношение владения, розовые вершины --- пользователи, синие --- карты. Хотим выбрать по некоторому критерию пользователей и их карты, а затем для анализа переводов хотим посчитать PageRank на подграфе, заданном переводами между отобранными картами. -Выбрать хотим все карты системы "МИР", которыми владеют пользователи мужского пола старше заданного года рождения. Покажем, как это можно сделать, используя матрично-векторные операции, в частности [GraphBLAS](https://github.com/GraphBLAS). +Выбрать хотим все карты системы "МИР", которыми владеют люди старше заданного возраста. Покажем, как это можно сделать, используя матрично-векторные операции, в частности [GraphBLAS](https://github.com/GraphBLAS). Полный код разбираемого примера мрожно увидеть в файле [!!!!](!!!!). GraphBLAS позволяет в качестве атрибутов использовать пользовательские типы (фиксированных размеров), потому объявим необходимый нам набор типов. @@ -137,25 +137,15 @@ void check_user_age(bool *z, const User *x, GrB_Index _i, GrB_Index _j, const ui Два дополнительных параметра типа ```GrB_Index``` позволяют, при необходимости, использовать в фильтре координаты рассматриваемого элемента. Для того, чтобы выбрать карты, принадлежащие выбранным пользователям, нам необходимо получить "концы" рёбер типа Owns, исходящие из выбранных пользователей. -Чтобы сделать это, воспользуемся тем фактом, что выбор исходящих рёбер, инцидентных заданному множеству вершин --- это умножение матрицы смежности на диагональную матрицу, в которой ненулевые элементы на местах интересующих нас вершин, слева. +Чтобы сделать это, выполним один шаг обхода в ширину, который в терминах линейной алгебры выражается через умноженеи вектора текущих вершин на матрицу смежности. +Текущие вершины в нашем случае --- выбранные пользователи. То есть нам необходимо вычислить следующее произведение. $$ -\texttt{Filtered-Owns} = -\begin{pmatrix} -\\{M; 42\\} & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & \\{F; 40\\} & . & . & . & . & . & . & . & . & . \\ -. & . & . & \\{M; 42\\} & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & \\{F; 35\\} & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -\end{pmatrix} +\texttt{Filtered-Cards} = +$$ +$$ +[\\{F; 52\\} \ ; \ . \ ; \ \\{F; 40\\} \ ; \ \\{M; 42\\} \ ; \ . \ ; \ . \ ; \ . \ ; \ . \ ; \ . \ ; \ \\{M; 35\\} \ ; \ . \ ; \ . ] \otimes \begin{pmatrix} . & . & . & . & . & . & . & . & 1 & . & . & . \\ @@ -170,37 +160,22 @@ $$ . & . & . & . & . & . & . & . & . & . & 1 & 1 \\ . & . & . & . & . & . & . & . & . & . & . & . \\ . & . & . & . & . & . & . & . & . & . & . & . \\ -\end{pmatrix} = -\begin{pmatrix} -. & . & . & . & . & . & . & . & 1 & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & 1 & . & . & . & . & . & . \\ -. & . & . & . & 1 & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & 1 & 1 \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -. & . & . & . & . & . & . & . & . & . & . & . \\ -\end{pmatrix} +\end{pmatrix} = $$ - -Здесь операция $\otimes$ требует задания специфичных поэлементных операций $+$ и $*$ (в терминах GraphBLAS необходимо сконструировать пользовательское полукольцо). - $$ -\+ : \textit{bool} \times \textit{bool} \to \textit{bool} -$$ -$$ -\* : \textit{User} \times \textit{bool} \to \textit{bool} +[. \ ; \ . \ ; \ . \ ; \ . \ ; \ 1 \ ; \ 1 \ ; \ . \ ; \ . \ ; \ 1 \ ; \ . \ ; \ 1 \ ; \ 1] $$ -В качестве конкретных реализаций для $+$ можно взять логическое "И", а в качестве $*$ операцию $\textit{second}$ (вернуть второй элемент из пары). +Мы получили не совсем карты, но вектор, который указывает, какие карты нас интересуют. +Вспомним, что мы хотим взять только карты "МИР". +Для этого снова будем использовать Select, а полученный вектор $\texttt{Filtered-Cards}$ будем использовать как маску, чтобы дополнительно тфильтровать результат. + -Для получения карт редуцируем матрицу $\texttt{Filtered-Owns}$ построчно. -Чтобы получить переводы только между отобранными картами применим уже известную технику с диагональной матрицей. -Но в данном случае нам необходимо умножить на неё и слева, и справа (нам важно, чтобы все рёбра шли **только между** отобранными картами). +Чтобы получить переводы только между отобранными картами, воспользуемся тем фактом, что выбор исходящих рёбер, инцидентных заданному множеству вершин --- это умножение матрицы смежности на диагональную матрицу, в которой ненулевые элементы на местах интересующих нас вершин, слева. +Для входящих рёбер нужно аналогичное умножение справа. +То есть нам необходимо вычислить следующее произведение. + +То есть данном случае нам необходимо умножить на диагональную матрицу и слева, и справа (нам важно, чтобы все рёбра шли **только между** отобранными картами). $$ \texttt{Filtered-Transactions} = @@ -264,8 +239,19 @@ $$ \end{pmatrix} $$ -Здесь операции $\otimes_1$ и $\otimes_2$ также требуют задания пользовательских полуколец, как и в предыдущем случае. -Конструироваться они будут по аналогии. +Здесь операции $\otimes_1$ и $\otimes_2$ требует задания специфичных поэлементных операций $+$ и $*$ (в терминах GraphBLAS необходимо сконструировать пользовательское полукольцо). +Например, для $\otimes_1$: + +$$ +\+ : \textit{bool} \times \textit{bool} \to \textit{bool} +$$ +$$ +\* : \textit{bool} \times \textit{EdgeTX} \to \textit{EdgeTX} +$$ + +В качестве конкретных реализаций для $+$ можно взять логическое "И", а в качестве $*$ операцию $\textit{second}$ (вернуть второй элемент из пары). + +Для $\otimes_2$ ситуация аналогияная, Необходимо только проследить за тем, в какие моменты надо брать первый элемент из пары, а в какие вотрой, чтобы в результате получилась матрица с элементами типа $\texttt{EdgeTX}$ Подграф готов. From 73793996f2eb7d672bc6ab0605e854f243110975 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 18:12:16 +0300 Subject: [PATCH 19/22] =?UTF-8?q?=D0=9F=D0=BE=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D0=B2=D1=85=D0=BE=D0=B4=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=B3?= =?UTF-8?q?=D1=80=D0=B0=D1=84=D0=B0.=20=D0=92=D0=BB=D0=B0=D0=B4=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=B5=20=D0=B8=D0=BC=D0=B5=D0=B5?= =?UTF-8?q?=D1=82=20=D0=B0=D1=82=D1=80=D0=B8=D0=B1=D1=83=D1=82=D0=BE=D0=B2?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 495f3d0..94524cc 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,8 @@ Stand for PageRank algorithm benchmark Пусть будут следующие типы карт: МИР, VISA, MASTERCARD. -Каждый тип рёбер также имеет свой набор атрибутов. -* "Перевод": общая сумма, "количество транзакций" -* "Владеет": не имеет атрибутов +При этом рёбра типа "Перевод" в качестве атрибутов сожержат общую сумму и "количество транзакций". +Рёбра типа "Владеет" не имеют атрибутов. Для примера возьмём следующий граф. ![Пример графа](./Figures/Graph.svg) From 61b625abe8739c96227be8ce07a524a496778973 Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 18:15:38 +0300 Subject: [PATCH 20/22] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BF=D1=80=D0=BE=20=D0=BF=D0=BE=D0=BB=D1=83=D0=BA?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D1=86=D0=B0=20=D1=82=D0=B0=D0=BC,=20=D0=B3?= =?UTF-8?q?=D0=B4=D0=B5=20=D0=BE=D0=BD=D0=B8=20=D0=B2=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B2=D1=8B=D0=B9=20=D1=80=D0=B0=D0=B7=20=D0=BF=D0=BE=D1=8F?= =?UTF-8?q?=D0=B2=D0=BB=D1=8F=D1=8E=D1=82=D1=81=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 94524cc..71acf83 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,17 @@ $$ [. \ ; \ . \ ; \ . \ ; \ . \ ; \ 1 \ ; \ 1 \ ; \ . \ ; \ . \ ; \ 1 \ ; \ . \ ; \ 1 \ ; \ 1] $$ +Здесь нам впервые потребуется переопределить поэлементные операции для $\otimes$ (в терминах GraphBLAS необходимо сконструировать пользовательское полукольцо). + +$$ +\+ \ : \ \textit{bool} \times \textit{bool} \to \textit{bool} +$$ +$$ +\* \ : \ \textit{User} \times \textit{bool} \to \textit{bool} +$$ + +В качестве конкретных реализаций для $+$ можно взять логическое "И", а в качестве $*$ операцию $\textit{second}$ (вернуть второй элемент из пары). + Мы получили не совсем карты, но вектор, который указывает, какие карты нас интересуют. Вспомним, что мы хотим взять только карты "МИР". Для этого снова будем использовать Select, а полученный вектор $\texttt{Filtered-Cards}$ будем использовать как маску, чтобы дополнительно тфильтровать результат. @@ -238,14 +249,14 @@ $$ \end{pmatrix} $$ -Здесь операции $\otimes_1$ и $\otimes_2$ требует задания специфичных поэлементных операций $+$ и $*$ (в терминах GraphBLAS необходимо сконструировать пользовательское полукольцо). +Здесь операции $\otimes_1$ и $\otimes_2$ также требует задания специфичных поэлементных операций $+$ и $*$. Например, для $\otimes_1$: $$ -\+ : \textit{bool} \times \textit{bool} \to \textit{bool} +\+ \ : \ \textit{bool} \times \textit{bool} \to \textit{bool} $$ $$ -\* : \textit{bool} \times \textit{EdgeTX} \to \textit{EdgeTX} +\* \ : \ \textit{bool} \times \textit{EdgeTX} \to \textit{EdgeTX} $$ В качестве конкретных реализаций для $+$ можно взять логическое "И", а в качестве $*$ операцию $\textit{second}$ (вернуть второй элемент из пары). From ac2259bdba0af6b347aeb5d7fe8384033b6223a0 Mon Sep 17 00:00:00 2001 From: gsv Date: Tue, 11 Nov 2025 18:54:01 +0300 Subject: [PATCH 21/22] =?UTF-8?q?=D0=A4=D0=B8=D0=BD=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D1=8B=D0=BD=D0=B5=20=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8:=20?= =?UTF-8?q?=D0=B8=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=86=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA?= =?UTF-8?q?=D0=B5,=20=D1=81=D1=81=D1=8B=D0=BB=D0=BA=D0=B8=20=D0=BD=D0=B0?= =?UTF-8?q?=20=D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D1=8B=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=B4=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 71acf83..0ac9997 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,27 @@ # PageRankBenchmark -Stand for PageRank algorithm benchmark +Демонстрация использования алгоритма "PageRank" на графе со сложными атрибутами вершин и ребёр. +# Руководство к запуску +## Установка зависимостей +```bash +sudo apt install ccache +sudo apt install ninja-build +``` + +## Сборка проекта +```bash +git clone https://github.com/SparseLinearAlgebra/PageRankBenchmark.git +cd PageRankBenchmark +git submodule init +git submodule update —recursive +make build +``` +## Запуск примера +``` +./build/main +``` # Минимальный пример +Полный код разбираемого примера можно увидеть в [файле](./src/main.c). Цель примера --- показать, как в рамках GraphBLAS можно работать со сложными атрибутами вершин и рёбер графа. @@ -17,7 +37,7 @@ Stand for PageRank algorithm benchmark Пусть будут следующие типы карт: МИР, VISA, MASTERCARD. -При этом рёбра типа "Перевод" в качестве атрибутов сожержат общую сумму и "количество транзакций". +При этом рёбра типа "Перевод" в качестве атрибутов содержат общую сумму и "количество транзакций". Рёбра типа "Владеет" не имеют атрибутов. Для примера возьмём следующий граф. @@ -26,7 +46,6 @@ Stand for PageRank algorithm benchmark Хотим выбрать по некоторому критерию пользователей и их карты, а затем для анализа переводов хотим посчитать PageRank на подграфе, заданном переводами между отобранными картами. Выбрать хотим все карты системы "МИР", которыми владеют люди старше заданного возраста. Покажем, как это можно сделать, используя матрично-векторные операции, в частности [GraphBLAS](https://github.com/GraphBLAS). -Полный код разбираемого примера мрожно увидеть в файле [!!!!](!!!!). GraphBLAS позволяет в качестве атрибутов использовать пользовательские типы (фиксированных размеров), потому объявим необходимый нам набор типов. ```c @@ -68,9 +87,9 @@ typedef struct ``` Граф представлен как набор матриц и векторов: по одной матрице на каждый тип рёбер и по одному вектору на каждый тип вершин. -Матрицы и вектора в большинстве случаев будут разреженными и мы будем использовать символ '$.$' для обозначения отсутсвующего элемента. +Матрицы и вектора в большинстве случаев будут разреженными и мы будем использовать символ '$.$' для обозначения отсутствующего элемента. Считаем при этом, что все вершины, вне зависимости от типа, занумерованы с 0 подряд (id вершин на рисунке). -Таким образом, нам понядобятся две матрицы: +Таким образом, нам понадобятся две матрицы: $$ \texttt{TX-Edges}= @@ -124,7 +143,7 @@ $$ Скажем, нас будут интересовать пользователи старше 30 лет. Для этого в GraphBLAS есть функция ```Select```, которая фильтрует коллекции, используя функцию-предикат принимаемую в качестве аргумента. -Так как нам предстоит работать с пользовательскими типами, то предётся написать собственный предикат. +Так как нам предстоит работать с пользовательскими типами, то придётся написать собственный предикат. ```c void check_user_age(bool *z, const User *x, GrB_Index _i, GrB_Index _j, const uint8_t *y) @@ -136,7 +155,7 @@ void check_user_age(bool *z, const User *x, GrB_Index _i, GrB_Index _j, const ui Два дополнительных параметра типа ```GrB_Index``` позволяют, при необходимости, использовать в фильтре координаты рассматриваемого элемента. Для того, чтобы выбрать карты, принадлежащие выбранным пользователям, нам необходимо получить "концы" рёбер типа Owns, исходящие из выбранных пользователей. -Чтобы сделать это, выполним один шаг обхода в ширину, который в терминах линейной алгебры выражается через умноженеи вектора текущих вершин на матрицу смежности. +Чтобы сделать это, выполним один шаг обхода в ширину, который в терминах линейной алгебры выражается через умножение вектора текущих вершин на матрицу смежности. Текущие вершины в нашем случае --- выбранные пользователи. То есть нам необходимо вычислить следующее произведение. @@ -178,7 +197,7 @@ $$ Мы получили не совсем карты, но вектор, который указывает, какие карты нас интересуют. Вспомним, что мы хотим взять только карты "МИР". -Для этого снова будем использовать Select, а полученный вектор $\texttt{Filtered-Cards}$ будем использовать как маску, чтобы дополнительно тфильтровать результат. +Для этого снова будем использовать Select, а полученный вектор $\texttt{Filtered-Cards}$ будем использовать как маску, чтобы дополнительно отфильтровать результат. Чтобы получить переводы только между отобранными картами, воспользуемся тем фактом, что выбор исходящих рёбер, инцидентных заданному множеству вершин --- это умножение матрицы смежности на диагональную матрицу, в которой ненулевые элементы на местах интересующих нас вершин, слева. @@ -261,14 +280,14 @@ $$ В качестве конкретных реализаций для $+$ можно взять логическое "И", а в качестве $*$ операцию $\textit{second}$ (вернуть второй элемент из пары). -Для $\otimes_2$ ситуация аналогияная, -Необходимо только проследить за тем, в какие моменты надо брать первый элемент из пары, а в какие вотрой, чтобы в результате получилась матрица с элементами типа $\texttt{EdgeTX}$ +Для $\otimes_2$ ситуация аналогичная, +Необходимо только проследить за тем, в какие моменты надо брать первый элемент из пары, а в какие второй, чтобы в результате получилась матрица с элементами типа $\texttt{EdgeTX}$ Подграф готов. -Теперь неорбходимо сконструировать матрицу, по которой непосредственно будем считать PageRank. +Теперь необходимо сконструировать матрицу, по которой непосредственно будем считать PageRank. Сейчас метки рёбер --- структуры, хранящие информацию о переводах, а мы хотим получить одно число. При этом важно, чтобы сумма весов всех исходящих рёбер была равна единице. -Для примера действовать будем следующим образом: возьмём "средний размер транзакции" (вычислим как $\frac{\textit{Sum}}{\textit{Count}}$), поделим на 1000 (на всякий случай, чтобы избежать слишком больших знчений) и затем построчно примерним Softmax. +Для примера действовать будем следующим образом: возьмём "средний размер транзакции" (вычислим как $\frac{\textit{Sum}}{\textit{Count}}$), поделим на 1000 (на всякий случай, чтобы избежать слишком больших значений) и затем построчно применим Softmax. Иными словами, будем использовать идею функции Softmax, которая задаётся следующим образом. $$ @@ -283,10 +302,10 @@ $$ $$ Вычисления построим следующим образом. Сперва выполним редукцию по колонкам с использованием функции $f$: таким образом получим знаменатель дроби. -После этого сконструируем две квадратные матрицы: в одной нулевой столбец --- это получанный вектор, а остальные нули, в другой --- нулевая строка --- единицы, остальное --- нули. +После этого сконструируем две квадратные матрицы: в одной нулевой столбец --- это полученный вектор, а остальные нули, в другой --- нулевая строка --- единицы, остальное --- нули. Перемножим эти две матрицы, использую исходную матрицу $\texttt{Filtered-Transactions}$ в качестве маски. Таким образом получим матрицу, в которой знаменатель стоит на необходимых местах. -Также нам нужна будет матрица, содержащая числители дробей (получается поэлементным примерением соответствующей функции к $\texttt{Filtered-Transactions}$) +Также нам нужна будет матрица, содержащая числители дробей (получается поэлементным применением соответствующей функции к $\texttt{Filtered-Transactions}$) После чего поэлементно поделим эти две матрицы. -Далее на полученной матрице запускаем [классический алгоритм PageRank](!!!) (правда, без "телепортации" в несвязанные вершины), который в терминах линейной алгебры реалищуется по определению: итеративное умножение исходной матрицы на вектор. +Далее на полученной матрице запускаем [классический алгоритм PageRank](./src/main.c#L190) (правда, без "телепортации" в несвязанные вершины), который в терминах линейной алгебры реализуется по определению: итеративное умножение исходной матрицы на вектор. From 935826200f12126061095e5efa8ff9691713a9fa Mon Sep 17 00:00:00 2001 From: Semyon Date: Tue, 11 Nov 2025 19:08:57 +0300 Subject: [PATCH 22/22] =?UTF-8?q?=D0=9F=D0=BE=D1=82=D0=B5=D1=80=D1=8F?= =?UTF-8?q?=D0=BD=D0=BD=D0=B0=D1=8F=20=D1=82=D0=BE=D1=87=D0=BA=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0ac9997..3bb2051 100644 --- a/README.md +++ b/README.md @@ -281,7 +281,7 @@ $$ В качестве конкретных реализаций для $+$ можно взять логическое "И", а в качестве $*$ операцию $\textit{second}$ (вернуть второй элемент из пары). Для $\otimes_2$ ситуация аналогичная, -Необходимо только проследить за тем, в какие моменты надо брать первый элемент из пары, а в какие второй, чтобы в результате получилась матрица с элементами типа $\texttt{EdgeTX}$ +Необходимо только проследить за тем, в какие моменты надо брать первый элемент из пары, а в какие второй, чтобы в результате получилась матрица с элементами типа $\texttt{EdgeTX}$. Подграф готов. Теперь необходимо сконструировать матрицу, по которой непосредственно будем считать PageRank.