[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