diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 735b473..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml new file mode 100644 index 0000000..314740c --- /dev/null +++ b/.github/workflows/wheels.yml @@ -0,0 +1,66 @@ +name: CI + +# Run manually +on: workflow_dispatch + +jobs: + build_wheels: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-20.04, macos-10.15] + + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.8' + + - name: Get deps (macOS) + if: matrix.os == 'macos-10.15' + run: | + brew install boost + brew install gmp + brew install tbb + brew install wiredtiger + + - name: Build wheels + uses: pypa/cibuildwheel@v2.2.2 + # to supply options, put them in 'env', like: + env: + CIBW_ARCHS_LINUX: x86_64 + CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_24 + CIBW_SKIP: "*-musllinux_x86_64" + CIBW_BEFORE_ALL_LINUX: > + apt-get update -y && + apt-get install -y libboost-all-dev && + apt-get install -y libgmp-dev && + apt-get install -y libgmp10 && + apt-get install -y ocl-icd-opencl-dev && + apt-get install -y libtbb-dev && + apt-get install -y wiredtiger + + - uses: actions/upload-artifact@v2 + with: + path: ./wheelhouse/*.whl + + build_sdist: + name: Build source distribution + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/setup-python@v2 + name: Install Python + with: + python-version: '3.8' + + - name: Build sdist + run: python setup.py sdist + + - uses: actions/upload-artifact@v2 + with: + path: dist/*.tar.gz diff --git a/.gitignore b/.gitignore index 5d2ab33..16b7ca4 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,6 @@ m4 libtool .deps gosdt -gosdt_test \ No newline at end of file +gosdt_test +*.DS_Store +wheelhouse/* diff --git a/Makefile.in b/Makefile.in index bde012d..f155cf9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. +# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -264,15 +264,12 @@ am__define_uniq_tagged_files = \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags -CSCOPE = cscope AM_RECURSIVE_TARGETS = cscope am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/build/compile \ $(top_srcdir)/build/config.guess \ $(top_srcdir)/build/config.sub $(top_srcdir)/build/depcomp \ $(top_srcdir)/build/install-sh $(top_srcdir)/build/missing \ - build/compile build/config.guess build/config.sub \ + README.md build/compile build/config.guess build/config.sub \ build/depcomp build/install-sh build/missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) @@ -287,6 +284,8 @@ am__post_remove_distdir = $(am__remove_distdir) DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip +# Exists only to be overridden by the user if desired. +AM_DISTCHECK_DVI_TARGET = dvi distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' @@ -307,6 +306,8 @@ CL_CFLAGS = @CL_CFLAGS@ CL_LIBS = @CL_LIBS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ CXX = @CXX@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ @@ -319,6 +320,7 @@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ +ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ GREP = @GREP@ HAVE_CXX11 = @HAVE_CXX11@ @@ -395,6 +397,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -1248,7 +1251,6 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files - distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am @@ -1307,6 +1309,10 @@ dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) +dist-zstd: distdir + tardir=$(distdir) && $(am__tar) | zstd -c $${ZSTD_CLEVEL-$${ZSTD_OPT--19}} >$(distdir).tar.zst + $(am__post_remove_distdir) + dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @@ -1349,6 +1355,8 @@ distcheck: dist eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ + *.tar.zst*) \ + zstd -dc $(distdir).tar.zst | $(am__untar) ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) @@ -1364,7 +1372,7 @@ distcheck: dist $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ - && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) $(AM_DISTCHECK_DVI_TARGET) \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ @@ -1596,17 +1604,18 @@ uninstall-am: uninstall-binPROGRAMS check-am clean clean-binPROGRAMS clean-cscope clean-generic \ cscope cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-lzip dist-shar dist-tarZ dist-xz dist-zip \ - distcheck distclean distclean-compile distclean-generic \ - distclean-tags distcleancheck distdir distuninstallcheck dvi \ - dvi-am html html-am info info-am install install-am \ - install-binPROGRAMS install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am uninstall-binPROGRAMS + dist-zstd distcheck distclean distclean-compile \ + distclean-generic distclean-tags distcleancheck distdir \ + distuninstallcheck dvi dvi-am html html-am info info-am \ + install install-am install-binPROGRAMS install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am uninstall-binPROGRAMS .PRECIOUS: Makefile diff --git a/README.md b/README.md index 9d15f5d..87c12e3 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Currently supported as a Python extension. ## Installing Dependencies Refer to [**Dependency Installation**](/doc/dependencies.md##Installation) -## As a Stand-Alone Command Line Program +## Stand-Alone Command Line Program ### Installation ``` ./autobuild --install @@ -38,15 +38,19 @@ For examples of dataset files, refer to `experiments/datasets/compas/binned.csv` For an example configuration file, refer to `experiments/configurations/compas.json`. For documentation on the configuration file, refer to [**Dependency Installation**](/doc/configuration.md) -## As a Python Library with C++ Extensions -### Build and Installation +## Python-wrapped C++ Extension +### Installation +#### x86 Linux or macOS +``` +pip install gosdt-deprecated +``` +#### Other platforms ``` ./autobuild --install-python ``` _If you have multiple Python installations, please make sure to build and install using the same Python installation as the one intended for interacting with this library._ - -### Importing the C++ Extension +### C++ extension example usage ```python import gosdt @@ -56,7 +60,6 @@ with open ("data.csv", "r") as data_file: with open ("config.json", "r") as config_file: config = config_file.read() - print("Config:", config) print("Data:", data) @@ -69,7 +72,9 @@ print("Iterations: ", gosdt.iterations()) print("Graph Size: ", gosdt.size()) ``` -### Importing Extension with local Python Wrapper +### With local Python wrapper +This module is local and not packaged; the following example assumes the user is working in the directory `GeneralizedOptimalSparseDecisionTrees/python`. + ```python import pandas as pd import numpy as np @@ -96,6 +101,36 @@ print("Training Accuracy: {}".format(training_accuracy)) print(model.tree) ``` +## Scikit-learn-style Python module +This option is currently only supported on x86-running Linux or macOS platforms. + +### Installation +``` +pip install imodels +``` +_[imodels](https://github.com/csinva/imodels) is an interpretable machine learning package containing gosdt among many others ._ + +### Usage +```python +import pandas as pd +import numpy as np +from imodels import GOSDTClassifier + +dataframe = pd.DataFrame(pd.read_csv("experiments/datasets/monk_2/data.csv")) + +X = dataframe[dataframe.columns[:-1]] +y = dataframe[dataframe.columns[-1:]] + +model = GOSDT(regularization=0.1, time_limit=3600, verbose=True) +model.fit(X, y) +print("Execution Time: {}".format(model.time)) + +prediction = model.predict(X) +training_accuracy = model.score(X, y) +print("Training Accuracy: {}".format(training_accuracy)) +print(model.tree) +``` + --- # Development @@ -148,6 +183,9 @@ Refer to [**Dependency Installation**](/doc/dependencies.md##Installation) ``` For a full list of build options, run `./autobuild --help` +### Building wheels for distribution (C++ extension) +Invoking `.github/workflows/wheels.yml` via Github Actions will output wheels for x86 Linux and macOS platforms using [cibuildwheel](https://github.com/pypa/cibuildwheel), as well as the source distribution. + --- # Configuration diff --git a/license.md b/license.md new file mode 100644 index 0000000..96f1555 --- /dev/null +++ b/license.md @@ -0,0 +1,19 @@ +Copyright (c) 2018 The Python Packaging Authority + +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. diff --git a/python/requirements.txt b/python/requirements.txt new file mode 100644 index 0000000..c8fdae7 --- /dev/null +++ b/python/requirements.txt @@ -0,0 +1,6 @@ +gmpy2 +matplotlib +numpy +pandas +sklearn +sortedcontainers diff --git a/python/test_installation.ipynb b/python/test_installation.ipynb new file mode 100644 index 0000000..90c576b --- /dev/null +++ b/python/test_installation.ipynb @@ -0,0 +1,208 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "from sklearn import model_selection\n", + "from model.gosdt import GOSDT" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "dataframe = pd.DataFrame(pd.read_csv(\"../experiments/datasets/compas/binned.csv\"))\n", + "\n", + "X = dataframe[dataframe.columns[:-1]]\n", + "y = dataframe[dataframe.columns[-1:]]\n", + "\n", + "hyperparameters = {\n", + " \"regularization\": 0.002,\n", + " \"time_limit\": 30,\n", + " \"verbose\": True,\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Using configuration: {\n", + " \"balance\": false,\n", + " \"cancellation\": true,\n", + " \"continuous_feature_exchange\": true,\n", + " \"costs\": \"\",\n", + " \"diagnostics\": false,\n", + " \"feature_exchange\": true,\n", + " \"feature_transform\": true,\n", + " \"look_ahead\": true,\n", + " \"model\": \"\",\n", + " \"model_limit\": 1,\n", + " \"non_binary\": false,\n", + " \"precision_limit\": 0,\n", + " \"profile\": \"\",\n", + " \"regularization\": 0.0020000000949949026,\n", + " \"rule_list\": false,\n", + " \"similar_support\": true,\n", + " \"stack_limit\": 0,\n", + " \"time_limit\": 30,\n", + " \"timing\": \"\",\n", + " \"trace\": \"\",\n", + " \"tree\": \"\",\n", + " \"uncertainty_tolerance\": 0.0,\n", + " \"upperbound\": 0.0,\n", + " \"verbose\": true,\n", + " \"worker_limit\": 1\n", + "}\n", + "Initializing Optimization Framework\n", + "Feature Index: 0, Feature Name: sex:Female\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 1, Feature Name: age:<21\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 2, Feature Name: age:<23\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 3, Feature Name: age:<26\n", + " Inferred Type: Binary, EmpirExecution Time: 0.5170000195503235ical Cardinality: 2, Optionality: 0\n", + "Feature Index: 4, Feature Name: age:<46\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 5, Feature Name: juvenile-felonies:=0\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 6, Feature Name: juvenile-misdemeanors:=0\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 7, Feature Name: juvenile-crimes:=0\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 8, Feature Name: priors:=0\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 9, Feature Name: priors:=1\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 10, Feature Name: priors:2-3\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 11, Feature Name: priors:>3\n", + " Inferred Type: Binary, Empirical Cardinality: 2, Optionality: 0\n", + "Feature Index: 12, Feature Name: class\n", + " Inferred Type: Categori\n", + "cal, Empirical Cardinality: 2, Optionality: 0\n", + "Original Dataset Dimension: 5180 x 13\n", + "Binary Dataset Dimension: 5180 x 14\n", + "Dataset Dimensions: 5180 x 12 x 2\n", + "Starting Optimization\n", + "Time: 0.000628064, Objective: [0.331483, 0.368865], Boundary: 0.0373822, Graph Size: 1, Queue Size: 24\n", + "Time: 0.458125, Objective: [0.332517, 0.345205], Boundary: 0.0126873, Graph Size: 2929, Queue Size: 980\n", + "Time: 0.460212, Objective: [0.332517, 0.344942], Boundary: 0.0124247, Graph Size: 2942, Queue Size: 930\n", + "Time: 0.4859, Objective: [0.332517, 0.344942], Boundary: 0.0124247, Graph Size: 3048, Queue Size: 345\n", + "Time: 0.514859, Objective: [0.332517, 0.344556], Boundary: 0.0120386, Graph Size: 3056, Queue Size: 34\n", + "Time: 0.516563, Objective: [0.335027, 0.344556], Boundary: 0.00952891, Graph Size: 3056, Queue Size: 21\n", + "Time: 0.516671, Objective: [0.336834, 0.344556], Boundary: 0.00772202, Graph Size: 3056, Queue Size: 20\n", + "Time: 0.51673, Objective: [0.337992, 0.344556], Boundary: 0.00656369, Graph Size: 3056, Queue Size: 19\n", + "Time: 0.517043, Objective: [0.338062, 0.344556], Boundary: 0.00649422, Graph Size: 3056, Queue Size: 18\n", + "Time: 0.517444, Objective: [0.338309, 0.344556], Boundary: 0.0062471, Graph Size: 3056, Queue Size: 10\n", + "Time: 0.517524, Objective: [0.344556, 0.344556], Boundary: 0, Graph Size: 3056, Queue Size: 10\n", + "Optimization Complete\n", + "Training Duration: 0.517 seconds\n", + "Number of Iterations: 11746 iterations\n", + "Size of Graph: 3056 nodes\n", + "Objective Boundary: [0.344556, 0.344556]\n", + "Optimality Gap: 0\n", + "Models Generated: 1\n", + "Loss: 0.334556\n", + "Complexity: 0.01\n" + ] + } + ], + "source": [ + "model = GOSDT(hyperparameters)\n", + "model.fit(X_train, y_train)\n", + "print(\"Execution Time: {}\".format(model.time))" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training Accuracy: 0.6797915460335843\n", + "if priors:>3 = 1 then:\n", + " predicted class: 1\n", + " misclassification penalty: 0.104\n", + " complexity penalty: 0.002\n", + "\n", + "else if age:<26 = 1 and juvenile-crimes:=0 = 1 and priors:2-3 = 1 and priors:>3 != 1 then:\n", + " predicted class: 1\n", + " misclassification penalty: 0.018\n", + " complexity penalty: 0.002\n", + "\n", + "else if age:<26 = 1 and juvenile-crimes:=0 = 1 and priors:2-3 != 1 and priors:>3 != 1 then:\n", + " predicted class: 0\n", + " misclassification penalty: 0.066\n", + " complexity penalty: 0.002\n", + "\n", + "else if age:<26 = 1 and juvenile-crimes:=0 != 1 and priors:>3 != 1 then:\n", + " predicted class: 1\n", + " misclassification penalty: 0.018\n", + " complexity penalty: 0.002\n", + "\n", + "else if age:<26 != 1 and priors:>3 != 1 then:\n", + " predicted class: 0\n", + " misclassification penalty: 0.129\n", + " complexity penalty: 0.002\n" + ] + } + ], + "source": [ + "prediction = model.predict(X_test)\n", + "training_accuracy = model.score(X_test, y_test)\n", + "print(\"Training Accuracy: {}\".format(training_accuracy))\n", + "print(model.tree)" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "88b44fd289801b8ea4f2ff653147c326007f4497d2047b559f97683ce23a45c5" + }, + "kernelspec": { + "display_name": "Python 3.9.7 64-bit ('gosdt': conda)", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/setup.py b/setup.py index bb95824..c19b719 100644 --- a/setup.py +++ b/setup.py @@ -1,8 +1,9 @@ -from distutils.core import setup, Extension import glob -import sys import os import platform +import setuptools +from distutils.core import Extension + # This script is used to build and/or install the trainer into as Python extension. # To build the extention, run: python python/extension/setup.py build @@ -36,7 +37,7 @@ LINK_ARGS = OPTIMIZATION + STD + INCLUDES + STDLIB + TBB_LIBS + CL_LIBS + GMP_LIBS module = Extension( - name='gosdt', + name="gosdt", # sources=['src/python_extension.cpp'], sources=[obj for obj in glob.glob('src/*.cpp')], language='c++', @@ -45,8 +46,19 @@ extra_objects=[obj for obj in glob.glob('src/*.o')] ) -setup( - name='gosdt', - version='0.1.1', - ext_modules=[module] +setuptools.setup( + name="gosdt-deprecated", + version="0.0.1", + author="Jimmy Lin, Chudi Zhong, and others", + author_email="jimmy.projects.lin@gmail.com", + description="C++ implementation of Generalized Optimal Sparse Decision Trees", + ext_modules=[module], + url="https://github.com/Jimmy-Lin/GeneralizedOptimalSparseDecisionTrees", + python_requires='>=3.6', + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: MacOS", + "Operating System :: POSIX :: Linux", + ], ) diff --git a/src/queue.hpp b/src/queue.hpp index e626c1a..12d9d9d 100644 --- a/src/queue.hpp +++ b/src/queue.hpp @@ -47,7 +47,7 @@ typedef tbb::concurrent_priority_queue< message_type *, PriorityKeyComparator, tbb::scalable_allocator< message_type * > > queue_type; typedef tbb::concurrent_hash_map< message_type *, bool, MembershipKeyHashCompare, - tbb::scalable_allocator>> membership_table_type; + tbb::scalable_allocator>> membership_table_type; class Queue { public: