Rollup
An extension of Open Graph's own: totals along every path from a set of starts, loops refused or solved - bills of materials, ownership, cost allocation, input-output.
6 entries: 2 functions, 3 types and 1 macro. Part of the Open Graph reference; All functions lists every entry on one page, with a filter. The badges say how each entry is checked.
Types
rollup_loops_ttype#
Exact Extension
What rollup does when the links it follows loop back.
typedef enum og_rollup_loops_t {
OG_ROLLUP_REFUSE = 0,
OG_ROLLUP_SOLVE = 1
} og_rollup_loops_t;
OG_ROLLUP_REFUSE (0, the default): a loop among the vertices the starts reach is an error, OG_EINVAL, and rollup names one cycle of it - right for a bill of materials, where a loop is a data error. OG_ROLLUP_SOLVE (1): loops are solved exactly, x_K = (I - C_K^T)^-1 b_K, as cross-holdings, reciprocal cost allocations and input-output tables need; a loop whose coefficients, taken without their signs, have a spectral radius of 1 or more does not converge and is OG_DIVERGED. Any other value is OG_EINVAL.
- Checked
- Open Graph extension, no igraph counterpart: Norway Analytics' own design for OpenBI's NETWORK.ROLLUP and the notebooks' Graph.Rollup, checked against its specification and its tests.
- C name
og_rollup_loops_t- In notebooks
Og.RollupLoops- igraph 1.0
- None: Open Graph's own.
- See also
rollup,rollup_options_t
ROLLUP_IN_LOOPmacro#
Exact Extension
The level rollup gives a vertex inside a solved loop.
#define OG_ROLLUP_IN_LOOP (-1)
A level counts the most links from a start, a loop being one stop; inside a loop the paths go round without end, so a vertex there has no level of its own and gets -1 (OpenBI shows BLANK). The vertices after the loop count on from the loop's place.
- Checked
- Open Graph extension, no igraph counterpart: Norway Analytics' own design for OpenBI's NETWORK.ROLLUP and the notebooks' Graph.Rollup, checked against its specification and its tests.
- C name
OG_ROLLUP_IN_LOOP- In notebooks
Og.OG_ROLLUP_IN_LOOP- igraph 1.0
- None: Open Graph's own.
- See also
rollup
rollup_options_ttype#
Exact Extension
The choices rollup takes.
typedef struct og_rollup_options_t {
og_neimode_t mode;
og_rollup_loops_t loops;
og_bool_t by_start;
og_int_t max_rows;
og_real_t max_work;
} og_rollup_options_t;
mode: OG_OUT (the default) follows each edge from its tail to its head - a bill of materials exploded, an owner's effective shares; OG_IN goes against the edges - costs rolled up from parts, a company's ultimate owners (ignored on an undirected graph, whose edges work both ways). loops: OG_ROLLUP_REFUSE (the default) or OG_ROLLUP_SOLVE. by_start: false (the default) gives one total per vertex over all starts; true gives each start's own totals, a row per start and vertex it reaches (which product drives the need for a part). max_rows and max_work: 0 (the default) for no limit; otherwise a call whose answer has more rows, or would take more elementary steps (vertices and arcs visited, entries of factors and sweeps used), stops with OG_ERANGE before the totals are made. A host derives max_work from the steps per second it measured, so its time guard refuses the same calls on every computer and never depends on a clock. Fill it with rollup_options_init.
- Checked
- Open Graph extension, no igraph counterpart: Norway Analytics' own design for OpenBI's NETWORK.ROLLUP and the notebooks' Graph.Rollup, checked against its specification and its tests.
- C name
og_rollup_options_t- In notebooks
Og.RollupOptions- igraph 1.0
- None: Open Graph's own.
- See also
rollup_options_init,rollup
rollup_info_ttype#
Exact Extension
What rollup found on its way, also when it stops with an error.
typedef struct og_rollup_info_t {
og_int_t reached;
og_int_t arcs;
og_int_t loops;
og_int_t largest;
og_int_t rows;
og_real_t work;
} og_rollup_info_t;
reached: the vertices the starts reach together, the starts included. arcs: the merged links leaving them. loops: the loops among them (strongly connected parts with a cycle) and largest: the vertices of the largest (0 without loops). rows: the rows of the answer (max_rows + 1 when it stopped for having more). work: the elementary steps the answer takes or would take (at least max_work when it stopped for that). Filled as far as the call got.
- Checked
- Open Graph extension, no igraph counterpart: Norway Analytics' own design for OpenBI's NETWORK.ROLLUP and the notebooks' Graph.Rollup, checked against its specification and its tests.
- C name
og_rollup_info_t- In notebooks
Og.RollupInfo- igraph 1.0
- None: Open Graph's own.
- See also
rollup
Functions
rollup_options_init#
Exact Extension
Fills the rollup's options with their defaults.
og_error_t og_rollup_options_init(og_rollup_options_t *opts);
Mode OG_OUT, loops OG_ROLLUP_REFUSE, not by start, no limit on rows or work. rollup takes NULL options to mean the same.
- Parameters
optsThe options to fill.
- Returns
OG_SUCCESS.- Errors
OG_EINVALopts is NULL.
- Complexity
- O(1).
- Checked
- Open Graph extension, no igraph counterpart: Norway Analytics' own design for OpenBI's NETWORK.ROLLUP and the notebooks' Graph.Rollup, checked against its specification and its tests.
- C name
og_rollup_options_init- In notebooks
Og.RollupOptionsInit- igraph 1.0
- None: Open Graph's own.
- See also
rollup_options_t,rollup
rollup#
Within tolerance Threads Extension
Multiplies along every path from the starts and adds the paths up: bills of materials, ownership through chains, reciprocal allocation, Leontief input-output.
og_error_t og_rollup(
const og_t *graph,
const og_vector_t *weights,
const og_vector_int_t *starts,
const og_vector_t *amounts,
const og_rollup_options_t *opts,
og_vector_int_t *res_start,
og_vector_int_t *res_vertex,
og_vector_t *res_total,
og_vector_int_t *res_level,
og_vector_int_t *loop,
og_rollup_info_t *info
);
Each edge carries a coefficient (its weight: a quantity per unit, a share, a cost rate) and each start an amount. A vertex's total is the sum, over every start and every path from it to the vertex, of the start's amount times the product of the coefficients along the path; a start's own amount counts (the path of no edges). With the 500 bikes of a bill of materials as the start, two wheels a bike and 36 spokes a wheel, the spokes' total is 36,000. Where edges loop back there are infinitely many paths, and their sum is the solution of x = d + C^T x, which rollup solves exactly (OG_ROLLUP_SOLVE) or refuses (OG_ROLLUP_REFUSE, the default).
Coefficients: several edges between one pair (one direction) add up, exactly and rounded once, so their order never changes a total and +0.3, -0.3, 0.1 give 0.1 itself; a pair adding up to exactly 0 is no link at all. Weights may be negative (a by-product), never NaN or infinite. Starts may repeat (their amounts add up the same way); a start nothing links from gives just its own row.
Loops (strongly connected parts with a cycle, or a vertex linked to itself) among the vertices reached are solved one by one in the order the links run: up to 32 vertices by a dense LU, larger ones by Gauss-Seidel sweeps when the convergence certificate's own sweeps settle quickly, else by the sparse LU. A loop converges when the spectral radius of its coefficients, taken without their signs, is below 1 (then the paths add up to the same total in any order); rollup certifies it by solving (I - |C_K|^T) y = 1, whose solution must be positive and at most 1e12. A loop that fails is OG_DIVERGED, and loop holds a cycle through its smallest vertex.
Rows come by start (ascending, only with by_start), then level, then vertex id. The level is the most links from a start, a loop counted as one stop (ROLLUP_IN_LOOP inside a loop). The same graph numbered the same gives the same bits whatever the order of its edges, the number of threads or the platform.
- Parameters
graphThe graph; directed for the usual cases (an undirected edge works both ways, so every edge is a loop of two).weightsEach edge's coefficient, finite and of any sign; NULL for all 1 (the totals then count paths).startsThe start vertices, repeats allowed; empty gives no rows.amountsEach start's amount, finite; NULL for all 1.optsThe options (rollup_options_t), or NULL for the defaults.res_startOutput, may be NULL: each row's start (-1 without by_start).res_vertexOutput: each row's vertex.res_totalOutput: each row's total.res_levelOutput, may be NULL: each row's level,ROLLUP_IN_LOOPinside a loop.loopOutput, may be NULL: on a loop refused (OG_EINVAL) or not converging (OG_DIVERGED), a shortest cycle through the loop's smallest vertex, from it; otherwise empty.infoOutput, may be NULL: what the call found (rollup_info_t).
- Returns
OG_SUCCESS.- Errors
OG_EINVALA weight or amount that is NaN or infinite; weights or amounts of the wrong length; an unknown loops value; a negative cap; a pair's weights or a start's amounts adding up beyond the largest double; a loop underOG_ROLLUP_REFUSE(named in loop).OG_EINVVIDA start that is no vertex.OG_EINVMODEA directed graph's mode other thanOG_OUTorOG_IN.OG_DIVERGEDA loop whose coefficients without their signs have a spectral radius of 1 or more (named in loop).OG_ERANGEMore rows than max_rows, or more work than max_work (info says how much).OG_ENOMEMNot enough memory.
- Complexity
- O(|R| + arcs of R) to merge the reached vertices' edges and find their loops; each loop prepared once (dense k^3/3 up to 32 vertices; larger, a few Gauss-Seidel sweeps over its arcs, or the sparse LU's factors); then each piece (all starts, or each start) visits its vertices and arcs, sorts them (O(r log r)) and solves its loops.
- Checked
- Open Graph extension, no igraph counterpart: Norway Analytics' own design for OpenBI's NETWORK.ROLLUP and the notebooks' Graph.Rollup, checked against its specification and its tests. Checked against an independent Python reference (exact fractions, brute-force paths, numpy/scipy dense solves; 2,943 cases, 28,666 rows): largest relative difference 2.2e-13, every vertex, start, level, loop and error the same; against Statistics Norway's (2000, 23 industries) and Statistics Finland's (2021 and 2022, 63 industries) published Leontief inverses within their 3 decimals and 1.9e-15 relative of the exact inverses.
- Threads
- With by_start, each start is a piece run as a task (a first pass counts each start's rows, a second writes them at their offsets); loops are prepared on the calling thread. Bit-identical for any number of threads and any executor.
- C name
og_rollup- In notebooks
Og.Rollup- igraph 1.0
- None: Open Graph's own.
- See also
rollup_options_t,rollup_info_t,rollup_loops_t,ROLLUP_IN_LOOP
#include "og.h"
#include <stdio.h>
int main(void) {
/* 0 bike, 1 wheel, 2 spoke: 2 wheels a bike, 36 spokes a wheel */
og_t g;
og_vector_int_t e, starts, vertex;
og_vector_t w, amounts, total;
og_int_t i;
og_vector_int_init_int(&e, 4, 0, 1, 1, 2);
og_create(&g, &e, 3, OG_DIRECTED);
og_vector_init_real(&w, 2, 2.0, 36.0);
og_vector_int_init_int(&starts, 1, 0);
og_vector_init_real(&amounts, 1, 500.0);
og_vector_int_init(&vertex, 0);
og_vector_init(&total, 0);
og_rollup(&g, &w, &starts, &amounts, NULL, NULL, &vertex, &total, NULL, NULL, NULL);
for (i = 0; i < og_vector_int_size(&vertex); i++) {
printf("%d: %g\n", (int) VECTOR(vertex)[i], VECTOR(total)[i]); /* 0: 500, 1: 1000, 2: 36000 */
}
og_vector_destroy(&total);
og_vector_int_destroy(&vertex);
og_vector_destroy(&amounts);
og_vector_int_destroy(&starts);
og_vector_destroy(&w);
og_destroy(&g);
og_vector_int_destroy(&e);
return 0;
}