1
/* Tyler R. Richard
2
   10/21/10
3
   This program uses sets to determine all the candidate keys and
4
   all non trivial closures of a given a list of
5
   single letter attributes and a set of functional dependences.
6
TODO:
7
-make it find canonical covers
8
  */
9
#include <iostream>
10
#include <cmath>
11
#include <algorithm>
12
#include <vector>
13
#include <string>
14
#include <map>
15
#include <set>
16
17
using namespace std;
18
19
set<char> setize(string data) {
20
	set<char> retval;
21
	for(int i = 0; i < data.size(); i++) {
22
		retval.insert(data[i]);
23
	}
24
	return retval;
25
}
26
27
int comp(set<char> a, set<char> b) {
28
	if(a.size() == b.size()) {
29
		return(a < b);
30
	}else{
31
		return(a.size() < b.size());
32
	}
33
}
34
35
string printSet(set<char> data) {
36
	string retval;
37
	for(set<char>::iterator p = data.begin(); p != data.end(); p++) {
38
	     retval += *p;
39
	}
40
	return(retval);
41
}
42
43
int main() {
44
	set<char> full_set;
45
	string determinant, product;
46
	map<set<char>,set<char> > F;
47
	map<set<char>,set<char> >::iterator it;
48
	cin >> determinant;
49
	full_set = setize(determinant);
50
	int n;
51
	cin >> n;
52
	// read in the functionality det pairs in
53
	for(int i =0; i < n; i++) {
54
		cin >> determinant >> product >> product;
55
		set<char> dets = setize(determinant);
56
		set<char> prods = setize(product);
57
		F[dets].insert(prods.begin(), prods.end());
58
	}
59
	// create a list of possible inputs
60
	unsigned int bitmask = 0;
61
	vector<char> v;
62
	vector<set<char> > possible_keys;
63
64
	for(set<char>::iterator i = full_set.begin(); i != full_set.end(); i++) {
65
		v.push_back(*i);
66
	}
67
	// assume # of attributes < 32
68
	while(bitmask <= 1<<v.size()){
69
		bitmask++;
70
		unsigned int index = 1;
71
		set<char> dets;
72
		for(int i = 0; i < v.size(); i++ ) {
73
			if(index & bitmask) {
74
				dets.insert(v[i]);
75
			}
76
			index = index << 1;
77
		}
78
		possible_keys.push_back(dets);
79
	}
80
	sort(possible_keys.begin(), possible_keys.end(),comp);
81
	vector<set<char> > found_keys;
82
	for(int i = 0; i < possible_keys.size(); i++) {
83
		//cout << printSet(possible_keys[i]);
84
		set<char> dets = possible_keys[i];
85
		bool cont = true;
86
		for(int j =0 ; j < found_keys.size(); j++) {
87
			if(includes( 
88
					dets.begin(), dets.end(),
89
					found_keys[j].begin(), found_keys[j].end())
90
			  ){
91
				//this key is a super set of a key we've already discovered
92
				cont = false;
93
				break;
94
			}
95
		}
96
		if(!cont){
97
			continue;
98
		}
99
		bool changes = true;
100
		while(changes && dets.size() != full_set.size()) {
101
			changes = false;
102
			for(it = F.begin();it != F.end() && dets.size() != full_set.size()
103
					; it++) {
104
				if(includes(dets.begin(), dets.end(),
105
						it->first.begin(),it->first.end()) &&
106
						!includes(dets.begin(), dets.end(),
107
							it->second.begin(), it->second.end())){
108
//					cout << it->first.size() << " " << dets.size() << endl;
109
					dets.insert(it->second.begin(),it->second.end());
110
					changes = true;
111
				}
112
			}
113
		}
114
		/* Print the keys that the given det can get to
115
		for(set<char>::iterator p=dets.begin(); p != dets.end(); p++) {
116
			cout << *p;
117
		}
118
		*/
119
120
		cout << printSet(possible_keys[i]);
121
		cout << " = ";
122
		cout << printSet(dets);
123
		if(dets.size() == full_set.size()) {
124
			found_keys.push_back(possible_keys[i]);
125
			cout << " is a candidate key!";
126
		}
127
		cout << endl;
128
	}	
129
}