/* Formal Concept Analysis based on Ganter Wyle's Book. See http://www.jfsowa.com/pubs/autotalk.htm#s10 for a quick introduction and example proving that beer is champagne. */ #include #include #include #include template class FormalContext{ set o;//objects set a;//attributes public: typedef set< pair > Relation; private: typedef map< Object, set > O2A; O2A o2a; typedef map< Attribute, set > A2O; A2O a2o; //- inv. o is the domain of o2a and the image of a2o //- inv. a is the domain of a2o and the image of o2a //- inv. for all x:o, x is a member( o2a(a2o(x))) //- inv. for all y:a, y is a member( a2o(a2o(y))) public: FormalContext(Relation r); set objects(){return o;} set objects(Attribute y){return a2o[y];} set attributes(){return a;} set attributes(Object x){return o2a[x];} set common_attributes(Object x){return o2a[x];} set common_attributes(set x); set common_objects(Attribute y){return a2o[y];} set common_objects(set y); set close_object(Object s) { return common_objects(common_attributes(s));} set close_object(set s) { return common_objects(common_attributes(s));} set close_attribute(Attribute s) { return common_attributes(common_objects(s));} set close_attribute(set s) { return common_attributes(common_objects(s));} }; template FormalContext::FormalContext(FormalContext::Relation r) { for(FormalContext::Relation::iterator p=r.begin(); p!=r.end(); ++p) { o.insert(p->first); a.insert(p->second); o2a[p->first].insert(p->second); a2o[p->second].insert(p->first); } } template set FormalContext::common_attributes(set x) { if(x.empty()) return attributes(); //else... set::iterator p=x.begin(); set::iterator xe=x.end(); set temp(o2a[*p]); set result(temp); set next; for( ++p; p!=xe; ++p) { temp=o2a[*p]; set_intersection (result.begin(),result.end(), temp.begin(), temp.end(), inserter(next, next.begin()) ); result=next; } return result; } template set FormalContext::common_objects(set y) { if(y.empty()) return objects(); //else set::iterator p=y.begin(); set temp(a2o[*p]); set result(temp); set next; for( ++p, temp=a2o[*p]; p!=y.end(); ++p) { set_intersection (result.begin(),result.end(), temp.begin(), temp.end(), inserter(next, next.begin()) ); result=next; } return result; } template void prin(set s) { cout <<"{ "; copy (s.begin(), s.end(), ostream_iterator(cout, " ")); cout << "}"; } template void print(set s) { prin(s); cout << endl; } int main() { typedef FormalContext FC; FC::Relation r; r.insert(make_pair(1,'a')); r.insert(make_pair(1,'b')); r.insert(make_pair(2,'b')); r.insert(make_pair(2,'c')); r.insert(make_pair(3,'a')); // r.insert(make_pair(4,'a')); // r.insert(make_pair(4,'c')); FC sample(r); print(sample.objects()); { set nullc; set s0 = sample.common_objects(nullc); print(s0); } print(sample.attributes()); { set nulli; set s0 = sample.common_attributes(nulli); print(s0); } set s1 = sample.common_attributes(1); print(s1); set s2 = sample.common_objects('b'); print(s2); set s3 = sample.common_objects(s1); print(s3); set s4 = sample.common_attributes(s3); print(s4); set s5 = sample.common_objects(sample.common_attributes(2)); print(s5); set s6 = sample.close_object(3); print(s6); set s7 = sample.close_attribute('a'); print(s7); set ca; set os=sample.objects(); set::iterator oe = os.end(); for(set::iterator i=os.begin(); i!=oe; ++i) { cout << *i << " : "; ca = sample.common_attributes(*i); prin(ca); cout << " - "; prin(sample.common_objects(ca)); cout << endl; } }