PaStiX Handbook 6.4.0
Loading...
Searching...
No Matches
elimintree.c
Go to the documentation of this file.
1/**
2 *
3 * @file elimintree.c
4 *
5 * PaStiX analyse routines
6 * PaStiX is a software package provided by Inria Bordeaux - Sud-Ouest,
7 * LaBRI, University of Bordeaux 1 and IPB.
8 *
9 * Contains basic functions to manipulate elimination tree structure.
10 *
11 * @copyright 2004-2025 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
12 * Univ. Bordeaux. All rights reserved.
13 *
14 * @version 6.4.0
15 * @author Pascal Henon
16 * @author Mathieu Faverge
17 * @date 2024-07-05
18 *
19 * @addtogroup blend_dev_elim
20 * @{
21 *
22 **/
23#include "common.h"
24#include "symbol/symbol.h"
25#include "blend/elimintree.h"
26
27/**
28 *******************************************************************************
29 *
30 * @brief Initialize the elimination tree structure.
31 *
32 *******************************************************************************
33 *
34 * @param[in] nodenbr
35 * TODO
36 *
37 *******************************************************************************
38 *
39 * @retval TODO
40 *
41 *******************************************************************************/
44{
45 EliminTree *etree;
46 eTreeNode_t *enode;
48
49 MALLOC_INTERN(etree, 1, EliminTree);
50
51 etree->baseval = 0;
52 etree->nodenbr = nodenbr;
53
54 MALLOC_INTERN( etree->nodetab, nodenbr + 1, eTreeNode_t);
55 MALLOC_INTERN( etree->sonstab, nodenbr, pastix_int_t);
56 memset( etree->sonstab, 0, nodenbr * sizeof(pastix_int_t) );
57
58 /* Initialize the structure fields */
59 enode = etree->nodetab;
60 for(i=-1; i<nodenbr; i++, enode++)
61 {
62 enode->ndecost = 0.0;
63 enode->ndepath = 0.0;
64 enode->subcost = 0.0;
65 enode->subpath = 0.0;
66 enode->ndlevel = -1;
67 enode->sonsnbr = 0;
68 enode->fathnum = -1;
69 enode->fsonnum = -1;
70 }
71
72 /* Shift the nodetab to get the root at -1 position */
73 etree->nodetab++;
74 return etree;
75}
76
77/**
78 *******************************************************************************
79 *
80 * @brief Free the elimination tree structure.
81 *
82 *******************************************************************************
83 *
84 * @param[inout] etree
85 * The pointer to the elimination tree to free.
86 *
87 *******************************************************************************/
88void
90{
91 if (etree != NULL) {
92 if (etree->nodetab != NULL) {
93 etree->nodetab--;
94 memFree_null(etree->nodetab);
95 }
96 memFree_null(etree->sonstab);
97 memFree_null(etree);
98 }
99}
100
101/**
102 *******************************************************************************
103 *
104 * @brief Set the fsonnum fields base on the initialized sonsnbr.
105 *
106 *******************************************************************************
107 *
108 * @param[inout] etree
109 * The pointer to the elimination tree for which the fsonnum fields
110 * must be initialized.
111 *
112 *******************************************************************************/
113static inline void
115{
116 eTreeNode_t *enode;
117 pastix_int_t i;
118
119 /* Set the index of the first sons */
120 enode = etree->nodetab - 1;
121 enode->fsonnum = 0;
122 for(i=0; i<etree->nodenbr; i++, enode++)
123 {
124 enode[1].fsonnum = enode[0].fsonnum + enode[0].sonsnbr;
125 }
126 assert((enode[0].fsonnum + enode[0].sonsnbr) == etree->nodenbr);
127}
128
129/**
130 *******************************************************************************
131 *
132 * @brief Set the fsonnum fields base on the initialized sonsnbr.
133 *
134 *******************************************************************************
135 *
136 * @param[inout] etree
137 * The pointer to the elimination tree for which the fsonnum fields
138 * must be initialized.
139 *
140 *******************************************************************************/
141void
143{
144 pastix_int_t i;
145
146 /* Set the index of the first sons */
147 etree_SetSonsIndex( etree );
148
149 /* Fill the sonstab */
150 for(i=0; i<etree->nodenbr; i++)
151 {
152 eTreeNode_t *efather = eTreeFather(etree, i);
153 pastix_int_t node = efather->fsonnum;
154 efather->fsonnum++;
155 assert( (node >= 0) && (node < etree->nodenbr) );
156 etree->sonstab[ node ] = i;
157 }
158
159 /* Restore fsonnum fields */
160 etree_SetSonsIndex( etree );
161}
162
163/**
164 *******************************************************************************
165 *
166 * @brief Compute the number of leaves.
167 *
168 *******************************************************************************
169 *
170 * @param[in] etree
171 * The pointer to the elimination tree.
172 *
173 *******************************************************************************
174 *
175 * @return The number of leaves in the elimination tree.
176 *
177 *******************************************************************************/
180{
181 pastix_int_t i;
182 pastix_int_t leavenbr;
183 leavenbr = 0;
184 for(i=0;i<etree->nodenbr;i++) {
185 if(etree->nodetab[i].sonsnbr == 0) {
186 leavenbr++;
187 }
188 }
189
190 return leavenbr;
191}
192
193/**
194 *******************************************************************************
195 *
196 * @brief Compute the height of the elimination tree.
197 *
198 *******************************************************************************
199 *
200 * @param[in] etree
201 * The pointer to the elimination tree.
202 *
203 *******************************************************************************
204 *
205 * @return The height of the elimination tree.
206 *
207 *******************************************************************************/
210{
211 pastix_int_t maxlevel;
212 pastix_int_t nodelevel;
213 pastix_int_t i;
214 maxlevel = 0;
215 for(i=0;i<etree->nodenbr;i++)
216 {
217 nodelevel = eTreeNodeLevel(etree, i);
218 if(nodelevel > maxlevel) {
219 maxlevel = nodelevel;
220 }
221 }
222
223 return maxlevel;
224}
225
226/**
227 *******************************************************************************
228 *
229 * @brief Compute the number of level existing below a given node.
230 *
231 *******************************************************************************
232 *
233 * @param[inout] etree
234 * The pointer to the elimination tree. On exit, all traversed nodes
235 * will be updated with the depth related to the given root.
236 *
237 *
238 * @param[in] rootnum
239 * The root of the tree to study.
240 *
241 * @param[in] rootlvl
242 * The level of the root node.
243 *
244 *******************************************************************************
245 *
246 * @return The maximal depth of the tree.
247 *
248 *******************************************************************************/
251{
252 pastix_int_t sonsnbr, i, son, max;
253 pastix_int_t maxlevel;
254
255 etree->nodetab[ rootnum ].ndlevel = rootlvl;
256 sonsnbr = etree->nodetab[ rootnum ].sonsnbr;
257
258 maxlevel = rootlvl;
259 rootlvl++;
260 for(i=0;i<sonsnbr;i++)
261 {
262 son = eTreeSonI( etree, rootnum, i );
263 max = eTreeComputeLevels( etree, son, rootlvl );
264 maxlevel = pastix_imax( max, maxlevel );
265 }
266 return maxlevel;
267}
268
269/**
270 *******************************************************************************
271 *
272 * @brief Compute the number of level existing below a given node.
273 *
274 *******************************************************************************
275 *
276 * @param[in] etree
277 * The pointer to the elimination tree.
278 *
279 *
280 * @param[in] nodenum
281 * The index of the node to study.
282 *
283 *******************************************************************************
284 *
285 * @return The number of level below the node including it.
286 *
287 *******************************************************************************/
290{
291 pastix_int_t level;
292
293 level = 0;
294 /* If fake root no levels */
295 if(nodenum == eTreeRoot(etree)) {
296 return 0;
297 }
298 level++;
299 while(etree->nodetab[nodenum].fathnum != eTreeRoot(etree))
300 {
301 level++;
302 nodenum = etree->nodetab[nodenum].fathnum;
303 }
304 return level;
305}
306
307/**
308 *******************************************************************************
309 *
310 * @brief Print the elimination tree in a dot file.
311 *
312 *******************************************************************************
313 *
314 * @param[in] etree
315 * The pointer to the elimination tree.
316 *
317 *
318 * @param[inout] stream
319 * The file to which write the elimination tree in the dot format.
320 *
321 *******************************************************************************/
322void
324 FILE *stream )
325{
326 pastix_int_t i;
327
328 fprintf(stream,
329 "digraph G {\n"
330 "\tcolor=white\n"
331 "rankdir=BT;\n");
332
333 for (i=0; i < etree->nodenbr; i++)
334 {
335 fprintf(stream, "\t\"%ld\" [label=\"#%ld\\nSubtree cost: %e\\nNode cost: %e\\nNode CP: %e\"]\n",
336 (long)i, (long)i,
337 etree->nodetab[i].subcost,
338 etree->nodetab[i].ndepath,
339 etree->nodetab[i].subpath );
340
341 if ((etree->nodetab[i]).fathnum == -1) {
342 continue;
343 }
344 fprintf( stream, "\t\"%ld\"->\"%ld\"\n",
345 (long)i,
346 (long)((etree->nodetab[i]).fathnum) );
347 }
348
349 fprintf(stream, "}\n");
350}
351
352/**
353 *******************************************************************************
354 *
355 * @brief Print the elimination tree in a human readable format.
356 *
357 * Each node is writen as:
358 * Rootnum idx number_of_sons:
359 * (son_1)
360 * (son_2)
361 * ...
362 * (son_n)
363 *
364 *******************************************************************************
365 *
366 * @param[in] etree
367 * The pointer to the elimination tree.
368 *
369 *
370 * @param[inout] stream
371 * The file to which write the elimination tree in the dot format.
372 *
373 * @param[in] rootnum
374 * The root of the subtree to write into the file.
375 *
376 *******************************************************************************/
377void
378eTreePrint(const EliminTree *etree, FILE *stream, pastix_int_t rootnum )
379{
380 int i, sonsnbr;
381 pastix_int_t son;
382
383 sonsnbr = etree->nodetab[ rootnum ].sonsnbr;
384
385 fprintf(stream, "Rootnum %ld %d\n", (long)rootnum, sonsnbr);
386 for(i=0;i<sonsnbr;i++) {
387 fprintf(stream," (%4ld)\n", (long)eTreeSonI(etree, rootnum, i));
388 }
389
390 for(i=0;i<sonsnbr;i++)
391 {
392 son = eTreeSonI(etree, rootnum, i);
393 if (etree->nodetab[son].sonsnbr) {
394 eTreePrint(etree, stream, son);
395 }
396 }
397}
398
399/**
400 *******************************************************************************
401 *
402 * @brief Return the smallest index of the nodes belonging to the level lvl in
403 * the elimination tree.
404 *
405 * Look recursively in the elimination tree to return the smallest index of all
406 * the nodes belonging to a same level defined by lvl.
407 *
408 *******************************************************************************
409 *
410 * @param[in] etree
411 * The pointer to the elimination tree.
412 *
413 * @param[in] root
414 * The root of the subtree to study.
415 *
416 * @param[in] lvl
417 * The number of levels below root to look for.
418 *
419 * @param[in] idxmin
420 * The minimum index already discovered.
421 *
422 *******************************************************************************
423 *
424 * @return The minimum index found in the descendants of the root node, lvl
425 * levels below.
426 *
427 *******************************************************************************/
430 pastix_int_t root,
431 pastix_int_t lvl,
432 pastix_int_t idxmin )
433{
434 int i, sonsnbr;
435 pastix_int_t idx, son;
436
437 idx = (root == -1) ? idxmin : pastix_imin( root, idxmin );
438
439 if ( lvl == 0 ) {
440 return idx;
441 }
442
443 sonsnbr = etree->nodetab[ root ].sonsnbr;
444 if ( sonsnbr == 0 ) {
445 return idx;
446 }
447
448 lvl--;
449 for(i=0;i<sonsnbr;i++)
450 {
451 son = eTreeSonI(etree, root, i);
452 idx = eTreeGetLevelMinIdx( etree, son, lvl, idx );
453 }
454 return idx;
455}
456
457/**
458 *******************************************************************************
459 *
460 * @brief Build the elimination tree.
461 *
462 * The elimination tree is computed based on a given symbolic structure, and
463 * not from the tree given by the ordering library. Each father of a node is
464 * defined as the facing column block of the first off diagonal block.
465 *
466 *******************************************************************************
467 *
468 * @param[in] symbmtx
469 * The pointer to the symbol matrix from which the elimination tree is
470 * computed.
471 *
472 *******************************************************************************
473 *
474 * @return The elimination tree linked to the symbol matrix.
475 *
476 *******************************************************************************/
479{
480 eTreeNode_t *enode, *eroot;
481 EliminTree *etree = NULL;
482 pastix_int_t i;
483 pastix_int_t totalsonsnbr;
484
485 etree = eTreeInit( symbmtx->cblknbr );
486 eroot = &(etree->nodetab[eTreeRoot(etree)]);
487
488 /* Compute the fathers and the number of sons */
489 totalsonsnbr = 0;
490 enode = etree->nodetab;
491 for(i=0; i<symbmtx->cblknbr; i++, enode++)
492 {
493 /* If the cblk has at least one extra diagonal block, */
494 /* the father of the node is the facing block of the first odb */
495 if( (symbmtx->cblktab[i+1].bloknum - symbmtx->cblktab[i].bloknum) > 1 )
496 {
497 pastix_int_t fathnum = symbmtx->bloktab[ symbmtx->cblktab[i].bloknum+1 ].fcblknm;
498 enode->fathnum = fathnum;
499 etree->nodetab[fathnum].sonsnbr++;
500 totalsonsnbr++;
501 }
502 /* Otherwise this is a root, and we attach it to -1 */
503 else {
504 etree->nodetab[i].fathnum = -1;
505 eroot->sonsnbr++;
506 totalsonsnbr++;
507 }
508 }
509
510 /* Check that we have only one root */
511 assert(totalsonsnbr == symbmtx->cblknbr);
512
513 /* Set the sons */
514 eTreeSetSons( etree );
515
516 return etree;
517}
518
519/**
520 *@}
521 */
BEGIN_C_DECLS typedef int pastix_int_t
Definition datatypes.h:51
double subpath
Definition elimintree.h:29
double subcost
Definition elimintree.h:28
double ndepath
Definition elimintree.h:27
double ndecost
Definition elimintree.h:26
pastix_int_t fsonnum
Definition elimintree.h:33
pastix_int_t * sonstab
Definition elimintree.h:43
pastix_int_t nodenbr
Definition elimintree.h:41
pastix_int_t baseval
Definition elimintree.h:40
eTreeNode_t * nodetab
Definition elimintree.h:42
pastix_int_t fathnum
Definition elimintree.h:32
static pastix_int_t eTreeRoot(const EliminTree *etree)
Return the root of the elimination tree.
Definition elimintree.h:126
static pastix_int_t eTreeSonI(const EliminTree *etree, pastix_int_t node, pastix_int_t i)
Return the i^{th} son of a given node.
Definition elimintree.h:105
void eTreeSetSons(EliminTree *)
Set the fsonnum fields base on the initialized sonsnbr.
Definition elimintree.c:142
void eTreeGenDot(const EliminTree *, FILE *)
Print the elimination tree in a dot file.
Definition elimintree.c:323
EliminTree * eTreeInit(pastix_int_t)
Initialize the elimination tree structure.
Definition elimintree.c:43
static void etree_SetSonsIndex(EliminTree *etree)
Set the fsonnum fields base on the initialized sonsnbr.
Definition elimintree.c:114
pastix_int_t eTreeLeavesNbr(const EliminTree *)
Compute the number of leaves.
Definition elimintree.c:179
EliminTree * eTreeBuild(const symbol_matrix_t *)
Build the elimination tree.
Definition elimintree.c:478
pastix_int_t eTreeGetLevelMinIdx(const EliminTree *, pastix_int_t, pastix_int_t, pastix_int_t)
Return the smallest index of the nodes belonging to the level lvl in the elimination tree.
Definition elimintree.c:429
void eTreePrint(const EliminTree *, FILE *, pastix_int_t)
Print the elimination tree in a human readable format.
Definition elimintree.c:378
static eTreeNode_t * eTreeFather(const EliminTree *etree, pastix_int_t node)
Return the father of a given node.
Definition elimintree.h:78
pastix_int_t eTreeComputeLevels(EliminTree *, pastix_int_t, pastix_int_t)
Compute the number of level existing below a given node.
Definition elimintree.c:250
pastix_int_t eTreeNodeLevel(const EliminTree *, pastix_int_t)
Compute the number of level existing below a given node.
Definition elimintree.c:289
pastix_int_t eTreeLevel(const EliminTree *)
Compute the height of the elimination tree.
Definition elimintree.c:209
void eTreeExit(EliminTree *)
Free the elimination tree structure.
Definition elimintree.c:89
Node of the elimination tree.
Definition elimintree.h:25
Elimination tree.
Definition elimintree.h:39
pastix_int_t fcblknm
Definition symbol.h:63
symbol_cblk_t * cblktab
Definition symbol.h:83
pastix_int_t bloknum
Definition symbol.h:48
symbol_blok_t * bloktab
Definition symbol.h:84
pastix_int_t cblknbr
Definition symbol.h:79
Symbol matrix structure.
Definition symbol.h:77