From 0a4a093fe84ee0012644c345ff5c1ea6c6be84cf Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 25 Sep 2023 11:01:14 +0000 Subject: [PATCH 01/12] Progress --- Dockerfile | 10 +-- qtensor/Bitstring.py | 51 +++++++++++ qtensor/Simulate.py | 71 ++++++++++++++++ qtensor/TNAdapter.py | 198 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 325 insertions(+), 5 deletions(-) create mode 100644 qtensor/Bitstring.py create mode 100644 qtensor/TNAdapter.py diff --git a/Dockerfile b/Dockerfile index 8f64607a..1eedea98 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,13 +6,13 @@ RUN yes | apt update RUN yes | apt install python3 python3-pip git htop vim WORKDIR /app -RUN git clone --recursive -b dev https://github.com/danlkv/QTensor.git +RUN git clone --recursive -b qtree-sample-api https://github.com/danlkv/QTensor.git RUN cd QTensor/qtree && pip install . RUN cd QTensor && pip install . - +COPY . . RUN pip install quimb pyrofiler cartesian-explorer opt_einsum RUN pip install --no-binary pynauty pynauty -RUN pip install torch -RUN pip install cupy-cuda110 +# RUN pip install torch +# RUN pip install cupy-cuda110 -ENTRYPOINT ["python3"] +ENTRYPOINT ["bash"] diff --git a/qtensor/Bitstring.py b/qtensor/Bitstring.py new file mode 100644 index 00000000..92b9b1b9 --- /dev/null +++ b/qtensor/Bitstring.py @@ -0,0 +1,51 @@ +import numpy as np + +class Bitstring: + """Bitstring class""" + def __init__(self, bits: 'list[int]', prob=None, dim=2): + self._bits = list(bits) + self._s = ''.join(str(b) for b in self._bits) + self._prob = prob + self._dim = dim + + def __iter__(self): + for i in self._bits: + yield int(i) + + def __repr__(self): + return f'<{self._s}>' + + def __len__(self): + return len(self._bits) + + @classmethod + def str(cls, s: str, **kwargs): + return cls([int(_s) for _s in s], **kwargs) + + @classmethod + def int(cls, i: int, width, **kwargs): + dim = kwargs.get('dim', 2) + return cls(list(int(_i) for _i in np.unravel_index(i, [dim]*width)), **kwargs) + + def __add__(self, other: 'Bitstring'): + assert self._dim == other._dim + if self._prob is not None and other._prob is not None: + return Bitstring(self._bits + other._bits, self._prob * other._prob, dim=self._dim) + return Bitstring(self._bits + other._bits, dim=self._dim) + + def __iadd__(self, other: 'Bitstring'): + assert self._dim == other._dim + if self._prob is not None and other._prob is not None: + self._prob *= other._prob + self._bits += other._bits + + def __eq__(self, other: 'Bitstring'): + return self.to_int() == other.to_int() + + def __hash__(self): + if self._prob is not None: + return hash((self._s, self._prob, self._dim)) + return int(self.to_int()) + + def to_int(self): + return np.ravel_multi_index(self._bits, [self._dim]*len(self._bits)) diff --git a/qtensor/Simulate.py b/qtensor/Simulate.py index 0e271bd1..51c5489c 100644 --- a/qtensor/Simulate.py +++ b/qtensor/Simulate.py @@ -4,6 +4,7 @@ from qtensor.optimisation.TensorNet import QtreeTensorNet from qtensor.optimisation.Optimizer import DefaultOptimizer, Optimizer +from qtensor import Bitstring as Bs, TNAdapter from tqdm.auto import tqdm from loguru import logger as log @@ -149,9 +150,79 @@ def simulate(self, qc): def simulate_state(self, qc, peo=None): return self.simulate_batch(qc, peo=peo, batch_vars=0) + def sample(self): + # TODO: can use TNAdapter in init to avoid this operation again + tn_adapter = TNAdapter.from_qtree_gates(self.all_ages) + return _sequence_sample(tn, composer.qubits) + + def _sequence_sample(tn: TNAdapter, indices, batch_size=10, batch_fix_sequence=None, dim=2): + """ + Args: + tn: tensor network + indices: list of indices to contract + """ + K = int(np.ceil(len(indices) / batch_size)) + if batch_fix_sequence is None: + batch_fix_sequence = [1]*K + + slice_dict = {} + cache = {} + samples = [Bs.str('', prob=1., dim=dim)] + z_0 = None + for i in range(K): + for j in range(len(samples)): + bs = samples.pop(0) + res = None + if len(bs)>0: + res = cache.get(bs.to_int()) + if res is None: + free_batch_ix = indices[i*batch_size:(i+1)*batch_size] + _fix_indices = indices[: len(bs)] + update = dict(zip(_fix_indices, list(bs))) + slice_dict.update(dict(zip(_fix_indices, list(bs)))) + res = contract_tn(tn, slice_dict, free_batch_ix) + res = res.real**2 + if len(bs)>0: + cache[bs.to_int()] = res + + # result should be shaped accourdingly + if z_0 is None: + z_0 = res.sum() + prob_prev = bs._prob + z_n = prob_prev * z_0 + z_n = res.sum() + logger.debug('bs {}, Sum res {}, prev_Z {}, prob_prev {}', + bs, res.sum(), prob_prev*z_0, prob_prev + ) + pdist = res.flatten() / z_n + logger.debug(f'Prob distribution: {pdist.round(4)}') + indices_bs = np.arange(len(pdist)) + batch_ix = np.random.choice(indices_bs, batch_fix_sequence[i], p=pdist) + for ix in batch_ix: + _new_s = bs + Bs.int(ix, width=len(free_batch_ix), prob=pdist[ix], dim=dim) + logger.trace(f'New sample: {_new_s}') + samples.append(_new_s) + + return samples + + class CirqSimulator(Simulator): def simulate(self, qc, **params): sim = cirq.Simulator(**params) return sim.simulate(qc) +if __name__=="__main__": + import networkx as nx + import numpy as np + + G = nx.random_regular_graph(3, 10) + gamma, beta = [np.pi/3], [np.pi/2] + + from qtensor import QtreeQAOAComposer, QAOAQtreeSimulator + composer = QtreeQAOAComposer(graph=G, gamma=gamma, beta=beta) + composer.ansatz_state() + + sim = QAOAQtreeSimulator(composer) + + print("hello world") \ No newline at end of file diff --git a/qtensor/TNAdapter.py b/qtensor/TNAdapter.py new file mode 100644 index 00000000..8d995c57 --- /dev/null +++ b/qtensor/TNAdapter.py @@ -0,0 +1,198 @@ +import numpy as np +import networkx as nx +from loguru import logger +import qtree, qtensor +import sys +from typing import Iterable, Union + +from qtensor.optimisation.TensorNet import circ2buckets_init + +logger.remove() +logger.add(sys.stderr, level='DEBUG') + +class ContractionInfo: + pass + +class TNAdapter: + def __init__(self, *args, **kwargs): + pass + + def optimize(self, out_indices: Iterable = []) -> ContractionInfo: + return ContractionInfo() + + # Inplace or not? + def slice(self, slice_dict: dict) -> 'TNAdapter': + ... + + # Inplace or not? + def contract(self, contraction_info: ContractionInfo) -> np.ndarray: + ... + + # require this? + def copy(self): + pass + + def add_tensor(self, data, indices): + pass + +def add_random_tn(tn:TNAdapter, graph:nx.Graph, e2i:dict={}, min_ix=0, dim=2): + e2i_default = {tuple(sorted(e)):i for i,e in enumerate(graph.edges(), min_ix)} + if set(e2i.keys()).intersection(set(e2i_default.keys())): + raise ValueError("e2i and e2i_default have common keys") + # overwrite default with e2i + e2i_default.update(e2i) + e2i = e2i_default + logger.debug("Indices: {}", e2i) + for u in graph: + indices = [] + for v in graph[u]: + edge = tuple(sorted((u,v))) + indices.append(e2i[edge]) + #tn.add_tensor(np.random.randn(*[dim]*len(indices)), indices) + tn.add_tensor(1+np.random.rand(*[dim]*len(indices)), indices) + return list(e2i_default.values()) + +def test_TNAdapter(cls): + for dim in [2,3,4]: + tn = cls() + logger.debug("Testing dim {}", dim) + graph = nx.random_regular_graph(3, 10) + indices = add_random_tn(tn, graph, dim=dim) + # tn full contraction + _c_info = tn.optimize() + ref = tn.contract(_c_info) + # test slicing + for index in indices: + values = [] + for v in range(dim): + tn2 = tn.slice({index:v}) + _c_info = tn2.optimize() + logger.debug("Contracting {} with value {}", str(index), v) + values.append(tn2.contract(_c_info)) + logger.debug("Reference: {}, values: {}", ref, values) + assert np.allclose(np.sum(values), ref) + # test free indices and partial contraction + for _ in range(5): + # random subset of indices + __memory_budget = 2**24 # 16MB + __max_free = int(np.log(__memory_budget) / np.log(dim)) + n_free = np.random.randint(1, min(len(indices), __max_free)) + n_contract = len(indices) - n_free + contract = np.random.choice(indices, n_contract, replace=False) + logger.debug("Free indices: {}, contract ({}): {}", n_free, n_contract, contract) + tn2 = tn.slice({}) # copy + # sometimes it's better to specify non-contracting indices + _c_info = tn2.optimize(index_list=contract) + res = tn2.contract(_c_info) + logger.debug("Reference: {}, result shape: {}", ref, res.shape) + assert np.allclose(res.sum(), ref) + + + logger.debug("Testing dim {} finished!\n===", dim) + +# -- QTensor tensor adapter + +import qtensor + +class QTensorContractionInfo(ContractionInfo): + def __init__(self, peo, width): + self.peo = peo + self.width = width + + def __repr__(self): + return f"QTensorContractionInfo({self.peo}, {self.width})" + +class QTensorTNAdapter(TNAdapter): + def __init__(self, buckets, data_dict, bra_vars, ket_vars, *args, **kwargs): + self._indices_to_vars = {} + self.qtn = qtensor.optimisation.QtreeTensorNet( + buckets, data_dict, bra_vars, ket_vars + ) + + @property + def _all_indices(self): + return set(self._indices_to_vars.keys()) + + def optimize(self, out_indices: Iterable = [], + opt:qtensor.optimisation.Optimizer=qtensor.optimisation.GreedyOptimizer()) -> QTensorContractionInfo: + logger.trace("Optimizing buckets: {}", self.qtn.buckets) + free_indices = out_indices + free_vars = [self._indices_to_vars[i] for i in free_indices] + self.qtn.free_vars = free_vars + logger.debug("Free vars: {}", free_vars) + peo, tn = opt.optimize(self.qtn) + logger.debug("Contraction path: {}", peo) + return QTensorContractionInfo(peo, opt.treewidth) + + def slice(self, slice_dict: dict): + slice_dict = {self._indices_to_vars[k]:v for k,v in slice_dict.items()} + logger.trace("Buckets before slicing: {}", self.qtn.buckets) + sliced_buckets = self.qtn.backend.get_sliced_buckets( + self.qtn.buckets, self.qtn.data_dict, slice_dict + ) + new_tn = QTensorTNAdapter() + logger.trace("slice dict {}, buckets: {}", slice_dict, sliced_buckets) + new_tn.qtn.buckets = sliced_buckets + new_tn.qtn.data_dict = self.qtn.data_dict + new_tn.qtn.bra_vars = self.qtn.bra_vars + new_tn.qtn.ket_vars = self.qtn.ket_vars + new_tn.qtn.backend = self.qtn.backend + new_tn.qtn.free_vars = self.qtn.free_vars + new_tn._indices_to_vars = self._indices_to_vars + return new_tn + + def contract(self, contraction_info: QTensorContractionInfo): + import qtree + peo = contraction_info.peo + if len(self.qtn.buckets) != len(peo): + _buckets = [[] for _ in peo] + _buckets[0] = sum(self.qtn.buckets, []) + self.qtn.buckets = _buckets + # -- fixer peo + i_to_var = {int(v): v for v in self._indices_to_vars.values()} + peo = [i_to_var[int(pv)] for pv in peo] + #-- + perm_buckets, perm_dict = qtree.optimizer.reorder_buckets( + self.qtn.buckets, peo + ) + + logger.trace("Permuted buckets: {}", perm_buckets) + sliced_buckets = self.qtn.backend.get_sliced_buckets( + perm_buckets, self.qtn.data_dict, {} + ) + be = qtensor.contraction_algos.bucket_elimination + logger.trace("Sliced buckets: {}", sliced_buckets) + + result = be(sliced_buckets, self.qtn.backend, + n_var_nosum=len(self.qtn.free_vars) + ) + if isinstance(result, qtree.optimizer.Tensor): + return result.data + else: + return result + + def add_tensor(self, data, indices): + import qtree + shape = data.shape + indices_v = {i: qtree.optimizer.Var(i, size=s) for i,s in zip(indices, shape)} + self._indices_to_vars.update(indices_v) + indices_v = list(indices_v.values()) + tensor = qtree.optimizer.Tensor(name='t', indices=indices_v, data_key=id(data)) + self.qtn.data_dict[id(data)] = data + self.qtn.buckets.append([tensor]) + logger.trace("Added tensor {}.", tensor) + + @classmethod + def from_qtree_gates(cls, qc, init_state=None, **kwargs): + all_gates = qc + n_qubits = len(set(sum([g.qubits for g in all_gates], tuple()))) + qtree_circuit = [[g] for g in qc] + if init_state is None: + buckets, data_dict, bra_vars, ket_vars = qtree.optimizer.circ2buckets( + n_qubits, qtree_circuit) + else: + buckets, data_dict, bra_vars, ket_vars = circ2buckets_init( + n_qubits, qtree_circuit, init_vector=init_state) + + tn = cls(buckets, data_dict, bra_vars, ket_vars, **kwargs) + return tn From cc455bef057c5ffb29e9fb46d10140487e417af4 Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 25 Sep 2023 11:03:41 +0000 Subject: [PATCH 02/12] Debug --- qtensor/Simulate.py | 91 +++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/qtensor/Simulate.py b/qtensor/Simulate.py index 51c5489c..51c41d7d 100644 --- a/qtensor/Simulate.py +++ b/qtensor/Simulate.py @@ -156,54 +156,49 @@ def sample(self): return _sequence_sample(tn, composer.qubits) def _sequence_sample(tn: TNAdapter, indices, batch_size=10, batch_fix_sequence=None, dim=2): - """ - Args: - tn: tensor network - indices: list of indices to contract - """ - K = int(np.ceil(len(indices) / batch_size)) - if batch_fix_sequence is None: - batch_fix_sequence = [1]*K - - slice_dict = {} - cache = {} - samples = [Bs.str('', prob=1., dim=dim)] - z_0 = None - for i in range(K): - for j in range(len(samples)): - bs = samples.pop(0) - res = None - if len(bs)>0: - res = cache.get(bs.to_int()) - if res is None: - free_batch_ix = indices[i*batch_size:(i+1)*batch_size] - _fix_indices = indices[: len(bs)] - update = dict(zip(_fix_indices, list(bs))) - slice_dict.update(dict(zip(_fix_indices, list(bs)))) - res = contract_tn(tn, slice_dict, free_batch_ix) - res = res.real**2 + K = int(np.ceil(len(indices) / batch_size)) + if batch_fix_sequence is None: + batch_fix_sequence = [1]*K + + slice_dict = {} + cache = {} + samples = [Bs.str('', prob=1., dim=dim)] + z_0 = None + for i in range(K): + for j in range(len(samples)): + bs = samples.pop(0) + res = None if len(bs)>0: - cache[bs.to_int()] = res - - # result should be shaped accourdingly - if z_0 is None: - z_0 = res.sum() - prob_prev = bs._prob - z_n = prob_prev * z_0 - z_n = res.sum() - logger.debug('bs {}, Sum res {}, prev_Z {}, prob_prev {}', - bs, res.sum(), prob_prev*z_0, prob_prev - ) - pdist = res.flatten() / z_n - logger.debug(f'Prob distribution: {pdist.round(4)}') - indices_bs = np.arange(len(pdist)) - batch_ix = np.random.choice(indices_bs, batch_fix_sequence[i], p=pdist) - for ix in batch_ix: - _new_s = bs + Bs.int(ix, width=len(free_batch_ix), prob=pdist[ix], dim=dim) - logger.trace(f'New sample: {_new_s}') - samples.append(_new_s) - - return samples + res = cache.get(bs.to_int()) + if res is None: + free_batch_ix = indices[i*batch_size:(i+1)*batch_size] + _fix_indices = indices[: len(bs)] + update = dict(zip(_fix_indices, list(bs))) + slice_dict.update(dict(zip(_fix_indices, list(bs)))) + res = contract_tn(tn, slice_dict, free_batch_ix) + res = res.real**2 + if len(bs)>0: + cache[bs.to_int()] = res + + # result should be shaped accourdingly + if z_0 is None: + z_0 = res.sum() + prob_prev = bs._prob + z_n = prob_prev * z_0 + z_n = res.sum() + logger.debug('bs {}, Sum res {}, prev_Z {}, prob_prev {}', + bs, res.sum(), prob_prev*z_0, prob_prev + ) + pdist = res.flatten() / z_n + logger.debug(f'Prob distribution: {pdist.round(4)}') + indices_bs = np.arange(len(pdist)) + batch_ix = np.random.choice(indices_bs, batch_fix_sequence[i], p=pdist) + for ix in batch_ix: + _new_s = bs + Bs.int(ix, width=len(free_batch_ix), prob=pdist[ix], dim=dim) + logger.trace(f'New sample: {_new_s}') + samples.append(_new_s) + + return samples class CirqSimulator(Simulator): @@ -225,4 +220,4 @@ def simulate(self, qc, **params): sim = QAOAQtreeSimulator(composer) - print("hello world") \ No newline at end of file + logger.debug('hello world') \ No newline at end of file From bc4de424602b43062f1ca21121f6f90e48f23965 Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 25 Sep 2023 11:13:55 +0000 Subject: [PATCH 03/12] Debug --- Dockerfile | 1 - qtensor/Simulate.py | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1eedea98..db6b5f01 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,6 @@ WORKDIR /app RUN git clone --recursive -b qtree-sample-api https://github.com/danlkv/QTensor.git RUN cd QTensor/qtree && pip install . RUN cd QTensor && pip install . -COPY . . RUN pip install quimb pyrofiler cartesian-explorer opt_einsum RUN pip install --no-binary pynauty pynauty # RUN pip install torch diff --git a/qtensor/Simulate.py b/qtensor/Simulate.py index 51c41d7d..0a50a8a8 100644 --- a/qtensor/Simulate.py +++ b/qtensor/Simulate.py @@ -4,7 +4,7 @@ from qtensor.optimisation.TensorNet import QtreeTensorNet from qtensor.optimisation.Optimizer import DefaultOptimizer, Optimizer -from qtensor import Bitstring as Bs, TNAdapter +from qtensor import Bitstring as Bs, TNAdapter, QTensorTNAdapter from tqdm.auto import tqdm from loguru import logger as log @@ -151,8 +151,8 @@ def simulate_state(self, qc, peo=None): return self.simulate_batch(qc, peo=peo, batch_vars=0) def sample(self): - # TODO: can use TNAdapter in init to avoid this operation again - tn_adapter = TNAdapter.from_qtree_gates(self.all_ages) + # TODO: can use QTensorTNAdapter in init to avoid this operation again + tn_adapter = QTensorTNAdapter.from_qtree_gates(self.all_gates) return _sequence_sample(tn, composer.qubits) def _sequence_sample(tn: TNAdapter, indices, batch_size=10, batch_fix_sequence=None, dim=2): @@ -220,4 +220,4 @@ def simulate(self, qc, **params): sim = QAOAQtreeSimulator(composer) - logger.debug('hello world') \ No newline at end of file + log.debug('hello world') \ No newline at end of file From 40c152f36a1d44d4fae97ad01adeace38e177c21 Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 25 Sep 2023 11:18:20 +0000 Subject: [PATCH 04/12] Debug --- qtensor/QAOASimulator.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qtensor/QAOASimulator.py b/qtensor/QAOASimulator.py index 4e9b9fc3..cf9a3445 100644 --- a/qtensor/QAOASimulator.py +++ b/qtensor/QAOASimulator.py @@ -204,7 +204,8 @@ def energy_expectation(self, G, gamma, beta, nprocs=None): class QAOAQtreeSimulator(QAOASimulator, QtreeSimulator): - pass + def sample(self): + super(QtreeSimulator, self).sample() class QAOAQtreeSimulatorSymmetryAccelerated(QAOASimulatorSymmetryAccelerated, QtreeSimulator): From 88abb82aab6aef0f97710b43b251ce9ed29845ea Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 25 Sep 2023 11:28:03 +0000 Subject: [PATCH 05/12] Debug --- Dockerfile | 1 + qtensor/QAOASimulator.py | 3 +-- qtensor/Simulate.py | 21 +++++++++++---------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/Dockerfile b/Dockerfile index db6b5f01..5cee0fc1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,6 +7,7 @@ RUN yes | apt install python3 python3-pip git htop vim WORKDIR /app RUN git clone --recursive -b qtree-sample-api https://github.com/danlkv/QTensor.git +COPY . . RUN cd QTensor/qtree && pip install . RUN cd QTensor && pip install . RUN pip install quimb pyrofiler cartesian-explorer opt_einsum diff --git a/qtensor/QAOASimulator.py b/qtensor/QAOASimulator.py index cf9a3445..4e9b9fc3 100644 --- a/qtensor/QAOASimulator.py +++ b/qtensor/QAOASimulator.py @@ -204,8 +204,7 @@ def energy_expectation(self, G, gamma, beta, nprocs=None): class QAOAQtreeSimulator(QAOASimulator, QtreeSimulator): - def sample(self): - super(QtreeSimulator, self).sample() + pass class QAOAQtreeSimulatorSymmetryAccelerated(QAOASimulatorSymmetryAccelerated, QtreeSimulator): diff --git a/qtensor/Simulate.py b/qtensor/Simulate.py index 0a50a8a8..ede329f2 100644 --- a/qtensor/Simulate.py +++ b/qtensor/Simulate.py @@ -145,6 +145,7 @@ def simulate_batch(self, qc, batch_vars=0, peo=None): return self.backend.get_result_data(result).flatten() def simulate(self, qc): + import pdb; pdb.set_trace() return self.simulate_state(qc) def simulate_state(self, qc, peo=None): @@ -208,16 +209,16 @@ def simulate(self, qc, **params): return sim.simulate(qc) if __name__=="__main__": - import networkx as nx - import numpy as np - - G = nx.random_regular_graph(3, 10) - gamma, beta = [np.pi/3], [np.pi/2] +import networkx as nx +import numpy as np - from qtensor import QtreeQAOAComposer, QAOAQtreeSimulator - composer = QtreeQAOAComposer(graph=G, gamma=gamma, beta=beta) - composer.ansatz_state() +G = nx.random_regular_graph(3, 10) +gamma, beta = [np.pi/3], [np.pi/2] - sim = QAOAQtreeSimulator(composer) +from qtensor import QtreeQAOAComposer, QAOAQtreeSimulator +composer = QtreeQAOAComposer(graph=G, gamma=gamma, beta=beta) +composer.ansatz_state() - log.debug('hello world') \ No newline at end of file +sim = QAOAQtreeSimulator(composer) + +log.debug('hello world') \ No newline at end of file From a53ba7dda259b5c6be9e8f85b3dd342666bfc373 Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 2 Oct 2023 15:13:22 +0000 Subject: [PATCH 06/12] Add dev dockerfile --- Dockerfile.dev | 13 +++++++++++++ dev.sh | 4 ++++ 2 files changed, 17 insertions(+) create mode 100644 Dockerfile.dev create mode 100755 dev.sh diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 00000000..f0a4869f --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,13 @@ +FROM nvidia/cuda:11.0.3-runtime-ubuntu20.04 + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt update -y && \ + apt install -y python3 python3-pip git htop vim + +WORKDIR /app +RUN pip install quimb pyrofiler cartesian-explorer opt_einsum +RUN pip install --no-binary pynauty pynauty +RUN pip install . + +ENTRYPOINT ["bash"] \ No newline at end of file diff --git a/dev.sh b/dev.sh new file mode 100755 index 00000000..4a9b7f05 --- /dev/null +++ b/dev.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +docker build -f Dockerfile.dev -t dev . +docker run -v $(pwd):/app -it dev From e7d1696fae0de0906be2debabcb0a9fca80f642c Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 2 Oct 2023 20:32:33 +0000 Subject: [PATCH 07/12] Cleanup --- Dockerfile | 12 +++++------- Dockerfile.dev | 2 ++ qtensor/Simulate.py | 23 +++++++++++------------ 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5cee0fc1..0b1b8012 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,16 @@ FROM nvidia/cuda:11.0.3-runtime-ubuntu20.04 - ENV DEBIAN_FRONTEND=noninteractive - RUN yes | apt update RUN yes | apt install python3 python3-pip git htop vim WORKDIR /app -RUN git clone --recursive -b qtree-sample-api https://github.com/danlkv/QTensor.git -COPY . . +RUN git clone --recursive -b dev https://github.com/danlkv/QTensor.git RUN cd QTensor/qtree && pip install . RUN cd QTensor && pip install . + RUN pip install quimb pyrofiler cartesian-explorer opt_einsum RUN pip install --no-binary pynauty pynauty -# RUN pip install torch -# RUN pip install cupy-cuda110 +RUN pip install torch +RUN pip install cupy-cuda110 -ENTRYPOINT ["bash"] +ENTRYPOINT ["python3"] \ No newline at end of file diff --git a/Dockerfile.dev b/Dockerfile.dev index f0a4869f..f8567217 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -8,6 +8,8 @@ RUN apt update -y && \ WORKDIR /app RUN pip install quimb pyrofiler cartesian-explorer opt_einsum RUN pip install --no-binary pynauty pynauty +RUN cd qtree && pip install . RUN pip install . +RUN pip install pdbpp ENTRYPOINT ["bash"] \ No newline at end of file diff --git a/qtensor/Simulate.py b/qtensor/Simulate.py index ede329f2..229fd82c 100644 --- a/qtensor/Simulate.py +++ b/qtensor/Simulate.py @@ -145,15 +145,14 @@ def simulate_batch(self, qc, batch_vars=0, peo=None): return self.backend.get_result_data(result).flatten() def simulate(self, qc): - import pdb; pdb.set_trace() return self.simulate_state(qc) def simulate_state(self, qc, peo=None): return self.simulate_batch(qc, peo=peo, batch_vars=0) - def sample(self): + def sample(self, circuit): # TODO: can use QTensorTNAdapter in init to avoid this operation again - tn_adapter = QTensorTNAdapter.from_qtree_gates(self.all_gates) + tn_adapter = QTensorTNAdapter.from_qtree_gates(circuit) return _sequence_sample(tn, composer.qubits) def _sequence_sample(tn: TNAdapter, indices, batch_size=10, batch_fix_sequence=None, dim=2): @@ -209,16 +208,16 @@ def simulate(self, qc, **params): return sim.simulate(qc) if __name__=="__main__": -import networkx as nx -import numpy as np + import networkx as nx + import numpy as np -G = nx.random_regular_graph(3, 10) -gamma, beta = [np.pi/3], [np.pi/2] + G = nx.random_regular_graph(3, 10) + gamma, beta = [np.pi/3], [np.pi/2] -from qtensor import QtreeQAOAComposer, QAOAQtreeSimulator -composer = QtreeQAOAComposer(graph=G, gamma=gamma, beta=beta) -composer.ansatz_state() + from qtensor import QtreeQAOAComposer, QAOAQtreeSimulator + composer = QtreeQAOAComposer(graph=G, gamma=gamma, beta=beta) + composer.ansatz_state() -sim = QAOAQtreeSimulator(composer) + sim = QAOAQtreeSimulator(composer) -log.debug('hello world') \ No newline at end of file + log.debug('hello world') \ No newline at end of file From e8ffc7102c473cd2a2f593de44c3564e3e4bf24c Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 2 Oct 2023 20:58:23 +0000 Subject: [PATCH 08/12] Progress --- Dockerfile | 2 +- qtensor/Simulate.py | 67 +++++++++++++++++++++++++-------------------- 2 files changed, 38 insertions(+), 31 deletions(-) diff --git a/Dockerfile b/Dockerfile index 0b1b8012..8e2ac8eb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,4 +13,4 @@ RUN pip install --no-binary pynauty pynauty RUN pip install torch RUN pip install cupy-cuda110 -ENTRYPOINT ["python3"] \ No newline at end of file +ENTRYPOINT ["python3"] diff --git a/qtensor/Simulate.py b/qtensor/Simulate.py index 229fd82c..b232b625 100644 --- a/qtensor/Simulate.py +++ b/qtensor/Simulate.py @@ -33,15 +33,6 @@ def __init__(self, backend=NumpyBackend(), optimizer=None, max_tw=None): self.optimizer = self.FallbackOptimizer() self.max_tw = max_tw - #-- Internal helpers - def _new_circuit(self, qc): - self.all_gates = qc - - def _create_buckets(self): - self.tn = QtreeTensorNet.from_qtree_gates(self.all_gates, - backend=self.backend) - self.tn.backend = self.backend - def _set_free_qubits(self, free_final_qubits): self.tn.free_vars = [self.tn.bra_vars[i] for i in free_final_qubits] self.tn.bra_vars = [var for var in self.tn.bra_vars if var not in self.tn.free_vars] @@ -101,10 +92,18 @@ def optimize_buckets(self): # print('Treewidth', self.optimizer.treewidth) # print(peo) return peo + + def _prepare_state(self, qc, batch_vars=0, peo=None, tn=None): + pass - def prepare_buckets(self, qc, batch_vars=0, peo=None): - self._new_circuit(qc) - self._create_buckets() + def contract_tn(self, qc, batch_vars=0, peo=None, tn=None): + self.all_gates = qc + if tn is None: + self.tn = QtreeTensorNet.from_qtree_gates(self.all_gates, + backend=self.backend) + else: + self.tn = tn + self.tn.backend = self.backend # Collect free qubit variables if isinstance(batch_vars, int): free_final_qubits = list(range(batch_vars)) @@ -124,43 +123,54 @@ def prepare_buckets(self, qc, batch_vars=0, peo=None): identity_map = {int(v): v for v in all_indices} self.peo = [identity_map[int(i)] for i in self.peo] - self._reorder_buckets() slice_dict = self._get_slice_dict() - #log.info('batch slice {}', slice_dict) + log.info('batch slice {}', slice_dict) sliced_buckets = self.tn.slice(slice_dict) - #self.backend.pbar.set_total ( len(sliced_buckets)) self.buckets = sliced_buckets - # print("Buckets:") - # print(sliced_buckets) - - def simulate_batch(self, qc, batch_vars=0, peo=None): - self.prepare_buckets(qc, batch_vars, peo) - + result = qtree.optimizer.bucket_elimination( self.buckets, self.backend.process_bucket, n_var_nosum=len(self.tn.free_vars) ) + + return result + + def simulate_batch(self, qc, batch_vars=0, peo=None): + result = self.contract_tn(qc, batch_vars, peo) return self.backend.get_result_data(result).flatten() def simulate(self, qc): return self.simulate_state(qc) def simulate_state(self, qc, peo=None): - return self.simulate_batch(qc, peo=peo, batch_vars=0) + return self.contract_tn(qc, peo=peo, batch_vars=0) def sample(self, circuit): # TODO: can use QTensorTNAdapter in init to avoid this operation again tn_adapter = QTensorTNAdapter.from_qtree_gates(circuit) - return _sequence_sample(tn, composer.qubits) - - def _sequence_sample(tn: TNAdapter, indices, batch_size=10, batch_fix_sequence=None, dim=2): + return _sequence_sample(tn_adapter, composer.qubits) + + # def contract_tn(self, tn, slice_dict, free_indices): + # # TODO:(@dallon) + # # tn_ = tn.slice(slice_dict) + # # c_info = tn_.optimize(free_indices) + # # return tn_.contract(c_info) + # # 1. `QtreeTensorNet.from_qtree_gates(self.all_gates)` + # # 2. Prepare list of “free” and “bra” vars (those will be fixed later) + # # 3. `peo, [self.tn](http://self.tn/) = self.optimizer.optimize([self.tn](http://self.tn/))` + # # 4. `perm_buckets, perm_dict = qtree.optimizer.reorder_buckets(self.tn.buckets, self.peo)` According to the contraction order (`peo`) + # # 5. `slice_dict = qtree.utils.slice_from_bits(initial_state, self.tn.ket_vars)` + # # 6. `sliced_buckets = self.tn.slice(slice_dict)` + # # 7. `result = qtree.optimizer.bucket_elimination(` + # pass + + def _sequence_sample(tn: TNAdapter, circuit, indices, batch_size=10, batch_fix_sequence=None, dim=2): K = int(np.ceil(len(indices) / batch_size)) if batch_fix_sequence is None: batch_fix_sequence = [1]*K - slice_dict = {} cache = {} samples = [Bs.str('', prob=1., dim=dim)] z_0 = None @@ -172,10 +182,7 @@ def _sequence_sample(tn: TNAdapter, indices, batch_size=10, batch_fix_sequence=N res = cache.get(bs.to_int()) if res is None: free_batch_ix = indices[i*batch_size:(i+1)*batch_size] - _fix_indices = indices[: len(bs)] - update = dict(zip(_fix_indices, list(bs))) - slice_dict.update(dict(zip(_fix_indices, list(bs)))) - res = contract_tn(tn, slice_dict, free_batch_ix) + res = self.contract_tn(circuit, batch_vars=free_batch_ix, tn=tn) res = res.real**2 if len(bs)>0: cache[bs.to_int()] = res From 775010576ee9908cdd47e701d616cb8de00f5efb Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:46:56 +0000 Subject: [PATCH 09/12] Prepare buckets to contraction --- qtensor/Simulate.py | 68 +++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 43 deletions(-) diff --git a/qtensor/Simulate.py b/qtensor/Simulate.py index b232b625..25d6a489 100644 --- a/qtensor/Simulate.py +++ b/qtensor/Simulate.py @@ -37,9 +37,6 @@ def _set_free_qubits(self, free_final_qubits): self.tn.free_vars = [self.tn.bra_vars[i] for i in free_final_qubits] self.tn.bra_vars = [var for var in self.tn.bra_vars if var not in self.tn.free_vars] - def _optimize_buckets(self): - self.peo = self.optimize_buckets() - def _reorder_buckets(self): """ Permutes indices in the tensor network and peo @@ -87,16 +84,20 @@ def _get_slice_dict(self, initial_state=0, target_state=0): return slice_dict #-- - def optimize_buckets(self): - peo, self.tn = self.optimizer.optimize(self.tn) - # print('Treewidth', self.optimizer.treewidth) - # print(peo) - return peo - - def _prepare_state(self, qc, batch_vars=0, peo=None, tn=None): - pass + def optimize_buckets(self, peo=None): + if peo is not None: + self.peo, self.tn = self.optimizer.optimize(self.tn) + if self.max_tw: + if self.optimizer.treewidth > self.max_tw: + raise ValueError(f'Treewidth {self.optimizer.treewidth} is larger than max_tw={self.max_tw}.') + + all_indices = sum([list(t.indices) for bucket in self.tn.buckets for t in bucket], []) + identity_map = {int(v): v for v in all_indices} + peo = [identity_map[int(i)] for i in self.peo] + self._reorder_buckets() - def contract_tn(self, qc, batch_vars=0, peo=None, tn=None): + + def _prepare_state(self, qc, batch_vars=0, tn=None): self.all_gates = qc if tn is None: self.tn = QtreeTensorNet.from_qtree_gates(self.all_gates, @@ -111,24 +112,11 @@ def contract_tn(self, qc, batch_vars=0, peo=None, tn=None): free_final_qubits = batch_vars self._set_free_qubits(free_final_qubits) - if peo is None: - self._optimize_buckets() - if self.max_tw: - if self.optimizer.treewidth > self.max_tw: - raise ValueError(f'Treewidth {self.optimizer.treewidth} is larger than max_tw={self.max_tw}.') - else: - self.peo = peo - - all_indices = sum([list(t.indices) for bucket in self.tn.buckets for t in bucket], []) - identity_map = {int(v): v for v in all_indices} - self.peo = [identity_map[int(i)] for i in self.peo] - self._reorder_buckets() - slice_dict = self._get_slice_dict() - log.info('batch slice {}', slice_dict) - - sliced_buckets = self.tn.slice(slice_dict) - self.buckets = sliced_buckets + def contract_tn(self, qc, batch_vars=0, peo=None, tn=None): + self._prepare_state(qc, batch_vars, tn) + self.optimize_buckets(peo) + self.slice() result = qtree.optimizer.bucket_elimination( self.buckets, self.backend.process_bucket, @@ -136,6 +124,14 @@ def contract_tn(self, qc, batch_vars=0, peo=None, tn=None): ) return result + + def slice(self): + slice_dict = self._get_slice_dict() + log.info('batch slice {}', slice_dict) + + sliced_buckets = self.tn.slice(slice_dict) + self.buckets = sliced_buckets + def simulate_batch(self, qc, batch_vars=0, peo=None): result = self.contract_tn(qc, batch_vars, peo) @@ -152,20 +148,6 @@ def sample(self, circuit): tn_adapter = QTensorTNAdapter.from_qtree_gates(circuit) return _sequence_sample(tn_adapter, composer.qubits) - # def contract_tn(self, tn, slice_dict, free_indices): - # # TODO:(@dallon) - # # tn_ = tn.slice(slice_dict) - # # c_info = tn_.optimize(free_indices) - # # return tn_.contract(c_info) - # # 1. `QtreeTensorNet.from_qtree_gates(self.all_gates)` - # # 2. Prepare list of “free” and “bra” vars (those will be fixed later) - # # 3. `peo, [self.tn](http://self.tn/) = self.optimizer.optimize([self.tn](http://self.tn/))` - # # 4. `perm_buckets, perm_dict = qtree.optimizer.reorder_buckets(self.tn.buckets, self.peo)` According to the contraction order (`peo`) - # # 5. `slice_dict = qtree.utils.slice_from_bits(initial_state, self.tn.ket_vars)` - # # 6. `sliced_buckets = self.tn.slice(slice_dict)` - # # 7. `result = qtree.optimizer.bucket_elimination(` - # pass - def _sequence_sample(tn: TNAdapter, circuit, indices, batch_size=10, batch_fix_sequence=None, dim=2): K = int(np.ceil(len(indices) / batch_size)) if batch_fix_sequence is None: From c724f66d056933065b91c35892844d98f01c8556 Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:57:24 +0000 Subject: [PATCH 10/12] Cleanup --- Dockerfile.dev | 6 ++++-- qtensor/TNAdapter.py | 2 -- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile.dev b/Dockerfile.dev index f8567217..1cace985 100644 --- a/Dockerfile.dev +++ b/Dockerfile.dev @@ -5,11 +5,13 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt update -y && \ apt install -y python3 python3-pip git htop vim +# Make sure you first recursively clone down the git repo before building WORKDIR /app RUN pip install quimb pyrofiler cartesian-explorer opt_einsum RUN pip install --no-binary pynauty pynauty -RUN cd qtree && pip install . -RUN pip install . +# Run the below commands after the container opens - because volume hasn't mounted yet +# RUN cd qtree && pip install . +# RUN pip install . RUN pip install pdbpp ENTRYPOINT ["bash"] \ No newline at end of file diff --git a/qtensor/TNAdapter.py b/qtensor/TNAdapter.py index 8d995c57..dfc7eadc 100644 --- a/qtensor/TNAdapter.py +++ b/qtensor/TNAdapter.py @@ -92,8 +92,6 @@ def test_TNAdapter(cls): # -- QTensor tensor adapter -import qtensor - class QTensorContractionInfo(ContractionInfo): def __init__(self, peo, width): self.peo = peo From 83fb6a450fc147f40f255a717573bf1528ec08b2 Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 2 Oct 2023 22:09:12 +0000 Subject: [PATCH 11/12] Debug --- qtensor/TNAdapter.py | 128 +++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/qtensor/TNAdapter.py b/qtensor/TNAdapter.py index dfc7eadc..fce6a425 100644 --- a/qtensor/TNAdapter.py +++ b/qtensor/TNAdapter.py @@ -111,74 +111,74 @@ def __init__(self, buckets, data_dict, bra_vars, ket_vars, *args, **kwargs): def _all_indices(self): return set(self._indices_to_vars.keys()) - def optimize(self, out_indices: Iterable = [], - opt:qtensor.optimisation.Optimizer=qtensor.optimisation.GreedyOptimizer()) -> QTensorContractionInfo: - logger.trace("Optimizing buckets: {}", self.qtn.buckets) - free_indices = out_indices - free_vars = [self._indices_to_vars[i] for i in free_indices] - self.qtn.free_vars = free_vars - logger.debug("Free vars: {}", free_vars) - peo, tn = opt.optimize(self.qtn) - logger.debug("Contraction path: {}", peo) - return QTensorContractionInfo(peo, opt.treewidth) + # def optimize(self, out_indices: Iterable = [], + # opt:qtensor.optimisation.Optimizer=qtensor.optimisation.GreedyOptimizer()) -> QTensorContractionInfo: + # logger.trace("Optimizing buckets: {}", self.qtn.buckets) + # free_indices = out_indices + # free_vars = [self._indices_to_vars[i] for i in free_indices] + # self.qtn.free_vars = free_vars + # logger.debug("Free vars: {}", free_vars) + # peo, tn = opt.optimize(self.qtn) + # logger.debug("Contraction path: {}", peo) + # return QTensorContractionInfo(peo, opt.treewidth) - def slice(self, slice_dict: dict): - slice_dict = {self._indices_to_vars[k]:v for k,v in slice_dict.items()} - logger.trace("Buckets before slicing: {}", self.qtn.buckets) - sliced_buckets = self.qtn.backend.get_sliced_buckets( - self.qtn.buckets, self.qtn.data_dict, slice_dict - ) - new_tn = QTensorTNAdapter() - logger.trace("slice dict {}, buckets: {}", slice_dict, sliced_buckets) - new_tn.qtn.buckets = sliced_buckets - new_tn.qtn.data_dict = self.qtn.data_dict - new_tn.qtn.bra_vars = self.qtn.bra_vars - new_tn.qtn.ket_vars = self.qtn.ket_vars - new_tn.qtn.backend = self.qtn.backend - new_tn.qtn.free_vars = self.qtn.free_vars - new_tn._indices_to_vars = self._indices_to_vars - return new_tn - - def contract(self, contraction_info: QTensorContractionInfo): - import qtree - peo = contraction_info.peo - if len(self.qtn.buckets) != len(peo): - _buckets = [[] for _ in peo] - _buckets[0] = sum(self.qtn.buckets, []) - self.qtn.buckets = _buckets - # -- fixer peo - i_to_var = {int(v): v for v in self._indices_to_vars.values()} - peo = [i_to_var[int(pv)] for pv in peo] - #-- - perm_buckets, perm_dict = qtree.optimizer.reorder_buckets( - self.qtn.buckets, peo - ) + # def slice(self, slice_dict: dict): + # slice_dict = {self._indices_to_vars[k]:v for k,v in slice_dict.items()} + # logger.trace("Buckets before slicing: {}", self.qtn.buckets) + # sliced_buckets = self.qtn.backend.get_sliced_buckets( + # self.qtn.buckets, self.qtn.data_dict, slice_dict + # ) + # new_tn = QTensorTNAdapter() + # logger.trace("slice dict {}, buckets: {}", slice_dict, sliced_buckets) + # new_tn.qtn.buckets = sliced_buckets + # new_tn.qtn.data_dict = self.qtn.data_dict + # new_tn.qtn.bra_vars = self.qtn.bra_vars + # new_tn.qtn.ket_vars = self.qtn.ket_vars + # new_tn.qtn.backend = self.qtn.backend + # new_tn.qtn.free_vars = self.qtn.free_vars + # new_tn._indices_to_vars = self._indices_to_vars + # return new_tn + + # def contract(self, contraction_info: QTensorContractionInfo): + # import qtree + # peo = contraction_info.peo + # if len(self.qtn.buckets) != len(peo): + # _buckets = [[] for _ in peo] + # _buckets[0] = sum(self.qtn.buckets, []) + # self.qtn.buckets = _buckets + # # -- fixer peo + # i_to_var = {int(v): v for v in self._indices_to_vars.values()} + # peo = [i_to_var[int(pv)] for pv in peo] + # #-- + # perm_buckets, perm_dict = qtree.optimizer.reorder_buckets( + # self.qtn.buckets, peo + # ) - logger.trace("Permuted buckets: {}", perm_buckets) - sliced_buckets = self.qtn.backend.get_sliced_buckets( - perm_buckets, self.qtn.data_dict, {} - ) - be = qtensor.contraction_algos.bucket_elimination - logger.trace("Sliced buckets: {}", sliced_buckets) + # logger.trace("Permuted buckets: {}", perm_buckets) + # sliced_buckets = self.qtn.backend.get_sliced_buckets( + # perm_buckets, self.qtn.data_dict, {} + # ) + # be = qtensor.contraction_algos.bucket_elimination + # logger.trace("Sliced buckets: {}", sliced_buckets) - result = be(sliced_buckets, self.qtn.backend, - n_var_nosum=len(self.qtn.free_vars) - ) - if isinstance(result, qtree.optimizer.Tensor): - return result.data - else: - return result + # result = be(sliced_buckets, self.qtn.backend, + # n_var_nosum=len(self.qtn.free_vars) + # ) + # if isinstance(result, qtree.optimizer.Tensor): + # return result.data + # else: + # return result - def add_tensor(self, data, indices): - import qtree - shape = data.shape - indices_v = {i: qtree.optimizer.Var(i, size=s) for i,s in zip(indices, shape)} - self._indices_to_vars.update(indices_v) - indices_v = list(indices_v.values()) - tensor = qtree.optimizer.Tensor(name='t', indices=indices_v, data_key=id(data)) - self.qtn.data_dict[id(data)] = data - self.qtn.buckets.append([tensor]) - logger.trace("Added tensor {}.", tensor) + # def add_tensor(self, data, indices): + # import qtree + # shape = data.shape + # indices_v = {i: qtree.optimizer.Var(i, size=s) for i,s in zip(indices, shape)} + # self._indices_to_vars.update(indices_v) + # indices_v = list(indices_v.values()) + # tensor = qtree.optimizer.Tensor(name='t', indices=indices_v, data_key=id(data)) + # self.qtn.data_dict[id(data)] = data + # self.qtn.buckets.append([tensor]) + # logger.trace("Added tensor {}.", tensor) @classmethod def from_qtree_gates(cls, qc, init_state=None, **kwargs): From 19ecefe8fbd41273c5e6c1f4c28da9f6ec83aa63 Mon Sep 17 00:00:00 2001 From: Dallon Asnes <30935722+dallonasnes@users.noreply.github.com> Date: Mon, 2 Oct 2023 22:22:35 +0000 Subject: [PATCH 12/12] Cleanup --- qtensor/TNAdapter.py | 68 -------------------------------------------- 1 file changed, 68 deletions(-) diff --git a/qtensor/TNAdapter.py b/qtensor/TNAdapter.py index fce6a425..a7b99666 100644 --- a/qtensor/TNAdapter.py +++ b/qtensor/TNAdapter.py @@ -111,75 +111,7 @@ def __init__(self, buckets, data_dict, bra_vars, ket_vars, *args, **kwargs): def _all_indices(self): return set(self._indices_to_vars.keys()) - # def optimize(self, out_indices: Iterable = [], - # opt:qtensor.optimisation.Optimizer=qtensor.optimisation.GreedyOptimizer()) -> QTensorContractionInfo: - # logger.trace("Optimizing buckets: {}", self.qtn.buckets) - # free_indices = out_indices - # free_vars = [self._indices_to_vars[i] for i in free_indices] - # self.qtn.free_vars = free_vars - # logger.debug("Free vars: {}", free_vars) - # peo, tn = opt.optimize(self.qtn) - # logger.debug("Contraction path: {}", peo) - # return QTensorContractionInfo(peo, opt.treewidth) - # def slice(self, slice_dict: dict): - # slice_dict = {self._indices_to_vars[k]:v for k,v in slice_dict.items()} - # logger.trace("Buckets before slicing: {}", self.qtn.buckets) - # sliced_buckets = self.qtn.backend.get_sliced_buckets( - # self.qtn.buckets, self.qtn.data_dict, slice_dict - # ) - # new_tn = QTensorTNAdapter() - # logger.trace("slice dict {}, buckets: {}", slice_dict, sliced_buckets) - # new_tn.qtn.buckets = sliced_buckets - # new_tn.qtn.data_dict = self.qtn.data_dict - # new_tn.qtn.bra_vars = self.qtn.bra_vars - # new_tn.qtn.ket_vars = self.qtn.ket_vars - # new_tn.qtn.backend = self.qtn.backend - # new_tn.qtn.free_vars = self.qtn.free_vars - # new_tn._indices_to_vars = self._indices_to_vars - # return new_tn - - # def contract(self, contraction_info: QTensorContractionInfo): - # import qtree - # peo = contraction_info.peo - # if len(self.qtn.buckets) != len(peo): - # _buckets = [[] for _ in peo] - # _buckets[0] = sum(self.qtn.buckets, []) - # self.qtn.buckets = _buckets - # # -- fixer peo - # i_to_var = {int(v): v for v in self._indices_to_vars.values()} - # peo = [i_to_var[int(pv)] for pv in peo] - # #-- - # perm_buckets, perm_dict = qtree.optimizer.reorder_buckets( - # self.qtn.buckets, peo - # ) - - # logger.trace("Permuted buckets: {}", perm_buckets) - # sliced_buckets = self.qtn.backend.get_sliced_buckets( - # perm_buckets, self.qtn.data_dict, {} - # ) - # be = qtensor.contraction_algos.bucket_elimination - # logger.trace("Sliced buckets: {}", sliced_buckets) - - # result = be(sliced_buckets, self.qtn.backend, - # n_var_nosum=len(self.qtn.free_vars) - # ) - # if isinstance(result, qtree.optimizer.Tensor): - # return result.data - # else: - # return result - - # def add_tensor(self, data, indices): - # import qtree - # shape = data.shape - # indices_v = {i: qtree.optimizer.Var(i, size=s) for i,s in zip(indices, shape)} - # self._indices_to_vars.update(indices_v) - # indices_v = list(indices_v.values()) - # tensor = qtree.optimizer.Tensor(name='t', indices=indices_v, data_key=id(data)) - # self.qtn.data_dict[id(data)] = data - # self.qtn.buckets.append([tensor]) - # logger.trace("Added tensor {}.", tensor) - @classmethod def from_qtree_gates(cls, qc, init_state=None, **kwargs): all_gates = qc