[Aptitude-svn-commit] r3989 - in branches/aptitude-0.3/aptitude: .
src/generic tests
Daniel Burrows
dburrows at costa.debian.org
Tue Aug 30 01:40:13 UTC 2005
Author: dburrows
Date: Tue Aug 30 01:40:10 2005
New Revision: 3989
Added:
branches/aptitude-0.3/aptitude/src/generic/setset.h
branches/aptitude-0.3/aptitude/tests/test_setset.cc
Modified:
branches/aptitude-0.3/aptitude/ChangeLog
branches/aptitude-0.3/aptitude/tests/Makefile.am
Log:
Add a class that efficiently implements a set-of-sets with fast subset searches.
Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog (original)
+++ branches/aptitude-0.3/aptitude/ChangeLog Tue Aug 30 01:40:10 2005
@@ -1,5 +1,11 @@
2005-08-29 Daniel Burrows <dburrows at debian.org>
+ * src/generic/setset.h, tests/test_setset.cc:
+
+ Add a data structure that stores a set of sets, optimized for
+ searching for a superset or a subset of a given set without
+ using imm::set's slow operator++.
+
* src/generic/immset.h:
Add missing const qualifier on wtree_node::for_each.
Added: branches/aptitude-0.3/aptitude/src/generic/setset.h
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/generic/setset.h Tue Aug 30 01:40:10 2005
@@ -0,0 +1,164 @@
+// setset.h -*-c++-*-
+//
+// Copyright (C) 2005 Daniel Burrows
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+//
+// Efficient representation of sets-of-sets and sets-of-maps which can
+// be indexed by a subset/superset relation. In particular, given a
+// set of sets SS and a set T, provides the operation "is there an
+// element S' of SS such that each element of S' stands in a relation
+// R to an equivalent element of T" as well as its dual. (with R
+// being the universal relation, this is just a straight subset
+// relation, but other general types of subsumption are also posible)
+
+#ifndef SETSET_H
+#define SETSET_H
+
+#include <map>
+#include <set>
+#include <vector>
+#include "immset.h"
+
+/** Maintains a set of imm::sets of Val objects, arranged so that
+ * quick answers to the query "does the set S subsume any element of
+ * this set?" can be produced. At the moment this object increases
+ * monotonically, to keep things simple.
+ */
+template<typename Val, typename Compare = std::less<Val> >
+class setset
+{
+public:
+ typedef typename std::vector<imm::set<Val, Compare> >::const_iterator const_iterator;
+
+private:
+ std::vector<imm::set<Val, Compare> > entries;
+
+ typedef std::vector<imm::set<Val, Compare> > entries_list;
+
+ typedef std::map<Val, std::set<typename entries_list::size_type> > index_type;
+
+ index_type sets_by_key;
+
+
+
+ // Used to construct a set traversal that populates the sets_by_key
+ // structure.
+ struct populate_sets_by_key
+ {
+ const typename entries_list::size_type index;
+
+ index_type &sets_by_key;
+ public:
+ populate_sets_by_key(index_type &_sets_by_key,
+ typename entries_list::size_type _index)
+ :index(_index), sets_by_key(_sets_by_key)
+ {
+ }
+
+ void operator()(const Val &v) const
+ {
+ sets_by_key[v].insert(index);
+ }
+ };
+
+ // Used by find_subset to tally up intersections.
+ struct tally_intersections
+ {
+ std::map<typename entries_list::size_type, unsigned int> &counts;
+
+ const index_type &sets_by_key;
+ public:
+ tally_intersections(std::map<typename entries_list::size_type, unsigned int> &_counts,
+ const index_type &_sets_by_key)
+ :counts(_counts), sets_by_key(_sets_by_key)
+ {
+ }
+
+ // For each set containing v, add 1 to its tally in counts.
+ void operator()(const Val &v) const
+ {
+ typename index_type::const_iterator found
+ = sets_by_key.find(v);
+
+ if(found != sets_by_key.end())
+ {
+ const std::set<typename entries_list::size_type> &vals = found->second;
+
+ for(typename std::set<typename entries_list::size_type>::const_iterator vi
+ = vals.begin(); vi != vals.end(); ++vi)
+ {
+ typename std::map<typename entries_list::size_type, unsigned int>::iterator found
+ = counts.find(*vi);
+
+ if(found == counts.end())
+ counts[*vi] = 1;
+ else
+ ++found->second;
+ }
+ }
+ }
+ };
+
+public:
+ setset(const Compare &c = Compare())
+ :sets_by_key(c)
+ {
+ }
+
+ const_iterator begin() const
+ {
+ return entries.begin();
+ }
+
+ const_iterator end() const
+ {
+ return entries.end();
+ }
+
+ /** Add a new set into this set. */
+ void insert(const imm::set<Val, Compare> &s)
+ {
+ typename entries_list::size_type index = entries.size();
+
+ entries.push_back(s);
+ s.for_each(populate_sets_by_key(sets_by_key, index));
+ }
+
+ /** Find an arbitrary element that is a subset of s. */
+ const_iterator find_subset(const imm::set<Val, Compare> &s) const
+ {
+ // For each element that intersects s, count how many times it
+ // intersects. If every element of a set intersects s (i.e., the
+ // count is equal to the set's size) then it is a subset of s.
+ std::map<typename entries_list::size_type, unsigned int> counts;
+ s.for_each(tally_intersections(counts, sets_by_key));
+
+ for(typename std::map<typename entries_list::size_type, unsigned int>::const_iterator ci
+ = counts.begin(); ci != counts.end(); ++ci)
+ {
+ typename entries_list::const_iterator found = entries.begin()+ci->first;
+
+ if(found->size() == ci->second)
+ return found;
+ }
+
+ return end();
+ }
+};
+
+#endif // SETSET_H
+
Modified: branches/aptitude-0.3/aptitude/tests/Makefile.am
==============================================================================
--- branches/aptitude-0.3/aptitude/tests/Makefile.am (original)
+++ branches/aptitude-0.3/aptitude/tests/Makefile.am Tue Aug 30 01:40:10 2005
@@ -16,5 +16,6 @@
main.cc \
test_misc.cc \
test_resolver.cc \
+ test_setset.cc \
test_tags.cc \
test_wtree.cc
Added: branches/aptitude-0.3/aptitude/tests/test_setset.cc
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/tests/test_setset.cc Tue Aug 30 01:40:10 2005
@@ -0,0 +1,92 @@
+// test_setset.cc
+//
+// Copyright (C) 2005 Daniel Burrows
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; see the file COPYING. If not, write to
+// the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <src/generic/setset.h>
+
+template<typename T>
+inline
+std::ostream &operator<<(std::ostream &out, const imm::set<T> &s)
+{
+ out << "{";
+
+ for(typename imm::set<T>::const_iterator i = s.begin(); i != s.end(); ++i)
+ {
+ if(i != s.begin())
+ out << ", ";
+ out << *i;
+ }
+
+ out << "}";
+
+ return out;
+}
+
+class SetSetTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(SetSetTest);
+
+ CPPUNIT_TEST(testSubsetSearch);
+
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ // Test searching for subsets of a set.
+ void testSubsetSearch()
+ {
+ imm::set<int> s1, s2, s3;
+
+ s1.insert(1);
+ s1.insert(2);
+ s1.insert(5);
+
+ s2.insert(5);
+
+ s3.insert(4);
+ s3.insert(5);
+
+ setset<int> S;
+
+ S.insert(s1);
+ S.insert(s2);
+ S.insert(s3);
+
+ imm::set<int> t;
+
+ t.insert(1);
+
+ setset<int>::const_iterator found = S.find_subset(t);
+ CPPUNIT_ASSERT(found == S.end());
+
+ t.insert(5);
+
+ found = S.find_subset(t);
+ CPPUNIT_ASSERT(found != S.end());
+ CPPUNIT_ASSERT_EQUAL(*found, s2);
+
+ t.insert(6);
+ t.insert(4);
+ t.insert(3);
+
+ CPPUNIT_ASSERT(S.find_subset(t) != S.end());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(SetSetTest);
More information about the Aptitude-svn-commit
mailing list