From 050b51f7cfad9bd0b629737e2d5ae4bbb93b463b Mon Sep 17 00:00:00 2001 From: Daniel Mahler Date: Thu, 9 Sep 2021 20:13:23 -0500 Subject: [PATCH 1/9] refactor and optimize BinaryPolynomial.__init__ --- dimod/higherorder/polynomial.py | 49 +++++++++++++++++++-------------- requirements.txt | 1 + 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/dimod/higherorder/polynomial.py b/dimod/higherorder/polynomial.py index 251b699b4..77a588cca 100644 --- a/dimod/higherorder/polynomial.py +++ b/dimod/higherorder/polynomial.py @@ -16,11 +16,14 @@ import itertools import collections.abc as abc +from collections import defaultdict from numbers import Number import numpy as np +import cytoolz as tl + from dimod.decorators import vartype_argument from dimod.sampleset import as_samples from dimod.utilities import iter_safe_relabels @@ -34,6 +37,25 @@ def asfrozenset(term): return term if isinstance(term, frozenset) else frozenset(term) +is_odd = tl.flip(tl.curried.operator.mod)(2) +second_is_odd = tl.compose(is_odd, tl.second) + +def freeze_term(term, vartype): + return ( + term + if isinstance(term, frozenset) + else ( + frozenset(term) + if vartype is Vartype.BINARY + else frozenset( + map( + tl.first, + filter(second_is_odd, tl.frequencies(term).items()) + ) + ) + ) + ) + class BinaryPolynomial(abc.MutableMapping): """A polynomial with binary variables and real-valued coefficients. @@ -92,26 +114,11 @@ def __init__(self, poly, vartype): poly = poly.items() # we need to aggregate the repeated terms - self._terms = terms = {} - for term, bias in poly: - - fsterm = asfrozenset(term) - - # when SPIN-valued, s^2 == 1, so we need to handle that case - # in BINARY, x^2 == x - if len(fsterm) < len(term) and vartype is Vartype.SPIN: - new = set() - term = tuple(term) # make sure it has .count - for v in fsterm: - if term.count(v) % 2: - new.add(v) - fsterm = frozenset(new) - - if fsterm in terms: - terms[fsterm] += bias - else: - terms[fsterm] = bias + self._terms = terms = defaultdict(int) + for term, bias in poly: + terms[freeze_term(term, vartype)] += bias + self.vartype = vartype def __contains__(self, term): @@ -127,10 +134,10 @@ def __eq__(self, other): except Exception: # not a polynomial return False - + self_terms = self._terms other_terms = other._terms - + return ( self.vartype == other.vartype and all( diff --git a/requirements.txt b/requirements.txt index 67bdf45cb..bb4c30b22 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,7 @@ numpy==1.19.4 cython==0.29.21 dwave-preprocessing==0.3.0 +cytoolz==0.11.0 reno==3.3.0 # for changelog From 0452df73dbac7bb4610959deb044033d3f007296 Mon Sep 17 00:00:00 2001 From: Daniel Mahler Date: Thu, 9 Sep 2021 21:25:27 -0500 Subject: [PATCH 2/9] (temporarily) adding notbook demnstrating >6x speedup with new __init__ method --- polynomial-perf.ipynb | 469 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 469 insertions(+) create mode 100644 polynomial-perf.ipynb diff --git a/polynomial-perf.ipynb b/polynomial-perf.ipynb new file mode 100644 index 000000000..4adccd02b --- /dev/null +++ b/polynomial-perf.ipynb @@ -0,0 +1,469 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "182a16c4-4777-4ec3-99b1-476914c2ec1b", + "metadata": {}, + "source": [ + "# Current" + ] + }, + { + "cell_type": "markdown", + "id": "11b1cb71-4f1b-441f-a6bf-93d430ac5356", + "metadata": { + "tags": [] + }, + "source": [ + "## Create test example" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "61901771-5a93-4cc9-a180-0cc2cc580a53", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b0d92f0d-3549-4619-a272-a324ef475104", + "metadata": {}, + "outputs": [], + "source": [ + "import string, random, toolz, pandas, importlib, sys, os" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d2c51a56-7617-427e-8ec5-12e4a0fc0a08", + "metadata": {}, + "outputs": [], + "source": [ + "terms = [(term, 1) for term in str(random.choices(string.ascii_letters, k=10**7)).split('Z')]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "1f8a40cc-df42-4f45-9220-afd1f212239f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "count 191557.000000\n", + "mean 260.018919\n", + "std 258.235286\n", + "min 4.000000\n", + "25% 74.000000\n", + "50% 179.000000\n", + "75% 359.000000\n", + "max 3084.000000\n", + "dtype: float64" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pandas.Series(len(term) for term, _ in terms).describe()" + ] + }, + { + "cell_type": "markdown", + "id": "ed7030e6-6d63-4f54-a8af-13e938191812", + "metadata": {}, + "source": [ + "## Run current version" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "bc701097-6aa9-44a1-8673-b2777e84e929", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Switched to branch 'main'\n", + "Your branch and 'upstream/main' have diverged,\n", + "and have 1 and 2 different commits each, respectively.\n", + " (use \"git pull\" to merge the remote branch into yours)\n" + ] + } + ], + "source": [ + "!git checkout main\n", + "#importlib.reload(dimod)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0dff8f12-ff29-4991-ad7c-8bb9d6367f5e", + "metadata": {}, + "outputs": [], + "source": [ + "from dimod import BinaryPolynomial as BPold" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "ec77f944-27b1-47ce-b141-2b8d6fc3f116", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[0;31mSignature:\u001b[0m \u001b[0mBPold\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mDocstring:\u001b[0m Initialize self. See help(type(self)) for accurate signature.\n", + "\u001b[0;31mSource:\u001b[0m \n", + " \u001b[0;34m@\u001b[0m\u001b[0mvartype_argument\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'vartype'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mabc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMapping\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mpoly\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;31m# we need to aggregate the repeated terms\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_terms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mterms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mfsterm\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0masfrozenset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;31m# when SPIN-valued, s^2 == 1, so we need to handle that case\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;31m# in BINARY, x^2 == x\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfsterm\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mVartype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSPIN\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mnew\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mterm\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# make sure it has .count\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mfsterm\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mterm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcount\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mnew\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mfsterm\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfrozenset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnew\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mfsterm\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mterms\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mterms\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mfsterm\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mterms\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mfsterm\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvartype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mFile:\u001b[0m ~/dimod/dimod/higherorder/polynomial.py\n", + "\u001b[0;31mType:\u001b[0m function\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "BPold.__init__??" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e4cfa0c6-b7d4-4642-82fb-9eba71ab340b", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + }, + { + "data": { + "text/plain": [ + " 9687489 function calls (9687409 primitive calls) in 28.809 seconds\n", + "\n", + " Ordered by: cumulative time\n", + " List reduced from 47 to 20 due to restriction <20>\n", + "\n", + " ncalls tottime percall cumtime percall filename:lineno(function)\n", + " 1 0.000 0.000 28.809 28.809 {built-in method builtins.exec}\n", + " 1 0.065 0.065 28.809 28.809 :1()\n", + " 1 0.000 0.000 28.743 28.743 decorators.py:289(new_f)\n", + " 1 2.587 2.587 28.743 28.743 polynomial.py:89(__init__)\n", + " 5468426 25.143 0.000 25.143 0.000 {method 'count' of 'tuple' objects}\n", + " 191557 0.649 0.000 0.677 0.000 polynomial.py:32(asfrozenset)\n", + " 3452632 0.297 0.000 0.297 0.000 {method 'add' of 'set' objects}\n", + " 383116 0.039 0.000 0.039 0.000 {built-in method builtins.len}\n", + " 191567 0.028 0.000 0.028 0.000 {built-in method builtins.isinstance}\n", + " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", + " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", + " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", + " 41/1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_subclasscheck}\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", + " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", + " 1 0.000 0.000 0.000 0.000 :1(__new__)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%prun -s cumtime -l 20 BPold(terms, 'SPIN')" + ] + }, + { + "cell_type": "markdown", + "id": "81473689-9ece-45a7-85a0-389d0418be3e", + "metadata": {}, + "source": [ + "# Exit interpreter\n", + "I just can'get module reloading to work properly here ..." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "673fe5b0-5934-4b40-a418-62122e867aa9", + "metadata": {}, + "outputs": [], + "source": [ + "## \n", + "exit()\n", + "#del BPold" + ] + }, + { + "cell_type": "markdown", + "id": "8d68e1c7-8d3c-40ae-acdd-360edccad297", + "metadata": {}, + "source": [ + "# Proposed" + ] + }, + { + "cell_type": "markdown", + "id": "c2041ccc-e502-4135-b067-159d85043378", + "metadata": { + "tags": [] + }, + "source": [ + "## Create test example" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "370178a2-f029-4e9b-b4f7-f4c051df686c", + "metadata": {}, + "outputs": [], + "source": [ + "import string, random, toolz, pandas, importlib, sys, os" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "a2199fbe-fa29-4286-b93a-eadba3b739e3", + "metadata": {}, + "outputs": [], + "source": [ + "terms = [(term, 1) for term in str(random.choices(string.ascii_letters, k=10**7)).split('Z')]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "5707eff9-710b-4799-87bc-99bed0eed866", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "count 192902.000000\n", + "mean 258.198977\n", + "std 257.967508\n", + "min 4.000000\n", + "25% 74.000000\n", + "50% 179.000000\n", + "75% 359.000000\n", + "max 3254.000000\n", + "dtype: float64" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pandas.Series(len(term) for term, _ in terms).describe()" + ] + }, + { + "cell_type": "markdown", + "id": "75dbfea5-3022-4652-89f2-e41f0b822abd", + "metadata": {}, + "source": [ + "## Run proposed version" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "6f8b616f-1835-4723-83c3-dc189b891a94", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Already on 'binary-polynomial'\n", + "Your branch is up to date with 'origin/binary-polynomial'.\n" + ] + } + ], + "source": [ + "!git checkout binary-polynomial\n", + "!touch -c ./dimod/higherorder/polynomial.py\n", + "#importlib.reload(dimod)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6e5ac6a3-5a9a-4147-8909-0b09208d66c2", + "metadata": {}, + "outputs": [], + "source": [ + "from dimod import BinaryPolynomial as BPnew" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "b8472b21-b3e6-4c19-b860-d2631dd78065", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[0;31mSignature:\u001b[0m \u001b[0mBPnew\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mDocstring:\u001b[0m Initialize self. See help(type(self)) for accurate signature.\n", + "\u001b[0;31mSource:\u001b[0m \n", + " \u001b[0;34m@\u001b[0m\u001b[0mvartype_argument\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'vartype'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mabc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mMapping\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mpoly\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;31m# we need to aggregate the repeated terms\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_terms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mterms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdefaultdict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mterms\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mfreeze_term\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvartype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mFile:\u001b[0m ~/dimod/dimod/higherorder/polynomial.py\n", + "\u001b[0;31mType:\u001b[0m function\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "BPnew.__init__??" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "9065a62a-4c71-4f58-843b-65f611bc4848", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + }, + { + "data": { + "text/plain": [ + " 578909 function calls (578829 primitive calls) in 4.456 seconds\n", + "\n", + " Ordered by: cumulative time\n", + " List reduced from 45 to 20 due to restriction <20>\n", + "\n", + " ncalls tottime percall cumtime percall filename:lineno(function)\n", + " 1 0.000 0.000 4.456 4.456 {built-in method builtins.exec}\n", + " 1 0.073 0.073 4.456 4.456 :1()\n", + " 1 0.000 0.000 4.383 4.383 decorators.py:289(new_f)\n", + " 1 0.188 0.188 4.383 4.383 polynomial.py:111(__init__)\n", + " 192902 4.167 0.000 4.195 0.000 polynomial.py:43(freeze_term)\n", + " 192912 0.015 0.000 0.015 0.000 {built-in method builtins.isinstance}\n", + " 192903 0.013 0.000 0.013 0.000 {method 'items' of 'dict' objects}\n", + " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", + " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", + " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", + " 41/1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_subclasscheck}\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", + " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", + " 1 0.000 0.000 0.000 0.000 :1(__new__)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", + " 38 0.000 0.000 0.000 0.000 _collections_abc.py:392(__subclasshook__)\n", + " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%prun -s cumtime -l 20 BPnew(terms, 'SPIN')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "909a0aa9-bf75-4026-9fc3-48879ee20269", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "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.8.11" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From b209990a48994727d0ed274aae3f1b5e8dfa7c82 Mon Sep 17 00:00:00 2001 From: Daniel Mahler Date: Thu, 9 Sep 2021 22:11:28 -0500 Subject: [PATCH 3/9] update evaluation notebook --- polynomial-perf.ipynb | 275 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 237 insertions(+), 38 deletions(-) diff --git a/polynomial-perf.ipynb b/polynomial-perf.ipynb index 4adccd02b..e12052148 100644 --- a/polynomial-perf.ipynb +++ b/polynomial-perf.ipynb @@ -58,14 +58,14 @@ { "data": { "text/plain": [ - "count 191557.000000\n", - "mean 260.018919\n", - "std 258.235286\n", + "count 193091.000000\n", + "mean 257.945269\n", + "std 256.685709\n", "min 4.000000\n", "25% 74.000000\n", "50% 179.000000\n", "75% 359.000000\n", - "max 3084.000000\n", + "max 3319.000000\n", "dtype: float64" ] }, @@ -185,21 +185,21 @@ { "data": { "text/plain": [ - " 9687489 function calls (9687409 primitive calls) in 28.809 seconds\n", + " 9739394 function calls (9739314 primitive calls) in 28.259 seconds\n", "\n", " Ordered by: cumulative time\n", " List reduced from 47 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 28.809 28.809 {built-in method builtins.exec}\n", - " 1 0.065 0.065 28.809 28.809 :1()\n", - " 1 0.000 0.000 28.743 28.743 decorators.py:289(new_f)\n", - " 1 2.587 2.587 28.743 28.743 polynomial.py:89(__init__)\n", - " 5468426 25.143 0.000 25.143 0.000 {method 'count' of 'tuple' objects}\n", - " 191557 0.649 0.000 0.677 0.000 polynomial.py:32(asfrozenset)\n", - " 3452632 0.297 0.000 0.297 0.000 {method 'add' of 'set' objects}\n", - " 383116 0.039 0.000 0.039 0.000 {built-in method builtins.len}\n", - " 191567 0.028 0.000 0.028 0.000 {built-in method builtins.isinstance}\n", + " 1 0.000 0.000 28.259 28.259 {built-in method builtins.exec}\n", + " 1 0.000 0.000 28.259 28.259 :1()\n", + " 1 0.000 0.000 28.259 28.259 decorators.py:289(new_f)\n", + " 1 2.699 2.699 28.259 28.259 polynomial.py:89(__init__)\n", + " 5492601 24.575 0.000 24.575 0.000 {method 'count' of 'tuple' objects}\n", + " 193091 0.614 0.000 0.645 0.000 polynomial.py:32(asfrozenset)\n", + " 3474226 0.298 0.000 0.298 0.000 {method 'add' of 'set' objects}\n", + " 386184 0.042 0.000 0.042 0.000 {built-in method builtins.len}\n", + " 193101 0.030 0.000 0.030 0.000 {built-in method builtins.isinstance}\n", " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", @@ -210,7 +210,7 @@ " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", - " 1 0.000 0.000 0.000 0.000 :1(__new__)" + " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)" ] }, "metadata": {}, @@ -218,21 +218,121 @@ } ], "source": [ - "%prun -s cumtime -l 20 BPold(terms, 'SPIN')" + "%%prun -s cumtime -l 20\n", + "bp = BPold(terms, 'SPIN')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "a74eb4b1-a59a-49d7-8e36-95ea91a7a12b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
01
count182233.000000182233.000000
mean18.9343861.059583
std7.5458629.112464
min1.0000001.000000
25%13.0000001.000000
50%20.0000001.000000
75%25.0000001.000000
max40.0000003851.000000
\n", + "
" + ], + "text/plain": [ + " 0 1\n", + "count 182233.000000 182233.000000\n", + "mean 18.934386 1.059583\n", + "std 7.545862 9.112464\n", + "min 1.000000 1.000000\n", + "25% 13.000000 1.000000\n", + "50% 20.000000 1.000000\n", + "75% 25.000000 1.000000\n", + "max 40.000000 3851.000000" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pandas.DataFrame((len(term), bias) for term, bias in bp.items()).describe()" ] }, { "cell_type": "markdown", "id": "81473689-9ece-45a7-85a0-389d0418be3e", - "metadata": {}, + "metadata": { + "tags": [] + }, "source": [ "# Exit interpreter\n", - "I just can'get module reloading to work properly here ..." + "I just can't get module reloading to work properly here ..." ] }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "id": "673fe5b0-5934-4b40-a418-62122e867aa9", "metadata": {}, "outputs": [], @@ -289,14 +389,14 @@ { "data": { "text/plain": [ - "count 192902.000000\n", - "mean 258.198977\n", - "std 257.967508\n", + "count 192689.000000\n", + "mean 258.485497\n", + "std 257.605560\n", "min 4.000000\n", "25% 74.000000\n", "50% 179.000000\n", "75% 359.000000\n", - "max 3254.000000\n", + "max 2809.000000\n", "dtype: float64" ] }, @@ -328,7 +428,8 @@ "output_type": "stream", "text": [ "Already on 'binary-polynomial'\n", - "Your branch is up to date with 'origin/binary-polynomial'.\n" + "Your branch is ahead of 'origin/binary-polynomial' by 1 commit.\n", + " (use \"git push\" to publish your local commits)\n" ] } ], @@ -400,19 +501,19 @@ { "data": { "text/plain": [ - " 578909 function calls (578829 primitive calls) in 4.456 seconds\n", + " 578270 function calls (578190 primitive calls) in 4.526 seconds\n", "\n", " Ordered by: cumulative time\n", " List reduced from 45 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 4.456 4.456 {built-in method builtins.exec}\n", - " 1 0.073 0.073 4.456 4.456 :1()\n", - " 1 0.000 0.000 4.383 4.383 decorators.py:289(new_f)\n", - " 1 0.188 0.188 4.383 4.383 polynomial.py:111(__init__)\n", - " 192902 4.167 0.000 4.195 0.000 polynomial.py:43(freeze_term)\n", - " 192912 0.015 0.000 0.015 0.000 {built-in method builtins.isinstance}\n", - " 192903 0.013 0.000 0.013 0.000 {method 'items' of 'dict' objects}\n", + " 1 0.000 0.000 4.526 4.526 {built-in method builtins.exec}\n", + " 1 0.000 0.000 4.526 4.526 :1()\n", + " 1 0.000 0.000 4.526 4.526 decorators.py:289(new_f)\n", + " 1 0.189 0.189 4.526 4.526 polynomial.py:111(__init__)\n", + " 192689 4.308 0.000 4.337 0.000 polynomial.py:43(freeze_term)\n", + " 192699 0.016 0.000 0.016 0.000 {built-in method builtins.isinstance}\n", + " 192690 0.013 0.000 0.013 0.000 {method 'items' of 'dict' objects}\n", " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", @@ -420,12 +521,12 @@ " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", + " 38 0.000 0.000 0.000 0.000 _collections_abc.py:392(__subclasshook__)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", + " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)\n", + " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)\n", " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", - " 1 0.000 0.000 0.000 0.000 :1(__new__)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", - " 38 0.000 0.000 0.000 0.000 _collections_abc.py:392(__subclasshook__)\n", - " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)" + " 1 0.000 0.000 0.000 0.000 inspect.py:80(ismethod)" ] }, "metadata": {}, @@ -433,13 +534,111 @@ } ], "source": [ - "%prun -s cumtime -l 20 BPnew(terms, 'SPIN')" + "%%prun -s cumtime -l 20 \n", + "bp = BPnew(terms, 'SPIN')" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "b9f0d049-5b6f-4521-a6c9-f6d0f529b8a8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
01
count181909.000000181909.000000
mean18.9143141.059260
std7.5439989.110785
min1.0000001.000000
25%13.0000001.000000
50%20.0000001.000000
75%25.0000001.000000
max40.0000003848.000000
\n", + "
" + ], + "text/plain": [ + " 0 1\n", + "count 181909.000000 181909.000000\n", + "mean 18.914314 1.059260\n", + "std 7.543998 9.110785\n", + "min 1.000000 1.000000\n", + "25% 13.000000 1.000000\n", + "50% 20.000000 1.000000\n", + "75% 25.000000 1.000000\n", + "max 40.000000 3848.000000" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pandas.DataFrame((len(term), bias) for term, bias in bp.items()).describe()" ] }, { "cell_type": "code", "execution_count": null, - "id": "909a0aa9-bf75-4026-9fc3-48879ee20269", + "id": "e396116b-8b48-4e80-b780-63e6918d75e3", "metadata": {}, "outputs": [], "source": [] From 7ddbe4c1dda7ee48136564b2ce743bd283354843 Mon Sep 17 00:00:00 2001 From: Daniel Mahler Date: Fri, 10 Sep 2021 01:39:00 -0500 Subject: [PATCH 4/9] simplify freeze_term --- dimod/higherorder/polynomial.py | 11 +++--- polynomial-perf.ipynb | 59 +++++++++++++++++---------------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/dimod/higherorder/polynomial.py b/dimod/higherorder/polynomial.py index 77a588cca..7379ac1d0 100644 --- a/dimod/higherorder/polynomial.py +++ b/dimod/higherorder/polynomial.py @@ -37,9 +37,6 @@ def asfrozenset(term): return term if isinstance(term, frozenset) else frozenset(term) -is_odd = tl.flip(tl.curried.operator.mod)(2) -second_is_odd = tl.compose(is_odd, tl.second) - def freeze_term(term, vartype): return ( term @@ -48,14 +45,14 @@ def freeze_term(term, vartype): frozenset(term) if vartype is Vartype.BINARY else frozenset( - map( - tl.first, - filter(second_is_odd, tl.frequencies(term).items()) - ) + var + for var, power in tl.frequencies(term).items() + if power % 2 ) ) ) + class BinaryPolynomial(abc.MutableMapping): """A polynomial with binary variables and real-valued coefficients. diff --git a/polynomial-perf.ipynb b/polynomial-perf.ipynb index e12052148..b84547548 100644 --- a/polynomial-perf.ipynb +++ b/polynomial-perf.ipynb @@ -389,14 +389,14 @@ { "data": { "text/plain": [ - "count 192689.000000\n", - "mean 258.485497\n", - "std 257.605560\n", + "count 192325.000000\n", + "mean 258.976607\n", + "std 257.827839\n", "min 4.000000\n", "25% 74.000000\n", "50% 179.000000\n", "75% 359.000000\n", - "max 2809.000000\n", + "max 3419.000000\n", "dtype: float64" ] }, @@ -427,6 +427,7 @@ "name": "stdout", "output_type": "stream", "text": [ + "M\tpolynomial-perf.ipynb\n", "Already on 'binary-polynomial'\n", "Your branch is ahead of 'origin/binary-polynomial' by 1 commit.\n", " (use \"git push\" to publish your local commits)\n" @@ -501,19 +502,20 @@ { "data": { "text/plain": [ - " 578270 function calls (578190 primitive calls) in 4.526 seconds\n", + " 4232729 function calls (4232649 primitive calls) in 3.246 seconds\n", "\n", " Ordered by: cumulative time\n", - " List reduced from 45 to 20 due to restriction <20>\n", + " List reduced from 46 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 4.526 4.526 {built-in method builtins.exec}\n", - " 1 0.000 0.000 4.526 4.526 :1()\n", - " 1 0.000 0.000 4.526 4.526 decorators.py:289(new_f)\n", - " 1 0.189 0.189 4.526 4.526 polynomial.py:111(__init__)\n", - " 192689 4.308 0.000 4.337 0.000 polynomial.py:43(freeze_term)\n", - " 192699 0.016 0.000 0.016 0.000 {built-in method builtins.isinstance}\n", - " 192690 0.013 0.000 0.013 0.000 {method 'items' of 'dict' objects}\n", + " 1 0.000 0.000 3.246 3.246 {built-in method builtins.exec}\n", + " 1 0.000 0.000 3.246 3.246 :1()\n", + " 1 0.000 0.000 3.246 3.246 decorators.py:289(new_f)\n", + " 1 0.177 0.177 3.246 3.246 polynomial.py:108(__init__)\n", + " 192325 2.615 0.000 3.069 0.000 polynomial.py:40(freeze_term)\n", + " 3655551 0.427 0.000 0.427 0.000 polynomial.py:47()\n", + " 192335 0.015 0.000 0.015 0.000 {built-in method builtins.isinstance}\n", + " 192326 0.012 0.000 0.012 0.000 {method 'items' of 'dict' objects}\n", " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", @@ -521,12 +523,11 @@ " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", - " 38 0.000 0.000 0.000 0.000 _collections_abc.py:392(__subclasshook__)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", - " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)\n", - " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)\n", " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:80(ismethod)" + " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", + " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)\n", + " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)" ] }, "metadata": {}, @@ -572,18 +573,18 @@ " \n", " \n", " count\n", - " 181909.000000\n", - " 181909.000000\n", + " 181650.000000\n", + " 181650.000000\n", " \n", " \n", " mean\n", - " 18.914314\n", - " 1.059260\n", + " 18.937605\n", + " 1.058767\n", " \n", " \n", " std\n", - " 7.543998\n", - " 9.110785\n", + " 7.559899\n", + " 8.875054\n", " \n", " \n", " min\n", @@ -607,8 +608,8 @@ " \n", " \n", " max\n", - " 40.000000\n", - " 3848.000000\n", + " 42.000000\n", + " 3742.000000\n", " \n", " \n", "\n", @@ -616,14 +617,14 @@ ], "text/plain": [ " 0 1\n", - "count 181909.000000 181909.000000\n", - "mean 18.914314 1.059260\n", - "std 7.543998 9.110785\n", + "count 181650.000000 181650.000000\n", + "mean 18.937605 1.058767\n", + "std 7.559899 8.875054\n", "min 1.000000 1.000000\n", "25% 13.000000 1.000000\n", "50% 20.000000 1.000000\n", "75% 25.000000 1.000000\n", - "max 40.000000 3848.000000" + "max 42.000000 3742.000000" ] }, "execution_count": 8, From 44e0921c0a8283e1b456e3ece1e66546687c63ec Mon Sep 17 00:00:00 2001 From: Daniel Mahler Date: Mon, 20 Sep 2021 23:23:58 -0500 Subject: [PATCH 5/9] added reduce_terms --- dimod/higherorder/utils.py | 81 +- polynomial-perf.ipynb | 1809 +++++++++++++++++++++++++++++++++++- 2 files changed, 1879 insertions(+), 11 deletions(-) diff --git a/dimod/higherorder/utils.py b/dimod/higherorder/utils.py index a343efcc2..83e6da7df 100644 --- a/dimod/higherorder/utils.py +++ b/dimod/higherorder/utils.py @@ -17,14 +17,20 @@ from collections import Counter +from collections import defaultdict +import functools as ft +import itertools as it +import cytoolz as tl + import numpy as np +import cytoolz as tl from dimod.binary_quadratic_model import BinaryQuadraticModel from dimod.higherorder.polynomial import BinaryPolynomial from dimod.sampleset import as_samples from dimod.vartypes import as_vartype, Vartype -__all__ = ['make_quadratic'] +__all__ = ['make_quadratic', 'reduce_terms'] def _spin_product(variables): @@ -97,6 +103,79 @@ def _new_aux(variables, u, v): return aux +def reduce_terms(bp): + variables = bp.variables + constraints = [] + reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2] + + idx = defaultdict( + dict, + tl.valmap( + tl.compose(dict, ft.partial(map, tl.second)), + tl.groupby( + tl.first, + ( + (frozenset(pair), item) + for item in bp.items() + if len(term := tl.first(item)) >= 3 + for pair in it.combinations(term, 2) )))) + + que = defaultdict( + set, + tl.valmap( + tl.compose(set, ft.partial(map, tl.first)), + tl.groupby(tl.second, tl.valmap(len, idx).items()))) + + while idx: + new_pairs = set() + most = max(que) + + #print(most, que[most]) + #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items()) + #pair, terms = max(idx.items(), key=tl.compose(len,tl.second)) + + que_most = que[most] + pair = que_most.pop() + if not que_most: + del que[most] + terms = idx[pair] + + p = _new_product(variables, *pair) + constraints.append((pair, p)) + del idx[pair] + pset = {p} + + for term, bias in terms.items(): + for pair2 in map(frozenset, (it.combinations(term, 2))): + if pair2 != pair: + if pair2 & pair: + count = len(idx[pair2]) + que_count = que[count] + que_count.remove(pair2) + if not que_count: + del que[count] + if count > 1: + que[count - 1].add(pair2) + idx_pair2 = idx[pair2] + del idx_pair2[term] + if not idx_pair2: + del idx[pair2] + + new_term = (term - pair) | pset + if len(new_term) <= 2: + reduced_terms.append((new_term, bias)) + else: + for new_pair in map(frozenset, it.combinations(new_term, 2)): + idx[new_pair][new_term] = bias + if p in new_pair: + new_pairs.add(new_pair) + + for new_pair in new_pairs: + que[len(idx[new_pair])].add(new_pair) + + return reduced_terms, constraints + + def make_quadratic(poly, strength, vartype=None, bqm=None): """Create a binary quadratic model from a higher order polynomial. diff --git a/polynomial-perf.ipynb b/polynomial-perf.ipynb index b84547548..52246542f 100644 --- a/polynomial-perf.ipynb +++ b/polynomial-perf.ipynb @@ -58,14 +58,24 @@ { "data": { "text/plain": [ +<<<<<<< Updated upstream "count 193091.000000\n", "mean 257.945269\n", "std 256.685709\n", +======= + "count 192160.000000\n", + "mean 259.199839\n", + "std 256.922932\n", +>>>>>>> Stashed changes "min 4.000000\n", "25% 74.000000\n", "50% 179.000000\n", "75% 359.000000\n", +<<<<<<< Updated upstream "max 3319.000000\n", +======= + "max 3174.000000\n", +>>>>>>> Stashed changes "dtype: float64" ] }, @@ -96,6 +106,10 @@ "name": "stdout", "output_type": "stream", "text": [ +<<<<<<< Updated upstream +======= + "Saved working directory and index state WIP on binary-polynomial: bc4521f added symbolic arithmetic refactored relabel_variables, to_binary, to_spin filter out 0 coefficient terms in polynomial construction\n", +>>>>>>> Stashed changes "Switched to branch 'main'\n", "Your branch and 'upstream/main' have diverged,\n", "and have 1 and 2 different commits each, respectively.\n", @@ -115,7 +129,8 @@ "metadata": {}, "outputs": [], "source": [ - "from dimod import BinaryPolynomial as BPold" + "from dimod import BinaryPolynomial as BPold\n", + "import dimod" ] }, { @@ -185,12 +200,17 @@ { "data": { "text/plain": [ +<<<<<<< Updated upstream " 9739394 function calls (9739314 primitive calls) in 28.259 seconds\n", +======= + " 9711530 function calls (9711450 primitive calls) in 48.033 seconds\n", +>>>>>>> Stashed changes "\n", " Ordered by: cumulative time\n", " List reduced from 47 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", +<<<<<<< Updated upstream " 1 0.000 0.000 28.259 28.259 {built-in method builtins.exec}\n", " 1 0.000 0.000 28.259 28.259 :1()\n", " 1 0.000 0.000 28.259 28.259 decorators.py:289(new_f)\n", @@ -200,6 +220,17 @@ " 3474226 0.298 0.000 0.298 0.000 {method 'add' of 'set' objects}\n", " 386184 0.042 0.000 0.042 0.000 {built-in method builtins.len}\n", " 193101 0.030 0.000 0.030 0.000 {built-in method builtins.isinstance}\n", +======= + " 1 0.000 0.000 48.033 48.033 {built-in method builtins.exec}\n", + " 1 0.000 0.000 48.033 48.033 :1()\n", + " 1 0.000 0.000 48.033 48.033 decorators.py:289(new_f)\n", + " 1 7.909 7.909 48.033 48.033 polynomial.py:89(__init__)\n", + " 5482062 38.220 0.000 38.220 0.000 {method 'count' of 'tuple' objects}\n", + " 192160 1.075 0.000 1.135 0.000 polynomial.py:32(asfrozenset)\n", + " 3460625 0.690 0.000 0.690 0.000 {method 'add' of 'set' objects}\n", + " 384322 0.079 0.000 0.079 0.000 {built-in method builtins.len}\n", + " 192170 0.060 0.000 0.060 0.000 {built-in method builtins.isinstance}\n", +>>>>>>> Stashed changes " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", @@ -209,8 +240,13 @@ " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", +<<<<<<< Updated upstream " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)" +======= + " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)\n", + " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)" +>>>>>>> Stashed changes ] }, "metadata": {}, @@ -256,6 +292,7 @@ " \n", " \n", " count\n", +<<<<<<< Updated upstream " 182233.000000\n", " 182233.000000\n", " \n", @@ -268,6 +305,20 @@ " std\n", " 7.545862\n", " 9.112464\n", +======= + " 181561.000000\n", + " 181561.000000\n", + " \n", + " \n", + " mean\n", + " 18.931703\n", + " 1.058377\n", + " \n", + " \n", + " std\n", + " 7.552280\n", + " 8.721284\n", +>>>>>>> Stashed changes " \n", " \n", " min\n", @@ -291,8 +342,13 @@ " \n", " \n", " max\n", +<<<<<<< Updated upstream " 40.000000\n", " 3851.000000\n", +======= + " 42.000000\n", + " 3677.000000\n", +>>>>>>> Stashed changes " \n", " \n", "\n", @@ -300,14 +356,24 @@ ], "text/plain": [ " 0 1\n", +<<<<<<< Updated upstream "count 182233.000000 182233.000000\n", "mean 18.934386 1.059583\n", "std 7.545862 9.112464\n", +======= + "count 181561.000000 181561.000000\n", + "mean 18.931703 1.058377\n", + "std 7.552280 8.721284\n", +>>>>>>> Stashed changes "min 1.000000 1.000000\n", "25% 13.000000 1.000000\n", "50% 20.000000 1.000000\n", "75% 25.000000 1.000000\n", +<<<<<<< Updated upstream "max 40.000000 3851.000000" +======= + "max 42.000000 3677.000000" +>>>>>>> Stashed changes ] }, "execution_count": 9, @@ -320,6 +386,296 @@ ] }, { +<<<<<<< Updated upstream +======= + "cell_type": "code", + "execution_count": null, + "id": "6f8463b3-a6fe-4841-918f-33743295181f", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "ce407274-b49c-4dc5-8fc0-69a5753029c7", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "term = string.ascii_letters[:12]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "0834a2d8-5e01-4a40-9541-0a871f18ff2a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.14 s ± 310 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%timeit BPold({term: 1}, 'SPIN').to_binary().to_spin() == BPold({term: 1}, 'SPIN')\n", + "BPold({term: 1}, 'SPIN').to_binary().to_spin() == BPold({term: 1}, 'SPIN')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a7e72459-4dce-458d-84d4-bf6ddf925e33", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.22 s ± 265 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%timeit BPold({term: 1}, 'BINARY').to_spin().to_binary() == BPold({term: 1}, 'BINARY')\n", + "BPold({term: 1}, 'BINARY').to_spin().to_binary() == BPold({term: 1}, 'BINARY')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "a8af1d2f-e9d4-4fe6-9129-173589c30d9b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4096" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(BPold({term: 1}, 'SPIN').to_binary().to_spin())" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "45b7c9d6-cc7a-475e-adaf-8fa4649119a6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4096" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(BPold({term: 1}, 'BINARY').to_spin().to_binary())" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "a4a0ea46-a6a5-47f7-8f4e-47fa480c492d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + }, + { + "data": { + "text/plain": [ + " 19196037 function calls (19196032 primitive calls) in 21.734 seconds\n", + "\n", + " Ordered by: cumulative time\n", + " List reduced from 66 to 20 due to restriction <20>\n", + "\n", + " ncalls tottime percall cumtime percall filename:lineno(function)\n", + " 1 0.000 0.000 21.734 21.734 {built-in method builtins.exec}\n", + " 1 0.000 0.000 21.733 21.733 :1()\n", + " 2/1 15.297 7.648 21.733 21.733 polynomial.py:232(relabel_variables)\n", + " 7237640 2.147 0.000 2.887 0.000 polynomial.py:256()\n", + " 544686 1.648 0.000 2.116 0.000 _collections_abc.py:742(__iter__)\n", + " 6874522 0.740 0.000 0.740 0.000 {method 'get' of 'dict' objects}\n", + " 363120 0.462 0.000 0.608 0.000 polynomial.py:158(__setitem__)\n", + " 1 0.000 0.000 0.517 0.517 polynomial.py:177(copy)\n", + " 1 0.000 0.000 0.517 0.517 decorators.py:289(new_f)\n", + " 1 0.200 0.200 0.517 0.517 polynomial.py:89(__init__)\n", + " 1452484 0.347 0.000 0.479 0.000 polynomial.py:32(asfrozenset)\n", + " 544683 0.313 0.000 0.468 0.000 polynomial.py:149(__getitem__)\n", + " 363120 0.282 0.000 0.409 0.000 polynomial.py:120(__delitem__)\n", + " 1 0.012 0.012 0.134 0.134 polynomial.py:165(variables)\n", + " 1452493 0.132 0.000 0.132 0.000 {built-in method builtins.isinstance}\n", + " 1 0.122 0.122 0.122 0.122 {method 'union' of 'set' objects}\n", + "363133/363129 0.031 0.000 0.031 0.000 {built-in method builtins.len}\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", + " 3 0.000 0.000 0.000 0.000 utilities.py:351(iter_safe_relabels)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "prun -s cumtime -l 20 bp2 = bp.relabel_variables(dict(zip(string.ascii_letters, reversed(string.ascii_letters))), inplace=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "7eeadfa9-40e8-41c5-bcf5-39d1ca2fbd00", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + }, + { + "data": { + "text/plain": [ + " 19196034 function calls (19196029 primitive calls) in 18.191 seconds\n", + "\n", + " Ordered by: cumulative time\n", + " List reduced from 63 to 20 due to restriction <20>\n", + "\n", + " ncalls tottime percall cumtime percall filename:lineno(function)\n", + " 1 0.000 0.000 18.191 18.191 {built-in method builtins.exec}\n", + " 1 0.000 0.000 18.191 18.191 :1()\n", + " 2/1 9.913 4.957 18.191 18.191 polynomial.py:232(relabel_variables)\n", + " 7237640 2.937 0.000 3.940 0.000 polynomial.py:256()\n", + " 544686 1.989 0.000 2.508 0.000 _collections_abc.py:742(__iter__)\n", + " 6874522 1.003 0.000 1.003 0.000 {method 'get' of 'dict' objects}\n", + " 363120 0.674 0.000 0.886 0.000 polynomial.py:158(__setitem__)\n", + " 1452484 0.430 0.000 0.592 0.000 polynomial.py:32(asfrozenset)\n", + " 363120 0.404 0.000 0.565 0.000 polynomial.py:120(__delitem__)\n", + " 544683 0.350 0.000 0.519 0.000 polynomial.py:149(__getitem__)\n", + " 1 0.000 0.000 0.477 0.477 polynomial.py:177(copy)\n", + " 1 0.000 0.000 0.477 0.477 decorators.py:289(new_f)\n", + " 1 0.178 0.178 0.477 0.477 polynomial.py:89(__init__)\n", + " 1452493 0.161 0.000 0.161 0.000 {built-in method builtins.isinstance}\n", + " 1 0.009 0.009 0.122 0.122 polynomial.py:165(variables)\n", + " 1 0.113 0.113 0.113 0.113 {method 'union' of 'set' objects}\n", + "363133/363129 0.030 0.000 0.030 0.000 {built-in method builtins.len}\n", + " 3 0.000 0.000 0.000 0.000 utilities.py:351(iter_safe_relabels)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "prun -s cumtime -l 20 bp3 = bp2.relabel_variables(dict(zip(string.ascii_letters, reversed(string.ascii_letters))), inplace=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "0791493b-2ded-4b56-84ea-accb50f0de3d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bp == bp2" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "3efb0d30-46a3-41f5-bebc-7d9a18d17e41", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bp == bp3" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "a81ab133-322d-4f93-a9d3-5abd8b49d6ab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bp2 == bp3" + ] + }, + { +>>>>>>> Stashed changes "cell_type": "markdown", "id": "81473689-9ece-45a7-85a0-389d0418be3e", "metadata": { @@ -332,7 +688,11 @@ }, { "cell_type": "code", +<<<<<<< Updated upstream "execution_count": 10, +======= + "execution_count": 20, +>>>>>>> Stashed changes "id": "673fe5b0-5934-4b40-a418-62122e867aa9", "metadata": {}, "outputs": [], @@ -362,12 +722,16 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 55, "id": "370178a2-f029-4e9b-b4f7-f4c051df686c", "metadata": {}, "outputs": [], "source": [ +<<<<<<< Updated upstream "import string, random, toolz, pandas, importlib, sys, os" +======= + "import string, random, toolz, pandas, importlib, sys, os, cytoolz, toolz, dimod" +>>>>>>> Stashed changes ] }, { @@ -375,9 +739,18 @@ "execution_count": 2, "id": "a2199fbe-fa29-4286-b93a-eadba3b739e3", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 122 ms, sys: 20.4 ms, total: 142 ms\n", + "Wall time: 141 ms\n" + ] + } + ], "source": [ - "terms = [(term, 1) for term in str(random.choices(string.ascii_letters, k=10**7)).split('Z')]" + "%time terms = [(term, 1) for term in ''.join(random.choices(string.ascii_letters, k=10**6)).split('Z')]" ] }, { @@ -389,6 +762,7 @@ { "data": { "text/plain": [ +<<<<<<< Updated upstream "count 192325.000000\n", "mean 258.976607\n", "std 257.827839\n", @@ -397,6 +771,16 @@ "50% 179.000000\n", "75% 359.000000\n", "max 3419.000000\n", +======= + "count 19253.000000\n", + "mean 50.940009\n", + "std 51.333538\n", + "min 0.000000\n", + "25% 14.000000\n", + "50% 35.000000\n", + "75% 71.000000\n", + "max 459.000000\n", +>>>>>>> Stashed changes "dtype: float64" ] }, @@ -427,10 +811,20 @@ "name": "stdout", "output_type": "stream", "text": [ +<<<<<<< Updated upstream "M\tpolynomial-perf.ipynb\n", "Already on 'binary-polynomial'\n", "Your branch is ahead of 'origin/binary-polynomial' by 1 commit.\n", " (use \"git push\" to publish your local commits)\n" +======= + "M\tdimod/higherorder/polynomial.py\n", + "M\tdimod/higherorder/utils.py\n", + "D\tpolynomial-perf.ipynb\n", + "Already on 'binary-polynomial'\n", + "Your branch is ahead of 'origin/binary-polynomial' by 1 commit.\n", + " (use \"git push\" to publish your local commits)\n", + "No stash entries found.\n" +>>>>>>> Stashed changes ] } ], @@ -468,9 +862,14 @@ "\u001b[0;34m\u001b[0m \u001b[0mpoly\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;31m# we need to aggregate the repeated terms\u001b[0m\u001b[0;34m\u001b[0m\n", +<<<<<<< Updated upstream "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_terms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mterms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdefaultdict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", +======= + "\u001b[0;34m\u001b[0m \u001b[0mterms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdefaultdict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mfilter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtl\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msecond\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", +>>>>>>> Stashed changes "\u001b[0;34m\u001b[0m \u001b[0mterms\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mfreeze_term\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvartype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", @@ -502,12 +901,17 @@ { "data": { "text/plain": [ +<<<<<<< Updated upstream " 4232729 function calls (4232649 primitive calls) in 3.246 seconds\n", +======= + " 404277 function calls (404197 primitive calls) in 0.299 seconds\n", +>>>>>>> Stashed changes "\n", " Ordered by: cumulative time\n", " List reduced from 46 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", +<<<<<<< Updated upstream " 1 0.000 0.000 3.246 3.246 {built-in method builtins.exec}\n", " 1 0.000 0.000 3.246 3.246 :1()\n", " 1 0.000 0.000 3.246 3.246 decorators.py:289(new_f)\n", @@ -516,6 +920,16 @@ " 3655551 0.427 0.000 0.427 0.000 polynomial.py:47()\n", " 192335 0.015 0.000 0.015 0.000 {built-in method builtins.isinstance}\n", " 192326 0.012 0.000 0.012 0.000 {method 'items' of 'dict' objects}\n", +======= + " 1 0.000 0.000 0.299 0.299 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.299 0.299 :1()\n", + " 1 0.001 0.001 0.299 0.299 decorators.py:289(new_f)\n", + " 1 0.028 0.028 0.298 0.298 polynomial.py:108(__init__)\n", + " 19253 0.198 0.000 0.269 0.000 polynomial.py:40(freeze_term)\n", + " 346315 0.067 0.000 0.067 0.000 polynomial.py:47()\n", + " 19263 0.003 0.000 0.003 0.000 {built-in method builtins.isinstance}\n", + " 19254 0.002 0.000 0.002 0.000 {method 'items' of 'dict' objects}\n", +>>>>>>> Stashed changes " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", @@ -525,9 +939,15 @@ " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", +<<<<<<< Updated upstream " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)\n", " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)" +======= + " 1 0.000 0.000 0.000 0.000 :1(__new__)\n", + " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}\n", + " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)" +>>>>>>> Stashed changes ] }, "metadata": {}, @@ -573,6 +993,7 @@ " \n", " \n", " count\n", +<<<<<<< Updated upstream " 181650.000000\n", " 181650.000000\n", " \n", @@ -585,37 +1006,57 @@ " std\n", " 7.559899\n", " 8.875054\n", +======= + " 18468.000000\n", + " 18468.000000\n", + " \n", + " \n", + " mean\n", + " 17.684644\n", + " 1.042506\n", + " \n", + " \n", + " std\n", + " 7.686658\n", + " 2.887464\n", +>>>>>>> Stashed changes " \n", " \n", " min\n", - " 1.000000\n", + " 0.000000\n", " 1.000000\n", " \n", " \n", " 25%\n", - " 13.000000\n", + " 12.000000\n", " 1.000000\n", " \n", " \n", " 50%\n", - " 20.000000\n", + " 19.000000\n", " 1.000000\n", " \n", " \n", " 75%\n", - " 25.000000\n", + " 24.000000\n", " 1.000000\n", " \n", " \n", " max\n", +<<<<<<< Updated upstream " 42.000000\n", " 3742.000000\n", +======= + " 40.000000\n", + " 390.000000\n", +>>>>>>> Stashed changes " \n", " \n", "\n", "" ], "text/plain": [ +<<<<<<< Updated upstream " 0 1\n", "count 181650.000000 181650.000000\n", "mean 18.937605 1.058767\n", @@ -625,6 +1066,17 @@ "50% 20.000000 1.000000\n", "75% 25.000000 1.000000\n", "max 42.000000 3742.000000" +======= + " 0 1\n", + "count 18468.000000 18468.000000\n", + "mean 17.684644 1.042506\n", + "std 7.686658 2.887464\n", + "min 0.000000 1.000000\n", + "25% 12.000000 1.000000\n", + "50% 19.000000 1.000000\n", + "75% 24.000000 1.000000\n", + "max 40.000000 390.000000" +>>>>>>> Stashed changes ] }, "execution_count": 8, @@ -638,11 +1090,1348 @@ }, { "cell_type": "code", +<<<<<<< Updated upstream "execution_count": null, "id": "e396116b-8b48-4e80-b780-63e6918d75e3", - "metadata": {}, +======= + "execution_count": 10, + "id": "e396116b-8b48-4e80-b780-63e6918d75e3", + "metadata": { + "tags": [] + }, "outputs": [], - "source": [] + "source": [ + "term = string.ascii_letters[:12]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "251c2cf3-d1e0-4f81-8b2d-0bfe3b809afc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.33 s ± 148 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%timeit BPnew({term: 1}, 'SPIN').to_binary().to_spin() == BPnew({term: 1}, 'SPIN')\n", + "BPnew({term: 1}, 'SPIN').to_binary().to_spin() == BPnew({term: 1}, 'SPIN')" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "1b734eee-3346-4ccf-a46b-b7f1062d7146", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "689 ms ± 113 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + }, + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%timeit BPnew({term: 1}, 'BINARY').to_spin().to_binary() == BPnew({term: 1}, 'BINARY')\n", + "BPnew({term: 1}, 'BINARY').to_spin().to_binary() == BPnew({term: 1}, 'BINARY')" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "cd914370-6d26-4549-8ac1-409b9cfb0d42", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(BPnew({term: 1}, 'BINARY').to_spin().to_binary())" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "9b8ea924-76fe-4dfc-9b0f-1e526c38f0ce", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(BPnew({term: 1}, 'SPIN').to_binary().to_spin())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3cec6003-377c-4ce2-aaff-195413a5d7f0", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "5855d98a-3560-4ff4-8717-c71e7a5b9322", + "metadata": {}, + "outputs": [], + "source": [ + "#len(BPnew({term: 1}, 'BINARY').to_spin() * BPnew({term: 1}, 'BINARY').to_spin())" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "8f1025ab-14a5-4ab2-b636-aae76d82b1cb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + }, + { + "data": { + "text/plain": [ + " 782622 function calls in 0.242 seconds\n", + "\n", + " Ordered by: cumulative time\n", + " List reduced from 56 to 20 due to restriction <20>\n", + "\n", + " ncalls tottime percall cumtime percall filename:lineno(function)\n", + " 1 0.000 0.000 0.242 0.242 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.242 0.242 :1()\n", + " 1 0.000 0.000 0.242 0.242 polynomial.py:269(relabel_variables)\n", + " 1 0.095 0.095 0.209 0.209 polynomial.py:295()\n", + " 345068 0.069 0.000 0.092 0.000 polynomial.py:296()\n", + " 326604 0.023 0.000 0.023 0.000 {method 'get' of 'dict' objects}\n", + " 18469 0.008 0.000 0.022 0.000 _collections_abc.py:742(__iter__)\n", + " 1 0.000 0.000 0.022 0.022 decorators.py:289(new_f)\n", + " 1 0.017 0.017 0.021 0.021 polynomial.py:108(__init__)\n", + " 18468 0.009 0.000 0.014 0.000 polynomial.py:153(__getitem__)\n", + " 1 0.001 0.001 0.011 0.011 polynomial.py:202(variables)\n", + " 1 0.009 0.009 0.009 0.009 {method 'union' of 'set' objects}\n", + " 18468 0.003 0.000 0.005 0.000 polynomial.py:35(asfrozenset)\n", + " 18468 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", + " 36945 0.003 0.000 0.003 0.000 {built-in method builtins.isinstance}\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", + " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "prun -s cumtime -l 20 bp2 = bp.relabel_variables(dict(zip(string.ascii_letters, reversed(string.ascii_letters))), inplace=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "f28b9d31-00f6-4d19-a799-4aebd8dcdf77", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + }, + { + "data": { + "text/plain": [ + " 782622 function calls in 0.252 seconds\n", + "\n", + " Ordered by: cumulative time\n", + " List reduced from 56 to 20 due to restriction <20>\n", + "\n", + " ncalls tottime percall cumtime percall filename:lineno(function)\n", + " 1 0.000 0.000 0.252 0.252 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.252 0.252 :1()\n", + " 1 0.000 0.000 0.252 0.252 polynomial.py:269(relabel_variables)\n", + " 1 0.103 0.103 0.225 0.225 polynomial.py:295()\n", + " 345068 0.073 0.000 0.098 0.000 polynomial.py:296()\n", + " 326604 0.025 0.000 0.025 0.000 {method 'get' of 'dict' objects}\n", + " 18469 0.009 0.000 0.024 0.000 _collections_abc.py:742(__iter__)\n", + " 1 0.000 0.000 0.017 0.017 decorators.py:289(new_f)\n", + " 1 0.013 0.013 0.016 0.016 polynomial.py:108(__init__)\n", + " 18468 0.010 0.000 0.015 0.000 polynomial.py:153(__getitem__)\n", + " 1 0.001 0.001 0.010 0.010 polynomial.py:202(variables)\n", + " 1 0.009 0.009 0.009 0.009 {method 'union' of 'set' objects}\n", + " 18468 0.004 0.000 0.005 0.000 polynomial.py:35(asfrozenset)\n", + " 18468 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", + " 36945 0.002 0.000 0.002 0.000 {built-in method builtins.isinstance}\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", + " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "prun -s cumtime -l 20 bp3 = bp2.relabel_variables(dict(zip(string.ascii_letters, reversed(string.ascii_letters))), inplace=False)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "1feeafa7-7b82-4936-8907-1d9e2cb2f09f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bp == bp2" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "2b68eedb-625d-4b55-913e-eca731039285", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bp == bp3" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "f26be75b-8a2f-4825-9c5d-61cb22cb23da", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bp2 == bp3" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "7ac90b1e-af50-42e1-89f5-7c3274d9bff0", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "%load_ext line_profiler" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "3ff64574-290e-4e1d-ba85-5dc597c31258", + "metadata": {}, + "outputs": [], + "source": [ + "#%lprun -fdimod.make_quadratic bqm = dimod.make_quadratic(bp, vartype = 'BINARY', strength = 2**6)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "7ac382c2-abc7-43e2-b599-8320b48d89f4", + "metadata": {}, + "outputs": [], + "source": [ + "import functools as ft\n", + "import itertools as it\n", + "import cytoolz as tl\n", + "from dimod.higherorder.utils import _new_product, as_vartype\n", + "from collections import defaultdict" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "cbb733a7-ea7a-44f8-87d5-2b53c5ea28a7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 16.6 s, sys: 759 ms, total: 17.3 s\n", + "Wall time: 17.3 s\n" + ] + } + ], + "source": [ + "%%time\n", + "idx = defaultdict(\n", + " dict,\n", + " tl.valmap(\n", + " tl.compose(dict, ft.partial(map, tl.second)),\n", + " tl.groupby(\n", + " tl.first,\n", + " (\n", + " (frozenset(pair), item)\n", + " for item in bp.items()\n", + " if len(term := tl.first(item)) >= 3\n", + " for pair in it.combinations(term, 2) ))))" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "fb73bc93-03de-477b-9157-faf63ea0736a", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1275" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(idx)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "b2b90337-0e71-4fec-939e-0999b9e9e3cc", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#idx" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "21d519e4-d50e-46de-8dd6-3b38a495f75e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#bp" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "a522c29b-62b8-4019-b096-cd03e6bc67c4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#terms" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "id": "e6a2909a-6752-46de-a52f-7c5754837c21", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2700" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "que = tl.valmap(tl.compose(set, ft.partial(map, tl.first)), tl.groupby(tl.second, tl.valmap(len, idx).items()))\n", + "most = max(que)\n", + "most" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "8b50b60f-64f1-4f8a-ace0-af13fe2e5dbd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "frozenset({'H', 'a'})" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "que[most].pop()" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "f8dbcabd-74d7-43c2-b6a0-d30628e6e5e1", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "set()" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "que[most]" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "52a46763-7cd9-491c-8608-88982806650b", + "metadata": {}, + "outputs": [], + "source": [ + "constraints = []\n", + "reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", + "pair, terms = tl.topk(1, idx.items(), tl.compose(len,tl.second))[0]\n", + "p = _new_product(bp.variables, *pair)\n", + "constraints.append((pair, p))\n", + "del idx[pair]\n", + "pset = {p}" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "365b65f0-41c1-4dbb-8bab-aea72369c98a", + "metadata": {}, + "outputs": [], + "source": [ + "for term, bias in terms.items():\n", + " for pair2 in map(frozenset, (it.combinations(term, 2))):\n", + " if pair2 != pair:\n", + " del idx[pair2][term]\n", + " base_term = term - pair\n", + " new_term = base_term | pset\n", + " if len(new_term) <= 3:\n", + " reduced_terms.append((new_term, bias))\n", + " else:\n", + " for pair3 in map(frozenset, it.combinations(new_term, 2)):\n", + " idx[pair3][new_term] = bias" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "6999b196-287e-4454-981d-4217a0135b1c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#reduced_terms" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "33266725-1494-4ffb-9855-cba3e8f1d36c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(frozenset({'H', 'a'}), 'a*H')]" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "constraints" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "186eb239-28d8-4f49-953c-ef168d371060", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "#terms" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "id": "42cb3775-6408-48e7-adc4-e612c314b0ad", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "((frozenset({'p', 'w'}), 2673),\n", + " (frozenset({'I', 'X'}), 2670),\n", + " (frozenset({'F', 'I'}), 2668),\n", + " (frozenset({'K', 'L'}), 2665),\n", + " (frozenset({'K', 'z'}), 2664))" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tl.topk(5, tl.valmap(len, idx).items(), tl.second)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "28138875-8a2d-42a2-b102-85a10c387ac0", + "metadata": {}, + "outputs": [], + "source": [ + "def reduce_terms(bp):\n", + " variables = bp.variables\n", + " constraints = []\n", + " reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", + "\n", + " idx = defaultdict(\n", + " dict,\n", + " tl.valmap(\n", + " tl.compose(dict, ft.partial(map, tl.second)),\n", + " tl.groupby(\n", + " tl.first,\n", + " (\n", + " (frozenset(pair), item)\n", + " for item in bp.items()\n", + " if len(term := tl.first(item)) >= 3\n", + " for pair in it.combinations(term, 2) ))))\n", + "\n", + " que = defaultdict(\n", + " set,\n", + " tl.valmap(\n", + " tl.compose(set, ft.partial(map, tl.first)),\n", + " tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", + "\n", + " while idx:\n", + " new_pairs = set()\n", + " most = max(que)\n", + " \n", + " #print(most, que[most])\n", + " #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items())\n", + " #pair, terms = max(idx.items(), key=tl.compose(len,tl.second))\n", + " \n", + " que_most = que[most]\n", + " pair = que_most.pop()\n", + " if not que_most:\n", + " del que[most]\n", + " terms = idx[pair]\n", + " \n", + " p = _new_product(variables, *pair)\n", + " constraints.append((pair, p))\n", + " del idx[pair]\n", + " pset = {p}\n", + "\n", + " for term, bias in terms.items():\n", + " for pair2 in map(frozenset, (it.combinations(term, 2))):\n", + " if pair2 != pair:\n", + " if pair2 & pair:\n", + " count = len(idx[pair2])\n", + " que_count = que[count]\n", + " que_count.remove(pair2)\n", + " if not que_count:\n", + " del que[count]\n", + " if count > 1:\n", + " que[count - 1].add(pair2)\n", + " idx_pair2 = idx[pair2]\n", + " del idx_pair2[term]\n", + " if not idx_pair2:\n", + " del idx[pair2]\n", + " \n", + " new_term = (term - pair) | pset\n", + " if len(new_term) <= 2:\n", + " reduced_terms.append((new_term, bias))\n", + " else:\n", + " for new_pair in map(frozenset, it.combinations(new_term, 2)):\n", + " idx[new_pair][new_term] = bias\n", + " if p in new_pair:\n", + " new_pairs.add(new_pair)\n", + " \n", + " for new_pair in new_pairs:\n", + " que[len(idx[new_pair])].add(new_pair)\n", + "\n", + " return reduced_terms, constraints" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "id": "faee8bfe-222d-447d-8e10-3e03e9dbb9fb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + }, + { + "data": { + "text/plain": [ + " 25423105 function calls in 81.671 seconds\n", + "\n", + " Ordered by: cumulative time\n", + "\n", + " ncalls tottime percall cumtime percall filename:lineno(function)\n", + " 1 0.000 0.000 81.671 81.671 {built-in method builtins.exec}\n", + " 1 0.003 0.003 81.671 81.671 :1()\n", + " 1 64.379 64.379 81.668 81.668 4179918042.py:1(reduce_terms)\n", + " 3269823 12.406 0.000 12.460 0.000 4179918042.py:12()\n", + " 5924056 2.249 0.000 2.249 0.000 {method 'remove' of 'set' objects}\n", + " 8983666 1.714 0.000 1.714 0.000 {method 'add' of 'set' objects}\n", + " 6728919 0.597 0.000 0.597 0.000 {built-in method builtins.len}\n", + " 58467 0.069 0.000 0.119 0.000 utils.py:88(_new_product)\n", + " 58467 0.074 0.000 0.074 0.000 {built-in method builtins.max}\n", + " 36938 0.029 0.000 0.070 0.000 _collections_abc.py:742(__iter__)\n", + " 36936 0.025 0.000 0.041 0.000 polynomial.py:153(__getitem__)\n", + " 58467 0.040 0.000 0.040 0.000 {method 'format' of 'str' objects}\n", + " 1 0.008 0.008 0.029 0.029 4179918042.py:4()\n", + " 76544 0.022 0.000 0.022 0.000 {method 'append' of 'list' objects}\n", + " 58467 0.019 0.000 0.019 0.000 {method 'pop' of 'set' objects}\n", + " 36936 0.011 0.000 0.016 0.000 polynomial.py:35(asfrozenset)\n", + " 1 0.001 0.001 0.011 0.011 polynomial.py:202(variables)\n", + " 1 0.010 0.010 0.010 0.010 {method 'union' of 'set' objects}\n", + " 58468 0.009 0.000 0.009 0.000 {method 'items' of 'dict' objects}\n", + " 36936 0.005 0.000 0.005 0.000 {built-in method builtins.isinstance}\n", + " 2 0.000 0.000 0.000 0.000 _collections_abc.py:676(items)\n", + " 2 0.000 0.000 0.000 0.000 polynomial.py:156(__iter__)\n", + " 2 0.000 0.000 0.000 0.000 _collections_abc.py:698(__init__)\n", + " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}\n", + " 2 0.000 0.000 0.000 0.000 {built-in method builtins.iter}" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%prun -s cumtime -l 30 reduced_terms, constraints = reduce_terms(bp)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "0b9b2c67-05fa-4a86-8c3a-acc15119e861", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(18468, 58467)" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(reduced_terms), len(constraints)" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "id": "179f7b4b-7895-4a12-824b-0f42c855727e", + "metadata": {}, + "outputs": [], + "source": [ + "#%prun -s cumtime -l 30 bqm = dimod.make_quadratic(bp, 1000, 'BINARY')" + ] + }, + { + "cell_type": "code", + "execution_count": 56, + "id": "9c4d1250-75ad-422a-8f20-04af19be39f7", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "import itertools\n", + "import warnings\n", + "\n", + "from collections import Counter\n", + "\n", + "import numpy as np\n", + "\n", + "\n", + "from dimod.higherorder.utils import _new_product, as_vartype, _binary_product, _new_aux, _spin_product\n", + "print(_binary_product)\n", + "from dimod.binary_quadratic_model import BinaryQuadraticModel\n", + "from dimod.higherorder.polynomial import BinaryPolynomial\n", + "from dimod.sampleset import as_samples\n", + "from dimod.vartypes import as_vartype, Vartype\n", + "\n", + "def make_quadratic(poly, strength, vartype=None, bqm=None):\n", + " \"\"\"Create a binary quadratic model from a higher order polynomial.\n", + "\n", + " Args:\n", + " poly (dict):\n", + " Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of\n", + " variables and `bias` the associated bias.\n", + "\n", + " strength (float):\n", + " The energy penalty for violating the prodcut constraint.\n", + " Insufficient strength can result in the binary quadratic model not\n", + " having the same minimizations as the polynomial.\n", + "\n", + " vartype (:class:`.Vartype`/str/set, optional):\n", + " Variable type for the binary quadratic model. Accepted input values:\n", + "\n", + " * :class:`.Vartype.SPIN`, ``'SPIN'``, ``{-1, 1}``\n", + " * :class:`.Vartype.BINARY`, ``'BINARY'``, ``{0, 1}``\n", + "\n", + " If `bqm` is provided, `vartype` is not required.\n", + "\n", + " bqm (:class:`.BinaryQuadraticModel`, optional):\n", + " The terms of the reduced polynomial are added to this binary quadratic model.\n", + " If not provided, a new binary quadratic model is created.\n", + "\n", + " Returns:\n", + " :class:`.BinaryQuadraticModel`\n", + "\n", + " Examples:\n", + "\n", + " >>> poly = {(0,): -1, (1,): 1, (2,): 1.5, (0, 1): -1, (0, 1, 2): -2}\n", + " >>> bqm = dimod.make_quadratic(poly, 5.0, dimod.SPIN)\n", + "\n", + " \"\"\"\n", + " if vartype is None:\n", + " if bqm is None:\n", + " raise ValueError(\"one of vartype or bqm must be provided\")\n", + " else:\n", + " vartype = bqm.vartype\n", + " else:\n", + " vartype = as_vartype(vartype) # handle other vartype inputs\n", + " if bqm is None:\n", + " bqm = BinaryQuadraticModel.empty(vartype)\n", + " else:\n", + " bqm = bqm.change_vartype(vartype, inplace=False)\n", + "\n", + " # for backwards compatibility, add an info field\n", + " if not hasattr(bqm, 'info'):\n", + " bqm.info = {}\n", + " bqm.info['reduction'] = {}\n", + "\n", + " if poly.vartype !=vartype:\n", + " poly = BinaryPolynomial(poly, vartype=vartype)\n", + "\n", + " variables = set().union(*poly)\n", + " reduced_terms, constraints = dimod.higherorder.utils.reduce_terms(poly)\n", + " \n", + " for (u, v), p in constraints:\n", + "\n", + " # add a constraint enforcing the relationship between p == u*v\n", + " if vartype is Vartype.BINARY:\n", + " constraint = _binary_product([u, v, p])\n", + " bqm.info['reduction'][(u, v)] = {'product': p}\n", + " elif vartype is Vartype.SPIN:\n", + " aux = _new_aux(variables, u, v) # need an aux in SPIN-space\n", + " constraint = _spin_product([u, v, p, aux])\n", + " bqm.info['reduction'][(u, v)] = {'product': p, 'auxiliary': aux}\n", + " else:\n", + " raise RuntimeError(\"unknown vartype: {!r}\".format(vartype))\n", + "\n", + " # scale constraint and update the polynomial with it\n", + " constraint.scale(strength)\n", + " for v, bias in constraint.linear.items():\n", + " bqm.add_variable(v, bias)\n", + " for uv, bias in constraint.quadratic.items():\n", + " bqm.add_interaction(*uv, bias)\n", + " bqm.offset += constraint.offset\n", + "\n", + " for term, bias in reduced_terms:\n", + " if len(term) == 2:\n", + " bqm.add_interaction(*term , bias)\n", + " elif len(term) == 1:\n", + " bqm.add_variable(*term, bias)\n", + " elif len(term) == 0:\n", + " bqm.offset += bias\n", + " else:\n", + " # still has higher order terms, this shouldn't happen\n", + " msg = ('Internal error: not all higher-order terms were reduced. '\n", + " 'Please file a bug report.')\n", + " raise RuntimeError(msg)\n", + "\n", + " return bqm" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "id": "9ca15f52-6ab1-4743-9c3f-3293512dc758", + "metadata": {}, + "outputs": [], + "source": [ + "zz = set(range(4))" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "24d32eb7-61af-4c89-80bf-87583d1d9a65", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/tmp/ipykernel_5226/2794073046.py:92: DeprecationWarning: BinaryQuadraticModel.add_offset(b) is deprecated. Please use bqm.offset += b.\n" + ] + }, + { + "data": { + "text/plain": [ + "Timer unit: 1e-06 s\n", + "\n", + "Total time: 0.041943 s\n", + "File: /home/daniel/dimod/dimod/higherorder/utils.py\n", + "Function: reduce_terms at line 106\n", + "\n", + "Line # Hits Time Per Hit % Time Line Contents\n", + "==============================================================\n", + " 106 def reduce_terms(bp):\n", + " 107 1 7.0 7.0 0.0 variables = bp.variables\n", + " 108 1 1.0 1.0 0.0 constraints = []\n", + " 109 1 16.0 16.0 0.0 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", + " 110 \n", + " 111 2 17.0 8.5 0.0 idx = defaultdict(\n", + " 112 1 1.0 1.0 0.0 dict,\n", + " 113 2 636.0 318.0 1.5 tl.valmap(\n", + " 114 1 8.0 8.0 0.0 tl.compose(dict, ft.partial(map, tl.second)),\n", + " 115 2 510.0 255.0 1.2 tl.groupby(\n", + " 116 1 1.0 1.0 0.0 tl.first,\n", + " 117 2 3.0 1.5 0.0 (\n", + " 118 (frozenset(pair), item)\n", + " 119 1 3.0 3.0 0.0 for item in bp.items()\n", + " 120 if len(term := tl.first(item)) >= 3\n", + " 121 for pair in it.combinations(term, 2) ))))\n", + " 122 \n", + " 123 2 4.0 2.0 0.0 que = defaultdict(\n", + " 124 1 1.0 1.0 0.0 set,\n", + " 125 2 48.0 24.0 0.1 tl.valmap(\n", + " 126 1 5.0 5.0 0.0 tl.compose(set, ft.partial(map, tl.first)),\n", + " 127 1 94.0 94.0 0.2 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", + " 128 \n", + " 129 23 28.0 1.2 0.1 while idx:\n", + " 130 22 63.0 2.9 0.2 new_pairs = set()\n", + " 131 22 75.0 3.4 0.2 most = max(que)\n", + " 132 \n", + " 133 #print(most, que[most])\n", + " 134 #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items())\n", + " 135 #pair, terms = max(idx.items(), key=tl.compose(len,tl.second))\n", + " 136 \n", + " 137 22 26.0 1.2 0.1 que_most = que[most]\n", + " 138 22 43.0 2.0 0.1 pair = que_most.pop()\n", + " 139 22 30.0 1.4 0.1 if not que_most:\n", + " 140 del que[most]\n", + " 141 22 41.0 1.9 0.1 terms = idx[pair]\n", + " 142 \n", + " 143 22 206.0 9.4 0.5 p = _new_product(variables, *pair)\n", + " 144 22 44.0 2.0 0.1 constraints.append((pair, p))\n", + " 145 22 37.0 1.7 0.1 del idx[pair]\n", + " 146 22 33.0 1.5 0.1 pset = {p}\n", + " 147 \n", + " 148 44 141.0 3.2 0.3 for term, bias in terms.items():\n", + " 149 2321 3503.0 1.5 8.4 for pair2 in map(frozenset, (it.combinations(term, 2))):\n", + " 150 2299 2846.0 1.2 6.8 if pair2 != pair:\n", + " 151 2277 3199.0 1.4 7.6 if pair2 & pair:\n", + " 152 506 981.0 1.9 2.3 count = len(idx[pair2])\n", + " 153 506 604.0 1.2 1.4 que_count = que[count]\n", + " 154 506 1210.0 2.4 2.9 que_count.remove(pair2)\n", + " 155 506 594.0 1.2 1.4 if not que_count:\n", + " 156 1 1.0 1.0 0.0 del que[count]\n", + " 157 506 925.0 1.8 2.2 if count > 1:\n", + " 158 que[count - 1].add(pair2)\n", + " 159 2277 4707.0 2.1 11.2 idx_pair2 = idx[pair2]\n", + " 160 2277 3150.0 1.4 7.5 del idx_pair2[term]\n", + " 161 2277 2594.0 1.1 6.2 if not idx_pair2:\n", + " 162 2277 4687.0 2.1 11.2 del idx[pair2]\n", + " 163 \n", + " 164 22 109.0 5.0 0.3 new_term = (term - pair) | pset\n", + " 165 22 39.0 1.8 0.1 if len(new_term) <= 2:\n", + " 166 1 2.0 2.0 0.0 reduced_terms.append((new_term, bias))\n", + " 167 else:\n", + " 168 2044 3253.0 1.6 7.8 for new_pair in map(frozenset, it.combinations(new_term, 2)):\n", + " 169 2023 3603.0 1.8 8.6 idx[new_pair][new_term] = bias\n", + " 170 2023 2528.0 1.2 6.0 if p in new_pair:\n", + " 171 252 350.0 1.4 0.8 new_pairs.add(new_pair)\n", + " 172 \n", + " 173 274 360.0 1.3 0.9 for new_pair in new_pairs:\n", + " 174 252 575.0 2.3 1.4 que[len(idx[new_pair])].add(new_pair)\n", + " 175 \n", + " 176 1 1.0 1.0 0.0 return reduced_terms, constraints" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%lprun -fdimod.higherorder.utils.reduce_terms bqm = make_quadratic(BPnew({term: 1}, 'SPIN'), strength=5, vartype='SPIN')" + ] + }, + { + "cell_type": "code", + "execution_count": 57, + "id": "1934c5e7-5e31-4939-aae5-e23f8ede4ea0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Timer unit: 1e-06 s\n", + "\n", + "Total time: 346.663 s\n", + "File: /home/daniel/dimod/dimod/higherorder/utils.py\n", + "Function: reduce_terms at line 106\n", + "\n", + "Line # Hits Time Per Hit % Time Line Contents\n", + "==============================================================\n", + " 106 def reduce_terms(bp):\n", + " 107 1 19566.0 19566.0 0.0 variables = bp.variables\n", + " 108 1 7.0 7.0 0.0 constraints = []\n", + " 109 1 37591.0 37591.0 0.0 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", + " 110 \n", + " 111 2 189.0 94.5 0.0 idx = defaultdict(\n", + " 112 1 2.0 2.0 0.0 dict,\n", + " 113 2 3424542.0 1712271.0 1.0 tl.valmap(\n", + " 114 1 46.0 46.0 0.0 tl.compose(dict, ft.partial(map, tl.second)),\n", + " 115 2 18779065.0 9389532.5 5.4 tl.groupby(\n", + " 116 1 1.0 1.0 0.0 tl.first,\n", + " 117 2 6.0 3.0 0.0 (\n", + " 118 (frozenset(pair), item)\n", + " 119 1 11.0 11.0 0.0 for item in bp.items()\n", + " 120 if len(term := tl.first(item)) >= 3\n", + " 121 for pair in it.combinations(term, 2) ))))\n", + " 122 \n", + " 123 2 10.0 5.0 0.0 que = defaultdict(\n", + " 124 1 1.0 1.0 0.0 set,\n", + " 125 2 434.0 217.0 0.0 tl.valmap(\n", + " 126 1 9.0 9.0 0.0 tl.compose(set, ft.partial(map, tl.first)),\n", + " 127 1 612.0 612.0 0.0 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", + " 128 \n", + " 129 58468 58998.0 1.0 0.0 while idx:\n", + " 130 58467 92099.0 1.6 0.0 new_pairs = set()\n", + " 131 58467 156064.0 2.7 0.0 most = max(que)\n", + " 132 \n", + " 133 #print(most, que[most])\n", + " 134 #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items())\n", + " 135 #pair, terms = max(idx.items(), key=tl.compose(len,tl.second))\n", + " 136 \n", + " 137 58467 64757.0 1.1 0.0 que_most = que[most]\n", + " 138 58467 79539.0 1.4 0.0 pair = que_most.pop()\n", + " 139 58467 56860.0 1.0 0.0 if not que_most:\n", + " 140 311 338.0 1.1 0.0 del que[most]\n", + " 141 58467 380892.0 6.5 0.1 terms = idx[pair]\n", + " 142 \n", + " 143 58467 304086.0 5.2 0.1 p = _new_product(variables, *pair)\n", + " 144 58467 82767.0 1.4 0.0 constraints.append((pair, p))\n", + " 145 58467 78700.0 1.3 0.0 del idx[pair]\n", + " 146 58467 68703.0 1.2 0.0 pset = {p}\n", + " 147 \n", + " 148 348184 682430.0 2.0 0.2 for term, bias in terms.items():\n", + " 149 26416713 31093376.0 1.2 9.0 for pair2 in map(frozenset, (it.combinations(term, 2))):\n", + " 150 26126996 23664115.0 0.9 6.8 if pair2 != pair:\n", + " 151 25837279 24898516.0 1.0 7.2 if pair2 & pair:\n", + " 152 5924056 10157809.0 1.7 2.9 count = len(idx[pair2])\n", + " 153 5924056 6996866.0 1.2 2.0 que_count = que[count]\n", + " 154 5924056 10361604.0 1.7 3.0 que_count.remove(pair2)\n", + " 155 5924056 5192684.0 0.9 1.5 if not que_count:\n", + " 156 1294711 1264056.0 1.0 0.4 del que[count]\n", + " 157 5924056 5275174.0 0.9 1.5 if count > 1:\n", + " 158 5503038 8409122.0 1.5 2.4 que[count - 1].add(pair2)\n", + " 159 25837279 37128294.0 1.4 10.7 idx_pair2 = idx[pair2]\n", + " 160 25837279 38704563.0 1.5 11.2 del idx_pair2[term]\n", + " 161 25837279 21610041.0 0.8 6.2 if not idx_pair2:\n", + " 162 810097 956368.0 1.2 0.3 del idx[pair2]\n", + " 163 \n", + " 164 289717 1127561.0 3.9 0.3 new_term = (term - pair) | pset\n", + " 165 289717 379470.0 1.3 0.1 if len(new_term) <= 2:\n", + " 166 18077 27904.0 1.5 0.0 reduced_terms.append((new_term, bias))\n", + " 167 else:\n", + " 168 23128814 30146342.0 1.3 8.7 for new_pair in map(frozenset, it.combinations(new_term, 2)):\n", + " 169 22857174 40166576.0 1.8 11.6 idx[new_pair][new_term] = bias\n", + " 170 22857174 20126136.0 0.9 5.8 if p in new_pair:\n", + " 171 2943951 3287438.0 1.1 0.9 new_pairs.add(new_pair)\n", + " 172 \n", + " 173 536677 555879.0 1.0 0.2 for new_pair in new_pairs:\n", + " 174 478210 764707.0 1.6 0.2 que[len(idx[new_pair])].add(new_pair)\n", + " 175 \n", + " 176 1 1.0 1.0 0.0 return reduced_terms, constraints" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%lprun -fdimod.higherorder.utils.reduce_terms bqm = make_quadratic(bp, strength=5, vartype=bp.vartype)" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "id": "1f1a5a0c-5a2f-4227-9f4b-2b3f4f696ce2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 6.21 ms, sys: 93 µs, total: 6.3 ms\n", + "Wall time: 6.09 ms\n" + ] + }, + { + "data": { + "text/plain": [ + "68" + ] + }, + "execution_count": 45, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%time len(dimod.make_quadratic(BPnew({term: 1}, 'SPIN'), strength=5, vartype='SPIN'))" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "1963c838-558b-4257-81d2-968c9648ea14", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[0;31mSignature:\u001b[0m \u001b[0mmake_quadratic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstrength\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mSource:\u001b[0m \n", + "\u001b[0;32mdef\u001b[0m \u001b[0mmake_quadratic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstrength\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;34m\"\"\"Create a binary quadratic model from a higher order polynomial.\u001b[0m\n", + "\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m Args:\u001b[0m\n", + "\u001b[0;34m poly (dict):\u001b[0m\n", + "\u001b[0;34m Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of\u001b[0m\n", + "\u001b[0;34m variables and `bias` the associated bias.\u001b[0m\n", + "\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m strength (float):\u001b[0m\n", + "\u001b[0;34m The energy penalty for violating the prodcut constraint.\u001b[0m\n", + "\u001b[0;34m Insufficient strength can result in the binary quadratic model not\u001b[0m\n", + "\u001b[0;34m having the same minimizations as the polynomial.\u001b[0m\n", + "\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m vartype (:class:`.Vartype`/str/set, optional):\u001b[0m\n", + "\u001b[0;34m Variable type for the binary quadratic model. Accepted input values:\u001b[0m\n", + "\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m * :class:`.Vartype.SPIN`, ``'SPIN'``, ``{-1, 1}``\u001b[0m\n", + "\u001b[0;34m * :class:`.Vartype.BINARY`, ``'BINARY'``, ``{0, 1}``\u001b[0m\n", + "\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m If `bqm` is provided, `vartype` is not required.\u001b[0m\n", + "\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m bqm (:class:`.BinaryQuadraticModel`, optional):\u001b[0m\n", + "\u001b[0;34m The terms of the reduced polynomial are added to this binary quadratic model.\u001b[0m\n", + "\u001b[0;34m If not provided, a new binary quadratic model is created.\u001b[0m\n", + "\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m Returns:\u001b[0m\n", + "\u001b[0;34m :class:`.BinaryQuadraticModel`\u001b[0m\n", + "\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m Examples:\u001b[0m\n", + "\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m >>> poly = {(0,): -1, (1,): 1, (2,): 1.5, (0, 1): -1, (0, 1, 2): -2}\u001b[0m\n", + "\u001b[0;34m >>> bqm = dimod.make_quadratic(poly, 5.0, dimod.SPIN)\u001b[0m\n", + "\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mbqm\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"one of vartype or bqm must be provided\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mas_vartype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# handle other vartype inputs\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mbqm\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mBinaryQuadraticModel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mempty\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mchange_vartype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minplace\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;31m# for backwards compatibility, add an info field\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mhasattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbqm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'info'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'reduction'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvartype\u001b[0m \u001b[0;34m!=\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mpoly\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mBinaryPolynomial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mvariables\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0munion\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mreduced_terms\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconstraints\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdimod\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhigherorder\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreduce_terms\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mconstraints\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;31m# add a constraint enforcing the relationship between p == u*v\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mVartype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mBINARY\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mconstraint\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_binary_product\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'reduction'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m'product'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mVartype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSPIN\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0maux\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_new_aux\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariables\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# need an aux in SPIN-space\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mconstraint\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_spin_product\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maux\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'reduction'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m'product'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'auxiliary'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0maux\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"unknown vartype: {!r}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;31m# scale constraint and update the polynomial with it\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mscale\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstrength\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinear\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_variable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0muv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mquadratic\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_interaction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0muv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_offset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moffset\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mreduced_terms\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_interaction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mterm\u001b[0m \u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_variable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moffset\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;31m# still has higher order terms, this shouldn't happen\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mmsg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'Internal error: not all higher-order terms were reduced. '\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;34m'Please file a bug report.'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mFile:\u001b[0m /tmp/ipykernel_5226/2794073046.py\n", + "\u001b[0;31mType:\u001b[0m function\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "make_quadratic??" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "ed0769ec-6d1b-40d2-b110-989f2f068c86", + "metadata": {}, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (3330683553.py, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_5226/3330683553.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m BinaryPolynomial.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "BinaryPolynomial." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4d4d5183-1bb3-4b7f-a8ab-4af55b2c55e7", +>>>>>>> Stashed changes + "metadata": {}, + "outputs": [], + "source": [ + "dimod.BQM" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7fdb1794-06f7-4fdf-a346-2533dc78ca63", + "metadata": {}, + "outputs": [], + "source": [ + "itertools" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fac7547a-db9e-4e35-8a5d-99e2aa72d137", + "metadata": {}, + "outputs": [], + "source": [ + "%prun -s cumtime -l 20 make_quadratic(bp, 100, vartype='BINARY')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "78014140-af4d-426f-8969-687e2750cfab", + "metadata": {}, + "outputs": [], + "source": [ + "from dimod.higherorder import utils" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b806c9a1-3690-4eab-8c6b-f200026cbfb9", + "metadata": {}, + "outputs": [], + "source": [ + "%pwd" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "bdb58284-1a2d-4880-93ff-b8dd31134d83", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "False" + ] + }, + "execution_count": 51, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "bool(set())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "629eea9c-0ccd-464c-afa5-de6d6ea071b2", + "metadata": {}, + "outputs": [], + "source": [ + "bool" + ] } ], "metadata": { From 6923abdbda2e6e90f431cbd24732105b885d2c56 Mon Sep 17 00:00:00 2001 From: Daniel Mahler Date: Mon, 20 Sep 2021 23:57:46 -0500 Subject: [PATCH 6/9] new version of make_quadratic - make_queadratic_old temporarily retained --- dimod/higherorder/utils.py | 108 ++++- polynomial-perf.ipynb | 860 ++++++++++++++++++------------------- 2 files changed, 510 insertions(+), 458 deletions(-) diff --git a/dimod/higherorder/utils.py b/dimod/higherorder/utils.py index 83e6da7df..6ec3a98a9 100644 --- a/dimod/higherorder/utils.py +++ b/dimod/higherorder/utils.py @@ -18,12 +18,10 @@ from collections import Counter from collections import defaultdict -import functools as ft -import itertools as it +from functools import partial import cytoolz as tl import numpy as np -import cytoolz as tl from dimod.binary_quadratic_model import BinaryQuadraticModel from dimod.higherorder.polynomial import BinaryPolynomial @@ -111,19 +109,19 @@ def reduce_terms(bp): idx = defaultdict( dict, tl.valmap( - tl.compose(dict, ft.partial(map, tl.second)), + tl.compose(dict, partial(map, tl.second)), tl.groupby( tl.first, ( (frozenset(pair), item) for item in bp.items() if len(term := tl.first(item)) >= 3 - for pair in it.combinations(term, 2) )))) + for pair in itertools.combinations(term, 2) )))) que = defaultdict( set, tl.valmap( - tl.compose(set, ft.partial(map, tl.first)), + tl.compose(set, partial(map, tl.first)), tl.groupby(tl.second, tl.valmap(len, idx).items()))) while idx: @@ -146,7 +144,7 @@ def reduce_terms(bp): pset = {p} for term, bias in terms.items(): - for pair2 in map(frozenset, (it.combinations(term, 2))): + for pair2 in map(frozenset, (itertools.combinations(term, 2))): if pair2 != pair: if pair2 & pair: count = len(idx[pair2]) @@ -165,7 +163,7 @@ def reduce_terms(bp): if len(new_term) <= 2: reduced_terms.append((new_term, bias)) else: - for new_pair in map(frozenset, it.combinations(new_term, 2)): + for new_pair in map(frozenset, itertools.combinations(new_term, 2)): idx[new_pair][new_term] = bias if p in new_pair: new_pairs.add(new_pair) @@ -179,6 +177,100 @@ def reduce_terms(bp): def make_quadratic(poly, strength, vartype=None, bqm=None): """Create a binary quadratic model from a higher order polynomial. + Args: + poly (dict): + Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of + variables and `bias` the associated bias. + + strength (float): + The energy penalty for violating the prodcut constraint. + Insufficient strength can result in the binary quadratic model not + having the same minimizations as the polynomial. + + vartype (:class:`.Vartype`/str/set, optional): + Variable type for the binary quadratic model. Accepted input values: + + * :class:`.Vartype.SPIN`, ``'SPIN'``, ``{-1, 1}`` + * :class:`.Vartype.BINARY`, ``'BINARY'``, ``{0, 1}`` + + If `bqm` is provided, `vartype` is not required. + + bqm (:class:`.BinaryQuadraticModel`, optional): + The terms of the reduced polynomial are added to this binary quadratic model. + If not provided, a new binary quadratic model is created. + + Returns: + :class:`.BinaryQuadraticModel` + + Examples: + + >>> poly = {(0,): -1, (1,): 1, (2,): 1.5, (0, 1): -1, (0, 1, 2): -2} + >>> bqm = dimod.make_quadratic(poly, 5.0, dimod.SPIN) + + """ + if vartype is None: + if bqm is None: + raise ValueError("one of vartype or bqm must be provided") + else: + vartype = bqm.vartype + else: + vartype = as_vartype(vartype) # handle other vartype inputs + if bqm is None: + bqm = BinaryQuadraticModel.empty(vartype) + else: + bqm = bqm.change_vartype(vartype, inplace=False) + + # for backwards compatibility, add an info field + if not hasattr(bqm, 'info'): + bqm.info = {} + bqm.info['reduction'] = {} + + if poly.vartype !=vartype: + poly = BinaryPolynomial(poly, vartype=vartype) + + variables = set().union(*poly) + reduced_terms, constraints = reduce_terms(poly) + + for (u, v), p in constraints: + + # add a constraint enforcing the relationship between p == u*v + if vartype is Vartype.BINARY: + constraint = _binary_product([u, v, p]) + bqm.info['reduction'][(u, v)] = {'product': p} + elif vartype is Vartype.SPIN: + aux = _new_aux(variables, u, v) # need an aux in SPIN-space + constraint = _spin_product([u, v, p, aux]) + bqm.info['reduction'][(u, v)] = {'product': p, 'auxiliary': aux} + else: + raise RuntimeError("unknown vartype: {!r}".format(vartype)) + + # scale constraint and update the polynomial with it + constraint.scale(strength) + for v, bias in constraint.linear.items(): + bqm.add_variable(v, bias) + for uv, bias in constraint.quadratic.items(): + bqm.add_interaction(*uv, bias) + bqm.offset += constraint.offset + + for term, bias in reduced_terms: + if len(term) == 2: + bqm.add_interaction(*term , bias) + elif len(term) == 1: + bqm.add_variable(*term, bias) + elif len(term) == 0: + bqm.offset += bias + else: + # still has higher order terms, this shouldn't happen + msg = ('Internal error: not all higher-order terms were reduced. ' + 'Please file a bug report.') + raise RuntimeError(msg) + + return bqm + + +def make_quadratic_old(poly, strength, vartype=None, bqm=None): + """Create a binary quadratic model from a higher order polynomial. + Args: poly (dict): Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of diff --git a/polynomial-perf.ipynb b/polynomial-perf.ipynb index 52246542f..16cc8b0de 100644 --- a/polynomial-perf.ipynb +++ b/polynomial-perf.ipynb @@ -58,24 +58,14 @@ { "data": { "text/plain": [ -<<<<<<< Updated upstream - "count 193091.000000\n", - "mean 257.945269\n", - "std 256.685709\n", -======= "count 192160.000000\n", "mean 259.199839\n", "std 256.922932\n", ->>>>>>> Stashed changes "min 4.000000\n", "25% 74.000000\n", "50% 179.000000\n", "75% 359.000000\n", -<<<<<<< Updated upstream - "max 3319.000000\n", -======= "max 3174.000000\n", ->>>>>>> Stashed changes "dtype: float64" ] }, @@ -106,18 +96,14 @@ "name": "stdout", "output_type": "stream", "text": [ -<<<<<<< Updated upstream -======= "Saved working directory and index state WIP on binary-polynomial: bc4521f added symbolic arithmetic refactored relabel_variables, to_binary, to_spin filter out 0 coefficient terms in polynomial construction\n", ->>>>>>> Stashed changes "Switched to branch 'main'\n", - "Your branch and 'upstream/main' have diverged,\n", - "and have 1 and 2 different commits each, respectively.\n", - " (use \"git pull\" to merge the remote branch into yours)\n" + "Your branch is up to date with 'origin/main'.\n" ] } ], "source": [ + "!git stash\n", "!git checkout main\n", "#importlib.reload(dimod)" ] @@ -200,27 +186,12 @@ { "data": { "text/plain": [ -<<<<<<< Updated upstream - " 9739394 function calls (9739314 primitive calls) in 28.259 seconds\n", -======= " 9711530 function calls (9711450 primitive calls) in 48.033 seconds\n", ->>>>>>> Stashed changes "\n", " Ordered by: cumulative time\n", " List reduced from 47 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", -<<<<<<< Updated upstream - " 1 0.000 0.000 28.259 28.259 {built-in method builtins.exec}\n", - " 1 0.000 0.000 28.259 28.259 :1()\n", - " 1 0.000 0.000 28.259 28.259 decorators.py:289(new_f)\n", - " 1 2.699 2.699 28.259 28.259 polynomial.py:89(__init__)\n", - " 5492601 24.575 0.000 24.575 0.000 {method 'count' of 'tuple' objects}\n", - " 193091 0.614 0.000 0.645 0.000 polynomial.py:32(asfrozenset)\n", - " 3474226 0.298 0.000 0.298 0.000 {method 'add' of 'set' objects}\n", - " 386184 0.042 0.000 0.042 0.000 {built-in method builtins.len}\n", - " 193101 0.030 0.000 0.030 0.000 {built-in method builtins.isinstance}\n", -======= " 1 0.000 0.000 48.033 48.033 {built-in method builtins.exec}\n", " 1 0.000 0.000 48.033 48.033 :1()\n", " 1 0.000 0.000 48.033 48.033 decorators.py:289(new_f)\n", @@ -230,7 +201,6 @@ " 3460625 0.690 0.000 0.690 0.000 {method 'add' of 'set' objects}\n", " 384322 0.079 0.000 0.079 0.000 {built-in method builtins.len}\n", " 192170 0.060 0.000 0.060 0.000 {built-in method builtins.isinstance}\n", ->>>>>>> Stashed changes " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", @@ -240,13 +210,8 @@ " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", -<<<<<<< Updated upstream - " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", - " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)" -======= " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)\n", " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)" ->>>>>>> Stashed changes ] }, "metadata": {}, @@ -292,20 +257,6 @@ " \n", " \n", " count\n", -<<<<<<< Updated upstream - " 182233.000000\n", - " 182233.000000\n", - " \n", - " \n", - " mean\n", - " 18.934386\n", - " 1.059583\n", - " \n", - " \n", - " std\n", - " 7.545862\n", - " 9.112464\n", -======= " 181561.000000\n", " 181561.000000\n", " \n", @@ -318,7 +269,6 @@ " std\n", " 7.552280\n", " 8.721284\n", ->>>>>>> Stashed changes " \n", " \n", " min\n", @@ -342,13 +292,8 @@ " \n", " \n", " max\n", -<<<<<<< Updated upstream - " 40.000000\n", - " 3851.000000\n", -======= " 42.000000\n", " 3677.000000\n", ->>>>>>> Stashed changes " \n", " \n", "\n", @@ -356,24 +301,14 @@ ], "text/plain": [ " 0 1\n", -<<<<<<< Updated upstream - "count 182233.000000 182233.000000\n", - "mean 18.934386 1.059583\n", - "std 7.545862 9.112464\n", -======= "count 181561.000000 181561.000000\n", "mean 18.931703 1.058377\n", "std 7.552280 8.721284\n", ->>>>>>> Stashed changes "min 1.000000 1.000000\n", "25% 13.000000 1.000000\n", "50% 20.000000 1.000000\n", "75% 25.000000 1.000000\n", -<<<<<<< Updated upstream - "max 40.000000 3851.000000" -======= "max 42.000000 3677.000000" ->>>>>>> Stashed changes ] }, "execution_count": 9, @@ -386,8 +321,6 @@ ] }, { -<<<<<<< Updated upstream -======= "cell_type": "code", "execution_count": null, "id": "6f8463b3-a6fe-4841-918f-33743295181f", @@ -675,7 +608,6 @@ ] }, { ->>>>>>> Stashed changes "cell_type": "markdown", "id": "81473689-9ece-45a7-85a0-389d0418be3e", "metadata": { @@ -688,18 +620,40 @@ }, { "cell_type": "code", -<<<<<<< Updated upstream - "execution_count": 10, -======= "execution_count": 20, ->>>>>>> Stashed changes "id": "673fe5b0-5934-4b40-a418-62122e867aa9", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "BYE\n" + ] + }, + { + "ename": "SystemExit", + "evalue": "", + "output_type": "error", + "traceback": [ + "An exception has occurred, use %tb to see the full traceback.\n", + "\u001b[0;31mSystemExit\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/daniel/anaconda3/lib/python3.8/site-packages/IPython/core/interactiveshell.py:3449: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.\n", + " warn(\"To exit: use 'exit', 'quit', or Ctrl-D.\", stacklevel=1)\n" + ] + } + ], "source": [ - "## \n", + "print('BYE')\n", "exit()\n", - "#del BPold" + "raise SystemExit\n", + "print('HI')" ] }, { @@ -722,21 +676,35 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 1, "id": "370178a2-f029-4e9b-b4f7-f4c051df686c", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], "source": [ -<<<<<<< Updated upstream - "import string, random, toolz, pandas, importlib, sys, os" -======= "import string, random, toolz, pandas, importlib, sys, os, cytoolz, toolz, dimod" ->>>>>>> Stashed changes ] }, { "cell_type": "code", "execution_count": 2, + "id": "47e01614-89da-426a-8f4d-a546fe454328", + "metadata": {}, + "outputs": [], + "source": [ + "import itertools as it" + ] + }, + { + "cell_type": "code", + "execution_count": 3, "id": "a2199fbe-fa29-4286-b93a-eadba3b739e3", "metadata": {}, "outputs": [ @@ -744,8 +712,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 122 ms, sys: 20.4 ms, total: 142 ms\n", - "Wall time: 141 ms\n" + "CPU times: user 147 ms, sys: 606 µs, total: 148 ms\n", + "Wall time: 147 ms\n" ] } ], @@ -755,36 +723,25 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "id": "5707eff9-710b-4799-87bc-99bed0eed866", "metadata": {}, "outputs": [ { "data": { "text/plain": [ -<<<<<<< Updated upstream - "count 192325.000000\n", - "mean 258.976607\n", - "std 257.827839\n", - "min 4.000000\n", - "25% 74.000000\n", - "50% 179.000000\n", - "75% 359.000000\n", - "max 3419.000000\n", -======= - "count 19253.000000\n", - "mean 50.940009\n", - "std 51.333538\n", + "count 19393.000000\n", + "mean 50.565049\n", + "std 51.640829\n", "min 0.000000\n", "25% 14.000000\n", "50% 35.000000\n", - "75% 71.000000\n", - "max 459.000000\n", ->>>>>>> Stashed changes + "75% 69.000000\n", + "max 548.000000\n", "dtype: float64" ] }, - "execution_count": 3, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -803,7 +760,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "id": "6f8b616f-1835-4723-83c3-dc189b891a94", "metadata": {}, "outputs": [ @@ -811,32 +768,24 @@ "name": "stdout", "output_type": "stream", "text": [ -<<<<<<< Updated upstream - "M\tpolynomial-perf.ipynb\n", - "Already on 'binary-polynomial'\n", - "Your branch is ahead of 'origin/binary-polynomial' by 1 commit.\n", - " (use \"git push\" to publish your local commits)\n" -======= - "M\tdimod/higherorder/polynomial.py\n", - "M\tdimod/higherorder/utils.py\n", - "D\tpolynomial-perf.ipynb\n", - "Already on 'binary-polynomial'\n", - "Your branch is ahead of 'origin/binary-polynomial' by 1 commit.\n", - " (use \"git push\" to publish your local commits)\n", + "dimod/higherorder/polynomial.py: needs merge\n", + "polynomial-perf.ipynb: needs merge\n", + "error: you need to resolve your current index first\n", "No stash entries found.\n" ->>>>>>> Stashed changes ] } ], "source": [ + "!mv polynomial-perf.ipynb{,.bak}\n", "!git checkout binary-polynomial\n", - "!touch -c ./dimod/higherorder/polynomial.py\n", + "!git stash pop\n", + "#!touch -c ./dimod/higherorder/polynomial.py\n", "#importlib.reload(dimod)" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "id": "6e5ac6a3-5a9a-4147-8909-0b09208d66c2", "metadata": {}, "outputs": [], @@ -846,7 +795,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "id": "b8472b21-b3e6-4c19-b860-d2631dd78065", "metadata": {}, "outputs": [ @@ -862,14 +811,9 @@ "\u001b[0;34m\u001b[0m \u001b[0mpoly\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;31m# we need to aggregate the repeated terms\u001b[0m\u001b[0;34m\u001b[0m\n", -<<<<<<< Updated upstream "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_terms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mterms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdefaultdict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", -======= - "\u001b[0;34m\u001b[0m \u001b[0mterms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdefaultdict\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mfilter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtl\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msecond\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", ->>>>>>> Stashed changes "\u001b[0;34m\u001b[0m \u001b[0mterms\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mfreeze_term\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvartype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", @@ -887,49 +831,27 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "id": "9065a62a-4c71-4f58-843b-65f611bc4848", "metadata": {}, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " " - ] - }, { "data": { "text/plain": [ -<<<<<<< Updated upstream - " 4232729 function calls (4232649 primitive calls) in 3.246 seconds\n", -======= - " 404277 function calls (404197 primitive calls) in 0.299 seconds\n", ->>>>>>> Stashed changes + " 406093 function calls (406013 primitive calls) in 0.221 seconds\n", "\n", " Ordered by: cumulative time\n", " List reduced from 46 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", -<<<<<<< Updated upstream - " 1 0.000 0.000 3.246 3.246 {built-in method builtins.exec}\n", - " 1 0.000 0.000 3.246 3.246 :1()\n", - " 1 0.000 0.000 3.246 3.246 decorators.py:289(new_f)\n", - " 1 0.177 0.177 3.246 3.246 polynomial.py:108(__init__)\n", - " 192325 2.615 0.000 3.069 0.000 polynomial.py:40(freeze_term)\n", - " 3655551 0.427 0.000 0.427 0.000 polynomial.py:47()\n", - " 192335 0.015 0.000 0.015 0.000 {built-in method builtins.isinstance}\n", - " 192326 0.012 0.000 0.012 0.000 {method 'items' of 'dict' objects}\n", -======= - " 1 0.000 0.000 0.299 0.299 {built-in method builtins.exec}\n", - " 1 0.000 0.000 0.299 0.299 :1()\n", - " 1 0.001 0.001 0.299 0.299 decorators.py:289(new_f)\n", - " 1 0.028 0.028 0.298 0.298 polynomial.py:108(__init__)\n", - " 19253 0.198 0.000 0.269 0.000 polynomial.py:40(freeze_term)\n", - " 346315 0.067 0.000 0.067 0.000 polynomial.py:47()\n", - " 19263 0.003 0.000 0.003 0.000 {built-in method builtins.isinstance}\n", - " 19254 0.002 0.000 0.002 0.000 {method 'items' of 'dict' objects}\n", ->>>>>>> Stashed changes + " 1 0.000 0.000 0.221 0.221 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.221 0.221 :1()\n", + " 1 0.000 0.000 0.221 0.221 decorators.py:289(new_f)\n", + " 1 0.016 0.016 0.221 0.221 polynomial.py:108(__init__)\n", + " 19393 0.152 0.000 0.205 0.000 polynomial.py:40(freeze_term)\n", + " 347711 0.050 0.000 0.050 0.000 polynomial.py:47()\n", + " 19403 0.002 0.000 0.002 0.000 {built-in method builtins.isinstance}\n", + " 19394 0.002 0.000 0.002 0.000 {method 'items' of 'dict' objects}\n", " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", @@ -938,20 +860,21 @@ " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", - " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", -<<<<<<< Updated upstream - " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)\n", - " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)" -======= - " 1 0.000 0.000 0.000 0.000 :1(__new__)\n", - " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}\n", - " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)" ->>>>>>> Stashed changes + " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", + " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)\n", + " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)" ] }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] } ], "source": [ @@ -961,7 +884,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "id": "b9f0d049-5b6f-4521-a6c9-f6d0f529b8a8", "metadata": {}, "outputs": [ @@ -993,33 +916,18 @@ " \n", " \n", " count\n", -<<<<<<< Updated upstream - " 181650.000000\n", - " 181650.000000\n", - " \n", - " \n", - " mean\n", - " 18.937605\n", - " 1.058767\n", - " \n", - " \n", - " std\n", - " 7.559899\n", - " 8.875054\n", -======= - " 18468.000000\n", - " 18468.000000\n", + " 18602.000000\n", + " 18602.000000\n", " \n", " \n", " mean\n", - " 17.684644\n", - " 1.042506\n", + " 17.624341\n", + " 1.042522\n", " \n", " \n", " std\n", - " 7.686658\n", - " 2.887464\n", ->>>>>>> Stashed changes + " 7.647118\n", + " 2.870007\n", " \n", " \n", " min\n", @@ -1043,43 +951,26 @@ " \n", " \n", " max\n", -<<<<<<< Updated upstream - " 42.000000\n", - " 3742.000000\n", -======= - " 40.000000\n", - " 390.000000\n", ->>>>>>> Stashed changes + " 38.000000\n", + " 389.000000\n", " \n", " \n", "\n", "" ], "text/plain": [ -<<<<<<< Updated upstream - " 0 1\n", - "count 181650.000000 181650.000000\n", - "mean 18.937605 1.058767\n", - "std 7.559899 8.875054\n", - "min 1.000000 1.000000\n", - "25% 13.000000 1.000000\n", - "50% 20.000000 1.000000\n", - "75% 25.000000 1.000000\n", - "max 42.000000 3742.000000" -======= " 0 1\n", - "count 18468.000000 18468.000000\n", - "mean 17.684644 1.042506\n", - "std 7.686658 2.887464\n", + "count 18602.000000 18602.000000\n", + "mean 17.624341 1.042522\n", + "std 7.647118 2.870007\n", "min 0.000000 1.000000\n", "25% 12.000000 1.000000\n", "50% 19.000000 1.000000\n", "75% 24.000000 1.000000\n", - "max 40.000000 390.000000" ->>>>>>> Stashed changes + "max 38.000000 389.000000" ] }, - "execution_count": 8, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -1090,10 +981,6 @@ }, { "cell_type": "code", -<<<<<<< Updated upstream - "execution_count": null, - "id": "e396116b-8b48-4e80-b780-63e6918d75e3", -======= "execution_count": 10, "id": "e396116b-8b48-4e80-b780-63e6918d75e3", "metadata": { @@ -1114,7 +1001,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "1.33 s ± 148 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + "887 ms ± 162 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] }, { @@ -1143,7 +1030,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "689 ms ± 113 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + "1.25 s ± 226 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] }, { @@ -1171,7 +1058,7 @@ { "data": { "text/plain": [ - "1" + "4096" ] }, "execution_count": 13, @@ -1192,7 +1079,7 @@ { "data": { "text/plain": [ - "1" + "4096" ] }, "execution_count": 14, @@ -1238,32 +1125,32 @@ { "data": { "text/plain": [ - " 782622 function calls in 0.242 seconds\n", + " 1832419 function calls (1832414 primitive calls) in 0.652 seconds\n", "\n", " Ordered by: cumulative time\n", - " List reduced from 56 to 20 due to restriction <20>\n", + " List reduced from 67 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 0.242 0.242 {built-in method builtins.exec}\n", - " 1 0.000 0.000 0.242 0.242 :1()\n", - " 1 0.000 0.000 0.242 0.242 polynomial.py:269(relabel_variables)\n", - " 1 0.095 0.095 0.209 0.209 polynomial.py:295()\n", - " 345068 0.069 0.000 0.092 0.000 polynomial.py:296()\n", - " 326604 0.023 0.000 0.023 0.000 {method 'get' of 'dict' objects}\n", - " 18469 0.008 0.000 0.022 0.000 _collections_abc.py:742(__iter__)\n", - " 1 0.000 0.000 0.022 0.022 decorators.py:289(new_f)\n", - " 1 0.017 0.017 0.021 0.021 polynomial.py:108(__init__)\n", - " 18468 0.009 0.000 0.014 0.000 polynomial.py:153(__getitem__)\n", - " 1 0.001 0.001 0.011 0.011 polynomial.py:202(variables)\n", - " 1 0.009 0.009 0.009 0.009 {method 'union' of 'set' objects}\n", - " 18468 0.003 0.000 0.005 0.000 polynomial.py:35(asfrozenset)\n", - " 18468 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", - " 36945 0.003 0.000 0.003 0.000 {built-in method builtins.isinstance}\n", + " 1 0.000 0.000 0.652 0.652 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.652 0.652 :1()\n", + " 2/1 0.301 0.151 0.652 0.652 polynomial.py:236(relabel_variables)\n", + " 692900 0.152 0.000 0.202 0.000 polynomial.py:260()\n", + " 55809 0.033 0.000 0.063 0.000 _collections_abc.py:742(__iter__)\n", + " 655700 0.051 0.000 0.051 0.000 {method 'get' of 'dict' objects}\n", + " 37202 0.025 0.000 0.035 0.000 polynomial.py:162(__setitem__)\n", + " 130210 0.024 0.000 0.031 0.000 polynomial.py:35(asfrozenset)\n", + " 1 0.000 0.000 0.030 0.030 polynomial.py:181(copy)\n", + " 1 0.000 0.000 0.030 0.030 decorators.py:289(new_f)\n", + " 55806 0.018 0.000 0.030 0.000 polynomial.py:153(__getitem__)\n", + " 1 0.010 0.010 0.030 0.030 polynomial.py:108(__init__)\n", + " 37202 0.015 0.000 0.024 0.000 polynomial.py:124(__delitem__)\n", + " 1 0.002 0.002 0.013 0.013 polynomial.py:169(variables)\n", + " 1 0.011 0.011 0.011 0.011 {method 'union' of 'set' objects}\n", + " 148821 0.009 0.000 0.009 0.000 {built-in method builtins.isinstance}\n", + " 18602 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", + " 3 0.000 0.000 0.000 0.000 utilities.py:351(iter_safe_relabels)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", - " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)" + " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)" ] }, "metadata": {}, @@ -1290,32 +1177,32 @@ { "data": { "text/plain": [ - " 782622 function calls in 0.252 seconds\n", + " 1832416 function calls (1832411 primitive calls) in 0.594 seconds\n", "\n", " Ordered by: cumulative time\n", - " List reduced from 56 to 20 due to restriction <20>\n", + " List reduced from 64 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 0.252 0.252 {built-in method builtins.exec}\n", - " 1 0.000 0.000 0.252 0.252 :1()\n", - " 1 0.000 0.000 0.252 0.252 polynomial.py:269(relabel_variables)\n", - " 1 0.103 0.103 0.225 0.225 polynomial.py:295()\n", - " 345068 0.073 0.000 0.098 0.000 polynomial.py:296()\n", - " 326604 0.025 0.000 0.025 0.000 {method 'get' of 'dict' objects}\n", - " 18469 0.009 0.000 0.024 0.000 _collections_abc.py:742(__iter__)\n", - " 1 0.000 0.000 0.017 0.017 decorators.py:289(new_f)\n", - " 1 0.013 0.013 0.016 0.016 polynomial.py:108(__init__)\n", - " 18468 0.010 0.000 0.015 0.000 polynomial.py:153(__getitem__)\n", - " 1 0.001 0.001 0.010 0.010 polynomial.py:202(variables)\n", + " 1 0.000 0.000 0.594 0.594 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.594 0.594 :1()\n", + " 2/1 0.227 0.113 0.594 0.594 polynomial.py:236(relabel_variables)\n", + " 692900 0.154 0.000 0.208 0.000 polynomial.py:260()\n", + " 55809 0.036 0.000 0.069 0.000 _collections_abc.py:742(__iter__)\n", + " 655700 0.054 0.000 0.054 0.000 {method 'get' of 'dict' objects}\n", + " 37202 0.027 0.000 0.037 0.000 polynomial.py:162(__setitem__)\n", + " 1 0.000 0.000 0.033 0.033 polynomial.py:181(copy)\n", + " 1 0.000 0.000 0.033 0.033 decorators.py:289(new_f)\n", + " 130210 0.024 0.000 0.033 0.000 polynomial.py:35(asfrozenset)\n", + " 1 0.011 0.011 0.033 0.033 polynomial.py:108(__init__)\n", + " 55806 0.020 0.000 0.033 0.000 polynomial.py:153(__getitem__)\n", + " 37202 0.018 0.000 0.027 0.000 polynomial.py:124(__delitem__)\n", + " 148821 0.010 0.000 0.010 0.000 {built-in method builtins.isinstance}\n", + " 1 0.001 0.001 0.010 0.010 polynomial.py:169(variables)\n", " 1 0.009 0.009 0.009 0.009 {method 'union' of 'set' objects}\n", - " 18468 0.004 0.000 0.005 0.000 polynomial.py:35(asfrozenset)\n", - " 18468 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", - " 36945 0.002 0.000 0.002 0.000 {built-in method builtins.isinstance}\n", + " 18602 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", + " 3 0.000 0.000 0.000 0.000 utilities.py:351(iter_safe_relabels)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", - " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)" + " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)" ] }, "metadata": {}, @@ -1434,8 +1321,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 16.6 s, sys: 759 ms, total: 17.3 s\n", - "Wall time: 17.3 s\n" + "CPU times: user 18.1 s, sys: 1.19 s, total: 19.3 s\n", + "Wall time: 19.3 s\n" ] } ], @@ -1520,7 +1407,7 @@ { "data": { "text/plain": [ - "2700" + "2720" ] }, "execution_count": 29, @@ -1543,7 +1430,7 @@ { "data": { "text/plain": [ - "frozenset({'H', 'a'})" + "frozenset({'F', 'J'})" ] }, "execution_count": 30, @@ -1633,7 +1520,7 @@ { "data": { "text/plain": [ - "[(frozenset({'H', 'a'}), 'a*H')]" + "[(frozenset({'F', 'J'}), 'J*F')]" ] }, "execution_count": 35, @@ -1668,11 +1555,11 @@ { "data": { "text/plain": [ - "((frozenset({'p', 'w'}), 2673),\n", - " (frozenset({'I', 'X'}), 2670),\n", - " (frozenset({'F', 'I'}), 2668),\n", - " (frozenset({'K', 'L'}), 2665),\n", - " (frozenset({'K', 'z'}), 2664))" + "((frozenset({'K', 'Y'}), 2689),\n", + " (frozenset({'A', 'T'}), 2680),\n", + " (frozenset({'C', 'l'}), 2674),\n", + " (frozenset({'C', 'p'}), 2671),\n", + " (frozenset({'L', 'M'}), 2670))" ] }, "execution_count": 37, @@ -1780,36 +1667,36 @@ { "data": { "text/plain": [ - " 25423105 function calls in 81.671 seconds\n", + " 25411126 function calls in 70.785 seconds\n", "\n", " Ordered by: cumulative time\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 81.671 81.671 {built-in method builtins.exec}\n", - " 1 0.003 0.003 81.671 81.671 :1()\n", - " 1 64.379 64.379 81.668 81.668 4179918042.py:1(reduce_terms)\n", - " 3269823 12.406 0.000 12.460 0.000 4179918042.py:12()\n", - " 5924056 2.249 0.000 2.249 0.000 {method 'remove' of 'set' objects}\n", - " 8983666 1.714 0.000 1.714 0.000 {method 'add' of 'set' objects}\n", - " 6728919 0.597 0.000 0.597 0.000 {built-in method builtins.len}\n", - " 58467 0.069 0.000 0.119 0.000 utils.py:88(_new_product)\n", - " 58467 0.074 0.000 0.074 0.000 {built-in method builtins.max}\n", - " 36938 0.029 0.000 0.070 0.000 _collections_abc.py:742(__iter__)\n", - " 36936 0.025 0.000 0.041 0.000 polynomial.py:153(__getitem__)\n", - " 58467 0.040 0.000 0.040 0.000 {method 'format' of 'str' objects}\n", - " 1 0.008 0.008 0.029 0.029 4179918042.py:4()\n", - " 76544 0.022 0.000 0.022 0.000 {method 'append' of 'list' objects}\n", - " 58467 0.019 0.000 0.019 0.000 {method 'pop' of 'set' objects}\n", - " 36936 0.011 0.000 0.016 0.000 polynomial.py:35(asfrozenset)\n", - " 1 0.001 0.001 0.011 0.011 polynomial.py:202(variables)\n", + " 1 0.000 0.000 70.785 70.785 {built-in method builtins.exec}\n", + " 1 0.004 0.004 70.785 70.785 :1()\n", + " 1 56.359 56.359 70.781 70.781 4179918042.py:1(reduce_terms)\n", + " 3268667 10.024 0.000 10.063 0.000 4179918042.py:12()\n", + " 5919520 2.057 0.000 2.057 0.000 {method 'remove' of 'set' objects}\n", + " 8977662 1.580 0.000 1.580 0.000 {method 'add' of 'set' objects}\n", + " 6724636 0.548 0.000 0.548 0.000 {built-in method builtins.len}\n", + " 58933 0.045 0.000 0.079 0.000 utils.py:88(_new_product)\n", + " 37206 0.021 0.000 0.053 0.000 _collections_abc.py:742(__iter__)\n", + " 58933 0.036 0.000 0.036 0.000 {built-in method builtins.max}\n", + " 37204 0.020 0.000 0.033 0.000 polynomial.py:153(__getitem__)\n", + " 58933 0.027 0.000 0.027 0.000 {method 'format' of 'str' objects}\n", + " 1 0.007 0.007 0.026 0.026 4179918042.py:4()\n", + " 77142 0.014 0.000 0.014 0.000 {method 'append' of 'list' objects}\n", + " 58933 0.013 0.000 0.013 0.000 {method 'pop' of 'set' objects}\n", + " 37204 0.009 0.000 0.013 0.000 polynomial.py:35(asfrozenset)\n", + " 1 0.001 0.001 0.012 0.012 polynomial.py:169(variables)\n", " 1 0.010 0.010 0.010 0.010 {method 'union' of 'set' objects}\n", - " 58468 0.009 0.000 0.009 0.000 {method 'items' of 'dict' objects}\n", - " 36936 0.005 0.000 0.005 0.000 {built-in method builtins.isinstance}\n", + " 58934 0.006 0.000 0.006 0.000 {method 'items' of 'dict' objects}\n", + " 37204 0.004 0.000 0.004 0.000 {built-in method builtins.isinstance}\n", " 2 0.000 0.000 0.000 0.000 _collections_abc.py:676(items)\n", " 2 0.000 0.000 0.000 0.000 polynomial.py:156(__iter__)\n", " 2 0.000 0.000 0.000 0.000 _collections_abc.py:698(__init__)\n", - " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}\n", - " 2 0.000 0.000 0.000 0.000 {built-in method builtins.iter}" + " 2 0.000 0.000 0.000 0.000 {built-in method builtins.iter}\n", + " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}" ] }, "metadata": {}, @@ -1829,7 +1716,7 @@ { "data": { "text/plain": [ - "(18468, 58467)" + "(18602, 58933)" ] }, "execution_count": 40, @@ -1853,7 +1740,7 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 42, "id": "9c4d1250-75ad-422a-8f20-04af19be39f7", "metadata": {}, "outputs": [ @@ -1861,7 +1748,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "\n" + "\n" ] } ], @@ -1987,97 +1874,90 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 44, "id": "24d32eb7-61af-4c89-80bf-87583d1d9a65", "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/tmp/ipykernel_5226/2794073046.py:92: DeprecationWarning: BinaryQuadraticModel.add_offset(b) is deprecated. Please use bqm.offset += b.\n" - ] - }, { "data": { "text/plain": [ "Timer unit: 1e-06 s\n", "\n", - "Total time: 0.041943 s\n", + "Total time: 0.07269 s\n", "File: /home/daniel/dimod/dimod/higherorder/utils.py\n", "Function: reduce_terms at line 106\n", "\n", "Line # Hits Time Per Hit % Time Line Contents\n", "==============================================================\n", " 106 def reduce_terms(bp):\n", - " 107 1 7.0 7.0 0.0 variables = bp.variables\n", + " 107 1 6.0 6.0 0.0 variables = bp.variables\n", " 108 1 1.0 1.0 0.0 constraints = []\n", - " 109 1 16.0 16.0 0.0 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", + " 109 1 20.0 20.0 0.0 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", " 110 \n", - " 111 2 17.0 8.5 0.0 idx = defaultdict(\n", + " 111 2 24.0 12.0 0.0 idx = defaultdict(\n", " 112 1 1.0 1.0 0.0 dict,\n", - " 113 2 636.0 318.0 1.5 tl.valmap(\n", - " 114 1 8.0 8.0 0.0 tl.compose(dict, ft.partial(map, tl.second)),\n", - " 115 2 510.0 255.0 1.2 tl.groupby(\n", - " 116 1 1.0 1.0 0.0 tl.first,\n", + " 113 2 644.0 322.0 0.9 tl.valmap(\n", + " 114 1 11.0 11.0 0.0 tl.compose(dict, ft.partial(map, tl.second)),\n", + " 115 2 1881.0 940.5 2.6 tl.groupby(\n", + " 116 1 0.0 0.0 0.0 tl.first,\n", " 117 2 3.0 1.5 0.0 (\n", " 118 (frozenset(pair), item)\n", - " 119 1 3.0 3.0 0.0 for item in bp.items()\n", + " 119 1 2.0 2.0 0.0 for item in bp.items()\n", " 120 if len(term := tl.first(item)) >= 3\n", " 121 for pair in it.combinations(term, 2) ))))\n", " 122 \n", - " 123 2 4.0 2.0 0.0 que = defaultdict(\n", - " 124 1 1.0 1.0 0.0 set,\n", - " 125 2 48.0 24.0 0.1 tl.valmap(\n", - " 126 1 5.0 5.0 0.0 tl.compose(set, ft.partial(map, tl.first)),\n", - " 127 1 94.0 94.0 0.2 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", + " 123 2 3.0 1.5 0.0 que = defaultdict(\n", + " 124 1 2.0 2.0 0.0 set,\n", + " 125 2 66.0 33.0 0.1 tl.valmap(\n", + " 126 1 8.0 8.0 0.0 tl.compose(set, ft.partial(map, tl.first)),\n", + " 127 1 112.0 112.0 0.2 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", " 128 \n", - " 129 23 28.0 1.2 0.1 while idx:\n", - " 130 22 63.0 2.9 0.2 new_pairs = set()\n", - " 131 22 75.0 3.4 0.2 most = max(que)\n", + " 129 31 32.0 1.0 0.0 while idx:\n", + " 130 30 83.0 2.8 0.1 new_pairs = set()\n", + " 131 30 85.0 2.8 0.1 most = max(que)\n", " 132 \n", " 133 #print(most, que[most])\n", " 134 #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items())\n", " 135 #pair, terms = max(idx.items(), key=tl.compose(len,tl.second))\n", " 136 \n", - " 137 22 26.0 1.2 0.1 que_most = que[most]\n", - " 138 22 43.0 2.0 0.1 pair = que_most.pop()\n", - " 139 22 30.0 1.4 0.1 if not que_most:\n", + " 137 30 27.0 0.9 0.0 que_most = que[most]\n", + " 138 30 60.0 2.0 0.1 pair = que_most.pop()\n", + " 139 30 31.0 1.0 0.0 if not que_most:\n", " 140 del que[most]\n", - " 141 22 41.0 1.9 0.1 terms = idx[pair]\n", + " 141 30 67.0 2.2 0.1 terms = idx[pair]\n", " 142 \n", - " 143 22 206.0 9.4 0.5 p = _new_product(variables, *pair)\n", - " 144 22 44.0 2.0 0.1 constraints.append((pair, p))\n", - " 145 22 37.0 1.7 0.1 del idx[pair]\n", - " 146 22 33.0 1.5 0.1 pset = {p}\n", + " 143 30 474.0 15.8 0.7 p = _new_product(variables, *pair)\n", + " 144 30 53.0 1.8 0.1 constraints.append((pair, p))\n", + " 145 30 41.0 1.4 0.1 del idx[pair]\n", + " 146 30 38.0 1.3 0.1 pset = {p}\n", " 147 \n", - " 148 44 141.0 3.2 0.3 for term, bias in terms.items():\n", - " 149 2321 3503.0 1.5 8.4 for pair2 in map(frozenset, (it.combinations(term, 2))):\n", - " 150 2299 2846.0 1.2 6.8 if pair2 != pair:\n", - " 151 2277 3199.0 1.4 7.6 if pair2 & pair:\n", - " 152 506 981.0 1.9 2.3 count = len(idx[pair2])\n", - " 153 506 604.0 1.2 1.4 que_count = que[count]\n", - " 154 506 1210.0 2.4 2.9 que_count.remove(pair2)\n", - " 155 506 594.0 1.2 1.4 if not que_count:\n", - " 156 1 1.0 1.0 0.0 del que[count]\n", - " 157 506 925.0 1.8 2.2 if count > 1:\n", + " 148 60 144.0 2.4 0.2 for term, bias in terms.items():\n", + " 149 5485 6347.0 1.2 8.7 for pair2 in map(frozenset, (it.combinations(term, 2))):\n", + " 150 5455 4861.0 0.9 6.7 if pair2 != pair:\n", + " 151 5425 5588.0 1.0 7.7 if pair2 & pair:\n", + " 152 930 1304.0 1.4 1.8 count = len(idx[pair2])\n", + " 153 930 845.0 0.9 1.2 que_count = que[count]\n", + " 154 930 2094.0 2.3 2.9 que_count.remove(pair2)\n", + " 155 930 1237.0 1.3 1.7 if not que_count:\n", + " 156 1 2.0 2.0 0.0 del que[count]\n", + " 157 930 800.0 0.9 1.1 if count > 1:\n", " 158 que[count - 1].add(pair2)\n", - " 159 2277 4707.0 2.1 11.2 idx_pair2 = idx[pair2]\n", - " 160 2277 3150.0 1.4 7.5 del idx_pair2[term]\n", - " 161 2277 2594.0 1.1 6.2 if not idx_pair2:\n", - " 162 2277 4687.0 2.1 11.2 del idx[pair2]\n", + " 159 5425 7460.0 1.4 10.3 idx_pair2 = idx[pair2]\n", + " 160 5425 5826.0 1.1 8.0 del idx_pair2[term]\n", + " 161 5425 4569.0 0.8 6.3 if not idx_pair2:\n", + " 162 5425 5848.0 1.1 8.0 del idx[pair2]\n", " 163 \n", - " 164 22 109.0 5.0 0.3 new_term = (term - pair) | pset\n", - " 165 22 39.0 1.8 0.1 if len(new_term) <= 2:\n", - " 166 1 2.0 2.0 0.0 reduced_terms.append((new_term, bias))\n", + " 164 30 245.0 8.2 0.3 new_term = (term - pair) | pset\n", + " 165 30 58.0 1.9 0.1 if len(new_term) <= 2:\n", + " 166 1 3.0 3.0 0.0 reduced_terms.append((new_term, bias))\n", " 167 else:\n", - " 168 2044 3253.0 1.6 7.8 for new_pair in map(frozenset, it.combinations(new_term, 2)):\n", - " 169 2023 3603.0 1.8 8.6 idx[new_pair][new_term] = bias\n", - " 170 2023 2528.0 1.2 6.0 if p in new_pair:\n", - " 171 252 350.0 1.4 0.8 new_pairs.add(new_pair)\n", + " 168 4988 7419.0 1.5 10.2 for new_pair in map(frozenset, it.combinations(new_term, 2)):\n", + " 169 4959 7160.0 1.4 9.9 idx[new_pair][new_term] = bias\n", + " 170 4959 5301.0 1.1 7.3 if p in new_pair:\n", + " 171 464 649.0 1.4 0.9 new_pairs.add(new_pair)\n", " 172 \n", - " 173 274 360.0 1.3 0.9 for new_pair in new_pairs:\n", - " 174 252 575.0 2.3 1.4 que[len(idx[new_pair])].add(new_pair)\n", + " 173 494 519.0 1.1 0.7 for new_pair in new_pairs:\n", + " 174 464 635.0 1.4 0.9 que[len(idx[new_pair])].add(new_pair)\n", " 175 \n", " 176 1 1.0 1.0 0.0 return reduced_terms, constraints" ] @@ -2087,12 +1967,12 @@ } ], "source": [ - "%lprun -fdimod.higherorder.utils.reduce_terms bqm = make_quadratic(BPnew({term: 1}, 'SPIN'), strength=5, vartype='SPIN')" + "%lprun -fdimod.higherorder.utils.reduce_terms bqm = dimod.make_quadratic(BPnew({term: 1}, 'SPIN'), strength=5, vartype='SPIN')" ] }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 45, "id": "1934c5e7-5e31-4939-aae5-e23f8ede4ea0", "metadata": {}, "outputs": [ @@ -2101,83 +1981,175 @@ "text/plain": [ "Timer unit: 1e-06 s\n", "\n", - "Total time: 346.663 s\n", + "Total time: 364.994 s\n", "File: /home/daniel/dimod/dimod/higherorder/utils.py\n", "Function: reduce_terms at line 106\n", "\n", "Line # Hits Time Per Hit % Time Line Contents\n", "==============================================================\n", - " 106 def reduce_terms(bp):\n", - " 107 1 19566.0 19566.0 0.0 variables = bp.variables\n", - " 108 1 7.0 7.0 0.0 constraints = []\n", - " 109 1 37591.0 37591.0 0.0 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", - " 110 \n", - " 111 2 189.0 94.5 0.0 idx = defaultdict(\n", - " 112 1 2.0 2.0 0.0 dict,\n", - " 113 2 3424542.0 1712271.0 1.0 tl.valmap(\n", - " 114 1 46.0 46.0 0.0 tl.compose(dict, ft.partial(map, tl.second)),\n", - " 115 2 18779065.0 9389532.5 5.4 tl.groupby(\n", - " 116 1 1.0 1.0 0.0 tl.first,\n", - " 117 2 6.0 3.0 0.0 (\n", - " 118 (frozenset(pair), item)\n", - " 119 1 11.0 11.0 0.0 for item in bp.items()\n", - " 120 if len(term := tl.first(item)) >= 3\n", - " 121 for pair in it.combinations(term, 2) ))))\n", - " 122 \n", - " 123 2 10.0 5.0 0.0 que = defaultdict(\n", - " 124 1 1.0 1.0 0.0 set,\n", - " 125 2 434.0 217.0 0.0 tl.valmap(\n", - " 126 1 9.0 9.0 0.0 tl.compose(set, ft.partial(map, tl.first)),\n", - " 127 1 612.0 612.0 0.0 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", - " 128 \n", - " 129 58468 58998.0 1.0 0.0 while idx:\n", - " 130 58467 92099.0 1.6 0.0 new_pairs = set()\n", - " 131 58467 156064.0 2.7 0.0 most = max(que)\n", - " 132 \n", - " 133 #print(most, que[most])\n", - " 134 #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items())\n", - " 135 #pair, terms = max(idx.items(), key=tl.compose(len,tl.second))\n", - " 136 \n", - " 137 58467 64757.0 1.1 0.0 que_most = que[most]\n", - " 138 58467 79539.0 1.4 0.0 pair = que_most.pop()\n", - " 139 58467 56860.0 1.0 0.0 if not que_most:\n", - " 140 311 338.0 1.1 0.0 del que[most]\n", - " 141 58467 380892.0 6.5 0.1 terms = idx[pair]\n", - " 142 \n", - " 143 58467 304086.0 5.2 0.1 p = _new_product(variables, *pair)\n", - " 144 58467 82767.0 1.4 0.0 constraints.append((pair, p))\n", - " 145 58467 78700.0 1.3 0.0 del idx[pair]\n", - " 146 58467 68703.0 1.2 0.0 pset = {p}\n", - " 147 \n", - " 148 348184 682430.0 2.0 0.2 for term, bias in terms.items():\n", - " 149 26416713 31093376.0 1.2 9.0 for pair2 in map(frozenset, (it.combinations(term, 2))):\n", - " 150 26126996 23664115.0 0.9 6.8 if pair2 != pair:\n", - " 151 25837279 24898516.0 1.0 7.2 if pair2 & pair:\n", - " 152 5924056 10157809.0 1.7 2.9 count = len(idx[pair2])\n", - " 153 5924056 6996866.0 1.2 2.0 que_count = que[count]\n", - " 154 5924056 10361604.0 1.7 3.0 que_count.remove(pair2)\n", - " 155 5924056 5192684.0 0.9 1.5 if not que_count:\n", - " 156 1294711 1264056.0 1.0 0.4 del que[count]\n", - " 157 5924056 5275174.0 0.9 1.5 if count > 1:\n", - " 158 5503038 8409122.0 1.5 2.4 que[count - 1].add(pair2)\n", - " 159 25837279 37128294.0 1.4 10.7 idx_pair2 = idx[pair2]\n", - " 160 25837279 38704563.0 1.5 11.2 del idx_pair2[term]\n", - " 161 25837279 21610041.0 0.8 6.2 if not idx_pair2:\n", - " 162 810097 956368.0 1.2 0.3 del idx[pair2]\n", - " 163 \n", - " 164 289717 1127561.0 3.9 0.3 new_term = (term - pair) | pset\n", - " 165 289717 379470.0 1.3 0.1 if len(new_term) <= 2:\n", - " 166 18077 27904.0 1.5 0.0 reduced_terms.append((new_term, bias))\n", - " 167 else:\n", - " 168 23128814 30146342.0 1.3 8.7 for new_pair in map(frozenset, it.combinations(new_term, 2)):\n", - " 169 22857174 40166576.0 1.8 11.6 idx[new_pair][new_term] = bias\n", - " 170 22857174 20126136.0 0.9 5.8 if p in new_pair:\n", - " 171 2943951 3287438.0 1.1 0.9 new_pairs.add(new_pair)\n", - " 172 \n", - " 173 536677 555879.0 1.0 0.2 for new_pair in new_pairs:\n", - " 174 478210 764707.0 1.6 0.2 que[len(idx[new_pair])].add(new_pair)\n", + " 106 constraints = []\n", + " 107 1 12957.0 12957.0 0.0 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", + " 108 1 3.0 3.0 0.0 \n", + " 109 1 46129.0 46129.0 0.0 idx = defaultdict(\n", + " 110 dict,\n", + " 111 2 458.0 229.0 0.0 tl.valmap(\n", + " 112 1 2.0 2.0 0.0 tl.compose(dict, partial(map, tl.second)),\n", + " 113 2 5879020.0 2939510.0 1.6 tl.groupby(\n", + " 114 1 26.0 26.0 0.0 tl.first,\n", + " 115 2 17846109.0 8923054.5 4.9 (\n", + " 116 1 2.0 2.0 0.0 (frozenset(pair), item)\n", + " 117 2 23.0 11.5 0.0 for item in bp.items()\n", + " 118 if len(term := tl.first(item)) >= 3\n", + " 119 1 32.0 32.0 0.0 for pair in itertools.combinations(term, 2) ))))\n", + " 120 \n", + " 121 que = defaultdict(\n", + " 122 set,\n", + " 123 2 14.0 7.0 0.0 tl.valmap(\n", + " 124 1 2.0 2.0 0.0 tl.compose(set, partial(map, tl.first)),\n", + " 125 2 605.0 302.5 0.0 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", + " 126 1 15.0 15.0 0.0 \n", + " 127 1 939.0 939.0 0.0 while idx:\n", + " 128 new_pairs = set()\n", + " 129 58934 51804.0 0.9 0.0 most = max(que)\n", + " 130 58933 88008.0 1.5 0.0 \n", + " 131 58933 129596.0 2.2 0.0 #print(most, que[most])\n", + " 132 #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items())\n", + " 133 #pair, terms = max(idx.items(), key=tl.compose(len,tl.second))\n", + " 134 \n", + " 135 que_most = que[most]\n", + " 136 pair = que_most.pop()\n", + " 137 58933 56237.0 1.0 0.0 if not que_most:\n", + " 138 58933 74910.0 1.3 0.0 del que[most]\n", + " 139 58933 51279.0 0.9 0.0 terms = idx[pair]\n", + " 140 307 339.0 1.1 0.0 \n", + " 141 58933 412141.0 7.0 0.1 p = _new_product(variables, *pair)\n", + " 142 constraints.append((pair, p))\n", + " 143 58933 309915.0 5.3 0.1 del idx[pair]\n", + " 144 58933 77720.0 1.3 0.0 pset = {p}\n", + " 145 58933 73491.0 1.2 0.0 \n", + " 146 58933 64554.0 1.1 0.0 for term, bias in terms.items():\n", + " 147 for pair2 in map(frozenset, (itertools.combinations(term, 2))):\n", + " 148 349630 715848.0 2.0 0.2 if pair2 != pair:\n", + " 149 26322163 31601354.0 1.2 8.7 if pair2 & pair:\n", + " 150 26031466 23522489.0 0.9 6.4 count = len(idx[pair2])\n", + " 151 25740769 24791172.0 1.0 6.8 que_count = que[count]\n", + " 152 5919520 10542398.0 1.8 2.9 que_count.remove(pair2)\n", + " 153 5919520 7283210.0 1.2 2.0 if not que_count:\n", + " 154 5919520 11160269.0 1.9 3.1 del que[count]\n", + " 155 5919520 5136317.0 0.9 1.4 if count > 1:\n", + " 156 1275146 1258590.0 1.0 0.3 que[count - 1].add(pair2)\n", + " 157 5919520 5160611.0 0.9 1.4 idx_pair2 = idx[pair2]\n", + " 158 5499963 9027859.0 1.6 2.5 del idx_pair2[term]\n", + " 159 25740769 38298017.0 1.5 10.5 if not idx_pair2:\n", + " 160 25740769 46003860.0 1.8 12.6 del idx[pair2]\n", + " 161 25740769 21756609.0 0.8 6.0 \n", + " 162 807706 870552.0 1.1 0.2 new_term = (term - pair) | pset\n", + " 163 if len(new_term) <= 2:\n", + " 164 290697 1244477.0 4.3 0.3 reduced_terms.append((new_term, bias))\n", + " 165 290697 381118.0 1.3 0.1 else:\n", + " 166 18209 28056.0 1.5 0.0 for new_pair in map(frozenset, itertools.combinations(new_term, 2)):\n", + " 167 idx[new_pair][new_term] = bias\n", + " 168 23035288 29258154.0 1.3 8.0 if p in new_pair:\n", + " 169 22762800 46979493.0 2.1 12.9 new_pairs.add(new_pair)\n", + " 170 22762800 20147204.0 0.9 5.5 \n", + " 171 2941551 3400857.0 1.2 0.9 for new_pair in new_pairs:\n", + " 172 que[len(idx[new_pair])].add(new_pair)\n", + " 173 536148 505010.0 0.9 0.1 \n", + " 174 477215 744440.0 1.6 0.2 return reduced_terms, constraints\n", " 175 \n", - " 176 1 1.0 1.0 0.0 return reduced_terms, constraints" + " 176 1 1.0 1.0 0.0 \n", + " 177 def make_quadratic(poly, strength, vartype=None, bqm=None):\n", + " 178 \"\"\"Create a binary quadratic model from a higher order polynomial.\n", + " 179 \n", + " 180 Args:\n", + " 181 poly (dict):\n", + " 182 Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of\n", + " 183 variables and `bias` the associated bias.\n", + " 184 \n", + " 185 strength (float):\n", + " 186 The energy penalty for violating the prodcut constraint.\n", + " 187 Insufficient strength can result in the binary quadratic model not\n", + " 188 having the same minimizations as the polynomial.\n", + " 189 \n", + " 190 vartype (:class:`.Vartype`/str/set, optional):\n", + " 191 Variable type for the binary quadratic model. Accepted input values:\n", + " 192 \n", + " 193 * :class:`.Vartype.SPIN`, ``'SPIN'``, ``{-1, 1}``\n", + " 194 * :class:`.Vartype.BINARY`, ``'BINARY'``, ``{0, 1}``\n", + " 195 \n", + " 196 If `bqm` is provided, `vartype` is not required.\n", + " 197 \n", + " 198 bqm (:class:`.BinaryQuadraticModel`, optional):\n", + " 199 The terms of the reduced polynomial are added to this binary quadratic model.\n", + " 200 If not provided, a new binary quadratic model is created.\n", + " 201 \n", + " 202 Returns:\n", + " 203 :class:`.BinaryQuadraticModel`\n", + " 204 \n", + " 205 Examples:\n", + " 206 \n", + " 207 >>> poly = {(0,): -1, (1,): 1, (2,): 1.5, (0, 1): -1, (0, 1, 2): -2}\n", + " 208 >>> bqm = dimod.make_quadratic(poly, 5.0, dimod.SPIN)\n", + " 209 \n", + " 210 \"\"\"\n", + " 211 if vartype is None:\n", + " 212 if bqm is None:\n", + " 213 raise ValueError(\"one of vartype or bqm must be provided\")\n", + " 214 else:\n", + " 215 vartype = bqm.vartype\n", + " 216 else:\n", + " 217 vartype = as_vartype(vartype) # handle other vartype inputs\n", + " 218 if bqm is None:\n", + " 219 bqm = BinaryQuadraticModel.empty(vartype)\n", + " 220 else:\n", + " 221 bqm = bqm.change_vartype(vartype, inplace=False)\n", + " 222 \n", + " 223 # for backwards compatibility, add an info field\n", + " 224 if not hasattr(bqm, 'info'):\n", + " 225 bqm.info = {}\n", + " 226 bqm.info['reduction'] = {}\n", + " 227 \n", + " 228 if poly.vartype !=vartype:\n", + " 229 poly = BinaryPolynomial(poly, vartype=vartype)\n", + " 230 \n", + " 231 variables = set().union(*poly)\n", + " 232 reduced_terms, constraints = reduce_terms(poly)\n", + " 233 \n", + " 234 for (u, v), p in constraints:\n", + " 235 \n", + " 236 # add a constraint enforcing the relationship between p == u*v\n", + " 237 if vartype is Vartype.BINARY:\n", + " 238 constraint = _binary_product([u, v, p])\n", + " 239 bqm.info['reduction'][(u, v)] = {'product': p}\n", + " 240 elif vartype is Vartype.SPIN:\n", + " 241 aux = _new_aux(variables, u, v) # need an aux in SPIN-space\n", + " 242 constraint = _spin_product([u, v, p, aux])\n", + " 243 bqm.info['reduction'][(u, v)] = {'product': p, 'auxiliary': aux}\n", + " 244 else:\n", + " 245 raise RuntimeError(\"unknown vartype: {!r}\".format(vartype))\n", + " 246 \n", + " 247 # scale constraint and update the polynomial with it\n", + " 248 constraint.scale(strength)\n", + " 249 for v, bias in constraint.linear.items():\n", + " 250 bqm.add_variable(v, bias)\n", + " 251 for uv, bias in constraint.quadratic.items():\n", + " 252 bqm.add_interaction(*uv, bias)\n", + " 253 bqm.offset += constraint.offset\n", + " 254 \n", + " 255 for term, bias in reduced_terms:\n", + " 256 if len(term) == 2:\n", + " 257 bqm.add_interaction(*term , bias)\n", + " 258 elif len(term) == 1:\n", + " 259 bqm.add_variable(*term, bias)\n", + " 260 elif len(term) == 0:\n", + " 261 bqm.offset += bias\n", + " 262 else:\n", + " 263 # still has higher order terms, this shouldn't happen\n", + " 264 msg = ('Internal error: not all higher-order terms were reduced. '\n", + " 265 'Please file a bug report.')\n", + " 266 raise RuntimeError(msg)\n", + " 267 \n", + " 268 return bqm" ] }, "metadata": {}, @@ -2185,12 +2157,12 @@ } ], "source": [ - "%lprun -fdimod.higherorder.utils.reduce_terms bqm = make_quadratic(bp, strength=5, vartype=bp.vartype)" + "%lprun -fdimod.higherorder.utils.reduce_terms bqm = dimod.make_quadratic(bp, strength=5, vartype=bp.vartype)" ] }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 46, "id": "1f1a5a0c-5a2f-4227-9f4b-2b3f4f696ce2", "metadata": {}, "outputs": [ @@ -2198,17 +2170,17 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 6.21 ms, sys: 93 µs, total: 6.3 ms\n", - "Wall time: 6.09 ms\n" + "CPU times: user 13.2 ms, sys: 9 µs, total: 13.2 ms\n", + "Wall time: 12.1 ms\n" ] }, { "data": { "text/plain": [ - "68" + "92" ] }, - "execution_count": 45, + "execution_count": 46, "metadata": {}, "output_type": "execute_result" } @@ -2219,7 +2191,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 47, "id": "1963c838-558b-4257-81d2-968c9648ea14", "metadata": {}, "outputs": [ @@ -2304,7 +2276,7 @@ "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_variable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0muv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mquadratic\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_interaction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0muv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_offset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moffset\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", + "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moffset\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moffset\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mreduced_terms\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", @@ -2320,7 +2292,7 @@ "\u001b[0;34m\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", "\u001b[0;34m\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mFile:\u001b[0m /tmp/ipykernel_5226/2794073046.py\n", + "\u001b[0;31mFile:\u001b[0m /tmp/ipykernel_5867/3448239133.py\n", "\u001b[0;31mType:\u001b[0m function\n" ] }, @@ -2334,7 +2306,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 48, "id": "ed0769ec-6d1b-40d2-b110-989f2f068c86", "metadata": {}, "outputs": [ @@ -2343,7 +2315,7 @@ "evalue": "invalid syntax (3330683553.py, line 1)", "output_type": "error", "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_5226/3330683553.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m BinaryPolynomial.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_5867/3330683553.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m BinaryPolynomial.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" ] } ], @@ -2355,7 +2327,6 @@ "cell_type": "code", "execution_count": null, "id": "4d4d5183-1bb3-4b7f-a8ab-4af55b2c55e7", ->>>>>>> Stashed changes "metadata": {}, "outputs": [], "source": [ @@ -2404,21 +2375,10 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": null, "id": "bdb58284-1a2d-4880-93ff-b8dd31134d83", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 51, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "bool(set())" ] From 695b45aca119863a9323b736f393a8c08c62296e Mon Sep 17 00:00:00 2001 From: Daniel Mahler Date: Tue, 21 Sep 2021 00:22:41 -0500 Subject: [PATCH 7/9] bugfix --- dimod/higherorder/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dimod/higherorder/utils.py b/dimod/higherorder/utils.py index 6ec3a98a9..641bcc0fb 100644 --- a/dimod/higherorder/utils.py +++ b/dimod/higherorder/utils.py @@ -225,7 +225,7 @@ def make_quadratic(poly, strength, vartype=None, bqm=None): bqm.info = {} bqm.info['reduction'] = {} - if poly.vartype !=vartype: + if not isinstance(poly, BinaryPolynomial) or poly.vartype != vartype: poly = BinaryPolynomial(poly, vartype=vartype) variables = set().union(*poly) From 887dec0f4674e1678be7e5957ff781d83abada65 Mon Sep 17 00:00:00 2001 From: Daniel Mahler Date: Tue, 21 Sep 2021 05:55:02 -0500 Subject: [PATCH 8/9] simpolifications --- dimod/higherorder/utils.py | 75 +-- polynomial-perf.ipynb | 1017 +++++++++++------------------------- 2 files changed, 355 insertions(+), 737 deletions(-) diff --git a/dimod/higherorder/utils.py b/dimod/higherorder/utils.py index 641bcc0fb..1b85f59c5 100644 --- a/dimod/higherorder/utils.py +++ b/dimod/higherorder/utils.py @@ -101,6 +101,23 @@ def _new_aux(variables, u, v): return aux +def _decrement_count(idx, que, pair): + count = len(idx[pair]) + que_count = que[count] + que_count.remove(pair) + if not que_count: + del que[count] + if count > 1: + que[count - 1].add(pair) + + +def _remove_old(idx, term, pair): + idx_pair = idx[pair] + del idx_pair[term] + if not idx_pair: + del idx[pair] + + def reduce_terms(bp): variables = bp.variables constraints = [] @@ -127,46 +144,34 @@ def reduce_terms(bp): while idx: new_pairs = set() most = max(que) - - #print(most, que[most]) - #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items()) - #pair, terms = max(idx.items(), key=tl.compose(len,tl.second)) - que_most = que[most] pair = que_most.pop() if not que_most: del que[most] - terms = idx[pair] + terms = idx.pop(pair) - p = _new_product(variables, *pair) - constraints.append((pair, p)) - del idx[pair] - pset = {p} - - for term, bias in terms.items(): - for pair2 in map(frozenset, (itertools.combinations(term, 2))): - if pair2 != pair: - if pair2 & pair: - count = len(idx[pair2]) - que_count = que[count] - que_count.remove(pair2) - if not que_count: - del que[count] - if count > 1: - que[count - 1].add(pair2) - idx_pair2 = idx[pair2] - del idx_pair2[term] - if not idx_pair2: - del idx[pair2] - - new_term = (term - pair) | pset - if len(new_term) <= 2: - reduced_terms.append((new_term, bias)) - else: - for new_pair in map(frozenset, itertools.combinations(new_term, 2)): + prod_var = _new_product(variables, *pair) + constraints.append((pair, prod_var)) + prod_var_set = {prod_var} + + for old_term, bias in terms.items(): + common_subterm = (old_term - pair) + new_term = common_subterm | prod_var_set + + for old_pair in map(frozenset, itertools.product(pair, common_subterm)): + _decrement_count(idx, que, old_pair) + _remove_old(idx, old_term, old_pair) + + for common_pair in map(frozenset, itertools.combinations(common_subterm, 2)): + idx[common_pair][new_term] = bias + _remove_old(idx, old_term, common_pair) + + if len(new_term) > 2: + for new_pair in (frozenset((prod_var, v)) for v in common_subterm): idx[new_pair][new_term] = bias - if p in new_pair: - new_pairs.add(new_pair) + new_pairs.add(new_pair) + else: + reduced_terms.append((new_term, bias)) for new_pair in new_pairs: que[len(idx[new_pair])].add(new_pair) @@ -230,7 +235,7 @@ def make_quadratic(poly, strength, vartype=None, bqm=None): variables = set().union(*poly) reduced_terms, constraints = reduce_terms(poly) - + for (u, v), p in constraints: # add a constraint enforcing the relationship between p == u*v diff --git a/polynomial-perf.ipynb b/polynomial-perf.ipynb index 16cc8b0de..c16f037df 100644 --- a/polynomial-perf.ipynb +++ b/polynomial-perf.ipynb @@ -679,15 +679,7 @@ "execution_count": 1, "id": "370178a2-f029-4e9b-b4f7-f4c051df686c", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], + "outputs": [], "source": [ "import string, random, toolz, pandas, importlib, sys, os, cytoolz, toolz, dimod" ] @@ -712,8 +704,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 147 ms, sys: 606 µs, total: 148 ms\n", - "Wall time: 147 ms\n" + "CPU times: user 114 ms, sys: 9.46 ms, total: 124 ms\n", + "Wall time: 122 ms\n" ] } ], @@ -730,14 +722,14 @@ { "data": { "text/plain": [ - "count 19393.000000\n", - "mean 50.565049\n", - "std 51.640829\n", + "count 19249.000000\n", + "mean 50.950803\n", + "std 51.208656\n", "min 0.000000\n", "25% 14.000000\n", "50% 35.000000\n", - "75% 69.000000\n", - "max 548.000000\n", + "75% 70.000000\n", + "max 515.000000\n", "dtype: float64" ] }, @@ -768,9 +760,10 @@ "name": "stdout", "output_type": "stream", "text": [ - "dimod/higherorder/polynomial.py: needs merge\n", - "polynomial-perf.ipynb: needs merge\n", - "error: you need to resolve your current index first\n", + "M\tdimod/higherorder/utils.py\n", + "D\tpolynomial-perf.ipynb\n", + "Already on 'binary-polynomial'\n", + "Your branch is up to date with 'origin/binary-polynomial'.\n", "No stash entries found.\n" ] } @@ -835,23 +828,30 @@ "id": "9065a62a-4c71-4f58-843b-65f611bc4848", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + }, { "data": { "text/plain": [ - " 406093 function calls (406013 primitive calls) in 0.221 seconds\n", + " 405071 function calls (404991 primitive calls) in 0.183 seconds\n", "\n", " Ordered by: cumulative time\n", " List reduced from 46 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 0.221 0.221 {built-in method builtins.exec}\n", - " 1 0.000 0.000 0.221 0.221 :1()\n", - " 1 0.000 0.000 0.221 0.221 decorators.py:289(new_f)\n", - " 1 0.016 0.016 0.221 0.221 polynomial.py:108(__init__)\n", - " 19393 0.152 0.000 0.205 0.000 polynomial.py:40(freeze_term)\n", - " 347711 0.050 0.000 0.050 0.000 polynomial.py:47()\n", - " 19403 0.002 0.000 0.002 0.000 {built-in method builtins.isinstance}\n", - " 19394 0.002 0.000 0.002 0.000 {method 'items' of 'dict' objects}\n", + " 1 0.000 0.000 0.183 0.183 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.183 0.183 :1()\n", + " 1 0.000 0.000 0.183 0.183 decorators.py:289(new_f)\n", + " 1 0.012 0.012 0.183 0.183 polynomial.py:108(__init__)\n", + " 19249 0.127 0.000 0.170 0.000 polynomial.py:40(freeze_term)\n", + " 347121 0.041 0.000 0.041 0.000 polynomial.py:47()\n", + " 19259 0.002 0.000 0.002 0.000 {built-in method builtins.isinstance}\n", + " 19250 0.001 0.000 0.001 0.000 {method 'items' of 'dict' objects}\n", " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", @@ -861,20 +861,13 @@ " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)\n", " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)\n", - " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)" + " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)" ] }, "metadata": {}, "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - " " - ] } ], "source": [ @@ -916,18 +909,18 @@ " \n", " \n", " count\n", - " 18602.000000\n", - " 18602.000000\n", + " 18500.000000\n", + " 18500.000000\n", " \n", " \n", " mean\n", - " 17.624341\n", - " 1.042522\n", + " 17.698595\n", + " 1.040486\n", " \n", " \n", " std\n", - " 7.647118\n", - " 2.870007\n", + " 7.689292\n", + " 2.693415\n", " \n", " \n", " min\n", @@ -952,7 +945,7 @@ " \n", " max\n", " 38.000000\n", - " 389.000000\n", + " 364.000000\n", " \n", " \n", "\n", @@ -960,14 +953,14 @@ ], "text/plain": [ " 0 1\n", - "count 18602.000000 18602.000000\n", - "mean 17.624341 1.042522\n", - "std 7.647118 2.870007\n", + "count 18500.000000 18500.000000\n", + "mean 17.698595 1.040486\n", + "std 7.689292 2.693415\n", "min 0.000000 1.000000\n", "25% 12.000000 1.000000\n", "50% 19.000000 1.000000\n", "75% 24.000000 1.000000\n", - "max 38.000000 389.000000" + "max 38.000000 364.000000" ] }, "execution_count": 9, @@ -1001,7 +994,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "887 ms ± 162 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + "522 ms ± 9.21 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] }, { @@ -1030,7 +1023,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "1.25 s ± 226 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + "736 ms ± 18.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] }, { @@ -1125,31 +1118,31 @@ { "data": { "text/plain": [ - " 1832419 function calls (1832414 primitive calls) in 0.652 seconds\n", + " 1827867 function calls (1827862 primitive calls) in 0.479 seconds\n", "\n", " Ordered by: cumulative time\n", " List reduced from 67 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 0.652 0.652 {built-in method builtins.exec}\n", - " 1 0.000 0.000 0.652 0.652 :1()\n", - " 2/1 0.301 0.151 0.652 0.652 polynomial.py:236(relabel_variables)\n", - " 692900 0.152 0.000 0.202 0.000 polynomial.py:260()\n", - " 55809 0.033 0.000 0.063 0.000 _collections_abc.py:742(__iter__)\n", - " 655700 0.051 0.000 0.051 0.000 {method 'get' of 'dict' objects}\n", - " 37202 0.025 0.000 0.035 0.000 polynomial.py:162(__setitem__)\n", - " 130210 0.024 0.000 0.031 0.000 polynomial.py:35(asfrozenset)\n", - " 1 0.000 0.000 0.030 0.030 polynomial.py:181(copy)\n", - " 1 0.000 0.000 0.030 0.030 decorators.py:289(new_f)\n", - " 55806 0.018 0.000 0.030 0.000 polynomial.py:153(__getitem__)\n", - " 1 0.010 0.010 0.030 0.030 polynomial.py:108(__init__)\n", - " 37202 0.015 0.000 0.024 0.000 polynomial.py:124(__delitem__)\n", - " 1 0.002 0.002 0.013 0.013 polynomial.py:169(variables)\n", + " 1 0.000 0.000 0.479 0.479 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.478 0.478 :1()\n", + " 2/1 0.219 0.109 0.478 0.478 polynomial.py:236(relabel_variables)\n", + " 691848 0.105 0.000 0.141 0.000 polynomial.py:260()\n", + " 55503 0.023 0.000 0.050 0.000 _collections_abc.py:742(__iter__)\n", + " 654852 0.036 0.000 0.036 0.000 {method 'get' of 'dict' objects}\n", + " 1 0.000 0.000 0.031 0.031 polynomial.py:181(copy)\n", + " 1 0.000 0.000 0.031 0.031 decorators.py:289(new_f)\n", + " 1 0.010 0.010 0.031 0.031 polynomial.py:108(__init__)\n", + " 55500 0.016 0.000 0.026 0.000 polynomial.py:153(__getitem__)\n", + " 129496 0.018 0.000 0.024 0.000 polynomial.py:35(asfrozenset)\n", + " 36998 0.016 0.000 0.024 0.000 polynomial.py:162(__setitem__)\n", + " 36998 0.011 0.000 0.018 0.000 polynomial.py:124(__delitem__)\n", + " 1 0.003 0.003 0.014 0.014 polynomial.py:169(variables)\n", " 1 0.011 0.011 0.011 0.011 {method 'union' of 'set' objects}\n", - " 148821 0.009 0.000 0.009 0.000 {built-in method builtins.isinstance}\n", - " 18602 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", - " 3 0.000 0.000 0.000 0.000 utilities.py:351(iter_safe_relabels)\n", + " 148005 0.007 0.000 0.007 0.000 {built-in method builtins.isinstance}\n", + " 18500 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", + " 3 0.000 0.000 0.000 0.000 utilities.py:351(iter_safe_relabels)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)" ] }, @@ -1177,29 +1170,29 @@ { "data": { "text/plain": [ - " 1832416 function calls (1832411 primitive calls) in 0.594 seconds\n", + " 1827864 function calls (1827859 primitive calls) in 0.425 seconds\n", "\n", " Ordered by: cumulative time\n", " List reduced from 64 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 0.594 0.594 {built-in method builtins.exec}\n", - " 1 0.000 0.000 0.594 0.594 :1()\n", - " 2/1 0.227 0.113 0.594 0.594 polynomial.py:236(relabel_variables)\n", - " 692900 0.154 0.000 0.208 0.000 polynomial.py:260()\n", - " 55809 0.036 0.000 0.069 0.000 _collections_abc.py:742(__iter__)\n", - " 655700 0.054 0.000 0.054 0.000 {method 'get' of 'dict' objects}\n", - " 37202 0.027 0.000 0.037 0.000 polynomial.py:162(__setitem__)\n", - " 1 0.000 0.000 0.033 0.033 polynomial.py:181(copy)\n", - " 1 0.000 0.000 0.033 0.033 decorators.py:289(new_f)\n", - " 130210 0.024 0.000 0.033 0.000 polynomial.py:35(asfrozenset)\n", - " 1 0.011 0.011 0.033 0.033 polynomial.py:108(__init__)\n", - " 55806 0.020 0.000 0.033 0.000 polynomial.py:153(__getitem__)\n", - " 37202 0.018 0.000 0.027 0.000 polynomial.py:124(__delitem__)\n", - " 148821 0.010 0.000 0.010 0.000 {built-in method builtins.isinstance}\n", - " 1 0.001 0.001 0.010 0.010 polynomial.py:169(variables)\n", - " 1 0.009 0.009 0.009 0.009 {method 'union' of 'set' objects}\n", - " 18602 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", + " 1 0.000 0.000 0.425 0.425 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.425 0.425 :1()\n", + " 2/1 0.162 0.081 0.425 0.425 polynomial.py:236(relabel_variables)\n", + " 691848 0.107 0.000 0.144 0.000 polynomial.py:260()\n", + " 55503 0.029 0.000 0.055 0.000 _collections_abc.py:742(__iter__)\n", + " 654852 0.037 0.000 0.037 0.000 {method 'get' of 'dict' objects}\n", + " 1 0.000 0.000 0.031 0.031 polynomial.py:181(copy)\n", + " 1 0.000 0.000 0.031 0.031 decorators.py:289(new_f)\n", + " 1 0.009 0.009 0.030 0.030 polynomial.py:108(__init__)\n", + " 55500 0.016 0.000 0.026 0.000 polynomial.py:153(__getitem__)\n", + " 36998 0.017 0.000 0.025 0.000 polynomial.py:162(__setitem__)\n", + " 129496 0.018 0.000 0.024 0.000 polynomial.py:35(asfrozenset)\n", + " 36998 0.011 0.000 0.018 0.000 polynomial.py:124(__delitem__)\n", + " 1 0.001 0.001 0.009 0.009 polynomial.py:169(variables)\n", + " 1 0.008 0.008 0.008 0.008 {method 'union' of 'set' objects}\n", + " 148005 0.007 0.000 0.007 0.000 {built-in method builtins.isinstance}\n", + " 18500 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", " 3 0.000 0.000 0.000 0.000 utilities.py:351(iter_safe_relabels)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)" @@ -1321,8 +1314,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 18.1 s, sys: 1.19 s, total: 19.3 s\n", - "Wall time: 19.3 s\n" + "CPU times: user 9.81 s, sys: 362 ms, total: 10.2 s\n", + "Wall time: 10.2 s\n" ] } ], @@ -1407,7 +1400,7 @@ { "data": { "text/plain": [ - "2720" + "2695" ] }, "execution_count": 29, @@ -1430,7 +1423,7 @@ { "data": { "text/plain": [ - "frozenset({'F', 'J'})" + "frozenset({'J', 'w'})" ] }, "execution_count": 30, @@ -1520,7 +1513,7 @@ { "data": { "text/plain": [ - "[(frozenset({'F', 'J'}), 'J*F')]" + "[(frozenset({'J', 'w'}), 'w*J')]" ] }, "execution_count": 35, @@ -1555,11 +1548,11 @@ { "data": { "text/plain": [ - "((frozenset({'K', 'Y'}), 2689),\n", - " (frozenset({'A', 'T'}), 2680),\n", - " (frozenset({'C', 'l'}), 2674),\n", - " (frozenset({'C', 'p'}), 2671),\n", - " (frozenset({'L', 'M'}), 2670))" + "((frozenset({'B', 'C'}), 2690),\n", + " (frozenset({'B', 'j'}), 2680),\n", + " (frozenset({'c', 't'}), 2677),\n", + " (frozenset({'A', 'V'}), 2676),\n", + " (frozenset({'B', 'O'}), 2674))" ] }, "execution_count": 37, @@ -1574,87 +1567,27 @@ { "cell_type": "code", "execution_count": 38, - "id": "28138875-8a2d-42a2-b102-85a10c387ac0", + "id": "faee8bfe-222d-447d-8e10-3e03e9dbb9fb", "metadata": {}, "outputs": [], "source": [ - "def reduce_terms(bp):\n", - " variables = bp.variables\n", - " constraints = []\n", - " reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", - "\n", - " idx = defaultdict(\n", - " dict,\n", - " tl.valmap(\n", - " tl.compose(dict, ft.partial(map, tl.second)),\n", - " tl.groupby(\n", - " tl.first,\n", - " (\n", - " (frozenset(pair), item)\n", - " for item in bp.items()\n", - " if len(term := tl.first(item)) >= 3\n", - " for pair in it.combinations(term, 2) ))))\n", - "\n", - " que = defaultdict(\n", - " set,\n", - " tl.valmap(\n", - " tl.compose(set, ft.partial(map, tl.first)),\n", - " tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", - "\n", - " while idx:\n", - " new_pairs = set()\n", - " most = max(que)\n", - " \n", - " #print(most, que[most])\n", - " #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items())\n", - " #pair, terms = max(idx.items(), key=tl.compose(len,tl.second))\n", - " \n", - " que_most = que[most]\n", - " pair = que_most.pop()\n", - " if not que_most:\n", - " del que[most]\n", - " terms = idx[pair]\n", - " \n", - " p = _new_product(variables, *pair)\n", - " constraints.append((pair, p))\n", - " del idx[pair]\n", - " pset = {p}\n", - "\n", - " for term, bias in terms.items():\n", - " for pair2 in map(frozenset, (it.combinations(term, 2))):\n", - " if pair2 != pair:\n", - " if pair2 & pair:\n", - " count = len(idx[pair2])\n", - " que_count = que[count]\n", - " que_count.remove(pair2)\n", - " if not que_count:\n", - " del que[count]\n", - " if count > 1:\n", - " que[count - 1].add(pair2)\n", - " idx_pair2 = idx[pair2]\n", - " del idx_pair2[term]\n", - " if not idx_pair2:\n", - " del idx[pair2]\n", - " \n", - " new_term = (term - pair) | pset\n", - " if len(new_term) <= 2:\n", - " reduced_terms.append((new_term, bias))\n", - " else:\n", - " for new_pair in map(frozenset, it.combinations(new_term, 2)):\n", - " idx[new_pair][new_term] = bias\n", - " if p in new_pair:\n", - " new_pairs.add(new_pair)\n", - " \n", - " for new_pair in new_pairs:\n", - " que[len(idx[new_pair])].add(new_pair)\n", - "\n", - " return reduced_terms, constraints" + "#%prun -s cumtime -l 30 dimod.reduced_terms, constraints = reduce_terms(bp)" ] }, { "cell_type": "code", "execution_count": 39, - "id": "faee8bfe-222d-447d-8e10-3e03e9dbb9fb", + "id": "0b9b2c67-05fa-4a86-8c3a-acc15119e861", + "metadata": {}, + "outputs": [], + "source": [ + "#len(reduced_terms), len(constraints)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "id": "179f7b4b-7895-4a12-824b-0f42c855727e", "metadata": {}, "outputs": [ { @@ -1667,36 +1600,42 @@ { "data": { "text/plain": [ - " 25411126 function calls in 70.785 seconds\n", + " 71617730 function calls (71617722 primitive calls) in 59.048 seconds\n", "\n", " Ordered by: cumulative time\n", + " List reduced from 106 to 30 due to restriction <30>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 70.785 70.785 {built-in method builtins.exec}\n", - " 1 0.004 0.004 70.785 70.785 :1()\n", - " 1 56.359 56.359 70.781 70.781 4179918042.py:1(reduce_terms)\n", - " 3268667 10.024 0.000 10.063 0.000 4179918042.py:12()\n", - " 5919520 2.057 0.000 2.057 0.000 {method 'remove' of 'set' objects}\n", - " 8977662 1.580 0.000 1.580 0.000 {method 'add' of 'set' objects}\n", - " 6724636 0.548 0.000 0.548 0.000 {built-in method builtins.len}\n", - " 58933 0.045 0.000 0.079 0.000 utils.py:88(_new_product)\n", - " 37206 0.021 0.000 0.053 0.000 _collections_abc.py:742(__iter__)\n", - " 58933 0.036 0.000 0.036 0.000 {built-in method builtins.max}\n", - " 37204 0.020 0.000 0.033 0.000 polynomial.py:153(__getitem__)\n", - " 58933 0.027 0.000 0.027 0.000 {method 'format' of 'str' objects}\n", - " 1 0.007 0.007 0.026 0.026 4179918042.py:4()\n", - " 77142 0.014 0.000 0.014 0.000 {method 'append' of 'list' objects}\n", - " 58933 0.013 0.000 0.013 0.000 {method 'pop' of 'set' objects}\n", - " 37204 0.009 0.000 0.013 0.000 polynomial.py:35(asfrozenset)\n", - " 1 0.001 0.001 0.012 0.012 polynomial.py:169(variables)\n", - " 1 0.010 0.010 0.010 0.010 {method 'union' of 'set' objects}\n", - " 58934 0.006 0.000 0.006 0.000 {method 'items' of 'dict' objects}\n", - " 37204 0.004 0.000 0.004 0.000 {built-in method builtins.isinstance}\n", - " 2 0.000 0.000 0.000 0.000 _collections_abc.py:676(items)\n", - " 2 0.000 0.000 0.000 0.000 polynomial.py:156(__iter__)\n", - " 2 0.000 0.000 0.000 0.000 _collections_abc.py:698(__init__)\n", - " 2 0.000 0.000 0.000 0.000 {built-in method builtins.iter}\n", - " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}" + " 1 0.000 0.000 59.048 59.048 {built-in method builtins.exec}\n", + " 1 0.021 0.021 59.048 59.048 :1()\n", + " 1 0.630 0.630 59.027 59.027 utils.py:182(make_quadratic)\n", + " 1 26.198 26.198 54.144 54.144 utils.py:121(reduce_terms)\n", + " 25951970 9.379 0.000 9.379 0.000 utils.py:114(_remove_old)\n", + " 3280262 8.620 0.000 8.652 0.000 utils.py:132()\n", + " 5943428 4.532 0.000 7.135 0.000 utils.py:104(_decrement_count)\n", + " 3226051 2.071 0.000 2.071 0.000 utils.py:170()\n", + " 57783 0.081 0.000 1.903 0.000 utils.py:63(_binary_product)\n", + " 57784 0.087 0.000 1.822 0.000 binary_quadratic_model.py:93(__init__)\n", + " 57783 0.280 0.000 1.715 0.000 binary_quadratic_model.py:136(_init_components)\n", + " 5943428 1.445 0.000 1.445 0.000 {method 'remove' of 'set' objects}\n", + " 9011363 1.248 0.000 1.248 0.000 {method 'add' of 'set' objects}\n", + " 365146 0.614 0.000 0.990 0.000 {method 'add_quadratic' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", + " 286635 0.143 0.000 0.825 0.000 _collections_abc.py:742(__iter__)\n", + " 2789747 0.368 0.000 0.736 0.000 abc.py:96(__instancecheck__)\n", + " 173351 0.212 0.000 0.586 0.000 decorators.py:474(wrapper)\n", + " 191797 0.045 0.000 0.574 0.000 binary_quadratic_model.py:709(add_interaction)\n", + " 57783 0.084 0.000 0.470 0.000 binary_quadratic_model.py:654(add_linear_from)\n", + " 7051542 0.451 0.000 0.451 0.000 {built-in method builtins.len}\n", + " 173400 0.268 0.000 0.400 0.000 {method 'add_variable' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", + " 2789747 0.367 0.000 0.367 0.000 {built-in method _abc._abc_instancecheck}\n", + " 231132 0.082 0.000 0.349 0.000 quadratic.py:136(__iter__)\n", + " 173349 0.066 0.000 0.298 0.000 quadratic.py:130(__getitem__)\n", + " 231132 0.256 0.000 0.256 0.000 _collections_abc.py:870(__iter__)\n", + " 231132 0.080 0.000 0.240 0.000 quadratic.py:176(__iter__)\n", + " 173349 0.110 0.000 0.197 0.000 {method 'add_linear' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", + " 362928 0.088 0.000 0.175 0.000 {built-in method builtins.isinstance}\n", + " 57784 0.135 0.000 0.168 0.000 binary_quadratic_model.py:187(_init_empty)\n", + " 231132 0.145 0.000 0.160 0.000 binary_quadratic_model.py:1252(iter_quadratic)" ] }, "metadata": {}, @@ -1704,167 +1643,12 @@ } ], "source": [ - "%prun -s cumtime -l 30 reduced_terms, constraints = reduce_terms(bp)" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "id": "0b9b2c67-05fa-4a86-8c3a-acc15119e861", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(18602, 58933)" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "len(reduced_terms), len(constraints)" + "%prun -s cumtime -l 30 bqm = dimod.make_quadratic(bp, 1000, 'BINARY')" ] }, { "cell_type": "code", "execution_count": 41, - "id": "179f7b4b-7895-4a12-824b-0f42c855727e", - "metadata": {}, - "outputs": [], - "source": [ - "#%prun -s cumtime -l 30 bqm = dimod.make_quadratic(bp, 1000, 'BINARY')" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "id": "9c4d1250-75ad-422a-8f20-04af19be39f7", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n" - ] - } - ], - "source": [ - "import itertools\n", - "import warnings\n", - "\n", - "from collections import Counter\n", - "\n", - "import numpy as np\n", - "\n", - "\n", - "from dimod.higherorder.utils import _new_product, as_vartype, _binary_product, _new_aux, _spin_product\n", - "print(_binary_product)\n", - "from dimod.binary_quadratic_model import BinaryQuadraticModel\n", - "from dimod.higherorder.polynomial import BinaryPolynomial\n", - "from dimod.sampleset import as_samples\n", - "from dimod.vartypes import as_vartype, Vartype\n", - "\n", - "def make_quadratic(poly, strength, vartype=None, bqm=None):\n", - " \"\"\"Create a binary quadratic model from a higher order polynomial.\n", - "\n", - " Args:\n", - " poly (dict):\n", - " Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of\n", - " variables and `bias` the associated bias.\n", - "\n", - " strength (float):\n", - " The energy penalty for violating the prodcut constraint.\n", - " Insufficient strength can result in the binary quadratic model not\n", - " having the same minimizations as the polynomial.\n", - "\n", - " vartype (:class:`.Vartype`/str/set, optional):\n", - " Variable type for the binary quadratic model. Accepted input values:\n", - "\n", - " * :class:`.Vartype.SPIN`, ``'SPIN'``, ``{-1, 1}``\n", - " * :class:`.Vartype.BINARY`, ``'BINARY'``, ``{0, 1}``\n", - "\n", - " If `bqm` is provided, `vartype` is not required.\n", - "\n", - " bqm (:class:`.BinaryQuadraticModel`, optional):\n", - " The terms of the reduced polynomial are added to this binary quadratic model.\n", - " If not provided, a new binary quadratic model is created.\n", - "\n", - " Returns:\n", - " :class:`.BinaryQuadraticModel`\n", - "\n", - " Examples:\n", - "\n", - " >>> poly = {(0,): -1, (1,): 1, (2,): 1.5, (0, 1): -1, (0, 1, 2): -2}\n", - " >>> bqm = dimod.make_quadratic(poly, 5.0, dimod.SPIN)\n", - "\n", - " \"\"\"\n", - " if vartype is None:\n", - " if bqm is None:\n", - " raise ValueError(\"one of vartype or bqm must be provided\")\n", - " else:\n", - " vartype = bqm.vartype\n", - " else:\n", - " vartype = as_vartype(vartype) # handle other vartype inputs\n", - " if bqm is None:\n", - " bqm = BinaryQuadraticModel.empty(vartype)\n", - " else:\n", - " bqm = bqm.change_vartype(vartype, inplace=False)\n", - "\n", - " # for backwards compatibility, add an info field\n", - " if not hasattr(bqm, 'info'):\n", - " bqm.info = {}\n", - " bqm.info['reduction'] = {}\n", - "\n", - " if poly.vartype !=vartype:\n", - " poly = BinaryPolynomial(poly, vartype=vartype)\n", - "\n", - " variables = set().union(*poly)\n", - " reduced_terms, constraints = dimod.higherorder.utils.reduce_terms(poly)\n", - " \n", - " for (u, v), p in constraints:\n", - "\n", - " # add a constraint enforcing the relationship between p == u*v\n", - " if vartype is Vartype.BINARY:\n", - " constraint = _binary_product([u, v, p])\n", - " bqm.info['reduction'][(u, v)] = {'product': p}\n", - " elif vartype is Vartype.SPIN:\n", - " aux = _new_aux(variables, u, v) # need an aux in SPIN-space\n", - " constraint = _spin_product([u, v, p, aux])\n", - " bqm.info['reduction'][(u, v)] = {'product': p, 'auxiliary': aux}\n", - " else:\n", - " raise RuntimeError(\"unknown vartype: {!r}\".format(vartype))\n", - "\n", - " # scale constraint and update the polynomial with it\n", - " constraint.scale(strength)\n", - " for v, bias in constraint.linear.items():\n", - " bqm.add_variable(v, bias)\n", - " for uv, bias in constraint.quadratic.items():\n", - " bqm.add_interaction(*uv, bias)\n", - " bqm.offset += constraint.offset\n", - "\n", - " for term, bias in reduced_terms:\n", - " if len(term) == 2:\n", - " bqm.add_interaction(*term , bias)\n", - " elif len(term) == 1:\n", - " bqm.add_variable(*term, bias)\n", - " elif len(term) == 0:\n", - " bqm.offset += bias\n", - " else:\n", - " # still has higher order terms, this shouldn't happen\n", - " msg = ('Internal error: not all higher-order terms were reduced. '\n", - " 'Please file a bug report.')\n", - " raise RuntimeError(msg)\n", - "\n", - " return bqm" - ] - }, - { - "cell_type": "code", - "execution_count": 43, "id": "9ca15f52-6ab1-4743-9c3f-3293512dc758", "metadata": {}, "outputs": [], @@ -1874,7 +1658,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 42, "id": "24d32eb7-61af-4c89-80bf-87583d1d9a65", "metadata": {}, "outputs": [ @@ -1883,83 +1667,71 @@ "text/plain": [ "Timer unit: 1e-06 s\n", "\n", - "Total time: 0.07269 s\n", + "Total time: 0.000832 s\n", "File: /home/daniel/dimod/dimod/higherorder/utils.py\n", - "Function: reduce_terms at line 106\n", + "Function: reduce_terms at line 121\n", "\n", "Line # Hits Time Per Hit % Time Line Contents\n", "==============================================================\n", - " 106 def reduce_terms(bp):\n", - " 107 1 6.0 6.0 0.0 variables = bp.variables\n", - " 108 1 1.0 1.0 0.0 constraints = []\n", - " 109 1 20.0 20.0 0.0 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", - " 110 \n", - " 111 2 24.0 12.0 0.0 idx = defaultdict(\n", - " 112 1 1.0 1.0 0.0 dict,\n", - " 113 2 644.0 322.0 0.9 tl.valmap(\n", - " 114 1 11.0 11.0 0.0 tl.compose(dict, ft.partial(map, tl.second)),\n", - " 115 2 1881.0 940.5 2.6 tl.groupby(\n", - " 116 1 0.0 0.0 0.0 tl.first,\n", - " 117 2 3.0 1.5 0.0 (\n", - " 118 (frozenset(pair), item)\n", - " 119 1 2.0 2.0 0.0 for item in bp.items()\n", - " 120 if len(term := tl.first(item)) >= 3\n", - " 121 for pair in it.combinations(term, 2) ))))\n", - " 122 \n", - " 123 2 3.0 1.5 0.0 que = defaultdict(\n", - " 124 1 2.0 2.0 0.0 set,\n", - " 125 2 66.0 33.0 0.1 tl.valmap(\n", - " 126 1 8.0 8.0 0.0 tl.compose(set, ft.partial(map, tl.first)),\n", - " 127 1 112.0 112.0 0.2 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", - " 128 \n", - " 129 31 32.0 1.0 0.0 while idx:\n", - " 130 30 83.0 2.8 0.1 new_pairs = set()\n", - " 131 30 85.0 2.8 0.1 most = max(que)\n", - " 132 \n", - " 133 #print(most, que[most])\n", - " 134 #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items())\n", - " 135 #pair, terms = max(idx.items(), key=tl.compose(len,tl.second))\n", - " 136 \n", - " 137 30 27.0 0.9 0.0 que_most = que[most]\n", - " 138 30 60.0 2.0 0.1 pair = que_most.pop()\n", - " 139 30 31.0 1.0 0.0 if not que_most:\n", - " 140 del que[most]\n", - " 141 30 67.0 2.2 0.1 terms = idx[pair]\n", - " 142 \n", - " 143 30 474.0 15.8 0.7 p = _new_product(variables, *pair)\n", - " 144 30 53.0 1.8 0.1 constraints.append((pair, p))\n", - " 145 30 41.0 1.4 0.1 del idx[pair]\n", - " 146 30 38.0 1.3 0.1 pset = {p}\n", - " 147 \n", - " 148 60 144.0 2.4 0.2 for term, bias in terms.items():\n", - " 149 5485 6347.0 1.2 8.7 for pair2 in map(frozenset, (it.combinations(term, 2))):\n", - " 150 5455 4861.0 0.9 6.7 if pair2 != pair:\n", - " 151 5425 5588.0 1.0 7.7 if pair2 & pair:\n", - " 152 930 1304.0 1.4 1.8 count = len(idx[pair2])\n", - " 153 930 845.0 0.9 1.2 que_count = que[count]\n", - " 154 930 2094.0 2.3 2.9 que_count.remove(pair2)\n", - " 155 930 1237.0 1.3 1.7 if not que_count:\n", - " 156 1 2.0 2.0 0.0 del que[count]\n", - " 157 930 800.0 0.9 1.1 if count > 1:\n", - " 158 que[count - 1].add(pair2)\n", - " 159 5425 7460.0 1.4 10.3 idx_pair2 = idx[pair2]\n", - " 160 5425 5826.0 1.1 8.0 del idx_pair2[term]\n", - " 161 5425 4569.0 0.8 6.3 if not idx_pair2:\n", - " 162 5425 5848.0 1.1 8.0 del idx[pair2]\n", - " 163 \n", - " 164 30 245.0 8.2 0.3 new_term = (term - pair) | pset\n", - " 165 30 58.0 1.9 0.1 if len(new_term) <= 2:\n", - " 166 1 3.0 3.0 0.0 reduced_terms.append((new_term, bias))\n", - " 167 else:\n", - " 168 4988 7419.0 1.5 10.2 for new_pair in map(frozenset, it.combinations(new_term, 2)):\n", - " 169 4959 7160.0 1.4 9.9 idx[new_pair][new_term] = bias\n", - " 170 4959 5301.0 1.1 7.3 if p in new_pair:\n", - " 171 464 649.0 1.4 0.9 new_pairs.add(new_pair)\n", - " 172 \n", - " 173 494 519.0 1.1 0.7 for new_pair in new_pairs:\n", - " 174 464 635.0 1.4 0.9 que[len(idx[new_pair])].add(new_pair)\n", + " 121 def reduce_terms(bp):\n", + " 122 1 4.0 4.0 0.5 variables = bp.variables\n", + " 123 1 0.0 0.0 0.0 constraints = []\n", + " 124 1 14.0 14.0 1.7 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", + " 125 \n", + " 126 2 5.0 2.5 0.6 idx = defaultdict(\n", + " 127 1 1.0 1.0 0.1 dict,\n", + " 128 2 26.0 13.0 3.1 tl.valmap(\n", + " 129 1 7.0 7.0 0.8 tl.compose(dict, partial(map, tl.second)),\n", + " 130 2 82.0 41.0 9.9 tl.groupby(\n", + " 131 1 1.0 1.0 0.1 tl.first,\n", + " 132 2 2.0 1.0 0.2 (\n", + " 133 (frozenset(pair), item)\n", + " 134 1 2.0 2.0 0.2 for item in bp.items()\n", + " 135 if len(term := tl.first(item)) >= 3\n", + " 136 for pair in itertools.combinations(term, 2) ))))\n", + " 137 \n", + " 138 2 2.0 1.0 0.2 que = defaultdict(\n", + " 139 1 1.0 1.0 0.1 set,\n", + " 140 2 7.0 3.5 0.8 tl.valmap(\n", + " 141 1 2.0 2.0 0.2 tl.compose(set, partial(map, tl.first)),\n", + " 142 1 11.0 11.0 1.3 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", + " 143 \n", + " 144 8 6.0 0.8 0.7 while idx:\n", + " 145 7 5.0 0.7 0.6 new_pairs = set()\n", + " 146 7 7.0 1.0 0.8 most = max(que)\n", + " 147 7 4.0 0.6 0.5 que_most = que[most]\n", + " 148 7 8.0 1.1 1.0 pair = que_most.pop()\n", + " 149 7 6.0 0.9 0.7 if not que_most:\n", + " 150 del que[most]\n", + " 151 7 8.0 1.1 1.0 terms = idx.pop(pair)\n", + " 152 \n", + " 153 7 17.0 2.4 2.0 prod_var = _new_product(variables, *pair)\n", + " 154 7 5.0 0.7 0.6 constraints.append((pair, prod_var))\n", + " 155 7 6.0 0.9 0.7 prod_var_set = {prod_var}\n", + " 156 \n", + " 157 14 11.0 0.8 1.3 for old_term, bias in terms.items():\n", + " 158 7 7.0 1.0 0.8 common_subterm = (old_term - pair)\n", + " 159 7 9.0 1.3 1.1 new_term = common_subterm | prod_var_set\n", + " 160 \n", + " 161 63 77.0 1.2 9.3 for old_pair in map(frozenset, (itertools.product(pair, common_subterm))):\n", + " 162 56 90.0 1.6 10.8 _decrement_count(idx, que, old_pair)\n", + " 163 56 78.0 1.4 9.4 _remove_old(idx, old_term, old_pair)\n", + " 164 \n", + " 165 63 54.0 0.9 6.5 for common_pair in map(frozenset, (itertools.combinations(common_subterm, 2))):\n", + " 166 56 46.0 0.8 5.5 idx[common_pair][new_term] = bias\n", + " 167 56 64.0 1.1 7.7 _remove_old(idx, old_term, common_pair)\n", + " 168 \n", + " 169 7 6.0 0.9 0.7 if len(new_term) > 2:\n", + " 170 33 39.0 1.2 4.7 for new_pair in (frozenset((prod_var, v)) for v in common_subterm):\n", + " 171 27 39.0 1.4 4.7 idx[new_pair][new_term] = bias\n", + " 172 27 23.0 0.9 2.8 new_pairs.add(new_pair)\n", + " 173 else:\n", + " 174 1 1.0 1.0 0.1 reduced_terms.append((new_term, bias))\n", " 175 \n", - " 176 1 1.0 1.0 0.0 return reduced_terms, constraints" + " 176 34 23.0 0.7 2.8 for new_pair in new_pairs:\n", + " 177 27 25.0 0.9 3.0 que[len(idx[new_pair])].add(new_pair)\n", + " 178 \n", + " 179 1 1.0 1.0 0.1 return reduced_terms, constraints" ] }, "metadata": {}, @@ -1972,7 +1744,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 47, "id": "1934c5e7-5e31-4939-aae5-e23f8ede4ea0", "metadata": {}, "outputs": [ @@ -1981,175 +1753,71 @@ "text/plain": [ "Timer unit: 1e-06 s\n", "\n", - "Total time: 364.994 s\n", + "Total time: 138.58 s\n", "File: /home/daniel/dimod/dimod/higherorder/utils.py\n", - "Function: reduce_terms at line 106\n", + "Function: reduce_terms at line 121\n", "\n", "Line # Hits Time Per Hit % Time Line Contents\n", "==============================================================\n", - " 106 constraints = []\n", - " 107 1 12957.0 12957.0 0.0 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", - " 108 1 3.0 3.0 0.0 \n", - " 109 1 46129.0 46129.0 0.0 idx = defaultdict(\n", - " 110 dict,\n", - " 111 2 458.0 229.0 0.0 tl.valmap(\n", - " 112 1 2.0 2.0 0.0 tl.compose(dict, partial(map, tl.second)),\n", - " 113 2 5879020.0 2939510.0 1.6 tl.groupby(\n", - " 114 1 26.0 26.0 0.0 tl.first,\n", - " 115 2 17846109.0 8923054.5 4.9 (\n", - " 116 1 2.0 2.0 0.0 (frozenset(pair), item)\n", - " 117 2 23.0 11.5 0.0 for item in bp.items()\n", - " 118 if len(term := tl.first(item)) >= 3\n", - " 119 1 32.0 32.0 0.0 for pair in itertools.combinations(term, 2) ))))\n", - " 120 \n", - " 121 que = defaultdict(\n", - " 122 set,\n", - " 123 2 14.0 7.0 0.0 tl.valmap(\n", - " 124 1 2.0 2.0 0.0 tl.compose(set, partial(map, tl.first)),\n", - " 125 2 605.0 302.5 0.0 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", - " 126 1 15.0 15.0 0.0 \n", - " 127 1 939.0 939.0 0.0 while idx:\n", - " 128 new_pairs = set()\n", - " 129 58934 51804.0 0.9 0.0 most = max(que)\n", - " 130 58933 88008.0 1.5 0.0 \n", - " 131 58933 129596.0 2.2 0.0 #print(most, que[most])\n", - " 132 #_, (pair, terms) = max((len(tl.second(item)), item) for item in idx.items())\n", - " 133 #pair, terms = max(idx.items(), key=tl.compose(len,tl.second))\n", - " 134 \n", - " 135 que_most = que[most]\n", - " 136 pair = que_most.pop()\n", - " 137 58933 56237.0 1.0 0.0 if not que_most:\n", - " 138 58933 74910.0 1.3 0.0 del que[most]\n", - " 139 58933 51279.0 0.9 0.0 terms = idx[pair]\n", - " 140 307 339.0 1.1 0.0 \n", - " 141 58933 412141.0 7.0 0.1 p = _new_product(variables, *pair)\n", - " 142 constraints.append((pair, p))\n", - " 143 58933 309915.0 5.3 0.1 del idx[pair]\n", - " 144 58933 77720.0 1.3 0.0 pset = {p}\n", - " 145 58933 73491.0 1.2 0.0 \n", - " 146 58933 64554.0 1.1 0.0 for term, bias in terms.items():\n", - " 147 for pair2 in map(frozenset, (itertools.combinations(term, 2))):\n", - " 148 349630 715848.0 2.0 0.2 if pair2 != pair:\n", - " 149 26322163 31601354.0 1.2 8.7 if pair2 & pair:\n", - " 150 26031466 23522489.0 0.9 6.4 count = len(idx[pair2])\n", - " 151 25740769 24791172.0 1.0 6.8 que_count = que[count]\n", - " 152 5919520 10542398.0 1.8 2.9 que_count.remove(pair2)\n", - " 153 5919520 7283210.0 1.2 2.0 if not que_count:\n", - " 154 5919520 11160269.0 1.9 3.1 del que[count]\n", - " 155 5919520 5136317.0 0.9 1.4 if count > 1:\n", - " 156 1275146 1258590.0 1.0 0.3 que[count - 1].add(pair2)\n", - " 157 5919520 5160611.0 0.9 1.4 idx_pair2 = idx[pair2]\n", - " 158 5499963 9027859.0 1.6 2.5 del idx_pair2[term]\n", - " 159 25740769 38298017.0 1.5 10.5 if not idx_pair2:\n", - " 160 25740769 46003860.0 1.8 12.6 del idx[pair2]\n", - " 161 25740769 21756609.0 0.8 6.0 \n", - " 162 807706 870552.0 1.1 0.2 new_term = (term - pair) | pset\n", - " 163 if len(new_term) <= 2:\n", - " 164 290697 1244477.0 4.3 0.3 reduced_terms.append((new_term, bias))\n", - " 165 290697 381118.0 1.3 0.1 else:\n", - " 166 18209 28056.0 1.5 0.0 for new_pair in map(frozenset, itertools.combinations(new_term, 2)):\n", - " 167 idx[new_pair][new_term] = bias\n", - " 168 23035288 29258154.0 1.3 8.0 if p in new_pair:\n", - " 169 22762800 46979493.0 2.1 12.9 new_pairs.add(new_pair)\n", - " 170 22762800 20147204.0 0.9 5.5 \n", - " 171 2941551 3400857.0 1.2 0.9 for new_pair in new_pairs:\n", - " 172 que[len(idx[new_pair])].add(new_pair)\n", - " 173 536148 505010.0 0.9 0.1 \n", - " 174 477215 744440.0 1.6 0.2 return reduced_terms, constraints\n", + " 121 def reduce_terms(bp):\n", + " 122 1 8412.0 8412.0 0.0 variables = bp.variables\n", + " 123 1 3.0 3.0 0.0 constraints = []\n", + " 124 1 20049.0 20049.0 0.0 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", + " 125 \n", + " 126 2 138.0 69.0 0.0 idx = defaultdict(\n", + " 127 1 0.0 0.0 0.0 dict,\n", + " 128 2 3123591.0 1561795.5 2.3 tl.valmap(\n", + " 129 1 8.0 8.0 0.0 tl.compose(dict, partial(map, tl.second)),\n", + " 130 2 12526859.0 6263429.5 9.0 tl.groupby(\n", + " 131 1 1.0 1.0 0.0 tl.first,\n", + " 132 2 2.0 1.0 0.0 (\n", + " 133 (frozenset(pair), item)\n", + " 134 1 4.0 4.0 0.0 for item in bp.items()\n", + " 135 if len(term := tl.first(item)) >= 3\n", + " 136 for pair in itertools.combinations(term, 2) ))))\n", + " 137 \n", + " 138 2 14.0 7.0 0.0 que = defaultdict(\n", + " 139 1 2.0 2.0 0.0 set,\n", + " 140 2 330.0 165.0 0.0 tl.valmap(\n", + " 141 1 8.0 8.0 0.0 tl.compose(set, partial(map, tl.first)),\n", + " 142 1 541.0 541.0 0.0 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", + " 143 \n", + " 144 57784 41700.0 0.7 0.0 while idx:\n", + " 145 57783 59630.0 1.0 0.0 new_pairs = set()\n", + " 146 57783 85719.0 1.5 0.1 most = max(que)\n", + " 147 57783 44164.0 0.8 0.0 que_most = que[most]\n", + " 148 57783 54744.0 0.9 0.0 pair = que_most.pop()\n", + " 149 57783 41427.0 0.7 0.0 if not que_most:\n", + " 150 326 284.0 0.9 0.0 del que[most]\n", + " 151 57783 258140.0 4.5 0.2 terms = idx.pop(pair)\n", + " 152 \n", + " 153 57783 178208.0 3.1 0.1 prod_var = _new_product(variables, *pair)\n", + " 154 57783 65217.0 1.1 0.0 constraints.append((pair, prod_var))\n", + " 155 57783 49162.0 0.9 0.0 prod_var_set = {prod_var}\n", + " 156 \n", + " 157 348260 444114.0 1.3 0.3 for old_term, bias in terms.items():\n", + " 158 290477 702133.0 2.4 0.5 common_subterm = (old_term - pair)\n", + " 159 290477 347608.0 1.2 0.3 new_term = common_subterm | prod_var_set\n", + " 160 \n", + " 161 6233905 6447556.0 1.0 4.7 for old_pair in map(frozenset, (itertools.product(pair, common_subterm))):\n", + " 162 5943428 15522741.0 2.6 11.2 _decrement_count(idx, que, old_pair)\n", + " 163 5943428 9631446.0 1.6 7.0 _remove_old(idx, old_term, old_pair)\n", + " 164 \n", + " 165 20299019 17587151.0 0.9 12.7 for common_pair in map(frozenset, (itertools.combinations(common_subterm, 2))):\n", + " 166 20008542 30545892.0 1.5 22.0 idx[common_pair][new_term] = bias\n", + " 167 20008542 28864233.0 1.4 20.8 _remove_old(idx, old_term, common_pair)\n", + " 168 \n", + " 169 290477 316414.0 1.1 0.2 if len(new_term) > 2:\n", + " 170 3226051 4315120.0 1.3 3.1 for new_pair in (frozenset((prod_var, v)) for v in common_subterm):\n", + " 171 2953644 3801197.0 1.3 2.7 idx[new_pair][new_term] = bias\n", + " 172 2953644 2534485.0 0.9 1.8 new_pairs.add(new_pair)\n", + " 173 else:\n", + " 174 18070 15985.0 0.9 0.0 reduced_terms.append((new_term, bias))\n", " 175 \n", - " 176 1 1.0 1.0 0.0 \n", - " 177 def make_quadratic(poly, strength, vartype=None, bqm=None):\n", - " 178 \"\"\"Create a binary quadratic model from a higher order polynomial.\n", - " 179 \n", - " 180 Args:\n", - " 181 poly (dict):\n", - " 182 Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of\n", - " 183 variables and `bias` the associated bias.\n", - " 184 \n", - " 185 strength (float):\n", - " 186 The energy penalty for violating the prodcut constraint.\n", - " 187 Insufficient strength can result in the binary quadratic model not\n", - " 188 having the same minimizations as the polynomial.\n", - " 189 \n", - " 190 vartype (:class:`.Vartype`/str/set, optional):\n", - " 191 Variable type for the binary quadratic model. Accepted input values:\n", - " 192 \n", - " 193 * :class:`.Vartype.SPIN`, ``'SPIN'``, ``{-1, 1}``\n", - " 194 * :class:`.Vartype.BINARY`, ``'BINARY'``, ``{0, 1}``\n", - " 195 \n", - " 196 If `bqm` is provided, `vartype` is not required.\n", - " 197 \n", - " 198 bqm (:class:`.BinaryQuadraticModel`, optional):\n", - " 199 The terms of the reduced polynomial are added to this binary quadratic model.\n", - " 200 If not provided, a new binary quadratic model is created.\n", - " 201 \n", - " 202 Returns:\n", - " 203 :class:`.BinaryQuadraticModel`\n", - " 204 \n", - " 205 Examples:\n", - " 206 \n", - " 207 >>> poly = {(0,): -1, (1,): 1, (2,): 1.5, (0, 1): -1, (0, 1, 2): -2}\n", - " 208 >>> bqm = dimod.make_quadratic(poly, 5.0, dimod.SPIN)\n", - " 209 \n", - " 210 \"\"\"\n", - " 211 if vartype is None:\n", - " 212 if bqm is None:\n", - " 213 raise ValueError(\"one of vartype or bqm must be provided\")\n", - " 214 else:\n", - " 215 vartype = bqm.vartype\n", - " 216 else:\n", - " 217 vartype = as_vartype(vartype) # handle other vartype inputs\n", - " 218 if bqm is None:\n", - " 219 bqm = BinaryQuadraticModel.empty(vartype)\n", - " 220 else:\n", - " 221 bqm = bqm.change_vartype(vartype, inplace=False)\n", - " 222 \n", - " 223 # for backwards compatibility, add an info field\n", - " 224 if not hasattr(bqm, 'info'):\n", - " 225 bqm.info = {}\n", - " 226 bqm.info['reduction'] = {}\n", - " 227 \n", - " 228 if poly.vartype !=vartype:\n", - " 229 poly = BinaryPolynomial(poly, vartype=vartype)\n", - " 230 \n", - " 231 variables = set().union(*poly)\n", - " 232 reduced_terms, constraints = reduce_terms(poly)\n", - " 233 \n", - " 234 for (u, v), p in constraints:\n", - " 235 \n", - " 236 # add a constraint enforcing the relationship between p == u*v\n", - " 237 if vartype is Vartype.BINARY:\n", - " 238 constraint = _binary_product([u, v, p])\n", - " 239 bqm.info['reduction'][(u, v)] = {'product': p}\n", - " 240 elif vartype is Vartype.SPIN:\n", - " 241 aux = _new_aux(variables, u, v) # need an aux in SPIN-space\n", - " 242 constraint = _spin_product([u, v, p, aux])\n", - " 243 bqm.info['reduction'][(u, v)] = {'product': p, 'auxiliary': aux}\n", - " 244 else:\n", - " 245 raise RuntimeError(\"unknown vartype: {!r}\".format(vartype))\n", - " 246 \n", - " 247 # scale constraint and update the polynomial with it\n", - " 248 constraint.scale(strength)\n", - " 249 for v, bias in constraint.linear.items():\n", - " 250 bqm.add_variable(v, bias)\n", - " 251 for uv, bias in constraint.quadratic.items():\n", - " 252 bqm.add_interaction(*uv, bias)\n", - " 253 bqm.offset += constraint.offset\n", - " 254 \n", - " 255 for term, bias in reduced_terms:\n", - " 256 if len(term) == 2:\n", - " 257 bqm.add_interaction(*term , bias)\n", - " 258 elif len(term) == 1:\n", - " 259 bqm.add_variable(*term, bias)\n", - " 260 elif len(term) == 0:\n", - " 261 bqm.offset += bias\n", - " 262 else:\n", - " 263 # still has higher order terms, this shouldn't happen\n", - " 264 msg = ('Internal error: not all higher-order terms were reduced. '\n", - " 265 'Please file a bug report.')\n", - " 266 raise RuntimeError(msg)\n", - " 267 \n", - " 268 return bqm" + " 176 530947 400212.0 0.8 0.3 for new_pair in new_pairs:\n", + " 177 473164 545266.0 1.2 0.4 que[len(idx[new_pair])].add(new_pair)\n", + " 178 \n", + " 179 1 1.0 1.0 0.0 return reduced_terms, constraints" ] }, "metadata": {}, @@ -2162,7 +1830,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 44, "id": "1f1a5a0c-5a2f-4227-9f4b-2b3f4f696ce2", "metadata": {}, "outputs": [ @@ -2170,17 +1838,17 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 13.2 ms, sys: 9 µs, total: 13.2 ms\n", - "Wall time: 12.1 ms\n" + "CPU times: user 990 µs, sys: 0 ns, total: 990 µs\n", + "Wall time: 994 µs\n" ] }, { "data": { "text/plain": [ - "92" + "23" ] }, - "execution_count": 46, + "execution_count": 44, "metadata": {}, "output_type": "execute_result" } @@ -2191,113 +1859,16 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 45, "id": "1963c838-558b-4257-81d2-968c9648ea14", "metadata": {}, "outputs": [ { - "data": { - "text/plain": [ - "\u001b[0;31mSignature:\u001b[0m \u001b[0mmake_quadratic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstrength\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mSource:\u001b[0m \n", - "\u001b[0;32mdef\u001b[0m \u001b[0mmake_quadratic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstrength\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;34m\"\"\"Create a binary quadratic model from a higher order polynomial.\u001b[0m\n", - "\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m Args:\u001b[0m\n", - "\u001b[0;34m poly (dict):\u001b[0m\n", - "\u001b[0;34m Polynomial as a dict of form {term: bias, ...}, where `term` is a tuple of\u001b[0m\n", - "\u001b[0;34m variables and `bias` the associated bias.\u001b[0m\n", - "\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m strength (float):\u001b[0m\n", - "\u001b[0;34m The energy penalty for violating the prodcut constraint.\u001b[0m\n", - "\u001b[0;34m Insufficient strength can result in the binary quadratic model not\u001b[0m\n", - "\u001b[0;34m having the same minimizations as the polynomial.\u001b[0m\n", - "\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m vartype (:class:`.Vartype`/str/set, optional):\u001b[0m\n", - "\u001b[0;34m Variable type for the binary quadratic model. Accepted input values:\u001b[0m\n", - "\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m * :class:`.Vartype.SPIN`, ``'SPIN'``, ``{-1, 1}``\u001b[0m\n", - "\u001b[0;34m * :class:`.Vartype.BINARY`, ``'BINARY'``, ``{0, 1}``\u001b[0m\n", - "\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m If `bqm` is provided, `vartype` is not required.\u001b[0m\n", - "\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m bqm (:class:`.BinaryQuadraticModel`, optional):\u001b[0m\n", - "\u001b[0;34m The terms of the reduced polynomial are added to this binary quadratic model.\u001b[0m\n", - "\u001b[0;34m If not provided, a new binary quadratic model is created.\u001b[0m\n", - "\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m Returns:\u001b[0m\n", - "\u001b[0;34m :class:`.BinaryQuadraticModel`\u001b[0m\n", - "\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m Examples:\u001b[0m\n", - "\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m >>> poly = {(0,): -1, (1,): 1, (2,): 1.5, (0, 1): -1, (0, 1, 2): -2}\u001b[0m\n", - "\u001b[0;34m >>> bqm = dimod.make_quadratic(poly, 5.0, dimod.SPIN)\u001b[0m\n", - "\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mbqm\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"one of vartype or bqm must be provided\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mas_vartype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# handle other vartype inputs\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mbqm\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mBinaryQuadraticModel\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mempty\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mchange_vartype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minplace\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;31m# for backwards compatibility, add an info field\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mhasattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbqm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'info'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'reduction'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mpoly\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvartype\u001b[0m \u001b[0;34m!=\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mpoly\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mBinaryPolynomial\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvartype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mvariables\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mset\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0munion\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mreduced_terms\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconstraints\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdimod\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhigherorder\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreduce_terms\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpoly\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mconstraints\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;31m# add a constraint enforcing the relationship between p == u*v\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mVartype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mBINARY\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mconstraint\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_binary_product\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'reduction'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m'product'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mvartype\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mVartype\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mSPIN\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0maux\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_new_aux\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvariables\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# need an aux in SPIN-space\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mconstraint\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_spin_product\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maux\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'reduction'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mu\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m{\u001b[0m\u001b[0;34m'product'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'auxiliary'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0maux\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"unknown vartype: {!r}\"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvartype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;31m# scale constraint and update the polynomial with it\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mscale\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstrength\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinear\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_variable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0muv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mquadratic\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_interaction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0muv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moffset\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mconstraint\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moffset\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mreduced_terms\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_interaction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mterm\u001b[0m \u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_variable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mterm\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moffset\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mbias\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;31m# still has higher order terms, this shouldn't happen\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0mmsg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m'Internal error: not all higher-order terms were reduced. '\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;34m'Please file a bug report.'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\n", - "\u001b[0;34m\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mbqm\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mFile:\u001b[0m /tmp/ipykernel_5867/3448239133.py\n", - "\u001b[0;31mType:\u001b[0m function\n" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + "Object `make_quadratic` not found.\n" + ] } ], "source": [ @@ -2306,7 +1877,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 46, "id": "ed0769ec-6d1b-40d2-b110-989f2f068c86", "metadata": {}, "outputs": [ @@ -2315,7 +1886,7 @@ "evalue": "invalid syntax (3330683553.py, line 1)", "output_type": "error", "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_5867/3330683553.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m BinaryPolynomial.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_7212/3330683553.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m BinaryPolynomial.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" ] } ], @@ -2345,12 +1916,54 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "id": "fac7547a-db9e-4e35-8a5d-99e2aa72d137", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " " + ] + }, + { + "data": { + "text/plain": [ + " 71617713 function calls in 62.426 seconds\n", + "\n", + " Ordered by: cumulative time\n", + " List reduced from 100 to 20 due to restriction <20>\n", + "\n", + " ncalls tottime percall cumtime percall filename:lineno(function)\n", + " 1 0.000 0.000 62.426 62.426 {built-in method builtins.exec}\n", + " 1 0.052 0.052 62.426 62.426 :1()\n", + " 1 0.627 0.627 62.374 62.374 utils.py:182(make_quadratic)\n", + " 1 28.181 28.181 57.161 57.161 utils.py:121(reduce_terms)\n", + " 25951970 9.679 0.000 9.679 0.000 utils.py:114(_remove_old)\n", + " 3280262 8.966 0.000 9.001 0.000 utils.py:132()\n", + " 5943428 4.742 0.000 7.417 0.000 utils.py:104(_decrement_count)\n", + " 3226051 2.157 0.000 2.157 0.000 utils.py:170()\n", + " 57783 0.082 0.000 2.010 0.000 utils.py:63(_binary_product)\n", + " 57784 0.087 0.000 1.928 0.000 binary_quadratic_model.py:93(__init__)\n", + " 57783 0.278 0.000 1.821 0.000 binary_quadratic_model.py:136(_init_components)\n", + " 5943428 1.504 0.000 1.504 0.000 {method 'remove' of 'set' objects}\n", + " 9011363 1.272 0.000 1.272 0.000 {method 'add' of 'set' objects}\n", + " 286635 0.148 0.000 1.029 0.000 _collections_abc.py:742(__iter__)\n", + " 365146 0.625 0.000 1.001 0.000 {method 'add_quadratic' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", + " 2789747 0.370 0.000 0.740 0.000 abc.py:96(__instancecheck__)\n", + " 173351 0.214 0.000 0.591 0.000 decorators.py:474(wrapper)\n", + " 191797 0.044 0.000 0.581 0.000 binary_quadratic_model.py:709(add_interaction)\n", + " 231132 0.082 0.000 0.546 0.000 quadratic.py:136(__iter__)\n", + " 57783 0.165 0.000 0.479 0.000 binary_quadratic_model.py:654(add_linear_from)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "%prun -s cumtime -l 20 make_quadratic(bp, 100, vartype='BINARY')" + "%prun -s cumtime -l 20 dimod.make_quadratic(bp, 100, vartype='BINARY')" ] }, { From 679e15f77f2f5fea8fb26016df3c25a5bf2c3f12 Mon Sep 17 00:00:00 2001 From: Daniel Mahler Date: Tue, 21 Sep 2021 07:03:31 -0500 Subject: [PATCH 9/9] more simplification --- dimod/higherorder/utils.py | 34 +-- polynomial-perf.ipynb | 512 +++++++++++++++++-------------------- 2 files changed, 244 insertions(+), 302 deletions(-) diff --git a/dimod/higherorder/utils.py b/dimod/higherorder/utils.py index 1b85f59c5..93c57546c 100644 --- a/dimod/higherorder/utils.py +++ b/dimod/higherorder/utils.py @@ -19,7 +19,6 @@ from collections import defaultdict from functools import partial -import cytoolz as tl import numpy as np @@ -121,25 +120,20 @@ def _remove_old(idx, term, pair): def reduce_terms(bp): variables = bp.variables constraints = [] - reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2] - - idx = defaultdict( - dict, - tl.valmap( - tl.compose(dict, partial(map, tl.second)), - tl.groupby( - tl.first, - ( - (frozenset(pair), item) - for item in bp.items() - if len(term := tl.first(item)) >= 3 - for pair in itertools.combinations(term, 2) )))) - - que = defaultdict( - set, - tl.valmap( - tl.compose(set, partial(map, tl.first)), - tl.groupby(tl.second, tl.valmap(len, idx).items()))) + + reduced_terms = [] + idx = defaultdict(dict) + for item in bp.items(): + term, bias = item + if len(term) <= 2: + reduced_terms.append(item) + else: + for pair in itertools.combinations(term, 2): + idx[frozenset(pair)][term] = bias + + que = defaultdict(set) + for pair, terms in idx.items(): + que[len(terms)].add(pair) while idx: new_pairs = set() diff --git a/polynomial-perf.ipynb b/polynomial-perf.ipynb index c16f037df..549083485 100644 --- a/polynomial-perf.ipynb +++ b/polynomial-perf.ipynb @@ -704,8 +704,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 114 ms, sys: 9.46 ms, total: 124 ms\n", - "Wall time: 122 ms\n" + "CPU times: user 96.8 ms, sys: 9.77 ms, total: 107 ms\n", + "Wall time: 106 ms\n" ] } ], @@ -722,14 +722,14 @@ { "data": { "text/plain": [ - "count 19249.000000\n", - "mean 50.950803\n", - "std 51.208656\n", + "count 18962.000000\n", + "mean 51.737106\n", + "std 52.324975\n", "min 0.000000\n", "25% 14.000000\n", - "50% 35.000000\n", - "75% 70.000000\n", - "max 515.000000\n", + "50% 36.000000\n", + "75% 72.000000\n", + "max 535.000000\n", "dtype: float64" ] }, @@ -760,10 +760,10 @@ "name": "stdout", "output_type": "stream", "text": [ - "M\tdimod/higherorder/utils.py\n", "D\tpolynomial-perf.ipynb\n", "Already on 'binary-polynomial'\n", - "Your branch is up to date with 'origin/binary-polynomial'.\n", + "Your branch is ahead of 'origin/binary-polynomial' by 1 commit.\n", + " (use \"git push\" to publish your local commits)\n", "No stash entries found.\n" ] } @@ -838,20 +838,20 @@ { "data": { "text/plain": [ - " 405071 function calls (404991 primitive calls) in 0.183 seconds\n", + " 399010 function calls (398930 primitive calls) in 0.179 seconds\n", "\n", " Ordered by: cumulative time\n", " List reduced from 46 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 0.183 0.183 {built-in method builtins.exec}\n", - " 1 0.000 0.000 0.183 0.183 :1()\n", - " 1 0.000 0.000 0.183 0.183 decorators.py:289(new_f)\n", - " 1 0.012 0.012 0.183 0.183 polynomial.py:108(__init__)\n", - " 19249 0.127 0.000 0.170 0.000 polynomial.py:40(freeze_term)\n", - " 347121 0.041 0.000 0.041 0.000 polynomial.py:47()\n", - " 19259 0.002 0.000 0.002 0.000 {built-in method builtins.isinstance}\n", - " 19250 0.001 0.000 0.001 0.000 {method 'items' of 'dict' objects}\n", + " 1 0.000 0.000 0.179 0.179 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.179 0.179 :1()\n", + " 1 0.000 0.000 0.178 0.178 decorators.py:289(new_f)\n", + " 1 0.013 0.013 0.178 0.178 polynomial.py:108(__init__)\n", + " 18962 0.123 0.000 0.165 0.000 polynomial.py:40(freeze_term)\n", + " 341921 0.039 0.000 0.039 0.000 polynomial.py:47()\n", + " 18972 0.001 0.000 0.002 0.000 {built-in method builtins.isinstance}\n", + " 18963 0.001 0.000 0.001 0.000 {method 'items' of 'dict' objects}\n", " 1 0.000 0.000 0.000 0.000 abc.py:96(__instancecheck__)\n", " 1 0.000 0.000 0.000 0.000 {built-in method _abc._abc_instancecheck}\n", " 41/1 0.000 0.000 0.000 0.000 abc.py:100(__subclasscheck__)\n", @@ -861,8 +861,8 @@ " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2124(_signature_from_function)\n", " 1 0.000 0.000 0.000 0.000 decorators.py:281(_enforce_single_arg)\n", - " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)\n", " 3 0.000 0.000 0.000 0.000 inspect.py:2489(__init__)\n", + " 1 0.000 0.000 0.000 0.000 vartypes.py:127(as_vartype)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:2772(__init__)" ] }, @@ -909,18 +909,18 @@ " \n", " \n", " count\n", - " 18500.000000\n", - " 18500.000000\n", + " 18203.000000\n", + " 18203.000000\n", " \n", " \n", " mean\n", - " 17.698595\n", - " 1.040486\n", + " 17.718838\n", + " 1.041696\n", " \n", " \n", " std\n", - " 7.689292\n", - " 2.693415\n", + " 7.690828\n", + " 2.906779\n", " \n", " \n", " min\n", @@ -944,8 +944,8 @@ " \n", " \n", " max\n", - " 38.000000\n", - " 364.000000\n", + " 39.000000\n", + " 390.000000\n", " \n", " \n", "\n", @@ -953,14 +953,14 @@ ], "text/plain": [ " 0 1\n", - "count 18500.000000 18500.000000\n", - "mean 17.698595 1.040486\n", - "std 7.689292 2.693415\n", + "count 18203.000000 18203.000000\n", + "mean 17.718838 1.041696\n", + "std 7.690828 2.906779\n", "min 0.000000 1.000000\n", "25% 12.000000 1.000000\n", "50% 19.000000 1.000000\n", "75% 24.000000 1.000000\n", - "max 38.000000 364.000000" + "max 39.000000 390.000000" ] }, "execution_count": 9, @@ -994,7 +994,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "522 ms ± 9.21 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + "528 ms ± 55.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] }, { @@ -1023,7 +1023,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "736 ms ± 18.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + "793 ms ± 77.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] }, { @@ -1118,31 +1118,31 @@ { "data": { "text/plain": [ - " 1827867 function calls (1827862 primitive calls) in 0.479 seconds\n", + " 1799999 function calls (1799994 primitive calls) in 0.717 seconds\n", "\n", " Ordered by: cumulative time\n", " List reduced from 67 to 20 due to restriction <20>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 0.479 0.479 {built-in method builtins.exec}\n", - " 1 0.000 0.000 0.478 0.478 :1()\n", - " 2/1 0.219 0.109 0.478 0.478 polynomial.py:236(relabel_variables)\n", - " 691848 0.105 0.000 0.141 0.000 polynomial.py:260()\n", - " 55503 0.023 0.000 0.050 0.000 _collections_abc.py:742(__iter__)\n", - " 654852 0.036 0.000 0.036 0.000 {method 'get' of 'dict' objects}\n", - " 1 0.000 0.000 0.031 0.031 polynomial.py:181(copy)\n", - " 1 0.000 0.000 0.031 0.031 decorators.py:289(new_f)\n", - " 1 0.010 0.010 0.031 0.031 polynomial.py:108(__init__)\n", - " 55500 0.016 0.000 0.026 0.000 polynomial.py:153(__getitem__)\n", - " 129496 0.018 0.000 0.024 0.000 polynomial.py:35(asfrozenset)\n", - " 36998 0.016 0.000 0.024 0.000 polynomial.py:162(__setitem__)\n", - " 36998 0.011 0.000 0.018 0.000 polynomial.py:124(__delitem__)\n", - " 1 0.003 0.003 0.014 0.014 polynomial.py:169(variables)\n", - " 1 0.011 0.011 0.011 0.011 {method 'union' of 'set' objects}\n", - " 148005 0.007 0.000 0.007 0.000 {built-in method builtins.isinstance}\n", - " 18500 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", + " 1 0.000 0.000 0.717 0.717 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.717 0.717 :1()\n", + " 2/1 0.370 0.185 0.717 0.717 polynomial.py:236(relabel_variables)\n", + " 681478 0.127 0.000 0.169 0.000 polynomial.py:260()\n", + " 54612 0.036 0.000 0.074 0.000 _collections_abc.py:742(__iter__)\n", + " 1 0.000 0.000 0.046 0.046 polynomial.py:181(copy)\n", + " 1 0.000 0.000 0.046 0.046 decorators.py:289(new_f)\n", + " 1 0.017 0.017 0.046 0.046 polynomial.py:108(__init__)\n", + " 645076 0.042 0.000 0.042 0.000 {method 'get' of 'dict' objects}\n", + " 36404 0.031 0.000 0.040 0.000 polynomial.py:162(__setitem__)\n", + " 54609 0.027 0.000 0.038 0.000 polynomial.py:153(__getitem__)\n", + " 127417 0.020 0.000 0.028 0.000 polynomial.py:35(asfrozenset)\n", + " 36404 0.018 0.000 0.025 0.000 polynomial.py:124(__delitem__)\n", + " 1 0.001 0.001 0.018 0.018 polynomial.py:169(variables)\n", + " 1 0.017 0.017 0.017 0.017 {method 'union' of 'set' objects}\n", + " 145629 0.009 0.000 0.009 0.000 {built-in method builtins.isinstance}\n", + " 18203 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", " 3 0.000 0.000 0.000 0.000 utilities.py:351(iter_safe_relabels)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)" ] }, @@ -1170,7 +1170,7 @@ { "data": { "text/plain": [ - " 1827864 function calls (1827859 primitive calls) in 0.425 seconds\n", + " 1799996 function calls (1799991 primitive calls) in 0.425 seconds\n", "\n", " Ordered by: cumulative time\n", " List reduced from 64 to 20 due to restriction <20>\n", @@ -1178,24 +1178,24 @@ " ncalls tottime percall cumtime percall filename:lineno(function)\n", " 1 0.000 0.000 0.425 0.425 {built-in method builtins.exec}\n", " 1 0.000 0.000 0.425 0.425 :1()\n", - " 2/1 0.162 0.081 0.425 0.425 polynomial.py:236(relabel_variables)\n", - " 691848 0.107 0.000 0.144 0.000 polynomial.py:260()\n", - " 55503 0.029 0.000 0.055 0.000 _collections_abc.py:742(__iter__)\n", - " 654852 0.037 0.000 0.037 0.000 {method 'get' of 'dict' objects}\n", - " 1 0.000 0.000 0.031 0.031 polynomial.py:181(copy)\n", - " 1 0.000 0.000 0.031 0.031 decorators.py:289(new_f)\n", - " 1 0.009 0.009 0.030 0.030 polynomial.py:108(__init__)\n", - " 55500 0.016 0.000 0.026 0.000 polynomial.py:153(__getitem__)\n", - " 36998 0.017 0.000 0.025 0.000 polynomial.py:162(__setitem__)\n", - " 129496 0.018 0.000 0.024 0.000 polynomial.py:35(asfrozenset)\n", - " 36998 0.011 0.000 0.018 0.000 polynomial.py:124(__delitem__)\n", - " 1 0.001 0.001 0.009 0.009 polynomial.py:169(variables)\n", - " 1 0.008 0.008 0.008 0.008 {method 'union' of 'set' objects}\n", - " 148005 0.007 0.000 0.007 0.000 {built-in method builtins.isinstance}\n", - " 18500 0.003 0.000 0.004 0.000 polynomial.py:40(freeze_term)\n", - " 3 0.000 0.000 0.000 0.000 utilities.py:351(iter_safe_relabels)\n", + " 2/1 0.165 0.082 0.425 0.425 polynomial.py:236(relabel_variables)\n", + " 681478 0.106 0.000 0.141 0.000 polynomial.py:260()\n", + " 54612 0.025 0.000 0.053 0.000 _collections_abc.py:742(__iter__)\n", + " 645076 0.036 0.000 0.036 0.000 {method 'get' of 'dict' objects}\n", + " 1 0.000 0.000 0.029 0.029 polynomial.py:181(copy)\n", + " 1 0.000 0.000 0.029 0.029 decorators.py:289(new_f)\n", + " 1 0.008 0.008 0.029 0.029 polynomial.py:108(__init__)\n", + " 54609 0.019 0.000 0.028 0.000 polynomial.py:153(__getitem__)\n", + " 36404 0.017 0.000 0.024 0.000 polynomial.py:162(__setitem__)\n", + " 127417 0.017 0.000 0.024 0.000 polynomial.py:35(asfrozenset)\n", + " 36404 0.011 0.000 0.018 0.000 polynomial.py:124(__delitem__)\n", + " 1 0.002 0.002 0.012 0.012 polynomial.py:169(variables)\n", + " 1 0.010 0.010 0.010 0.010 {method 'union' of 'set' objects}\n", + " 145629 0.007 0.000 0.007 0.000 {built-in method builtins.isinstance}\n", + " 18203 0.002 0.000 0.003 0.000 polynomial.py:40(freeze_term)\n", " 1 0.000 0.000 0.000 0.000 inspect.py:1340(getcallargs)\n", - " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)" + " 1 0.000 0.000 0.000 0.000 inspect.py:1102(getfullargspec)\n", + " 1 0.000 0.000 0.000 0.000 inspect.py:2218(_signature_from_callable)" ] }, "metadata": {}, @@ -1314,8 +1314,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 9.81 s, sys: 362 ms, total: 10.2 s\n", - "Wall time: 10.2 s\n" + "CPU times: user 11.4 s, sys: 571 ms, total: 12 s\n", + "Wall time: 12 s\n" ] } ], @@ -1400,7 +1400,7 @@ { "data": { "text/plain": [ - "2695" + "2679" ] }, "execution_count": 29, @@ -1423,7 +1423,7 @@ { "data": { "text/plain": [ - "frozenset({'J', 'w'})" + "frozenset({'K', 'u'})" ] }, "execution_count": 30, @@ -1513,7 +1513,7 @@ { "data": { "text/plain": [ - "[(frozenset({'J', 'w'}), 'w*J')]" + "[(frozenset({'K', 'u'}), 'u*K')]" ] }, "execution_count": 35, @@ -1548,11 +1548,11 @@ { "data": { "text/plain": [ - "((frozenset({'B', 'C'}), 2690),\n", - " (frozenset({'B', 'j'}), 2680),\n", - " (frozenset({'c', 't'}), 2677),\n", - " (frozenset({'A', 'V'}), 2676),\n", - " (frozenset({'B', 'O'}), 2674))" + "((frozenset({'V', 's'}), 2668),\n", + " (frozenset({'d', 't'}), 2658),\n", + " (frozenset({'U', 'V'}), 2656),\n", + " (frozenset({'M', 'V'}), 2655),\n", + " (frozenset({'C', 'V'}), 2649))" ] }, "execution_count": 37, @@ -1600,42 +1600,42 @@ { "data": { "text/plain": [ - " 71617730 function calls (71617722 primitive calls) in 59.048 seconds\n", + " 67534938 function calls (67534930 primitive calls) in 45.651 seconds\n", "\n", " Ordered by: cumulative time\n", - " List reduced from 106 to 30 due to restriction <30>\n", + " List reduced from 104 to 30 due to restriction <30>\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 59.048 59.048 {built-in method builtins.exec}\n", - " 1 0.021 0.021 59.048 59.048 :1()\n", - " 1 0.630 0.630 59.027 59.027 utils.py:182(make_quadratic)\n", - " 1 26.198 26.198 54.144 54.144 utils.py:121(reduce_terms)\n", - " 25951970 9.379 0.000 9.379 0.000 utils.py:114(_remove_old)\n", - " 3280262 8.620 0.000 8.652 0.000 utils.py:132()\n", - " 5943428 4.532 0.000 7.135 0.000 utils.py:104(_decrement_count)\n", - " 3226051 2.071 0.000 2.071 0.000 utils.py:170()\n", - " 57783 0.081 0.000 1.903 0.000 utils.py:63(_binary_product)\n", - " 57784 0.087 0.000 1.822 0.000 binary_quadratic_model.py:93(__init__)\n", - " 57783 0.280 0.000 1.715 0.000 binary_quadratic_model.py:136(_init_components)\n", - " 5943428 1.445 0.000 1.445 0.000 {method 'remove' of 'set' objects}\n", - " 9011363 1.248 0.000 1.248 0.000 {method 'add' of 'set' objects}\n", - " 365146 0.614 0.000 0.990 0.000 {method 'add_quadratic' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", - " 286635 0.143 0.000 0.825 0.000 _collections_abc.py:742(__iter__)\n", - " 2789747 0.368 0.000 0.736 0.000 abc.py:96(__instancecheck__)\n", - " 173351 0.212 0.000 0.586 0.000 decorators.py:474(wrapper)\n", - " 191797 0.045 0.000 0.574 0.000 binary_quadratic_model.py:709(add_interaction)\n", - " 57783 0.084 0.000 0.470 0.000 binary_quadratic_model.py:654(add_linear_from)\n", - " 7051542 0.451 0.000 0.451 0.000 {built-in method builtins.len}\n", - " 173400 0.268 0.000 0.400 0.000 {method 'add_variable' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", - " 2789747 0.367 0.000 0.367 0.000 {built-in method _abc._abc_instancecheck}\n", - " 231132 0.082 0.000 0.349 0.000 quadratic.py:136(__iter__)\n", - " 173349 0.066 0.000 0.298 0.000 quadratic.py:130(__getitem__)\n", - " 231132 0.256 0.000 0.256 0.000 _collections_abc.py:870(__iter__)\n", - " 231132 0.080 0.000 0.240 0.000 quadratic.py:176(__iter__)\n", - " 173349 0.110 0.000 0.197 0.000 {method 'add_linear' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", - " 362928 0.088 0.000 0.175 0.000 {built-in method builtins.isinstance}\n", - " 57784 0.135 0.000 0.168 0.000 binary_quadratic_model.py:187(_init_empty)\n", - " 231132 0.145 0.000 0.160 0.000 binary_quadratic_model.py:1252(iter_quadratic)" + " 1 0.000 0.000 45.651 45.651 {built-in method builtins.exec}\n", + " 1 0.023 0.023 45.651 45.651 :1()\n", + " 1 0.624 0.624 45.628 45.628 utils.py:176(make_quadratic)\n", + " 1 22.136 22.136 40.487 40.487 utils.py:120(reduce_terms)\n", + " 25594299 8.849 0.000 8.849 0.000 utils.py:113(_remove_old)\n", + " 5860386 4.291 0.000 6.749 0.000 utils.py:103(_decrement_count)\n", + " 3180742 2.057 0.000 2.057 0.000 utils.py:164()\n", + " 58153 0.083 0.000 1.989 0.000 utils.py:62(_binary_product)\n", + " 58154 0.087 0.000 1.906 0.000 binary_quadratic_model.py:93(__init__)\n", + " 58153 0.270 0.000 1.799 0.000 binary_quadratic_model.py:136(_init_components)\n", + " 5860386 1.356 0.000 1.356 0.000 {method 'remove' of 'set' objects}\n", + " 8889068 1.190 0.000 1.190 0.000 {method 'add' of 'set' objects}\n", + " 367069 0.642 0.000 1.022 0.000 {method 'add_quadratic' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", + " 269020 0.140 0.000 0.972 0.000 _collections_abc.py:742(__iter__)\n", + " 2805949 0.374 0.000 0.740 0.000 abc.py:96(__instancecheck__)\n", + " 174461 0.210 0.000 0.590 0.000 decorators.py:474(wrapper)\n", + " 192610 0.046 0.000 0.588 0.000 binary_quadratic_model.py:709(add_interaction)\n", + " 232612 0.080 0.000 0.514 0.000 quadratic.py:136(__iter__)\n", + " 58153 0.154 0.000 0.474 0.000 binary_quadratic_model.py:654(add_linear_from)\n", + " 6951364 0.434 0.000 0.434 0.000 {built-in method builtins.len}\n", + " 232612 0.422 0.000 0.422 0.000 _collections_abc.py:870(__iter__)\n", + " 174510 0.278 0.000 0.413 0.000 {method 'add_variable' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", + " 2805949 0.366 0.000 0.366 0.000 {built-in method _abc._abc_instancecheck}\n", + " 174459 0.065 0.000 0.295 0.000 quadratic.py:130(__getitem__)\n", + " 232612 0.078 0.000 0.236 0.000 quadratic.py:176(__iter__)\n", + " 174459 0.115 0.000 0.202 0.000 {method 'add_linear' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", + " 345387 0.086 0.000 0.173 0.000 {built-in method builtins.isinstance}\n", + " 58154 0.136 0.000 0.170 0.000 binary_quadratic_model.py:187(_init_empty)\n", + " 232612 0.143 0.000 0.158 0.000 binary_quadratic_model.py:1252(iter_quadratic)\n", + " 174459 0.095 0.000 0.147 0.000 {method 'get_linear' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}" ] }, "metadata": {}, @@ -1667,71 +1667,66 @@ "text/plain": [ "Timer unit: 1e-06 s\n", "\n", - "Total time: 0.000832 s\n", + "Total time: 0.006932 s\n", "File: /home/daniel/dimod/dimod/higherorder/utils.py\n", - "Function: reduce_terms at line 121\n", + "Function: reduce_terms at line 120\n", "\n", "Line # Hits Time Per Hit % Time Line Contents\n", "==============================================================\n", - " 121 def reduce_terms(bp):\n", - " 122 1 4.0 4.0 0.5 variables = bp.variables\n", - " 123 1 0.0 0.0 0.0 constraints = []\n", - " 124 1 14.0 14.0 1.7 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", - " 125 \n", - " 126 2 5.0 2.5 0.6 idx = defaultdict(\n", - " 127 1 1.0 1.0 0.1 dict,\n", - " 128 2 26.0 13.0 3.1 tl.valmap(\n", - " 129 1 7.0 7.0 0.8 tl.compose(dict, partial(map, tl.second)),\n", - " 130 2 82.0 41.0 9.9 tl.groupby(\n", - " 131 1 1.0 1.0 0.1 tl.first,\n", - " 132 2 2.0 1.0 0.2 (\n", - " 133 (frozenset(pair), item)\n", - " 134 1 2.0 2.0 0.2 for item in bp.items()\n", - " 135 if len(term := tl.first(item)) >= 3\n", - " 136 for pair in itertools.combinations(term, 2) ))))\n", + " 120 def reduce_terms(bp):\n", + " 121 1 4.0 4.0 0.1 variables = bp.variables\n", + " 122 1 1.0 1.0 0.0 constraints = []\n", + " 123 \n", + " 124 1 0.0 0.0 0.0 reduced_terms = []\n", + " 125 1 1.0 1.0 0.0 idx = defaultdict(dict)\n", + " 126 2 11.0 5.5 0.2 for item in bp.items():\n", + " 127 1 0.0 0.0 0.0 term, bias = item\n", + " 128 1 1.0 1.0 0.0 if len(term) <= 2:\n", + " 129 reduced_terms.append(item)\n", + " 130 else:\n", + " 131 232 106.0 0.5 1.5 for pair in itertools.combinations(term, 2):\n", + " 132 231 298.0 1.3 4.3 idx[frozenset(pair)][term] = bias\n", + " 133 \n", + " 134 1 1.0 1.0 0.0 que = defaultdict(set)\n", + " 135 232 127.0 0.5 1.8 for pair, terms in idx.items():\n", + " 136 231 151.0 0.7 2.2 que[len(terms)].add(pair)\n", " 137 \n", - " 138 2 2.0 1.0 0.2 que = defaultdict(\n", - " 139 1 1.0 1.0 0.1 set,\n", - " 140 2 7.0 3.5 0.8 tl.valmap(\n", - " 141 1 2.0 2.0 0.2 tl.compose(set, partial(map, tl.first)),\n", - " 142 1 11.0 11.0 1.3 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", - " 143 \n", - " 144 8 6.0 0.8 0.7 while idx:\n", - " 145 7 5.0 0.7 0.6 new_pairs = set()\n", - " 146 7 7.0 1.0 0.8 most = max(que)\n", - " 147 7 4.0 0.6 0.5 que_most = que[most]\n", - " 148 7 8.0 1.1 1.0 pair = que_most.pop()\n", - " 149 7 6.0 0.9 0.7 if not que_most:\n", - " 150 del que[most]\n", - " 151 7 8.0 1.1 1.0 terms = idx.pop(pair)\n", - " 152 \n", - " 153 7 17.0 2.4 2.0 prod_var = _new_product(variables, *pair)\n", - " 154 7 5.0 0.7 0.6 constraints.append((pair, prod_var))\n", - " 155 7 6.0 0.9 0.7 prod_var_set = {prod_var}\n", - " 156 \n", - " 157 14 11.0 0.8 1.3 for old_term, bias in terms.items():\n", - " 158 7 7.0 1.0 0.8 common_subterm = (old_term - pair)\n", - " 159 7 9.0 1.3 1.1 new_term = common_subterm | prod_var_set\n", - " 160 \n", - " 161 63 77.0 1.2 9.3 for old_pair in map(frozenset, (itertools.product(pair, common_subterm))):\n", - " 162 56 90.0 1.6 10.8 _decrement_count(idx, que, old_pair)\n", - " 163 56 78.0 1.4 9.4 _remove_old(idx, old_term, old_pair)\n", - " 164 \n", - " 165 63 54.0 0.9 6.5 for common_pair in map(frozenset, (itertools.combinations(common_subterm, 2))):\n", - " 166 56 46.0 0.8 5.5 idx[common_pair][new_term] = bias\n", - " 167 56 64.0 1.1 7.7 _remove_old(idx, old_term, common_pair)\n", - " 168 \n", - " 169 7 6.0 0.9 0.7 if len(new_term) > 2:\n", - " 170 33 39.0 1.2 4.7 for new_pair in (frozenset((prod_var, v)) for v in common_subterm):\n", - " 171 27 39.0 1.4 4.7 idx[new_pair][new_term] = bias\n", - " 172 27 23.0 0.9 2.8 new_pairs.add(new_pair)\n", - " 173 else:\n", - " 174 1 1.0 1.0 0.1 reduced_terms.append((new_term, bias))\n", - " 175 \n", - " 176 34 23.0 0.7 2.8 for new_pair in new_pairs:\n", - " 177 27 25.0 0.9 3.0 que[len(idx[new_pair])].add(new_pair)\n", - " 178 \n", - " 179 1 1.0 1.0 0.1 return reduced_terms, constraints" + " 138 21 15.0 0.7 0.2 while idx:\n", + " 139 20 19.0 0.9 0.3 new_pairs = set()\n", + " 140 20 22.0 1.1 0.3 most = max(que)\n", + " 141 20 14.0 0.7 0.2 que_most = que[most]\n", + " 142 20 19.0 0.9 0.3 pair = que_most.pop()\n", + " 143 20 15.0 0.8 0.2 if not que_most:\n", + " 144 del que[most]\n", + " 145 20 20.0 1.0 0.3 terms = idx.pop(pair)\n", + " 146 \n", + " 147 20 134.0 6.7 1.9 prod_var = _new_product(variables, *pair)\n", + " 148 20 12.0 0.6 0.2 constraints.append((pair, prod_var))\n", + " 149 20 11.0 0.6 0.2 prod_var_set = {prod_var}\n", + " 150 \n", + " 151 40 48.0 1.2 0.7 for old_term, bias in terms.items():\n", + " 152 20 32.0 1.6 0.5 common_subterm = (old_term - pair)\n", + " 153 20 20.0 1.0 0.3 new_term = common_subterm | prod_var_set\n", + " 154 \n", + " 155 440 386.0 0.9 5.6 for old_pair in map(frozenset, itertools.product(pair, common_subterm)):\n", + " 156 420 707.0 1.7 10.2 _decrement_count(idx, que, old_pair)\n", + " 157 420 560.0 1.3 8.1 _remove_old(idx, old_term, old_pair)\n", + " 158 \n", + " 159 1350 886.0 0.7 12.8 for common_pair in map(frozenset, itertools.combinations(common_subterm, 2)):\n", + " 160 1330 965.0 0.7 13.9 idx[common_pair][new_term] = bias\n", + " 161 1330 1264.0 1.0 18.2 _remove_old(idx, old_term, common_pair)\n", + " 162 \n", + " 163 20 19.0 0.9 0.3 if len(new_term) > 2:\n", + " 164 228 253.0 1.1 3.6 for new_pair in (frozenset((prod_var, v)) for v in common_subterm):\n", + " 165 209 174.0 0.8 2.5 idx[new_pair][new_term] = bias\n", + " 166 209 305.0 1.5 4.4 new_pairs.add(new_pair)\n", + " 167 else:\n", + " 168 1 4.0 4.0 0.1 reduced_terms.append((new_term, bias))\n", + " 169 \n", + " 170 229 137.0 0.6 2.0 for new_pair in new_pairs:\n", + " 171 209 190.0 0.9 2.7 que[len(idx[new_pair])].add(new_pair)\n", + " 172 \n", + " 173 1 0.0 0.0 0.0 return reduced_terms, constraints" ] }, "metadata": {}, @@ -1744,7 +1739,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 43, "id": "1934c5e7-5e31-4939-aae5-e23f8ede4ea0", "metadata": {}, "outputs": [ @@ -1753,71 +1748,66 @@ "text/plain": [ "Timer unit: 1e-06 s\n", "\n", - "Total time: 138.58 s\n", + "Total time: 101.475 s\n", "File: /home/daniel/dimod/dimod/higherorder/utils.py\n", - "Function: reduce_terms at line 121\n", + "Function: reduce_terms at line 120\n", "\n", "Line # Hits Time Per Hit % Time Line Contents\n", "==============================================================\n", - " 121 def reduce_terms(bp):\n", - " 122 1 8412.0 8412.0 0.0 variables = bp.variables\n", - " 123 1 3.0 3.0 0.0 constraints = []\n", - " 124 1 20049.0 20049.0 0.0 reduced_terms = [item for item in bp.items() if len(tl.first(item)) <= 2]\n", - " 125 \n", - " 126 2 138.0 69.0 0.0 idx = defaultdict(\n", - " 127 1 0.0 0.0 0.0 dict,\n", - " 128 2 3123591.0 1561795.5 2.3 tl.valmap(\n", - " 129 1 8.0 8.0 0.0 tl.compose(dict, partial(map, tl.second)),\n", - " 130 2 12526859.0 6263429.5 9.0 tl.groupby(\n", - " 131 1 1.0 1.0 0.0 tl.first,\n", - " 132 2 2.0 1.0 0.0 (\n", - " 133 (frozenset(pair), item)\n", - " 134 1 4.0 4.0 0.0 for item in bp.items()\n", - " 135 if len(term := tl.first(item)) >= 3\n", - " 136 for pair in itertools.combinations(term, 2) ))))\n", + " 120 def reduce_terms(bp):\n", + " 121 1 8869.0 8869.0 0.0 variables = bp.variables\n", + " 122 1 3.0 3.0 0.0 constraints = []\n", + " 123 \n", + " 124 1 1.0 1.0 0.0 reduced_terms = []\n", + " 125 1 29.0 29.0 0.0 idx = defaultdict(dict)\n", + " 126 18204 52791.0 2.9 0.1 for item in bp.items():\n", + " 127 18203 9428.0 0.5 0.0 term, bias = item\n", + " 128 18203 12144.0 0.7 0.0 if len(term) <= 2:\n", + " 129 386 823.0 2.1 0.0 reduced_terms.append(item)\n", + " 130 else:\n", + " 131 3252010 1518548.0 0.5 1.5 for pair in itertools.combinations(term, 2):\n", + " 132 3234193 3075564.0 1.0 3.0 idx[frozenset(pair)][term] = bias\n", + " 133 \n", + " 134 1 11.0 11.0 0.0 que = defaultdict(set)\n", + " 135 1276 679.0 0.5 0.0 for pair, terms in idx.items():\n", + " 136 1275 10824.0 8.5 0.0 que[len(terms)].add(pair)\n", " 137 \n", - " 138 2 14.0 7.0 0.0 que = defaultdict(\n", - " 139 1 2.0 2.0 0.0 set,\n", - " 140 2 330.0 165.0 0.0 tl.valmap(\n", - " 141 1 8.0 8.0 0.0 tl.compose(set, partial(map, tl.first)),\n", - " 142 1 541.0 541.0 0.0 tl.groupby(tl.second, tl.valmap(len, idx).items())))\n", - " 143 \n", - " 144 57784 41700.0 0.7 0.0 while idx:\n", - " 145 57783 59630.0 1.0 0.0 new_pairs = set()\n", - " 146 57783 85719.0 1.5 0.1 most = max(que)\n", - " 147 57783 44164.0 0.8 0.0 que_most = que[most]\n", - " 148 57783 54744.0 0.9 0.0 pair = que_most.pop()\n", - " 149 57783 41427.0 0.7 0.0 if not que_most:\n", - " 150 326 284.0 0.9 0.0 del que[most]\n", - " 151 57783 258140.0 4.5 0.2 terms = idx.pop(pair)\n", - " 152 \n", - " 153 57783 178208.0 3.1 0.1 prod_var = _new_product(variables, *pair)\n", - " 154 57783 65217.0 1.1 0.0 constraints.append((pair, prod_var))\n", - " 155 57783 49162.0 0.9 0.0 prod_var_set = {prod_var}\n", - " 156 \n", - " 157 348260 444114.0 1.3 0.3 for old_term, bias in terms.items():\n", - " 158 290477 702133.0 2.4 0.5 common_subterm = (old_term - pair)\n", - " 159 290477 347608.0 1.2 0.3 new_term = common_subterm | prod_var_set\n", - " 160 \n", - " 161 6233905 6447556.0 1.0 4.7 for old_pair in map(frozenset, (itertools.product(pair, common_subterm))):\n", - " 162 5943428 15522741.0 2.6 11.2 _decrement_count(idx, que, old_pair)\n", - " 163 5943428 9631446.0 1.6 7.0 _remove_old(idx, old_term, old_pair)\n", - " 164 \n", - " 165 20299019 17587151.0 0.9 12.7 for common_pair in map(frozenset, (itertools.combinations(common_subterm, 2))):\n", - " 166 20008542 30545892.0 1.5 22.0 idx[common_pair][new_term] = bias\n", - " 167 20008542 28864233.0 1.4 20.8 _remove_old(idx, old_term, common_pair)\n", - " 168 \n", - " 169 290477 316414.0 1.1 0.2 if len(new_term) > 2:\n", - " 170 3226051 4315120.0 1.3 3.1 for new_pair in (frozenset((prod_var, v)) for v in common_subterm):\n", - " 171 2953644 3801197.0 1.3 2.7 idx[new_pair][new_term] = bias\n", - " 172 2953644 2534485.0 0.9 1.8 new_pairs.add(new_pair)\n", - " 173 else:\n", - " 174 18070 15985.0 0.9 0.0 reduced_terms.append((new_term, bias))\n", - " 175 \n", - " 176 530947 400212.0 0.8 0.3 for new_pair in new_pairs:\n", - " 177 473164 545266.0 1.2 0.4 que[len(idx[new_pair])].add(new_pair)\n", - " 178 \n", - " 179 1 1.0 1.0 0.0 return reduced_terms, constraints" + " 138 58154 29577.0 0.5 0.0 while idx:\n", + " 139 58153 47937.0 0.8 0.0 new_pairs = set()\n", + " 140 58153 79341.0 1.4 0.1 most = max(que)\n", + " 141 58153 32205.0 0.6 0.0 que_most = que[most]\n", + " 142 58153 44334.0 0.8 0.0 pair = que_most.pop()\n", + " 143 58153 30567.0 0.5 0.0 if not que_most:\n", + " 144 316 191.0 0.6 0.0 del que[most]\n", + " 145 58153 235823.0 4.1 0.2 terms = idx.pop(pair)\n", + " 146 \n", + " 147 58153 176664.0 3.0 0.2 prod_var = _new_product(variables, *pair)\n", + " 148 58153 50434.0 0.9 0.0 constraints.append((pair, prod_var))\n", + " 149 58153 36876.0 0.6 0.0 prod_var_set = {prod_var}\n", + " 150 \n", + " 151 344336 359995.0 1.0 0.4 for old_term, bias in terms.items():\n", + " 152 286183 566357.0 2.0 0.6 common_subterm = (old_term - pair)\n", + " 153 286183 267784.0 0.9 0.3 new_term = common_subterm | prod_var_set\n", + " 154 \n", + " 155 6146569 5191902.0 0.8 5.1 for old_pair in map(frozenset, itertools.product(pair, common_subterm)):\n", + " 156 5860386 12781714.0 2.2 12.6 _decrement_count(idx, que, old_pair)\n", + " 157 5860386 7942377.0 1.4 7.8 _remove_old(idx, old_term, old_pair)\n", + " 158 \n", + " 159 20020096 12707113.0 0.6 12.5 for common_pair in map(frozenset, itertools.combinations(common_subterm, 2)):\n", + " 160 19733913 22539962.0 1.1 22.2 idx[common_pair][new_term] = bias\n", + " 161 19733913 22912153.0 1.2 22.6 _remove_old(idx, old_term, common_pair)\n", + " 162 \n", + " 163 286183 229066.0 0.8 0.2 if len(new_term) > 2:\n", + " 164 3180742 5189832.0 1.6 5.1 for new_pair in (frozenset((prod_var, v)) for v in common_subterm):\n", + " 165 2912376 2771588.0 1.0 2.7 idx[new_pair][new_term] = bias\n", + " 166 2912376 1802737.0 0.6 1.8 new_pairs.add(new_pair)\n", + " 167 else:\n", + " 168 17817 14797.0 0.8 0.0 reduced_terms.append((new_term, bias))\n", + " 169 \n", + " 170 534444 288154.0 0.5 0.3 for new_pair in new_pairs:\n", + " 171 476291 455596.0 1.0 0.4 que[len(idx[new_pair])].add(new_pair)\n", + " 172 \n", + " 173 1 0.0 0.0 0.0 return reduced_terms, constraints" ] }, "metadata": {}, @@ -1838,14 +1828,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 990 µs, sys: 0 ns, total: 990 µs\n", - "Wall time: 994 µs\n" + "CPU times: user 2.84 ms, sys: 13 µs, total: 2.85 ms\n", + "Wall time: 2.86 ms\n" ] }, { "data": { "text/plain": [ - "23" + "62" ] }, "execution_count": 44, @@ -1886,7 +1876,7 @@ "evalue": "invalid syntax (3330683553.py, line 1)", "output_type": "error", "traceback": [ - "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_7212/3330683553.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m BinaryPolynomial.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + "\u001b[0;36m File \u001b[0;32m\"/tmp/ipykernel_7808/3330683553.py\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m BinaryPolynomial.\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" ] } ], @@ -1916,52 +1906,10 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": null, "id": "fac7547a-db9e-4e35-8a5d-99e2aa72d137", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " " - ] - }, - { - "data": { - "text/plain": [ - " 71617713 function calls in 62.426 seconds\n", - "\n", - " Ordered by: cumulative time\n", - " List reduced from 100 to 20 due to restriction <20>\n", - "\n", - " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.000 0.000 62.426 62.426 {built-in method builtins.exec}\n", - " 1 0.052 0.052 62.426 62.426 :1()\n", - " 1 0.627 0.627 62.374 62.374 utils.py:182(make_quadratic)\n", - " 1 28.181 28.181 57.161 57.161 utils.py:121(reduce_terms)\n", - " 25951970 9.679 0.000 9.679 0.000 utils.py:114(_remove_old)\n", - " 3280262 8.966 0.000 9.001 0.000 utils.py:132()\n", - " 5943428 4.742 0.000 7.417 0.000 utils.py:104(_decrement_count)\n", - " 3226051 2.157 0.000 2.157 0.000 utils.py:170()\n", - " 57783 0.082 0.000 2.010 0.000 utils.py:63(_binary_product)\n", - " 57784 0.087 0.000 1.928 0.000 binary_quadratic_model.py:93(__init__)\n", - " 57783 0.278 0.000 1.821 0.000 binary_quadratic_model.py:136(_init_components)\n", - " 5943428 1.504 0.000 1.504 0.000 {method 'remove' of 'set' objects}\n", - " 9011363 1.272 0.000 1.272 0.000 {method 'add' of 'set' objects}\n", - " 286635 0.148 0.000 1.029 0.000 _collections_abc.py:742(__iter__)\n", - " 365146 0.625 0.000 1.001 0.000 {method 'add_quadratic' of 'dimod.binary.cybqm.cybqm_float64.cyBQM_template' objects}\n", - " 2789747 0.370 0.000 0.740 0.000 abc.py:96(__instancecheck__)\n", - " 173351 0.214 0.000 0.591 0.000 decorators.py:474(wrapper)\n", - " 191797 0.044 0.000 0.581 0.000 binary_quadratic_model.py:709(add_interaction)\n", - " 231132 0.082 0.000 0.546 0.000 quadratic.py:136(__iter__)\n", - " 57783 0.165 0.000 0.479 0.000 binary_quadratic_model.py:654(add_linear_from)" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "%prun -s cumtime -l 20 dimod.make_quadratic(bp, 100, vartype='BINARY')" ]