944,085 Members | Top Members by Rank

Ad:
You are currently viewing page 1 of this multi-page discussion thread
Mar 21st, 2006
0

The fastest combination generator

Expand Post »
Dear all,

I am looking for an expert opinion on what the fastest combination generator is. I am currently facing a problem of generating a huge combinations (k elements out of n) and as it stands now, the running time of my program will take more than three years. My current implementation uses the Algorithm R (see Knuth's book pre-fascicle 3a), a revolving-door algorithm.

If anyone knows a better/faster way of enumerating combinations, please let me know. Many thanks.
Similar Threads
Reputation Points: 10
Solved Threads: 0
Newbie Poster
dirt_bagz is offline Offline
3 posts
since Mar 2006
Mar 22nd, 2006
0

Re: The fastest combination generator

Quote originally posted by dirt_bagz ...
Dear all,

I am looking for an expert opinion on what the fastest combination generator is. I am currently facing a problem of generating a huge combinations (k elements out of n) and as it stands now, the running time of my program will take more than three years. My current implementation uses the Algorithm R (see Knuth's book pre-fascicle 3a), a revolving-door algorithm.

If anyone knows a better/faster way of enumerating combinations, please let me know. Many thanks.
Well unless you have access to a quantum computer I doubt you will be able to cut down on run time. Knuth's work is generally accepted as being the best for algorithms and reducing time complexity.

However, you may be looking at your problem in the wrong way. Take for example the classic travelling salesman problem.

Applying a brute force algorithm to calculate the shortest route for a journey with 100+ pit-stops will take an unfathomable amount of time.

However, if you adopt a heuristic approach you can find a high probabilistic solution,within a much smaller time scale.

Perhaps you need to think about approaching your problem from a different angle.

See this:

http://en.wikipedia.org/wiki/Dynamic_programming

Incase anyone wanted to know here is Knuth's algorithm for producing combinations in C.

 
/* Algorithm by Donald Knuth. */
 
#include <stdio.h>
#include <stdlib.h> 
void main( void)
{
	int i, j=1, k, n, *c, x;
	printf( "Enter n,k: ");
	scanf( "%d,%d", &n, &k);
	c = malloc( (k+3) * sizeof(int));
 
	for (i=1; i <= k; i++) c[i] = i;
	c[k+1] = n+1;
	c[k+2] = 0;
	j = k;
visit:
	for (i=k; i >= 1; i--) printf( "%3d", c[i]);
	printf( "\n");
	if (j > 0) {x = j+1; goto incr;}
	if (c[1] + 1 < c[2])
	 {
	 c[1] += 1;
	 goto visit;
	 }
	j = 2;
do_more:
	c[j-1] = j-1;
	x = c[j] + 1;
	if (x == c[j+1]) {j++; goto do_more;}
	if (j > k) exit(0);
incr:
	c[j] = x;
	j--;
	goto visit;
}


And java
 
//CombinationGenerator.java
//--------------------------------------
// Systematically generate combinations.
//--------------------------------------
import java.math.BigInteger;
public class CombinationGenerator {
private int[] a;
private int n;
private int r;
private BigInteger numLeft;
private BigInteger total;
//------------
// Constructor
//------------
public CombinationGenerator (int n, int r) {
	if (r > n) {
	 throw new IllegalArgumentException ();
	}
	if (n < 1) {
	 throw new IllegalArgumentException ();
	}
	this.n = n;
	this.r = r;
	a = new int[r];
	BigInteger nFact = getFactorial (n);
	BigInteger rFact = getFactorial (r);
	BigInteger nminusrFact = getFactorial (n - r);
	total = nFact.divide (rFact.multiply (nminusrFact));
	reset ();
}
//------
// Reset
//------
public void reset () {
	for (int i = 0; i < a.length; i++) {
	 a[i] = i;
	}
	numLeft = new BigInteger (total.toString ());
}
//------------------------------------------------
// Return number of combinations not yet generated
//------------------------------------------------
public BigInteger getNumLeft () {
	return numLeft;
}
//-----------------------------
// Are there more combinations?
//-----------------------------
public boolean hasMore () {
	return numLeft.compareTo (BigInteger.ZERO) == 1;
}
//------------------------------------
// Return total number of combinations
//------------------------------------
public BigInteger getTotal () {
	return total;
}
//------------------
// Compute factorial
//------------------
private static BigInteger getFactorial (int n) {
	BigInteger fact = BigInteger.ONE;
	for (int i = n; i > 1; i--) {
	 fact = fact.multiply (new BigInteger (Integer.toString (i)));
	}
	return fact;
}
//--------------------------------------------------------
// Generate next combination (algorithm from Rosen p. 286)
//--------------------------------------------------------
public int[] getNext () {
	if (numLeft.equals (total)) {
	 numLeft = numLeft.subtract (BigInteger.ONE);
	 return a;
	}
	int i = r - 1;
	while (a[i] == n - r + i) {
	 i--;
	}
	a[i] = a[i] + 1;
	for (int j = i + 1; j < r; j++) {
	 a[j] = a[i] + j - i;
	}
	numLeft = numLeft.subtract (BigInteger.ONE);
	return a;
}
}

 
/*
* test.java
*
* Created on 14 January 2006, 16:29
*/
/**
*
* @author iamthwee
*/
public class test {
 
	/** Creates a new instance of test */
	public test() {
	}
 
	/**
	 * @param args the command line arguments
	 */
	public static void main(String[] args) {
		String[] elements = {"a", "b","c","d"};
int[] indices;
CombinationGenerator x = new CombinationGenerator (elements.length, 2);
StringBuffer combination;
while (x.hasMore ()) {
combination = new StringBuffer ();
indices = x.getNext ();
for (int i = 0; i < indices.length; i++) {
	combination.append (elements[indices[i]]);
}
System.out.println (combination.toString ());
}
 
	}
 
}
Featured Poster
Reputation Points: 1536
Solved Threads: 431
Posting Expert
iamthwee is offline Offline
5,865 posts
since Aug 2005
Mar 22nd, 2006
0

Re: The fastest combination generator

Quote originally posted by iamthwee ...
Well unless you have access to a quantum computer I doubt you will be able to cut down on run time. Knuth's work is generally accepted as being the best for algorithms and reducing time complexity.

However, you may be looking at your problem in the wrong way. Take for example the classic travelling salesman problem.

Applying a brute force algorithm to calculate the shortest route for a journey with 100+ pit-stops will take an unfathomable amount of time.

However, if you adopt a heuristic approach you can find a high probabilistic solution,within a much smaller time scale.

Perhaps you need to think about approaching your problem from a different angle.

See this:

http://en.wikipedia.org/wiki/Dynamic_programming

Incase anyone wanted to know here is Knuth's algorithm for producing combinations in C.

 
/* Algorithm by Donald Knuth. */
 
#include <stdio.h>
#include <stdlib.h> 
void main( void)
{
	int i, j=1, k, n, *c, x;
	printf( "Enter n,k: ");
	scanf( "%d,%d", &n, &k);
	c = malloc( (k+3) * sizeof(int));
 
	for (i=1; i <= k; i++) c[i] = i;
	c[k+1] = n+1;
	c[k+2] = 0;
	j = k;
visit:
	for (i=k; i >= 1; i--) printf( "%3d", c[i]);
	printf( "\n");
	if (j > 0) {x = j+1; goto incr;}
	if (c[1] + 1 < c[2])
	 {
	 c[1] += 1;
	 goto visit;
	 }
	j = 2;
do_more:
	c[j-1] = j-1;
	x = c[j] + 1;
	if (x == c[j+1]) {j++; goto do_more;}
	if (j > k) exit(0);
incr:
	c[j] = x;
	j--;
	goto visit;
}


And java
 
//CombinationGenerator.java
//--------------------------------------
// Systematically generate combinations.
//--------------------------------------
import java.math.BigInteger;
public class CombinationGenerator {
private int[] a;
private int n;
private int r;
private BigInteger numLeft;
private BigInteger total;
//------------
// Constructor
//------------
public CombinationGenerator (int n, int r) {
	if (r > n) {
	 throw new IllegalArgumentException ();
	}
	if (n < 1) {
	 throw new IllegalArgumentException ();
	}
	this.n = n;
	this.r = r;
	a = new int[r];
	BigInteger nFact = getFactorial (n);
	BigInteger rFact = getFactorial (r);
	BigInteger nminusrFact = getFactorial (n - r);
	total = nFact.divide (rFact.multiply (nminusrFact));
	reset ();
}
//------
// Reset
//------
public void reset () {
	for (int i = 0; i < a.length; i++) {
	 a[i] = i;
	}
	numLeft = new BigInteger (total.toString ());
}
//------------------------------------------------
// Return number of combinations not yet generated
//------------------------------------------------
public BigInteger getNumLeft () {
	return numLeft;
}
//-----------------------------
// Are there more combinations?
//-----------------------------
public boolean hasMore () {
	return numLeft.compareTo (BigInteger.ZERO) == 1;
}
//------------------------------------
// Return total number of combinations
//------------------------------------
public BigInteger getTotal () {
	return total;
}
//------------------
// Compute factorial
//------------------
private static BigInteger getFactorial (int n) {
	BigInteger fact = BigInteger.ONE;
	for (int i = n; i > 1; i--) {
	 fact = fact.multiply (new BigInteger (Integer.toString (i)));
	}
	return fact;
}
//--------------------------------------------------------
// Generate next combination (algorithm from Rosen p. 286)
//--------------------------------------------------------
public int[] getNext () {
	if (numLeft.equals (total)) {
	 numLeft = numLeft.subtract (BigInteger.ONE);
	 return a;
	}
	int i = r - 1;
	while (a[i] == n - r + i) {
	 i--;
	}
	a[i] = a[i] + 1;
	for (int j = i + 1; j < r; j++) {
	 a[j] = a[i] + j - i;
	}
	numLeft = numLeft.subtract (BigInteger.ONE);
	return a;
}
}

 
/*
* test.java
*
* Created on 14 January 2006, 16:29
*/
/**
*
* @author iamthwee
*/
public class test {
 
	/** Creates a new instance of test */
	public test() {
	}
 
	/**
	 * @param args the command line arguments
	 */
	public static void main(String[] args) {
		String[] elements = {"a", "b","c","d"};
int[] indices;
CombinationGenerator x = new CombinationGenerator (elements.length, 2);
StringBuffer combination;
while (x.hasMore ()) {
combination = new StringBuffer ();
indices = x.getNext ();
for (int i = 0; i < indices.length; i++) {
	combination.append (elements[indices[i]]);
}
System.out.println (combination.toString ());
}
 
	}
 
}
Dear iamthwee, thanks for your response. I understand that there is a probabilistic way of looking at this problem. However, for my this particular problem, probabilistic solution is not acceptable. This problem is similar to the search for optimum Golomb Ruler of certain marks or minimum distance computation in linear error correcting codes. As you can see here, in order to prove something, a non probabilistic solution is required. Anyway, many thanks.
Reputation Points: 10
Solved Threads: 0
Newbie Poster
dirt_bagz is offline Offline
3 posts
since Mar 2006
Mar 23rd, 2006
0

Re: The fastest combination generator

>This problem is similar to the search for optimum Golomb Ruler Well finding a solution AND proving it is quite beyond me. Oh dear brain lock...:cry: Sorrie.
Featured Poster
Reputation Points: 1536
Solved Threads: 431
Posting Expert
iamthwee is offline Offline
5,865 posts
since Aug 2005
Mar 26th, 2006
0

Re: The fastest combination generator

Hi,

Do you need a solution which is in a smaller time complexity class than Knuth's or have a bound for n,k and just need a faster code to get it done in less than 3 years ? +what is the maximum acceptable time span for you ? because I have some ideas for optimization which can reduce your 3 year but not for n limit to infinity.

Loren Soth
Reputation Points: 28
Solved Threads: 4
Posting Whiz in Training
Lord Soth is offline Offline
233 posts
since Mar 2006
Mar 26th, 2006
0

Re: The fastest combination generator

Hi Loren Soth,

Thanks for your response. I just need a faster code to get my computation done. The value of n does not go to infinity, in fact n <= 512 and 1 <= k <= n/2. If possible, I would like to have to computation done in less than 1 year. Well, 1 year may seem rather long, but I probably can run this computation in parallel using many computers. Hope to hear your optimisation ideas soon.

dirt_bagz.


Quote originally posted by Lord Soth ...
Hi,

Do you need a solution which is in a smaller time complexity class than Knuth's or have a bound for n,k and just need a faster code to get it done in less than 3 years ? +what is the maximum acceptable time span for you ? because I have some ideas for optimization which can reduce your 3 year but not for n limit to infinity.

Loren Soth
Reputation Points: 10
Solved Threads: 0
Newbie Poster
dirt_bagz is offline Offline
3 posts
since Mar 2006
Jun 30th, 2006
0

Re: The fastest combination generator

Hi there!...I'd like to point you to http://www.merriampark.com/comb.htm
I don't know if it's any faster than your current considerations but hope it'll open up some more avenues for thinking...
rgds,
Sandeep
Reputation Points: 10
Solved Threads: 0
Newbie Poster
sandysat is offline Offline
1 posts
since Jun 2006
Jul 13th, 2007
0

Re: The fastest combination generator

I doubt it is as fast as the Knuth code but here is a slightly more modern version of a combination generator using some features of C++ so I guess its C++

nb. if you copy the code and run it you may like to change the lines that set j and k as this currently give all possible combinations of the letters of the English alphabet.

#include <iostream>
#include <vector>
#include <string>

using namespace std;

// just to check the numbers are right

long totalcombs(int n, int r){
	long c=1;
	if (r > n) return 0;
	for (long d=1; d <= r; d++) {
		c *= n--;
		c /= d;
	}
	return c;
}

// example code to get all combination 

int main(){
	vector<int> indx;
	string alpha("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
	int n=26;
	int j=1;
	int k=26;
	for(int twk=j;twk<=k;twk++){
		int r=twk;
		int total=totalcombs(n,r);
		int ccount=1;
		bool done=true;
		for(int iwk=0;iwk<r;iwk++)indx.push_back(iwk);
		while(done){
			done=false;
			cout << ccount++ << " of " << total << " ";
			for(int owk=0;owk<r;owk++){
				cout << alpha[indx[owk]] << " ";
			}
			cout << endl;
			for(int iwk=r-1;iwk>=0;iwk--){
				if(indx[iwk]<=(n-1)-(r-iwk)){
					indx[iwk]++;
					for(int swk=iwk+1;swk<r;swk++){
						indx[swk]=indx[swk-1]+1;
					}
					iwk=-1;
					done=true;
				}	
			}	
		}
		cout << " --------------------------- " << endl;
		indx.clear();
	}
	return 0;
}
Reputation Points: 10
Solved Threads: 0
Newbie Poster
piagina is offline Offline
1 posts
since Jul 2007
Dec 8th, 2007
0

Re: The fastest combination generator

Does the problem resolved ? Can you describe what you're doing ? Generate C(N,1..N/2) ?
wwx
Reputation Points: 10
Solved Threads: 0
Newbie Poster
wwx is offline Offline
2 posts
since Dec 2007
Dec 9th, 2007
0

Re: The fastest combination generator

It is an NP complete problem , so you can only get some approximation algorithm to get it faster.
Reputation Points: 769
Solved Threads: 128
Banned
ithelp is offline Offline
1,910 posts
since May 2006
Message:
Previous Thread in Computer Science Forum Timeline: How to know what to do?
Next Thread in Computer Science Forum Timeline: Question... About a question?





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC