-1

Given a truth table with 5 inputs and one output, with a function prototype like:

bool compute(bool in1, bool in2, bool in3, bool in4, bool in5);

Is there somewhere, in the STL or other library, a class that allows to easily and efficiently manage the implementation of such a function?

In particular, the idea would be to be able to easily code the truth table with a kind of array like this:

some_type truth_table = [[0,0,0,0,0,0],
[0,0,0,0,1,1],
[0,0,0,1,0,1]
...];

Ideally, the class could "optimize" the truth table by avoiding unnecessary row evaluation.

This post and this post start to answer the question but using custom macros/implems.

Welgriv
  • 714
  • 9
  • 24
  • what library or class are you looking for? You need boolean operators, what else? A simple brute force wont be less efficient than some clever tricks. Proove me wrong, I doubt it. – 463035818_is_not_an_ai Feb 21 '23 at 09:55
  • btw asking for libraries is offtopic – 463035818_is_not_an_ai Feb 21 '23 at 09:56
  • Well, it's kinda hard to answer without knowing *what* truth table are you talking about. – Bob__ Feb 21 '23 at 09:57
  • @463035818_is_not_a_number sorry for got errors, however, regarding your comments, it seems obvious you get what I asked for. – Welgriv Feb 21 '23 at 10:06
  • no, not really "obvious". I really do not understand what you are looking for. Its a common problem of questions that ask how to avoid code that they assume things would be obvious and it would be not necessary to explain what should be avoided. – 463035818_is_not_an_ai Feb 21 '23 at 10:10
  • @463035818_is_not_a_number of course I *can* code it with boolean operators, `if` `else` or even assembly, but I just search for something convenient to use and that won't be insanely hard to read and understand. I am sure many peoples have this same problem and I was just wondering if something convenient already exists instead of re-coding my own thing. There is nothing to prove here. – Welgriv Feb 21 '23 at 10:10
  • Whats wrong with the Q&As you link? – 463035818_is_not_an_ai Feb 21 '23 at 10:11
  • @463035818_is_not_a_number posts I linked reinvent the wheel each time. I was hoping for an already coded that I can use has an API. – Welgriv Feb 21 '23 at 10:19
  • and that is bullet 3) here https://stackoverflow.com/help/on-topic. – 463035818_is_not_an_ai Feb 21 '23 at 10:20
  • btw, nothing to proove, indeed, but I really do not see the wheel. I see a function that is a couple of lines of code. I see no hard to read and understand code. If you have such code and you need help to fix it, you need to show the code – 463035818_is_not_an_ai Feb 21 '23 at 10:22
  • @463035818_is_not_a_number if bullet3) was fully respected everywhere then any post mentioning the use of some stl function like even `cout` would be irrelevant. – Welgriv Feb 21 '23 at 10:24
  • I think the crucial part is "...Instead, describe the problem and what has been done so far to solve it.". You state the problem would be obvious. hm... ok – 463035818_is_not_an_ai Feb 21 '23 at 10:28

4 Answers4

1

If you want to check if all the supplied values are true, you could make a variadic function template and do a fold over logical AND:

template<class... Args>
constexpr bool compute(Args&&... bools) {
    return (... && static_cast<bool>(bools));
    //     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  fold over &&
}

bool result = compute(true, true, true, true);

A 1D array version could look like this:

template<class some_type, std::size_t N>
constexpr bool compute(const some_type(&arr)[N]) {
    return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
        return (... && static_cast<bool>(arr[Is]));
    }(std::make_index_sequence<N>());
}

bool result = compute({true, true, true, true});

For arrays with an arbitraty number of dimensions:

template <class some_type, std::size_t N>
constexpr bool compute(const some_type (&arr)[N]) {
    if constexpr (std::rank_v<some_type> == 0) {
        // The same 1D array fold expression as above
        return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
            return (... && static_cast<bool>(arr[Is]));
        }(std::make_index_sequence<N>());
    } else {
        // More than 1 dimension:
        return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
            // recursively unwrap dimensions
            return (... && compute(arr[Is]));
        }(std::make_index_sequence<N>());
    }
}

some_type truth_table[2][3][6] = {{
                                        {1, 1, 1, 1, 1, 1},
                                        {0, 0, 0, 0, 1, 1},
                                        {0, 0, 0, 1, 0, 1},
                                    },
                                    {
                                        {1, 1, 1, 1, 1, 1},
                                        {0, 0, 0, 0, 1, 1},
                                        {0, 0, 0, 1, 0, 1},
                                    }};

std::cout << compute(truth_table) << '\n';

Ideally, the class could "optimize" the truth table by avoiding unnecessary row evaluation.

All of the above makes use of short-circuit evaluation and will stop the comparison at the first false encountered.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • note that OP links duplicates already, but states they dont want code, they want a library. In either case the question is offtopic. – 463035818_is_not_an_ai Feb 21 '23 at 10:07
  • @463035818_is_not_a_number didn't asked for library, asked for a class/interface ready to use. I was speaking about library because it is likely that code distribution is done through such a mean. – Welgriv Feb 21 '23 at 10:17
  • @463035818_is_not_a_number Aha, I didn't read beyond _"macros"_ :-) – Ted Lyngmo Feb 21 '23 at 11:02
  • @Welgriv I added an array version since you updated your question. To my knowledge, there is nothing ready in the standard library to do this for runtime values. – Ted Lyngmo Feb 21 '23 at 11:27
1

Is there somewhere, in the STL or other library, a class that allows to easily and efficiently manage the implementation of such a function?

Yes. The input to your function can construct a std::array<bool, 5>, and your truth table a std::set<std::array<bool, 5>>. Wrapped up in a class, to hide the modifiers of table:

class TruthTable
{
public: 
    TruthTable(std::set<std::array<bool, 5>> table = {}) : table(table) {}

    bool compute(bool in1, bool in2, bool in3, bool in4, bool in5) { return table.contains({ in1, in2, in3, in4, in5, }); }
private:
    std::set<std::array<bool, 5>> table;
};

To generalise this, you could extract the 5 out into a template parameter:

template <size_t N>
class TruthTable
{
public: 
    TruthTable(std::set<std::array<bool, N>> table = {}) : table(table) {}

    template <typename... Args>
    requires (sizeof...(Args) == N)
    bool compute(Args... args) { return table.contains({ args... }); }
private:
    std::set<std::array<bool, N>> table;
};

Or as bitmask suggests, you can represent it with std::bitsets

template <size_t N>
class TruthTable
{
public: 
    TruthTable(std::initializer_list<std::bitset<N>> strings = {}) 
    {
        for (auto string : strings) table.set(string.to_ullong());
    }

    bool compute(std::bitset<N> string) { return table.test(string.to_ullong()); }
private:

    std::bitset<1<<N> table;
};
Caleth
  • 52,200
  • 2
  • 44
  • 75
1

Just to mention, the tool on this website implements the basic algorithm to generate a binary formula from the output values of a truth table with an arbitrary number of inputs. You enter the boolean sequence of outputs and the formula is visible in the upper left corner. You can then select the "PROGRAMMING" mode to have the correct operators. Then you just have to substitute the names of the given inputs (a,b,c etc...) by the name of the parameters of your function (in1, in2, in3...).

For instance the output sequence 00110101 gives

f(a,b,c)= (a && c) || ( ~a && b)

then after manual substitution you can have the code (for three inputs only):

return (in1 && in3) || ( ~in1 && in2);
Welgriv
  • 714
  • 9
  • 24
0

If you have a set of only five input bits, there can be only 2^2^5 = 2^32 different functions.

The encoding of a binary function taking five bool inputs is therefore -- std::uint32_t. More generally, std::bitset<1<<N>.


What does that mean?

For example if you have only two boolean values you have 2^2^2 = 16 different functions being encodable in 4 bits (instead of 32). How do we decode the function? Easy, take the numerical representation of the input values (as bits) and access that bit in the function's number:

Input: (1,0), Function: 0110b
10b = 2
0110b
 ^--- bit 2 == 10b

The same applies to five bits, but the number is just longer:

Input (0,0,1,0,1), Function: 10101011101110101110110101010101b
                                                       ^-- bit 5 == 00101b

The implementation is trivial, branch-free and minimal with respect to required memory.

If you have hand-implemented constexpr functions you could even extract the binary representation at compile-time and build a database this way.

bitmask
  • 32,434
  • 14
  • 99
  • 159