0

I'd like to create a set which has transitive pairs. My input will be of the form pair<int, int> and I need a set which has all transitive pairs for the given inputs. For example, if I have pairs {1, 2} {2, 1} {2, 3} {3,4} as inputs, then I need to have a SET which has pairs { {1,2}, {2,1}, {1, 3}, {3, 4}, {1, 4}, {2, 4} }. I also need to find whether a given pair is a member of this transitive set. Is there any built-in data structure/STL library that will allow me to accomplish this in C++?

user3125772
  • 73
  • 1
  • 10

2 Answers2

1

You have a graph and you want to turn it into a free category, AKA the transitive closure of that graph.

Your int pair elements are vertices, the pairs themselves are edges, that's your graph. Now a free category on a graph is that graph with an edge composition law, and all additional edges that can be produced by the law. The law says that

  • if there is an edge (or "arrow" as the category theory names it) f that runs from a to b
  • and an edge g that runs from b to c
  • then there's another edge denoted f∘g that runs from a to c
  • the composition is associative ((f∘g)∘h = f∘(g∘h))

(Every category also have unit edges, denoted 1a that run from a to a for every vertex a, and a law which says that for every arrow f that runs from a to b, 1a∘f = f∘1b= f, but we are not talking about those).

The general education part of this answer is hereby completed.

There are no relevant algorithms in the C++ standard library, but you may want to check boost::graph or any other graph-oriented library. boost::graph has the transitive_closure method which is just what you want.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
1

You can represent your set with:

set<pair<int, int>> myset;

The transitive closure could then be computed with:

void transitive_closure(set<pair<int, int>>& s)
{
    set<pair<int, int>> a;   // missing nodes to add
    for (auto i = s.cbegin(); i != s.cend(); i++)
    {
        for (auto j = i; ++j != s.cend(); j)
        {
            if (i->second == j->first 
                  && i->first != j->second 
                  && s.count(make_pair(i->first, j->second))==0 )
                a.insert(make_pair(i->first, j->second));
        }
    }
    if (!a.empty()) {
        for (auto p : a)
            s.insert(p);
        transitive_closure(s);
    }
}

It's not the most optimized algorithm, because the recursion will repeat some comparisons. But it works. By he way, I think you've forgotten {2, 3} in your result set.

To check if a pair belongs to the set, just check if s.count(make_pair(i->first, j->second)!=0

Christophe
  • 68,716
  • 7
  • 72
  • 138
  • I'm getting this error: 'class std::set >' has no member named 'cbegin', 'cend' , | base operand of '->' is not a pointer| Also { for (auto p : a) } <- This also throws up another error. – user3125772 Jul 07 '14 at 13:38
  • Hm... I compiled and tested it with msvc2013. What compiler do you use ? – Christophe Jul 07 '14 at 16:48
  • @user3125772 `.cbegin()` and `.cend()` are C++11 (http://www.cplusplus.com/reference/set/set/). If you use gnu, don't forget the `-std=c++11` compiler option. Otherwhise you could use `.begin()` and `.end()`, their non const equivalent. – Christophe Jul 07 '14 at 17:40
  • I'm making the following pairs: pair {1 1}pair {1 2} pair {2 1} pair {2 2} pair{ 2 4}pair 3 3 pair 3 4 pair 4 2 pair 4 3 pair 4 4 pair 5 5, after that I'm calling the transitive closure function. So basically 1,3 should now be in the transitive set. ((1,2)(2,4)(4,3) so I want (1,3) in the transitive set too) But it still says "NO"..! – user3125772 Jul 07 '14 at 17:50
  • Can I use a binary tree? – user3125772 Jul 07 '14 at 18:08
  • With `input[]={{1,1},{1,2},{2,1},{2,2},{2,4},{3,3},{3,4},{4,2},{4,3},{4,4},{5,5}}`, I get the following closure set: `{{1,1}{1,2}{1,3}{1,4}{2,1}{2,2}{2,3}{2,4}{3,2}{3,3}{3,4}{4,2}{4,3}{4,4}{5,5}}` so 1,3 is in... – Christophe Jul 07 '14 at 18:38
  • If I want to check programatically, `cout << "(1,3) " << ((myset.count(make_pair(1, 3)) != 0) ? "is":"is not" ) << " in\n";` also confirms that the pair is in. In fact sets are typically implemented as binary search trees. – Christophe Jul 07 '14 at 18:44