0

I want to write the maximal clique algorithm for use with an adjacency matrix. I'm following a video which explains how to code and implement the algorithm using Python. I'm currently trying to code the powerset function at 2 minutes into the video.

def powerSet(elts):
    if len(elts) == 0:
        return [[]]
    else:
        smaller = powerSet(elts[1:])
        elt = [elts[0]]
        withElt = []
        for s in smaller:
            withElt.append(s + elt)
        allofthem = smaller + withElt
    return allofthem

print powerSet([1, 2, 3, 4, 5])

I want to rewrite this in C++. I'm not sure if I should be using arrays or not. So far I have coded the below but I don't know how to return an empty array inside an empty array (when the elts list is of size 0).

I wrote an isEmpty function for the array since I cant use len(elts) like in Python. My approach is probably not the best approach to take so I am open to any advice.

UPDATE:

array powerSet(int elts[])
{
     if (isEmpty(elts)==1)
     {
          return {{}};
     }

}

In my int main I have:

list<int> elts;

list<int>::iterator i;

for (i=elts.begin(); i != elts.end(); ++i)
      cout << *i << " ";
      cout << endl;

powerSet(elts);    

I don't know what to do from here.

The code should use either an array/list/vector that we call 'elts' (short for elements). Then firstly, it should add the empty list [], then the rest of the power set (all shown in the video).

So for example, in the case that elts = [1,2,3,4], my code should return:

`[ [],[4],[3],[4,3],[2],[4,2],[3,2],[4,3,2],[1],[4,1],[3,1],[4,3,1],[2,1],[4,2,1],[‌​3,2,1],[4,3,2,1] ]  `  

I don't know how to use array/list/vector to do the above.

TooTone
  • 7,129
  • 5
  • 34
  • 60
  • 1
    To start out with, the Python snip is using lists, so that may be a good place to start. I recommend using an STL container class (std::list, std::vector, std::array [if you can work with C++11], etc.) That will allow you to take advantage of the `.empty()` function and remove the need for isEmpty. – Elliot Robinson Apr 06 '14 at 19:04
  • Nuitka may "compile" python to C++. Maybe try some simple stataments and check the generated code help. – cox Apr 06 '14 at 19:52
  • I'd like to be able to write the code in c++ if possible. – user3504227 Apr 06 '14 at 21:21
  • I'd like to be able to write the code in c++ if possible. I have no experience using arrays,lists or vectors so if someone could show me how to implement the code using one of the above it would be a help. I'll need to make a list of lists it seems, as the first entry where it equals zero just prints {{}} ... What i'll want is the set to be printed out as list of lists.. like the video where it shows testset= [1,2,3,4] .. the output is then [ [],[4],[3],[4,3],[2],[4,2],[3,2],[4,3,2],[1],[4,1],[3,1],[4,3,1],[2,1],[4,2,1],[3,2,1],[4,3,2,1] ]. I don't know how to print out like this. Please help – user3504227 Apr 06 '14 at 21:29
  • This code http://www.cplusplus.com/forum/beginner/51164/ does what I want but I dont understand it. Could anyone explain how it works ? – user3504227 Apr 06 '14 at 22:02
  • @user3504227 I saw your latest comment after I finished up my answer. I've addressed your original question using the Python code from the video. If there's anything you don't understand, please comment under my answer. – TooTone Apr 06 '14 at 22:55

1 Answers1

0

Here's a fairly literal translation of the Python code

#include <vector>
using std::vector;
#include <iostream>
using std::cout;

//def powerSet(elts):
vector<vector<int>> powerSet(const vector<int>& elts)
{
//  if len(elts) == 0:
    if (elts.empty()) {
//      return [[]]
        return vector<vector<int>>(
            1, // vector contains 1 element which is...
            vector<int>()); // ...empty vector of ints
    }
//  else:
    else {
//      smaller = powerSet(elts[1:])
        vector<vector<int>> smaller = powerSet(
            vector<int>(elts.begin() +1, elts.end()));
//      elt = [elts[0]]
        int elt = elts[0]; // in Python elt is a list (of int)
//      withElt = []
        vector<vector<int>> withElt;
//      for s in smaller:
        for (const vector<int>& s: smaller) {
//          withElt.append(s + elt)
            withElt.push_back(s);
            withElt.back().push_back(elt);
        }
//      allofthem = smaller + withElt
        vector<vector<int>> allofthem(smaller);
        allofthem.insert(allofthem.end(), withElt.begin(), withElt.end());
//      return allofthem
        return allofthem;
    }
}

This uses vector<int> for the set of integers. And then a vector of this, i.e. vector<vector<int>> is a list of sets of integers. You specifically asked about one thing

I don't know how to return an empty array inside an empty array (when the elts list is of size 0).

The first return statement returns a list with one element, the empty set, using a vector constructor, whose first argument n is the number of elements in the vector, and whose second argument is the element to repeat n times. An equivalent but more long-winded alternative is

    vector<vector<int>> powerSetOfEmptySet;
    vector<int> emptySet;
    powerSetOfEmptySet.push_back(emptySet);
    return powerSetOfEmptySet;

I've tried to keep the code simple and avoid too many esoteric C++ features. Hopefully you can work through it with the aid of a good reference. One C++ idiom I have used is appending one vector to another as in allofthem.insert(allofthem.end(), withElt.begin(), withElt.end());.

Also in C++, which is "closer to the metal" than Python, you would probably use just one vector in place of the three vectors smaller, withElt and allofthem. This leads to the shorter and more optimal code below.

//def powerSet(elts):
vector<vector<int>> powerSet(const vector<int>& elts)
{
//  if len(elts) == 0:
    if (elts.empty()) {
//      return [[]]
        return vector<vector<int>>(1, vector<int>());
    }
//  else:
    else {
//      smaller = powerSet(elts[1:])
        vector<vector<int>> allofthem = powerSet(
            vector<int>(elts.begin() +1, elts.end()));
//      elt = [elts[0]]
        int elt = elts[0]; // in Python elt is a list (of int)
//      withElt = []
//      for s in smaller:
//          withElt.append(s + elt)
//      allofthem = smaller + withElt
        const int n = allofthem.size();
        for (int i=0; i<n; ++i) {
            const vector<int>& s = allofthem[i];
            allofthem.push_back(s);
            allofthem.back().push_back(elt);
        }
//      return allofthem
        return allofthem;
    }
}

Test code below

int main()
{
    const int N = 5;
    vector<int> input;
    for(int i=1; i<=N; ++i) {
        input.push_back(i);
    }
    vector<vector<int>> ps = powerSet(input);
    for(const vector<int>& set:ps) {
        cout << "[ ";
        for(int elt: set) {
            cout << elt << " ";
        }
        cout << "]\n";
    }
    return 0;
}

As a footnote, I was pleasantly surprised as to how straightforward it was to translate from Python into C++. I had read that it might make sense to use Python to write (or prototype) algorithms, and then rewrite in a language such as C++ as necessary, but, as the proverb goes, seeing is believing.


Here is a version of the program that works with C++98. I reverted the basic C++11 features that I used (>> in template declarations and range-based for).

#include <vector>
using std::vector;
#include <iostream>
using std::cout;

vector<vector<int> > powerSet(const vector<int>& elts)
{
    if (elts.empty()) {
        return vector<vector<int> >(1, vector<int>());
    }
    else {
        vector<vector<int> > allofthem = powerSet(
            vector<int>(elts.begin() +1, elts.end()));
        int elt = elts[0];
        const int n = allofthem.size();
        for (int i=0; i<n; ++i) {
            const vector<int>& s = allofthem[i];
            allofthem.push_back(s);
            allofthem.back().push_back(elt);
        }
        return allofthem;
    }
}

int main()
{
    const int N = 5;
    vector<int> input;
    for(int i=1; i<=N; ++i) {
        input.push_back(i);
    }
    vector<vector<int> > ps = powerSet(input);
    for(vector<vector<int> >::const_iterator i=ps.begin(); i!=ps.end(); ++i) {
        const vector<int>& set = *i;
        cout << "[ ";
        for(vector<int>::const_iterator j=set.begin(); j!=set.end(); ++j) {
            int elt = *j;
            cout << elt << " ";
        }
        cout << "]\n";
    }
    return 0;
}
TooTone
  • 7,129
  • 5
  • 34
  • 60
  • Thanks for the reply TooTone ! I'm trying to run the optimal code + test code above. The first time I attempted to run, I get an error '>>' should be `> >' within a nested template argument list " so I changed anywhere it says vector> to vector > and the error was no longer reported. But now it gives me an error "expected primary-expression before "const" " at line 8 of the int main test code "vector> ps = powerSet(input); ". Not too sure what to do to fix error. – user3504227 Apr 06 '14 at 23:42
  • Its also stopping me for same "expected primary-expression before "const" " error on this line: "for (const vector& s: smaller){" on your longer code above. – user3504227 Apr 06 '14 at 23:52
  • @user3504227 I'm compiling on VS2012, which has C++11 support; I haven't done anything complicated however (far from it!). What compiler are you using? This should compile ok with `gcc` and if you're on Windows you can get Visual C++ Express 2012 I believe. I'd strongly advise you use the latest stable compiler. If you can't do that, then try something like ideone. I've put the code up there as http://ideone.com/ENgGL2 and it works fine (click on the link to see and run the program code). – TooTone Apr 06 '14 at 23:53
  • Atm I'm using the most reason version of dev c++. So i think its g++. I want to change to something else because I dont like really dev c++. We use it for college. I want to use something that my college can also install on the computers if it is good. Maybe netbeans ? – user3504227 Apr 06 '14 at 23:58
  • @user3504227 I've added a C++98 version to my answer. Good luck getting it to work. And good luck getting something better on your college computers! (although perhaps you just need to enable C++11 compilation for dev c++?) – TooTone Apr 07 '14 at 00:10
  • Thanks I got that working ! My goal is to code the remaining functions on the video and then be able to run the functions on an adjacency matrix to find the max clique. I already have my function which creates an adjacency matrix from social network data. So I should be able to use the functions to efficiently find the maximal clique from this matrix. – user3504227 Apr 07 '14 at 00:38