-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathdev_measure.tex
More file actions
583 lines (470 loc) · 19.5 KB
/
dev_measure.tex
File metadata and controls
583 lines (470 loc) · 19.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
\documentclass{tufte-handout}
\usepackage{../braph2_dev}
%\geometry{showframe} % display margins for debugging page layout
\title{Implement a New Measure}
\begin{document}
\maketitle
\begin{abstract}
\noindent
This is the developer tutorial for implementing a new measure.
In this tutorial, you will learn how to create the generator file \fn{*.gen.m} for a new measure, which can the be compiled by \code{braph2genesis}. All measures are (direct or indirect) extensions of the element \code{Measure}. Here, you will use as examples the measures \code{Degree}, \code{DegreeAv}, \code{Distance}, and \code{Triangles}.
\end{abstract}
\tableofcontents
\clearpage
\section{Implementation of unilayer measures}
\subsection{Nodal unilayer measure (\code{Degree})}
You will start by implementing in detail the measure \code{Degree}, which applies to most graphs and is a direct extension of the element \code{Measure}.
\begin{lstlisting}[
label=cd:m:degree:header,
caption={
{\bf Degree element header.}
The \code{header} section of the generator code in \fn{\_Degree.gen.m} provides the general information about the \code{Degree} element.
}
]
%% ¡header!
Degree < Measure (m, degree) is the graph degree. ¥\circled{1}\circlednote{1}{ The element \code{Degree} is defined as a subclass of \code{Measure}. The moniker will be \code{m}.}¥
%%% ¡description!
The degree of a node is the number of edges connected to the node within a layer.
Connection weights are ignored in calculations.
%%% ¡build!
1
\end{lstlisting}
\begin{lstlisting}[
label=cd:m:degree:prop_update,
caption={
{\bf Degree element prop update.}
The \code{props\_update} section of the generator code in \fn{\_Degree.gen.m} updates the properties of the \code{Measure} element. This defines the core properties of the measure.
}
]
%% ¡props_update!
%%% ¡prop!
NAME (constant, string) is the name of the degree.
%%%% ¡default!
'Degree'
%%% ¡prop!
DESCRIPTION (constant, string) is the description of the degree.
%%%% ¡default!
'The degree of a node is the number of edges connected to the node within a layer. Connection weights are ignored in calculations.'
%%% ¡prop!
TEMPLATE (parameter, item) is the template of the degree.
%%%% ¡settings!
'Degree'
%%% ¡prop!
ID (data, string) is a few-letter code of the degree.
%%%% ¡default!
'Degree ID'
%%% ¡prop!
LABEL (metadata, string) is an extended label of the degree.
%%%% ¡default!
'Degree label'
%%% ¡prop!
NOTES (metadata, string) are some specific notes about the degree.
%%%% ¡default!
'Degree notes'
%%% ¡prop! ¥\circled{1}\circlednote{1}{ Measures have a \emph{shape}: \code{Measure.GLOBAL} (a value for the whole brain graph, e.g., average degree), \code{Measure.NODAL} (a value for each brain region, e.g., degree), or \code{Measure.BINODAL} (a value for each couple of brain regions, e.g., distance between couples of nodes).}¥
SHAPE (constant, scalar) is the measure shape __Measure.NODAL__.
%%%% ¡default!
Measure.NODAL
%%% ¡prop! ¥\circled{2}\circlednote{2}{ Measures have a \emph{scope}: \code{Measure.SUPERGLOBAL} (a result for the whole multi-layer graph, e.g., overlapping strength), \code{Measure.UNILAYER} (a result for each layer, e.g., average strength), or \code{Measure.BILAYER} (a result for each couple of layers).}¥
SCOPE (constant, scalar) is the measure scope __Measure.UNILAYER__.
%%%% ¡default!
Measure.UNILAYER
%%% ¡prop! ¥\circled{3}\circlednote{3}{ Measures are either \code{Measure.NONPARAMETRIC} (the usual case) or \code{Measure.PARAMETRIC} (depending on some parameter).}¥
PARAMETRICITY (constant, scalar) is the parametricity of the measure __Measure.NONPARAMETRIC__.
%%%% ¡default!
Measure.NONPARAMETRIC
%%% ¡prop! ¥\circled{4}\circlednote{4}{ Each measure has a list of compatible graphs for which the measure can be used.}¥
COMPATIBLE_GRAPHS (constant, classlist) is the list of compatible graphs.
%%%% ¡default!
{'GraphWU' 'GraphBU' 'MultigraphBUD' 'MultigraphBUT' 'MultiplexWU' 'MultiplexBU' 'MultiplexBUD' 'MultiplexBUT' 'OrdMxWU' 'OrdMxBU'}
%%% ¡prop! ¥\circled{5}\circlednote{5}{ The property \code{M} contains the code to be executed to calculate the measure. Here is where most of the action happens.}¥
M (result, cell) is the degree.
%%%% ¡calculate!
g = m.get('G'); ¥\circled{6}\circlednote{6}{ retrieves the graph from the property \code{G} of the measure \code{m}.}¥
A = g.get('A'); ¥\circled{7}\circlednote{7}{ retrieves the cell with the adjacency matrix (for graph) or 2D-cell array (for multigraph, multiplex, etc.).}¥
degree = cell(g.get('LAYERNUMBER'), 1); ¥\circled{8}\circlednote{8}{ preallocates the variable to contain the result of the measure calculation.}¥
parfor li = 1:1:g.get('LAYERNUMBER')
Aii = A{li, li};
Aii = binarize(Aii); ¥\circled{9}\circlednote{9}{ binarizes the adjacency matrix (removing diagonal).}¥
degree(li) = {sum(Aii, 2)}; ¥\circled{10}\circlednote{10}{ calculates the degree of the node for layer \code{li}.}¥
end
value = degree; ¥\circled{11}\circlednote{11}{ returns the calculated value of the measure \code{degree} assigning it to the output variable \code{value}.}¥
\end{lstlisting}
\begin{lstlisting}[
label=cd:m:degree:tests,
caption={
{\bf Degree element tests.}
The \code{tests} section from the element generator \fn{\_Degree.gen.m}.
A test should be prepared for each graph with which the measure is compatible. The test should at least verify in some simple cases that the value of the measure is correct.
}
]
%% ¡tests!
%%% ¡excluded_props! ¥\circled{1}\circlednote{1}{ List of properties that are excluded from testing.}¥
[Degree.PFM]
%%% ¡test! ¥\circled{2}\circlednote{2}{ Test for \code{GraphWU}. Similar tests should be implemented for each graph compatible with the measure.}¥
%%%% ¡name!
GraphWU
%%%% ¡probability! ¥\circled{3}\circlednote{3}{ assigns a low test execution probability.}¥
.01
%%%% ¡code!
B = [
0 .6 1
.6 0 0
1 0 0
];
known_degree = {[2 1 1]'}; ¥\circled{4}\circlednote{4}{ is the expected value of the measure calculated by external means.}¥
g = GraphWU('B', B); ¥\circled{5}\circlednote{5}{ creates the graph.}¥
m_outside_g = Degree('G', g); ¥\circled{6}\circlednote{6}{ creates the measure.}¥
assert(isequal(m_outside_g.get('M'), known_degree), ... ¥\circled{7}\circlednote{7}{ tests that the value of the measure coicides with its expected value.}¥
[BRAPH2.STR ':Degree:' BRAPH2.FAIL_TEST], ...
[class(m_outside_g) ' is not being calculated correctly for ' class(g) '.'])
m_inside_g = g.get('MEASURE', 'Degree'); ¥\circled{8}\circlednote{8}{ extracts the measure from the graph.}¥
assert(isequal(m_inside_g.get('M'), known_degree), ... ¥\circled{8}\circlednote{8}{ tests that the value of the measure extracted from the graph coicides with its expected value.}¥
[BRAPH2.STR ':Degree:' BRAPH2.FAIL_TEST], ...
[class(m_inside_g) ' is not being calculated correctly for ' class(g) '.'])
¤...¤
\end{lstlisting}
\clearpage
\subsection{Global unilayer measure (\code{DegreeAv})}
You can now use \code{Degree} as the basis to implement the global measure \code{DegreeAv}.
{%TEX
The parts of the code that are modified are highlighted.
}%TEX
\begin{lstlisting}[
label=cd:m:degreeav:header,
caption={
{\bf DegreeAv element header.}
The \code{header} section of the generator code in \fn{\_DegreeAv.gen.m} provides the general information about the \code{DegreeAv} element.
\expand{cd:m:degree:header}
}
]
¤%% ¡header!¤
DegreeAv ¤<¤ Degree ¤(m, ¤average degree¤)¤ is the graph average degree. ¥\circled{1}\circlednote{1}{ \code{DegreeAv} is a child of \code{Degree}.}¥
¤%%% ¡description!¤
The average degree of a graph is the average of all number of edges connected to a node within a layer.
Connection weights are ignored in calculations.
¤%%% ¡build!¤
1
\end{lstlisting}
\begin{lstlisting}[
label=cd:m:degreeav:prop_update,
caption={
{\bf DegreeAv element prop update.}
The \code{props\_update} section of the generator code in \fn{\_DegreeAv.gen.m} updates the properties of the \code{Degree} element.
\expand{cd:m:degree:prop_update}
}
]
¤%% ¡props_update!¤
¤%%% ¡prop!
NAME (constant, string) is the name of the ¤average degree¤.
%%%% ¡default!¤
'DegreeAv'
¤%%% ¡prop!
DESCRIPTION (constant, string) is the description of the ¤average degree¤.
%%%% ¡default!¤
'The average degree of a graph is the average of all number of edges connected to a node within a layer. Connection weights are ignored in calculations.'
¤%%% ¡prop!
TEMPLATE (parameter, item) is the template of the ¤average degree¤.
%%%% ¡settings!¤
'DegreeAv'
¤%%% ¡prop!
ID (data, string) is a few-letter code of the ¤average degree¤.
%%%% ¡default!¤
'DegreeAv ID'
¤%%% ¡prop!
LABEL (metadata, string) is an extended label of the ¤average degree¤.
%%%% ¡default!¤
'DegreeAv label'
¤%%% ¡prop!
NOTES (metadata, string) are some specific notes about the ¤average degree¤.
%%%% ¡default!¤
'DegreeAv notes'
¤%%% ¡prop!
SHAPE (constant, scalar) is the measure shape ¤__Measure.GLOBAL__¤.
%%%% ¡default!¤
Measure.GLOBAL
¤%%% ¡prop!
SCOPE (constant, scalar) is the measure scope ¤__Measure.UNILAYER__¤.
%%%% ¡default!¤
Measure.UNILAYER
¤%%% ¡prop!
PARAMETRICITY (constant, scalar) is the parametricity of the measure ¤__Measure.NONPARAMETRIC__¤.
%%%% ¡default!¤
Measure.NONPARAMETRIC
¤%%% ¡prop!
COMPATIBLE_GRAPHS (constant, classlist) is the list of compatible graphs.
%%%% ¡default!¤
{'GraphWU' 'GraphBU' 'MultigraphBUD' 'MultigraphBUT' 'MultiplexWU' 'MultiplexBU' 'MultiplexBUD' 'MultiplexBUT' 'OrdMxWU' 'OrdMxBU'}
¤%%% ¡prop!
M (result, cell) is the ¤average degree¤.
%%%% ¡calculate!¤
degree = calculateValue@Degree(m, prop); ¥\circled{1}\circlednote{1}{ calculates the value of the degree calling its parent \code{Degree}.}¥
g = m.get('G');
degree_av = cell(g.get('LAYERNUMBER'), 1);
parfor li = 1:1:g.get('LAYERNUMBER')
degree_av(li) = {mean(degree{li})};
end
value = degree_av;
\end{lstlisting}
\begin{lstlisting}[
label=cd:m:degreeav:tests,
caption={
{\bf DegreeAv element tests.}
The \code{tests} section from the element generator \fn{\_DegreeAv.gen.m}.
\expand{cd:m:degree:tests}
}
]
¤%% ¡tests!¤
¤%%% ¡excluded_props!¤
[DegreeAv.PFM]
¤%%% ¡test!
%%%% ¡name!
GraphWU
%%%% ¡probability!
.01
%%%% ¡code!
B = [
0 .6 1
.6 0 0
1 0 0
];
¤known_degree_av = {mean([2 1 1])};¤
g = GraphWU('B', B);
m_outside_g = ¤DegreeAv¤('G', g);
assert(isequal(m_outside_g.get('M'), ¤known_degree_av¤), ...
[BRAPH2.STR ':¤DegreeAv¤:' BRAPH2.FAIL_TEST], ...
[class(m_outside_g) ' is not being calculated correctly for ' class(g) '.'])
m_inside_g = g.get('MEASURE', ¤'DegreeAv'¤);
assert(isequal(m_inside_g.get('M'), ¤known_degree_av¤), ...
[BRAPH2.STR ':¤DegreeAv¤:' BRAPH2.FAIL_TEST], ...
[class(m_inside_g) ' is not being calculated correctly for ' class(g) '.'])
...¤
\end{lstlisting}
\clearpage
\subsection{Binodal unilayer measure (\code{Distance})}
Now you will implement the binodal measure \code{Distance}.
{%TEX
Again the differences in the code will be highlighted.
}%TEX
\begin{lstlisting}[
label=cd:m:distance:header,
caption={
{\bf Distance element header.}
The \code{header} section of the generator code in \fn{\_Distance.gen.m} provides the general information about the \code{Distance} element.
\expand{cd:m:degree:header}
}
]
¤%% ¡header!¤
Distance ¤< Measure (m, ¤distance¤) ¤is the distance.
¤%%% ¡description!¤
The distance of a graph is the shortest path between all pairs of nodes within a layer of the graph.
For weighted graphs, the distance is calculated with the Dijkstra algorithm using the inverse weight as the distance associated to the edge.
¤%%% ¡build!¤
1
\end{lstlisting}
\begin{lstlisting}[
label=cd:m:distance:prop_update,
caption={
{\bf Distance element prop update.}
The \code{props\_update} section of the generator code in \fn{\_Distance.gen.m} updates the properties of the \code{Measure} element.
\expand{cd:m:degree:prop_update}
}
]
¤%% ¡props_update!
%%% ¡prop!
NAME (constant, string) is the name of the ¤distance¤.
%%%% ¡default!
¤'Distance'¤
%%% ¡prop!
DESCRIPTION (constant, string) is the description of the ¤distance¤.
%%%% ¡default!
¤'The distance of a graph is the shortest path between all pairs of nodes within a layer of the graph. For weighted graphs, the distance is calculated with the Dijkstra algorithm using the inverse weight as the distance associated to the edge.'¤
%%% ¡prop!
TEMPLATE (parameter, item) is the template of the ¤distance¤.
%%%% ¡settings!¤
'Distance'
¤%%% ¡prop!
ID (data, string) is a few-letter code of the ¤distance¤.
%%%% ¡default!
¤'Distance ID'¤
%%% ¡prop!
LABEL (metadata, string) is an extended label of the ¤distance¤.
%%%% ¡default!
¤'Distance label'¤
%%% ¡prop!
NOTES (metadata, string) are some specific notes about the ¤distance¤.
%%%% ¡default!
¤'Distance notes'¤
%%% ¡prop!
SHAPE (constant, scalar) is the measure shape ¤__Measure.BINODAL__¤.
%%%% ¡default!
¤Measure.BINODAL¤
%%% ¡prop!
SCOPE (constant, scalar) is the measure scope ¤__Measure.UNILAYER__¤.
%%%% ¡default!
¤Measure.UNILAYER¤
%%% ¡prop!
PARAMETRICITY (constant, scalar) is the parametricity of the measure ¤__Measure.NONPARAMETRIC__¤.
%%%% ¡default!
¤Measure.NONPARAMETRIC¤
%%% ¡prop!
COMPATIBLE_GRAPHS (constant, classlist) is the list of compatible graphs.
%%%% ¡default!
¤{'GraphBD' 'GraphBU' 'GraphWD' 'GraphWU' 'MultigraphBUD' 'MultigraphBUT' 'MultiplexBD' 'MultiplexBU' 'MultiplexWD' 'MultiplexWU' 'MultiplexBUD' 'MultiplexBUT' 'OrdMxBD' 'OrdMxBU' 'OrdMxWD' 'OrdMxWU'}¤
%%% ¡prop!
M (result, cell) is the ¤distance¤.
%%%% ¡calculate!
¤g = m.get('G');
A = g.get('A');
distance = cell(g.get('LAYERNUMBER'), 1);
connectivity_type = g.get('CONNECTIVITY_TYPE', g.get('LAYERNUMBER'));
connectivity_type = diag(connectivity_type);
Aii_tmp = {};
for li = 1:1:g.get('LAYERNUMBER')
Aii_tmp{li} = A{li, li};
end
for li = 1:1:g.get('LAYERNUMBER')
Aii = Aii_tmp{li};
connectivity_layer = connectivity_type(li);
if connectivity_layer == Graph.WEIGHTED % weighted graphs
distance(li) = {getWeightedCalculation(Aii)}; ¥\circled{1}\circlednote{1}{ and \circled{2} call some callback functions that are provided below in \circled{3}.}¥
else % binary (i.e., non-weighted) graphs
distance(li) = {getBinaryCalculation(Aii)}; ¥\circled{2}¥
end
end
value = distance;
%%%% ¡calculate_callbacks! ¥\circled{3}\circlednote{3}{ This section contains the callback functions for the calculation of the measure.}¥
function weighted_distance = getWeightedCalculation(A)
...
end
function binary_distance = getBinaryCalculation(A)
...
end
\end{lstlisting}
\begin{lstlisting}[
label=cd:m:distance:tests,
caption={
{\bf Distance element tests.}
The \code{tests} section from the element generator \fn{\_Distance.gen.m}.
\expand{cd:m:degree:tests}
}
]
¤%% ¡tests!
%%% ¡excluded_props!
¤[Distance.PFM]¤
%%% ¡test!
%%%% ¡name!
GraphWU
%%%% ¡probability!
.01
%%%% ¡code!
¤B = [
0 .1 .2 .25 0
.125 0 0 0 0
.2 .5 0 .25 0
.125 10 0 0 0
0 0 0 0 0
];
known_distance = {[
0 5 5 4 Inf
5 0 2 1 Inf
5 2 0 3 Inf
4 1 3 0 Inf
Inf Inf Inf Inf 0
]};¤
g = GraphWU('B', B);
m_outside_g = ¤Distance¤('G', g);
assert(isequal(m_outside_g.get('M'), ¤known_distance¤), ...
[BRAPH2.STR ':¤Distance¤:' BRAPH2.FAIL_TEST], ...
[class(m_outside_g) ' is not being calculated correctly for ' class(g) '.'])
m_inside_g = g.get('MEASURE', ¤'Distance'¤);
assert(isequal(m_inside_g.get('M'), ¤known_distance¤), ...
[BRAPH2.STR ':¤Distance¤:' BRAPH2.FAIL_TEST], ...
[class(m_inside_g) ' is not being calculated correctly for ' class(g) '.'])
...¤
\end{lstlisting}
\clearpage
\section{Implementation of measure parameters (\code{Triangles})}
Now, you will implement the (nodal unilayer) measure \code{Triangles}, which depends on a parameter \code{RULE}, which we add as a property of category \code{parameter}.
{%TEX
The parts of the code that are modified are highlighted.
}%TEX
\begin{lstlisting}[
label=cd:m:triangles:header,
caption={
{\bf Triangles element header.}
The \code{header} section of the generator code in \fn{\_Triangles.gen.m} provides the general information about the \code{Triangles} element.
\expand{cd:m:triangles:header}
}
]
¤%% ¡header!¤
Triangles ¤< Measure (m, ¤triangles¤) ¤is the triangles.
¤%%% ¡description!¤
The triangles are calculated as the number of neighbors of a node that are also neighbors of each other within a layer.
In weighted graphs, the triangles are calculated as geometric mean of the weights of the edges forming the triangle.
¤%%% ¡build!¤
1
\end{lstlisting}
\begin{lstlisting}[
label=cd:m:triangles:calculate,
caption={
{\bf Triangles element calculate.}
The \code{calculate} section of \fn{\_Triangles.gen.m} utilizes the rule property to select which algorithm it will use to calculate the \code{Triangles} element.
\expand{cd:m:triangles:calculate}
}
]
¤%% ¡props_update!
%%% ¡prop!
NAME (constant, string) is the name of the ¤triangles¤.
%%%% ¡default!
¤'Triangles'¤
%%% ¡prop!
DESCRIPTION (constant, string) is the description of the ¤triangles¤.
%%%% ¡default!
¤'The triangles are calculated as the number of neighbors of a node that are also neighbors of each other within a layer. In weighted graphs, the triangles are calculated as geometric mean of the weights of the edges forming the triangle.'
¤...¤
¤%%% ¡prop!
M (result, cell) is the ¤triangles¤.
%%% ¡calculate!
¤g = m.get('G'); % graph from measure class
A = g.get('A'); % cell with adjacency matrix (for graph) or 2D-cell array (for multigraph, multiplex, etc.)
L = g.get('LAYERNUMBER');
triangles = cell(L, 1);
directionality_type = g.get('DIRECTIONALITY\_TYPE', L);
for li = 1:1:L
Aii = A{li, li};
if directionality_type == Graph.UNDIRECTED % undirected graphs
triangles_layer = diag((Aii.^(1/3))^3) / 2;
triangles_layer(isnan(triangles_layer)) = 0; % Should return zeros, not NaN
triangles(li) = {triangles_layer};
else % directed graphs
directed_triangles_rule = m.get('RULE'); ¥\circled{1}\circlednote{1}{ gets the rule to calculate the measure Triangle. See below how this rule is defined in \circled{2}, \circled{3}, and \circled{4}.}¥
switch lower(directed_triangles_rule)
case 'all' % all rule
triangles_layer = diag((Aii.^(1/3) + transpose(Aii).^(1/3))^3) / 2;
case 'middleman' % middleman rule
triangles_layer = diag(Aii.^(1/3) * ...
transpose(Aii).^(1/3) * Aii.^(1/3));
case 'in' % in rule
triangles_layer = diag(transpose(Aii).^(1/3) * (Aii.^(1/3))^2);
case 'out' % out rule
triangles_layer = diag((Aii.^(1/3))^2 * transpose(Aii).^(1/3));
otherwise % {'cycle'} % cycle rule
triangles_layer = diag((Aii.^(1/3))^3);
end
triangles_layer(isnan(triangles_layer)) = 0; % Should return zeros, not NaN
triangles(li) = {triangles_layer};
end
end
value = triangles;¤
¤%% ¡props!
%%% ¡prop!
RULE (parameter, option) is the rule to determine what is a triangle in a directed graph. ¥\circled{2}\circlednote{2}{ defines a parameter to determine how the measure is calculated. This property must be of category \code{parameter}.}¥
%%%% ¡settings!
{'all' 'middleman' 'in' 'out' 'cycle'} ¥\circled{3}\circlednote{3}{ defines the available triangle rule options, which are case sensitive.}¥
%%%% ¡default!
'cycle' ¥\circled{4}\circlednote{4}{ defines the default option, in this case \code{'cycle'}.}¥
\end{lstlisting}
%\bibliography{biblio}
%\bibliographystyle{plainnat}
\end{document}