17faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// This file is part of Eigen, a lightweight C++ template library
27faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// for linear algebra.
37faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez//
47faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr>
57faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez//
67faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// This Source Code Form is subject to the terms of the Mozilla
77faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// Public License v. 2.0. If a copy of the MPL was not distributed
87faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
97faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/* This file is a modified version of heap_relax_snode.c file in SuperLU
117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * -- SuperLU routine (version 3.0) --
127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Univ. of California Berkeley, Xerox Palo Alto Research Center,
137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * and Lawrence Berkeley National Lab.
147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * October 15, 2003
157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *
167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Copyright (c) 1994 by Xerox Corporation.  All rights reserved.
177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *
187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY
197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *
217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Permission is hereby granted to use or copy this program for any
227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * purpose, provided the above notices are retained on all copies.
237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * Permission to modify the code and to distribute modified code is
247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * granted, provided the above notices are retained, and a notice that
257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * the code was modified is included with the above copyright notice.
267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */
277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
287faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#ifndef SPARSELU_HEAP_RELAX_SNODE_H
297faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#define SPARSELU_HEAP_RELAX_SNODE_H
307faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
317faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeznamespace Eigen {
327faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeznamespace internal {
337faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
347faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez/**
357faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \brief Identify the initial relaxed supernodes
367faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez *
377faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * This routine applied to a symmetric elimination tree.
387faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * It assumes that the matrix has been reordered according to the postorder of the etree
397faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param n The number of columns
407faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param et elimination tree
417faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param relax_columns Maximum number of columns allowed in a relaxed snode
427faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param descendants Number of descendants of each node in the etree
437faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez * \param relax_end last column in a supernode
447faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez */
457faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandeztemplate <typename Scalar, typename Index>
467faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandezvoid SparseLUImpl<Scalar,Index>::heap_relax_snode (const Index n, IndexVector& et, const Index relax_columns, IndexVector& descendants, IndexVector& relax_end)
477faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez{
487faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
497faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // The etree may not be postordered, but its heap ordered
507faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  IndexVector post;
517faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  internal::treePostorder(n, et, post); // Post order etree
527faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  IndexVector inv_post(n+1);
537faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index i;
547faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for (i = 0; i < n+1; ++i) inv_post(post(i)) = i; // inv_post = post.inverse()???
557faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
567faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // Renumber etree in postorder
577faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  IndexVector iwork(n);
587faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  IndexVector et_save(n+1);
597faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for (i = 0; i < n; ++i)
607faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
617faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    iwork(post(i)) = post(et(i));
627faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
637faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  et_save = et; // Save the original etree
647faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  et = iwork;
657faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
667faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // compute the number of descendants of each node in the etree
677faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  relax_end.setConstant(emptyIdxLU);
687faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index j, parent;
697faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  descendants.setZero();
707faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for (j = 0; j < n; j++)
717faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
727faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    parent = et(j);
737faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    if (parent != n) // not the dummy root
747faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      descendants(parent) += descendants(j) + 1;
757faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  }
767faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // Identify the relaxed supernodes by postorder traversal of the etree
777faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index snode_start; // beginning of a snode
787faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index k;
797faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index nsuper_et_post = 0; // Number of relaxed snodes in postordered etree
807faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index nsuper_et = 0; // Number of relaxed snodes in the original etree
817faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  Index l;
827faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  for (j = 0; j < n; )
837faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  {
847faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    parent = et(j);
857faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    snode_start = j;
867faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    while ( parent != n && descendants(parent) < relax_columns )
877faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
887faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      j = parent;
897faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      parent = et(j);
907faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
917faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // Found a supernode in postordered etree, j is the last column
927faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    ++nsuper_et_post;
937faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    k = n;
947faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    for (i = snode_start; i <= j; ++i)
957faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      k = (std::min)(k, inv_post(i));
967faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    l = inv_post(j);
977faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    if ( (l - k) == (j - snode_start) )  // Same number of columns in the snode
987faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
997faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      // This is also a supernode in the original etree
1007faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      relax_end(k) = l; // Record last column
1017faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      ++nsuper_et;
1027faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
1037faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    else
1047faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    {
1057faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      for (i = snode_start; i <= j; ++i)
1067faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      {
1077faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        l = inv_post(i);
1087faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        if (descendants(i) == 0)
1097faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        {
1107faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          relax_end(l) = l;
1117faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez          ++nsuper_et;
1127faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez        }
1137faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez      }
1147faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    }
1157faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    j++;
1167faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    // Search for a new leaf
1177faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez    while (descendants(j) != 0 && j < n) j++;
1187faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  } // End postorder traversal of the etree
1197faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1207faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  // Recover the original etree
1217faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez  et = et_save;
1227faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez}
1237faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1247faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} // end namespace internal
1257faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez
1267faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez} // end namespace Eigen
1277faaa9f3f0df9d23790277834d426c3d992ac3baCarlos Hernandez#endif // SPARSELU_HEAP_RELAX_SNODE_H
128