panthema / 2016 / 0114-diploma-thesis / bispanning-graph-framework-v0.5 / src / combinatorics.h (Download File)
/*******************************************************************************
 * src/combinatorics.h
 *
 * Some basic combinatorial enumeration utilities.
 *
 * Copyright (C) 2013-2016 Timo Bingmann <tb@panthema.net>
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/

#ifndef BISPANNING_COMBINATORICS_HEADER
#define BISPANNING_COMBINATORICS_HEADER

#include <algorithm>
#include <string>
#include <vector>

//! increment a left-most least-significant vector [0,1,0,1,...,1,0] of boolean
//! values, false if the vector wrapped to zero.
template <typename ValueType>
bool increment_boolean_vector(std::vector<ValueType>& v)
{
    for (unsigned int i = 0; i < v.size(); ++i)
    {
        if (v[i] == 0) {
            v[i] = 1;
            return true;
        }
        else {
            v[i] = 0;
        }
    }
    return false;
}

//! Call a functional object enumerating all k-subsets of {0,...,n-1} providing
//! them as a std::vector<size_t>. The enumeration is ended if the functional
//! returns false.
template <typename Functor>
bool choose(unsigned int n, unsigned int k, Functor functor)
{
    std::string bitmask(k, 1); // k leading 1's
    bitmask.resize(n, 0);      // n-k trailing 0's

    std::vector<size_t> items(k);

    // permute bitmask and output items
    do {
        for (unsigned int i = 0, j = 0; i < n; ++i) { // items [0..N-1]
            if (bitmask[i]) items[j++] = i;
        }

        if (!functor(items)) return false;
    }
    while (std::prev_permutation(bitmask.begin(), bitmask.end()));

    return true;
}

//! Call a functional object for all set partitions of {0,...,n-1}, providing
//! identification via a std::vector<size_t>. The enumeration is ended if the
//! functional returns false.
template <typename Functor>
bool enumerate_set_partitions(size_t n, Functor functor)
{
    // from http://compprog.wordpress.com/2007/10/15/generating-the-partitions-of-a-set/
    // massively fixed and changed to 0..n-1.

    /* s[i] is the number of the set in which the ith element should go */
    std::vector<size_t> s(n, 0);
    /* m[i] is the largest of the first i elements in s */
    std::vector<size_t> m(n, 0);

    /* 0 0 0 0 is the first way to partition a set is to put all the elements
       in the same subset. */

    /* Output the first partitioning. */
    if (!functor(s))
        return false;

    /* Print the other partitioning schemes. */
    while (1)
    {
        /* Update s: 0 0 0 0 -> 1 0 0 0 -> 0 1 0 0 ->
           1 1 0 0 -> 2 1 0 0 -> 0 0 1 0 ... */

        size_t i = 0;
        ++s[i];
        while ((i < n - 1) && (s[i] > m[i + 1] + 1)) {
            s[i] = 0;
            ++i;
            ++s[i];
        }

        /* If i is has reached n-1 th element, then the last unique partitiong
           has been found */
        if (i == n - 1)
            break;

        /* Because all the first i elements are now 1, s[i] (i + 1 th element)
           is the largest. So we update max by copying it to all the first i
           positions in m. */
        if (s[i] > m[i])
            m[i] = s[i];

        size_t j = i;
        while (j > 0)
            m[--j] = m[i];

        if (!functor(s))
            return false;
    }

    return true;
}

#endif // !BISPANNING_COMBINATORICS_HEADER

/******************************************************************************/