Constraint programming is a nice approach if you want to generate all the combinations. Just to try it out, I wrote a model using Gecode (version 3.2.2) to solve your problem. The two examples given are very easy to solve, but other instances might be harder. It should be better than generate and test in any case.
/*
* Main authors:
* Mikael Zayenz Lagerkvist <[email protected]>
*
* Copyright:
* Mikael Zayenz Lagerkvist, 2009
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <gecode/driver.hh>
#include <gecode/int.hh>
#include <gecode/minimodel.hh>
using namespace Gecode;
namespace {
/// List of specifications
extern const int* specs[];
/// Number of specifications
extern const unsigned int n_specs;
}
/**
* \brief Selecting pairs
*
* Given a set of lists of pairs of values, select a pair from each
* list so that no value is selected more than once.
*
*/
class SelectPairs : public Script {
protected:
/// Specification
const int* spec;
/// The values from all selected pairs
IntVarArray s;
public:
/// The actual problem
SelectPairs(const SizeOptions& opt)
: spec(specs[opt.size()]),
s(*this,spec[0] * 2,Int::Limits::min, Int::Limits::max) {
int pos = 1; // Position read from spec
// For all lists
for (int i = 0; i < spec[0]; ++i) {
int npairs = spec[pos++];
// Construct TupleSet for pairs from list i
TupleSet ts;
for (int p = 0; p < npairs; ++p) {
IntArgs tuple(2);
tuple[0] = spec[pos++];
tuple[1] = spec[pos++];
ts.add(tuple);
}
ts.finalize();
// <s[2i],s[2i+1]> must be from list i
IntVarArgs pair(2);
pair[0] = s[2*i]; pair[1] = s[2*i + 1];
extensional(*this, pair, ts);
}
// All values must be pairwise distinct
distinct(*this, s, opt.icl());
// Select values for the variables
branch(*this, s, INT_VAR_SIZE_MIN, INT_VAL_MIN);
}
/// Constructor for cloning \a s
SelectPairs(bool share, SelectPairs& sp)
: Script(share,sp), spec(sp.spec) {
s.update(*this, share, sp.s);
}
/// Perform copying during cloning
virtual Space*
copy(bool share) {
return new SelectPairs(share,*this);
}
/// Print solution
virtual void
print(std::ostream& os) const {
os << "\t";
for (int i = 0; i < spec[0]; ++i) {
os << "(" << s[2*i] << "," << s[2*i+1] << ") ";
if ((i+1) % 10 == 0)
os << std::endl << "\t";
}
if (spec[0] % 10)
os << std::endl;
}
};
/** \brief Main-function
* \relates SelectPairs
*/
int
main(int argc, char* argv[]) {
SizeOptions opt("SelectPairs");
opt.iterations(500);
opt.size(0);
opt.parse(argc,argv);
if (opt.size() >= n_specs) {
std::cerr << "Error: size must be between 0 and "
<< n_specs-1 << std::endl;
return 1;
}
Script::run<SelectPairs,DFS,SizeOptions>(opt);
return 0;
}
namespace {
const int s0[] = {
// Number of lists
3,
// Lists (number of pairs, pair0, pair1, ...)
5, 1,2, 1,3, 1,4, 2,3, 2,4,
3, 1,4, 1,5, 2,5,
5, 1,6, 1,7, 2,5, 2,6, 3,6
};
const int s1[] = {
// Number of lists
3,
// Lists (number of pairs, pair0, pair1, ...)
5, 1,2, 2,3, 3,4, 4,5, 6,7,
5, 1,2, 2,3, 3,4, 4,5, 6,7,
5, 1,2, 2,3, 3,4, 4,5, 6,7
};
const int *specs[] = {s0, s1};
const unsigned n_specs = sizeof(specs)/sizeof(int*);
}